VirtualBox

Ignore:
Timestamp:
Jul 17, 2015 9:43:26 AM (9 years ago)
Author:
vboxsync
Message:

HostServices/SharedFolders: enable guest to host path conversion

Location:
trunk/src/VBox/HostServices/SharedFolders
Files:
1 added
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostServices/SharedFolders/Makefile.kmk

    r56301 r56962  
    4141        shflhandle.cpp \
    4242        vbsf.cpp \
     43        vbsfpath.cpp \
    4344        mappings.cpp
    4445VBoxSharedFolders_SOURCES.win = \
  • trunk/src/VBox/HostServices/SharedFolders/mappings.cpp

    r51250 r56962  
    322322        return NULL;
    323323    return pFolderMapping->pszFolderName;
     324}
     325
     326int vbsfMappingsQueryHostRootEx(SHFLROOT hRoot, const char **ppszRoot, uint32_t *pcbRootLen)
     327{
     328    MAPPING *pFolderMapping = vbsfMappingGetByRoot(hRoot);
     329    AssertReturn(pFolderMapping, VERR_INVALID_PARAMETER);
     330    if (pFolderMapping->fMissing)
     331        return VERR_NOT_FOUND;
     332    if (   pFolderMapping->pszFolderName == NULL
     333        || pFolderMapping->pszFolderName[0] == 0)
     334        return VERR_NOT_FOUND;
     335    *ppszRoot = pFolderMapping->pszFolderName;
     336    *pcbRootLen = strlen(pFolderMapping->pszFolderName);
     337    return VINF_SUCCESS;
    324338}
    325339
  • trunk/src/VBox/HostServices/SharedFolders/mappings.h

    r44528 r56962  
    5757
    5858const char* vbsfMappingsQueryHostRoot(SHFLROOT root);
     59int vbsfMappingsQueryHostRootEx(SHFLROOT hRoot, const char **ppszRoot, uint32_t *pcbRootLen);
    5960bool vbsfIsGuestMappingCaseSensitive(SHFLROOT root);
    6061bool vbsfIsHostMappingCaseSensitive(SHFLROOT root);
  • trunk/src/VBox/HostServices/SharedFolders/testcase/Makefile.kmk

    r56301 r56962  
    6464    ../service.cpp \
    6565    ../shflhandle.cpp \
     66    ../vbsfpath.cpp \
    6667    ../vbsf.cpp
    6768tstSharedFolderService_LDFLAGS.darwin = \
  • trunk/src/VBox/HostServices/SharedFolders/vbsf.cpp

    r51250 r56962  
    55
    66/*
    7  * Copyright (C) 2006-2013 Oracle Corporation
     7 * Copyright (C) 2006-2015 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2020#endif
    2121
     22#include "vbsfpath.h"
    2223#include "mappings.h"
    2324#include "vbsf.h"
     
    2627#include <iprt/alloc.h>
    2728#include <iprt/assert.h>
     29#include <iprt/asm.h>
    2830#include <iprt/fs.h>
    2931#include <iprt/dir.h>
     
    107109}
    108110
    109 /**
    110  * Corrects the casing of the final component
    111  *
    112  * @returns
    113  * @param   pClient             .
    114  * @param   pszFullPath         .
    115  * @param   pszStartComponent   .
    116  */
    117 static int vbsfCorrectCasing(SHFLCLIENTDATA *pClient, char *pszFullPath, char *pszStartComponent)
    118 {
    119     Log2(("vbsfCorrectCasing: %s %s\n", pszFullPath, pszStartComponent));
    120 
    121     AssertReturn((uintptr_t)pszFullPath < (uintptr_t)pszStartComponent - 1U, VERR_INTERNAL_ERROR_2);
    122     AssertReturn(pszStartComponent[-1] == RTPATH_DELIMITER, VERR_INTERNAL_ERROR_5);
    123 
    124     /*
    125      * Allocate a buffer that can hold really long file name entries as well as
    126      * the initial search pattern.
    127      */
    128     size_t cchComponent = strlen(pszStartComponent);
    129     size_t cchParentDir = pszStartComponent - pszFullPath;
    130     size_t cchFullPath  = cchParentDir + cchComponent;
    131     Assert(strlen(pszFullPath) == cchFullPath);
    132 
    133     size_t cbDirEntry   = 4096;
    134     if (cchFullPath + 4 > cbDirEntry - RT_OFFSETOF(RTDIRENTRYEX, szName))
    135         cbDirEntry = RT_OFFSETOF(RTDIRENTRYEX, szName) + cchFullPath + 4;
    136 
    137     PRTDIRENTRYEX pDirEntry = (PRTDIRENTRYEX)RTMemAlloc(cbDirEntry);
    138     if (pDirEntry == NULL)
    139         return VERR_NO_MEMORY;
    140 
    141     /*
    142      * Construct the search criteria in the szName member of pDirEntry.
    143      */
    144     /** @todo This is quite inefficient, especially for directories with many
    145      *        files.  If any of the typically case sensitive host systems start
    146      *        supporting opendir wildcard filters, it would make sense to build
    147      *        one here with '?' for case foldable charaters. */
    148     /** @todo Use RTDirOpen here and drop the whole uncessary path copying? */
    149     int rc = RTPathJoinEx(pDirEntry->szName, cbDirEntry - RT_OFFSETOF(RTDIRENTRYEX, szName),
    150                           pszFullPath, cchParentDir,
    151                           RT_STR_TUPLE("*"));
    152     AssertRC(rc);
    153     if (RT_SUCCESS(rc))
    154     {
    155         PRTDIR hSearch = NULL;
    156         rc = RTDirOpenFiltered(&hSearch, pDirEntry->szName, RTDIRFILTER_WINNT, 0);
    157         if (RT_SUCCESS(rc))
    158         {
    159             for (;;)
    160             {
    161                 size_t cbDirEntrySize = cbDirEntry;
    162 
    163                 rc = RTDirReadEx(hSearch, pDirEntry, &cbDirEntrySize, RTFSOBJATTRADD_NOTHING, SHFL_RT_LINK(pClient));
    164                 if (rc == VERR_NO_MORE_FILES)
    165                     break;
    166 
    167                 if (   rc != VINF_SUCCESS
    168                     && rc != VWRN_NO_DIRENT_INFO)
    169                 {
    170                     AssertFailed();
    171                     if (   rc == VERR_NO_TRANSLATION
    172                         || rc == VERR_INVALID_UTF8_ENCODING)
    173                         continue;
    174                     break;
    175                 }
    176 
    177                 Log2(("vbsfCorrectCasing: found %s\n", &pDirEntry->szName[0]));
    178                 if (    pDirEntry->cbName == cchComponent
    179                     &&  !RTStrICmp(pszStartComponent, &pDirEntry->szName[0]))
    180                 {
    181                     Log(("Found original name %s (%s)\n", &pDirEntry->szName[0], pszStartComponent));
    182                     strcpy(pszStartComponent, &pDirEntry->szName[0]);
    183                     rc = VINF_SUCCESS;
    184                     break;
    185                 }
    186             }
    187 
    188             RTDirClose(hSearch);
    189         }
    190     }
    191 
    192     if (RT_FAILURE(rc))
    193         Log(("vbsfCorrectCasing %s failed with %Rrc\n", pszStartComponent, rc));
    194 
    195     RTMemFree(pDirEntry);
    196 
    197     return rc;
    198 }
    199 
    200 /* Temporary stand-in for RTPathExistEx. */
    201 static int vbsfQueryExistsEx(const char *pszPath, uint32_t fFlags)
    202 {
    203 #if 0 /** @todo Fix the symlink issue on windows! */
    204     return RTPathExistsEx(pszPath, fFlags);
    205 #else
    206     RTFSOBJINFO IgnInfo;
    207     return RTPathQueryInfoEx(pszPath, &IgnInfo, RTFSOBJATTRADD_NOTHING, fFlags);
    208 #endif
    209 }
    210 
    211 /**
    212  * Helper for vbsfBuildFullPath that performs case corrections on the path
    213  * that's being build.
    214  *
    215  * @returns VINF_SUCCESS at the moment.
    216  * @param   pClient                 The client data.
    217  * @param   pszFullPath             Pointer to the full path.  This is the path
    218  *                                  which may need case corrections.  The
    219  *                                  corrections will be applied in place.
    220  * @param   cchFullPath             The length of the full path.
    221  * @param   fWildCard               Whether the last component may contain
    222  *                                  wildcards and thus might require exclusion
    223  *                                  from the case correction.
    224  * @param   fPreserveLastComponent  Always exclude the last component from case
    225  *                                  correction if set.
    226  */
    227 static int vbsfCorrectPathCasing(SHFLCLIENTDATA *pClient, char *pszFullPath, size_t cchFullPath,
    228                                  bool fWildCard, bool fPreserveLastComponent)
    229 {
    230     /*
    231      * Hide the last path component if it needs preserving.  This is required
    232      * in the following cases:
    233      *    - Contains the wildcard(s).
    234      *    - Is a 'rename' target.
    235      */
    236     char *pszLastComponent = NULL;
    237     if (fWildCard || fPreserveLastComponent)
    238     {
    239         char *pszSrc = pszFullPath + cchFullPath - 1;
    240         Assert(strchr(pszFullPath, '\0') == pszSrc + 1);
    241         while ((uintptr_t)pszSrc > (uintptr_t)pszFullPath)
    242         {
    243             if (*pszSrc == RTPATH_DELIMITER)
    244                 break;
    245             pszSrc--;
    246         }
    247         if (*pszSrc == RTPATH_DELIMITER)
    248         {
    249             if (   fPreserveLastComponent
    250                 /* Or does it really have wildcards? */
    251                 || strchr(pszSrc + 1, '*') != NULL
    252                 || strchr(pszSrc + 1, '?') != NULL
    253                 || strchr(pszSrc + 1, '>') != NULL
    254                 || strchr(pszSrc + 1, '<') != NULL
    255                 || strchr(pszSrc + 1, '"') != NULL )
    256             {
    257                 pszLastComponent = pszSrc;
    258                 *pszLastComponent = '\0';
    259             }
    260         }
    261     }
    262 
    263     /*
    264      * If the path/file doesn't exist, we need to attempt case correcting it.
    265      */
    266     /** @todo Don't check when creating files or directories; waste of time. */
    267     int rc = vbsfQueryExistsEx(pszFullPath, SHFL_RT_LINK(pClient));
    268     if (rc == VERR_FILE_NOT_FOUND || rc == VERR_PATH_NOT_FOUND)
    269     {
    270         Log(("Handle case insensitive guest fs on top of host case sensitive fs for %s\n", pszFullPath));
    271 
    272         /*
    273          * Work from the end of the path to find a partial path that's valid.
    274          */
    275         char *pszSrc = pszLastComponent ? pszLastComponent - 1 : pszFullPath + cchFullPath - 1;
    276         Assert(strchr(pszFullPath, '\0') == pszSrc + 1);
    277 
    278         while ((uintptr_t)pszSrc > (uintptr_t)pszFullPath)
    279         {
    280             if (*pszSrc == RTPATH_DELIMITER)
    281             {
    282                 *pszSrc = '\0';
    283                 rc = vbsfQueryExistsEx(pszFullPath, SHFL_RT_LINK(pClient));
    284                 *pszSrc = RTPATH_DELIMITER;
    285                 if (RT_SUCCESS(rc))
    286                 {
    287 #ifdef DEBUG
    288                     *pszSrc = '\0';
    289                     Log(("Found valid partial path %s\n", pszFullPath));
    290                     *pszSrc = RTPATH_DELIMITER;
    291 #endif
    292                     break;
    293                 }
    294             }
    295 
    296             pszSrc--;
    297         }
    298         Assert(*pszSrc == RTPATH_DELIMITER && RT_SUCCESS(rc));
    299         if (   *pszSrc == RTPATH_DELIMITER
    300             && RT_SUCCESS(rc))
    301         {
    302             /*
    303              * Turn around and work the other way case correcting the components.
    304              */
    305             pszSrc++;
    306             for (;;)
    307             {
    308                 bool fEndOfString = true;
    309 
    310                 /* Find the end of the component. */
    311                 char *pszEnd = pszSrc;
    312                 while (*pszEnd)
    313                 {
    314                     if (*pszEnd == RTPATH_DELIMITER)
    315                         break;
    316                     pszEnd++;
    317                 }
    318 
    319                 if (*pszEnd == RTPATH_DELIMITER)
    320                 {
    321                     fEndOfString = false;
    322                     *pszEnd = '\0';
    323 #if 0 /** @todo Please, double check this. The original code is in the #if 0, what I hold as correct is in the #else. */
    324                     rc = RTPathQueryInfoEx(pszSrc, &info, RTFSOBJATTRADD_NOTHING, SHFL_RT_LINK(pClient));
    325 #else
    326                     rc = vbsfQueryExistsEx(pszFullPath, SHFL_RT_LINK(pClient));
    327 #endif
    328                     Assert(rc == VINF_SUCCESS || rc == VERR_FILE_NOT_FOUND || rc == VERR_PATH_NOT_FOUND);
    329                 }
    330                 else if (pszEnd == pszSrc)
    331                     rc = VINF_SUCCESS;  /* trailing delimiter */
    332                 else
    333                     rc = VERR_FILE_NOT_FOUND;
    334 
    335                 if (rc == VERR_FILE_NOT_FOUND || rc == VERR_PATH_NOT_FOUND)
    336                 {
    337                     /* Path component is invalid; try to correct the casing. */
    338                     rc = vbsfCorrectCasing(pClient, pszFullPath, pszSrc);
    339                     if (RT_FAILURE(rc))
    340                     {
    341                         /* Failed, so don't bother trying any further components. */
    342                         if (!fEndOfString)
    343                             *pszEnd = RTPATH_DELIMITER; /* Restore the original full path. */
    344                         break;
    345                     }
    346                 }
    347 
    348                 /* Next (if any). */
    349                 if (fEndOfString)
    350                     break;
    351 
    352                 *pszEnd = RTPATH_DELIMITER;
    353                 pszSrc = pszEnd + 1;
    354             }
    355             if (RT_FAILURE(rc))
    356                 Log(("Unable to find suitable component rc=%d\n", rc));
    357         }
    358         else
    359             rc = VERR_FILE_NOT_FOUND;
    360 
    361     }
    362 
    363     /* Restore the final component if it was dropped. */
    364     if (pszLastComponent)
    365         *pszLastComponent = RTPATH_DELIMITER;
    366 
    367     /* might be a new file so don't fail here! */
    368     return VINF_SUCCESS;
    369 }
    370 
    371 
    372 /** @def VBSF_IS_PATH_SLASH
    373  * Checks if @a a_ch is a path delimiter (slash, not volume spearator) for the
    374  * guest or the host.
    375  * @param   a_pClient   Pointer to the client data (SHFLCLIENTDATA).
    376  * @param   a_ch        The character to inspect.
    377  */
    378 #if 1
    379 # define VBSF_IS_PATH_SLASH(a_pClient, a_ch)     ( (a_ch) == '\\' || (a_ch) == '/' || RTPATH_IS_SLASH(a_ch) )
    380 #else
    381 # define VBSF_IS_PATH_SLASH(a_pClient, a_ch)     ( (RTUTF16)(a_ch) == (a_pClient)->PathDelimiter || RTPATH_IS_SLASH(a_ch) )
    382 #endif
    383 
    384 
    385 /**
    386  * Check the given UTF-8 path for root escapes.
    387  *
    388  * Verify that the path is within the root directory of the mapping.  Count '..'
    389  * and other path components and check that we do not go over the root.
    390  *
    391  * @returns VBox status code.
    392  * @retval  VINF_SUCCESS
    393  * @retval  VERR_INVALID_NAME
    394  *
    395  * @param   pszPath         The (UTF-8) path to check.  Slashes has been convert
    396  *                          to host slashes by this time.
    397  *
    398  * @remarks This function assumes that the path will be appended to the root
    399  *          directory of the shared folder mapping.  Keep that in mind when
    400  *          checking absolute paths!
    401  */
    402 static int vbsfPathCheck(const char *pszPath)
    403 {
    404     /*
    405      * Walk the path, component by component and check for escapes.
    406      */
    407 
    408     int cComponents = 0; /* How many normal path components. */
    409     int cParentDirs = 0; /* How many '..' components. */
    410 
    411     for (;;)
    412     {
    413         char ch;
    414 
    415         /* Skip leading path delimiters. */
    416         do
    417             ch = *pszPath++;
    418         while (RTPATH_IS_SLASH(ch));
    419         if (ch == '\0')
    420             return VINF_SUCCESS;
    421 
    422         /* Check if that is a dot component. */
    423         int cDots = 0;
    424         while (ch == '.')
    425         {
    426             cDots++;
    427             ch = *pszPath++;
    428         }
    429 
    430         if (   cDots >= 1
    431             && (ch == '\0' || RTPATH_IS_SLASH(ch)) )
    432         {
    433             if (cDots >= 2) /* Consider all multidots sequences as a 'parent dir'. */
    434             {
    435                 cParentDirs++;
    436 
    437                 /* Escaping? */
    438                 if (cParentDirs > cComponents)
    439                     return VERR_INVALID_NAME;
    440             }
    441             /* else: Single dot, nothing changes. */
    442         }
    443         else
    444         {
    445             /* Not a dot component, skip to the end of it. */
    446             while (ch != '\0' && !RTPATH_IS_SLASH(ch))
    447                 ch = *pszPath++;
    448             cComponents++;
    449         }
    450         Assert(cComponents >= cParentDirs);
    451 
    452         /* The end? */
    453         Assert(ch == '\0' || RTPATH_IS_SLASH(ch));
    454         if (ch == '\0')
    455             return VINF_SUCCESS;
    456     }
    457 }
    458 
    459111static int vbsfBuildFullPath(SHFLCLIENTDATA *pClient, SHFLROOT root, PSHFLSTRING pPath,
    460112                             uint32_t cbPath, char **ppszFullPath, uint32_t *pcbFullPathRoot,
    461113                             bool fWildCard = false, bool fPreserveLastComponent = false)
    462114{
    463     /* Resolve the root prefix into a string. */
    464     const char *pszRoot = vbsfMappingsQueryHostRoot(root);
    465     if (   !pszRoot
    466         || !*pszRoot)
    467     {
    468         Log(("vbsfBuildFullPath: invalid root!\n"));
    469         return VERR_INVALID_PARAMETER;
    470     }
    471     uint32_t cchRoot = (uint32_t)strlen(pszRoot);
    472 #if RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS
    473     Assert(!strchr(pszRoot, '/'));
    474 #endif
    475 
    476     /*
    477      * Combine the root prefix with the guest path into a full UTF-8 path in a
    478      * buffer pointed to by pszFullPath.  cchRoot may be adjusted in the process.
    479      */
    480     int    rc;
    481     size_t cchFullPath;
    482     char  *pszFullPath = NULL;
     115    char *pszHostPath = NULL;
     116    uint32_t fu32PathFlags = 0;
     117    int rc = vbsfPathGuestToHost(pClient, root, pPath, cbPath,
     118                                 &pszHostPath, pcbFullPathRoot, fWildCard, fPreserveLastComponent, &fu32PathFlags);
    483119    if (BIT_FLAG(pClient->fu32Flags, SHFL_CF_UTF8))
    484120    {
    485         /* Strip leading slashes from the path the guest specified. */
    486         uint32_t    cchSrc = pPath->u16Length;
    487         const char *pszSrc = (char *)&pPath->String.utf8[0];
    488         Log(("Root %s path %.*s\n", pszRoot, cchSrc, pszSrc));
    489 
    490         while (   cchSrc > 0
    491                && VBSF_IS_PATH_SLASH(pClient, *pszSrc))
    492         {
    493             pszSrc++;
    494             cchSrc--;
    495         }
    496 
    497         /* Allocate a buffer that will be able to contain the root prefix and
    498            the path specified by the guest. */
    499         cchFullPath = cchRoot + cchSrc;
    500         pszFullPath = (char *)RTMemAlloc(cchFullPath + 1 + 1);
    501         if (RT_LIKELY(pszFullPath != NULL))
    502         {
    503             memcpy(pszFullPath, pszRoot, cchRoot);
    504             if (!RTPATH_IS_SLASH(pszRoot[-1]))
    505             {
    506                 pszFullPath[cchRoot++] = RTPATH_DELIMITER;
    507                 cchFullPath++;
    508             }
    509 
    510             if (cchSrc)
    511                 memcpy(&pszFullPath[cchRoot], pszSrc, cchSrc);
    512 
    513             /* Terminate the string. */
    514             pszFullPath[cchRoot + cchSrc] = '\0';
    515             rc = VINF_SUCCESS;
    516         }
    517         else
    518         {
    519             Log(("RTMemAlloc %x failed!!\n", cchFullPath + 1));
    520             rc = VERR_NO_MEMORY;
    521         }
    522     }
    523     else /* Client speaks UTF-16. */
    524     {
    525 #ifdef RT_OS_DARWIN /* Misplaced hack! See todo! */
    526 /** @todo This belongs in rtPathToNative or in the windows shared folder file system driver...
    527  * The question is simply whether the NFD normalization is actually applied on a (virtual) file
    528  * system level in darwin, or just by the user mode application libs. */
    529         SHFLSTRING *pPathParameter = pPath;
    530         size_t cbPathLength;
    531         CFMutableStringRef inStr = ::CFStringCreateMutable(NULL, 0);
    532         uint16_t ucs2Length;
    533         CFRange rangeCharacters;
    534 
    535         // Is 8 times length enough for decomposed in worst case...?
    536         cbPathLength = sizeof(SHFLSTRING) + pPathParameter->u16Length * 8 + 2;
    537         pPath = (SHFLSTRING *)RTMemAllocZ(cbPathLength);
    538         if (!pPath)
    539         {
    540             rc = VERR_NO_MEMORY;
    541             Log(("RTMemAllocZ %x failed!!\n", cbPathLength));
    542             return rc;
    543         }
    544 
    545         ::CFStringAppendCharacters(inStr, (UniChar*)pPathParameter->String.ucs2,
    546                                    pPathParameter->u16Length / sizeof(pPathParameter->String.ucs2[0]));
    547         ::CFStringNormalize(inStr, kCFStringNormalizationFormD);
    548         ucs2Length = ::CFStringGetLength(inStr);
    549 
    550         rangeCharacters.location = 0;
    551         rangeCharacters.length = ucs2Length;
    552         ::CFStringGetCharacters(inStr, rangeCharacters, pPath->String.ucs2);
    553         pPath->String.ucs2[ucs2Length] = 0x0000; // NULL terminated
    554         pPath->u16Length = ucs2Length * sizeof(pPath->String.ucs2[0]);
    555         pPath->u16Size = pPath->u16Length + sizeof(pPath->String.ucs2[0]);
    556 
    557         CFRelease(inStr);
    558 #endif
    559 
    560         /* Strip leading slashes and calculate the UTF-8 length. */
    561         size_t      cwcSrc  = pPath->u16Length / sizeof(RTUTF16);
    562         PRTUTF16    pwszSrc = &pPath->String.ucs2[0];
    563         Log(("Root %s path %.*ls\n", pszRoot, cwcSrc, pwszSrc));
    564 
    565         while (   cwcSrc > 0
    566                && *pwszSrc < 0x80
    567                && VBSF_IS_PATH_SLASH(pClient, (char)*pwszSrc))
    568         {
    569             pwszSrc++;
    570             cwcSrc--;
    571         }
    572 
    573         size_t      cchPathAsUtf8 = RTUtf16CalcUtf8Len(pwszSrc);
    574 #ifdef RT_OS_DARWIN
    575         AssertReturnStmt(cchPathAsUtf8 >= cwcSrc, RTMemFree(pPath), VERR_INTERNAL_ERROR_3);
    576 #else
    577         AssertReturn(cchPathAsUtf8 >= cwcSrc, VERR_INTERNAL_ERROR_3);
    578 #endif
    579 
    580         /* Allocate buffer that will be able to contain the root prefix and
    581          * the pPath converted to UTF-8. */
    582         cchFullPath = cchRoot + cchPathAsUtf8;
    583         pszFullPath = (char *)RTMemAlloc(cchFullPath + 1 + 1);
    584         if (RT_LIKELY(pszFullPath != NULL))
    585         {
    586             /* Copy the root prefix into the result buffer and make sure it
    587                ends with a path separator. */
    588             memcpy(pszFullPath, pszRoot, cchRoot);
    589             if (!RTPATH_IS_SLASH(pszFullPath[cchRoot - 1]))
    590             {
    591                 pszFullPath[cchRoot++] = RTPATH_DELIMITER;
    592                 cchFullPath++;
    593             }
    594 
    595             /* Append the path specified by the guest (if any). */
    596             if (cchPathAsUtf8)
    597             {
    598                 size_t cchActual;
    599                 char *pszDst = &pszFullPath[cchRoot];
    600                 rc = RTUtf16ToUtf8Ex(pwszSrc, cwcSrc, &pszDst, cchFullPath - cchRoot + 1, &cchActual);
    601                 AssertRC(rc);
    602                 AssertStmt(RT_FAILURE(rc) || cchActual == cchPathAsUtf8, rc = VERR_INTERNAL_ERROR_4);
    603                 Assert(strlen(pszDst) == cchPathAsUtf8);
    604             }
    605             else
    606                 rc = VINF_SUCCESS;
    607 
    608             /* Terminate the string. */
    609             pszFullPath[cchRoot + cchPathAsUtf8] = '\0';
    610         }
    611         else
    612         {
    613             Log(("RTMemAlloc %x failed!!\n", cchFullPath + 1));
    614             rc = VERR_NO_MEMORY;
    615         }
    616 
    617 #ifdef RT_OS_DARWIN
    618         RTMemFree(pPath);
    619         pPath = pPathParameter;
    620 #endif
    621     }
     121        LogRel2(("SharedFolders: GuestToHost 0x%RX32 [%.*s]->[%s] %Rrc\n", fu32PathFlags, pPath->u16Length, &pPath->String.utf8[0], pszHostPath, rc));
     122    }
     123    else
     124    {
     125        LogRel2(("SharedFolders: GuestToHost 0x%RX32 [%.*ls]->[%s] %Rrc\n", fu32PathFlags, pPath->u16Length / 2, &pPath->String.ucs2[0], pszHostPath, rc));
     126    }
     127
    622128    if (RT_SUCCESS(rc))
    623129    {
    624         Assert(strlen(pszFullPath) == cchFullPath);
    625         Assert(RTPATH_IS_SLASH(pszFullPath[cchRoot - 1])); /* includes delimiter. */
    626 
    627         if (pcbFullPathRoot)
    628             *pcbFullPathRoot = cchRoot - 1; /* Must index the path delimiter. */
    629 
    630         /*
    631          * Convert guest path delimiters into host ones and check for attempts
    632          * to escape the shared folder root directory.
    633          *
    634          * After this, there will only be RTPATH_DELIMITER slashes in the path!
    635          *
    636          * ASSUMES that the root path only has RTPATH_DELIMITER as well.
    637          */
    638         char  ch;
    639         char *pszTmp = &pszFullPath[cchRoot];
    640         while ((ch = *pszTmp) != '\0')
    641         {
    642             if (VBSF_IS_PATH_SLASH(pClient, ch))
    643                 *pszTmp = RTPATH_DELIMITER;
    644             pszTmp++;
    645         }
    646         LogFlow(("Corrected string %s\n", pszFullPath));
    647 
    648         rc = vbsfPathCheck(&pszFullPath[cchRoot]);
    649         if (RT_SUCCESS(rc))
    650         {
    651             /*
    652              * When the host file system is case sensitive and the guest expects
    653              * a case insensitive fs, then problems can occur.
    654              */
    655             if (    vbsfIsHostMappingCaseSensitive(root)
    656                 && !vbsfIsGuestMappingCaseSensitive(root))
    657                 rc = vbsfCorrectPathCasing(pClient, pszFullPath, cchFullPath, fWildCard, fPreserveLastComponent);
    658             if (RT_SUCCESS(rc))
    659             {
    660                 /*
    661                  * We're good.
    662                  */
    663                 *ppszFullPath = pszFullPath;
    664                 LogFlow(("vbsfBuildFullPath: %s rc=%Rrc\n", pszFullPath, rc));
    665                 return rc;
    666             }
    667 
    668             /* Failed, clean up. */
    669             Log(("vbsfBuildFullPath: %s rc=%Rrc\n", pszFullPath, rc));
    670         }
    671         else
    672             Log(("vbsfBuildPath: Caught escape attempt: (%.*s) '%s'\n", cchRoot, pszFullPath, &pszFullPath[cchRoot]));
    673     }
    674 
    675     if (pszFullPath)
    676         RTMemFree(pszFullPath);
    677     *ppszFullPath = NULL;
     130        if (ppszFullPath)
     131            *ppszFullPath = pszHostPath;
     132    }
    678133    return rc;
    679134}
     
    681136static void vbsfFreeFullPath(char *pszFullPath)
    682137{
    683     RTMemFree(pszFullPath);
     138    vbsfFreeHostPath(pszFullPath);
    684139}
    685140
     
    16531108            Assert(pHandle->dir.pLastValidEntry == 0);
    16541109
    1655             rc = vbsfBuildFullPath(pClient, root, pPath, pPath->u16Size, &pszFullPath, NULL, true);
     1110            rc = vbsfBuildFullPath(pClient, root, pPath, pPath->u16Size + SHFLSTRING_HEADER_SIZE, &pszFullPath, NULL, true);
    16561111
    16571112            if (RT_SUCCESS(rc))
     
    20571512    ShflStringInitBuffer(&dummy, sizeof(dummy));
    20581513    dummy.String.ucs2[0] = '\0';
    2059     rc = vbsfBuildFullPath(pClient, root, &dummy, 0, &pszFullPath, NULL);
     1514    rc = vbsfBuildFullPath(pClient, root, &dummy, sizeof(dummy), &pszFullPath, NULL);
    20601515
    20611516    if (RT_SUCCESS(rc))
     
    23351790    char *pszFullPathDest = NULL;
    23361791
    2337     rc = vbsfBuildFullPath(pClient, root, pSrc, pSrc->u16Size, &pszFullPathSrc, NULL);
     1792    rc = vbsfBuildFullPath(pClient, root, pSrc, pSrc->u16Size + SHFLSTRING_HEADER_SIZE, &pszFullPathSrc, NULL);
    23381793    if (rc != VINF_SUCCESS)
    23391794        return rc;
    23401795
    2341     rc = vbsfBuildFullPath(pClient, root, pDest, pDest->u16Size, &pszFullPathDest, NULL, false, true);
     1796    rc = vbsfBuildFullPath(pClient, root, pDest, pDest->u16Size + SHFLSTRING_HEADER_SIZE, &pszFullPathDest, NULL, false, true);
    23421797    if (RT_SUCCESS (rc))
    23431798    {
     
    24031858        return VERR_WRITE_PROTECT; /* XXX or VERR_TOO_MANY_SYMLINKS? */
    24041859
    2405     rc = vbsfBuildFullPath(pClient, root, pNewPath, pNewPath->u16Size, &pszFullNewPath, NULL);
     1860    rc = vbsfBuildFullPath(pClient, root, pNewPath, pNewPath->u16Size + SHFLSTRING_HEADER_SIZE, &pszFullNewPath, NULL);
    24061861    AssertRCReturn(rc, rc);
    24071862
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette