summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2006-07-28 22:03:44 +0000
committerChris Lattner <sabre@nondot.org>2006-07-28 22:03:44 +0000
commit252ad03d7db0add504fdcc6bd67c1bc1e28bdd57 (patch)
treeb53953cdbf21813671a66e76191e4bd39c4bf6e7
parent3236ced25f152ca3035b335008056cd91af5f8bf (diff)
Change Path::getStatusInfo to return a boolean and error string on an error
instead of throwing an exception. This reduces the amount of code that is exposed to exceptions (e.g. FileUtilities), though it is clearly only one step along the way. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@29395 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/Bytecode/Archive.h19
-rw-r--r--include/llvm/System/Path.h100
-rw-r--r--lib/Archive/Archive.cpp6
-rw-r--r--lib/Archive/ArchiveWriter.cpp4
-rw-r--r--lib/Bytecode/Archive/Archive.cpp6
-rw-r--r--lib/Bytecode/Archive/ArchiveWriter.cpp4
-rw-r--r--lib/Debugger/ProgramInfo.cpp5
-rw-r--r--lib/Support/FileUtilities.cpp28
-rw-r--r--lib/System/Unix/Path.inc30
-rw-r--r--tools/llvm-ar/llvm-ar.cpp14
-rw-r--r--tools/llvm-db/Commands.cpp8
11 files changed, 116 insertions, 108 deletions
diff --git a/include/llvm/Bytecode/Archive.h b/include/llvm/Bytecode/Archive.h
index bd971cab7d0..62a05bbcd80 100644
--- a/include/llvm/Bytecode/Archive.h
+++ b/include/llvm/Bytecode/Archive.h
@@ -40,7 +40,6 @@ class ArchiveMemberHeader; // Internal implementation class
/// of the Archive class instead.
/// @brief This class represents a single archive member.
class ArchiveMember {
-
/// @name Types
/// @{
public:
@@ -75,28 +74,28 @@ class ArchiveMember {
/// have any applicability on non-Unix systems but is a required component
/// of the "ar" file format.
/// @brief Get the user associated with this archive member.
- unsigned getUser() const { return info.user; }
+ unsigned getUser() const { return info.getUser(); }
/// The "group" is the owning group of the file per Unix security. This
/// may not have any applicability on non-Unix systems but is a required
/// component of the "ar" file format.
/// @brief Get the group associated with this archive member.
- unsigned getGroup() const { return info.group; }
+ unsigned getGroup() const { return info.getGroup(); }
/// The "mode" specifies the access permissions for the file per Unix
/// security. This may not have any applicabiity on non-Unix systems but is
/// a required component of the "ar" file format.
/// @brief Get the permission mode associated with this archive member.
- unsigned getMode() const { return info.mode; }
+ unsigned getMode() const { return info.getMode(); }
/// This method returns the time at which the archive member was last
/// modified when it was not in the archive.
/// @brief Get the time of last modification of the archive member.
- sys::TimeValue getModTime() const { return info.modTime; }
+ sys::TimeValue getModTime() const { return info.getTimestamp(); }
/// @returns the size of the archive member in bytes.
/// @brief Get the size of the archive member.
- unsigned getSize() const { return info.fileSize; }
+ unsigned getSize() const { return info.getSize(); }
/// This method returns the total size of the archive member as it
/// appears on disk. This includes the file content, the header, the
@@ -162,14 +161,14 @@ class ArchiveMember {
/// systems.
/// @returns the status info for the archive member
/// @brief Obtain the status info for the archive member
- const sys::Path::StatusInfo& getStatusInfo() const { return info; }
+ const sys::FileStatus &getFileStatus() const { return info; }
/// This method causes the archive member to be replaced with the contents
/// of the file specified by \p File. The contents of \p this will be
/// updated to reflect the new data from \p File. The \p File must exist and
/// be readable on entry to this method.
/// @brief Replace contents of archive member with a new file.
- void replaceWith(const sys::Path& aFile);
+ void replaceWith(const sys::Path &aFile);
/// @}
/// @name ilist methods - do not use
@@ -190,7 +189,7 @@ class ArchiveMember {
ArchiveMember* prev; ///< Pointer to previous archive member
Archive* parent; ///< Pointer to parent archive
sys::Path path; ///< Path of file containing the member
- sys::Path::StatusInfo info; ///< Status info (size,mode,date)
+ sys::FileStatus info; ///< Status info (size,mode,date)
unsigned flags; ///< Flags about the archive member
const void* data; ///< Data for the member
@@ -205,7 +204,7 @@ class ArchiveMember {
private:
/// Used internally by the Archive class to construct an ArchiveMember.
/// The contents of the ArchiveMember are filled out by the Archive class.
- ArchiveMember( Archive* PAR );
+ ArchiveMember(Archive *PAR);
// So Archive can construct an ArchiveMember
friend class llvm::Archive;
diff --git a/include/llvm/System/Path.h b/include/llvm/System/Path.h
index b4eaca7abf4..f8ff8f4233b 100644
--- a/include/llvm/System/Path.h
+++ b/include/llvm/System/Path.h
@@ -24,6 +24,35 @@
namespace llvm {
namespace sys {
+ /// This structure provides basic file system information about a file. It
+ /// is patterned after the stat(2) Unix operating system call but made
+ /// platform independent and eliminates many of the unix-specific fields.
+ /// However, to support llvm-ar, the mode, user, and group fields are
+ /// retained. These pertain to unix security and may not have a meaningful
+ /// value on non-Unix platforms. However, the fileSize and modTime fields
+ /// should always be applicable on all platforms. The structure is
+ /// filled in by the Path::getFileStatus method.
+ /// @brief File status structure
+ class FileStatus {
+ public:
+ uint64_t fileSize; ///< Size of the file in bytes
+ TimeValue modTime; ///< Time of file's modification
+ uint32_t mode; ///< Mode of the file, if applicable
+ uint32_t user; ///< User ID of owner, if applicable
+ uint32_t group; ///< Group ID of owner, if applicable
+ bool isDir : 1; ///< True if this is a directory.
+ bool isFile : 1; ///< True if this is a file.
+
+ FileStatus() : fileSize(0), modTime(0,0), mode(0777), user(999),
+ group(999), isDir(false) { }
+
+ TimeValue getTimestamp() const { return modTime; }
+ size_t getSize() const { return fileSize; }
+ uint32_t getMode() const { return mode; }
+ uint32_t getUser() const { return user; }
+ uint32_t getGroup() const { return group; }
+ };
+
/// This class provides an abstraction for the path to a file or directory
/// in the operating system's filesystem and provides various basic operations
/// on it. Note that this class only represents the name of a path to a file
@@ -53,30 +82,6 @@ namespace sys {
/// @since 1.4
/// @brief An abstraction for operating system paths.
class Path {
- /// @name Types
- /// @{
- public:
- /// This structure provides basic file system information about a file. It
- /// is patterned after the stat(2) Unix operating system call but made
- /// platform independent and eliminates many of the unix-specific fields.
- /// However, to support llvm-ar, the mode, user, and group fields are
- /// retained. These pertain to unix security and may not have a meaningful
- /// value on non-Unix platforms. However, the fileSize and modTime fields
- /// should always be applicabe on all platforms. The structure is
- /// filled in by the getStatusInfo method.
- /// @brief File status structure
- struct StatusInfo {
- StatusInfo() : fileSize(0), modTime(0,0), mode(0777), user(999),
- group(999), isDir(false) { }
- uint64_t fileSize; ///< Size of the file in bytes
- TimeValue modTime; ///< Time of file's modification
- uint32_t mode; ///< Mode of the file, if applicable
- uint32_t user; ///< User ID of owner, if applicable
- uint32_t group; ///< Group ID of owner, if applicable
- bool isDir; ///< True if this is a directory.
- };
-
- /// @}
/// @name Constructors
/// @{
public:
@@ -175,7 +180,7 @@ namespace sys {
/// Makes a copy of \p that to \p this.
/// @returns \p this
/// @brief Assignment Operator
- Path & operator = ( const Path & that ) {
+ Path &operator=(const Path &that) {
path = that.path;
return *this;
}
@@ -183,15 +188,15 @@ namespace sys {
/// Compares \p this Path with \p that Path for equality.
/// @returns true if \p this and \p that refer to the same thing.
/// @brief Equality Operator
- bool operator == (const Path& that) const {
- return 0 == path.compare(that.path) ;
+ bool operator==(const Path &that) const {
+ return 0 == path.compare(that.path);
}
/// Compares \p this Path with \p that Path for inequality.
/// @returns true if \p this and \p that refer to different things.
/// @brief Inequality Operator
- bool operator !=( const Path & that ) const {
- return 0 != path.compare( that.path );
+ bool operator!=(const Path &that) const {
+ return 0 != path.compare(that.path);
}
/// Determines if \p this Path is less than \p that Path. This is required
@@ -200,8 +205,8 @@ namespace sys {
/// the std::string::compare method.
/// @returns true if \p this path is lexicographically less than \p that.
/// @brief Less Than Operator
- bool operator< (const Path& that) const {
- return 0 > path.compare( that.path );
+ bool operator<(const Path& that) const {
+ return 0 > path.compare(that.path);
}
/// @}
@@ -228,7 +233,7 @@ namespace sys {
/// std::string. This allows the underlying path string to be manipulated.
/// @returns std::string containing the path name.
/// @brief Returns the path as a std::string.
- const std::string& toString() const { return path; }
+ const std::string &toString() const { return path; }
/// This function returns the last component of the path name. The last
/// component is the file or directory name occuring after the last
@@ -248,7 +253,7 @@ namespace sys {
/// Obtain a 'C' string for the path name.
/// @returns a 'C' string containing the path name.
/// @brief Returns the path as a C string.
- const char* const c_str() const { return path.c_str(); }
+ const char *const c_str() const { return path.c_str(); }
/// @}
/// @name Disk Accessors
@@ -362,31 +367,14 @@ namespace sys {
/// @returns false if \p this is not a directory, true otherwise
/// @throws std::string if the directory cannot be searched
/// @brief Build a list of directory's contents.
- bool getDirectoryContents(std::set<Path>& paths) const;
+ bool getDirectoryContents(std::set<Path> &paths) const;
/// This function returns status information about the file. The type of
/// path (file or directory) is updated to reflect the actual contents
- /// of the file system. If the file does not exist, false is returned.
- /// For other (hard I/O) errors, a std::string is thrown indicating the
- /// problem.
- /// @throws std::string if an error occurs.
+ /// of the file system. This returns false on success, or true on error
+ /// and fills in the specified error string if specified.
/// @brief Get file status.
- void getStatusInfo(StatusInfo& info) const;
-
- /// This function returns the last modified time stamp for the file
- /// referenced by this path. The Path may reference a file or a directory.
- /// If the file does not exist, a ZeroTime timestamp is returned.
- /// @returns last modified timestamp of the file/directory or ZeroTime
- /// @brief Get file timestamp.
- inline TimeValue getTimestamp() const {
- StatusInfo info; getStatusInfo(info); return info.modTime;
- }
-
- /// This function returns the size of the file referenced by this path.
- /// @brief Get file size.
- inline size_t getSize() const {
- StatusInfo info; getStatusInfo(info); return info.fileSize;
- }
+ bool getFileStatus(FileStatus &Status, std::string *Error = 0) const;
/// @}
/// @name Path Mutators
@@ -475,7 +463,7 @@ namespace sys {
/// @throws std::string if an error occurs.
/// @returns true
/// @brief Set the status information.
- bool setStatusInfoOnDisk(const StatusInfo& si) const;
+ bool setStatusInfoOnDisk(const FileStatus &SI) const;
/// This method attempts to create a directory in the file system with the
/// same name as the Path object. The \p create_parents parameter controls
@@ -538,7 +526,7 @@ namespace sys {
/// refers to something that is neither a file nor a directory.
/// @throws std::string if there is an error.
/// @brief Removes the file or directory from the filesystem.
- bool eraseFromDisk( bool destroy_contents = false ) const;
+ bool eraseFromDisk(bool destroy_contents = false) const;
/// @}
/// @name Data
diff --git a/lib/Archive/Archive.cpp b/lib/Archive/Archive.cpp
index 66b9d703a0d..3bb9a055083 100644
--- a/lib/Archive/Archive.cpp
+++ b/lib/Archive/Archive.cpp
@@ -104,12 +104,14 @@ void ArchiveMember::replaceWith(const sys::Path& newFile) {
flags &= ~HasLongFilenameFlag;
// Get the signature and status info
- std::string magic;
const char* signature = (const char*) data;
+ std::string magic;
if (!signature) {
path.getMagicNumber(magic,4);
signature = magic.c_str();
- path.getStatusInfo(info);
+ std::string err;
+ if (path.getFileStatus(info, &err))
+ throw err;
}
// Determine what kind of file it is
diff --git a/lib/Archive/ArchiveWriter.cpp b/lib/Archive/ArchiveWriter.cpp
index 390fd128512..52ba99e8054 100644
--- a/lib/Archive/ArchiveWriter.cpp
+++ b/lib/Archive/ArchiveWriter.cpp
@@ -159,7 +159,9 @@ Archive::addFileBefore(const sys::Path& filePath, iterator where) {
mbr->data = 0;
mbr->path = filePath;
- mbr->path.getStatusInfo(mbr->info);
+ std::string err;
+ if (mbr->path.getFileStatus(mbr->info, &err))
+ throw err;
unsigned flags = 0;
bool hasSlash = filePath.toString().find('/') != std::string::npos;
diff --git a/lib/Bytecode/Archive/Archive.cpp b/lib/Bytecode/Archive/Archive.cpp
index 66b9d703a0d..3bb9a055083 100644
--- a/lib/Bytecode/Archive/Archive.cpp
+++ b/lib/Bytecode/Archive/Archive.cpp
@@ -104,12 +104,14 @@ void ArchiveMember::replaceWith(const sys::Path& newFile) {
flags &= ~HasLongFilenameFlag;
// Get the signature and status info
- std::string magic;
const char* signature = (const char*) data;
+ std::string magic;
if (!signature) {
path.getMagicNumber(magic,4);
signature = magic.c_str();
- path.getStatusInfo(info);
+ std::string err;
+ if (path.getFileStatus(info, &err))
+ throw err;
}
// Determine what kind of file it is
diff --git a/lib/Bytecode/Archive/ArchiveWriter.cpp b/lib/Bytecode/Archive/ArchiveWriter.cpp
index 390fd128512..52ba99e8054 100644
--- a/lib/Bytecode/Archive/ArchiveWriter.cpp
+++ b/lib/Bytecode/Archive/ArchiveWriter.cpp
@@ -159,7 +159,9 @@ Archive::addFileBefore(const sys::Path& filePath, iterator where) {
mbr->data = 0;
mbr->path = filePath;
- mbr->path.getStatusInfo(mbr->info);
+ std::string err;
+ if (mbr->path.getFileStatus(mbr->info, &err))
+ throw err;
unsigned flags = 0;
bool hasSlash = filePath.toString().find('/') != std::string::npos;
diff --git a/lib/Debugger/ProgramInfo.cpp b/lib/Debugger/ProgramInfo.cpp
index 66d38f73ca8..b60f5fc4bcf 100644
--- a/lib/Debugger/ProgramInfo.cpp
+++ b/lib/Debugger/ProgramInfo.cpp
@@ -196,8 +196,9 @@ void SourceFunctionInfo::getSourceLocation(unsigned &RetLineNo,
ProgramInfo::ProgramInfo(Module *m) : M(m), ProgramTimeStamp(0,0) {
assert(M && "Cannot create program information with a null module!");
- sys::Path modulePath(M->getModuleIdentifier());
- ProgramTimeStamp = modulePath.getTimestamp();
+ sys::FileStatus Stat;
+ if (!sys::Path(M->getModuleIdentifier()).getFileStatus(Stat))
+ ProgramTimeStamp = Stat.getTimestamp();
SourceFilesIsComplete = false;
SourceFunctionsIsComplete = false;
diff --git a/lib/Support/FileUtilities.cpp b/lib/Support/FileUtilities.cpp
index a7f42ddebf8..d4608ccb65b 100644
--- a/lib/Support/FileUtilities.cpp
+++ b/lib/Support/FileUtilities.cpp
@@ -146,19 +146,23 @@ int llvm::DiffFilesWithTolerance(const sys::Path &FileA,
const sys::Path &FileB,
double AbsTol, double RelTol,
std::string *Error) {
- try {
- // Check for zero length files because some systems croak when you try to
- // mmap an empty file.
- size_t A_size = FileA.getSize();
- size_t B_size = FileB.getSize();
-
- // If they are both zero sized then they're the same
- if (A_size == 0 && B_size == 0)
- return 0;
- // If only one of them is zero sized then they can't be the same
- if ((A_size == 0 || B_size == 0))
- return 1;
+ sys::FileStatus FileAStat, FileBStat;
+ if (FileA.getFileStatus(FileAStat, Error) ||
+ FileB.getFileStatus(FileBStat, Error))
+ return 2;
+ // Check for zero length files because some systems croak when you try to
+ // mmap an empty file.
+ size_t A_size = FileAStat.getSize();
+ size_t B_size = FileBStat.getSize();
+
+ // If they are both zero sized then they're the same
+ if (A_size == 0 && B_size == 0)
+ return 0;
+ // If only one of them is zero sized then they can't be the same
+ if ((A_size == 0 || B_size == 0))
+ return 1;
+ try {
// Now its safe to mmap the files into memory becasue both files
// have a non-zero size.
sys::MappedFile F1(FileA);
diff --git a/lib/System/Unix/Path.inc b/lib/System/Unix/Path.inc
index 4ca4753962f..a0d76b032b4 100644
--- a/lib/System/Unix/Path.inc
+++ b/lib/System/Unix/Path.inc
@@ -386,21 +386,22 @@ Path::getLast() const {
return path.substr(pos+1);
}
-void
-Path::getStatusInfo(StatusInfo& info) const {
+bool
+Path::getFileStatus(FileStatus &info, std::string *ErrStr) const {
struct stat buf;
- if (0 != stat(path.c_str(), &buf)) {
- ThrowErrno(path + ": can't determine type of path object: ");
- }
+ if (0 != stat(path.c_str(), &buf))
+ return GetErrno(path + ": can't determine type of path object: ", ErrStr);
info.fileSize = buf.st_size;
info.modTime.fromEpochTime(buf.st_mtime);
info.mode = buf.st_mode;
info.user = buf.st_uid;
info.group = buf.st_gid;
- info.isDir = S_ISDIR(buf.st_mode);
+ info.isDir = S_ISDIR(buf.st_mode);
+ info.isFile = S_ISREG(buf.st_mode);
+ return false;
}
-static bool AddPermissionBits(const std::string& Filename, int bits) {
+static bool AddPermissionBits(const Path &File, int bits) {
// Get the umask value from the operating system. We want to use it
// when changing the file's permissions. Since calling umask() sets
// the umask and returns its old value, we must call it a second
@@ -409,30 +410,29 @@ static bool AddPermissionBits(const std::string& Filename, int bits) {
umask(mask); // Restore the umask.
// Get the file's current mode.
- struct stat st;
- if ((stat(Filename.c_str(), &st)) == -1)
- return false;
+ FileStatus Stat;
+ if (File.getFileStatus(Stat)) return false;
// Change the file to have whichever permissions bits from 'bits'
// that the umask would not disable.
- if ((chmod(Filename.c_str(), (st.st_mode | (bits & ~mask)))) == -1)
+ if ((chmod(File.c_str(), (Stat.getMode() | (bits & ~mask)))) == -1)
return false;
return true;
}
void Path::makeReadableOnDisk() {
- if (!AddPermissionBits(path,0444))
+ if (!AddPermissionBits(*this, 0444))
ThrowErrno(path + ": can't make file readable");
}
void Path::makeWriteableOnDisk() {
- if (!AddPermissionBits(path,0222))
+ if (!AddPermissionBits(*this, 0222))
ThrowErrno(path + ": can't make file writable");
}
void Path::makeExecutableOnDisk() {
- if (!AddPermissionBits(path,0111))
+ if (!AddPermissionBits(*this, 0111))
ThrowErrno(path + ": can't make file executable");
}
@@ -642,7 +642,7 @@ Path::renamePathOnDisk(const Path& newName) {
}
bool
-Path::setStatusInfoOnDisk(const StatusInfo& si) const {
+Path::setStatusInfoOnDisk(const FileStatus &si) const {
struct utimbuf utb;
utb.actime = si.modTime.toPosixTime();
utb.modtime = utb.actime;
diff --git a/tools/llvm-ar/llvm-ar.cpp b/tools/llvm-ar/llvm-ar.cpp
index 8bc9e048daf..2ec431727a6 100644
--- a/tools/llvm-ar/llvm-ar.cpp
+++ b/tools/llvm-ar/llvm-ar.cpp
@@ -299,8 +299,10 @@ void buildPaths(bool checkExistence = true) {
if (checkExistence) {
if (!aPath.exists())
throw std::string("File does not exist: ") + Members[i];
- sys::Path::StatusInfo si;
- aPath.getStatusInfo(si);
+ sys::FileStatus si;
+ std::string Err;
+ if (aPath.getFileStatus(si, &Err))
+ throw Err;
if (si.isDir) {
std::set<sys::Path> dirpaths = recurseDirectories(aPath);
Paths.insert(dirpaths.begin(),dirpaths.end());
@@ -456,7 +458,7 @@ void doExtract() {
// If we're supposed to retain the original modification times, etc. do so
// now.
if (OriginalDates)
- I->getPath().setStatusInfoOnDisk(I->getStatusInfo());
+ I->getPath().setStatusInfoOnDisk(I->getFileStatus());
}
}
}
@@ -610,8 +612,10 @@ void doReplaceOrInsert() {
}
if (found != remaining.end()) {
- sys::Path::StatusInfo si;
- found->getStatusInfo(si);
+ sys::FileStatus si;
+ std::string Err;
+ if (found->getFileStatus(si, &Err))
+ throw Err;
if (si.isDir) {
if (OnlyUpdate) {
// Replace the item only if it is newer.
diff --git a/tools/llvm-db/Commands.cpp b/tools/llvm-db/Commands.cpp
index 1716e1ba497..da07769fbb0 100644
--- a/tools/llvm-db/Commands.cpp
+++ b/tools/llvm-db/Commands.cpp
@@ -49,8 +49,12 @@ void CLIDebugger::startProgramRunning() {
eliminateRunInfo();
// If the program has been modified, reload it!
- sys::Path Program (Dbg.getProgramPath());
- if (TheProgramInfo->getProgramTimeStamp() != Program.getTimestamp()) {
+ sys::Path Program(Dbg.getProgramPath());
+ sys::FileStatus Status;
+ std::string Err;
+ if (Program.getFileStatus(Status, &Err))
+ throw Err;
+ if (TheProgramInfo->getProgramTimeStamp() != Status.getTimestamp()) {
std::cout << "'" << Program << "' has changed; re-reading program.\n";
// Unload an existing program. This kills the program if necessary.