Refactor several utility functions

This commit is contained in:
topjohnwu 2017-08-20 21:36:32 +08:00
parent 1913125881
commit e3df62d812
7 changed files with 117 additions and 129 deletions

View File

@ -136,8 +136,7 @@ static void exec_common_script(const char* stage) {
if (access(buf2, X_OK) == -1) if (access(buf2, X_OK) == -1)
continue; continue;
LOGI("%s.d: exec [%s]\n", stage, entry->d_name); LOGI("%s.d: exec [%s]\n", stage, entry->d_name);
char *const command[] = { "sh", buf2, NULL }; int pid = exec_command(0, NULL, bb_setenv, "sh", buf2, NULL);
int pid = run_command2(0, NULL, bb_setenv, command);
if (pid != -1) if (pid != -1)
waitpid(pid, NULL, 0); waitpid(pid, NULL, 0);
} }
@ -154,8 +153,7 @@ static void exec_module_script(const char* stage) {
if (access(buf2, F_OK) == -1 || access(buf, F_OK) == 0) if (access(buf2, F_OK) == -1 || access(buf, F_OK) == 0)
continue; continue;
LOGI("%s: exec [%s.sh]\n", module, stage); LOGI("%s: exec [%s.sh]\n", module, stage);
char *const command[] = { "sh", buf2, NULL }; int pid = exec_command(0, NULL, bb_setenv, "sh", buf2, NULL);
int pid = run_command2(0, NULL, bb_setenv, command);
if (pid != -1) if (pid != -1)
waitpid(pid, NULL, 0); waitpid(pid, NULL, 0);
} }
@ -402,8 +400,7 @@ static void mount_mirrors() {
static void link_busybox() { static void link_busybox() {
mkdir_p(BBPATH, 0755); mkdir_p(BBPATH, 0755);
char *const command[] = { MIRRDIR "/bin/busybox", "--install", "-s", BBPATH, NULL}; exec_command_sync(MIRRDIR "/bin/busybox", "--install", "-s", BBPATH, NULL);
run_command(command);
symlink(MIRRDIR "/bin/busybox", BBPATH "/busybox"); symlink(MIRRDIR "/bin/busybox", BBPATH "/busybox");
} }
@ -442,7 +439,7 @@ static int prepare_img() {
snprintf(buf, PATH_MAX, "%s/%s/remove", MOUNTPOINT, entry->d_name); snprintf(buf, PATH_MAX, "%s/%s/remove", MOUNTPOINT, entry->d_name);
if (access(buf, F_OK) == 0) { if (access(buf, F_OK) == 0) {
snprintf(buf, PATH_MAX, "%s/%s", MOUNTPOINT, entry->d_name); snprintf(buf, PATH_MAX, "%s/%s", MOUNTPOINT, entry->d_name);
rm_rf(buf); exec_command_sync(BBPATH "/rm", "-rf", buf, NULL);
continue; continue;
} }
snprintf(buf, PATH_MAX, "%s/%s/disable", MOUNTPOINT, entry->d_name); snprintf(buf, PATH_MAX, "%s/%s/disable", MOUNTPOINT, entry->d_name);
@ -520,8 +517,7 @@ void post_fs_data(int client) {
#ifdef MAGISK_DEBUG #ifdef MAGISK_DEBUG
// Start debug logs in new process // Start debug logs in new process
debug_log_fd = xopen(DEBUG_LOG, O_WRONLY | O_CREAT | O_CLOEXEC | O_TRUNC, 0644); debug_log_fd = xopen(DEBUG_LOG, O_WRONLY | O_CREAT | O_CLOEXEC | O_TRUNC, 0644);
char *const command[] = { "logcat", "-v", "brief", NULL }; debug_log_pid = exec_command(0, &debug_log_fd, NULL, "logcat", "-v", "brief", NULL);
debug_log_pid = run_command2(0, &debug_log_fd, NULL, command);
close(debug_log_fd); close(debug_log_fd);
#endif #endif
@ -531,20 +527,25 @@ void post_fs_data(int client) {
if (buf == NULL) buf = xmalloc(PATH_MAX); if (buf == NULL) buf = xmalloc(PATH_MAX);
if (buf2 == NULL) buf2 = xmalloc(PATH_MAX); if (buf2 == NULL) buf2 = xmalloc(PATH_MAX);
// Cache support // Magisk binaries
if (access("/cache/data_bin", F_OK) == 0) { char *bin_path = NULL;
rm_rf(DATABIN); if (access("/cache/data_bin", F_OK) == 0)
rename("/cache/data_bin", DATABIN); bin_path = "/cache/data_bin";
else if (access("/data/local/tmp/magisk_inject", F_OK) == 0)
bin_path = "/data/local/tmp/magisk_inject";
if (bin_path) {
exec_command_sync("rm", "-rf", DATABIN, NULL);
exec_command_sync("cp", "-r", bin_path, DATABIN, NULL);
exec_command_sync("rm", "-rf", bin_path, NULL);
exec_command_sync("chmod", "-R", "755", bin_path, NULL);
} }
// Magisk Manual Injector support // Lazy.... use shell blob to match files
if (access("/data/local/tmp/magisk_inject", F_OK) == 0) { exec_command_sync("sh", "-c", "mv /data/magisk/stock_boot* /data", NULL);
rm_rf(DATABIN);
rename("/data/local/tmp/magisk_inject", DATABIN);
}
// Lazy.... use shell blob // Link busybox
system("mv /data/magisk/stock_boot* /data;"); mount_mirrors();
link_busybox();
// Merge images // Merge images
if (merge_img("/cache/magisk.img", MAINIMG)) { if (merge_img("/cache/magisk.img", MAINIMG)) {
@ -556,15 +557,12 @@ void post_fs_data(int client) {
goto unblock; goto unblock;
} }
// Link busybox
mount_mirrors();
link_busybox();
// uninstaller // uninstaller
if (access(UNINSTALLER, F_OK) == 0) { if (access(UNINSTALLER, F_OK) == 0) {
close(open(UNBLOCKFILE, O_RDONLY | O_CREAT)); close(open(UNBLOCKFILE, O_RDONLY | O_CREAT));
bb_setenv(); bb_setenv();
system("(BOOTMODE=true sh " UNINSTALLER ") &"); setenv("BOOTMODE", "true", 1);
exec_command(0, NULL, NULL, "sh", UNINSTALLER, NULL);
return; return;
} }
@ -704,11 +702,11 @@ core_only:
if (access(MANAGERAPK, F_OK) == 0) { if (access(MANAGERAPK, F_OK) == 0) {
while (1) { while (1) {
sleep(5); sleep(5);
char *const command[] = { "app_process",
"/system/bin", "com.android.commands.pm.Pm",
"install", "-r", MANAGERAPK, NULL };
int apk_res = -1, pid; int apk_res = -1, pid;
pid = run_command2(1, &apk_res, pm_setenv, command); pid = exec_command(1, &apk_res, pm_setenv,
"app_process",
"/system/bin", "com.android.commands.pm.Pm",
"install", "-r", MANAGERAPK, NULL);
if (pid != -1) { if (pid != -1) {
waitpid(pid, NULL, 0); waitpid(pid, NULL, 0);
fdgets(buf, PATH_MAX, apk_res); fdgets(buf, PATH_MAX, apk_res);

View File

@ -26,13 +26,11 @@ static void *logger_thread(void *args) {
while (1) { while (1) {
// Start logcat // Start logcat
char *const command[] = { "logcat", "-s", "Magisk", "-v", "thread", NULL }; log_pid = exec_command(0, &log_fd, NULL, "logcat", "-s", "Magisk", "-v", "thread", NULL);
log_pid = run_command2(0, &log_fd, NULL, command);
if (log_pid > 0) if (log_pid > 0)
waitpid(log_pid, NULL, 0); waitpid(log_pid, NULL, 0);
// For some reason it went here, clear buffer and restart // For some reason it went here, clear buffer and restart
char *const restart[] = { "logcat", "-c", NULL }; exec_command_sync("logcat", "-c", NULL);
run_command(restart);
} }
// Should never be here, but well... // Should never be here, but well...

View File

@ -75,21 +75,18 @@ unsigned get_radio_uid();
int check_data(); int check_data();
int file_to_vector(const char* filename, struct vector *v); int file_to_vector(const char* filename, struct vector *v);
int vector_to_file(const char* filename, struct vector *v); int vector_to_file(const char* filename, struct vector *v);
int isNum(const char *s);
ssize_t fdgets(char *buf, size_t size, int fd); ssize_t fdgets(char *buf, size_t size, int fd);
void ps(void (*func)(int)); void ps(void (*func)(int));
void ps_filter_proc_name(const char *filter, void (*func)(int)); void ps_filter_proc_name(const char *filter, void (*func)(int));
int create_links(const char *bin, const char *path); int create_links(const char *bin, const char *path);
void unlock_blocks(); void unlock_blocks();
void setup_sighandlers(void (*handler)(int)); void setup_sighandlers(void (*handler)(int));
int run_command(char *const argv[]); int exec_command(int err, int *fd, void (*cb)(void), const char *argv0, ...);
int run_command2(int err, int *fd, void (*cb)(void), char *const argv[]); int exec_command_sync(char *const argv0, ...);
int mkdir_p(const char *pathname, mode_t mode); int mkdir_p(const char *pathname, mode_t mode);
int bind_mount(const char *from, const char *to); int bind_mount(const char *from, const char *to);
int open_new(const char *filename); int open_new(const char *filename);
int cp_afc(const char *source, const char *target); int cp_afc(const char *source, const char *target);
int clone_dir(const char *source, const char *target);
void rm_rf(const char *target);
void fclone_attr(const int sourcefd, const int targetfd); void fclone_attr(const int sourcefd, const int targetfd);
void clone_attr(const char *source, const char *target); void clone_attr(const char *source, const char *target);
void get_client_cred(int fd, struct ucred *cred); void get_client_cred(int fd, struct ucred *cred);

View File

@ -32,4 +32,4 @@ struct vector *vec_dup(struct vector *v);
e = v ? (v)->data[(v)->size - 1] : NULL; \ e = v ? (v)->data[(v)->size - 1] : NULL; \
for (size_t _ = (v)->size; v && _ > 0; --_, e = (v)->data[_ - 1]) for (size_t _ = (v)->size; v && _ > 0; --_, e = (v)->data[_ - 1])
#endif #endif

View File

@ -181,13 +181,11 @@ void proc_monitor() {
while (1) { while (1) {
// Clear previous logcat buffer // Clear previous logcat buffer
char *const restart[] = { "logcat", "-b", "events", "-c", NULL }; exec_command_sync("logcat", "-b", "events", "-c", NULL);
run_command(restart);
// Monitor am_proc_start // Monitor am_proc_start
char *const command[] = { "logcat", "-b", "events", "-v", "raw", "-s", "am_proc_start", NULL };
log_fd = -1; log_fd = -1;
log_pid = run_command2(0, &log_fd, NULL, command); log_pid = exec_command(0, &log_fd, NULL, "logcat", "-b", "events", "-v", "raw", "-s", "am_proc_start", NULL);
if (log_pid < 0) continue; if (log_pid < 0) continue;
if (kill(log_pid, 0)) continue; if (kill(log_pid, 0)) continue;

View File

@ -14,8 +14,7 @@ static int e2fsck(const char *img) {
// Check and repair ext4 image // Check and repair ext4 image
char buffer[128]; char buffer[128];
int pid, fd = -1; int pid, fd = -1;
char *const command[] = { "e2fsck", "-yf", (char *) img, NULL }; pid = exec_command(1, &fd, NULL, "e2fsck", "-yf", img, NULL);
pid = run_command2(1, &fd, NULL, command);
if (pid < 0) if (pid < 0)
return 1; return 1;
while (fdgets(buffer, sizeof(buffer), fd)) while (fdgets(buffer, sizeof(buffer), fd))
@ -56,19 +55,17 @@ int create_img(const char *img, int size) {
char file_contexts[] = "/magisk(/.*)? u:object_r:system_file:s0\n"; char file_contexts[] = "/magisk(/.*)? u:object_r:system_file:s0\n";
// If not root, attempt to create in current diretory // If not root, attempt to create in current diretory
char *filename = getuid() == UID_ROOT ? "/dev/file_contexts_image" : "file_contexts_image"; char *filename = getuid() == UID_ROOT ? "/dev/file_contexts_image" : "file_contexts_image";
int pid, status, fd = xopen(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644); int ret, fd = xopen(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
xwrite(fd, file_contexts, sizeof(file_contexts)); xwrite(fd, file_contexts, sizeof(file_contexts));
close(fd); close(fd);
char buffer[16]; char buffer[16];
snprintf(buffer, sizeof(buffer), "%dM", size); snprintf(buffer, sizeof(buffer), "%dM", size);
char *const command[] = { "make_ext4fs", "-l", buffer, "-a", "/magisk", "-S", filename, (char *) img, NULL }; ret = exec_command_sync("make_ext4fs", "-l", buffer, "-a", "/magisk", "-S", filename, img, NULL);
pid = run_command2(0, NULL, NULL, command); if (ret < 0)
if (pid < 0)
return 1; return 1;
waitpid(pid, &status, 0);
unlink(filename); unlink(filename);
return WEXITSTATUS(status); return ret;
} }
int get_img_size(const char *img, int *used, int *total) { int get_img_size(const char *img, int *used, int *total) {
@ -76,8 +73,7 @@ int get_img_size(const char *img, int *used, int *total) {
return 1; return 1;
char buffer[PATH_MAX]; char buffer[PATH_MAX];
int pid, fd = -1, status = 1; int pid, fd = -1, status = 1;
char *const command[] = { "e2fsck", "-n", (char *) img, NULL }; pid = exec_command(1, &fd, NULL, "e2fsck", "-n", img, NULL);
pid = run_command2(1, &fd, NULL, command);
if (pid < 0) if (pid < 0)
return 1; return 1;
while (fdgets(buffer, sizeof(buffer), fd)) { while (fdgets(buffer, sizeof(buffer), fd)) {
@ -109,8 +105,7 @@ int resize_img(const char *img, int size) {
char buffer[128]; char buffer[128];
int pid, status, fd = -1; int pid, status, fd = -1;
snprintf(buffer, sizeof(buffer), "%dM", size); snprintf(buffer, sizeof(buffer), "%dM", size);
char *const command[] = { "resize2fs", (char *) img, buffer, NULL }; pid = exec_command(1, &fd, NULL, "resize2fs", img, buffer, NULL);
pid = run_command2(1, &fd, NULL, command);
if (pid < 0) if (pid < 0)
return 1; return 1;
while (fdgets(buffer, sizeof(buffer), fd)) while (fdgets(buffer, sizeof(buffer), fd))
@ -188,14 +183,14 @@ int merge_img(const char *source, const char *target) {
snprintf(buffer, sizeof(buffer), "%s/%s", TARGET_TMP, entry->d_name); snprintf(buffer, sizeof(buffer), "%s/%s", TARGET_TMP, entry->d_name);
if (access(buffer, F_OK) == 0) { if (access(buffer, F_OK) == 0) {
LOGI("Upgrade module: %s\n", entry->d_name); LOGI("Upgrade module: %s\n", entry->d_name);
rm_rf(buffer); exec_command_sync(BBPATH "/rm", "-rf", buffer, NULL);
} else { } else {
LOGI("New module: %s\n", entry->d_name); LOGI("New module: %s\n", entry->d_name);
} }
} }
} }
closedir(dir); closedir(dir);
clone_dir(SOURCE_TMP, TARGET_TMP); cp_afc(SOURCE_TMP, TARGET_TMP);
// Unmount all loop devices // Unmount all loop devices
umount_image(SOURCE_TMP, s_loop); umount_image(SOURCE_TMP, s_loop);

View File

@ -5,6 +5,7 @@
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h>
#include <dirent.h> #include <dirent.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
@ -97,7 +98,7 @@ int vector_to_file(const char *filename, struct vector *v) {
} }
/* Check if the string only contains digits */ /* Check if the string only contains digits */
int isNum(const char *s) { static int is_num(const char *s) {
int len = strlen(s); int len = strlen(s);
for (int i = 0; i < len; ++i) for (int i = 0; i < len; ++i)
if (s[i] < '0' || s[i] > '9') if (s[i] < '0' || s[i] > '9')
@ -129,7 +130,7 @@ void ps(void (*func)(int)) {
while ((entry = xreaddir(dir))) { while ((entry = xreaddir(dir))) {
if (entry->d_type == DT_DIR) { if (entry->d_type == DT_DIR) {
if (isNum(entry->d_name)) if (is_num(entry->d_name))
func(atoi(entry->d_name)); func(atoi(entry->d_name));
} }
} }
@ -219,22 +220,13 @@ void setup_sighandlers(void (*handler)(int)) {
} }
} }
int run_command(char *const argv[]) {
int pid = run_command2(0, NULL, NULL, argv);
if (pid != -1)
waitpid(pid, NULL, 0);
else
return 1;
return 0;
}
/* /*
fd == NULL -> Ignore output fd == NULL -> Ignore output
*fd < 0 -> Open pipe and set *fd to the read end *fd < 0 -> Open pipe and set *fd to the read end
*fd >= 0 -> STDOUT (or STDERR) will be redirected to *fd *fd >= 0 -> STDOUT (or STDERR) will be redirected to *fd
*cb -> A callback function which runs after fork *cb -> A callback function which runs after fork
*/ */
int run_command2(int err, int *fd, void (*cb)(void), char *const argv[]) { static int v_exec_command(int err, int *fd, void (*cb)(void), const char *argv0, va_list argv) {
int pipefd[2], writeEnd = -1; int pipefd[2], writeEnd = -1;
if (fd) { if (fd) {
@ -257,6 +249,9 @@ int run_command2(int err, int *fd, void (*cb)(void), char *const argv[]) {
return pid; return pid;
} }
// Don't affect the daemon if anything wrong happens
err_handler = do_nothing;
if (cb) cb(); if (cb) cb();
if (fd) { if (fd) {
@ -264,11 +259,39 @@ int run_command2(int err, int *fd, void (*cb)(void), char *const argv[]) {
if (err) xdup2(writeEnd, STDERR_FILENO); if (err) xdup2(writeEnd, STDERR_FILENO);
} }
execvp(argv[0], argv); // Collect va_list into vector
PLOGE("execv"); struct vector v;
vec_init(&v);
vec_push_back(&v, (void *) argv0);
for (void *arg = va_arg(argv, void*); arg; arg = va_arg(argv, void*))
vec_push_back(&v, arg);
vec_push_back(&v, NULL);
execvp(argv0, (char **) vec_entry(&v));
PLOGE("execvp");
return -1; return -1;
} }
int exec_command_sync(char *const argv0, ...) {
va_list argv;
va_start(argv, argv0);
int pid, status;
pid = v_exec_command(0, NULL, NULL, argv0, argv);
va_end(argv);
if (pid < 0)
return pid;
waitpid(pid, &status, 0);
return WEXITSTATUS(status);
}
int exec_command(int err, int *fd, void (*cb)(void), const char *argv0, ...) {
va_list argv;
va_start(argv, argv0);
int pid = v_exec_command(err, fd, cb, argv0, argv);
va_end(argv);
return pid;
}
int mkdir_p(const char *pathname, mode_t mode) { int mkdir_p(const char *pathname, mode_t mode) {
char *path = strdup(pathname), *p; char *path = strdup(pathname), *p;
errno = 0; errno = 0;
@ -304,78 +327,57 @@ int open_new(const char *filename) {
return xopen(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644); return xopen(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
} }
// file/link -> file/link only!!
int cp_afc(const char *source, const char *target) { int cp_afc(const char *source, const char *target) {
struct stat buf; struct stat buf;
xlstat(source, &buf); xlstat(source, &buf);
unlink(target);
char *con;
if (S_ISREG(buf.st_mode)) {
int sfd, tfd;
sfd = xopen(source, O_RDONLY);
tfd = xopen(target, O_WRONLY | O_CREAT | O_TRUNC);
xsendfile(tfd, sfd, NULL, buf.st_size);
fclone_attr(sfd, tfd);
close(sfd);
close(tfd);
} else if (S_ISLNK(buf.st_mode)) {
char buffer[PATH_MAX];
xreadlink(source, buffer, sizeof(buffer));
xsymlink(buffer, target);
lchown(target, buf.st_uid, buf.st_gid);
lgetfilecon(source, &con);
lsetfilecon(target, con);
free(con);
} else {
return 1;
}
return 0;
}
int clone_dir(const char *source, const char *target) { if (S_ISDIR(buf.st_mode)) {
DIR *dir; DIR *dir;
struct dirent *entry; struct dirent *entry;
char *s_path, *t_path; char *s_path, *t_path;
if (!(dir = xopendir(source))) if (!(dir = xopendir(source)))
return 1; return 1;
s_path = xmalloc(PATH_MAX); s_path = xmalloc(PATH_MAX);
t_path = xmalloc(PATH_MAX); t_path = xmalloc(PATH_MAX);
mkdir_p(target, 0755); mkdir_p(target, 0755);
clone_attr(source, target); clone_attr(source, target);
while ((entry = xreaddir(dir))) { while ((entry = xreaddir(dir))) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
continue; continue;
snprintf(s_path, PATH_MAX, "%s/%s", source, entry->d_name); snprintf(s_path, PATH_MAX, "%s/%s", source, entry->d_name);
snprintf(t_path, PATH_MAX, "%s/%s", target, entry->d_name); snprintf(t_path, PATH_MAX, "%s/%s", target, entry->d_name);
switch (entry->d_type) {
case DT_DIR:
clone_dir(s_path, t_path);
break;
case DT_REG:
case DT_LNK:
cp_afc(s_path, t_path); cp_afc(s_path, t_path);
break; }
free(s_path);
free(t_path);
closedir(dir);
} else{
unlink(target);
if (S_ISREG(buf.st_mode)) {
int sfd, tfd;
sfd = xopen(source, O_RDONLY);
tfd = xopen(target, O_WRONLY | O_CREAT | O_TRUNC);
xsendfile(tfd, sfd, NULL, buf.st_size);
fclone_attr(sfd, tfd);
close(sfd);
close(tfd);
} else if (S_ISLNK(buf.st_mode)) {
char buffer[PATH_MAX];
xreadlink(source, buffer, sizeof(buffer));
xsymlink(buffer, target);
clone_attr(source, target);
} else {
return 1;
} }
} }
free(s_path);
free(t_path);
closedir(dir);
return 0; return 0;
} }
void rm_rf(const char *target) {
if (access(target, F_OK) == -1)
return;
// Use external rm command, saves a lot of headache and issues
char *const command[] = { "rm", "-rf", (char*) target, NULL };
run_command(command);
}
void clone_attr(const char *source, const char *target) { void clone_attr(const char *source, const char *target) {
int sourcefd, targetfd; int sourcefd, targetfd;
sourcefd = xopen(source, O_RDONLY); sourcefd = xopen(source, O_RDONLY);