blob: c40b9a586b428491d0e7969a3f841dd873530bb5 [file] [log] [blame]
Andrew Scull18834872018-10-12 11:48:09 +01001/*
Andrew Walbran692b3252019-03-07 15:51:31 +00002 * Copyright 2018 The Hafnium Authors.
Andrew Scull18834872018-10-12 11:48:09 +01003 *
Andrew Walbrane959ec12020-06-17 15:01:09 +01004 * 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 Scull18834872018-10-12 11:48:09 +01007 */
8
Andrew Scull18c78fc2018-08-20 12:57:41 +01009#include "hf/cpio.h"
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010010
11#include <stdint.h>
12
Andrew Scull8d9e1212019-04-05 13:52:55 +010013#include "hf/std.h"
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010014
15#pragma pack(push, 1)
16struct 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 Filho9ee60e92018-07-23 18:56:56 +010031/**
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 Brazdil136f2942019-09-23 14:11:03 +010036static bool cpio_next(struct memiter *iter, const char **name,
37 const void **contents, size_t *size)
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010038{
Andrew Scull3c351e92020-01-28 11:26:05 +000039 static const char trailer[] = "TRAILER!!!";
Wedson Almeida Filho9ee60e92018-07-23 18:56:56 +010040 size_t len;
41 struct memiter lit = *iter;
42 const struct cpio_header *h = (const struct cpio_header *)lit.next;
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010043
Wedson Almeida Filho9ee60e92018-07-23 18:56:56 +010044 if (!memiter_advance(&lit, 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
Wedson Almeida Filho9ee60e92018-07-23 18:56:56 +010048 *name = lit.next;
49
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010050 /* TODO: Check magic. */
51
Wedson Almeida Filho9ee60e92018-07-23 18:56:56 +010052 len = (h->namesize + 1) & ~1;
53 if (!memiter_advance(&lit, len)) {
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010054 return false;
Andrew Scull7364a8e2018-07-19 15:39:29 +010055 }
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010056
Wedson Almeida Filho9ee60e92018-07-23 18:56:56 +010057 *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 Filho987c0ff2018-06-20 16:34:38 +010061 return false;
Andrew Scull7364a8e2018-07-19 15:39:29 +010062 }
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010063
64 /* TODO: Check that string is null-terminated. */
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010065
66 /* Stop enumerating files when we hit the end marker. */
Andrew Scull3c351e92020-01-28 11:26:05 +000067 if (!strncmp(*name, trailer, sizeof(trailer))) {
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010068 return false;
Andrew Scull7364a8e2018-07-19 15:39:29 +010069 }
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010070
Wedson Almeida Filho9ee60e92018-07-23 18:56:56 +010071 *size = len;
72 *iter = lit;
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010073
74 return true;
75}
David Brazdil136f2942019-09-23 14:11:03 +010076
77/**
78 * Looks for a file in the given cpio archive. The file, if found, is returned
79 * in the "it" argument.
80 */
81bool 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 Scull3c351e92020-01-28 11:26:05 +000090 if (!strncmp(fname, string_data(name), STRING_MAX_SIZE)) {
David Brazdil136f2942019-09-23 14:11:03 +010091 memiter_init(it, fcontents, fsize);
92 return true;
93 }
94 }
95
96 return false;
97}