1/* 2 * Copyright (c) 2000-2001 Boris Popov 3 * All rights reserved. 4 * 5 * Portions Copyright (C) 2001 - 2014 Apple Inc. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Boris Popov. 18 * 4. Neither the name of the author nor the names of any co-contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 */ 35#include <sys/param.h> 36#include <sys/systm.h> 37#include <sys/vnode.h> 38#include <sys/xattr.h> 39#include <sys/kernel.h> 40#include <sys/proc.h> 41#include <sys/fcntl.h> 42#include <sys/mount.h> 43#include <sys/unistd.h> 44#include <sys/lockf.h> 45#include <sys/stat.h> 46#include <sys/mman.h> 47#include <vfs/vfs_support.h> 48#include <sys/namei.h> 49#include <libkern/OSAtomic.h> 50#include <sys/attr.h> 51#include <sys/kauth.h> 52#include <sys/syslog.h> 53 54#include <sys/smb_apple.h> 55#include <sys/smb_byte_order.h> 56#include <sys/mchain.h> 57#include <sys/msfscc.h> 58 59#include <netsmb/smb.h> 60#include <netsmb/smb_2.h> 61#include <netsmb/smb_rq.h> 62#include <netsmb/smb_rq_2.h> 63#include <netsmb/smb_conn.h> 64#include <netsmb/smb_conn_2.h> 65#include <netsmb/smb_subr.h> 66 67#include <smbfs/smbfs.h> 68#include <smbfs/smbfs_node.h> 69#include <smbfs/smbfs_subr.h> 70#include <smbfs/smbfs_subr_2.h> 71#include <smbfs/smbfs_lockf.h> 72#include <netsmb/smb_converter.h> 73#include <smbfs/smbfs_security.h> 74#include <smbfs/smbfs_attrlist.h> 75 76#include <sys/buf.h> 77 78char smb_symmagic[SMB_SYMMAGICLEN] = {'X', 'S', 'y', 'm', '\n'}; 79 80static int smbfs_setattr(struct smb_share *share, vnode_t vp, struct vnode_attr *vap, 81 vfs_context_t context); 82static void smbfs_set_create_vap(struct smb_share *share, struct vnode_attr *vap, vnode_t vp, 83 vfs_context_t context, int set_mode_now); 84static int smbfs_vnop_compound_open(struct vnop_compound_open_args *ap); 85static int smbfs_vnop_open(struct vnop_open_args *ap); 86 87/* 88 * We were doing an IO and received an error. Was the error caused because we were 89 * reconnecting to the server. If yes then see if we can reopen the file. If everything 90 * is ok and the file was reopened then get the fid we need for doing the IO. 91 * 92 * The calling routine must hold a reference on the share 93 * 94 */ 95static int 96smbfs_io_reopen(struct smb_share *share, vnode_t vp, uio_t uio, 97 uint16_t accessMode, SMBFID *fid, int error, 98 vfs_context_t context) 99{ 100 struct smbnode *np = VTOSMB(vp); 101 102 if (!(np->f_openState & kNeedReopen)) 103 return(error); 104 105 error = smbfs_smb_reopen_file(share, np, context); 106 if (error) 107 return(error); 108 109 if (FindFileRef(vp, vfs_context_proc(context), accessMode, kCheckDenyOrLocks, 110 uio_offset(uio), uio_resid(uio), NULL, fid)) { 111 *fid = np->f_fid; 112 } 113 114 /* Should always have a fid at this point */ 115 DBG_ASSERT(*fid != 0); 116 return(0); 117} 118 119/* 120 * smbfs_update_cache 121 * 122 * General routine that will update the meta data cache for the vnode. If a vap 123 * is passed in it will get filled in with the correct information, otherwise it 124 * will be ignored. 125 * 126 * The calling routine must hold a reference on the share 127 * 128 */ 129int 130smbfs_update_cache(struct smb_share *share, vnode_t vp, 131 struct vnode_attr *vap, vfs_context_t context) 132 { 133 /* If we are in reconnect mode, then use cached data for now. */ 134 int use_cached_data = 0; 135 struct smbfattr fattr; 136 int error = 0; 137 138 /* If we are in reconnect, use cached data if we have it */ 139 if (VTOSMB(vp)->attribute_cache_timer != 0) { 140 use_cached_data = (share->ss_flags & SMBS_RECONNECTING); 141 } 142 143 error = smbfs_attr_cachelookup(share, vp, vap, context, use_cached_data); 144 145 SMB_LOG_KTRACE(SMB_DBG_SMBFS_UPDATE_CACHE | DBG_FUNC_START, 146 error, 0, 0, 0, 0); 147 148 if (error != ENOENT) { 149 goto done; 150 } 151 152 error = smbfs_lookup(share, VTOSMB(vp), NULL, NULL, &fattr, context); 153 SMB_LOG_KTRACE(SMB_DBG_SMBFS_UPDATE_CACHE | DBG_FUNC_NONE, 154 0xabc001, error, 0, 0, 0); 155 156 if ((error == ETIMEDOUT) && (VTOSMB(vp)->attribute_cache_timer != 0)) { 157 /* Just return the cached data */ 158 use_cached_data = TRUE; 159 goto use_cache; 160 } 161 162 if (error) { 163 goto done; 164 } 165 166 /* 167 * At this point we have the data from the server, so we can 168 * just use cached data for now. See <rdar://problem/13813721>. 169 */ 170 use_cached_data = TRUE; 171 172 /* Enter in the latest data from the server into the caches */ 173 smbfs_attr_cacheenter(share, vp, &fattr, TRUE, context); 174 175use_cache: 176 error = smbfs_attr_cachelookup(share, vp, vap, context, use_cached_data); 177 178done: 179 SMB_LOG_KTRACE(SMB_DBG_SMBFS_UPDATE_CACHE | DBG_FUNC_END, error, 0, 0, 0, 0); 180 return (error); 181 } 182 183/* 184 * smbfs_close - The internal open routine, the vnode should be locked 185 * before this is called. We only handle VREG in this routine. 186 * 187 * The calling routine must hold a reference on the share 188 * 189 */ 190int 191smbfs_close(struct smb_share *share, vnode_t vp, int openMode, 192 vfs_context_t context) 193{ 194 struct smbnode *np = VTOSMB(vp); 195 proc_t p = vfs_context_proc(context); 196 struct fileRefEntry *fndEntry = NULL; 197 struct fileRefEntry *curr = NULL; 198 int error = 0; 199 uint16_t accessMode = 0; 200 SMBFID fid = 0; 201 int32_t needOpenFile; 202 uint16_t openAccessMode; 203 uint32_t rights; 204 struct smbfattr *fap = NULL; 205 206 /* 207 * We have more than one open, so before closing see if the file needs to 208 * be reopened 209 */ 210 if ((np->f_refcnt > 1) && (smbfs_smb_reopen_file(share, np, context) == EIO)) { 211 lck_rw_lock_shared(&np->n_name_rwlock); 212 SMBDEBUG(" %s waiting to be revoked\n", np->n_name); 213 lck_rw_unlock_shared(&np->n_name_rwlock); 214 215 np->f_refcnt--; 216 return (0); 217 } 218 219 SMB_LOG_KTRACE(SMB_DBG_SMBFS_CLOSE | DBG_FUNC_START, 220 openMode, np->f_refcnt, 0, 0, 0); 221 222 if (openMode & FREAD) 223 accessMode |= kAccessRead; 224 225 if (openMode & FWRITE) 226 accessMode |= kAccessWrite; 227 228 /* Check the number of times Open() was called */ 229 if (np->f_refcnt == 1) { 230 ubc_msync(vp, 0, ubc_getsize(vp), NULL, UBC_PUSHDIRTY | UBC_SYNC | UBC_INVALIDATE); 231 /* 232 * This is the last Close() we will get, so close sharedForkRef 233 * and any other forks created by ByteRangeLocks 234 */ 235 if (np->f_fid != 0) { 236 SMBFID oldFID = np->f_fid; 237 238 /* Close the shared file first. Clear out the refs to it 239 * first so that no one else trys to use it while I'm waiting 240 * for the close file reply to arrive. There was a case 241 * where cluster i/o was firing off after I sent the close 242 * file req, but had not gotten the close file reply yet 243 * and tyring to still use the shared file 244 */ 245 np->f_fid = 0; /* clear the ref num */ 246 np->f_accessMode = 0; 247 np->f_rights = 0; 248 np->f_openRWCnt = 0; 249 np->f_openRCnt = 0; 250 np->f_openWCnt = 0; 251 np->f_openTotalWCnt = 0; 252 np->f_needClose = 0; 253 np->f_clusterCloseError = 0; 254 /* 255 * They didn't unlock the file before closing. A SMB close will remove 256 * any locks so lets free the memory associated with that lock. 257 */ 258 if (np->f_smbflock) { 259 SMB_FREE(np->f_smbflock, M_LOCKF); 260 np->f_smbflock = NULL; 261 } 262 error = smbfs_smb_close(share, oldFID, context); 263 if (error) { 264 SMBWARNING("close file failed %d on fid %llx\n", 265 error, oldFID); 266 } 267 } 268 269 /* Remove forks that were opened due to ByteRangeLocks or DenyModes */ 270 lck_mtx_lock(&np->f_openDenyListLock); 271 curr = np->f_openDenyList; 272 while (curr != NULL) { 273 error = smbfs_smb_close(share, curr->fid, context); 274 if (error) { 275 SMBWARNING("close file failed %d on fid %llx\n", 276 error, curr->fid); 277 } 278 curr = curr->next; 279 } 280 lck_mtx_unlock(&np->f_openDenyListLock); 281 np->f_refcnt = 0; 282 RemoveFileRef (vp, NULL); /* remove all file refs */ 283 284 /* 285 * We did the last close on the file. This file is 286 * marked for deletion on close. So lets delete it 287 * here. If we get an error then try again when the node 288 * becomes inactive. 289 */ 290 if (np->n_flag & NDELETEONCLOSE) { 291 if (smbfs_smb_delete(share, np, VREG, 292 NULL, 0, 293 0, context) == 0) { 294 np->n_flag &= ~NDELETEONCLOSE; 295 296 /* Assume the file is now deleted on the server */ 297 smb_vhashrem(np); 298 299 lck_rw_lock_shared(&np->n_parent_rwlock); 300 if (np->n_parent != NULL) { 301 smbfs_attr_touchdir(np->n_parent, (share->ss_fstype == SMB_FS_FAT)); 302 np->n_parent->d_changecnt++; 303 304 /* Remove any negative cache entries. */ 305 if (np->n_parent->n_flag & NNEGNCENTRIES) { 306 np->n_parent->n_flag &= ~NNEGNCENTRIES; 307 cache_purge_negatives(np->n_parent->n_vnode); 308 } 309 } 310 lck_rw_unlock_shared(&np->n_parent_rwlock); 311 } 312 } 313 314 /* 315 * It was not cacheable before, but now that all files are closed, 316 * make it cacheable again (if its a valid cacheable file). If 317 * we were caching should we remove attributes cache. Realy only 318 * matters when we turn on cluster io? 319 */ 320 if (vnode_isnocache(vp)) 321 vnode_clearnocache(vp); 322 323 /* Did we change the file during the open */ 324 if (np->n_flag & NATTRCHANGED) 325 np->attribute_cache_timer = 0; 326 327 lck_mtx_lock(&np->f_openStateLock); 328 if (np->f_openState & kNeedRevoke) 329 error = 0; 330 /* 331 * Clear all the f_openState flags, we are closed. If we have a pending 332 * revoke clear that out, the file is closed no need to revoke it now. 333 */ 334 np->f_openState = 0; 335 lck_mtx_unlock(&np->f_openStateLock); 336 337 goto exit; 338 } 339 340 /* More than one open */ 341 342 /* 343 * See if we can match this Close() to a matching file that has byte range 344 * locks or denyModes. 345 * 346 * NOTE: FHASLOCK can be set by open with O_EXCLUSIVE or O_SHARED which 347 * maps to my deny modes or FHASLOCK could also have been set/cleared 348 * by calling flock directly. 349 * 350 * Cases that work are: 351 * 1) Carbon using deny modes and thus FHASLOCK maps to my deny modes. 352 * No flock being used. 353 * 2) Cocoa using open with O_EXCLUSIVE or O_SHARED and not calling flock. 354 * 3) Cocoa using open, then calling flock and later calling flock 355 * to unlock before close. 356 * 4) Cocoa open, then calling flock, but not calling flock to unlock 357 * before close. I would fall through to the shared fork code correctly. 358 * 359 * Cases that may not work are: 360 * 1) Carbon using deny modes and then calling flock to unlock, thus 361 * clearing FHASLOCK flag.I would assume it was the shared file. 362 * 2) Cocoa open with O_EXCLUSIVE or O_SHARED and then calling flock 363 * to lock and then unlock, then calling close. 364 * 3) ??? 365 */ 366 if (openMode & FHASLOCK) { 367 uint16_t tempAccessMode = accessMode; 368 369 /* Try with denyWrite, if not found, then try with denyRead/denyWrite */ 370 tempAccessMode |= kDenyWrite; 371 error = FindFileRef(vp, p, tempAccessMode, kExactMatch, 0, 0, &fndEntry, 372 &fid); 373 if (error != 0) { 374 tempAccessMode |= kDenyRead; 375 error = FindFileRef(vp, p, tempAccessMode, kExactMatch, 0, 0, 376 &fndEntry, &fid); 377 } 378 if (error == 0) 379 accessMode = tempAccessMode; 380 381 SMB_LOG_KTRACE(SMB_DBG_SMBFS_CLOSE | DBG_FUNC_NONE, 382 0xabc001, error, 0, 0, 0); 383 } else { 384 /* No deny modes used, so look for any forks opened for byteRangeLocks */ 385 error = FindFileRef(vp, p, accessMode, kExactMatch, 0, 0, &fndEntry, &fid); 386 SMB_LOG_KTRACE(SMB_DBG_SMBFS_CLOSE | DBG_FUNC_NONE, 387 0xabc002, error, 0, 0, 0); 388 } 389 390 /* always decrement the count, dont care if got an error or not */ 391 if (np->f_refcnt > 0) { 392 np->f_refcnt--; 393 } 394 395 /* 396 * We have an Open Deny entry that is being used by more than one open call, 397 * just decrement it and get out. 398 * This code should be combined with the code right below here. 399 */ 400 if ((error == 0) && fndEntry && (fndEntry->refcnt > 0)) { 401 fndEntry->refcnt--; 402 SMB_LOG_KTRACE(SMB_DBG_SMBFS_CLOSE | DBG_FUNC_NONE, 403 0xabc003, error, 0, 0, 0); 404 goto exit; 405 } 406 407 /* 408 * We have an Open Deny entry that is all done. Time to close it. 409 * This code should be combined with the code right above here. 410 */ 411 if ((error == 0) && fndEntry) { 412 error = smbfs_smb_close(share, fndEntry->fid, context); 413 /* We are not going to get another close, so always remove it from the list */ 414 RemoveFileRef(vp, fndEntry); 415 SMB_LOG_KTRACE(SMB_DBG_SMBFS_CLOSE | DBG_FUNC_NONE, 416 0xabc004, error, 0, 0, 0); 417 goto exit; 418 } 419 420 /* 421 * Not an open deny mode open. 422 * 423 * An oddity. If first open was read/write/denyWrite and then a second 424 * open of just read, then the second open will open the shared fork. 425 * Now, get a close on the "read" fork, the np->f_refcnt will be 2, and we 426 * will end up here. The np->f_refcnt will be decremented to 1 so the next 427 * close call will close everything. In the meantime, we end up leaving 428 * the shared fork open with "read" and thus we actually have two forks 429 * open, one for the read/write/denyWrite and the other is the shared fork. 430 * We have has this behavior for a long time and just have not noticed. 431 * Since its an edge case and no one has complained, we can leave it this 432 * way for now. 433 */ 434 needOpenFile = 0; 435 openAccessMode = 0; 436 fid = 0; 437 rights = SMB2_READ_CONTROL; 438 439 /* 440 * Just return 0 for no err, but dont close the file since another 441 * process is still using it 442 */ 443 error = 0; 444 445 /* Check to downgrade access mode if needed */ 446 switch (accessMode) { 447 case (kAccessRead | kAccessWrite): 448 np->f_openRWCnt -= 1; 449 if ((np->f_openRWCnt == 0) && (np->f_openRCnt > 0) && (np->f_openWCnt == 0)) { 450 /* drop from rw to read only */ 451 needOpenFile = 1; 452 openAccessMode = kAccessRead; 453 rights |= SMB2_FILE_READ_DATA; 454 } 455 /* Dont ever downgrade to write only since Unix expects read/write */ 456 break; 457 case kAccessRead: 458 np->f_openRCnt -= 1; 459 /* Dont ever downgrade to write only since Unix expects read/write */ 460 break; 461 case kAccessWrite: 462 np->f_openWCnt -= 1; 463 if ( (np->f_openRCnt > 0) && (np->f_openRWCnt == 0) && 464 (np->f_openWCnt == 0) ) { 465 /* drop from rw to read only */ 466 needOpenFile = 1; 467 openAccessMode = kAccessRead; 468 rights |= SMB2_FILE_READ_DATA; 469 } 470 break; 471 } 472 /* set up for the open fork */ 473 if (needOpenFile == 1) { 474 SMB_MALLOC(fap, 475 struct smbfattr *, 476 sizeof(struct smbfattr), 477 M_SMBTEMP, 478 M_WAITOK | M_ZERO); 479 if (fap == NULL) { 480 SMBERROR("SMB_MALLOC failed\n"); 481 error = ENOMEM; 482 goto exit; 483 } 484 485 error = smbfs_smb_open_file(share, np, 486 rights, NTCREATEX_SHARE_ACCESS_ALL, &fid, 487 NULL, 0, FALSE, 488 fap, context); 489 SMB_LOG_KTRACE(SMB_DBG_SMBFS_CLOSE | DBG_FUNC_NONE, 490 0xabc005, error, 0, 0, 0); 491 if (error == 0) { 492 SMBFID oldFID = np->f_fid; 493 494 /* We are downgrading the open flush it out any data */ 495 ubc_msync(vp, 0, ubc_getsize(vp), NULL, UBC_PUSHDIRTY | UBC_SYNC | UBC_INVALIDATE); 496 /* Close the shared file first and use this new one now 497 * Switch the ref before closing the old shared file so the 498 * old file wont get used while its being closed. 499 */ 500 np->f_fid = fid; /* reset the ref num */ 501 np->f_accessMode = openAccessMode; 502 np->f_rights = rights; 503 error = smbfs_smb_close(share, oldFID, context); 504 if (error) { 505 SMBWARNING("close file failed %d on fid %llx\n", error, oldFID); 506 } 507 SMB_LOG_KTRACE(SMB_DBG_SMBFS_CLOSE | DBG_FUNC_NONE, 508 0xabc006, error, 0, 0, 0); 509 } 510 } 511 512 SMB_LOG_KTRACE(SMB_DBG_SMBFS_CLOSE | DBG_FUNC_NONE, 513 0xabc007, 514 np->f_openRCnt, 515 np->f_openWCnt, 516 np->f_openRWCnt, 517 0); 518 519exit: 520 if ((error == 0) && (openMode & FWRITE) && (np->f_openTotalWCnt > 0)) { 521 np->f_openTotalWCnt--; 522 } 523 524 if (fap != NULL) { 525 SMB_FREE(fap, M_SMBTEMP); 526 } 527 528 SMB_LOG_KTRACE(SMB_DBG_SMBFS_CLOSE | DBG_FUNC_END, error, 0, 0, 0, 0); 529 530 return (error); 531} 532 533/* 534 * smbfs_vnop_close - smbfs vnodeop entry point 535 * vnode_t a_vp; 536 * int a_fflags; 537 * vfs_context_t a_context; 538 */ 539static int 540smbfs_vnop_close(struct vnop_close_args *ap) 541{ 542 vnode_t vp = ap->a_vp; 543 int error = 0; 544 struct smbnode *np; 545 546 if (smbnode_lock(VTOSMB(vp), SMBFS_EXCLUSIVE_LOCK) != 0) 547 return (0); 548 549 SMB_LOG_KTRACE(SMB_DBG_CLOSE | DBG_FUNC_START, 0, 0, 0, 0, 0); 550 551 np = VTOSMB(vp); 552 np->n_lastvop = smbfs_vnop_close; 553 554 if (vnode_isdir(vp)) { 555 if (--np->d_refcnt) { 556 error = 0; 557 } else { 558 smbfs_closedirlookup(np, ap->a_context); 559 } 560 } else if ( vnode_isreg(vp) || vnode_islnk(vp) ) { 561 int clusterCloseError = np->f_clusterCloseError; 562 struct smb_share *share; 563 564 /* if its readonly volume, then no sense in trying to write out dirty data */ 565 if (!vnode_vfsisrdonly(vp) && smbfsIsCacheable(vp)) { 566 if (np->n_flag & NISMAPPED) { 567 /* More expensive, but handles mmapped files */ 568 ubc_msync (vp, 0, ubc_getsize(vp), NULL, UBC_PUSHDIRTY | UBC_SYNC); 569 } else { 570 /* Less expensive, but does not handle mmapped files */ 571 cluster_push(vp, IO_CLOSE); 572 } 573 } 574 share = smb_get_share_with_reference(VTOSMBFS(vp)); 575 576 /* Do any pending set eof or flushes before closing the file */ 577 smbfs_smb_fsync(share, np, ap->a_context); 578 579 error = smbfs_close(share, vp, ap->a_fflag, ap->a_context); 580 smb_share_rele(share, ap->a_context); 581 if (!error) 582 error = clusterCloseError; 583 } 584 smbnode_unlock(np); 585 586 SMB_LOG_KTRACE(SMB_DBG_CLOSE | DBG_FUNC_END, 0, 0, 0, 0, 0); 587 return (error); 588} 589 590static void 591smbfs_get_rights_shareMode(int fmode, uint32_t *rights, uint32_t *shareMode, uint16_t *accessMode) 592{ 593 /* 594 * We always ask for READ_CONTROL so we can always get the owner/group 595 * IDs to satisfy a stat. 596 */ 597 *rights = SMB2_READ_CONTROL; 598 if (fmode & FREAD) { 599 *accessMode |= kAccessRead; 600 *rights |= SMB2_FILE_READ_DATA; 601 } 602 if (fmode & FWRITE) { 603 *accessMode |= kAccessWrite; 604 *rights |= SMB2_FILE_APPEND_DATA | SMB2_FILE_WRITE_DATA; 605 } 606 607 /* 608 * O_EXLOCK -> denyRead/denyWrite is always cacheable since we have exclusive 609 * access. 610 * O_SHLOCK -> denyWrite is always cacheable since we are the only one who 611 * can change the file. 612 * denyNone -> is not cacheable if from Carbon (a FSCTL call from Carbon 613 * will set the vnode to be non cacheable). It is always 614 * cacheable from Unix since that is what home dirs mainly use. 615 */ 616 *shareMode = NTCREATEX_SHARE_ACCESS_ALL; 617 if (fmode & O_SHLOCK) { 618 *accessMode |= kDenyWrite; 619 /* Remove the wr shared access */ 620 *shareMode &= ~NTCREATEX_SHARE_ACCESS_WRITE; 621 } 622 623 if (fmode & O_EXLOCK) { 624 *accessMode |= kDenyWrite; 625 *accessMode |= kDenyRead; 626 /* Remove the rdwr shared access */ 627 *shareMode &= ~(NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_READ); 628 } 629} 630 631static void 632smbfs_update_RW_cnts(vnode_t vp, uint16_t accessMode) 633{ 634 /* count nbr of opens with rw, r, w so can downgrade access in close if needed */ 635 struct smbnode *np = VTOSMB(vp); 636 637 switch (accessMode) { 638 case (kAccessWrite | kAccessRead): 639 np->f_openRWCnt += 1; 640 break; 641 case kAccessRead: 642 np->f_openRCnt += 1; 643 break; 644 case kAccessWrite: 645 np->f_openWCnt += 1; 646 break; 647 } 648} 649 650static int 651smbfs_create_open(struct smb_share *share, vnode_t dvp, struct componentname *cnp, 652 struct vnode_attr *vap, uint32_t open_disp, int fmode, 653 SMBFID *fidp, struct smbfattr *fattrp, vnode_t *vpp, 654 vfs_context_t context) 655{ 656 struct smbnode *dnp = VTOSMB(dvp); 657 struct smbmount *smp = VTOSMBFS(dvp); 658 vnode_t vp; 659 const char *name = cnp->cn_nameptr; 660 size_t nmlen = cnp->cn_namelen; 661 int error = 0; 662 uint32_t rights, addedReadRights, saved_rights; 663 uint16_t accessMode = 0; 664 uint16_t savedAccessMode = 0; 665 struct smbnode *np; 666 uint32_t shareMode = 0; 667 char *target = NULL; 668 size_t targetlen = 0; 669 struct smb2_durable_handle dur_handle; 670 671 /* 672 * We have NO vnode for the target! 673 * The target may or may not exist on the server. 674 * The target could be a dir or a file. 675 * 676 * If its a dir, then it can not be a creation. Use vnop_mkdir instead. 677 * It could be an open on a dir which SMB protocol allows. Make sure 678 * to close the dir afterwards. 679 * 680 * If its a file, it cant be a symlink, use vnop_link instead. 681 * It could be a create and open on a file. 682 * Since a vnode was not found for the file, we know its not already open 683 * by this client. This means I know its the FIRST open call. 684 * 685 * dnp should be locked when this function is called 686 */ 687 688 *fidp = 0; 689 690 smbfs_get_rights_shareMode(fmode, &rights, &shareMode, &accessMode); 691 savedAccessMode = accessMode; /* Save the original access requested */ 692 /* 693 * If opening with write only, try opening it with read/write. Unix 694 * expects read/write access like open/map/close/PageIn. This also helps 695 * the cluster code since if write only, the reads will fail in the 696 * cluster code since it trys to page align the requests. 697 * 698 * NOTE: Since this call only creates items that are regular files we always 699 * set the vtype to VREG. The smbfs_smb_ntcreatex only uses that on create. 700 */ 701 addedReadRights = (accessMode == kAccessWrite) ? SMB2_FILE_READ_DATA : 0; 702 saved_rights = rights | addedReadRights; 703 704 error = smbfs_smb_ntcreatex(share, dnp, 705 rights | addedReadRights, shareMode, VREG, 706 fidp, name, nmlen, 707 open_disp, 0, fattrp, 708 TRUE, NULL, context); 709 710 if (error && addedReadRights) { 711 addedReadRights = 0; 712 saved_rights = rights; 713 714 error = smbfs_smb_ntcreatex(share, dnp, 715 rights, shareMode, VREG, 716 fidp, name, nmlen, 717 open_disp, 0, fattrp, 718 TRUE, NULL, context); 719 } 720 721 if (error) { 722 return error; 723 } 724 725 /* Reparse point need to get the reparse tag */ 726 if (fattrp->fa_attr & SMB_EFA_REPARSE_POINT) { 727 error = smbfs_smb_get_reparse_tag(share, *fidp, &fattrp->fa_reparse_tag, 728 &target, &targetlen, context); 729 if (error) { 730 (void) smbfs_smb_close(share, *fidp, context); 731 return error; 732 } 733 } 734 735 /* Create the vnode using fattr info and return the created vnode */ 736 error = smbfs_nget(share, vnode_mount(dvp), 737 dvp, name, nmlen, 738 fattrp, &vp, 739 cnp->cn_flags, SMBFS_NGET_CREATE_VNODE, 740 context); 741 if (error) { 742 if (target) { 743 SMB_FREE(target, M_TEMP); 744 } 745 (void) smbfs_smb_close(share, *fidp, context); 746 return error; 747 } 748 749 /* 750 * If they passed in a vnode then we no longer need it, so remove the 751 * reference. The smbfs_nget always returns us a vnode with a reference. The 752 * vnode could be the same or a new one. 753 */ 754 if (*vpp) { 755 vnode_put(*vpp); 756 } 757 *vpp = vp; 758 np = VTOSMB(vp); 759 760 /* 761 * We treat directories, files and symlinks different. Since currently we 762 * only handle reparse points as dfs triggers or symlinks we can ignore 763 * treating reparse points special. 764 */ 765 if (vnode_isdir(vp)) { 766 /* We opened a directory, increment its ref count and close it */ 767 np->d_refcnt++; 768 (void)smbfs_smb_close(share, *fidp, context); 769 } else if (vnode_islnk(vp)) { 770 /* We opened a symlink, close it */ 771 (void)smbfs_smb_close(share, *fidp, context); 772 if (target && targetlen) { 773 smbfs_update_symlink_cache(np, target, targetlen); 774 } 775 } else if (vnode_isreg(vp)) { 776 /* We opened the file so bump ref count */ 777 np->f_refcnt++; 778 779 np->f_rights = rights; 780 np->f_accessMode = accessMode; 781 if (addedReadRights) { 782 np->f_rights |= SMB2_FILE_READ_DATA; 783 np->f_accessMode |= kAccessRead; 784 } 785 786 /* if deny modes were used, save the file ref into file list */ 787 if ((fmode & O_EXLOCK) || (fmode & O_SHLOCK)) { 788 error = smb2_smb_dur_handle_init(share, np, &dur_handle); 789 if (error == 0) { 790 /* 791 * %%% TO DO - can we improve the performance of this? 792 * Want to get a durable handle, but the lease key consists 793 * of the file ID, so have to wait until the first create 794 * succeeds which gets us the file ID, then close it and reopen 795 * it but this time requesting the durable handle. 796 */ 797 (void) smbfs_smb_close(share, *fidp, context); 798 799 error = smbfs_smb_ntcreatex(share, dnp, 800 saved_rights, shareMode, VREG, 801 fidp, name, nmlen, 802 FILE_OPEN, 0, fattrp, 803 FALSE, &dur_handle, context); 804 } 805 else { 806 /* 807 * Durable handles must not be supported by this server, just 808 * use the earlier open which must have worked. 809 * Clear the durable handle not supported error 810 */ 811 error = 0; 812 } 813 814 if (error == 0) { 815 /* 816 * Either durable handles not supported or reopening the file 817 * with durable handle worked so save file ref 818 */ 819 AddFileRef (vp, vfs_context_proc(context), accessMode, rights, 820 *fidp, dur_handle, NULL); 821 } 822 } 823 else { 824 np->f_fid = *fidp; 825 smbfs_update_RW_cnts(vp, savedAccessMode); 826 if (accessMode == kAccessWrite) { 827 /* if opened with just write, then turn off cluster code */ 828 vnode_setnocache(vp); 829 } 830 } 831 } 832 833 /* If it was allocated then free, since we are done with it now */ 834 if (target) { 835 SMB_FREE(target, M_TEMP); 836 } 837 838 if (fattrp->fa_created_disp == FILE_CREATE) { 839 struct timespec ts; 840 /* 841 * We just created the file, so we have no finder info and the resource fork 842 * should be empty. So set our cache timers to reflect this information 843 */ 844 nanouptime(&ts); 845 VTOSMB(vp)->finfo_cache_timer = ts.tv_sec; 846 VTOSMB(vp)->rfrk_cache_timer = ts.tv_sec; 847 848 /* 849 * On create, an initial ACL can be set. 850 * If unix extensions are supported, then can set mode, owner, group. 851 */ 852 if (vap != NULL) { 853 smbfs_set_create_vap(share, vap, vp, context, TRUE); /* Set the REAL create attributes NOW */ 854 } 855 856 smbfs_attr_touchdir(dnp, (share->ss_fstype == SMB_FS_FAT)); 857 858 dnp->d_changecnt++; 859 860 /* Remove any negative cache entries. */ 861 if (dnp->n_flag & NNEGNCENTRIES) { 862 dnp->n_flag &= ~NNEGNCENTRIES; 863 cache_purge_negatives(dvp); 864 } 865 866 /* blow away statfs cache */ 867 smp->sm_statfstime = 0; 868 } 869 /* smbfs_nget returns a locked node, unlock it */ 870 smbnode_unlock(VTOSMB(vp)); /* Release the smbnode lock */ 871 872 return (error); 873} 874 875/* 876 * smbfs_open - The internal open routine, the vnode should be locked 877 * before this is called. 878 * 879 * The calling routine must hold a reference on the share 880 * 881 */ 882int 883smbfs_open(struct smb_share *share, vnode_t vp, int mode, 884 vfs_context_t context) 885{ 886 proc_t p = vfs_context_proc(context); 887 struct smbnode *np = VTOSMB(vp); 888 uint16_t accessMode = 0; 889 uint16_t savedAccessMode = 0; 890 uint32_t rights; 891 uint32_t shareMode; 892 SMBFID fid = 0; 893 int error = 0; 894 int warning = 0; 895 struct smbfattr *fap = NULL; 896 struct smb2_durable_handle dur_handle, *dptr; 897 int do_create; 898 uint32_t disp; 899 struct fileRefEntry *fndEntry = NULL; 900 901 SMB_LOG_KTRACE(SMB_DBG_SMBFS_OPEN | DBG_FUNC_START, 0, 0, 0, 0, 0); 902 903 /* It was already open so see if the file needs to be reopened */ 904 if ((np->f_refcnt) && 905 ((error = smbfs_smb_reopen_file(share, np, context)) != 0)) { 906 lck_rw_lock_shared(&np->n_name_rwlock); 907 SMBDEBUG(" %s waiting to be revoked\n", np->n_name); 908 lck_rw_unlock_shared(&np->n_name_rwlock); 909 910 goto exit; 911 } 912 913 SMB_MALLOC(fap, 914 struct smbfattr *, 915 sizeof(struct smbfattr), 916 M_SMBTEMP, 917 M_WAITOK | M_ZERO); 918 if (fap == NULL) { 919 SMBERROR("SMB_MALLOC failed\n"); 920 error = ENOMEM; 921 goto exit; 922 } 923 924 smbfs_get_rights_shareMode(mode, &rights, &shareMode, &accessMode); 925 savedAccessMode = accessMode; /* Save the original access requested */ 926 927 if ((mode & O_EXLOCK) || (mode & O_SHLOCK)) { 928 /* 929 * if using deny modes and I had to open the file myself, then close 930 * the file now so it does not interfere with the deny mode open. 931 * We only do this in read. 932 */ 933 if (np->f_needClose) { 934 np->f_needClose = 0; 935 warning = smbfs_close(share, vp, FREAD, context); 936 if (warning) { 937 lck_rw_lock_shared(&np->n_name_rwlock); 938 SMBWARNING("error %d closing %s\n", warning, np->n_name); 939 lck_rw_unlock_shared(&np->n_name_rwlock); 940 } 941 } 942 943 /* Using deny modes, see if already in file list */ 944 error = FindFileRef(vp, p, accessMode, kExactMatch, 0, 0, &fndEntry, &fid); 945 if (error == 0) { 946 /* 947 * Already in list due to previous open with deny modes. Can't have 948 * two exclusive or two write/denyWrite. Multiple read/denyWrites are 949 * allowed. 950 */ 951 if ((accessMode & kDenyWrite) && (accessMode & kAccessWrite)) { 952 error = EBUSY; 953 goto exit; 954 } 955 956 if (mode & O_EXLOCK) { 957 if ((accessMode & kAccessRead) && !(accessMode & kAccessWrite)) { 958 /* 959 * Multiple r/dR/dW are allowed, see FindFileRef for 960 * more details 961 */ 962 } 963 else { 964 error = EBUSY; 965 goto exit; 966 } 967 } 968 969 DBG_ASSERT(fndEntry); 970 /* 971 * We are going to reuse this Open Deny entry. Up the counter so 972 * we will know not to free it until the counter goes back to zero. 973 */ 974 fndEntry->refcnt++; 975 } 976 else { 977 /* 978 * Check one more time looking for other pids that might already 979 * have the file open for exclusive or shared access that will 980 * cause this open to get denied. This is to reduce the number of 981 * times a handle lease break will occur with SMB 2/3. If we lose 982 * the handle lease, then reopening a durable handle reconnect will 983 * fail. 984 */ 985 error = FindFileRef(vp, NULL, accessMode, kPreflightOpen, 0, 0, &fndEntry, &fid); 986 if (error == 0) { 987 /* Some other process has it open already */ 988 error = EBUSY; 989 goto exit; 990 } 991 992 /* not in list, so open new file */ 993 994 /* Request a durable handle */ 995 dptr = NULL; 996 error = smb2_smb_dur_handle_init(share, np, &dur_handle); 997 if (!error) { 998 dptr = &dur_handle; 999 } 1000 1001 if (np->n_flag & N_ISRSRCFRK) { 1002 disp = FILE_OPEN_IF; 1003 do_create = TRUE; 1004 } 1005 else { 1006 disp = FILE_OPEN; 1007 do_create = FALSE; 1008 } 1009 1010 error = smbfs_smb_ntcreatex(share, np, 1011 rights, shareMode, VREG, 1012 &fid, NULL, 0, 1013 disp, FALSE, fap, 1014 do_create, dptr, context); 1015 if (error == 0) { 1016 /* if open worked, save the file ref into file list */ 1017 AddFileRef (vp, p, accessMode, rights, fid, dur_handle, NULL); 1018 } 1019 } 1020 goto exit; 1021 } 1022 1023 /* 1024 * If we get here, then deny modes are NOT being used. If the open call is 1025 * coming in from Carbon, then Carbon will follow immediately with an FSCTL 1026 * to turn off caching (I am assuming that denyNone means this file will 1027 * be shared among multiple process and that ByteRangeLocking will be used). 1028 * 1029 * no deny modes, so use the shared file reference 1030 * 1031 */ 1032 /* We have open file descriptor for non deny mode opens */ 1033 if (np->f_fid != 0) { 1034 /* Already open check to make sure current access is sufficient */ 1035 int needUpgrade = 0; 1036 switch (np->f_accessMode) { 1037 case (kAccessRead | kAccessWrite): 1038 /* Currently RW, can't do any better than that so dont open a new fork */ 1039 break; 1040 case kAccessRead: 1041 /* Currently only have Read access, if they want Write too, then open as RW */ 1042 if (accessMode & kAccessWrite) { 1043 needUpgrade = 1; 1044 accessMode |= kAccessRead; /* keep orginal mode */ 1045 rights |= SMB2_FILE_READ_DATA; 1046 } 1047 break; 1048 case kAccessWrite: 1049 /* Currently only have Write access, if they want Read too, then open as RW */ 1050 if (accessMode & kAccessRead) { 1051 needUpgrade = 1; 1052 accessMode |= kAccessWrite; 1053 rights |= SMB2_FILE_APPEND_DATA | SMB2_FILE_WRITE_DATA; 1054 } 1055 break; 1056 } 1057 if (! needUpgrade) /* the existing open is good enough */ 1058 goto ShareOpen; 1059 } else if (accessMode == kAccessWrite) { 1060 /* 1061 * If opening with write only, try opening it with read/write. Unix 1062 * expects read/write access like open/map/close/PageIn. This also helps 1063 * the cluster code since if write only, the reads will fail in the 1064 * cluster code since it trys to page align the requests. 1065 */ 1066 1067 /* 1068 * Preflight for open deny to preserve handle lease. More details in 1069 * O_EXLOCK/O_SHLOCK code above. 1070 */ 1071 error = FindFileRef(vp, NULL, accessMode | kAccessRead, kPreflightOpen, 1072 0, 0, &fndEntry, &fid); 1073 if (error != 0) { 1074 /* Not already open locally, so try to open it */ 1075 error = smbfs_smb_open_file(share, np, 1076 rights | SMB2_FILE_READ_DATA, shareMode, &fid, 1077 NULL, 0, FALSE, 1078 fap, context); 1079 if (error == 0) { 1080 np->f_fid = fid; 1081 np->f_rights = rights | SMB2_FILE_READ_DATA; 1082 np->f_accessMode = accessMode | kAccessRead; 1083 goto ShareOpen; 1084 } 1085 } 1086 } 1087 1088 /* 1089 * Preflight for open deny to preserve handle lease. More details in 1090 * O_EXLOCK/O_SHLOCK code above. 1091 */ 1092 error = FindFileRef(vp, NULL, accessMode, kPreflightOpen, 0, 0, &fndEntry, 1093 &fid); 1094 if (error == 0) { 1095 /* Some other process has it open already */ 1096 error = EBUSY; 1097 goto exit; 1098 } 1099 1100 error = smbfs_smb_open_file(share, np, 1101 rights, shareMode, &fid, 1102 NULL, 0, FALSE, 1103 fap, context); 1104 if (error) 1105 goto exit; 1106 1107 /* 1108 * We already had it open (presumably because it was open with insufficient 1109 * rights.) So now close the old open, if we already had it open. 1110 */ 1111 if (np->f_refcnt && 1112 (np->f_fid != 0)) { 1113 warning = smbfs_smb_close(share, np->f_fid, context); 1114 if (warning) { 1115 lck_rw_lock_shared(&np->n_name_rwlock); 1116 SMBWARNING("error %d closing %s\n", warning, np->n_name); 1117 lck_rw_unlock_shared(&np->n_name_rwlock); 1118 } 1119 } 1120 np->f_fid = fid; 1121 np->f_rights = rights; 1122 np->f_accessMode = accessMode; 1123 1124ShareOpen: 1125 smbfs_update_RW_cnts(vp, savedAccessMode); 1126 if (accessMode == kAccessWrite) { 1127 /* if opened with just write, then turn off cluster code */ 1128 vnode_setnocache(vp); 1129 } 1130exit: 1131 if (!error) { 1132 /* We opened the file or pretended too; either way bump the count */ 1133 np->f_refcnt++; 1134 1135 /* keep track of how many opens for this file had write access */ 1136 if (mode & FWRITE) { 1137 np->f_openTotalWCnt++; 1138 } 1139 } 1140 1141 if (fap != NULL) { 1142 SMB_FREE(fap, M_SMBTEMP); 1143 } 1144 1145 SMB_LOG_KTRACE(SMB_DBG_SMBFS_OPEN | DBG_FUNC_END, error, 0, 0, 0, 0); 1146 return (error); 1147} 1148 1149static int 1150smbfs_vnop_open_common(vnode_t vp, int mode, vfs_context_t context, void *n_lastvop) 1151{ 1152 struct smbnode *np; 1153 int error; 1154 1155 /* We only open files and directories and symlinks */ 1156 if (!vnode_isreg(vp) && !vnode_isdir(vp) && !vnode_islnk(vp)) { 1157 return (EACCES); 1158 } 1159 1160 if ((error = smbnode_lock(VTOSMB(vp), SMBFS_EXCLUSIVE_LOCK))) 1161 return (error); 1162 1163 np = VTOSMB(vp); 1164 np->n_lastvop = n_lastvop; 1165 1166 /* Just mark that the directory was opened */ 1167 if (vnode_isdir(vp)) { 1168 np->d_refcnt++; 1169 error = 0; 1170 } else { 1171 struct smb_share * share; 1172 1173 share = smb_get_share_with_reference(VTOSMBFS(vp)); 1174 1175 if (mode & O_TRUNC) { 1176 /* If truncating the file on open, do any pending set eofs */ 1177 smbfs_smb_fsync(share, np, context); 1178 } 1179 1180 error = smbfs_open(share, vp, mode, context); 1181 /* 1182 * We created the file with different posix modes than request in 1183 * smbfs_vnop_create. We need to correct that here, so set the posix 1184 * modes to those request on create. See smbfs_set_create_vap for more 1185 * details on this issue. 1186 */ 1187 if ((error == 0) && (np->set_create_va_mode) && (mode & O_CREAT)) { 1188 struct vnode_attr vap; 1189 1190 np->set_create_va_mode = FALSE; /* Only try once */ 1191 VATTR_INIT(&vap); 1192 VATTR_SET_ACTIVE(&vap, va_mode); 1193 vap.va_mode = np->create_va_mode; 1194 error = smbfs_setattr(share, vp, &vap, context); 1195 if (error) /* Got an error close the file and return the error */ 1196 (void)smbfs_close(share, vp, mode, context); 1197 } 1198 smb_share_rele(share, context); 1199 } 1200 if (error == EBUSY) 1201 error = EAGAIN; 1202 1203 smbnode_unlock(np); 1204 return(error); 1205} 1206 1207/* 1208 * smbfs_vnop_compound_open - smbfs vnodeop entry point 1209 * vnode_t a_dvp; 1210 * vnode_t *a_vpp; 1211 * int a_fmode; 1212 * struct componentname *a_cnp; 1213 * vnode_attr *a_vap; 1214 * uint32_t a_flags; 1215 * uint32_t *a_status; 1216 * vfs_context_t context; 1217 * int (*a_open_create_authorizer); 1218 * int (*a_open_existing_authorizer); 1219 * void *a_reserved; 1220 * 1221 * In broad strokes, our compound Open VNOP will be able to act as a 1222 * VNOP_LOOKUP(), a VNOP_OPEN(), and possibly a VNOP_CREATE(), all in one trip 1223 * to the filesystem. Depending on flags, it may execute an operation similar 1224 * to an open(2) with O_CREAT: lookup, create if not present, and open. It may 1225 * also act as a simple open(2) without O_CREAT: lookup and open if present. 1226 * When it returns successfully, the file it has found or created will be "open" 1227 * and ready to be hooked into a file descriptor. As we will discuss later, this 1228 * call may under some circumstances return to VFS with its operation unfinished, 1229 * to request help from VFS, or fail but nonetheless return a vnode. Filesystems 1230 * will be responsible for calling the passed-in authorizer routines to make sure 1231 * that the caller can legitimately perform the requested action. 1232 * 1233 * Arguments in Detail 1234 * 1235 * 1. a_dvp - The directory in which to open/create. The directory vnode is 1236 * equivalent to what would be passed to VNOP_LOOKUP() or VNOP_CREATE(): 1237 * it is the directory in which we wish to open a file, possibly doing 1238 * a create if the file is not already present. 1239 * 2. a_vpp - Resulting vnode. This argument is a pointer to a "vnode_t" 1240 * in which the filesystem can place a pointer to the vnode for a file 1241 * it either looks up or creates. In the event of a hit in the name 1242 * cache, VFS will pass a file to the filesystem in *a_vpp. In that 1243 * case, the filesystem will be free to call vnode_put() on that vnode 1244 * and replace it with another of its choosing. In the event of a cache 1245 * miss, *a_vpp will store NULLVP. On success, the pointer installed at 1246 * this address shall point to an "opened" vnode. On failure, it may 1247 * point to a vnode which is not open. Because several facilities in 1248 * the kernel--notably auditing and kdebug support for fs_usage--rely 1249 * on examining vnodes between lookup and a subsequent VNOP, filesystems 1250 * should make every effort to return a vnode with an iocount if a lookup 1251 * would have succeeded for that file, regardless of whether the main 1252 * operation has failed. This subtlety will apply to all other compound 1253 * VNOPs as well, including those which might fail with EEXIST (e.g. mkdir). 1254 * An unopened vnode may also be returned because more help is required 1255 * from VFS (EKEEPLOOKING). 1256 * 3. a_fmode - Open mode. This field will contain open flags as normally 1257 * passed to VNOP_OPEN(), e.g. O_TRUNC. For filesystems implementing 1258 * compound open, O_TRUNC must be handled as part of the compound open 1259 * call--a subsequent VNOP_SETATTR() call will not be sent to set the size. 1260 * 4. a_cnp - Path to look up. This field will contain a componentname, as 1261 * passed to VNOP_LOOKUP() or VNOP_CREATE(), specifying the name of the 1262 * file to look up and possibly create. 1263 * 5. a_vap - Attributes with which to create, if appropriate. This field 1264 * will contain a pointer to vnode attributes to be used in creating a 1265 * file. In the event of an open without O_CREAT, this field will be NULL. 1266 * In the event of a cache hit, it will also be NULL, as we wish to take 1267 * a fast path in this case which does not involve the heavyweight operation 1268 * of initializing creation attributes. This field can be ignored in 1269 * the event that an existing file is detected. 1270 * 6. a_flags - VNOP-control flags. This field will contain control flags 1271 * specific to the compound open VNOP. For now, there will be only one 1272 * flag: VNOP_COMPOUND_OPEN_DO_CREATE will indicate that if no existing 1273 * file is found, a new one is to be created (authorization, etc. permitting). 1274 * 7. a_status - Information about results. The filesystem will use this 1275 * field to return information about the result of the VNOP. At the moment, 1276 * there will be only one flag: COMPOUND_OPEN_STATUS_DID_CREATE will 1277 * indicate that a file was created by this call. The field will be set 1278 * to zero before a pointer is passed to the filesystem, so the FS will 1279 * be free (for now) to only touch it in the event of having done a 1280 * create. COMPOUND_OPEN_STATUS_DID_CREATE should never be set if 1281 * VNOP_COMPOUND_OPEN_DO_CREATE was not set in a_flags. 1282 * 8. a_context - Authorization context. This field is a vfs_context_t, 1283 * just as is passed to most VNOPs. 1284 * 9. a_open_create_authorizer - Authorizer for create case. This field 1285 * will contain a pointer to a function to be called to authorize creating 1286 * a file. It need only be called if a file is to be created; for an 1287 * existing file, a_open_existing_authorizer should be used. The 1288 * componentname and vnode_attr passed to this function should be exactly 1289 * those which were passed to the VNOP, because opaque data in these 1290 * structures, installed by VFS, will be interpreted in authorization 1291 * (the same will apply to all other authorizer callbacks). Some additional 1292 * validation which is not authorization per se, but which is currently 1293 * performed in VFS on behalf of the filesystem, will also be executed 1294 * here. As a result of that validation, a variety of errors may be 1295 * returned; these should generally be passed back to VFS. Filesystems 1296 * which will attempt a compound RPC that may result in a file's being 1297 * created should always call this function beforehand. In that case, 1298 * if authorization is denied, the filesystem should attempt an "open 1299 * without O_CREAT," because an open of an existing file may succeed 1300 * despite a denial of permission to create. The reserved argument should 1301 * currently always be NULL. 1302 * NOTE: The locking constraints with respect to this call, and all 1303 * authorizer callbacks in this document must unfortunately be left 1304 * somewhat ambiguous due to the unrestricted behavior of Kauth and 1305 * MACF plugins. However, I believe that it should be safe to call out 1306 * with resources (iocounts, memory, references) held, and even with some 1307 * kinds of locks (a lock preventing only remove of a file, for instance). 1308 * The chief thing to avoid is holding big locks (directory lock, file lock) 1309 * which would prevent stat(2) and similar operations which authorizers 1310 * are likely to try to use. 1311 * 10. a_open_existing_authorizer - Authorizer for preexisting case. This 1312 * field will contain a pointer to a function to be called to authorize 1313 * opening an existing file. It need only be called if a file has not 1314 * been created. The componentname passed to this function should be 1315 * exactly that which was passed to the VNOP, because opaque data in 1316 * this structure, installed by VFS, will be interpreted in authorization. 1317 * Some additional validation which is not authorization per se, but which 1318 * is currently performed in VFS on behalf of the filesystem, will also 1319 * be executed here. As a result of that validation, a variety of errors 1320 * may be returned; these should generally be passed back to VFS. 1321 * The reserved argument should currently always be NULL. For networked 1322 * filesystems, this routine can be used after going over the wire with a 1323 * compound lookup+open RPC; if access is denied, the filesystem should 1324 * clean up (e.g. issue a close over the wire) and return to VFS. 1325 * 11. a_reserved - This field is currently unused and should not be interpreted. 1326 * 1327 * Symlinks, Mountpoints, Trigger Points: 1328 * 1329 * int vnode_lookup_continue_needed(vnode_t vp, struct componentname *cnp); 1330 * 1331 * #define EKEEPLOOKING (-7) 1332 * 1333 * As part of a compound operation, a file may be detected which the filesystem 1334 * is not equipped to handle--for instance, a mountpoint, a symlink if O_NOFOLLOW 1335 * is set (which may point to another volume), or a trigger point. VFS will 1336 * provide the above routine to determine if a given vnode is one which requires 1337 * additional VFS processing. It will take a vnode (the preexisting file 1338 * discovered by a compound VNOP) and a componentname; the latter should be the 1339 * exact pointer which was passed to the filesystem by VFS, because opaque data 1340 * will be interpreted to make the decision. If this routine returns a nonzero 1341 * value, the filesystem should return EKEEPLOOKING to VFS. 1342 * vnode_lookup_continue_needed() will also update an opaque field on the 1343 * componentname for interpretation by VFS--while unnecessary for VNOP_COMPOUND_OPEN(), 1344 * for a rename (where two lookups take place) that update will let VFS determine 1345 * which lookup needs to be continued. This helper will be used in numerous 1346 * compound VNOPs. 1347 * 1348 * "Traditional"VNOPs, Dark Corners of the Kernel, and the Root of a Filesystem 1349 * 1350 * VNOP_LOOKUP() will still need to be supported to allow us to reach intermediate 1351 * components of a path. Currently, we plan to require that filesystems continue 1352 * to support the "traditional" VNOP_CREATE() and VNOP_OPEN() (and correspondingly, 1353 * the traditional version of other namespace-changing operations). The chief 1354 * reason for this is that there are numerous areas in the kernel that use these 1355 * old-style operations directly. After some discussion with various filesystem 1356 * owners, I think that it is best that we gradually adjust those areas to be 1357 * able to use compound VNOPs, thereby limiting the instability from moving them 1358 * all at once. When all internal code has been prepared to use a given compound 1359 * VNOP, filesystems will be able to remove their "traditional" implementation. 1360 * VNOP_OPEN() deserves a bit of special discussion. There are some places in 1361 * the kernel where we "open" a vnode without doing a true lookup; the best example 1362 * is the root of a filesystem, which is never "looked up" the way other entries 1363 * in a volume are, but there are other places where we have in hand that a vnode 1364 * that was obtained at some point in the past. I therefore think that we will 1365 * probably keep VNOP_OPEN() around for the long term, rather than increasing the 1366 * complexity of the spreadsheet of "which arguments can be NULL, and when" for 1367 * VNOP_COMPOUND_OPEN(). 1368*/ 1369static int 1370smbfs_vnop_compound_open(struct vnop_compound_open_args *ap) 1371{ 1372 vnode_t dvp = ap->a_dvp; 1373 vnode_t *vpp = ap->a_vpp; 1374 vnode_t vp = (ap->a_vpp) ? *ap->a_vpp : NULL; 1375 vfs_context_t context = ap->a_context; 1376 struct componentname *cnp = ap->a_cnp; 1377 struct vnode_attr *vap = ap->a_vap; 1378 int fmode = ap->a_fmode; 1379 int error; 1380 int create_authorizer_error = 0; 1381 uint32_t open_disp = 0; 1382 struct smb_share *share = NULL; 1383 struct smbnode *dnp; 1384 SMBFID fid = 0; 1385 uint32_t vid; 1386 struct smbfattr *fap = NULL; 1387 const char *namep = cnp->cn_nameptr; 1388 size_t name_len = cnp->cn_namelen; 1389 1390 1391 if (vpp == NULL) { 1392 SMBWARNING("Calling us without a vpp\n"); 1393 return ENOTSUP; 1394 } 1395 1396 /* 1397 * Case 1: 1398 * They passed in a vnode they found in the name cache or we found 1399 * one in our hash table and its a symlink or reprase point. Not sure what 1400 * to do with reprase points yet. Symlinks are easy call vnode_lookup_continue_needed 1401 * and let it tell us what to do. 1402 * 1403 * Case 2: 1404 * They passed in a vnode they found in the name cache or we found in our 1405 * hash table. If they don't have O_CREAT set or its already open then we 1406 * can just do a normaly open. We need to call a_open_existing_authorizer 1407 * before calling smbfs_vnop_open_common. If O_TRUNC is set then we need to 1408 * set the file size to zero. Even on error we need to return the vnode 1409 * with a reference. 1410 * 1411 * Case 3: 1412 * We have no vnode or they have O_CREAT set and we don't have it already 1413 * open. Set the correct open dispostion depending on the modes passed in 1414 * and what a_open_create_authorizer returns. We only call a_open_create_authorizer 1415 * if O_CREAT is set. Now we let smbfs_create_open handle all other cases. 1416 * Will use <rdar://problem/8574808> to update this comment and to make 1417 * reprase points and symlinks work correctly. 1418 * 1419 * 1420 * Notes: 1421 * 1) vap may be null, if null on create then thats not supported 1422 * 2) if a_vpp is null and we return a vnode, dont do a vnode_put on it as the 1423 * vfs open code will call vnode_put on it for us. 1424 */ 1425 1426 /* 1427 * We may have to create the item make sure it has a vap and they 1428 * are creating a file. We only support create on files. 1429 */ 1430 if ((fmode & O_CREAT) && ((vap == NULL) || (vap->va_type != VREG))) { 1431 return (ENOTSUP); 1432 } 1433 1434 SMB_LOG_KTRACE(SMB_DBG_CMPD_OPEN | DBG_FUNC_START, fmode, 0, 0, 0, 0); 1435 1436 SMB_MALLOC(fap, 1437 struct smbfattr *, 1438 sizeof(struct smbfattr), 1439 M_SMBTEMP, 1440 M_WAITOK | M_ZERO); 1441 if (fap == NULL) { 1442 SMBERROR("SMB_MALLOC failed\n"); 1443 error = ENOMEM; 1444 goto done; 1445 } 1446 1447 share = smb_get_share_with_reference(VTOSMBFS(dvp)); 1448 1449 /* They didn't pass us a vnode, see if we have one in our hash */ 1450 if (vp == NULLVP) { 1451 SMB_LOG_KTRACE(SMB_DBG_CMPD_OPEN | DBG_FUNC_NONE, 0xabc001, 0, 0, 0, 0); 1452 1453 if ((cnp->cn_nameptr[0] == '.') && (cnp->cn_namelen == 1)) { 1454 /* 1455 * They didn't give us a vnode, but they want dot open, so 1456 * get a reference on the parent node. 1457 */ 1458 vid = vnode_vid(dvp); 1459 error = vnode_getwithvid(dvp, vid); 1460 if (error) { 1461 goto done; 1462 } 1463 vp = dvp; 1464 } 1465 else { 1466 if (SSTOVC(share)->vc_misc_flags & SMBV_HAS_FILEIDS) { 1467 /* 1468 * Server supports File IDs. 1469 */ 1470 if (fmode & O_CREAT) { 1471 /* 1472 * In this case a lookup was done earlier and we know the 1473 * item does not exist so trying to get its File ID is 1474 * useless. Just skip straight to not found */ 1475 goto not_found; 1476 } 1477 1478 /* 1479 * Before we can see if vnode already exists in our hash, 1480 * need to get the inode number first. Might as well get all 1481 * the meta data too so we can update the vnode if its found 1482 */ 1483 if (SSTOVC(share)->vc_misc_flags & SMBV_NO_QUERYINFO) { 1484 /* 1485 * Server does not like Query Info on files, so use Query 1486 * Dir instead. 1487 * 1488 * Should never be a named stream vnode 1489 */ 1490 if ((VTOSMB(dvp)->n_vnode) && vnode_isnamedstream(VTOSMB(dvp)->n_vnode)) { 1491 DBG_ASSERT(0); 1492 } 1493 1494 error = smb2fs_smb_cmpd_query_dir_one(share, VTOSMB(dvp), 1495 namep, name_len, 1496 fap, (char **) &namep, &name_len, 1497 context); 1498 } 1499 else { 1500 error = smbfs_smb_qpathinfo(share, VTOSMB(dvp), VREG, 1501 fap, SMB_QFILEINFO_ALL_INFO, 1502 &namep, &name_len, 1503 context); 1504 } 1505 SMB_LOG_KTRACE(SMB_DBG_CMPD_OPEN | DBG_FUNC_NONE, 1506 0xabc002, error, 0, 0, 0); 1507 1508 if (error == 0) { 1509 /* Lock the parent */ 1510 dnp = VTOSMB(dvp); 1511 if (smbnode_lock(dnp, SMBFS_EXCLUSIVE_LOCK) != 0) { 1512 error = ENOENT; 1513 goto done; 1514 } 1515 1516 /* 1517 * Found item on server, see if its in the hash. 1518 * If it is in hash, then update its meta data and return vp 1519 * If its not in hash, smbfs_nget will create it for us and 1520 * return it in vp. Either way, we get back a vp. 1521 */ 1522 if (smbfs_nget(share, vnode_mount(dvp), 1523 dvp, cnp->cn_nameptr, cnp->cn_namelen, 1524 fap, &vp, 1525 cnp->cn_flags, SMBFS_NGET_CREATE_VNODE, 1526 ap->a_context) == 0) { 1527 /* 1528 * Found one in our hash table unlock it, we just need 1529 * the vnode reference at this point 1530 */ 1531 smbnode_unlock(VTOSMB(vp)); 1532 } 1533 1534 /* Unlock the parent */ 1535 dnp->n_lastvop = smbfs_vnop_compound_open; 1536 smbnode_unlock(dnp); 1537 1538 /* If smbfs_smb_qpathinfo returned a new name, free it */ 1539 if (namep != cnp->cn_nameptr) { 1540 SMB_FREE(namep, M_SMBNODENAME); 1541 } 1542 } 1543 else { 1544 /* Probably not found, either way vp is left at NULL */ 1545 goto not_found; 1546 } 1547 } 1548 else { 1549 /* Lock the parent */ 1550 dnp = VTOSMB(dvp); 1551 if (smbnode_lock(dnp, SMBFS_EXCLUSIVE_LOCK) != 0) { 1552 error = ENOENT; 1553 goto done; 1554 } 1555 1556 /* 1557 * Server does not support File IDs. 1558 * Use the name for the hash value and try to find the vnode 1559 * in the hash table with just the parent vnode and name. If its 1560 * does not already exist in the hash,then smbfs_nget will 1561 * return ENOENT (since fap == NULL) and vp will be left as NULL 1562 * 1563 * If server does support File IDs, we dont have the inode number 1564 * at this time, so can not check the hash table at this time. 1565 */ 1566 if (smbfs_nget(share, vnode_mount(dvp), 1567 dvp, cnp->cn_nameptr, cnp->cn_namelen, 1568 NULL, &vp, 1569 cnp->cn_flags, SMBFS_NGET_LOOKUP_ONLY, 1570 ap->a_context) == 0) { 1571 /* 1572 * Found one in our hash table unlock it, we just need 1573 * the vnode reference at this point 1574 */ 1575 smbnode_unlock(VTOSMB(vp)); 1576 } 1577 1578 /* Unlock the parent */ 1579 dnp->n_lastvop = smbfs_vnop_compound_open; 1580 smbnode_unlock(dnp); 1581 } 1582 } 1583 } 1584 1585 /* 1586 * Symlink or reparse point. Call vnode_lookup_continue_needed before 1587 * proceeding. 1588 */ 1589 if (vp && (vnode_islnk(vp) || (VTOSMB(vp)->n_dosattr & SMB_EFA_REPARSE_POINT))) { 1590 lck_rw_lock_shared(&VTOSMB(vp)->n_name_rwlock); 1591 SMBDEBUG("symlink %s\n", VTOSMB(vp)->n_name); 1592 lck_rw_unlock_shared(&VTOSMB(vp)->n_name_rwlock); 1593 1594 error = vnode_lookup_continue_needed(vp, cnp); 1595 if (error) { 1596 *vpp = vp; 1597 vp = NULL; 1598 goto done; 1599 } 1600 /* Let smbfs_vnop_open_common handle any open errors */ 1601 fmode &= ~(O_CREAT | O_TRUNC); /* Can't create or truncate a symlink */ 1602 } 1603 1604 /* 1605 * Do a normal open: 1606 * 1. We have a vnode and they just want to open the file or directory. The 1607 * O_CREAT/O_TRUNC is not set. NOTE they can't have O_CREAT set on a directory. 1608 * 2. We have a vnode to a file and its already opened. 1609 * 1610 * NOTE: They could be opening a file with O_CREAT, we found a directory in 1611 * our hash, yet it doesn't exist on the server. So we should create the file 1612 * and remove the directory node from our hash table. In this case we should 1613 * falldown to the create open code. 1614 */ 1615 if (vp && (!(fmode & (O_CREAT | O_TRUNC)) || (vnode_isreg(vp) && VTOSMB(vp)->f_refcnt))) { 1616 1617 if ((fmode & O_EXCL) && vnode_isreg(vp) && VTOSMB(vp)->f_refcnt) { 1618 /* 1619 * O_EXCL is set and we *know* the file exists (we have 1620 * a vp and it's opened). No need to go to the server, 1621 * since we know the result. 1622 */ 1623 if (fmode & O_CREAT) { 1624 /* If O_CREAT and O_EXCL and file exists then EEXISTS */ 1625 error = EEXIST; 1626 } 1627 else { 1628 error = EAGAIN; 1629 } 1630 *vpp = vp; 1631 vp = NULL; 1632 goto done; 1633 } 1634 1635 /* Call back and see if it is ok to be opened */ 1636 error = ap->a_open_existing_authorizer(vp, cnp, fmode, context, NULL); 1637 if (!error) { 1638 error = smbfs_vnop_open_common(vp, fmode, context, smbfs_vnop_compound_open); 1639 SMB_LOG_KTRACE(SMB_DBG_CMPD_OPEN | DBG_FUNC_NONE, 1640 0xabc003, error, 0, 0, 0); 1641 } 1642 1643 /* The file was already open, but they wanted us to truncate it. */ 1644 if (!error && (fmode & O_TRUNC)){ 1645 struct vnode_attr va; 1646 1647 memset(&va, 0, sizeof(va)); 1648 VATTR_INIT(&va); 1649 VATTR_SET_ACTIVE(&va, va_data_size); 1650 error = smbfs_setattr(share, vp, &va, context); 1651 if (error) { 1652 /* Got an error close the file and return the error */ 1653 (void)smbfs_close(share, vp, fmode, context); 1654 } 1655 } 1656 /* Even if the truncate fails we need to return the vnode */ 1657 *vpp = vp; 1658 vp = NULL; 1659 goto done; 1660 } 1661 1662not_found: 1663 /* Set the default create dispostion value */ 1664 create_authorizer_error = 0; 1665 1666 if (fmode & O_TRUNC) { 1667 open_disp = FILE_OVERWRITE; 1668 if (vp) { 1669 /* If truncating the file on open, do any pending set eofs */ 1670 smbfs_smb_fsync(share, VTOSMB(vp), context); 1671 } 1672 } 1673 else { 1674 open_disp = FILE_OPEN; 1675 } 1676 1677 if (fmode & O_CREAT) { 1678 /* Call back and see if it is ok to be created */ 1679 create_authorizer_error = ap->a_open_create_authorizer(dvp, cnp, vap, context, NULL); 1680 if (!create_authorizer_error) { 1681 /* We can create so set the correct create dispostion value */ 1682 if (fmode & O_EXCL) { 1683 open_disp = FILE_CREATE; 1684 } else if (fmode & O_TRUNC) { 1685 open_disp = FILE_OVERWRITE_IF; 1686 } else { 1687 open_disp = FILE_OPEN_IF; 1688 } 1689 } 1690 } 1691 1692 /* Lock the parent */ 1693 if ((error = smbnode_lock(VTOSMB(dvp), SMBFS_EXCLUSIVE_LOCK))) { 1694 goto done; 1695 } 1696 1697 dnp = VTOSMB(dvp); 1698 dnp->n_lastvop = smbfs_vnop_compound_open; 1699 1700 /* Try to create/open the file */ 1701 error = smbfs_create_open(share, dvp, cnp, vap, open_disp, fmode, &fid, fap, &vp, context); 1702 smbnode_unlock(dnp); 1703 1704 SMB_LOG_KTRACE(SMB_DBG_CMPD_OPEN | DBG_FUNC_NONE, 0xabc004, error, 0, 0, 0); 1705 if (error) { 1706 if (create_authorizer_error) { 1707 error = create_authorizer_error; 1708 } 1709 } 1710 else { 1711 if ((fap->fa_created_disp == FILE_CREATE) && (!(fmode & O_CREAT))) { 1712 /* 1713 * The server says it was created, but we didn't request it to be 1714 * created. The VFS layer can't handle this so just replace the 1715 * FILE_CREATE with FILE_OPEN and log what happen. This should never 1716 * happen, but it is better than the VFS panicing. 1717 */ 1718 fap->fa_created_disp = FILE_OPEN; 1719 SMBERROR("Server created %s when we only wanted it open, server error\n", 1720 cnp->cn_nameptr); 1721 } 1722 if (fap->fa_created_disp == FILE_CREATE) { 1723 *ap->a_status = COMPOUND_OPEN_STATUS_DID_CREATE; 1724 } else { 1725 error = ap->a_open_existing_authorizer(vp, cnp, fmode, context, NULL); 1726 /* Error so close it */ 1727 if (error) { 1728 (void)smbfs_smb_close(share, fid, context); 1729 } 1730 /* Not sure how to handle reparse yet, deal with that in <rdar://problem/8574808> */ 1731 if (vnode_islnk(vp) || (VTOSMB(vp)->n_dosattr & SMB_EFA_REPARSE_POINT)) { 1732 error = vnode_lookup_continue_needed(vp, cnp); 1733 if (!error && (vnode_islnk(vp))) { 1734 /* We never let them open a symlink */ 1735 error = EACCES; 1736 } 1737 } 1738 } 1739 /* Note: Even on error, return the vnode */ 1740 *vpp = vp; 1741 vp = NULL; /* Don't release the reference */ 1742 } 1743 1744done: 1745 if (error) { 1746 if ((fmode & O_CREAT) && (error == ENOENT)) { 1747 SMBDEBUG("Creating %s returned ENOENT, resetting to EACCES\n", cnp->cn_nameptr); 1748 /* 1749 * Some servers (Samba) support an option called veto. This prevents 1750 * clients from creating or access these files. The server returns 1751 * an ENOENT error in these cases. The VFS layer will loop forever 1752 * if a ENOENT error is returned on create, so we convert this error 1753 * to EACCES. 1754 */ 1755 error = EACCES; 1756 } else if ((fmode & O_EXCL) && (error != EEXIST)) { 1757 /* 1758 * Since O_EXCL is set, we really need to return EEXIST 1759 * if the file exists. 1760 * See <rdar://problem/10074916> 1761 */ 1762 if ( (smbfs_smb_query_info(share, VTOSMB(dvp), VREG, 1763 cnp->cn_nameptr, cnp->cn_namelen, 1764 NULL, context) == 0)) { 1765 SMBDEBUG("%s: O_EXCL but error = %d, resetting to EEXIST.\n", __FUNCTION__, error); 1766 if (fmode & O_CREAT) { 1767 /* If O_CREAT and O_EXCL and file exists then EEXISTS */ 1768 error = EEXIST; 1769 } 1770 else { 1771 error = EAGAIN; 1772 } 1773 } 1774 } 1775 } 1776 1777 if (share) { 1778 smb_share_rele(share, context); 1779 } 1780 1781 /* 1782 * We have an error and they didn't pass us in a vnode, then we found the 1783 * vnode in our hash table. We need to remove our reference. 1784 */ 1785 if (error && (*vpp == NULLVP) && vp) { 1786 vnode_put(vp); 1787 } 1788 1789 if (fap) { 1790 SMB_FREE(fap, M_SMBTEMP); 1791 } 1792 1793 SMB_LOG_KTRACE(SMB_DBG_CMPD_OPEN | DBG_FUNC_END, error, 0, 0, 0, 0); 1794 return (error); 1795} 1796 1797/* 1798 * smbfs_vnop_open - smbfs vnodeop entry point 1799 * vnode_t a_vp; 1800 * int a_mode; 1801 * vfs_context_t a_context; 1802 */ 1803static int 1804smbfs_vnop_open(struct vnop_open_args *ap) 1805{ 1806 int error; 1807 1808 SMB_LOG_KTRACE(SMB_DBG_OPEN | DBG_FUNC_START, 0, 0, 0, 0, 0); 1809 1810 error = smbfs_vnop_open_common(ap->a_vp, ap->a_mode, ap->a_context, smbfs_vnop_open); 1811 1812 SMB_LOG_KTRACE(SMB_DBG_OPEN | DBG_FUNC_END, error, 0, 0, 0, 0); 1813 return (error); 1814} 1815 1816/* 1817 * smbfs_vnop_mmap - smbfs vnodeop entry point 1818 * vnode_t a_vp; 1819 * int a_fflags; 1820 * vfs_context_t a_context; 1821 * 1822 * The mmap routine is a hint that we need to keep the file open. We can get 1823 * mutilple mmap before we get a mnomap. We only care about the first one. We 1824 * need to take a reference count on the open file and hold it open until we get 1825 * a mnomap call. The file should already be open when we get the mmap call and 1826 * with the correct open mode access. So we shouldn't have to worry about 1827 * upgrading because the open should have handled that for us. If the open was 1828 * done using an Open Deny mode then we need to mark the open deny entry as being 1829 * mmaped so the pagein, pageout, and mnomap routines can find. 1830 * 1831 * NOTE: On return all errors are ignored except EPERM. 1832 */ 1833static int 1834smbfs_vnop_mmap(struct vnop_mmap_args *ap) 1835{ 1836 vnode_t vp = ap->a_vp; 1837 struct smbnode *np = NULL; 1838 int error = 0; 1839 uint32_t mode = (ap->a_fflags & PROT_WRITE) ? (FWRITE | FREAD) : FREAD; 1840 int accessMode = (ap->a_fflags & PROT_WRITE) ? kAccessWrite : kAccessRead; 1841 SMBFID fid = 0; 1842 struct fileRefEntry *entry = NULL; 1843 1844 if ((error = smbnode_lock(VTOSMB(vp), SMBFS_EXCLUSIVE_LOCK))) 1845 return (EPERM); 1846 1847 SMB_LOG_KTRACE(SMB_DBG_MMAP | DBG_FUNC_START, 0, 0, 0, 0, 0); 1848 1849 np = VTOSMB(vp); 1850 np->n_lastvop = smbfs_vnop_mmap; 1851 1852 /* We already have it mapped, just ignore this one */ 1853 if (np->n_flag & NISMAPPED) 1854 goto out; 1855 /* 1856 * Since we should already be open with the correct modes then we should never 1857 * need to really open the file. For now we try these three cases. 1858 * 1859 * First try the simple case, we have a posix open with the correct access. 1860 * 1861 * Second see if we have a match in the open deny mode list. Still not 100% sure this 1862 * will work ever time because they are passing the current context, which may not match 1863 * the one passed to open. From taking to Joe he believe we will always be in the open 1864 * context when call. From my testing this seems to be true. 1865 * 1866 * Third just return EPERM. 1867 */ 1868 if ((np->f_fid != 0) && 1869 (np->f_accessMode & accessMode)) { 1870 np->f_refcnt++; 1871 } else if (FindFileRef(vp, vfs_context_proc(ap->a_context), accessMode, 1872 kAnyMatch, 0, 0, &entry, &fid) == 0) { 1873 entry->refcnt++; 1874 entry->mmapped = TRUE; 1875 np->f_refcnt++; 1876 } else { 1877 lck_rw_lock_shared(&np->n_name_rwlock); 1878 SMBERROR("%s We could not find an open file with mode = 0x%x? \n", np->n_name, mode); 1879 lck_rw_unlock_shared(&np->n_name_rwlock); 1880 1881 error = EPERM; 1882 goto out; 1883 } 1884 np->n_flag |= NISMAPPED; 1885 np->f_mmapMode = mode; 1886out: 1887 smbnode_unlock(np); 1888 1889 SMB_LOG_KTRACE(SMB_DBG_MMAP | DBG_FUNC_END, error, 0, 0, 0, 0); 1890 return (error); 1891} 1892 1893/* 1894 * smbfs_vnop_mnomap - smbfs vnodeop entry point 1895 * vnode_t a_vp; 1896 * vfs_context_t a_context; 1897 * 1898 * When called this is a hint that we can now close the file. We will not get any 1899 * more pagein or pageout calls without another mmap call. If our reference count 1900 * is down to one then all we have to do is call close and it will clean everything 1901 * up. Otherwise we have a little more work to do see below for more details. 1902 * 1903 * NOTE: All errors are ignored by the calling routine 1904 */ 1905static int 1906smbfs_vnop_mnomap(struct vnop_mnomap_args *ap) 1907{ 1908 vnode_t vp = ap->a_vp; 1909 struct smbnode *np; 1910 struct fileRefEntry *entry; 1911 int error = 0; 1912 1913 if (smbnode_lock(VTOSMB(vp), SMBFS_EXCLUSIVE_LOCK)) 1914 return (EPERM); /* Not sure what to do here, they ignore errors */ 1915 1916 SMB_LOG_KTRACE(SMB_DBG_MNOMAP | DBG_FUNC_START, 0, 0, 0, 0, 0); 1917 1918 np = VTOSMB(vp); 1919 np->n_lastvop = smbfs_vnop_mnomap; 1920 1921 /* Only one open reference just call close and let it clean every thing up. */ 1922 if (np->f_refcnt == 1) { 1923 struct smb_share *share; 1924 1925 share = smb_get_share_with_reference(VTOSMBFS(vp)); 1926 error = smbfs_close(share, vp, np->f_mmapMode, ap->a_context); 1927 smb_share_rele(share, ap->a_context); 1928 if (error) { 1929 lck_rw_lock_shared(&np->n_name_rwlock); 1930 SMBWARNING("%s close failed with error = %d\n", np->n_name, error); 1931 lck_rw_unlock_shared(&np->n_name_rwlock); 1932 } 1933 goto out; 1934 } else { 1935 if (np->f_refcnt > 0) { 1936 np->f_refcnt--; 1937 } 1938 } 1939 /* 1940 * We get passed the current context which may or may not be the the same as the one used 1941 * in the open. So search the list and see if there are any mapped entries. Remember we only 1942 * have one item mapped at a time. 1943 */ 1944 if (FindMappedFileRef(vp, &entry, NULL) == TRUE) { 1945 entry->mmapped = FALSE; 1946 if (entry->refcnt > 0) /* This entry is still in use don't remove it yet. */ 1947 entry->refcnt--; 1948 else /* Done with it remove it from the list */ 1949 RemoveFileRef(vp, entry); 1950 } 1951out: 1952 np->f_mmapMode = 0; 1953 np->n_flag &= ~NISMAPPED; 1954 smbnode_unlock(np); 1955 1956 SMB_LOG_KTRACE(SMB_DBG_MNOMAP | DBG_FUNC_END, error, 0, 0, 0, 0); 1957 return (error); 1958} 1959 1960/* 1961 * smbfs_vnop_inactive - smbfs vnodeop entry point 1962 * vnode_t a_vp; 1963 * vfs_context_t a_context; 1964 */ 1965static int 1966smbfs_vnop_inactive(struct vnop_inactive_args *ap) 1967{ 1968 vnode_t vp = ap->a_vp; 1969 struct smbnode *np; 1970 struct smb_share *share = NULL; 1971 int error = 0; 1972 int releaseLock = TRUE; 1973 1974 SMB_LOG_KTRACE(SMB_DBG_INACTIVE | DBG_FUNC_START, 0, 0, 0, 0, 0); 1975 1976 (void)smbnode_lock(VTOSMB(vp), SMBFS_RECLAIM_LOCK); 1977 np = VTOSMB(vp); 1978 np->n_lastvop = smbfs_vnop_inactive; 1979 share = smb_get_share_with_reference(VTOSMBFS(vp)); 1980 1981 1982 /* Clear any symlink cache, always safe to do even on non symlinks */ 1983 if (np->n_symlink_target) { 1984 SMB_FREE(np->n_symlink_target, M_TEMP); 1985 } 1986 np->n_symlink_target_len = 0; 1987 np->n_symlink_cache_timer = 0; 1988 1989 /* Node went inactive clear the ACL cache */ 1990 if (!vnode_isnamedstream(vp)) 1991 smbfs_clear_acl_cache(np); 1992 1993 /* 1994 * Before we take the lock, someone could jump in and do an open and start using this vnode again. 1995 * We now check for that and just skip out if it happens. We will get another inactive later, if 1996 * this volume is not being force unmount. So check here to see if the vnode is in use and the 1997 * volume is not being forced unmounted. Note that Kqueue opens will not be found by vnode_isinuse. 1998 */ 1999 if ((vnode_isinuse(vp, 0)) && !(vfs_isforce(vnode_mount(vp)))) 2000 goto out; 2001 2002 if (vnode_isdir(vp)) { 2003 smbfs_closedirlookup(np, ap->a_context); 2004 np->d_refcnt = 0; 2005 if (np->d_kqrefcnt) { 2006 smbfs_stop_change_notify(share, np, TRUE, ap->a_context, &releaseLock); 2007 } 2008 goto out; 2009 } 2010 2011 /* its not in use are they don't care about it close it */ 2012 if (np->f_refcnt) { 2013 np->f_refcnt = 1; 2014 error = smbfs_close(share, vp, FREAD, ap->a_context); 2015 if (error) { 2016 lck_rw_lock_shared(&np->n_name_rwlock); 2017 SMBDEBUG("error %d closing fid %llx file %s\n", 2018 error, np->f_fid, np->n_name); 2019 lck_rw_unlock_shared(&np->n_name_rwlock); 2020 } 2021 } 2022 2023 /* 2024 * Does the file need to be deleted on close. Make one more check here 2025 * just in case. 2026 */ 2027 if (np->n_flag & NDELETEONCLOSE) { 2028 error = smbfs_smb_delete(share, np, VREG, 2029 NULL, 0, 2030 0, ap->a_context); 2031 if (error) { 2032 lck_rw_lock_shared(&np->n_name_rwlock); 2033 SMBWARNING("error %d deleting silly rename file %s\n", 2034 error, np->n_name); 2035 lck_rw_unlock_shared(&np->n_name_rwlock); 2036 } 2037 else np->n_flag &= ~NDELETEONCLOSE; 2038 } 2039#ifdef SMB_DEBUG 2040 /* If the file is not in use then it should be closed. */ 2041 DBG_ASSERT((np->f_refcnt == 0)); 2042 DBG_ASSERT((np->f_openDenyList == NULL)); 2043 DBG_ASSERT((np->f_smbflock == NULL)); 2044#endif // SMB_DEBUG 2045 2046out: 2047 smb_share_rele(share, ap->a_context); 2048 if (releaseLock) 2049 smbnode_unlock(np); 2050 2051 SMB_LOG_KTRACE(SMB_DBG_INACTIVE | DBG_FUNC_END, 0, 0, 0, 0, 0); 2052 return (0); 2053} 2054 2055/* 2056 * Free smbnode, and give vnode back to system 2057 * struct vnodeop_desc *a_desc; 2058 * vnode_t a_vp; 2059 * vfs_context_t a_context; 2060 */ 2061static int smbfs_vnop_reclaim(struct vnop_reclaim_args *ap) 2062{ 2063 vnode_t vp = ap->a_vp; 2064 vnode_t dvp; 2065 struct smbnode *np = NULL; 2066 struct smbmount *smp = NULL; 2067 2068 SMB_LOG_KTRACE(SMB_DBG_RECLAIM | DBG_FUNC_START, 0, 0, 0, 0, 0); 2069 2070 (void) smbnode_lock(VTOSMB(vp), SMBFS_RECLAIM_LOCK); 2071 2072 np = VTOSMB(vp); 2073 np->n_lastvop = smbfs_vnop_reclaim; 2074 smp = VTOSMBFS(vp); 2075 2076#ifdef SMB_DEBUG 2077 /* We should never have a file open at this point */ 2078 if (vnode_isreg(vp)) { 2079 DBG_ASSERT((np->f_refcnt == 0)); 2080 } else if (vnode_isdir(vp)) { 2081 DBG_ASSERT((np->d_kqrefcnt == 0)); 2082 DBG_ASSERT((np->d_fctx == NULL)); 2083 } 2084#endif // SMB_DEBUG 2085 2086 lck_rw_lock_exclusive(&np->n_parent_rwlock); 2087 2088 SET(np->n_flag, NTRANSIT); 2089 2090 dvp = ((np->n_parent && (np->n_flag & NREFPARENT)) && 2091 ((np->n_parent->n_flag & NTRANSIT) != NTRANSIT)) ? 2092 np->n_parent->n_vnode : NULL; 2093 2094 if (dvp != NULL) { 2095 /* Parent exists and is not being reclaimed, remove child's refcount */ 2096 OSDecrementAtomic(&VTOSMB(dvp)->n_child_refcnt); 2097 np->n_parent = NULL; 2098 } 2099 2100 lck_rw_unlock_exclusive(&np->n_parent_rwlock); 2101 2102 SMB_LOG_KTRACE(SMB_DBG_RECLAIM | DBG_FUNC_NONE, 2103 0xabc001, 2104 np->n_child_refcnt, 2105 vfs_isforce(vnode_mount(vp)), 0, 0); 2106 2107 /* Child_refcnt should be zero */ 2108 if (np->n_child_refcnt) { 2109 if (!(vfs_isforce(vnode_mount(vp)))) { 2110 /* 2111 * Forced unmounts are very brutal, and it's not unusual for a 2112 * parent node being reclaimed to have a non-zero child refcount. 2113 * So we only log an error if this is not a forced unmount, which 2114 * we do care about. 2115 */ 2116 if (vnode_getname(vp) != NULL) { 2117 SMBERROR("%s: node: %s, n_child_refcnt not zero like it should be: %ld\n", 2118 __FUNCTION__, vnode_getname(vp), (long) np->n_child_refcnt); 2119 } 2120 else { 2121 SMBERROR("%s: n_child_refcnt not zero like it should be: %ld\n", 2122 __FUNCTION__, (long) np->n_child_refcnt); 2123 } 2124 } 2125 2126 /* 2127 * We hold sm_reclaim_lock to protect np->n_parent fields from a 2128 * race with other functions that walk all the parents up to the root 2129 * vnode. Always lock sm_reclaim_lock first and then individual 2130 * n_parent_rwlock/n_name_rwlock next. 2131 * See <rdar://problem/15707521>. 2132 */ 2133 lck_mtx_lock(&smp->sm_reclaim_lock); 2134 2135 smbfs_ClearChildren(smp, np); 2136 2137 /* 2138 * In previous code - smb_vhashrem() was called after releasing 2139 * sm_reclaim_lock. 2140 * There was a small window between sm_reclaim_lock is released and 2141 * smbnode (say child) is deleted from hash. 2142 * During this window, child can be NTRANSIT and parent can acquire 2143 * sm_reclaim_lock, proceed further in reclaim to call 2144 * smbfs_ClearChildren(), but skips the above child (NTRASIT set), 2145 * gets deleted from hash before child gets deleted. 2146 * May not affect anything as such, but just to be safe, I am moving 2147 * smb_vhashrem() in the scope of the sm_reclaim_lock. 2148 * Most likely, this can happen during the force unmount. 2149 */ 2150 smb_vhashrem(np); 2151 2152 lck_mtx_unlock(&smp->sm_reclaim_lock); 2153 } 2154 else { 2155 smb_vhashrem(np); 2156 } 2157 2158 cache_purge(vp); 2159 if (smp->sm_rvp == vp) { 2160 SMBVDEBUG("root vnode\n"); 2161 smp->sm_rvp = NULL; 2162 } 2163 2164 /* Destroy the lock used for the open state, open deny list and resource size/timer */ 2165 if (!vnode_isdir(vp)) { 2166 lck_mtx_destroy(&np->f_openDenyListLock, smbfs_mutex_group); 2167 lck_mtx_destroy(&np->f_openStateLock, smbfs_mutex_group); 2168 lck_mtx_destroy(&np->f_clusterWriteLock, smbfs_mutex_group); 2169 if (!vnode_isnamedstream(vp)) 2170 lck_mtx_destroy(&np->rfrkMetaLock, smbfs_mutex_group); 2171 } 2172 2173 /* Clear any symlink cache, always safe to do even on non symlinks */ 2174 if (np->n_symlink_target != NULL) { 2175 SMB_FREE(np->n_symlink_target, M_TEMP); 2176 } 2177 np->n_symlink_target_len = 0; 2178 np->n_symlink_cache_timer = 0; 2179 2180 /* We are done with the node clear the acl cache and destroy the acl cache lock */ 2181 if (!vnode_isnamedstream(vp)) { 2182 smbfs_clear_acl_cache(np); 2183 lck_mtx_destroy(&np->f_ACLCacheLock, smbfs_mutex_group); 2184 } 2185 2186 /* Free up both names before we unlock the node */ 2187 lck_rw_lock_exclusive(&np->n_name_rwlock); 2188 if (np->n_name != NULL) { 2189 SMB_FREE(np->n_name, M_SMBNODENAME); 2190 np->n_name = NULL; 2191 } 2192 2193 if (np->n_sname != NULL) { 2194 SMB_FREE(np->n_sname, M_SMBNODENAME); 2195 np->n_sname = NULL; 2196 } 2197 lck_rw_unlock_exclusive(&np->n_name_rwlock); 2198 2199 /* Clear the private data pointer *before* unlocking the node, so we don't 2200 * race with another thread doing a 'np = VTOSMB(vp)'. 2201 */ 2202 vnode_clearfsnode(vp); 2203 smbnode_unlock(np); 2204 2205 CLR(np->n_flag, (NALLOC|NTRANSIT)); 2206 if (ISSET(np->n_flag, NWALLOC) || ISSET(np->n_flag, NWTRANSIT)) { 2207 CLR(np->n_flag, (NWALLOC|NWTRANSIT)); 2208 wakeup(np); 2209 } 2210 lck_rw_destroy(&np->n_rwlock, smbfs_rwlock_group); 2211 lck_rw_destroy(&np->n_name_rwlock, smbfs_rwlock_group); 2212 lck_rw_destroy(&np->n_parent_rwlock, smbfs_rwlock_group); 2213 SMB_FREE(np, M_SMBNODE); 2214 if (dvp && (vnode_get(dvp) == 0)) { 2215 vnode_rele(dvp); 2216 vnode_put(dvp); 2217 } 2218 2219 SMB_LOG_KTRACE(SMB_DBG_RECLAIM | DBG_FUNC_END, 0, 0, 0, 0, 0); 2220 return 0; 2221} 2222 2223/* 2224 * smbfs_getattr call from vfs. 2225 * 2226 * The calling routine must hold a reference on the share 2227 * 2228 */ 2229static int 2230smbfs_getattr(struct smb_share *share, vnode_t vp, struct vnode_attr *vap, 2231 vfs_context_t context) 2232{ 2233 if (share->ss_attributes & FILE_PERSISTENT_ACLS && 2234 (VATTR_IS_ACTIVE(vap, va_acl) || VATTR_IS_ACTIVE(vap, va_guuid) || 2235 VATTR_IS_ACTIVE(vap, va_uuuid))) { 2236 DBG_ASSERT(!vnode_isnamedstream(vp)); 2237 (void)smbfs_getsecurity(share, VTOSMB(vp), vap, context); 2238 } 2239 return smbfs_update_cache(share, vp, vap, context); 2240} 2241 2242/* 2243 * smbfs_vnop_getattr 2244 * 2245 * vnode_t a_vp; 2246 * struct vnode_attr *a_vap; 2247 * vfs_context_t a_context; 2248 */ 2249static int 2250smbfs_vnop_getattr(struct vnop_getattr_args *ap) 2251{ 2252 int32_t error = 0; 2253 struct smb_share *share; 2254 struct smbnode *np; 2255 2256 if ((error = smbnode_lock(VTOSMB(ap->a_vp), SMBFS_SHARED_LOCK))) { 2257 return (error); 2258 } 2259 2260 SMB_LOG_KTRACE(SMB_DBG_GET_ATTR | DBG_FUNC_START, 0, 0, 0, 0, 0); 2261 2262 np = VTOSMB(ap->a_vp); 2263 np->n_lastvop = smbfs_vnop_getattr; 2264 share = smb_get_share_with_reference(VTOSMBFS(ap->a_vp)); 2265 2266 /* Before updating see if it needs to be reopened. */ 2267 if ((!vnode_isdir(ap->a_vp)) && (np->f_openState & kNeedReopen)) { 2268 /* smbfs_smb_reopen_file should check to see if the share changed? */ 2269 (void)smbfs_smb_reopen_file(share, np, ap->a_context); 2270 } 2271 2272 error = smbfs_getattr(share, ap->a_vp, ap->a_vap, ap->a_context); 2273 smb_share_rele(share, ap->a_context); 2274 smbnode_unlock(np); 2275 2276 SMB_LOG_KTRACE(SMB_DBG_GET_ATTR | DBG_FUNC_END, error, 0, 0, 0, 0); 2277 return (error); 2278} 2279 2280/* 2281 * The number of seconds between Jan 1, 1970 and Jan 1, 1980. In that 2282 * interval there were 8 regular years and 2 leap years. 2283 */ 2284#define SECONDSTO1980 (((8 * 365) + (2 * 366)) * (24 * 60 * 60)) 2285static struct timespec fat1980_time = {SECONDSTO1980, 0}; 2286 2287/* 2288* The calling routine must hold a reference on the share 2289*/ 2290static int 2291smbfs_setattr(struct smb_share *share, vnode_t vp, struct vnode_attr *vap, 2292 vfs_context_t context) 2293{ 2294 struct smbnode *np = VTOSMB(vp); 2295 struct smbmount *smp = VTOSMBFS(vp); 2296 struct timespec *crtime, *mtime, *atime; 2297 u_quad_t tsize = 0; 2298 int error = 0, cerror, modified = 0; 2299 SMBFID fid = 0; 2300 uint32_t rights; 2301 Boolean useFatTimes = (share->ss_fstype == SMB_FS_FAT); 2302 enum vtype vnode_type = VREG; 2303 2304 SMB_LOG_KTRACE(SMB_DBG_SMBFS_SETATTR | DBG_FUNC_START, 0, 0, 0, 0, 0); 2305 2306 if (np == NULL) { 2307 SMBERROR("Null np \n"); 2308 error = EINVAL; 2309 goto out; 2310 } 2311 2312 if ((np) && (np->n_vnode)) { 2313 /* Use vnode to determine type */ 2314 vnode_type = vnode_isdir(np->n_vnode) ? VDIR : VREG; 2315 } 2316 2317 /* If this is a stream then they can only set the size */ 2318 if ((vnode_isnamedstream(vp)) && 2319 (vap->va_active & ~VNODE_ATTR_BIT(va_data_size))) { 2320 lck_rw_lock_shared(&np->n_name_rwlock); 2321 SMBDEBUG("Using stream node %s to set something besides the size?\n", 2322 np->n_name); 2323 lck_rw_unlock_shared(&np->n_name_rwlock); 2324 2325 error = ENOTSUP; 2326 goto out; 2327 } 2328 2329 /* 2330 * If our caller is trying to set multiple attributes, they 2331 * can make no assumption about what order they are done in. 2332 * Here we try to do them in order of decreasing likelihood 2333 * of failure, just to minimize the chance we'll wind up 2334 * with a partially complete request. 2335 */ 2336 2337 if (share->ss_attributes & FILE_PERSISTENT_ACLS && 2338 (VATTR_IS_ACTIVE(vap, va_acl) || VATTR_IS_ACTIVE(vap, va_guuid) || 2339 VATTR_IS_ACTIVE(vap, va_uuuid))) { 2340 error = smbfs_setsecurity(share, vp, vap, context); 2341 SMB_LOG_KTRACE(SMB_DBG_SMBFS_SETATTR | DBG_FUNC_NONE, 2342 0xabc001, error, 0, 0, 0); 2343 if (error) 2344 goto out; 2345 /* 2346 * Failing to set VATTR_SET_SUPPORTED to something which was 2347 * requested causes fallback to EAs, which we never want. This 2348 * is done because of HFS, so if you support it you have to 2349 * always return something, even if its wrong. 2350 */ 2351 if (VATTR_IS_ACTIVE(vap, va_acl)) 2352 VATTR_SET_SUPPORTED(vap, va_acl); 2353 if (VATTR_IS_ACTIVE(vap, va_guuid)) 2354 VATTR_SET_SUPPORTED(vap, va_guuid); 2355 if (VATTR_IS_ACTIVE(vap, va_uuuid)) 2356 VATTR_SET_SUPPORTED(vap, va_uuuid); 2357 modified = 1; 2358 } 2359 2360 /* 2361 * If the server supports the new UNIX extensions, then we can support 2362 * changing the uid, gid, mode, and va_flags. Currently the uid and gid 2363 * don't make any sense, but in the future we may add this support. 2364 * 2365 * The old code would check the users creditials here. There is no need for 2366 * that in our case. The lower level will make sure the correct local user 2367 * is using the vc and the server should protect us for any other case. 2368 */ 2369 2370 if ((VATTR_IS_ACTIVE(vap, va_mode)) || (VATTR_IS_ACTIVE(vap, va_flags))) { 2371 int supportUnixBSDFlags = ((UNIX_CAPS(share) & UNIX_SFILEINFO_UNIX_INFO2_CAP)) ? TRUE : FALSE; 2372 int supportUnixInfo2 = ((UNIX_CAPS(share) & UNIX_QFILEINFO_UNIX_INFO2_CAP)) ? TRUE : FALSE; 2373 int darwin = (SSTOVC(share)->vc_flags & SMBV_DARWIN) ? TRUE : FALSE; 2374 int dosattr = np->n_dosattr; 2375 uint32_t vaflags = 0; 2376 uint32_t vaflags_mask = SMB_FLAGS_NO_CHANGE; 2377 uint64_t vamode = SMB_MODE_NO_CHANGE; 2378 2379 if (VATTR_IS_ACTIVE(vap, va_flags)) { 2380 /* 2381 * Here we are strict, stricter than ufs in not allowing users to 2382 * attempt to set SF_SETTABLE bits or anyone to set unsupported bits. 2383 * However, we ignore attempts to set ATTR_ARCHIVE for directories 2384 * `cp -pr' from a more sensible file system attempts it a lot. 2385 */ 2386 if (vap->va_flags & ~(SF_ARCHIVED | SF_IMMUTABLE | UF_IMMUTABLE | UF_HIDDEN)) 2387 { 2388 error = EINVAL; 2389 goto out; 2390 } 2391 /* Only set items we can change and the server supports */ 2392 vaflags_mask = np->n_flags_mask & EXT_REQUIRED_BY_MAC; 2393 2394 /* 2395 * Remember that SMB_EFA_ARCHIVE means the items needs to be 2396 * archive and SF_ARCHIVED means the item has been archive. 2397 */ 2398 if (vap->va_flags & SF_ARCHIVED) { 2399 dosattr &= ~SMB_EFA_ARCHIVE; 2400 vaflags |= EXT_DO_NOT_BACKUP; 2401 } else { 2402 dosattr |= SMB_EFA_ARCHIVE; 2403 } 2404 /* 2405 * SMB_EFA_RDONLY ~ UF_IMMUTABLE 2406 * 2407 * We treat the SMB_EFA_RDONLY as the immutable flag. This allows 2408 * us to support the finder lock bit and makes us follow the 2409 * MSDOS code model. See msdosfs project. 2410 * 2411 * NOTE: The ready-only flags does not exactly follow the 2412 * lock/immutable bit also note the for directories its advisory only. 2413 * 2414 * We do not support the setting the read-only bit for folders if 2415 * the server does not support the new UNIX extensions. 2416 * 2417 * See Radar 5582956 for more details. 2418 */ 2419 if (SSTOVC(share)->vc_flags & SMBV_SMB2) { 2420 if (UNIX_SERVER(SSTOVC(share)) || (!vnode_isdir(vp))) { 2421 if (vap->va_flags & (SF_IMMUTABLE | UF_IMMUTABLE)) { 2422 dosattr |= SMB_EFA_RDONLY; 2423 vaflags |= EXT_IMMUTABLE; 2424 } 2425 else { 2426 dosattr &= ~SMB_EFA_RDONLY; 2427 } 2428 } 2429 } 2430 else { 2431 if (supportUnixBSDFlags || darwin || (!vnode_isdir(vp))) { 2432 if (vap->va_flags & (SF_IMMUTABLE | UF_IMMUTABLE)) { 2433 dosattr |= SMB_EFA_RDONLY; 2434 vaflags |= EXT_IMMUTABLE; 2435 } 2436 else { 2437 dosattr &= ~SMB_EFA_RDONLY; 2438 } 2439 } 2440 } 2441 2442 /* 2443 * NOTE: Windows does not set ATTR_ARCHIVE bit for directories. 2444 */ 2445 if ((! supportUnixBSDFlags) && (vnode_isdir(vp))) 2446 dosattr &= ~SMB_EFA_ARCHIVE; 2447 2448 /* Now deal with the new Hidden bit */ 2449 if (vap->va_flags & UF_HIDDEN) { 2450 dosattr |= SMB_EFA_HIDDEN; 2451 vaflags |= EXT_HIDDEN; 2452 } else { 2453 dosattr &= ~SMB_EFA_HIDDEN; 2454 } 2455 } 2456 2457 /* 2458 * Currently we do not allow setting the uid, gid, or sticky bits. Also 2459 * chmod on a symbolic link doesn't really make sense. BSD allows this 2460 * with the lchmod and on create, but Samba doesn't support this because 2461 * its not POSIX. If we try to chmod here it will get set on the target 2462 * which would be bad. So ignore the fact that they made this request. 2463 */ 2464 if (VATTR_IS_ACTIVE(vap, va_mode)) { 2465 if (supportUnixInfo2 && (!vnode_islnk(vp))) { 2466 vamode = vap->va_mode & ACCESSPERMS; 2467 } else if ((share->ss_attributes & FILE_PERSISTENT_ACLS) && 2468 (darwin || !UNIX_CAPS(share))) { 2469 vamode = vap->va_mode & ACCESSPERMS; 2470 } else if (SSTOVC(share)->vc_server_caps & kAAPL_SUPPORTS_NFS_ACE) { 2471 /* 2472 * For OS X <-> OS X PFS (where ACLs are off by default), we 2473 * need a way to set Posix permissions. If the server supports 2474 * the NFS ACE, then it will allow us to get the ACL and send 2475 * it back with the desired Posix permissions in the NFS ACE. 2476 */ 2477 vamode = vap->va_mode & ACCESSPERMS; 2478 } 2479 2480 } 2481 if (dosattr == np->n_dosattr) { 2482 vaflags_mask = 0; /* Nothing really changes, no need to make the call */ 2483 } 2484 if (vaflags_mask || (vamode != SMB_MODE_NO_CHANGE)) { 2485 if (!supportUnixInfo2) { 2486 /* Windows style server */ 2487 if (vaflags_mask) { 2488 error = smbfs_smb_setpattr(share, np, vnode_type, 2489 NULL, 0, 2490 dosattr, context); 2491 } 2492 if (vamode != SMB_MODE_NO_CHANGE) { 2493 /* Should we report the error? */ 2494 error = smbfs_set_ace_modes(share, np, vamode, context); 2495 } 2496 } else if (supportUnixBSDFlags) { 2497 /* Samba server that does support the BSD flags (Mac OS) */ 2498 error = smbfs_set_unix_info2(share, np, NULL, NULL, NULL, 2499 SMB_SIZE_NO_CHANGE, vamode, vaflags, 2500 vaflags_mask, context); 2501 } else { 2502 /* Samba server that doesn't support the BSD flags, Linux */ 2503 if (vamode != SMB_MODE_NO_CHANGE) { 2504 /* Now set the posix modes, using unix info level */ 2505 error = smbfs_set_unix_info2(share, np, NULL, NULL, NULL, 2506 SMB_SIZE_NO_CHANGE, vamode, 2507 SMB_FLAGS_NO_CHANGE, vaflags_mask, 2508 context); 2509 } 2510 if (vaflags_mask) { 2511 /* Set the BSD flags using normal smb info level */ 2512 error = smbfs_smb_setpattr(share, np, vnode_type, 2513 NULL, 0, 2514 dosattr, context); 2515 } 2516 } 2517 if (error) 2518 goto out; 2519 } 2520 /* Everything work update the local cache and mark that we did the work */ 2521 if (VATTR_IS_ACTIVE(vap, va_mode)) { 2522 if (vamode != SMB_MODE_NO_CHANGE) { 2523 np->n_mode = vamode; 2524 VATTR_SET_SUPPORTED(vap, va_mode); 2525 } 2526 } 2527 if (VATTR_IS_ACTIVE(vap, va_flags)) { 2528 np->n_dosattr = dosattr; 2529 VATTR_SET_SUPPORTED(vap, va_flags); 2530 } 2531 } 2532 2533 if (VATTR_IS_ACTIVE(vap, va_data_size) && (vnode_isreg(vp))) { 2534 uint32_t trycnt = 0; 2535 2536 ubc_msync (vp, 0, ubc_getsize(vp), NULL, UBC_PUSHDIRTY | UBC_SYNC); 2537 /* The seteof call requires the file to be opened for write and append data. */ 2538 rights = SMB2_FILE_WRITE_DATA | SMB2_FILE_APPEND_DATA; 2539 /* 2540 * The connection could go down in the middle of setting the eof, in 2541 * this case we will get a bad file descriptor error. Keep trying until 2542 * the open fails or we get something besides EBADF. 2543 * 2544 * We now have a counter that keeps us from going into an infinite loop. Once 2545 * we implement SMB 2/3 we should take a second look at how this should be done. 2546 */ 2547 do { 2548 error = smbfs_tmpopen(share, np, rights, &fid, context); 2549 if (error) { 2550 lck_rw_lock_shared(&np->n_name_rwlock); 2551 SMB_LOG_IO("%s seteof open failed %d\n", np->n_name, error); 2552 lck_rw_unlock_shared(&np->n_name_rwlock); 2553 /* The open failed, fail the seteof. */ 2554 break; 2555 } 2556 2557 /* zero fill if needed, ignore any errors will catch them on the seteof call */ 2558 tsize = np->n_size; 2559 if (tsize < vap->va_data_size) { 2560 error = smbfs_0extend(share, fid, tsize, vap->va_data_size, 0, context); 2561 SMB_LOG_KTRACE(SMB_DBG_SMBFS_SETATTR | DBG_FUNC_NONE, 2562 0xabc002, error, 0, 0, 0); 2563 } 2564 /* Set the eof on the server */ 2565 if (!error) { 2566 error = smbfs_seteof(share, np, fid, vap->va_data_size, context); 2567 SMB_LOG_KTRACE(SMB_DBG_SMBFS_SETATTR | DBG_FUNC_NONE, 2568 0xabc003, error, 0, 0, 0); 2569 } 2570 if (error == EBADF) { 2571 trycnt++; 2572 lck_rw_lock_shared(&np->n_name_rwlock); 2573 SMB_LOG_IO("%s seteof failed because of reconnect, trying again.\n", 2574 np->n_name); 2575 lck_rw_unlock_shared(&np->n_name_rwlock); 2576 } 2577 /* 2578 * Windows FAT file systems require a flush, after a seteof. Until the 2579 * the flush they will keep returning the old file size. 2580 */ 2581 if ((!error) && (share->ss_fstype == SMB_FS_FAT) && 2582 (!UNIX_SERVER(SSTOVC(share)))) { 2583 error = smbfs_smb_flush(share, fid, context); 2584 if (!error) 2585 np->n_flag &= ~NNEEDS_FLUSH; 2586 } 2587 /* We ignore errors on close, not much we can do about it here */ 2588 (void)smbfs_tmpclose(share, np, fid, context); 2589 } while ((error == EBADF) && (trycnt < SMB_MAX_REOPEN_CNT)); 2590 2591 lck_rw_lock_shared(&np->n_name_rwlock); 2592 SMB_LOG_IO("%s: Calling smbfs_setsize, old eof = %lld new eof = %lld\n", 2593 np->n_name, tsize, vap->va_data_size); 2594 lck_rw_unlock_shared(&np->n_name_rwlock); 2595 2596 if (error) { 2597 smbfs_setsize(vp, (off_t)tsize); 2598 goto out; 2599 } else { 2600 smbfs_setsize(vp, (off_t)vap->va_data_size); 2601 } 2602 SMB_LOG_KTRACE(SMB_DBG_SMBFS_SETATTR | DBG_FUNC_NONE, 2603 0xabc004, error, 0, 0, 0); 2604 2605 VATTR_SET_SUPPORTED(vap, va_data_size); 2606 /* Tell the stream's parent that something has changed */ 2607 if (vnode_isnamedstream(vp)) { 2608 vnode_t parent_vp = smb_update_rsrc_and_getparent(vp, TRUE); 2609 /* 2610 * We cannot always update the parents meta cache timer, so don't 2611 * even try here 2612 */ 2613 if (parent_vp) 2614 vnode_put(parent_vp); 2615 } 2616 2617 modified = 1; 2618 } 2619 2620 /* 2621 * Note that it's up to the caller to provide (or not) a fallback for 2622 * backup_time, as we don't support them. 2623 * 2624 */ 2625 crtime = VATTR_IS_ACTIVE(vap, va_create_time) ? &vap->va_create_time : NULL; 2626 mtime = VATTR_IS_ACTIVE(vap, va_modify_time) ? &vap->va_modify_time : NULL; 2627 atime = VATTR_IS_ACTIVE(vap, va_access_time) ? &vap->va_access_time : NULL; 2628 2629 /* 2630 * If they are just setting the time to the same value then just say we made 2631 * the call. This will not hurt anything and will protect us from badly 2632 * written applications. Here is what was happening in the case of the finder 2633 * copy. The file gets copied, and the modify time and create time have been set to 2634 * the current time by the server. The application is using utimes to set the 2635 * modify time to the original file's modify time. This time is before the create time. 2636 * So we set both the create and modify time to the same value. See the HFS note 2637 * below. Now the applications wants to set the create time to be the same as the 2638 * orignal file. In this case the original file has the same modify and create time. So 2639 * we end up setting the create time twice to the same value. Even with this code the 2640 * copy engine needs to be fixed, looking into that now. Looks like this will get fix 2641 * with Radar 4385758. We should retest once that radar is completed. 2642 */ 2643 if (crtime && (timespeccmp(crtime, &np->n_crtime, ==))) { 2644 VATTR_SET_SUPPORTED(vap, va_create_time); 2645 crtime = NULL; 2646 } 2647 if (mtime && (timespeccmp(mtime, &np->n_mtime, ==))) { 2648 VATTR_SET_SUPPORTED(vap, va_modify_time); 2649 mtime = NULL; 2650 } 2651 if (atime && (timespeccmp(atime, &np->n_atime, ==))) { 2652 VATTR_SET_SUPPORTED(vap, va_access_time); 2653 atime = NULL; 2654 } 2655 2656 /* 2657 * We sometimes get sent a zero access time. Did some testing and found 2658 * out the following: 2659 * 2660 * MSDOS - The date gets set to Dec 30 17:31:44 1969 2661 * SMB FAT - The date gets set to Jan 1 00:00:00 1980 2662 * UFS - The date gets set to Dec 31 16:00:00 1969 2663 * SMB NTFS- The date gets set to Dec 31 16:00:00 1969 2664 * HFS - The date displayed from ls is Dec 31 16:00:00 1969 2665 * HFS - The getattrlist date is <no value> 2666 * 2667 * I believe this is from a utimes call where they are setting the 2668 * modify time, but leaving the access time set to zero. We seem to be 2669 * doing the same thing as everyone else so let them do it. 2670 */ 2671 /* 2672 * The following comment came from the HFS code. 2673 * The utimes system call can reset the modification time but it doesn't 2674 * know about create times. So we need to ensure that the creation time 2675 * is always at least as old as the modification time. 2676 * 2677 * The HFS code also checks to make sure it was not the root vnode. Don 2678 * Brady said that the SMB code should not use that part of the check. 2679 */ 2680 if (!crtime && mtime && (timespeccmp(mtime, &np->n_crtime, <))) { 2681 crtime = mtime; 2682 } 2683 2684 if (!crtime && !mtime && !atime) { 2685 /* Nothing left to do here get out */ 2686 goto out; 2687 } 2688retrySettingTime: 2689#if 0 2690 lck_rw_lock_shared(&np->n_name_rwlock); 2691 if (crtime && mtime) { 2692 SMBDEBUG("%s crtime = %ld:%ld mtime = %ld:%ld\n", np->n_name, 2693 crtime->tv_sec, crtime->tv_nsec, mtime->tv_sec, mtime->tv_nsec); 2694 } else if (crtime) { 2695 SMBDEBUG("%s crtime = %ld:%ld\n", np->n_name, crtime->tv_sec, crtime->tv_nsec); 2696 } else if (mtime) { 2697 SMBDEBUG("%s mtime = %ld:%ld\n", np->n_name, mtime->tv_sec, mtime->tv_nsec); 2698 } 2699 lck_rw_unlock_shared(&np->n_name_rwlock); 2700#endif // SMB_DEBUG 2701 /* 2702 * FAT file systems don't support dates earlier than 1980, reset the 2703 * date to 1980. Now the Finder likes to set the create date to 1904 or 1946, 2704 * should we treat this special? We could hold on to the original time 2705 * and return that value until they reset it or the vnode goes away. Since 2706 * we never had any reports lets not add any extra code. 2707 */ 2708 if (useFatTimes) { 2709 if (crtime && (timespeccmp(crtime, &fat1980_time, <))) { 2710 crtime = &fat1980_time; 2711 lck_rw_lock_shared(&np->n_name_rwlock); 2712 SMBDEBUG("%s FAT crtime.tv_sec = %ld crtime.tv_nsec = %ld\n", 2713 np->n_name, crtime->tv_sec, crtime->tv_nsec); 2714 lck_rw_unlock_shared(&np->n_name_rwlock); 2715 } 2716 if (mtime && (timespeccmp(mtime, &fat1980_time, <))) { 2717 mtime = &fat1980_time; 2718 lck_rw_lock_shared(&np->n_name_rwlock); 2719 SMBDEBUG("%s FAT mtime.tv_sec = %ld mtime.tv_nsec = %ld\n", 2720 np->n_name, mtime->tv_sec, mtime->tv_nsec); 2721 lck_rw_unlock_shared(&np->n_name_rwlock); 2722 } 2723 /* Never let them set the access time before 1980 */ 2724 if (atime && (timespeccmp(atime, &fat1980_time, <))) { 2725 atime = NULL; 2726 } 2727 } 2728 2729 if (SSTOVC(share)->vc_flags & SMBV_SMB2) { 2730 /* SMB 2/3 always has to open/set/close the file */ 2731 error = smb2fs_smb_setpattrNT(share, np, vnode_type, 2732 NULL, 0, 2733 np->n_dosattr, crtime, 2734 mtime, atime, 2735 context); 2736 SMB_LOG_KTRACE(SMB_DBG_SMBFS_SETATTR | DBG_FUNC_NONE, 2737 0xabc005, error, 0, 0, 0); 2738 } 2739 else { 2740 rights = SMB2_FILE_WRITE_ATTRIBUTES; 2741 /* 2742 * For Windows 95/98/Me/NT4 and all old dialects we must have 2743 * the item open before we can set the date and time. For all 2744 * other systems; if the item is already open then make sure it 2745 * has the correct open mode. 2746 * 2747 * We currently never do a NT style open with write attributes. 2748 * So for all systems except NT4 that spport the NTCreateAndX 2749 * call we will fall through and just use the set path method. 2750 * In the future we may decide to add open deny support. So if 2751 * we decide to add write atributes access then this code will 2752 * work without any other changes. 2753 */ 2754 if ((SSTOVC(share)->vc_flags & SMBV_NT4) || 2755 (smp->sm_flags & MNT_REQUIRES_FILEID_FOR_TIME) || 2756 ((!vnode_isdir(vp)) && np->f_refcnt && (np->f_rights & rights))) { 2757 2758 /* 2759 * For NT systems we need the file open for write attributes. 2760 * Either write access or all access will work. If they 2761 * already have it open for all access just use that, 2762 * otherwise use write. We corrected tmpopen 2763 * to work correctly now. So just ask for the NT access. 2764 */ 2765 error = smbfs_tmpopen(share, np, rights, &fid, context); 2766 if (error) 2767 goto out; 2768 2769 error = smbfs_smb_setfattrNT(share, np->n_dosattr, fid, crtime, 2770 mtime, atime, context); 2771 cerror = smbfs_tmpclose(share, np, fid, context); 2772 if (cerror) { 2773 lck_rw_lock_shared(&np->n_name_rwlock); 2774 SMBERROR("error %d closing fid %llx file %s\n", 2775 cerror, fid, np->n_name); 2776 lck_rw_unlock_shared(&np->n_name_rwlock); 2777 } 2778 2779 } else { 2780 error = smbfs_smb_setpattrNT(share, np, vnode_type, 2781 NULL, 0, 2782 np->n_dosattr, crtime, mtime, 2783 atime, context); 2784 /* They don't support this call, we need to fallback to the old method; stupid NetApp */ 2785 if (error == ENOTSUP) { 2786 SMBWARNING("Server does not support setting time by path, fallback to old method\n"); 2787 smp->sm_flags |= MNT_REQUIRES_FILEID_FOR_TIME; /* Never go down this path again */ 2788 error = smbfs_tmpopen(share, np, rights, &fid, context); 2789 if (!error) { 2790 error = smbfs_smb_setfattrNT(share, np->n_dosattr, fid, 2791 crtime, mtime, atime, context); 2792 (void)smbfs_tmpclose(share, np, fid, context); 2793 } 2794 } 2795 } 2796 } 2797 /* 2798 * Some servers (NetApp) don't support setting time before 1970 and will 2799 * return an error here. So if we get an error and we were trying to set 2800 * the time to before 1970 lets try again, but this time lets treat them 2801 * the same as a FAT file system. 2802 */ 2803 if (error && !useFatTimes && 2804 ((crtime && (crtime->tv_sec < 0)) || (mtime && (mtime->tv_sec < 0)))) { 2805 useFatTimes = TRUE; 2806 goto retrySettingTime; 2807 } 2808 2809 if (error) 2810 goto out; 2811 2812 if (crtime) { 2813 VATTR_SET_SUPPORTED(vap, va_create_time); 2814 np->n_crtime = *crtime; 2815 } 2816 if (mtime) { 2817 VATTR_SET_SUPPORTED(vap, va_modify_time); 2818 np->n_mtime = *mtime; 2819 } 2820 if (atime) { 2821 VATTR_SET_SUPPORTED(vap, va_access_time); 2822 np->n_atime = *atime; 2823 } 2824 /* Update the change time */ 2825 if (crtime || mtime || atime) 2826 nanotime(&np->n_chtime); /* Need current date/time, so use nanotime */ 2827 2828out: 2829 if (modified) { 2830 /* 2831 * Invalidate attribute cache in case if server doesn't set 2832 * required attributes. 2833 */ 2834 np->attribute_cache_timer = 0; /* invalidate cache */ 2835 } 2836 2837 SMB_LOG_KTRACE(SMB_DBG_SMBFS_SETATTR | DBG_FUNC_END, error, 0, 0, 0, 0); 2838 return (error); 2839} 2840 2841/* 2842 * smbfs_vnop_getattr 2843 * 2844 * vnode_t a_vp; 2845 * struct vnode_attr *a_vap; 2846 * vfs_context_t a_context; 2847 */ 2848static int 2849smbfs_vnop_setattr(struct vnop_setattr_args *ap) 2850{ 2851 int32_t error = 0; 2852 struct smbnode *np; 2853 struct smb_share *share; 2854 2855 if ((error = smbnode_lock(VTOSMB(ap->a_vp), SMBFS_EXCLUSIVE_LOCK))) { 2856 return (error); 2857 } 2858 2859 SMB_LOG_KTRACE(SMB_DBG_SET_ATTR | DBG_FUNC_START, 0, 0, 0, 0, 0); 2860 2861 np = VTOSMB(ap->a_vp); 2862 np->n_lastvop = smbfs_vnop_setattr; 2863 share = smb_get_share_with_reference(VTOSMBFS(ap->a_vp)); 2864 error = smbfs_setattr (share, ap->a_vp, ap->a_vap, ap->a_context); 2865 smb_share_rele(share, ap->a_context); 2866 smbnode_unlock(VTOSMB(ap->a_vp)); 2867 /* If this is a stream try to update the parents meta cache timer. */ 2868 if (vnode_isnamedstream(ap->a_vp)) { 2869 vnode_t parent_vp = vnode_getparent(ap->a_vp); 2870 if (parent_vp) { 2871 VTOSMB(parent_vp)->attribute_cache_timer = 0; 2872 vnode_put(parent_vp); 2873 } 2874 } 2875 2876 SMB_LOG_KTRACE(SMB_DBG_SET_ATTR | DBG_FUNC_END, error, 0, 0, 0, 0); 2877 return (error); 2878} 2879 2880/* 2881 * smbfs_vnop_blockmap 2882 * 2883 * vnode_t a_vp; 2884 * off_t a_foffset; 2885 * uint32_t a_size; 2886 * daddr64_t *a_bpn; 2887 * uint32_t *a_run; 2888 * void *a_poff; 2889 * int32_t a_flags; 2890 */ 2891static int 2892smbfs_vnop_blockmap(struct vnop_blockmap_args *ap) 2893{ 2894 /* 2895 * Always match the VM page size. At this time it is 4K which limits us 2896 * to 44 bit file size instead of 64...??? 2897 */ 2898 /* make sure we don't go past EOF */ 2899 if (ap->a_run) 2900 *ap->a_run = ap->a_size; 2901 2902 /* divide it by block size, MUST match value in smbfs_strategy */ 2903 *ap->a_bpn = (daddr64_t)(ap->a_foffset / PAGE_SIZE); 2904 2905 if (ap->a_poff) 2906 *(int32_t *)ap->a_poff = 0; 2907 2908 return (0); 2909} 2910 2911/* 2912 * smbfs_vnop_strategy 2913 * 2914 * struct buf *a_bp; 2915 */ 2916static int 2917smbfs_vnop_strategy(struct vnop_strategy_args *ap) 2918{ 2919 struct buf *bp = ap->a_bp; 2920 vnode_t vp = buf_vnode(bp); 2921 int32_t bflags = buf_flags(bp); 2922 struct smbnode *np = VTOSMB(vp); 2923 caddr_t io_addr = 0; 2924 uio_t uio = NULL; 2925 int32_t error; 2926 SMBFID fid = 0; 2927 struct smb_share *share; 2928 uint32_t trycnt = 0; 2929 struct smbfattr *fap = NULL; 2930 2931 SMB_LOG_KTRACE(SMB_DBG_STRATEGY | DBG_FUNC_START, 0, 0, 0, 0, 0); 2932 2933 if (np->f_openState & kNeedRevoke) { 2934 /* behave like the deadfs does */ 2935 lck_rw_lock_shared(&np->n_name_rwlock); 2936 SMBERROR("%s waiting to be revoked\n", np->n_name); 2937 lck_rw_unlock_shared(&np->n_name_rwlock); 2938 error = EIO; 2939 buf_seterror(bp, error); 2940 goto exit; 2941 } 2942 2943 if (np->f_refcnt == 0) { 2944 /* 2945 * This happens when a file is open and mmapped, then server goes down 2946 * and calls start soft timing out with ETIMEDOUT. The reads/writes 2947 * error out, then the close gets called, it gets an error but clears 2948 * the f_refcnt. When unmount comes along, it tries again to push 2949 * out the data and thats when we end up here. 2950 */ 2951 lck_rw_lock_shared(&np->n_name_rwlock); 2952 SMBDEBUG("%s has no file refs\n", np->n_name); 2953 lck_rw_unlock_shared(&np->n_name_rwlock); 2954 error = EIO; 2955 buf_seterror(bp, error); 2956 goto exit; 2957 } 2958 2959 SMB_MALLOC(fap, 2960 struct smbfattr *, 2961 sizeof(struct smbfattr), 2962 M_SMBTEMP, 2963 M_WAITOK | M_ZERO); 2964 if (fap == NULL) { 2965 SMBERROR("SMB_MALLOC failed\n"); 2966 error = ENOMEM; 2967 goto exit; 2968 } 2969 2970 /* 2971 * Can't use the physical addresses passed in the vector list, so map it 2972 * into the kernel address space 2973 */ 2974 if ((error = buf_map(bp, &io_addr))) { 2975 panic("smbfs_vnop_strategy: buf_map() failed with (%d)", error); 2976 } 2977 2978 uio = uio_create(1, ((off_t)buf_blkno(bp)) * PAGE_SIZE, UIO_SYSSPACE, 2979 (bflags & B_READ) ? UIO_READ : UIO_WRITE); 2980 if (!uio) { 2981 panic("smbfs_vnop_strategy: uio_create() failed"); 2982 } 2983 2984 uio_addiov(uio, CAST_USER_ADDR_T(io_addr), buf_count(bp)); 2985 /* 2986 * Remember that buf_proc(bp) can return NULL, but in that case this is 2987 * coming from the kernel and is not associated with a particular proc. 2988 * In fact it just may be the pager itself trying to free up space and there 2989 * is no proc. I need to find any proc that already has the fork open for 2990 * read or write to use for read/write to work. This is handled in the 2991 * FindFileRef routine. 2992 */ 2993 if (FindFileRef(vp, buf_proc(bp), (bflags & B_READ) ? kAccessRead : kAccessWrite, 2994 kCheckDenyOrLocks, uio_offset(uio), uio_resid(uio), NULL, &fid)) { 2995 /* No matches or no pid to match, so just use the generic shared fork */ 2996 fid = np->f_fid; /* We should always have something at this point */ 2997 } 2998 DBG_ASSERT(fid); 2999 3000 lck_rw_lock_shared(&np->n_name_rwlock); 3001 SMB_LOG_IO("%s: %s offset %lld, size %lld, bflags 0x%x\n", 3002 (bflags & B_READ) ? "Read":"Write", np->n_name, uio_offset(uio), 3003 uio_resid(uio), bflags); 3004 lck_rw_unlock_shared(&np->n_name_rwlock); 3005 3006 share = smb_get_share_with_reference(VTOSMBFS(vp)); 3007 /* 3008 * Since we have already authorized the user when we opened the file, just 3009 * pass a NULL context down to the authorization code. 3010 */ 3011 if (bflags & B_READ) { 3012 error = smbfs_doread(share, (off_t)np->n_size, uio, fid, NULL); 3013 } else { 3014 error = smbfs_dowrite(share, (off_t)np->n_size, uio, fid, 0, NULL); 3015 3016 if (!error) { 3017 /* Save last time we wrote data */ 3018 nanouptime(&np->n_last_write_time); 3019 } 3020 } 3021 SMB_LOG_KTRACE(SMB_DBG_STRATEGY | DBG_FUNC_NONE, 3022 0xabc001, error, 0, 0, 0); 3023 3024 /* 3025 * We can't handle reopens in the normal fashion, because we have no lock. A 3026 * bad file descriptor error, could mean a reconnect happen. Since 3027 * we revoke all opens with manatory locks or open deny mode, we can just 3028 * do the open, read/write then close. 3029 * 3030 * We now have a counter that keeps us from going into an infinite loop. Once 3031 * we implement SMB 2/3 we should take a second look at how this should be done. 3032 */ 3033 while ((error == EBADF) && (trycnt < SMB_MAX_REOPEN_CNT)) { 3034 lck_mtx_lock(&np->f_openStateLock); 3035 3036 lck_rw_lock_shared(&np->n_name_rwlock); 3037 SMB_LOG_IO("%s failed the %s, because of reconnect, openState = 0x%x. Try again.\n", 3038 np->n_name, (bflags & B_READ) ? "READ" : "WRITE", np->f_openState); 3039 lck_rw_unlock_shared(&np->n_name_rwlock); 3040 3041 if (np->f_openState & kNeedRevoke) { 3042 lck_mtx_unlock(&np->f_openStateLock); 3043 break; 3044 } 3045 3046 np->f_openState |= (kNeedReopen | kInReopen); 3047 lck_mtx_unlock(&np->f_openStateLock); 3048 3049 /* Could be a dfs share make sure we have the correct share */ 3050 smb_share_rele(share, NULL); 3051 share = smb_get_share_with_reference(VTOSMBFS(vp)); 3052 /* Recreate the uio */ 3053 uio_free(uio); 3054 uio = uio_create(1, ((off_t)buf_blkno(bp)) * PAGE_SIZE, UIO_SYSSPACE, 3055 (bflags & B_READ) ? UIO_READ : UIO_WRITE); 3056 if (!uio) { 3057 error = ENOMEM; 3058 } else { 3059 uio_addiov(uio, CAST_USER_ADDR_T(io_addr), buf_count(bp)); 3060 3061 error = smbfs_smb_open_file(share, np, 3062 np->f_rights, NTCREATEX_SHARE_ACCESS_ALL, &fid, 3063 NULL, 0, FALSE, 3064 fap, NULL); 3065 } 3066 3067 lck_mtx_lock(&np->f_openStateLock); 3068 np->f_openState &= ~kInReopen; 3069 lck_mtx_unlock(&np->f_openStateLock); 3070 3071 if (error) { 3072 break; 3073 } 3074 if (bflags & B_READ) { 3075 error = smbfs_doread(share, (off_t)np->n_size, uio, fid, NULL); 3076 } else { 3077 error = smbfs_dowrite(share, (off_t)np->n_size, uio, fid, 0, NULL); 3078 3079 if (!error) { 3080 /* Save last time we wrote data */ 3081 nanouptime(&np->n_last_write_time); 3082 } 3083 } 3084 SMB_LOG_KTRACE(SMB_DBG_STRATEGY | DBG_FUNC_NONE, 3085 0xabc002, error, 0, 0, 0); 3086 3087 (void)smbfs_smb_close(share, fid, NULL); 3088 trycnt++; 3089 } 3090 3091 if (bflags & B_READ) { 3092 /* 3093 * If we were not able to read the entire page, check to 3094 * see if we are at the end of the file, and if so, zero 3095 * out the remaining part of the page. 3096 */ 3097 while ((error == 0) && (uio_resid(uio))) { 3098 size_t bytes_to_zero = (uio_resid(uio) > PAGE_SIZE) ? PAGE_SIZE : (size_t)uio_resid(uio); 3099 3100 bzero((caddr_t) (io_addr + buf_count(bp) - uio_resid(uio)), bytes_to_zero); 3101 uio_update(uio, bytes_to_zero); 3102 } 3103 } else { 3104 lck_mtx_lock(&np->f_clusterWriteLock); 3105 if ((u_quad_t)uio_offset(uio) >= np->n_size) { 3106 /* We finished writing past the eof reset the flag */ 3107 nanouptime(&np->n_sizetime); 3108 np->waitOnClusterWrite = FALSE; 3109 lck_rw_lock_shared(&np->n_name_rwlock); 3110 SMB_LOG_IO("%s: TURNING OFF waitOnClusterWrite np->n_size = %lld\n", 3111 np->n_name, np->n_size); 3112 lck_rw_unlock_shared(&np->n_name_rwlock); 3113 } 3114 lck_mtx_unlock(&np->f_clusterWriteLock); 3115 } 3116 3117 if (error) { 3118 lck_rw_lock_shared(&np->n_name_rwlock); 3119 SMBERROR("%s on %s failed with an error of %d\n", 3120 (bflags & B_READ) ? "READ" : "WRITE", np->n_name, error); 3121 lck_rw_unlock_shared(&np->n_name_rwlock); 3122 3123 np->f_clusterCloseError = error; /* Error to be returned on close */ 3124 3125 if ( (error == ENOTCONN) || (error == EBADF) || (error == ETIMEDOUT) ) { 3126 /* 3127 * VFS cluster code has now been changed to handle non transient 3128 * errors see radar 2894150. It should be safe to return ENXIO. 3129 */ 3130 SMB_LOG_IO("failed with %d, returning ENXIO instead\n", error); 3131 error = ENXIO; 3132 } 3133 } 3134 smb_share_rele(share, NULL); 3135 buf_seterror(bp, error); 3136 3137 /* Should be zero when all done with reading/writing file */ 3138 buf_setresid(bp, (uint32_t)uio_resid(uio)); 3139 3140 if ((error = buf_unmap(bp))) 3141 panic("smbfs_vnop_strategy: buf_unmap() failed with (%d)", error); 3142 3143 3144exit: 3145 if (error) { 3146 lck_rw_lock_shared(&np->n_name_rwlock); 3147 SMB_LOG_IO("%s: buf_resid(bp) %d, error = %d \n", 3148 np->n_name, buf_resid(bp), error); 3149 lck_rw_unlock_shared(&np->n_name_rwlock); 3150 } 3151 3152 if (uio != NULL) 3153 uio_free(uio); 3154 3155 buf_biodone(bp); 3156 3157 if (fap != NULL) { 3158 SMB_FREE(fap, M_SMBTEMP); 3159 } 3160 3161 SMB_LOG_KTRACE(SMB_DBG_STRATEGY | DBG_FUNC_END, error, 0, 0, 0, 0); 3162 return (error); 3163} 3164 3165/* 3166 * smbfs_vnop_read 3167 * 3168 * vnode_t a_vp; 3169 * uio_t a_uio; 3170 * int a_ioflag; 3171 * vfs_context_t a_context; 3172 */ 3173static int 3174smbfs_vnop_read(struct vnop_read_args *ap) 3175{ 3176 vnode_t vp = ap->a_vp; 3177 uio_t uio = ap->a_uio; 3178 int error = 0; 3179 struct smbnode *np = NULL; 3180 SMBFID fid = 0; 3181 struct smb_share *share; 3182 3183 /* Preflight checks */ 3184 if (!vnode_isreg(vp)) { 3185 /* can only read regular files */ 3186 if (vnode_isdir(vp)) 3187 return (EISDIR); 3188 else 3189 return (EPERM); 3190 } 3191 3192 if (uio_resid(uio) == 0) 3193 return (0); /* Nothing left to do */ 3194 3195 if (uio_offset(uio) < 0) 3196 return (EINVAL); /* cant read from a negative offset */ 3197 3198 if ((error = smbnode_lock(VTOSMB(vp), SMBFS_SHARED_LOCK))) 3199 return (error); 3200 3201 SMB_LOG_KTRACE(SMB_DBG_READ | DBG_FUNC_START, 3202 uio_offset(uio), 3203 uio_resid(uio), 0, 0, 0); 3204 3205 np = VTOSMB(vp); 3206 np->n_lastvop = smbfs_vnop_read; 3207 share = smb_get_share_with_reference(VTOSMBFS(vp)); 3208 /* 3209 * History: FreeBSD vs Darwin VFS difference; we can get VNOP_READ without 3210 * preceeding open via the exec path, so do it implicitly. VNOP_INACTIVE 3211 * closes the extra network file handle, and decrements the open count. 3212 * 3213 * If we are in reconnect mode calling smbfs_open will handle any reconnect 3214 * issues. So only if we have a f_refcnt do we call smbfs_smb_reopen_file. 3215 */ 3216 if (!np->f_refcnt) { 3217 error = smbfs_open(share, vp, FREAD, ap->a_context); 3218 if (error) 3219 goto exit; 3220 else np->f_needClose = 1; 3221 } else { 3222 error = smbfs_smb_reopen_file(share, np, ap->a_context); 3223 if (error) { 3224 lck_rw_lock_shared(&np->n_name_rwlock); 3225 SMBDEBUG(" %s waiting to be revoked\n", np->n_name); 3226 lck_rw_unlock_shared(&np->n_name_rwlock); 3227 goto exit; 3228 } 3229 } 3230 3231 /* 3232 * Note: smbfs_isCacheable checks to see if the file is globally non 3233 * cacheable, but we also need to support non cacheable on a per file 3234 * descriptor level for reads/writes. So also check the IO_NOCACHE flag. 3235 * 3236 * So IO_NOCACHE means the same thing as VNOCACHE_DATA but only for this IO. 3237 * Now VNOCACHE_DATA has the following comment: 3238 * "don't keep data cached once it's been consumed" 3239 * Which seems to imply we could use cluster_read, but we would need to 3240 * push out any data first and then invalidate the range after we are done 3241 * with the read? Byte range locking prevents us from using the cluster_read. 3242 */ 3243 if ( smbfsIsCacheable(vp) && !(ap->a_ioflag & IO_NOCACHE)) { 3244 error = cluster_read(vp, uio, (off_t) np->n_size, ap->a_ioflag); 3245 SMB_LOG_KTRACE(SMB_DBG_READ | DBG_FUNC_NONE, 0xabc001, error, 0, 0, 0); 3246 if (error) { 3247 lck_rw_lock_shared(&np->n_name_rwlock); 3248 SMB_LOG_IO("%s failed cluster_read with an error of %d\n", 3249 np->n_name, error); 3250 lck_rw_unlock_shared(&np->n_name_rwlock); 3251 } 3252 /* 3253 * EACCES means a denyConflict occured and must have hit some other 3254 * computer's byte range lock on that file. Mark the file as 3255 * noncacheable and retry read again 3256 * 3257 * Need to check the error here, could be EIO/EPERM 3258 * 3259 * XXX - NOTE: The strategy routine is going to mark this vnode as needing 3260 * to be revoked. So this code seems wrong. We should either correct 3261 * the strategy routine or remove this code. 3262 */ 3263 if (error == EACCES) { 3264 if (np->n_flag & NISMAPPED) { 3265 /* More expensive, but handles mmapped files */ 3266 ubc_msync (vp, 0, ubc_getsize(vp), NULL, UBC_PUSHDIRTY | UBC_SYNC); 3267 } else { 3268 /* Less expensive, but does not handle mmapped files */ 3269 cluster_push(vp, IO_SYNC); 3270 } 3271 ubc_msync (vp, 0, ubc_getsize(vp), NULL, UBC_INVALIDATE); 3272 vnode_setnocache(vp); 3273 /* Fall through and try a non cached read */ 3274 error = 0; 3275 } else { 3276 goto exit; 3277 } 3278 } 3279 3280 if (error) 3281 goto exit; 3282 3283 /* 3284 * AFP COMMENTS (<rdar://problem/5977339>) Be careful of a cacheable write 3285 * that extends the eof, but leaves a hole between the old eof and the new 3286 * eof. It that is followed by a non cacheable read that starts before the 3287 * old eof and extends into the hole (or starts in the hole), but does not 3288 * extend past the hole, then msync for the read range will not find any 3289 * dirty pages in the hole and thus no data will be pushed and thus the eof 3290 * will not get extended which will cause the non cacheable read to get 3291 * erroneous data. cluster_push works around this because it pushes all of 3292 * the pages in the delayed clusters. msync for the entire range also works 3293 * too. 3294 */ 3295 if (VTOSMB(vp)->n_flag & NISMAPPED) { 3296 /* More expensive, but handles mmapped files */ 3297 ubc_msync (vp, 0, ubc_getsize(vp), NULL, UBC_PUSHDIRTY | UBC_SYNC); 3298 } else { 3299 /* Less expensive, but does not handle mmapped files */ 3300 cluster_push(vp, IO_SYNC); 3301 } 3302 3303 /* 3304 * AFP doesn't invalidate the range here. That seems wrong, we should 3305 * invalidate the range here. 3306 */ 3307 ubc_msync (vp, uio_offset(uio), uio_offset(uio)+ uio_resid(uio), NULL, 3308 UBC_INVALIDATE); 3309 3310 if (FindFileRef(vp, vfs_context_proc(ap->a_context), kAccessRead, 3311 kCheckDenyOrLocks, uio_offset(uio), uio_resid(uio), 3312 NULL, &fid)) { 3313 /* No matches or no pid to match, so just use the generic shared fork */ 3314 fid = np->f_fid; /* We should always have something at this point */ 3315 } 3316 DBG_ASSERT(fid); 3317 3318 error = smbfs_doread(share, (off_t)np->n_size, uio, fid, ap->a_context); 3319 SMB_LOG_KTRACE(SMB_DBG_READ | DBG_FUNC_NONE, 0xabc002, error, 0, 0, 0); 3320 3321 /* 3322 * We got an error, did it happen on a reconnect, then retry. First see if 3323 * we have a new share to use, then attmept to reopent the file, then try 3324 * the read again. 3325 */ 3326 while (error == EBADF) { 3327 lck_rw_lock_shared(&np->n_name_rwlock); 3328 SMB_LOG_IO("%s failed the non cache read, because of reconnect. Try again.\n", 3329 np->n_name); 3330 lck_rw_unlock_shared(&np->n_name_rwlock); 3331 3332 /* Could be a dfs share make sure we have the correct share */ 3333 smb_share_rele(share, ap->a_context); 3334 share = smb_get_share_with_reference(VTOSMBFS(vp)); 3335 /* The reopen code will handle the case of the node being revoked. */ 3336 if (smbfs_io_reopen(share, vp, uio, kAccessRead, &fid, error, ap->a_context) == 0) { 3337 error = smbfs_doread(share, (off_t)np->n_size, uio, fid, 3338 ap->a_context); 3339 SMB_LOG_KTRACE(SMB_DBG_READ | DBG_FUNC_NONE, 3340 0xabc003, error, 0, 0, 0); 3341 } 3342 else { 3343 lck_rw_lock_shared(&np->n_name_rwlock); 3344 SMB_LOG_IO("%s : The Read reopen failed.\n", np->n_name); 3345 lck_rw_unlock_shared(&np->n_name_rwlock); 3346 break; 3347 } 3348 } 3349 3350 if (error) { 3351 lck_rw_lock_shared(&np->n_name_rwlock); 3352 SMB_LOG_IO("%s failed non cached read with an error of %d\n", np->n_name, error); 3353 lck_rw_unlock_shared(&np->n_name_rwlock); 3354 } 3355 3356exit: 3357 smb_share_rele(share, ap->a_context); 3358 smbnode_unlock(np); 3359 3360 SMB_LOG_KTRACE(SMB_DBG_READ | DBG_FUNC_END, error, 0, 0, 0, 0); 3361 return (error); 3362} 3363 3364/* 3365 * smbfs_vnop_write 3366 * 3367 * vnode_t a_vp; 3368 * uio_t a_uio; 3369 * int a_ioflag; 3370 * vfs_context_t a_context; 3371 */ 3372static int 3373smbfs_vnop_write(struct vnop_write_args *ap) 3374{ 3375 vnode_t vp = ap->a_vp; 3376 vnode_t parent_vp = NULL; /* Always null unless this is a stream node */ 3377 struct smbnode *np = NULL; 3378 struct smb_share *share; 3379 uio_t uio = ap->a_uio; 3380 int error = 0; 3381 SMBFID fid = 0; 3382 u_quad_t originalEOF; 3383 user_size_t writeCount; 3384 3385 /* Preflight checks */ 3386 if (!vnode_isreg(vp)) { 3387 /* can only read regular files */ 3388 if (vnode_isdir(vp)) 3389 return (EISDIR); 3390 else 3391 return (EPERM); 3392 } 3393 3394 if (uio_offset(uio) < 0) 3395 return (EINVAL); 3396 3397 if (uio_resid(uio) == 0) 3398 return (0); 3399 3400 if ((error = smbnode_lock(VTOSMB(vp), SMBFS_EXCLUSIVE_LOCK))) 3401 return (error); 3402 3403 SMB_LOG_KTRACE(SMB_DBG_WRITE | DBG_FUNC_START, 3404 uio_offset(uio), 3405 uio_resid(uio), 0, 0, 0); 3406 3407 np = VTOSMB(vp); 3408 np->n_lastvop = smbfs_vnop_write; 3409 share = smb_get_share_with_reference(VTOSMBFS(vp)); 3410 3411 /* Before trying the write see if the file needs to be reopened */ 3412 error = smbfs_smb_reopen_file(share, np, ap->a_context); 3413 if (error) { 3414 lck_rw_lock_shared(&np->n_name_rwlock); 3415 SMBDEBUG(" %s waiting to be revoked\n", np->n_name); 3416 lck_rw_unlock_shared(&np->n_name_rwlock); 3417 goto exit; 3418 } 3419 3420 if (ap->a_ioflag & IO_APPEND) 3421 uio_setoffset(uio, np->n_size); 3422 3423 originalEOF = np->n_size; /* Save off the orignial end of file */ 3424 3425 /* 3426 * Note: smbfs_isCacheable checks to see if the file is globally non 3427 * cacheable, but we also need to support non cacheable on a per file 3428 * descriptor level for reads/writes. So also check the IO_NOCACHE flag. 3429 * 3430 * So IO_NOCACHE means the same thing as VNOCACHE_DATA but only for this IO. 3431 * Now VNOCACHE_DATA has the following comment: 3432 * "don't keep data cached once it's been consumed" 3433 * Which seems to imply we could use cluster_write, but we would need to 3434 * push out any data and then invalidate the range after we are done 3435 * with the write? Byte range locking prevents us from using the cluster_write. 3436 */ 3437 if (smbfsIsCacheable(vp) && !(ap->a_ioflag & IO_NOCACHE)) { 3438 u_quad_t writelimit; 3439 u_quad_t newEOF; 3440 u_quad_t zero_head_off; 3441 u_quad_t zero_tail_off; 3442 int32_t lflag; 3443 3444 lflag = ap->a_ioflag & ~(IO_TAILZEROFILL | IO_HEADZEROFILL | 3445 IO_NOZEROVALID | IO_NOZERODIRTY); 3446 zero_head_off = 0; 3447 zero_tail_off = 0; 3448 writelimit = uio_offset(uio) + uio_resid(uio); 3449 3450 /* 3451 * They are writing pass the eof, force a zero fill. What should we 3452 * do for sparse files? 3453 */ 3454 if ((uint64_t)writelimit > np->n_size) { 3455 /* Save off the new eof */ 3456 newEOF = writelimit; 3457 if ((uint64_t) uio_offset(uio) > np->n_size) { 3458 zero_head_off = np->n_size; 3459 /* Make sure we tell the kernel to zero fill the head */ 3460 lflag |= IO_HEADZEROFILL; 3461 } 3462 zero_tail_off = (writelimit + (PAGE_SIZE_64 - 1)) & ~PAGE_MASK_64; 3463 if (zero_tail_off > newEOF) { 3464 zero_tail_off = newEOF; 3465 } 3466 if (zero_tail_off > writelimit) { 3467 /* Make sure we tell the kernel to zero fill the tail */ 3468 lflag |= IO_TAILZEROFILL; 3469 } 3470 } else 3471 newEOF = np->n_size; 3472 3473 lck_mtx_lock(&np->f_clusterWriteLock); 3474 if (originalEOF < newEOF) { 3475 np->waitOnClusterWrite = TRUE; 3476 np->n_size = newEOF; 3477 lck_rw_lock_shared(&np->n_name_rwlock); 3478 SMB_LOG_IO("%s: TURNING ON waitOnClusterWrite old eof = %lld new eof = %lld\n", 3479 np->n_name, originalEOF, newEOF); 3480 lck_rw_unlock_shared(&np->n_name_rwlock); 3481 } 3482 lck_mtx_unlock(&np->f_clusterWriteLock); 3483 /* 3484 * If the write starts beyond the current EOF then we we'll zero fill 3485 * from the current EOF to where the write begins 3486 */ 3487 error = cluster_write(vp, uio, originalEOF, newEOF, zero_head_off, zero_tail_off, lflag); 3488 SMB_LOG_KTRACE(SMB_DBG_WRITE | DBG_FUNC_NONE, 3489 0xabc001, error, 0, 0, 0); 3490 if (error) { 3491 lck_mtx_lock(&np->f_clusterWriteLock); 3492 np->n_size = originalEOF; /* Set it back to the original eof */ 3493 np->waitOnClusterWrite = FALSE; 3494 lck_mtx_unlock(&np->f_clusterWriteLock); 3495 3496 lck_rw_lock_shared(&np->n_name_rwlock); 3497 SMB_LOG_IO("%s failed cluster_write with an error of %d\n", np->n_name, error); 3498 lck_rw_unlock_shared(&np->n_name_rwlock); 3499 } 3500 /* 3501 * EACCES means a denyConflict occured and must have hit some other 3502 * computer's byte range lock on that file. Mark the file as 3503 * noncacheable and retry read again 3504 * 3505 * Need to check the error here, could be EIO/EPERM 3506 * 3507 * XXX - NOTE: The stragey routine is going to mark this vnode as needing 3508 * to be revokd. So this code seems wrong. We should either correct 3509 * the stragey routine or remove this code. 3510 */ 3511 if (error == EACCES) { 3512 if (np->n_flag & NISMAPPED) { 3513 /* More expensive, but handles mmapped files */ 3514 ubc_msync (vp, 0, ubc_getsize(vp), NULL, UBC_PUSHDIRTY | UBC_SYNC); 3515 } else { 3516 /* Less expensive, but does not handle mmapped files */ 3517 cluster_push(vp, IO_SYNC); 3518 } 3519 ubc_msync (vp, 0, ubc_getsize(vp), NULL, UBC_INVALIDATE); 3520 vnode_setnocache(vp); 3521 /* Fall through and try a non cached write */ 3522 error = 0; 3523 } else { 3524 goto exit; 3525 } 3526 } 3527 3528 if (error) 3529 goto exit; 3530 /* 3531 * If it is not cacheable, make sure to wipe out UBC since any of its 3532 * data would be no be invalid. Make sure to push out any dirty data 3533 * first due to prev cached write. 3534 */ 3535 ubc_msync(vp, uio_offset(uio), uio_offset(uio)+ uio_resid(uio), NULL, 3536 UBC_PUSHDIRTY | UBC_SYNC); 3537 ubc_msync(vp, uio_offset(uio), uio_offset(uio)+ uio_resid(uio), NULL, 3538 UBC_INVALIDATE); 3539 3540 3541 if (FindFileRef(vp, vfs_context_proc(ap->a_context), kAccessWrite, 3542 kCheckDenyOrLocks, uio_offset(uio), uio_resid(uio), NULL, &fid)) { 3543 /* No matches or no pid to match, so just use the generic shared fork */ 3544 fid = np->f_fid; /* We should always have something at this point */ 3545 } 3546 DBG_ASSERT(fid); 3547 3548 /* Total amount that we need to write */ 3549 writeCount = uio_resid(ap->a_uio); 3550 do { 3551 if (uio && (uio != ap->a_uio)) { 3552 /* We allocated, need to free it */ 3553 uio_free(uio); 3554 } 3555 /* 3556 * We could get disconnected in the middle of a write, so we need to make 3557 * a copy of the uio, just in case. 3558 */ 3559 uio = uio_duplicate(ap->a_uio); 3560 if (uio == NULL) { 3561 /* Failed, so just used the passed in uio */ 3562 uio = ap->a_uio; 3563 } 3564 error = smbfs_dowrite(share, (off_t)np->n_size, uio, fid, ap->a_ioflag, 3565 ap->a_context); 3566 SMB_LOG_KTRACE(SMB_DBG_WRITE | DBG_FUNC_NONE, 3567 0xabc002, error, 0, 0, 0); 3568 if (!error) { 3569 /* Save last time we wrote data */ 3570 nanouptime(&np->n_last_write_time); 3571 } 3572 3573 if (error == EBADF) { 3574 /* Could be a dfs share make sure we have the correct share */ 3575 smb_share_rele(share, ap->a_context); 3576 share = smb_get_share_with_reference(VTOSMBFS(vp)); 3577 if (smbfs_io_reopen(share, vp, uio, kAccessWrite, &fid, error, 3578 ap->a_context) != 0) { 3579 /* The reopen failed, just get out nothing left to do here */ 3580 break; 3581 } 3582 } 3583 } while ((error == EBADF) && (uio != ap->a_uio)); 3584 /* Set the original uio to match the one passed into the write. */ 3585 if (uio != ap->a_uio) { 3586 /* Total amount we were able to write */ 3587 writeCount -= uio_resid(uio); 3588 /* Update the user's uio with that amount */ 3589 uio_update( ap->a_uio, writeCount); 3590 uio_free(uio); 3591 uio = ap->a_uio; 3592 } 3593 3594 /* 3595 * Mark that we need to send a flush if we didn't get an error and 3596 * we didn't send a write though message. Remember if the IO_SYNC bit 3597 * is set then we set the write though bit, which should do the same 3598 * thing as a flush. 3599 */ 3600 if (!error && !(ap->a_ioflag & IO_SYNC)) { 3601 VTOSMB(vp)->n_flag |= NNEEDS_FLUSH; 3602 } else if (error) { 3603 lck_rw_lock_shared(&np->n_name_rwlock); 3604 SMB_LOG_IO("%s failed non cached write with an error of %d\n", 3605 np->n_name, error); 3606 lck_rw_unlock_shared(&np->n_name_rwlock); 3607 } 3608exit: 3609 /* Wrote pass the eof, need to set the new file size */ 3610 if (!error && ((uint64_t) uio_offset(uio) > originalEOF)) { 3611 /* 3612 * Windows servers do not handle writing past the end of file the 3613 * same as Unix servers. If we do a directory lookup before the file 3614 * is closed then the server may return the old size. Setting the end of 3615 * file here will prevent that from happening. Unix servers do not seem 3616 * to have this problem so there is no reason to make this call in that 3617 * case. So if the file size has changed and this is not a Unix server 3618 * then set the eof of file to the new value. 3619 */ 3620 if (!UNIX_SERVER(SSTOVC(share))) { 3621 /* 3622 * Just set the flag to set EOF later. Otherwise for every write 3623 * on a cached file, a set EOF request will be sent to the server. 3624 * This will result in hundreds/thousands of set EOF requests being 3625 * sent constantly to the server. 3626 * 3627 * The file size is cached locally so sending the set EOF request 3628 * to the server can wait until system sync or vnop_sync time. 3629 */ 3630 np->n_flag |= NNEEDS_EOF_SET; 3631 3632 /* 3633 * Windows FAT file systems require a flush, after a seteof. Until the 3634 * the flush they will keep returning the old file size. 3635 */ 3636 if (share->ss_fstype == SMB_FS_FAT) { 3637 /* Do the flush later too */ 3638 np->n_flag |= NNEEDS_FLUSH; 3639 3640 } 3641 } 3642 3643 smbfs_setsize(vp, uio_offset(uio)); 3644 3645 lck_rw_lock_shared(&np->n_name_rwlock); 3646 SMB_LOG_IO("%s: Calling smbfs_setsize, old eof = %lld new eof = %lld time %ld:%ld\n", 3647 np->n_name, originalEOF, uio_offset(uio), 3648 np->n_sizetime.tv_sec, np->n_sizetime.tv_nsec); 3649 lck_rw_unlock_shared(&np->n_name_rwlock); 3650 3651 /* 3652 * We could have lost a cache update in the write. Since we wrote pass 3653 * the eof, mark that the close should clear the cache timer. This way 3654 * the cache will be update with the server. We clear this flag in cache 3655 * entry so any lookups after this write will clear the flag. 3656 */ 3657 np->n_flag |= NATTRCHANGED; 3658 } 3659 3660 /* Tell the stream's parent that something has changed */ 3661 if (vnode_isnamedstream(vp)) 3662 parent_vp = smb_update_rsrc_and_getparent(vp, FALSE); 3663 3664 smb_share_rele(share, ap->a_context); 3665 smbnode_unlock(VTOSMB(vp)); 3666 /* We have the parent vnode, so reset its meta data cache timer. */ 3667 if (parent_vp) { 3668 VTOSMB(parent_vp)->attribute_cache_timer = 0; 3669 vnode_put(parent_vp); 3670 } 3671 3672 SMB_LOG_KTRACE(SMB_DBG_WRITE | DBG_FUNC_END, error, 0, 0, 0, 0); 3673 return (error); 3674} 3675 3676/* 3677 * This is an internal utility function called from our smbfs_mkdir and 3678 * smbfs_create to set the vnode_attr passed into those routines. The first 3679 * problem comes from the vfs layer. It wants to set things that the server will 3680 * set for us. So to stop taking a performance hit turn off those items that vfs 3681 * turn on. See vnode_authattr_new for what is getting set. Second there is a set 3682 * of items that we can't set anyways so clear them out and pretend we did it. 3683 * Third if they are setting ACLs then make sure we keep any inherited ACLs. 3684 * 3685 * Question should we ever error out in this routine? The old code never did, but 3686 * what if setting the mode, owner, group, or acl fails? 3687 * 3688 * The calling routine must hold a reference on the share 3689 * 3690 */ 3691static void 3692smbfs_set_create_vap(struct smb_share *share, struct vnode_attr *vap, vnode_t vp, 3693 vfs_context_t context, int set_mode_now) 3694{ 3695 struct smbnode *np = VTOSMB(vp); 3696 struct smbmount *smp = np->n_mount; 3697 struct vnode_attr svrva; 3698 kauth_acl_t savedacl = NULL; 3699 int error; 3700 int has_posix_modes = ((UNIX_CAPS(share) & UNIX_QFILEINFO_UNIX_INFO2_CAP)) ? TRUE : FALSE;; 3701 3702 if ((!has_posix_modes) && 3703 (SSTOVC(share)->vc_server_caps & kAAPL_SUPPORTS_NFS_ACE)) { 3704 /* 3705 * For OS X <-> OS X PFS (where ACLs are off by default), we 3706 * need a way to set Posix permissions. If the server supports 3707 * the NFS ACE, then it will allow us to get the ACL and send 3708 * it back with the desired Posix permissions in the NFS ACE. 3709 */ 3710 has_posix_modes = TRUE; 3711 } 3712 3713 /* 3714 * Initialize here so we know if it needs to be freed at the end. Also 3715 * ask for everything since its the same performance hit and updates our 3716 * nodes uid/gid cache. The following are not used unless the user is 3717 * setting ACLs. 3718 */ 3719 VATTR_INIT(&svrva); 3720 VATTR_WANTED(&svrva, va_acl); 3721 VATTR_WANTED(&svrva, va_uuuid); 3722 VATTR_WANTED(&svrva, va_guuid); 3723 3724 /* 3725 * This will be zero if vnode_authattr_new set it. Do not change 3726 * this on create, the default is fine. 3727 */ 3728 if (VATTR_IS_ACTIVE(vap, va_flags) && (vap->va_flags == 0)) { 3729 VATTR_SET_SUPPORTED(vap, va_flags); 3730 VATTR_CLEAR_ACTIVE(vap, va_flags); 3731 } 3732 /* The server will set all times for us */ 3733 if (VATTR_IS_ACTIVE(vap, va_create_time)) { 3734 VATTR_SET_SUPPORTED(vap, va_create_time); 3735 VATTR_CLEAR_ACTIVE(vap, va_create_time); 3736 } 3737 if (VATTR_IS_ACTIVE(vap, va_modify_time)) { 3738 VATTR_SET_SUPPORTED(vap, va_modify_time); 3739 VATTR_CLEAR_ACTIVE(vap, va_modify_time); 3740 } 3741 if (VATTR_IS_ACTIVE(vap, va_access_time)) { 3742 VATTR_CLEAR_ACTIVE(vap, va_access_time); 3743 VATTR_SET_SUPPORTED(vap, va_access_time); 3744 } 3745 if (VATTR_IS_ACTIVE(vap, va_change_time)) { 3746 VATTR_CLEAR_ACTIVE(vap, va_change_time); 3747 VATTR_SET_SUPPORTED(vap, va_change_time); 3748 } 3749 3750 if (VATTR_IS_ACTIVE(vap, va_mode)) { 3751 if (set_mode_now == TRUE) { 3752 /* compound_vnop_open already has the file open so we can set the 3753 Posix file modes if server supports Posix perms and reg file */ 3754 VATTR_SET_SUPPORTED(vap, va_mode); 3755 3756 if ( !vnode_isreg(vp) || !has_posix_modes ) { 3757 VATTR_CLEAR_ACTIVE(vap, va_mode); 3758 } 3759 } 3760 else { 3761 /* 3762 * This routine gets called from create. If this is a regular file they 3763 * could be setting the posix file modes to something that doesn't allow 3764 * them to open the file with the permissions they requested. 3765 * Example: open(path, O_WRONLY | O_CREAT | O_EXCL, 0400) 3766 * We only care about this if the server supports setting/getting posix 3767 * permissions. So if they are setting the owner with read/write access 3768 * then save the settings until after the open. We will just pretend to 3769 * set them here. The following radar will make this a mute point. 3770 * 3771 * <rdar://problem/5199099> Need a new VNOP_OPEN call that allows the 3772 * create/lookup/open/access in one call 3773 */ 3774 if (vnode_isreg(vp) && has_posix_modes && 3775 ((vap->va_mode & (S_IRUSR | S_IWUSR)) != (S_IRUSR | S_IWUSR))) { 3776 np->create_va_mode = vap->va_mode; 3777 np->set_create_va_mode = TRUE; 3778 /* The server should always give us read/write on create */ 3779 VATTR_SET_SUPPORTED(vap, va_mode); 3780 VATTR_CLEAR_ACTIVE(vap, va_mode); 3781 } else if (!has_posix_modes) { 3782 /* We can only set these if the server supports the unix extensions */ 3783 VATTR_SET_SUPPORTED(vap, va_mode); 3784 VATTR_CLEAR_ACTIVE(vap, va_mode); 3785 } 3786 } 3787 } 3788 3789 /* 3790 * We have never supported setting the uid, this is supported by the 3791 * UNIX extensions and for other servers we could convert it using 3792 * uid --> UUID --> SID translation. This just seems like a waste of 3793 * time since they would only be able to set it to themself if they 3794 * are already the owner. So just say we did, this is what we have 3795 * always done. 3796 */ 3797 if (VATTR_IS_ACTIVE(vap, va_uid)) { 3798 VATTR_SET_SUPPORTED(vap, va_uid); 3799 VATTR_CLEAR_ACTIVE(vap, va_uid); 3800 } 3801 3802 /* 3803 * We have never supported setting the gid, this is supported by the 3804 * UNIX extensions and for other servers we could convert it using 3805 * gid --> GUID --> SID translation. We may want to add the support 3806 * in the future, but we should require that they do this by setting 3807 * the va_guuid. 3808 */ 3809 if (VATTR_IS_ACTIVE(vap, va_gid)) { 3810 VATTR_SET_SUPPORTED(vap, va_gid); 3811 VATTR_CLEAR_ACTIVE(vap, va_gid); 3812 if (vap->va_gid != smp->sm_args.gid) 3813 SMB_LOG_ACCESS("They want to set the gid to %d from %d\n", 3814 vap->va_gid, smp->sm_args.gid); 3815 } 3816 3817 /* 3818 * If they have an ACE that allows them to take ownership then 3819 * this call will work. Should we test to see before going any 3820 * future. 3821 */ 3822 if (VATTR_IS_ACTIVE(vap, va_uuuid)) { 3823 VATTR_SET_SUPPORTED(vap, va_uuuid); 3824 /* We never let them set it if a TEMP UUID */ 3825 if (is_memberd_tempuuid(&vap->va_uuuid)) 3826 VATTR_CLEAR_ACTIVE(vap, va_uuuid); 3827 } 3828 3829 /* 3830 * If they have an ACE that allows them to make this change then 3831 * this call will work. Should we test to see before going any 3832 * future. 3833 */ 3834 if (VATTR_IS_ACTIVE(vap, va_guuid)) { 3835 VATTR_SET_SUPPORTED(vap, va_guuid); 3836 /* We never let them set it if a TEMP UUID */ 3837 if (is_memberd_tempuuid(&vap->va_guuid)) 3838 VATTR_CLEAR_ACTIVE(vap, va_guuid); 3839 } 3840 3841 /* 3842 * Make sure the VFS layer doesn't fall back to using EA, always say we set 3843 * the ACL. 3844 */ 3845 if (VATTR_IS_ACTIVE(vap, va_acl)) { 3846 VATTR_SET_SUPPORTED(vap, va_acl); 3847 /* Nothing for us to do here */ 3848 if ((vap->va_acl == NULL) || (vap->va_acl->acl_entrycount == 0)) 3849 VATTR_CLEAR_ACTIVE(vap, va_acl); 3850 } 3851 3852 /* All we have left to do is call our setattr */ 3853 if (!VATTR_IS_ACTIVE(vap, va_acl)) 3854 goto do_setattr; 3855 3856 /* Get the inherited ACLs from the server */ 3857 error = smbfs_getattr(share, vp, &svrva, context); 3858 if (error) { 3859 SMBWARNING("Error %d returned while gettting the inherit ACLs from the server\n", 3860 error); 3861 goto out; 3862 } 3863 3864 /* 3865 * if none created then just slam in the requested ACEs 3866 */ 3867 if (!VATTR_IS_SUPPORTED(&svrva, va_acl) || svrva.va_acl == NULL || 3868 svrva.va_acl->acl_entrycount == 0) { 3869 goto do_setattr; 3870 } 3871 error = smbfs_compose_create_acl(vap, &svrva, &savedacl); 3872 if (error) 3873 goto out; 3874 3875do_setattr: 3876 error = smbfs_setattr(share, vp, vap, context); 3877 if (error) 3878 SMBERROR("smbfs_setattr, error %d\n", error); 3879 if (savedacl) { 3880 kauth_acl_free(vap->va_acl); 3881 vap->va_acl = savedacl; 3882 } 3883out: 3884 if (VATTR_IS_SUPPORTED(&svrva, va_acl) && svrva.va_acl != NULL) 3885 kauth_acl_free(svrva.va_acl); 3886 return; 3887} 3888 3889/* 3890 * Create a regular file or a "symlink". In the symlink case we will have a target. Depending 3891 * on the sytle of symlink the target may be just what we set or we may need to encode it into 3892 * that wacky windows data 3893 * 3894 * The calling routine must hold a reference on the share 3895 * 3896 */ 3897static int 3898smbfs_create(struct smb_share *share, struct vnop_create_args *ap, char *target, 3899 size_t targetlen) 3900{ 3901 vnode_t dvp = ap->a_dvp; 3902 struct vnode_attr *vap = ap->a_vap; 3903 vnode_t *vpp = ap->a_vpp; 3904 struct componentname *cnp = ap->a_cnp; 3905 struct smbnode *dnp = VTOSMB(dvp); 3906 struct smbmount *smp = VTOSMBFS(dvp); 3907 vnode_t vp; 3908 struct smbfattr fattr; 3909 const char *name = cnp->cn_nameptr; 3910 size_t nmlen = cnp->cn_namelen; 3911 int error; 3912 struct timespec ts; 3913 int unix_symlink = ((UNIX_CAPS(share) & UNIX_SFILEINFO_UNIX_LINK_CAP)) ? TRUE : FALSE; 3914 3915 *vpp = NULL; 3916 if (vap->va_type != VREG && vap->va_type != VLNK) 3917 return (ENOTSUP); 3918 3919 SMB_LOG_KTRACE(SMB_DBG_SMBFS_CREATE | DBG_FUNC_START, 3920 vap->va_type, 0, 0, 0, 0); 3921 3922 if (vap->va_type == VLNK) { 3923 if (smp->sm_flags & MNT_SUPPORTS_REPARSE_SYMLINKS) { 3924 error = smbfs_smb_create_reparse_symlink(share, dnp, name, nmlen, target, 3925 targetlen, &fattr, ap->a_context); 3926 } else if (unix_symlink) { 3927 error = smbfs_smb_create_unix_symlink(share, dnp, name, nmlen, target, 3928 targetlen, &fattr, ap->a_context); 3929 } else { 3930 error = smbfs_smb_create_windows_symlink(share, dnp, name, nmlen, target, 3931 targetlen, &fattr, ap->a_context); 3932 } 3933 } else { 3934 /* Now create the file, sending a null fid pointer will cause it to be closed */ 3935 error = smbfs_smb_create(share, dnp, name, nmlen, SMB2_FILE_WRITE_DATA, 3936 NULL, FILE_CREATE, 0, &fattr, ap->a_context); 3937 } 3938 3939 SMB_LOG_KTRACE(SMB_DBG_SMBFS_CREATE | DBG_FUNC_NONE, 3940 0xabc001, error, 0, 0, 0); 3941 3942 if (error) { 3943 if (error == ENOENT) { 3944 SMBDEBUG("Creating %s returned ENOENT, resetting to EACCES\n", name); 3945 /* 3946 * Some servers (Samba) support an option called veto. This prevents 3947 * clients from creating or access these files. The server returns 3948 * an ENOENT error in these cases. The VFS layer will loop forever 3949 * if a ENOENT error is returned on create, so we convert this error 3950 * to EACCES. 3951 */ 3952 error = EACCES; 3953 } 3954 return (error); 3955 } 3956 smbfs_attr_touchdir(dnp, (share->ss_fstype == SMB_FS_FAT)); 3957 3958 /* 3959 * We have smbfs_nget returning a lock so we need to unlock it when we 3960 * are done with it. Would really like to clean this code up in the future. 3961 * The whole create, mkdir and smblink create code should use the same code path. 3962 */ 3963 fattr.fa_vtype = vap->va_type; 3964 error = smbfs_nget(share, vnode_mount(dvp), 3965 dvp, name, nmlen, 3966 &fattr, &vp, 3967 cnp->cn_flags, SMBFS_NGET_CREATE_VNODE, 3968 ap->a_context); 3969 if (error) { 3970 /* Error, try to cleanup anything we created on the server */ 3971 smbfs_smb_delete(share, dnp, VREG, 3972 name, nmlen, 3973 0, ap->a_context); 3974 goto bad; 3975 } 3976 3977 /* 3978 * We just created the file, so we have no finder info and the resource fork 3979 * should be empty. So set our cache timers to reflect this information 3980 */ 3981 nanouptime(&ts); 3982 VTOSMB(vp)->finfo_cache_timer = ts.tv_sec; 3983 VTOSMB(vp)->rfrk_cache_timer = ts.tv_sec; 3984 3985 smbfs_set_create_vap(share, vap, vp, ap->a_context, FALSE); 3986 3987 if (vap->va_type == VLNK) { 3988 smbfs_update_symlink_cache(VTOSMB(vp), target, targetlen); 3989 VTOSMB(vp)->n_size = targetlen; /* Set it to the correct size */ 3990 if (!unix_symlink) /* Mark it as a Windows symlink */ 3991 VTOSMB(vp)->n_flag |= NWINDOWSYMLNK; 3992 } 3993 *vpp = vp; 3994 smbnode_unlock(VTOSMB(vp)); /* Done with the smbnode unlock it. */ 3995 3996 dnp->d_changecnt++; 3997 3998 /* Remove any negative cache entries. */ 3999 if (dnp->n_flag & NNEGNCENTRIES) { 4000 dnp->n_flag &= ~NNEGNCENTRIES; 4001 cache_purge_negatives(dvp); 4002 } 4003 4004bad: 4005 /* if success, blow away statfs cache */ 4006 if (!error) 4007 smp->sm_statfstime = 0; 4008 4009 SMB_LOG_KTRACE(SMB_DBG_SMBFS_CREATE | DBG_FUNC_END, error, 0, 0, 0, 0); 4010 return (error); 4011} 4012 4013/* 4014 * smbfs_vnop_create 4015 * 4016 * vnode_t a_dvp; 4017 * vnode_t *a_vpp; 4018 * struct componentname *a_cnp; 4019 * struct vnode_attr *a_vap; 4020 * vfs_context_t a_context; 4021 */ 4022static int 4023smbfs_vnop_create(struct vnop_create_args *ap) 4024{ 4025 vnode_t dvp = ap->a_dvp; 4026 int error; 4027 struct smbnode *dnp; 4028 struct smb_share *share; 4029 4030 /* Make sure we lock the parent before calling smbfs_create */ 4031 if ((error = smbnode_lock(VTOSMB(dvp), SMBFS_EXCLUSIVE_LOCK))) 4032 return (error); 4033 4034 SMB_LOG_KTRACE(SMB_DBG_CREATE | DBG_FUNC_START, 0, 0, 0, 0, 0); 4035 4036 dnp = VTOSMB(dvp); 4037 dnp->n_lastvop = smbfs_vnop_create; 4038 share = smb_get_share_with_reference(VTOSMBFS(dvp)); 4039 4040 error = smbfs_create(share, ap, NULL, 0); 4041 4042 smb_share_rele(share, ap->a_context); 4043 smbnode_unlock(dnp); 4044 4045 SMB_LOG_KTRACE(SMB_DBG_CREATE | DBG_FUNC_END, error, 0, 0, 0, 0); 4046 return (error); 4047} 4048 4049/* 4050 * The calling routine must hold a reference on the share 4051 */ 4052static int 4053smbfs_remove(struct smb_share *share, vnode_t dvp, vnode_t vp, 4054 struct componentname *cnp, int flags, vfs_context_t context) 4055{ 4056#pragma unused(cnp) 4057 struct smbnode *dnp = VTOSMB(dvp); 4058 proc_t p = vfs_context_proc(context); 4059 struct smbnode *np = VTOSMB(vp); 4060 struct smbmount *smp = VTOSMBFS(vp); 4061 int error; 4062 uint64_t hashval = 0; 4063 4064 SMB_LOG_KTRACE(SMB_DBG_SMBFS_REMOVE | DBG_FUNC_START, 0, 0, 0, 0, 0); 4065 4066 DBG_ASSERT((!vnode_isnamedstream(vp))) 4067 cache_purge(vp); 4068 4069 /* 4070 * Carbon semantics prohibit deleting busy files. 4071 * (enforced when NODELETEBUSY is requested) We just return 4072 * EBUSY here. Do not print an error to system log in this 4073 * case. 4074 * 4075 * NOTE: Kqueue opens will not be found by vnode_isinuse 4076 */ 4077 if (flags & VNODE_REMOVE_NODELETEBUSY) { 4078 if (vnode_isinuse(vp, 0)) { 4079 error = EBUSY; /* Do not print an error in this case */ 4080 goto done; 4081 } else { 4082 /* Check if any streams associated with this vnode are opened */ 4083 vnode_t svpp = smbfs_find_vgetstrm(smp, np, SFM_RESOURCEFORK_NAME, 4084 share->ss_maxfilenamelen); 4085 if (svpp) { 4086 if (vnode_isinuse(svpp, 0)) { 4087 /* 4088 * This vnode has an opened stream associated with it, 4089 * we still need to return EBUSY here. 4090 * See <rdar://problem/9904683> 4091 */ 4092 smbnode_unlock(VTOSMB(svpp)); 4093 vnode_put(svpp); 4094 SMBDEBUG("%s: Cannot delete %s, resource fork in use\n", __FUNCTION__, vnode_getname(vp)); 4095 error = EBUSY; /* Do not print an error in this case */ 4096 goto done; 4097 } else { 4098 smbnode_unlock(VTOSMB(svpp)); 4099 vnode_put(svpp); 4100 } 4101 } 4102 } 4103 } 4104 4105 /* 4106 * Did we open this in our read routine. Then we should close it. 4107 */ 4108 if ((np->f_refcnt == 1) && np->f_needClose) { 4109 error = smbfs_close(share, vp, FREAD, context); 4110 if (error) { 4111 lck_rw_lock_shared(&np->n_name_rwlock); 4112 SMBWARNING("error %d closing %s\n", error, np->n_name); 4113 lck_rw_unlock_shared(&np->n_name_rwlock); 4114 } 4115 } 4116 4117 /* 4118 * The old code would check vnode_isinuse to see if the file was open, 4119 * but if the file was open by Kqueue then vnode_isinuse will not find it. 4120 * So at this point if the file is open then do the silly rename delete 4121 * trick if the server supports it. 4122 */ 4123 if (np->f_refcnt) { 4124 error = smbfs_delete_openfile(share, dnp, np, context); 4125 SMB_LOG_KTRACE(SMB_DBG_SMBFS_REMOVE | DBG_FUNC_NONE, 4126 0xabc001, error, 0, 0, 0); 4127 if (!error) { 4128 /* skip doing the vnode_recycle as file may still be on server */ 4129 error = 0; 4130 goto done; 4131 } 4132 4133 goto out; 4134 } 4135 4136 /* 4137 * NetApp and Samba servers will reuse the File ID immediately after a 4138 * delete, so remove the smb node from the hash table before doing the 4139 * delete. If the delete fails, then we know the File ID is still valid 4140 * and it should be ok to reinsert the smbnode. 4141 */ 4142 smb_vhashrem(np); 4143 4144 error = smbfs_smb_delete(share, np, VREG, 4145 NULL, 0, 4146 0, context); 4147 SMB_LOG_KTRACE(SMB_DBG_SMBFS_REMOVE | DBG_FUNC_NONE, 4148 0xabc002, error, 0, 0, 0); 4149 if (error) { 4150 /* 4151 * Delete failed, add smbnode back into hash table. 4152 * Then leave as there is nothing else we can do at this point 4153 */ 4154 lck_rw_lock_shared(&np->n_name_rwlock); 4155 hashval = smbfs_hash(share, np->n_ino, np->n_name, np->n_nmlen); 4156 lck_rw_unlock_shared(&np->n_name_rwlock); 4157 4158 smb_vhashadd(np, hashval); 4159 4160 goto out; 4161 } 4162 4163 smbfs_attr_touchdir(dnp, (share->ss_fstype == SMB_FS_FAT)); 4164 dnp->d_changecnt++; 4165 4166 /* Remove any negative cache entries. */ 4167 if (dnp->n_flag & NNEGNCENTRIES) { 4168 dnp->n_flag &= ~NNEGNCENTRIES; 4169 cache_purge_negatives(dvp); 4170 } 4171 4172out: 4173 if (error == EBUSY) { 4174 char errbuf[32]; 4175 4176 (void)proc_name(proc_pid(p), &errbuf[0], 32); 4177 4178 lck_rw_lock_shared(&np->n_name_rwlock); 4179 SMBWARNING("warning: pid %d(%.*s) unlink open file(%s)\n", proc_pid(p), 4180 32, &errbuf[0], np->n_name); 4181 lck_rw_unlock_shared(&np->n_name_rwlock); 4182 } 4183 4184 if (!error) { 4185 /* Not sure why we do this here. Leave it for now. */ 4186 (void) vnode_recycle(vp); 4187 /* if success, blow away statfs cache */ 4188 smp->sm_statfstime = 0; 4189 } 4190 4191done: 4192 SMB_LOG_KTRACE(SMB_DBG_SMBFS_REMOVE | DBG_FUNC_END, error, 0, 0, 0, 0); 4193 return (error); 4194} 4195 4196/* 4197 * smbfs_vnop_remove 4198 * 4199 * vnode_t a_dvp; 4200 * vnode_t a_vp; 4201 * struct componentname *a_cnp; 4202 * int a_flags; 4203 * vfs_context_t a_context; 4204 */ 4205static int 4206smbfs_vnop_remove(struct vnop_remove_args *ap) 4207{ 4208 vnode_t dvp = ap->a_dvp; 4209 vnode_t vp = ap->a_vp; 4210 int32_t error; 4211 struct smb_share *share; 4212 4213 if (dvp == vp) 4214 return (EINVAL); 4215 4216 /* Always put in the order of parent then child */ 4217 if ((error = smbnode_lockpair(VTOSMB(dvp), VTOSMB(vp), SMBFS_EXCLUSIVE_LOCK))) 4218 return (error); 4219 4220 SMB_LOG_KTRACE(SMB_DBG_REMOVE | DBG_FUNC_START, 0, 0, 0, 0, 0); 4221 4222 VTOSMB(dvp)->n_lastvop = smbfs_vnop_remove; 4223 VTOSMB(vp)->n_lastvop = smbfs_vnop_remove; 4224 share = smb_get_share_with_reference(VTOSMBFS(dvp)); 4225 error = smbfs_remove(share, dvp, vp, ap->a_cnp, ap->a_flags, ap->a_context); 4226 smb_share_rele(share, ap->a_context); 4227 smbnode_unlockpair(VTOSMB(dvp), VTOSMB(vp)); 4228 4229 SMB_LOG_KTRACE(SMB_DBG_REMOVE | DBG_FUNC_END, error, 0, 0, 0, 0); 4230 return (error); 4231} 4232 4233/* 4234 * smbfs remove directory call 4235 * 4236 * The calling routine must hold a reference on the share 4237 * 4238 */ 4239static int 4240smbfs_rmdir(struct smb_share *share, vnode_t dvp, vnode_t vp, 4241 struct componentname *cnp, vfs_context_t context) 4242{ 4243#pragma unused(cnp) 4244 struct smbmount *smp = VTOSMBFS(vp); 4245 struct smbnode *dnp = VTOSMB(dvp); 4246 struct smbnode *np = VTOSMB(vp); 4247 int error; 4248 SMBFID fid = 0; 4249 uint64_t hashval = 0; 4250 4251 /* XXX other OSX fs test fs nodes here, not vnodes. Why? */ 4252 if (dvp == vp) { 4253 error = EINVAL; 4254 goto bad; 4255 } 4256 4257 /* Close Query Dir Create FID if we need to */ 4258 if ((np->d_fctx != NULL) && (np->d_fctx->f_need_close == TRUE)) { 4259 error = smb2_smb_close_fid(np->d_fctx->f_share, 4260 np->d_fctx->f_create_fid, 4261 NULL, NULL, context); 4262 if (error) { 4263 SMBDEBUG("smb2_smb_close_fid failed %d\n", error); 4264 } 4265 np->d_fctx->f_need_close = FALSE; 4266 } 4267 4268 /* 4269 * We may still have a change notify on this node, close it so 4270 * the item will get deleted on the server. Mark it not to be 4271 * reopened first, then save off the fid, clear the node fid 4272 * now close the file descriptor. 4273 */ 4274 np->d_needReopen = FALSE; 4275 fid = np->d_fid; 4276 np->d_fid = 0; 4277 if (fid != 0) { 4278 (void)smbfs_tmpclose(share, np, fid, context); 4279 } 4280 4281 cache_purge(vp); 4282 4283 /* 4284 * NetApp and Samba servers will reuse the File ID immediately after a 4285 * delete, so remove the smb node from the hash table before doing the 4286 * delete. If the delete fails, then we know the File ID is still valid 4287 * and it should be ok to reinsert the smbnode. 4288 */ 4289 smb_vhashrem(np); 4290 4291 error = smbfs_smb_rmdir(share, np, context); 4292 if (error) { 4293 /* 4294 * Delete failed, add smbnode back into hash table. 4295 * Then leave as there is nothing else we can do at this point 4296 */ 4297 lck_rw_lock_shared(&np->n_name_rwlock); 4298 hashval = smbfs_hash(share, np->n_ino, np->n_name, np->n_nmlen); 4299 lck_rw_unlock_shared(&np->n_name_rwlock); 4300 4301 smb_vhashadd(np, hashval); 4302 goto bad; 4303 } 4304 4305 smbfs_attr_touchdir(dnp, (share->ss_fstype == SMB_FS_FAT)); 4306 dnp->d_changecnt++; 4307 4308 /* Remove any negative cache entries. */ 4309 if (dnp->n_flag & NNEGNCENTRIES) { 4310 dnp->n_flag &= ~NNEGNCENTRIES; 4311 cache_purge_negatives(dvp); 4312 } 4313 4314bad: 4315 /* if success, blow away statfs cache */ 4316 if (!error) { 4317 smp->sm_statfstime = 0; 4318 (void) vnode_recycle(vp); 4319 } 4320 return (error); 4321} 4322 4323/* 4324 * smbfs_vnop_rmdir 4325 * 4326 * vnode_t a_dvp; 4327 * vnode_t a_vp; 4328 * struct componentname *a_cnp; 4329 * vfs_context_t a_context; 4330 */ 4331static int smbfs_vnop_rmdir(struct vnop_rmdir_args *ap) 4332{ 4333 vnode_t dvp = ap->a_dvp; 4334 vnode_t vp = ap->a_vp; 4335 int32_t error; 4336 struct smb_share *share; 4337 4338 if (!vnode_isdir(vp)) 4339 return (ENOTDIR); 4340 4341 if (dvp == vp) 4342 return (EINVAL); 4343 4344 /* Always put in the order of parent then child */ 4345 if ((error = smbnode_lockpair(VTOSMB(dvp), VTOSMB(vp), SMBFS_EXCLUSIVE_LOCK))) 4346 return (error); 4347 4348 SMB_LOG_KTRACE(SMB_DBG_RM_DIR | DBG_FUNC_START, 0, 0, 0, 0, 0); 4349 4350 VTOSMB(dvp)->n_lastvop = smbfs_vnop_rmdir; 4351 VTOSMB(vp)->n_lastvop = smbfs_vnop_rmdir; 4352 share = smb_get_share_with_reference(VTOSMBFS(dvp)); 4353 error = smbfs_rmdir(share, dvp, vp, ap->a_cnp, ap->a_context); 4354 smb_share_rele(share, ap->a_context); 4355 smbnode_unlockpair(VTOSMB(dvp), VTOSMB(vp)); 4356 4357 SMB_LOG_KTRACE(SMB_DBG_RM_DIR | DBG_FUNC_END, error, 0, 0, 0, 0); 4358 return (error); 4359} 4360 4361/* 4362 * smbfs_vnop_rename 4363 * 4364 * vnode_t a_fdvp; 4365 * vnode_t a_fvp; 4366 * struct componentname *a_fcnp; 4367 * vnode_t a_tdvp; 4368 * vnode_t a_tvp; 4369 * struct componentname *a_tcnp; 4370 * vfs_context_t a_context; 4371 */ 4372static int 4373smbfs_vnop_rename(struct vnop_rename_args *ap) 4374{ 4375 vnode_t fvp = ap->a_fvp; 4376 vnode_t tvp = ap->a_tvp; 4377 vnode_t fdvp = ap->a_fdvp; 4378 vnode_t tdvp = ap->a_tdvp; 4379 struct smbmount *smp = VFSTOSMBFS(vnode_mount(fvp)); 4380 struct smb_share *share = NULL; 4381 struct componentname *tcnp = ap->a_tcnp; 4382 struct componentname *fcnp = ap->a_fcnp; 4383 proc_t p = vfs_context_proc(ap->a_context); 4384 int error = 0; 4385 struct smbnode *fnp = NULL; 4386 struct smbnode *tdnp = NULL; 4387 struct smbnode *fdnp = NULL; 4388 int vtype; 4389 struct smbnode * lock_order[4] = {NULL}; 4390 int lock_cnt = 0; 4391 int ii; 4392 4393 /* Check for cross-device rename */ 4394 if ((vnode_mount(fvp) != vnode_mount(tdvp)) || 4395 (tvp && (vnode_mount(fvp) != vnode_mount(tvp)))) 4396 return (EXDEV); 4397 4398 vtype = vnode_vtype(fvp); 4399 if ( (vtype != VDIR) && (vtype != VREG) && (vtype != VLNK) ) 4400 return (EINVAL); 4401 4402 SMB_LOG_KTRACE(SMB_DBG_RENAME | DBG_FUNC_START, 0, 0, 0, 0, 0); 4403 4404 /* 4405 * First lets deal with the parents. If they are the same only lock the from 4406 * vnode, otherwise see if one is the parent of the other. We always want 4407 * to lock in parent child order if we can. If they are not the parent of 4408 * each other then lock in address order. 4409 */ 4410 4411 if (fdvp != tdvp) { 4412 lck_rw_lock_shared(&VTOSMB(fdvp)->n_parent_rwlock); 4413 lck_rw_lock_shared(&VTOSMB(tdvp)->n_parent_rwlock); 4414 } 4415 4416 if (fdvp == tdvp) 4417 lock_order[lock_cnt++] = VTOSMB(fdvp); 4418 else if (VTOSMB(fdvp)->n_parent && (VTOSMB(fdvp)->n_parent == VTOSMB(tdvp))) { 4419 lock_order[lock_cnt++] = VTOSMB(tdvp); 4420 lock_order[lock_cnt++] = VTOSMB(fdvp); 4421 } else if (VTOSMB(tdvp)->n_parent && (VTOSMB(tdvp)->n_parent == VTOSMB(fdvp))) { 4422 lock_order[lock_cnt++] = VTOSMB(fdvp); 4423 lock_order[lock_cnt++] = VTOSMB(tdvp); 4424 } else if (VTOSMB(fdvp) < VTOSMB(tdvp)) { 4425 lock_order[lock_cnt++] = VTOSMB(fdvp); 4426 lock_order[lock_cnt++] = VTOSMB(tdvp); 4427 } else { 4428 lock_order[lock_cnt++] = VTOSMB(tdvp); 4429 lock_order[lock_cnt++] = VTOSMB(fdvp); 4430 } 4431 4432 /* 4433 * Now lets deal with the children. If any of the following is true then just 4434 * lock the from vnode: 4435 * 1. The to vnode doesn't exist 4436 * 2. The to vnode and from vnodes are the same 4437 * 3. The to vnode and the from parent vnodes are the same, I know 4438 * it's strange but can happen. 4439 * Otherwise, lock in address order 4440 */ 4441 if ((tvp == NULL) || (tvp == fvp) || (tvp == fdvp)) 4442 lock_order[lock_cnt++] = VTOSMB(fvp); 4443 else { 4444 if (VTOSMB(fvp) < VTOSMB(tvp)) { 4445 lock_order[lock_cnt++] = VTOSMB(fvp); 4446 lock_order[lock_cnt++] = VTOSMB(tvp); 4447 } else { 4448 lock_order[lock_cnt++] = VTOSMB(tvp); 4449 lock_order[lock_cnt++] = VTOSMB(fvp); 4450 } 4451 } 4452 /* Make sure there are no duplicates, this would be a design flaw */ 4453 DBG_LOCKLIST_ASSERT(lock_cnt, lock_order); 4454 4455 if (fdvp != tdvp) { 4456 lck_rw_unlock_shared(&VTOSMB(tdvp)->n_parent_rwlock); 4457 lck_rw_unlock_shared(&VTOSMB(fdvp)->n_parent_rwlock); 4458 } 4459 4460 for (ii = 0; ii < lock_cnt; ii++) { 4461 if (error) 4462 lock_order[ii] = NULL; 4463 else if ((error = smbnode_lock(lock_order[ii], SMBFS_EXCLUSIVE_LOCK))) 4464 lock_order[ii] = NULL; 4465 } 4466 if (error) 4467 goto out; 4468 4469 /* 4470 * Make sure that we do not proceed if we get lock after parent is 4471 * reclaimed after forced unmount. 4472 */ 4473 if (vfs_isforce(smp->sm_mp)) { 4474 error = ENXIO; 4475 goto out; 4476 } 4477 4478 fdnp = VTOSMB(fdvp); 4479 fnp = VTOSMB(fvp); 4480 tdnp = VTOSMB(tdvp); 4481 4482 fdnp->n_lastvop = smbfs_vnop_rename; 4483 fnp->n_lastvop = smbfs_vnop_rename; 4484 tdnp->n_lastvop = smbfs_vnop_rename; 4485 if (tvp != NULL) 4486 VTOSMB(tvp)->n_lastvop = smbfs_vnop_rename; 4487 4488 lck_rw_lock_shared(&fnp->n_parent_rwlock); 4489 if (fnp->n_parent != VTOSMB(fdvp)) { 4490 /* 4491 * We lost the race with another thread that just 4492 * changed the parent of fvp, so fdvp is stale and 4493 * we punt. See <rdar://problem/15313516> 4494 */ 4495 lck_rw_unlock_shared(&fnp->n_parent_rwlock); 4496 error = ENOENT; 4497 goto out; 4498 } 4499 lck_rw_unlock_shared(&fnp->n_parent_rwlock); 4500 4501 share = smb_get_share_with_reference(smp); 4502 /* 4503 * Check to see if the SMB_EFA_RDONLY/IMMUTABLE are set. If they are set 4504 * then do not allow the rename. See HFS and AFP code. 4505 */ 4506 if (node_isimmutable(share, fvp, NULL)) { 4507 lck_rw_lock_shared(&fnp->n_name_rwlock); 4508 SMBWARNING( "%s is a locked file : Permissions error on delete\n", 4509 fnp->n_name); 4510 lck_rw_unlock_shared(&fnp->n_name_rwlock); 4511 error = EPERM; 4512 goto out; 4513 } 4514 4515 /* 4516 * Since there are no hard links (from our client point of view) 4517 * fvp==tvp means the arguments are case-variants. (If they 4518 * were identical the rename syscall doesnt call us.) 4519 */ 4520 if (fvp == tvp) 4521 tvp = NULL; 4522 4523 /* 4524 * The problem we have here is some servers will not return the correct 4525 * case of the file name in the lookup. This can cause to have two vnodes 4526 * that point to the same item. Very bad but nothing we can do about that 4527 * in smb. So if the target exist, the parents are the same and the name is 4528 * the same except for case, then don't delete the target. 4529 */ 4530 if (SSTOVC(share)->vc_misc_flags & SMBV_HAS_FILEIDS) { 4531 /* Server supports File IDs */ 4532 if (tvp && (fdvp == tdvp) && (fnp->n_ino == VTOSMB(tvp)->n_ino)) { 4533 lck_rw_lock_shared(&fnp->n_name_rwlock); 4534 SMBWARNING("Not removing target, same file. %s \n", 4535 fnp->n_name); 4536 lck_rw_unlock_shared(&fnp->n_name_rwlock); 4537 4538 smb_vhashrem(VTOSMB(tvp)); /* Remove it from our hash so it can't be found */ 4539 (void) vnode_recycle(tvp); 4540 tvp = NULL; 4541 } 4542 } 4543 else { 4544 /* Server does not support File IDs */ 4545 lck_rw_lock_shared(&fnp->n_name_rwlock); 4546 4547 if (tvp) { 4548 lck_rw_lock_shared(&VTOSMB(tvp)->n_name_rwlock); 4549 } 4550 4551 if (tvp && (fdvp == tdvp) && (fnp->n_nmlen == VTOSMB(tvp)->n_nmlen) && 4552 (strncasecmp((char *)fnp->n_name, (char *)VTOSMB(tvp)->n_name, 4553 fnp->n_nmlen) == 0)) { 4554 SMBWARNING("Not removing target, same file. %s ==> %s\n", 4555 fnp->n_name, VTOSMB(tvp)->n_name); 4556 lck_rw_unlock_shared(&VTOSMB(tvp)->n_name_rwlock); 4557 4558 smb_vhashrem(VTOSMB(tvp)); /* Remove it from our hash so it can't be found */ 4559 (void) vnode_recycle(tvp); 4560 tvp = NULL; 4561 } 4562 4563 if (tvp) { 4564 /* tvp might have been unlocked and null'd out above */ 4565 lck_rw_unlock_shared(&VTOSMB(tvp)->n_name_rwlock); 4566 } 4567 4568 lck_rw_unlock_shared(&fnp->n_name_rwlock); 4569 } 4570 4571 /* 4572 * If we are not doing Named Streams, they gave us a target to delete, and 4573 * the source is a dot underscore file then make sure the source exist before 4574 * deleting the target. 4575 * 4576 * This problem happens when going Mac to Mac and the share is FAT or some 4577 * share that doesn't support streams. The remote VNOP_RENAME will rename 4578 * the dot underscore file underneath the client. So when the cleint tries 4579 * to rename the dot underscore it thinkis the target exist and needs to be 4580 * deleted. So never delete the target if the source doesn't exist. 4581 */ 4582 lck_rw_lock_shared(&fnp->n_name_rwlock); 4583 if ((tvp) && (!(share->ss_attributes & FILE_NAMED_STREAMS)) && 4584 (fnp->n_nmlen > 2) && (fnp->n_name[0] == '.') && (fnp->n_name[1] == '_')) { 4585 const char *name = (const char *)fnp->n_name; 4586 size_t nmlen = fnp->n_nmlen; 4587 struct smbfattr fattr; 4588 4589 error = smbfs_lookup(share, fdnp, &name, &nmlen, &fattr, ap->a_context); 4590 /* Should we check for any error or just ENOENT */ 4591 if (error == ENOENT) 4592 tvp = NULL; 4593 /* smbfs_lookup could have replace the name, free it if did */ 4594 if (name != (char *)fnp->n_name) { 4595 SMB_FREE(name, M_SMBNODENAME); 4596 } 4597 } 4598 lck_rw_unlock_shared(&fnp->n_name_rwlock); 4599 4600 /* 4601 * If the destination exists then it needs to be removed. 4602 */ 4603 if (tvp) { 4604 if (vnode_isdir(tvp)) { 4605 /* 4606 * From the man 2 rename 4607 * 4608 * CONFORMANCE 4609 * The restriction on renaming a directory whose permissions disallow 4610 * writing is based on the fact that UFS directories contain a ".." 4611 * entry. If renaming a directory would move it to another parent 4612 * directory, this entry needs to be changed. 4613 * 4614 * This restriction has been generalized to disallow renaming of any 4615 * write-disabled directory, even when this would not require a 4616 * change to the ".." entry. For consistency, HFS+ directories 4617 * emulate this behavior. 4618 * 4619 * So if you are renaming a dir to an existing dir, you must have 4620 * write access on the existing dir. Seems if the user is a super 4621 * user then we can delete the existing directory. 4622 * 4623 * XXX - We need to remove the smb_check_posix_access and just do a 4624 * vnop_access. 4625 */ 4626 if (share->ss_attributes & FILE_PERSISTENT_ACLS) 4627 error = smbfs_rmdir(share, tdvp, tvp, tcnp, ap->a_context); 4628 else if ((vfs_context_suser(ap->a_context) == 0) || 4629 (smb_check_posix_access(ap->a_context, VTOSMB(tvp), S_IWOTH))) 4630 error = smbfs_rmdir(share, tdvp, tvp, tcnp, ap->a_context); 4631 else 4632 error = EPERM; 4633 } else { 4634 error = smbfs_remove(share, tdvp, tvp, tcnp, 0, ap->a_context); 4635 } 4636 if (error) 4637 goto out; 4638 } 4639 4640 cache_purge(fvp); 4641 4642 /* Did we open this in our read routine. Then we should close it. */ 4643 if ((!vnode_isdir(fvp)) && (!vnode_isinuse(fvp, 0)) && 4644 (fnp->f_refcnt == 1) && fnp->f_needClose) { 4645 error = smbfs_close(share, fvp, FREAD, ap->a_context); 4646 if (error) { 4647 lck_rw_lock_shared(&fnp->n_name_rwlock); 4648 SMBWARNING("error %d closing %s\n", error, fnp->n_name); 4649 lck_rw_unlock_shared(&fnp->n_name_rwlock); 4650 } 4651 } 4652 4653 /* 4654 * Windows Servers will not let you move a item that contains open items. So 4655 * if we are moving an folder and the source folder has an open notification 4656 * then close the notification, before doing the move. 4657 */ 4658 if (vnode_isdir(fvp) && 4659 (fnp->d_fid != 0)) { 4660 (void)smbfs_tmpclose(share, fnp, fnp->d_fid, ap->a_context); 4661 /* Mark it to be reopen */ 4662 fnp->d_needReopen = TRUE; 4663 fnp->d_fid = 0; 4664 } 4665 4666 /* 4667 * Try to rename the file, this may fail if the file is open. Some 4668 * SAMBA systems allow us to rename an open file, so try this case 4669 * first. 4670 * 4671 * FYI: While working on Radar 4532498 I notice that you can move/rename 4672 * an open file if it is open for read-only. Only tested this on Windows 2003. 4673 */ 4674 error = smbfs_smb_rename(share, fnp, tdnp, tcnp->cn_nameptr, 4675 tcnp->cn_namelen, ap->a_context); 4676 /* 4677 * The file could be open so lets try again. This call does not work on 4678 * Windows 95/98/Me/NT4 systems. Since this call only allows you to 4679 * rename in place do not even try it if they are moving the item. 4680 */ 4681 if ( (fdvp == tdvp) && error && 4682 (VC_CAPS(SSTOVC(share)) & SMB_CAP_INFOLEVEL_PASSTHRU)) 4683 error = smbfs_smb_t2rename(share, fnp, tcnp->cn_nameptr, 4684 tcnp->cn_namelen, 1, NULL, ap->a_context); 4685 4686 /* 4687 * We should really print a better description of the error to the 4688 * system log. Thing we could print in the system log. 4689 * 1. This server does not support renaming of an open file. 4690 * 2. This server only supports renaming of an open file in place. 4691 * 3. Renaming open file failed. 4692 * 4693 * Written up as Radar 4381236 4694 */ 4695 if (!error) { 4696 char *new_name; 4697 uint64_t hashval; 4698 uint32_t orig_flag = fnp->n_flag; 4699 4700 /* 4701 * At this point we still have both parents and the children locked if 4702 * they exist. Since the parents are locked we know that a lookup of the 4703 * children cannot happen over the network. So we are safe to play with 4704 * both names and the hash node entries. The old code would just remove 4705 * the node from the hash table and then just change the nodes name, this 4706 * was very bad and could cause the following to happen: 4707 * 4708 * RENAME HAPPENS ON VP1: vp1->np1->n_name = file1 gets renamed to vp1->np1->n_name = file2 4709 * 1. vp1 is no longer in the name cache. 4710 * 2. np1 is no longer in the hash table. 4711 * 3. vp1 still has a ref taken on it and can still be used. 4712 * 4713 * LOOKUP HAPPNES ON file2: Which will cause a new vnode and smbnode to get created 4714 * 1. vp1 is not found because its not in the name cache. 4715 * 2. np1 is not found because its not in the hash table. 4716 * 3. vp2 and np2 get created and vp2->np2->n_name = file2 4717 * 4718 * RENAME HAPPENS ON VP2: vp2->np2->n_name = file2 gets renamed to vp2->np2->n_name = file3 4719 * 1. vp1 no longer has the correct name. 4720 * 2. vp2 is no longer in the name cache. 4721 * 3. np2 is no longer in the hash table. 4722 * 4. vp2 still has a ref taken on it and can still be used. 4723 * 4724 * SOME OTHER OPERATION HAPPENS ON VP1: It will fail because VP1 now has the wrong name. 4725 * 1. Now the whole thing can repeat, very bad! 4726 */ 4727 4728 if (!(SSTOVC(share)->vc_misc_flags & SMBV_HAS_FILEIDS)) { 4729 /* 4730 * Server does not support File IDs. 4731 * Remove it from the hash, it doesn't exist under that name 4732 * anymore 4733 */ 4734 smb_vhashrem(fnp); 4735 } 4736 4737 /* We always need the following code. */ 4738 if (tdvp && (fdvp != tdvp)) { 4739 lck_rw_lock_exclusive(&fnp->n_parent_rwlock); 4740 4741 /* Take a ref count on the new parent */ 4742 if (!vnode_isvroot(tdvp)) { 4743 if (vnode_get(tdvp) == 0) { 4744 if (vnode_ref(tdvp) == 0) { 4745 fnp->n_flag |= NREFPARENT; 4746 4747 /* Increment new parent node's child refcnt */ 4748 OSIncrementAtomic(&tdnp->n_child_refcnt); 4749 } 4750 else { 4751 fnp->n_flag &= ~NREFPARENT; 4752 } 4753 vnode_put(tdvp); 4754 } 4755 } 4756 else 4757 fnp->n_flag &= ~NREFPARENT; 4758 4759 /* Remove the ref count off the old parent */ 4760 if ((!vnode_isvroot(fdvp)) && (orig_flag & NREFPARENT)) { 4761 if (vnode_get(fdvp) == 0) { 4762 vnode_rele(fdvp); 4763 vnode_put(fdvp); 4764 4765 /* Remove the child refcnt from old parent */ 4766 OSDecrementAtomic(&fdnp->n_child_refcnt); 4767 } 4768 } 4769 4770 fnp->n_parent = VTOSMB(tdvp); 4771 4772 lck_rw_unlock_exclusive(&fnp->n_parent_rwlock); 4773 4774 VTOSMB(tdvp)->d_changecnt++; 4775 VTOSMB(fdvp)->d_changecnt++; 4776 } 4777 4778 /* 4779 * Now reset the name so path lookups will work and add the node back 4780 * into the hash table, so other lookups can this node. 4781 */ 4782 new_name = smb_strndup(tcnp->cn_nameptr, tcnp->cn_namelen); 4783 if (new_name) { 4784 char * old_name = NULL; 4785 4786 lck_rw_lock_exclusive(&fnp->n_name_rwlock); 4787 old_name = fnp->n_name; 4788 fnp->n_name = new_name; 4789 fnp->n_nmlen = tcnp->cn_namelen; 4790 4791 if (!(SSTOVC(share)->vc_misc_flags & SMBV_HAS_FILEIDS)) { 4792 /* Server does not support File IDs */ 4793 hashval = smbfs_hash(NULL, 0, fnp->n_name, fnp->n_nmlen); 4794 smb_vhashadd(fnp, hashval); 4795 } 4796 4797 lck_rw_unlock_exclusive(&fnp->n_name_rwlock); 4798 4799 /* Now its safe to free the old name */ 4800 SMB_FREE(old_name, M_SMBNODENAME); 4801 } 4802 4803 if (!(SSTOVC(share)->vc_misc_flags & SMBV_HAS_FILEIDS)) { 4804 /* 4805 * Servers does not support File IDs 4806 * <10854595> Update the n_ino with the new name and/or parent 4807 */ 4808 lck_rw_lock_shared(&fnp->n_parent_rwlock); 4809 lck_rw_lock_shared(&fnp->n_name_rwlock); 4810 4811 fnp->n_ino = smbfs_getino(fnp->n_parent, fnp->n_name, fnp->n_nmlen); 4812 4813 lck_rw_unlock_shared(&fnp->n_name_rwlock); 4814 lck_rw_unlock_shared(&fnp->n_parent_rwlock); 4815 } 4816 4817 /* Update time stamp of when we last did rename */ 4818 nanouptime(&fnp->n_rename_time); 4819 } 4820 4821 /* 4822 * Source Target 4823 * Dot Hidden Dot HIDE 4824 * Dot Unhidden Dot HIDE! (Puma recovery) 4825 * NoDot Hidden Dot HIDE (Win hid it) 4826 * NoDot Unhidden Dot HIDE 4827 * Dot Hidden NoDot UNHIDE 4828 * Dot Unhidden NoDot UNHIDE 4829 * NoDot Hidden NoDot HIDE! (Win hid it) 4830 * NoDot Unhidden NoDot UNHIDE 4831 */ 4832 if (!error) { 4833 int hiderr; 4834 Boolean hideItem = (tcnp->cn_nameptr[0] == '.'); 4835 Boolean unHideItem = ((tcnp->cn_nameptr[0] != '.') && 4836 (fcnp->cn_nameptr[0] == '.')); 4837 4838 if (hideItem || unHideItem) { 4839 hiderr = smbfs_set_hidden_bit(share, tdnp, (vtype == VDIR) ? VDIR : VREG, 4840 tcnp->cn_nameptr, tcnp->cn_namelen, 4841 hideItem, ap->a_context); 4842 if (hiderr) { 4843 SMBWARNING("Error %d %s %s\n", hiderr, (hideItem) ? "hiding" : 4844 "unhiding", tcnp->cn_nameptr); 4845 } 4846 } 4847 } 4848 4849 if (error == EBUSY) { 4850 char errbuf[32]; 4851 4852 proc_name(proc_pid(p), &errbuf[0], 32); 4853 4854 lck_rw_lock_shared(&fnp->n_name_rwlock); 4855 SMBERROR("warning: pid %d(%.*s) rename open file(%s)\n", proc_pid(p), 4856 32, &errbuf[0], fnp->n_name); 4857 lck_rw_unlock_shared(&fnp->n_name_rwlock); 4858 } 4859 4860 smbfs_attr_touchdir(fdnp, (share->ss_fstype == SMB_FS_FAT)); 4861 if (tdvp != fdvp) 4862 smbfs_attr_touchdir(tdnp, (share->ss_fstype == SMB_FS_FAT)); 4863 /* if success, blow away statfs cache */ 4864 if (!error) { 4865 smp->sm_statfstime = 0; 4866 4867 /* Invalidate negative cache entries in destination dir */ 4868 if (tdnp->n_flag & NNEGNCENTRIES) { 4869 tdnp->n_flag &= ~NNEGNCENTRIES; 4870 cache_purge_negatives(tdvp); 4871 } 4872 } 4873 4874out: 4875 /* We only have a share if we obtain a reference on it, so release it */ 4876 if (share) { 4877 smb_share_rele(share, ap->a_context); 4878 } 4879 if (error == EBUSY) { 4880 char errbuf[32]; 4881 4882 proc_name(proc_pid(p), &errbuf[0], 32); 4883 4884 lck_rw_lock_shared(&fnp->n_name_rwlock); 4885 SMBWARNING("warning: pid %d(%.*s) rename open file(%s)\n", proc_pid(p), 32, &errbuf[0], fnp->n_name); 4886 lck_rw_unlock_shared(&fnp->n_name_rwlock); 4887 } 4888 for (ii = 0; ii < lock_cnt; ii++) 4889 if (lock_order[ii]) 4890 smbnode_unlock(lock_order[ii]); 4891 4892 SMB_LOG_KTRACE(SMB_DBG_RENAME | DBG_FUNC_END, error, 0, 0, 0, 0); 4893 return (error); 4894} 4895 4896/* 4897 * smbfs_vnop_link 4898 * 4899 * vnode_t a_vp; 4900 * vnode_t a_tdvp; 4901 * struct componentname *a_cnp; 4902 * vfs_context_t a_context; 4903 * 4904 * someday this will come true... 4905 */ 4906static int 4907smbfs_vnop_link(struct vnop_link_args *ap) 4908{ 4909 proc_t p = vfs_context_proc(ap->a_context); 4910 struct smbnode *np = VTOSMB(ap->a_vp); 4911 char errbuf[32]; 4912 4913 SMB_LOG_KTRACE(SMB_DBG_LINK | DBG_FUNC_START, 0, 0, 0, 0, 0); 4914 4915 proc_name(proc_pid(p), &errbuf[0], 32); 4916 4917 lck_rw_lock_shared(&np->n_name_rwlock); 4918 SMBERROR("warning: pid %d(%.*s) hardlink(%s)\n", proc_pid(p), 32, &errbuf[0], np->n_name); 4919 lck_rw_unlock_shared(&np->n_name_rwlock); 4920 4921 SMB_LOG_KTRACE(SMB_DBG_LINK | DBG_FUNC_END, 0, 0, 0, 0, 0); 4922 return (err_link(ap)); 4923} 4924 4925/* 4926 * smbfs_vnop_symlink link create call. 4927 * 4928 * vnode_t a_dvp; 4929 * vnode_t *a_vpp; 4930 * struct componentname *a_cnp; 4931 * struct vnode_attr *a_vap; 4932 * char *a_target; 4933 * vfs_context_t a_context; 4934 */ 4935static int smbfs_vnop_symlink(struct vnop_symlink_args *ap) 4936{ 4937 int error; 4938 struct vnop_create_args a; 4939 vnode_t dvp = ap->a_dvp; 4940 struct smbnode *dnp; 4941 struct smb_share *share; 4942 4943 /* Make sure we lock the parent before calling smbfs_create */ 4944 if ((error = smbnode_lock(VTOSMB(dvp), SMBFS_EXCLUSIVE_LOCK))) 4945 return error; 4946 4947 SMB_LOG_KTRACE(SMB_DBG_SYM_LINK | DBG_FUNC_START, 0, 0, 0, 0, 0); 4948 4949 dnp = VTOSMB(dvp); 4950 dnp->n_lastvop = smbfs_vnop_symlink; 4951 a.a_dvp = dvp; 4952 a.a_vpp = ap->a_vpp; 4953 a.a_cnp = ap->a_cnp; 4954 a.a_vap = ap->a_vap; 4955 a.a_context = ap->a_context; 4956 /* 4957 * We use PATH_MAX because we have no way currently to find out what is the 4958 * max path on the server. 4959 */ 4960 share = smb_get_share_with_reference(VTOSMBFS(dvp)); 4961 4962 error = smbfs_create(share, &a, ap->a_target, strnlen(ap->a_target, PATH_MAX+1)); 4963 4964 smb_share_rele(share, ap->a_context); 4965 smbnode_unlock(dnp); 4966 4967 SMB_LOG_KTRACE(SMB_DBG_SYM_LINK | DBG_FUNC_END, error, 0, 0, 0, 0); 4968 return (error); 4969} 4970 4971/* 4972 * smbfs_vnop_readlink read symlink call. 4973 * 4974 * vnode_t *a_vpp; 4975 * struct componentname *a_cnp; 4976 * uio_t a_uio; 4977 * vfs_context_t a_context; 4978 */ 4979static int 4980smbfs_vnop_readlink(struct vnop_readlink_args *ap) 4981{ 4982 vnode_t vp = ap->a_vp; 4983 struct smbnode *np = NULL; 4984 int error; 4985 struct smb_share *share; 4986 time_t attrtimeo; 4987 struct timespec ts; 4988 int use_cached_data = 0; 4989 4990 if (vnode_vtype(vp) != VLNK) 4991 return (EINVAL); 4992 4993 if ((error = smbnode_lock(VTOSMB(vp), SMBFS_EXCLUSIVE_LOCK))) 4994 return (error); 4995 4996 SMB_LOG_KTRACE(SMB_DBG_READ_LINK | DBG_FUNC_START, 0, 0, 0, 0, 0); 4997 4998 np = VTOSMB(vp); 4999 np->n_lastvop = smbfs_vnop_readlink; 5000 share = smb_get_share_with_reference(VTOSMBFS(vp)); 5001 5002 /* If we are in reconnect, use cached data if we have it */ 5003 if (np->n_symlink_cache_timer != 0) { 5004 use_cached_data = (share->ss_flags & SMBS_RECONNECTING); 5005 } 5006 5007 /* Check to see if the cache has timed out */ 5008 SMB_CACHE_TIME(ts, np, attrtimeo); 5009 5010 if ((np->n_symlink_target) && 5011 (use_cached_data || ((ts.tv_sec - np->n_symlink_cache_timer) <= attrtimeo))) { 5012 /* Cached data is still valid */ 5013 error = uiomove(np->n_symlink_target, (int)np->n_symlink_target_len, ap->a_uio); 5014 } else if ((np->n_dosattr & SMB_EFA_REPARSE_POINT) && 5015 (np->n_reparse_tag == IO_REPARSE_TAG_SYMLINK)) { 5016 error = smbfs_smb_reparse_read_symlink(share, np, ap->a_uio, ap->a_context); 5017 } else if (np->n_flag & NWINDOWSYMLNK) { 5018 error = smbfs_smb_windows_read_symlink(share, np, ap->a_uio, ap->a_context); 5019 } else { 5020 error = smbfs_smb_unix_read_symlink(share, np, ap->a_uio, ap->a_context); 5021 } 5022 5023 if ((error == ETIMEDOUT) && (np->n_symlink_cache_timer != 0)) { 5024 /* Just return the cached data */ 5025 error = uiomove(np->n_symlink_target, (int)np->n_symlink_target_len, ap->a_uio); 5026 } 5027 5028 smb_share_rele(share, ap->a_context); 5029 smbnode_unlock(np); 5030 5031 SMB_LOG_KTRACE(SMB_DBG_READ_LINK | DBG_FUNC_END, error, 0, 0, 0, 0); 5032 return (error); 5033} 5034 5035/* 5036 * smbfs_vnop_mknod 5037 * 5038 * vnode_t a_dvp; 5039 * vnode_t *a_vpp; 5040 * struct componentname *a_cnp; 5041 * struct vnode_attr *a_vap; 5042 * vfs_context_t a_context; 5043 */ 5044static int 5045smbfs_vnop_mknod(struct vnop_mknod_args *ap) 5046{ 5047 proc_t p = vfs_context_proc(ap->a_context); 5048 char errbuf[32]; 5049 5050 SMB_LOG_KTRACE(SMB_DBG_MKNODE | DBG_FUNC_START, 0, 0, 0, 0, 0); 5051 5052 proc_name(proc_pid(p), &errbuf[0], 32); 5053 SMBERROR("warning: pid %d(%.*s) mknod(%s)\n", proc_pid(p), 32, &errbuf[0], 5054 ap->a_cnp->cn_nameptr); 5055 5056 SMB_LOG_KTRACE(SMB_DBG_MKNODE | DBG_FUNC_END, 0, 0, 0, 0, 0); 5057 return (err_mknod(ap)); 5058} 5059 5060/* 5061 * smbfs_vnop_mkdir 5062 * 5063 * vnode_t a_dvp; 5064 * vnode_t *a_vpp; 5065 * struct componentname *a_cnp; 5066 * struct vnode_attr *a_vap; 5067 * vfs_context_t a_context; 5068 */ 5069static int 5070smbfs_vnop_mkdir(struct vnop_mkdir_args *ap) 5071{ 5072 vnode_t dvp = ap->a_dvp; 5073 struct vnode_attr *vap = ap->a_vap; 5074 vnode_t vp; 5075 struct componentname *cnp = ap->a_cnp; 5076 struct smbnode *dnp = NULL; 5077 struct smbmount *smp = NULL; 5078 struct smbfattr fattr; 5079 const char *name = cnp->cn_nameptr; 5080 size_t len = cnp->cn_namelen; 5081 int error; 5082 struct smb_share *share; 5083 struct timespec ts; 5084 5085 if (name[0] == '.' && (len == 1 || (len == 2 && name[1] == '.'))) 5086 return (EEXIST); 5087 5088 if ((error = smbnode_lock(VTOSMB(dvp), SMBFS_EXCLUSIVE_LOCK))) 5089 return (error); 5090 5091 SMB_LOG_KTRACE(SMB_DBG_MKDIR | DBG_FUNC_START, 0, 0, 0, 0, 0); 5092 5093 dnp = VTOSMB(dvp); 5094 dnp->n_lastvop = smbfs_vnop_mkdir; 5095 smp = dnp->n_mount; 5096 share = smb_get_share_with_reference(smp); 5097 error = smbfs_smb_mkdir(share, dnp, name, len, &fattr, ap->a_context); 5098 if (error) 5099 goto exit; 5100 5101 smbfs_attr_touchdir(dnp, (share->ss_fstype == SMB_FS_FAT)); 5102 dnp->d_changecnt++; 5103 5104 /* 5105 * %%% 5106 * Would really like to clean this code up in the future. The whole create, 5107 * mkdir and smblink create code should use the same code path. 5108 */ 5109 error = smbfs_nget(share, vnode_mount(dvp), 5110 dvp, name, len, 5111 &fattr, &vp, 5112 cnp->cn_flags, SMBFS_NGET_CREATE_VNODE, 5113 ap->a_context); 5114 if (error) 5115 goto bad; 5116 5117 /* 5118 * We just create the directory, so we have no finder info. So set our cache 5119 * timer to reflect this information 5120 */ 5121 nanouptime(&ts); 5122 VTOSMB(vp)->finfo_cache_timer = ts.tv_sec; 5123 smbfs_set_create_vap(share, vap, vp, ap->a_context, FALSE); 5124 *ap->a_vpp = vp; 5125 smbnode_unlock(VTOSMB(vp)); /* Done with the smbnode unlock it. */ 5126 error = 0; 5127 if (dnp->n_flag & NNEGNCENTRIES) { 5128 dnp->n_flag &= ~NNEGNCENTRIES; 5129 cache_purge_negatives(dvp); 5130 } 5131 5132bad: 5133 if (name != cnp->cn_nameptr) { 5134 SMB_FREE(name, M_SMBNODENAME); 5135 } 5136 /* if success, blow away statfs cache */ 5137 smp->sm_statfstime = 0; 5138exit: 5139 smb_share_rele(share, ap->a_context); 5140 smbnode_unlock(dnp); 5141 5142 SMB_LOG_KTRACE(SMB_DBG_MKDIR | DBG_FUNC_END, error, 0, 0, 0, 0); 5143 return (error); 5144} 5145 5146/* 5147 * smbfs_vnop_readdir 5148 * 5149 * vnode_t a_vp; 5150 * struct uio *a_uio; 5151 * int a_flags; 5152 * int *a_eofflag; 5153 * int *a_numdirent; 5154 * vfs_context_t a_context; 5155 */ 5156static int 5157smbfs_vnop_readdir(struct vnop_readdir_args *ap) 5158{ 5159 vnode_t vp = ap->a_vp; 5160 uio_t uio = ap->a_uio; 5161 int error; 5162 int32_t numdirent = 0; 5163 5164 if (uio_offset(uio) < 0) 5165 return (EINVAL); 5166 5167 if (!vnode_isdir(vp)) 5168 return (EPERM); 5169 5170 if (ap->a_eofflag) 5171 *ap->a_eofflag = 0; 5172 5173 if (uio_resid(uio) == 0) 5174 return (0); 5175 5176 if ((error = smbnode_lock(VTOSMB(vp), SMBFS_EXCLUSIVE_LOCK))) 5177 return (error); 5178 5179 SMB_LOG_KTRACE(SMB_DBG_READ_DIR | DBG_FUNC_START, VTOSMB(vp)->d_fid, 0, 0, 0, 0); 5180 5181 VTOSMB(vp)->n_lastvop = smbfs_vnop_readdir; 5182 5183 error = smbfs_readvdir(vp, uio, ap->a_context, ap->a_flags, &numdirent); 5184 if (error == ENOENT) { 5185 /* We have reached the end of the search */ 5186 if (ap->a_eofflag) 5187 *ap->a_eofflag = 1; 5188 error = 0; 5189 } 5190 5191 /* Return the number of entries from this lookup */ 5192 if (ap->a_numdirent) 5193 *ap->a_numdirent = numdirent; 5194 5195 smbnode_unlock(VTOSMB(vp)); 5196 5197 SMB_LOG_KTRACE(SMB_DBG_READ_DIR | DBG_FUNC_END, error, numdirent, 0, 0, 0); 5198 return (error); 5199} 5200 5201int32_t 5202smbfs_fsync(struct smb_share *share, vnode_t vp, int waitfor, int ubc_flags, 5203 vfs_context_t context) 5204{ 5205#pragma unused(waitfor, ubc_flags) 5206 int error; 5207 off_t size; 5208 5209 if (!vnode_isreg(vp)) { 5210 return 0; /* Nothing to do here */ 5211 } 5212 5213 SMB_LOG_KTRACE(SMB_DBG_SMBFS_FSYNC | DBG_FUNC_START, 0, 0, 0, 0, 0); 5214 5215 size = smb_ubc_getsize(vp); 5216 if ((size > 0) && smbfsIsCacheable(vp)) { 5217 if (VTOSMB(vp)->n_flag & NISMAPPED) { 5218 /* More expensive, but handles mmapped files */ 5219 ubc_msync (vp, 0, ubc_getsize(vp), NULL, UBC_PUSHDIRTY | UBC_SYNC); 5220 } else { 5221 /* Less expensive, but does not handle mmapped files */ 5222 cluster_push(vp, IO_SYNC); 5223 } 5224 } 5225 error = smbfs_smb_fsync(share, VTOSMB(vp), context); 5226 if (!error) 5227 VTOSMBFS(vp)->sm_statfstime = 0; 5228 5229 SMB_LOG_KTRACE(SMB_DBG_SMBFS_FSYNC | DBG_FUNC_END, error, 0, 0, 0, 0); 5230 return (error); 5231} 5232 5233/* smbfs_vnop_fsync 5234 * 5235 * vnode_t a_vp; 5236 * int32_t a_waitfor; 5237 * vfs_context_t a_context; 5238 */ 5239static int32_t 5240smbfs_vnop_fsync(struct vnop_fsync_args *ap) 5241{ 5242 int32_t error; 5243 struct smb_share *share; 5244 5245 /* If this is a read-only mount, there is nothing to do here */ 5246 if (vfs_isrdonly(vnode_mount(ap->a_vp))) { 5247 return (0); 5248 } 5249 5250 error = smbnode_lock(VTOSMB(ap->a_vp), SMBFS_EXCLUSIVE_LOCK); 5251 if (error) 5252 return (0); 5253 5254 SMB_LOG_KTRACE(SMB_DBG_FSYNC | DBG_FUNC_START, 0, 0, 0, 0, 0); 5255 5256 VTOSMB(ap->a_vp)->n_lastvop = smbfs_vnop_fsync; 5257 share = smb_get_share_with_reference(VTOSMBFS(ap->a_vp)); 5258 error = smbfs_fsync(share, ap->a_vp, ap->a_waitfor, 0, ap->a_context); 5259 smb_share_rele(share, ap->a_context); 5260 smbnode_unlock(VTOSMB(ap->a_vp)); 5261 5262 SMB_LOG_KTRACE(SMB_DBG_FSYNC | DBG_FUNC_END, error, 0, 0, 0, 0); 5263 return (error); 5264} 5265 5266/* 5267 * smbfs_vnop_pathconf 5268 * 5269 * vnode_t a_vp; 5270 * int a_name; 5271 * int32_t *a_retval; 5272 * vfs_context_t a_context; 5273 */ 5274static int smbfs_vnop_pathconf(struct vnop_pathconf_args *ap) 5275{ 5276 struct smb_share *share; 5277 int32_t *retval = ap->a_retval; 5278 int error = 0; 5279 5280 SMB_LOG_KTRACE(SMB_DBG_PATHCONF | DBG_FUNC_START, ap->a_name, 0, 0, 0, 0); 5281 5282 share = smb_get_share_with_reference(VTOSMBFS(ap->a_vp)); 5283 switch (ap->a_name) { 5284 case _PC_LINK_MAX: /* Hard Link Support */ 5285 *retval = 0; /* May support in the future. Depends on the server */ 5286 break; 5287 case _PC_NAME_MAX: 5288 *retval = share->ss_maxfilenamelen; 5289 break; 5290 case _PC_PATH_MAX: 5291 /* 5292 * XXX 5293 * Most Windows system have a 255 limit, but you can configure 5294 * them to support 1024. It would be nice if we could figure out 5295 * the real value for this field. 5296 */ 5297 *retval = PATH_MAX; 5298 break; 5299 case _PC_CHOWN_RESTRICTED: 5300 *retval = 1; 5301 break; 5302 case _PC_NO_TRUNC: 5303 *retval = 0; 5304 break; 5305 case _PC_NAME_CHARS_MAX: 5306 *retval = share->ss_maxfilenamelen; 5307 break; 5308 case _PC_CASE_SENSITIVE: 5309 *retval = 0; 5310 5311 if (SSTOVC(share)->vc_misc_flags & SMBV_OSX_SERVER) { 5312 /* Its OS X Server so we know for sure */ 5313 if (SSTOVC(share)->vc_volume_caps & kAAPL_CASE_SENSITIVE) { 5314 SMBDEBUG("Volume is case sensitive\n"); 5315 *retval = 1; 5316 } 5317 } 5318 else { 5319 /* 5320 * Thought about using FILE_CASE_SENSITIVE_SEARCH, but this 5321 * really just means they will search by case. It does not mean 5322 * this is a case sensitive file system. Currently we have no 5323 * way of determining if this is a case sensitive or 5324 * insensitive file system. We need to return a consistent 5325 * answer between pathconf and vfs_getattr. We do not know the real 5326 * answer for case sensitive, but lets default to what 90% of the 5327 * servers have set. Also remember this fixes Radar 4057391 and 3530751. 5328 */ 5329 *retval = 0; 5330 } 5331 break; 5332 case _PC_CASE_PRESERVING: 5333 if (share->ss_attributes & FILE_CASE_PRESERVED_NAMES) 5334 *retval = 1; 5335 else *retval = 0; 5336 break; 5337 /* 5338 * Handle by vn_pathconf. 5339 * 5340 * case _PC_EXTENDED_SECURITY_NP: 5341 * *retval = vfs_extendedsecurity(vnode_mount(vp)) ? 1 : 0; 5342 * break; 5343 * case _PC_AUTH_OPAQUE_NP: 5344 * *retval = vfs_authopaque(vnode_mount(vp)); 5345 * break; 5346 * case _PC_2_SYMLINKS: 5347 * *retval = 1; 5348 * break; 5349 * case _PC_ALLOC_SIZE_MIN: 5350 * *retval = 1; // XXX lie: 1 byte 5351 * break; 5352 * case _PC_ASYNC_IO: // unistd.h: _POSIX_ASYNCHRONUS_IO 5353 * *retval = 1; // [AIO] option is supported 5354 * break; 5355 */ 5356 case _PC_FILESIZEBITS: 5357 if (VC_CAPS(SSTOVC(share)) & SMB_CAP_LARGE_FILES) 5358 *retval = 64; /* The server supports 64 bit offsets */ 5359 else *retval = 32; /* The server supports 32 bit offsets */ 5360 break; 5361 case _PC_XATTR_SIZE_BITS: 5362 if (!(share->ss_attributes & FILE_NAMED_STREAMS)) { 5363 /* Doesn't support named streams VFS handles this cases */ 5364 error = EINVAL; 5365 } else if (VC_CAPS(SSTOVC(share)) & SMB_CAP_LARGE_FILES) { 5366 *retval = 64; /* The server supports 64 bit offsets */ 5367 } else { 5368 *retval = 32; /* The server supports 32 bit offsets */ 5369 } 5370 break; 5371 /* 5372 * Handle by vn_pathconf. 5373 * 5374 * case _PC_PRIO_IO: // unistd.h: _POSIX_PRIORITIZED_IO 5375 * *retval = 0; // [PIO] option is not supported 5376 * break; 5377 * case _PC_REC_INCR_XFER_SIZE: 5378 * *retval = 4096; // XXX go from MIN to MAX 4K at a time 5379 * break; 5380 * case _PC_REC_MIN_XFER_SIZE: 5381 * *retval = 4096; // XXX recommend 4K minimum reads/writes 5382 * break; 5383 * case _PC_REC_MAX_XFER_SIZE: // Should we use SMB_IOMAX 5384 * *retval = 65536; // XXX recommend 64K maximum reads/writes 5385 * break; 5386 * case _PC_REC_XFER_ALIGN: 5387 * *retval = 4096; // XXX recommend page aligned buffers 5388 * break; 5389 * case _PC_SYMLINK_MAX: 5390 * *retval = 255; // Minimum acceptable POSIX value 5391 * break; 5392 * case _PC_SYNC_IO: // unistd.h: _POSIX_SYNCHRONIZED_IO 5393 * *retval = 0; // [SIO] option is not supported 5394 * break; 5395 */ 5396 default: 5397 error = EINVAL; 5398 } 5399 smb_share_rele(share, ap->a_context); 5400 5401 SMB_LOG_KTRACE(SMB_DBG_PATHCONF | DBG_FUNC_END, error, 0, 0, 0, 0); 5402 return (error); 5403} 5404 5405/* 5406 * smbfs_vnop_ioctl - smbfs vnodeop entry point 5407 * vnode_t a_vp; 5408 * int32_t a_command; 5409 * caddr_t a_data; 5410 * int32_t a_fflag; 5411 * vfs_context_t context; 5412 */ 5413static int32_t smbfs_vnop_ioctl(struct vnop_ioctl_args *ap) 5414{ 5415 vnode_t vp = ap->a_vp; 5416 struct smbnode *np; 5417 int32_t error = 0; 5418 proc_t p = vfs_context_proc(ap->a_context); 5419 struct smb_share *share; 5420 struct smbmount *smp; 5421 5422 error = smbnode_lock(VTOSMB(ap->a_vp), SMBFS_EXCLUSIVE_LOCK); 5423 if (error) 5424 return (error); 5425 5426 SMB_LOG_KTRACE(SMB_DBG_IOCTL | DBG_FUNC_START, ap->a_command, 0, 0, 0, 0); 5427 5428 np = VTOSMB(vp); 5429 np->n_lastvop = smbfs_vnop_ioctl; 5430 smp = VTOSMBFS(vp); 5431 share = smb_get_share_with_reference(VTOSMBFS(vp)); 5432 5433 /* 5434 * %%% 5435 * Remove the IOCBASECMD case lines (OLD) when fsctl code in vfs_syscalls.c 5436 * gets fixed to not use IOCBASECMD before calling VOP_IOCTL. 5437 * 5438 * The smbfsByteRangeLock2FSCTL call was made to support classic. We do 5439 * not support classic, but the file manager will only make the 5440 * smbfsByteRangeLock2FSCTL call. So for now support all the commands, but 5441 * treat them all the same. 5442 */ 5443 switch (ap->a_command) { 5444 case smbfsGetVCSockaddrFSCTL: 5445 case smbfsGetVCSockaddrFSCTL_BASECMD: { 5446 5447 if (SSTOVC(share)->vc_saddr) { 5448 memcpy(ap->a_data, SSTOVC(share)->vc_saddr, 5449 SSTOVC(share)->vc_saddr->sa_len); 5450 } else { 5451 error = EINVAL; /* Better never happen, but just in case */ 5452 } 5453 break; 5454 } 5455 case smbfsUniqueShareIDFSCTL: 5456 case smbfsUniqueShareIDFSCTL_BASECMD: { 5457 struct UniqueSMBShareID *uniqueptr = (struct UniqueSMBShareID *)ap->a_data; 5458 5459 uniqueptr->error = 0; 5460 if ((uniqueptr->flags & SMBFS_GET_ACCESS_INFO) || 5461 ((uniqueptr->unique_id_len == smp->sm_args.unique_id_len) && 5462 (bcmp(smp->sm_args.unique_id, uniqueptr->unique_id, 5463 uniqueptr->unique_id_len) == 0))) { 5464 5465 /* In the future we should return the lsa name if we have one */ 5466 uniqueptr->user[0] = 0; /* Just in case we have no user name */ 5467 if (SSTOVC(share)->vc_flags & SMBV_GUEST_ACCESS) { 5468 uniqueptr->connection_type = kConnectedByGuest; 5469 strlcpy(uniqueptr->user, kGuestAccountName, SMB_MAXUSERNAMELEN + 1); 5470 } 5471 else if (SSTOVC(share)->vc_username) { 5472 uniqueptr->connection_type = kConnectedByUser; 5473 strlcpy(uniqueptr->user, SSTOVC(share)->vc_username, SMB_MAXUSERNAMELEN + 1); 5474 } else { 5475 uniqueptr->connection_type = kConnectedByKerberos; 5476 } 5477 uniqueptr->error = EEXIST; 5478 } 5479 } 5480 break; 5481 case smbfsByteRangeLock2FSCTL: 5482 case smbfsByteRangeLock2FSCTL_BASECMD: 5483 case smbfsByteRangeLockFSCTL: 5484 case smbfsByteRangeLockFSCTL_BASECMD: { 5485 struct ByteRangeLockPB *pb = (struct ByteRangeLockPB *) ap->a_data; 5486 struct ByteRangeLockPB2 *pb2 = (struct ByteRangeLockPB2 *) ap->a_data; 5487 uint32_t lck_pid; 5488 uint32_t timo; 5489 SMBFID fid = 0; 5490 struct fileRefEntry *fndEntry = NULL; 5491 uint16_t accessMode = 0; 5492 int8_t flags; 5493 struct smbfattr *fap = NULL; 5494 struct smb2_durable_handle dur_handle, *dptr; 5495 int do_create; 5496 uint32_t disp; 5497 5498 /* make sure its a file */ 5499 if (vnode_isdir(vp)) { 5500 error = EISDIR; 5501 goto exit; 5502 } 5503 5504 /* Before trying the lock see if the file needs to be reopened */ 5505 error = smbfs_smb_reopen_file(share, np, ap->a_context); 5506 if (error) { 5507 lck_rw_lock_shared(&np->n_name_rwlock); 5508 SMBDEBUG(" %s waiting to be revoked\n", np->n_name); 5509 lck_rw_unlock_shared(&np->n_name_rwlock); 5510 goto exit; 5511 } 5512 5513 /* 5514 * If adding/removing a ByteRangeLock, thus this vnode should NEVER 5515 * be cacheable since the page in/out may overlap a lock and get 5516 * an error. 5517 */ 5518 if (smbfsIsCacheable(vp)) { 5519 if (np->n_flag & NISMAPPED) { 5520 /* More expensive, but handles mmapped files */ 5521 ubc_msync (vp, 0, ubc_getsize(vp), NULL, UBC_PUSHDIRTY | UBC_SYNC); 5522 } else { 5523 /* Less expensive, but does not handle mmapped files */ 5524 cluster_push(vp, IO_SYNC); 5525 } 5526 ubc_msync (vp, 0, ubc_getsize(vp), NULL, UBC_INVALIDATE); 5527 vnode_setnocache(vp); 5528 } 5529 5530 accessMode = np->f_accessMode; 5531 5532 /* 5533 * Since we never get a smbfsByteRangeLockFSCTL call we could skip this 5534 * check, but for now leave it. 5535 */ 5536 if ( (ap->a_command == smbfsByteRangeLock2FSCTL) || 5537 (ap->a_command == smbfsByteRangeLock2FSCTL_BASECMD) ) { 5538 int32_t openMode = 0; 5539 5540 /* 5541 * Not just for classic any more, could get this from Carbon. 5542 * 5543 * They will be using an extended BRL call that also passes in the 5544 * open mode used that was used to open the file. I will use the 5545 * open access mode and pid to find the fork ref to do the lock on. 5546 * Scenarios: 5547 * Open (R/W), BRL, Close (R/W) 5548 * Open (R/W/dW), BRL, Close (R/W/dW) 5549 * Open1 (R/W), Open2 (R), BRL1, BRL2, Close1 (R/W), Close2 (R) 5550 * Open1 (R/W/dW), Open2 (R), BRL1, BRL2, Close1 (R/W/dW), Close2 (R) 5551 * Open1 (R/dW), Open2 (R/dW), BRL1, BRL2, Close1 (R/dW), Close2 (R/dW) 5552 */ 5553 if ( (error = file_flags(pb2->fd, &openMode)) ) { 5554 goto exit; 5555 } 5556 5557 if (openMode & FREAD) { 5558 accessMode |= kAccessRead; 5559 } 5560 if (openMode & FWRITE) { 5561 accessMode |= kAccessWrite; 5562 } 5563 5564 /* 5565 * See if we can find a matching fork that has byte range locks or 5566 * denyModes 5567 */ 5568 if (openMode & FHASLOCK) { 5569 /* 5570 * NOTE: FHASLOCK can be set by open with O_EXCLUSIVE or 5571 * O_SHARED which maps to my deny modes or FHASLOCK could also 5572 * have been set/cleared by calling flock directly. I assume 5573 * that if they are using byte range locks, then they are Carbon 5574 * and unlikely to be using flock. 5575 * 5576 * Assume it was opened with denyRead/denyWrite or just denyWrite. 5577 * Try denyWrite first, if not found, try with denyRead and denyWrite 5578 */ 5579 accessMode |= kDenyWrite; 5580 error = FindFileRef(vp, p, accessMode, kExactMatch, 0, 0, 5581 &fndEntry, &fid); 5582 if (error != 0) { 5583 accessMode |= kDenyRead; 5584 error = FindFileRef(vp, p, accessMode, kExactMatch, 0, 0, 5585 &fndEntry, &fid); 5586 } 5587 if (error != 0) { 5588 /* deny modes were used, but the fork ref cant be found, return error */ 5589 error = EBADF; 5590 goto exit; 5591 } 5592 } 5593 else { 5594 /* no deny modes used, look for any forks opened previously for BRL */ 5595 error = FindFileRef(vp, p, accessMode, kExactMatch, 0, 0, 5596 &fndEntry, &fid); 5597 } 5598 } else { 5599 error = FindFileRef(vp, p, kAccessRead | kAccessWrite, kAnyMatch, 5600 0, 0, &fndEntry, &fid); 5601 } 5602 /* 5603 * The process was not found or no list found 5604 * Either case, we need to 5605 * 1) Open a new fork 5606 * 2) create a new OpenForkRefEntry entry and add it into the list 5607 */ 5608 if (error) { 5609 uint32_t rights = 0; 5610 uint32_t shareMode = NTCREATEX_SHARE_ACCESS_ALL; 5611 proc_t p = vfs_context_proc(ap->a_context); 5612 5613 /* This is wrong, someone has to call open() before doing a byterange lock */ 5614 if (np->f_refcnt <= 0) { 5615 error = EBADF; 5616 goto exit; 5617 } 5618 5619 /* We must find a matching lock in order to succeed at unlock */ 5620 if (pb->unLockFlag == 1) { 5621 error = EINVAL; 5622 goto exit; 5623 } 5624 5625 /* Need to open the file here */ 5626 if (accessMode & kAccessRead) 5627 rights |= SMB2_FILE_READ_DATA; 5628 if (accessMode & kAccessWrite) 5629 rights |= SMB2_FILE_APPEND_DATA | SMB2_FILE_WRITE_DATA; 5630 5631 if (accessMode & kDenyWrite) 5632 shareMode &= ~NTCREATEX_SHARE_ACCESS_WRITE; /* Remove the wr shared access */ 5633 if (accessMode & kDenyRead) 5634 shareMode &= ~NTCREATEX_SHARE_ACCESS_READ; /* Remove the wr shared access */ 5635 5636 SMB_MALLOC(fap, 5637 struct smbfattr *, 5638 sizeof(struct smbfattr), 5639 M_SMBTEMP, 5640 M_WAITOK | M_ZERO); 5641 if (fap == NULL) { 5642 SMBERROR("SMB_MALLOC failed\n"); 5643 error = ENOMEM; 5644 goto exit; 5645 } 5646 5647 /* Request a durable handle */ 5648 dptr = NULL; 5649 error = smb2_smb_dur_handle_init(share, np, &dur_handle); 5650 if (!error) { 5651 dptr = &dur_handle; 5652 } 5653 5654 if (np->n_flag & N_ISRSRCFRK) { 5655 disp = FILE_OPEN_IF; 5656 do_create = TRUE; 5657 } 5658 else { 5659 disp = FILE_OPEN; 5660 do_create = FALSE; 5661 } 5662 5663 error = smbfs_smb_ntcreatex(share, np, 5664 rights, shareMode, VREG, 5665 &fid, NULL, 0, 5666 disp, FALSE, fap, 5667 do_create, dptr, ap->a_context); 5668 5669 if (error != 0) 5670 goto exit; 5671 5672 AddFileRef(vp, p, accessMode, rights, fid, dur_handle, &fndEntry); 5673 } 5674 5675 /* Now I can do the ByteRangeLock */ 5676 if (pb->startEndFlag) { 5677 /* 5678 * SMB only allows you to lock relative to the begining of the 5679 * file. So, I need to convert offset base on the begining 5680 * of the file. 5681 */ 5682 uint64_t fileSize = np->n_size; 5683 5684 pb->offset += fileSize; 5685 pb->startEndFlag = 0; 5686 } 5687 5688 flags = 0; 5689 if (pb->unLockFlag) 5690 flags |= SMB_LOCK_RELEASE; 5691 else 5692 flags |= SMB_LOCK_EXCL; 5693 5694 /* The problem here is that the lock pid must match the SMB Header PID. 5695 * Some day it would be nice to pass a better value here. But for now 5696 * always use the same value. 5697 */ 5698 lck_pid = 1; 5699 /* 5700 * -1 infinite wait 5701 * 0 no wait 5702 * any other number is the number of milliseconds to wait. 5703 */ 5704 timo = 0; 5705 5706 error = smbfs_smb_lock(share, flags, fid, lck_pid, pb->offset, 5707 pb->length, timo, ap->a_context); 5708 if (error == 0) { 5709 /* Save/remove lock info for use in read/write to determine what fork to use */ 5710 AddRemoveByteRangeLockEntry (fndEntry, pb->offset, pb->length, 5711 pb->unLockFlag, lck_pid); 5712 /* return the offset to the first byte of the lock */ 5713 pb->retRangeStart = pb->offset; 5714 } else if ((!pb->unLockFlag) && (error == EACCES)) { 5715 /* 5716 * Need to see if we are locking against ourself, so we can return 5717 * the correct error. 5718 */ 5719 if (FindByteRangeLockEntry(fndEntry, pb->offset, pb->length, lck_pid)) 5720 error = EAGAIN; 5721 } 5722 } 5723 break; 5724 default: 5725 error = ENOTSUP; 5726 goto exit; 5727 } 5728 5729exit: 5730 smb_share_rele(share, ap->a_context); 5731 smbnode_unlock(np); 5732 5733 SMB_LOG_KTRACE(SMB_DBG_IOCTL | DBG_FUNC_END, error, 0, 0, 0, 0); 5734 return (error); 5735} 5736 5737/* 5738 * SMB locks do not map to POSIX.1 advisory locks in several ways: 5739 * 1 - SMB provides no way to find an existing lock on the server. 5740 * So, the F_GETLK operation can only report locks created by processes 5741 * on this client. 5742 * 2 - SMB locks cannot overlap an existing locked region of a file. So, 5743 * F_SETLK/F_SETLKW operations that establish locks cannot extend an 5744 * existing lock. 5745 * 3 - When unlocking a SMB locked region, the region to unlock must correspond 5746 * exactly to an existing locked region. So, F_SETLK F_UNLCK operations 5747 * cannot split an existing lock or unlock more than was locked (this is 5748 * especially important because whne files are closed, we receive a request 5749 * to unlock the entire file: l_whence and l_start point to the beginning 5750 * of the file, and l_len is zero). 5751 * 5752 * The result... SMB cannot support POSIX.1 advisory locks. It can however 5753 * support BSD flock() locks, so that's what this implementation will allow. 5754 * 5755 * Since we now support open deny modes we will only support flocks on files that 5756 * have no files open w 5757 * 5758 * vnode_t a_vp; 5759 * caddr_t a_id; 5760 * int a_op; 5761 * struct flock *a_fl; 5762 * int a_flags; 5763 * vfs_context_t a_context; 5764 */ 5765static int32_t 5766smbfs_vnop_advlock(struct vnop_advlock_args *ap) 5767{ 5768 int flags = ap->a_flags; 5769 vnode_t vp = ap->a_vp; 5770 struct smb_share *share; 5771 struct smbnode *np; 5772 int error = 0; 5773 uint32_t timo; 5774 off_t start = 0; 5775 uint64_t len = -1; 5776 uint32_t lck_pid; 5777 5778 /* Preflight checks */ 5779 if (!vnode_isreg(vp)) { 5780 /* can only read regular files */ 5781 if (vnode_isdir(vp)) 5782 return (EISDIR); 5783 else 5784 return (EPERM); 5785 } 5786 5787 share = smb_get_share_with_reference(VTOSMBFS(vp)); 5788 if ((flags & F_POSIX) && ((UNIX_CAPS(share) & CIFS_UNIX_FCNTL_LOCKS_CAP) == 0)) { 5789 /* Release the share reference before returning */ 5790 smb_share_rele(share, ap->a_context); 5791 return(err_advlock(ap)); 5792 } 5793 5794 if ((flags & (F_FLOCK | F_POSIX)) == 0) { 5795 /* Release the share reference before returning */ 5796 smb_share_rele(share, ap->a_context); 5797 SMBWARNING("Lock flag we do not understand %x\n", flags); 5798 return(err_advlock(ap)); 5799 } 5800 5801 if ((error = smbnode_lock(VTOSMB(vp), SMBFS_EXCLUSIVE_LOCK))) { 5802 /* Release the share reference before returning */ 5803 smb_share_rele(share, ap->a_context); 5804 return (error); 5805 } 5806 5807 SMB_LOG_KTRACE(SMB_DBG_ADVLOCK | DBG_FUNC_START, 0, 0, 0, 0, 0); 5808 5809 /* If we got here it must be a flock. Remember flocks lock the whole file. */ 5810 np = VTOSMB(vp); 5811 np->n_lastvop = smbfs_vnop_advlock; 5812 5813 /* 5814 * This vnode has a file open with open deny modes, so the file is really 5815 * already locked. Remember that vn_open and vn_close will also call us here 5816 * so to make them work for now, return no err. If the opened it for 5817 * Open Deny then no one else should be allowed to use it. We could check 5818 * the pid here, but the open call should have handled that for us. 5819 */ 5820 if (np->f_openDenyList) { 5821 error = 0; 5822 goto exit; 5823 } 5824 5825 /* Before trying the lock see if the file needs to be reopened */ 5826 error = smbfs_smb_reopen_file(share, np, ap->a_context); 5827 if (error) { 5828 lck_rw_lock_shared(&np->n_name_rwlock); 5829 SMBDEBUG(" %s waiting to be revoked\n", np->n_name); 5830 lck_rw_unlock_shared(&np->n_name_rwlock); 5831 goto exit; 5832 } 5833 5834 /* 5835 * So if we got to this point we have a normal flock happening. We can have 5836 * the following flags passed to us. 5837 * 5838 * LOCK_SH - shared lock 5839 * LOCK_EX - exclusive lock 5840 * LOCK_NB - don't block when locking 5841 * LOCK_UN - unlock 5842 * 5843 * Currently we always allow the server handle blocking. We may want to 5844 * re-look at this later. What if we have a lock that is blocked and 5845 * the server goes down how long to we wait. 5846 * 5847 * The locking mechanism allows two types of locks: shared locks and 5848 * exclusive locks. At any time multiple shared locks may be applied to a 5849 * file, but at no time are multiple exclusive, or both shared and exclusive, 5850 * locks allowed simultaneously on a file. 5851 * 5852 * A shared lock may be upgraded to an exclusive lock, and vice versa, sim- 5853 * ply by specifying the appropriate lock type; this results in the previous 5854 * lock being released and the new lock applied (possibly after other processes 5855 * have gained and released the lock). 5856 * 5857 * We currently treat LOCK_EX and LOCK_SH the same except we do not allow 5858 * you to have more that one LOCK_EX. 5859 */ 5860 timo = (flags & F_WAIT) ? -1 : 0; 5861 /* The problem here is that the lock pid must match the SMB Header PID. Some 5862 * day it would be nice to pass a better value here. But for now always 5863 * use the same value. 5864 */ 5865 lck_pid = 1; 5866 /* Remember that we are always using the share open file at this point */ 5867 switch(ap->a_op) { 5868 case F_SETLK: 5869 if (! np->f_smbflock) { 5870 error = smbfs_smb_lock(share, SMB_LOCK_EXCL, np->f_fid, lck_pid, 5871 start, len, timo, ap->a_context); 5872 if (error) 5873 goto exit; 5874 SMB_MALLOC(np->f_smbflock, struct smbfs_flock *, sizeof *np->f_smbflock, 5875 M_LOCKF, M_WAITOK); 5876 np->f_smbflock->refcnt = 1; 5877 np->f_smbflock->fl_type = ap->a_fl->l_type; 5878 np->f_smbflock->lck_pid = lck_pid; 5879 np->f_smbflock->start = start; 5880 np->f_smbflock->len = len; 5881 np->f_smbflock->flck_pid = proc_pid(vfs_context_proc(ap->a_context)); 5882 } else if (np->f_smbflock->flck_pid == (uint32_t)proc_pid(vfs_context_proc(ap->a_context))) { 5883 /* First see if this is a upgrade or downgrade */ 5884 if ((np->f_smbflock->refcnt == 1) && 5885 (np->f_smbflock->fl_type != ap->a_fl->l_type)) { 5886 np->f_smbflock->fl_type = ap->a_fl->l_type; 5887 goto exit; 5888 } 5889 /* Trying to mismatch two different style of locks with the same process id bad! */ 5890 if (np->f_smbflock->fl_type != ap->a_fl->l_type) { 5891 error = ENOTSUP; 5892 goto exit; 5893 } 5894 /* 5895 * We know they have the same lock style from above, but they are 5896 * asking for two exclusive. So from Terry comments it looks like 5897 * this is ok. Here's the issue: because what they are doing is 5898 * upgrading an exclusive lock to an exclusive lock in the process 5899 * that holds the previous lock, there are _not_ multiple locks 5900 * involved; there's only the first lock and the lock that replaces 5901 * it. 5902 */ 5903 if (np->f_smbflock->fl_type != F_WRLCK) { 5904 /* 5905 * At no time are multiple exclusive locks allowed simultaneously 5906 * on a file. So we can have only one refcnt. This is an upgrade 5907 * not another lock. 5908 */ 5909 } else { 5910 np->f_smbflock->refcnt++; 5911 } 5912 } else { 5913 /* 5914 * Radar 5572840 5915 * F_WAIT is set we should sleep until the other flock 5916 * gets free then to an upgrade or down grade. Not support 5917 * with SMB yet. 5918 */ 5919 error = EWOULDBLOCK; 5920 goto exit; 5921 } 5922 break; 5923 case F_UNLCK: 5924 error = 0; 5925 if (! np->f_smbflock) /* Got an unlock and had no lock ignore */ 5926 break; 5927 np->f_smbflock->refcnt--; 5928 /* remove the lock on the network and */ 5929 if (np->f_smbflock->refcnt <= 0) { 5930 error = smbfs_smb_lock(share, SMB_LOCK_RELEASE, np->f_fid, lck_pid, 5931 start, len, timo, ap->a_context); 5932 if (error == 0) { 5933 SMB_FREE(np->f_smbflock, M_LOCKF); 5934 np->f_smbflock = NULL; 5935 } 5936 } 5937 break; 5938 default: 5939 error = EINVAL; 5940 break; 5941 } 5942exit: 5943 smb_share_rele(share, ap->a_context); 5944 smbnode_unlock(np); 5945 5946 SMB_LOG_KTRACE(SMB_DBG_ADVLOCK | DBG_FUNC_END, error, 0, 0, 0, 0); 5947 return (error); 5948} 5949 5950/* 5951 * The calling routine must hold a reference on the share 5952 */ 5953static int 5954smbfs_pathcheck(struct smb_share *share, const char *name, size_t nmlen, 5955 uint32_t nameiop) 5956{ 5957 const char *cp, *endp; 5958 int error; 5959 5960 /* 5961 * We need to check the file name length. We now use ss_maxfilenamelen 5962 * since that gives us a more accurate max file name length. If the 5963 * server supports UNICODE we should do more checking. Since UTF8 can 5964 * have three bytes per character just checking the length is not enough. 5965 * We should convert it to UTF16 and see if the length is twice 5966 * ss_maxfilenamelen. 5967 * 5968 */ 5969 if ((uint32_t)nmlen > share->ss_maxfilenamelen) { 5970 if (SMB_UNICODE_STRINGS(SSTOVC(share))) { 5971 uint16_t *convbuf; 5972 size_t ntwrk_len; 5973 /* 5974 * smb_strtouni needs an output buffer that is twice 5975 * as large as the input buffer (name). 5976 */ 5977 SMB_MALLOC(convbuf, uint16_t *, nmlen * 2, M_SMBNODENAME, M_WAITOK); 5978 if (! convbuf) 5979 return ENAMETOOLONG; 5980 /* 5981 * We need to get the UFT16 length, so just use smb_strtouni 5982 * instead of smb_convert_to_network. 5983 */ 5984 ntwrk_len = smb_strtouni(convbuf, name, nmlen, 5985 UTF_PRECOMPOSED | UTF_SFM_CONVERSIONS); 5986 SMB_FREE(convbuf, M_SMBNODENAME); 5987 if (ntwrk_len > (share->ss_maxfilenamelen * 2)) 5988 return ENAMETOOLONG; 5989 } else { 5990 return ENAMETOOLONG; 5991 } 5992 } else if (! nmlen) { 5993 return ENAMETOOLONG; 5994 } 5995 5996 /* Check name only if CREATE, DELETE, or RENAME */ 5997 if (nameiop == LOOKUP) 5998 return (0); 5999 6000 /* 6001 * Winodws systems do not allow items that begin with "con" to be created. 6002 * If this is not a UNIX server then stop the user from trying 6003 * to create this file or folder. When trying to create a "con" folder or 6004 * "con.xxx" file a windows system will report the following error: 6005 * Cannot create or replace file: The filename you specified is too long. 6006 * Specify a different filename. 6007 * 6008 * From my testing any name that matches "con" or begins with "con." 6009 * should not be create. 6010 * 6011 * Should we be like windows and return ENAMETOOLONG or EACCES 6012 */ 6013 if ((! UNIX_SERVER(SSTOVC(share))) && CON_FILENAME(name, nmlen)) { 6014 if ((nmlen == 3) || ((nmlen > 3) && (*(name+3) == '.'))) 6015 return (ENAMETOOLONG); 6016 } 6017 6018 /* If the server supports UNICODE then we are done checking the name. */ 6019 if (SMB_UNICODE_STRINGS(SSTOVC(share))) 6020 return (0); 6021 6022 /* 6023 * Normally, we'd return EINVAL when the name is syntactically invalid, 6024 * but ENAMETOOLONG makes it clear that the name is the problem (and 6025 * allows Carbon to return a more meaningful error). 6026 */ 6027 error = ENAMETOOLONG; 6028 6029 /* 6030 * Note: This code does not prevent the smb file system client 6031 * from creating filenames which are difficult to use with 6032 * other clients. For example, you can create " foo " or 6033 * "foo..." which cannot be moved, renamed, or deleted by some 6034 * other clients. 6035 */ 6036 6037 /* check for illegal characters, if the server does not support UNICODE */ 6038 for (cp = name, endp = name + nmlen; cp < endp; ++cp) { 6039 /* 6040 * The set of illegal characters in long names is the same as 6041 * 8.3 except the characters 0x20, 0x2b, 0x2c, 0x3b, 0x3d, 0x5b, 6042 * and 0x5d are now legal, and the restrictions on periods was 6043 * removed. 6044 */ 6045 switch (*cp) { 6046 case 0x20: /* space */ 6047 case 0x2B: /* + */ 6048 case 0x2C: /* , */ 6049 case 0x3B: /* ; */ 6050 case 0x3D: /* = */ 6051 case 0x5B: /* [ */ 6052 case 0x5D: /* ] */ 6053 break; 6054 case 0x22: /* " */ 6055 case 0x2A: /* * */ 6056 case 0x2F: /* / */ 6057 case 0x3A: /* : */ 6058 case 0x3C: /* < */ 6059 case 0x3E: /* > */ 6060 case 0x3F: /* ? */ 6061 case 0x5C: /* \ */ 6062 case 0x7C: /* | */ 6063 /* illegal character found */ 6064 return (error); 6065 break; 6066 default: 6067 break; 6068 } 6069 } 6070 return (0); 6071} 6072 6073/* 6074 * smbfs_vnop_lookup 6075 * 6076 * struct vnodeop_desc *a_desc; 6077 * vnode_t a_dvp; 6078 * vnode_t *a_vpp; 6079 * struct componentname *a_cnp; 6080 * vfs_context_t a_context; 6081 */ 6082static int 6083smbfs_vnop_lookup(struct vnop_lookup_args *ap) 6084{ 6085 vfs_context_t context = ap->a_context; 6086 vnode_t dvp = ap->a_dvp; 6087 vnode_t *vpp = ap->a_vpp; 6088 vnode_t vp; 6089 struct smbnode *dnp = NULL; 6090 struct mount *mp = vnode_mount(dvp); 6091 struct smb_share *share = NULL; 6092 struct componentname *cnp = ap->a_cnp; 6093 const char *name = cnp->cn_nameptr; 6094 uint32_t flags = cnp->cn_flags; 6095 uint32_t nameiop = cnp->cn_nameiop; 6096 size_t nmlen = cnp->cn_namelen; 6097 struct smbfattr fattr, *fap = NULL; 6098 int wantparent, error, islastcn, isdot = FALSE; 6099 int parent_locked = FALSE; 6100 6101 /* 6102 * We may want to move smbfs_pathcheck here, but we really should never 6103 * find a bad name in the name cache lookup. 6104 */ 6105 if (!vnode_isdir(dvp)) 6106 return (ENOTDIR); 6107 6108 if ((flags & ISDOTDOT) && vnode_isvroot(dvp)) { 6109 SMBERROR("invalid '..'\n"); 6110 return (EIO); 6111 } 6112 6113 islastcn = (flags & ISLASTCN) ? TRUE : FALSE; 6114 if (islastcn && vfs_isrdonly(mp) && nameiop != LOOKUP) 6115 return (EROFS); 6116 6117 SMB_LOG_KTRACE(SMB_DBG_LOOKUP | DBG_FUNC_START, 6118 VTOSMB(dvp)->d_fid, 0, 0, 0, 0); 6119 6120 wantparent = (flags & (LOCKPARENT|WANTPARENT)) ? TRUE : FALSE; 6121 6122 share = smb_get_share_with_reference(VTOSMBFS(dvp)); 6123 6124 /* 6125 * We need to make sure the negative name cache gets updated if 6126 * needed. So if the parents cache has expired, then update the 6127 * the parent's cache. This will cause the negative name cache to 6128 * be flush if the parent's modify time has changed. 6129 */ 6130 if (smbnode_lock(VTOSMB(dvp), SMBFS_EXCLUSIVE_LOCK) == 0) { 6131 VTOSMB(dvp)->n_lastvop = smbfs_vnop_lookup; 6132 if (VTOSMB(dvp)->n_flag & NNEGNCENTRIES) { 6133 /* ignore any errors here we will catch them later */ 6134 (void)smbfs_update_cache(share, dvp, NULL, context); 6135 } 6136 smbnode_unlock(VTOSMB(dvp)); /* Release the smbnode lock */ 6137 } 6138 6139 *vpp = NULLVP; 6140 error = cache_lookup(dvp, vpp, cnp); 6141 6142 SMB_LOG_KTRACE(SMB_DBG_LOOKUP | DBG_FUNC_NONE, 6143 0xabc001, error, 0, 0, 0); 6144 6145 switch (error) { 6146 case ENOENT: /* negative cache entry */ 6147 goto skipLookup; 6148 case 0: /* cache miss */ 6149 break; 6150 case -1: /* cache hit */ 6151 /* 6152 * On CREATE we can't trust a cache hit as if it is stale 6153 * and the object doesn't exist on the server returning zero 6154 * here would cause the vfs layer to, for instance, EEXIST 6155 * the mkdir. 6156 */ 6157 if (nameiop != CREATE) { 6158 error = 0; 6159 /* Check to see it the node's meta cache needs to be update */ 6160 if (smbnode_lock(VTOSMB(*vpp), SMBFS_EXCLUSIVE_LOCK) == 0) { 6161 VTOSMB(*vpp)->n_lastvop = smbfs_vnop_lookup; 6162 error = smbfs_update_cache(share, *vpp, NULL, context); 6163 smbnode_unlock(VTOSMB(*vpp)); /* Release the smbnode lock */ 6164 } 6165 /* 6166 * At this point we only care if it exist or not so any other 6167 * error should just get ignored 6168 */ 6169 if (error != ENOENT) { 6170 error = 0; 6171 goto done; 6172 } 6173 /* 6174 * The item we had, no longer exists so fall through and see if 6175 * it exist as a different item 6176 */ 6177 } 6178 if (*vpp) { 6179 cache_purge(*vpp); 6180 vnode_put(*vpp); 6181 *vpp = NULLVP; 6182 } 6183 break; 6184 default: /* unknown & unexpected! */ 6185 SMBWARNING("cache_lookup error=%d\n", error); 6186 goto done; 6187 } 6188 6189 /* 6190 * entry is not in the name cache 6191 * 6192 * validate syntax of name. ENAMETOOLONG makes it clear the name 6193 * is the problem 6194 */ 6195 error = smbfs_pathcheck(share, cnp->cn_nameptr, cnp->cn_namelen, nameiop); 6196 if (error) { 6197 SMBWARNING("warning: bad filename %s\n", name); 6198 goto done; 6199 } 6200 dnp = VTOSMB(dvp); 6201 6202 /* lock the parent while we go look for the item on server */ 6203 if (smbnode_lock(dnp, SMBFS_EXCLUSIVE_LOCK) != 0) { 6204 error = ENOENT; 6205 goto skipLookup; 6206 } 6207 parent_locked = TRUE; 6208 dnp->n_lastvop = smbfs_vnop_lookup; 6209 6210 isdot = (nmlen == 1 && name[0] == '.'); 6211 fap = &fattr; 6212 /* 6213 * This can allocate a new "name" do not return before the end of the 6214 * routine from here on. 6215 */ 6216 if (flags & ISDOTDOT) { 6217 lck_rw_lock_shared(&dnp->n_parent_rwlock); 6218 error = smbfs_lookup(share, dnp->n_parent, NULL, NULL, fap, context); 6219 lck_rw_unlock_shared(&dnp->n_parent_rwlock); 6220 } 6221 else { 6222 error = smbfs_lookup(share, dnp, &name, &nmlen, fap, context); 6223 } 6224 SMB_LOG_KTRACE(SMB_DBG_LOOKUP | DBG_FUNC_NONE, 6225 0xabc002, error, 0, 0, 0); 6226 6227 /* 6228 * We use to unlock the parent here, but we really need it locked 6229 * until after we do the smbfs_nget calls. 6230 */ 6231 /* 6232 * We didn't find it and this is not a CREATE or RENAME operation so 6233 * add it to the negative name cache. 6234 */ 6235 if ((error == ENOENT) && (cnp->cn_flags & MAKEENTRY) && 6236 (!(((nameiop == CREATE) || (nameiop == RENAME)) && islastcn))) { 6237 /* add a negative entry in the name cache */ 6238 cache_enter(dvp, NULL, cnp); 6239 dnp->n_flag |= NNEGNCENTRIES; 6240 } 6241 6242skipLookup: 6243 if (error) { 6244 /* 6245 * note the EJUSTRETURN code in lookup() 6246 */ 6247 if (((nameiop == CREATE) || (nameiop == RENAME)) && 6248 (error == ENOENT) && islastcn) { 6249 error = EJUSTRETURN; 6250 } 6251 } else if ((nameiop == RENAME) && islastcn && wantparent) { 6252 if (isdot) { 6253 error = EISDIR; 6254 } else { 6255 error = smbfs_nget(share, mp, 6256 dvp, name, nmlen, 6257 fap, &vp, 6258 0, SMBFS_NGET_CREATE_VNODE, 6259 context); 6260 if (!error) { 6261 smbnode_unlock(VTOSMB(vp)); /* Release the smbnode lock */ 6262 *vpp = vp; 6263 } 6264 } 6265 } else if ((nameiop == DELETE) && islastcn) { 6266 if (isdot) { 6267 error = vnode_get(dvp); 6268 if (!error) 6269 *vpp = dvp; 6270 } else { 6271 error = smbfs_nget(share, mp, 6272 dvp, name, nmlen, 6273 fap, &vp, 6274 0, SMBFS_NGET_CREATE_VNODE, 6275 context); 6276 if (!error) { 6277 smbnode_unlock(VTOSMB(vp)); /* Release the smbnode lock */ 6278 *vpp = vp; 6279 } 6280 } 6281 } else if (flags & ISDOTDOT) { 6282 if (dvp) { 6283 lck_rw_lock_shared(&VTOSMB(dvp)->n_parent_rwlock); 6284 if (VTOSMB(dvp)->n_parent) { 6285 vp = VTOSMB(dvp)->n_parent->n_vnode; 6286 error = vnode_get(vp); 6287 if (!error) 6288 *vpp = vp; 6289 } 6290 lck_rw_unlock_shared(&VTOSMB(dvp)->n_parent_rwlock); 6291 } 6292 } else if (isdot) { 6293 error = vnode_get(dvp); 6294 if (!error) 6295 *vpp = dvp; 6296 } else { 6297 error = smbfs_nget(share, mp, 6298 dvp, name, nmlen, 6299 fap, &vp, 6300 cnp->cn_flags, SMBFS_NGET_CREATE_VNODE, 6301 context); 6302 if (!error) { 6303 smbnode_unlock(VTOSMB(vp)); /* Release the smbnode lock */ 6304 *vpp = vp; 6305 } 6306 } 6307 if (name != cnp->cn_nameptr) { 6308 SMB_FREE(name, M_SMBNODENAME); 6309 } 6310 /* If the parent node is still lock then unlock it here. */ 6311 if (parent_locked && dnp) 6312 smbnode_unlock(dnp); 6313done: 6314 smb_share_rele(share, context); 6315 6316 SMB_LOG_KTRACE(SMB_DBG_LOOKUP | DBG_FUNC_END, error, 0, 0, 0, 0); 6317 return (error); 6318} 6319 6320/* 6321 * smbfs_vnop_offtoblk 6322 * 6323 * vnode_t a_vp; 6324 * off_t a_offset; 6325 * daddr64_t *a_lblkno; 6326 * vfs_context_t a_context; 6327 * 6328 * ftoblk converts a file offset to a logical block number 6329 */ 6330static int 6331smbfs_vnop_offtoblk(struct vnop_offtoblk_args *ap) 6332{ 6333 *ap->a_lblkno = ap->a_offset / PAGE_SIZE_64; 6334 return (0); 6335} 6336 6337/* 6338 * smbfs_vnop_blktooff 6339 * 6340 * vnode_t a_vp; 6341 * off_t a_offset; 6342 * daddr64_t *a_lblkno; 6343 * off_t *a_offset; 6344 * vfs_context_t a_context; 6345 * 6346 * blktooff converts a logical block number to a file offset 6347 */ 6348static int 6349smbfs_vnop_blktooff(struct vnop_blktooff_args *ap) 6350{ 6351 *ap->a_offset = (off_t)ap->a_lblkno * PAGE_SIZE_64; 6352 return (0); 6353} 6354 6355/* 6356 * smbfs_vnop_pagein 6357 * 6358 * vnode_t a_vp, 6359 * upl_t a_pl, 6360 * vm_offset_t a_pl_offset, 6361 * off_t a_f_offset, 6362 * size_t a_size, 6363 * int a_flags 6364 * vfs_context_t a_context; 6365 * 6366 * NOTE: We no longer take a node lock in this routine. 6367 */ 6368static int 6369smbfs_vnop_pagein(struct vnop_pagein_args *ap) 6370{ 6371 vnode_t vp = ap->a_vp; 6372 struct smb_share *share; 6373 size_t size = ap->a_size; 6374 off_t f_offset = ap->a_f_offset; 6375 struct smbnode *np; 6376 int error; 6377 6378 SMB_LOG_KTRACE(SMB_DBG_PAGE_IN | DBG_FUNC_START, 0, 0, 0, 0, 0); 6379 6380 np = VTOSMB(vp); 6381 6382 if ((size <= 0) || (f_offset < 0) || (f_offset >= (off_t)np->n_size) || 6383 (f_offset & PAGE_MASK_64) || (size & PAGE_MASK)) { 6384 error = err_pagein(ap); /* behave like the deadfs does */ 6385 goto done; 6386 } 6387 share = smb_get_share_with_reference(VTOSMBFS(vp)); 6388 /* Before trying the read see if the file needs to be reopened */ 6389 error = smbfs_smb_reopen_file(share, np, ap->a_context); 6390 if (error) { 6391 lck_rw_lock_shared(&np->n_name_rwlock); 6392 SMBDEBUG(" %s waiting to be revoked\n", np->n_name); 6393 lck_rw_unlock_shared(&np->n_name_rwlock); 6394 6395 /* Release the share reference before returning */ 6396 smb_share_rele(share, ap->a_context); 6397 error = err_pagein(ap); /* behave like the deadfs does */ 6398 goto done; 6399 } 6400 /* 6401 * The old code would check to see if the node smbfsIsCacheable. If not then 6402 * it would try to invalidate the page to force the cluster code to get a 6403 * new copy from disk/network. Talked this over with Joe and this is not 6404 * really need. 6405 * 6406 * The smbfs_vnop_pagein will only be called for extents of pages that do 6407 * NOT already exist in the cache. When the UPL is created, the pages are 6408 * acquired and locked down for the 'holes' that exist in the cache. Once 6409 * those pages are locked into the UPL, there can be no other path by which 6410 * the pages can be made valid. So... no reason to flush pages in the range 6411 * being passed into you and then on to cluster_pagein. 6412 */ 6413 error = cluster_pagein(vp, ap->a_pl, ap->a_pl_offset, ap->a_f_offset, 6414 (int)ap->a_size, (off_t)np->n_size, ap->a_flags); 6415 if (error) { 6416 lck_rw_lock_shared(&np->n_name_rwlock); 6417 SMB_LOG_IO("%s failed cluster_pagein with an error of %d\n", np->n_name, error); 6418 lck_rw_unlock_shared(&np->n_name_rwlock); 6419 } 6420 smb_share_rele(share, ap->a_context); 6421 6422done: 6423 SMB_LOG_KTRACE(SMB_DBG_PAGE_IN | DBG_FUNC_END, error, 0, 0, 0, 0); 6424 return (error); 6425} 6426 6427/* 6428 * smbfs_vnop_pageout 6429 * 6430 * vnode_t a_vp, 6431 * upl_t a_pl, 6432 * vm_offset_t a_pl_offset, 6433 * off_t a_f_offset, 6434 * size_t a_size, 6435 * int a_flags 6436 * vfs_context_t a_context; 6437 * 6438 * NOTE: We no longer take a node lock in this routine. 6439 * 6440 */ 6441static int 6442smbfs_vnop_pageout(struct vnop_pageout_args *ap) 6443{ 6444 vnode_t vp = ap->a_vp; 6445 struct smbnode *np; 6446 struct smb_share *share; 6447 upl_t pl = ap->a_pl; 6448 size_t size = ap->a_size; 6449 off_t f_offset = ap->a_f_offset; 6450 int error; 6451 6452 if (vnode_vfsisrdonly(vp)) 6453 return(EROFS); 6454 6455 SMB_LOG_KTRACE(SMB_DBG_PAGE_OUT | DBG_FUNC_START, 0, 0, 0, 0, 0); 6456 6457 np = VTOSMB(vp); 6458 6459 if (pl == (upl_t)NULL) 6460 panic("smbfs_vnop_pageout: no upl"); 6461 6462 if ((size <= 0) || (f_offset < 0) || (f_offset >= (off_t)np->n_size) || 6463 (f_offset & PAGE_MASK_64) || (size & PAGE_MASK)) { 6464 error = err_pageout(ap); 6465 goto done; 6466 } 6467 share = smb_get_share_with_reference(VTOSMBFS(vp)); 6468 /* Before trying the write see if the file needs to be reopened */ 6469 error = smbfs_smb_reopen_file(share, np, ap->a_context); 6470 if (error) { 6471 lck_rw_lock_shared(&np->n_name_rwlock); 6472 SMBDEBUG(" %s waiting to be revoked\n", np->n_name); 6473 lck_rw_unlock_shared(&np->n_name_rwlock); 6474 6475 /* Release the share reference before returning */ 6476 smb_share_rele(share, ap->a_context); 6477 error = err_pageout(ap); 6478 goto done; 6479 } 6480 6481 error = cluster_pageout(vp, ap->a_pl, ap->a_pl_offset, ap->a_f_offset, 6482 (int)ap->a_size, (off_t)np->n_size, ap->a_flags); 6483 if (error) { 6484 lck_rw_lock_shared(&np->n_name_rwlock); 6485 SMB_LOG_IO("%s failed cluster_pageout with an error of %d\n", 6486 np->n_name, error); 6487 lck_rw_unlock_shared(&np->n_name_rwlock); 6488 } 6489 6490 smb_share_rele(share, ap->a_context); 6491 /* If we can get the parent vnode, reset its meta data cache timer. */ 6492 if (vnode_isnamedstream(vp)) { 6493 vnode_t parent_vp = vnode_getparent(vp); 6494 if (parent_vp) { 6495 VTOSMB(parent_vp)->attribute_cache_timer = 0; 6496 vnode_put(parent_vp); 6497 } 6498 } 6499 6500done: 6501 SMB_LOG_KTRACE(SMB_DBG_PAGE_OUT | DBG_FUNC_END, error, 0, 0, 0, 0); 6502 return (error); 6503} 6504 6505/* 6506 * smbfs_vnop_copyfile 6507 * 6508 * vnode_t a_fvp; 6509 * vnode_t a_tdvp; 6510 * vnode_t a_tvp; 6511 * struct componentname *a_tcnp; 6512 * int a_flags; 6513 * vfs_context_t a_context; 6514 */ 6515static int 6516smbfs_vnop_copyfile(struct vnop_copyfile_args *ap) 6517{ 6518 vnode_t fvp = ap->a_fvp; 6519 vnode_t tvp = ap->a_tvp; 6520 vnode_t tdvp = ap->a_tdvp; 6521 struct smbmount *smp = VFSTOSMBFS(vnode_mount(fvp)); 6522 struct smb_share *share = NULL; 6523 struct componentname *tcnp = ap->a_tcnp; 6524 struct smbnode *fnp = NULL; 6525 struct smbnode *tdnp = NULL; 6526 struct smbnode *tnp = NULL; 6527 int error = 0, vtype, need_unlock = 0; 6528 6529 /* VFS checks the following before calling us: 6530 * 6531 * tvp exists AND (ap->flags & CPF_OVERWRITE) 6532 * fvp AND tvp are not directories 6533 * KAUTH_VNODE_ADD_FILE authorized on tdvp 6534 * fvp != tvp 6535 * fvp != tdvp 6536 */ 6537 6538 SMB_LOG_KTRACE(SMB_DBG_COPYFILE | DBG_FUNC_START, 0, 0, 0, 0, 0); 6539 6540 /* Check if this is an SMB 2/3 server (need COPYCHUNK IOCTL) */ 6541 share = smb_get_share_with_reference(smp); 6542 if (!SSTOVC(share)->vc_flags & SMBV_SMB2) { 6543 SMBERROR("copyfile not supported on this server.\n"); 6544 error = ENOTSUP; 6545 goto out; 6546 } 6547 6548 /* Check for cross-device copyfile */ 6549 if ((vnode_mount(fvp) != vnode_mount(tdvp)) || 6550 (tvp && (vnode_mount(fvp) != vnode_mount(tvp)))) { 6551 SMBERROR("cross-device copyfile not supported.\n"); 6552 error = EXDEV; 6553 goto out; 6554 } 6555 6556 /* source file must be a directory, symbolic link, or regular file */ 6557 vtype = vnode_vtype(fvp); 6558 if ( (vtype != VDIR) && (vtype != VREG) && (vtype != VLNK) ) { 6559 SMBERROR("copyfile not supported on vtype: %d\n", vtype); 6560 error = EINVAL; 6561 goto out; 6562 } 6563 6564 fnp = VTOSMB(fvp); 6565 tdnp = VTOSMB(tdvp); 6566 tnp = (tvp == NULL) ? NULL : VTOSMB(tvp); 6567 6568 /* Lock source file and target directory */ 6569 smbnode_lockpair(fnp, tdnp, SMBFS_EXCLUSIVE_LOCK); 6570 need_unlock = 1; 6571 6572 fnp->n_lastvop = smbfs_vnop_copyfile; 6573 tdnp->n_lastvop = smbfs_vnop_copyfile; 6574 if (tnp != NULL) 6575 tnp->n_lastvop = smbfs_vnop_copyfile; 6576 6577 /* 6578 * Do the copyfile operation. 6579 */ 6580 error = smb2fs_smb_copyfile(share, fnp, tdnp, tcnp->cn_nameptr, 6581 tcnp->cn_namelen, ap->a_context); 6582 if (error) { 6583 SMBERROR("smb2fs_smb_copyfile returned: %d\n", error); 6584 goto out; 6585 } 6586 6587 smbfs_attr_touchdir(tdnp, (share->ss_fstype == SMB_FS_FAT)); 6588 6589 /* blow away statfs cache */ 6590 smp->sm_statfstime = 0; 6591 6592 /* Invalidate negative cache entries in destination dir */ 6593 if (tdnp->n_flag & NNEGNCENTRIES) { 6594 tdnp->n_flag &= ~NNEGNCENTRIES; 6595 cache_purge_negatives(tdvp); 6596 } 6597 6598out: 6599 /* We only have a share if we obtain a reference on it, so release it */ 6600 if (share) { 6601 smb_share_rele(share, ap->a_context); 6602 } 6603 6604 if (need_unlock) { 6605 smbnode_unlockpair(fnp, tdnp); 6606 } 6607 6608 SMB_LOG_KTRACE(SMB_DBG_COPYFILE | DBG_FUNC_END, error, 0, 0, 0, 0); 6609 return (error); 6610} 6611 6612static uint32_t emptyfinfo[8] = {0}; 6613/* 6614 * DefaultFillAfpInfo 6615 * 6616 * Given a buffer fill in the default AfpInfo values. 6617 */ 6618static void 6619DefaultFillAfpInfo(uint8_t *afpinfo) 6620{ 6621 int ii = 0; 6622 bzero(afpinfo, AFP_INFO_SIZE); 6623 /* Signature is a DWORD. Must be *(PDWORDD)"AFP" */ 6624 afpinfo[ii++] = 'A'; 6625 afpinfo[ii++] = 'F'; 6626 afpinfo[ii++] = 'P'; 6627 afpinfo[ii++] = 0; 6628 /* Version is a DWORD. Must be 0x00010000 (byte swapped) */ 6629 afpinfo[ii++] = 0; 6630 afpinfo[ii++] = 0; 6631 afpinfo[ii++] = 0x01; 6632 afpinfo[ii++] = 0; 6633 /* Reserved1 is a DWORD */ 6634 ii += 4; 6635 /* 6636 * Backup time is a DWORD. Backup time for the file/dir. Not set equals 6637 * 0x80010000 (byte swapped) 6638 */ 6639 afpinfo[ii++] = 0; 6640 afpinfo[ii++] = 0; 6641 afpinfo[ii++] = 0; 6642 afpinfo[ii] = 0x80; 6643 /* Finder Info is 32 bytes. Calling process fills this in */ 6644 /* ProDos Info is 6 bytes. Leave set to zero? */ 6645 /* Reserved2 is 6 bytes */ 6646} 6647 6648/* 6649 * xattr2sfm 6650 * 6651 * See if this xattr is really the resource fork or the finder info stream. If so 6652 * return the correct streams name otherwise just return the name passed to us. 6653 */ 6654static const char * 6655xattr2sfm(const char *xa, enum stream_types *stype) 6656{ 6657 /* Never let them use the SFM Stream Names */ 6658 if (!bcmp(xa, SFM_RESOURCEFORK_NAME, sizeof(SFM_RESOURCEFORK_NAME))) { 6659 return(NULL); 6660 } 6661 if (!bcmp(xa, SFM_FINDERINFO_NAME, sizeof(SFM_FINDERINFO_NAME))) { 6662 return(NULL); 6663 } 6664 if (!bcmp(xa, SFM_DESKTOP_NAME, sizeof(SFM_DESKTOP_NAME))) { 6665 return(NULL); 6666 } 6667 if (!bcmp(xa, SFM_IDINDEX_NAME, sizeof(SFM_IDINDEX_NAME))) { 6668 return(NULL); 6669 } 6670 6671 if (!bcmp(xa, XATTR_RESOURCEFORK_NAME, sizeof(XATTR_RESOURCEFORK_NAME))) { 6672 *stype = kResourceFrk; 6673 return (SFM_RESOURCEFORK_NAME); 6674 } 6675 if (!bcmp(xa, XATTR_FINDERINFO_NAME, sizeof(XATTR_FINDERINFO_NAME))) { 6676 *stype = kFinderInfo; 6677 return (SFM_FINDERINFO_NAME); 6678 } 6679 *stype = kExtendedAttr; 6680 return (xa); 6681} 6682 6683/* 6684 * smbfs_vnop_setxattr 6685 * 6686 * vnode_t a_vp; 6687 * int8_t * a_name; 6688 * uio_t a_uio; 6689 * int32_t a_options; 6690 * vfs_context_t a_context; 6691 */ 6692static int 6693smbfs_vnop_setxattr(struct vnop_setxattr_args *ap) 6694{ 6695 vnode_t vp = ap->a_vp; 6696 const char *sfmname; 6697 int error = 0; 6698 SMBFID fid = 0; 6699 uint32_t rights = SMB2_FILE_WRITE_DATA; 6700 struct smbnode *np = NULL; 6701 struct smb_share *share = NULL; 6702 enum stream_types stype = kNoStream; 6703 uint32_t open_disp = 0; 6704 uio_t afp_uio = NULL; 6705 uint8_t afpinfo[60]; 6706 struct smbfattr fattr; 6707 6708 DBG_ASSERT(!vnode_isnamedstream(vp)); 6709 6710 if ((error = smbnode_lock(VTOSMB(vp), SMBFS_EXCLUSIVE_LOCK))) 6711 return (error); 6712 6713 SMB_LOG_KTRACE(SMB_DBG_SET_XATTR | DBG_FUNC_START, 0, 0, 0, 0, 0); 6714 6715 np = VTOSMB(vp); 6716 np->n_lastvop = smbfs_vnop_setxattr; 6717 share = smb_get_share_with_reference(VTOSMBFS(vp)); 6718 6719 /* 6720 * FILE_NAMED_STREAMS tells us the server supports streams. 6721 * NOTE: This flag may have been overwriten by us in smbfs_mount. The default 6722 * is for streams to be turn off. See the smbfs_mount for more details. 6723 */ 6724 if (!(share->ss_attributes & FILE_NAMED_STREAMS)) { 6725 error = ENOTSUP; 6726 goto exit; 6727 } 6728 6729 /* You cant have both of these set at the same time. */ 6730 if ( (ap->a_options & XATTR_CREATE) && (ap->a_options & XATTR_REPLACE) ) { 6731 error = EINVAL; 6732 goto exit; 6733 } 6734 6735 /* SMB doesn't support having a slash in the xattr name */ 6736 if (strchr(ap->a_name, '/')) { 6737 error = EINVAL; 6738 6739 lck_rw_lock_shared(&np->n_name_rwlock); 6740 SMBWARNING("Slash in xattr name not allowed: error %d %s:%s\n", error, 6741 np->n_name, ap->a_name); 6742 lck_rw_unlock_shared(&np->n_name_rwlock); 6743 goto exit; 6744 } 6745 sfmname = xattr2sfm(ap->a_name, &stype); 6746 if (!sfmname) { 6747 error = EINVAL; 6748 goto exit; 6749 } 6750 6751 /* 6752 * Need to add write attributes if we want to reset the modify time. We never do this 6753 * for the resource fork. The file manager expects the modify time to change if the 6754 * resource fork changes. 6755 */ 6756 if ((stype & kResourceFrk) != kResourceFrk) 6757 rights |= SMB2_FILE_WRITE_ATTRIBUTES; 6758 6759 /* 6760 * We treat finder info differently than any other EA/Stream. Because of 6761 * SFM we need to do things a little different. Remember the AFPInfo stream 6762 * has more information in it than just the finder info. WARNING: SFM can 6763 * get very confused if you do not handle this correctly! 6764 */ 6765 if (stype & kFinderInfo) { 6766 uint8_t finfo[FINDERINFOSIZE]; 6767 time_t attrtimeo; 6768 struct timespec ts; 6769 size_t sizep; 6770 int len = (int)uio_resid(ap->a_uio); 6771 6772 /* Can't be larger that 32 bytes */ 6773 if (len > FINDERINFOSIZE) { 6774 error = EINVAL; 6775 goto exit; 6776 } 6777 6778 error = uiomove((void *)finfo, len, ap->a_uio); 6779 if (error) { 6780 goto exit; 6781 } 6782 6783 SMB_CACHE_TIME(ts, np, attrtimeo); 6784 /* 6785 * The Finder Info cache hasn't expired so check to see if they are 6786 * setting it to something different or the same. If the same then skip 6787 * setting it, this is what AFP does. 6788 */ 6789 if ((ts.tv_sec - np->finfo_cache_timer) <= attrtimeo) { 6790 if (bcmp(np->finfo, finfo, sizeof(finfo)) == 0) 6791 goto exit; 6792 } 6793 6794 /* We want to read also in this case. */ 6795 rights |= SMB2_FILE_READ_DATA; 6796 6797 /* Create a dummy uio structure */ 6798 afp_uio = uio_create(1, 0, UIO_SYSSPACE, UIO_READ); 6799 if (afp_uio) 6800 error = uio_addiov( afp_uio, CAST_USER_ADDR_T(afpinfo), sizeof(afpinfo)); 6801 else 6802 error = ENOMEM; 6803 if (error) 6804 goto exit; 6805 6806 /* Now set the default afp info buffer */ 6807 DefaultFillAfpInfo(afpinfo); 6808 6809 /* Open and read the data in, if an empty file we will still get an fid */ 6810 error = smbfs_smb_openread(share, np, 6811 &fid, rights, 6812 afp_uio, &sizep, sfmname, 6813 &ts, ap->a_context); 6814 6815 SMB_LOG_KTRACE(SMB_DBG_SET_XATTR | DBG_FUNC_NONE, 6816 0xabc001, error, stype, 0, 0); 6817 6818 /* Replace the finder info with the data that was passed down. */ 6819 if (!error) { 6820 bcopy((void *)finfo, (void *)&afpinfo[AFP_INFO_FINDER_OFFSET], len); 6821 uio_reset(afp_uio, 0, UIO_SYSSPACE, UIO_WRITE ); 6822 error = uio_addiov( afp_uio, CAST_USER_ADDR_T(afpinfo), sizeof(afpinfo)); 6823 } 6824 if (error) 6825 goto out; 6826 6827 /* Truncate the stream if there is anything in it, this will wake up SFM */ 6828 if (sizep && (VTOSMBFS(vp)->sm_flags & MNT_IS_SFM_VOLUME)) { 6829 /* Ignore any errors, write will catch them */ 6830 (void)smbfs_smb_seteof(share, fid, 0, ap->a_context); 6831 } 6832 6833 /* Now we can write the afp info back out with the new finder information */ 6834 if (!error) { 6835 error = smb_smb_write(share, fid, afp_uio, 0, ap->a_context); 6836 SMB_LOG_KTRACE(SMB_DBG_SET_XATTR | DBG_FUNC_NONE, 6837 0xabc002, error, stype, 0, 0); 6838 } 6839 6840 /* 6841 * Try to set the modify time back to the original time, ignore any 6842 * errors. Since we are using the open stream file descriptor to change 6843 * the time remove the directory attribute bit if set. 6844 */ 6845 (void)smbfs_smb_setfattrNT(share, (np->n_dosattr & ~SMB_EFA_DIRECTORY), 6846 fid, NULL, &ts, NULL, ap->a_context); 6847 /* Reset our cache timer and copy the new data into our cache */ 6848 if (!error) { 6849 nanouptime(&ts); 6850 np->finfo_cache_timer = ts.tv_sec; 6851 bcopy((void *)&afpinfo[AFP_INFO_FINDER_OFFSET], np->finfo, 6852 sizeof(np->finfo)); 6853 } 6854 goto out; 6855 } 6856 6857 switch(ap->a_options & (XATTR_CREATE | XATTR_REPLACE)) { 6858 case XATTR_CREATE: /* set the value, fail if attr already exists */ 6859 /* if exists fail else create it */ 6860 open_disp = FILE_CREATE; 6861 break; 6862 case XATTR_REPLACE: /* set the value, fail if attr does not exist */ 6863 /* if exists overwrite item else fail */ 6864 open_disp = FILE_OVERWRITE; 6865 break; 6866 default: 6867 if ((stype & kResourceFrk) == kResourceFrk) { 6868 /* if resource fork then if it exists open it else create it */ 6869 open_disp = FILE_OPEN_IF; 6870 } else { 6871 /* if anything else then if it exists overwrite it else create it */ 6872 open_disp = FILE_OVERWRITE_IF; 6873 } 6874 break; 6875 } 6876 6877 /* Open/create the stream */ 6878 error = smbfs_smb_create(share, np, sfmname, 6879 strnlen(sfmname, share->ss_maxfilenamelen+1), 6880 rights, &fid, open_disp, 1, &fattr, ap->a_context); 6881 SMB_LOG_KTRACE(SMB_DBG_SET_XATTR | DBG_FUNC_NONE, 6882 0xabc003, error, stype, 0, 0); 6883 if (error) { 6884 goto exit; 6885 } 6886 6887 /* Now write out the stream data */ 6888 error = smb_smb_write(share, fid, ap->a_uio, 0, ap->a_context); 6889 SMB_LOG_KTRACE(SMB_DBG_SET_XATTR | DBG_FUNC_NONE, 6890 0xabc004, error, stype, 0, 0); 6891 6892 /* 6893 * %%% 6894 * Should we reset the modify time back to the original time? Never for the 6895 * resource fork, but what about EAs? Could be a performance issue, really 6896 * need a clearer message from the rest of the file system team. 6897 * 6898 * For now try to set the modify time back to the original time, ignore any 6899 * errors. Since we are using the open stream file descriptor to change the 6900 * time remove the directory attribute bit if set. 6901 */ 6902 if ((stype & kResourceFrk) != kResourceFrk) { 6903 (void)smbfs_smb_setfattrNT(share, (np->n_dosattr & ~SMB_EFA_DIRECTORY), 6904 fid, NULL, &np->n_mtime, NULL, ap->a_context); 6905 } 6906 6907out: 6908 if (fid != 0) { 6909 (void)smbfs_smb_close(share, fid, ap->a_context); 6910 } 6911 6912exit: 6913 if (afp_uio) 6914 uio_free(afp_uio); 6915 6916 if (error == ENOENT) 6917 error = ENOATTR; 6918 6919 /* Check to see if its a normal error */ 6920 if (error && (error != ENOTSUP) && (error != ENOATTR)) { 6921 lck_rw_lock_shared(&np->n_name_rwlock); 6922 SMBWARNING("error %d %s:%s\n", error, np->n_name, ap->a_name); 6923 lck_rw_unlock_shared(&np->n_name_rwlock); 6924 6925 /* Always make sure its a legit error, see man listxattr */ 6926 if ((error != EROFS) && (error != EPERM) && (error != EINVAL) && 6927 (error != ENOTDIR) && (error != EACCES) && (error != ELOOP) && 6928 (error != EFAULT) && (error != EIO) && (error != ENAMETOOLONG) && 6929 (error != EEXIST) && (error != ERANGE) && 6930 (error != E2BIG) && (error != ENOSPC)) 6931 error = EIO; /* Not sure what else to do here */ 6932 } 6933 if (!error) { 6934 /* We create a named stream, so remove the no stream flag */ 6935 np->n_fstatus &= ~kNO_SUBSTREAMS; 6936 } 6937 smb_share_rele(share, ap->a_context); 6938 smbnode_unlock(np); 6939 6940 SMB_LOG_KTRACE(SMB_DBG_SET_XATTR | DBG_FUNC_END, error, 0, 0, 0, 0); 6941 return (error); 6942} 6943 6944/* 6945 * smbfs_vnop_listxattr 6946 * 6947 * vnode_t a_vp; 6948 * uio_t a_uio; 6949 * size_t *a_size; 6950 * int32_t a_options; 6951 * vfs_context_t a_context; 6952 */ 6953static int 6954smbfs_vnop_listxattr(struct vnop_listxattr_args *ap) 6955{ 6956 vnode_t vp = ap->a_vp; 6957 uio_t uio = ap->a_uio; 6958 size_t *sizep = ap->a_size; 6959 struct smbnode *np = NULL; 6960 struct smb_share *share = NULL; 6961 int error = 0; 6962 uint32_t stream_flags = 0; 6963 enum vtype vnode_type = VREG; 6964 6965 DBG_ASSERT(!vnode_isnamedstream(vp)); 6966 6967 if ((error = smbnode_lock(VTOSMB(vp), SMBFS_EXCLUSIVE_LOCK))) 6968 return (error); 6969 6970 SMB_LOG_KTRACE(SMB_DBG_LIST_XATTR | DBG_FUNC_START, 0, 0, 0, 0, 0); 6971 6972 np = VTOSMB(vp); 6973 np->n_lastvop = smbfs_vnop_listxattr; 6974 share = smb_get_share_with_reference(VTOSMBFS(vp)); 6975 6976 /* 6977 * FILE_NAMED_STREAMS tells us the server supports streams. 6978 * NOTE: This flag may have been overwriten by us in smbfs_mount. The default 6979 * is for streams to be turn off. See the smbfs_mount for more details. 6980 */ 6981 if (!(share->ss_attributes & FILE_NAMED_STREAMS)) { 6982 error = ENOTSUP; 6983 goto exit; 6984 } 6985 6986 if (np->n_fstatus & kNO_SUBSTREAMS) { 6987 error = ENOATTR; 6988 goto exit; 6989 } 6990 6991 /* For listing xattrs, create is done on the item, not the stream */ 6992 if ((np) && (np->n_vnode)) { 6993 /* Use vnode to determine type */ 6994 vnode_type = vnode_isdir(np->n_vnode) ? VDIR : VREG; 6995 } 6996 6997 error = smbfs_smb_qstreaminfo(share, np, vnode_type, 6998 NULL, 0, 6999 NULL, 7000 uio, sizep, 7001 NULL, NULL, 7002 &stream_flags, NULL, 7003 ap->a_context); 7004 7005exit: 7006 /* 7007 * From the man pages: If no accessible extended attributes are associated 7008 * with the given path or fd, the function returns zero. 7009 */ 7010 if (error == ENOATTR) 7011 error = 0; 7012 7013 /* Check to see if its a normal error */ 7014 if (error && (error != ENOTSUP)) { 7015 lck_rw_lock_shared(&np->n_name_rwlock); 7016 SMBWARNING("error %d %s\n", error, np->n_name); 7017 lck_rw_unlock_shared(&np->n_name_rwlock); 7018 7019 /* Always make sure its a legit error, see man listxattr */ 7020 if ((error != ERANGE) && (error != EPERM) && (error != EINVAL) && 7021 (error != ENOTDIR) && (error != EACCES) && (error != ELOOP) && 7022 (error != EFAULT) && (error != EIO)) 7023 error = 0; /* Just pretend it doesn't exist */ 7024 } 7025 smb_share_rele(share, ap->a_context); 7026 smbnode_unlock(np); 7027 7028 SMB_LOG_KTRACE(SMB_DBG_LIST_XATTR | DBG_FUNC_END, error, 0, 0, 0, 0); 7029 return (error); 7030} 7031 7032/* 7033 * vnop_removexattr_args 7034 * 7035 * vnode_t a_vp; 7036 * int8_t * a_name; 7037 * int32_t a_options; 7038 * vfs_context_t a_context; 7039 */ 7040static int 7041smbfs_vnop_removexattr(struct vnop_removexattr_args *ap) 7042{ 7043 vnode_t vp = ap->a_vp; 7044 const char *sfmname; 7045 int error = 0, saved_error = 0; 7046 struct smbnode *np = NULL; 7047 struct smb_share *share = NULL; 7048 enum stream_types stype = kNoStream; 7049 struct timespec ts; 7050 7051 DBG_ASSERT(!vnode_isnamedstream(vp)); 7052 7053 if ((error = smbnode_lock(VTOSMB(vp), SMBFS_EXCLUSIVE_LOCK))) 7054 return (error); 7055 7056 SMB_LOG_KTRACE(SMB_DBG_RM_XATTR | DBG_FUNC_START, 0, 0, 0, 0, 0); 7057 7058 np = VTOSMB(vp); 7059 np->n_lastvop = smbfs_vnop_removexattr; 7060 share = smb_get_share_with_reference(VTOSMBFS(vp)); 7061 /* 7062 * FILE_NAMED_STREAMS tells us the server supports streams. 7063 * NOTE: This flag may have been overwriten by us in smbfs_mount. The default 7064 * is for streams to be turn off. See the smbfs_mount for more details. 7065 */ 7066 if (!(share->ss_attributes & FILE_NAMED_STREAMS)) { 7067 error = ENOTSUP; 7068 goto exit; 7069 } 7070 7071 /* SMB doesn't support having a slash in the xattr name */ 7072 if (strchr(ap->a_name, '/')) { 7073 error = EINVAL; 7074 7075 lck_rw_lock_shared(&np->n_name_rwlock); 7076 SMBWARNING("Slash in xattr name not allowed: error %d %s:%s\n", error, 7077 np->n_name, ap->a_name); 7078 lck_rw_unlock_shared(&np->n_name_rwlock); 7079 goto exit; 7080 } 7081 7082 sfmname = xattr2sfm(ap->a_name, &stype); 7083 if (!sfmname) { 7084 error = EINVAL; 7085 goto exit; 7086 } 7087 7088 if (stype & kFinderInfo) { 7089 if (VTOSMBFS(vp)->sm_flags & MNT_IS_SFM_VOLUME) { 7090 /* 7091 * We do not allow them to remove the finder info stream on SFM 7092 * Volume. It could hold other information used by SFM. 7093 */ 7094 error = ENOTSUP; 7095 } 7096 else { 7097 /* 7098 * If the volume is just a normal NTFS Volume then deleting the named 7099 * stream should be ok, but some servers (EMC) don't support deleting 7100 * the named stream. In this case see if we can just zero out the 7101 * finder info. 7102 * 7103 * Streams are always VREG since they are files 7104 */ 7105 error = smbfs_smb_delete(share, np, VREG, 7106 sfmname, strnlen(sfmname, share->ss_maxfilenamelen+1), 7107 1, ap->a_context); 7108 SMB_LOG_KTRACE(SMB_DBG_RM_XATTR | DBG_FUNC_NONE, 7109 0xabc001, error, stype, 0, 0); 7110 } 7111 7112 /* SFM server or the server doesn't support deleting named streams */ 7113 if (error) { 7114 uio_t afp_uio = NULL; 7115 uint8_t afpinfo[60]; 7116 SMBFID fid = 0; 7117 uint32_t rights = SMB2_FILE_WRITE_DATA | SMB2_FILE_READ_DATA | SMB2_FILE_WRITE_ATTRIBUTES; 7118 7119 /* 7120 * Either a SFM volume or the server doesn't support deleting named 7121 * streams. Try to zero out the finder info data. 7122 */ 7123 saved_error = error; /* save original failure error */ 7124 7125 afp_uio = uio_create(1, 0, UIO_SYSSPACE, UIO_READ); 7126 if (!afp_uio) { 7127 error = saved_error; 7128 goto exit; 7129 } 7130 error = uio_addiov( afp_uio, CAST_USER_ADDR_T(afpinfo), sizeof(afpinfo)); 7131 if (error) { 7132 uio_free(afp_uio); 7133 error = saved_error; 7134 goto exit; 7135 } 7136 7137 /* open and read the data */ 7138 error = smbfs_smb_openread(share, np, 7139 &fid, rights, 7140 afp_uio, NULL, sfmname, 7141 &ts, ap->a_context); 7142 SMB_LOG_KTRACE(SMB_DBG_RM_XATTR | DBG_FUNC_NONE, 7143 0xabc002, error, stype, 0, 0); 7144 7145 /* clear out the finder info data */ 7146 bzero(&afpinfo[AFP_INFO_FINDER_OFFSET], FINDERINFOSIZE); 7147 7148 if (!error) { 7149 /* truncate the stream, this will wake up SFM */ 7150 error = smbfs_smb_seteof(share, fid, 0, ap->a_context); 7151 } 7152 7153 /* Reset our uio */ 7154 if (!error) { 7155 uio_reset(afp_uio, 0, UIO_SYSSPACE, UIO_WRITE ); 7156 error = uio_addiov( afp_uio, CAST_USER_ADDR_T(afpinfo), sizeof(afpinfo)); 7157 } 7158 7159 if (!error) { 7160 error = smb_smb_write(share, fid, afp_uio, 0, ap->a_context); 7161 SMB_LOG_KTRACE(SMB_DBG_RM_XATTR | DBG_FUNC_NONE, 7162 0xabc003, error, stype, 0, 0); 7163 } 7164 7165 if (error) { 7166 error = saved_error; /* restore original error */ 7167 } 7168 7169 /* Try to set the modify time back to the original time, ignore any errors */ 7170 (void)smbfs_smb_setfattrNT(share, (np->n_dosattr & ~SMB_EFA_DIRECTORY), fid, NULL, &ts, 7171 NULL, ap->a_context); 7172 if (fid != 0) 7173 (void)smbfs_smb_close(share, fid, ap->a_context); 7174 if (afp_uio) { 7175 uio_free(afp_uio); 7176 } 7177 } 7178 } 7179 else { 7180 /* Streams are always VREG since they are files */ 7181 error = smbfs_smb_delete(share, np, VREG, 7182 sfmname, strnlen(sfmname, share->ss_maxfilenamelen+1), 7183 1, ap->a_context); 7184 SMB_LOG_KTRACE(SMB_DBG_RM_XATTR | DBG_FUNC_NONE, 7185 0xabc004, error, stype, 0, 0); 7186 } 7187 7188 /* Finder info so reset our cache timer and zero out our cache */ 7189 if ((stype & kFinderInfo) && !error) { 7190 nanouptime(&ts); 7191 np->finfo_cache_timer = ts.tv_sec; 7192 bzero(np->finfo, sizeof(np->finfo)); 7193 } 7194 7195exit: 7196 if (error == ENOENT) 7197 error = ENOATTR; 7198 7199 /* Check to see if its a normal error */ 7200 if (error && (error != ENOTSUP) && (error != ENOATTR)) { 7201 lck_rw_lock_shared(&np->n_name_rwlock); 7202 SMBWARNING("error %d %s:%s\n", error, np->n_name, ap->a_name); 7203 lck_rw_unlock_shared(&np->n_name_rwlock); 7204 7205 /* Always make sure its a legit error, see man listxattr */ 7206 if ((error != EROFS) && (error != EPERM) && (error != EINVAL) && 7207 (error != ENOTDIR) && (error != EACCES) && (error != ELOOP) && 7208 (error != EFAULT) && (error != EIO) && (error != ENAMETOOLONG)) 7209 error = ENOATTR; /* Not sure what else to do here */ 7210 } 7211 smb_share_rele(share, ap->a_context); 7212 smbnode_unlock(np); 7213 7214 SMB_LOG_KTRACE(SMB_DBG_RM_XATTR | DBG_FUNC_END, error, 0, 0, 0, 0); 7215 return (error); 7216} 7217 7218/* 7219 * smbfs_vnop_getxattr 7220 * 7221 * vnode_t a_vp; 7222 * int8_t * a_name; 7223 * uio_t a_uio; 7224 * size_t *a_size; 7225 * int32_t a_options; 7226 * vfs_context_t a_context; 7227 */ 7228static int 7229smbfs_vnop_getxattr(struct vnop_getxattr_args *ap) 7230{ 7231 vnode_t vp = ap->a_vp; 7232 const char *sfmname; 7233 uio_t uio = ap->a_uio; 7234 size_t *sizep = ap->a_size; 7235 SMBFID fid = 0; 7236 int error = 0; 7237 struct smbnode *np = NULL; 7238 struct smb_share *share = NULL; 7239 size_t rq_resid = (uio) ? (size_t)uio_resid(uio) : 0; 7240 uio_t afp_uio = NULL; 7241 enum stream_types stype = kNoStream; 7242 struct timespec ts; 7243 time_t attrtimeo; 7244 uint32_t stream_flags = 0; 7245 int use_cached_data = 0; 7246 uint64_t strmsize = 0; 7247 uint64_t strm_alloc_size = 0; 7248 size_t afpsize = 0; 7249 uint8_t afpinfo[60]; 7250 enum vtype vnode_type = VREG; /* Streams are always files */ 7251 7252 DBG_ASSERT(!vnode_isnamedstream(vp)); 7253 7254 if ((error = smbnode_lock(VTOSMB(vp), SMBFS_EXCLUSIVE_LOCK))) 7255 return (error); 7256 7257 7258 SMB_LOG_KTRACE(SMB_DBG_GET_XATTR | DBG_FUNC_START, 0, 0, 0, 0, 0); 7259 7260 np = VTOSMB(vp); 7261 np->n_lastvop = smbfs_vnop_getxattr; 7262 share = smb_get_share_with_reference(VTOSMBFS(vp)); 7263 7264 /* 7265 * FILE_NAMED_STREAMS tells us the server supports streams. 7266 * NOTE: This flag may have been overwriten by us in smbfs_mount. The default 7267 * is for streams to be turn off. See the smbfs_mount for more details. 7268 */ 7269 if (!(share->ss_attributes & FILE_NAMED_STREAMS)) { 7270 error = ENOTSUP; 7271 goto exit; 7272 } 7273 7274 /* SMB doesn't support having a slash in the xattr name */ 7275 if (strchr(ap->a_name, '/')) { 7276 error = ENOTSUP; 7277 lck_rw_lock_shared(&np->n_name_rwlock); 7278 SMBWARNING("Slash in xattr name not allowed: error %d %s:%s\n", error, 7279 np->n_name, ap->a_name); 7280 lck_rw_unlock_shared(&np->n_name_rwlock); 7281 goto exit; 7282 } 7283 if (np->n_fstatus & kNO_SUBSTREAMS) { 7284 error = ENOATTR; 7285 goto exit; 7286 } 7287 7288 sfmname = xattr2sfm(ap->a_name, &stype); 7289 if (!sfmname) { 7290 error = EINVAL; 7291 goto exit; 7292 } 7293 7294 /* 7295 * They just want the size of the stream. */ 7296 if ((uio == NULL) && !(stype & kFinderInfo)) { 7297 if (stype & kResourceFrk) { 7298 error = smb_get_rsrcfrk_size(share, vp, ap->a_context); 7299 lck_mtx_lock(&np->rfrkMetaLock); 7300 /* The node's rfork size will have the correct value at this point */ 7301 strmsize = np->rfrk_size; 7302 lck_mtx_unlock(&np->rfrkMetaLock); 7303 } 7304 else { 7305 /* For listing xattrs, create is done on the item, not the stream */ 7306 if ((np) && (np->n_vnode)) { 7307 /* Use vnode to determine type */ 7308 vnode_type = vnode_isdir(np->n_vnode) ? VDIR : VREG; 7309 } 7310 7311 error = smbfs_smb_qstreaminfo(share, np, vnode_type, 7312 NULL, 0, 7313 sfmname, 7314 NULL, NULL, 7315 &strmsize, &strm_alloc_size, 7316 &stream_flags, NULL, 7317 ap->a_context); 7318 SMB_LOG_KTRACE(SMB_DBG_GET_XATTR | DBG_FUNC_NONE, 7319 0xabc001, error, stype, 0, 0); 7320 } 7321 if (sizep) 7322 *sizep = (size_t)strmsize; 7323 if (error) 7324 error = ENOATTR; 7325 goto exit; 7326 } 7327 7328 /* 7329 * We treat finder info differently than any other EA/Stream. Because of SFM 7330 * we need to do things a little different. Remember the AFPInfo stream has 7331 * more information in it than just the finder info. WARNING: SFM can get 7332 * very confused if you do not handle this correctly! 7333 */ 7334 if (stype & kFinderInfo) { 7335 /* If we are in reconnect, use cached data if we have it */ 7336 if (np->finfo_cache_timer != 0) { 7337 use_cached_data = (share->ss_flags & SMBS_RECONNECTING); 7338 } 7339 7340 /* Check to see if the cache has timed out */ 7341 SMB_CACHE_TIME(ts, np, attrtimeo); 7342 if (((ts.tv_sec - np->finfo_cache_timer) > attrtimeo) && 7343 !use_cached_data) { 7344 /* Cache has expired go get the finder information. */ 7345 afp_uio = uio_create(1, 0, UIO_SYSSPACE, UIO_READ); 7346 if (afp_uio) { 7347 error = uio_addiov( afp_uio, CAST_USER_ADDR_T(afpinfo), 7348 sizeof(afpinfo)); 7349 } 7350 else { 7351 error = ENOMEM; 7352 } 7353 7354 if (error) { 7355 goto exit; 7356 } 7357 7358 uio_setoffset(afp_uio, 0); 7359 7360 /* open and read the data */ 7361 if (SSTOVC(share)->vc_flags & SMBV_SMB2) { 7362 /* SMB 2/3 will do create/read/close */ 7363 error = smbfs_smb_openread(share, np, 7364 NULL, SMB2_FILE_READ_DATA, 7365 afp_uio, &afpsize, sfmname, 7366 NULL, ap->a_context); 7367 fid = 0; 7368 } 7369 else { 7370 /* SMB 1 will do create/read */ 7371 error = smbfs_smb_openread(share, np, 7372 &fid, SMB2_FILE_READ_DATA, 7373 afp_uio, &afpsize, sfmname, 7374 NULL, ap->a_context); 7375 } 7376 7377 SMB_LOG_KTRACE(SMB_DBG_GET_XATTR | DBG_FUNC_NONE, 7378 0xabc002, error, stype, 0, 0); 7379 7380 if ((error == ETIMEDOUT) && (np->finfo_cache_timer != 0)) { 7381 /* Just return the cached data */ 7382 error = 0; 7383 goto done; 7384 } 7385 7386 /* Should never happen but just in case */ 7387 if (afpsize != AFP_INFO_SIZE) { 7388 error = ENOENT; 7389 } 7390 7391 /* If ENOENT, return zero'd Finder Info, else return the info */ 7392 if (error == ENOENT) { 7393 bzero(np->finfo, sizeof(np->finfo)); 7394 } 7395 else { 7396 bcopy((void *)&afpinfo[AFP_INFO_FINDER_OFFSET], np->finfo, 7397 sizeof(np->finfo)); 7398 } 7399 7400 /* Cache the finder info as long as its not a copy in progress */ 7401 if (vnode_isreg(vp) && (bcmp(np->finfo, "brokMACS", 8) == 0)) { 7402 np->finfo_cache_timer = 0; 7403 SMBDEBUG("Don't cache finder info, we have a finder copy in progress\n"); 7404 } 7405 else { 7406 nanouptime(&ts); 7407 np->finfo_cache_timer = ts.tv_sec; 7408 } 7409 } 7410 7411done: 7412 /* If the finder info is all zero hide it, except if its a SFM volume */ 7413 if ((!(VTOSMBFS(vp)->sm_flags & MNT_IS_SFM_VOLUME)) && 7414 (bcmp(np->finfo, emptyfinfo, sizeof(emptyfinfo)) == 0)) { 7415 error = ENOENT; 7416 } 7417 7418 if (uio && !error) { 7419 error = uiomove((const char *)np->finfo, (int)sizeof(np->finfo), ap->a_uio); 7420 } 7421 7422 if (sizep && !error) 7423 *sizep = FINDERINFOSIZE; 7424 } 7425 else { 7426 error = smbfs_smb_openread(share, np, 7427 &fid, SMB2_FILE_READ_DATA, 7428 uio, sizep, sfmname, 7429 NULL, ap->a_context); 7430 SMB_LOG_KTRACE(SMB_DBG_GET_XATTR | DBG_FUNC_NONE, 7431 0xabc003, error, stype, 0, 0); 7432 } 7433 /* If ENOTSUP support is returned then do the open and read in two transactions. */ 7434 if (error != ENOTSUP) 7435 goto out; 7436 7437 /* 7438 * May need to add an oplock to this open call, if this is a finder info open. 7439 * Not sure I remember the exact details, something about deletes. 7440 */ 7441 error = smbfs_smb_open_xattr(share, np, SMB2_FILE_READ_DATA, 7442 NTCREATEX_SHARE_ACCESS_ALL, &fid, 7443 sfmname, sizep, ap->a_context); 7444 7445 SMB_LOG_KTRACE(SMB_DBG_GET_XATTR | DBG_FUNC_NONE, 7446 0xabc004, error, stype, 0, 0); 7447 if (error) 7448 goto exit; 7449 7450 /* 7451 * When reading finder-info, munge the uio so we read at offset 16 where the 7452 * actual finder info is located. Also ensure we don't read past the 32 bytes, 7453 * of finder info. Since we are just reading we really don't care about the 7454 * rest of the data. 7455 * This is only here in case a server does not support the chain message above. 7456 * We do not cache in this case. Should never happen, but just to be safe. 7457 */ 7458 if (stype & kFinderInfo) { 7459 user_ssize_t r; 7460 7461 if (sizep) 7462 *sizep = FINDERINFOSIZE; 7463 /* Just wanted the size get out */ 7464 if (uio == NULL) 7465 goto out; 7466 7467 r = uio_resid(uio); 7468 if (uio_offset(uio) >= FINDERINFOSIZE) { 7469 uio_setresid(uio, 0); 7470 } else if (uio_offset(uio) + r > FINDERINFOSIZE) 7471 uio_setresid(uio, FINDERINFOSIZE - uio_offset(uio)); 7472 r = r - uio_resid(uio); 7473 uio_setoffset(uio, uio_offset(uio) + 4*4); 7474 7475 error = smb_smb_read(share, fid, uio, ap->a_context); 7476 7477 uio_setoffset(uio, uio_offset(uio) - 4*4); 7478 uio_setresid(uio, uio_resid(uio) + r); 7479 } 7480 else { 7481 error = smb_smb_read(share, fid, uio, ap->a_context); 7482 } 7483 7484 SMB_LOG_KTRACE(SMB_DBG_GET_XATTR | DBG_FUNC_NONE, 7485 0xabc005, error, stype, 0, 0); 7486 7487out:; 7488 if (uio && sizep && (*sizep > rq_resid)) 7489 error = ERANGE; 7490 7491 /* Even an error can leave the file open. */ 7492 if (fid != 0) 7493 (void)smbfs_smb_close(share, fid, ap->a_context); 7494exit: 7495 /* 7496 * So ENOENT just means ENOATTR. 7497 * Note: SAMBA 4 will reutrn EISDIR for folders which is legit, but not 7498 * expected by the finder 7499 */ 7500 if ((error == ENOENT) || ((error == EISDIR) && (stype & kFinderInfo))) 7501 error = ENOATTR; 7502 7503 if (afp_uio) 7504 uio_free(afp_uio); 7505 7506 /* Check to see if its a normal error */ 7507 if (error && (error != ENOTSUP) && (error != ENOATTR)) { 7508 lck_rw_lock_shared(&np->n_name_rwlock); 7509 SMBWARNING("error %d %s:%s\n", error, np->n_name, ap->a_name); 7510 lck_rw_unlock_shared(&np->n_name_rwlock); 7511 7512 /* Nope make sure its a legit error, see man getxattr */ 7513 if ((error != ERANGE) && (error != EPERM) && (error != EINVAL) && 7514 (error != EISDIR) && (error != ENOTDIR) && (error != EACCES) && 7515 (error != ELOOP) && (error != EFAULT) && (error != EIO)) 7516 error = ENOATTR; 7517 } 7518 smb_share_rele(share, ap->a_context); 7519 smbnode_unlock(np); 7520 7521 SMB_LOG_KTRACE(SMB_DBG_GET_XATTR | DBG_FUNC_END, error, 0, 0, 0, 0); 7522 return (error); 7523} 7524 7525/* 7526 * smbfs_vnop_getnamedstream - Obtain the vnode for a stream. 7527 * 7528 * vnode_t a_vp; 7529 * vnode_t *a_svpp; 7530 * const char *a_name; 7531 enum nsoperation a_operation; (NS_OPEN, NS_CREATE, NS_DELETE) 7532 * vfs_context_t a_context; 7533 * 7534 */ 7535static int 7536smbfs_vnop_getnamedstream(struct vnop_getnamedstream_args* ap) 7537{ 7538 struct smb_share *share; 7539 vnode_t vp = ap->a_vp; 7540 vnode_t *svpp = ap->a_svpp; 7541 const char * streamname = ap->a_name; 7542 const char * sname = ap->a_name; 7543 struct smbnode *np = NULL; 7544 int error = 0; 7545 uint64_t strmsize = 0; 7546 uint64_t strm_alloc_size = 0; 7547 struct smbfattr fattr; 7548 struct vnode_attr vap; 7549 struct timespec ts; 7550 time_t attrtimeo; 7551 struct timespec reqtime; 7552 uint32_t stream_flags = 0; 7553 int use_cached_data = 0; 7554 enum vtype vnode_type = VREG; 7555 7556 /* Lock the parent while we look for the stream */ 7557 if ((error = smbnode_lock(VTOSMB(vp), SMBFS_EXCLUSIVE_LOCK))) 7558 return (error); 7559 7560 SMB_LOG_KTRACE(SMB_DBG_GET_NSTREAM | DBG_FUNC_START, 0, 0, 0, 0, 0); 7561 7562 nanouptime(&reqtime); 7563 np = VTOSMB(vp); 7564 np->n_lastvop = smbfs_vnop_getnamedstream; 7565 share = smb_get_share_with_reference(VTOSMBFS(vp)); 7566 7567 *svpp = NULL; 7568 /* Currently we only support the "com.apple.ResourceFork" stream. */ 7569 if (bcmp(streamname, XATTR_RESOURCEFORK_NAME, sizeof(XATTR_RESOURCEFORK_NAME)) != 0) { 7570 lck_rw_lock_shared(&np->n_name_rwlock); 7571 SMBDEBUG("Wrong stream %s:$%s\n", np->n_name, streamname); 7572 lck_rw_unlock_shared(&np->n_name_rwlock); 7573 7574 error = ENOATTR; 7575 goto exit; 7576 } else { 7577 sname = SFM_RESOURCEFORK_NAME; /* This is the resource stream use the SFM name */ 7578 } 7579 if ( !vnode_isreg(vp) ) { 7580 lck_rw_lock_shared(&np->n_name_rwlock); 7581 SMBDEBUG("%s not a file (EPERM)\n", np->n_name); 7582 lck_rw_unlock_shared(&np->n_name_rwlock); 7583 7584 error = EPERM; 7585 goto exit; 7586 } 7587 7588 /* 7589 * %%% 7590 * Since we have the parent node update its meta cache. Remember that 7591 * smbfs_getattr will check to see if the cache has expired. May want to 7592 * look at this and see how it affects performance. 7593 */ 7594 VATTR_INIT(&vap); /* Really don't care about the vap */ 7595 error = smbfs_getattr(share, vp, &vap, ap->a_context); 7596 if (error) { 7597 lck_rw_lock_shared(&np->n_name_rwlock); 7598 SMBERROR("%s lookup failed %d\n", np->n_name, error); 7599 lck_rw_unlock_shared(&np->n_name_rwlock); 7600 goto exit; 7601 } 7602 7603 /* 7604 * If we already have the stream vnode in our hash table and its cache timer 7605 * has not expired then just return we are done. 7606 */ 7607 if ((*svpp = smbfs_find_vgetstrm(VTOSMBFS(vp), np, sname, 7608 share->ss_maxfilenamelen)) != NULL) { 7609 /* If we are in reconnect, use cached data if we have it */ 7610 if (np->attribute_cache_timer != 0) { 7611 use_cached_data = (share->ss_flags & SMBS_RECONNECTING); 7612 } 7613 7614 VTOSMB(*svpp)->n_mtime = np->n_mtime; /* update the modify time */ 7615 7616 /* Check to see if the cache has timed out */ 7617 SMB_CACHE_TIME(ts, VTOSMB(*svpp), attrtimeo); 7618 if (((ts.tv_sec - VTOSMB(*svpp)->attribute_cache_timer) <= attrtimeo) || 7619 use_cached_data) { 7620 /* The cache is up to date, we are done */ 7621 goto exit; 7622 } 7623 } 7624 7625 if ((np) && (np->n_vnode)) { 7626 /* Use vnode to determine type */ 7627 vnode_type = vnode_isdir(np->n_vnode) ? VDIR : VREG; 7628 } 7629 7630 /* 7631 * Lookup the stream and get its size. This call will fail if the server 7632 * tells us the stream does not exist. 7633 * 7634 * NOTE1: If this is the resource stream then making this call will update 7635 * the the data fork node's resource size and its resource cache timer. 7636 * 7637 * NOTE2: SAMBA will not return the resource stream if the size is zero. 7638 * 7639 * NOTE3: We always try to create the stream on an open. Because of note two. 7640 * 7641 * If smbfs_smb_qstreaminfo returns an error and we do not have the stream 7642 * node in our hash table then it doesn't exist and they will have to create 7643 * it. 7644 * 7645 * If smbfs_smb_qstreaminfo returns an error and we do have the stream node 7646 * in our hash table then it could exist so just pretend that it does for 7647 * now. If they try to open it and it doesn't exist the open will create it. 7648 * 7649 * If smbfs_smb_qstreaminfo returns no error and we do have the stream node 7650 * in our hash table then just update its size and cache timers. 7651 * 7652 * If smbfs_smb_qstreaminfo returns no error and we do not have the stream 7653 * node in our hash table then create the stream node, using the data node 7654 * to fill in all information except the size. 7655 */ 7656 error = smbfs_smb_qstreaminfo(share, np, vnode_type, 7657 NULL, 0, 7658 sname, 7659 NULL, NULL, 7660 &strmsize, &strm_alloc_size, 7661 &stream_flags, NULL, 7662 ap->a_context); 7663 if (error && (*svpp == NULL)) { 7664 error = ENOATTR; 7665 goto exit; 7666 } 7667 7668 if ((error == ETIMEDOUT) && (np->attribute_cache_timer != 0)) { 7669 /* Just return the cached data */ 7670 error = 0; 7671 goto exit; 7672 } 7673 7674 /* 7675 * We already have the stream vnode. If it doesn't exist we will attempt to 7676 * create it on the open. In the SMB open you can say create it if it does 7677 * not exist. Reset the size if the above called failed then set the size to 7678 * zero. 7679 */ 7680 if (*svpp) { 7681 if (smbfs_update_size(VTOSMB(*svpp), &reqtime, strmsize) == TRUE) { 7682 /* Remember the only attribute for a stream is its size */ 7683 nanouptime(&ts); 7684 VTOSMB(*svpp)->attribute_cache_timer = ts.tv_sec; 7685 } 7686 goto exit; /* We have everything we need, so we are done */ 7687 } 7688 7689 bzero(&fattr, sizeof(fattr)); 7690 fattr.fa_vtype = VREG; /* Streams are always regular files */ 7691 fattr.fa_valid_mask |= FA_VTYPE_VALID; 7692 fattr.fa_size = strmsize; /* Fill in the stream size */ 7693 fattr.fa_data_alloc = 0; /* %%% not sure this really matters */ 7694 /* Now for the rest of the information we just use the data node information */ 7695 fattr.fa_attr = np->n_dosattr; 7696 fattr.fa_atime = np->n_atime; /* Access Time */ 7697 fattr.fa_chtime = np->n_chtime; /* Change Time */ 7698 fattr.fa_mtime = np->n_mtime; /* Modify Time */ 7699 fattr.fa_crtime = np->n_crtime; /* Create Time */ 7700 /* Stream inode number has same inode number as data node */ 7701 fattr.fa_ino = np->n_ino; 7702 nanouptime(&fattr.fa_reqtime); 7703 error = smbfs_vgetstrm(share, VTOSMBFS(vp), vp, svpp, &fattr, sname); 7704 7705exit: 7706 if (*svpp) 7707 smbnode_unlock(VTOSMB(*svpp)); /* We are done with the node unlock it. */ 7708 7709 if (error && (error != ENOATTR)) { 7710 lck_rw_lock_shared(&np->n_name_rwlock); 7711 SMBWARNING(" %s:$%s Original Stream name %s error = %d\n", np->n_name, 7712 sname, streamname, error); 7713 lck_rw_unlock_shared(&np->n_name_rwlock); 7714 } 7715 smb_share_rele(share, ap->a_context); 7716 smbnode_unlock(np); 7717 7718 SMB_LOG_KTRACE(SMB_DBG_GET_NSTREAM | DBG_FUNC_END, error, 0, 0, 0, 0); 7719 return (error); 7720} 7721 7722/* 7723 * smbfs_vnop_makenamedstream - Create a stream. 7724 * 7725 * vnode_t a_vp; 7726 * vnode_t *a_svpp; 7727 * const char *a_name; 7728 * vfs_context_t a_context; 7729 */ 7730static int 7731smbfs_vnop_makenamedstream(struct vnop_makenamedstream_args* ap) 7732{ 7733 struct smb_share *share; 7734 vnode_t vp = ap->a_vp; 7735 vnode_t *svpp = ap->a_svpp; 7736 const char * streamname = ap->a_name; 7737 struct smbnode *np = NULL; 7738 int error = 0; 7739 struct smbfattr fattr; 7740 struct timespec ts; 7741 int rsrcfrk = FALSE; 7742 size_t max_name_len; 7743 7744 /* Lock the parent while we create the stream */ 7745 if ((error = smbnode_lock(VTOSMB(vp), SMBFS_EXCLUSIVE_LOCK))) 7746 return (error); 7747 7748 SMB_LOG_KTRACE(SMB_DBG_MAKE_NSTREAM | DBG_FUNC_START, 0, 0, 0, 0, 0); 7749 7750 np = VTOSMB(vp); 7751 np->n_lastvop = smbfs_vnop_makenamedstream; 7752 share = smb_get_share_with_reference(VTOSMBFS(vp)); 7753 7754 *svpp = NULL; 7755 7756 /* Currently we only support the "com.apple.ResourceFork" stream. */ 7757 if (bcmp(streamname, XATTR_RESOURCEFORK_NAME, 7758 sizeof(XATTR_RESOURCEFORK_NAME)) != 0) { 7759 lck_rw_lock_shared(&np->n_name_rwlock); 7760 SMBDEBUG("Wrong stream %s:$%s\n", np->n_name, streamname); 7761 lck_rw_unlock_shared(&np->n_name_rwlock); 7762 7763 /* max_name_len = strnlen(streamname, share->ss_maxfilenamelen+1) */ 7764 error = ENOATTR; 7765 goto exit; 7766 } else { 7767 max_name_len = sizeof(XATTR_RESOURCEFORK_NAME); 7768 /* This is the resource stream use the SFM name */ 7769 streamname = SFM_RESOURCEFORK_NAME; 7770 } 7771 7772 if ( !vnode_isreg(vp) ) { 7773 lck_rw_lock_shared(&np->n_name_rwlock); 7774 SMBDEBUG("%s not a file (EPERM)\n", np->n_name); 7775 lck_rw_unlock_shared(&np->n_name_rwlock); 7776 7777 error = EPERM; 7778 goto exit; 7779 } 7780 7781 /* Now create the stream, sending a null fid pointer will cause it to be closed */ 7782 error = smbfs_smb_create(share, np, streamname, max_name_len, 7783 SMB2_FILE_WRITE_DATA, NULL, 7784 FILE_OPEN_IF, 1, &fattr, ap->a_context); 7785 if (error) 7786 goto exit; 7787 7788 /* We create a named stream, so remove the no stream flag */ 7789 np->n_fstatus &= ~kNO_SUBSTREAMS; 7790 7791 /* Stream inode number has same inode number as data node */ 7792 fattr.fa_ino = np->n_ino; 7793 7794 error = smbfs_vgetstrm(share, VTOSMBFS(vp), vp, svpp, &fattr, streamname); 7795 if (error == 0) { 7796 if (rsrcfrk) /* Update the data nodes resource size */ { 7797 lck_mtx_lock(&np->rfrkMetaLock); 7798 np->rfrk_size = fattr.fa_size; 7799 /* assume alloc size is the same */ 7800 np->rfrk_alloc_size = fattr.fa_size; 7801 nanouptime(&ts); 7802 np->rfrk_cache_timer = ts.tv_sec; 7803 lck_mtx_unlock(&np->rfrkMetaLock); 7804 } 7805 smbnode_unlock(VTOSMB(*svpp)); /* Done with the smbnode unlock it. */ 7806 } 7807 7808exit: 7809 if (error) { 7810 lck_rw_lock_shared(&np->n_name_rwlock); 7811 SMBWARNING(" %s:$%s error = %d\n", np->n_name, streamname, error); 7812 lck_rw_unlock_shared(&np->n_name_rwlock); 7813 } 7814 7815 smb_share_rele(share, ap->a_context); 7816 smbnode_unlock(np); 7817 7818 SMB_LOG_KTRACE(SMB_DBG_MAKE_NSTREAM | DBG_FUNC_END, error, 0, 0, 0, 0); 7819 return (error); 7820} 7821 7822/* 7823 * smbfs_vnop_removenamedstream - Remove a stream. 7824 * 7825 * vnode_t a_vp; 7826 * vnode_t a_svpp; 7827 * const char *a_name; 7828 * vfs_context_t a_context; 7829 */ 7830static int 7831smbfs_vnop_removenamedstream(struct vnop_removenamedstream_args* ap) 7832{ 7833 vnode_t vp = ap->a_vp; 7834 vnode_t svp = ap->a_svp; 7835 const char * streamname = ap->a_name; 7836 struct smbnode *np = NULL; 7837 int error = 0; 7838 size_t max_name_len; 7839 struct smb_share *share = NULL; 7840 7841 7842 /* Lock the parent and stream while we delete the stream*/ 7843 if ((error = smbnode_lockpair(VTOSMB(vp), VTOSMB(svp), SMBFS_EXCLUSIVE_LOCK))) 7844 return (error); 7845 7846 SMB_LOG_KTRACE(SMB_DBG_RM_NSTREAM | DBG_FUNC_START, 0, 0, 0, 0, 0); 7847 7848 np = VTOSMB(svp); 7849 np->n_lastvop = smbfs_vnop_removenamedstream; 7850 share = smb_get_share_with_reference(VTOSMBFS(vp)); 7851 7852 /* Currently we only support the "com.apple.ResourceFork" stream. */ 7853 if (bcmp(streamname, XATTR_RESOURCEFORK_NAME, sizeof(XATTR_RESOURCEFORK_NAME)) != 0) { 7854 lck_rw_lock_shared(&np->n_name_rwlock); 7855 SMBDEBUG("Wrong stream %s:$%s\n", np->n_name, streamname); 7856 lck_rw_unlock_shared(&np->n_name_rwlock); 7857 7858 /* max_name_len = strnlen(streamname, share->ss_maxfilenamelen+1) */ 7859 error = ENOATTR; 7860 goto exit; 7861 } 7862 else { 7863 max_name_len = sizeof(XATTR_RESOURCEFORK_NAME); 7864 /* This is the resource stream use the SFM name */ 7865 streamname = SFM_RESOURCEFORK_NAME; 7866 } 7867 7868 if ( !vnode_isreg(vp) ) { 7869 lck_rw_lock_shared(&np->n_name_rwlock); 7870 SMBDEBUG("%s not a file (EPERM)\n", np->n_name); 7871 lck_rw_unlock_shared(&np->n_name_rwlock); 7872 7873 error = EPERM; 7874 goto exit; 7875 } 7876 7877 /* Streams are always VREG since they are files */ 7878 error = smbfs_smb_delete(share, np, VREG, 7879 streamname, max_name_len, 7880 TRUE, ap->a_context); 7881 if (!error) 7882 smb_vhashrem(np); 7883exit: 7884 if (error) { 7885 lck_rw_lock_shared(&np->n_name_rwlock); 7886 SMBWARNING(" %s:$%s error = %d\n", np->n_name, streamname, error); 7887 lck_rw_unlock_shared(&np->n_name_rwlock); 7888 } 7889 7890 smb_share_rele(share, ap->a_context); 7891 smbnode_unlockpair(VTOSMB(vp), VTOSMB(svp)); 7892 7893 SMB_LOG_KTRACE(SMB_DBG_RM_NSTREAM | DBG_FUNC_END, error, 0, 0, 0, 0); 7894 return (error); 7895} 7896 7897/* 7898 * smbfs_vnop_monitor - Monitor an item. 7899 * 7900 * vnode_t a_vp; 7901 * uint32_t a_unused_events; - not used currently 7902 * uint32_t a_flags; 7903 * VNODE_MONITOR_BEGIN - setup notfication 7904 * VNODE_MONITOR_END - remove notfication 7905 * VNODE_MONITOR_UPDATE - change 7906 * void *a_handle; 7907 * struct knote * 7908 * vfs_context_t a_context; 7909 * 7910 */ 7911static int 7912smbfs_vnop_monitor(struct vnop_monitor_args *ap) 7913{ 7914 struct smbnode *np; 7915 struct smb_share *share = NULL; 7916 int error = 0; 7917 int releaseLock = TRUE; 7918 7919 /* Currently we only support directories */ 7920 if (! vnode_isdir(ap->a_vp)) { 7921 lck_rw_lock_shared(&VTOSMB(ap->a_vp)->n_name_rwlock); 7922 SMBDEBUG("%s is not a directory (ENOTSUP): node type = 0x%0x a_events = 0x%x, a_flags = 0x%x, a_handle = %p\n", 7923 VTOSMB(ap->a_vp)->n_name, vnode_vtype(ap->a_vp), 7924 ap->a_events, ap->a_flags, ap->a_handle); 7925 lck_rw_unlock_shared(&VTOSMB(ap->a_vp)->n_name_rwlock); 7926 return ENOTSUP; 7927 } 7928 7929 if ((error = smbnode_lock(VTOSMB(ap->a_vp), SMBFS_EXCLUSIVE_LOCK))) 7930 return (error); 7931 7932 SMB_LOG_KTRACE(SMB_DBG_MONITOR | DBG_FUNC_START, ap->a_flags, 0, 0, 0, 0); 7933 7934 np = VTOSMB(ap->a_vp); 7935 np->n_lastvop = smbfs_vnop_monitor; 7936 share = smb_get_share_with_reference(VTOSMBFS(ap->a_vp)); 7937 7938 lck_rw_lock_shared(&np->n_name_rwlock); 7939 SMBDEBUG("%s a_events = 0x%x, a_flags = 0x%x, a_handle = %p\n", 7940 np->n_name, ap->a_events, ap->a_flags, ap->a_handle); 7941 lck_rw_unlock_shared(&np->n_name_rwlock); 7942 7943 switch (ap->a_flags) { 7944 case VNODE_MONITOR_BEGIN: 7945 error = smbfs_start_change_notify(share, np, ap->a_context, 7946 &releaseLock); 7947 break; 7948 case VNODE_MONITOR_END: 7949 error = smbfs_stop_change_notify(share, np, FALSE, ap->a_context, 7950 &releaseLock); 7951 break; 7952 case VNODE_MONITOR_UPDATE: /* We no longer get called to update */ 7953 default: 7954 error = ENOTSUP; 7955 break; 7956 } 7957 smb_share_rele(share, ap->a_context); 7958 if (releaseLock) 7959 smbnode_unlock(VTOSMB(ap->a_vp)); 7960 7961 SMB_LOG_KTRACE(SMB_DBG_MONITOR | DBG_FUNC_END, error, 0, 0, 0, 0); 7962 return error; 7963} 7964 7965/* 7966 * smbfs_vnop_access - Check for access 7967 * 7968 * vnode_t a_vp; 7969 * int32_t a_action; 7970 * vfs_context_t a_context; 7971 * 7972 */ 7973static int 7974smbfs_vnop_access(struct vnop_access_args *ap) 7975{ 7976 vnode_t vp = ap->a_vp; 7977 int32_t action = ap->a_action, write_rights; 7978 vfs_context_t context = ap->a_context; 7979 kauth_cred_t cred = vfs_context_ucred(context); 7980 struct smbmount *smp = VTOSMBFS(vp); 7981 struct smb_share *share; 7982 uint32_t maxAccessRights; 7983 int error = 0; 7984 7985 SMB_LOG_KTRACE(SMB_DBG_ACCESS | DBG_FUNC_START, action, 0, 0, 0, 0); 7986 7987 share = smb_get_share_with_reference(VTOSMBFS(vp)); 7988 /* 7989 * Not the root user, not the user that mounted the volume and the volume 7990 * wasn't mounted as guest then refuse all access. 7991 */ 7992 if ((vfs_context_suser(context) != 0) && 7993 (kauth_cred_getuid(cred) != smp->sm_args.uid) && 7994 !SMBV_HAS_GUEST_ACCESS(SSTOVC(share))) { 7995 lck_rw_lock_shared(&VTOSMB(vp)->n_name_rwlock); 7996 SMB_LOG_ACCESS("%d not authorized to access %s : action = 0x%x\n", 7997 kauth_cred_getuid(cred), VTOSMB(vp)->n_name, action); 7998 lck_rw_unlock_shared(&VTOSMB(vp)->n_name_rwlock); 7999 8000 error = EACCES; 8001 goto done; 8002 } 8003 8004 /* 8005 * If KAUTH_VNODE_ACCESS is not set then this is an authoritative request, 8006 * we can't answer those correctly so always grant access. Now if they are 8007 * asking about excute we should do some extra checking. If we have excute or 8008 * read access then grant it otherwise fail the access request. 8009 */ 8010 if (((action & KAUTH_VNODE_ACCESS) != KAUTH_VNODE_ACCESS) && 8011 (((action & KAUTH_VNODE_EXECUTE) != KAUTH_VNODE_EXECUTE) || 8012 (!vnode_isreg(vp)))) { 8013 goto done; 8014 } 8015 8016 /* Deal with the immutable bit, never allow write, delete or security changes. */ 8017 write_rights = KAUTH_VNODE_WRITE_RIGHTS; 8018 /* Allow them to change the immutable, if they own it, we always allow */ 8019 write_rights &= ~(KAUTH_VNODE_WRITE_ATTRIBUTES | KAUTH_VNODE_WRITE_EXTATTRIBUTES); 8020 /* Remove this one, we allow access if its set */ 8021 write_rights &= ~KAUTH_VNODE_CHECKIMMUTABLE; 8022 if (node_isimmutable(share, vp, NULL) && (action & write_rights)) { 8023 lck_rw_lock_shared(&VTOSMB(vp)->n_name_rwlock); 8024 SMB_LOG_ACCESS("%s action = 0x%x %s denied\n", VTOSMB(vp)->n_name, action, 8025 vnode_isdir(vp) ? "IMMUTABLE_DIR" : "IMMUTABLE_FILE"); 8026 lck_rw_unlock_shared(&VTOSMB(vp)->n_name_rwlock); 8027 8028 error = EPERM; 8029 goto done; 8030 } 8031 8032 /* 8033 * Windows FAT file systems have no access check, so always grant access and 8034 * let the server make the final call. We could have some strange server that 8035 * supports ACLs on a FAT file system or has some kind of access model. See 8036 * FAT on a UNIX/Mac. In that case lets see if they are returning the correct 8037 * maximal access. 8038 */ 8039 if ((share->ss_fstype == SMB_FS_FAT) && 8040 ((share->ss_attributes & FILE_PERSISTENT_ACLS) != FILE_PERSISTENT_ACLS)) { 8041 SMB_LOG_ACCESS("FAT: Access call not supported by server\n"); 8042 goto done; 8043 } 8044 /* 8045 * We were mounted with guest access. 8046 * 8047 * 1. We turn off ACLs if mounted as guest. Without ACLs we can't determine 8048 * maximal access with Samba that includes our version. So in the samba 8049 * case we always ask the server for the check. 8050 * 2. Windows return us the correct maximal access, so we can return the 8051 * the correct value in that case. 8052 * 8053 */ 8054#ifdef SMB_DEBUG_ACCESS 8055 lck_rw_lock_shared(&VTOSMB(vp)->n_name_rwlock); 8056 if (SMBV_HAS_GUEST_ACCESS(SSTOVC(share))) { 8057 SMB_LOG_ACCESS("SMBV_GUEST_ACCESS: %s action = 0x%x\n", 8058 VTOSMB(vp)->n_name, action); 8059 } 8060 else { 8061 SMB_LOG_ACCESS("%s action = 0x%x\n", VTOSMB(vp)->n_name, action); 8062 } 8063 lck_rw_unlock_shared(&VTOSMB(vp)->n_name_rwlock); 8064#endif // SMB_DEBUG_ACCESS 8065 8066 /* 8067 * They are asking about a stream, how do we want to handle stream 8068 * nodes. Windows will return this in the open, but we would need to change 8069 * the open call to support getting it on stream.Streams have the same access 8070 * as the parent (data stream). So lets get the parent and return whatever 8071 * the parent supports. 8072 */ 8073 if (vnode_isnamedstream(vp)) { 8074 vnode_t parent_vp = vnode_getparent(vp); 8075 if (!parent_vp) 8076 return 0; /* Can't get the parent, let the server make the call */ 8077 maxAccessRights = smbfs_get_maximum_access(share, parent_vp, context); 8078 vnode_put(parent_vp); 8079 } else { 8080 maxAccessRights = smbfs_get_maximum_access(share, vp, context); 8081 } 8082 8083 /* KAUTH_VNODE_READ_DATA for files and KAUTH_VNODE_LIST_DIRECTORY for directories */ 8084 if ((action & KAUTH_VNODE_READ_DATA) && 8085 ((maxAccessRights & SMB2_FILE_READ_DATA) != SMB2_FILE_READ_DATA)) { 8086 lck_rw_lock_shared(&VTOSMB(vp)->n_name_rwlock); 8087 SMB_LOG_ACCESS("%s action = 0x%x %s denied\n", VTOSMB(vp)->n_name, action, 8088 vnode_isdir(vp) ? "KAUTH_VNODE_LIST_DIRECTORY" : "KAUTH_VNODE_READ_DATA"); 8089 lck_rw_unlock_shared(&VTOSMB(vp)->n_name_rwlock); 8090 8091 error = EACCES; 8092 goto done; 8093 } 8094 8095 /* KAUTH_VNODE_WRITE_DATA for files and KAUTH_VNODE_ADD_FILE for directories */ 8096 if ((action & KAUTH_VNODE_WRITE_DATA) && 8097 ((maxAccessRights & SMB2_FILE_WRITE_DATA) != SMB2_FILE_WRITE_DATA)) { 8098 lck_rw_lock_shared(&VTOSMB(vp)->n_name_rwlock); 8099 SMB_LOG_ACCESS("%s action = 0x%x %s denied\n", VTOSMB(vp)->n_name, action, 8100 vnode_isdir(vp) ? "KAUTH_VNODE_ADD_FILE" : "KAUTH_VNODE_WRITE_DATA"); 8101 lck_rw_unlock_shared(&VTOSMB(vp)->n_name_rwlock); 8102 8103 error = EACCES; 8104 goto done; 8105 } 8106 8107 /* KAUTH_VNODE_EXECUTE for files and KAUTH_VNODE_SEARCH for directories */ 8108 if (action & KAUTH_VNODE_EXECUTE) { 8109 if ((vnode_isdir(vp)) && 8110 ((maxAccessRights & SMB2_FILE_TRAVERSE) != SMB2_FILE_TRAVERSE) && 8111 ((maxAccessRights & SMB2_FILE_LIST_DIRECTORY) != SMB2_FILE_LIST_DIRECTORY)) { 8112 /* 8113 * See <rdar://problem/11151288> for more details, we use to require 8114 * SMB2_FILE_TRAVERSE for granting directory search access, but now 8115 * we also accept SMB2_FILE_LIST_DIRECTORY as well. 8116 */ 8117 lck_rw_lock_shared(&VTOSMB(vp)->n_name_rwlock); 8118 SMB_LOG_ACCESS("%s action = 0x%x KAUTH_VNODE_SEARCH denied\n", VTOSMB(vp)->n_name, action); 8119 lck_rw_unlock_shared(&VTOSMB(vp)->n_name_rwlock); 8120 8121 error = EACCES; 8122 goto done; 8123 } else if (!vnode_isdir(vp) && 8124 ((maxAccessRights & SMB2_FILE_EXECUTE) != SMB2_FILE_EXECUTE)) { 8125 /* 8126 * If this authoritative request and they have execute or read access 8127 * then grant the access. 8128 */ 8129 if (((action & KAUTH_VNODE_ACCESS) != KAUTH_VNODE_ACCESS) && 8130 ((maxAccessRights & SMB2_FILE_READ_DATA) == SMB2_FILE_READ_DATA)) { 8131 goto done; 8132 } 8133 8134 /* 8135 * See <rdar://problem/7327306> for more details, but we use to say 8136 * if the file had read access let them have execute access. Not sure 8137 * why I did that and it broke <rdar://problem/7327306> so removing 8138 * that check. 8139 */ 8140 lck_rw_lock_shared(&VTOSMB(vp)->n_name_rwlock); 8141 SMB_LOG_ACCESS("%s action = 0x%x SMB2_FILE_EXECUTE denied\n", 8142 VTOSMB(vp)->n_name, action); 8143 lck_rw_unlock_shared(&VTOSMB(vp)->n_name_rwlock); 8144 8145 error = EACCES; 8146 goto done; 8147 } 8148 } 8149 8150 if ((action & KAUTH_VNODE_DELETE) && 8151 ((maxAccessRights & SMB2_DELETE) != SMB2_DELETE)) { 8152 lck_rw_lock_shared(&VTOSMB(vp)->n_name_rwlock); 8153 SMB_LOG_ACCESS("%s action = 0x%x KAUTH_VNODE_DELETE denied\n", 8154 VTOSMB(vp)->n_name, action); 8155 lck_rw_unlock_shared(&VTOSMB(vp)->n_name_rwlock); 8156 8157 error = EACCES; 8158 goto done; 8159 } 8160 8161 /* KAUTH_VNODE_APPEND_DATA for files and KAUTH_VNODE_ADD_SUBDIRECTORY for directories */ 8162 if ((action & KAUTH_VNODE_APPEND_DATA) && 8163 ((maxAccessRights & SMB2_FILE_APPEND_DATA) != SMB2_FILE_APPEND_DATA)) { 8164 lck_rw_lock_shared(&VTOSMB(vp)->n_name_rwlock); 8165 SMB_LOG_ACCESS("%s action = 0x%x %s denied\n", VTOSMB(vp)->n_name, action, 8166 vnode_isdir(vp) ? "KAUTH_VNODE_ADD_SUBDIRECTORY" : "KAUTH_VNODE_APPEND_DATA"); 8167 lck_rw_unlock_shared(&VTOSMB(vp)->n_name_rwlock); 8168 8169 error = EACCES; 8170 goto done; 8171 } 8172 8173#ifdef SMB_DEBUG_ACCESS 8174 /* Need to look at this some more, seems Apple and MS don't argree on this SMB2_FILE_DELETE_CHILD */ 8175 if ((action & KAUTH_VNODE_DELETE_CHILD) && 8176 ((maxAccessRights & SMB2_FILE_DELETE_CHILD) != SMB2_FILE_DELETE_CHILD)) { 8177 lck_rw_lock_shared(&VTOSMB(vp)->n_name_rwlock); 8178 SMB_LOG_ACCESS("%s action = 0x%x 0x%x KAUTH_VNODE_DELETE_CHILD should denied\n", 8179 VTOSMB(vp)->n_name, action, KAUTH_VNODE_DELETE_CHILD); 8180 lck_rw_unlock_shared(&VTOSMB(vp)->n_name_rwlock); 8181 } 8182 /* 8183 * Need to look at this some more, seems Apple and MS don't argree on what 8184 * KAUTH_VNODE_READ_ATTRIBUTES allows and doesn't allow. Window still 8185 * allow us to get some meta data? 8186 */ 8187 if ((action & KAUTH_VNODE_READ_ATTRIBUTES) && 8188 ((maxAccessRights & SMB2_FILE_READ_ATTRIBUTES) != SMB2_FILE_READ_ATTRIBUTES)) { 8189 lck_rw_lock_shared(&VTOSMB(vp)->n_name_rwlock); 8190 SMB_LOG_ACCESS("%s action = 0x%x 0x%x KAUTH_VNODE_READ_ATTRIBUTES should denied\n", 8191 VTOSMB(vp)->n_name, action, KAUTH_VNODE_READ_ATTRIBUTES); 8192 lck_rw_unlock_shared(&VTOSMB(vp)->n_name_rwlock); 8193 } 8194#endif // SMB_DEBUG_ACCESS 8195 8196 if ((action & KAUTH_VNODE_WRITE_ATTRIBUTES) && 8197 ((maxAccessRights & SMB2_FILE_WRITE_ATTRIBUTES) != SMB2_FILE_WRITE_ATTRIBUTES)) { 8198 lck_rw_lock_shared(&VTOSMB(vp)->n_name_rwlock); 8199 SMB_LOG_ACCESS("%s action = 0x%x KAUTH_VNODE_WRITE_ATTRIBUTES denied\n", 8200 VTOSMB(vp)->n_name, action); 8201 lck_rw_unlock_shared(&VTOSMB(vp)->n_name_rwlock); 8202 8203 error = EACCES; 8204 goto done; 8205 } 8206 8207 if ((action & KAUTH_VNODE_READ_EXTATTRIBUTES) && 8208 ((maxAccessRights & SMB2_FILE_READ_ATTRIBUTES) != SMB2_FILE_READ_ATTRIBUTES)) { 8209 lck_rw_lock_shared(&VTOSMB(vp)->n_name_rwlock); 8210 SMB_LOG_ACCESS("%s action = 0x%x KAUTH_VNODE_READ_EXTATTRIBUTES denied\n", 8211 VTOSMB(vp)->n_name, action); 8212 lck_rw_unlock_shared(&VTOSMB(vp)->n_name_rwlock); 8213 8214 error = EACCES; 8215 goto done; 8216 } 8217 8218 if ((action & KAUTH_VNODE_WRITE_EXTATTRIBUTES) && 8219 ((maxAccessRights & SMB2_FILE_WRITE_ATTRIBUTES) != SMB2_FILE_WRITE_ATTRIBUTES)) { 8220 lck_rw_lock_shared(&VTOSMB(vp)->n_name_rwlock); 8221 SMB_LOG_ACCESS("%s action = 0x%x KAUTH_VNODE_WRITE_EXTATTRIBUTES denied\n", 8222 VTOSMB(vp)->n_name, action); 8223 lck_rw_unlock_shared(&VTOSMB(vp)->n_name_rwlock); 8224 8225 error = EACCES; 8226 goto done; 8227 } 8228 8229 if ((action & KAUTH_VNODE_READ_SECURITY) && 8230 ((maxAccessRights & SMB2_READ_CONTROL) != SMB2_READ_CONTROL)) { 8231 lck_rw_lock_shared(&VTOSMB(vp)->n_name_rwlock); 8232 SMB_LOG_ACCESS("%s action = 0x%x KAUTH_VNODE_READ_SECURITY denied\n", 8233 VTOSMB(vp)->n_name, action); 8234 lck_rw_unlock_shared(&VTOSMB(vp)->n_name_rwlock); 8235 8236 error = EACCES; 8237 goto done; 8238 } 8239 8240 /* Check to see if the share acls allow access */ 8241 if ((action & KAUTH_VNODE_WRITE_SECURITY) && 8242 ((share->maxAccessRights & SMB2_WRITE_DAC) != SMB2_WRITE_DAC)) { 8243 lck_rw_lock_shared(&VTOSMB(vp)->n_name_rwlock); 8244 SMB_LOG_ACCESS("%s action = 0x%x KAUTH_VNODE_WRITE_SECURITY denied by Share ACL\n", 8245 VTOSMB(vp)->n_name, action); 8246 lck_rw_unlock_shared(&VTOSMB(vp)->n_name_rwlock); 8247 8248 error = EACCES; 8249 goto done; 8250 } 8251 8252 /* Check to see if the share acls allow access */ 8253 if ((action & KAUTH_VNODE_TAKE_OWNERSHIP) && 8254 ((share->maxAccessRights & SMB2_WRITE_OWNER) != SMB2_WRITE_OWNER)) { 8255 lck_rw_lock_shared(&VTOSMB(vp)->n_name_rwlock); 8256 SMB_LOG_ACCESS("%s action = 0x%x SHARE KAUTH_VNODE_TAKE_OWNERSHIP by Share ACL\n", 8257 VTOSMB(vp)->n_name, action); 8258 lck_rw_unlock_shared(&VTOSMB(vp)->n_name_rwlock); 8259 8260 error = EACCES; 8261 goto done; 8262 } 8263 8264 if ((action & KAUTH_VNODE_WRITE_SECURITY) && 8265 ((maxAccessRights & SMB2_WRITE_DAC) != SMB2_WRITE_DAC)) { 8266 lck_rw_lock_shared(&VTOSMB(vp)->n_name_rwlock); 8267 SMB_LOG_ACCESS("%s action = 0x%x KAUTH_VNODE_WRITE_SECURITY denied\n", 8268 VTOSMB(vp)->n_name, action); 8269 lck_rw_unlock_shared(&VTOSMB(vp)->n_name_rwlock); 8270 8271 error = EACCES; 8272 goto done; 8273 } 8274 8275 if ((action & KAUTH_VNODE_TAKE_OWNERSHIP) && 8276 ((maxAccessRights & SMB2_WRITE_OWNER) != SMB2_WRITE_OWNER)) { 8277 lck_rw_lock_shared(&VTOSMB(vp)->n_name_rwlock); 8278 SMB_LOG_ACCESS("%s action = 0x%x KAUTH_VNODE_TAKE_OWNERSHIP denied\n", 8279 VTOSMB(vp)->n_name, action); 8280 lck_rw_unlock_shared(&VTOSMB(vp)->n_name_rwlock); 8281 8282 error = EACCES; 8283 goto done; 8284 } 8285 8286done: 8287 if (error) { 8288 lck_rw_lock_shared(&VTOSMB(vp)->n_name_rwlock); 8289 SMB_LOG_ACCESS("%s action = 0x%x denied\n", VTOSMB(vp)->n_name, action); 8290 lck_rw_unlock_shared(&VTOSMB(vp)->n_name_rwlock); 8291 } 8292 smb_share_rele(share, ap->a_context); 8293 8294 SMB_LOG_KTRACE(SMB_DBG_ACCESS | DBG_FUNC_END, error, 0, 0, 0, 0); 8295 return error; 8296} 8297 8298 8299/* 8300 * smbfs_vnop_allocate - 8301 * 8302 * vnode_t a_vp; 8303 * off_t a_length; 8304 * u_int32_t a_flags; 8305 * off_t *a_bytesallocated; 8306 * off_t a_offset; 8307 * vfs_context_t a_context; 8308 * 8309 */ 8310static int 8311smbfs_vnop_allocate(struct vnop_allocate_args *ap) 8312{ 8313 vnode_t vp = ap->a_vp; 8314 u_int64_t length = (u_int64_t)ap->a_length; 8315 struct smbnode *np; 8316 int32_t error = 0; 8317 SMBFID fid = 0; 8318 8319 *(ap->a_bytesallocated) = 0; 8320 8321 /* Preflight checks */ 8322 if (!vnode_isreg(vp)) { 8323 /* can only read regular files */ 8324 if (vnode_isdir(vp)) 8325 return (EISDIR); 8326 else 8327 return (EPERM); 8328 } 8329 8330 if ((error = smbnode_lock(VTOSMB(vp), SMBFS_EXCLUSIVE_LOCK))) { 8331 return (error); 8332 } 8333 8334 SMB_LOG_KTRACE(SMB_DBG_ALLOCATE | DBG_FUNC_START, 0, 0, 0, 0, 0); 8335 8336 np = VTOSMB(vp); 8337 np->n_lastvop = smbfs_vnop_allocate; 8338 8339 if ((ap->a_flags & ALLOCATEFROMVOL) && (length < np->n_size)) { 8340 error = EINVAL; 8341 goto done; 8342 } 8343 8344 if (ap->a_flags & ALLOCATEFROMPEOF) { 8345 if (length > (UINT32_MAX - np->n_size)) { 8346 error = EINVAL; 8347 goto done; 8348 } 8349 length += np->n_size; 8350 } 8351 8352 if (FindFileRef(vp, vfs_context_proc(ap->a_context), kAccessWrite, 8353 kAnyMatch, 0, 0, NULL, &fid)) { 8354 /* No matches or no pid to match, so just use the generic shared fork */ 8355 fid = np->f_fid; 8356 } 8357 8358 if (fid == 0) { 8359 error = EBADF; 8360 goto done; 8361 } 8362 8363 /* If nothing is changing, then we're done */ 8364 if (!length || (np->n_size == length)) { 8365 length = 0; 8366 } 8367 else { 8368 struct smb_share *share; 8369 8370 share = smb_get_share_with_reference(VTOSMBFS(vp)); 8371 length = roundup(length, VTOSMBFS(vp)->sm_statfsbuf.f_bsize); 8372 error = smbfs_smb_set_allocation(share, fid, length, ap->a_context); 8373 8374 SMB_LOG_KTRACE(SMB_DBG_ALLOCATE | DBG_FUNC_NONE, 8375 0xabc001, error, 0, 0, 0); 8376 smb_share_rele(share, ap->a_context); 8377 } 8378 8379 if (!error) { 8380 *(ap->a_bytesallocated) = length; 8381 } 8382 8383done: 8384 if (error) { 8385 lck_rw_lock_shared(&np->n_name_rwlock); 8386 SMBWARNING("%s: length = %lld, error = %d\n", np->n_name, length, error); 8387 lck_rw_unlock_shared(&np->n_name_rwlock); 8388 } 8389 smbnode_unlock(VTOSMB(ap->a_vp)); 8390 8391 SMB_LOG_KTRACE(SMB_DBG_ALLOCATE | DBG_FUNC_END, error, 0, 0, 0, 0); 8392 return error; 8393} 8394 8395static char* 8396mountpointname(struct mount *mp) 8397{ 8398 size_t namelength = strlen(vfs_statfs(mp)->f_mntonname); 8399 int foundchars = 0; 8400 char *c; 8401 8402 if (namelength == 0) { 8403 return (NULL); 8404 } 8405 8406 /* 8407 * Look backwards through the name string, looking for 8408 * the first slash encountered (which must precede the 8409 * last part of the pathname). 8410 */ 8411 for (c = vfs_statfs(mp)->f_mntonname + namelength - 1; 8412 namelength > 0; --c, --namelength) { 8413 if (*c != '/') { 8414 foundchars = 1; 8415 } else if (foundchars) { 8416 return (c + 1); 8417 } 8418 } 8419 8420 return (vfs_statfs(mp)->f_mntonname); 8421} 8422 8423/* 8424 * The calling routine must hold a reference on the share 8425 */ 8426static int 8427smbfs_pack_vap(struct smbmount *smp, struct smbfs_fctx *ctx, 8428 struct vnode_attr *vap, vfs_context_t context) 8429{ 8430 uint32_t is_dir; 8431 uint64_t data_fork_size, data_fork_alloc; 8432 uint64_t rsrc_fork_size, rsrc_fork_alloc; 8433 uint64_t file_id; 8434 uid_t uid; 8435 gid_t gid; 8436 mode_t mode = 0; 8437 uint32_t flags = 0; 8438 int isroot = 0; 8439 uid_t cuid = 1; 8440 uint32_t cmn_user_rights = 0; 8441 char *mp_name = NULL; 8442 size_t mp_namelen = 0; 8443 8444 if ((!vap) || (!ctx) || (!smp)) { 8445 SMBERROR("Missing vap, ctx, or smp \n"); 8446 return (EINVAL); 8447 } 8448 8449 is_dir = (ctx->f_attr.fa_attr & SMB_EFA_DIRECTORY) ? 1 : 0; 8450 8451 /* Use values from ctx */ 8452 data_fork_size = ctx->f_attr.fa_size; 8453 data_fork_alloc = ctx->f_attr.fa_data_alloc; 8454 rsrc_fork_size = ctx->f_attr.fa_rsrc_size; 8455 rsrc_fork_alloc = ctx->f_attr.fa_rsrc_alloc; 8456 8457 /* 8458 * If there was a vnode np, then ctx->f_attr.fa_uid/fa_gid was set to 8459 * np->n_uid/n_gid which could have been updated by a Get ACL 8460 */ 8461 uid = (uid_t) ctx->f_attr.fa_uid; 8462 gid = (gid_t) ctx->f_attr.fa_gid; 8463 8464 if (VATTR_IS_ACTIVE(vap, va_mode) || 8465 VATTR_IS_ACTIVE(vap, va_uid) || 8466 VATTR_IS_ACTIVE(vap, va_gid)) { 8467 /* This is used later in this function... */ 8468 cuid = kauth_cred_getuid(vfs_context_ucred(context)); 8469 isroot = cuid == 0; 8470 8471 /* Calculate uid, gid and mode from Query Dir results */ 8472 if (is_dir) { 8473 flags |= SMBFS_GET_UGM_IS_DIR; 8474 } 8475 8476 if (!(ctx->f_attr.fa_valid_mask & FA_UNIX_MODES_VALID)) { 8477 /* Must not have had a vnode to get unix mode from */ 8478 flags |= SMBFS_GET_UGM_REMOVE_POSIX_MODES; 8479 } 8480 8481 smb_get_uid_gid_mode(ctx->f_share, smp, 8482 &ctx->f_attr, flags, 8483 &uid, &gid, &mode); 8484 } 8485 8486 if (VATTR_IS_ACTIVE(vap, va_rdev)) { 8487 VATTR_RETURN(vap, va_rdev, 0); 8488 } 8489 8490 /* 8491 * The DIR_LINKCOUNT is the count of real directory hard links. 8492 * (i.e. its not the sum of the implied "." and ".." references 8493 * typically used in stat's st_nlink field) 8494 */ 8495 if (VATTR_IS_ACTIVE(vap, va_nlink)) { 8496 /* There ARE no hard links, at least not yet... */ 8497 VATTR_RETURN(vap, va_nlink, 1); 8498 } 8499 8500 if (VATTR_IS_ACTIVE(vap, va_total_size)) { 8501 VATTR_RETURN(vap, va_total_size, data_fork_size + rsrc_fork_size); 8502 } 8503 8504 if (VATTR_IS_ACTIVE(vap, va_total_alloc)) { 8505 /* Should already be rounded up */ 8506 VATTR_RETURN(vap, va_total_alloc, data_fork_alloc + rsrc_fork_alloc); 8507 } 8508 8509 if (VATTR_IS_ACTIVE(vap, va_data_size)) { 8510 VATTR_RETURN(vap, va_data_size, data_fork_size); 8511 } 8512 8513 if (VATTR_IS_ACTIVE(vap, va_data_alloc)) { 8514 VATTR_RETURN(vap, va_data_alloc, data_fork_alloc); 8515 } 8516 8517 if (VATTR_IS_ACTIVE(vap, va_iosize)) { 8518 VATTR_RETURN(vap, va_iosize, smp->sm_statfsbuf.f_bsize); 8519 } 8520 8521 if (VATTR_IS_ACTIVE(vap, va_uid)) { 8522 uid_t nuid; 8523 8524 if (SMBV_HAS_GUEST_ACCESS(SSTOVC(ctx->f_share))) { 8525 nuid = UNKNOWNUID; 8526 } 8527 else { 8528 /* 8529 * For servers that support the UNIX extensions we know the uid/gid. 8530 * For server that don't support ACLs then the node uid/gid will be 8531 * set to the mounted user's uid/gid. For all other servers we need 8532 * to get the ACL and translate the SID to a uid or gid. The uid/gid 8533 * really is for display purpose only and means nothing to us. We will 8534 * set the nodes ids if we get a request for the ACL, but otherwise 8535 * we leave them unset for performance reasons. 8536 */ 8537 if (ctx->f_attr.fa_uid == KAUTH_UID_NONE) { 8538 nuid = smp->sm_args.uid; 8539 } 8540 else { 8541 nuid = uid; 8542 } 8543 } 8544 8545 if (!isroot) { 8546 if (((unsigned int)vfs_flags(smp->sm_mp)) & MNT_UNKNOWNPERMISSIONS) 8547 nuid = cuid; 8548 else if (nuid == UNKNOWNUID) 8549 nuid = cuid; 8550 } 8551 8552 VATTR_RETURN(vap, va_uid, nuid); 8553 } 8554 8555 if (VATTR_IS_ACTIVE(vap, va_gid)) { 8556 gid_t ngid; 8557 8558 if (SMBV_HAS_GUEST_ACCESS(SSTOVC(ctx->f_share))) { 8559 ngid = UNKNOWNGID; 8560 } 8561 else { 8562 /* 8563 * For servers that support the UNIX extensions we know the uid/gid. 8564 * For server that don't support ACLs then the node uid/gid will be 8565 * set to the mounted user's uid/gid. For all other servers we need 8566 * to get the ACL and translate the SID to a uid or gid. The uid/gid 8567 * really is for display purpose only and means nothing to us. We will 8568 * set the nodes ids if we get a request for the ACL, but otherwise 8569 * we leave them unset for performance reasons. 8570 */ 8571 if (ctx->f_attr.fa_gid == KAUTH_GID_NONE) { 8572 ngid = smp->sm_args.gid; 8573 } 8574 else { 8575 ngid = gid; 8576 } 8577 } 8578 8579 if (!isroot) { 8580 gid_t cgid = kauth_cred_getgid(vfs_context_ucred(context)); 8581 if (((unsigned int)vfs_flags(smp->sm_mp)) & MNT_UNKNOWNPERMISSIONS) 8582 ngid = cgid; 8583 else if (ngid == UNKNOWNUID) 8584 ngid = cgid; 8585 } 8586 8587 VATTR_RETURN(vap, va_gid, ngid); 8588 } 8589 8590 if (VATTR_IS_ACTIVE(vap, va_mode)) { 8591 if (ctx->f_attr.fa_vtype == VDIR) { 8592 VATTR_RETURN(vap, va_mode, (S_IFDIR | mode)); 8593 } 8594 8595 if (ctx->f_attr.fa_vtype == VREG) { 8596 VATTR_RETURN(vap, va_mode, (S_IFREG | mode)); 8597 } 8598 8599 if (ctx->f_attr.fa_vtype == VLNK) { 8600 VATTR_RETURN(vap, va_mode, (S_IFLNK | mode)); 8601 } 8602 } 8603 8604 if (VATTR_IS_ACTIVE(vap, va_flags)) { 8605 uint32_t va_flags = 0; 8606 8607 if (ctx->f_attr.fa_attr & SMB_EFA_HIDDEN) { 8608 /* 8609 * Dont have to special case whether root vnode is hidden or not. 8610 * root volume doesn't show up in a readdirattr, I think? 8611 */ 8612 va_flags |= UF_HIDDEN; 8613 } 8614 8615 /* 8616 * Remember that SMB_EFA_ARCHIVE means the items needs to be 8617 * archived and SF_ARCHIVED means the item has been archive. 8618 * 8619 * NOTE: Windows does not set ATTR_ARCHIVE bit for directories. 8620 */ 8621 if ((ctx->f_attr.fa_vtype != VDIR) && 8622 !(ctx->f_attr.fa_attr & SMB_EFA_ARCHIVE)) { 8623 va_flags |= SF_ARCHIVED; 8624 } 8625 8626 if (node_isimmutable(ctx->f_share, NULL, &ctx->f_attr)) { 8627 va_flags |= UF_IMMUTABLE; 8628 } 8629 8630 VATTR_RETURN(vap, va_flags, va_flags); 8631 } 8632 8633 /* va_acl is done in smbfs_vnop_getattrlistbulk() */ 8634 8635 if (VATTR_IS_ACTIVE(vap, va_create_time)) { 8636 VATTR_RETURN(vap, va_create_time, ctx->f_attr.fa_crtime); 8637 } 8638 8639 if (VATTR_IS_ACTIVE(vap, va_access_time)) { 8640 VATTR_RETURN(vap, va_access_time, ctx->f_attr.fa_atime); 8641 } 8642 8643 if (VATTR_IS_ACTIVE(vap, va_modify_time)) { 8644 VATTR_RETURN(vap, va_modify_time, ctx->f_attr.fa_mtime); 8645 } 8646 8647 if (VATTR_IS_ACTIVE(vap, va_change_time)) { 8648 if (ctx->f_share->ss_fstype == SMB_FS_FAT) { 8649 /* 8650 * FAT does not support change time, so just return the modify time. 8651 * Copied from the msdos code. SMB has no backup time so skip the 8652 * va_backup_time. 8653 */ 8654 VATTR_RETURN(vap, va_change_time, ctx->f_attr.fa_mtime); 8655 } 8656 else { 8657 VATTR_RETURN(vap, va_change_time, ctx->f_attr.fa_chtime); 8658 } 8659 } 8660 8661 if (VATTR_IS_ACTIVE(vap, va_backup_time)) { 8662 /* Backup time not supported so return 0 */ 8663 vap->va_backup_time.tv_sec = 0; 8664 vap->va_backup_time.tv_nsec = 0; 8665 VATTR_SET_SUPPORTED(vap, va_backup_time); 8666 } 8667 8668 if (VATTR_IS_ACTIVE(vap, va_fileid)) { 8669 file_id = smb2fs_smb_file_id_get(smp, 8670 ctx->f_attr.fa_ino, 8671 ctx->f_LocalName); 8672 VATTR_RETURN(vap, va_fileid, file_id); 8673 } 8674 8675 if (VATTR_IS_ACTIVE(vap, va_linkid)) { 8676 file_id = smb2fs_smb_file_id_get(smp, 8677 ctx->f_attr.fa_ino, 8678 ctx->f_LocalName); 8679 VATTR_RETURN(vap, va_linkid, file_id); 8680 } 8681 8682 if (VATTR_IS_ACTIVE(vap, va_parentid)) { 8683 lck_rw_lock_shared(&ctx->f_dnp->n_name_rwlock); 8684 file_id = smb2fs_smb_file_id_get(smp, 8685 ctx->f_dnp->n_ino, 8686 ctx->f_dnp->n_name); 8687 lck_rw_unlock_shared(&ctx->f_dnp->n_name_rwlock); 8688 VATTR_RETURN(vap, va_parentid, file_id); 8689 } 8690 8691 if (VATTR_IS_ACTIVE(vap, va_fsid)) { 8692 /* Copy AFP Client behavior */ 8693 VATTR_RETURN(vap, va_fsid, vfs_statfs(vfs_statfs(smp->sm_mp)->f_fsid.val[0])); 8694 } 8695 8696 if (VATTR_IS_ACTIVE(vap, va_filerev)) { 8697 VATTR_RETURN(vap, va_filerev, 0); 8698 } 8699 8700 if (VATTR_IS_ACTIVE(vap, va_gen)) { 8701 VATTR_RETURN(vap, va_gen, 0); 8702 } 8703 8704 /* 8705 * We currently have no way to know the va_encoding. The VFS layer fills it 8706 * in with kTextEncodingMacUnicode = 0x7E, so use the same value; 8707 */ 8708 if (VATTR_IS_ACTIVE(vap, va_encoding)) { 8709 VATTR_RETURN(vap, va_encoding, 0x7E); 8710 } 8711 8712 /* 8713 * If this is the root, let VFS find out the mount name, which may be 8714 * different from the real name 8715 */ 8716 if (VATTR_IS_ACTIVE(vap, va_name)) { 8717 if (ctx->f_attr.fa_ino != smp->sm_root_ino) { 8718 strlcpy ((char*) vap->va_name, (char*) ctx->f_LocalName, MAXPATHLEN); 8719 VATTR_SET_SUPPORTED(vap, va_name); 8720 } 8721 else { 8722 /* 8723 * A cnode's name may be incorrect for the root of a mounted 8724 * filesystem (it can be mounted on a different directory name 8725 * than the name of the volume, such as "blah-1"). So for the 8726 * root directory, it's best to return the last element of the 8727 * location where the volume's mounted. 8728 */ 8729 mp_name = mountpointname(vnode_mount(ctx->f_dnp->n_vnode)); 8730 if (mp_name != NULL) { 8731 mp_namelen = strlen(mp_name); 8732 8733 /* Trim off any trailing slashes: */ 8734 while ((mp_namelen > 0) && (mp_name[mp_namelen - 1] == '/')) { 8735 --mp_namelen; 8736 } 8737 8738 /* If there's anything left, use it instead of the vol's name */ 8739 if (mp_namelen > 0) { 8740 strlcpy ((char*) vap->va_name, (char*) mp_name, MAXPATHLEN); 8741 VATTR_SET_SUPPORTED(vap, va_name); 8742 } 8743 else { 8744 SMBERROR("mountpointname failed to find a name\n"); 8745 } 8746 } 8747 else { 8748 SMBERROR("mountpointname failed \n"); 8749 } 8750 } 8751 } 8752 8753 /* va_uuuid, va_guuid is done in smbfs_vnop_getattrlistbulk() */ 8754 8755 if (VATTR_IS_ACTIVE(vap, va_nchildren)) { 8756 /* Apparently 0 is a fine answer to return for a filesystem */ 8757 VATTR_RETURN(vap, va_nchildren, 0); 8758 } 8759 8760 /* There ARE no hard links, at least not yet... */ 8761 if (VATTR_IS_ACTIVE(vap, va_dirlinkcount)) { 8762 VATTR_RETURN(vap, va_dirlinkcount, 1); 8763 } 8764 8765 /* 8766 * We have no way to get: 8767 * va_addedtime, 8768 * va_dataprotect_class, va_dataprotect_flags, va_document_id 8769 */ 8770 8771 /* 8772 * New fields added to the struct vnode_attr for the vnop_getattrlistbulk 8773 */ 8774 if (VATTR_IS_ACTIVE(vap, va_devid)) { 8775 /* Copy AFP Client behavior */ 8776 VATTR_RETURN(vap, va_devid, vfs_statfs(vfs_statfs(smp->sm_mp)->f_fsid.val[0])); 8777 } 8778 8779 if (VATTR_IS_ACTIVE(vap, va_objtype)) { 8780 /* 8781 * Because of the Steve/Conrad Symlinks we can never be completely 8782 * sure that we have the correct vnode type if its a file. Since we 8783 * don't support Steve/Conrad Symlinks with Darwin we can always count 8784 * on the vtype being correct. For directories we always know the 8785 * correct information. 8786 */ 8787 VATTR_RETURN(vap, va_objtype, ctx->f_attr.fa_vtype); 8788 } 8789 8790 if (VATTR_IS_ACTIVE(vap, va_objtag)) { 8791 VATTR_RETURN(vap, va_objtag, VT_CIFS); 8792 } 8793 8794 if (VATTR_IS_ACTIVE(vap, va_user_access)) { 8795 /* 8796 * The effective permissions for the current user which we derive 8797 * from the max access 8798 */ 8799 DBG_ASSERT(ctx->f_attr.fa_valid_mask & FA_MAX_ACCESS_VALID); 8800 8801 if (ctx->f_attr.fa_max_access & SMB2_FILE_READ_DATA) { 8802 cmn_user_rights |= R_OK; 8803 } 8804 8805 if (ctx->f_attr.fa_max_access & SMB2_FILE_WRITE_DATA) { 8806 cmn_user_rights |= W_OK; 8807 } 8808 8809 if (ctx->f_attr.fa_max_access & SMB2_FILE_EXECUTE) { 8810 cmn_user_rights |= X_OK; 8811 } 8812 8813 VATTR_RETURN(vap, va_user_access, cmn_user_rights); 8814 } 8815 8816 if (VATTR_IS_ACTIVE(vap, va_finderinfo)) { 8817 DBG_ASSERT(ctx->f_attr.fa_valid_mask & FA_FINDERINFO_VALID); 8818 bcopy(ctx->f_attr.fa_finder_info, vap->va_finderinfo, sizeof(u_int8_t) * 32); 8819 VATTR_SET_SUPPORTED(vap, va_finderinfo); 8820 } 8821 8822 if (VATTR_IS_ACTIVE(vap, va_rsrc_length)) { 8823 VATTR_RETURN(vap, va_rsrc_length, rsrc_fork_size); 8824 } 8825 8826 if (VATTR_IS_ACTIVE(vap, va_rsrc_alloc)) { 8827 VATTR_RETURN(vap, va_rsrc_alloc, rsrc_fork_alloc); 8828 } 8829 8830 if (VATTR_IS_ACTIVE(vap, va_fsid64)) { 8831 /* Copy AFP Client behavior */ 8832 memcpy(&vap->va_fsid64, &(vfs_statfs(smp->sm_mp)->f_fsid), sizeof(vap->va_fsid64)); 8833 VATTR_SET_SUPPORTED(vap, va_fsid64); 8834 } 8835 8836 return (0); 8837} 8838 8839/* 8840 * Check for any missing data in the ctx that we could not get from just 8841 * the enumeration and fill in the missing data. Missing data could be Resource 8842 * Fork Info, Finder Info, etc. Missing data can come from a pre existing 8843 * vnode, or retrieved from over the wire. 8844 */ 8845static void 8846smbfs_update_ctx(struct vnode *vp, 8847 struct vnode_attr *vap, 8848 struct smbfs_fctx *ctx, 8849 struct vfs_context *context) 8850{ 8851 uint32_t is_dir; 8852 int error; 8853 uint32_t stream_flags = 0; 8854 struct smbnode *np = NULL; 8855 uint32_t need_rsrc_fork = 0; 8856 size_t afp_size = 0; 8857 uint8_t afp_info[60] = {0}; 8858 uint8_t zero_finfo[32] = {0}; 8859 uio_t afp_uio = NULL; 8860 SMBFID fid = 0; 8861 struct timespec ts; 8862 uint32_t rsrc_fork_from_cache = 0; 8863 uint32_t finder_info_from_cache = 0; 8864 uint32_t max_access_from_cache = 0; 8865 uint32_t need_finder_info = 0; 8866 uint32_t need_cmn_user_access = 0; 8867 8868 SMB_LOG_KTRACE(SMB_DBG_UPDATE_CTX | DBG_FUNC_START, vap->va_active, 0, 0, 0, 0); 8869 8870 /* Do we need Resource Fork info? */ 8871 is_dir = (ctx->f_attr.fa_attr & SMB_EFA_DIRECTORY) ? 1 : 0; 8872 if ((!is_dir) && 8873 (VATTR_IS_ACTIVE(vap, va_total_size) || 8874 VATTR_IS_ACTIVE(vap, va_total_alloc) || 8875 VATTR_IS_ACTIVE(vap, va_rsrc_length) || 8876 VATTR_IS_ACTIVE(vap, va_rsrc_alloc))) { 8877 need_rsrc_fork = 1; 8878 } 8879 8880 if (VATTR_IS_ACTIVE(vap, va_finderinfo)) { 8881 need_finder_info = 1; 8882 } 8883 8884 if (VATTR_IS_ACTIVE(vap, va_user_access)) { 8885 need_cmn_user_access = 1; 8886 } 8887 8888 /* 8889 * We may already have all the meta data we need from Mac <-> Mac (not yet 8890 * implemented) or dont need Resource Fork, Finder Info, or Max Access data. 8891 * If we do have all the needed meta data, then just go update vnode caches 8892 * if we have a vnode and then pack the return attribute block. 8893 */ 8894 if ((need_rsrc_fork && (ctx->f_attr.fa_valid_mask & FA_RSRC_FORK_VALID)) && 8895 (need_finder_info && (ctx->f_attr.fa_valid_mask & FA_FINDERINFO_VALID)) && 8896 (need_cmn_user_access && (ctx->f_attr.fa_valid_mask & FA_MAX_ACCESS_VALID))) { 8897 SMB_LOG_KTRACE(SMB_DBG_UPDATE_CTX | DBG_FUNC_NONE, 8898 0xabc001, 0, 0, 0, 0); 8899 goto update_caches; 8900 } 8901 8902 /* 8903 * Figure out what attributes we are missing and then go get them from 8904 * either the vnode or from the server. 8905 */ 8906 8907 /* 8908 * Do we have a vnode that already has the attributes we need? 8909 */ 8910 if (vp != NULL) { 8911 np = VTOSMB(vp); 8912 8913 /* Check cached Resource Fork info */ 8914 if ((need_rsrc_fork) && 8915 !(ctx->f_attr.fa_valid_mask & FA_RSRC_FORK_VALID)) { 8916 8917 lck_mtx_lock(&np->rfrkMetaLock); 8918 8919 if (np->rfrk_cache_timer != 0) { 8920 /* Resource fork data is valid in vnode so use it */ 8921 rsrc_fork_from_cache = 1; 8922 ctx->f_attr.fa_valid_mask |= FA_RSRC_FORK_VALID; 8923 ctx->f_attr.fa_rsrc_size = np->rfrk_size; 8924 ctx->f_attr.fa_rsrc_alloc = np->rfrk_alloc_size; 8925 8926 SMB_LOG_KTRACE(SMB_DBG_UPDATE_CTX | DBG_FUNC_NONE, 8927 0xabc002, 0, 0, 0, 0); 8928 } 8929 8930 lck_mtx_unlock(&np->rfrkMetaLock); 8931 } 8932 8933 /* Check cached Finder Info */ 8934 if (need_finder_info && 8935 !(ctx->f_attr.fa_valid_mask & FA_FINDERINFO_VALID)) { 8936 8937 if (np->finfo_cache_timer != 0) { 8938 /* Finder Info data is valid in vnode so use it */ 8939 finder_info_from_cache = 1; 8940 ctx->f_attr.fa_valid_mask |= FA_FINDERINFO_VALID; 8941 bcopy(&np->finfo, ctx->f_attr.fa_finder_info, sizeof(u_int8_t) * 32); 8942 8943 SMB_LOG_KTRACE(SMB_DBG_UPDATE_CTX | DBG_FUNC_NONE, 8944 0xabc003, 0, 0, 0, 0); 8945 } 8946 } 8947 8948 /* Check cached Max Info */ 8949 if (need_cmn_user_access && 8950 !(ctx->f_attr.fa_valid_mask & FA_MAX_ACCESS_VALID)) { 8951 if (timespeccmp(&np->maxAccessRightChTime, &np->n_chtime, ==)) { 8952 8953 /* Max Access data is valid in vnode so use it */ 8954 max_access_from_cache = 1; 8955 ctx->f_attr.fa_valid_mask |= FA_MAX_ACCESS_VALID; 8956 ctx->f_attr.fa_max_access = np->maxAccessRights; 8957 8958 SMB_LOG_KTRACE(SMB_DBG_UPDATE_CTX | DBG_FUNC_NONE, 8959 0xabc004, 0, 0, 0, 0); 8960 } 8961 } 8962 } 8963 8964 /* Are we still missing attribute information? */ 8965 if ((need_rsrc_fork && !(ctx->f_attr.fa_valid_mask & FA_RSRC_FORK_VALID)) || 8966 (need_finder_info && !(ctx->f_attr.fa_valid_mask & FA_FINDERINFO_VALID)) || 8967 (need_cmn_user_access && !(ctx->f_attr.fa_valid_mask & FA_MAX_ACCESS_VALID))) { 8968 /* 8969 * This will get us 8970 * 1) Resource Fork sizes 8971 * 2) Whether Finder Info exists or not on the item 8972 * 3) For SMB 2/3, gets the max access on the item 8973 * 8974 * If we have to ask the server for the resource fork info or the 8975 * user access, do it now as this will also tell us if there is any 8976 * Finder Info on the file or not. For SMB 2/3, it will also get us the 8977 * max access which is used for ATTR_CMN_USERACCESS. 8978 * 8979 * Best case (SMB 2/3) - Just this one call because no Finder Info found 8980 * Worst case (SMB 2/3) - This call and another call to read Finder Info 8981 * 8982 * Best case (SMB 1) - This call and 2 calls (Create/Read + Close) to 8983 * read Finder Info which will get the max access 8984 * for SMB 1 8985 * Worst case (SMB 1) - This call and 2 calls (Create + Close) to get 8986 * max access because there is no Finder Info 8987 */ 8988 error = smbfs_smb_qstreaminfo(ctx->f_share, ctx->f_dnp, (is_dir) ? VDIR : VREG, 8989 ctx->f_LocalName, ctx->f_LocalNameLen, 8990 SFM_RESOURCEFORK_NAME, 8991 NULL, NULL, 8992 &ctx->f_attr.fa_rsrc_size, &ctx->f_attr.fa_rsrc_alloc, 8993 &stream_flags, &ctx->f_attr.fa_max_access, 8994 context); 8995 8996 SMB_LOG_KTRACE(SMB_DBG_UPDATE_CTX | DBG_FUNC_NONE, 8997 0xabc005, error, 0, 0, 0); 8998 8999 if ((!error) || (error == ENOATTR)) { 9000 /* smbfs_smb_qstreaminfo worked */ 9001 9002 if (stream_flags & SMB_NO_SUBSTREAMS) { 9003 /* No named streams at all on item */ 9004 ctx->f_attr.fa_valid_mask |= FA_FSTATUS_VALID; 9005 ctx->f_attr.fa_fstatus = kNO_SUBSTREAMS; 9006 } 9007 else { 9008 /* At least one named stream on item */ 9009 ctx->f_attr.fa_valid_mask |= FA_FSTATUS_VALID; 9010 ctx->f_attr.fa_fstatus = 0; 9011 } 9012 9013 /* Did we need Resource Fork info? */ 9014 if (need_rsrc_fork && 9015 !(ctx->f_attr.fa_valid_mask & FA_RSRC_FORK_VALID)) { 9016 /* 9017 * Successfully got Resource Fork Info. Its either already in 9018 * f_attr or no Resource Fork was found 9019 */ 9020 ctx->f_attr.fa_valid_mask |= FA_RSRC_FORK_VALID; 9021 9022 if (stream_flags & SMB_NO_RESOURCE_FORK) { 9023 /* No Resource Fork, so set resource fork lengths to zero */ 9024 ctx->f_attr.fa_rsrc_size = 0; 9025 ctx->f_attr.fa_rsrc_alloc = 0; 9026 } 9027 else { 9028 /* SMBDEBUG("%s rsrc fork from qstreaminfo\n", ctx->f_LocalName); */ 9029 } 9030 } 9031 9032 /* Did we need Finder Info? */ 9033 if (need_finder_info && 9034 !(ctx->f_attr.fa_valid_mask & FA_FINDERINFO_VALID)) { 9035 /* 9036 * Now we know if there is Finder Info or not on the item 9037 */ 9038 if (stream_flags & SMB_NO_FINDER_INFO) { 9039 /* No Finder Info, so set Finder Info to all zeros */ 9040 ctx->f_attr.fa_valid_mask |= FA_FINDERINFO_VALID; 9041 bcopy(&zero_finfo, ctx->f_attr.fa_finder_info, 9042 sizeof(u_int8_t) * 32); 9043 } 9044 } 9045 9046 /* Did we need Max Access? */ 9047 if (need_cmn_user_access && 9048 !(ctx->f_attr.fa_valid_mask & FA_MAX_ACCESS_VALID)) { 9049 if (SSTOVC(ctx->f_share)->vc_flags & SMBV_SMB2) { 9050 /* 9051 * Only SMB 2/3 can get max access from 9052 * smbfs_smb_qstreaminfo call 9053 */ 9054 ctx->f_attr.fa_valid_mask |= FA_MAX_ACCESS_VALID; 9055 } 9056 } 9057 } 9058 else { 9059 /* Got some sort of error. This shouldn't happen */ 9060 SMBDEBUG("smbfs_smb_qstreaminfo failed %d for %s \n", 9061 error, ctx->f_LocalName); 9062 } 9063 } 9064 9065 /* 9066 * Do we still need to get the Finder Info? At this point we know 9067 * (1) Either no vnode or the cached finder info is not present 9068 * (2) smbfs_smb_qstreaminfo told us that there is Finder Info on the item 9069 * 9070 * <11615553> For SMB 1, we can NOT get both the Finder Info and max 9071 * access at the same time. Windows based servers will often give 9072 * "Unspecified error" when you do a CreateAndX with extended response (ie 9073 * max access) combined with Read of a named stream. 9074 */ 9075 if (need_finder_info && 9076 !(ctx->f_attr.fa_valid_mask & FA_FINDERINFO_VALID)) { 9077 9078 do { 9079 afp_uio = uio_create(1, 0, UIO_SYSSPACE, UIO_READ); 9080 if (afp_uio == NULL) { 9081 SMBERROR("uio_create failed for %s \n", ctx->f_LocalName); 9082 break; 9083 } 9084 9085 error = uio_addiov(afp_uio, CAST_USER_ADDR_T(afp_info), 9086 sizeof(afp_info)); 9087 if (error) { 9088 SMBERROR("uio_addiov failed for %s \n", ctx->f_LocalName); 9089 break; 9090 } 9091 9092 uio_setoffset(afp_uio, 0); 9093 9094 /* Open/Read/Close the Finder Info */ 9095 error = smbfs_smb_cmpd_create_read_close(ctx->f_share, ctx->f_dnp, 9096 ctx->f_LocalName, ctx->f_LocalNameLen, 9097 SFM_FINDERINFO_NAME, strlen(SFM_FINDERINFO_NAME), 9098 afp_uio, &afp_size, 9099 NULL, 9100 context); 9101 9102 SMB_LOG_KTRACE(SMB_DBG_UPDATE_CTX | DBG_FUNC_NONE, 9103 0xabc006, error, 0, 0, 0); 9104 9105 if (!error) { 9106 /* Successfully got Finder Info */ 9107 ctx->f_attr.fa_valid_mask |= FA_FINDERINFO_VALID; 9108 9109 /* Verify returned size */ 9110 if (afp_size != AFP_INFO_SIZE) { 9111 /* Could be a 0 size returned meaning no Finder Info */ 9112 if (afp_size != 0) { 9113 /* SMBDEBUG("%s Finder Info size mismatch %ld != %d \n", 9114 ctx->f_LocalName, afp_size, AFP_INFO_SIZE); */ 9115 } 9116 bcopy(&zero_finfo, ctx->f_attr.fa_finder_info, 9117 sizeof(u_int8_t) * 32); 9118 } 9119 else { 9120 /* Correct size, so just copy it in */ 9121 bcopy(&afp_info[AFP_INFO_FINDER_OFFSET], 9122 ctx->f_attr.fa_finder_info, 9123 sizeof(u_int8_t) * 32); 9124 /* SMBDEBUG("Finder Info 0x%x 0x%x 0x%x 0x%x for %s \n", 9125 afp_info[AFP_INFO_FINDER_OFFSET], 9126 afp_info[AFP_INFO_FINDER_OFFSET + 1], 9127 afp_info[AFP_INFO_FINDER_OFFSET + 2], 9128 afp_info[AFP_INFO_FINDER_OFFSET + 3], 9129 ctx->f_LocalName); */ 9130 } 9131 } 9132 else { 9133 if (error != ENOENT) { 9134 SMBDEBUG("smbfs_smb_cmpd_create_read_close failed %d for %s \n", 9135 error, ctx->f_LocalName); 9136 } 9137 } 9138 9139 if (afp_uio) { 9140 uio_free(afp_uio); 9141 } 9142 } while (0); 9143 } 9144 9145 /* Do we still need Max Access and its SMB 1? */ 9146 if (need_cmn_user_access && 9147 !(ctx->f_attr.fa_valid_mask & FA_MAX_ACCESS_VALID) && 9148 !(SSTOVC(ctx->f_share)->vc_flags & SMBV_SMB2)) 9149 { 9150 error = smb1fs_smb_open_maxaccess(ctx->f_share, ctx->f_dnp, 9151 ctx->f_LocalName, ctx->f_LocalNameLen, 9152 &fid, &ctx->f_attr.fa_max_access, 9153 context); 9154 if (!error) { 9155 ctx->f_attr.fa_valid_mask |= FA_MAX_ACCESS_VALID; 9156 } 9157 9158 if (fid) { 9159 (void)smbfs_smb_close(ctx->f_share, fid, context); 9160 } 9161 } 9162 9163update_caches: 9164 9165 /* Update vnodes caches if the data did not come from the vnode caches */ 9166 if (vp) { 9167 np = VTOSMB(vp); 9168 9169 if (ctx->f_attr.fa_valid_mask & FA_FSTATUS_VALID) { 9170 /* Update whether there is a named streams or not */ 9171 np->n_fstatus = ctx->f_attr.fa_fstatus; 9172 } 9173 9174 /* Do we have updated resource fork info? */ 9175 if ((rsrc_fork_from_cache == 0) && 9176 need_rsrc_fork && 9177 (ctx->f_attr.fa_valid_mask & FA_RSRC_FORK_VALID)) { 9178 9179 lck_mtx_lock(&np->rfrkMetaLock); 9180 np->rfrk_size = ctx->f_attr.fa_rsrc_size; 9181 np->rfrk_alloc_size = ctx->f_attr.fa_rsrc_alloc; 9182 nanouptime(&ts); 9183 np->rfrk_cache_timer = ts.tv_sec; 9184 lck_mtx_unlock(&np->rfrkMetaLock); 9185 } 9186 9187 /* Do we have updated Finder Info? */ 9188 if ((finder_info_from_cache == 0) && 9189 need_finder_info && 9190 (ctx->f_attr.fa_valid_mask & FA_FINDERINFO_VALID)) { 9191 9192 bcopy(ctx->f_attr.fa_finder_info, &np->finfo, 9193 sizeof(u_int8_t) * 32); 9194 nanouptime(&ts); 9195 np->finfo_cache_timer = ts.tv_sec; 9196 } 9197 9198 /* Do we have updated Max Access? */ 9199 if ((max_access_from_cache == 0) && 9200 need_cmn_user_access && 9201 (ctx->f_attr.fa_valid_mask & FA_MAX_ACCESS_VALID)) { 9202 9203 np->maxAccessRights = ctx->f_attr.fa_max_access; 9204 np->maxAccessRightChTime = ctx->f_attr.fa_chtime; 9205 } 9206 9207 /* We can get the unix mode from the vnode */ 9208 if (np->n_flag & NHAS_POSIXMODES) { 9209 ctx->f_attr.fa_permissions = np->n_mode; 9210 ctx->f_attr.fa_valid_mask |= FA_UNIX_MODES_VALID; 9211 } 9212 9213 /* We can get the uid/gid from the vnode */ 9214 ctx->f_attr.fa_uid = np->n_uid; 9215 ctx->f_attr.fa_gid = np->n_gid; 9216 } 9217 9218 /* 9219 * Error Handling. At this point, we should have valid information and if 9220 * we do not, then some earlier error must have occurred, so fill in with 9221 * default values. 9222 */ 9223 if (need_rsrc_fork && 9224 !(ctx->f_attr.fa_valid_mask & FA_RSRC_FORK_VALID)) { 9225 /* Assume resource fork lengths of zero */ 9226 ctx->f_attr.fa_valid_mask |= FA_RSRC_FORK_VALID; 9227 ctx->f_attr.fa_rsrc_size = 0; 9228 ctx->f_attr.fa_rsrc_alloc = 0; 9229 } 9230 9231 if (need_finder_info && 9232 !(ctx->f_attr.fa_valid_mask & FA_FINDERINFO_VALID)) { 9233 /* Assume zero Finder Info */ 9234 ctx->f_attr.fa_valid_mask |= FA_FINDERINFO_VALID; 9235 bcopy(&zero_finfo, ctx->f_attr.fa_finder_info, sizeof(u_int8_t) * 32); 9236 } 9237 9238 if (need_cmn_user_access && 9239 !(ctx->f_attr.fa_valid_mask & FA_MAX_ACCESS_VALID)) { 9240 /* Assume full access */ 9241 ctx->f_attr.fa_valid_mask |= FA_MAX_ACCESS_VALID; 9242 ctx->f_attr.fa_max_access = SA_RIGHT_FILE_ALL_ACCESS | STD_RIGHT_ALL_ACCESS; 9243 } 9244 9245 SMB_LOG_KTRACE(SMB_DBG_UPDATE_CTX | DBG_FUNC_END, 0, 0, 0, 0, 0); 9246} 9247 9248static int 9249smbfs_vnop_getattrlistbulk(struct vnop_getattrlistbulk_args *ap) 9250/* struct vnop_getattrlistbulk_args { 9251 struct vnodeop_desc *a_desc; 9252 vnode_t a_vp; 9253 struct attrlist *a_alist; 9254 struct vnode_attr *a_vap; 9255 struct uio *a_uio; 9256 void *a_private; 9257 uint64_t a_options; 9258 int32_t *a_eofflag; 9259 int32_t *a_actualcount; 9260 vfs_context_t a_context; 9261 } *ap; */ 9262{ 9263 struct vnode *vp = NULL; 9264 struct vnode *dvp = ap->a_vp; 9265 uio_t uio = ap->a_uio; 9266 vfs_context_t context = ap->a_context; 9267 struct smbnode *dnp = NULL; 9268 struct smbfs_fctx *ctx; 9269 off_t offset, orig_resid; 9270 int error = 0, tmp_error = 0; 9271 struct smb_share *share = NULL; 9272 struct smbmount *smp = NULL; 9273 struct vnode_attr *vap = ap->a_vap; 9274 char *name = NULL; 9275 int free_name = 0; 9276 ssize_t fixedlen = 0, maxfixed_len = 0; 9277 ssize_t variable_len = 0, acl_len = 0; 9278 enum vtype vnode_type = VREG; 9279 9280 /* Check for invalid buffer space. */ 9281 if ((uio_resid(uio) <= 0) || (uio_iovcnt(uio) > 1)) { 9282 SMBDEBUG("Invalid buf size\n"); 9283 return (EINVAL); 9284 } 9285 9286 *(ap->a_actualcount) = 0; 9287 *(ap->a_eofflag) = 0; 9288 9289 /* 9290 * Lock parent dir that we are enumerating 9291 */ 9292 if ((error = smbnode_lock(VTOSMB(dvp), SMBFS_EXCLUSIVE_LOCK))) { 9293 return (error); 9294 } 9295 9296 VTOSMB(dvp)->n_lastvop = smbfs_vnop_getattrlistbulk; 9297 9298 dnp = VTOSMB(dvp); 9299 smp = VTOSMBFS(dvp); 9300 9301 SMB_LOG_KTRACE(SMB_DBG_GET_ATTRLIST_BULK | DBG_FUNC_START, dnp->d_fid, 0, 0, 0, 0); 9302 9303 /* Get Share reference */ 9304 share = smb_get_share_with_reference(VTOSMBFS(dvp)); 9305 9306 /* Non FAT Filesystem and named streams are required */ 9307 if ((share->ss_fstype == SMB_FS_FAT) || 9308 !(share->ss_attributes & FILE_NAMED_STREAMS)) { 9309 smb_share_rele(share, context); 9310 SMBDEBUG("FAT or no named streams so smbfs_vnop_getattrlistbulk not supported\n"); 9311 error = ENOTSUP; 9312 goto done; 9313 } 9314 9315 /* 9316 * Do we need to start or restart the directory listing 9317 * 9318 * The uio_offset is actually just used to store whatever we want. In HFS, 9319 * they store an index and a dir tag. For SMB, we will store just the offset 9320 */ 9321 offset = uio_offset(uio); 9322 if (!dnp->d_fctx || 9323 (dnp->d_fctx->f_share != share) || 9324 (offset == 0) || 9325 (offset != dnp->d_offset)) { 9326 smbfs_closedirlookup(dnp, context); 9327 error = smbfs_smb_findopen(share, dnp, "*", 1, &dnp->d_fctx, TRUE, 9328 context); 9329 } 9330 9331 /* 9332 * The directory fctx keeps a reference on the share so we can release our 9333 * reference on the share now. 9334 */ 9335 smb_share_rele(share, context); 9336 9337 if (error) { 9338 lck_rw_lock_shared(&dnp->n_name_rwlock); 9339 SMBERROR("Can't open search for %s, error = %d", dnp->n_name, error); 9340 lck_rw_unlock_shared(&dnp->n_name_rwlock); 9341 goto done; 9342 } 9343 ctx = dnp->d_fctx; 9344 9345 /* 9346 * They are continuing from some point ahead of us in the buffer. Skip all 9347 * entries until we reach their point in the buffer. 9348 */ 9349 while (dnp->d_offset < offset) { 9350 error = smbfs_findnext(ctx, context); 9351 if (error) { 9352 smbfs_closedirlookup(dnp, context); 9353 goto done; 9354 } 9355 dnp->d_offset++; 9356 } 9357 9358 /* Do we need to allocate va_name? */ 9359 if (VATTR_IS_ACTIVE(vap, va_name)) { 9360 if (vap->va_name == NULL) { 9361 /* We need to allocate space for va_name */ 9362 SMB_MALLOC(name, 9363 char *, 9364 MAXPATHLEN, 9365 M_SMBTEMP, 9366 M_WAITOK | M_ZERO); 9367 if (name == NULL) { 9368 SMBERROR("Malloc for va_name failed \n"); 9369 error = ENOMEM; 9370 goto done; 9371 } 9372 9373 free_name = 1; 9374 } 9375 else { 9376 name = vap->va_name; 9377 } 9378 9379 /* Add name length for termination check */ 9380 variable_len += MAXPATHLEN; 9381 } 9382 9383 /* Loop until we end the search or we don't have enough room for the max element */ 9384 while (uio_resid(uio)) { 9385 /* Get one entry out of the buffer and fill in ctx with its info */ 9386 error = smbfs_findnext(ctx, context); 9387 if (error) { 9388 break; 9389 } 9390 9391 /* 9392 * Get the vnode type. vfs_setup_vattr_from_attrlist() only cares if 9393 * its a dir or not. 9394 */ 9395 vnode_type = (ctx->f_attr.fa_attr & SMB_EFA_DIRECTORY) ? VDIR : VREG; 9396 9397 /* Make sure the vap is zero'd out and set up correctly */ 9398 bzero(vap, sizeof(struct vnode_attr)); 9399 vfs_setup_vattr_from_attrlist(ap->a_alist, vap, vnode_type, &fixedlen, 9400 context); 9401 vap->va_name = name; 9402 9403 /* Calculate maxfixed_len for termination check */ 9404 if (fixedlen > maxfixed_len) { 9405 maxfixed_len = fixedlen; 9406 } 9407 9408 /* 9409 * <14430881> If file IDs are supported by this server, skip any 9410 * child that has the same id as the current parent that we are 9411 * enumerating. Seems like snapshot dirs have the same id as the parent 9412 * and that will cause us to deadlock when we find the vnode with same 9413 * id and then try to lock it again (deadlock on parent id). 9414 */ 9415 if (SSTOVC(share)->vc_misc_flags & SMBV_HAS_FILEIDS) { 9416 if (ctx->f_attr.fa_ino == dnp->n_ino) { 9417 SMBDEBUG("Skipping <%s> as it has same ID as parent\n", 9418 ctx->f_LocalName); 9419 continue; 9420 } 9421 } 9422 9423 if ((ctx->f_share->ss_attributes & FILE_PERSISTENT_ACLS) && 9424 (VATTR_IS_ACTIVE(vap, va_acl) || 9425 VATTR_IS_ACTIVE(vap, va_guuid) || 9426 VATTR_IS_ACTIVE(vap, va_uuuid))) { 9427 /* 9428 * In order to get the ACL, we are going to need a vnode 9429 * created. Someday, we may be able to get the ACL without 9430 * a vnode, but that is a lot of code to change at this time. 9431 */ 9432 tmp_error = smbfs_nget(share, vnode_mount(dvp), 9433 dvp, ctx->f_LocalName, ctx->f_LocalNameLen, 9434 &ctx->f_attr, &vp, 9435 MAKEENTRY, SMBFS_NGET_CREATE_VNODE, 9436 context); 9437 9438 /* Calculate maxacl_len for termination check */ 9439 if (!acl_len) { 9440 acl_len = KAUTH_ACL_SIZE(KAUTH_ACL_MAX_ENTRIES); 9441 } 9442 } 9443 else { 9444 /* 9445 * Check to see if vnode already exists. If so, then can pull the 9446 * data from the inode instead of having to poll the server for 9447 * missing info 9448 * 9449 * <14985596> Go ahead and create the vnode if its not already 9450 * there. This improves Finder browsing performance 9451 */ 9452 tmp_error = smbfs_nget(share, vnode_mount(dvp), 9453 dvp, ctx->f_LocalName, ctx->f_LocalNameLen, 9454 &ctx->f_attr, &vp, 9455 MAKEENTRY, SMBFS_NGET_CREATE_VNODE, 9456 context); 9457 } 9458 9459 SMB_LOG_KTRACE(SMB_DBG_GET_ATTRLIST_BULK | DBG_FUNC_NONE, 9460 0xabc001, tmp_error, 0, 0, 0); 9461 9462 /* Dont care if we got an error or not, just whether vp == NULL or not */ 9463 if (vp != NULL) { 9464 /* 9465 * Enumerates alway return the correct case of the name. 9466 * Update the name and parent if needed. 9467 */ 9468 smbfs_update_name_par(ctx->f_share, dvp, vp, 9469 &ctx->f_attr.fa_reqtime, 9470 ctx->f_LocalName, ctx->f_LocalNameLen); 9471 } 9472 9473 /* 9474 * Is there enough buffer space remaining in the uio to add this? 9475 * Need at least 4 bytes for len, and then 4 bytes for one data element 9476 */ 9477 if (uio_resid(uio) <= 8) { 9478 if (vp != NULL) { 9479 smbnode_unlock(VTOSMB(vp)); 9480 vnode_put(vp); 9481 } 9482 break; 9483 } 9484 9485 /* 9486 * If there is any missing or stale data in the ctx, fill it in 9487 */ 9488 smbfs_update_ctx(vp, vap, ctx, context); 9489 9490 /* 9491 * Fill in the ACL info here if needed. ACL data has to have a 9492 * vnode to use (at least for now). 9493 */ 9494 if ((share->ss_attributes & FILE_PERSISTENT_ACLS) && 9495 (vp != NULL) && 9496 (VATTR_IS_ACTIVE(vap, va_acl) || 9497 VATTR_IS_ACTIVE(vap, va_guuid) || 9498 VATTR_IS_ACTIVE(vap, va_uuuid))) { 9499 DBG_ASSERT(!vnode_isnamedstream(vp)); 9500 (void)smbfs_getsecurity(share, VTOSMB(vp), vap, context); 9501 } 9502 9503 /* 9504 * If we have a vnode, then it must be unlocked before calling 9505 * vfs_attr_pack 9506 */ 9507 if (vp != NULL) { 9508 smbnode_unlock(VTOSMB(vp)); 9509 } 9510 9511 /* 9512 * Fill in the vap using the data from the ctx 9513 */ 9514 tmp_error = smbfs_pack_vap(smp, ctx, vap, context); 9515 if (tmp_error == 0) { 9516 /* Save current resid so can tell if uio is full */ 9517 orig_resid = uio_resid(uio); 9518 9519 /* Copy info from vap into uio */ 9520 tmp_error = vfs_attr_pack(vp, uio, ap->a_alist, ap->a_options, 9521 ap->a_vap, NULL, ap->a_context); 9522 if (tmp_error == 0) { 9523 if (orig_resid == uio_resid(uio)) { 9524 /* No more space in uio */ 9525 tmp_error = ENOBUFS; 9526 } 9527 else { 9528 /* Successfully added an entry */ 9529 *ap->a_actualcount += 1; 9530 dnp->d_offset++; 9531 9532 /* 9533 * Termination check. 9534 * Make sure the uio buffer has enough space 9535 * for another entry. 9536 */ 9537 if (uio_resid(uio) < (maxfixed_len + variable_len + acl_len)) { 9538 tmp_error = ENOBUFS; 9539 } 9540 } 9541 } 9542 else { 9543 SMBERROR("vfs_attr_pack() failed for %s, error %d", 9544 ctx->f_LocalName, tmp_error); 9545 } 9546 } 9547 else { 9548 SMBERROR("smbfs_pack_vap() failed for %s, error %d", 9549 ctx->f_LocalName, tmp_error); 9550 } 9551 9552 /* Done with the vp */ 9553 if (vp != NULL) { 9554 vnode_put(vp); 9555 } 9556 9557 if (tmp_error) { 9558 /* Either got some error or uio is full so all done */ 9559 break; 9560 } 9561 9562 } /* while loop */ 9563 9564 if (error == ENOENT) { 9565 *(ap->a_eofflag) = TRUE; 9566 error = 0; 9567 } 9568 9569done: 9570 /* Last offset into uio_offset. */ 9571 uio_setoffset(uio, dnp->d_offset); 9572 9573 /* If we allocated it, then we free it */ 9574 if ((free_name == 1) && (name != NULL)) { 9575 SMB_FREE(name, M_SMBTEMP); 9576 } 9577 9578 smbnode_unlock(VTOSMB(dvp)); 9579 9580 SMB_LOG_KTRACE(SMB_DBG_GET_ATTRLIST_BULK | DBG_FUNC_END, 9581 error, *ap->a_actualcount, 0, 0, 0); 9582 9583 return (error); 9584} 9585 9586vnop_t **smbfs_vnodeop_p; 9587static struct vnodeopv_entry_desc smbfs_vnodeop_entries[] = { 9588 { &vnop_default_desc, (vnop_t *) vn_default_error }, 9589 { &vnop_advlock_desc, (vnop_t *) smbfs_vnop_advlock }, 9590 { &vnop_close_desc, (vnop_t *) smbfs_vnop_close }, 9591 { &vnop_create_desc, (vnop_t *) smbfs_vnop_create }, 9592 { &vnop_fsync_desc, (vnop_t *) smbfs_vnop_fsync }, 9593 { &vnop_getattr_desc, (vnop_t *) smbfs_vnop_getattr }, 9594 { &vnop_pagein_desc, (vnop_t *) smbfs_vnop_pagein }, 9595 { &vnop_inactive_desc, (vnop_t *) smbfs_vnop_inactive }, 9596 { &vnop_ioctl_desc, (vnop_t *) smbfs_vnop_ioctl }, 9597 { &vnop_link_desc, (vnop_t *) smbfs_vnop_link }, 9598 { &vnop_lookup_desc, (vnop_t *) smbfs_vnop_lookup }, 9599 { &vnop_mkdir_desc, (vnop_t *) smbfs_vnop_mkdir }, 9600 { &vnop_mknod_desc, (vnop_t *) smbfs_vnop_mknod }, 9601 { &vnop_mmap_desc, (vnop_t *) smbfs_vnop_mmap }, 9602 { &vnop_mnomap_desc, (vnop_t *) smbfs_vnop_mnomap }, 9603 { &vnop_open_desc, (vnop_t *) smbfs_vnop_open }, 9604 { &vnop_compound_open_desc, (vnop_t *) smbfs_vnop_compound_open }, 9605 { &vnop_pathconf_desc, (vnop_t *) smbfs_vnop_pathconf }, 9606 { &vnop_pageout_desc, (vnop_t *) smbfs_vnop_pageout }, 9607 { &vnop_copyfile_desc, (vnop_t *) smbfs_vnop_copyfile }, 9608 { &vnop_read_desc, (vnop_t *) smbfs_vnop_read }, 9609 { &vnop_readdir_desc, (vnop_t *) smbfs_vnop_readdir }, 9610 { &vnop_readdirattr_desc, (vnop_t *) smbfs_vnop_readdirattr }, 9611 { &vnop_getattrlistbulk_desc, (vnop_t *) smbfs_vnop_getattrlistbulk }, 9612 { &vnop_readlink_desc, (vnop_t *) smbfs_vnop_readlink }, 9613 { &vnop_reclaim_desc, (vnop_t *) smbfs_vnop_reclaim }, 9614 { &vnop_remove_desc, (vnop_t *) smbfs_vnop_remove }, 9615 { &vnop_rename_desc, (vnop_t *) smbfs_vnop_rename }, 9616 { &vnop_rmdir_desc, (vnop_t *) smbfs_vnop_rmdir }, 9617 { &vnop_setattr_desc, (vnop_t *) smbfs_vnop_setattr }, 9618 { &vnop_symlink_desc, (vnop_t *) smbfs_vnop_symlink }, 9619 { &vnop_write_desc, (vnop_t *) smbfs_vnop_write }, 9620 { &vnop_blockmap_desc, (vnop_t *) smbfs_vnop_blockmap }, 9621 { &vnop_strategy_desc, (vnop_t *) smbfs_vnop_strategy }, 9622 { &vnop_searchfs_desc, (vnop_t *) err_searchfs }, 9623 { &vnop_offtoblk_desc, (vnop_t *) smbfs_vnop_offtoblk }, 9624 { &vnop_blktooff_desc, (vnop_t *) smbfs_vnop_blktooff }, 9625 { &vnop_getxattr_desc, (vnop_t *) smbfs_vnop_getxattr }, 9626 { &vnop_setxattr_desc, (vnop_t *) smbfs_vnop_setxattr }, 9627 { &vnop_removexattr_desc, (vnop_t *) smbfs_vnop_removexattr }, 9628 { &vnop_listxattr_desc, (vnop_t *) smbfs_vnop_listxattr }, 9629 { &vnop_monitor_desc, (vnop_t *) smbfs_vnop_monitor}, 9630 { &vnop_getnamedstream_desc, (vnop_t *) smbfs_vnop_getnamedstream }, 9631 { &vnop_makenamedstream_desc, (vnop_t *) smbfs_vnop_makenamedstream }, 9632 { &vnop_removenamedstream_desc, (vnop_t *) smbfs_vnop_removenamedstream }, 9633 { &vnop_access_desc, (vnop_t *) smbfs_vnop_access }, 9634 { &vnop_allocate_desc, (vnop_t *) smbfs_vnop_allocate }, 9635 { NULL, NULL } 9636}; 9637 9638struct vnodeopv_desc smbfs_vnodeop_opv_desc = 9639 { &smbfs_vnodeop_p, smbfs_vnodeop_entries }; 9640