mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-11-30 13:35:27 +00:00
Refactor several utility functions
This commit is contained in:
parent
1913125881
commit
e3df62d812
@ -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);
|
||||||
|
@ -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...
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
112
jni/utils/misc.c
112
jni/utils/misc.c
@ -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,35 +327,11 @@ 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;
|
||||||
@ -351,29 +350,32 @@ int clone_dir(const char *source, const char *target) {
|
|||||||
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(s_path);
|
||||||
free(t_path);
|
free(t_path);
|
||||||
|
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
return 0;
|
} 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;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
void rm_rf(const char *target) {
|
return 0;
|
||||||
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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user