a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross/*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * CDDL HEADER START
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross *
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * The contents of this file are subject to the terms of the
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Common Development and Distribution License (the "License").
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * You may not use this file except in compliance with the License.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross *
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * or http://www.opensolaris.org/os/licensing.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * See the License for the specific language governing permissions
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * and limitations under the License.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross *
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * When distributing Covered Code, include this CDDL HEADER in each
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * If applicable, add the following below this CDDL HEADER, with the
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * fields enclosed by brackets "[]" replaced with your own identifying
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * information: Portions Copyright [yyyy] [name of copyright owner]
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross *
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * CDDL HEADER END
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross/*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Use is subject to license terms.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross *
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross/*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Dispatch function for SMB2_QUERY_DIRECTORY
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross *
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Similar to smb_trans2_find.c (from SMB1)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross#include <smbsrv/smb2_kproto.h>
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross/*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Args (and other state) that we carry around among the
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * various functions involved in SMB2 Query Directory.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rosstypedef struct smb2_find_args {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint32_t fa_maxdata;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint8_t fa_infoclass;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint8_t fa_fflags;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint16_t fa_maxcount;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint16_t fa_eos; /* End Of Search */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint16_t fa_fixedsize; /* size of fixed part of a returned entry */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint32_t fa_lastkey; /* Last resume key */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross int fa_last_entry; /* offset of last entry */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross} smb2_find_args_t;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rossstatic uint32_t smb2_find_entries(smb_request_t *,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb_odir_t *, smb2_find_args_t *);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rossstatic uint32_t smb2_find_mbc_encode(smb_request_t *,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb_fileinfo_t *, smb2_find_args_t *);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross/*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Tunable parameter to limit the maximum
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * number of entries to be returned.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rossuint16_t smb2_find_max = 128;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rosssmb_sdrc_t
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rosssmb2_query_dir(smb_request_t *sr)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross{
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb2_find_args_t args;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb_odir_resume_t odir_resume;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb_ofile_t *of = NULL;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb_odir_t *od = NULL;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross char *pattern = NULL;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint16_t StructSize;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint32_t FileIndex;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint16_t NameOffset;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint16_t NameLength;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb2fid_t smb2fid;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint16_t sattr = SMB_SEARCH_ATTRIBUTES;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint16_t DataOff;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint32_t DataLen;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint32_t status;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross int skip, rc = 0;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross bzero(&args, sizeof (args));
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross bzero(&odir_resume, sizeof (odir_resume));
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * SMB2 Query Directory request
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross rc = smb_mbc_decodef(
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &sr->smb_data, "wbblqqwwl",
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &StructSize, /* w */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &args.fa_infoclass, /* b */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &args.fa_fflags, /* b */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &FileIndex, /* l */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &smb2fid.persistent, /* q */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &smb2fid.temporal, /* q */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &NameOffset, /* w */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &NameLength, /* w */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &args.fa_maxdata); /* l */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (rc || StructSize != 33)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (SDRC_ERROR);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross status = smb2sr_lookup_fid(sr, &smb2fid);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (status)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross goto errout;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross of = sr->fid_ofile;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * If there's an input buffer (search pattern), decode it.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Two times MAXNAMELEN because it represents the UNICODE string
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * length in bytes.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (NameLength >= (2 * MAXNAMELEN)) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross status = NT_STATUS_OBJECT_PATH_INVALID;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross goto errout;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross }
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (NameLength != 0) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * We're normally positioned at the pattern now,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * but there could be some padding before it.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross skip = (sr->smb2_cmd_hdr + NameOffset) -
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross sr->smb_data.chain_offset;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (skip < 0) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross status = NT_STATUS_OBJECT_PATH_INVALID;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross goto errout;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross }
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (skip > 0)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross (void) smb_mbc_decodef(&sr->smb_data, "#.", skip);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross rc = smb_mbc_decodef(&sr->smb_data, "%#U", sr,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross NameLength, &pattern);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (rc || pattern == NULL) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross status = NT_STATUS_OBJECT_PATH_INVALID;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross goto errout;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross }
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross } else
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross pattern = "*";
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Setup the output buffer.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (args.fa_maxdata > smb2_max_trans)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross args.fa_maxdata = smb2_max_trans;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross sr->raw_data.max_bytes = args.fa_maxdata;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Get the mininum size of entries we will return, which
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * lets us estimate the number of entries we'll need.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * This should be the size with a one character name.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Compare w/ smb2_find_get_maxdata().
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross *
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Also use this opportunity to validate fa_infoclass.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross switch (args.fa_infoclass) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross case FileDirectoryInformation: /* 1 */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross args.fa_fixedsize = 64;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross break;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross case FileFullDirectoryInformation: /* 2 */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross args.fa_fixedsize = 68;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross break;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross case FileBothDirectoryInformation: /* 3 */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross args.fa_fixedsize = 94;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross break;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross case FileNamesInformation: /* 12 */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross args.fa_fixedsize = 12;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross break;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross case FileIdBothDirectoryInformation: /* 37 */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross args.fa_fixedsize = 96;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross break;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross case FileIdFullDirectoryInformation: /* 38 */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross args.fa_fixedsize = 84;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross break;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross default:
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross status = NT_STATUS_INVALID_INFO_CLASS;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross goto errout;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross }
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross args.fa_maxcount = args.fa_maxdata / (args.fa_fixedsize + 4);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (args.fa_maxcount == 0)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross args.fa_maxcount = 1;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if ((smb2_find_max != 0) && (args.fa_maxcount > smb2_find_max))
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross args.fa_maxcount = smb2_find_max;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (args.fa_fflags & SMB2_QDIR_FLAG_SINGLE)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross args.fa_maxcount = 1;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * If this ofile does not have an odir yet, get one.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross mutex_enter(&of->f_mutex);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if ((od = of->f_odir) == NULL) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross status = smb_odir_openfh(sr, pattern, sattr, &od);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross of->f_odir = od;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross }
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross mutex_exit(&of->f_mutex);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (od == NULL) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (status == 0)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross status = NT_STATUS_INTERNAL_ERROR;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross goto errout;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross }
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * "Reopen" sets a new pattern and restart.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (args.fa_fflags & SMB2_QDIR_FLAG_REOPEN) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb_odir_reopen(od, pattern, sattr);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross }
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Set the correct position in the directory.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (args.fa_fflags & SMB2_QDIR_FLAG_RESTART) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross odir_resume.or_type = SMB_ODIR_RESUME_COOKIE;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross odir_resume.or_cookie = 0;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross } else if (args.fa_fflags & SMB2_QDIR_FLAG_INDEX) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross odir_resume.or_type = SMB_ODIR_RESUME_COOKIE;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross odir_resume.or_cookie = FileIndex;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross } else {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross odir_resume.or_type = SMB_ODIR_RESUME_CONT;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross }
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb_odir_resume_at(od, &odir_resume);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross of->f_seek_pos = od->d_offset;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * The real work of readdir and format conversion.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross status = smb2_find_entries(sr, od, &args);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross of->f_seek_pos = od->d_offset;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (status == NT_STATUS_NO_MORE_FILES) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (args.fa_fflags & SMB2_QDIR_FLAG_SINGLE) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross status = NT_STATUS_NO_SUCH_FILE;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross goto errout;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross }
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * This is not an error, but a warning that can be
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * used to tell the client that this data return
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * is the last of the enumeration. Returning this
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * warning now (with the data) saves the client a
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * round trip that would otherwise be needed to
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * find out it's at the end.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross sr->smb2_status = status;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross status = 0;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross }
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (status)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross goto errout;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * SMB2 Query Directory reply
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross StructSize = 9;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross DataOff = SMB2_HDR_SIZE + 8;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross DataLen = MBC_LENGTH(&sr->raw_data);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross rc = smb_mbc_encodef(
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &sr->reply, "wwlC",
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross StructSize, /* w */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross DataOff, /* w */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross DataLen, /* l */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &sr->raw_data); /* C */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (DataLen == 0)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross (void) smb_mbc_encodef(&sr->reply, ".");
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (rc == 0)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (SDRC_SUCCESS);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross status = NT_STATUS_UNSUCCESSFUL;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rosserrout:
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb2sr_put_error(sr, status);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (SDRC_SUCCESS);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross}
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross/*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * smb2_find_entries
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross *
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Find and encode up to args->fa_maxcount directory entries.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross *
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Returns:
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * NT status
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rossstatic uint32_t
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rosssmb2_find_entries(smb_request_t *sr, smb_odir_t *od, smb2_find_args_t *args)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross{
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb_fileinfo_t fileinfo;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb_odir_resume_t odir_resume;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint16_t count;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint16_t minsize;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint32_t status = 0;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross int rc = -1;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Let's stop when the remaining space will not hold a
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * minimum size entry. That's the fixed part plus the
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * storage size of a 1 char unicode string.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross minsize = args->fa_fixedsize + 2;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross count = 0;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross while (count < args->fa_maxcount) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (!MBC_ROOM_FOR(&sr->raw_data, minsize)) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross status = NT_STATUS_BUFFER_OVERFLOW;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross break;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross }
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross rc = smb_odir_read_fileinfo(sr, od, &fileinfo, &args->fa_eos);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (rc == ENOENT) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross status = NT_STATUS_NO_MORE_FILES;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross break;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross }
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (rc != 0) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross status = smb_errno2status(rc);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross break;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross }
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (args->fa_eos != 0) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /* The readdir call hit the end. */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross status = NT_STATUS_NO_MORE_FILES;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross break;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross }
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross status = smb2_find_mbc_encode(sr, &fileinfo, args);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (status) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * We read a directory entry but failed to
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * copy it into the output buffer. Rewind
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * the directory pointer so this will be
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * the first entry read next time.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross bzero(&odir_resume, sizeof (odir_resume));
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross odir_resume.or_type = SMB_ODIR_RESUME_COOKIE;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross odir_resume.or_cookie = args->fa_lastkey;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb_odir_resume_at(od, &odir_resume);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross break;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross }
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Save the offset of the next entry we'll read.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * If we fail copying, we'll need this offset.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross args->fa_lastkey = fileinfo.fi_cookie;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross ++count;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross }
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (count == 0) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross ASSERT(status != 0);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross } else {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * We copied some directory entries, but stopped for
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * NT_STATUS_NO_MORE_FILES, or something.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross *
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Per [MS-FSCC] sec. 2.4, the last entry in the
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * enumeration MUST have its NextEntryOffset value
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * set to zero. Overwrite that in the last entry.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross (void) smb_mbc_poke(&sr->raw_data,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross args->fa_last_entry, "l", 0);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross status = 0;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross }
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (status);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross}
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross/*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * smb2_mbc_encode
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross *
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * This function encodes the mbc for one directory entry.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross *
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * The function returns -1 when the max data requested by client
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * is reached. If the entry is valid and successful encoded, 0
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * will be returned; otherwise, 1 will be returned.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross *
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * We always null terminate the filename. The space for the null
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * is included in the maxdata calculation and is therefore included
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * in the next_entry_offset. namelen is the unterminated length of
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * the filename. For levels except STANDARD and EA_SIZE, if the
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * filename is ascii the name length returned to the client should
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * include the null terminator. Otherwise the length returned to
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * the client should not include the terminator.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross *
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Returns: 0 - data successfully encoded
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * NT status
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rossstatic uint32_t
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rosssmb2_find_mbc_encode(smb_request_t *sr, smb_fileinfo_t *fileinfo,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb2_find_args_t *args)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross{
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint8_t buf83[26];
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb_msgbuf_t mb;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross int namelen, padsz;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross int shortlen = 0;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross int rc, starting_offset;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint32_t next_entry_offset;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint32_t mb_flags = SMB_MSGBUF_UNICODE;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint32_t resume_key;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross namelen = smb_wcequiv_strlen(fileinfo->fi_name);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (namelen == -1)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (NT_STATUS_INTERNAL_ERROR);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Keep track of where the last entry starts so we can
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * come back and poke the NextEntryOffset field. Also,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * after enumeration finishes, the caller uses this to
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * poke the last entry again with zero to mark it as
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * the end of the enumeration.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross starting_offset = sr->raw_data.chain_offset;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Technically (per MS-SMB2) resume keys are optional.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Windows doesn't need them, but MacOS does.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross resume_key = fileinfo->fi_cookie;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * This switch handles all the "information levels" (formats)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * that we support. Note that all formats have the file name
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * placed after some fixed-size data, and the code to write
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * the file name is factored out at the end of this switch.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross switch (args->fa_infoclass) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /* See also: SMB_FIND_FILE_DIRECTORY_INFO */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross case FileDirectoryInformation: /* 1 */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross rc = smb_mbc_encodef(
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &sr->raw_data, "llTTTTqqll",
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross 0, /* NextEntryOffset (set later) */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross resume_key,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &fileinfo->fi_crtime,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &fileinfo->fi_atime,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &fileinfo->fi_mtime,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &fileinfo->fi_ctime,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross fileinfo->fi_size,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross fileinfo->fi_alloc_size,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross fileinfo->fi_dosattr,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross namelen);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross break;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /* See also: SMB_FIND_FILE_FULL_DIRECTORY_INFO */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross case FileFullDirectoryInformation: /* 2 */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross rc = smb_mbc_encodef(
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &sr->raw_data, "llTTTTqqlll",
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross 0, /* NextEntryOffset (set later) */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross resume_key,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &fileinfo->fi_crtime,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &fileinfo->fi_atime,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &fileinfo->fi_mtime,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &fileinfo->fi_ctime,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross fileinfo->fi_size,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross fileinfo->fi_alloc_size,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross fileinfo->fi_dosattr,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross namelen,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross 0L); /* EaSize */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross break;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /* See also: SMB_FIND_FILE_ID_FULL_DIRECTORY_INFO */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross case FileIdFullDirectoryInformation: /* 38 */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross rc = smb_mbc_encodef(
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &sr->raw_data, "llTTTTqqllllq",
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross 0, /* NextEntryOffset (set later) */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross resume_key,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &fileinfo->fi_crtime,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &fileinfo->fi_atime,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &fileinfo->fi_mtime,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &fileinfo->fi_ctime,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross fileinfo->fi_size,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross fileinfo->fi_alloc_size,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross fileinfo->fi_dosattr,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross namelen,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross 0L, /* EaSize */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross 0L, /* reserved */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross fileinfo->fi_nodeid);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross break;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /* See also: SMB_FIND_FILE_BOTH_DIRECTORY_INFO */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross case FileBothDirectoryInformation: /* 3 */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross bzero(buf83, sizeof (buf83));
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb_msgbuf_init(&mb, buf83, sizeof (buf83), mb_flags);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (!smb_msgbuf_encode(&mb, "U", fileinfo->fi_shortname))
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross shortlen = smb_wcequiv_strlen(fileinfo->fi_shortname);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross rc = smb_mbc_encodef(
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &sr->raw_data, "llTTTTqqlllb.24c",
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross 0, /* NextEntryOffset (set later) */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross resume_key,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &fileinfo->fi_crtime,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &fileinfo->fi_atime,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &fileinfo->fi_mtime,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &fileinfo->fi_ctime,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross fileinfo->fi_size,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross fileinfo->fi_alloc_size,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross fileinfo->fi_dosattr,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross namelen,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross 0L, /* EaSize */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross shortlen,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross buf83);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb_msgbuf_term(&mb);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross break;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /* See also: SMB_FIND_FILE_ID_BOTH_DIRECTORY_INFO */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross case FileIdBothDirectoryInformation: /* 37 */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross bzero(buf83, sizeof (buf83));
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb_msgbuf_init(&mb, buf83, sizeof (buf83), mb_flags);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (!smb_msgbuf_encode(&mb, "U", fileinfo->fi_shortname))
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross shortlen = smb_wcequiv_strlen(fileinfo->fi_shortname);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross rc = smb_mbc_encodef(
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &sr->raw_data, "llTTTTqqlllb.24c..q",
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross 0, /* NextEntryOffset (set later) */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross resume_key,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &fileinfo->fi_crtime,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &fileinfo->fi_atime,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &fileinfo->fi_mtime,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &fileinfo->fi_ctime,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross fileinfo->fi_size, /* q */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross fileinfo->fi_alloc_size, /* q */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross fileinfo->fi_dosattr, /* l */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross namelen, /* l */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross 0L, /* EaSize l */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross shortlen, /* b. */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross buf83, /* 24c */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /* reserved .. */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross fileinfo->fi_nodeid); /* q */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb_msgbuf_term(&mb);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross break;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /* See also: SMB_FIND_FILE_NAMES_INFO */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross case FileNamesInformation: /* 12 */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross rc = smb_mbc_encodef(
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &sr->raw_data, "lll",
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross 0, /* NextEntryOffset (set later) */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross resume_key,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross namelen);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross break;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross default:
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (NT_STATUS_INVALID_INFO_CLASS);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross }
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (rc) /* smb_mbc_encodef failed */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (NT_STATUS_BUFFER_OVERFLOW);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * At this point we have written all the fixed-size data
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * for the specified info. class. Now put the name and
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * alignment padding, and then patch the NextEntryOffset.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Also store this offset for the caller so they can
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * patch this (again) to zero on the very last entry.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross rc = smb_mbc_encodef(
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &sr->raw_data, "U",
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross fileinfo->fi_name);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (rc)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (NT_STATUS_BUFFER_OVERFLOW);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /* Next entry needs to be 8-byte aligned. */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross padsz = sr->raw_data.chain_offset & 7;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (padsz) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross padsz = 8 - padsz;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross (void) smb_mbc_encodef(&sr->raw_data, "#.", padsz);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross }
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross next_entry_offset = sr->raw_data.chain_offset - starting_offset;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross (void) smb_mbc_poke(&sr->raw_data, starting_offset, "l",
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross next_entry_offset);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross args->fa_last_entry = starting_offset;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (0);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross}