X-Git-Url: http://git.vrable.net/?p=cumulus.git;a=blobdiff_plain;f=scandir.cc;h=8af3175b64c3b6007a5497f4c4ac8d81e5d9ff7c;hp=a2a7a4996be46f3c20e6b83934f8a78cda2c0722;hb=f38dd9bcb0caffd3fc9126b05788c936690e8288;hpb=260aaf269765b6fdf0c74ec51615e38a70b27fa3 diff --git a/scandir.cc b/scandir.cc index a2a7a49..8af3175 100644 --- a/scandir.cc +++ b/scandir.cc @@ -90,12 +90,15 @@ double snapshot_intent = 1.0; /* Selection of files to include/exclude in the snapshot. */ std::list includes; // Paths in which files should be saved std::list excludes; // Paths which will not be saved +std::list excluded_names; // Directories which will not be saved std::list searches; // Directories we don't want to save, but // do want to descend searching for data // in included paths bool relative_paths = true; +bool flag_rebuild_statcache = false; + /* Whether verbose output is enabled. */ bool verbose = false; @@ -154,7 +157,9 @@ int64_t dumpfile(int fd, dictionary &file_info, const string &path, if (found) old_blocks = metawriter->get_blocks(); - if (found && metawriter->is_unchanged(&stat_buf)) { + if (found + && !flag_rebuild_statcache + && metawriter->is_unchanged(&stat_buf)) { cached = true; /* If any of the blocks in the object have been expired, then we should @@ -266,6 +271,10 @@ int64_t dumpfile(int fd, dictionary &file_info, const string &path, subfile.analyze_new_block(block_buf, bytes); refs = subfile.create_incremental(tss, o, block_age); } else { + if (flag_rebuild_statcache && ref.is_normal()) { + subfile.analyze_new_block(block_buf, bytes); + subfile.store_analyzed_signatures(ref); + } refs.push_back(ref); } @@ -285,6 +294,24 @@ int64_t dumpfile(int fd, dictionary &file_info, const string &path, file_info["checksum"] = hash.checksum_str(); } + // Sanity check: if we are rebuilding the statcache, but the file looks + // like it hasn't changed, then the newly-computed checksum should match + // the checksum in the statcache. If not, we have possible disk corruption + // and report a warning. + if (flag_rebuild_statcache) { + if (found + && metawriter->is_unchanged(&stat_buf) + && file_info["checksum"] != metawriter->get_checksum()) { + fprintf(stderr, + "Warning: Checksum for %s does not match expected value\n" + " expected: %s\n" + " actual: %s\n", + path.c_str(), + metawriter->get_checksum().c_str(), + file_info["checksum"].c_str()); + } + } + if (verbose && status != NULL) printf(" [%s]\n", status); @@ -330,12 +357,12 @@ void dump_inode(const string& path, // Path within snapshot file_info["volatile"] = "1"; struct passwd *pwd = getpwuid(stat_buf.st_uid); - if (pwd != NULL) { + if (pwd != NULL && pwd->pw_name != NULL) { file_info["user"] += " (" + uri_encode(pwd->pw_name) + ")"; } struct group *grp = getgrgid(stat_buf.st_gid); - if (pwd != NULL) { + if (grp != NULL && grp->gr_name != NULL) { file_info["group"] += " (" + uri_encode(grp->gr_name) + ")"; } @@ -444,6 +471,21 @@ void scanfile(const string& path, bool include) } } + if (excluded_names.size() > 0) { + std::string name = path; + std::string::size_type last_slash = name.rfind('/'); + if (last_slash != std::string::npos) { + name.replace(0, last_slash + 1, ""); + } + + for (list::iterator i = excluded_names.begin(); + i != excluded_names.end(); ++i) { + if (name == *i) { + include = false; + } + } + } + for (list::iterator i = searches.begin(); i != searches.end(); ++i) { if (path == *i) { @@ -594,6 +636,7 @@ void usage(const char *program) " --upload-script=COMMAND\n" " program to invoke for each backup file generated\n" " --exclude=PATH exclude files in PATH from snapshot\n" + " --exclude-name=NAME exclude files called NAME from snapshot\n" " --localdb=PATH local backup metadata is stored in PATH\n" " --tmpdir=PATH path for temporarily storing backup files\n" " (defaults to TMPDIR environment variable or /tmp)\n" @@ -608,6 +651,7 @@ void usage(const char *program) " --intent=FLOAT intended backup type: 1=daily, 7=weekly, ...\n" " (defaults to \"1\")\n" " --full-metadata do not re-use metadata from previous backups\n" + " --rebuild-statcache re-read all file data to verify statcache\n" " -v --verbose list files as they are backed up\n" "\n" "Exactly one of --dest or --upload-script must be specified.\n", @@ -639,6 +683,8 @@ int main(int argc, char *argv[]) {"full-metadata", 0, 0, 0}, // 8 {"tmpdir", 1, 0, 0}, // 9 {"upload-script", 1, 0, 0}, // 10 + {"rebuild-statcache", 0, 0, 0}, // 11 + {"exclude-name", 1, 0, 0}, // 12 // Aliases for short options {"verbose", 0, 0, 'v'}, {NULL, 0, 0, 0}, @@ -690,6 +736,12 @@ int main(int argc, char *argv[]) case 10: // --upload-script backup_script = optarg; break; + case 11: // --rebuild-statcache + flag_rebuild_statcache = true; + break; + case 12: // --exclude-name + excluded_names.push_back(optarg); + break; default: fprintf(stderr, "Unhandled long option!\n"); return 1; @@ -752,8 +804,7 @@ int main(int argc, char *argv[]) tmp_dir.c_str()); return 1; } - remote = new RemoteStore(tmp_dir); - remote->set_script(backup_script); + remote = new RemoteStore(tmp_dir, backup_script=backup_script); } else { remote = new RemoteStore(backup_dest); } @@ -894,7 +945,7 @@ int main(int argc, char *argv[]) waitpid(signature_pid, &status, 0); if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { - throw IOException("Signature filter process error"); + fatal("Signature filter process error"); } }