1/* 2 * Copyright (c) 2000-2001 Boris Popov 3 * All rights reserved. 4 * 5 * Portions Copyright (C) 2001 - 2013 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 useCacheData = (share->ss_flags & SMBS_RECONNECTING); 135 struct smbfattr fattr; 136 int error = smbfs_attr_cachelookup(share, vp, vap, context, useCacheData); 137 138 if (error != ENOENT) 139 return (error); 140 error = smbfs_lookup(share, VTOSMB(vp), NULL, NULL, &fattr, context); 141 if (error) 142 return (error); 143 144 /* 145 * At this point we have the data from the server, so we can 146 * just use cached data for now. See <rdar://problem/13813721>. 147 */ 148 useCacheData = TRUE; 149 150 smbfs_attr_cacheenter(share, vp, &fattr, TRUE, context); 151 return (smbfs_attr_cachelookup(share, vp, vap, context, useCacheData)); 152 } 153 154/* 155 * smbfs_close - The internal open routine, the vnode should be locked 156 * before this is called. We only handle VREG in this routine. 157 * 158 * The calling routine must hold a reference on the share 159 * 160 */ 161int 162smbfs_close(struct smb_share *share, vnode_t vp, int openMode, 163 vfs_context_t context) 164{ 165 struct smbnode *np = VTOSMB(vp); 166 proc_t p = vfs_context_proc(context); 167 struct fileRefEntry *fndEntry = NULL; 168 struct fileRefEntry *curr = NULL; 169 int error = 0; 170 uint16_t accessMode = 0; 171 SMBFID fid = 0; 172 int32_t needOpenFile; 173 uint16_t openAccessMode; 174 uint32_t rights; 175 struct smbfattr *fap = NULL; 176 177 /* 178 * We have more than one open, so before closing see if the file needs to 179 * be reopened 180 */ 181 if ((np->f_refcnt > 1) && (smbfs_smb_reopen_file(share, np, context) == EIO)) { 182 SMBDEBUG(" %s waiting to be revoked\n", np->n_name); 183 np->f_refcnt--; 184 return (0); 185 } 186 187 if (openMode & FREAD) 188 accessMode |= kAccessRead; 189 190 if (openMode & FWRITE) 191 accessMode |= kAccessWrite; 192 193 /* Check the number of times Open() was called */ 194 if (np->f_refcnt == 1) { 195 ubc_msync(vp, 0, ubc_getsize(vp), NULL, UBC_PUSHDIRTY | UBC_SYNC | UBC_INVALIDATE); 196 /* 197 * This is the last Close() we will get, so close sharedForkRef 198 * and any other forks created by ByteRangeLocks 199 */ 200 if (np->f_fid != 0) { 201 SMBFID oldFID = np->f_fid; 202 203 /* Close the shared file first. Clear out the refs to it 204 * first so that no one else trys to use it while I'm waiting 205 * for the close file reply to arrive. There was a case 206 * where cluster i/o was firing off after I sent the close 207 * file req, but had not gotten the close file reply yet 208 * and tyring to still use the shared file 209 */ 210 np->f_fid = 0; /* clear the ref num */ 211 np->f_accessMode = 0; 212 np->f_rights = 0; 213 np->f_openRWCnt = 0; 214 np->f_openRCnt = 0; 215 np->f_openWCnt = 0; 216 np->f_openTotalWCnt = 0; 217 np->f_needClose = 0; 218 np->f_clusterCloseError = 0; 219 /* 220 * They didn't unlock the file before closing. A SMB close will remove 221 * any locks so lets free the memory associated with that lock. 222 */ 223 if (np->f_smbflock) { 224 SMB_FREE(np->f_smbflock, M_LOCKF); 225 np->f_smbflock = NULL; 226 } 227 error = smbfs_smb_close(share, oldFID, context); 228 if (error) { 229 SMBWARNING("close file failed %d on fid %llx\n", 230 error, oldFID); 231 } 232 } 233 234 /* Remove forks that were opened due to ByteRangeLocks or DenyModes */ 235 lck_mtx_lock(&np->f_openDenyListLock); 236 curr = np->f_openDenyList; 237 while (curr != NULL) { 238 error = smbfs_smb_close(share, curr->fid, context); 239 if (error) { 240 SMBWARNING("close file failed %d on fid %llx\n", 241 error, curr->fid); 242 } 243 curr = curr->next; 244 } 245 lck_mtx_unlock(&np->f_openDenyListLock); 246 np->f_refcnt = 0; 247 RemoveFileRef (vp, NULL); /* remove all file refs */ 248 249 /* 250 * We did the last close on the file. This file is 251 * marked for deletion on close. So lets delete it 252 * here. If we get an error then try again when the node 253 * becomes inactive. 254 */ 255 if (np->n_flag & NDELETEONCLOSE) { 256 if (smbfs_smb_delete(share, np, NULL, 0, 0, context) == 0) { 257 np->n_flag &= ~NDELETEONCLOSE; 258 259 /* Assume the file is now deleted on the server */ 260 smb_vhashrem(np); 261 262 /* Lock protects np->n_parent. See <rdar://problem/11824956> */ 263 lck_rw_lock_shared(&np->n_name_rwlock); 264 if (np->n_parent != NULL) { 265 smbfs_attr_touchdir(np->n_parent, (share->ss_fstype == SMB_FS_FAT)); 266 np->n_parent->d_changecnt++; 267 268 /* Remove any negative cache entries. */ 269 if (np->n_parent->n_flag & NNEGNCENTRIES) { 270 np->n_parent->n_flag &= ~NNEGNCENTRIES; 271 cache_purge_negatives(np->n_parent->n_vnode); 272 } 273 } 274 lck_rw_unlock_shared(&np->n_name_rwlock); 275 } 276 } 277 278 /* 279 * It was not cacheable before, but now that all files are closed, 280 * make it cacheable again (if its a valid cacheable file). If 281 * we were caching should we remove attributes cache. Realy only 282 * matters when we turn on cluster io? 283 */ 284 if (vnode_isnocache(vp)) 285 vnode_clearnocache(vp); 286 287 /* Did we change the file during the open */ 288 if (np->n_flag & NATTRCHANGED) 289 np->attribute_cache_timer = 0; 290 291 lck_mtx_lock(&np->f_openStateLock); 292 if (np->f_openState & kNeedRevoke) 293 error = 0; 294 /* 295 * Clear all the f_openState flags, we are closed. If we have a pending 296 * revoke clear that out, the file is closed no need to revoke it now. 297 */ 298 np->f_openState = 0; 299 lck_mtx_unlock(&np->f_openStateLock); 300 301 goto exit; 302 } 303 304 /* More than one open */ 305 306 /* 307 * See if we can match this Close() to a matching file that has byte range 308 * locks or denyModes. 309 * 310 * NOTE: FHASLOCK can be set by open with O_EXCLUSIVE or O_SHARED which 311 * maps to my deny modes or FHASLOCK could also have been set/cleared 312 * by calling flock directly. 313 * 314 * Cases that work are: 315 * 1) Carbon using deny modes and thus FHASLOCK maps to my deny modes. 316 * No flock being used. 317 * 2) Cocoa using open with O_EXCLUSIVE or O_SHARED and not calling flock. 318 * 3) Cocoa using open, then calling flock and later calling flock 319 * to unlock before close. 320 * 4) Cocoa open, then calling flock, but not calling flock to unlock 321 * before close. I would fall through to the shared fork code correctly. 322 * 323 * Cases that may not work are: 324 * 1) Carbon using deny modes and then calling flock to unlock, thus 325 * clearing FHASLOCK flag.I would assume it was the shared file. 326 * 2) Cocoa open with O_EXCLUSIVE or O_SHARED and then calling flock 327 * to lock and then unlock, then calling close. 328 * 3) ??? 329 */ 330 if (openMode & FHASLOCK) { 331 uint16_t tempAccessMode = accessMode; 332 333 /* Try with denyWrite, if not found, then try with denyRead/denyWrite */ 334 tempAccessMode |= kDenyWrite; 335 error = FindFileRef(vp, p, tempAccessMode, kExactMatch, 0, 0, &fndEntry, 336 &fid); 337 if (error != 0) { 338 tempAccessMode |= kDenyRead; 339 error = FindFileRef(vp, p, tempAccessMode, kExactMatch, 0, 0, 340 &fndEntry, &fid); 341 } 342 if (error == 0) 343 accessMode = tempAccessMode; 344 } else { 345 /* No deny modes used, so look for any forks opened for byteRangeLocks */ 346 error = FindFileRef(vp, p, accessMode, kExactMatch, 0, 0, &fndEntry, &fid); 347 } 348 349 /* always decrement the count, dont care if got an error or not */ 350 np->f_refcnt--; 351 352 /* 353 * We have an Open Deny entry that is being used by more than one open call, 354 * just decrement it and get out. 355 * This code should be combined with the code right below here. 356 */ 357 if ((error == 0) && fndEntry && (fndEntry->refcnt > 0)) { 358 fndEntry->refcnt--; 359 goto exit; 360 } 361 362 /* 363 * We have an Open Deny entry that is all done. Time to close it. 364 * This code should be combined with the code right above here. 365 */ 366 if ((error == 0) && fndEntry) { 367 error = smbfs_smb_close(share, fndEntry->fid, context); 368 /* We are not going to get another close, so always remove it from the list */ 369 RemoveFileRef(vp, fndEntry); 370 goto exit; 371 } 372 373 /* 374 * Not an open deny mode open. 375 * 376 * An oddity. If first open was read/write/denyWrite and then a second 377 * open of just read, then the second open will open the shared fork. 378 * Now, get a close on the "read" fork, the np->f_refcnt will be 2, and we 379 * will end up here. The np->f_refcnt will be decremented to 1 so the next 380 * close call will close everything. In the meantime, we end up leaving 381 * the shared fork open with "read" and thus we actually have two forks 382 * open, one for the read/write/denyWrite and the other is the shared fork. 383 * We have has this behavior for a long time and just have not noticed. 384 * Since its an edge case and no one has complained, we can leave it this 385 * way for now. 386 */ 387 needOpenFile = 0; 388 openAccessMode = 0; 389 fid = 0; 390 rights = SMB2_READ_CONTROL; 391 392 /* 393 * Just return 0 for no err, but dont close the file since another 394 * process is still using it 395 */ 396 error = 0; 397 398 /* Check to downgrade access mode if needed */ 399 switch (accessMode) { 400 case (kAccessRead | kAccessWrite): 401 np->f_openRWCnt -= 1; 402 if ((np->f_openRWCnt == 0) && (np->f_openRCnt > 0) && (np->f_openWCnt == 0)) { 403 /* drop from rw to read only */ 404 needOpenFile = 1; 405 openAccessMode = kAccessRead; 406 rights |= SMB2_FILE_READ_DATA; 407 } 408 /* Dont ever downgrade to write only since Unix expects read/write */ 409 break; 410 case kAccessRead: 411 np->f_openRCnt -= 1; 412 /* Dont ever downgrade to write only since Unix expects read/write */ 413 break; 414 case kAccessWrite: 415 np->f_openWCnt -= 1; 416 if ( (np->f_openRCnt > 0) && (np->f_openRWCnt == 0) && 417 (np->f_openWCnt == 0) ) { 418 /* drop from rw to read only */ 419 needOpenFile = 1; 420 openAccessMode = kAccessRead; 421 rights |= SMB2_FILE_READ_DATA; 422 } 423 break; 424 } 425 /* set up for the open fork */ 426 if (needOpenFile == 1) { 427 SMB_MALLOC(fap, 428 struct smbfattr *, 429 sizeof(struct smbfattr), 430 M_SMBTEMP, 431 M_WAITOK | M_ZERO); 432 if (fap == NULL) { 433 SMBERROR("SMB_MALLOC failed\n"); 434 error = ENOMEM; 435 goto exit; 436 } 437 438 error = smbfs_smb_open_file(share, np, 439 rights, NTCREATEX_SHARE_ACCESS_ALL, &fid, 440 NULL, 0, FALSE, 441 fap, context); 442 if (error == 0) { 443 SMBFID oldFID = np->f_fid; 444 445 /* We are downgrading the open flush it out any data */ 446 ubc_msync(vp, 0, ubc_getsize(vp), NULL, UBC_PUSHDIRTY | UBC_SYNC | UBC_INVALIDATE); 447 /* Close the shared file first and use this new one now 448 * Switch the ref before closing the old shared file so the 449 * old file wont get used while its being closed. 450 */ 451 np->f_fid = fid; /* reset the ref num */ 452 np->f_accessMode = openAccessMode; 453 np->f_rights = rights; 454 error = smbfs_smb_close(share, oldFID, context); 455 if (error) { 456 SMBWARNING("close file failed %d on fid %llx\n", error, oldFID); 457 } 458 } 459 } 460 461exit: 462 if ((error == 0) && (openMode & FWRITE) && (np->f_openTotalWCnt > 0)) { 463 np->f_openTotalWCnt--; 464 } 465 466 if (fap != NULL) { 467 SMB_FREE(fap, M_SMBTEMP); 468 } 469 470 return (error); 471} 472 473/* 474 * smbfs_vnop_close - smbfs vnodeop entry point 475 * vnode_t a_vp; 476 * int a_fflags; 477 * vfs_context_t a_context; 478 */ 479static int 480smbfs_vnop_close(struct vnop_close_args *ap) 481{ 482 vnode_t vp = ap->a_vp; 483 int error = 0; 484 struct smbnode *np; 485 486 487 if (smbnode_lock(VTOSMB(vp), SMBFS_EXCLUSIVE_LOCK) != 0) 488 return (0); 489 np = VTOSMB(vp); 490 np->n_lastvop = smbfs_vnop_close; 491 492 if (vnode_isdir(vp)) { 493 if (--np->d_refcnt) { 494 error = 0; 495 } else { 496 smbfs_closedirlookup(np, ap->a_context); 497 } 498 } else if ( vnode_isreg(vp) || vnode_islnk(vp) ) { 499 int clusterCloseError = np->f_clusterCloseError; 500 struct smb_share *share; 501 502 /* if its readonly volume, then no sense in trying to write out dirty data */ 503 if (!vnode_vfsisrdonly(vp) && smbfsIsCacheable(vp)) { 504 if (np->n_flag & NISMAPPED) { 505 /* More expensive, but handles mmapped files */ 506 ubc_msync (vp, 0, ubc_getsize(vp), NULL, UBC_PUSHDIRTY | UBC_SYNC); 507 } else { 508 /* Less expensive, but does not handle mmapped files */ 509 cluster_push(vp, IO_CLOSE); 510 } 511 } 512 share = smb_get_share_with_reference(VTOSMBFS(vp)); 513 514 /* Do any pending set eof or flushes before closing the file */ 515 smbfs_smb_fsync(share, np, ap->a_context); 516 517 error = smbfs_close(share, vp, ap->a_fflag, ap->a_context); 518 smb_share_rele(share, ap->a_context); 519 if (!error) 520 error = clusterCloseError; 521 } 522 smbnode_unlock(np); 523 return (error); 524} 525 526static void 527smbfs_get_rights_shareMode(int fmode, uint32_t *rights, uint32_t *shareMode, uint16_t *accessMode) 528{ 529 /* 530 * We always ask for READ_CONTROL so we can always get the owner/group 531 * IDs to satisfy a stat. 532 */ 533 *rights = SMB2_READ_CONTROL; 534 if (fmode & FREAD) { 535 *accessMode |= kAccessRead; 536 *rights |= SMB2_FILE_READ_DATA; 537 } 538 if (fmode & FWRITE) { 539 *accessMode |= kAccessWrite; 540 *rights |= SMB2_FILE_APPEND_DATA | SMB2_FILE_WRITE_DATA; 541 } 542 543 /* 544 * O_EXLOCK -> denyRead/denyWrite is always cacheable since we have exclusive 545 * access. 546 * O_SHLOCK -> denyWrite is always cacheable since we are the only one who 547 * can change the file. 548 * denyNone -> is not cacheable if from Carbon (a FSCTL call from Carbon 549 * will set the vnode to be non cacheable). It is always 550 * cacheable from Unix since that is what home dirs mainly use. 551 */ 552 *shareMode = NTCREATEX_SHARE_ACCESS_ALL; 553 if (fmode & O_SHLOCK) { 554 *accessMode |= kDenyWrite; 555 /* Remove the wr shared access */ 556 *shareMode &= ~NTCREATEX_SHARE_ACCESS_WRITE; 557 } 558 559 if (fmode & O_EXLOCK) { 560 *accessMode |= kDenyWrite; 561 *accessMode |= kDenyRead; 562 /* Remove the rdwr shared access */ 563 *shareMode &= ~(NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_READ); 564 } 565} 566 567static void 568smbfs_update_RW_cnts(vnode_t vp, uint16_t accessMode) 569{ 570 /* count nbr of opens with rw, r, w so can downgrade access in close if needed */ 571 struct smbnode *np = VTOSMB(vp); 572 573 switch (accessMode) { 574 case (kAccessWrite | kAccessRead): 575 np->f_openRWCnt += 1; 576 break; 577 case kAccessRead: 578 np->f_openRCnt += 1; 579 break; 580 case kAccessWrite: 581 np->f_openWCnt += 1; 582 break; 583 } 584} 585 586static int 587smbfs_create_open(struct smb_share *share, vnode_t dvp, struct componentname *cnp, 588 struct vnode_attr *vap, uint32_t open_disp, int fmode, 589 SMBFID *fidp, struct smbfattr *fattrp, vnode_t *vpp, 590 vfs_context_t context) 591{ 592 struct smbnode *dnp = VTOSMB(dvp); 593 struct smbmount *smp = VTOSMBFS(dvp); 594 vnode_t vp; 595 const char *name = cnp->cn_nameptr; 596 size_t nmlen = cnp->cn_namelen; 597 int error = 0; 598 uint32_t rights, addedReadRights, saved_rights; 599 uint16_t accessMode = 0; 600 uint16_t savedAccessMode = 0; 601 struct smbnode *np; 602 uint32_t shareMode = 0; 603 char *target = NULL; 604 size_t targetlen = 0; 605 struct smb2_durable_handle dur_handle; 606 607 /* 608 * We have NO vnode for the target! 609 * The target may or may not exist on the server. 610 * The target could be a dir or a file. 611 * 612 * If its a dir, then it can not be a creation. Use vnop_mkdir instead. 613 * It could be an open on a dir which SMB protocol allows. Make sure 614 * to close the dir afterwards. 615 * 616 * If its a file, it cant be a symlink, use vnop_link instead. 617 * It could be a create and open on a file. 618 * Since a vnode was not found for the file, we know its not already open 619 * by this client. This means I know its the FIRST open call. 620 * 621 * dnp should be locked when this function is called 622 */ 623 624 *fidp = 0; 625 626 smbfs_get_rights_shareMode(fmode, &rights, &shareMode, &accessMode); 627 savedAccessMode = accessMode; /* Save the original access requested */ 628 /* 629 * If opening with write only, try opening it with read/write. Unix 630 * expects read/write access like open/map/close/PageIn. This also helps 631 * the cluster code since if write only, the reads will fail in the 632 * cluster code since it trys to page align the requests. 633 * 634 * NOTE: Since this call only creates items that are regular files we always 635 * set the vtype to VREG. The smbfs_smb_ntcreatex only uses that on create. 636 */ 637 addedReadRights = (accessMode == kAccessWrite) ? SMB2_FILE_READ_DATA : 0; 638 saved_rights = rights | addedReadRights; 639 640 error = smbfs_smb_ntcreatex(share, dnp, 641 rights | addedReadRights, shareMode, VREG, 642 fidp, name, nmlen, 643 open_disp, 0, fattrp, 644 TRUE, NULL, context); 645 646 if (error && addedReadRights) { 647 addedReadRights = 0; 648 saved_rights = rights; 649 650 error = smbfs_smb_ntcreatex(share, dnp, 651 rights, shareMode, VREG, 652 fidp, name, nmlen, 653 open_disp, 0, fattrp, 654 TRUE, NULL, context); 655 } 656 657 if (error) { 658 return error; 659 } 660 661 /* Reparse point need to get the reparse tag */ 662 if (fattrp->fa_attr & SMB_EFA_REPARSE_POINT) { 663 error = smbfs_smb_get_reparse_tag(share, *fidp, &fattrp->fa_reparse_tag, 664 &target, &targetlen, context); 665 if (error) { 666 (void) smbfs_smb_close(share, *fidp, context); 667 return error; 668 } 669 } 670 671 /* Create the vnode using fattr info and return the created vnode */ 672 error = smbfs_nget(share, vnode_mount(dvp), 673 dvp, name, nmlen, 674 fattrp, &vp, 675 cnp->cn_flags, SMBFS_NGET_CREATE_VNODE, 676 context); 677 if (error) { 678 if (target) { 679 SMB_FREE(target, M_TEMP); 680 } 681 (void) smbfs_smb_close(share, *fidp, context); 682 return error; 683 } 684 685 /* 686 * If they passed in a vnode then we no longer need it, so remove the 687 * reference. The smbfs_nget always returns us a vnode with a reference. The 688 * vnode could be the same or a new one. 689 */ 690 if (*vpp) { 691 vnode_put(*vpp); 692 } 693 *vpp = vp; 694 np = VTOSMB(vp); 695 696 /* 697 * We treat directories, files and symlinks different. Since currently we 698 * only handle reparse points as dfs triggers or symlinks we can ignore 699 * treating reparse points special. 700 */ 701 if (vnode_isdir(vp)) { 702 /* We opened a directory, increment its ref count and close it */ 703 np->d_refcnt++; 704 (void)smbfs_smb_close(share, *fidp, context); 705 } else if (vnode_islnk(vp)) { 706 /* We opened a symlink, close it */ 707 (void)smbfs_smb_close(share, *fidp, context); 708 if (target && targetlen) { 709 smbfs_update_symlink_cache(np, target, targetlen); 710 } 711 } else if (vnode_isreg(vp)) { 712 /* We opened the file so bump ref count */ 713 np->f_refcnt++; 714 715 np->f_rights = rights; 716 np->f_accessMode = accessMode; 717 if (addedReadRights) { 718 np->f_rights |= SMB2_FILE_READ_DATA; 719 np->f_accessMode |= kAccessRead; 720 } 721 722 /* if deny modes were used, save the file ref into file list */ 723 if ((fmode & O_EXLOCK) || (fmode & O_SHLOCK)) { 724 error = smb2_smb_dur_handle_init(share, np, &dur_handle); 725 if (error == 0) { 726 /* 727 * %%% TO DO - can we improve the performance of this? 728 * Want to get a durable handle, but the lease key consists 729 * of the file ID, so have to wait until the first create 730 * succeeds which gets us the file ID, then close it and reopen 731 * it but this time requesting the durable handle. 732 */ 733 (void) smbfs_smb_close(share, *fidp, context); 734 735 error = smbfs_smb_ntcreatex(share, dnp, 736 saved_rights, shareMode, VREG, 737 fidp, name, nmlen, 738 FILE_OPEN, 0, fattrp, 739 FALSE, &dur_handle, context); 740 } 741 else { 742 /* 743 * Durable handles must not be supported by this server, just 744 * use the earlier open which must have worked. 745 * Clear the durable handle not supported error 746 */ 747 error = 0; 748 } 749 750 if (error == 0) { 751 /* 752 * Either durable handles not supported or reopening the file 753 * with durable handle worked so save file ref 754 */ 755 AddFileRef (vp, vfs_context_proc(context), accessMode, rights, 756 *fidp, dur_handle, NULL); 757 } 758 } 759 else { 760 np->f_fid = *fidp; 761 smbfs_update_RW_cnts(vp, savedAccessMode); 762 if (accessMode == kAccessWrite) { 763 /* if opened with just write, then turn off cluster code */ 764 vnode_setnocache(vp); 765 } 766 } 767 } 768 769 /* If it was allocated then free, since we are done with it now */ 770 if (target) { 771 SMB_FREE(target, M_TEMP); 772 } 773 774 if (fattrp->fa_created_disp == FILE_CREATE) { 775 struct timespec ts; 776 /* 777 * We just created the file, so we have no finder info and the resource fork 778 * should be empty. So set our cache timers to reflect this information 779 */ 780 nanouptime(&ts); 781 VTOSMB(vp)->finfo_cache = ts.tv_sec; 782 VTOSMB(vp)->rfrk_cache_timer = ts.tv_sec; 783 784 /* 785 * On create, an initial ACL can be set. 786 * If unix extensions are supported, then can set mode, owner, group. 787 */ 788 if (vap != NULL) { 789 smbfs_set_create_vap(share, vap, vp, context, TRUE); /* Set the REAL create attributes NOW */ 790 } 791 792 smbfs_attr_touchdir(dnp, (share->ss_fstype == SMB_FS_FAT)); 793 794 dnp->d_changecnt++; 795 796 /* Remove any negative cache entries. */ 797 if (dnp->n_flag & NNEGNCENTRIES) { 798 dnp->n_flag &= ~NNEGNCENTRIES; 799 cache_purge_negatives(dvp); 800 } 801 802 /* blow away statfs cache */ 803 smp->sm_statfstime = 0; 804 } 805 /* smbfs_nget returns a locked node, unlock it */ 806 smbnode_unlock(VTOSMB(vp)); /* Release the smbnode lock */ 807 808 return (error); 809} 810 811/* 812 * smbfs_open - The internal open routine, the vnode should be locked 813 * before this is called. 814 * 815 * The calling routine must hold a reference on the share 816 * 817 */ 818int 819smbfs_open(struct smb_share *share, vnode_t vp, int mode, 820 vfs_context_t context) 821{ 822 proc_t p = vfs_context_proc(context); 823 struct smbnode *np = VTOSMB(vp); 824 uint16_t accessMode = 0; 825 uint16_t savedAccessMode = 0; 826 uint32_t rights; 827 uint32_t shareMode; 828 SMBFID fid = 0; 829 int error = 0; 830 int warning = 0; 831 struct smbfattr *fap = NULL; 832 struct smb2_durable_handle dur_handle, *dptr; 833 int do_create; 834 uint32_t disp; 835 struct fileRefEntry *fndEntry = NULL; 836 837 /* It was already open so see if the file needs to be reopened */ 838 if ((np->f_refcnt) && 839 ((error = smbfs_smb_reopen_file(share, np, context)) != 0)) { 840 SMBDEBUG(" %s waiting to be revoked\n", np->n_name); 841 return (error); 842 } 843 844 SMB_MALLOC(fap, 845 struct smbfattr *, 846 sizeof(struct smbfattr), 847 M_SMBTEMP, 848 M_WAITOK | M_ZERO); 849 if (fap == NULL) { 850 SMBERROR("SMB_MALLOC failed\n"); 851 error = ENOMEM; 852 goto exit; 853 } 854 855 smbfs_get_rights_shareMode(mode, &rights, &shareMode, &accessMode); 856 savedAccessMode = accessMode; /* Save the original access requested */ 857 858 if ((mode & O_EXLOCK) || (mode & O_SHLOCK)) { 859 /* 860 * if using deny modes and I had to open the file myself, then close 861 * the file now so it does not interfere with the deny mode open. 862 * We only do this in read. 863 */ 864 if (np->f_needClose) { 865 np->f_needClose = 0; 866 warning = smbfs_close(share, vp, FREAD, context); 867 if (warning) 868 SMBWARNING("error %d closing %s\n", warning, np->n_name); 869 } 870 871 /* Using deny modes, see if already in file list */ 872 error = FindFileRef(vp, p, accessMode, kExactMatch, 0, 0, &fndEntry, &fid); 873 if (error == 0) { 874 /* 875 * Already in list due to previous open with deny modes. Can't have 876 * two exclusive or two write/denyWrite. Multiple read/denyWrites are 877 * allowed. 878 */ 879 if ((accessMode & kDenyWrite) && (accessMode & kAccessWrite)) { 880 error = EBUSY; 881 goto exit; 882 } 883 884 if (mode & O_EXLOCK) { 885 if ((accessMode & kAccessRead) && !(accessMode & kAccessWrite)) { 886 /* 887 * Multiple r/dR/dW are allowed, see FindFileRef for 888 * more details 889 */ 890 } 891 else { 892 error = EBUSY; 893 goto exit; 894 } 895 } 896 897 DBG_ASSERT(fndEntry); 898 /* 899 * We are going to reuse this Open Deny entry. Up the counter so 900 * we will know not to free it until the counter goes back to zero. 901 */ 902 fndEntry->refcnt++; 903 } 904 else { 905 /* 906 * Check one more time looking for other pids that might already 907 * have the file open for exclusive or shared access that will 908 * cause this open to get denied. This is to reduce the number of 909 * times a handle lease break will occur with SMB 2.x. If we lose 910 * the handle lease, then reopening a durable handle reconnect will 911 * fail. 912 */ 913 error = FindFileRef(vp, NULL, accessMode, kPreflightOpen, 0, 0, &fndEntry, &fid); 914 if (error == 0) { 915 /* Some other process has it open already */ 916 error = EBUSY; 917 goto exit; 918 } 919 920 /* not in list, so open new file */ 921 922 /* Request a durable handle */ 923 dptr = NULL; 924 error = smb2_smb_dur_handle_init(share, np, &dur_handle); 925 if (!error) { 926 dptr = &dur_handle; 927 } 928 929 if (np->n_flag & N_ISRSRCFRK) { 930 disp = FILE_OPEN_IF; 931 do_create = TRUE; 932 } 933 else { 934 disp = FILE_OPEN; 935 do_create = FALSE; 936 } 937 938 error = smbfs_smb_ntcreatex(share, np, 939 rights, shareMode, VREG, 940 &fid, NULL, 0, 941 disp, FALSE, fap, 942 do_create, dptr, context); 943 if (error == 0) { 944 /* if open worked, save the file ref into file list */ 945 AddFileRef (vp, p, accessMode, rights, fid, dur_handle, NULL); 946 } 947 } 948 goto exit; 949 } 950 951 /* 952 * If we get here, then deny modes are NOT being used. If the open call is 953 * coming in from Carbon, then Carbon will follow immediately with an FSCTL 954 * to turn off caching (I am assuming that denyNone means this file will 955 * be shared among multiple process and that ByteRangeLocking will be used). 956 * 957 * no deny modes, so use the shared file reference 958 * 959 */ 960 /* We have open file descriptor for non deny mode opens */ 961 if (np->f_fid != 0) { 962 /* Already open check to make sure current access is sufficient */ 963 int needUpgrade = 0; 964 switch (np->f_accessMode) { 965 case (kAccessRead | kAccessWrite): 966 /* Currently RW, can't do any better than that so dont open a new fork */ 967 break; 968 case kAccessRead: 969 /* Currently only have Read access, if they want Write too, then open as RW */ 970 if (accessMode & kAccessWrite) { 971 needUpgrade = 1; 972 accessMode |= kAccessRead; /* keep orginal mode */ 973 rights |= SMB2_FILE_READ_DATA; 974 } 975 break; 976 case kAccessWrite: 977 /* Currently only have Write access, if they want Read too, then open as RW */ 978 if (accessMode & kAccessRead) { 979 needUpgrade = 1; 980 accessMode |= kAccessWrite; 981 rights |= SMB2_FILE_APPEND_DATA | SMB2_FILE_WRITE_DATA; 982 } 983 break; 984 } 985 if (! needUpgrade) /* the existing open is good enough */ 986 goto ShareOpen; 987 } else if (accessMode == kAccessWrite) { 988 /* 989 * If opening with write only, try opening it with read/write. Unix 990 * expects read/write access like open/map/close/PageIn. This also helps 991 * the cluster code since if write only, the reads will fail in the 992 * cluster code since it trys to page align the requests. 993 */ 994 995 /* 996 * Preflight for open deny to preserve handle lease. More details in 997 * O_EXLOCK/O_SHLOCK code above. 998 */ 999 error = FindFileRef(vp, NULL, accessMode | kAccessRead, kPreflightOpen, 1000 0, 0, &fndEntry, &fid); 1001 if (error != 0) { 1002 /* Not already open locally, so try to open it */ 1003 error = smbfs_smb_open_file(share, np, 1004 rights | SMB2_FILE_READ_DATA, shareMode, &fid, 1005 NULL, 0, FALSE, 1006 fap, context); 1007 if (error == 0) { 1008 np->f_fid = fid; 1009 np->f_rights = rights | SMB2_FILE_READ_DATA; 1010 np->f_accessMode = accessMode | kAccessRead; 1011 goto ShareOpen; 1012 } 1013 } 1014 } 1015 1016 /* 1017 * Preflight for open deny to preserve handle lease. More details in 1018 * O_EXLOCK/O_SHLOCK code above. 1019 */ 1020 error = FindFileRef(vp, NULL, accessMode, kPreflightOpen, 0, 0, &fndEntry, 1021 &fid); 1022 if (error == 0) { 1023 /* Some other process has it open already */ 1024 error = EBUSY; 1025 goto exit; 1026 } 1027 1028 error = smbfs_smb_open_file(share, np, 1029 rights, shareMode, &fid, 1030 NULL, 0, FALSE, 1031 fap, context); 1032 if (error) 1033 goto exit; 1034 1035 /* 1036 * We already had it open (presumably because it was open with insufficient 1037 * rights.) So now close the old open, if we already had it open. 1038 */ 1039 if (np->f_refcnt && 1040 (np->f_fid != 0)) { 1041 warning = smbfs_smb_close(share, np->f_fid, context); 1042 if (warning) 1043 SMBWARNING("error %d closing %s\n", warning, np->n_name); 1044 } 1045 np->f_fid = fid; 1046 np->f_rights = rights; 1047 np->f_accessMode = accessMode; 1048 1049ShareOpen: 1050 smbfs_update_RW_cnts(vp, savedAccessMode); 1051 if (accessMode == kAccessWrite) { 1052 /* if opened with just write, then turn off cluster code */ 1053 vnode_setnocache(vp); 1054 } 1055exit: 1056 if (!error) { 1057 /* We opened the file or pretended too; either way bump the count */ 1058 np->f_refcnt++; 1059 1060 /* keep track of how many opens for this file had write access */ 1061 if (mode & FWRITE) { 1062 np->f_openTotalWCnt++; 1063 } 1064 } 1065 1066 if (fap != NULL) { 1067 SMB_FREE(fap, M_SMBTEMP); 1068 } 1069 1070 return (error); 1071} 1072 1073static int 1074smbfs_vnop_open_common(vnode_t vp, int mode, vfs_context_t context, void *n_lastvop) 1075{ 1076 struct smbnode *np; 1077 int error; 1078 1079 /* We only open files and directories and symlinks */ 1080 if (!vnode_isreg(vp) && !vnode_isdir(vp) && !vnode_islnk(vp)) { 1081 return (EACCES); 1082 } 1083 1084 if ((error = smbnode_lock(VTOSMB(vp), SMBFS_EXCLUSIVE_LOCK))) 1085 return (error); 1086 1087 np = VTOSMB(vp); 1088 np->n_lastvop = n_lastvop; 1089 1090 /* Just mark that the directory was opened */ 1091 if (vnode_isdir(vp)) { 1092 np->d_refcnt++; 1093 error = 0; 1094 } else { 1095 struct smb_share * share; 1096 1097 share = smb_get_share_with_reference(VTOSMBFS(vp)); 1098 1099 if (mode & O_TRUNC) { 1100 /* If truncating the file on open, do any pending set eofs */ 1101 smbfs_smb_fsync(share, np, context); 1102 } 1103 1104 error = smbfs_open(share, vp, mode, context); 1105 /* 1106 * We created the file with different posix modes than request in 1107 * smbfs_vnop_create. We need to correct that here, so set the posix 1108 * modes to those request on create. See smbfs_set_create_vap for more 1109 * details on this issue. 1110 */ 1111 if ((error == 0) && (np->set_create_va_mode) && (mode & O_CREAT)) { 1112 struct vnode_attr vap; 1113 1114 np->set_create_va_mode = FALSE; /* Only try once */ 1115 VATTR_INIT(&vap); 1116 VATTR_SET_ACTIVE(&vap, va_mode); 1117 vap.va_mode = np->create_va_mode; 1118 error = smbfs_setattr(share, vp, &vap, context); 1119 if (error) /* Got an error close the file and return the error */ 1120 (void)smbfs_close(share, vp, mode, context); 1121 } 1122 smb_share_rele(share, context); 1123 } 1124 if (error == EBUSY) 1125 error = EAGAIN; 1126 1127 smbnode_unlock(np); 1128 return(error); 1129} 1130 1131/* 1132 * smbfs_vnop_compound_open - smbfs vnodeop entry point 1133 * vnode_t a_dvp; 1134 * vnode_t *a_vpp; 1135 * int a_fmode; 1136 * struct componentname *a_cnp; 1137 * vnode_attr *a_vap; 1138 * uint32_t a_flags; 1139 * uint32_t *a_status; 1140 * vfs_context_t context; 1141 * int (*a_open_create_authorizer); 1142 * int (*a_open_existing_authorizer); 1143 * void *a_reserved; 1144 * 1145 * In broad strokes, our compound Open VNOP will be able to act as a 1146 * VNOP_LOOKUP(), a VNOP_OPEN(), and possibly a VNOP_CREATE(), all in one trip 1147 * to the filesystem. Depending on flags, it may execute an operation similar 1148 * to an open(2) with O_CREAT: lookup, create if not present, and open. It may 1149 * also act as a simple open(2) without O_CREAT: lookup and open if present. 1150 * When it returns successfully, the file it has found or created will be "open" 1151 * and ready to be hooked into a file descriptor. As we will discuss later, this 1152 * call may under some circumstances return to VFS with its operation unfinished, 1153 * to request help from VFS, or fail but nonetheless return a vnode. Filesystems 1154 * will be responsible for calling the passed-in authorizer routines to make sure 1155 * that the caller can legitimately perform the requested action. 1156 * 1157 * Arguments in Detail 1158 * 1159 * 1. a_dvp - The directory in which to open/create. The directory vnode is 1160 * equivalent to what would be passed to VNOP_LOOKUP() or VNOP_CREATE(): 1161 * it is the directory in which we wish to open a file, possibly doing 1162 * a create if the file is not already present. 1163 * 2. a_vpp - Resulting vnode. This argument is a pointer to a "vnode_t" 1164 * in which the filesystem can place a pointer to the vnode for a file 1165 * it either looks up or creates. In the event of a hit in the name 1166 * cache, VFS will pass a file to the filesystem in *a_vpp. In that 1167 * case, the filesystem will be free to call vnode_put() on that vnode 1168 * and replace it with another of its choosing. In the event of a cache 1169 * miss, *a_vpp will store NULLVP. On success, the pointer installed at 1170 * this address shall point to an "opened" vnode. On failure, it may 1171 * point to a vnode which is not open. Because several facilities in 1172 * the kernel--notably auditing and kdebug support for fs_usage--rely 1173 * on examining vnodes between lookup and a subsequent VNOP, filesystems 1174 * should make every effort to return a vnode with an iocount if a lookup 1175 * would have succeeded for that file, regardless of whether the main 1176 * operation has failed. This subtlety will apply to all other compound 1177 * VNOPs as well, including those which might fail with EEXIST (e.g. mkdir). 1178 * An unopened vnode may also be returned because more help is required 1179 * from VFS (EKEEPLOOKING). 1180 * 3. a_fmode - Open mode. This field will contain open flags as normally 1181 * passed to VNOP_OPEN(), e.g. O_TRUNC. For filesystems implementing 1182 * compound open, O_TRUNC must be handled as part of the compound open 1183 * call--a subsequent VNOP_SETATTR() call will not be sent to set the size. 1184 * 4. a_cnp - Path to look up. This field will contain a componentname, as 1185 * passed to VNOP_LOOKUP() or VNOP_CREATE(), specifying the name of the 1186 * file to look up and possibly create. 1187 * 5. a_vap - Attributes with which to create, if appropriate. This field 1188 * will contain a pointer to vnode attributes to be used in creating a 1189 * file. In the event of an open without O_CREAT, this field will be NULL. 1190 * In the event of a cache hit, it will also be NULL, as we wish to take 1191 * a fast path in this case which does not involve the heavyweight operation 1192 * of initializing creation attributes. This field can be ignored in 1193 * the event that an existing file is detected. 1194 * 6. a_flags - VNOP-control flags. This field will contain control flags 1195 * specific to the compound open VNOP. For now, there will be only one 1196 * flag: VNOP_COMPOUND_OPEN_DO_CREATE will indicate that if no existing 1197 * file is found, a new one is to be created (authorization, etc. permitting). 1198 * 7. a_status - Information about results. The filesystem will use this 1199 * field to return information about the result of the VNOP. At the moment, 1200 * there will be only one flag: COMPOUND_OPEN_STATUS_DID_CREATE will 1201 * indicate that a file was created by this call. The field will be set 1202 * to zero before a pointer is passed to the filesystem, so the FS will 1203 * be free (for now) to only touch it in the event of having done a 1204 * create. COMPOUND_OPEN_STATUS_DID_CREATE should never be set if 1205 * VNOP_COMPOUND_OPEN_DO_CREATE was not set in a_flags. 1206 * 8. a_context - Authorization context. This field is a vfs_context_t, 1207 * just as is passed to most VNOPs. 1208 * 9. a_open_create_authorizer - Authorizer for create case. This field 1209 * will contain a pointer to a function to be called to authorize creating 1210 * a file. It need only be called if a file is to be created; for an 1211 * existing file, a_open_existing_authorizer should be used. The 1212 * componentname and vnode_attr passed to this function should be exactly 1213 * those which were passed to the VNOP, because opaque data in these 1214 * structures, installed by VFS, will be interpreted in authorization 1215 * (the same will apply to all other authorizer callbacks). Some additional 1216 * validation which is not authorization per se, but which is currently 1217 * performed in VFS on behalf of the filesystem, will also be executed 1218 * here. As a result of that validation, a variety of errors may be 1219 * returned; these should generally be passed back to VFS. Filesystems 1220 * which will attempt a compound RPC that may result in a file's being 1221 * created should always call this function beforehand. In that case, 1222 * if authorization is denied, the filesystem should attempt an "open 1223 * without O_CREAT," because an open of an existing file may succeed 1224 * despite a denial of permission to create. The reserved argument should 1225 * currently always be NULL. 1226 * NOTE: The locking constraints with respect to this call, and all 1227 * authorizer callbacks in this document must unfortunately be left 1228 * somewhat ambiguous due to the unrestricted behavior of Kauth and 1229 * MACF plugins. However, I believe that it should be safe to call out 1230 * with resources (iocounts, memory, references) held, and even with some 1231 * kinds of locks (a lock preventing only remove of a file, for instance). 1232 * The chief thing to avoid is holding big locks (directory lock, file lock) 1233 * which would prevent stat(2) and similar operations which authorizers 1234 * are likely to try to use. 1235 * 10. a_open_existing_authorizer - Authorizer for preexisting case. This 1236 * field will contain a pointer to a function to be called to authorize 1237 * opening an existing file. It need only be called if a file has not 1238 * been created. The componentname passed to this function should be 1239 * exactly that which was passed to the VNOP, because opaque data in 1240 * this structure, installed by VFS, will be interpreted in authorization. 1241 * Some additional validation which is not authorization per se, but which 1242 * is currently performed in VFS on behalf of the filesystem, will also 1243 * be executed here. As a result of that validation, a variety of errors 1244 * may be returned; these should generally be passed back to VFS. 1245 * The reserved argument should currently always be NULL. For networked 1246 * filesystems, this routine can be used after going over the wire with a 1247 * compound lookup+open RPC; if access is denied, the filesystem should 1248 * clean up (e.g. issue a close over the wire) and return to VFS. 1249 * 11. a_reserved - This field is currently unused and should not be interpreted. 1250 * 1251 * Symlinks, Mountpoints, Trigger Points: 1252 * 1253 * int vnode_lookup_continue_needed(vnode_t vp, struct componentname *cnp); 1254 * 1255 * #define EKEEPLOOKING (-7) 1256 * 1257 * As part of a compound operation, a file may be detected which the filesystem 1258 * is not equipped to handle--for instance, a mountpoint, a symlink if O_NOFOLLOW 1259 * is set (which may point to another volume), or a trigger point. VFS will 1260 * provide the above routine to determine if a given vnode is one which requires 1261 * additional VFS processing. It will take a vnode (the preexisting file 1262 * discovered by a compound VNOP) and a componentname; the latter should be the 1263 * exact pointer which was passed to the filesystem by VFS, because opaque data 1264 * will be interpreted to make the decision. If this routine returns a nonzero 1265 * value, the filesystem should return EKEEPLOOKING to VFS. 1266 * vnode_lookup_continue_needed() will also update an opaque field on the 1267 * componentname for interpretation by VFS--while unnecessary for VNOP_COMPOUND_OPEN(), 1268 * for a rename (where two lookups take place) that update will let VFS determine 1269 * which lookup needs to be continued. This helper will be used in numerous 1270 * compound VNOPs. 1271 * 1272 * "Traditional"VNOPs, Dark Corners of the Kernel, and the Root of a Filesystem 1273 * 1274 * VNOP_LOOKUP() will still need to be supported to allow us to reach intermediate 1275 * components of a path. Currently, we plan to require that filesystems continue 1276 * to support the "traditional" VNOP_CREATE() and VNOP_OPEN() (and correspondingly, 1277 * the traditional version of other namespace-changing operations). The chief 1278 * reason for this is that there are numerous areas in the kernel that use these 1279 * old-style operations directly. After some discussion with various filesystem 1280 * owners, I think that it is best that we gradually adjust those areas to be 1281 * able to use compound VNOPs, thereby limiting the instability from moving them 1282 * all at once. When all internal code has been prepared to use a given compound 1283 * VNOP, filesystems will be able to remove their "traditional" implementation. 1284 * VNOP_OPEN() deserves a bit of special discussion. There are some places in 1285 * the kernel where we "open" a vnode without doing a true lookup; the best example 1286 * is the root of a filesystem, which is never "looked up" the way other entries 1287 * in a volume are, but there are other places where we have in hand that a vnode 1288 * that was obtained at some point in the past. I therefore think that we will 1289 * probably keep VNOP_OPEN() around for the long term, rather than increasing the 1290 * complexity of the spreadsheet of "which arguments can be NULL, and when" for 1291 * VNOP_COMPOUND_OPEN(). 1292*/ 1293static int 1294smbfs_vnop_compound_open(struct vnop_compound_open_args *ap) 1295{ 1296 vnode_t dvp = ap->a_dvp; 1297 vnode_t *vpp = ap->a_vpp; 1298 vnode_t vp = (ap->a_vpp) ? *ap->a_vpp : NULL; 1299 vfs_context_t context = ap->a_context; 1300 struct componentname *cnp = ap->a_cnp; 1301 struct vnode_attr *vap = ap->a_vap; 1302 int fmode = ap->a_fmode; 1303 int error; 1304 int create_authorizer_error = 0; 1305 uint32_t open_disp = 0; 1306 struct smb_share *share = NULL; 1307 struct smbnode *dnp; 1308 SMBFID fid = 0; 1309 uint32_t vid; 1310 struct smbfattr *fap = NULL; 1311 const char *namep = cnp->cn_nameptr; 1312 size_t name_len = cnp->cn_namelen; 1313 1314 1315 if (vpp == NULL) { 1316 SMBWARNING("Calling us without a vpp\n"); 1317 return ENOTSUP; 1318 } 1319 /* 1320 * Case 1: 1321 * They passed in a vnode they found in the name cache or we found 1322 * one in our hash table and its a symlink or reprase point. Not sure what 1323 * to do with reprase points yet. Symlinks are easy call vnode_lookup_continue_needed 1324 * and let it tell us what to do. 1325 * 1326 * Case 2: 1327 * They passed in a vnode they found in the name cache or we found in our 1328 * hash table. If they don't have O_CREAT set or its already open then we 1329 * can just do a normaly open. We need to call a_open_existing_authorizer 1330 * before calling smbfs_vnop_open_common. If O_TRUNC is set then we need to 1331 * set the file size to zero. Even on error we need to return the vnode 1332 * with a reference. 1333 * 1334 * Case 3: 1335 * We have no vnode or they have O_CREAT set and we don't have it already 1336 * open. Set the correct open dispostion depending on the modes passed in 1337 * and what a_open_create_authorizer returns. We only call a_open_create_authorizer 1338 * if O_CREAT is set. Now we let smbfs_create_open handle all other cases. 1339 * Will use <rdar://problem/8574808> to update this comment and to make 1340 * reprase points and symlinks work correctly. 1341 * 1342 * 1343 * Notes: 1344 * 1) vap may be null, if null on create then thats not supported 1345 * 2) if a_vpp is null and we return a vnode, dont do a vnode_put on it as the 1346 * vfs open code will call vnode_put on it for us. 1347 */ 1348 1349 /* 1350 * We may have to create the item make sure it has a vap and they 1351 * are creating a file. We only support create on files. 1352 */ 1353 if ((fmode & O_CREAT) && ((vap == NULL) || (vap->va_type != VREG))) { 1354 return (ENOTSUP); 1355 } 1356 1357 SMB_MALLOC(fap, 1358 struct smbfattr *, 1359 sizeof(struct smbfattr), 1360 M_SMBTEMP, 1361 M_WAITOK | M_ZERO); 1362 if (fap == NULL) { 1363 SMBERROR("SMB_MALLOC failed\n"); 1364 error = ENOMEM; 1365 goto done; 1366 } 1367 1368 share = smb_get_share_with_reference(VTOSMBFS(dvp)); 1369 1370 /* They didn't pass us a vnode, see if we have one in our hash */ 1371 if (vp == NULLVP) { 1372 if ((cnp->cn_nameptr[0] == '.') && (cnp->cn_namelen == 1)) { 1373 /* 1374 * They didn't give us a vnode, but they want dot open, so 1375 * get a reference on the parent node. 1376 */ 1377 vid = vnode_vid(dvp); 1378 error = vnode_getwithvid(dvp, vid); 1379 if (error) { 1380 goto done; 1381 } 1382 vp = dvp; 1383 } 1384 else { 1385 if (SSTOVC(share)->vc_misc_flags & SMBV_HAS_FILEIDS) { 1386 /* 1387 * Server supports File IDs. 1388 */ 1389 if (fmode & O_CREAT) { 1390 /* 1391 * In this case a lookup was done earlier and we know the 1392 * item does not exist so trying to get its File ID is 1393 * useless. Just skip straight to not found */ 1394 goto not_found; 1395 } 1396 1397 /* 1398 * Before we can see if vnode already exists in our hash, 1399 * need to get the inode number first. Might as well get all 1400 * the meta data too so we can update the vnode if its found 1401 */ 1402 if (SSTOVC(share)->vc_misc_flags & SMBV_NO_QUERYINFO) { 1403 /* 1404 * Server does not like Query Info on files, so use Query 1405 * Dir instead. 1406 * 1407 * Should never be a named stream vnode 1408 */ 1409 if ((VTOSMB(dvp)->n_vnode) && vnode_isnamedstream(VTOSMB(dvp)->n_vnode)) { 1410 DBG_ASSERT(0); 1411 } 1412 1413 error = smb2fs_smb_cmpd_query_dir_one(share, VTOSMB(dvp), 1414 namep, name_len, 1415 fap, (char **) &namep, &name_len, 1416 context); 1417 } 1418 else { 1419 error = smbfs_smb_qpathinfo(share, VTOSMB(dvp), 1420 fap, SMB_QFILEINFO_ALL_INFO, 1421 &namep, &name_len, 1422 context); 1423 } 1424 1425 if (error == 0) { 1426 /* Lock the parent */ 1427 dnp = VTOSMB(dvp); 1428 if (smbnode_lock(dnp, SMBFS_EXCLUSIVE_LOCK) != 0) { 1429 error = ENOENT; 1430 goto done; 1431 } 1432 1433 /* 1434 * Found item on server, see if its in the hash. 1435 * If it is in hash, then update its meta data and return vp 1436 * If its not in hash, smbfs_nget will create it for us and 1437 * return it in vp. Either way, we get back a vp. 1438 */ 1439 if (smbfs_nget(share, vnode_mount(dvp), 1440 dvp, cnp->cn_nameptr, cnp->cn_namelen, 1441 fap, &vp, 1442 cnp->cn_flags, SMBFS_NGET_CREATE_VNODE, 1443 ap->a_context) == 0) { 1444 /* 1445 * Found one in our hash table unlock it, we just need 1446 * the vnode reference at this point 1447 */ 1448 smbnode_unlock(VTOSMB(vp)); 1449 } 1450 1451 /* Unlock the parent */ 1452 dnp->n_lastvop = smbfs_vnop_compound_open; 1453 smbnode_unlock(dnp); 1454 1455 /* If smbfs_smb_qpathinfo returned a new name, free it */ 1456 if (namep != cnp->cn_nameptr) { 1457 SMB_FREE(namep, M_SMBNODENAME); 1458 } 1459 } 1460 else { 1461 /* Probably not found, either way vp is left at NULL */ 1462 goto not_found; 1463 } 1464 } 1465 else { 1466 /* Lock the parent */ 1467 dnp = VTOSMB(dvp); 1468 if (smbnode_lock(dnp, SMBFS_EXCLUSIVE_LOCK) != 0) { 1469 error = ENOENT; 1470 goto done; 1471 } 1472 1473 /* 1474 * Server does not support File IDs. 1475 * Use the name for the hash value and try to find the vnode 1476 * in the hash table with just the parent vnode and name. If its 1477 * does not already exist in the hash,then smbfs_nget will 1478 * return ENOENT (since fap == NULL) and vp will be left as NULL 1479 * 1480 * If server does support File IDs, we dont have the inode number 1481 * at this time, so can not check the hash table at this time. 1482 */ 1483 if (smbfs_nget(share, vnode_mount(dvp), 1484 dvp, cnp->cn_nameptr, cnp->cn_namelen, 1485 NULL, &vp, 1486 cnp->cn_flags, SMBFS_NGET_LOOKUP_ONLY, 1487 ap->a_context) == 0) { 1488 /* 1489 * Found one in our hash table unlock it, we just need 1490 * the vnode reference at this point 1491 */ 1492 smbnode_unlock(VTOSMB(vp)); 1493 } 1494 1495 /* Unlock the parent */ 1496 dnp->n_lastvop = smbfs_vnop_compound_open; 1497 smbnode_unlock(dnp); 1498 } 1499 } 1500 } 1501 1502 /* 1503 * Symlink or reparse point. Call vnode_lookup_continue_needed before 1504 * proceeding. 1505 */ 1506 if (vp && (vnode_islnk(vp) || (VTOSMB(vp)->n_dosattr & SMB_EFA_REPARSE_POINT))) { 1507 SMBDEBUG("symlink %s\n", VTOSMB(vp)->n_name); 1508 error = vnode_lookup_continue_needed(vp, cnp); 1509 if (error) { 1510 *vpp = vp; 1511 vp = NULL; 1512 goto done; 1513 } 1514 /* Let smbfs_vnop_open_common handle any open errors */ 1515 fmode &= ~(O_CREAT | O_TRUNC); /* Can't create or truncate a symlink */ 1516 } 1517 1518 /* 1519 * Do a normal open: 1520 * 1. We have a vnode and they just want to open the file or directory. The 1521 * O_CREAT/O_TRUNC is not set. NOTE they can't have O_CREAT set on a directory. 1522 * 2. We have a vnode to a file and its already opened. 1523 * 1524 * NOTE: They could be opening a file with O_CREAT, we found a directory in 1525 * our hash, yet it doesn't exist on the server. So we should create the file 1526 * and remove the directory node from our hash table. In this case we should 1527 * falldown to the create open code. 1528 */ 1529 if (vp && (!(fmode & (O_CREAT | O_TRUNC)) || (vnode_isreg(vp) && VTOSMB(vp)->f_refcnt))) { 1530 1531 if ((fmode & O_EXCL) && vnode_isreg(vp) && VTOSMB(vp)->f_refcnt) { 1532 /* 1533 * O_EXCL is set and we *know* the file exists (we have 1534 * a vp and it's opened). No need to go to the server, 1535 * since we know the result. 1536 */ 1537 error = EEXIST; 1538 *vpp = vp; 1539 vp = NULL; 1540 goto done; 1541 } 1542 1543 /* Call back and see if it is ok to be opened */ 1544 error = ap->a_open_existing_authorizer(vp, cnp, fmode, context, NULL); 1545 if (!error) { 1546 error = smbfs_vnop_open_common(vp, fmode, context, smbfs_vnop_compound_open); 1547 } 1548 /* The file was already open, but they wanted us to truncate it. */ 1549 if (!error && (fmode & O_TRUNC)){ 1550 struct vnode_attr va; 1551 1552 memset(&va, 0, sizeof(va)); 1553 VATTR_INIT(&va); 1554 VATTR_SET_ACTIVE(&va, va_data_size); 1555 error = smbfs_setattr(share, vp, &va, context); 1556 if (error) { 1557 /* Got an error close the file and return the error */ 1558 (void)smbfs_close(share, vp, fmode, context); 1559 } 1560 } 1561 /* Even if the truncate fails we need to return the vnode */ 1562 *vpp = vp; 1563 vp = NULL; 1564 goto done; 1565 } 1566 1567not_found: 1568 /* Set the default create dispostion value */ 1569 create_authorizer_error = 0; 1570 1571 if (fmode & O_TRUNC) { 1572 open_disp = FILE_OVERWRITE; 1573 if (vp) { 1574 /* If truncating the file on open, do any pending set eofs */ 1575 smbfs_smb_fsync(share, VTOSMB(vp), context); 1576 } 1577 } 1578 else { 1579 open_disp = FILE_OPEN; 1580 } 1581 1582 if (fmode & O_CREAT) { 1583 /* Call back and see if it is ok to be created */ 1584 create_authorizer_error = ap->a_open_create_authorizer(dvp, cnp, vap, context, NULL); 1585 if (!create_authorizer_error) { 1586 /* We can create so set the correct create dispostion value */ 1587 if (fmode & O_EXCL) { 1588 open_disp = FILE_CREATE; 1589 } else if (fmode & O_TRUNC) { 1590 open_disp = FILE_OVERWRITE_IF; 1591 } else { 1592 open_disp = FILE_OPEN_IF; 1593 } 1594 } 1595 } 1596 1597 /* Lock the parent */ 1598 if ((error = smbnode_lock(VTOSMB(dvp), SMBFS_EXCLUSIVE_LOCK))) { 1599 goto done; 1600 } 1601 1602 dnp = VTOSMB(dvp); 1603 dnp->n_lastvop = smbfs_vnop_compound_open; 1604 1605 /* Try to create/open the file */ 1606 error = smbfs_create_open(share, dvp, cnp, vap, open_disp, fmode, &fid, fap, &vp, context); 1607 smbnode_unlock(dnp); 1608 if (error) { 1609 if (create_authorizer_error) { 1610 error = create_authorizer_error; 1611 } 1612 } 1613 else { 1614 if ((fap->fa_created_disp == FILE_CREATE) && (!(fmode & O_CREAT))) { 1615 /* 1616 * The server says it was created, but we didn't request it to be 1617 * created. The VFS layer can't handle this so just replace the 1618 * FILE_CREATE with FILE_OPEN and log what happen. This should never 1619 * happen, but it is better than the VFS panicing. 1620 */ 1621 fap->fa_created_disp = FILE_OPEN; 1622 SMBERROR("Server created %s when we only wanted it open, server error\n", 1623 cnp->cn_nameptr); 1624 } 1625 if (fap->fa_created_disp == FILE_CREATE) { 1626 *ap->a_status = COMPOUND_OPEN_STATUS_DID_CREATE; 1627 } else { 1628 error = ap->a_open_existing_authorizer(vp, cnp, fmode, context, NULL); 1629 /* Error so close it */ 1630 if (error) { 1631 (void)smbfs_smb_close(share, fid, context); 1632 } 1633 /* Not sure how to handle reparse yet, deal with that in <rdar://problem/8574808> */ 1634 if (vnode_islnk(vp) || (VTOSMB(vp)->n_dosattr & SMB_EFA_REPARSE_POINT)) { 1635 error = vnode_lookup_continue_needed(vp, cnp); 1636 if (!error && (vnode_islnk(vp))) { 1637 /* We never let them open a symlink */ 1638 error = EACCES; 1639 } 1640 } 1641 } 1642 /* Note: Even on error, return the vnode */ 1643 *vpp = vp; 1644 vp = NULL; /* Don't release the reference */ 1645 } 1646 1647done: 1648 if (error) { 1649 if ((fmode & O_CREAT) && (error == ENOENT)) { 1650 SMBDEBUG("Creating %s returned ENOENT, resetting to EACCES\n", cnp->cn_nameptr); 1651 /* 1652 * Some servers (Samba) support an option called veto. This prevents 1653 * clients from creating or access these files. The server returns 1654 * an ENOENT error in these cases. The VFS layer will loop forever 1655 * if a ENOENT error is returned on create, so we convert this error 1656 * to EACCES. 1657 */ 1658 error = EACCES; 1659 } else if ((fmode & O_EXCL) && (error != EEXIST)) { 1660 /* 1661 * Since O_EXCL is set, we really need to return EEXIST 1662 * if the file exists. 1663 * See <rdar://problem/10074916> 1664 */ 1665 if ( (smbfs_smb_query_info(share, VTOSMB(dvp), cnp->cn_nameptr, cnp->cn_namelen, NULL, context) == 0)) { 1666 SMBDEBUG("%s: O_EXCL but error = %d, resetting to EEXIST.\n", __FUNCTION__, error); 1667 error = EEXIST; 1668 } 1669 } 1670 } 1671 1672 if (share) { 1673 smb_share_rele(share, context); 1674 } 1675 1676 /* 1677 * We have an error and they didn't pass us in a vnode, then we found the 1678 * vnode in our hash table. We need to remove our reference. 1679 */ 1680 if (error && (*vpp == NULLVP) && vp) { 1681 vnode_put(vp); 1682 } 1683 1684 if (fap) { 1685 SMB_FREE(fap, M_SMBTEMP); 1686 } 1687 1688 return (error); 1689} 1690 1691/* 1692 * smbfs_vnop_open - smbfs vnodeop entry point 1693 * vnode_t a_vp; 1694 * int a_mode; 1695 * vfs_context_t a_context; 1696 */ 1697static int 1698smbfs_vnop_open(struct vnop_open_args *ap) 1699{ 1700 return ( smbfs_vnop_open_common(ap->a_vp, ap->a_mode, ap->a_context, smbfs_vnop_open) ); 1701} 1702 1703/* 1704 * smbfs_vnop_mmap - smbfs vnodeop entry point 1705 * vnode_t a_vp; 1706 * int a_fflags; 1707 * vfs_context_t a_context; 1708 * 1709 * The mmap routine is a hint that we need to keep the file open. We can get 1710 * mutilple mmap before we get a mnomap. We only care about the first one. We 1711 * need to take a reference count on the open file and hold it open until we get 1712 * a mnomap call. The file should already be open when we get the mmap call and 1713 * with the correct open mode access. So we shouldn't have to worry about 1714 * upgrading because the open should have handled that for us. If the open was 1715 * done using an Open Deny mode then we need to mark the open deny entry as being 1716 * mmaped so the pagein, pageout, and mnomap routines can find. 1717 * 1718 * NOTE: On return all errors are ignored except EPERM. 1719 */ 1720static int 1721smbfs_vnop_mmap(struct vnop_mmap_args *ap) 1722{ 1723 vnode_t vp = ap->a_vp; 1724 struct smbnode *np = NULL; 1725 int error = 0; 1726 uint32_t mode = (ap->a_fflags & PROT_WRITE) ? (FWRITE | FREAD) : FREAD; 1727 int accessMode = (ap->a_fflags & PROT_WRITE) ? kAccessWrite : kAccessRead; 1728 SMBFID fid = 0; 1729 struct fileRefEntry *entry = NULL; 1730 1731 if ((error = smbnode_lock(VTOSMB(vp), SMBFS_EXCLUSIVE_LOCK))) 1732 return (EPERM); 1733 1734 np = VTOSMB(vp); 1735 np->n_lastvop = smbfs_vnop_mmap; 1736 1737 /* We already have it mapped, just ignore this one */ 1738 if (np->n_flag & NISMAPPED) 1739 goto out; 1740 /* 1741 * Since we should already be open with the correct modes then we should never 1742 * need to really open the file. For now we try these three cases. 1743 * 1744 * First try the simple case, we have a posix open with the correct access. 1745 * 1746 * Second see if we have a match in the open deny mode list. Still not 100% sure this 1747 * will work ever time because they are passing the current context, which may not match 1748 * the one passed to open. From taking to Joe he believe we will always be in the open 1749 * context when call. From my testing this seems to be true. 1750 * 1751 * Third just return EPERM. 1752 */ 1753 if ((np->f_fid != 0) && 1754 (np->f_accessMode & accessMode)) { 1755 np->f_refcnt++; 1756 } else if (FindFileRef(vp, vfs_context_proc(ap->a_context), accessMode, 1757 kAnyMatch, 0, 0, &entry, &fid) == 0) { 1758 entry->refcnt++; 1759 entry->mmapped = TRUE; 1760 np->f_refcnt++; 1761 } else { 1762 SMBERROR("%s We could not find an open file with mode = 0x%x? \n", np->n_name, mode); 1763 error = EPERM; 1764 goto out; 1765 } 1766 np->n_flag |= NISMAPPED; 1767 np->f_mmapMode = mode; 1768out: 1769 smbnode_unlock(np); 1770 return (error); 1771} 1772 1773/* 1774 * smbfs_vnop_mnomap - smbfs vnodeop entry point 1775 * vnode_t a_vp; 1776 * vfs_context_t a_context; 1777 * 1778 * When called this is a hint that we can now close the file. We will not get any 1779 * more pagein or pageout calls without another mmap call. If our reference count 1780 * is down to one then all we have to do is call close and it will clean everything 1781 * up. Otherwise we have a little more work to do see below for more details. 1782 * 1783 * NOTE: All errors are ignored by the calling routine 1784 */ 1785static int 1786smbfs_vnop_mnomap(struct vnop_mnomap_args *ap) 1787{ 1788 vnode_t vp = ap->a_vp; 1789 struct smbnode *np; 1790 struct fileRefEntry *entry; 1791 int error = 0; 1792 1793 if (smbnode_lock(VTOSMB(vp), SMBFS_EXCLUSIVE_LOCK)) 1794 return (EPERM); /* Not sure what to do here, they ignore errors */ 1795 np = VTOSMB(vp); 1796 np->n_lastvop = smbfs_vnop_mnomap; 1797 1798 /* Only one open reference just call close and let it clean every thing up. */ 1799 if (np->f_refcnt == 1) { 1800 struct smb_share *share; 1801 1802 share = smb_get_share_with_reference(VTOSMBFS(vp)); 1803 error = smbfs_close(share, vp, np->f_mmapMode, ap->a_context); 1804 smb_share_rele(share, ap->a_context); 1805 if (error) 1806 SMBWARNING("%s close failed with error = %d\n", np->n_name, error); 1807 goto out; 1808 } else { 1809 np->f_refcnt--; 1810 } 1811 /* 1812 * We get passed the current context which may or may not be the the same as the one used 1813 * in the open. So search the list and see if there are any mapped entries. Remember we only 1814 * have one item mapped at a time. 1815 */ 1816 if (FindMappedFileRef(vp, &entry, NULL) == TRUE) { 1817 entry->mmapped = FALSE; 1818 if (entry->refcnt > 0) /* This entry is still in use don't remove it yet. */ 1819 entry->refcnt--; 1820 else /* Done with it remove it from the list */ 1821 RemoveFileRef(vp, entry); 1822 } 1823out: 1824 np->f_mmapMode = 0; 1825 np->n_flag &= ~NISMAPPED; 1826 smbnode_unlock(np); 1827 return (error); 1828} 1829 1830/* 1831 * smbfs_vnop_inactive - smbfs vnodeop entry point 1832 * vnode_t a_vp; 1833 * vfs_context_t a_context; 1834 */ 1835static int 1836smbfs_vnop_inactive(struct vnop_inactive_args *ap) 1837{ 1838 vnode_t vp = ap->a_vp; 1839 struct smbnode *np; 1840 struct smb_share *share = NULL; 1841 int error = 0; 1842 int releaseLock = TRUE; 1843 1844 (void)smbnode_lock(VTOSMB(vp), SMBFS_RECLAIM_LOCK); 1845 np = VTOSMB(vp); 1846 np->n_lastvop = smbfs_vnop_inactive; 1847 share = smb_get_share_with_reference(VTOSMBFS(vp)); 1848 1849 1850 /* Clear any symlink cache, always safe to do even on non symlinks */ 1851 if (np->n_symlink_target) { 1852 SMB_FREE(np->n_symlink_target, M_TEMP); 1853 } 1854 np->n_symlink_target_len = 0; 1855 np->n_symlink_cache_timer = 0; 1856 1857 /* Node went inactive clear the ACL cache */ 1858 if (!vnode_isnamedstream(vp)) 1859 smbfs_clear_acl_cache(np); 1860 1861 /* 1862 * Before we take the lock, someone could jump in and do an open and start using this vnode again. 1863 * We now check for that and just skip out if it happens. We will get another inactive later, if 1864 * this volume is not being force unmount. So check here to see if the vnode is in use and the 1865 * volume is not being forced unmounted. Note that Kqueue opens will not be found by vnode_isinuse. 1866 */ 1867 if ((vnode_isinuse(vp, 0)) && !(vfs_isforce(vnode_mount(vp)))) 1868 goto out; 1869 1870 if (vnode_isdir(vp)) { 1871 smbfs_closedirlookup(np, ap->a_context); 1872 np->d_refcnt = 0; 1873 if (np->d_kqrefcnt) { 1874 smbfs_stop_change_notify(share, np, TRUE, ap->a_context, &releaseLock); 1875 } 1876 goto out; 1877 } 1878 1879 /* its not in use are they don't care about it close it */ 1880 if (np->f_refcnt) { 1881 np->f_refcnt = 1; 1882 error = smbfs_close(share, vp, FREAD, ap->a_context); 1883 if (error) { 1884 SMBDEBUG("error %d closing fid %llx file %s\n", 1885 error, np->f_fid, np->n_name); 1886 } 1887 } 1888 1889 /* 1890 * Does the file need to be deleted on close. Make one more check here 1891 * just in case. 1892 */ 1893 if (np->n_flag & NDELETEONCLOSE) { 1894 error = smbfs_smb_delete(share, np, NULL, 0, 0, ap->a_context); 1895 if (error) 1896 SMBWARNING("error %d deleting silly rename file %s\n", 1897 error, np->n_name); 1898 else np->n_flag &= ~NDELETEONCLOSE; 1899 } 1900#ifdef SMB_DEBUG 1901 /* If the file is not in use then it should be closed. */ 1902 DBG_ASSERT((np->f_refcnt == 0)); 1903 DBG_ASSERT((np->f_openDenyList == NULL)); 1904 DBG_ASSERT((np->f_smbflock == NULL)); 1905#endif // SMB_DEBUG 1906 1907out: 1908 smb_share_rele(share, ap->a_context); 1909 if (releaseLock) 1910 smbnode_unlock(np); 1911 return (0); 1912} 1913 1914/* 1915 * Free smbnode, and give vnode back to system 1916 * struct vnodeop_desc *a_desc; 1917 * vnode_t a_vp; 1918 * vfs_context_t a_context; 1919 */ 1920static int smbfs_vnop_reclaim(struct vnop_reclaim_args *ap) 1921{ 1922 vnode_t vp = ap->a_vp; 1923 vnode_t dvp; 1924 struct smbnode *np = NULL; 1925 struct smbmount *smp = NULL; 1926 1927 (void) smbnode_lock(VTOSMB(vp), SMBFS_RECLAIM_LOCK); 1928 np = VTOSMB(vp); 1929 np->n_lastvop = smbfs_vnop_reclaim; 1930 smp = VTOSMBFS(vp); 1931#ifdef SMB_DEBUG 1932 /* We should never have a file open at this point */ 1933 if (vnode_isreg(vp)) { 1934 DBG_ASSERT((np->f_refcnt == 0)); 1935 } else if (vnode_isdir(vp)) { 1936 DBG_ASSERT((np->d_kqrefcnt == 0)); 1937 DBG_ASSERT((np->d_fctx == NULL)); 1938 } 1939#endif // SMB_DEBUG 1940 1941 lck_mtx_lock(&smp->sm_reclaim_renamelock); 1942 SET(np->n_flag, NTRANSIT); 1943 1944 dvp = ( (np->n_parent && (np->n_flag & NREFPARENT)) && 1945 ((np->n_parent->n_flag & NTRANSIT) != NTRANSIT)) ? 1946 np->n_parent->n_vnode : NULL; 1947 1948 if (dvp != NULL) { 1949 /* Parent exists and is not being reclaimed, remove child's refcount */ 1950 OSDecrementAtomic(&VTOSMB(dvp)->n_child_refcnt); 1951 np->n_parent = NULL; 1952 } 1953 1954 /* child_refcnt better be zero */ 1955 if (np->n_child_refcnt && !(vfs_isforce(vnode_mount(vp)))) { 1956 /* 1957 * Forced unmounts are very brutal, and it's not unusual for a parent 1958 * node being reclaimed to have a non-zero child refcount. So we only 1959 * log an error if this is not a forced unmount, which we do care about. 1960 */ 1961 if (vnode_getname(vp) != NULL) { 1962 SMBERROR("%s: node: %s, n_child_refcnt not zero like it should be: %ld\n", 1963 __FUNCTION__, vnode_getname(vp), (long) np->n_child_refcnt); 1964 } else { 1965 SMBERROR("%s: n_child_refcnt not zero like it should be: %ld\n", 1966 __FUNCTION__, (long) np->n_child_refcnt); 1967 } 1968 } 1969 if (np->n_child_refcnt) { 1970 smbfs_ClearChildren(smp, np); 1971 } 1972 1973 /* 1974 * In previous code - smb_vhashrem() was called after releasing 1975 * sm_reclaim_renamelock. 1976 * There was a small window between sm_reclaim_renamelock is released and 1977 * smbnode (say child) is deleted from hash. 1978 * During this window, child can be NTRANSIT and parent can acquire 1979 * sm_reclaim_renamelock, proceed further in reclaim to call 1980 * smbfs_ClearChildren(), but skips the above child (NTRASIT set), 1981 * gets deleted from hash before child gets deleted. 1982 * May not affect anything as such, but just to be safe, I am moving 1983 * smb_vhashrem() in the scope of the sm_reclaim_renamelock. 1984 * Most likely, this can happen during the force unmount. 1985 */ 1986 smb_vhashrem(np); 1987 lck_mtx_unlock(&smp->sm_reclaim_renamelock); 1988 1989 cache_purge(vp); 1990 if (smp->sm_rvp == vp) { 1991 SMBVDEBUG("root vnode\n"); 1992 smp->sm_rvp = NULL; 1993 } 1994 /* Destroy the lock used for the open state, open deny list and resource size/timer */ 1995 if (!vnode_isdir(vp)) { 1996 lck_mtx_destroy(&np->f_openDenyListLock, smbfs_mutex_group); 1997 lck_mtx_destroy(&np->f_openStateLock, smbfs_mutex_group); 1998 lck_mtx_destroy(&np->f_clusterWriteLock, smbfs_mutex_group); 1999 if (!vnode_isnamedstream(vp)) 2000 lck_mtx_destroy(&np->rfrkMetaLock, smbfs_mutex_group); 2001 } 2002 2003 /* Clear any symlink cache, always safe to do even on non symlinks */ 2004 if (np->n_symlink_target != NULL) { 2005 SMB_FREE(np->n_symlink_target, M_TEMP); 2006 } 2007 np->n_symlink_target_len = 0; 2008 np->n_symlink_cache_timer = 0; 2009 2010 /* We are done with the node clear the acl cache and destroy the acl cache lock */ 2011 if (!vnode_isnamedstream(vp)) { 2012 smbfs_clear_acl_cache(np); 2013 lck_mtx_destroy(&np->f_ACLCacheLock, smbfs_mutex_group); 2014 } 2015 2016 /* Free up both names before we unlock the node */ 2017 if (np->n_name != NULL) { 2018 SMB_FREE(np->n_name, M_SMBNODENAME); 2019 } 2020 if (np->n_sname != NULL) { 2021 SMB_FREE(np->n_sname, M_SMBNODENAME); 2022 } 2023 2024 /* Clear the private data pointer *before* unlocking the node, so we don't 2025 * race with another thread doing a 'np = VTOSMB(vp)'. 2026 */ 2027 vnode_clearfsnode(vp); 2028 smbnode_unlock(np); 2029 2030 CLR(np->n_flag, (NALLOC|NTRANSIT)); 2031 if (ISSET(np->n_flag, NWALLOC) || ISSET(np->n_flag, NWTRANSIT)) { 2032 CLR(np->n_flag, (NWALLOC|NWTRANSIT)); 2033 wakeup(np); 2034 } 2035 lck_rw_destroy(&np->n_rwlock, smbfs_rwlock_group); 2036 lck_rw_destroy(&np->n_name_rwlock, smbfs_rwlock_group); 2037 SMB_FREE(np, M_SMBNODE); 2038 if (dvp && (vnode_get(dvp) == 0)) { 2039 vnode_rele(dvp); 2040 vnode_put(dvp); 2041 } 2042 return 0; 2043} 2044 2045/* 2046 * smbfs_getattr call from vfs. 2047 * 2048 * The calling routine must hold a reference on the share 2049 * 2050 */ 2051static int 2052smbfs_getattr(struct smb_share *share, vnode_t vp, struct vnode_attr *vap, 2053 vfs_context_t context) 2054{ 2055 if (share->ss_attributes & FILE_PERSISTENT_ACLS && 2056 (VATTR_IS_ACTIVE(vap, va_acl) || VATTR_IS_ACTIVE(vap, va_guuid) || 2057 VATTR_IS_ACTIVE(vap, va_uuuid))) { 2058 DBG_ASSERT(!vnode_isnamedstream(vp)); 2059 (void)smbfs_getsecurity(share, VTOSMB(vp), vap, context); 2060 } 2061 return smbfs_update_cache(share, vp, vap, context); 2062} 2063 2064/* 2065 * smbfs_vnop_getattr 2066 * 2067 * vnode_t a_vp; 2068 * struct vnode_attr *a_vap; 2069 * vfs_context_t a_context; 2070 */ 2071static int 2072smbfs_vnop_getattr(struct vnop_getattr_args *ap) 2073{ 2074 int32_t error = 0; 2075 struct smb_share *share; 2076 struct smbnode *np; 2077 2078 if ((error = smbnode_lock(VTOSMB(ap->a_vp), SMBFS_SHARED_LOCK))) { 2079 return (error); 2080 } 2081 np = VTOSMB(ap->a_vp); 2082 np->n_lastvop = smbfs_vnop_getattr; 2083 share = smb_get_share_with_reference(VTOSMBFS(ap->a_vp)); 2084 /* Before updating see if it needs to be reopened. */ 2085 if ((!vnode_isdir(ap->a_vp)) && (np->f_openState & kNeedReopen)) { 2086 /* smbfs_smb_reopen_file should check to see if the share changed? */ 2087 (void)smbfs_smb_reopen_file(share, np, ap->a_context); 2088 } 2089 error = smbfs_getattr(share, ap->a_vp, ap->a_vap, ap->a_context); 2090 smb_share_rele(share, ap->a_context); 2091 smbnode_unlock(np); 2092 return (error); 2093} 2094 2095/* 2096 * The number of seconds between Jan 1, 1970 and Jan 1, 1980. In that 2097 * interval there were 8 regular years and 2 leap years. 2098 */ 2099#define SECONDSTO1980 (((8 * 365) + (2 * 366)) * (24 * 60 * 60)) 2100static struct timespec fat1980_time = {SECONDSTO1980, 0}; 2101 2102/* 2103* The calling routine must hold a reference on the share 2104*/ 2105static int 2106smbfs_setattr(struct smb_share *share, vnode_t vp, struct vnode_attr *vap, 2107 vfs_context_t context) 2108{ 2109 struct smbnode *np = VTOSMB(vp); 2110 struct smbmount *smp = VTOSMBFS(vp); 2111 struct timespec *crtime, *mtime, *atime; 2112 u_quad_t tsize = 0; 2113 int error = 0, cerror, modified = 0; 2114 SMBFID fid = 0; 2115 uint32_t rights; 2116 Boolean useFatTimes = (share->ss_fstype == SMB_FS_FAT); 2117 2118 /* If this is a stream then they can only set the size */ 2119 if ((vnode_isnamedstream(vp)) && 2120 (vap->va_active & ~VNODE_ATTR_BIT(va_data_size))) { 2121 SMBDEBUG("Using stream node %s to set something besides the size?\n", 2122 np->n_name); 2123 error = ENOTSUP; 2124 goto out; 2125 } 2126 2127 /* 2128 * If our caller is trying to set multiple attributes, they 2129 * can make no assumption about what order they are done in. 2130 * Here we try to do them in order of decreasing likelihood 2131 * of failure, just to minimize the chance we'll wind up 2132 * with a partially complete request. 2133 */ 2134 2135 if (share->ss_attributes & FILE_PERSISTENT_ACLS && 2136 (VATTR_IS_ACTIVE(vap, va_acl) || VATTR_IS_ACTIVE(vap, va_guuid) || 2137 VATTR_IS_ACTIVE(vap, va_uuuid))) { 2138 error = smbfs_setsecurity(share, vp, vap, context); 2139 if (error) 2140 goto out; 2141 /* 2142 * Failing to set VATTR_SET_SUPPORTED to something which was 2143 * requested causes fallback to EAs, which we never want. This 2144 * is done because of HFS, so if you support it you have to 2145 * always return something, even if its wrong. 2146 */ 2147 if (VATTR_IS_ACTIVE(vap, va_acl)) 2148 VATTR_SET_SUPPORTED(vap, va_acl); 2149 if (VATTR_IS_ACTIVE(vap, va_guuid)) 2150 VATTR_SET_SUPPORTED(vap, va_guuid); 2151 if (VATTR_IS_ACTIVE(vap, va_uuuid)) 2152 VATTR_SET_SUPPORTED(vap, va_uuuid); 2153 modified = 1; 2154 } 2155 2156 /* 2157 * If the server supports the new UNIX extensions, then we can support 2158 * changing the uid, gid, mode, and va_flags. Currently the uid and gid 2159 * don't make any sense, but in the future we may add this support. 2160 * 2161 * The old code would check the users creditials here. There is no need for 2162 * that in our case. The lower level will make sure the correct local user 2163 * is using the vc and the server should protect us for any other case. 2164 */ 2165 2166 if ((VATTR_IS_ACTIVE(vap, va_mode)) || (VATTR_IS_ACTIVE(vap, va_flags))) { 2167 int supportUnixBSDFlags = ((UNIX_CAPS(share) & UNIX_SFILEINFO_UNIX_INFO2_CAP)) ? TRUE : FALSE; 2168 int supportUnixInfo2 = ((UNIX_CAPS(share) & UNIX_QFILEINFO_UNIX_INFO2_CAP)) ? TRUE : FALSE; 2169 int darwin = (SSTOVC(share)->vc_flags & SMBV_DARWIN) ? TRUE : FALSE; 2170 int dosattr = np->n_dosattr; 2171 uint32_t vaflags = 0; 2172 uint32_t vaflags_mask = SMB_FLAGS_NO_CHANGE; 2173 uint64_t vamode = SMB_MODE_NO_CHANGE; 2174 2175 if (VATTR_IS_ACTIVE(vap, va_flags)) { 2176 /* 2177 * Here we are strict, stricter than ufs in not allowing users to 2178 * attempt to set SF_SETTABLE bits or anyone to set unsupported bits. 2179 * However, we ignore attempts to set ATTR_ARCHIVE for directories 2180 * `cp -pr' from a more sensible file system attempts it a lot. 2181 */ 2182 if (vap->va_flags & ~(SF_ARCHIVED | SF_IMMUTABLE | UF_IMMUTABLE | UF_HIDDEN)) 2183 { 2184 error = EINVAL; 2185 goto out; 2186 } 2187 /* Only set items we can change and the server supports */ 2188 vaflags_mask = np->n_flags_mask & EXT_REQUIRED_BY_MAC; 2189 2190 /* 2191 * Remember that SMB_EFA_ARCHIVE means the items needs to be 2192 * archive and SF_ARCHIVED means the item has been archive. 2193 */ 2194 if (vap->va_flags & SF_ARCHIVED) { 2195 dosattr &= ~SMB_EFA_ARCHIVE; 2196 vaflags |= EXT_DO_NOT_BACKUP; 2197 } else { 2198 dosattr |= SMB_EFA_ARCHIVE; 2199 } 2200 /* 2201 * SMB_EFA_RDONLY ~ UF_IMMUTABLE 2202 * 2203 * We treat the SMB_EFA_RDONLY as the immutable flag. This allows 2204 * us to support the finder lock bit and makes us follow the 2205 * MSDOS code model. See msdosfs project. 2206 * 2207 * NOTE: The ready-only flags does not exactly follow the 2208 * lock/immutable bit also note the for directories its advisory only. 2209 * 2210 * We do not support the setting the read-only bit for folders if 2211 * the server does not support the new UNIX extensions. 2212 * 2213 * See Radar 5582956 for more details. 2214 */ 2215 if (SSTOVC(share)->vc_flags & SMBV_SMB2) { 2216 if (UNIX_SERVER(SSTOVC(share)) || (!vnode_isdir(vp))) { 2217 if (vap->va_flags & (SF_IMMUTABLE | UF_IMMUTABLE)) { 2218 dosattr |= SMB_EFA_RDONLY; 2219 vaflags |= EXT_IMMUTABLE; 2220 } 2221 else { 2222 dosattr &= ~SMB_EFA_RDONLY; 2223 } 2224 } 2225 } 2226 else { 2227 if (supportUnixBSDFlags || darwin || (!vnode_isdir(vp))) { 2228 if (vap->va_flags & (SF_IMMUTABLE | UF_IMMUTABLE)) { 2229 dosattr |= SMB_EFA_RDONLY; 2230 vaflags |= EXT_IMMUTABLE; 2231 } 2232 else { 2233 dosattr &= ~SMB_EFA_RDONLY; 2234 } 2235 } 2236 } 2237 2238 /* 2239 * NOTE: Windows does not set ATTR_ARCHIVE bit for directories. 2240 */ 2241 if ((! supportUnixBSDFlags) && (vnode_isdir(vp))) 2242 dosattr &= ~SMB_EFA_ARCHIVE; 2243 2244 /* Now deal with the new Hidden bit */ 2245 if (vap->va_flags & UF_HIDDEN) { 2246 dosattr |= SMB_EFA_HIDDEN; 2247 vaflags |= EXT_HIDDEN; 2248 } else { 2249 dosattr &= ~SMB_EFA_HIDDEN; 2250 } 2251 } 2252 2253 /* 2254 * Currently we do not allow setting the uid, gid, or sticky bits. Also 2255 * chmod on a symbolic link doesn't really make sense. BSD allows this 2256 * with the lchmod and on create, but Samba doesn't support this because 2257 * its not POSIX. If we try to chmod here it will get set on the target 2258 * which would be bad. So ignore the fact that they made this request. 2259 */ 2260 if (VATTR_IS_ACTIVE(vap, va_mode)) { 2261 if (supportUnixInfo2 && (!vnode_islnk(vp))) { 2262 vamode = vap->va_mode & ACCESSPERMS; 2263 } else if ((share->ss_attributes & FILE_PERSISTENT_ACLS) && 2264 (darwin || !UNIX_CAPS(share))) { 2265 vamode = vap->va_mode & ACCESSPERMS; 2266 } else if (SSTOVC(share)->vc_server_caps & kAAPL_SUPPORTS_NFS_ACE) { 2267 /* 2268 * For OS X <-> OS X PFS (where ACLs are off by default), we 2269 * need a way to set Posix permissions. If the server supports 2270 * the NFS ACE, then it will allow us to get the ACL and send 2271 * it back with the desired Posix permissions in the NFS ACE. 2272 */ 2273 vamode = vap->va_mode & ACCESSPERMS; 2274 } 2275 2276 } 2277 if (dosattr == np->n_dosattr) { 2278 vaflags_mask = 0; /* Nothing really changes, no need to make the call */ 2279 } 2280 if (vaflags_mask || (vamode != SMB_MODE_NO_CHANGE)) { 2281 if (!supportUnixInfo2) { 2282 /* Windows style server */ 2283 if (vaflags_mask) { 2284 error = smbfs_smb_setpattr(share, np, NULL, 0, dosattr, context); 2285 } 2286 if (vamode != SMB_MODE_NO_CHANGE) { 2287 /* Should we report the error? */ 2288 error = smbfs_set_ace_modes(share, np, vamode, context); 2289 } 2290 } else if (supportUnixBSDFlags) { 2291 /* Samba server that does support the BSD flags (Mac OS) */ 2292 error = smbfs_set_unix_info2(share, np, NULL, NULL, NULL, 2293 SMB_SIZE_NO_CHANGE, vamode, vaflags, 2294 vaflags_mask, context); 2295 } else { 2296 /* Samba server that doesn't support the BSD flags, Linux */ 2297 if (vamode != SMB_MODE_NO_CHANGE) { 2298 /* Now set the posix modes, using unix info level */ 2299 error = smbfs_set_unix_info2(share, np, NULL, NULL, NULL, 2300 SMB_SIZE_NO_CHANGE, vamode, 2301 SMB_FLAGS_NO_CHANGE, vaflags_mask, 2302 context); 2303 } 2304 if (vaflags_mask) { 2305 /* Set the BSD flags using normal smb info level */ 2306 error = smbfs_smb_setpattr(share, np, NULL, 0, dosattr, context); 2307 } 2308 } 2309 if (error) 2310 goto out; 2311 } 2312 /* Everything work update the local cache and mark that we did the work */ 2313 if (VATTR_IS_ACTIVE(vap, va_mode)) { 2314 if (vamode != SMB_MODE_NO_CHANGE) { 2315 np->n_mode = vamode; 2316 VATTR_SET_SUPPORTED(vap, va_mode); 2317 } 2318 } 2319 if (VATTR_IS_ACTIVE(vap, va_flags)) { 2320 np->n_dosattr = dosattr; 2321 VATTR_SET_SUPPORTED(vap, va_flags); 2322 } 2323 } 2324 2325 if (VATTR_IS_ACTIVE(vap, va_data_size) && (vnode_isreg(vp))) { 2326 uint32_t trycnt = 0; 2327 2328 ubc_msync (vp, 0, ubc_getsize(vp), NULL, UBC_PUSHDIRTY | UBC_SYNC); 2329 /* The seteof call requires the file to be opened for write and append data. */ 2330 rights = SMB2_FILE_WRITE_DATA | SMB2_FILE_APPEND_DATA; 2331 /* 2332 * The connection could go down in the middle of setting the eof, in 2333 * this case we will get a bad file descriptor error. Keep trying until 2334 * the open fails or we get something besides EBADF. 2335 * 2336 * We now have a counter that keeps us from going into an infinite loop. Once 2337 * we implement SMB2 we should take a second look at how this should be done. 2338 */ 2339 do { 2340 error = smbfs_tmpopen(share, np, rights, &fid, context); 2341 if (error) { 2342 SMB_LOG_IO("%s seteof open failed %d\n", np->n_name, error); 2343 /* The open failed, fail the seteof. */ 2344 break; 2345 } 2346 2347 /* zero fill if needed, ignore any errors will catch them on the seteof call */ 2348 tsize = np->n_size; 2349 if (tsize < vap->va_data_size) { 2350 error = smbfs_0extend(share, fid, tsize, vap->va_data_size, 0, context); 2351 } 2352 /* Set the eof on the server */ 2353 if (!error) { 2354 error = smbfs_seteof(share, np, fid, vap->va_data_size, context); 2355 } 2356 if (error == EBADF) { 2357 trycnt++; 2358 SMB_LOG_IO("%s seteof failed because of reconnect, trying again.\n", 2359 np->n_name); 2360 } 2361 /* 2362 * Windows FAT file systems require a flush, after a seteof. Until the 2363 * the flush they will keep returning the old file size. 2364 */ 2365 if ((!error) && (share->ss_fstype == SMB_FS_FAT) && 2366 (!UNIX_SERVER(SSTOVC(share)))) { 2367 error = smbfs_smb_flush(share, fid, context); 2368 if (!error) 2369 np->n_flag &= ~NNEEDS_FLUSH; 2370 } 2371 /* We ignore errors on close, not much we can do about it here */ 2372 (void)smbfs_tmpclose(share, np, fid, context); 2373 } while ((error == EBADF) && (trycnt < SMB_MAX_REOPEN_CNT)); 2374 2375 SMB_LOG_IO("%s: Calling smbfs_setsize, old eof = %lld new eof = %lld\n", 2376 np->n_name, tsize, vap->va_data_size); 2377 if (error) { 2378 smbfs_setsize(vp, (off_t)tsize); 2379 goto out; 2380 } else { 2381 smbfs_setsize(vp, (off_t)vap->va_data_size); 2382 } 2383 2384 VATTR_SET_SUPPORTED(vap, va_data_size); 2385 /* Tell the stream's parent that something has changed */ 2386 if (vnode_isnamedstream(vp)) { 2387 vnode_t parent_vp = smb_update_rsrc_and_getparent(vp, TRUE); 2388 /* 2389 * We cannot always update the parents meta cache timer, so don't 2390 * even try here 2391 */ 2392 if (parent_vp) 2393 vnode_put(parent_vp); 2394 } 2395 2396 modified = 1; 2397 } 2398 2399 /* 2400 * Note that it's up to the caller to provide (or not) a fallback for 2401 * backup_time, as we don't support them. 2402 * 2403 */ 2404 crtime = VATTR_IS_ACTIVE(vap, va_create_time) ? &vap->va_create_time : NULL; 2405 mtime = VATTR_IS_ACTIVE(vap, va_modify_time) ? &vap->va_modify_time : NULL; 2406 atime = VATTR_IS_ACTIVE(vap, va_access_time) ? &vap->va_access_time : NULL; 2407 2408 /* 2409 * If they are just setting the time to the same value then just say we made 2410 * the call. This will not hurt anything and will protect us from badly 2411 * written applications. Here is what was happening in the case of the finder 2412 * copy. The file gets copied, and the modify time and create time have been set to 2413 * the current time by the server. The application is using utimes to set the 2414 * modify time to the original file's modify time. This time is before the create time. 2415 * So we set both the create and modify time to the same value. See the HFS note 2416 * below. Now the applications wants to set the create time to be the same as the 2417 * orignal file. In this case the original file has the same modify and create time. So 2418 * we end up setting the create time twice to the same value. Even with this code the 2419 * copy engine needs to be fixed, looking into that now. Looks like this will get fix 2420 * with Radar 4385758. We should retest once that radar is completed. 2421 */ 2422 if (crtime && (timespeccmp(crtime, &np->n_crtime, ==))) { 2423 VATTR_SET_SUPPORTED(vap, va_create_time); 2424 crtime = NULL; 2425 } 2426 if (mtime && (timespeccmp(mtime, &np->n_mtime, ==))) { 2427 VATTR_SET_SUPPORTED(vap, va_modify_time); 2428 mtime = NULL; 2429 } 2430 if (atime && (timespeccmp(atime, &np->n_atime, ==))) { 2431 VATTR_SET_SUPPORTED(vap, va_access_time); 2432 atime = NULL; 2433 } 2434 2435 /* 2436 * We sometimes get sent a zero access time. Did some testing and found 2437 * out the following: 2438 * 2439 * MSDOS - The date gets set to Dec 30 17:31:44 1969 2440 * SMB FAT - The date gets set to Jan 1 00:00:00 1980 2441 * UFS - The date gets set to Dec 31 16:00:00 1969 2442 * SMB NTFS- The date gets set to Dec 31 16:00:00 1969 2443 * HFS - The date displayed from ls is Dec 31 16:00:00 1969 2444 * HFS - The getattrlist date is <no value> 2445 * 2446 * I believe this is from a utimes call where they are setting the 2447 * modify time, but leaving the access time set to zero. We seem to be 2448 * doing the same thing as everyone else so let them do it. 2449 */ 2450 /* 2451 * The following comment came from the HFS code. 2452 * The utimes system call can reset the modification time but it doesn't 2453 * know about create times. So we need to ensure that the creation time 2454 * is always at least as old as the modification time. 2455 * 2456 * The HFS code also checks to make sure it was not the root vnode. Don 2457 * Brady said that the SMB code should not use that part of the check. 2458 */ 2459 if (!crtime && mtime && (timespeccmp(mtime, &np->n_crtime, <))) { 2460 crtime = mtime; 2461 } 2462 2463 if (!crtime && !mtime && !atime) { 2464 /* Nothing left to do here get out */ 2465 goto out; 2466 } 2467retrySettingTime: 2468#if 0 2469 if (crtime && mtime) { 2470 SMBDEBUG("%s crtime = %ld:%ld mtime = %ld:%ld\n", np->n_name, 2471 crtime->tv_sec, crtime->tv_nsec, mtime->tv_sec, mtime->tv_nsec); 2472 } else if (crtime) { 2473 SMBDEBUG("%s crtime = %ld:%ld\n", np->n_name, crtime->tv_sec, crtime->tv_nsec); 2474 } else if (mtime) { 2475 SMBDEBUG("%s mtime = %ld:%ld\n", np->n_name, mtime->tv_sec, mtime->tv_nsec); 2476 } 2477#endif // SMB_DEBUG 2478 /* 2479 * FAT file systems don't support dates earlier than 1980, reset the 2480 * date to 1980. Now the Finder likes to set the create date to 1904 or 1946, 2481 * should we treat this special? We could hold on to the original time 2482 * and return that value until they reset it or the vnode goes away. Since 2483 * we never had any reports lets not add any extra code. 2484 */ 2485 if (useFatTimes) { 2486 if (crtime && (timespeccmp(crtime, &fat1980_time, <))) { 2487 crtime = &fat1980_time; 2488 SMBDEBUG("%s FAT crtime.tv_sec = %ld crtime.tv_nsec = %ld\n", 2489 np->n_name, crtime->tv_sec, crtime->tv_nsec); 2490 } 2491 if (mtime && (timespeccmp(mtime, &fat1980_time, <))) { 2492 mtime = &fat1980_time; 2493 SMBDEBUG("%s FAT mtime.tv_sec = %ld mtime.tv_nsec = %ld\n", 2494 np->n_name, mtime->tv_sec, mtime->tv_nsec); 2495 } 2496 /* Never let them set the access time before 1980 */ 2497 if (atime && (timespeccmp(atime, &fat1980_time, <))) { 2498 atime = NULL; 2499 } 2500 } 2501 2502 if (SSTOVC(share)->vc_flags & SMBV_SMB2) { 2503 /* SMB2.x always has to open/set/close the file */ 2504 error = smb2fs_smb_setpattrNT(share, np, 2505 NULL, 0, 2506 np->n_dosattr, crtime, 2507 mtime, atime, 2508 context); 2509 } 2510 else { 2511 rights = SMB2_FILE_WRITE_ATTRIBUTES; 2512 /* 2513 * For Windows 95/98/Me/NT4 and all old dialects we must have 2514 * the item open before we can set the date and time. For all 2515 * other systems; if the item is already open then make sure it 2516 * has the correct open mode. 2517 * 2518 * We currently never do a NT style open with write attributes. 2519 * So for all systems except NT4 that spport the NTCreateAndX 2520 * call we will fall through and just use the set path method. 2521 * In the future we may decide to add open deny support. So if 2522 * we decide to add write atributes access then this code will 2523 * work without any other changes. 2524 */ 2525 if ((SSTOVC(share)->vc_flags & SMBV_NT4) || 2526 (smp->sm_flags & MNT_REQUIRES_FILEID_FOR_TIME) || 2527 ((!vnode_isdir(vp)) && np->f_refcnt && (np->f_rights & rights))) { 2528 2529 /* 2530 * For NT systems we need the file open for write attributes. 2531 * Either write access or all access will work. If they 2532 * already have it open for all access just use that, 2533 * otherwise use write. We corrected tmpopen 2534 * to work correctly now. So just ask for the NT access. 2535 */ 2536 error = smbfs_tmpopen(share, np, rights, &fid, context); 2537 if (error) 2538 goto out; 2539 2540 error = smbfs_smb_setfattrNT(share, np->n_dosattr, fid, crtime, 2541 mtime, atime, context); 2542 cerror = smbfs_tmpclose(share, np, fid, context); 2543 if (cerror) 2544 SMBERROR("error %d closing fid %llx file %s\n", 2545 cerror, fid, np->n_name); 2546 2547 } else { 2548 error = smbfs_smb_setpattrNT(share, np, 2549 NULL, 0, 2550 np->n_dosattr, crtime, mtime, 2551 atime, context); 2552 /* They don't support this call, we need to fallback to the old method; stupid NetApp */ 2553 if (error == ENOTSUP) { 2554 SMBWARNING("Server does not support setting time by path, fallback to old method\n"); 2555 smp->sm_flags |= MNT_REQUIRES_FILEID_FOR_TIME; /* Never go down this path again */ 2556 error = smbfs_tmpopen(share, np, rights, &fid, context); 2557 if (!error) { 2558 error = smbfs_smb_setfattrNT(share, np->n_dosattr, fid, 2559 crtime, mtime, atime, context); 2560 (void)smbfs_tmpclose(share, np, fid, context); 2561 } 2562 } 2563 } 2564 } 2565 /* 2566 * Some servers (NetApp) don't support setting time before 1970 and will 2567 * return an error here. So if we get an error and we were trying to set 2568 * the time to before 1970 lets try again, but this time lets treat them 2569 * the same as a FAT file system. 2570 */ 2571 if (error && !useFatTimes && 2572 ((crtime && (crtime->tv_sec < 0)) || (mtime && (mtime->tv_sec < 0)))) { 2573 useFatTimes = TRUE; 2574 goto retrySettingTime; 2575 } 2576 2577 if (error) 2578 goto out; 2579 2580 if (crtime) { 2581 VATTR_SET_SUPPORTED(vap, va_create_time); 2582 np->n_crtime = *crtime; 2583 } 2584 if (mtime) { 2585 VATTR_SET_SUPPORTED(vap, va_modify_time); 2586 np->n_mtime = *mtime; 2587 } 2588 if (atime) { 2589 VATTR_SET_SUPPORTED(vap, va_access_time); 2590 np->n_atime = *atime; 2591 } 2592 /* Update the change time */ 2593 if (crtime || mtime || atime) 2594 nanotime(&np->n_chtime); /* Need current date/time, so use nanotime */ 2595 2596out: 2597 if (modified) { 2598 /* 2599 * Invalidate attribute cache in case if server doesn't set 2600 * required attributes. 2601 */ 2602 np->attribute_cache_timer = 0; /* invalidate cache */ 2603 } 2604 return (error); 2605} 2606 2607/* 2608 * smbfs_vnop_getattr 2609 * 2610 * vnode_t a_vp; 2611 * struct vnode_attr *a_vap; 2612 * vfs_context_t a_context; 2613 */ 2614static int 2615smbfs_vnop_setattr(struct vnop_setattr_args *ap) 2616{ 2617 int32_t error = 0; 2618 struct smbnode *np; 2619 struct smb_share *share; 2620 2621 if ((error = smbnode_lock(VTOSMB(ap->a_vp), SMBFS_EXCLUSIVE_LOCK))) { 2622 return (error); 2623 } 2624 np = VTOSMB(ap->a_vp); 2625 np->n_lastvop = smbfs_vnop_setattr; 2626 share = smb_get_share_with_reference(VTOSMBFS(ap->a_vp)); 2627 error = smbfs_setattr (share, ap->a_vp, ap->a_vap, ap->a_context); 2628 smb_share_rele(share, ap->a_context); 2629 smbnode_unlock(VTOSMB(ap->a_vp)); 2630 /* If this is a stream try to update the parents meta cache timer. */ 2631 if (vnode_isnamedstream(ap->a_vp)) { 2632 vnode_t parent_vp = vnode_getparent(ap->a_vp); 2633 if (parent_vp) { 2634 VTOSMB(parent_vp)->attribute_cache_timer = 0; 2635 vnode_put(parent_vp); 2636 } 2637 } 2638 return (error); 2639} 2640 2641/* 2642 * smbfs_vnop_blockmap 2643 * 2644 * vnode_t a_vp; 2645 * off_t a_foffset; 2646 * uint32_t a_size; 2647 * daddr64_t *a_bpn; 2648 * uint32_t *a_run; 2649 * void *a_poff; 2650 * int32_t a_flags; 2651 */ 2652static int 2653smbfs_vnop_blockmap(struct vnop_blockmap_args *ap) 2654{ 2655 /* 2656 * Always match the VM page size. At this time it is 4K which limits us 2657 * to 44 bit file size instead of 64...??? 2658 */ 2659 /* make sure we don't go past EOF */ 2660 if (ap->a_run) 2661 *ap->a_run = ap->a_size; 2662 2663 /* divide it by block size, MUST match value in smbfs_strategy */ 2664 *ap->a_bpn = (daddr64_t)(ap->a_foffset / PAGE_SIZE); 2665 2666 if (ap->a_poff) 2667 *(int32_t *)ap->a_poff = 0; 2668 2669 return (0); 2670} 2671 2672/* 2673 * smbfs_vnop_strategy 2674 * 2675 * struct buf *a_bp; 2676 */ 2677static int 2678smbfs_vnop_strategy(struct vnop_strategy_args *ap) 2679{ 2680 struct buf *bp = ap->a_bp; 2681 vnode_t vp = buf_vnode(bp); 2682 int32_t bflags = buf_flags(bp); 2683 struct smbnode *np = VTOSMB(vp); 2684 caddr_t io_addr = 0; 2685 uio_t uio = NULL; 2686 int32_t error; 2687 SMBFID fid = 0; 2688 struct smb_share *share; 2689 uint32_t trycnt = 0; 2690 struct smbfattr *fap = NULL; 2691 2692 if (np->f_openState & kNeedRevoke) { 2693 /* behave like the deadfs does */ 2694 SMBERROR("%s waiting to be revoked\n", np->n_name); 2695 error = EIO; 2696 buf_seterror(bp, error); 2697 goto exit; 2698 } 2699 2700 SMB_MALLOC(fap, 2701 struct smbfattr *, 2702 sizeof(struct smbfattr), 2703 M_SMBTEMP, 2704 M_WAITOK | M_ZERO); 2705 if (fap == NULL) { 2706 SMBERROR("SMB_MALLOC failed\n"); 2707 error = ENOMEM; 2708 goto exit; 2709 } 2710 2711 /* 2712 * Can't use the physical addresses passed in the vector list, so map it 2713 * into the kernel address space 2714 */ 2715 if ((error = buf_map(bp, &io_addr))) { 2716 panic("smbfs_vnop_strategy: buf_map() failed with (%d)", error); 2717 } 2718 2719 uio = uio_create(1, ((off_t)buf_blkno(bp)) * PAGE_SIZE, UIO_SYSSPACE, 2720 (bflags & B_READ) ? UIO_READ : UIO_WRITE); 2721 if (!uio) { 2722 panic("smbfs_vnop_strategy: uio_create() failed"); 2723 } 2724 2725 uio_addiov(uio, CAST_USER_ADDR_T(io_addr), buf_count(bp)); 2726 /* 2727 * Remember that buf_proc(bp) can return NULL, but in that case this is 2728 * coming from the kernel and is not associated with a particular proc. 2729 * In fact it just may be the pager itself trying to free up space and there 2730 * is no proc. I need to find any proc that already has the fork open for 2731 * read or write to use for read/write to work. This is handled in the 2732 * FindFileRef routine. 2733 */ 2734 if (FindFileRef(vp, buf_proc(bp), (bflags & B_READ) ? kAccessRead : kAccessWrite, 2735 kCheckDenyOrLocks, uio_offset(uio), uio_resid(uio), NULL, &fid)) { 2736 /* No matches or no pid to match, so just use the generic shared fork */ 2737 fid = np->f_fid; /* We should always have something at this point */ 2738 } 2739 DBG_ASSERT(fid); 2740 2741 SMB_LOG_IO("%s: %s offset %lld, size %lld, bflags 0x%x\n", 2742 (bflags & B_READ) ? "Read":"Write", np->n_name, uio_offset(uio), 2743 uio_resid(uio), bflags); 2744 2745 share = smb_get_share_with_reference(VTOSMBFS(vp)); 2746 /* 2747 * Since we have already authorized the user when we opened the file, just 2748 * pass a NULL context down to the authorization code. 2749 */ 2750 if (bflags & B_READ) { 2751 error = smbfs_doread(share, (off_t)np->n_size, uio, fid, NULL); 2752 } else { 2753 error = smbfs_dowrite(share, (off_t)np->n_size, uio, fid, 0, NULL); 2754 2755 if (!error) { 2756 /* Save last time we wrote data */ 2757 nanouptime(&np->n_last_write_time); 2758 } 2759 } 2760 /* 2761 * We can't handle reopens in the normal fashion, because we have no lock. A 2762 * bad file descriptor error, could mean a reconnect happen. Since 2763 * we revoke all opens with manatory locks or open deny mode, we can just 2764 * do the open, read/write then close. 2765 * 2766 * We now have a counter that keeps us from going into an infinite loop. Once 2767 * we implement SMB2 we should take a second look at how this should be done. 2768 */ 2769 while ((error == EBADF) && (trycnt < SMB_MAX_REOPEN_CNT)) { 2770 lck_mtx_lock(&np->f_openStateLock); 2771 SMB_LOG_IO("%s failed the %s, because of reconnect, openState = 0x%x. Try again.\n", 2772 np->n_name, (bflags & B_READ) ? "READ" : "WRITE", np->f_openState); 2773 2774 if (np->f_openState & kNeedRevoke) { 2775 lck_mtx_unlock(&np->f_openStateLock); 2776 break; 2777 } 2778 2779 np->f_openState |= (kNeedReopen | kInReopen); 2780 lck_mtx_unlock(&np->f_openStateLock); 2781 2782 /* Could be a dfs share make sure we have the correct share */ 2783 smb_share_rele(share, NULL); 2784 share = smb_get_share_with_reference(VTOSMBFS(vp)); 2785 /* Recreate the uio */ 2786 uio_free(uio); 2787 uio = uio_create(1, ((off_t)buf_blkno(bp)) * PAGE_SIZE, UIO_SYSSPACE, 2788 (bflags & B_READ) ? UIO_READ : UIO_WRITE); 2789 if (!uio) { 2790 error = ENOMEM; 2791 } else { 2792 uio_addiov(uio, CAST_USER_ADDR_T(io_addr), buf_count(bp)); 2793 2794 error = smbfs_smb_open_file(share, np, 2795 np->f_rights, NTCREATEX_SHARE_ACCESS_ALL, &fid, 2796 NULL, 0, FALSE, 2797 fap, NULL); 2798 } 2799 2800 lck_mtx_lock(&np->f_openStateLock); 2801 np->f_openState &= ~kInReopen; 2802 lck_mtx_unlock(&np->f_openStateLock); 2803 2804 if (error) { 2805 break; 2806 } 2807 if (bflags & B_READ) { 2808 error = smbfs_doread(share, (off_t)np->n_size, uio, fid, NULL); 2809 } else { 2810 error = smbfs_dowrite(share, (off_t)np->n_size, uio, fid, 0, NULL); 2811 2812 if (!error) { 2813 /* Save last time we wrote data */ 2814 nanouptime(&np->n_last_write_time); 2815 } 2816 } 2817 (void)smbfs_smb_close(share, fid, NULL); 2818 trycnt++; 2819 } 2820 2821 2822 if (bflags & B_READ) { 2823 /* 2824 * If we were not able to read the entire page, check to 2825 * see if we are at the end of the file, and if so, zero 2826 * out the remaining part of the page. 2827 */ 2828 while ((error == 0) && (uio_resid(uio))) { 2829 size_t bytes_to_zero = (uio_resid(uio) > PAGE_SIZE) ? PAGE_SIZE : (size_t)uio_resid(uio); 2830 2831 bzero((caddr_t) (io_addr + buf_count(bp) - uio_resid(uio)), bytes_to_zero); 2832 uio_update(uio, bytes_to_zero); 2833 } 2834 } else { 2835 lck_mtx_lock(&np->f_clusterWriteLock); 2836 if ((u_quad_t)uio_offset(uio) >= np->n_size) { 2837 /* We finished writing past the eof reset the flag */ 2838 nanouptime(&np->n_sizetime); 2839 np->waitOnClusterWrite = FALSE; 2840 SMB_LOG_IO("%s: TURNING OFF waitOnClusterWrite np->n_size = %lld\n", 2841 np->n_name, np->n_size); 2842 } 2843 lck_mtx_unlock(&np->f_clusterWriteLock); 2844 } 2845 2846 if (error) { 2847 SMBERROR("%s on %s failed with an error of %d\n", 2848 (bflags & B_READ) ? "READ" : "WRITE", np->n_name, error); 2849 np->f_clusterCloseError = error; /* Error to be returned on close */ 2850 2851 if ( (error == ENOTCONN) || (error == EBADF) || (error == ETIMEDOUT) ) { 2852 /* 2853 * VFS cluster code has now been changed to handle non transient 2854 * errors see radar 2894150. It should be safe to return ENXIO. 2855 */ 2856 SMB_LOG_IO("failed with %d, returning ENXIO instead\n", error); 2857 error = ENXIO; 2858 } 2859 } 2860 smb_share_rele(share, NULL); 2861 buf_seterror(bp, error); 2862 2863 /* Should be zero when all done with reading/writing file */ 2864 buf_setresid(bp, (uint32_t)uio_resid(uio)); 2865 2866 if ((error = buf_unmap(bp))) 2867 panic("smbfs_vnop_strategy: buf_unmap() failed with (%d)", error); 2868 2869 2870exit: 2871 if (error) { 2872 SMB_LOG_IO("%s: buf_resid(bp) %d, error = %d \n", 2873 np->n_name, buf_resid(bp), error); 2874 } 2875 2876 if (uio != NULL) 2877 uio_free(uio); 2878 2879 buf_biodone(bp); 2880 2881 if (fap != NULL) { 2882 SMB_FREE(fap, M_SMBTEMP); 2883 } 2884 2885 return (error); 2886} 2887 2888/* 2889 * smbfs_vnop_read 2890 * 2891 * vnode_t a_vp; 2892 * uio_t a_uio; 2893 * int a_ioflag; 2894 * vfs_context_t a_context; 2895 */ 2896static int 2897smbfs_vnop_read(struct vnop_read_args *ap) 2898{ 2899 vnode_t vp = ap->a_vp; 2900 uio_t uio = ap->a_uio; 2901 int error = 0; 2902 struct smbnode *np = NULL; 2903 SMBFID fid = 0; 2904 struct smb_share *share; 2905 2906 /* Preflight checks */ 2907 if (!vnode_isreg(vp)) { 2908 /* can only read regular files */ 2909 if (vnode_isdir(vp)) 2910 return (EISDIR); 2911 else 2912 return (EPERM); 2913 } 2914 2915 if (uio_resid(uio) == 0) 2916 return (0); /* Nothing left to do */ 2917 2918 if (uio_offset(uio) < 0) 2919 return (EINVAL); /* cant read from a negative offset */ 2920 2921 if ((error = smbnode_lock(VTOSMB(vp), SMBFS_SHARED_LOCK))) 2922 return (error); 2923 2924 np = VTOSMB(vp); 2925 np->n_lastvop = smbfs_vnop_read; 2926 share = smb_get_share_with_reference(VTOSMBFS(vp)); 2927 /* 2928 * History: FreeBSD vs Darwin VFS difference; we can get VNOP_READ without 2929 * preceeding open via the exec path, so do it implicitly. VNOP_INACTIVE 2930 * closes the extra network file handle, and decrements the open count. 2931 * 2932 * If we are in reconnect mode calling smbfs_open will handle any reconnect 2933 * issues. So only if we have a f_refcnt do we call smbfs_smb_reopen_file. 2934 */ 2935 if (!np->f_refcnt) { 2936 error = smbfs_open(share, vp, FREAD, ap->a_context); 2937 if (error) 2938 goto exit; 2939 else np->f_needClose = 1; 2940 } else { 2941 error = smbfs_smb_reopen_file(share, np, ap->a_context); 2942 if (error) { 2943 SMBDEBUG(" %s waiting to be revoked\n", np->n_name); 2944 goto exit; 2945 } 2946 } 2947 /* 2948 * Note: smbfs_isCacheable checks to see if the file is globally non 2949 * cacheable, but we also need to support non cacheable on a per file 2950 * descriptor level for reads/writes. So also check the IO_NOCACHE flag. 2951 * 2952 * So IO_NOCACHE means the same thing as VNOCACHE_DATA but only for this IO. 2953 * Now VNOCACHE_DATA has the following comment: 2954 * "don't keep data cached once it's been consumed" 2955 * Which seems to imply we could use cluster_read, but we would need to 2956 * push out any data first and then invalidate the range after we are done 2957 * with the read? Byte range locking prevents us from using the cluster_read. 2958 */ 2959 if ( smbfsIsCacheable(vp) && !(ap->a_ioflag & IO_NOCACHE)) { 2960 error = cluster_read(vp, uio, (off_t) np->n_size, ap->a_ioflag); 2961 if (error) { 2962 SMB_LOG_IO("%s failed cluster_read with an error of %d\n", 2963 np->n_name, error); 2964 } 2965 /* 2966 * EACCES means a denyConflict occured and must have hit some other 2967 * computer's byte range lock on that file. Mark the file as 2968 * noncacheable and retry read again 2969 * 2970 * Need to check the error here, could be EIO/EPERM 2971 * 2972 * XXX - NOTE: The strategy routine is going to mark this vnode as needing 2973 * to be revoked. So this code seems wrong. We should either correct 2974 * the strategy routine or remove this code. 2975 */ 2976 if (error == EACCES) { 2977 if (np->n_flag & NISMAPPED) { 2978 /* More expensive, but handles mmapped files */ 2979 ubc_msync (vp, 0, ubc_getsize(vp), NULL, UBC_PUSHDIRTY | UBC_SYNC); 2980 } else { 2981 /* Less expensive, but does not handle mmapped files */ 2982 cluster_push(vp, IO_SYNC); 2983 } 2984 ubc_msync (vp, 0, ubc_getsize(vp), NULL, UBC_INVALIDATE); 2985 vnode_setnocache(vp); 2986 /* Fall through and try a non cached read */ 2987 error = 0; 2988 } else { 2989 goto exit; 2990 } 2991 } 2992 if (error) 2993 goto exit; 2994 /* 2995 * AFP COMMENTS (<rdar://problem/5977339>) Be careful of a cacheable write 2996 * that extends the eof, but leaves a hole between the old eof and the new 2997 * eof. It that is followed by a non cacheable read that starts before the 2998 * old eof and extends into the hole (or starts in the hole), but does not 2999 * extend past the hole, then msync for the read range will not find any 3000 * dirty pages in the hole and thus no data will be pushed and thus the eof 3001 * will not get extended which will cause the non cacheable read to get 3002 * erroneous data. cluster_push works around this because it pushes all of 3003 * the pages in the delayed clusters. msync for the entire range also works 3004 * too. 3005 */ 3006 if (VTOSMB(vp)->n_flag & NISMAPPED) { 3007 /* More expensive, but handles mmapped files */ 3008 ubc_msync (vp, 0, ubc_getsize(vp), NULL, UBC_PUSHDIRTY | UBC_SYNC); 3009 } else { 3010 /* Less expensive, but does not handle mmapped files */ 3011 cluster_push(vp, IO_SYNC); 3012 } 3013 /* 3014 * AFP doesn't invalidate the range here. That seems wrong, we should 3015 * invalidate the range here. 3016 */ 3017 ubc_msync (vp, uio_offset(uio), uio_offset(uio)+ uio_resid(uio), NULL, 3018 UBC_INVALIDATE); 3019 3020 if (FindFileRef(vp, vfs_context_proc(ap->a_context), kAccessRead, 3021 kCheckDenyOrLocks, uio_offset(uio), uio_resid(uio), 3022 NULL, &fid)) { 3023 /* No matches or no pid to match, so just use the generic shared fork */ 3024 fid = np->f_fid; /* We should always have something at this point */ 3025 } 3026 DBG_ASSERT(fid); 3027 3028 error = smbfs_doread(share, (off_t)np->n_size, uio, fid, ap->a_context); 3029 /* 3030 * We got an error, did it happen on a reconnect, then retry. First see if 3031 * we have a new share to use, then attmept to reopent the file, then try 3032 * the read again. 3033 */ 3034 while (error == EBADF) { 3035 SMB_LOG_IO("%s failed the non cache read, because of reconnect. Try again.\n", 3036 np->n_name); 3037 /* Could be a dfs share make sure we have the correct share */ 3038 smb_share_rele(share, ap->a_context); 3039 share = smb_get_share_with_reference(VTOSMBFS(vp)); 3040 /* The reopen code will handle the case of the node being revoked. */ 3041 if (smbfs_io_reopen(share, vp, uio, kAccessRead, &fid, error, ap->a_context) == 0) { 3042 error = smbfs_doread(share, (off_t)np->n_size, uio, fid, 3043 ap->a_context); 3044 } else { 3045 SMB_LOG_IO("%s : The Read reopen failed.\n", np->n_name); 3046 break; 3047 } 3048 } 3049 3050 if (error) { 3051 SMB_LOG_IO("%s failed non cached read with an error of %d\n", np->n_name, error); 3052 } 3053 3054exit: 3055 smb_share_rele(share, ap->a_context); 3056 smbnode_unlock(np); 3057 return (error); 3058} 3059 3060/* 3061 * smbfs_vnop_write 3062 * 3063 * vnode_t a_vp; 3064 * uio_t a_uio; 3065 * int a_ioflag; 3066 * vfs_context_t a_context; 3067 */ 3068static int 3069smbfs_vnop_write(struct vnop_write_args *ap) 3070{ 3071 vnode_t vp = ap->a_vp; 3072 vnode_t parent_vp = NULL; /* Always null unless this is a stream node */ 3073 struct smbnode *np = NULL; 3074 struct smb_share *share; 3075 uio_t uio = ap->a_uio; 3076 int error = 0; 3077 SMBFID fid = 0; 3078 u_quad_t originalEOF; 3079 user_size_t writeCount; 3080 3081 /* Preflight checks */ 3082 if (!vnode_isreg(vp)) { 3083 /* can only read regular files */ 3084 if (vnode_isdir(vp)) 3085 return (EISDIR); 3086 else 3087 return (EPERM); 3088 } 3089 3090 if (uio_offset(uio) < 0) 3091 return (EINVAL); 3092 3093 if (uio_resid(uio) == 0) 3094 return (0); 3095 3096 if ((error = smbnode_lock(VTOSMB(vp), SMBFS_EXCLUSIVE_LOCK))) 3097 return (error); 3098 3099 np = VTOSMB(vp); 3100 np->n_lastvop = smbfs_vnop_write; 3101 share = smb_get_share_with_reference(VTOSMBFS(vp)); 3102 3103 /* Before trying the write see if the file needs to be reopened */ 3104 error = smbfs_smb_reopen_file(share, np, ap->a_context); 3105 if (error) { 3106 SMBDEBUG(" %s waiting to be revoked\n", np->n_name); 3107 goto exit; 3108 } 3109 3110 if (ap->a_ioflag & IO_APPEND) 3111 uio_setoffset(uio, np->n_size); 3112 3113 originalEOF = np->n_size; /* Save off the orignial end of file */ 3114 3115 /* 3116 * Note: smbfs_isCacheable checks to see if the file is globally non 3117 * cacheable, but we also need to support non cacheable on a per file 3118 * descriptor level for reads/writes. So also check the IO_NOCACHE flag. 3119 * 3120 * So IO_NOCACHE means the same thing as VNOCACHE_DATA but only for this IO. 3121 * Now VNOCACHE_DATA has the following comment: 3122 * "don't keep data cached once it's been consumed" 3123 * Which seems to imply we could use cluster_write, but we would need to 3124 * push out any data and then invalidate the range after we are done 3125 * with the write? Byte range locking prevents us from using the cluster_write. 3126 */ 3127 if (smbfsIsCacheable(vp) && !(ap->a_ioflag & IO_NOCACHE)) { 3128 u_quad_t writelimit; 3129 u_quad_t newEOF; 3130 u_quad_t zero_head_off; 3131 u_quad_t zero_tail_off; 3132 int32_t lflag; 3133 3134 lflag = ap->a_ioflag & ~(IO_TAILZEROFILL | IO_HEADZEROFILL | 3135 IO_NOZEROVALID | IO_NOZERODIRTY); 3136 zero_head_off = 0; 3137 zero_tail_off = 0; 3138 writelimit = uio_offset(uio) + uio_resid(uio); 3139 3140 /* 3141 * They are writing pass the eof, force a zero fill. What should we 3142 * do for sparse files? 3143 */ 3144 if ((uint64_t)writelimit > np->n_size) { 3145 /* Save off the new eof */ 3146 newEOF = writelimit; 3147 if ((uint64_t) uio_offset(uio) > np->n_size) { 3148 zero_head_off = np->n_size; 3149 /* Make sure we tell the kernel to zero fill the head */ 3150 lflag |= IO_HEADZEROFILL; 3151 } 3152 zero_tail_off = (writelimit + (PAGE_SIZE_64 - 1)) & ~PAGE_MASK_64; 3153 if (zero_tail_off > newEOF) { 3154 zero_tail_off = newEOF; 3155 } 3156 if (zero_tail_off > writelimit) { 3157 /* Make sure we tell the kernel to zero fill the tail */ 3158 lflag |= IO_TAILZEROFILL; 3159 } 3160 } else 3161 newEOF = np->n_size; 3162 3163 lck_mtx_lock(&np->f_clusterWriteLock); 3164 if (originalEOF < newEOF) { 3165 np->waitOnClusterWrite = TRUE; 3166 np->n_size = newEOF; 3167 SMB_LOG_IO("%s: TURNING ON waitOnClusterWrite old eof = %lld new eof = %lld\n", 3168 np->n_name, originalEOF, newEOF); 3169 } 3170 lck_mtx_unlock(&np->f_clusterWriteLock); 3171 /* 3172 * If the write starts beyond the current EOF then we we'll zero fill 3173 * from the current EOF to where the write begins 3174 */ 3175 error = cluster_write(vp, uio, originalEOF, newEOF, zero_head_off, zero_tail_off, lflag); 3176 if (error) { 3177 lck_mtx_lock(&np->f_clusterWriteLock); 3178 np->n_size = originalEOF; /* Set it back to the original eof */ 3179 np->waitOnClusterWrite = FALSE; 3180 lck_mtx_unlock(&np->f_clusterWriteLock); 3181 SMB_LOG_IO("%s failed cluster_write with an error of %d\n", np->n_name, error); 3182 } 3183 /* 3184 * EACCES means a denyConflict occured and must have hit some other 3185 * computer's byte range lock on that file. Mark the file as 3186 * noncacheable and retry read again 3187 * 3188 * Need to check the error here, could be EIO/EPERM 3189 * 3190 * XXX - NOTE: The stragey routine is going to mark this vnode as needing 3191 * to be revokd. So this code seems wrong. We should either correct 3192 * the stragey routine or remove this code. 3193 */ 3194 if (error == EACCES) { 3195 if (np->n_flag & NISMAPPED) { 3196 /* More expensive, but handles mmapped files */ 3197 ubc_msync (vp, 0, ubc_getsize(vp), NULL, UBC_PUSHDIRTY | UBC_SYNC); 3198 } else { 3199 /* Less expensive, but does not handle mmapped files */ 3200 cluster_push(vp, IO_SYNC); 3201 } 3202 ubc_msync (vp, 0, ubc_getsize(vp), NULL, UBC_INVALIDATE); 3203 vnode_setnocache(vp); 3204 /* Fall through and try a non cached write */ 3205 error = 0; 3206 } else { 3207 goto exit; 3208 } 3209 } 3210 if (error) 3211 goto exit; 3212 /* 3213 * If it is not cacheable, make sure to wipe out UBC since any of its 3214 * data would be no be invalid. Make sure to push out any dirty data 3215 * first due to prev cached write. 3216 */ 3217 ubc_msync(vp, uio_offset(uio), uio_offset(uio)+ uio_resid(uio), NULL, 3218 UBC_PUSHDIRTY | UBC_SYNC); 3219 ubc_msync(vp, uio_offset(uio), uio_offset(uio)+ uio_resid(uio), NULL, 3220 UBC_INVALIDATE); 3221 3222 3223 if (FindFileRef(vp, vfs_context_proc(ap->a_context), kAccessWrite, 3224 kCheckDenyOrLocks, uio_offset(uio), uio_resid(uio), NULL, &fid)) { 3225 /* No matches or no pid to match, so just use the generic shared fork */ 3226 fid = np->f_fid; /* We should always have something at this point */ 3227 } 3228 DBG_ASSERT(fid); 3229 3230 /* Total amount that we need to write */ 3231 writeCount = uio_resid(ap->a_uio); 3232 do { 3233 if (uio && (uio != ap->a_uio)) { 3234 /* We allocated, need to free it */ 3235 uio_free(uio); 3236 } 3237 /* 3238 * We could get disconnected in the middle of a write, so we need to make 3239 * a copy of the uio, just in case. 3240 */ 3241 uio = uio_duplicate(ap->a_uio); 3242 if (uio == NULL) { 3243 /* Failed, so just used the passed in uio */ 3244 uio = ap->a_uio; 3245 } 3246 error = smbfs_dowrite(share, (off_t)np->n_size, uio, fid, ap->a_ioflag, 3247 ap->a_context); 3248 if (!error) { 3249 /* Save last time we wrote data */ 3250 nanouptime(&np->n_last_write_time); 3251 } 3252 3253 if (error == EBADF) { 3254 /* Could be a dfs share make sure we have the correct share */ 3255 smb_share_rele(share, ap->a_context); 3256 share = smb_get_share_with_reference(VTOSMBFS(vp)); 3257 if (smbfs_io_reopen(share, vp, uio, kAccessWrite, &fid, error, 3258 ap->a_context) != 0) { 3259 /* The reopen failed, just get out nothing left to do here */ 3260 break; 3261 } 3262 } 3263 } while ((error == EBADF) && (uio != ap->a_uio)); 3264 /* Set the original uio to match the one passed into the write. */ 3265 if (uio != ap->a_uio) { 3266 /* Total amount we were able to write */ 3267 writeCount -= uio_resid(uio); 3268 /* Update the user's uio with that amount */ 3269 uio_update( ap->a_uio, writeCount); 3270 uio_free(uio); 3271 uio = ap->a_uio; 3272 } 3273 3274 /* 3275 * Mark that we need to send a flush if we didn't get an error and 3276 * we didn't send a write though message. Remember if the IO_SYNC bit 3277 * is set then we set the write though bit, which should do the same 3278 * thing as a flush. 3279 */ 3280 if (!error && !(ap->a_ioflag & IO_SYNC)) { 3281 VTOSMB(vp)->n_flag |= NNEEDS_FLUSH; 3282 } else if (error) { 3283 SMB_LOG_IO("%s failed non cached write with an error of %d\n", 3284 np->n_name, error); 3285 } 3286exit: 3287 /* Wrote pass the eof, need to set the new file size */ 3288 if (!error && ((uint64_t) uio_offset(uio) > originalEOF)) { 3289 /* 3290 * Windows servers do not handle writing past the end of file the 3291 * same as Unix servers. If we do a directory lookup before the file 3292 * is closed then the server may return the old size. Setting the end of 3293 * file here will prevent that from happening. Unix servers do not seem 3294 * to have this problem so there is no reason to make this call in that 3295 * case. So if the file size has changed and this is not a Unix server 3296 * then set the eof of file to the new value. 3297 */ 3298 if (!UNIX_SERVER(SSTOVC(share))) { 3299 /* 3300 * Just set the flag to set EOF later. Otherwise for every write 3301 * on a cached file, a set EOF request will be sent to the server. 3302 * This will result in hundreds/thousands of set EOF requests being 3303 * sent constantly to the server. 3304 * 3305 * The file size is cached locally so sending the set EOF request 3306 * to the server can wait until system sync or vnop_sync time. 3307 */ 3308 np->n_flag |= NNEEDS_EOF_SET; 3309 3310 /* 3311 * Windows FAT file systems require a flush, after a seteof. Until the 3312 * the flush they will keep returning the old file size. 3313 */ 3314 if (share->ss_fstype == SMB_FS_FAT) { 3315 /* Do the flush later too */ 3316 np->n_flag |= NNEEDS_FLUSH; 3317 3318 } 3319 } 3320 3321 smbfs_setsize(vp, uio_offset(uio)); 3322 SMB_LOG_IO("%s: Calling smbfs_setsize, old eof = %lld new eof = %lld time %ld:%ld\n", 3323 np->n_name, originalEOF, uio_offset(uio), 3324 np->n_sizetime.tv_sec, np->n_sizetime.tv_nsec); 3325 /* 3326 * We could have lost a cache update in the write. Since we wrote pass 3327 * the eof, mark that the close should clear the cache timer. This way 3328 * the cache will be update with the server. We clear this flag in cache 3329 * entry so any lookups after this write will clear the flag. 3330 */ 3331 np->n_flag |= NATTRCHANGED; 3332 } 3333 3334 /* Tell the stream's parent that something has changed */ 3335 if (vnode_isnamedstream(vp)) 3336 parent_vp = smb_update_rsrc_and_getparent(vp, FALSE); 3337 3338 smb_share_rele(share, ap->a_context); 3339 smbnode_unlock(VTOSMB(vp)); 3340 /* We have the parent vnode, so reset its meta data cache timer. */ 3341 if (parent_vp) { 3342 VTOSMB(parent_vp)->attribute_cache_timer = 0; 3343 vnode_put(parent_vp); 3344 } 3345 3346 return (error); 3347} 3348 3349/* 3350 * This is an internal utility function called from our smbfs_mkdir and 3351 * smbfs_create to set the vnode_attr passed into those routines. The first 3352 * problem comes from the vfs layer. It wants to set things that the server will 3353 * set for us. So to stop taking a performance hit turn off those items that vfs 3354 * turn on. See vnode_authattr_new for what is getting set. Second there is a set 3355 * of items that we can't set anyways so clear them out and pretend we did it. 3356 * Third if they are setting ACLs then make sure we keep any inherited ACLs. 3357 * 3358 * Question should we ever error out in this routine? The old code never did, but 3359 * what if setting the mode, owner, group, or acl fails? 3360 * 3361 * The calling routine must hold a reference on the share 3362 * 3363 */ 3364static void 3365smbfs_set_create_vap(struct smb_share *share, struct vnode_attr *vap, vnode_t vp, 3366 vfs_context_t context, int set_mode_now) 3367{ 3368 struct smbnode *np = VTOSMB(vp); 3369 struct smbmount *smp = np->n_mount; 3370 struct vnode_attr svrva; 3371 kauth_acl_t savedacl = NULL; 3372 int error; 3373 int has_posix_modes = ((UNIX_CAPS(share) & UNIX_QFILEINFO_UNIX_INFO2_CAP)) ? TRUE : FALSE;; 3374 3375 if ((!has_posix_modes) && 3376 (SSTOVC(share)->vc_server_caps & kAAPL_SUPPORTS_NFS_ACE)) { 3377 /* 3378 * For OS X <-> OS X PFS (where ACLs are off by default), we 3379 * need a way to set Posix permissions. If the server supports 3380 * the NFS ACE, then it will allow us to get the ACL and send 3381 * it back with the desired Posix permissions in the NFS ACE. 3382 */ 3383 has_posix_modes = TRUE; 3384 } 3385 3386 /* 3387 * Initialize here so we know if it needs to be freed at the end. Also 3388 * ask for everything since its the same performance hit and updates our 3389 * nodes uid/gid cache. The following are not used unless the user is 3390 * setting ACLs. 3391 */ 3392 VATTR_INIT(&svrva); 3393 VATTR_WANTED(&svrva, va_acl); 3394 VATTR_WANTED(&svrva, va_uuuid); 3395 VATTR_WANTED(&svrva, va_guuid); 3396 3397 /* 3398 * This will be zero if vnode_authattr_new set it. Do not change 3399 * this on create, the default is fine. 3400 */ 3401 if (VATTR_IS_ACTIVE(vap, va_flags) && (vap->va_flags == 0)) { 3402 VATTR_SET_SUPPORTED(vap, va_flags); 3403 VATTR_CLEAR_ACTIVE(vap, va_flags); 3404 } 3405 /* The server will set all times for us */ 3406 if (VATTR_IS_ACTIVE(vap, va_create_time)) { 3407 VATTR_SET_SUPPORTED(vap, va_create_time); 3408 VATTR_CLEAR_ACTIVE(vap, va_create_time); 3409 } 3410 if (VATTR_IS_ACTIVE(vap, va_modify_time)) { 3411 VATTR_SET_SUPPORTED(vap, va_modify_time); 3412 VATTR_CLEAR_ACTIVE(vap, va_modify_time); 3413 } 3414 if (VATTR_IS_ACTIVE(vap, va_access_time)) { 3415 VATTR_CLEAR_ACTIVE(vap, va_access_time); 3416 VATTR_SET_SUPPORTED(vap, va_access_time); 3417 } 3418 if (VATTR_IS_ACTIVE(vap, va_change_time)) { 3419 VATTR_CLEAR_ACTIVE(vap, va_change_time); 3420 VATTR_SET_SUPPORTED(vap, va_change_time); 3421 } 3422 3423 if (VATTR_IS_ACTIVE(vap, va_mode)) { 3424 if (set_mode_now == TRUE) { 3425 /* compound_vnop_open already has the file open so we can set the 3426 Posix file modes if server supports Posix perms and reg file */ 3427 VATTR_SET_SUPPORTED(vap, va_mode); 3428 3429 if ( !vnode_isreg(vp) || !has_posix_modes ) { 3430 VATTR_CLEAR_ACTIVE(vap, va_mode); 3431 } 3432 } 3433 else { 3434 /* 3435 * This routine gets called from create. If this is a regular file they 3436 * could be setting the posix file modes to something that doesn't allow 3437 * them to open the file with the permissions they requested. 3438 * Example: open(path, O_WRONLY | O_CREAT | O_EXCL, 0400) 3439 * We only care about this if the server supports setting/getting posix 3440 * permissions. So if they are setting the owner with read/write access 3441 * then save the settings until after the open. We will just pretend to 3442 * set them here. The following radar will make this a mute point. 3443 * 3444 * <rdar://problem/5199099> Need a new VNOP_OPEN call that allows the 3445 * create/lookup/open/access in one call 3446 */ 3447 if (vnode_isreg(vp) && has_posix_modes && 3448 ((vap->va_mode & (S_IRUSR | S_IWUSR)) != (S_IRUSR | S_IWUSR))) { 3449 np->create_va_mode = vap->va_mode; 3450 np->set_create_va_mode = TRUE; 3451 /* The server should always give us read/write on create */ 3452 VATTR_SET_SUPPORTED(vap, va_mode); 3453 VATTR_CLEAR_ACTIVE(vap, va_mode); 3454 } else if (!has_posix_modes) { 3455 /* We can only set these if the server supports the unix extensions */ 3456 VATTR_SET_SUPPORTED(vap, va_mode); 3457 VATTR_CLEAR_ACTIVE(vap, va_mode); 3458 } 3459 } 3460 } 3461 3462 /* 3463 * We have never supported setting the uid, this is supported by the 3464 * UNIX extensions and for other servers we could convert it using 3465 * uid --> UUID --> SID translation. This just seems like a waste of 3466 * time since they would only be able to set it to themself if they 3467 * are already the owner. So just say we did, this is what we have 3468 * always done. 3469 */ 3470 if (VATTR_IS_ACTIVE(vap, va_uid)) { 3471 VATTR_SET_SUPPORTED(vap, va_uid); 3472 VATTR_CLEAR_ACTIVE(vap, va_uid); 3473 } 3474 3475 /* 3476 * We have never supported setting the gid, this is supported by the 3477 * UNIX extensions and for other servers we could convert it using 3478 * gid --> GUID --> SID translation. We may want to add the support 3479 * in the future, but we should require that they do this by setting 3480 * the va_guuid. 3481 */ 3482 if (VATTR_IS_ACTIVE(vap, va_gid)) { 3483 VATTR_SET_SUPPORTED(vap, va_gid); 3484 VATTR_CLEAR_ACTIVE(vap, va_gid); 3485 if (vap->va_gid != smp->sm_args.gid) 3486 SMB_LOG_ACCESS("They want to set the gid to %d from %d\n", 3487 vap->va_gid, smp->sm_args.gid); 3488 } 3489 3490 /* 3491 * If they have an ACE that allows them to take ownership then 3492 * this call will work. Should we test to see before going any 3493 * future. 3494 */ 3495 if (VATTR_IS_ACTIVE(vap, va_uuuid)) { 3496 VATTR_SET_SUPPORTED(vap, va_uuuid); 3497 /* We never let them set it if a TEMP UUID */ 3498 if (is_memberd_tempuuid(&vap->va_uuuid)) 3499 VATTR_CLEAR_ACTIVE(vap, va_uuuid); 3500 } 3501 3502 /* 3503 * If they have an ACE that allows them to make this change then 3504 * this call will work. Should we test to see before going any 3505 * future. 3506 */ 3507 if (VATTR_IS_ACTIVE(vap, va_guuid)) { 3508 VATTR_SET_SUPPORTED(vap, va_guuid); 3509 /* We never let them set it if a TEMP UUID */ 3510 if (is_memberd_tempuuid(&vap->va_guuid)) 3511 VATTR_CLEAR_ACTIVE(vap, va_guuid); 3512 } 3513 3514 /* 3515 * Make sure the VFS layer doesn't fall back to using EA, always say we set 3516 * the ACL. 3517 */ 3518 if (VATTR_IS_ACTIVE(vap, va_acl)) { 3519 VATTR_SET_SUPPORTED(vap, va_acl); 3520 /* Nothing for us to do here */ 3521 if ((vap->va_acl == NULL) || (vap->va_acl->acl_entrycount == 0)) 3522 VATTR_CLEAR_ACTIVE(vap, va_acl); 3523 } 3524 3525 /* All we have left to do is call our setattr */ 3526 if (!VATTR_IS_ACTIVE(vap, va_acl)) 3527 goto do_setattr; 3528 3529 /* Get the inherited ACLs from the server */ 3530 error = smbfs_getattr(share, vp, &svrva, context); 3531 if (error) { 3532 SMBWARNING("Error %d returned while gettting the inherit ACLs from the server\n", 3533 error); 3534 goto out; 3535 } 3536 3537 /* 3538 * if none created then just slam in the requested ACEs 3539 */ 3540 if (!VATTR_IS_SUPPORTED(&svrva, va_acl) || svrva.va_acl == NULL || 3541 svrva.va_acl->acl_entrycount == 0) { 3542 goto do_setattr; 3543 } 3544 error = smbfs_compose_create_acl(vap, &svrva, &savedacl); 3545 if (error) 3546 goto out; 3547 3548do_setattr: 3549 error = smbfs_setattr(share, vp, vap, context); 3550 if (error) 3551 SMBERROR("smbfs_setattr, error %d\n", error); 3552 if (savedacl) { 3553 kauth_acl_free(vap->va_acl); 3554 vap->va_acl = savedacl; 3555 } 3556out: 3557 if (VATTR_IS_SUPPORTED(&svrva, va_acl) && svrva.va_acl != NULL) 3558 kauth_acl_free(svrva.va_acl); 3559 return; 3560} 3561 3562/* 3563 * Create a regular file or a "symlink". In the symlink case we will have a target. Depending 3564 * on the sytle of symlink the target may be just what we set or we may need to encode it into 3565 * that wacky windows data 3566 * 3567 * The calling routine must hold a reference on the share 3568 * 3569 */ 3570static int 3571smbfs_create(struct smb_share *share, struct vnop_create_args *ap, char *target, 3572 size_t targetlen) 3573{ 3574 vnode_t dvp = ap->a_dvp; 3575 struct vnode_attr *vap = ap->a_vap; 3576 vnode_t *vpp = ap->a_vpp; 3577 struct componentname *cnp = ap->a_cnp; 3578 struct smbnode *dnp = VTOSMB(dvp); 3579 struct smbmount *smp = VTOSMBFS(dvp); 3580 vnode_t vp; 3581 struct smbfattr fattr; 3582 const char *name = cnp->cn_nameptr; 3583 size_t nmlen = cnp->cn_namelen; 3584 int error; 3585 struct timespec ts; 3586 int unix_symlink = ((UNIX_CAPS(share) & UNIX_SFILEINFO_UNIX_LINK_CAP)) ? TRUE : FALSE; 3587 3588 *vpp = NULL; 3589 if (vap->va_type != VREG && vap->va_type != VLNK) 3590 return (ENOTSUP); 3591 3592 if (vap->va_type == VLNK) { 3593 if (smp->sm_flags & MNT_SUPPORTS_REPARSE_SYMLINKS) { 3594 error = smbfs_smb_create_reparse_symlink(share, dnp, name, nmlen, target, 3595 targetlen, &fattr, ap->a_context); 3596 } else if (unix_symlink) { 3597 error = smbfs_smb_create_unix_symlink(share, dnp, name, nmlen, target, 3598 targetlen, &fattr, ap->a_context); 3599 } else { 3600 error = smbfs_smb_create_windows_symlink(share, dnp, name, nmlen, target, 3601 targetlen, &fattr, ap->a_context); 3602 } 3603 } else { 3604 /* Now create the file, sending a null fid pointer will cause it to be closed */ 3605 error = smbfs_smb_create(share, dnp, name, nmlen, SMB2_FILE_WRITE_DATA, 3606 NULL, FILE_CREATE, 0, &fattr, ap->a_context); 3607 } 3608 if (error) { 3609 if (error == ENOENT) { 3610 SMBDEBUG("Creating %s returned ENOENT, resetting to EACCES\n", name); 3611 /* 3612 * Some servers (Samba) support an option called veto. This prevents 3613 * clients from creating or access these files. The server returns 3614 * an ENOENT error in these cases. The VFS layer will loop forever 3615 * if a ENOENT error is returned on create, so we convert this error 3616 * to EACCES. 3617 */ 3618 error = EACCES; 3619 } 3620 return (error); 3621 } 3622 smbfs_attr_touchdir(dnp, (share->ss_fstype == SMB_FS_FAT)); 3623 /* 3624 * We have smbfs_nget returning a lock so we need to unlock it when we 3625 * are done with it. Would really like to clean this code up in the future. 3626 * The whole create, mkdir and smblink create code should use the same code path. 3627 */ 3628 fattr.fa_vtype = vap->va_type; 3629 error = smbfs_nget(share, vnode_mount(dvp), 3630 dvp, name, nmlen, 3631 &fattr, &vp, 3632 cnp->cn_flags, SMBFS_NGET_CREATE_VNODE, 3633 ap->a_context); 3634 if (error) { 3635 /* Error, try to cleanup anything we created on the server */ 3636 smbfs_smb_delete(share, dnp, name, nmlen, 0, ap->a_context); 3637 goto bad; 3638 } 3639 3640 /* 3641 * We just created the file, so we have no finder info and the resource fork 3642 * should be empty. So set our cache timers to reflect this information 3643 */ 3644 nanouptime(&ts); 3645 VTOSMB(vp)->finfo_cache = ts.tv_sec; 3646 VTOSMB(vp)->rfrk_cache_timer = ts.tv_sec; 3647 3648 smbfs_set_create_vap(share, vap, vp, ap->a_context, FALSE); 3649 3650 if (vap->va_type == VLNK) { 3651 smbfs_update_symlink_cache(VTOSMB(vp), target, targetlen); 3652 VTOSMB(vp)->n_size = targetlen; /* Set it to the correct size */ 3653 if (!unix_symlink) /* Mark it as a Windows symlink */ 3654 VTOSMB(vp)->n_flag |= NWINDOWSYMLNK; 3655 } 3656 *vpp = vp; 3657 smbnode_unlock(VTOSMB(vp)); /* Done with the smbnode unlock it. */ 3658 3659 dnp->d_changecnt++; 3660 3661 /* Remove any negative cache entries. */ 3662 if (dnp->n_flag & NNEGNCENTRIES) { 3663 dnp->n_flag &= ~NNEGNCENTRIES; 3664 cache_purge_negatives(dvp); 3665 } 3666 3667bad: 3668 /* if success, blow away statfs cache */ 3669 if (!error) 3670 smp->sm_statfstime = 0; 3671 return (error); 3672} 3673 3674/* 3675 * smbfs_vnop_create 3676 * 3677 * vnode_t a_dvp; 3678 * vnode_t *a_vpp; 3679 * struct componentname *a_cnp; 3680 * struct vnode_attr *a_vap; 3681 * vfs_context_t a_context; 3682 */ 3683static int 3684smbfs_vnop_create(struct vnop_create_args *ap) 3685{ 3686 vnode_t dvp = ap->a_dvp; 3687 int error; 3688 struct smbnode *dnp; 3689 struct smb_share *share; 3690 3691 /* Make sure we lock the parent before calling smbfs_create */ 3692 if ((error = smbnode_lock(VTOSMB(dvp), SMBFS_EXCLUSIVE_LOCK))) 3693 return (error); 3694 3695 dnp = VTOSMB(dvp); 3696 dnp->n_lastvop = smbfs_vnop_create; 3697 share = smb_get_share_with_reference(VTOSMBFS(dvp)); 3698 3699 error = smbfs_create(share, ap, NULL, 0); 3700 3701 smb_share_rele(share, ap->a_context); 3702 smbnode_unlock(dnp); 3703 return (error); 3704} 3705 3706/* 3707 * The calling routine must hold a reference on the share 3708 */ 3709static int 3710smbfs_remove(struct smb_share *share, vnode_t dvp, vnode_t vp, 3711 struct componentname *cnp, int flags, vfs_context_t context) 3712{ 3713#pragma unused(cnp) 3714 struct smbnode *dnp = VTOSMB(dvp); 3715 proc_t p = vfs_context_proc(context); 3716 struct smbnode *np = VTOSMB(vp); 3717 struct smbmount *smp = VTOSMBFS(vp); 3718 int error; 3719 uint64_t hashval = 0; 3720 3721 DBG_ASSERT((!vnode_isnamedstream(vp))) 3722 cache_purge(vp); 3723 3724 /* 3725 * Carbon semantics prohibit deleting busy files. 3726 * (enforced when NODELETEBUSY is requested) We just return 3727 * EBUSY here. Do not print an error to system log in this 3728 * case. 3729 * 3730 * NOTE: Kqueue opens will not be found by vnode_isinuse 3731 */ 3732 if (flags & VNODE_REMOVE_NODELETEBUSY) { 3733 if (vnode_isinuse(vp, 0)) { 3734 return (EBUSY); /* Do not print an error in this case */ 3735 } else { 3736 /* Check if any streams associated with this vnode are opened */ 3737 vnode_t svpp = smbfs_find_vgetstrm(smp, np, SFM_RESOURCEFORK_NAME, 3738 share->ss_maxfilenamelen); 3739 if (svpp) { 3740 if (vnode_isinuse(svpp, 0)) { 3741 /* 3742 * This vnode has an opened stream associated with it, 3743 * we still need to return EBUSY here. 3744 * See <rdar://problem/9904683> 3745 */ 3746 smbnode_unlock(VTOSMB(svpp)); 3747 vnode_put(svpp); 3748 SMBDEBUG("%s: Cannot delete %s, resource fork in use\n", __FUNCTION__, vnode_getname(vp)); 3749 return (EBUSY); /* Do not print an error in this case */ 3750 } else { 3751 smbnode_unlock(VTOSMB(svpp)); 3752 vnode_put(svpp); 3753 } 3754 } 3755 } 3756 } 3757 3758 /* 3759 * Did we open this in our read routine. Then we should close it. 3760 */ 3761 if ((np->f_refcnt == 1) && np->f_needClose) { 3762 error = smbfs_close(share, vp, FREAD, context); 3763 if (error) 3764 SMBWARNING("error %d closing %s\n", error, np->n_name); 3765 } 3766 3767 /* 3768 * The old code would check vnode_isinuse to see if the file was open, 3769 * but if the file was open by Kqueue then vnode_isinuse will not find it. 3770 * So at this point if the file is open then do the silly rename delete 3771 * trick if the server supports it. 3772 */ 3773 if (np->f_refcnt) { 3774 error = smbfs_delete_openfile(share, dnp, np, context); 3775 if (!error) { 3776 /* skip doing the vnode_recycle as file may still be on server */ 3777 return(0); 3778 } 3779 3780 goto out; 3781 } 3782 3783 /* 3784 * NetApp and Samba servers will reuse the File ID immediately after a 3785 * delete, so remove the smb node from the hash table before doing the 3786 * delete. If the delete fails, then we know the File ID is still valid 3787 * and it should be ok to reinsert the smbnode. 3788 */ 3789 smb_vhashrem(np); 3790 3791 error = smbfs_smb_delete(share, np, NULL, 0, 0, context); 3792 if (error) { 3793 /* 3794 * Delete failed, add smbnode back into hash table. 3795 * Then leave as there is nothing else we can do at this point 3796 */ 3797 hashval = smbfs_hash(share, np->n_ino, np->n_name, np->n_nmlen); 3798 smb_vhashadd(np, hashval); 3799 3800 goto out; 3801 } 3802 3803 smbfs_attr_touchdir(dnp, (share->ss_fstype == SMB_FS_FAT)); 3804 dnp->d_changecnt++; 3805 3806 /* Remove any negative cache entries. */ 3807 if (dnp->n_flag & NNEGNCENTRIES) { 3808 dnp->n_flag &= ~NNEGNCENTRIES; 3809 cache_purge_negatives(dvp); 3810 } 3811 3812out: 3813 if (error == EBUSY) { 3814 char errbuf[32]; 3815 3816 (void)proc_name(proc_pid(p), &errbuf[0], 32); 3817 SMBWARNING("warning: pid %d(%.*s) unlink open file(%s)\n", proc_pid(p), 3818 32, &errbuf[0], np->n_name); 3819 } 3820 3821 if (!error) { 3822 /* Not sure why we do this here. Leave it for now. */ 3823 (void) vnode_recycle(vp); 3824 /* if success, blow away statfs cache */ 3825 smp->sm_statfstime = 0; 3826 } 3827 3828 return (error); 3829} 3830 3831/* 3832 * smbfs_vnop_remove 3833 * 3834 * vnode_t a_dvp; 3835 * vnode_t a_vp; 3836 * struct componentname *a_cnp; 3837 * int a_flags; 3838 * vfs_context_t a_context; 3839 */ 3840static int 3841smbfs_vnop_remove(struct vnop_remove_args *ap) 3842{ 3843 vnode_t dvp = ap->a_dvp; 3844 vnode_t vp = ap->a_vp; 3845 int32_t error; 3846 struct smb_share *share; 3847 3848 if (dvp == vp) 3849 return (EINVAL); 3850 3851 /* Always put in the order of parent then child */ 3852 if ((error = smbnode_lockpair(VTOSMB(dvp), VTOSMB(vp), SMBFS_EXCLUSIVE_LOCK))) 3853 return (error); 3854 3855 VTOSMB(dvp)->n_lastvop = smbfs_vnop_remove; 3856 VTOSMB(vp)->n_lastvop = smbfs_vnop_remove; 3857 share = smb_get_share_with_reference(VTOSMBFS(dvp)); 3858 error = smbfs_remove(share, dvp, vp, ap->a_cnp, ap->a_flags, ap->a_context); 3859 smb_share_rele(share, ap->a_context); 3860 smbnode_unlockpair(VTOSMB(dvp), VTOSMB(vp)); 3861 return (error); 3862 3863} 3864 3865/* 3866 * smbfs remove directory call 3867 * 3868 * The calling routine must hold a reference on the share 3869 * 3870 */ 3871static int 3872smbfs_rmdir(struct smb_share *share, vnode_t dvp, vnode_t vp, 3873 struct componentname *cnp, vfs_context_t context) 3874{ 3875#pragma unused(cnp) 3876 struct smbmount *smp = VTOSMBFS(vp); 3877 struct smbnode *dnp = VTOSMB(dvp); 3878 struct smbnode *np = VTOSMB(vp); 3879 int error; 3880 SMBFID fid = 0; 3881 uint64_t hashval = 0; 3882 3883 /* XXX other OSX fs test fs nodes here, not vnodes. Why? */ 3884 if (dvp == vp) { 3885 error = EINVAL; 3886 goto bad; 3887 } 3888 3889 cache_purge(vp); 3890 3891 /* 3892 * NetApp and Samba servers will reuse the File ID immediately after a 3893 * delete, so remove the smb node from the hash table before doing the 3894 * delete. If the delete fails, then we know the File ID is still valid 3895 * and it should be ok to reinsert the smbnode. 3896 */ 3897 smb_vhashrem(np); 3898 3899 error = smbfs_smb_rmdir(share, np, context); 3900 if (error) { 3901 /* 3902 * Delete failed, add smbnode back into hash table. 3903 * Then leave as there is nothing else we can do at this point 3904 */ 3905 hashval = smbfs_hash(share, np->n_ino, np->n_name, np->n_nmlen); 3906 smb_vhashadd(np, hashval); 3907 goto bad; 3908 } 3909 3910 smbfs_attr_touchdir(dnp, (share->ss_fstype == SMB_FS_FAT)); 3911 dnp->d_changecnt++; 3912 3913 /* 3914 * We may still have a change notify on this node, close it so 3915 * the item will get delete on the server. Mark it not to be 3916 * reopened first, then save off the fid, clear the node fid 3917 * now close the file descriptor. 3918 */ 3919 np->d_needReopen = FALSE; 3920 fid = np->d_fid; 3921 np->d_fid = 0; 3922 if (fid != 0) { 3923 (void)smbfs_tmpclose(share, np, fid, context); 3924 } 3925 3926 /* Remove any negative cache entries. */ 3927 if (dnp->n_flag & NNEGNCENTRIES) { 3928 dnp->n_flag &= ~NNEGNCENTRIES; 3929 cache_purge_negatives(dvp); 3930 } 3931 3932bad: 3933 /* if success, blow away statfs cache */ 3934 if (!error) { 3935 smp->sm_statfstime = 0; 3936 (void) vnode_recycle(vp); 3937 } 3938 return (error); 3939} 3940 3941/* 3942 * smbfs_vnop_rmdir 3943 * 3944 * vnode_t a_dvp; 3945 * vnode_t a_vp; 3946 * struct componentname *a_cnp; 3947 * vfs_context_t a_context; 3948 */ 3949static int smbfs_vnop_rmdir(struct vnop_rmdir_args *ap) 3950{ 3951 vnode_t dvp = ap->a_dvp; 3952 vnode_t vp = ap->a_vp; 3953 int32_t error; 3954 struct smb_share *share; 3955 3956 if (!vnode_isdir(vp)) 3957 return (ENOTDIR); 3958 3959 if (dvp == vp) 3960 return (EINVAL); 3961 3962 /* Always put in the order of parent then child */ 3963 if ((error = smbnode_lockpair(VTOSMB(dvp), VTOSMB(vp), SMBFS_EXCLUSIVE_LOCK))) 3964 return (error); 3965 3966 VTOSMB(dvp)->n_lastvop = smbfs_vnop_rmdir; 3967 VTOSMB(vp)->n_lastvop = smbfs_vnop_rmdir; 3968 share = smb_get_share_with_reference(VTOSMBFS(dvp)); 3969 error = smbfs_rmdir(share, dvp, vp, ap->a_cnp, ap->a_context); 3970 smb_share_rele(share, ap->a_context); 3971 smbnode_unlockpair(VTOSMB(dvp), VTOSMB(vp)); 3972 3973 return (error); 3974} 3975 3976/* 3977 * smbfs_vnop_rename 3978 * 3979 * vnode_t a_fdvp; 3980 * vnode_t a_fvp; 3981 * struct componentname *a_fcnp; 3982 * vnode_t a_tdvp; 3983 * vnode_t a_tvp; 3984 * struct componentname *a_tcnp; 3985 * vfs_context_t a_context; 3986 */ 3987static int 3988smbfs_vnop_rename(struct vnop_rename_args *ap) 3989{ 3990 vnode_t fvp = ap->a_fvp; 3991 vnode_t tvp = ap->a_tvp; 3992 vnode_t fdvp = ap->a_fdvp; 3993 vnode_t tdvp = ap->a_tdvp; 3994 struct smbmount *smp = VFSTOSMBFS(vnode_mount(fvp)); 3995 struct smb_share *share = NULL; 3996 struct componentname *tcnp = ap->a_tcnp; 3997 struct componentname *fcnp = ap->a_fcnp; 3998 proc_t p = vfs_context_proc(ap->a_context); 3999 int error = 0; 4000 struct smbnode *fnp = NULL; 4001 struct smbnode *tdnp = NULL; 4002 struct smbnode *fdnp = NULL; 4003 int vtype; 4004 struct smbnode * lock_order[4] = {NULL}; 4005 int lock_cnt = 0; 4006 int ii; 4007 4008 /* Check for cross-device rename */ 4009 if ((vnode_mount(fvp) != vnode_mount(tdvp)) || 4010 (tvp && (vnode_mount(fvp) != vnode_mount(tvp)))) 4011 return (EXDEV); 4012 4013 vtype = vnode_vtype(fvp); 4014 if ( (vtype != VDIR) && (vtype != VREG) && (vtype != VLNK) ) 4015 return (EINVAL); 4016 4017 /* 4018 * First lets deal with the parents. If they are the same only lock the from 4019 * vnode, otherwise see if one is the parent of the other. We always want 4020 * to lock in parent child order if we can. If they are not the parent of 4021 * each other then lock in address order. 4022 */ 4023 lck_mtx_lock(&smp->sm_reclaim_renamelock); 4024 if (fdvp == tdvp) 4025 lock_order[lock_cnt++] = VTOSMB(fdvp); 4026 else if (VTOSMB(fdvp)->n_parent && (VTOSMB(fdvp)->n_parent == VTOSMB(tdvp))) { 4027 lock_order[lock_cnt++] = VTOSMB(tdvp); 4028 lock_order[lock_cnt++] = VTOSMB(fdvp); 4029 } else if (VTOSMB(tdvp)->n_parent && (VTOSMB(tdvp)->n_parent == VTOSMB(fdvp))) { 4030 lock_order[lock_cnt++] = VTOSMB(fdvp); 4031 lock_order[lock_cnt++] = VTOSMB(tdvp); 4032 } else if (VTOSMB(fdvp) < VTOSMB(tdvp)) { 4033 lock_order[lock_cnt++] = VTOSMB(fdvp); 4034 lock_order[lock_cnt++] = VTOSMB(tdvp); 4035 } else { 4036 lock_order[lock_cnt++] = VTOSMB(tdvp); 4037 lock_order[lock_cnt++] = VTOSMB(fdvp); 4038 } 4039 /* 4040 * Now lets deal with the children. If any of the following is true then just 4041 * lock the from vnode: 4042 * 1. The to vnode doesn't exist 4043 * 2. The to vnode and from vnodes are the same 4044 * 3. The to vnode and the from parent vnodes are the same, I know 4045 * it's strange but can happen. 4046 * Otherwise, lock in address order 4047 */ 4048 if ((tvp == NULL) || (tvp == fvp) || (tvp == fdvp)) 4049 lock_order[lock_cnt++] = VTOSMB(fvp); 4050 else { 4051 if (VTOSMB(fvp) < VTOSMB(tvp)) { 4052 lock_order[lock_cnt++] = VTOSMB(fvp); 4053 lock_order[lock_cnt++] = VTOSMB(tvp); 4054 } else { 4055 lock_order[lock_cnt++] = VTOSMB(tvp); 4056 lock_order[lock_cnt++] = VTOSMB(fvp); 4057 } 4058 } 4059 /* Make sure there are now duplicates, this would be a design flaw */ 4060 DBG_LOCKLIST_ASSERT(lock_cnt, lock_order); 4061 4062 lck_mtx_unlock(&smp->sm_reclaim_renamelock); 4063 4064 for (ii=0; ii<lock_cnt; ii++) { 4065 if (error) 4066 lock_order[ii] = NULL; 4067 else if ((error = smbnode_lock(lock_order[ii], SMBFS_EXCLUSIVE_LOCK))) 4068 lock_order[ii] = NULL; 4069 } 4070 if (error) 4071 goto out; 4072 4073 /* 4074 * Make sure that we do not proceed if we get lock after parent is 4075 * reclaimed after forced unmount. 4076 */ 4077 if (vfs_isforce(smp->sm_mp)) { 4078 error = ENXIO; 4079 goto out; 4080 } 4081 4082 fdnp = VTOSMB(fdvp); 4083 fnp = VTOSMB(fvp); 4084 tdnp = VTOSMB(tdvp); 4085 4086 fdnp->n_lastvop = smbfs_vnop_rename; 4087 fnp->n_lastvop = smbfs_vnop_rename; 4088 tdnp->n_lastvop = smbfs_vnop_rename; 4089 if (tvp != NULL) 4090 VTOSMB(tvp)->n_lastvop = smbfs_vnop_rename; 4091 4092 share = smb_get_share_with_reference(smp); 4093 /* 4094 * Check to see if the SMB_EFA_RDONLY/IMMUTABLE are set. If they are set 4095 * then do not allow the rename. See HFS and AFP code. 4096 */ 4097 if (node_isimmutable(share, fvp)) { 4098 SMBWARNING( "%s is a locked file : Permissions error on delete\n", 4099 fnp->n_name); 4100 error = EPERM; 4101 goto out; 4102 } 4103 4104 /* 4105 * Since there are no hard links (from our client point of view) 4106 * fvp==tvp means the arguments are case-variants. (If they 4107 * were identical the rename syscall doesnt call us.) 4108 */ 4109 if (fvp == tvp) 4110 tvp = NULL; 4111 4112 /* 4113 * The problem we have here is some servers will not return the correct 4114 * case of the file name in the lookup. This can cause to have two vnodes 4115 * that point to the same item. Very bad but nothing we can do about that 4116 * in smb. So if the target exist, the parents are the same and the name is 4117 * the same except for case, then don't delete the target. 4118 */ 4119 if (SSTOVC(share)->vc_misc_flags & SMBV_HAS_FILEIDS) { 4120 /* Server supports File IDs */ 4121 if (tvp && (fdvp == tdvp) && (fnp->n_ino == VTOSMB(tvp)->n_ino)) { 4122 SMBWARNING("Not removing target, same file. %s ==> %s\n", 4123 fnp->n_name, VTOSMB(tvp)->n_name); 4124 smb_vhashrem(VTOSMB(tvp)); /* Remove it from our hash so it can't be found */ 4125 (void) vnode_recycle(tvp); 4126 tvp = NULL; 4127 } 4128 } 4129 else { 4130 /* Server does not support File IDs */ 4131 if (tvp && (fdvp == tdvp) && (fnp->n_nmlen == VTOSMB(tvp)->n_nmlen) && 4132 (strncasecmp((char *)fnp->n_name, (char *)VTOSMB(tvp)->n_name, 4133 fnp->n_nmlen) == 0)) { 4134 SMBWARNING("Not removing target, same file. %s ==> %s\n", 4135 fnp->n_name, VTOSMB(tvp)->n_name); 4136 smb_vhashrem(VTOSMB(tvp)); /* Remove it from our hash so it can't be found */ 4137 (void) vnode_recycle(tvp); 4138 tvp = NULL; 4139 } 4140 } 4141 4142 /* 4143 * If we are not doing Named Streams, they gave us a target to delete, and 4144 * the source is a dot underscore file then make sure the source exist before 4145 * deleting the target. 4146 * 4147 * This problem happens when going Mac to Mac and the share is FAT or some 4148 * share that doesn't support streams. The remote VNOP_RENAME will rename 4149 * the dot underscore file underneath the client. So when the cleint tries 4150 * to rename the dot underscore it thinkis the target exist and needs to be 4151 * deleted. So never delete the target if the source doesn't exist. 4152 */ 4153 if ((tvp) && (!(share->ss_attributes & FILE_NAMED_STREAMS)) && 4154 (fnp->n_nmlen > 2) && (fnp->n_name[0] == '.') && (fnp->n_name[1] == '_')) { 4155 const char *name = (const char *)fnp->n_name; 4156 size_t nmlen = fnp->n_nmlen; 4157 struct smbfattr fattr; 4158 4159 error = smbfs_lookup(share, fdnp, &name, &nmlen, &fattr, ap->a_context); 4160 /* Should we check for any error or just ENOENT */ 4161 if (error == ENOENT) 4162 tvp = NULL; 4163 /* smbfs_lookup could have replace the name, free it if did */ 4164 if (name != (char *)fnp->n_name) { 4165 SMB_FREE(name, M_SMBNODENAME); 4166 } 4167 } 4168 4169 /* 4170 * If the destination exists then it needs to be removed. 4171 */ 4172 if (tvp) { 4173 if (vnode_isdir(tvp)) { 4174 /* 4175 * From the man 2 rename 4176 * 4177 * CONFORMANCE 4178 * The restriction on renaming a directory whose permissions disallow 4179 * writing is based on the fact that UFS directories contain a ".." 4180 * entry. If renaming a directory would move it to another parent 4181 * directory, this entry needs to be changed. 4182 * 4183 * This restriction has been generalized to disallow renaming of any 4184 * write-disabled directory, even when this would not require a 4185 * change to the ".." entry. For consistency, HFS+ directories 4186 * emulate this behavior. 4187 * 4188 * So if you are renaming a dir to an existing dir, you must have 4189 * write access on the existing dir. Seems if the user is a super 4190 * user then we can delete the existing directory. 4191 * 4192 * XXX - We need to remove the smb_check_posix_access and just do a 4193 * vnop_access. 4194 */ 4195 if (share->ss_attributes & FILE_PERSISTENT_ACLS) 4196 error = smbfs_rmdir(share, tdvp, tvp, tcnp, ap->a_context); 4197 else if ((vfs_context_suser(ap->a_context) == 0) || 4198 (smb_check_posix_access(ap->a_context, VTOSMB(tvp), S_IWOTH))) 4199 error = smbfs_rmdir(share, tdvp, tvp, tcnp, ap->a_context); 4200 else 4201 error = EPERM; 4202 } else { 4203 error = smbfs_remove(share, tdvp, tvp, tcnp, 0, ap->a_context); 4204 } 4205 if (error) 4206 goto out; 4207 } 4208 4209 cache_purge(fvp); 4210 4211 /* Did we open this in our read routine. Then we should close it. */ 4212 if ((!vnode_isdir(fvp)) && (!vnode_isinuse(fvp, 0)) && 4213 (fnp->f_refcnt == 1) && fnp->f_needClose) { 4214 error = smbfs_close(share, fvp, FREAD, ap->a_context); 4215 if (error) 4216 SMBWARNING("error %d closing %s\n", error, fnp->n_name); 4217 } 4218 4219 /* 4220 * Windows Servers will not let you move a item that contains open items. So 4221 * if we are moving an folder and the source folder has an open notification 4222 * then close the notification, before doing the move. 4223 */ 4224 if (vnode_isdir(fvp) && 4225 (fnp->d_fid != 0)) { 4226 (void)smbfs_tmpclose(share, fnp, fnp->d_fid, ap->a_context); 4227 /* Mark it to be reopen */ 4228 fnp->d_needReopen = TRUE; 4229 fnp->d_fid = 0; 4230 } 4231 4232 /* 4233 * Try to rename the file, this may fail if the file is open. Some 4234 * SAMBA systems allow us to rename an open file, so try this case 4235 * first. 4236 * 4237 * FYI: While working on Radar 4532498 I notice that you can move/rename 4238 * an open file if it is open for read-only. Only tested this on Windows 2003. 4239 */ 4240 error = smbfs_smb_rename(share, fnp, tdnp, tcnp->cn_nameptr, 4241 tcnp->cn_namelen, ap->a_context); 4242 /* 4243 * The file could be open so lets try again. This call does not work on 4244 * Windows 95/98/Me/NT4 systems. Since this call only allows you to 4245 * rename in place do not even try it if they are moving the item. 4246 */ 4247 if ( (fdvp == tdvp) && error && 4248 (VC_CAPS(SSTOVC(share)) & SMB_CAP_INFOLEVEL_PASSTHRU)) 4249 error = smbfs_smb_t2rename(share, fnp, tcnp->cn_nameptr, 4250 tcnp->cn_namelen, 1, NULL, ap->a_context); 4251 4252 /* 4253 * We should really print a better description of the error to the 4254 * system log. Thing we could print in the system log. 4255 * 1. This server does not support renaming of an open file. 4256 * 2. This server only supports renaming of an open file in place. 4257 * 3. Renaming open file failed. 4258 * 4259 * Written up as Radar 4381236 4260 */ 4261 if (!error) { 4262 char *new_name; 4263 uint64_t hashval; 4264 uint32_t orig_flag = fnp->n_flag; 4265 4266 /* 4267 * At this point we still have both parents and the children locked if 4268 * they exist. Since the parents are locked we know that a lookup of the 4269 * children cannot happen over the network. So we are safe to play with 4270 * both names and the hash node entries. The old code would just remove 4271 * the node from the hash table and then just change the nodes name, this 4272 * was very bad and could cause the following to happen: 4273 * 4274 * RENAME HAPPENS ON VP1: vp1->np1->n_name = file1 gets renamed to vp1->np1->n_name = file2 4275 * 1. vp1 is no longer in the name cache. 4276 * 2. np1 is no longer in the hash table. 4277 * 3. vp1 still has a ref taken on it and can still be used. 4278 * 4279 * LOOKUP HAPPNES ON file2: Which will cause a new vnode and smbnode to get created 4280 * 1. vp1 is not found because its not in the name cache. 4281 * 2. np1 is not found because its not in the hash table. 4282 * 3. vp2 and np2 get created and vp2->np2->n_name = file2 4283 * 4284 * RENAME HAPPENS ON VP2: vp2->np2->n_name = file2 gets renamed to vp2->np2->n_name = file3 4285 * 1. vp1 no longer has the correct name. 4286 * 2. vp2 is no longer in the name cache. 4287 * 3. np2 is no longer in the hash table. 4288 * 4. vp2 still has a ref taken on it and can still be used. 4289 * 4290 * SOME OTHER OPERATION HAPPENS ON VP1: It will fail because VP1 now has the wrong name. 4291 * 1. Now the whole thing can repeat, very bad! 4292 */ 4293 4294 if (!(SSTOVC(share)->vc_misc_flags & SMBV_HAS_FILEIDS)) { 4295 /* 4296 * Server does not support File IDs. 4297 * Remove it from the hash, it doesn't exist under that name 4298 * anymore 4299 */ 4300 smb_vhashrem(fnp); 4301 } 4302 4303 /* We always need the following code. */ 4304 if (tdvp && (fdvp != tdvp)) { 4305 /* Take a ref count on the new parent */ 4306 if (!vnode_isvroot(tdvp)) { 4307 if (vnode_get(tdvp) == 0) { 4308 if (vnode_ref(tdvp) == 0) { 4309 fnp->n_flag |= NREFPARENT; 4310 4311 /* Increment new parent node's child refcnt */ 4312 OSIncrementAtomic(&tdnp->n_child_refcnt); 4313 } 4314 else { 4315 fnp->n_flag &= ~NREFPARENT; 4316 } 4317 vnode_put(tdvp); 4318 } 4319 } 4320 else 4321 fnp->n_flag &= ~NREFPARENT; 4322 /* Remove the ref count off the old parent */ 4323 if ((!vnode_isvroot(fdvp)) && (orig_flag & NREFPARENT)) { 4324 if (vnode_get(fdvp) == 0) { 4325 vnode_rele(fdvp); 4326 vnode_put(fdvp); 4327 4328 /* Remove the child refcnt from old parent */ 4329 OSDecrementAtomic(&fdnp->n_child_refcnt); 4330 } 4331 } 4332 4333 fnp->n_parent = VTOSMB(tdvp); 4334 4335 VTOSMB(tdvp)->d_changecnt++; 4336 VTOSMB(fdvp)->d_changecnt++; 4337 } 4338 4339 /* 4340 * Now reset the name so path lookups will work and add the node back 4341 * into the hash table, so other lookups can this node. 4342 */ 4343 new_name = smb_strndup(tcnp->cn_nameptr, tcnp->cn_namelen); 4344 if (new_name) { 4345 char * old_name = fnp->n_name; 4346 lck_rw_lock_exclusive(&fnp->n_name_rwlock); 4347 fnp->n_name = new_name; 4348 fnp->n_nmlen = tcnp->cn_namelen; 4349 lck_rw_unlock_exclusive(&fnp->n_name_rwlock); 4350 4351 if (!(SSTOVC(share)->vc_misc_flags & SMBV_HAS_FILEIDS)) { 4352 /* Server does not support File IDs */ 4353 hashval = smbfs_hash(NULL, 0, fnp->n_name, fnp->n_nmlen); 4354 smb_vhashadd(fnp, hashval); 4355 } 4356 4357 /* Now its safe to free the old name */ 4358 SMB_FREE(old_name, M_SMBNODENAME); 4359 } 4360 4361 if (!(SSTOVC(share)->vc_misc_flags & SMBV_HAS_FILEIDS)) { 4362 /* 4363 * Servers does not support File IDs 4364 * <10854595> Update the n_ino with the new name and/or parent 4365 */ 4366 fnp->n_ino = smbfs_getino(fnp->n_parent, fnp->n_name, fnp->n_nmlen); 4367 } 4368 4369 /* Update time stamp of when we last did rename */ 4370 nanouptime(&fnp->n_rename_time); 4371 } 4372 4373 /* 4374 * Source Target 4375 * Dot Hidden Dot HIDE 4376 * Dot Unhidden Dot HIDE! (Puma recovery) 4377 * NoDot Hidden Dot HIDE (Win hid it) 4378 * NoDot Unhidden Dot HIDE 4379 * Dot Hidden NoDot UNHIDE 4380 * Dot Unhidden NoDot UNHIDE 4381 * NoDot Hidden NoDot HIDE! (Win hid it) 4382 * NoDot Unhidden NoDot UNHIDE 4383 */ 4384 if (!error) { 4385 int hiderr; 4386 Boolean hideItem = (tcnp->cn_nameptr[0] == '.'); 4387 Boolean unHideItem = ((tcnp->cn_nameptr[0] != '.') && 4388 (fcnp->cn_nameptr[0] == '.')); 4389 4390 if (hideItem || unHideItem) { 4391 hiderr = smbfs_set_hidden_bit(share, tdnp, tcnp->cn_nameptr, 4392 tcnp->cn_namelen, hideItem, 4393 ap->a_context); 4394 if (hiderr) { 4395 SMBWARNING("Error %d %s %s\n", hiderr, (hideItem) ? "hiding" : 4396 "unhiding", tcnp->cn_nameptr); 4397 } 4398 } 4399 } 4400 4401 if (error == EBUSY) { 4402 char errbuf[32]; 4403 4404 proc_name(proc_pid(p), &errbuf[0], 32); 4405 SMBERROR("warning: pid %d(%.*s) rename open file(%s)\n", proc_pid(p), 4406 32, &errbuf[0], fnp->n_name); 4407 } 4408 smbfs_attr_touchdir(fdnp, (share->ss_fstype == SMB_FS_FAT)); 4409 if (tdvp != fdvp) 4410 smbfs_attr_touchdir(tdnp, (share->ss_fstype == SMB_FS_FAT)); 4411 /* if success, blow away statfs cache */ 4412 if (!error) { 4413 smp->sm_statfstime = 0; 4414 4415 /* Invalidate negative cache entries in destination dir */ 4416 if (tdnp->n_flag & NNEGNCENTRIES) { 4417 tdnp->n_flag &= ~NNEGNCENTRIES; 4418 cache_purge_negatives(tdvp); 4419 } 4420 } 4421 4422out: 4423 /* We only have a share if we obtain a reference on it, so release it */ 4424 if (share) { 4425 smb_share_rele(share, ap->a_context); 4426 } 4427 if (error == EBUSY) { 4428 char errbuf[32]; 4429 4430 proc_name(proc_pid(p), &errbuf[0], 32); 4431 SMBWARNING("warning: pid %d(%.*s) rename open file(%s)\n", proc_pid(p), 32, &errbuf[0], fnp->n_name); 4432 } 4433 for (ii=0; ii<lock_cnt; ii++) 4434 if (lock_order[ii]) 4435 smbnode_unlock(lock_order[ii]); 4436 4437 return (error); 4438} 4439 4440/* 4441 * smbfs_vnop_link 4442 * 4443 * vnode_t a_vp; 4444 * vnode_t a_tdvp; 4445 * struct componentname *a_cnp; 4446 * vfs_context_t a_context; 4447 * 4448 * someday this will come true... 4449 */ 4450static int 4451smbfs_vnop_link(struct vnop_link_args *ap) 4452{ 4453 proc_t p = vfs_context_proc(ap->a_context); 4454 struct smbnode *np = VTOSMB(ap->a_vp); 4455 char errbuf[32]; 4456 4457 proc_name(proc_pid(p), &errbuf[0], 32); 4458 SMBERROR("warning: pid %d(%.*s) hardlink(%s)\n", proc_pid(p), 32, &errbuf[0], np->n_name); 4459 return (err_link(ap)); 4460} 4461 4462/* 4463 * smbfs_vnop_symlink link create call. 4464 * 4465 * vnode_t a_dvp; 4466 * vnode_t *a_vpp; 4467 * struct componentname *a_cnp; 4468 * struct vnode_attr *a_vap; 4469 * char *a_target; 4470 * vfs_context_t a_context; 4471 */ 4472static int smbfs_vnop_symlink(struct vnop_symlink_args *ap) 4473{ 4474 int error; 4475 struct vnop_create_args a; 4476 vnode_t dvp = ap->a_dvp; 4477 struct smbnode *dnp; 4478 struct smb_share *share; 4479 4480 /* Make sure we lock the parent before calling smbfs_create */ 4481 if ((error = smbnode_lock(VTOSMB(dvp), SMBFS_EXCLUSIVE_LOCK))) 4482 return error; 4483 4484 dnp = VTOSMB(dvp); 4485 dnp->n_lastvop = smbfs_vnop_symlink; 4486 a.a_dvp = dvp; 4487 a.a_vpp = ap->a_vpp; 4488 a.a_cnp = ap->a_cnp; 4489 a.a_vap = ap->a_vap; 4490 a.a_context = ap->a_context; 4491 /* 4492 * We use PATH_MAX because we have no way currently to find out what is the 4493 * max path on the server. 4494 */ 4495 share = smb_get_share_with_reference(VTOSMBFS(dvp)); 4496 4497 error = smbfs_create(share, &a, ap->a_target, strnlen(ap->a_target, PATH_MAX+1)); 4498 4499 smb_share_rele(share, ap->a_context); 4500 smbnode_unlock(dnp); 4501 return (error); 4502} 4503 4504/* 4505 * smbfs_vnop_readlink read symlink call. 4506 * 4507 * vnode_t *a_vpp; 4508 * struct componentname *a_cnp; 4509 * uio_t a_uio; 4510 * vfs_context_t a_context; 4511 */ 4512static int 4513smbfs_vnop_readlink(struct vnop_readlink_args *ap) 4514{ 4515 vnode_t vp = ap->a_vp; 4516 struct smbnode *np = NULL; 4517 int error; 4518 struct smb_share *share; 4519 time_t symlinktimeo; 4520 struct timespec ts; 4521 4522 if (vnode_vtype(vp) != VLNK) 4523 return (EINVAL); 4524 4525 if ((error = smbnode_lock(VTOSMB(vp), SMBFS_EXCLUSIVE_LOCK))) 4526 return (error); 4527 4528 np = VTOSMB(vp); 4529 np->n_lastvop = smbfs_vnop_readlink; 4530 share = smb_get_share_with_reference(VTOSMBFS(vp)); 4531 SMB_CACHE_TIME(ts, np, symlinktimeo); 4532 4533 if ((np->n_symlink_target) && ((share->ss_flags & SMBS_RECONNECTING) || 4534 (symlinktimeo > (ts.tv_sec - np->n_symlink_cache_timer)))) { 4535 error = uiomove(np->n_symlink_target, (int)np->n_symlink_target_len, ap->a_uio); 4536 } else if ((np->n_dosattr & SMB_EFA_REPARSE_POINT) && 4537 (np->n_reparse_tag == IO_REPARSE_TAG_SYMLINK)) { 4538 error = smbfs_smb_reparse_read_symlink(share, np, ap->a_uio, ap->a_context); 4539 } else if (np->n_flag & NWINDOWSYMLNK) { 4540 error = smbfs_smb_windows_read_symlink(share, np, ap->a_uio, ap->a_context); 4541 } else { 4542 error = smbfs_smb_unix_read_symlink(share, np, ap->a_uio, ap->a_context); 4543 } 4544 smb_share_rele(share, ap->a_context); 4545 smbnode_unlock(np); 4546 return (error); 4547} 4548 4549/* 4550 * smbfs_vnop_mknod 4551 * 4552 * vnode_t a_dvp; 4553 * vnode_t *a_vpp; 4554 * struct componentname *a_cnp; 4555 * struct vnode_attr *a_vap; 4556 * vfs_context_t a_context; 4557 */ 4558static int 4559smbfs_vnop_mknod(struct vnop_mknod_args *ap) 4560{ 4561 proc_t p = vfs_context_proc(ap->a_context); 4562 char errbuf[32]; 4563 4564 proc_name(proc_pid(p), &errbuf[0], 32); 4565 SMBERROR("warning: pid %d(%.*s) mknod(%s)\n", proc_pid(p), 32, &errbuf[0], 4566 ap->a_cnp->cn_nameptr); 4567 return (err_mknod(ap)); 4568} 4569 4570/* 4571 * smbfs_vnop_mkdir 4572 * 4573 * vnode_t a_dvp; 4574 * vnode_t *a_vpp; 4575 * struct componentname *a_cnp; 4576 * struct vnode_attr *a_vap; 4577 * vfs_context_t a_context; 4578 */ 4579static int 4580smbfs_vnop_mkdir(struct vnop_mkdir_args *ap) 4581{ 4582 vnode_t dvp = ap->a_dvp; 4583 struct vnode_attr *vap = ap->a_vap; 4584 vnode_t vp; 4585 struct componentname *cnp = ap->a_cnp; 4586 struct smbnode *dnp = NULL; 4587 struct smbmount *smp = NULL; 4588 struct smbfattr fattr; 4589 const char *name = cnp->cn_nameptr; 4590 size_t len = cnp->cn_namelen; 4591 int error; 4592 struct smb_share *share; 4593 struct timespec ts; 4594 4595 if (name[0] == '.' && (len == 1 || (len == 2 && name[1] == '.'))) 4596 return (EEXIST); 4597 4598 if ((error = smbnode_lock(VTOSMB(dvp), SMBFS_EXCLUSIVE_LOCK))) 4599 return (error); 4600 dnp = VTOSMB(dvp); 4601 dnp->n_lastvop = smbfs_vnop_mkdir; 4602 smp = dnp->n_mount; 4603 share = smb_get_share_with_reference(smp); 4604 error = smbfs_smb_mkdir(share, dnp, name, len, &fattr, ap->a_context); 4605 if (error) 4606 goto exit; 4607 4608 smbfs_attr_touchdir(dnp, (share->ss_fstype == SMB_FS_FAT)); 4609 dnp->d_changecnt++; 4610 4611 /* 4612 * %%% 4613 * Would really like to clean this code up in the future. The whole create, 4614 * mkdir and smblink create code should use the same code path. 4615 */ 4616 error = smbfs_nget(share, vnode_mount(dvp), 4617 dvp, name, len, 4618 &fattr, &vp, 4619 cnp->cn_flags, SMBFS_NGET_CREATE_VNODE, 4620 ap->a_context); 4621 if (error) 4622 goto bad; 4623 4624 /* 4625 * We just create the directory, so we have no finder info. So set our cache 4626 * timer to reflect this information 4627 */ 4628 nanouptime(&ts); 4629 VTOSMB(vp)->finfo_cache = ts.tv_sec; 4630 smbfs_set_create_vap(share, vap, vp, ap->a_context, FALSE); 4631 *ap->a_vpp = vp; 4632 smbnode_unlock(VTOSMB(vp)); /* Done with the smbnode unlock it. */ 4633 error = 0; 4634 if (dnp->n_flag & NNEGNCENTRIES) { 4635 dnp->n_flag &= ~NNEGNCENTRIES; 4636 cache_purge_negatives(dvp); 4637 } 4638 4639bad: 4640 if (name != cnp->cn_nameptr) { 4641 SMB_FREE(name, M_SMBNODENAME); 4642 } 4643 /* if success, blow away statfs cache */ 4644 smp->sm_statfstime = 0; 4645exit: 4646 smb_share_rele(share, ap->a_context); 4647 smbnode_unlock(dnp); 4648 return (error); 4649} 4650 4651/* 4652 * smbfs_vnop_readdir 4653 * 4654 * vnode_t a_vp; 4655 * struct uio *a_uio; 4656 * int a_flags; 4657 * int *a_eofflag; 4658 * int *a_numdirent; 4659 * vfs_context_t a_context; 4660 */ 4661static int 4662smbfs_vnop_readdir(struct vnop_readdir_args *ap) 4663{ 4664 vnode_t vp = ap->a_vp; 4665 uio_t uio = ap->a_uio; 4666 int error; 4667 int32_t numdirent = 0; 4668 4669 if (uio_offset(uio) < 0) 4670 return (EINVAL); 4671 4672 if (!vnode_isdir(vp)) 4673 return (EPERM); 4674 4675 if (ap->a_eofflag) 4676 *ap->a_eofflag = 0; 4677 4678 if (uio_resid(uio) == 0) 4679 return (0); 4680 4681 if ((error = smbnode_lock(VTOSMB(vp), SMBFS_EXCLUSIVE_LOCK))) 4682 return (error); 4683 VTOSMB(vp)->n_lastvop = smbfs_vnop_readdir; 4684 4685 error = smbfs_readvdir(vp, uio, ap->a_context, ap->a_flags, &numdirent); 4686 if (error == ENOENT) { 4687 /* We have reached the end of the search */ 4688 if (ap->a_eofflag) 4689 *ap->a_eofflag = 1; 4690 error = 0; 4691 } 4692 /* Return the number of entries from this lookup */ 4693 if (ap->a_numdirent) 4694 *ap->a_numdirent = numdirent; 4695 smbnode_unlock(VTOSMB(vp)); 4696 return (error); 4697} 4698 4699int32_t 4700smbfs_fsync(struct smb_share *share, vnode_t vp, int waitfor, int ubc_flags, 4701 vfs_context_t context) 4702{ 4703#pragma unused(waitfor, ubc_flags) 4704 int error; 4705 off_t size; 4706 4707 if (!vnode_isreg(vp)) { 4708 return 0; /* Nothing to do here */ 4709 } 4710 size = smb_ubc_getsize(vp); 4711 if ((size > 0) && smbfsIsCacheable(vp)) { 4712 if (VTOSMB(vp)->n_flag & NISMAPPED) { 4713 /* More expensive, but handles mmapped files */ 4714 ubc_msync (vp, 0, ubc_getsize(vp), NULL, UBC_PUSHDIRTY | UBC_SYNC); 4715 } else { 4716 /* Less expensive, but does not handle mmapped files */ 4717 cluster_push(vp, IO_SYNC); 4718 } 4719 } 4720 error = smbfs_smb_fsync(share, VTOSMB(vp), context); 4721 if (!error) 4722 VTOSMBFS(vp)->sm_statfstime = 0; 4723 return (error); 4724} 4725 4726/* smbfs_vnop_fsync 4727 * 4728 * vnode_t a_vp; 4729 * int32_t a_waitfor; 4730 * vfs_context_t a_context; 4731 */ 4732static int32_t 4733smbfs_vnop_fsync(struct vnop_fsync_args *ap) 4734{ 4735 int32_t error; 4736 struct smb_share *share; 4737 4738 /* If this is a read-only mount, there is nothing to do here */ 4739 if (vfs_isrdonly(vnode_mount(ap->a_vp))) { 4740 return (0); 4741 } 4742 4743 error = smbnode_lock(VTOSMB(ap->a_vp), SMBFS_EXCLUSIVE_LOCK); 4744 if (error) 4745 return (0); 4746 VTOSMB(ap->a_vp)->n_lastvop = smbfs_vnop_fsync; 4747 share = smb_get_share_with_reference(VTOSMBFS(ap->a_vp)); 4748 error = smbfs_fsync(share, ap->a_vp, ap->a_waitfor, 0, ap->a_context); 4749 smb_share_rele(share, ap->a_context); 4750 smbnode_unlock(VTOSMB(ap->a_vp)); 4751 return (error); 4752} 4753 4754/* 4755 * smbfs_vnop_pathconf 4756 * 4757 * vnode_t a_vp; 4758 * int a_name; 4759 * int32_t *a_retval; 4760 * vfs_context_t a_context; 4761 */ 4762static int smbfs_vnop_pathconf(struct vnop_pathconf_args *ap) 4763{ 4764 struct smb_share *share; 4765 int32_t *retval = ap->a_retval; 4766 int error = 0; 4767 4768 share = smb_get_share_with_reference(VTOSMBFS(ap->a_vp)); 4769 switch (ap->a_name) { 4770 case _PC_LINK_MAX: /* Hard Link Support */ 4771 *retval = 0; /* May support in the future. Depends on the server */ 4772 break; 4773 case _PC_NAME_MAX: 4774 *retval = share->ss_maxfilenamelen; 4775 break; 4776 case _PC_PATH_MAX: 4777 /* 4778 * XXX 4779 * Most Windows system have a 255 limit, but you can configure 4780 * them to support 1024. It would be nice if we could figure out 4781 * the real value for this field. 4782 */ 4783 *retval = PATH_MAX; 4784 break; 4785 case _PC_CHOWN_RESTRICTED: 4786 *retval = 1; 4787 break; 4788 case _PC_NO_TRUNC: 4789 *retval = 0; 4790 break; 4791 case _PC_NAME_CHARS_MAX: 4792 *retval = share->ss_maxfilenamelen; 4793 break; 4794 case _PC_CASE_SENSITIVE: 4795 *retval = 0; 4796 4797 if (SSTOVC(share)->vc_misc_flags & SMBV_OSX_SERVER) { 4798 /* Its OS X Server so we know for sure */ 4799 if (SSTOVC(share)->vc_volume_caps & kAAPL_CASE_SENSITIVE) { 4800 SMBDEBUG("Volume is case sensitive\n"); 4801 *retval = 1; 4802 } 4803 } 4804 else { 4805 /* 4806 * Thought about using FILE_CASE_SENSITIVE_SEARCH, but this 4807 * really just means they will search by case. It does not mean 4808 * this is a case sensitive file system. Currently we have no 4809 * way of determining if this is a case sensitive or 4810 * insensitive file system. We need to return a consistent 4811 * answer between pathconf and vfs_getattr. We do not know the real 4812 * answer for case sensitive, but lets default to what 90% of the 4813 * servers have set. Also remember this fixes Radar 4057391 and 3530751. 4814 */ 4815 *retval = 0; 4816 } 4817 break; 4818 case _PC_CASE_PRESERVING: 4819 if (share->ss_attributes & FILE_CASE_PRESERVED_NAMES) 4820 *retval = 1; 4821 else *retval = 0; 4822 break; 4823 /* 4824 * Handle by vn_pathconf. 4825 * 4826 * case _PC_EXTENDED_SECURITY_NP: 4827 * *retval = vfs_extendedsecurity(vnode_mount(vp)) ? 1 : 0; 4828 * break; 4829 * case _PC_AUTH_OPAQUE_NP: 4830 * *retval = vfs_authopaque(vnode_mount(vp)); 4831 * break; 4832 * case _PC_2_SYMLINKS: 4833 * *retval = 1; 4834 * break; 4835 * case _PC_ALLOC_SIZE_MIN: 4836 * *retval = 1; // XXX lie: 1 byte 4837 * break; 4838 * case _PC_ASYNC_IO: // unistd.h: _POSIX_ASYNCHRONUS_IO 4839 * *retval = 1; // [AIO] option is supported 4840 * break; 4841 */ 4842 case _PC_FILESIZEBITS: 4843 if (VC_CAPS(SSTOVC(share)) & SMB_CAP_LARGE_FILES) 4844 *retval = 64; /* The server supports 64 bit offsets */ 4845 else *retval = 32; /* The server supports 32 bit offsets */ 4846 break; 4847 case _PC_XATTR_SIZE_BITS: 4848 if (!(share->ss_attributes & FILE_NAMED_STREAMS)) { 4849 /* Doesn't support named streams VFS handles this cases */ 4850 error = EINVAL; 4851 } else if (VC_CAPS(SSTOVC(share)) & SMB_CAP_LARGE_FILES) { 4852 *retval = 64; /* The server supports 64 bit offsets */ 4853 } else { 4854 *retval = 32; /* The server supports 32 bit offsets */ 4855 } 4856 break; 4857 /* 4858 * Handle by vn_pathconf. 4859 * 4860 * case _PC_PRIO_IO: // unistd.h: _POSIX_PRIORITIZED_IO 4861 * *retval = 0; // [PIO] option is not supported 4862 * break; 4863 * case _PC_REC_INCR_XFER_SIZE: 4864 * *retval = 4096; // XXX go from MIN to MAX 4K at a time 4865 * break; 4866 * case _PC_REC_MIN_XFER_SIZE: 4867 * *retval = 4096; // XXX recommend 4K minimum reads/writes 4868 * break; 4869 * case _PC_REC_MAX_XFER_SIZE: // Should we use SMB_IOMAX 4870 * *retval = 65536; // XXX recommend 64K maximum reads/writes 4871 * break; 4872 * case _PC_REC_XFER_ALIGN: 4873 * *retval = 4096; // XXX recommend page aligned buffers 4874 * break; 4875 * case _PC_SYMLINK_MAX: 4876 * *retval = 255; // Minimum acceptable POSIX value 4877 * break; 4878 * case _PC_SYNC_IO: // unistd.h: _POSIX_SYNCHRONIZED_IO 4879 * *retval = 0; // [SIO] option is not supported 4880 * break; 4881 */ 4882 default: 4883 error = EINVAL; 4884 } 4885 smb_share_rele(share, ap->a_context); 4886 return (error); 4887} 4888 4889/* 4890 * smbfs_vnop_ioctl - smbfs vnodeop entry point 4891 * vnode_t a_vp; 4892 * int32_t a_command; 4893 * caddr_t a_data; 4894 * int32_t a_fflag; 4895 * vfs_context_t context; 4896 */ 4897static int32_t smbfs_vnop_ioctl(struct vnop_ioctl_args *ap) 4898{ 4899 vnode_t vp = ap->a_vp; 4900 struct smbnode *np; 4901 int32_t error = 0; 4902 proc_t p = vfs_context_proc(ap->a_context); 4903 struct smb_share *share; 4904 struct smbmount *smp; 4905 4906 error = smbnode_lock(VTOSMB(ap->a_vp), SMBFS_EXCLUSIVE_LOCK); 4907 if (error) 4908 return (error); 4909 4910 np = VTOSMB(vp); 4911 np->n_lastvop = smbfs_vnop_ioctl; 4912 smp = VTOSMBFS(vp); 4913 share = smb_get_share_with_reference(VTOSMBFS(vp)); 4914 4915 /* 4916 * %%% 4917 * Remove the IOCBASECMD case lines (OLD) when fsctl code in vfs_syscalls.c 4918 * gets fixed to not use IOCBASECMD before calling VOP_IOCTL. 4919 * 4920 * The smbfsByteRangeLock2FSCTL call was made to support classic. We do 4921 * not support classic, but the file manager will only make the 4922 * smbfsByteRangeLock2FSCTL call. So for now support all the commands, but 4923 * treat them all the same. 4924 */ 4925 switch (ap->a_command) { 4926 case smbfsGetVCSockaddrFSCTL: 4927 case smbfsGetVCSockaddrFSCTL_BASECMD: { 4928 4929 if (SSTOVC(share)->vc_saddr) { 4930 memcpy(ap->a_data, SSTOVC(share)->vc_saddr, 4931 SSTOVC(share)->vc_saddr->sa_len); 4932 } else { 4933 error = EINVAL; /* Better never happen, but just in case */ 4934 } 4935 break; 4936 } 4937 case smbfsUniqueShareIDFSCTL: 4938 case smbfsUniqueShareIDFSCTL_BASECMD: { 4939 struct UniqueSMBShareID *uniqueptr = (struct UniqueSMBShareID *)ap->a_data; 4940 4941 uniqueptr->error = 0; 4942 if ((uniqueptr->flags & SMBFS_GET_ACCESS_INFO) || 4943 ((uniqueptr->unique_id_len == smp->sm_args.unique_id_len) && 4944 (bcmp(smp->sm_args.unique_id, uniqueptr->unique_id, 4945 uniqueptr->unique_id_len) == 0))) { 4946 4947 /* In the future we should return the lsa name if we have one */ 4948 uniqueptr->user[0] = 0; /* Just in case we have no user name */ 4949 if (SSTOVC(share)->vc_flags & SMBV_GUEST_ACCESS) { 4950 uniqueptr->connection_type = kConnectedByGuest; 4951 strlcpy(uniqueptr->user, kGuestAccountName, SMB_MAXUSERNAMELEN + 1); 4952 } 4953 else if (SSTOVC(share)->vc_username) { 4954 uniqueptr->connection_type = kConnectedByUser; 4955 strlcpy(uniqueptr->user, SSTOVC(share)->vc_username, SMB_MAXUSERNAMELEN + 1); 4956 } else { 4957 uniqueptr->connection_type = kConnectedByKerberos; 4958 } 4959 uniqueptr->error = EEXIST; 4960 } 4961 } 4962 break; 4963 case smbfsByteRangeLock2FSCTL: 4964 case smbfsByteRangeLock2FSCTL_BASECMD: 4965 case smbfsByteRangeLockFSCTL: 4966 case smbfsByteRangeLockFSCTL_BASECMD: { 4967 struct ByteRangeLockPB *pb = (struct ByteRangeLockPB *) ap->a_data; 4968 struct ByteRangeLockPB2 *pb2 = (struct ByteRangeLockPB2 *) ap->a_data; 4969 uint32_t lck_pid; 4970 uint32_t timo; 4971 SMBFID fid = 0; 4972 struct fileRefEntry *fndEntry = NULL; 4973 uint16_t accessMode = 0; 4974 int8_t flags; 4975 struct smbfattr *fap = NULL; 4976 struct smb2_durable_handle dur_handle, *dptr; 4977 int do_create; 4978 uint32_t disp; 4979 4980 /* make sure its a file */ 4981 if (vnode_isdir(vp)) { 4982 error = EISDIR; 4983 goto exit; 4984 } 4985 4986 /* Before trying the lock see if the file needs to be reopened */ 4987 error = smbfs_smb_reopen_file(share, np, ap->a_context); 4988 if (error) { 4989 SMBDEBUG(" %s waiting to be revoked\n", np->n_name); 4990 goto exit; 4991 } 4992 4993 /* 4994 * If adding/removing a ByteRangeLock, thus this vnode should NEVER 4995 * be cacheable since the page in/out may overlap a lock and get 4996 * an error. 4997 */ 4998 if (smbfsIsCacheable(vp)) { 4999 if (np->n_flag & NISMAPPED) { 5000 /* More expensive, but handles mmapped files */ 5001 ubc_msync (vp, 0, ubc_getsize(vp), NULL, UBC_PUSHDIRTY | UBC_SYNC); 5002 } else { 5003 /* Less expensive, but does not handle mmapped files */ 5004 cluster_push(vp, IO_SYNC); 5005 } 5006 ubc_msync (vp, 0, ubc_getsize(vp), NULL, UBC_INVALIDATE); 5007 vnode_setnocache(vp); 5008 } 5009 5010 accessMode = np->f_accessMode; 5011 5012 /* 5013 * Since we never get a smbfsByteRangeLockFSCTL call we could skip this 5014 * check, but for now leave it. 5015 */ 5016 if ( (ap->a_command == smbfsByteRangeLock2FSCTL) || 5017 (ap->a_command == smbfsByteRangeLock2FSCTL_BASECMD) ) { 5018 int32_t openMode = 0; 5019 5020 /* 5021 * Not just for classic any more, could get this from Carbon. 5022 * 5023 * They will be using an extended BRL call that also passes in the 5024 * open mode used that was used to open the file. I will use the 5025 * open access mode and pid to find the fork ref to do the lock on. 5026 * Scenarios: 5027 * Open (R/W), BRL, Close (R/W) 5028 * Open (R/W/dW), BRL, Close (R/W/dW) 5029 * Open1 (R/W), Open2 (R), BRL1, BRL2, Close1 (R/W), Close2 (R) 5030 * Open1 (R/W/dW), Open2 (R), BRL1, BRL2, Close1 (R/W/dW), Close2 (R) 5031 * Open1 (R/dW), Open2 (R/dW), BRL1, BRL2, Close1 (R/dW), Close2 (R/dW) 5032 */ 5033 if ( (error = file_flags(pb2->fd, &openMode)) ) { 5034 goto exit; 5035 } 5036 5037 if (openMode & FREAD) { 5038 accessMode |= kAccessRead; 5039 } 5040 if (openMode & FWRITE) { 5041 accessMode |= kAccessWrite; 5042 } 5043 5044 /* 5045 * See if we can find a matching fork that has byte range locks or 5046 * denyModes 5047 */ 5048 if (openMode & FHASLOCK) { 5049 /* 5050 * NOTE: FHASLOCK can be set by open with O_EXCLUSIVE or 5051 * O_SHARED which maps to my deny modes or FHASLOCK could also 5052 * have been set/cleared by calling flock directly. I assume 5053 * that if they are using byte range locks, then they are Carbon 5054 * and unlikely to be using flock. 5055 * 5056 * Assume it was opened with denyRead/denyWrite or just denyWrite. 5057 * Try denyWrite first, if not found, try with denyRead and denyWrite 5058 */ 5059 accessMode |= kDenyWrite; 5060 error = FindFileRef(vp, p, accessMode, kExactMatch, 0, 0, 5061 &fndEntry, &fid); 5062 if (error != 0) { 5063 accessMode |= kDenyRead; 5064 error = FindFileRef(vp, p, accessMode, kExactMatch, 0, 0, 5065 &fndEntry, &fid); 5066 } 5067 if (error != 0) { 5068 /* deny modes were used, but the fork ref cant be found, return error */ 5069 error = EBADF; 5070 goto exit; 5071 } 5072 } 5073 else { 5074 /* no deny modes used, look for any forks opened previously for BRL */ 5075 error = FindFileRef(vp, p, accessMode, kExactMatch, 0, 0, 5076 &fndEntry, &fid); 5077 } 5078 } else { 5079 error = FindFileRef(vp, p, kAccessRead | kAccessWrite, kAnyMatch, 5080 0, 0, &fndEntry, &fid); 5081 } 5082 /* 5083 * The process was not found or no list found 5084 * Either case, we need to 5085 * 1) Open a new fork 5086 * 2) create a new OpenForkRefEntry entry and add it into the list 5087 */ 5088 if (error) { 5089 uint32_t rights = 0; 5090 uint32_t shareMode = NTCREATEX_SHARE_ACCESS_ALL; 5091 proc_t p = vfs_context_proc(ap->a_context); 5092 5093 /* This is wrong, someone has to call open() before doing a byterange lock */ 5094 if (np->f_refcnt <= 0) { 5095 error = EBADF; 5096 goto exit; 5097 } 5098 5099 /* We must find a matching lock in order to succeed at unlock */ 5100 if (pb->unLockFlag == 1) { 5101 error = EINVAL; 5102 goto exit; 5103 } 5104 5105 /* Need to open the file here */ 5106 if (accessMode & kAccessRead) 5107 rights |= SMB2_FILE_READ_DATA; 5108 if (accessMode & kAccessWrite) 5109 rights |= SMB2_FILE_APPEND_DATA | SMB2_FILE_WRITE_DATA; 5110 5111 if (accessMode & kDenyWrite) 5112 shareMode &= ~NTCREATEX_SHARE_ACCESS_WRITE; /* Remove the wr shared access */ 5113 if (accessMode & kDenyRead) 5114 shareMode &= ~NTCREATEX_SHARE_ACCESS_READ; /* Remove the wr shared access */ 5115 5116 SMB_MALLOC(fap, 5117 struct smbfattr *, 5118 sizeof(struct smbfattr), 5119 M_SMBTEMP, 5120 M_WAITOK | M_ZERO); 5121 if (fap == NULL) { 5122 SMBERROR("SMB_MALLOC failed\n"); 5123 error = ENOMEM; 5124 goto exit; 5125 } 5126 5127 /* Request a durable handle */ 5128 dptr = NULL; 5129 error = smb2_smb_dur_handle_init(share, np, &dur_handle); 5130 if (!error) { 5131 dptr = &dur_handle; 5132 } 5133 5134 if (np->n_flag & N_ISRSRCFRK) { 5135 disp = FILE_OPEN_IF; 5136 do_create = TRUE; 5137 } 5138 else { 5139 disp = FILE_OPEN; 5140 do_create = FALSE; 5141 } 5142 5143 error = smbfs_smb_ntcreatex(share, np, 5144 rights, shareMode, VREG, 5145 &fid, NULL, 0, 5146 disp, FALSE, fap, 5147 do_create, dptr, ap->a_context); 5148 5149 if (error != 0) 5150 goto exit; 5151 5152 AddFileRef(vp, p, accessMode, rights, fid, dur_handle, &fndEntry); 5153 } 5154 5155 /* Now I can do the ByteRangeLock */ 5156 if (pb->startEndFlag) { 5157 /* 5158 * SMB only allows you to lock relative to the begining of the 5159 * file. So, I need to convert offset base on the begining 5160 * of the file. 5161 */ 5162 uint64_t fileSize = np->n_size; 5163 5164 pb->offset += fileSize; 5165 pb->startEndFlag = 0; 5166 } 5167 5168 flags = 0; 5169 if (pb->unLockFlag) 5170 flags |= SMB_LOCK_RELEASE; 5171 else 5172 flags |= SMB_LOCK_EXCL; 5173 5174 /* The problem here is that the lock pid must match the SMB Header PID. 5175 * Some day it would be nice to pass a better value here. But for now 5176 * always use the same value. 5177 */ 5178 lck_pid = 1; 5179 /* 5180 * -1 infinite wait 5181 * 0 no wait 5182 * any other number is the number of milliseconds to wait. 5183 */ 5184 timo = 0; 5185 5186 error = smbfs_smb_lock(share, flags, fid, lck_pid, pb->offset, 5187 pb->length, timo, ap->a_context); 5188 if (error == 0) { 5189 /* Save/remove lock info for use in read/write to determine what fork to use */ 5190 AddRemoveByteRangeLockEntry (fndEntry, pb->offset, pb->length, 5191 pb->unLockFlag, lck_pid); 5192 /* return the offset to the first byte of the lock */ 5193 pb->retRangeStart = pb->offset; 5194 } else if ((!pb->unLockFlag) && (error == EACCES)) { 5195 /* 5196 * Need to see if we are locking against ourself, so we can return 5197 * the correct error. 5198 */ 5199 if (FindByteRangeLockEntry(fndEntry, pb->offset, pb->length, lck_pid)) 5200 error = EAGAIN; 5201 } 5202 } 5203 break; 5204 default: 5205 error = ENOTSUP; 5206 goto exit; 5207 } 5208 5209exit: 5210 smb_share_rele(share, ap->a_context); 5211 smbnode_unlock(np); 5212 return (error); 5213} 5214 5215/* 5216 * SMB locks do not map to POSIX.1 advisory locks in several ways: 5217 * 1 - SMB provides no way to find an existing lock on the server. 5218 * So, the F_GETLK operation can only report locks created by processes 5219 * on this client. 5220 * 2 - SMB locks cannot overlap an existing locked region of a file. So, 5221 * F_SETLK/F_SETLKW operations that establish locks cannot extend an 5222 * existing lock. 5223 * 3 - When unlocking a SMB locked region, the region to unlock must correspond 5224 * exactly to an existing locked region. So, F_SETLK F_UNLCK operations 5225 * cannot split an existing lock or unlock more than was locked (this is 5226 * especially important because whne files are closed, we receive a request 5227 * to unlock the entire file: l_whence and l_start point to the beginning 5228 * of the file, and l_len is zero). 5229 * 5230 * The result... SMB cannot support POSIX.1 advisory locks. It can however 5231 * support BSD flock() locks, so that's what this implementation will allow. 5232 * 5233 * Since we now support open deny modes we will only support flocks on files that 5234 * have no files open w 5235 * 5236 * vnode_t a_vp; 5237 * caddr_t a_id; 5238 * int a_op; 5239 * struct flock *a_fl; 5240 * int a_flags; 5241 * vfs_context_t a_context; 5242 */ 5243static int32_t 5244smbfs_vnop_advlock(struct vnop_advlock_args *ap) 5245{ 5246 int flags = ap->a_flags; 5247 vnode_t vp = ap->a_vp; 5248 struct smb_share *share; 5249 struct smbnode *np; 5250 int error = 0; 5251 uint32_t timo; 5252 off_t start = 0; 5253 uint64_t len = -1; 5254 uint32_t lck_pid; 5255 5256 /* Preflight checks */ 5257 if (!vnode_isreg(vp)) { 5258 /* can only read regular files */ 5259 if (vnode_isdir(vp)) 5260 return (EISDIR); 5261 else 5262 return (EPERM); 5263 } 5264 5265 share = smb_get_share_with_reference(VTOSMBFS(vp)); 5266 if ((flags & F_POSIX) && ((UNIX_CAPS(share) & CIFS_UNIX_FCNTL_LOCKS_CAP) == 0)) { 5267 /* Release the share reference before returning */ 5268 smb_share_rele(share, ap->a_context); 5269 return(err_advlock(ap)); 5270 } 5271 if ((flags & (F_FLOCK | F_POSIX)) == 0) { 5272 /* Release the share reference before returning */ 5273 smb_share_rele(share, ap->a_context); 5274 SMBWARNING("Lock flag we do not understand %x\n", flags); 5275 return(err_advlock(ap)); 5276 } 5277 5278 if ((error = smbnode_lock(VTOSMB(vp), SMBFS_EXCLUSIVE_LOCK))) { 5279 /* Release the share reference before returning */ 5280 smb_share_rele(share, ap->a_context); 5281 return (error); 5282 } 5283 /* If we got here it must be a flock. Remember flocks lock the whole file. */ 5284 np = VTOSMB(vp); 5285 np->n_lastvop = smbfs_vnop_advlock; 5286 5287 /* 5288 * This vnode has a file open with open deny modes, so the file is really 5289 * already locked. Remember that vn_open and vn_close will also call us here 5290 * so to make them work for now, return no err. If the opened it for 5291 * Open Deny then no one else should be allowed to use it. We could check 5292 * the pid here, but the open call should have handled that for us. 5293 */ 5294 if (np->f_openDenyList) { 5295 error = 0; 5296 goto exit; 5297 } 5298 5299 /* Before trying the lock see if the file needs to be reopened */ 5300 error = smbfs_smb_reopen_file(share, np, ap->a_context); 5301 if (error) { 5302 SMBDEBUG(" %s waiting to be revoked\n", np->n_name); 5303 goto exit; 5304 } 5305 5306 /* 5307 * So if we got to this point we have a normal flock happening. We can have 5308 * the following flags passed to us. 5309 * 5310 * LOCK_SH - shared lock 5311 * LOCK_EX - exclusive lock 5312 * LOCK_NB - don't block when locking 5313 * LOCK_UN - unlock 5314 * 5315 * Currently we always allow the server handle blocking. We may want to 5316 * re-look at this later. What if we have a lock that is blocked and 5317 * the server goes down how long to we wait. 5318 * 5319 * The locking mechanism allows two types of locks: shared locks and 5320 * exclusive locks. At any time multiple shared locks may be applied to a 5321 * file, but at no time are multiple exclusive, or both shared and exclusive, 5322 * locks allowed simultaneously on a file. 5323 * 5324 * A shared lock may be upgraded to an exclusive lock, and vice versa, sim- 5325 * ply by specifying the appropriate lock type; this results in the previous 5326 * lock being released and the new lock applied (possibly after other processes 5327 * have gained and released the lock). 5328 * 5329 * We currently treat LOCK_EX and LOCK_SH the same except we do not allow 5330 * you to have more that one LOCK_EX. 5331 */ 5332 timo = (flags & F_WAIT) ? -1 : 0; 5333 /* The problem here is that the lock pid must match the SMB Header PID. Some 5334 * day it would be nice to pass a better value here. But for now always 5335 * use the same value. 5336 */ 5337 lck_pid = 1; 5338 /* Remember that we are always using the share open file at this point */ 5339 switch(ap->a_op) { 5340 case F_SETLK: 5341 if (! np->f_smbflock) { 5342 error = smbfs_smb_lock(share, SMB_LOCK_EXCL, np->f_fid, lck_pid, 5343 start, len, timo, ap->a_context); 5344 if (error) 5345 goto exit; 5346 SMB_MALLOC(np->f_smbflock, struct smbfs_flock *, sizeof *np->f_smbflock, 5347 M_LOCKF, M_WAITOK); 5348 np->f_smbflock->refcnt = 1; 5349 np->f_smbflock->fl_type = ap->a_fl->l_type; 5350 np->f_smbflock->lck_pid = lck_pid; 5351 np->f_smbflock->start = start; 5352 np->f_smbflock->len = len; 5353 np->f_smbflock->flck_pid = proc_pid(vfs_context_proc(ap->a_context)); 5354 } else if (np->f_smbflock->flck_pid == (uint32_t)proc_pid(vfs_context_proc(ap->a_context))) { 5355 /* First see if this is a upgrade or downgrade */ 5356 if ((np->f_smbflock->refcnt == 1) && 5357 (np->f_smbflock->fl_type != ap->a_fl->l_type)) { 5358 np->f_smbflock->fl_type = ap->a_fl->l_type; 5359 goto exit; 5360 } 5361 /* Trying to mismatch two different style of locks with the same process id bad! */ 5362 if (np->f_smbflock->fl_type != ap->a_fl->l_type) { 5363 error = ENOTSUP; 5364 goto exit; 5365 } 5366 /* 5367 * We know they have the same lock style from above, but they are 5368 * asking for two exclusive. So from Terry comments it looks like 5369 * this is ok. Here's the issue: because what they are doing is 5370 * upgrading an exclusive lock to an exclusive lock in the process 5371 * that holds the previous lock, there are _not_ multiple locks 5372 * involved; there's only the first lock and the lock that replaces 5373 * it. 5374 */ 5375 if (np->f_smbflock->fl_type != F_WRLCK) { 5376 /* 5377 * At no time are multiple exclusive locks allowed simultaneously 5378 * on a file. So we can have only one refcnt. This is an upgrade 5379 * not another lock. 5380 */ 5381 } else { 5382 np->f_smbflock->refcnt++; 5383 } 5384 } else { 5385 /* 5386 * Radar 5572840 5387 * F_WAIT is set we should sleep until the other flock 5388 * gets free then to an upgrade or down grade. Not support 5389 * with SMB yet. 5390 */ 5391 error = EWOULDBLOCK; 5392 goto exit; 5393 } 5394 break; 5395 case F_UNLCK: 5396 error = 0; 5397 if (! np->f_smbflock) /* Got an unlock and had no lock ignore */ 5398 break; 5399 np->f_smbflock->refcnt--; 5400 /* remove the lock on the network and */ 5401 if (np->f_smbflock->refcnt <= 0) { 5402 error = smbfs_smb_lock(share, SMB_LOCK_RELEASE, np->f_fid, lck_pid, 5403 start, len, timo, ap->a_context); 5404 if (error == 0) { 5405 SMB_FREE(np->f_smbflock, M_LOCKF); 5406 np->f_smbflock = NULL; 5407 } 5408 } 5409 break; 5410 default: 5411 error = EINVAL; 5412 break; 5413 } 5414exit: 5415 smb_share_rele(share, ap->a_context); 5416 smbnode_unlock(np); 5417 return (error); 5418} 5419 5420/* 5421 * The calling routine must hold a reference on the share 5422 */ 5423static int 5424smbfs_pathcheck(struct smb_share *share, const char *name, size_t nmlen, 5425 uint32_t nameiop) 5426{ 5427 const char *cp, *endp; 5428 int error; 5429 5430 /* 5431 * We need to check the file name length. We now use ss_maxfilenamelen 5432 * since that gives us a more accurate max file name length. If the 5433 * server supports UNICODE we should do more checking. Since UTF8 can 5434 * have three bytes per character just checking the length is not enough. 5435 * We should convert it to UTF16 and see if the length is twice 5436 * ss_maxfilenamelen. 5437 * 5438 */ 5439 if ((uint32_t)nmlen > share->ss_maxfilenamelen) { 5440 if (SMB_UNICODE_STRINGS(SSTOVC(share))) { 5441 uint16_t *convbuf; 5442 size_t ntwrk_len; 5443 /* 5444 * smb_strtouni needs an output buffer that is twice 5445 * as large as the input buffer (name). 5446 */ 5447 SMB_MALLOC(convbuf, uint16_t *, nmlen * 2, M_SMBNODENAME, M_WAITOK); 5448 if (! convbuf) 5449 return ENAMETOOLONG; 5450 /* 5451 * We need to get the UFT16 length, so just use smb_strtouni 5452 * instead of smb_convert_to_network. 5453 */ 5454 ntwrk_len = smb_strtouni(convbuf, name, nmlen, 5455 UTF_PRECOMPOSED | UTF_SFM_CONVERSIONS); 5456 SMB_FREE(convbuf, M_SMBNODENAME); 5457 if (ntwrk_len > (share->ss_maxfilenamelen * 2)) 5458 return ENAMETOOLONG; 5459 } else { 5460 return ENAMETOOLONG; 5461 } 5462 } else if (! nmlen) { 5463 return ENAMETOOLONG; 5464 } 5465 5466 /* Check name only if CREATE, DELETE, or RENAME */ 5467 if (nameiop == LOOKUP) 5468 return (0); 5469 5470 /* 5471 * Winodws systems do not allow items that begin with "con" to be created. 5472 * If this is not a UNIX server then stop the user from trying 5473 * to create this file or folder. When trying to create a "con" folder or 5474 * "con.xxx" file a windows system will report the following error: 5475 * Cannot create or replace file: The filename you specified is too long. 5476 * Specify a different filename. 5477 * 5478 * From my testing any name that matches "con" or begins with "con." 5479 * should not be create. 5480 * 5481 * Should we be like windows and return ENAMETOOLONG or EACCES 5482 */ 5483 if ((! UNIX_SERVER(SSTOVC(share))) && CON_FILENAME(name, nmlen)) { 5484 if ((nmlen == 3) || ((nmlen > 3) && (*(name+3) == '.'))) 5485 return (ENAMETOOLONG); 5486 } 5487 5488 /* If the server supports UNICODE then we are done checking the name. */ 5489 if (SMB_UNICODE_STRINGS(SSTOVC(share))) 5490 return (0); 5491 5492 /* 5493 * Normally, we'd return EINVAL when the name is syntactically invalid, 5494 * but ENAMETOOLONG makes it clear that the name is the problem (and 5495 * allows Carbon to return a more meaningful error). 5496 */ 5497 error = ENAMETOOLONG; 5498 5499 /* 5500 * Note: This code does not prevent the smb file system client 5501 * from creating filenames which are difficult to use with 5502 * other clients. For example, you can create " foo " or 5503 * "foo..." which cannot be moved, renamed, or deleted by some 5504 * other clients. 5505 */ 5506 5507 /* check for illegal characters, if the server does not support UNICODE */ 5508 for (cp = name, endp = name + nmlen; cp < endp; ++cp) { 5509 /* 5510 * The set of illegal characters in long names is the same as 5511 * 8.3 except the characters 0x20, 0x2b, 0x2c, 0x3b, 0x3d, 0x5b, 5512 * and 0x5d are now legal, and the restrictions on periods was 5513 * removed. 5514 */ 5515 switch (*cp) { 5516 case 0x20: /* space */ 5517 case 0x2B: /* + */ 5518 case 0x2C: /* , */ 5519 case 0x3B: /* ; */ 5520 case 0x3D: /* = */ 5521 case 0x5B: /* [ */ 5522 case 0x5D: /* ] */ 5523 break; 5524 case 0x22: /* " */ 5525 case 0x2A: /* * */ 5526 case 0x2F: /* / */ 5527 case 0x3A: /* : */ 5528 case 0x3C: /* < */ 5529 case 0x3E: /* > */ 5530 case 0x3F: /* ? */ 5531 case 0x5C: /* \ */ 5532 case 0x7C: /* | */ 5533 /* illegal character found */ 5534 return (error); 5535 break; 5536 default: 5537 break; 5538 } 5539 } 5540 return (0); 5541} 5542 5543/* 5544 * smbfs_vnop_lookup 5545 * 5546 * struct vnodeop_desc *a_desc; 5547 * vnode_t a_dvp; 5548 * vnode_t *a_vpp; 5549 * struct componentname *a_cnp; 5550 * vfs_context_t a_context; 5551 */ 5552static int 5553smbfs_vnop_lookup(struct vnop_lookup_args *ap) 5554{ 5555 vfs_context_t context = ap->a_context; 5556 vnode_t dvp = ap->a_dvp; 5557 vnode_t *vpp = ap->a_vpp; 5558 vnode_t vp; 5559 struct smbnode *dnp = NULL; 5560 struct mount *mp = vnode_mount(dvp); 5561 struct smb_share *share = NULL; 5562 struct componentname *cnp = ap->a_cnp; 5563 const char *name = cnp->cn_nameptr; 5564 uint32_t flags = cnp->cn_flags; 5565 uint32_t nameiop = cnp->cn_nameiop; 5566 size_t nmlen = cnp->cn_namelen; 5567 struct smbfattr fattr, *fap = NULL; 5568 int wantparent, error, islastcn, isdot = FALSE; 5569 int parent_locked = FALSE; 5570 5571 /* 5572 * We may want to move smbfs_pathcheck here, but we really should never 5573 * find a bad name in the name cache lookup. 5574 */ 5575 if (!vnode_isdir(dvp)) 5576 return (ENOTDIR); 5577 if ((flags & ISDOTDOT) && vnode_isvroot(dvp)) { 5578 SMBFSERR("invalid '..'\n"); 5579 return (EIO); 5580 } 5581 islastcn = (flags & ISLASTCN) ? TRUE : FALSE; 5582 if (islastcn && vfs_isrdonly(mp) && nameiop != LOOKUP) 5583 return (EROFS); 5584 wantparent = (flags & (LOCKPARENT|WANTPARENT)) ? TRUE : FALSE; 5585 5586 share = smb_get_share_with_reference(VTOSMBFS(dvp)); 5587 /* 5588 * We need to make sure the negative name cache gets updated if 5589 * needed. So if the parents cache has expired, then update the 5590 * the parent's cache. This will cause the negative name cache to 5591 * be flush if the parent's modify time has changed. 5592 */ 5593 if (smbnode_lock(VTOSMB(dvp), SMBFS_EXCLUSIVE_LOCK) == 0) { 5594 VTOSMB(dvp)->n_lastvop = smbfs_vnop_lookup; 5595 if (VTOSMB(dvp)->n_flag & NNEGNCENTRIES) { 5596 /* ignore any errors here we will catch them later */ 5597 (void)smbfs_update_cache(share, dvp, NULL, context); 5598 } 5599 smbnode_unlock(VTOSMB(dvp)); /* Release the smbnode lock */ 5600 } 5601 5602 *vpp = NULLVP; 5603 error = cache_lookup(dvp, vpp, cnp); 5604 switch (error) { 5605 case ENOENT: /* negative cache entry */ 5606 goto skipLookup; 5607 case 0: /* cache miss */ 5608 break; 5609 case -1: /* cache hit */ 5610 /* 5611 * On CREATE we can't trust a cache hit as if it is stale 5612 * and the object doesn't exist on the server returning zero 5613 * here would cause the vfs layer to, for instance, EEXIST 5614 * the mkdir. 5615 */ 5616 if (nameiop != CREATE) { 5617 error = 0; 5618 /* Check to see it the node's meta cache needs to be update */ 5619 if (smbnode_lock(VTOSMB(*vpp), SMBFS_EXCLUSIVE_LOCK) == 0) { 5620 VTOSMB(*vpp)->n_lastvop = smbfs_vnop_lookup; 5621 error = smbfs_update_cache(share, *vpp, NULL, context); 5622 smbnode_unlock(VTOSMB(*vpp)); /* Release the smbnode lock */ 5623 } 5624 /* 5625 * At this point we only care if it exist or not so any other 5626 * error should just get ignored 5627 */ 5628 if (error != ENOENT) { 5629 error = 0; 5630 goto done; 5631 } 5632 /* 5633 * The item we had, no longer exists so fall through and see if 5634 * it exist as a different item 5635 */ 5636 } 5637 if (*vpp) { 5638 cache_purge(*vpp); 5639 vnode_put(*vpp); 5640 *vpp = NULLVP; 5641 } 5642 break; 5643 default: /* unknown & unexpected! */ 5644 SMBWARNING("cache_lookup error=%d\n", error); 5645 goto done; 5646 } 5647 /* 5648 * entry is not in the name cache 5649 * 5650 * validate syntax of name. ENAMETOOLONG makes it clear the name 5651 * is the problem 5652 */ 5653 error = smbfs_pathcheck(share, cnp->cn_nameptr, cnp->cn_namelen, nameiop); 5654 if (error) { 5655 SMBWARNING("warning: bad filename %s\n", name); 5656 goto done; 5657 } 5658 dnp = VTOSMB(dvp); 5659 5660 /* lock the parent while we go look for the item on server */ 5661 if (smbnode_lock(dnp, SMBFS_EXCLUSIVE_LOCK) != 0) { 5662 error = ENOENT; 5663 goto skipLookup; 5664 } 5665 parent_locked = TRUE; 5666 dnp->n_lastvop = smbfs_vnop_lookup; 5667 5668 isdot = (nmlen == 1 && name[0] == '.'); 5669 fap = &fattr; 5670 /* 5671 * This can allocate a new "name" do not return before the end of the 5672 * routine from here on. 5673 */ 5674 if (flags & ISDOTDOT) { 5675 /* Lock protects dnp->n_parent. See <rdar://problem/11824956> */ 5676 lck_rw_lock_shared(&dnp->n_name_rwlock); 5677 error = smbfs_lookup(share, dnp->n_parent, NULL, NULL, fap, context); 5678 lck_rw_unlock_shared(&dnp->n_name_rwlock); 5679 } else { 5680 error = smbfs_lookup(share, dnp, &name, &nmlen, fap, context); 5681 } 5682 /* 5683 * We use to unlock the parent here, but we really need it locked 5684 * until after we do the smbfs_nget calls. 5685 */ 5686 /* 5687 * We didn't find it and this is not a CREATE or RENAME operation so 5688 * add it to the negative name cache. 5689 */ 5690 if ((error == ENOENT) && (cnp->cn_flags & MAKEENTRY) && 5691 (!(((nameiop == CREATE) || (nameiop == RENAME)) && islastcn))) { 5692 /* add a negative entry in the name cache */ 5693 cache_enter(dvp, NULL, cnp); 5694 dnp->n_flag |= NNEGNCENTRIES; 5695 } 5696 5697skipLookup: 5698 if (error) { 5699 /* 5700 * note the EJUSTRETURN code in lookup() 5701 */ 5702 if (((nameiop == CREATE) || (nameiop == RENAME)) && 5703 (error == ENOENT) && islastcn) { 5704 error = EJUSTRETURN; 5705 } 5706 } else if ((nameiop == RENAME) && islastcn && wantparent) { 5707 if (isdot) { 5708 error = EISDIR; 5709 } else { 5710 error = smbfs_nget(share, mp, 5711 dvp, name, nmlen, 5712 fap, &vp, 5713 0, SMBFS_NGET_CREATE_VNODE, 5714 context); 5715 if (!error) { 5716 smbnode_unlock(VTOSMB(vp)); /* Release the smbnode lock */ 5717 *vpp = vp; 5718 } 5719 } 5720 } else if ((nameiop == DELETE) && islastcn) { 5721 if (isdot) { 5722 error = vnode_get(dvp); 5723 if (!error) 5724 *vpp = dvp; 5725 } else { 5726 error = smbfs_nget(share, mp, 5727 dvp, name, nmlen, 5728 fap, &vp, 5729 0, SMBFS_NGET_CREATE_VNODE, 5730 context); 5731 if (!error) { 5732 smbnode_unlock(VTOSMB(vp)); /* Release the smbnode lock */ 5733 *vpp = vp; 5734 } 5735 } 5736 } else if (flags & ISDOTDOT) { 5737 if (dvp) { 5738 /* Lock protects dvp->n_parent. See <rdar://problem/11824956> */ 5739 lck_rw_lock_shared(&VTOSMB(dvp)->n_name_rwlock); 5740 if (VTOSMB(dvp)->n_parent) { 5741 vp = VTOSMB(dvp)->n_parent->n_vnode; 5742 error = vnode_get(vp); 5743 if (!error) 5744 *vpp = vp; 5745 } 5746 lck_rw_unlock_shared(&VTOSMB(dvp)->n_name_rwlock); 5747 } 5748 } else if (isdot) { 5749 error = vnode_get(dvp); 5750 if (!error) 5751 *vpp = dvp; 5752 } else { 5753 error = smbfs_nget(share, mp, 5754 dvp, name, nmlen, 5755 fap, &vp, 5756 cnp->cn_flags, SMBFS_NGET_CREATE_VNODE, 5757 context); 5758 if (!error) { 5759 smbnode_unlock(VTOSMB(vp)); /* Release the smbnode lock */ 5760 *vpp = vp; 5761 } 5762 } 5763 if (name != cnp->cn_nameptr) { 5764 SMB_FREE(name, M_SMBNODENAME); 5765 } 5766 /* If the parent node is still lock then unlock it here. */ 5767 if (parent_locked && dnp) 5768 smbnode_unlock(dnp); 5769done: 5770 smb_share_rele(share, context); 5771 return (error); 5772} 5773 5774/* 5775 * smbfs_vnop_offtoblk 5776 * 5777 * vnode_t a_vp; 5778 * off_t a_offset; 5779 * daddr64_t *a_lblkno; 5780 * vfs_context_t a_context; 5781 * 5782 * ftoblk converts a file offset to a logical block number 5783 */ 5784static int 5785smbfs_vnop_offtoblk(struct vnop_offtoblk_args *ap) 5786{ 5787 *ap->a_lblkno = ap->a_offset / PAGE_SIZE_64; 5788 return (0); 5789} 5790 5791/* 5792 * smbfs_vnop_blktooff 5793 * 5794 * vnode_t a_vp; 5795 * off_t a_offset; 5796 * daddr64_t *a_lblkno; 5797 * off_t *a_offset; 5798 * vfs_context_t a_context; 5799 * 5800 * blktooff converts a logical block number to a file offset 5801 */ 5802static int 5803smbfs_vnop_blktooff(struct vnop_blktooff_args *ap) 5804{ 5805 *ap->a_offset = (off_t)ap->a_lblkno * PAGE_SIZE_64; 5806 return (0); 5807} 5808 5809/* 5810 * smbfs_vnop_pagein 5811 * 5812 * vnode_t a_vp, 5813 * upl_t a_pl, 5814 * vm_offset_t a_pl_offset, 5815 * off_t a_f_offset, 5816 * size_t a_size, 5817 * int a_flags 5818 * vfs_context_t a_context; 5819 * 5820 * NOTE: We no longer take a node lock in this routine. 5821 */ 5822static int 5823smbfs_vnop_pagein(struct vnop_pagein_args *ap) 5824{ 5825 vnode_t vp = ap->a_vp; 5826 struct smb_share *share; 5827 size_t size = ap->a_size; 5828 off_t f_offset = ap->a_f_offset; 5829 struct smbnode *np; 5830 int error; 5831 5832 np = VTOSMB(vp); 5833 5834 if ((size <= 0) || (f_offset < 0) || (f_offset >= (off_t)np->n_size) || 5835 (f_offset & PAGE_MASK_64) || (size & PAGE_MASK)) { 5836 return err_pagein(ap); /* behave like the deadfs does */ 5837 } 5838 share = smb_get_share_with_reference(VTOSMBFS(vp)); 5839 /* Before trying the read see if the file needs to be reopened */ 5840 error = smbfs_smb_reopen_file(share, np, ap->a_context); 5841 if (error) { 5842 SMBDEBUG(" %s waiting to be revoked\n", np->n_name); 5843 /* Release the share reference before returning */ 5844 smb_share_rele(share, ap->a_context); 5845 error = err_pagein(ap); /* behave like the deadfs does */ 5846 return error; 5847 } 5848 /* 5849 * The old code would check to see if the node smbfsIsCacheable. If not then 5850 * it would try to invalidate the page to force the cluster code to get a 5851 * new copy from disk/network. Talked this over with Joe and this is not 5852 * really need. 5853 * 5854 * The smbfs_vnop_pagein will only be called for extents of pages that do 5855 * NOT already exist in the cache. When the UPL is created, the pages are 5856 * acquired and locked down for the 'holes' that exist in the cache. Once 5857 * those pages are locked into the UPL, there can be no other path by which 5858 * the pages can be made valid. So... no reason to flush pages in the range 5859 * being passed into you and then on to cluster_pagein. 5860 */ 5861 error = cluster_pagein(vp, ap->a_pl, ap->a_pl_offset, ap->a_f_offset, 5862 (int)ap->a_size, (off_t)np->n_size, ap->a_flags); 5863 if (error) { 5864 SMB_LOG_IO("%s failed cluster_pagein with an error of %d\n", np->n_name, error); 5865 } 5866 smb_share_rele(share, ap->a_context); 5867 return (error); 5868} 5869 5870/* 5871 * smbfs_vnop_pageout 5872 * 5873 * vnode_t a_vp, 5874 * upl_t a_pl, 5875 * vm_offset_t a_pl_offset, 5876 * off_t a_f_offset, 5877 * size_t a_size, 5878 * int a_flags 5879 * vfs_context_t a_context; 5880 * 5881 * NOTE: We no longer take a node lock in this routine. 5882 * 5883 */ 5884static int 5885smbfs_vnop_pageout(struct vnop_pageout_args *ap) 5886{ 5887 vnode_t vp = ap->a_vp; 5888 struct smbnode *np; 5889 struct smb_share *share; 5890 upl_t pl = ap->a_pl; 5891 size_t size = ap->a_size; 5892 off_t f_offset = ap->a_f_offset; 5893 int error; 5894 5895 if (vnode_vfsisrdonly(vp)) 5896 return(EROFS); 5897 5898 np = VTOSMB(vp); 5899 5900 if (pl == (upl_t)NULL) 5901 panic("smbfs_vnop_pageout: no upl"); 5902 5903 if ((size <= 0) || (f_offset < 0) || (f_offset >= (off_t)np->n_size) || 5904 (f_offset & PAGE_MASK_64) || (size & PAGE_MASK)) { 5905 return err_pageout(ap); 5906 } 5907 share = smb_get_share_with_reference(VTOSMBFS(vp)); 5908 /* Before trying the write see if the file needs to be reopened */ 5909 error = smbfs_smb_reopen_file(share, np, ap->a_context); 5910 if (error) { 5911 SMBDEBUG(" %s waiting to be revoked\n", np->n_name); 5912 /* Release the share reference before returning */ 5913 smb_share_rele(share, ap->a_context); 5914 return err_pageout(ap); 5915 } 5916 5917 error = cluster_pageout(vp, ap->a_pl, ap->a_pl_offset, ap->a_f_offset, 5918 (int)ap->a_size, (off_t)np->n_size, ap->a_flags); 5919 if (error) { 5920 SMB_LOG_IO("%s failed cluster_pageout with an error of %d\n", 5921 np->n_name, error); 5922 } 5923 5924 smb_share_rele(share, ap->a_context); 5925 /* If we can get the parent vnode, reset its meta data cache timer. */ 5926 if (vnode_isnamedstream(vp)) { 5927 vnode_t parent_vp = vnode_getparent(vp); 5928 if (parent_vp) { 5929 VTOSMB(parent_vp)->attribute_cache_timer = 0; 5930 vnode_put(parent_vp); 5931 } 5932 } 5933 return (error); 5934} 5935 5936/* 5937 * smbfs_vnop_copyfile 5938 * 5939 * vnode_t a_fvp; 5940 * vnode_t a_tdvp; 5941 * vnode_t a_tvp; 5942 * struct componentname *a_tcnp; 5943 * int a_flags; 5944 * vfs_context_t a_context; 5945 */ 5946static int 5947smbfs_vnop_copyfile(struct vnop_copyfile_args *ap) 5948{ 5949 vnode_t fvp = ap->a_fvp; 5950 vnode_t tvp = ap->a_tvp; 5951 vnode_t tdvp = ap->a_tdvp; 5952 struct smbmount *smp = VFSTOSMBFS(vnode_mount(fvp)); 5953 struct smb_share *share = NULL; 5954 struct componentname *tcnp = ap->a_tcnp; 5955 struct smbnode *fnp = NULL; 5956 struct smbnode *tdnp = NULL; 5957 struct smbnode *tnp = NULL; 5958 int error = 0, vtype, need_unlock = 0; 5959 5960 /* VFS checks the following before calling us: 5961 * 5962 * tvp exists AND (ap->flags & CPF_OVERWRITE) 5963 * fvp AND tvp are not directories 5964 * KAUTH_VNODE_ADD_FILE authorized on tdvp 5965 * fvp != tvp 5966 * fvp != tdvp 5967 */ 5968 5969 /* Check if this is an SMB2 server (need COPYCHUNK IOCTL) */ 5970 share = smb_get_share_with_reference(smp); 5971 if (!SSTOVC(share)->vc_flags & SMBV_SMB2) { 5972 SMBERROR("copyfile not supported on this server.\n"); 5973 error = ENOTSUP; 5974 goto out; 5975 } 5976 5977 /* Check for cross-device copyfile */ 5978 if ((vnode_mount(fvp) != vnode_mount(tdvp)) || 5979 (tvp && (vnode_mount(fvp) != vnode_mount(tvp)))) { 5980 SMBERROR("cross-device copyfile not supported.\n"); 5981 error = EXDEV; 5982 goto out; 5983 } 5984 5985 /* source file must be a directory, symbolic link, or regular file */ 5986 vtype = vnode_vtype(fvp); 5987 if ( (vtype != VDIR) && (vtype != VREG) && (vtype != VLNK) ) { 5988 SMBERROR("copyfile not supported on vtype: %d\n", vtype); 5989 error = EINVAL; 5990 goto out; 5991 } 5992 5993 fnp = VTOSMB(fvp); 5994 tdnp = VTOSMB(tdvp); 5995 tnp = (tvp == NULL) ? NULL : VTOSMB(tvp); 5996 5997 /* Lock source file and target directory */ 5998 smbnode_lockpair(fnp, tdnp, SMBFS_EXCLUSIVE_LOCK); 5999 need_unlock = 1; 6000 6001 fnp->n_lastvop = smbfs_vnop_copyfile; 6002 tdnp->n_lastvop = smbfs_vnop_copyfile; 6003 if (tnp != NULL) 6004 tnp->n_lastvop = smbfs_vnop_copyfile; 6005 6006 /* 6007 * Do the copyfile operation. 6008 */ 6009 error = smb2fs_smb_copyfile(share, fnp, tdnp, tcnp->cn_nameptr, 6010 tcnp->cn_namelen, ap->a_context); 6011 if (error) { 6012 SMBERROR("smb2fs_smb_copyfile returned: %d\n", error); 6013 goto out; 6014 } 6015 6016 smbfs_attr_touchdir(tdnp, (share->ss_fstype == SMB_FS_FAT)); 6017 6018 /* blow away statfs cache */ 6019 smp->sm_statfstime = 0; 6020 6021 /* Invalidate negative cache entries in destination dir */ 6022 if (tdnp->n_flag & NNEGNCENTRIES) { 6023 tdnp->n_flag &= ~NNEGNCENTRIES; 6024 cache_purge_negatives(tdvp); 6025 } 6026 6027out: 6028 /* We only have a share if we obtain a reference on it, so release it */ 6029 if (share) { 6030 smb_share_rele(share, ap->a_context); 6031 } 6032 6033 if (need_unlock) { 6034 smbnode_unlockpair(fnp, tdnp); 6035 } 6036 6037 return (error); 6038} 6039 6040static uint32_t emptyfinfo[8] = {0}; 6041/* 6042 * DefaultFillAfpInfo 6043 * 6044 * Given a buffer fill in the default AfpInfo values. 6045 */ 6046static void 6047DefaultFillAfpInfo(uint8_t *afpinfo) 6048{ 6049 int ii = 0; 6050 bzero(afpinfo, AFP_INFO_SIZE); 6051 /* Signature is a DWORD. Must be *(PDWORDD)"AFP" */ 6052 afpinfo[ii++] = 'A'; 6053 afpinfo[ii++] = 'F'; 6054 afpinfo[ii++] = 'P'; 6055 afpinfo[ii++] = 0; 6056 /* Version is a DWORD. Must be 0x00010000 (byte swapped) */ 6057 afpinfo[ii++] = 0; 6058 afpinfo[ii++] = 0; 6059 afpinfo[ii++] = 0x01; 6060 afpinfo[ii++] = 0; 6061 /* Reserved1 is a DWORD */ 6062 ii += 4; 6063 /* 6064 * Backup time is a DWORD. Backup time for the file/dir. Not set equals 6065 * 0x80010000 (byte swapped) 6066 */ 6067 afpinfo[ii++] = 0; 6068 afpinfo[ii++] = 0; 6069 afpinfo[ii++] = 0; 6070 afpinfo[ii] = 0x80; 6071 /* Finder Info is 32 bytes. Calling process fills this in */ 6072 /* ProDos Info is 6 bytes. Leave set to zero? */ 6073 /* Reserved2 is 6 bytes */ 6074} 6075 6076/* 6077 * xattr2sfm 6078 * 6079 * See if this xattr is really the resource fork or the finder info stream. If so 6080 * return the correct streams name otherwise just return the name passed to us. 6081 */ 6082static const char * 6083xattr2sfm(const char *xa, enum stream_types *stype) 6084{ 6085 /* Never let them use the SFM Stream Names */ 6086 if (!bcmp(xa, SFM_RESOURCEFORK_NAME, sizeof(SFM_RESOURCEFORK_NAME))) { 6087 return(NULL); 6088 } 6089 if (!bcmp(xa, SFM_FINDERINFO_NAME, sizeof(SFM_FINDERINFO_NAME))) { 6090 return(NULL); 6091 } 6092 if (!bcmp(xa, SFM_DESKTOP_NAME, sizeof(SFM_DESKTOP_NAME))) { 6093 return(NULL); 6094 } 6095 if (!bcmp(xa, SFM_IDINDEX_NAME, sizeof(SFM_IDINDEX_NAME))) { 6096 return(NULL); 6097 } 6098 6099 if (!bcmp(xa, XATTR_RESOURCEFORK_NAME, sizeof(XATTR_RESOURCEFORK_NAME))) { 6100 *stype = kResourceFrk; 6101 return (SFM_RESOURCEFORK_NAME); 6102 } 6103 if (!bcmp(xa, XATTR_FINDERINFO_NAME, sizeof(XATTR_FINDERINFO_NAME))) { 6104 *stype = kFinderInfo; 6105 return (SFM_FINDERINFO_NAME); 6106 } 6107 *stype = kExtendedAttr; 6108 return (xa); 6109} 6110 6111/* 6112 * smbfs_vnop_setxattr 6113 * 6114 * vnode_t a_vp; 6115 * int8_t * a_name; 6116 * uio_t a_uio; 6117 * int32_t a_options; 6118 * vfs_context_t a_context; 6119 */ 6120static int 6121smbfs_vnop_setxattr(struct vnop_setxattr_args *ap) 6122{ 6123 vnode_t vp = ap->a_vp; 6124 const char *sfmname; 6125 int error = 0; 6126 SMBFID fid = 0; 6127 uint32_t rights = SMB2_FILE_WRITE_DATA; 6128 struct smbnode *np = NULL; 6129 struct smb_share *share = NULL; 6130 enum stream_types stype = kNoStream; 6131 uint32_t open_disp = 0; 6132 uio_t afp_uio = NULL; 6133 uint8_t afpinfo[60]; 6134 struct smbfattr fattr; 6135 6136 DBG_ASSERT(!vnode_isnamedstream(vp)); 6137 6138 if ((error = smbnode_lock(VTOSMB(vp), SMBFS_EXCLUSIVE_LOCK))) 6139 return (error); 6140 np = VTOSMB(vp); 6141 np->n_lastvop = smbfs_vnop_setxattr; 6142 share = smb_get_share_with_reference(VTOSMBFS(vp)); 6143 6144 /* 6145 * FILE_NAMED_STREAMS tells us the server supports streams. 6146 * NOTE: This flag may have been overwriten by us in smbfs_mount. The default 6147 * is for streams to be turn off. See the smbfs_mount for more details. 6148 */ 6149 if (!(share->ss_attributes & FILE_NAMED_STREAMS)) { 6150 error = ENOTSUP; 6151 goto exit; 6152 } 6153 6154 /* You cant have both of these set at the same time. */ 6155 if ( (ap->a_options & XATTR_CREATE) && (ap->a_options & XATTR_REPLACE) ) { 6156 error = EINVAL; 6157 goto exit; 6158 } 6159 6160 /* SMB doesn't support having a slash in the xattr name */ 6161 if (strchr(ap->a_name, '/')) { 6162 error = EINVAL; 6163 SMBWARNING("Slash in xattr name not allowed: error %d %s:%s\n", error, 6164 np->n_name, ap->a_name); 6165 goto exit; 6166 } 6167 sfmname = xattr2sfm(ap->a_name, &stype); 6168 if (!sfmname) { 6169 error = EINVAL; 6170 goto exit; 6171 } 6172 6173 /* 6174 * Need to add write attributes if we want to reset the modify time. We never do this 6175 * for the resource fork. The file manager expects the modify time to change if the 6176 * resource fork changes. 6177 */ 6178 if ((stype & kResourceFrk) != kResourceFrk) 6179 rights |= SMB2_FILE_WRITE_ATTRIBUTES; 6180 6181 /* 6182 * We treat finder info differently than any other EA/Stream. Because of 6183 * SFM we need to do things a little different. Remember the AFPInfo stream 6184 * has more information in it than just the finder info. WARNING: SFM can 6185 * get very confused if you do not handle this correctly! 6186 */ 6187 if (stype & kFinderInfo) { 6188 uint8_t finfo[FINDERINFOSIZE]; 6189 time_t attrtimeo; 6190 struct timespec ts; 6191 size_t sizep; 6192 int len = (int)uio_resid(ap->a_uio); 6193 6194 /* Can't be larger that 32 bytes */ 6195 if (len > FINDERINFOSIZE) { 6196 error = EINVAL; 6197 goto exit; 6198 } 6199 error = uiomove((void *)finfo, len, ap->a_uio); 6200 if (error) 6201 goto exit; 6202 SMB_CACHE_TIME(ts, np, attrtimeo); 6203 /* 6204 * The Finder Info cache hasn't expired so check to see if they are 6205 * setting it to something different or the same. If the same then skip 6206 * setting it, this is what AFP does. 6207 */ 6208 if ((ts.tv_sec - np->finfo_cache) <= attrtimeo) { 6209 if (bcmp(np->finfo, finfo, sizeof(finfo)) == 0) 6210 goto exit; 6211 } 6212 /* We want to read also in this case. */ 6213 rights |= SMB2_FILE_READ_DATA; 6214 /* Create a dummy uio structure */ 6215 afp_uio = uio_create(1, 0, UIO_SYSSPACE, UIO_READ); 6216 if (afp_uio) 6217 error = uio_addiov( afp_uio, CAST_USER_ADDR_T(afpinfo), sizeof(afpinfo)); 6218 else 6219 error = ENOMEM; 6220 if (error) 6221 goto exit; 6222 /* Now set the default afp info buffer */ 6223 DefaultFillAfpInfo(afpinfo); 6224 /* Open and read the data in, if an empty file we will still get an fid */ 6225 error = smbfs_smb_openread(share, np, &fid, rights, afp_uio, &sizep, 6226 sfmname, &ts, ap->a_context); 6227 /* Replace the finder info with the data that was passed down. */ 6228 if (!error) { 6229 bcopy((void *)finfo, (void *)&afpinfo[AFP_INFO_FINDER_OFFSET], len); 6230 uio_reset(afp_uio, 0, UIO_SYSSPACE, UIO_WRITE ); 6231 error = uio_addiov( afp_uio, CAST_USER_ADDR_T(afpinfo), sizeof(afpinfo)); 6232 } 6233 if (error) 6234 goto out; 6235 /* Truncate the stream if there is anything in it, this will wake up SFM */ 6236 if (sizep && (VTOSMBFS(vp)->sm_flags & MNT_IS_SFM_VOLUME)) { 6237 /* Ignore any errors, write will catch them */ 6238 (void)smbfs_smb_seteof(share, fid, 0, ap->a_context); 6239 } 6240 /* Now we can write the afp info back out with the new finder information */ 6241 if (!error) { 6242 error = smb_smb_write(share, fid, afp_uio, 0, ap->a_context); 6243 } 6244 /* 6245 * Try to set the modify time back to the original time, ignore any 6246 * errors. Since we are using the open stream file descriptor to change 6247 * the time remove the directory attribute bit if set. 6248 */ 6249 (void)smbfs_smb_setfattrNT(share, (np->n_dosattr & ~SMB_EFA_DIRECTORY), 6250 fid, NULL, &ts, NULL, ap->a_context); 6251 /* Reset our cache timer and copy the new data into our cache */ 6252 if (!error) { 6253 nanouptime(&ts); 6254 np->finfo_cache = ts.tv_sec; 6255 bcopy((void *)&afpinfo[AFP_INFO_FINDER_OFFSET], np->finfo, 6256 sizeof(np->finfo)); 6257 } 6258 goto out; 6259 } 6260 6261 switch(ap->a_options & (XATTR_CREATE | XATTR_REPLACE)) { 6262 case XATTR_CREATE: /* set the value, fail if attr already exists */ 6263 /* if exists fail else create it */ 6264 open_disp = FILE_CREATE; 6265 break; 6266 case XATTR_REPLACE: /* set the value, fail if attr does not exist */ 6267 /* if exists overwrite item else fail */ 6268 open_disp = FILE_OVERWRITE; 6269 break; 6270 default: 6271 if ((stype & kResourceFrk) == kResourceFrk) { 6272 /* if resource fork then if it exists open it else create it */ 6273 open_disp = FILE_OPEN_IF; 6274 } else { 6275 /* if anything else then if it exists overwrite it else create it */ 6276 open_disp = FILE_OVERWRITE_IF; 6277 } 6278 break; 6279 } 6280 /* Open/create the stream */ 6281 error = smbfs_smb_create(share, np, sfmname, 6282 strnlen(sfmname, share->ss_maxfilenamelen+1), 6283 rights, &fid, open_disp, 1, &fattr, ap->a_context); 6284 if (error) { 6285 goto exit; 6286 } 6287 /* Now write out the stream data */ 6288 error = smb_smb_write(share, fid, ap->a_uio, 0, ap->a_context); 6289 /* 6290 * %%% 6291 * Should we reset the modify time back to the original time? Never for the 6292 * resource fork, but what about EAs? Could be a performance issue, really 6293 * need a clearer message from the rest of the file system team. 6294 * 6295 * For now try to set the modify time back to the original time, ignore any 6296 * errors. Since we are using the open stream file descriptor to change the 6297 * time remove the directory attribute bit if set. 6298 */ 6299 if ((stype & kResourceFrk) != kResourceFrk) { 6300 (void)smbfs_smb_setfattrNT(share, (np->n_dosattr & ~SMB_EFA_DIRECTORY), 6301 fid, NULL, &np->n_mtime, NULL, ap->a_context); 6302 } 6303 6304out: 6305 if (fid != 0) { 6306 (void)smbfs_smb_close(share, fid, ap->a_context); 6307 } 6308 6309exit: 6310 if (afp_uio) 6311 uio_free(afp_uio); 6312 6313 if (error == ENOENT) 6314 error = ENOATTR; 6315 6316 /* Check to see if its a normal error */ 6317 if (error && (error != ENOTSUP) && (error != ENOATTR)) { 6318 SMBWARNING("error %d %s:%s\n", error, np->n_name, ap->a_name); 6319 /* Always make sure its a legit error, see man listxattr */ 6320 if ((error != EROFS) && (error != EPERM) && (error != EINVAL) && 6321 (error != ENOTDIR) && (error != EACCES) && (error != ELOOP) && 6322 (error != EFAULT) && (error != EIO) && (error != ENAMETOOLONG) && 6323 (error != EEXIST) && (error != ERANGE) && 6324 (error != E2BIG) && (error != ENOSPC)) 6325 error = EIO; /* Not sure what else to do here */ 6326 } 6327 if (!error) { 6328 /* We create a named stream, so remove the no stream flag */ 6329 np->n_fstatus &= ~kNO_SUBSTREAMS; 6330 } 6331 smb_share_rele(share, ap->a_context); 6332 smbnode_unlock(np); 6333 return (error); 6334} 6335 6336/* 6337 * smbfs_vnop_listxattr 6338 * 6339 * vnode_t a_vp; 6340 * uio_t a_uio; 6341 * size_t *a_size; 6342 * int32_t a_options; 6343 * vfs_context_t a_context; 6344 */ 6345static int 6346smbfs_vnop_listxattr(struct vnop_listxattr_args *ap) 6347{ 6348 vnode_t vp = ap->a_vp; 6349 uio_t uio = ap->a_uio; 6350 size_t *sizep = ap->a_size; 6351 struct smbnode *np = NULL; 6352 struct smb_share *share = NULL; 6353 int error = 0; 6354 uint32_t stream_flags = 0; 6355 6356 DBG_ASSERT(!vnode_isnamedstream(vp)); 6357 6358 if ((error = smbnode_lock(VTOSMB(vp), SMBFS_EXCLUSIVE_LOCK))) 6359 return (error); 6360 np = VTOSMB(vp); 6361 np->n_lastvop = smbfs_vnop_listxattr; 6362 share = smb_get_share_with_reference(VTOSMBFS(vp)); 6363 /* 6364 * FILE_NAMED_STREAMS tells us the server supports streams. 6365 * NOTE: This flag may have been overwriten by us in smbfs_mount. The default 6366 * is for streams to be turn off. See the smbfs_mount for more details. 6367 */ 6368 if (!(share->ss_attributes & FILE_NAMED_STREAMS)) { 6369 error = ENOTSUP; 6370 goto exit; 6371 } 6372 if (np->n_fstatus & kNO_SUBSTREAMS) { 6373 error = ENOATTR; 6374 goto exit; 6375 } 6376 error = smbfs_smb_qstreaminfo(share, np, 6377 NULL, 0, 6378 NULL, 6379 uio, sizep, 6380 NULL, NULL, 6381 &stream_flags, NULL, 6382 ap->a_context); 6383 6384exit: 6385 6386 /* 6387 * From the man pages: If no accessible extended attributes are associated 6388 * with the given path or fd, the function returns zero. 6389 */ 6390 if (error == ENOATTR) 6391 error = 0; 6392 6393 /* Check to see if its a normal error */ 6394 if (error && (error != ENOTSUP)) { 6395 SMBWARNING("error %d %s\n", error, np->n_name); 6396 /* Always make sure its a legit error, see man listxattr */ 6397 if ((error != ERANGE) && (error != EPERM) && (error != EINVAL) && 6398 (error != ENOTDIR) && (error != EACCES) && (error != ELOOP) && 6399 (error != EFAULT) && (error != EIO)) 6400 error = 0; /* Just pretend it doesn't exist */ 6401 } 6402 smb_share_rele(share, ap->a_context); 6403 smbnode_unlock(np); 6404 return (error); 6405} 6406 6407/* 6408 * vnop_removexattr_args 6409 * 6410 * vnode_t a_vp; 6411 * int8_t * a_name; 6412 * int32_t a_options; 6413 * vfs_context_t a_context; 6414 */ 6415static int 6416smbfs_vnop_removexattr(struct vnop_removexattr_args *ap) 6417{ 6418 vnode_t vp = ap->a_vp; 6419 const char *sfmname; 6420 int error = 0, saved_error = 0; 6421 struct smbnode *np = NULL; 6422 struct smb_share *share = NULL; 6423 enum stream_types stype = kNoStream; 6424 struct timespec ts; 6425 6426 DBG_ASSERT(!vnode_isnamedstream(vp)); 6427 6428 if ((error = smbnode_lock(VTOSMB(vp), SMBFS_EXCLUSIVE_LOCK))) 6429 return (error); 6430 np = VTOSMB(vp); 6431 np->n_lastvop = smbfs_vnop_removexattr; 6432 share = smb_get_share_with_reference(VTOSMBFS(vp)); 6433 /* 6434 * FILE_NAMED_STREAMS tells us the server supports streams. 6435 * NOTE: This flag may have been overwriten by us in smbfs_mount. The default 6436 * is for streams to be turn off. See the smbfs_mount for more details. 6437 */ 6438 if (!(share->ss_attributes & FILE_NAMED_STREAMS)) { 6439 error = ENOTSUP; 6440 goto exit; 6441 } 6442 6443 /* SMB doesn't support having a slash in the xattr name */ 6444 if (strchr(ap->a_name, '/')) { 6445 error = EINVAL; 6446 SMBWARNING("Slash in xattr name not allowed: error %d %s:%s\n", error, 6447 np->n_name, ap->a_name); 6448 goto exit; 6449 } 6450 6451 sfmname = xattr2sfm(ap->a_name, &stype); 6452 if (!sfmname) { 6453 error = EINVAL; 6454 goto exit; 6455 } 6456 6457 if (stype & kFinderInfo) { 6458 if (VTOSMBFS(vp)->sm_flags & MNT_IS_SFM_VOLUME) { 6459 /* 6460 * We do not allow them to remove the finder info stream on SFM 6461 * Volume. It could hold other information used by SFM. 6462 */ 6463 error = ENOTSUP; 6464 } else { 6465 /* 6466 * If the volume is just a normal NTFS Volume then deleting the named 6467 * stream should be ok, but some servers (EMC) don't support deleting 6468 * the named stream. In this case see if we can just zero out the 6469 * finder info. 6470 */ 6471 error = smbfs_smb_delete(share, np, sfmname, 6472 strnlen(sfmname, share->ss_maxfilenamelen+1), 6473 1, ap->a_context); 6474 } 6475 /* SFM server or the server doesn't support deleting named streams */ 6476 if (error) { 6477 uio_t afp_uio = NULL; 6478 uint8_t afpinfo[60]; 6479 SMBFID fid = 0; 6480 uint32_t rights = SMB2_FILE_WRITE_DATA | SMB2_FILE_READ_DATA | SMB2_FILE_WRITE_ATTRIBUTES; 6481 6482 /* 6483 * Either a SFM volume or the server doesn't support deleting named 6484 * streams. Try to zero out the finder info data. 6485 */ 6486 saved_error = error; /* save original failure error */ 6487 6488 afp_uio = uio_create(1, 0, UIO_SYSSPACE, UIO_READ); 6489 if (!afp_uio) { 6490 error = saved_error; 6491 goto exit; 6492 } 6493 error = uio_addiov( afp_uio, CAST_USER_ADDR_T(afpinfo), sizeof(afpinfo)); 6494 if (error) { 6495 uio_free(afp_uio); 6496 error = saved_error; 6497 goto exit; 6498 } 6499 6500 /* open and read the data */ 6501 error = smbfs_smb_openread(share, np, &fid, rights, afp_uio, NULL, 6502 sfmname, &ts, ap->a_context); 6503 /* clear out the finder info data */ 6504 bzero(&afpinfo[AFP_INFO_FINDER_OFFSET], FINDERINFOSIZE); 6505 6506 if (!error) { 6507 /* truncate the stream, this will wake up SFM */ 6508 error = smbfs_smb_seteof(share, fid, 0, ap->a_context); 6509 } 6510 /* Reset our uio */ 6511 if (!error) { 6512 uio_reset(afp_uio, 0, UIO_SYSSPACE, UIO_WRITE ); 6513 error = uio_addiov( afp_uio, CAST_USER_ADDR_T(afpinfo), sizeof(afpinfo)); 6514 } 6515 6516 if (!error) 6517 error = smb_smb_write(share, fid, afp_uio, 0, ap->a_context); 6518 if (error) { 6519 error = saved_error; /* restore original error */ 6520 } 6521 6522 /* Try to set the modify time back to the original time, ignore any errors */ 6523 (void)smbfs_smb_setfattrNT(share, np->n_dosattr, fid, NULL, &ts, 6524 NULL, ap->a_context); 6525 if (fid != 0) 6526 (void)smbfs_smb_close(share, fid, ap->a_context); 6527 if (afp_uio) { 6528 uio_free(afp_uio); 6529 } 6530 } 6531 } else { 6532 error = smbfs_smb_delete(share, np, sfmname, 6533 strnlen(sfmname, share->ss_maxfilenamelen+1), 6534 1, ap->a_context); 6535 } 6536 6537 /* Finder info so reset our cache timer and zero out our cache */ 6538 if ((stype & kFinderInfo) && !error) { 6539 nanouptime(&ts); 6540 np->finfo_cache = ts.tv_sec; 6541 bzero(np->finfo, sizeof(np->finfo)); 6542 } 6543 6544exit: 6545 6546 if (error == ENOENT) 6547 error = ENOATTR; 6548 6549 /* Check to see if its a normal error */ 6550 if (error && (error != ENOTSUP) && (error != ENOATTR)) { 6551 SMBWARNING("error %d %s:%s\n", error, np->n_name, ap->a_name); 6552 /* Always make sure its a legit error, see man listxattr */ 6553 if ((error != EROFS) && (error != EPERM) && (error != EINVAL) && 6554 (error != ENOTDIR) && (error != EACCES) && (error != ELOOP) && 6555 (error != EFAULT) && (error != EIO) && (error != ENAMETOOLONG)) 6556 error = ENOATTR; /* Not sure what else to do here */ 6557 } 6558 smb_share_rele(share, ap->a_context); 6559 smbnode_unlock(np); 6560 return (error); 6561} 6562 6563/* 6564 * smbfs_vnop_getxattr 6565 * 6566 * vnode_t a_vp; 6567 * int8_t * a_name; 6568 * uio_t a_uio; 6569 * size_t *a_size; 6570 * int32_t a_options; 6571 * vfs_context_t a_context; 6572 */ 6573static int 6574smbfs_vnop_getxattr(struct vnop_getxattr_args *ap) 6575{ 6576 vnode_t vp = ap->a_vp; 6577 const char *sfmname; 6578 uio_t uio = ap->a_uio; 6579 size_t *sizep = ap->a_size; 6580 SMBFID fid = 0; 6581 int error = 0; 6582 struct smbnode *np = NULL; 6583 struct smb_share *share = NULL; 6584 size_t rq_resid = (uio) ? (size_t)uio_resid(uio) : 0; 6585 uio_t afp_uio = NULL; 6586 enum stream_types stype = kNoStream; 6587 struct timespec ts; 6588 time_t attrtimeo; 6589 uint32_t stream_flags = 0; 6590 6591 DBG_ASSERT(!vnode_isnamedstream(vp)); 6592 6593 if ((error = smbnode_lock(VTOSMB(vp), SMBFS_EXCLUSIVE_LOCK))) 6594 return (error); 6595 np = VTOSMB(vp); 6596 np->n_lastvop = smbfs_vnop_getxattr; 6597 share = smb_get_share_with_reference(VTOSMBFS(vp)); 6598 /* 6599 * FILE_NAMED_STREAMS tells us the server supports streams. 6600 * NOTE: This flag may have been overwriten by us in smbfs_mount. The default 6601 * is for streams to be turn off. See the smbfs_mount for more details. 6602 */ 6603 if (!(share->ss_attributes & FILE_NAMED_STREAMS)) { 6604 error = ENOTSUP; 6605 goto exit; 6606 } 6607 6608 /* SMB doesn't support having a slash in the xattr name */ 6609 if (strchr(ap->a_name, '/')) { 6610 error = ENOTSUP; 6611 SMBWARNING("Slash in xattr name not allowed: error %d %s:%s\n", error, 6612 np->n_name, ap->a_name); 6613 goto exit; 6614 } 6615 if (np->n_fstatus & kNO_SUBSTREAMS) { 6616 error = ENOATTR; 6617 goto exit; 6618 } 6619 6620 sfmname = xattr2sfm(ap->a_name, &stype); 6621 if (!sfmname) { 6622 error = EINVAL; 6623 goto exit; 6624 } 6625 6626 /* 6627 * They just want the size of the stream. */ 6628 if ((uio == NULL) && !(stype & kFinderInfo)) { 6629 uint64_t strmsize = 0; 6630 uint64_t strm_alloc_size = 0; 6631 6632 if (stype & kResourceFrk) { 6633 error = smb_get_rsrcfrk_size(share, vp, ap->a_context); 6634 lck_mtx_lock(&np->rfrkMetaLock); 6635 /* The node's rfork size will have the correct value at this point */ 6636 strmsize = np->rfrk_size; 6637 lck_mtx_unlock(&np->rfrkMetaLock); 6638 } 6639 else { 6640 error = smbfs_smb_qstreaminfo(share, np, 6641 NULL, 0, 6642 sfmname, 6643 NULL, NULL, 6644 &strmsize, &strm_alloc_size, 6645 &stream_flags, NULL, 6646 ap->a_context); 6647 } 6648 if (sizep) 6649 *sizep = (size_t)strmsize; 6650 if (error) 6651 error = ENOATTR; 6652 goto exit; 6653 } 6654 6655 /* 6656 * We treat finder info differently than any other EA/Stream. Because of SFM 6657 * we need to do things a little different. Remember the AFPInfo stream has 6658 * more information in it than just the finder info. WARNING: SFM can get 6659 * very confused if you do not handle this correctly! 6660 */ 6661 if (stype & kFinderInfo) { 6662 SMB_CACHE_TIME(ts, np, attrtimeo); 6663 /* Cache has expired go get the finder information. */ 6664 if ((ts.tv_sec - np->finfo_cache) > attrtimeo) { 6665 size_t afpsize = 0; 6666 uint8_t afpinfo[60]; 6667 6668 afp_uio = uio_create(1, 0, UIO_SYSSPACE, UIO_READ); 6669 if (afp_uio) 6670 error = uio_addiov( afp_uio, CAST_USER_ADDR_T(afpinfo), 6671 sizeof(afpinfo)); 6672 else error = ENOMEM; 6673 6674 if (error) 6675 goto exit; 6676 6677 uio_setoffset(afp_uio, 0); 6678 /* open and read the data */ 6679 error = smbfs_smb_openread(share, np, &fid, SMB2_FILE_READ_DATA, 6680 afp_uio, &afpsize, sfmname, NULL, 6681 ap->a_context); 6682 /* Should never happen but just in case */ 6683 if (afpsize != AFP_INFO_SIZE) 6684 error = ENOENT; 6685 6686 if (error == ENOENT) { 6687 bzero(np->finfo, sizeof(np->finfo)); 6688 } else { 6689 bcopy((void *)&afpinfo[AFP_INFO_FINDER_OFFSET], np->finfo, 6690 sizeof(np->finfo)); 6691 } 6692 if (vnode_isreg(vp) && (bcmp(np->finfo, "brokMACS", 8) == 0)) { 6693 np->finfo_cache = 0; 6694 SMBDEBUG("Don't cache finder info, we have a finder copy in progress\n"); 6695 } else { 6696 nanouptime(&ts); 6697 np->finfo_cache = ts.tv_sec; 6698 } 6699 } 6700 /* If the finder info is all zero hide it, except if its a SFM volume */ 6701 if ((!(VTOSMBFS(vp)->sm_flags & MNT_IS_SFM_VOLUME)) && 6702 (bcmp(np->finfo, emptyfinfo, sizeof(emptyfinfo)) == 0)) { 6703 error = ENOENT; 6704 } 6705 if (uio && !error) { 6706 error = uiomove((const char *)np->finfo, (int)sizeof(np->finfo), ap->a_uio); 6707 } 6708 if (sizep && !error) 6709 *sizep = FINDERINFOSIZE; 6710 } else { 6711 error = smbfs_smb_openread(share, np, &fid, SMB2_FILE_READ_DATA, uio, 6712 sizep, sfmname, NULL, ap->a_context); 6713 } 6714 /* If ENOTSUP support is returned then do the open and read in two transactions. */ 6715 if (error != ENOTSUP) 6716 goto out; 6717 6718 /* 6719 * May need to add an oplock to this open call, if this is a finder info open. 6720 * Not sure I remember the exact details, something about deletes. 6721 */ 6722 error = smbfs_smb_open_xattr(share, np, SMB2_FILE_READ_DATA, 6723 NTCREATEX_SHARE_ACCESS_ALL, &fid, 6724 sfmname, sizep, ap->a_context); 6725 if (error) 6726 goto exit; 6727 6728 /* 6729 * When reading finder-info, munge the uio so we read at offset 16 where the 6730 * actual finder info is located. Also ensure we don't read past the 32 bytes, 6731 * of finder info. Since we are just reading we really don't care about the 6732 * rest of the data. 6733 * This is only here in case a server does not support the chain message above. 6734 * We do not cache in this case. Should never happen, but just to be safe. 6735 */ 6736 if (stype & kFinderInfo) { 6737 user_ssize_t r; 6738 6739 if (sizep) 6740 *sizep = FINDERINFOSIZE; 6741 /* Just wanted the size get out */ 6742 if (uio == NULL) 6743 goto out; 6744 6745 r = uio_resid(uio); 6746 if (uio_offset(uio) >= FINDERINFOSIZE) { 6747 uio_setresid(uio, 0); 6748 } else if (uio_offset(uio) + r > FINDERINFOSIZE) 6749 uio_setresid(uio, FINDERINFOSIZE - uio_offset(uio)); 6750 r = r - uio_resid(uio); 6751 uio_setoffset(uio, uio_offset(uio) + 4*4); 6752 6753 error = smb_smb_read(share, fid, uio, ap->a_context); 6754 6755 uio_setoffset(uio, uio_offset(uio) - 4*4); 6756 uio_setresid(uio, uio_resid(uio) + r); 6757 } 6758 else error = smb_smb_read(share, fid, uio, ap->a_context); 6759 6760out:; 6761 if (uio && sizep && (*sizep > rq_resid)) 6762 error = ERANGE; 6763 6764 /* Even an error can leave the file open. */ 6765 if (fid != 0) 6766 (void)smbfs_smb_close(share, fid, ap->a_context); 6767exit: 6768 /* 6769 * So ENOENT just means ENOATTR. 6770 * Note: SAMBA 4 will reutrn EISDIR for folders which is legit, but not 6771 * expected by the finder 6772 */ 6773 if ((error == ENOENT) || ((error == EISDIR) && (stype & kFinderInfo))) 6774 error = ENOATTR; 6775 6776 if (afp_uio) 6777 uio_free(afp_uio); 6778 6779 /* Check to see if its a normal error */ 6780 if (error && (error != ENOTSUP) && (error != ENOATTR)) { 6781 SMBWARNING("error %d %s:%s\n", error, np->n_name, ap->a_name); 6782 /* Nope make sure its a legit error, see man getxattr */ 6783 if ((error != ERANGE) && (error != EPERM) && (error != EINVAL) && 6784 (error != EISDIR) && (error != ENOTDIR) && (error != EACCES) && 6785 (error != ELOOP) && (error != EFAULT) && (error != EIO)) 6786 error = ENOATTR; 6787 } 6788 smb_share_rele(share, ap->a_context); 6789 smbnode_unlock(np); 6790 return (error); 6791} 6792 6793/* 6794 * smbfs_vnop_getnamedstream - Obtain the vnode for a stream. 6795 * 6796 * vnode_t a_vp; 6797 * vnode_t *a_svpp; 6798 * const char *a_name; 6799 enum nsoperation a_operation; (NS_OPEN, NS_CREATE, NS_DELETE) 6800 * vfs_context_t a_context; 6801 * 6802 */ 6803static int 6804smbfs_vnop_getnamedstream(struct vnop_getnamedstream_args* ap) 6805{ 6806 struct smb_share *share; 6807 vnode_t vp = ap->a_vp; 6808 vnode_t *svpp = ap->a_svpp; 6809 const char * streamname = ap->a_name; 6810 const char * sname = ap->a_name; 6811 struct smbnode *np = NULL; 6812 int error = 0; 6813 uint64_t strmsize = 0; 6814 uint64_t strm_alloc_size = 0; 6815 struct smbfattr fattr; 6816 struct vnode_attr vap; 6817 struct timespec ts; 6818 time_t attrtimeo; 6819 struct timespec reqtime; 6820 uint32_t stream_flags = 0; 6821 6822 /* Lock the parent while we look for the stream */ 6823 if ((error = smbnode_lock(VTOSMB(vp), SMBFS_EXCLUSIVE_LOCK))) 6824 return (error); 6825 6826 nanouptime(&reqtime); 6827 np = VTOSMB(vp); 6828 np->n_lastvop = smbfs_vnop_getnamedstream; 6829 share = smb_get_share_with_reference(VTOSMBFS(vp)); 6830 6831 *svpp = NULL; 6832 /* Currently we only support the "com.apple.ResourceFork" stream. */ 6833 if (bcmp(streamname, XATTR_RESOURCEFORK_NAME, sizeof(XATTR_RESOURCEFORK_NAME)) != 0) { 6834 SMBDEBUG("Wrong stream %s:$%s\n", np->n_name, streamname); 6835 error = ENOATTR; 6836 goto exit; 6837 } else { 6838 sname = SFM_RESOURCEFORK_NAME; /* This is the resource stream use the SFM name */ 6839 } 6840 if ( !vnode_isreg(vp) ) { 6841 SMBDEBUG("%s not a file (EPERM)\n", np->n_name); 6842 error = EPERM; 6843 goto exit; 6844 } 6845 6846 /* 6847 * %%% 6848 * Since we have the parent node update its meta cache. Remember that 6849 * smbfs_getattr will check to see if the cache has expired. May want to 6850 * look at this and see how it affects performance. 6851 */ 6852 VATTR_INIT(&vap); /* Really don't care about the vap */ 6853 error = smbfs_getattr(share, vp, &vap, ap->a_context); 6854 if (error) { 6855 SMBERROR("%s lookup failed %d\n", np->n_name, error); 6856 goto exit; 6857 } 6858 6859 /* 6860 * If we already have the stream vnode in our hash table and its cache timer 6861 * has not expired then just return we are done. 6862 */ 6863 if ((*svpp = smbfs_find_vgetstrm(VTOSMBFS(vp), np, sname, 6864 share->ss_maxfilenamelen)) != NULL) { 6865 VTOSMB(*svpp)->n_mtime = np->n_mtime; /* update the modify time */ 6866 SMB_CACHE_TIME(ts, VTOSMB(*svpp), attrtimeo); 6867 if ((ts.tv_sec - VTOSMB(*svpp)->attribute_cache_timer) <= attrtimeo) 6868 goto exit; /* The cache is up to date, we are done */ 6869 } 6870 6871 /* 6872 * Lookup the stream and get its size. This call will fail if the server 6873 * tells us the stream does not exist. 6874 * 6875 * NOTE1: If this is the resource stream then making this call will update 6876 * the the data fork node's resource size and its resource cache timer. 6877 * 6878 * NOTE2: SAMBA will not return the resource stream if the size is zero. 6879 * 6880 * NOTE3: We always try to create the stream on an open. Because of note two. 6881 * 6882 * If smbfs_smb_qstreaminfo returns an error and we do not have the stream 6883 * node in our hash table then it doesn't exist and they will have to create 6884 * it. 6885 * 6886 * If smbfs_smb_qstreaminfo returns an error and we do have the stream node 6887 * in our hash table then it could exist so just pretend that it does for 6888 * now. If they try to open it and it doesn't exist the open will create it. 6889 * 6890 * If smbfs_smb_qstreaminfo returns no error and we do have the stream node 6891 * in our hash table then just update its size and cache timers. 6892 * 6893 * If smbfs_smb_qstreaminfo returns no error and we do not have the stream 6894 * node in our hash table then create the stream node, using the data node 6895 * to fill in all information except the size. 6896 */ 6897 if ((smbfs_smb_qstreaminfo(share, np, 6898 NULL, 0, 6899 sname, 6900 NULL, NULL, 6901 &strmsize, &strm_alloc_size, 6902 &stream_flags, NULL, 6903 ap->a_context)) && (*svpp == NULL)) { 6904 error = ENOATTR; 6905 goto exit; 6906 } 6907 /* 6908 * We already have the stream vnode. If it doesn't exist we will attempt to 6909 * create it on the open. In the SMB open you can say create it if it does 6910 * not exist. Reset the size if the above called failed then set the size to 6911 * zero. 6912 */ 6913 if (*svpp) { 6914 if (smbfs_update_size(VTOSMB(*svpp), &reqtime, strmsize) == TRUE) { 6915 /* Remember the only attribute for a stream is its size */ 6916 nanouptime(&ts); 6917 VTOSMB(*svpp)->attribute_cache_timer = ts.tv_sec; 6918 } 6919 goto exit; /* We have everything we need, so we are done */ 6920 } 6921 6922 bzero(&fattr, sizeof(fattr)); 6923 fattr.fa_vtype = VREG; /* Streams are always regular files */ 6924 fattr.fa_size = strmsize; /* Fill in the stream size */ 6925 fattr.fa_data_alloc = 0; /* %%% not sure this really matters */ 6926 /* Now for the rest of the information we just use the data node information */ 6927 fattr.fa_attr = np->n_dosattr; 6928 fattr.fa_atime = np->n_atime; /* Access Time */ 6929 fattr.fa_chtime = np->n_chtime; /* Change Time */ 6930 fattr.fa_mtime = np->n_mtime; /* Modify Time */ 6931 fattr.fa_crtime = np->n_crtime; /* Create Time */ 6932 /* Stream inode number has same inode number as data node */ 6933 fattr.fa_ino = np->n_ino; 6934 nanouptime(&fattr.fa_reqtime); 6935 error = smbfs_vgetstrm(share, VTOSMBFS(vp), vp, svpp, &fattr, sname); 6936 6937exit: 6938 if (*svpp) 6939 smbnode_unlock(VTOSMB(*svpp)); /* We are done with the node unlock it. */ 6940 6941 if (error && (error != ENOATTR)) { 6942 SMBWARNING(" %s:$%s Original Stream name %s error = %d\n", np->n_name, 6943 sname, streamname, error); 6944 } 6945 smb_share_rele(share, ap->a_context); 6946 smbnode_unlock(np); 6947 return (error); 6948} 6949 6950/* 6951 * smbfs_vnop_makenamedstream - Create a stream. 6952 * 6953 * vnode_t a_vp; 6954 * vnode_t *a_svpp; 6955 * const char *a_name; 6956 * vfs_context_t a_context; 6957 */ 6958static int 6959smbfs_vnop_makenamedstream(struct vnop_makenamedstream_args* ap) 6960{ 6961 struct smb_share *share; 6962 vnode_t vp = ap->a_vp; 6963 vnode_t *svpp = ap->a_svpp; 6964 const char * streamname = ap->a_name; 6965 struct smbnode *np = NULL; 6966 int error = 0; 6967 struct smbfattr fattr; 6968 struct timespec ts; 6969 int rsrcfrk = FALSE; 6970 size_t max_name_len; 6971 6972 /* Lock the parent while we create the stream */ 6973 if ((error = smbnode_lock(VTOSMB(vp), SMBFS_EXCLUSIVE_LOCK))) 6974 return (error); 6975 np = VTOSMB(vp); 6976 np->n_lastvop = smbfs_vnop_makenamedstream; 6977 share = smb_get_share_with_reference(VTOSMBFS(vp)); 6978 6979 *svpp = NULL; 6980 /* Currently we only support the "com.apple.ResourceFork" stream. */ 6981 if (bcmp(streamname, XATTR_RESOURCEFORK_NAME, 6982 sizeof(XATTR_RESOURCEFORK_NAME)) != 0) { 6983 SMBDEBUG("Wrong stream %s:$%s\n", np->n_name, streamname); 6984 /* max_name_len = strnlen(streamname, share->ss_maxfilenamelen+1) */ 6985 error = ENOATTR; 6986 goto exit; 6987 } else { 6988 max_name_len = sizeof(XATTR_RESOURCEFORK_NAME); 6989 /* This is the resource stream use the SFM name */ 6990 streamname = SFM_RESOURCEFORK_NAME; 6991 } 6992 6993 if ( !vnode_isreg(vp) ) { 6994 SMBDEBUG("%s not a file (EPERM)\n", np->n_name); 6995 error = EPERM; 6996 goto exit; 6997 } 6998 6999 /* Now create the stream, sending a null fid pointer will cause it to be closed */ 7000 error = smbfs_smb_create(share, np, streamname, max_name_len, 7001 SMB2_FILE_WRITE_DATA, NULL, 7002 FILE_OPEN_IF, 1, &fattr, ap->a_context); 7003 if (error) 7004 goto exit; 7005 7006 /* We create a named stream, so remove the no stream flag */ 7007 np->n_fstatus &= ~kNO_SUBSTREAMS; 7008 7009 /* Stream inode number has same inode number as data node */ 7010 fattr.fa_ino = np->n_ino; 7011 7012 error = smbfs_vgetstrm(share, VTOSMBFS(vp), vp, svpp, &fattr, streamname); 7013 if (error == 0) { 7014 if (rsrcfrk) /* Update the data nodes resource size */ { 7015 lck_mtx_lock(&np->rfrkMetaLock); 7016 np->rfrk_size = fattr.fa_size; 7017 /* assume alloc size is the same */ 7018 np->rfrk_alloc_size = fattr.fa_size; 7019 nanouptime(&ts); 7020 np->rfrk_cache_timer = ts.tv_sec; 7021 lck_mtx_unlock(&np->rfrkMetaLock); 7022 } 7023 smbnode_unlock(VTOSMB(*svpp)); /* Done with the smbnode unlock it. */ 7024 } 7025 7026exit: 7027 if (error) 7028 SMBWARNING(" %s:$%s error = %d\n", np->n_name, streamname, error); 7029 smb_share_rele(share, ap->a_context); 7030 smbnode_unlock(np); 7031 return (error); 7032} 7033 7034/* 7035 * smbfs_vnop_removenamedstream - Remove a stream. 7036 * 7037 * vnode_t a_vp; 7038 * vnode_t a_svpp; 7039 * const char *a_name; 7040 * vfs_context_t a_context; 7041 */ 7042static int 7043smbfs_vnop_removenamedstream(struct vnop_removenamedstream_args* ap) 7044{ 7045 vnode_t vp = ap->a_vp; 7046 vnode_t svp = ap->a_svp; 7047 const char * streamname = ap->a_name; 7048 struct smbnode *np = NULL; 7049 int error = 0; 7050 size_t max_name_len; 7051 struct smb_share *share = NULL; 7052 7053 7054 /* Lock the parent and stream while we delete the stream*/ 7055 if ((error = smbnode_lockpair(VTOSMB(vp), VTOSMB(svp), SMBFS_EXCLUSIVE_LOCK))) 7056 return (error); 7057 np = VTOSMB(svp); 7058 np->n_lastvop = smbfs_vnop_removenamedstream; 7059 share = smb_get_share_with_reference(VTOSMBFS(vp)); 7060 /* Currently we only support the "com.apple.ResourceFork" stream. */ 7061 if (bcmp(streamname, XATTR_RESOURCEFORK_NAME, sizeof(XATTR_RESOURCEFORK_NAME)) != 0) { 7062 SMBDEBUG("Wrong stream %s:$%s\n", np->n_name, streamname); 7063 /* max_name_len = strnlen(streamname, share->ss_maxfilenamelen+1) */ 7064 error = ENOATTR; 7065 goto exit; 7066 } else { 7067 max_name_len = sizeof(XATTR_RESOURCEFORK_NAME); 7068 /* This is the resource stream use the SFM name */ 7069 streamname = SFM_RESOURCEFORK_NAME; 7070 } 7071 7072 if ( !vnode_isreg(vp) ) { 7073 SMBDEBUG("%s not a file (EPERM)\n", np->n_name); 7074 error = EPERM; 7075 goto exit; 7076 } 7077 error = smbfs_smb_delete(share, np, streamname, max_name_len, TRUE, 7078 ap->a_context); 7079 if (!error) 7080 smb_vhashrem(np); 7081exit: 7082 if (error) 7083 SMBWARNING(" %s:$%s error = %d\n", np->n_name, streamname, error); 7084 smb_share_rele(share, ap->a_context); 7085 smbnode_unlockpair(VTOSMB(vp), VTOSMB(svp)); 7086 return (error); 7087} 7088 7089/* 7090 * smbfs_vnop_monitor - Monitor an item. 7091 * 7092 * vnode_t a_vp; 7093 * uint32_t a_unused_events; - not used currently 7094 * uint32_t a_flags; 7095 * VNODE_MONITOR_BEGIN - setup notfication 7096 * VNODE_MONITOR_END - remove notfication 7097 * VNODE_MONITOR_UPDATE - change 7098 * void *a_handle; 7099 * struct knote * 7100 * vfs_context_t a_context; 7101 * 7102 */ 7103static int 7104smbfs_vnop_monitor(struct vnop_monitor_args *ap) 7105{ 7106 struct smbnode *np; 7107 struct smb_share *share = NULL; 7108 int error = 0; 7109 int releaseLock = TRUE; 7110 7111 /* Currently we only support directories */ 7112 if (! vnode_isdir(ap->a_vp)) { 7113 SMBDEBUG("%s is not a directory (ENOTSUP): node type = 0x%0x a_events = 0x%x, a_flags = 0x%x, a_handle = %p\n", 7114 VTOSMB(ap->a_vp)->n_name, vnode_vtype(ap->a_vp), 7115 ap->a_events, ap->a_flags, ap->a_handle); 7116 return ENOTSUP; 7117 } 7118 7119 if ((error = smbnode_lock(VTOSMB(ap->a_vp), SMBFS_EXCLUSIVE_LOCK))) 7120 return (error); 7121 7122 np = VTOSMB(ap->a_vp); 7123 np->n_lastvop = smbfs_vnop_monitor; 7124 share = smb_get_share_with_reference(VTOSMBFS(ap->a_vp)); 7125 SMBDEBUG("%s a_events = 0x%x, a_flags = 0x%x, a_handle = %p\n", 7126 np->n_name, ap->a_events, ap->a_flags, ap->a_handle); 7127 7128 switch (ap->a_flags) { 7129 case VNODE_MONITOR_BEGIN: 7130 error = smbfs_start_change_notify(share, np, ap->a_context, 7131 &releaseLock); 7132 break; 7133 case VNODE_MONITOR_END: 7134 error = smbfs_stop_change_notify(share, np, FALSE, ap->a_context, 7135 &releaseLock); 7136 break; 7137 case VNODE_MONITOR_UPDATE: /* We no longer get called to update */ 7138 default: 7139 error = ENOTSUP; 7140 break; 7141 } 7142 smb_share_rele(share, ap->a_context); 7143 if (releaseLock) 7144 smbnode_unlock(VTOSMB(ap->a_vp)); 7145 return error; 7146} 7147 7148/* 7149 * smbfs_vnop_access - Check for access 7150 * 7151 * vnode_t a_vp; 7152 * int32_t a_action; 7153 * vfs_context_t a_context; 7154 * 7155 */ 7156static int 7157smbfs_vnop_access(struct vnop_access_args *ap) 7158{ 7159 vnode_t vp = ap->a_vp; 7160 int32_t action = ap->a_action, write_rights; 7161 vfs_context_t context = ap->a_context; 7162 kauth_cred_t cred = vfs_context_ucred(context); 7163 struct smbmount *smp = VTOSMBFS(vp); 7164 struct smb_share *share; 7165 uint32_t maxAccessRights; 7166 int error = 0; 7167 7168 share = smb_get_share_with_reference(VTOSMBFS(vp)); 7169 /* 7170 * Not the root user, not the user that mounted the volume and the volume 7171 * wasn't mounted as guest then refuse all access. 7172 */ 7173 if ((vfs_context_suser(context) != 0) && 7174 (kauth_cred_getuid(cred) != smp->sm_args.uid) && 7175 !SMBV_HAS_GUEST_ACCESS(SSTOVC(share))) { 7176 SMB_LOG_ACCESS("%d not authorized to access %s : action = 0x%x\n", 7177 kauth_cred_getuid(cred), VTOSMB(vp)->n_name, action); 7178 error = EACCES; 7179 goto done; 7180 } 7181 7182 /* 7183 * If KAUTH_VNODE_ACCESS is not set then this is an authoritative request, 7184 * we can't answer those correctly so always grant access. Now if they are 7185 * asking about excute we should do some extra checking. If we have excute or 7186 * read access then grant it otherwise fail the access request. 7187 */ 7188 if (((action & KAUTH_VNODE_ACCESS) != KAUTH_VNODE_ACCESS) && 7189 (((action & KAUTH_VNODE_EXECUTE) != KAUTH_VNODE_EXECUTE) || 7190 (!vnode_isreg(vp)))) { 7191 goto done; 7192 } 7193 7194 /* Deal with the immutable bit, never allow write, delete or security changes. */ 7195 write_rights = KAUTH_VNODE_WRITE_RIGHTS; 7196 /* Allow them to change the immutable, if they own it, we always allow */ 7197 write_rights &= ~(KAUTH_VNODE_WRITE_ATTRIBUTES | KAUTH_VNODE_WRITE_EXTATTRIBUTES); 7198 /* Remove this one, we allow access if its set */ 7199 write_rights &= ~KAUTH_VNODE_CHECKIMMUTABLE; 7200 if (node_isimmutable(share, vp) && (action & write_rights)) { 7201 SMB_LOG_ACCESS("%s action = 0x%x %s denied\n", VTOSMB(vp)->n_name, action, 7202 vnode_isdir(vp) ? "IMMUTABLE_DIR" : "IMMUTABLE_FILE"); 7203 error = EPERM; 7204 goto done; 7205 } 7206 7207 /* 7208 * Windows FAT file systems have no access check, so always grant access and 7209 * let the server make the final call. We could have some strange server that 7210 * supports ACLs on a FAT file system or has some kind of access model. See 7211 * FAT on a UNIX/Mac. In that case lets see if they are returning the correct 7212 * maximal access. 7213 */ 7214 if ((share->ss_fstype == SMB_FS_FAT) && 7215 ((share->ss_attributes & FILE_PERSISTENT_ACLS) != FILE_PERSISTENT_ACLS)) { 7216 SMB_LOG_ACCESS("FAT: Access call not supported by server\n"); 7217 goto done; 7218 } 7219 /* 7220 * We were mounted with guest access. 7221 * 7222 * 1. We turn off ACLs if mounted as guest. Without ACLs we can't determine 7223 * maximal access with Samba that includes our version. So in the samba 7224 * case we always ask the server for the check. 7225 * 2. Windows return us the correct maximal access, so we can return the 7226 * the correct value in that case. 7227 * 7228 */ 7229#ifdef SMB_DEBUG_ACCESS 7230 if (SMBV_HAS_GUEST_ACCESS(SSTOVC(share))) { 7231 SMB_LOG_ACCESS("SMBV_GUEST_ACCESS: %s action = 0x%x\n", 7232 VTOSMB(vp)->n_name, action); 7233 } else { 7234 SMB_LOG_ACCESS("%s action = 0x%x\n", VTOSMB(vp)->n_name, action); 7235 } 7236#endif // SMB_DEBUG_ACCESS 7237 7238 /* 7239 * They are asking about a stream, how do we want to handle stream 7240 * nodes. Windows will return this in the open, but we would need to change 7241 * the open call to support getting it on stream.Streams have the same access 7242 * as the parent (data stream). So lets get the parent and return whatever 7243 * the parent supports. 7244 */ 7245 if (vnode_isnamedstream(vp)) { 7246 vnode_t parent_vp = vnode_getparent(vp); 7247 if (!parent_vp) 7248 return 0; /* Can't get the parent, let the server make the call */ 7249 maxAccessRights = smbfs_get_maximum_access(share, parent_vp, context); 7250 vnode_put(parent_vp); 7251 } else { 7252 maxAccessRights = smbfs_get_maximum_access(share, vp, context); 7253 } 7254 7255 /* KAUTH_VNODE_READ_DATA for files and KAUTH_VNODE_LIST_DIRECTORY for directories */ 7256 if ((action & KAUTH_VNODE_READ_DATA) && 7257 ((maxAccessRights & SMB2_FILE_READ_DATA) != SMB2_FILE_READ_DATA)) { 7258 SMB_LOG_ACCESS("%s action = 0x%x %s denied\n", VTOSMB(vp)->n_name, action, 7259 vnode_isdir(vp) ? "KAUTH_VNODE_LIST_DIRECTORY" : "KAUTH_VNODE_READ_DATA"); 7260 error = EACCES; 7261 goto done; 7262 } 7263 /* KAUTH_VNODE_WRITE_DATA for files and KAUTH_VNODE_ADD_FILE for directories */ 7264 if ((action & KAUTH_VNODE_WRITE_DATA) && 7265 ((maxAccessRights & SMB2_FILE_WRITE_DATA) != SMB2_FILE_WRITE_DATA)) { 7266 SMB_LOG_ACCESS("%s action = 0x%x %s denied\n", VTOSMB(vp)->n_name, action, 7267 vnode_isdir(vp) ? "KAUTH_VNODE_ADD_FILE" : "KAUTH_VNODE_WRITE_DATA"); 7268 error = EACCES; 7269 goto done; 7270 } 7271 7272 /* KAUTH_VNODE_EXECUTE for files and KAUTH_VNODE_SEARCH for directories */ 7273 if (action & KAUTH_VNODE_EXECUTE) { 7274 if ((vnode_isdir(vp)) && 7275 ((maxAccessRights & SMB2_FILE_TRAVERSE) != SMB2_FILE_TRAVERSE) && 7276 ((maxAccessRights & SMB2_FILE_LIST_DIRECTORY) != SMB2_FILE_LIST_DIRECTORY)) { 7277 /* 7278 * See <rdar://problem/11151288> for more details, we use to require 7279 * SMB2_FILE_TRAVERSE for granting directory search access, but now 7280 * we also accept SMB2_FILE_LIST_DIRECTORY as well. 7281 */ 7282 SMB_LOG_ACCESS("%s action = 0x%x KAUTH_VNODE_SEARCH denied\n", VTOSMB(vp)->n_name, action); 7283 error = EACCES; 7284 goto done; 7285 } else if (!vnode_isdir(vp) && 7286 ((maxAccessRights & SMB2_FILE_EXECUTE) != SMB2_FILE_EXECUTE)) { 7287 /* 7288 * If this authoritative request and they have execute or read access 7289 * then grant the access. 7290 */ 7291 if (((action & KAUTH_VNODE_ACCESS) != KAUTH_VNODE_ACCESS) && 7292 ((maxAccessRights & SMB2_FILE_READ_DATA) == SMB2_FILE_READ_DATA)) { 7293 goto done; 7294 } 7295 7296 /* 7297 * See <rdar://problem/7327306> for more details, but we use to say 7298 * if the file had read access let them have execute access. Not sure 7299 * why I did that and it broke <rdar://problem/7327306> so removing 7300 * that check. 7301 */ 7302 SMB_LOG_ACCESS("%s action = 0x%x SMB2_FILE_EXECUTE denied\n", 7303 VTOSMB(vp)->n_name, action); 7304 error = EACCES; 7305 goto done; 7306 } 7307 } 7308 if ((action & KAUTH_VNODE_DELETE) && 7309 ((maxAccessRights & SMB2_DELETE) != SMB2_DELETE)) { 7310 SMB_LOG_ACCESS("%s action = 0x%x KAUTH_VNODE_DELETE denied\n", 7311 VTOSMB(vp)->n_name, action); 7312 error = EACCES; 7313 goto done; 7314 } 7315 /* KAUTH_VNODE_APPEND_DATA for files and KAUTH_VNODE_ADD_SUBDIRECTORY for directories */ 7316 if ((action & KAUTH_VNODE_APPEND_DATA) && 7317 ((maxAccessRights & SMB2_FILE_APPEND_DATA) != SMB2_FILE_APPEND_DATA)) { 7318 SMB_LOG_ACCESS("%s action = 0x%x %s denied\n", VTOSMB(vp)->n_name, action, 7319 vnode_isdir(vp) ? "KAUTH_VNODE_ADD_SUBDIRECTORY" : "KAUTH_VNODE_APPEND_DATA"); 7320 error = EACCES; 7321 goto done; 7322 } 7323#ifdef SMB_DEBUG_ACCESS 7324 /* Need to look at this some more, seems Apple and MS don't argree on this SMB2_FILE_DELETE_CHILD */ 7325 if ((action & KAUTH_VNODE_DELETE_CHILD) && 7326 ((maxAccessRights & SMB2_FILE_DELETE_CHILD) != SMB2_FILE_DELETE_CHILD)) { 7327 SMB_LOG_ACCESS("%s action = 0x%x 0x%x KAUTH_VNODE_DELETE_CHILD should denied\n", 7328 VTOSMB(vp)->n_name, action, KAUTH_VNODE_DELETE_CHILD); 7329 } 7330 /* 7331 * Need to look at this some more, seems Apple and MS don't argree on what 7332 * KAUTH_VNODE_READ_ATTRIBUTES allows and doesn't allow. Window still 7333 * allow us to get some meta data? 7334 */ 7335 if ((action & KAUTH_VNODE_READ_ATTRIBUTES) && 7336 ((maxAccessRights & SMB2_FILE_READ_ATTRIBUTES) != SMB2_FILE_READ_ATTRIBUTES)) { 7337 SMB_LOG_ACCESS("%s action = 0x%x 0x%x KAUTH_VNODE_READ_ATTRIBUTES should denied\n", 7338 VTOSMB(vp)->n_name, action, KAUTH_VNODE_READ_ATTRIBUTES); 7339 } 7340#endif // SMB_DEBUG_ACCESS 7341 if ((action & KAUTH_VNODE_WRITE_ATTRIBUTES) && 7342 ((maxAccessRights & SMB2_FILE_WRITE_ATTRIBUTES) != SMB2_FILE_WRITE_ATTRIBUTES)) { 7343 SMB_LOG_ACCESS("%s action = 0x%x KAUTH_VNODE_WRITE_ATTRIBUTES denied\n", 7344 VTOSMB(vp)->n_name, action); 7345 error = EACCES; 7346 goto done; 7347 } 7348 if ((action & KAUTH_VNODE_READ_EXTATTRIBUTES) && 7349 ((maxAccessRights & SMB2_FILE_READ_ATTRIBUTES) != SMB2_FILE_READ_ATTRIBUTES)) { 7350 SMB_LOG_ACCESS("%s action = 0x%x KAUTH_VNODE_READ_EXTATTRIBUTES denied\n", 7351 VTOSMB(vp)->n_name, action); 7352 error = EACCES; 7353 goto done; 7354 } 7355 if ((action & KAUTH_VNODE_WRITE_EXTATTRIBUTES) && 7356 ((maxAccessRights & SMB2_FILE_WRITE_ATTRIBUTES) != SMB2_FILE_WRITE_ATTRIBUTES)) { 7357 SMB_LOG_ACCESS("%s action = 0x%x KAUTH_VNODE_WRITE_EXTATTRIBUTES denied\n", 7358 VTOSMB(vp)->n_name, action); 7359 error = EACCES; 7360 goto done; 7361 } 7362 if ((action & KAUTH_VNODE_READ_SECURITY) && 7363 ((maxAccessRights & SMB2_READ_CONTROL) != SMB2_READ_CONTROL)) { 7364 SMB_LOG_ACCESS("%s action = 0x%x KAUTH_VNODE_READ_SECURITY denied\n", 7365 VTOSMB(vp)->n_name, action); 7366 error = EACCES; 7367 goto done; 7368 } 7369 /* Check to see if the share acls allow access */ 7370 if ((action & KAUTH_VNODE_WRITE_SECURITY) && 7371 ((share->maxAccessRights & SMB2_WRITE_DAC) != SMB2_WRITE_DAC)) { 7372 SMB_LOG_ACCESS("%s action = 0x%x KAUTH_VNODE_WRITE_SECURITY denied by Share ACL\n", 7373 VTOSMB(vp)->n_name, action); 7374 error = EACCES; 7375 goto done; 7376 } 7377 /* Check to see if the share acls allow access */ 7378 if ((action & KAUTH_VNODE_TAKE_OWNERSHIP) && 7379 ((share->maxAccessRights & SMB2_WRITE_OWNER) != SMB2_WRITE_OWNER)) { 7380 SMB_LOG_ACCESS("%s action = 0x%x SHARE KAUTH_VNODE_TAKE_OWNERSHIP by Share ACL\n", 7381 VTOSMB(vp)->n_name, action); 7382 error = EACCES; 7383 goto done; 7384 } 7385 if ((action & KAUTH_VNODE_WRITE_SECURITY) && 7386 ((maxAccessRights & SMB2_WRITE_DAC) != SMB2_WRITE_DAC)) { 7387 SMB_LOG_ACCESS("%s action = 0x%x KAUTH_VNODE_WRITE_SECURITY denied\n", 7388 VTOSMB(vp)->n_name, action); 7389 error = EACCES; 7390 goto done; 7391 } 7392 if ((action & KAUTH_VNODE_TAKE_OWNERSHIP) && 7393 ((maxAccessRights & SMB2_WRITE_OWNER) != SMB2_WRITE_OWNER)) { 7394 SMB_LOG_ACCESS("%s action = 0x%x KAUTH_VNODE_TAKE_OWNERSHIP denied\n", 7395 VTOSMB(vp)->n_name, action); 7396 error = EACCES; 7397 goto done; 7398 } 7399done: 7400 if (error) { 7401 SMB_LOG_ACCESS("%s action = 0x%x denied\n", VTOSMB(vp)->n_name, action); 7402 } 7403 smb_share_rele(share, ap->a_context); 7404 return error; 7405} 7406 7407 7408/* 7409 * smbfs_vnop_allocate - 7410 * 7411 * vnode_t a_vp; 7412 * off_t a_length; 7413 * u_int32_t a_flags; 7414 * off_t *a_bytesallocated; 7415 * off_t a_offset; 7416 * vfs_context_t a_context; 7417 * 7418 */ 7419static int 7420smbfs_vnop_allocate(struct vnop_allocate_args *ap) 7421{ 7422 vnode_t vp = ap->a_vp; 7423 u_int64_t length = (u_int64_t)ap->a_length; 7424 struct smbnode *np; 7425 int32_t error = 0; 7426 SMBFID fid = 0; 7427 7428 *(ap->a_bytesallocated) = 0; 7429 7430 /* Preflight checks */ 7431 if (!vnode_isreg(vp)) { 7432 /* can only read regular files */ 7433 if (vnode_isdir(vp)) 7434 return (EISDIR); 7435 else 7436 return (EPERM); 7437 } 7438 7439 if ((error = smbnode_lock(VTOSMB(vp), SMBFS_EXCLUSIVE_LOCK))) { 7440 return (error); 7441 } 7442 np = VTOSMB(vp); 7443 np->n_lastvop = smbfs_vnop_allocate; 7444 7445 if ((ap->a_flags & ALLOCATEFROMVOL) && (length < np->n_size)) { 7446 error = EINVAL; 7447 goto done; 7448 } 7449 if (ap->a_flags & ALLOCATEFROMPEOF) { 7450 if (length > (UINT32_MAX - np->n_size)) { 7451 error = EINVAL; 7452 goto done; 7453 } 7454 length += np->n_size; 7455 } 7456 7457 if (FindFileRef(vp, vfs_context_proc(ap->a_context), kAccessWrite, 7458 kAnyMatch, 0, 0, NULL, &fid)) { 7459 /* No matches or no pid to match, so just use the generic shared fork */ 7460 fid = np->f_fid; 7461 } 7462 if (fid == 0) { 7463 error = EBADF; 7464 goto done; 7465 } 7466 /* If nothing is changing, then we're done */ 7467 if (!length || (np->n_size == length)) { 7468 length = 0; 7469 } else { 7470 struct smb_share *share; 7471 7472 share = smb_get_share_with_reference(VTOSMBFS(vp)); 7473 length = roundup(length, VTOSMBFS(vp)->sm_statfsbuf.f_bsize); 7474 error = smbfs_smb_set_allocation(share, fid, length, ap->a_context); 7475 smb_share_rele(share, ap->a_context); 7476 } 7477 if (!error) { 7478 *(ap->a_bytesallocated) = length; 7479 } 7480 7481done: 7482 if (error) { 7483 SMBWARNING("%s: length = %lld, error = %d\n", np->n_name, length, error); 7484 } 7485 smbnode_unlock(VTOSMB(ap->a_vp)); 7486 return error; 7487} 7488 7489vnop_t **smbfs_vnodeop_p; 7490static struct vnodeopv_entry_desc smbfs_vnodeop_entries[] = { 7491 { &vnop_default_desc, (vnop_t *) vn_default_error }, 7492 { &vnop_advlock_desc, (vnop_t *) smbfs_vnop_advlock }, 7493 { &vnop_close_desc, (vnop_t *) smbfs_vnop_close }, 7494 { &vnop_create_desc, (vnop_t *) smbfs_vnop_create }, 7495 { &vnop_fsync_desc, (vnop_t *) smbfs_vnop_fsync }, 7496 { &vnop_getattr_desc, (vnop_t *) smbfs_vnop_getattr }, 7497 { &vnop_pagein_desc, (vnop_t *) smbfs_vnop_pagein }, 7498 { &vnop_inactive_desc, (vnop_t *) smbfs_vnop_inactive }, 7499 { &vnop_ioctl_desc, (vnop_t *) smbfs_vnop_ioctl }, 7500 { &vnop_link_desc, (vnop_t *) smbfs_vnop_link }, 7501 { &vnop_lookup_desc, (vnop_t *) smbfs_vnop_lookup }, 7502 { &vnop_mkdir_desc, (vnop_t *) smbfs_vnop_mkdir }, 7503 { &vnop_mknod_desc, (vnop_t *) smbfs_vnop_mknod }, 7504 { &vnop_mmap_desc, (vnop_t *) smbfs_vnop_mmap }, 7505 { &vnop_mnomap_desc, (vnop_t *) smbfs_vnop_mnomap }, 7506 { &vnop_open_desc, (vnop_t *) smbfs_vnop_open }, 7507 { &vnop_compound_open_desc, (vnop_t *) smbfs_vnop_compound_open }, 7508 { &vnop_pathconf_desc, (vnop_t *) smbfs_vnop_pathconf }, 7509 { &vnop_pageout_desc, (vnop_t *) smbfs_vnop_pageout }, 7510 { &vnop_copyfile_desc, (vnop_t *) smbfs_vnop_copyfile }, 7511 { &vnop_read_desc, (vnop_t *) smbfs_vnop_read }, 7512 { &vnop_readdir_desc, (vnop_t *) smbfs_vnop_readdir }, 7513 { &vnop_readdirattr_desc, (vnop_t *) smbfs_vnop_readdirattr }, 7514 { &vnop_readlink_desc, (vnop_t *) smbfs_vnop_readlink }, 7515 { &vnop_reclaim_desc, (vnop_t *) smbfs_vnop_reclaim }, 7516 { &vnop_remove_desc, (vnop_t *) smbfs_vnop_remove }, 7517 { &vnop_rename_desc, (vnop_t *) smbfs_vnop_rename }, 7518 { &vnop_rmdir_desc, (vnop_t *) smbfs_vnop_rmdir }, 7519 { &vnop_setattr_desc, (vnop_t *) smbfs_vnop_setattr }, 7520 { &vnop_symlink_desc, (vnop_t *) smbfs_vnop_symlink }, 7521 { &vnop_write_desc, (vnop_t *) smbfs_vnop_write }, 7522 { &vnop_blockmap_desc, (vnop_t *) smbfs_vnop_blockmap }, 7523 { &vnop_strategy_desc, (vnop_t *) smbfs_vnop_strategy }, 7524 { &vnop_searchfs_desc, (vnop_t *) err_searchfs }, 7525 { &vnop_offtoblk_desc, (vnop_t *) smbfs_vnop_offtoblk }, 7526 { &vnop_blktooff_desc, (vnop_t *) smbfs_vnop_blktooff }, 7527 { &vnop_getxattr_desc, (vnop_t *) smbfs_vnop_getxattr }, 7528 { &vnop_setxattr_desc, (vnop_t *) smbfs_vnop_setxattr }, 7529 { &vnop_removexattr_desc, (vnop_t *) smbfs_vnop_removexattr }, 7530 { &vnop_listxattr_desc, (vnop_t *) smbfs_vnop_listxattr }, 7531 { &vnop_monitor_desc, (vnop_t *) smbfs_vnop_monitor}, 7532 { &vnop_getnamedstream_desc, (vnop_t *) smbfs_vnop_getnamedstream }, 7533 { &vnop_makenamedstream_desc, (vnop_t *) smbfs_vnop_makenamedstream }, 7534 { &vnop_removenamedstream_desc, (vnop_t *) smbfs_vnop_removenamedstream }, 7535 { &vnop_access_desc, (vnop_t *) smbfs_vnop_access }, 7536 { &vnop_allocate_desc, (vnop_t *) smbfs_vnop_allocate }, 7537 { NULL, NULL } 7538}; 7539 7540struct vnodeopv_desc smbfs_vnodeop_opv_desc = 7541 { &smbfs_vnodeop_p, smbfs_vnodeop_entries }; 7542