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