summaryrefslogtreecommitdiff
path: root/sal/android
diff options
context:
space:
mode:
authorTor Lillqvist <tlillqvist@suse.com>2012-01-12 01:24:49 +0200
committerTor Lillqvist <tlillqvist@suse.com>2012-01-12 01:28:03 +0200
commit4a8666cc68a4659b22a6f78c04065efb7bd2a0f9 (patch)
tree885cb6e6729b4402469c3dedbd291a9e269f22a1 /sal/android
parente6a32a0d45fe4f6ad748123c6129310b0ae471b4 (diff)
Add unpacking of files from assets/unpack to the data dir
Diffstat (limited to 'sal/android')
-rw-r--r--sal/android/lo-bootstrap.c118
1 files changed, 118 insertions, 0 deletions
diff --git a/sal/android/lo-bootstrap.c b/sal/android/lo-bootstrap.c
index ad1a3e8d4d59..c827ea913ab5 100644
--- a/sal/android/lo-bootstrap.c
+++ b/sal/android/lo-bootstrap.c
@@ -71,6 +71,7 @@ struct engine {
};
static struct android_app *app;
+static const char *data_dir;
static const char **library_locations;
static void *apk_file;
static int apk_file_size;
@@ -475,6 +476,8 @@ Java_org_libreoffice_android_Bootstrap_setup__Ljava_lang_String_2Ljava_lang_Stri
dataDirPath = (*env)->GetStringUTFChars(env, dataDir, NULL);
+ data_dir = strdup(dataDirPath);
+
lib_dir = malloc(strlen(dataDirPath) + 5);
strcpy(lib_dir, dataDirPath);
strcat(lib_dir, "/lib");
@@ -1312,6 +1315,119 @@ patch_libgnustl_shared(void)
&replacement_method_before_arm);
}
+#define UNPACK_TREE "/assets/unpack"
+
+static int
+mkdir_p(const char *dirname)
+{
+ char *p = malloc(strlen(dirname) + 1);
+ const char *q = dirname + 1;
+ const char *slash;
+
+ do {
+ slash = strchr(q, '/');
+ if (slash == NULL)
+ slash = q + strlen(q);
+ memcpy(p, dirname, slash-dirname);
+ p[slash-dirname] = '\0';
+ if (mkdir(p, 0700) == -1 && errno != EEXIST) {
+ LOGE("mkdir_p: Could not create %s: %s", p, strerror(errno));
+ free(p);
+ return 0;
+ }
+ if (*slash)
+ q = slash + 1;
+ } while (*slash);
+
+ free(p);
+ return 1;
+}
+
+static void
+extract_files(const char *prefix)
+{
+ lo_apk_dir *tree = lo_apk_opendir(prefix);
+ struct dirent *dent;
+
+ if (tree == NULL)
+ return;
+
+ while ((dent = lo_apk_readdir(tree)) != NULL) {
+ if (strcmp(dent->d_name, ".") == 0 ||
+ strcmp(dent->d_name, "..") == 0)
+ continue;
+
+ if (dent->d_type == DT_DIR) {
+ char *subdir = malloc(strlen(prefix) + 1 + strlen(dent->d_name) + 1);
+ strcpy(subdir, prefix);
+ strcat(subdir, "/");
+ strcat(subdir, dent->d_name);
+ extract_files(subdir);
+ free(subdir);
+ } else {
+ char *filename;
+ char *newfilename;
+ const char *apkentry;
+ size_t size;
+ struct stat st;
+ FILE *f;
+
+ filename = malloc(strlen(prefix) + 1 + strlen(dent->d_name) + 1);
+ strcpy(filename, prefix);
+ strcat(filename, "/");
+ strcat(filename, dent->d_name);
+
+ apkentry = lo_apkentry(filename, &size);
+ if (apkentry == NULL) {
+ LOGE("extract_files: Could not find %s in .apk", newfilename);
+ free(filename);
+ continue;
+ }
+
+ newfilename = malloc(strlen(data_dir) + 1 + strlen(prefix) - sizeof(UNPACK_TREE) + 1 + strlen(dent->d_name) + 1);
+ strcpy(newfilename, data_dir);
+ strcat(newfilename, "/");
+ strcat(newfilename, prefix + sizeof(UNPACK_TREE));
+
+ if (!mkdir_p(newfilename)) {
+ free(filename);
+ free(newfilename);
+ continue;
+ }
+
+ strcat(newfilename, "/");
+ strcat(newfilename, dent->d_name);
+
+ if (stat(newfilename, &st) == 0 &&
+ st.st_size == size) {
+ free(filename);
+ free(newfilename);
+ continue;
+ }
+
+ f = fopen(newfilename, "w");
+ if (f == NULL) {
+ LOGE("extract_files: Could not open %s for writing: %s", newfilename, strerror(errno));
+ free(filename);
+ free(newfilename);
+ continue;
+ }
+
+ if (fwrite(apkentry, size, 1, f) != 1) {
+ LOGE("extract_files: Could not write %d bytes to %s: %s", size, newfilename, strerror(errno));
+ }
+
+ LOGI("extract_files: Copied %s to %s: %d bytes", filename, newfilename, size);
+
+ fclose(f);
+
+ free(filename);
+ free(newfilename);
+ }
+ }
+ lo_apk_closedir(tree);
+}
+
__attribute__ ((visibility("default")))
void
Java_org_libreoffice_android_Bootstrap_patch_libgnustl_shared(JNIEnv* env,
@@ -1352,6 +1468,8 @@ android_main(struct android_app* state)
patch_libgnustl_shared();
+ extract_files(UNPACK_TREE);
+
lo_main(lo_main_argc, lo_main_argv);
exit(0);