#include "llvm/Support/DataTypes.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/TimeValue.h"
-#include "llvm/Support/system_error.h"
#include <ctime>
#include <iterator>
#include <stack>
#include <string>
+#include <system_error>
#include <tuple>
#include <vector>
namespace sys {
namespace fs {
-/// An "enum class" enumeration for the file system's view of the type.
-struct file_type {
- enum Impl {
- status_error,
- file_not_found,
- regular_file,
- directory_file,
- symlink_file,
- block_file,
- character_file,
- fifo_file,
- socket_file,
- type_unknown
- };
-
- file_type(Impl V) : V(V) {}
- operator Impl() const { return V; }
-
-private:
- Impl V;
+/// An enumeration for the file system's view of the type.
+enum class file_type {
+ status_error,
+ file_not_found,
+ regular_file,
+ directory_file,
+ symlink_file,
+ block_file,
+ character_file,
+ fifo_file,
+ socket_file,
+ type_unknown
};
/// space_info - Self explanatory.
};
/// file_status - Represents the result of a call to stat and friends. It has
-/// a platform specific member to store the result.
+/// a platform-specific member to store the result.
class file_status
{
#if defined(LLVM_ON_UNIX)
file_type Type;
perms Perms;
public:
- file_status() : Type(file_type::status_error) {}
- file_status(file_type Type) : Type(Type) {}
-
#if defined(LLVM_ON_UNIX)
+ file_status() : fs_st_dev(0), fs_st_ino(0), fs_st_mtime(0),
+ fs_st_uid(0), fs_st_gid(0), fs_st_size(0),
+ Type(file_type::status_error), Perms(perms_not_known) {}
+
+ file_status(file_type Type) : fs_st_dev(0), fs_st_ino(0), fs_st_mtime(0),
+ fs_st_uid(0), fs_st_gid(0), fs_st_size(0), Type(Type),
+ Perms(perms_not_known) {}
+
file_status(file_type Type, perms Perms, dev_t Dev, ino_t Ino, time_t MTime,
uid_t UID, gid_t GID, off_t Size)
: fs_st_dev(Dev), fs_st_ino(Ino), fs_st_mtime(MTime), fs_st_uid(UID),
fs_st_gid(GID), fs_st_size(Size), Type(Type), Perms(Perms) {}
#elif defined(LLVM_ON_WIN32)
+ file_status() : LastWriteTimeHigh(0), LastWriteTimeLow(0),
+ VolumeSerialNumber(0), FileSizeHigh(0), FileSizeLow(0),
+ FileIndexHigh(0), FileIndexLow(0), Type(file_type::status_error),
+ Perms(perms_not_known) {}
+
+ file_status(file_type Type) : LastWriteTimeHigh(0), LastWriteTimeLow(0),
+ VolumeSerialNumber(0), FileSizeHigh(0), FileSizeLow(0),
+ FileIndexHigh(0), FileIndexLow(0), Type(Type),
+ Perms(perms_not_known) {}
+
file_status(file_type Type, uint32_t LastWriteTimeHigh,
uint32_t LastWriteTimeLow, uint32_t VolumeSerialNumber,
uint32_t FileSizeHigh, uint32_t FileSizeLow,
unknown = 0, ///< Unrecognized file
bitcode, ///< Bitcode file
archive, ///< ar style archive file
+ elf, ///< ELF Unknown type
elf_relocatable, ///< ELF Relocatable object file
elf_executable, ///< ELF Executable image
elf_shared_object, ///< ELF dynamically linked shared lib
///
/// @param path A path that is modified to be an absolute path.
/// @returns errc::success if \a path has been made absolute, otherwise a
-/// platform specific error_code.
-error_code make_absolute(SmallVectorImpl<char> &path);
+/// platform-specific error_code.
+std::error_code make_absolute(SmallVectorImpl<char> &path);
/// @brief Create all the non-existent directories in path.
///
/// @returns errc::success if is_directory(path), otherwise a platform
/// specific error_code. If IgnoreExisting is false, also returns
/// error if the directory already existed.
-error_code create_directories(const Twine &path, bool IgnoreExisting = true);
+std::error_code create_directories(const Twine &path,
+ bool IgnoreExisting = true);
/// @brief Create the directory in path.
///
/// @returns errc::success if is_directory(path), otherwise a platform
/// specific error_code. If IgnoreExisting is false, also returns
/// error if the directory already existed.
-error_code create_directory(const Twine &path, bool IgnoreExisting = true);
+std::error_code create_directory(const Twine &path, bool IgnoreExisting = true);
-/// @brief Create a hard link from \a from to \a to.
+/// @brief Create a link from \a from to \a to.
+///
+/// The link may be a soft or a hard link, depending on the platform. The caller
+/// may not assume which one. Currently on windows it creates a hard link since
+/// soft links require extra privileges. On unix, it creates a soft link since
+/// hard links don't work on SMB file systems.
///
/// @param to The path to hard link to.
/// @param from The path to hard link from. This is created.
-/// @returns errc::success if exists(to) && exists(from) && equivalent(to, from)
-/// , otherwise a platform specific error_code.
-error_code create_hard_link(const Twine &to, const Twine &from);
+/// @returns errc::success if the link was created, otherwise a platform
+/// specific error_code.
+std::error_code create_link(const Twine &to, const Twine &from);
/// @brief Get the current path.
///
/// @param result Holds the current path on return.
/// @returns errc::success if the current path has been stored in result,
-/// otherwise a platform specific error_code.
-error_code current_path(SmallVectorImpl<char> &result);
+/// otherwise a platform-specific error_code.
+std::error_code current_path(SmallVectorImpl<char> &result);
/// @brief Remove path. Equivalent to POSIX remove().
///
/// @param path Input path.
/// @returns errc::success if path has been removed or didn't exist, otherwise a
-/// platform specific error code. If IgnoreNonExisting is false, also
+/// platform-specific error code. If IgnoreNonExisting is false, also
/// returns error if the file didn't exist.
-error_code remove(const Twine &path, bool IgnoreNonExisting = true);
+std::error_code remove(const Twine &path, bool IgnoreNonExisting = true);
/// @brief Rename \a from to \a to. Files are renamed as if by POSIX rename().
///
/// @param from The path to rename from.
/// @param to The path to rename to. This is created.
-error_code rename(const Twine &from, const Twine &to);
+std::error_code rename(const Twine &from, const Twine &to);
+
+/// @brief Copy the contents of \a From to \a To.
+///
+/// @param From The path to copy from.
+/// @param To The path to copy to. This is created.
+std::error_code copy_file(const Twine &From, const Twine &To);
/// @brief Resize path to size. File is resized as if by POSIX truncate().
///
/// @param path Input path.
/// @param size Size to resize to.
/// @returns errc::success if \a path has been resized to \a size, otherwise a
-/// platform specific error_code.
-error_code resize_file(const Twine &path, uint64_t size);
+/// platform-specific error_code.
+std::error_code resize_file(const Twine &path, uint64_t size);
/// @}
/// @name Physical Observers
/// not.
bool exists(file_status status);
-/// @brief Does file exist?
+enum class AccessMode { Exist, Write, Execute };
+
+/// @brief Can the file be accessed?
///
-/// @param path Input path.
-/// @param result Set to true if the file represented by status exists, false if
-/// it does not. Undefined otherwise.
-/// @returns errc::success if result has been successfully set, otherwise a
-/// platform specific error_code.
-error_code exists(const Twine &path, bool &result);
+/// @param Path Input path.
+/// @returns errc::success if the path can be accessed, otherwise a
+/// platform-specific error_code.
+std::error_code access(const Twine &Path, AccessMode Mode);
-/// @brief Simpler version of exists for clients that don't need to
-/// differentiate between an error and false.
-inline bool exists(const Twine &path) {
- bool result;
- return !exists(path, result) && result;
+/// @brief Does file exist?
+///
+/// @param Path Input path.
+/// @returns True if it exists, false otherwise.
+inline bool exists(const Twine &Path) {
+ return !access(Path, AccessMode::Exist);
}
/// @brief Can we execute this file?
///
/// @param Path Input path.
/// @returns True if we can execute it, false otherwise.
-bool can_execute(const Twine &Path);
+inline bool can_execute(const Twine &Path) {
+ return !access(Path, AccessMode::Execute);
+}
/// @brief Can we write this file?
///
/// @param Path Input path.
/// @returns True if we can write to it, false otherwise.
-bool can_write(const Twine &Path);
+inline bool can_write(const Twine &Path) {
+ return !access(Path, AccessMode::Write);
+}
/// @brief Do file_status's represent the same thing?
///
/// @param result Set to true if stat(A) and stat(B) have the same device and
/// inode (or equivalent).
/// @returns errc::success if result has been successfully set, otherwise a
-/// platform specific error_code.
-error_code equivalent(const Twine &A, const Twine &B, bool &result);
+/// platform-specific error_code.
+std::error_code equivalent(const Twine &A, const Twine &B, bool &result);
/// @brief Simpler version of equivalent for clients that don't need to
/// differentiate between an error and false.
/// @param result Set to true if \a path is a directory, false if it is not.
/// Undefined otherwise.
/// @returns errc::success if result has been successfully set, otherwise a
-/// platform specific error_code.
-error_code is_directory(const Twine &path, bool &result);
+/// platform-specific error_code.
+std::error_code is_directory(const Twine &path, bool &result);
/// @brief Simpler version of is_directory for clients that don't need to
/// differentiate between an error and false.
/// @param result Set to true if \a path is a regular file, false if it is not.
/// Undefined otherwise.
/// @returns errc::success if result has been successfully set, otherwise a
-/// platform specific error_code.
-error_code is_regular_file(const Twine &path, bool &result);
+/// platform-specific error_code.
+std::error_code is_regular_file(const Twine &path, bool &result);
/// @brief Simpler version of is_regular_file for clients that don't need to
/// differentiate between an error and false.
/// directory, regular file, or symlink?
///
/// @param status A file_status previously returned from status.
-/// @returns exists(s) && !is_regular_file(s) && !is_directory(s) &&
-/// !is_symlink(s)
+/// @returns exists(s) && !is_regular_file(s) && !is_directory(s)
bool is_other(file_status status);
/// @brief Is path something that exists but is not a directory,
/// @param result Set to true if \a path exists, but is not a directory, regular
/// file, or a symlink, false if it does not. Undefined otherwise.
/// @returns errc::success if result has been successfully set, otherwise a
-/// platform specific error_code.
-error_code is_other(const Twine &path, bool &result);
-
-/// @brief Does status represent a symlink?
-///
-/// @param status A file_status previously returned from stat.
-/// @returns status.type() == symlink_file.
-bool is_symlink(file_status status);
-
-/// @brief Is path a symlink?
-///
-/// @param path Input path.
-/// @param result Set to true if \a path is a symlink, false if it is not.
-/// Undefined otherwise.
-/// @returns errc::success if result has been successfully set, otherwise a
-/// platform specific error_code.
-error_code is_symlink(const Twine &path, bool &result);
+/// platform-specific error_code.
+std::error_code is_other(const Twine &path, bool &result);
/// @brief Get file status as if by POSIX stat().
///
/// @param path Input path.
/// @param result Set to the file status.
/// @returns errc::success if result has been successfully set, otherwise a
-/// platform specific error_code.
-error_code status(const Twine &path, file_status &result);
+/// platform-specific error_code.
+std::error_code status(const Twine &path, file_status &result);
/// @brief A version for when a file descriptor is already available.
-error_code status(int FD, file_status &Result);
+std::error_code status(int FD, file_status &Result);
/// @brief Get file size.
///
/// @param Path Input path.
/// @param Result Set to the size of the file in \a Path.
/// @returns errc::success if result has been successfully set, otherwise a
-/// platform specific error_code.
-inline error_code file_size(const Twine &Path, uint64_t &Result) {
+/// platform-specific error_code.
+inline std::error_code file_size(const Twine &Path, uint64_t &Result) {
file_status Status;
- error_code EC = status(Path, Status);
+ std::error_code EC = status(Path, Status);
if (EC)
return EC;
Result = Status.getSize();
- return error_code::success();
+ return std::error_code();
}
/// @brief Set the file modification and access time.
///
/// @returns errc::success if the file times were successfully set, otherwise a
-/// platform specific error_code or errc::not_supported on platforms
-/// where the functionality isn't available.
-error_code setLastModificationAndAccessTime(int FD, TimeValue Time);
+/// platform-specific error_code or errc::function_not_supported on
+/// platforms where the functionality isn't available.
+std::error_code setLastModificationAndAccessTime(int FD, TimeValue Time);
/// @brief Is status available?
///
/// @param path Input path.
/// @param result Set to true if status() != status_error.
/// @returns errc::success if result has been successfully set, otherwise a
-/// platform specific error_code.
-error_code status_known(const Twine &path, bool &result);
+/// platform-specific error_code.
+std::error_code status_known(const Twine &path, bool &result);
/// @brief Create a uniquely named file.
///
/// @param ResultFD Set to the opened file's file descriptor.
/// @param ResultPath Set to the opened file's absolute path.
/// @returns errc::success if Result{FD,Path} have been successfully set,
-/// otherwise a platform specific error_code.
-error_code createUniqueFile(const Twine &Model, int &ResultFD,
- SmallVectorImpl<char> &ResultPath,
- unsigned Mode = all_read | all_write);
+/// otherwise a platform-specific error_code.
+std::error_code createUniqueFile(const Twine &Model, int &ResultFD,
+ SmallVectorImpl<char> &ResultPath,
+ unsigned Mode = all_read | all_write);
/// @brief Simpler version for clients that don't want an open file.
-error_code createUniqueFile(const Twine &Model,
- SmallVectorImpl<char> &ResultPath);
+std::error_code createUniqueFile(const Twine &Model,
+ SmallVectorImpl<char> &ResultPath);
/// @brief Create a file in the system temporary directory.
///
///
/// This should be used for things like a temporary .s that is removed after
/// running the assembler.
-error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
- int &ResultFD,
- SmallVectorImpl<char> &ResultPath);
+std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
+ int &ResultFD,
+ SmallVectorImpl<char> &ResultPath);
/// @brief Simpler version for clients that don't want an open file.
-error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
- SmallVectorImpl<char> &ResultPath);
+std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
+ SmallVectorImpl<char> &ResultPath);
-error_code createUniqueDirectory(const Twine &Prefix,
- SmallVectorImpl<char> &ResultPath);
+std::error_code createUniqueDirectory(const Twine &Prefix,
+ SmallVectorImpl<char> &ResultPath);
-enum OpenFlags {
+enum OpenFlags : unsigned {
F_None = 0,
/// F_Excl - When opening a file, this flag makes raw_fd_ostream
return A;
}
-error_code openFileForWrite(const Twine &Name, int &ResultFD, OpenFlags Flags,
- unsigned Mode = 0666);
-
-error_code openFileForRead(const Twine &Name, int &ResultFD);
-
-/// @brief Are \a path's first bytes \a magic?
-///
-/// @param path Input path.
-/// @param magic Byte sequence to compare \a path's first len(magic) bytes to.
-/// @returns errc::success if result has been successfully set, otherwise a
-/// platform specific error_code.
-error_code has_magic(const Twine &path, const Twine &magic, bool &result);
+std::error_code openFileForWrite(const Twine &Name, int &ResultFD,
+ OpenFlags Flags, unsigned Mode = 0666);
-/// @brief Get \a path's first \a len bytes.
-///
-/// @param path Input path.
-/// @param len Number of magic bytes to get.
-/// @param result Set to the first \a len bytes in the file pointed to by
-/// \a path. Or the entire file if file_size(path) < len, in which
-/// case result.size() returns the size of the file.
-/// @returns errc::success if result has been successfully set,
-/// errc::value_too_large if len is larger then the file pointed to by
-/// \a path, otherwise a platform specific error_code.
-error_code get_magic(const Twine &path, uint32_t len,
- SmallVectorImpl<char> &result);
+std::error_code openFileForRead(const Twine &Name, int &ResultFD);
/// @brief Identify the type of a binary file based on how magical it is.
file_magic identify_magic(StringRef magic);
/// @param path Input path.
/// @param result Set to the type of file, or file_magic::unknown.
/// @returns errc::success if result has been successfully set, otherwise a
-/// platform specific error_code.
-error_code identify_magic(const Twine &path, file_magic &result);
+/// platform-specific error_code.
+std::error_code identify_magic(const Twine &path, file_magic &result);
-error_code getUniqueID(const Twine Path, UniqueID &Result);
+std::error_code getUniqueID(const Twine Path, UniqueID &Result);
/// This class represents a memory mapped file. It is based on
/// boost::iostreams::mapped_file.
};
private:
- /// Platform specific mapping state.
- mapmode Mode;
+ /// Platform-specific mapping state.
uint64_t Size;
void *Mapping;
#ifdef LLVM_ON_WIN32
void *FileMappingHandle;
#endif
- error_code init(int FD, bool CloseFD, uint64_t Offset);
+ std::error_code init(int FD, uint64_t Offset, mapmode Mode);
public:
- typedef char char_type;
-
- mapped_file_region(mapped_file_region&&);
- mapped_file_region &operator =(mapped_file_region&&);
-
- /// Construct a mapped_file_region at \a path starting at \a offset of length
- /// \a length and with access \a mode.
- ///
- /// \param path Path to the file to map. If it does not exist it will be
- /// created.
- /// \param mode How to map the memory.
- /// \param length Number of bytes to map in starting at \a offset. If the file
- /// is shorter than this, it will be extended. If \a length is
- /// 0, the entire file will be mapped.
- /// \param offset Byte offset from the beginning of the file where the map
- /// should begin. Must be a multiple of
- /// mapped_file_region::alignment().
- /// \param ec This is set to errc::success if the map was constructed
- /// successfully. Otherwise it is set to a platform dependent error.
- mapped_file_region(const Twine &path,
- mapmode mode,
- uint64_t length,
- uint64_t offset,
- error_code &ec);
-
/// \param fd An open file descriptor to map. mapped_file_region takes
/// ownership if closefd is true. It must have been opended in the correct
/// mode.
- mapped_file_region(int fd,
- bool closefd,
- mapmode mode,
- uint64_t length,
- uint64_t offset,
- error_code &ec);
+ mapped_file_region(int fd, mapmode mode, uint64_t length, uint64_t offset,
+ std::error_code &ec);
~mapped_file_region();
- mapmode flags() const;
uint64_t size() const;
char *data() const;
static int alignment();
};
-/// @brief Memory maps the contents of a file
-///
-/// @param path Path to file to map.
-/// @param file_offset Byte offset in file where mapping should begin.
-/// @param size Byte length of range of the file to map.
-/// @param map_writable If true, the file will be mapped in r/w such
-/// that changes to the mapped buffer will be flushed back
-/// to the file. If false, the file will be mapped read-only
-/// and the buffer will be read-only.
-/// @param result Set to the start address of the mapped buffer.
-/// @returns errc::success if result has been successfully set, otherwise a
-/// platform specific error_code.
-error_code map_file_pages(const Twine &path, off_t file_offset, size_t size,
- bool map_writable, void *&result);
-
-
-/// @brief Memory unmaps the contents of a file
-///
-/// @param base Pointer to the start of the buffer.
-/// @param size Byte length of the range to unmmap.
-/// @returns errc::success if result has been successfully set, otherwise a
-/// platform specific error_code.
-error_code unmap_file_pages(void *base, size_t size);
-
/// Return the path to the main executable, given the value of argv[0] from
/// program startup and the address of main itself. In extremis, this function
/// may fail and return an empty path.
void replace_filename(const Twine &filename, file_status st = file_status());
const std::string &path() const { return Path; }
- error_code status(file_status &result) const;
+ std::error_code status(file_status &result) const;
bool operator==(const directory_entry& rhs) const { return Path == rhs.Path; }
bool operator!=(const directory_entry& rhs) const { return !(*this == rhs); }
namespace detail {
struct DirIterState;
- error_code directory_iterator_construct(DirIterState&, StringRef);
- error_code directory_iterator_increment(DirIterState&);
- error_code directory_iterator_destruct(DirIterState&);
+ std::error_code directory_iterator_construct(DirIterState &, StringRef);
+ std::error_code directory_iterator_increment(DirIterState &);
+ std::error_code directory_iterator_destruct(DirIterState &);
/// DirIterState - Keeps state for the directory_iterator. It is reference
/// counted in order to preserve InputIterator semantics on copy.
IntrusiveRefCntPtr<detail::DirIterState> State;
public:
- explicit directory_iterator(const Twine &path, error_code &ec) {
+ explicit directory_iterator(const Twine &path, std::error_code &ec) {
State = new detail::DirIterState;
SmallString<128> path_storage;
ec = detail::directory_iterator_construct(*State,
path.toStringRef(path_storage));
}
- explicit directory_iterator(const directory_entry &de, error_code &ec) {
+ explicit directory_iterator(const directory_entry &de, std::error_code &ec) {
State = new detail::DirIterState;
ec = detail::directory_iterator_construct(*State, de.path());
}
/// Construct end iterator.
- directory_iterator() : State(0) {}
+ directory_iterator() : State(nullptr) {}
// No operator++ because we need error_code.
- directory_iterator &increment(error_code &ec) {
+ directory_iterator &increment(std::error_code &ec) {
ec = directory_iterator_increment(*State);
return *this;
}
bool operator==(const directory_iterator &RHS) const {
if (State == RHS.State)
return true;
- if (RHS.State == 0)
+ if (!RHS.State)
return State->CurrentEntry == directory_entry();
- if (State == 0)
+ if (!State)
return RHS.State->CurrentEntry == directory_entry();
return State->CurrentEntry == RHS.State->CurrentEntry;
}
public:
recursive_directory_iterator() {}
- explicit recursive_directory_iterator(const Twine &path, error_code &ec)
- : State(new detail::RecDirIterState) {
+ explicit recursive_directory_iterator(const Twine &path, std::error_code &ec)
+ : State(new detail::RecDirIterState) {
State->Stack.push(directory_iterator(path, ec));
if (State->Stack.top() == directory_iterator())
State.reset();
}
// No operator++ because we need error_code.
- recursive_directory_iterator &increment(error_code &ec) {
+ recursive_directory_iterator &increment(std::error_code &ec) {
const directory_iterator end_itr;
if (State->HasNoPushRequest)
assert(State->Level > 0 && "Cannot pop an iterator with level < 1");
const directory_iterator end_itr;
- error_code ec;
+ std::error_code ec;
do {
if (ec)
report_fatal_error("Error incrementing directory iterator.");