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

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

Merge "Use inode numbers for CE storage, fix sizes." into nyc-dev

parents 4ad5c141 2f720f7e
Loading
Loading
Loading
Loading
+85 −129
Original line number Diff line number Diff line
@@ -74,7 +74,7 @@ int create_app_data(const char *uuid, const char *pkgname, userid_t userid, int
    uid_t uid = multiuser_get_uid(userid, appid);
    int target_mode = target_sdk_version >= MIN_RESTRICTED_HOME_SDK_VERSION ? 0700 : 0751;
    if (flags & FLAG_STORAGE_CE) {
        auto path = create_data_user_package_path(uuid, userid, pkgname);
        auto path = create_data_user_ce_package_path(uuid, userid, pkgname);
        if (fs_prepare_dir_strict(path.c_str(), target_mode, uid, uid) != 0) {
            PLOG(ERROR) << "Failed to prepare " << path;
            return -1;
@@ -124,7 +124,7 @@ int migrate_app_data(const char *uuid, const char *pkgname, userid_t userid, int
    // consistent location.  This only works on non-FBE devices, since we
    // never want to risk exposing data on a device with real CE/DE storage.

    auto ce_path = create_data_user_package_path(uuid, userid, pkgname);
    auto ce_path = create_data_user_ce_package_path(uuid, userid, pkgname);
    auto de_path = create_data_user_de_package_path(uuid, userid, pkgname);

    // If neither directory is marked as default, assume CE is default
@@ -234,7 +234,8 @@ int clear_app_profiles(const char* pkgname) {
    return success ? 0 : -1;
}

int clear_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags) {
int clear_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags,
        ino_t ce_data_inode) {
    std::string suffix = "";
    bool only_cache = false;
    if (flags & FLAG_CLEAR_CACHE_ONLY) {
@@ -247,7 +248,7 @@ int clear_app_data(const char *uuid, const char *pkgname, userid_t userid, int f

    int res = 0;
    if (flags & FLAG_STORAGE_CE) {
        auto path = create_data_user_package_path(uuid, userid, pkgname) + suffix;
        auto path = create_data_user_ce_package_path(uuid, userid, pkgname, ce_data_inode) + suffix;
        if (access(path.c_str(), F_OK) == 0) {
            res |= delete_dir_contents(path);
        }
@@ -289,11 +290,12 @@ int destroy_app_profiles(const char *pkgname) {
    return result;
}

int destroy_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags) {
int destroy_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags,
        ino_t ce_data_inode) {
    int res = 0;
    if (flags & FLAG_STORAGE_CE) {
        res |= delete_dir_contents_and_dir(
                create_data_user_package_path(uuid, userid, pkgname));
                create_data_user_ce_package_path(uuid, userid, pkgname, ce_data_inode));
    }
    if (flags & FLAG_STORAGE_DE) {
        res |= delete_dir_contents_and_dir(
@@ -346,9 +348,9 @@ int move_complete_app(const char *from_uuid, const char *to_uuid, const char *pa
    // Copy private data for all known users
    // TODO: handle user_de paths
    for (auto user : users) {
        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));
        std::string from(create_data_user_ce_package_path(from_uuid, user, package_name));
        std::string to(create_data_user_ce_package_path(to_uuid, user, package_name));
        std::string to_parent(create_data_user_ce_path(to_uuid, user));

        // Data source may not exist for all users; that's okay
        if (access(from.c_str(), F_OK) != 0) {
@@ -356,7 +358,7 @@ int move_complete_app(const char *from_uuid, const char *to_uuid, const char *pa
            continue;
        }

        std::string user_path(create_data_user_path(to_uuid, user));
        std::string user_path(create_data_user_ce_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;
@@ -409,7 +411,7 @@ fail:
        }
    }
    for (auto user : users) {
        std::string to(create_data_user_package_path(to_uuid, user, package_name));
        std::string to(create_data_user_ce_package_path(to_uuid, user, package_name));
        if (delete_dir_contents(to.c_str(), 1, NULL) != 0) {
            LOG(WARNING) << "Failed to rollback " << to;
        }
@@ -429,7 +431,7 @@ int make_user_config(userid_t userid)
int delete_user(const char *uuid, userid_t userid) {
    int res = 0;

    std::string data_path(create_data_user_path(uuid, userid));
    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));
@@ -480,7 +482,7 @@ int free_cache(const char *uuid, int64_t free_size)

    // Special case for owner on internal storage
    if (uuid == nullptr) {
        std::string _tmpdir(create_data_user_path(nullptr, 0));
        std::string _tmpdir(create_data_user_ce_path(nullptr, 0));
        add_cache_files(cache, _tmpdir.c_str(), "cache");
    }

@@ -567,141 +569,95 @@ int rm_dex(const char *path, const char *instruction_set)
    }
}

int get_app_size(const char *uuid, const char *pkgname, int userid, int flags,
        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) {
static void add_app_data_size(std::string& path, int64_t *codesize, int64_t *datasize,
        int64_t *cachesize) {
    DIR *d;
    int dfd;
    struct dirent *de;
    struct stat s;
    char path[PKG_PATH_MAX];

    int64_t codesize = 0;
    int64_t datasize = 0;
    int64_t cachesize = 0;
    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. */
    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 */
    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) {
            codesize += stat_size(&s);
        }
    }

    /* add in size of any libraries */
    if (libdirpath != NULL && libdirpath[0] != '!') {
        d = opendir(libdirpath);
        if (d != NULL) {
            dfd = dirfd(d);
            codesize += calculate_dir_size(dfd);
            closedir(d);
        }
    }

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

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

    for (auto user : users) {
        // TODO: handle user_de directories
        if (!(flags & FLAG_STORAGE_CE)) continue;

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

        d = opendir(pkgdir);
        if (d == NULL) {
            PLOG(WARNING) << "Failed to open " << pkgdir;
            continue;
    d = opendir(path.c_str());
    if (d == nullptr) {
        PLOG(WARNING) << "Failed to open " << path;
        return;
    }
    dfd = dirfd(d);

        /* most stuff in the pkgdir is data, except for the "cache"
         * directory and below, which is cache, and the "lib" directory
         * and below, which is code...
         */
    while ((de = readdir(d))) {
        const char *name = de->d_name;

        int64_t statsize = 0;
        if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
            statsize = stat_size(&s);
        }

        if (de->d_type == DT_DIR) {
            int subfd;
                int64_t statsize = 0;
            int64_t dirsize = 0;
            /* always skip "." and ".." */
            if (name[0] == '.') {
                if (name[1] == 0) continue;
                if ((name[1] == '.') && (name[2] == 0)) continue;
            }
                if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
                    statsize = stat_size(&s);
                }
            subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
            if (subfd >= 0) {
                dirsize = calculate_dir_size(subfd);
                close(subfd);
            }
                if(!strcmp(name,"lib")) {
                    codesize += dirsize + statsize;
                } else if(!strcmp(name,"cache")) {
                    cachesize += dirsize + statsize;
            // TODO: check xattrs!
            if (!strcmp(name, "cache") || !strcmp(name, "code_cache")) {
                *datasize += statsize;
                *cachesize += dirsize;
            } else {
                    datasize += dirsize + statsize;
                *datasize += dirsize + statsize;
            }
        } else if (de->d_type == DT_LNK && !strcmp(name, "lib")) {
                // This is the symbolic link to the application's library
                // code.  We'll count this as code instead of data, since
                // it is not something that the app creates.
                if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
                    codesize += stat_size(&s);
                }
            *codesize += statsize;
        } else {
                if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
                    datasize += stat_size(&s);
            *datasize += statsize;
        }
    }
    closedir(d);
}

int get_app_size(const char *uuid, const char *pkgname, int userid, int flags, ino_t ce_data_inode,
        const char *code_path, int64_t *codesize, int64_t *datasize, int64_t *cachesize,
        int64_t* asecsize) {
    DIR *d;
    int dfd;

    d = opendir(code_path);
    if (d != nullptr) {
        dfd = dirfd(d);
        *codesize += calculate_dir_size(dfd);
        closedir(d);
    }
    *_codesize = codesize;
    *_datasize = datasize;
    *_cachesize = cachesize;
    *_asecsize = asecsize;

    if (flags & FLAG_STORAGE_CE) {
        auto path = create_data_user_ce_package_path(uuid, userid, pkgname, ce_data_inode);
        add_app_data_size(path, codesize, datasize, cachesize);
    }
    if (flags & FLAG_STORAGE_DE) {
        auto path = create_data_user_de_package_path(uuid, userid, pkgname);
        add_app_data_size(path, codesize, datasize, cachesize);
    }

    *asecsize = 0;

    return 0;
}

int get_app_data_inode(const char *uuid, const char *pkgname, int userid, int flags, ino_t *inode) {
    struct stat buf;
    memset(&buf, 0, sizeof(buf));
    if (flags & FLAG_STORAGE_CE) {
        auto path = create_data_user_ce_package_path(uuid, userid, pkgname);
        if (stat(path.c_str(), &buf) == 0) {
            *inode = buf.st_ino;
            return 0;
        }
    }
    return -1;
}

static int split_count(const char *str)
{
@@ -1617,7 +1573,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_data_user_package_path(uuid, userId, pkgname));
    std::string _pkgdir(create_data_user_ce_package_path(uuid, userId, pkgname));
    std::string _libsymlink(_pkgdir + PKG_LIB_POSTFIX);

    const char* pkgdir = _pkgdir.c_str();
@@ -1804,7 +1760,7 @@ int restorecon_app_data(const char* uuid, const char* pkgName, userid_t userid,

    uid_t uid = multiuser_get_uid(userid, appid);
    if (flags & FLAG_STORAGE_CE) {
        auto path = create_data_user_package_path(uuid, userid, pkgName);
        auto path = create_data_user_ce_package_path(uuid, userid, pkgName);
        if (selinux_android_restorecon_pkgdir(path.c_str(), seinfo, uid, seflags) < 0) {
            PLOG(ERROR) << "restorecon failed for " << path;
            res = -1;
+8 −6
Original line number Diff line number Diff line
@@ -33,16 +33,18 @@ int create_app_data(const char *uuid, const char *pkgname, userid_t userid, int
int restorecon_app_data(const char* uuid, const char* pkgName, userid_t userid, int flags,
        appid_t appid, const char* seinfo);
int migrate_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags);
int clear_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags);
int destroy_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags);
int clear_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags,
        ino_t ce_data_inode);
int destroy_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags,
        ino_t ce_data_inode);

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

int get_app_size(const char *uuid, const char *pkgname, int userid, int flags,
        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_app_size(const char *uuid, const char *pkgname, int userid, int flags, ino_t ce_data_inode,
        const char* code_path, int64_t *codesize, int64_t *datasize, int64_t *cachesize,
        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);
+23 −12
Original line number Diff line number Diff line
@@ -207,13 +207,13 @@ static int do_migrate_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSE
}

static int do_clear_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
    /* const char *uuid, const char *pkgname, userid_t userid, int flags */
    return clear_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]));
    /* const char *uuid, const char *pkgname, userid_t userid, int flags, ino_t ce_data_inode */
    return clear_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atol(arg[4]));
}

static int do_destroy_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
    /* const char *uuid, const char *pkgname, userid_t userid, int flags */
    return destroy_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]));
    /* const char *uuid, const char *pkgname, userid_t userid, int flags, ino_t ce_data_inode */
    return destroy_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atol(arg[4]));
}

// We use otapreopt_chroot to get into the chroot.
@@ -303,11 +303,10 @@ static int do_get_app_size(char **arg, char reply[REPLY_MAX]) {
    int64_t asecsize = 0;
    int res = 0;

    /* const char *uuid, const char *pkgname, userid_t userid, int flags,
            const char *apkpath, const char *libdirpath, const char *fwdlock_apkpath,
            const char *asecpath, const char *instruction_set */
    res = get_app_size(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), arg[4], arg[5],
            arg[6], arg[7], arg[8], &codesize, &datasize, &cachesize, &asecsize);
    /* const char *uuid, const char *pkgname, int userid, int flags, ino_t ce_data_inode,
            const char* code_path */
    res = get_app_size(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atol(arg[4]),
            arg[5], &codesize, &datasize, &cachesize, &asecsize);

    /*
     * Each int64_t can take up 22 characters printed out. Make sure it
@@ -318,6 +317,17 @@ static int do_get_app_size(char **arg, char reply[REPLY_MAX]) {
    return res;
}

static int do_get_app_data_inode(char **arg, char reply[REPLY_MAX]) {
    ino_t inode = 0;
    int res = 0;

    /* const char *uuid, const char *pkgname, int userid, int flags */
    res = get_app_data_inode(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), &inode);

    snprintf(reply, REPLY_MAX, "%" PRId64, inode);
    return res;
}

static int do_move_complete_app(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
    /* const char* from_uuid, const char *to_uuid, const char *package_name,
            const char *data_app_name, appid_t appid, const char* seinfo,
@@ -393,10 +403,11 @@ struct cmdinfo cmds[] = {
    { "create_app_data",      7, do_create_app_data },
    { "restorecon_app_data",  6, do_restorecon_app_data },
    { "migrate_app_data",     4, do_migrate_app_data },
    { "clear_app_data",       4, do_clear_app_data },
    { "destroy_app_data",     4, do_destroy_app_data },
    { "clear_app_data",       5, do_clear_app_data },
    { "destroy_app_data",     5, do_destroy_app_data },
    { "move_complete_app",    7, do_move_complete_app },
    { "get_app_size",         9, do_get_app_size },
    { "get_app_size",         6, do_get_app_size },
    { "get_app_data_inode",   4, do_get_app_data_inode },

    { "dexopt",               9, do_dexopt },
    { "markbootcomplete",     1, do_mark_boot_complete },
+8 −8
Original line number Diff line number Diff line
@@ -472,13 +472,13 @@ TEST_F(UtilsTest, CreateDataAppPath) {
}

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));
    EXPECT_EQ("/data/data", create_data_user_ce_path(nullptr, 0));
    EXPECT_EQ("/data/user/10", create_data_user_ce_path(nullptr, 10));

    EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/0",
            create_data_user_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0));
            create_data_user_ce_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0));
    EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/10",
            create_data_user_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10));
            create_data_user_ce_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10));
}

TEST_F(UtilsTest, CreateDataMediaPath) {
@@ -499,13 +499,13 @@ TEST_F(UtilsTest, CreateDataAppPackagePath) {
}

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("/data/data/com.example", create_data_user_ce_package_path(nullptr, 0, "com.example"));
    EXPECT_EQ("/data/user/10/com.example", create_data_user_ce_package_path(nullptr, 10, "com.example"));

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

}  // namespace installd
+32 −4
Original line number Diff line number Diff line
@@ -81,11 +81,39 @@ std::string create_data_app_package_path(const char* volume_uuid,
 * volume UUID, package name, and user ID. An empty UUID is assumed to be
 * internal storage.
 */
std::string create_data_user_package_path(const char* volume_uuid,
std::string create_data_user_ce_package_path(const char* volume_uuid,
        userid_t user, const char* package_name) {
    check_package_name(package_name);
    return StringPrintf("%s/%s",
            create_data_user_path(volume_uuid, user).c_str(), package_name);
            create_data_user_ce_path(volume_uuid, user).c_str(), package_name);
}

std::string create_data_user_ce_package_path(const char* volume_uuid, userid_t user,
        const char* package_name, ino_t ce_data_inode) {
    // For testing purposes, rely on the inode when defined; this could be
    // optimized to use access() in the future.
    auto fallback = create_data_user_ce_package_path(volume_uuid, user, package_name);
    if (ce_data_inode != 0) {
        auto user_path = create_data_user_ce_path(volume_uuid, user);
        DIR* dir = opendir(user_path.c_str());
        if (dir == nullptr) {
            PLOG(ERROR) << "Failed to opendir " << user_path;
            return fallback;
        }

        struct dirent* ent;
        while ((ent = readdir(dir))) {
            if (ent->d_ino == ce_data_inode) {
                closedir(dir);
                return StringPrintf("%s/%s", user_path.c_str(), ent->d_name);
            }
        }
        LOG(WARNING) << "Failed to find inode " << ce_data_inode << " for package " << package_name;
        closedir(dir);
        return fallback;
    } else {
        return fallback;
    }
}

std::string create_data_user_de_package_path(const char* volume_uuid,
@@ -102,7 +130,7 @@ int create_pkg_path(char path[PKG_PATH_MAX], const char *pkgname,
        return -1;
    }

    std::string _tmp(create_data_user_package_path(nullptr, userid, pkgname) + postfix);
    std::string _tmp(create_data_user_ce_package_path(nullptr, userid, pkgname) + postfix);
    const char* tmp = _tmp.c_str();
    if (strlen(tmp) >= PKG_PATH_MAX) {
        path[0] = '\0';
@@ -132,7 +160,7 @@ std::string create_data_app_path(const char* volume_uuid) {
/**
 * Create the path name for user data for a certain userid.
 */
std::string create_data_user_path(const char* volume_uuid, userid_t userid) {
std::string create_data_user_ce_path(const char* volume_uuid, userid_t userid) {
    std::string data(create_data_path(volume_uuid));
    if (volume_uuid == nullptr) {
        if (userid == 0) {
Loading