1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <list>
#include <exception>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include <boost/iostreams/copy.hpp>
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_entry> index;
list<vector<char> > 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<char> v(4);
*reinterpret_cast<unsigned int*>(&v[0]) = boost::filesystem::file_size(itr->path());
boost::iostreams::filtering_streambuf<boost::iostreams::output> 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<vector<char> >::iterator f_it = files.begin();
for (list<index_entry>::iterator i_it = index.begin(); i_it != index.end(); i_it++)
{
paq << static_cast<char>(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<char*>(&file_size), 4);
paq << static_cast<char>(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] << " <in-directory> <out-paq>" << 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;
}
|