1
0
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:
Reid Spencer 2004-09-29 00:01:17 +00:00
parent 6a072ccbb0
commit 3d434887d4

View File

@ -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: ");