Открытые форматы (gltth)

Файлы

gltth.zip Класс для работы с хешами в ntfs-потоках. Просьба не менять формат данных и название используемого потока.

File.cpp

// [...]

// greylink dc++: work with long timestamps
int64_t File::getTimeStamp(const string& aFileName) throw(FileException) {
        WIN32_FIND_DATA fd;
        HANDLE hFind = FindFirstFile(Text::toT(aFileName).c_str(), &fd);
       if (hFind == INVALID_HANDLE_VALUE)
               throw FileException(Util::translateError(GetLastError()) + ": " + aFileName);
        FindClose(hFind);
       return *(int64_t*)&fd.ftLastWriteTime;
}
void File::setTimeStamp(const string& aFileName, const int64_t stamp) throw(FileException) {
        HANDLE h = CreateFile(Text::toT(aFileName).c_str(), FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
       if(h == INVALID_HANDLE_VALUE)
               throw FileException(Util::translateError(GetLastError()) + ": " + aFileName);
       if (!SetFileTime(h, NULL, NULL, (FILETIME*)&stamp))
               throw FileException(Util::translateError(GetLastError()) + ": " + aFileName);
        CloseHandle(h);
}

// [...]

HashManager.h

#pragma once

#include "Singleton.h"
#include "MultiThreadHasher.h"
#include "TimerManager.h"
#include "DatabaseManager.h"
#include "HashManagerListener.h"

STANDARD_EXCEPTION(HashException);

class HashManager : public Singleton<HashManager>, public Speaker<HashManagerListener>, private TimerManagerListener, public MultiThreadHasher {
public:
       /** We don't keep leaves for blocks smaller than this... */
       static const int64_t MIN_BLOCK_SIZE = 64*1024;

       // Check if the TTH tree associated with the filename is current.
       tthroot_t checkTTH(const string& aFileName, int64_t aSize, uint32_t aTimeStamp);
       // start background hashing or read TTH from NTFS stream
       void hashFile(const string& aFileName, int64_t aSize, Flags flags = 0, DbFileObjPtr file = NULL);
       // start hashing from GUI, etc
       void hashFile(const string& aFileName, Flags flags = 0);

       // fire TTHDone event for all queued done hashes
       void flushHasher();

       bool getTTH(const string& aFileName, TTHValue& dst) throw(); // [gl] nothrow version
       bool getTree(const TTHValue& root, TigerTree& tt);
       void addTree(const TigerTree& tree);

        string getFilePath(const TTHValue& tth); // [gl]-s
       size_t getBlockSize(const TTHValue& root, int64_t* fileSize = NULL);

       void startup();
       void shutdown();

       class StreamStore { // greylink dc++: work with ntfs stream
       public:
                StreamStore(const string& aFileName) : fileName(aFileName) { }
               bool loadTree(TigerTree& tt, int64_t aFileSize = -1);
               bool saveTree(const TigerTree& tt);
       private:
               struct TTHStreamHeader {
                        uint32_t magic;
                        uint32_t checksum;      // xor of other TTHStreamHeader DWORDs
                       uint64_t fileSize;
                        uint64_t timeStamp;
                        uint64_t blockSize;
                        TTHValue root;
                };
               static const uint64_t minStreamedFileSize = 16*1048576;
               static const uint32_t MAGIC = '++lg';
               static const string streamName;
                string fileName;

               void setCheckSum(TTHStreamHeader& h);
               bool validateCheckSum(const TTHStreamHeader& h);
        };

private:
        HasherFileTask::List finished;
        CriticalSection cs;

       void hashDone(HasherFileTask::Ptr& fileTask, bool fromStream);

       // `MultiThreadHasher` override
       virtual void hashDone(HasherFileTask::Ptr& fileTask) { hashDone(fileTask, false); }

       // TimerManagerListener
       void on(Second, tick_t) throw() {}
       void on(Minute, tick_t) throw();
};

HashManager.cpp

// [...]


// greylink dc++
const string HashManager::StreamStore::streamName(".gltth");
void HashManager::StreamStore::setCheckSum(TTHStreamHeader& h) {
        h.magic = MAGIC;
        uint32_t sum = 0;
       for (size_t i = 0; i < sizeof(TTHStreamHeader) / sizeof(uint32_t); i++)
                sum ^= ((uint32_t*)&h)[i];
        h.checksum ^= sum;
}

bool HashManager::StreamStore::validateCheckSum(const TTHStreamHeader& h) {
       if (h.magic != MAGIC)
               return false;
        uint32_t sum = 0;
       for (size_t i = 0; i < sizeof(TTHStreamHeader) / sizeof(uint32_t); i++)
                sum ^= ((uint32_t*)&h)[i];
       return (sum == 0);
}
bool HashManager::StreamStore::loadTree(TigerTree& tt, int64_t aFileSize /* = -1 */ ) {
       try {
                int64_t fileSize = (aFileSize == -1)? File::getSize(fileName) : aFileSize;
               if (fileSize < minStreamedFileSize) // that's why minStreamedFileSize never be changed!
                       return false;
                uint64_t timeStamp = File::getTimeStamp(fileName);
                {
                        File stream(fileName + ":" + streamName, File::READ, File::OPEN);
                        size_t sz = sizeof(TTHStreamHeader);
                        TTHStreamHeader h;
                       if (stream.read(&h, sz) != sizeof(TTHStreamHeader))
                               return false;
                       if (!validateCheckSum(h) || (uint64_t)fileSize != h.fileSize || timeStamp != h.timeStamp)
                               return false;
                        size_t datalen = TigerTree::calcBlocks(fileSize, h.blockSize) * TTHValue::BYTES;
                        sz = datalen;
                        AutoArray<uint8_t> buf(datalen);
                       if (stream.read((uint8_t*)buf, sz) != datalen)
                               return false;
                        tt = TigerTree(fileSize, h.blockSize, buf);
                       if(!(tt.getRoot() == h.root))
                               return false;
                }
        } catch (const Exception&) {
               return false;
        }
       return true;
}

bool HashManager::StreamStore::saveTree(const TigerTree& tt) {
       if (!gSETTING(TTH_IN_NTFS_STREAM))
               return false;
       try {
                TTHStreamHeader h;
                h.fileSize = File::getSize(fileName);
               if (h.fileSize < minStreamedFileSize || h.fileSize != (uint64_t)tt.getFileSize())
                       return false; // that's why minStreamedFileSize never be changed!
               h.timeStamp = File::getTimeStamp(fileName);
                h.root = tt.getRoot();
                h.blockSize = tt.getBlockSize();
                setCheckSum(h);
                {
                        File stream(fileName + ":" + streamName, File::WRITE, File::CREATE | File::TRUNCATE);
                        stream.write(&h, sizeof(TTHStreamHeader));
                        stream.write(tt.getLeaves()[0].data, tt.getLeaves().size() * TTHValue::BYTES);
                }
                File::setTimeStamp(fileName, h.timeStamp);
        } catch (const Exception&) {
               return false;
        }
       return true;
}

// [...]
Тэги:
Код для вставки: :: :: :: ГОСТ ::
Поделиться: //
 

Реклама

Для скачивания с этих сайтов нужно подключиться к внешним хабам

Нужен свой портал? magneto!