#include "initrd.h" #include "vfile.h" #include int initrd_check(uint8_t *data) { initrd_header *h = (initrd_header*)data; if (h->magic == INITRD_MAGIC) return 0; return -1; } int initrd_load(uint8_t *data, vdir *root) { if (root == 0) return -1; union { uint8_t *c; initrd_header *ih; initrd_file_header *fh; } curr; curr.c = data; if (curr.ih->magic != INITRD_MAGIC) return -2; uint32_t files = curr.ih->files; curr.ih++; for (unsigned i = 0; i < files; i++) { initrd_file_header *h = curr.fh; curr.fh++; if (h->name_length == 0) continue; char* path = (char*)curr.c; curr.c += h->name_length + 1; if (strlen(path) != (int)h->name_length) return -3; node* parent = root; // parse filename char *member = path; while (*path != 0 && parent != 0) { if (*path == '/') { if (member == path) { member++; path++; } else { *path = 0; path++; node* n = parent->get_child(member); if (n == 0) { n = new vdir(parent); parent->add_child(member, n); } parent = n; member = path; } } else { path++; } } if (parent == 0) return -5; if (member == path) return -6; // filename ended by '/', bad. // add file if (h->file_length == 0) { if (parent->add_child(member, new vdir(parent)) != 0) return -4; } else { if (parent->add_child(member, new vfile(parent, (char*)curr.c, h->file_length)) != 0) return -4; curr.c += h->file_length; } } return 0; }