[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