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