From 1d3ce9fef1e8e3bd963465c24687b8f99276808b Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Sat, 23 Feb 2019 16:16:35 -0500 Subject: [PATCH] Support loading CPIO from a chunk of bytes --- native/jni/utils/cpio.cpp | 59 +++++++++++++++++---------------- native/jni/utils/include/cpio.h | 6 ++-- 2 files changed, 34 insertions(+), 31 deletions(-) diff --git a/native/jni/utils/cpio.cpp b/native/jni/utils/cpio.cpp index b31ae8620..6eecdf7fa 100644 --- a/native/jni/utils/cpio.cpp +++ b/native/jni/utils/cpio.cpp @@ -47,23 +47,6 @@ static uint32_t x8u(const char *hex) { cpio_entry_base::cpio_entry_base(const cpio_newc_header *h) : mode(x8u(h->mode)), uid(x8u(h->uid)), gid(x8u(h->gid)), filesize(x8u(h->filesize)) {}; -#define fd_align() lseek(fd, do_align(lseek(fd, 0, SEEK_CUR), 4), SEEK_SET) -cpio_entry::cpio_entry(int fd, cpio_newc_header &header) : cpio_entry_base(&header) { - uint32_t namesize = x8u(header.namesize); - filename.resize(namesize - 1); - xxread(fd, &filename[0], namesize); - fd_align(); - if (filesize) { - data = xmalloc(filesize); - xxread(fd, data, filesize); - fd_align(); - } -} - -cpio_entry::~cpio_entry() { - free(data); -} - void cpio::dump(const char *file) { fprintf(stderr, "Dump cpio: [%s]\n", file); FDOutStream fd_out(xopen(file, O_WRONLY | O_CREAT | O_TRUNC, 0644), true); @@ -167,19 +150,12 @@ void cpio::output(OutStream &out) { } cpio_rw::cpio_rw(const char *filename) { - int fd = xopen(filename, O_RDONLY); + char *buf; + size_t sz; + mmap_ro(filename, (void **) &buf, &sz); fprintf(stderr, "Loading cpio: [%s]\n", filename); - cpio_newc_header header; - unique_ptr entry; - while(xxread(fd, &header, sizeof(cpio_newc_header)) != -1) { - entry = make_unique(fd, header); - if (entry->filename == "." || entry->filename == "..") - continue; - if (entry->filename == "TRAILER!!!") - break; - entries[entry->filename] = std::move(entry); - } - close(fd); + load_cpio(buf, sz); + munmap(buf, sz); } void cpio_rw::insert(cpio_entry *e) { @@ -239,6 +215,31 @@ bool cpio_rw::mv(const char *from, const char *to) { } #define pos_align(p) p = do_align(p, 4) + +void cpio_rw::load_cpio(char *buf, size_t sz) { + size_t pos = 0; + cpio_newc_header *header; + unique_ptr entry; + while (pos < sz) { + header = (cpio_newc_header *)(buf + pos); + entry = make_unique(header); + pos += sizeof(*header); + string_view name_view(buf + pos); + pos += x8u(header->namesize); + pos_align(pos); + if (name_view == "." || name_view == "..") + continue; + if (name_view == "TRAILER!!!") + break; + entry->filename = name_view; + entry->data = xmalloc(entry->filesize); + memcpy(entry->data, buf + pos, entry->filesize); + pos += entry->filesize; + entries[entry->filename] = std::move(entry); + pos_align(pos); + } +} + cpio_mmap::cpio_mmap(const char *filename) { mmap_ro(filename, (void **) &buf, &sz); fprintf(stderr, "Loading cpio: [%s]\n", filename); diff --git a/native/jni/utils/include/cpio.h b/native/jni/utils/include/cpio.h index e23761f84..b24e5183a 100644 --- a/native/jni/utils/include/cpio.h +++ b/native/jni/utils/include/cpio.h @@ -30,8 +30,9 @@ struct cpio_entry : public cpio_entry_base { explicit cpio_entry(const char *name, uint32_t mode) : filename(name) { this->mode = mode; } - cpio_entry(int fd, cpio_newc_header &header); - ~cpio_entry() override; + explicit cpio_entry(cpio_newc_header *h) : cpio_entry_base(h) {} + + ~cpio_entry() override { free(data); }; }; typedef std::map> entry_map; @@ -61,6 +62,7 @@ public: protected: void mv(entry_map::iterator &it, const char *to); + void load_cpio(char *buf, size_t sz); }; class cpio_mmap : public cpio {