blob: d613e5416fd6fc05a2ef590b54f2c9b7d8190ab6 [file] [log] [blame]
Andrew Scull18c78fc2018-08-20 12:57:41 +01001#include "hf/cpio.h"
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +01002
3#include <stdint.h>
4
Andrew Scull18c78fc2018-08-20 12:57:41 +01005#include "hf/std.h"
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +01006
7#pragma pack(push, 1)
8struct cpio_header {
9 uint16_t magic;
10 uint16_t dev;
11 uint16_t ino;
12 uint16_t mode;
13 uint16_t uid;
14 uint16_t gid;
15 uint16_t nlink;
16 uint16_t rdev;
17 uint16_t mtime[2];
18 uint16_t namesize;
19 uint16_t filesize[2];
20};
21#pragma pack(pop)
22
Wedson Almeida Filho9ee60e92018-07-23 18:56:56 +010023/**
24 * Retrieves the next file stored in the cpio archive stored in the cpio, and
25 * advances the iterator such that another call to this function would return
26 * the following file.
27 */
28bool cpio_next(struct memiter *iter, const char **name, const void **contents,
Andrew Scull4f170f52018-07-19 12:58:20 +010029 size_t *size)
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010030{
Wedson Almeida Filho9ee60e92018-07-23 18:56:56 +010031 size_t len;
32 struct memiter lit = *iter;
33 const struct cpio_header *h = (const struct cpio_header *)lit.next;
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010034
Wedson Almeida Filho9ee60e92018-07-23 18:56:56 +010035 if (!memiter_advance(&lit, sizeof(struct cpio_header))) {
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010036 return false;
Andrew Scull7364a8e2018-07-19 15:39:29 +010037 }
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010038
Wedson Almeida Filho9ee60e92018-07-23 18:56:56 +010039 *name = lit.next;
40
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010041 /* TODO: Check magic. */
42
Wedson Almeida Filho9ee60e92018-07-23 18:56:56 +010043 len = (h->namesize + 1) & ~1;
44 if (!memiter_advance(&lit, len)) {
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010045 return false;
Andrew Scull7364a8e2018-07-19 15:39:29 +010046 }
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010047
Wedson Almeida Filho9ee60e92018-07-23 18:56:56 +010048 *contents = lit.next;
49
50 len = (size_t)h->filesize[0] << 16 | h->filesize[1];
51 if (!memiter_advance(&lit, (len + 1) & ~1)) {
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010052 return false;
Andrew Scull7364a8e2018-07-19 15:39:29 +010053 }
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010054
55 /* TODO: Check that string is null-terminated. */
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010056
57 /* Stop enumerating files when we hit the end marker. */
Wedson Almeida Filho9ee60e92018-07-23 18:56:56 +010058 if (!strcmp(*name, "TRAILER!!!")) {
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010059 return false;
Andrew Scull7364a8e2018-07-19 15:39:29 +010060 }
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010061
Wedson Almeida Filho9ee60e92018-07-23 18:56:56 +010062 *size = len;
63 *iter = lit;
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010064
65 return true;
66}