For PR797:
Remove exceptions from the Path::create*OnDisk methods. Update their users
to handle error messages via arguments and result codes.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@29840 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/llvm/System/Path.h b/include/llvm/System/Path.h
index 306ce84..e354efe 100644
--- a/include/llvm/System/Path.h
+++ b/include/llvm/System/Path.h
@@ -424,18 +424,18 @@
       /// This method attempts to make the file referenced by the Path object
       /// available for reading so that the canRead() method will return true.
       /// @brief Make the file readable;
-      bool makeReadableOnDisk(std::string* ErrMsg);
+      bool makeReadableOnDisk(std::string* ErrMsg = 0);
 
       /// This method attempts to make the file referenced by the Path object
       /// available for writing so that the canWrite() method will return true.
       /// @brief Make the file writable;
-      bool makeWriteableOnDisk(std::string* ErrMsg);
+      bool makeWriteableOnDisk(std::string* ErrMsg = 0);
 
       /// This method attempts to make the file referenced by the Path object
       /// available for execution so that the canExecute() method will return
       /// true.
       /// @brief Make the file readable;
-      bool makeExecutableOnDisk(std::string* ErrMsg);
+      bool makeExecutableOnDisk(std::string* ErrMsg = 0);
 
       /// This method allows the last modified time stamp and permission bits
       /// to be set on the disk object referenced by the Path.
@@ -452,23 +452,25 @@
       /// intermediate directories, as needed. If \p create_parents is false,
       /// then only the final directory component of the Path name will be
       /// created. The created directory will have no entries.
-      /// @returns false if the Path does not reference a directory, true
-      /// otherwise.
-      /// @param create_parents Determines whether non-existent directory
-      /// components other than the last one (the "parents") are created or not.
-      /// @throws std::string if an error occurs.
+      /// @returns true if the directory could not be created, false otherwise
       /// @brief Create the directory this Path refers to.
-      bool createDirectoryOnDisk( bool create_parents = false );
+      bool createDirectoryOnDisk( 
+        bool create_parents = false, ///<  Determines whether non-existent 
+           ///< directory components other than the last one (the "parents") 
+           ///< are created or not.
+        std::string* ErrMsg = 0 ///< Optional place to put error messages.
+      );
 
       /// This method attempts to create a file in the file system with the same
       /// name as the Path object. The intermediate directories must all exist
       /// at the time this method is called. Use createDirectoriesOnDisk to
       /// accomplish that. The created file will be empty upon return from this
       /// function.
-      /// @returns false if the Path does not reference a file, true otherwise.
-      /// @throws std::string if an error occurs.
+      /// @returns true if the file could not be created, false otherwise.
       /// @brief Create the file this Path refers to.
-      bool createFileOnDisk();
+      bool createFileOnDisk(
+        std::string* ErrMsg = 0 ///< Optional place to put error messages.
+      );
 
       /// This is like createFile except that it creates a temporary file. A
       /// unique temporary file name is generated based on the contents of
@@ -476,14 +478,14 @@
       /// file is created.  Note that this will both change the Path object
       /// *and* create the corresponding file. This function will ensure that
       /// the newly generated temporary file name is unique in the file system.
-      /// @param reuse_current When set to true, this parameter indicates that
-      /// if the current file name does not exist then it will be used without
-      /// modification.
-      /// @returns true if successful, false if the file couldn't be created.
-      /// @throws std::string if there is a hard error creating the temp file
-      /// name.
+      /// @returns true if the file couldn't be created, false otherwise. 
       /// @brief Create a unique temporary file
-      bool createTemporaryFileOnDisk(bool reuse_current = false);
+      bool createTemporaryFileOnDisk(
+        bool reuse_current = false, ///< When set to true, this parameter 
+          ///< indicates that if the current file name does not exist then 
+          ///< it will be used without modification.
+        std::string* ErrMsg = 0 ///< Optional place to put error messages
+      );
 
       /// This method renames the file referenced by \p this as \p newName. The
       /// file referenced by \p this must exist. The file referenced by
diff --git a/lib/Archive/ArchiveWriter.cpp b/lib/Archive/ArchiveWriter.cpp
index c99d851..c3fda5f 100644
--- a/lib/Archive/ArchiveWriter.cpp
+++ b/lib/Archive/ArchiveWriter.cpp
@@ -389,7 +389,8 @@
 
   // Create a temporary file to store the archive in
   sys::Path TmpArchive = archPath;
-  TmpArchive.createTemporaryFileOnDisk();
+  if (TmpArchive.createTemporaryFileOnDisk(error))
+    return false;
 
   // Make sure the temporary gets removed if we crash
   sys::RemoveFileOnSignal(TmpArchive);
@@ -452,7 +453,8 @@
     // Open another temporary file in order to avoid invalidating the 
     // mmapped data
     sys::Path FinalFilePath = archPath;
-    FinalFilePath.createTemporaryFileOnDisk();
+    if (FinalFilePath.createTemporaryFileOnDisk(error))
+      return false;
     sys::RemoveFileOnSignal(FinalFilePath);
 
     std::ofstream FinalFile(FinalFilePath.c_str(), io_mode);
diff --git a/lib/Bytecode/Archive/ArchiveWriter.cpp b/lib/Bytecode/Archive/ArchiveWriter.cpp
index c99d851..c3fda5f 100644
--- a/lib/Bytecode/Archive/ArchiveWriter.cpp
+++ b/lib/Bytecode/Archive/ArchiveWriter.cpp
@@ -389,7 +389,8 @@
 
   // Create a temporary file to store the archive in
   sys::Path TmpArchive = archPath;
-  TmpArchive.createTemporaryFileOnDisk();
+  if (TmpArchive.createTemporaryFileOnDisk(error))
+    return false;
 
   // Make sure the temporary gets removed if we crash
   sys::RemoveFileOnSignal(TmpArchive);
@@ -452,7 +453,8 @@
     // Open another temporary file in order to avoid invalidating the 
     // mmapped data
     sys::Path FinalFilePath = archPath;
-    FinalFilePath.createTemporaryFileOnDisk();
+    if (FinalFilePath.createTemporaryFileOnDisk(error))
+      return false;
     sys::RemoveFileOnSignal(FinalFilePath);
 
     std::ofstream FinalFile(FinalFilePath.c_str(), io_mode);
diff --git a/lib/System/Unix/Path.inc b/lib/System/Unix/Path.inc
index db7f4c6..7fc77a9 100644
--- a/lib/System/Unix/Path.inc
+++ b/lib/System/Unix/Path.inc
@@ -517,7 +517,7 @@
 }
 
 bool
-Path::createDirectoryOnDisk( bool create_parents) {
+Path::createDirectoryOnDisk( bool create_parents, std::string* ErrMsg ) {
   // Get a writeable copy of the path name
   char pathname[MAXPATHLEN];
   path.copy(pathname,MAXPATHLEN);
@@ -540,8 +540,11 @@
     while ( next != 0 ) {
       *next = 0;
       if (0 != access(pathname, F_OK | R_OK | W_OK))
-        if (0 != mkdir(pathname, S_IRWXU | S_IRWXG))
-          ThrowErrno(std::string(pathname) + ": can't create directory");
+        if (0 != mkdir(pathname, S_IRWXU | S_IRWXG)) {
+          MakeErrMsg(ErrMsg, 
+            std::string(pathname) + ": can't create directory");
+          return true;
+        }
       char* save = next;
       next = strchr(next+1,'/');
       *save = '/';
@@ -549,33 +552,37 @@
   } 
 
   if (0 != access(pathname, F_OK | R_OK))
-    if (0 != mkdir(pathname, S_IRWXU | S_IRWXG))
-      ThrowErrno(std::string(pathname) + ": can't create directory");
-  return true;
+    if (0 != mkdir(pathname, S_IRWXU | S_IRWXG)) {
+      MakeErrMsg(ErrMsg, std::string(pathname) + ": can't create directory");
+      return true;
+    }
+  return false;
 }
 
 bool
-Path::createFileOnDisk() {
+Path::createFileOnDisk(std::string* ErrMsg) {
   // Create the file
   int fd = ::creat(path.c_str(), S_IRUSR | S_IWUSR);
-  if (fd < 0)
-    ThrowErrno(path + ": can't create file");
+  if (fd < 0) {
+    MakeErrMsg(ErrMsg, path + ": can't create file");
+    return true;
+  }
   ::close(fd);
-
-  return true;
+  return false;
 }
 
 bool
-Path::createTemporaryFileOnDisk(bool reuse_current) {
+Path::createTemporaryFileOnDisk(bool reuse_current, std::string* ErrMsg) {
   // Make this into a unique file name
   makeUnique( reuse_current );
 
   // create the file
-  int outFile = ::open(path.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0666);
-  if (outFile != -1) {
-    ::close(outFile);
+  int fd = ::open(path.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0666);
+  if (fd < 0) {
+    MakeErrMsg(ErrMsg, path + ": can't create temporary file");
     return true;
   }
+  ::close(fd);
   return false;
 }
 
diff --git a/tools/llvm-ar/llvm-ar.cpp b/tools/llvm-ar/llvm-ar.cpp
index d2d8c85..e5abea4 100644
--- a/tools/llvm-ar/llvm-ar.cpp
+++ b/tools/llvm-ar/llvm-ar.cpp
@@ -425,8 +425,8 @@
 }
 
 // doExtract - Implement the 'x' operation. This function extracts files back to
-// the file system, making sure to uncompress any that were compressed.
-void doExtract() {
+// the file system, making sure to uncompress any that were compressed
+bool doExtract(std::string* ErrMsg) {
   buildPaths(false);
   unsigned countDown = Count;
   for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end();
@@ -438,7 +438,8 @@
       if (I->hasPath()) {
         sys::Path dirs(I->getPath());
         dirs.eraseComponent();
-        dirs.createDirectoryOnDisk(/*create_parents=*/true);
+        if (dirs.createDirectoryOnDisk(/*create_parents=*/true, ErrMsg)) 
+          return true;
       }
 
       // Open up a file stream for writing
@@ -464,6 +465,7 @@
         I->getPath().setStatusInfoOnDisk(I->getFileStatus());
     }
   }
+  return false;
 }
 
 // doDelete - Implement the delete operation. This function deletes zero or more
@@ -711,6 +713,7 @@
     std::auto_ptr<Archive> AutoArchive(TheArchive);
 
     // Perform the operation
+    std::string ErrMsg;
     switch (Operation) {
       case Print:           doPrint(); break;
       case Delete:          doDelete(); break;
@@ -718,7 +721,12 @@
       case QuickAppend:      /* FALL THROUGH */
       case ReplaceOrInsert: doReplaceOrInsert(); break;
       case DisplayTable:    doDisplayTable(); break;
-      case Extract:         doExtract(); break;
+      case Extract:         
+        if (doExtract(&ErrMsg)) {
+          std::cerr << argv[0] << ": " << ErrMsg << "\n";
+          return 1;
+        }
+        break;
       case NoOperation:
         std::cerr << argv[0] << ": No operation was selected.\n";
         break;
diff --git a/tools/llvm-ld/llvm-ld.cpp b/tools/llvm-ld/llvm-ld.cpp
index 679522f..53f04e6 100644
--- a/tools/llvm-ld/llvm-ld.cpp
+++ b/tools/llvm-ld/llvm-ld.cpp
@@ -492,16 +492,15 @@
           }
           // Get the program arguments
           sys::Path tmp_output("opt_result");
-          if (!tmp_output.createTemporaryFileOnDisk()) {
-            return PrintAndReturn(
-              "Can't create temporary file for post-link optimization");
+          std::string ErrMsg;
+          if (tmp_output.createTemporaryFileOnDisk(&ErrMsg)) {
+            return PrintAndReturn(ErrMsg);
           }
           const char* args[4];
           args[0] = I->c_str();
           args[1] = RealBytecodeOutput.c_str();
           args[2] = tmp_output.c_str();
           args[3] = 0;
-          std::string ErrMsg;
           if (0 == sys::Program::ExecuteAndWait(prog, args, 0,0,0, &ErrMsg)) {
             if (tmp_output.isBytecodeFile()) {
               sys::Path target(RealBytecodeOutput);
diff --git a/tools/lto/lto.cpp b/tools/lto/lto.cpp
index 570558a..372e6ea 100644
--- a/tools/lto/lto.cpp
+++ b/tools/lto/lto.cpp
@@ -295,7 +295,11 @@
   }
 
   sys::Path tmpAsmFilePath("/tmp/");
-  tmpAsmFilePath.createTemporaryFileOnDisk();
+  std::string ErrMsg;
+  if (tmpAsmFilePath.createTemporaryFileOnDisk(&ErrMsg)) {
+    std::cerr << "lto: " << ErrMsg << "\n";
+    return;
+  }
   sys::RemoveFileOnSignal(tmpAsmFilePath);
 
   std::ofstream asmFile(tmpAsmFilePath.c_str(), io_mode);