From 470ae13be812132097cf4c17a189c47def5c19a1 Mon Sep 17 00:00:00 2001 From: "Michael J. Spencer" Date: Sat, 4 Dec 2010 00:32:40 +0000 Subject: [PATCH] Support/FileSystem: Add status implementation. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@120870 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Support/FileSystem.h | 8 ++++-- lib/Support/PathV2.cpp | 2 ++ lib/Support/Unix/PathV2.inc | 32 +++++++++++++++++++++ lib/Support/Windows/PathV2.inc | 48 +++++++++++++++++++++++++++++++ 4 files changed, 87 insertions(+), 3 deletions(-) diff --git a/include/llvm/Support/FileSystem.h b/include/llvm/Support/FileSystem.h index 46bb3d68ba9..fbf1e0d0a82 100644 --- a/include/llvm/Support/FileSystem.h +++ b/include/llvm/Support/FileSystem.h @@ -91,11 +91,13 @@ struct space_info { class file_status { // implementation defined status field. + file_type Type; public: - explicit file_status(file_type v=file_type::status_error); + explicit file_status(file_type v=file_type::status_error) + : Type(v) {} - file_type type() const; - void type(file_type v); + file_type type() const { return Type; } + void type(file_type v) { Type = v; } }; /// @} diff --git a/lib/Support/PathV2.cpp b/lib/Support/PathV2.cpp index 7d4d6d1fc28..829e107b2d5 100644 --- a/lib/Support/PathV2.cpp +++ b/lib/Support/PathV2.cpp @@ -37,6 +37,8 @@ namespace { const char prefered_separator = '/'; #endif + const llvm::error_code success; + StringRef find_first_component(const StringRef &path) { // Look for this first component in the following order. // * empty (in this case we return an empty string) diff --git a/lib/Support/Unix/PathV2.inc b/lib/Support/Unix/PathV2.inc index d8575bf4e64..f71212f5e6e 100644 --- a/lib/Support/Unix/PathV2.inc +++ b/lib/Support/Unix/PathV2.inc @@ -277,6 +277,38 @@ error_code file_size(const Twine &path, uint64_t &result) { return make_error_code(errc::success); } +error_code status(const Twine &path, file_status &result) { + SmallString<128> path_storage; + StringRef p = path.toNullTerminatedStringRef(path_storage); + + struct stat status; + if (::stat(p.begin(), &status) != 0) { + error_code ec(errno, system_category()); + if (ec == errc::no_such_file_or_directory) + result = file_status(file_type::file_not_found); + else + result = file_status(file_type::status_error); + return ec; + } + + if (S_ISDIR(status.st_mode)) + result = file_status(file_type::directory_file); + else if (S_ISREG(status.st_mode)) + result = file_status(file_type::regular_file); + else if (S_ISBLK(status.st_mode)) + result = file_status(file_type::block_file); + else if (S_ISCHR(status.st_mode)) + result = file_status(file_type::character_file); + else if (S_ISFIFO(status.st_mode)) + result = file_status(file_type::fifo_file); + else if (S_ISSOCK(status.st_mode)) + result = file_status(file_type::socket_file); + else + result = file_status(file_type::type_unknown); + + return success; +} + error_code unique_file(const Twine &model, int &result_fd, SmallVectorImpl &result_path) { SmallString<128> Model; diff --git a/lib/Support/Windows/PathV2.inc b/lib/Support/Windows/PathV2.inc index a84783f96ac..7d9421ac768 100644 --- a/lib/Support/Windows/PathV2.inc +++ b/lib/Support/Windows/PathV2.inc @@ -427,6 +427,54 @@ error_code file_size(const Twine &path, uint64_t &result) { return make_error_code(errc::success); } +error_code status(const Twine &path, file_status &result) { + SmallString<128> path_storage; + SmallVector path_utf16; + + if (error_code ec = UTF8ToUTF16(path.toStringRef(path_storage), + path_utf16)) + return ec; + + DWORD attr = ::GetFileAttributesW(path_utf16.begin()); + if (attr == INVALID_FILE_ATTRIBUTES) + goto handle_status_error; + + // Handle reparse points. + if (attr & FILE_ATTRIBUTE_REPARSE_POINT) { + AutoHandle h( + ::CreateFileW(path_utf16.begin(), + 0, // Attributes only. + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, + 0)); + if (h == INVALID_HANDLE_VALUE) + goto handle_status_error; + } + + if (attr & FILE_ATTRIBUTE_DIRECTORY) + result = file_status(file_type::directory_file); + else + result = file_status(file_type::regular_file); + + return success; + +handle_status_error: + error_code ec = windows_error(::GetLastError()); + if (ec == windows_error::file_not_found || + ec == windows_error::path_not_found) + result = file_status(file_type::file_not_found); + else if (ec == windows_error::sharing_violation) + result = file_status(file_type::type_unknown); + else { + result = file_status(file_type::status_error); + return ec; + } + + return success; +} + error_code unique_file(const Twine &model, int &result_fd, SmallVectorImpl &result_path) { // Use result_path as temp storage. -- 2.34.1