14bff34e3Sthurlow /*
24bff34e3Sthurlow  * Copyright (c) 2000-2001 Boris Popov
34bff34e3Sthurlow  * All rights reserved.
44bff34e3Sthurlow  *
54bff34e3Sthurlow  * Redistribution and use in source and binary forms, with or without
64bff34e3Sthurlow  * modification, are permitted provided that the following conditions
74bff34e3Sthurlow  * are met:
84bff34e3Sthurlow  * 1. Redistributions of source code must retain the above copyright
94bff34e3Sthurlow  *    notice, this list of conditions and the following disclaimer.
104bff34e3Sthurlow  * 2. Redistributions in binary form must reproduce the above copyright
114bff34e3Sthurlow  *    notice, this list of conditions and the following disclaimer in the
124bff34e3Sthurlow  *    documentation and/or other materials provided with the distribution.
134bff34e3Sthurlow  * 3. All advertising materials mentioning features or use of this software
144bff34e3Sthurlow  *    must display the following acknowledgement:
154bff34e3Sthurlow  *    This product includes software developed by Boris Popov.
164bff34e3Sthurlow  * 4. Neither the name of the author nor the names of any co-contributors
174bff34e3Sthurlow  *    may be used to endorse or promote products derived from this software
184bff34e3Sthurlow  *    without specific prior written permission.
194bff34e3Sthurlow  *
204bff34e3Sthurlow  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
214bff34e3Sthurlow  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
224bff34e3Sthurlow  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
234bff34e3Sthurlow  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
244bff34e3Sthurlow  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
254bff34e3Sthurlow  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
264bff34e3Sthurlow  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
274bff34e3Sthurlow  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
284bff34e3Sthurlow  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
294bff34e3Sthurlow  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
304bff34e3Sthurlow  * SUCH DAMAGE.
314bff34e3Sthurlow  */
324bff34e3Sthurlow 
334bff34e3Sthurlow /*
34613a2f6bSGordon Ross  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
354bff34e3Sthurlow  * Use is subject to license terms.
368329232eSGordon Ross  *
37*168091e5SGordon Ross  * Copyright 2021 Tintri by DDN, Inc.  All rights reserved.
384bff34e3Sthurlow  */
394bff34e3Sthurlow 
404bff34e3Sthurlow #include <sys/param.h>
414bff34e3Sthurlow #include <sys/systm.h>
428329232eSGordon Ross #include <sys/inttypes.h>
434bff34e3Sthurlow #include <sys/time.h>
444bff34e3Sthurlow #include <sys/vnode.h>
45613a2f6bSGordon Ross #include <sys/sunddi.h>
464bff34e3Sthurlow #include <sys/cmn_err.h>
474bff34e3Sthurlow 
484bff34e3Sthurlow #include <netsmb/smb_osdep.h>
494bff34e3Sthurlow 
504bff34e3Sthurlow #include <netsmb/smb.h>
51adee6784SGordon Ross #include <netsmb/smb2.h>
524bff34e3Sthurlow #include <netsmb/smb_conn.h>
534bff34e3Sthurlow #include <netsmb/smb_subr.h>
544bff34e3Sthurlow #include <netsmb/smb_rq.h>
554bff34e3Sthurlow 
564bff34e3Sthurlow #include <smbfs/smbfs.h>
574bff34e3Sthurlow #include <smbfs/smbfs_node.h>
584bff34e3Sthurlow #include <smbfs/smbfs_subr.h>
594bff34e3Sthurlow 
6002d09e03SGordon Ross /*
6102d09e03SGordon Ross  * Jan 1 1980 as 64 bit NT time.
6202d09e03SGordon Ross  * (tenths of microseconds since 1601)
6302d09e03SGordon Ross  */
6402d09e03SGordon Ross const uint64_t NT1980 = 11960035200ULL*10000000ULL;
6502d09e03SGordon Ross 
664bff34e3Sthurlow 
674bff34e3Sthurlow /*
68adee6784SGordon Ross  * Helper for smbfs_getattr_otw
69adee6784SGordon Ross  * used when we have an open FID
704bff34e3Sthurlow  */
714bff34e3Sthurlow int
smbfs_smb_getfattr(struct smbnode * np,smb_fh_t * fhp,struct smbfattr * fap,struct smb_cred * scrp)724bff34e3Sthurlow smbfs_smb_getfattr(
734bff34e3Sthurlow 	struct smbnode *np,
74adee6784SGordon Ross 	smb_fh_t *fhp,
754bff34e3Sthurlow 	struct smbfattr *fap,
764bff34e3Sthurlow 	struct smb_cred *scrp)
774bff34e3Sthurlow {
78adee6784SGordon Ross 	struct smb_share *ssp = np->n_mount->smi_share;
794bff34e3Sthurlow 	int error;
804bff34e3Sthurlow 
81adee6784SGordon Ross 	if (SSTOVC(ssp)->vc_flags & SMBV_SMB2) {
82adee6784SGordon Ross 		error = smbfs_smb2_qfileinfo(ssp, &fhp->fh_fid2, fap, scrp);
83adee6784SGordon Ross 	} else {
84adee6784SGordon Ross 		error = smbfs_smb1_trans2_query(np, fhp->fh_fid1, fap, scrp);
8591d632c8Sgwr 	}
8691d632c8Sgwr 
874bff34e3Sthurlow 	return (error);
884bff34e3Sthurlow }
894bff34e3Sthurlow 
904bff34e3Sthurlow /*
91adee6784SGordon Ross  * Helper for smbfs_getattr_otw
92adee6784SGordon Ross  * used when we don't have an open FID
93adee6784SGordon Ross  *
94adee6784SGordon Ross  * For SMB1 we can just use the path form of trans2 query.
95adee6784SGordon Ross  * For SMB2 we need to do an attribute-only open.
96adee6784SGordon Ross  * See smbfs_smb2_getpattr()
974bff34e3Sthurlow  */
984bff34e3Sthurlow int
smbfs_smb_getpattr(struct smbnode * np,struct smbfattr * fap,struct smb_cred * scrp)99adee6784SGordon Ross smbfs_smb_getpattr(
100adee6784SGordon Ross 	struct smbnode *np,
101adee6784SGordon Ross 	struct smbfattr *fap,
102adee6784SGordon Ross 	struct smb_cred *scrp)
1034bff34e3Sthurlow {
1044bff34e3Sthurlow 	struct smb_share *ssp = np->n_mount->smi_share;
105adee6784SGordon Ross 	int error;
10602d09e03SGordon Ross 
107adee6784SGordon Ross 	if (SSTOVC(ssp)->vc_flags & SMBV_SMB2) {
108adee6784SGordon Ross 		error = smbfs_smb2_getpattr(np, fap, scrp);
109adee6784SGordon Ross 	} else {
110adee6784SGordon Ross 		uint16_t fid = SMB_FID_UNUSED;
111adee6784SGordon Ross 		error = smbfs_smb1_trans2_query(np, fid, fap, scrp);
1124bff34e3Sthurlow 	}
11302d09e03SGordon Ross 
1144bff34e3Sthurlow 	return (error);
1154bff34e3Sthurlow }
1164bff34e3Sthurlow 
1174bff34e3Sthurlow /*
118adee6784SGordon Ross  * Get and parse FileFsAttributeInformation
1194bff34e3Sthurlow  */
1204bff34e3Sthurlow int
smbfs_smb_qfsattr(struct smb_share * ssp,struct smb_fs_attr_info * fsa,struct smb_cred * scrp)121613a2f6bSGordon Ross smbfs_smb_qfsattr(struct smb_share *ssp, struct smb_fs_attr_info *fsa,
122613a2f6bSGordon Ross 	struct smb_cred *scrp)
1234bff34e3Sthurlow {
1244bff34e3Sthurlow 	int error;
125613a2f6bSGordon Ross 
126adee6784SGordon Ross 	if (SSTOVC(ssp)->vc_flags & SMBV_SMB2) {
127adee6784SGordon Ross 		error = smbfs_smb2_qfsattr(ssp, fsa, scrp);
128613a2f6bSGordon Ross 	} else {
129adee6784SGordon Ross 		error = smbfs_smb1_qfsattr(ssp, fsa, scrp);
1304bff34e3Sthurlow 	}
131613a2f6bSGordon Ross 
13202d09e03SGordon Ross 	/*
13302d09e03SGordon Ross 	 * If fs_name starts with FAT, we can't set dates before 1980
13402d09e03SGordon Ross 	 */
13502d09e03SGordon Ross 	if (0 == strncmp(fsa->fsa_tname, "FAT", 3)) {
13602d09e03SGordon Ross 		SMB_SS_LOCK(ssp);
13702d09e03SGordon Ross 		ssp->ss_flags |= SMBS_FST_FAT;
13802d09e03SGordon Ross 		SMB_SS_UNLOCK(ssp);
13902d09e03SGordon Ross 	}
14002d09e03SGordon Ross 
141adee6784SGordon Ross 	return (error);
1424bff34e3Sthurlow }
1434bff34e3Sthurlow 
1444bff34e3Sthurlow int
smbfs_smb_statfs(struct smb_share * ssp,statvfs64_t * sbp,struct smb_cred * scp)1454bff34e3Sthurlow smbfs_smb_statfs(struct smb_share *ssp, statvfs64_t *sbp,
1464bff34e3Sthurlow 	struct smb_cred *scp)
1474bff34e3Sthurlow {
148adee6784SGordon Ross 	struct smb_fs_size_info info;
149adee6784SGordon Ross 	struct smb_vc *vcp = SSTOVC(ssp);
150adee6784SGordon Ross 	uint32_t bps, spu;
1514bff34e3Sthurlow 	int error;
1524bff34e3Sthurlow 
153adee6784SGordon Ross 	if (vcp->vc_flags & SMBV_SMB2) {
154adee6784SGordon Ross 		error = smbfs_smb2_statfs(ssp, &info, scp);
155adee6784SGordon Ross 	} else {
156adee6784SGordon Ross 		error = smbfs_smb1_statfs(ssp, &info, scp);
157adee6784SGordon Ross 	}
158adee6784SGordon Ross 	if (error)
159adee6784SGordon Ross 		return (error);
160adee6784SGordon Ross 
161adee6784SGordon Ross 	/* A bit of paranoia. */
162adee6784SGordon Ross 	bps = info.bytes_per_sect;
163adee6784SGordon Ross 	if (bps < DEV_BSIZE)
164adee6784SGordon Ross 		bps = DEV_BSIZE;
165adee6784SGordon Ross 	spu = info.sect_per_unit;
166adee6784SGordon Ross 	if (spu == 0)
167adee6784SGordon Ross 		spu = 1;
168adee6784SGordon Ross 
169adee6784SGordon Ross 	/* preferred file system block size */
170adee6784SGordon Ross 	sbp->f_bsize = bps * spu;
171adee6784SGordon Ross 
172adee6784SGordon Ross 	/* file system block size ("fragment size") */
173adee6784SGordon Ross 	sbp->f_frsize = bps;
174adee6784SGordon Ross 
175adee6784SGordon Ross 	/* total blocks of f_frsize */
176adee6784SGordon Ross 	sbp->f_blocks = info.total_units * spu;
177adee6784SGordon Ross 
178adee6784SGordon Ross 	/* free blocks of f_frsize */
179adee6784SGordon Ross 	sbp->f_bfree = info.actual_avail * spu;
180adee6784SGordon Ross 
181adee6784SGordon Ross 	/* free blocks avail to non-superuser */
182adee6784SGordon Ross 	sbp->f_bavail = info.caller_avail * spu;
183adee6784SGordon Ross 
184adee6784SGordon Ross 	sbp->f_files = (-1);	/* total file nodes in file system */
185adee6784SGordon Ross 	sbp->f_ffree = (-1);	/* free file nodes in fs */
1864bff34e3Sthurlow 
1874bff34e3Sthurlow 	return (error);
1884bff34e3Sthurlow }
1894bff34e3Sthurlow 
1904bff34e3Sthurlow int
smbfs_smb_setdisp(struct smb_share * ssp,smb_fh_t * fhp,uint8_t disp,struct smb_cred * scrp)191adee6784SGordon Ross smbfs_smb_setdisp(struct smb_share *ssp, smb_fh_t *fhp,
192adee6784SGordon Ross 	uint8_t disp, struct smb_cred *scrp)
1934bff34e3Sthurlow {
194adee6784SGordon Ross 	int err;
19502d09e03SGordon Ross 
196adee6784SGordon Ross 	if (SSTOVC(ssp)->vc_flags & SMBV_SMB2) {
197adee6784SGordon Ross 		err = smbfs_smb2_setdisp(ssp, &fhp->fh_fid2, disp, scrp);
198adee6784SGordon Ross 	} else {
199adee6784SGordon Ross 		err = smbfs_smb1_setdisp(ssp, fhp->fh_fid1, disp, scrp);
2004bff34e3Sthurlow 	}
20102d09e03SGordon Ross 
202adee6784SGordon Ross 	return (err);
2034bff34e3Sthurlow }
2044bff34e3Sthurlow 
2054bff34e3Sthurlow int
smbfs_smb_setfsize(struct smb_share * ssp,smb_fh_t * fhp,uint64_t size,struct smb_cred * scrp)206adee6784SGordon Ross smbfs_smb_setfsize(struct smb_share *ssp, smb_fh_t *fhp,
207adee6784SGordon Ross 	uint64_t size, struct smb_cred *scrp)
2084bff34e3Sthurlow {
2094bff34e3Sthurlow 	int error;
2104bff34e3Sthurlow 
211adee6784SGordon Ross 	if (SSTOVC(ssp)->vc_flags & SMBV_SMB2) {
212adee6784SGordon Ross 		error = smbfs_smb2_seteof(ssp, &fhp->fh_fid2, size, scrp);
213adee6784SGordon Ross 	} else {
214adee6784SGordon Ross 		error = smbfs_smb1_seteof(ssp, fhp->fh_fid1, size, scrp);
2154bff34e3Sthurlow 	}
21602d09e03SGordon Ross 
217adee6784SGordon Ross 	return (error);
2184bff34e3Sthurlow }
2194bff34e3Sthurlow 
220adee6784SGordon Ross 
221adee6784SGordon Ross /*
222adee6784SGordon Ross  * Set file attributes (optionally: DOS attr, atime, mtime)
223adee6784SGordon Ross  * Always have an open FID with set attr rights.
224adee6784SGordon Ross  */
2254bff34e3Sthurlow int
smbfs_smb_setfattr(struct smb_share * ssp,smb_fh_t * fhp,uint32_t attr,struct timespec * mtime,struct timespec * atime,struct smb_cred * scrp)226adee6784SGordon Ross smbfs_smb_setfattr(
227adee6784SGordon Ross 	struct smb_share *ssp,
228adee6784SGordon Ross 	smb_fh_t *fhp,
229adee6784SGordon Ross 	uint32_t attr,
230adee6784SGordon Ross 	struct timespec *mtime,
231adee6784SGordon Ross 	struct timespec *atime,
232adee6784SGordon Ross 	struct smb_cred *scrp)
2334bff34e3Sthurlow {
234adee6784SGordon Ross 	struct mbchain mb_info;
235adee6784SGordon Ross 	struct mbchain *mbp = &mb_info;
236adee6784SGordon Ross 	uint64_t tm;
2374bff34e3Sthurlow 	int error;
2384bff34e3Sthurlow 
239adee6784SGordon Ross 	/*
240adee6784SGordon Ross 	 * Build a struct FILE_BASIC_INFORMATION in mbp
241adee6784SGordon Ross 	 *	LARGE_INTEGER CreationTime;
242adee6784SGordon Ross 	 *	LARGE_INTEGER LastAccessTime;
243adee6784SGordon Ross 	 *	LARGE_INTEGER LastWriteTime;
244adee6784SGordon Ross 	 *	LARGE_INTEGER ChangeTime;
245adee6784SGordon Ross 	 *	ULONG FileAttributes;
246adee6784SGordon Ross 	 * Zero in times means "no change".
247adee6784SGordon Ross 	 */
2484bff34e3Sthurlow 	mb_init(mbp);
249adee6784SGordon Ross 	mb_put_uint64le(mbp, 0);		/* creation time */
250adee6784SGordon Ross 	if (atime) {
251adee6784SGordon Ross 		smb_time_local2NT(atime, &tm);
252adee6784SGordon Ross 		if (tm != 0 && (ssp->ss_flags & SMBS_FST_FAT) &&
253adee6784SGordon Ross 		    tm < NT1980)
254adee6784SGordon Ross 			tm = NT1980;
255adee6784SGordon Ross 	} else
256adee6784SGordon Ross 		tm = 0;
257adee6784SGordon Ross 	mb_put_uint64le(mbp, tm);		/* last access time */
258adee6784SGordon Ross 	if (mtime) {
259adee6784SGordon Ross 		smb_time_local2NT(mtime, &tm);
260adee6784SGordon Ross 		if (tm != 0 && (ssp->ss_flags & SMBS_FST_FAT) &&
261adee6784SGordon Ross 		    tm < NT1980)
262adee6784SGordon Ross 			tm = NT1980;
263adee6784SGordon Ross 	} else
264adee6784SGordon Ross 		tm = 0;
265adee6784SGordon Ross 	mb_put_uint64le(mbp, tm);		/* last write time */
266adee6784SGordon Ross 	mb_put_uint64le(mbp, 0);		/* change time */
267adee6784SGordon Ross 	mb_put_uint32le(mbp, attr);
2688a2c2d71SGordon Ross 	mb_put_uint32le(mbp, 0);		/* reserved */
269adee6784SGordon Ross 
270adee6784SGordon Ross 	if (SSTOVC(ssp)->vc_flags & SMBV_SMB2) {
271adee6784SGordon Ross 		error = smbfs_smb2_setfattr(ssp, &fhp->fh_fid2, mbp, scrp);
272adee6784SGordon Ross 	} else {
273adee6784SGordon Ross 		error = smbfs_smb1_setfattr(ssp, fhp->fh_fid1, mbp, scrp);
274adee6784SGordon Ross 	}
275adee6784SGordon Ross 
2764bff34e3Sthurlow 	return (error);
2774bff34e3Sthurlow }
2784bff34e3Sthurlow 
2794bff34e3Sthurlow int
smbfs_smb_flush(struct smb_share * ssp,smb_fh_t * fhp,struct smb_cred * scrp)280adee6784SGordon Ross smbfs_smb_flush(struct smb_share *ssp, smb_fh_t *fhp,
2818329232eSGordon Ross 	struct smb_cred *scrp)
2824bff34e3Sthurlow {
283ff1e230cSjilinxpd 	int error;
2844bff34e3Sthurlow 
285adee6784SGordon Ross 	if (SSTOVC(ssp)->vc_flags & SMBV_SMB2) {
286adee6784SGordon Ross 		error = smbfs_smb2_flush(ssp, &fhp->fh_fid2, scrp);
287adee6784SGordon Ross 	} else {
288adee6784SGordon Ross 		error = smbfs_smb1_flush(ssp, fhp->fh_fid1, scrp);
289adee6784SGordon Ross 	}
290ff1e230cSjilinxpd 	return (error);
291ff1e230cSjilinxpd }
2924bff34e3Sthurlow 
293ff1e230cSjilinxpd /*
294adee6784SGordon Ross  * Modern create/open of file or directory.
295adee6784SGordon Ross  * On success, fills in fhp->fh_fid* and fhp->fh_rights
296ff1e230cSjilinxpd  */
297ff1e230cSjilinxpd int
smbfs_smb_ntcreatex(struct smbnode * np,const char * name,int nmlen,int xattr,uint32_t req_acc,uint32_t efa,uint32_t share_acc,uint32_t disp,uint32_t createopt,struct smb_cred * scrp,smb_fh_t * fhp,uint32_t * cr_act_p,struct smbfattr * fap)298adee6784SGordon Ross smbfs_smb_ntcreatex(
299adee6784SGordon Ross 	struct smbnode *np,
300adee6784SGordon Ross 	const char *name,
301adee6784SGordon Ross 	int nmlen,
302adee6784SGordon Ross 	int xattr,		/* is named stream? */
303adee6784SGordon Ross 	uint32_t req_acc,	/* requested access */
304adee6784SGordon Ross 	uint32_t efa,		/* ext. file attrs (DOS attr +) */
305adee6784SGordon Ross 	uint32_t share_acc,
306adee6784SGordon Ross 	uint32_t disp,		/* open disposition */
307adee6784SGordon Ross 	uint32_t createopt,	/* NTCREATEX_OPTIONS_ */
308adee6784SGordon Ross 	struct smb_cred *scrp,
309adee6784SGordon Ross 	smb_fh_t *fhp,		/* pre-made file handle to fill in */
310adee6784SGordon Ross 	uint32_t *cr_act_p,	/* optional returned create action */
311adee6784SGordon Ross 	struct smbfattr *fap)	/* optional returned attributes */
312ff1e230cSjilinxpd {
313adee6784SGordon Ross 	struct mbchain name_mb;
314ff1e230cSjilinxpd 	struct smb_share *ssp = np->n_mount->smi_share;
315adee6784SGordon Ross 	int err;
316ff1e230cSjilinxpd 
317adee6784SGordon Ross 	mb_init(&name_mb);
318ff1e230cSjilinxpd 
319adee6784SGordon Ross 	if (name == NULL)
320adee6784SGordon Ross 		nmlen = 0;
321adee6784SGordon Ross 	err = smbfs_fullpath(&name_mb, SSTOVC(ssp),
322adee6784SGordon Ross 	    np, name, nmlen, xattr ? ':' : '\\');
323adee6784SGordon Ross 	if (err)
324ff1e230cSjilinxpd 		goto out;
3254bff34e3Sthurlow 
326adee6784SGordon Ross 	err = smb_smb_ntcreate(ssp, &name_mb,
327adee6784SGordon Ross 	    0,	/* NTCREATEX_FLAGS... */
328adee6784SGordon Ross 	    req_acc, efa, share_acc, disp, createopt,
329adee6784SGordon Ross 	    NTCREATEX_IMPERSONATION_IMPERSONATION,
330adee6784SGordon Ross 	    scrp, fhp, cr_act_p, fap);
3314bff34e3Sthurlow 
332adee6784SGordon Ross out:
333adee6784SGordon Ross 	mb_done(&name_mb);
334613a2f6bSGordon Ross 
335adee6784SGordon Ross 	return (err);
3364bff34e3Sthurlow }
3374bff34e3Sthurlow 
338adee6784SGordon Ross /*
339adee6784SGordon Ross  * Get a file handle with (at least) the specified rights.
340adee6784SGordon Ross  *
341adee6784SGordon Ross  * We'll try to borrow the node ->n_fid if we can.  When we
342adee6784SGordon Ross  * borrow n_fid, just take a hold on the smb_fh_t, and don't
343adee6784SGordon Ross  * bump n_fidrefs as that tracks VFS-level opens.  Similarly
344adee6784SGordon Ross  * in _tmpclose we just release the smb_fh_t, not n_fidrefs.
345adee6784SGordon Ross  */
3464bff34e3Sthurlow int
smbfs_smb_tmpopen(struct smbnode * np,uint32_t rights,struct smb_cred * scrp,smb_fh_t ** fhpp)347adee6784SGordon Ross smbfs_smb_tmpopen(struct smbnode *np, uint32_t rights, struct smb_cred *scrp,
348adee6784SGordon Ross 	smb_fh_t **fhpp)
3494bff34e3Sthurlow {
3504bff34e3Sthurlow 	struct smb_share *ssp = np->n_mount->smi_share;
351adee6784SGordon Ross 	smb_fh_t *fhp = NULL;
3524bff34e3Sthurlow 	int error;
3534bff34e3Sthurlow 
354613a2f6bSGordon Ross 	/* Can we re-use n_fid? or must we open anew? */
355adee6784SGordon Ross 	mutex_enter(&np->r_statelock);
356adee6784SGordon Ross 	if (np->n_fidrefs > 0 &&
357adee6784SGordon Ross 	   (fhp = np->n_fid) != NULL &&
358adee6784SGordon Ross 	   fhp->fh_vcgenid == ssp->ss_vcgenid &&
359adee6784SGordon Ross 	   (fhp->fh_rights & rights) == rights) {
360adee6784SGordon Ross 		smb_fh_hold(fhp);
361adee6784SGordon Ross 		*fhpp = fhp;
362adee6784SGordon Ross 		mutex_exit(&np->r_statelock);
3634bff34e3Sthurlow 		return (0);
36402d09e03SGordon Ross 	}
365adee6784SGordon Ross 	mutex_exit(&np->r_statelock);
366adee6784SGordon Ross 
367adee6784SGordon Ross 	error = smb_fh_create(ssp, &fhp);
368adee6784SGordon Ross 	if (error != 0)
369adee6784SGordon Ross 		goto out;
370adee6784SGordon Ross 
371adee6784SGordon Ross 	/* re-open an existing file. */
372adee6784SGordon Ross 	error = smbfs_smb_ntcreatex(np,
373adee6784SGordon Ross 	    NULL, 0, 0,	/* name nmlen xattr */
374adee6784SGordon Ross 	    rights, SMB_EFA_NORMAL,
375adee6784SGordon Ross 	    NTCREATEX_SHARE_ACCESS_ALL,
376adee6784SGordon Ross 	    NTCREATEX_DISP_OPEN,
377adee6784SGordon Ross 	    0, /* create options */
378adee6784SGordon Ross 	    scrp, fhp,
379adee6784SGordon Ross 	    NULL, NULL); /* cr_act_p fa_p */
380adee6784SGordon Ross 	if (error != 0)
381adee6784SGordon Ross 		goto out;
382adee6784SGordon Ross 
383adee6784SGordon Ross 	fhp->fh_rights = rights;
384adee6784SGordon Ross 	smb_fh_opened(fhp);
385adee6784SGordon Ross 	*fhpp = fhp;
386adee6784SGordon Ross 	fhp = NULL;
387adee6784SGordon Ross 
388adee6784SGordon Ross out:
389adee6784SGordon Ross 	if (fhp != NULL)
390adee6784SGordon Ross 		smb_fh_rele(fhp);
39102d09e03SGordon Ross 
39202d09e03SGordon Ross 	return (error);
3934bff34e3Sthurlow }
3944bff34e3Sthurlow 
395adee6784SGordon Ross /* ARGSUSED */
396adee6784SGordon Ross void
smbfs_smb_tmpclose(struct smbnode * np,smb_fh_t * fhp)397adee6784SGordon Ross smbfs_smb_tmpclose(struct smbnode *np, smb_fh_t *fhp)
398adee6784SGordon Ross {
399adee6784SGordon Ross 	smb_fh_rele(fhp);
400adee6784SGordon Ross }
401adee6784SGordon Ross 
4024bff34e3Sthurlow int
smbfs_smb_open(struct smbnode * np,const char * name,int nmlen,int xattr,uint32_t rights,struct smb_cred * scrp,smb_fh_t ** fhpp,smbfattr_t * fap)403adee6784SGordon Ross smbfs_smb_open(
404adee6784SGordon Ross 	struct smbnode *np,
405adee6784SGordon Ross 	const char *name,
406adee6784SGordon Ross 	int nmlen,
407adee6784SGordon Ross 	int xattr,
408adee6784SGordon Ross 	uint32_t rights,
409adee6784SGordon Ross 	struct smb_cred *scrp,
410adee6784SGordon Ross 	smb_fh_t **fhpp,
411adee6784SGordon Ross 	smbfattr_t *fap)
4124bff34e3Sthurlow {
4134bff34e3Sthurlow 	struct smb_share *ssp = np->n_mount->smi_share;
414adee6784SGordon Ross 	// struct smb_vc *vcp = SSTOVC(ssp);
415adee6784SGordon Ross 	smb_fh_t *fhp = NULL;
4164bff34e3Sthurlow 	int error;
4174bff34e3Sthurlow 
418adee6784SGordon Ross 	error = smb_fh_create(ssp, &fhp);
419adee6784SGordon Ross 	if (error != 0)
420adee6784SGordon Ross 		goto out;
4214bff34e3Sthurlow 
422adee6784SGordon Ross 	/* open an existing file */
423adee6784SGordon Ross 	error = smbfs_smb_ntcreatex(np,
424adee6784SGordon Ross 	    name, nmlen, xattr,
425adee6784SGordon Ross 	    rights, SMB_EFA_NORMAL,
426adee6784SGordon Ross 	    NTCREATEX_SHARE_ACCESS_ALL,
427adee6784SGordon Ross 	    NTCREATEX_DISP_OPEN,
428adee6784SGordon Ross 	    0, /* create options */
429adee6784SGordon Ross 	    scrp, fhp, NULL, fap);
430adee6784SGordon Ross 	if (error != 0)
431adee6784SGordon Ross 		goto out;
4324bff34e3Sthurlow 
433adee6784SGordon Ross 	fhp->fh_rights = rights;
434adee6784SGordon Ross 	smb_fh_opened(fhp);
435adee6784SGordon Ross 	*fhpp = fhp;
436adee6784SGordon Ross 	fhp = NULL;
4374bff34e3Sthurlow 
438adee6784SGordon Ross out:
439adee6784SGordon Ross 	if (fhp != NULL)
440adee6784SGordon Ross 		smb_fh_rele(fhp);
44191d632c8Sgwr 
442*168091e5SGordon Ross 	return (error);
4434bff34e3Sthurlow }
4444bff34e3Sthurlow 
445adee6784SGordon Ross void
smbfs_smb_close(smb_fh_t * fhp)446adee6784SGordon Ross smbfs_smb_close(smb_fh_t *fhp)
4474bff34e3Sthurlow {
4484bff34e3Sthurlow 
449adee6784SGordon Ross 	smb_fh_close(fhp);
450adee6784SGordon Ross 	smb_fh_rele(fhp);
4514bff34e3Sthurlow }
4524bff34e3Sthurlow 
453adee6784SGordon Ross int
smbfs_smb_create(struct smbnode * dnp,const char * name,int nmlen,int xattr,uint32_t disp,struct smb_cred * scrp,smb_fh_t ** fhpp)454adee6784SGordon Ross smbfs_smb_create(
455adee6784SGordon Ross 	struct smbnode *dnp,
456adee6784SGordon Ross 	const char *name,
457adee6784SGordon Ross 	int nmlen,
458adee6784SGordon Ross 	int xattr,
459adee6784SGordon Ross 	uint32_t disp,
460adee6784SGordon Ross 	struct smb_cred *scrp,
461adee6784SGordon Ross 	smb_fh_t **fhpp)
4624bff34e3Sthurlow {
463adee6784SGordon Ross 	struct smb_share *ssp = dnp->n_mount->smi_share;
464adee6784SGordon Ross 	// struct smb_vc *vcp = SSTOVC(ssp);
465adee6784SGordon Ross 	smb_fh_t *fhp = NULL;
466adee6784SGordon Ross 	uint32_t efa, rights;
467430b4c46SGordon Ross 	int error;
4684bff34e3Sthurlow 
469adee6784SGordon Ross 	error = smb_fh_create(ssp, &fhp);
4705ecede33SGordon Ross 	if (error != 0)
471adee6784SGordon Ross 		goto out;
4725ecede33SGordon Ross 
4734bff34e3Sthurlow 	/*
474adee6784SGordon Ross 	 * At present the only access we might need is to WRITE data,
475adee6784SGordon Ross 	 * and that only if we are creating a "symlink".  When/if the
476adee6784SGordon Ross 	 * access needed gets more complex it should made a parameter
477adee6784SGordon Ross 	 * and be set upstream.
4784bff34e3Sthurlow 	 */
479adee6784SGordon Ross 	rights = SA_RIGHT_FILE_WRITE_DATA;
480adee6784SGordon Ross 	efa = SMB_EFA_NORMAL;
481adee6784SGordon Ross 	if (!xattr && name && *name == '.')
482adee6784SGordon Ross 		efa = SMB_EFA_HIDDEN;
483adee6784SGordon Ross 	error = smbfs_smb_ntcreatex(dnp,
484adee6784SGordon Ross 	    name, nmlen, xattr, rights, efa,
485adee6784SGordon Ross 	    NTCREATEX_SHARE_ACCESS_ALL,
486adee6784SGordon Ross 	    disp, /* != NTCREATEX_DISP_OPEN */
487adee6784SGordon Ross 	    NTCREATEX_OPTIONS_NON_DIRECTORY_FILE,
488adee6784SGordon Ross 	    scrp, fhp, NULL, NULL);
489adee6784SGordon Ross 	if (error != 0)
490adee6784SGordon Ross 		goto out;
4915ecede33SGordon Ross 
492adee6784SGordon Ross 	fhp->fh_rights = rights;
493adee6784SGordon Ross 	smb_fh_opened(fhp);
494adee6784SGordon Ross 	*fhpp = fhp;
495adee6784SGordon Ross 	fhp = NULL;
4964bff34e3Sthurlow 
497adee6784SGordon Ross out:
498adee6784SGordon Ross 	if (fhp != NULL)
499adee6784SGordon Ross 		smb_fh_rele(fhp);
5004bff34e3Sthurlow 
5014bff34e3Sthurlow 	return (error);
5024bff34e3Sthurlow }
5034bff34e3Sthurlow 
504adee6784SGordon Ross int
smbfs_smb_rename(struct smbnode * sdnp,struct smbnode * np,struct smbnode * tdnp,const char * tname,int tnlen,smb_fh_t * fhp,struct smb_cred * scrp)505adee6784SGordon Ross smbfs_smb_rename(struct smbnode *sdnp, struct smbnode *np,
506adee6784SGordon Ross     struct smbnode *tdnp, const char *tname, int tnlen,
507adee6784SGordon Ross     smb_fh_t *fhp, struct smb_cred *scrp)
5084bff34e3Sthurlow {
509adee6784SGordon Ross 	struct smb_share *ssp = np->n_mount->smi_share;
510adee6784SGordon Ross 	struct smb_vc *vcp = SSTOVC(ssp);
511adee6784SGordon Ross 	int err;
512613a2f6bSGordon Ross 
513adee6784SGordon Ross 	if (vcp->vc_flags & SMBV_SMB2) {
514adee6784SGordon Ross 		err = smbfs_smb2_rename(np, tdnp, tname, tnlen, 0,
515adee6784SGordon Ross 		    &fhp->fh_fid2, scrp);
516adee6784SGordon Ross 		return (err);
5174bff34e3Sthurlow 	}
5184bff34e3Sthurlow 
5194bff34e3Sthurlow 	/*
520adee6784SGordon Ross 	 * SMB1 -- Want to use _t2rename if we can
521adee6784SGordon Ross 	 * (rename in same dir and cap pass-through)
522adee6784SGordon Ross 	 * Most SMB1 servers have cap pass-through.
5234bff34e3Sthurlow 	 */
524adee6784SGordon Ross 	if (sdnp == tdnp &&
525adee6784SGordon Ross 	    (vcp->vc_sopt.sv_caps & SMB_CAP_INFOLEVEL_PASSTHRU) != 0) {
526adee6784SGordon Ross 		err = smbfs_smb1_t2rename(np, tname, tnlen, fhp->fh_fid1, scrp);
527adee6784SGordon Ross 	} else {
528adee6784SGordon Ross 		err = smbfs_smb1_oldrename(np, tdnp, tname, tnlen, scrp);
5294bff34e3Sthurlow 	}
53091d632c8Sgwr 
531adee6784SGordon Ross 	return (err);
532adee6784SGordon Ross }
533adee6784SGordon Ross 
534adee6784SGordon Ross int
smbfs_smb_mkdir(struct smbnode * dnp,const char * name,int nmlen,struct smb_cred * scrp)535adee6784SGordon Ross smbfs_smb_mkdir(struct smbnode *dnp, const char *name, int nmlen,
536adee6784SGordon Ross 		struct smb_cred *scrp)
537adee6784SGordon Ross {
538adee6784SGordon Ross 	smb_fh_t tmp_fh;
539adee6784SGordon Ross 	struct smb_share *ssp = dnp->n_mount->smi_share;
540adee6784SGordon Ross 	uint32_t efa, rights;
541adee6784SGordon Ross 	int error;
5425ecede33SGordon Ross 
5435ecede33SGordon Ross 	/*
544adee6784SGordon Ross 	 * Using a faked-up handle here to avoid the work of
545adee6784SGordon Ross 	 * creating and destroying a real "conn obj".
5465ecede33SGordon Ross 	 */
547adee6784SGordon Ross 	bzero(&tmp_fh, sizeof (tmp_fh));
5484bff34e3Sthurlow 
54902d09e03SGordon Ross 	/*
550adee6784SGordon Ross 	 * We ask for SA_RIGHT_FILE_READ_DATA not because we need it, but
551adee6784SGordon Ross 	 * just to be asking for something.  The rights==0 case could
552adee6784SGordon Ross 	 * easily be broken on some old or unusual servers.
55302d09e03SGordon Ross 	 */
554adee6784SGordon Ross 	rights = SA_RIGHT_FILE_READ_DATA;
555adee6784SGordon Ross 	efa = SMB_EFA_NORMAL;
556adee6784SGordon Ross 	if (name && *name == '.')
557adee6784SGordon Ross 		efa |= SMB_EFA_HIDDEN;
558adee6784SGordon Ross 	error = smbfs_smb_ntcreatex(dnp,
559adee6784SGordon Ross 	    name, nmlen, 0, /* xattr */
560adee6784SGordon Ross 	    rights, SMB_EFA_DIRECTORY,
561adee6784SGordon Ross 	    NTCREATEX_SHARE_ACCESS_ALL,
562adee6784SGordon Ross 	    NTCREATEX_DISP_CREATE,
563adee6784SGordon Ross 	    NTCREATEX_OPTIONS_DIRECTORY,
564adee6784SGordon Ross 	    scrp, &tmp_fh, NULL, NULL);
565adee6784SGordon Ross 	if (error == 0) {
566adee6784SGordon Ross 		(void) smb_smb_close(ssp, &tmp_fh, scrp);
567adee6784SGordon Ross 	}
568adee6784SGordon Ross 
5697568150aSgwr 	return (error);
5704bff34e3Sthurlow }
5714bff34e3Sthurlow 
572adee6784SGordon Ross /*
573adee6784SGordon Ross  * Protocol-level directory open
574adee6784SGordon Ross  */
5754bff34e3Sthurlow int
smbfs_smb_findopen(struct smbnode * dnp,const char * wild,int wlen,int attr,struct smb_cred * scrp,struct smbfs_fctx ** ctxpp)57691d632c8Sgwr smbfs_smb_findopen(struct smbnode *dnp, const char *wild, int wlen,
5774bff34e3Sthurlow 			int attr, struct smb_cred *scrp,
5784bff34e3Sthurlow 			struct smbfs_fctx **ctxpp)
5794bff34e3Sthurlow {
580adee6784SGordon Ross 	struct smb_share *ssp = dnp->n_mount->smi_share;
581adee6784SGordon Ross 	struct smb_vc *vcp = SSTOVC(ssp);
5824bff34e3Sthurlow 	struct smbfs_fctx *ctx;
5834bff34e3Sthurlow 	int error;
5844bff34e3Sthurlow 
585613a2f6bSGordon Ross 	ctx = kmem_zalloc(sizeof (*ctx), KM_SLEEP);
58691d632c8Sgwr 
5874bff34e3Sthurlow 	ctx->f_flags = SMBFS_RDD_FINDFIRST;
58891d632c8Sgwr 	ctx->f_dnp = dnp;
5894bff34e3Sthurlow 	ctx->f_scred = scrp;
590adee6784SGordon Ross 	ctx->f_ssp = ssp;
59191d632c8Sgwr 
59291d632c8Sgwr 	if (dnp->n_flag & N_XATTR) {
59391d632c8Sgwr 		error = smbfs_xa_findopen(ctx, dnp, wild, wlen);
59491d632c8Sgwr 		goto out;
59591d632c8Sgwr 	}
59691d632c8Sgwr 
597adee6784SGordon Ross 	if (vcp->vc_flags & SMBV_SMB2) {
598adee6784SGordon Ross 		error = smbfs_smb2_findopen(ctx, dnp, wild, wlen, attr);
59991d632c8Sgwr 	} else {
60091d632c8Sgwr 		error = smbfs_smb_findopenLM2(ctx, dnp, wild, wlen, attr);
60191d632c8Sgwr 	}
60291d632c8Sgwr 
60391d632c8Sgwr out:
604adee6784SGordon Ross 	ctx->f_scred = NULL;
605adee6784SGordon Ross 	if (error) {
606adee6784SGordon Ross 		kmem_free(ctx, sizeof (*ctx));
607adee6784SGordon Ross 	} else {
6084bff34e3Sthurlow 		*ctxpp = ctx;
609adee6784SGordon Ross 	}
610adee6784SGordon Ross 
6114bff34e3Sthurlow 	return (error);
6124bff34e3Sthurlow }
6134bff34e3Sthurlow 
6144bff34e3Sthurlow int
smbfs_smb_findnext(struct smbfs_fctx * ctx,int limit,struct smb_cred * scrp)6154bff34e3Sthurlow smbfs_smb_findnext(struct smbfs_fctx *ctx, int limit, struct smb_cred *scrp)
6164bff34e3Sthurlow {
617adee6784SGordon Ross 	int error = 0;
618adee6784SGordon Ross 	uint16_t lim;
6194bff34e3Sthurlow 
6204bff34e3Sthurlow 	/*
6214bff34e3Sthurlow 	 * Note: "limit" (maxcount) needs to fit in a short!
6224bff34e3Sthurlow 	 */
6235ecede33SGordon Ross 	if (limit > 0xffff)
6245ecede33SGordon Ross 		limit = 0xffff;
625adee6784SGordon Ross 	lim = (uint16_t)limit;
6264bff34e3Sthurlow 
6274bff34e3Sthurlow 	ctx->f_scred = scrp;
6284bff34e3Sthurlow 	for (;;) {
62991d632c8Sgwr 		bzero(&ctx->f_attr, sizeof (ctx->f_attr));
63091d632c8Sgwr 		switch (ctx->f_type) {
631adee6784SGordon Ross 
632adee6784SGordon Ross 		case ft_SMB2:
633adee6784SGordon Ross 			error = smbfs_smb2_findnext(ctx, lim);
63491d632c8Sgwr 			break;
63591d632c8Sgwr 		case ft_LM2:
636adee6784SGordon Ross 			error = smbfs_smb_findnextLM2(ctx, lim);
63791d632c8Sgwr 			break;
63891d632c8Sgwr 		case ft_XA:
639adee6784SGordon Ross 			error = smbfs_xa_findnext(ctx, lim);
64091d632c8Sgwr 			break;
64191d632c8Sgwr 		default:
64291d632c8Sgwr 			ASSERT(0);
64391d632c8Sgwr 			error = EINVAL;
64491d632c8Sgwr 			break;
64591d632c8Sgwr 		}
6464bff34e3Sthurlow 		if (error)
647adee6784SGordon Ross 			break;
64891d632c8Sgwr 		/*
64991d632c8Sgwr 		 * Skip "." or ".." - easy now that ctx->f_name
65091d632c8Sgwr 		 * has already been converted to utf-8 format.
65191d632c8Sgwr 		 */
65291d632c8Sgwr 		if ((ctx->f_nmlen == 1 && ctx->f_name[0] == '.') ||
65391d632c8Sgwr 		    (ctx->f_nmlen == 2 && ctx->f_name[0] == '.' &&
65491d632c8Sgwr 		    ctx->f_name[1] == '.'))
65591d632c8Sgwr 			continue;
6564bff34e3Sthurlow 		break;
6574bff34e3Sthurlow 	}
658adee6784SGordon Ross 	ctx->f_scred = NULL;
659adee6784SGordon Ross 	if (error != 0)
660adee6784SGordon Ross 		return (error);
66191d632c8Sgwr 
662adee6784SGordon Ross 	ctx->f_inum = smbfs_getino(ctx->f_dnp,
663adee6784SGordon Ross 	    ctx->f_name, ctx->f_nmlen);
66491d632c8Sgwr 
665adee6784SGordon Ross #ifdef	DEBUG
666adee6784SGordon Ross 	SMBVDEBUG("findnext: (%s)\n", ctx->f_name);
667adee6784SGordon Ross #endif
668adee6784SGordon Ross 
669adee6784SGordon Ross 	return (error);
6704bff34e3Sthurlow }
6714bff34e3Sthurlow 
6724bff34e3Sthurlow 
6734bff34e3Sthurlow int
smbfs_smb_findclose(struct smbfs_fctx * ctx,struct smb_cred * scrp)6744bff34e3Sthurlow smbfs_smb_findclose(struct smbfs_fctx *ctx, struct smb_cred *scrp)
6754bff34e3Sthurlow {
6767568150aSgwr 	int error;
67791d632c8Sgwr 
6784bff34e3Sthurlow 	ctx->f_scred = scrp;
67991d632c8Sgwr 	switch (ctx->f_type) {
680adee6784SGordon Ross 	case ft_SMB2:
681adee6784SGordon Ross 		error = smbfs_smb2_findclose(ctx);
68291d632c8Sgwr 		break;
68391d632c8Sgwr 	case ft_LM2:
6847568150aSgwr 		error = smbfs_smb_findcloseLM2(ctx);
68591d632c8Sgwr 		break;
68691d632c8Sgwr 	case ft_XA:
68791d632c8Sgwr 		error = smbfs_xa_findclose(ctx);
68891d632c8Sgwr 		break;
6898329232eSGordon Ross 	default:
6908329232eSGordon Ross 		error = ENOSYS;
6918329232eSGordon Ross 		break;
69291d632c8Sgwr 	}
693adee6784SGordon Ross 	ctx->f_scred = NULL;
6944bff34e3Sthurlow 	if (ctx->f_rname)
6954bff34e3Sthurlow 		kmem_free(ctx->f_rname, ctx->f_rnamelen);
6964bff34e3Sthurlow 	if (ctx->f_firstnm)
6974bff34e3Sthurlow 		kmem_free(ctx->f_firstnm, ctx->f_firstnmlen);
6984bff34e3Sthurlow 	kmem_free(ctx, sizeof (*ctx));
6997568150aSgwr 	return (error);
7004bff34e3Sthurlow }
7014bff34e3Sthurlow 
7024bff34e3Sthurlow 
7034bff34e3Sthurlow int
smbfs_smb_lookup(struct smbnode * dnp,const char ** namep,int * nmlenp,struct smbfattr * fap,struct smb_cred * scrp)7044bff34e3Sthurlow smbfs_smb_lookup(struct smbnode *dnp, const char **namep, int *nmlenp,
7054bff34e3Sthurlow 	struct smbfattr *fap, struct smb_cred *scrp)
7064bff34e3Sthurlow {
7074bff34e3Sthurlow 	struct smbfs_fctx *ctx;
7084bff34e3Sthurlow 	int error, intr;
7094bff34e3Sthurlow 	const char *name = (namep ? *namep : NULL);
7104bff34e3Sthurlow 	int nmlen = (nmlenp ? *nmlenp : 0);
7114bff34e3Sthurlow 
7124bff34e3Sthurlow 	/* This is no longer called with a null dnp */
7134bff34e3Sthurlow 	ASSERT(dnp);
7144bff34e3Sthurlow 
7154bff34e3Sthurlow 	/*
7164bff34e3Sthurlow 	 * Should not get here with "" anymore.
7174bff34e3Sthurlow 	 */
7184bff34e3Sthurlow 	if (!name || !nmlen) {
7194bff34e3Sthurlow 		DEBUG_ENTER("smbfs_smb_lookup: name is NULL");
7204bff34e3Sthurlow 		return (EINVAL);
7214bff34e3Sthurlow 	}
7224bff34e3Sthurlow 
7234bff34e3Sthurlow 	/*
7244bff34e3Sthurlow 	 * Should not get here with "." or ".." anymore.
7254bff34e3Sthurlow 	 */
7264bff34e3Sthurlow 	if ((nmlen == 1 && name[0] == '.') ||
7274bff34e3Sthurlow 	    (nmlen == 2 && name[0] == '.' && name[1] == '.')) {
7284bff34e3Sthurlow 		DEBUG_ENTER("smbfs_smb_lookup: name is '.' or '..'");
7294bff34e3Sthurlow 		return (EINVAL);
7304bff34e3Sthurlow 	}
7314bff34e3Sthurlow 
7324bff34e3Sthurlow 	/*
7334bff34e3Sthurlow 	 * Shared lock for n_fid use (smb_flush).
7344bff34e3Sthurlow 	 */
7354bff34e3Sthurlow 	intr = dnp->n_mount->smi_flags & SMI_INT;
7364bff34e3Sthurlow 	if (smbfs_rw_enter_sig(&dnp->r_lkserlock, RW_READER, intr))
7374bff34e3Sthurlow 		return (EINTR);
7384bff34e3Sthurlow 
7394bff34e3Sthurlow 	error = smbfs_smb_findopen(dnp, name, nmlen,
7404bff34e3Sthurlow 	    SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_DIR, scrp, &ctx);
7414bff34e3Sthurlow 	if (error)
7424bff34e3Sthurlow 		goto out;
7434bff34e3Sthurlow 	ctx->f_flags |= SMBFS_RDD_FINDSINGLE;
7444bff34e3Sthurlow 	error = smbfs_smb_findnext(ctx, 1, scrp);
7454bff34e3Sthurlow 	if (error == 0) {
7464bff34e3Sthurlow 		*fap = ctx->f_attr;
74702d09e03SGordon Ross 		/*
74802d09e03SGordon Ross 		 * Solaris smbfattr doesn't have fa_ino,
74902d09e03SGordon Ross 		 * and we don't allow name==NULL in this
75002d09e03SGordon Ross 		 * function anymore.
75102d09e03SGordon Ross 		 */
7524bff34e3Sthurlow 		if (namep)
7534bff34e3Sthurlow 			*namep = (const char *)smbfs_name_alloc(
7544bff34e3Sthurlow 			    ctx->f_name, ctx->f_nmlen);
7554bff34e3Sthurlow 		if (nmlenp)
7564bff34e3Sthurlow 			*nmlenp = ctx->f_nmlen;
7574bff34e3Sthurlow 	}
7587568150aSgwr 	(void) smbfs_smb_findclose(ctx, scrp);
7594bff34e3Sthurlow 
7604bff34e3Sthurlow out:
7614bff34e3Sthurlow 	smbfs_rw_exit(&dnp->r_lkserlock);
7624bff34e3Sthurlow 	return (error);
7634bff34e3Sthurlow }
7644bff34e3Sthurlow 
7654bff34e3Sthurlow /*
7667568150aSgwr  * OTW function to Get a security descriptor (SD).
7677568150aSgwr  *
7687568150aSgwr  * Note: On success, this fills in mdp->md_top,
7697568150aSgwr  * which the caller should free.
7704bff34e3Sthurlow  */
7714bff34e3Sthurlow int
smbfs_smb_getsec(struct smb_share * ssp,smb_fh_t * fhp,uint32_t selector,mblk_t ** res,uint32_t * reslen,struct smb_cred * scrp)772adee6784SGordon Ross smbfs_smb_getsec(struct smb_share *ssp, smb_fh_t *fhp,
773adee6784SGordon Ross 	uint32_t selector, mblk_t **res, uint32_t *reslen,
774adee6784SGordon Ross 	struct smb_cred *scrp)
7754bff34e3Sthurlow {
776adee6784SGordon Ross 	struct smb_vc *vcp = SSTOVC(ssp);
7774bff34e3Sthurlow 	int error, len;
7784bff34e3Sthurlow 
7794bff34e3Sthurlow 	*res = NULL;
7807568150aSgwr 
781adee6784SGordon Ross 	if (vcp->vc_flags & SMBV_SMB2) {
782adee6784SGordon Ross 		error = smbfs_smb2_getsec(ssp, &fhp->fh_fid2,
783adee6784SGordon Ross 		    selector, res, reslen, scrp);
784adee6784SGordon Ross 	} else {
785adee6784SGordon Ross 		error = smbfs_smb1_getsec(ssp, fhp->fh_fid1,
786adee6784SGordon Ross 		    selector, res, reslen, scrp);
787adee6784SGordon Ross 	}
7884bff34e3Sthurlow 
7897568150aSgwr 	/*
7907568150aSgwr 	 * get the data part.
7917568150aSgwr 	 */
792adee6784SGordon Ross 	if (*res == NULL) {
7937568150aSgwr 		error = EBADRPC;
7947568150aSgwr 		goto done;
7957568150aSgwr 	}
7967568150aSgwr 
7977568150aSgwr 	/*
798adee6784SGordon Ross 	 * If message length is < returned SD_length,
799adee6784SGordon Ross 	 * correct *reslen (reduce it).  It greater,
800adee6784SGordon Ross 	 * just ignore the extra data.
8017568150aSgwr 	 */
802adee6784SGordon Ross 	len = m_fixhdr(*res);
8037568150aSgwr 	if (len < *reslen)
8047568150aSgwr 		*reslen = len;
8057568150aSgwr 
8064bff34e3Sthurlow done:
8077568150aSgwr 	if (error == 0 && *res == NULL) {
8087568150aSgwr 		ASSERT(*res);
8097568150aSgwr 		error = EBADRPC;
8107568150aSgwr 	}
8117568150aSgwr 
8124bff34e3Sthurlow 	return (error);
8134bff34e3Sthurlow }
8144bff34e3Sthurlow 
8157568150aSgwr /*
8167568150aSgwr  * OTW function to Set a security descriptor (SD).
8177568150aSgwr  * Caller data are carried in an mbchain_t.
8187568150aSgwr  *
8197568150aSgwr  * Note: This normally consumes mbp->mb_top, and clears
8207568150aSgwr  * that pointer when it does.
8217568150aSgwr  */
8227568150aSgwr int
smbfs_smb_setsec(struct smb_share * ssp,smb_fh_t * fhp,uint32_t selector,mblk_t ** mp,struct smb_cred * scrp)823adee6784SGordon Ross smbfs_smb_setsec(struct smb_share *ssp, smb_fh_t *fhp,
824adee6784SGordon Ross 	uint32_t selector, mblk_t **mp,
825adee6784SGordon Ross 	struct smb_cred *scrp)
8267568150aSgwr {
827adee6784SGordon Ross 	struct smb_vc *vcp = SSTOVC(ssp);
828adee6784SGordon Ross 	int error;
8297568150aSgwr 
830adee6784SGordon Ross 	if (vcp->vc_flags & SMBV_SMB2) {
831adee6784SGordon Ross 		error = smbfs_smb2_setsec(ssp, &fhp->fh_fid2,
832adee6784SGordon Ross 		    selector, mp, scrp);
833adee6784SGordon Ross 	} else {
834adee6784SGordon Ross 		error = smbfs_smb1_setsec(ssp, fhp->fh_fid1,
835adee6784SGordon Ross 		    selector, mp, scrp);
8364bff34e3Sthurlow 	}
8377568150aSgwr 
8384bff34e3Sthurlow 	return (error);
8394bff34e3Sthurlow }
840