Changeset 75407 in vbox
- Timestamp:
- Nov 12, 2018 8:06:57 PM (6 years ago)
- Location:
- trunk
- Files:
-
- 13 edited
-
include/VBox/VBoxGuestLib.h (modified) (1 diff)
-
include/VBox/shflsvc.h (modified) (7 diffs)
-
src/VBox/Additions/WINNT/VBoxTray/Makefile.kmk (modified) (1 diff)
-
src/VBox/Additions/WINNT/VBoxTray/VBoxTray.cpp (modified) (2 diffs)
-
src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibSharedFolders.cpp (modified) (5 diffs)
-
src/VBox/Additions/common/VBoxService/Makefile.kmk (modified) (6 diffs)
-
src/VBox/Additions/common/VBoxService/VBoxServiceAutoMount.cpp (modified) (25 diffs)
-
src/VBox/Additions/linux/sharedfolders/vfsmod.c (modified) (1 diff)
-
src/VBox/HostServices/SharedFolders/mappings.cpp (modified) (20 diffs)
-
src/VBox/HostServices/SharedFolders/mappings.h (modified) (3 diffs)
-
src/VBox/HostServices/SharedFolders/service.cpp (modified) (7 diffs)
-
src/VBox/HostServices/SharedFolders/shfl.h (modified) (1 diff)
-
src/VBox/HostServices/SharedFolders/vbsf.h (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/VBoxGuestLib.h
r74535 r75407 682 682 PVBGLR3SHAREDFOLDERMAPPING *ppaMappings, uint32_t *pcMappings); 683 683 VBGLR3DECL(void) VbglR3SharedFolderFreeMappings(PVBGLR3SHAREDFOLDERMAPPING paMappings); 684 VBGLR3DECL(int) VbglR3SharedFolderGetName(HGCMCLIENTID idClient,uint32_t u32Root, char **ppszName); 685 VBGLR3DECL(int) VbglR3SharedFolderGetMountPrefix(char **ppszPrefix); 686 VBGLR3DECL(int) VbglR3SharedFolderGetMountDir(char **ppszDir); 684 VBGLR3DECL(int) VbglR3SharedFolderGetName(HGCMCLIENTID idClient,uint32_t u32Root, char **ppszName); /**< @todo r=bird: GET functions return the value, not a status code!*/ 685 VBGLR3DECL(int) VbglR3SharedFolderQueryFolderInfo(HGCMCLIENTID idClient, uint32_t idRoot, uint64_t fQueryFlags, 686 char **ppszName, char **ppszMountPoint, 687 uint64_t *pfFlags, uint32_t *puRootIdVersion); 688 VBGLR3DECL(int) VbglR3SharedFolderWaitForMappingsChanges(HGCMCLIENTID idClient, uint32_t uPrevVersion, uint32_t *puCurVersion); 689 VBGLR3DECL(int) VbglR3SharedFolderCancelMappingsChangesWaits(HGCMCLIENTID idClient); 690 691 VBGLR3DECL(int) VbglR3SharedFolderGetMountPrefix(char **ppszPrefix); /**< @todo r=bird: GET functions return the value, not a status code! */ 692 VBGLR3DECL(int) VbglR3SharedFolderGetMountDir(char **ppszDir); /**< @todo r=bird: GET functions return the value, not a status code! */ 687 693 /** @} */ 688 694 # endif /* VBOX_WITH_SHARED_FOLDERS defined */ -
trunk/include/VBox/shflsvc.h
r75384 r75407 77 77 * @{ 78 78 */ 79 /** Query mappings changes. */ 79 /** Query mappings changes. 80 * @note Description is currently misleading, it will always return all 81 * current mappings with SHFL_MS_NEW status. Only modification is the 82 * SHFL_MF_AUTOMOUNT flag that causes filtering out non-auto mounts. */ 80 83 #define SHFL_FN_QUERY_MAPPINGS (1) 81 /** Query mappings changes. */84 /** Query the name of a map. */ 82 85 #define SHFL_FN_QUERY_MAP_NAME (2) 83 86 /** Open/create object. */ … … 118 121 * @since VBox 4.0 */ 119 122 #define SHFL_FN_SET_SYMLINKS (20) 123 /** Query information about a map. 124 * @since VBox 6.0 */ 125 #define SHFL_FN_QUERY_MAP_INFO (21) 126 /** Wait for changes to the mappings. 127 * @since VBox 6.0 */ 128 #define SHFL_FN_WAIT_FOR_MAPPINGS_CHANGES (22) 129 /** Cancel all waits for changes to the mappings for the calling client. 130 * The wait calls will return VERR_CANCELLED. 131 * @since VBox 6.0 */ 132 #define SHFL_FN_CANCEL_MAPPINGS_CHANGES_WAITS (23) 120 133 /** @} */ 121 134 … … 240 253 * Helper for copying one string into another. 241 254 * 242 * @returns pDst243 * @ param pDst The destination string. Assumed to be the same size as244 * the source.255 * @returns IPRT status code. 256 * @retval VERR_BUFFER_OVERFLOW and pDst->u16Length set to source length. 257 * @param pDst The destination string. 245 258 * @param pSrc The source string. 246 */ 247 DECLINLINE(PSHFLSTRING) ShflStringCopy(PSHFLSTRING pDst, PCSHFLSTRING pSrc) 248 { 259 * @param cbTerm The size of the string terminator. 260 */ 261 DECLINLINE(int) ShflStringCopy(PSHFLSTRING pDst, PCSHFLSTRING pSrc, size_t cbTerm) 262 { 263 int rc = VINF_SUCCESS; 264 if (pDst->u16Size >= pSrc->u16Length + cbTerm) 265 { 266 memcpy(&pDst->String, &pSrc->String, pSrc->u16Length); 267 switch (cbTerm) 268 { 269 default: 270 case 2: pDst->String.ach[pSrc->u16Length + 1] = '\0'; RT_FALL_THROUGH(); 271 case 1: pDst->String.ach[pSrc->u16Length + 0] = '\0'; break; 272 case 0: break; 273 } 274 } 275 else 276 rc = VERR_BUFFER_OVERFLOW; 249 277 pDst->u16Length = pSrc->u16Length; 250 pDst->u16Size = pSrc->u16Size; 251 memcpy(&pDst->String, &pSrc->String, pSrc->u16Size); 252 return pDst; 278 return rc; 253 279 } 254 280 … … 265 291 PSHFLSTRING pDst = (PSHFLSTRING)RTMemAlloc(SHFLSTRING_HEADER_SIZE + pSrc->u16Size); 266 292 if (pDst) 267 return ShflStringCopy(pDst, pSrc); 293 { 294 pDst->u16Length = pSrc->u16Length; 295 pDst->u16Size = pSrc->u16Size; 296 memcpy(&pDst->String, &pSrc->String, pSrc->u16Size); 297 } 268 298 return pDst; 269 299 } … … 355 385 AssertMsgFailed(("rc=%Rrc cwcConversion=%#x\n", rc, cwcConversion)); 356 386 return NULL; 387 } 388 389 /** 390 * Copies a UTF-8 string to a buffer as UTF-16. 391 * 392 * @returns IPRT status code. 393 * @param pDst The destination buffer. 394 * @param pszSrc The source string. 395 * @param cchSrc The source string length, or RTSTR_MAX. 396 */ 397 DECLINLINE(int) ShflStringCopyUtf8AsUtf16(PSHFLSTRING pDst, const char *pszSrc, size_t cchSrc) 398 { 399 int rc; 400 size_t cwcDst = 0; 401 if (pDst->u16Size >= sizeof(RTUTF16)) 402 { 403 PRTUTF16 pwszDst = pDst->String.utf16; 404 rc = RTStrToUtf16Ex(pszSrc, cchSrc, &pwszDst, pDst->u16Size / sizeof(RTUTF16), &cwcDst); 405 } 406 else 407 { 408 RTStrCalcUtf16LenEx(pszSrc, cchSrc, &cwcDst); 409 rc = VERR_BUFFER_OVERFLOW; 410 } 411 pDst->u16Length = (uint16_t)(cwcDst * sizeof(RTUTF16)); 412 return rc != VERR_BUFFER_OVERFLOW || cwcDst < UINT16_MAX / sizeof(RTUTF16) ? rc : VERR_TOO_MUCH_DATA; 413 } 414 415 /** 416 * Copies a UTF-8 string buffer to another buffer as UTF-16 417 * 418 * @returns IPRT status code. 419 * @param pDst The destination buffer (UTF-16). 420 * @param pSrc The source buffer (UTF-8). 421 */ 422 DECLINLINE(int) ShflStringCopyUtf8BufAsUtf16(PSHFLSTRING pDst, PCSHFLSTRING pSrc) 423 { 424 return ShflStringCopyUtf8AsUtf16(pDst, pSrc->String.ach, pSrc->u16Length); 425 } 426 427 /** 428 * Copies a UTF-16 string to a buffer as UTF-8 429 * 430 * @returns IPRT status code. 431 * @param pDst The destination buffer. 432 * @param pwszSrc The source string. 433 * @param cwcSrc The source string length, or RTSTR_MAX. 434 */ 435 DECLINLINE(int) ShflStringCopyUtf16AsUtf8(PSHFLSTRING pDst, PCRTUTF16 pwszSrc, size_t cwcSrc) 436 { 437 int rc; 438 size_t cchDst = 0; 439 if (pDst->u16Size > 0) 440 { 441 char *pszDst = pDst->String.ach; 442 rc = RTUtf16ToUtf8Ex(pwszSrc, cwcSrc, &pszDst, pDst->u16Size, &cchDst); 443 } 444 else 445 { 446 RTUtf16CalcUtf8LenEx(pwszSrc, cwcSrc, &cchDst); 447 rc = VERR_BUFFER_OVERFLOW; 448 } 449 pDst->u16Length = (uint16_t)cchDst; 450 return rc != VERR_BUFFER_OVERFLOW || cchDst < UINT16_MAX ? rc : VERR_TOO_MUCH_DATA; 451 } 452 453 /** 454 * Copies a UTF-16 string buffer to another buffer as UTF-8 455 * 456 * @returns IPRT status code. 457 * @param pDst The destination buffer (UTF-8). 458 * @param pSrc The source buffer (UTF-16). 459 */ 460 DECLINLINE(int) ShflStringCopyUtf16BufAsUtf8(PSHFLSTRING pDst, PCSHFLSTRING pSrc) 461 { 462 return ShflStringCopyUtf16AsUtf8(pDst, pSrc->String.utf16, pSrc->u16Length / sizeof(RTUTF16)); 357 463 } 358 464 … … 802 908 typedef struct _SHFLMAPPING 803 909 { 804 /** Mapping status. */ 910 /** Mapping status. 911 * @note Currently always set to SHFL_MS_NEW. */ 805 912 uint32_t u32Status; 806 913 /** Root handle. */ … … 1558 1665 1559 1666 1667 /** @name SHFL_FN_QUERY_MAP_INFO 1668 * @{ 1669 */ 1670 /** Query flag: Guest prefers drive letters as mount points. */ 1671 #define SHFL_MIQF_DRIVE_LETTER RT_BIT_64(0) 1672 /** Query flag: Guest prefers paths as mount points. */ 1673 #define SHFL_MIQF_PATH RT_BIT_64(1) 1674 1675 /** Set if writable. */ 1676 #define SHFL_MIF_WRITABLE RT_BIT_64(0) 1677 /** Indicates that the mapping should be auto-mounted. */ 1678 #define SHFL_MIF_AUTO_MOUNT RT_BIT_64(1) 1679 /** Set if host is case insensitive. */ 1680 #define SHFL_MIF_HOST_ICASE RT_BIT_64(2) 1681 /** Set if guest is case insensitive. */ 1682 #define SHFL_MIF_GUEST_ICASE RT_BIT_64(3) 1683 /** Symbolic link creation is allowed. */ 1684 #define SHFL_MIF_SYMLINK_CREATION RT_BIT_64(4) 1685 1686 /** Parameters structure. */ 1687 typedef struct VBoxSFQueryMapInfo 1688 { 1689 /** Common header. */ 1690 VBGLIOCHGCMCALL callInfo; 1691 /** 32-bit, in: SHFLROOT - root handle of the mapping to query. */ 1692 HGCMFunctionParameter root; 1693 /** pointer, in/out: SHFLSTRING buffer for the name. */ 1694 HGCMFunctionParameter name; 1695 /** pointer, in/out: SHFLSTRING buffer for the auto mount point. */ 1696 HGCMFunctionParameter mountPoint; 1697 /** 64-bit, in: SHFL_MIQF_XXX; out: SHFL_MIF_XXX. */ 1698 HGCMFunctionParameter flags; 1699 /** 32-bit, out: Root ID version number - root handle reuse guard. */ 1700 HGCMFunctionParameter rootIdVersion; 1701 } VBoxSFQueryMapInfo; 1702 /** Number of parameters */ 1703 #define SHFL_CPARMS_QUERY_MAP_INFO (5) 1704 /** @} */ 1705 1706 1707 /** @name SHFL_FN_WAIT_FOR_MAPPINGS_CHANGES 1708 * 1709 * Returns VINF_SUCCESS on change and VINF_TRY_AGAIN when restored from saved 1710 * state. If the guest makes too many calls (max 64) VERR_OUT_OF_RESOURCES will 1711 * be returned. 1712 * 1713 * @{ 1714 */ 1715 /** Parameters structure. */ 1716 typedef struct VBoxSFWaitForMappingsChanges 1717 { 1718 /** Common header. */ 1719 VBGLIOCHGCMCALL callInfo; 1720 /** 32-bit, in/out: The mappings configuration version. 1721 * On input the client sets it to the last config it knows about, on return 1722 * it holds the current version. */ 1723 HGCMFunctionParameter version; 1724 } VBoxSFWaitForMappingsChanges; 1725 /** Number of parameters */ 1726 #define SHFL_CPARMS_WAIT_FOR_MAPPINGS_CHANGES (1) 1727 /** @} */ 1728 1729 1730 /** @name SHFL_FN_CANCEL_MAPPINGS_CHANGES_WAITS 1731 * @{ 1732 */ 1733 /** Number of parameters */ 1734 #define SHFL_CPARMS_CANCEL_MAPPINGS_CHANGES_WAITS (0) 1735 /** @} */ 1736 1560 1737 1561 1738 /** @name SHFL_FN_ADD_MAPPING -
trunk/src/VBox/Additions/WINNT/VBoxTray/Makefile.kmk
r70378 r75407 65 65 VBoxLA.cpp 66 66 endif 67 ifdef VBOX_WITH_SHARED_FOLDERS 68 VBoxTray_DEFS += VBOX_WITH_SHARED_FOLDERS 69 VBoxTray_SOURCES += \ 70 VBoxSharedFolders.cpp 71 VBoxTray_LIBS.win += \ 72 mpr.lib 73 endif 67 ## Now handled by VBoxService. 68 #ifdef VBOX_WITH_SHARED_FOLDERS 69 # VBoxTray_DEFS += VBOX_WITH_SHARED_FOLDERS 70 # VBoxTray_SOURCES += \ 71 # VBoxSharedFolders.cpp 72 # VBoxTray_LIBS.win += \ 73 # mpr.lib 74 #endif 74 75 ifdef VBOX_WITH_WDDM 75 76 VBoxTray_DEFS += VBOX_WITH_WDDM -
trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxTray.cpp
r74528 r75407 31 31 #include "VBoxVRDP.h" 32 32 #include "VBoxHostVersion.h" 33 #include "VBoxSharedFolders.h" 33 #ifdef VBOX_WITH_SHARED_FOLDERS 34 # include "VBoxSharedFolders.h" 35 #endif 34 36 #ifdef VBOX_WITH_DRAG_AND_DROP 35 37 # include "VBoxDnD.h" … … 825 827 if (RT_SUCCESS(rc)) 826 828 { 829 #ifdef VBOX_WITH_SHARED_FOLDERS 827 830 /* Do the Shared Folders auto-mounting stuff. */ 828 831 rc = VBoxSharedFoldersAutoMount(); 832 #endif 829 833 if (RT_SUCCESS(rc)) 830 834 { -
trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibSharedFolders.cpp
r69500 r75407 161 161 } 162 162 } 163 } while (rc == VINF_BUFFER_OVERFLOW); 163 } while (rc == VINF_BUFFER_OVERFLOW); /** @todo r=bird: This won't happen because the weird host code never returns it. */ 164 164 165 165 if ( RT_FAILURE(rc) … … 211 211 212 212 int rc; 213 uint32_t cbString = SHFLSTRING_HEADER_SIZE + SHFL_MAX_LEN ;213 uint32_t cbString = SHFLSTRING_HEADER_SIZE + SHFL_MAX_LEN * sizeof(RTUTF16); 214 214 PSHFLSTRING pString = (PSHFLSTRING)RTMemAlloc(cbString); 215 215 if (pString) … … 233 233 } 234 234 else 235 rc = VERR_INVALID_PARAMETER; 236 return rc; 237 } 235 rc = VERR_NO_MEMORY; 236 return rc; 237 } 238 239 240 /** 241 * Queries information about a shared folder. 242 * 243 * @returns VBox status code. 244 * 245 * @param idClient The client ID. 246 * @param idRoot The root ID of the folder to query information for. 247 * @param fQueryFlags SHFL_MIQF_XXX. 248 * @param ppszName Where to return the pointer to the name. 249 * Free using RTStrFree. Optional. 250 * @param ppszMountPoint Where to return the pointer to the auto mount point. 251 * Free using RTStrFree. Optional. 252 * @param pfFlags Where to return the flags (SHFL_MIF_XXX). Optional. 253 * @param puRootIdVersion where to return the root ID version. Optional. 254 * This helps detecting root-id reuse. 255 * 256 * @remarks ASSUMES UTF-16 connection to host. 257 */ 258 VBGLR3DECL(int) VbglR3SharedFolderQueryFolderInfo(HGCMCLIENTID idClient, uint32_t idRoot, uint64_t fQueryFlags, 259 char **ppszName, char **ppszMountPoint, 260 uint64_t *pfFlags, uint32_t *puRootIdVersion) 261 { 262 AssertReturn(!(fQueryFlags & ~(SHFL_MIQF_DRIVE_LETTER | SHFL_MIQF_PATH), VERR_INVALID_FLAGS); 263 264 /* 265 * Allocate string buffers first. 266 */ 267 int rc; 268 PSHFLSTRING pNameBuf = (PSHFLSTRING)RTMemAlloc(SHFLSTRING_HEADER_SIZE + (SHFL_MAX_LEN + 1) * sizeof(RTUTF16)); 269 PSHFLSTRING pMountPoint = (PSHFLSTRING)RTMemAlloc(SHFLSTRING_HEADER_SIZE + (260 + 1) * sizeof(RTUTF16)); 270 if (pNameBuf && pMountPoint) 271 { 272 ShflStringInitBuffer(pNameBuf, SHFLSTRING_HEADER_SIZE + (SHFL_MAX_LEN + 1) * sizeof(RTUTF16)); 273 ShflStringInitBuffer(pMountPoint, SHFLSTRING_HEADER_SIZE + (260 + 1) * sizeof(RTUTF16)); 274 275 /* 276 * Make the call. 277 */ 278 VBoxSFQueryMapInfo Msg; 279 VBGL_HGCM_HDR_INIT(&Msg.callInfo, idClient, SHFL_FN_QUERY_MAP_INFO, 5); 280 VbglHGCMParmUInt32Set(&Msg.root, idRoot); 281 VbglHGCMParmPtrSet(&Msg.name, pNameBuf, SHFLSTRING_HEADER_SIZE + pNameBuf->u16Size); 282 VbglHGCMParmPtrSet(&Msg.mountPoint, pMountPoint, SHFLSTRING_HEADER_SIZE + pMountPoint->u16Size); 283 VbglHGCMParmUInt64Set(&Msg.flags, fQueryFlags); 284 VbglHGCMParmUInt32Set(&Msg.rootIdVersion, 0); 285 286 rc = VbglR3HGCMCall(&Msg.callInfo, sizeof(Msg)); 287 if (RT_SUCCESS(rc)) 288 { 289 /* 290 * Copy out the results. 291 */ 292 if (puRootIdVersion) 293 *puRootIdVersion = Msg.rootIdVersion.u.value64; 294 295 if (pfFlags) 296 *pfFlags = Msg.flags.u.value64; 297 298 if (ppszName) 299 { 300 *ppszName = NULL; 301 rc = RTUtf16ToUtf8Ex(pNameBuf->String.utf16, pNameBuf->u16Length / sizeof(RTUTF16), ppszName, 0, NULL); 302 } 303 304 if (ppszMountPoint && RT_SUCCESS(rc)) 305 { 306 *ppszMountPoint = NULL; 307 rc = RTUtf16ToUtf8Ex(pMountPoint->String.utf16, pMountPoint->u16Length / sizeof(RTUTF16), ppszMountPoint, 0, NULL); 308 if (RT_FAILURE(rc) && ppszName) 309 { 310 RTStrFree(*ppszName); 311 *ppszName = NULL; 312 } 313 } 314 } 315 } 316 else 317 rc = VERR_NO_MEMORY; 318 RTMemFree(pMountPoint); 319 RTMemFree(pNameBuf); 320 return rc; 321 } 322 323 324 /** 325 * Waits for changes to the mappings (add, remove, restore). 326 * 327 * @returns VBox status code. 328 * @retval VINF_SUCCESS on change 329 * @retval VINF_TRY_AGAIN on restore. 330 * @retval VERR_OUT_OF_RESOURCES if there are too many guys waiting. 331 * 332 * @param idClient The client ID. 333 * @param uPrevVersion The mappings config version number returned the last 334 * time around. Use UINT32_MAX for the first call. 335 * @param puCurVersion Where to return the current mappings config version. 336 */ 337 VBGLR3DECL(int) VbglR3SharedFolderWaitForMappingsChanges(HGCMCLIENTID idClient, uint32_t uPrevVersion, uint32_t *puCurVersion) 338 { 339 VBoxSFWaitForMappingsChanges Msg; 340 VBGL_HGCM_HDR_INIT(&Msg.callInfo, idClient, SHFL_FN_WAIT_FOR_MAPPINGS_CHANGES, 1); 341 VbglHGCMParmUInt32Set(&Msg.version, uPrevVersion); 342 343 int rc = VbglR3HGCMCall(&Msg.callInfo, sizeof(Msg)); 344 345 *puCurVersion = Msg.version.u.value32; 346 return rc; 347 } 348 349 350 /** 351 * Cancels all threads currently waiting for changes for this client. 352 * 353 * @returns VBox status code. 354 * @param idClient The client ID. 355 */ 356 VBGLR3DECL(int) VbglR3SharedFolderCancelMappingsChangesWaits(HGCMCLIENTID idClient) 357 { 358 VBGLIOCHGCMCALL CallInfo; 359 VBGL_HGCM_HDR_INIT(&CallInfo, idClient, SHFL_FN_CANCEL_MAPPINGS_CHANGES_WAITS, 0); 360 361 return VbglR3HGCMCall(&CallInfo, sizeof(CallInfo)); 362 } 363 238 364 239 365 /** … … 258 384 { 259 385 #endif 386 /** @todo r=bird: Inconsistent! VbglR3SharedFolderGetMountDir does not return a default. */ 260 387 rc = RTStrDupEx(ppszPrefix, "sf_"); 261 388 #ifdef VBOX_WITH_GUEST_PROPS … … 266 393 return rc; 267 394 } 395 268 396 269 397 /** -
trunk/src/VBox/Additions/common/VBoxService/Makefile.kmk
r70346 r75407 40 40 if1of ($(KBUILD_TARGET), linux) 41 41 # CPU hotplugging. 42 VBOX_WITH_VBOXSERVICE_CPUHOTPLUG := 1 43 endif 44 42 VBOX_WITH_VBOXSERVICE_CPUHOTPLUG := 1 43 endif 44 45 # Page Sharing (Page Fusion). 45 46 if1of ($(KBUILD_TARGET), win) 46 # Page Sharing (Page Fusion). 47 VBOX_WITH_VBOXSERVICE_PAGE_SHARING := 1 47 VBOX_WITH_VBOXSERVICE_PAGE_SHARING := 1 48 48 endif 49 49 50 50 ifdef VBOX_WITH_GUEST_PROPS 51 VBOX_WITH_VBOXSERVICE_VMINFO := 1 52 endif 53 51 VBOX_WITH_VBOXSERVICE_VMINFO := 1 52 endif 53 54 # Guest Control. 54 55 ifdef VBOX_WITH_GUEST_CONTROL 55 # Guest Control. 56 VBOX_WITH_VBOXSERVICE_CONTROL := 1 56 VBOX_WITH_VBOXSERVICE_CONTROL := 1 57 57 endif 58 58 … … 68 68 # Define features to be activate. 69 69 VBoxService_DEFS += \ 70 $(if $(VBOX_WITH_VBOXSERVICE_CONTROL),VBOX_WITH_VBOXSERVICE_CONTROL,) \71 $(if $(VBOX_WITH_VBOXSERVICE_CPUHOTPLUG),VBOX_WITH_VBOXSERVICE_CPUHOTPLUG,) \72 $(if $(VBOX_WITH_VBOXSERVICE_MANAGEMENT),VBOX_WITH_VBOXSERVICE_MANAGEMENT,) \70 $(if $(VBOX_WITH_VBOXSERVICE_CONTROL),VBOX_WITH_VBOXSERVICE_CONTROL,) \ 71 $(if $(VBOX_WITH_VBOXSERVICE_CPUHOTPLUG),VBOX_WITH_VBOXSERVICE_CPUHOTPLUG,) \ 72 $(if $(VBOX_WITH_VBOXSERVICE_MANAGEMENT),VBOX_WITH_VBOXSERVICE_MANAGEMENT,) \ 73 73 $(if $(VBOX_WITH_VBOXSERVICE_PAGE_SHARING),VBOX_WITH_VBOXSERVICE_PAGE_SHARING,) \ 74 $(if $(VBOX_WITH_VBOXSERVICE_TIMESYNC),VBOX_WITH_VBOXSERVICE_TIMESYNC,) \75 $(if $(VBOX_WITH_VBOXSERVICE_TOOLBOX),VBOX_WITH_VBOXSERVICE_TOOLBOX,) \74 $(if $(VBOX_WITH_VBOXSERVICE_TIMESYNC),VBOX_WITH_VBOXSERVICE_TIMESYNC,) \ 75 $(if $(VBOX_WITH_VBOXSERVICE_TOOLBOX),VBOX_WITH_VBOXSERVICE_TOOLBOX,) \ 76 76 $(if $(VBOX_WITH_VBOXSERVICE_VMINFO),VBOX_WITH_VBOXSERVICE_VMINFO,) 77 77 78 78 # Import global defines. 79 VBoxService_DEFS += \80 $(if $(VBOX_WITH_DBUS),VBOX_WITH_DBUS,) \79 VBoxService_DEFS += \ 80 $(if $(VBOX_WITH_DBUS),VBOX_WITH_DBUS,) \ 81 81 $(if $(VBOX_WITH_GUEST_CONTROL),VBOX_WITH_GUEST_CONTROL,) \ 82 $(if $(VBOX_WITH_GUEST_PROPS),VBOX_WITH_GUEST_PROPS,) \82 $(if $(VBOX_WITH_GUEST_PROPS),VBOX_WITH_GUEST_PROPS,) \ 83 83 $(if $(VBOX_WITH_HGCM),VBOX_WITH_HGCM,) 84 84 … … 88 88 VBoxService_DEFS.os2 = VBOX_WITH_HGCM VBOX_WITH_VBOXSERVICE_CLIPBOARD 89 89 90 ifdef VBOX_WITH_SHARED_FOLDERS 91 # darwin freebsd 92 if1of ($(KBUILD_TARGET), linux solaris) 93 VBoxService_DEFS += VBOX_WITH_SHARED_FOLDERS 94 endif 95 endif 96 97 VBoxService_SOURCES = \ 98 VBoxService.cpp \ 90 VBoxService_SOURCES = \ 91 VBoxService.cpp \ 99 92 VBoxServiceUtils.cpp \ 100 93 VBoxServiceStats.cpp 101 94 102 95 ifdef VBOX_WITH_VBOXSERVICE_TIMESYNC 103 VBoxService_SOURCES+= \96 VBoxService_SOURCES += \ 104 97 VBoxServiceTimeSync.cpp 105 98 endif 106 99 107 100 ifdef VBOX_WITH_VBOXSERVICE_TOOLBOX 108 VBoxService_SOURCES+= \101 VBoxService_SOURCES += \ 109 102 VBoxServiceToolBox.cpp 110 103 endif 111 104 112 105 ifdef VBOX_WITH_VBOXSERVICE_CONTROL 113 VBoxService_SOURCES +=\114 VBoxServiceControl.cpp\106 VBoxService_SOURCES += \ 107 VBoxServiceControl.cpp \ 115 108 VBoxServiceControlProcess.cpp \ 116 109 VBoxServiceControlSession.cpp … … 118 111 119 112 ifdef VBOX_WITH_VBOXSERVICE_MANAGEMENT 120 VBoxService_SOURCES += \ 121 VBoxServiceBalloon.cpp 122 VBoxService_DEFS += $(if $(VBOX_WITH_MEMBALLOON),VBOX_WITH_MEMBALLOON,) 113 VBoxService_SOURCES += \ 114 VBoxServiceBalloon.cpp 115 ifdef VBOX_WITH_MEMBALLOON 116 VBoxService_DEFS += VBOX_WITH_MEMBALLOON 117 endif 123 118 endif 124 119 125 120 if1of ($(KBUILD_TARGET), win) 126 VBoxService_SOURCES+= \121 VBoxService_SOURCES += \ 127 122 VBoxServicePageSharing.cpp 128 123 endif 129 124 130 125 ifdef VBOX_WITH_VBOXSERVICE_VMINFO 131 VBoxService_SOURCES.win+= \126 VBoxService_SOURCES.win += \ 132 127 VBoxServiceVMInfo-win.cpp 133 VBoxService_SOURCES +=\134 VBoxServiceVMInfo.cpp\135 VBoxServicePropCache.cpp128 VBoxService_SOURCES += \ 129 VBoxServiceVMInfo.cpp \ 130 VBoxServicePropCache.cpp 136 131 endif 137 132 138 133 ifdef VBOX_WITH_VBOXSERVICE_CPUHOTPLUG 139 VBoxService_SOURCES+= \134 VBoxService_SOURCES += \ 140 135 VBoxServiceCpuHotPlug.cpp 141 136 endif 142 137 143 138 ifdef VBOX_WITH_SHARED_FOLDERS 144 if1of ($(KBUILD_TARGET), linux solaris) 145 VBoxService_SOURCES += \ 139 if1of ($(KBUILD_TARGET), win linux solaris) 140 VBoxService_DEFS += VBOX_WITH_SHARED_FOLDERS 141 VBoxService_SOURCES += \ 146 142 VBoxServiceAutoMount.cpp 147 VBoxService_SOURCES.linux+= \143 VBoxService_SOURCES.linux += \ 148 144 ../../linux/sharedfolders/vbsfmount.c 145 VBoxService_LIBS.win += \ 146 Mpr.Lib 149 147 endif 150 148 endif … … 160 158 VBoxService_LDFLAGS.darwin = -framework IOKit 161 159 162 VBoxService_LIBS += \160 VBoxService_LIBS += \ 163 161 $(VBOX_LIB_IPRT_GUEST_R3) \ 164 162 $(VBOX_LIB_VBGL_R3) \ … … 170 168 ifdef VBOX_WITH_DBUS 171 169 if1of ($(KBUILD_TARGET), linux solaris) # FreeBSD? 172 VBoxService_LIBS+= \170 VBoxService_LIBS += \ 173 171 dl 174 172 endif 175 173 endif 176 174 ifdef VBOX_WITH_GUEST_PROPS 177 VBoxService_LIBS.win+= \178 Secur32.lib \179 WtsApi32.lib \180 Psapi.lib181 VBoxService_LIBS.solaris += \182 nsl \175 VBoxService_LIBS.win += \ 176 Secur32.lib \ 177 WtsApi32.lib \ 178 Psapi.lib 179 VBoxService_LIBS.solaris += \ 180 nsl \ 183 181 kstat \ 184 182 contract -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceAutoMount.cpp
r69500 r75407 38 38 *********************************************************************************************************************************/ 39 39 #include <iprt/assert.h> 40 #include <iprt/ctype.h> 40 41 #include <iprt/dir.h> 41 42 #include <iprt/mem.h> 42 43 #include <iprt/path.h> 44 #include <iprt/semaphore.h> 45 #include <iprt/sort.h> 43 46 #include <iprt/string.h> 44 #include <iprt/semaphore.h>45 47 #include <VBox/VBoxGuestLib.h> 48 #include <VBox/shflsvc.h> 46 49 #include "VBoxServiceInternal.h" 47 50 #include "VBoxServiceUtils.h" 48 51 49 #include <errno.h> 50 #include <grp.h> 51 #include <sys/mount.h> 52 #ifdef RT_OS_SOLARIS 53 # include <sys/mntent.h> 54 # include <sys/mnttab.h> 55 # include <sys/vfs.h> 52 #ifdef RT_OS_WINDOWS 53 #elif defined(RT_OS_OS2) 56 54 #else 57 # include <mntent.h> 58 # include <paths.h> 55 # include <errno.h> 56 # include <grp.h> 57 # include <sys/mount.h> 58 # ifdef RT_OS_SOLARIS 59 # include <sys/mntent.h> 60 # include <sys/mnttab.h> 61 # include <sys/vfs.h> 62 # elif defined(RT_OS_LINUX) 63 # include <mntent.h> 64 # include <paths.h> 65 RT_C_DECLS_BEGIN 66 # include "../../linux/sharedfolders/vbsfmount.h" 67 RT_C_DECLS_END 68 # else 69 # error "Port me!" 70 # endif 71 # include <unistd.h> 59 72 #endif 60 #include <unistd.h> 61 62 RT_C_DECLS_BEGIN 63 #include "../../linux/sharedfolders/vbsfmount.h" 64 RT_C_DECLS_END 65 66 #ifdef RT_OS_SOLARIS 67 # define VBOXSERVICE_AUTOMOUNT_DEFAULT_DIR "/mnt" 68 #else 69 # define VBOXSERVICE_AUTOMOUNT_DEFAULT_DIR "/media" 73 74 75 76 /********************************************************************************************************************************* 77 * Defined Constants And Macros * 78 *********************************************************************************************************************************/ 79 /** @def VBOXSERVICE_AUTOMOUNT_DEFAULT_DIR 80 * Default mount directory (unix only). 81 */ 82 #ifndef VBOXSERVICE_AUTOMOUNT_DEFAULT_DIR 83 # ifdef RT_OS_SOLARIS 84 # define VBOXSERVICE_AUTOMOUNT_DEFAULT_DIR "/mnt" 85 # else 86 # define VBOXSERVICE_AUTOMOUNT_DEFAULT_DIR "/media" 87 # endif 88 #endif 89 90 /** @def VBOXSERVICE_AUTOMOUNT_DEFAULT_PREFIX 91 * Default mount prefix (unix only). 92 */ 93 #ifndef VBOXSERVICE_AUTOMOUNT_DEFAULT_PREFIX 94 # define VBOXSERVICE_AUTOMOUNT_DEFAULT_PREFIX "sf_" 70 95 #endif 71 96 … … 78 103 #endif 79 104 105 /** @def VBOXSERVICE_AUTOMOUNT_MIQF 106 * The drive letter / path mount point flag. */ 107 #if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2) 108 # define VBOXSERVICE_AUTOMOUNT_MIQF SHFL_MIQF_DRIVE_LETTER 109 #else 110 # define VBOXSERVICE_AUTOMOUNT_MIQF SHFL_MIQF_PATH 111 #endif 112 113 114 /********************************************************************************************************************************* 115 * Structures and Typedefs * 116 *********************************************************************************************************************************/ 117 /** 118 * Automounter mount table entry. 119 * 120 * This holds the information returned by SHFL_FN_QUERY_MAP_INFO and 121 * additional mount state info. We only keep entries for mounted mappings. 122 */ 123 typedef struct VBSVCAUTOMOUNTERENTRY 124 { 125 /** The root ID. */ 126 uint32_t idRoot; 127 /** The root ID version. */ 128 uint32_t uRootIdVersion; 129 /** Map info flags, SHFL_MIF_XXX. */ 130 uint64_t fFlags; 131 /** The shared folder (mapping) name. */ 132 char *pszName; 133 /** The configured mount point, NULL if none. */ 134 char *pszMountPoint; 135 /** The actual mount point, NULL if not mount. */ 136 char *pszActualMountPoint; 137 } VBSVCAUTOMOUNTERENTRY; 138 /** Pointer to an automounter entry. */ 139 typedef VBSVCAUTOMOUNTERENTRY *PVBSVCAUTOMOUNTERENTRY; 140 141 /** Automounter mount table. */ 142 typedef struct VBSVCAUTOMOUNTERTABLE 143 { 144 /** Current number of entries in the array. */ 145 uint32_t cEntries; 146 /** Max number of entries the array can hold w/o growing it. */ 147 uint32_t cAllocated; 148 /** Pointer to an array of entry pointers. */ 149 PVBSVCAUTOMOUNTERENTRY *papEntries; 150 } VBSVCAUTOMOUNTERTABLE; 151 /** Pointer to an automounter mount table. */ 152 typedef VBSVCAUTOMOUNTERTABLE *PVBSVCAUTOMOUNTERTABLE; 153 80 154 81 155 /********************************************************************************************************************************* … … 83 157 *********************************************************************************************************************************/ 84 158 /** The semaphore we're blocking on. */ 85 static RTSEMEVENTMULTI g_ AutoMountEvent = NIL_RTSEMEVENTMULTI;159 static RTSEMEVENTMULTI g_hAutoMountEvent = NIL_RTSEMEVENTMULTI; 86 160 /** The Shared Folders service client ID. */ 87 static uint32_t g_SharedFoldersSvcClientID = 0; 161 static uint32_t g_idClientSharedFolders = 0; 162 /** Set if we can wait on changes to the mappings. */ 163 static bool g_fHostSupportsWaitAndInfoQuery = false; 164 165 #ifdef RT_OS_OS2 166 /** The attachment tag we use to identify attchments that belongs to us. */ 167 static char const g_szTag[] = "VBoxAutomounter"; 168 #elif defined(RT_OS_SOLARIS) 169 /** Dummy mount option that lets us identify mounts that belongs to us. */ 170 static char const g_szTag[] = ",VBoxService=auto"; 171 #endif 172 88 173 89 174 … … 91 176 * @interface_method_impl{VBOXSERVICE,pfnInit} 92 177 */ 93 static DECLCALLBACK(int) vbsvcAuto MountInit(void)94 { 95 VGSvcVerbose(3, "vbsvcAuto MountInit\n");96 97 int rc = RTSemEventMultiCreate(&g_ AutoMountEvent);178 static DECLCALLBACK(int) vbsvcAutomounterInit(void) 179 { 180 VGSvcVerbose(3, "vbsvcAutomounterInit\n"); 181 182 int rc = RTSemEventMultiCreate(&g_hAutoMountEvent); 98 183 AssertRCReturn(rc, rc); 99 184 100 rc = VbglR3SharedFolderConnect(&g_ SharedFoldersSvcClientID);185 rc = VbglR3SharedFolderConnect(&g_idClientSharedFolders); 101 186 if (RT_SUCCESS(rc)) 102 187 { 103 VGSvcVerbose(3, "vbsvcAutoMountInit: Service Client ID: %#x\n", g_SharedFoldersSvcClientID); 188 VGSvcVerbose(3, "vbsvcAutomounterInit: Service Client ID: %#x\n", g_idClientSharedFolders); 189 g_fHostSupportsWaitAndInfoQuery = RT_SUCCESS(VbglR3SharedFolderCancelMappingsChangesWaits(g_idClientSharedFolders)); 104 190 } 105 191 else … … 109 195 if (rc == VERR_HGCM_SERVICE_NOT_FOUND) /* Host service is not available. */ 110 196 { 111 VGSvcVerbose(0, "vbsvcAuto MountInit: Shared Folders service is not available\n");197 VGSvcVerbose(0, "vbsvcAutomounterInit: Shared Folders service is not available\n"); 112 198 rc = VERR_SERVICE_DISABLED; 113 199 } 114 200 else 115 201 VGSvcError("Control: Failed to connect to the Shared Folders service! Error: %Rrc\n", rc); 116 RTSemEventMultiDestroy(g_ AutoMountEvent);117 g_ AutoMountEvent = NIL_RTSEMEVENTMULTI;202 RTSemEventMultiDestroy(g_hAutoMountEvent); 203 g_hAutoMountEvent = NIL_RTSEMEVENTMULTI; 118 204 } 119 205 … … 122 208 123 209 210 #if defined(RT_OS_SOLARIS) || defined(RT_OS_LINUX) /* The old code: */ 211 124 212 /** 125 213 * @todo Integrate into RTFsQueryMountpoint()? 126 214 */ 127 static bool vbsvcAutoMountShareIsMounted (const char *pszShare, char *pszMountPoint, size_t cbMountPoint)128 { 129 AssertPtrReturn(pszShare, VERR_INVALID_PARAMETER);130 AssertPtrReturn(pszMountPoint, VERR_INVALID_PARAMETER);131 AssertReturn(cbMountPoint, VERR_INVALID_PARAMETER);215 static bool vbsvcAutoMountShareIsMountedOld(const char *pszShare, char *pszMountPoint, size_t cbMountPoint) 216 { 217 AssertPtrReturn(pszShare, false); 218 AssertPtrReturn(pszMountPoint, false); 219 AssertReturn(cbMountPoint, false); 132 220 133 221 bool fMounted = false; 222 223 # if defined(RT_OS_SOLARIS) 134 224 /** @todo What to do if we have a relative path in mtab instead 135 225 * of an absolute one ("temp" vs. "/media/temp")? 136 226 * procfs contains the full path but not the actual share name ... 137 227 * FILE *pFh = setmntent("/proc/mounts", "r+t"); */ 138 #ifdef RT_OS_SOLARIS139 228 FILE *pFh = fopen(_PATH_MOUNTED, "r"); 140 229 if (!pFh) 141 VGSvcError("vbsvcAutoMountShareIsMounted : Could not open mount tab '%s'!\n", _PATH_MOUNTED);230 VGSvcError("vbsvcAutoMountShareIsMountedOld: Could not open mount tab '%s'!\n", _PATH_MOUNTED); 142 231 else 143 232 { … … 154 243 fclose(pFh); 155 244 } 156 # else245 # elif defined(RT_OS_LINUX) 157 246 FILE *pFh = setmntent(_PATH_MOUNTED, "r+t"); /** @todo r=bird: why open it for writing? (the '+') */ 158 247 if (pFh == NULL) 159 VGSvcError("vbsvcAutoMountShareIsMounted : Could not open mount tab '%s'!\n", _PATH_MOUNTED);248 VGSvcError("vbsvcAutoMountShareIsMountedOld: Could not open mount tab '%s'!\n", _PATH_MOUNTED); 160 249 else 161 250 { … … 172 261 endmntent(pFh); 173 262 } 174 #endif 175 176 VGSvcVerbose(4, "vbsvcAutoMountShareIsMounted: Share '%s' at mount point '%s' = %s\n", 263 # else 264 # error "PORTME!" 265 # endif 266 267 VGSvcVerbose(4, "vbsvcAutoMountShareIsMountedOld: Share '%s' at mount point '%s' = %s\n", 177 268 pszShare, fMounted ? pszMountPoint : "<None>", fMounted ? "Yes" : "No"); 178 269 return fMounted; … … 186 277 * @param pszMountPoint The shared folder mount point. 187 278 */ 188 static int vbsvcAutoMountUnmount (const char *pszMountPoint)279 static int vbsvcAutoMountUnmountOld(const char *pszMountPoint) 189 280 { 190 281 AssertPtrReturn(pszMountPoint, VERR_INVALID_PARAMETER); … … 217 308 * @param pOpts For getting the group ID. 218 309 */ 219 static int vbsvcAutoMountPrepareMountPoint (const char *pszMountPoint, const char *pszShareName, vbsf_mount_opts *pOpts)310 static int vbsvcAutoMountPrepareMountPointOld(const char *pszMountPoint, const char *pszShareName, vbsf_mount_opts *pOpts) 220 311 { 221 312 AssertPtrReturn(pOpts, VERR_INVALID_PARAMETER); … … 235 326 if (rc == VERR_WRITE_PROTECT) 236 327 { 237 VGSvcVerbose(3, "vbsvcAutoMountPrepareMountPoint : Mount directory '%s' already is used/mounted\n",238 pszMountPoint);328 VGSvcVerbose(3, "vbsvcAutoMountPrepareMountPointOld: Mount directory '%s' already is used/mounted\n", 329 pszMountPoint); 239 330 rc = VINF_SUCCESS; 240 331 } 241 332 else 242 VGSvcError("vbsvcAutoMountPrepareMountPoint : Could not set mode %RTfmode for mount directory '%s', rc = %Rrc\n",243 fMode, pszMountPoint, rc);333 VGSvcError("vbsvcAutoMountPrepareMountPointOld: Could not set mode %RTfmode for mount directory '%s', rc = %Rrc\n", 334 fMode, pszMountPoint, rc); 244 335 } 245 336 } 246 337 else 247 VGSvcError("vbsvcAutoMountPrepareMountPoint : Could not set permissions for mount directory '%s', rc = %Rrc\n",248 pszMountPoint, rc);338 VGSvcError("vbsvcAutoMountPrepareMountPointOld: Could not set permissions for mount directory '%s', rc = %Rrc\n", 339 pszMountPoint, rc); 249 340 } 250 341 else 251 VGSvcError("vbsvcAutoMountPrepareMountPoint : Could not create mount directory '%s' with mode %RTfmode, rc = %Rrc\n",252 pszMountPoint, fMode, rc);342 VGSvcError("vbsvcAutoMountPrepareMountPointOld: Could not create mount directory '%s' with mode %RTfmode, rc = %Rrc\n", 343 pszMountPoint, fMode, rc); 253 344 return rc; 254 345 } … … 265 356 * @param pOpts The mount options. 266 357 */ 267 static int vbsvcAutoMountSharedFolder(const char *pszShareName, const char *pszMountPoint, struct vbsf_mount_opts *pOpts) 268 { 269 AssertPtr(pOpts); 270 271 int rc = VINF_SUCCESS; 272 bool fSkip = false; 273 274 /* Already mounted? */ 275 char szAlreadyMountedTo[RTPATH_MAX]; 276 if (vbsvcAutoMountShareIsMounted(pszShareName, szAlreadyMountedTo, sizeof(szAlreadyMountedTo))) 277 { 278 fSkip = true; 279 /* Do if it not mounted to our desired mount point */ 280 if (RTStrICmp(pszMountPoint, szAlreadyMountedTo)) 281 { 282 VGSvcVerbose(3, "vbsvcAutoMountWorker: Shared folder '%s' already mounted to '%s', unmounting ...\n", 283 pszShareName, szAlreadyMountedTo); 284 rc = vbsvcAutoMountUnmount(szAlreadyMountedTo); 285 if (RT_SUCCESS(rc)) 286 fSkip = false; 287 else 288 VGSvcError("vbsvcAutoMountWorker: Failed to unmount '%s', %s (%d)! (rc=%Rrc)\n", 289 szAlreadyMountedTo, strerror(errno), errno, rc); /** @todo errno isn't reliable at this point */ 290 } 291 if (fSkip) 292 VGSvcVerbose(3, "vbsvcAutoMountWorker: Shared folder '%s' already mounted to '%s', skipping\n", 293 pszShareName, szAlreadyMountedTo); 294 } 295 296 if (!fSkip && RT_SUCCESS(rc)) 297 rc = vbsvcAutoMountPrepareMountPoint(pszMountPoint, pszShareName, pOpts); 298 if (!fSkip && RT_SUCCESS(rc)) 299 { 300 #ifdef RT_OS_SOLARIS 358 static int vbsvcAutoMountSharedFolderOld(const char *pszShareName, const char *pszMountPoint) 359 { 360 /* 361 * Linux and solaris share the same mount structure. 362 */ 363 struct group *grp_vboxsf = getgrnam("vboxsf"); 364 if (!grp_vboxsf) 365 { 366 VGSvcError("vbsvcAutoMountWorker: Group 'vboxsf' does not exist\n"); 367 return VINF_SUCCESS; 368 } 369 370 struct vbsf_mount_opts Opts = 371 { 372 0, /* uid */ 373 (int)grp_vboxsf->gr_gid, /* gid */ 374 0, /* ttl */ 375 0770, /* dmode, owner and group "vboxsf" have full access */ 376 0770, /* fmode, owner and group "vboxsf" have full access */ 377 0, /* dmask */ 378 0, /* fmask */ 379 0, /* ronly */ 380 0, /* sloppy */ 381 0, /* noexec */ 382 0, /* nodev */ 383 0, /* nosuid */ 384 0, /* remount */ 385 "\0", /* nls_name */ 386 NULL, /* convertcp */ 387 }; 388 389 int rc = vbsvcAutoMountPrepareMountPointOld(pszMountPoint, pszShareName, &Opts); 390 if (RT_SUCCESS(rc)) 391 { 392 # ifdef RT_OS_SOLARIS 393 int fFlags = 0; 394 if (Opts.ronly) 395 fFlags |= MS_RDONLY; 301 396 char szOptBuf[MAX_MNTOPT_STR] = { '\0', }; 302 int fFlags = 0;303 if (pOpts->ronly)304 fFlags |= MS_RDONLY;305 397 RTStrPrintf(szOptBuf, sizeof(szOptBuf), "uid=%d,gid=%d,dmode=%0o,fmode=%0o,dmask=%0o,fmask=%0o", 306 pOpts->uid, pOpts->gid, pOpts->dmode, pOpts->fmode, pOpts->dmask, pOpts->fmask);398 Opts.uid, Opts.gid, Opts.dmode, Opts.fmode, Opts.dmask, Opts.fmask); 307 399 int r = mount(pszShareName, 308 400 pszMountPoint, … … 317 409 else if (errno != EBUSY) /* Share is already mounted? Then skip error msg. */ 318 410 VGSvcError("vbsvcAutoMountWorker: Could not mount shared folder '%s' to '%s', error = %s\n", 319 pszShareName, pszMountPoint, strerror(errno));320 321 # elif defined(RT_OS_LINUX)411 pszShareName, pszMountPoint, strerror(errno)); 412 413 # else /* RT_OS_LINUX */ 322 414 unsigned long fFlags = MS_NODEV; 323 415 … … 331 423 mntinf.length = sizeof(mntinf); 332 424 333 mntinf.uid = pOpts->uid;334 mntinf.gid = pOpts->gid;335 mntinf.ttl = pOpts->ttl;336 mntinf.dmode = pOpts->dmode;337 mntinf.fmode = pOpts->fmode;338 mntinf.dmask = pOpts->dmask;339 mntinf.fmask = pOpts->fmask;425 mntinf.uid = Opts.uid; 426 mntinf.gid = Opts.gid; 427 mntinf.ttl = Opts.ttl; 428 mntinf.dmode = Opts.dmode; 429 mntinf.fmode = Opts.fmode; 430 mntinf.dmask = Opts.dmask; 431 mntinf.fmask = Opts.fmask; 340 432 341 433 strcpy(mntinf.name, pszShareName); … … 351 443 VGSvcVerbose(0, "vbsvcAutoMountWorker: Shared folder '%s' was mounted to '%s'\n", pszShareName, pszMountPoint); 352 444 353 r = vbsfmount_complete(pszShareName, pszMountPoint, fFlags, pOpts);445 r = vbsfmount_complete(pszShareName, pszMountPoint, fFlags, &Opts); 354 446 switch (r) 355 447 { … … 360 452 case 1: 361 453 VGSvcError("vbsvcAutoMountWorker: Could not update mount table (failed to create memstream): %s\n", 362 strerror(errno));454 strerror(errno)); 363 455 break; 364 456 … … 427 519 } 428 520 } 429 #else 430 # error "PORTME" 431 #endif 521 # endif 432 522 } 433 523 VGSvcVerbose(3, "vbsvcAutoMountWorker: Mounting returned with rc=%Rrc\n", rc); … … 446 536 * @param uClientID The shared folder service (HGCM) client ID. 447 537 */ 448 static int vbsvcAutoMountProcessMappings (PCVBGLR3SHAREDFOLDERMAPPING paMappings, uint32_t cMappings,449 const char *pszMountDir, const char *pszSharePrefix, uint32_t uClientID)538 static int vbsvcAutoMountProcessMappingsOld(PCVBGLR3SHAREDFOLDERMAPPING paMappings, uint32_t cMappings, 539 const char *pszMountDir, const char *pszSharePrefix, uint32_t uClientID) 450 540 { 451 541 if (cMappings == 0) … … 490 580 VGSvcVerbose(4, "vbsvcAutoMountWorker: Processing mount point '%s'\n", szMountPoint); 491 581 492 struct group *grp_vboxsf = getgrnam("vboxsf"); 493 if (grp_vboxsf) 582 /* 583 * Already mounted? 584 */ 585 /** @todo r-bird: this does not take into account that a shared folder could 586 * be mounted twice... We're really just interested in whether the 587 * folder is mounted on 'szMountPoint', no where else... */ 588 bool fSkip = false; 589 char szAlreadyMountedOn[RTPATH_MAX]; 590 if (vbsvcAutoMountShareIsMountedOld(pszShareName, szAlreadyMountedOn, sizeof(szAlreadyMountedOn))) 494 591 { 495 struct vbsf_mount_opts mount_opts = 592 /* Do if it not mounted to our desired mount point */ 593 if (RTStrICmp(szMountPoint, szAlreadyMountedOn)) 496 594 { 497 0, /* uid */ 498 (int)grp_vboxsf->gr_gid, /* gid */ 499 0, /* ttl */ 500 0770, /* dmode, owner and group "vboxsf" have full access */ 501 0770, /* fmode, owner and group "vboxsf" have full access */ 502 0, /* dmask */ 503 0, /* fmask */ 504 0, /* ronly */ 505 0, /* sloppy */ 506 0, /* noexec */ 507 0, /* nodev */ 508 0, /* nosuid */ 509 0, /* remount */ 510 "\0", /* nls_name */ 511 NULL, /* convertcp */ 512 }; 513 514 rc = vbsvcAutoMountSharedFolder(pszShareName, szMountPoint, &mount_opts); 595 VGSvcVerbose(3, "vbsvcAutoMountWorker: Shared folder '%s' already mounted on '%s', unmounting ...\n", 596 pszShareName, szAlreadyMountedOn); 597 rc = vbsvcAutoMountUnmountOld(szAlreadyMountedOn); 598 if (RT_SUCCESS(rc)) 599 fSkip = false; 600 else 601 VGSvcError("vbsvcAutoMountWorker: Failed to unmount '%s', %s (%d)! (rc=%Rrc)\n", 602 szAlreadyMountedOn, strerror(errno), errno, rc); /** @todo errno isn't reliable at this point */ 603 } 604 if (fSkip) 605 VGSvcVerbose(3, "vbsvcAutoMountWorker: Shared folder '%s' already mounted on '%s', skipping\n", 606 pszShareName, szAlreadyMountedOn); 515 607 } 516 else 517 VGSvcError("vbsvcAutoMountWorker: Group 'vboxsf' does not exist\n"); 608 if (!fSkip) 609 { 610 /* 611 * Mount it. 612 */ 613 rc = vbsvcAutoMountSharedFolderOld(pszShareName, szMountPoint); 614 } 518 615 } 519 616 else … … 532 629 } 533 630 534 535 /** 536 * @interface_method_impl{VBOXSERVICE,pfnWorker} 537 */ 538 static DECLCALLBACK(int) vbsvcAutoMountWorker(bool volatile *pfShutdown) 539 { 540 /* 541 * Tell the control thread that it can continue 542 * spawning services. 543 */ 544 RTThreadUserSignal(RTThreadSelf()); 545 631 #endif /* defined(RT_OS_SOLARIS) || defined(RT_OS_LINUX) - the old code*/ 632 633 634 /** 635 * Service worker function for old host. 636 * 637 * This only mount stuff on startup. 638 * 639 * @returns VBox status code. 640 * @param pfShutdown Shutdown indicator. 641 */ 642 static int vbsvcAutoMountWorkerOld(bool volatile *pfShutdown) 643 { 644 #if defined(RT_OS_SOLARIS) || defined(RT_OS_LINUX) 645 /* 646 * We only do a single pass here. 647 */ 546 648 uint32_t cMappings; 547 649 PVBGLR3SHAREDFOLDERMAPPING paMappings; 548 int rc = VbglR3SharedFolderGetMappings(g_ SharedFoldersSvcClientID, true /* Only process auto-mounted folders */,650 int rc = VbglR3SharedFolderGetMappings(g_idClientSharedFolders, true /* Only process auto-mounted folders */, 549 651 &paMappings, &cMappings); 550 652 if ( RT_SUCCESS(rc) … … 564 666 { 565 667 VGSvcVerbose(3, "vbsvcAutoMountWorker: Shared folder mount prefix set to '%s'\n", pszSharePrefix); 566 # ifdef USE_VIRTUAL_SHARES668 # ifdef USE_VIRTUAL_SHARES 567 669 /* Check for a fixed/virtual auto-mount share. */ 568 if (VbglR3SharedFolderExists(g_SharedFoldersSvcClientID, "vbsfAutoMount")) 569 { 670 if (VbglR3SharedFolderExists(g_idClientSharedFolders, "vbsfAutoMount")) 570 671 VGSvcVerbose(3, "vbsvcAutoMountWorker: Host supports auto-mount root\n"); 571 }572 672 else 573 673 { 574 # endif674 # endif 575 675 VGSvcVerbose(3, "vbsvcAutoMountWorker: Got %u shared folder mappings\n", cMappings); 576 rc = vbsvcAutoMountProcessMappings(paMappings, cMappings, pszMountDir, pszSharePrefix, g_SharedFoldersSvcClientID); 577 #ifdef USE_VIRTUAL_SHARES 676 rc = vbsvcAutoMountProcessMappingsOld(paMappings, cMappings, pszMountDir, pszSharePrefix, 677 g_idClientSharedFolders); 678 # ifdef USE_VIRTUAL_SHARES 578 679 } 579 # endif680 # endif 580 681 RTStrFree(pszSharePrefix); 581 682 } /* Mount share prefix. */ … … 593 694 VGSvcVerbose(3, "vbsvcAutoMountWorker: No shared folder mappings found\n"); 594 695 595 /* 596 * Because this thread is a one-timer at the moment we don't want to break/change 597 * the semantics of the main thread's start/stop sub-threads handling. 696 #else 697 int rc = VINF_SUCCESS; 698 #endif /* defined(RT_OS_SOLARIS) || defined(RT_OS_LINUX) */ 699 700 701 /* 702 * Wait on shutdown (this used to be a silly RTThreadSleep(500) loop). 703 */ 704 while (!*pfShutdown) 705 { 706 rc = RTSemEventMultiWait(g_hAutoMountEvent, RT_MS_1MIN); 707 if (rc != VERR_TIMEOUT) 708 break; 709 } 710 711 VGSvcVerbose(3, "vbsvcAutoMountWorkerOld: Finished with rc=%Rrc\n", rc); 712 return rc; 713 } 714 715 #if !defined(RT_OS_WINDOWS) && !defined(RT_OS_OS2) 716 /** 717 * Assembles the mount directory and prefix into @a pszDst. 718 * 719 * Will fall back on defaults if we have trouble with the configuration from the 720 * host. This ASSUMES that @a cbDst is rather large and won't cause trouble 721 * with the default. 722 * 723 * @returns IPRT status code. 724 * @param pszDst Where to return the prefix. 725 * @param cbDst The size of the prefix buffer. 726 */ 727 static int vbsvcAutomounterQueryMountDirAndPrefix(char *pszDst, size_t cbDst) 728 { 729 /* 730 * Query the config first. 731 */ 732 /* Mount directory: */ 733 const char *pszDir = VBOXSERVICE_AUTOMOUNT_DEFAULT_DIR; 734 char *pszCfgDir; 735 int rc = VbglR3SharedFolderGetMountDir(&pszCfgDir); 736 if (RT_SUCCESS(rc)) 737 { 738 if (*pszCfgDir == '/') 739 pszDir = pszCfgDir; 740 } 741 else 742 pszCfgDir = NULL; 743 744 /* Prefix: */ 745 const char *pszPrefix = VBOXSERVICE_AUTOMOUNT_DEFAULT_PREFIX; 746 char *pszCfgPrefix; 747 rc = VbglR3SharedFolderGetMountPrefix(&pszCfgPrefix); 748 if (RT_SUCCESS(rc)) 749 { 750 if ( strchr(pszCfgPrefix, '/') == NULL 751 && strchr(pszCfgPrefix, '\\') == NULL 752 && strcmp(pszCfgPrefix, "..") != 0) 753 pszPrefix = pszCfgPrefix; 754 } 755 else 756 pszCfgPrefix = NULL; 757 758 /* 759 * Try combine the two. 760 */ 761 rc = RTPathAbs(pszDir, pszDst, cbDst); 762 if (RT_SUCCESS(rc)) 763 { 764 if (*pszPrefix) 765 { 766 rc = RTPathAppend(pszDst, cbDst, pszPrefix); 767 if (RT_FAILURE(rc)) 768 VGSvcError("vbsvcAutomounterQueryMountDirAndPrefix: RTPathAppend(%s,,%s) -> %Rrc\n", pszDst, pszPrefix, rc); 769 } 770 else 771 { 772 rc = RTPathEnsureTrailingSeparator(pszDst, cbDst); 773 if (RT_FAILURE(rc)) 774 VGSvcError("vbsvcAutomounterQueryMountDirAndPrefix: RTPathEnsureTrailingSeparator(%s) -> %Rrc\n", pszDst, rc); 775 } 776 } 777 else 778 VGSvcError("vbsvcAutomounterQueryMountDirAndPrefix: RTPathAbs(%s) -> %Rrc\n", rc); 779 780 781 /* 782 * Return the default dir + prefix if the above failed. 783 */ 784 if (RT_FAILURE(rc)) 785 { 786 rc = RTStrCopy(pszDst, cbDst, VBOXSERVICE_AUTOMOUNT_DEFAULT_DIR "/" VBOXSERVICE_AUTOMOUNT_DEFAULT_PREFIX); 787 AssertRC(rc); 788 } 789 790 RTStrFree(pszCfgDir); 791 RTStrFree(pszCfgPrefix); 792 return rc; 793 } 794 #endif /* !RT_OS_WINDOW && !RT_OS_OS2 */ 795 796 797 /** 798 * @callback_method_impl{FNRTSORTCMP, For sorting mount table by root ID. } 799 */ 800 static DECLCALLBACK(int) vbsvcAutomounterCompareEntry(void const *pvElement1, void const *pvElement2, void *pvUser) 801 { 802 RT_NOREF_PV(pvUser); 803 PVBSVCAUTOMOUNTERENTRY pEntry1 = (PVBSVCAUTOMOUNTERENTRY)pvElement1; 804 PVBSVCAUTOMOUNTERENTRY pEntry2 = (PVBSVCAUTOMOUNTERENTRY)pvElement2; 805 return pEntry1->idRoot < pEntry2->idRoot ? -1 806 : pEntry1->idRoot > pEntry2->idRoot ? 1 : 0; 807 } 808 809 810 /** 811 * Worker for vbsvcAutomounterPopulateTable for adding discovered entries. 812 * 813 * This is puts dummies in for missing values, depending on 814 * vbsvcAutomounterPopulateTable to query them later. 815 * 816 * @returns VINF_SUCCESS or VERR_NO_MEMORY; 817 * @param pMountTable The mount table to add an entry to. 818 * @param pszName The shared folder name. 819 * @param pszMountPoint The mount point. 820 */ 821 static int vbsvcAutomounterAddEntry(PVBSVCAUTOMOUNTERTABLE pMountTable, const char *pszName, const char *pszMountPoint) 822 { 823 VGSvcVerbose(2, "vbsvcAutomounterAddEntry: %s -> %s\n", pszMountPoint, pszName); 824 PVBSVCAUTOMOUNTERENTRY pEntry = (PVBSVCAUTOMOUNTERENTRY)RTMemAlloc(sizeof(*pEntry)); 825 pEntry->idRoot = UINT32_MAX; 826 pEntry->uRootIdVersion = UINT32_MAX; 827 pEntry->fFlags = UINT64_MAX; 828 pEntry->pszName = RTStrDup(pszName); 829 pEntry->pszMountPoint = NULL; 830 pEntry->pszActualMountPoint = RTStrDup(pszMountPoint); 831 if (pEntry->pszName && pEntry->pszActualMountPoint) 832 { 833 if (pMountTable->cEntries + 1 <= pMountTable->cAllocated) 834 { 835 pMountTable->papEntries[pMountTable->cEntries++] = pEntry; 836 return VINF_SUCCESS; 837 } 838 839 void *pvNew = RTMemRealloc(pMountTable->papEntries, (pMountTable->cAllocated + 8) * sizeof(pMountTable->papEntries[0])); 840 if (pvNew) 841 { 842 pMountTable->cAllocated += 8; 843 pMountTable->papEntries = (PVBSVCAUTOMOUNTERENTRY *)pvNew; 844 845 pMountTable->papEntries[pMountTable->cEntries++] = pEntry; 846 return VINF_SUCCESS; 847 } 848 } 849 RTMemFree(pEntry->pszActualMountPoint); 850 RTMemFree(pEntry->pszName); 851 RTMemFree(pEntry); 852 return VERR_NO_MEMORY; 853 } 854 855 856 /** 857 * Populates the mount table as best we can with existing automount entries. 858 * 859 * @returns VINF_SUCCESS or VERR_NO_MEMORY; 860 * @param pMountTable The mount table (empty). 861 */ 862 static int vbsvcAutomounterPopulateTable(PVBSVCAUTOMOUNTERTABLE pMountTable) 863 { 864 int rc; 865 866 #ifdef RT_OS_WINDOWS 867 /* 868 * Loop thru the drive letters and check out each of them using QueryDosDeviceW. 869 */ 870 static const char s_szDevicePath[] = "\\Device\\VBoxMiniRdr\\;"; 871 for (char chDrive = 'Z'; chDrive >= 'A'; chDrive--) 872 { 873 RTUTF16 const wszMountPoint[4] = { chDrive, ':', '\0', '\0' }; 874 RTUTF16 wszTargetPath[RTPATH_MAX]; 875 DWORD const cwcResult = QueryDosDeviceW(wszMountPoint, wszTargetPath, RT_ELEMENTS(wszTargetPath)); 876 if ( cwcResult > sizeof(s_szDevicePath) 877 && RTUtf16NICmpAscii(wszTargetPath, RT_STR_TUPLE(s_szDevicePath)) == 0) 878 { 879 PCRTUTF16 pwsz = &wszTargetPath[RT_ELEMENTS(s_szDevicePath) - 1]; 880 Assert(pwsz[-1] == ';'); 881 if ( (pwsz[0] & ~(RTUTF16)0x20) == chDrive 882 && pwsz[1] == ':' 883 && pwsz[2] == '\\') 884 { 885 /* For now we'll just use the special capitalization of the 886 "server" name to identify it as our work. We could check 887 if the symlink is from \Global?? or \??, but that trick does 888 work for older OS versions (<= XP) or when running the 889 service manually for testing/wathever purposes. */ 890 /** @todo Modify the windows shared folder driver to allow tagging drives.*/ 891 if (RTUtf16NCmpAscii(&pwsz[3], RT_STR_TUPLE("VBoxSvr\\")) == 0) 892 { 893 pwsz += 3 + 8; 894 if (*pwsz != '\\' && *pwsz) 895 { 896 /* The shared folder name should follow immediately after the server prefix. */ 897 char *pszMountedName = NULL; 898 rc = RTUtf16ToUtf8(pwsz, &pszMountedName); 899 if (RT_SUCCESS(rc)) 900 { 901 char const szMountPoint[4] = { chDrive, ':', '\0', '\0' }; 902 rc = vbsvcAutomounterAddEntry(pMountTable, pszMountedName, szMountPoint); 903 RTStrFree(pszMountedName); 904 } 905 if (RT_FAILURE(rc)) 906 return rc; 907 } 908 else 909 VGSvcVerbose(2, "vbsvcAutomounterPopulateTable: Malformed, not ours: %ls -> %ls\n", 910 wszMountPoint, wszTargetPath); 911 } 912 else 913 VGSvcVerbose(3, "vbsvcAutomounterPopulateTable: Not ours: %ls -> %ls\n", wszMountPoint, wszTargetPath); 914 } 915 } 916 } 917 918 #elif defined(RT_OS_OS2) 919 /* 920 * Just loop thru the drive letters and check the attachment of each. 921 */ 922 for (char chDrive = 'Z'; chDrive >= 'A'; chDrive--) 923 { 924 char const szMountPoint[4] = { chDrive, ':', '\0', '\0' }; 925 union 926 { 927 FSQBUFFER2 FsQueryBuf; 928 char achPadding[1024]; 929 } uBuf; 930 RT_ZERO(uBuf); 931 ULONG cbBuf = sizeof(uBuf) - 2; 932 APIRET rcOs2 = DosQueryFSAttach(szMountPoint, 0, FSAIL_QUERYNAME, uBuf, &cbBuf); 933 if (rcOs2 == NO_ERROR) 934 { 935 const char *pszFsdName = &uBuf.FsQueryBuf.szName[uBuf.FsQueryBuf.cbName + 1]; 936 if ( uBuf.FsQueryBuf.iType == FSAT_REMOTEDRV 937 && RTStrICmpAscii(pszFsdName, "VBOXSF") == 0) 938 { 939 const char *pszMountedName = &pszFsdName[uBuf.FsQueryBuf.cbFSDName + 1]; 940 const char *pszTag = strlen(pszMountedName) + 1; /* (Safe. Always two trailing zero bytes, see above.) */ 941 if (strcmp(pszTag, g_szTag) == 0) 942 { 943 rc = vbsvcAutomounterAddEntry(pMountTable, pszMountedName, szMountPoint); 944 if (RT_FAILURE(rc)) 945 return rc; 946 } 947 } 948 } 949 } 950 951 #elif defined(RT_OS_LINUX) 952 /* 953 * Scan the mount table file for the mount point and then match file system 954 * and device/share. We identify our mounts by mount path + prefix for now, 955 * but later we may use the same approach as on solaris. 956 */ 957 char szMountPrefix[RTPATH_MAX]; 958 rc = vbsvcAutomounterQueryMountDirAndPrefix(szMountPrefix, sizeof(szMountPrefix)); 959 AssertRCReturn(rc, rc); 960 size_t const cchMountPrefix = strlen(szMountPrefix); 961 962 FILE *pFile = setmntent(_PATH_MOUNTED, "r"); 963 if (pFile) 964 { 965 rc = VWRN_NOT_FOUND; 966 struct mntent *pEntry; 967 while ((pEntry = getmntent(pFile)) != NULL) 968 if (strcmp(pEntry->mnt_type, "vboxsf") == 0) 969 { 970 /** @todo add mount option for tagging a mount, make kernel show it by 971 * implementing super_operations::show_options. */ 972 if (strncmp(pEntry->mnt_dir, szMountPrefix, cchMountPrefix) == 0) 973 { 974 rc = vbsvcAutomounterAddEntry(pMountTable, pEntry->mnt_fsname, pEntry->mnt_dir); 975 if (RT_FAILURE(rc)) 976 { 977 endmntent(pFile); 978 return rc; 979 } 980 } 981 } 982 endmntent(pFile); 983 } 984 else 985 VGSvcError("vbsvcAutomounterQueryMountPoint: Could not open mount tab '%s' (errno=%d) or '/proc/mounts' (errno=%d)\n", 986 _PATH_MOUNTED, errno); 987 return rc; 988 989 #elif defined(RT_OS_SOLARIS) 990 /* 991 * Look thru the system mount table and inspect the vboxsf mounts. 992 */ 993 FILE *pFile = fopen(_PATH_MOUNTED, "r"); 994 if (pFile) 995 { 996 rc = VINF_SUCCESS; 997 struct mnttab Entry; 998 while (getmntent(pFile, &Entry) == 0) 999 if (strcmp(Entry.mnt_fstype, "vboxsf") == 0) 1000 { 1001 /* Look for the dummy automounter option. */ 1002 if ( Entry.mnt_opts != NULL 1003 && strstr(Entry.mnt_opts, g_szTag) != NULL) 1004 { 1005 rc = vbsvcAutomounterAddEntry(pMountTable, Entry.mnt_special, Entry.mnt_mountp); 1006 if (RT_FAILURE(rc)) 1007 { 1008 fclose(pFile); 1009 return rc; 1010 } 1011 } 1012 } 1013 fclose(pFile); 1014 } 1015 else 1016 VGSvcError("vbsvcAutomounterQueryMountPoint: Could not open mount tab '%s' (errno=%d)\n", _PATH_MOUNTED, errno); 1017 1018 #else 1019 # error "PORTME!" 1020 #endif 1021 1022 /* 1023 * Try reconcile the detected folders with data from the host. 1024 */ 1025 uint32_t cMappings = 0; 1026 PVBGLR3SHAREDFOLDERMAPPING paMappings = NULL; 1027 rc = VbglR3SharedFolderGetMappings(g_idClientSharedFolders, true /*fAutoMountOnly*/, &paMappings, &cMappings); 1028 if (RT_SUCCESS(rc)) 1029 { 1030 for (uint32_t i = 0; i < cMappings && RT_SUCCESS(rc); i++) 1031 { 1032 uint32_t const idRootSrc = paMappings[i].u32Root; 1033 1034 uint32_t uRootIdVer = UINT32_MAX; 1035 uint64_t fFlags = 0; 1036 char *pszName = NULL; 1037 char *pszMntPt = NULL; 1038 int rc2 = VbglR3SharedFolderQueryFolderInfo(g_idClientSharedFolders, idRootSrc, VBOXSERVICE_AUTOMOUNT_MIQF, 1039 &pszName, &pszMntPt, &fFlags, &uRootIdVer); 1040 if (RT_SUCCESS(rc2)) 1041 { 1042 uint32_t iPrevHit = UINT32_MAX; 1043 for (uint32_t iTable = 0; iTable < pMountTable->cEntries; iTable++) 1044 { 1045 PVBSVCAUTOMOUNTERENTRY pEntry = pMountTable->papEntries[iTable]; 1046 if (RTStrICmp(pEntry->pszName, pszName) == 0) 1047 { 1048 VGSvcVerbose(2, "vbsvcAutomounterPopulateTable: Identified %s -> %s: idRoot=%u ver=%u fFlags=%#x AutoMntPt=%s\n", 1049 pEntry->pszActualMountPoint, pEntry->pszName, idRootSrc, uRootIdVer, fFlags, pszMntPt); 1050 pEntry->fFlags = fFlags; 1051 pEntry->idRoot = idRootSrc; 1052 pEntry->uRootIdVersion = uRootIdVer; 1053 RTStrFree(pEntry->pszMountPoint); 1054 pEntry->pszMountPoint = RTStrDup(pszMntPt); 1055 if (!pEntry->pszMountPoint) 1056 { 1057 rc = VERR_NO_MEMORY; 1058 break; 1059 } 1060 1061 /* If multiple mappings of the same folder, pick the first or the one 1062 with matching mount point. */ 1063 if (iPrevHit == UINT32_MAX) 1064 iPrevHit = iTable; 1065 else if (RTPathCompare(pszMntPt, pEntry->pszActualMountPoint) == 0) 1066 { 1067 if (iPrevHit != UINT32_MAX) 1068 pMountTable->papEntries[iPrevHit]->uRootIdVersion -= 1; 1069 iPrevHit = iTable; 1070 } 1071 else 1072 pEntry->uRootIdVersion -= 1; 1073 } 1074 } 1075 1076 RTStrFree(pszName); 1077 RTStrFree(pszMntPt); 1078 } 1079 else 1080 VGSvcError("vbsvcAutomounterPopulateTable: VbglR3SharedFolderQueryFolderInfo(%u) failed: %Rrc\n", idRootSrc, rc2); 1081 } 1082 1083 VbglR3SharedFolderFreeMappings(paMappings); 1084 1085 /* 1086 * Sort the table by root ID. 1087 */ 1088 if (pMountTable->cEntries > 1) 1089 RTSortApvShell((void **)pMountTable->papEntries, pMountTable->cEntries, vbsvcAutomounterCompareEntry, NULL); 1090 1091 for (uint32_t iTable = 0; iTable < pMountTable->cEntries; iTable++) 1092 { 1093 PVBSVCAUTOMOUNTERENTRY pEntry = pMountTable->papEntries[iTable]; 1094 if (pMountTable->papEntries[iTable]->idRoot != UINT32_MAX) 1095 VGSvcVerbose(1, "vbsvcAutomounterPopulateTable: #%u: %s -> %s idRoot=%u ver=%u fFlags=%#x AutoMntPt=%s\n", 1096 iTable, pEntry->pszActualMountPoint, pEntry->pszName, pEntry->idRoot, pEntry->uRootIdVersion, 1097 pEntry->fFlags, pEntry->pszMountPoint); 1098 else 1099 VGSvcVerbose(1, "vbsvcAutomounterPopulateTable: #%u: %s -> %s - not identified!\n", 1100 iTable, pEntry->pszActualMountPoint, pEntry->pszName); 1101 } 1102 } 1103 else 1104 VGSvcError("vbsvcAutomounterPopulateTable: VbglR3SharedFolderGetMappings failed: %Rrc\n", rc); 1105 return rc; 1106 } 1107 1108 1109 /** 1110 * Checks whether the shared folder @a pszName is mounted on @a pszMountPoint. 1111 * 1112 * @returns Exactly one of the following IPRT status codes; 1113 * @retval VINF_SUCCESS if mounted 1114 * @retval VWRN_NOT_FOUND if nothing is mounted at @a pszMountPoint. 1115 * @retval VERR_RESOURCE_BUSY if a different shared folder is mounted there. 1116 * @retval VERR_ACCESS_DENIED if a non-shared folder file system is mounted 1117 * there. 1118 * 1119 * @param pszMountPoint The mount point to check. 1120 * @param pszName The name of the shared folder (mapping). 1121 */ 1122 static int vbsvcAutomounterQueryMountPoint(const char *pszMountPoint, const char *pszName) 1123 { 1124 VGSvcVerbose(4, "vbsvcAutomounterQueryMountPoint: pszMountPoint=%s pszName=%s\n", pszMountPoint, pszName); 1125 1126 #ifdef RT_OS_WINDOWS 1127 /* 1128 * We could've used RTFsQueryType here but would then have to 1129 * calling RTFsQueryLabel for the share name hint, ending up 1130 * doing the same work twice. We could also use QueryDosDeviceW, 1131 * but output is less clear... 1132 */ 1133 PRTUTF16 pwszMountPoint = NULL; 1134 int rc = RTStrToUtf16(pszMountPoint, &pwszMountPoint); 1135 if (RT_SUCCESS(rc)) 1136 { 1137 DWORD uSerial = 0; 1138 DWORD cchCompMax = 0; 1139 DWORD fFlags = 0; 1140 RTUTF16 wszLabel[512]; 1141 RTUTF16 wszFileSystem[256]; 1142 RT_ZERO(wszLabel); 1143 RT_ZERO(wszFileSystem); 1144 if (GetVolumeInformationW(pwszMountPoint, wszLabel, RT_ELEMENTS(wszLabel) - 1, &uSerial, &cchCompMax, &fFlags, 1145 wszFileSystem, RT_ELEMENTS(wszFileSystem) - 1)) 1146 { 1147 if (RTUtf16ICmpAscii(wszFileSystem, "VBoxSharedFolderFS") == 0) 1148 { 1149 char *pszLabel = NULL; 1150 rc = RTUtf16ToUtf8(wszLabel, &pszLabel); 1151 if (RT_SUCCESS(rc)) 1152 { 1153 const char *pszMountedName = pszLabel; 1154 if (RTStrStartsWith(pszMountedName, "VBOX_")) 1155 pszMountedName += sizeof("VBOX_") - 1; 1156 if (RTStrICmp(pszMountedName, pszName) == 0) 1157 { 1158 VGSvcVerbose(3, "vbsvcAutomounterQueryMountPoint: Found shared folder '%s' at '%s' as expected.\n", 1159 pszMountPoint, pszName); 1160 rc = VINF_SUCCESS; 1161 } 1162 else 1163 { 1164 VGSvcVerbose(3, "vbsvcAutomounterQueryMountPoint: Found shared folder '%s' at '%s', not '%s'...\n", 1165 pszMountedName, pszMountPoint, pszName); 1166 rc = VERR_RESOURCE_BUSY; 1167 } 1168 RTStrFree(pszLabel); 1169 } 1170 else 1171 { 1172 VGSvcVerbose(3, "vbsvcAutomounterQueryMountPoint: RTUtf16ToUtf8(%ls,) failed: %Rrc\n", wszLabel, rc); 1173 rc = VERR_RESOURCE_BUSY; 1174 } 1175 } 1176 else 1177 { 1178 VGSvcVerbose(3, "vbsvcAutomounterQueryMountPoint: Found a '%ls' with label '%ls' mount at '%s', not '%s'...\n", 1179 wszFileSystem, wszLabel, pszMountPoint, pszName); 1180 rc = VERR_ACCESS_DENIED; 1181 } 1182 } 1183 else 1184 { 1185 rc = GetLastError(); 1186 if (rc != ERROR_PATH_NOT_FOUND || g_cVerbosity >= 4) 1187 VGSvcVerbose(3, "vbsvcAutomounterQueryMountPoint: GetVolumeInformationW('%ls',,,,) failed: %u\n", pwszMountPoint, rc); 1188 rc = VWRN_NOT_FOUND; 1189 } 1190 RTUtf16Free(pwszMountPoint); 1191 } 1192 else 1193 { 1194 VGSvcError("vbsvcAutomounterQueryMountPoint: RTStrToUtf16(%s,) -> %Rrc\n", pszMountPoint, rc); 1195 rc = VWRN_NOT_FOUND; 1196 } 1197 return rc; 1198 1199 #elif defined(RT_OS_OS2) 1200 /* 1201 * Query file system attachment info for the given drive letter. 1202 */ 1203 union 1204 { 1205 FSQBUFFER2 FsQueryBuf; 1206 char achPadding[512]; 1207 } uBuf; 1208 RT_ZERO(uBuf); 1209 1210 ULONG cbBuf = sizeof(uBuf); 1211 APIRET rcOs2 = DosQueryFSAttach((PCSZ)pFsInfo->szMountpoint, 0, FSAIL_QUERYNAME, uBuf, &cbBuf); 1212 int rc; 1213 if (rcOs2 == NO_ERROR) 1214 { 1215 const char *pszFsdName = &uBuf.FsQueryBuf.szName[uBuf.FsQueryBuf.cbName + 1]; 1216 if ( uBuf.FsQueryBuf.iType == FSAT_REMOTEDRV 1217 && RTStrICmpAscii(pszFsdName, "VBOXSF") == 0) 1218 { 1219 const char *pszMountedName = &pszFsdName[uBuf.FsQueryBuf.cbFSDName + 1]; 1220 if (RTStrICmp(pszMountedName, pszName) == 0) 1221 { 1222 VGSvcVerbose(3, "vbsvcAutomounterQueryMountPoint: Found shared folder '%s' at '%s' as expected.\n", 1223 pszMountPoint, pszName); 1224 rc = VINF_SUCCESS; 1225 } 1226 else 1227 { 1228 VGSvcVerbose(3, "vbsvcAutomounterQueryMountPoint: Found shared folder '%s' at '%s', not '%s'...\n", 1229 pszMountedName, pszMountPoint, pszName); 1230 rc = VERR_RESOURCE_BUSY; 1231 } 1232 } 1233 else 1234 { 1235 VGSvcVerbose(3, "vbsvcAutomounterQueryMountPoint: Found a '%s' type %u mount at '%s', not '%s'...\n", 1236 pszFsdName, uBuf.FsQueryBuf.iType, pszMountPoint, pszName); 1237 rc = VERR_ACCESS_DENIED; 1238 } 1239 } 1240 else 1241 { 1242 rc = VWRN_NOT_FOUND; 1243 VGSvcVerbose(3, "vbsvcAutomounterQueryMountPoint: DosQueryFSAttach(%s) -> %u\n", pszMountPoint, rcOs2); 1244 AssertMsgStmt(rcOs2 != ERROR_BUFFER_OVERFLOW && rcOs2 != ERROR_INVALID_PARAMETER, 1245 ("%s -> %u\n", pszMountPoint, rcOs2), rc = VERR_ACCESS_DENIED); 1246 } 1247 return rc; 1248 1249 #elif defined(RT_OS_LINUX) 1250 /* 1251 * Scan one of the mount table file for the mount point and then 1252 * match file system and device/share. 1253 */ 1254 FILE *pFile = setmntent(_PATH_MOUNTED, "r"); 1255 int rc = errno; 1256 if (!pFile) 1257 pFile = setmntent("/proc/mounts", "r"); 1258 if (pFile) 1259 { 1260 rc = VWRN_NOT_FOUND; 1261 struct mntent *pEntry; 1262 while ((pEntry = getmntent(pFile)) != NULL) 1263 if (RTPathCompare(pEntry->mnt_dir, pszMountPoint) == 0) 1264 { 1265 if (strcmp(pEntry->mnt_type, "vboxsf") == 0) 1266 { 1267 if (RTStrICmp(pEntry->mnt_fsname, pszName) == 0) 1268 { 1269 VGSvcVerbose(3, "vbsvcAutomounterQueryMountPoint: Found shared folder '%s' at '%s' as expected.\n", 1270 pszMountPoint, pszName); 1271 rc = VINF_SUCCESS; 1272 } 1273 else 1274 { 1275 VGSvcVerbose(3, "vbsvcAutomounterQueryMountPoint: Found shared folder '%s' at '%s', not '%s'...\n", 1276 pEntry->mnt_fsname, pszMountPoint, pszName); 1277 rc = VERR_RESOURCE_BUSY; 1278 } 1279 } 1280 else 1281 { 1282 VGSvcVerbose(3, "vbsvcAutomounterQueryMountPoint: Found a '%s' mount of '%s' at '%s', not '%s'...\n", 1283 pEntry->mnt_type, pEntry->mnt_fsname, pszMountPoint, pszName); 1284 rc = VERR_ACCESS_DENIED; 1285 } 1286 /* We continue searching in case of stacked mounts, we want the last one. */ 1287 } 1288 endmntent(pFile); 1289 } 1290 else 1291 { 1292 VGSvcError("vbsvcAutomounterQueryMountPoint: Could not open mount tab '%s' (errno=%d) or '/proc/mounts' (errno=%d)\n", 1293 _PATH_MOUNTED, rc, errno); 1294 rc = VERR_ACCESS_DENIED; 1295 } 1296 return rc; 1297 1298 #elif defined(RT_OS_SOLARIS) 1299 /* 1300 * Similar to linux. 1301 */ 1302 int rc; 1303 FILE *pFile = fopen(_PATH_MOUNTED, "r"); 1304 if (pFile) 1305 { 1306 rc = VWRN_NOT_FOUND; 1307 struct mnttab Entry; 1308 while (getmntent(pFile, &Entry) == 0) 1309 if (RTPathCompare(Entry.mnt_mountp, pszMountPoint) == 0) 1310 { 1311 if (strcmp(Entry.mnt_fstype, "vboxsf") == 0) 1312 { 1313 if (RTStrICmp(Entry.mnt_special, pszName) == 0) 1314 { 1315 VGSvcVerbose(3, "vbsvcAutomounterQueryMountPoint: Found shared folder '%s' at '%s' as expected.\n", 1316 pszMountPoint, pszName); 1317 rc = VINF_SUCCESS; 1318 } 1319 else 1320 { 1321 VGSvcVerbose(3, "vbsvcAutomounterQueryMountPoint: Found shared folder '%s' at '%s', not '%s'...\n", 1322 Entry.mnt_special, pszMountPoint, pszName); 1323 rc = VERR_RESOURCE_BUSY; 1324 } 1325 } 1326 else 1327 { 1328 VGSvcVerbose(3, "vbsvcAutomounterQueryMountPoint: Found a '%s' mount of '%s' at '%s', not '%s'...\n", 1329 Entry.mnt_fstype, Entry.mnt_special, pszMountPoint, pszName); 1330 rc = VERR_ACCESS_DENIED; 1331 } 1332 /* We continue searching in case of stacked mounts, we want the last one. */ 1333 } 1334 fclose(pFile); 1335 } 1336 else 1337 { 1338 VGSvcError("vbsvcAutomounterQueryMountPoint: Could not open mount tab '%s' (errno=%d)\n", _PATH_MOUNTED, errno); 1339 rc = VERR_ACCESS_DENIED; 1340 } 1341 return rc; 1342 #else 1343 # error "PORTME" 1344 #endif 1345 } 1346 1347 1348 /** 1349 * Worker for vbsvcAutomounterMountNewEntry that does the OS mounting. 1350 * 1351 * @returns IPRT status code. 1352 * @param pEntry The entry to try mount. 1353 */ 1354 static int vbsvcAutomounterMountIt(PVBSVCAUTOMOUNTERENTRY pEntry) 1355 { 1356 VGSvcVerbose(3, "vbsvcAutomounterMountIt: Trying to mount '%s' (idRoot=%#x) on '%s'...\n", 1357 pEntry->pszName, pEntry->idRoot, pEntry->pszActualMountPoint); 1358 #ifdef RT_OS_WINDOWS 1359 /* 1360 * Attach the shared folder using WNetAddConnection2W. 598 1361 * 599 * This thread exits so fast while doing its own startup in VGSvcStartServices() 600 * that this->fShutdown flag is set to true in VGSvcThread() before we have the 601 * chance to check for a service failure in VGSvcStartServices() to indicate 602 * a VBoxService startup error. 1362 * According to google we should get a drive symlink in \\GLOBAL?? when 1363 * we are running under the system account. Otherwise it will a session 1364 * local link (\\??). 1365 */ 1366 Assert(RT_C_IS_UPPER(pEntry->pszActualMountPoint[0]) && pEntry->pszActualMountPoint[1] == ':' && pEntry->pszActualMountPoint[2] == '\0'); 1367 RTUTF16 wszDrive[4] = { pEntry->pszActualMountPoint[0], ':', '\0', '\0' }; 1368 1369 RTUTF16 wszPrefixedName[RTPATH_MAX]; 1370 int rc = RTUtf16CopyAscii(wszPrefixedName, RT_ELEMENTS(wszPrefixedName), "\\\\VBoxSvr\\"); 1371 AssertRC(rc); 1372 1373 PRTUTF16 pwszName = &wszPrefixedName[RTUtf16Len(wszPrefixedName)]; 1374 rc = RTStrToUtf16Ex(pEntry->pszName, RTSTR_MAX, &pwszName, pwszName - wszPrefixedName, NULL); 1375 if (RT_FAILURE(rc)) 1376 { 1377 VGSvcError("vbsvcAutomounterMountIt: RTStrToUtf16Ex failed on '%s': %Rrc\n", pEntry->pszName, rc); 1378 return rc; 1379 } 1380 1381 NETRESOURCEW NetRsrc; 1382 RT_ZERO(NetRsrc); 1383 NetRsrc.dwType = RESOURCETYPE_DISK; 1384 NetRsrc.lpLocalName = wszDrive; 1385 NetRsrc.lpRemoteName = wszPrefixedName; 1386 NetRsrc.lpProvider = L"VirtualBox Shared Folders"; /* Only try our provider. */ 1387 NetRsrc.lpComment = pwszName; 1388 1389 DWORD dwErr = WNetAddConnection2W(&NetRsrc, NULL /*pwszPassword*/, NULL /*pwszUserName*/, 0 /*dwFlags*/); 1390 if (dwErr == NO_ERROR) 1391 { 1392 VGSvcVerbose(0, "vbsvcAutomounterMountIt: Successfully mounted '%s' on '%s'\n", 1393 pEntry->pszName, pEntry->pszActualMountPoint); 1394 return VINF_SUCCESS; 1395 } 1396 VGSvcError("vbsvcAutomounterMountIt: Failed to attach '%s' to '%s': %u\n", 1397 pEntry->pszName, pEntry->pszActualMountPoint, rc); 1398 return VERR_OPEN_FAILED; 1399 1400 #elif defined(RT_OS_OS2) 1401 /* 1402 * It's a rather simple affair on OS/2. 603 1403 * 604 * Therefore *no* service threads are allowed to quit themselves and need to wait 605 * for the pfShutdown flag to be set by the main thread. 606 */ 607 /** @todo r=bird: Shared folders have always been configurable at run time, so 608 * this service must be changed to check for changes and execute those changes! 609 * 610 * The 0.5sec sleep here is just soo crude and must go! 611 */ 1404 * In order to be able to detect our mounts we add a 2nd string after 1405 * the folder name that tags the attachment. The IFS will remember this 1406 * and return it when DosQueryFSAttach is called. 1407 * 1408 * Note! Kernel currently accepts limited 7-bit ASCII names. We could 1409 * change that to UTF-8 if we like as that means no extra string 1410 * encoding conversion fun here. 1411 */ 1412 char szzNameAndTag[256]; 1413 size_t cchName = strlen(pEntry->pszName); 1414 if (cchName + 1 + sizeof(g_szTag) <= sizeof(szzNameAndTag)) 1415 { 1416 memcpy(szzNameAndTag, pEntry->pszName, cchName); 1417 szzNameAndTag[cchName] = '\0'; 1418 memcpy(&szzNameAndTag[cchName + 1], g_szTag, sizeof(g_szTag)); 1419 1420 APIRET rc = DosFSAttach(pEntry->pszActualMountPoint, "VBOXSF", szzNameAndTag, cchName + 1 + sizeof(g_szzTag), FS_ATTACH); 1421 if (rc == NO_ERROR) 1422 { 1423 VGSvcVerbose(0, "vbsvcAutomounterMountIt: Successfully mounted '%s' on '%s'\n", 1424 pEntry->pszName, pEntry->pszActualMountPoint); 1425 return VINF_SUCCESS; 1426 } 1427 VGSvcError("vbsvcAutomounterMountIt: DosFSAttach failed to attach '%s' to '%s': %u\n", 1428 pEntry->pszName, pEntry->pszActualMountPoint, rc); 1429 } 1430 else 1431 VGSvcError("vbsvcAutomounterMountIt: Share name for attach to '%s' is too long: %u chars - '%s'\n", 1432 pEntry->pszActualMountPoint, cchName, pEntry->pszName; 1433 return VERR_OPEN_FAILED; 1434 1435 #else 1436 /* 1437 * Common work for unix-like systems: Get group, make sure mount directory exist. 1438 */ 1439 int rc = RTDirCreateFullPath(pEntry->pszActualMountPoint, 1440 RTFS_UNIX_IRWXU | RTFS_UNIX_IXGRP | RTFS_UNIX_IRGRP | RTFS_UNIX_IXOTH | RTFS_UNIX_IROTH); 1441 if (RT_FAILURE(rc)) 1442 { 1443 VGSvcError("vbsvcAutomounterMountIt: Failed to create mount path '%s' for share '%s': %Rrc\n", 1444 pEntry->pszActualMountPoint, pEntry->pszName, rc); 1445 return rc; 1446 } 1447 1448 gid_t gidMount; 1449 struct group *grp_vboxsf = getgrnam("vboxsf"); 1450 if (grp_vboxsf) 1451 gidMount = grp_vboxsf->gr_gid; 1452 else 1453 { 1454 VGSvcError("vbsvcAutomounterMountIt: Group 'vboxsf' does not exist\n"); 1455 gidMount = 0; 1456 } 1457 1458 # if defined(RT_OS_LINUX) 1459 /* 1460 * Linux a bit more work... 1461 */ 1462 struct vbsf_mount_info_new MntInfo; 1463 RT_ZERO(MntInfo); 1464 struct vbsf_mount_opts MntOpts; 1465 RT_ZERO(MntOpts); 1466 MntInfo.nullchar = '\0'; 1467 MntInfo.signature[0] = VBSF_MOUNT_SIGNATURE_BYTE_0; 1468 MntInfo.signature[1] = VBSF_MOUNT_SIGNATURE_BYTE_1; 1469 MntInfo.signature[2] = VBSF_MOUNT_SIGNATURE_BYTE_2; 1470 MntInfo.length = sizeof(MntInfo); 1471 MntInfo.uid = MntOpts.uid = 0; 1472 MntInfo.gid = MntOpts.gid = gidMount; 1473 MntInfo.dmode = MntOpts.dmode = 0770; 1474 MntInfo.fmode = MntOpts.fmode = 0770; 1475 MntInfo.dmask = MntOpts.dmask = 0000; 1476 MntInfo.fmask = MntOpts.fmask = 0000; 1477 rc = RTStrCopy(MntInfo.name, sizeof(MntInfo.name), pEntry->pszName); 1478 if (RT_FAILURE(rc)) 1479 { 1480 VGSvcError("vbsvcAutomounterMountIt: Share name '%s' is too long for the MntInfo.name field!\n", pEntry->pszName); 1481 return rc; 1482 } 1483 1484 errno = 0; 1485 unsigned long fFlags = MS_NODEV; 1486 rc = mount(pEntry->pszName, pEntry->pszActualMountPoint, "vboxsf", fFlags, &MntInfo); 1487 if (rc == 0) 1488 { 1489 VGSvcVerbose(0, "vbsvcAutomounterMountIt: Successfully mounted '%s' on '%s'\n", 1490 pEntry->pszName, pEntry->pszActualMountPoint); 1491 1492 errno = 0; 1493 rc = vbsfmount_complete(pEntry->pszName, pEntry->pszActualMountPoint, fFlags, &MntOpts); 1494 if (rc == 0) 1495 return VINF_SUCCESS; 1496 1497 VGSvcError("vbsvcAutomounterMountIt: vbsfmount_complete failed: %s (%d/%d)\n", 1498 rc == 1 ? "open_memstream" : rc == 2 ? "setmntent" : rc == 3 ? "addmntent" : "unknown", rc, errno); 1499 } 1500 else if (errno == EINVAL) 1501 VGSvcError("vbsvcAutomounterMountIt: Failed to mount '%s' on '%s' because it is probably mounted elsewhere arleady! (%d,%d)\n", 1502 pEntry->pszName, pEntry->pszActualMountPoint, rc, errno); 1503 else 1504 VGSvcError("vbsvcAutomounterMountIt: Failed to mount '%s' on '%s': %s (%d,%d)\n", 1505 pEntry->pszName, pEntry->pszActualMountPoint, strerror(errno), rc, errno); 1506 return VERR_WRITE_ERROR; 1507 1508 # elif defined(RT_OS_SOLARIS) 1509 /* 1510 * Solaris is rather simple compared to linux. 1511 * 1512 * The ',VBoxService=auto' option (g_szTag) is ignored by the kernel but helps 1513 * us identify our own mounts on restart. See vbsvcAutomounterPopulateTable(). 1514 */ 1515 char szOpts[MAX_MNTOPT_STR] = { '\0', }; 1516 ssize_t cchOpts = RTStrPrintf2(szOpts, sizeof(szOpts), 1517 "uid=0,gid=%d,dmode=0770,fmode=0770,dmask=0000,fmask=0000%s", gidMount, g_szTag); 1518 if (cchOpts <= 0) 1519 { 1520 VGSvcError("vbsvcAutomounterMountIt: szOpts overflow! %zd\n", cchOpts); 1521 return VERR_BUFFER_OVERFLOW; 1522 } 1523 1524 rc = mount(pEntry->pszName, pEntry->pszActualMountPoint, MS_OPTIONSTR, "vboxfs", 1525 NULL /*dataptr*/, 0 /* datalen */, szOptBuf, cchOpts + 1); 1526 if (rc == 0) 1527 { 1528 VGSvcVerbose(0, "vbsvcAutomounterMountIt: Shared folder '%s' was mounted to '%s'\n", pszShareName, pszMountPoint); 1529 return VINF_SUCCESS; 1530 } 1531 1532 rc = errno; 1533 VGSvcError("vbsvcAutomounterMountIt: mount failed for '%s' at '%s': %s (%d)\n", 1534 pEntry->pszName, pEntry->pszActualMountPoint, strerror(rc), rc); 1535 return VERR_OPEN_FAILED; 1536 1537 # else 1538 # error "PORTME!" 1539 # endif 1540 #endif 1541 } 1542 1543 1544 /** 1545 * Attempts to mount the given shared folder, adding it to the mount table on 1546 * success. 1547 * 1548 * @returns iTable + 1 on success, iTable on failure. 1549 * @param pTable The mount table. 1550 * @param iTable The mount table index at which to add the mount. 1551 * @param pszName The name of the shared folder mapping. 1552 * @param pszMntPt The mount point (hint) specified by the host. 1553 * @param fFlags The shared folder flags, SHFL_MIF_XXX. 1554 * @param idRoot The root ID. 1555 * @param uRootIdVersion The root ID version. 1556 * @param fAutoMntPt Whether to try automatically assign a mount point if 1557 * pszMntPt doesn't work out. This is set in pass \#3. 1558 */ 1559 static uint32_t vbsvcAutomounterMountNewEntry(PVBSVCAUTOMOUNTERTABLE pTable, uint32_t iTable, 1560 const char *pszName, const char *pszMntPt, uint64_t fFlags, 1561 uint32_t idRoot, uint32_t uRootIdVersion, bool fAutoMntPt) 1562 { 1563 VGSvcVerbose(3, "vbsvcAutomounterMountNewEntry: #%u: '%s' at '%s'%s\n", 1564 iTable, pszName, pszMntPt, fAutoMntPt ? " auto-assign" : ""); 1565 1566 /* 1567 * First we need to figure out the actual mount point. 1568 */ 1569 char szActualMountPoint[RTPATH_MAX]; 1570 1571 #if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS) 1572 /* 1573 * Drive letter based: 1574 */ 1575 char chNextLetter = 'Z'; 1576 if (RT_C_IS_UPPER(pszMntPt[0]) && pszMntPt[1] == ':') 1577 szActualMountPoint[0] = RT_C_TO_UPPER(pszMntPt[0]); 1578 else if (!fAutoMntPt) 1579 return iTable; 1580 else 1581 szActualMountPoint[0] = chNextLetter--; 1582 szActualMountPoint[1] = ':'; 1583 szActualMountPoint[2] = '\0'; 1584 1585 int rc; 612 1586 for (;;) 613 1587 { 614 /* Do we need to shutdown? */615 if ( *pfShutdown)1588 rc = vbsvcAutomounterQueryMountPoint(szActualMountPoint, pszName); 1589 if (rc == VWRN_NOT_FOUND) 616 1590 break; 617 1591 618 /* Let's sleep for a bit and let others run ... */ 619 RTThreadSleep(500); 620 } 621 622 VGSvcVerbose(3, "vbsvcAutoMountWorker: Finished with rc=%Rrc\n", rc); 1592 /* next */ 1593 if (chNextLetter == 'A' || !fAutoMntPt) 1594 return iTable; 1595 szActualMountPoint[0] = chNextLetter--; 1596 } 1597 1598 #else 1599 /* 1600 * Path based #1: Host specified mount point. 1601 */ 1602 int rc = VERR_ACCESS_DENIED; 1603 if (*pszMntPt == '/') 1604 { 1605 rc = RTPathAbs(pszMntPt, szActualMountPoint, sizeof(szActualMountPoint)); 1606 if (RT_SUCCESS(rc)) 1607 { 1608 static const char * const s_apszBlacklist[] = 1609 { "/", "/dev", "/bin", "/sbin", "/lib", "/etc", "/var", "/tmp", "/usr", "/usr/bin", "/usr/sbin", "/usr/lib" }; 1610 for (size_t i = 0; i < RT_ELEMENTS(s_apszBlacklist); i++) 1611 if (strcmp(szActualMountPoint, s_apszBlacklist[i]) == 0) 1612 { 1613 rc = VERR_ACCESS_DENIED; 1614 break; 1615 } 1616 if (RT_SUCCESS(rc)) 1617 rc = vbsvcAutomounterQueryMountPoint(szActualMountPoint, pszName); 1618 } 1619 } 1620 if (rc != VWRN_NOT_FOUND) 1621 { 1622 if (!fAutoMntPt) 1623 return iTable; 1624 1625 /* 1626 * Path based #2: Mount dir + prefix + share. 1627 */ 1628 /* Mount base directory: */ 1629 szActualMountPoint[0] = '\0'; 1630 char *pszProp; 1631 rc = VbglR3SharedFolderGetMountDir(&pszProp); 1632 if (RT_SUCCESS(rc)) 1633 { 1634 if (*pszProp == '/') 1635 rc = RTPathAbs(pszProp, szActualMountPoint, sizeof(szActualMountPoint)); 1636 else 1637 VGSvcError("vbsvcAutomounterMountNewEntry: Invalid mount directory: '%s'\n", pszProp); 1638 RTStrFree(pszProp); 1639 } 1640 if (RT_FAILURE(rc) || szActualMountPoint[0] != '/') 1641 memcpy(szActualMountPoint, VBOXSERVICE_AUTOMOUNT_DEFAULT_DIR, sizeof(VBOXSERVICE_AUTOMOUNT_DEFAULT_DIR)); 1642 1643 /* Add prefix: */ 1644 rc = VbglR3SharedFolderGetMountPrefix(&pszProp); 1645 if (RT_SUCCESS(rc)) 1646 { 1647 if ( strchr(pszProp, '/') == NULL 1648 && strchr(pszProp, '\\') == NULL 1649 && strcmp(pszProp, "..") != 0) 1650 rc = RTPathAppend(szActualMountPoint, sizeof(szActualMountPoint), pszProp); 1651 else 1652 VGSvcError("vbsvcAutomounterMountNewEntry: Invalid mount prefix: '%s'\n", pszProp); 1653 RTStrFree(pszProp); 1654 } 1655 else 1656 rc = RTPathEnsureTrailingSeparator(szActualMountPoint, sizeof(szActualMountPoint)) != 0 1657 ? VINF_SUCCESS : VERR_BUFFER_OVERFLOW; 1658 if (RT_SUCCESS(rc)) 1659 { 1660 /* Add sanitized share name: */ 1661 size_t const offShare = strlen(szActualMountPoint); 1662 size_t offDst = offShare; 1663 size_t offSrc = 0; 1664 for (;;) 1665 { 1666 char ch = pszName[offSrc++]; 1667 if (ch == ' ' || ch == '/' || ch == '\\' || ch == ':' || ch == '$') 1668 ch = '_'; 1669 else if (!ch) 1670 break; 1671 else if (ch < 0x20 || ch == 0x7f) 1672 continue; 1673 if (offDst < sizeof(szActualMountPoint) - 1) 1674 szActualMountPoint[offDst++] = ch; 1675 } 1676 szActualMountPoint[offDst] = '\0'; 1677 if (offDst > offShare) 1678 { 1679 rc = vbsvcAutomounterQueryMountPoint(szActualMountPoint, pszName); 1680 if (rc != VWRN_NOT_FOUND) 1681 { 1682 /* 1683 * Path based #3: Mount dir + prefix + share + _ + number. 1684 */ 1685 if (offDst + 2 >= sizeof(szActualMountPoint)) 1686 return iTable; 1687 1688 szActualMountPoint[offDst++] = '_'; 1689 for (uint32_t iTry = 1; iTry < 10 && rc != VWRN_NOT_FOUND; iTry++) 1690 { 1691 szActualMountPoint[offDst] = '0' + iTry; 1692 szActualMountPoint[offDst + 1] = '\0'; 1693 rc = vbsvcAutomounterQueryMountPoint(szActualMountPoint, pszName); 1694 } 1695 if (rc != VWRN_NOT_FOUND) 1696 return iTable; 1697 } 1698 } 1699 else 1700 VGSvcError("vbsvcAutomounterMountNewEntry: Bad share name: %.*Rhxs", strlen(pszName), pszName); 1701 } 1702 else 1703 VGSvcError("vbsvcAutomounterMountNewEntry: Failed to construct basic auto mount point for '%s'", pszName); 1704 } 1705 #endif 1706 1707 /* 1708 * Prepare a table entry and ensure space in the table.. 1709 */ 1710 if (pTable->cEntries + 1 > pTable->cAllocated) 1711 { 1712 void *pvEntries = RTMemRealloc(pTable->papEntries, sizeof(pTable->papEntries[0]) * (pTable->cAllocated + 8)); 1713 if (!pvEntries) 1714 { 1715 VGSvcError("vbsvcAutomounterMountNewEntry: Out of memory for growing table (size %u)\n", pTable->cAllocated); 1716 return iTable; 1717 } 1718 pTable->cAllocated += 8; 1719 pTable->papEntries = (PVBSVCAUTOMOUNTERENTRY *)pvEntries; 1720 } 1721 1722 PVBSVCAUTOMOUNTERENTRY pEntry = (PVBSVCAUTOMOUNTERENTRY)RTMemAlloc(sizeof(*pEntry)); 1723 if (pEntry) 1724 { 1725 pEntry->idRoot = idRoot; 1726 pEntry->uRootIdVersion = uRootIdVersion; 1727 pEntry->fFlags = fFlags; 1728 pEntry->pszName = RTStrDup(pszName); 1729 pEntry->pszMountPoint = RTStrDup(pszMntPt); 1730 pEntry->pszActualMountPoint = RTStrDup(szActualMountPoint); 1731 if (pEntry->pszName && pEntry->pszMountPoint && pEntry->pszActualMountPoint) 1732 { 1733 /* 1734 * Now try mount it. 1735 */ 1736 rc = vbsvcAutomounterMountIt(pEntry); 1737 if (RT_SUCCESS(rc)) 1738 { 1739 uint32_t cToMove = pTable->cEntries - iTable; 1740 if (cToMove > 0) 1741 memmove(&pTable->papEntries[iTable + 1], &pTable->papEntries[iTable], cToMove * sizeof(pTable->papEntries[0])); 1742 pTable->papEntries[iTable] = pEntry; 1743 pTable->cEntries++; 1744 return iTable + 1; 1745 } 1746 } 1747 else 1748 VGSvcError("vbsvcAutomounterMountNewEntry: Out of memory for table entry!\n"); 1749 RTMemFree(pEntry->pszActualMountPoint); 1750 RTMemFree(pEntry->pszMountPoint); 1751 RTMemFree(pEntry->pszName); 1752 RTMemFree(pEntry); 1753 } 1754 else 1755 VGSvcError("vbsvcAutomounterMountNewEntry: Out of memory for table entry!\n"); 1756 return iTable; 1757 } 1758 1759 1760 1761 /** 1762 * Does the actual unmounting. 1763 * 1764 * @returns Exactly one of the following IPRT status codes; 1765 * @retval VINF_SUCCESS if successfully umounted or nothing was mounted there. 1766 * @retval VERR_TRY_AGAIN if the shared folder is busy. 1767 * @retval VERR_RESOURCE_BUSY if a different shared folder is mounted there. 1768 * @retval VERR_ACCESS_DENIED if a non-shared folder file system is mounted 1769 * there. 1770 * 1771 * @param pszMountPoint The mount point. 1772 * @param pszName The shared folder (mapping) name. 1773 */ 1774 static int vbsvcAutomounterUnmount(const char *pszMountPoint, const char *pszName) 1775 { 1776 /* 1777 * Retry for 5 seconds in a hope that busy mounts will quiet down. 1778 */ 1779 for (unsigned iTry = 0; ; iTry++) 1780 { 1781 /* 1782 * Check what's mounted there before we start umounting stuff. 1783 */ 1784 int rc = vbsvcAutomounterQueryMountPoint(pszMountPoint, pszName); 1785 if (rc == VINF_SUCCESS) 1786 { /* pszName is mounted there */ } 1787 else if (rc == VWRN_NOT_FOUND) /* nothing mounted there */ 1788 return VINF_SUCCESS; 1789 else 1790 { 1791 Assert(rc == VERR_RESOURCE_BUSY || rc == VERR_ACCESS_DENIED); 1792 return VERR_RESOURCE_BUSY; 1793 } 1794 1795 /* 1796 * Do host specific unmounting. 1797 */ 1798 #ifdef RT_OS_WINDOWS 1799 Assert(RT_C_IS_UPPER(pszMountPoint[0]) && pszMountPoint[1] == ':' && pszMountPoint[2] == '\0'); 1800 RTUTF16 const wszDrive[4] = { pszMountPoint[0], ':', '\0', '\0' }; 1801 DWORD dwErr = WNetCancelConnection2W(wszDrive, 0 /*dwFlags*/, FALSE /*fForce*/); 1802 if (dwErr == NO_ERROR) 1803 return VINF_SUCCESS; 1804 VGSvcVerbose(2, "vbsvcAutomounterUnmount: WNetCancelConnection2W returns %u for '%s' ('%s')\n", dwErr, pszMountPoint, pszName); 1805 if (dwErr == ERROR_NOT_CONNECTED) 1806 return VINF_SUCCESS; 1807 1808 #elif defined(RT_OS_OS2) 1809 APIRET rcOs2 = DosFSAttach(pszMountPoint, "VBOXSF", NULL, 0, FS_DETACH); 1810 if (rcOs2 == NO_ERROR) 1811 return VINF_SUCCESS; 1812 VGSvcVerbose(2, "vbsvcAutomounterUnmount: DosFSAttach failed on '%s' ('%s'): %u\n", pszMountPoint, pszName, rcOs2); 1813 if (rcOs2 == ERROR_INVALID_FSD_NAME) 1814 return VERR_ACCESS_DENIED; 1815 if ( rcOs2 == ERROR_INVALID_DRIVE 1816 || rcOs2 == ERROR_INVALID_PATH) 1817 return VERR_TRY_AGAIN; 1818 1819 #else 1820 int rc2 = umount(pszMountPoint); 1821 if (rc2 == 0) 1822 return VINF_SUCCESS; 1823 rc2 = errno; 1824 VGSvcVerbose(2, "vbsvcAutomounterUnmount: umount failed on '%s' ('%s'): %d\n", pszMountPoint, pszName, rc2); 1825 if (rc2 != EBUSY && rc2 != EAGAIN) 1826 return VERR_ACCESS_DENIED; 1827 #endif 1828 1829 /* 1830 * Check what's mounted there before we start delaying. 1831 */ 1832 RTThreadSleep(8); /* fudge */ 1833 rc = vbsvcAutomounterQueryMountPoint(pszMountPoint, pszName); 1834 if (rc == VINF_SUCCESS) 1835 { /* pszName is mounted there */ } 1836 else if (rc == VWRN_NOT_FOUND) /* nothing mounted there */ 1837 return VINF_SUCCESS; 1838 else 1839 { 1840 Assert(rc == VERR_RESOURCE_BUSY || rc == VERR_ACCESS_DENIED); 1841 return VERR_RESOURCE_BUSY; 1842 } 1843 1844 if (iTry >= 5) 1845 return VERR_TRY_AGAIN; 1846 RTThreadSleep(1000); 1847 } 1848 } 1849 1850 1851 /** 1852 * Unmounts a mount table entry and evicts it from the table if successful. 1853 * 1854 * @returns The next iTable (same value on success, +1 on failure). 1855 * @param pTable The mount table. 1856 * @param iTable The table entry. 1857 * @param pszReason Why we're here. 1858 */ 1859 static uint32_t vbsvcAutomounterUnmountEntry(PVBSVCAUTOMOUNTERTABLE pTable, uint32_t iTable, const char *pszReason) 1860 { 1861 Assert(iTable < pTable->cEntries); 1862 PVBSVCAUTOMOUNTERENTRY pEntry = pTable->papEntries[iTable]; 1863 VGSvcVerbose(3, "vbsvcAutomounterUnmountEntry: #%u: '%s' at '%s' (reason: %s)\n", 1864 iTable, pEntry->pszName, pEntry->pszMountPoint, pszReason); 1865 1866 /* 1867 * Do we need to umount the entry? Return if unmount fails and we . 1868 */ 1869 if (pEntry->pszActualMountPoint) 1870 { 1871 int rc = vbsvcAutomounterUnmount(pEntry->pszActualMountPoint, pEntry->pszName); 1872 if (rc == VERR_TRY_AGAIN) 1873 { 1874 VGSvcVerbose(2, "vbsvcAutomounterUnmountEntry: Keeping '%s' -> '%s' (VERR_TRY_AGAIN)\n", 1875 pEntry->pszActualMountPoint, pEntry->pszName); 1876 return iTable + 1; 1877 } 1878 } 1879 1880 /* 1881 * Remove the entry by shifting up the ones after it. 1882 */ 1883 pTable->cEntries -= 1; 1884 uint32_t cAfter = pTable->cEntries - iTable; 1885 if (cAfter) 1886 memmove(&pTable->papEntries[iTable], &pTable->papEntries[iTable + 1], cAfter * sizeof(pTable->papEntries[0])); 1887 pTable->papEntries[pTable->cEntries] = NULL; 1888 1889 RTStrFree(pEntry->pszActualMountPoint); 1890 pEntry->pszActualMountPoint = NULL; 1891 RTStrFree(pEntry->pszMountPoint); 1892 pEntry->pszMountPoint = NULL; 1893 RTStrFree(pEntry->pszName); 1894 pEntry->pszName = NULL; 1895 RTMemFree(pEntry); 1896 1897 return iTable; 1898 } 1899 1900 1901 /** 1902 * @callback_method_impl{FNRTSORTCMP, For sorting the mappings by ID,} 1903 */ 1904 static DECLCALLBACK(int) vbsvcSharedFolderMappingCompare(void const *pvElement1, void const *pvElement2, void *pvUser) 1905 { 1906 RT_NOREF_PV(pvUser); 1907 PVBGLR3SHAREDFOLDERMAPPING pMapping1 = (PVBGLR3SHAREDFOLDERMAPPING)pvElement1; 1908 PVBGLR3SHAREDFOLDERMAPPING pMapping2 = (PVBGLR3SHAREDFOLDERMAPPING)pvElement2; 1909 return pMapping1->u32Root < pMapping2->u32Root ? -1 : pMapping1->u32Root != pMapping2->u32Root ? 1 : 0; 1910 } 1911 1912 1913 /** 1914 * Refreshes the mount table. 1915 * 1916 * @returns true if we've processed the current config, false if we failed to 1917 * query the mappings. 1918 * @param pTable The mount table to refresh. 1919 */ 1920 static bool vbsvcAutomounterRefreshTable(PVBSVCAUTOMOUNTERTABLE pTable) 1921 { 1922 /* 1923 * Query the root IDs of all auto-mountable shared folder mappings. 1924 */ 1925 uint32_t cMappings = 0; 1926 PVBGLR3SHAREDFOLDERMAPPING paMappings = NULL; 1927 int rc = VbglR3SharedFolderGetMappings(g_idClientSharedFolders, true /*fAutoMountOnly*/, &paMappings, &cMappings); 1928 if (RT_FAILURE(rc)) 1929 { 1930 VGSvcError("vbsvcAutomounterRefreshTable: VbglR3SharedFolderGetMappings failed: %Rrc\n", rc); 1931 return false; 1932 } 1933 1934 /* 1935 * Walk the table and the mappings in parallel, so we have to make sure 1936 * they are both sorted by root ID. 1937 */ 1938 if (cMappings > 1) 1939 RTSortShell(paMappings, cMappings, sizeof(paMappings[0]), vbsvcSharedFolderMappingCompare, NULL); 1940 1941 /* 1942 * Pass #1: Do all the umounting. 1943 * 1944 * By doing the umount pass separately from the mount pass, we can 1945 * better handle changing involving the same mount points (switching 1946 * mount points between two shares, new share on same mount point but 1947 * with lower root ID, ++). 1948 */ 1949 uint32_t iTable = 0; 1950 for (uint32_t iSrc = 0; iSrc < cMappings; iSrc++) 1951 { 1952 /* 1953 * Unmount table entries up to idRootSrc. 1954 */ 1955 uint32_t const idRootSrc = paMappings[iSrc].u32Root; 1956 while ( iTable < pTable->cEntries 1957 && pTable->papEntries[iTable]->idRoot < idRootSrc) 1958 iTable = vbsvcAutomounterUnmountEntry(pTable, iTable, "dropped"); 1959 1960 /* 1961 * If the paMappings entry and the mount table entry has the same 1962 * root ID, umount if anything has changed or if we cannot query 1963 * the mapping data. 1964 */ 1965 if (iTable < pTable->cEntries) 1966 { 1967 PVBSVCAUTOMOUNTERENTRY pEntry = pTable->papEntries[iTable]; 1968 if (pEntry->idRoot == idRootSrc) 1969 { 1970 uint32_t uRootIdVer = UINT32_MAX; 1971 uint64_t fFlags = 0; 1972 char *pszName = NULL; 1973 char *pszMntPt = NULL; 1974 rc = VbglR3SharedFolderQueryFolderInfo(g_idClientSharedFolders, idRootSrc, VBOXSERVICE_AUTOMOUNT_MIQF, 1975 &pszName, &pszMntPt, &fFlags, &uRootIdVer); 1976 if (RT_FAILURE(rc)) 1977 iTable = vbsvcAutomounterUnmountEntry(pTable, iTable, "VbglR3SharedFolderQueryFolderInfo failed"); 1978 else if (pEntry->uRootIdVersion != uRootIdVer) 1979 iTable = vbsvcAutomounterUnmountEntry(pTable, iTable, "root ID version changed"); 1980 else if (RTPathCompare(pEntry->pszMountPoint, pszMntPt) != 0) 1981 iTable = vbsvcAutomounterUnmountEntry(pTable, iTable, "mount point changed"); 1982 else if (RTStrICmp(pEntry->pszName, pszName) != 0) 1983 iTable = vbsvcAutomounterUnmountEntry(pTable, iTable, "name changed"); 1984 else 1985 { 1986 VGSvcVerbose(3, "vbsvcAutomounterRefreshTable: Unchanged: %s -> %s\n", pEntry->pszMountPoint, pEntry->pszName); 1987 iTable++; 1988 } 1989 if (RT_SUCCESS(rc)) 1990 { 1991 RTStrFree(pszName); 1992 RTStrFree(pszMntPt); 1993 } 1994 } 1995 } 1996 } 1997 1998 while (iTable < pTable->cEntries) 1999 iTable = vbsvcAutomounterUnmountEntry(pTable, iTable, "dropped (tail)"); 2000 2001 VGSvcVerbose(4, "vbsvcAutomounterRefreshTable: %u entries in mount table after pass #1.\n", pTable->cEntries); 2002 2003 /* 2004 * Pass #2: Try mount new folders that has mount points assigned. 2005 * Pass #3: Try mount new folders not mounted in pass #2. 2006 */ 2007 for (uint32_t iPass = 2; iPass <= 3; iPass++) 2008 { 2009 iTable = 0; 2010 for (uint32_t iSrc = 0; iSrc < cMappings; iSrc++) 2011 { 2012 uint32_t const idRootSrc = paMappings[iSrc].u32Root; 2013 2014 /* 2015 * Skip tabel entries we couldn't umount in pass #1. 2016 */ 2017 while ( iTable < pTable->cEntries 2018 && pTable->papEntries[iTable]->idRoot < idRootSrc) 2019 { 2020 VGSvcVerbose(4, "vbsvcAutomounterRefreshTable: %u/#%u/%#u: Skipping idRoot=%u %s\n", 2021 iPass, iSrc, iTable, pTable->papEntries[iTable]->idRoot, pTable->papEntries[iTable]->pszName); 2022 iTable++; 2023 } 2024 2025 /* 2026 * New share? 2027 */ 2028 if ( iTable >= pTable->cEntries 2029 || pTable->papEntries[iTable]->idRoot != idRootSrc) 2030 { 2031 uint32_t uRootIdVer = UINT32_MAX; 2032 uint64_t fFlags = 0; 2033 char *pszName = NULL; 2034 char *pszMntPt = NULL; 2035 rc = VbglR3SharedFolderQueryFolderInfo(g_idClientSharedFolders, idRootSrc, VBOXSERVICE_AUTOMOUNT_MIQF, 2036 &pszName, &pszMntPt, &fFlags, &uRootIdVer); 2037 if (RT_SUCCESS(rc)) 2038 { 2039 VGSvcVerbose(4, "vbsvcAutomounterRefreshTable: %u/#%u/%#u: Mounting idRoot=%u/%u %s\n", iPass, iSrc, iTable, 2040 idRootSrc, iTable >= pTable->cEntries ? UINT32_MAX : pTable->papEntries[iTable]->idRoot, pszName); 2041 iTable = vbsvcAutomounterMountNewEntry(pTable, iTable, pszName, pszMntPt, fFlags, 2042 idRootSrc, uRootIdVer, iPass == 3); 2043 2044 RTStrFree(pszName); 2045 RTStrFree(pszMntPt); 2046 } 2047 else 2048 VGSvcVerbose(1, "vbsvcAutomounterRefreshTable: VbglR3SharedFolderQueryFolderInfo failed: %Rrc\n", rc); 2049 } 2050 else 2051 VGSvcVerbose(4, "vbsvcAutomounterRefreshTable: %u/#%u/%#u: idRootSrc=%u vs idRoot=%u %s\n", iPass, iSrc, 2052 iTable, idRootSrc, pTable->papEntries[iTable]->idRoot, pTable->papEntries[iTable]->pszName); 2053 } 2054 } 2055 2056 VbglR3SharedFolderFreeMappings(paMappings); 2057 return true; 2058 } 2059 2060 2061 /** 2062 * @interface_method_impl{VBOXSERVICE,pfnWorker} 2063 */ 2064 static DECLCALLBACK(int) vbsvcAutomounterWorker(bool volatile *pfShutdown) 2065 { 2066 /* 2067 * Tell the control thread that it can continue spawning services. 2068 */ 2069 RTThreadUserSignal(RTThreadSelf()); 2070 2071 /* Divert old hosts to original auto-mount code. */ 2072 if (!g_fHostSupportsWaitAndInfoQuery) 2073 return vbsvcAutoMountWorkerOld(pfShutdown); 2074 2075 /* 2076 * Initialize the state in case we're restarted... 2077 */ 2078 VBSVCAUTOMOUNTERTABLE MountTable = { 0, 0, NULL }; 2079 int rc = vbsvcAutomounterPopulateTable(&MountTable); 2080 if (RT_FAILURE(rc)) 2081 { 2082 VGSvcError("vbsvcAutomounterWorker: vbsvcAutomounterPopulateTable failed (%Rrc), quitting!\n", rc); 2083 return rc; 2084 } 2085 2086 /* 2087 * Work loop. 2088 */ 2089 uint32_t uConfigVer = UINT32_MAX; 2090 uint32_t uNewVersion = 0; 2091 bool fForceRefresh = true; 2092 while (!*pfShutdown) 2093 { 2094 /* 2095 * Update the mounts. 2096 */ 2097 if ( uConfigVer != uNewVersion 2098 || fForceRefresh) 2099 { 2100 fForceRefresh = !vbsvcAutomounterRefreshTable(&MountTable); 2101 uConfigVer = uNewVersion; 2102 } 2103 2104 /* 2105 * Wait for more to do. 2106 */ 2107 if (!*pfShutdown) 2108 { 2109 uNewVersion = uConfigVer - 1; 2110 VGSvcVerbose(2, "vbsvcAutomounterWorker: Waiting with uConfigVer=%u\n", uConfigVer); 2111 rc = VbglR3SharedFolderWaitForMappingsChanges(g_idClientSharedFolders, uConfigVer, &uNewVersion); 2112 VGSvcVerbose(2, "vbsvcAutomounterWorker: Woke up with uNewVersion=%u and rc=%Rrc\n", uNewVersion, rc); 2113 2114 /* Delay a little before doing a table refresh so the GUI can finish 2115 all its updates. Delay a little longer on non-shutdown failure to 2116 avoid eating too many CPU cycles if something goes wrong here... */ 2117 if (!*pfShutdown) 2118 RTSemEventMultiWait(g_hAutoMountEvent, RT_SUCCESS(rc) ? 256 : 1000); 2119 } 2120 } 2121 2122 /* 2123 * Destroy the mount table. 2124 */ 2125 while (MountTable.cEntries-- > 0) 2126 RTMemFree(MountTable.papEntries[MountTable.cEntries]); 2127 MountTable.papEntries = NULL; 2128 2129 VGSvcVerbose(3, "vbsvcAutomounterWorker: Finished\n"); 623 2130 return VINF_SUCCESS; 624 2131 } … … 626 2133 627 2134 /** 2135 * @interface_method_impl{VBOXSERVICE,pfnStop} 2136 */ 2137 static DECLCALLBACK(void) vbsvcAutomounterStop(void) 2138 { 2139 RTSemEventMultiSignal(g_hAutoMountEvent); 2140 if (g_fHostSupportsWaitAndInfoQuery) 2141 VbglR3SharedFolderCancelMappingsChangesWaits(g_idClientSharedFolders); 2142 } 2143 2144 2145 /** 628 2146 * @interface_method_impl{VBOXSERVICE,pfnTerm} 629 2147 */ 630 static DECLCALLBACK(void) vbsvcAuto MountTerm(void)2148 static DECLCALLBACK(void) vbsvcAutomounterTerm(void) 631 2149 { 632 2150 VGSvcVerbose(3, "vbsvcAutoMountTerm\n"); 633 2151 634 VbglR3SharedFolderDisconnect(g_SharedFoldersSvcClientID); 635 g_SharedFoldersSvcClientID = 0; 636 637 if (g_AutoMountEvent != NIL_RTSEMEVENTMULTI) 638 { 639 RTSemEventMultiDestroy(g_AutoMountEvent); 640 g_AutoMountEvent = NIL_RTSEMEVENTMULTI; 641 } 642 return; 643 } 644 645 646 /** 647 * @interface_method_impl{VBOXSERVICE,pfnStop} 648 */ 649 static DECLCALLBACK(void) vbsvcAutoMountStop(void) 650 { 651 RTSemEventMultiSignal(g_AutoMountEvent); 2152 if (g_fHostSupportsWaitAndInfoQuery) 2153 VbglR3SharedFolderCancelMappingsChangesWaits(g_idClientSharedFolders); 2154 2155 VbglR3SharedFolderDisconnect(g_idClientSharedFolders); 2156 g_idClientSharedFolders = 0; 2157 2158 if (g_hAutoMountEvent != NIL_RTSEMEVENTMULTI) 2159 { 2160 RTSemEventMultiDestroy(g_hAutoMountEvent); 2161 g_hAutoMountEvent = NIL_RTSEMEVENTMULTI; 2162 } 652 2163 } 653 2164 … … 661 2172 "automount", 662 2173 /* pszDescription. */ 663 "Auto -mountfor Shared Folders",2174 "Automounter for Shared Folders", 664 2175 /* pszUsage. */ 665 2176 NULL, … … 669 2180 VGSvcDefaultPreInit, 670 2181 VGSvcDefaultOption, 671 vbsvcAuto MountInit,672 vbsvcAuto MountWorker,673 vbsvcAuto MountStop,674 vbsvcAuto MountTerm2182 vbsvcAutomounterInit, 2183 vbsvcAutomounterWorker, 2184 vbsvcAutomounterStop, 2185 vbsvcAutomounterTerm 675 2186 }; 2187 -
trunk/src/VBox/Additions/linux/sharedfolders/vfsmod.c
r72627 r75407 479 479 } 480 480 481 /** @todo Implement show_options (forever) or maybe set s_options (2.6.25+). 482 * Necessary for the automounter tagging. */ 481 483 static struct super_operations sf_super_ops = { 482 484 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) -
trunk/src/VBox/HostServices/SharedFolders/mappings.cpp
r75380 r75407 23 23 #include <iprt/alloc.h> 24 24 #include <iprt/assert.h> 25 #include <iprt/list.h> 25 26 #include <iprt/path.h> 26 27 #include <iprt/string.h> … … 30 31 #endif 31 32 32 /* Shared folders order in the saved state and in the FolderMapping can differ. 33 extern PVBOXHGCMSVCHELPERS g_pHelpers; /* service.cpp */ 34 35 36 /* Shared folders order in the saved state and in the g_FolderMapping can differ. 33 37 * So a translation array of root handle is needed. 34 38 */ 35 39 36 static MAPPING FolderMapping[SHFL_MAX_MAPPINGS]; 37 static SHFLROOT aIndexFromRoot[SHFL_MAX_MAPPINGS]; 40 static MAPPING g_FolderMapping[SHFL_MAX_MAPPINGS]; 41 static SHFLROOT g_aIndexFromRoot[SHFL_MAX_MAPPINGS]; 42 /**< Array running parallel to g_aIndexFromRoot and which entries are increased 43 * as an root handle is added or removed. 44 * 45 * This helps the guest figuring out that a mapping may have been reconfigured 46 * or that saved state has been restored. Entry reuse is very likely given that 47 * vbsfRootHandleAdd() always starts searching at the start for an unused entry. 48 */ 49 static uint32_t g_auRootHandleVersions[SHFL_MAX_MAPPINGS]; 50 /** Version number that is increased for every change made. 51 * This is used by the automount guest service to wait for changes. 52 * @note This does not need saving, the guest should be woken up and refresh 53 * its sate when restored. */ 54 static uint32_t volatile g_uFolderMappingsVersion = 0; 55 56 57 /** For recording async vbsfMappingsWaitForChanges calls. */ 58 typedef struct SHFLMAPPINGSWAIT 59 { 60 RTLISTNODE ListEntry; /**< List entry. */ 61 PSHFLCLIENTDATA pClient; /**< The client that's waiting. */ 62 VBOXHGCMCALLHANDLE hCall; /**< The call handle to signal completion with. */ 63 PVBOXHGCMSVCPARM pParm; /**< The 32-bit unsigned parameter to stuff g_uFolderMappingsVersion into. */ 64 } SHFLMAPPINGSWAIT; 65 /** Pointer to async mappings change wait. */ 66 typedef SHFLMAPPINGSWAIT *PSHFLMAPPINGSWAIT; 67 /** List head for clients waiting on mapping changes (SHFLMAPPINGSWAIT). */ 68 static RTLISTANCHOR g_MappingsChangeWaiters; 69 /** Number of clients waiting on mapping changes. 70 * We use this to limit the number of waiting calls the clients can make. */ 71 static uint32_t g_cMappingChangeWaiters = 0; 72 static void vbsfMappingsWakeupAllWaiters(void); 73 38 74 39 75 void vbsfMappingInit(void) … … 41 77 unsigned root; 42 78 43 for (root = 0; root < RT_ELEMENTS(aIndexFromRoot); root++) 44 { 45 aIndexFromRoot[root] = SHFL_ROOT_NIL; 46 } 47 } 48 49 int vbsfMappingLoaded(const PMAPPING pLoadedMapping, SHFLROOT root) 79 for (root = 0; root < RT_ELEMENTS(g_aIndexFromRoot); root++) 80 { 81 g_aIndexFromRoot[root] = SHFL_ROOT_NIL; 82 } 83 84 RTListInit(&g_MappingsChangeWaiters); 85 } 86 87 int vbsfMappingLoaded(const MAPPING *pLoadedMapping, SHFLROOT root) 50 88 { 51 89 /* Mapping loaded from the saved state with the index. Which means 52 90 * the guest uses the iMapping as root handle for this folder. 53 * Check whether there is the same mapping in FolderMapping and54 * update the aIndexFromRoot.91 * Check whether there is the same mapping in g_FolderMapping and 92 * update the g_aIndexFromRoot. 55 93 * 56 94 * Also update the mapping properties, which were lost: cMappings. … … 62 100 63 101 SHFLROOT i; 64 for (i = 0; i < RT_ELEMENTS( FolderMapping); i++)65 { 66 MAPPING *pMapping = & FolderMapping[i];102 for (i = 0; i < RT_ELEMENTS(g_FolderMapping); i++) 103 { 104 MAPPING *pMapping = &g_FolderMapping[i]; 67 105 68 106 /* Equal? */ … … 71 109 && memcmp(pLoadedMapping->pMapName, pMapping->pMapName, ShflStringSizeOfBuffer(pMapping->pMapName)) == 0) 72 110 { 73 /* Actual index is i. */ 74 aIndexFromRoot[root] = i; 75 76 /* Update the mapping properties. */ 77 pMapping->cMappings = pLoadedMapping->cMappings; 78 79 return VINF_SUCCESS; 111 if (!pMapping->fLoadedRootId) 112 { 113 pMapping->fLoadedRootId = true; 114 Log(("vbsfMappingLoaded: root=%u i=%u (was %u) (%ls)\n", 115 root, i, g_aIndexFromRoot[root], pLoadedMapping->pMapName->String.utf16)); 116 117 /* Actual index is i. */ 118 /** @todo This will not work with global shared folders, as these can change 119 * while state is saved and these blind assignments may hid new ones. */ 120 g_aIndexFromRoot[root] = i; 121 122 /* Update the mapping properties. */ 123 pMapping->cMappings = pLoadedMapping->cMappings; 124 125 return VINF_SUCCESS; 126 } 80 127 } 81 128 } … … 93 140 MAPPING *vbsfMappingGetByRoot(SHFLROOT root) 94 141 { 95 if (root < RT_ELEMENTS( aIndexFromRoot))96 { 97 SHFLROOT iMapping = aIndexFromRoot[root];142 if (root < RT_ELEMENTS(g_aIndexFromRoot)) 143 { 144 SHFLROOT iMapping = g_aIndexFromRoot[root]; 98 145 99 146 if ( iMapping != SHFL_ROOT_NIL 100 && iMapping < RT_ELEMENTS( FolderMapping))101 { 102 return & FolderMapping[iMapping];147 && iMapping < RT_ELEMENTS(g_FolderMapping)) 148 { 149 return &g_FolderMapping[iMapping]; 103 150 } 104 151 } … … 111 158 unsigned root; 112 159 113 for (root = 0; root < RT_ELEMENTS( aIndexFromRoot); root++)114 { 115 if (iMapping == aIndexFromRoot[root])160 for (root = 0; root < RT_ELEMENTS(g_aIndexFromRoot); root++) 161 { 162 if (iMapping == g_aIndexFromRoot[root]) 116 163 { 117 164 return root; … … 122 169 } 123 170 124 static MAPPING *vbsfMappingGetByName (PRTUTF16 pwszName, SHFLROOT *pRoot) 125 { 126 unsigned i; 127 128 for (i=0; i<SHFL_MAX_MAPPINGS; i++) 129 { 130 if (FolderMapping[i].fValid == true) 131 { 132 if (!RTUtf16LocaleICmp(FolderMapping[i].pMapName->String.ucs2, pwszName)) 171 static MAPPING *vbsfMappingGetByName(PRTUTF16 pwszName, SHFLROOT *pRoot) 172 { 173 for (unsigned i = 0; i < SHFL_MAX_MAPPINGS; i++) 174 { 175 if ( g_FolderMapping[i].fValid 176 && !g_FolderMapping[i].fPlaceholder) /* Don't allow mapping placeholders. */ 177 { 178 if (!RTUtf16LocaleICmp(g_FolderMapping[i].pMapName->String.ucs2, pwszName)) 133 179 { 134 180 SHFLROOT root = vbsfMappingGetRootFromIndex(i); … … 140 186 *pRoot = root; 141 187 } 142 return & FolderMapping[i];188 return &g_FolderMapping[i]; 143 189 } 144 else 145 { 146 AssertFailed(); 147 } 190 AssertFailed(); 148 191 } 149 192 } 150 193 } 151 152 194 return NULL; 153 195 } … … 157 199 unsigned root; 158 200 159 for (root = 0; root < RT_ELEMENTS(aIndexFromRoot); root++) 160 { 161 if (aIndexFromRoot[root] == SHFL_ROOT_NIL) 162 { 163 aIndexFromRoot[root] = iMapping; 201 for (root = 0; root < RT_ELEMENTS(g_aIndexFromRoot); root++) 202 { 203 if (g_aIndexFromRoot[root] == SHFL_ROOT_NIL) 204 { 205 g_aIndexFromRoot[root] = iMapping; 206 g_auRootHandleVersions[root] += 1; 164 207 return; 165 208 } … … 173 216 unsigned root; 174 217 175 for (root = 0; root < RT_ELEMENTS(aIndexFromRoot); root++) 176 { 177 if (aIndexFromRoot[root] == iMapping) 178 { 179 aIndexFromRoot[root] = SHFL_ROOT_NIL; 180 return; 218 for (root = 0; root < RT_ELEMENTS(g_aIndexFromRoot); root++) 219 { 220 if (g_aIndexFromRoot[root] == iMapping) 221 { 222 g_aIndexFromRoot[root] = SHFL_ROOT_NIL; 223 g_auRootHandleVersions[root] += 1; 224 Log(("vbsfRootHandleRemove: Removed root=%u (iMapping=%u)\n", root, iMapping)); 225 226 /* Note! Do not stop here as g_aIndexFromRoot may (at least it could 227 prior to the introduction of fLoadedRootId) contain 228 duplicates after restoring save state. */ 181 229 } 182 230 } … … 209 257 Log(("vbsfMappingsAdd %ls\n", pMapName->String.ucs2)); 210 258 211 /* check for duplicates */ 212 for (i=0; i<SHFL_MAX_MAPPINGS; i++) 213 { 214 if (FolderMapping[i].fValid == true) 215 { 216 if (!RTUtf16LocaleICmp(FolderMapping[i].pMapName->String.ucs2, pMapName->String.ucs2)) 259 /* Check for duplicates, ignoring placeholders to give the GUI to change stuff at runtime. */ 260 /** @todo bird: Not entirely sure about ignoring placeholders, but you cannot 261 * trigger auto-umounting without ignoring them. */ 262 if (!fPlaceholder) 263 { 264 for (i = 0; i < SHFL_MAX_MAPPINGS; i++) 265 { 266 if ( g_FolderMapping[i].fValid 267 && !g_FolderMapping[i].fPlaceholder) 217 268 { 218 AssertMsgFailed(("vbsfMappingsAdd: %ls mapping already exists!!\n", pMapName->String.ucs2)); 219 return VERR_ALREADY_EXISTS; 269 if (!RTUtf16LocaleICmp(g_FolderMapping[i].pMapName->String.ucs2, pMapName->String.ucs2)) 270 { 271 AssertMsgFailed(("vbsfMappingsAdd: %ls mapping already exists!!\n", pMapName->String.ucs2)); 272 return VERR_ALREADY_EXISTS; 273 } 220 274 } 221 275 } 222 276 } 223 277 224 for (i =0; i<SHFL_MAX_MAPPINGS; i++)225 { 226 if ( FolderMapping[i].fValid == false)278 for (i = 0; i < SHFL_MAX_MAPPINGS; i++) 279 { 280 if (g_FolderMapping[i].fValid == false) 227 281 { 228 282 /* Make sure the folder name is an absolute path, otherwise we're … … 232 286 AssertRCReturn(rc, rc); 233 287 234 FolderMapping[i].pszFolderName = RTStrDup(szAbsFolderName);235 FolderMapping[i].pMapName = ShflStringDup(pMapName);236 FolderMapping[i].pAutoMountPoint = ShflStringDup(pAutoMountPoint);237 if ( ! FolderMapping[i].pszFolderName238 || ! FolderMapping[i].pMapName239 || ! FolderMapping[i].pAutoMountPoint)288 g_FolderMapping[i].pszFolderName = RTStrDup(szAbsFolderName); 289 g_FolderMapping[i].pMapName = ShflStringDup(pMapName); 290 g_FolderMapping[i].pAutoMountPoint = ShflStringDup(pAutoMountPoint); 291 if ( !g_FolderMapping[i].pszFolderName 292 || !g_FolderMapping[i].pMapName 293 || !g_FolderMapping[i].pAutoMountPoint) 240 294 { 241 RTStrFree( FolderMapping[i].pszFolderName);242 RTMemFree( FolderMapping[i].pMapName);243 RTMemFree( FolderMapping[i].pAutoMountPoint);295 RTStrFree(g_FolderMapping[i].pszFolderName); 296 RTMemFree(g_FolderMapping[i].pMapName); 297 RTMemFree(g_FolderMapping[i].pAutoMountPoint); 244 298 return VERR_NO_MEMORY; 245 299 } 246 300 247 FolderMapping[i].fValid = true; 248 FolderMapping[i].cMappings = 0; 249 FolderMapping[i].fWritable = fWritable; 250 FolderMapping[i].fAutoMount = fAutoMount; 251 FolderMapping[i].fSymlinksCreate = fSymlinksCreate; 252 FolderMapping[i].fMissing = fMissing; 253 FolderMapping[i].fPlaceholder = fPlaceholder; 301 g_FolderMapping[i].fValid = true; 302 g_FolderMapping[i].cMappings = 0; 303 g_FolderMapping[i].fWritable = fWritable; 304 g_FolderMapping[i].fAutoMount = fAutoMount; 305 g_FolderMapping[i].fSymlinksCreate = fSymlinksCreate; 306 g_FolderMapping[i].fMissing = fMissing; 307 g_FolderMapping[i].fPlaceholder = fPlaceholder; 308 g_FolderMapping[i].fLoadedRootId = false; 254 309 255 310 /* Check if the host file system is case sensitive */ 256 311 RTFSPROPERTIES prop; 257 312 prop.fCaseSensitive = false; /* Shut up MSC. */ 258 rc = RTFsQueryProperties( FolderMapping[i].pszFolderName, &prop);313 rc = RTFsQueryProperties(g_FolderMapping[i].pszFolderName, &prop); 259 314 AssertRC(rc); 260 FolderMapping[i].fHostCaseSensitive = RT_SUCCESS(rc) ? prop.fCaseSensitive : false;315 g_FolderMapping[i].fHostCaseSensitive = RT_SUCCESS(rc) ? prop.fCaseSensitive : false; 261 316 vbsfRootHandleAdd(i); 317 vbsfMappingsWakeupAllWaiters(); 262 318 break; 263 319 } … … 269 325 } 270 326 271 Log(("vbsfMappingsAdd: added mapping %s to %ls\n", pszFolderName, pMapName->String.ucs2)); 327 Log(("vbsfMappingsAdd: added mapping %s to %ls (slot %u, root %u)\n", 328 pszFolderName, pMapName->String.ucs2, i, vbsfMappingGetRootFromIndex(i))); 272 329 return VINF_SUCCESS; 273 330 } … … 285 342 int vbsfMappingsRemove(PSHFLSTRING pMapName) 286 343 { 287 unsigned i;288 289 344 Assert(pMapName); 290 291 345 Log(("vbsfMappingsRemove %ls\n", pMapName->String.ucs2)); 292 for (i=0; i<SHFL_MAX_MAPPINGS; i++) 293 { 294 if (FolderMapping[i].fValid == true) 295 { 296 if (!RTUtf16LocaleICmp(FolderMapping[i].pMapName->String.ucs2, pMapName->String.ucs2)) 346 347 /* 348 * We must iterate thru the whole table as may have 0+ placeholder entries 349 * and 0-1 regular entries with the same name. Also, it is good to kick 350 * the guest automounter into action wrt to evicting placeholders. 351 */ 352 int rc = VERR_FILE_NOT_FOUND; 353 for (unsigned i = 0; i < SHFL_MAX_MAPPINGS; i++) 354 { 355 if (g_FolderMapping[i].fValid == true) 356 { 357 if (!RTUtf16LocaleICmp(g_FolderMapping[i].pMapName->String.ucs2, pMapName->String.ucs2)) 297 358 { 298 if ( FolderMapping[i].cMappings != 0)359 if (g_FolderMapping[i].cMappings != 0) 299 360 { 300 LogRel2(("SharedFolders: removing '%ls' -> '%s', which is still used by the guest\n", 301 pMapName->String.ucs2, FolderMapping[i].pszFolderName)); 302 FolderMapping[i].fMissing = true; 303 FolderMapping[i].fPlaceholder = true; 304 return VINF_PERMISSION_DENIED; 361 LogRel2(("SharedFolders: removing '%ls' -> '%s'%s, which is still used by the guest\n", pMapName->String.ucs2, 362 g_FolderMapping[i].pszFolderName, g_FolderMapping[i].fPlaceholder ? " (again)" : "")); 363 g_FolderMapping[i].fMissing = true; 364 g_FolderMapping[i].fPlaceholder = true; 365 vbsfMappingsWakeupAllWaiters(); 366 rc = VINF_PERMISSION_DENIED; 305 367 } 306 307 /* pMapName can be the same as FolderMapping[i].pMapName, 308 * log it before deallocating the memory. 309 */ 310 Log(("vbsfMappingsRemove: mapping %ls removed\n", pMapName->String.ucs2)); 311 312 RTStrFree(FolderMapping[i].pszFolderName); 313 RTMemFree(FolderMapping[i].pMapName); 314 FolderMapping[i].pszFolderName = NULL; 315 FolderMapping[i].pMapName = NULL; 316 FolderMapping[i].fValid = false; 317 vbsfRootHandleRemove(i); 318 return VINF_SUCCESS; 368 else 369 { 370 /* pMapName can be the same as g_FolderMapping[i].pMapName when 371 * called from vbsfUnmapFolder, log it before deallocating the memory. */ 372 Log(("vbsfMappingsRemove: mapping %ls removed\n", pMapName->String.ucs2)); 373 bool fSame = g_FolderMapping[i].pMapName == pMapName; 374 375 RTStrFree(g_FolderMapping[i].pszFolderName); 376 RTMemFree(g_FolderMapping[i].pMapName); 377 g_FolderMapping[i].pszFolderName = NULL; 378 g_FolderMapping[i].pMapName = NULL; 379 g_FolderMapping[i].fValid = false; 380 vbsfRootHandleRemove(i); 381 vbsfMappingsWakeupAllWaiters(); 382 if (rc == VERR_FILE_NOT_FOUND) 383 rc = VINF_SUCCESS; 384 if (fSame) 385 break; 386 } 319 387 } 320 388 } 321 389 } 322 390 323 AssertMsgFailed(("vbsfMappingsRemove: mapping %ls not found!!!!\n", pMapName->String.ucs2)); 324 return VERR_FILE_NOT_FOUND; 391 return rc; 325 392 } 326 393 … … 378 445 #endif 379 446 /** 380 * Note: If pMappings / *pcMappings is smaller than the actual amount of mappings 381 * that *could* have been returned *pcMappings contains the required buffer size 382 * so that the caller can retry the operation if wanted. 383 */ 384 int vbsfMappingsQuery(PSHFLCLIENTDATA pClient, PSHFLMAPPING pMappings, uint32_t *pcMappings) 385 { 386 int rc = VINF_SUCCESS; 387 388 uint32_t cMappings = 0; /* Will contain actual valid mappings. */ 389 uint32_t idx = 0; /* Current index in mappings buffer. */ 390 447 * @note If pMappings / *pcMappings is smaller than the actual amount of 448 * mappings that *could* have been returned *pcMappings contains the 449 * required buffer size so that the caller can retry the operation if 450 * wanted. 451 */ 452 int vbsfMappingsQuery(PSHFLCLIENTDATA pClient, bool fOnlyAutoMounts, PSHFLMAPPING pMappings, uint32_t *pcMappings) 453 { 391 454 LogFlow(("vbsfMappingsQuery: pClient = %p, pMappings = %p, pcMappings = %p, *pcMappings = %d\n", 392 455 pClient, pMappings, pcMappings, *pcMappings)); 393 456 457 uint32_t const cMaxMappings = *pcMappings; 458 uint32_t idx = 0; 394 459 for (uint32_t i = 0; i < SHFL_MAX_MAPPINGS; i++) 395 460 { 396 461 MAPPING *pFolderMapping = vbsfMappingGetByRoot(i); 397 462 if ( pFolderMapping != NULL 398 && pFolderMapping->fValid == true) 399 { 400 if (idx < *pcMappings) 463 && pFolderMapping->fValid 464 && ( !fOnlyAutoMounts 465 || (pFolderMapping->fAutoMount && !pFolderMapping->fPlaceholder)) ) 466 { 467 if (idx < cMaxMappings) 401 468 { 402 /* Skip mappings which are not marked for auto-mounting if403 * the SHFL_MF_AUTOMOUNT flag ist set. */404 if ( (pClient->fu32Flags & SHFL_MF_AUTOMOUNT)405 && !pFolderMapping->fAutoMount)406 continue;407 408 469 pMappings[idx].u32Status = SHFL_MS_NEW; 409 pMappings[idx].root = i; 410 idx++; 470 pMappings[idx].root = i; 411 471 } 412 cMappings++;472 idx++; 413 473 } 414 474 } … … 416 476 /* Return actual number of mappings, regardless whether the handed in 417 477 * mapping buffer was big enough. */ 418 *pcMappings = cMappings; 419 420 LogFlow(("vbsfMappingsQuery: return rc = %Rrc\n", rc)); 421 return rc; 478 /** @todo r=bird: This is non-standard interface behaviour. We return 479 * VERR_BUFFER_OVERFLOW or at least a VINF_BUFFER_OVERFLOW here. 480 * 481 * Guess this goes well along with ORing SHFL_MF_AUTOMOUNT into 482 * pClient->fu32Flags rather than passing it as fOnlyAutoMounts... 483 * Not amused by this. */ 484 *pcMappings = idx; 485 486 LogFlow(("vbsfMappingsQuery: returns VINF_SUCCESS (idx=%u, cMaxMappings=%u)\n", idx, cMaxMappings)); 487 return VINF_SUCCESS; 422 488 } 423 489 … … 437 503 int vbsfMappingsQueryName(PSHFLCLIENTDATA pClient, SHFLROOT root, SHFLSTRING *pString) 438 504 { 439 int rc = VINF_SUCCESS; 440 441 LogFlow(("vbsfMappingsQuery: pClient = %p, root = %d, *pString = %p\n", 442 pClient, root, pString)); 443 505 LogFlow(("vbsfMappingsQuery: pClient = %p, root = %d, *pString = %p\n", pClient, root, pString)); 506 507 int rc; 444 508 MAPPING *pFolderMapping = vbsfMappingGetByRoot(root); 445 if (pFolderMapping == NULL) 446 { 447 return VERR_INVALID_PARAMETER; 448 } 449 450 if (BIT_FLAG(pClient->fu32Flags, SHFL_CF_UTF8)) 451 { 452 /* Not implemented. */ 453 AssertFailed(); 454 return VERR_INVALID_PARAMETER; 455 } 456 457 if (pFolderMapping->fValid == true) 458 { 459 if (pString->u16Size < pFolderMapping->pMapName->u16Size) 460 { 461 Log(("vbsfMappingsQuery: passed string too short (%d < %d bytes)!\n", 462 pString->u16Size, pFolderMapping->pMapName->u16Size)); 463 rc = VERR_INVALID_PARAMETER; 509 if (pFolderMapping) 510 { 511 if (pFolderMapping->fValid) 512 { 513 if (BIT_FLAG(pClient->fu32Flags, SHFL_CF_UTF8)) 514 rc = ShflStringCopyUtf16BufAsUtf8(pString, pFolderMapping->pMapName); 515 else 516 { 517 /* Not using ShlfStringCopy here as behaviour shouldn't change... */ 518 if (pString->u16Size < pFolderMapping->pMapName->u16Size) 519 { 520 Log(("vbsfMappingsQuery: passed string too short (%d < %d bytes)!\n", 521 pString->u16Size, pFolderMapping->pMapName->u16Size)); 522 rc = VERR_INVALID_PARAMETER; 523 } 524 else 525 { 526 pString->u16Length = pFolderMapping->pMapName->u16Length; 527 memcpy(pString->String.ucs2, pFolderMapping->pMapName->String.ucs2, 528 pFolderMapping->pMapName->u16Size); 529 rc = VINF_SUCCESS; 530 } 531 } 464 532 } 465 533 else 466 { 467 pString->u16Length = pFolderMapping->pMapName->u16Length; 468 memcpy(pString->String.ucs2, pFolderMapping->pMapName->String.ucs2, 469 pFolderMapping->pMapName->u16Size); 470 } 534 rc = VERR_FILE_NOT_FOUND; 471 535 } 472 536 else 473 rc = VERR_ FILE_NOT_FOUND;537 rc = VERR_INVALID_PARAMETER; 474 538 475 539 LogFlow(("vbsfMappingsQuery:Name return rc = %Rrc\n", rc)); 476 477 540 return rc; 478 541 } … … 540 603 return rc; 541 604 } 605 606 /** 607 * Implements SHFL_FN_QUERY_MAP_INFO. 608 * @since VBox 6.0 609 */ 610 int vbsfMappingsQueryInfo(PSHFLCLIENTDATA pClient, SHFLROOT root, PSHFLSTRING pNameBuf, PSHFLSTRING pMntPtBuf, 611 uint64_t *pfFlags, uint32_t *puVersion) 612 { 613 LogFlow(("vbsfMappingsQueryInfo: pClient=%p root=%d\n", pClient, root)); 614 615 /* Resolve the root handle. */ 616 int rc; 617 PMAPPING pFolderMapping = vbsfMappingGetByRoot(root); 618 if (pFolderMapping) 619 { 620 if (pFolderMapping->fValid) 621 { 622 /* 623 * Produce the output. 624 */ 625 *puVersion = g_auRootHandleVersions[root]; 626 627 *pfFlags = 0; 628 if (pFolderMapping->fWritable) 629 *pfFlags |= SHFL_MIF_WRITABLE; 630 if (pFolderMapping->fAutoMount) 631 *pfFlags |= SHFL_MIF_AUTO_MOUNT; 632 if (pFolderMapping->fHostCaseSensitive) 633 *pfFlags |= SHFL_MIF_HOST_ICASE; 634 if (pFolderMapping->fGuestCaseSensitive) 635 *pfFlags |= SHFL_MIF_GUEST_ICASE; 636 if (pFolderMapping->fSymlinksCreate) 637 *pfFlags |= SHFL_MIF_SYMLINK_CREATION; 638 639 int rc2; 640 if (pClient->fu32Flags & SHFL_CF_UTF8) 641 { 642 rc = ShflStringCopyUtf16BufAsUtf8(pNameBuf, pFolderMapping->pMapName); 643 rc2 = ShflStringCopyUtf16BufAsUtf8(pMntPtBuf, pFolderMapping->pAutoMountPoint); 644 } 645 else 646 { 647 rc = ShflStringCopy(pNameBuf, pFolderMapping->pMapName, sizeof(RTUTF16)); 648 rc2 = ShflStringCopy(pMntPtBuf, pFolderMapping->pAutoMountPoint, sizeof(RTUTF16)); 649 } 650 if (RT_SUCCESS(rc)) 651 rc = rc2; 652 } 653 else 654 rc = VERR_FILE_NOT_FOUND; 655 } 656 else 657 rc = VERR_INVALID_PARAMETER; 658 LogFlow(("vbsfMappingsQueryInfo: returns %Rrc\n", rc)); 659 return rc; 660 } 661 662 542 663 543 664 #ifdef UNITTEST … … 662 783 return rc; 663 784 } 785 786 /** 787 * SHFL_FN_WAIT_FOR_MAPPINGS_CHANGES implementation. 788 * 789 * @returns VBox status code. 790 * @retval VINF_SUCCESS on change. 791 * @retval VINF_TRY_AGAIN on resume. 792 * @retval VINF_HGCM_ASYNC_EXECUTE if waiting. 793 * @retval VERR_CANCELLED if cancelled. 794 * @retval VERR_OUT_OF_RESOURCES if there are too many pending waits. 795 * 796 * @param pClient The calling client. 797 * @param hCall The call handle. 798 * @param pParm The parameter (32-bit). 799 * @param fRestored Set if this is a call restored & resubmitted from saved 800 * state. 801 * @since VBox 6.0 802 */ 803 int vbsfMappingsWaitForChanges(PSHFLCLIENTDATA pClient, VBOXHGCMCALLHANDLE hCall, PVBOXHGCMSVCPARM pParm, bool fRestored) 804 { 805 /* 806 * Return immediately if the fodler mappings have changed since last call 807 * or if we got restored from saved state (adding of global folders, etc). 808 */ 809 uint32_t uCurVersion = g_uFolderMappingsVersion; 810 if ( pParm->u.uint32 != uCurVersion 811 || fRestored 812 || (pClient->fu32Flags & SHFL_CF_CANCEL_NEXT_WAIT) ) 813 { 814 int rc = VINF_SUCCESS; 815 if (pClient->fu32Flags & SHFL_CF_CANCEL_NEXT_WAIT) 816 { 817 pClient->fu32Flags &= ~SHFL_CF_CANCEL_NEXT_WAIT; 818 rc = VERR_CANCELLED; 819 } 820 else if (fRestored) 821 { 822 rc = VINF_TRY_AGAIN; 823 if (pParm->u.uint32 == uCurVersion) 824 uCurVersion = uCurVersion != UINT32_C(0x55555555) ? UINT32_C(0x55555555) : UINT32_C(0x99999999); 825 } 826 Log(("vbsfMappingsWaitForChanges: Version %#x -> %#x, returning %Rrc immediately.\n", pParm->u.uint32, uCurVersion, rc)); 827 pParm->u.uint32 = uCurVersion; 828 return rc; 829 } 830 831 /* 832 * Setup a wait if we can. 833 */ 834 if (g_cMappingChangeWaiters < 64) 835 { 836 PSHFLMAPPINGSWAIT pWait = (PSHFLMAPPINGSWAIT)RTMemAlloc(sizeof(*pWait)); 837 if (pWait) 838 { 839 pWait->pClient = pClient; 840 pWait->hCall = hCall; 841 pWait->pParm = pParm; 842 843 RTListAppend(&g_MappingsChangeWaiters, &pWait->ListEntry); 844 g_cMappingChangeWaiters += 1; 845 return VINF_HGCM_ASYNC_EXECUTE; 846 } 847 return VERR_NO_MEMORY; 848 } 849 LogRelMax(32, ("vbsfMappingsWaitForChanges: Too many threads waiting for changes!\n")); 850 return VERR_OUT_OF_RESOURCES; 851 } 852 853 /** 854 * SHFL_FN_CANCEL_MAPPINGS_CHANGES_WAITS implementation. 855 * 856 * @returns VINF_SUCCESS 857 * @param pClient The calling client to cancel all waits for. 858 * @since VBox 6.0 859 */ 860 int vbsfMappingsCancelChangesWaits(PSHFLCLIENTDATA pClient) 861 { 862 uint32_t const uCurVersion = g_uFolderMappingsVersion; 863 864 PSHFLMAPPINGSWAIT pCur, pNext; 865 RTListForEachSafe(&g_MappingsChangeWaiters, pCur, pNext, SHFLMAPPINGSWAIT, ListEntry) 866 { 867 if (pCur->pClient == pClient) 868 { 869 RTListNodeRemove(&pCur->ListEntry); 870 pCur->pParm->u.uint32 = uCurVersion; 871 g_pHelpers->pfnCallComplete(pCur->hCall, VERR_CANCELLED); 872 RTMemFree(pCur); 873 } 874 } 875 876 /* Set a flag to make sure the next SHFL_FN_WAIT_FOR_MAPPINGS_CHANGES doesn't block. 877 This should help deal with races between this call and a thread about to do a wait. */ 878 pClient->fu32Flags |= SHFL_CF_CANCEL_NEXT_WAIT; 879 880 return VINF_SUCCESS; 881 } 882 883 /** 884 * Wakes up all clients waiting on 885 */ 886 static void vbsfMappingsWakeupAllWaiters(void) 887 { 888 uint32_t const uCurVersion = ++g_uFolderMappingsVersion; 889 890 PSHFLMAPPINGSWAIT pCur, pNext; 891 RTListForEachSafe(&g_MappingsChangeWaiters, pCur, pNext, SHFLMAPPINGSWAIT, ListEntry) 892 { 893 RTListNodeRemove(&pCur->ListEntry); 894 pCur->pParm->u.uint32 = uCurVersion; 895 g_pHelpers->pfnCallComplete(pCur->hCall, VERR_CANCELLED); 896 RTMemFree(pCur); 897 } 898 } 899 -
trunk/src/VBox/HostServices/SharedFolders/mappings.h
r75380 r75407 38 38 bool fPlaceholder; /**< Mapping does not exist in the VM settings but the guest 39 39 still has. fMissing is always true for this mapping. */ 40 bool fLoadedRootId; /**< Set if vbsfMappingLoaded has found this mapping already. */ 40 41 } MAPPING; 41 42 /** Pointer to a MAPPING structure. */ … … 50 51 int vbsfMappingsRemove(PSHFLSTRING pMapName); 51 52 52 int vbsfMappingsQuery(PSHFLCLIENTDATA pClient, PSHFLMAPPING pMappings, uint32_t *pcMappings);53 int vbsfMappingsQuery(PSHFLCLIENTDATA pClient, bool fOnlyAutoMounts, PSHFLMAPPING pMappings, uint32_t *pcMappings); 53 54 int vbsfMappingsQueryName(PSHFLCLIENTDATA pClient, SHFLROOT root, SHFLSTRING *pString); 54 55 int vbsfMappingsQueryWritable(PSHFLCLIENTDATA pClient, SHFLROOT root, bool *fWritable); 55 56 int vbsfMappingsQueryAutoMount(PSHFLCLIENTDATA pClient, SHFLROOT root, bool *fAutoMount); 56 57 int vbsfMappingsQuerySymlinksCreate(PSHFLCLIENTDATA pClient, SHFLROOT root, bool *fSymlinksCreate); 58 int vbsfMappingsQueryInfo(PSHFLCLIENTDATA pClient, SHFLROOT root, PSHFLSTRING pNameBuf, PSHFLSTRING pMntPtBuf, 59 uint64_t *pfFlags, uint32_t *puVersion); 57 60 58 61 int vbsfMapFolder(PSHFLCLIENTDATA pClient, PSHFLSTRING pszMapName, RTUTF16 delimiter, 59 62 bool fCaseSensitive, SHFLROOT *pRoot); 60 63 int vbsfUnmapFolder(PSHFLCLIENTDATA pClient, SHFLROOT root); 64 65 int vbsfMappingsWaitForChanges(PSHFLCLIENTDATA pClient, VBOXHGCMCALLHANDLE hCall, PVBOXHGCMSVCPARM pParm, bool fRestored); 66 int vbsfMappingsCancelChangesWaits(PSHFLCLIENTDATA pClient); 61 67 62 68 const char* vbsfMappingsQueryHostRoot(SHFLROOT root); … … 65 71 bool vbsfIsHostMappingCaseSensitive(SHFLROOT root); 66 72 67 int vbsfMappingLoaded( const PMAPPINGpLoadedMapping, SHFLROOT root);73 int vbsfMappingLoaded(MAPPING const *pLoadedMapping, SHFLROOT root); 68 74 PMAPPING vbsfMappingGetByRoot(SHFLROOT root); 69 75 -
trunk/src/VBox/HostServices/SharedFolders/service.cpp
r75380 r75407 26 26 #include <iprt/string.h> 27 27 #include <iprt/assert.h> 28 #include <VBox/AssertGuest.h> 28 29 #include <VBox/vmm/ssm.h> 29 30 #include <VBox/vmm/pdmifs.h> … … 237 238 rc = SSMR3GetMem(pSSM, pFolderName, cb); 238 239 AssertRCReturn(rc, rc); 239 AssertReturn(pFolderName->u16 Length < cb && pFolderName->u16Size < pFolderName->u16Length,240 AssertReturn(pFolderName->u16Size < cb && pFolderName->u16Length < pFolderName->u16Size, 240 241 SSMR3SetLoadError(pSSM, VERR_SSM_DATA_UNIT_FORMAT_CHANGED, RT_SRC_POS, 241 242 "Bad folder name string: %#x/%#x cb=%#x\n", … … 267 268 rc = SSMR3GetMem(pSSM, pMapName, cb); 268 269 AssertRCReturn(rc, rc); 269 AssertReturn(pMapName->u16 Length < cb && pMapName->u16Size < pMapName->u16Length,270 AssertReturn(pMapName->u16Size < cb && pMapName->u16Length < pMapName->u16Size, 270 271 SSMR3SetLoadError(pSSM, VERR_SSM_DATA_UNIT_FORMAT_CHANGED, RT_SRC_POS, 271 272 "Bad map name string: %#x/%#x cb=%#x\n", … … 293 294 rc = SSMR3GetMem(pSSM, pAutoMountPoint, cb); 294 295 AssertRCReturn(rc, rc); 295 AssertReturn(pAutoMountPoint->u16 Length < cb && pAutoMountPoint->u16Size < pAutoMountPoint->u16Length,296 AssertReturn(pAutoMountPoint->u16Size < cb && pAutoMountPoint->u16Length < pAutoMountPoint->u16Size, 296 297 SSMR3SetLoadError(pSSM, VERR_SSM_DATA_UNIT_FORMAT_CHANGED, RT_SRC_POS, 297 298 "Bad auto mount point string: %#x/%#x cb=%#x\n", … … 331 332 } 332 333 333 static DECLCALLBACK(void) svcCall (void *, VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID, void *pvClient, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 334 static DECLCALLBACK(void) svcCall (void *, VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID, 335 void *pvClient, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 334 336 { 335 337 RT_NOREF1(u32ClientID); … … 388 390 if (fu32Flags & SHFL_MF_UTF8) 389 391 pClient->fu32Flags |= SHFL_CF_UTF8; 390 if (fu32Flags & SHFL_MF_AUTOMOUNT) 391 pClient->fu32Flags |= SHFL_MF_AUTOMOUNT; 392 393 rc = vbsfMappingsQuery(pClient, pMappings, &cMappings); 392 /// @todo r=bird: Someone please explain this amusing code (r63916): 393 //if (fu32Flags & SHFL_MF_AUTOMOUNT) 394 // pClient->fu32Flags |= SHFL_MF_AUTOMOUNT; 395 // 396 //rc = vbsfMappingsQuery(pClient, pMappings, &cMappings); 397 398 rc = vbsfMappingsQuery(pClient, RT_BOOL(fu32Flags & SHFL_MF_AUTOMOUNT), pMappings, &cMappings); 394 399 if (RT_SUCCESS(rc)) 395 400 { … … 1295 1300 } 1296 1301 1302 case SHFL_FN_QUERY_MAP_INFO: 1303 { 1304 Log(("SharedFolders host service: svnCall: SHFL_FN_QUERY_MAP_INFO\n")); 1305 1306 /* Validate input: */ 1307 rc = VERR_INVALID_PARAMETER; 1308 ASSERT_GUEST_BREAK(cParms == SHFL_CPARMS_QUERY_MAP_INFO); 1309 ASSERT_GUEST_BREAK(paParms[0].type == VBOX_HGCM_SVC_PARM_32BIT); /* root */ 1310 ASSERT_GUEST_BREAK(paParms[1].type == VBOX_HGCM_SVC_PARM_PTR); /* name */ 1311 PSHFLSTRING pNameBuf = (PSHFLSTRING)paParms[1].u.pointer.addr; 1312 ASSERT_GUEST_BREAK(ShflStringIsValidOut(pNameBuf, paParms[1].u.pointer.size)); 1313 ASSERT_GUEST_BREAK(paParms[2].type == VBOX_HGCM_SVC_PARM_PTR); /* mountPoint */ 1314 PSHFLSTRING pMntPtBuf = (PSHFLSTRING)paParms[2].u.pointer.addr; 1315 ASSERT_GUEST_BREAK(ShflStringIsValidOut(pMntPtBuf, paParms[2].u.pointer.size)); 1316 ASSERT_GUEST_BREAK(paParms[3].type == VBOX_HGCM_SVC_PARM_64BIT); /* flags */ 1317 ASSERT_GUEST_BREAK(!(paParms[3].u.uint64 & ~(SHFL_MIQF_DRIVE_LETTER | SHFL_MIQF_PATH))); /* flags */ 1318 ASSERT_GUEST_BREAK(paParms[4].type == VBOX_HGCM_SVC_PARM_32BIT); /* version */ 1319 1320 /* Execute the function: */ 1321 rc = vbsfMappingsQueryInfo(pClient, paParms[0].u.uint32, pNameBuf, pMntPtBuf, 1322 &paParms[3].u.uint64, &paParms[4].u.uint32); 1323 break; 1324 } 1325 1326 case SHFL_FN_WAIT_FOR_MAPPINGS_CHANGES: 1327 { 1328 Log(("SharedFolders host service: svnCall: SHFL_FN_WAIT_FOR_CHANGES\n")); 1329 1330 /* Validate input: */ 1331 rc = VERR_INVALID_PARAMETER; 1332 ASSERT_GUEST_BREAK(cParms == SHFL_CPARMS_WAIT_FOR_MAPPINGS_CHANGES); 1333 ASSERT_GUEST_BREAK(paParms[0].type == VBOX_HGCM_SVC_PARM_32BIT); /* uFolderMappingsVersion */ 1334 1335 /* Execute the function: */ 1336 rc = vbsfMappingsWaitForChanges(pClient, callHandle, paParms, g_pHelpers->pfnIsCallRestored(callHandle)); 1337 fAsynchronousProcessing = rc == VINF_HGCM_ASYNC_EXECUTE; 1338 break; 1339 } 1340 1341 case SHFL_FN_CANCEL_MAPPINGS_CHANGES_WAITS: 1342 { 1343 Log(("SharedFolders host service: svnCall: SHFL_FN_CANCEL_WAIT_FOR_CHANGES\n")); 1344 1345 /* Validate input: */ 1346 rc = VERR_INVALID_PARAMETER; 1347 ASSERT_GUEST_BREAK(cParms == SHFL_CPARMS_CANCEL_MAPPINGS_CHANGES_WAITS); 1348 1349 /* Execute the function: */ 1350 rc = vbsfMappingsCancelChangesWaits(pClient); 1351 break; 1352 } 1353 1297 1354 default: 1298 1355 { -
trunk/src/VBox/HostServices/SharedFolders/shfl.h
r69500 r75407 43 43 #define SHFL_CF_SYMLINKS (0x00000008) 44 44 45 /** The call to SHFL_FN_WAIT_FOR_MAPPINGS_CHANGES will return immediately 46 * because of a SHFL_FN_CANCEL_MAPPINGS_CHANGES_WAITS call. */ 47 #define SHFL_CF_CANCEL_NEXT_WAIT (0x00000010) 48 45 49 /** @} */ 46 50 -
trunk/src/VBox/HostServices/SharedFolders/vbsf.h
r69500 r75407 1 /* $Id$ */ 1 2 /** @file 2 3 * VBox Shared Folders header. … … 15 16 */ 16 17 17 #ifndef __ VBSF__H18 #define __ VBSF__H18 #ifndef ___vbsf_h___ 19 #define ___vbsf_h___ 19 20 20 21 #include "shfl.h" … … 41 42 int vbsfSymlink(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLSTRING *pNewPath, SHFLSTRING *pOldPath, SHFLFSOBJINFO *pInfo); 42 43 43 #endif /* __VBSF__H */ 44 #endif /* !___vbsf_h___ */ 45
Note:
See TracChangeset
for help on using the changeset viewer.

