diff options
-rw-r--r-- | include/llvm/Bytecode/Archive.h | 19 | ||||
-rw-r--r-- | include/llvm/System/Path.h | 100 | ||||
-rw-r--r-- | lib/Archive/Archive.cpp | 6 | ||||
-rw-r--r-- | lib/Archive/ArchiveWriter.cpp | 4 | ||||
-rw-r--r-- | lib/Bytecode/Archive/Archive.cpp | 6 | ||||
-rw-r--r-- | lib/Bytecode/Archive/ArchiveWriter.cpp | 4 | ||||
-rw-r--r-- | lib/Debugger/ProgramInfo.cpp | 5 | ||||
-rw-r--r-- | lib/Support/FileUtilities.cpp | 28 | ||||
-rw-r--r-- | lib/System/Unix/Path.inc | 30 | ||||
-rw-r--r-- | tools/llvm-ar/llvm-ar.cpp | 14 | ||||
-rw-r--r-- | tools/llvm-db/Commands.cpp | 8 |
11 files changed, 116 insertions, 108 deletions
diff --git a/include/llvm/Bytecode/Archive.h b/include/llvm/Bytecode/Archive.h index bd971cab7d..62a05bbcd8 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 b4eaca7abf..f8ff8f4233 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 66b9d703a0..3bb9a05508 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 390fd12851..52ba99e805 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 66b9d703a0..3bb9a05508 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 390fd12851..52ba99e805 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 66d38f73ca..b60f5fc4bc 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 a7f42ddebf..d4608ccb65 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 4ca4753962..a0d76b032b 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 8bc9e048da..2ec431727a 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 1716e1ba49..da07769fbb 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. |