VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/dir2.cpp@ 72915

Last change on this file since 72915 was 69753, checked in by vboxsync, 7 years ago

iprt/dir: Morphing PRTDIR into a handle named RTDIR. (Been wanting to correct this for years. Don't know why I makde it a pointer rather than an abstrct handle like everything else.)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 6.7 KB
Line 
1/* $Id: dir2.cpp 69753 2017-11-19 14:27:58Z vboxsync $ */
2/** @file
3 * IPRT - Directory Manipulation, Part 2.
4 */
5
6/*
7 * Copyright (C) 2006-2017 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#define LOG_GROUP RTLOGGROUP_DIR
32#include <iprt/dir.h>
33#include "internal/iprt.h"
34
35#include <iprt/assert.h>
36#include <iprt/file.h>
37#include <iprt/err.h>
38#include <iprt/log.h>
39#include <iprt/mem.h>
40#include <iprt/param.h>
41#include <iprt/path.h>
42#include <iprt/string.h>
43#include "internal/path.h"
44
45
46/**
47 * Recursion worker for RTDirRemoveRecursive.
48 *
49 * @returns IPRT status code.
50 * @param pszBuf The path buffer. Contains the abs path to the
51 * directory to recurse into. Trailing slash.
52 * @param cchDir The length of the directory we're cursing into,
53 * including the trailing slash.
54 * @param pDirEntry The dir entry buffer. (Shared to save stack.)
55 * @param pObjInfo The object info buffer. (ditto)
56 */
57static int rtDirRemoveRecursiveSub(char *pszBuf, size_t cchDir, PRTDIRENTRY pDirEntry, PRTFSOBJINFO pObjInfo)
58{
59 AssertReturn(RTPATH_IS_SLASH(pszBuf[cchDir - 1]), VERR_INTERNAL_ERROR_4);
60
61 /*
62 * Enumerate the directory content and dispose of it.
63 */
64 RTDIR hDir;
65 int rc = RTDirOpen(&hDir, pszBuf);
66 if (RT_FAILURE(rc))
67 return rc;
68 while (RT_SUCCESS(rc = RTDirRead(hDir, pDirEntry, NULL)))
69 {
70 if (!RTDirEntryIsStdDotLink(pDirEntry))
71 {
72 /* Construct the full name of the entry. */
73 if (cchDir + pDirEntry->cbName + 1 /* dir slash */ >= RTPATH_MAX)
74 {
75 rc = VERR_FILENAME_TOO_LONG;
76 break;
77 }
78 memcpy(&pszBuf[cchDir], pDirEntry->szName, pDirEntry->cbName + 1);
79
80 /* Deal with the unknown type. */
81 if (pDirEntry->enmType == RTDIRENTRYTYPE_UNKNOWN)
82 {
83 rc = RTPathQueryInfoEx(pszBuf, pObjInfo, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
84 if (RT_SUCCESS(rc) && RTFS_IS_DIRECTORY(pObjInfo->Attr.fMode))
85 pDirEntry->enmType = RTDIRENTRYTYPE_DIRECTORY;
86 else if (RT_SUCCESS(rc) && RTFS_IS_FILE(pObjInfo->Attr.fMode))
87 pDirEntry->enmType = RTDIRENTRYTYPE_FILE;
88 else if (RT_SUCCESS(rc) && RTFS_IS_SYMLINK(pObjInfo->Attr.fMode))
89 pDirEntry->enmType = RTDIRENTRYTYPE_SYMLINK;
90 }
91
92 /* Try the delete the fs object. */
93 switch (pDirEntry->enmType)
94 {
95 case RTDIRENTRYTYPE_FILE:
96 rc = RTFileDelete(pszBuf);
97 break;
98
99 case RTDIRENTRYTYPE_DIRECTORY:
100 {
101 size_t cchSubDir = cchDir + pDirEntry->cbName;
102 pszBuf[cchSubDir++] = '/';
103 pszBuf[cchSubDir] = '\0';
104 rc = rtDirRemoveRecursiveSub(pszBuf, cchSubDir, pDirEntry, pObjInfo);
105 if (RT_SUCCESS(rc))
106 {
107 pszBuf[cchSubDir] = '\0';
108 rc = RTDirRemove(pszBuf);
109 }
110 break;
111 }
112
113 //case RTDIRENTRYTYPE_SYMLINK:
114 // rc = RTSymlinkDelete(pszBuf, 0);
115 // break;
116
117 default:
118 /** @todo not implemented yet. */
119 rc = VINF_SUCCESS;
120 break;
121 }
122 if (RT_FAILURE(rc))
123 break;
124 }
125 }
126 if (rc == VERR_NO_MORE_FILES)
127 rc = VINF_SUCCESS;
128 RTDirClose(hDir);
129 return rc;
130}
131
132
133RTDECL(int) RTDirRemoveRecursive(const char *pszPath, uint32_t fFlags)
134{
135 AssertReturn(!(fFlags & ~RTDIRRMREC_F_VALID_MASK), VERR_INVALID_PARAMETER);
136
137 /* Get an absolute path because this is easier to work with. */
138 /** @todo use RTPathReal here instead? */
139 char szAbsPath[RTPATH_MAX];
140 int rc = RTPathAbs(pszPath, szAbsPath, sizeof(szAbsPath));
141 if (RT_FAILURE(rc))
142 return rc;
143
144 /* This API is not permitted applied to the root of anything. */
145 if (RTPathCountComponents(szAbsPath) <= 1)
146 return VERR_ACCESS_DENIED;
147
148 /* Because of the above restriction, we never have to deal with the root
149 slash problem and can safely strip any trailing slashes and add a
150 definite one. */
151 RTPathStripTrailingSlash(szAbsPath);
152 size_t cchAbsPath = strlen(szAbsPath);
153 if (cchAbsPath + 1 >= RTPATH_MAX)
154 return VERR_FILENAME_TOO_LONG;
155 szAbsPath[cchAbsPath++] = '/';
156 szAbsPath[cchAbsPath] = 0;
157
158 /* Check if it exists so we can return quietly if it doesn't. */
159 RTFSOBJINFO SharedObjInfoBuf;
160 rc = RTPathQueryInfoEx(szAbsPath, &SharedObjInfoBuf, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
161 if ( rc == VERR_PATH_NOT_FOUND
162 || rc == VERR_FILE_NOT_FOUND)
163 return VINF_SUCCESS;
164 if (RT_FAILURE(rc))
165 return rc;
166 if (!RTFS_IS_DIRECTORY(SharedObjInfoBuf.Attr.fMode))
167 return VERR_NOT_A_DIRECTORY;
168
169 /* We're all set for the recursion now, so get going. */
170 RTDIRENTRY SharedDirEntryBuf;
171 rc = rtDirRemoveRecursiveSub(szAbsPath, cchAbsPath, &SharedDirEntryBuf, &SharedObjInfoBuf);
172
173 /* Remove the specified directory if desired and removing the content was
174 successful. */
175 if ( RT_SUCCESS(rc)
176 && !(fFlags & RTDIRRMREC_F_CONTENT_ONLY))
177 {
178 szAbsPath[cchAbsPath] = 0;
179 rc = RTDirRemove(szAbsPath);
180 }
181 return rc;
182}
183
Note: See TracBrowser for help on using the repository browser.

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