From ee1699c3625cfbc2b122e11f4259860fff5b0e68 Mon Sep 17 00:00:00 2001 From: "Michael J. Spencer" Date: Sat, 15 Jan 2011 18:52:33 +0000 Subject: [PATCH] Support/PathV2: Implement get_magic. llvm-svn: 123544 --- llvm/include/llvm/Support/FileSystem.h | 8 +++-- llvm/lib/Support/Unix/PathV2.inc | 31 +++++++++++++++++ llvm/lib/Support/Windows/PathV2.inc | 42 +++++++++++++++++++++++ llvm/lib/Support/Windows/system_error.inc | 1 + 4 files changed, 79 insertions(+), 3 deletions(-) diff --git a/llvm/include/llvm/Support/FileSystem.h b/llvm/include/llvm/Support/FileSystem.h index 960875e98975..12f6d9b1d7a9 100644 --- a/llvm/include/llvm/Support/FileSystem.h +++ b/llvm/include/llvm/Support/FileSystem.h @@ -455,9 +455,11 @@ error_code has_magic(const Twine &path, const Twine &magic, bool &result); /// @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. -/// @results errc::success if result has been successfully set, otherwise a -/// platform specific error_code. +/// \a path. Or the entire file if file_size(path) < len, in which +/// case result.size() returns the size of the file. +/// @results 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 &result); diff --git a/llvm/lib/Support/Unix/PathV2.inc b/llvm/lib/Support/Unix/PathV2.inc index 80e75ecbf5a0..056708a7b0b1 100644 --- a/llvm/lib/Support/Unix/PathV2.inc +++ b/llvm/lib/Support/Unix/PathV2.inc @@ -462,6 +462,37 @@ error_code directory_iterator_increment(directory_iterator& it) { return success; } +error_code get_magic(const Twine &path, uint32_t len, + SmallVectorImpl &result) { + SmallString<128> PathStorage; + StringRef Path = path.toNullTerminatedStringRef(PathStorage); + result.set_size(0); + + // Open path. + std::FILE *file = std::fopen(Path.data(), "rb"); + if (file == 0) + return error_code(errno, system_category()); + + // Reserve storage. + result.reserve(len); + + // Read magic! + size_t size = std::fread(result.data(), 1, len, file); + if (std::ferror(file) != 0) { + std::fclose(file); + return error_code(errno, system_category()); + } else if (size != result.size()) { + if (std::feof(file) != 0) { + std::fclose(file); + result.set_size(size); + return make_error_code(errc::value_too_large); + } + } + std::fclose(file); + result.set_size(len); + return success; +} + } // end namespace fs } // end namespace sys } // end namespace llvm diff --git a/llvm/lib/Support/Windows/PathV2.inc b/llvm/lib/Support/Windows/PathV2.inc index c618dbf52008..f4629a15c4b5 100644 --- a/llvm/lib/Support/Windows/PathV2.inc +++ b/llvm/lib/Support/Windows/PathV2.inc @@ -616,6 +616,48 @@ retry_create_file: return success; } +error_code get_magic(const Twine &path, uint32_t len, + SmallVectorImpl &result) { + SmallString<128> path_storage; + SmallVector path_utf16; + result.set_size(0); + + // Convert path to UTF-16. + if (error_code ec = UTF8ToUTF16(path.toStringRef(path_storage), + path_utf16)) + return ec; + + // Open file. + HANDLE file = ::CreateFileW(c_str(path_utf16), + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_READONLY, + NULL); + if (file == INVALID_HANDLE_VALUE) + return windows_error(::GetLastError()); + + // Allocate buffer. + result.reserve(len); + + // Get magic! + DWORD bytes_read = 0; + BOOL read_success = ::ReadFile(file, result.data(), len, &bytes_read, NULL); + error_code ec = windows_error(::GetLastError()); + ::CloseHandle(file); + if (!read_success || (bytes_read != len)) { + // Set result size to the number of bytes read if it's valid. + if (bytes_read >= 0 && bytes_read <= len) + result.set_size(bytes_read); + // ERROR_HANDLE_EOF is mapped to errc::value_too_large. + return ec; + } + + result.set_size(len); + return success; +} + error_code directory_iterator_construct(directory_iterator &it, StringRef path){ SmallVector path_utf16; diff --git a/llvm/lib/Support/Windows/system_error.inc b/llvm/lib/Support/Windows/system_error.inc index 73304d517fa9..64753d0eea8a 100644 --- a/llvm/lib/Support/Windows/system_error.inc +++ b/llvm/lib/Support/Windows/system_error.inc @@ -79,6 +79,7 @@ _system_error_category::default_error_condition(int ev) const { MAP_ERR_TO_COND(ERROR_FILE_EXISTS, file_exists); MAP_ERR_TO_COND(ERROR_FILE_NOT_FOUND, no_such_file_or_directory); MAP_ERR_TO_COND(ERROR_HANDLE_DISK_FULL, no_space_on_device); + MAP_ERR_TO_COND(ERROR_HANDLE_EOF, value_too_large); MAP_ERR_TO_COND(ERROR_INVALID_ACCESS, permission_denied); MAP_ERR_TO_COND(ERROR_INVALID_DRIVE, no_such_device); MAP_ERR_TO_COND(ERROR_INVALID_FUNCTION, function_not_supported);