Add auto cpio backup and restore

This commit is contained in:
topjohnwu 2017-03-10 07:52:59 +08:00
parent 3f3568d8af
commit 212a303347
3 changed files with 173 additions and 20 deletions

View File

@ -17,6 +17,14 @@ static uint32_t x8u(char *hex) {
return val;
}
static void cpio_free(cpio_file *f) {
if (f) {
free(f->filename);
free(f->data);
free(f);
}
}
static void cpio_vec_insert(vector *v, cpio_file *n) {
cpio_file *f, *t;
int shift = 0;
@ -30,9 +38,7 @@ static void cpio_vec_insert(vector *v, cpio_file *n) {
t = f;
if (strcmp(f->filename, n->filename) == 0) {
// Replace, then all is done
free(f->filename);
free(f->data);
free(f);
cpio_free(f);
vec_entry(v)[_i] = n;
return;
} else if (strcmp(f->filename, n->filename) > 0) {
@ -42,7 +48,10 @@ static void cpio_vec_insert(vector *v, cpio_file *n) {
shift = 1;
}
}
vec_push_back(v, t);
if (shift)
vec_push_back(v, t);
else
vec_push_back(v, n);
}
static int cpio_compare(const void *a, const void *b) {
@ -76,9 +85,8 @@ static void parse_cpio(const char *filename, vector *v) {
read(fd, f->filename, f->namesize);
file_align(fd, 4, 0);
if (strcmp(f->filename, "TRAILER!!!") == 0 || strcmp(f->filename, ".") == 0) {
free(f->filename);
free(f);
break;
cpio_free(f);
continue;
}
if (f->filesize) {
f->data = malloc(f->filesize);
@ -93,7 +101,7 @@ static void parse_cpio(const char *filename, vector *v) {
}
static void dump_cpio(const char *filename, vector *v) {
printf("Dump cpio: [%s]\n\n", filename);
printf("\nDump cpio: [%s]\n\n", filename);
int fd = open_new(filename);
unsigned inode = 300000;
char header[111];
@ -128,15 +136,14 @@ static void dump_cpio(const char *filename, vector *v) {
write(fd, header, 110);
write(fd, "TRAILER!!!\0", 11);
file_align(fd, 4, 1);
close(fd);
}
static void cpio_vec_destroy(vector *v) {
// Free each cpio_file
cpio_file *f;
vec_for_each(v, f) {
free(f->filename);
free(f->data);
free(f);
cpio_free(f);
}
vec_destroy(v);
}
@ -146,7 +153,11 @@ static void cpio_rm(int recursive, const char *entry, vector *v) {
vec_for_each(v, f) {
if ((recursive && strncmp(f->filename, entry, strlen(entry)) == 0)
|| (strcmp(f->filename, entry) == 0) ) {
f->remove = 1;
if (!f->remove) {
printf("Remove [%s]\n", entry);
f->remove = 1;
}
if (!recursive) return;
}
}
}
@ -158,6 +169,7 @@ static void cpio_mkdir(mode_t mode, const char *entry, vector *v) {
f->filename = malloc(f->namesize);
memcpy(f->filename, entry, f->namesize);
cpio_vec_insert(v, f);
printf("Create directory [%s] (%04o)\n",entry, mode);
}
static void cpio_add(mode_t mode, const char *entry, const char *filename, vector *v) {
@ -173,7 +185,9 @@ static void cpio_add(mode_t mode, const char *entry, const char *filename, vecto
lseek(fd, 0, SEEK_SET);
f->data = malloc(f->filesize);
read(fd, f->data, f->filesize);
close(fd);
cpio_vec_insert(v, f);
printf("Add entry [%s] (%04o)\n", entry, mode);
}
static void cpio_test(vector *v) {
@ -222,7 +236,6 @@ static void cpio_dmverity(vector *v) {
break;
}
}
printf("\n");
}
static void cpio_forceencrypt(vector *v) {
@ -247,14 +260,13 @@ static void cpio_forceencrypt(vector *v) {
f->filesize = write;
}
}
printf("\n");
}
static void cpio_extract(const char *entry, const char *filename, vector *v) {
cpio_file *f;
vec_for_each(v, f) {
if (strcmp(f->filename, entry) == 0 && S_ISREG(f->mode)) {
printf("Extracting [%s] to [%s]\n\n", entry, filename);
printf("Extracting [%s] to [%s]\n", entry, filename);
int fd = open_new(filename);
write(fd, f->data, f->filesize);
fchmod(fd, f->mode);
@ -266,6 +278,134 @@ static void cpio_extract(const char *entry, const char *filename, vector *v) {
error(1, "Cannot find the file entry [%s]", entry);
}
static void cpio_backup(const char *orig, vector *v) {
vector o_body, *o = &o_body, bak;
cpio_file *m, *n, *dir, *rem;
char chk1[21], chk2[21], buf[PATH_MAX];
int res, doBak;
dir = calloc(sizeof(*dir), 1);
rem = calloc(sizeof(*rem), 1);
vec_init(o);
vec_init(&bak);
// First push back the directory and the rmlist
vec_push_back(&bak, dir);
vec_push_back(&bak, rem);
parse_cpio(orig, o);
// Remove possible backups in original ramdisk
cpio_rm(1, ".backup", o);
cpio_rm(1, ".backup", v);
// Init the directory and rmlist
dir->filename = strdup(".backup");
dir->namesize = strlen(dir->filename) + 1;
dir->mode = S_IFDIR;
rem->filename = strdup(".backup/.rmlist");
rem->namesize = strlen(rem->filename) + 1;
rem->mode = S_IFREG;
// Start comparing
size_t i = 0, j = 0;
while(i != vec_size(o) || j != vec_size(v)) {
doBak = 0;
if (i != vec_size(o) && j != vec_size(v)) {
m = vec_entry(o)[i];
n = vec_entry(v)[j];
res = strcmp(m->filename, n->filename);
} else if (i == vec_size(o)) {
n = vec_entry(v)[j];
res = 1;
} else if (j == vec_size(v)) {
m = vec_entry(o)[i];
res = -1;
}
if (res < 0) {
// Something is missing in new ramdisk, backup!
++i;
doBak = 1;
printf("Entry [%s] is missing\n", m->filename);
} else if (res == 0) {
// Do SHA1 checksum to check if file is identical
++i; ++j;
SHA1(chk1, m->data, m->filesize);
SHA1(chk2, n->data, n->filesize);
if (strcmp(chk1, chk2) != 0) {
// Not the same!
doBak = 1;
printf("Entry [%s] checksum missmatch\n", m->filename);
}
} else {
// Someting new in ramdisk, record in rem
++j;
if (n->remove) continue;
rem->data = realloc(rem->data, rem->filesize + n->namesize);
memcpy(rem->data + rem->filesize, n->filename, n->namesize);
rem->filesize += n->namesize;
printf("Entry [%s] is new\n", n->filename);
}
if (doBak) {
m->namesize += 8;
m->filename = realloc(m->filename, m->namesize);
strcpy(buf, m->filename);
sprintf(m->filename, ".backup/%s", buf);
vec_push_back(&bak, m);
// NULL the original entry, so it won't be freed
vec_entry(o)[i - 1] = NULL;
}
}
// Add the backup files to the original ramdisk
vec_for_each(&bak, m) {
vec_push_back(v, m);
}
// Don't include if empty
if (rem->filesize == 0) {
rem->remove = 1;
if (bak.size == 2)
dir->remove = 1;
}
// Sort
vec_sort(v, cpio_compare);
// Cleanup
cpio_vec_destroy(o);
}
static void cpio_restore(vector *v) {
cpio_file *f, *n;
vec_for_each(v, f) {
if (strstr(f->filename, ".backup") != NULL) {
f->remove = 1;
if (strcmp(f->filename, ".backup") == 0) continue;
if (strcmp(f->filename, ".backup/.rmlist") == 0) {
int pos = 0;
while(pos < f->filesize) {
cpio_rm(0, f->data + pos, v);
pos += strlen(f->data + pos) + 1;
}
continue;
}
n = calloc(sizeof(*n), 1);
memcpy(n, f, sizeof(*f));
n->namesize -= 8;
n->filename = malloc(n->namesize);
memcpy(n->filename, f->filename + 8, n->namesize);
n->data = malloc(n->filesize);
memcpy(n->data, f->data, n->filesize);
n->remove = 0;
printf("Restoring [%s] -> [%s]\n", f->filename, n->filename);
cpio_vec_insert(v, n);
}
}
// Some known stuff we can remove
cpio_rm(0, "sbin/magic_mask.sh", v);
cpio_rm(0, "init.magisk.rc", v);
cpio_rm(0, "magisk", v);
}
int cpio_commands(const char *command, int argc, char *argv[]) {
int recursive = 0;
command_t cmd;
@ -278,8 +418,10 @@ int cpio_commands(const char *command, int argc, char *argv[]) {
cmd = DMVERITY;
} else if (strcmp(command, "patch-forceencrypt") == 0) {
cmd = FORCEENCRYPT;
} else if (argc == 2 && strcmp(command, "extract") == 0) {
cmd = EXTRACT;
} else if (strcmp(command, "restore") == 0) {
cmd = RESTORE;
} else if (argc == 1 && strcmp(command, "backup") == 0) {
cmd = BACKUP;
} else if (argc > 0 && strcmp(command, "rm") == 0) {
cmd = RM;
if (argc == 2 && strcmp(argv[0], "-r") == 0) {
@ -287,6 +429,8 @@ int cpio_commands(const char *command, int argc, char *argv[]) {
++argv;
--argc;
}
} else if (argc == 2 && strcmp(command, "extract") == 0) {
cmd = EXTRACT;
} else if (argc == 2 && strcmp(command, "mkdir") == 0) {
cmd = MKDIR;
} else if (argc == 3 && strcmp(command, "add") == 0) {
@ -308,12 +452,17 @@ int cpio_commands(const char *command, int argc, char *argv[]) {
case FORCEENCRYPT:
cpio_forceencrypt(&v);
break;
case EXTRACT:
cpio_extract(argv[0], argv[1], &v);
case RESTORE:
cpio_restore(&v);
break;
case BACKUP:
cpio_backup(argv[0], &v);
case RM:
cpio_rm(recursive, argv[0], &v);
break;
case EXTRACT:
cpio_extract(argv[0], argv[1], &v);
break;
case MKDIR:
cpio_mkdir(strtoul(argv[0], NULL, 8), argv[1], &v);
break;

View File

@ -59,7 +59,9 @@ typedef enum {
EXTRACT,
TEST,
DMVERITY,
FORCEENCRYPT
FORCEENCRYPT,
BACKUP,
RESTORE
} command_t;
extern char *SUP_EXT_LIST[SUP_NUM];

View File

@ -30,6 +30,8 @@ static void usage(char *arg0) {
fprintf(stderr, " --cpio-test <incpio>\n Return value: 0/not patched 1/Magisk 2/SuperSU\n");
fprintf(stderr, " --cpio-patch-dmverity <incpio>\n Remove dm-verity\n");
fprintf(stderr, " --cpio-patch-forceencrypt <incpio>\n Change forceencrypt flag to encryptable\n");
fprintf(stderr, " --cpio-backup <incpio> <origcpio>\n Create ramdisk backups into <incpio> from <origcpio>\n");
fprintf(stderr, " --cpio-restore <incpio>\n Restore ramdisk from ramdisk backup within <incpio>\n");
fprintf(stderr, "\n");
fprintf(stderr, "%s --compress[=method] <file>\n", arg0);