From 2ae9d11b7c0fd54e0b5298fb4fcf17b6ee9d5c91 Mon Sep 17 00:00:00 2001 From: Reid Spencer Date: Sat, 7 Apr 2007 18:52:17 +0000 Subject: For PR1291: Implement the PathWithStatus class and its use throughout lib/System. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@35742 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/System/Unix/Path.inc | 89 +++++++++++++++++++++++---------------------- lib/System/Unix/Signals.inc | 12 ++++-- 2 files changed, 54 insertions(+), 47 deletions(-) (limited to 'lib/System/Unix') diff --git a/lib/System/Unix/Path.inc b/lib/System/Unix/Path.inc index 6ceffcd..53906d9 100644 --- a/lib/System/Unix/Path.inc +++ b/lib/System/Unix/Path.inc @@ -333,10 +333,10 @@ bool Path::canExecute() const { if (0 != access(path.c_str(), R_OK | X_OK )) return false; - if (const FileStatus *fs = getFileStatus(true, 0)) { - if (!S_ISREG(fs->mode)) - return false; - } else + struct stat buf; + if (0 != stat(path.c_str(), &buf)) + return false; + if (!S_ISREG(buf.st_mode)) return false; return true; } @@ -363,26 +363,25 @@ Path::getLast() const { return path.substr(pos+1); } -const FileStatus* -Path::getFileStatus(bool update, std::string *ErrStr) const { - if (status == 0 || update) { +const FileStatus * +PathWithStatus::getFileStatus(bool update, std::string *ErrStr) const { + if (!fsIsValid || update) { struct stat buf; if (0 != stat(path.c_str(), &buf)) { MakeErrMsg(ErrStr, path + ": can't get status of file"); return 0; } - if (status == 0) - status = new FileStatus; - status->fileSize = buf.st_size; - status->modTime.fromEpochTime(buf.st_mtime); - status->mode = buf.st_mode; - status->user = buf.st_uid; - status->group = buf.st_gid; - status->uniqueID = uint64_t(buf.st_ino); - status->isDir = S_ISDIR(buf.st_mode); - status->isFile = S_ISREG(buf.st_mode); + status.fileSize = buf.st_size; + status.modTime.fromEpochTime(buf.st_mtime); + status.mode = buf.st_mode; + status.user = buf.st_uid; + status.group = buf.st_gid; + status.uniqueID = uint64_t(buf.st_ino); + status.isDir = S_ISDIR(buf.st_mode); + status.isFile = S_ISREG(buf.st_mode); + fsIsValid = true; } - return status; + return &status; } static bool AddPermissionBits(const Path &File, int bits) { @@ -394,14 +393,13 @@ static bool AddPermissionBits(const Path &File, int bits) { umask(mask); // Restore the umask. // Get the file's current mode. - if (const FileStatus *fs = File.getFileStatus()) { - // Change the file to have whichever permissions bits from 'bits' - // that the umask would not disable. - if ((chmod(File.c_str(), (fs->getMode() | (bits & ~mask)))) == -1) - return false; - } else + struct stat buf; + if (0 != stat(File.toString().c_str(), &buf)) return false; - + // Change the file to have whichever permissions bits from 'bits' + // that the umask would not disable. + if ((chmod(File.c_str(), (buf.st_mode | (bits & ~mask)))) == -1) + return false; return true; } @@ -594,25 +592,28 @@ Path::createTemporaryFileOnDisk(bool reuse_current, std::string* ErrMsg) { bool Path::eraseFromDisk(bool remove_contents, std::string *ErrStr) const { - FileStatus Status; - if (const FileStatus *Status = getFileStatus(false, ErrStr)) { - // Note: this check catches strange situations. In all cases, LLVM should - // only be involved in the creation and deletion of regular files. This - // check ensures that what we're trying to erase is a regular file. It - // effectively prevents LLVM from erasing things like /dev/null, any block - // special file, or other things that aren't "regular" files. - if (Status->isFile) { - if (unlink(path.c_str()) != 0) - return MakeErrMsg(ErrStr, path + ": can't destroy file"); - return false; - } - - if (!Status->isDir) { - if (ErrStr) *ErrStr = "not a file or directory"; - return true; - } - } else + // Get the status so we can determin if its a file or directory + struct stat buf; + if (0 != stat(path.c_str(), &buf)) { + MakeErrMsg(ErrStr, path + ": can't get status of file"); return true; + } + + // Note: this check catches strange situations. In all cases, LLVM should + // only be involved in the creation and deletion of regular files. This + // check ensures that what we're trying to erase is a regular file. It + // effectively prevents LLVM from erasing things like /dev/null, any block + // special file, or other things that aren't "regular" files. + if (S_ISREG(buf.st_mode)) { + if (unlink(path.c_str()) != 0) + return MakeErrMsg(ErrStr, path + ": can't destroy file"); + return false; + } + + if (!S_ISDIR(buf.st_mode)) { + if (ErrStr) *ErrStr = "not a file or directory"; + return true; + } if (remove_contents) { // Recursively descend the directory to remove its contents. @@ -644,7 +645,7 @@ Path::renamePathOnDisk(const Path& newName, std::string* ErrMsg) { return false; } -bool +bool Path::setStatusInfoOnDisk(const FileStatus &si, std::string *ErrStr) const { struct utimbuf utb; utb.actime = si.modTime.toPosixTime(); diff --git a/lib/System/Unix/Signals.inc b/lib/System/Unix/Signals.inc index a471b95..d1493a2 100644 --- a/lib/System/Unix/Signals.inc +++ b/lib/System/Unix/Signals.inc @@ -21,6 +21,9 @@ #if HAVE_SIGNAL_H #include #endif +#if HAVE_SYS_STAT_H +#include +#endif using namespace llvm; namespace { @@ -168,10 +171,13 @@ bool sys::RemoveFileOnSignal(const sys::Path &Filename, std::string* ErrMsg) { // RemoveDirectoryOnSignal - The public API bool sys::RemoveDirectoryOnSignal(const sys::Path& path, std::string* ErrMsg) { // Not a directory? - const sys::FileStatus *Status = path.getFileStatus(false, ErrMsg); - if (!Status) + struct stat buf; + if (0 != stat(path.c_str(), &buf)) { + MakeErrMsg(ErrMsg, path.toString() + ": can't get status of file"); return true; - if (!Status->isDir) { + } + + if (!S_ISDIR(buf.st_mode)) { if (ErrMsg) *ErrMsg = path.toString() + " is not a directory"; return true; -- cgit v1.1