From 04538372c6e6b3aedc26330c2d4aa98c8183c0ea Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Sat, 24 Jun 2017 23:37:45 +0900 Subject: [PATCH] Add more image commands --- jni/Android.mk | 1 + jni/daemon/bootstages.c | 38 ------------ jni/main.c | 22 ++++++- jni/utils/img.c | 128 ++++++++++++++++++++++++++++++++++++++++ jni/utils/misc.c | 72 ---------------------- jni/utils/utils.h | 7 ++- 6 files changed, 155 insertions(+), 113 deletions(-) create mode 100644 jni/utils/img.c diff --git a/jni/Android.mk b/jni/Android.mk index 30d522e7f..19949fc68 100644 --- a/jni/Android.mk +++ b/jni/Android.mk @@ -20,6 +20,7 @@ LOCAL_SRC_FILES := \ utils/vector.c \ utils/xwrap.c \ utils/list.c \ + utils/img.c \ daemon/daemon.c \ daemon/socket_trans.c \ daemon/log_monitor.c \ diff --git a/jni/daemon/bootstages.c b/jni/daemon/bootstages.c index 7314842f5..035dc9670 100644 --- a/jni/daemon/bootstages.c +++ b/jni/daemon/bootstages.c @@ -54,44 +54,6 @@ struct node_entry { * Image handling * ******************/ -static char *loopsetup(const char *img) { - char device[20]; - struct loop_info64 info; - int i, lfd, ffd; - memset(&info, 0, sizeof(info)); - // First get an empty loop device - for (i = 0; i <= 7; ++i) { - sprintf(device, "/dev/block/loop%d", i); - lfd = xopen(device, O_RDWR); - if (ioctl(lfd, LOOP_GET_STATUS64, &info) == -1) - break; - close(lfd); - } - if (i == 8) return NULL; - ffd = xopen(img, O_RDWR); - if (ioctl(lfd, LOOP_SET_FD, ffd) == -1) - return NULL; - strcpy((char *) info.lo_file_name, img); - ioctl(lfd, LOOP_SET_STATUS64, &info); - close(lfd); - close(ffd); - return strdup(device); -} - -static char *mount_image(const char *img, const char *target) { - char *device = loopsetup(img); - if (device) - xmount(device, target, "ext4", 0, NULL); - return device; -} - -static void umount_image(const char *target, const char *device) { - xumount(target); - int fd = xopen(device, O_RDWR); - ioctl(fd, LOOP_CLR_FD); - close(fd); -} - #define round_size(a) ((((a) / 32) + 2) * 32) #define SOURCE_TMP "/dev/source" #define TARGET_TMP "/dev/target" diff --git a/jni/main.c b/jni/main.c index dda4b0eee..8c97ea5e5 100644 --- a/jni/main.c +++ b/jni/main.c @@ -32,6 +32,9 @@ static void usage() { " or: %s --imgsize \n" " or: %s --resizeimg \n" " SIZE is interpreted in MB\n" + " or: %s --mountimg \n" + " Prints out the loop device\n" + " or: %s --umountimg \n" " or: %s --[boot stage]\n" " start boot stage service\n" " or: %s [options]\n" @@ -46,7 +49,7 @@ static void usage() { " -V print daemon version code\n" "\n" "Supported applets:\n" - , argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0); + , argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0); for (int i = 0; applet[i]; ++i) { fprintf(stderr, i ? ", %s" : " %s", applet[i]); @@ -99,7 +102,7 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Cannot check %s size\n", argv[2]); return 1; } - printf("Used: %dM\tTotal: %dM\n", used, total); + printf("%d %d\n", used, total); return 0; } else if (strcmp(argv[1], "--resizeimg") == 0) { if (argc < 4) usage(); @@ -114,6 +117,21 @@ int main(int argc, char *argv[]) { return 1; } return resize_img(argv[2], size); + } else if (strcmp(argv[1], "--mountimg") == 0) { + if (argc < 4) usage(); + char *loop = mount_image(argv[2], argv[3]); + if (loop == NULL) { + fprintf(stderr, "Cannot mount image!\n"); + return 1; + } else { + printf("%s\n", loop); + free(loop); + return 0; + } + } else if (strcmp(argv[1], "--umountimg") == 0) { + if (argc < 4) usage(); + umount_image(argv[2], argv[3]); + return 0; } else if (strcmp(argv[1], "--post-fs") == 0) { int fd = connect_daemon(); write_int(fd, POST_FS); diff --git a/jni/utils/img.c b/jni/utils/img.c new file mode 100644 index 000000000..2a2228b44 --- /dev/null +++ b/jni/utils/img.c @@ -0,0 +1,128 @@ +/* img.c - All image related functions + */ + +#include +#include +#include +#include +#include + +#include "magisk.h" +#include "utils.h" + +int create_img(const char *img, int size) { + unlink(img); + LOGI("Create %s with size %dM\n", img, size); + // Create a temp file with the file contexts + 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 fd = xopen(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644); + xwrite(fd, file_contexts, sizeof(file_contexts)); + close(fd); + + char buffer[PATH_MAX]; + snprintf(buffer, sizeof(buffer), + "make_ext4fs -l %dM -a /magisk -S %s %s; e2fsck -yf %s;", size, filename, img, img); + char *const command[] = { "sh", "-c", buffer, NULL }; + int pid, status; + pid = run_command(0, NULL, "/system/bin/sh", command); + if (pid == -1) + return 1; + waitpid(pid, &status, 0); + unlink(filename); + return WEXITSTATUS(status); +} + +int get_img_size(const char *img, int *used, int *total) { + if (access(img, R_OK) == -1) + return 1; + char buffer[PATH_MAX]; + snprintf(buffer, sizeof(buffer), "e2fsck -n %s", img); + char *const command[] = { "sh", "-c", buffer, NULL }; + int pid, fd = 0, status = 1; + pid = run_command(1, &fd, "/system/bin/sh", command); + if (pid == -1) + return 1; + while (fdgets(buffer, sizeof(buffer), fd)) { + LOGD("magisk_img: %s", buffer); + if (strstr(buffer, img)) { + char *tok = strtok(buffer, ","); + while(tok != NULL) { + if (strstr(tok, "blocks")) { + status = 0; + break; + } + tok = strtok(NULL, ","); + } + if (status) continue; + sscanf(tok, "%d/%d", used, total); + *used = *used / 256 + 1; + *total /= 256; + break; + } + } + close(fd); + waitpid(pid, &status, 0); + return WEXITSTATUS(status); +} + +int resize_img(const char *img, int size) { + LOGI("Resize %s to %dM\n", img, size); + char buffer[PATH_MAX]; + snprintf(buffer, sizeof(buffer), "e2fsck -yf %s; resize2fs %s %dM;", img, img, size); + char *const command[] = { "sh", "-c", buffer, NULL }; + int pid, status, fd = 0; + pid = run_command(1, &fd, "/system/bin/sh", command); + if (pid == -1) + return 1; + while (fdgets(buffer, sizeof(buffer), fd)) + LOGD("magisk_img: %s", buffer); + close(fd); + waitpid(pid, &status, 0); + return WEXITSTATUS(status); +} + +char *loopsetup(const char *img) { + char device[20]; + struct loop_info64 info; + int i, lfd, ffd; + memset(&info, 0, sizeof(info)); + // First get an empty loop device + for (i = 0; i <= 7; ++i) { + sprintf(device, "/dev/block/loop%d", i); + lfd = xopen(device, O_RDWR); + if (ioctl(lfd, LOOP_GET_STATUS64, &info) == -1) + break; + close(lfd); + } + if (i == 8) return NULL; + ffd = xopen(img, O_RDWR); + if (ioctl(lfd, LOOP_SET_FD, ffd) == -1) + return NULL; + strcpy((char *) info.lo_file_name, img); + ioctl(lfd, LOOP_SET_STATUS64, &info); + close(lfd); + close(ffd); + return strdup(device); +} + +char *mount_image(const char *img, const char *target) { + if (access(target, F_OK) == -1) { + if (mkdir(target, 0755) == -1) { + xmount(NULL, "/", NULL, MS_REMOUNT, NULL); + xmkdir(target, 0755); + } + } + char *device = loopsetup(img); + if (device) + xmount(device, target, "ext4", 0, NULL); + return device; +} + +void umount_image(const char *target, const char *device) { + xumount(target); + int fd = xopen(device, O_RDWR); + ioctl(fd, LOOP_CLR_FD); + close(fd); +} diff --git a/jni/utils/misc.c b/jni/utils/misc.c index c04e01925..a1ff6aa69 100644 --- a/jni/utils/misc.c +++ b/jni/utils/misc.c @@ -411,78 +411,6 @@ void get_client_cred(int fd, struct ucred *cred) { PLOGE("getsockopt"); } -int create_img(const char *img, int size) { - unlink(img); - LOGI("Create %s with size %dM\n", img, size); - // Create a temp file with the file contexts - char file_contexts[] = "/magisk(/.*)? u:object_r:system_file:s0\n"; - int fd = xopen("/dev/file_contexts_image", O_WRONLY | O_CREAT | O_TRUNC, 0644); - xwrite(fd, file_contexts, sizeof(file_contexts)); - close(fd); - - char buffer[PATH_MAX]; - snprintf(buffer, sizeof(buffer), - "make_ext4fs -l %dM -a /magisk -S /dev/file_contexts_image %s; e2fsck -yf %s;", size, img, img); - char *const command[] = { "sh", "-c", buffer, NULL }; - int pid, status; - pid = run_command(0, NULL, "/system/bin/sh", command); - if (pid == -1) - return 1; - waitpid(pid, &status, 0); - unlink("/dev/file_contexts_image"); - return WEXITSTATUS(status); -} - -int get_img_size(const char *img, int *used, int *total) { - if (access(img, R_OK) == -1) - return 1; - char buffer[PATH_MAX]; - snprintf(buffer, sizeof(buffer), "e2fsck -yf %s", img); - char *const command[] = { "sh", "-c", buffer, NULL }; - int pid, fd = 0, status = 1; - pid = run_command(1, &fd, "/system/bin/sh", command); - if (pid == -1) - return 1; - while (fdgets(buffer, sizeof(buffer), fd)) { - LOGD("magisk_img: %s", buffer); - if (strstr(buffer, img)) { - char *tok; - tok = strtok(buffer, ","); - while(tok != NULL) { - if (strstr(tok, "blocks")) { - status = 0; - break; - } - tok = strtok(NULL, ","); - } - if (status) continue; - sscanf(tok, "%d/%d", used, total); - *used = *used / 256 + 1; - *total /= 256; - break; - } - } - close(fd); - waitpid(pid, &status, 0); - return WEXITSTATUS(status); -} - -int resize_img(const char *img, int size) { - LOGI("Resize %s to %dM\n", img, size); - char buffer[PATH_MAX]; - snprintf(buffer, sizeof(buffer), "resize2fs %s %dM; e2fsck -yf %s;", img, size, img); - char *const command[] = { "sh", "-c", buffer, NULL }; - int pid, status, fd = 0; - pid = run_command(1, &fd, "/system/bin/sh", command); - if (pid == -1) - return 1; - while (fdgets(buffer, sizeof(buffer), fd)) - LOGD("magisk_img: %s", buffer); - close(fd); - waitpid(pid, &status, 0); - return WEXITSTATUS(status); -} - int switch_mnt_ns(int pid) { char mnt[32]; snprintf(mnt, sizeof(mnt), "/proc/%d/ns/mnt", pid); diff --git a/jni/utils/utils.h b/jni/utils/utils.h index efba1fcb0..6d60b70cc 100644 --- a/jni/utils/utils.h +++ b/jni/utils/utils.h @@ -91,9 +91,14 @@ int clone_dir(const char *source, const char *target); int rm_rf(const char *target); void clone_attr(const char *source, const char *target); void get_client_cred(int fd, struct ucred *cred); +int switch_mnt_ns(int pid); + +// img.c int create_img(const char *img, int size); int get_img_size(const char *img, int *used, int *total); int resize_img(const char *img, int size); -int switch_mnt_ns(int pid); +char *loopsetup(const char *img); +char *mount_image(const char *img, const char *target); +void umount_image(const char *target, const char *device); #endif