//
// The LLVM Compiler Infrastructure
//
-// This file was developed by Reid Spencer and is distributed under the
-// University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the 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.
// We need to undo a macro defined in Windows.h, otherwise we won't compile:
#undef CopyFile
+#undef GetCurrentDirectory
// Windows happily accepts either forward or backward slashes, though any path
// returned by a Win32 API will have backward slashes. As LLVM code basically
return true;
}
+bool
+Path::isAbsolute() const {
+ switch (path.length()) {
+ case 0:
+ return false;
+ case 1:
+ case 2:
+ return path[0] == '/';
+ default:
+ return path[0] == '/' || (path[1] == ':' && path[2] == '/');
+ }
+}
+
static Path *TempDirectory = NULL;
Path
// Append a subdirectory passed on our process id so multiple LLVMs don't
// step on each other's toes.
+#ifdef __MINGW32__
+ // Mingw's Win32 header files are broken.
sprintf(pathname, "LLVM_%u", unsigned(GetCurrentProcessId()));
+#else
+ sprintf(pathname, "LLVM_%u", GetCurrentProcessId());
+#endif
result.appendComponent(pathname);
// If there's a directory left over from a previous LLVM execution that
}
void
-Path::GetBytecodeLibraryPaths(std::vector<sys::Path>& Paths) {
+Path::GetBitcodeLibraryPaths(std::vector<sys::Path>& Paths) {
char * env_var = getenv("LLVM_LIB_SEARCH_PATH");
if (env_var != 0) {
getPathList(env_var,Paths);
}
return GetRootDirectory();
}
+
+Path
+Path::GetCurrentDirectory() {
+ char pathname[MAX_PATH];
+ ::GetCurrentDirectoryA(MAX_PATH,pathname);
+ return Path(pathname);
+}
+
+
// FIXME: the above set of functions don't map to Windows very well.
return path.substr(slash, dot - slash);
}
-bool Path::hasMagicNumber(const std::string &Magic) const {
- std::string actualMagic;
- if (getMagicNumber(actualMagic, Magic.size()))
- return Magic == actualMagic;
- return false;
-}
-
bool
-Path::isBytecodeFile() const {
- std::string actualMagic;
- if (!getMagicNumber(actualMagic, 4))
- return false;
- return actualMagic == "llvc" || actualMagic == "llvm";
+Path::exists() const {
+ DWORD attr = GetFileAttributes(path.c_str());
+ return attr != INVALID_FILE_ATTRIBUTES;
}
bool
-Path::exists() const {
+Path::isDirectory() const {
DWORD attr = GetFileAttributes(path.c_str());
- return attr != INVALID_FILE_ATTRIBUTES;
+ return (attr != INVALID_FILE_ATTRIBUTES) &&
+ (attr & FILE_ATTRIBUTE_DIRECTORY);
}
bool
return path.substr(pos+1);
}
-bool
-Path::getFileStatus(FileStatus &info, std::string *ErrStr) const {
- WIN32_FILE_ATTRIBUTE_DATA fi;
- if (!GetFileAttributesEx(path.c_str(), GetFileExInfoStandard, &fi))
- return GetError("getStatusInfo():" + std::string(path) +
- ": Can't get status: ", ErrStr);
-
- info.fileSize = fi.nFileSizeHigh;
- info.fileSize <<= sizeof(fi.nFileSizeHigh)*8;
- info.fileSize += fi.nFileSizeLow;
-
- info.mode = fi.dwFileAttributes & FILE_ATTRIBUTE_READONLY ? 0555 : 0777;
- info.user = 9999; // Not applicable to Windows, so...
- info.group = 9999; // Not applicable to Windows, so...
+const FileStatus *
+PathWithStatus::getFileStatus(bool update, std::string *ErrStr) const {
+ if (!fsIsValid || update) {
+ WIN32_FILE_ATTRIBUTE_DATA fi;
+ if (!GetFileAttributesEx(path.c_str(), GetFileExInfoStandard, &fi)) {
+ MakeErrMsg(ErrStr, "getStatusInfo():" + std::string(path) +
+ ": Can't get status: ");
+ return 0;
+ }
- __int64 ft = *reinterpret_cast<__int64*>(&fi.ftLastWriteTime);
- info.modTime.fromWin32Time(ft);
+ status.fileSize = fi.nFileSizeHigh;
+ status.fileSize <<= sizeof(fi.nFileSizeHigh)*8;
+ status.fileSize += fi.nFileSizeLow;
- info.isDir = fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
- return false;
-}
+ status.mode = fi.dwFileAttributes & FILE_ATTRIBUTE_READONLY ? 0555 : 0777;
+ status.user = 9999; // Not applicable to Windows, so...
+ status.group = 9999; // Not applicable to Windows, so...
-static bool AddPermissionBits(const std::string& Filename, int bits) {
- DWORD attr = GetFileAttributes(Filename.c_str());
+ // FIXME: this is only unique if the file is accessed by the same file path.
+ // How do we do this for C:\dir\file and ..\dir\file ? Unix has inode
+ // numbers, but the concept doesn't exist in Windows.
+ status.uniqueID = 0;
+ for (unsigned i = 0; i < path.length(); ++i)
+ status.uniqueID += path[i];
- // If it doesn't exist, we're done.
- if (attr == INVALID_FILE_ATTRIBUTES)
- return false;
+ __int64 ft = *reinterpret_cast<__int64*>(&fi.ftLastWriteTime);
+ status.modTime.fromWin32Time(ft);
- // The best we can do to interpret Unix permission bits is to use
- // the owner writable bit.
- if ((attr & FILE_ATTRIBUTE_READONLY) && (bits & 0200)) {
- if (!SetFileAttributes(Filename.c_str(), attr & ~FILE_ATTRIBUTE_READONLY))
- ThrowError(Filename + ": SetFileAttributes: ");
+ status.isDir = fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
+ fsIsValid = true;
}
- return true;
+ return &status;
}
bool Path::makeReadableOnDisk(std::string* ErrMsg) {
return false;
}
-void Path::makeWriteableOnDisk(std::string* ErrMsg) {
+bool Path::makeWriteableOnDisk(std::string* ErrMsg) {
DWORD attr = GetFileAttributes(path.c_str());
// If it doesn't exist, we're done.
if (attr == INVALID_FILE_ATTRIBUTES)
- return;
+ return false;
if (attr & FILE_ATTRIBUTE_READONLY) {
if (!SetFileAttributes(path.c_str(), attr & ~FILE_ATTRIBUTE_READONLY)) {
bool
Path::getDirectoryContents(std::set<Path>& result, std::string* ErrMsg) const {
- if (!isDirectory()) {
- MakeErrMsg(ErrMsg, path + ": not a directory");
+ WIN32_FILE_ATTRIBUTE_DATA fi;
+ if (!GetFileAttributesEx(path.c_str(), GetFileExInfoStandard, &fi)) {
+ MakeErrMsg(ErrMsg, path + ": can't get status of file");
+ return true;
+ }
+
+ if (!(fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
+ if (ErrMsg)
+ *ErrMsg = path + ": not a directory";
return true;
}
return false;
}
+inline bool PathMsg(std::string* ErrMsg, const char* pathname, const char*msg) {
+ if (ErrMsg)
+ *ErrMsg = std::string(pathname) + ": " + std::string(msg);
+ return true;
+}
+
bool
-Path::createDirectoryOnDisk(bool create_parents) {
+Path::createDirectoryOnDisk(bool create_parents, std::string* ErrMsg) {
// Get a writeable copy of the path name
size_t len = path.length();
char *pathname = reinterpret_cast<char *>(_alloca(len+2));
// Skip host name.
next = strchr(pathname+2, '/');
if (next == NULL)
- throw std::string(pathname) + ": badly formed remote directory";
+ return PathMsg(ErrMsg, pathname, "badly formed remote directory");
+
// Skip share name.
next = strchr(next+1, '/');
if (next == NULL)
- throw std::string(pathname) + ": badly formed remote directory";
+ return PathMsg(ErrMsg, pathname,"badly formed remote directory");
+
next++;
if (*next == 0)
- throw std::string(pathname) + ": badly formed remote directory";
+ return PathMsg(ErrMsg, pathname, "badly formed remote directory");
+
} else {
if (pathname[1] == ':')
next += 2; // skip drive letter
next = strchr(next, '/');
*next = 0;
if (!CreateDirectory(pathname, NULL))
- ThrowError(std::string(pathname) + ": Can't create directory: ");
+ return MakeErrMsg(ErrMsg,
+ std::string(pathname) + ": Can't create directory: ");
*next++ = '/';
}
} else {
// Drop trailing slash.
pathname[len-1] = 0;
if (!CreateDirectory(pathname, NULL)) {
- ThrowError(std::string(pathname) + ": Can't create directory: ");
+ return MakeErrMsg(ErrMsg, std::string(pathname) + ": Can't create directory: ");
}
}
- return true;
+ return false;
}
bool
-Path::createFileOnDisk() {
+Path::createFileOnDisk(std::string* ErrMsg) {
// Create the file
HANDLE h = CreateFile(path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_NEW,
FILE_ATTRIBUTE_NORMAL, NULL);
if (h == INVALID_HANDLE_VALUE)
- ThrowError(path + ": Can't create file: ");
+ return MakeErrMsg(ErrMsg, path + ": Can't create file: ");
CloseHandle(h);
- return true;
+ return false;
}
bool
Path::eraseFromDisk(bool remove_contents, std::string *ErrStr) const {
- FileStatus Status;
- if (getFileStatus(Status, ErrStr))
+ WIN32_FILE_ATTRIBUTE_DATA fi;
+ if (!GetFileAttributesEx(path.c_str(), GetFileExInfoStandard, &fi))
return true;
- if (Status.isFile) {
- 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))
- return GetError(path + ": Can't destroy file: ", ErrStr);
- }
-
- if (!DeleteFile(path.c_str()))
- ThrowError(path + ": Can't destroy file: ");
- return false;
- } else if (Status.isDir) {
+ if (fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// If it doesn't exist, we're done.
if (!exists())
return false;
FindClose(h);
if (err != ERROR_NO_MORE_FILES) {
SetLastError(err);
- return GetError(path + ": Can't read directory: ", ErrStr);
+ return MakeErrMsg(ErrStr, path + ": Can't read directory: ");
}
for (std::vector<Path>::iterator I = list.begin(); I != list.end();
}
} else {
if (GetLastError() != ERROR_FILE_NOT_FOUND)
- return GetError(path + ": Can't read directory: ", ErrStr);
+ return MakeErrMsg(ErrStr, path + ": Can't read directory: ");
}
}
pathname[lastchar] = 0;
if (!RemoveDirectory(pathname))
- return GetError(std::string(pathname) + ": Can't destroy directory: ",
- ErrStr);
+ return MakeErrMsg(ErrStr,
+ std::string(pathname) + ": Can't destroy directory: ");
return false;
} else {
- // It appears the path doesn't exist.
- return true;
+ // Read-only files cannot be deleted on Windows. Must remove the read-only
+ // attribute first.
+ if (fi.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
+ if (!SetFileAttributes(path.c_str(),
+ fi.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY))
+ return MakeErrMsg(ErrStr, path + ": Can't destroy file: ");
+ }
+
+ if (!DeleteFile(path.c_str()))
+ return MakeErrMsg(ErrStr, path + ": Can't destroy file: ");
+ return false;
}
}
}
bool
-Path::setStatusInfoOnDisk(const FileStatus &si, std::string *ErrStr) const {
+Path::setStatusInfoOnDisk(const FileStatus &si, std::string *ErrMsg) const {
// FIXME: should work on directories also.
- if (!isFile()) return true;
-
+ if (!si.isFile) {
+ return true;
+ }
+
HANDLE h = CreateFile(path.c_str(),
FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
DWORD err = GetLastError();
CloseHandle(h);
SetLastError(err);
- return GetError(path + ": GetFileInformationByHandle: ", ErrStr);
+ return MakeErrMsg(ErrMsg, path + ": GetFileInformationByHandle: ");
}
FILETIME ft;
CloseHandle(h);
if (!ret) {
SetLastError(err);
- return GetError(path + ": SetFileTime: ", ErrStr);
+ return MakeErrMsg(ErrMsg, path + ": SetFileTime: ");
}
// Best we can do with Unix permission bits is to interpret the owner
if (bhfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
if (!SetFileAttributes(path.c_str(),
bhfi.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY))
- return GetError(path + ": SetFileAttributes: ", ErrStr);
+ return MakeErrMsg(ErrMsg, path + ": SetFileAttributes: ");
}
} else {
if (!(bhfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) {
if (!SetFileAttributes(path.c_str(),
bhfi.dwFileAttributes | FILE_ATTRIBUTE_READONLY))
- return GetError(path + ": SetFileAttributes: ", ErrStr);
+ return MakeErrMsg(ErrMsg, path + ": SetFileAttributes: ");
}
}
return false;
}
-void
-CopyFile(const sys::Path &Dest, const sys::Path &Src) {
+bool
+CopyFile(const sys::Path &Dest, const sys::Path &Src, std::string* ErrMsg) {
// Can't use CopyFile macro defined in Windows.h because it would mess up the
// above line. We use the expansion it would have in a non-UNICODE build.
if (!::CopyFileA(Src.c_str(), Dest.c_str(), false))
- ThrowError("Can't copy '" + Src.toString() +
+ return MakeErrMsg(ErrMsg, "Can't copy '" + Src.toString() +
"' to '" + Dest.toString() + "': ");
+ return false;
}
-void
-Path::makeUnique(bool reuse_current) {
+bool
+Path::makeUnique(bool reuse_current, std::string* ErrMsg) {
if (reuse_current && !exists())
- return; // File doesn't exist already, just use it!
+ return false; // File doesn't exist already, just use it!
// Reserve space for -XXXXXX at the end.
char *FNBuffer = (char*) alloca(path.size()+8);
FCounter = 0;
path = FNBuffer;
} while (exists());
+ return false;
}
bool
-Path::createTemporaryFileOnDisk(bool reuse_current) {
+Path::createTemporaryFileOnDisk(bool reuse_current, std::string* ErrMsg) {
// Make this into a unique file name
- makeUnique(reuse_current);
+ makeUnique(reuse_current, ErrMsg);
// Now go and create it
HANDLE h = CreateFile(path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_NEW,
FILE_ATTRIBUTE_NORMAL, NULL);
if (h == INVALID_HANDLE_VALUE)
- return false;
+ return MakeErrMsg(ErrMsg, path + ": can't create file");
CloseHandle(h);
- return true;
+ return false;
}
}