summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmds/installd/commands.cpp213
-rw-r--r--cmds/installd/installd.cpp8
-rw-r--r--cmds/installd/installd.h24
-rw-r--r--cmds/installd/tests/installd_utils_test.cpp24
-rw-r--r--cmds/installd/utils.cpp30
5 files changed, 201 insertions, 98 deletions
diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
index de6fd96..99da968 100644
--- a/cmds/installd/commands.cpp
+++ b/cmds/installd/commands.cpp
@@ -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)
@@ -470,30 +515,38 @@ int get_size(const char *uuid, const char *pkgname, userid_t userid, const char
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.
- */
+ /* 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
- */
+
+ /* 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 */
+
+ /* 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 */
+ /* add in size of any libraries */
if (libdirpath != NULL && libdirpath[0] != '!') {
d = opendir(libdirpath);
if (d != NULL) {
@@ -503,68 +556,76 @@ 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));
- const char* pkgdir = _pkgdir.c_str();
-
- d = opendir(pkgdir);
- if (d == NULL) {
- goto done;
+ std::vector<userid_t> users;
+ if (userid == -1) {
+ users = get_known_users(uuid);
+ } else {
+ users.push_back(userid);
}
- 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;
+ for (auto user : users) {
+ std::string _pkgdir(create_data_user_package_path(uuid, user, pkgname));
+ const char* pkgdir = _pkgdir.c_str();
- 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;
+ 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);
+ }
} 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);
- }
- } else {
- if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
- datasize += stat_size(&s);
+ if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
+ datasize += stat_size(&s);
+ }
}
}
+ closedir(d);
}
- 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;
diff --git a/cmds/installd/installd.cpp b/cmds/installd/installd.cpp
index 3a86181..01e7cdd 100644
--- a/cmds/installd/installd.cpp
+++ b/cmds/installd/installd.cpp
@@ -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 },
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index f31bf4f..ce6c857 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -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,
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index 4ce559d..5e397f9 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -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"));
}
}
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index ba411cd..3f679a2 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -37,16 +37,31 @@ 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';
@@ -77,6 +92,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.
*/
std::string create_data_user_path(const char* volume_uuid, userid_t userid) {