Add stdin/stdout support

This commit is contained in:
topjohnwu 2017-11-10 20:25:41 +08:00
parent 2487ec94e6
commit 9136573596
4 changed files with 85 additions and 42 deletions

View File

@ -117,6 +117,7 @@ void clone_attr(const char *source, const char *target);
void restorecon(int dirfd, int force); void restorecon(int dirfd, int force);
void mmap_ro(const char *filename, void **buf, size_t *size); void mmap_ro(const char *filename, void **buf, size_t *size);
void mmap_rw(const char *filename, void **buf, size_t *size); void mmap_rw(const char *filename, void **buf, size_t *size);
void full_read(int fd, void **buf, size_t *size);
void write_zero(int fd, size_t size); void write_zero(int fd, size_t size);
void mem_align(size_t *pos, size_t align); void mem_align(size_t *pos, size_t align);
void file_align(int fd, size_t align, int out); void file_align(int fd, size_t align, int out);

View File

@ -87,7 +87,6 @@ size_t gzip(int mode, int fd, const void *buf, size_t size) {
return total; return total;
} }
// Mode: 0 = decode xz/lzma; 1 = encode xz; 2 = encode lzma // Mode: 0 = decode xz/lzma; 1 = encode xz; 2 = encode lzma
size_t lzma(int mode, int fd, const void *buf, size_t size) { size_t lzma(int mode, int fd, const void *buf, size_t size) {
size_t have, pos = 0, total = 0; size_t have, pos = 0, total = 0;
@ -405,7 +404,6 @@ long long decomp(file_t type, int to, const void *from, size_t size) {
} }
} }
// Output will be to.ext
long long comp(file_t type, int to, const void *from, size_t size) { long long comp(file_t type, int to, const void *from, size_t size) {
switch (type) { switch (type) {
case GZIP: case GZIP:
@ -431,60 +429,68 @@ long long comp(file_t type, int to, const void *from, size_t size) {
*/ */
void decomp_file(char *from, const char *to) { void decomp_file(char *from, const char *to) {
int ok = 1; int strip = 1;
void *file; void *file;
size_t size; size_t size = 0;
mmap_ro(from, &file, &size); if (strcmp(from, "-") == 0)
full_read(STDIN_FILENO, &file, &size);
else
mmap_ro(from, &file, &size);
file_t type = check_type(file); file_t type = check_type(file);
char *ext; char *ext;
ext = strrchr(from, '.'); ext = strrchr(from, '.');
if (ext == NULL) if (to == NULL)
LOGE("Bad filename extention\n"); to = from;
if (ext != NULL) {
// File type and extension should match // Strip out a matched file extension
switch (type) { switch (type) {
case GZIP: case GZIP:
if (strcmp(ext, ".gz") != 0) if (strcmp(ext, ".gz") != 0)
ok = 0; strip = 0;
break; break;
case XZ: case XZ:
if (strcmp(ext, ".xz") != 0) if (strcmp(ext, ".xz") != 0)
ok = 0; strip = 0;
break; break;
case LZMA: case LZMA:
if (strcmp(ext, ".lzma") != 0) if (strcmp(ext, ".lzma") != 0)
ok = 0; strip = 0;
break; break;
case BZIP2: case BZIP2:
if (strcmp(ext, ".bz2") != 0) if (strcmp(ext, ".bz2") != 0)
ok = 0; strip = 0;
break; break;
case LZ4_LEGACY: case LZ4_LEGACY:
case LZ4: case LZ4:
if (strcmp(ext, ".lz4") != 0) if (strcmp(ext, ".lz4") != 0)
ok = 0; strip = 0;
break; break;
default: default:
LOGE("Provided file \'%s\' is not a supported archive format\n", from); LOGE("Provided file \'%s\' is not a supported archive format\n", from);
} }
if (ok) { if (strip)
// If all match, strip out the suffix
if (!to) {
*ext = '\0'; *ext = '\0';
to = from;
}
int fd = creat(to, 0644);
fprintf(stderr, "Decompressing to [%s]\n\n", to);
decomp(type, fd, file, size);
close(fd);
if (to == from) {
*ext = '.';
unlink(from);
}
} else {
LOGE("Bad filename extention \'%s\'\n", ext);
} }
munmap(file, size);
int fd;
if (strcmp(to, "-") == 0) {
fd = STDOUT_FILENO;
} else {
fd = creat(to, 0644);
fprintf(stderr, "Decompressing to [%s]\n\n", to);
}
decomp(type, fd, file, size);
close(fd);
if (to == from && ext != NULL) {
*ext = '.';
unlink(from);
}
if (strcmp(from, "-") == 0)
free(file);
else
munmap(file, size);
} }
void comp_file(const char *method, const char *from, const char *to) { void comp_file(const char *method, const char *from, const char *to) {
@ -517,17 +523,31 @@ void comp_file(const char *method, const char *from, const char *to) {
} }
void *file; void *file;
size_t size; size_t size;
mmap_ro(from, &file, &size); if (strcmp(from, "-") == 0)
if (!to) full_read(STDIN_FILENO, &file, &size);
snprintf(dest, sizeof(dest), "%s.%s", from, ext);
else else
mmap_ro(from, &file, &size);
if (to == NULL) {
if (strcmp(from, "-") == 0)
strcpy(dest, "-");
else
snprintf(dest, sizeof(dest), "%s.%s", from, ext);
} else
strcpy(dest, to); strcpy(dest, to);
fprintf(stderr, "Compressing to [%s]\n\n", dest); int fd;
int fd = creat(dest, 0644); if (strcmp(dest, "-") == 0) {
fd = STDOUT_FILENO;
} else {
fd = creat(dest, 0644);
fprintf(stderr, "Compressing to [%s]\n\n", dest);
}
comp(type, fd, file, size); comp(type, fd, file, size);
close(fd); close(fd);
munmap(file, size); if (strcmp(from, "-") == 0)
if (!to) free(file);
else
munmap(file, size);
if (to == NULL)
unlink(from); unlink(from);
} }

View File

@ -18,8 +18,8 @@ static void usage(char *arg0) {
"\n" "\n"
"Supported actions:\n" "Supported actions:\n"
" --unpack <bootimg>\n" " --unpack <bootimg>\n"
" Unpack <bootimg> to kernel, ramdisk.cpio, (second), (dtb) into the\n" " Unpack <bootimg> to kernel, ramdisk.cpio, (second), (dtb), (extra) into\n"
" current directory\n" " the current directory\n"
"\n" "\n"
" --repack <origbootimg> [outbootimg]\n" " --repack <origbootimg> [outbootimg]\n"
" Repack kernel, ramdisk.cpio[.ext], second, dtb... from current directory\n" " Repack kernel, ramdisk.cpio[.ext], second, dtb... from current directory\n"
@ -66,6 +66,7 @@ static void usage(char *arg0) {
"\n" "\n"
" --compress[=method] <infile> [outfile]\n" " --compress[=method] <infile> [outfile]\n"
" Compress <infile> with [method] (default: gzip), optionally to [outfile]\n" " Compress <infile> with [method] (default: gzip), optionally to [outfile]\n"
" <infile>/[outfile] can be '-' to be STDIN/STDOUT\n"
" Supported methods: " " Supported methods: "
, arg0); , arg0);
for (int i = 0; SUP_LIST[i]; ++i) for (int i = 0; SUP_LIST[i]; ++i)
@ -74,7 +75,9 @@ static void usage(char *arg0) {
"\n" "\n"
"\n" "\n"
" --decompress <infile> [outfile]\n" " --decompress <infile> [outfile]\n"
" Detect method and decompress <infile>, optionally to [outfile]\n Supported methods: "); " Detect method and decompress <infile>, optionally to [outfile]\n"
" <infile>/[outfile] can be '-' to be STDIN/STDOUT\n"
" Supported methods: ");
for (int i = 0; SUP_LIST[i]; ++i) for (int i = 0; SUP_LIST[i]; ++i)
fprintf(stderr, "%s ", SUP_LIST[i]); fprintf(stderr, "%s ", SUP_LIST[i]);
fprintf(stderr, fprintf(stderr,

View File

@ -351,6 +351,25 @@ void mmap_rw(const char *filename, void **buf, size_t *size) {
close(fd); close(fd);
} }
void full_read(int fd, void **buf, size_t *size) {
size_t cap = 1 << 20;
uint8_t tmp[1 << 20];
*buf = xmalloc(cap);
ssize_t read;
*size = 0;
while (1) {
read = xread(fd, tmp, sizeof(tmp));
if (read <= 0)
break;
if (*size + read > cap) {
cap *= 2;
*buf = realloc(*buf, cap);
}
memcpy(*buf + *size, tmp, read);
*size += read;
}
}
void write_zero(int fd, size_t size) { void write_zero(int fd, size_t size) {
size_t pos = lseek(fd, 0, SEEK_CUR); size_t pos = lseek(fd, 0, SEEK_CUR);
ftruncate(fd, pos + size); ftruncate(fd, pos + size);