Change Path::getStatusInfo to return a boolean and error string on an error
authorChris Lattner <sabre@nondot.org>
Fri, 28 Jul 2006 22:03:44 +0000 (22:03 +0000)
committerChris Lattner <sabre@nondot.org>
Fri, 28 Jul 2006 22:03:44 +0000 (22:03 +0000)
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

include/llvm/Bytecode/Archive.h
include/llvm/System/Path.h
lib/Archive/Archive.cpp
lib/Archive/ArchiveWriter.cpp
lib/Bytecode/Archive/Archive.cpp
lib/Bytecode/Archive/ArchiveWriter.cpp
lib/Debugger/ProgramInfo.cpp
lib/Support/FileUtilities.cpp
lib/System/Unix/Path.inc
tools/llvm-ar/llvm-ar.cpp
tools/llvm-db/Commands.cpp

index bd971cab7d0e7212c90739569d2a6d1613d77c0c..62a05bbcd80d32a43747c407b8c35c71831a7981 100644 (file)
@@ -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::PathaFile);
+    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;
index b4eaca7abf4e35635e9a3792861d29f8b69fb8a1..f8ff8f4233bd4a348a812779eba912c2bdf665fb 100644 (file)
 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::stringtoString() 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 charconst 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
index 66b9d703a0da117537d3ceae4cadc68000e55180..3bb9a05508384e9478e9a163f9eb67aadcabf791 100644 (file)
@@ -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
index 390fd128512f20e66164b5bbc9740968ea632d3c..52ba99e805493fae333de9f566570ac7236962bd 100644 (file)
@@ -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;
index 66b9d703a0da117537d3ceae4cadc68000e55180..3bb9a05508384e9478e9a163f9eb67aadcabf791 100644 (file)
@@ -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
index 390fd128512f20e66164b5bbc9740968ea632d3c..52ba99e805493fae333de9f566570ac7236962bd 100644 (file)
@@ -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;
index 66d38f73ca853c6bd816a76012dd969063528882..b60f5fc4bcfc7d0ee4264305d407e266b4fdfa73 100644 (file)
@@ -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;
index a7f42ddebf8c165dec4232b61e38874ef623cbbc..d4608ccb65b394a4b13d3bddcd9d04fe90b83fcc 100644 (file)
@@ -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);
index 4ca4753962fc54a91cfdd06fd751df03135a958e..a0d76b032b494d5d1c8ae3ee23e22998720dd95b 100644 (file)
@@ -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;
index 8bc9e048daf5b3735d737e2e7595fb3f06694ee0..2ec431727a6bf29d821a952d4a49a3408aaf94cd 100644 (file)
@@ -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.
index 1716e1ba49763b1e3f7cd5facb3d2df8f71f422d..da07769fbb083ce4f44749775e62586d1b4f64b4 100644 (file)
@@ -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.