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

@@ -14,8 +14,7 @@ static int e2fsck(const char *img) {
// Check and repair ext4 image
char buffer[128];
int pid, fd = -1;
char *const command[] = { "e2fsck", "-yf", (char *) img, NULL };
pid = run_command2(1, &fd, NULL, command);
pid = exec_command(1, &fd, NULL, "e2fsck", "-yf", img, NULL);
if (pid < 0)
return 1;
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";
// If not root, attempt to create in current diretory
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));
close(fd);
char buffer[16];
snprintf(buffer, sizeof(buffer), "%dM", size);
char *const command[] = { "make_ext4fs", "-l", buffer, "-a", "/magisk", "-S", filename, (char *) img, NULL };
pid = run_command2(0, NULL, NULL, command);
if (pid < 0)
ret = exec_command_sync("make_ext4fs", "-l", buffer, "-a", "/magisk", "-S", filename, img, NULL);
if (ret < 0)
return 1;
waitpid(pid, &status, 0);
unlink(filename);
return WEXITSTATUS(status);
return ret;
}
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;
char buffer[PATH_MAX];
int pid, fd = -1, status = 1;
char *const command[] = { "e2fsck", "-n", (char *) img, NULL };
pid = run_command2(1, &fd, NULL, command);
pid = exec_command(1, &fd, NULL, "e2fsck", "-n", img, NULL);
if (pid < 0)
return 1;
while (fdgets(buffer, sizeof(buffer), fd)) {
@@ -109,8 +105,7 @@ int resize_img(const char *img, int size) {
char buffer[128];
int pid, status, fd = -1;
snprintf(buffer, sizeof(buffer), "%dM", size);
char *const command[] = { "resize2fs", (char *) img, buffer, NULL };
pid = run_command2(1, &fd, NULL, command);
pid = exec_command(1, &fd, NULL, "resize2fs", img, buffer, NULL);
if (pid < 0)
return 1;
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);
if (access(buffer, F_OK) == 0) {
LOGI("Upgrade module: %s\n", entry->d_name);
rm_rf(buffer);
exec_command_sync(BBPATH "/rm", "-rf", buffer, NULL);
} else {
LOGI("New module: %s\n", entry->d_name);
}
}
}
closedir(dir);
clone_dir(SOURCE_TMP, TARGET_TMP);
cp_afc(SOURCE_TMP, TARGET_TMP);
// Unmount all loop devices
umount_image(SOURCE_TMP, s_loop);

View File

@@ -5,6 +5,7 @@
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <dirent.h>
#include <unistd.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 */
int isNum(const char *s) {
static int is_num(const char *s) {
int len = strlen(s);
for (int i = 0; i < len; ++i)
if (s[i] < '0' || s[i] > '9')
@@ -129,7 +130,7 @@ void ps(void (*func)(int)) {
while ((entry = xreaddir(dir))) {
if (entry->d_type == DT_DIR) {
if (isNum(entry->d_name))
if (is_num(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 < 0 -> Open pipe and set *fd to the read end
*fd >= 0 -> STDOUT (or STDERR) will be redirected to *fd
*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;
if (fd) {
@@ -257,6 +249,9 @@ int run_command2(int err, int *fd, void (*cb)(void), char *const argv[]) {
return pid;
}
// Don't affect the daemon if anything wrong happens
err_handler = do_nothing;
if (cb) cb();
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);
}
execvp(argv[0], argv);
PLOGE("execv");
// Collect va_list into vector
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;
}
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) {
char *path = strdup(pathname), *p;
errno = 0;
@@ -304,78 +327,57 @@ int open_new(const char *filename) {
return xopen(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
}
// file/link -> file/link only!!
int cp_afc(const char *source, const char *target) {
struct stat 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) {
DIR *dir;
struct dirent *entry;
char *s_path, *t_path;
if (S_ISDIR(buf.st_mode)) {
DIR *dir;
struct dirent *entry;
char *s_path, *t_path;
if (!(dir = xopendir(source)))
return 1;
if (!(dir = xopendir(source)))
return 1;
s_path = xmalloc(PATH_MAX);
t_path = xmalloc(PATH_MAX);
s_path = xmalloc(PATH_MAX);
t_path = xmalloc(PATH_MAX);
mkdir_p(target, 0755);
clone_attr(source, target);
mkdir_p(target, 0755);
clone_attr(source, target);
while ((entry = xreaddir(dir))) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
continue;
snprintf(s_path, PATH_MAX, "%s/%s", source, 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:
while ((entry = xreaddir(dir))) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
continue;
snprintf(s_path, PATH_MAX, "%s/%s", source, entry->d_name);
snprintf(t_path, PATH_MAX, "%s/%s", target, entry->d_name);
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;
}
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) {
int sourcefd, targetfd;
sourcefd = xopen(source, O_RDONLY);