#include #include #include #include #include #include #include #include typedef unsigned long lword; typedef unsigned long long llword; typedef unsigned char byte; char* strcopy(const char* s) { char* r = new char[(strlen(s)+1)]; strcpy(r,s); return r; } lword readhexlong(const char* s) { int i; lword result = 0; for (i = 0; i < 8; i++) if ('0' <= s[i] && s[i] <= '9') result = (result << 4) | (s[i] - '0'); else if ('A' <= s[i] && s[i] <= 'F') result = (result << 4) | (s[i] - 'A' + 10); return result; } class DirectoryFileIterator { public: DirectoryFileIterator(const char* name) { fin = fopen(name, "rt"); next(); // skip first line next(); } ~DirectoryFileIterator() { if (fin != 0) fclose(fin); } void next() { if (fin == 0) { depth = -1; return; } is_dir = false; length = 0; date = 0; h1 = 0; h2 = 0; h3 = 0; char buf[1000]; fgets(buf, 999, fin); if (feof(fin) || buf[0] == '\0' || buf[0] == '\n') { fclose(fin); fin = 0; depth = -1; return; } char *s = buf; depth = 0; while (*s == ' ') { s++; depth++; } char *name = s; while (s[1] != '\0' && s[1] != '\n') s++; if (s[1] == '\n') s[1] = '\0'; int i = 0; while (s >= buf && isxdigit(*s)) { s--; i++; } if (i != 32 || *s != ' ' || s <= name) { is_dir = true; strcpy(filename, name); return; } char *hash = s+1; s--; i = 0; while (isdigit(*s)) { s--; i++; } if (i == 0 || *s != ' ') { is_dir = true; strcpy(filename, name); return; } length = atol(s+1); *s = '\0'; strcpy(filename, name); date = readhexlong(hash); h1 = readhexlong(hash+8); h2 = readhexlong(hash+16); h3 = readhexlong(hash+24); } int depth; char filename[1000]; bool is_dir; lword length; lword date; lword h1; lword h2; lword h3; private: FILE *fin; }; //int depth = 0; class HashData { public: HashData() : length(0), date(0), h1(0), h2(0), h3(0) {} HashData(lword n_length, lword n_date, lword n_h1, lword n_h2, lword n_h3) : length(n_length), date(n_date), h1(n_h1), h2(n_h2), h3(n_h3) {} lword length; lword date; lword h1, h2, h3; bool operator==(const HashData& rhs) { return length == rhs.length // && date == rhs.date && h1 == rhs.h1 && h2 == rhs.h2 && h3 == rhs.h3; } bool operator!=(const HashData& rhs) { return !(*this == rhs); } bool operator<(const HashData& rhs) { if (length < rhs.length) return true; if (length > rhs.length) return false; //if (date < rhs.date) return true; //if (date > rhs.date) return false; if (h1 < rhs.h1) return true; if (h1 > rhs.h1) return false; if (h2 < rhs.h2) return true; if (h2 > rhs.h2) return false; return h3 < rhs.h3; } void filehash(const char *fn) { FILE *f = fopen(fn, "rb"); if (f == 0) { h1 = 0; h2 = 0; h3 = 0; return; } //printf("!"); lword r1 = 0; lword r2 = 3; h1 = 0; h2 = 3; h3 = 41; char ch; while (ch = fgetc(f), !feof(f)) { r1 = (r1 + 64763) % 78887; r2 = (r2 + 67354) % 52361; h1 = (ch*r1) ^ (h1 * 31) ^ (h1 >> 4); h2 = (ch*r2) ^ (h2 * 29) ^ (h2 >> 5); h3 = ch ^ (h3 * 37) ^ (h3 >> 3); } fclose(f); if (h1 == 0) h1 = 1; } }; class FileEntry; class UniqueFile { public: UniqueFile() : entries(0) {} ~UniqueFile() { delete entries; } void add(FileEntry* entry) { entries = new FileEntryList(entry, entries); } private: struct FileEntryList { FileEntryList(FileEntry* n_entry, FileEntryList* n_next) : entry(n_entry), next(n_next) {} ~FileEntryList() { delete next; } FileEntry* entry; FileEntryList* next; }; FileEntryList* entries; public: class EntryIterator { public: EntryIterator(UniqueFile *uniqueFile) : _it(uniqueFile->entries) {} inline bool more() { return _it != 0; } inline void next() { _it = _it->next; } inline FileEntry* value() { return _it->entry; } private: FileEntryList* _it; }; FileEntry* first() { return entries != 0 ? entries->entry : 0; } }; class UniqueFileList { public: UniqueFileList() : elements(0) {} private: struct UniqueFileListElem { UniqueFileListElem(UniqueFile* n_uniqueFile, UniqueFileListElem* n_next) : uniqueFile(n_uniqueFile), next(n_next) {} UniqueFile* uniqueFile; UniqueFileListElem* next; }; UniqueFileListElem* elements; public: UniqueFile* add() { UniqueFile* uniqueFile = new UniqueFile(); elements = new UniqueFileListElem(uniqueFile, elements); return uniqueFile; } class iterator { public: iterator(UniqueFileList* list) { it = list->elements; } inline bool more() { return it != 0; } inline void next() { it = it->next; } inline UniqueFile* value() { return it->uniqueFile; } private: UniqueFileListElem* it; }; }; const int hash_table_size = 10000; class HashTable { public: HashTable() { for (int i = 0; i < hash_table_size; i++) hash_table[i] = 0; } UniqueFileList* getUniqueFileList(HashData& hashData) { lword o = (lword)(hashData.length + hashData.h1 + hashData.h2 + hashData.h3) % hash_table_size; if (o < 0 || o >= hash_table_size) fprintf(stderr, "FATAL\n"); HashEntry** ref_hash_ent = &hash_table[o]; while ((*ref_hash_ent) != 0 && (*ref_hash_ent)->key != hashData) ref_hash_ent = &(*ref_hash_ent)->next; if ((*ref_hash_ent) == 0) *ref_hash_ent = new HashEntry(hashData); return &(*ref_hash_ent)->uniqueFileList; } private: struct HashEntry { HashEntry(HashData& data) : key(data), next(0) {} HashData key; UniqueFileList uniqueFileList; HashEntry* next; }; HashEntry* hash_table[hash_table_size]; }; class FileEntry { public: FileEntry() : parent(0), name(0), is_dir(true), first_child(0), next_sibling(0), state(s_unknown), unique_file(0) {} FileEntry(FileEntry* n_parent, const char* n_name) : parent(n_parent), name(strcopy(n_name)), is_dir(false), first_child(0), next_sibling(0), state(s_unknown), unique_file(0) {} FileEntry(FileEntry* n_parent, const char* n_name, bool n_is_dir, const HashData& n_hashData) : parent(n_parent), name(strcopy(n_name)), is_dir(n_is_dir), hashData(n_hashData), first_child(0), next_sibling(0), state(s_unknown), unique_file(0) {} ~FileEntry() { delete name; for (ChildIterator it(this); it.more();) { FileEntry* child = it.value(); it.next(); delete child; } } char *name; bool is_dir; HashData hashData; enum { s_unknown, s_verified, s_incorrect, s_not_verified } state; UniqueFile* unique_file; class ChildIterator { public: ChildIterator(const FileEntry* entry) : _it(entry->first_child) {} inline bool more() { return _it != 0; } inline void next() { _it = _it->next_sibling; } inline FileEntry* value() { return _it; } private: FileEntry* _it; }; FileEntry* findChild(const char* name) { for (ChildIterator it(this); it.more(); it.next()) if (strcmp(it.value()->name, name) == 0) return it.value(); return 0; } void print(FILE* f, int depth) { if (depth >= 0) { fprintf(f, "%*.*s%s", depth, depth, "", name); if (!is_dir) fprintf(f, " %ld %08lX%08lX%08lX%08lX\n", hashData.length, hashData.date, hashData.h1, hashData.h2, hashData.h3); else fprintf(f, "\n"); } for (ChildIterator it(this); it.more(); it.next()) it.value()->print(f, depth+1); } void readFromFile(DirectoryFileIterator &readdir, int depth, lword &oldestDate) { FileEntry** ref_next_child = &first_child; while (*ref_next_child != 0) ref_next_child = &(*ref_next_child)->next_sibling; while (readdir.depth == depth) { FileEntry* child = 0; // Check if already entry with same name for (ChildIterator it(this); it.more(); it.next()) if (strcmp(it.value()->name, readdir.filename) == 0) { child = it.value(); break; } if (child == 0) { child = new FileEntry(this, readdir.filename, readdir.is_dir, HashData(readdir.length, readdir.date, readdir.h1, readdir.h2, readdir.h3)); *ref_next_child = child; ref_next_child = &child->next_sibling; } else if (!child->is_dir && !readdir.is_dir) { if (child->is_dir == readdir.is_dir && child->hashData == HashData(readdir.length, readdir.date, readdir.h1, readdir.h2, readdir.h3)) fprintf(stdout, "Warning: %s double entry. Ignored\n", child->fullName()); else { fprintf(stdout, "Error: %s different double file entry found. Overwritten\n", child->fullName()); child->hashData = HashData(readdir.length, readdir.date, readdir.h1, readdir.h2, readdir.h3); } } if (!child->is_dir && !readdir.is_dir && readdir.date > oldestDate) oldestDate = readdir.date; readdir.next(); if (child->is_dir) child->readFromFile(readdir, depth+1, oldestDate); } } void readFromDirectory(const char* dir_path) { fprintf(stderr, "read_dir_from_disk %s\n", dir_path); FileEntry** ref_next_child = &first_child; char buf[1000]; strcpy(buf, dir_path); char *s = buf + strlen(buf); *s++ = '/'; DIR* dir = opendir(dir_path); for (struct dirent *dir_ent; (dir_ent = readdir(dir)) != 0;) { strcpy(s, dir_ent->d_name); if (s[0] != '.' || (s[1] != '.' && s[1] != '\0')) { FileEntry *entry = new FileEntry(this, dir_ent->d_name); *ref_next_child = entry; ref_next_child = &entry->next_sibling; struct stat file_stat; stat(buf, &file_stat); if (S_ISDIR(file_stat.st_mode)) { entry->is_dir = true; entry->readFromDirectory(buf); //printf("%*.*s%s Dir\n", depth, depth, "", s); } else { entry->hashData.date = file_stat.st_mtime; entry->hashData.length = file_stat.st_size; entry->hashData.filehash(buf); //printf("%*.*s%s\n", depth, depth, "", s); //fprintf(stderr, "."); } } } closedir(dir); } void verifyWith(FileEntry* other, FILE* f) { if (hashData == other->hashData) { if (state == s_incorrect) fprintf(f, "Message: %s - found correct hash after incorrect one was found\n", fullName()); state = s_verified; } else if (state == s_verified) fprintf(f, "Warning: %s - alternative hash does not match\n", fullName()); else { fprintf(f, "Error: %s - hash does not match\n", fullName()); state = s_incorrect; } for (ChildIterator it(this); it.more(); it.next()) { FileEntry* child = it.value(); FileEntry* other_child = other->findChild(child->name); if (other_child != 0) child->verifyWith(other_child, f); } for (ChildIterator it(other); it.more(); it.next()) { FileEntry* other_child = it.value(); FileEntry* child = findChild(other_child->name); if (child == 0) fprintf(f, "Info: %s - extra in hash file\n", other_child->fullName()); } } void markNotVerified() { if (state == s_unknown) { state = s_not_verified; if (is_dir) { fprintf(stdout, "Error: %s - directory not verified\n", fullName()); return; } else if (hashData.length == 0) fprintf(stdout, "Info: %s - empty file\n", fullName()); else fprintf(stdout, "Warning: %s - not verified\n", fullName()); } for (ChildIterator it(this); it.more(); it.next()) it.value()->markNotVerified(); } void analyze(HashTable &hash_table, llword &nr_first, llword &size_first, llword &nr_matched, llword &size_matched) { if (!is_dir && hashData.length > 0) { UniqueFileList* uniqueFileList = hash_table.getUniqueFileList(hashData); for (UniqueFileList::iterator it(uniqueFileList); it.more(); it.next()) if (it.value()->first() != 0 && strcmp(it.value()->first()->name, name) == 0) { unique_file = it.value(); nr_matched++; size_matched += hashData.length; break; } if (unique_file == 0) { fprintf(stdout, "%s\n", fullName()); nr_first++; size_first += hashData.length; unique_file = uniqueFileList->add(); } unique_file->add(this); } for (ChildIterator it(this); it.more(); it.next()) it.value()->analyze(hash_table, nr_first, size_first, nr_matched, size_matched); } private: FileEntry* parent; FileEntry* first_child; FileEntry* next_sibling; void fillPath(char *buf) { if (parent != 0 && parent->name != 0) { parent->fillPath(buf); strcat(buf, "/"); } strcat(buf, name); } const char* fullName() { static char buf[1000]; buf[0] = '\0'; fillPath(buf); return buf; } }; class FileDirectoryListing : public FileEntry { public: FileDirectoryListing() : oldestDate(0), next(0) {} lword oldestDate; void print(FILE *f, const char* header) { fprintf(f, "%s\n", header); FileEntry::print(f, -1); } void output(const char* filename, const char* dir) { FILE *f = fopen(filename, "wt"); if (f == 0) return; fprintf(f, "%s\n", dir); FileEntry::print(f, -1); fclose(f); } void readFromFile(const char* filename) //, byte medium, double weight, bool summertime) { fprintf(stdout, "Info: read from file: %s\n", filename); name = strcopy(filename); DirectoryFileIterator readdir(filename); FileEntry::readFromFile(readdir, 0, oldestDate); } void verifyWith(const char *filename) { FileDirectoryListing verifyFileDirListing; verifyFileDirListing.readFromFile(filename); FileEntry::verifyWith(&verifyFileDirListing, stdout); } void verifyWithChild(const char *filename, const char *childname) { FileDirectoryListing verifyFileDirListing; verifyFileDirListing.readFromFile(filename); FileEntry* childDir = verifyFileDirListing.findChild(childname); if (childDir == 0 || !childDir->is_dir) fprintf(stdout, "Did not find directory %s\n", childname); else FileEntry::verifyWith(childDir, stdout); } FileDirectoryListing* next; }; class FileDirectoryListings { public: FileDirectoryListings() : first_listing(0) { ref_next_listing = &first_listing; } void add(FileDirectoryListing& listing) { (*ref_next_listing) = &listing; ref_next_listing = &listing.next; } class iterator { public: iterator(FileDirectoryListings &listings) : _it(listings.first_listing) {} inline bool more() { return _it != 0; } inline void next() { _it = _it->next; } inline FileDirectoryListing* value() { return _it; } private: FileDirectoryListing* _it; }; private: FileDirectoryListing* first_listing; FileDirectoryListing** ref_next_listing; }; void make_dir_listing(const char *dir, const char *output_filename) { FileDirectoryListing fileDirListing; fileDirListing.readFromDirectory(dir); fileDirListing.output(output_filename, dir); } void make_dir_listing_cd(const char *dir) { char buf[500]; sprintf(buf, "ls/%s", dir); make_dir_listing(dir, buf); } int main(int argc, char *argv[]) { // -- command line arguments are ignored /* // Scan directories and create hashes make_dir_listing("../floppies", "ls/floppies"); make_dir_listing("../ester", "ls/ester"); make_dir_listing_cd("cd001214"); make_dir_listing_cd("cd010310"); make_dir_listing_cd("cd010601"); make_dir_listing_cd("cd010703"); make_dir_listing_cd("cd010713"); make_dir_listing_cd("cd010822"); make_dir_listing_cd("cd011027"); make_dir_listing_cd("cd011231"); make_dir_listing_cd("cd020314"); make_dir_listing_cd("cd020326"); make_dir_listing_cd("cd020617"); make_dir_listing_cd("cd020915"); make_dir_listing_cd("cd021124"); make_dir_listing_cd("cd030216"); make_dir_listing_cd("cd030812"); make_dir_listing_cd("cd031122"); make_dir_listing_cd("cd040114"); make_dir_listing_cd("cd040430"); make_dir_listing_cd("cd040813"); make_dir_listing_cd("cd041205"); make_dir_listing_cd("cd050102"); make_dir_listing_cd("cd050227"); make_dir_listing_cd("cd050306"); make_dir_listing_cd("cd050419"); make_dir_listing_cd("cd050807"); make_dir_listing_cd("cd051112"); make_dir_listing_cd("cd060129"); make_dir_listing("e:/g", "ls/lacie"); make_dir_listing("g:/g", "ls/freecom_g"); make_dir_listing("g:/Ester", "ls/freecom_ester"); make_dir_listing("f:/Temp", "ls/freecom_temp"); make_dir_listing("c:/g", "ls/c_g"); make_dir_listing("c:/Temp/stick", "ls/c_temp_stick"); make_dir_listing("c:/Temp/Ester", "ls/c_temp_ester"); */ FileDirectoryListings allListings; FileDirectoryListing fd_cd001214; fd_cd001214.readFromFile("ls/cd001214"); fd_cd001214.verifyWith("contents/cdtranscoop"); fd_cd001214.markNotVerified(); allListings.add(fd_cd001214); fprintf(stdout, "\n-----\n"); FileDirectoryListing fd_cd010310; fd_cd010310.readFromFile("ls/cd010310"); fd_cd010310.verifyWith("contents/cd20010310"); //.verifyWith("contents/cd20010310.txt"); //.verifyWith("contents/cd20010310.txt.gz"); fd_cd010310.markNotVerified(); allListings.add(fd_cd010310); //.verifyWith("contents/cd20010531"); fprintf(stdout, "\n-----\n"); FileDirectoryListing fd_cd010601; fd_cd010601.readFromFile("ls/cd010601"); allListings.add(fd_cd010601); fprintf(stdout, "\n-----\n"); FileDirectoryListing fd_cd010703; fd_cd010703.readFromFile("ls/cd010703"); fd_cd010703.verifyWith("contents/cdpa"); fd_cd010703.markNotVerified(); allListings.add(fd_cd010703); fprintf(stdout, "\n-----\n"); FileDirectoryListing fd_cd010713; fd_cd010713.readFromFile("ls/cd010713"); fd_cd010713.verifyWith("contents/cd20010713"); fd_cd010713.markNotVerified(); allListings.add(fd_cd010713); fprintf(stdout, "\n-----\n"); FileDirectoryListing fd_cd010822; fd_cd010822.readFromFile("ls/cd010822"); fd_cd010822.verifyWith("contents/cd20010822"); fd_cd010822.markNotVerified(); allListings.add(fd_cd010822); fprintf(stdout, "\n-----\n"); FileDirectoryListing fd_cd011027; fd_cd011027.readFromFile("ls/cd011027"); fd_cd011027.verifyWith("contents/cd20011027"); fd_cd011027.markNotVerified(); allListings.add(fd_cd011027); fprintf(stdout, "\n-----\n"); FileDirectoryListing fd_cd011231; fd_cd011231.readFromFile("ls/cd011231"); fd_cd011231.verifyWith("contents/cd20011231"); fd_cd011231.markNotVerified(); allListings.add(fd_cd011231); fprintf(stdout, "\n-----\n"); FileDirectoryListing fd_cd020314; fd_cd020314.readFromFile("ls/cd020314"); fd_cd020314.verifyWith("contents/cdtelic"); fd_cd020314.markNotVerified(); allListings.add(fd_cd020314); fprintf(stdout, "\n-----\n"); FileDirectoryListing fd_cd020326; fd_cd020326.readFromFile("ls/cd020326"); fd_cd020326.verifyWith("contents/cd20020326"); fd_cd020326.markNotVerified(); allListings.add(fd_cd020326); fprintf(stdout, "\n-----\n"); FileDirectoryListing fd_cd020617; fd_cd020617.readFromFile("ls/cd020617"); fd_cd020617.verifyWithChild("contents/cd20020617", "andy"); fd_cd020617.state = FileEntry::s_verified; fd_cd020617.markNotVerified(); allListings.add(fd_cd020617); fprintf(stdout, "\n-----\n"); FileDirectoryListing fd_cd020915; fd_cd020915.readFromFile("ls/cd020915"); fd_cd020915.verifyWith("contents/cd20020915"); fd_cd020915.markNotVerified(); allListings.add(fd_cd020915); fprintf(stdout, "\n-----\n"); FileDirectoryListing fd_cd021124; fd_cd021124.readFromFile("ls/cd021124"); fd_cd021124.verifyWith("contents/cd20021124"); fd_cd021124.markNotVerified(); allListings.add(fd_cd021124); fprintf(stdout, "\n-----\n"); FileDirectoryListing fd_cd030216; fd_cd030216.readFromFile("ls/cd030216"); fd_cd030216.verifyWith("contents/cd20030216"); fd_cd030216.markNotVerified(); allListings.add(fd_cd030216); fprintf(stdout, "\n-----\n"); FileDirectoryListing fd_cd030812; fd_cd030812.readFromFile("ls/cd030812"); fd_cd030812.verifyWith("contents/cd20030812"); fd_cd030812.markNotVerified(); allListings.add(fd_cd030812); fprintf(stdout, "\n-----\n"); FileDirectoryListing fd_cd031122; fd_cd031122.readFromFile("ls/cd031122"); fd_cd031122.verifyWith("contents/cd20031122"); fd_cd031122.markNotVerified(); allListings.add(fd_cd031122); fprintf(stdout, "\n-----\n"); FileDirectoryListing fd_cd040114; fd_cd040114.readFromFile("ls/cd040114"); fd_cd040114.verifyWith("contents/cd20040113"); fd_cd040114.verifyWith("contents/cd20040113b"); fd_cd040114.markNotVerified(); allListings.add(fd_cd040114); fprintf(stdout, "\n-----\n"); FileDirectoryListing fd_cd040430; fd_cd040430.readFromFile("ls/cd040430"); fd_cd040430.verifyWith("contents/cd20040430"); fd_cd040430.verifyWith("contents/cd20040430b"); fd_cd040430.markNotVerified(); allListings.add(fd_cd040430); fprintf(stdout, "\n-----\n"); FileDirectoryListing fd_cd040813; fd_cd040813.readFromFile("ls/cd040813"); fd_cd040813.verifyWith("contents/cd20040813"); fd_cd040813.verifyWith("contents/cd20040813b"); fd_cd040813.markNotVerified(); allListings.add(fd_cd040813); fprintf(stdout, "\n-----\n"); FileDirectoryListing fd_cd041205; fd_cd041205.readFromFile("ls/cd041205"); fd_cd041205.verifyWith("contents/cd20041205"); fd_cd041205.verifyWith("contents/cd20041205b"); fd_cd041205.markNotVerified(); allListings.add(fd_cd041205); fprintf(stdout, "\n-----\n"); FileDirectoryListing fd_cd050102; fd_cd050102.readFromFile("ls/cd050102"); fd_cd050102.verifyWith("contents/cd20050102"); fd_cd050102.markNotVerified(); allListings.add(fd_cd050102); fprintf(stdout, "\n-----\n"); FileDirectoryListing fd_cd050227; fd_cd050227.readFromFile("ls/cd050227"); fd_cd050227.verifyWithChild("contents/cd20050227", "cd"); fd_cd050227.verifyWith("contents/cd20050227b"); fd_cd050227.markNotVerified(); allListings.add(fd_cd050227); fprintf(stdout, "\n-----\n"); FileDirectoryListing fd_cd050306; fd_cd050306.readFromFile("ls/cd050306"); fd_cd050306.verifyWith("contents/cd20050306"); fd_cd050306.markNotVerified(); allListings.add(fd_cd050306); fprintf(stdout, "\n-----\n"); FileDirectoryListing fd_cd050419; fd_cd050419.readFromFile("ls/cd050419"); allListings.add(fd_cd050419); fprintf(stdout, "\n-----\n"); FileDirectoryListing fd_cd050807; fd_cd050807.readFromFile("ls/cd050807"); fd_cd050807.verifyWith("contents/cd20050807a"); fd_cd050807.verifyWith("contents/cd20050807b"); fd_cd050807.markNotVerified(); allListings.add(fd_cd050807); fprintf(stdout, "\n-----\n"); FileDirectoryListing fd_cd051112; fd_cd051112.readFromFile("ls/cd051112"); allListings.add(fd_cd051112); fprintf(stdout, "\n-----\n"); FileDirectoryListing fd_floppies; fd_floppies.readFromFile("ls/floppies"); allListings.add(fd_floppies); fprintf(stdout, "\n-----\n"); FileDirectoryListing fd_freecom_ester; fd_freecom_ester.readFromFile("ls/freecom_ester"); allListings.add(fd_freecom_ester); fprintf(stdout, "\n-----\n"); FileDirectoryListing fd_freecom_temp; fd_freecom_temp.readFromFile("ls/freecom_temp"); allListings.add(fd_freecom_temp); fprintf(stdout, "\n-----\n"); FileDirectoryListing fd_cd060129; fd_cd060129.readFromFile("ls/cd060129"); fd_cd060129.verifyWith("contents/cd20060129a"); fd_cd060129.verifyWith("contents/cd20060129b"); fd_cd060129.markNotVerified(); allListings.add(fd_cd060129); fprintf(stdout, "\n-----\n"); FileDirectoryListing fd_ester; fd_ester.readFromFile("ls/ester"); allListings.add(fd_ester); fprintf(stdout, "\n-----\n"); FileDirectoryListing fd_lacie; fd_lacie.readFromFile("ls/lacie"); allListings.add(fd_lacie); fprintf(stdout, "\n-----\n"); FileDirectoryListing fd_freecom_g; fd_freecom_g.readFromFile("ls/freecom_g"); allListings.add(fd_freecom_g); fprintf(stdout, "\n-----\n"); FileDirectoryListing fd_c_g; fd_c_g.readFromFile("ls/c_g"); allListings.add(fd_c_g); fprintf(stdout, "\n-----\n"); FileDirectoryListing fd_c_temp_stick; fd_c_temp_stick.readFromFile("ls/c_temp_stick"); allListings.add(fd_c_temp_stick); fprintf(stdout, "\n-----\n"); FileDirectoryListing fd_c_temp_ester; fd_c_temp_ester.readFromFile("ls/c_temp_ester"); allListings.add(fd_c_temp_ester); fprintf(stdout, "\n\n\n-----\n"); llword total_unique_files = 0; llword total_size_unique = 0; llword total_size = 0; HashTable hash_table; for (FileDirectoryListings::iterator it(allListings); it.more(); it.next()) { llword nr_first = 0; llword size_first = 0; llword nr_matched = 0; llword size_matched = 0; it.value()->analyze(hash_table, nr_first, size_first, nr_matched, size_matched); fprintf(stdout, "%20s %15lld %15lld %15lld %15lld\n", it.value()->name, nr_first, size_first, nr_matched, size_matched); total_unique_files += nr_first; total_size_unique += size_first; total_size += size_first + size_matched; } fprintf(stdout, "-----\n%lld %lld %lld\nDone", total_unique_files, total_size_unique, total_size); return 0; }