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_vnops.c,v 1.128.36.1 2005/05/27 02:35:28 lindak Exp $
33 */
34
35 /*
36 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
37 */
38
39 #include <sys/systm.h>
40 #include <sys/cred.h>
41 #include <sys/vnode.h>
42 #include <sys/vfs.h>
43 #include <sys/filio.h>
44 #include <sys/uio.h>
45 #include <sys/dirent.h>
46 #include <sys/errno.h>
47 #include <sys/sunddi.h>
48 #include <sys/sysmacros.h>
49 #include <sys/kmem.h>
50 #include <sys/cmn_err.h>
51 #include <sys/vfs_opreg.h>
52 #include <sys/policy.h>
53
54 #include <netsmb/smb_osdep.h>
55 #include <netsmb/smb.h>
56 #include <netsmb/smb_conn.h>
57 #include <netsmb/smb_subr.h>
58
59 #include <smbfs/smbfs.h>
60 #include <smbfs/smbfs_node.h>
61 #include <smbfs/smbfs_subr.h>
62
63 #include <sys/fs/smbfs_ioctl.h>
64 #include <fs/fs_subr.h>
65
66 /*
67 * We assign directory offsets like the NFS client, where the
68 * offset increments by _one_ after each directory entry.
69 * Further, the entries "." and ".." are always at offsets
70 * zero and one (respectively) and the "real" entries from
71 * the server appear at offsets starting with two. This
72 * macro is used to initialize the n_dirofs field after
73 * setting n_dirseq with a _findopen call.
74 */
75 #define FIRST_DIROFS 2
76
77 /*
78 * These characters are illegal in NTFS file names.
79 * ref: http://support.microsoft.com/kb/147438
80 *
81 * Careful! The check in the XATTR case skips the
82 * first character to allow colon in XATTR names.
83 */
84 static const char illegal_chars[] = {
85 ':', /* colon - keep this first! */
86 '\\', /* back slash */
87 '/', /* slash */
88 '*', /* asterisk */
89 '?', /* question mark */
90 '"', /* double quote */
91 '<', /* less than sign */
92 '>', /* greater than sign */
93 '|', /* vertical bar */
94 0
95 };
96
97 /*
98 * Turning this on causes nodes to be created in the cache
99 * during directory listings, normally avoiding a second
100 * OtW attribute fetch just after a readdir.
101 */
102 int smbfs_fastlookup = 1;
103
104 /* local static function defines */
105
106 static int smbfslookup_cache(vnode_t *, char *, int, vnode_t **,
107 cred_t *);
108 static int smbfslookup(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr,
109 int cache_ok, caller_context_t *);
110 static int smbfsrename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm,
111 cred_t *cr, caller_context_t *);
112 static int smbfssetattr(vnode_t *, struct vattr *, int, cred_t *);
113 static int smbfs_accessx(void *, int, cred_t *);
114 static int smbfs_readvdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp,
115 caller_context_t *);
116 static void smbfs_rele_fid(smbnode_t *, struct smb_cred *);
117 static uint32_t xvattr_to_dosattr(smbnode_t *, struct vattr *);
118
119 /*
120 * These are the vnode ops routines which implement the vnode interface to
121 * the networked file system. These routines just take their parameters,
122 * make them look networkish by putting the right info into interface structs,
123 * and then calling the appropriate remote routine(s) to do the work.
124 *
125 * Note on directory name lookup cacheing: If we detect a stale fhandle,
126 * we purge the directory cache relative to that vnode. This way, the
127 * user won't get burned by the cache repeatedly. See <smbfs/smbnode.h> for
128 * more details on smbnode locking.
129 */
130
131 static int smbfs_open(vnode_t **, int, cred_t *, caller_context_t *);
132 static int smbfs_close(vnode_t *, int, int, offset_t, cred_t *,
133 caller_context_t *);
134 static int smbfs_read(vnode_t *, struct uio *, int, cred_t *,
135 caller_context_t *);
136 static int smbfs_write(vnode_t *, struct uio *, int, cred_t *,
137 caller_context_t *);
138 static int smbfs_ioctl(vnode_t *, int, intptr_t, int, cred_t *, int *,
139 caller_context_t *);
140 static int smbfs_getattr(vnode_t *, struct vattr *, int, cred_t *,
141 caller_context_t *);
142 static int smbfs_setattr(vnode_t *, struct vattr *, int, cred_t *,
143 caller_context_t *);
144 static int smbfs_access(vnode_t *, int, int, cred_t *, caller_context_t *);
145 static int smbfs_fsync(vnode_t *, int, cred_t *, caller_context_t *);
146 static void smbfs_inactive(vnode_t *, cred_t *, caller_context_t *);
147 static int smbfs_lookup(vnode_t *, char *, vnode_t **, struct pathname *,
148 int, vnode_t *, cred_t *, caller_context_t *,
149 int *, pathname_t *);
150 static int smbfs_create(vnode_t *, char *, struct vattr *, enum vcexcl,
151 int, vnode_t **, cred_t *, int, caller_context_t *,
152 vsecattr_t *);
153 static int smbfs_remove(vnode_t *, char *, cred_t *, caller_context_t *,
154 int);
155 static int smbfs_rename(vnode_t *, char *, vnode_t *, char *, cred_t *,
156 caller_context_t *, int);
157 static int smbfs_mkdir(vnode_t *, char *, struct vattr *, vnode_t **,
158 cred_t *, caller_context_t *, int, vsecattr_t *);
159 static int smbfs_rmdir(vnode_t *, char *, vnode_t *, cred_t *,
160 caller_context_t *, int);
161 static int smbfs_readdir(vnode_t *, struct uio *, cred_t *, int *,
162 caller_context_t *, int);
163 static int smbfs_rwlock(vnode_t *, int, caller_context_t *);
164 static void smbfs_rwunlock(vnode_t *, int, caller_context_t *);
165 static int smbfs_seek(vnode_t *, offset_t, offset_t *, caller_context_t *);
166 static int smbfs_frlock(vnode_t *, int, struct flock64 *, int, offset_t,
167 struct flk_callback *, cred_t *, caller_context_t *);
168 static int smbfs_space(vnode_t *, int, struct flock64 *, int, offset_t,
169 cred_t *, caller_context_t *);
170 static int smbfs_pathconf(vnode_t *, int, ulong_t *, cred_t *,
171 caller_context_t *);
172 static int smbfs_setsecattr(vnode_t *, vsecattr_t *, int, cred_t *,
173 caller_context_t *);
174 static int smbfs_getsecattr(vnode_t *, vsecattr_t *, int, cred_t *,
175 caller_context_t *);
176 static int smbfs_shrlock(vnode_t *, int, struct shrlock *, int, cred_t *,
177 caller_context_t *);
178
179 /* Dummy function to use until correct function is ported in */
180 int noop_vnodeop() {
181 return (0);
182 }
183
184 struct vnodeops *smbfs_vnodeops = NULL;
185
186 /*
187 * Most unimplemented ops will return ENOSYS because of fs_nosys().
188 * The only ops where that won't work are ACCESS (due to open(2)
189 * failures) and ... (anything else left?)
190 */
191 const fs_operation_def_t smbfs_vnodeops_template[] = {
192 { VOPNAME_OPEN, { .vop_open = smbfs_open } },
193 { VOPNAME_CLOSE, { .vop_close = smbfs_close } },
194 { VOPNAME_READ, { .vop_read = smbfs_read } },
195 { VOPNAME_WRITE, { .vop_write = smbfs_write } },
196 { VOPNAME_IOCTL, { .vop_ioctl = smbfs_ioctl } },
197 { VOPNAME_GETATTR, { .vop_getattr = smbfs_getattr } },
198 { VOPNAME_SETATTR, { .vop_setattr = smbfs_setattr } },
199 { VOPNAME_ACCESS, { .vop_access = smbfs_access } },
200 { VOPNAME_LOOKUP, { .vop_lookup = smbfs_lookup } },
201 { VOPNAME_CREATE, { .vop_create = smbfs_create } },
202 { VOPNAME_REMOVE, { .vop_remove = smbfs_remove } },
203 { VOPNAME_LINK, { .error = fs_nosys } }, /* smbfs_link, */
204 { VOPNAME_RENAME, { .vop_rename = smbfs_rename } },
205 { VOPNAME_MKDIR, { .vop_mkdir = smbfs_mkdir } },
206 { VOPNAME_RMDIR, { .vop_rmdir = smbfs_rmdir } },
207 { VOPNAME_READDIR, { .vop_readdir = smbfs_readdir } },
208 { VOPNAME_SYMLINK, { .error = fs_nosys } }, /* smbfs_symlink, */
209 { VOPNAME_READLINK, { .error = fs_nosys } }, /* smbfs_readlink, */
210 { VOPNAME_FSYNC, { .vop_fsync = smbfs_fsync } },
211 { VOPNAME_INACTIVE, { .vop_inactive = smbfs_inactive } },
212 { VOPNAME_FID, { .error = fs_nosys } }, /* smbfs_fid, */
213 { VOPNAME_RWLOCK, { .vop_rwlock = smbfs_rwlock } },
214 { VOPNAME_RWUNLOCK, { .vop_rwunlock = smbfs_rwunlock } },
215 { VOPNAME_SEEK, { .vop_seek = smbfs_seek } },
216 { VOPNAME_FRLOCK, { .vop_frlock = smbfs_frlock } },
217 { VOPNAME_SPACE, { .vop_space = smbfs_space } },
218 { VOPNAME_REALVP, { .error = fs_nosys } }, /* smbfs_realvp, */
219 { VOPNAME_GETPAGE, { .error = fs_nosys } }, /* smbfs_getpage, */
220 { VOPNAME_PUTPAGE, { .error = fs_nosys } }, /* smbfs_putpage, */
221 { VOPNAME_MAP, { .error = fs_nosys } }, /* smbfs_map, */
222 { VOPNAME_ADDMAP, { .error = fs_nosys } }, /* smbfs_addmap, */
223 { VOPNAME_DELMAP, { .error = fs_nosys } }, /* smbfs_delmap, */
224 { VOPNAME_DUMP, { .error = fs_nosys } }, /* smbfs_dump, */
225 { VOPNAME_PATHCONF, { .vop_pathconf = smbfs_pathconf } },
226 { VOPNAME_PAGEIO, { .error = fs_nosys } }, /* smbfs_pageio, */
227 { VOPNAME_SETSECATTR, { .vop_setsecattr = smbfs_setsecattr } },
228 { VOPNAME_GETSECATTR, { .vop_getsecattr = smbfs_getsecattr } },
229 { VOPNAME_SHRLOCK, { .vop_shrlock = smbfs_shrlock } },
230 { NULL, NULL }
231 };
232
233 /*
234 * XXX
235 * When new and relevant functionality is enabled, we should be
236 * calling vfs_set_feature() to inform callers that pieces of
237 * functionality are available, per PSARC 2007/227.
238 */
239 /* ARGSUSED */
240 static int
241 smbfs_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct)
242 {
243 smbnode_t *np;
244 vnode_t *vp;
245 smbfattr_t fa;
246 u_int32_t rights, rightsrcvd;
247 u_int16_t fid, oldfid;
248 int oldgenid;
249 struct smb_cred scred;
250 smbmntinfo_t *smi;
251 smb_share_t *ssp;
252 cred_t *oldcr;
253 int tmperror;
254 int error = 0;
255
256 vp = *vpp;
257 np = VTOSMB(vp);
258 smi = VTOSMI(vp);
259 ssp = smi->smi_share;
260
261 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
262 return (EIO);
263
264 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
265 return (EIO);
266
267 if (vp->v_type != VREG && vp->v_type != VDIR) { /* XXX VLNK? */
268 SMBVDEBUG("open eacces vtype=%d\n", vp->v_type);
269 return (EACCES);
270 }
271
272 /*
273 * Get exclusive access to n_fid and related stuff.
274 * No returns after this until out.
275 */
276 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, SMBINTR(vp)))
277 return (EINTR);
278 smb_credinit(&scred, cr);
279
280 /*
281 * Keep track of the vnode type at first open.
282 * It may change later, and we need close to do
283 * cleanup for the type we opened. Also deny
284 * open of new types until old type is closed.
285 * XXX: Per-open instance nodes whould help.
286 */
287 if (np->n_ovtype == VNON) {
288 ASSERT(np->n_dirrefs == 0);
289 ASSERT(np->n_fidrefs == 0);
290 } else if (np->n_ovtype != vp->v_type) {
291 SMBVDEBUG("open n_ovtype=%d v_type=%d\n",
292 np->n_ovtype, vp->v_type);
293 error = EACCES;
294 goto out;
295 }
296
297 /*
298 * Directory open. See smbfs_readvdir()
299 */
300 if (vp->v_type == VDIR) {
301 if (np->n_dirseq == NULL) {
302 /* first open */
303 error = smbfs_smb_findopen(np, "*", 1,
304 SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_DIR,
305 &scred, &np->n_dirseq);
306 if (error != 0)
307 goto out;
308 }
309 np->n_dirofs = FIRST_DIROFS;
310 np->n_dirrefs++;
311 goto have_fid;
312 }
313
314 /*
315 * If caller specified O_TRUNC/FTRUNC, then be sure to set
316 * FWRITE (to drive successful setattr(size=0) after open)
317 */
318 if (flag & FTRUNC)
319 flag |= FWRITE;
320
321 /*
322 * If we already have it open, and the FID is still valid,
323 * check whether the rights are sufficient for FID reuse.
324 */
325 if (np->n_fidrefs > 0 &&
326 np->n_vcgenid == ssp->ss_vcgenid) {
327 int upgrade = 0;
328
329 if ((flag & FWRITE) &&
330 !(np->n_rights & SA_RIGHT_FILE_WRITE_DATA))
331 upgrade = 1;
332 if ((flag & FREAD) &&
333 !(np->n_rights & SA_RIGHT_FILE_READ_DATA))
334 upgrade = 1;
335 if (!upgrade) {
336 /*
337 * the existing open is good enough
338 */
339 np->n_fidrefs++;
340 goto have_fid;
341 }
342 }
343 rights = np->n_fidrefs ? np->n_rights : 0;
344
345 /*
346 * we always ask for READ_CONTROL so we can always get the
347 * owner/group IDs to satisfy a stat. Ditto attributes.
348 */
349 rights |= (STD_RIGHT_READ_CONTROL_ACCESS |
350 SA_RIGHT_FILE_READ_ATTRIBUTES);
351 if ((flag & FREAD))
352 rights |= SA_RIGHT_FILE_READ_DATA;
353 if ((flag & FWRITE))
354 rights |= SA_RIGHT_FILE_WRITE_DATA |
355 SA_RIGHT_FILE_APPEND_DATA |
356 SA_RIGHT_FILE_WRITE_ATTRIBUTES;
357
358 bzero(&fa, sizeof (fa));
359 error = smbfs_smb_open(np,
360 NULL, 0, 0, /* name nmlen xattr */
361 rights, &scred,
362 &fid, &rightsrcvd, &fa);
363 if (error)
364 goto out;
365 smbfs_attrcache_fa(vp, &fa);
366
367 /*
368 * We have a new FID and access rights.
369 */
370 oldfid = np->n_fid;
371 oldgenid = np->n_vcgenid;
372 np->n_fid = fid;
373 np->n_vcgenid = ssp->ss_vcgenid;
374 np->n_rights = rightsrcvd;
375 np->n_fidrefs++;
376 if (np->n_fidrefs > 1 &&
377 oldgenid == ssp->ss_vcgenid) {
378 /*
379 * We already had it open (presumably because
380 * it was open with insufficient rights.)
381 * Close old wire-open.
382 */
383 tmperror = smbfs_smb_close(ssp,
384 oldfid, NULL, &scred);
385 if (tmperror)
386 SMBVDEBUG("error %d closing %s\n",
387 tmperror, np->n_rpath);
388 }
389
390 /*
391 * This thread did the open.
392 * Save our credentials too.
393 */
394 mutex_enter(&np->r_statelock);
395 oldcr = np->r_cred;
396 np->r_cred = cr;
397 crhold(cr);
398 if (oldcr)
399 crfree(oldcr);
400 mutex_exit(&np->r_statelock);
401
402 have_fid:
403 /*
404 * Keep track of the vnode type at first open.
405 * (see comments above)
406 */
407 if (np->n_ovtype == VNON)
408 np->n_ovtype = vp->v_type;
409
410 out:
411 smb_credrele(&scred);
412 smbfs_rw_exit(&np->r_lkserlock);
413 return (error);
414 }
415
416 /*ARGSUSED*/
417 static int
418 smbfs_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr,
419 caller_context_t *ct)
420 {
421 smbnode_t *np;
422 smbmntinfo_t *smi;
423 struct smb_cred scred;
424
425 np = VTOSMB(vp);
426 smi = VTOSMI(vp);
427
428 /*
429 * Don't "bail out" for VFS_UNMOUNTED here,
430 * as we want to do cleanup, etc.
431 */
432
433 /*
434 * zone_enter(2) prevents processes from changing zones with SMBFS files
435 * open; if we happen to get here from the wrong zone we can't do
436 * anything over the wire.
437 */
438 if (smi->smi_zone_ref.zref_zone != curproc->p_zone) {
439 /*
440 * We could attempt to clean up locks, except we're sure
441 * that the current process didn't acquire any locks on
442 * the file: any attempt to lock a file belong to another zone
443 * will fail, and one can't lock an SMBFS file and then change
444 * zones, as that fails too.
445 *
446 * Returning an error here is the sane thing to do. A
447 * subsequent call to VN_RELE() which translates to a
448 * smbfs_inactive() will clean up state: if the zone of the
449 * vnode's origin is still alive and kicking, an async worker
450 * thread will handle the request (from the correct zone), and
451 * everything (minus the final smbfs_getattr_otw() call) should
452 * be OK. If the zone is going away smbfs_async_inactive() will
453 * throw away cached pages inline.
454 */
455 return (EIO);
456 }
457
458 /*
459 * If we are using local locking for this filesystem, then
460 * release all of the SYSV style record locks. Otherwise,
461 * we are doing network locking and we need to release all
462 * of the network locks. All of the locks held by this
463 * process on this file are released no matter what the
464 * incoming reference count is.
465 */
466 if (smi->smi_flags & SMI_LLOCK) {
467 pid_t pid = ddi_get_pid();
468 cleanlocks(vp, pid, 0);
469 cleanshares(vp, pid);
470 }
471
472 /*
473 * This (passed in) count is the ref. count from the
474 * user's file_t before the closef call (fio.c).
475 * We only care when the reference goes away.
476 */
477 if (count > 1)
478 return (0);
479
480 /*
481 * Decrement the reference count for the FID
482 * and possibly do the OtW close.
483 *
484 * Exclusive lock for modifying n_fid stuff.
485 * Don't want this one ever interruptible.
486 */
487 (void) smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, 0);
488 smb_credinit(&scred, cr);
489
490 smbfs_rele_fid(np, &scred);
491
492 smb_credrele(&scred);
493 smbfs_rw_exit(&np->r_lkserlock);
494
495 return (0);
496 }
497
498 /*
499 * Helper for smbfs_close. Decrement the reference count
500 * for an SMB-level file or directory ID, and when the last
501 * reference for the fid goes away, do the OtW close.
502 * Also called in smbfs_inactive (defensive cleanup).
503 */
504 static void
505 smbfs_rele_fid(smbnode_t *np, struct smb_cred *scred)
506 {
507 smb_share_t *ssp;
508 cred_t *oldcr;
509 struct smbfs_fctx *fctx;
510 int error;
511 uint16_t ofid;
512
513 ssp = np->n_mount->smi_share;
514 error = 0;
515
516 /* Make sure we serialize for n_dirseq use. */
517 ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_WRITER));
518
519 /*
520 * Note that vp->v_type may change if a remote node
521 * is deleted and recreated as a different type, and
522 * our getattr may change v_type accordingly.
523 * Now use n_ovtype to keep track of the v_type
524 * we had during open (see comments above).
525 */
526 switch (np->n_ovtype) {
527 case VDIR:
528 ASSERT(np->n_dirrefs > 0);
529 if (--np->n_dirrefs)
530 return;
531 if ((fctx = np->n_dirseq) != NULL) {
532 np->n_dirseq = NULL;
533 np->n_dirofs = 0;
534 error = smbfs_smb_findclose(fctx, scred);
535 }
536 break;
537
538 case VREG:
539 ASSERT(np->n_fidrefs > 0);
540 if (--np->n_fidrefs)
541 return;
542 if ((ofid = np->n_fid) != SMB_FID_UNUSED) {
543 np->n_fid = SMB_FID_UNUSED;
544 /* After reconnect, n_fid is invalid */
545 if (np->n_vcgenid == ssp->ss_vcgenid) {
546 error = smbfs_smb_close(
547 ssp, ofid, NULL, scred);
548 }
549 }
550 break;
551
552 default:
553 SMBVDEBUG("bad n_ovtype %d\n", np->n_ovtype);
554 break;
555 }
556 if (error) {
557 SMBVDEBUG("error %d closing %s\n",
558 error, np->n_rpath);
559 }
560
561 /* Allow next open to use any v_type. */
562 np->n_ovtype = VNON;
563
564 /*
565 * Other "last close" stuff.
566 */
567 mutex_enter(&np->r_statelock);
568 if (np->n_flag & NATTRCHANGED)
569 smbfs_attrcache_rm_locked(np);
570 oldcr = np->r_cred;
571 np->r_cred = NULL;
572 mutex_exit(&np->r_statelock);
573 if (oldcr != NULL)
574 crfree(oldcr);
575 }
576
577 /* ARGSUSED */
578 static int
579 smbfs_read(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *cr,
580 caller_context_t *ct)
581 {
582 struct smb_cred scred;
583 struct vattr va;
584 smbnode_t *np;
585 smbmntinfo_t *smi;
586 smb_share_t *ssp;
587 offset_t endoff;
588 ssize_t past_eof;
589 int error;
590
591 np = VTOSMB(vp);
592 smi = VTOSMI(vp);
593 ssp = smi->smi_share;
594
595 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
596 return (EIO);
597
598 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
599 return (EIO);
600
601 ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_READER));
602
603 if (vp->v_type != VREG)
604 return (EISDIR);
605
606 if (uiop->uio_resid == 0)
607 return (0);
608
609 /*
610 * Like NFS3, just check for 63-bit overflow.
611 * Our SMB layer takes care to return EFBIG
612 * when it has to fallback to a 32-bit call.
613 */
614 endoff = uiop->uio_loffset + uiop->uio_resid;
615 if (uiop->uio_loffset < 0 || endoff < 0)
616 return (EINVAL);
617
618 /* get vnode attributes from server */
619 va.va_mask = AT_SIZE | AT_MTIME;
620 if (error = smbfsgetattr(vp, &va, cr))
621 return (error);
622
623 /* Update mtime with mtime from server here? */
624
625 /* if offset is beyond EOF, read nothing */
626 if (uiop->uio_loffset >= va.va_size)
627 return (0);
628
629 /*
630 * Limit the read to the remaining file size.
631 * Do this by temporarily reducing uio_resid
632 * by the amount the lies beyoned the EOF.
633 */
634 if (endoff > va.va_size) {
635 past_eof = (ssize_t)(endoff - va.va_size);
636 uiop->uio_resid -= past_eof;
637 } else
638 past_eof = 0;
639
640 /* Shared lock for n_fid use in smb_rwuio */
641 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
642 return (EINTR);
643 smb_credinit(&scred, cr);
644
645 /* After reconnect, n_fid is invalid */
646 if (np->n_vcgenid != ssp->ss_vcgenid)
647 error = ESTALE;
648 else
649 error = smb_rwuio(ssp, np->n_fid, UIO_READ,
650 uiop, &scred, smb_timo_read);
651
652 smb_credrele(&scred);
653 smbfs_rw_exit(&np->r_lkserlock);
654
655 /* undo adjustment of resid */
656 uiop->uio_resid += past_eof;
657
658 return (error);
659 }
660
661
662 /* ARGSUSED */
663 static int
664 smbfs_write(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *cr,
665 caller_context_t *ct)
666 {
667 struct smb_cred scred;
668 struct vattr va;
669 smbnode_t *np;
670 smbmntinfo_t *smi;
671 smb_share_t *ssp;
672 offset_t endoff, limit;
673 ssize_t past_limit;
674 int error, timo;
675
676 np = VTOSMB(vp);
677 smi = VTOSMI(vp);
678 ssp = smi->smi_share;
679
680 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
681 return (EIO);
682
683 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
684 return (EIO);
685
686 ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_WRITER));
687
688 if (vp->v_type != VREG)
689 return (EISDIR);
690
691 if (uiop->uio_resid == 0)
692 return (0);
693
694 /*
695 * Handle ioflag bits: (FAPPEND|FSYNC|FDSYNC)
696 */
697 if (ioflag & (FAPPEND | FSYNC)) {
698 if (np->n_flag & NMODIFIED) {
699 smbfs_attrcache_remove(np);
700 /* XXX: smbfs_vinvalbuf? */
701 }
702 }
703 if (ioflag & FAPPEND) {
704 /*
705 * File size can be changed by another client
706 */
707 va.va_mask = AT_SIZE;
708 if (error = smbfsgetattr(vp, &va, cr))
709 return (error);
710 uiop->uio_loffset = va.va_size;
711 }
712
713 /*
714 * Like NFS3, just check for 63-bit overflow.
715 */
716 endoff = uiop->uio_loffset + uiop->uio_resid;
717 if (uiop->uio_loffset < 0 || endoff < 0)
718 return (EINVAL);
719
720 /*
721 * Check to make sure that the process will not exceed
722 * its limit on file size. It is okay to write up to
723 * the limit, but not beyond. Thus, the write which
724 * reaches the limit will be short and the next write
725 * will return an error.
726 *
727 * So if we're starting at or beyond the limit, EFBIG.
728 * Otherwise, temporarily reduce resid to the amount
729 * the falls after the limit.
730 */
731 limit = uiop->uio_llimit;
732 if (limit == RLIM64_INFINITY || limit > MAXOFFSET_T)
733 limit = MAXOFFSET_T;
734 if (uiop->uio_loffset >= limit)
735 return (EFBIG);
736 if (endoff > limit) {
737 past_limit = (ssize_t)(endoff - limit);
738 uiop->uio_resid -= past_limit;
739 } else
740 past_limit = 0;
741
742 /* Timeout: longer for append. */
743 timo = smb_timo_write;
744 if (endoff > np->r_size)
745 timo = smb_timo_append;
746
747 /* Shared lock for n_fid use in smb_rwuio */
748 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
749 return (EINTR);
750 smb_credinit(&scred, cr);
751
752 /* After reconnect, n_fid is invalid */
753 if (np->n_vcgenid != ssp->ss_vcgenid)
754 error = ESTALE;
755 else
756 error = smb_rwuio(ssp, np->n_fid, UIO_WRITE,
757 uiop, &scred, timo);
758
759 if (error == 0) {
760 mutex_enter(&np->r_statelock);
761 np->n_flag |= (NFLUSHWIRE | NATTRCHANGED);
762 if (uiop->uio_loffset > (offset_t)np->r_size)
763 np->r_size = (len_t)uiop->uio_loffset;
764 mutex_exit(&np->r_statelock);
765 if (ioflag & (FSYNC|FDSYNC)) {
766 /* Don't error the I/O if this fails. */
767 (void) smbfs_smb_flush(np, &scred);
768 }
769 }
770
771 smb_credrele(&scred);
772 smbfs_rw_exit(&np->r_lkserlock);
773
774 /* undo adjustment of resid */
775 uiop->uio_resid += past_limit;
776
777 return (error);
778 }
779
780
781 /* ARGSUSED */
782 static int
783 smbfs_ioctl(vnode_t *vp, int cmd, intptr_t arg, int flag,
784 cred_t *cr, int *rvalp, caller_context_t *ct)
785 {
786 int error;
787 smbmntinfo_t *smi;
788
789 smi = VTOSMI(vp);
790
791 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
792 return (EIO);
793
794 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
795 return (EIO);
796
797 switch (cmd) {
798 /* First three from ZFS. XXX - need these? */
799
800 case _FIOFFS:
801 error = smbfs_fsync(vp, 0, cr, ct);
802 break;
803
804 /*
805 * The following two ioctls are used by bfu.
806 * Silently ignore to avoid bfu errors.
807 */
808 case _FIOGDIO:
809 case _FIOSDIO:
810 error = 0;
811 break;
812
813 #ifdef NOT_YET /* XXX - from the NFS code. */
814 case _FIODIRECTIO:
815 error = smbfs_directio(vp, (int)arg, cr);
816 #endif
817
818 /*
819 * Allow get/set with "raw" security descriptor (SD) data.
820 * Useful for testing, diagnosing idmap problems, etc.
821 */
822 case SMBFSIO_GETSD:
823 error = smbfs_acl_iocget(vp, arg, flag, cr);
824 break;
825
826 case SMBFSIO_SETSD:
827 error = smbfs_acl_iocset(vp, arg, flag, cr);
828 break;
829
830 default:
831 error = ENOTTY;
832 break;
833 }
834
835 return (error);
836 }
837
838
839 /*
840 * Return either cached or remote attributes. If get remote attr
841 * use them to check and invalidate caches, then cache the new attributes.
842 */
843 /* ARGSUSED */
844 static int
845 smbfs_getattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr,
846 caller_context_t *ct)
847 {
848 smbnode_t *np;
849 smbmntinfo_t *smi;
850
851 smi = VTOSMI(vp);
852
853 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
854 return (EIO);
855
856 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
857 return (EIO);
858
859 /*
860 * If it has been specified that the return value will
861 * just be used as a hint, and we are only being asked
862 * for size, fsid or rdevid, then return the client's
863 * notion of these values without checking to make sure
864 * that the attribute cache is up to date.
865 * The whole point is to avoid an over the wire GETATTR
866 * call.
867 */
868 np = VTOSMB(vp);
869 if (flags & ATTR_HINT) {
870 if (vap->va_mask ==
871 (vap->va_mask & (AT_SIZE | AT_FSID | AT_RDEV))) {
872 mutex_enter(&np->r_statelock);
873 if (vap->va_mask | AT_SIZE)
874 vap->va_size = np->r_size;
875 if (vap->va_mask | AT_FSID)
876 vap->va_fsid = vp->v_vfsp->vfs_dev;
877 if (vap->va_mask | AT_RDEV)
878 vap->va_rdev = vp->v_rdev;
879 mutex_exit(&np->r_statelock);
880 return (0);
881 }
882 }
883
884 return (smbfsgetattr(vp, vap, cr));
885 }
886
887 /* smbfsgetattr() in smbfs_client.c */
888
889 /*ARGSUSED4*/
890 static int
891 smbfs_setattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr,
892 caller_context_t *ct)
893 {
894 vfs_t *vfsp;
895 smbmntinfo_t *smi;
896 int error;
897 uint_t mask;
898 struct vattr oldva;
899
900 vfsp = vp->v_vfsp;
901 smi = VFTOSMI(vfsp);
902
903 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
904 return (EIO);
905
906 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED)
907 return (EIO);
908
909 mask = vap->va_mask;
910 if (mask & AT_NOSET)
911 return (EINVAL);
912
913 if (vfsp->vfs_flag & VFS_RDONLY)
914 return (EROFS);
915
916 /*
917 * This is a _local_ access check so that only the owner of
918 * this mount can set attributes. With ACLs enabled, the
919 * file owner can be different from the mount owner, and we
920 * need to check the _mount_ owner here. See _access_rwx
921 */
922 bzero(&oldva, sizeof (oldva));
923 oldva.va_mask = AT_TYPE | AT_MODE;
924 error = smbfsgetattr(vp, &oldva, cr);
925 if (error)
926 return (error);
927 oldva.va_mask |= AT_UID | AT_GID;
928 oldva.va_uid = smi->smi_uid;
929 oldva.va_gid = smi->smi_gid;
930
931 error = secpolicy_vnode_setattr(cr, vp, vap, &oldva, flags,
932 smbfs_accessx, vp);
933 if (error)
934 return (error);
935
936 if (mask & (AT_UID | AT_GID)) {
937 if (smi->smi_flags & SMI_ACL)
938 error = smbfs_acl_setids(vp, vap, cr);
939 else
940 error = ENOSYS;
941 if (error != 0) {
942 SMBVDEBUG("error %d seting UID/GID on %s",
943 error, VTOSMB(vp)->n_rpath);
944 /*
945 * It might be more correct to return the
946 * error here, but that causes complaints
947 * when root extracts a cpio archive, etc.
948 * So ignore this error, and go ahead with
949 * the rest of the setattr work.
950 */
951 }
952 }
953
954 return (smbfssetattr(vp, vap, flags, cr));
955 }
956
957 /*
958 * Mostly from Darwin smbfs_setattr()
959 * but then modified a lot.
960 */
961 /* ARGSUSED */
962 static int
963 smbfssetattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr)
964 {
965 int error = 0;
966 smbnode_t *np = VTOSMB(vp);
967 uint_t mask = vap->va_mask;
968 struct timespec *mtime, *atime;
969 struct smb_cred scred;
970 int cerror, modified = 0;
971 unsigned short fid;
972 int have_fid = 0;
973 uint32_t rights = 0;
974 uint32_t dosattr = 0;
975
976 ASSERT(curproc->p_zone == VTOSMI(vp)->smi_zone_ref.zref_zone);
977
978 /*
979 * There are no settable attributes on the XATTR dir,
980 * so just silently ignore these. On XATTR files,
981 * you can set the size but nothing else.
982 */
983 if (vp->v_flag & V_XATTRDIR)
984 return (0);
985 if (np->n_flag & N_XATTR) {
986 if (mask & AT_TIMES)
987 SMBVDEBUG("ignore set time on xattr\n");
988 mask &= AT_SIZE;
989 }
990
991 /*
992 * If our caller is trying to set multiple attributes, they
993 * can make no assumption about what order they are done in.
994 * Here we try to do them in order of decreasing likelihood
995 * of failure, just to minimize the chance we'll wind up
996 * with a partially complete request.
997 */
998
999 /* Shared lock for (possible) n_fid use. */
1000 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
1001 return (EINTR);
1002 smb_credinit(&scred, cr);
1003
1004 /*
1005 * If the caller has provided extensible attributes,
1006 * map those into DOS attributes supported by SMB.
1007 * Note: zero means "no change".
1008 */
1009 if (mask & AT_XVATTR)
1010 dosattr = xvattr_to_dosattr(np, vap);
1011
1012 /*
1013 * Will we need an open handle for this setattr?
1014 * If so, what rights will we need?
1015 */
1016 if (dosattr || (mask & (AT_ATIME | AT_MTIME))) {
1017 rights |=
1018 SA_RIGHT_FILE_WRITE_ATTRIBUTES;
1019 }
1020 if (mask & AT_SIZE) {
1021 rights |=
1022 SA_RIGHT_FILE_WRITE_DATA |
1023 SA_RIGHT_FILE_APPEND_DATA;
1024 }
1025
1026 /*
1027 * Only SIZE really requires a handle, but it's
1028 * simpler and more reliable to set via a handle.
1029 * Some servers like NT4 won't set times by path.
1030 * Also, we're usually setting everything anyway.
1031 */
1032 if (rights != 0) {
1033 error = smbfs_smb_tmpopen(np, rights, &scred, &fid);
1034 if (error) {
1035 SMBVDEBUG("error %d opening %s\n",
1036 error, np->n_rpath);
1037 goto out;
1038 }
1039 have_fid = 1;
1040 }
1041
1042 /*
1043 * If the server supports the UNIX extensions, right here is where
1044 * we'd support changes to uid, gid, mode, and possibly va_flags.
1045 * For now we claim to have made any such changes.
1046 */
1047
1048 if (mask & AT_SIZE) {
1049 /*
1050 * If the new file size is less than what the client sees as
1051 * the file size, then just change the size and invalidate
1052 * the pages.
1053 * I am commenting this code at present because the function
1054 * smbfs_putapage() is not yet implemented.
1055 */
1056
1057 /*
1058 * Set the file size to vap->va_size.
1059 */
1060 ASSERT(have_fid);
1061 error = smbfs_smb_setfsize(np, fid, vap->va_size, &scred);
1062 if (error) {
1063 SMBVDEBUG("setsize error %d file %s\n",
1064 error, np->n_rpath);
1065 } else {
1066 /*
1067 * Darwin had code here to zero-extend.
1068 * Tests indicate the server will zero-fill,
1069 * so looks like we don't need to do this.
1070 * Good thing, as this could take forever.
1071 *
1072 * XXX: Reportedly, writing one byte of zero
1073 * at the end offset avoids problems here.
1074 */
1075 mutex_enter(&np->r_statelock);
1076 np->r_size = vap->va_size;
1077 mutex_exit(&np->r_statelock);
1078 modified = 1;
1079 }
1080 }
1081
1082 /*
1083 * XXX: When Solaris has create_time, set that too.
1084 * Note: create_time is different from ctime.
1085 */
1086 mtime = ((mask & AT_MTIME) ? &vap->va_mtime : 0);
1087 atime = ((mask & AT_ATIME) ? &vap->va_atime : 0);
1088
1089 if (dosattr || mtime || atime) {
1090 /*
1091 * Always use the handle-based set attr call now.
1092 * Not trying to set DOS attributes here so pass zero.
1093 */
1094 ASSERT(have_fid);
1095 error = smbfs_smb_setfattr(np, fid,
1096 dosattr, mtime, atime, &scred);
1097 if (error) {
1098 SMBVDEBUG("set times error %d file %s\n",
1099 error, np->n_rpath);
1100 } else {
1101 modified = 1;
1102 }
1103 }
1104
1105 out:
1106 if (modified) {
1107 /*
1108 * Invalidate attribute cache in case the server
1109 * doesn't set exactly the attributes we asked.
1110 */
1111 smbfs_attrcache_remove(np);
1112 }
1113
1114 if (have_fid) {
1115 cerror = smbfs_smb_tmpclose(np, fid, &scred);
1116 if (cerror)
1117 SMBVDEBUG("error %d closing %s\n",
1118 cerror, np->n_rpath);
1119 }
1120
1121 smb_credrele(&scred);
1122 smbfs_rw_exit(&np->r_lkserlock);
1123
1124 return (error);
1125 }
1126
1127 /*
1128 * Helper function for extensible system attributes (PSARC 2007/315)
1129 * Compute the DOS attribute word to pass to _setfattr (see above).
1130 * This returns zero IFF no change is being made to attributes.
1131 * Otherwise return the new attributes or SMB_EFA_NORMAL.
1132 */
1133 static uint32_t
1134 xvattr_to_dosattr(smbnode_t *np, struct vattr *vap)
1135 {
1136 xvattr_t *xvap = (xvattr_t *)vap;
1137 xoptattr_t *xoap = NULL;
1138 uint32_t attr = np->r_attr.fa_attr;
1139 boolean_t anyset = B_FALSE;
1140
1141 if ((xoap = xva_getxoptattr(xvap)) == NULL)
1142 return (0);
1143
1144 if (XVA_ISSET_REQ(xvap, XAT_ARCHIVE)) {
1145 if (xoap->xoa_archive)
1146 attr |= SMB_FA_ARCHIVE;
1147 else
1148 attr &= ~SMB_FA_ARCHIVE;
1149 XVA_SET_RTN(xvap, XAT_ARCHIVE);
1150 anyset = B_TRUE;
1151 }
1152 if (XVA_ISSET_REQ(xvap, XAT_SYSTEM)) {
1153 if (xoap->xoa_system)
1154 attr |= SMB_FA_SYSTEM;
1155 else
1156 attr &= ~SMB_FA_SYSTEM;
1157 XVA_SET_RTN(xvap, XAT_SYSTEM);
1158 anyset = B_TRUE;
1159 }
1160 if (XVA_ISSET_REQ(xvap, XAT_READONLY)) {
1161 if (xoap->xoa_readonly)
1162 attr |= SMB_FA_RDONLY;
1163 else
1164 attr &= ~SMB_FA_RDONLY;
1165 XVA_SET_RTN(xvap, XAT_READONLY);
1166 anyset = B_TRUE;
1167 }
1168 if (XVA_ISSET_REQ(xvap, XAT_HIDDEN)) {
1169 if (xoap->xoa_hidden)
1170 attr |= SMB_FA_HIDDEN;
1171 else
1172 attr &= ~SMB_FA_HIDDEN;
1173 XVA_SET_RTN(xvap, XAT_HIDDEN);
1174 anyset = B_TRUE;
1175 }
1176
1177 if (anyset == B_FALSE)
1178 return (0); /* no change */
1179 if (attr == 0)
1180 attr = SMB_EFA_NORMAL;
1181
1182 return (attr);
1183 }
1184
1185 /*
1186 * smbfs_access_rwx()
1187 * Common function for smbfs_access, etc.
1188 *
1189 * The security model implemented by the FS is unusual
1190 * due to the current "single user mounts" restriction:
1191 * All access under a given mount point uses the CIFS
1192 * credentials established by the owner of the mount.
1193 *
1194 * Most access checking is handled by the CIFS server,
1195 * but we need sufficient Unix access checks here to
1196 * prevent other local Unix users from having access
1197 * to objects under this mount that the uid/gid/mode
1198 * settings in the mount would not allow.
1199 *
1200 * With this model, there is a case where we need the
1201 * ability to do an access check before we have the
1202 * vnode for an object. This function takes advantage
1203 * of the fact that the uid/gid/mode is per mount, and
1204 * avoids the need for a vnode.
1205 *
1206 * We still (sort of) need a vnode when we call
1207 * secpolicy_vnode_access, but that only uses
1208 * the vtype field, so we can use a pair of fake
1209 * vnodes that have only v_type filled in.
1210 *
1211 * XXX: Later, add a new secpolicy_vtype_access()
1212 * that takes the vtype instead of a vnode, and
1213 * get rid of the tmpl_vxxx fake vnodes below.
1214 */
1215 static int
1216 smbfs_access_rwx(vfs_t *vfsp, int vtype, int mode, cred_t *cr)
1217 {
1218 /* See the secpolicy call below. */
1219 static const vnode_t tmpl_vdir = { .v_type = VDIR };
1220 static const vnode_t tmpl_vreg = { .v_type = VREG };
1221 vattr_t va;
1222 vnode_t *tvp;
1223 struct smbmntinfo *smi = VFTOSMI(vfsp);
1224 int shift = 0;
1225
1226 /*
1227 * Build our (fabricated) vnode attributes.
1228 * XXX: Could make these templates in the
1229 * per-mount struct and use them here.
1230 */
1231 bzero(&va, sizeof (va));
1232 va.va_mask = AT_TYPE | AT_MODE | AT_UID | AT_GID;
1233 va.va_type = vtype;
1234 va.va_mode = (vtype == VDIR) ?
1235 smi->smi_dmode : smi->smi_fmode;
1236 va.va_uid = smi->smi_uid;
1237 va.va_gid = smi->smi_gid;
1238
1239 /*
1240 * Disallow write attempts on read-only file systems,
1241 * unless the file is a device or fifo node. Note:
1242 * Inline vn_is_readonly and IS_DEVVP here because
1243 * we may not have a vnode ptr. Original expr. was:
1244 * (mode & VWRITE) && vn_is_readonly(vp) && !IS_DEVVP(vp))
1245 */
1246 if ((mode & VWRITE) &&
1247 (vfsp->vfs_flag & VFS_RDONLY) &&
1248 !(vtype == VCHR || vtype == VBLK || vtype == VFIFO))
1249 return (EROFS);
1250
1251 /*
1252 * Disallow attempts to access mandatory lock files.
1253 * Similarly, expand MANDLOCK here.
1254 * XXX: not sure we need this.
1255 */
1256 if ((mode & (VWRITE | VREAD | VEXEC)) &&
1257 va.va_type == VREG && MANDMODE(va.va_mode))
1258 return (EACCES);
1259
1260 /*
1261 * Access check is based on only
1262 * one of owner, group, public.
1263 * If not owner, then check group.
1264 * If not a member of the group,
1265 * then check public access.
1266 */
1267 if (crgetuid(cr) != va.va_uid) {
1268 shift += 3;
1269 if (!groupmember(va.va_gid, cr))
1270 shift += 3;
1271 }
1272
1273 /*
1274 * We need a vnode for secpolicy_vnode_access,
1275 * but the only thing it looks at is v_type,
1276 * so pass one of the templates above.
1277 */
1278 tvp = (va.va_type == VDIR) ?
1279 (vnode_t *)&tmpl_vdir :
1280 (vnode_t *)&tmpl_vreg;
1281
1282 return (secpolicy_vnode_access2(cr, tvp, va.va_uid,
1283 va.va_mode << shift, mode));
1284 }
1285
1286 /*
1287 * See smbfs_setattr
1288 */
1289 static int
1290 smbfs_accessx(void *arg, int mode, cred_t *cr)
1291 {
1292 vnode_t *vp = arg;
1293 /*
1294 * Note: The caller has checked the current zone,
1295 * the SMI_DEAD and VFS_UNMOUNTED flags, etc.
1296 */
1297 return (smbfs_access_rwx(vp->v_vfsp, vp->v_type, mode, cr));
1298 }
1299
1300 /*
1301 * XXX
1302 * This op should support PSARC 2007/403, Modified Access Checks for CIFS
1303 */
1304 /* ARGSUSED */
1305 static int
1306 smbfs_access(vnode_t *vp, int mode, int flags, cred_t *cr, caller_context_t *ct)
1307 {
1308 vfs_t *vfsp;
1309 smbmntinfo_t *smi;
1310
1311 vfsp = vp->v_vfsp;
1312 smi = VFTOSMI(vfsp);
1313
1314 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
1315 return (EIO);
1316
1317 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED)
1318 return (EIO);
1319
1320 return (smbfs_access_rwx(vfsp, vp->v_type, mode, cr));
1321 }
1322
1323
1324 /*
1325 * Flush local dirty pages to stable storage on the server.
1326 *
1327 * If FNODSYNC is specified, then there is nothing to do because
1328 * metadata changes are not cached on the client before being
1329 * sent to the server.
1330 */
1331 /* ARGSUSED */
1332 static int
1333 smbfs_fsync(vnode_t *vp, int syncflag, cred_t *cr, caller_context_t *ct)
1334 {
1335 int error = 0;
1336 smbmntinfo_t *smi;
1337 smbnode_t *np;
1338 struct smb_cred scred;
1339
1340 np = VTOSMB(vp);
1341 smi = VTOSMI(vp);
1342
1343 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
1344 return (EIO);
1345
1346 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
1347 return (EIO);
1348
1349 if ((syncflag & FNODSYNC) || IS_SWAPVP(vp))
1350 return (0);
1351
1352 if ((syncflag & (FSYNC|FDSYNC)) == 0)
1353 return (0);
1354
1355 /* Shared lock for n_fid use in _flush */
1356 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
1357 return (EINTR);
1358 smb_credinit(&scred, cr);
1359
1360 error = smbfs_smb_flush(np, &scred);
1361
1362 smb_credrele(&scred);
1363 smbfs_rw_exit(&np->r_lkserlock);
1364
1365 return (error);
1366 }
1367
1368 /*
1369 * Last reference to vnode went away.
1370 */
1371 /* ARGSUSED */
1372 static void
1373 smbfs_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct)
1374 {
1375 smbnode_t *np;
1376 struct smb_cred scred;
1377
1378 /*
1379 * Don't "bail out" for VFS_UNMOUNTED here,
1380 * as we want to do cleanup, etc.
1381 * See also pcfs_inactive
1382 */
1383
1384 np = VTOSMB(vp);
1385
1386 /*
1387 * If this is coming from the wrong zone, we let someone in the right
1388 * zone take care of it asynchronously. We can get here due to
1389 * VN_RELE() being called from pageout() or fsflush(). This call may
1390 * potentially turn into an expensive no-op if, for instance, v_count
1391 * gets incremented in the meantime, but it's still correct.
1392 */
1393
1394 /*
1395 * Defend against the possibility that higher-level callers
1396 * might not correctly balance open and close calls. If we
1397 * get here with open references remaining, it means there
1398 * was a missing VOP_CLOSE somewhere. If that happens, do
1399 * the close here so we don't "leak" FIDs on the server.
1400 *
1401 * Exclusive lock for modifying n_fid stuff.
1402 * Don't want this one ever interruptible.
1403 */
1404 (void) smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, 0);
1405 smb_credinit(&scred, cr);
1406
1407 switch (np->n_ovtype) {
1408 case VNON:
1409 /* not open (OK) */
1410 break;
1411
1412 case VDIR:
1413 if (np->n_dirrefs == 0)
1414 break;
1415 SMBVDEBUG("open dir: refs %d path %s\n",
1416 np->n_dirrefs, np->n_rpath);
1417 /* Force last close. */
1418 np->n_dirrefs = 1;
1419 smbfs_rele_fid(np, &scred);
1420 break;
1421
1422 case VREG:
1423 if (np->n_fidrefs == 0)
1424 break;
1425 SMBVDEBUG("open file: refs %d id 0x%x path %s\n",
1426 np->n_fidrefs, np->n_fid, np->n_rpath);
1427 /* Force last close. */
1428 np->n_fidrefs = 1;
1429 smbfs_rele_fid(np, &scred);
1430 break;
1431
1432 default:
1433 SMBVDEBUG("bad n_ovtype %d\n", np->n_ovtype);
1434 np->n_ovtype = VNON;
1435 break;
1436 }
1437
1438 smb_credrele(&scred);
1439 smbfs_rw_exit(&np->r_lkserlock);
1440
1441 smbfs_addfree(np);
1442 }
1443
1444 /*
1445 * Remote file system operations having to do with directory manipulation.
1446 */
1447 /* ARGSUSED */
1448 static int
1449 smbfs_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct pathname *pnp,
1450 int flags, vnode_t *rdir, cred_t *cr, caller_context_t *ct,
1451 int *direntflags, pathname_t *realpnp)
1452 {
1453 vfs_t *vfs;
1454 smbmntinfo_t *smi;
1455 smbnode_t *dnp;
1456 int error;
1457
1458 vfs = dvp->v_vfsp;
1459 smi = VFTOSMI(vfs);
1460
1461 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
1462 return (EPERM);
1463
1464 if (smi->smi_flags & SMI_DEAD || vfs->vfs_flag & VFS_UNMOUNTED)
1465 return (EIO);
1466
1467 dnp = VTOSMB(dvp);
1468
1469 /*
1470 * Are we looking up extended attributes? If so, "dvp" is
1471 * the file or directory for which we want attributes, and
1472 * we need a lookup of the (faked up) attribute directory
1473 * before we lookup the rest of the path.
1474 */
1475 if (flags & LOOKUP_XATTR) {
1476 /*
1477 * Require the xattr mount option.
1478 */
1479 if ((vfs->vfs_flag & VFS_XATTR) == 0)
1480 return (EINVAL);
1481
1482 error = smbfs_get_xattrdir(dvp, vpp, cr, flags);
1483 return (error);
1484 }
1485
1486 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_READER, SMBINTR(dvp)))
1487 return (EINTR);
1488
1489 error = smbfslookup(dvp, nm, vpp, cr, 1, ct);
1490
1491 smbfs_rw_exit(&dnp->r_rwlock);
1492
1493 return (error);
1494 }
1495
1496 /* ARGSUSED */
1497 static int
1498 smbfslookup(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr,
1499 int cache_ok, caller_context_t *ct)
1500 {
1501 int error;
1502 int supplen; /* supported length */
1503 vnode_t *vp;
1504 smbnode_t *np;
1505 smbnode_t *dnp;
1506 smbmntinfo_t *smi;
1507 /* struct smb_vc *vcp; */
1508 const char *ill;
1509 const char *name = (const char *)nm;
1510 int nmlen = strlen(nm);
1511 int rplen;
1512 struct smb_cred scred;
1513 struct smbfattr fa;
1514
1515 smi = VTOSMI(dvp);
1516 dnp = VTOSMB(dvp);
1517
1518 ASSERT(curproc->p_zone == smi->smi_zone_ref.zref_zone);
1519
1520 #ifdef NOT_YET
1521 vcp = SSTOVC(smi->smi_share);
1522
1523 /* XXX: Should compute this once and store it in smbmntinfo_t */
1524 supplen = (SMB_DIALECT(vcp) >= SMB_DIALECT_LANMAN2_0) ? 255 : 12;
1525 #else
1526 supplen = 255;
1527 #endif
1528
1529 /*
1530 * RWlock must be held, either reader or writer.
1531 * XXX: Can we check without looking directly
1532 * inside the struct smbfs_rwlock_t?
1533 */
1534 ASSERT(dnp->r_rwlock.count != 0);
1535
1536 /*
1537 * If lookup is for "", just return dvp.
1538 * No need to perform any access checks.
1539 */
1540 if (nmlen == 0) {
1541 VN_HOLD(dvp);
1542 *vpp = dvp;
1543 return (0);
1544 }
1545
1546 /*
1547 * Can't do lookups in non-directories.
1548 */
1549 if (dvp->v_type != VDIR)
1550 return (ENOTDIR);
1551
1552 /*
1553 * Need search permission in the directory.
1554 */
1555 error = smbfs_access(dvp, VEXEC, 0, cr, ct);
1556 if (error)
1557 return (error);
1558
1559 /*
1560 * If lookup is for ".", just return dvp.
1561 * Access check was done above.
1562 */
1563 if (nmlen == 1 && name[0] == '.') {
1564 VN_HOLD(dvp);
1565 *vpp = dvp;
1566 return (0);
1567 }
1568
1569 /*
1570 * Now some sanity checks on the name.
1571 * First check the length.
1572 */
1573 if (nmlen > supplen)
1574 return (ENAMETOOLONG);
1575
1576 /*
1577 * Avoid surprises with characters that are
1578 * illegal in Windows file names.
1579 * Todo: CATIA mappings XXX
1580 */
1581 ill = illegal_chars;
1582 if (dnp->n_flag & N_XATTR)
1583 ill++; /* allow colon */
1584 if (strpbrk(nm, ill))
1585 return (EINVAL);
1586
1587 /*
1588 * Special handling for lookup of ".."
1589 *
1590 * We keep full pathnames (as seen on the server)
1591 * so we can just trim off the last component to
1592 * get the full pathname of the parent. Note:
1593 * We don't actually copy and modify, but just
1594 * compute the trimmed length and pass that with
1595 * the current dir path (not null terminated).
1596 *
1597 * We don't go over-the-wire to get attributes
1598 * for ".." because we know it's a directory,
1599 * and we can just leave the rest "stale"
1600 * until someone does a getattr.
1601 */
1602 if (nmlen == 2 && name[0] == '.' && name[1] == '.') {
1603 if (dvp->v_flag & VROOT) {
1604 /*
1605 * Already at the root. This can happen
1606 * with directory listings at the root,
1607 * which lookup "." and ".." to get the
1608 * inode numbers. Let ".." be the same
1609 * as "." in the FS root.
1610 */
1611 VN_HOLD(dvp);
1612 *vpp = dvp;
1613 return (0);
1614 }
1615
1616 /*
1617 * Special case for XATTR directory
1618 */
1619 if (dvp->v_flag & V_XATTRDIR) {
1620 error = smbfs_xa_parent(dvp, vpp);
1621 return (error);
1622 }
1623
1624 /*
1625 * Find the parent path length.
1626 */
1627 rplen = dnp->n_rplen;
1628 ASSERT(rplen > 0);
1629 while (--rplen >= 0) {
1630 if (dnp->n_rpath[rplen] == '\\')
1631 break;
1632 }
1633 if (rplen <= 0) {
1634 /* Found our way to the root. */
1635 vp = SMBTOV(smi->smi_root);
1636 VN_HOLD(vp);
1637 *vpp = vp;
1638 return (0);
1639 }
1640 np = smbfs_node_findcreate(smi,
1641 dnp->n_rpath, rplen, NULL, 0, 0,
1642 &smbfs_fattr0); /* force create */
1643 ASSERT(np != NULL);
1644 vp = SMBTOV(np);
1645 vp->v_type = VDIR;
1646
1647 /* Success! */
1648 *vpp = vp;
1649 return (0);
1650 }
1651
1652 /*
1653 * Normal lookup of a name under this directory.
1654 * Note we handled "", ".", ".." above.
1655 */
1656 if (cache_ok) {
1657 /*
1658 * The caller indicated that it's OK to use a
1659 * cached result for this lookup, so try to
1660 * reclaim a node from the smbfs node cache.
1661 */
1662 error = smbfslookup_cache(dvp, nm, nmlen, &vp, cr);
1663 if (error)
1664 return (error);
1665 if (vp != NULL) {
1666 /* hold taken in lookup_cache */
1667 *vpp = vp;
1668 return (0);
1669 }
1670 }
1671
1672 /*
1673 * OK, go over-the-wire to get the attributes,
1674 * then create the node.
1675 */
1676 smb_credinit(&scred, cr);
1677 /* Note: this can allocate a new "name" */
1678 error = smbfs_smb_lookup(dnp, &name, &nmlen, &fa, &scred);
1679 smb_credrele(&scred);
1680 if (error == ENOTDIR) {
1681 /*
1682 * Lookup failed because this directory was
1683 * removed or renamed by another client.
1684 * Remove any cached attributes under it.
1685 */
1686 smbfs_attrcache_remove(dnp);
1687 smbfs_attrcache_prune(dnp);
1688 }
1689 if (error)
1690 goto out;
1691
1692 error = smbfs_nget(dvp, name, nmlen, &fa, &vp);
1693 if (error)
1694 goto out;
1695
1696 /* Success! */
1697 *vpp = vp;
1698
1699 out:
1700 /* smbfs_smb_lookup may have allocated name. */
1701 if (name != nm)
1702 smbfs_name_free(name, nmlen);
1703
1704 return (error);
1705 }
1706
1707 /*
1708 * smbfslookup_cache
1709 *
1710 * Try to reclaim a node from the smbfs node cache.
1711 * Some statistics for DEBUG.
1712 *
1713 * This mechanism lets us avoid many of the five (or more)
1714 * OtW lookup calls per file seen with "ls -l" if we search
1715 * the smbfs node cache for recently inactive(ated) nodes.
1716 */
1717 #ifdef DEBUG
1718 int smbfs_lookup_cache_calls = 0;
1719 int smbfs_lookup_cache_error = 0;
1720 int smbfs_lookup_cache_miss = 0;
1721 int smbfs_lookup_cache_stale = 0;
1722 int smbfs_lookup_cache_hits = 0;
1723 #endif /* DEBUG */
1724
1725 /* ARGSUSED */
1726 static int
1727 smbfslookup_cache(vnode_t *dvp, char *nm, int nmlen,
1728 vnode_t **vpp, cred_t *cr)
1729 {
1730 struct vattr va;
1731 smbnode_t *dnp;
1732 smbnode_t *np;
1733 vnode_t *vp;
1734 int error;
1735 char sep;
1736
1737 dnp = VTOSMB(dvp);
1738 *vpp = NULL;
1739
1740 #ifdef DEBUG
1741 smbfs_lookup_cache_calls++;
1742 #endif
1743
1744 /*
1745 * First make sure we can get attributes for the
1746 * directory. Cached attributes are OK here.
1747 * If we removed or renamed the directory, this
1748 * will return ENOENT. If someone else removed
1749 * this directory or file, we'll find out when we
1750 * try to open or get attributes.
1751 */
1752 va.va_mask = AT_TYPE | AT_MODE;
1753 error = smbfsgetattr(dvp, &va, cr);
1754 if (error) {
1755 #ifdef DEBUG
1756 smbfs_lookup_cache_error++;
1757 #endif
1758 return (error);
1759 }
1760
1761 /*
1762 * Passing NULL smbfattr here so we will
1763 * just look, not create.
1764 */
1765 sep = SMBFS_DNP_SEP(dnp);
1766 np = smbfs_node_findcreate(dnp->n_mount,
1767 dnp->n_rpath, dnp->n_rplen,
1768 nm, nmlen, sep, NULL);
1769 if (np == NULL) {
1770 #ifdef DEBUG
1771 smbfs_lookup_cache_miss++;
1772 #endif
1773 return (0);
1774 }
1775
1776 /*
1777 * Found it. Attributes still valid?
1778 */
1779 vp = SMBTOV(np);
1780 if (np->r_attrtime <= gethrtime()) {
1781 /* stale */
1782 #ifdef DEBUG
1783 smbfs_lookup_cache_stale++;
1784 #endif
1785 VN_RELE(vp);
1786 return (0);
1787 }
1788
1789 /*
1790 * Success!
1791 * Caller gets hold from smbfs_node_findcreate
1792 */
1793 #ifdef DEBUG
1794 smbfs_lookup_cache_hits++;
1795 #endif
1796 *vpp = vp;
1797 return (0);
1798 }
1799
1800 /*
1801 * XXX
1802 * vsecattr_t is new to build 77, and we need to eventually support
1803 * it in order to create an ACL when an object is created.
1804 *
1805 * This op should support the new FIGNORECASE flag for case-insensitive
1806 * lookups, per PSARC 2007/244.
1807 */
1808 /* ARGSUSED */
1809 static int
1810 smbfs_create(vnode_t *dvp, char *nm, struct vattr *va, enum vcexcl exclusive,
1811 int mode, vnode_t **vpp, cred_t *cr, int lfaware, caller_context_t *ct,
1812 vsecattr_t *vsecp)
1813 {
1814 int error;
1815 int cerror;
1816 vfs_t *vfsp;
1817 vnode_t *vp;
1818 #ifdef NOT_YET
1819 smbnode_t *np;
1820 #endif
1821 smbnode_t *dnp;
1822 smbmntinfo_t *smi;
1823 struct vattr vattr;
1824 struct smbfattr fattr;
1825 struct smb_cred scred;
1826 const char *name = (const char *)nm;
1827 int nmlen = strlen(nm);
1828 uint32_t disp;
1829 uint16_t fid;
1830 int xattr;
1831
1832 vfsp = dvp->v_vfsp;
1833 smi = VFTOSMI(vfsp);
1834 dnp = VTOSMB(dvp);
1835 vp = NULL;
1836
1837 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
1838 return (EPERM);
1839
1840 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED)
1841 return (EIO);
1842
1843 /*
1844 * Note: this may break mknod(2) calls to create a directory,
1845 * but that's obscure use. Some other filesystems do this.
1846 * XXX: Later, redirect VDIR type here to _mkdir.
1847 */
1848 if (va->va_type != VREG)
1849 return (EINVAL);
1850
1851 /*
1852 * If the pathname is "", just use dvp, no checks.
1853 * Do this outside of the rwlock (like zfs).
1854 */
1855 if (nmlen == 0) {
1856 VN_HOLD(dvp);
1857 *vpp = dvp;
1858 return (0);
1859 }
1860
1861 /* Don't allow "." or ".." through here. */
1862 if ((nmlen == 1 && name[0] == '.') ||
1863 (nmlen == 2 && name[0] == '.' && name[1] == '.'))
1864 return (EISDIR);
1865
1866 /*
1867 * We make a copy of the attributes because the caller does not
1868 * expect us to change what va points to.
1869 */
1870 vattr = *va;
1871
1872 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp)))
1873 return (EINTR);
1874 smb_credinit(&scred, cr);
1875
1876 /*
1877 * XXX: Do we need r_lkserlock too?
1878 * No use of any shared fid or fctx...
1879 */
1880
1881 /*
1882 * NFS needs to go over the wire, just to be sure whether the
1883 * file exists or not. Using a cached result is dangerous in
1884 * this case when making a decision regarding existence.
1885 *
1886 * The SMB protocol does NOT really need to go OTW here
1887 * thanks to the expressive NTCREATE disposition values.
1888 * Unfortunately, to do Unix access checks correctly,
1889 * we need to know if the object already exists.
1890 * When the object does not exist, we need VWRITE on
1891 * the directory. Note: smbfslookup() checks VEXEC.
1892 */
1893 error = smbfslookup(dvp, nm, &vp, cr, 0, ct);
1894 if (error == 0) {
1895 /*
1896 * The file already exists. Error?
1897 * NB: have a hold from smbfslookup
1898 */
1899 if (exclusive == EXCL) {
1900 error = EEXIST;
1901 VN_RELE(vp);
1902 goto out;
1903 }
1904 /*
1905 * Verify requested access.
1906 */
1907 error = smbfs_access(vp, mode, 0, cr, ct);
1908 if (error) {
1909 VN_RELE(vp);
1910 goto out;
1911 }
1912
1913 /*
1914 * Truncate (if requested).
1915 */
1916 if ((vattr.va_mask & AT_SIZE) && vattr.va_size == 0) {
1917 vattr.va_mask = AT_SIZE;
1918 error = smbfssetattr(vp, &vattr, 0, cr);
1919 if (error) {
1920 VN_RELE(vp);
1921 goto out;
1922 }
1923 }
1924 /* Success! */
1925 #ifdef NOT_YET
1926 vnevent_create(vp, ct);
1927 #endif
1928 *vpp = vp;
1929 goto out;
1930 }
1931
1932 /*
1933 * The file did not exist. Need VWRITE in the directory.
1934 */
1935 error = smbfs_access(dvp, VWRITE, 0, cr, ct);
1936 if (error)
1937 goto out;
1938
1939 /*
1940 * Now things get tricky. We also need to check the
1941 * requested open mode against the file we may create.
1942 * See comments at smbfs_access_rwx
1943 */
1944 error = smbfs_access_rwx(vfsp, VREG, mode, cr);
1945 if (error)
1946 goto out;
1947
1948 /*
1949 * Now the code derived from Darwin,
1950 * but with greater use of NT_CREATE
1951 * disposition options. Much changed.
1952 *
1953 * Create (or open) a new child node.
1954 * Note we handled "." and ".." above.
1955 */
1956
1957 if (exclusive == EXCL)
1958 disp = NTCREATEX_DISP_CREATE;
1959 else {
1960 /* Truncate regular files if requested. */
1961 if ((va->va_type == VREG) &&
1962 (va->va_mask & AT_SIZE) &&
1963 (va->va_size == 0))
1964 disp = NTCREATEX_DISP_OVERWRITE_IF;
1965 else
1966 disp = NTCREATEX_DISP_OPEN_IF;
1967 }
1968 xattr = (dnp->n_flag & N_XATTR) ? 1 : 0;
1969 error = smbfs_smb_create(dnp,
1970 name, nmlen, xattr,
1971 disp, &scred, &fid);
1972 if (error)
1973 goto out;
1974
1975 /*
1976 * XXX: Missing some code here to deal with
1977 * the case where we opened an existing file,
1978 * it's size is larger than 32-bits, and we're
1979 * setting the size from a process that's not
1980 * aware of large file offsets. i.e.
1981 * from the NFS3 code:
1982 */
1983 #if NOT_YET /* XXX */
1984 if ((vattr.va_mask & AT_SIZE) &&
1985 vp->v_type == VREG) {
1986 np = VTOSMB(vp);
1987 /*
1988 * Check here for large file handled
1989 * by LF-unaware process (as
1990 * ufs_create() does)
1991 */
1992 if (!(lfaware & FOFFMAX)) {
1993 mutex_enter(&np->r_statelock);
1994 if (np->r_size > MAXOFF32_T)
1995 error = EOVERFLOW;
1996 mutex_exit(&np->r_statelock);
1997 }
1998 if (!error) {
1999 vattr.va_mask = AT_SIZE;
2000 error = smbfssetattr(vp,
2001 &vattr, 0, cr);
2002 }
2003 }
2004 #endif /* XXX */
2005 /*
2006 * Should use the fid to get/set the size
2007 * while we have it opened here. See above.
2008 */
2009
2010 cerror = smbfs_smb_close(smi->smi_share, fid, NULL, &scred);
2011 if (cerror)
2012 SMBVDEBUG("error %d closing %s\\%s\n",
2013 cerror, dnp->n_rpath, name);
2014
2015 /*
2016 * In the open case, the name may differ a little
2017 * from what we passed to create (case, etc.)
2018 * so call lookup to get the (opened) name.
2019 *
2020 * XXX: Could avoid this extra lookup if the
2021 * "createact" result from NT_CREATE says we
2022 * created the object.
2023 */
2024 error = smbfs_smb_lookup(dnp, &name, &nmlen, &fattr, &scred);
2025 if (error)
2026 goto out;
2027
2028 /* update attr and directory cache */
2029 smbfs_attr_touchdir(dnp);
2030
2031 error = smbfs_nget(dvp, name, nmlen, &fattr, &vp);
2032 if (error)
2033 goto out;
2034
2035 /* XXX invalidate pages if we truncated? */
2036
2037 /* Success! */
2038 *vpp = vp;
2039 error = 0;
2040
2041 out:
2042 smb_credrele(&scred);
2043 smbfs_rw_exit(&dnp->r_rwlock);
2044 if (name != nm)
2045 smbfs_name_free(name, nmlen);
2046 return (error);
2047 }
2048
2049 /*
2050 * XXX
2051 * This op should support the new FIGNORECASE flag for case-insensitive
2052 * lookups, per PSARC 2007/244.
2053 */
2054 /* ARGSUSED */
2055 static int
2056 smbfs_remove(vnode_t *dvp, char *nm, cred_t *cr, caller_context_t *ct,
2057 int flags)
2058 {
2059 int error;
2060 vnode_t *vp;
2061 smbnode_t *np;
2062 smbnode_t *dnp;
2063 struct smb_cred scred;
2064 /* enum smbfsstat status; */
2065 smbmntinfo_t *smi;
2066
2067 smi = VTOSMI(dvp);
2068
2069 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
2070 return (EPERM);
2071
2072 if (smi->smi_flags & SMI_DEAD || dvp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2073 return (EIO);
2074
2075 dnp = VTOSMB(dvp);
2076 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp)))
2077 return (EINTR);
2078 smb_credinit(&scred, cr);
2079
2080 /*
2081 * Verify access to the dirctory.
2082 */
2083 error = smbfs_access(dvp, VWRITE|VEXEC, 0, cr, ct);
2084 if (error)
2085 goto out;
2086
2087 /*
2088 * NOTE: the darwin code gets the "vp" passed in so it looks
2089 * like the "vp" has probably been "lookup"ed by the VFS layer.
2090 * It looks like we will need to lookup the vp to check the
2091 * caches and check if the object being deleted is a directory.
2092 */
2093 error = smbfslookup(dvp, nm, &vp, cr, 0, ct);
2094 if (error)
2095 goto out;
2096
2097 /* Never allow link/unlink directories on CIFS. */
2098 if (vp->v_type == VDIR) {
2099 VN_RELE(vp);
2100 error = EPERM;
2101 goto out;
2102 }
2103
2104 /*
2105 * Now we have the real reference count on the vnode
2106 * Do we have the file open?
2107 */
2108 np = VTOSMB(vp);
2109 mutex_enter(&np->r_statelock);
2110 if ((vp->v_count > 1) && (np->n_fidrefs > 0)) {
2111 /*
2112 * NFS does a rename on remove here.
2113 * Probably not applicable for SMB.
2114 * Like Darwin, just return EBUSY.
2115 *
2116 * XXX: Todo - Use Trans2rename, and
2117 * if that fails, ask the server to
2118 * set the delete-on-close flag.
2119 */
2120 mutex_exit(&np->r_statelock);
2121 error = EBUSY;
2122 } else {
2123 smbfs_attrcache_rm_locked(np);
2124 mutex_exit(&np->r_statelock);
2125
2126 error = smbfs_smb_delete(np, &scred, NULL, 0, 0);
2127
2128 /*
2129 * If the file should no longer exist, discard
2130 * any cached attributes under this node.
2131 */
2132 switch (error) {
2133 case 0:
2134 case ENOENT:
2135 case ENOTDIR:
2136 smbfs_attrcache_prune(np);
2137 break;
2138 }
2139 }
2140
2141 VN_RELE(vp);
2142
2143 out:
2144 smb_credrele(&scred);
2145 smbfs_rw_exit(&dnp->r_rwlock);
2146
2147 return (error);
2148 }
2149
2150
2151 /*
2152 * XXX
2153 * This op should support the new FIGNORECASE flag for case-insensitive
2154 * lookups, per PSARC 2007/244.
2155 */
2156 /* ARGSUSED */
2157 static int
2158 smbfs_rename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm, cred_t *cr,
2159 caller_context_t *ct, int flags)
2160 {
2161 /* vnode_t *realvp; */
2162
2163 if (curproc->p_zone != VTOSMI(odvp)->smi_zone_ref.zref_zone ||
2164 curproc->p_zone != VTOSMI(ndvp)->smi_zone_ref.zref_zone)
2165 return (EPERM);
2166
2167 if (VTOSMI(odvp)->smi_flags & SMI_DEAD ||
2168 VTOSMI(ndvp)->smi_flags & SMI_DEAD ||
2169 odvp->v_vfsp->vfs_flag & VFS_UNMOUNTED ||
2170 ndvp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2171 return (EIO);
2172
2173 return (smbfsrename(odvp, onm, ndvp, nnm, cr, ct));
2174 }
2175
2176 /*
2177 * smbfsrename does the real work of renaming in SMBFS
2178 */
2179 /* ARGSUSED */
2180 static int
2181 smbfsrename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm, cred_t *cr,
2182 caller_context_t *ct)
2183 {
2184 int error;
2185 int nvp_locked = 0;
2186 vnode_t *nvp = NULL;
2187 vnode_t *ovp = NULL;
2188 smbnode_t *onp;
2189 smbnode_t *nnp;
2190 smbnode_t *odnp;
2191 smbnode_t *ndnp;
2192 struct smb_cred scred;
2193 /* enum smbfsstat status; */
2194
2195 ASSERT(curproc->p_zone == VTOSMI(odvp)->smi_zone_ref.zref_zone);
2196
2197 if (strcmp(onm, ".") == 0 || strcmp(onm, "..") == 0 ||
2198 strcmp(nnm, ".") == 0 || strcmp(nnm, "..") == 0)
2199 return (EINVAL);
2200
2201 /*
2202 * Check that everything is on the same filesystem.
2203 * vn_rename checks the fsid's, but in case we don't
2204 * fill those in correctly, check here too.
2205 */
2206 if (odvp->v_vfsp != ndvp->v_vfsp)
2207 return (EXDEV);
2208
2209 odnp = VTOSMB(odvp);
2210 ndnp = VTOSMB(ndvp);
2211
2212 /*
2213 * Avoid deadlock here on old vs new directory nodes
2214 * by always taking the locks in order of address.
2215 * The order is arbitrary, but must be consistent.
2216 */
2217 if (odnp < ndnp) {
2218 if (smbfs_rw_enter_sig(&odnp->r_rwlock, RW_WRITER,
2219 SMBINTR(odvp)))
2220 return (EINTR);
2221 if (smbfs_rw_enter_sig(&ndnp->r_rwlock, RW_WRITER,
2222 SMBINTR(ndvp))) {
2223 smbfs_rw_exit(&odnp->r_rwlock);
2224 return (EINTR);
2225 }
2226 } else {
2227 if (smbfs_rw_enter_sig(&ndnp->r_rwlock, RW_WRITER,
2228 SMBINTR(ndvp)))
2229 return (EINTR);
2230 if (smbfs_rw_enter_sig(&odnp->r_rwlock, RW_WRITER,
2231 SMBINTR(odvp))) {
2232 smbfs_rw_exit(&ndnp->r_rwlock);
2233 return (EINTR);
2234 }
2235 }
2236 smb_credinit(&scred, cr);
2237 /*
2238 * No returns after this point (goto out)
2239 */
2240
2241 /*
2242 * Need write access on source and target.
2243 * Server takes care of most checks.
2244 */
2245 error = smbfs_access(odvp, VWRITE|VEXEC, 0, cr, ct);
2246 if (error)
2247 goto out;
2248 if (odvp != ndvp) {
2249 error = smbfs_access(ndvp, VWRITE, 0, cr, ct);
2250 if (error)
2251 goto out;
2252 }
2253
2254 /*
2255 * Lookup the source name. Must already exist.
2256 */
2257 error = smbfslookup(odvp, onm, &ovp, cr, 0, ct);
2258 if (error)
2259 goto out;
2260
2261 /*
2262 * Lookup the target file. If it exists, it needs to be
2263 * checked to see whether it is a mount point and whether
2264 * it is active (open).
2265 */
2266 error = smbfslookup(ndvp, nnm, &nvp, cr, 0, ct);
2267 if (!error) {
2268 /*
2269 * Target (nvp) already exists. Check that it
2270 * has the same type as the source. The server
2271 * will check this also, (and more reliably) but
2272 * this lets us return the correct error codes.
2273 */
2274 if (ovp->v_type == VDIR) {
2275 if (nvp->v_type != VDIR) {
2276 error = ENOTDIR;
2277 goto out;
2278 }
2279 } else {
2280 if (nvp->v_type == VDIR) {
2281 error = EISDIR;
2282 goto out;
2283 }
2284 }
2285
2286 /*
2287 * POSIX dictates that when the source and target
2288 * entries refer to the same file object, rename
2289 * must do nothing and exit without error.
2290 */
2291 if (ovp == nvp) {
2292 error = 0;
2293 goto out;
2294 }
2295
2296 /*
2297 * Also must ensure the target is not a mount point,
2298 * and keep mount/umount away until we're done.
2299 */
2300 if (vn_vfsrlock(nvp)) {
2301 error = EBUSY;
2302 goto out;
2303 }
2304 nvp_locked = 1;
2305 if (vn_mountedvfs(nvp) != NULL) {
2306 error = EBUSY;
2307 goto out;
2308 }
2309
2310 /*
2311 * CIFS gives a SHARING_VIOLATION error when
2312 * trying to rename onto an exising object,
2313 * so try to remove the target first.
2314 * (Only for files, not directories.)
2315 */
2316 if (nvp->v_type == VDIR) {
2317 error = EEXIST;
2318 goto out;
2319 }
2320
2321 /*
2322 * Nodes that are "not active" here have v_count=2
2323 * because vn_renameat (our caller) did a lookup on
2324 * both the source and target before this call.
2325 * Otherwise this similar to smbfs_remove.
2326 */
2327 nnp = VTOSMB(nvp);
2328 mutex_enter(&nnp->r_statelock);
2329 if ((nvp->v_count > 2) && (nnp->n_fidrefs > 0)) {
2330 /*
2331 * The target file exists, is not the same as
2332 * the source file, and is active. Other FS
2333 * implementations unlink the target here.
2334 * For SMB, we don't assume we can remove an
2335 * open file. Return an error instead.
2336 */
2337 mutex_exit(&nnp->r_statelock);
2338 error = EBUSY;
2339 goto out;
2340 }
2341
2342 /*
2343 * Target file is not active. Try to remove it.
2344 */
2345 smbfs_attrcache_rm_locked(nnp);
2346 mutex_exit(&nnp->r_statelock);
2347
2348 error = smbfs_smb_delete(nnp, &scred, NULL, 0, 0);
2349
2350 /*
2351 * Similar to smbfs_remove
2352 */
2353 switch (error) {
2354 case 0:
2355 case ENOENT:
2356 case ENOTDIR:
2357 smbfs_attrcache_prune(nnp);
2358 break;
2359 }
2360
2361 if (error)
2362 goto out;
2363 /*
2364 * OK, removed the target file. Continue as if
2365 * lookup target had failed (nvp == NULL).
2366 */
2367 vn_vfsunlock(nvp);
2368 nvp_locked = 0;
2369 VN_RELE(nvp);
2370 nvp = NULL;
2371 } /* nvp */
2372
2373 onp = VTOSMB(ovp);
2374 smbfs_attrcache_remove(onp);
2375
2376 error = smbfs_smb_rename(onp, ndnp, nnm, strlen(nnm), &scred);
2377
2378 /*
2379 * If the old name should no longer exist,
2380 * discard any cached attributes under it.
2381 */
2382 if (error == 0)
2383 smbfs_attrcache_prune(onp);
2384
2385 out:
2386 if (nvp) {
2387 if (nvp_locked)
2388 vn_vfsunlock(nvp);
2389 VN_RELE(nvp);
2390 }
2391 if (ovp)
2392 VN_RELE(ovp);
2393
2394 smb_credrele(&scred);
2395 smbfs_rw_exit(&odnp->r_rwlock);
2396 smbfs_rw_exit(&ndnp->r_rwlock);
2397
2398 return (error);
2399 }
2400
2401 /*
2402 * XXX
2403 * vsecattr_t is new to build 77, and we need to eventually support
2404 * it in order to create an ACL when an object is created.
2405 *
2406 * This op should support the new FIGNORECASE flag for case-insensitive
2407 * lookups, per PSARC 2007/244.
2408 */
2409 /* ARGSUSED */
2410 static int
2411 smbfs_mkdir(vnode_t *dvp, char *nm, struct vattr *va, vnode_t **vpp,
2412 cred_t *cr, caller_context_t *ct, int flags, vsecattr_t *vsecp)
2413 {
2414 vnode_t *vp;
2415 struct smbnode *dnp = VTOSMB(dvp);
2416 struct smbmntinfo *smi = VTOSMI(dvp);
2417 struct smb_cred scred;
2418 struct smbfattr fattr;
2419 const char *name = (const char *) nm;
2420 int nmlen = strlen(name);
2421 int error, hiderr;
2422
2423 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
2424 return (EPERM);
2425
2426 if (smi->smi_flags & SMI_DEAD || dvp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2427 return (EIO);
2428
2429 if ((nmlen == 1 && name[0] == '.') ||
2430 (nmlen == 2 && name[0] == '.' && name[1] == '.'))
2431 return (EEXIST);
2432
2433 /* Only plain files are allowed in V_XATTRDIR. */
2434 if (dvp->v_flag & V_XATTRDIR)
2435 return (EINVAL);
2436
2437 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp)))
2438 return (EINTR);
2439 smb_credinit(&scred, cr);
2440
2441 /*
2442 * XXX: Do we need r_lkserlock too?
2443 * No use of any shared fid or fctx...
2444 */
2445
2446 /*
2447 * Require write access in the containing directory.
2448 */
2449 error = smbfs_access(dvp, VWRITE, 0, cr, ct);
2450 if (error)
2451 goto out;
2452
2453 error = smbfs_smb_mkdir(dnp, name, nmlen, &scred);
2454 if (error)
2455 goto out;
2456
2457 error = smbfs_smb_lookup(dnp, &name, &nmlen, &fattr, &scred);
2458 if (error)
2459 goto out;
2460
2461 smbfs_attr_touchdir(dnp);
2462
2463 error = smbfs_nget(dvp, name, nmlen, &fattr, &vp);
2464 if (error)
2465 goto out;
2466
2467 if (name[0] == '.')
2468 if ((hiderr = smbfs_smb_hideit(VTOSMB(vp), NULL, 0, &scred)))
2469 SMBVDEBUG("hide failure %d\n", hiderr);
2470
2471 /* Success! */
2472 *vpp = vp;
2473 error = 0;
2474 out:
2475 smb_credrele(&scred);
2476 smbfs_rw_exit(&dnp->r_rwlock);
2477
2478 if (name != nm)
2479 smbfs_name_free(name, nmlen);
2480
2481 return (error);
2482 }
2483
2484 /*
2485 * XXX
2486 * This op should support the new FIGNORECASE flag for case-insensitive
2487 * lookups, per PSARC 2007/244.
2488 */
2489 /* ARGSUSED */
2490 static int
2491 smbfs_rmdir(vnode_t *dvp, char *nm, vnode_t *cdir, cred_t *cr,
2492 caller_context_t *ct, int flags)
2493 {
2494 vnode_t *vp = NULL;
2495 int vp_locked = 0;
2496 struct smbmntinfo *smi = VTOSMI(dvp);
2497 struct smbnode *dnp = VTOSMB(dvp);
2498 struct smbnode *np;
2499 struct smb_cred scred;
2500 int error;
2501
2502 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
2503 return (EPERM);
2504
2505 if (smi->smi_flags & SMI_DEAD || dvp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2506 return (EIO);
2507
2508 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp)))
2509 return (EINTR);
2510 smb_credinit(&scred, cr);
2511
2512 /*
2513 * Require w/x access in the containing directory.
2514 * Server handles all other access checks.
2515 */
2516 error = smbfs_access(dvp, VEXEC|VWRITE, 0, cr, ct);
2517 if (error)
2518 goto out;
2519
2520 /*
2521 * First lookup the entry to be removed.
2522 */
2523 error = smbfslookup(dvp, nm, &vp, cr, 0, ct);
2524 if (error)
2525 goto out;
2526 np = VTOSMB(vp);
2527
2528 /*
2529 * Disallow rmdir of "." or current dir, or the FS root.
2530 * Also make sure it's a directory, not a mount point,
2531 * and lock to keep mount/umount away until we're done.
2532 */
2533 if ((vp == dvp) || (vp == cdir) || (vp->v_flag & VROOT)) {
2534 error = EINVAL;
2535 goto out;
2536 }
2537 if (vp->v_type != VDIR) {
2538 error = ENOTDIR;
2539 goto out;
2540 }
2541 if (vn_vfsrlock(vp)) {
2542 error = EBUSY;
2543 goto out;
2544 }
2545 vp_locked = 1;
2546 if (vn_mountedvfs(vp) != NULL) {
2547 error = EBUSY;
2548 goto out;
2549 }
2550
2551 smbfs_attrcache_remove(np);
2552 error = smbfs_smb_rmdir(np, &scred);
2553
2554 /*
2555 * Similar to smbfs_remove
2556 */
2557 switch (error) {
2558 case 0:
2559 case ENOENT:
2560 case ENOTDIR:
2561 smbfs_attrcache_prune(np);
2562 break;
2563 }
2564
2565 if (error)
2566 goto out;
2567
2568 mutex_enter(&np->r_statelock);
2569 dnp->n_flag |= NMODIFIED;
2570 mutex_exit(&np->r_statelock);
2571 smbfs_attr_touchdir(dnp);
2572 smbfs_rmhash(np);
2573
2574 out:
2575 if (vp) {
2576 if (vp_locked)
2577 vn_vfsunlock(vp);
2578 VN_RELE(vp);
2579 }
2580 smb_credrele(&scred);
2581 smbfs_rw_exit(&dnp->r_rwlock);
2582
2583 return (error);
2584 }
2585
2586
2587 /* ARGSUSED */
2588 static int
2589 smbfs_readdir(vnode_t *vp, struct uio *uiop, cred_t *cr, int *eofp,
2590 caller_context_t *ct, int flags)
2591 {
2592 struct smbnode *np = VTOSMB(vp);
2593 int error = 0;
2594 smbmntinfo_t *smi;
2595
2596 smi = VTOSMI(vp);
2597
2598 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
2599 return (EIO);
2600
2601 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2602 return (EIO);
2603
2604 /*
2605 * Require read access in the directory.
2606 */
2607 error = smbfs_access(vp, VREAD, 0, cr, ct);
2608 if (error)
2609 return (error);
2610
2611 ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_READER));
2612
2613 /*
2614 * XXX: Todo readdir cache here
2615 * Note: NFS code is just below this.
2616 *
2617 * I am serializing the entire readdir opreation
2618 * now since we have not yet implemented readdir
2619 * cache. This fix needs to be revisited once
2620 * we implement readdir cache.
2621 */
2622 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, SMBINTR(vp)))
2623 return (EINTR);
2624
2625 error = smbfs_readvdir(vp, uiop, cr, eofp, ct);
2626
2627 smbfs_rw_exit(&np->r_lkserlock);
2628
2629 return (error);
2630 }
2631
2632 /* ARGSUSED */
2633 static int
2634 smbfs_readvdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp,
2635 caller_context_t *ct)
2636 {
2637 /*
2638 * Note: "limit" tells the SMB-level FindFirst/FindNext
2639 * functions how many directory entries to request in
2640 * each OtW call. It needs to be large enough so that
2641 * we don't make lots of tiny OtW requests, but there's
2642 * no point making it larger than the maximum number of
2643 * OtW entries that would fit in a maximum sized trans2
2644 * response (64k / 48). Beyond that, it's just tuning.
2645 * WinNT used 512, Win2k used 1366. We use 1000.
2646 */
2647 static const int limit = 1000;
2648 /* Largest possible dirent size. */
2649 static const size_t dbufsiz = DIRENT64_RECLEN(SMB_MAXFNAMELEN);
2650 struct smb_cred scred;
2651 vnode_t *newvp;
2652 struct smbnode *np = VTOSMB(vp);
2653 struct smbfs_fctx *ctx;
2654 struct dirent64 *dp;
2655 ssize_t save_resid;
2656 offset_t save_offset; /* 64 bits */
2657 int offset; /* yes, 32 bits */
2658 int nmlen, error;
2659 ushort_t reclen;
2660
2661 ASSERT(curproc->p_zone == VTOSMI(vp)->smi_zone_ref.zref_zone);
2662
2663 /* Make sure we serialize for n_dirseq use. */
2664 ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_WRITER));
2665
2666 /*
2667 * Make sure smbfs_open filled in n_dirseq
2668 */
2669 if (np->n_dirseq == NULL)
2670 return (EBADF);
2671
2672 /* Check for overflow of (32-bit) directory offset. */
2673 if (uio->uio_loffset < 0 || uio->uio_loffset > INT32_MAX ||
2674 (uio->uio_loffset + uio->uio_resid) > INT32_MAX)
2675 return (EINVAL);
2676
2677 /* Require space for at least one dirent. */
2678 if (uio->uio_resid < dbufsiz)
2679 return (EINVAL);
2680
2681 SMBVDEBUG("dirname='%s'\n", np->n_rpath);
2682 smb_credinit(&scred, cr);
2683 dp = kmem_alloc(dbufsiz, KM_SLEEP);
2684
2685 save_resid = uio->uio_resid;
2686 save_offset = uio->uio_loffset;
2687 offset = uio->uio_offset;
2688 SMBVDEBUG("in: offset=%d, resid=%d\n",
2689 (int)uio->uio_offset, (int)uio->uio_resid);
2690 error = 0;
2691
2692 /*
2693 * Generate the "." and ".." entries here so we can
2694 * (1) make sure they appear (but only once), and
2695 * (2) deal with getting their I numbers which the
2696 * findnext below does only for normal names.
2697 */
2698 while (offset < FIRST_DIROFS) {
2699 /*
2700 * Tricky bit filling in the first two:
2701 * offset 0 is ".", offset 1 is ".."
2702 * so strlen of these is offset+1.
2703 */
2704 reclen = DIRENT64_RECLEN(offset + 1);
2705 if (uio->uio_resid < reclen)
2706 goto out;
2707 bzero(dp, reclen);
2708 dp->d_reclen = reclen;
2709 dp->d_name[0] = '.';
2710 dp->d_name[1] = '.';
2711 dp->d_name[offset + 1] = '\0';
2712 /*
2713 * Want the real I-numbers for the "." and ".."
2714 * entries. For these two names, we know that
2715 * smbfslookup can get the nodes efficiently.
2716 */
2717 error = smbfslookup(vp, dp->d_name, &newvp, cr, 1, ct);
2718 if (error) {
2719 dp->d_ino = np->n_ino + offset; /* fiction */
2720 } else {
2721 dp->d_ino = VTOSMB(newvp)->n_ino;
2722 VN_RELE(newvp);
2723 }
2724 /*
2725 * Note: d_off is the offset that a user-level program
2726 * should seek to for reading the NEXT directory entry.
2727 * See libc: readdir, telldir, seekdir
2728 */
2729 dp->d_off = offset + 1;
2730 error = uiomove(dp, reclen, UIO_READ, uio);
2731 if (error)
2732 goto out;
2733 /*
2734 * Note: uiomove updates uio->uio_offset,
2735 * but we want it to be our "cookie" value,
2736 * which just counts dirents ignoring size.
2737 */
2738 uio->uio_offset = ++offset;
2739 }
2740
2741 /*
2742 * If there was a backward seek, we have to reopen.
2743 */
2744 if (offset < np->n_dirofs) {
2745 SMBVDEBUG("Reopening search %d:%d\n",
2746 offset, np->n_dirofs);
2747 error = smbfs_smb_findopen(np, "*", 1,
2748 SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_DIR,
2749 &scred, &ctx);
2750 if (error) {
2751 SMBVDEBUG("can not open search, error = %d", error);
2752 goto out;
2753 }
2754 /* free the old one */
2755 (void) smbfs_smb_findclose(np->n_dirseq, &scred);
2756 /* save the new one */
2757 np->n_dirseq = ctx;
2758 np->n_dirofs = FIRST_DIROFS;
2759 } else {
2760 ctx = np->n_dirseq;
2761 }
2762
2763 /*
2764 * Skip entries before the requested offset.
2765 */
2766 while (np->n_dirofs < offset) {
2767 error = smbfs_smb_findnext(ctx, limit, &scred);
2768 if (error != 0)
2769 goto out;
2770 np->n_dirofs++;
2771 }
2772
2773 /*
2774 * While there's room in the caller's buffer:
2775 * get a directory entry from SMB,
2776 * convert to a dirent, copyout.
2777 * We stop when there is no longer room for a
2778 * maximum sized dirent because we must decide
2779 * before we know anything about the next entry.
2780 */
2781 while (uio->uio_resid >= dbufsiz) {
2782 error = smbfs_smb_findnext(ctx, limit, &scred);
2783 if (error != 0)
2784 goto out;
2785 np->n_dirofs++;
2786
2787 /* Sanity check the name length. */
2788 nmlen = ctx->f_nmlen;
2789 if (nmlen > SMB_MAXFNAMELEN) {
2790 nmlen = SMB_MAXFNAMELEN;
2791 SMBVDEBUG("Truncating name: %s\n", ctx->f_name);
2792 }
2793 if (smbfs_fastlookup) {
2794 /* See comment at smbfs_fastlookup above. */
2795 if (smbfs_nget(vp, ctx->f_name, nmlen,
2796 &ctx->f_attr, &newvp) == 0)
2797 VN_RELE(newvp);
2798 }
2799
2800 reclen = DIRENT64_RECLEN(nmlen);
2801 bzero(dp, reclen);
2802 dp->d_reclen = reclen;
2803 bcopy(ctx->f_name, dp->d_name, nmlen);
2804 dp->d_name[nmlen] = '\0';
2805 dp->d_ino = ctx->f_inum;
2806 dp->d_off = offset + 1; /* See d_off comment above */
2807 error = uiomove(dp, reclen, UIO_READ, uio);
2808 if (error)
2809 goto out;
2810 /* See comment re. uio_offset above. */
2811 uio->uio_offset = ++offset;
2812 }
2813
2814 out:
2815 /*
2816 * When we come to the end of a directory, the
2817 * SMB-level functions return ENOENT, but the
2818 * caller is not expecting an error return.
2819 *
2820 * Also note that we must delay the call to
2821 * smbfs_smb_findclose(np->n_dirseq, ...)
2822 * until smbfs_close so that all reads at the
2823 * end of the directory will return no data.
2824 */
2825 if (error == ENOENT) {
2826 error = 0;
2827 if (eofp)
2828 *eofp = 1;
2829 }
2830 /*
2831 * If we encountered an error (i.e. "access denied")
2832 * from the FindFirst call, we will have copied out
2833 * the "." and ".." entries leaving offset == 2.
2834 * In that case, restore the original offset/resid
2835 * so the caller gets no data with the error.
2836 */
2837 if (error != 0 && offset == FIRST_DIROFS) {
2838 uio->uio_loffset = save_offset;
2839 uio->uio_resid = save_resid;
2840 }
2841 SMBVDEBUG("out: offset=%d, resid=%d\n",
2842 (int)uio->uio_offset, (int)uio->uio_resid);
2843
2844 kmem_free(dp, dbufsiz);
2845 smb_credrele(&scred);
2846 return (error);
2847 }
2848
2849
2850 /*
2851 * The pair of functions VOP_RWLOCK, VOP_RWUNLOCK
2852 * are optional functions that are called by:
2853 * getdents, before/after VOP_READDIR
2854 * pread, before/after ... VOP_READ
2855 * pwrite, before/after ... VOP_WRITE
2856 * (other places)
2857 *
2858 * Careful here: None of the above check for any
2859 * error returns from VOP_RWLOCK / VOP_RWUNLOCK!
2860 * In fact, the return value from _rwlock is NOT
2861 * an error code, but V_WRITELOCK_TRUE / _FALSE.
2862 *
2863 * Therefore, it's up to _this_ code to make sure
2864 * the lock state remains balanced, which means
2865 * we can't "bail out" on interrupts, etc.
2866 */
2867
2868 /* ARGSUSED2 */
2869 static int
2870 smbfs_rwlock(vnode_t *vp, int write_lock, caller_context_t *ctp)
2871 {
2872 smbnode_t *np = VTOSMB(vp);
2873
2874 if (!write_lock) {
2875 (void) smbfs_rw_enter_sig(&np->r_rwlock, RW_READER, FALSE);
2876 return (V_WRITELOCK_FALSE);
2877 }
2878
2879
2880 (void) smbfs_rw_enter_sig(&np->r_rwlock, RW_WRITER, FALSE);
2881 return (V_WRITELOCK_TRUE);
2882 }
2883
2884 /* ARGSUSED */
2885 static void
2886 smbfs_rwunlock(vnode_t *vp, int write_lock, caller_context_t *ctp)
2887 {
2888 smbnode_t *np = VTOSMB(vp);
2889
2890 smbfs_rw_exit(&np->r_rwlock);
2891 }
2892
2893
2894 /* ARGSUSED */
2895 static int
2896 smbfs_seek(vnode_t *vp, offset_t ooff, offset_t *noffp, caller_context_t *ct)
2897 {
2898 smbmntinfo_t *smi;
2899
2900 smi = VTOSMI(vp);
2901
2902 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
2903 return (EPERM);
2904
2905 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2906 return (EIO);
2907
2908 /*
2909 * Because we stuff the readdir cookie into the offset field
2910 * someone may attempt to do an lseek with the cookie which
2911 * we want to succeed.
2912 */
2913 if (vp->v_type == VDIR)
2914 return (0);
2915
2916 /* Like NFS3, just check for 63-bit overflow. */
2917 if (*noffp < 0)
2918 return (EINVAL);
2919
2920 return (0);
2921 }
2922
2923
2924 /*
2925 * XXX
2926 * This op may need to support PSARC 2007/440, nbmand changes for CIFS Service.
2927 */
2928 static int
2929 smbfs_frlock(vnode_t *vp, int cmd, struct flock64 *bfp, int flag,
2930 offset_t offset, struct flk_callback *flk_cbp, cred_t *cr,
2931 caller_context_t *ct)
2932 {
2933 if (curproc->p_zone != VTOSMI(vp)->smi_zone_ref.zref_zone)
2934 return (EIO);
2935
2936 if (VTOSMI(vp)->smi_flags & SMI_LLOCK)
2937 return (fs_frlock(vp, cmd, bfp, flag, offset, flk_cbp, cr, ct));
2938 else
2939 return (ENOSYS);
2940 }
2941
2942 /*
2943 * Free storage space associated with the specified vnode. The portion
2944 * to be freed is specified by bfp->l_start and bfp->l_len (already
2945 * normalized to a "whence" of 0).
2946 *
2947 * Called by fcntl(fd, F_FREESP, lkp) for libc:ftruncate, etc.
2948 */
2949 /* ARGSUSED */
2950 static int
2951 smbfs_space(vnode_t *vp, int cmd, struct flock64 *bfp, int flag,
2952 offset_t offset, cred_t *cr, caller_context_t *ct)
2953 {
2954 int error;
2955 smbmntinfo_t *smi;
2956
2957 smi = VTOSMI(vp);
2958
2959 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
2960 return (EIO);
2961
2962 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2963 return (EIO);
2964
2965 /* Caller (fcntl) has checked v_type */
2966 ASSERT(vp->v_type == VREG);
2967 if (cmd != F_FREESP)
2968 return (EINVAL);
2969
2970 /*
2971 * Like NFS3, no 32-bit offset checks here.
2972 * Our SMB layer takes care to return EFBIG
2973 * when it has to fallback to a 32-bit call.
2974 */
2975
2976 error = convoff(vp, bfp, 0, offset);
2977 if (!error) {
2978 ASSERT(bfp->l_start >= 0);
2979 if (bfp->l_len == 0) {
2980 struct vattr va;
2981
2982 /*
2983 * ftruncate should not change the ctime and
2984 * mtime if we truncate the file to its
2985 * previous size.
2986 */
2987 va.va_mask = AT_SIZE;
2988 error = smbfsgetattr(vp, &va, cr);
2989 if (error || va.va_size == bfp->l_start)
2990 return (error);
2991 va.va_mask = AT_SIZE;
2992 va.va_size = bfp->l_start;
2993 error = smbfssetattr(vp, &va, 0, cr);
2994 } else
2995 error = EINVAL;
2996 }
2997
2998 return (error);
2999 }
3000
3001 /* ARGSUSED */
3002 static int
3003 smbfs_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr,
3004 caller_context_t *ct)
3005 {
3006 vfs_t *vfs;
3007 smbmntinfo_t *smi;
3008 struct smb_share *ssp;
3009
3010 vfs = vp->v_vfsp;
3011 smi = VFTOSMI(vfs);
3012
3013 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
3014 return (EIO);
3015
3016 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
3017 return (EIO);
3018
3019 switch (cmd) {
3020 case _PC_FILESIZEBITS:
3021 ssp = smi->smi_share;
3022 if (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES)
3023 *valp = 64;
3024 else
3025 *valp = 32;
3026 break;
3027
3028 case _PC_LINK_MAX:
3029 /* We only ever report one link to an object */
3030 *valp = 1;
3031 break;
3032
3033 case _PC_ACL_ENABLED:
3034 /*
3035 * Always indicate that ACLs are enabled and
3036 * that we support ACE_T format, otherwise
3037 * libsec will ask for ACLENT_T format data
3038 * which we don't support.
3039 */
3040 *valp = _ACL_ACE_ENABLED;
3041 break;
3042
3043 case _PC_SYMLINK_MAX: /* No symlinks until we do Unix extensions */
3044 *valp = 0;
3045 break;
3046
3047 case _PC_XATTR_EXISTS:
3048 if (vfs->vfs_flag & VFS_XATTR) {
3049 *valp = smbfs_xa_exists(vp, cr);
3050 break;
3051 }
3052 return (EINVAL);
3053
3054 case _PC_SATTR_ENABLED:
3055 case _PC_SATTR_EXISTS:
3056 *valp = 1;
3057 break;
3058
3059 case _PC_TIMESTAMP_RESOLUTION:
3060 /*
3061 * Windows times are tenths of microseconds
3062 * (multiples of 100 nanoseconds).
3063 */
3064 *valp = 100L;
3065 break;
3066
3067 default:
3068 return (fs_pathconf(vp, cmd, valp, cr, ct));
3069 }
3070 return (0);
3071 }
3072
3073 /* ARGSUSED */
3074 static int
3075 smbfs_getsecattr(vnode_t *vp, vsecattr_t *vsa, int flag, cred_t *cr,
3076 caller_context_t *ct)
3077 {
3078 vfs_t *vfsp;
3079 smbmntinfo_t *smi;
3080 int error;
3081 uint_t mask;
3082
3083 vfsp = vp->v_vfsp;
3084 smi = VFTOSMI(vfsp);
3085
3086 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
3087 return (EIO);
3088
3089 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED)
3090 return (EIO);
3091
3092 /*
3093 * Our _pathconf indicates _ACL_ACE_ENABLED,
3094 * so we should only see VSA_ACE, etc here.
3095 * Note: vn_create asks for VSA_DFACLCNT,
3096 * and it expects ENOSYS and empty data.
3097 */
3098 mask = vsa->vsa_mask & (VSA_ACE | VSA_ACECNT |
3099 VSA_ACE_ACLFLAGS | VSA_ACE_ALLTYPES);
3100 if (mask == 0)
3101 return (ENOSYS);
3102
3103 if (smi->smi_flags & SMI_ACL)
3104 error = smbfs_acl_getvsa(vp, vsa, flag, cr);
3105 else
3106 error = ENOSYS;
3107
3108 if (error == ENOSYS)
3109 error = fs_fab_acl(vp, vsa, flag, cr, ct);
3110
3111 return (error);
3112 }
3113
3114 /* ARGSUSED */
3115 static int
3116 smbfs_setsecattr(vnode_t *vp, vsecattr_t *vsa, int flag, cred_t *cr,
3117 caller_context_t *ct)
3118 {
3119 vfs_t *vfsp;
3120 smbmntinfo_t *smi;
3121 int error;
3122 uint_t mask;
3123
3124 vfsp = vp->v_vfsp;
3125 smi = VFTOSMI(vfsp);
3126
3127 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
3128 return (EIO);
3129
3130 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED)
3131 return (EIO);
3132
3133 /*
3134 * Our _pathconf indicates _ACL_ACE_ENABLED,
3135 * so we should only see VSA_ACE, etc here.
3136 */
3137 mask = vsa->vsa_mask & (VSA_ACE | VSA_ACECNT);
3138 if (mask == 0)
3139 return (ENOSYS);
3140
3141 if (vfsp->vfs_flag & VFS_RDONLY)
3142 return (EROFS);
3143
3144 /*
3145 * Allow only the mount owner to do this.
3146 * See comments at smbfs_access_rwx.
3147 */
3148 error = secpolicy_vnode_setdac(cr, smi->smi_uid);
3149 if (error != 0)
3150 return (error);
3151
3152 if (smi->smi_flags & SMI_ACL)
3153 error = smbfs_acl_setvsa(vp, vsa, flag, cr);
3154 else
3155 error = ENOSYS;
3156
3157 return (error);
3158 }
3159
3160
3161 /*
3162 * XXX
3163 * This op should eventually support PSARC 2007/268.
3164 */
3165 static int
3166 smbfs_shrlock(vnode_t *vp, int cmd, struct shrlock *shr, int flag, cred_t *cr,
3167 caller_context_t *ct)
3168 {
3169 if (curproc->p_zone != VTOSMI(vp)->smi_zone_ref.zref_zone)
3170 return (EIO);
3171
3172 if (VTOSMI(vp)->smi_flags & SMI_LLOCK)
3173 return (fs_shrlock(vp, cmd, shr, flag, cr, ct));
3174 else
3175 return (ENOSYS);
3176 }