From 4535e40544aeb957d44fad75fbe5676effe03689 Mon Sep 17 00:00:00 2001 From: Joe Onorato Date: Fri, 15 May 2009 09:07:06 -0400 Subject: Implement the C++ class to write the backed up file data. --- include/utils/ByteOrder.h | 32 +- include/utils/backup_helpers.h | 54 +++ libs/utils/Android.mk | 3 +- libs/utils/backup_data.cpp | 236 +++++++++++ libs/utils/backup_helper_file.cpp | 826 ++++++++++++++++++++++++++++++++++++ libs/utils/file_backup_helper.cpp | 685 ------------------------------ tests/backup/backup_helper_test.cpp | 3 + 7 files changed, 1143 insertions(+), 696 deletions(-) create mode 100644 libs/utils/backup_data.cpp create mode 100644 libs/utils/backup_helper_file.cpp delete mode 100644 libs/utils/file_backup_helper.cpp diff --git a/include/utils/ByteOrder.h b/include/utils/ByteOrder.h index 4c0606763d6f..baa3a83dddfc 100644 --- a/include/utils/ByteOrder.h +++ b/include/utils/ByteOrder.h @@ -38,6 +38,16 @@ * intent is to allow us to avoid byte swapping on the device. */ +static inline uint32_t android_swap_long(uint32_t v) +{ + return (v<<24) | ((v<<8)&0x00FF0000) | ((v>>8)&0x0000FF00) | (v>>24); +} + +static inline uint16_t android_swap_short(uint16_t v) +{ + return (v<<8) | (v>>8); +} + #define DEVICE_BYTE_ORDER LITTLE_ENDIAN #if BYTE_ORDER == DEVICE_BYTE_ORDER @@ -49,16 +59,6 @@ #else -static inline uint32_t android_swap_long(uint32_t v) -{ - return (v<<24) | ((v<<8)&0x00FF0000) | ((v>>8)&0x0000FF00) | (v>>24); -} - -static inline uint16_t android_swap_short(uint16_t v) -{ - return (v<<8) | (v>>8); -} - #define dtohl(x) (android_swap_long(x)) #define dtohs(x) (android_swap_short(x)) #define htodl(x) (android_swap_long(x)) @@ -66,4 +66,16 @@ static inline uint16_t android_swap_short(uint16_t v) #endif +#if BYTE_ORDER == LITTLE_ENDIAN +#define fromlel(x) (x) +#define fromles(x) (x) +#define tolel(x) (x) +#define toles(x) (x) +#else +#define fromlel(x) (android_swap_long(x)) +#define fromles(x) (android_swap_short(x)) +#define tolel(x) (android_swap_long(x)) +#define toles(x) (android_swap_short(x)) +#endif + #endif // _LIBS_UTILS_BYTE_ORDER_H diff --git a/include/utils/backup_helpers.h b/include/utils/backup_helpers.h index 137c5f104172..73b9989126c0 100644 --- a/include/utils/backup_helpers.h +++ b/include/utils/backup_helpers.h @@ -1,15 +1,69 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifndef _UTILS_BACKUP_HELPERS_H #define _UTILS_BACKUP_HELPERS_H +#include +#include + +namespace android { + int back_up_files(int oldSnapshotFD, int oldDataStream, int newSnapshotFD, char const* fileBase, char const* const* files, int fileCount); +/** + * Reads the data. + * + * If an error occurs, it poisons this object and all write calls will fail + * with the error that occurred. + */ +class BackupDataWriter +{ +public: + BackupDataWriter(int fd); + // does not close fd + ~BackupDataWriter(); + + status_t WriteAppHeader(const String8& packageName); + + status_t WriteEntityHeader(const String8& key, size_t dataSize); + status_t WriteEntityData(const void* data, size_t size); + + status_t WriteAppFooter(); + +private: + explicit BackupDataWriter(); + status_t write_padding_for(int n); + + int m_fd; + status_t m_status; + ssize_t m_pos; + int m_entityCount; +}; + #define TEST_BACKUP_HELPERS 0 #if TEST_BACKUP_HELPERS int backup_helper_test_empty(); int backup_helper_test_four(); int backup_helper_test_files(); +int backup_helper_test_data_writer(); #endif +} // namespace android + #endif // _UTILS_BACKUP_HELPERS_H diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk index f9fb780388bc..5a1a89b46e30 100644 --- a/libs/utils/Android.mk +++ b/libs/utils/Android.mk @@ -117,7 +117,8 @@ LOCAL_SRC_FILES:= \ IPermissionController.cpp \ IServiceManager.cpp \ Unicode.cpp \ - file_backup_helper.cpp + backup_data.cpp \ + backup_helper_file.cpp ifeq ($(TARGET_SIMULATOR),true) LOCAL_SRC_FILES += $(hostSources) diff --git a/libs/utils/backup_data.cpp b/libs/utils/backup_data.cpp new file mode 100644 index 000000000000..c7f1fdb58ee4 --- /dev/null +++ b/libs/utils/backup_data.cpp @@ -0,0 +1,236 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include + +namespace android { + +/* + * File Format (v1): + * + * All ints are stored little-endian. + * + * - An app_header_v1 struct. + * - The name of the package, utf-8, null terminated, padded to 4-byte boundary. + * - A sequence of zero or more key/value paires (entities), each with + * - A entity_header_v1 struct + * - The key, utf-8, null terminated, padded to 4-byte boundary. + * - The value, padded to 4 byte boundary + */ + +#define APP_MAGIC_V1 0x31707041 // App1 (little endian) +#define ENTITY_MAGIC_V1 0x61746144 // Data (little endian) +#define FOOTER_MAGIC_V1 0x746f6f46 // Foot (little endian) + +typedef struct { + int type; // == APP_MAGIC_V1 + int packageLen; // length of the name of the package that follows, not including the null. +} app_header_v1; + +typedef struct { + int type; // ENTITY_MAGIC_V1 + int keyLen; // length of the key name, not including the null terminator + int dataSize; // size of the data, not including the padding +} entity_header_v1; + +typedef struct { + int type; // FOOTER_MAGIC_V1 + int entityCount; // the number of entities that were written +} app_footer_v1; + +const static int ROUND_UP[4] = { 0, 3, 2, 1 }; + +static inline size_t +round_up(size_t n) +{ + return n + ROUND_UP[n % 4]; +} + +static inline size_t +padding_extra(size_t n) +{ + return ROUND_UP[n % 4]; +} + +BackupDataWriter::BackupDataWriter(int fd) + :m_fd(fd), + m_status(NO_ERROR), + m_pos(0), + m_entityCount(0) +{ +} + +BackupDataWriter::~BackupDataWriter() +{ +} + +// Pad out anything they've previously written to the next 4 byte boundary. +status_t +BackupDataWriter::write_padding_for(int n) +{ + ssize_t amt; + ssize_t paddingSize; + + paddingSize = padding_extra(n); + if (paddingSize > 0) { + uint32_t padding = 0xbcbcbcbc; + amt = write(m_fd, &padding, paddingSize); + if (amt != paddingSize) { + m_status = errno; + return m_status; + } + m_pos += amt; + } + return NO_ERROR; +} + +status_t +BackupDataWriter::WriteAppHeader(const String8& packageName) +{ + if (m_status != NO_ERROR) { + return m_status; + } + + ssize_t amt; + + amt = write_padding_for(m_pos); + if (amt != 0) { + return amt; + } + + app_header_v1 header; + ssize_t nameLen; + + nameLen = packageName.length(); + + header.type = tolel(APP_MAGIC_V1); + header.packageLen = tolel(nameLen); + + amt = write(m_fd, &header, sizeof(app_header_v1)); + if (amt != sizeof(app_header_v1)) { + m_status = errno; + return m_status; + } + m_pos += amt; + + amt = write(m_fd, packageName.string(), nameLen+1); + if (amt != nameLen+1) { + m_status = errno; + return m_status; + } + m_pos += amt; + + return NO_ERROR; +} + +status_t +BackupDataWriter::WriteEntityHeader(const String8& key, size_t dataSize) +{ + if (m_status != NO_ERROR) { + return m_status; + } + + ssize_t amt; + + amt = write_padding_for(m_pos); + if (amt != 0) { + return amt; + } + + entity_header_v1 header; + ssize_t keyLen; + + keyLen = key.length(); + + header.type = tolel(ENTITY_MAGIC_V1); + header.keyLen = tolel(keyLen); + header.dataSize = tolel(dataSize); + + amt = write(m_fd, &header, sizeof(entity_header_v1)); + if (amt != sizeof(entity_header_v1)) { + m_status = errno; + return m_status; + } + m_pos += amt; + + amt = write(m_fd, key.string(), keyLen+1); + if (amt != keyLen+1) { + m_status = errno; + return m_status; + } + m_pos += amt; + + amt = write_padding_for(keyLen+1); + + m_entityCount++; + + return amt; +} + +status_t +BackupDataWriter::WriteEntityData(const void* data, size_t size) +{ + if (m_status != NO_ERROR) { + return m_status; + } + + // We don't write padding here, because they're allowed to call this several + // times with smaller buffers. We write it at the end of WriteEntityHeader + // instead. + ssize_t amt = write(m_fd, data, size); + if (amt != (ssize_t)size) { + m_status = errno; + return m_status; + } + m_pos += amt; + return NO_ERROR; +} + +status_t +BackupDataWriter::WriteAppFooter() +{ + if (m_status != NO_ERROR) { + return m_status; + } + + ssize_t amt; + + amt = write_padding_for(m_pos); + if (amt != 0) { + return amt; + } + + app_footer_v1 footer; + ssize_t nameLen; + + footer.type = tolel(FOOTER_MAGIC_V1); + footer.entityCount = tolel(m_entityCount); + + amt = write(m_fd, &footer, sizeof(app_footer_v1)); + if (amt != sizeof(app_footer_v1)) { + m_status = errno; + return m_status; + } + m_pos += amt; + + return NO_ERROR; +} + +} // namespace android diff --git a/libs/utils/backup_helper_file.cpp b/libs/utils/backup_helper_file.cpp new file mode 100644 index 000000000000..1fa6a0f02ae9 --- /dev/null +++ b/libs/utils/backup_helper_file.cpp @@ -0,0 +1,826 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "file_backup_helper" + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace android { + +#define MAGIC0 0x70616e53 // Snap +#define MAGIC1 0x656c6946 // File + +#if TEST_BACKUP_HELPERS +#define LOGP(x...) printf(x) +#else +#define LOGP(x...) LOGD(x) +#endif + +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); + LOGP("file added: %s\n", realFilename.string()); + write_update_file(realFilename, q); + m++; + } + else if (cmp < 0) { + // file removed + LOGP("file removed: %s\n", p.string()); + 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); + + LOGP("%s\n", q.string()); + LOGP(" new: modTime=%d,%d size=%-3d crc32=0x%08x\n", + f.modTime_sec, f.modTime_nsec, f.size, f.crc32); + LOGP(" 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 - -#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 - -#define LOGP(x...) LOGD(x) -//#define LOGP(x...) printf(x) - -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); - - LOGP("%s\n", q.string()); - LOGP(" new: modTime=%d,%d size=%-3d crc32=0x%08x\n", - f.modTime_sec, f.modTime_nsec, f.size, f.crc32); - LOGP(" 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 #include +using namespace android; + #if TEST_BACKUP_HELPERS // ============================================================ @@ -20,6 +22,7 @@ Test TESTS[] = { { "backup_helper_test_empty", backup_helper_test_empty, 0, false }, { "backup_helper_test_four", backup_helper_test_four, 0, false }, { "backup_helper_test_files", backup_helper_test_files, 0, false }, + { "backup_helper_test_data_writer", backup_helper_test_data_writer, 0, false }, { 0, NULL, 0, false} }; -- cgit v1.2.3-59-g8ed1b