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 2010 Sun Microsystems, Inc. All rights reserved. 37 * Use is subject to license terms. 38 */ 39 40 #include <sys/systm.h> 41 #include <sys/cred.h> 42 #include <sys/vnode.h> 43 #include <sys/vfs.h> 44 #include <sys/filio.h> 45 #include <sys/uio.h> 46 #include <sys/dirent.h> 47 #include <sys/errno.h> 48 #include <sys/sunddi.h> 49 #include <sys/sysmacros.h> 50 #include <sys/kmem.h> 51 #include <sys/cmn_err.h> 52 #include <sys/vfs_opreg.h> 53 #include <sys/policy.h> 54 55 #include <netsmb/smb_osdep.h> 56 #include <netsmb/smb.h> 57 #include <netsmb/smb_conn.h> 58 #include <netsmb/smb_subr.h> 59 60 #include <smbfs/smbfs.h> 61 #include <smbfs/smbfs_node.h> 62 #include <smbfs/smbfs_subr.h> 63 64 #include <sys/fs/smbfs_ioctl.h> 65 #include <fs/fs_subr.h> 66 67 /* 68 * We assign directory offsets like the NFS client, where the 69 * offset increments by _one_ after each directory entry. 70 * Further, the entries "." and ".." are always at offsets 71 * zero and one (respectively) and the "real" entries from 72 * the server appear at offsets starting with two. This 73 * macro is used to initialize the n_dirofs field after 74 * setting n_dirseq with a _findopen call. 75 */ 76 #define FIRST_DIROFS 2 77 78 /* 79 * These characters are illegal in NTFS file names. 80 * ref: http://support.microsoft.com/kb/147438 81 * 82 * Careful! The check in the XATTR case skips the 83 * first character to allow colon in XATTR names. 84 */ 85 static const char illegal_chars[] = { 86 ':', /* colon - keep this first! */ 87 '\\', /* back slash */ 88 '/', /* slash */ 89 '*', /* asterisk */ 90 '?', /* question mark */ 91 '"', /* double quote */ 92 '<', /* less than sign */ 93 '>', /* greater than sign */ 94 '|', /* vertical bar */ 95 0 96 }; 97 98 /* 99 * Turning this on causes nodes to be created in the cache 100 * during directory listings, normally avoiding a second 101 * OtW attribute fetch just after a readdir. 102 */ 103 int smbfs_fastlookup = 1; 104 105 /* local static function defines */ 106 107 static int smbfslookup_cache(vnode_t *, char *, int, vnode_t **, 108 cred_t *); 109 static int smbfslookup(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr, 110 int cache_ok, caller_context_t *); 111 static int smbfsrename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm, 112 cred_t *cr, caller_context_t *); 113 static int smbfssetattr(vnode_t *, struct vattr *, int, cred_t *); 114 static int smbfs_accessx(void *, int, cred_t *); 115 static int smbfs_readvdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp, 116 caller_context_t *); 117 static void smbfs_rele_fid(smbnode_t *, struct smb_cred *); 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) 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 != 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) 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) 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) 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 * XXX 844 * This op should eventually support PSARC 2007/315, Extensible Attribute 845 * Interfaces, for richer metadata. 846 */ 847 /* ARGSUSED */ 848 static int 849 smbfs_getattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr, 850 caller_context_t *ct) 851 { 852 smbnode_t *np; 853 smbmntinfo_t *smi; 854 855 smi = VTOSMI(vp); 856 857 if (curproc->p_zone != smi->smi_zone) 858 return (EIO); 859 860 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 861 return (EIO); 862 863 /* 864 * If it has been specified that the return value will 865 * just be used as a hint, and we are only being asked 866 * for size, fsid or rdevid, then return the client's 867 * notion of these values without checking to make sure 868 * that the attribute cache is up to date. 869 * The whole point is to avoid an over the wire GETATTR 870 * call. 871 */ 872 np = VTOSMB(vp); 873 if (flags & ATTR_HINT) { 874 if (vap->va_mask == 875 (vap->va_mask & (AT_SIZE | AT_FSID | AT_RDEV))) { 876 mutex_enter(&np->r_statelock); 877 if (vap->va_mask | AT_SIZE) 878 vap->va_size = np->r_size; 879 if (vap->va_mask | AT_FSID) 880 vap->va_fsid = vp->v_vfsp->vfs_dev; 881 if (vap->va_mask | AT_RDEV) 882 vap->va_rdev = vp->v_rdev; 883 mutex_exit(&np->r_statelock); 884 return (0); 885 } 886 } 887 888 return (smbfsgetattr(vp, vap, cr)); 889 } 890 891 /* smbfsgetattr() in smbfs_client.c */ 892 893 /* 894 * XXX 895 * This op should eventually support PSARC 2007/315, Extensible Attribute 896 * Interfaces, for richer metadata. 897 */ 898 /*ARGSUSED4*/ 899 static int 900 smbfs_setattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr, 901 caller_context_t *ct) 902 { 903 vfs_t *vfsp; 904 smbmntinfo_t *smi; 905 int error; 906 uint_t mask; 907 struct vattr oldva; 908 909 vfsp = vp->v_vfsp; 910 smi = VFTOSMI(vfsp); 911 912 if (curproc->p_zone != smi->smi_zone) 913 return (EIO); 914 915 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED) 916 return (EIO); 917 918 mask = vap->va_mask; 919 if (mask & AT_NOSET) 920 return (EINVAL); 921 922 if (vfsp->vfs_flag & VFS_RDONLY) 923 return (EROFS); 924 925 /* 926 * This is a _local_ access check so that only the owner of 927 * this mount can set attributes. With ACLs enabled, the 928 * file owner can be different from the mount owner, and we 929 * need to check the _mount_ owner here. See _access_rwx 930 */ 931 bzero(&oldva, sizeof (oldva)); 932 oldva.va_mask = AT_TYPE | AT_MODE; 933 error = smbfsgetattr(vp, &oldva, cr); 934 if (error) 935 return (error); 936 oldva.va_mask |= AT_UID | AT_GID; 937 oldva.va_uid = smi->smi_uid; 938 oldva.va_gid = smi->smi_gid; 939 940 error = secpolicy_vnode_setattr(cr, vp, vap, &oldva, flags, 941 smbfs_accessx, vp); 942 if (error) 943 return (error); 944 945 if (mask & (AT_UID | AT_GID)) { 946 if (smi->smi_flags & SMI_ACL) 947 error = smbfs_acl_setids(vp, vap, cr); 948 else 949 error = ENOSYS; 950 if (error != 0) { 951 SMBVDEBUG("error %d seting UID/GID on %s", 952 error, VTOSMB(vp)->n_rpath); 953 /* 954 * It might be more correct to return the 955 * error here, but that causes complaints 956 * when root extracts a cpio archive, etc. 957 * So ignore this error, and go ahead with 958 * the rest of the setattr work. 959 */ 960 } 961 } 962 963 return (smbfssetattr(vp, vap, flags, cr)); 964 } 965 966 /* 967 * Mostly from Darwin smbfs_setattr() 968 * but then modified a lot. 969 */ 970 /* ARGSUSED */ 971 static int 972 smbfssetattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr) 973 { 974 int error = 0; 975 smbnode_t *np = VTOSMB(vp); 976 uint_t mask = vap->va_mask; 977 struct timespec *mtime, *atime; 978 struct smb_cred scred; 979 int cerror, modified = 0; 980 unsigned short fid; 981 int have_fid = 0; 982 uint32_t rights = 0; 983 984 ASSERT(curproc->p_zone == VTOSMI(vp)->smi_zone); 985 986 /* 987 * There are no settable attributes on the XATTR dir, 988 * so just silently ignore these. On XATTR files, 989 * you can set the size but nothing else. 990 */ 991 if (vp->v_flag & V_XATTRDIR) 992 return (0); 993 if (np->n_flag & N_XATTR) { 994 if (mask & AT_TIMES) 995 SMBVDEBUG("ignore set time on xattr\n"); 996 mask &= AT_SIZE; 997 } 998 999 /* 1000 * If our caller is trying to set multiple attributes, they 1001 * can make no assumption about what order they are done in. 1002 * Here we try to do them in order of decreasing likelihood 1003 * of failure, just to minimize the chance we'll wind up 1004 * with a partially complete request. 1005 */ 1006 1007 /* Shared lock for (possible) n_fid use. */ 1008 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp))) 1009 return (EINTR); 1010 smb_credinit(&scred, cr); 1011 1012 /* 1013 * Will we need an open handle for this setattr? 1014 * If so, what rights will we need? 1015 */ 1016 if (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 (mask & (AT_SIZE | AT_ATIME | AT_MTIME)) { 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 (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 0, 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 * smbfs_access_rwx() 1129 * Common function for smbfs_access, etc. 1130 * 1131 * The security model implemented by the FS is unusual 1132 * due to the current "single user mounts" restriction: 1133 * All access under a given mount point uses the CIFS 1134 * credentials established by the owner of the mount. 1135 * 1136 * Most access checking is handled by the CIFS server, 1137 * but we need sufficient Unix access checks here to 1138 * prevent other local Unix users from having access 1139 * to objects under this mount that the uid/gid/mode 1140 * settings in the mount would not allow. 1141 * 1142 * With this model, there is a case where we need the 1143 * ability to do an access check before we have the 1144 * vnode for an object. This function takes advantage 1145 * of the fact that the uid/gid/mode is per mount, and 1146 * avoids the need for a vnode. 1147 * 1148 * We still (sort of) need a vnode when we call 1149 * secpolicy_vnode_access, but that only uses 1150 * the vtype field, so we can use a pair of fake 1151 * vnodes that have only v_type filled in. 1152 * 1153 * XXX: Later, add a new secpolicy_vtype_access() 1154 * that takes the vtype instead of a vnode, and 1155 * get rid of the tmpl_vxxx fake vnodes below. 1156 */ 1157 static int 1158 smbfs_access_rwx(vfs_t *vfsp, int vtype, int mode, cred_t *cr) 1159 { 1160 /* See the secpolicy call below. */ 1161 static const vnode_t tmpl_vdir = { .v_type = VDIR }; 1162 static const vnode_t tmpl_vreg = { .v_type = VREG }; 1163 vattr_t va; 1164 vnode_t *tvp; 1165 struct smbmntinfo *smi = VFTOSMI(vfsp); 1166 int shift = 0; 1167 1168 /* 1169 * Build our (fabricated) vnode attributes. 1170 * XXX: Could make these templates in the 1171 * per-mount struct and use them here. 1172 */ 1173 bzero(&va, sizeof (va)); 1174 va.va_mask = AT_TYPE | AT_MODE | AT_UID | AT_GID; 1175 va.va_type = vtype; 1176 va.va_mode = (vtype == VDIR) ? 1177 smi->smi_dmode : smi->smi_fmode; 1178 va.va_uid = smi->smi_uid; 1179 va.va_gid = smi->smi_gid; 1180 1181 /* 1182 * Disallow write attempts on read-only file systems, 1183 * unless the file is a device or fifo node. Note: 1184 * Inline vn_is_readonly and IS_DEVVP here because 1185 * we may not have a vnode ptr. Original expr. was: 1186 * (mode & VWRITE) && vn_is_readonly(vp) && !IS_DEVVP(vp)) 1187 */ 1188 if ((mode & VWRITE) && 1189 (vfsp->vfs_flag & VFS_RDONLY) && 1190 !(vtype == VCHR || vtype == VBLK || vtype == VFIFO)) 1191 return (EROFS); 1192 1193 /* 1194 * Disallow attempts to access mandatory lock files. 1195 * Similarly, expand MANDLOCK here. 1196 * XXX: not sure we need this. 1197 */ 1198 if ((mode & (VWRITE | VREAD | VEXEC)) && 1199 va.va_type == VREG && MANDMODE(va.va_mode)) 1200 return (EACCES); 1201 1202 /* 1203 * Access check is based on only 1204 * one of owner, group, public. 1205 * If not owner, then check group. 1206 * If not a member of the group, 1207 * then check public access. 1208 */ 1209 if (crgetuid(cr) != va.va_uid) { 1210 shift += 3; 1211 if (!groupmember(va.va_gid, cr)) 1212 shift += 3; 1213 } 1214 mode &= ~(va.va_mode << shift); 1215 if (mode == 0) 1216 return (0); 1217 1218 /* 1219 * We need a vnode for secpolicy_vnode_access, 1220 * but the only thing it looks at is v_type, 1221 * so pass one of the templates above. 1222 */ 1223 tvp = (va.va_type == VDIR) ? 1224 (vnode_t *)&tmpl_vdir : 1225 (vnode_t *)&tmpl_vreg; 1226 return (secpolicy_vnode_access(cr, tvp, va.va_uid, mode)); 1227 } 1228 1229 /* 1230 * See smbfs_setattr 1231 */ 1232 static int 1233 smbfs_accessx(void *arg, int mode, cred_t *cr) 1234 { 1235 vnode_t *vp = arg; 1236 /* 1237 * Note: The caller has checked the current zone, 1238 * the SMI_DEAD and VFS_UNMOUNTED flags, etc. 1239 */ 1240 return (smbfs_access_rwx(vp->v_vfsp, vp->v_type, mode, cr)); 1241 } 1242 1243 /* 1244 * XXX 1245 * This op should support PSARC 2007/403, Modified Access Checks for CIFS 1246 */ 1247 /* ARGSUSED */ 1248 static int 1249 smbfs_access(vnode_t *vp, int mode, int flags, cred_t *cr, caller_context_t *ct) 1250 { 1251 vfs_t *vfsp; 1252 smbmntinfo_t *smi; 1253 1254 vfsp = vp->v_vfsp; 1255 smi = VFTOSMI(vfsp); 1256 1257 if (curproc->p_zone != smi->smi_zone) 1258 return (EIO); 1259 1260 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED) 1261 return (EIO); 1262 1263 return (smbfs_access_rwx(vfsp, vp->v_type, mode, cr)); 1264 } 1265 1266 1267 /* 1268 * Flush local dirty pages to stable storage on the server. 1269 * 1270 * If FNODSYNC is specified, then there is nothing to do because 1271 * metadata changes are not cached on the client before being 1272 * sent to the server. 1273 */ 1274 /* ARGSUSED */ 1275 static int 1276 smbfs_fsync(vnode_t *vp, int syncflag, cred_t *cr, caller_context_t *ct) 1277 { 1278 int error = 0; 1279 smbmntinfo_t *smi; 1280 smbnode_t *np; 1281 struct smb_cred scred; 1282 1283 np = VTOSMB(vp); 1284 smi = VTOSMI(vp); 1285 1286 if (curproc->p_zone != smi->smi_zone) 1287 return (EIO); 1288 1289 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 1290 return (EIO); 1291 1292 if ((syncflag & FNODSYNC) || IS_SWAPVP(vp)) 1293 return (0); 1294 1295 if ((syncflag & (FSYNC|FDSYNC)) == 0) 1296 return (0); 1297 1298 /* Shared lock for n_fid use in _flush */ 1299 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp))) 1300 return (EINTR); 1301 smb_credinit(&scred, cr); 1302 1303 error = smbfs_smb_flush(np, &scred); 1304 1305 smb_credrele(&scred); 1306 smbfs_rw_exit(&np->r_lkserlock); 1307 1308 return (error); 1309 } 1310 1311 /* 1312 * Last reference to vnode went away. 1313 */ 1314 /* ARGSUSED */ 1315 static void 1316 smbfs_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct) 1317 { 1318 smbnode_t *np; 1319 struct smb_cred scred; 1320 1321 /* 1322 * Don't "bail out" for VFS_UNMOUNTED here, 1323 * as we want to do cleanup, etc. 1324 * See also pcfs_inactive 1325 */ 1326 1327 np = VTOSMB(vp); 1328 1329 /* 1330 * If this is coming from the wrong zone, we let someone in the right 1331 * zone take care of it asynchronously. We can get here due to 1332 * VN_RELE() being called from pageout() or fsflush(). This call may 1333 * potentially turn into an expensive no-op if, for instance, v_count 1334 * gets incremented in the meantime, but it's still correct. 1335 */ 1336 1337 /* 1338 * Defend against the possibility that higher-level callers 1339 * might not correctly balance open and close calls. If we 1340 * get here with open references remaining, it means there 1341 * was a missing VOP_CLOSE somewhere. If that happens, do 1342 * the close here so we don't "leak" FIDs on the server. 1343 * 1344 * Exclusive lock for modifying n_fid stuff. 1345 * Don't want this one ever interruptible. 1346 */ 1347 (void) smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, 0); 1348 smb_credinit(&scred, cr); 1349 1350 switch (np->n_ovtype) { 1351 case VNON: 1352 /* not open (OK) */ 1353 break; 1354 1355 case VDIR: 1356 if (np->n_dirrefs == 0) 1357 break; 1358 SMBVDEBUG("open dir: refs %d path %s\n", 1359 np->n_dirrefs, np->n_rpath); 1360 /* Force last close. */ 1361 np->n_dirrefs = 1; 1362 smbfs_rele_fid(np, &scred); 1363 break; 1364 1365 case VREG: 1366 if (np->n_fidrefs == 0) 1367 break; 1368 SMBVDEBUG("open file: refs %d id 0x%x path %s\n", 1369 np->n_fidrefs, np->n_fid, np->n_rpath); 1370 /* Force last close. */ 1371 np->n_fidrefs = 1; 1372 smbfs_rele_fid(np, &scred); 1373 break; 1374 1375 default: 1376 SMBVDEBUG("bad n_ovtype %d\n", np->n_ovtype); 1377 np->n_ovtype = VNON; 1378 break; 1379 } 1380 1381 smb_credrele(&scred); 1382 smbfs_rw_exit(&np->r_lkserlock); 1383 1384 smbfs_addfree(np); 1385 } 1386 1387 /* 1388 * Remote file system operations having to do with directory manipulation. 1389 */ 1390 /* ARGSUSED */ 1391 static int 1392 smbfs_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct pathname *pnp, 1393 int flags, vnode_t *rdir, cred_t *cr, caller_context_t *ct, 1394 int *direntflags, pathname_t *realpnp) 1395 { 1396 vfs_t *vfs; 1397 smbmntinfo_t *smi; 1398 smbnode_t *dnp; 1399 int error; 1400 1401 vfs = dvp->v_vfsp; 1402 smi = VFTOSMI(vfs); 1403 1404 if (curproc->p_zone != smi->smi_zone) 1405 return (EPERM); 1406 1407 if (smi->smi_flags & SMI_DEAD || vfs->vfs_flag & VFS_UNMOUNTED) 1408 return (EIO); 1409 1410 dnp = VTOSMB(dvp); 1411 1412 /* 1413 * Are we looking up extended attributes? If so, "dvp" is 1414 * the file or directory for which we want attributes, and 1415 * we need a lookup of the (faked up) attribute directory 1416 * before we lookup the rest of the path. 1417 */ 1418 if (flags & LOOKUP_XATTR) { 1419 /* 1420 * Require the xattr mount option. 1421 */ 1422 if ((vfs->vfs_flag & VFS_XATTR) == 0) 1423 return (EINVAL); 1424 1425 error = smbfs_get_xattrdir(dvp, vpp, cr, flags); 1426 return (error); 1427 } 1428 1429 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_READER, SMBINTR(dvp))) 1430 return (EINTR); 1431 1432 error = smbfslookup(dvp, nm, vpp, cr, 1, ct); 1433 1434 smbfs_rw_exit(&dnp->r_rwlock); 1435 1436 return (error); 1437 } 1438 1439 /* ARGSUSED */ 1440 static int 1441 smbfslookup(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr, 1442 int cache_ok, caller_context_t *ct) 1443 { 1444 int error; 1445 int supplen; /* supported length */ 1446 vnode_t *vp; 1447 smbnode_t *np; 1448 smbnode_t *dnp; 1449 smbmntinfo_t *smi; 1450 /* struct smb_vc *vcp; */ 1451 const char *ill; 1452 const char *name = (const char *)nm; 1453 int nmlen = strlen(nm); 1454 int rplen; 1455 struct smb_cred scred; 1456 struct smbfattr fa; 1457 1458 smi = VTOSMI(dvp); 1459 dnp = VTOSMB(dvp); 1460 1461 ASSERT(curproc->p_zone == smi->smi_zone); 1462 1463 #ifdef NOT_YET 1464 vcp = SSTOVC(smi->smi_share); 1465 1466 /* XXX: Should compute this once and store it in smbmntinfo_t */ 1467 supplen = (SMB_DIALECT(vcp) >= SMB_DIALECT_LANMAN2_0) ? 255 : 12; 1468 #else 1469 supplen = 255; 1470 #endif 1471 1472 /* 1473 * RWlock must be held, either reader or writer. 1474 * XXX: Can we check without looking directly 1475 * inside the struct smbfs_rwlock_t? 1476 */ 1477 ASSERT(dnp->r_rwlock.count != 0); 1478 1479 /* 1480 * If lookup is for "", just return dvp. 1481 * No need to perform any access checks. 1482 */ 1483 if (nmlen == 0) { 1484 VN_HOLD(dvp); 1485 *vpp = dvp; 1486 return (0); 1487 } 1488 1489 /* 1490 * Can't do lookups in non-directories. 1491 */ 1492 if (dvp->v_type != VDIR) 1493 return (ENOTDIR); 1494 1495 /* 1496 * Need search permission in the directory. 1497 */ 1498 error = smbfs_access(dvp, VEXEC, 0, cr, ct); 1499 if (error) 1500 return (error); 1501 1502 /* 1503 * If lookup is for ".", just return dvp. 1504 * Access check was done above. 1505 */ 1506 if (nmlen == 1 && name[0] == '.') { 1507 VN_HOLD(dvp); 1508 *vpp = dvp; 1509 return (0); 1510 } 1511 1512 /* 1513 * Now some sanity checks on the name. 1514 * First check the length. 1515 */ 1516 if (nmlen > supplen) 1517 return (ENAMETOOLONG); 1518 1519 /* 1520 * Avoid surprises with characters that are 1521 * illegal in Windows file names. 1522 * Todo: CATIA mappings XXX 1523 */ 1524 ill = illegal_chars; 1525 if (dnp->n_flag & N_XATTR) 1526 ill++; /* allow colon */ 1527 if (strpbrk(nm, ill)) 1528 return (EINVAL); 1529 1530 /* 1531 * Special handling for lookup of ".." 1532 * 1533 * We keep full pathnames (as seen on the server) 1534 * so we can just trim off the last component to 1535 * get the full pathname of the parent. Note: 1536 * We don't actually copy and modify, but just 1537 * compute the trimmed length and pass that with 1538 * the current dir path (not null terminated). 1539 * 1540 * We don't go over-the-wire to get attributes 1541 * for ".." because we know it's a directory, 1542 * and we can just leave the rest "stale" 1543 * until someone does a getattr. 1544 */ 1545 if (nmlen == 2 && name[0] == '.' && name[1] == '.') { 1546 if (dvp->v_flag & VROOT) { 1547 /* 1548 * Already at the root. This can happen 1549 * with directory listings at the root, 1550 * which lookup "." and ".." to get the 1551 * inode numbers. Let ".." be the same 1552 * as "." in the FS root. 1553 */ 1554 VN_HOLD(dvp); 1555 *vpp = dvp; 1556 return (0); 1557 } 1558 1559 /* 1560 * Special case for XATTR directory 1561 */ 1562 if (dvp->v_flag & V_XATTRDIR) { 1563 error = smbfs_xa_parent(dvp, vpp); 1564 return (error); 1565 } 1566 1567 /* 1568 * Find the parent path length. 1569 */ 1570 rplen = dnp->n_rplen; 1571 ASSERT(rplen > 0); 1572 while (--rplen >= 0) { 1573 if (dnp->n_rpath[rplen] == '\\') 1574 break; 1575 } 1576 if (rplen <= 0) { 1577 /* Found our way to the root. */ 1578 vp = SMBTOV(smi->smi_root); 1579 VN_HOLD(vp); 1580 *vpp = vp; 1581 return (0); 1582 } 1583 np = smbfs_node_findcreate(smi, 1584 dnp->n_rpath, rplen, NULL, 0, 0, 1585 &smbfs_fattr0); /* force create */ 1586 ASSERT(np != NULL); 1587 vp = SMBTOV(np); 1588 vp->v_type = VDIR; 1589 1590 /* Success! */ 1591 *vpp = vp; 1592 return (0); 1593 } 1594 1595 /* 1596 * Normal lookup of a name under this directory. 1597 * Note we handled "", ".", ".." above. 1598 */ 1599 if (cache_ok) { 1600 /* 1601 * The caller indicated that it's OK to use a 1602 * cached result for this lookup, so try to 1603 * reclaim a node from the smbfs node cache. 1604 */ 1605 error = smbfslookup_cache(dvp, nm, nmlen, &vp, cr); 1606 if (error) 1607 return (error); 1608 if (vp != NULL) { 1609 /* hold taken in lookup_cache */ 1610 *vpp = vp; 1611 return (0); 1612 } 1613 } 1614 1615 /* 1616 * OK, go over-the-wire to get the attributes, 1617 * then create the node. 1618 */ 1619 smb_credinit(&scred, cr); 1620 /* Note: this can allocate a new "name" */ 1621 error = smbfs_smb_lookup(dnp, &name, &nmlen, &fa, &scred); 1622 smb_credrele(&scred); 1623 if (error == ENOTDIR) { 1624 /* 1625 * Lookup failed because this directory was 1626 * removed or renamed by another client. 1627 * Remove any cached attributes under it. 1628 */ 1629 smbfs_attrcache_remove(dnp); 1630 smbfs_attrcache_prune(dnp); 1631 } 1632 if (error) 1633 goto out; 1634 1635 error = smbfs_nget(dvp, name, nmlen, &fa, &vp); 1636 if (error) 1637 goto out; 1638 1639 /* Success! */ 1640 *vpp = vp; 1641 1642 out: 1643 /* smbfs_smb_lookup may have allocated name. */ 1644 if (name != nm) 1645 smbfs_name_free(name, nmlen); 1646 1647 return (error); 1648 } 1649 1650 /* 1651 * smbfslookup_cache 1652 * 1653 * Try to reclaim a node from the smbfs node cache. 1654 * Some statistics for DEBUG. 1655 * 1656 * This mechanism lets us avoid many of the five (or more) 1657 * OtW lookup calls per file seen with "ls -l" if we search 1658 * the smbfs node cache for recently inactive(ated) nodes. 1659 */ 1660 #ifdef DEBUG 1661 int smbfs_lookup_cache_calls = 0; 1662 int smbfs_lookup_cache_error = 0; 1663 int smbfs_lookup_cache_miss = 0; 1664 int smbfs_lookup_cache_stale = 0; 1665 int smbfs_lookup_cache_hits = 0; 1666 #endif /* DEBUG */ 1667 1668 /* ARGSUSED */ 1669 static int 1670 smbfslookup_cache(vnode_t *dvp, char *nm, int nmlen, 1671 vnode_t **vpp, cred_t *cr) 1672 { 1673 struct vattr va; 1674 smbnode_t *dnp; 1675 smbnode_t *np; 1676 vnode_t *vp; 1677 int error; 1678 char sep; 1679 1680 dnp = VTOSMB(dvp); 1681 *vpp = NULL; 1682 1683 #ifdef DEBUG 1684 smbfs_lookup_cache_calls++; 1685 #endif 1686 1687 /* 1688 * First make sure we can get attributes for the 1689 * directory. Cached attributes are OK here. 1690 * If we removed or renamed the directory, this 1691 * will return ENOENT. If someone else removed 1692 * this directory or file, we'll find out when we 1693 * try to open or get attributes. 1694 */ 1695 va.va_mask = AT_TYPE | AT_MODE; 1696 error = smbfsgetattr(dvp, &va, cr); 1697 if (error) { 1698 #ifdef DEBUG 1699 smbfs_lookup_cache_error++; 1700 #endif 1701 return (error); 1702 } 1703 1704 /* 1705 * Passing NULL smbfattr here so we will 1706 * just look, not create. 1707 */ 1708 sep = SMBFS_DNP_SEP(dnp); 1709 np = smbfs_node_findcreate(dnp->n_mount, 1710 dnp->n_rpath, dnp->n_rplen, 1711 nm, nmlen, sep, NULL); 1712 if (np == NULL) { 1713 #ifdef DEBUG 1714 smbfs_lookup_cache_miss++; 1715 #endif 1716 return (0); 1717 } 1718 1719 /* 1720 * Found it. Attributes still valid? 1721 */ 1722 vp = SMBTOV(np); 1723 if (np->r_attrtime <= gethrtime()) { 1724 /* stale */ 1725 #ifdef DEBUG 1726 smbfs_lookup_cache_stale++; 1727 #endif 1728 VN_RELE(vp); 1729 return (0); 1730 } 1731 1732 /* 1733 * Success! 1734 * Caller gets hold from smbfs_node_findcreate 1735 */ 1736 #ifdef DEBUG 1737 smbfs_lookup_cache_hits++; 1738 #endif 1739 *vpp = vp; 1740 return (0); 1741 } 1742 1743 /* 1744 * XXX 1745 * vsecattr_t is new to build 77, and we need to eventually support 1746 * it in order to create an ACL when an object is created. 1747 * 1748 * This op should support the new FIGNORECASE flag for case-insensitive 1749 * lookups, per PSARC 2007/244. 1750 */ 1751 /* ARGSUSED */ 1752 static int 1753 smbfs_create(vnode_t *dvp, char *nm, struct vattr *va, enum vcexcl exclusive, 1754 int mode, vnode_t **vpp, cred_t *cr, int lfaware, caller_context_t *ct, 1755 vsecattr_t *vsecp) 1756 { 1757 int error; 1758 int cerror; 1759 vfs_t *vfsp; 1760 vnode_t *vp; 1761 #ifdef NOT_YET 1762 smbnode_t *np; 1763 #endif 1764 smbnode_t *dnp; 1765 smbmntinfo_t *smi; 1766 struct vattr vattr; 1767 struct smbfattr fattr; 1768 struct smb_cred scred; 1769 const char *name = (const char *)nm; 1770 int nmlen = strlen(nm); 1771 uint32_t disp; 1772 uint16_t fid; 1773 int xattr; 1774 1775 vfsp = dvp->v_vfsp; 1776 smi = VFTOSMI(vfsp); 1777 dnp = VTOSMB(dvp); 1778 vp = NULL; 1779 1780 if (curproc->p_zone != smi->smi_zone) 1781 return (EPERM); 1782 1783 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED) 1784 return (EIO); 1785 1786 /* 1787 * Note: this may break mknod(2) calls to create a directory, 1788 * but that's obscure use. Some other filesystems do this. 1789 * XXX: Later, redirect VDIR type here to _mkdir. 1790 */ 1791 if (va->va_type != VREG) 1792 return (EINVAL); 1793 1794 /* 1795 * If the pathname is "", just use dvp, no checks. 1796 * Do this outside of the rwlock (like zfs). 1797 */ 1798 if (nmlen == 0) { 1799 VN_HOLD(dvp); 1800 *vpp = dvp; 1801 return (0); 1802 } 1803 1804 /* Don't allow "." or ".." through here. */ 1805 if ((nmlen == 1 && name[0] == '.') || 1806 (nmlen == 2 && name[0] == '.' && name[1] == '.')) 1807 return (EISDIR); 1808 1809 /* 1810 * We make a copy of the attributes because the caller does not 1811 * expect us to change what va points to. 1812 */ 1813 vattr = *va; 1814 1815 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp))) 1816 return (EINTR); 1817 smb_credinit(&scred, cr); 1818 1819 /* 1820 * XXX: Do we need r_lkserlock too? 1821 * No use of any shared fid or fctx... 1822 */ 1823 1824 /* 1825 * NFS needs to go over the wire, just to be sure whether the 1826 * file exists or not. Using a cached result is dangerous in 1827 * this case when making a decision regarding existence. 1828 * 1829 * The SMB protocol does NOT really need to go OTW here 1830 * thanks to the expressive NTCREATE disposition values. 1831 * Unfortunately, to do Unix access checks correctly, 1832 * we need to know if the object already exists. 1833 * When the object does not exist, we need VWRITE on 1834 * the directory. Note: smbfslookup() checks VEXEC. 1835 */ 1836 error = smbfslookup(dvp, nm, &vp, cr, 0, ct); 1837 if (error == 0) { 1838 /* 1839 * The file already exists. Error? 1840 * NB: have a hold from smbfslookup 1841 */ 1842 if (exclusive == EXCL) { 1843 error = EEXIST; 1844 VN_RELE(vp); 1845 goto out; 1846 } 1847 /* 1848 * Verify requested access. 1849 */ 1850 error = smbfs_access(vp, mode, 0, cr, ct); 1851 if (error) { 1852 VN_RELE(vp); 1853 goto out; 1854 } 1855 1856 /* 1857 * Truncate (if requested). 1858 */ 1859 if ((vattr.va_mask & AT_SIZE) && vattr.va_size == 0) { 1860 vattr.va_mask = AT_SIZE; 1861 error = smbfssetattr(vp, &vattr, 0, cr); 1862 if (error) { 1863 VN_RELE(vp); 1864 goto out; 1865 } 1866 } 1867 /* Success! */ 1868 #ifdef NOT_YET 1869 vnevent_create(vp, ct); 1870 #endif 1871 *vpp = vp; 1872 goto out; 1873 } 1874 1875 /* 1876 * The file did not exist. Need VWRITE in the directory. 1877 */ 1878 error = smbfs_access(dvp, VWRITE, 0, cr, ct); 1879 if (error) 1880 goto out; 1881 1882 /* 1883 * Now things get tricky. We also need to check the 1884 * requested open mode against the file we may create. 1885 * See comments at smbfs_access_rwx 1886 */ 1887 error = smbfs_access_rwx(vfsp, VREG, mode, cr); 1888 if (error) 1889 goto out; 1890 1891 /* 1892 * Now the code derived from Darwin, 1893 * but with greater use of NT_CREATE 1894 * disposition options. Much changed. 1895 * 1896 * Create (or open) a new child node. 1897 * Note we handled "." and ".." above. 1898 */ 1899 1900 if (exclusive == EXCL) 1901 disp = NTCREATEX_DISP_CREATE; 1902 else { 1903 /* Truncate regular files if requested. */ 1904 if ((va->va_type == VREG) && 1905 (va->va_mask & AT_SIZE) && 1906 (va->va_size == 0)) 1907 disp = NTCREATEX_DISP_OVERWRITE_IF; 1908 else 1909 disp = NTCREATEX_DISP_OPEN_IF; 1910 } 1911 xattr = (dnp->n_flag & N_XATTR) ? 1 : 0; 1912 error = smbfs_smb_create(dnp, 1913 name, nmlen, xattr, 1914 disp, &scred, &fid); 1915 if (error) 1916 goto out; 1917 1918 /* 1919 * XXX: Missing some code here to deal with 1920 * the case where we opened an existing file, 1921 * it's size is larger than 32-bits, and we're 1922 * setting the size from a process that's not 1923 * aware of large file offsets. i.e. 1924 * from the NFS3 code: 1925 */ 1926 #if NOT_YET /* XXX */ 1927 if ((vattr.va_mask & AT_SIZE) && 1928 vp->v_type == VREG) { 1929 np = VTOSMB(vp); 1930 /* 1931 * Check here for large file handled 1932 * by LF-unaware process (as 1933 * ufs_create() does) 1934 */ 1935 if (!(lfaware & FOFFMAX)) { 1936 mutex_enter(&np->r_statelock); 1937 if (np->r_size > MAXOFF32_T) 1938 error = EOVERFLOW; 1939 mutex_exit(&np->r_statelock); 1940 } 1941 if (!error) { 1942 vattr.va_mask = AT_SIZE; 1943 error = smbfssetattr(vp, 1944 &vattr, 0, cr); 1945 } 1946 } 1947 #endif /* XXX */ 1948 /* 1949 * Should use the fid to get/set the size 1950 * while we have it opened here. See above. 1951 */ 1952 1953 cerror = smbfs_smb_close(smi->smi_share, fid, NULL, &scred); 1954 if (cerror) 1955 SMBVDEBUG("error %d closing %s\\%s\n", 1956 cerror, dnp->n_rpath, name); 1957 1958 /* 1959 * In the open case, the name may differ a little 1960 * from what we passed to create (case, etc.) 1961 * so call lookup to get the (opened) name. 1962 * 1963 * XXX: Could avoid this extra lookup if the 1964 * "createact" result from NT_CREATE says we 1965 * created the object. 1966 */ 1967 error = smbfs_smb_lookup(dnp, &name, &nmlen, &fattr, &scred); 1968 if (error) 1969 goto out; 1970 1971 /* update attr and directory cache */ 1972 smbfs_attr_touchdir(dnp); 1973 1974 error = smbfs_nget(dvp, name, nmlen, &fattr, &vp); 1975 if (error) 1976 goto out; 1977 1978 /* XXX invalidate pages if we truncated? */ 1979 1980 /* Success! */ 1981 *vpp = vp; 1982 error = 0; 1983 1984 out: 1985 smb_credrele(&scred); 1986 smbfs_rw_exit(&dnp->r_rwlock); 1987 if (name != nm) 1988 smbfs_name_free(name, nmlen); 1989 return (error); 1990 } 1991 1992 /* 1993 * XXX 1994 * This op should support the new FIGNORECASE flag for case-insensitive 1995 * lookups, per PSARC 2007/244. 1996 */ 1997 /* ARGSUSED */ 1998 static int 1999 smbfs_remove(vnode_t *dvp, char *nm, cred_t *cr, caller_context_t *ct, 2000 int flags) 2001 { 2002 int error; 2003 vnode_t *vp; 2004 smbnode_t *np; 2005 smbnode_t *dnp; 2006 struct smb_cred scred; 2007 /* enum smbfsstat status; */ 2008 smbmntinfo_t *smi; 2009 2010 smi = VTOSMI(dvp); 2011 2012 if (curproc->p_zone != smi->smi_zone) 2013 return (EPERM); 2014 2015 if (smi->smi_flags & SMI_DEAD || dvp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 2016 return (EIO); 2017 2018 dnp = VTOSMB(dvp); 2019 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp))) 2020 return (EINTR); 2021 smb_credinit(&scred, cr); 2022 2023 /* 2024 * Verify access to the dirctory. 2025 */ 2026 error = smbfs_access(dvp, VWRITE|VEXEC, 0, cr, ct); 2027 if (error) 2028 goto out; 2029 2030 /* 2031 * NOTE: the darwin code gets the "vp" passed in so it looks 2032 * like the "vp" has probably been "lookup"ed by the VFS layer. 2033 * It looks like we will need to lookup the vp to check the 2034 * caches and check if the object being deleted is a directory. 2035 */ 2036 error = smbfslookup(dvp, nm, &vp, cr, 0, ct); 2037 if (error) 2038 goto out; 2039 2040 /* Never allow link/unlink directories on CIFS. */ 2041 if (vp->v_type == VDIR) { 2042 VN_RELE(vp); 2043 error = EPERM; 2044 goto out; 2045 } 2046 2047 /* 2048 * Now we have the real reference count on the vnode 2049 * Do we have the file open? 2050 */ 2051 np = VTOSMB(vp); 2052 mutex_enter(&np->r_statelock); 2053 if ((vp->v_count > 1) && (np->n_fidrefs > 0)) { 2054 /* 2055 * NFS does a rename on remove here. 2056 * Probably not applicable for SMB. 2057 * Like Darwin, just return EBUSY. 2058 * 2059 * XXX: Todo - Use Trans2rename, and 2060 * if that fails, ask the server to 2061 * set the delete-on-close flag. 2062 */ 2063 mutex_exit(&np->r_statelock); 2064 error = EBUSY; 2065 } else { 2066 smbfs_attrcache_rm_locked(np); 2067 mutex_exit(&np->r_statelock); 2068 2069 error = smbfs_smb_delete(np, &scred, NULL, 0, 0); 2070 2071 /* 2072 * If the file should no longer exist, discard 2073 * any cached attributes under this node. 2074 */ 2075 switch (error) { 2076 case 0: 2077 case ENOENT: 2078 case ENOTDIR: 2079 smbfs_attrcache_prune(np); 2080 break; 2081 } 2082 } 2083 2084 VN_RELE(vp); 2085 2086 out: 2087 smb_credrele(&scred); 2088 smbfs_rw_exit(&dnp->r_rwlock); 2089 2090 return (error); 2091 } 2092 2093 2094 /* 2095 * XXX 2096 * This op should support the new FIGNORECASE flag for case-insensitive 2097 * lookups, per PSARC 2007/244. 2098 */ 2099 /* ARGSUSED */ 2100 static int 2101 smbfs_rename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm, cred_t *cr, 2102 caller_context_t *ct, int flags) 2103 { 2104 /* vnode_t *realvp; */ 2105 2106 if (curproc->p_zone != VTOSMI(odvp)->smi_zone || 2107 curproc->p_zone != VTOSMI(ndvp)->smi_zone) 2108 return (EPERM); 2109 2110 if (VTOSMI(odvp)->smi_flags & SMI_DEAD || 2111 VTOSMI(ndvp)->smi_flags & SMI_DEAD || 2112 odvp->v_vfsp->vfs_flag & VFS_UNMOUNTED || 2113 ndvp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 2114 return (EIO); 2115 2116 return (smbfsrename(odvp, onm, ndvp, nnm, cr, ct)); 2117 } 2118 2119 /* 2120 * smbfsrename does the real work of renaming in SMBFS 2121 */ 2122 /* ARGSUSED */ 2123 static int 2124 smbfsrename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm, cred_t *cr, 2125 caller_context_t *ct) 2126 { 2127 int error; 2128 int nvp_locked = 0; 2129 vnode_t *nvp = NULL; 2130 vnode_t *ovp = NULL; 2131 smbnode_t *onp; 2132 smbnode_t *nnp; 2133 smbnode_t *odnp; 2134 smbnode_t *ndnp; 2135 struct smb_cred scred; 2136 /* enum smbfsstat status; */ 2137 2138 ASSERT(curproc->p_zone == VTOSMI(odvp)->smi_zone); 2139 2140 if (strcmp(onm, ".") == 0 || strcmp(onm, "..") == 0 || 2141 strcmp(nnm, ".") == 0 || strcmp(nnm, "..") == 0) 2142 return (EINVAL); 2143 2144 /* 2145 * Check that everything is on the same filesystem. 2146 * vn_rename checks the fsid's, but in case we don't 2147 * fill those in correctly, check here too. 2148 */ 2149 if (odvp->v_vfsp != ndvp->v_vfsp) 2150 return (EXDEV); 2151 2152 odnp = VTOSMB(odvp); 2153 ndnp = VTOSMB(ndvp); 2154 2155 /* 2156 * Avoid deadlock here on old vs new directory nodes 2157 * by always taking the locks in order of address. 2158 * The order is arbitrary, but must be consistent. 2159 */ 2160 if (odnp < ndnp) { 2161 if (smbfs_rw_enter_sig(&odnp->r_rwlock, RW_WRITER, 2162 SMBINTR(odvp))) 2163 return (EINTR); 2164 if (smbfs_rw_enter_sig(&ndnp->r_rwlock, RW_WRITER, 2165 SMBINTR(ndvp))) { 2166 smbfs_rw_exit(&odnp->r_rwlock); 2167 return (EINTR); 2168 } 2169 } else { 2170 if (smbfs_rw_enter_sig(&ndnp->r_rwlock, RW_WRITER, 2171 SMBINTR(ndvp))) 2172 return (EINTR); 2173 if (smbfs_rw_enter_sig(&odnp->r_rwlock, RW_WRITER, 2174 SMBINTR(odvp))) { 2175 smbfs_rw_exit(&ndnp->r_rwlock); 2176 return (EINTR); 2177 } 2178 } 2179 smb_credinit(&scred, cr); 2180 /* 2181 * No returns after this point (goto out) 2182 */ 2183 2184 /* 2185 * Need write access on source and target. 2186 * Server takes care of most checks. 2187 */ 2188 error = smbfs_access(odvp, VWRITE|VEXEC, 0, cr, ct); 2189 if (error) 2190 goto out; 2191 if (odvp != ndvp) { 2192 error = smbfs_access(ndvp, VWRITE, 0, cr, ct); 2193 if (error) 2194 goto out; 2195 } 2196 2197 /* 2198 * Lookup the source name. Must already exist. 2199 */ 2200 error = smbfslookup(odvp, onm, &ovp, cr, 0, ct); 2201 if (error) 2202 goto out; 2203 2204 /* 2205 * Lookup the target file. If it exists, it needs to be 2206 * checked to see whether it is a mount point and whether 2207 * it is active (open). 2208 */ 2209 error = smbfslookup(ndvp, nnm, &nvp, cr, 0, ct); 2210 if (!error) { 2211 /* 2212 * Target (nvp) already exists. Check that it 2213 * has the same type as the source. The server 2214 * will check this also, (and more reliably) but 2215 * this lets us return the correct error codes. 2216 */ 2217 if (ovp->v_type == VDIR) { 2218 if (nvp->v_type != VDIR) { 2219 error = ENOTDIR; 2220 goto out; 2221 } 2222 } else { 2223 if (nvp->v_type == VDIR) { 2224 error = EISDIR; 2225 goto out; 2226 } 2227 } 2228 2229 /* 2230 * POSIX dictates that when the source and target 2231 * entries refer to the same file object, rename 2232 * must do nothing and exit without error. 2233 */ 2234 if (ovp == nvp) { 2235 error = 0; 2236 goto out; 2237 } 2238 2239 /* 2240 * Also must ensure the target is not a mount point, 2241 * and keep mount/umount away until we're done. 2242 */ 2243 if (vn_vfsrlock(nvp)) { 2244 error = EBUSY; 2245 goto out; 2246 } 2247 nvp_locked = 1; 2248 if (vn_mountedvfs(nvp) != NULL) { 2249 error = EBUSY; 2250 goto out; 2251 } 2252 2253 /* 2254 * CIFS gives a SHARING_VIOLATION error when 2255 * trying to rename onto an exising object, 2256 * so try to remove the target first. 2257 * (Only for files, not directories.) 2258 */ 2259 if (nvp->v_type == VDIR) { 2260 error = EEXIST; 2261 goto out; 2262 } 2263 2264 /* 2265 * Nodes that are "not active" here have v_count=2 2266 * because vn_renameat (our caller) did a lookup on 2267 * both the source and target before this call. 2268 * Otherwise this similar to smbfs_remove. 2269 */ 2270 nnp = VTOSMB(nvp); 2271 mutex_enter(&nnp->r_statelock); 2272 if ((nvp->v_count > 2) && (nnp->n_fidrefs > 0)) { 2273 /* 2274 * The target file exists, is not the same as 2275 * the source file, and is active. Other FS 2276 * implementations unlink the target here. 2277 * For SMB, we don't assume we can remove an 2278 * open file. Return an error instead. 2279 */ 2280 mutex_exit(&nnp->r_statelock); 2281 error = EBUSY; 2282 goto out; 2283 } 2284 2285 /* 2286 * Target file is not active. Try to remove it. 2287 */ 2288 smbfs_attrcache_rm_locked(nnp); 2289 mutex_exit(&nnp->r_statelock); 2290 2291 error = smbfs_smb_delete(nnp, &scred, NULL, 0, 0); 2292 2293 /* 2294 * Similar to smbfs_remove 2295 */ 2296 switch (error) { 2297 case 0: 2298 case ENOENT: 2299 case ENOTDIR: 2300 smbfs_attrcache_prune(nnp); 2301 break; 2302 } 2303 2304 if (error) 2305 goto out; 2306 /* 2307 * OK, removed the target file. Continue as if 2308 * lookup target had failed (nvp == NULL). 2309 */ 2310 vn_vfsunlock(nvp); 2311 nvp_locked = 0; 2312 VN_RELE(nvp); 2313 nvp = NULL; 2314 } /* nvp */ 2315 2316 onp = VTOSMB(ovp); 2317 smbfs_attrcache_remove(onp); 2318 2319 error = smbfs_smb_rename(onp, ndnp, nnm, strlen(nnm), &scred); 2320 2321 /* 2322 * If the old name should no longer exist, 2323 * discard any cached attributes under it. 2324 */ 2325 if (error == 0) 2326 smbfs_attrcache_prune(onp); 2327 2328 out: 2329 if (nvp) { 2330 if (nvp_locked) 2331 vn_vfsunlock(nvp); 2332 VN_RELE(nvp); 2333 } 2334 if (ovp) 2335 VN_RELE(ovp); 2336 2337 smb_credrele(&scred); 2338 smbfs_rw_exit(&odnp->r_rwlock); 2339 smbfs_rw_exit(&ndnp->r_rwlock); 2340 2341 return (error); 2342 } 2343 2344 /* 2345 * XXX 2346 * vsecattr_t is new to build 77, and we need to eventually support 2347 * it in order to create an ACL when an object is created. 2348 * 2349 * This op should support the new FIGNORECASE flag for case-insensitive 2350 * lookups, per PSARC 2007/244. 2351 */ 2352 /* ARGSUSED */ 2353 static int 2354 smbfs_mkdir(vnode_t *dvp, char *nm, struct vattr *va, vnode_t **vpp, 2355 cred_t *cr, caller_context_t *ct, int flags, vsecattr_t *vsecp) 2356 { 2357 vnode_t *vp; 2358 struct smbnode *dnp = VTOSMB(dvp); 2359 struct smbmntinfo *smi = VTOSMI(dvp); 2360 struct smb_cred scred; 2361 struct smbfattr fattr; 2362 const char *name = (const char *) nm; 2363 int nmlen = strlen(name); 2364 int error, hiderr; 2365 2366 if (curproc->p_zone != smi->smi_zone) 2367 return (EPERM); 2368 2369 if (smi->smi_flags & SMI_DEAD || dvp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 2370 return (EIO); 2371 2372 if ((nmlen == 1 && name[0] == '.') || 2373 (nmlen == 2 && name[0] == '.' && name[1] == '.')) 2374 return (EEXIST); 2375 2376 /* Only plain files are allowed in V_XATTRDIR. */ 2377 if (dvp->v_flag & V_XATTRDIR) 2378 return (EINVAL); 2379 2380 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp))) 2381 return (EINTR); 2382 smb_credinit(&scred, cr); 2383 2384 /* 2385 * XXX: Do we need r_lkserlock too? 2386 * No use of any shared fid or fctx... 2387 */ 2388 2389 /* 2390 * Require write access in the containing directory. 2391 */ 2392 error = smbfs_access(dvp, VWRITE, 0, cr, ct); 2393 if (error) 2394 goto out; 2395 2396 error = smbfs_smb_mkdir(dnp, name, nmlen, &scred); 2397 if (error) 2398 goto out; 2399 2400 error = smbfs_smb_lookup(dnp, &name, &nmlen, &fattr, &scred); 2401 if (error) 2402 goto out; 2403 2404 smbfs_attr_touchdir(dnp); 2405 2406 error = smbfs_nget(dvp, name, nmlen, &fattr, &vp); 2407 if (error) 2408 goto out; 2409 2410 if (name[0] == '.') 2411 if ((hiderr = smbfs_smb_hideit(VTOSMB(vp), NULL, 0, &scred))) 2412 SMBVDEBUG("hide failure %d\n", hiderr); 2413 2414 /* Success! */ 2415 *vpp = vp; 2416 error = 0; 2417 out: 2418 smb_credrele(&scred); 2419 smbfs_rw_exit(&dnp->r_rwlock); 2420 2421 if (name != nm) 2422 smbfs_name_free(name, nmlen); 2423 2424 return (error); 2425 } 2426 2427 /* 2428 * XXX 2429 * This op should support the new FIGNORECASE flag for case-insensitive 2430 * lookups, per PSARC 2007/244. 2431 */ 2432 /* ARGSUSED */ 2433 static int 2434 smbfs_rmdir(vnode_t *dvp, char *nm, vnode_t *cdir, cred_t *cr, 2435 caller_context_t *ct, int flags) 2436 { 2437 vnode_t *vp = NULL; 2438 int vp_locked = 0; 2439 struct smbmntinfo *smi = VTOSMI(dvp); 2440 struct smbnode *dnp = VTOSMB(dvp); 2441 struct smbnode *np; 2442 struct smb_cred scred; 2443 int error; 2444 2445 if (curproc->p_zone != smi->smi_zone) 2446 return (EPERM); 2447 2448 if (smi->smi_flags & SMI_DEAD || dvp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 2449 return (EIO); 2450 2451 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp))) 2452 return (EINTR); 2453 smb_credinit(&scred, cr); 2454 2455 /* 2456 * Require w/x access in the containing directory. 2457 * Server handles all other access checks. 2458 */ 2459 error = smbfs_access(dvp, VEXEC|VWRITE, 0, cr, ct); 2460 if (error) 2461 goto out; 2462 2463 /* 2464 * First lookup the entry to be removed. 2465 */ 2466 error = smbfslookup(dvp, nm, &vp, cr, 0, ct); 2467 if (error) 2468 goto out; 2469 np = VTOSMB(vp); 2470 2471 /* 2472 * Disallow rmdir of "." or current dir, or the FS root. 2473 * Also make sure it's a directory, not a mount point, 2474 * and lock to keep mount/umount away until we're done. 2475 */ 2476 if ((vp == dvp) || (vp == cdir) || (vp->v_flag & VROOT)) { 2477 error = EINVAL; 2478 goto out; 2479 } 2480 if (vp->v_type != VDIR) { 2481 error = ENOTDIR; 2482 goto out; 2483 } 2484 if (vn_vfsrlock(vp)) { 2485 error = EBUSY; 2486 goto out; 2487 } 2488 vp_locked = 1; 2489 if (vn_mountedvfs(vp) != NULL) { 2490 error = EBUSY; 2491 goto out; 2492 } 2493 2494 smbfs_attrcache_remove(np); 2495 error = smbfs_smb_rmdir(np, &scred); 2496 2497 /* 2498 * Similar to smbfs_remove 2499 */ 2500 switch (error) { 2501 case 0: 2502 case ENOENT: 2503 case ENOTDIR: 2504 smbfs_attrcache_prune(np); 2505 break; 2506 } 2507 2508 if (error) 2509 goto out; 2510 2511 mutex_enter(&np->r_statelock); 2512 dnp->n_flag |= NMODIFIED; 2513 mutex_exit(&np->r_statelock); 2514 smbfs_attr_touchdir(dnp); 2515 smbfs_rmhash(np); 2516 2517 out: 2518 if (vp) { 2519 if (vp_locked) 2520 vn_vfsunlock(vp); 2521 VN_RELE(vp); 2522 } 2523 smb_credrele(&scred); 2524 smbfs_rw_exit(&dnp->r_rwlock); 2525 2526 return (error); 2527 } 2528 2529 2530 /* ARGSUSED */ 2531 static int 2532 smbfs_readdir(vnode_t *vp, struct uio *uiop, cred_t *cr, int *eofp, 2533 caller_context_t *ct, int flags) 2534 { 2535 struct smbnode *np = VTOSMB(vp); 2536 int error = 0; 2537 smbmntinfo_t *smi; 2538 2539 smi = VTOSMI(vp); 2540 2541 if (curproc->p_zone != smi->smi_zone) 2542 return (EIO); 2543 2544 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 2545 return (EIO); 2546 2547 /* 2548 * Require read access in the directory. 2549 */ 2550 error = smbfs_access(vp, VREAD, 0, cr, ct); 2551 if (error) 2552 return (error); 2553 2554 ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_READER)); 2555 2556 /* 2557 * XXX: Todo readdir cache here 2558 * Note: NFS code is just below this. 2559 * 2560 * I am serializing the entire readdir opreation 2561 * now since we have not yet implemented readdir 2562 * cache. This fix needs to be revisited once 2563 * we implement readdir cache. 2564 */ 2565 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, SMBINTR(vp))) 2566 return (EINTR); 2567 2568 error = smbfs_readvdir(vp, uiop, cr, eofp, ct); 2569 2570 smbfs_rw_exit(&np->r_lkserlock); 2571 2572 return (error); 2573 } 2574 2575 /* ARGSUSED */ 2576 static int 2577 smbfs_readvdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp, 2578 caller_context_t *ct) 2579 { 2580 /* 2581 * Note: "limit" tells the SMB-level FindFirst/FindNext 2582 * functions how many directory entries to request in 2583 * each OtW call. It needs to be large enough so that 2584 * we don't make lots of tiny OtW requests, but there's 2585 * no point making it larger than the maximum number of 2586 * OtW entries that would fit in a maximum sized trans2 2587 * response (64k / 48). Beyond that, it's just tuning. 2588 * WinNT used 512, Win2k used 1366. We use 1000. 2589 */ 2590 static const int limit = 1000; 2591 /* Largest possible dirent size. */ 2592 static const size_t dbufsiz = DIRENT64_RECLEN(SMB_MAXFNAMELEN); 2593 struct smb_cred scred; 2594 vnode_t *newvp; 2595 struct smbnode *np = VTOSMB(vp); 2596 struct smbfs_fctx *ctx; 2597 struct dirent64 *dp; 2598 ssize_t save_resid; 2599 offset_t save_offset; /* 64 bits */ 2600 int offset; /* yes, 32 bits */ 2601 int nmlen, error; 2602 ushort_t reclen; 2603 2604 ASSERT(curproc->p_zone == VTOSMI(vp)->smi_zone); 2605 2606 /* Make sure we serialize for n_dirseq use. */ 2607 ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_WRITER)); 2608 2609 /* 2610 * Make sure smbfs_open filled in n_dirseq 2611 */ 2612 if (np->n_dirseq == NULL) 2613 return (EBADF); 2614 2615 /* Check for overflow of (32-bit) directory offset. */ 2616 if (uio->uio_loffset < 0 || uio->uio_loffset > INT32_MAX || 2617 (uio->uio_loffset + uio->uio_resid) > INT32_MAX) 2618 return (EINVAL); 2619 2620 /* Require space for at least one dirent. */ 2621 if (uio->uio_resid < dbufsiz) 2622 return (EINVAL); 2623 2624 SMBVDEBUG("dirname='%s'\n", np->n_rpath); 2625 smb_credinit(&scred, cr); 2626 dp = kmem_alloc(dbufsiz, KM_SLEEP); 2627 2628 save_resid = uio->uio_resid; 2629 save_offset = uio->uio_loffset; 2630 offset = uio->uio_offset; 2631 SMBVDEBUG("in: offset=%d, resid=%d\n", 2632 (int)uio->uio_offset, (int)uio->uio_resid); 2633 error = 0; 2634 2635 /* 2636 * Generate the "." and ".." entries here so we can 2637 * (1) make sure they appear (but only once), and 2638 * (2) deal with getting their I numbers which the 2639 * findnext below does only for normal names. 2640 */ 2641 while (offset < FIRST_DIROFS) { 2642 /* 2643 * Tricky bit filling in the first two: 2644 * offset 0 is ".", offset 1 is ".." 2645 * so strlen of these is offset+1. 2646 */ 2647 reclen = DIRENT64_RECLEN(offset + 1); 2648 if (uio->uio_resid < reclen) 2649 goto out; 2650 bzero(dp, reclen); 2651 dp->d_reclen = reclen; 2652 dp->d_name[0] = '.'; 2653 dp->d_name[1] = '.'; 2654 dp->d_name[offset + 1] = '\0'; 2655 /* 2656 * Want the real I-numbers for the "." and ".." 2657 * entries. For these two names, we know that 2658 * smbfslookup can get the nodes efficiently. 2659 */ 2660 error = smbfslookup(vp, dp->d_name, &newvp, cr, 1, ct); 2661 if (error) { 2662 dp->d_ino = np->n_ino + offset; /* fiction */ 2663 } else { 2664 dp->d_ino = VTOSMB(newvp)->n_ino; 2665 VN_RELE(newvp); 2666 } 2667 /* 2668 * Note: d_off is the offset that a user-level program 2669 * should seek to for reading the NEXT directory entry. 2670 * See libc: readdir, telldir, seekdir 2671 */ 2672 dp->d_off = offset + 1; 2673 error = uiomove(dp, reclen, UIO_READ, uio); 2674 if (error) 2675 goto out; 2676 /* 2677 * Note: uiomove updates uio->uio_offset, 2678 * but we want it to be our "cookie" value, 2679 * which just counts dirents ignoring size. 2680 */ 2681 uio->uio_offset = ++offset; 2682 } 2683 2684 /* 2685 * If there was a backward seek, we have to reopen. 2686 */ 2687 if (offset < np->n_dirofs) { 2688 SMBVDEBUG("Reopening search %d:%d\n", 2689 offset, np->n_dirofs); 2690 error = smbfs_smb_findopen(np, "*", 1, 2691 SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_DIR, 2692 &scred, &ctx); 2693 if (error) { 2694 SMBVDEBUG("can not open search, error = %d", error); 2695 goto out; 2696 } 2697 /* free the old one */ 2698 (void) smbfs_smb_findclose(np->n_dirseq, &scred); 2699 /* save the new one */ 2700 np->n_dirseq = ctx; 2701 np->n_dirofs = FIRST_DIROFS; 2702 } else { 2703 ctx = np->n_dirseq; 2704 } 2705 2706 /* 2707 * Skip entries before the requested offset. 2708 */ 2709 while (np->n_dirofs < offset) { 2710 error = smbfs_smb_findnext(ctx, limit, &scred); 2711 if (error != 0) 2712 goto out; 2713 np->n_dirofs++; 2714 } 2715 2716 /* 2717 * While there's room in the caller's buffer: 2718 * get a directory entry from SMB, 2719 * convert to a dirent, copyout. 2720 * We stop when there is no longer room for a 2721 * maximum sized dirent because we must decide 2722 * before we know anything about the next entry. 2723 */ 2724 while (uio->uio_resid >= dbufsiz) { 2725 error = smbfs_smb_findnext(ctx, limit, &scred); 2726 if (error != 0) 2727 goto out; 2728 np->n_dirofs++; 2729 2730 /* Sanity check the name length. */ 2731 nmlen = ctx->f_nmlen; 2732 if (nmlen > SMB_MAXFNAMELEN) { 2733 nmlen = SMB_MAXFNAMELEN; 2734 SMBVDEBUG("Truncating name: %s\n", ctx->f_name); 2735 } 2736 if (smbfs_fastlookup) { 2737 /* See comment at smbfs_fastlookup above. */ 2738 if (smbfs_nget(vp, ctx->f_name, nmlen, 2739 &ctx->f_attr, &newvp) == 0) 2740 VN_RELE(newvp); 2741 } 2742 2743 reclen = DIRENT64_RECLEN(nmlen); 2744 bzero(dp, reclen); 2745 dp->d_reclen = reclen; 2746 bcopy(ctx->f_name, dp->d_name, nmlen); 2747 dp->d_name[nmlen] = '\0'; 2748 dp->d_ino = ctx->f_inum; 2749 dp->d_off = offset + 1; /* See d_off comment above */ 2750 error = uiomove(dp, reclen, UIO_READ, uio); 2751 if (error) 2752 goto out; 2753 /* See comment re. uio_offset above. */ 2754 uio->uio_offset = ++offset; 2755 } 2756 2757 out: 2758 /* 2759 * When we come to the end of a directory, the 2760 * SMB-level functions return ENOENT, but the 2761 * caller is not expecting an error return. 2762 * 2763 * Also note that we must delay the call to 2764 * smbfs_smb_findclose(np->n_dirseq, ...) 2765 * until smbfs_close so that all reads at the 2766 * end of the directory will return no data. 2767 */ 2768 if (error == ENOENT) { 2769 error = 0; 2770 if (eofp) 2771 *eofp = 1; 2772 } 2773 /* 2774 * If we encountered an error (i.e. "access denied") 2775 * from the FindFirst call, we will have copied out 2776 * the "." and ".." entries leaving offset == 2. 2777 * In that case, restore the original offset/resid 2778 * so the caller gets no data with the error. 2779 */ 2780 if (error != 0 && offset == FIRST_DIROFS) { 2781 uio->uio_loffset = save_offset; 2782 uio->uio_resid = save_resid; 2783 } 2784 SMBVDEBUG("out: offset=%d, resid=%d\n", 2785 (int)uio->uio_offset, (int)uio->uio_resid); 2786 2787 kmem_free(dp, dbufsiz); 2788 smb_credrele(&scred); 2789 return (error); 2790 } 2791 2792 2793 /* 2794 * The pair of functions VOP_RWLOCK, VOP_RWUNLOCK 2795 * are optional functions that are called by: 2796 * getdents, before/after VOP_READDIR 2797 * pread, before/after ... VOP_READ 2798 * pwrite, before/after ... VOP_WRITE 2799 * (other places) 2800 * 2801 * Careful here: None of the above check for any 2802 * error returns from VOP_RWLOCK / VOP_RWUNLOCK! 2803 * In fact, the return value from _rwlock is NOT 2804 * an error code, but V_WRITELOCK_TRUE / _FALSE. 2805 * 2806 * Therefore, it's up to _this_ code to make sure 2807 * the lock state remains balanced, which means 2808 * we can't "bail out" on interrupts, etc. 2809 */ 2810 2811 /* ARGSUSED2 */ 2812 static int 2813 smbfs_rwlock(vnode_t *vp, int write_lock, caller_context_t *ctp) 2814 { 2815 smbnode_t *np = VTOSMB(vp); 2816 2817 if (!write_lock) { 2818 (void) smbfs_rw_enter_sig(&np->r_rwlock, RW_READER, FALSE); 2819 return (V_WRITELOCK_FALSE); 2820 } 2821 2822 2823 (void) smbfs_rw_enter_sig(&np->r_rwlock, RW_WRITER, FALSE); 2824 return (V_WRITELOCK_TRUE); 2825 } 2826 2827 /* ARGSUSED */ 2828 static void 2829 smbfs_rwunlock(vnode_t *vp, int write_lock, caller_context_t *ctp) 2830 { 2831 smbnode_t *np = VTOSMB(vp); 2832 2833 smbfs_rw_exit(&np->r_rwlock); 2834 } 2835 2836 2837 /* ARGSUSED */ 2838 static int 2839 smbfs_seek(vnode_t *vp, offset_t ooff, offset_t *noffp, caller_context_t *ct) 2840 { 2841 smbmntinfo_t *smi; 2842 2843 smi = VTOSMI(vp); 2844 2845 if (curproc->p_zone != smi->smi_zone) 2846 return (EPERM); 2847 2848 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 2849 return (EIO); 2850 2851 /* 2852 * Because we stuff the readdir cookie into the offset field 2853 * someone may attempt to do an lseek with the cookie which 2854 * we want to succeed. 2855 */ 2856 if (vp->v_type == VDIR) 2857 return (0); 2858 2859 /* Like NFS3, just check for 63-bit overflow. */ 2860 if (*noffp < 0) 2861 return (EINVAL); 2862 2863 return (0); 2864 } 2865 2866 2867 /* 2868 * XXX 2869 * This op may need to support PSARC 2007/440, nbmand changes for CIFS Service. 2870 */ 2871 static int 2872 smbfs_frlock(vnode_t *vp, int cmd, struct flock64 *bfp, int flag, 2873 offset_t offset, struct flk_callback *flk_cbp, cred_t *cr, 2874 caller_context_t *ct) 2875 { 2876 if (curproc->p_zone != VTOSMI(vp)->smi_zone) 2877 return (EIO); 2878 2879 if (VTOSMI(vp)->smi_flags & SMI_LLOCK) 2880 return (fs_frlock(vp, cmd, bfp, flag, offset, flk_cbp, cr, ct)); 2881 else 2882 return (ENOSYS); 2883 } 2884 2885 /* 2886 * Free storage space associated with the specified vnode. The portion 2887 * to be freed is specified by bfp->l_start and bfp->l_len (already 2888 * normalized to a "whence" of 0). 2889 * 2890 * Called by fcntl(fd, F_FREESP, lkp) for libc:ftruncate, etc. 2891 */ 2892 /* ARGSUSED */ 2893 static int 2894 smbfs_space(vnode_t *vp, int cmd, struct flock64 *bfp, int flag, 2895 offset_t offset, cred_t *cr, caller_context_t *ct) 2896 { 2897 int error; 2898 smbmntinfo_t *smi; 2899 2900 smi = VTOSMI(vp); 2901 2902 if (curproc->p_zone != smi->smi_zone) 2903 return (EIO); 2904 2905 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 2906 return (EIO); 2907 2908 /* Caller (fcntl) has checked v_type */ 2909 ASSERT(vp->v_type == VREG); 2910 if (cmd != F_FREESP) 2911 return (EINVAL); 2912 2913 /* 2914 * Like NFS3, no 32-bit offset checks here. 2915 * Our SMB layer takes care to return EFBIG 2916 * when it has to fallback to a 32-bit call. 2917 */ 2918 2919 error = convoff(vp, bfp, 0, offset); 2920 if (!error) { 2921 ASSERT(bfp->l_start >= 0); 2922 if (bfp->l_len == 0) { 2923 struct vattr va; 2924 2925 /* 2926 * ftruncate should not change the ctime and 2927 * mtime if we truncate the file to its 2928 * previous size. 2929 */ 2930 va.va_mask = AT_SIZE; 2931 error = smbfsgetattr(vp, &va, cr); 2932 if (error || va.va_size == bfp->l_start) 2933 return (error); 2934 va.va_mask = AT_SIZE; 2935 va.va_size = bfp->l_start; 2936 error = smbfssetattr(vp, &va, 0, cr); 2937 } else 2938 error = EINVAL; 2939 } 2940 2941 return (error); 2942 } 2943 2944 /* ARGSUSED */ 2945 static int 2946 smbfs_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr, 2947 caller_context_t *ct) 2948 { 2949 vfs_t *vfs; 2950 smbmntinfo_t *smi; 2951 struct smb_share *ssp; 2952 2953 vfs = vp->v_vfsp; 2954 smi = VFTOSMI(vfs); 2955 2956 if (curproc->p_zone != smi->smi_zone) 2957 return (EIO); 2958 2959 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 2960 return (EIO); 2961 2962 switch (cmd) { 2963 case _PC_FILESIZEBITS: 2964 ssp = smi->smi_share; 2965 if (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES) 2966 *valp = 64; 2967 else 2968 *valp = 32; 2969 break; 2970 2971 case _PC_LINK_MAX: 2972 /* We only ever report one link to an object */ 2973 *valp = 1; 2974 break; 2975 2976 case _PC_ACL_ENABLED: 2977 /* 2978 * Always indicate that ACLs are enabled and 2979 * that we support ACE_T format, otherwise 2980 * libsec will ask for ACLENT_T format data 2981 * which we don't support. 2982 */ 2983 *valp = _ACL_ACE_ENABLED; 2984 break; 2985 2986 case _PC_SYMLINK_MAX: /* No symlinks until we do Unix extensions */ 2987 *valp = 0; 2988 break; 2989 2990 case _PC_XATTR_EXISTS: 2991 if (vfs->vfs_flag & VFS_XATTR) { 2992 *valp = smbfs_xa_exists(vp, cr); 2993 break; 2994 } 2995 return (EINVAL); 2996 2997 case _PC_TIMESTAMP_RESOLUTION: 2998 /* 2999 * Windows times are tenths of microseconds 3000 * (multiples of 100 nanoseconds). 3001 */ 3002 *valp = 100L; 3003 break; 3004 3005 default: 3006 return (fs_pathconf(vp, cmd, valp, cr, ct)); 3007 } 3008 return (0); 3009 } 3010 3011 /* ARGSUSED */ 3012 static int 3013 smbfs_getsecattr(vnode_t *vp, vsecattr_t *vsa, int flag, cred_t *cr, 3014 caller_context_t *ct) 3015 { 3016 vfs_t *vfsp; 3017 smbmntinfo_t *smi; 3018 int error; 3019 uint_t mask; 3020 3021 vfsp = vp->v_vfsp; 3022 smi = VFTOSMI(vfsp); 3023 3024 if (curproc->p_zone != smi->smi_zone) 3025 return (EIO); 3026 3027 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED) 3028 return (EIO); 3029 3030 /* 3031 * Our _pathconf indicates _ACL_ACE_ENABLED, 3032 * so we should only see VSA_ACE, etc here. 3033 * Note: vn_create asks for VSA_DFACLCNT, 3034 * and it expects ENOSYS and empty data. 3035 */ 3036 mask = vsa->vsa_mask & (VSA_ACE | VSA_ACECNT | 3037 VSA_ACE_ACLFLAGS | VSA_ACE_ALLTYPES); 3038 if (mask == 0) 3039 return (ENOSYS); 3040 3041 if (smi->smi_flags & SMI_ACL) 3042 error = smbfs_acl_getvsa(vp, vsa, flag, cr); 3043 else 3044 error = ENOSYS; 3045 3046 if (error == ENOSYS) 3047 error = fs_fab_acl(vp, vsa, flag, cr, ct); 3048 3049 return (error); 3050 } 3051 3052 /* ARGSUSED */ 3053 static int 3054 smbfs_setsecattr(vnode_t *vp, vsecattr_t *vsa, int flag, cred_t *cr, 3055 caller_context_t *ct) 3056 { 3057 vfs_t *vfsp; 3058 smbmntinfo_t *smi; 3059 int error; 3060 uint_t mask; 3061 3062 vfsp = vp->v_vfsp; 3063 smi = VFTOSMI(vfsp); 3064 3065 if (curproc->p_zone != smi->smi_zone) 3066 return (EIO); 3067 3068 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED) 3069 return (EIO); 3070 3071 /* 3072 * Our _pathconf indicates _ACL_ACE_ENABLED, 3073 * so we should only see VSA_ACE, etc here. 3074 */ 3075 mask = vsa->vsa_mask & (VSA_ACE | VSA_ACECNT); 3076 if (mask == 0) 3077 return (ENOSYS); 3078 3079 if (vfsp->vfs_flag & VFS_RDONLY) 3080 return (EROFS); 3081 3082 /* 3083 * Allow only the mount owner to do this. 3084 * See comments at smbfs_access_rwx. 3085 */ 3086 error = secpolicy_vnode_setdac(cr, smi->smi_uid); 3087 if (error != 0) 3088 return (error); 3089 3090 if (smi->smi_flags & SMI_ACL) 3091 error = smbfs_acl_setvsa(vp, vsa, flag, cr); 3092 else 3093 error = ENOSYS; 3094 3095 return (error); 3096 } 3097 3098 3099 /* 3100 * XXX 3101 * This op should eventually support PSARC 2007/268. 3102 */ 3103 static int 3104 smbfs_shrlock(vnode_t *vp, int cmd, struct shrlock *shr, int flag, cred_t *cr, 3105 caller_context_t *ct) 3106 { 3107 if (curproc->p_zone != VTOSMI(vp)->smi_zone) 3108 return (EIO); 3109 3110 if (VTOSMI(vp)->smi_flags & SMI_LLOCK) 3111 return (fs_shrlock(vp, cmd, shr, flag, cr, ct)); 3112 else 3113 return (ENOSYS); 3114 } 3115