Home | History | Annotate | Download | only in smbfs
      1 /*
      2  * Copyright (c) 2000-2001 Boris Popov
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  * 3. All advertising materials mentioning features or use of this software
     14  *    must display the following acknowledgement:
     15  *    This product includes software developed by Boris Popov.
     16  * 4. Neither the name of the author nor the names of any co-contributors
     17  *    may be used to endorse or promote products derived from this software
     18  *    without specific prior written permission.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     30  * SUCH DAMAGE.
     31  *
     32  * $Id: smbfs_smb.c,v 1.73.38.1 2005/05/27 02:35:28 lindak Exp $
     33  */
     34 
     35 /*
     36  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     37  * Use is subject to license terms.
     38  */
     39 
     40 #include <sys/param.h>
     41 #include <sys/systm.h>
     42 #include <sys/time.h>
     43 #include <sys/vnode.h>
     44 #include <sys/sunddi.h>
     45 #include <sys/cmn_err.h>
     46 
     47 #include <netsmb/smb_osdep.h>
     48 
     49 #include <netsmb/smb.h>
     50 #include <netsmb/smb_conn.h>
     51 #include <netsmb/smb_subr.h>
     52 #include <netsmb/smb_rq.h>
     53 
     54 #include <smbfs/smbfs.h>
     55 #include <smbfs/smbfs_node.h>
     56 #include <smbfs/smbfs_subr.h>
     57 
     58 /*
     59  * Jan 1 1980 as 64 bit NT time.
     60  * (tenths of microseconds since 1601)
     61  */
     62 const uint64_t NT1980 = 11960035200ULL*10000000ULL;
     63 
     64 /*
     65  * Local functions.
     66  * Not static, to aid debugging.
     67  */
     68 
     69 int smbfs_smb_query_info(struct smbnode *np, const char *name, int nmlen,
     70 	struct smbfattr *fap, struct smb_cred *scrp);
     71 int smbfs_smb_trans2_query(struct smbnode *np, struct smbfattr *fap,
     72 	struct smb_cred *scrp, uint16_t infolevel);
     73 
     74 int smbfs_smb_statfsLM1(struct smb_share *ssp,
     75 	statvfs64_t *sbp, struct smb_cred *scrp);
     76 int smbfs_smb_statfsLM2(struct smb_share *ssp,
     77 	statvfs64_t *sbp, struct smb_cred *scrp);
     78 
     79 int  smbfs_smb_setfattrNT(struct smbnode *np, int fid,
     80 	uint32_t attr, struct timespec *mtime,	struct timespec *atime,
     81 	struct smb_cred *scrp);
     82 
     83 int  smbfs_smb_setftime1(struct smbnode *np, uint16_t fid,
     84 	struct timespec *mtime,	struct timespec *atime,
     85 	struct smb_cred *scrp);
     86 
     87 int  smbfs_smb_setpattr1(struct smbnode *np,
     88 	const char *name, int len, uint32_t attr,
     89 	struct timespec *mtime, struct smb_cred *scrp);
     90 
     91 
     92 /*
     93  * Todo: locking over-the-wire
     94  */
     95 #ifdef APPLE
     96 
     97 static int
     98 smbfs_smb_lockandx(struct smbnode *np, int op, uint32_t pid,
     99 	offset_t start, uint64_t len, int largelock,
    100 	struct smb_cred *scrp, uint32_t timeout)
    101 {
    102 	struct smb_share *ssp = np->n_mount->smi_share;
    103 	struct smb_rq rq, *rqp = &rq;
    104 	struct mbchain *mbp;
    105 	uint8_t ltype = 0;
    106 	int error;
    107 
    108 	/* Shared lock for n_fid use below. */
    109 	ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_READER));
    110 
    111 	/* After reconnect, n_fid is invalid */
    112 	if (np->n_vcgenid != ssp->ss_vcgenid)
    113 		return (ESTALE);
    114 
    115 	if (op == SMB_LOCK_SHARED)
    116 		ltype |= SMB_LOCKING_ANDX_SHARED_LOCK;
    117 	/* XXX: if (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES)? */
    118 	if (largelock)
    119 		ltype |= SMB_LOCKING_ANDX_LARGE_FILES;
    120 	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_LOCKING_ANDX, scrp);
    121 	if (error)
    122 		return (error);
    123 	smb_rq_getrequest(rqp, &mbp);
    124 	smb_rq_wstart(rqp);
    125 	mb_put_uint8(mbp, 0xff);	/* secondary command */
    126 	mb_put_uint8(mbp, 0);		/* MBZ */
    127 	mb_put_uint16le(mbp, 0);
    128 	mb_put_uint16le(mbp, np->n_fid);
    129 	mb_put_uint8(mbp, ltype);	/* locktype */
    130 	mb_put_uint8(mbp, 0);		/* oplocklevel - 0 seems is NO_OPLOCK */
    131 	mb_put_uint32le(mbp, timeout);	/* 0 nowait, -1 infinite wait */
    132 	mb_put_uint16le(mbp, op == SMB_LOCK_RELEASE ? 1 : 0);
    133 	mb_put_uint16le(mbp, op == SMB_LOCK_RELEASE ? 0 : 1);
    134 	smb_rq_wend(rqp);
    135 	smb_rq_bstart(rqp);
    136 	mb_put_uint16le(mbp, pid);
    137 	if (!largelock) {
    138 		mb_put_uint32le(mbp, start);
    139 		mb_put_uint32le(mbp, len);
    140 	} else {
    141 		mb_put_uint16le(mbp, 0); /* pad */
    142 		mb_put_uint32le(mbp, start >> 32); /* OffsetHigh */
    143 		mb_put_uint32le(mbp, start & 0xffffffff); /* OffsetLow */
    144 		mb_put_uint32le(mbp, len >> 32); /* LengthHigh */
    145 		mb_put_uint32le(mbp, len & 0xffffffff); /* LengthLow */
    146 	}
    147 	smb_rq_bend(rqp);
    148 	/*
    149 	 * Don't want to risk missing a successful
    150 	 * unlock send or lock response, or we could
    151 	 * lose track of an outstanding lock.
    152 	 */
    153 	if (op == SMB_LOCK_RELEASE)
    154 		rqp->sr_flags |= SMBR_NOINTR_SEND;
    155 	else
    156 		rqp->sr_flags |= SMBR_NOINTR_RECV;
    157 
    158 	error = smb_rq_simple(rqp);
    159 	smb_rq_done(rqp);
    160 	return (error);
    161 }
    162 
    163 int
    164 smbfs_smb_lock(struct smbnode *np, int op, caddr_t id,
    165 	offset_t start, uint64_t len,	int largelock,
    166 	struct smb_cred *scrp, uint32_t timeout)
    167 {
    168 	struct smb_share *ssp = np->n_mount->smi_share;
    169 
    170 	if (SMB_DIALECT(SSTOVC(ssp)) < SMB_DIALECT_LANMAN1_0)
    171 		/*
    172 		 * TODO: use LOCK_BYTE_RANGE here.
    173 		 */
    174 		return (EINVAL);
    175 
    176 	/*
    177 	 * XXX: compute largelock via:
    178 	 * (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES)?
    179 	 */
    180 	return (smbfs_smb_lockandx(np, op, (uint32_t)id, start, len,
    181 	    largelock, scrp, timeout));
    182 }
    183 
    184 #endif /* APPLE */
    185 
    186 /*
    187  * Helper for smbfs_getattr
    188  * Something like nfs_getattr_otw
    189  */
    190 int
    191 smbfs_smb_getfattr(
    192 	struct smbnode *np,
    193 	struct smbfattr *fap,
    194 	struct smb_cred *scrp)
    195 {
    196 	int error;
    197 
    198 	/*
    199 	 * This lock is necessary for FID-based calls.
    200 	 * Lock may be writer (via open) or reader.
    201 	 */
    202 	ASSERT(np->r_lkserlock.count != 0);
    203 
    204 	/*
    205 	 * Extended attribute directory or file.
    206 	 */
    207 	if (np->n_flag & N_XATTR) {
    208 		error = smbfs_xa_getfattr(np, fap, scrp);
    209 		return (error);
    210 	}
    211 
    212 	error = smbfs_smb_trans2_query(np, fap, scrp, 0);
    213 	if (error != EINVAL)
    214 		return (error);
    215 
    216 	/* fallback */
    217 	error = smbfs_smb_query_info(np, NULL, 0, fap, scrp);
    218 
    219 	return (error);
    220 }
    221 
    222 /*
    223  * Common function for QueryFileInfo, QueryPathInfo.
    224  */
    225 int
    226 smbfs_smb_trans2_query(struct smbnode *np, struct smbfattr *fap,
    227 	struct smb_cred *scrp, uint16_t infolevel)
    228 {
    229 	struct smb_share *ssp = np->n_mount->smi_share;
    230 	struct smb_vc *vcp = SSTOVC(ssp);
    231 	struct smb_t2rq *t2p;
    232 	int error, svtz, timesok = 1;
    233 	struct mbchain *mbp;
    234 	struct mdchain *mdp;
    235 	uint16_t cmd, date, time, wattr;
    236 	uint64_t llongint, lsize;
    237 	uint32_t size, dattr;
    238 
    239 	/*
    240 	 * Shared lock for n_fid use below.
    241 	 * See smbfs_smb_getfattr()
    242 	 */
    243 	ASSERT(np->r_lkserlock.count != 0);
    244 
    245 	/*
    246 	 * If we have a valid open FID, use it.
    247 	 */
    248 	if ((np->n_fidrefs > 0) &&
    249 	    (np->n_fid != SMB_FID_UNUSED) &&
    250 	    (np->n_vcgenid == ssp->ss_vcgenid))
    251 		cmd = SMB_TRANS2_QUERY_FILE_INFORMATION;
    252 	else
    253 		cmd = SMB_TRANS2_QUERY_PATH_INFORMATION;
    254 
    255 top:
    256 	error = smb_t2_alloc(SSTOCP(ssp), cmd, scrp, &t2p);
    257 	if (error)
    258 		return (error);
    259 	mbp = &t2p->t2_tparam;
    260 	mb_init(mbp);
    261 	if (!infolevel) {
    262 		if (SMB_DIALECT(vcp) < SMB_DIALECT_NTLM0_12)
    263 			infolevel = SMB_QFILEINFO_STANDARD;
    264 		else
    265 			infolevel = SMB_QFILEINFO_ALL_INFO;
    266 	}
    267 
    268 	if (cmd == SMB_TRANS2_QUERY_FILE_INFORMATION)
    269 		mb_put_uint16le(mbp, np->n_fid);
    270 
    271 	mb_put_uint16le(mbp, infolevel);
    272 
    273 	if (cmd == SMB_TRANS2_QUERY_PATH_INFORMATION) {
    274 		mb_put_uint32le(mbp, 0);
    275 		/* mb_put_uint8(mbp, SMB_DT_ASCII); specs are wrong */
    276 		error = smbfs_fullpath(mbp, vcp, np, NULL, NULL, '\\');
    277 		if (error) {
    278 			smb_t2_done(t2p);
    279 			return (error);
    280 		}
    281 	}
    282 
    283 	t2p->t2_maxpcount = 2;
    284 	t2p->t2_maxdcount = vcp->vc_txmax;
    285 	error = smb_t2_request(t2p);
    286 	if (error) {
    287 		smb_t2_done(t2p);
    288 		/* Invalid info level?  Try fallback. */
    289 		if (error == EINVAL &&
    290 		    infolevel == SMB_QFILEINFO_ALL_INFO) {
    291 			infolevel = SMB_QFILEINFO_STANDARD;
    292 			goto top;
    293 		}
    294 		return (error);
    295 	}
    296 	mdp = &t2p->t2_rdata;
    297 	svtz = vcp->vc_sopt.sv_tz;
    298 	switch (infolevel) {
    299 	case SMB_QFILEINFO_STANDARD:
    300 		md_get_uint16le(mdp, &date);
    301 		md_get_uint16le(mdp, &time);	/* creation time */
    302 		smb_dos2unixtime(date, time, 0, svtz, &fap->fa_createtime);
    303 		md_get_uint16le(mdp, &date);
    304 		md_get_uint16le(mdp, &time);	/* access time */
    305 		smb_dos2unixtime(date, time, 0, svtz, &fap->fa_atime);
    306 		md_get_uint16le(mdp, &date);
    307 		md_get_uint16le(mdp, &time);	/* modify time */
    308 		smb_dos2unixtime(date, time, 0, svtz, &fap->fa_mtime);
    309 		md_get_uint32le(mdp, &size);	/* EOF position */
    310 		fap->fa_size = size;
    311 		md_get_uint32le(mdp, &size);	/* allocation size */
    312 		fap->fa_allocsz = size;
    313 		error = md_get_uint16le(mdp, &wattr);
    314 		fap->fa_attr = wattr;
    315 		timesok = 1;
    316 		break;
    317 	case SMB_QFILEINFO_ALL_INFO:
    318 		timesok = 0;
    319 		/* creation time */
    320 		md_get_uint64le(mdp, &llongint);
    321 		if (llongint)
    322 			timesok++;
    323 		smb_time_NT2local(llongint, &fap->fa_createtime);
    324 
    325 		/* last access time */
    326 		md_get_uint64le(mdp, &llongint);
    327 		if (llongint)
    328 			timesok++;
    329 		smb_time_NT2local(llongint, &fap->fa_atime);
    330 
    331 		/* last write time */
    332 		md_get_uint64le(mdp, &llongint);
    333 		if (llongint)
    334 			timesok++;
    335 		smb_time_NT2local(llongint, &fap->fa_mtime);
    336 
    337 		/* last change time */
    338 		md_get_uint64le(mdp, &llongint);
    339 		if (llongint)
    340 			timesok++;
    341 		smb_time_NT2local(llongint, &fap->fa_ctime);
    342 
    343 		/* attributes */
    344 		md_get_uint32le(mdp, &dattr);
    345 		fap->fa_attr = dattr;
    346 
    347 		/*
    348 		 * 4-Byte alignment - discard
    349 		 * Specs don't talk about this.
    350 		 */
    351 		md_get_uint32le(mdp, NULL);
    352 		/* allocation size */
    353 		md_get_uint64le(mdp, &lsize);
    354 		fap->fa_allocsz = lsize;
    355 		/* File size */
    356 		error = md_get_uint64le(mdp, &lsize);
    357 		fap->fa_size = lsize;
    358 		break;
    359 	default:
    360 		SMBVDEBUG("unexpected info level %d\n", infolevel);
    361 		error = EINVAL;
    362 	}
    363 	smb_t2_done(t2p);
    364 	/*
    365 	 * if all times are zero (observed with FAT on NT4SP6)
    366 	 * then fall back to older info level
    367 	 */
    368 	if (!timesok) {
    369 		if (infolevel == SMB_QFILEINFO_ALL_INFO) {
    370 			infolevel = SMB_QFILEINFO_STANDARD;
    371 			goto top;
    372 		}
    373 		error = EINVAL;
    374 	}
    375 	return (error);
    376 }
    377 
    378 /*
    379  * Support functions for _qstreaminfo
    380  * Moved to smbfs_xattr.c
    381  */
    382 
    383 int
    384 smbfs_smb_qfsattr(struct smb_share *ssp, struct smb_fs_attr_info *fsa,
    385 	struct smb_cred *scrp)
    386 {
    387 	struct smb_t2rq *t2p;
    388 	struct mbchain *mbp;
    389 	struct mdchain *mdp;
    390 	int error;
    391 	uint32_t nlen;
    392 
    393 	error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_QUERY_FS_INFORMATION,
    394 	    scrp, &t2p);
    395 	if (error)
    396 		return (error);
    397 	mbp = &t2p->t2_tparam;
    398 	mb_init(mbp);
    399 	mb_put_uint16le(mbp, SMB_QFS_ATTRIBUTE_INFO);
    400 	t2p->t2_maxpcount = 4;
    401 	t2p->t2_maxdcount = 4 * 3 + 512;
    402 	error = smb_t2_request(t2p);
    403 	if (error)
    404 		goto out;
    405 
    406 	mdp = &t2p->t2_rdata;
    407 	md_get_uint32le(mdp, &fsa->fsa_aflags);
    408 	md_get_uint32le(mdp, &fsa->fsa_maxname);
    409 	error = md_get_uint32le(mdp, &nlen);	/* fs name length */
    410 	if (error)
    411 		goto out;
    412 
    413 	/*
    414 	 * Get the FS type name.
    415 	 */
    416 	bzero(fsa->fsa_tname, FSTYPSZ);
    417 	if (SMB_UNICODE_STRINGS(SSTOVC(ssp))) {
    418 		uint16_t tmpbuf[FSTYPSZ];
    419 		size_t tmplen, outlen;
    420 
    421 		if (nlen > sizeof (tmpbuf))
    422 			nlen = sizeof (tmpbuf);
    423 		error = md_get_mem(mdp, tmpbuf, nlen, MB_MSYSTEM);
    424 		tmplen = nlen / 2;	/* UCS-2 chars */
    425 		outlen = FSTYPSZ - 1;
    426 		(void) uconv_u16tou8(tmpbuf, &tmplen,
    427 		    (uchar_t *)fsa->fsa_tname, &outlen,
    428 		    UCONV_IN_LITTLE_ENDIAN);
    429 	} else {
    430 		if (nlen > (FSTYPSZ - 1))
    431 			nlen = FSTYPSZ - 1;
    432 		error = md_get_mem(mdp, fsa->fsa_tname, nlen, MB_MSYSTEM);
    433 	}
    434 
    435 	/*
    436 	 * If fs_name starts with FAT, we can't set dates before 1980
    437 	 */
    438 	if (0 == strncmp(fsa->fsa_tname, "FAT", 3)) {
    439 		SMB_SS_LOCK(ssp);
    440 		ssp->ss_flags |= SMBS_FST_FAT;
    441 		SMB_SS_UNLOCK(ssp);
    442 	}
    443 
    444 out:
    445 	smb_t2_done(t2p);
    446 	return (0);
    447 }
    448 
    449 int
    450 smbfs_smb_statfs(struct smb_share *ssp, statvfs64_t *sbp,
    451 	struct smb_cred *scp)
    452 {
    453 	int error;
    454 
    455 	if (SMB_DIALECT(SSTOVC(ssp)) >= SMB_DIALECT_LANMAN2_0)
    456 		error = smbfs_smb_statfsLM2(ssp, sbp, scp);
    457 	else
    458 		error = smbfs_smb_statfsLM1(ssp, sbp, scp);
    459 
    460 	return (error);
    461 }
    462 
    463 int
    464 smbfs_smb_statfsLM2(struct smb_share *ssp, statvfs64_t *sbp,
    465 	struct smb_cred *scrp)
    466 {
    467 	struct smb_t2rq *t2p;
    468 	struct mbchain *mbp;
    469 	struct mdchain *mdp;
    470 	uint16_t bsize;
    471 	uint32_t units, bpu, funits;
    472 	uint64_t s, t, f;
    473 	int error;
    474 
    475 	error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_QUERY_FS_INFORMATION,
    476 	    scrp, &t2p);
    477 	if (error)
    478 		return (error);
    479 	mbp = &t2p->t2_tparam;
    480 	mb_init(mbp);
    481 	mb_put_uint16le(mbp, SMB_QFS_ALLOCATION);
    482 	t2p->t2_maxpcount = 4;
    483 	t2p->t2_maxdcount = 4 * 4 + 2;
    484 	error = smb_t2_request(t2p);
    485 	if (error)
    486 		goto out;
    487 
    488 	mdp = &t2p->t2_rdata;
    489 	md_get_uint32le(mdp, NULL);	/* fs id */
    490 	md_get_uint32le(mdp, &bpu);
    491 	md_get_uint32le(mdp, &units);
    492 	md_get_uint32le(mdp, &funits);
    493 	error = md_get_uint16le(mdp, &bsize);
    494 	if (error)
    495 		goto out;
    496 	s = bsize;
    497 	s *= bpu;
    498 	t = units;
    499 	f = funits;
    500 	/*
    501 	 * Don't allow over-large blocksizes as they determine
    502 	 * Finder List-view size granularities.  On the other
    503 	 * hand, we mustn't let the block count overflow the
    504 	 * 31 bits available.
    505 	 */
    506 	while (s > 16 * 1024) {
    507 		if (t > LONG_MAX)
    508 			break;
    509 		s /= 2;
    510 		t *= 2;
    511 		f *= 2;
    512 	}
    513 	while (t > LONG_MAX) {
    514 		t /= 2;
    515 		f /= 2;
    516 		s *= 2;
    517 	}
    518 	sbp->f_bsize  = (ulong_t)s;	/* file system block size */
    519 	sbp->f_blocks = t;	/* total data blocks in file system */
    520 	sbp->f_bfree  = f;	/* free blocks in fs */
    521 	sbp->f_bavail = f;	/* free blocks avail to non-superuser */
    522 	sbp->f_files  = (-1);	/* total file nodes in file system */
    523 	sbp->f_ffree  = (-1);	/* free file nodes in fs */
    524 
    525 out:
    526 	smb_t2_done(t2p);
    527 	return (0);
    528 }
    529 
    530 int
    531 smbfs_smb_statfsLM1(struct smb_share *ssp, statvfs64_t *sbp,
    532 	struct smb_cred *scrp)
    533 {
    534 	struct smb_rq rq, *rqp = &rq;
    535 	struct mdchain *mdp;
    536 	uint16_t units, bpu, bsize, funits;
    537 	uint64_t s, t, f;
    538 	int error;
    539 
    540 	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_QUERY_INFORMATION_DISK,
    541 	    scrp);
    542 	if (error)
    543 		return (error);
    544 	smb_rq_wstart(rqp);
    545 	smb_rq_wend(rqp);
    546 	smb_rq_bstart(rqp);
    547 	smb_rq_bend(rqp);
    548 	error = smb_rq_simple(rqp);
    549 	if (error)
    550 		goto out;
    551 
    552 	smb_rq_getreply(rqp, &mdp);
    553 	md_get_uint16le(mdp, &units);
    554 	md_get_uint16le(mdp, &bpu);
    555 	md_get_uint16le(mdp, &bsize);
    556 	error = md_get_uint16le(mdp, &funits);
    557 	if (error)
    558 		goto out;
    559 	s = bsize;
    560 	s *= bpu;
    561 	t = units;
    562 	f = funits;
    563 	/*
    564 	 * Don't allow over-large blocksizes as they determine
    565 	 * Finder List-view size granularities.  On the other
    566 	 * hand, we mustn't let the block count overflow the
    567 	 * 31 bits available.
    568 	 */
    569 	while (s > 16 * 1024) {
    570 		if (t > LONG_MAX)
    571 			break;
    572 		s /= 2;
    573 		t *= 2;
    574 		f *= 2;
    575 	}
    576 	while (t > LONG_MAX) {
    577 		t /= 2;
    578 		f /= 2;
    579 		s *= 2;
    580 	}
    581 	sbp->f_bsize = (ulong_t)s;	/* file system block size */
    582 	sbp->f_blocks = t;	/* total data blocks in file system */
    583 	sbp->f_bfree = f;	/* free blocks in fs */
    584 	sbp->f_bavail = f;	/* free blocks avail to non-superuser */
    585 	sbp->f_files = (-1);		/* total file nodes in file system */
    586 	sbp->f_ffree = (-1);		/* free file nodes in fs */
    587 
    588 out:
    589 	smb_rq_done(rqp);
    590 	return (0);
    591 }
    592 
    593 int
    594 smbfs_smb_seteof(struct smb_share *ssp, uint16_t fid, uint64_t newsize,
    595 			struct smb_cred *scrp)
    596 {
    597 	struct smb_t2rq *t2p;
    598 	struct smb_vc *vcp = SSTOVC(ssp);
    599 	struct mbchain *mbp;
    600 	int error;
    601 
    602 	error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_FILE_INFORMATION,
    603 	    scrp, &t2p);
    604 	if (error)
    605 		return (error);
    606 	mbp = &t2p->t2_tparam;
    607 	mb_init(mbp);
    608 	mb_put_uint16le(mbp, fid);
    609 	if (vcp->vc_sopt.sv_caps & SMB_CAP_INFOLEVEL_PASSTHRU)
    610 		mb_put_uint16le(mbp, SMB_SFILEINFO_END_OF_FILE_INFORMATION);
    611 	else
    612 		mb_put_uint16le(mbp, SMB_SFILEINFO_END_OF_FILE_INFO);
    613 	mb_put_uint16le(mbp, 0); /* pad */
    614 	mbp = &t2p->t2_tdata;
    615 	mb_init(mbp);
    616 	mb_put_uint64le(mbp, newsize);
    617 	t2p->t2_maxpcount = 2;
    618 	t2p->t2_maxdcount = 0;
    619 	error = smb_t2_request(t2p);
    620 	smb_t2_done(t2p);
    621 	return (error);
    622 }
    623 
    624 /*ARGSUSED*/
    625 int
    626 smbfs_smb_t2rename(struct smbnode *np, struct smbnode *tdnp,
    627 	const char *tname, int tnmlen, struct smb_cred *scrp, int overwrite)
    628 {
    629 	struct smb_t2rq *t2p;
    630 	struct smb_share *ssp = np->n_mount->smi_share;
    631 	struct smb_vc *vcp = SSTOVC(ssp);
    632 	struct mbchain *mbp;
    633 	int32_t *ucslenp;
    634 	int error, cerror;
    635 	uint16_t fid = 0;
    636 
    637 	/* Shared lock for n_fid use below. */
    638 	ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_READER));
    639 
    640 	/* After reconnect, n_fid is invalid */
    641 	if (np->n_vcgenid != ssp->ss_vcgenid)
    642 		return (ESTALE);
    643 
    644 	if (!(vcp->vc_sopt.sv_caps & SMB_CAP_INFOLEVEL_PASSTHRU))
    645 		return (ENOTSUP);
    646 	error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_FILE_INFORMATION,
    647 	    scrp, &t2p);
    648 	if (error)
    649 		return (error);
    650 	if (tdnp) {
    651 		error = smbfs_smb_tmpopen(tdnp, SA_RIGHT_FILE_READ_DATA, scrp,
    652 		    &fid);
    653 		if (error)
    654 			goto exit;
    655 	}
    656 	mbp = &t2p->t2_tparam;
    657 	mb_init(mbp);
    658 	mb_put_uint16le(mbp, np->n_fid);
    659 	mb_put_uint16le(mbp, SMB_SFILEINFO_RENAME_INFORMATION);
    660 	mb_put_uint16le(mbp, 0); /* reserved, nowadays */
    661 	mbp = &t2p->t2_tdata;
    662 	mb_init(mbp);
    663 	mb_put_uint32le(mbp, overwrite);
    664 	mb_put_uint16le(mbp, fid); /* base for tname */
    665 	mb_put_uint16le(mbp, 0); /* part of a 32bit fid? */
    666 	ucslenp = (int32_t *)mb_reserve(mbp, sizeof (int32_t));
    667 	mbp->mb_count = 0;
    668 	error = smb_put_dstring(mbp, vcp, tname, SMB_CS_NONE);
    669 	if (error)
    670 		goto exit;
    671 	mbp->mb_count--;	/* don't count the null */
    672 	*ucslenp = htolel(mbp->mb_count);
    673 	t2p->t2_maxpcount = 2;
    674 	t2p->t2_maxdcount = 0;
    675 	error = smb_t2_request(t2p);
    676 exit:
    677 	if (fid) {
    678 		cerror = smbfs_smb_tmpclose(tdnp, fid, scrp);
    679 		if (cerror)
    680 			SMBVDEBUG("error %d closing %s\n",
    681 			    cerror, tdnp->n_rpath);
    682 	}
    683 	smb_t2_done(t2p);
    684 	return (error);
    685 }
    686 
    687 int
    688 smbfs_smb_flush(struct smbnode *np, struct smb_cred *scrp)
    689 {
    690 	struct smb_share *ssp = np->n_mount->smi_share;
    691 	struct smb_rq rq, *rqp = &rq;
    692 	struct mbchain *mbp;
    693 	int error;
    694 
    695 	/* Shared lock for n_fid use below. */
    696 	ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_READER));
    697 
    698 	if (!(np->n_flag & NFLUSHWIRE))
    699 		return (0);
    700 	if (np->n_fidrefs == 0)
    701 		return (0); /* not open */
    702 
    703 	/* After reconnect, n_fid is invalid */
    704 	if (np->n_vcgenid != ssp->ss_vcgenid)
    705 		return (ESTALE);
    706 
    707 	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_FLUSH, scrp);
    708 	if (error)
    709 		return (error);
    710 	smb_rq_getrequest(rqp, &mbp);
    711 	smb_rq_wstart(rqp);
    712 	mb_put_uint16le(mbp, np->n_fid);
    713 	smb_rq_wend(rqp);
    714 	smb_rq_bstart(rqp);
    715 	smb_rq_bend(rqp);
    716 	error = smb_rq_simple(rqp);
    717 	smb_rq_done(rqp);
    718 	if (!error) {
    719 		mutex_enter(&np->r_statelock);
    720 		np->n_flag &= ~NFLUSHWIRE;
    721 		mutex_exit(&np->r_statelock);
    722 	}
    723 	return (error);
    724 }
    725 
    726 int
    727 smbfs_smb_setfsize(struct smbnode *np, uint16_t fid, uint64_t newsize,
    728 			struct smb_cred *scrp)
    729 {
    730 	struct smb_share *ssp = np->n_mount->smi_share;
    731 	struct smb_rq rq, *rqp = &rq;
    732 	struct mbchain *mbp;
    733 	int error;
    734 
    735 	if (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) {
    736 		/*
    737 		 * This call knows about 64-bit offsets.
    738 		 */
    739 		error = smbfs_smb_seteof(ssp, fid, newsize, scrp);
    740 		if (!error) {
    741 			mutex_enter(&np->r_statelock);
    742 			np->n_flag |= (NFLUSHWIRE | NATTRCHANGED);
    743 			mutex_exit(&np->r_statelock);
    744 			return (0);
    745 		}
    746 	}
    747 
    748 	/*
    749 	 * OK, so fallback to SMB_COM_WRITE, but note:
    750 	 * it only supports 32-bit file offsets.
    751 	 */
    752 	if (newsize > UINT32_MAX)
    753 		return (EFBIG);
    754 
    755 	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_WRITE, scrp);
    756 	if (error)
    757 		return (error);
    758 	smb_rq_getrequest(rqp, &mbp);
    759 	smb_rq_wstart(rqp);
    760 	mb_put_uint16le(mbp, fid);
    761 	mb_put_uint16le(mbp, 0);
    762 	mb_put_uint32le(mbp, newsize);
    763 	mb_put_uint16le(mbp, 0);
    764 	smb_rq_wend(rqp);
    765 	smb_rq_bstart(rqp);
    766 	mb_put_uint8(mbp, SMB_DT_DATA);
    767 	mb_put_uint16le(mbp, 0);
    768 	smb_rq_bend(rqp);
    769 	error = smb_rq_simple(rqp);
    770 	smb_rq_done(rqp);
    771 	mutex_enter(&np->r_statelock);
    772 	np->n_flag |= (NFLUSHWIRE | NATTRCHANGED);
    773 	mutex_exit(&np->r_statelock);
    774 	return (error);
    775 }
    776 
    777 /*
    778  * Old method for getting file attributes.
    779  */
    780 int
    781 smbfs_smb_query_info(struct smbnode *np, const char *name, int nmlen,
    782 	struct smbfattr *fap, struct smb_cred *scrp)
    783 {
    784 	struct smb_rq rq, *rqp = &rq;
    785 	struct smb_share *ssp = np->n_mount->smi_share;
    786 	struct mbchain *mbp;
    787 	struct mdchain *mdp;
    788 	uint8_t wc;
    789 	int error;
    790 	uint16_t wattr;
    791 	uint32_t longint;
    792 
    793 	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_QUERY_INFORMATION, scrp);
    794 	if (error)
    795 		return (error);
    796 	smb_rq_getrequest(rqp, &mbp);
    797 	smb_rq_wstart(rqp);
    798 	smb_rq_wend(rqp);
    799 	smb_rq_bstart(rqp);
    800 	mb_put_uint8(mbp, SMB_DT_ASCII);
    801 
    802 	error = smbfs_fullpath(mbp, SSTOVC(ssp), np,
    803 	    name, &nmlen, '\\');
    804 	if (error)
    805 		goto out;
    806 	smb_rq_bend(rqp);
    807 	error = smb_rq_simple(rqp);
    808 	if (error)
    809 		goto out;
    810 	smb_rq_getreply(rqp, &mdp);
    811 	error = md_get_uint8(mdp, &wc);
    812 	if (error)
    813 		goto out;
    814 	if (wc != 10) {
    815 		error = EBADRPC;
    816 		goto out;
    817 	}
    818 	md_get_uint16le(mdp, &wattr);
    819 	fap->fa_attr = wattr;
    820 	/*
    821 	 * Be careful using the time returned here, as
    822 	 * with FAT on NT4SP6, at least, the time returned is low
    823 	 * 32 bits of 100s of nanoseconds (since 1601) so it rolls
    824 	 * over about every seven minutes!
    825 	 */
    826 	md_get_uint32le(mdp, &longint); /* specs: secs since 1970 */
    827 	smb_time_server2local(longint,
    828 	    SSTOVC(ssp)->vc_sopt.sv_tz, &fap->fa_mtime);
    829 	error = md_get_uint32le(mdp, &longint);
    830 	fap->fa_size = longint;
    831 
    832 out:
    833 	smb_rq_done(rqp);
    834 	return (error);
    835 }
    836 
    837 /*
    838  * Set DOS file attributes. mtime should be NULL for dialects above lm10
    839  */
    840 int
    841 smbfs_smb_setpattr1(struct smbnode *np, const char *name, int len,
    842 	uint32_t attr, struct timespec *mtime,
    843 	struct smb_cred *scrp)
    844 {
    845 	struct smb_rq rq, *rqp = &rq;
    846 	struct smb_share *ssp = np->n_mount->smi_share;
    847 	struct mbchain *mbp;
    848 	long time;
    849 	int error, svtz;
    850 
    851 	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_SET_INFORMATION, scrp);
    852 	if (error)
    853 		return (error);
    854 	svtz = SSTOVC(ssp)->vc_sopt.sv_tz;
    855 	smb_rq_getrequest(rqp, &mbp);
    856 	smb_rq_wstart(rqp);
    857 	mb_put_uint16le(mbp, (uint16_t)attr);
    858 	if (mtime) {
    859 		smb_time_local2server(mtime, svtz, &time);
    860 	} else
    861 		time = 0;
    862 	mb_put_uint32le(mbp, time);		/* mtime */
    863 	mb_put_mem(mbp, NULL, 5 * 2, MB_MZERO);
    864 	smb_rq_wend(rqp);
    865 	smb_rq_bstart(rqp);
    866 	mb_put_uint8(mbp, SMB_DT_ASCII);
    867 
    868 	error = smbfs_fullpath(mbp, SSTOVC(ssp), np, name, &len, '\\');
    869 	if (error)
    870 		goto out;
    871 	mb_put_uint8(mbp, SMB_DT_ASCII);
    872 	if (SMB_UNICODE_STRINGS(SSTOVC(ssp))) {
    873 		mb_put_padbyte(mbp);
    874 		mb_put_uint8(mbp, 0);	/* 1st byte NULL Unicode char */
    875 	}
    876 	mb_put_uint8(mbp, 0);
    877 	smb_rq_bend(rqp);
    878 	error = smb_rq_simple(rqp);
    879 
    880 out:
    881 	smb_rq_done(rqp);
    882 	return (error);
    883 }
    884 
    885 int
    886 smbfs_smb_hideit(struct smbnode *np, const char *name, int len,
    887 			struct smb_cred *scrp)
    888 {
    889 	struct smbfattr fa;
    890 	int error;
    891 	uint32_t attr;
    892 
    893 	error = smbfs_smb_query_info(np, name, len, &fa, scrp);
    894 	attr = fa.fa_attr;
    895 	if (!error && !(attr & SMB_FA_HIDDEN)) {
    896 		attr |= SMB_FA_HIDDEN;
    897 		error = smbfs_smb_setpattr1(np, name, len, attr, NULL, scrp);
    898 	}
    899 	return (error);
    900 }
    901 
    902 
    903 int
    904 smbfs_smb_unhideit(struct smbnode *np, const char *name, int len,
    905 			struct smb_cred *scrp)
    906 {
    907 	struct smbfattr fa;
    908 	uint32_t attr;
    909 	int error;
    910 
    911 	error = smbfs_smb_query_info(np, name, len, &fa, scrp);
    912 	attr = fa.fa_attr;
    913 	if (!error && (attr & SMB_FA_HIDDEN)) {
    914 		attr &= ~SMB_FA_HIDDEN;
    915 		error = smbfs_smb_setpattr1(np, name, len, attr, NULL, scrp);
    916 	}
    917 	return (error);
    918 }
    919 
    920 /*
    921  * Set file attributes (optionally: DOS attr, atime, mtime)
    922  * either by open FID or by path name (FID == -1).
    923  */
    924 int
    925 smbfs_smb_setfattr(
    926 	struct smbnode *np,
    927 	int fid,
    928 	uint32_t attr,
    929 	struct timespec *mtime,
    930 	struct timespec *atime,
    931 	struct smb_cred *scrp)
    932 {
    933 	struct smb_share *ssp = np->n_mount->smi_share;
    934 	struct smb_vc *vcp = SSTOVC(ssp);
    935 	int error;
    936 
    937 	/*
    938 	 * Normally can use the trans2 call.
    939 	 */
    940 	if (vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) {
    941 		error = smbfs_smb_setfattrNT(np, fid,
    942 		    attr, mtime, atime, scrp);
    943 		return (error);
    944 	}
    945 
    946 	/*
    947 	 * Fall-back for older protocols.
    948 	 */
    949 	if (SMB_DIALECT(vcp) >= SMB_DIALECT_LANMAN1_0) {
    950 		error = smbfs_smb_setftime1(np, fid,
    951 		    mtime, atime, scrp);
    952 		return (error);
    953 	}
    954 	error = smbfs_smb_setpattr1(np, NULL, 0,
    955 	    attr, mtime, scrp);
    956 	return (error);
    957 }
    958 
    959 /*
    960  * Set file atime and mtime. Isn't supported by core dialect.
    961  */
    962 int
    963 smbfs_smb_setftime1(
    964 	struct smbnode *np,
    965 	uint16_t fid,
    966 	struct timespec *mtime,
    967 	struct timespec *atime,
    968 	struct smb_cred *scrp)
    969 {
    970 	struct smb_rq rq, *rqp = &rq;
    971 	struct smb_share *ssp = np->n_mount->smi_share;
    972 	struct mbchain *mbp;
    973 	uint16_t date, time;
    974 	int error, tzoff;
    975 
    976 	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_SET_INFORMATION2, scrp);
    977 	if (error)
    978 		return (error);
    979 
    980 	tzoff = SSTOVC(ssp)->vc_sopt.sv_tz;
    981 	smb_rq_getrequest(rqp, &mbp);
    982 	smb_rq_wstart(rqp);
    983 	mb_put_uint16le(mbp, fid);
    984 	mb_put_uint32le(mbp, 0);		/* creation time */
    985 
    986 	if (atime)
    987 		smb_time_unix2dos(atime, tzoff, &date, &time, NULL);
    988 	else
    989 		time = date = 0;
    990 	mb_put_uint16le(mbp, date);
    991 	mb_put_uint16le(mbp, time);
    992 	if (mtime)
    993 		smb_time_unix2dos(mtime, tzoff, &date, &time, NULL);
    994 	else
    995 		time = date = 0;
    996 	mb_put_uint16le(mbp, date);
    997 	mb_put_uint16le(mbp, time);
    998 	smb_rq_wend(rqp);
    999 	smb_rq_bstart(rqp);
   1000 	smb_rq_bend(rqp);
   1001 	error = smb_rq_simple(rqp);
   1002 	SMBVDEBUG("%d\n", error);
   1003 	smb_rq_done(rqp);
   1004 	return (error);
   1005 }
   1006 
   1007 /*
   1008  * Set DOS file attributes, either via open FID or by path name.
   1009  * Looks like this call can be used only if CAP_NT_SMBS bit is on.
   1010  *
   1011  * When setting via path (fid == -1):
   1012  * *BASIC_INFO works with Samba, but Win2K servers say it is an
   1013  * invalid information level on a SET_PATH_INFO.  Note Win2K does
   1014  * support *BASIC_INFO on a SET_FILE_INFO, and they support the
   1015  * equivalent *BASIC_INFORMATION on SET_PATH_INFO.  Go figure.
   1016  */
   1017 int
   1018 smbfs_smb_setfattrNT(
   1019 	struct smbnode *np,
   1020 	int fid,		/* if fid == -1, set by path */
   1021 	uint32_t attr,
   1022 	struct timespec *mtime,
   1023 	struct timespec *atime,
   1024 	struct smb_cred *scrp)
   1025 {
   1026 	struct smb_t2rq *t2p;
   1027 	struct smb_share *ssp = np->n_mount->smi_share;
   1028 	struct smb_vc *vcp = SSTOVC(ssp);
   1029 	struct mbchain *mbp;
   1030 	uint64_t tm;
   1031 	int error;
   1032 	uint16_t cmd, level;
   1033 
   1034 	if (fid == -1) {
   1035 		cmd = SMB_TRANS2_SET_PATH_INFORMATION;
   1036 	} else {
   1037 		if (fid > UINT16_MAX)
   1038 			return (EINVAL);
   1039 		cmd = SMB_TRANS2_SET_FILE_INFORMATION;
   1040 	}
   1041 	if (vcp->vc_sopt.sv_caps & SMB_CAP_INFOLEVEL_PASSTHRU)
   1042 		level = SMB_SFILEINFO_BASIC_INFORMATION;
   1043 	else
   1044 		level = SMB_SFILEINFO_BASIC_INFO;
   1045 
   1046 	error = smb_t2_alloc(SSTOCP(ssp), cmd, scrp, &t2p);
   1047 	if (error)
   1048 		return (error);
   1049 
   1050 	mbp = &t2p->t2_tparam;
   1051 	mb_init(mbp);
   1052 
   1053 	if (cmd == SMB_TRANS2_SET_FILE_INFORMATION)
   1054 		mb_put_uint16le(mbp, fid);
   1055 
   1056 	mb_put_uint16le(mbp, level);
   1057 	mb_put_uint32le(mbp, 0);		/* MBZ */
   1058 
   1059 	if (cmd == SMB_TRANS2_SET_PATH_INFORMATION) {
   1060 		error = smbfs_fullpath(mbp, vcp, np, NULL, NULL, '\\');
   1061 		if (error != 0)
   1062 			goto out;
   1063 	}
   1064 
   1065 	/* FAT file systems don't support dates earlier than 1980. */
   1066 
   1067 	mbp = &t2p->t2_tdata;
   1068 	mb_init(mbp);
   1069 	mb_put_uint64le(mbp, 0);		/* creation time */
   1070 	if (atime) {
   1071 		smb_time_local2NT(atime, &tm);
   1072 		if (tm != 0 && (ssp->ss_flags & SMBS_FST_FAT) &&
   1073 		    tm < NT1980)
   1074 			tm = NT1980;
   1075 	} else
   1076 		tm = 0;
   1077 	mb_put_uint64le(mbp, tm);		/* access time */
   1078 	if (mtime) {
   1079 		smb_time_local2NT(mtime, &tm);
   1080 		if (tm != 0 && (ssp->ss_flags & SMBS_FST_FAT) &&
   1081 		    tm < NT1980)
   1082 			tm = NT1980;
   1083 	} else
   1084 		tm = 0;
   1085 	mb_put_uint64le(mbp, tm);		/* last write time */
   1086 	mb_put_uint64le(mbp, 0);		/* ctime (no change) */
   1087 	mb_put_uint32le(mbp, attr);
   1088 	mb_put_uint32le(mbp, 0);		/* padding */
   1089 	t2p->t2_maxpcount = 2;
   1090 	t2p->t2_maxdcount = 0;
   1091 	error = smb_t2_request(t2p);
   1092 out:
   1093 	smb_t2_done(t2p);
   1094 	return (error);
   1095 }
   1096 
   1097 /*
   1098  * Modern create/open of file or directory.
   1099  *
   1100  * If disp is ..._DISP_OPEN, or ...DISP_OPEN_IF, or...
   1101  * then this is an open attempt, and:
   1102  *   If xattr then name is the stream to be opened at np,
   1103  *   Else np should be opened.
   1104  *   ...we won't touch *fidp,
   1105  *   ...we will set or clear *attrcacheupdated.
   1106  * Else this is a creation attempt, and:
   1107  *   If xattr then name is the stream to create at np,
   1108  *   Else name is the thing to create under directory np.
   1109  *   ...we will return *fidp,
   1110  *   ...we won't touch *attrcacheupdated.
   1111  *
   1112  * Note, We use: disp = ...OPEN_IF, ...OVERWRITE_IF, etc.
   1113  * now too, which may or may not create a new object.
   1114  */
   1115 int
   1116 smbfs_smb_ntcreatex(
   1117 	struct smbnode *np,
   1118 	const char *name,
   1119 	int nmlen,
   1120 	int xattr,		/* is named stream? */
   1121 	uint32_t req_acc,	/* requested access */
   1122 	uint32_t efa,		/* ext. file attrs (DOS attr +) */
   1123 	uint32_t share_acc,
   1124 	uint32_t disp,		/* open disposition */
   1125 	uint32_t createopt,	/* NTCREATEX_OPTIONS_ */
   1126 	struct smb_cred *scrp,
   1127 	uint16_t *fidp,
   1128 	uint32_t *cr_act_p,	/* create action */
   1129 	struct smbfattr *fap)	/* optional */
   1130 {
   1131 	struct smb_rq rq, *rqp = &rq;
   1132 	struct smb_share *ssp = np->n_mount->smi_share;
   1133 	struct smb_vc *vcp = SSTOVC(ssp);
   1134 	struct mbchain *mbp;
   1135 	struct mdchain *mdp;
   1136 	struct smbfattr fa;
   1137 	uint8_t wc;
   1138 	uint32_t longint, createact;
   1139 	uint64_t llongint;
   1140 	int error;
   1141 	uint16_t fid, *namelenp;
   1142 
   1143 	bzero(&fa, sizeof (fa));
   1144 	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_NT_CREATE_ANDX, scrp);
   1145 	if (error)
   1146 		return (error);
   1147 	smb_rq_getrequest(rqp, &mbp);
   1148 	smb_rq_wstart(rqp);
   1149 	mb_put_uint8(mbp, 0xff);	/* secondary command */
   1150 	mb_put_uint8(mbp, 0);		/* MBZ */
   1151 	mb_put_uint16le(mbp, 0);	/* offset to next command (none) */
   1152 	mb_put_uint8(mbp, 0);		/* MBZ */
   1153 	namelenp = (uint16_t *)mb_reserve(mbp, sizeof (uint16_t));
   1154 	/*
   1155 	 * XP to a W2K Server does not use NTCREATEX_FLAGS_OPEN_DIRECTORY
   1156 	 * for creating nor for opening a directory.  Samba ignores the bit.
   1157 	 */
   1158 	mb_put_uint32le(mbp, 0);	/* NTCREATEX_FLAGS_* */
   1159 	mb_put_uint32le(mbp, 0);	/* FID - basis for path if not root */
   1160 	mb_put_uint32le(mbp, req_acc);
   1161 	mb_put_uint64le(mbp, 0);	/* "initial allocation size" */
   1162 	mb_put_uint32le(mbp, efa);
   1163 	mb_put_uint32le(mbp, share_acc);
   1164 	mb_put_uint32le(mbp, disp);
   1165 	mb_put_uint32le(mbp, createopt);
   1166 	mb_put_uint32le(mbp, NTCREATEX_IMPERSONATION_IMPERSONATION); /* (?) */
   1167 	mb_put_uint8(mbp, 0);   /* security flags (?) */
   1168 	smb_rq_wend(rqp);
   1169 	smb_rq_bstart(rqp);
   1170 
   1171 	if (name == NULL)
   1172 		nmlen = 0;
   1173 	error = smbfs_fullpath(mbp, vcp, np, name, &nmlen,
   1174 	    xattr ? ':' : '\\');
   1175 	if (error)
   1176 		goto done;
   1177 	*namelenp = htoles(nmlen); /* includes null */
   1178 	smb_rq_bend(rqp);
   1179 	/*
   1180 	 * Don't want to risk missing a successful
   1181 	 * open response, or we could "leak" FIDs.
   1182 	 */
   1183 	rqp->sr_flags |= SMBR_NOINTR_RECV;
   1184 	error = smb_rq_simple_timed(rqp, smb_timo_open);
   1185 	if (error)
   1186 		goto done;
   1187 	smb_rq_getreply(rqp, &mdp);
   1188 	/*
   1189 	 * spec says 26 for word count, but 34 words are defined
   1190 	 * and observed from win2000
   1191 	 */
   1192 	error = md_get_uint8(mdp, &wc);
   1193 	if (error)
   1194 		goto done;
   1195 	if (wc != 26 && wc != 34 && wc != 42) {
   1196 		error = EBADRPC;
   1197 		goto done;
   1198 	}
   1199 	md_get_uint8(mdp, NULL);		/* secondary cmd */
   1200 	md_get_uint8(mdp, NULL);		/* mbz */
   1201 	md_get_uint16le(mdp, NULL);		/* andxoffset */
   1202 	md_get_uint8(mdp, NULL);		/* oplock lvl granted */
   1203 	md_get_uint16le(mdp, &fid);		/* file ID */
   1204 	md_get_uint32le(mdp, &createact);	/* create_action */
   1205 
   1206 	md_get_uint64le(mdp, &llongint);	/* creation time */
   1207 	smb_time_NT2local(llongint, &fa.fa_createtime);
   1208 	md_get_uint64le(mdp, &llongint);	/* access time */
   1209 	smb_time_NT2local(llongint, &fa.fa_atime);
   1210 	md_get_uint64le(mdp, &llongint);	/* write time */
   1211 	smb_time_NT2local(llongint, &fa.fa_mtime);
   1212 	md_get_uint64le(mdp, &llongint);	/* change time */
   1213 	smb_time_NT2local(llongint, &fa.fa_ctime);
   1214 
   1215 	md_get_uint32le(mdp, &longint);		/* attributes */
   1216 	fa.fa_attr = longint;
   1217 
   1218 	md_get_uint64le(mdp, &llongint);	/* allocation size */
   1219 	fa.fa_allocsz = llongint;
   1220 
   1221 	md_get_uint64le(mdp, &llongint);	/* EOF position */
   1222 	fa.fa_size = llongint;
   1223 
   1224 	error = md_get_uint16le(mdp, NULL);	/* file type */
   1225 	/* other stuff we don't care about */
   1226 
   1227 done:
   1228 	smb_rq_done(rqp);
   1229 	if (error)
   1230 		return (error);
   1231 
   1232 	if (fidp)
   1233 		*fidp = fid;
   1234 	if (cr_act_p)
   1235 		*cr_act_p = createact;
   1236 	if (fap)
   1237 		*fap = fa; /* struct copy */
   1238 
   1239 	return (0);
   1240 }
   1241 
   1242 static uint32_t
   1243 smb_mode2rights(int mode)
   1244 {
   1245 	mode = mode & SMB_AM_OPENMODE;
   1246 	uint32_t rights =
   1247 	    STD_RIGHT_SYNCHRONIZE_ACCESS |
   1248 	    STD_RIGHT_READ_CONTROL_ACCESS;
   1249 
   1250 	if ((mode == SMB_AM_OPENREAD) ||
   1251 	    (mode == SMB_AM_OPENRW)) {
   1252 		rights |=
   1253 		    SA_RIGHT_FILE_READ_ATTRIBUTES |
   1254 		    SA_RIGHT_FILE_READ_DATA;
   1255 	}
   1256 
   1257 	if ((mode == SMB_AM_OPENWRITE) ||
   1258 	    (mode == SMB_AM_OPENRW)) {
   1259 		rights |=
   1260 		    SA_RIGHT_FILE_WRITE_ATTRIBUTES |
   1261 		    SA_RIGHT_FILE_APPEND_DATA |
   1262 		    SA_RIGHT_FILE_WRITE_DATA;
   1263 	}
   1264 
   1265 	if (mode == SMB_AM_OPENEXEC) {
   1266 		rights |=
   1267 		    SA_RIGHT_FILE_READ_ATTRIBUTES |
   1268 		    SA_RIGHT_FILE_EXECUTE;
   1269 	}
   1270 
   1271 	return (rights);
   1272 }
   1273 
   1274 static int
   1275 smb_rights2mode(uint32_t rights)
   1276 {
   1277 	int accmode = SMB_AM_OPENEXEC; /* our fallback */
   1278 
   1279 	if (rights & (SA_RIGHT_FILE_APPEND_DATA | SA_RIGHT_FILE_DELETE_CHILD |
   1280 	    SA_RIGHT_FILE_WRITE_EA | SA_RIGHT_FILE_WRITE_ATTRIBUTES |
   1281 	    SA_RIGHT_FILE_WRITE_DATA | STD_RIGHT_WRITE_OWNER_ACCESS |
   1282 	    STD_RIGHT_DELETE_ACCESS | STD_RIGHT_WRITE_DAC_ACCESS))
   1283 		accmode = SMB_AM_OPENWRITE;
   1284 	if (rights & (SA_RIGHT_FILE_READ_DATA | SA_RIGHT_FILE_READ_ATTRIBUTES |
   1285 	    SA_RIGHT_FILE_READ_EA | STD_RIGHT_READ_CONTROL_ACCESS))
   1286 		accmode = (accmode == SMB_AM_OPENEXEC) ? SMB_AM_OPENREAD
   1287 		    : SMB_AM_OPENRW;
   1288 	return (accmode);
   1289 }
   1290 
   1291 static int
   1292 smbfs_smb_oldopen(
   1293 	struct smbnode *np,
   1294 	const char *name,
   1295 	int nmlen,
   1296 	int xattr,
   1297 	int accmode,
   1298 	struct smb_cred *scrp,
   1299 	uint16_t *fidp,
   1300 	uint16_t *granted_mode_p,
   1301 	smbfattr_t *fap)
   1302 {
   1303 	struct smb_rq rq, *rqp = &rq;
   1304 	struct smb_share *ssp = np->n_mount->smi_share;
   1305 	struct smb_vc *vcp = SSTOVC(ssp);
   1306 	struct mbchain *mbp;
   1307 	struct mdchain *mdp;
   1308 	struct smbfattr fa;
   1309 	uint8_t wc;
   1310 	uint16_t wattr;
   1311 	uint32_t longint;
   1312 	int error;
   1313 
   1314 	bzero(&fa, sizeof (fa));
   1315 
   1316 	/*
   1317 	 * XXX: move to callers...
   1318 	 *
   1319 	 * Use DENYNONE to give unixy semantics of permitting
   1320 	 * everything not forbidden by permissions.  Ie denial
   1321 	 * is up to server with clients/openers needing to use
   1322 	 * advisory locks for further control.
   1323 	 */
   1324 	accmode |= SMB_SM_DENYNONE;
   1325 
   1326 	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_OPEN, scrp);
   1327 	if (error)
   1328 		return (error);
   1329 	smb_rq_getrequest(rqp, &mbp);
   1330 	smb_rq_wstart(rqp);
   1331 	mb_put_uint16le(mbp, accmode);
   1332 	mb_put_uint16le(mbp, SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_RDONLY |
   1333 	    SMB_FA_DIR);
   1334 	smb_rq_wend(rqp);
   1335 	smb_rq_bstart(rqp);
   1336 	mb_put_uint8(mbp, SMB_DT_ASCII);
   1337 
   1338 	error = smbfs_fullpath(mbp, vcp, np, name, &nmlen,
   1339 	    xattr ? ':' : '\\');
   1340 	if (error)
   1341 		goto done;
   1342 	smb_rq_bend(rqp);
   1343 	/*
   1344 	 * Don't want to risk missing a successful
   1345 	 * open response, or we could "leak" FIDs.
   1346 	 */
   1347 	rqp->sr_flags |= SMBR_NOINTR_RECV;
   1348 	error = smb_rq_simple_timed(rqp, smb_timo_open);
   1349 	if (error)
   1350 		goto done;
   1351 	smb_rq_getreply(rqp, &mdp);
   1352 	/*
   1353 	 * 8/2002 a DAVE server returned wc of 15 so we ignore that.
   1354 	 * (the actual packet length and data was correct)
   1355 	 */
   1356 	error = md_get_uint8(mdp, &wc);
   1357 	if (error)
   1358 		goto done;
   1359 	if (wc != 7 && wc != 15) {
   1360 		error = EBADRPC;
   1361 		goto done;
   1362 	}
   1363 	md_get_uint16le(mdp, fidp);
   1364 	md_get_uint16le(mdp, &wattr);
   1365 	fa.fa_attr = wattr;
   1366 	/*
   1367 	 * Be careful using the time returned here, as
   1368 	 * with FAT on NT4SP6, at least, the time returned is low
   1369 	 * 32 bits of 100s of nanoseconds (since 1601) so it rolls
   1370 	 * over about every seven minutes!
   1371 	 */
   1372 	md_get_uint32le(mdp, &longint); /* specs: secs since 1970 */
   1373 	smb_time_server2local(longint, vcp->vc_sopt.sv_tz, &fa.fa_mtime);
   1374 	md_get_uint32le(mdp, &longint);
   1375 	fa.fa_size = longint;
   1376 	error = md_get_uint16le(mdp, granted_mode_p);
   1377 
   1378 done:
   1379 	smb_rq_done(rqp);
   1380 	if (error)
   1381 		return (error);
   1382 
   1383 	if (fap)
   1384 		*fap = fa; /* struct copy */
   1385 
   1386 	return (0);
   1387 }
   1388 
   1389 int
   1390 smbfs_smb_tmpopen(struct smbnode *np, uint32_t rights, struct smb_cred *scrp,
   1391 			uint16_t *fidp)
   1392 {
   1393 	struct smb_share *ssp = np->n_mount->smi_share;
   1394 	struct smb_vc *vcp = SSTOVC(ssp);
   1395 	int accmode, error;
   1396 
   1397 	/* Shared lock for n_fid use below. */
   1398 	ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_READER));
   1399 
   1400 	/* Can we re-use n_fid? or must we open anew? */
   1401 	mutex_enter(&np->r_statelock);
   1402 	if (np->n_fidrefs > 0 &&
   1403 	    np->n_vcgenid == ssp->ss_vcgenid &&
   1404 	    (rights & np->n_rights) == rights) {
   1405 		np->n_fidrefs++;
   1406 		*fidp = np->n_fid;
   1407 		mutex_exit(&np->r_statelock);
   1408 		return (0);
   1409 	}
   1410 	mutex_exit(&np->r_statelock);
   1411 
   1412 	/* re-open an existing file. */
   1413 	if (vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) {
   1414 		error = smbfs_smb_ntcreatex(np,
   1415 		    NULL, 0, 0,	/* name nmlen xattr */
   1416 		    rights, SMB_EFA_NORMAL,
   1417 		    NTCREATEX_SHARE_ACCESS_ALL,
   1418 		    NTCREATEX_DISP_OPEN,
   1419 		    0, /* create options */
   1420 		    scrp, fidp,
   1421 		    NULL, NULL); /* cr_act_p fa_p */
   1422 		return (error);
   1423 	}
   1424 
   1425 	accmode = smb_rights2mode(rights);
   1426 	error = smbfs_smb_oldopen(np,
   1427 	    NULL, 0, 0, /* name nmlen xattr */
   1428 	    accmode, scrp,
   1429 	    fidp,
   1430 	    NULL, /* granted mode p */
   1431 	    NULL); /* fa p */
   1432 
   1433 	return (error);
   1434 }
   1435 
   1436 int
   1437 smbfs_smb_tmpclose(struct smbnode *np, uint16_t fid, struct smb_cred *scrp)
   1438 {
   1439 	struct smb_share *ssp = np->n_mount->smi_share;
   1440 	int error = 0;
   1441 	uint16_t oldfid = SMB_FID_UNUSED;
   1442 
   1443 	/* Shared lock for n_fid use below. */
   1444 	ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_READER));
   1445 
   1446 	mutex_enter(&np->r_statelock);
   1447 	if (fid == np->n_fid) {
   1448 		ASSERT(np->n_fidrefs > 0);
   1449 		if (--np->n_fidrefs == 0) {
   1450 			/*
   1451 			 * Don't expect to find the last reference
   1452 			 * here in tmpclose.  Hard to deal with as
   1453 			 * we don't have r_lkserlock exclusive.
   1454 			 * Will close oldfid below.
   1455 			 */
   1456 			oldfid = np->n_fid;
   1457 			np->n_fid = SMB_FID_UNUSED;
   1458 		}
   1459 	} else {
   1460 		/* Will close the passed fid. */
   1461 		oldfid = fid;
   1462 	}
   1463 	mutex_exit(&np->r_statelock);
   1464 
   1465 	if (oldfid != SMB_FID_UNUSED)
   1466 		error = smbfs_smb_close(ssp, oldfid, NULL, scrp);
   1467 
   1468 	return (error);
   1469 }
   1470 
   1471 int
   1472 smbfs_smb_open(
   1473 	struct smbnode *np,
   1474 	const char *name,
   1475 	int nmlen,
   1476 	int xattr,
   1477 	uint32_t rights,
   1478 	struct smb_cred *scrp,
   1479 	uint16_t *fidp,
   1480 	uint32_t *rightsp,
   1481 	smbfattr_t *fap)
   1482 {
   1483 	struct smb_share *ssp = np->n_mount->smi_share;
   1484 	struct smb_vc *vcp = SSTOVC(ssp);
   1485 	int accmode, error;
   1486 	uint16_t grantedmode;
   1487 
   1488 	/* open an existing file */
   1489 	if (vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) {
   1490 		error = smbfs_smb_ntcreatex(np,
   1491 		    name, nmlen, xattr,
   1492 		    rights, SMB_EFA_NORMAL,
   1493 		    NTCREATEX_SHARE_ACCESS_ALL,
   1494 		    NTCREATEX_DISP_OPEN,
   1495 		    0, /* create options */
   1496 		    scrp, fidp,
   1497 		    NULL, fap); /* cr_act_p fa_p */
   1498 		if (error != 0)
   1499 			return (error);
   1500 		*rightsp = rights;
   1501 		return (0);
   1502 	}
   1503 
   1504 	accmode = smb_rights2mode(rights);
   1505 	error = smbfs_smb_oldopen(np,
   1506 	    name, nmlen, xattr, accmode, scrp,
   1507 	    fidp, &grantedmode, fap);
   1508 	if (error != 0)
   1509 		return (error);
   1510 	*rightsp = smb_mode2rights(grantedmode);
   1511 	(void) smbfs_smb_getfattr(np, fap, scrp);
   1512 
   1513 	return (0);
   1514 }
   1515 
   1516 int
   1517 smbfs_smb_close(struct smb_share *ssp, uint16_t fid, struct timespec *mtime,
   1518 	struct smb_cred *scrp)
   1519 {
   1520 	struct smb_rq rq, *rqp = &rq;
   1521 	struct mbchain *mbp;
   1522 	long time;
   1523 	int error;
   1524 
   1525 	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CLOSE, scrp);
   1526 	if (error)
   1527 		return (error);
   1528 	smb_rq_getrequest(rqp, &mbp);
   1529 	smb_rq_wstart(rqp);
   1530 	mb_put_uint16le(mbp, fid);
   1531 	if (mtime) {
   1532 		int sv_tz = SSTOVC(ssp)->vc_sopt.sv_tz;
   1533 		smb_time_local2server(mtime, sv_tz, &time);
   1534 	} else
   1535 		time = 0;
   1536 	mb_put_uint32le(mbp, time);
   1537 	smb_rq_wend(rqp);
   1538 	smb_rq_bstart(rqp);
   1539 	smb_rq_bend(rqp);
   1540 
   1541 	/*
   1542 	 * We don't really care about the result here, but we
   1543 	 * do need to make sure we send this out, or we could
   1544 	 * "leak" open file handles on interrupt or timeout.
   1545 	 * The NOINTR_SEND flag makes this request immune to
   1546 	 * interrupt or timeout until the send is done.
   1547 	 */
   1548 	rqp->sr_flags |= SMBR_NOINTR_SEND;
   1549 	error = smb_rq_simple(rqp);
   1550 	smb_rq_done(rqp);
   1551 	/*
   1552 	 * ENOTCONN isn't interesting - if the connection is closed,
   1553 	 * so are all our FIDs - and EIO is also not interesting,
   1554 	 * as it means a forced unmount was done. (was ENXIO)
   1555 	 * Also ETIME, which means we sent the request but gave up
   1556 	 * waiting before the response came back.
   1557 	 *
   1558 	 * Don't clog up the system log with warnings about these
   1559 	 * uninteresting failures on closes.
   1560 	 */
   1561 	switch (error) {
   1562 	case ENOTCONN:
   1563 	case ENXIO:
   1564 	case EIO:
   1565 	case ETIME:
   1566 		error = 0;
   1567 	}
   1568 	return (error);
   1569 }
   1570 
   1571 static int
   1572 smbfs_smb_oldcreate(struct smbnode *dnp, const char *name, int nmlen,
   1573 	int xattr, struct smb_cred *scrp, uint16_t *fidp)
   1574 {
   1575 	struct smb_rq rq, *rqp = &rq;
   1576 	struct smb_share *ssp = dnp->n_mount->smi_share;
   1577 	struct mbchain *mbp;
   1578 	struct mdchain *mdp;
   1579 	struct timespec ctime;
   1580 	uint8_t wc;
   1581 	long tm;
   1582 	int error;
   1583 	uint16_t attr = SMB_FA_ARCHIVE;
   1584 
   1585 	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CREATE, scrp);
   1586 	if (error)
   1587 		return (error);
   1588 	smb_rq_getrequest(rqp, &mbp);
   1589 	smb_rq_wstart(rqp);
   1590 	if (name && *name == '.')
   1591 		attr |= SMB_FA_HIDDEN;
   1592 	mb_put_uint16le(mbp, attr);		/* attributes  */
   1593 	gethrestime(&ctime);
   1594 	smb_time_local2server(&ctime, SSTOVC(ssp)->vc_sopt.sv_tz, &tm);
   1595 	mb_put_uint32le(mbp, tm);
   1596 	smb_rq_wend(rqp);
   1597 	smb_rq_bstart(rqp);
   1598 	mb_put_uint8(mbp, SMB_DT_ASCII);
   1599 	error = smbfs_fullpath(mbp, SSTOVC(ssp), dnp, name, &nmlen,
   1600 	    xattr ? ':' : '\\');
   1601 	if (error)
   1602 		goto out;
   1603 	smb_rq_bend(rqp);
   1604 	/*
   1605 	 * Don't want to risk missing a successful
   1606 	 * open response, or we could "leak" FIDs.
   1607 	 */
   1608 	rqp->sr_flags |= SMBR_NOINTR_RECV;
   1609 	error = smb_rq_simple_timed(rqp, smb_timo_open);
   1610 	if (error)
   1611 		goto out;
   1612 
   1613 	smb_rq_getreply(rqp, &mdp);
   1614 	md_get_uint8(mdp, &wc);
   1615 	if (wc != 1) {
   1616 		error = EBADRPC;
   1617 		goto out;
   1618 	}
   1619 	error = md_get_uint16le(mdp, fidp);
   1620 
   1621 out:
   1622 	smb_rq_done(rqp);
   1623 	return (error);
   1624 }
   1625 
   1626 int
   1627 smbfs_smb_create(
   1628 	struct smbnode *dnp,
   1629 	const char *name,
   1630 	int nmlen,
   1631 	int xattr,
   1632 	uint32_t disp,
   1633 	struct smb_cred *scrp,
   1634 	uint16_t *fidp)
   1635 {
   1636 	struct smb_share *ssp = dnp->n_mount->smi_share;
   1637 	struct smb_vc *vcp = SSTOVC(ssp);
   1638 	uint32_t efa, rights;
   1639 	int error;
   1640 
   1641 	/*
   1642 	 * At present the only access we might need is to WRITE data,
   1643 	 * and that only if we are creating a "symlink".  When/if the
   1644 	 * access needed gets more complex it should made a parameter
   1645 	 * and be set upstream.
   1646 	 */
   1647 	if (vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) {
   1648 		rights = SA_RIGHT_FILE_WRITE_DATA;
   1649 		efa = SMB_EFA_NORMAL;
   1650 		if (!xattr && name && *name == '.')
   1651 			efa = SMB_EFA_HIDDEN;
   1652 		error = smbfs_smb_ntcreatex(dnp,
   1653 		    name, nmlen, xattr, rights, efa,
   1654 		    NTCREATEX_SHARE_ACCESS_ALL,
   1655 		    disp, /* != NTCREATEX_DISP_OPEN */
   1656 		    NTCREATEX_OPTIONS_NON_DIRECTORY_FILE,
   1657 		    scrp, fidp, NULL, NULL); /* cr_act_p fa_p */
   1658 		return (error);
   1659 	}
   1660 
   1661 	error = smbfs_smb_oldcreate(dnp, name, nmlen, xattr, scrp, fidp);
   1662 	return (error);
   1663 }
   1664 
   1665 int
   1666 smbfs_smb_delete(struct smbnode *np, struct smb_cred *scrp, const char *name,
   1667 			int nmlen, int xattr)
   1668 {
   1669 	struct smb_rq rq, *rqp = &rq;
   1670 	struct smb_share *ssp = np->n_mount->smi_share;
   1671 	struct mbchain *mbp;
   1672 	int error;
   1673 
   1674 	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_DELETE, scrp);
   1675 	if (error)
   1676 		return (error);
   1677 	smb_rq_getrequest(rqp, &mbp);
   1678 	smb_rq_wstart(rqp);
   1679 	mb_put_uint16le(mbp, SMB_FA_SYSTEM | SMB_FA_HIDDEN);
   1680 	smb_rq_wend(rqp);
   1681 	smb_rq_bstart(rqp);
   1682 	mb_put_uint8(mbp, SMB_DT_ASCII);
   1683 	error = smbfs_fullpath(mbp, SSTOVC(ssp), np, name, &nmlen,
   1684 	    xattr ? ':' : '\\');
   1685 	if (!error) {
   1686 		smb_rq_bend(rqp);
   1687 		error = smb_rq_simple(rqp);
   1688 	}
   1689 	smb_rq_done(rqp);
   1690 	return (error);
   1691 }
   1692 
   1693 int
   1694 smbfs_smb_rename(struct smbnode *src, struct smbnode *tdnp,
   1695 	const char *tname, int tnmlen, struct smb_cred *scrp)
   1696 {
   1697 	struct smb_rq rq, *rqp = &rq;
   1698 	struct smb_share *ssp = src->n_mount->smi_share;
   1699 	struct mbchain *mbp;
   1700 	int error;
   1701 	uint16_t fa;
   1702 	char sep;
   1703 
   1704 	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_RENAME, scrp);
   1705 	if (error)
   1706 		return (error);
   1707 	smb_rq_getrequest(rqp, &mbp);
   1708 	smb_rq_wstart(rqp);
   1709 	/* freebsd bug: Let directories be renamed - Win98 requires DIR bit */
   1710 	fa = (SMBTOV(src)->v_type == VDIR) ? SMB_FA_DIR : 0;
   1711 	fa |= SMB_FA_SYSTEM | SMB_FA_HIDDEN;
   1712 	mb_put_uint16le(mbp, fa);
   1713 	smb_rq_wend(rqp);
   1714 	smb_rq_bstart(rqp);
   1715 
   1716 	/*
   1717 	 * When we're not adding any component name, the
   1718 	 * passed sep is ignored, so just pass sep=0.
   1719 	 */
   1720 	mb_put_uint8(mbp, SMB_DT_ASCII);
   1721 	error = smbfs_fullpath(mbp, SSTOVC(ssp), src, NULL, NULL, 0);
   1722 	if (error)
   1723 		goto out;
   1724 
   1725 	/*
   1726 	 * After XATTR directories, separator is ":"
   1727 	 */
   1728 	sep = (src->n_flag & N_XATTR) ? ':' : '\\';
   1729 	mb_put_uint8(mbp, SMB_DT_ASCII);
   1730 	error = smbfs_fullpath(mbp, SSTOVC(ssp), tdnp, tname, &tnmlen, sep);
   1731 	if (error)
   1732 		goto out;
   1733 
   1734 	smb_rq_bend(rqp);
   1735 	error = smb_rq_simple(rqp);
   1736 out:
   1737 	smb_rq_done(rqp);
   1738 	return (error);
   1739 }
   1740 
   1741 int
   1742 smbfs_smb_move(struct smbnode *src, struct smbnode *tdnp,
   1743 	const char *tname, int tnmlen, uint16_t flags, struct smb_cred *scrp)
   1744 {
   1745 	struct smb_rq rq, *rqp = &rq;
   1746 	struct smb_share *ssp = src->n_mount->smi_share;
   1747 	struct mbchain *mbp;
   1748 	int error;
   1749 
   1750 	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_MOVE, scrp);
   1751 	if (error)
   1752 		return (error);
   1753 	smb_rq_getrequest(rqp, &mbp);
   1754 	smb_rq_wstart(rqp);
   1755 	mb_put_uint16le(mbp, SMB_TID_UNKNOWN);
   1756 	mb_put_uint16le(mbp, 0x20);	/* delete target file */
   1757 	mb_put_uint16le(mbp, flags);
   1758 	smb_rq_wend(rqp);
   1759 	smb_rq_bstart(rqp);
   1760 	mb_put_uint8(mbp, SMB_DT_ASCII);
   1761 
   1762 	error = smbfs_fullpath(mbp, SSTOVC(ssp), src, NULL, NULL, '\\');
   1763 	if (error)
   1764 		goto out;
   1765 	mb_put_uint8(mbp, SMB_DT_ASCII);
   1766 	error = smbfs_fullpath(mbp, SSTOVC(ssp), tdnp, tname, &tnmlen, '\\');
   1767 	if (error)
   1768 		goto out;
   1769 	smb_rq_bend(rqp);
   1770 	error = smb_rq_simple(rqp);
   1771 
   1772 out:
   1773 	smb_rq_done(rqp);
   1774 	return (error);
   1775 }
   1776 
   1777 static int
   1778 smbfs_smb_oldmkdir(struct smbnode *dnp, const char *name, int len,
   1779 			struct smb_cred *scrp)
   1780 {
   1781 	struct smb_rq rq, *rqp = &rq;
   1782 	struct smb_share *ssp = dnp->n_mount->smi_share;
   1783 	struct mbchain *mbp;
   1784 	int error;
   1785 
   1786 	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CREATE_DIRECTORY, scrp);
   1787 	if (error)
   1788 		return (error);
   1789 	smb_rq_getrequest(rqp, &mbp);
   1790 	smb_rq_wstart(rqp);
   1791 	smb_rq_wend(rqp);
   1792 	smb_rq_bstart(rqp);
   1793 	mb_put_uint8(mbp, SMB_DT_ASCII);
   1794 	error = smbfs_fullpath(mbp, SSTOVC(ssp), dnp, name, &len, '\\');
   1795 	if (!error) {
   1796 		smb_rq_bend(rqp);
   1797 		error = smb_rq_simple(rqp);
   1798 	}
   1799 	smb_rq_done(rqp);
   1800 	return (error);
   1801 }
   1802 
   1803 int
   1804 smbfs_smb_mkdir(struct smbnode *dnp, const char *name, int nmlen,
   1805 		struct smb_cred *scrp)
   1806 {
   1807 	struct smb_share *ssp = dnp->n_mount->smi_share;
   1808 	struct smb_vc *vcp = SSTOVC(ssp);
   1809 	uint32_t rights;
   1810 	uint16_t fid;
   1811 	int error;
   1812 
   1813 	/*
   1814 	 * We ask for SA_RIGHT_FILE_READ_DATA not because we need it, but
   1815 	 * just to be asking for something.  The rights==0 case could
   1816 	 * easily be broken on some old or unusual servers.
   1817 	 */
   1818 	if (vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) {
   1819 		rights = SA_RIGHT_FILE_READ_DATA;
   1820 		error = smbfs_smb_ntcreatex(dnp,
   1821 		    name, nmlen, 0, /* xattr */
   1822 		    rights, SMB_EFA_DIRECTORY,
   1823 		    NTCREATEX_SHARE_ACCESS_ALL,
   1824 		    NTCREATEX_DISP_CREATE,
   1825 		    NTCREATEX_OPTIONS_DIRECTORY,
   1826 		    scrp, &fid, NULL, NULL); /* cr_act_p fa_p */
   1827 		if (error)
   1828 			return (error);
   1829 		(void) smbfs_smb_close(ssp, fid, NULL, scrp);
   1830 		return (0);
   1831 	}
   1832 
   1833 	error = smbfs_smb_oldmkdir(dnp, name, nmlen, scrp);
   1834 	return (error);
   1835 }
   1836 
   1837 int
   1838 smbfs_smb_rmdir(struct smbnode *np, struct smb_cred *scrp)
   1839 {
   1840 	struct smb_rq rq, *rqp = &rq;
   1841 	struct smb_share *ssp = np->n_mount->smi_share;
   1842 	struct mbchain *mbp;
   1843 	int error;
   1844 
   1845 	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_DELETE_DIRECTORY, scrp);
   1846 	if (error)
   1847 		return (error);
   1848 	smb_rq_getrequest(rqp, &mbp);
   1849 	smb_rq_wstart(rqp);
   1850 	smb_rq_wend(rqp);
   1851 	smb_rq_bstart(rqp);
   1852 	mb_put_uint8(mbp, SMB_DT_ASCII);
   1853 	error = smbfs_fullpath(mbp, SSTOVC(ssp), np, NULL, NULL, '\\');
   1854 	if (!error) {
   1855 		smb_rq_bend(rqp);
   1856 		error = smb_rq_simple(rqp);
   1857 	}
   1858 	smb_rq_done(rqp);
   1859 	return (error);
   1860 }
   1861 
   1862 static int
   1863 smbfs_smb_search(struct smbfs_fctx *ctx)
   1864 {
   1865 	struct smb_vc *vcp = SSTOVC(ctx->f_ssp);
   1866 	struct smb_rq *rqp;
   1867 	struct mbchain *mbp;
   1868 	struct mdchain *mdp;
   1869 	uint8_t wc, bt;
   1870 	uint16_t ec, dlen, bc;
   1871 	int len, maxent, error, iseof = 0;
   1872 
   1873 	maxent = min(ctx->f_left,
   1874 	    (vcp->vc_txmax - SMB_HDRLEN - 2*2) / SMB_DENTRYLEN);
   1875 	if (ctx->f_rq) {
   1876 		smb_rq_done(ctx->f_rq);
   1877 		ctx->f_rq = NULL;
   1878 	}
   1879 	error = smb_rq_alloc(SSTOCP(ctx->f_ssp), SMB_COM_SEARCH,
   1880 	    ctx->f_scred, &rqp);
   1881 	if (error)
   1882 		return (error);
   1883 	ctx->f_rq = rqp;
   1884 	smb_rq_getrequest(rqp, &mbp);
   1885 	smb_rq_wstart(rqp);
   1886 	mb_put_uint16le(mbp, maxent);	/* max entries to return */
   1887 	mb_put_uint16le(mbp, ctx->f_attrmask);
   1888 	smb_rq_wend(rqp);
   1889 	smb_rq_bstart(rqp);
   1890 	mb_put_uint8(mbp, SMB_DT_ASCII);	/* buffer format */
   1891 	if (ctx->f_flags & SMBFS_RDD_FINDFIRST) {
   1892 		len = ctx->f_wclen;
   1893 		error = smbfs_fullpath(mbp, vcp, ctx->f_dnp, ctx->f_wildcard,
   1894 		    &len, '\\');
   1895 		if (error)
   1896 			return (error);
   1897 		mb_put_uint8(mbp, SMB_DT_VARIABLE);
   1898 		mb_put_uint16le(mbp, 0);	/* context length */
   1899 		ctx->f_flags &= ~SMBFS_RDD_FINDFIRST;
   1900 	} else {
   1901 		if (SMB_UNICODE_STRINGS(vcp)) {
   1902 			mb_put_padbyte(mbp);
   1903 			mb_put_uint8(mbp, 0);
   1904 		}
   1905 		mb_put_uint8(mbp, 0);
   1906 		mb_put_uint8(mbp, SMB_DT_VARIABLE);
   1907 		mb_put_uint16le(mbp, SMB_SKEYLEN);
   1908 		mb_put_mem(mbp, (char *)ctx->f_skey, SMB_SKEYLEN, MB_MSYSTEM);
   1909 	}
   1910 	smb_rq_bend(rqp);
   1911 	error = smb_rq_simple(rqp);
   1912 	if (rqp->sr_errclass == ERRDOS && rqp->sr_serror == ERRnofiles) {
   1913 		error = 0;
   1914 		iseof = 1;
   1915 		ctx->f_flags |= SMBFS_RDD_EOF;
   1916 	} else if (error)
   1917 		return (error);
   1918 	smb_rq_getreply(rqp, &mdp);
   1919 	error = md_get_uint8(mdp, &wc);
   1920 	if (error)
   1921 		return (error);
   1922 	if (wc != 1)
   1923 		return (iseof ? ENOENT : EBADRPC);
   1924 	md_get_uint16le(mdp, &ec);
   1925 	md_get_uint16le(mdp, &bc);
   1926 	md_get_uint8(mdp, &bt);
   1927 	error = md_get_uint16le(mdp, &dlen);
   1928 	if (error)
   1929 		return (error);
   1930 	if (ec == 0)
   1931 		return (ENOENT);
   1932 	ctx->f_ecnt = ec;
   1933 	if (bc < 3)
   1934 		return (EBADRPC);
   1935 	bc -= 3;
   1936 	if (bt != SMB_DT_VARIABLE)
   1937 		return (EBADRPC);
   1938 	if (dlen != bc || dlen % SMB_DENTRYLEN != 0)
   1939 		return (EBADRPC);
   1940 	return (0);
   1941 }
   1942 
   1943 
   1944 /*ARGSUSED*/
   1945 static int
   1946 smbfs_smb_findopenLM1(struct smbfs_fctx *ctx, struct smbnode *dnp,
   1947     const char *wildcard, int wclen, uint16_t attr)
   1948 {
   1949 
   1950 	ctx->f_type = ft_LM1;
   1951 	ctx->f_attrmask = attr;
   1952 	if (wildcard) {
   1953 		if (wclen == 1 && wildcard[0] == '*') {
   1954 			ctx->f_wildcard = "*.*";
   1955 			ctx->f_wclen = 3;
   1956 		} else {
   1957 			ctx->f_wildcard = wildcard;
   1958 			ctx->f_wclen = wclen;
   1959 		}
   1960 	} else {
   1961 		ctx->f_wildcard = NULL;
   1962 		ctx->f_wclen = 0;
   1963 	}
   1964 	ctx->f_name = (char *)ctx->f_fname;
   1965 	ctx->f_namesz = 0;
   1966 	return (0);
   1967 }
   1968 
   1969 static int
   1970 smbfs_smb_findnextLM1(struct smbfs_fctx *ctx, uint16_t limit)
   1971 {
   1972 	struct mdchain *mdp;
   1973 	struct smb_rq *rqp;
   1974 	char *cp;
   1975 	uint8_t battr;
   1976 	uint16_t date, time;
   1977 	uint32_t size;
   1978 	int error;
   1979 	struct timespec ts;
   1980 
   1981 	if (ctx->f_ecnt == 0) {
   1982 		if (ctx->f_flags & SMBFS_RDD_EOF)
   1983 			return (ENOENT);
   1984 		ctx->f_left = ctx->f_limit = limit;
   1985 		gethrestime(&ts);
   1986 		error = smbfs_smb_search(ctx);
   1987 		if (error)
   1988 			return (error);
   1989 	}
   1990 	rqp = ctx->f_rq;
   1991 	smb_rq_getreply(rqp, &mdp);
   1992 	md_get_mem(mdp, (char *)ctx->f_skey, SMB_SKEYLEN, MB_MSYSTEM);
   1993 	md_get_uint8(mdp, &battr);
   1994 	md_get_uint16le(mdp, &time);
   1995 	md_get_uint16le(mdp, &date);
   1996 	md_get_uint32le(mdp, &size);
   1997 	cp = ctx->f_name;
   1998 	error = md_get_mem(mdp, cp, sizeof (ctx->f_fname), MB_MSYSTEM);
   1999 	cp[sizeof (ctx->f_fname) - 1] = 0;
   2000 	cp += strlen(cp) - 1;
   2001 	while (*cp == ' ' && cp >= ctx->f_name)
   2002 		*cp-- = 0;
   2003 	ctx->f_attr.fa_attr = battr;
   2004 	smb_dos2unixtime(date, time, 0, rqp->sr_vc->vc_sopt.sv_tz,
   2005 	    &ctx->f_attr.fa_mtime);
   2006 	ctx->f_attr.fa_size = size;
   2007 	ctx->f_nmlen = strlen(ctx->f_name);
   2008 	ctx->f_ecnt--;
   2009 	ctx->f_left--;
   2010 	return (0);
   2011 }
   2012 
   2013 static int
   2014 smbfs_smb_findcloseLM1(struct smbfs_fctx *ctx)
   2015 {
   2016 	if (ctx->f_rq)
   2017 		smb_rq_done(ctx->f_rq);
   2018 	return (0);
   2019 }
   2020 
   2021 /*
   2022  * TRANS2_FIND_FIRST2/NEXT2, used for NT LM12 dialect
   2023  */
   2024 static int
   2025 smbfs_smb_trans2find2(struct smbfs_fctx *ctx)
   2026 {
   2027 	struct smb_t2rq *t2p;
   2028 	struct smb_vc *vcp = SSTOVC(ctx->f_ssp);
   2029 	struct mbchain *mbp;
   2030 	struct mdchain *mdp;
   2031 	uint16_t ecnt, eos, lno, flags;
   2032 	int len, error;
   2033 
   2034 	if (ctx->f_t2) {
   2035 		smb_t2_done(ctx->f_t2);
   2036 		ctx->f_t2 = NULL;
   2037 	}
   2038 	flags = FIND2_RETURN_RESUME_KEYS | FIND2_CLOSE_ON_EOS;
   2039 	if (ctx->f_flags & SMBFS_RDD_FINDSINGLE) {
   2040 		flags |= FIND2_CLOSE_AFTER_REQUEST;
   2041 		ctx->f_flags |= SMBFS_RDD_NOCLOSE;
   2042 	}
   2043 	if (ctx->f_flags & SMBFS_RDD_FINDFIRST) {
   2044 		error = smb_t2_alloc(SSTOCP(ctx->f_ssp), SMB_TRANS2_FIND_FIRST2,
   2045 		    ctx->f_scred, &t2p);
   2046 		if (error)
   2047 			return (error);
   2048 		ctx->f_t2 = t2p;
   2049 		mbp = &t2p->t2_tparam;
   2050 		mb_init(mbp);
   2051 		mb_put_uint16le(mbp, ctx->f_attrmask);
   2052 		mb_put_uint16le(mbp, ctx->f_limit);
   2053 		mb_put_uint16le(mbp, flags);
   2054 		mb_put_uint16le(mbp, ctx->f_infolevel);
   2055 		mb_put_uint32le(mbp, 0);
   2056 		len = ctx->f_wclen;
   2057 		error = smbfs_fullpath(mbp, vcp, ctx->f_dnp, ctx->f_wildcard,
   2058 		    &len, '\\');
   2059 		if (error)
   2060 			return (error);
   2061 	} else	{
   2062 		error = smb_t2_alloc(SSTOCP(ctx->f_ssp), SMB_TRANS2_FIND_NEXT2,
   2063 		    ctx->f_scred, &t2p);
   2064 		if (error)
   2065 			return (error);
   2066 		ctx->f_t2 = t2p;
   2067 		mbp = &t2p->t2_tparam;
   2068 		mb_init(mbp);
   2069 		mb_put_uint16le(mbp, ctx->f_Sid);
   2070 		mb_put_uint16le(mbp, ctx->f_limit);
   2071 		mb_put_uint16le(mbp, ctx->f_infolevel);
   2072 		/* Send whatever resume key we received... */
   2073 		mb_put_uint32le(mbp, ctx->f_rkey);
   2074 		mb_put_uint16le(mbp, flags);
   2075 		/* ... and the resume name if we have one. */
   2076 		if (ctx->f_rname) {
   2077 			/* resume file name */
   2078 			mb_put_mem(mbp, ctx->f_rname, ctx->f_rnamelen,
   2079 			    MB_MSYSTEM);
   2080 		}
   2081 		/* Add trailing null - 1 byte if ASCII, 2 if Unicode */
   2082 		if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp)))
   2083 			mb_put_uint8(mbp, 0);	/* 1st byte NULL Unicode char */
   2084 		mb_put_uint8(mbp, 0);
   2085 	}
   2086 	t2p->t2_maxpcount = 5 * 2;
   2087 	t2p->t2_maxdcount = 0xF000;	/* 64K less some overhead */
   2088 	error = smb_t2_request(t2p);
   2089 	if (error)
   2090 		return (error);
   2091 
   2092 	/*
   2093 	 * This is the "resume name" we just sent.
   2094 	 * We want the new one (if any) that may be
   2095 	 * found in the response we just received and
   2096 	 * will now begin parsing.  Free the old one
   2097 	 * now so we'll know if we found a new one.
   2098 	 */
   2099 	if (ctx->f_rname) {
   2100 		kmem_free(ctx->f_rname, ctx->f_rnamelen);
   2101 		ctx->f_rname = NULL;
   2102 		ctx->f_rnamelen = 0;
   2103 	}
   2104 
   2105 	mdp = &t2p->t2_rparam;
   2106 	if (ctx->f_flags & SMBFS_RDD_FINDFIRST) {
   2107 		if ((error = md_get_uint16le(mdp, &ctx->f_Sid)) != 0)
   2108 			goto nodata;
   2109 		ctx->f_flags &= ~SMBFS_RDD_FINDFIRST;
   2110 	}
   2111 	md_get_uint16le(mdp, &ecnt);		/* entry count */
   2112 	md_get_uint16le(mdp, &eos);		/* end of search */
   2113 	md_get_uint16le(mdp, NULL);		/* EA err. off. */
   2114 	error = md_get_uint16le(mdp, &lno);	/* last name off. */
   2115 	if (error != 0)
   2116 		goto nodata;
   2117 
   2118 	/*
   2119 	 * The "end of search" flag from an XP server sometimes
   2120 	 * comes back zero when the prior find_next returned exactly
   2121 	 * the number of entries requested.  in which case we'd try again
   2122 	 * but the search has in fact been closed so an EBADF results.
   2123 	 * our circumvention is to check here for a zero entry count.
   2124 	 */
   2125 	ctx->f_ecnt = ecnt;
   2126 	if (eos || ctx->f_ecnt == 0)
   2127 		ctx->f_flags |= SMBFS_RDD_EOF | SMBFS_RDD_NOCLOSE;
   2128 	if (ctx->f_ecnt == 0)
   2129 		return (ENOENT);
   2130 
   2131 	/* Last Name Off (LNO) is the entry with the resume name. */
   2132 	ctx->f_rnameofs = lno;
   2133 	ctx->f_eofs = 0;
   2134 	return (0);
   2135 
   2136 nodata:
   2137 	/*
   2138 	 * Failed parsing the FindFirst or FindNext response.
   2139 	 * Force this directory listing closed, otherwise the
   2140 	 * calling process may hang in an infinite loop.
   2141 	 */
   2142 	ctx->f_ecnt = 0; /* Force closed. */
   2143 	ctx->f_flags |= SMBFS_RDD_EOF;
   2144 	return (EIO);
   2145 }
   2146 
   2147 static int
   2148 smbfs_smb_findclose2(struct smbfs_fctx *ctx)
   2149 {
   2150 	struct smb_rq rq, *rqp = &rq;
   2151 	struct mbchain *mbp;
   2152 	int error;
   2153 
   2154 	error = smb_rq_init(rqp, SSTOCP(ctx->f_ssp), SMB_COM_FIND_CLOSE2,
   2155 	    ctx->f_scred);
   2156 	if (error)
   2157 		return (error);
   2158 	smb_rq_getrequest(rqp, &mbp);
   2159 	smb_rq_wstart(rqp);
   2160 	mb_put_uint16le(mbp, ctx->f_Sid);
   2161 	smb_rq_wend(rqp);
   2162 	smb_rq_bstart(rqp);
   2163 	smb_rq_bend(rqp);
   2164 	/* Ditto comments at _smb_close */
   2165 	rqp->sr_flags |= SMBR_NOINTR_SEND;
   2166 	error = smb_rq_simple(rqp);
   2167 	smb_rq_done(rqp);
   2168 	return (error);
   2169 }
   2170 
   2171 /*ARGSUSED*/
   2172 static int
   2173 smbfs_smb_findopenLM2(struct smbfs_fctx *ctx, struct smbnode *dnp,
   2174     const char *wildcard, int wclen, uint16_t attr)
   2175 {
   2176 
   2177 	ctx->f_type = ft_LM2;
   2178 	ctx->f_namesz = SMB_MAXFNAMELEN + 1;
   2179 	if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp)))
   2180 		ctx->f_namesz *= 2;
   2181 	ctx->f_name = kmem_alloc(ctx->f_namesz, KM_SLEEP);
   2182 	ctx->f_infolevel = SMB_DIALECT(SSTOVC(ctx->f_ssp))
   2183 	    < SMB_DIALECT_NTLM0_12 ? SMB_FIND_STANDARD :
   2184 	    SMB_FIND_BOTH_DIRECTORY_INFO;
   2185 	ctx->f_attrmask = attr;
   2186 	ctx->f_wildcard = wildcard;
   2187 	ctx->f_wclen = wclen;
   2188 	return (0);
   2189 }
   2190 
   2191 static int
   2192 smbfs_smb_findnextLM2(struct smbfs_fctx *ctx, uint16_t limit)
   2193 {
   2194 	struct mdchain *mdp;
   2195 	struct smb_t2rq *t2p;
   2196 	char *cp;
   2197 	uint8_t tb;
   2198 	uint16_t date, time, wattr;
   2199 	uint32_t size, next, dattr, resumekey = 0;
   2200 	uint64_t llongint;
   2201 	int error, svtz, cnt, fxsz, nmlen, recsz;
   2202 	struct timespec ts;
   2203 
   2204 	if (ctx->f_ecnt == 0) {
   2205 		if (ctx->f_flags & SMBFS_RDD_EOF)
   2206 			return (ENOENT);
   2207 		ctx->f_left = ctx->f_limit = limit;
   2208 		gethrestime(&ts);
   2209 		error = smbfs_smb_trans2find2(ctx);
   2210 		if (error)
   2211 			return (error);
   2212 		ctx->f_otws++;
   2213 	}
   2214 	t2p = ctx->f_t2;
   2215 	mdp = &t2p->t2_rdata;
   2216 	svtz = SSTOVC(ctx->f_ssp)->vc_sopt.sv_tz;
   2217 	switch (ctx->f_infolevel) {
   2218 	case SMB_FIND_STANDARD:
   2219 		next = 0;
   2220 		fxsz = 0;
   2221 		md_get_uint16le(mdp, &date);
   2222 		md_get_uint16le(mdp, &time);	/* creation time */
   2223 		smb_dos2unixtime(date, time, 0, svtz,
   2224 		    &ctx->f_attr.fa_createtime);
   2225 		md_get_uint16le(mdp, &date);
   2226 		md_get_uint16le(mdp, &time);	/* access time */
   2227 		smb_dos2unixtime(date, time, 0, svtz, &ctx->f_attr.fa_atime);
   2228 		md_get_uint16le(mdp, &date);
   2229 		md_get_uint16le(mdp, &time);	/* modify time */
   2230 		smb_dos2unixtime(date, time, 0, svtz, &ctx->f_attr.fa_mtime);
   2231 		md_get_uint32le(mdp, &size);
   2232 		ctx->f_attr.fa_size = size;
   2233 		md_get_uint32le(mdp, &size);	/* allocation size */
   2234 		ctx->f_attr.fa_allocsz = size;
   2235 		md_get_uint16le(mdp, &wattr);
   2236 		ctx->f_attr.fa_attr = wattr;
   2237 		error = md_get_uint8(mdp, &tb);
   2238 		if (error)
   2239 			goto nodata;
   2240 		size = nmlen = tb;
   2241 		fxsz = 23;
   2242 		recsz = next = 24 + nmlen;	/* docs misses zero byte @end */
   2243 		break;
   2244 	case SMB_FIND_DIRECTORY_INFO:
   2245 	case SMB_FIND_BOTH_DIRECTORY_INFO:
   2246 		md_get_uint32le(mdp, &next);
   2247 		md_get_uint32le(mdp, &resumekey); /* file index (resume key) */
   2248 		md_get_uint64le(mdp, &llongint);	/* creation time */
   2249 		smb_time_NT2local(llongint, &ctx->f_attr.fa_createtime);
   2250 		md_get_uint64le(mdp, &llongint);
   2251 		smb_time_NT2local(llongint, &ctx->f_attr.fa_atime);
   2252 		md_get_uint64le(mdp, &llongint);
   2253 		smb_time_NT2local(llongint, &ctx->f_attr.fa_mtime);
   2254 		md_get_uint64le(mdp, &llongint);
   2255 		smb_time_NT2local(llongint, &ctx->f_attr.fa_ctime);
   2256 		md_get_uint64le(mdp, &llongint);	/* file size */
   2257 		ctx->f_attr.fa_size = llongint;
   2258 		md_get_uint64le(mdp, &llongint);	/* alloc. size */
   2259 		ctx->f_attr.fa_allocsz = llongint;
   2260 		md_get_uint32le(mdp, &dattr);	/* ext. file attributes */
   2261 		ctx->f_attr.fa_attr = dattr;
   2262 		error = md_get_uint32le(mdp, &size);	/* name len */
   2263 		if (error)
   2264 			goto nodata;
   2265 		fxsz = 64; /* size ofinfo up to filename */
   2266 		if (ctx->f_infolevel == SMB_FIND_BOTH_DIRECTORY_INFO) {
   2267 			/*
   2268 			 * Skip EaSize(4 bytes), a byte of ShortNameLength,
   2269 			 * a reserved byte, and ShortName(8.3 means 24 bytes,
   2270 			 * as Leach defined it to always be Unicode)
   2271 			 */
   2272 			error = md_get_mem(mdp, NULL, 30, MB_MSYSTEM);
   2273 			if (error)
   2274 				goto nodata;
   2275 			fxsz += 30;
   2276 		}
   2277 		recsz = next ? next : fxsz + size;
   2278 		break;
   2279 	default:
   2280 		SMBVDEBUG("unexpected info level %d\n", ctx->f_infolevel);
   2281 		return (EINVAL);
   2282 	}
   2283 
   2284 	if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp)))
   2285 		nmlen = min(size, SMB_MAXFNAMELEN * 2);
   2286 	else
   2287 		nmlen = min(size, SMB_MAXFNAMELEN);
   2288 
   2289 	/* Allocated f_name in findopen */
   2290 	ASSERT(nmlen < ctx->f_namesz);
   2291 	cp = ctx->f_name;
   2292 
   2293 	error = md_get_mem(mdp, cp, nmlen, MB_MSYSTEM);
   2294 	if (error)
   2295 		goto nodata;
   2296 	if (next) {
   2297 		/* How much data to skip? */
   2298 		cnt = next - nmlen - fxsz;
   2299 		if (cnt < 0) {
   2300 			SMBVDEBUG("out of sync\n");
   2301 			goto nodata;
   2302 		}
   2303 		if (cnt > 0)
   2304 			md_get_mem(mdp, NULL, cnt, MB_MSYSTEM);
   2305 	}
   2306 	/* Don't count any trailing null in the name. */
   2307 	if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp))) {
   2308 		if (nmlen > 1 && cp[nmlen - 1] == 0 && cp[nmlen - 2] == 0)
   2309 			nmlen -= 2;
   2310 	} else {
   2311 		if (nmlen && cp[nmlen - 1] == 0)
   2312 			nmlen--;
   2313 	}
   2314 	if (nmlen == 0)
   2315 		goto nodata;
   2316 
   2317 	/*
   2318 	 * On a find-next we expect that the server will:
   2319 	 * 1) if the continue bit is set, use the server's offset,
   2320 	 * 2) else if the resume key is non-zero, use that offset,
   2321 	 * 3) else if the resume name is set, use that offset,
   2322 	 * 4) else use the server's idea of current offset.
   2323 	 *
   2324 	 * We always set the resume key flag. If the server returns
   2325 	 * a resume key then we should always send it back to them.
   2326 	 */
   2327 	ctx->f_rkey = resumekey;
   2328 
   2329 	next = ctx->f_eofs + recsz;
   2330 	if (ctx->f_rnameofs &&
   2331 	    ctx->f_rnameofs >= ctx->f_eofs &&
   2332 	    ctx->f_rnameofs < (int)next) {
   2333 		/*
   2334 		 * This entry is the "resume name".
   2335 		 * Save it for the next request.
   2336 		 */
   2337 		if (ctx->f_rnamelen != nmlen) {
   2338 			if (ctx->f_rname)
   2339 				kmem_free(ctx->f_rname, ctx->f_rnamelen);
   2340 			ctx->f_rname = kmem_alloc(nmlen, KM_SLEEP);
   2341 			ctx->f_rnamelen = nmlen;
   2342 		}
   2343 		bcopy(ctx->f_name, ctx->f_rname, nmlen);
   2344 	}
   2345 	ctx->f_nmlen = nmlen;
   2346 	ctx->f_eofs = next;
   2347 	ctx->f_ecnt--;
   2348 	ctx->f_left--;
   2349 
   2350 	smbfs_fname_tolocal(ctx);
   2351 	return (0);
   2352 
   2353 nodata:
   2354 	/*
   2355 	 * Something bad has happened and we ran out of data
   2356 	 * before we could parse all f_ecnt entries expected.
   2357 	 * Force this directory listing closed, otherwise the
   2358 	 * calling process may hang in an infinite loop.
   2359 	 */
   2360 	SMBVDEBUG("ran out of data\n");
   2361 	ctx->f_ecnt = 0; /* Force closed. */
   2362 	ctx->f_flags |= SMBFS_RDD_EOF;
   2363 	return (EIO);
   2364 }
   2365 
   2366 static int
   2367 smbfs_smb_findcloseLM2(struct smbfs_fctx *ctx)
   2368 {
   2369 	int error = 0;
   2370 	if (ctx->f_name)
   2371 		kmem_free(ctx->f_name, ctx->f_namesz);
   2372 	if (ctx->f_t2)
   2373 		smb_t2_done(ctx->f_t2);
   2374 	/*
   2375 	 * If SMBFS_RDD_FINDFIRST is still set, we were opened
   2376 	 * but never saw a findfirst, so we don't have any
   2377 	 * search handle to close.
   2378 	 */
   2379 	if ((ctx->f_flags & (SMBFS_RDD_FINDFIRST | SMBFS_RDD_NOCLOSE)) == 0)
   2380 		error = smbfs_smb_findclose2(ctx);
   2381 	return (error);
   2382 }
   2383 
   2384 int
   2385 smbfs_smb_findopen(struct smbnode *dnp, const char *wild, int wlen,
   2386 			int attr, struct smb_cred *scrp,
   2387 			struct smbfs_fctx **ctxpp)
   2388 {
   2389 	struct smbfs_fctx *ctx;
   2390 	int error;
   2391 
   2392 	ctx = kmem_zalloc(sizeof (*ctx), KM_SLEEP);
   2393 
   2394 	ctx->f_flags = SMBFS_RDD_FINDFIRST;
   2395 	ctx->f_dnp = dnp;
   2396 	ctx->f_scred = scrp;
   2397 	ctx->f_ssp = dnp->n_mount->smi_share;
   2398 
   2399 	if (dnp->n_flag & N_XATTR) {
   2400 		error = smbfs_xa_findopen(ctx, dnp, wild, wlen);
   2401 		goto out;
   2402 	}
   2403 
   2404 	if (SMB_DIALECT(SSTOVC(ctx->f_ssp)) < SMB_DIALECT_LANMAN2_0) {
   2405 		error = smbfs_smb_findopenLM1(ctx, dnp, wild, wlen, attr);
   2406 	} else {
   2407 		error = smbfs_smb_findopenLM2(ctx, dnp, wild, wlen, attr);
   2408 	}
   2409 
   2410 out:
   2411 	if (error)
   2412 		(void) smbfs_smb_findclose(ctx, scrp);
   2413 	else
   2414 		*ctxpp = ctx;
   2415 	return (error);
   2416 }
   2417 
   2418 int
   2419 smbfs_smb_findnext(struct smbfs_fctx *ctx, int limit, struct smb_cred *scrp)
   2420 {
   2421 	int error;
   2422 
   2423 	/*
   2424 	 * Note: "limit" (maxcount) needs to fit in a short!
   2425 	 */
   2426 	if (limit > 0xffff)
   2427 		limit = 0xffff;
   2428 
   2429 	ctx->f_scred = scrp;
   2430 	for (;;) {
   2431 		bzero(&ctx->f_attr, sizeof (ctx->f_attr));
   2432 		switch (ctx->f_type) {
   2433 		case ft_LM1:
   2434 			error = smbfs_smb_findnextLM1(ctx, (uint16_t)limit);
   2435 			break;
   2436 		case ft_LM2:
   2437 			error = smbfs_smb_findnextLM2(ctx, (uint16_t)limit);
   2438 			break;
   2439 		case ft_XA:
   2440 			error = smbfs_xa_findnext(ctx, (uint16_t)limit);
   2441 			break;
   2442 		default:
   2443 			ASSERT(0);
   2444 			error = EINVAL;
   2445 			break;
   2446 		}
   2447 		if (error)
   2448 			return (error);
   2449 		/*
   2450 		 * Skip "." or ".." - easy now that ctx->f_name
   2451 		 * has already been converted to utf-8 format.
   2452 		 */
   2453 		if ((ctx->f_nmlen == 1 && ctx->f_name[0] == '.') ||
   2454 		    (ctx->f_nmlen == 2 && ctx->f_name[0] == '.' &&
   2455 		    ctx->f_name[1] == '.'))
   2456 			continue;
   2457 		break;
   2458 	}
   2459 
   2460 	/*
   2461 	 * Moved the smbfs_fname_tolocal(ctx) call into
   2462 	 * the ..._findnext functions above.
   2463 	 */
   2464 
   2465 	ctx->f_inum = smbfs_getino(ctx->f_dnp, ctx->f_name, ctx->f_nmlen);
   2466 	return (0);
   2467 }
   2468 
   2469 
   2470 int
   2471 smbfs_smb_findclose(struct smbfs_fctx *ctx, struct smb_cred *scrp)
   2472 {
   2473 	int error;
   2474 
   2475 	ctx->f_scred = scrp;
   2476 	switch (ctx->f_type) {
   2477 	case ft_LM1:
   2478 		error = smbfs_smb_findcloseLM1(ctx);
   2479 		break;
   2480 	case ft_LM2:
   2481 		error = smbfs_smb_findcloseLM2(ctx);
   2482 		break;
   2483 	case ft_XA:
   2484 		error = smbfs_xa_findclose(ctx);
   2485 		break;
   2486 	}
   2487 	if (ctx->f_rname)
   2488 		kmem_free(ctx->f_rname, ctx->f_rnamelen);
   2489 	if (ctx->f_firstnm)
   2490 		kmem_free(ctx->f_firstnm, ctx->f_firstnmlen);
   2491 	kmem_free(ctx, sizeof (*ctx));
   2492 	return (error);
   2493 }
   2494 
   2495 
   2496 int
   2497 smbfs_smb_lookup(struct smbnode *dnp, const char **namep, int *nmlenp,
   2498 	struct smbfattr *fap, struct smb_cred *scrp)
   2499 {
   2500 	struct smbfs_fctx *ctx;
   2501 	int error, intr;
   2502 	const char *name = (namep ? *namep : NULL);
   2503 	int nmlen = (nmlenp ? *nmlenp : 0);
   2504 
   2505 	/* This is no longer called with a null dnp */
   2506 	ASSERT(dnp);
   2507 
   2508 	/*
   2509 	 * Should not get here with "" anymore.
   2510 	 */
   2511 	if (!name || !nmlen) {
   2512 		DEBUG_ENTER("smbfs_smb_lookup: name is NULL");
   2513 		return (EINVAL);
   2514 	}
   2515 
   2516 	/*
   2517 	 * Should not get here with "." or ".." anymore.
   2518 	 */
   2519 	if ((nmlen == 1 && name[0] == '.') ||
   2520 	    (nmlen == 2 && name[0] == '.' && name[1] == '.')) {
   2521 		DEBUG_ENTER("smbfs_smb_lookup: name is '.' or '..'");
   2522 		return (EINVAL);
   2523 	}
   2524 
   2525 	/*
   2526 	 * XXX: Should use _qpathinfo here instead.
   2527 	 * (if SMB_CAP_NT_SMBS)
   2528 	 */
   2529 
   2530 	/*
   2531 	 * Shared lock for n_fid use (smb_flush).
   2532 	 */
   2533 	intr = dnp->n_mount->smi_flags & SMI_INT;
   2534 	if (smbfs_rw_enter_sig(&dnp->r_lkserlock, RW_READER, intr))
   2535 		return (EINTR);
   2536 
   2537 	/*
   2538 	 * This hides a server bug observable in Win98:
   2539 	 * size changes may not show until a CLOSE or a FLUSH op
   2540 	 * XXX: Make this conditional on !NTSMBs
   2541 	 */
   2542 	error = smbfs_smb_flush(dnp, scrp);
   2543 	if (error)
   2544 		goto out;
   2545 	error = smbfs_smb_findopen(dnp, name, nmlen,
   2546 	    SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_DIR, scrp, &ctx);
   2547 	if (error)
   2548 		goto out;
   2549 	ctx->f_flags |= SMBFS_RDD_FINDSINGLE;
   2550 	error = smbfs_smb_findnext(ctx, 1, scrp);
   2551 	if (error == 0) {
   2552 		*fap = ctx->f_attr;
   2553 		/*
   2554 		 * Solaris smbfattr doesn't have fa_ino,
   2555 		 * and we don't allow name==NULL in this
   2556 		 * function anymore.
   2557 		 */
   2558 		if (namep)
   2559 			*namep = (const char *)smbfs_name_alloc(
   2560 			    ctx->f_name, ctx->f_nmlen);
   2561 		if (nmlenp)
   2562 			*nmlenp = ctx->f_nmlen;
   2563 	}
   2564 	(void) smbfs_smb_findclose(ctx, scrp);
   2565 
   2566 out:
   2567 	smbfs_rw_exit(&dnp->r_lkserlock);
   2568 	return (error);
   2569 }
   2570 
   2571 /*
   2572  * OTW function to Get a security descriptor (SD).
   2573  *
   2574  * Note: On success, this fills in mdp->md_top,
   2575  * which the caller should free.
   2576  */
   2577 int
   2578 smbfs_smb_getsec_m(struct smb_share *ssp, uint16_t fid,
   2579 		struct smb_cred *scrp, uint32_t selector,
   2580 		mblk_t **res, uint32_t *reslen)
   2581 {
   2582 	struct smb_ntrq *ntp;
   2583 	struct mbchain *mbp;
   2584 	struct mdchain *mdp;
   2585 	int error, len;
   2586 
   2587 	error = smb_nt_alloc(SSTOCP(ssp), NT_TRANSACT_QUERY_SECURITY_DESC,
   2588 	    scrp, &ntp);
   2589 	if (error)
   2590 		return (error);
   2591 
   2592 	/* Parameters part */
   2593 	mbp = &ntp->nt_tparam;
   2594 	mb_init(mbp);
   2595 	mb_put_uint16le(mbp, fid);
   2596 	mb_put_uint16le(mbp, 0); /* reserved */
   2597 	mb_put_uint32le(mbp, selector);
   2598 	/* Data part (none) */
   2599 
   2600 	/* Max. returned parameters and data. */
   2601 	ntp->nt_maxpcount = 4;
   2602 	ntp->nt_maxdcount = *reslen;
   2603 
   2604 	error = smb_nt_request(ntp);
   2605 	if (error && !(ntp->nt_flags & SMBT2_MOREDATA))
   2606 		goto done;
   2607 	*res = NULL;
   2608 
   2609 	/*
   2610 	 * if there's more data than we said we could receive, here
   2611 	 * is where we pick up the length of it
   2612 	 */
   2613 	mdp = &ntp->nt_rparam;
   2614 	md_get_uint32le(mdp, reslen);
   2615 	if (error)
   2616 		goto done;
   2617 
   2618 	/*
   2619 	 * get the data part.
   2620 	 */
   2621 	mdp = &ntp->nt_rdata;
   2622 	if (mdp->md_top == NULL) {
   2623 		SMBVDEBUG("null md_top? fid 0x%x\n", fid);
   2624 		error = EBADRPC;
   2625 		goto done;
   2626 	}
   2627 
   2628 	/*
   2629 	 * The returned parameter SD_length should match
   2630 	 * the length of the returned data.  Unfortunately,
   2631 	 * we have to work around server bugs here.
   2632 	 */
   2633 	len = m_fixhdr(mdp->md_top);
   2634 	if (len != *reslen) {
   2635 		SMBVDEBUG("len %d *reslen %d fid 0x%x\n",
   2636 		    len, *reslen, fid);
   2637 	}
   2638 
   2639 	/*
   2640 	 * Actual data provided is < returned SD_length.
   2641 	 *
   2642 	 * The following "if (len < *reslen)" handles a Windows bug
   2643 	 * observed when the underlying filesystem is FAT32.  In that
   2644 	 * case a 32 byte security descriptor comes back (S-1-1-0, ie
   2645 	 * "Everyone") but the Parameter Block claims 44 is the length
   2646 	 * of the security descriptor.  (The Data Block length
   2647 	 * claimed is 32.  This server bug was reported against NT
   2648 	 * first and I've personally observed it with W2K.
   2649 	 */
   2650 	if (len < *reslen)
   2651 		*reslen = len;
   2652 
   2653 	/*
   2654 	 * Actual data provided is > returned SD_length.
   2655 	 * (Seen on StorageTek NAS 5320, s/w ver. 4.21 M0)
   2656 	 * Narrow work-around for returned SD_length==0.
   2657 	 */
   2658 	if (len > *reslen) {
   2659 		/*
   2660 		 * Increase *reslen, but carefully.
   2661 		 */
   2662 		if (*reslen == 0 && len <= ntp->nt_maxdcount)
   2663 			*reslen = len;
   2664 	}
   2665 	error = md_get_mbuf(mdp, len, res);
   2666 
   2667 done:
   2668 	if (error == 0 && *res == NULL) {
   2669 		ASSERT(*res);
   2670 		error = EBADRPC;
   2671 	}
   2672 
   2673 	smb_nt_done(ntp);
   2674 	return (error);
   2675 }
   2676 
   2677 #ifdef	APPLE
   2678 /*
   2679  * Wrapper for _getsd() compatible with darwin code.
   2680  */
   2681 int
   2682 smbfs_smb_getsec(struct smb_share *ssp, uint16_t fid, struct smb_cred *scrp,
   2683 	uint32_t selector, struct ntsecdesc **res)
   2684 {
   2685 	int error;
   2686 	uint32_t len, olen;
   2687 	struct mdchain *mdp, md_store;
   2688 	struct mbuf *m;
   2689 
   2690 	bzero(mdp, sizeof (*mdp));
   2691 	len = 500; /* "overlarge" values => server errors */
   2692 again:
   2693 	olen = len;
   2694 	error = smbfs_smb_getsec_m(ssp, fid, scrp, selector, &m, &len);
   2695 	/*
   2696 	 * Server may give us an error indicating that we
   2697 	 * need a larger data buffer to receive the SD,
   2698 	 * and the size we'll need.  Use the given size,
   2699 	 * but only after a sanity check.
   2700 	 *
   2701 	 * XXX: Check for specific error values here?
   2702 	 * XXX: also ... && len <= MAX_RAW_SD_SIZE
   2703 	 */
   2704 	if (error && len > olen)
   2705 		goto again;
   2706 
   2707 	if (error)
   2708 		return (error);
   2709 
   2710 	mdp = &md_store;
   2711 	md_initm(mdp, m);
   2712 	MALLOC(*res, struct ntsecdesc *, len, M_TEMP, M_WAITOK);
   2713 	error = md_get_mem(mdp, (caddr_t)*res, len, MB_MSYSTEM);
   2714 	md_done(mdp);
   2715 
   2716 	return (error);
   2717 }
   2718 #endif /* APPLE */
   2719 
   2720 /*
   2721  * OTW function to Set a security descriptor (SD).
   2722  * Caller data are carried in an mbchain_t.
   2723  *
   2724  * Note: This normally consumes mbp->mb_top, and clears
   2725  * that pointer when it does.
   2726  */
   2727 int  smbfs_smb_setsec_m(struct smb_share *ssp, uint16_t fid,
   2728 	struct smb_cred *scrp, uint32_t selector, mblk_t **mp)
   2729 {
   2730 	struct smb_ntrq *ntp;
   2731 	struct mbchain *mbp;
   2732 	int error;
   2733 
   2734 	error = smb_nt_alloc(SSTOCP(ssp), NT_TRANSACT_SET_SECURITY_DESC,
   2735 	    scrp, &ntp);
   2736 	if (error)
   2737 		return (error);
   2738 
   2739 	/* Parameters part */
   2740 	mbp = &ntp->nt_tparam;
   2741 	mb_init(mbp);
   2742 	mb_put_uint16le(mbp, fid);
   2743 	mb_put_uint16le(mbp, 0); /* reserved */
   2744 	mb_put_uint32le(mbp, selector);
   2745 
   2746 	/* Data part */
   2747 	mbp = &ntp->nt_tdata;
   2748 	mb_initm(mbp, *mp);
   2749 	*mp = NULL; /* consumed */
   2750 
   2751 	/* No returned parameters or data. */
   2752 	ntp->nt_maxpcount = 0;
   2753 	ntp->nt_maxdcount = 0;
   2754 
   2755 	error = smb_nt_request(ntp);
   2756 	smb_nt_done(ntp);
   2757 
   2758 	return (error);
   2759 }
   2760 
   2761 #ifdef	APPLE
   2762 /*
   2763  * This function builds the SD given the various parts.
   2764  */
   2765 int
   2766 smbfs_smb_setsec(struct smb_share *ssp, uint16_t fid, struct smb_cred *scrp,
   2767 	uint32_t selector, uint16_t flags, struct ntsid *owner,
   2768 	struct ntsid *group, struct ntacl *sacl, struct ntacl *dacl)
   2769 {
   2770 	struct mbchain *mbp, mb_store;
   2771 	struct ntsecdesc ntsd;
   2772 	int error, off;
   2773 
   2774 	/*
   2775 	 * Build the SD as its own mbuf chain and pass it to
   2776 	 * smbfs_smb_setsec_m()
   2777 	 */
   2778 	mbp = &mb_store;
   2779 	mb_init(mbp);
   2780 	bzero(&ntsd, sizeof (ntsd));
   2781 	wset_sdrevision(&ntsd);
   2782 	/*
   2783 	 * A note about flags ("SECURITY_DESCRIPTOR_CONTROL" in MSDN)
   2784 	 * We set here only those bits we can be sure must be set.  The rest
   2785 	 * are up to the caller.  In particular, the caller may intentionally
   2786 	 * set an acl PRESENT bit while giving us a null pointer for the
   2787 	 * acl - that sets a null acl, giving access to everyone.  Note also
   2788 	 * that the AUTO_INHERITED bits should probably always be set unless
   2789 	 * the server is NT.
   2790 	 */
   2791 	flags |= SD_SELF_RELATIVE;
   2792 	off = sizeof (ntsd);
   2793 	if (owner) {
   2794 		wset_sdowneroff(&ntsd, off);
   2795 		off += sidlen(owner);
   2796 	}
   2797 	if (group) {
   2798 		wset_sdgroupoff(&ntsd, off);
   2799 		off += sidlen(group);
   2800 	}
   2801 	if (sacl) {
   2802 		flags |= SD_SACL_PRESENT;
   2803 		wset_sdsacloff(&ntsd, off);
   2804 		off += acllen(sacl);
   2805 	}
   2806 	if (dacl) {
   2807 		flags |= SD_DACL_PRESENT;
   2808 		wset_sddacloff(&ntsd, off);
   2809 	}
   2810 	wset_sdflags(&ntsd, flags);
   2811 	mb_put_mem(mbp, (caddr_t)&ntsd, sizeof (ntsd), MB_MSYSTEM);
   2812 	if (owner)
   2813 		mb_put_mem(mbp, (caddr_t)owner, sidlen(owner), MB_MSYSTEM);
   2814 	if (group)
   2815 		mb_put_mem(mbp, (caddr_t)group, sidlen(group), MB_MSYSTEM);
   2816 	if (sacl)
   2817 		mb_put_mem(mbp, (caddr_t)sacl, acllen(sacl), MB_MSYSTEM);
   2818 	if (dacl)
   2819 		mb_put_mem(mbp, (caddr_t)dacl, acllen(dacl), MB_MSYSTEM);
   2820 
   2821 	/*
   2822 	 * Just pass the mbuf to _setsec_m
   2823 	 * It will clear mb_top if consumed.
   2824 	 */
   2825 	error = smbfs_smb_setsec_m(ssp, fid, scrp, selector, &mbp->mb_top);
   2826 	mb_done(mbp);
   2827 
   2828 	return (error);
   2829 }
   2830 
   2831 #endif /* APPLE */
   2832