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