diff options
| -rw-r--r-- | cmds/keystore/commands.c | 170 | ||||
| -rw-r--r-- | cmds/keystore/keystore.c | 100 | ||||
| -rw-r--r-- | cmds/keystore/keystore.h | 37 | ||||
| -rw-r--r-- | include/utils/BackupHelpers.h | 63 | ||||
| -rw-r--r-- | libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp | 11 | ||||
| -rw-r--r-- | libs/utils/BackupData.cpp | 196 | ||||
| -rw-r--r-- | libs/utils/BackupHelpers.cpp | 215 |
7 files changed, 438 insertions, 354 deletions
diff --git a/cmds/keystore/commands.c b/cmds/keystore/commands.c index e53cecef2b..17dd060ac5 100644 --- a/cmds/keystore/commands.c +++ b/cmds/keystore/commands.c @@ -1,5 +1,5 @@ /* -** Copyright 2008, The Android Open Source Project +** Copyright 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. @@ -30,7 +30,8 @@ static DIR *open_keystore(const char *dir) return d; } -static int list_files(const char *dir, char reply[REPLY_MAX]) { +static int list_files(const char *dir, char reply[REPLY_MAX]) +{ struct dirent *de; DIR *d; @@ -39,7 +40,9 @@ static int list_files(const char *dir, char reply[REPLY_MAX]) { } reply[0]=0; while ((de = readdir(d))) { - if (de->d_type != DT_REG) continue; + if (de->d_type != DT_DIR) continue; + if ((strcmp(DOT, de->d_name) == 0) || + (strcmp(DOTDOT, de->d_name) == 0)) continue; if (reply[0] != 0) strlcat(reply, " ", REPLY_MAX); if (strlcat(reply, de->d_name, REPLY_MAX) >= REPLY_MAX) { LOGE("reply is too long(too many files under '%s'\n", dir); @@ -50,31 +53,25 @@ static int list_files(const char *dir, char reply[REPLY_MAX]) { return 0; } -static int copy_keyfile(const char *keystore, const char *srcfile) { - int srcfd, dstfd; - int length; - char buf[2048]; - char dstfile[KEYNAME_LENGTH]; - const char *filename = strrchr(srcfile, '/'); +static int copy_keyfile(const char *src, int src_type, const char *dstfile) { + int srcfd = -1, dstfd; + char buf[REPLY_MAX]; - strlcpy(dstfile, keystore, KEYNAME_LENGTH); - strlcat(dstfile, "/", KEYNAME_LENGTH); - if (strlcat(dstfile, filename ? filename + 1 : srcfile, - KEYNAME_LENGTH) >= KEYNAME_LENGTH) { - LOGE("keyname is too long '%s'\n", srcfile); - return -1; - } - - if ((srcfd = open(srcfile, O_RDONLY)) == -1) { - LOGE("Cannot open the original file '%s'\n", srcfile); + if ((src_type == IS_FILE) && (srcfd = open(src, O_RDONLY)) == -1) { + LOGE("Cannot open the original file '%s'\n", src); return -1; } if ((dstfd = open(dstfile, O_CREAT|O_RDWR)) == -1) { LOGE("Cannot open the destination file '%s'\n", dstfile); return -1; } - while((length = read(srcfd, buf, 2048)) > 0) { - write(dstfd, buf, length); + if (src_type == IS_FILE) { + int length; + while((length = read(srcfd, buf, REPLY_MAX)) > 0) { + write(dstfd, buf, length); + } + } else { + write(dstfd, src, strlen(src)); } close(srcfd); close(dstfd); @@ -82,60 +79,149 @@ static int copy_keyfile(const char *keystore, const char *srcfile) { return 0; } -static int install_key(const char *dir, const char *keyfile) +static int install_key(const char *path, const char *certname, const char *src, + int src_is_file, char *dstfile) { struct dirent *de; + char fullpath[KEYNAME_LENGTH]; DIR *d; - if ((d = open_keystore(dir)) == NULL) { + if (snprintf(fullpath, sizeof(fullpath), "%s/%s/", path, certname) + >= KEYNAME_LENGTH) { + LOGE("cert name '%s' is too long.\n", certname); + return -1; + } + + if ((d = open_keystore(fullpath)) == NULL) { + LOGE("Can not open the keystore '%s'\n", fullpath); + return -1; + } + closedir(d); + if (strlcat(fullpath, dstfile, KEYNAME_LENGTH) >= KEYNAME_LENGTH) { + LOGE("cert name '%s' is too long.\n", certname); return -1; } - return copy_keyfile(dir, keyfile); + return copy_keyfile(src, src_is_file, fullpath); } -static int remove_key(const char *dir, const char *keyfile) +static int get_key(const char *path, const char *keyname, const char *file, + char reply[REPLY_MAX]) +{ + struct dirent *de; + char filename[KEYNAME_LENGTH]; + int fd; + + if (snprintf(filename, sizeof(filename), "%s/%s/%s", path, keyname, file) + >= KEYNAME_LENGTH) { + LOGE("cert name '%s' is too long.\n", keyname); + return -1; + } + + if ((fd = open(filename, O_RDONLY)) == -1) { + return -1; + } + close(fd); + strlcpy(reply, filename, REPLY_MAX); + return 0; +} + +static int remove_key(const char *dir, const char *key) { char dstfile[KEYNAME_LENGTH]; + char *keyfile[4] = { USER_KEY, USER_P12_CERT, USER_CERTIFICATE, + CA_CERTIFICATE }; + int i, count = 0; + + for ( i = 0 ; i < 4 ; i++) { + if (snprintf(dstfile, KEYNAME_LENGTH, "%s/%s/%s", dir, key, keyfile[i]) + >= KEYNAME_LENGTH) { + LOGE("keyname is too long '%s'\n", key); + return -1; + } + if (unlink(dstfile) == 0) count++; + } - strlcpy(dstfile, dir, KEYNAME_LENGTH); - strlcat(dstfile, "/", KEYNAME_LENGTH); - if (strlcat(dstfile, keyfile, KEYNAME_LENGTH) >= KEYNAME_LENGTH) { - LOGE("keyname is too long '%s'\n", keyfile); + if (count == 0) { + LOGE("can not clean up '%s' keys or not exist\n", key); return -1; } - if (unlink(dstfile)) { - LOGE("cannot delete '%s': %s\n", dstfile, strerror(errno)); + + snprintf(dstfile, KEYNAME_LENGTH, "%s/%s", dir, key); + if (rmdir(dstfile)) { + LOGE("can not clean up '%s' directory\n", key); return -1; } return 0; } -int list_certs(char reply[REPLY_MAX]) +int list_user_certs(char reply[REPLY_MAX]) { return list_files(CERTS_DIR, reply); } -int list_userkeys(char reply[REPLY_MAX]) +int list_ca_certs(char reply[REPLY_MAX]) { - return list_files(USERKEYS_DIR, reply); + return list_files(CACERTS_DIR, reply); } -int install_cert(const char *certfile) +int install_user_cert(const char *keyname, const char *cert, const char *key) { - return install_key(CERTS_DIR, certfile); + if (install_key(CERTS_DIR, keyname, cert, IS_FILE, USER_CERTIFICATE) == 0) { + return install_key(CERTS_DIR, keyname, key, IS_FILE, USER_KEY); + } + return -1; } -int install_userkey(const char *keyfile) +int install_ca_cert(const char *keyname, const char *certfile) { - return install_key(USERKEYS_DIR, keyfile); + return install_key(CACERTS_DIR, keyname, certfile, IS_FILE, CA_CERTIFICATE); +} + +int install_p12_cert(const char *keyname, const char *certfile) +{ + return install_key(CERTS_DIR, keyname, certfile, IS_FILE, USER_P12_CERT); +} + +int add_ca_cert(const char *keyname, const char *certificate) +{ + return install_key(CACERTS_DIR, keyname, certificate, IS_CONTENT, + CA_CERTIFICATE); +} + +int add_user_cert(const char *keyname, const char *certificate) +{ + return install_key(CERTS_DIR, keyname, certificate, IS_CONTENT, + USER_CERTIFICATE); +} + +int add_user_key(const char *keyname, const char *key) +{ + return install_key(CERTS_DIR, keyname, key, IS_CONTENT, USER_KEY); +} + +int get_ca_cert(const char *keyname, char reply[REPLY_MAX]) +{ + return get_key(CACERTS_DIR, keyname, CA_CERTIFICATE, reply); +} + +int get_user_cert(const char *keyname, char reply[REPLY_MAX]) +{ + return get_key(CERTS_DIR, keyname, USER_CERTIFICATE, reply); +} + +int get_user_key(const char *keyname, char reply[REPLY_MAX]) +{ + if(get_key(CERTS_DIR, keyname, USER_KEY, reply)) + return get_key(CERTS_DIR, keyname, USER_P12_CERT, reply); + return 0; } -int remove_cert(const char *certfile) +int remove_user_cert(const char *key) { - return remove_key(CERTS_DIR, certfile); + return remove_key(CERTS_DIR, key); } -int remove_userkey(const char *keyfile) +int remove_ca_cert(const char *key) { - return remove_key(USERKEYS_DIR, keyfile); + return remove_key(CACERTS_DIR, key); } diff --git a/cmds/keystore/keystore.c b/cmds/keystore/keystore.c index 5193b3dba5..df8d832726 100644 --- a/cmds/keystore/keystore.c +++ b/cmds/keystore/keystore.c @@ -16,37 +16,89 @@ #include "keystore.h" +static inline int has_whitespace(char *name) +{ + if((strrchr(name, ' ') != NULL)) { + LOGE("'%s' contains whitespace character\n", name); + return 1; + } + return 0; +} + +static int do_list_user_certs(char **arg, char reply[REPLY_MAX]) +{ + return list_user_certs(reply); +} + +static int do_list_ca_certs(char **arg, char reply[REPLY_MAX]) +{ + return list_ca_certs(reply); +} + +static int do_install_user_cert(char **arg, char reply[REPLY_MAX]) +{ + if (has_whitespace(arg[0])) return -1; + /* copy the certificate and key to keystore */ + return install_user_cert(arg[0], arg[1], arg[2]); +} -static int do_list_certs(char **arg, char reply[REPLY_MAX]) +static int do_install_p12_cert(char **arg, char reply[REPLY_MAX]) { - return list_certs(reply); + if (has_whitespace(arg[0])) return -1; + return install_p12_cert(arg[0], arg[1]); } -static int do_list_userkeys(char **arg, char reply[REPLY_MAX]) +static int do_install_ca_cert(char **arg, char reply[REPLY_MAX]) { - return list_userkeys(reply); + if (has_whitespace(arg[0])) return -1; + /* copy the certificate and key to keystore */ + return install_ca_cert(arg[0], arg[1]); } -static int do_install_cert(char **arg, char reply[REPLY_MAX]) +static int do_add_ca_cert(char **arg, char reply[REPLY_MAX]) { - return install_cert(arg[0]); /* move the certificate to keystore */ + if (has_whitespace(arg[0])) return -1; + return add_ca_cert(arg[0], arg[1]); } -static int do_remove_cert(char **arg, char reply[REPLY_MAX]) +static int do_add_user_cert(char **arg, char reply[REPLY_MAX]) { - return remove_cert(arg[0]); /* certificate */ + if (has_whitespace(arg[0])) return -1; + return add_user_cert(arg[0], arg[1]); } -static int do_install_userkey(char **arg, char reply[REPLY_MAX]) +static int do_add_user_key(char **arg, char reply[REPLY_MAX]) { - return install_userkey(arg[0]); /* move the certificate to keystore */ + if (has_whitespace(arg[0])) return -1; + return add_user_key(arg[0], arg[1]); } -static int do_remove_userkey(char **arg, char reply[REPLY_MAX]) +static int do_get_ca_cert(char **arg, char reply[REPLY_MAX]) { - return remove_userkey(arg[0]); /* userkey */ + return get_ca_cert(arg[0], reply); } +static int do_get_user_cert(char **arg, char reply[REPLY_MAX]) +{ + return get_user_cert(arg[0], reply); +} + +static int do_get_user_key(char **arg, char reply[REPLY_MAX]) +{ + return get_user_key(arg[0], reply); +} + +static int do_remove_user_cert(char **arg, char reply[REPLY_MAX]) +{ + return remove_user_cert(arg[0]); +} + +static int do_remove_ca_cert(char **arg, char reply[REPLY_MAX]) +{ + return remove_ca_cert(arg[0]); +} + + struct cmdinfo { const char *name; unsigned numargs; @@ -55,12 +107,19 @@ struct cmdinfo { struct cmdinfo cmds[] = { - { "listcerts", 0, do_list_certs }, - { "listuserkeys", 0, do_list_userkeys }, - { "installcert", 1, do_install_cert }, - { "removecert", 1, do_remove_cert }, - { "installuserkey", 1, do_install_userkey }, - { "removeuserkey", 1, do_remove_userkey }, + { "listcacerts", 0, do_list_ca_certs }, + { "listusercerts", 0, do_list_user_certs }, + { "installusercert", 3, do_install_user_cert }, + { "installcacert", 2, do_install_ca_cert }, + { "installp12cert", 2, do_install_p12_cert }, + { "addusercert", 2, do_add_user_cert }, + { "adduserkey", 2, do_add_user_key }, + { "addcacert", 2, do_add_ca_cert }, + { "getusercert", 1, do_get_user_cert }, + { "getuserkey", 1, do_get_user_key }, + { "getcacert", 1, do_get_ca_cert }, + { "removecacert", 1, do_remove_ca_cert }, + { "removeusercert", 1, do_remove_user_cert }, }; static int readx(int s, void *_buf, int count) @@ -121,7 +180,7 @@ static int execute(int s, char cmd[BUFFER_MAX]) /* n is number of args (not counting arg[0]) */ arg[0] = cmd; while (*cmd) { - if (isspace(*cmd)) { + if (*cmd == CMD_DELIMITER) { *cmd++ = 0; n++; arg[n] = cmd; @@ -167,6 +226,7 @@ int shell_command(const int argc, const char **argv) int fd, i; short ret; unsigned short count; + char delimiter[2] = { CMD_DELIMITER, 0 }; char buf[BUFFER_MAX]=""; fd = socket_local_client(SOCKET_PATH, @@ -177,7 +237,7 @@ int shell_command(const int argc, const char **argv) exit(1); } for(i = 0; i < argc; i++) { - if (i > 0) strlcat(buf, " ", BUFFER_MAX); + if (i > 0) strlcat(buf, delimiter, BUFFER_MAX); if(strlcat(buf, argv[i], BUFFER_MAX) >= BUFFER_MAX) { fprintf(stderr, "Arguments are too long\n"); exit(1); diff --git a/cmds/keystore/keystore.h b/cmds/keystore/keystore.h index 35acf0b9bd..b9cb1851b9 100644 --- a/cmds/keystore/keystore.h +++ b/cmds/keystore/keystore.h @@ -40,18 +40,35 @@ /* path of the keystore */ #define KEYSTORE_DIR_PREFIX "/data/misc/keystore" -#define CERTS_DIR KEYSTORE_DIR_PREFIX "/certs" -#define USERKEYS_DIR KEYSTORE_DIR_PREFIX "/userkeys" +#define CERTS_DIR KEYSTORE_DIR_PREFIX "/keys" +#define CACERTS_DIR KEYSTORE_DIR_PREFIX "/cacerts" +#define CA_CERTIFICATE "ca.crt" +#define USER_CERTIFICATE "user.crt" +#define USER_P12_CERT "user.p12" +#define USER_KEY "user.key" +#define DOT "." +#define DOTDOT ".." -#define BUFFER_MAX 1024 /* input buffer for commands */ +#define BUFFER_MAX 4096 /* input buffer for commands */ #define TOKEN_MAX 8 /* max number of arguments in buffer */ -#define REPLY_MAX 1024 /* largest reply allowed */ +#define REPLY_MAX 4096 /* largest reply allowed */ +#define CMD_DELIMITER '\t' #define KEYNAME_LENGTH 128 +#define IS_CONTENT 0 +#define IS_FILE 1 + /* commands.c */ -int list_certs(char reply[REPLY_MAX]); -int list_userkeys(char reply[REPLY_MAX]); -int install_cert(const char *certfile); -int install_userkey(const char *keyfile); -int remove_cert(const char *certfile); -int remove_userkey(const char *keyfile); +int list_ca_certs(char reply[REPLY_MAX]); +int list_user_certs(char reply[REPLY_MAX]); +int install_user_cert(const char *certname, const char *cert, const char *key); +int install_ca_cert(const char *certname, const char *cert); +int install_p12_cert(const char *certname, const char *cert); +int add_ca_cert(const char *certname, const char *content); +int add_user_cert(const char *certname, const char *content); +int add_user_key(const char *keyname, const char *content); +int get_ca_cert(const char *keyname, char reply[REPLY_MAX]); +int get_user_cert(const char *keyname, char reply[REPLY_MAX]); +int get_user_key(const char *keyname, char reply[REPLY_MAX]); +int remove_user_cert(const char *certname); +int remove_ca_cert(const char *certname); diff --git a/include/utils/BackupHelpers.h b/include/utils/BackupHelpers.h index f60f4ead64..c78b99a8dc 100644 --- a/include/utils/BackupHelpers.h +++ b/include/utils/BackupHelpers.h @@ -19,33 +19,40 @@ #include <utils/Errors.h> #include <utils/String8.h> +#include <utils/KeyedVector.h> namespace android { enum { - BACKUP_HEADER_APP_V1 = 0x31707041, // App1 (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 { int type; // BACKUP_HEADER_ENTITY_V1 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 } 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; +struct SnapshotHeader { + int magic0; + int fileCount; + int magic1; + int totalSize; +}; + +struct FileState { + int modTime_sec; + int modTime_nsec; + int size; + int crc32; + int nameLen; +}; + +struct FileRec { + String8 file; + bool deleted; + FileState s; +}; /** @@ -61,13 +68,9 @@ public: // does not close fd ~BackupDataWriter(); - status_t WriteAppHeader(const String8& packageName, int cookie); - status_t WriteEntityHeader(const String8& key, size_t dataSize); status_t WriteEntityData(const void* data, size_t size); - status_t WriteAppFooter(int cookie); - private: explicit BackupDataWriter(); status_t write_padding_for(int n); @@ -92,34 +95,46 @@ public: ~BackupDataReader(); 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(); 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 ReadEntityData(void* data, size_t size); - status_t ReadAppFooter(int* cookie); + ssize_t ReadEntityData(void* data, size_t size); private: explicit BackupDataReader(); status_t skip_padding(); int m_fd; + bool m_done; status_t m_status; ssize_t m_pos; + ssize_t m_dataEndPos; int m_entityCount; union { int type; - app_header_v1 app; entity_header_v1 entity; - app_footer_v1 footer; } m_header; + String8 m_key; }; int back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD, char const* const* files, char const* const *keys, int fileCount); +class RestoreHelperBase +{ +public: + RestoreHelperBase(); + ~RestoreHelperBase(); + + status_t WriteFile(const String8& filename, BackupDataReader* in); + status_t WriteSnapshot(int fd); + +private: + void* m_buf; + KeyedVector<String8,FileRec> m_files; +}; #define TEST_BACKUP_HELPERS 1 diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp index f14d7e99c2..eec645edc9 100644 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp +++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp @@ -189,9 +189,14 @@ void DisplayHardware::init(uint32_t dpy) char property[PROPERTY_VALUE_MAX]; - if (property_get("ro.sf.lcd_density", property, NULL) <= 0) { - LOGW("ro.sf.lcd_density not defined, using 160 dpi by default."); - strcpy(property, "160"); + /* Read density from build-specific ro.sf.lcd_density property + * except if it is overriden by qemu.sf.lcd_density. + */ + if (property_get("qemu.sf.lcd_density", property, NULL) <= 0) { + if (property_get("ro.sf.lcd_density", property, NULL) <= 0) { + LOGW("ro.sf.lcd_density not defined, using 160 dpi by default."); + strcpy(property, "160"); + } } mDensity = atoi(property) * (1.0f/160.0f); diff --git a/libs/utils/BackupData.cpp b/libs/utils/BackupData.cpp index 8c9f87528e..6a7f056464 100644 --- a/libs/utils/BackupData.cpp +++ b/libs/utils/BackupData.cpp @@ -86,46 +86,6 @@ BackupDataWriter::write_padding_for(int n) } 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 BackupDataWriter::WriteEntityHeader(const String8& key, size_t dataSize) { if (m_status != NO_ERROR) { @@ -188,40 +148,11 @@ BackupDataWriter::WriteEntityData(const void* data, size_t size) 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) :m_fd(fd), + m_done(false), m_status(NO_ERROR), m_pos(0), m_entityCount(0) @@ -260,32 +191,31 @@ BackupDataReader::Status() } while(0) status_t -BackupDataReader::ReadNextHeader(int* type) +BackupDataReader::ReadNextHeader(bool* done, int* type) { + *done = m_done; if (m_status != NO_ERROR) { return m_status; } 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)); + *done = m_done = (amt == 0); CHECK_SIZE(amt, sizeof(m_header)); + m_pos += sizeof(m_header); + if (type) { + *type = m_header.type; + } // validate and fix up the fields. m_header.type = fromlel(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: + { m_header.entity.keyLen = fromlel(m_header.entity.keyLen); if (m_header.entity.keyLen <= 0) { LOGD("Entity header at %d has keyLen<=0: 0x%08x\n", (int)m_pos, @@ -294,52 +224,31 @@ BackupDataReader::ReadNextHeader(int* type) } m_header.entity.dataSize = fromlel(m_header.entity.dataSize); m_entityCount++; - 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; + + // read the rest of the header (filename) + size_t size = m_header.entity.keyLen; + char* buf = m_key.lockBuffer(size); + if (buf == NULL) { + m_status = ENOMEM; + return m_status; } - m_header.footer.cookie = m_header.footer.cookie; + int amt = read(m_fd, buf, size+1); + CHECK_SIZE(amt, (int)size+1); + m_key.unlockBuffer(size); + m_pos += size+1; + SKIP_PADDING(); + m_dataEndPos = m_pos + m_header.entity.dataSize; + break; + } default: LOGD("Chunk header at %d has invalid type: 0x%08x", (int)m_pos, (int)m_header.type); m_status = EINVAL; } - m_pos += sizeof(m_header); - if (type) { - *type = m_header.type; - } 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 BackupDataReader::HasEntities() { @@ -355,19 +264,8 @@ BackupDataReader::ReadEntityHeader(String8* key, size_t* dataSize) if (m_header.type != BACKUP_HEADER_ENTITY_V1) { return EINVAL; } - size_t size = m_header.entity.keyLen; - char* buf = key->lockBuffer(size); - if (key == NULL) { - key->unlockBuffer(); - m_status = ENOMEM; - return m_status; - } - int amt = read(m_fd, buf, size+1); - CHECK_SIZE(amt, (int)size+1); - key->unlockBuffer(size); - m_pos += size+1; + *key = m_key; *dataSize = m_header.entity.dataSize; - SKIP_PADDING(); return NO_ERROR; } @@ -381,42 +279,36 @@ BackupDataReader::SkipEntityData() return EINVAL; } 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; } else { return NO_ERROR; } } -status_t +ssize_t BackupDataReader::ReadEntityData(void* data, size_t size) { if (m_status != NO_ERROR) { - return m_status; + return -1; } - int amt = read(m_fd, data, size); - CHECK_SIZE(amt, (int)size); - m_pos += size; - return NO_ERROR; -} - -status_t -BackupDataReader::ReadAppFooter(int* cookie) -{ - if (m_status != NO_ERROR) { - return m_status; + int remaining = m_dataEndPos - m_pos; + //LOGD("ReadEntityData size=%d m_pos=0x%x m_dataEndPos=0x%x remaining=%d\n", + // size, m_pos, m_dataEndPos, remaining); + if (remaining <= 0) { + return 0; } - if (m_header.type != BACKUP_FOOTER_APP_V1) { - return EINVAL; + if (size > remaining) { + size = remaining; } - 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; + //LOGD(" reading %d bytes", size); + int amt = read(m_fd, data, size); + if (amt < 0) { + m_status = errno; + return -1; } - *cookie = m_header.footer.cookie; - return NO_ERROR; + m_pos += amt; + return amt; } status_t diff --git a/libs/utils/BackupHelpers.cpp b/libs/utils/BackupHelpers.cpp index 4c3e37dd1c..d65a457f39 100644 --- a/libs/utils/BackupHelpers.cpp +++ b/libs/utils/BackupHelpers.cpp @@ -47,27 +47,6 @@ namespace android { #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; -}; - -struct FileRec { - char const* file; // this object does not own this string - bool deleted; - FileState s; -}; - const static int ROUND_UP[4] = { 0, 3, 2, 1 }; static inline int @@ -310,7 +289,8 @@ back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD for (int i=0; i<fileCount; i++) { String8 key(keys[i]); FileRec r; - char const* file = r.file = files[i]; + char const* file = files[i]; + r.file = file; struct stat st; err = stat(file, &st); @@ -351,20 +331,20 @@ back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD } else if (cmp > 0) { // file added - LOGP("file added: %s", g.file); - write_update_file(dataStream, q, g.file); + LOGP("file added: %s", g.file.string()); + write_update_file(dataStream, q, g.file.string()); m++; } else { // both files exist, check them const FileState& f = oldSnapshot.valueAt(n); - int fd = open(g.file, O_RDONLY); + int fd = open(g.file.string(), O_RDONLY); if (fd < 0) { // We can't open the file. Don't report it as a delete either. Let the // server keep the old version. Maybe they'll be able to deal with it // on restore. - LOGP("Unable to open file %s - skipping", g.file); + LOGP("Unable to open file %s - skipping", g.file.string()); } else { g.s.crc32 = compute_crc32(fd); @@ -375,7 +355,7 @@ back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD g.s.modTime_sec, g.s.modTime_nsec, g.s.size, g.s.crc32); if (f.modTime_sec != g.s.modTime_sec || f.modTime_nsec != g.s.modTime_nsec || f.size != g.s.size || f.crc32 != g.s.crc32) { - write_update_file(dataStream, fd, p, g.file); + write_update_file(dataStream, fd, p, g.file.string()); } close(fd); @@ -395,7 +375,7 @@ back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD while (m<fileCount) { const String8& q = newSnapshot.keyAt(m); FileRec& g = newSnapshot.editValueAt(m); - write_update_file(dataStream, q, g.file); + write_update_file(dataStream, q, g.file.string()); m++; } @@ -404,6 +384,86 @@ back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD return 0; } +#define RESTORE_BUF_SIZE (8*1024) + +RestoreHelperBase::RestoreHelperBase() +{ + m_buf = malloc(RESTORE_BUF_SIZE); +} + +RestoreHelperBase::~RestoreHelperBase() +{ + free(m_buf); +} + +status_t +RestoreHelperBase::WriteFile(const String8& filename, BackupDataReader* in) +{ + ssize_t err; + size_t dataSize; + String8 key; + int fd; + void* buf = m_buf; + ssize_t amt; + int mode; + int crc; + struct stat st; + FileRec r; + + err = in->ReadEntityHeader(&key, &dataSize); + if (err != NO_ERROR) { + return err; + } + + // TODO: World readable/writable for now. + mode = 0666; + + // Write the file and compute the crc + crc = crc32(0L, Z_NULL, 0); + fd = open(filename.string(), O_CREAT|O_RDWR|O_TRUNC, mode); + if (fd == -1) { + LOGW("Could not open file %s -- %s", filename.string(), strerror(errno)); + return errno; + } + + while ((amt = in->ReadEntityData(buf, RESTORE_BUF_SIZE)) > 0) { + err = write(fd, buf, amt); + if (err != amt) { + close(fd); + LOGW("Error '%s' writing '%s'", strerror(errno), filename.string()); + return errno; + } + crc = crc32(crc, (Bytef*)buf, amt); + } + + close(fd); + + // Record for the snapshot + err = stat(filename.string(), &st); + if (err != 0) { + LOGW("Error stating file that we just created %s", filename.string()); + return errno; + } + + r.file = filename; + r.deleted = false; + r.s.modTime_sec = st.st_mtime; + r.s.modTime_nsec = 0; // workaround sim breakage + //r.s.modTime_nsec = st.st_mtime_nsec; + r.s.size = st.st_size; + r.s.crc32 = crc; + + m_files.add(key, r); + + return NO_ERROR; +} + +status_t +RestoreHelperBase::WriteSnapshot(int fd) +{ + return write_snapshot_file(fd, m_files);; +} + #if TEST_BACKUP_HELPERS #define SCRATCH_DIR "/data/backup_helper_test/" @@ -560,7 +620,6 @@ backup_helper_test_four() FileState states[4]; FileRec r; r.deleted = false; - r.file = NULL; states[0].modTime_sec = 0xfedcba98; states[0].modTime_nsec = 0xdeadbeef; @@ -689,41 +748,27 @@ backup_helper_test_four() // hexdump -v -e '" " 8/1 " 0x%02x," "\n"' data_writer.data 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, 0x0c, 0x00, 0x00, 0x00, 0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x00, 0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69, - 0x6e, 0x67, 0x5f, 0x00, 0x41, 0x70, 0x70, 0x31, - 0x0c, 0x00, 0x00, 0x00, 0xdd, 0xcc, 0xbb, 0xaa, + 0x6e, 0x67, 0x5f, 0x00, 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, - 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, - 0x6f, 0x5f, 0x32, 0x5f, 0x5f, 0x00, 0xbc, 0xbc, + 0x6f, 0x5f, 0x5f, 0x33, 0x00, 0xbc, 0xbc, 0xbc, 0x44, 0x61, 0x74, 0x61, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x32, 0x5f, 0x5f, 0x00, 0xbc, 0xbc, 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x32, 0x5f, - 0x5f, 0x00, 0xbc, 0xbc, 0x41, 0x70, 0x70, 0x31, - 0x0a, 0x00, 0x00, 0x00, 0xdd, 0xcc, 0xbb, 0xaa, - 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74, - 0x6f, 0x31, 0x00, 0xbc, 0x44, 0x61, 0x74, 0x61, + 0x5f, 0x00, 0xbc, 0xbc, 0x44, 0x61, 0x74, 0x61, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x31, 0x00, 0xbc, 0x70, 0x61, 0x64, 0x64, - 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x31, 0x00, 0xbc, - 0x46, 0x6f, 0x6f, 0x74, 0x04, 0x00, 0x00, 0x00, - 0x99, 0x99, 0x77, 0x77 + 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x31, 0x00 + }; const int DATA_GOLDEN_FILE_SIZE = sizeof(DATA_GOLDEN_FILE); @@ -733,12 +778,6 @@ test_write_header_and_entity(BackupDataWriter& writer, const char* str) int err; 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); if (err != 0) { fprintf(stderr, "WriteEntityHeader failed with %s\n", strerror(err)); @@ -779,8 +818,6 @@ backup_helper_test_data_writer() err |= test_write_header_and_entity(writer, "padded_to_2__"); err |= test_write_header_and_entity(writer, "padded_to1"); - writer.WriteAppFooter(0x77779999); - close(fd); err = compare_file(filename, DATA_GOLDEN_FILE, DATA_GOLDEN_FILE_SIZE); @@ -800,70 +837,59 @@ test_read_header_and_entity(BackupDataReader& reader, const char* str) String8 string; int cookie = 0x11111111; size_t actualSize; + bool done; + int type; // printf("\n\n---------- test_read_header_and_entity -- %s\n\n", str); - err = reader.ReadNextHeader(); - if (err != 0) { - fprintf(stderr, "ReadNextHeader (for app header) failed with %s\n", strerror(err)); - goto done; + err = reader.ReadNextHeader(&done, &type); + if (done) { + fprintf(stderr, "should not be done yet\n"); + goto finished; } - - err = reader.ReadAppHeader(&string, &cookie); if (err != 0) { - fprintf(stderr, "ReadAppHeader failed with %s\n", strerror(err)); - goto done; - } - if (string != str) { - fprintf(stderr, "ReadAppHeader expected packageName '%s' got '%s'\n", str, string.string()); - err = EINVAL; - goto done; + fprintf(stderr, "ReadNextHeader (for app header) failed with %s\n", strerror(err)); + goto finished; } - if (cookie != (int)0xaabbccdd) { - fprintf(stderr, "ReadAppHeader expected cookie 0x%08x got 0x%08x\n", 0xaabbccdd, cookie); + if (type != BACKUP_HEADER_ENTITY_V1) { err = EINVAL; - goto done; - } - - err = reader.ReadNextHeader(); - if (err != 0) { - fprintf(stderr, "ReadNextHeader (for entity header) failed with %s\n", strerror(err)); - goto done; + fprintf(stderr, "type=0x%08x expected 0x%08x\n", type, BACKUP_HEADER_ENTITY_V1); } err = reader.ReadEntityHeader(&string, &actualSize); if (err != 0) { fprintf(stderr, "ReadEntityHeader failed with %s\n", strerror(err)); - goto done; + goto finished; } if (string != str) { fprintf(stderr, "ReadEntityHeader expected key '%s' got '%s'\n", str, string.string()); err = EINVAL; - goto done; + goto finished; } if ((int)actualSize != bufSize) { fprintf(stderr, "ReadEntityHeader expected dataSize 0x%08x got 0x%08x\n", bufSize, actualSize); err = EINVAL; - goto done; + goto finished; } err = reader.ReadEntityData(buf, bufSize); if (err != NO_ERROR) { fprintf(stderr, "ReadEntityData failed with %s\n", strerror(err)); - goto done; + goto finished; } if (0 != memcmp(buf, str, bufSize)) { 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; - goto done; + goto finished; } // The next read will confirm whether it got the right amount of data. -done: +finished: if (err != NO_ERROR) { fprintf(stderr, "test_read_header_and_entity failed with %s\n", strerror(err)); } @@ -923,23 +949,6 @@ backup_helper_test_data_reader() if (err == NO_ERROR) { 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); |