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