mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 11:42:57 +01:00
Improve validity checking of windows path names and fix file creation
problems. Patch contributed by Jeff Cohen. Thanks Jeff! llvm-svn: 16565
This commit is contained in:
parent
6a072ccbb0
commit
3d434887d4
@ -24,6 +24,12 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
|
|
||||||
|
static void FlipBackSlashes(std::string& s) {
|
||||||
|
for (size_t i = 0; i < s.size(); i++)
|
||||||
|
if (s[i] == '\\')
|
||||||
|
s[i] = '/';
|
||||||
|
}
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
namespace sys {
|
namespace sys {
|
||||||
|
|
||||||
@ -32,17 +38,35 @@ Path::is_valid() const {
|
|||||||
if (path.empty())
|
if (path.empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// On Unix, the realpath function is used, which only requires that the
|
// If there is a colon, it must be the second character, preceded by a letter
|
||||||
// directories leading up the to final file name are valid. The file itself
|
// and followed by something.
|
||||||
// need not exist. To get this behavior on Windows, we must elide the file
|
size_t len = path.size();
|
||||||
// name manually.
|
size_t pos = path.rfind(':',len);
|
||||||
Path dir(*this);
|
if (pos != std::string::npos) {
|
||||||
dir.elide_file();
|
if (pos != 1 || !isalpha(path[0]) || len < 3)
|
||||||
if (dir.path.empty())
|
return false;
|
||||||
return true;
|
}
|
||||||
|
|
||||||
DWORD attr = GetFileAttributes(dir.path.c_str());
|
// Check for illegal characters.
|
||||||
return (attr != INVALID_FILE_ATTRIBUTES) && (attr & FILE_ATTRIBUTE_DIRECTORY);
|
if (path.find_first_of("\\<>\"|\001\002\003\004\005\006\007\010\011\012"
|
||||||
|
"\013\014\015\016\017\020\021\022\023\024\025\026"
|
||||||
|
"\027\030\031\032\033\034\035\036\037")
|
||||||
|
!= std::string::npos)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// A file or directory name may not end in a period.
|
||||||
|
if (path[len-1] == '.')
|
||||||
|
return false;
|
||||||
|
if (len >= 2 && path[len-2] == '.' && path[len-1] == '/')
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// A file or directory name may not end in a space.
|
||||||
|
if (path[len-1] == ' ')
|
||||||
|
return false;
|
||||||
|
if (len >= 2 && path[len-2] == ' ' && path[len-1] == '/')
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Path *TempDirectory = NULL;
|
static Path *TempDirectory = NULL;
|
||||||
@ -54,7 +78,7 @@ Path::GetTemporaryDirectory() {
|
|||||||
|
|
||||||
char pathname[MAX_PATH];
|
char pathname[MAX_PATH];
|
||||||
if (!GetTempPath(MAX_PATH, pathname))
|
if (!GetTempPath(MAX_PATH, pathname))
|
||||||
ThrowError("Can't determine temporary directory");
|
throw std::string("Can't determine temporary directory");
|
||||||
|
|
||||||
Path result;
|
Path result;
|
||||||
result.set_directory(pathname);
|
result.set_directory(pathname);
|
||||||
@ -77,13 +101,14 @@ Path::GetTemporaryDirectory() {
|
|||||||
Path::Path(std::string unverified_path)
|
Path::Path(std::string unverified_path)
|
||||||
: path(unverified_path)
|
: path(unverified_path)
|
||||||
{
|
{
|
||||||
|
FlipBackSlashes(path);
|
||||||
if (unverified_path.empty())
|
if (unverified_path.empty())
|
||||||
return;
|
return;
|
||||||
if (this->is_valid())
|
if (this->is_valid())
|
||||||
return;
|
return;
|
||||||
// oops, not valid.
|
// oops, not valid.
|
||||||
path.clear();
|
path.clear();
|
||||||
ThrowError(unverified_path + ": path is not valid");
|
throw std::string(unverified_path + ": path is not valid");
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: the following set of functions don't map to Windows very well.
|
// FIXME: the following set of functions don't map to Windows very well.
|
||||||
@ -94,6 +119,11 @@ Path::GetRootDirectory() {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
Path::GetDLLSuffix() {
|
||||||
|
return "dll";
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool IsLibrary(Path& path, const std::string& basename) {
|
static inline bool IsLibrary(Path& path, const std::string& basename) {
|
||||||
if (path.append_file(std::string("lib") + basename)) {
|
if (path.append_file(std::string("lib") + basename)) {
|
||||||
if (path.append_suffix(Path::GetDLLSuffix()) && path.readable())
|
if (path.append_suffix(Path::GetDLLSuffix()) && path.readable())
|
||||||
@ -281,6 +311,7 @@ Path::set_directory(const std::string& a_path) {
|
|||||||
return false;
|
return false;
|
||||||
Path save(*this);
|
Path save(*this);
|
||||||
path = a_path;
|
path = a_path;
|
||||||
|
FlipBackSlashes(path);
|
||||||
size_t last = a_path.size() -1;
|
size_t last = a_path.size() -1;
|
||||||
if (last != 0 && a_path[last] != '/')
|
if (last != 0 && a_path[last] != '/')
|
||||||
path += '/';
|
path += '/';
|
||||||
@ -297,6 +328,7 @@ Path::set_file(const std::string& a_path) {
|
|||||||
return false;
|
return false;
|
||||||
Path save(*this);
|
Path save(*this);
|
||||||
path = a_path;
|
path = a_path;
|
||||||
|
FlipBackSlashes(path);
|
||||||
size_t last = a_path.size() - 1;
|
size_t last = a_path.size() - 1;
|
||||||
while (last > 0 && a_path[last] == '/')
|
while (last > 0 && a_path[last] == '/')
|
||||||
last--;
|
last--;
|
||||||
@ -396,31 +428,46 @@ Path::create_directory( bool create_parents) {
|
|||||||
|
|
||||||
// Get a writeable copy of the path name
|
// Get a writeable copy of the path name
|
||||||
char *pathname = reinterpret_cast<char *>(_alloca(path.length()+1));
|
char *pathname = reinterpret_cast<char *>(_alloca(path.length()+1));
|
||||||
path.copy(pathname,path.length()+1);
|
path.copy(pathname,path.length());
|
||||||
|
pathname[path.length()] = 0;
|
||||||
|
|
||||||
// Null-terminate the last component
|
// Determine starting point for initial / search.
|
||||||
int lastchar = path.length() - 1 ;
|
char *next = pathname;
|
||||||
if (pathname[lastchar] == '/')
|
if (pathname[0] == '/' && pathname[1] == '/') {
|
||||||
pathname[lastchar] = 0;
|
// Skip host name.
|
||||||
|
next = strchr(pathname+2, '/');
|
||||||
|
if (next == NULL)
|
||||||
|
throw std::string(pathname) + ": badly formed remote directory";
|
||||||
|
// Skip share name.
|
||||||
|
next = strchr(next+1, '/');
|
||||||
|
if (next == NULL)
|
||||||
|
throw std::string(pathname) + ": badly formed remote directory";
|
||||||
|
next++;
|
||||||
|
if (*next == 0)
|
||||||
|
throw std::string(pathname) + ": badly formed remote directory";
|
||||||
|
} else {
|
||||||
|
if (pathname[1] == ':')
|
||||||
|
next += 2; // skip drive letter
|
||||||
|
if (*next == '/')
|
||||||
|
next++; // skip root directory
|
||||||
|
}
|
||||||
|
|
||||||
// If we're supposed to create intermediate directories
|
// If we're supposed to create intermediate directories
|
||||||
if ( create_parents ) {
|
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
|
// Loop through the directory components until we're done
|
||||||
while ( next != 0 ) {
|
while (*next) {
|
||||||
|
next = strchr(next, '/');
|
||||||
*next = 0;
|
*next = 0;
|
||||||
if (!CreateDirectory(pathname, NULL))
|
if (!CreateDirectory(pathname, NULL))
|
||||||
ThrowError(std::string(pathname) + ": Can't create directory: ");
|
ThrowError(std::string(pathname) + ": Can't create directory: ");
|
||||||
char* save = next;
|
*next++ = '/';
|
||||||
next = strchr(pathname,'/');
|
}
|
||||||
*save = '/';
|
} else {
|
||||||
|
// Drop trailing slash.
|
||||||
|
pathname[path.size()-1] = 0;
|
||||||
|
if (!CreateDirectory(pathname, NULL)) {
|
||||||
|
ThrowError(std::string(pathname) + ": Can't create directory: ");
|
||||||
}
|
}
|
||||||
} else if (!CreateDirectory(pathname, NULL)) {
|
|
||||||
ThrowError(std::string(pathname) + ": Can't create directory: ");
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -431,7 +478,7 @@ Path::create_file() {
|
|||||||
if (!is_file()) return false;
|
if (!is_file()) return false;
|
||||||
|
|
||||||
// Create the file
|
// Create the file
|
||||||
HANDLE h = CreateFile(path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
|
HANDLE h = CreateFile(path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_NEW,
|
||||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
if (h == INVALID_HANDLE_VALUE)
|
if (h == INVALID_HANDLE_VALUE)
|
||||||
ThrowError(std::string(path.c_str()) + ": Can't create file: ");
|
ThrowError(std::string(path.c_str()) + ": Can't create file: ");
|
||||||
|
Loading…
Reference in New Issue
Block a user