// 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.
-//
//===----------------------------------------------------------------------===//
//
// This file provides the Win32 specific implementation of the Path class.
namespace llvm {
namespace sys {
+
const char PathSeparator = ';';
-Path::Path(const std::string& p)
+StringRef Path::GetEXESuffix() {
+ return "exe";
+}
+
+Path::Path(llvm::StringRef p)
: path(p) {
FlipBackSlashes(path);
}
}
Path&
-Path::operator=(const std::string &that) {
- path = that;
+Path::operator=(StringRef that) {
+ path.assign(that.data(), that.size());
FlipBackSlashes(path);
return *this;
}
+// push_back 0 on create, and pop_back on delete.
+struct ScopedNullTerminator {
+ std::string &str;
+ ScopedNullTerminator(std::string &s) : str(s) { str.push_back(0); }
+ ~ScopedNullTerminator() {
+ // str.pop_back(); But wait, C++03 doesn't have this...
+ assert(!str.empty() && str[str.size() - 1] == 0
+ && "Null char not present!");
+ str.resize(str.size() - 1);
+ }
+};
+
bool
Path::isValid() const {
if (path.empty())
// If there is a colon, it must be the second character, preceded by a letter
// and followed by something.
size_t len = path.size();
+ // This code assumes that path is null terminated, so make sure it is.
+ ScopedNullTerminator snt(path);
size_t pos = path.rfind(':',len);
size_t rootslash = 0;
if (pos != std::string::npos) {
}
void Path::makeAbsolute() {
- TCHAR FullPath[MAX_PATH + 1] = {0};
+ TCHAR FullPath[MAX_PATH + 1] = {0};
LPTSTR FilePart = NULL;
DWORD RetLength = ::GetFullPathNameA(path.c_str(),
case 2:
return NameStart[0] == '/';
default:
- return (NameStart[0] == '/' || (NameStart[1] == ':' && NameStart[2] == '/')) ||
- (NameStart[0] == '\\' || (NameStart[1] == ':' && NameStart[2] == '\\'));
+ return
+ (NameStart[0] == '/' || (NameStart[1] == ':' && NameStart[2] == '/')) ||
+ (NameStart[0] == '\\' || (NameStart[1] == ':' && NameStart[2] == '\\'));
}
}
-bool
+bool
Path::isAbsolute() const {
// FIXME: This does not handle correctly an absolute path starting from
// a drive letter or in UNC format.
default:
return path[0] == '/' || (path[1] == ':' && path[2] == '/');
}
-}
+}
-static Path *TempDirectory = NULL;
+static Path *TempDirectory;
Path
Path::GetTemporaryDirectory(std::string* ErrMsg) {
// FIXME: the following set of functions don't map to Windows very well.
Path
Path::GetRootDirectory() {
- Path result;
- result.set("C:/");
- return result;
+ // This is the only notion that that Windows has of a root directory. Nothing
+ // is here except for drives.
+ return Path("file:///");
}
void
Path::GetSystemLibraryPaths(std::vector<sys::Path>& Paths) {
- Paths.push_back(sys::Path("C:/WINDOWS/SYSTEM32"));
- Paths.push_back(sys::Path("C:/WINDOWS"));
+ char buff[MAX_PATH];
+ // Generic form of C:\Windows\System32
+ HRESULT res = SHGetFolderPathA(NULL,
+ CSIDL_FLAG_CREATE | CSIDL_SYSTEM,
+ NULL,
+ SHGFP_TYPE_CURRENT,
+ buff);
+ if (res != S_OK) {
+ assert(0 && "Failed to get system directory");
+ return;
+ }
+ Paths.push_back(sys::Path(buff));
+
+ // Reset buff.
+ buff[0] = 0;
+ // Generic form of C:\Windows
+ res = SHGetFolderPathA(NULL,
+ CSIDL_FLAG_CREATE | CSIDL_WINDOWS,
+ NULL,
+ SHGFP_TYPE_CURRENT,
+ buff);
+ if (res != S_OK) {
+ assert(0 && "Failed to get windows directory");
+ return;
+ }
+ Paths.push_back(sys::Path(buff));
}
void
Path
Path::GetLLVMDefaultConfigDir() {
- // TODO: this isn't going to fly on Windows
- return Path("/etc/llvm");
+ Path ret = GetUserHomeDirectory();
+ if (!ret.appendComponent(".llvm"))
+ assert(0 && "Failed to append .llvm");
+ return ret;
}
Path
Path::GetUserHomeDirectory() {
- // TODO: Typical Windows setup doesn't define HOME.
- const char* home = getenv("HOME");
- if (home) {
- Path result;
- if (result.set(home))
- return result;
- }
- return GetRootDirectory();
+ char buff[MAX_PATH];
+ HRESULT res = SHGetFolderPathA(NULL,
+ CSIDL_FLAG_CREATE | CSIDL_APPDATA,
+ NULL,
+ SHGFP_TYPE_CURRENT,
+ buff);
+ if (res != S_OK)
+ assert(0 && "Failed to get user home directory");
+ return Path(buff);
}
Path
Path::GetCurrentDirectory() {
char pathname[MAX_PATH];
::GetCurrentDirectoryA(MAX_PATH,pathname);
- return Path(pathname);
+ return Path(pathname);
}
/// GetMainExecutable - Return the path to the main executable, given the
// FIXME: the above set of functions don't map to Windows very well.
-bool
-Path::isRootDirectory() const {
- size_t len = path.size();
- return len > 0 && path[len-1] == '/';
-}
-
-std::string Path::getDirname() const {
- return getDirnameCharSep(path, '/');
+StringRef Path::getDirname() const {
+ return getDirnameCharSep(path, "/");
}
-std::string
+StringRef
Path::getBasename() const {
// Find the last slash
size_t slash = path.rfind('/');
size_t dot = path.rfind('.');
if (dot == std::string::npos || dot < slash)
- return path.substr(slash);
+ return StringRef(path).substr(slash);
else
- return path.substr(slash, dot - slash);
+ return StringRef(path).substr(slash, dot - slash);
}
-std::string
+StringRef
Path::getSuffix() const {
// Find the last slash
size_t slash = path.rfind('/');
size_t dot = path.rfind('.');
if (dot == std::string::npos || dot < slash)
- return std::string();
+ return StringRef("");
else
- return path.substr(dot + 1);
+ return StringRef(path).substr(dot + 1);
}
bool
(attr & FILE_ATTRIBUTE_DIRECTORY);
}
+bool
+Path::isSymLink() const {
+ DWORD attributes = GetFileAttributes(path.c_str());
+
+ if (attributes == INVALID_FILE_ATTRIBUTES)
+ // There's no sane way to report this :(.
+ assert(0 && "GetFileAttributes returned INVALID_FILE_ATTRIBUTES");
+
+ // This isn't exactly what defines a NTFS symlink, but it is only true for
+ // paths that act like a symlink.
+ return attributes & FILE_ATTRIBUTE_REPARSE_POINT;
+}
+
bool
Path::canRead() const {
// FIXME: take security attributes into account.
return true;
}
-std::string
+StringRef
Path::getLast() const {
// Find the last slash
size_t pos = path.rfind('/');
return path;
// Return everything after the last slash
- return path.substr(pos+1);
+ return StringRef(path).substr(pos+1);
}
const FileStatus *
for (unsigned i = 0; i < path.length(); ++i)
status.uniqueID += path[i];
- __int64 ft = *reinterpret_cast<__int64*>(&fi.ftLastWriteTime);
- status.modTime.fromWin32Time(ft);
+ ULARGE_INTEGER ui;
+ ui.LowPart = fi.ftLastWriteTime.dwLowDateTime;
+ ui.HighPart = fi.ftLastWriteTime.dwHighDateTime;
+ status.modTime.fromWin32Time(ui.QuadPart);
status.isDir = fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
fsIsValid = true;
MakeErrMsg(ErrMsg, path + ": can't get status of file");
return true;
}
-
+
if (!(fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
if (ErrMsg)
*ErrMsg = path + ": not a directory";
}
bool
-Path::set(const std::string& a_path) {
+Path::set(StringRef a_path) {
if (a_path.empty())
return false;
std::string save(path);
}
bool
-Path::appendComponent(const std::string& name) {
+Path::appendComponent(StringRef name) {
if (name.empty())
return false;
std::string save(path);
return true;
}
-bool
-Path::appendSuffix(const std::string& suffix) {
- std::string save(path);
- path.append(".");
- path.append(suffix);
- if (!isValid()) {
- path = save;
- return false;
- }
- return true;
-}
-
bool
Path::eraseSuffix() {
size_t dotpos = path.rfind('.',path.size());
*next = 0;
if (!CreateDirectory(pathname, NULL) &&
GetLastError() != ERROR_ALREADY_EXISTS)
- return MakeErrMsg(ErrMsg,
+ return MakeErrMsg(ErrMsg,
std::string(pathname) + ": Can't create directory: ");
*next++ = '/';
}
pathname[len-1] = 0;
if (!CreateDirectory(pathname, NULL) &&
GetLastError() != ERROR_ALREADY_EXISTS) {
- return MakeErrMsg(ErrMsg, std::string(pathname) + ": Can't create directory: ");
+ return MakeErrMsg(ErrMsg, std::string(pathname) +
+ ": Can't create directory: ");
}
}
return false;
WIN32_FILE_ATTRIBUTE_DATA fi;
if (!GetFileAttributesEx(path.c_str(), GetFileExInfoStandard, &fi))
return true;
-
+
if (fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// If it doesn't exist, we're done.
if (!exists())
pathname[lastchar] = 0;
if (!RemoveDirectory(pathname))
- return MakeErrMsg(ErrStr,
+ return MakeErrMsg(ErrStr,
std::string(pathname) + ": Can't destroy directory: ");
return false;
} else {
bool Path::getMagicNumber(std::string& Magic, unsigned len) const {
assert(len < 1024 && "Request for magic string too long");
- char* buf = (char*) alloca(1 + len);
+ char* buf = reinterpret_cast<char*>(alloca(len));
HANDLE h = CreateFile(path.c_str(),
GENERIC_READ,
if (!ret || nRead != len)
return false;
- buf[len] = '\0';
- Magic = buf;
+ Magic = std::string(buf, len);
return true;
}
bool
Path::renamePathOnDisk(const Path& newName, std::string* ErrMsg) {
if (!MoveFileEx(path.c_str(), newName.c_str(), MOVEFILE_REPLACE_EXISTING))
- return MakeErrMsg(ErrMsg, "Can't move '" + path + "' to '" + newName.path
+ return MakeErrMsg(ErrMsg, "Can't move '" + path + "' to '" + newName.path
+ "': ");
return false;
}
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,
return MakeErrMsg(ErrMsg, path + ": GetFileInformationByHandle: ");
}
+ ULARGE_INTEGER ui;
+ ui.QuadPart = si.modTime.toWin32Time();
FILETIME ft;
- (uint64_t&)ft = si.modTime.toWin32Time();
+ ft.dwLowDateTime = ui.LowPart;
+ ft.dwHighDateTime = ui.HighPart;
BOOL ret = SetFileTime(h, NULL, &ft, &ft);
DWORD err = GetLastError();
CloseHandle(h);