Changeset 75675 in vbox for trunk/src/VBox/Additions/darwin/VBoxSF
- Timestamp:
- Nov 22, 2018 9:16:48 PM (6 years ago)
- svn:sync-xref-src-repo-rev:
- 126870
- Location:
- trunk/src/VBox/Additions/darwin/VBoxSF
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/darwin/VBoxSF/VBoxSF-Utils.cpp
r75666 r75675 20 20 * Header Files * 21 21 *********************************************************************************************************************************/ 22 #define LOG_GROUP LOG_GROUP_SHARED_FOLDERS 22 23 #include "VBoxSFInternal.h" 23 24 24 25 #include <iprt/assert.h> 25 26 #include <iprt/mem.h> 26 27 27 #include <VBox/log.h> 28 29 #if 0 28 30 /** 29 31 * Helper function to create XNU VFS vnode object. … … 387 389 parms.CreateFlags = fFlags; 388 390 389 rc = VbglR0SfCreate(&g_SfClient , &pMount->pMap, pPath, &parms);391 rc = VbglR0SfCreate(&g_SfClientDarwin, &pMount->pMap, pPath, &parms); 390 392 if (RT_SUCCESS(rc)) 391 393 { … … 412 414 { 413 415 AssertReturn(pMount, EINVAL); 414 return VbglR0SfClose(&g_SfClient , &pMount->pMap, pHandle);416 return VbglR0SfClose(&g_SfClientDarwin, &pMount->pMap, pHandle); 415 417 } 416 418 … … 442 444 parms.CreateFlags = SHFL_CF_LOOKUP | SHFL_CF_ACT_FAIL_IF_NEW; 443 445 444 rc = VbglR0SfCreate(&g_SfClient , &pMount->pMap, pSHFLDPath, &parms);446 rc = VbglR0SfCreate(&g_SfClientDarwin, &pMount->pMap, pSHFLDPath, &parms); 445 447 if (rc == 0) 446 448 *Info = parms.Info; … … 594 596 } 595 597 598 #endif -
trunk/src/VBox/Additions/darwin/VBoxSF/VBoxSF-VNodeOps.cpp
r75666 r75675 21 21 * Header Files * 22 22 *********************************************************************************************************************************/ 23 #define LOG_GROUP LOG_GROUP_SHARED_FOLDERS 23 24 #include "VBoxSFInternal.h" 24 25 25 26 #include <iprt/mem.h> 26 27 #include <iprt/assert.h> 27 28 29 30 int vboxvfs_dfl_error(void) 31 { 32 PDEBUG("vboxvfs_dfl_error is called"); 33 28 #include <VBox/log.h> 29 30 31 /********************************************************************************************************************************* 32 * Structures and Typedefs * 33 *********************************************************************************************************************************/ 34 struct default_error_args_hack 35 { 36 struct default_error_vdesc_hack 37 { 38 int vdesc_offset; 39 const char *vdesc_name; 40 } const *a_desc; 41 }; 42 43 44 45 /** 46 * Default implementation that returns ENOTSUP. 47 */ 48 static int vboxSfDwnVnDefaultError(struct default_error_args_hack *pArgs) 49 { 50 Log(("vboxSfDwnVnDefaultError: %s\n", RT_VALID_PTR(pArgs) && RT_VALID_PTR(pArgs->a_desc) ? pArgs->a_desc->vdesc_name : "??")); 51 RT_NOREF(pArgs); 34 52 return ENOTSUP; 35 53 } 36 54 37 int vboxvfs_vnode_getattr(struct vnop_getattr_args *args) 38 { 55 56 static int vboxFsDwnVnGetAttr(struct vnop_getattr_args *pArgs) 57 { 58 #if 1 59 RT_NOREF(pArgs); 60 return ENOTSUP; 61 #else 62 39 63 vboxvfs_mount_t *pMount; 40 64 struct vnode_attr *vnode_args; … … 50 74 PDEBUG("Getting vnode attribute..."); 51 75 52 AssertReturn( args, EINVAL);53 54 vnode = args->a_vp; AssertReturn(vnode, EINVAL);55 vnode_args = args->a_vap; AssertReturn(vnode_args, EINVAL);76 AssertReturn(pArgs, EINVAL); 77 78 vnode = pArgs->a_vp; AssertReturn(vnode, EINVAL); 79 vnode_args = pArgs->a_vap; AssertReturn(vnode_args, EINVAL); 56 80 mp = vnode_mount(vnode); AssertReturn(mp, EINVAL); 57 81 pMount = (vboxvfs_mount_t *)vfs_fsprivate(mp); AssertReturn(pMount, EINVAL); … … 125 149 126 150 return rc; 127 } 128 151 #endif 152 } 153 154 #if 0 129 155 /** 130 156 * Helper function for vboxvfs_vnode_lookup(): create new vnode. … … 217 243 */ 218 244 static int 219 vboxvfs_vnode_lookup_dot_handler(struct vnop_lookup_args * args, vnode_t *result_vnode)245 vboxvfs_vnode_lookup_dot_handler(struct vnop_lookup_args *pArgs, vnode_t *result_vnode) 220 246 { 221 247 vnode_t vnode = NULL; 222 248 223 if ( args->a_cnp->cn_flags & ISDOTDOT)224 { 225 vnode = vnode_getparent( args->a_dvp);249 if (pArgs->a_cnp->cn_flags & ISDOTDOT) 250 { 251 vnode = vnode_getparent(pArgs->a_dvp); 226 252 if (vnode) 227 253 { … … 233 259 { 234 260 PDEBUG("return parent directory not found, return current directory"); 235 *result_vnode = args->a_dvp;261 *result_vnode = pArgs->a_dvp; 236 262 return 0; 237 263 } 238 264 } 239 else if ((strncmp( args->a_cnp->cn_nameptr, ".", 1) == 0) &&240 args->a_cnp->cn_namelen == 1)265 else if ((strncmp(pArgs->a_cnp->cn_nameptr, ".", 1) == 0) && 266 pArgs->a_cnp->cn_namelen == 1) 241 267 { 242 268 PDEBUG("return current directory"); 243 *result_vnode = args->a_dvp;269 *result_vnode = pArgs->a_dvp; 244 270 return 0; 245 271 } … … 247 273 return ENOENT; 248 274 } 249 250 int vboxvfs_vnode_lookup(struct vnop_lookup_args *args) 251 { 275 #endif 276 277 static int vboxSfDwnVnLookup(struct vnop_lookup_args *pArgs) 278 { 279 #if 1 280 RT_NOREF(pArgs); 281 return ENOTSUP; 282 #else 252 283 int rc; 253 284 … … 257 288 PDEBUG("Looking up for vnode..."); 258 289 259 AssertReturn( args, EINVAL);260 AssertReturn( args->a_dvp, EINVAL);261 AssertReturn(vnode_isdir( args->a_dvp), EINVAL);262 AssertReturn( args->a_cnp, EINVAL);263 AssertReturn( args->a_cnp->cn_nameptr, EINVAL);264 AssertReturn( args->a_vpp, EINVAL);265 266 pVnodeData = (vboxvfs_vnode_t *)vnode_fsnode( args->a_dvp);290 AssertReturn(pArgs, EINVAL); 291 AssertReturn(pArgs->a_dvp, EINVAL); 292 AssertReturn(vnode_isdir(pArgs->a_dvp), EINVAL); 293 AssertReturn(pArgs->a_cnp, EINVAL); 294 AssertReturn(pArgs->a_cnp->cn_nameptr, EINVAL); 295 AssertReturn(pArgs->a_vpp, EINVAL); 296 297 pVnodeData = (vboxvfs_vnode_t *)vnode_fsnode(pArgs->a_dvp); 267 298 AssertReturn(pVnodeData, EINVAL); 268 299 AssertReturn(pVnodeData->pLock, EINVAL); 269 300 270 301 /* 271 todo: take care about args->a_cnp->cn_nameiop302 todo: take care about pArgs->a_cnp->cn_nameiop 272 303 */ 273 304 274 if ( args->a_cnp->cn_nameiop == LOOKUP) PDEBUG("LOOKUP");275 else if ( args->a_cnp->cn_nameiop == CREATE) PDEBUG("CREATE");276 else if ( args->a_cnp->cn_nameiop == RENAME) PDEBUG("RENAME");277 else if ( args->a_cnp->cn_nameiop == DELETE) PDEBUG("DELETE");278 else PDEBUG("Unknown cn_nameiop: 0x%X", (int) args->a_cnp->cn_nameiop);305 if (pArgs->a_cnp->cn_nameiop == LOOKUP) PDEBUG("LOOKUP"); 306 else if (pArgs->a_cnp->cn_nameiop == CREATE) PDEBUG("CREATE"); 307 else if (pArgs->a_cnp->cn_nameiop == RENAME) PDEBUG("RENAME"); 308 else if (pArgs->a_cnp->cn_nameiop == DELETE) PDEBUG("DELETE"); 309 else PDEBUG("Unknown cn_nameiop: 0x%X", (int)pArgs->a_cnp->cn_nameiop); 279 310 280 311 lck_rw_lock_exclusive(pVnodeData->pLock); 281 312 282 313 /* Take care about '.' and '..' entries */ 283 if (vboxvfs_vnode_lookup_dot_handler( args, &vnode) == 0)314 if (vboxvfs_vnode_lookup_dot_handler(pArgs, &vnode) == 0) 284 315 { 285 316 vnode_get(vnode); 286 * args->a_vpp = vnode;317 *pArgs->a_vpp = vnode; 287 318 288 319 lck_rw_unlock_exclusive(pVnodeData->pLock); … … 292 323 293 324 /* Look into VFS cache and attempt to find previously allocated vnode there. */ 294 rc = cache_lookup( args->a_dvp, &vnode, args->a_cnp);325 rc = cache_lookup(pArgs->a_dvp, &vnode, pArgs->a_cnp); 295 326 if (rc == -1) /* Record found */ 296 327 { … … 302 333 /* Prepare & return cached vnode */ 303 334 vnode_get(vnode); 304 * args->a_vpp = vnode;335 *pArgs->a_vpp = vnode; 305 336 306 337 rc = 0; … … 318 349 PDEBUG("cache_lookup() returned %d, create new VFS vnode", rc); 319 350 320 rc = vboxvfs_vnode_lookup_instantinate_vnode( args->a_dvp, args->a_cnp->cn_nameptr, &vnode);351 rc = vboxvfs_vnode_lookup_instantinate_vnode(pArgs->a_dvp, pArgs->a_cnp->cn_nameptr, &vnode); 321 352 if (rc == 0) 322 353 { 323 cache_enter( args->a_dvp, vnode, args->a_cnp);324 * args->a_vpp = vnode;354 cache_enter(pArgs->a_dvp, vnode, pArgs->a_cnp); 355 *pArgs->a_vpp = vnode; 325 356 } 326 357 else … … 333 364 334 365 return rc; 335 } 336 337 int vboxvfs_vnode_open(struct vnop_open_args *args) 338 { 366 #endif 367 } 368 369 static int vboxSfDwnVnOpen(struct vnop_open_args *pArgs) 370 { 371 #if 1 372 RT_NOREF(pArgs); 373 return ENOTSUP; 374 #else 339 375 vnode_t vnode; 340 376 vboxvfs_vnode_t *pVnodeData; … … 347 383 PDEBUG("Opening vnode..."); 348 384 349 AssertReturn( args, EINVAL);350 351 vnode = args->a_vp; AssertReturn(vnode, EINVAL);385 AssertReturn(pArgs, EINVAL); 386 387 vnode = pArgs->a_vp; AssertReturn(vnode, EINVAL); 352 388 pVnodeData = (vboxvfs_vnode_t *)vnode_fsnode(vnode); AssertReturn(pVnodeData, EINVAL); 353 389 mp = vnode_mount(vnode); AssertReturn(mp, EINVAL); … … 374 410 //} 375 411 376 fHostFlags = vboxvfs_g2h_mode_inernal( args->a_mode);412 fHostFlags = vboxvfs_g2h_mode_inernal(pArgs->a_mode); 377 413 fHostFlags |= (vnode_isdir(vnode) ? SHFL_CF_DIRECTORY : 0); 378 414 … … 397 433 398 434 return rc; 399 } 400 401 int vboxvfs_vnode_close(struct vnop_close_args *args) 402 { 435 #endif 436 } 437 438 static int vboxSfDwnVnClose(struct vnop_close_args *pArgs) 439 { 440 #if 1 441 RT_NOREF(pArgs); 442 return ENOTSUP; 443 #else 444 403 445 vnode_t vnode; 404 446 mount_t mp; … … 410 452 PDEBUG("Closing vnode..."); 411 453 412 AssertReturn( args, EINVAL);413 414 vnode = args->a_vp; AssertReturn(vnode, EINVAL);454 AssertReturn(pArgs, EINVAL); 455 456 vnode = pArgs->a_vp; AssertReturn(vnode, EINVAL); 415 457 pVnodeData = (vboxvfs_vnode_t *)vnode_fsnode(vnode); AssertReturn(pVnodeData, EINVAL); 416 458 mp = vnode_mount(vnode); AssertReturn(mp, EINVAL); … … 457 499 458 500 return rc; 459 } 460 501 #endif 502 } 503 504 #if 0 461 505 /** 462 506 * Convert SHFLDIRINFO to struct dirent and copy it back to user. … … 501 545 return rc; 502 546 } 503 504 int vboxvfs_vnode_readdir(struct vnop_readdir_args *args) 505 { 547 #endif 548 549 static int vboxSfDwnVnReadDir(struct vnop_readdir_args *pArgs) 550 { 551 #if 1 552 RT_NOREF(pArgs); 553 return ENOTSUP; 554 #else 506 555 vboxvfs_mount_t *pMount; 507 556 vboxvfs_vnode_t *pVnodeData; … … 516 565 PDEBUG("Reading directory..."); 517 566 518 AssertReturn( args, EINVAL);519 AssertReturn( args->a_eofflag, EINVAL);520 AssertReturn( args->a_numdirent, EINVAL);521 522 uio = args->a_uio; AssertReturn(uio, EINVAL);523 vnode = args->a_vp; AssertReturn(vnode, EINVAL); AssertReturn(vnode_isdir(vnode), EINVAL);567 AssertReturn(pArgs, EINVAL); 568 AssertReturn(pArgs->a_eofflag, EINVAL); 569 AssertReturn(pArgs->a_numdirent, EINVAL); 570 571 uio = pArgs->a_uio; AssertReturn(uio, EINVAL); 572 vnode = pArgs->a_vp; AssertReturn(vnode, EINVAL); AssertReturn(vnode_isdir(vnode), EINVAL); 524 573 pVnodeData = (vboxvfs_vnode_t *)vnode_fsnode(vnode); AssertReturn(pVnodeData, EINVAL); 525 574 mp = vnode_mount(vnode); AssertReturn(mp, EINVAL); … … 572 621 uint32_t cbReturned = cbInfo; 573 622 //rc = VbglR0SfDirInfo(&g_vboxSFClient, &pMount->pMap, Handle, pMask, SHFL_LIST_RETURN_ONE, 0, &cbReturned, (PSHFLDIRINFO)Info, &cFiles); 574 rc = VbglR0SfDirInfo(&g_SfClient , &pMount->pMap, Handle, 0, SHFL_LIST_RETURN_ONE, 0,623 rc = VbglR0SfDirInfo(&g_SfClientDarwin, &pMount->pMap, Handle, 0, SHFL_LIST_RETURN_ONE, 0, 575 624 &cbReturned, (PSHFLDIRINFO)Info, &cFiles); 576 625 … … 598 647 case VINF_SUCCESS: 599 648 { 600 rc = vboxvfs_vnode_readdir_copy_data((ino_t)(index + 1), Info, uio, args->a_numdirent);649 rc = vboxvfs_vnode_readdir_copy_data((ino_t)(index + 1), Info, uio, pArgs->a_numdirent); 601 650 break; 602 651 } … … 605 654 { 606 655 PDEBUG("No more entries in directory"); 607 *( args->a_eofflag) = 1;656 *(pArgs->a_eofflag) = 1; 608 657 break; 609 658 } … … 621 670 622 671 return rc; 623 } 624 625 626 int vboxvfs_vnode_access(struct vnop_access_args *args) 672 #endif 673 } 674 675 676 static int vboxSfDwnVnPathConf(struct vnop_pathconf_args *pArgs) 627 677 { 628 678 PDEBUG("here"); … … 631 681 632 682 633 int vboxvfs_vnode_readdirattr(struct vnop_readdirattr_args *args)634 {635 PDEBUG("here");636 return 0;637 }638 639 int vboxvfs_vnode_pathconf(struct vnop_pathconf_args *args)640 {641 PDEBUG("here");642 return 0;643 }644 645 683 /** 684 * vnop_reclaim implementation. 685 * 646 686 * VBoxVFS reclaim callback. 647 687 * Called when vnode is going to be deallocated. Should release … … 652 692 * @return 0 on success, BSD error code otherwise. 653 693 */ 654 int vboxvfs_vnode_reclaim(struct vnop_reclaim_args *pArgs) 655 { 656 PDEBUG("Releasing vnode resources..."); 657 658 AssertReturn(pArgs, EINVAL); 659 660 vnode_t pVnode; 661 vboxvfs_vnode_t *pVnodeData; 662 vboxvfs_mount_t *pMount; 663 mount_t mp; 664 665 pVnode = pArgs->a_vp; 666 AssertReturn(pVnode, EINVAL); 667 668 mp = vnode_mount(pVnode); 669 AssertReturn(mp, EINVAL); 670 671 pMount = (vboxvfs_mount_t *)vfs_fsprivate(mp); 672 AssertReturn(pMount, EINVAL); 673 674 pVnodeData = (vboxvfs_vnode_t *)vnode_fsnode(pVnode); 675 AssertReturn(pVnodeData, EINVAL); 676 AssertReturn(pVnodeData->pPath, EINVAL); 677 AssertReturn(pVnodeData->pLockAttr, EINVAL); 678 AssertReturn(pVnodeData->pLock, EINVAL); 679 680 RTMemFree(pVnodeData->pPath); 681 pVnodeData->pPath = NULL; 682 683 lck_rw_free(pVnodeData->pLock, pMount->pLockGroup); 684 pVnodeData->pLock = NULL; 685 686 lck_attr_free(pVnodeData->pLockAttr); 687 pVnodeData->pLockAttr = NULL; 688 694 static int vboxSfDwnVnReclaim(struct vnop_reclaim_args *pArgs) 695 { 696 AssertReturn(pArgs && pArgs->a_vp, EINVAL); 697 698 /* Check that it's not a root node that's in use. */ 699 PVBOXSFMNT pMntData = (PVBOXSFMNT)vfs_fsprivate(vnode_mount(pArgs->a_vp)); 700 AssertReturn(!pMntData || pMntData->pVnRoot != pArgs->a_vp, EBUSY); 701 702 /* Get the private data and free it. */ 703 PVBOXSFDWNVNDATA pVnData = (PVBOXSFDWNVNDATA)vnode_fsnode(pArgs->a_vp); 704 AssertPtrReturn(pVnData, 0); 705 706 if (pVnData->hHandle != SHFL_HANDLE_NIL) 707 { 708 /** @todo can this happen? */ 709 pVnData->hHandle = SHFL_HANDLE_NIL; 710 } 711 712 RTMemFree(pVnData); 689 713 return 0; 714 } 715 716 717 /** 718 * Allocates a vnode. 719 * 720 * @returns Pointer to the new VNode, NULL if out of memory. 721 * @param pMount The file system mount structure. 722 * @param enmType The vnode type. 723 * @param pParent The parent vnode, NULL if root. 724 * @param cbFile The file size 725 */ 726 vnode_t vboxSfDwnVnAlloc(mount_t pMount, enum vtype enmType, vnode_t pParent, uint64_t cbFile) 727 { 728 /* 729 * Create our private data. 730 */ 731 PVBOXSFDWNVNDATA pVnData = (PVBOXSFDWNVNDATA)RTMemAllocZ(sizeof(*pVnData)); 732 if (pVnData) 733 { 734 pVnData->hHandle = SHFL_HANDLE_NIL; 735 736 struct vnode_fsparam VnParms; 737 RT_ZERO(VnParms); 738 VnParms.vnfs_mp = pMount; 739 VnParms.vnfs_vtype = enmType; 740 VnParms.vnfs_str = "vboxsf"; 741 VnParms.vnfs_dvp = pParent; 742 VnParms.vnfs_fsnode = pVnData; 743 VnParms.vnfs_vops = g_papfnVBoxVFSVnodeDirOpsVector; 744 VnParms.vnfs_markroot = pParent == NULL; 745 VnParms.vnfs_marksystem = 0; 746 VnParms.vnfs_rdev = 0; 747 VnParms.vnfs_filesize = cbFile; 748 VnParms.vnfs_cnp = 0; 749 VnParms.vnfs_flags = VNFS_NOCACHE; 750 751 vnode_t pVnRet; 752 int rc = vnode_create(VNCREATE_FLAVOR, VCREATESIZE, &VnParms, &pVnRet); 753 if (rc == 0) 754 return pVnRet; 755 RTMemFree(pVnData); 756 } 757 printf("vboxSfDwnVnAlloc: out of memory!\n"); 758 return NULL; 690 759 } 691 760 … … 697 766 { 698 767 #define VNODEOPFUNC int(*)(void *) 699 { &vnop_default_desc, (VNODEOPFUNC)vboxvfs_dfl_error }, 700 { &vnop_lookup_desc, (VNODEOPFUNC)vboxvfs_vnode_lookup }, 701 { &vnop_create_desc, (VNODEOPFUNC)vboxvfs_dfl_error }, 702 { &vnop_whiteout_desc, (VNODEOPFUNC)vboxvfs_dfl_error }, 703 { &vnop_mknod_desc, (VNODEOPFUNC)vboxvfs_dfl_error }, 704 { &vnop_open_desc, (VNODEOPFUNC)vboxvfs_vnode_open }, 705 { &vnop_close_desc, (VNODEOPFUNC)vboxvfs_vnode_close }, 706 { &vnop_access_desc, (VNODEOPFUNC)vboxvfs_vnode_access }, 707 { &vnop_getattr_desc, (VNODEOPFUNC)vboxvfs_vnode_getattr }, 708 { &vnop_setattr_desc, (VNODEOPFUNC)vboxvfs_dfl_error }, 709 { &vnop_read_desc, (VNODEOPFUNC)vboxvfs_dfl_error }, 710 { &vnop_write_desc, (VNODEOPFUNC)vboxvfs_dfl_error }, 711 { &vnop_ioctl_desc, (VNODEOPFUNC)vboxvfs_dfl_error }, 712 { &vnop_select_desc, (VNODEOPFUNC)vboxvfs_dfl_error }, 713 { &vnop_exchange_desc, (VNODEOPFUNC)vboxvfs_dfl_error }, 714 { &vnop_revoke_desc, (VNODEOPFUNC)vboxvfs_dfl_error }, 715 { &vnop_mmap_desc, (VNODEOPFUNC)vboxvfs_dfl_error }, 716 { &vnop_mnomap_desc, (VNODEOPFUNC)vboxvfs_dfl_error }, 717 { &vnop_fsync_desc, (VNODEOPFUNC)vboxvfs_dfl_error }, 718 { &vnop_remove_desc, (VNODEOPFUNC)vboxvfs_dfl_error }, 719 { &vnop_link_desc, (VNODEOPFUNC)vboxvfs_dfl_error }, 720 { &vnop_rename_desc, (VNODEOPFUNC)vboxvfs_dfl_error }, 721 { &vnop_mkdir_desc, (VNODEOPFUNC)vboxvfs_dfl_error }, 722 { &vnop_rmdir_desc, (VNODEOPFUNC)vboxvfs_dfl_error }, 723 { &vnop_symlink_desc, (VNODEOPFUNC)vboxvfs_dfl_error }, 724 { &vnop_readdir_desc, (VNODEOPFUNC)vboxvfs_vnode_readdir }, 725 { &vnop_readdirattr_desc, (VNODEOPFUNC)vboxvfs_vnode_readdirattr }, 726 { &vnop_readlink_desc, (VNODEOPFUNC)vboxvfs_dfl_error }, 727 { &vnop_inactive_desc, (VNODEOPFUNC)vboxvfs_dfl_error }, 728 { &vnop_reclaim_desc, (VNODEOPFUNC)vboxvfs_vnode_reclaim }, 729 /* { &vnop_print_desc, (VNODEOPFUNC)vboxvfs_dfl_error }, undefined in ML */ 730 { &vnop_pathconf_desc, (VNODEOPFUNC)vboxvfs_vnode_pathconf }, 731 { &vnop_advlock_desc, (VNODEOPFUNC)vboxvfs_dfl_error }, 732 /* { &vnop_truncate_desc, (VNODEOPFUNC)vboxvfs_dfl_error }, undefined in ML */ 733 { &vnop_allocate_desc, (VNODEOPFUNC)vboxvfs_dfl_error }, 734 { &vnop_pagein_desc, (VNODEOPFUNC)vboxvfs_dfl_error }, 735 { &vnop_pageout_desc, (VNODEOPFUNC)vboxvfs_dfl_error }, 736 { &vnop_searchfs_desc, (VNODEOPFUNC)vboxvfs_dfl_error }, 737 { &vnop_copyfile_desc, (VNODEOPFUNC)vboxvfs_dfl_error }, 738 { &vnop_blktooff_desc, (VNODEOPFUNC)vboxvfs_dfl_error }, 739 { &vnop_offtoblk_desc, (VNODEOPFUNC)vboxvfs_dfl_error }, 740 { &vnop_blockmap_desc, (VNODEOPFUNC)vboxvfs_dfl_error }, 741 { &vnop_strategy_desc, (VNODEOPFUNC)vboxvfs_dfl_error }, 742 { &vnop_bwrite_desc, (VNODEOPFUNC)vboxvfs_dfl_error }, 768 { &vnop_default_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, 769 //{ &vnop_access_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, - probably not needed. 770 //{ &vnop_advlock_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, - later. 771 //{ &vnop_allocate_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, - maybe, need shfl function 772 { &vnop_blktooff_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, 773 //{ &vnop_blockmap_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, 774 //{ &vnop_bwrite_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, 775 { &vnop_close_desc, (VNODEOPFUNC)vboxSfDwnVnClose }, 776 //{ &vnop_copyfile_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, 777 { &vnop_create_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, 778 //{ &vnop_exchange_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, 779 { &vnop_fsync_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, 780 { &vnop_getattr_desc, (VNODEOPFUNC)vboxFsDwnVnGetAttr }, 781 //{ &vnop_getnamedstream_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, 782 //{ &vnop_getxattr_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, 783 { &vnop_inactive_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, 784 { &vnop_ioctl_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, 785 { &vnop_link_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, 786 //{ &vnop_listxattr_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, 787 { &vnop_lookup_desc, (VNODEOPFUNC)vboxSfDwnVnLookup }, 788 { &vnop_mkdir_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, 789 { &vnop_mknod_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, 790 { &vnop_mmap_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, 791 { &vnop_mnomap_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, 792 { &vnop_offtoblk_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, 793 { &vnop_open_desc, (VNODEOPFUNC)vboxSfDwnVnOpen }, 794 { &vnop_pagein_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, 795 { &vnop_pageout_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, 796 { &vnop_pathconf_desc, (VNODEOPFUNC)vboxSfDwnVnPathConf }, 797 /* { &vnop_print_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, undefined in ML */ 798 { &vnop_read_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, 799 { &vnop_readdir_desc, (VNODEOPFUNC)vboxSfDwnVnReadDir }, 800 //{ &vnop_readdirattr_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, - hfs specific. 801 { &vnop_readlink_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, 802 { &vnop_reclaim_desc, (VNODEOPFUNC)vboxSfDwnVnReclaim }, 803 { &vnop_remove_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, 804 //{ &vnop_removexattr_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, 805 { &vnop_rename_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, 806 //{ &vnop_revoke_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, - not needed 807 { &vnop_rmdir_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, 808 { &vnop_searchfs_desc, (VNODEOPFUNC)err_searchfs }, 809 //{ &vnop_select_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, - not needed 810 { &vnop_setattr_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, 811 { &vnop_setxattr_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, 812 //{ &vnop_strategy_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, - not needed 813 { &vnop_symlink_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, 814 /* { &vnop_truncate_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, undefined in ML */ 815 //{ &vnop_whiteout_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, - not needed/supported 816 { &vnop_write_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, 743 817 { NULL, (VNODEOPFUNC)NULL }, 744 818 #undef VNODEOPFUNC -
trunk/src/VBox/Additions/darwin/VBoxSF/VBoxSF-VfsOps.cpp
r75666 r75675 20 20 * Header Files * 21 21 *********************************************************************************************************************************/ 22 #define LOG_GROUP LOG_GROUP_SHARED_FOLDERS 22 23 #include "VBoxSFInternal.h" 23 24 24 25 #include <iprt/assert.h> 26 #include <iprt/asm.h> 25 27 #include <iprt/mem.h> 26 #include <iprt/asm.h> 28 #include <iprt/string.h> 29 #include <VBox/log.h> 27 30 28 31 … … 35 38 36 39 40 37 41 /** 38 * Mount helper: Get mounting parameters from user space and validate them.42 * vfsops::vfs_getattr implementation. 39 43 * 40 * @param pUserData Mounting parameters provided by user space mount tool. 41 * @param pKernelData Buffer to store pUserData in kernel space. 42 * 43 * @return 0 on success or BSD error code otherwise. 44 */ 45 static int 46 vboxvfs_get_mount_info(user_addr_t pUserData, PVBOXSFDRWNMOUNTINFO pKernelData) 44 * @returns 0 on success or errno.h value on failure. 45 * @param pMount The mount data structure. 46 * @param pFsAttr Input & output structure. 47 * @param pContext Unused kAuth parameter. 48 */ 49 static int vboxSfDwnVfsGetAttr(mount_t pMount, struct vfs_attr *pFsAttr, vfs_context_t pContext) 47 50 { 48 AssertReturn(pKernelData, EINVAL); 49 AssertReturn(pUserData, EINVAL); 50 51 /* Get mount parameters from user space */ 52 if (copyin(pUserData, pKernelData, sizeof(*pKernelData)) != 0) 53 { 54 PERROR("Unable to copy mount parameters from user space"); 55 return EINVAL; 56 } 57 58 /* Validate data magic */ 59 if (pKernelData->u32Magic != VBOXSFDRWNMOUNTINFO_MAGIC) 60 { 61 PERROR("Mount parameter magic mismatch"); 62 return EINVAL; 63 } 64 65 return 0; 66 } 67 68 69 /** 70 * Mount helper: Provide VFS layer with a VBox share name (stored as mounted device). 71 * 72 * @param mp Mount data provided by VFS layer. 73 * @param szShareName VBox share name. 74 * @param cbShareName Returning parameter which contains VBox share name string length. 75 * 76 * @return 0 on success or BSD error code otherwise. 77 */ 78 static int 79 vboxvfs_set_share_name(struct mount *mp, char *szShareName, size_t *cbShareName) 80 { 81 struct vfsstatfs *pVfsInfo; 82 83 AssertReturn(mp, EINVAL); 84 AssertReturn(szShareName, EINVAL); 85 AssertReturn(cbShareName, EINVAL); 86 87 pVfsInfo = vfs_statfs(mp); 88 if (!pVfsInfo) 89 { 90 PERROR("Unable to get VFS data for the mount structure"); 91 return EINVAL; 92 } 93 94 return copystr(szShareName, pVfsInfo->f_mntfromname, MAXPATHLEN, cbShareName); 95 } 96 97 98 /** 99 * Mount helper: allocate locking group attribute and locking group itself. 100 * Store allocated data into VBoxVFS private data. 101 * 102 * @param pMount VBoxVFS global data which will be updated with 103 * locking group and its attribute in case of success; 104 * otherwise pMount unchanged. 105 * 106 * @return 0 on success or BSD error code otherwise. 107 * 108 */ 109 static int 110 vboxvfs_prepare_locking(vboxvfs_mount_t *pMount) 111 { 112 lck_grp_attr_t *pGrpAttr; 113 lck_grp_t *pGrp; 114 115 AssertReturn(pMount, EINVAL); 116 117 pGrpAttr = lck_grp_attr_alloc_init(); 118 if (pGrpAttr) 119 { 120 pGrp = lck_grp_alloc_init("VBoxVFS", pGrpAttr); 121 if (pGrp) 51 PVBOXSFMNT pThis = (PVBOXSFMNT)vfs_fsprivate(pMount); 52 AssertReturn(pThis, EBADMSG); 53 LogFlow(("vboxSfDwnVfsGetAttr: %s\n", pThis->MntInfo.szFolder)); 54 RT_NOREF(pContext); 55 56 /* 57 * Get the file system stats from the host. 58 */ 59 int rc; 60 struct MyEmbReq 61 { 62 VBGLIOCIDCHGCMFASTCALL Hdr; 63 VMMDevHGCMCall Call; 64 VBoxSFParmInformation Parms; 65 SHFLVOLINFO VolInfo; 66 } *pReq = (struct MyEmbReq *)VbglR0PhysHeapAlloc(sizeof(*pReq)); 67 if (pReq) 68 { 69 RT_ZERO(pReq->VolInfo); 70 71 VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClientDarwin.idClient, 72 SHFL_FN_INFORMATION, SHFL_CPARMS_INFORMATION, sizeof(*pReq)); 73 pReq->Parms.id32Root.type = VMMDevHGCMParmType_32bit; 74 pReq->Parms.id32Root.u.value32 = pThis->hHostFolder.root; 75 pReq->Parms.u64Handle.type = VMMDevHGCMParmType_64bit; 76 pReq->Parms.u64Handle.u.value64 = 0; 77 pReq->Parms.f32Flags.type = VMMDevHGCMParmType_32bit; 78 pReq->Parms.f32Flags.u.value32 = SHFL_INFO_VOLUME | SHFL_INFO_GET; 79 pReq->Parms.cb32.type = VMMDevHGCMParmType_32bit; 80 pReq->Parms.cb32.u.value32 = sizeof(pReq->VolInfo); 81 pReq->Parms.pInfo.type = VMMDevHGCMParmType_Embedded; 82 pReq->Parms.pInfo.u.Embedded.cbData = sizeof(pReq->VolInfo); 83 pReq->Parms.pInfo.u.Embedded.offData = RT_UOFFSETOF(struct MyEmbReq, VolInfo) - sizeof(VBGLIOCIDCHGCMFASTCALL); 84 pReq->Parms.pInfo.u.Embedded.fFlags = VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST; 85 86 int vrc = VbglR0HGCMFastCall(g_SfClientDarwin.handle, &pReq->Hdr, sizeof(*pReq)); 87 if (RT_SUCCESS(vrc)) 88 vrc = pReq->Call.header.result; 89 if (RT_SUCCESS(vrc)) 122 90 { 123 pMount->pLockGroupAttr = pGrpAttr; 124 pMount->pLockGroup = pGrp; 125 126 return 0; 127 } 128 else 129 PERROR("Unable to allocate locking group"); 130 131 lck_grp_attr_free(pGrpAttr); 132 } 133 else 134 PERROR("Unable to allocate locking group attribute"); 135 136 return ENOMEM; 137 } 138 139 140 /** 141 * Mount and unmount helper: destroy locking group attribute and locking group itself. 142 * 143 * @param pMount VBoxVFS global data for which locking 144 * group and attribute will be deallocated and set to NULL. 145 */ 146 static void 147 vboxvfs_destroy_locking(vboxvfs_mount_t *pMount) 148 { 149 AssertReturnVoid(pMount); 150 151 if (pMount->pLockGroup) 152 { 153 lck_grp_free(pMount->pLockGroup); 154 pMount->pLockGroup = NULL; 155 } 156 157 if (pMount->pLockGroupAttr) 158 { 159 lck_grp_attr_free(pMount->pLockGroupAttr); 160 pMount->pLockGroupAttr = NULL; 161 } 162 } 163 164 /** 165 * Mount helper: Allocate and init VBoxVFS global data. 166 * 167 * @param mp Mount data provided by VFS layer. 168 * @param pUserData Mounting parameters provided by user space mount tool. 169 * 170 * @return VBoxVFS global data or NULL. 171 */ 172 static vboxvfs_mount_t * 173 vboxvfs_alloc_internal_data(struct mount *mp, user_addr_t pUserData) 174 { 175 vboxvfs_mount_t *pMount; 176 struct vboxvfs_mount_info mountInfo; 177 struct vfsstatfs *pVfsInfo; 178 size_t cbShareName; 179 180 int rc; 181 182 AssertReturn(mp, NULL); 183 AssertReturn(pUserData, NULL); 184 185 pVfsInfo = vfs_statfs(mp); 186 AssertReturn(pVfsInfo, NULL); 187 188 /* Allocate memory for VBoxVFS internal data */ 189 pMount = (vboxvfs_mount_t *)RTMemAllocZ(sizeof(vboxvfs_mount_t)); 190 if (pMount) 191 { 192 rc = vboxvfs_get_mount_info(pUserData, &mountInfo); 193 if (rc == 0) 194 { 195 PDEBUG("Mounting shared folder '%s'", mountInfo.szFolder); 196 197 /* Prepare for locking. We prepare locking group and attr data here, 198 * but allocate and initialize real lock in vboxvfs_create_vnode_internal(). 199 * We use the same pLockGroup and pLockAttr for all vnodes related to this mount point. */ 200 rc = vboxvfs_prepare_locking(pMount); 201 if (rc == 0) 91 /* 92 * Fill in stuff. 93 */ 94 /* Copy over the results we got from the host. */ 95 uint32_t cbUnit = pReq->VolInfo.ulBytesPerSector * pReq->VolInfo.ulBytesPerAllocationUnit; 96 VFSATTR_RETURN(pFsAttr, f_bsize, cbUnit); 97 VFSATTR_RETURN(pFsAttr, f_iosize, _64K); /** @todo what's a good block size... */ 98 VFSATTR_RETURN(pFsAttr, f_blocks, (uint64_t)pReq->VolInfo.ullTotalAllocationBytes / cbUnit); 99 VFSATTR_RETURN(pFsAttr, f_bavail, (uint64_t)pReq->VolInfo.ullAvailableAllocationBytes / cbUnit); 100 VFSATTR_RETURN(pFsAttr, f_bfree, (uint64_t)pReq->VolInfo.ullAvailableAllocationBytes / cbUnit); 101 VFSATTR_RETURN(pFsAttr, f_bused, 102 ((uint64_t)pReq->VolInfo.ullTotalAllocationBytes - (uint64_t)pReq->VolInfo.ullAvailableAllocationBytes) / cbUnit); 103 fsid_t const fsid = { { vfs_statfs(pMount)->f_fsid.val[0], vfs_typenum(pMount) } }; 104 VFSATTR_RETURN(pFsAttr, f_fsid, fsid); 105 106 /* f_owner is handled by caller. */ 107 /* f_signature is handled by caller. */ 108 109 struct timespec TmpTv = { 1084190406, 0 }; 110 VFSATTR_RETURN(pFsAttr, f_create_time, TmpTv); 111 112 /* 113 * Unsupported bits. 114 */ 115 /* Dummies for some values we don't support. */ 116 VFSATTR_RETURN(pFsAttr, f_objcount, 0); 117 VFSATTR_RETURN(pFsAttr, f_filecount, 0); 118 VFSATTR_RETURN(pFsAttr, f_dircount, 0); 119 VFSATTR_RETURN(pFsAttr, f_maxobjcount, UINT32_MAX); 120 VFSATTR_RETURN(pFsAttr, f_files, UINT32_MAX); 121 VFSATTR_RETURN(pFsAttr, f_ffree, UINT32_MAX); 122 VFSATTR_RETURN(pFsAttr, f_fssubtype, 0); 123 VFSATTR_RETURN(pFsAttr, f_carbon_fsid, 0); 124 125 /* Totally not supported: */ 126 VFSATTR_CLEAR_ACTIVE(pFsAttr, f_modify_time); 127 VFSATTR_CLEAR_ACTIVE(pFsAttr, f_access_time); 128 VFSATTR_CLEAR_ACTIVE(pFsAttr, f_backup_time); 129 130 /* 131 * Annoying capability stuff. 132 * The 'valid' bits are only supposed to be set when we know for sure. 133 */ 134 if (VFSATTR_IS_ACTIVE(pFsAttr, f_capabilities)) 202 135 { 203 rc = vboxvfs_set_share_name(mp, (char *)mountInfo.szFolder, &cbShareName); 204 if (rc == 0) 205 { 206 pMount->pShareName = vboxvfs_construct_shflstring(mountInfo.szFolder, cbShareName); 207 if (pMount->pShareName) 208 { 209 /* Remember user who mounted this share */ 210 pMount->owner = pVfsInfo->f_owner; 211 212 /* Mark root vnode as uninitialized */ 213 ASMAtomicWriteU8(&pMount->fRootVnodeState, VBOXVFS_OBJECT_UNINITIALIZED); 214 215 return pMount; 216 } 217 } 136 vol_capabilities_attr_t *pCaps = &pFsAttr->f_capabilities; 137 138 pCaps->valid[VOL_CAPABILITIES_FORMAT] = VOL_CAP_FMT_PERSISTENTOBJECTIDS 139 | VOL_CAP_FMT_SYMBOLICLINKS 140 | VOL_CAP_FMT_HARDLINKS 141 | VOL_CAP_FMT_JOURNAL 142 | VOL_CAP_FMT_JOURNAL_ACTIVE 143 | VOL_CAP_FMT_NO_ROOT_TIMES 144 | VOL_CAP_FMT_SPARSE_FILES 145 | VOL_CAP_FMT_ZERO_RUNS 146 | VOL_CAP_FMT_CASE_SENSITIVE 147 | VOL_CAP_FMT_CASE_PRESERVING 148 | VOL_CAP_FMT_FAST_STATFS 149 | VOL_CAP_FMT_2TB_FILESIZE 150 | VOL_CAP_FMT_OPENDENYMODES 151 | VOL_CAP_FMT_HIDDEN_FILES 152 | VOL_CAP_FMT_PATH_FROM_ID 153 | VOL_CAP_FMT_NO_VOLUME_SIZES 154 | VOL_CAP_FMT_DECMPFS_COMPRESSION 155 | VOL_CAP_FMT_64BIT_OBJECT_IDS; 156 pCaps->capabilities[VOL_CAPABILITIES_FORMAT] = VOL_CAP_FMT_2TB_FILESIZE 157 ///@todo | VOL_CAP_FMT_SYMBOLICLINKS - later 158 ///@todo | VOL_CAP_FMT_SPARSE_FILES - probably, needs testing. 159 /*| VOL_CAP_FMT_CASE_SENSITIVE - case-insensitive */ 160 | VOL_CAP_FMT_CASE_PRESERVING 161 ///@todo | VOL_CAP_FMT_HIDDEN_FILES - if windows host. 162 ///@todo | VOL_CAP_FMT_OPENDENYMODES - if windows host. 163 ; 164 pCaps->valid[VOL_CAPABILITIES_INTERFACES] = VOL_CAP_INT_SEARCHFS 165 | VOL_CAP_INT_ATTRLIST 166 | VOL_CAP_INT_NFSEXPORT 167 | VOL_CAP_INT_READDIRATTR 168 | VOL_CAP_INT_EXCHANGEDATA 169 | VOL_CAP_INT_COPYFILE 170 | VOL_CAP_INT_ALLOCATE 171 | VOL_CAP_INT_VOL_RENAME 172 | VOL_CAP_INT_ADVLOCK 173 | VOL_CAP_INT_FLOCK 174 | VOL_CAP_INT_EXTENDED_SECURITY 175 | VOL_CAP_INT_USERACCESS 176 | VOL_CAP_INT_MANLOCK 177 | VOL_CAP_INT_NAMEDSTREAMS 178 | VOL_CAP_INT_EXTENDED_ATTR; 179 pCaps->capabilities[VOL_CAPABILITIES_INTERFACES] = 0 180 ///@todo | VOL_CAP_INT_SEARCHFS 181 ///@todo | VOL_CAP_INT_COPYFILE 182 ///@todo | VOL_CAP_INT_READDIRATTR 183 ; 184 185 pCaps->valid[VOL_CAPABILITIES_RESERVED1] = 0; 186 pCaps->capabilities[VOL_CAPABILITIES_RESERVED1] = 0; 187 188 pCaps->valid[VOL_CAPABILITIES_RESERVED2] = 0; 189 pCaps->capabilities[VOL_CAPABILITIES_RESERVED2] = 0; 190 191 VFSATTR_SET_SUPPORTED(pFsAttr, f_capabilities); 218 192 } 219 193 220 vboxvfs_destroy_locking(pMount); 221 } 222 223 RTMemFree(pMount); 224 } 225 226 return NULL; 227 } 228 229 230 /** 231 * Mount and unmount helper: Release VBoxVFS internal resources. 232 * Deallocates ppMount as well. 233 * 234 * @param ppMount Pointer to reference of VBoxVFS internal data. 235 */ 236 static void 237 vboxvfs_destroy_internal_data(vboxvfs_mount_t **ppMount) 238 { 239 AssertReturnVoid(ppMount); 240 AssertReturnVoid(*ppMount); 241 AssertReturnVoid((*ppMount)->pShareName); 242 243 RTMemFree((*ppMount)->pShareName); 244 (*ppMount)->pShareName = NULL; 245 246 vboxvfs_destroy_locking(*ppMount); 247 RTMemFree(*ppMount); 248 *ppMount = NULL; 249 } 250 251 252 /** 253 * Mount VBoxVFS. 254 * 255 * @param mp Mount data provided by VFS layer. 256 * @param pDev Device structure provided by VFS layer. 257 * @param pUserData Mounting parameters provided by user space mount tool. 258 * @param pContext kAuth context needed in order to authentificate mount operation. 259 * 260 * @return 0 on success or BSD error code otherwise. 261 */ 262 static int 263 vboxvfs_mount(struct mount *mp, vnode_t pDev, user_addr_t pUserData, vfs_context_t pContext) 264 { 265 NOREF(pDev); 266 NOREF(pContext); 267 268 vboxvfs_mount_t *pMount; 269 270 int rc = ENOMEM; 271 272 PDEBUG("Mounting..."); 273 274 pMount = vboxvfs_alloc_internal_data(mp, pUserData); 275 if (pMount) 276 { 277 rc = VbglR0SfMapFolder(&g_SfClient, pMount->pShareName, &pMount->pMap); 278 if (RT_SUCCESS(rc)) 279 { 280 /* Private data should be set before vboxvfs_create_vnode_internal() call 281 * because we need it in order to create vnode. */ 282 vfs_setfsprivate(mp, pMount); 283 284 /* Reset root vnode */ 285 pMount->pRootVnode = NULL; 286 287 vfs_setflags(mp, MNT_RDONLY | MNT_SYNCHRONOUS | MNT_NOEXEC | MNT_NOSUID | MNT_NODEV); 288 289 PDEBUG("VirtualBox shared folder successfully mounted"); 290 291 return 0; 292 } 293 294 PDEBUG("Unable to map shared folder"); 295 vboxvfs_destroy_internal_data(&pMount); 296 } 297 else 298 PDEBUG("Unable to allocate internal data"); 299 300 return rc; 301 } 302 303 304 /** 305 * Unmount VBoxVFS. 306 * 307 * @param mp Mount data provided by VFS layer. 308 * @param fFlags Unmounting flags. 309 * @param pContext kAuth context needed in order to authentificate mount operation. 310 * 311 * @return 0 on success or BSD error code otherwise. 312 */ 313 static int 314 vboxvfs_unmount(struct mount *mp, int fFlags, vfs_context_t pContext) 315 { 316 NOREF(pContext); 317 318 vboxvfs_mount_t *pMount; 319 int rc = EBUSY; 320 int fFlush = (fFlags & MNT_FORCE) ? FORCECLOSE : 0; 321 322 PDEBUG("Attempting to %s unmount a shared folder", (fFlags & MNT_FORCE) ? "forcibly" : "normally"); 323 324 AssertReturn(mp, EINVAL); 325 326 pMount = (vboxvfs_mount_t *)vfs_fsprivate(mp); 327 328 AssertReturn(pMount, EINVAL); 329 AssertReturn(pMount->pRootVnode, EINVAL); 330 331 /* Check if we can do unmount at the moment */ 332 if (!vnode_isinuse(pMount->pRootVnode, 1)) 333 { 334 /* Flush child vnodes first */ 335 rc = vflush(mp, pMount->pRootVnode, fFlush); 336 if (rc == 0) 337 { 338 /* Flush root vnode */ 339 rc = vflush(mp, NULL, fFlush); 340 if (rc == 0) 194 195 /* 196 * Annoying attribute stuff. 197 * The 'valid' bits are only supposed to be set when we know for sure. 198 */ 199 if (VFSATTR_IS_ACTIVE(pFsAttr, f_attributes)) 341 200 { 342 vfs_setfsprivate(mp, NULL); 343 344 rc = VbglR0SfUnmapFolder(&g_SfClient, &pMount->pMap); 345 if (RT_SUCCESS(rc)) 346 { 347 vboxvfs_destroy_internal_data(&pMount); 348 PDEBUG("A shared folder has been successfully unmounted"); 349 return 0; 350 } 351 352 PDEBUG("Unable to unmount shared folder"); 353 rc = EPROTO; 201 vol_attributes_attr_t *pAt = &pFsAttr->f_attributes; 202 203 pAt->validattr.commonattr = ATTR_CMN_NAME 204 | ATTR_CMN_DEVID 205 | ATTR_CMN_FSID 206 | ATTR_CMN_OBJTYPE 207 | ATTR_CMN_OBJTAG 208 | ATTR_CMN_OBJID 209 | ATTR_CMN_OBJPERMANENTID 210 | ATTR_CMN_PAROBJID 211 | ATTR_CMN_SCRIPT 212 | ATTR_CMN_CRTIME 213 | ATTR_CMN_MODTIME 214 | ATTR_CMN_CHGTIME 215 | ATTR_CMN_ACCTIME 216 | ATTR_CMN_BKUPTIME 217 | ATTR_CMN_FNDRINFO 218 | ATTR_CMN_OWNERID 219 | ATTR_CMN_GRPID 220 | ATTR_CMN_ACCESSMASK 221 | ATTR_CMN_FLAGS 222 | ATTR_CMN_USERACCESS 223 | ATTR_CMN_EXTENDED_SECURITY 224 | ATTR_CMN_UUID 225 | ATTR_CMN_GRPUUID 226 | ATTR_CMN_FILEID 227 | ATTR_CMN_PARENTID 228 | ATTR_CMN_FULLPATH 229 | ATTR_CMN_ADDEDTIME; 230 pAt->nativeattr.commonattr = ATTR_CMN_NAME 231 | ATTR_CMN_DEVID 232 | ATTR_CMN_FSID 233 | ATTR_CMN_OBJTYPE 234 | ATTR_CMN_OBJTAG 235 | ATTR_CMN_OBJID 236 //| ATTR_CMN_OBJPERMANENTID 237 | ATTR_CMN_PAROBJID 238 //| ATTR_CMN_SCRIPT 239 | ATTR_CMN_CRTIME 240 | ATTR_CMN_MODTIME 241 | ATTR_CMN_CHGTIME 242 | ATTR_CMN_ACCTIME 243 //| ATTR_CMN_BKUPTIME 244 //| ATTR_CMN_FNDRINFO 245 //| ATTR_CMN_OWNERID 246 //| ATTR_CMN_GRPID 247 | ATTR_CMN_ACCESSMASK 248 //| ATTR_CMN_FLAGS 249 //| ATTR_CMN_USERACCESS 250 //| ATTR_CMN_EXTENDED_SECURITY 251 //| ATTR_CMN_UUID 252 //| ATTR_CMN_GRPUUID 253 | ATTR_CMN_FILEID 254 | ATTR_CMN_PARENTID 255 | ATTR_CMN_FULLPATH 256 //| ATTR_CMN_ADDEDTIME 257 ; 258 pAt->validattr.volattr = ATTR_VOL_FSTYPE 259 | ATTR_VOL_SIGNATURE 260 | ATTR_VOL_SIZE 261 | ATTR_VOL_SPACEFREE 262 | ATTR_VOL_SPACEAVAIL 263 | ATTR_VOL_MINALLOCATION 264 | ATTR_VOL_ALLOCATIONCLUMP 265 | ATTR_VOL_IOBLOCKSIZE 266 | ATTR_VOL_OBJCOUNT 267 | ATTR_VOL_FILECOUNT 268 | ATTR_VOL_DIRCOUNT 269 | ATTR_VOL_MAXOBJCOUNT 270 | ATTR_VOL_MOUNTPOINT 271 | ATTR_VOL_NAME 272 | ATTR_VOL_MOUNTFLAGS 273 | ATTR_VOL_MOUNTEDDEVICE 274 | ATTR_VOL_ENCODINGSUSED 275 | ATTR_VOL_CAPABILITIES 276 | ATTR_VOL_UUID 277 | ATTR_VOL_ATTRIBUTES 278 | ATTR_VOL_INFO; 279 pAt->nativeattr.volattr = ATTR_VOL_FSTYPE 280 //| ATTR_VOL_SIGNATURE 281 | ATTR_VOL_SIZE 282 | ATTR_VOL_SPACEFREE 283 | ATTR_VOL_SPACEAVAIL 284 | ATTR_VOL_MINALLOCATION 285 | ATTR_VOL_ALLOCATIONCLUMP 286 | ATTR_VOL_IOBLOCKSIZE 287 //| ATTR_VOL_OBJCOUNT 288 //| ATTR_VOL_FILECOUNT 289 //| ATTR_VOL_DIRCOUNT 290 //| ATTR_VOL_MAXOBJCOUNT 291 //| ATTR_VOL_MOUNTPOINT - ?? 292 | ATTR_VOL_NAME 293 | ATTR_VOL_MOUNTFLAGS 294 | ATTR_VOL_MOUNTEDDEVICE 295 //| ATTR_VOL_ENCODINGSUSED 296 | ATTR_VOL_CAPABILITIES 297 //| ATTR_VOL_UUID 298 | ATTR_VOL_ATTRIBUTES 299 //| ATTR_VOL_INFO 300 ; 301 pAt->validattr.dirattr = ATTR_DIR_LINKCOUNT 302 | ATTR_DIR_ENTRYCOUNT 303 | ATTR_DIR_MOUNTSTATUS; 304 pAt->nativeattr.dirattr = 0 //ATTR_DIR_LINKCOUNT 305 | ATTR_DIR_ENTRYCOUNT 306 | ATTR_DIR_MOUNTSTATUS 307 ; 308 pAt->validattr.fileattr = ATTR_FILE_LINKCOUNT 309 | ATTR_FILE_TOTALSIZE 310 | ATTR_FILE_ALLOCSIZE 311 | ATTR_FILE_IOBLOCKSIZE 312 | ATTR_FILE_DEVTYPE 313 | ATTR_FILE_FORKCOUNT 314 | ATTR_FILE_FORKLIST 315 | ATTR_FILE_DATALENGTH 316 | ATTR_FILE_DATAALLOCSIZE 317 | ATTR_FILE_RSRCLENGTH 318 | ATTR_FILE_RSRCALLOCSIZE; 319 pAt->nativeattr.fileattr = 0 320 //|ATTR_FILE_LINKCOUNT 321 | ATTR_FILE_TOTALSIZE 322 | ATTR_FILE_ALLOCSIZE 323 //| ATTR_FILE_IOBLOCKSIZE 324 | ATTR_FILE_DEVTYPE 325 //| ATTR_FILE_FORKCOUNT 326 //| ATTR_FILE_FORKLIST 327 | ATTR_FILE_DATALENGTH 328 | ATTR_FILE_DATAALLOCSIZE 329 | ATTR_FILE_RSRCLENGTH 330 | ATTR_FILE_RSRCALLOCSIZE 331 ; 332 pAt->validattr.forkattr = ATTR_FORK_TOTALSIZE 333 | ATTR_FORK_ALLOCSIZE; 334 pAt->nativeattr.forkattr = 0 335 //| ATTR_FORK_TOTALSIZE 336 //| ATTR_FORK_ALLOCSIZE 337 ; 338 VFSATTR_SET_SUPPORTED(pFsAttr, f_attributes); 354 339 } 355 else 356 PDEBUG("Unable to flush filesystem before unmount, some data might be lost"); 357 } 358 else 359 PDEBUG("Unable to flush child vnodes"); 360 361 } 362 else 363 PDEBUG("Root vnode is in use, can't unmount"); 364 365 vnode_put(pMount->pRootVnode); 366 367 return rc; 368 } 369 370 371 /** 372 * Get VBoxVFS root vnode. 373 * 374 * Handle three cases here: 375 * - vnode does not exist yet: create a new one 376 * - currently creating vnode: wait till the end, increment usage count and return existing one 377 * - vnode already created: increment usage count and return existing one 378 * - vnode was failed to create: give a chance to try to re-create it later 379 * 380 * @param mp Mount data provided by VFS layer. 381 * @param ppVnode vnode to return. 382 * @param pContext kAuth context needed in order to authentificate mount operation. 383 * 384 * @return 0 on success or BSD error code otherwise. 385 */ 386 static int 387 vboxvfs_root(struct mount *mp, struct vnode **ppVnode, vfs_context_t pContext) 388 { 389 NOREF(pContext); 390 391 vboxvfs_mount_t *pMount; 392 int rc = 0; 393 uint32_t vid; 394 395 PDEBUG("Getting root vnode..."); 396 397 AssertReturn(mp, EINVAL); 398 AssertReturn(ppVnode, EINVAL); 399 400 pMount = (vboxvfs_mount_t *)vfs_fsprivate(mp); 401 AssertReturn(pMount, EINVAL); 402 403 /* Check case when vnode does not exist yet */ 404 if (ASMAtomicCmpXchgU8(&pMount->fRootVnodeState, VBOXVFS_OBJECT_INITIALIZING, VBOXVFS_OBJECT_UNINITIALIZED)) 405 { 406 PDEBUG("Create new root vnode"); 407 408 /* Allocate empty SHFLSTRING to indicate path to root vnode within Shared Folder */ 409 char szEmpty[1]; 410 SHFLSTRING *pSFVnodePath; 411 412 pSFVnodePath = vboxvfs_construct_shflstring((char *)szEmpty, 0); 413 if (pSFVnodePath) 414 { 415 int rc2; 416 rc2 = vboxvfs_create_vnode_internal(mp, VDIR, NULL, TRUE, pSFVnodePath, &pMount->pRootVnode); 417 if (rc2 != 0) 340 341 if (VFSATTR_IS_ACTIVE(pFsAttr, f_vol_name)) 418 342 { 419 RT MemFree(pSFVnodePath);420 rc = ENOTSUP;343 RTStrCopy(pFsAttr->f_vol_name, MAXPATHLEN, pThis->MntInfo.szFolder); 344 VFSATTR_SET_SUPPORTED(pFsAttr, f_vol_name); 421 345 } 422 } 423 else 424 rc = ENOMEM; 425 426 /* Notify other threads about result */ 427 if (rc == 0) 428 ASMAtomicWriteU8(&pMount->fRootVnodeState, VBOXVFS_OBJECT_INITIALIZED); 429 else 430 ASMAtomicWriteU8(&pMount->fRootVnodeState, VBOXVFS_OBJECT_INVALID); 431 } 432 else 433 { 434 /* Check case if we are currently creating vnode. Wait while other thread to finish allocation. */ 435 uint8_t fRootVnodeState = VBOXVFS_OBJECT_UNINITIALIZED; 436 while (fRootVnodeState != VBOXVFS_OBJECT_INITIALIZED 437 && fRootVnodeState != VBOXVFS_OBJECT_INVALID) 438 { 439 /** @todo Currently, we are burning CPU cycles while waiting. This is for a short 440 * time but we should relax here! */ 441 fRootVnodeState = ASMAtomicReadU8(&pMount->fRootVnodeState); 442 443 } 444 445 /* Check if the other thread initialized root vnode and it is ready to be returned */ 446 if (fRootVnodeState == VBOXVFS_OBJECT_INITIALIZED) 447 { 448 /* Take care about iocount */ 449 vid = vnode_vid(pMount->pRootVnode); 450 rc = vnode_getwithvid(pMount->pRootVnode, vid); 346 347 rc = 0; 451 348 } 452 349 else 453 350 { 454 /* Other thread reported initialization failure. 455 * Set vnode state VBOXVFS_OBJECT_UNINITIALIZED in order to try recreate root 456 * vnode in other attempt */ 457 ASMAtomicWriteU8(&pMount->fRootVnodeState, VBOXVFS_OBJECT_UNINITIALIZED); 351 Log(("vboxSfOs2QueryFileInfo: VbglR0SfFsInfo failed: %Rrc\n", vrc)); 352 rc = RTErrConvertToErrno(vrc); 458 353 } 459 354 460 } 461 462 /* Only return vnode if we got success */ 463 if (rc == 0) 464 { 465 PDEBUG("Root vnode can be returned"); 466 *ppVnode = pMount->pRootVnode; 355 VbglR0PhysHeapFree(pReq); 467 356 } 468 357 else 469 PDEBUG("Root vnode cannot be returned: 0x%X", rc); 470 358 rc = ENOMEM; 471 359 return rc; 472 360 } 473 361 362 474 363 /** 475 * VBoxVFS get VFS layer object attribute callback.364 * vfsops::vfs_root implementation. 476 365 * 477 * @param mp Mount data provided by VFS layer. 478 * @param pAttr Output buffer to return attributes. 479 * @param pContext kAuth context needed in order to authentificate mount operation. 366 * @returns 0 on success or errno.h value on failure. 367 * @param pMount The mount data structure. 368 * @param ppVnode Where to return the referenced root node on success. 369 * @param pContext Unused kAuth parameter. 370 */ 371 static int vboxSfDwnVfsRoot(mount_t pMount, vnode_t *ppVnode, vfs_context_t pContext) 372 { 373 PVBOXSFMNT pThis = (PVBOXSFMNT)vfs_fsprivate(pMount); 374 AssertReturn(pThis, EBADMSG); 375 LogFlow(("vboxSfDwnVfsRoot: pThis=%p:{%s}\n", pThis, pThis->MntInfo.szFolder)); 376 377 /* 378 * We shouldn't be callable during unmount, should we? 379 */ 380 AssertReturn(vfs_isunmount(pMount), EBUSY); 381 382 /* 383 * There should always be a root node around. 384 */ 385 if (pThis->pVnRoot) 386 { 387 int rc = vnode_get(pThis->pVnRoot); 388 if (rc == 0) 389 { 390 *ppVnode = pThis->pVnRoot; 391 LogFlow(("vboxSfDwnVfsRoot: return %p\n", *ppVnode)); 392 return 0; 393 } 394 Log(("vboxSfDwnVfsRoot: vnode_get failed! %d\n", rc)); 395 return rc; 396 } 397 398 LogRel(("vboxSfDwnVfsRoot: pVnRoot is NULL!\n")); 399 return EILSEQ; 400 } 401 402 403 /** 404 * vfsops::vfs_umount implementation. 480 405 * 481 * @returns 0 for success, else an error code. 482 */ 483 static int 484 vboxvfs_getattr(struct mount *mp, struct vfs_attr *pAttr, vfs_context_t pContext) 406 * @returns 0 on success or errno.h value on failure. 407 * @param pMount The mount data. 408 * @param fFlags Unmount flags. 409 * @param pContext kAuth context which we don't care much about. 410 * 411 */ 412 static int vboxSfDwnVfsUnmount(mount_t pMount, int fFlags, vfs_context_t pContext) 485 413 { 486 NOREF(pContext); 487 488 vboxvfs_mount_t *pMount; 489 SHFLVOLINFO SHFLVolumeInfo; 490 491 int rc; 492 uint32_t cbBuffer = sizeof(SHFLVolumeInfo); 493 494 uint32_t u32bsize; 495 uint64_t u64blocks; 496 uint64_t u64bfree; 497 498 PDEBUG("Getting attribute...\n"); 499 500 AssertReturn(mp, EINVAL); 501 502 pMount = (vboxvfs_mount_t *)vfs_fsprivate(mp); 503 AssertReturn(pMount, EINVAL); 504 AssertReturn(pMount->pShareName, EINVAL); 505 506 rc = VbglR0SfFsInfo(&g_SfClient, &pMount->pMap, 0, SHFL_INFO_GET | SHFL_INFO_VOLUME, 507 &cbBuffer, (PSHFLDIRINFO)&SHFLVolumeInfo); 508 AssertReturn(rc == 0, EPROTO); 509 510 u32bsize = (uint32_t)SHFLVolumeInfo.ulBytesPerAllocationUnit; 511 AssertReturn(u32bsize > 0, ENOTSUP); 512 513 u64blocks = (uint64_t)SHFLVolumeInfo.ullTotalAllocationBytes / (uint64_t)u32bsize; 514 u64bfree = (uint64_t)SHFLVolumeInfo.ullAvailableAllocationBytes / (uint64_t)u32bsize; 515 516 VFSATTR_RETURN(pAttr, f_bsize, u32bsize); 517 VFSATTR_RETURN(pAttr, f_blocks, u64blocks); 518 VFSATTR_RETURN(pAttr, f_bfree, u64bfree); 519 VFSATTR_RETURN(pAttr, f_bavail, u64bfree); 520 VFSATTR_RETURN(pAttr, f_bused, u64blocks - u64bfree); 521 522 VFSATTR_RETURN(pAttr, f_owner, pMount->owner); 523 524 VFSATTR_CLEAR_ACTIVE(pAttr, f_iosize); 525 VFSATTR_CLEAR_ACTIVE(pAttr, f_files); 526 VFSATTR_CLEAR_ACTIVE(pAttr, f_ffree); 527 VFSATTR_CLEAR_ACTIVE(pAttr, f_fssubtype); 528 529 /** @todo take care about f_capabilities and f_attributes, f_fsid */ 530 VFSATTR_CLEAR_ACTIVE(pAttr, f_capabilities); 531 VFSATTR_CLEAR_ACTIVE(pAttr, f_attributes); 532 VFSATTR_CLEAR_ACTIVE(pAttr, f_fsid); 533 534 /** @todo take care about f_create_time, f_modify_time, f_access_time, f_backup_time */ 535 VFSATTR_CLEAR_ACTIVE(pAttr, f_create_time); 536 VFSATTR_CLEAR_ACTIVE(pAttr, f_modify_time); 537 VFSATTR_CLEAR_ACTIVE(pAttr, f_access_time); 538 VFSATTR_CLEAR_ACTIVE(pAttr, f_backup_time); 539 540 VFSATTR_CLEAR_ACTIVE(pAttr, f_signature); 541 VFSATTR_CLEAR_ACTIVE(pAttr, f_carbon_fsid); 542 VFSATTR_CLEAR_ACTIVE(pAttr, f_uuid); 543 544 if (VFSATTR_IS_ACTIVE(pAttr, f_vol_name)) 545 { 546 strlcpy(pAttr->f_vol_name, (char*)pMount->pShareName->String.utf8, MAXPATHLEN); 547 VFSATTR_SET_SUPPORTED(pAttr, f_vol_name); 548 } 549 550 VFSATTR_ALL_SUPPORTED(pAttr); 551 414 PVBOXSFMNT pThis = (PVBOXSFMNT)vfs_fsprivate(pMount); 415 AssertReturn(pThis, 0); 416 LogFlowFunc(("pThis=%p:{%s} fFlags=%#x\n", pThis, pThis->MntInfo.szFolder, fFlags)); 417 418 /* 419 * Flush vnodes. 420 */ 421 int rc = vflush(pMount, pThis->pVnRoot, fFlags & MNT_FORCE ? FORCECLOSE : 0); 422 if (rc == 0) 423 { 424 /* 425 * Is the file system still busy? 426 * 427 * Until we find a way of killing any active host calls, we cannot properly 428 * respect the MNT_FORCE flag here. So, MNT_FORCE is ignored here. 429 */ 430 if ( !pThis->pVnRoot 431 || !vnode_isinuse(pThis->pVnRoot, 1)) 432 { 433 /* 434 * Release our root vnode reference and do another flush. 435 */ 436 if (pThis->pVnRoot) 437 { 438 vnode_put(pThis->pVnRoot); 439 pThis->pVnRoot = NULL; 440 } 441 vflush(pMount, NULLVP, FORCECLOSE); 442 443 /* 444 * Unmap the shared folder and destroy our mount info structure. 445 */ 446 vfs_setfsprivate(pMount, NULL); 447 448 rc = VbglR0SfUnmapFolder(&g_SfClientDarwin, &pThis->hHostFolder); 449 AssertRC(rc); 450 451 RT_ZERO(*pThis); 452 RTMemFree(pThis); 453 454 vfs_clearflags(pMount, MNT_LOCAL); /* ?? */ 455 rc = 0; 456 457 g_cVBoxSfMounts--; 458 } 459 else 460 { 461 Log(("VBoxSF: umount failed: file system busy! (%s)\n", pThis->MntInfo.szFolder)); 462 rc = EBUSY; 463 } 464 } 465 return rc; 466 } 467 468 469 /** 470 * vfsops::vfs_start implementation. 471 */ 472 static int vboxSfDwnVfsStart(mount_t pMount, int fFlags, vfs_context_t pContext) 473 { 474 RT_NOREF(pMount, fFlags, pContext); 552 475 return 0; 553 476 } 554 477 478 479 /** 480 * vfsops::vfs_mount implementation. 481 * 482 * @returns 0 on success or errno.h value on failure. 483 * @param pMount The mount data structure. 484 * @param pDevVp The device to mount. Not used by us. 485 * @param pUserData User space address of parameters supplied to mount(). 486 * We expect a VBOXSFDRWNMOUNTINFO structure. 487 * @param pContext kAuth context needed in order to authentificate mount 488 * operation. 489 */ 490 static int vboxSfDwnVfsMount(mount_t pMount, vnode_t pDevVp, user_addr_t pUserData, vfs_context_t pContext) 491 { 492 RT_NOREF(pDevVp) 493 494 /* 495 * We don't support mount updating. 496 */ 497 if (vfs_isupdate(pMount)) 498 { 499 LogRel(("VBoxSF: mount: MNT_UPDATE is not supported.\n")); 500 return ENOTSUP; 501 } 502 if (pUserData == USER_ADDR_NULL) 503 { 504 LogRel(("VBoxSF: mount: pUserData is NULL.\n")); 505 return EINVAL; 506 } 507 struct vfsstatfs *pFsStats = vfs_statfs(pMount); 508 AssertReturn(pFsStats, EINVAL); 509 510 /* 511 * Get the mount information from userland. 512 */ 513 PVBOXSFMNT pThis = (PVBOXSFMNT)RTMemAllocZ(sizeof(*pThis)); 514 if (!pThis) 515 return ENOMEM; 516 pThis->uidMounter = pFsStats->f_owner; 517 518 int rc = RTR0MemUserCopyFrom(&pThis->MntInfo, (RTR3PTR)pUserData, sizeof(pThis->MntInfo)); 519 if (RT_FAILURE(rc)) 520 { 521 LogRel(("VBoxSF: mount: Failed to copy in mount user data: %Rrc\n", rc)); 522 rc = EFAULT; 523 } 524 else if (pThis->MntInfo.u32Magic != VBOXSFDRWNMOUNTINFO_MAGIC) 525 { 526 LogRel(("VBoxSF: mount: Invalid user data magic (%#x)\n", pThis->MntInfo.u32Magic)); 527 rc = EINVAL; 528 } 529 else if ( (rc = RTStrValidateEncodingEx(pThis->MntInfo.szFolder, sizeof(pThis->MntInfo.szFolder), 530 RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED)) != VINF_SUCCESS 531 || pThis->MntInfo.szFolder[0] == '\0') 532 { 533 LogRel(("VBoxSF: mount: Invalid or empty share name!\n")); 534 rc = EINVAL; 535 } 536 else 537 { 538 /* 539 * Try map the shared folder. 540 */ 541 if (vboxSfDwnConnect()) 542 { 543 PSHFLSTRING pName = ShflStringDupUtf8(pThis->MntInfo.szFolder); 544 if (pName) 545 { 546 rc = VbglR0SfMapFolder(&g_SfClientDarwin, pName, &pThis->hHostFolder); 547 RTMemFree(pName); 548 if (RT_SUCCESS(rc)) 549 { 550 551 /* 552 * Create a root node, that avoid races later. 553 */ 554 pThis->pVnRoot = vboxSfDwnVnAlloc(pMount, VDIR, NULL /*pParent*/, 0); 555 if (pThis->pVnRoot) 556 { 557 /* 558 * Fill file system stats with dummy data. 559 */ 560 pFsStats->f_bsize = 512; 561 pFsStats->f_iosize = _64K; 562 pFsStats->f_blocks = _1M; 563 pFsStats->f_bavail = _1M / 4 * 3; 564 pFsStats->f_bused = _1M / 4; 565 pFsStats->f_files = 1024; 566 pFsStats->f_ffree = _64K; 567 vfs_getnewfsid(pMount); /* f_fsid */ 568 /* pFsStats->f_fowner - don't touch */ 569 /* pFsStats->f_fstypename - don't touch */ 570 /* pFsStats->f_mntonname - don't touch */ 571 RTStrCopy(pFsStats->f_mntfromname, sizeof(pFsStats->f_mntfromname), pThis->MntInfo.szFolder); 572 /* pFsStats->f_fssubtype - don't touch? */ 573 /* pFsStats->f_reserved[0] - don't touch? */ 574 /* pFsStats->f_reserved[1] - don't touch? */ 575 576 /* 577 * We're good. Set private data and flags. 578 */ 579 vfs_setfsprivate(pMount, pThis); 580 vfs_setflags(pMount, MNT_SYNCHRONOUS | MNT_NOSUID | MNT_NODEV); 581 /** @todo Consider flags like MNT_NOEXEC ? */ 582 583 /// @todo vfs_setauthopaque(pMount)? 584 /// @todo vfs_clearauthopaqueaccess(pMount)? 585 /// @todo vfs_clearextendedsecurity(pMount)? 586 587 LogRel(("VBoxSF: mount: Successfully mounted '%s' (uidMounter=%u).\n", 588 pThis->MntInfo.szFolder, pThis->uidMounter)); 589 return 0; 590 } 591 592 LogRel(("VBoxSF: mount: Failed to allocate root node!\n")); 593 rc = ENOMEM; 594 } 595 else 596 { 597 LogRel(("VBoxSF: mount: VbglR0SfMapFolder failed on '%s': %Rrc\n", pThis->MntInfo.szFolder, rc)); 598 rc = ENOENT; 599 } 600 } 601 else 602 rc = ENOMEM; 603 } 604 else 605 { 606 LogRel(("VBoxSF: mount: Not connected to shared folders service!\n")); 607 rc = ENOTCONN; 608 } 609 } 610 RTMemFree(pThis); 611 return rc; 612 } 613 614 555 615 /** 556 616 * VFS operations … … 558 618 struct vfsops g_VBoxSfVfsOps = 559 619 { 560 /* Standard operations */ 561 &vboxvfs_mount, 562 NULL, /* Skipped: vfs_start() */ 563 &vboxvfs_unmount, 564 &vboxvfs_root, 620 vboxSfDwnVfsMount, 621 vboxSfDwnVfsStart, 622 vboxSfDwnVfsUnmount, 623 vboxSfDwnVfsRoot, 565 624 NULL, /* Skipped: vfs_quotactl */ 566 &vboxvfs_getattr,625 vboxSfDwnVfsGetAttr, 567 626 NULL, /* Skipped: vfs_sync */ 568 627 NULL, /* Skipped: vfs_vget */ -
trunk/src/VBox/Additions/darwin/VBoxSF/VBoxSF.cpp
r75666 r75675 20 20 * Header Files * 21 21 *********************************************************************************************************************************/ 22 #define LOG_GROUP LOG_GROUP_ DEFAULT22 #define LOG_GROUP LOG_GROUP_SHARED_FOLDERS 23 23 #include "VBoxSFInternal.h" 24 24 25 25 #include <iprt/asm.h> 26 26 #include <iprt/assert.h> 27 #include <iprt/initterm.h> 27 28 #include <VBox/version.h> 28 29 #include <VBox/log.h> … … 30 31 31 32 /********************************************************************************************************************************* 32 * Structures and Typedefs*33 * Internal Functions * 33 34 *********************************************************************************************************************************/ 34 /** 35 * The service class for this driver. 36 * 37 * This has one purpose: Use waitForMatchingService() to find VBoxGuest. 38 */ 39 class org_virtualbox_VBoxSF : public IOService 40 { 41 OSDeclareDefaultStructors(org_virtualbox_VBoxSF); 42 43 private: 44 IOService *waitForCoreService(void); 45 46 IOService *m_pCoreService; 47 48 public: 49 virtual bool start(IOService *pProvider); 50 virtual void stop(IOService *pProvider); 51 }; 52 53 OSDefineMetaClassAndStructors(org_virtualbox_VBoxSF, IOService); 35 static kern_return_t vboxSfDwnModuleLoad(struct kmod_info *pKModInfo, void *pvData); 36 static kern_return_t vboxSfDwnModuleUnload(struct kmod_info *pKModInfo, void *pvData); 54 37 55 38 … … 57 40 * Global Variables * 58 41 *********************************************************************************************************************************/ 59 /** 60 * Declare the module stuff. 61 */ 62 RT_C_DECLS_BEGIN 63 static kern_return_t VBoxSfModuleLoad(struct kmod_info *pKModInfo, void *pvData); 64 static kern_return_t VBoxSfModuleUnload(struct kmod_info *pKModInfo, void *pvData); 65 extern kern_return_t _start(struct kmod_info *pKModInfo, void *pvData); 66 extern kern_return_t _stop(struct kmod_info *pKModInfo, void *pvData); 67 KMOD_EXPLICIT_DECL(VBoxVFS, VBOX_VERSION_STRING, _start, _stop) 68 DECLHIDDEN(kmod_start_func_t *) _realmain = VBoxSfModuleLoad; 69 DECLHIDDEN(kmod_stop_func_t *) _antimain = VBoxSfModuleUnload; 70 DECLHIDDEN(int) _kext_apple_cc = __APPLE_CC__; 71 RT_C_DECLS_END 72 73 /** The org_virtualbox_VBoxSF instance. 74 * Used for preventing multiple instantiations. */ 75 static org_virtualbox_VBoxSF *g_pService = NULL; 76 42 /** The VBoxGuest service if we've managed to connect to it already. */ 43 static IOService *g_pVBoxGuest = NULL; 77 44 /** The shared folder service client structure. */ 78 VBGLSFCLIENT g_SfClient; 45 VBGLSFCLIENT g_SfClientDarwin = { UINT32_MAX, NULL }; 46 /** Number of active mounts. Used for unload prevention. */ 47 uint32_t volatile g_cVBoxSfMounts = 0; 48 79 49 /* VBoxVFS filesystem handle. Needed for FS unregistering. */ 80 50 static vfstable_t g_pVBoxSfVfsTableEntry; 81 82 51 /** For vfs_fsentry. */ 83 52 static struct vnodeopv_desc *g_apVBoxSfVnodeOpDescList[] = … … 85 54 &g_VBoxSfVnodeOpvDesc, 86 55 }; 87 88 89 56 /** VFS registration structure. */ 90 static struct vfs_fsentry g_VBoxSfFsEntry =57 static struct vfs_fsentry g_VBoxSfFsEntry = 91 58 { 92 59 .vfe_vfsops = &g_VBoxSfVfsOps, … … 105 72 106 73 /** 107 * KEXT Module BSD entry point 108 */ 109 static kern_return_t VBoxSfModuleLoad(struct kmod_info *pKModInfo, void *pvData) 110 { 111 /* Initialize the R0 guest library. */ 112 #if 0 113 rc = VbglR0SfInit(); 114 if (RT_FAILURE(rc)) 115 return KERN_FAILURE; 74 * Declare the module stuff. 75 */ 76 RT_C_DECLS_BEGIN 77 extern kern_return_t _start(struct kmod_info *pKModInfo, void *pvData); 78 extern kern_return_t _stop(struct kmod_info *pKModInfo, void *pvData); 79 80 KMOD_EXPLICIT_DECL(VBoxVFS, VBOX_VERSION_STRING, _start, _stop) 81 DECLHIDDEN(kmod_start_func_t *) _realmain = vboxSfDwnModuleLoad; 82 DECLHIDDEN(kmod_stop_func_t *) _antimain = vboxSfDwnModuleUnload; 83 DECLHIDDEN(int) _kext_apple_cc = __APPLE_CC__; 84 RT_C_DECLS_END 85 86 87 /** 88 * Connect to VBoxGuest and host shared folders service. 89 * 90 * @returns true if connected, false if not. 91 */ 92 bool vboxSfDwnConnect(void) 93 { 94 /* 95 * Grab VBoxGuest - since it's a dependency of this module, it shouldn't be hard. 96 */ 97 if (!g_pVBoxGuest) 98 { 99 OSDictionary *pServiceMatcher = IOService::serviceMatching("org_virtualbox_VBoxGuest"); 100 if (pServiceMatcher) 101 { 102 IOService *pVBoxGuest = IOService::waitForMatchingService(pServiceMatcher, 10 * RT_NS_1SEC); 103 if (pVBoxGuest) 104 g_pVBoxGuest = pVBoxGuest; 105 else 106 LogRel(("vboxSfDwnConnect: IOService::waitForMatchingService failed!!\n")); 107 } 108 else 109 LogRel(("vboxSfDwnConnect: serviceMatching failed\n")); 110 } 111 112 if (g_pVBoxGuest) 113 { 114 /* 115 * Get hold of the shared folders service if we haven't already. 116 */ 117 if (g_SfClientDarwin.handle != NULL) 118 return true; 119 120 int rc = VbglR0SfConnect(&g_SfClientDarwin); 121 if (RT_SUCCESS(rc)) 122 { 123 rc = VbglR0SfSetUtf8(&g_SfClientDarwin); 124 if (RT_SUCCESS(rc)) 125 return true; 126 127 LogRel(("VBoxSF: VbglR0SfSetUtf8 failed: %Rrc\n", rc)); 128 129 VbglR0SfDisconnect(&g_SfClientDarwin); 130 g_SfClientDarwin.handle = NULL; 131 } 132 else 133 LogRel(("VBoxSF: VbglR0SfConnect failed: %Rrc\n", rc)); 134 } 135 136 return false; 137 } 138 139 140 /** 141 * Start the kernel module. 142 */ 143 static kern_return_t vboxSfDwnModuleLoad(struct kmod_info *pKModInfo, void *pvData) 144 { 145 RT_NOREF(pKModInfo, pvData); 146 #ifdef DEBUG 147 printf("vboxSfDwnModuleLoad\n"); 148 RTLogBackdoorPrintf("vboxSfDwnModuleLoad\n"); 116 149 #endif 117 150 118 PINFO("VirtualBox " VBOX_VERSION_STRING " shared folders " 119 "driver is loaded"); 120 151 /* 152 * Initialize IPRT and the ring-0 guest library. 153 */ 154 int rc = RTR0Init(0); 155 if (RT_SUCCESS(rc)) 156 { 157 rc = VbglR0SfInit(); 158 if (RT_SUCCESS(rc)) 159 { 160 /* 161 * Register the file system. 162 */ 163 rc = vfs_fsadd(&g_VBoxSfFsEntry, &g_pVBoxSfVfsTableEntry); 164 if (rc == 0) 165 { 166 /* 167 * Try find VBoxGuest and connect to the shared folders service on the host. 168 */ 169 /** @todo should we just ignore the error here and retry at mount time? 170 * Technically, VBoxGuest should be available since it's one of our 171 * dependencies... */ 172 vboxSfDwnConnect(); 173 174 /* 175 * We're done for now. We'll deal with 176 */ 177 LogRel(("VBoxSF: loaded\n")); 178 return KERN_SUCCESS; 179 } 180 181 printf("VBoxSF: vfs_fsadd failed: %d\n", rc); 182 RTLogBackdoorPrintf("VBoxSF: vfs_fsadd failed: %d\n", rc); 183 VbglR0SfTerm(); 184 } 185 else 186 { 187 printf("VBoxSF: VbglR0SfInit failed: %d\n", rc); 188 RTLogBackdoorPrintf("VBoxSF: VbglR0SfInit failed: %Rrc\n", rc); 189 } 190 RTR0Term(); 191 } 192 else 193 { 194 printf("VBoxSF: RTR0Init failed: %d\n", rc); 195 RTLogBackdoorPrintf("VBoxSF: RTR0Init failed: %Rrc\n", rc); 196 } 197 return KERN_FAILURE; 198 } 199 200 201 /** 202 * Stop the kernel module. 203 */ 204 static kern_return_t vboxSfDwnModuleUnload(struct kmod_info *pKModInfo, void *pvData) 205 { 206 #ifdef DEBUG 207 printf("vboxSfDwnModuleUnload\n"); 208 RTLogBackdoorPrintf("vboxSfDwnModuleUnload\n"); 209 #endif 210 211 /* 212 * Are we busy? If so fail. 213 */ 214 if (g_cVBoxSfMounts > 0) 215 { 216 LogRel(("VBoxSF: Refusing to unload with %u active mounts\n", g_cVBoxSfMounts)); 217 return KERN_NO_ACCESS; 218 } 219 220 /* 221 * Disconnect and terminate libraries we're using. 222 */ 223 224 if (g_SfClientDarwin.handle != NULL) 225 { 226 VbglR0SfDisconnect(&g_SfClientDarwin); 227 g_SfClientDarwin.handle = NULL; 228 } 229 230 if (g_pVBoxGuest) 231 { 232 g_pVBoxGuest->release(); 233 g_pVBoxGuest = NULL; 234 } 235 236 VbglR0SfTerm(); 237 RTR0Term(); 121 238 return KERN_SUCCESS; 122 239 } 123 240 124 125 /**126 * KEXT Module BSD exit point127 */128 static kern_return_t VBoxSfModuleUnload(struct kmod_info *pKModInfo, void *pvData)129 {130 #if 0131 VbglR0SfTerm();132 #endif133 134 PINFO("VirtualBox " VBOX_VERSION_STRING " shared folders driver is unloaded");135 136 return KERN_SUCCESS;137 }138 139 /**140 * Wait for VBoxGuest.kext to be started141 */142 IOService *org_virtualbox_VBoxSF::waitForCoreService(void)143 {144 OSDictionary *pServiceToMatach = serviceMatching("org_virtualbox_VBoxGuest");145 if (pServiceToMatach)146 {147 /* Wait 15 seconds for VBoxGuest to be started */148 IOService *pService = waitForMatchingService(pServiceToMatach, 15 * RT_NS_1SEC_64);149 pServiceToMatach->release();150 return pService;151 }152 PINFO("unable to create matching dictionary");153 return NULL;154 }155 156 157 /**158 * Start this service.159 */160 bool org_virtualbox_VBoxSF::start(IOService *pProvider)161 {162 if (g_pService == NULL)163 g_pService = this;164 else165 {166 printf("org_virtualbox_VBoxSF::start: g_pService=%p this=%p -> false\n", g_pService, this);167 return false;168 }169 170 if (IOService::start(pProvider))171 {172 /*173 * Get hold of VBoxGuest.174 */175 m_pCoreService = waitForCoreService();176 if (m_pCoreService)177 {178 int rc = VbglR0SfInit();179 if (RT_SUCCESS(rc))180 {181 /*182 * Connect to the host service and set UTF-8 as the string encoding to use.183 */184 rc = VbglR0SfConnect(&g_SfClient);185 if (RT_SUCCESS(rc))186 {187 rc = VbglR0SfSetUtf8(&g_SfClient);188 if (RT_SUCCESS(rc))189 {190 /*191 * Register the file system.192 */193 rc = vfs_fsadd(&g_VBoxSfFsEntry, &g_pVBoxSfVfsTableEntry);194 if (rc == 0)195 {196 registerService();197 198 LogRel(("VBoxSF: ready\n"));199 return true;200 }201 202 LogRel(("VBoxSF: vfs_fsadd failed: %d\n", rc));203 }204 else205 LogRel(("VBoxSF: VbglR0SfSetUtf8 failed: %Rrc\n", rc));206 VbglR0SfDisconnect(&g_SfClient);207 }208 else209 LogRel(("VBoxSF: VbglR0SfConnect failed: %Rrc\n", rc));210 VbglR0SfTerm();211 }212 else213 LogRel(("VBoxSF: VbglR0SfInit failed: %Rrc\n", rc));214 m_pCoreService->release();215 }216 else217 LogRel(("VBoxSF: Failed to find VBoxGuest!\n"));218 219 IOService::stop(pProvider);220 }221 g_pService = NULL;222 return false;223 }224 225 226 /**227 * Stop this service.228 */229 void org_virtualbox_VBoxSF::stop(IOService *pProvider)230 {231 if (m_pCoreService == this)232 {233 /*234 * Unregister the filesystem.235 */236 if (g_pVBoxSfVfsTableEntry != NULL)237 {238 int rc = vfs_fsremove(g_pVBoxSfVfsTableEntry);239 if (rc == 0)240 {241 g_pVBoxSfVfsTableEntry = NULL;242 PINFO("VBoxVFS filesystem successfully unregistered");243 }244 else245 {246 PINFO("Unable to unregister the VBoxSF filesystem (%d)", rc);247 /** @todo how on earth do we deal with this... Gues we shouldn't be using248 * IOService at all here. sigh. */249 }250 }251 VbglR0SfDisconnect(&g_SfClient);252 VbglR0SfTerm();253 if (m_pCoreService)254 m_pCoreService->release();255 256 }257 IOService::stop(pProvider);258 }259 -
trunk/src/VBox/Additions/darwin/VBoxSF/VBoxSFInternal.h
r75666 r75675 39 39 #include <sys/param.h> 40 40 #include <sys/vnode.h> 41 #include <vfs/vfs_support.h> 41 42 #undef PVM 42 43 44 #include <iprt/mem.h> 45 #include <VBox/VBoxGuest.h> 43 46 #include <VBox/VBoxGuestLibSharedFolders.h> 44 47 … … 59 62 typedef struct vboxvfs_mount_data 60 63 { 61 VBGLSFMAP pMap; /** Shared folder mapping */ 62 SHFLSTRING *pShareName; /** VBoxVFS share name */ 63 uint64_t cFileIdCounter; /** Counter that used in order to assign unique ID to each vnode within mounted share */ 64 vnode_t pRootVnode; /** VFS object: vnode that corresponds shared folder root */ 65 uint8_t volatile fRootVnodeState; /** Sync flag that used in order to safely allocate pRootVnode */ 66 uid_t owner; /** User ID tha mounted shared folder */ 67 lck_grp_t *pLockGroup; /** BSD locking stuff */ 68 lck_grp_attr_t *pLockGroupAttr; /** BSD locking stuff */ 69 } vboxvfs_mount_t; 64 /** The shared folder mapping */ 65 VBGLSFMAP hHostFolder; 66 /** The root VNode. */ 67 vnode_t pVnRoot; 68 /** User that mounted shared folder (anyone but root?). */ 69 uid_t uidMounter; 70 /** The mount info from the mount() call. */ 71 VBOXSFDRWNMOUNTINFO MntInfo; 72 } vboxvfs_mount_t, VBOXSFMNT; 73 typedef VBOXSFMNT *PVBOXSFMNT; 70 74 71 75 /** Private data assigned to each vnode object. */ 72 76 typedef struct vboxvfs_vnode_data 73 77 { 74 SHFLHANDLE pHandle; /** VBoxVFS object handle. */ 75 PSHFLSTRING pPath; /** Path within shared folder */ 76 lck_attr_t *pLockAttr; /** BSD locking stuff */ 77 lck_rw_t *pLock; /** BSD locking stuff */ 78 } vboxvfs_vnode_t; 78 SHFLHANDLE hHandle; /** VBoxVFS object handle. */ 79 ///PSHFLSTRING pPath; /** Path within shared folder */ 80 ///lck_attr_t *pLockAttr; /** BSD locking stuff */ 81 ///lck_rw_t *pLock; /** BSD locking stuff */ 82 } vboxvfs_vnode_t, VBOXSFDWNVNDATA; 83 /** Private vnode data. */ 84 typedef VBOXSFDWNVNDATA *PVBOXSFDWNVNDATA; 85 79 86 80 87 … … 82 89 * Global Variables * 83 90 *********************************************************************************************************************************/ 84 extern VBGLSFCLIENT g_SfClient; 91 extern VBGLSFCLIENT g_SfClientDarwin; 92 extern uint32_t volatile g_cVBoxSfMounts; 85 93 extern struct vfsops g_VBoxSfVfsOps; 86 94 extern struct vnodeopv_desc g_VBoxSfVnodeOpvDesc; … … 91 99 * Functions * 92 100 *********************************************************************************************************************************/ 101 bool vboxSfDwnConnect(void); 102 vnode_t vboxSfDwnVnAlloc(mount_t pMount, enum vtype enmType, vnode_t pParent, uint64_t cbFile); 103 104 105 93 106 94 107 /** … … 228 241 extern SHFLSTRING *vboxvfs_construct_shflstring(const char *pszName, size_t cchName); 229 242 230 extern int vboxvfs_register_filesystem(void);231 extern int vboxvfs_unregister_filesystem(void);232 233 243 234 244 #endif
Note:
See TracChangeset
for help on using the changeset viewer.