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