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