Andrew Scull | 1883487 | 2018-10-12 11:48:09 +0100 | [diff] [blame] | 1 | /* |
Andrew Walbran | 692b325 | 2019-03-07 15:51:31 +0000 | [diff] [blame] | 2 | * Copyright 2018 The Hafnium Authors. |
Andrew Scull | 1883487 | 2018-10-12 11:48:09 +0100 | [diff] [blame] | 3 | * |
Andrew Walbran | e959ec1 | 2020-06-17 15:01:09 +0100 | [diff] [blame] | 4 | * Use of this source code is governed by a BSD-style |
| 5 | * license that can be found in the LICENSE file or at |
| 6 | * https://opensource.org/licenses/BSD-3-Clause. |
Andrew Scull | 1883487 | 2018-10-12 11:48:09 +0100 | [diff] [blame] | 7 | */ |
| 8 | |
Andrew Scull | 18c78fc | 2018-08-20 12:57:41 +0100 | [diff] [blame] | 9 | #include "hf/cpio.h" |
Wedson Almeida Filho | 987c0ff | 2018-06-20 16:34:38 +0100 | [diff] [blame] | 10 | |
| 11 | #include <stdint.h> |
| 12 | |
Andrew Scull | 8d9e121 | 2019-04-05 13:52:55 +0100 | [diff] [blame] | 13 | #include "hf/std.h" |
Wedson Almeida Filho | 987c0ff | 2018-06-20 16:34:38 +0100 | [diff] [blame] | 14 | |
| 15 | #pragma pack(push, 1) |
| 16 | struct cpio_header { |
| 17 | uint16_t magic; |
| 18 | uint16_t dev; |
| 19 | uint16_t ino; |
| 20 | uint16_t mode; |
| 21 | uint16_t uid; |
| 22 | uint16_t gid; |
| 23 | uint16_t nlink; |
| 24 | uint16_t rdev; |
| 25 | uint16_t mtime[2]; |
| 26 | uint16_t namesize; |
| 27 | uint16_t filesize[2]; |
| 28 | }; |
| 29 | #pragma pack(pop) |
| 30 | |
Wedson Almeida Filho | 9ee60e9 | 2018-07-23 18:56:56 +0100 | [diff] [blame] | 31 | /** |
| 32 | * Retrieves the next file stored in the cpio archive stored in the cpio, and |
| 33 | * advances the iterator such that another call to this function would return |
| 34 | * the following file. |
| 35 | */ |
David Brazdil | 136f294 | 2019-09-23 14:11:03 +0100 | [diff] [blame] | 36 | static bool cpio_next(struct memiter *iter, const char **name, |
| 37 | const void **contents, size_t *size) |
Wedson Almeida Filho | 987c0ff | 2018-06-20 16:34:38 +0100 | [diff] [blame] | 38 | { |
Andrew Scull | 3c351e9 | 2020-01-28 11:26:05 +0000 | [diff] [blame] | 39 | static const char trailer[] = "TRAILER!!!"; |
Wedson Almeida Filho | 9ee60e9 | 2018-07-23 18:56:56 +0100 | [diff] [blame] | 40 | size_t len; |
| 41 | struct memiter lit = *iter; |
| 42 | const struct cpio_header *h = (const struct cpio_header *)lit.next; |
Wedson Almeida Filho | 987c0ff | 2018-06-20 16:34:38 +0100 | [diff] [blame] | 43 | |
Wedson Almeida Filho | 9ee60e9 | 2018-07-23 18:56:56 +0100 | [diff] [blame] | 44 | if (!memiter_advance(&lit, sizeof(struct cpio_header))) { |
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 | *name = lit.next; |
| 49 | |
Wedson Almeida Filho | 987c0ff | 2018-06-20 16:34:38 +0100 | [diff] [blame] | 50 | /* TODO: Check magic. */ |
| 51 | |
Wedson Almeida Filho | 9ee60e9 | 2018-07-23 18:56:56 +0100 | [diff] [blame] | 52 | len = (h->namesize + 1) & ~1; |
| 53 | if (!memiter_advance(&lit, len)) { |
Wedson Almeida Filho | 987c0ff | 2018-06-20 16:34:38 +0100 | [diff] [blame] | 54 | return false; |
Andrew Scull | 7364a8e | 2018-07-19 15:39:29 +0100 | [diff] [blame] | 55 | } |
Wedson Almeida Filho | 987c0ff | 2018-06-20 16:34:38 +0100 | [diff] [blame] | 56 | |
Wedson Almeida Filho | 9ee60e9 | 2018-07-23 18:56:56 +0100 | [diff] [blame] | 57 | *contents = lit.next; |
| 58 | |
| 59 | len = (size_t)h->filesize[0] << 16 | h->filesize[1]; |
| 60 | if (!memiter_advance(&lit, (len + 1) & ~1)) { |
Wedson Almeida Filho | 987c0ff | 2018-06-20 16:34:38 +0100 | [diff] [blame] | 61 | return false; |
Andrew Scull | 7364a8e | 2018-07-19 15:39:29 +0100 | [diff] [blame] | 62 | } |
Wedson Almeida Filho | 987c0ff | 2018-06-20 16:34:38 +0100 | [diff] [blame] | 63 | |
| 64 | /* TODO: Check that string is null-terminated. */ |
Wedson Almeida Filho | 987c0ff | 2018-06-20 16:34:38 +0100 | [diff] [blame] | 65 | |
| 66 | /* Stop enumerating files when we hit the end marker. */ |
Andrew Scull | 3c351e9 | 2020-01-28 11:26:05 +0000 | [diff] [blame] | 67 | if (!strncmp(*name, trailer, sizeof(trailer))) { |
Wedson Almeida Filho | 987c0ff | 2018-06-20 16:34:38 +0100 | [diff] [blame] | 68 | return false; |
Andrew Scull | 7364a8e | 2018-07-19 15:39:29 +0100 | [diff] [blame] | 69 | } |
Wedson Almeida Filho | 987c0ff | 2018-06-20 16:34:38 +0100 | [diff] [blame] | 70 | |
Wedson Almeida Filho | 9ee60e9 | 2018-07-23 18:56:56 +0100 | [diff] [blame] | 71 | *size = len; |
| 72 | *iter = lit; |
Wedson Almeida Filho | 987c0ff | 2018-06-20 16:34:38 +0100 | [diff] [blame] | 73 | |
| 74 | return true; |
| 75 | } |
David Brazdil | 136f294 | 2019-09-23 14:11:03 +0100 | [diff] [blame] | 76 | |
| 77 | /** |
| 78 | * Looks for a file in the given cpio archive. The file, if found, is returned |
| 79 | * in the "it" argument. |
| 80 | */ |
| 81 | bool cpio_get_file(const struct memiter *cpio, const struct string *name, |
| 82 | struct memiter *it) |
| 83 | { |
| 84 | const char *fname; |
| 85 | const void *fcontents; |
| 86 | size_t fsize; |
| 87 | struct memiter iter = *cpio; |
| 88 | |
| 89 | while (cpio_next(&iter, &fname, &fcontents, &fsize)) { |
Andrew Scull | 3c351e9 | 2020-01-28 11:26:05 +0000 | [diff] [blame] | 90 | if (!strncmp(fname, string_data(name), STRING_MAX_SIZE)) { |
David Brazdil | 136f294 | 2019-09-23 14:11:03 +0100 | [diff] [blame] | 91 | memiter_init(it, fcontents, fsize); |
| 92 | return true; |
| 93 | } |
| 94 | } |
| 95 | |
| 96 | return false; |
| 97 | } |