Installd: Refactor in preparation for OTA
Refactor installd code so reuse with a few key plugin functions is
possible. Do a bit of code cleanup.
Bug: 25612095
Change-Id: I544604f0a391583a4c07887a8234343a3a255942
diff --git a/cmds/installd/Android.mk b/cmds/installd/Android.mk
index eaeeb22..488de0f 100644
--- a/cmds/installd/Android.mk
+++ b/cmds/installd/Android.mk
@@ -1,6 +1,6 @@
LOCAL_PATH := $(call my-dir)
-common_src_files := commands.cpp utils.cpp
+common_src_files := commands.cpp globals.cpp utils.cpp
common_cflags := -Wall -Werror
#
@@ -41,3 +41,7 @@
LOCAL_INIT_RC := installd.rc
LOCAL_CLANG := true
include $(BUILD_EXECUTABLE)
+
+# Tests.
+
+include $(LOCAL_PATH)/tests/Android.mk
\ No newline at end of file
diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
index 3b2a086..7544e4d 100644
--- a/cmds/installd/commands.cpp
+++ b/cmds/installd/commands.cpp
@@ -14,33 +14,40 @@
** limitations under the License.
*/
-#include "installd.h"
+#include "commands.h"
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <sys/capability.h>
+#include <sys/file.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <unistd.h>
#include <android-base/stringprintf.h>
#include <android-base/logging.h>
+#include <cutils/fs.h>
+#include <cutils/log.h> // TODO: Move everything to base/logging.
#include <cutils/sched_policy.h>
#include <diskusage/dirsize.h>
#include <logwrap/logwrap.h>
-#include <system/thread_defs.h>
+#include <private/android_filesystem_config.h>
#include <selinux/android.h>
+#include <system/thread_defs.h>
-#include <inttypes.h>
-#include <sys/capability.h>
-#include <sys/file.h>
-#include <unistd.h>
+#include <globals.h>
+#include <installd_deps.h>
+#include <utils.h>
+
+#ifndef LOG_TAG
+#define LOG_TAG "installd"
+#endif
using android::base::StringPrintf;
-/* Directory records that are used in execution of commands. */
-dir_rec_t android_data_dir;
-dir_rec_t android_asec_dir;
-dir_rec_t android_app_dir;
-dir_rec_t android_app_private_dir;
-dir_rec_t android_app_ephemeral_dir;
-dir_rec_t android_app_lib_dir;
-dir_rec_t android_media_dir;
-dir_rec_t android_mnt_expand_dir;
-dir_rec_array_t android_system_dirs;
+namespace android {
+namespace installd {
static const char* kCpPath = "/system/bin/cp";
@@ -420,8 +427,8 @@
return -1;
}
- if (create_cache_path(src_dex, src, instruction_set)) return -1;
- if (create_cache_path(dst_dex, dst, instruction_set)) return -1;
+ if (!create_cache_path(src_dex, src, instruction_set)) return -1;
+ if (!create_cache_path(dst_dex, dst, instruction_set)) return -1;
ALOGV("move %s -> %s\n", src_dex, dst_dex);
if (rename(src_dex, dst_dex) < 0) {
@@ -441,7 +448,7 @@
return -1;
}
- if (create_cache_path(dex_path, path, instruction_set)) return -1;
+ if (!create_cache_path(dex_path, path, instruction_set)) return -1;
ALOGV("unlink %s\n", dex_path);
if (unlink(dex_path) < 0) {
@@ -495,7 +502,7 @@
}
/* count the cached dexfile as code */
- if (!create_cache_path(path, apkpath, instruction_set)) {
+ if (create_cache_path(path, apkpath, instruction_set)) {
if (stat(path, &s) == 0) {
codesize += stat_size(&s);
}
@@ -589,51 +596,11 @@
return 0;
}
-int create_cache_path(char path[PKG_PATH_MAX], const char *src, const char *instruction_set)
-{
- char *tmp;
- int srclen;
- int dstlen;
-
- srclen = strlen(src);
-
- /* demand that we are an absolute path */
- if ((src == 0) || (src[0] != '/') || strstr(src,"..")) {
- return -1;
- }
-
- if (srclen > PKG_PATH_MAX) { // XXX: PKG_NAME_MAX?
- return -1;
- }
-
- dstlen = srclen + strlen(DALVIK_CACHE_PREFIX) +
- strlen(instruction_set) +
- strlen(DALVIK_CACHE_POSTFIX) + 2;
-
- if (dstlen > PKG_PATH_MAX) {
- return -1;
- }
-
- sprintf(path,"%s%s/%s%s",
- DALVIK_CACHE_PREFIX,
- instruction_set,
- src + 1, /* skip the leading / */
- DALVIK_CACHE_POSTFIX);
-
- for(tmp = path + strlen(DALVIK_CACHE_PREFIX) + strlen(instruction_set) + 1; *tmp; tmp++) {
- if (*tmp == '/') {
- *tmp = '@';
- }
- }
-
- return 0;
-}
-
static int split_count(const char *str)
{
char *ctx;
int count = 0;
- char buf[PROPERTY_VALUE_MAX];
+ char buf[kPropertyValueMax];
strncpy(buf, str, sizeof(buf));
char *pBuf = buf;
@@ -662,7 +629,7 @@
}
static void run_patchoat(int input_fd, int oat_fd, const char* input_file_name,
- const char* output_file_name, const char *pkgname __unused, const char *instruction_set)
+ const char* output_file_name, const char *pkgname ATTRIBUTE_UNUSED, const char *instruction_set)
{
static const int MAX_INT_LEN = 12; // '-'+10dig+'\0' -OR- 0x+8dig
static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
@@ -702,8 +669,8 @@
}
static bool check_boolean_property(const char* property_name, bool default_value = false) {
- char tmp_property_value[PROPERTY_VALUE_MAX];
- bool have_property = property_get(property_name, tmp_property_value, nullptr) > 0;
+ char tmp_property_value[kPropertyValueMax];
+ bool have_property = get_property(property_name, tmp_property_value, nullptr) > 0;
if (!have_property) {
return default_value;
}
@@ -722,50 +689,50 @@
return;
}
- char dex2oat_Xms_flag[PROPERTY_VALUE_MAX];
- bool have_dex2oat_Xms_flag = property_get("dalvik.vm.dex2oat-Xms", dex2oat_Xms_flag, NULL) > 0;
+ char dex2oat_Xms_flag[kPropertyValueMax];
+ bool have_dex2oat_Xms_flag = get_property("dalvik.vm.dex2oat-Xms", dex2oat_Xms_flag, NULL) > 0;
- char dex2oat_Xmx_flag[PROPERTY_VALUE_MAX];
- bool have_dex2oat_Xmx_flag = property_get("dalvik.vm.dex2oat-Xmx", dex2oat_Xmx_flag, NULL) > 0;
+ char dex2oat_Xmx_flag[kPropertyValueMax];
+ bool have_dex2oat_Xmx_flag = get_property("dalvik.vm.dex2oat-Xmx", dex2oat_Xmx_flag, NULL) > 0;
- char dex2oat_compiler_filter_flag[PROPERTY_VALUE_MAX];
- bool have_dex2oat_compiler_filter_flag = property_get("dalvik.vm.dex2oat-filter",
+ char dex2oat_compiler_filter_flag[kPropertyValueMax];
+ bool have_dex2oat_compiler_filter_flag = get_property("dalvik.vm.dex2oat-filter",
dex2oat_compiler_filter_flag, NULL) > 0;
- char dex2oat_threads_buf[PROPERTY_VALUE_MAX];
- bool have_dex2oat_threads_flag = property_get(post_bootcomplete
+ char dex2oat_threads_buf[kPropertyValueMax];
+ bool have_dex2oat_threads_flag = get_property(post_bootcomplete
? "dalvik.vm.dex2oat-threads"
: "dalvik.vm.boot-dex2oat-threads",
dex2oat_threads_buf,
NULL) > 0;
- char dex2oat_threads_arg[PROPERTY_VALUE_MAX + 2];
+ char dex2oat_threads_arg[kPropertyValueMax + 2];
if (have_dex2oat_threads_flag) {
sprintf(dex2oat_threads_arg, "-j%s", dex2oat_threads_buf);
}
- char dex2oat_isa_features_key[PROPERTY_KEY_MAX];
+ char dex2oat_isa_features_key[kPropertyKeyMax];
sprintf(dex2oat_isa_features_key, "dalvik.vm.isa.%s.features", instruction_set);
- char dex2oat_isa_features[PROPERTY_VALUE_MAX];
- bool have_dex2oat_isa_features = property_get(dex2oat_isa_features_key,
+ char dex2oat_isa_features[kPropertyValueMax];
+ bool have_dex2oat_isa_features = get_property(dex2oat_isa_features_key,
dex2oat_isa_features, NULL) > 0;
- char dex2oat_isa_variant_key[PROPERTY_KEY_MAX];
+ char dex2oat_isa_variant_key[kPropertyKeyMax];
sprintf(dex2oat_isa_variant_key, "dalvik.vm.isa.%s.variant", instruction_set);
- char dex2oat_isa_variant[PROPERTY_VALUE_MAX];
- bool have_dex2oat_isa_variant = property_get(dex2oat_isa_variant_key,
+ char dex2oat_isa_variant[kPropertyValueMax];
+ bool have_dex2oat_isa_variant = get_property(dex2oat_isa_variant_key,
dex2oat_isa_variant, NULL) > 0;
const char *dex2oat_norelocation = "-Xnorelocate";
bool have_dex2oat_relocation_skip_flag = false;
- char dex2oat_flags[PROPERTY_VALUE_MAX];
- int dex2oat_flags_count = property_get("dalvik.vm.dex2oat-flags",
+ char dex2oat_flags[kPropertyValueMax];
+ int dex2oat_flags_count = get_property("dalvik.vm.dex2oat-flags",
dex2oat_flags, NULL) <= 0 ? 0 : split_count(dex2oat_flags);
ALOGV("dalvik.vm.dex2oat-flags=%s\n", dex2oat_flags);
// If we booting without the real /data, don't spend time compiling.
- char vold_decrypt[PROPERTY_VALUE_MAX];
- bool have_vold_decrypt = property_get("vold.decrypt", vold_decrypt, "") > 0;
+ char vold_decrypt[kPropertyValueMax];
+ bool have_vold_decrypt = get_property("vold.decrypt", vold_decrypt, "") > 0;
bool skip_compilation = (have_vold_decrypt &&
(strcmp(vold_decrypt, "trigger_restart_min_framework") == 0 ||
(strcmp(vold_decrypt, "1") == 0)));
@@ -783,11 +750,11 @@
char oat_fd_arg[strlen("--oat-fd=") + MAX_INT_LEN];
char oat_location_arg[strlen("--oat-location=") + PKG_PATH_MAX];
char instruction_set_arg[strlen("--instruction-set=") + MAX_INSTRUCTION_SET_LEN];
- char instruction_set_variant_arg[strlen("--instruction-set-variant=") + PROPERTY_VALUE_MAX];
- char instruction_set_features_arg[strlen("--instruction-set-features=") + PROPERTY_VALUE_MAX];
- char dex2oat_Xms_arg[strlen("-Xms") + PROPERTY_VALUE_MAX];
- char dex2oat_Xmx_arg[strlen("-Xmx") + PROPERTY_VALUE_MAX];
- char dex2oat_compiler_filter_arg[strlen("--compiler-filter=") + PROPERTY_VALUE_MAX];
+ char instruction_set_variant_arg[strlen("--instruction-set-variant=") + kPropertyValueMax];
+ char instruction_set_features_arg[strlen("--instruction-set-features=") + kPropertyValueMax];
+ char dex2oat_Xms_arg[strlen("-Xms") + kPropertyValueMax];
+ char dex2oat_Xmx_arg[strlen("-Xmx") + kPropertyValueMax];
+ char dex2oat_compiler_filter_arg[strlen("--compiler-filter=") + kPropertyValueMax];
bool have_dex2oat_swap_fd = false;
char dex2oat_swap_fd[strlen("--swap-fd=") + MAX_INT_LEN];
@@ -827,9 +794,9 @@
// Check whether all apps should be compiled debuggable.
if (!debuggable) {
- char prop_buf[PROPERTY_VALUE_MAX];
+ char prop_buf[kPropertyValueMax];
debuggable =
- (property_get("dalvik.vm.always_debuggable", prop_buf, "0") > 0) &&
+ (get_property("dalvik.vm.always_debuggable", prop_buf, "0") > 0) &&
(prop_buf[0] == '1');
}
@@ -897,32 +864,6 @@
ALOGE("execv(%s) failed: %s\n", DEX2OAT_BIN, strerror(errno));
}
-static int wait_child(pid_t pid)
-{
- int status;
- pid_t got_pid;
-
- while (1) {
- got_pid = waitpid(pid, &status, 0);
- if (got_pid == -1 && errno == EINTR) {
- printf("waitpid interrupted, retrying\n");
- } else {
- break;
- }
- }
- if (got_pid != pid) {
- ALOGW("waitpid failed: wanted %d, got %d: %s\n",
- (int) pid, (int) got_pid, strerror(errno));
- return 1;
- }
-
- if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
- return 0;
- } else {
- return status; /* always nonzero */
- }
-}
-
/*
* Whether dexopt should use a swap file when compiling an APK.
*
@@ -944,8 +885,8 @@
}
// Check the "override" property. If it exists, return value == "true".
- char dex2oat_prop_buf[PROPERTY_VALUE_MAX];
- if (property_get("dalvik.vm.dex2oat-swap", dex2oat_prop_buf, "") > 0) {
+ char dex2oat_prop_buf[kPropertyValueMax];
+ if (get_property("dalvik.vm.dex2oat-swap", dex2oat_prop_buf, "") > 0) {
if (strcmp(dex2oat_prop_buf, "true") == 0) {
return true;
} else {
@@ -969,42 +910,6 @@
return kDefaultProvideSwapFile;
}
-/*
- * Computes the odex file for the given apk_path and instruction_set.
- * /system/framework/whatever.jar -> /system/framework/oat/<isa>/whatever.odex
- *
- * Returns false if it failed to determine the odex file path.
- */
-static bool calculate_odex_file_path(char path[PKG_PATH_MAX],
- const char *apk_path,
- const char *instruction_set)
-{
- if (strlen(apk_path) + strlen("oat/") + strlen(instruction_set)
- + strlen("/") + strlen("odex") + 1 > PKG_PATH_MAX) {
- ALOGE("apk_path '%s' may be too long to form odex file path.\n", apk_path);
- return false;
- }
-
- strcpy(path, apk_path);
- char *end = strrchr(path, '/');
- if (end == NULL) {
- ALOGE("apk_path '%s' has no '/'s in it?!\n", apk_path);
- return false;
- }
- const char *apk_end = apk_path + (end - path); // strrchr(apk_path, '/');
-
- strcpy(end + 1, "oat/"); // path = /system/framework/oat/\0
- strcat(path, instruction_set); // path = /system/framework/oat/<isa>\0
- strcat(path, apk_end); // path = /system/framework/oat/<isa>/whatever.jar\0
- end = strrchr(path, '.');
- if (end == NULL) {
- ALOGE("apk_path '%s' has no extension.\n", apk_path);
- return false;
- }
- strcpy(end + 1, "odex");
- return true;
-}
-
static void SetDex2OatAndPatchOatScheduling(bool set_to_bg) {
if (set_to_bg) {
if (set_sched_policy(0, SP_BACKGROUND) < 0) {
@@ -1051,11 +956,11 @@
ALOGE("invalid oat_dir '%s'\n", oat_dir);
return -1;
}
- if (calculate_oat_file_path(out_path, oat_dir, apk_path, instruction_set)) {
+ if (!calculate_oat_file_path(out_path, oat_dir, apk_path, instruction_set)) {
return -1;
}
} else {
- if (create_cache_path(out_path, apk_path, instruction_set)) {
+ if (!create_cache_path(out_path, apk_path, instruction_set)) {
return -1;
}
}
@@ -1212,7 +1117,11 @@
int mark_boot_complete(const char* instruction_set)
{
char boot_marker_path[PKG_PATH_MAX];
- sprintf(boot_marker_path,"%s%s/.booting", DALVIK_CACHE_PREFIX, instruction_set);
+ sprintf(boot_marker_path,
+ "%s/%s/%s/.booting",
+ android_data_dir.path,
+ DALVIK_CACHE,
+ instruction_set);
ALOGV("mark_boot_complete : %s", boot_marker_path);
if (unlink(boot_marker_path) != 0) {
@@ -1750,29 +1659,5 @@
return 0;
}
-int calculate_oat_file_path(char path[PKG_PATH_MAX], const char *oat_dir, const char *apk_path,
- const char *instruction_set) {
- char *file_name_start;
- char *file_name_end;
-
- file_name_start = strrchr(apk_path, '/');
- if (file_name_start == NULL) {
- ALOGE("apk_path '%s' has no '/'s in it\n", apk_path);
- return -1;
- }
- file_name_end = strrchr(apk_path, '.');
- if (file_name_end < file_name_start) {
- ALOGE("apk_path '%s' has no extension\n", apk_path);
- return -1;
- }
-
- // Calculate file_name
- int file_name_len = file_name_end - file_name_start - 1;
- char file_name[file_name_len + 1];
- memcpy(file_name, file_name_start + 1, file_name_len);
- file_name[file_name_len] = '\0';
-
- // <apk_parent_dir>/oat/<isa>/<file_name>.odex
- snprintf(path, PKG_PATH_MAX, "%s/%s/%s.odex", oat_dir, instruction_set, file_name);
- return 0;
-}
+} // namespace installd
+} // namespace android
diff --git a/cmds/installd/commands.h b/cmds/installd/commands.h
new file mode 100644
index 0000000..55a6e62
--- /dev/null
+++ b/cmds/installd/commands.h
@@ -0,0 +1,70 @@
+/*
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef COMMANDS_H_
+#define COMMANDS_H_
+
+#include <inttypes.h>
+#include <unistd.h>
+
+#include <cutils/multiuser.h>
+
+#include <installd_constants.h>
+
+namespace android {
+namespace installd {
+
+int install(const char *uuid, const char *pkgname, uid_t uid, gid_t gid, const char *seinfo);
+int uninstall(const char *uuid, const char *pkgname, userid_t userid);
+int renamepkg(const char *oldpkgname, const char *newpkgname);
+int fix_uid(const char *uuid, const char *pkgname, uid_t uid, gid_t gid);
+int delete_user_data(const char *uuid, const char *pkgname, userid_t userid);
+int make_user_data(const char *uuid, const char *pkgname, uid_t uid,
+ userid_t userid, const char* seinfo);
+int copy_complete_app(const char* from_uuid, const char *to_uuid,
+ const char *package_name, const char *data_app_name, appid_t appid,
+ const char* seinfo);
+int make_user_config(userid_t userid);
+int delete_user(const char *uuid, userid_t userid);
+int delete_cache(const char *uuid, const char *pkgname, userid_t userid);
+int delete_code_cache(const char *uuid, const char *pkgname, userid_t userid);
+int move_dex(const char *src, const char *dst, const char *instruction_set);
+int rm_dex(const char *path, const char *instruction_set);
+int protect(char *pkgname, gid_t gid);
+int get_size(const char *uuid, const char *pkgname, int userid,
+ const char *apkpath, const char *libdirpath,
+ const char *fwdlock_apkpath, const char *asecpath,
+ const char *instruction_set, int64_t *codesize, int64_t *datasize,
+ int64_t *cachesize, int64_t *asecsize);
+int free_cache(const char *uuid, int64_t free_size);
+int dexopt(const char *apk_path, uid_t uid, const char *pkgName, const char *instruction_set,
+ int dexopt_needed, const char* oat_dir, int dexopt_flags);
+int mark_boot_complete(const char *instruction_set);
+int movefiles();
+int linklib(const char* uuid, const char* pkgname, const char* asecLibDir, int userId);
+int idmap(const char *target_path, const char *overlay_path, uid_t uid);
+int restorecon_data(const char *uuid, const char* pkgName, const char* seinfo, uid_t uid);
+int create_oat_dir(const char* oat_dir, const char *instruction_set);
+int rm_package_dir(const char* apk_path);
+int move_package_dir(char path[PKG_PATH_MAX], const char *oat_dir, const char *apk_path,
+ const char *instruction_set);
+int link_file(const char *relative_path, const char *from_base, const char *to_base);
+
+} // namespace installd
+} // namespace android
+
+#endif // COMMANDS_H_
diff --git a/cmds/installd/globals.cpp b/cmds/installd/globals.cpp
new file mode 100644
index 0000000..bee2790
--- /dev/null
+++ b/cmds/installd/globals.cpp
@@ -0,0 +1,132 @@
+/*
+** Copyright 2015, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <cutils/log.h> // TODO: Move everything to base::logging.
+
+#include <globals.h>
+#include <installd_constants.h>
+#include <utils.h>
+
+#ifndef LOG_TAG
+#define LOG_TAG "installd"
+#endif
+
+namespace android {
+namespace installd {
+
+/* Directory records that are used in execution of commands. */
+dir_rec_t android_app_dir;
+dir_rec_t android_app_ephemeral_dir;
+dir_rec_t android_app_lib_dir;
+dir_rec_t android_app_private_dir;
+dir_rec_t android_asec_dir;
+dir_rec_t android_data_dir;
+dir_rec_t android_media_dir;
+dir_rec_t android_mnt_expand_dir;
+
+dir_rec_array_t android_system_dirs;
+
+/**
+ * Initialize all the global variables that are used elsewhere. Returns 0 upon
+ * success and -1 on error.
+ */
+void free_globals() {
+ size_t i;
+
+ for (i = 0; i < android_system_dirs.count; i++) {
+ if (android_system_dirs.dirs[i].path != NULL) {
+ free(android_system_dirs.dirs[i].path);
+ }
+ }
+
+ free(android_system_dirs.dirs);
+}
+
+bool init_globals_from_data_and_root(const char* data, const char* root) {
+ // Get the android data directory.
+ if (get_path_from_string(&android_data_dir, data) < 0) {
+ return false;
+ }
+
+ // Get the android app directory.
+ if (copy_and_append(&android_app_dir, &android_data_dir, APP_SUBDIR) < 0) {
+ return false;
+ }
+
+ // Get the android protected app directory.
+ if (copy_and_append(&android_app_private_dir, &android_data_dir, PRIVATE_APP_SUBDIR) < 0) {
+ return false;
+ }
+
+ // Get the android ephemeral app directory.
+ if (copy_and_append(&android_app_ephemeral_dir, &android_data_dir, EPHEMERAL_APP_SUBDIR) < 0) {
+ return -1;
+ }
+
+ // Get the android app native library directory.
+ if (copy_and_append(&android_app_lib_dir, &android_data_dir, APP_LIB_SUBDIR) < 0) {
+ return false;
+ }
+
+ // Get the sd-card ASEC mount point.
+ if (get_path_from_env(&android_asec_dir, "ASEC_MOUNTPOINT") < 0) {
+ return false;
+ }
+
+ // Get the android media directory.
+ if (copy_and_append(&android_media_dir, &android_data_dir, MEDIA_SUBDIR) < 0) {
+ return false;
+ }
+
+ // Get the android external app directory.
+ if (get_path_from_string(&android_mnt_expand_dir, "/mnt/expand/") < 0) {
+ return false;
+ }
+
+ // Take note of the system and vendor directories.
+ android_system_dirs.count = 4;
+
+ android_system_dirs.dirs = (dir_rec_t*) calloc(android_system_dirs.count, sizeof(dir_rec_t));
+ if (android_system_dirs.dirs == NULL) {
+ ALOGE("Couldn't allocate array for dirs; aborting\n");
+ return false;
+ }
+
+ dir_rec_t android_root_dir;
+ if (get_path_from_string(&android_root_dir, root) < 0) {
+ return false;
+ }
+
+ android_system_dirs.dirs[0].path = build_string2(android_root_dir.path, APP_SUBDIR);
+ android_system_dirs.dirs[0].len = strlen(android_system_dirs.dirs[0].path);
+
+ android_system_dirs.dirs[1].path = build_string2(android_root_dir.path, PRIV_APP_SUBDIR);
+ android_system_dirs.dirs[1].len = strlen(android_system_dirs.dirs[1].path);
+
+ android_system_dirs.dirs[2].path = strdup("/vendor/app/");
+ android_system_dirs.dirs[2].len = strlen(android_system_dirs.dirs[2].path);
+
+ android_system_dirs.dirs[3].path = strdup("/oem/app/");
+ android_system_dirs.dirs[3].len = strlen(android_system_dirs.dirs[3].path);
+
+ return true;
+}
+
+} // namespace installd
+} // namespace android
diff --git a/cmds/installd/globals.h b/cmds/installd/globals.h
new file mode 100644
index 0000000..2e61f85
--- /dev/null
+++ b/cmds/installd/globals.h
@@ -0,0 +1,55 @@
+/*
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef GLOBALS_H_
+#define GLOBALS_H_
+
+#include <inttypes.h>
+
+namespace android {
+namespace installd {
+
+/* data structures */
+
+struct dir_rec_t {
+ char* path;
+ size_t len;
+};
+
+struct dir_rec_array_t {
+ size_t count;
+ dir_rec_t* dirs;
+};
+
+extern dir_rec_t android_app_dir;
+extern dir_rec_t android_app_ephemeral_dir;
+extern dir_rec_t android_app_lib_dir;
+extern dir_rec_t android_app_private_dir;
+extern dir_rec_t android_asec_dir;
+extern dir_rec_t android_data_dir;
+extern dir_rec_t android_media_dir;
+extern dir_rec_t android_mnt_expand_dir;
+
+extern dir_rec_array_t android_system_dirs;
+
+void free_globals();
+bool init_globals_from_data_and_root(const char* data, const char* root);
+
+} // namespace installd
+} // namespace android
+
+#endif // GLOBALS_H_
diff --git a/cmds/installd/installd.cpp b/cmds/installd/installd.cpp
index a7202b6..17ae521 100644
--- a/cmds/installd/installd.cpp
+++ b/cmds/installd/installd.cpp
@@ -14,19 +14,167 @@
** limitations under the License.
*/
-#include "installd.h"
-
-#include <android-base/logging.h>
-
-#include <sys/capability.h>
-#include <sys/prctl.h>
+#include <fcntl.h>
#include <selinux/android.h>
#include <selinux/avc.h>
+#include <sys/capability.h>
+#include <sys/prctl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+
+#include <android-base/logging.h>
+#include <cutils/fs.h>
+#include <cutils/log.h> // TODO: Move everything to base::logging.
+#include <cutils/properties.h>
+#include <cutils/sockets.h>
+#include <private/android_filesystem_config.h>
+
+#include <commands.h>
+#include <globals.h>
+#include <installd_constants.h>
+#include <installd_deps.h> // Need to fill in requirements of commands.
+#include <utils.h>
+
+#ifndef LOG_TAG
+#define LOG_TAG "installd"
+#endif
+#define SOCKET_PATH "installd"
#define BUFFER_MAX 1024 /* input buffer for commands */
#define TOKEN_MAX 16 /* max number of arguments in buffer */
#define REPLY_MAX 256 /* largest reply allowed */
+
+namespace android {
+namespace installd {
+
+// Check that installd-deps sizes match cutils sizes.
+static_assert(kPropertyKeyMax == PROPERTY_KEY_MAX, "Size mismatch.");
+static_assert(kPropertyValueMax == PROPERTY_VALUE_MAX, "Size mismatch.");
+
+////////////////////////
+// Plug-in functions. //
+////////////////////////
+
+int get_property(const char *key, char *value, const char *default_value) {
+ return property_get(key, value, default_value);
+}
+
+// Compute the output path of
+bool calculate_oat_file_path(char path[PKG_PATH_MAX],
+ const char *oat_dir,
+ const char *apk_path,
+ const char *instruction_set) {
+ char *file_name_start;
+ char *file_name_end;
+
+ file_name_start = strrchr(apk_path, '/');
+ if (file_name_start == NULL) {
+ ALOGE("apk_path '%s' has no '/'s in it\n", apk_path);
+ return false;
+ }
+ file_name_end = strrchr(apk_path, '.');
+ if (file_name_end < file_name_start) {
+ ALOGE("apk_path '%s' has no extension\n", apk_path);
+ return false;
+ }
+
+ // Calculate file_name
+ int file_name_len = file_name_end - file_name_start - 1;
+ char file_name[file_name_len + 1];
+ memcpy(file_name, file_name_start + 1, file_name_len);
+ file_name[file_name_len] = '\0';
+
+ // <apk_parent_dir>/oat/<isa>/<file_name>.odex
+ snprintf(path, PKG_PATH_MAX, "%s/%s/%s.odex", oat_dir, instruction_set, file_name);
+ return true;
+}
+
+/*
+ * Computes the odex file for the given apk_path and instruction_set.
+ * /system/framework/whatever.jar -> /system/framework/oat/<isa>/whatever.odex
+ *
+ * Returns false if it failed to determine the odex file path.
+ */
+bool calculate_odex_file_path(char path[PKG_PATH_MAX],
+ const char *apk_path,
+ const char *instruction_set) {
+ if (strlen(apk_path) + strlen("oat/") + strlen(instruction_set)
+ + strlen("/") + strlen("odex") + 1 > PKG_PATH_MAX) {
+ ALOGE("apk_path '%s' may be too long to form odex file path.\n", apk_path);
+ return false;
+ }
+
+ strcpy(path, apk_path);
+ char *end = strrchr(path, '/');
+ if (end == NULL) {
+ ALOGE("apk_path '%s' has no '/'s in it?!\n", apk_path);
+ return false;
+ }
+ const char *apk_end = apk_path + (end - path); // strrchr(apk_path, '/');
+
+ strcpy(end + 1, "oat/"); // path = /system/framework/oat/\0
+ strcat(path, instruction_set); // path = /system/framework/oat/<isa>\0
+ strcat(path, apk_end); // path = /system/framework/oat/<isa>/whatever.jar\0
+ end = strrchr(path, '.');
+ if (end == NULL) {
+ ALOGE("apk_path '%s' has no extension.\n", apk_path);
+ return false;
+ }
+ strcpy(end + 1, "odex");
+ return true;
+}
+
+bool create_cache_path(char path[PKG_PATH_MAX],
+ const char *src,
+ const char *instruction_set) {
+ size_t srclen = strlen(src);
+
+ /* demand that we are an absolute path */
+ if ((src == 0) || (src[0] != '/') || strstr(src,"..")) {
+ return false;
+ }
+
+ if (srclen > PKG_PATH_MAX) { // XXX: PKG_NAME_MAX?
+ return false;
+ }
+
+ size_t dstlen =
+ android_data_dir.len +
+ strlen(DALVIK_CACHE) +
+ 1 +
+ strlen(instruction_set) +
+ srclen +
+ strlen(DALVIK_CACHE_POSTFIX) + 2;
+
+ if (dstlen > PKG_PATH_MAX) {
+ return false;
+ }
+
+ sprintf(path,"%s%s/%s/%s%s",
+ android_data_dir.path,
+ DALVIK_CACHE,
+ instruction_set,
+ src + 1, /* skip the leading / */
+ DALVIK_CACHE_POSTFIX);
+
+ char* tmp =
+ path +
+ android_data_dir.len +
+ strlen(DALVIK_CACHE) +
+ 1 +
+ strlen(instruction_set) + 1;
+
+ for(; *tmp; tmp++) {
+ if (*tmp == '/') {
+ *tmp = '@';
+ }
+ }
+
+ return true;
+}
+
+
static char* parse_null(char* arg) {
if (strcmp(arg, "!") == 0) {
return nullptr;
@@ -35,59 +183,59 @@
}
}
-static int do_ping(char **arg __unused, char reply[REPLY_MAX] __unused)
+static int do_ping(char **arg ATTRIBUTE_UNUSED, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
{
return 0;
}
-static int do_install(char **arg, char reply[REPLY_MAX] __unused)
+static int do_install(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
{
return install(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), arg[4]); /* uuid, pkgname, uid, gid, seinfo */
}
-static int do_dexopt(char **arg, char reply[REPLY_MAX] __unused)
+static int do_dexopt(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
{
/* apk_path, uid, pkgname, instruction_set, dexopt_needed, oat_dir, dexopt_flags */
return dexopt(arg[0], atoi(arg[1]), arg[2], arg[3], atoi(arg[4]),
arg[5], atoi(arg[6]));
}
-static int do_mark_boot_complete(char **arg, char reply[REPLY_MAX] __unused)
+static int do_mark_boot_complete(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
{
return mark_boot_complete(arg[0] /* instruction set */);
}
-static int do_move_dex(char **arg, char reply[REPLY_MAX] __unused)
+static int do_move_dex(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
{
return move_dex(arg[0], arg[1], arg[2]); /* src, dst, instruction_set */
}
-static int do_rm_dex(char **arg, char reply[REPLY_MAX] __unused)
+static int do_rm_dex(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
{
return rm_dex(arg[0], arg[1]); /* pkgname, instruction_set */
}
-static int do_remove(char **arg, char reply[REPLY_MAX] __unused)
+static int do_remove(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
{
return uninstall(parse_null(arg[0]), arg[1], atoi(arg[2])); /* uuid, pkgname, userid */
}
-static int do_fixuid(char **arg, char reply[REPLY_MAX] __unused)
+static int do_fixuid(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
{
return fix_uid(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3])); /* uuid, pkgname, uid, gid */
}
-static int do_free_cache(char **arg, char reply[REPLY_MAX] __unused) /* TODO int:free_size */
+static int do_free_cache(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) /* TODO int:free_size */
{
return free_cache(parse_null(arg[0]), (int64_t)atoll(arg[1])); /* uuid, free_size */
}
-static int do_rm_cache(char **arg, char reply[REPLY_MAX] __unused)
+static int do_rm_cache(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
{
return delete_cache(parse_null(arg[0]), arg[1], atoi(arg[2])); /* uuid, pkgname, userid */
}
-static int do_rm_code_cache(char **arg, char reply[REPLY_MAX] __unused)
+static int do_rm_code_cache(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
{
return delete_code_cache(parse_null(arg[0]), arg[1], atoi(arg[2])); /* uuid, pkgname, userid */
}
@@ -113,67 +261,67 @@
return res;
}
-static int do_rm_user_data(char **arg, char reply[REPLY_MAX] __unused)
+static int do_rm_user_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
{
return delete_user_data(parse_null(arg[0]), arg[1], atoi(arg[2])); /* uuid, pkgname, userid */
}
-static int do_cp_complete_app(char **arg, char reply[REPLY_MAX] __unused)
+static int do_cp_complete_app(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
{
// from_uuid, to_uuid, package_name, data_app_name, appid, seinfo
return copy_complete_app(parse_null(arg[0]), parse_null(arg[1]), arg[2], arg[3], atoi(arg[4]), arg[5]);
}
-static int do_mk_user_data(char **arg, char reply[REPLY_MAX] __unused)
+static int do_mk_user_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
{
return make_user_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), arg[4]);
/* uuid, pkgname, uid, userid, seinfo */
}
-static int do_mk_user_config(char **arg, char reply[REPLY_MAX] __unused)
+static int do_mk_user_config(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
{
return make_user_config(atoi(arg[0])); /* userid */
}
-static int do_rm_user(char **arg, char reply[REPLY_MAX] __unused)
+static int do_rm_user(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
{
return delete_user(parse_null(arg[0]), atoi(arg[1])); /* uuid, userid */
}
-static int do_movefiles(char **arg __unused, char reply[REPLY_MAX] __unused)
+static int do_movefiles(char **arg ATTRIBUTE_UNUSED, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
{
return movefiles();
}
-static int do_linklib(char **arg, char reply[REPLY_MAX] __unused)
+static int do_linklib(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
{
return linklib(parse_null(arg[0]), arg[1], arg[2], atoi(arg[3]));
}
-static int do_idmap(char **arg, char reply[REPLY_MAX] __unused)
+static int do_idmap(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
{
return idmap(arg[0], arg[1], atoi(arg[2]));
}
-static int do_restorecon_data(char **arg, char reply[REPLY_MAX] __attribute__((unused)))
+static int do_restorecon_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
{
return restorecon_data(parse_null(arg[0]), arg[1], arg[2], atoi(arg[3]));
/* uuid, pkgName, seinfo, uid*/
}
-static int do_create_oat_dir(char **arg, char reply[REPLY_MAX] __unused)
+static int do_create_oat_dir(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
{
/* oat_dir, instruction_set */
return create_oat_dir(arg[0], arg[1]);
}
-static int do_rm_package_dir(char **arg, char reply[REPLY_MAX] __unused)
+static int do_rm_package_dir(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
{
/* oat_dir */
return rm_package_dir(arg[0]);
}
-static int do_link_file(char **arg, char reply[REPLY_MAX] __unused)
+static int do_link_file(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
{
/* relative_path, from_base, to_base */
return link_file(arg[0], arg[1], arg[2]);
@@ -314,97 +462,22 @@
return 0;
}
-/**
- * Initialize all the global variables that are used elsewhere. Returns 0 upon
- * success and -1 on error.
- */
-void free_globals() {
- size_t i;
-
- for (i = 0; i < android_system_dirs.count; i++) {
- if (android_system_dirs.dirs[i].path != NULL) {
- free(android_system_dirs.dirs[i].path);
- }
+bool initialize_globals() {
+ const char* data_path = getenv("ANDROID_DATA");
+ if (data_path == nullptr) {
+ ALOGE("Could not find ANDROID_DATA");
+ return false;
+ }
+ const char* root_path = getenv("ANDROID_ROOT");
+ if (root_path == nullptr) {
+ ALOGE("Could not find ANDROID_ROOT");
+ return false;
}
- free(android_system_dirs.dirs);
+ return init_globals_from_data_and_root(data_path, root_path);
}
-int initialize_globals() {
- // Get the android data directory.
- if (get_path_from_env(&android_data_dir, "ANDROID_DATA") < 0) {
- return -1;
- }
-
- // Get the android app directory.
- if (copy_and_append(&android_app_dir, &android_data_dir, APP_SUBDIR) < 0) {
- return -1;
- }
-
- // Get the android protected app directory.
- if (copy_and_append(&android_app_private_dir, &android_data_dir, PRIVATE_APP_SUBDIR) < 0) {
- return -1;
- }
-
- // Get the android ephemeral app directory.
- if (copy_and_append(&android_app_ephemeral_dir, &android_data_dir, EPHEMERAL_APP_SUBDIR) < 0) {
- return -1;
- }
-
- // Get the android app native library directory.
- if (copy_and_append(&android_app_lib_dir, &android_data_dir, APP_LIB_SUBDIR) < 0) {
- return -1;
- }
-
- // Get the sd-card ASEC mount point.
- if (get_path_from_env(&android_asec_dir, "ASEC_MOUNTPOINT") < 0) {
- return -1;
- }
-
- // Get the android media directory.
- if (copy_and_append(&android_media_dir, &android_data_dir, MEDIA_SUBDIR) < 0) {
- return -1;
- }
-
- // Get the android external app directory.
- if (get_path_from_string(&android_mnt_expand_dir, "/mnt/expand/") < 0) {
- return -1;
- }
-
- // Take note of the system and vendor directories.
- android_system_dirs.count = 5;
-
- android_system_dirs.dirs = (dir_rec_t*) calloc(android_system_dirs.count, sizeof(dir_rec_t));
- if (android_system_dirs.dirs == NULL) {
- ALOGE("Couldn't allocate array for dirs; aborting\n");
- return -1;
- }
-
- dir_rec_t android_root_dir;
- if (get_path_from_env(&android_root_dir, "ANDROID_ROOT") < 0) {
- ALOGE("Missing ANDROID_ROOT; aborting\n");
- return -1;
- }
-
- android_system_dirs.dirs[0].path = build_string2(android_root_dir.path, APP_SUBDIR);
- android_system_dirs.dirs[0].len = strlen(android_system_dirs.dirs[0].path);
-
- android_system_dirs.dirs[1].path = build_string2(android_root_dir.path, PRIV_APP_SUBDIR);
- android_system_dirs.dirs[1].len = strlen(android_system_dirs.dirs[1].path);
-
- android_system_dirs.dirs[2].path = strdup("/vendor/app/");
- android_system_dirs.dirs[2].len = strlen(android_system_dirs.dirs[2].path);
-
- android_system_dirs.dirs[3].path = strdup("/oem/app/");
- android_system_dirs.dirs[3].len = strlen(android_system_dirs.dirs[3].path);
-
- android_system_dirs.dirs[4].path = build_string2(android_root_dir.path, EPHEMERAL_APP_SUBDIR);
- android_system_dirs.dirs[4].len = strlen(android_system_dirs.dirs[4].path);
-
- return 0;
-}
-
-int initialize_directories() {
+static int initialize_directories() {
int res = -1;
// Read current filesystem layout version to handle upgrade paths
@@ -658,7 +731,7 @@
return 0;
}
-int main(const int argc __unused, char *argv[]) {
+static int installd_main(const int argc ATTRIBUTE_UNUSED, char *argv[]) {
char buf[BUFFER_MAX];
struct sockaddr addr;
socklen_t alen;
@@ -674,7 +747,7 @@
cb.func_log = log_callback;
selinux_set_callback(SELINUX_CB_LOG, cb);
- if (initialize_globals() < 0) {
+ if (!initialize_globals()) {
ALOGE("Could not initialize globals; exiting.\n");
exit(1);
}
@@ -736,3 +809,10 @@
return 0;
}
+
+} // namespace installd
+} // namespace android
+
+int main(const int argc, char *argv[]) {
+ return android::installd::installd_main(argc, argv);
+}
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
deleted file mode 100644
index 8662417..0000000
--- a/cmds/installd/installd.h
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#define LOG_TAG "installd"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/stat.h>
-#include <dirent.h>
-#include <unistd.h>
-#include <ctype.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <utime.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <string>
-#include <vector>
-
-#include <cutils/fs.h>
-#include <cutils/sockets.h>
-#include <cutils/log.h>
-#include <cutils/properties.h>
-#include <cutils/multiuser.h>
-
-#include <private/android_filesystem_config.h>
-
-#if defined(__APPLE__)
-#include <sys/mount.h>
-#else
-#include <sys/statfs.h>
-#endif
-
-#define SOCKET_PATH "installd"
-
-
-/* elements combined with a valid package name to form paths */
-
-#define PRIMARY_USER_PREFIX "data/"
-#define SECONDARY_USER_PREFIX "user/"
-
-#define PKG_DIR_POSTFIX ""
-
-#define PKG_LIB_POSTFIX "/lib"
-
-#define CACHE_DIR_POSTFIX "/cache"
-#define CODE_CACHE_DIR_POSTFIX "/code_cache"
-
-#define APP_SUBDIR "app/" // sub-directory under ANDROID_DATA
-#define PRIV_APP_SUBDIR "priv-app/" // sub-directory under ANDROID_DATA
-#define EPHEMERAL_APP_SUBDIR "app-ephemeral/" // sub-directory under ANDROID_DATA
-
-#define APP_LIB_SUBDIR "app-lib/" // sub-directory under ANDROID_DATA
-
-#define MEDIA_SUBDIR "media/" // sub-directory under ANDROID_DATA
-
-/* other handy constants */
-
-#define PRIVATE_APP_SUBDIR "app-private/" // sub-directory under ANDROID_DATA
-
-#define DALVIK_CACHE_PREFIX "/data/dalvik-cache/"
-#define DALVIK_CACHE_POSTFIX "/classes.dex"
-
-#define UPDATE_COMMANDS_DIR_PREFIX "/system/etc/updatecmds/"
-
-#define IDMAP_PREFIX "/data/resource-cache/"
-#define IDMAP_SUFFIX "@idmap"
-
-#define PKG_NAME_MAX 128 /* largest allowed package name */
-#define PKG_PATH_MAX 256 /* max size of any path we use */
-
-/* dexopt needed flags matching those in dalvik.system.DexFile */
-#define DEXOPT_DEX2OAT_NEEDED 1
-#define DEXOPT_PATCHOAT_NEEDED 2
-#define DEXOPT_SELF_PATCHOAT_NEEDED 3
-
-/****************************************************************************
- * IMPORTANT: These values are passed from Java code. Keep them in sync with
- * frameworks/base/services/core/java/com/android/server/pm/Installer.java
- ***************************************************************************/
-constexpr int DEXOPT_PUBLIC = 1 << 1;
-constexpr int DEXOPT_SAFEMODE = 1 << 2;
-constexpr int DEXOPT_DEBUGGABLE = 1 << 3;
-constexpr int DEXOPT_BOOTCOMPLETE = 1 << 4;
-constexpr int DEXOPT_USEJIT = 1 << 5;
-
-/* all known values for dexopt flags */
-constexpr int DEXOPT_MASK =
- DEXOPT_PUBLIC
- | DEXOPT_SAFEMODE
- | DEXOPT_DEBUGGABLE
- | DEXOPT_BOOTCOMPLETE
- | DEXOPT_USEJIT;
-
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
-
-/* data structures */
-
-typedef struct {
- char* path;
- size_t len;
-} dir_rec_t;
-
-typedef struct {
- size_t count;
- dir_rec_t* dirs;
-} dir_rec_array_t;
-
-extern dir_rec_t android_app_dir;
-extern dir_rec_t android_app_private_dir;
-extern dir_rec_t android_app_ephemeral_dir;
-extern dir_rec_t android_app_lib_dir;
-extern dir_rec_t android_data_dir;
-extern dir_rec_t android_asec_dir;
-extern dir_rec_t android_media_dir;
-extern dir_rec_t android_mnt_expand_dir;
-extern dir_rec_array_t android_system_dirs;
-
-typedef struct cache_dir_struct {
- struct cache_dir_struct* parent;
- int32_t childCount;
- int32_t hiddenCount;
- int32_t deleted;
- char name[];
-} cache_dir_t;
-
-typedef struct {
- cache_dir_t* dir;
- time_t modTime;
- char name[];
-} cache_file_t;
-
-typedef struct {
- size_t numDirs;
- size_t availDirs;
- cache_dir_t** dirs;
- size_t numFiles;
- size_t availFiles;
- cache_file_t** files;
- size_t numCollected;
- void* memBlocks;
- int8_t* curMemBlockAvail;
- int8_t* curMemBlockEnd;
-} cache_t;
-
-/* util.c */
-
-int create_pkg_path(char path[PKG_PATH_MAX],
- const char *pkgname,
- const char *postfix,
- userid_t userid);
-
-std::string create_data_path(const char* volume_uuid);
-
-std::string create_data_app_path(const char* volume_uuid);
-
-std::string create_data_app_package_path(const char* volume_uuid, const char* package_name);
-
-// TODO: finish refactoring to "_ce"
-std::string create_data_user_path(const char* volume_uuid, userid_t userid);
-std::string create_data_user_de_path(const char* volume_uuid, userid_t userid);
-
-std::string create_data_user_package_path(const char* volume_uuid,
- userid_t user, const char* package_name);
-std::string create_data_user_de_package_path(const char* volume_uuid,
- userid_t user, const char* package_name);
-
-std::string create_data_media_path(const char* volume_uuid, userid_t userid);
-
-std::vector<userid_t> get_known_users(const char* volume_uuid);
-
-int create_user_config_path(char path[PKG_PATH_MAX], userid_t userid);
-
-int create_move_path(char path[PKG_PATH_MAX],
- const char* pkgname,
- const char* leaf,
- userid_t userid);
-
-int is_valid_package_name(const char* pkgname);
-
-int create_cache_path(char path[PKG_PATH_MAX], const char *src,
- const char *instruction_set);
-
-int delete_dir_contents(const std::string& pathname);
-int delete_dir_contents_and_dir(const std::string& pathname);
-
-int delete_dir_contents(const char *pathname,
- int also_delete_dir,
- int (*exclusion_predicate)(const char *name, const int is_dir));
-
-int delete_dir_contents_fd(int dfd, const char *name);
-
-int copy_dir_files(const char *srcname, const char *dstname, uid_t owner, gid_t group);
-
-int lookup_media_dir(char basepath[PATH_MAX], const char *dir);
-
-int64_t data_disk_free(const std::string& data_path);
-
-cache_t* start_cache_collection();
-
-void add_cache_files(cache_t* cache, const char *basepath, const char *cachedir);
-
-void clear_cache_files(const std::string& data_path, cache_t* cache, int64_t free_size);
-
-void finish_cache_collection(cache_t* cache);
-
-int validate_system_app_path(const char* path);
-
-int get_path_from_env(dir_rec_t* rec, const char* var);
-
-int get_path_from_string(dir_rec_t* rec, const char* path);
-
-int copy_and_append(dir_rec_t* dst, const dir_rec_t* src, const char* suffix);
-
-int validate_apk_path(const char *path);
-int validate_apk_path_subdirs(const char *path);
-
-int append_and_increment(char** dst, const char* src, size_t* dst_size);
-
-char *build_string2(const char *s1, const char *s2);
-char *build_string3(const char *s1, const char *s2, const char *s3);
-
-int ensure_dir(const char* path, mode_t mode, uid_t uid, gid_t gid);
-int ensure_media_user_dirs(const char* uuid, userid_t userid);
-int ensure_config_user_dirs(userid_t userid);
-
-/* commands.c */
-
-int install(const char *uuid, const char *pkgname, uid_t uid, gid_t gid, const char *seinfo);
-int uninstall(const char *uuid, const char *pkgname, userid_t userid);
-int renamepkg(const char *oldpkgname, const char *newpkgname);
-int fix_uid(const char *uuid, const char *pkgname, uid_t uid, gid_t gid);
-int delete_user_data(const char *uuid, const char *pkgname, userid_t userid);
-int make_user_data(const char *uuid, const char *pkgname, uid_t uid,
- userid_t userid, const char* seinfo);
-int copy_complete_app(const char* from_uuid, const char *to_uuid,
- const char *package_name, const char *data_app_name, appid_t appid,
- const char* seinfo);
-int make_user_config(userid_t userid);
-int delete_user(const char *uuid, userid_t userid);
-int delete_cache(const char *uuid, const char *pkgname, userid_t userid);
-int delete_code_cache(const char *uuid, const char *pkgname, userid_t userid);
-int move_dex(const char *src, const char *dst, const char *instruction_set);
-int rm_dex(const char *path, const char *instruction_set);
-int protect(char *pkgname, gid_t gid);
-int get_size(const char *uuid, const char *pkgname, int userid,
- const char *apkpath, const char *libdirpath,
- const char *fwdlock_apkpath, const char *asecpath,
- const char *instruction_set, int64_t *codesize, int64_t *datasize,
- int64_t *cachesize, int64_t *asecsize);
-int free_cache(const char *uuid, int64_t free_size);
-int dexopt(const char *apk_path, uid_t uid, const char *pkgName, const char *instruction_set,
- int dexopt_needed, const char* oat_dir, int dexopt_flags);
-int mark_boot_complete(const char *instruction_set);
-int movefiles();
-int linklib(const char* uuid, const char* pkgname, const char* asecLibDir, int userId);
-int idmap(const char *target_path, const char *overlay_path, uid_t uid);
-int restorecon_data(const char *uuid, const char* pkgName, const char* seinfo, uid_t uid);
-int create_oat_dir(const char* oat_dir, const char *instruction_set);
-int rm_package_dir(const char* apk_path);
-int calculate_oat_file_path(char path[PKG_PATH_MAX], const char *oat_dir, const char *apk_path,
- const char *instruction_set);
-int move_package_dir(char path[PKG_PATH_MAX], const char *oat_dir, const char *apk_path,
- const char *instruction_set);
-int link_file(const char *relative_path, const char *from_base, const char *to_base);
diff --git a/cmds/installd/installd_constants.h b/cmds/installd/installd_constants.h
new file mode 100644
index 0000000..058db4c
--- /dev/null
+++ b/cmds/installd/installd_constants.h
@@ -0,0 +1,88 @@
+/*
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef INSTALLD_CONSTANTS_H_
+#define INSTALLD_CONSTANTS_H_
+
+namespace android {
+namespace installd {
+
+/* elements combined with a valid package name to form paths */
+
+constexpr const char* PRIMARY_USER_PREFIX = "data/";
+constexpr const char* SECONDARY_USER_PREFIX = "user/";
+
+constexpr const char* PKG_DIR_POSTFIX = "";
+
+constexpr const char* PKG_LIB_POSTFIX = "/lib";
+
+constexpr const char* CACHE_DIR_POSTFIX = "/cache";
+constexpr const char* CODE_CACHE_DIR_POSTFIX = "/code_cache";
+
+constexpr const char* APP_SUBDIR = "app/"; // sub-directory under ANDROID_DATA
+constexpr const char* PRIV_APP_SUBDIR = "priv-app/"; // sub-directory under ANDROID_DATA
+constexpr const char* EPHEMERAL_APP_SUBDIR = "app-ephemeral/"; // sub-directory under ANDROID_DATA
+
+constexpr const char* APP_LIB_SUBDIR = "app-lib/"; // sub-directory under ANDROID_DATA
+
+constexpr const char* MEDIA_SUBDIR = "media/"; // sub-directory under ANDROID_DATA
+
+/* other handy constants */
+
+constexpr const char* PRIVATE_APP_SUBDIR = "app-private/"; // sub-directory under ANDROID_DATA
+
+// This is used as a string literal, can't be constants. TODO: std::string...
+#define DALVIK_CACHE "dalvik-cache"
+constexpr const char* DALVIK_CACHE_POSTFIX = "/classes.dex";
+
+constexpr const char* UPDATE_COMMANDS_DIR_PREFIX = "/system/etc/updatecmds/";
+
+constexpr const char* IDMAP_PREFIX = "/data/resource-cache/";
+constexpr const char* IDMAP_SUFFIX = "@idmap";
+
+constexpr size_t PKG_NAME_MAX = 128u; /* largest allowed package name */
+constexpr size_t PKG_PATH_MAX = 256u; /* max size of any path we use */
+
+/* dexopt needed flags matching those in dalvik.system.DexFile */
+constexpr int DEXOPT_DEX2OAT_NEEDED = 1;
+constexpr int DEXOPT_PATCHOAT_NEEDED = 2;
+constexpr int DEXOPT_SELF_PATCHOAT_NEEDED = 3;
+
+/****************************************************************************
+ * IMPORTANT: These values are passed from Java code. Keep them in sync with
+ * frameworks/base/services/core/java/com/android/server/pm/Installer.java
+ ***************************************************************************/
+constexpr int DEXOPT_PUBLIC = 1 << 1;
+constexpr int DEXOPT_SAFEMODE = 1 << 2;
+constexpr int DEXOPT_DEBUGGABLE = 1 << 3;
+constexpr int DEXOPT_BOOTCOMPLETE = 1 << 4;
+constexpr int DEXOPT_USEJIT = 1 << 5;
+
+/* all known values for dexopt flags */
+constexpr int DEXOPT_MASK =
+ DEXOPT_PUBLIC
+ | DEXOPT_SAFEMODE
+ | DEXOPT_DEBUGGABLE
+ | DEXOPT_BOOTCOMPLETE
+ | DEXOPT_USEJIT;
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
+
+} // namespace installd
+} // namespace android
+
+#endif // INSTALLD_CONSTANTS_H_
diff --git a/cmds/installd/installd_deps.h b/cmds/installd/installd_deps.h
new file mode 100644
index 0000000..5ff46e6
--- /dev/null
+++ b/cmds/installd/installd_deps.h
@@ -0,0 +1,66 @@
+/*
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef INSTALLD_DEPS_H_
+#define INSTALLD_DEPS_H_
+
+#include <inttypes.h>
+
+#include <installd_constants.h>
+
+namespace android {
+namespace installd {
+
+// Dependencies for a full binary. These functions need to be provided to
+// figure out parts of the configuration.
+
+// Retrieve a system property. Same API as cutils, just renamed.
+extern int get_property(const char *key,
+ char *value,
+ const char *default_value);
+// Size constants. Should be checked to be equal to the cutils requirements.
+constexpr size_t kPropertyKeyMax = 32u;
+constexpr size_t kPropertyValueMax = 92u;
+
+// Compute the output path for dex2oat.
+extern bool calculate_oat_file_path(char path[PKG_PATH_MAX],
+ const char *oat_dir,
+ const char *apk_path,
+ const char *instruction_set);
+// Compute the output path for patchoat.
+//
+// Computes the odex file for the given apk_path and instruction_set, e.g.,
+// /system/framework/whatever.jar -> /system/framework/oat/<isa>/whatever.odex
+//
+// Returns false if it failed to determine the odex file path.
+//
+extern bool calculate_odex_file_path(char path[PKG_PATH_MAX],
+ const char *apk_path,
+ const char *instruction_set);
+
+// Compute the output path into the dalvik cache.
+extern bool create_cache_path(char path[PKG_PATH_MAX],
+ const char *src,
+ const char *instruction_set);
+
+// Initialize globals. May be implemented with the helper in globals.h.
+extern bool initialize_globals();
+
+} // namespace installd
+} // namespace android
+
+#endif // INSTALLD_DEPS_H_
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index 5e397f9..ff69f4b 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -19,7 +19,9 @@
#include <gtest/gtest.h>
-#include "installd.h"
+#include <commands.h>
+#include <globals.h>
+#include <utils.h>
#undef LOG_TAG
#define LOG_TAG "utils_test"
@@ -44,6 +46,7 @@
"shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_"
namespace android {
+namespace installd {
class UtilsTest : public testing::Test {
protected:
@@ -319,8 +322,8 @@
EXPECT_EQ(0, create_pkg_path(path, pkgname, "", 0))
<< "Should successfully be able to create package name.";
- const char *prefix = TEST_DATA_DIR PRIMARY_USER_PREFIX;
- size_t offset = strlen(prefix);
+ std::string prefix = std::string(TEST_DATA_DIR) + PRIMARY_USER_PREFIX;
+ size_t offset = prefix.length();
EXPECT_STREQ(pkgname, path + offset)
<< "Package path should be a really long string of a's";
@@ -358,7 +361,10 @@
EXPECT_EQ(0, create_pkg_path(path, "com.example.package", "", 0))
<< "Should return error because postfix is too long.";
- EXPECT_STREQ(TEST_DATA_DIR PRIMARY_USER_PREFIX "com.example.package", path)
+ std::string p = std::string(TEST_DATA_DIR)
+ + PRIMARY_USER_PREFIX
+ + "com.example.package";
+ EXPECT_STREQ(p.c_str(), path)
<< "Package path should be in /data/data/";
}
@@ -368,7 +374,10 @@
EXPECT_EQ(0, create_pkg_path(path, "com.example.package", "", 1))
<< "Should successfully create package path.";
- EXPECT_STREQ(TEST_DATA_DIR SECONDARY_USER_PREFIX "1/com.example.package", path)
+ std::string p = std::string(TEST_DATA_DIR)
+ + SECONDARY_USER_PREFIX
+ + "1/com.example.package";
+ EXPECT_STREQ(p.c_str(), path)
<< "Package path should be in /data/user/";
}
@@ -499,4 +508,5 @@
create_data_user_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10, "com.example"));
}
-}
+} // namespace installd
+} // namespace android
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 750a136..92a9565 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -14,15 +14,38 @@
** limitations under the License.
*/
-#include "installd.h"
+#include "utils.h"
-#include <android-base/stringprintf.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#if defined(__APPLE__)
+#include <sys/mount.h>
+#else
+#include <sys/statfs.h>
+#endif
+
#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <cutils/fs.h>
+#include <cutils/log.h>
+#include <private/android_filesystem_config.h>
+#include "globals.h" // extern variables.
+
+#ifndef LOG_TAG
+#define LOG_TAG "installd"
+#endif
#define CACHE_NOISY(x) //x
using android::base::StringPrintf;
+namespace android {
+namespace installd {
+
/**
* Check that given string is valid filename, and that it attempts no
* parent or child directory traversal.
@@ -184,7 +207,7 @@
int create_move_path(char path[PKG_PATH_MAX],
const char* pkgname,
const char* leaf,
- userid_t userid __unused)
+ userid_t userid ATTRIBUTE_UNUSED)
{
if ((android_data_dir.len + strlen(PRIMARY_USER_PREFIX) + strlen(pkgname) + strlen(leaf) + 1)
>= PKG_PATH_MAX) {
@@ -1170,3 +1193,32 @@
return 0;
}
+
+int wait_child(pid_t pid)
+{
+ int status;
+ pid_t got_pid;
+
+ while (1) {
+ got_pid = waitpid(pid, &status, 0);
+ if (got_pid == -1 && errno == EINTR) {
+ printf("waitpid interrupted, retrying\n");
+ } else {
+ break;
+ }
+ }
+ if (got_pid != pid) {
+ ALOGW("waitpid failed: wanted %d, got %d: %s\n",
+ (int) pid, (int) got_pid, strerror(errno));
+ return 1;
+ }
+
+ if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
+ return 0;
+ } else {
+ return status; /* always nonzero */
+ }
+}
+
+} // namespace installd
+} // namespace android
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
new file mode 100644
index 0000000..4d6b66e
--- /dev/null
+++ b/cmds/installd/utils.h
@@ -0,0 +1,146 @@
+/*
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef UTILS_H_
+#define UTILS_H_
+
+#include <string>
+#include <vector>
+
+#include <dirent.h>
+#include <inttypes.h>
+#include <unistd.h>
+#include <utime.h>
+
+#include <cutils/multiuser.h>
+
+#include <installd_constants.h>
+
+namespace android {
+namespace installd {
+
+struct dir_rec_t;
+
+typedef struct cache_dir_struct {
+ struct cache_dir_struct* parent;
+ int32_t childCount;
+ int32_t hiddenCount;
+ int32_t deleted;
+ char name[];
+} cache_dir_t;
+
+typedef struct {
+ cache_dir_t* dir;
+ time_t modTime;
+ char name[];
+} cache_file_t;
+
+typedef struct {
+ size_t numDirs;
+ size_t availDirs;
+ cache_dir_t** dirs;
+ size_t numFiles;
+ size_t availFiles;
+ cache_file_t** files;
+ size_t numCollected;
+ void* memBlocks;
+ int8_t* curMemBlockAvail;
+ int8_t* curMemBlockEnd;
+} cache_t;
+
+int create_pkg_path(char path[PKG_PATH_MAX],
+ const char *pkgname,
+ const char *postfix,
+ userid_t userid);
+
+std::string create_data_path(const char* volume_uuid);
+
+std::string create_data_app_path(const char* volume_uuid);
+
+std::string create_data_app_package_path(const char* volume_uuid, const char* package_name);
+
+// TODO: finish refactoring to "_ce"
+std::string create_data_user_path(const char* volume_uuid, userid_t userid);
+std::string create_data_user_de_path(const char* volume_uuid, userid_t userid);
+
+std::string create_data_user_package_path(const char* volume_uuid,
+ userid_t user, const char* package_name);
+std::string create_data_user_de_package_path(const char* volume_uuid,
+ userid_t user, const char* package_name);
+
+std::string create_data_media_path(const char* volume_uuid, userid_t userid);
+
+std::vector<userid_t> get_known_users(const char* volume_uuid);
+
+int create_user_config_path(char path[PKG_PATH_MAX], userid_t userid);
+
+int create_move_path(char path[PKG_PATH_MAX],
+ const char* pkgname,
+ const char* leaf,
+ userid_t userid);
+
+int is_valid_package_name(const char* pkgname);
+
+int delete_dir_contents(const std::string& pathname);
+int delete_dir_contents_and_dir(const std::string& pathname);
+
+int delete_dir_contents(const char *pathname,
+ int also_delete_dir,
+ int (*exclusion_predicate)(const char *name, const int is_dir));
+
+int delete_dir_contents_fd(int dfd, const char *name);
+
+int copy_dir_files(const char *srcname, const char *dstname, uid_t owner, gid_t group);
+
+int lookup_media_dir(char basepath[PATH_MAX], const char *dir);
+
+int64_t data_disk_free(const std::string& data_path);
+
+cache_t* start_cache_collection();
+
+void add_cache_files(cache_t* cache, const char *basepath, const char *cachedir);
+
+void clear_cache_files(const std::string& data_path, cache_t* cache, int64_t free_size);
+
+void finish_cache_collection(cache_t* cache);
+
+int validate_system_app_path(const char* path);
+
+int get_path_from_env(dir_rec_t* rec, const char* var);
+
+int get_path_from_string(dir_rec_t* rec, const char* path);
+
+int copy_and_append(dir_rec_t* dst, const dir_rec_t* src, const char* suffix);
+
+int validate_apk_path(const char *path);
+int validate_apk_path_subdirs(const char *path);
+
+int append_and_increment(char** dst, const char* src, size_t* dst_size);
+
+char *build_string2(const char *s1, const char *s2);
+char *build_string3(const char *s1, const char *s2, const char *s3);
+
+int ensure_dir(const char* path, mode_t mode, uid_t uid, gid_t gid);
+int ensure_media_user_dirs(const char* uuid, userid_t userid);
+int ensure_config_user_dirs(userid_t userid);
+
+int wait_child(pid_t pid);
+
+} // namespace installd
+} // namespace android
+
+#endif // UTILS_H_