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