1228753Smm/*-
2228753Smm * Copyright (c) 2003-2007 Tim Kientzle
3228753Smm * All rights reserved.
4228753Smm *
5228753Smm * Redistribution and use in source and binary forms, with or without
6228753Smm * modification, are permitted provided that the following conditions
7228753Smm * are met:
8228753Smm * 1. Redistributions of source code must retain the above copyright
9228753Smm *    notice, this list of conditions and the following disclaimer.
10228753Smm * 2. Redistributions in binary form must reproduce the above copyright
11228753Smm *    notice, this list of conditions and the following disclaimer in the
12228753Smm *    documentation and/or other materials provided with the distribution.
13228753Smm *
14228753Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15228753Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16228753Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17228753Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18228753Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19228753Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20228753Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21228753Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22228753Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23228753Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24228753Smm */
25228753Smm
26228753Smm#include "archive_platform.h"
27229592Smm__FBSDID("$FreeBSD$");
28228753Smm
29228753Smm#ifdef HAVE_ERRNO_H
30228753Smm#include <errno.h>
31228753Smm#endif
32228753Smm/* #include <stdint.h> */ /* See archive_platform.h */
33228753Smm#ifdef HAVE_STDLIB_H
34228753Smm#include <stdlib.h>
35228753Smm#endif
36228753Smm#ifdef HAVE_STRING_H
37228753Smm#include <string.h>
38228753Smm#endif
39228753Smm
40228753Smm#include "archive.h"
41228753Smm#include "archive_entry.h"
42228753Smm#include "archive_private.h"
43228753Smm#include "archive_read_private.h"
44228753Smm
45229592Smm#ifdef _MSC_VER
46229592Smm#define __packed
47229592Smm#pragma pack(push, 1)
48229592Smm#endif
49228753Smmstruct cpio_bin_header {
50228753Smm	unsigned char	c_magic[2];
51228753Smm	unsigned char	c_dev[2];
52228753Smm	unsigned char	c_ino[2];
53228753Smm	unsigned char	c_mode[2];
54228753Smm	unsigned char	c_uid[2];
55228753Smm	unsigned char	c_gid[2];
56228753Smm	unsigned char	c_nlink[2];
57228753Smm	unsigned char	c_rdev[2];
58228753Smm	unsigned char	c_mtime[4];
59228753Smm	unsigned char	c_namesize[2];
60228753Smm	unsigned char	c_filesize[4];
61229592Smm} __packed;
62228753Smm
63228753Smmstruct cpio_odc_header {
64228753Smm	char	c_magic[6];
65228753Smm	char	c_dev[6];
66228753Smm	char	c_ino[6];
67228753Smm	char	c_mode[6];
68228753Smm	char	c_uid[6];
69228753Smm	char	c_gid[6];
70228753Smm	char	c_nlink[6];
71228753Smm	char	c_rdev[6];
72228753Smm	char	c_mtime[11];
73228753Smm	char	c_namesize[6];
74228753Smm	char	c_filesize[11];
75229592Smm} __packed;
76228753Smm
77228753Smmstruct cpio_newc_header {
78228753Smm	char	c_magic[6];
79228753Smm	char	c_ino[8];
80228753Smm	char	c_mode[8];
81228753Smm	char	c_uid[8];
82228753Smm	char	c_gid[8];
83228753Smm	char	c_nlink[8];
84228753Smm	char	c_mtime[8];
85228753Smm	char	c_filesize[8];
86228753Smm	char	c_devmajor[8];
87228753Smm	char	c_devminor[8];
88228753Smm	char	c_rdevmajor[8];
89228753Smm	char	c_rdevminor[8];
90228753Smm	char	c_namesize[8];
91228753Smm	char	c_crc[8];
92229592Smm} __packed;
93228753Smm
94229592Smm#ifdef _MSC_VER
95229592Smm#undef __packed
96229592Smm#pragma pack(pop)
97229592Smm#endif
98229592Smm
99228753Smmstruct links_entry {
100228753Smm        struct links_entry      *next;
101228753Smm        struct links_entry      *previous;
102228753Smm        int                      links;
103228753Smm        dev_t                    dev;
104228753Smm        int64_t                  ino;
105228753Smm        char                    *name;
106228753Smm};
107228753Smm
108228753Smm#define	CPIO_MAGIC   0x13141516
109228753Smmstruct cpio {
110228753Smm	int			  magic;
111228753Smm	int			(*read_header)(struct archive_read *, struct cpio *,
112228753Smm				     struct archive_entry *, size_t *, size_t *);
113228753Smm	struct links_entry	 *links_head;
114228753Smm	struct archive_string	  entry_name;
115228753Smm	struct archive_string	  entry_linkname;
116228753Smm	off_t			  entry_bytes_remaining;
117228753Smm	off_t			  entry_offset;
118228753Smm	off_t			  entry_padding;
119228753Smm};
120228753Smm
121228753Smmstatic int64_t	atol16(const char *, unsigned);
122228753Smmstatic int64_t	atol8(const char *, unsigned);
123228753Smmstatic int	archive_read_format_cpio_bid(struct archive_read *);
124228753Smmstatic int	archive_read_format_cpio_cleanup(struct archive_read *);
125228753Smmstatic int	archive_read_format_cpio_read_data(struct archive_read *,
126228753Smm		    const void **, size_t *, off_t *);
127228753Smmstatic int	archive_read_format_cpio_read_header(struct archive_read *,
128228753Smm		    struct archive_entry *);
129228753Smmstatic int	be4(const unsigned char *);
130228753Smmstatic int	find_odc_header(struct archive_read *);
131228753Smmstatic int	find_newc_header(struct archive_read *);
132228753Smmstatic int	header_bin_be(struct archive_read *, struct cpio *,
133228753Smm		    struct archive_entry *, size_t *, size_t *);
134228753Smmstatic int	header_bin_le(struct archive_read *, struct cpio *,
135228753Smm		    struct archive_entry *, size_t *, size_t *);
136228753Smmstatic int	header_newc(struct archive_read *, struct cpio *,
137228753Smm		    struct archive_entry *, size_t *, size_t *);
138228753Smmstatic int	header_odc(struct archive_read *, struct cpio *,
139228753Smm		    struct archive_entry *, size_t *, size_t *);
140228753Smmstatic int	is_octal(const char *, size_t);
141228753Smmstatic int	is_hex(const char *, size_t);
142228753Smmstatic int	le4(const unsigned char *);
143228753Smmstatic void	record_hardlink(struct cpio *cpio, struct archive_entry *entry);
144228753Smm
145228753Smmint
146228753Smmarchive_read_support_format_cpio(struct archive *_a)
147228753Smm{
148228753Smm	struct archive_read *a = (struct archive_read *)_a;
149228753Smm	struct cpio *cpio;
150228753Smm	int r;
151228753Smm
152228753Smm	cpio = (struct cpio *)malloc(sizeof(*cpio));
153228753Smm	if (cpio == NULL) {
154228753Smm		archive_set_error(&a->archive, ENOMEM, "Can't allocate cpio data");
155228753Smm		return (ARCHIVE_FATAL);
156228753Smm	}
157228753Smm	memset(cpio, 0, sizeof(*cpio));
158228753Smm	cpio->magic = CPIO_MAGIC;
159228753Smm
160228753Smm	r = __archive_read_register_format(a,
161228753Smm	    cpio,
162228753Smm	    "cpio",
163228753Smm	    archive_read_format_cpio_bid,
164228753Smm	    NULL,
165228753Smm	    archive_read_format_cpio_read_header,
166228753Smm	    archive_read_format_cpio_read_data,
167228753Smm	    NULL,
168228753Smm	    archive_read_format_cpio_cleanup);
169228753Smm
170228753Smm	if (r != ARCHIVE_OK)
171228753Smm		free(cpio);
172228753Smm	return (ARCHIVE_OK);
173228753Smm}
174228753Smm
175228753Smm
176228753Smmstatic int
177228753Smmarchive_read_format_cpio_bid(struct archive_read *a)
178228753Smm{
179228753Smm	const void *h;
180228753Smm	const unsigned char *p;
181228753Smm	struct cpio *cpio;
182228753Smm	int bid;
183228753Smm
184228753Smm	cpio = (struct cpio *)(a->format->data);
185228753Smm
186228753Smm	if ((h = __archive_read_ahead(a, 6, NULL)) == NULL)
187228753Smm		return (-1);
188228753Smm
189228753Smm	p = (const unsigned char *)h;
190228753Smm	bid = 0;
191228753Smm	if (memcmp(p, "070707", 6) == 0) {
192228753Smm		/* ASCII cpio archive (odc, POSIX.1) */
193228753Smm		cpio->read_header = header_odc;
194228753Smm		bid += 48;
195228753Smm		/*
196228753Smm		 * XXX TODO:  More verification; Could check that only octal
197228753Smm		 * digits appear in appropriate header locations. XXX
198228753Smm		 */
199228753Smm	} else if (memcmp(p, "070701", 6) == 0) {
200228753Smm		/* ASCII cpio archive (SVR4 without CRC) */
201228753Smm		cpio->read_header = header_newc;
202228753Smm		bid += 48;
203228753Smm		/*
204228753Smm		 * XXX TODO:  More verification; Could check that only hex
205228753Smm		 * digits appear in appropriate header locations. XXX
206228753Smm		 */
207228753Smm	} else if (memcmp(p, "070702", 6) == 0) {
208228753Smm		/* ASCII cpio archive (SVR4 with CRC) */
209228753Smm		/* XXX TODO: Flag that we should check the CRC. XXX */
210228753Smm		cpio->read_header = header_newc;
211228753Smm		bid += 48;
212228753Smm		/*
213228753Smm		 * XXX TODO:  More verification; Could check that only hex
214228753Smm		 * digits appear in appropriate header locations. XXX
215228753Smm		 */
216228753Smm	} else if (p[0] * 256 + p[1] == 070707) {
217228753Smm		/* big-endian binary cpio archives */
218228753Smm		cpio->read_header = header_bin_be;
219228753Smm		bid += 16;
220228753Smm		/* Is more verification possible here? */
221228753Smm	} else if (p[0] + p[1] * 256 == 070707) {
222228753Smm		/* little-endian binary cpio archives */
223228753Smm		cpio->read_header = header_bin_le;
224228753Smm		bid += 16;
225228753Smm		/* Is more verification possible here? */
226228753Smm	} else
227228753Smm		return (ARCHIVE_WARN);
228228753Smm
229228753Smm	return (bid);
230228753Smm}
231228753Smm
232228753Smmstatic int
233228753Smmarchive_read_format_cpio_read_header(struct archive_read *a,
234228753Smm    struct archive_entry *entry)
235228753Smm{
236228753Smm	struct cpio *cpio;
237228753Smm	const void *h;
238228753Smm	size_t namelength;
239228753Smm	size_t name_pad;
240228753Smm	int r;
241228753Smm
242228753Smm	cpio = (struct cpio *)(a->format->data);
243228753Smm	r = (cpio->read_header(a, cpio, entry, &namelength, &name_pad));
244228753Smm
245228753Smm	if (r < ARCHIVE_WARN)
246228753Smm		return (r);
247228753Smm
248228753Smm	/* Read name from buffer. */
249228753Smm	h = __archive_read_ahead(a, namelength + name_pad, NULL);
250228753Smm	if (h == NULL)
251228753Smm	    return (ARCHIVE_FATAL);
252228753Smm	__archive_read_consume(a, namelength + name_pad);
253228753Smm	archive_strncpy(&cpio->entry_name, (const char *)h, namelength);
254228753Smm	archive_entry_set_pathname(entry, cpio->entry_name.s);
255228753Smm	cpio->entry_offset = 0;
256228753Smm
257228753Smm	/* If this is a symlink, read the link contents. */
258228753Smm	if (archive_entry_filetype(entry) == AE_IFLNK) {
259228753Smm		h = __archive_read_ahead(a, cpio->entry_bytes_remaining, NULL);
260228753Smm		if (h == NULL)
261228753Smm			return (ARCHIVE_FATAL);
262228753Smm		__archive_read_consume(a, cpio->entry_bytes_remaining);
263228753Smm		archive_strncpy(&cpio->entry_linkname, (const char *)h,
264228753Smm		    cpio->entry_bytes_remaining);
265228753Smm		archive_entry_set_symlink(entry, cpio->entry_linkname.s);
266228753Smm		cpio->entry_bytes_remaining = 0;
267228753Smm	}
268228753Smm
269228753Smm	/* XXX TODO: If the full mode is 0160200, then this is a Solaris
270228753Smm	 * ACL description for the following entry.  Read this body
271228753Smm	 * and parse it as a Solaris-style ACL, then read the next
272228753Smm	 * header.  XXX */
273228753Smm
274228753Smm	/* Compare name to "TRAILER!!!" to test for end-of-archive. */
275228753Smm	if (namelength == 11 && strcmp((const char *)h, "TRAILER!!!") == 0) {
276228753Smm		/* TODO: Store file location of start of block. */
277228753Smm		archive_clear_error(&a->archive);
278228753Smm		return (ARCHIVE_EOF);
279228753Smm	}
280228753Smm
281228753Smm	/* Detect and record hardlinks to previously-extracted entries. */
282228753Smm	record_hardlink(cpio, entry);
283228753Smm
284228753Smm	return (r);
285228753Smm}
286228753Smm
287228753Smmstatic int
288228753Smmarchive_read_format_cpio_read_data(struct archive_read *a,
289228753Smm    const void **buff, size_t *size, off_t *offset)
290228753Smm{
291228753Smm	ssize_t bytes_read;
292228753Smm	struct cpio *cpio;
293228753Smm
294228753Smm	cpio = (struct cpio *)(a->format->data);
295228753Smm	if (cpio->entry_bytes_remaining > 0) {
296228753Smm		*buff = __archive_read_ahead(a, 1, &bytes_read);
297228753Smm		if (bytes_read <= 0)
298228753Smm			return (ARCHIVE_FATAL);
299228753Smm		if (bytes_read > cpio->entry_bytes_remaining)
300228753Smm			bytes_read = cpio->entry_bytes_remaining;
301228753Smm		*size = bytes_read;
302228753Smm		*offset = cpio->entry_offset;
303228753Smm		cpio->entry_offset += bytes_read;
304228753Smm		cpio->entry_bytes_remaining -= bytes_read;
305228753Smm		__archive_read_consume(a, bytes_read);
306228753Smm		return (ARCHIVE_OK);
307228753Smm	} else {
308228753Smm		while (cpio->entry_padding > 0) {
309228753Smm			*buff = __archive_read_ahead(a, 1, &bytes_read);
310228753Smm			if (bytes_read <= 0)
311228753Smm				return (ARCHIVE_FATAL);
312228753Smm			if (bytes_read > cpio->entry_padding)
313228753Smm				bytes_read = cpio->entry_padding;
314228753Smm			__archive_read_consume(a, bytes_read);
315228753Smm			cpio->entry_padding -= bytes_read;
316228753Smm		}
317228753Smm		*buff = NULL;
318228753Smm		*size = 0;
319228753Smm		*offset = cpio->entry_offset;
320228753Smm		return (ARCHIVE_EOF);
321228753Smm	}
322228753Smm}
323228753Smm
324228753Smm/*
325228753Smm * Skip forward to the next cpio newc header by searching for the
326228753Smm * 07070[12] string.  This should be generalized and merged with
327228753Smm * find_odc_header below.
328228753Smm */
329228753Smmstatic int
330228753Smmis_hex(const char *p, size_t len)
331228753Smm{
332228753Smm	while (len-- > 0) {
333228753Smm		if ((*p >= '0' && *p <= '9')
334228753Smm		    || (*p >= 'a' && *p <= 'f')
335228753Smm		    || (*p >= 'A' && *p <= 'F'))
336228753Smm			++p;
337228753Smm		else
338228753Smm			return (0);
339228753Smm	}
340228753Smm	return (1);
341228753Smm}
342228753Smm
343228753Smmstatic int
344228753Smmfind_newc_header(struct archive_read *a)
345228753Smm{
346228753Smm	const void *h;
347228753Smm	const char *p, *q;
348228753Smm	size_t skip, skipped = 0;
349228753Smm	ssize_t bytes;
350228753Smm
351228753Smm	for (;;) {
352228753Smm		h = __archive_read_ahead(a, sizeof(struct cpio_newc_header), &bytes);
353228753Smm		if (h == NULL)
354228753Smm			return (ARCHIVE_FATAL);
355228753Smm		p = h;
356228753Smm		q = p + bytes;
357228753Smm
358228753Smm		/* Try the typical case first, then go into the slow search.*/
359228753Smm		if (memcmp("07070", p, 5) == 0
360228753Smm		    && (p[5] == '1' || p[5] == '2')
361228753Smm		    && is_hex(p, sizeof(struct cpio_newc_header)))
362228753Smm			return (ARCHIVE_OK);
363228753Smm
364228753Smm		/*
365228753Smm		 * Scan ahead until we find something that looks
366228753Smm		 * like an odc header.
367228753Smm		 */
368228753Smm		while (p + sizeof(struct cpio_newc_header) <= q) {
369228753Smm			switch (p[5]) {
370228753Smm			case '1':
371228753Smm			case '2':
372228753Smm				if (memcmp("07070", p, 5) == 0
373228753Smm					&& is_hex(p, sizeof(struct cpio_newc_header))) {
374228753Smm					skip = p - (const char *)h;
375228753Smm					__archive_read_consume(a, skip);
376228753Smm					skipped += skip;
377228753Smm					if (skipped > 0) {
378228753Smm						archive_set_error(&a->archive,
379228753Smm						    0,
380228753Smm						    "Skipped %d bytes before "
381228753Smm						    "finding valid header",
382228753Smm						    (int)skipped);
383228753Smm						return (ARCHIVE_WARN);
384228753Smm					}
385228753Smm					return (ARCHIVE_OK);
386228753Smm				}
387228753Smm				p += 2;
388228753Smm				break;
389228753Smm			case '0':
390228753Smm				p++;
391228753Smm				break;
392228753Smm			default:
393228753Smm				p += 6;
394228753Smm				break;
395228753Smm			}
396228753Smm		}
397228753Smm		skip = p - (const char *)h;
398228753Smm		__archive_read_consume(a, skip);
399228753Smm		skipped += skip;
400228753Smm	}
401228753Smm}
402228753Smm
403228753Smmstatic int
404228753Smmheader_newc(struct archive_read *a, struct cpio *cpio,
405228753Smm    struct archive_entry *entry, size_t *namelength, size_t *name_pad)
406228753Smm{
407228753Smm	const void *h;
408228753Smm	const struct cpio_newc_header *header;
409228753Smm	int r;
410228753Smm
411228753Smm	r = find_newc_header(a);
412228753Smm	if (r < ARCHIVE_WARN)
413228753Smm		return (r);
414228753Smm
415228753Smm	/* Read fixed-size portion of header. */
416228753Smm	h = __archive_read_ahead(a, sizeof(struct cpio_newc_header), NULL);
417228753Smm	if (h == NULL)
418228753Smm	    return (ARCHIVE_FATAL);
419228753Smm	__archive_read_consume(a, sizeof(struct cpio_newc_header));
420228753Smm
421228753Smm	/* Parse out hex fields. */
422228753Smm	header = (const struct cpio_newc_header *)h;
423228753Smm
424228753Smm	if (memcmp(header->c_magic, "070701", 6) == 0) {
425228753Smm		a->archive.archive_format = ARCHIVE_FORMAT_CPIO_SVR4_NOCRC;
426228753Smm		a->archive.archive_format_name = "ASCII cpio (SVR4 with no CRC)";
427228753Smm	} else if (memcmp(header->c_magic, "070702", 6) == 0) {
428228753Smm		a->archive.archive_format = ARCHIVE_FORMAT_CPIO_SVR4_CRC;
429228753Smm		a->archive.archive_format_name = "ASCII cpio (SVR4 with CRC)";
430228753Smm	} else {
431228753Smm		/* TODO: Abort here? */
432228753Smm	}
433228753Smm
434228753Smm	archive_entry_set_devmajor(entry, atol16(header->c_devmajor, sizeof(header->c_devmajor)));
435228753Smm	archive_entry_set_devminor(entry, atol16(header->c_devminor, sizeof(header->c_devminor)));
436228753Smm	archive_entry_set_ino(entry, atol16(header->c_ino, sizeof(header->c_ino)));
437228753Smm	archive_entry_set_mode(entry, atol16(header->c_mode, sizeof(header->c_mode)));
438228753Smm	archive_entry_set_uid(entry, atol16(header->c_uid, sizeof(header->c_uid)));
439228753Smm	archive_entry_set_gid(entry, atol16(header->c_gid, sizeof(header->c_gid)));
440228753Smm	archive_entry_set_nlink(entry, atol16(header->c_nlink, sizeof(header->c_nlink)));
441228753Smm	archive_entry_set_rdevmajor(entry, atol16(header->c_rdevmajor, sizeof(header->c_rdevmajor)));
442228753Smm	archive_entry_set_rdevminor(entry, atol16(header->c_rdevminor, sizeof(header->c_rdevminor)));
443228753Smm	archive_entry_set_mtime(entry, atol16(header->c_mtime, sizeof(header->c_mtime)), 0);
444228753Smm	*namelength = atol16(header->c_namesize, sizeof(header->c_namesize));
445228753Smm	/* Pad name to 2 more than a multiple of 4. */
446228753Smm	*name_pad = (2 - *namelength) & 3;
447228753Smm
448228753Smm	/*
449228753Smm	 * Note: entry_bytes_remaining is at least 64 bits and
450228753Smm	 * therefore guaranteed to be big enough for a 33-bit file
451228753Smm	 * size.
452228753Smm	 */
453228753Smm	cpio->entry_bytes_remaining =
454228753Smm	    atol16(header->c_filesize, sizeof(header->c_filesize));
455228753Smm	archive_entry_set_size(entry, cpio->entry_bytes_remaining);
456228753Smm	/* Pad file contents to a multiple of 4. */
457228753Smm	cpio->entry_padding = 3 & -cpio->entry_bytes_remaining;
458228753Smm	return (r);
459228753Smm}
460228753Smm
461228753Smm/*
462228753Smm * Skip forward to the next cpio odc header by searching for the
463228753Smm * 070707 string.  This is a hand-optimized search that could
464228753Smm * probably be easily generalized to handle all character-based
465228753Smm * cpio variants.
466228753Smm */
467228753Smmstatic int
468228753Smmis_octal(const char *p, size_t len)
469228753Smm{
470228753Smm	while (len-- > 0) {
471228753Smm		if (*p < '0' || *p > '7')
472228753Smm			return (0);
473228753Smm	        ++p;
474228753Smm	}
475228753Smm	return (1);
476228753Smm}
477228753Smm
478228753Smmstatic int
479228753Smmfind_odc_header(struct archive_read *a)
480228753Smm{
481228753Smm	const void *h;
482228753Smm	const char *p, *q;
483228753Smm	size_t skip, skipped = 0;
484228753Smm	ssize_t bytes;
485228753Smm
486228753Smm	for (;;) {
487228753Smm		h = __archive_read_ahead(a, sizeof(struct cpio_odc_header), &bytes);
488228753Smm		if (h == NULL)
489228753Smm			return (ARCHIVE_FATAL);
490228753Smm		p = h;
491228753Smm		q = p + bytes;
492228753Smm
493228753Smm		/* Try the typical case first, then go into the slow search.*/
494228753Smm		if (memcmp("070707", p, 6) == 0
495228753Smm		    && is_octal(p, sizeof(struct cpio_odc_header)))
496228753Smm			return (ARCHIVE_OK);
497228753Smm
498228753Smm		/*
499228753Smm		 * Scan ahead until we find something that looks
500228753Smm		 * like an odc header.
501228753Smm		 */
502228753Smm		while (p + sizeof(struct cpio_odc_header) <= q) {
503228753Smm			switch (p[5]) {
504228753Smm			case '7':
505228753Smm				if (memcmp("070707", p, 6) == 0
506228753Smm					&& is_octal(p, sizeof(struct cpio_odc_header))) {
507228753Smm					skip = p - (const char *)h;
508228753Smm					__archive_read_consume(a, skip);
509228753Smm					skipped += skip;
510228753Smm					if (skipped > 0) {
511228753Smm						archive_set_error(&a->archive,
512228753Smm						    0,
513228753Smm						    "Skipped %d bytes before "
514228753Smm						    "finding valid header",
515228753Smm						    (int)skipped);
516228753Smm						return (ARCHIVE_WARN);
517228753Smm					}
518228753Smm					return (ARCHIVE_OK);
519228753Smm				}
520228753Smm				p += 2;
521228753Smm				break;
522228753Smm			case '0':
523228753Smm				p++;
524228753Smm				break;
525228753Smm			default:
526228753Smm				p += 6;
527228753Smm				break;
528228753Smm			}
529228753Smm		}
530228753Smm		skip = p - (const char *)h;
531228753Smm		__archive_read_consume(a, skip);
532228753Smm		skipped += skip;
533228753Smm	}
534228753Smm}
535228753Smm
536228753Smmstatic int
537228753Smmheader_odc(struct archive_read *a, struct cpio *cpio,
538228753Smm    struct archive_entry *entry, size_t *namelength, size_t *name_pad)
539228753Smm{
540228753Smm	const void *h;
541228753Smm	int r;
542228753Smm	const struct cpio_odc_header *header;
543228753Smm
544228753Smm	a->archive.archive_format = ARCHIVE_FORMAT_CPIO_POSIX;
545228753Smm	a->archive.archive_format_name = "POSIX octet-oriented cpio";
546228753Smm
547228753Smm	/* Find the start of the next header. */
548228753Smm	r = find_odc_header(a);
549228753Smm	if (r < ARCHIVE_WARN)
550228753Smm		return (r);
551228753Smm
552228753Smm	/* Read fixed-size portion of header. */
553228753Smm	h = __archive_read_ahead(a, sizeof(struct cpio_odc_header), NULL);
554228753Smm	if (h == NULL)
555228753Smm	    return (ARCHIVE_FATAL);
556228753Smm	__archive_read_consume(a, sizeof(struct cpio_odc_header));
557228753Smm
558228753Smm	/* Parse out octal fields. */
559228753Smm	header = (const struct cpio_odc_header *)h;
560228753Smm
561228753Smm	archive_entry_set_dev(entry, atol8(header->c_dev, sizeof(header->c_dev)));
562228753Smm	archive_entry_set_ino(entry, atol8(header->c_ino, sizeof(header->c_ino)));
563228753Smm	archive_entry_set_mode(entry, atol8(header->c_mode, sizeof(header->c_mode)));
564228753Smm	archive_entry_set_uid(entry, atol8(header->c_uid, sizeof(header->c_uid)));
565228753Smm	archive_entry_set_gid(entry, atol8(header->c_gid, sizeof(header->c_gid)));
566228753Smm	archive_entry_set_nlink(entry, atol8(header->c_nlink, sizeof(header->c_nlink)));
567228753Smm	archive_entry_set_rdev(entry, atol8(header->c_rdev, sizeof(header->c_rdev)));
568228753Smm	archive_entry_set_mtime(entry, atol8(header->c_mtime, sizeof(header->c_mtime)), 0);
569228753Smm	*namelength = atol8(header->c_namesize, sizeof(header->c_namesize));
570228753Smm	*name_pad = 0; /* No padding of filename. */
571228753Smm
572228753Smm	/*
573228753Smm	 * Note: entry_bytes_remaining is at least 64 bits and
574228753Smm	 * therefore guaranteed to be big enough for a 33-bit file
575228753Smm	 * size.
576228753Smm	 */
577228753Smm	cpio->entry_bytes_remaining =
578228753Smm	    atol8(header->c_filesize, sizeof(header->c_filesize));
579228753Smm	archive_entry_set_size(entry, cpio->entry_bytes_remaining);
580228753Smm	cpio->entry_padding = 0;
581228753Smm	return (r);
582228753Smm}
583228753Smm
584228753Smmstatic int
585228753Smmheader_bin_le(struct archive_read *a, struct cpio *cpio,
586228753Smm    struct archive_entry *entry, size_t *namelength, size_t *name_pad)
587228753Smm{
588228753Smm	const void *h;
589228753Smm	const struct cpio_bin_header *header;
590228753Smm
591228753Smm	a->archive.archive_format = ARCHIVE_FORMAT_CPIO_BIN_LE;
592228753Smm	a->archive.archive_format_name = "cpio (little-endian binary)";
593228753Smm
594228753Smm	/* Read fixed-size portion of header. */
595228753Smm	h = __archive_read_ahead(a, sizeof(struct cpio_bin_header), NULL);
596228753Smm	if (h == NULL)
597228753Smm	    return (ARCHIVE_FATAL);
598228753Smm	__archive_read_consume(a, sizeof(struct cpio_bin_header));
599228753Smm
600228753Smm	/* Parse out binary fields. */
601228753Smm	header = (const struct cpio_bin_header *)h;
602228753Smm
603228753Smm	archive_entry_set_dev(entry, header->c_dev[0] + header->c_dev[1] * 256);
604228753Smm	archive_entry_set_ino(entry, header->c_ino[0] + header->c_ino[1] * 256);
605228753Smm	archive_entry_set_mode(entry, header->c_mode[0] + header->c_mode[1] * 256);
606228753Smm	archive_entry_set_uid(entry, header->c_uid[0] + header->c_uid[1] * 256);
607228753Smm	archive_entry_set_gid(entry, header->c_gid[0] + header->c_gid[1] * 256);
608228753Smm	archive_entry_set_nlink(entry, header->c_nlink[0] + header->c_nlink[1] * 256);
609228753Smm	archive_entry_set_rdev(entry, header->c_rdev[0] + header->c_rdev[1] * 256);
610228753Smm	archive_entry_set_mtime(entry, le4(header->c_mtime), 0);
611228753Smm	*namelength = header->c_namesize[0] + header->c_namesize[1] * 256;
612228753Smm	*name_pad = *namelength & 1; /* Pad to even. */
613228753Smm
614228753Smm	cpio->entry_bytes_remaining = le4(header->c_filesize);
615228753Smm	archive_entry_set_size(entry, cpio->entry_bytes_remaining);
616228753Smm	cpio->entry_padding = cpio->entry_bytes_remaining & 1; /* Pad to even. */
617228753Smm	return (ARCHIVE_OK);
618228753Smm}
619228753Smm
620228753Smmstatic int
621228753Smmheader_bin_be(struct archive_read *a, struct cpio *cpio,
622228753Smm    struct archive_entry *entry, size_t *namelength, size_t *name_pad)
623228753Smm{
624228753Smm	const void *h;
625228753Smm	const struct cpio_bin_header *header;
626228753Smm
627228753Smm	a->archive.archive_format = ARCHIVE_FORMAT_CPIO_BIN_BE;
628228753Smm	a->archive.archive_format_name = "cpio (big-endian binary)";
629228753Smm
630228753Smm	/* Read fixed-size portion of header. */
631228753Smm	h = __archive_read_ahead(a, sizeof(struct cpio_bin_header), NULL);
632228753Smm	if (h == NULL)
633228753Smm	    return (ARCHIVE_FATAL);
634228753Smm	__archive_read_consume(a, sizeof(struct cpio_bin_header));
635228753Smm
636228753Smm	/* Parse out binary fields. */
637228753Smm	header = (const struct cpio_bin_header *)h;
638228753Smm	archive_entry_set_dev(entry, header->c_dev[0] * 256 + header->c_dev[1]);
639228753Smm	archive_entry_set_ino(entry, header->c_ino[0] * 256 + header->c_ino[1]);
640228753Smm	archive_entry_set_mode(entry, header->c_mode[0] * 256 + header->c_mode[1]);
641228753Smm	archive_entry_set_uid(entry, header->c_uid[0] * 256 + header->c_uid[1]);
642228753Smm	archive_entry_set_gid(entry, header->c_gid[0] * 256 + header->c_gid[1]);
643228753Smm	archive_entry_set_nlink(entry, header->c_nlink[0] * 256 + header->c_nlink[1]);
644228753Smm	archive_entry_set_rdev(entry, header->c_rdev[0] * 256 + header->c_rdev[1]);
645228753Smm	archive_entry_set_mtime(entry, be4(header->c_mtime), 0);
646228753Smm	*namelength = header->c_namesize[0] * 256 + header->c_namesize[1];
647228753Smm	*name_pad = *namelength & 1; /* Pad to even. */
648228753Smm
649228753Smm	cpio->entry_bytes_remaining = be4(header->c_filesize);
650228753Smm	archive_entry_set_size(entry, cpio->entry_bytes_remaining);
651228753Smm	cpio->entry_padding = cpio->entry_bytes_remaining & 1; /* Pad to even. */
652228753Smm	return (ARCHIVE_OK);
653228753Smm}
654228753Smm
655228753Smmstatic int
656228753Smmarchive_read_format_cpio_cleanup(struct archive_read *a)
657228753Smm{
658228753Smm	struct cpio *cpio;
659228753Smm
660228753Smm	cpio = (struct cpio *)(a->format->data);
661228753Smm        /* Free inode->name map */
662228753Smm        while (cpio->links_head != NULL) {
663228753Smm                struct links_entry *lp = cpio->links_head->next;
664228753Smm
665228753Smm                if (cpio->links_head->name)
666228753Smm                        free(cpio->links_head->name);
667228753Smm                free(cpio->links_head);
668228753Smm                cpio->links_head = lp;
669228753Smm        }
670228753Smm	archive_string_free(&cpio->entry_name);
671228753Smm	free(cpio);
672228753Smm	(a->format->data) = NULL;
673228753Smm	return (ARCHIVE_OK);
674228753Smm}
675228753Smm
676228753Smmstatic int
677228753Smmle4(const unsigned char *p)
678228753Smm{
679228753Smm	return ((p[0]<<16) + (p[1]<<24) + (p[2]<<0) + (p[3]<<8));
680228753Smm}
681228753Smm
682228753Smm
683228753Smmstatic int
684228753Smmbe4(const unsigned char *p)
685228753Smm{
686228753Smm	return ((p[0]<<24) + (p[1]<<16) + (p[2]<<8) + (p[3]));
687228753Smm}
688228753Smm
689228753Smm/*
690228753Smm * Note that this implementation does not (and should not!) obey
691228753Smm * locale settings; you cannot simply substitute strtol here, since
692228753Smm * it does obey locale.
693228753Smm */
694228753Smmstatic int64_t
695228753Smmatol8(const char *p, unsigned char_cnt)
696228753Smm{
697228753Smm	int64_t l;
698228753Smm	int digit;
699228753Smm
700228753Smm	l = 0;
701228753Smm	while (char_cnt-- > 0) {
702228753Smm		if (*p >= '0' && *p <= '7')
703228753Smm			digit = *p - '0';
704228753Smm		else
705228753Smm			return (l);
706228753Smm		p++;
707228753Smm		l <<= 3;
708228753Smm		l |= digit;
709228753Smm	}
710228753Smm	return (l);
711228753Smm}
712228753Smm
713228753Smmstatic int64_t
714228753Smmatol16(const char *p, unsigned char_cnt)
715228753Smm{
716228753Smm	int64_t l;
717228753Smm	int digit;
718228753Smm
719228753Smm	l = 0;
720228753Smm	while (char_cnt-- > 0) {
721228753Smm		if (*p >= 'a' && *p <= 'f')
722228753Smm			digit = *p - 'a' + 10;
723228753Smm		else if (*p >= 'A' && *p <= 'F')
724228753Smm			digit = *p - 'A' + 10;
725228753Smm		else if (*p >= '0' && *p <= '9')
726228753Smm			digit = *p - '0';
727228753Smm		else
728228753Smm			return (l);
729228753Smm		p++;
730228753Smm		l <<= 4;
731228753Smm		l |= digit;
732228753Smm	}
733228753Smm	return (l);
734228753Smm}
735228753Smm
736228753Smmstatic void
737228753Smmrecord_hardlink(struct cpio *cpio, struct archive_entry *entry)
738228753Smm{
739228753Smm	struct links_entry      *le;
740228753Smm	dev_t dev;
741228753Smm	int64_t ino;
742228753Smm
743228753Smm	if (archive_entry_nlink(entry) <= 1)
744228753Smm		return;
745228753Smm
746228753Smm	dev = archive_entry_dev(entry);
747228753Smm	ino = archive_entry_ino64(entry);
748228753Smm
749228753Smm	/*
750228753Smm	 * First look in the list of multiply-linked files.  If we've
751228753Smm	 * already dumped it, convert this entry to a hard link entry.
752228753Smm	 */
753228753Smm	for (le = cpio->links_head; le; le = le->next) {
754228753Smm		if (le->dev == dev && le->ino == ino) {
755228753Smm			archive_entry_copy_hardlink(entry, le->name);
756228753Smm
757228753Smm			if (--le->links <= 0) {
758228753Smm				if (le->previous != NULL)
759228753Smm					le->previous->next = le->next;
760228753Smm				if (le->next != NULL)
761228753Smm					le->next->previous = le->previous;
762228753Smm				if (cpio->links_head == le)
763228753Smm					cpio->links_head = le->next;
764228753Smm				free(le->name);
765228753Smm				free(le);
766228753Smm			}
767228753Smm
768228753Smm			return;
769228753Smm		}
770228753Smm	}
771228753Smm
772228753Smm	le = (struct links_entry *)malloc(sizeof(struct links_entry));
773228753Smm	if (le == NULL)
774228753Smm		__archive_errx(1, "Out of memory adding file to list");
775228753Smm	if (cpio->links_head != NULL)
776228753Smm		cpio->links_head->previous = le;
777228753Smm	le->next = cpio->links_head;
778228753Smm	le->previous = NULL;
779228753Smm	cpio->links_head = le;
780228753Smm	le->dev = dev;
781228753Smm	le->ino = ino;
782228753Smm	le->links = archive_entry_nlink(entry) - 1;
783228753Smm	le->name = strdup(archive_entry_pathname(entry));
784228753Smm	if (le->name == NULL)
785228753Smm		__archive_errx(1, "Out of memory adding file to list");
786228753Smm}
787