summaryrefslogtreecommitdiff
path: root/lib/System/Unix/Path.inc
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2008-04-03 16:11:31 +0000
committerTed Kremenek <kremenek@apple.com>2008-04-03 16:11:31 +0000
commitc5412c58d2dd6c89e4b03c7c446d69a6b01e7a3f (patch)
treeb6f4b548e180389ae59a8c8d8fea9e6f53d48130 /lib/System/Unix/Path.inc
parent43b7ca15a3f5c80847e078d2201e935ffc3e0e4a (diff)
downloadllvm-c5412c58d2dd6c89e4b03c7c446d69a6b01e7a3f.tar.gz
llvm-c5412c58d2dd6c89e4b03c7c446d69a6b01e7a3f.tar.bz2
llvm-c5412c58d2dd6c89e4b03c7c446d69a6b01e7a3f.tar.xz
Re-implemented Path::createDirectoryOnDisk (for Unix).
This method allows one to create a directory, and optionally create all parent directories that do not exist. The original implementation would require that *all* directories along a path are writable by the user, including directories that already exist. For example, suppose we wanted to create the directory "/tmp/foo/bar", and the directory "/tmp" already exists, but not "/tmp/foo". Since "/tmp" is writable by all users, the original implementation would work, and create "/tmp/foo", followed by "/tmp/bar". A problem occurred, however if one wanted to created the directory "/Users/myuser/bar" (or equivalently "/home/myuser/bar"), and "/Users/myuser" already existed and is writable by the current user. The directory "/User/myuser" is writable by the user, but "/User" is not. The original implementation of createDirectoryOnDisk would return with failure since "/User" is not writable, even though "/User/mysuser" is writable. The new implementation works by recursively creating parents as needed, and thus doesn't need to check the permissions on every directory in a path. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@49162 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/System/Unix/Path.inc')
-rw-r--r--lib/System/Unix/Path.inc71
1 files changed, 39 insertions, 32 deletions
diff --git a/lib/System/Unix/Path.inc b/lib/System/Unix/Path.inc
index 2f24b893c6..c3d06a3fa1 100644
--- a/lib/System/Unix/Path.inc
+++ b/lib/System/Unix/Path.inc
@@ -527,6 +527,34 @@ Path::eraseSuffix() {
return false;
}
+static bool createDirectoryHelper(char* beg, char* end, bool create_parents) {
+
+ if (access(beg, F_OK | R_OK | W_OK) == 0)
+ return false;
+
+ if (create_parents) {
+
+ char* c = end;
+
+ for (; c != beg; --c)
+ if (*c == '/') {
+
+ // Recurse to handling the parent directory.
+ *c = '\0';
+ bool x = createDirectoryHelper(beg, c, create_parents);
+ *c = '/';
+
+ // Return if we encountered an error.
+ if (x)
+ return true;
+
+ break;
+ }
+ }
+
+ return mkdir(beg, S_IRWXU | S_IRWXG) != 0;
+}
+
bool
Path::createDirectoryOnDisk( bool create_parents, std::string* ErrMsg ) {
// Get a writeable copy of the path name
@@ -534,38 +562,17 @@ Path::createDirectoryOnDisk( bool create_parents, std::string* ErrMsg ) {
path.copy(pathname,MAXPATHLEN);
// Null-terminate the last component
- int lastchar = path.length() - 1 ;
- if (pathname[lastchar] == '/')
- pathname[lastchar] = 0;
- else
- pathname[lastchar+1] = 0;
-
- // If we're supposed to create intermediate directories
- if ( create_parents ) {
- // Find the end of the initial name component
- char * next = strchr(pathname,'/');
- if ( pathname[0] == '/')
- next = strchr(&pathname[1],'/');
-
- // Loop through the directory components until we're done
- while ( next != 0 ) {
- *next = 0;
- if (0 != access(pathname, F_OK | R_OK | W_OK))
- if (0 != mkdir(pathname, S_IRWXU | S_IRWXG)) {
- return MakeErrMsg(ErrMsg,
- std::string(pathname) + ": can't create directory");
- }
- char* save = next;
- next = strchr(next+1,'/');
- *save = '/';
- }
- }
-
- if (0 != access(pathname, F_OK | R_OK))
- if (0 != mkdir(pathname, S_IRWXU | S_IRWXG)) {
- return MakeErrMsg(ErrMsg,
- std::string(pathname) + ": can't create directory");
- }
+ int lastchar = path.length() - 1 ;
+
+ if (pathname[lastchar] != '/')
+ ++lastchar;
+
+ pathname[lastchar] = 0;
+
+ if (createDirectoryHelper(pathname, pathname+lastchar, create_parents))
+ return MakeErrMsg(ErrMsg,
+ std::string(pathname) + ": can't create directory");
+
return false;
}