blob: 50aa95c641d78d11afda66d3850ff13d153c33af (
plain) (
tree)
|
|
#include "initrd.h"
#include "vfile.h"
#include <ui/vt.h>
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;
}
|