mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-10-16 21:53:04 +00:00
Refactor several utility functions
This commit is contained in:
@@ -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);
|
||||
|
146
jni/utils/misc.c
146
jni/utils/misc.c
@@ -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);
|
||||
|
Reference in New Issue
Block a user