Add an installd command to prune dex files.

This is a straightforward port of logic from
PackageManagerService#pruneDexFiles.

bug: 14407732

Change-Id: I892cff027ddcbb1a4fb37a7af5ecf1697049a188
This commit is contained in:
Narayan Kamath 2014-06-10 13:16:47 +01:00
parent 065e9c86e2
commit 3aee2c5c74
4 changed files with 54 additions and 12 deletions

View File

@ -73,7 +73,7 @@ int install(const char *pkgname, uid_t uid, gid_t gid, const char *seinfo)
} }
} else { } else {
if (S_ISDIR(libStat.st_mode)) { if (S_ISDIR(libStat.st_mode)) {
if (delete_dir_contents(libsymlink, 1, 0) < 0) { if (delete_dir_contents(libsymlink, 1, NULL) < 0) {
ALOGE("couldn't delete lib directory during install for: %s", libsymlink); ALOGE("couldn't delete lib directory during install for: %s", libsymlink);
return -1; return -1;
} }
@ -176,6 +176,10 @@ int fix_uid(const char *pkgname, uid_t uid, gid_t gid)
return 0; return 0;
} }
static int lib_dir_matcher(const char* file_name, const int is_dir) {
return is_dir && !strcmp(file_name, "lib");
}
int delete_user_data(const char *pkgname, userid_t userid) int delete_user_data(const char *pkgname, userid_t userid)
{ {
char pkgdir[PKG_PATH_MAX]; char pkgdir[PKG_PATH_MAX];
@ -184,7 +188,7 @@ int delete_user_data(const char *pkgname, userid_t userid)
return -1; return -1;
/* delete contents, excluding "lib", but not the directory itself */ /* delete contents, excluding "lib", but not the directory itself */
return delete_dir_contents(pkgdir, 0, "lib"); return delete_dir_contents(pkgdir, 0, &lib_dir_matcher);
} }
int make_user_data(const char *pkgname, uid_t uid, userid_t userid, const char* seinfo) int make_user_data(const char *pkgname, uid_t uid, userid_t userid, const char* seinfo)
@ -225,7 +229,7 @@ int make_user_data(const char *pkgname, uid_t uid, userid_t userid, const char*
} }
} else { } else {
if (S_ISDIR(libStat.st_mode)) { if (S_ISDIR(libStat.st_mode)) {
if (delete_dir_contents(libsymlink, 1, 0) < 0) { if (delete_dir_contents(libsymlink, 1, NULL) < 0) {
ALOGE("couldn't delete lib directory during install for non-primary: %s", ALOGE("couldn't delete lib directory during install for non-primary: %s",
libsymlink); libsymlink);
unlink(pkgdir); unlink(pkgdir);
@ -294,7 +298,7 @@ int delete_cache(const char *pkgname, userid_t userid)
return -1; return -1;
/* delete contents, not the directory, no exceptions */ /* delete contents, not the directory, no exceptions */
return delete_dir_contents(cachedir, 0, 0); return delete_dir_contents(cachedir, 0, NULL);
} }
/* Try to ensure free_size bytes of storage are available. /* Try to ensure free_size bytes of storage are available.
@ -1105,7 +1109,7 @@ int linklib(const char* pkgname, const char* asecLibDir, int userId)
} }
} else { } else {
if (S_ISDIR(libStat.st_mode)) { if (S_ISDIR(libStat.st_mode)) {
if (delete_dir_contents(libsymlink, 1, 0) < 0) { if (delete_dir_contents(libsymlink, 1, NULL) < 0) {
rc = -1; rc = -1;
goto out; goto out;
} }
@ -1330,3 +1334,30 @@ int restorecon_data(const char* pkgName, const char* seinfo, uid_t uid)
free(userdir); free(userdir);
return ret; return ret;
} }
static int prune_dex_exclusion_predicate(const char *file_name, const int is_dir)
{
// Don't exclude any directories, we want to inspect them
// recusively for files.
if (is_dir) {
return 0;
}
// Don't exclude regular files that start with the list
// of prefixes.
static const char data_app_prefix[] = "data@app@";
static const char data_priv_app_prefix[] = "data@priv-app@";
if (!strncmp(file_name, data_app_prefix, sizeof(data_app_prefix) - 1) ||
!strncmp(file_name, data_priv_app_prefix, sizeof(data_priv_app_prefix) - 1)) {
return 0;
}
// Exclude all regular files that don't start with the prefix "data@app@" or
// "data@priv-app@".
return 1;
}
int prune_dex_cache() {
return delete_dir_contents(DALVIK_CACHE_PREFIX, 0, &prune_dex_exclusion_predicate);
}

View File

@ -135,6 +135,12 @@ static int do_restorecon_data(char **arg, char reply[REPLY_MAX] __attribute__((u
/* pkgName, seinfo, uid*/ /* pkgName, seinfo, uid*/
} }
static int do_prune_dex_cache(char **arg __attribute__((unused)),
char reply[REPLY_MAX] __attribute__((unused)))
{
return prune_dex_cache();
}
struct cmdinfo { struct cmdinfo {
const char *name; const char *name;
unsigned numargs; unsigned numargs;
@ -160,6 +166,7 @@ struct cmdinfo cmds[] = {
{ "rmuser", 1, do_rm_user }, { "rmuser", 1, do_rm_user },
{ "idmap", 3, do_idmap }, { "idmap", 3, do_idmap },
{ "restorecondata", 3, do_restorecon_data }, { "restorecondata", 3, do_restorecon_data },
{ "prunedexcache", 0, do_prune_dex_cache },
}; };
static int readx(int s, void *_buf, int count) static int readx(int s, void *_buf, int count)

View File

@ -157,7 +157,7 @@ int create_cache_path(char path[PKG_PATH_MAX], const char *src,
int delete_dir_contents(const char *pathname, int delete_dir_contents(const char *pathname,
int also_delete_dir, int also_delete_dir,
const char *ignore); int (*exclusion_predicate)(const char *name, const int is_dir));
int delete_dir_contents_fd(int dfd, const char *name); int delete_dir_contents_fd(int dfd, const char *name);
@ -216,3 +216,4 @@ int movefiles();
int linklib(const char* target, const char* source, int userId); int linklib(const char* target, const char* source, int userId);
int idmap(const char *target_path, const char *overlay_path, uid_t uid); int idmap(const char *target_path, const char *overlay_path, uid_t uid);
int restorecon_data(); int restorecon_data();
int prune_dex_cache();

View File

@ -208,7 +208,8 @@ int is_valid_package_name(const char* pkgname) {
return 0; return 0;
} }
static int _delete_dir_contents(DIR *d, const char *ignore) static int _delete_dir_contents(DIR *d,
int (*exclusion_predicate)(const char *name, const int is_dir))
{ {
int result = 0; int result = 0;
struct dirent *de; struct dirent *de;
@ -221,8 +222,10 @@ static int _delete_dir_contents(DIR *d, const char *ignore)
while ((de = readdir(d))) { while ((de = readdir(d))) {
const char *name = de->d_name; const char *name = de->d_name;
/* skip the ignore name if provided */ /* check using the exclusion predicate, if provided */
if (ignore && !strcmp(name, ignore)) continue; if (exclusion_predicate && exclusion_predicate(name, (de->d_type == DT_DIR))) {
continue;
}
if (de->d_type == DT_DIR) { if (de->d_type == DT_DIR) {
int r, subfd; int r, subfd;
@ -247,7 +250,7 @@ static int _delete_dir_contents(DIR *d, const char *ignore)
result = -1; result = -1;
continue; continue;
} }
if (_delete_dir_contents(subdir, 0)) { if (_delete_dir_contents(subdir, exclusion_predicate)) {
result = -1; result = -1;
} }
closedir(subdir); closedir(subdir);
@ -268,7 +271,7 @@ static int _delete_dir_contents(DIR *d, const char *ignore)
int delete_dir_contents(const char *pathname, int delete_dir_contents(const char *pathname,
int also_delete_dir, int also_delete_dir,
const char *ignore) int (*exclusion_predicate)(const char*, const int))
{ {
int res = 0; int res = 0;
DIR *d; DIR *d;
@ -278,7 +281,7 @@ int delete_dir_contents(const char *pathname,
ALOGE("Couldn't opendir %s: %s\n", pathname, strerror(errno)); ALOGE("Couldn't opendir %s: %s\n", pathname, strerror(errno));
return -errno; return -errno;
} }
res = _delete_dir_contents(d, ignore); res = _delete_dir_contents(d, exclusion_predicate);
closedir(d); closedir(d);
if (also_delete_dir) { if (also_delete_dir) {
if (rmdir(pathname)) { if (rmdir(pathname)) {