Support loading CPIO from a chunk of bytes

This commit is contained in:
topjohnwu 2019-02-23 16:16:35 -05:00
parent 4a398642b8
commit 1d3ce9fef1
2 changed files with 34 additions and 31 deletions

View File

@ -47,23 +47,6 @@ static uint32_t x8u(const char *hex) {
cpio_entry_base::cpio_entry_base(const cpio_newc_header *h) 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)) {}; : 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) { void cpio::dump(const char *file) {
fprintf(stderr, "Dump cpio: [%s]\n", file); fprintf(stderr, "Dump cpio: [%s]\n", file);
FDOutStream fd_out(xopen(file, O_WRONLY | O_CREAT | O_TRUNC, 0644), true); 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) { 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); fprintf(stderr, "Loading cpio: [%s]\n", filename);
cpio_newc_header header; load_cpio(buf, sz);
unique_ptr<cpio_entry> entry; munmap(buf, sz);
while(xxread(fd, &header, sizeof(cpio_newc_header)) != -1) {
entry = make_unique<cpio_entry>(fd, header);
if (entry->filename == "." || entry->filename == "..")
continue;
if (entry->filename == "TRAILER!!!")
break;
entries[entry->filename] = std::move(entry);
}
close(fd);
} }
void cpio_rw::insert(cpio_entry *e) { 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) #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<cpio_entry> entry;
while (pos < sz) {
header = (cpio_newc_header *)(buf + pos);
entry = make_unique<cpio_entry>(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) { cpio_mmap::cpio_mmap(const char *filename) {
mmap_ro(filename, (void **) &buf, &sz); mmap_ro(filename, (void **) &buf, &sz);
fprintf(stderr, "Loading cpio: [%s]\n", filename); fprintf(stderr, "Loading cpio: [%s]\n", filename);

View File

@ -30,8 +30,9 @@ struct cpio_entry : public cpio_entry_base {
explicit cpio_entry(const char *name, uint32_t mode) : filename(name) { explicit cpio_entry(const char *name, uint32_t mode) : filename(name) {
this->mode = mode; this->mode = mode;
} }
cpio_entry(int fd, cpio_newc_header &header); explicit cpio_entry(cpio_newc_header *h) : cpio_entry_base(h) {}
~cpio_entry() override;
~cpio_entry() override { free(data); };
}; };
typedef std::map<std::string_view, std::unique_ptr<cpio_entry_base>> entry_map; typedef std::map<std::string_view, std::unique_ptr<cpio_entry_base>> entry_map;
@ -61,6 +62,7 @@ public:
protected: protected:
void mv(entry_map::iterator &it, const char *to); void mv(entry_map::iterator &it, const char *to);
void load_cpio(char *buf, size_t sz);
}; };
class cpio_mmap : public cpio { class cpio_mmap : public cpio {