* Implement getStatusInfo for getting stat(2) like information
authorReid Spencer <rspencer@reidspencer.com>
Tue, 9 Nov 2004 20:26:31 +0000 (20:26 +0000)
committerReid Spencer <rspencer@reidspencer.com>
Tue, 9 Nov 2004 20:26:31 +0000 (20:26 +0000)
* Implement createTemporaryFile for mkstemp(3) functionality
* Fix isBytecodeFile to accept llvc magic # (compressed) as bytecode.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@17654 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/System/Path.h
lib/System/Unix/Path.cpp
lib/System/Unix/Path.inc

index 7f59d60135238013141ba61defdc1e580380f63a..77a5add2fc641fb2a178d0982c81b71c0492532c 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <string>
 #include <vector>
+#include "llvm/System/TimeValue.h"
 
 namespace llvm {
 namespace sys {
@@ -306,6 +307,24 @@ namespace sys {
       /// @brief Get the base name of the path
       std::string getBasename() const;
 
+      /// This structure provides basic file system information about a file.
+      /// The structure is filled in by the getStatusInfo method.
+      /// @brief File status structure
+      struct StatusInfo {
+        StatusInfo() : modTime(0,0) { fileSize=0; mode=0; user=0; group=0; }
+        size_t      fileSize;   ///< Size of the file in bytes
+        TimeValue   modTime;    ///< Time of file's modification
+        uint64_t    mode;       ///< Mode of the file, if applicable
+        uint64_t    user;       ///< User ID of owner, if applicable
+        uint64_t    group;      ///< Group ID of owner, if applicable
+      };
+
+      /// This function returns status information about the file. 
+      /// @returns nothing
+      /// @throws std::string if an error occurs.
+      /// @brief Get file status.
+      void getStatusInfo(StatusInfo& stat) const;
+
       /// @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(); }
@@ -425,6 +444,17 @@ namespace sys {
       /// @brief Create the file this Path refers to.
       bool createFile();
 
+      /// This is like createFile except that it creates a temporary file. A 
+      /// unique temporary file name is generated based on the contents of 
+      /// \p this before the call. The new name is assigned to \p this and the
+      /// file is created.  Note that this will both change the Path object
+      /// *and* create the corresponding file. The path of \p this will have 
+      /// six characters added to it (per mkstemp(3)) that ensure the file 
+      /// name is unique.
+      /// @throws std::string if there is an error
+      /// @brief Create a temporary file
+      bool createTemporaryFile();
+
       /// This method attempts to destroy the directory named by the last in 
       /// the Path name.  If \p remove_contents is false, an attempt will be 
       /// made to remove just the directory that this Path object refers to 
index 4f4d347f0928e9e17b6e33ac2fa49f4ad3dda8c8..c3c6775968cdef09567be5a4e099709e25e79c70 100644 (file)
@@ -164,10 +164,13 @@ bool Path::hasMagicNumber(const std::string &Magic) const {
 
 bool 
 Path::isBytecodeFile() const {
-  if (readable()) {
-    return hasMagicNumber("llvm");
-  }
-  return false;
+  char buffer[ 4];
+  buffer[0] = 0;
+  std::ifstream f(path.c_str());
+  f.read(buffer, 4);
+  if (f.bad())
+    ThrowErrno("can't read file signature");
+  return 0 == memcmp(buffer,"llvc",4) || 0 == memcmp(buffer,"llvm",4);
 }
 
 bool
@@ -220,6 +223,19 @@ Path::getLast() const {
   return path.substr(pos+1);
 }
 
+void
+Path::getStatusInfo(StatusInfo& info) const {
+  struct stat buf;
+  if (0 != stat(path.c_str(), &buf)) {
+    ThrowErrno(std::string("Can't get status: ")+path);
+  }
+  info.fileSize = buf.st_size;
+  info.modTime.fromPosixTime(buf.st_mtime);
+  info.mode = buf.st_mode;
+  info.user = buf.st_uid;
+  info.group = buf.st_gid;
+}
+
 bool
 Path::setDirectory(const std::string& a_path) {
   if (a_path.size() == 0)
@@ -379,12 +395,30 @@ Path::createFile() {
   // Create the file
   int fd = ::creat(path.c_str(), S_IRUSR | S_IWUSR);
   if (fd < 0)
-    ThrowErrno(std::string(path.c_str()) + ": Can't create file");
+    ThrowErrno(path + ": Can't create file");
   ::close(fd);
 
   return true;
 }
 
+bool
+Path::createTemporaryFile() {
+  // Make sure we're dealing with a file
+  if (!isFile()) return false;
+
+  // Append the filename filler
+  char pathname[MAXPATHLEN];
+  path.copy(pathname,MAXPATHLEN);
+  strcat(pathname,"XXXXXX");
+  int fd = ::mkstemp(pathname);
+  if (fd < 0) {
+    ThrowErrno(path + ": Can't create temporary file");
+  }
+  path = pathname;
+  ::close(fd);
+  return true;
+}
+
 bool
 Path::destroyDirectory(bool remove_contents) {
   // Make sure we're dealing with a directory
index 4f4d347f0928e9e17b6e33ac2fa49f4ad3dda8c8..c3c6775968cdef09567be5a4e099709e25e79c70 100644 (file)
@@ -164,10 +164,13 @@ bool Path::hasMagicNumber(const std::string &Magic) const {
 
 bool 
 Path::isBytecodeFile() const {
-  if (readable()) {
-    return hasMagicNumber("llvm");
-  }
-  return false;
+  char buffer[ 4];
+  buffer[0] = 0;
+  std::ifstream f(path.c_str());
+  f.read(buffer, 4);
+  if (f.bad())
+    ThrowErrno("can't read file signature");
+  return 0 == memcmp(buffer,"llvc",4) || 0 == memcmp(buffer,"llvm",4);
 }
 
 bool
@@ -220,6 +223,19 @@ Path::getLast() const {
   return path.substr(pos+1);
 }
 
+void
+Path::getStatusInfo(StatusInfo& info) const {
+  struct stat buf;
+  if (0 != stat(path.c_str(), &buf)) {
+    ThrowErrno(std::string("Can't get status: ")+path);
+  }
+  info.fileSize = buf.st_size;
+  info.modTime.fromPosixTime(buf.st_mtime);
+  info.mode = buf.st_mode;
+  info.user = buf.st_uid;
+  info.group = buf.st_gid;
+}
+
 bool
 Path::setDirectory(const std::string& a_path) {
   if (a_path.size() == 0)
@@ -379,12 +395,30 @@ Path::createFile() {
   // Create the file
   int fd = ::creat(path.c_str(), S_IRUSR | S_IWUSR);
   if (fd < 0)
-    ThrowErrno(std::string(path.c_str()) + ": Can't create file");
+    ThrowErrno(path + ": Can't create file");
   ::close(fd);
 
   return true;
 }
 
+bool
+Path::createTemporaryFile() {
+  // Make sure we're dealing with a file
+  if (!isFile()) return false;
+
+  // Append the filename filler
+  char pathname[MAXPATHLEN];
+  path.copy(pathname,MAXPATHLEN);
+  strcat(pathname,"XXXXXX");
+  int fd = ::mkstemp(pathname);
+  if (fd < 0) {
+    ThrowErrno(path + ": Can't create temporary file");
+  }
+  path = pathname;
+  ::close(fd);
+  return true;
+}
+
 bool
 Path::destroyDirectory(bool remove_contents) {
   // Make sure we're dealing with a directory