{
int64_t size = 0;
list<string> object_list;
+ const char *status = NULL; /* Status indicator printed out */
/* Look up this file in the old stat cache, if we can. If the stat
* information indicates that the file has not changed, do not bother
const ObjectReference &ref = *i;
if (!db->IsAvailable(ref)) {
cached = false;
+ status = "repack";
break;
}
}
/* If the file is new or changed, we must read in the contents a block at a
* time. */
if (!cached) {
- printf(" [new]\n");
-
SHA1Checksum hash;
while (true) {
ssize_t bytes = file_read(fd, block_buf, LBS_BLOCK_SIZE);
* Additionally, keep track of the age of the data by looking
* up the age of the block which was expired and using that
* instead of the current time. */
- if (db->IsOldObject(block_csum, bytes, &block_age))
+ if (db->IsOldObject(block_csum, bytes, &block_age)) {
o->set_group("compacted");
- else
+ if (status == NULL)
+ status = "partial";
+ } else {
o->set_group("data");
+ status = "new";
+ }
o->set_data(block_buf, bytes);
o->write(tss);
segment_list.insert(ref.get_segment());
db->UseObject(ref);
size += bytes;
+
+ if (status == NULL)
+ status = "old";
}
file_info["checksum"] = hash.checksum_str();
}
+ if (status != NULL)
+ printf(" [%s]\n", status);
+
statcache->Save(path, &stat_buf, file_info["checksum"], object_list);
/* For files that only need to be broken apart into a few objects, store
printf("%s\n", path.c_str());
- file_info["mode"] = encode_int(stat_buf.st_mode & 07777);
+ file_info["mode"] = encode_int(stat_buf.st_mode & 07777, 8);
file_info["mtime"] = encode_int(stat_buf.st_mtime);
file_info["user"] = encode_int(stat_buf.st_uid);
file_info["group"] = encode_int(stat_buf.st_gid);
file_info["group"] += " (" + uri_encode(grp->gr_name) + ")";
}
+ if (stat_buf.st_nlink > 1 && (stat_buf.st_mode & S_IFMT) != S_IFDIR) {
+ file_info["links"] = encode_int(stat_buf.st_nlink);
+ file_info["inode"] = encode_int(major(stat_buf.st_dev))
+ + "/" + encode_int(minor(stat_buf.st_dev))
+ + "/" + encode_int(stat_buf.st_ino);
+ }
+
char inode_type;
switch (stat_buf.st_mode & S_IFMT) {
" (defaults to \"bzip2 -c\")\n"
" --filter-extension=EXT\n"
" string to append to segment files\n"
- " (defaults to \".bz2\")\n",
+ " (defaults to \".bz2\")\n"
+ " --scheme=NAME optional name for this snapshot\n",
program
);
}
int main(int argc, char *argv[])
{
- string backup_source = ".";
string backup_dest = "";
string localdb_dir = "";
+ string backup_scheme = "";
while (1) {
static struct option long_options[] = {
{"filter", 1, 0, 0}, // 2
{"filter-extension", 1, 0, 0}, // 3
{"dest", 1, 0, 0}, // 4
+ {"scheme", 1, 0, 0}, // 5
{NULL, 0, 0, 0},
};
case 4: // --dest
backup_dest = optarg;
break;
+ case 5: // --scheme
+ backup_scheme = optarg;
+ break;
default:
fprintf(stderr, "Unhandled long option!\n");
return 1;
}
}
- if (argc < optind + 2) {
+ if (optind == argc) {
usage(argv[0]);
return 1;
}
searches.push_back(".");
- if (optind == argc) {
- add_include(".");
- } else {
- for (int i = optind; i < argc; i++)
- add_include(argv[i]);
- }
-
- backup_source = argv[optind];
+ for (int i = optind; i < argc; i++)
+ add_include(argv[i]);
if (backup_dest == "") {
fprintf(stderr,
* snapshot. */
string database_path = localdb_dir + "/localdb.sqlite";
db = new LocalDb;
- db->Open(database_path.c_str(), desc_buf);
+ db->Open(database_path.c_str(), desc_buf,
+ backup_scheme.size() ? backup_scheme.c_str() : NULL);
/* Initialize the stat cache, for skipping over unchanged files. */
statcache = new StatCache;
- statcache->Open(localdb_dir.c_str(), desc_buf);
+ statcache->Open(localdb_dir.c_str(), desc_buf,
+ backup_scheme.size() ? backup_scheme.c_str() : NULL);
scanfile(".", false);
/* Write a backup descriptor file, which says which segments are needed and
* where to start to restore this snapshot. The filename is based on the
* current time. */
- string desc_filename = backup_dest + "/snapshot-" + desc_buf + ".lbs";
+ string desc_filename = backup_dest + "/snapshot-";
+ if (backup_scheme.size() > 0)
+ desc_filename += backup_scheme + "-";
+ desc_filename = desc_filename + desc_buf + ".lbs";
std::ofstream descriptor(desc_filename.c_str());
- descriptor << "Format: LBS Snapshot v0.1\n";
+ descriptor << "Format: LBS Snapshot v0.2\n";
descriptor << "Producer: LBS " << lbs_version << "\n";
strftime(desc_buf, sizeof(desc_buf), "%Y-%m-%d %H:%M:%S %z", &time_buf);
descriptor << "Date: " << desc_buf << "\n";
+ if (backup_scheme.size() > 0)
+ descriptor << "Scheme: " << backup_scheme << "\n";
descriptor << "Root: " << backup_root << "\n";
descriptor << "Segments:\n";