diff --git a/jni/daemon/bootstages.c b/jni/daemon/bootstages.c index a9f67808e..3dca31f41 100644 --- a/jni/daemon/bootstages.c +++ b/jni/daemon/bootstages.c @@ -86,38 +86,8 @@ static void umount_image(const char *target, const char *device) { close(fd); } -static int get_img_size(const char *img, int *used, int *total) { - char buffer[PATH_MAX]; - snprintf(buffer, sizeof(buffer), "e2fsck -n %s 2>/dev/null | tail -n 1", img); - char *const command[] = { "sh", "-c", buffer, NULL }; - int pid, fd; - pid = run_command(&fd, "/system/bin/sh", command); - fdgets(buffer, sizeof(buffer), fd); - close(fd); - if (pid == -1) - return 1; - waitpid(pid, NULL, 0); - char *tok; - tok = strtok(buffer, ","); - while(tok != NULL) { - if (strstr(tok, "blocks")) - break; - tok = strtok(NULL, ","); - } - sscanf(tok, "%d/%d", used, total); - *used = *used / 256 + 1; - *total /= 256; - return 0; -} - #define round_size(a) ((((a) / 32) + 2) * 32) -static int resize_img(const char *img, int size) { - LOGI("resize %s to %dM\n", img, size); - snprintf(buf, PATH_MAX, "e2fsck -yf %s; resize2fs %s %dM;", img, img, size); - return system(buf); -} - static int merge_img(const char *source, const char *target) { if (access(source, F_OK) == -1) return 0; @@ -544,6 +514,9 @@ void post_fs_data(int client) { if (merge_img("/data/magisk_merge.img", MAINIMG)) goto unblock; + if (access(MAINIMG, F_OK) == -1 && create_img(MAINIMG, 64)) + goto unblock; + LOGI("* Mounting " MAINIMG "\n"); // Mounting magisk image char *magiskloop = mount_image(MAINIMG, MOUNTPOINT); diff --git a/jni/main.c b/jni/main.c index 97b628cc2..dda4b0eee 100644 --- a/jni/main.c +++ b/jni/main.c @@ -27,7 +27,13 @@ static void usage() { "Usage: %s [applet [arguments]...]\n" " or: %s --install [SOURCE] \n" " or: %s --list\n" - " or: %s --[boot stage] start boot stage service\n" + " or: %s --createimg \n" + " create ext4 image, SIZE is interpreted in MB\n" + " or: %s --imgsize \n" + " or: %s --resizeimg \n" + " SIZE is interpreted in MB\n" + " or: %s --[boot stage]\n" + " start boot stage service\n" " or: %s [options]\n" " or: applet [arguments]...\n" "\n" @@ -40,7 +46,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); for (int i = 0; applet[i]; ++i) { fprintf(stderr, i ? ", %s" : " %s", applet[i]); @@ -81,6 +87,33 @@ int main(int argc, char *argv[]) { for (int i = 0; applet[i]; ++i) printf("%s\n", applet[i]); return 0; + } else if (strcmp(argv[1], "--createimg") == 0) { + if (argc < 4) usage(); + int size; + sscanf(argv[3], "%d", &size); + return create_img(argv[2], size); + } else if (strcmp(argv[1], "--imgsize") == 0) { + if (argc < 3) usage(); + int used, total; + if (get_img_size(argv[2], &used, &total)) { + fprintf(stderr, "Cannot check %s size\n", argv[2]); + return 1; + } + printf("Used: %dM\tTotal: %dM\n", used, total); + return 0; + } else if (strcmp(argv[1], "--resizeimg") == 0) { + if (argc < 4) usage(); + int used, total, size; + sscanf(argv[3], "%d", &size); + if (get_img_size(argv[2], &used, &total)) { + fprintf(stderr, "Cannot check %s size\n", argv[2]); + return 1; + } + if (size <= used) { + fprintf(stderr, "Cannot resize smaller than %dM\n", used); + return 1; + } + return resize_img(argv[2], size); } else if (strcmp(argv[1], "--post-fs") == 0) { int fd = connect_daemon(); write_int(fd, POST_FS); diff --git a/jni/utils/misc.c b/jni/utils/misc.c index 4cbb8f082..749f8f2b1 100644 --- a/jni/utils/misc.c +++ b/jni/utils/misc.c @@ -397,3 +397,53 @@ void get_client_cred(int fd, struct ucred *cred) { if(getsockopt(fd, SOL_SOCKET, SO_PEERCRED, cred, &ucred_length)) 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 command[PATH_MAX]; + snprintf(command, sizeof(command), + "make_ext4fs -l %dM -a /magisk -S /dev/file_contexts_image %s", size, img); + int ret = system(command); + unlink("/dev/file_contexts_image"); + return ret; +} + +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 2>/dev/null | tail -n 1", img); + char *const command[] = { "sh", "-c", buffer, NULL }; + int pid, fd; + pid = run_command(&fd, "/system/bin/sh", command); + fdgets(buffer, sizeof(buffer), fd); + close(fd); + if (pid == -1) + return 1; + waitpid(pid, NULL, 0); + char *tok; + tok = strtok(buffer, ","); + while(tok != NULL) { + if (strstr(tok, "blocks")) + break; + tok = strtok(NULL, ","); + } + sscanf(tok, "%d/%d", used, total); + *used = *used / 256 + 1; + *total /= 256; + return 0; +} + +int resize_img(const char *img, int size) { + LOGI("Resize %s to %dM\n", img, size); + char buffer[PATH_MAX]; + snprintf(buffer, PATH_MAX, "e2fsck -yf %s; resize2fs %s %dM;", img, img, size); + return system(buffer); +} diff --git a/jni/utils/utils.h b/jni/utils/utils.h index 4bae70012..500540919 100644 --- a/jni/utils/utils.h +++ b/jni/utils/utils.h @@ -91,5 +91,8 @@ 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 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); #endif