Use inode numbers for CE storage, fix sizes.
Certain operations, such as clearing/destroying app data, or just
counting on-disk size, require us to know the CE storage directory
of a particular app. To facilitate these operations, offer a method
to get the inode of a CE directory, and accept that inode number
for later operations.
In previous releases, we started installing apps using a new
directory-based layout, where all app code, unpacked native libraries,
and optimized code is bundled together. So now we only have a single
path to measure for code size.
Start measuring both CE and DE storage data usage for apps, and tweak
the reporting so that empty cache/data directories actually show up
as "0 bytes".
Fix bugs in disk usage counting, since st_blksize has no bearing on
the allocated disk space. Also don't double-count "." and ".."
directories when measuring storage.
Bug: 27828915, 27197819
Change-Id: I350b951f5c24165edb253ac663c9aae020c24dc9
diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
index 5481313..20ad5f9 100644
--- a/cmds/installd/commands.cpp
+++ b/cmds/installd/commands.cpp
@@ -74,7 +74,7 @@
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 @@
// 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 @@
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 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 @@
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 @@
// 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 @@
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 @@
}
}
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 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 @@
// 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,142 +569,96 @@
}
}
-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;
+ d = opendir(path.c_str());
+ if (d == nullptr) {
+ PLOG(WARNING) << "Failed to open " << path;
+ return;
+ }
+ dfd = dirfd(d);
+ while ((de = readdir(d))) {
+ const char *name = de->d_name;
- /* 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);
- }
+ 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 dirsize = 0;
+ /* always skip "." and ".." */
+ if (name[0] == '.') {
+ if (name[1] == 0) continue;
+ if ((name[1] == '.') && (name[2] == 0)) continue;
}
- }
- }
-
- /* 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;
- }
- 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;
-
- 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);
- }
- if(!strcmp(name,"lib")) {
- codesize += dirsize + statsize;
- } else if(!strcmp(name,"cache")) {
- cachesize += dirsize + statsize;
- } else {
- 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);
- }
+ subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
+ if (subfd >= 0) {
+ dirsize = calculate_dir_size(subfd);
+ close(subfd);
+ }
+ // TODO: check xattrs!
+ if (!strcmp(name, "cache") || !strcmp(name, "code_cache")) {
+ *datasize += statsize;
+ *cachesize += dirsize;
} else {
- if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
- datasize += stat_size(&s);
- }
+ *datasize += dirsize + statsize;
}
+ } else if (de->d_type == DT_LNK && !strcmp(name, "lib")) {
+ *codesize += statsize;
+ } else {
+ *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)
{
char *ctx;
@@ -1617,7 +1573,7 @@
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 @@
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;
diff --git a/cmds/installd/commands.h b/cmds/installd/commands.h
index 13143c5..f13ceea 100644
--- a/cmds/installd/commands.h
+++ b/cmds/installd/commands.h
@@ -33,16 +33,18 @@
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);
diff --git a/cmds/installd/installd.cpp b/cmds/installd/installd.cpp
index de3f54a..c7f4ffc 100644
--- a/cmds/installd/installd.cpp
+++ b/cmds/installd/installd.cpp
@@ -207,13 +207,13 @@
}
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 @@
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 @@
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 @@
{ "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 },
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index ff69f4b..9b2de88 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -472,13 +472,13 @@
}
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, 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
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index d84d9f6..878fb2d 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -81,11 +81,39 @@
* 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 @@
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 @@
/**
* 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) {
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index 416a726..9d9a423 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -73,12 +73,13 @@
std::string create_data_app_package_path(const char* volume_uuid, const char* package_name);
-// TODO: finish refactoring to "_ce"
-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 create_data_user_de_path(const char* volume_uuid, userid_t userid);
-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);
+std::string create_data_user_ce_package_path(const char* volume_uuid,
+ userid_t user, const char* package_name, ino_t ce_data_inode);
std::string create_data_user_de_package_path(const char* volume_uuid,
userid_t user, const char* package_name);
diff --git a/libs/diskusage/dirsize.c b/libs/diskusage/dirsize.c
index 7576994..5b5ab70 100644
--- a/libs/diskusage/dirsize.c
+++ b/libs/diskusage/dirsize.c
@@ -24,16 +24,7 @@
int64_t stat_size(struct stat *s)
{
- int64_t blksize = s->st_blksize;
- // count actual blocks used instead of nominal file size
- int64_t size = s->st_blocks * 512;
-
- if (blksize) {
- /* round up to filesystem block size */
- size = (size + blksize - 1) & (~(blksize - 1));
- }
-
- return size;
+ return s->st_blocks * 512;
}
int64_t calculate_dir_size(int dfd)
@@ -51,9 +42,6 @@
while ((de = readdir(d))) {
const char *name = de->d_name;
- if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
- size += stat_size(&s);
- }
if (de->d_type == DT_DIR) {
int subfd;
@@ -65,10 +53,17 @@
continue;
}
+ if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
+ size += stat_size(&s);
+ }
subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
if (subfd >= 0) {
size += calculate_dir_size(subfd);
}
+ } else {
+ if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
+ size += stat_size(&s);
+ }
}
}
closedir(d);