aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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.substr(0,pos);
+ else
+ return path.substr(pos2+1,pos-pos2-1);
}
+ // Return everything after the last slash
+ return path.substr(pos+1);
}
-void
-Path::remove() {
- if ( is_directory() ) {
- if ( exists() )
- this->remove_directory( );
- } else if ( is_file() )
- if ( exists() )
- this->remove_file( );
+bool
+Path::set_directory(const std::string& a_path) {
+ if (a_path.size() == 0)
+ return false;
+ Path save(*this);
+ path = a_path;
+ size_t last = a_path.size() -1;
+ if (last != 0 && a_path[last] != '/')
+ path += '/';
+ if (!is_valid()) {
+ path = save.path;
+ return false;
+ }
+ return true;
}
bool
-Path::exists() {
- char pathname[MAXP