Support loading CPIO from a chunk of bytes
This commit is contained in:
parent
4a398642b8
commit
1d3ce9fef1
@ -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<cpio_entry> entry;
|
||||
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);
|
||||
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<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) {
|
||||
mmap_ro(filename, (void **) &buf, &sz);
|
||||
fprintf(stderr, "Loading cpio: [%s]\n", filename);
|
||||
|
@ -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<std::string_view, std::unique_ptr<cpio_entry_base>> 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 {
|
||||
|
Loading…
Reference in New Issue
Block a user