Skip to content

Instantly share code, notes, and snippets.

@retep998
Created August 26, 2011 22:56
Show Gist options
  • Save retep998/1174642 to your computer and use it in GitHub Desktop.
Save retep998/1174642 to your computer and use it in GitHub Desktop.
Backup system
#include <boost/filesystem.hpp>
#include <boost/lexical_cast.hpp>
using namespace boost::filesystem;
using boost::lexical_cast;
//std
#include <iostream>
#include <string>
#include <fstream>
#include <map>
using namespace std;
#define FAIL exit(273);
int main(int argc, char* argv[]) {
if (argc<3) {
FAIL
}
string command = argv[1];
path p = argv[2];
auto strip = [&](path pp) -> path {
path result;
for (auto it1 = pp.begin(), it2 = p.begin(); it1 != pp.end(); it1++) {
if (it2 != p.end()) {
it2++;
} else {
result /= *it1;
}
}
return result;
};
if (command == "backup") {
cout << "Backing up your shit" << endl;
time_t curtime = time(0);
string timestr = lexical_cast <string> (curtime);
path info = p;
info /= "info.dat";
file_status stat = status(info);
file_type t = stat.type();
map <string, pair <time_t, time_t>> last;
if (t == regular_file) {
ifstream file(info.string());
while (!file.eof()) {
time_t back;
time_t mod;
file >> back >> mod;
char s[1024];
file.getline(s, 1024);
last[string(s).substr(1)].first = back;
last[string(s).substr(1)].second = mod;
}
file.close();
} else if (t = file_not_found) {
//Ignore
} else {
FAIL
}
create_directory(p/"backup");
create_directory(p/"backup"/timestr);
function <void(path)> recurse = [&](path pp) {
for (directory_iterator it(pp); it != directory_iterator(); it++) {
if (is_directory(it->path())) {
if (it->path().filename() == "backup") {
//Ignore
} else {
path fun = strip(it->path());
create_directory(p/"backup"/timestr/fun);
recurse(it->path());
}
} else if (is_regular_file(it->path())) {
if (it->path().filename() == "info.dat") {
//Ignore
} else {
time_t mod = last_write_time(it->path());
path fun = strip(it->path());
if (mod != last[fun.string()].second) {
cout << "Adding: " << fun << endl;
last[fun.string()].first = curtime;
last[fun.string()].second = mod;
copy_file(p/fun, p/"backup"/timestr/fun);
}
}
} else {
//Ignore
}
}
};
for (auto it = last.begin(); it != last.end();) {
if (!is_regular_file(p/it->first)) {
cout << "Removing: " << it->first << endl;
last.erase(it++);
} else {
it++;
}
}
recurse(p);
ofstream file(info.string());
for (auto it = last.begin(); it != last.end(); it++) {
if (it != last.begin()) {
file << endl;
}
file << it->second.first << " " << it->second.second << " " << it->first;
}
file.close();
copy_file(p/"info.dat", p/"backup"/timestr/"info.dat");
} else if (command == "restore") {
if (argc<4) {
FAIL
}
cout << "Restoring your shit" << endl;
string version = argv[3];
map <string, pair <time_t, time_t>> last;
ifstream file((p/"backup"/version/"info.dat").string());
while (!file.eof()) {
time_t back;
time_t mod;
file >> back >> mod;
char s[1024];
file.getline(s, 1024);
last[string(s).substr(1)].first = back;
last[string(s).substr(1)].second = mod;
}
file.close();
function <void(path)> recurse = [&](path pp) {
for (directory_iterator it(pp); it != directory_iterator(); it++) {
if (is_directory(it->path())) {
if (it->path().filename() == "backup") {
//Ignore
} else {
recurse(it->path());
}
} else if (is_regular_file(it->path())) {
if (it->path().filename() == "info.dat") {
} else {
time_t mod = last_write_time(it->path());
path fun = strip(it->path());
if (last.find(fun.string()) == last.end()) {
cout << "Erasing: " << fun << endl;
if (exists(it->path())) {
remove(it->path());
}
} else if (mod != last[fun.string()].second) {
cout << "Restoring: " << fun << endl;
copy_file(p/"backup"/lexical_cast<string>(last[fun.string()].first)/fun, p/fun, copy_option::overwrite_if_exists);
last.erase(fun.string());
}
}
} else {
//Ignore
}
}
};
recurse(p);
for (auto it = last.begin(); it != last.end(); it++) {
function <void(path)> verify = [&](path pp) {
if (exists(pp)) {
return;
} else {
verify(pp.parent_path());
create_directory(pp);
}
};
verify(p/"backup"/lexical_cast<string>(it->second.first)/it->first);
copy_file(p/"backup"/lexical_cast<string>(it->second.first)/it->first, p/it->first, copy_option::overwrite_if_exists);
cout << "Restoring: " << it->first << endl;
}
copy_file(p/"backup"/version/"info.dat", p/"info.dat", copy_option::overwrite_if_exists);
} else {
FAIL
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment