-//===- llvm/System/Linux/Path.cpp - Linux Path Implementation ---*- C++ -*-===//
+//===- llvm/System/Win32/Path.cpp - Win32 Path Implementation ---*- C++ -*-===//
//
// 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.
#include "Win32.h"
#include <malloc.h>
+#include <cstdio>
// 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
namespace llvm {
namespace sys {
+const char PathSeparator = ';';
+
+Path::Path(const std::string& p)
+ : path(p) {
+ FlipBackSlashes(path);
+}
+
+Path::Path(const char *StrStart, unsigned StrLen)
+ : path(StrStart, StrLen) {
+ FlipBackSlashes(path);
+}
+
+Path&
+Path::operator=(const std::string &that) {
+ path = that;
+ FlipBackSlashes(path);
+ return *this;
+}
bool
Path::isValid() const {
return true;
}
+bool
+Path::isAbsolute(const char *NameStart, unsigned NameLen) {
+ assert(NameStart);
+ switch (NameLen) {
+ case 0:
+ return false;
+ case 1:
+ case 2:
+ return NameStart[0] == '/';
+ default:
+ return NameStart[0] == '/' || (NameStart[1] == ':' && NameStart[2] == '/');
+ }
+}
+
bool
Path::isAbsolute() const {
- if (path.length() < 3)
- return false;
- return path[0] == 'C' && path[1] == ':' && path[2] == '\\';
+ 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;
return result;
}
-static void getPathList(const char*path, std::vector<sys::Path>& Paths) {
- const char* at = path;
- const char* delim = strchr(at, ';');
- Path tmpPath;
- while (delim != 0) {
- std::string tmp(at, size_t(delim-at));
- if (tmpPath.set(tmp))
- if (tmpPath.canRead())
- Paths.push_back(tmpPath);
- at = delim + 1;
- delim = strchr(at, ';');
- }
-
- if (*at != 0)
- if (tmpPath.set(std::string(at)))
- if (tmpPath.canRead())
- Paths.push_back(tmpPath);
-}
-
void
Path::GetSystemLibraryPaths(std::vector<sys::Path>& Paths) {
Paths.push_back(sys::Path("C:/WINDOWS/SYSTEM32"));
}
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);
+}
+
+/// GetMainExecutable - Return the path to the main executable, given the
+/// value of argv[0] from program startup.
+Path Path::GetMainExecutable(const char *argv0, void *MainAddr) {
+ char pathname[MAX_PATH];
+ DWORD ret = ::GetModuleFileNameA(NULL, pathname, MAX_PATH);
+ return ret != MAX_PATH ? Path(pathname) : Path();
+}
+
+
// FIXME: the above set of functions don't map to Windows very well.
return len > 0 && path[len-1] == '/';
}
+std::string Path::getDirname() const {
+ return getDirnameCharSep(path, '/');
+}
+
std::string
Path::getBasename() const {
// Find the last slash
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;
-}
+std::string
+Path::getSuffix() const {
+ // Find the last slash
+ size_t slash = path.rfind('/');
+ if (slash == std::string::npos)
+ slash = 0;
+ else
+ slash++;
-bool
-Path::isBytecodeFile() const {
- std::string actualMagic;
- if (!getMagicNumber(actualMagic, 4))
- return false;
- return actualMagic == "llvc" || actualMagic == "llvm";
+ size_t dot = path.rfind('.');
+ if (dot == std::string::npos || dot < slash)
+ return std::string();
+ else
+ return path.substr(dot + 1);
}
bool
return attr != INVALID_FILE_ATTRIBUTES;
}
+bool
+Path::isDirectory() const {
+ DWORD attr = GetFileAttributes(path.c_str());
+ return (attr != INVALID_FILE_ATTRIBUTES) &&
+ (attr & FILE_ATTRIBUTE_DIRECTORY);
+}
+
bool
Path::canRead() const {
// FIXME: take security attributes into account.
return path.substr(pos+1);
}
-bool
-Path::getFileStatus(FileStatus &info, bool update, std::string *ErrStr) const {
- if (status == 0 || update) {
+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))
- return MakeErrMsg(ErrStr, "getStatusInfo():" + std::string(path) +
+ if (!GetFileAttributesEx(path.c_str(), GetFileExInfoStandard, &fi)) {
+ MakeErrMsg(ErrStr, "getStatusInfo():" + std::string(path) +
": Can't get status: ");
+ return 0;
+ }
- if (status == 0)
- status = new FileStatus;
+ status.fileSize = fi.nFileSizeHigh;
+ status.fileSize <<= sizeof(fi.nFileSizeHigh)*8;
+ status.fileSize += fi.nFileSizeLow;
- status->fileSize = fi.nFileSizeHigh;
- status->fileSize <<= sizeof(fi.nFileSizeHigh)*8;
- status->fileSize += fi.nFileSizeLow;
+ 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...
- 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...
+ // 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];
__int64 ft = *reinterpret_cast<__int64*>(&fi.ftLastWriteTime);
- status->modTime.fromWin32Time(ft);
+ status.modTime.fromWin32Time(ft);
- status->isDir = fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
+ status.isDir = fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
+ fsIsValid = true;
}
- info = *status;
- return false;
+ return &status;
}
bool Path::makeReadableOnDisk(std::string* ErrMsg) {
bool
Path::getDirectoryContents(std::set<Path>& result, std::string* ErrMsg) const {
- FileStatus Status;
- if (getFileStatus(Status, ErrMsg))
+ WIN32_FILE_ATTRIBUTE_DATA fi;
+ if (!GetFileAttributesEx(path.c_str(), GetFileExInfoStandard, &fi)) {
+ MakeErrMsg(ErrMsg, path + ": can't get status of file");
return true;
-
- if (!Status.isDir) {
- MakeErrMsg(ErrMsg, path + ": not a directory");
+ }
+
+ if (!(fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
+ if (ErrMsg)
+ *ErrMsg = path + ": not a directory";
return true;
}
bool
Path::set(const std::string& a_path) {
- if (a_path.size() == 0)
+ if (a_path.empty())
return false;
std::string save(path);
path = a_path;
bool
Path::eraseFromDisk(bool remove_contents, std::string *ErrStr) const {
- FileStatus Status;
- if (getFileStatus(Status, ErrStr))
- return false;
+ 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 false;
-
- // 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 MakeErrMsg(ErrStr, path + ": Can't destroy file: ");
- }
-
- if (!DeleteFile(path.c_str()))
- return MakeErrMsg(ErrStr, 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;
return MakeErrMsg(ErrStr,
std::string(pathname) + ": Can't destroy directory: ");
return false;
- }
- // It appears the path doesn't exist.
- return true;
+ } else {
+ // 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::getMagicNumber(std::string& Magic, unsigned len) const {
if (!MoveFileEx(path.c_str(), newName.c_str(), MOVEFILE_REPLACE_EXISTING))
return MakeErrMsg(ErrMsg, "Can't move '" + path + "' to '" + newName.path
+ "': ");
- return true;
+ return false;
}
bool
return false;
}
+/// MapInFilePages - Not yet implemented on win32.
+const char *Path::MapInFilePages(int FD, uint64_t FileSize) {
+ return 0;
+}
+
+/// MapInFilePages - Not yet implemented on win32.
+void Path::UnMapFilePages(const char *Base, uint64_t FileSize) {
+ assert(0 && "NOT IMPLEMENTED");
+}
+
}
}