#include "hash.h" #include #include #include #include #include #include #include #include const static size_t HASHSIZE = 32; // the size of the SHA256 Hashsum in bytes Hash::Hash() {} Hash::~Hash() { if(data) { delete data; data = nullptr; } } bool Hash::create(Hash& h, const std::string& file) { int fd = ::open(file.c_str(), O_RDONLY); bool result = Hash::create(h, fd); ::close(fd); return result; } bool Hash::create(Hash& h, int fd) { if(fd < 0 || h.data) { return false; } SHA256_CTX hashctx; if(SHA256_Init(&hashctx) != 1) { Log::error << "Can not create SHA256 CTX"; return false; } //determine filesize loff_t fs = lseek64(fd, 0, SEEK_END); lseek64(fd, 0, SEEK_SET); void* mapping = ::mmap(NULL, fs, PROT_READ, MAP_SHARED | MAP_POPULATE, fd, 0); if(mapping == MAP_FAILED) { return false; } ::madvise(mapping, fs, MADV_DONTDUMP); ::madvise(mapping, fs, MADV_DONTFORK); ::madvise(mapping, fs, MADV_SEQUENTIAL); ::madvise(mapping, fs, MADV_WILLNEED); if(SHA256_Update(&hashctx, mapping, fs) != 1) { Log::error << "Can not update hash"; return false; } ::munmap(mapping, fs); unsigned char* md = new unsigned char[HASHSIZE]; if(SHA256_Final(md, &hashctx) != 1) { Log::error << "Can not finalize hash"; return false; } h.data = md; return true; } Hash::operator bool() const { return data; } Hash::operator std::string() const { std::stringstream str; str << *this; return str.str(); } bool Hash::operator==(const Hash& rhs) const { // same data ptr if(data == rhs.data) return true; // both no data if(static_cast(data) == static_cast(rhs) && data == nullptr) return true; return std::memcmp(data, rhs.data, HASHSIZE) == 0; } bool Hash::operator!=(const Hash& rhs) const { return !(*this == rhs); } std::ostream& operator<<(std::ostream& str, const Hash& rhs) { str << std::hex << std::setfill('0'); for(size_t i = 0; i < HASHSIZE; ++i) { str << std::setw(2) << (int) rhs.data[i]; } return str; }