Command to move private app data between volumes.
New "mvuserdata" command will move all private app data from one
volume UUID to another. It leverages the existing "cp" toybox
command to do the heavy lifting for all known users, preserving
details like timestamps and permissions. It invokes restorecon()
to correctly label the new location when the copy is finished.
Changes installd to no longer drop capabilities, so we run as root
again. This also allows us to exec "cp" with CAP_DAC_OVERRIDE and
CAP_FOWNER still in effect.
Bug: 19993667
Change-Id: I1f407a7c4a1af97ca5afc27b04eb16b4936cbdef
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index e10116e..ba411cd 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -99,6 +99,38 @@
return StringPrintf("%s/media/%u", create_data_path(volume_uuid).c_str(), userid);
}
+std::vector<userid_t> get_known_users(const char* volume_uuid) {
+ std::vector<userid_t> users;
+
+ // We always have an owner
+ users.push_back(0);
+
+ std::string path(create_data_path(volume_uuid) + "/" + SECONDARY_USER_PREFIX);
+ DIR* dir = opendir(path.c_str());
+ if (dir == NULL) {
+ // Unable to discover other users, but at least return owner
+ PLOG(ERROR) << "Failed to opendir " << path;
+ return users;
+ }
+
+ struct dirent* ent;
+ while ((ent = readdir(dir))) {
+ if (ent->d_type != DT_DIR) {
+ continue;
+ }
+
+ char* end;
+ userid_t user = strtol(ent->d_name, &end, 10);
+ if (*end == '\0' && user != 0) {
+ LOG(DEBUG) << "Found valid user " << user;
+ users.push_back(user);
+ }
+ }
+ closedir(dir);
+
+ return users;
+}
+
/**
* Create the path name for config for a certain userid.
* Returns 0 on success, and -1 on failure.