#include #include #include #include #include #include #include #include #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef WORDS_BIGENDIAN #define SIGNATURE 0x4e504151 #else #define SIGNATURE 0x5141504e #endif String current_dir; extern "C" int sortdir(const void * d1, const void * d2) { struct stat fstats1, fstats2; String n; n = current_dir + "/" + (**((const dirent **)d1)).d_name; stat(n.to_charp(), &fstats1); n = current_dir + "/" + (**((const dirent **)d2)).d_name; stat(n.to_charp(), &fstats2); if (!((S_ISDIR(fstats1.st_mode) ? 1 : 0) ^ (S_ISDIR(fstats2.st_mode) ? 1 : 0))) { return alphasort(d1, d2); } else { if (S_ISDIR(fstats1.st_mode)) return -1; else return 1; } } CODE_BEGINS private: struct couple { String p, v; }; Output * Archive; std::list filelist; void finalize(void) { int size; Input * file; for (std::list::iterator i = filelist.begin(); i != filelist.end(); i++) { cerr << "Finalize file " << *i << endl; file = new Input(*i); size = file->GetSize(); Archive->write(&size, 4); delete file; file = new Input(*i + ".gz"); copy(file, Archive); delete file; unlink((*i + ".gz").to_charp()); } } void process_file(const String & filename) { char t; int size, old_size; cerr << "Processing file " << filename << "... "; Input * from = new Input(filename); Output * to = new Output(filename + ".gz"); to->SetZ(); old_size = from->GetSize(); copy(from, to); delete to; delete from; filelist.push_back(filename); from = new Input(filename + ".gz"); size = from->GetSize() + 4; cerr << old_size << " --> " << from->GetSize() << " (" << 100 * from->GetSize() / old_size << "%)\n"; Archive->write(&size, 4); delete from; t = 0; Archive->write(&t, 1); } void process_directory(const String & dirname) throw (GeneralException) { struct dirent ** namelist; int n, i; char t; struct stat fstats; String fname; current_dir = dirname; n = scandir(dirname.to_charp(), &namelist, NULL, sortdir); cerr << "Processing directory " << dirname << endl; if (n < 0) { throw GeneralException("Unable to open directory " + dirname); } for (i = 0; i < n; i++) { fname = dirname + "/" + namelist[i]->d_name; stat(fname.to_charp(), &fstats); if (S_ISDIR(fstats.st_mode)) { if (!Regex("^\.{1,2}$").Match(namelist[i]->d_name)) { t = strlen(namelist[i]->d_name); Archive->write(&t, 1); Archive->write(namelist[i]->d_name, t); t = 0; Archive->write(&t, 1); Archive->write(&t, 1); Archive->write(&t, 1); Archive->write(&t, 1); t = 1; Archive->write(&t, 1); process_directory(dirname + "/" + namelist[i]->d_name); } } else { if (!Regex("\.gz$").Match(namelist[i]->d_name)) { t = strlen(namelist[i]->d_name); Archive->write(&t, 1); Archive->write(namelist[i]->d_name, t); process_file(dirname + "/" + namelist[i]->d_name); } } free((void *)namelist[i]); } free((void *)namelist); t = 0; Archive->write(&t, 1); } void build_archive(const String & dirname) { char buff[4]; *((int *) buff) = SIGNATURE; Archive->write(buff, 4); process_directory(dirname); finalize(); } public: virtual int startup(void) throw (GeneralException) { Archive = new Output("/tmp/bleh.paq"); build_archive("."); return 0; } CODE_ENDS