VirtualBox

Changeset 44286 in vbox


Ignore:
Timestamp:
Jan 14, 2013 1:24:13 PM (12 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
83194
Message:

iprt/rm: Some corrections and optimizations.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/path/RTPathRmCmd.cpp

    r44279 r44286  
    5353
    5454/** The max directory entry size. */
    55 #define RTPATHRM_DIR_MAX_ENTRY_SIZE         4096
     55#define RTPATHRM_DIR_MAX_ENTRY_SIZE         (sizeof(RTDIRENTRYEX) + 4096)
    5656
    5757
     
    253253 * @param   pDirEntry           Pointer to a directory entry buffer that is
    254254 *                              RTPATHRM_DIR_MAX_ENTRY_SIZE bytes big.
    255  * @param   pObjInfo            Pointer the FS object info for the directory.
    256  *                              This will be modified.
    257  */
    258 static int rtPathRmRecursive(PRTPATHRMCMDOPTS pOpts, char *pszPath, size_t cchPath, PRTDIRENTRY pDirEntry, PRTFSOBJINFO pObjInfo)
     255 */
     256static int rtPathRmRecursive(PRTPATHRMCMDOPTS pOpts, char *pszPath, size_t cchPath, PRTDIRENTRYEX pDirEntry)
    259257{
    260258    /*
     
    283281         */
    284282        size_t cbEntry = RTPATHRM_DIR_MAX_ENTRY_SIZE;
    285         rc = RTDirRead(hDir, pDirEntry, &cbEntry);
     283        rc = RTDirReadEx(hDir, pDirEntry, &cbEntry, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
    286284        if (rc == VERR_NO_MORE_FILES)
    287285        {
     286            /*
     287             * Reached the end of the directory.
     288             */
    288289            pszPath[cchPath] = '\0';
    289290            rc = RTDirClose(hDir);
     
    297298            return rcRet;
    298299        }
     300
    299301        if (RT_FAILURE(rc))
    300302        {
     
    320322
    321323        /*
    322          * Just query the full path info as we'll need it.
    323          */
    324         rc = RTPathQueryInfoEx(pszPath, pObjInfo, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
    325         if (RT_FAILURE(rc))
    326         {
    327             rc = rtPathRmError(pOpts, pszPath, rc, "RTPathQueryInfoEx failed on '%s': %Rrc", pszPath, rc);
    328             if (RT_SUCCESS(rcRet))
    329                 rcRet = rc;
    330         }
    331 
    332         /*
    333324         * Take action according to the type.
    334325         */
    335         switch (pObjInfo->Attr.fMode & RTFS_TYPE_MASK)
     326        switch (pDirEntry->Info.Attr.fMode & RTFS_TYPE_MASK)
    336327        {
    337328            case RTFS_TYPE_FILE:
    338                 rc = rtPathRmOneFile(pOpts, pszPath, pObjInfo);
     329                rc = rtPathRmOneFile(pOpts, pszPath, &pDirEntry->Info);
    339330                break;
    340331
    341332            case RTFS_TYPE_DIRECTORY:
    342                 rc = rtPathRmRecursive(pOpts, pszPath, cchPath, pDirEntry, pObjInfo);
     333                rc = rtPathRmRecursive(pOpts, pszPath, cchPath + pDirEntry->cbName, pDirEntry);
    343334                break;
    344335
     
    351342            case RTFS_TYPE_DEV_BLOCK:
    352343            case RTFS_TYPE_SOCKET:
    353                 rc = rtPathRmOneFile(pOpts, pszPath, pObjInfo);
     344                rc = rtPathRmOneFile(pOpts, pszPath, &pDirEntry->Info);
    354345                break;
    355346
     
    357348            default:
    358349                rc = rtPathRmError(pOpts, pszPath, VERR_UNEXPECTED_FS_OBJ_TYPE,
    359                                    "Object '%s' has an unknown file type: %o\n", pszPath, pObjInfo->Attr.fMode & RTFS_TYPE_MASK);
     350                                   "Object '%s' has an unknown file type: %o\n",
     351                                   pszPath, pDirEntry->Info.Attr.fMode & RTFS_TYPE_MASK);
    360352                break;
    361353        }
     
    364356    }
    365357
     358    /*
     359     * Some error occured, close and return.
     360     */
    366361    RTDirClose(hDir);
    367362    return rc;
    368363}
    369364
    370 
    371365/**
    372  * Remove one user specified file or directory.
     366 * Validates the specified file or directory.
    373367 *
    374368 * @returns IPRT status code, errors go via rtPathRmError.
     
    376370 * @param   pszPath             The path to the file, directory, whatever.
    377371 */
     372static int rtPathRmOneValidate(PRTPATHRMCMDOPTS pOpts, const char *pszPath)
     373{
     374    /*
     375     * RTPathFilename doesn't do the trailing slash thing the way we need it to.
     376     * E.g. both '..' and '../' should be rejected.
     377     */
     378    size_t cchPath = strlen(pszPath);
     379    while (cchPath > 0 && RTPATH_IS_SLASH(pszPath[cchPath - 1]))
     380        cchPath--;
     381
     382    if (   (  cchPath == 0
     383            || 0 /** @todo drive letter + UNC crap */)
     384        && pOpts->fPreserveRoot)
     385        return rtPathRmError(pOpts, pszPath, VERR_CANT_DELETE_DIRECTORY, "Cannot remove root directory ('%s').\n", pszPath);
     386
     387    size_t offLast = cchPath - 1;
     388    while (offLast > 0 && !RTPATH_IS_SEP(pszPath[offLast - 1]))
     389        offLast--;
     390
     391    size_t cchLast = cchPath - offLast;
     392    if (   pszPath[offLast] == '.'
     393        && (   cchLast == 1
     394            || (cchLast == 2 && pszPath[offLast + 1] == '.')))
     395        return rtPathRmError(pOpts, pszPath, VERR_CANT_DELETE_DIRECTORY, "Cannot remove special directory '%s'.\n", pszPath);
     396
     397    return VINF_SUCCESS;
     398}
     399
     400
     401/**
     402 * Remove one user specified file or directory.
     403 *
     404 * @returns IPRT status code, errors go via rtPathRmError.
     405 * @param   pOpts               The RM options.
     406 * @param   pszPath             The path to the file, directory, whatever.
     407 */
    378408static int rtPathRmOne(PRTPATHRMCMDOPTS pOpts, const char *pszPath)
    379409{
    380410    /*
    381      * Refuse to remove '.' and '..'.
    382      */
    383     const char *pszFilename = RTPathFilename(pszPath);
    384     if (   pszFilename[0] == '.'
    385         && (   pszFilename[1] == '\0'
    386             || (pszFilename[1] == '.' && pszFilename[2] == '\0')))
    387         return rtPathRmError(pOpts, pszPath, VERR_CANT_DELETE_DIRECTORY, "Cannot remove directory '%s'.\n", pszPath);
     411     * RM refuses to delete some directories.
     412     */
     413    int rc = rtPathRmOneValidate(pOpts, pszPath);
     414    if (RT_FAILURE(rc))
     415        return rc;
    388416
    389417    /*
     
    391419     */
    392420    RTFSOBJINFO ObjInfo;
    393     int rc = RTPathQueryInfoEx(pszPath, &ObjInfo, RTFSOBJATTRADD_UNIX, RTPATH_F_ON_LINK);
     421    rc = RTPathQueryInfoEx(pszPath, &ObjInfo, RTFSOBJATTRADD_UNIX, RTPATH_F_ON_LINK);
    394422    if (RT_FAILURE(rc))
    395423    {
     
    417445                union
    418446                {
    419                     RTDIRENTRY  Core;
    420                     uint8_t     abPadding[RTPATHRM_DIR_MAX_ENTRY_SIZE];
     447                    RTDIRENTRYEX    Core;
     448                    uint8_t         abPadding[RTPATHRM_DIR_MAX_ENTRY_SIZE];
    421449                } DirEntry;
    422450
    423                 return rtPathRmRecursive(pOpts, szPath, strlen(szPath), &DirEntry.Core, &ObjInfo);
     451                return rtPathRmRecursive(pOpts, szPath, strlen(szPath), &DirEntry.Core);
    424452            }
    425453            if (pOpts->fDirsAndOther)
Note: See TracChangeset for help on using the changeset viewer.

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