[llvm-commits] CVS: llvm/lib/System/Win32/Path.cpp
Reid Spencer
reid at x10sys.com
Tue Sep 28 17:01:28 PDT 2004
Changes in directory llvm/lib/System/Win32:
Path.cpp updated: 1.3 -> 1.4
---
Log message:
Improve validity checking of windows path names and fix file creation
problems.
Patch contributed by Jeff Cohen. Thanks Jeff!
---
Diffs of the changes: (+77 -30)
Index: llvm/lib/System/Win32/Path.cpp
diff -u llvm/lib/System/Win32/Path.cpp:1.3 llvm/lib/System/Win32/Path.cpp:1.4
--- llvm/lib/System/Win32/Path.cpp:1.3 Sat Sep 18 14:29:16 2004
+++ llvm/lib/System/Win32/Path.cpp Tue Sep 28 19:01:17 2004
@@ -24,6 +24,12 @@
#include <fstream>
#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 sys {
@@ -32,17 +38,35 @@
if (path.empty())
return false;
- // On Unix, the realpath function is used, which only requires that the
- // directories leading up the to final file name are valid. The file itself
- // need not exist. To get this behavior on Windows, we must elide the file
- // name manually.
- Path dir(*this);
- dir.elide_file();
- if (dir.path.empty())
- return true;
+ // If there is a colon, it must be the second character, preceded by a letter
+ // and followed by something.
+ size_t len = path.size();
+ size_t pos = path.rfind(':',len);
+ if (pos != std::string::npos) {
+ if (pos != 1 || !isalpha(path[0]) || len < 3)
+ return false;
+ }
- DWORD attr = GetFileAttributes(dir.path.c_str());
- return (attr != INVALID_FILE_ATTRIBUTES) && (attr & FILE_ATTRIBUTE_DIRECTORY);
+ // Check for illegal characters.
+ 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;
@@ -54,7 +78,7 @@
char pathname[MAX_PATH];
if (!GetTempPath(MAX_PATH, pathname))
- ThrowError("Can't determine temporary directory");
+ throw std::string("Can't determine temporary directory");
Path result;
result.set_directory(pathname);
@@ -77,13 +101,14 @@
Path::Path(std::string unverified_path)
: path(unverified_path)
{
+ FlipBackSlashes(path);
if (unverified_path.empty())
return;
if (this->is_valid())
return;
// oops, not valid.
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.
@@ -94,6 +119,11 @@
return result;
}
+std::string
+Path::GetDLLSuffix() {
+ return "dll";
+}
+
static inline bool IsLibrary(Path& path, const std::string& basename) {
if (path.append_file(std::string("lib") + basename)) {
if (path.append_suffix(Path::GetDLLSuffix()) && path.readable())
@@ -281,6 +311,7 @@
return false;
Path save(*this);
path = a_path;
+ FlipBackSlashes(path);
size_t last = a_path.size() -1;
if (last != 0 && a_path[last] != '/')
path += '/';
@@ -297,6 +328,7 @@
return false;
Path save(*this);
path = a_path;
+ FlipBackSlashes(path);
size_t last = a_path.size() - 1;
while (last > 0 && a_path[last] == '/')
last--;
@@ -396,31 +428,46 @@
// Get a writeable copy of the path name
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
- int lastchar = path.length() - 1 ;
- if (pathname[lastchar] == '/')
- pathname[lastchar] = 0;
+ // Determine starting point for initial / search.
+ char *next = pathname;
+ if (pathname[0] == '/' && pathname[1] == '/') {
+ // 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 ( create_parents ) {
- // Find the end of the initial name component
- char * next = strchr(pathname,'/');
- if ( pathname[0] == '/')
- next = strchr(&pathname[1],'/');
-
+ if (create_parents) {
// Loop through the directory components until we're done
- while ( next != 0 ) {
+ while (*next) {
+ next = strchr(next, '/');
*next = 0;
if (!CreateDirectory(pathname, NULL))
ThrowError(std::string(pathname) + ": Can't create directory: ");
- char* save = next;
- next = strchr(pathname,'/');
- *save = '/';
+ *next++ = '/';
+ }
+ } 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;
}
@@ -431,7 +478,7 @@
if (!is_file()) return false;
// 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);
if (h == INVALID_HANDLE_VALUE)
ThrowError(std::string(path.c_str()) + ": Can't create file: ");
More information about the llvm-commits
mailing list