97 lines
1.8 KiB
C
97 lines
1.8 KiB
C
|
|
#include "tar.h"
|
||
|
|
|
||
|
|
#include <mango/handle.h>
|
||
|
|
#include <mango/vm.h>
|
||
|
|
#include <string.h>
|
||
|
|
|
||
|
|
size_t getsize(const char *in)
|
||
|
|
{
|
||
|
|
size_t size = 0;
|
||
|
|
size_t j;
|
||
|
|
size_t count = 1;
|
||
|
|
|
||
|
|
for (j = 11; j > 0; j--, count *= 8) {
|
||
|
|
size += ((in[j - 1] - '0') * count);
|
||
|
|
}
|
||
|
|
|
||
|
|
return size;
|
||
|
|
}
|
||
|
|
|
||
|
|
int tar_init(struct tar *tar, uintptr_t base)
|
||
|
|
{
|
||
|
|
memset(tar, 0x0, sizeof *tar);
|
||
|
|
tar->tar_entries = (struct tar_bin_header *)base;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
int tar_open(struct tar *tar, const char *path, struct tar_file *out)
|
||
|
|
{
|
||
|
|
while (*path == '/') {
|
||
|
|
path++;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (*path == '\0') {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
struct tar_bin_header *bin_header = tar->tar_entries;
|
||
|
|
struct tar_header header;
|
||
|
|
for (size_t i = 0;; i++) {
|
||
|
|
tar_header_decode(bin_header, &header);
|
||
|
|
if (bin_header->filename[0] == 0) {
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
char *s = (char *)bin_header;
|
||
|
|
s += sizeof *bin_header;
|
||
|
|
|
||
|
|
if (!strcmp(bin_header->filename, path)) {
|
||
|
|
out->f_header = header;
|
||
|
|
out->f_data = s;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
s += header.size;
|
||
|
|
s += ((sizeof *bin_header)
|
||
|
|
- ((uintptr_t)s % (sizeof *bin_header)));
|
||
|
|
|
||
|
|
bin_header = (struct tar_bin_header *)s;
|
||
|
|
}
|
||
|
|
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
int tar_file_create_vm_object(const struct tar_file *file, kern_handle_t *out)
|
||
|
|
{
|
||
|
|
const void *data = file->f_data;
|
||
|
|
size_t len = file->f_header.size;
|
||
|
|
kern_handle_t vmo = KERN_HANDLE_INVALID;
|
||
|
|
|
||
|
|
kern_status_t status = vm_object_create(
|
||
|
|
NULL,
|
||
|
|
0,
|
||
|
|
file->f_header.size,
|
||
|
|
VM_PROT_READ | VM_PROT_EXEC | VM_PROT_USER,
|
||
|
|
&vmo);
|
||
|
|
if (status != KERN_OK) {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
size_t nr_written = 0;
|
||
|
|
status = vm_object_write(vmo, data, 0, len, &nr_written);
|
||
|
|
if (status != KERN_OK || nr_written != len) {
|
||
|
|
kern_handle_close(vmo);
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
*out = vmo;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
int tar_header_decode(const struct tar_bin_header *in, struct tar_header *out)
|
||
|
|
{
|
||
|
|
memcpy(out->filename, in->filename, sizeof out->filename);
|
||
|
|
out->size = getsize(in->size);
|
||
|
|
return 0;
|
||
|
|
}
|