Support/PathV2: Implement has_magic.
authorMichael J. Spencer <bigcheesegs@gmail.com>
Tue, 28 Dec 2010 01:49:01 +0000 (01:49 +0000)
committerMichael J. Spencer <bigcheesegs@gmail.com>
Tue, 28 Dec 2010 01:49:01 +0000 (01:49 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@122587 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Support/FileSystem.h
lib/Support/PathV2.cpp

index 2a2daaecedfcda4fd9fb6b82def8855d20b3b067..960875e989752a877521665b97d11e8024096df4 100644 (file)
@@ -448,7 +448,7 @@ error_code canonicalize(const Twine &path, SmallVectorImpl<char> &result);
 /// @param magic Byte sequence to compare \a path's first len(magic) bytes to.
 /// @results errc::success if result has been successfully set, otherwise a
 ///          platform specific error_code.
-error_code has_magic(const Twine &path, const Twine &magic);
+error_code has_magic(const Twine &path, const Twine &magic, bool &result);
 
 /// @brief Get \a path's first \a len bytes.
 ///
index 335f7ff91944475350da1456d0ac4672a9c5d98a..4cfb650a6cc8984c96e78450c7f0eaf40486ea94 100644 (file)
@@ -15,6 +15,8 @@
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/ErrorHandling.h"
 #include <cctype>
+#include <cstdio>
+#include <cstring>
 
 namespace {
   using llvm::StringRef;
@@ -659,6 +661,42 @@ void directory_entry::replace_filename(const Twine &filename, file_status st,
   SymlinkStatus = symlink_st;
 }
 
+error_code has_magic(const Twine &path, const Twine &magic, bool &result) {
+  SmallString<128> PathStorage;
+  SmallString<32>  MagicStorage;
+  StringRef Path  = path.toNullTerminatedStringRef(PathStorage);
+  StringRef Magic = magic.toNullTerminatedStringRef(MagicStorage);
+
+  assert(Magic.size() > 0 && "magic must be non-empty!");
+
+  SmallString<32> BufferStorage;
+  BufferStorage.reserve(Magic.size());
+
+  // Open file.
+  std::FILE *file = std::fopen(Path.data(), "rb");
+  if (file == 0)
+    return error_code(errno, posix_category());
+  int size = ::fread(BufferStorage.data(), 1, Magic.size(), file);
+  if (size != Magic.size()) {
+    int error = errno;
+    bool eof = std::feof(file) != 0;
+    std::fclose(file);
+    if (eof) {
+      // EOF, return false.
+      result = false;
+      return success;
+    }
+    return error_code(error, posix_category());
+  }
+  std::fclose(file);
+
+  if (std::memcmp(BufferStorage.data(), Magic.data(), Magic.size()) != 0)
+    result = false;
+  else
+    result = true;
+  return success;
+}
+
 } // end namespace fs
 } // end namespace sys
 } // end namespace llvm