Andrew Scull | 18c78fc | 2018-08-20 12:57:41 +0100 | [diff] [blame] | 1 | #include "hf/cpio.h" |
Wedson Almeida Filho | 987c0ff | 2018-06-20 16:34:38 +0100 | [diff] [blame] | 2 | |
| 3 | #include <stdint.h> |
| 4 | |
Andrew Scull | 18c78fc | 2018-08-20 12:57:41 +0100 | [diff] [blame] | 5 | #include "hf/std.h" |
Wedson Almeida Filho | 987c0ff | 2018-06-20 16:34:38 +0100 | [diff] [blame] | 6 | |
| 7 | #pragma pack(push, 1) |
| 8 | struct 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 Filho | 9ee60e9 | 2018-07-23 18:56:56 +0100 | [diff] [blame] | 23 | /** |
| 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 | */ |
| 28 | bool cpio_next(struct memiter *iter, const char **name, const void **contents, |
Andrew Scull | 4f170f5 | 2018-07-19 12:58:20 +0100 | [diff] [blame] | 29 | size_t *size) |
Wedson Almeida Filho | 987c0ff | 2018-06-20 16:34:38 +0100 | [diff] [blame] | 30 | { |
Wedson Almeida Filho | 9ee60e9 | 2018-07-23 18:56:56 +0100 | [diff] [blame] | 31 | size_t len; |
| 32 | struct memiter lit = *iter; |
| 33 | const struct cpio_header *h = (const struct cpio_header *)lit.next; |
Wedson Almeida Filho | 987c0ff | 2018-06-20 16:34:38 +0100 | [diff] [blame] | 34 | |
Wedson Almeida Filho | 9ee60e9 | 2018-07-23 18:56:56 +0100 | [diff] [blame] | 35 | if (!memiter_advance(&lit, sizeof(struct cpio_header))) { |
Wedson Almeida Filho | 987c0ff | 2018-06-20 16:34:38 +0100 | [diff] [blame] | 36 | return false; |
Andrew Scull | 7364a8e | 2018-07-19 15:39:29 +0100 | [diff] [blame] | 37 | } |
Wedson Almeida Filho | 987c0ff | 2018-06-20 16:34:38 +0100 | [diff] [blame] | 38 | |
Wedson Almeida Filho | 9ee60e9 | 2018-07-23 18:56:56 +0100 | [diff] [blame] | 39 | *name = lit.next; |
| 40 | |
Wedson Almeida Filho | 987c0ff | 2018-06-20 16:34:38 +0100 | [diff] [blame] | 41 | /* TODO: Check magic. */ |
| 42 | |
Wedson Almeida Filho | 9ee60e9 | 2018-07-23 18:56:56 +0100 | [diff] [blame] | 43 | len = (h->namesize + 1) & ~1; |
| 44 | if (!memiter_advance(&lit, len)) { |
Wedson Almeida Filho | 987c0ff | 2018-06-20 16:34:38 +0100 | [diff] [blame] | 45 | return false; |
Andrew Scull | 7364a8e | 2018-07-19 15:39:29 +0100 | [diff] [blame] | 46 | } |
Wedson Almeida Filho | 987c0ff | 2018-06-20 16:34:38 +0100 | [diff] [blame] | 47 | |
Wedson Almeida Filho | 9ee60e9 | 2018-07-23 18:56:56 +0100 | [diff] [blame] | 48 | *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 Filho | 987c0ff | 2018-06-20 16:34:38 +0100 | [diff] [blame] | 52 | return false; |
Andrew Scull | 7364a8e | 2018-07-19 15:39:29 +0100 | [diff] [blame] | 53 | } |
Wedson Almeida Filho | 987c0ff | 2018-06-20 16:34:38 +0100 | [diff] [blame] | 54 | |
| 55 | /* TODO: Check that string is null-terminated. */ |
Wedson Almeida Filho | 987c0ff | 2018-06-20 16:34:38 +0100 | [diff] [blame] | 56 | |
| 57 | /* Stop enumerating files when we hit the end marker. */ |
Wedson Almeida Filho | 9ee60e9 | 2018-07-23 18:56:56 +0100 | [diff] [blame] | 58 | if (!strcmp(*name, "TRAILER!!!")) { |
Wedson Almeida Filho | 987c0ff | 2018-06-20 16:34:38 +0100 | [diff] [blame] | 59 | return false; |
Andrew Scull | 7364a8e | 2018-07-19 15:39:29 +0100 | [diff] [blame] | 60 | } |
Wedson Almeida Filho | 987c0ff | 2018-06-20 16:34:38 +0100 | [diff] [blame] | 61 | |
Wedson Almeida Filho | 9ee60e9 | 2018-07-23 18:56:56 +0100 | [diff] [blame] | 62 | *size = len; |
| 63 | *iter = lit; |
Wedson Almeida Filho | 987c0ff | 2018-06-20 16:34:38 +0100 | [diff] [blame] | 64 | |
| 65 | return true; |
| 66 | } |