VirtualBox

Changeset 69720 in vbox for trunk


Ignore:
Timestamp:
Nov 16, 2017 4:18:19 PM (7 years ago)
Author:
vboxsync
Message:

IPRT: More work on directory relative APIs (NT mainly) and VFS; introducing RTRmDir (test) tool.

  • Added RTVfsDirRemoveDir
  • Native NT implementation of RTDirRelRemoveDir.
  • Improved the RTFS_TYPE_DIRECTORY case of rtVfsStdDir_UnlinkEntry.
  • Added two new status code conversions to RTErrConvertFromNtStatus.
Location:
trunk
Files:
8 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/mangling.h

    r69716 r69720  
    24382438# define RTVfsDirQueryPathInfo                          RT_MANGLER(RTVfsDirQueryPathInfo)
    24392439# define RTVfsDirReadEx                                 RT_MANGLER(RTVfsDirReadEx)
     2440# define RTVfsDirRemoveDir                              RT_MANGLER(RTVfsDirRemoveDir)
    24402441# define RTVfsFileFlush                                 RT_MANGLER(RTVfsFileFlush)
    24412442# define RTVfsFileFromBuffer                            RT_MANGLER(RTVfsFileFromBuffer)
  • trunk/include/iprt/vfs.h

    r69716 r69720  
    528528
    529529/**
     530 * Removes a directory relative to @a hVfsDir.
     531 *
     532 * @returns IPRT status code.
     533 * @param   hVfsDir         The VFS directory to start walking the @a pszRelPath
     534 *                          relative to.
     535 * @param   pszRelPath      The path to the directory that should be removed.
     536 * @param   fFlags          Reserved, MBZ.
     537 */
     538RTDECL(int) RTVfsDirRemoveDir(RTVFSDIR hVfsDir, const char *pszRelPath, uint32_t fFlags);
     539
     540/**
    530541 * Reads the next entry in the directory returning extended information.
    531542 *
  • trunk/src/VBox/Runtime/common/vfs/vfsbase.cpp

    r69718 r69720  
    25402540
    25412541
     2542RTDECL(int) RTVfsDirRemoveDir(RTVFSDIR hVfsDir, const char *pszRelPath, uint32_t fFlags)
     2543{
     2544    /*
     2545     * Validate input.
     2546     */
     2547    RTVFSDIRINTERNAL *pThis = hVfsDir;
     2548    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     2549    AssertReturn(pThis->uMagic == RTVFSDIR_MAGIC, VERR_INVALID_HANDLE);
     2550    AssertPtrReturn(pszRelPath, VERR_INVALID_POINTER);
     2551    AssertReturn(!fFlags, VERR_INVALID_FLAGS);
     2552
     2553    /*
     2554     * Parse the path, it's always relative to the given directory.
     2555     */
     2556    PRTVFSPARSEDPATH pPath;
     2557    int rc = RTVfsParsePathA(pszRelPath, NULL, &pPath);
     2558    if (RT_SUCCESS(rc))
     2559    {
     2560        if (pPath->cComponents > 0)
     2561        {
     2562            /*
     2563             * Tranverse the path, resolving the parent node, not checking for symbolic
     2564             * links in the final element, and ask the directory to remove the subdir.
     2565             */
     2566            RTVFSDIRINTERNAL *pVfsParentDir;
     2567            rc = rtVfsDirTraverseToParent(pThis, pPath, RTPATH_F_ON_LINK, &pVfsParentDir);
     2568            if (RT_SUCCESS(rc))
     2569            {
     2570                const char *pszEntryName = &pPath->szPath[pPath->aoffComponents[pPath->cComponents - 1]];
     2571
     2572                RTVfsLockAcquireWrite(pVfsParentDir->Base.hLock);
     2573                rc = pVfsParentDir->pOps->pfnUnlinkEntry(pVfsParentDir->Base.pvThis, pszEntryName, RTFS_TYPE_DIRECTORY);
     2574                RTVfsLockReleaseWrite(pVfsParentDir->Base.hLock);
     2575
     2576                RTVfsDirRelease(pVfsParentDir);
     2577            }
     2578        }
     2579        else
     2580            rc = VERR_PATH_ZERO_LENGTH;
     2581        RTVfsParsePathFree(pPath);
     2582    }
     2583    return rc;
     2584}
     2585
     2586
     2587
    25422588RTDECL(int) RTVfsDirReadEx(RTVFSDIR hVfsDir, PRTDIRENTRYEX pDirEntry, size_t *pcbDirEntry, RTFSOBJATTRADD enmAddAttr)
    25432589{
  • trunk/src/VBox/Runtime/common/vfs/vfsstddir.cpp

    r69716 r69720  
    443443    if (fType != 0)
    444444    {
     445        if (fType == RTFS_TYPE_DIRECTORY)
     446            return RTDirRelDirRemove(pThis->hDir, pszEntry);
     447
    445448        RTFSOBJINFO ObjInfo;
    446449        int rc = rtVfsStdDir_QueryEntryInfo(pThis, pszEntry, &ObjInfo, RTFSOBJATTRADD_NOTHING);
  • trunk/src/VBox/Runtime/nt/RTErrConvertFromNtStatus.cpp

    r69111 r69720  
    8181        case STATUS_BAD_NETWORK_PATH:       return VERR_NET_PATH_NOT_FOUND;
    8282        case STATUS_NOT_A_DIRECTORY:        return VERR_NOT_A_DIRECTORY;
     83        case STATUS_DIRECTORY_NOT_EMPTY:    return VERR_DIR_NOT_EMPTY;
     84        case STATUS_SHARING_VIOLATION:      return VERR_SHARING_VIOLATION;
    8385
    8486        case STATUS_UNEXPECTED_NETWORK_ERROR:
  • trunk/src/VBox/Runtime/r3/nt/dirrel-r3-nt.cpp

    r69718 r69720  
    217217
    218218
    219 /**
    220  * Creates a directory relative to @a hDir.
    221  *
    222  * @returns IPRT status code.
    223  * @param   hDir            The directory @a pszRelPath is relative to.
    224  * @param   pszRelPath      The relative path to the directory to create.
    225  * @param   fMode           The mode of the new directory.
    226  * @param   fCreate         Create flags, RTDIRCREATE_FLAGS_XXX.
    227  * @param   phSubDir        Where to return the handle of the created directory.
    228  *                          Optional.
    229  *
    230  * @sa      RTDirCreate
    231  */
    232219RTDECL(int) RTDirRelDirCreate(PRTDIR hDir, const char *pszRelPath, RTFMODE fMode, uint32_t fCreate, PRTDIR *phSubDir)
    233220{
     
    321308
    322309
    323 /**
    324  * Removes a directory relative to @a hDir if empty.
    325  *
    326  * @returns IPRT status code.
    327  * @param   hDir            The directory @a pszRelPath is relative to.
    328  * @param   pszRelPath      The relative path to the directory to remove.
    329  *
    330  * @sa      RTDirRemove
    331  */
    332310RTDECL(int) RTDirRelDirRemove(PRTDIR hDir, const char *pszRelPath)
    333311{
     
    336314    AssertReturn(pThis->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE);
    337315
    338 
    339     char szPath[RTPATH_MAX];
    340     int rc = rtDirRelBuildFullPath(pThis, szPath, sizeof(szPath), pszRelPath);
    341     if (RT_SUCCESS(rc))
    342     {
    343 RTAssertMsg2("DBG: RTDirRelDirRemove(%s)...\n", szPath);
    344         rc = RTDirRemove(szPath);
     316    /*
     317     * Convert and normalize the path.
     318     */
     319    UNICODE_STRING NtName;
     320    HANDLE hRoot = pThis->hDir;
     321    int rc = RTNtPathRelativeFromUtf8(&NtName, &hRoot, pszRelPath, RTDIRREL_NT_GET_ASCENT(pThis),
     322                                      pThis->enmInfoClass == FileMaximumInformation);
     323    if (RT_SUCCESS(rc))
     324    {
     325        HANDLE              hSubDir = RTNT_INVALID_HANDLE_VALUE;
     326        IO_STATUS_BLOCK     Ios     = RTNT_IO_STATUS_BLOCK_INITIALIZER;
     327        OBJECT_ATTRIBUTES   ObjAttr;
     328        InitializeObjectAttributes(&ObjAttr, &NtName, 0 /*fAttrib*/, hRoot, NULL);
     329
     330        NTSTATUS rcNt = NtCreateFile(&hSubDir,
     331                                     DELETE | SYNCHRONIZE,
     332                                     &ObjAttr,
     333                                     &Ios,
     334                                     NULL /*AllocationSize*/,
     335                                     FILE_ATTRIBUTE_NORMAL,
     336                                     FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
     337                                     FILE_OPEN,
     338                                     FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_REPARSE_POINT,
     339                                     NULL /*EaBuffer*/,
     340                                     0 /*EaLength*/);
     341        if (NT_SUCCESS(rcNt))
     342        {
     343            FILE_DISPOSITION_INFORMATION DispInfo;
     344            DispInfo.DeleteFile = TRUE;
     345            RTNT_IO_STATUS_BLOCK_REINIT(&Ios);
     346            rcNt = NtSetInformationFile(hSubDir, &Ios, &DispInfo, sizeof(DispInfo), FileDispositionInformation);
     347
     348            NTSTATUS rcNt2 = NtClose(hSubDir);
     349            if (!NT_SUCCESS(rcNt2) && NT_SUCCESS(rcNt))
     350                rcNt = rcNt2;
     351        }
     352
     353        if (NT_SUCCESS(rcNt))
     354            rc = VINF_SUCCESS;
     355        else
     356            rc = RTErrConvertFromNtStatus(rcNt);
     357
     358        RTNtPathFree(&NtName, NULL);
    345359    }
    346360    return rc;
  • trunk/src/VBox/Runtime/tools/Makefile.kmk

    r69716 r69720  
    118118 RTMkDir_SOURCES = RTMkDir.cpp
    119119
     120 # RTRmDir - our mkdir clone.
     121 PROGRAMS += RTRmDir
     122 RTRmDir_TEMPLATE = VBoxR3Tool
     123 RTRmDir_SOURCES = RTRmDir.cpp
     124
    120125 # RTShutdown - similar (but not identical) to a typical unix shutdown command.
    121126 PROGRAMS += RTShutdown
  • trunk/src/VBox/Runtime/tools/RTMkDir.cpp

    r69718 r69720  
    108108                if (RT_FAILURE(rc))
    109109                    RTVfsChainMsgError("RTVfsChainOpenDir", pszSpec, rc, offError, &ErrInfo.Core);
     110                else if (!pszFinalPath)
     111                    pszFinalPath = RTStrEnd(pszSpec, RTSTR_MAX);
    110112            }
    111113            else if (!RTPathStartsWithRoot(pszFinalPath))
  • trunk/src/VBox/Runtime/tools/RTRmDir.cpp

    r69718 r69720  
    11/* $Id$ */
    22/** @file
    3  * IPRT - Creates directory.
     3 * IPRT - Removes directory.
    44 */
    55
     
    4444*   Structures and Typedefs                                                                                                      *
    4545*********************************************************************************************************************************/
    46 typedef struct RTCMDMKDIROPTS
     46typedef struct RTCMDRMDIROPTS
    4747{
    4848    /** -v, --verbose */
     
    5050    /** -p, --parents */
    5151    bool        fParents;
     52    /** Don't fail if directories that aren't empty. */
     53    bool        fIgnoreNotEmpty;
     54    /** Don't fail a directory doesn't exist (i.e. has already been removed). */
     55    bool        fIgnoreNonExisting;
    5256    /** Whether to always use the VFS chain API (for testing). */
    5357    bool        fAlwaysUseChainApi;
    54     /** Directory creation flags (RTDIRCREATE_FLAGS_XXX).   */
    55     uint32_t    fCreateFlags;
    56     /** The directory mode. */
    57     RTFMODE     fMode;
    58 } RTCMDMKDIROPTS;
     58} RTCMDRMDIROPTS;
    5959
    6060
     
    6666 * @param   pszDir              The path to the new directory.
    6767 */
    68 static int rtCmdMkDirOneWithParents(RTCMDMKDIROPTS const *pOpts, const char *pszDir)
    69 {
     68static int rtCmdRmDirOneWithParents(RTCMDRMDIROPTS const *pOpts, const char *pszDir)
     69{
     70    /* We need a copy we can work with here. */
     71    char *pszCopy = RTStrDup(pszDir);
     72    if (!pszCopy)
     73        return RTMsgErrorExitFailure("Out of string memory!");
     74
    7075    int rc;
    7176    if (!pOpts->fAlwaysUseChainApi && !RTVfsChainIsSpec(pszDir) )
    7277    {
    73         /*
    74          * Use the API for doing the entire job.  Unfortuantely, this means we
    75          * can't be very  verbose about what we're doing.
    76          */
    77         rc = RTDirCreateFullPath(pszDir, pOpts->fMode);
    78         if (RT_FAILURE(rc))
    79             RTMsgError("Failed to create directory '%s' (or a parent): %Rrc", pszDir, rc);
    80         else if (pOpts->fVerbose)
    81             RTPrintf("%s\n", pszDir);
     78        size_t cchCopy = strlen(pszCopy);
     79        do
     80        {
     81            rc = RTDirRemove(pszCopy);
     82            if (RT_SUCCESS(rc))
     83            {
     84                if (pOpts->fVerbose)
     85                    RTPrintf("%s\n", pszCopy);
     86            }
     87            else if ((rc == VERR_PATH_NOT_FOUND || rc == VERR_FILE_NOT_FOUND) && pOpts->fIgnoreNonExisting)
     88                rc = VINF_SUCCESS;
     89            else
     90            {
     91                if ((rc == VERR_DIR_NOT_EMPTY || rc == VERR_SHARING_VIOLATION) && pOpts->fIgnoreNotEmpty)
     92                    rc = VINF_SUCCESS;
     93                else
     94                    RTMsgError("Failed to remove directory '%s': %Rrc", pszCopy, rc);
     95                break;
     96            }
     97
     98            /* Strip off a component. */
     99            while (cchCopy > 0 && RTPATH_IS_SLASH(pszCopy[cchCopy - 1]))
     100                cchCopy--;
     101            while (cchCopy > 0 && !RTPATH_IS_SLASH(pszCopy[cchCopy - 1]))
     102                cchCopy--;
     103            while (cchCopy > 0 && RTPATH_IS_SLASH(pszCopy[cchCopy - 1]))
     104                cchCopy--;
     105            pszCopy[cchCopy] = '\0';
     106        } while (cchCopy > 0);
    82107    }
    83108    else
     
    86111         * Strip the final path element from the pszDir spec.
    87112         */
    88         char *pszCopy = RTStrDup(pszDir);
    89         if (!pszCopy)
    90             return RTMsgErrorExitFailure("Out of string memory!");
    91 
    92113        char       *pszFinalPath;
    93114        char       *pszSpec;
     
    96117        if (RT_SUCCESS(rc))
    97118        {
    98             const char * const pszFullFinalPath = pszFinalPath;
    99 
    100119            /*
    101120             * Open the root director/whatever.
    102121             */
    103122            RTERRINFOSTATIC ErrInfo;
    104             RTVFSDIR hVfsCurDir;
     123            RTVFSDIR hVfsBaseDir;
    105124            if (pszSpec)
    106125            {
    107                 rc = RTVfsChainOpenDir(pszSpec, 0 /*fOpen*/, &hVfsCurDir, &offError, RTErrInfoInitStatic(&ErrInfo));
     126                rc = RTVfsChainOpenDir(pszSpec, 0 /*fOpen*/, &hVfsBaseDir, &offError, RTErrInfoInitStatic(&ErrInfo));
    108127                if (RT_FAILURE(rc))
    109128                    RTVfsChainMsgError("RTVfsChainOpenDir", pszSpec, rc, offError, &ErrInfo.Core);
     129                else if (!pszFinalPath)
     130                    pszFinalPath = RTStrEnd(pszSpec, RTSTR_MAX);
    110131            }
    111132            else if (!RTPathStartsWithRoot(pszFinalPath))
    112133            {
    113                 rc = RTVfsDirOpenNormal(".", 0 /*fOpen*/, &hVfsCurDir);
     134                rc = RTVfsDirOpenNormal(".", 0 /*fOpen*/, &hVfsBaseDir);
    114135                if (RT_FAILURE(rc))
    115136                    RTMsgError("Failed to open '.' (for %s): %Rrc", rc, pszFinalPath);
     
    121142                char const chSaved = *pszFinalPath;
    122143                *pszFinalPath = '\0';
    123                 rc = RTVfsDirOpenNormal(pszRoot, 0 /*fOpen*/, &hVfsCurDir);
     144                rc = RTVfsDirOpenNormal(pszRoot, 0 /*fOpen*/, &hVfsBaseDir);
    124145                *pszFinalPath = chSaved;
    125146                if (RT_FAILURE(rc))
     
    128149
    129150            /*
    130              * Walk the path component by component.
     151             * Walk the path component by component, starting at the end.
    131152             */
    132             while (RT_SUCCESS(rc))
    133             {
    134                 /*
    135                  * Strip leading slashes.
    136                  */
    137                 while (RTPATH_IS_SLASH(*pszFinalPath))
    138                     pszFinalPath++;
    139                 if (*pszFinalPath == '\0')
     153            if (RT_SUCCESS(rc))
     154            {
     155                size_t cchFinalPath = strlen(pszFinalPath);
     156                while (RT_SUCCESS(rc) && cchFinalPath > 0)
    140157                {
    141                     RTVfsDirRelease(hVfsCurDir);
    142                     break;
    143                 }
    144 
    145                 /*
    146                  * Find the end of the next path component.
    147                  */
    148                 size_t cchComponent = 0;
    149                 char   ch;
    150                 while (   (ch = pszFinalPath[cchComponent]) != '\0'
    151                        && !RTPATH_IS_SLASH(ch))
    152                     cchComponent++;
    153 
    154                 /*
    155                  * Open or create the component.
    156                  */
    157                 pszFinalPath[cchComponent] = '\0';
    158                 RTVFSDIR hVfsNextDir = NIL_RTVFSDIR;
    159                 for (uint32_t cTries = 0; cTries < 8; cTries++)
    160                 {
    161                     /* Try open it. */
    162                     rc = RTVfsDirOpenDir(hVfsCurDir, pszFinalPath, 0 /*fFlags*/, &hVfsNextDir);
     158                    rc = RTVfsDirRemoveDir(hVfsBaseDir, pszFinalPath, 0 /*fFlags*/);
    163159                    if (RT_SUCCESS(rc))
    164                         break;
    165                     if (   rc != VERR_FILE_NOT_FOUND
    166                         && rc != VERR_PATH_NOT_FOUND)
    167160                    {
    168                         if (ch == '\0')
    169                             RTMsgError("Failed opening directory '%s': %Rrc", pszDir, rc);
     161                        if (pOpts->fVerbose)
     162                            RTPrintf("%s\n", pszCopy);
     163                    }
     164                    else if ((rc == VERR_PATH_NOT_FOUND || rc == VERR_FILE_NOT_FOUND) && pOpts->fIgnoreNonExisting)
     165                        rc = VINF_SUCCESS;
     166                    else
     167                    {
     168                        if ((rc == VERR_DIR_NOT_EMPTY || rc == VERR_SHARING_VIOLATION) && pOpts->fIgnoreNotEmpty)
     169                            rc = VINF_SUCCESS;
     170                        else if (pszSpec)
     171                            RTMsgError("Failed to remove directory '%s:%s': %Rrc", pszSpec, pszFinalPath, rc);
    170172                        else
    171                             RTMsgError("Failed opening dir '%s' (for creating '%s'): %Rrc", pszFullFinalPath, pszDir, rc);
     173                            RTMsgError("Failed to remove directory '%s': %Rrc", pszFinalPath, rc);
    172174                        break;
    173175                    }
    174176
    175                     /* Not found, so try create it. */
    176                     rc = RTVfsDirCreateDir(hVfsCurDir, pszFinalPath, pOpts->fMode, pOpts->fCreateFlags, &hVfsNextDir);
    177                     if (rc == VERR_ALREADY_EXISTS)
    178                         continue; /* We lost a creation race, try again. */
    179                     if (RT_SUCCESS(rc) && pOpts->fVerbose)
    180                     {
    181                         if (pszSpec)
    182                             RTPrintf("%s:%s\n", pszSpec, pszFullFinalPath);
    183                         else
    184                             RTPrintf("%s\n", pszFullFinalPath);
    185                     }
    186                     else if (RT_FAILURE(rc))
    187                     {
    188                         if (ch == '\0')
    189                             RTMsgError("Failed creating directory '%s': %Rrc", pszDir, rc);
    190                         else
    191                             RTMsgError("Failed creating dir '%s' (for '%s'): %Rrc", pszFullFinalPath, pszDir, rc);
    192                     }
    193                     break;
     177                    /* Strip off a component. */
     178                    while (cchFinalPath > 0 && RTPATH_IS_SLASH(pszFinalPath[cchFinalPath - 1]))
     179                        cchFinalPath--;
     180                    while (cchFinalPath > 0 && !RTPATH_IS_SLASH(pszFinalPath[cchFinalPath - 1]))
     181                        cchFinalPath--;
     182                    while (cchFinalPath > 0 && RTPATH_IS_SLASH(pszFinalPath[cchFinalPath - 1]))
     183                        cchFinalPath--;
     184                    pszFinalPath[cchFinalPath] = '\0';
    194185                }
    195                 pszFinalPath[cchComponent] = ch;
    196 
    197                 RTVfsDirRelease(hVfsCurDir);
    198                 hVfsCurDir = hVfsNextDir;
    199                 pszFinalPath += cchComponent;
     186
     187                RTVfsDirRelease(hVfsBaseDir);
    200188            }
    201189        }
    202190        else
    203191            RTVfsChainMsgError("RTVfsChainOpenParentDir", pszCopy, rc, offError, NULL);
    204         RTStrFree(pszCopy);
    205     }
     192    }
     193    RTStrFree(pszCopy);
    206194    return RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
    207195}
     
    209197
    210198/**
    211  * Create one directory.
     199 * Removes one directory.
    212200 *
    213201 * @returns exit code
     
    215203 * @param   pszDir              The path to the new directory.
    216204 */
    217 static RTEXITCODE rtCmdMkDirOne(RTCMDMKDIROPTS const *pOpts, const char *pszDir)
     205static RTEXITCODE rtCmdRmDirOne(RTCMDRMDIROPTS const *pOpts, const char *pszDir)
    218206{
    219207    int rc;
    220208    if (!pOpts->fAlwaysUseChainApi && !RTVfsChainIsSpec(pszDir) )
    221         rc = RTDirCreate(pszDir, pOpts->fMode, 0);
     209        rc = RTDirRemove(pszDir);
    222210    else
    223211    {
     
    229217        if (RT_SUCCESS(rc))
    230218        {
    231             rc = RTVfsDirCreateDir(hVfsDir, pszChild, pOpts->fMode, 0 /*fFlags*/, NULL);
     219            rc = RTVfsDirRemoveDir(hVfsDir, pszChild, 0 /*fFlags*/);
    232220            RTVfsDirRelease(hVfsDir);
    233221        }
     
    241229        return RTEXITCODE_SUCCESS;
    242230    }
    243     return RTMsgErrorExitFailure("Failed to create '%s': %Rrc", pszDir, rc);
     231    if ((rc == VERR_DIR_NOT_EMPTY || rc == VERR_SHARING_VIOLATION) && pOpts->fIgnoreNotEmpty)
     232        return RTEXITCODE_SUCCESS; /** @todo be verbose about this? */
     233    if ((rc == VERR_PATH_NOT_FOUND || rc == VERR_FILE_NOT_FOUND) && pOpts->fIgnoreNonExisting)
     234        return RTEXITCODE_SUCCESS; /** @todo be verbose about this? */
     235    return RTMsgErrorExitFailure("Failed to remove '%s': %Rrc", pszDir, rc);
    244236}
    245237
    246238
    247 static RTEXITCODE RTCmdMkDir(unsigned cArgs,  char **papszArgs)
     239static RTEXITCODE RTCmdRmDir(unsigned cArgs,  char **papszArgs)
    248240{
    249241    /*
     
    253245    {
    254246        /* operations */
    255         { "--mode",                     'm', RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_OCT },
    256247        { "--parents",                  'p', RTGETOPT_REQ_NOTHING },
     248        { "--ignore-fail-on-non-empty", 'F', RTGETOPT_REQ_NOTHING },
     249        { "--ignore-non-existing",      'E', RTGETOPT_REQ_NOTHING },
    257250        { "--always-use-vfs-chain-api", 'A', RTGETOPT_REQ_NOTHING },
    258         { "--allow-content-indexing",   'i', RTGETOPT_REQ_NOTHING },
    259251        { "--verbose",                  'v', RTGETOPT_REQ_NOTHING },
    260252    };
     
    266258        return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTGetOpt failed: %Rrc", rc);
    267259
    268     RTCMDMKDIROPTS Opts;
     260    RTCMDRMDIROPTS Opts;
    269261    Opts.fVerbose               = false;
    270262    Opts.fParents               = false;
     263    Opts.fIgnoreNotEmpty        = false;
     264    Opts.fIgnoreNonExisting     = false;
    271265    Opts.fAlwaysUseChainApi     = false;
    272     Opts.fCreateFlags           = RTDIRCREATE_FLAGS_NOT_CONTENT_INDEXED_NOT_CRITICAL | RTDIRCREATE_FLAGS_NOT_CONTENT_INDEXED_SET;
    273     Opts.fMode                  = 0775 | RTFS_TYPE_DIRECTORY | RTFS_DOS_DIRECTORY;
    274266
    275267    RTGETOPTUNION ValueUnion;
     
    279271        switch (rc)
    280272        {
    281             case 'm':
    282                 /** @todo DOS+NT attributes and symbolic notation. */
    283                 Opts.fMode &= ~07777;
    284                 Opts.fMode |= ValueUnion.u32 & 07777;
    285                 break;
    286 
    287273            case 'p':
    288274                Opts.fParents = true;
     
    297283                break;
    298284
    299             case 'i':
    300                 Opts.fCreateFlags &= ~RTDIRCREATE_FLAGS_NOT_CONTENT_INDEXED_SET;
    301                 Opts.fCreateFlags |= RTDIRCREATE_FLAGS_NOT_CONTENT_INDEXED_DONT_SET;
     285            case 'E':
     286                Opts.fIgnoreNonExisting = true;
     287                break;
     288
     289            case 'F':
     290                Opts.fIgnoreNotEmpty = true;
    302291                break;
    303292
     
    305294                RTPrintf("Usage: %s [options] <dir> [..]\n"
    306295                         "\n"
     296                         "Removes empty directories.\n"
     297                         "\n"
    307298                         "Options:\n"
    308                          "  -m <mode>, --mode <mode>\n"
    309                          "      The creation mode. Default is 0775.\n"
    310299                         "  -p, --parent\n"
    311                          "      Create parent directories too. Ignore any existing directories.\n"
     300                         "      Remove specified parent directories too.\n"
     301                         "  -F, --ignore-fail-on-non-empty\n"
     302                         "      Do not fail if a directory is not empty, just ignore it.\n"
     303                         "      This is really handy with the -p option.\n"
     304                         "  -E, --ignore-non-existing\n"
     305                         "      Do not fail if a specified directory is not there.\n"
    312306                         "  -v, --verbose\n"
    313                          "      Tell which directories get created.\n"
     307                         "      Tell which directories get remove.\n"
    314308                         "  -A, --always-use-vfs-chain-api\n"
    315309                         "      Always use the VFS API.\n"
    316                          "  -i, --allow-content-indexing\n"
    317                          "      Don't set flags to disable context indexing on windows.\n"
    318310                         , papszArgs[0]);
    319311                return RTEXITCODE_SUCCESS;
     
    342334    {
    343335        if (Opts.fParents)
    344             rc = rtCmdMkDirOneWithParents(&Opts, ValueUnion.psz);
     336            rc = rtCmdRmDirOneWithParents(&Opts, ValueUnion.psz);
    345337        else
    346             rc = rtCmdMkDirOne(&Opts, ValueUnion.psz);
     338            rc = rtCmdRmDirOne(&Opts, ValueUnion.psz);
    347339        if (RT_FAILURE(rc))
    348340            rcExit = RTEXITCODE_FAILURE;
     
    363355    if (RT_FAILURE(rc))
    364356        return RTMsgInitFailure(rc);
    365     return RTCmdMkDir(argc, argv);
     357    return RTCmdRmDir(argc, argv);
    366358}
    367359
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