Drop the use of exceptions for fatal error handling.
[cumulus.git] / scandir.cc
index a2a7a49..f119197 100644 (file)
@@ -96,6 +96,8 @@ std::list<string> searches;         // Directories we don't want to save, but
 
 bool relative_paths = true;
 
+bool flag_rebuild_statcache = false;
+
 /* Whether verbose output is enabled. */
 bool verbose = false;
 
@@ -154,7 +156,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 +270,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 +293,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);
 
@@ -608,6 +634,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 +666,7 @@ 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
             // Aliases for short options
             {"verbose", 0, 0, 'v'},
             {NULL, 0, 0, 0},
@@ -690,6 +718,9 @@ int main(int argc, char *argv[])
             case 10:    // --upload-script
                 backup_script = optarg;
                 break;
+            case 11:    // --rebuild-statcache
+                flag_rebuild_statcache = true;
+                break;
             default:
                 fprintf(stderr, "Unhandled long option!\n");
                 return 1;
@@ -894,7 +925,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");
         }
     }