Mostly cleanup, but also some bug fixes, for win32/Path.cpp

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@19202 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jeff Cohen 2004-12-31 19:01:08 +00:00
parent 92ced2f16a
commit 51b8d211f6
2 changed files with 162 additions and 76 deletions

View File

@ -20,7 +20,6 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "Win32.h" #include "Win32.h"
#include <fstream>
#include <malloc.h> #include <malloc.h>
// We need to undo a macro defined in Windows.h, otherwise we won't compile: // We need to undo a macro defined in Windows.h, otherwise we won't compile:
@ -205,23 +204,18 @@ Path::getBasename() const {
} }
bool Path::hasMagicNumber(const std::string &Magic) const { bool Path::hasMagicNumber(const std::string &Magic) const {
size_t len = Magic.size(); std::string actualMagic;
char *buf = reinterpret_cast<char *>(_alloca(len+1)); if (getMagicNumber(actualMagic, Magic.size()))
std::ifstream f(path.c_str()); return Magic == actualMagic;
f.read(buf, len); return false;
buf[len] = '\0';
return Magic == buf;
} }
bool bool
Path::isBytecodeFile() const { Path::isBytecodeFile() const {
char buffer[ 4]; std::string actualMagic;
buffer[0] = 0; if (!getMagicNumber(actualMagic, 4))
std::ifstream f(path.c_str()); return false;
f.read(buffer, 4); return actualMagic == "llvc" || actualMagic == "llvm";
if (f.bad())
ThrowErrno("can't read file signature");
return 0 == memcmp(buffer,"llvc",4) || 0 == memcmp(buffer,"llvm",4);
} }
bool bool
@ -357,9 +351,12 @@ Path::getDirectoryContents(std::set<Path>& result) const {
result.insert(aPath); result.insert(aPath);
} while (FindNextFile(h, &fd)); } while (FindNextFile(h, &fd));
CloseHandle(h); DWORD err = GetLastError();
if (GetLastError() != ERROR_NO_MORE_FILES) FindClose(h);
if (err != ERROR_NO_MORE_FILES) {
SetLastError(err);
ThrowError(path + ": Can't read directory: "); ThrowError(path + ": Can't read directory: ");
}
return true; return true;
} }
@ -539,7 +536,7 @@ Path::createFile() {
HANDLE h = CreateFile(path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_NEW, HANDLE h = CreateFile(path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_NEW,
FILE_ATTRIBUTE_NORMAL, NULL); FILE_ATTRIBUTE_NORMAL, NULL);
if (h == INVALID_HANDLE_VALUE) if (h == INVALID_HANDLE_VALUE)
ThrowError(std::string(path.c_str()) + ": Can't create file: "); ThrowError(path + ": Can't create file: ");
CloseHandle(h); CloseHandle(h);
return true; return true;
@ -560,17 +557,49 @@ Path::destroyDirectory(bool remove_contents) const {
pathname[lastchar] = 0; pathname[lastchar] = 0;
if (remove_contents) { if (remove_contents) {
// Recursively descend the directory to remove its content WIN32_FIND_DATA fd;
// FIXME: The correct way of doing this on Windows isn't pretty... HANDLE h = FindFirstFile(path.c_str(), &fd);
// but this may work if unix-like utils are present.
std::string cmd("rm -rf "); // It's a bad idea to alter the contents of a directory while enumerating
cmd += path; // its contents. So build a list of its contents first, then destroy them.
system(cmd.c_str());
} else { if (h != INVALID_HANDLE_VALUE) {
// Otherwise, try to just remove the one directory std::vector<Path> list;
if (!RemoveDirectory(pathname))
ThrowError(std::string(pathname) + ": Can't destroy directory: "); do {
if (strcmp(fd.cFileName, ".") == 0)
continue;
if (strcmp(fd.cFileName, "..") == 0)
continue;
Path aPath(path + &fd.cFileName[0]);
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
aPath.path += "/";
list.push_back(aPath);
} while (FindNextFile(h, &fd));
DWORD err = GetLastError();
FindClose(h);
if (err != ERROR_NO_MORE_FILES) {
SetLastError(err);
ThrowError(path + ": Can't read directory: ");
}
for (std::vector<Path>::iterator I = list.begin(); I != list.end(); ++I) {
Path &aPath = *I;
if (aPath.isDirectory())
aPath.destroyDirectory(true);
else
aPath.destroyFile();
}
} else {
if (GetLastError() != ERROR_NO_MORE_FILES)
ThrowError(path + ": Can't read directory: ");
}
} }
if (!RemoveDirectory(pathname))
ThrowError(std::string(pathname) + ": Can't destroy directory: ");
return true; return true;
} }
@ -588,11 +617,11 @@ Path::destroyFile() const {
// attribute first. // attribute first.
if (attr & FILE_ATTRIBUTE_READONLY) { if (attr & FILE_ATTRIBUTE_READONLY) {
if (!SetFileAttributes(path.c_str(), attr & ~FILE_ATTRIBUTE_READONLY)) if (!SetFileAttributes(path.c_str(), attr & ~FILE_ATTRIBUTE_READONLY))
ThrowError(std::string(path.c_str()) + ": Can't destroy file: "); ThrowError(path + ": Can't destroy file: ");
} }
if (!DeleteFile(path.c_str())) if (!DeleteFile(path.c_str()))
ThrowError(std::string(path.c_str()) + ": Can't destroy file: "); ThrowError(path + ": Can't destroy file: ");
return true; return true;
} }
@ -601,15 +630,24 @@ bool Path::getMagicNumber(std::string& Magic, unsigned len) const {
return false; return false;
assert(len < 1024 && "Request for magic string too long"); assert(len < 1024 && "Request for magic string too long");
char* buf = (char*) alloca(1 + len); char* buf = (char*) alloca(1 + len);
std::ofstream ofs(path.c_str(),std::ofstream::in);
if (!ofs.is_open()) HANDLE h = CreateFile(path.c_str(),
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (h == INVALID_HANDLE_VALUE)
return false; return false;
std::ifstream ifs(path.c_str());
if (!ifs.is_open()) DWORD nRead = 0;
BOOL ret = ReadFile(h, buf, len, &nRead, NULL);
CloseHandle(h);
if (!ret || nRead != len)
return false; return false;
ifs.read(buf, len);
ofs.close();
ifs.close();
buf[len] = '\0'; buf[len] = '\0';
Magic = buf; Magic = buf;
return true; return true;
@ -640,16 +678,21 @@ Path::setStatusInfo(const StatusInfo& si) const {
BY_HANDLE_FILE_INFORMATION bhfi; BY_HANDLE_FILE_INFORMATION bhfi;
if (!GetFileInformationByHandle(h, &bhfi)) { if (!GetFileInformationByHandle(h, &bhfi)) {
DWORD err = GetLastError();
CloseHandle(h); CloseHandle(h);
SetLastError(err);
ThrowError(path + ": GetFileInformationByHandle: "); ThrowError(path + ": GetFileInformationByHandle: ");
} }
FILETIME ft; FILETIME ft;
(uint64_t&)ft = si.modTime.toWin32Time(); (uint64_t&)ft = si.modTime.toWin32Time();
BOOL ret = SetFileTime(h, NULL, &ft, &ft); BOOL ret = SetFileTime(h, NULL, &ft, &ft);
DWORD err = GetLastError();
CloseHandle(h); CloseHandle(h);
if (!ret) if (!ret) {
SetLastError(err);
ThrowError(path + ": SetFileTime: "); ThrowError(path + ": SetFileTime: ");
}
// Best we can do with Unix permission bits is to interpret the owner // Best we can do with Unix permission bits is to interpret the owner
// writable bit. // writable bit.
@ -690,7 +733,7 @@ Path::makeUnique(bool reuse_current) {
char newName[MAX_PATH + 1]; char newName[MAX_PATH + 1];
if (!GetTempFileName(dir.c_str(), fname.c_str(), 0, newName)) if (!GetTempFileName(dir.c_str(), fname.c_str(), 0, newName))
ThrowError("Cannot make unique filename for '" + path + "'"); ThrowError("Cannot make unique filename for '" + path + "': ");
path = newName; path = newName;
} }

View File

@ -20,7 +20,6 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "Win32.h" #include "Win32.h"
#include <fstream>
#include <malloc.h> #include <malloc.h>
// We need to undo a macro defined in Windows.h, otherwise we won't compile: // We need to undo a macro defined in Windows.h, otherwise we won't compile:
@ -205,23 +204,18 @@ Path::getBasename() const {
} }
bool Path::hasMagicNumber(const std::string &Magic) const { bool Path::hasMagicNumber(const std::string &Magic) const {
size_t len = Magic.size(); std::string actualMagic;
char *buf = reinterpret_cast<char *>(_alloca(len+1)); if (getMagicNumber(actualMagic, Magic.size()))
std::ifstream f(path.c_str()); return Magic == actualMagic;
f.read(buf, len); return false;
buf[len] = '\0';
return Magic == buf;
} }
bool bool
Path::isBytecodeFile() const { Path::isBytecodeFile() const {
char buffer[ 4]; std::string actualMagic;
buffer[0] = 0; if (!getMagicNumber(actualMagic, 4))
std::ifstream f(path.c_str()); return false;
f.read(buffer, 4); return actualMagic == "llvc" || actualMagic == "llvm";
if (f.bad())
ThrowErrno("can't read file signature");
return 0 == memcmp(buffer,"llvc",4) || 0 == memcmp(buffer,"llvm",4);
} }
bool bool
@ -357,9 +351,12 @@ Path::getDirectoryContents(std::set<Path>& result) const {
result.insert(aPath); result.insert(aPath);
} while (FindNextFile(h, &fd)); } while (FindNextFile(h, &fd));
CloseHandle(h); DWORD err = GetLastError();
if (GetLastError() != ERROR_NO_MORE_FILES) FindClose(h);
if (err != ERROR_NO_MORE_FILES) {
SetLastError(err);
ThrowError(path + ": Can't read directory: "); ThrowError(path + ": Can't read directory: ");
}
return true; return true;
} }
@ -539,7 +536,7 @@ Path::createFile() {
HANDLE h = CreateFile(path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_NEW, HANDLE h = CreateFile(path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_NEW,
FILE_ATTRIBUTE_NORMAL, NULL); FILE_ATTRIBUTE_NORMAL, NULL);
if (h == INVALID_HANDLE_VALUE) if (h == INVALID_HANDLE_VALUE)
ThrowError(std::string(path.c_str()) + ": Can't create file: "); ThrowError(path + ": Can't create file: ");
CloseHandle(h); CloseHandle(h);
return true; return true;
@ -560,17 +557,49 @@ Path::destroyDirectory(bool remove_contents) const {
pathname[lastchar] = 0; pathname[lastchar] = 0;
if (remove_contents) { if (remove_contents) {
// Recursively descend the directory to remove its content WIN32_FIND_DATA fd;
// FIXME: The correct way of doing this on Windows isn't pretty... HANDLE h = FindFirstFile(path.c_str(), &fd);
// but this may work if unix-like utils are present.
std::string cmd("rm -rf "); // It's a bad idea to alter the contents of a directory while enumerating
cmd += path; // its contents. So build a list of its contents first, then destroy them.
system(cmd.c_str());
} else { if (h != INVALID_HANDLE_VALUE) {
// Otherwise, try to just remove the one directory std::vector<Path> list;
if (!RemoveDirectory(pathname))
ThrowError(std::string(pathname) + ": Can't destroy directory: "); do {
if (strcmp(fd.cFileName, ".") == 0)
continue;
if (strcmp(fd.cFileName, "..") == 0)
continue;
Path aPath(path + &fd.cFileName[0]);
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
aPath.path += "/";
list.push_back(aPath);
} while (FindNextFile(h, &fd));
DWORD err = GetLastError();
FindClose(h);
if (err != ERROR_NO_MORE_FILES) {
SetLastError(err);
ThrowError(path + ": Can't read directory: ");
}
for (std::vector<Path>::iterator I = list.begin(); I != list.end(); ++I) {
Path &aPath = *I;
if (aPath.isDirectory())
aPath.destroyDirectory(true);
else
aPath.destroyFile();
}
} else {
if (GetLastError() != ERROR_NO_MORE_FILES)
ThrowError(path + ": Can't read directory: ");
}
} }
if (!RemoveDirectory(pathname))
ThrowError(std::string(pathname) + ": Can't destroy directory: ");
return true; return true;
} }
@ -588,11 +617,11 @@ Path::destroyFile() const {
// attribute first. // attribute first.
if (attr & FILE_ATTRIBUTE_READONLY) { if (attr & FILE_ATTRIBUTE_READONLY) {
if (!SetFileAttributes(path.c_str(), attr & ~FILE_ATTRIBUTE_READONLY)) if (!SetFileAttributes(path.c_str(), attr & ~FILE_ATTRIBUTE_READONLY))
ThrowError(std::string(path.c_str()) + ": Can't destroy file: "); ThrowError(path + ": Can't destroy file: ");
} }
if (!DeleteFile(path.c_str())) if (!DeleteFile(path.c_str()))
ThrowError(std::string(path.c_str()) + ": Can't destroy file: "); ThrowError(path + ": Can't destroy file: ");
return true; return true;
} }
@ -601,15 +630,24 @@ bool Path::getMagicNumber(std::string& Magic, unsigned len) const {
return false; return false;
assert(len < 1024 && "Request for magic string too long"); assert(len < 1024 && "Request for magic string too long");
char* buf = (char*) alloca(1 + len); char* buf = (char*) alloca(1 + len);
std::ofstream ofs(path.c_str(),std::ofstream::in);
if (!ofs.is_open()) HANDLE h = CreateFile(path.c_str(),
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (h == INVALID_HANDLE_VALUE)
return false; return false;
std::ifstream ifs(path.c_str());
if (!ifs.is_open()) DWORD nRead = 0;
BOOL ret = ReadFile(h, buf, len, &nRead, NULL);
CloseHandle(h);
if (!ret || nRead != len)
return false; return false;
ifs.read(buf, len);
ofs.close();
ifs.close();
buf[len] = '\0'; buf[len] = '\0';
Magic = buf; Magic = buf;
return true; return true;
@ -640,16 +678,21 @@ Path::setStatusInfo(const StatusInfo& si) const {
BY_HANDLE_FILE_INFORMATION bhfi; BY_HANDLE_FILE_INFORMATION bhfi;
if (!GetFileInformationByHandle(h, &bhfi)) { if (!GetFileInformationByHandle(h, &bhfi)) {
DWORD err = GetLastError();
CloseHandle(h); CloseHandle(h);
SetLastError(err);
ThrowError(path + ": GetFileInformationByHandle: "); ThrowError(path + ": GetFileInformationByHandle: ");
} }
FILETIME ft; FILETIME ft;
(uint64_t&)ft = si.modTime.toWin32Time(); (uint64_t&)ft = si.modTime.toWin32Time();
BOOL ret = SetFileTime(h, NULL, &ft, &ft); BOOL ret = SetFileTime(h, NULL, &ft, &ft);
DWORD err = GetLastError();
CloseHandle(h); CloseHandle(h);
if (!ret) if (!ret) {
SetLastError(err);
ThrowError(path + ": SetFileTime: "); ThrowError(path + ": SetFileTime: ");
}
// Best we can do with Unix permission bits is to interpret the owner // Best we can do with Unix permission bits is to interpret the owner
// writable bit. // writable bit.
@ -690,7 +733,7 @@ Path::makeUnique(bool reuse_current) {
char newName[MAX_PATH + 1]; char newName[MAX_PATH + 1];
if (!GetTempFileName(dir.c_str(), fname.c_str(), 0, newName)) if (!GetTempFileName(dir.c_str(), fname.c_str(), 0, newName))
ThrowError("Cannot make unique filename for '" + path + "'"); ThrowError("Cannot make unique filename for '" + path + "': ");
path = newName; path = newName;
} }