Add 'rmprofiles' command to installd

Adds a new command to installd which clears all profile data of
a given package.

Bug: 27516490
Change-Id: I92cc374b5b6d95ca7755e08b95a9bc9060df2178
diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
index 44e2dd2..ac2ee30 100644
--- a/cmds/installd/commands.cpp
+++ b/cmds/installd/commands.cpp
@@ -161,17 +161,20 @@
     return StringPrintf("%s/%s", profile_dir.c_str(), PRIMARY_PROFILE_NAME);
 }
 
-static void unlink_reference_profile(const char* pkgname) {
+static bool unlink_reference_profile(const char* pkgname) {
     std::string reference_profile_dir = create_data_ref_profile_package_path(pkgname);
     std::string reference_profile = create_primary_profile(reference_profile_dir);
     if (unlink(reference_profile.c_str()) != 0) {
         if (errno != ENOENT) {
             PLOG(WARNING) << "Could not unlink " << reference_profile;
+            return false;
         }
     }
+    return true;
 }
 
-static void unlink_current_profiles(const char* pkgname) {
+static bool unlink_current_profiles(const char* pkgname) {
+    bool success = true;
     std::vector<userid_t> users = get_known_users(/*volume_uuid*/ nullptr);
     for (auto user : users) {
         std::string profile_dir = create_data_user_profile_package_path(user, pkgname);
@@ -179,14 +182,18 @@
         if (unlink(profile.c_str()) != 0) {
             if (errno != ENOENT) {
                 PLOG(WARNING) << "Could not unlink " << profile;
+                success = false;
             }
         }
     }
+    return success;
 }
 
-static void unlink_all_profiles(const char* pkgname) {
-    unlink_reference_profile(pkgname);
-    unlink_current_profiles(pkgname);
+static bool unlink_all_profiles(const char* pkgname) {
+    bool success = true;
+    success &= unlink_reference_profile(pkgname);
+    success &= unlink_current_profiles(pkgname);
+    return success;
 }
 
 int clear_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags) {
@@ -1761,6 +1768,11 @@
     return delete_dir_contents(apk_path, 1 /* also_delete_dir */ , NULL /* exclusion_predicate */);
 }
 
+int rm_profiles(const char* pkgname)
+{
+    return unlink_all_profiles(pkgname) ? 0 : -1;
+}
+
 int link_file(const char* relative_path, const char* from_base, const char* to_base) {
     char from_path[PKG_PATH_MAX];
     char to_path[PKG_PATH_MAX];
diff --git a/cmds/installd/commands.h b/cmds/installd/commands.h
index 8507eff..d28f6fd 100644
--- a/cmds/installd/commands.h
+++ b/cmds/installd/commands.h
@@ -56,6 +56,7 @@
 int idmap(const char *target_path, const char *overlay_path, uid_t uid);
 int create_oat_dir(const char* oat_dir, const char *instruction_set);
 int rm_package_dir(const char* apk_path);
+int rm_profiles(const char* apk_path);
 int link_file(const char *relative_path, const char *from_base, const char *to_base);
 
 // Move a B version over to the A location. Only works for oat_dir != nullptr.
diff --git a/cmds/installd/installd.cpp b/cmds/installd/installd.cpp
index 54d3970..7ca7527 100644
--- a/cmds/installd/installd.cpp
+++ b/cmds/installd/installd.cpp
@@ -330,6 +330,12 @@
     return rm_package_dir(arg[0]);
 }
 
+static int do_rm_profiles(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
+{
+    /* package_name */
+    return rm_profiles(arg[0]);
+}
+
 static int do_link_file(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
 {
     /* relative_path, from_base, to_base */
@@ -368,6 +374,7 @@
     { "idmap",                3, do_idmap },
     { "createoatdir",         2, do_create_oat_dir },
     { "rmpackagedir",         1, do_rm_package_dir },
+    { "rmprofiles",           1, do_rm_profiles },
     { "linkfile",             3, do_link_file },
     { "move_ab",              3, do_move_ab },
 };