xref: /aosp_15_r20/external/vboot_reference/futility/updater_archive.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
1*8617a60dSAndroid Build Coastguard Worker /* Copyright 2018 The ChromiumOS Authors
2*8617a60dSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
3*8617a60dSAndroid Build Coastguard Worker  * found in the LICENSE file.
4*8617a60dSAndroid Build Coastguard Worker  *
5*8617a60dSAndroid Build Coastguard Worker  * Accessing updater resources from an archive.
6*8617a60dSAndroid Build Coastguard Worker  */
7*8617a60dSAndroid Build Coastguard Worker 
8*8617a60dSAndroid Build Coastguard Worker #include <assert.h>
9*8617a60dSAndroid Build Coastguard Worker #include <errno.h>
10*8617a60dSAndroid Build Coastguard Worker #if defined(__OpenBSD__)
11*8617a60dSAndroid Build Coastguard Worker #include <sys/types.h>
12*8617a60dSAndroid Build Coastguard Worker #endif
13*8617a60dSAndroid Build Coastguard Worker #include <fts.h>
14*8617a60dSAndroid Build Coastguard Worker #include <sys/stat.h>
15*8617a60dSAndroid Build Coastguard Worker #include <sys/time.h>
16*8617a60dSAndroid Build Coastguard Worker #include <unistd.h>
17*8617a60dSAndroid Build Coastguard Worker 
18*8617a60dSAndroid Build Coastguard Worker #ifdef HAVE_LIBARCHIVE
19*8617a60dSAndroid Build Coastguard Worker #include <archive.h>
20*8617a60dSAndroid Build Coastguard Worker #include <archive_entry.h>
21*8617a60dSAndroid Build Coastguard Worker #endif
22*8617a60dSAndroid Build Coastguard Worker 
23*8617a60dSAndroid Build Coastguard Worker #ifdef HAVE_LIBZIP
24*8617a60dSAndroid Build Coastguard Worker #ifndef __clang__
25*8617a60dSAndroid Build Coastguard Worker /* If libzip headers were built for Clang but later get included with GCC you
26*8617a60dSAndroid Build Coastguard Worker    need this. This check should really be in libzip but apparently they think
27*8617a60dSAndroid Build Coastguard Worker    it's fine to ship compiler-specific system headers or something... */
28*8617a60dSAndroid Build Coastguard Worker #define _Nullable
29*8617a60dSAndroid Build Coastguard Worker #define _Nonnull
30*8617a60dSAndroid Build Coastguard Worker #endif
31*8617a60dSAndroid Build Coastguard Worker #include <zip.h>
32*8617a60dSAndroid Build Coastguard Worker #endif
33*8617a60dSAndroid Build Coastguard Worker 
34*8617a60dSAndroid Build Coastguard Worker #include "host_misc.h"
35*8617a60dSAndroid Build Coastguard Worker #include "updater.h"
36*8617a60dSAndroid Build Coastguard Worker 
37*8617a60dSAndroid Build Coastguard Worker /*
38*8617a60dSAndroid Build Coastguard Worker  * A firmware update package (archive) is a file packed by either shar(1) or
39*8617a60dSAndroid Build Coastguard Worker  * zip(1). See https://chromium.googlesource.com/chromiumos/platform/firmware/
40*8617a60dSAndroid Build Coastguard Worker  * for more information.
41*8617a60dSAndroid Build Coastguard Worker  */
42*8617a60dSAndroid Build Coastguard Worker 
43*8617a60dSAndroid Build Coastguard Worker struct u_archive {
44*8617a60dSAndroid Build Coastguard Worker 	void *handle;
45*8617a60dSAndroid Build Coastguard Worker 
46*8617a60dSAndroid Build Coastguard Worker 	void * (*open)(const char *name);
47*8617a60dSAndroid Build Coastguard Worker 	int (*close)(void *handle);
48*8617a60dSAndroid Build Coastguard Worker 
49*8617a60dSAndroid Build Coastguard Worker 	int (*walk)(void *handle, void *arg,
50*8617a60dSAndroid Build Coastguard Worker 		    int (*callback)(const char *path, void *arg));
51*8617a60dSAndroid Build Coastguard Worker 	int (*has_entry)(void *handle, const char *name);
52*8617a60dSAndroid Build Coastguard Worker 	int (*read_file)(void *handle, const char *fname,
53*8617a60dSAndroid Build Coastguard Worker 			 uint8_t **data, uint32_t *size, int64_t *mtime);
54*8617a60dSAndroid Build Coastguard Worker 	int (*write_file)(void *handle, const char *fname,
55*8617a60dSAndroid Build Coastguard Worker 			  uint8_t *data, uint32_t size, int64_t mtime);
56*8617a60dSAndroid Build Coastguard Worker };
57*8617a60dSAndroid Build Coastguard Worker 
58*8617a60dSAndroid Build Coastguard Worker /*
59*8617a60dSAndroid Build Coastguard Worker  * -- The fallback driver (using general file system). --
60*8617a60dSAndroid Build Coastguard Worker  */
61*8617a60dSAndroid Build Coastguard Worker 
62*8617a60dSAndroid Build Coastguard Worker /* Callback for archive_open on a general file system. */
archive_fallback_open(const char * name)63*8617a60dSAndroid Build Coastguard Worker static void *archive_fallback_open(const char *name)
64*8617a60dSAndroid Build Coastguard Worker {
65*8617a60dSAndroid Build Coastguard Worker 	assert(name && *name);
66*8617a60dSAndroid Build Coastguard Worker 	return strdup(name);
67*8617a60dSAndroid Build Coastguard Worker }
68*8617a60dSAndroid Build Coastguard Worker 
69*8617a60dSAndroid Build Coastguard Worker /* Callback for archive_close on a general file system. */
archive_fallback_close(void * handle)70*8617a60dSAndroid Build Coastguard Worker static int archive_fallback_close(void *handle)
71*8617a60dSAndroid Build Coastguard Worker {
72*8617a60dSAndroid Build Coastguard Worker 	free(handle);
73*8617a60dSAndroid Build Coastguard Worker 	return 0;
74*8617a60dSAndroid Build Coastguard Worker }
75*8617a60dSAndroid Build Coastguard Worker 
76*8617a60dSAndroid Build Coastguard Worker /* Callback for archive_walk on a general file system. */
archive_fallback_walk(void * handle,void * arg,int (* callback)(const char * path,void * arg))77*8617a60dSAndroid Build Coastguard Worker static int archive_fallback_walk(
78*8617a60dSAndroid Build Coastguard Worker 		void *handle, void *arg,
79*8617a60dSAndroid Build Coastguard Worker 		int (*callback)(const char *path, void *arg))
80*8617a60dSAndroid Build Coastguard Worker {
81*8617a60dSAndroid Build Coastguard Worker 	FTS *fts_handle;
82*8617a60dSAndroid Build Coastguard Worker 	FTSENT *ent;
83*8617a60dSAndroid Build Coastguard Worker 	char *fts_argv[2] = {};
84*8617a60dSAndroid Build Coastguard Worker 	char default_path[] = ".";
85*8617a60dSAndroid Build Coastguard Worker 	char *root = default_path;
86*8617a60dSAndroid Build Coastguard Worker 	size_t root_len;
87*8617a60dSAndroid Build Coastguard Worker 
88*8617a60dSAndroid Build Coastguard Worker 	if (handle)
89*8617a60dSAndroid Build Coastguard Worker 		root = (char *)handle;
90*8617a60dSAndroid Build Coastguard Worker 	root_len = strlen(root);
91*8617a60dSAndroid Build Coastguard Worker 	fts_argv[0] = root;
92*8617a60dSAndroid Build Coastguard Worker 
93*8617a60dSAndroid Build Coastguard Worker 	fts_handle = fts_open(fts_argv, FTS_NOCHDIR, NULL);
94*8617a60dSAndroid Build Coastguard Worker 	if (!fts_handle)
95*8617a60dSAndroid Build Coastguard Worker 		return -1;
96*8617a60dSAndroid Build Coastguard Worker 
97*8617a60dSAndroid Build Coastguard Worker 	while ((ent = fts_read(fts_handle)) != NULL) {
98*8617a60dSAndroid Build Coastguard Worker 		char *path = ent->fts_path + root_len;
99*8617a60dSAndroid Build Coastguard Worker 		if (ent->fts_info != FTS_F && ent->fts_info != FTS_SL)
100*8617a60dSAndroid Build Coastguard Worker 			continue;
101*8617a60dSAndroid Build Coastguard Worker 		while (*path == '/')
102*8617a60dSAndroid Build Coastguard Worker 			path++;
103*8617a60dSAndroid Build Coastguard Worker 		if (!*path)
104*8617a60dSAndroid Build Coastguard Worker 			continue;
105*8617a60dSAndroid Build Coastguard Worker 		if (callback(path, arg))
106*8617a60dSAndroid Build Coastguard Worker 			break;
107*8617a60dSAndroid Build Coastguard Worker 	}
108*8617a60dSAndroid Build Coastguard Worker 	return 0;
109*8617a60dSAndroid Build Coastguard Worker }
110*8617a60dSAndroid Build Coastguard Worker 
111*8617a60dSAndroid Build Coastguard Worker /* Callback for fallback drivers to get full path easily. */
archive_fallback_get_path(void * handle,const char * fname,char ** temp_path)112*8617a60dSAndroid Build Coastguard Worker static const char *archive_fallback_get_path(void *handle, const char *fname,
113*8617a60dSAndroid Build Coastguard Worker 					     char **temp_path)
114*8617a60dSAndroid Build Coastguard Worker {
115*8617a60dSAndroid Build Coastguard Worker 	if (handle && *fname != '/') {
116*8617a60dSAndroid Build Coastguard Worker 		ASPRINTF(temp_path, "%s/%s", (char *)handle, fname);
117*8617a60dSAndroid Build Coastguard Worker 		return *temp_path;
118*8617a60dSAndroid Build Coastguard Worker 	}
119*8617a60dSAndroid Build Coastguard Worker 	return fname;
120*8617a60dSAndroid Build Coastguard Worker }
121*8617a60dSAndroid Build Coastguard Worker 
122*8617a60dSAndroid Build Coastguard Worker /* Callback for archive_has_entry on a general file system. */
archive_fallback_has_entry(void * handle,const char * fname)123*8617a60dSAndroid Build Coastguard Worker static int archive_fallback_has_entry(void *handle, const char *fname)
124*8617a60dSAndroid Build Coastguard Worker {
125*8617a60dSAndroid Build Coastguard Worker 	int r;
126*8617a60dSAndroid Build Coastguard Worker 	char *temp_path = NULL;
127*8617a60dSAndroid Build Coastguard Worker 	const char *path = archive_fallback_get_path(handle, fname, &temp_path);
128*8617a60dSAndroid Build Coastguard Worker 
129*8617a60dSAndroid Build Coastguard Worker 	VB2_DEBUG("Checking %s\n", path);
130*8617a60dSAndroid Build Coastguard Worker 	r = access(path, R_OK);
131*8617a60dSAndroid Build Coastguard Worker 	free(temp_path);
132*8617a60dSAndroid Build Coastguard Worker 	return r == 0;
133*8617a60dSAndroid Build Coastguard Worker }
134*8617a60dSAndroid Build Coastguard Worker 
135*8617a60dSAndroid Build Coastguard Worker /* Callback for archive_read_file on a general file system. */
archive_fallback_read_file(void * handle,const char * fname,uint8_t ** data,uint32_t * size,int64_t * mtime)136*8617a60dSAndroid Build Coastguard Worker static int archive_fallback_read_file(void *handle, const char *fname,
137*8617a60dSAndroid Build Coastguard Worker 				      uint8_t **data, uint32_t *size, int64_t *mtime)
138*8617a60dSAndroid Build Coastguard Worker {
139*8617a60dSAndroid Build Coastguard Worker 	int r;
140*8617a60dSAndroid Build Coastguard Worker 	char *temp_path = NULL;
141*8617a60dSAndroid Build Coastguard Worker 	const char *path = archive_fallback_get_path(handle, fname, &temp_path);
142*8617a60dSAndroid Build Coastguard Worker 	struct stat st;
143*8617a60dSAndroid Build Coastguard Worker 
144*8617a60dSAndroid Build Coastguard Worker 	VB2_DEBUG("Reading %s\n", path);
145*8617a60dSAndroid Build Coastguard Worker 	*data = NULL;
146*8617a60dSAndroid Build Coastguard Worker 	*size = 0;
147*8617a60dSAndroid Build Coastguard Worker 	/* vb2_read_file already has an extra '\0' in the end. */
148*8617a60dSAndroid Build Coastguard Worker 	r = vb2_read_file(path, data, size) != VB2_SUCCESS;
149*8617a60dSAndroid Build Coastguard Worker 	if (mtime) {
150*8617a60dSAndroid Build Coastguard Worker 		if (stat(path, &st) == 0)
151*8617a60dSAndroid Build Coastguard Worker 			*mtime = st.st_mtime;
152*8617a60dSAndroid Build Coastguard Worker 		else
153*8617a60dSAndroid Build Coastguard Worker 			WARN("Unable to stat %s: %s\n", path, strerror(errno));
154*8617a60dSAndroid Build Coastguard Worker 	}
155*8617a60dSAndroid Build Coastguard Worker 	free(temp_path);
156*8617a60dSAndroid Build Coastguard Worker 	return r;
157*8617a60dSAndroid Build Coastguard Worker }
158*8617a60dSAndroid Build Coastguard Worker 
159*8617a60dSAndroid Build Coastguard Worker /* Callback for archive_write_file on a general file system. */
archive_fallback_write_file(void * handle,const char * fname,uint8_t * data,uint32_t size,int64_t mtime)160*8617a60dSAndroid Build Coastguard Worker static int archive_fallback_write_file(void *handle, const char *fname,
161*8617a60dSAndroid Build Coastguard Worker 				       uint8_t *data, uint32_t size, int64_t mtime)
162*8617a60dSAndroid Build Coastguard Worker {
163*8617a60dSAndroid Build Coastguard Worker 	int r;
164*8617a60dSAndroid Build Coastguard Worker 	char *temp_path = NULL;
165*8617a60dSAndroid Build Coastguard Worker 	const char *path = archive_fallback_get_path(handle, fname, &temp_path);
166*8617a60dSAndroid Build Coastguard Worker 
167*8617a60dSAndroid Build Coastguard Worker 	VB2_DEBUG("Writing %s\n", path);
168*8617a60dSAndroid Build Coastguard Worker 	if (strchr(path, '/')) {
169*8617a60dSAndroid Build Coastguard Worker 		char *dirname = strdup(path);
170*8617a60dSAndroid Build Coastguard Worker 		*strrchr(dirname, '/') = '\0';
171*8617a60dSAndroid Build Coastguard Worker 		/* TODO(hungte): call mkdir(2) instead of shell invocation. */
172*8617a60dSAndroid Build Coastguard Worker 		if (access(dirname, W_OK) != 0) {
173*8617a60dSAndroid Build Coastguard Worker 			char *command;
174*8617a60dSAndroid Build Coastguard Worker 			ASPRINTF(&command, "mkdir -p %s", dirname);
175*8617a60dSAndroid Build Coastguard Worker 			free(host_shell(command));
176*8617a60dSAndroid Build Coastguard Worker 			free(command);
177*8617a60dSAndroid Build Coastguard Worker 		}
178*8617a60dSAndroid Build Coastguard Worker 		free(dirname);
179*8617a60dSAndroid Build Coastguard Worker 	}
180*8617a60dSAndroid Build Coastguard Worker 	r = vb2_write_file(path, data, size) != VB2_SUCCESS;
181*8617a60dSAndroid Build Coastguard Worker 	if (mtime) {
182*8617a60dSAndroid Build Coastguard Worker 		struct timeval times[2] = {
183*8617a60dSAndroid Build Coastguard Worker 			{.tv_sec = mtime, .tv_usec = 0},
184*8617a60dSAndroid Build Coastguard Worker 			{.tv_sec = mtime, .tv_usec = 0},
185*8617a60dSAndroid Build Coastguard Worker 		};
186*8617a60dSAndroid Build Coastguard Worker 		if (utimes(path, times) != 0)
187*8617a60dSAndroid Build Coastguard Worker 			WARN("Unable to set times on %s: %s\n", path, strerror(errno));
188*8617a60dSAndroid Build Coastguard Worker 	}
189*8617a60dSAndroid Build Coastguard Worker 	free(temp_path);
190*8617a60dSAndroid Build Coastguard Worker 	return r;
191*8617a60dSAndroid Build Coastguard Worker }
192*8617a60dSAndroid Build Coastguard Worker 
193*8617a60dSAndroid Build Coastguard Worker /*
194*8617a60dSAndroid Build Coastguard Worker  * -- The cache driver (used by other drivers). --
195*8617a60dSAndroid Build Coastguard Worker  */
196*8617a60dSAndroid Build Coastguard Worker 
197*8617a60dSAndroid Build Coastguard Worker #ifdef HAVE_LIBARCHIVE
198*8617a60dSAndroid Build Coastguard Worker 
199*8617a60dSAndroid Build Coastguard Worker /*
200*8617a60dSAndroid Build Coastguard Worker  * For stream-based archives (e.g., tar+gz) we want to create a cache for
201*8617a60dSAndroid Build Coastguard Worker  * storing the names and contents for later processing.
202*8617a60dSAndroid Build Coastguard Worker  */
203*8617a60dSAndroid Build Coastguard Worker struct archive_cache {
204*8617a60dSAndroid Build Coastguard Worker 	char *name;
205*8617a60dSAndroid Build Coastguard Worker 	uint8_t *data;
206*8617a60dSAndroid Build Coastguard Worker 	int64_t mtime;
207*8617a60dSAndroid Build Coastguard Worker 	size_t size;
208*8617a60dSAndroid Build Coastguard Worker 	int has_data;
209*8617a60dSAndroid Build Coastguard Worker 	struct archive_cache *next;
210*8617a60dSAndroid Build Coastguard Worker };
211*8617a60dSAndroid Build Coastguard Worker 
212*8617a60dSAndroid Build Coastguard Worker /* Add a new cache node to an existing cache list and return the new head. */
archive_cache_new(struct archive_cache * cache,const char * name)213*8617a60dSAndroid Build Coastguard Worker static struct archive_cache *archive_cache_new(struct archive_cache *cache,
214*8617a60dSAndroid Build Coastguard Worker 					       const char *name)
215*8617a60dSAndroid Build Coastguard Worker {
216*8617a60dSAndroid Build Coastguard Worker 	struct archive_cache *c;
217*8617a60dSAndroid Build Coastguard Worker 
218*8617a60dSAndroid Build Coastguard Worker 	c = (struct archive_cache *)calloc(sizeof(*c), 1);
219*8617a60dSAndroid Build Coastguard Worker 	if (!c)
220*8617a60dSAndroid Build Coastguard Worker 		return NULL;
221*8617a60dSAndroid Build Coastguard Worker 
222*8617a60dSAndroid Build Coastguard Worker 	c->name = strdup(name);
223*8617a60dSAndroid Build Coastguard Worker 	if (!c->name) {
224*8617a60dSAndroid Build Coastguard Worker 		free(c);
225*8617a60dSAndroid Build Coastguard Worker 		return NULL;
226*8617a60dSAndroid Build Coastguard Worker 	}
227*8617a60dSAndroid Build Coastguard Worker 
228*8617a60dSAndroid Build Coastguard Worker 	c->next = cache;
229*8617a60dSAndroid Build Coastguard Worker 	return c;
230*8617a60dSAndroid Build Coastguard Worker }
231*8617a60dSAndroid Build Coastguard Worker 
232*8617a60dSAndroid Build Coastguard Worker /* Find and return an entry (by name) from the cache. */
archive_cache_find(struct archive_cache * c,const char * name)233*8617a60dSAndroid Build Coastguard Worker static struct archive_cache *archive_cache_find(struct archive_cache *c,
234*8617a60dSAndroid Build Coastguard Worker 						const char *name)
235*8617a60dSAndroid Build Coastguard Worker {
236*8617a60dSAndroid Build Coastguard Worker 	for (; c; c = c->next) {
237*8617a60dSAndroid Build Coastguard Worker 		assert(c->name);
238*8617a60dSAndroid Build Coastguard Worker 		if (!strcmp(c->name, name))
239*8617a60dSAndroid Build Coastguard Worker 			return c;
240*8617a60dSAndroid Build Coastguard Worker 	}
241*8617a60dSAndroid Build Coastguard Worker 	return NULL;
242*8617a60dSAndroid Build Coastguard Worker }
243*8617a60dSAndroid Build Coastguard Worker 
244*8617a60dSAndroid Build Coastguard Worker /* Callback for archive_walk to process all entries in the cache. */
archive_cache_walk(struct archive_cache * c,void * arg,int (* callback)(const char * name,void * arg))245*8617a60dSAndroid Build Coastguard Worker static int archive_cache_walk(
246*8617a60dSAndroid Build Coastguard Worker 		struct archive_cache *c, void *arg,
247*8617a60dSAndroid Build Coastguard Worker 		int (*callback)(const char *name, void *arg))
248*8617a60dSAndroid Build Coastguard Worker {
249*8617a60dSAndroid Build Coastguard Worker 	for (; c; c = c->next) {
250*8617a60dSAndroid Build Coastguard Worker 		assert(c->name);
251*8617a60dSAndroid Build Coastguard Worker 		if (callback(c->name, arg))
252*8617a60dSAndroid Build Coastguard Worker 			break;
253*8617a60dSAndroid Build Coastguard Worker 	}
254*8617a60dSAndroid Build Coastguard Worker 	return 0;
255*8617a60dSAndroid Build Coastguard Worker }
256*8617a60dSAndroid Build Coastguard Worker 
257*8617a60dSAndroid Build Coastguard Worker /* Delete all entries in the cache. */
archive_cache_free(struct archive_cache * c)258*8617a60dSAndroid Build Coastguard Worker static void *archive_cache_free(struct archive_cache *c)
259*8617a60dSAndroid Build Coastguard Worker {
260*8617a60dSAndroid Build Coastguard Worker 	struct archive_cache *next;
261*8617a60dSAndroid Build Coastguard Worker 
262*8617a60dSAndroid Build Coastguard Worker 	while (c) {
263*8617a60dSAndroid Build Coastguard Worker 		next = c->next;
264*8617a60dSAndroid Build Coastguard Worker 		free(c->name);
265*8617a60dSAndroid Build Coastguard Worker 		free(c->data);
266*8617a60dSAndroid Build Coastguard Worker 		free(c);
267*8617a60dSAndroid Build Coastguard Worker 		c = next;
268*8617a60dSAndroid Build Coastguard Worker 	}
269*8617a60dSAndroid Build Coastguard Worker 	return NULL;
270*8617a60dSAndroid Build Coastguard Worker }
271*8617a60dSAndroid Build Coastguard Worker 
272*8617a60dSAndroid Build Coastguard Worker /*
273*8617a60dSAndroid Build Coastguard Worker  * -- The libarchive driver (multiple formats but very slow). --
274*8617a60dSAndroid Build Coastguard Worker  */
275*8617a60dSAndroid Build Coastguard Worker 
276*8617a60dSAndroid Build Coastguard Worker enum {
277*8617a60dSAndroid Build Coastguard Worker 	FILTER_IGNORE,
278*8617a60dSAndroid Build Coastguard Worker 	FILTER_ABORT,
279*8617a60dSAndroid Build Coastguard Worker 	FILTER_NAME_ONLY,
280*8617a60dSAndroid Build Coastguard Worker 	FILTER_READ_ALL,
281*8617a60dSAndroid Build Coastguard Worker };
282*8617a60dSAndroid Build Coastguard Worker 
libarchive_read_file_entries(const char * fpath,int (* filter)(struct archive_entry * entry))283*8617a60dSAndroid Build Coastguard Worker static struct archive_cache *libarchive_read_file_entries(
284*8617a60dSAndroid Build Coastguard Worker 		const char *fpath, int (*filter)(struct archive_entry *entry))
285*8617a60dSAndroid Build Coastguard Worker {
286*8617a60dSAndroid Build Coastguard Worker 	struct archive *a = archive_read_new();
287*8617a60dSAndroid Build Coastguard Worker 	struct archive_entry *entry;
288*8617a60dSAndroid Build Coastguard Worker 	struct archive_cache *c, *cache = NULL;
289*8617a60dSAndroid Build Coastguard Worker 	int r;
290*8617a60dSAndroid Build Coastguard Worker 
291*8617a60dSAndroid Build Coastguard Worker 	assert(a);
292*8617a60dSAndroid Build Coastguard Worker 	archive_read_support_filter_all(a);
293*8617a60dSAndroid Build Coastguard Worker 	archive_read_support_format_all(a);
294*8617a60dSAndroid Build Coastguard Worker 	r = archive_read_open_filename(a, fpath, 10240);
295*8617a60dSAndroid Build Coastguard Worker 	if (r != ARCHIVE_OK) {
296*8617a60dSAndroid Build Coastguard Worker 		ERROR("Failed parsing archive using libarchive: %s\n", fpath);
297*8617a60dSAndroid Build Coastguard Worker 		archive_read_free(a);
298*8617a60dSAndroid Build Coastguard Worker 		return NULL;
299*8617a60dSAndroid Build Coastguard Worker 	}
300*8617a60dSAndroid Build Coastguard Worker 
301*8617a60dSAndroid Build Coastguard Worker 	WARN("Loading data from archive: %s ", fpath);
302*8617a60dSAndroid Build Coastguard Worker 	while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
303*8617a60dSAndroid Build Coastguard Worker 		fputc('.', stderr);
304*8617a60dSAndroid Build Coastguard Worker 		if (archive_entry_filetype(entry) != AE_IFREG)
305*8617a60dSAndroid Build Coastguard Worker 			continue;
306*8617a60dSAndroid Build Coastguard Worker 		if (filter)
307*8617a60dSAndroid Build Coastguard Worker 			r = filter(entry);
308*8617a60dSAndroid Build Coastguard Worker 		else
309*8617a60dSAndroid Build Coastguard Worker 			r = FILTER_READ_ALL;
310*8617a60dSAndroid Build Coastguard Worker 
311*8617a60dSAndroid Build Coastguard Worker 		if (r == FILTER_ABORT)
312*8617a60dSAndroid Build Coastguard Worker 			break;
313*8617a60dSAndroid Build Coastguard Worker 		if (r == FILTER_IGNORE)
314*8617a60dSAndroid Build Coastguard Worker 			continue;
315*8617a60dSAndroid Build Coastguard Worker 
316*8617a60dSAndroid Build Coastguard Worker 		c = archive_cache_new(cache, archive_entry_pathname(entry));
317*8617a60dSAndroid Build Coastguard Worker 		if (!c) {
318*8617a60dSAndroid Build Coastguard Worker 			ERROR("Internal error: out of memory.\n");
319*8617a60dSAndroid Build Coastguard Worker 			archive_cache_free(cache);
320*8617a60dSAndroid Build Coastguard Worker 			archive_read_free(a);
321*8617a60dSAndroid Build Coastguard Worker 			return NULL;
322*8617a60dSAndroid Build Coastguard Worker 		}
323*8617a60dSAndroid Build Coastguard Worker 		cache = c;
324*8617a60dSAndroid Build Coastguard Worker 
325*8617a60dSAndroid Build Coastguard Worker 		if (r == FILTER_NAME_ONLY)
326*8617a60dSAndroid Build Coastguard Worker 			continue;
327*8617a60dSAndroid Build Coastguard Worker 
328*8617a60dSAndroid Build Coastguard Worker 		assert(r == FILTER_READ_ALL);
329*8617a60dSAndroid Build Coastguard Worker 		c->size = archive_entry_size(entry);
330*8617a60dSAndroid Build Coastguard Worker 		c->mtime = archive_entry_mtime(entry);
331*8617a60dSAndroid Build Coastguard Worker 		c->data = (uint8_t *)calloc(1, c->size + 1);
332*8617a60dSAndroid Build Coastguard Worker 		if (!c->data) {
333*8617a60dSAndroid Build Coastguard Worker 			WARN("Out of memory when loading: %s\n", c->name);
334*8617a60dSAndroid Build Coastguard Worker 			continue;
335*8617a60dSAndroid Build Coastguard Worker 		}
336*8617a60dSAndroid Build Coastguard Worker 		if (archive_read_data(a, c->data, c->size) != c->size) {
337*8617a60dSAndroid Build Coastguard Worker 			WARN("Failed reading from archive: %s\n", c->name);
338*8617a60dSAndroid Build Coastguard Worker 			continue;
339*8617a60dSAndroid Build Coastguard Worker 		}
340*8617a60dSAndroid Build Coastguard Worker 		c->has_data = 1;
341*8617a60dSAndroid Build Coastguard Worker 	}
342*8617a60dSAndroid Build Coastguard Worker 	fputs("\r\n", stderr);  /* Flush the '.' */
343*8617a60dSAndroid Build Coastguard Worker 	VB2_DEBUG("Finished loading from archive: %s.\n", fpath);
344*8617a60dSAndroid Build Coastguard Worker 
345*8617a60dSAndroid Build Coastguard Worker 	archive_read_free(a);
346*8617a60dSAndroid Build Coastguard Worker 	return cache;
347*8617a60dSAndroid Build Coastguard Worker }
348*8617a60dSAndroid Build Coastguard Worker 
349*8617a60dSAndroid Build Coastguard Worker /* Callback for archive_open on an ARCHIVE file. */
archive_libarchive_open(const char * name)350*8617a60dSAndroid Build Coastguard Worker static void *archive_libarchive_open(const char *name)
351*8617a60dSAndroid Build Coastguard Worker {
352*8617a60dSAndroid Build Coastguard Worker 	/*
353*8617a60dSAndroid Build Coastguard Worker 	 * The firmware archives today can usually all load into memory
354*8617a60dSAndroid Build Coastguard Worker 	 * so we are using a NULL filter. Change that to a specific list in
355*8617a60dSAndroid Build Coastguard Worker 	 * future if the /build/$BOARD/firmware archive becomes too large.
356*8617a60dSAndroid Build Coastguard Worker 	 */
357*8617a60dSAndroid Build Coastguard Worker 	return libarchive_read_file_entries(name, NULL);
358*8617a60dSAndroid Build Coastguard Worker }
359*8617a60dSAndroid Build Coastguard Worker 
360*8617a60dSAndroid Build Coastguard Worker /* Callback for archive_close on an ARCHIVE file. */
archive_libarchive_close(void * handle)361*8617a60dSAndroid Build Coastguard Worker static int archive_libarchive_close(void *handle)
362*8617a60dSAndroid Build Coastguard Worker {
363*8617a60dSAndroid Build Coastguard Worker 	archive_cache_free(handle);
364*8617a60dSAndroid Build Coastguard Worker 	return 0;
365*8617a60dSAndroid Build Coastguard Worker }
366*8617a60dSAndroid Build Coastguard Worker 
367*8617a60dSAndroid Build Coastguard Worker /* Callback for archive_has_entry on an ARCHIVE file. */
archive_libarchive_has_entry(void * handle,const char * fname)368*8617a60dSAndroid Build Coastguard Worker static int archive_libarchive_has_entry(void *handle, const char *fname)
369*8617a60dSAndroid Build Coastguard Worker {
370*8617a60dSAndroid Build Coastguard Worker 	return archive_cache_find(handle, fname) != NULL;
371*8617a60dSAndroid Build Coastguard Worker }
372*8617a60dSAndroid Build Coastguard Worker 
373*8617a60dSAndroid Build Coastguard Worker /* Callback for archive_walk on an ARCHIVE file. */
archive_libarchive_walk(void * handle,void * arg,int (* callback)(const char * name,void * arg))374*8617a60dSAndroid Build Coastguard Worker static int archive_libarchive_walk(
375*8617a60dSAndroid Build Coastguard Worker 		void *handle, void *arg,
376*8617a60dSAndroid Build Coastguard Worker 		int (*callback)(const char *name, void *arg))
377*8617a60dSAndroid Build Coastguard Worker {
378*8617a60dSAndroid Build Coastguard Worker 	return archive_cache_walk(handle, arg, callback);
379*8617a60dSAndroid Build Coastguard Worker }
380*8617a60dSAndroid Build Coastguard Worker 
381*8617a60dSAndroid Build Coastguard Worker /* Callback for archive_read_file on an ARCHIVE file. */
archive_libarchive_read_file(void * handle,const char * fname,uint8_t ** data,uint32_t * size,int64_t * mtime)382*8617a60dSAndroid Build Coastguard Worker static int archive_libarchive_read_file(
383*8617a60dSAndroid Build Coastguard Worker 		void *handle, const char *fname, uint8_t **data,
384*8617a60dSAndroid Build Coastguard Worker 		uint32_t *size, int64_t *mtime)
385*8617a60dSAndroid Build Coastguard Worker {
386*8617a60dSAndroid Build Coastguard Worker 	struct archive_cache *c = archive_cache_find(handle, fname);
387*8617a60dSAndroid Build Coastguard Worker 
388*8617a60dSAndroid Build Coastguard Worker 	if (!c)
389*8617a60dSAndroid Build Coastguard Worker 		return 1;
390*8617a60dSAndroid Build Coastguard Worker 
391*8617a60dSAndroid Build Coastguard Worker 	if (!c->has_data) {
392*8617a60dSAndroid Build Coastguard Worker 		/* TODO(hungte) Re-read. */
393*8617a60dSAndroid Build Coastguard Worker 		ERROR("Not in the cache: %s\n", fname);
394*8617a60dSAndroid Build Coastguard Worker 		return 1;
395*8617a60dSAndroid Build Coastguard Worker 	}
396*8617a60dSAndroid Build Coastguard Worker 
397*8617a60dSAndroid Build Coastguard Worker 	if (mtime)
398*8617a60dSAndroid Build Coastguard Worker 		*mtime = c->mtime;
399*8617a60dSAndroid Build Coastguard Worker 	if (size)
400*8617a60dSAndroid Build Coastguard Worker 		*size = c->size;
401*8617a60dSAndroid Build Coastguard Worker 	*data = (uint8_t *)malloc(c->size + 1);
402*8617a60dSAndroid Build Coastguard Worker 	if (!*data) {
403*8617a60dSAndroid Build Coastguard Worker 		ERROR("Out of memory when reading: %s\n", c->name);
404*8617a60dSAndroid Build Coastguard Worker 		return 1;
405*8617a60dSAndroid Build Coastguard Worker 	}
406*8617a60dSAndroid Build Coastguard Worker 	memcpy(*data, c->data, c->size);
407*8617a60dSAndroid Build Coastguard Worker 	(*data)[c->size] = '\0';
408*8617a60dSAndroid Build Coastguard Worker 	return 0;
409*8617a60dSAndroid Build Coastguard Worker }
410*8617a60dSAndroid Build Coastguard Worker 
411*8617a60dSAndroid Build Coastguard Worker /* Callback for archive_write_file on an ARCHIVE file. */
archive_libarchive_write_file(void * handle,const char * fname,uint8_t * data,uint32_t size,int64_t mtime)412*8617a60dSAndroid Build Coastguard Worker static int archive_libarchive_write_file(
413*8617a60dSAndroid Build Coastguard Worker 		void *handle, const char *fname, uint8_t *data, uint32_t size,
414*8617a60dSAndroid Build Coastguard Worker 		int64_t mtime)
415*8617a60dSAndroid Build Coastguard Worker {
416*8617a60dSAndroid Build Coastguard Worker 	ERROR("Not implemented!\n");
417*8617a60dSAndroid Build Coastguard Worker 	return 1;
418*8617a60dSAndroid Build Coastguard Worker }
419*8617a60dSAndroid Build Coastguard Worker #endif
420*8617a60dSAndroid Build Coastguard Worker 
421*8617a60dSAndroid Build Coastguard Worker /*
422*8617a60dSAndroid Build Coastguard Worker  * -- The libzip driver (for ZIP, the official format for CrOS fw updater). --
423*8617a60dSAndroid Build Coastguard Worker  */
424*8617a60dSAndroid Build Coastguard Worker 
425*8617a60dSAndroid Build Coastguard Worker #ifdef HAVE_LIBZIP
426*8617a60dSAndroid Build Coastguard Worker 
427*8617a60dSAndroid Build Coastguard Worker /* Callback for archive_open on a ZIP file. */
archive_zip_open(const char * name)428*8617a60dSAndroid Build Coastguard Worker static void *archive_zip_open(const char *name)
429*8617a60dSAndroid Build Coastguard Worker {
430*8617a60dSAndroid Build Coastguard Worker 	return zip_open(name, 0, NULL);
431*8617a60dSAndroid Build Coastguard Worker }
432*8617a60dSAndroid Build Coastguard Worker 
433*8617a60dSAndroid Build Coastguard Worker /* Callback for archive_close on a ZIP file. */
archive_zip_close(void * handle)434*8617a60dSAndroid Build Coastguard Worker static int archive_zip_close(void *handle)
435*8617a60dSAndroid Build Coastguard Worker {
436*8617a60dSAndroid Build Coastguard Worker 	struct zip *zip = (struct zip *)handle;
437*8617a60dSAndroid Build Coastguard Worker 
438*8617a60dSAndroid Build Coastguard Worker 	if (zip)
439*8617a60dSAndroid Build Coastguard Worker 		return zip_close(zip);
440*8617a60dSAndroid Build Coastguard Worker 	return 0;
441*8617a60dSAndroid Build Coastguard Worker }
442*8617a60dSAndroid Build Coastguard Worker 
443*8617a60dSAndroid Build Coastguard Worker /* Callback for archive_has_entry on a ZIP file. */
archive_zip_has_entry(void * handle,const char * fname)444*8617a60dSAndroid Build Coastguard Worker static int archive_zip_has_entry(void *handle, const char *fname)
445*8617a60dSAndroid Build Coastguard Worker {
446*8617a60dSAndroid Build Coastguard Worker 	struct zip *zip = (struct zip *)handle;
447*8617a60dSAndroid Build Coastguard Worker 	assert(zip);
448*8617a60dSAndroid Build Coastguard Worker 	return zip_name_locate(zip, fname, 0) != -1;
449*8617a60dSAndroid Build Coastguard Worker }
450*8617a60dSAndroid Build Coastguard Worker 
451*8617a60dSAndroid Build Coastguard Worker /* Callback for archive_walk on a ZIP file. */
archive_zip_walk(void * handle,void * arg,int (* callback)(const char * name,void * arg))452*8617a60dSAndroid Build Coastguard Worker static int archive_zip_walk(
453*8617a60dSAndroid Build Coastguard Worker 		void *handle, void *arg,
454*8617a60dSAndroid Build Coastguard Worker 		int (*callback)(const char *name, void *arg))
455*8617a60dSAndroid Build Coastguard Worker {
456*8617a60dSAndroid Build Coastguard Worker 	zip_int64_t num, i;
457*8617a60dSAndroid Build Coastguard Worker 	struct zip *zip = (struct zip *)handle;
458*8617a60dSAndroid Build Coastguard Worker 	assert(zip);
459*8617a60dSAndroid Build Coastguard Worker 
460*8617a60dSAndroid Build Coastguard Worker 	num = zip_get_num_entries(zip, 0);
461*8617a60dSAndroid Build Coastguard Worker 	if (num < 0)
462*8617a60dSAndroid Build Coastguard Worker 		return 1;
463*8617a60dSAndroid Build Coastguard Worker 	for (i = 0; i < num; i++) {
464*8617a60dSAndroid Build Coastguard Worker 		const char *name = zip_get_name(zip, i, 0);
465*8617a60dSAndroid Build Coastguard Worker 		if (*name && name[strlen(name) - 1] == '/')
466*8617a60dSAndroid Build Coastguard Worker 			continue;
467*8617a60dSAndroid Build Coastguard Worker 		if (callback(name, arg))
468*8617a60dSAndroid Build Coastguard Worker 			break;
469*8617a60dSAndroid Build Coastguard Worker 	}
470*8617a60dSAndroid Build Coastguard Worker 	return 0;
471*8617a60dSAndroid Build Coastguard Worker }
472*8617a60dSAndroid Build Coastguard Worker 
473*8617a60dSAndroid Build Coastguard Worker /* Callback for archive_zip_read_file on a ZIP file. */
archive_zip_read_file(void * handle,const char * fname,uint8_t ** data,uint32_t * size,int64_t * mtime)474*8617a60dSAndroid Build Coastguard Worker static int archive_zip_read_file(void *handle, const char *fname,
475*8617a60dSAndroid Build Coastguard Worker 			     uint8_t **data, uint32_t *size, int64_t *mtime)
476*8617a60dSAndroid Build Coastguard Worker {
477*8617a60dSAndroid Build Coastguard Worker 	struct zip *zip = (struct zip *)handle;
478*8617a60dSAndroid Build Coastguard Worker 	struct zip_file *fp;
479*8617a60dSAndroid Build Coastguard Worker 	struct zip_stat stat;
480*8617a60dSAndroid Build Coastguard Worker 
481*8617a60dSAndroid Build Coastguard Worker 	assert(zip);
482*8617a60dSAndroid Build Coastguard Worker 	*data = NULL;
483*8617a60dSAndroid Build Coastguard Worker 	*size = 0;
484*8617a60dSAndroid Build Coastguard Worker 	zip_stat_init(&stat);
485*8617a60dSAndroid Build Coastguard Worker 	if (zip_stat(zip, fname, 0, &stat)) {
486*8617a60dSAndroid Build Coastguard Worker 		ERROR("Fail to stat entry in ZIP: %s\n", fname);
487*8617a60dSAndroid Build Coastguard Worker 		return 1;
488*8617a60dSAndroid Build Coastguard Worker 	}
489*8617a60dSAndroid Build Coastguard Worker 	fp = zip_fopen(zip, fname, 0);
490*8617a60dSAndroid Build Coastguard Worker 	if (!fp) {
491*8617a60dSAndroid Build Coastguard Worker 		ERROR("Failed to open entry in ZIP: %s\n", fname);
492*8617a60dSAndroid Build Coastguard Worker 		return 1;
493*8617a60dSAndroid Build Coastguard Worker 	}
494*8617a60dSAndroid Build Coastguard Worker 	*data = (uint8_t *)malloc(stat.size + 1);
495*8617a60dSAndroid Build Coastguard Worker 	if (*data) {
496*8617a60dSAndroid Build Coastguard Worker 		if (zip_fread(fp, *data, stat.size) == stat.size) {
497*8617a60dSAndroid Build Coastguard Worker 			if (mtime)
498*8617a60dSAndroid Build Coastguard Worker 				*mtime = stat.mtime;
499*8617a60dSAndroid Build Coastguard Worker 			*size = stat.size;
500*8617a60dSAndroid Build Coastguard Worker 			(*data)[stat.size] = '\0';
501*8617a60dSAndroid Build Coastguard Worker 		} else {
502*8617a60dSAndroid Build Coastguard Worker 			ERROR("Failed to read entry in zip: %s\n", fname);
503*8617a60dSAndroid Build Coastguard Worker 			free(*data);
504*8617a60dSAndroid Build Coastguard Worker 			*data = NULL;
505*8617a60dSAndroid Build Coastguard Worker 		}
506*8617a60dSAndroid Build Coastguard Worker 	}
507*8617a60dSAndroid Build Coastguard Worker 	zip_fclose(fp);
508*8617a60dSAndroid Build Coastguard Worker 	return *data == NULL;
509*8617a60dSAndroid Build Coastguard Worker }
510*8617a60dSAndroid Build Coastguard Worker 
511*8617a60dSAndroid Build Coastguard Worker /* Callback for archive_zip_write_file on a ZIP file. */
archive_zip_write_file(void * handle,const char * fname,uint8_t * data,uint32_t size,int64_t mtime)512*8617a60dSAndroid Build Coastguard Worker static int archive_zip_write_file(void *handle, const char *fname,
513*8617a60dSAndroid Build Coastguard Worker 				  uint8_t *data, uint32_t size, int64_t mtime)
514*8617a60dSAndroid Build Coastguard Worker {
515*8617a60dSAndroid Build Coastguard Worker 	struct zip *zip = (struct zip *)handle;
516*8617a60dSAndroid Build Coastguard Worker 	struct zip_source *src;
517*8617a60dSAndroid Build Coastguard Worker 
518*8617a60dSAndroid Build Coastguard Worker 	VB2_DEBUG("Writing %s\n", fname);
519*8617a60dSAndroid Build Coastguard Worker 	assert(zip);
520*8617a60dSAndroid Build Coastguard Worker 	src = zip_source_buffer(zip, data, size, 0);
521*8617a60dSAndroid Build Coastguard Worker 	if (!src) {
522*8617a60dSAndroid Build Coastguard Worker 		ERROR("Internal error: cannot allocate buffer: %s\n", fname);
523*8617a60dSAndroid Build Coastguard Worker 		return 1;
524*8617a60dSAndroid Build Coastguard Worker 	}
525*8617a60dSAndroid Build Coastguard Worker 
526*8617a60dSAndroid Build Coastguard Worker 	if (zip_file_add(zip, fname, src, ZIP_FL_OVERWRITE) < 0) {
527*8617a60dSAndroid Build Coastguard Worker 		zip_source_free(src);
528*8617a60dSAndroid Build Coastguard Worker 		ERROR("Internal error: failed to add: %s\n", fname);
529*8617a60dSAndroid Build Coastguard Worker 		return 1;
530*8617a60dSAndroid Build Coastguard Worker 	}
531*8617a60dSAndroid Build Coastguard Worker 	/* zip_source_free is not needed if zip_file_add success. */
532*8617a60dSAndroid Build Coastguard Worker #if LIBZIP_VERSION_MAJOR >= 1
533*8617a60dSAndroid Build Coastguard Worker 	zip_file_set_mtime(zip, zip_name_locate(zip, fname, 0), mtime, 0);
534*8617a60dSAndroid Build Coastguard Worker #endif
535*8617a60dSAndroid Build Coastguard Worker 	return 0;
536*8617a60dSAndroid Build Coastguard Worker }
537*8617a60dSAndroid Build Coastguard Worker #endif
538*8617a60dSAndroid Build Coastguard Worker 
539*8617a60dSAndroid Build Coastguard Worker /*
540*8617a60dSAndroid Build Coastguard Worker  * -- The public functions for using u_archive. --
541*8617a60dSAndroid Build Coastguard Worker  */
542*8617a60dSAndroid Build Coastguard Worker 
archive_open(const char * path)543*8617a60dSAndroid Build Coastguard Worker struct u_archive *archive_open(const char *path)
544*8617a60dSAndroid Build Coastguard Worker {
545*8617a60dSAndroid Build Coastguard Worker 	struct stat path_stat;
546*8617a60dSAndroid Build Coastguard Worker 	struct u_archive *ar;
547*8617a60dSAndroid Build Coastguard Worker 
548*8617a60dSAndroid Build Coastguard Worker 	if (stat(path, &path_stat) != 0) {
549*8617a60dSAndroid Build Coastguard Worker 		ERROR("Cannot identify type of path: %s\n", path);
550*8617a60dSAndroid Build Coastguard Worker 		return NULL;
551*8617a60dSAndroid Build Coastguard Worker 	}
552*8617a60dSAndroid Build Coastguard Worker 
553*8617a60dSAndroid Build Coastguard Worker 	ar = (struct u_archive *)calloc(sizeof(*ar), 1);
554*8617a60dSAndroid Build Coastguard Worker 	if (!ar) {
555*8617a60dSAndroid Build Coastguard Worker 		ERROR("Internal error: allocation failure.\n");
556*8617a60dSAndroid Build Coastguard Worker 		return NULL;
557*8617a60dSAndroid Build Coastguard Worker 	}
558*8617a60dSAndroid Build Coastguard Worker 
559*8617a60dSAndroid Build Coastguard Worker 	if (S_ISDIR(path_stat.st_mode)) {
560*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Found directory, use fallback (fs) driver: %s\n",
561*8617a60dSAndroid Build Coastguard Worker 			  path);
562*8617a60dSAndroid Build Coastguard Worker 		/* Regular file system. */
563*8617a60dSAndroid Build Coastguard Worker 		ar->open = archive_fallback_open;
564*8617a60dSAndroid Build Coastguard Worker 		ar->close = archive_fallback_close;
565*8617a60dSAndroid Build Coastguard Worker 		ar->walk = archive_fallback_walk;
566*8617a60dSAndroid Build Coastguard Worker 		ar->has_entry = archive_fallback_has_entry;
567*8617a60dSAndroid Build Coastguard Worker 		ar->read_file = archive_fallback_read_file;
568*8617a60dSAndroid Build Coastguard Worker 		ar->write_file = archive_fallback_write_file;
569*8617a60dSAndroid Build Coastguard Worker 	}
570*8617a60dSAndroid Build Coastguard Worker 
571*8617a60dSAndroid Build Coastguard Worker 	/* Format detection must try ZIP (the official format) first. */
572*8617a60dSAndroid Build Coastguard Worker #ifdef HAVE_LIBZIP
573*8617a60dSAndroid Build Coastguard Worker 	if (!ar->open) {
574*8617a60dSAndroid Build Coastguard Worker 		ar->handle = archive_zip_open(path);
575*8617a60dSAndroid Build Coastguard Worker 
576*8617a60dSAndroid Build Coastguard Worker 		if (ar->handle) {
577*8617a60dSAndroid Build Coastguard Worker 			VB2_DEBUG("Found a ZIP file: %s\n", path);
578*8617a60dSAndroid Build Coastguard Worker 			ar->open = archive_zip_open;
579*8617a60dSAndroid Build Coastguard Worker 			ar->close = archive_zip_close;
580*8617a60dSAndroid Build Coastguard Worker 			ar->walk = archive_zip_walk;
581*8617a60dSAndroid Build Coastguard Worker 			ar->has_entry = archive_zip_has_entry;
582*8617a60dSAndroid Build Coastguard Worker 			ar->read_file = archive_zip_read_file;
583*8617a60dSAndroid Build Coastguard Worker 			ar->write_file = archive_zip_write_file;
584*8617a60dSAndroid Build Coastguard Worker 		}
585*8617a60dSAndroid Build Coastguard Worker 	}
586*8617a60dSAndroid Build Coastguard Worker #endif
587*8617a60dSAndroid Build Coastguard Worker 
588*8617a60dSAndroid Build Coastguard Worker 	/* LIBARCHIVE must be the last driver. */
589*8617a60dSAndroid Build Coastguard Worker #ifdef HAVE_LIBARCHIVE
590*8617a60dSAndroid Build Coastguard Worker 	if (!ar->open) {
591*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Found a file, use libarchive: %s\n", path);
592*8617a60dSAndroid Build Coastguard Worker 		ar->open = archive_libarchive_open;
593*8617a60dSAndroid Build Coastguard Worker 		ar->close = archive_libarchive_close;
594*8617a60dSAndroid Build Coastguard Worker 		ar->walk = archive_libarchive_walk;
595*8617a60dSAndroid Build Coastguard Worker 		ar->has_entry = archive_libarchive_has_entry;
596*8617a60dSAndroid Build Coastguard Worker 		ar->read_file = archive_libarchive_read_file;
597*8617a60dSAndroid Build Coastguard Worker 		ar->write_file = archive_libarchive_write_file;
598*8617a60dSAndroid Build Coastguard Worker 	}
599*8617a60dSAndroid Build Coastguard Worker #endif
600*8617a60dSAndroid Build Coastguard Worker 
601*8617a60dSAndroid Build Coastguard Worker 	if (!ar->open) {
602*8617a60dSAndroid Build Coastguard Worker 		ERROR("Found a file, but no drivers were selected: %s\n", path);
603*8617a60dSAndroid Build Coastguard Worker 		free(ar);
604*8617a60dSAndroid Build Coastguard Worker 		return NULL;
605*8617a60dSAndroid Build Coastguard Worker 	}
606*8617a60dSAndroid Build Coastguard Worker 
607*8617a60dSAndroid Build Coastguard Worker 	/* Some drivers may have already opened the archive. */
608*8617a60dSAndroid Build Coastguard Worker 	if (!ar->handle)
609*8617a60dSAndroid Build Coastguard Worker 		ar->handle = ar->open(path);
610*8617a60dSAndroid Build Coastguard Worker 
611*8617a60dSAndroid Build Coastguard Worker 	if (!ar->handle) {
612*8617a60dSAndroid Build Coastguard Worker 		ERROR("Failed to open archive: %s\n", path);
613*8617a60dSAndroid Build Coastguard Worker 		free(ar);
614*8617a60dSAndroid Build Coastguard Worker 		return NULL;
615*8617a60dSAndroid Build Coastguard Worker 	}
616*8617a60dSAndroid Build Coastguard Worker 	return ar;
617*8617a60dSAndroid Build Coastguard Worker }
618*8617a60dSAndroid Build Coastguard Worker 
archive_close(struct u_archive * ar)619*8617a60dSAndroid Build Coastguard Worker int archive_close(struct u_archive *ar)
620*8617a60dSAndroid Build Coastguard Worker {
621*8617a60dSAndroid Build Coastguard Worker 	int r = ar->close(ar->handle);
622*8617a60dSAndroid Build Coastguard Worker 	free(ar);
623*8617a60dSAndroid Build Coastguard Worker 	return r;
624*8617a60dSAndroid Build Coastguard Worker }
625*8617a60dSAndroid Build Coastguard Worker 
archive_has_entry(struct u_archive * ar,const char * name)626*8617a60dSAndroid Build Coastguard Worker int archive_has_entry(struct u_archive *ar, const char *name)
627*8617a60dSAndroid Build Coastguard Worker {
628*8617a60dSAndroid Build Coastguard Worker 	if (!ar || *name == '/')
629*8617a60dSAndroid Build Coastguard Worker 		return archive_fallback_has_entry(NULL, name);
630*8617a60dSAndroid Build Coastguard Worker 	return ar->has_entry(ar->handle, name);
631*8617a60dSAndroid Build Coastguard Worker }
632*8617a60dSAndroid Build Coastguard Worker 
archive_walk(struct u_archive * ar,void * arg,int (* callback)(const char * path,void * arg))633*8617a60dSAndroid Build Coastguard Worker int archive_walk(struct u_archive *ar, void *arg,
634*8617a60dSAndroid Build Coastguard Worker 		 int (*callback)(const char *path, void *arg))
635*8617a60dSAndroid Build Coastguard Worker {
636*8617a60dSAndroid Build Coastguard Worker 	if (!ar)
637*8617a60dSAndroid Build Coastguard Worker 		return archive_fallback_walk(NULL, arg, callback);
638*8617a60dSAndroid Build Coastguard Worker 	return ar->walk(ar->handle, arg, callback);
639*8617a60dSAndroid Build Coastguard Worker }
640*8617a60dSAndroid Build Coastguard Worker 
archive_read_file(struct u_archive * ar,const char * fname,uint8_t ** data,uint32_t * size,int64_t * mtime)641*8617a60dSAndroid Build Coastguard Worker int archive_read_file(struct u_archive *ar, const char *fname,
642*8617a60dSAndroid Build Coastguard Worker 		      uint8_t **data, uint32_t *size, int64_t *mtime)
643*8617a60dSAndroid Build Coastguard Worker {
644*8617a60dSAndroid Build Coastguard Worker 	if (!ar || *fname == '/')
645*8617a60dSAndroid Build Coastguard Worker 		return archive_fallback_read_file(NULL, fname, data, size, mtime);
646*8617a60dSAndroid Build Coastguard Worker 	return ar->read_file(ar->handle, fname, data, size, mtime);
647*8617a60dSAndroid Build Coastguard Worker }
648*8617a60dSAndroid Build Coastguard Worker 
archive_write_file(struct u_archive * ar,const char * fname,uint8_t * data,uint32_t size,int64_t mtime)649*8617a60dSAndroid Build Coastguard Worker int archive_write_file(struct u_archive *ar, const char *fname,
650*8617a60dSAndroid Build Coastguard Worker 		       uint8_t *data, uint32_t size, int64_t mtime)
651*8617a60dSAndroid Build Coastguard Worker {
652*8617a60dSAndroid Build Coastguard Worker 	if (!ar || *fname == '/')
653*8617a60dSAndroid Build Coastguard Worker 		return archive_fallback_write_file(NULL, fname, data, size, mtime);
654*8617a60dSAndroid Build Coastguard Worker 	return ar->write_file(ar->handle, fname, data, size, mtime);
655*8617a60dSAndroid Build Coastguard Worker }
656*8617a60dSAndroid Build Coastguard Worker 
657*8617a60dSAndroid Build Coastguard Worker struct _copy_arg {
658*8617a60dSAndroid Build Coastguard Worker 	struct u_archive *from, *to;
659*8617a60dSAndroid Build Coastguard Worker };
660*8617a60dSAndroid Build Coastguard Worker 
661*8617a60dSAndroid Build Coastguard Worker /* Callback for archive_copy. */
archive_copy_callback(const char * path,void * _arg)662*8617a60dSAndroid Build Coastguard Worker static int archive_copy_callback(const char *path, void *_arg)
663*8617a60dSAndroid Build Coastguard Worker {
664*8617a60dSAndroid Build Coastguard Worker 	const struct _copy_arg *arg = (const struct _copy_arg*)_arg;
665*8617a60dSAndroid Build Coastguard Worker 	uint32_t size;
666*8617a60dSAndroid Build Coastguard Worker 	uint8_t *data;
667*8617a60dSAndroid Build Coastguard Worker 	int64_t mtime;
668*8617a60dSAndroid Build Coastguard Worker 	int r;
669*8617a60dSAndroid Build Coastguard Worker 
670*8617a60dSAndroid Build Coastguard Worker 	INFO("Copying: %s\n", path);
671*8617a60dSAndroid Build Coastguard Worker 	if (archive_read_file(arg->from, path, &data, &size, &mtime)) {
672*8617a60dSAndroid Build Coastguard Worker 		ERROR("Failed reading: %s\n", path);
673*8617a60dSAndroid Build Coastguard Worker 		return 1;
674*8617a60dSAndroid Build Coastguard Worker 	}
675*8617a60dSAndroid Build Coastguard Worker 	r = archive_write_file(arg->to, path, data, size, mtime);
676*8617a60dSAndroid Build Coastguard Worker 	VB2_DEBUG("result=%d\n", r);
677*8617a60dSAndroid Build Coastguard Worker 	free(data);
678*8617a60dSAndroid Build Coastguard Worker 	return r;
679*8617a60dSAndroid Build Coastguard Worker }
680*8617a60dSAndroid Build Coastguard Worker 
archive_copy(struct u_archive * from,struct u_archive * to)681*8617a60dSAndroid Build Coastguard Worker int archive_copy(struct u_archive *from, struct u_archive *to)
682*8617a60dSAndroid Build Coastguard Worker {
683*8617a60dSAndroid Build Coastguard Worker 	struct _copy_arg arg = { .from = from, .to = to };
684*8617a60dSAndroid Build Coastguard Worker 	return archive_walk(from, &arg, archive_copy_callback);
685*8617a60dSAndroid Build Coastguard Worker }
686