summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmds/keystore/commands.c170
-rw-r--r--cmds/keystore/keystore.c100
-rw-r--r--cmds/keystore/keystore.h37
-rw-r--r--include/utils/BackupHelpers.h63
-rw-r--r--libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp11
-rw-r--r--libs/utils/BackupData.cpp196
-rw-r--r--libs/utils/BackupHelpers.cpp215
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);