From 1048a6510710acb5bef352d0acb2dd13ecce0e01 Mon Sep 17 00:00:00 2001 From: Michael Vrable Date: Thu, 9 Aug 2007 20:36:51 -0700 Subject: [PATCH] Write out a .sha1sums file with checksums for segments in this snapshot. Some segments might be left out; we only write out lines for those segments that we know a checksum for. These checksums are stored in the local database (so we can find checksums for old segments), but entries might be missing. --- localdb.cc | 40 ++++++++++++++++++++++++++++++++++++++++ localdb.h | 2 ++ scandir.cc | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+) diff --git a/localdb.cc b/localdb.cc index 8a5e1f1..e946d18 100644 --- a/localdb.cc +++ b/localdb.cc @@ -325,3 +325,43 @@ void LocalDb::SetSegmentChecksum(const std::string &segment, sqlite3_finalize(stmt); } + +bool LocalDb::GetSegmentChecksum(const string &segment, + string *seg_path, + string *seg_checksum) +{ + int rc; + sqlite3_stmt *stmt; + ObjectReference ref; + int found = false; + + stmt = Prepare("select path, checksum from segments where segment = ?"); + sqlite3_bind_text(stmt, 1, segment.c_str(), segment.size(), + SQLITE_TRANSIENT); + + rc = sqlite3_step(stmt); + if (rc == SQLITE_DONE) { + } else if (rc == SQLITE_ROW) { + found = true; + const char *val; + + val = (const char *)sqlite3_column_text(stmt, 0); + if (val == NULL) + found = false; + else + *seg_path = val; + + val = (const char *)sqlite3_column_text(stmt, 1); + if (val == NULL) + found = false; + else + *seg_checksum = val; + } else { + fprintf(stderr, "Could not execute SELECT statement!\n"); + ReportError(rc); + } + + sqlite3_finalize(stmt); + + return found; +} diff --git a/localdb.h b/localdb.h index e8a350e..6d28cd8 100644 --- a/localdb.h +++ b/localdb.h @@ -33,6 +33,8 @@ public: void SetSegmentChecksum(const std::string &segment, const std::string &path, const std::string &checksum); + bool GetSegmentChecksum(const std::string &segment, + std::string *seg_path, std::string *seg_checksum); private: sqlite3 *db; int64_t snapshotid; diff --git a/scandir.cc b/scandir.cc index 82160a1..9075e51 100644 --- a/scandir.cc +++ b/scandir.cc @@ -723,6 +723,40 @@ int main(int argc, char *argv[]) tss->dump_stats(); delete tss; + /* Write out a checksums file which lists the checksums for all the + * segments included in this snapshot. The format is designed so that it + * may be easily verified using the sha1sums command. */ + const char csum_type[] = "sha1"; + string checksum_filename = backup_dest + "/snapshot-"; + if (backup_scheme.size() > 0) + checksum_filename += backup_scheme + "-"; + checksum_filename = checksum_filename + desc_buf + "." + csum_type + "sums"; + FILE *checksums = fopen(checksum_filename.c_str(), "w"); + if (checksums != NULL) { + for (std::set::iterator i = segment_list.begin(); + i != segment_list.end(); ++i) { + string seg_path, seg_csum; + if (db->GetSegmentChecksum(*i, &seg_path, &seg_csum)) { + const char *raw_checksum = NULL; + if (strncmp(seg_csum.c_str(), csum_type, + strlen(csum_type)) == 0) { + raw_checksum = seg_csum.c_str() + strlen(csum_type); + if (*raw_checksum == '=') + raw_checksum++; + else + raw_checksum = NULL; + } + + if (raw_checksum != NULL) + fprintf(checksums, "%s *%s\n", + raw_checksum, seg_path.c_str()); + } + } + fclose(checksums); + } else { + fprintf(stderr, "ERROR: Unable to write checksums file: %m\n"); + } + db->Close(); /* Write a backup descriptor file, which says which segments are needed and @@ -742,6 +776,11 @@ int main(int argc, char *argv[]) descriptor << "Scheme: " << backup_scheme << "\n"; descriptor << "Root: " << backup_root << "\n"; + SHA1Checksum checksum_csum; + if (checksum_csum.process_file(checksum_filename.c_str())) { + descriptor << "Checksum-File: " << checksum_csum.checksum_str() << "\n"; + } + descriptor << "Segments:\n"; for (std::set::iterator i = segment_list.begin(); i != segment_list.end(); ++i) { -- 2.20.1