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