aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReid Spencer <rspencer@reidspencer.com>2004-08-29 05:24:01 +0000
committerReid Spencer <rspencer@reidspencer.com>2004-08-29 05:24:01 +0000
commit8e66595512b065b69d595bae665b6ad665eca6d0 (patch)
tree1c901bbf4fff4a03d396f9374940fc8d7392651f
parent81bc6e377e06c358747f59bce781aba25c60fb56 (diff)
Revise the design of the Path concept per peer review. Too many changes to
note individually but these essence of it is to not derive from std::string, clarify the interface, and provide better documentation. There is now also (untested) implementations for AIX, Darwin, and SunOS. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16078 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/System/Path.h490
-rw-r--r--lib/System/AIX/Path.cpp36
-rw-r--r--lib/System/Darwin/Path.cpp36
-rw-r--r--lib/System/Linux/Path.cpp22
-rw-r--r--lib/System/Path.cpp35
-rw-r--r--lib/System/SunOS/Path.cpp38
-rw-r--r--lib/System/Unix/Path.cpp367
-rw-r--r--lib/System/Unix/Path.inc367
8 files changed, 1071 insertions, 320 deletions
diff --git a/include/llvm/System/Path.h b/include/llvm/System/Path.h
index df699a3584..3792f87890 100644
--- a/include/llvm/System/Path.h
+++ b/include/llvm/System/Path.h
@@ -19,138 +19,392 @@
namespace llvm {
namespace sys {
- /// This class provides an abstraction for the name of a path
- /// to a file or directory in the filesystem and various basic operations
- /// on it.
+ /// 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
+ /// or directory which may or may not be valid for a given machine's file
+ /// system. A Path ensures that the name it encapsulates is syntactical valid
+ /// for the operating system it is running on but does not ensure correctness
+ /// for any particular file system. A Path either references a file or a
+ /// directory and the distinction is consistently maintained. Most operations
+ /// on the class have invariants that require the Path object to be either a
+ /// file path or a directory path, but not both. Those operations will also
+ /// leave the object as either a file path or object path. There is exactly
+ /// one invalid Path which is the empty path. The class should never allow any
+ /// other syntactically invalid non-empty path name to be assigned. Empty
+ /// paths are required in order to indicate an error result. If the path is
+ /// empty, the is_valid operation will return false. All operations will fail
+ /// if is_valid is false. Operations that change the path will either return
+ /// false if it would cause a syntactically invalid path name (in which case
+ /// the Path object is left unchanged) or throw an std::string exception
+ /// indicating the error.
/// @since 1.4
/// @brief An abstraction for operating system paths.
- class Path : public std::string {
- /// @name Constructors
- /// @{
- public:
- /// Creates a null (empty) path
- /// @brief Default Constructor
- Path () : std::string() {}
-
- /// Creates a path from char*
- /// @brief char* converter
- Path ( const char * name ) : std::string(name) {
- assert(is_valid());
- }
-
- /// @brief std::string converter
- Path ( const std::string& name ) : std::string(name){
- assert(is_valid());
- };
-
- /// Copies the path with copy-on-write semantics. The \p this Path
- /// will reference \p the that Path until one of them is modified
- /// at which point a full copy is taken before the write.
- /// @brief Copy Constructor
- Path ( const Path & that ) : std::string(that) {}
-
- /// Releases storage associated with the Path object
- /// @brief Destructor
- ~Path ( void ) {};
-
- /// @}
- /// @name Operators
- /// @{
- public:
- /// Makes a copy of \p that to \p this with copy-on-write semantics.
- /// @returns \p this
- /// @brief Assignment Operator
- Path & operator = ( const Path & that ) {
- this->assign (that);
- return *this;
- }
-
- /// Comparies \p this Path with \p that Path for equality.
- /// @returns true if \p this and \p that refer to the same item.
- /// @brief Equality Operator
- bool operator ==( const Path & that ) const {
- return 0 == this->compare( that ) ;
- }
-
- /// Comparies \p this Path with \p that Path for inequality.
- /// @returns true if \p this and \p that refer to different items.
- /// @brief Inequality Operator
- bool operator !=( const Path & that ) const {
- return 0 != this->compare( that );
- }
-
- /// @}
- /// @name Accessors
- /// @{
- public:
- /// @returns true if the path is valid
- /// @brief Determines if the path is valid (properly formed) or not.
- bool is_valid() const;
-
- /// @returns true if the path could reference a file
- /// @brief Determines if the path is valid for a file reference.
- bool is_file() const;
-
- /// @returns true if the path could reference a directory
- /// @brief Determines if the path is valid for a directory reference.
- bool is_directory() const;
-
- /// @brief Fills and zero terminates a buffer with the path
- void fill( char* buffer, unsigned len ) const;
-
- /// @}
- /// @name Mutators
- /// @{
- public:
- /// This ensures that the pathname is terminated with a /
- /// @brief Make the path reference a directory.
- void make_directory();
-
- /// This ensures that the pathname is not terminated with a /
- /// @brief Makes the path reference a file.
- void make_file();
+ class Path {
+ /// @name Constructors
+ /// @{
+ public:
+ /// Construct a path to the root directory of the file system. The root
+ /// directory is a top level directory above which there are no more
+ /// directories. For example, on UNIX, the root directory is /. On Windows
+ /// it is C:\. Other operating systems may have different notions of
+ /// what the root directory is.
+ /// @throws nothing
+ static Path GetRootDirectory();
- /// the file system.
+ /// Construct a path to a unique temporary directory that is created in
+ /// a "standard" place for the operating system. The directory is
+ /// guaranteed to be created on exit from this function. If the directory
+ /// cannot be created, the function will throw an exception.
+ /// @throws std::string indicating why the directory could not be created.
+ /// @brief Constrct a path to an new, unique, existing temporary
+ /// directory.
+ static Path GetTemporaryDirectory();
+
+ /// Construct a path to the first system library directory. The
+ /// implementation of Path on a given platform must ensure that this
+ /// directory both exists and also contains standard system libraries
+ /// suitable for linking into programs.
+ /// @throws nothing
+ /// @brief Construct a path to the first system library directory
+ static Path GetSystemLibraryPath1();
+
+ /// Construct a path to the second system library directory. The
+ /// implementation of Path on a given platform must ensure that this
+ /// directory both exists and also contains standard system libraries
+ /// suitable for linking into programs. Note that the "second" system
+ /// library directory may or may not be different from the first.
+ /// @throws nothing
+ /// @brief Construct a path to the second system library directory
+ static Path GetSystemLibraryPath2();
+
+ /// Construct a path to the default LLVM configuration directory. The
+ /// implementation must ensure that this is a well-known (same on many
+ /// systems) directory in which llvm configuration files exist. For
+ /// example, on Unix, the /etc/llvm directory has been selected.
+ /// @throws nothing
+ /// @brief Construct a path to the default LLVM configuration directory
+ static Path GetLLVMDefaultConfigDir();
+
+ /// Construct a path to the LLVM installed configuration directory. The
+ /// implementation must ensure that this refers to the "etc" directory of
+ /// the LLVM installation. This is the location where configuration files
+ /// will be located for a particular installation of LLVM on a machine.
+ /// @throws nothing
+ /// @brief Construct a path to the LLVM installed configuration directory
+ static Path GetLLVMConfigDir();
+
+ /// Construct a path to the current user's home directory. The
+ /// implementation must use an operating system specific mechanism for
+ /// determining the user's home directory. For example, the environment
+ /// variable "HOME" could be used on Unix. If a given operating system
+ /// does not have the concept of a user's home directory, this static
+ /// constructor must provide the same result as GetRootDirectory.
+ /// @throws nothing
+ /// @brief Construct a path to the current user's "home" directory
+ static Path GetUserHomeDirectory();
+
+ /// This is one of the very few ways in which a path can be constructed
+ /// with a syntactically invalid name. The only *legal* invalid name is an
+ /// empty one. Other invalid names are not permitted. Empty paths are
+ /// provided so that they can be used to indicate null or error results in
+ /// other lib/System functionality.
+ /// @throws nothing
+ /// @brief Construct an empty (and invalid) path.
+ Path() : path() {}
+
+ /// This constructor will accept a std::string as a path but if verifies
+ /// that the path string has a legal syntax for the operating system on
+ /// which it is running. This allows a path to be taken in from outside
+ /// the program. However, if the path is not valid, the Path object will
+ /// be set to an empty string and an exception will be thrown.
+ /// @throws std::string if the path string is not legal.
+ /// @param unvalidated_path The path to verify and assign.
+ /// @brief Construct a Path from a string.
+ explicit Path(std::string unverified_path);
+
+ /// @}
+ /// @name Operators
+ /// @{
+ public:
+ /// Makes a copy of \p that to \p this.
+ /// @returns \p this
+ /// @throws nothing
+ /// @brief Assignment Operator
+ Path & operator = ( const Path & that ) {
+ path = that.path;
+ return *this;
+ }
+
+ /// Compares \p this Path with \p that Path for equality.
+ /// @returns true if \p this and \p that refer to the same thing.
+ /// @throws nothing
+ /// @brief Equality Operator
+ 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.
+ /// @throws nothing
+ /// @brief Inequality Operator
+ 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
+ /// so that Path objects can be placed into ordered collections (e.g.
+ /// std::map). The comparison is done lexicographically as defined by
+ /// the std::string::compare method.
+ /// @returns true if \p this path is lexicographically less than \p that.
+ /// @throws nothing
+ /// @brief Less Than Operator
+ bool operator< (const Path& that) const {
+ return 0 > path.compare( that.path );
+ }
+
+ /// @}
+ /// @name Accessors
+ /// @{
+ public:
+ /// This function will use an operating system specific algorithm to
+ /// determine if the current value of \p this is a syntactically valid
+ /// path name for the operating system. The path name does not need to
+ /// exist, validity is simply syntactical. Empty paths are always invalid.
+ /// @returns true iff the path name is syntactically legal for the
+ /// host operating system.
+ /// @brief Determine if a path is syntactically valid or not.
+ bool is_valid() const;
+
+ /// This function determines if the contents of the path name are
+ /// empty. That is, the path has a zero length.
+ /// @returns true iff the path is empty.
+ /// @brief Determines if the path name is empty (invalid).
+ bool is_empty() const { return path.empty(); }
+
+ /// This function determines if the path name in this object is intended
+ /// to reference a legal file name (as opposed to a directory name). This
+ /// function does not verify anything with the file system, it merely
+ /// determines if the syntax of the path represents a file name or not.
+ /// @returns true if this path name references a file.
+ /// @brief Determines if the path name references a file.
+ bool is_file() const;
+
+ /// This function determines if the path name in this object is intended
+ /// to reference a legal directory name (as opposed to a file name). This
+ /// function does not verify anything with the file system, it merely
+ /// determines if the syntax of the path represents a directory name or
+ /// not.
+ /// @returns true if the path name references a directory
+ /// @brief Determines if the path name references a directory.
+ bool is_directory() const;
+
+ /// This function determines if the path name in this object references
+ /// the root (top level directory) of the file system. The details of what
+ /// is considered the "root" may vary from system to system so this method
+ /// will do the necessary checking.
+ /// @returns true iff the path name references the root directory.
+ /// @brief Determines if the path references the root directory.
+ bool is_root_directory() const;
+
+ /// This function determines if the path name references an existing file
+ /// or directory in the file system. Unlike is_file and is_directory, this
+ /// function actually checks for the existence of the file or directory.
/// @returns true if the pathname references an existing file.
/// @brief Determines if the path is a file or directory in
- bool exists();
+ /// the file system.
+ bool exists() const;
+
+ /// This function determines if the path name references a readable file
+ /// or directory in the file system. Unlike is_file and is_directory, this
+ /// function actually checks for the existence and readability (by the
+ /// current program) of the file or directory.
+ /// @returns true if the pathname references a readable file.
+ /// @brief Determines if the path is a readable file or directory
+ /// in the file system.
+ bool readable() const;
+
+ /// This function determines if the path name references a writable file
+ /// or directory in the file system. Unlike is_file and is_directory, this
+ /// function actually checks for the existence and writability (by the
+ /// current program) of the file or directory.
+ /// @returns true if the pathname references a writable file.
+ /// @brief Determines if the path is a writable file or directory
+ /// in the file system.
+ bool writable() const;
+
+ /// This function determines if the path name references an executable
+ /// file in the file system. Unlike is_file and is_directory, this
+ /// function actually checks for the existence and executability (by
+ /// the current program) of the file.
+ /// @returns true if the pathname references an executable file.
+ /// @brief Determines if the path is an executable file in the file
+ /// system.
+ bool executable() const;
+
+ /// This function returns the current contents of the path as a
+ /// std::string. This allows the underlying path string to be manipulated
+ /// by other software.
+ /// @returns std::string containing the path name.
+ /// @brief Returns the path as a std::string.
+ std::string get() const { return path; }
+
+ /// This function returns the last component of the path name. If the
+ /// is_directory() function would return true then this returns the name
+ /// of the last directory in the path. If the is_file() function would
+ /// return true then this function returns the name of the file without
+ /// any of the preceding directories.
+ /// @returns std::string containing the last component of the path name.
+ /// @brief Returns the last component of the path name.
+ std::string getLast() 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(); }
+
+ /// @}
+ /// @name Mutators
+ /// @{
+ public:
+ /// The path name is cleared and becomes empty. This is an invalid
+ /// path name but is the *only* invalid path name. This is provided
+ /// so that path objects can be used to indicate the lack of a
+ /// valid path being found.
+ void clear() { path.clear(); }
- /// The \p dirname is added to the end of the Path.
+ /// This method attempts to set the Path object to \p unverified_path
+ /// and interpret the name as a directory name. The \p unverified_path
+ /// is verified. If verification succeeds then \p unverified_path
+ /// is accepted as a directory and true is returned. Otherwise,
+ /// the Path object remains unchanged and false is returned.
+ /// @returns true if the path was set, false otherwise.
+ /// @param unverified_path The path to be set in Path object.
+ /// @throws nothing
+ /// @brief Set a full path from a std::string
+ bool set_directory(const std::string& unverified_path);
+
+ /// This method attempts to set the Path object to \p unverified_path
+ /// and interpret the name as a file name. The \p unverified_path
+ /// is verified. If verification succeeds then \p unverified_path
+ /// is accepted as a file name and true is returned. Otherwise,
+ /// the Path object remains unchanged and false is returned.
+ /// @returns true if the path was set, false otherwise.
+ /// @param unverified_path The path to be set in Path object.
+ /// @throws nothing
+ /// @brief Set a full path from a std::string
+ bool set_file(const std::string& unverified_path);
+
+ /// The \p dirname is added to the end of the Path if it is a legal
+ /// directory name for the operating system. The precondition for this
+ /// function is that the Path must reference a directory name (i.e.
+ /// is_directory() returns true).
/// @param dirname A string providing the directory name to
- /// be appended to the path.
- /// @brief Appends the name of a directory.
- void append_directory( const std::string& dirname ) {
- this->append( dirname );
- make_directory();
- }
+ /// be added to the end of the path.
+ /// @returns false if the directory name could not be added
+ /// @throws nothing
+ /// @brief Adds the name of a directory to a Path.
+ bool append_directory( const std::string& dirname );
- /// The \p filename is added to the end of the Path.
+ /// One directory component is removed from the Path name. The Path must
+ /// refer to a non-root directory name (i.e. is_directory() returns true
+ /// but is_root_directory() returns false). Upon exit, the Path will
+ /// refer to the directory above it.
+ /// @throws nothing
+ /// @returns false if the directory name could not be removed.
+ /// @brief Removes the last directory component of the Path.
+ bool elide_directory();
+
+ /// The \p filename is added to the end of the Path if it is a legal
+ /// directory name for the operating system. The precondition for this
+ /// function is that the Path reference a directory name (i.e.
+ /// is_directory() returns true).
+ /// @throws nothing
+ /// @returns false if the file name could not be added.
/// @brief Appends the name of a file.
- void append_file( const std::string& filename ) {
- this->append( filename );
- }
+ bool append_file( const std::string& filename );
- /// Directories will have no entries. Files will be zero length. If
- /// the file or directory already exists, no error results.
- /// @throws SystemException if any error occurs.
- /// @brief Causes the file or directory to exist in the filesystem.
- void create( bool create_parents = false );
+ /// One file component is removed from the Path name. The Path must
+ /// refer to a file (i.e. is_file() returns true). Upon exit,
+ /// the Path will refer to the directory above it.
+ /// @throws nothing
+ /// @returns false if the file name could not be removed
+ /// @brief Removes the last file component of the path.
+ bool elide_file();
- void create_directory( void );
- void create_directories( void );
- void create_file( void );
+ /// A period and the \p suffix are appended to the end of the pathname.
+ /// The precondition for this function is that the Path reference a file
+ /// name (i.e. is_file() returns true). If the Path is not a file, no
+ /// action is taken and the function returns false. If the path would
+ /// become invalid for the host operating system, false is returned.
+ /// @returns false if the suffix could not be added, true if it was.
+ /// @throws nothing
+ /// @brief Adds a period and the \p suffix to the end of the pathname.
+ bool append_suffix(const std::string& suffix);
- /// Directories must be empty before they can be removed. If not,
- /// an error will result. Files will be unlinked, even if another
- /// process is using them.
+ /// The suffix of the filename is removed. The suffix begins with and
+ /// includes the last . character in the filename after the last directory
+ /// separator and extends until the end of the name. If no . character is
+ /// after the last directory separator, then the file name is left
+ /// unchanged (i.e. it was already without a suffix) but the function return
+ /// false.
+ /// @returns false if there was no suffix to remove, true otherwise.
+ /// @throws nothing
+ /// @brief Remove the suffix from a path name.
+ bool elide_suffix();
+
+ /// 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
+ /// whether intermediate directories are created or not. if \p
+ /// create_parents is true, then an attempt will be made to create all
+ /// intermediate directories. 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.
+ /// @brief Create the directory this Path refers to.
+ bool create_directory( bool create_parents = false );
+
+ /// 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 create_directories 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.
+ /// @brief Create the file this Path refers to.
+ bool create_file();
+
+ /// 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
+ /// (the final Path component). If \p remove_contents is true, an attempt
+ /// will be made to remove the entire contents of the directory,
+ /// recursively.
+ /// @param destroy_contents Indicates whether the contents of a destroyed
+ /// directory should also be destroyed (recursively).
+ /// @returns false if the Path does not refer to a directory, true
+ /// otherwise.
+ /// @throws std::string if there is an error.
/// @brief Removes the file or directory from the filesystem.
- void remove( void );
- void remove_directory( void );
- void remove_file( void );
+ bool destroy_directory( bool destroy_contents = false );
+
+ /// This method attempts to destroy the file named by the last item in the
+ /// Path name.
+ /// @returns false if the Path does not refer to a file, true otherwise.
+ /// @throws std::string if there is an error.
+ /// @brief Destroy the file this Path refers to.
+ bool destroy_file();
+
+ /// @}
+ /// @name Data
+ /// @{
+ private:
+ std::string path; ///< Platform agnostic storage for the path name.
- /// Find library.
- void find_lib( const char * file );
- /// @}
+ /// @}
};
}
}
diff --git a/lib/System/AIX/Path.cpp b/lib/System/AIX/Path.cpp
new file mode 100644
index 0000000000..f75ab90748
--- /dev/null
+++ b/lib/System/AIX/Path.cpp
@@ -0,0 +1,36 @@
+//===- llvm/System/AIX/Path.cpp - AIX Path Implementation -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file was developed by Reid Spencer and is distributed under the
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides the AIX specific implementation of the Path class.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only AIX specific code
+//=== and must not be generic UNIX code (see ../Unix/Path.cpp)
+//===----------------------------------------------------------------------===//
+
+// Include the generic unix implementation
+#include "../Unix/Path.cpp"
+
+namespace llvm {
+using namespace sys;
+
+bool
+Path::is_valid() const {
+ if (path.empty())
+ return false;
+ if (path.length() >= MAXPATHLEN)
+ return false;
+ return true;
+}
+
+}
+
+// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab
diff --git a/lib/System/Darwin/Path.cpp b/lib/System/Darwin/Path.cpp
new file mode 100644
index 0000000000..b3321a47df
--- /dev/null
+++ b/lib/System/Darwin/Path.cpp
@@ -0,0 +1,36 @@
+//===- llvm/System/Darwin/Path.cpp - Linux Path Implementation --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file was developed by Reid Spencer and is distributed under the
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides the Darwin specific implementation of the Path class.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only Darwin specific code
+//=== and must not be generic UNIX code (see ../Unix/Path.cpp)
+//===----------------------------------------------------------------------===//
+
+// Include the generic unix implementation
+#include "../Unix/Path.cpp"
+
+namespace llvm {
+using namespace sys;
+
+bool
+Path::is_valid() const {
+ if (path.empty())
+ return false;
+ if (path.length() >= MAXPATHLEN)
+ return false;
+ return true;
+}
+
+}
+
+// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab
diff --git a/lib/System/Linux/Path.cpp b/lib/System/Linux/Path.cpp
index 5c73d0176a..e7efd2fb95 100644
--- a/lib/System/Linux/Path.cpp
+++ b/lib/System/Linux/Path.cpp
@@ -13,8 +13,26 @@
//===----------------------------------------------------------------------===//
//=== WARNING: Implementation here must contain only Linux specific code
-//=== and must not be generic UNIX code (see ../Unix)
+//=== and must not be generic UNIX code (see ../Unix/Path.cpp)
//===----------------------------------------------------------------------===//
-// Th..Th..Th..Tha's All Folks!
+// Include the generic Unix implementation
#include "../Unix/Path.cpp"
+
+namespace llvm {
+using namespace sys;
+
+bool
+Path::is_valid() const {
+ if (path.empty())
+ return false;
+ char pathname[MAXPATHLEN];
+ if (0 == realpath(path.c_str(), pathname))
+ if (errno != EACCES && errno != EIO && errno != ENOENT && errno != ENOTDIR)
+ return false;
+ return true;
+}
+
+}
+
+// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab
diff --git a/lib/System/Path.cpp b/lib/System/Path.cpp
index e32842dd18..93c1e0a710 100644
--- a/lib/System/Path.cpp
+++ b/lib/System/Path.cpp
@@ -10,10 +10,11 @@
// This header file implements the operating system Path concept.
//
//===----------------------------------------------------------------------===//
+
#include "llvm/System/Path.h"
namespace llvm {
-namespace sys {
+using namespace sys;
//===----------------------------------------------------------------------===//
//=== WARNING: Implementation here must contain only TRULY operating system
@@ -21,40 +22,18 @@ namespace sys {
//===----------------------------------------------------------------------===//
bool
-Path::is_valid() const {
- if ( empty() ) return false;
- return true;
-}
-
-void
-Path::fill( char* buffer, unsigned bufflen ) const {
- unsigned pathlen = length();
- assert( bufflen > pathlen && "Insufficient buffer size" );
- unsigned copylen = pathlen <? (bufflen - 1);
- this->copy(buffer, copylen, 0 );
- buffer[ copylen ] = 0;
+Path::is_file() const {
+ return (is_valid() && path[path.length()-1] != '/');
}
-void
-Path::make_directory() {
- char end[2];
- end[0] = '/';
- end[1] = 0;
- if ( empty() )
- this->assign( end );
- else if ( (*this)[length()-1] != '/')
- this->append( end );
+bool
+Path::is_directory() const {
+ return (is_valid() && path[path.length()-1] == '/');
}
-void
-Path::make_file() {
- if ( (*this)[length()-1] == '/')
- this->erase( this->length()-1, 1 );
}
// Include the truly platform-specific parts of this class.
#include "platform/Path.cpp"
-}
-}
// vim: sw=2
diff --git a/lib/System/SunOS/Path.cpp b/lib/System/SunOS/Path.cpp
new file mode 100644
index 0000000000..a180bbfe12
--- /dev/null
+++ b/lib/System/SunOS/Path.cpp
@@ -0,0 +1,38 @@
+//===- llvm/System/SunOS/Path.cpp - SunOS Path Implementation ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file was developed by Reid Spencer and is distributed under the
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides the SunOS specific implementation of the Path class.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only SunOS specific code
+//=== and must not be generic UNIX code (see ../Unix/Path.cpp)
+//===----------------------------------------------------------------------===//
+
+// Include the generic Unix implementation
+#include "../Unix/Path.cpp"
+
+namespace llvm {
+using namespace sys;
+
+bool
+Path::is_valid() const {
+ if (path.empty())
+ return false;
+ char pathname[MAXPATHLEN];
+ if (0 == realpath(path.c_str(), pathname))
+ if (errno != EACCES && errno != EIO && errno != ENOENT && errno != ENOTDIR)
+ return false;
+ return true;
+}
+
+}
+
+// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab
diff --git a/lib/System/Unix/Path.cpp b/lib/System/Unix/Path.cpp
index 9253f8c9f7..9d9dd99103 100644
--- a/lib/System/Unix/Path.cpp
+++ b/lib/System/Unix/Path.cpp
@@ -13,126 +13,321 @@
//===----------------------------------------------------------------------===//
//=== WARNING: Implementation here must contain only generic UNIX code that
-//=== is guaranteed to work on all UNIX variants.
+//=== is guaranteed to work on *all* UNIX variants.
//===----------------------------------------------------------------------===//
#include "Unix.h"
#include <sys/stat.h>
#include <fcntl.h>
+#include <Config/config.h>
+
+namespace llvm {
+using namespace sys;
+
+Path::Path(std::string unverified_path)
+ : path(unverified_path)
+{
+ if (unverified_path.empty())
+ return;
+ if (this->is_valid())
+ return;
+ // oops, not valid.
+ path.clear();
+ ThrowErrno(unverified_path + ": path is not valid");
+}
+
+Path
+Path::GetRootDirectory() {
+ Path result;
+ result.set_directory("/");
+ return result;
+}
+
+Path
+Path::GetTemporaryDirectory() {
+ char pathname[MAXPATHLEN];
+ strcpy(pathname,"/tmp/llvm_XXXXXX");
+ if (0 == mkdtemp(pathname))
+ ThrowErrno(std::string(pathname) + ": Can't create temporary directory");
+ Path result;
+ result.set_directory(pathname);
+ assert(result.is_valid() && "mkdtemp didn't create a valid pathname!");
+ return result;
+}
+
+Path
+Path::GetSystemLibraryPath1() {
+ return Path("/lib/");
+}
+
+Path
+Path::GetSystemLibraryPath2() {
+ return Path("/usr/lib/");
+}
+
+Path
+Path::GetLLVMDefaultConfigDir() {
+ return Path("/etc/llvm/");
+}
+
+Path
+Path::GetLLVMConfigDir() {
+ Path result;
+ if (result.set_directory(LLVM_ETCDIR))
+ return result;
+ return GetLLVMDefaultConfigDir();
+}
+
+Path
+Path::GetUserHomeDirectory() {
+ const char* home = getenv("HOME");
+ if (home) {
+ Path result;
+ if (result.set_directory(home))
+ return result;
+ }
+ return GetRootDirectory();
+}
bool
-Path::is_file() const {
- if (!empty() && ((*this)[length()-1] != '/'))
- return true;
- return false;
+Path::exists() const {
+ return 0 == access(path.c_str(), F_OK );
}
bool
-Path::is_directory() const {
- if ((!empty()) && ((*this)[length()-1] == '/'))
- return true;
- return false;
+Path::readable() const {
+ return 0 == access(path.c_str(), F_OK | R_OK );
+}
+
+bool
+Path::writable() const {
+ return 0 == access(path.c_str(), F_OK | W_OK );
}
-void
-Path::create( bool create_parents) {
- if ( is_directory() ) {
- if ( create_parents )
- this->create_directories( );
- this->create_directory( );
- } else if ( is_file() ) {
- if ( create_parents )
- this->create_directories( );
- this->create_file( );
+bool
+Path::executable() const {
+ return 0 == access(path.c_str(), R_OK | X_OK );
+}
+
+std::string
+Path::getLast() const {
+ // Find the last slash
+ size_t pos = path.rfind('/');
+
+ // Handle the corner cases
+ if (pos == std::string::npos)
+ return path;
+
+ // If the last character is a slash
+ if (pos == path.length()-1) {
+ // Find the second to last slash
+ size_t pos2 = path.rfind('/', pos-1);
+ if (pos2 == std::string::npos)
+ return path.s