Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 61a3c8de authored by Jeff Sharkey's avatar Jeff Sharkey Committed by Android (Google) Code Review
Browse files

Merge "Offer to move both code and data together." into mnc-dev

parents 7b2fc930 d792118c
Loading
Loading
Loading
Loading
+137 −76
Original line number Diff line number Diff line
@@ -50,7 +50,7 @@ int install(const char *uuid, const char *pkgname, uid_t uid, gid_t gid, const c
        return -1;
    }

    std::string _pkgdir(create_package_data_path(uuid, pkgname, 0));
    std::string _pkgdir(create_data_user_package_path(uuid, 0, pkgname));
    const char* pkgdir = _pkgdir.c_str();

    if (mkdir(pkgdir, 0751) < 0) {
@@ -80,7 +80,7 @@ int install(const char *uuid, const char *pkgname, uid_t uid, gid_t gid, const c

int uninstall(const char *uuid, const char *pkgname, userid_t userid)
{
    std::string _pkgdir(create_package_data_path(uuid, pkgname, userid));
    std::string _pkgdir(create_data_user_package_path(uuid, userid, pkgname));
    const char* pkgdir = _pkgdir.c_str();

    remove_profile_file(pkgname);
@@ -115,7 +115,7 @@ int fix_uid(const char *uuid, const char *pkgname, uid_t uid, gid_t gid)
        return -1;
    }

    std::string _pkgdir(create_package_data_path(uuid, pkgname, 0));
    std::string _pkgdir(create_data_user_package_path(uuid, 0, pkgname));
    const char* pkgdir = _pkgdir.c_str();

    if (stat(pkgdir, &s) < 0) return -1;
@@ -141,7 +141,7 @@ 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)
{
    std::string _pkgdir(create_package_data_path(uuid, pkgname, userid));
    std::string _pkgdir(create_data_user_package_path(uuid, userid, pkgname));
    const char* pkgdir = _pkgdir.c_str();

    return delete_dir_contents(pkgdir, 0, NULL);
@@ -149,7 +149,7 @@ 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)
{
    std::string _pkgdir(create_package_data_path(uuid, pkgname, userid));
    std::string _pkgdir(create_data_user_package_path(uuid, userid, pkgname));
    const char* pkgdir = _pkgdir.c_str();

    if (mkdir(pkgdir, 0751) < 0) {
@@ -177,15 +177,48 @@ 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) {
int move_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) {
    std::vector<userid_t> users = get_known_users(from_uuid);

    // Copy package private data for all known users
    // Copy app
    {
        std::string from(create_data_app_package_path(from_uuid, data_app_name));
        std::string to(create_data_app_package_path(to_uuid, data_app_name));
        std::string to_parent(create_data_app_path(to_uuid));

        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_parent.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 (selinux_android_restorecon(to.c_str(), SELINUX_ANDROID_RESTORECON_RECURSE) != 0) {
            LOG(ERROR) << "Failed to restorecon " << to;
            goto fail;
        }
    }

    // Copy 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));
        std::string from(create_data_user_package_path(from_uuid, user, package_name));
        std::string to(create_data_user_package_path(to_uuid, user, package_name));
        std::string to_parent(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) {
@@ -213,7 +246,7 @@ int move_user_data(const char *from_uuid, const char *to_uuid,
            (char*) "-P", /* Do not follow symlinks [default] */
            (char*) "-d", /* don't dereference symlinks */
            (char*) from.c_str(),
            (char*) to_user.c_str()
            (char*) to_parent.c_str()
        };

        LOG(DEBUG) << "Copying " << from << " to " << to;
@@ -231,9 +264,15 @@ int move_user_data(const char *from_uuid, const char *to_uuid,
        }
    }

    // Copy successful, so delete old data
    // Delete old app and data
    {
        std::string from(create_data_app_package_path(from_uuid, data_app_name));
        if (delete_dir_contents(from.c_str(), 1, NULL) != 0) {
            LOG(WARNING) << "Failed to delete " << from;
        }
    }
    for (auto user : users) {
        std::string from(create_package_data_path(from_uuid, package_name, user));
        std::string from(create_data_user_package_path(from_uuid, user, package_name));
        if (delete_dir_contents(from.c_str(), 1, NULL) != 0) {
            LOG(WARNING) << "Failed to delete " << from;
        }
@@ -242,8 +281,14 @@ int move_user_data(const char *from_uuid, const char *to_uuid,

fail:
    // Nuke everything we might have already copied
    {
        std::string to(create_data_app_package_path(to_uuid, data_app_name));
        if (delete_dir_contents(to.c_str(), 1, NULL) != 0) {
            LOG(WARNING) << "Failed to rollback " << to;
        }
    }
    for (auto user : users) {
        std::string to(create_package_data_path(to_uuid, package_name, user));
        std::string to(create_data_user_package_path(to_uuid, user, package_name));
        if (delete_dir_contents(to.c_str(), 1, NULL) != 0) {
            LOG(WARNING) << "Failed to rollback " << to;
        }
@@ -289,7 +334,7 @@ int delete_user(const char *uuid, userid_t userid)
int delete_cache(const char *uuid, const char *pkgname, userid_t userid)
{
    std::string _cachedir(
            create_package_data_path(uuid, pkgname, userid) + CACHE_DIR_POSTFIX);
            create_data_user_package_path(uuid, userid, pkgname) + CACHE_DIR_POSTFIX);
    const char* cachedir = _cachedir.c_str();

    /* delete contents, not the directory, no exceptions */
@@ -299,7 +344,7 @@ 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)
{
    std::string _codecachedir(
            create_package_data_path(uuid, pkgname, userid) + CACHE_DIR_POSTFIX);
            create_data_user_package_path(uuid, userid, pkgname) + CACHE_DIR_POSTFIX);
    const char* codecachedir = _codecachedir.c_str();

    struct stat s;
@@ -454,7 +499,7 @@ int rm_dex(const char *path, const char *instruction_set)
    }
}

int get_size(const char *uuid, const char *pkgname, userid_t userid, const char *apkpath,
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)
@@ -471,21 +516,29 @@ int get_size(const char *uuid, const char *pkgname, userid_t userid, const char
    int64_t asecsize = 0;

    /* count the source apk as code -- but only if it's not
         * on the /system partition and its not on the sdcard.
         */
     * on the /system partition and its not on the sdcard. */
    if (validate_system_app_path(apkpath) &&
            strncmp(apkpath, android_asec_dir.path, android_asec_dir.len) != 0) {
        if (stat(apkpath, &s) == 0) {
            codesize += stat_size(&s);
            if (S_ISDIR(s.st_mode)) {
                d = opendir(apkpath);
                if (d != NULL) {
                    dfd = dirfd(d);
                    codesize += calculate_dir_size(dfd);
                    closedir(d);
                }
            }
        /* count the forward locked apk as code if it is given
         */
        }
    }

    /* count the forward locked apk as code if it is given */
    if (fwdlock_apkpath != NULL && fwdlock_apkpath[0] != '!') {
        if (stat(fwdlock_apkpath, &s) == 0) {
            codesize += stat_size(&s);
        }
    }

    /* count the cached dexfile as code */
    if (!create_cache_path(path, apkpath, instruction_set)) {
        if (stat(path, &s) == 0) {
@@ -503,20 +556,28 @@ int get_size(const char *uuid, const char *pkgname, userid_t userid, const char
        }
    }

        /* compute asec size if it is given
         */
    /* compute asec size if it is given */
    if (asecpath != NULL && asecpath[0] != '!') {
        if (stat(asecpath, &s) == 0) {
            asecsize += stat_size(&s);
        }
    }

    std::string _pkgdir(create_package_data_path(uuid, pkgname, userid));
    std::vector<userid_t> users;
    if (userid == -1) {
        users = get_known_users(uuid);
    } else {
        users.push_back(userid);
    }

    for (auto user : users) {
        std::string _pkgdir(create_data_user_package_path(uuid, user, pkgname));
        const char* pkgdir = _pkgdir.c_str();

        d = opendir(pkgdir);
        if (d == NULL) {
        goto done;
            PLOG(WARNING) << "Failed to open " << pkgdir;
            continue;
        }
        dfd = dirfd(d);

@@ -564,7 +625,7 @@ int get_size(const char *uuid, const char *pkgname, userid_t userid, const char
            }
        }
        closedir(d);
done:
    }
    *_codesize = codesize;
    *_datasize = datasize;
    *_cachesize = cachesize;
@@ -1448,7 +1509,7 @@ int linklib(const char* uuid, const char* pkgname, const char* asecLibDir, int u
    struct stat s, libStat;
    int rc = 0;

    std::string _pkgdir(create_package_data_path(uuid, pkgname, userId));
    std::string _pkgdir(create_data_user_package_path(uuid, userId, pkgname));
    std::string _libsymlink(_pkgdir + PKG_LIB_POSTFIX);

    const char* pkgdir = _pkgdir.c_str();
@@ -1639,7 +1700,7 @@ int restorecon_data(const char* uuid, const char* pkgName,

    // Special case for owner on internal storage
    if (uuid == nullptr) {
        std::string path(create_package_data_path(nullptr, pkgName, 0));
        std::string path(create_data_user_package_path(nullptr, 0, pkgName));

        if (selinux_android_restorecon_pkgdir(path.c_str(), seinfo, uid, flags) < 0) {
            PLOG(ERROR) << "restorecon failed for " << path;
+4 −4
Original line number Diff line number Diff line
@@ -124,10 +124,10 @@ static int do_rm_user_data(char **arg, char reply[REPLY_MAX] __unused)
    return delete_user_data(parse_null(arg[0]), arg[1], atoi(arg[2])); /* uuid, pkgname, userid */
}

static int do_mv_user_data(char **arg, char reply[REPLY_MAX] __unused)
static int do_mv_complete_app(char **arg, char reply[REPLY_MAX] __unused)
{
    // from_uuid, to_uuid, pkgname, appid, seinfo
    return move_user_data(parse_null(arg[0]), parse_null(arg[1]), arg[2], atoi(arg[3]), arg[4]);
    // from_uuid, to_uuid, package_name, data_app_name, appid, seinfo
    return move_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)
@@ -200,7 +200,7 @@ struct cmdinfo cmds[] = {
    { "rmcodecache",          3, do_rm_code_cache },
    { "getsize",              8, do_get_size },
    { "rmuserdata",           3, do_rm_user_data },
    { "mvuserdata",           5, do_mv_user_data },
    { "mvcompleteapp",        6, do_mv_complete_app },
    { "movefiles",            0, do_movefiles },
    { "linklib",              4, do_linklib },
    { "mkuserdata",           5, do_mk_user_data },
+15 −9
Original line number Diff line number Diff line
@@ -142,10 +142,6 @@ typedef struct {

/* util.c */

// TODO: rename to create_data_user_package_path
std::string create_package_data_path(const char* volume_uuid,
        const char* package_name, userid_t user);

int create_pkg_path(char path[PKG_PATH_MAX],
                    const char *pkgname,
                    const char *postfix,
@@ -153,8 +149,15 @@ int create_pkg_path(char path[PKG_PATH_MAX],

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);

std::string create_data_user_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_media_path(const char* volume_uuid, userid_t userid);

std::vector<userid_t> get_known_users(const char* volume_uuid);
@@ -221,8 +224,9 @@ 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 move_user_data(const char* from_uuid, const char *to_uuid,
        const char *package_name, appid_t appid, const char* seinfo);
int move_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);
@@ -230,9 +234,11 @@ 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, userid_t 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 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, bool is_public, const char *pkgName,
           const char *instruction_set, int dexopt_needed, bool vm_safe_mode,
+19 −5
Original line number Diff line number Diff line
@@ -455,6 +455,13 @@ TEST_F(UtilsTest, CreateDataPath) {
            create_data_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b"));
}

TEST_F(UtilsTest, CreateDataAppPath) {
    EXPECT_EQ("/data/app", create_data_app_path(nullptr));

    EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/app",
            create_data_app_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b"));
}

TEST_F(UtilsTest, CreateDataUserPath) {
    EXPECT_EQ("/data/data", create_data_user_path(nullptr, 0));
    EXPECT_EQ("/data/user/10", create_data_user_path(nullptr, 10));
@@ -475,14 +482,21 @@ TEST_F(UtilsTest, CreateDataMediaPath) {
            create_data_media_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10));
}

TEST_F(UtilsTest, CreatePackageDataPath) {
    EXPECT_EQ("/data/data/com.example", create_package_data_path(nullptr, "com.example", 0));
    EXPECT_EQ("/data/user/10/com.example", create_package_data_path(nullptr, "com.example", 10));
TEST_F(UtilsTest, CreateDataAppPackagePath) {
    EXPECT_EQ("/data/app/com.example", create_data_app_package_path(nullptr, "com.example"));

    EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/app/com.example",
            create_data_app_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", "com.example"));
}

TEST_F(UtilsTest, CreateDataUserPackagePath) {
    EXPECT_EQ("/data/data/com.example", create_data_user_package_path(nullptr, 0, "com.example"));
    EXPECT_EQ("/data/user/10/com.example", create_data_user_package_path(nullptr, 10, "com.example"));

    EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/0/com.example",
            create_package_data_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", "com.example", 0));
            create_data_user_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0, "com.example"));
    EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/10/com.example",
            create_package_data_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", "com.example", 10));
            create_data_user_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10, "com.example"));
}

}
+26 −4
Original line number Diff line number Diff line
@@ -36,17 +36,32 @@ static bool is_valid_filename(const std::string& name) {
    }
}

/**
 * Create the path name where package app contents should be stored for
 * the given volume UUID and package name.  An empty UUID is assumed to
 * be internal storage.
 */
std::string create_data_app_package_path(const char* volume_uuid,
        const char* package_name) {
    CHECK(is_valid_filename(package_name));
    CHECK(is_valid_package_name(package_name) == 0);

    return StringPrintf("%s/%s",
            create_data_app_path(volume_uuid).c_str(), package_name);
}

/**
 * Create the path name where package data should be stored for the given
 * volume UUID, package name, and user ID. An empty UUID is assumed to be
 * internal storage.
 */
std::string create_package_data_path(const char* volume_uuid,
        const char* package_name, userid_t user) {
std::string create_data_user_package_path(const char* volume_uuid,
        userid_t user, const char* package_name) {
    CHECK(is_valid_filename(package_name));
    CHECK(is_valid_package_name(package_name) == 0);

    return StringPrintf("%s/%s", create_data_user_path(volume_uuid, user).c_str(), package_name);
    return StringPrintf("%s/%s",
            create_data_user_path(volume_uuid, user).c_str(), package_name);
}

int create_pkg_path(char path[PKG_PATH_MAX], const char *pkgname,
@@ -56,7 +71,7 @@ int create_pkg_path(char path[PKG_PATH_MAX], const char *pkgname,
        return -1;
    }

    std::string _tmp(create_package_data_path(nullptr, pkgname, userid) + postfix);
    std::string _tmp(create_data_user_package_path(nullptr, userid, pkgname) + postfix);
    const char* tmp = _tmp.c_str();
    if (strlen(tmp) >= PKG_PATH_MAX) {
        path[0] = '\0';
@@ -76,6 +91,13 @@ std::string create_data_path(const char* volume_uuid) {
    }
}

/**
 * Create the path name for app data.
 */
std::string create_data_app_path(const char* volume_uuid) {
    return StringPrintf("%s/app", create_data_path(volume_uuid).c_str());
}

/**
 * Create the path name for user data for a certain userid.
 */