cpio.c revision 284008
1/*-
2 * Copyright (c) 1992 Keith Muller.
3 * Copyright (c) 1992, 1993
4 *	The Regents of the University of California.  All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * Keith Muller of the University of California, San Diego.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35#if 0
36static char sccsid[] = "@(#)cpio.c	8.1 (Berkeley) 5/31/93";
37#endif
38#endif /* not lint */
39#include <sys/cdefs.h>
40__FBSDID("$FreeBSD: stable/10/bin/pax/cpio.c 284008 2015-06-05 00:39:34Z delphij $");
41
42#include <sys/types.h>
43#include <sys/time.h>
44#include <sys/stat.h>
45#include <string.h>
46#include <stdint.h>
47#include <stdio.h>
48#include "pax.h"
49#include "cpio.h"
50#include "extern.h"
51
52static int rd_nm(ARCHD *, int);
53static int rd_ln_nm(ARCHD *);
54static int com_rd(ARCHD *);
55
56/*
57 * Routines which support the different cpio versions
58 */
59
60static int swp_head;		/* binary cpio header byte swap */
61
62/*
63 * Routines common to all versions of cpio
64 */
65
66/*
67 * cpio_strd()
68 *	Fire up the hard link detection code
69 * Return:
70 *      0 if ok -1 otherwise (the return values of lnk_start())
71 */
72
73int
74cpio_strd(void)
75{
76	return(lnk_start());
77}
78
79/*
80 * cpio_trail()
81 *	Called to determine if a header block is a valid trailer. We are
82 *	passed the block, the in_sync flag (which tells us we are in resync
83 *	mode; looking for a valid header), and cnt (which starts at zero)
84 *	which is used to count the number of empty blocks we have seen so far.
85 * Return:
86 *	0 if a valid trailer, -1 if not a valid trailer,
87 */
88
89int
90cpio_trail(ARCHD *arcn)
91{
92	/*
93	 * look for trailer id in file we are about to process
94	 */
95	if ((strcmp(arcn->name, TRAILER) == 0) && (arcn->sb.st_size == 0))
96		return(0);
97	return(-1);
98}
99
100/*
101 * com_rd()
102 *	operations common to all cpio read functions.
103 * Return:
104 *	0
105 */
106
107static int
108com_rd(ARCHD *arcn)
109{
110	arcn->skip = 0;
111	arcn->pat = NULL;
112	arcn->org_name = arcn->name;
113	switch(arcn->sb.st_mode & C_IFMT) {
114	case C_ISFIFO:
115		arcn->type = PAX_FIF;
116		break;
117	case C_ISDIR:
118		arcn->type = PAX_DIR;
119		break;
120	case C_ISBLK:
121		arcn->type = PAX_BLK;
122		break;
123	case C_ISCHR:
124		arcn->type = PAX_CHR;
125		break;
126	case C_ISLNK:
127		arcn->type = PAX_SLK;
128		break;
129	case C_ISOCK:
130		arcn->type = PAX_SCK;
131		break;
132	case C_ISCTG:
133	case C_ISREG:
134	default:
135		/*
136		 * we have file data, set up skip (pad is set in the format
137		 * specific sections)
138		 */
139		arcn->sb.st_mode = (arcn->sb.st_mode & 0xfff) | C_ISREG;
140		arcn->type = PAX_REG;
141		arcn->skip = arcn->sb.st_size;
142		break;
143	}
144	if (chk_lnk(arcn) < 0)
145		return(-1);
146	return(0);
147}
148
149/*
150 * cpio_end_wr()
151 *	write the special file with the name trailer in the proper format
152 * Return:
153 *	result of the write of the trailer from the cpio specific write func
154 */
155
156int
157cpio_endwr(void)
158{
159	ARCHD last;
160
161	/*
162	 * create a trailer request and call the proper format write function
163	 */
164	memset(&last, 0, sizeof(last));
165	last.nlen = sizeof(TRAILER) - 1;
166	last.type = PAX_REG;
167	last.sb.st_nlink = 1;
168	(void)strcpy(last.name, TRAILER);
169	return((*frmt->wr)(&last));
170}
171
172/*
173 * rd_nam()
174 *	read in the file name which follows the cpio header
175 * Return:
176 *	0 if ok, -1 otherwise
177 */
178
179static int
180rd_nm(ARCHD *arcn, int nsz)
181{
182	/*
183	 * do not even try bogus values
184	 */
185	if ((nsz == 0) || (nsz > (int)sizeof(arcn->name))) {
186		paxwarn(1, "Cpio file name length %d is out of range", nsz);
187		return(-1);
188	}
189
190	/*
191	 * read the name and make sure it is not empty and is \0 terminated
192	 */
193	if ((rd_wrbuf(arcn->name,nsz) != nsz) || (arcn->name[nsz-1] != '\0') ||
194	    (arcn->name[0] == '\0')) {
195		paxwarn(1, "Cpio file name in header is corrupted");
196		return(-1);
197	}
198	return(0);
199}
200
201/*
202 * rd_ln_nm()
203 *	read in the link name for a file with links. The link name is stored
204 *	like file data (and is NOT \0 terminated!)
205 * Return:
206 *	0 if ok, -1 otherwise
207 */
208
209static int
210rd_ln_nm(ARCHD *arcn)
211{
212	/*
213	 * check the length specified for bogus values
214	 */
215	if ((arcn->sb.st_size == 0) ||
216	    ((size_t)arcn->sb.st_size >= sizeof(arcn->ln_name))) {
217#		ifdef NET2_STAT
218		paxwarn(1, "Cpio link name length is invalid: %lu",
219		    arcn->sb.st_size);
220#		else
221		paxwarn(1, "Cpio link name length is invalid: %ju",
222		    (uintmax_t)arcn->sb.st_size);
223#		endif
224		return(-1);
225	}
226
227	/*
228	 * read in the link name and \0 terminate it
229	 */
230	if (rd_wrbuf(arcn->ln_name, (int)arcn->sb.st_size) !=
231	    (int)arcn->sb.st_size) {
232		paxwarn(1, "Cpio link name read error");
233		return(-1);
234	}
235	arcn->ln_nlen = arcn->sb.st_size;
236	arcn->ln_name[arcn->ln_nlen] = '\0';
237
238	/*
239	 * watch out for those empty link names
240	 */
241	if (arcn->ln_name[0] == '\0') {
242		paxwarn(1, "Cpio link name is corrupt");
243		return(-1);
244	}
245	return(0);
246}
247
248/*
249 * Routines common to the extended byte oriented cpio format
250 */
251
252/*
253 * cpio_id()
254 *      determine if a block given to us is a valid extended byte oriented
255 *	cpio header
256 * Return:
257 *      0 if a valid header, -1 otherwise
258 */
259
260int
261cpio_id(char *blk, int size)
262{
263	if ((size < (int)sizeof(HD_CPIO)) ||
264	    (strncmp(blk, AMAGIC, sizeof(AMAGIC) - 1) != 0))
265		return(-1);
266	return(0);
267}
268
269/*
270 * cpio_rd()
271 *	determine if a buffer is a byte oriented extended cpio archive entry.
272 *	convert and store the values in the ARCHD parameter.
273 * Return:
274 *	0 if a valid header, -1 otherwise.
275 */
276
277int
278cpio_rd(ARCHD *arcn, char *buf)
279{
280	int nsz;
281	HD_CPIO *hd;
282
283	/*
284	 * check that this is a valid header, if not return -1
285	 */
286	if (cpio_id(buf, sizeof(HD_CPIO)) < 0)
287		return(-1);
288	hd = (HD_CPIO *)buf;
289
290	/*
291	 * byte oriented cpio (posix) does not have padding! extract the octal
292	 * ascii fields from the header
293	 */
294	arcn->pad = 0L;
295	arcn->sb.st_dev = (dev_t)asc_ul(hd->c_dev, sizeof(hd->c_dev), OCT);
296	arcn->sb.st_ino = (ino_t)asc_ul(hd->c_ino, sizeof(hd->c_ino), OCT);
297	arcn->sb.st_mode = (mode_t)asc_ul(hd->c_mode, sizeof(hd->c_mode), OCT);
298	arcn->sb.st_uid = (uid_t)asc_ul(hd->c_uid, sizeof(hd->c_uid), OCT);
299	arcn->sb.st_gid = (gid_t)asc_ul(hd->c_gid, sizeof(hd->c_gid), OCT);
300	arcn->sb.st_nlink = (nlink_t)asc_ul(hd->c_nlink, sizeof(hd->c_nlink),
301	    OCT);
302	arcn->sb.st_rdev = (dev_t)asc_ul(hd->c_rdev, sizeof(hd->c_rdev), OCT);
303#ifdef NET2_STAT
304	arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime, sizeof(hd->c_mtime),
305	    OCT);
306#else
307	arcn->sb.st_mtime = (time_t)asc_uqd(hd->c_mtime, sizeof(hd->c_mtime),
308	    OCT);
309#endif
310	arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
311#ifdef NET2_STAT
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	HD_CPIO hdblk;
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 = &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 NET2_STAT
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((char *)&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 < (int)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 < (int)sizeof(HD_VCPIO)) ||
537	    (strncmp(blk, AVCMAGIC, (int)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#ifdef NET2_STAT
595	arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime,sizeof(hd->c_mtime),HEX);
596#else
597	arcn->sb.st_mtime = (time_t)asc_uqd(hd->c_mtime,sizeof(hd->c_mtime),HEX);
598#endif
599	arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
600#ifdef NET2_STAT
601	arcn->sb.st_size = (off_t)asc_ul(hd->c_filesize,
602	    sizeof(hd->c_filesize), HEX);
603#else
604	arcn->sb.st_size = (off_t)asc_uqd(hd->c_filesize,
605	    sizeof(hd->c_filesize), HEX);
606#endif
607	arcn->sb.st_nlink = (nlink_t)asc_ul(hd->c_nlink, sizeof(hd->c_nlink),
608	    HEX);
609	devmajor = (dev_t)asc_ul(hd->c_maj, sizeof(hd->c_maj), HEX);
610	devminor = (dev_t)asc_ul(hd->c_min, sizeof(hd->c_min), HEX);
611	arcn->sb.st_dev = TODEV(devmajor, devminor);
612	devmajor = (dev_t)asc_ul(hd->c_rmaj, sizeof(hd->c_maj), HEX);
613	devminor = (dev_t)asc_ul(hd->c_rmin, sizeof(hd->c_min), HEX);
614	arcn->sb.st_rdev = TODEV(devmajor, devminor);
615	arcn->crc = asc_ul(hd->c_chksum, sizeof(hd->c_chksum), HEX);
616
617	/*
618	 * check the length of the file name, if ok read it in, return -1 if
619	 * bogus
620	 */
621	if ((nsz = (int)asc_ul(hd->c_namesize,sizeof(hd->c_namesize),HEX)) < 2)
622		return(-1);
623	arcn->nlen = nsz - 1;
624	if (rd_nm(arcn, nsz) < 0)
625		return(-1);
626
627	/*
628	 * skip padding. header + filename is aligned to 4 byte boundaries
629	 */
630	if (rd_skip((off_t)(VCPIO_PAD(sizeof(HD_VCPIO) + nsz))) < 0)
631		return(-1);
632
633	/*
634	 * if not a link (or a file with no data), calculate pad size (for
635	 * padding which follows the file data), clear the link name and return
636	 */
637	if (((arcn->sb.st_mode&C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)) {
638		/*
639		 * we have a valid header (not a link)
640		 */
641		arcn->ln_nlen = 0;
642		arcn->ln_name[0] = '\0';
643		arcn->pad = VCPIO_PAD(arcn->sb.st_size);
644		return(com_rd(arcn));
645	}
646
647	/*
648	 * read in the link name and skip over the padding
649	 */
650	if ((rd_ln_nm(arcn) < 0) ||
651	    (rd_skip((off_t)(VCPIO_PAD(arcn->sb.st_size))) < 0))
652		return(-1);
653
654	/*
655	 * we have a valid header (with a link)
656	 */
657	return(com_rd(arcn));
658}
659
660/*
661 * vcpio_endrd()
662 *      no cleanup needed here, just return size of the trailer (for append)
663 * Return:
664 *      size of trailer header in this format
665 */
666
667off_t
668vcpio_endrd(void)
669{
670	return((off_t)(sizeof(HD_VCPIO) + sizeof(TRAILER) +
671		(VCPIO_PAD(sizeof(HD_VCPIO) + sizeof(TRAILER)))));
672}
673
674/*
675 * crc_stwr()
676 *	start up the device mapping table, enable crc file calculation
677 * Return:
678 *	0 if ok, -1 otherwise (what dev_start() returns)
679 */
680
681int
682crc_stwr(void)
683{
684	docrc = 1;
685	return(dev_start());
686}
687
688/*
689 * vcpio_wr()
690 *	copy the data in the ARCHD to buffer in system VR4 cpio
691 *	(with/without crc) format.
692 * Return
693 *	0 if file has data to be written after the header, 1 if file has
694 *	NO data to write after the header, -1 if archive write failed
695 */
696
697int
698vcpio_wr(ARCHD *arcn)
699{
700	HD_VCPIO *hd;
701	unsigned int nsz;
702	HD_VCPIO hdblk;
703
704	/*
705	 * check and repair truncated device and inode fields in the cpio
706	 * header
707	 */
708	if (map_dev(arcn, (u_long)VCPIO_MASK, (u_long)VCPIO_MASK) < 0)
709		return(-1);
710	nsz = arcn->nlen + 1;
711	hd = &hdblk;
712	if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR))
713		arcn->sb.st_rdev = 0;
714
715	/*
716	 * add the proper magic value depending whether we were asked for
717	 * file data crc's, and the crc if needed.
718	 */
719	if (docrc) {
720		if (ul_asc((u_long)VCMAGIC, hd->c_magic, sizeof(hd->c_magic),
721	    		OCT) ||
722		    ul_asc((u_long)arcn->crc,hd->c_chksum,sizeof(hd->c_chksum),
723	    		HEX))
724			goto out;
725	} else {
726		if (ul_asc((u_long)VMAGIC, hd->c_magic, sizeof(hd->c_magic),
727	    		OCT) ||
728		    ul_asc((u_long)0L, hd->c_chksum, sizeof(hd->c_chksum),HEX))
729			goto out;
730	}
731
732	switch(arcn->type) {
733	case PAX_CTG:
734	case PAX_REG:
735	case PAX_HRG:
736		/*
737		 * caller will copy file data to the archive. tell him how
738		 * much to pad.
739		 */
740		arcn->pad = VCPIO_PAD(arcn->sb.st_size);
741#		ifdef NET2_STAT
742		if (ul_asc((u_long)arcn->sb.st_size, hd->c_filesize,
743		    sizeof(hd->c_filesize), HEX)) {
744#		else
745		if (uqd_asc((u_quad_t)arcn->sb.st_size, hd->c_filesize,
746		    sizeof(hd->c_filesize), HEX)) {
747#		endif
748			paxwarn(1,"File is too large for sv4cpio format %s",
749			    arcn->org_name);
750			return(1);
751		}
752		break;
753	case PAX_SLK:
754		/*
755		 * no file data for the caller to process, the file data has
756		 * the size of the link
757		 */
758		arcn->pad = 0L;
759		if (ul_asc((u_long)arcn->ln_nlen, hd->c_filesize,
760		    sizeof(hd->c_filesize), HEX))
761			goto out;
762		break;
763	default:
764		/*
765		 * no file data for the caller to process
766		 */
767		arcn->pad = 0L;
768		if (ul_asc((u_long)0L, hd->c_filesize, sizeof(hd->c_filesize),
769		    HEX))
770			goto out;
771		break;
772	}
773
774	/*
775	 * set the other fields in the header
776	 */
777	if (ul_asc((u_long)arcn->sb.st_ino, hd->c_ino, sizeof(hd->c_ino),
778		HEX) ||
779	    ul_asc((u_long)arcn->sb.st_mode, hd->c_mode, sizeof(hd->c_mode),
780		HEX) ||
781	    ul_asc((u_long)arcn->sb.st_uid, hd->c_uid, sizeof(hd->c_uid),
782		HEX) ||
783	    ul_asc((u_long)arcn->sb.st_gid, hd->c_gid, sizeof(hd->c_gid),
784    		HEX) ||
785	    ul_asc((u_long)arcn->sb.st_mtime, hd->c_mtime, sizeof(hd->c_mtime),
786    		HEX) ||
787	    ul_asc((u_long)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink),
788    		HEX) ||
789	    ul_asc((u_long)MAJOR(arcn->sb.st_dev),hd->c_maj, sizeof(hd->c_maj),
790		HEX) ||
791	    ul_asc((u_long)MINOR(arcn->sb.st_dev),hd->c_min, sizeof(hd->c_min),
792		HEX) ||
793	    ul_asc((u_long)MAJOR(arcn->sb.st_rdev),hd->c_rmaj,sizeof(hd->c_maj),
794		HEX) ||
795	    ul_asc((u_long)MINOR(arcn->sb.st_rdev),hd->c_rmin,sizeof(hd->c_min),
796		HEX) ||
797	    ul_asc((u_long)nsz, hd->c_namesize, sizeof(hd->c_namesize), HEX))
798		goto out;
799
800	/*
801	 * write the header, the file name and padding as required.
802	 */
803	if ((wr_rdbuf((char *)&hdblk, (int)sizeof(HD_VCPIO)) < 0) ||
804	    (wr_rdbuf(arcn->name, (int)nsz) < 0)  ||
805	    (wr_skip((off_t)(VCPIO_PAD(sizeof(HD_VCPIO) + nsz))) < 0)) {
806		paxwarn(1,"Could not write sv4cpio header for %s",arcn->org_name);
807		return(-1);
808	}
809
810	/*
811	 * if we have file data, tell the caller we are done, copy the file
812	 */
813	if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) ||
814	    (arcn->type == PAX_HRG))
815		return(0);
816
817	/*
818	 * if we are not a link, tell the caller we are done, go to next file
819	 */
820	if (arcn->type != PAX_SLK)
821		return(1);
822
823	/*
824	 * write the link name, tell the caller we are done.
825	 */
826	if ((wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) ||
827	    (wr_skip((off_t)(VCPIO_PAD(arcn->ln_nlen))) < 0)) {
828		paxwarn(1,"Could not write sv4cpio link name for %s",
829		    arcn->org_name);
830		return(-1);
831	}
832	return(1);
833
834    out:
835	/*
836	 * header field is out of range
837	 */
838	paxwarn(1,"Sv4cpio header field is too small for file %s",arcn->org_name);
839	return(1);
840}
841
842/*
843 * Routines common to the old binary header cpio
844 */
845
846/*
847 * bcpio_id()
848 *      determine if a block given to us is an old binary cpio header
849 *	(with/without header byte swapping)
850 * Return:
851 *      0 if a valid header, -1 otherwise
852 */
853
854int
855bcpio_id(char *blk, int size)
856{
857	if (size < (int)sizeof(HD_BCPIO))
858		return(-1);
859
860	/*
861	 * check both normal and byte swapped magic cookies
862	 */
863	if (((u_short)SHRT_EXT(blk)) == MAGIC)
864		return(0);
865	if (((u_short)RSHRT_EXT(blk)) == MAGIC) {
866		if (!swp_head)
867			++swp_head;
868		return(0);
869	}
870	return(-1);
871}
872
873/*
874 * bcpio_rd()
875 *	determine if a buffer is an old binary archive entry. (It may have byte
876 *	swapped header) convert and store the values in the ARCHD parameter.
877 *	This is a very old header format and should not really be used.
878 * Return:
879 *	0 if a valid header, -1 otherwise.
880 */
881
882int
883bcpio_rd(ARCHD *arcn, char *buf)
884{
885	HD_BCPIO *hd;
886	int nsz;
887
888	/*
889	 * check the header
890	 */
891	if (bcpio_id(buf, sizeof(HD_BCPIO)) < 0)
892		return(-1);
893
894	arcn->pad = 0L;
895	hd = (HD_BCPIO *)buf;
896	if (swp_head) {
897		/*
898		 * header has swapped bytes on 16 bit boundaries
899		 */
900		arcn->sb.st_dev = (dev_t)(RSHRT_EXT(hd->h_dev));
901		arcn->sb.st_ino = (ino_t)(RSHRT_EXT(hd->h_ino));
902		arcn->sb.st_mode = (mode_t)(RSHRT_EXT(hd->h_mode));
903		arcn->sb.st_uid = (uid_t)(RSHRT_EXT(hd->h_uid));
904		arcn->sb.st_gid = (gid_t)(RSHRT_EXT(hd->h_gid));
905		arcn->sb.st_nlink = (nlink_t)(RSHRT_EXT(hd->h_nlink));
906		arcn->sb.st_rdev = (dev_t)(RSHRT_EXT(hd->h_rdev));
907		arcn->sb.st_mtime = (time_t)(RSHRT_EXT(hd->h_mtime_1));
908		arcn->sb.st_mtime =  (arcn->sb.st_mtime << 16) |
909			((time_t)(RSHRT_EXT(hd->h_mtime_2)));
910		arcn->sb.st_size = (off_t)(RSHRT_EXT(hd->h_filesize_1));
911		arcn->sb.st_size = (arcn->sb.st_size << 16) |
912			((off_t)(RSHRT_EXT(hd->h_filesize_2)));
913		nsz = (int)(RSHRT_EXT(hd->h_namesize));
914	} else {
915		arcn->sb.st_dev = (dev_t)(SHRT_EXT(hd->h_dev));
916		arcn->sb.st_ino = (ino_t)(SHRT_EXT(hd->h_ino));
917		arcn->sb.st_mode = (mode_t)(SHRT_EXT(hd->h_mode));
918		arcn->sb.st_uid = (uid_t)(SHRT_EXT(hd->h_uid));
919		arcn->sb.st_gid = (gid_t)(SHRT_EXT(hd->h_gid));
920		arcn->sb.st_nlink = (nlink_t)(SHRT_EXT(hd->h_nlink));
921		arcn->sb.st_rdev = (dev_t)(SHRT_EXT(hd->h_rdev));
922		arcn->sb.st_mtime = (time_t)(SHRT_EXT(hd->h_mtime_1));
923		arcn->sb.st_mtime =  (arcn->sb.st_mtime << 16) |
924			((time_t)(SHRT_EXT(hd->h_mtime_2)));
925		arcn->sb.st_size = (off_t)(SHRT_EXT(hd->h_filesize_1));
926		arcn->sb.st_size = (arcn->sb.st_size << 16) |
927			((off_t)(SHRT_EXT(hd->h_filesize_2)));
928		nsz = (int)(SHRT_EXT(hd->h_namesize));
929	}
930	arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
931
932	/*
933	 * check the file name size, if bogus give up. otherwise read the file
934	 * name
935	 */
936	if (nsz < 2)
937		return(-1);
938	arcn->nlen = nsz - 1;
939	if (rd_nm(arcn, nsz) < 0)
940		return(-1);
941
942	/*
943	 * header + file name are aligned to 2 byte boundaries, skip if needed
944	 */
945	if (rd_skip((off_t)(BCPIO_PAD(sizeof(HD_BCPIO) + nsz))) < 0)
946		return(-1);
947
948	/*
949	 * if not a link (or a file with no data), calculate pad size (for
950	 * padding which follows the file data), clear the link name and return
951	 */
952	if (((arcn->sb.st_mode & C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)){
953		/*
954		 * we have a valid header (not a link)
955		 */
956		arcn->ln_nlen = 0;
957		arcn->ln_name[0] = '\0';
958		arcn->pad = BCPIO_PAD(arcn->sb.st_size);
959		return(com_rd(arcn));
960	}
961
962	if ((rd_ln_nm(arcn) < 0) ||
963	    (rd_skip((off_t)(BCPIO_PAD(arcn->sb.st_size))) < 0))
964		return(-1);
965
966	/*
967	 * we have a valid header (with a link)
968	 */
969	return(com_rd(arcn));
970}
971
972/*
973 * bcpio_endrd()
974 *      no cleanup needed here, just return size of the trailer (for append)
975 * Return:
976 *      size of trailer header in this format
977 */
978
979off_t
980bcpio_endrd(void)
981{
982	return((off_t)(sizeof(HD_BCPIO) + sizeof(TRAILER) +
983		(BCPIO_PAD(sizeof(HD_BCPIO) + sizeof(TRAILER)))));
984}
985
986/*
987 * bcpio_wr()
988 *	copy the data in the ARCHD to buffer in old binary cpio format
989 *	There is a real chance of field overflow with this critter. So we
990 *	always check that the conversion is ok. nobody in their right mind
991 *	should write an archive in this format...
992 * Return
993 *      0 if file has data to be written after the header, 1 if file has NO
994 *	data to write after the header, -1 if archive write failed
995 */
996
997int
998bcpio_wr(ARCHD *arcn)
999{
1000	HD_BCPIO *hd;
1001	int nsz;
1002	HD_BCPIO hdblk;
1003	off_t t_offt;
1004	int t_int;
1005	time_t t_timet;
1006
1007	/*
1008	 * check and repair truncated device and inode fields in the cpio
1009	 * header
1010	 */
1011	if (map_dev(arcn, (u_long)BCPIO_MASK, (u_long)BCPIO_MASK) < 0)
1012		return(-1);
1013
1014	if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR))
1015		arcn->sb.st_rdev = 0;
1016	hd = &hdblk;
1017
1018	switch(arcn->type) {
1019	case PAX_CTG:
1020	case PAX_REG:
1021	case PAX_HRG:
1022		/*
1023		 * caller will copy file data to the archive. tell him how
1024		 * much to pad.
1025		 */
1026		arcn->pad = BCPIO_PAD(arcn->sb.st_size);
1027		hd->h_filesize_1[0] = CHR_WR_0(arcn->sb.st_size);
1028		hd->h_filesize_1[1] = CHR_WR_1(arcn->sb.st_size);
1029		hd->h_filesize_2[0] = CHR_WR_2(arcn->sb.st_size);
1030		hd->h_filesize_2[1] = CHR_WR_3(arcn->sb.st_size);
1031		t_offt = (off_t)(SHRT_EXT(hd->h_filesize_1));
1032		t_offt = (t_offt<<16) | ((off_t)(SHRT_EXT(hd->h_filesize_2)));
1033		if (arcn->sb.st_size != t_offt) {
1034			paxwarn(1,"File is too large for bcpio format %s",
1035			    arcn->org_name);
1036			return(1);
1037		}
1038		break;
1039	case PAX_SLK:
1040		/*
1041		 * no file data for the caller to process, the file data has
1042		 * the size of the link
1043		 */
1044		arcn->pad = 0L;
1045		hd->h_filesize_1[0] = CHR_WR_0(arcn->ln_nlen);
1046		hd->h_filesize_1[1] = CHR_WR_1(arcn->ln_nlen);
1047		hd->h_filesize_2[0] = CHR_WR_2(arcn->ln_nlen);
1048		hd->h_filesize_2[1] = CHR_WR_3(arcn->ln_nlen);
1049		t_int = (int)(SHRT_EXT(hd->h_filesize_1));
1050		t_int = (t_int << 16) | ((int)(SHRT_EXT(hd->h_filesize_2)));
1051		if (arcn->ln_nlen != t_int)
1052			goto out;
1053		break;
1054	default:
1055		/*
1056		 * no file data for the caller to process
1057		 */
1058		arcn->pad = 0L;
1059		hd->h_filesize_1[0] = (char)0;
1060		hd->h_filesize_1[1] = (char)0;
1061		hd->h_filesize_2[0] = (char)0;
1062		hd->h_filesize_2[1] = (char)0;
1063		break;
1064	}
1065
1066	/*
1067	 * build up the rest of the fields
1068	 */
1069	hd->h_magic[0] = CHR_WR_2(MAGIC);
1070	hd->h_magic[1] = CHR_WR_3(MAGIC);
1071	hd->h_dev[0] = CHR_WR_2(arcn->sb.st_dev);
1072	hd->h_dev[1] = CHR_WR_3(arcn->sb.st_dev);
1073	if (arcn->sb.st_dev != (dev_t)(SHRT_EXT(hd->h_dev)))
1074		goto out;
1075	hd->h_ino[0] = CHR_WR_2(arcn->sb.st_ino);
1076	hd->h_ino[1] = CHR_WR_3(arcn->sb.st_ino);
1077	if (arcn->sb.st_ino != (ino_t)(SHRT_EXT(hd->h_ino)))
1078		goto out;
1079	hd->h_mode[0] = CHR_WR_2(arcn->sb.st_mode);
1080	hd->h_mode[1] = CHR_WR_3(arcn->sb.st_mode);
1081	if (arcn->sb.st_mode != (mode_t)(SHRT_EXT(hd->h_mode)))
1082		goto out;
1083	hd->h_uid[0] = CHR_WR_2(arcn->sb.st_uid);
1084	hd->h_uid[1] = CHR_WR_3(arcn->sb.st_uid);
1085	if (arcn->sb.st_uid != (uid_t)(SHRT_EXT(hd->h_uid)))
1086		goto out;
1087	hd->h_gid[0] = CHR_WR_2(arcn->sb.st_gid);
1088	hd->h_gid[1] = CHR_WR_3(arcn->sb.st_gid);
1089	if (arcn->sb.st_gid != (gid_t)(SHRT_EXT(hd->h_gid)))
1090		goto out;
1091	hd->h_nlink[0] = CHR_WR_2(arcn->sb.st_nlink);
1092	hd->h_nlink[1] = CHR_WR_3(arcn->sb.st_nlink);
1093	if (arcn->sb.st_nlink != (nlink_t)(SHRT_EXT(hd->h_nlink)))
1094		goto out;
1095	hd->h_rdev[0] = CHR_WR_2(arcn->sb.st_rdev);
1096	hd->h_rdev[1] = CHR_WR_3(arcn->sb.st_rdev);
1097	if (arcn->sb.st_rdev != (dev_t)(SHRT_EXT(hd->h_rdev)))
1098		goto out;
1099	hd->h_mtime_1[0] = CHR_WR_0(arcn->sb.st_mtime);
1100	hd->h_mtime_1[1] = CHR_WR_1(arcn->sb.st_mtime);
1101	hd->h_mtime_2[0] = CHR_WR_2(arcn->sb.st_mtime);
1102	hd->h_mtime_2[1] = CHR_WR_3(arcn->sb.st_mtime);
1103	t_timet = (time_t)(SHRT_EXT(hd->h_mtime_1));
1104	t_timet =  (t_timet << 16) | ((time_t)(SHRT_EXT(hd->h_mtime_2)));
1105	if (arcn->sb.st_mtime != t_timet)
1106		goto out;
1107	nsz = arcn->nlen + 1;
1108	hd->h_namesize[0] = CHR_WR_2(nsz);
1109	hd->h_namesize[1] = CHR_WR_3(nsz);
1110	if (nsz != (int)(SHRT_EXT(hd->h_namesize)))
1111		goto out;
1112
1113	/*
1114	 * write the header, the file name and padding as required.
1115	 */
1116	if ((wr_rdbuf((char *)&hdblk, (int)sizeof(HD_BCPIO)) < 0) ||
1117	    (wr_rdbuf(arcn->name, nsz) < 0) ||
1118	    (wr_skip((off_t)(BCPIO_PAD(sizeof(HD_BCPIO) + nsz))) < 0)) {
1119		paxwarn(1, "Could not write bcpio header for %s", arcn->org_name);
1120		return(-1);
1121	}
1122
1123	/*
1124	 * if we have file data, tell the caller we are done
1125	 */
1126	if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) ||
1127	    (arcn->type == PAX_HRG))
1128		return(0);
1129
1130	/*
1131	 * if we are not a link, tell the caller we are done, go to next file
1132	 */
1133	if (arcn->type != PAX_SLK)
1134		return(1);
1135
1136	/*
1137	 * write the link name, tell the caller we are done.
1138	 */
1139	if ((wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) ||
1140	    (wr_skip((off_t)(BCPIO_PAD(arcn->ln_nlen))) < 0)) {
1141		paxwarn(1,"Could not write bcpio link name for %s",arcn->org_name);
1142		return(-1);
1143	}
1144	return(1);
1145
1146    out:
1147	/*
1148	 * header field is out of range
1149	 */
1150	paxwarn(1,"Bcpio header field is too small for file %s", arcn->org_name);
1151	return(1);
1152}
1153