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