* Implement getStatusInfo for getting stat(2) like information
* 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
diff --git a/include/llvm/System/Path.h b/include/llvm/System/Path.h
index 7f59d60..77a5add 100644
--- a/include/llvm/System/Path.h
+++ b/include/llvm/System/Path.h
@@ -16,6 +16,7 @@
#include <string>
#include <vector>
+#include "llvm/System/TimeValue.h"
namespace llvm {
namespace sys {
@@ -306,6 +307,24 @@
/// @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 @@
/// @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
diff --git a/lib/System/Unix/Path.cpp b/lib/System/Unix/Path.cpp
index 4f4d347..c3c6775 100644
--- a/lib/System/Unix/Path.cpp
+++ b/lib/System/Unix/Path.cpp
@@ -164,10 +164,13 @@
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 @@
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,13 +395,31 @@
// 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
if (!isDirectory()) return false;
diff --git a/lib/System/Unix/Path.inc b/lib/System/Unix/Path.inc
index 4f4d347..c3c6775 100644
--- a/lib/System/Unix/Path.inc
+++ b/lib/System/Unix/Path.inc
@@ -164,10 +164,13 @@
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 @@
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,13 +395,31 @@
// 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
if (!isDirectory()) return false;