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