blob: c40b9a586b428491d0e7969a3f841dd873530bb5 [file] [log] [blame]
/*
* Copyright 2018 The Hafnium Authors.
*
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/BSD-3-Clause.
*/
#include "hf/cpio.h"
#include <stdint.h>
#include "hf/std.h"
#pragma pack(push, 1)
struct cpio_header {
uint16_t magic;
uint16_t dev;
uint16_t ino;
uint16_t mode;
uint16_t uid;
uint16_t gid;
uint16_t nlink;
uint16_t rdev;
uint16_t mtime[2];
uint16_t namesize;
uint16_t filesize[2];
};
#pragma pack(pop)
/**
* Retrieves the next file stored in the cpio archive stored in the cpio, and
* advances the iterator such that another call to this function would return
* the following file.
*/
static bool cpio_next(struct memiter *iter, const char **name,
const void **contents, size_t *size)
{
static const char trailer[] = "TRAILER!!!";
size_t len;
struct memiter lit = *iter;
const struct cpio_header *h = (const struct cpio_header *)lit.next;
if (!memiter_advance(&lit, sizeof(struct cpio_header))) {
return false;
}
*name = lit.next;
/* TODO: Check magic. */
len = (h->namesize + 1) & ~1;
if (!memiter_advance(&lit, len)) {
return false;
}
*contents = lit.next;
len = (size_t)h->filesize[0] << 16 | h->filesize[1];
if (!memiter_advance(&lit, (len + 1) & ~1)) {
return false;
}
/* TODO: Check that string is null-terminated. */
/* Stop enumerating files when we hit the end marker. */
if (!strncmp(*name, trailer, sizeof(trailer))) {
return false;
}
*size = len;
*iter = lit;
return true;
}
/**
* Looks for a file in the given cpio archive. The file, if found, is returned
* in the "it" argument.
*/
bool cpio_get_file(const struct memiter *cpio, const struct string *name,
struct memiter *it)
{
const char *fname;
const void *fcontents;
size_t fsize;
struct memiter iter = *cpio;
while (cpio_next(&iter, &fname, &fcontents, &fsize)) {
if (!strncmp(fname, string_data(name), STRING_MAX_SIZE)) {
memiter_init(it, fcontents, fsize);
return true;
}
}
return false;
}