From aaead201642faec52df1424d8ab3fcc21a69224f Mon Sep 17 00:00:00 2001 From: Joe Onorato Date: Tue, 5 May 2009 11:50:51 -0700 Subject: [PATCH] Add some C++ code to do raw files for backup --- include/utils/backup_helpers.h | 15 + libs/utils/Android.mk | 3 +- libs/utils/file_backup_helper.cpp | 680 ++++++++++++++++++++++++++++++ 3 files changed, 697 insertions(+), 1 deletion(-) create mode 100644 include/utils/backup_helpers.h create mode 100644 libs/utils/file_backup_helper.cpp diff --git a/include/utils/backup_helpers.h b/include/utils/backup_helpers.h new file mode 100644 index 000000000..f70444df6 --- /dev/null +++ b/include/utils/backup_helpers.h @@ -0,0 +1,15 @@ +#ifndef _UTILS_BACKUP_HELPERS_H +#define _UTILS_BACKUP_HELPERS_H + +int back_up_files(int oldSnapshotFD, int newSnapshotFD, int oldDataStream, + char const* fileBase, char const* const* files, int fileCount); + +#define TEST_BACKUP_HELPERS 1 + +#if TEST_BACKUP_HELPERS +int backup_helper_test_empty(); +int backup_helper_test_four(); +int backup_helper_test_files(); +#endif + +#endif // _UTILS_BACKUP_HELPERS_H diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk index cdb8ca2d7..f9fb78038 100644 --- a/libs/utils/Android.mk +++ b/libs/utils/Android.mk @@ -116,7 +116,8 @@ LOCAL_SRC_FILES:= \ ProcessState.cpp \ IPermissionController.cpp \ IServiceManager.cpp \ - Unicode.cpp + Unicode.cpp \ + file_backup_helper.cpp ifeq ($(TARGET_SIMULATOR),true) LOCAL_SRC_FILES += $(hostSources) diff --git a/libs/utils/file_backup_helper.cpp b/libs/utils/file_backup_helper.cpp new file mode 100644 index 000000000..16cbb6ec4 --- /dev/null +++ b/libs/utils/file_backup_helper.cpp @@ -0,0 +1,680 @@ +#define LOG_TAG "file_backup_helper" + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace android; + +#define MAGIC0 0x70616e53 // Snap +#define MAGIC1 0x656c6946 // File + +struct SnapshotHeader { + int magic0; + int fileCount; + int magic1; + int totalSize; +}; + +struct FileState { + int modTime_sec; + int modTime_nsec; + int size; + int crc32; + int nameLen; +}; + +const static int ROUND_UP[4] = { 0, 3, 2, 1 }; + +static inline int +round_up(int n) +{ + return n + ROUND_UP[n % 4]; +} + +static int +read_snapshot_file(int fd, KeyedVector* snapshot) +{ + int bytesRead = 0; + int amt; + SnapshotHeader header; + + amt = read(fd, &header, sizeof(header)); + if (amt != sizeof(header)) { + return errno; + } + bytesRead += amt; + + if (header.magic0 != MAGIC0 || header.magic1 != MAGIC1) { + LOGW("read_snapshot_file header.magic0=0x%08x magic1=0x%08x", header.magic0, header.magic1); + return 1; + } + + for (int i=0; iadd(String8(filename, file.nameLen), file); + } + bytesRead += amt; + if (filename != filenameBuf) { + free(filename); + } + if (amt != nameBufSize) { + LOGW("read_snapshot_file filename truncated/error with read at %d bytes\n", bytesRead); + return 1; + } + } + + if (header.totalSize != bytesRead) { + LOGW("read_snapshot_file length mismatch: header.totalSize=%d bytesRead=%d\n", + header.totalSize, bytesRead); + return 1; + } + + return 0; +} + +static int +write_snapshot_file(int fd, const KeyedVector& snapshot) +{ + int bytesWritten = sizeof(SnapshotHeader); + // preflight size + const int N = snapshot.size(); + for (int i=0; i oldSnapshot; + KeyedVector newSnapshot; + + if (oldSnapshotFD != -1) { + err = read_snapshot_file(oldSnapshotFD, &oldSnapshot); + if (err != 0) { + // On an error, treat this as a full backup. + oldSnapshot.clear(); + } + } + + for (int i=0; i 0) { + // file added + String8 realFilename(base); + realFilename.appendPath(q); + write_update_file(realFilename, q); + m++; + } + else if (cmp < 0) { + // file removed + write_delete_file(p); + n++; + } + else { + // both files exist, check them + String8 realFilename(base); + realFilename.appendPath(q); + const FileState& f = oldSnapshot.valueAt(n); + const FileState& g = newSnapshot.valueAt(m); + + printf("%s\n", q.string()); + printf(" new: modTime=%d,%d size=%-3d crc32=0x%08x\n", + f.modTime_sec, f.modTime_nsec, f.size, f.crc32); + printf(" old: modTime=%d,%d size=%-3d crc32=0x%08x\n", + g.modTime_sec, g.modTime_nsec, g.size, g.crc32); + if (f.modTime_sec != g.modTime_sec || f.modTime_nsec != g.modTime_nsec + || f.size != g.size || f.crc32 != g.crc32) { + write_update_file(realFilename, p); + } + n++; + m++; + } + } + + // these were deleted + while (n snapshot; + const char* filename = SCRATCH_DIR "backup_helper_test_empty.snap"; + + system("rm -r " SCRATCH_DIR); + mkdir(SCRATCH_DIR, 0777); + + // write + fd = creat(filename, 0666); + if (fd == -1) { + fprintf(stderr, "error creating %s\n", filename); + return 1; + } + + err = write_snapshot_file(fd, snapshot); + + close(fd); + + if (err != 0) { + fprintf(stderr, "write_snapshot_file reported error %d (%s)\n", err, strerror(err)); + return err; + } + + static const unsigned char correct_data[] = { + 0x53, 0x6e, 0x61, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x46, 0x69, 0x6c, 0x65, 0x10, 0x00, 0x00, 0x00 + }; + + err = compare_file(filename, correct_data, sizeof(correct_data)); + if (err != 0) { + return err; + } + + // read + fd = open(filename, O_RDONLY); + if (fd == -1) { + fprintf(stderr, "error opening for read %s\n", filename); + return 1; + } + + KeyedVector readSnapshot; + err = read_snapshot_file(fd, &readSnapshot); + if (err != 0) { + fprintf(stderr, "read_snapshot_file failed %d\n", err); + return err; + } + + if (readSnapshot.size() != 0) { + fprintf(stderr, "readSnapshot should be length 0\n"); + return 1; + } + + return 0; +} + +int +backup_helper_test_four() +{ + int err; + int fd; + KeyedVector snapshot; + const char* filename = SCRATCH_DIR "backup_helper_test_four.snap"; + + system("rm -r " SCRATCH_DIR); + mkdir(SCRATCH_DIR, 0777); + + // write + fd = creat(filename, 0666); + if (fd == -1) { + fprintf(stderr, "error opening %s\n", filename); + return 1; + } + + String8 filenames[4]; + FileState states[4]; + + states[0].modTime_sec = 0xfedcba98; + states[0].modTime_nsec = 0xdeadbeef; + states[0].size = 0xababbcbc; + states[0].crc32 = 0x12345678; + states[0].nameLen = -12; + filenames[0] = String8("bytes_of_padding"); + snapshot.add(filenames[0], states[0]); + + states[1].modTime_sec = 0x93400031; + states[1].modTime_nsec = 0xdeadbeef; + states[1].size = 0x88557766; + states[1].crc32 = 0x22334422; + states[1].nameLen = -1; + filenames[1] = String8("bytes_of_padding3"); + snapshot.add(filenames[1], states[1]); + + states[2].modTime_sec = 0x33221144; + states[2].modTime_nsec = 0xdeadbeef; + states[2].size = 0x11223344; + states[2].crc32 = 0x01122334; + states[2].nameLen = 0; + filenames[2] = String8("bytes_of_padding_2"); + snapshot.add(filenames[2], states[2]); + + states[3].modTime_sec = 0x33221144; + states[3].modTime_nsec = 0xdeadbeef; + states[3].size = 0x11223344; + states[3].crc32 = 0x01122334; + states[3].nameLen = 0; + filenames[3] = String8("bytes_of_padding__1"); + snapshot.add(filenames[3], states[3]); + + err = write_snapshot_file(fd, snapshot); + + close(fd); + + if (err != 0) { + fprintf(stderr, "write_snapshot_file reported error %d (%s)\n", err, strerror(err)); + return err; + } + + static const unsigned char correct_data[] = { + // header + 0x53, 0x6e, 0x61, 0x70, 0x04, 0x00, 0x00, 0x00, + 0x46, 0x69, 0x6c, 0x65, 0xac, 0x00, 0x00, 0x00, + + // bytes_of_padding + 0x98, 0xba, 0xdc, 0xfe, 0xef, 0xbe, 0xad, 0xde, + 0xbc, 0xbc, 0xab, 0xab, 0x78, 0x56, 0x34, 0x12, + 0x10, 0x00, 0x00, 0x00, 0x62, 0x79, 0x74, 0x65, + 0x73, 0x5f, 0x6f, 0x66, 0x5f, 0x70, 0x61, 0x64, + 0x64, 0x69, 0x6e, 0x67, + + // bytes_of_padding3 + 0x31, 0x00, 0x40, 0x93, 0xef, 0xbe, 0xad, 0xde, + 0x66, 0x77, 0x55, 0x88, 0x22, 0x44, 0x33, 0x22, + 0x11, 0x00, 0x00, 0x00, 0x62, 0x79, 0x74, 0x65, + 0x73, 0x5f, 0x6f, 0x66, 0x5f, 0x70, 0x61, 0x64, + 0x64, 0x69, 0x6e, 0x67, 0x33, 0xab, 0xab, 0xab, + + // bytes of padding2 + 0x44, 0x11, 0x22, 0x33, 0xef, 0xbe, 0xad, 0xde, + 0x44, 0x33, 0x22, 0x11, 0x34, 0x23, 0x12, 0x01, + 0x12, 0x00, 0x00, 0x00, 0x62, 0x79, 0x74, 0x65, + 0x73, 0x5f, 0x6f, 0x66, 0x5f, 0x70, 0x61, 0x64, + 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x32, 0xab, 0xab, + + // bytes of padding3 + 0x44, 0x11, 0x22, 0x33, 0xef, 0xbe, 0xad, 0xde, + 0x44, 0x33, 0x22, 0x11, 0x34, 0x23, 0x12, 0x01, + 0x13, 0x00, 0x00, 0x00, 0x62, 0x79, 0x74, 0x65, + 0x73, 0x5f, 0x6f, 0x66, 0x5f, 0x70, 0x61, 0x64, + 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x5f, 0x31, 0xab + }; + + err = compare_file(filename, correct_data, sizeof(correct_data)); + if (err != 0) { + return err; + } + + // read + fd = open(filename, O_RDONLY); + if (fd == -1) { + fprintf(stderr, "error opening for read %s\n", filename); + return 1; + } + + + KeyedVector readSnapshot; + err = read_snapshot_file(fd, &readSnapshot); + if (err != 0) { + fprintf(stderr, "read_snapshot_file failed %d\n", err); + return err; + } + + if (readSnapshot.size() != 4) { + fprintf(stderr, "readSnapshot should be length 4 is %d\n", readSnapshot.size()); + return 1; + } + + bool matched = true; + for (size_t i=0; i