More optimized APK traversal

This commit is contained in:
topjohnwu 2019-02-14 00:52:59 -05:00
parent 4eed6794c7
commit d584360de2
3 changed files with 54 additions and 42 deletions

View File

@ -188,51 +188,64 @@ static bool process_pid(int pid) {
return true;
}
static void listdir_apk(const char *name) {
DIR *dir;
struct dirent *entry;
const char *ext;
char path[4096];
static int xinotify_add_watch(int fd, const char* path, uint32_t mask) {
int ret = inotify_add_watch(fd, path, mask);
if (ret >= 0) {
LOGI("proc_monitor: Monitoring %s\n", path);
} else {
PLOGE("proc_monitor: Monitor %s", path);
}
return ret;
}
if (!(dir = opendir(name)))
static char *append_path(char *eof, const char *name) {
*(eof++) = '/';
char c;
while ((c = *(name++)))
*(eof++) = c;
*eof = '\0';
return eof;
}
#define DATA_APP "/data/app"
static void find_apks(char *path, char *eof) {
DIR *dir = opendir(path);
if (dir == nullptr)
return;
while ((entry = readdir(dir)) != NULL) {
snprintf(path, sizeof(path), "%s/%s", name,
entry->d_name);
// assert(*eof == '\0');
struct dirent *entry;
while ((entry = xreaddir(dir))) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
continue;
if (entry->d_type == DT_DIR) {
if (strcmp(entry->d_name, ".") == 0
|| strcmp(entry->d_name, "..") == 0)
continue;
listdir_apk(path);
} else {
ext = &path[strlen(path) - 4];
if (!strncmp(".apk", ext, 4)) {
pthread_mutex_lock(&list_lock);
for (auto &s : hide_list) {
// Compare with (path + 10) to trim "/data/app/"
if (strncmp(path + 10, s.c_str(), s.length()) == 0) {
if (inotify_add_watch(inotify_fd, path, IN_OPEN | IN_DELETE) > 0) {
LOGI("proc_monitor: Monitoring %s\n", path);
} else {
LOGE("proc_monitor: Failed to monitor %s: %s\n", path, strerror(errno));
}
break;
}
find_apks(path, append_path(eof, entry->d_name));
*eof = '\0';
} else if (strend(entry->d_name, ".apk") == 0) {
// Path will be in this format: /data/app/[pkg]-[hash or 1 or 2]
char *dash = strchr(path, '-');
*dash = '\0';
for (auto &s : hide_list) {
if (s == path + sizeof(DATA_APP)) {
*dash = '-';
append_path(eof, entry->d_name);
xinotify_add_watch(inotify_fd, path, IN_OPEN | IN_DELETE);
*eof = '\0';
break;
}
pthread_mutex_unlock(&list_lock);
}
*dash = '-';
break;
}
}
closedir(dir);
}
// Iterate through /data/app and search all .apk files
void update_inotify_mask() {
// Setup inotify
const char data_app[] = "/data/app";
char buf[4096];
if (inotify_fd >= 0)
close(inotify_fd);
@ -244,14 +257,13 @@ void update_inotify_mask() {
}
LOGI("proc_monitor: Updating APK list\n");
listdir_apk(data_app);
strcpy(buf, DATA_APP);
pthread_mutex_lock(&list_lock);
find_apks(buf, buf + sizeof(DATA_APP) - 1);
pthread_mutex_unlock(&list_lock);
// Add /data/app itself to the watch list to detect app (un)installations/updates
if (inotify_add_watch(inotify_fd, data_app, IN_CLOSE_WRITE | IN_MOVED_TO | IN_DELETE) > 0) {
LOGI("proc_monitor: Monitoring %s\n", data_app, inotify_fd);
} else {
LOGE("proc_monitor: Failed to monitor %s: %s\n", strerror(errno));
}
xinotify_add_watch(inotify_fd, DATA_APP, IN_CLOSE_WRITE | IN_MOVED_TO | IN_DELETE);
}
void proc_monitor() {

View File

@ -60,7 +60,7 @@ int mkdirs(const char *pathname, mode_t mode) {
return 0;
}
void in_order_walk(int dirfd, void (*callback)(int, struct dirent*)) {
void post_order_walk(int dirfd, void (*fn)(int, struct dirent *)) {
struct dirent *entry;
int newfd;
DIR *dir = fdopendir(dirfd);
@ -73,10 +73,10 @@ void in_order_walk(int dirfd, void (*callback)(int, struct dirent*)) {
continue;
if (entry->d_type == DT_DIR) {
newfd = xopenat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC);
in_order_walk(newfd, callback);
post_order_walk(newfd, fn);
close(newfd);
}
callback(dirfd, entry);
fn(dirfd, entry);
}
}
@ -93,7 +93,7 @@ void rm_rf(const char *path) {
}
void frm_rf(int dirfd) {
in_order_walk(dirfd, [](auto dirfd, auto entry) -> void {
post_order_walk(dirfd, [](auto dirfd, auto entry) -> void {
unlinkat(dirfd, entry->d_name, entry->d_type == DT_DIR ? AT_REMOVEDIR : 0);
});
}

View File

@ -108,7 +108,7 @@ struct file_attr {
int fd_getpath(int fd, char *path, size_t size);
int fd_getpathat(int dirfd, const char *name, char *path, size_t size);
int mkdirs(const char *pathname, mode_t mode);
void in_order_walk(int dirfd, void (*callback)(int, struct dirent*));
void post_order_walk(int dirfd, void (*fn)(int, struct dirent *));
void rm_rf(const char *path);
void frm_rf(int dirfd);
void mv_f(const char *source, const char *destination);