mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-17 00:50:58 +00:00
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
This commit is contained in:
parent
43b7ca15a3
commit
c5412c58d2
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user