Consistent creation/destruction of user data.

Preparing and destroying users currently needs to be split across
installd, system_server, and vold, since no single party has all the
required SELinux permissions.

Start passing down flags so we only prepare/destroy storage areas
that have keys currently installed.

Add delete_dir_contents_and_dir() argument to ignore ENOENT, since
all we care about is the directory being gone.

Bug: 27896918
Change-Id: Ia1cccc9b35e6ff09e3ca50effeab676157b856e8
diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
index 20ad5f9..f4d894b 100644
--- a/cmds/installd/commands.cpp
+++ b/cmds/installd/commands.cpp
@@ -419,38 +419,29 @@
     return -1;
 }
 
-int make_user_config(userid_t userid)
-{
-    if (ensure_config_user_dirs(userid) == -1) {
-        return -1;
+int create_user_data(const char *uuid, userid_t userid, int user_serial ATTRIBUTE_UNUSED,
+        int flags) {
+    if (flags & FLAG_STORAGE_DE) {
+        if (uuid == nullptr) {
+            return ensure_config_user_dirs(userid);
+        }
     }
-
     return 0;
 }
 
-int delete_user(const char *uuid, userid_t userid) {
+int destroy_user_data(const char *uuid, userid_t userid, int flags) {
     int res = 0;
-
-    std::string data_path(create_data_user_ce_path(uuid, userid));
-    std::string data_de_path(create_data_user_de_path(uuid, userid));
-    std::string media_path(create_data_media_path(uuid, userid));
-    std::string profiles_path(create_data_user_profiles_path(userid));
-
-    res |= delete_dir_contents_and_dir(data_path);
-    // TODO: include result once 25796509 is fixed
-    delete_dir_contents_and_dir(data_de_path);
-    res |= delete_dir_contents_and_dir(media_path);
-    res |= delete_dir_contents_and_dir(profiles_path);
-
-    // Config paths only exist on internal storage
-    if (uuid == nullptr) {
-        char config_path[PATH_MAX];
-        if ((create_user_config_path(config_path, userid) != 0)
-                || (delete_dir_contents(config_path, 1, NULL) != 0)) {
-            res = -1;
+    if (flags & FLAG_STORAGE_DE) {
+        res |= delete_dir_contents_and_dir(create_data_user_de_path(uuid, userid), true);
+        if (uuid == nullptr) {
+            res |= delete_dir_contents_and_dir(create_data_misc_legacy_path(userid), true);
+            res |= delete_dir_contents_and_dir(create_data_user_profiles_path(userid), true);
         }
     }
-
+    if (flags & FLAG_STORAGE_CE) {
+        res |= delete_dir_contents_and_dir(create_data_user_ce_path(uuid, userid), true);
+        res |= delete_dir_contents_and_dir(create_data_media_path(uuid, userid), true);
+    }
     return res;
 }
 
diff --git a/cmds/installd/commands.h b/cmds/installd/commands.h
index f13ceea..81c13b4 100644
--- a/cmds/installd/commands.h
+++ b/cmds/installd/commands.h
@@ -46,8 +46,9 @@
         int64_t *asecsize);
 int get_app_data_inode(const char *uuid, const char *pkgname, int userid, int flags, ino_t *inode);
 
-int make_user_config(userid_t userid);
-int delete_user(const char *uuid, userid_t userid);
+int create_user_data(const char *uuid, userid_t userid, int user_serial, int flags);
+int destroy_user_data(const char *uuid, userid_t userid, int flags);
+
 int rm_dex(const char *path, const char *instruction_set);
 int free_cache(const char *uuid, int64_t free_size);
 
diff --git a/cmds/installd/installd.cpp b/cmds/installd/installd.cpp
index 5c29eb4..eb51e70 100644
--- a/cmds/installd/installd.cpp
+++ b/cmds/installd/installd.cpp
@@ -336,14 +336,16 @@
                              atoi(arg[4]), arg[5], atoi(arg[6]));
 }
 
-static int do_mk_user_config(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
+static int do_create_user_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
 {
-    return make_user_config(atoi(arg[0])); /* userid */
+    /* const char *uuid, userid_t userid, int user_serial, int flags */
+    return create_user_data(parse_null(arg[0]), atoi(arg[1]), atoi(arg[2]), atoi(arg[3]));
 }
 
-static int do_rm_user(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
+static int do_destroy_user_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
 {
-    return delete_user(parse_null(arg[0]), atoi(arg[1])); /* uuid, userid */
+    /* const char *uuid, userid_t userid, int flags */
+    return destroy_user_data(parse_null(arg[0]), atoi(arg[1]), atoi(arg[2]));
 }
 
 static int do_linklib(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
@@ -409,13 +411,14 @@
     { "get_app_size",         6, do_get_app_size },
     { "get_app_data_inode",   4, do_get_app_data_inode },
 
+    { "create_user_data",     4, do_create_user_data },
+    { "destroy_user_data",    3, do_destroy_user_data },
+
     { "dexopt",               9, do_dexopt },
     { "markbootcomplete",     1, do_mark_boot_complete },
     { "rmdex",                2, do_rm_dex },
     { "freecache",            2, do_free_cache },
     { "linklib",              4, do_linklib },
-    { "mkuserconfig",         1, do_mk_user_config },
-    { "rmuser",               2, do_rm_user },
     { "idmap",                3, do_idmap },
     { "createoatdir",         2, do_create_oat_dir },
     { "rmpackagedir",         1, do_rm_package_dir },
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 5c2ad2d..90d2a9e 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -193,6 +193,10 @@
     return StringPrintf("%s/media/%u", create_data_path(volume_uuid).c_str(), userid);
 }
 
+std::string create_data_misc_legacy_path(userid_t userid) {
+    return StringPrintf("%s/misc/user/%u", create_data_path(nullptr).c_str(), userid);
+}
+
 std::string create_data_user_profiles_path(userid_t userid) {
     return StringPrintf("%s/cur/%u", android_profiles_dir.path, userid);
 }
@@ -239,17 +243,6 @@
     return users;
 }
 
-/**
- * Create the path name for config for a certain userid.
- * Returns 0 on success, and -1 on failure.
- */
-int create_user_config_path(char path[PATH_MAX], userid_t userid) {
-    if (snprintf(path, PATH_MAX, "%s%d", "/data/misc/user/", userid) > PATH_MAX) {
-        return -1;
-    }
-    return 0;
-}
-
 int create_move_path(char path[PKG_PATH_MAX],
     const char* pkgname,
     const char* leaf,
@@ -1219,19 +1212,13 @@
 }
 
 int ensure_config_user_dirs(userid_t userid) {
-    char config_user_path[PATH_MAX];
-
     // writable by system, readable by any app within the same user
     const int uid = multiuser_get_uid(userid, AID_SYSTEM);
     const int gid = multiuser_get_uid(userid, AID_EVERYBODY);
 
     // Ensure /data/misc/user/<userid> exists
-    create_user_config_path(config_user_path, userid);
-    if (fs_prepare_dir(config_user_path, 0750, uid, gid) == -1) {
-        return -1;
-    }
-
-   return 0;
+    auto path = create_data_misc_legacy_path(userid);
+    return fs_prepare_dir(path.c_str(), 0750, uid, gid);
 }
 
 int wait_child(pid_t pid)
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index 9d9a423..477baea 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -85,6 +85,8 @@
 
 std::string create_data_media_path(const char* volume_uuid, userid_t userid);
 
+std::string create_data_misc_legacy_path(userid_t userid);
+
 std::string create_data_user_profiles_path(userid_t userid);
 std::string create_data_user_profile_package_path(userid_t user, const char* package_name);
 std::string create_data_ref_profile_package_path(const char* package_name);
@@ -140,8 +142,6 @@
 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);