blob: e8e95ec8596622f2de76bf85a87beb39144e8b7f [file] [log] [blame]
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +01001#include "cpio.h"
2
3#include <stdint.h>
4
5#include "std.h"
6
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
23void cpio_init(struct cpio *c, const void *buf, size_t size)
24{
25 c->first = buf;
26 c->total_size = size;
27}
28
29void cpio_init_iter(struct cpio *c, struct cpio_iter *iter)
30{
31 iter->cur = c->first;
32 iter->size_left = c->total_size;
33}
34
Andrew Scull4f170f52018-07-19 12:58:20 +010035bool cpio_next(struct cpio_iter *iter, const char **name, const void **contents,
36 size_t *size)
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010037{
38 const struct cpio_header *h = iter->cur;
39 size_t size_left;
40 size_t filelen;
41 size_t namelen;
42
43 size_left = iter->size_left;
44 if (size_left < sizeof(struct cpio_header))
45 return false;
46
47 /* TODO: Check magic. */
48
49 size_left -= sizeof(struct cpio_header);
50 namelen = (h->namesize + 1) & ~1;
51 if (size_left < namelen)
52 return false;
53
54 size_left -= namelen;
55 filelen = (size_t)h->filesize[0] << 16 | h->filesize[1];
56 if (size_left < filelen)
57 return false;
58
59 /* TODO: Check that string is null-terminated. */
60 /* TODO: Check that trailler is not returned. */
61
62 /* Stop enumerating files when we hit the end marker. */
63 if (!strcmp((const char *)(iter->cur + 1), "TRAILER!!!"))
64 return false;
65
66 size_left -= filelen;
67
68 *name = (const char *)(iter->cur + 1);
69 *contents = *name + namelen;
70 *size = filelen;
71
72 iter->cur = (struct cpio_header *)((char *)*contents + filelen);
Andrew Scull4f170f52018-07-19 12:58:20 +010073 iter->cur =
74 (struct cpio_header *)(char *)(((size_t)iter->cur + 1) & ~1);
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010075 iter->size_left = size_left;
76
77 return true;
78}