1/*	$OpenBSD: cpio.c,v 1.18 2008/01/01 16:22:44 tobias Exp $	*/
2/*	$NetBSD: cpio.c,v 1.5 1995/03/21 09:07:13 cgd Exp $	*/
3
4/*-
5 * Copyright (c) 1992 Keith Muller.
6 * Copyright (c) 1992, 1993
7 *	The Regents of the University of California.  All rights reserved.
8 *
9 * This code is derived from software contributed to Berkeley by
10 * Keith Muller of the University of California, San Diego.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 *    notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 *    notice, this list of conditions and the following disclaimer in the
19 *    documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its contributors
21 *    may be used to endorse or promote products derived from this software
22 *    without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#ifndef lint
38#if 0
39static const char sccsid[] = "@(#)cpio.c	8.1 (Berkeley) 5/31/93";
40#else
41static const char rcsid[] = "$OpenBSD: cpio.c,v 1.18 2008/01/01 16:22:44 tobias Exp $";
42#endif
43#endif /* not lint */
44
45#include <sys/types.h>
46#include <sys/time.h>
47#include <sys/stat.h>
48#include <sys/param.h>
49#include <string.h>
50#include <stdio.h>
51#include <unistd.h>
52#include <stdlib.h>
53#include "pax.h"
54#include "cpio.h"
55#include "extern.h"
56
57static int rd_nm(ARCHD *, int);
58static int rd_ln_nm(ARCHD *);
59static int com_rd(ARCHD *);
60
61/*
62 * Routines which support the different cpio versions
63 */
64
65static int swp_head;		/* binary cpio header byte swap */
66
67/*
68 * Routines common to all versions of cpio
69 */
70
71/*
72 * cpio_strd()
73 *	Fire up the hard link detection code
74 * Return:
75 *      0 if ok -1 otherwise (the return values of lnk_start())
76 */
77
78int
79cpio_strd(void)
80{
81	return(lnk_start());
82}
83
84/*
85 * cpio_trail()
86 *	Called to determine if a header block is a valid trailer. We are
87 *	passed the block, the in_sync flag (which tells us we are in resync
88 *	mode; looking for a valid header), and cnt (which starts at zero)
89 *	which is used to count the number of empty blocks we have seen so far.
90 * Return:
91 *	0 if a valid trailer, -1 if not a valid trailer,
92 */
93
94int
95cpio_trail(ARCHD *arcn, char *notused, int notused2, int *notused3)
96{
97	/*
98	 * look for trailer id in file we are about to process
99	 */
100	if ((strcmp(arcn->name, TRAILER) == 0) && (arcn->sb.st_size == 0))
101		return(0);
102	return(-1);
103}
104
105/*
106 * com_rd()
107 *	operations common to all cpio read functions.
108 * Return:
109 *	0
110 */
111
112static int
113com_rd(ARCHD *arcn)
114{
115	arcn->skip = 0;
116	arcn->pat = NULL;
117	arcn->org_name = arcn->name;
118	switch (arcn->sb.st_mode & C_IFMT) {
119	case C_ISFIFO:
120		arcn->type = PAX_FIF;
121		break;
122	case C_ISDIR:
123		arcn->type = PAX_DIR;
124		break;
125	case C_ISBLK:
126		arcn->type = PAX_BLK;
127		break;
128	case C_ISCHR:
129		arcn->type = PAX_CHR;
130		break;
131	case C_ISLNK:
132		arcn->type = PAX_SLK;
133		break;
134	case C_ISOCK:
135		arcn->type = PAX_SCK;
136		break;
137	case C_ISCTG:
138	case C_ISREG:
139	default:
140		/*
141		 * we have file data, set up skip (pad is set in the format
142		 * specific sections)
143		 */
144		arcn->sb.st_mode = (arcn->sb.st_mode & 0xfff) | C_ISREG;
145		arcn->type = PAX_REG;
146		arcn->skip = arcn->sb.st_size;
147		break;
148	}
149	if (chk_lnk(arcn) < 0)
150		return(-1);
151	return(0);
152}
153
154/*
155 * cpio_endwr()
156 *	write the special file with the name trailer in the proper format
157 * Return:
158 *	result of the write of the trailer from the cpio specific write func
159 */
160
161int
162cpio_endwr(void)
163{
164	ARCHD last;
165
166	/*
167	 * create a trailer request and call the proper format write function
168	 */
169	memset(&last, 0, sizeof(last));
170	last.nlen = sizeof(TRAILER) - 1;
171	last.type = PAX_REG;
172	last.sb.st_nlink = 1;
173	(void)strlcpy(last.name, TRAILER, sizeof(last.name));
174	return((*frmt->wr)(&last));
175}
176
177/*
178 * rd_nam()
179 *	read in the file name which follows the cpio header
180 * Return:
181 *	0 if ok, -1 otherwise
182 */
183
184static int
185rd_nm(ARCHD *arcn, int nsz)
186{
187	/*
188	 * do not even try bogus values
189	 */
190	if ((nsz == 0) || (nsz > sizeof(arcn->name))) {
191		paxwarn(1, "Cpio file name length %d is out of range", nsz);
192		return(-1);
193	}
194
195	/*
196	 * read the name and make sure it is not empty and is \0 terminated
197	 */
198	if ((rd_wrbuf(arcn->name,nsz) != nsz) || (arcn->name[nsz-1] != '\0') ||
199	    (arcn->name[0] == '\0')) {
200		paxwarn(1, "Cpio file name in header is corrupted");
201		return(-1);
202	}
203	return(0);
204}
205
206/*
207 * rd_ln_nm()
208 *	read in the link name for a file with links. The link name is stored
209 *	like file data (and is NOT \0 terminated!)
210 * Return:
211 *	0 if ok, -1 otherwise
212 */
213
214static int
215rd_ln_nm(ARCHD *arcn)
216{
217	/*
218	 * check the length specified for bogus values
219	 */
220	if ((arcn->sb.st_size == 0) ||
221	    (arcn->sb.st_size >= sizeof(arcn->ln_name))) {
222#		ifdef LONG_OFF_T
223		paxwarn(1, "Cpio link name length is invalid: %lu",
224		    arcn->sb.st_size);
225#		else
226		paxwarn(1, "Cpio link name length is invalid: %qu",
227		    arcn->sb.st_size);
228#		endif
229		return(-1);
230	}
231
232	/*
233	 * read in the link name and \0 terminate it
234	 */
235	if (rd_wrbuf(arcn->ln_name, (int)arcn->sb.st_size) !=
236	    (int)arcn->sb.st_size) {
237		paxwarn(1, "Cpio link name read error");
238		return(-1);
239	}
240	arcn->ln_nlen = (int)arcn->sb.st_size;
241	arcn->ln_name[arcn->ln_nlen] = '\0';
242
243	/*
244	 * watch out for those empty link names
245	 */
246	if (arcn->ln_name[0] == '\0') {
247		paxwarn(1, "Cpio link name is corrupt");
248		return(-1);
249	}
250	return(0);
251}
252
253/*
254 * Routines common to the extended byte oriented cpio format
255 */
256
257/*
258 * cpio_id()
259 *      determine if a block given to us is a valid extended byte oriented
260 *	cpio header
261 * Return:
262 *      0 if a valid header, -1 otherwise
263 */
264
265int
266cpio_id(char *blk, int size)
267{
268	if ((size < sizeof(HD_CPIO)) ||
269	    (strncmp(blk, AMAGIC, sizeof(AMAGIC) - 1) != 0))
270		return(-1);
271	return(0);
272}
273
274/*
275 * cpio_rd()
276 *	determine if a buffer is a byte oriented extended cpio archive entry.
277 *	convert and store the values in the ARCHD parameter.
278 * Return:
279 *	0 if a valid header, -1 otherwise.
280 */
281
282int
283cpio_rd(ARCHD *arcn, char *buf)
284{
285	int nsz;
286	HD_CPIO *hd;
287
288	/*
289	 * check that this is a valid header, if not return -1
290	 */
291	if (cpio_id(buf, sizeof(HD_CPIO)) < 0)
292		return(-1);
293	hd = (HD_CPIO *)buf;
294
295	/*
296	 * byte oriented cpio (posix) does not have padding! extract the octal
297	 * ascii fields from the header
298	 */
299	arcn->pad = 0L;
300	arcn->sb.st_dev = (dev_t)asc_ul(hd->c_dev, sizeof(hd->c_dev), OCT);
301	arcn->sb.st_ino = (ino_t)asc_ul(hd->c_ino, sizeof(hd->c_ino), OCT);
302	arcn->sb.st_mode = (mode_t)asc_ul(hd->c_mode, sizeof(hd->c_mode), OCT);
303	arcn->sb.st_uid = (uid_t)asc_ul(hd->c_uid, sizeof(hd->c_uid), OCT);
304	arcn->sb.st_gid = (gid_t)asc_ul(hd->c_gid, sizeof(hd->c_gid), OCT);
305	arcn->sb.st_nlink = (nlink_t)asc_ul(hd->c_nlink, sizeof(hd->c_nlink),
306	    OCT);
307	arcn->sb.st_rdev = (dev_t)asc_ul(hd->c_rdev, sizeof(hd->c_rdev), OCT);
308	arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime, sizeof(hd->c_mtime),
309	    OCT);
310	arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
311#	ifdef LONG_OFF_T
312	arcn->sb.st_size = (off_t)asc_ul(hd->c_filesize,sizeof(hd->c_filesize),
313	    OCT);
314#	else
315	arcn->sb.st_size = (off_t)asc_uqd(hd->c_filesize,sizeof(hd->c_filesize),
316	    OCT);
317#	endif
318
319	/*
320	 * check name size and if valid, read in the name of this entry (name
321	 * follows header in the archive)
322	 */
323	if ((nsz = (int)asc_ul(hd->c_namesize,sizeof(hd->c_namesize),OCT)) < 2)
324		return(-1);
325	arcn->nlen = nsz - 1;
326	if (rd_nm(arcn, nsz) < 0)
327		return(-1);
328
329	if (((arcn->sb.st_mode&C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)) {
330		/*
331		 * no link name to read for this file
332		 */
333		arcn->ln_nlen = 0;
334		arcn->ln_name[0] = '\0';
335		return(com_rd(arcn));
336	}
337
338	/*
339	 * check link name size and read in the link name. Link names are
340	 * stored like file data.
341	 */
342	if (rd_ln_nm(arcn) < 0)
343		return(-1);
344
345	/*
346	 * we have a valid header (with a link)
347	 */
348	return(com_rd(arcn));
349}
350
351/*
352 * cpio_endrd()
353 *      no cleanup needed here, just return size of the trailer (for append)
354 * Return:
355 *      size of trailer header in this format
356 */
357
358off_t
359cpio_endrd(void)
360{
361	return((off_t)(sizeof(HD_CPIO) + sizeof(TRAILER)));
362}
363
364/*
365 * cpio_stwr()
366 *	start up the device mapping table
367 * Return:
368 *	0 if ok, -1 otherwise (what dev_start() returns)
369 */
370
371int
372cpio_stwr(void)
373{
374	return(dev_start());
375}
376
377/*
378 * cpio_wr()
379 *	copy the data in the ARCHD to buffer in extended byte oriented cpio
380 *	format.
381 * Return
382 *      0 if file has data to be written after the header, 1 if file has NO
383 *	data to write after the header, -1 if archive write failed
384 */
385
386int
387cpio_wr(ARCHD *arcn)
388{
389	HD_CPIO *hd;
390	int nsz;
391	char hdblk[sizeof(HD_CPIO)];
392
393	/*
394	 * check and repair truncated device and inode fields in the header
395	 */
396	if (map_dev(arcn, (u_long)CPIO_MASK, (u_long)CPIO_MASK) < 0)
397		return(-1);
398
399	arcn->pad = 0L;
400	nsz = arcn->nlen + 1;
401	hd = (HD_CPIO *)hdblk;
402	if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR))
403		arcn->sb.st_rdev = 0;
404
405	switch (arcn->type) {
406	case PAX_CTG:
407	case PAX_REG:
408	case PAX_HRG:
409		/*
410		 * set data size for file data
411		 */
412#		ifdef LONG_OFF_T
413		if (ul_asc((u_long)arcn->sb.st_size, hd->c_filesize,
414		    sizeof(hd->c_filesize), OCT)) {
415#		else
416		if (uqd_asc((u_quad_t)arcn->sb.st_size, hd->c_filesize,
417		    sizeof(hd->c_filesize), OCT)) {
418#		endif
419			paxwarn(1,"File is too large for cpio format %s",
420			    arcn->org_name);
421			return(1);
422		}
423		break;
424	case PAX_SLK:
425		/*
426		 * set data size to hold link name
427		 */
428		if (ul_asc((u_long)arcn->ln_nlen, hd->c_filesize,
429		    sizeof(hd->c_filesize), OCT))
430			goto out;
431		break;
432	default:
433		/*
434		 * all other file types have no file data
435		 */
436		if (ul_asc((u_long)0, hd->c_filesize, sizeof(hd->c_filesize),
437		     OCT))
438			goto out;
439		break;
440	}
441
442	/*
443	 * copy the values to the header using octal ascii
444	 */
445	if (ul_asc((u_long)MAGIC, hd->c_magic, sizeof(hd->c_magic), OCT) ||
446	    ul_asc((u_long)arcn->sb.st_dev, hd->c_dev, sizeof(hd->c_dev),
447		OCT) ||
448	    ul_asc((u_long)arcn->sb.st_ino, hd->c_ino, sizeof(hd->c_ino),
449		OCT) ||
450	    ul_asc((u_long)arcn->sb.st_mode, hd->c_mode, sizeof(hd->c_mode),
451		OCT) ||
452	    ul_asc((u_long)arcn->sb.st_uid, hd->c_uid, sizeof(hd->c_uid),
453		OCT) ||
454	    ul_asc((u_long)arcn->sb.st_gid, hd->c_gid, sizeof(hd->c_gid),
455		OCT) ||
456	    ul_asc((u_long)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink),
457		 OCT) ||
458	    ul_asc((u_long)arcn->sb.st_rdev, hd->c_rdev, sizeof(hd->c_rdev),
459		OCT) ||
460	    ul_asc((u_long)arcn->sb.st_mtime,hd->c_mtime,sizeof(hd->c_mtime),
461		OCT) ||
462	    ul_asc((u_long)nsz, hd->c_namesize, sizeof(hd->c_namesize), OCT))
463		goto out;
464
465	/*
466	 * write the file name to the archive
467	 */
468	if ((wr_rdbuf(hdblk, (int)sizeof(HD_CPIO)) < 0) ||
469	    (wr_rdbuf(arcn->name, nsz) < 0)) {
470		paxwarn(1, "Unable to write cpio header for %s", arcn->org_name);
471		return(-1);
472	}
473
474	/*
475	 * if this file has data, we are done. The caller will write the file
476	 * data, if we are link tell caller we are done, go to next file
477	 */
478	if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) ||
479	    (arcn->type == PAX_HRG))
480		return(0);
481	if (arcn->type != PAX_SLK)
482		return(1);
483
484	/*
485	 * write the link name to the archive, tell the caller to go to the
486	 * next file as we are done.
487	 */
488	if (wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) {
489		paxwarn(1,"Unable to write cpio link name for %s",arcn->org_name);
490		return(-1);
491	}
492	return(1);
493
494    out:
495	/*
496	 * header field is out of range
497	 */
498	paxwarn(1, "Cpio header field is too small to store file %s",
499	    arcn->org_name);
500	return(1);
501}
502
503/*
504 * Routines common to the system VR4 version of cpio (with/without file CRC)
505 */
506
507/*
508 * vcpio_id()
509 *      determine if a block given to us is a valid system VR4 cpio header
510 *	WITHOUT crc. WATCH it the magic cookies are in OCTAL, the header
511 *	uses HEX
512 * Return:
513 *      0 if a valid header, -1 otherwise
514 */
515
516int
517vcpio_id(char *blk, int size)
518{
519	if ((size < sizeof(HD_VCPIO)) ||
520	    (strncmp(blk, AVMAGIC, sizeof(AVMAGIC) - 1) != 0))
521		return(-1);
522	return(0);
523}
524
525/*
526 * crc_id()
527 *      determine if a block given to us is a valid system VR4 cpio header
528 *	WITH crc. WATCH it the magic cookies are in OCTAL the header uses HEX
529 * Return:
530 *      0 if a valid header, -1 otherwise
531 */
532
533int
534crc_id(char *blk, int size)
535{
536	if ((size < sizeof(HD_VCPIO)) ||
537	    (strncmp(blk, AVCMAGIC, sizeof(AVCMAGIC) - 1) != 0))
538		return(-1);
539	return(0);
540}
541
542/*
543 * crc_strd()
544 w	set file data CRC calculations. Fire up the hard link detection code
545 * Return:
546 *      0 if ok -1 otherwise (the return values of lnk_start())
547 */
548
549int
550crc_strd(void)
551{
552	docrc = 1;
553	return(lnk_start());
554}
555
556/*
557 * vcpio_rd()
558 *	determine if a buffer is a system VR4 archive entry. (with/without CRC)
559 *	convert and store the values in the ARCHD parameter.
560 * Return:
561 *	0 if a valid header, -1 otherwise.
562 */
563
564int
565vcpio_rd(ARCHD *arcn, char *buf)
566{
567	HD_VCPIO *hd;
568	dev_t devminor;
569	dev_t devmajor;
570	int nsz;
571
572	/*
573	 * during the id phase it was determined if we were using CRC, use the
574	 * proper id routine.
575	 */
576	if (docrc) {
577		if (crc_id(buf, sizeof(HD_VCPIO)) < 0)
578			return(-1);
579	} else {
580		if (vcpio_id(buf, sizeof(HD_VCPIO)) < 0)
581			return(-1);
582	}
583
584	hd = (HD_VCPIO *)buf;
585	arcn->pad = 0L;
586
587	/*
588	 * extract the hex ascii fields from the header
589	 */
590	arcn->sb.st_ino = (ino_t)asc_ul(hd->c_ino, sizeof(hd->c_ino), HEX);
591	arcn->sb.st_mode = (mode_t)asc_ul(hd->c_mode, sizeof(hd->c_mode), HEX);
592	arcn->sb.st_uid = (uid_t)asc_ul(hd->c_uid, sizeof(hd->c_uid), HEX);
593	arcn->sb.st_gid = (gid_t)asc_ul(hd->c_gid, sizeof(hd->c_gid), HEX);
594	arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime,sizeof(hd->c_mtime),HEX);
595	arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
596#	ifdef LONG_OFF_T
597	arcn->sb.st_size = (off_t)asc_ul(hd->c_filesize,
598	    sizeof(hd->c_filesize), HEX);
599#	else
600	arcn->sb.st_size = (off_t)asc_uqd(hd->c_filesize,
601	    sizeof(hd->c_filesize), HEX);
602#	endif
603	arcn->sb.st_nlink = (nlink_t)asc_ul(hd->c_nlink, sizeof(hd->c_nlink),
604	    HEX);
605	devmajor = (dev_t)asc_ul(hd->c_maj, sizeof(hd->c_maj), HEX);
606	devminor = (dev_t)asc_ul(hd->c_min, sizeof(hd->c_min), HEX);
607	arcn->sb.st_dev = TODEV(devmajor, devminor);
608	devmajor = (dev_t)asc_ul(hd->c_rmaj, sizeof(hd->c_maj), HEX);
609	devminor = (dev_t)asc_ul(hd->c_rmin, sizeof(hd->c_min), HEX);
610	arcn->sb.st_rdev = TODEV(devmajor, devminor);
611	arcn->crc = asc_ul(hd->c_chksum, sizeof(hd->c_chksum), HEX);
612
613	/*
614	 * check the length of the file name, if ok read it in, return -1 if
615	 * bogus
616	 */
617	if ((nsz = (int)asc_ul(hd->c_namesize,sizeof(hd->c_namesize),HEX)) < 2)
618		return(-1);
619	arcn->nlen = nsz - 1;
620	if (rd_nm(arcn, nsz) < 0)
621		return(-1);
622
623	/*
624	 * skip padding. header + filename is aligned to 4 byte boundaries
625	 */
626	if (rd_skip((off_t)(VCPIO_PAD(sizeof(HD_VCPIO) + nsz))) < 0)
627		return(-1);
628
629	/*
630	 * if not a link (or a file with no data), calculate pad size (for
631	 * padding which follows the file data), clear the link name and return
632	 */
633	if (((arcn->sb.st_mode&C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)) {
634		/*
635		 * we have a valid header (not a link)
636		 */
637		arcn->ln_nlen = 0;
638		arcn->ln_name[0] = '\0';
639		arcn->pad = VCPIO_PAD(arcn->sb.st_size);
640		return(com_rd(arcn));
641	}
642
643	/*
644	 * read in the link name and skip over the padding
645	 */
646	if ((rd_ln_nm(arcn) < 0) ||
647	    (rd_skip((off_t)(VCPIO_PAD(arcn->sb.st_size))) < 0))
648		return(-1);
649
650	/*
651	 * we have a valid header (with a link)
652	 */
653	return(com_rd(arcn));
654}
655
656/*
657 * vcpio_endrd()
658 *      no cleanup needed here, just return size of the trailer (for append)
659 * Return:
660 *      size of trailer header in this format
661 */
662
663off_t
664vcpio_endrd(void)
665{
666	return((off_t)(sizeof(HD_VCPIO) + sizeof(TRAILER) +
667		(VCPIO_PAD(sizeof(HD_VCPIO) + sizeof(TRAILER)))));
668}
669
670/*
671 * crc_stwr()
672 *	start up the device mapping table, enable crc file calculation
673 * Return:
674 *	0 if ok, -1 otherwise (what dev_start() returns)
675 */
676
677int
678crc_stwr(void)
679{
680	docrc = 1;
681	return(dev_start());
682}
683
684/*
685 * vcpio_wr()
686 *	copy the data in the ARCHD to buffer in system VR4 cpio
687 *	(with/without crc) format.
688 * Return
689 *	0 if file has data to be written after the header, 1 if file has
690 *	NO data to write after the header, -1 if archive write failed
691 */
692
693int
694vcpio_wr(ARCHD *arcn)
695{
696	HD_VCPIO *hd;
697	unsigned int nsz;
698	char hdblk[sizeof(HD_VCPIO)];
699
700	/*
701	 * check and repair truncated device and inode fields in the cpio
702	 * header
703	 */
704	if (map_dev(arcn, (u_long)VCPIO_MASK, (u_long)VCPIO_MASK) < 0)
705		return(-1);
706	nsz = arcn->nlen + 1;
707	hd = (HD_VCPIO *)hdblk;
708	if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR))
709		arcn->sb.st_rdev = 0;
710
711	/*
712	 * add the proper magic value depending whether we were asked for
713	 * file data crc's, and the crc if needed.
714	 */
715	if (docrc) {
716		if (ul_asc((u_long)VCMAGIC, hd->c_magic, sizeof(hd->c_magic),
717			OCT) ||
718		    ul_asc((u_long)arcn->crc,hd->c_chksum,sizeof(hd->c_chksum),
719			HEX))
720			goto out;
721	} else {
722		if (ul_asc((u_long)VMAGIC, hd->c_magic, sizeof(hd->c_magic),
723			OCT) ||
724		    ul_asc((u_long)0L, hd->c_chksum, sizeof(hd->c_chksum),HEX))
725			goto out;
726	}
727
728	switch (arcn->type) {
729	case PAX_CTG:
730	case PAX_REG:
731	case PAX_HRG:
732		/*
733		 * caller will copy file data to the archive. tell him how
734		 * much to pad.
735		 */
736		arcn->pad = VCPIO_PAD(arcn->sb.st_size);
737#		ifdef LONG_OFF_T
738		if (ul_asc((u_long)arcn->sb.st_size, hd->c_filesize,
739		    sizeof(hd->c_filesize), HEX)) {
740#		else
741		if (uqd_asc((u_quad_t)arcn->sb.st_size, hd->c_filesize,
742		    sizeof(hd->c_filesize), HEX)) {
743#		endif
744			paxwarn(1,"File is too large for sv4cpio format %s",
745			    arcn->org_name);
746			return(1);
747		}
748		break;
749	case PAX_SLK:
750		/*
751		 * no file data for the caller to process, the file data has
752		 * the size of the link
753		 */
754		arcn->pad = 0L;
755		if (ul_asc((u_long)arcn->ln_nlen, hd->c_filesize,
756		    sizeof(hd->c_filesize), HEX))
757			goto out;
758		break;
759	default:
760		/*
761		 * no file data for the caller to process
762		 */
763		arcn->pad = 0L;
764		if (ul_asc((u_long)0L, hd->c_filesize, sizeof(hd->c_filesize),
765		    HEX))
766			goto out;
767		break;
768	}
769
770	/*
771	 * set the other fields in the header
772	 */
773	if (ul_asc((u_long)arcn->sb.st_ino, hd->c_ino, sizeof(hd->c_ino),
774		HEX) ||
775	    ul_asc((u_long)arcn->sb.st_mode, hd->c_mode, sizeof(hd->c_mode),
776		HEX) ||
777	    ul_asc((u_long)arcn->sb.st_uid, hd->c_uid, sizeof(hd->c_uid),
778		HEX) ||
779	    ul_asc((u_long)arcn->sb.st_gid, hd->c_gid, sizeof(hd->c_gid),
780		HEX) ||
781	    ul_asc((u_long)arcn->sb.st_mtime, hd->c_mtime, sizeof(hd->c_mtime),
782		HEX) ||
783	    ul_asc((u_long)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink),
784		HEX) ||
785	    ul_asc((u_long)MAJOR(arcn->sb.st_dev),hd->c_maj, sizeof(hd->c_maj),
786		HEX) ||
787	    ul_asc((u_long)MINOR(arcn->sb.st_dev),hd->c_min, sizeof(hd->c_min),
788		HEX) ||
789	    ul_asc((u_long)MAJOR(arcn->sb.st_rdev),hd->c_rmaj,sizeof(hd->c_maj),
790		HEX) ||
791	    ul_asc((u_long)MINOR(arcn->sb.st_rdev),hd->c_rmin,sizeof(hd->c_min),
792		HEX) ||
793	    ul_asc((u_long)nsz, hd->c_namesize, sizeof(hd->c_namesize), HEX))
794		goto out;
795
796	/*
797	 * write the header, the file name and padding as required.
798	 */
799	if ((wr_rdbuf(hdblk, (int)sizeof(HD_VCPIO)) < 0) ||
800	    (wr_rdbuf(arcn->name, (int)nsz) < 0)  ||
801	    (wr_skip((off_t)(VCPIO_PAD(sizeof(HD_VCPIO) + nsz))) < 0)) {
802		paxwarn(1,"Could not write sv4cpio header for %s",arcn->org_name);
803		return(-1);
804	}
805
806	/*
807	 * if we have file data, tell the caller we are done, copy the file
808	 */
809	if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) ||
810	    (arcn->type == PAX_HRG))
811		return(0);
812
813	/*
814	 * if we are not a link, tell the caller we are done, go to next file
815	 */
816	if (arcn->type != PAX_SLK)
817		return(1);
818
819	/*
820	 * write the link name, tell the caller we are done.
821	 */
822	if ((wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) ||
823	    (wr_skip((off_t)(VCPIO_PAD(arcn->ln_nlen))) < 0)) {
824		paxwarn(1,"Could not write sv4cpio link name for %s",
825		    arcn->org_name);
826		return(-1);
827	}
828	return(1);
829
830    out:
831	/*
832	 * header field is out of range
833	 */
834	paxwarn(1,"Sv4cpio header field is too small for file %s",arcn->org_name);
835	return(1);
836}
837
838/*
839 * Routines common to the old binary header cpio
840 */
841
842/*
843 * bcpio_id()
844 *      determine if a block given to us is a old binary cpio header
845 *	(with/without header byte swapping)
846 * Return:
847 *      0 if a valid header, -1 otherwise
848 */
849
850int
851bcpio_id(char *blk, int size)
852{
853	if (size < sizeof(HD_BCPIO))
854		return(-1);
855
856	/*
857	 * check both normal and byte swapped magic cookies
858	 */
859	if (((u_short)SHRT_EXT(blk)) == MAGIC)
860		return(0);
861	if (((u_short)RSHRT_EXT(blk)) == MAGIC) {
862		if (!swp_head)
863			++swp_head;
864		return(0);
865	}
866	return(-1);
867}
868
869/*
870 * bcpio_rd()
871 *	determine if a buffer is a old binary archive entry. (it may have byte
872 *	swapped header) convert and store the values in the ARCHD parameter.
873 *	This is a very old header format and should not really be used.
874 * Return:
875 *	0 if a valid header, -1 otherwise.
876 */
877
878int
879bcpio_rd(ARCHD *arcn, char *buf)
880{
881	HD_BCPIO *hd;
882	int nsz;
883
884	/*
885	 * check the header
886	 */
887	if (bcpio_id(buf, sizeof(HD_BCPIO)) < 0)
888		return(-1);
889
890	arcn->pad = 0L;
891	hd = (HD_BCPIO *)buf;
892	if (swp_head) {
893		/*
894		 * header has swapped bytes on 16 bit boundaries
895		 */
896		arcn->sb.st_dev = (dev_t)(RSHRT_EXT(hd->h_dev));
897		arcn->sb.st_ino = (ino_t)(RSHRT_EXT(hd->h_ino));
898		arcn->sb.st_mode = (mode_t)(RSHRT_EXT(hd->h_mode));
899		arcn->sb.st_uid = (uid_t)(RSHRT_EXT(hd->h_uid));
900		arcn->sb.st_gid = (gid_t)(RSHRT_EXT(hd->h_gid));
901		arcn->sb.st_nlink = (nlink_t)(RSHRT_EXT(hd->h_nlink));
902		arcn->sb.st_rdev = (dev_t)(RSHRT_EXT(hd->h_rdev));
903		arcn->sb.st_mtime = (time_t)(RSHRT_EXT(hd->h_mtime_1));
904		arcn->sb.st_mtime =  (arcn->sb.st_mtime << 16) |
905			((time_t)(RSHRT_EXT(hd->h_mtime_2)));
906		arcn->sb.st_size = (off_t)(RSHRT_EXT(hd->h_filesize_1));
907		arcn->sb.st_size = (arcn->sb.st_size << 16) |
908			((off_t)(RSHRT_EXT(hd->h_filesize_2)));
909		nsz = (int)(RSHRT_EXT(hd->h_namesize));
910	} else {
911		arcn->sb.st_dev = (dev_t)(SHRT_EXT(hd->h_dev));
912		arcn->sb.st_ino = (ino_t)(SHRT_EXT(hd->h_ino));
913		arcn->sb.st_mode = (mode_t)(SHRT_EXT(hd->h_mode));
914		arcn->sb.st_uid = (uid_t)(SHRT_EXT(hd->h_uid));
915		arcn->sb.st_gid = (gid_t)(SHRT_EXT(hd->h_gid));
916		arcn->sb.st_nlink = (nlink_t)(SHRT_EXT(hd->h_nlink));
917		arcn->sb.st_rdev = (dev_t)(SHRT_EXT(hd->h_rdev));
918		arcn->sb.st_mtime = (time_t)(SHRT_EXT(hd->h_mtime_1));
919		arcn->sb.st_mtime =  (arcn->sb.st_mtime << 16) |
920			((time_t)(SHRT_EXT(hd->h_mtime_2)));
921		arcn->sb.st_size = (off_t)(SHRT_EXT(hd->h_filesize_1));
922		arcn->sb.st_size = (arcn->sb.st_size << 16) |
923			((off_t)(SHRT_EXT(hd->h_filesize_2)));
924		nsz = (int)(SHRT_EXT(hd->h_namesize));
925	}
926	arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
927
928	/*
929	 * check the file name size, if bogus give up. otherwise read the file
930	 * name
931	 */
932	if (nsz < 2)
933		return(-1);
934	arcn->nlen = nsz - 1;
935	if (rd_nm(arcn, nsz) < 0)
936		return(-1);
937
938	/*
939	 * header + file name are aligned to 2 byte boundaries, skip if needed
940	 */
941	if (rd_skip((off_t)(BCPIO_PAD(sizeof(HD_BCPIO) + nsz))) < 0)
942		return(-1);
943
944	/*
945	 * if not a link (or a file with no data), calculate pad size (for
946	 * padding which follows the file data), clear the link name and return
947	 */
948	if (((arcn->sb.st_mode & C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)){
949		/*
950		 * we have a valid header (not a link)
951		 */
952		arcn->ln_nlen = 0;
953		arcn->ln_name[0] = '\0';
954		arcn->pad = BCPIO_PAD(arcn->sb.st_size);
955		return(com_rd(arcn));
956	}
957
958	if ((rd_ln_nm(arcn) < 0) ||
959	    (rd_skip((off_t)(BCPIO_PAD(arcn->sb.st_size))) < 0))
960		return(-1);
961
962	/*
963	 * we have a valid header (with a link)
964	 */
965	return(com_rd(arcn));
966}
967
968/*
969 * bcpio_endrd()
970 *      no cleanup needed here, just return size of the trailer (for append)
971 * Return:
972 *      size of trailer header in this format
973 */
974
975off_t
976bcpio_endrd(void)
977{
978	return((off_t)(sizeof(HD_BCPIO) + sizeof(TRAILER) +
979		(BCPIO_PAD(sizeof(HD_BCPIO) + sizeof(TRAILER)))));
980}
981
982/*
983 * bcpio_wr()
984 *	copy the data in the ARCHD to buffer in old binary cpio format
985 *	There is a real chance of field overflow with this critter. So we
986 *	always check the conversion is ok. nobody in their right mind
987 *	should write an archive in this format...
988 * Return
989 *      0 if file has data to be written after the header, 1 if file has NO
990 *	data to write after the header, -1 if archive write failed
991 */
992
993int
994bcpio_wr(ARCHD *arcn)
995{
996	HD_BCPIO *hd;
997	int nsz;
998	char hdblk[sizeof(HD_BCPIO)];
999	off_t t_offt;
1000	int t_int;
1001	time_t t_timet;
1002
1003	/*
1004	 * check and repair truncated device and inode fields in the cpio
1005	 * header
1006	 */
1007	if (map_dev(arcn, (u_long)BCPIO_MASK, (u_long)BCPIO_MASK) < 0)
1008		return(-1);
1009
1010	if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR))
1011		arcn->sb.st_rdev = 0;
1012	hd = (HD_BCPIO *)hdblk;
1013
1014	switch (arcn->type) {
1015	case PAX_CTG:
1016	case PAX_REG:
1017	case PAX_HRG:
1018		/*
1019		 * caller will copy file data to the archive. tell him how
1020		 * much to pad.
1021		 */
1022		arcn->pad = BCPIO_PAD(arcn->sb.st_size);
1023		hd->h_filesize_1[0] = CHR_WR_0(arcn->sb.st_size);
1024		hd->h_filesize_1[1] = CHR_WR_1(arcn->sb.st_size);
1025		hd->h_filesize_2[0] = CHR_WR_2(arcn->sb.st_size);
1026		hd->h_filesize_2[1] = CHR_WR_3(arcn->sb.st_size);
1027		t_offt = (off_t)(SHRT_EXT(hd->h_filesize_1));
1028		t_offt = (t_offt<<16) | ((off_t)(SHRT_EXT(hd->h_filesize_2)));
1029		if (arcn->sb.st_size != t_offt) {
1030			paxwarn(1,"File is too large for bcpio format %s",
1031			    arcn->org_name);
1032			return(1);
1033		}
1034		break;
1035	case PAX_SLK:
1036		/*
1037		 * no file data for the caller to process, the file data has
1038		 * the size of the link
1039		 */
1040		arcn->pad = 0L;
1041		hd->h_filesize_1[0] = CHR_WR_0(arcn->ln_nlen);
1042		hd->h_filesize_1[1] = CHR_WR_1(arcn->ln_nlen);
1043		hd->h_filesize_2[0] = CHR_WR_2(arcn->ln_nlen);
1044		hd->h_filesize_2[1] = CHR_WR_3(arcn->ln_nlen);
1045		t_int = (int)(SHRT_EXT(hd->h_filesize_1));
1046		t_int = (t_int << 16) | ((int)(SHRT_EXT(hd->h_filesize_2)));
1047		if (arcn->ln_nlen != t_int)
1048			goto out;
1049		break;
1050	default:
1051		/*
1052		 * no file data for the caller to process
1053		 */
1054		arcn->pad = 0L;
1055		hd->h_filesize_1[0] = (char)0;
1056		hd->h_filesize_1[1] = (char)0;
1057		hd->h_filesize_2[0] = (char)0;
1058		hd->h_filesize_2[1] = (char)0;
1059		break;
1060	}
1061
1062	/*
1063	 * build up the rest of the fields
1064	 */
1065	hd->h_magic[0] = CHR_WR_2(MAGIC);
1066	hd->h_magic[1] = CHR_WR_3(MAGIC);
1067	hd->h_dev[0] = CHR_WR_2(arcn->sb.st_dev);
1068	hd->h_dev[1] = CHR_WR_3(arcn->sb.st_dev);
1069	if (arcn->sb.st_dev != (dev_t)(SHRT_EXT(hd->h_dev)))
1070		goto out;
1071	hd->h_ino[0] = CHR_WR_2(arcn->sb.st_ino);
1072	hd->h_ino[1] = CHR_WR_3(arcn->sb.st_ino);
1073	if (arcn->sb.st_ino != (ino_t)(SHRT_EXT(hd->h_ino)))
1074		goto out;
1075	hd->h_mode[0] = CHR_WR_2(arcn->sb.st_mode);
1076	hd->h_mode[1] = CHR_WR_3(arcn->sb.st_mode);
1077	if (arcn->sb.st_mode != (mode_t)(SHRT_EXT(hd->h_mode)))
1078		goto out;
1079	hd->h_uid[0] = CHR_WR_2(arcn->sb.st_uid);
1080	hd->h_uid[1] = CHR_WR_3(arcn->sb.st_uid);
1081	if (arcn->sb.st_uid != (uid_t)(SHRT_EXT(hd->h_uid)))
1082		goto out;
1083	hd->h_gid[0] = CHR_WR_2(arcn->sb.st_gid);
1084	hd->h_gid[1] = CHR_WR_3(arcn->sb.st_gid);
1085	if (arcn->sb.st_gid != (gid_t)(SHRT_EXT(hd->h_gid)))
1086		goto out;
1087	hd->h_nlink[0] = CHR_WR_2(arcn->sb.st_nlink);
1088	hd->h_nlink[1] = CHR_WR_3(arcn->sb.st_nlink);
1089	if (arcn->sb.st_nlink != (nlink_t)(SHRT_EXT(hd->h_nlink)))
1090		goto out;
1091	hd->h_rdev[0] = CHR_WR_2(arcn->sb.st_rdev);
1092	hd->h_rdev[1] = CHR_WR_3(arcn->sb.st_rdev);
1093	if (arcn->sb.st_rdev != (dev_t)(SHRT_EXT(hd->h_rdev)))
1094		goto out;
1095	hd->h_mtime_1[0] = CHR_WR_0(arcn->sb.st_mtime);
1096	hd->h_mtime_1[1] = CHR_WR_1(arcn->sb.st_mtime);
1097	hd->h_mtime_2[0] = CHR_WR_2(arcn->sb.st_mtime);
1098	hd->h_mtime_2[1] = CHR_WR_3(arcn->sb.st_mtime);
1099	t_timet = (time_t)(SHRT_EXT(hd->h_mtime_1));
1100	t_timet =  (t_timet << 16) | ((time_t)(SHRT_EXT(hd->h_mtime_2)));
1101	if (arcn->sb.st_mtime != t_timet)
1102		goto out;
1103	nsz = arcn->nlen + 1;
1104	hd->h_namesize[0] = CHR_WR_2(nsz);
1105	hd->h_namesize[1] = CHR_WR_3(nsz);
1106	if (nsz != (int)(SHRT_EXT(hd->h_namesize)))
1107		goto out;
1108
1109	/*
1110	 * write the header, the file name and padding as required.
1111	 */
1112	if ((wr_rdbuf(hdblk, (int)sizeof(HD_BCPIO)) < 0) ||
1113	    (wr_rdbuf(arcn->name, nsz) < 0) ||
1114	    (wr_skip((off_t)(BCPIO_PAD(sizeof(HD_BCPIO) + nsz))) < 0)) {
1115		paxwarn(1, "Could not write bcpio header for %s", arcn->org_name);
1116		return(-1);
1117	}
1118
1119	/*
1120	 * if we have file data, tell the caller we are done
1121	 */
1122	if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) ||
1123	    (arcn->type == PAX_HRG))
1124		return(0);
1125
1126	/*
1127	 * if we are not a link, tell the caller we are done, go to next file
1128	 */
1129	if (arcn->type != PAX_SLK)
1130		return(1);
1131
1132	/*
1133	 * write the link name, tell the caller we are done.
1134	 */
1135	if ((wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) ||
1136	    (wr_skip((off_t)(BCPIO_PAD(arcn->ln_nlen))) < 0)) {
1137		paxwarn(1,"Could not write bcpio link name for %s",arcn->org_name);
1138		return(-1);
1139	}
1140	return(1);
1141
1142    out:
1143	/*
1144	 * header field is out of range
1145	 */
1146	paxwarn(1,"Bcpio header field is too small for file %s", arcn->org_name);
1147	return(1);
1148}
1149