VirtualBox

Changeset 69705 in vbox for trunk/src/VBox/Runtime/common


Ignore:
Timestamp:
Nov 15, 2017 4:42:59 PM (7 years ago)
Author:
vboxsync
Message:

IPRT: VFS and NT path handling fixes.

  • Rewrote RTDirQueryInfo for NT. When RTDirOpen* now opens directories, it will request read-attribute access in additions to listing.
  • Major adjustment of the VFS path parser. It now accepts both slashes and will deal differently with '..' in operations on directories.
  • Implemented native RTDirRelPathQueryInfo for NT.
  • NT directory object (NT namespace objects, not file system dirs) fixes for NT specific RTDirRel APIs.
Location:
trunk/src/VBox/Runtime/common/vfs
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/vfs/vfsbase.cpp

    r69111 r69705  
    11911191
    11921192
    1193 
    1194 /**
    1195  * Removes dots from the path.
    1196  *
    1197  * @returns The new @a pszDst value.
    1198  * @param   pPath               The path parsing buffer.
    1199  * @param   pszDst              The current szPath position.  This will be
    1200  *                              updated and returned.
    1201  * @param   fTheEnd             Indicates whether we're at the end of the path
    1202  *                              or not.
    1203  * @param   piRestartComp       The component to restart parsing at.
    1204  */
    1205 static char *rtVfsParsePathHandleDots(PRTVFSPARSEDPATH pPath, char *pszDst, bool fTheEnd, uint16_t *piRestartComp)
    1206 {
    1207     if (pszDst[-1] != '.')
    1208         return pszDst;
    1209 
    1210     if (pszDst[-2] == '/')
    1211     {
    1212         pPath->cComponents--;
    1213         pszDst = &pPath->szPath[pPath->aoffComponents[pPath->cComponents]];
    1214     }
    1215     else if (pszDst[-2] == '.' && pszDst[-3] == '/')
    1216     {
    1217         pPath->cComponents -= pPath->cComponents > 1 ? 2 : 1;
    1218         pszDst = &pPath->szPath[pPath->aoffComponents[pPath->cComponents]];
    1219         if (piRestartComp && *piRestartComp + 1 >= pPath->cComponents)
    1220             *piRestartComp = pPath->cComponents > 0 ? pPath->cComponents - 1 : 0;
    1221     }
    1222     else
    1223         return pszDst;
    1224 
    1225     /*
    1226      * Drop the trailing slash if we're at the end of the source path.
    1227      */
    1228     if (fTheEnd && pPath->cComponents == 0)
    1229         pszDst--;
    1230     return pszDst;
    1231 }
    1232 
    1233 
    12341193RTDECL(int) RTVfsParsePathAppend(PRTVFSPARSEDPATH pPath, const char *pszPath, uint16_t *piRestartComp)
    12351194{
    1236     AssertReturn(*pszPath != '/', VERR_INTERNAL_ERROR_4);
     1195    AssertReturn(*pszPath != '/' && *pszPath != '\\', VERR_INTERNAL_ERROR_4);
    12371196
    12381197    /* In case *piRestartComp was set higher than the number of components
     
    12441203     * Append a slash to the destination path if necessary.
    12451204     */
    1246     char *pszDst = &pPath->szPath[pPath->cch];
     1205    char * const pszDst         = pPath->szPath;
     1206    size_t       offDst         = pPath->cch;
    12471207    if (pPath->cComponents > 0)
    12481208    {
    1249         *pszDst++ = '/';
    1250         if (pszDst - &pPath->szPath[0] >= RTVFSPARSEDPATH_MAX)
     1209        pszDst[offDst++] = '/';
     1210        if (offDst >= RTVFSPARSEDPATH_MAX)
    12511211            return VERR_FILENAME_TOO_LONG;
    12521212    }
    1253     Assert(pszDst[-1] == '/');
     1213    if (pPath->fAbsolute)
     1214        Assert(pszDst[offDst - 1] == '/' && pszDst[0] == '/');
     1215    else
     1216        Assert(offDst == 0 || (pszDst[0] != '/' && pszDst[offDst - 1] == '/'));
    12541217
    12551218    /*
     
    12581221    const char *pszSrc = pszPath;
    12591222    pPath->fDirSlash   = false;
    1260     while (pszSrc[0])
    1261     {
    1262         /* Skip unncessary slashes. */
    1263         while (pszSrc[0] == '/')
    1264             pszSrc++;
    1265 
     1223    for (;;)
     1224    {
    12661225        /* Copy until we encounter the next slash. */
    1267         pPath->aoffComponents[pPath->cComponents++] = pszDst - &pPath->szPath[0];
    1268         while (pszSrc[0])
    1269         {
    1270             if (pszSrc[0] == '/')
     1226        pPath->aoffComponents[pPath->cComponents++] = (uint16_t)offDst;
     1227        for (;;)
     1228        {
     1229            char ch = *pszSrc++;
     1230            if (   ch != '/'
     1231                && ch != '\\'
     1232                && ch != '\0')
    12711233            {
    1272                 pszSrc++;
    1273                 if (pszSrc[0])
    1274                     *pszDst++ = '/';
     1234                pszDst[offDst++] = ch;
     1235                if (offDst < RTVFSPARSEDPATH_MAX)
     1236                { /* likely */ }
    12751237                else
    1276                     pPath->fDirSlash = true;
    1277                 pszDst = rtVfsParsePathHandleDots(pPath, pszDst, pszSrc[0] == '\0', piRestartComp);
     1238                    return VERR_FILENAME_TOO_LONG;
     1239            }
     1240            else
     1241            {
     1242                /* Deal with dot components before we processes the slash/end. */
     1243                if (pszDst[offDst - 1] == '.')
     1244                {
     1245                    if (   offDst == 1
     1246                        || pszDst[offDst - 2] == '/')
     1247                    {
     1248                        pPath->cComponents--;
     1249                        offDst = pPath->aoffComponents[pPath->cComponents];
     1250                    }
     1251                    else if (   offDst > 3
     1252                             && pszDst[offDst - 2] == '.'
     1253                             && pszDst[offDst - 3] == '/')
     1254                    {
     1255                        if (   pPath->fAbsolute
     1256                            || offDst < 5
     1257                            || pszDst[offDst - 4] != '.'
     1258                            || pszDst[offDst - 5] != '.'
     1259                            || (offDst >= 6 && pszDst[offDst - 6] != '/') )
     1260                        {
     1261                            pPath->cComponents -= pPath->cComponents > 1 ? 2 : 1;
     1262                            offDst = pPath->aoffComponents[pPath->cComponents];
     1263                            if (piRestartComp && *piRestartComp + 1 >= pPath->cComponents)
     1264                                *piRestartComp = pPath->cComponents > 0 ? pPath->cComponents - 1 : 0;
     1265                        }
     1266                    }
     1267                }
     1268
     1269                if (ch != '\0')
     1270                {
     1271                    /* Skip unnecessary slashes and check for end of path. */
     1272                    while ((ch = *pszSrc) == '/' || ch == '\\')
     1273                        pszSrc++;
     1274
     1275                    if (ch == '\0')
     1276                        pPath->fDirSlash = true;
     1277                }
     1278
     1279                if (ch == '\0')
     1280                {
     1281                    /* Drop trailing slash unless it's the root slash. */
     1282                    if (   offDst > 0
     1283                        && pszDst[offDst - 1] == '/'
     1284                        && (   !pPath->fAbsolute
     1285                            || offDst > 1))
     1286                        offDst--;
     1287
     1288                    /* Terminate the string and enter its length. */
     1289                    pszDst[offDst]     = '\0';
     1290                    pszDst[offDst + 1] = '\0'; /* for aoffComponents[pPath->cComponents] */
     1291                    pPath->cch = (uint16_t)offDst;
     1292                    pPath->aoffComponents[pPath->cComponents] = (uint16_t)(offDst + 1);
     1293                    return VINF_SUCCESS;
     1294                }
     1295
     1296                /* Append component separator before continuing with the next component. */
     1297                if (offDst > 0 && pszDst[offDst - 1] != '/')
     1298                    pszDst[offDst++] = '/';
     1299                if (offDst >= RTVFSPARSEDPATH_MAX)
     1300                    return VERR_FILENAME_TOO_LONG;
    12781301                break;
    12791302            }
    1280 
    1281             *pszDst++ = *pszSrc++;
    1282             if (pszDst - &pPath->szPath[0] >= RTVFSPARSEDPATH_MAX)
    1283                 return VERR_FILENAME_TOO_LONG;
    1284         }
    1285     }
    1286     pszDst = rtVfsParsePathHandleDots(pPath, pszDst, true /*fTheEnd*/, piRestartComp);
    1287 
    1288     /* Terminate the string and enter its length. */
    1289     pszDst[0] = '\0';
    1290     pszDst[1] = '\0';                   /* for aoffComponents */
    1291     pPath->cch = (uint16_t)(pszDst - &pPath->szPath[0]);
    1292     pPath->aoffComponents[pPath->cComponents] = pPath->cch + 1;
    1293 
    1294     return VINF_SUCCESS;
     1303        }
     1304    }
    12951305}
    12961306
     
    13011311    if (*pszPath != '/')
    13021312    {
    1303         /*
    1304          * Relative, recurse and parse pszCwd first.
    1305          */
    1306         int rc = RTVfsParsePath(pPath, pszCwd, NULL /*crash if pszCwd is not absolute*/);
    1307         if (RT_FAILURE(rc))
    1308             return rc;
     1313        if (pszCwd)
     1314        {
     1315            /*
     1316             * Relative with a CWD.
     1317             */
     1318            int rc = RTVfsParsePath(pPath, pszCwd, NULL /*crash if pszCwd is not absolute*/);
     1319            if (RT_FAILURE(rc))
     1320                return rc;
     1321        }
     1322        else
     1323        {
     1324            /*
     1325             * Relative.
     1326             */
     1327            pPath->cch               = 0;
     1328            pPath->cComponents       = 0;
     1329            pPath->fDirSlash         = false;
     1330            pPath->fAbsolute         = false;
     1331            pPath->aoffComponents[0] = 0;
     1332            pPath->aoffComponents[1] = 1;
     1333            pPath->szPath[0]         = '\0';
     1334            pPath->szPath[1]         = '\0';
     1335        }
    13091336    }
    13101337    else
     
    13171344        pPath->cComponents       = 0;
    13181345        pPath->fDirSlash         = false;
     1346        pPath->fAbsolute         = true;
    13191347        pPath->aoffComponents[0] = 1;
    13201348        pPath->aoffComponents[1] = 2;
     
    22762304     */
    22772305    PRTVFSPARSEDPATH pPath;
    2278     int rc = RTVfsParsePathA(pszPath, "/", &pPath);
     2306    int rc = RTVfsParsePathA(pszPath, NULL, &pPath);
    22792307    if (RT_SUCCESS(rc))
    22802308    {
     
    23422370     */
    23432371    PRTVFSPARSEDPATH pPath;
    2344     rc = RTVfsParsePathA(pszPath, "/", &pPath);
     2372    rc = RTVfsParsePathA(pszPath, NULL, &pPath);
    23452373    if (RT_SUCCESS(rc))
    23462374    {
     
    24112439
    24122440    /*
    2413      * Parse the path, assume current directory is root since we've got no
    2414      * caller context here.  Then traverse to the parent directory.
     2441     * Parse the relative path.  Then traverse to the parent directory.
    24152442     */
    24162443    PRTVFSPARSEDPATH pPath;
    2417     int rc = RTVfsParsePathA(pszPath, "/", &pPath);
     2444    int rc = RTVfsParsePathA(pszPath, NULL, &pPath);
    24182445    if (RT_SUCCESS(rc))
    24192446    {
  • trunk/src/VBox/Runtime/common/vfs/vfschain.cpp

    r69674 r69705  
    145145        {
    146146            /*
    147              * First element: Ttransform into 'stdfile' or 'stddir' if registered.
     147             * First element: Transform into 'stdfile' or 'stddir' if registered.
    148148             */
    149149            const char            *pszNewProvider = pElement->enmType == RTVFSOBJTYPE_DIR ? "stddir" : "stdfile";
     
    177177            return VERR_VFS_CHAIN_INVALID_ARGUMENT;
    178178        }
    179     }
     179        return rc;
     180    }
     181
    180182
    181183    /*
     
    184186    if (pElement->cArgs > 1)
    185187        return VERR_VFS_CHAIN_AT_MOST_ONE_ARG;
     188    pElement->uProvider = 0;
    186189    return VINF_SUCCESS;
    187190}
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