- Timestamp:
- Nov 16, 2017 4:18:19 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 8 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/mangling.h
r69716 r69720 2438 2438 # define RTVfsDirQueryPathInfo RT_MANGLER(RTVfsDirQueryPathInfo) 2439 2439 # define RTVfsDirReadEx RT_MANGLER(RTVfsDirReadEx) 2440 # define RTVfsDirRemoveDir RT_MANGLER(RTVfsDirRemoveDir) 2440 2441 # define RTVfsFileFlush RT_MANGLER(RTVfsFileFlush) 2441 2442 # define RTVfsFileFromBuffer RT_MANGLER(RTVfsFileFromBuffer) -
trunk/include/iprt/vfs.h
r69716 r69720 528 528 529 529 /** 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 */ 538 RTDECL(int) RTVfsDirRemoveDir(RTVFSDIR hVfsDir, const char *pszRelPath, uint32_t fFlags); 539 540 /** 530 541 * Reads the next entry in the directory returning extended information. 531 542 * -
trunk/src/VBox/Runtime/common/vfs/vfsbase.cpp
r69718 r69720 2540 2540 2541 2541 2542 RTDECL(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 2542 2588 RTDECL(int) RTVfsDirReadEx(RTVFSDIR hVfsDir, PRTDIRENTRYEX pDirEntry, size_t *pcbDirEntry, RTFSOBJATTRADD enmAddAttr) 2543 2589 { -
trunk/src/VBox/Runtime/common/vfs/vfsstddir.cpp
r69716 r69720 443 443 if (fType != 0) 444 444 { 445 if (fType == RTFS_TYPE_DIRECTORY) 446 return RTDirRelDirRemove(pThis->hDir, pszEntry); 447 445 448 RTFSOBJINFO ObjInfo; 446 449 int rc = rtVfsStdDir_QueryEntryInfo(pThis, pszEntry, &ObjInfo, RTFSOBJATTRADD_NOTHING); -
trunk/src/VBox/Runtime/nt/RTErrConvertFromNtStatus.cpp
r69111 r69720 81 81 case STATUS_BAD_NETWORK_PATH: return VERR_NET_PATH_NOT_FOUND; 82 82 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; 83 85 84 86 case STATUS_UNEXPECTED_NETWORK_ERROR: -
trunk/src/VBox/Runtime/r3/nt/dirrel-r3-nt.cpp
r69718 r69720 217 217 218 218 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 RTDirCreate231 */232 219 RTDECL(int) RTDirRelDirCreate(PRTDIR hDir, const char *pszRelPath, RTFMODE fMode, uint32_t fCreate, PRTDIR *phSubDir) 233 220 { … … 321 308 322 309 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 RTDirRemove331 */332 310 RTDECL(int) RTDirRelDirRemove(PRTDIR hDir, const char *pszRelPath) 333 311 { … … 336 314 AssertReturn(pThis->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE); 337 315 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); 345 359 } 346 360 return rc; -
trunk/src/VBox/Runtime/tools/Makefile.kmk
r69716 r69720 118 118 RTMkDir_SOURCES = RTMkDir.cpp 119 119 120 # RTRmDir - our mkdir clone. 121 PROGRAMS += RTRmDir 122 RTRmDir_TEMPLATE = VBoxR3Tool 123 RTRmDir_SOURCES = RTRmDir.cpp 124 120 125 # RTShutdown - similar (but not identical) to a typical unix shutdown command. 121 126 PROGRAMS += RTShutdown -
trunk/src/VBox/Runtime/tools/RTMkDir.cpp
r69718 r69720 108 108 if (RT_FAILURE(rc)) 109 109 RTVfsChainMsgError("RTVfsChainOpenDir", pszSpec, rc, offError, &ErrInfo.Core); 110 else if (!pszFinalPath) 111 pszFinalPath = RTStrEnd(pszSpec, RTSTR_MAX); 110 112 } 111 113 else if (!RTPathStartsWithRoot(pszFinalPath)) -
trunk/src/VBox/Runtime/tools/RTRmDir.cpp
r69718 r69720 1 1 /* $Id$ */ 2 2 /** @file 3 * IPRT - Creates directory.3 * IPRT - Removes directory. 4 4 */ 5 5 … … 44 44 * Structures and Typedefs * 45 45 *********************************************************************************************************************************/ 46 typedef struct RTCMD MKDIROPTS46 typedef struct RTCMDRMDIROPTS 47 47 { 48 48 /** -v, --verbose */ … … 50 50 /** -p, --parents */ 51 51 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; 52 56 /** Whether to always use the VFS chain API (for testing). */ 53 57 bool fAlwaysUseChainApi; 54 /** Directory creation flags (RTDIRCREATE_FLAGS_XXX). */ 55 uint32_t fCreateFlags; 56 /** The directory mode. */ 57 RTFMODE fMode; 58 } RTCMDMKDIROPTS; 58 } RTCMDRMDIROPTS; 59 59 60 60 … … 66 66 * @param pszDir The path to the new directory. 67 67 */ 68 static int rtCmdMkDirOneWithParents(RTCMDMKDIROPTS const *pOpts, const char *pszDir) 69 { 68 static 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 70 75 int rc; 71 76 if (!pOpts->fAlwaysUseChainApi && !RTVfsChainIsSpec(pszDir) ) 72 77 { 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); 82 107 } 83 108 else … … 86 111 * Strip the final path element from the pszDir spec. 87 112 */ 88 char *pszCopy = RTStrDup(pszDir);89 if (!pszCopy)90 return RTMsgErrorExitFailure("Out of string memory!");91 92 113 char *pszFinalPath; 93 114 char *pszSpec; … … 96 117 if (RT_SUCCESS(rc)) 97 118 { 98 const char * const pszFullFinalPath = pszFinalPath;99 100 119 /* 101 120 * Open the root director/whatever. 102 121 */ 103 122 RTERRINFOSTATIC ErrInfo; 104 RTVFSDIR hVfs CurDir;123 RTVFSDIR hVfsBaseDir; 105 124 if (pszSpec) 106 125 { 107 rc = RTVfsChainOpenDir(pszSpec, 0 /*fOpen*/, &hVfs CurDir, &offError, RTErrInfoInitStatic(&ErrInfo));126 rc = RTVfsChainOpenDir(pszSpec, 0 /*fOpen*/, &hVfsBaseDir, &offError, RTErrInfoInitStatic(&ErrInfo)); 108 127 if (RT_FAILURE(rc)) 109 128 RTVfsChainMsgError("RTVfsChainOpenDir", pszSpec, rc, offError, &ErrInfo.Core); 129 else if (!pszFinalPath) 130 pszFinalPath = RTStrEnd(pszSpec, RTSTR_MAX); 110 131 } 111 132 else if (!RTPathStartsWithRoot(pszFinalPath)) 112 133 { 113 rc = RTVfsDirOpenNormal(".", 0 /*fOpen*/, &hVfs CurDir);134 rc = RTVfsDirOpenNormal(".", 0 /*fOpen*/, &hVfsBaseDir); 114 135 if (RT_FAILURE(rc)) 115 136 RTMsgError("Failed to open '.' (for %s): %Rrc", rc, pszFinalPath); … … 121 142 char const chSaved = *pszFinalPath; 122 143 *pszFinalPath = '\0'; 123 rc = RTVfsDirOpenNormal(pszRoot, 0 /*fOpen*/, &hVfs CurDir);144 rc = RTVfsDirOpenNormal(pszRoot, 0 /*fOpen*/, &hVfsBaseDir); 124 145 *pszFinalPath = chSaved; 125 146 if (RT_FAILURE(rc)) … … 128 149 129 150 /* 130 * Walk the path component by component .151 * Walk the path component by component, starting at the end. 131 152 */ 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) 140 157 { 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*/); 163 159 if (RT_SUCCESS(rc)) 164 break;165 if ( rc != VERR_FILE_NOT_FOUND166 && rc != VERR_PATH_NOT_FOUND)167 160 { 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); 170 172 else 171 RTMsgError("Failed opening dir '%s' (for creating '%s'): %Rrc", pszFullFinalPath, pszDir, rc);173 RTMsgError("Failed to remove directory '%s': %Rrc", pszFinalPath, rc); 172 174 break; 173 175 } 174 176 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'; 194 185 } 195 pszFinalPath[cchComponent] = ch; 196 197 RTVfsDirRelease(hVfsCurDir); 198 hVfsCurDir = hVfsNextDir; 199 pszFinalPath += cchComponent; 186 187 RTVfsDirRelease(hVfsBaseDir); 200 188 } 201 189 } 202 190 else 203 191 RTVfsChainMsgError("RTVfsChainOpenParentDir", pszCopy, rc, offError, NULL); 204 RTStrFree(pszCopy);205 }192 } 193 RTStrFree(pszCopy); 206 194 return RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; 207 195 } … … 209 197 210 198 /** 211 * Createone directory.199 * Removes one directory. 212 200 * 213 201 * @returns exit code … … 215 203 * @param pszDir The path to the new directory. 216 204 */ 217 static RTEXITCODE rtCmd MkDirOne(RTCMDMKDIROPTS const *pOpts, const char *pszDir)205 static RTEXITCODE rtCmdRmDirOne(RTCMDRMDIROPTS const *pOpts, const char *pszDir) 218 206 { 219 207 int rc; 220 208 if (!pOpts->fAlwaysUseChainApi && !RTVfsChainIsSpec(pszDir) ) 221 rc = RTDir Create(pszDir, pOpts->fMode, 0);209 rc = RTDirRemove(pszDir); 222 210 else 223 211 { … … 229 217 if (RT_SUCCESS(rc)) 230 218 { 231 rc = RTVfsDir CreateDir(hVfsDir, pszChild, pOpts->fMode, 0 /*fFlags*/, NULL);219 rc = RTVfsDirRemoveDir(hVfsDir, pszChild, 0 /*fFlags*/); 232 220 RTVfsDirRelease(hVfsDir); 233 221 } … … 241 229 return RTEXITCODE_SUCCESS; 242 230 } 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); 244 236 } 245 237 246 238 247 static RTEXITCODE RTCmd MkDir(unsigned cArgs, char **papszArgs)239 static RTEXITCODE RTCmdRmDir(unsigned cArgs, char **papszArgs) 248 240 { 249 241 /* … … 253 245 { 254 246 /* operations */ 255 { "--mode", 'm', RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_OCT },256 247 { "--parents", 'p', RTGETOPT_REQ_NOTHING }, 248 { "--ignore-fail-on-non-empty", 'F', RTGETOPT_REQ_NOTHING }, 249 { "--ignore-non-existing", 'E', RTGETOPT_REQ_NOTHING }, 257 250 { "--always-use-vfs-chain-api", 'A', RTGETOPT_REQ_NOTHING }, 258 { "--allow-content-indexing", 'i', RTGETOPT_REQ_NOTHING },259 251 { "--verbose", 'v', RTGETOPT_REQ_NOTHING }, 260 252 }; … … 266 258 return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTGetOpt failed: %Rrc", rc); 267 259 268 RTCMD MKDIROPTS Opts;260 RTCMDRMDIROPTS Opts; 269 261 Opts.fVerbose = false; 270 262 Opts.fParents = false; 263 Opts.fIgnoreNotEmpty = false; 264 Opts.fIgnoreNonExisting = false; 271 265 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;274 266 275 267 RTGETOPTUNION ValueUnion; … … 279 271 switch (rc) 280 272 { 281 case 'm':282 /** @todo DOS+NT attributes and symbolic notation. */283 Opts.fMode &= ~07777;284 Opts.fMode |= ValueUnion.u32 & 07777;285 break;286 287 273 case 'p': 288 274 Opts.fParents = true; … … 297 283 break; 298 284 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; 302 291 break; 303 292 … … 305 294 RTPrintf("Usage: %s [options] <dir> [..]\n" 306 295 "\n" 296 "Removes empty directories.\n" 297 "\n" 307 298 "Options:\n" 308 " -m <mode>, --mode <mode>\n"309 " The creation mode. Default is 0775.\n"310 299 " -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" 312 306 " -v, --verbose\n" 313 " Tell which directories get created.\n"307 " Tell which directories get remove.\n" 314 308 " -A, --always-use-vfs-chain-api\n" 315 309 " Always use the VFS API.\n" 316 " -i, --allow-content-indexing\n"317 " Don't set flags to disable context indexing on windows.\n"318 310 , papszArgs[0]); 319 311 return RTEXITCODE_SUCCESS; … … 342 334 { 343 335 if (Opts.fParents) 344 rc = rtCmd MkDirOneWithParents(&Opts, ValueUnion.psz);336 rc = rtCmdRmDirOneWithParents(&Opts, ValueUnion.psz); 345 337 else 346 rc = rtCmd MkDirOne(&Opts, ValueUnion.psz);338 rc = rtCmdRmDirOne(&Opts, ValueUnion.psz); 347 339 if (RT_FAILURE(rc)) 348 340 rcExit = RTEXITCODE_FAILURE; … … 363 355 if (RT_FAILURE(rc)) 364 356 return RTMsgInitFailure(rc); 365 return RTCmd MkDir(argc, argv);357 return RTCmdRmDir(argc, argv); 366 358 } 367 359
Note:
See TracChangeset
for help on using the changeset viewer.