summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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.