[llvm-commits] CVS: llvm/lib/System/Win32/Path.cpp
Reid Spencer
reid at x10sys.com
Sat Sep 18 12:29:26 PDT 2004
Changes in directory llvm/lib/System/Win32:
Path.cpp updated: 1.2 -> 1.3
---
Log message:
Porting of Unix implementation to Win32.
Patch contributed by Jeff Cohen. Thanks Jeff!
---
Diffs of the changes: (+190 -48)
Index: llvm/lib/System/Win32/Path.cpp
diff -u llvm/lib/System/Win32/Path.cpp:1.2 llvm/lib/System/Win32/Path.cpp:1.3
--- llvm/lib/System/Win32/Path.cpp:1.2 Wed Sep 15 00:49:50 2004
+++ llvm/lib/System/Win32/Path.cpp Sat Sep 18 14:29:16 2004
@@ -6,6 +6,7 @@
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
// Modified by Henrik Bach to comply with at least MinGW.
+// Ported to Win32 by Jeff Cohen.
//
//===----------------------------------------------------------------------===//
//
@@ -18,18 +19,10 @@
//=== is guaranteed to work on *all* Win32 variants.
//===----------------------------------------------------------------------===//
-#include <llvm/Config/config.h>
-#include <limits.h>
-#include <stdarg.h>
-#include <assert.h>
-#include <fcntl.h>
-#include <sys/stat.h>
+#include "Win32.h"
#include <llvm/System/Path.h>
-
-#include <windef.h>
-#include <winbase.h>
-
-#define MAXPATHLEN PATH_MAX
+#include <fstream>
+#include <malloc.h>
namespace llvm {
namespace sys {
@@ -38,23 +31,47 @@
Path::is_valid() const {
if (path.empty())
return false;
-/*hb: char pathname[MAXPATHLEN];
- if (0 == realpath(path.c_str(), pathname))
- if (errno != EACCES && errno != EIO && errno != ENOENT && errno !=
-ENOTDIR)
- return false;*/
- return true;
+
+ // 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;
+
+ DWORD attr = GetFileAttributes(dir.path.c_str());
+ return (attr != INVALID_FILE_ATTRIBUTES) && (attr & FILE_ATTRIBUTE_DIRECTORY);
}
+static Path *TempDirectory = NULL;
+
Path
Path::GetTemporaryDirectory() {
- char pathname[MAXPATHLEN];
- if (0 == GetTempPath(MAXPATHLEN,pathname))
- ThrowError(std::string(pathname) + ": Can't create temporary directory");
+ if (TempDirectory)
+ return *TempDirectory;
+
+ char pathname[MAX_PATH];
+ if (!GetTempPath(MAX_PATH, pathname))
+ ThrowError("Can't determine temporary directory");
+
Path result;
result.set_directory(pathname);
- assert(result.is_valid() && "GetTempPath didn't create a valid pathname!");
- return result;
+
+ // Append a subdirectory passed on our process id so multiple LLVMs don't
+ // step on each other's toes.
+ sprintf(pathname, "LLVM_%u", GetCurrentProcessId());
+ result.append_directory(pathname);
+
+ // If there's a directory left over from a previous LLVM execution that
+ // happened to have the same process id, get rid of it.
+ result.destroy_directory(true);
+
+ // And finally (re-)create the empty directory.
+ result.create_directory(false);
+ TempDirectory = new Path(result);
+ return *TempDirectory;
}
Path::Path(std::string unverified_path)
@@ -69,6 +86,7 @@
ThrowError(unverified_path + ": path is not valid");
}
+// FIXME: the following set of functions don't map to Windows very well.
Path
Path::GetRootDirectory() {
Path result;
@@ -76,6 +94,59 @@
return result;
}
+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())
+ return true;
+ else if (path.elide_suffix() && path.append_suffix("a") && path.readable())
+ return true;
+ else if (path.elide_suffix() && path.append_suffix("o") && path.readable())
+ return true;
+ else if (path.elide_suffix() && path.append_suffix("bc") && path.readable())
+ return true;
+ } else if (path.elide_file() && path.append_file(basename)) {
+ if (path.append_suffix(Path::GetDLLSuffix()) && path.readable())
+ return true;
+ else if (path.elide_suffix() && path.append_suffix("a") && path.readable())
+ return true;
+ else if (path.elide_suffix() && path.append_suffix("o") && path.readable())
+ return true;
+ else if (path.elide_suffix() && path.append_suffix("bc") && path.readable())
+ return true;
+ }
+ path.clear();
+ return false;
+}
+
+Path
+Path::GetLibraryPath(const std::string& basename,
+ const std::vector<std::string>& LibPaths) {
+ Path result;
+
+ // Try the paths provided
+ for (std::vector<std::string>::const_iterator I = LibPaths.begin(),
+ E = LibPaths.end(); I != E; ++I ) {
+ if (result.set_directory(*I) && IsLibrary(result,basename))
+ return result;
+ }
+
+ // Try the LLVM lib directory in the LLVM install area
+ //if (result.set_directory(LLVM_LIBDIR) && IsLibrary(result,basename))
+ // return result;
+
+ // Try /usr/lib
+ if (result.set_directory("/usr/lib/") && IsLibrary(result,basename))
+ return result;
+
+ // Try /lib
+ if (result.set_directory("/lib/") && IsLibrary(result,basename))
+ return result;
+
+ // Can't find it, give up and return invalid path.
+ result.clear();
+ return result;
+}
+
Path
Path::GetSystemLibraryPath1() {
return Path("/lib/");
@@ -93,9 +164,6 @@
Path
Path::GetLLVMConfigDir() {
- Path result;
- if (result.set_directory(LLVM_ETCDIR))
- return result;
return GetLLVMDefaultConfigDir();
}
@@ -109,25 +177,80 @@
}
return GetRootDirectory();
}
+// FIXME: the above set of functions don't map to Windows very well.
+
+bool
+Path::is_file() const {
+ return (is_valid() && path[path.length()-1] != '/');
+}
+
+bool
+Path::is_directory() const {
+ return (is_valid() && path[path.length()-1] == '/');
+}
+
+std::string
+Path::get_basename() const {
+ // Find the last slash
+ size_t slash = path.rfind('/');
+ if (slash == std::string::npos)
+ slash = 0;
+ else
+ slash++;
+
+ return path.substr(slash, path.rfind('.'));
+}
+
+bool Path::has_magic_number(const std::string &Magic) const {
+ size_t len = Magic.size();
+ char *buf = reinterpret_cast<char *>(_alloca(len+1));
+ std::ifstream f(path.c_str());
+ f.read(buf, len);
+ buf[len] = '\0';
+ return Magic == buf;
+}
+
+bool
+Path::is_bytecode_file() const {
+ if (readable()) {
+ return has_magic_number("llvm");
+ }
+ return false;
+}
+
+bool
+Path::is_archive() const {
+ if (readable()) {
+ return has_magic_number("!<arch>\012");
+ }
+ return false;
+}
bool
Path::exists() const {
- return 0 == access(path.c_str(), F_OK );
+ DWORD attr = GetFileAttributes(path.c_str());
+ return attr != INVALID_FILE_ATTRIBUTES;
}
bool
Path::readable() const {
- return 0 == access(path.c_str(), F_OK | R_OK );
+ // FIXME: take security attributes into account.
+ DWORD attr = GetFileAttributes(path.c_str());
+ return attr != INVALID_FILE_ATTRIBUTES;
}
bool
Path::writable() const {
- return 0 == access(path.c_str(), F_OK | W_OK );
+ // FIXME: take security attributes into account.
+ DWORD attr = GetFileAttributes(path.c_str());
+ return (attr != INVALID_FILE_ATTRIBUTES) && !(attr & FILE_ATTRIBUTE_READONLY);
}
bool
Path::executable() const {
- return 0 == access(path.c_str(), R_OK | X_OK );
+ // FIXME: take security attributes into account.
+ DWORD attr = GetFileAttributes(path.c_str());
+ return attr != INVALID_FILE_ATTRIBUTES;
}
std::string
@@ -272,8 +395,8 @@
if (!is_directory()) return false;
// Get a writeable copy of the path name
- char pathname[MAXPATHLEN];
- path.copy(pathname,MAXPATHLEN);
+ char *pathname = reinterpret_cast<char *>(_alloca(path.length()+1));
+ path.copy(pathname,path.length()+1);
// Null-terminate the last component
int lastchar = path.length() - 1 ;
@@ -290,15 +413,14 @@
// 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))
- ThrowError(std::string(pathname) + ": Can't create directory");
+ if (!CreateDirectory(pathname, NULL))
+ ThrowError(std::string(pathname) + ": Can't create directory: ");
char* save = next;
next = strchr(pathname,'/');
*save = '/';
}
- } else if (0 != mkdir(pathname)) {
- ThrowError(std::string(pathname) + ": Can't create directory");
+ } else if (!CreateDirectory(pathname, NULL)) {
+ ThrowError(std::string(pathname) + ": Can't create directory: ");
}
return true;
}
@@ -309,9 +431,12 @@
if (!is_file()) return false;
// Create the file
- if (0 != creat(path.c_str(), S_IRUSR | S_IWUSR))
- ThrowError(std::string(path.c_str()) + ": Can't create file");
+ HANDLE h = CreateFile(path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ ThrowError(std::string(path.c_str()) + ": Can't create file: ");
+ CloseHandle(h);
return true;
}
@@ -323,20 +448,23 @@
// If it doesn't exist, we're done.
if (!exists()) return true;
+ char *pathname = reinterpret_cast<char *>(_alloca(path.length()+1));
+ path.copy(pathname,path.length()+1);
+ int lastchar = path.length() - 1 ;
+ if (pathname[lastchar] == '/')
+ pathname[lastchar] = 0;
+
if (remove_contents) {
// Recursively descend the directory to remove its content
- std::string cmd("/bin/rm -rf ");
+ // FIXME: The correct way of doing this on Windows isn't pretty...
+ // but this may work if unix-like utils are present.
+ std::string cmd("rm -rf ");
cmd += path;
system(cmd.c_str());
} else {
// Otherwise, try to just remove the one directory
- char pathname[MAXPATHLEN];
- path.copy(pathname,MAXPATHLEN);
- int lastchar = path.length() - 1 ;
- if (pathname[lastchar] == '/')
- pathname[lastchar] = 0;
- if ( 0 != rmdir(pathname))
- ThrowError(std::string(pathname) + ": Can't destroy directory");
+ if (!RemoveDirectory(pathname))
+ ThrowError(std::string(pathname) + ": Can't destroy directory: ");
}
return true;
}
@@ -344,8 +472,22 @@
bool
Path::destroy_file() {
if (!is_file()) return false;
- if (0 != unlink(path.c_str()))
- ThrowError(std::string(path.c_str()) + ": Can't destroy file");
+
+ DWORD attr = GetFileAttributes(path.c_str());
+
+ // If it doesn't exist, we're done.
+ if (attr == INVALID_FILE_ATTRIBUTES)
+ return true;
+
+ // Read-only files cannot be deleted on Windows. Must remove the read-only
+ // attribute first.
+ if (attr & FILE_ATTRIBUTE_READONLY) {
+ if (!SetFileAttributes(path.c_str(), attr & ~FILE_ATTRIBUTE_READONLY))
+ ThrowError(std::string(path.c_str()) + ": Can't destroy file: ");
+ }
+
+ if (!DeleteFile(path.c_str()))
+ ThrowError(std::string(path.c_str()) + ": Can't destroy file: ");
return true;
}
More information about the llvm-commits
mailing list