Loading include/utils/BackupHelpers.h +3 −24 Original line number Original line Diff line number Diff line Loading @@ -23,30 +23,15 @@ namespace android { namespace android { enum { enum { BACKUP_HEADER_APP_V1 = 0x31707041, // App1 (little endian) BACKUP_HEADER_ENTITY_V1 = 0x61746144, // Data (little endian) BACKUP_HEADER_ENTITY_V1 = 0x61746144, // Data (little endian) BACKUP_FOOTER_APP_V1 = 0x746f6f46, // Foot (little endian) }; }; // the sizes of all of these match. typedef struct { int type; // == BACKUP_HEADER_APP_V1 int packageLen; // length of the name of the package that follows, not including the null. int cookie; } app_header_v1; typedef struct { typedef struct { int type; // BACKUP_HEADER_ENTITY_V1 int type; // BACKUP_HEADER_ENTITY_V1 int keyLen; // length of the key name, not including the null terminator int keyLen; // length of the key name, not including the null terminator int dataSize; // size of the data, not including the padding, -1 means delete int dataSize; // size of the data, not including the padding, -1 means delete } entity_header_v1; } entity_header_v1; typedef struct { int type; // BACKUP_FOOTER_APP_V1 int entityCount; // the number of entities that were written int cookie; } app_footer_v1; /** /** * Writes the data. * Writes the data. Loading @@ -61,13 +46,9 @@ public: // does not close fd // does not close fd ~BackupDataWriter(); ~BackupDataWriter(); status_t WriteAppHeader(const String8& packageName, int cookie); status_t WriteEntityHeader(const String8& key, size_t dataSize); status_t WriteEntityHeader(const String8& key, size_t dataSize); status_t WriteEntityData(const void* data, size_t size); status_t WriteEntityData(const void* data, size_t size); status_t WriteAppFooter(int cookie); private: private: explicit BackupDataWriter(); explicit BackupDataWriter(); status_t write_padding_for(int n); status_t write_padding_for(int n); Loading @@ -92,28 +73,26 @@ public: ~BackupDataReader(); ~BackupDataReader(); status_t Status(); status_t Status(); status_t ReadNextHeader(int* type = NULL); status_t ReadNextHeader(bool* done, int* type); status_t ReadAppHeader(String8* packageName, int* cookie); bool HasEntities(); bool HasEntities(); status_t ReadEntityHeader(String8* key, size_t* dataSize); status_t ReadEntityHeader(String8* key, size_t* dataSize); status_t SkipEntityData(); // must be called with the pointer at the begining of the data. status_t SkipEntityData(); // must be called with the pointer at the begining of the data. status_t ReadEntityData(void* data, size_t size); status_t ReadEntityData(void* data, size_t size); status_t ReadAppFooter(int* cookie); private: private: explicit BackupDataReader(); explicit BackupDataReader(); status_t skip_padding(); status_t skip_padding(); int m_fd; int m_fd; bool m_done; status_t m_status; status_t m_status; ssize_t m_pos; ssize_t m_pos; ssize_t m_dataEndPos; int m_entityCount; int m_entityCount; union { union { int type; int type; app_header_v1 app; entity_header_v1 entity; entity_header_v1 entity; app_footer_v1 footer; } m_header; } m_header; }; }; Loading libs/utils/BackupData.cpp +17 −134 Original line number Original line Diff line number Diff line Loading @@ -85,46 +85,6 @@ BackupDataWriter::write_padding_for(int n) return NO_ERROR; return NO_ERROR; } } status_t BackupDataWriter::WriteAppHeader(const String8& packageName, int cookie) { 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(BACKUP_HEADER_APP_V1); header.packageLen = tolel(nameLen); header.cookie = cookie; 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 status_t BackupDataWriter::WriteEntityHeader(const String8& key, size_t dataSize) BackupDataWriter::WriteEntityHeader(const String8& key, size_t dataSize) { { Loading Loading @@ -188,40 +148,11 @@ BackupDataWriter::WriteEntityData(const void* data, size_t size) return NO_ERROR; return NO_ERROR; } } status_t BackupDataWriter::WriteAppFooter(int cookie) { 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(BACKUP_FOOTER_APP_V1); footer.entityCount = tolel(m_entityCount); footer.cookie = cookie; 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; } BackupDataReader::BackupDataReader(int fd) BackupDataReader::BackupDataReader(int fd) :m_fd(fd), :m_fd(fd), m_done(false), m_status(NO_ERROR), m_status(NO_ERROR), m_pos(0), m_pos(0), m_entityCount(0) m_entityCount(0) Loading Loading @@ -260,31 +191,25 @@ BackupDataReader::Status() } while(0) } while(0) status_t status_t BackupDataReader::ReadNextHeader(int* type) BackupDataReader::ReadNextHeader(bool* done, int* type) { { *done = m_done; if (m_status != NO_ERROR) { if (m_status != NO_ERROR) { return m_status; return m_status; } } int amt; int amt; SKIP_PADDING(); // No error checking here, in case we're at the end of the stream. Just let read() fail. skip_padding(); amt = read(m_fd, &m_header, sizeof(m_header)); amt = read(m_fd, &m_header, sizeof(m_header)); *done = m_done = (amt == 0); CHECK_SIZE(amt, sizeof(m_header)); CHECK_SIZE(amt, sizeof(m_header)); // validate and fix up the fields. // validate and fix up the fields. m_header.type = fromlel(m_header.type); m_header.type = fromlel(m_header.type); switch (m_header.type) switch (m_header.type) { { case BACKUP_HEADER_APP_V1: m_header.app.packageLen = fromlel(m_header.app.packageLen); if (m_header.app.packageLen < 0) { LOGD("App header at %d has packageLen<0: 0x%08x\n", (int)m_pos, (int)m_header.app.packageLen); m_status = EINVAL; } m_header.app.cookie = m_header.app.cookie; break; case BACKUP_HEADER_ENTITY_V1: case BACKUP_HEADER_ENTITY_V1: m_header.entity.keyLen = fromlel(m_header.entity.keyLen); m_header.entity.keyLen = fromlel(m_header.entity.keyLen); if (m_header.entity.keyLen <= 0) { if (m_header.entity.keyLen <= 0) { Loading @@ -295,15 +220,6 @@ BackupDataReader::ReadNextHeader(int* type) m_header.entity.dataSize = fromlel(m_header.entity.dataSize); m_header.entity.dataSize = fromlel(m_header.entity.dataSize); m_entityCount++; m_entityCount++; break; break; case BACKUP_FOOTER_APP_V1: m_header.footer.entityCount = fromlel(m_header.footer.entityCount); if (m_header.footer.entityCount < 0) { LOGD("Entity header at %d has entityCount<0: 0x%08x\n", (int)m_pos, (int)m_header.footer.entityCount); m_status = EINVAL; } m_header.footer.cookie = m_header.footer.cookie; break; default: default: LOGD("Chunk header at %d has invalid type: 0x%08x", (int)m_pos, (int)m_header.type); LOGD("Chunk header at %d has invalid type: 0x%08x", (int)m_pos, (int)m_header.type); m_status = EINVAL; m_status = EINVAL; Loading @@ -316,30 +232,6 @@ BackupDataReader::ReadNextHeader(int* type) return m_status; return m_status; } } status_t BackupDataReader::ReadAppHeader(String8* packageName, int* cookie) { if (m_status != NO_ERROR) { return m_status; } if (m_header.type != BACKUP_HEADER_APP_V1) { return EINVAL; } size_t size = m_header.app.packageLen; char* buf = packageName->lockBuffer(size); if (buf == NULL) { packageName->unlockBuffer(); m_status = ENOMEM; return m_status; } int amt = read(m_fd, buf, size+1); CHECK_SIZE(amt, (int)size+1); packageName->unlockBuffer(size); m_pos += size+1; *cookie = m_header.app.cookie; return NO_ERROR; } bool bool BackupDataReader::HasEntities() BackupDataReader::HasEntities() { { Loading Loading @@ -368,6 +260,7 @@ BackupDataReader::ReadEntityHeader(String8* key, size_t* dataSize) m_pos += size+1; m_pos += size+1; *dataSize = m_header.entity.dataSize; *dataSize = m_header.entity.dataSize; SKIP_PADDING(); SKIP_PADDING(); m_dataEndPos = m_pos + *dataSize; return NO_ERROR; return NO_ERROR; } } Loading @@ -381,7 +274,7 @@ BackupDataReader::SkipEntityData() return EINVAL; return EINVAL; } } if (m_header.entity.dataSize > 0) { if (m_header.entity.dataSize > 0) { int pos = lseek(m_fd, m_header.entity.dataSize, SEEK_CUR); int pos = lseek(m_fd, m_dataEndPos, SEEK_SET); return pos == -1 ? (int)errno : (int)NO_ERROR; return pos == -1 ? (int)errno : (int)NO_ERROR; } else { } else { return NO_ERROR; return NO_ERROR; Loading @@ -394,31 +287,21 @@ BackupDataReader::ReadEntityData(void* data, size_t size) if (m_status != NO_ERROR) { if (m_status != NO_ERROR) { return m_status; return m_status; } } int remaining = m_dataEndPos - m_pos; if (size > remaining) { printf("size=%d m_pos=0x%x m_dataEndPos=0x%x remaining=%d\n", size, m_pos, m_dataEndPos, remaining); size = remaining; } if (remaining <= 0) { return 0; } int amt = read(m_fd, data, size); int amt = read(m_fd, data, size); CHECK_SIZE(amt, (int)size); CHECK_SIZE(amt, (int)size); m_pos += size; m_pos += size; return NO_ERROR; return NO_ERROR; } } status_t BackupDataReader::ReadAppFooter(int* cookie) { if (m_status != NO_ERROR) { return m_status; } if (m_header.type != BACKUP_FOOTER_APP_V1) { return EINVAL; } if (m_header.footer.entityCount != m_entityCount) { LOGD("entity count mismatch actual=%d expected=%d", m_entityCount, m_header.footer.entityCount); m_status = EINVAL; return m_status; } *cookie = m_header.footer.cookie; return NO_ERROR; } status_t status_t BackupDataReader::skip_padding() BackupDataReader::skip_padding() { { Loading libs/utils/BackupHelpers.cpp +24 −74 Original line number Original line Diff line number Diff line Loading @@ -689,41 +689,27 @@ backup_helper_test_four() // hexdump -v -e '" " 8/1 " 0x%02x," "\n"' data_writer.data // hexdump -v -e '" " 8/1 " 0x%02x," "\n"' data_writer.data const unsigned char DATA_GOLDEN_FILE[] = { const unsigned char DATA_GOLDEN_FILE[] = { 0x41, 0x70, 0x70, 0x31, 0x0b, 0x00, 0x00, 0x00, 0xdd, 0xcc, 0xbb, 0xaa, 0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x00, 0x44, 0x61, 0x74, 0x61, 0x0b, 0x00, 0x00, 0x00, 0x44, 0x61, 0x74, 0x61, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x6e, 0x6f, 0x5f, 0x70, 0x0c, 0x00, 0x00, 0x00, 0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x00, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x00, 0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x00, 0x41, 0x70, 0x70, 0x31, 0x6e, 0x67, 0x5f, 0x00, 0x44, 0x61, 0x74, 0x61, 0x0c, 0x00, 0x00, 0x00, 0xdd, 0xcc, 0xbb, 0xaa, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x5f, 0x33, 0x00, 0xbc, 0xbc, 0xbc, 0x6f, 0x5f, 0x5f, 0x33, 0x00, 0xbc, 0xbc, 0xbc, 0x44, 0x61, 0x74, 0x61, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x5f, 0x33, 0x00, 0xbc, 0xbc, 0xbc, 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x5f, 0x33, 0x00, 0xbc, 0xbc, 0xbc, 0x41, 0x70, 0x70, 0x31, 0x0d, 0x00, 0x00, 0x00, 0xdd, 0xcc, 0xbb, 0xaa, 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x32, 0x5f, 0x5f, 0x00, 0xbc, 0xbc, 0x6f, 0x5f, 0x5f, 0x33, 0x00, 0xbc, 0xbc, 0xbc, 0x44, 0x61, 0x74, 0x61, 0x0d, 0x00, 0x00, 0x00, 0x44, 0x61, 0x74, 0x61, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64, 0x0e, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x32, 0x5f, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x32, 0x5f, 0x5f, 0x00, 0xbc, 0xbc, 0x70, 0x61, 0x64, 0x64, 0x5f, 0x00, 0xbc, 0xbc, 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x32, 0x5f, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x32, 0x5f, 0x5f, 0x00, 0xbc, 0xbc, 0x41, 0x70, 0x70, 0x31, 0x5f, 0x00, 0xbc, 0xbc, 0x44, 0x61, 0x74, 0x61, 0x0a, 0x00, 0x00, 0x00, 0xdd, 0xcc, 0xbb, 0xaa, 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x31, 0x00, 0xbc, 0x44, 0x61, 0x74, 0x61, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x31, 0x00, 0xbc, 0x70, 0x61, 0x64, 0x64, 0x6f, 0x31, 0x00, 0xbc, 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x31, 0x00, 0xbc, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x31, 0x00 0x46, 0x6f, 0x6f, 0x74, 0x04, 0x00, 0x00, 0x00, 0x99, 0x99, 0x77, 0x77 }; }; const int DATA_GOLDEN_FILE_SIZE = sizeof(DATA_GOLDEN_FILE); const int DATA_GOLDEN_FILE_SIZE = sizeof(DATA_GOLDEN_FILE); Loading @@ -733,12 +719,6 @@ test_write_header_and_entity(BackupDataWriter& writer, const char* str) int err; int err; String8 text(str); String8 text(str); err = writer.WriteAppHeader(text, 0xaabbccdd); if (err != 0) { fprintf(stderr, "WriteAppHeader failed with %s\n", strerror(err)); return err; } err = writer.WriteEntityHeader(text, text.length()+1); err = writer.WriteEntityHeader(text, text.length()+1); if (err != 0) { if (err != 0) { fprintf(stderr, "WriteEntityHeader failed with %s\n", strerror(err)); fprintf(stderr, "WriteEntityHeader failed with %s\n", strerror(err)); Loading Loading @@ -779,8 +759,6 @@ backup_helper_test_data_writer() err |= test_write_header_and_entity(writer, "padded_to_2__"); err |= test_write_header_and_entity(writer, "padded_to_2__"); err |= test_write_header_and_entity(writer, "padded_to1"); err |= test_write_header_and_entity(writer, "padded_to1"); writer.WriteAppFooter(0x77779999); close(fd); close(fd); err = compare_file(filename, DATA_GOLDEN_FILE, DATA_GOLDEN_FILE_SIZE); err = compare_file(filename, DATA_GOLDEN_FILE, DATA_GOLDEN_FILE_SIZE); Loading @@ -800,70 +778,59 @@ test_read_header_and_entity(BackupDataReader& reader, const char* str) String8 string; String8 string; int cookie = 0x11111111; int cookie = 0x11111111; size_t actualSize; size_t actualSize; bool done; int type; // printf("\n\n---------- test_read_header_and_entity -- %s\n\n", str); // printf("\n\n---------- test_read_header_and_entity -- %s\n\n", str); err = reader.ReadNextHeader(); err = reader.ReadNextHeader(&done, &type); if (err != 0) { if (done) { fprintf(stderr, "ReadNextHeader (for app header) failed with %s\n", strerror(err)); fprintf(stderr, "should not be done yet\n"); goto done; goto finished; } } err = reader.ReadAppHeader(&string, &cookie); if (err != 0) { if (err != 0) { fprintf(stderr, "ReadAppHeader failed with %s\n", strerror(err)); fprintf(stderr, "ReadNextHeader (for app header) failed with %s\n", strerror(err)); goto done; goto finished; } if (string != str) { fprintf(stderr, "ReadAppHeader expected packageName '%s' got '%s'\n", str, string.string()); err = EINVAL; goto done; } } if (cookie != (int)0xaabbccdd) { if (type != BACKUP_HEADER_ENTITY_V1) { fprintf(stderr, "ReadAppHeader expected cookie 0x%08x got 0x%08x\n", 0xaabbccdd, cookie); err = EINVAL; err = EINVAL; goto done; fprintf(stderr, "type=0x%08x expected 0x%08x\n", type, BACKUP_HEADER_ENTITY_V1); } err = reader.ReadNextHeader(); if (err != 0) { fprintf(stderr, "ReadNextHeader (for entity header) failed with %s\n", strerror(err)); goto done; } } err = reader.ReadEntityHeader(&string, &actualSize); err = reader.ReadEntityHeader(&string, &actualSize); if (err != 0) { if (err != 0) { fprintf(stderr, "ReadEntityHeader failed with %s\n", strerror(err)); fprintf(stderr, "ReadEntityHeader failed with %s\n", strerror(err)); goto done; goto finished; } } if (string != str) { if (string != str) { fprintf(stderr, "ReadEntityHeader expected key '%s' got '%s'\n", str, string.string()); fprintf(stderr, "ReadEntityHeader expected key '%s' got '%s'\n", str, string.string()); err = EINVAL; err = EINVAL; goto done; goto finished; } } if ((int)actualSize != bufSize) { if ((int)actualSize != bufSize) { fprintf(stderr, "ReadEntityHeader expected dataSize 0x%08x got 0x%08x\n", bufSize, fprintf(stderr, "ReadEntityHeader expected dataSize 0x%08x got 0x%08x\n", bufSize, actualSize); actualSize); err = EINVAL; err = EINVAL; goto done; goto finished; } } err = reader.ReadEntityData(buf, bufSize); err = reader.ReadEntityData(buf, bufSize); if (err != NO_ERROR) { if (err != NO_ERROR) { fprintf(stderr, "ReadEntityData failed with %s\n", strerror(err)); fprintf(stderr, "ReadEntityData failed with %s\n", strerror(err)); goto done; goto finished; } } if (0 != memcmp(buf, str, bufSize)) { if (0 != memcmp(buf, str, bufSize)) { fprintf(stderr, "ReadEntityData expected '%s' but got something starting with " fprintf(stderr, "ReadEntityData expected '%s' but got something starting with " "%02x %02x %02x %02x\n", str, buf[0], buf[1], buf[2], buf[3]); "%02x %02x %02x %02x '%c%c%c%c'\n", str, buf[0], buf[1], buf[2], buf[3], buf[0], buf[1], buf[2], buf[3]); err = EINVAL; err = EINVAL; goto done; goto finished; } } // The next read will confirm whether it got the right amount of data. // The next read will confirm whether it got the right amount of data. done: finished: if (err != NO_ERROR) { if (err != NO_ERROR) { fprintf(stderr, "test_read_header_and_entity failed with %s\n", strerror(err)); fprintf(stderr, "test_read_header_and_entity failed with %s\n", strerror(err)); } } Loading Loading @@ -923,23 +890,6 @@ backup_helper_test_data_reader() if (err == NO_ERROR) { if (err == NO_ERROR) { err = test_read_header_and_entity(reader, "padded_to1"); err = test_read_header_and_entity(reader, "padded_to1"); } } if (err == NO_ERROR) { err = reader.ReadNextHeader(); if (err != 0) { fprintf(stderr, "ReadNextHeader (for app header) failed with %s\n", strerror(err)); } if (err == NO_ERROR) { int cookie; err |= reader.ReadAppFooter(&cookie); if (cookie != 0x77779999) { fprintf(stderr, "app footer cookie expected=0x%08x actual=0x%08x\n", 0x77779999, cookie); err = EINVAL; } } } } } close(fd); close(fd); Loading Loading
include/utils/BackupHelpers.h +3 −24 Original line number Original line Diff line number Diff line Loading @@ -23,30 +23,15 @@ namespace android { namespace android { enum { enum { BACKUP_HEADER_APP_V1 = 0x31707041, // App1 (little endian) BACKUP_HEADER_ENTITY_V1 = 0x61746144, // Data (little endian) BACKUP_HEADER_ENTITY_V1 = 0x61746144, // Data (little endian) BACKUP_FOOTER_APP_V1 = 0x746f6f46, // Foot (little endian) }; }; // the sizes of all of these match. typedef struct { int type; // == BACKUP_HEADER_APP_V1 int packageLen; // length of the name of the package that follows, not including the null. int cookie; } app_header_v1; typedef struct { typedef struct { int type; // BACKUP_HEADER_ENTITY_V1 int type; // BACKUP_HEADER_ENTITY_V1 int keyLen; // length of the key name, not including the null terminator int keyLen; // length of the key name, not including the null terminator int dataSize; // size of the data, not including the padding, -1 means delete int dataSize; // size of the data, not including the padding, -1 means delete } entity_header_v1; } entity_header_v1; typedef struct { int type; // BACKUP_FOOTER_APP_V1 int entityCount; // the number of entities that were written int cookie; } app_footer_v1; /** /** * Writes the data. * Writes the data. Loading @@ -61,13 +46,9 @@ public: // does not close fd // does not close fd ~BackupDataWriter(); ~BackupDataWriter(); status_t WriteAppHeader(const String8& packageName, int cookie); status_t WriteEntityHeader(const String8& key, size_t dataSize); status_t WriteEntityHeader(const String8& key, size_t dataSize); status_t WriteEntityData(const void* data, size_t size); status_t WriteEntityData(const void* data, size_t size); status_t WriteAppFooter(int cookie); private: private: explicit BackupDataWriter(); explicit BackupDataWriter(); status_t write_padding_for(int n); status_t write_padding_for(int n); Loading @@ -92,28 +73,26 @@ public: ~BackupDataReader(); ~BackupDataReader(); status_t Status(); status_t Status(); status_t ReadNextHeader(int* type = NULL); status_t ReadNextHeader(bool* done, int* type); status_t ReadAppHeader(String8* packageName, int* cookie); bool HasEntities(); bool HasEntities(); status_t ReadEntityHeader(String8* key, size_t* dataSize); status_t ReadEntityHeader(String8* key, size_t* dataSize); status_t SkipEntityData(); // must be called with the pointer at the begining of the data. status_t SkipEntityData(); // must be called with the pointer at the begining of the data. status_t ReadEntityData(void* data, size_t size); status_t ReadEntityData(void* data, size_t size); status_t ReadAppFooter(int* cookie); private: private: explicit BackupDataReader(); explicit BackupDataReader(); status_t skip_padding(); status_t skip_padding(); int m_fd; int m_fd; bool m_done; status_t m_status; status_t m_status; ssize_t m_pos; ssize_t m_pos; ssize_t m_dataEndPos; int m_entityCount; int m_entityCount; union { union { int type; int type; app_header_v1 app; entity_header_v1 entity; entity_header_v1 entity; app_footer_v1 footer; } m_header; } m_header; }; }; Loading
libs/utils/BackupData.cpp +17 −134 Original line number Original line Diff line number Diff line Loading @@ -85,46 +85,6 @@ BackupDataWriter::write_padding_for(int n) return NO_ERROR; return NO_ERROR; } } status_t BackupDataWriter::WriteAppHeader(const String8& packageName, int cookie) { 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(BACKUP_HEADER_APP_V1); header.packageLen = tolel(nameLen); header.cookie = cookie; 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 status_t BackupDataWriter::WriteEntityHeader(const String8& key, size_t dataSize) BackupDataWriter::WriteEntityHeader(const String8& key, size_t dataSize) { { Loading Loading @@ -188,40 +148,11 @@ BackupDataWriter::WriteEntityData(const void* data, size_t size) return NO_ERROR; return NO_ERROR; } } status_t BackupDataWriter::WriteAppFooter(int cookie) { 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(BACKUP_FOOTER_APP_V1); footer.entityCount = tolel(m_entityCount); footer.cookie = cookie; 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; } BackupDataReader::BackupDataReader(int fd) BackupDataReader::BackupDataReader(int fd) :m_fd(fd), :m_fd(fd), m_done(false), m_status(NO_ERROR), m_status(NO_ERROR), m_pos(0), m_pos(0), m_entityCount(0) m_entityCount(0) Loading Loading @@ -260,31 +191,25 @@ BackupDataReader::Status() } while(0) } while(0) status_t status_t BackupDataReader::ReadNextHeader(int* type) BackupDataReader::ReadNextHeader(bool* done, int* type) { { *done = m_done; if (m_status != NO_ERROR) { if (m_status != NO_ERROR) { return m_status; return m_status; } } int amt; int amt; SKIP_PADDING(); // No error checking here, in case we're at the end of the stream. Just let read() fail. skip_padding(); amt = read(m_fd, &m_header, sizeof(m_header)); amt = read(m_fd, &m_header, sizeof(m_header)); *done = m_done = (amt == 0); CHECK_SIZE(amt, sizeof(m_header)); CHECK_SIZE(amt, sizeof(m_header)); // validate and fix up the fields. // validate and fix up the fields. m_header.type = fromlel(m_header.type); m_header.type = fromlel(m_header.type); switch (m_header.type) switch (m_header.type) { { case BACKUP_HEADER_APP_V1: m_header.app.packageLen = fromlel(m_header.app.packageLen); if (m_header.app.packageLen < 0) { LOGD("App header at %d has packageLen<0: 0x%08x\n", (int)m_pos, (int)m_header.app.packageLen); m_status = EINVAL; } m_header.app.cookie = m_header.app.cookie; break; case BACKUP_HEADER_ENTITY_V1: case BACKUP_HEADER_ENTITY_V1: m_header.entity.keyLen = fromlel(m_header.entity.keyLen); m_header.entity.keyLen = fromlel(m_header.entity.keyLen); if (m_header.entity.keyLen <= 0) { if (m_header.entity.keyLen <= 0) { Loading @@ -295,15 +220,6 @@ BackupDataReader::ReadNextHeader(int* type) m_header.entity.dataSize = fromlel(m_header.entity.dataSize); m_header.entity.dataSize = fromlel(m_header.entity.dataSize); m_entityCount++; m_entityCount++; break; break; case BACKUP_FOOTER_APP_V1: m_header.footer.entityCount = fromlel(m_header.footer.entityCount); if (m_header.footer.entityCount < 0) { LOGD("Entity header at %d has entityCount<0: 0x%08x\n", (int)m_pos, (int)m_header.footer.entityCount); m_status = EINVAL; } m_header.footer.cookie = m_header.footer.cookie; break; default: default: LOGD("Chunk header at %d has invalid type: 0x%08x", (int)m_pos, (int)m_header.type); LOGD("Chunk header at %d has invalid type: 0x%08x", (int)m_pos, (int)m_header.type); m_status = EINVAL; m_status = EINVAL; Loading @@ -316,30 +232,6 @@ BackupDataReader::ReadNextHeader(int* type) return m_status; return m_status; } } status_t BackupDataReader::ReadAppHeader(String8* packageName, int* cookie) { if (m_status != NO_ERROR) { return m_status; } if (m_header.type != BACKUP_HEADER_APP_V1) { return EINVAL; } size_t size = m_header.app.packageLen; char* buf = packageName->lockBuffer(size); if (buf == NULL) { packageName->unlockBuffer(); m_status = ENOMEM; return m_status; } int amt = read(m_fd, buf, size+1); CHECK_SIZE(amt, (int)size+1); packageName->unlockBuffer(size); m_pos += size+1; *cookie = m_header.app.cookie; return NO_ERROR; } bool bool BackupDataReader::HasEntities() BackupDataReader::HasEntities() { { Loading Loading @@ -368,6 +260,7 @@ BackupDataReader::ReadEntityHeader(String8* key, size_t* dataSize) m_pos += size+1; m_pos += size+1; *dataSize = m_header.entity.dataSize; *dataSize = m_header.entity.dataSize; SKIP_PADDING(); SKIP_PADDING(); m_dataEndPos = m_pos + *dataSize; return NO_ERROR; return NO_ERROR; } } Loading @@ -381,7 +274,7 @@ BackupDataReader::SkipEntityData() return EINVAL; return EINVAL; } } if (m_header.entity.dataSize > 0) { if (m_header.entity.dataSize > 0) { int pos = lseek(m_fd, m_header.entity.dataSize, SEEK_CUR); int pos = lseek(m_fd, m_dataEndPos, SEEK_SET); return pos == -1 ? (int)errno : (int)NO_ERROR; return pos == -1 ? (int)errno : (int)NO_ERROR; } else { } else { return NO_ERROR; return NO_ERROR; Loading @@ -394,31 +287,21 @@ BackupDataReader::ReadEntityData(void* data, size_t size) if (m_status != NO_ERROR) { if (m_status != NO_ERROR) { return m_status; return m_status; } } int remaining = m_dataEndPos - m_pos; if (size > remaining) { printf("size=%d m_pos=0x%x m_dataEndPos=0x%x remaining=%d\n", size, m_pos, m_dataEndPos, remaining); size = remaining; } if (remaining <= 0) { return 0; } int amt = read(m_fd, data, size); int amt = read(m_fd, data, size); CHECK_SIZE(amt, (int)size); CHECK_SIZE(amt, (int)size); m_pos += size; m_pos += size; return NO_ERROR; return NO_ERROR; } } status_t BackupDataReader::ReadAppFooter(int* cookie) { if (m_status != NO_ERROR) { return m_status; } if (m_header.type != BACKUP_FOOTER_APP_V1) { return EINVAL; } if (m_header.footer.entityCount != m_entityCount) { LOGD("entity count mismatch actual=%d expected=%d", m_entityCount, m_header.footer.entityCount); m_status = EINVAL; return m_status; } *cookie = m_header.footer.cookie; return NO_ERROR; } status_t status_t BackupDataReader::skip_padding() BackupDataReader::skip_padding() { { Loading
libs/utils/BackupHelpers.cpp +24 −74 Original line number Original line Diff line number Diff line Loading @@ -689,41 +689,27 @@ backup_helper_test_four() // hexdump -v -e '" " 8/1 " 0x%02x," "\n"' data_writer.data // hexdump -v -e '" " 8/1 " 0x%02x," "\n"' data_writer.data const unsigned char DATA_GOLDEN_FILE[] = { const unsigned char DATA_GOLDEN_FILE[] = { 0x41, 0x70, 0x70, 0x31, 0x0b, 0x00, 0x00, 0x00, 0xdd, 0xcc, 0xbb, 0xaa, 0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x00, 0x44, 0x61, 0x74, 0x61, 0x0b, 0x00, 0x00, 0x00, 0x44, 0x61, 0x74, 0x61, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x6e, 0x6f, 0x5f, 0x70, 0x0c, 0x00, 0x00, 0x00, 0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x00, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x00, 0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x00, 0x41, 0x70, 0x70, 0x31, 0x6e, 0x67, 0x5f, 0x00, 0x44, 0x61, 0x74, 0x61, 0x0c, 0x00, 0x00, 0x00, 0xdd, 0xcc, 0xbb, 0xaa, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x5f, 0x33, 0x00, 0xbc, 0xbc, 0xbc, 0x6f, 0x5f, 0x5f, 0x33, 0x00, 0xbc, 0xbc, 0xbc, 0x44, 0x61, 0x74, 0x61, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x5f, 0x33, 0x00, 0xbc, 0xbc, 0xbc, 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x5f, 0x33, 0x00, 0xbc, 0xbc, 0xbc, 0x41, 0x70, 0x70, 0x31, 0x0d, 0x00, 0x00, 0x00, 0xdd, 0xcc, 0xbb, 0xaa, 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x32, 0x5f, 0x5f, 0x00, 0xbc, 0xbc, 0x6f, 0x5f, 0x5f, 0x33, 0x00, 0xbc, 0xbc, 0xbc, 0x44, 0x61, 0x74, 0x61, 0x0d, 0x00, 0x00, 0x00, 0x44, 0x61, 0x74, 0x61, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64, 0x0e, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x32, 0x5f, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x32, 0x5f, 0x5f, 0x00, 0xbc, 0xbc, 0x70, 0x61, 0x64, 0x64, 0x5f, 0x00, 0xbc, 0xbc, 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x32, 0x5f, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x32, 0x5f, 0x5f, 0x00, 0xbc, 0xbc, 0x41, 0x70, 0x70, 0x31, 0x5f, 0x00, 0xbc, 0xbc, 0x44, 0x61, 0x74, 0x61, 0x0a, 0x00, 0x00, 0x00, 0xdd, 0xcc, 0xbb, 0xaa, 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x31, 0x00, 0xbc, 0x44, 0x61, 0x74, 0x61, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x31, 0x00, 0xbc, 0x70, 0x61, 0x64, 0x64, 0x6f, 0x31, 0x00, 0xbc, 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x31, 0x00, 0xbc, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x31, 0x00 0x46, 0x6f, 0x6f, 0x74, 0x04, 0x00, 0x00, 0x00, 0x99, 0x99, 0x77, 0x77 }; }; const int DATA_GOLDEN_FILE_SIZE = sizeof(DATA_GOLDEN_FILE); const int DATA_GOLDEN_FILE_SIZE = sizeof(DATA_GOLDEN_FILE); Loading @@ -733,12 +719,6 @@ test_write_header_and_entity(BackupDataWriter& writer, const char* str) int err; int err; String8 text(str); String8 text(str); err = writer.WriteAppHeader(text, 0xaabbccdd); if (err != 0) { fprintf(stderr, "WriteAppHeader failed with %s\n", strerror(err)); return err; } err = writer.WriteEntityHeader(text, text.length()+1); err = writer.WriteEntityHeader(text, text.length()+1); if (err != 0) { if (err != 0) { fprintf(stderr, "WriteEntityHeader failed with %s\n", strerror(err)); fprintf(stderr, "WriteEntityHeader failed with %s\n", strerror(err)); Loading Loading @@ -779,8 +759,6 @@ backup_helper_test_data_writer() err |= test_write_header_and_entity(writer, "padded_to_2__"); err |= test_write_header_and_entity(writer, "padded_to_2__"); err |= test_write_header_and_entity(writer, "padded_to1"); err |= test_write_header_and_entity(writer, "padded_to1"); writer.WriteAppFooter(0x77779999); close(fd); close(fd); err = compare_file(filename, DATA_GOLDEN_FILE, DATA_GOLDEN_FILE_SIZE); err = compare_file(filename, DATA_GOLDEN_FILE, DATA_GOLDEN_FILE_SIZE); Loading @@ -800,70 +778,59 @@ test_read_header_and_entity(BackupDataReader& reader, const char* str) String8 string; String8 string; int cookie = 0x11111111; int cookie = 0x11111111; size_t actualSize; size_t actualSize; bool done; int type; // printf("\n\n---------- test_read_header_and_entity -- %s\n\n", str); // printf("\n\n---------- test_read_header_and_entity -- %s\n\n", str); err = reader.ReadNextHeader(); err = reader.ReadNextHeader(&done, &type); if (err != 0) { if (done) { fprintf(stderr, "ReadNextHeader (for app header) failed with %s\n", strerror(err)); fprintf(stderr, "should not be done yet\n"); goto done; goto finished; } } err = reader.ReadAppHeader(&string, &cookie); if (err != 0) { if (err != 0) { fprintf(stderr, "ReadAppHeader failed with %s\n", strerror(err)); fprintf(stderr, "ReadNextHeader (for app header) failed with %s\n", strerror(err)); goto done; goto finished; } if (string != str) { fprintf(stderr, "ReadAppHeader expected packageName '%s' got '%s'\n", str, string.string()); err = EINVAL; goto done; } } if (cookie != (int)0xaabbccdd) { if (type != BACKUP_HEADER_ENTITY_V1) { fprintf(stderr, "ReadAppHeader expected cookie 0x%08x got 0x%08x\n", 0xaabbccdd, cookie); err = EINVAL; err = EINVAL; goto done; fprintf(stderr, "type=0x%08x expected 0x%08x\n", type, BACKUP_HEADER_ENTITY_V1); } err = reader.ReadNextHeader(); if (err != 0) { fprintf(stderr, "ReadNextHeader (for entity header) failed with %s\n", strerror(err)); goto done; } } err = reader.ReadEntityHeader(&string, &actualSize); err = reader.ReadEntityHeader(&string, &actualSize); if (err != 0) { if (err != 0) { fprintf(stderr, "ReadEntityHeader failed with %s\n", strerror(err)); fprintf(stderr, "ReadEntityHeader failed with %s\n", strerror(err)); goto done; goto finished; } } if (string != str) { if (string != str) { fprintf(stderr, "ReadEntityHeader expected key '%s' got '%s'\n", str, string.string()); fprintf(stderr, "ReadEntityHeader expected key '%s' got '%s'\n", str, string.string()); err = EINVAL; err = EINVAL; goto done; goto finished; } } if ((int)actualSize != bufSize) { if ((int)actualSize != bufSize) { fprintf(stderr, "ReadEntityHeader expected dataSize 0x%08x got 0x%08x\n", bufSize, fprintf(stderr, "ReadEntityHeader expected dataSize 0x%08x got 0x%08x\n", bufSize, actualSize); actualSize); err = EINVAL; err = EINVAL; goto done; goto finished; } } err = reader.ReadEntityData(buf, bufSize); err = reader.ReadEntityData(buf, bufSize); if (err != NO_ERROR) { if (err != NO_ERROR) { fprintf(stderr, "ReadEntityData failed with %s\n", strerror(err)); fprintf(stderr, "ReadEntityData failed with %s\n", strerror(err)); goto done; goto finished; } } if (0 != memcmp(buf, str, bufSize)) { if (0 != memcmp(buf, str, bufSize)) { fprintf(stderr, "ReadEntityData expected '%s' but got something starting with " fprintf(stderr, "ReadEntityData expected '%s' but got something starting with " "%02x %02x %02x %02x\n", str, buf[0], buf[1], buf[2], buf[3]); "%02x %02x %02x %02x '%c%c%c%c'\n", str, buf[0], buf[1], buf[2], buf[3], buf[0], buf[1], buf[2], buf[3]); err = EINVAL; err = EINVAL; goto done; goto finished; } } // The next read will confirm whether it got the right amount of data. // The next read will confirm whether it got the right amount of data. done: finished: if (err != NO_ERROR) { if (err != NO_ERROR) { fprintf(stderr, "test_read_header_and_entity failed with %s\n", strerror(err)); fprintf(stderr, "test_read_header_and_entity failed with %s\n", strerror(err)); } } Loading Loading @@ -923,23 +890,6 @@ backup_helper_test_data_reader() if (err == NO_ERROR) { if (err == NO_ERROR) { err = test_read_header_and_entity(reader, "padded_to1"); err = test_read_header_and_entity(reader, "padded_to1"); } } if (err == NO_ERROR) { err = reader.ReadNextHeader(); if (err != 0) { fprintf(stderr, "ReadNextHeader (for app header) failed with %s\n", strerror(err)); } if (err == NO_ERROR) { int cookie; err |= reader.ReadAppFooter(&cookie); if (cookie != 0x77779999) { fprintf(stderr, "app footer cookie expected=0x%08x actual=0x%08x\n", 0x77779999, cookie); err = EINVAL; } } } } } close(fd); close(fd); Loading