-//===- llvm/System/Linux/Path.cpp - Linux Path Implementation ---*- C++ -*-===//
+//===- llvm/System/Win32/Path.cpp - Win32 Path Implementation ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
#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
namespace sys {
const char PathSeparator = ';';
+Path::Path(llvm::StringRef p)
+ : path(p) {
+ FlipBackSlashes(path);
+}
+
+Path::Path(const char *StrStart, unsigned StrLen)
+ : path(StrStart, StrLen) {
+ FlipBackSlashes(path);
+}
+
+Path&
+Path::operator=(StringRef that) {
+ path.assign(that.data(), that.size());
+ FlipBackSlashes(path);
+ return *this;
+}
+
bool
Path::isValid() const {
if (path.empty())
return true;
}
-bool
+void Path::makeAbsolute() {
+ TCHAR FullPath[MAX_PATH + 1] = {0};
+ LPTSTR FilePart = NULL;
+
+ DWORD RetLength = ::GetFullPathNameA(path.c_str(),
+ sizeof(FullPath)/sizeof(FullPath[0]),
+ FullPath, &FilePart);
+
+ if (0 == RetLength) {
+ // FIXME: Report the error GetLastError()
+ assert(0 && "Unable to make absolute path!");
+ } else if (RetLength > MAX_PATH) {
+ // FIXME: Report too small buffer (needed RetLength bytes).
+ assert(0 && "Unable to make absolute path!");
+ } else {
+ path = FullPath;
+ }
+}
+
+bool
+Path::isAbsolute(const char *NameStart, unsigned NameLen) {
+ assert(NameStart);
+ // FIXME: This does not handle correctly an absolute path starting from
+ // a drive letter or in UNC format.
+ switch (NameLen) {
+ case 0:
+ return false;
+ case 1:
+ case 2:
+ return NameStart[0] == '/';
+ default:
+ return (NameStart[0] == '/' || (NameStart[1] == ':' && NameStart[2] == '/')) ||
+ (NameStart[0] == '\\' || (NameStart[1] == ':' && NameStart[2] == '\\'));
+ }
+}
+
+bool
Path::isAbsolute() const {
+ // FIXME: This does not handle correctly an absolute path starting from
+ // a drive letter or in UNC format.
switch (path.length()) {
case 0:
return false;
default:
return path[0] == '/' || (path[1] == ':' && path[2] == '/');
}
-}
+}
-static Path *TempDirectory = NULL;
+static Path *TempDirectory;
Path
Path::GetTemporaryDirectory(std::string* ErrMsg) {
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
/// value of argv[0] from program startup.
Path Path::GetMainExecutable(const char *argv0, void *MainAddr) {
- return Path();
+ 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.
-bool
-Path::isRootDirectory() const {
- size_t len = path.size();
- return len > 0 && path[len-1] == '/';
+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);
+}
+
+StringRef
+Path::getSuffix() const {
+ // Find the last slash
+ size_t slash = path.rfind('/');
+ if (slash == std::string::npos)
+ slash = 0;
+ else
+ slash++;
+
+ size_t dot = path.rfind('.');
+ if (dot == std::string::npos || dot < slash)
+ return StringRef("");
+ else
+ return StringRef(path).substr(dot + 1);
}
bool
return attr != INVALID_FILE_ATTRIBUTES;
}
-std::string
+bool
+Path::isRegularFile() const {
+ if (isDirectory())
+ return false;
+ return true;
+}
+
+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);
}
bool
-Path::appendSuffix(const std::string& suffix) {
+Path::appendSuffix(StringRef suffix) {
std::string save(path);
path.append(".");
path.append(suffix);
while (*next) {
next = strchr(next, '/');
*next = 0;
- if (!CreateDirectory(pathname, NULL))
- return MakeErrMsg(ErrMsg,
+ if (!CreateDirectory(pathname, NULL) &&
+ GetLastError() != ERROR_ALREADY_EXISTS)
+ return MakeErrMsg(ErrMsg,
std::string(pathname) + ": Can't create directory: ");
*next++ = '/';
}
} else {
// Drop trailing slash.
pathname[len-1] = 0;
- if (!CreateDirectory(pathname, NULL)) {
+ if (!CreateDirectory(pathname, NULL) &&
+ GetLastError() != ERROR_ALREADY_EXISTS) {
return MakeErrMsg(ErrMsg, std::string(pathname) + ": Can't create directory: ");
}
}
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 true;
+ return false;
}
bool
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);
// 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))
- return MakeErrMsg(ErrMsg, "Can't copy '" + Src.toString() +
- "' to '" + Dest.toString() + "': ");
+ return MakeErrMsg(ErrMsg, "Can't copy '" + Src.str() +
+ "' to '" + Dest.str() + "': ");
return false;
}
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");
+}
+
}
}