blob: 6cf87575fb144cd2cea24d376dd7c8e4a989f4e8 [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 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Andrew Scull18c78fc2018-08-20 12:57:41 +010017#include "hf/cpio.h"
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010018
19#include <stdint.h>
20
Andrew Scull8d9e1212019-04-05 13:52:55 +010021#include "hf/std.h"
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010022
23#pragma pack(push, 1)
24struct cpio_header {
25 uint16_t magic;
26 uint16_t dev;
27 uint16_t ino;
28 uint16_t mode;
29 uint16_t uid;
30 uint16_t gid;
31 uint16_t nlink;
32 uint16_t rdev;
33 uint16_t mtime[2];
34 uint16_t namesize;
35 uint16_t filesize[2];
36};
37#pragma pack(pop)
38
Wedson Almeida Filho9ee60e92018-07-23 18:56:56 +010039/**
40 * Retrieves the next file stored in the cpio archive stored in the cpio, and
41 * advances the iterator such that another call to this function would return
42 * the following file.
43 */
David Brazdil136f2942019-09-23 14:11:03 +010044static bool cpio_next(struct memiter *iter, const char **name,
45 const void **contents, size_t *size)
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010046{
Andrew Scull3c351e92020-01-28 11:26:05 +000047 static const char trailer[] = "TRAILER!!!";
Wedson Almeida Filho9ee60e92018-07-23 18:56:56 +010048 size_t len;
49 struct memiter lit = *iter;
50 const struct cpio_header *h = (const struct cpio_header *)lit.next;
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010051
Wedson Almeida Filho9ee60e92018-07-23 18:56:56 +010052 if (!memiter_advance(&lit, sizeof(struct cpio_header))) {
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
Wedson Almeida Filho9ee60e92018-07-23 18:56:56 +010056 *name = lit.next;
57
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010058 /* TODO: Check magic. */
59
Wedson Almeida Filho9ee60e92018-07-23 18:56:56 +010060 len = (h->namesize + 1) & ~1;
61 if (!memiter_advance(&lit, len)) {
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010062 return false;
Andrew Scull7364a8e2018-07-19 15:39:29 +010063 }
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010064
Wedson Almeida Filho9ee60e92018-07-23 18:56:56 +010065 *contents = lit.next;
66
67 len = (size_t)h->filesize[0] << 16 | h->filesize[1];
68 if (!memiter_advance(&lit, (len + 1) & ~1)) {
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010069 return false;
Andrew Scull7364a8e2018-07-19 15:39:29 +010070 }
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010071
72 /* TODO: Check that string is null-terminated. */
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010073
74 /* Stop enumerating files when we hit the end marker. */
Andrew Scull3c351e92020-01-28 11:26:05 +000075 if (!strncmp(*name, trailer, sizeof(trailer))) {
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010076 return false;
Andrew Scull7364a8e2018-07-19 15:39:29 +010077 }
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010078
Wedson Almeida Filho9ee60e92018-07-23 18:56:56 +010079 *size = len;
80 *iter = lit;
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010081
82 return true;
83}
David Brazdil136f2942019-09-23 14:11:03 +010084
85/**
86 * Looks for a file in the given cpio archive. The file, if found, is returned
87 * in the "it" argument.
88 */
89bool cpio_get_file(const struct memiter *cpio, const struct string *name,
90 struct memiter *it)
91{
92 const char *fname;
93 const void *fcontents;
94 size_t fsize;
95 struct memiter iter = *cpio;
96
97 while (cpio_next(&iter, &fname, &fcontents, &fsize)) {
Andrew Scull3c351e92020-01-28 11:26:05 +000098 if (!strncmp(fname, string_data(name), STRING_MAX_SIZE)) {
David Brazdil136f2942019-09-23 14:11:03 +010099 memiter_init(it, fcontents, fsize);
100 return true;
101 }
102 }
103
104 return false;
105}