blob: 2a00837b5838b590c5d7541860a6bf3925ee8307 [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;
Andrew Scull7364a8e2018-07-19 15:39:29 +010044 if (size_left < sizeof(struct cpio_header)) {
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
48 /* TODO: Check magic. */
49
50 size_left -= sizeof(struct cpio_header);
51 namelen = (h->namesize + 1) & ~1;
Andrew Scull7364a8e2018-07-19 15:39:29 +010052 if (size_left < namelen) {
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010053 return false;
Andrew Scull7364a8e2018-07-19 15:39:29 +010054 }
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010055
56 size_left -= namelen;
57 filelen = (size_t)h->filesize[0] << 16 | h->filesize[1];
Andrew Scull7364a8e2018-07-19 15:39:29 +010058 if (size_left < filelen) {
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
62 /* TODO: Check that string is null-terminated. */
63 /* TODO: Check that trailler is not returned. */
64
65 /* Stop enumerating files when we hit the end marker. */
Andrew Scull7364a8e2018-07-19 15:39:29 +010066 if (!strcmp((const char *)(iter->cur + 1), "TRAILER!!!")) {
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010067 return false;
Andrew Scull7364a8e2018-07-19 15:39:29 +010068 }
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010069
70 size_left -= filelen;
71
72 *name = (const char *)(iter->cur + 1);
73 *contents = *name + namelen;
74 *size = filelen;
75
76 iter->cur = (struct cpio_header *)((char *)*contents + filelen);
Andrew Scull4f170f52018-07-19 12:58:20 +010077 iter->cur =
78 (struct cpio_header *)(char *)(((size_t)iter->cur + 1) & ~1);
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010079 iter->size_left = size_left;
80
81 return true;
82}