summaryrefslogtreecommitdiff
path: root/cmds/installd/commands.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cmds/installd/commands.cpp')
-rw-r--r--cmds/installd/commands.cpp93
1 files changed, 86 insertions, 7 deletions
diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
index 32a03f49de..de6fd960f9 100644
--- a/cmds/installd/commands.cpp
+++ b/cmds/installd/commands.cpp
@@ -16,15 +16,18 @@
#include "installd.h"
-#include <inttypes.h>
-#include <sys/capability.h>
-#include <sys/file.h>
+#include <base/stringprintf.h>
+#include <base/logging.h>
#include <cutils/sched_policy.h>
#include <diskusage/dirsize.h>
-#include <selinux/android.h>
+#include <logwrap/logwrap.h>
#include <system/thread_defs.h>
-#include <base/stringprintf.h>
-#include <base/logging.h>
+#include <selinux/android.h>
+
+#include <inttypes.h>
+#include <sys/capability.h>
+#include <sys/file.h>
+#include <unistd.h>
using android::base::StringPrintf;
@@ -38,6 +41,8 @@ dir_rec_t android_media_dir;
dir_rec_t android_mnt_expand_dir;
dir_rec_array_t android_system_dirs;
+static const char* kCpPath = "/system/bin/cp";
+
int install(const char *uuid, const char *pkgname, uid_t uid, gid_t gid, const char *seinfo)
{
if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) {
@@ -172,6 +177,80 @@ int make_user_data(const char *uuid, const char *pkgname, uid_t uid, userid_t us
return 0;
}
+int move_user_data(const char *from_uuid, const char *to_uuid,
+ const char *package_name, appid_t appid, const char* seinfo) {
+ std::vector<userid_t> users = get_known_users(from_uuid);
+
+ // Copy package private data for all known users
+ for (auto user : users) {
+ std::string from(create_package_data_path(from_uuid, package_name, user));
+ std::string to(create_package_data_path(to_uuid, package_name, user));
+ std::string to_user(create_data_user_path(to_uuid, user));
+
+ // Data source may not exist for all users; that's okay
+ if (access(from.c_str(), F_OK) != 0) {
+ LOG(INFO) << "Missing source " << from;
+ continue;
+ }
+
+ std::string user_path(create_data_user_path(to_uuid, user));
+ if (fs_prepare_dir(user_path.c_str(), 0771, AID_SYSTEM, AID_SYSTEM) != 0) {
+ LOG(ERROR) << "Failed to prepare user target " << user_path;
+ goto fail;
+ }
+
+ uid_t uid = multiuser_get_uid(user, appid);
+ if (make_user_data(to_uuid, package_name, uid, user, seinfo) != 0) {
+ LOG(ERROR) << "Failed to create package target " << to;
+ goto fail;
+ }
+
+ char *argv[] = {
+ (char*) kCpPath,
+ (char*) "-F", /* delete any existing destination file first (--remove-destination) */
+ (char*) "-p", /* preserve timestamps, ownership, and permissions */
+ (char*) "-R", /* recurse into subdirectories (DEST must be a directory) */
+ (char*) "-P", /* Do not follow symlinks [default] */
+ (char*) "-d", /* don't dereference symlinks */
+ (char*) from.c_str(),
+ (char*) to_user.c_str()
+ };
+
+ LOG(DEBUG) << "Copying " << from << " to " << to;
+ int rc = android_fork_execvp(ARRAY_SIZE(argv), argv, NULL, false, true);
+
+ if (rc != 0) {
+ LOG(ERROR) << "Failed copying " << from << " to " << to
+ << ": status " << rc;
+ goto fail;
+ }
+
+ if (restorecon_data(to_uuid, package_name, seinfo, uid) != 0) {
+ LOG(ERROR) << "Failed to restorecon " << to;
+ goto fail;
+ }
+ }
+
+ // Copy successful, so delete old data
+ for (auto user : users) {
+ std::string from(create_package_data_path(from_uuid, package_name, user));
+ if (delete_dir_contents(from.c_str(), 1, NULL) != 0) {
+ LOG(WARNING) << "Failed to delete " << from;
+ }
+ }
+ return 0;
+
+fail:
+ // Nuke everything we might have already copied
+ for (auto user : users) {
+ std::string to(create_package_data_path(to_uuid, package_name, user));
+ if (delete_dir_contents(to.c_str(), 1, NULL) != 0) {
+ LOG(WARNING) << "Failed to rollback " << to;
+ }
+ }
+ return -1;
+}
+
int make_user_config(userid_t userid)
{
if (ensure_config_user_dirs(userid) == -1) {
@@ -1592,7 +1671,7 @@ int restorecon_data(const char* uuid, const char* pkgName,
continue;
}
- std::string pkgdir(StringPrintf("%s/%s/%s", userdir.c_str(), user, pkgName));
+ std::string pkgdir(StringPrintf("%s%s/%s", userdir.c_str(), user, pkgName));
if (stat(pkgdir.c_str(), &s) < 0) {
continue;
}