#include #include #include #include #include #include #include #include #include #include #include using namespace std; class my_exception : public exception { private: string cause; public: my_exception(const string& cause) : cause(cause) { } virtual const char* what() const { return cause.c_str(); } }; class paq_builder { private: struct index_entry { index_entry(const string& file_name, bool is_dir) : file_name(file_name), is_dir(is_dir) { } string file_name; bool is_dir; }; list index; list > files; void process(string path) { boost::filesystem::directory_iterator end; for (boost::filesystem::directory_iterator itr(path.c_str()); itr != end ; ++itr) { index.push_back(index_entry(itr->filename(), boost::filesystem::is_directory(itr->status()))); if (index.back().is_dir) process(path + "/" + itr->filename()); else { ifstream in(itr->string().c_str(), ios::binary); if (!in) throw my_exception(string("Can't open ") + itr->string()); vector v(4); *reinterpret_cast(&v[0]) = boost::filesystem::file_size(itr->path()); boost::iostreams::filtering_streambuf out; out.push(boost::iostreams::gzip_compressor()); out.push(boost::iostreams::back_inserter(v)); boost::iostreams::copy(in, out); files.push_back(v); } } index.push_back(index_entry(string(""), 0)); } public: paq_builder(const char* path) { if (!boost::filesystem::exists(path) || !boost::filesystem::is_directory(path)) throw my_exception(string(path) + " doesn't exist or isn't a directory!"); process(string(path)); } void write_to_file(const char* path) { ofstream paq(path, ios::binary); if (!paq) throw my_exception(string("Can't open ") + path); paq.write("NPAQ", 4); list >::iterator f_it = files.begin(); for (list::iterator i_it = index.begin(); i_it != index.end(); i_it++) { paq << static_cast(i_it->file_name.size()); if (i_it->file_name.size()) { paq.write(i_it->file_name.c_str(), i_it->file_name.size()); unsigned int file_size = i_it->is_dir ? 0 : f_it++->size(); paq.write(reinterpret_cast(&file_size), 4); paq << static_cast(file_size ? 0 : 1); } } for(f_it = files.begin(); f_it != files.end(); f_it++) paq.write(&(*f_it)[0], f_it->size()); } }; int main(int argc, char** argv) { if (argc < 3) { cout << "Usage: " << argv[0] << " " << endl; return 0; } try { paq_builder(argv[1]).write_to_file(argv[2]); } catch (const exception& e) { cerr << e.what() << endl; return -1; } return 0; }