cpio.c revision 90113
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 * 3. All advertising materials mentioning features or use of this software
18 *    must display the following acknowledgement:
19 *	This product includes software developed by the University of
20 *	California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 *    may be used to endorse or promote products derived from this software
23 *    without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 */
37
38#ifndef lint
39#if 0
40static char sccsid[] = "@(#)cpio.c	8.1 (Berkeley) 5/31/93";
41#endif
42static const char rcsid[] =
43  "$FreeBSD: head/bin/pax/cpio.c 90113 2002-02-02 07:07:59Z imp $";
44#endif /* not lint */
45
46#include <sys/types.h>
47#include <sys/time.h>
48#include <sys/stat.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)
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_end_wr()
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)strcpy(last.name, TRAILER);
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 NET2_STAT
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 = 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#ifdef NET2_STAT
309	arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime, sizeof(hd->c_mtime),
310	    OCT);
311#else
312	arcn->sb.st_mtime = (time_t)asc_uqd(hd->c_mtime, sizeof(hd->c_mtime),
313	    OCT);
314#endif
315	arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
316#ifdef NET2_STAT
317	arcn->sb.st_size = (off_t)asc_ul(hd->c_filesize,sizeof(hd->c_filesize),
318	    OCT);
319#else
320	arcn->sb.st_size = (off_t)asc_uqd(hd->c_filesize,sizeof(hd->c_filesize),
321	    OCT);
322#endif
323
324	/*
325	 * check name size and if valid, read in the name of this entry (name
326	 * follows header in the archive)
327	 */
328	if ((nsz = (int)asc_ul(hd->c_namesize,sizeof(hd->c_namesize),OCT)) < 2)
329		return(-1);
330	arcn->nlen = nsz - 1;
331	if (rd_nm(arcn, nsz) < 0)
332		return(-1);
333
334	if (((arcn->sb.st_mode&C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)) {
335		/*
336	 	 * no link name to read for this file
337	 	 */
338		arcn->ln_nlen = 0;
339		arcn->ln_name[0] = '\0';
340		return(com_rd(arcn));
341	}
342
343	/*
344	 * check link name size and read in the link name. Link names are
345	 * stored like file data.
346	 */
347	if (rd_ln_nm(arcn) < 0)
348		return(-1);
349
350	/*
351	 * we have a valid header (with a link)
352	 */
353	return(com_rd(arcn));
354}
355
356/*
357 * cpio_endrd()
358 *      no cleanup needed here, just return size of the trailer (for append)
359 * Return:
360 *      size of trailer header in this format
361 */
362
363off_t
364cpio_endrd(void)
365{
366	return((off_t)(sizeof(HD_CPIO) + sizeof(TRAILER)));
367}
368
369/*
370 * cpio_stwr()
371 *	start up the device mapping table
372 * Return:
373 *	0 if ok, -1 otherwise (what dev_start() returns)
374 */
375
376int
377cpio_stwr(void)
378{
379	return(dev_start());
380}
381
382/*
383 * cpio_wr()
384 *	copy the data in the ARCHD to buffer in extended byte oriented cpio
385 *	format.
386 * Return
387 *      0 if file has data to be written after the header, 1 if file has NO
388 *	data to write after the header, -1 if archive write failed
389 */
390
391int
392cpio_wr(ARCHD *arcn)
393{
394	HD_CPIO *hd;
395	int nsz;
396	char hdblk[sizeof(HD_CPIO)];
397
398	/*
399	 * check and repair truncated device and inode fields in the header
400	 */
401	if (map_dev(arcn, (u_long)CPIO_MASK, (u_long)CPIO_MASK) < 0)
402		return(-1);
403
404	arcn->pad = 0L;
405	nsz = arcn->nlen + 1;
406	hd = (HD_CPIO *)hdblk;
407	if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR))
408		arcn->sb.st_rdev = 0;
409
410	switch(arcn->type) {
411	case PAX_CTG:
412	case PAX_REG:
413	case PAX_HRG:
414		/*
415		 * set data size for file data
416		 */
417#		ifdef NET2_STAT
418		if (ul_asc((u_long)arcn->sb.st_size, hd->c_filesize,
419		    sizeof(hd->c_filesize), OCT)) {
420#		else
421		if (uqd_asc((u_quad_t)arcn->sb.st_size, hd->c_filesize,
422		    sizeof(hd->c_filesize), OCT)) {
423#		endif
424			paxwarn(1,"File is too large for cpio format %s",
425			    arcn->org_name);
426			return(1);
427		}
428		break;
429	case PAX_SLK:
430		/*
431		 * set data size to hold link name
432		 */
433		if (ul_asc((u_long)arcn->ln_nlen, hd->c_filesize,
434		    sizeof(hd->c_filesize), OCT))
435			goto out;
436		break;
437	default:
438		/*
439		 * all other file types have no file data
440		 */
441		if (ul_asc((u_long)0, hd->c_filesize, sizeof(hd->c_filesize),
442		     OCT))
443			goto out;
444		break;
445	}
446
447	/*
448	 * copy the values to the header using octal ascii
449	 */
450	if (ul_asc((u_long)MAGIC, hd->c_magic, sizeof(hd->c_magic), OCT) ||
451	    ul_asc((u_long)arcn->sb.st_dev, hd->c_dev, sizeof(hd->c_dev),
452		OCT) ||
453	    ul_asc((u_long)arcn->sb.st_ino, hd->c_ino, sizeof(hd->c_ino),
454		OCT) ||
455	    ul_asc((u_long)arcn->sb.st_mode, hd->c_mode, sizeof(hd->c_mode),
456		OCT) ||
457	    ul_asc((u_long)arcn->sb.st_uid, hd->c_uid, sizeof(hd->c_uid),
458		OCT) ||
459	    ul_asc((u_long)arcn->sb.st_gid, hd->c_gid, sizeof(hd->c_gid),
460		OCT) ||
461	    ul_asc((u_long)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink),
462		 OCT) ||
463	    ul_asc((u_long)arcn->sb.st_rdev, hd->c_rdev, sizeof(hd->c_rdev),
464		OCT) ||
465	    ul_asc((u_long)arcn->sb.st_mtime,hd->c_mtime,sizeof(hd->c_mtime),
466		OCT) ||
467	    ul_asc((u_long)nsz, hd->c_namesize, sizeof(hd->c_namesize), OCT))
468		goto out;
469
470	/*
471	 * write the file name to the archive
472	 */
473	if ((wr_rdbuf(hdblk, (int)sizeof(HD_CPIO)) < 0) ||
474	    (wr_rdbuf(arcn->name, nsz) < 0)) {
475		paxwarn(1, "Unable to write cpio header for %s", arcn->org_name);
476		return(-1);
477	}
478
479	/*
480	 * if this file has data, we are done. The caller will write the file
481	 * data, if we are link tell caller we are done, go to next file
482	 */
483	if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) ||
484	    (arcn->type == PAX_HRG))
485		return(0);
486	if (arcn->type != PAX_SLK)
487		return(1);
488
489	/*
490	 * write the link name to the archive, tell the caller to go to the
491	 * next file as we are done.
492	 */
493	if (wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) {
494		paxwarn(1,"Unable to write cpio link name for %s",arcn->org_name);
495		return(-1);
496	}
497	return(1);
498
499    out:
500	/*
501	 * header field is out of range
502	 */
503	paxwarn(1, "Cpio header field is too small to store file %s",
504	    arcn->org_name);
505	return(1);
506}
507
508/*
509 * Routines common to the system VR4 version of cpio (with/without file CRC)
510 */
511
512/*
513 * vcpio_id()
514 *      determine if a block given to us is a valid system VR4 cpio header
515 *	WITHOUT crc. WATCH it the magic cookies are in OCTAL, the header
516 *	uses HEX
517 * Return:
518 *      0 if a valid header, -1 otherwise
519 */
520
521int
522vcpio_id(char *blk, int size)
523{
524	if ((size < sizeof(HD_VCPIO)) ||
525	    (strncmp(blk, AVMAGIC, sizeof(AVMAGIC) - 1) != 0))
526		return(-1);
527	return(0);
528}
529
530/*
531 * crc_id()
532 *      determine if a block given to us is a valid system VR4 cpio header
533 *	WITH crc. WATCH it the magic cookies are in OCTAL the header uses HEX
534 * Return:
535 *      0 if a valid header, -1 otherwise
536 */
537
538int
539crc_id(char *blk, int size)
540{
541	if ((size < sizeof(HD_VCPIO)) ||
542	    (strncmp(blk, AVCMAGIC, sizeof(AVCMAGIC) - 1) != 0))
543		return(-1);
544	return(0);
545}
546
547/*
548 * crc_strd()
549 w	set file data CRC calculations. Fire up the hard link detection code
550 * Return:
551 *      0 if ok -1 otherwise (the return values of lnk_start())
552 */
553
554int
555crc_strd(void)
556{
557	docrc = 1;
558	return(lnk_start());
559}
560
561/*
562 * vcpio_rd()
563 *	determine if a buffer is a system VR4 archive entry. (with/without CRC)
564 *	convert and store the values in the ARCHD parameter.
565 * Return:
566 *	0 if a valid header, -1 otherwise.
567 */
568
569int
570vcpio_rd(ARCHD *arcn, char *buf)
571{
572	HD_VCPIO *hd;
573	dev_t devminor;
574	dev_t devmajor;
575	int nsz;
576
577	/*
578	 * during the id phase it was determined if we were using CRC, use the
579	 * proper id routine.
580	 */
581	if (docrc) {
582		if (crc_id(buf, sizeof(HD_VCPIO)) < 0)
583			return(-1);
584	} else {
585		if (vcpio_id(buf, sizeof(HD_VCPIO)) < 0)
586			return(-1);
587	}
588
589	hd = (HD_VCPIO *)buf;
590	arcn->pad = 0L;
591
592	/*
593	 * extract the hex ascii fields from the header
594	 */
595	arcn->sb.st_ino = (ino_t)asc_ul(hd->c_ino, sizeof(hd->c_ino), HEX);
596	arcn->sb.st_mode = (mode_t)asc_ul(hd->c_mode, sizeof(hd->c_mode), HEX);
597	arcn->sb.st_uid = (uid_t)asc_ul(hd->c_uid, sizeof(hd->c_uid), HEX);
598	arcn->sb.st_gid = (gid_t)asc_ul(hd->c_gid, sizeof(hd->c_gid), HEX);
599#ifdef NET2_STAT
600	arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime,sizeof(hd->c_mtime),HEX);
601#else
602	arcn->sb.st_mtime = (time_t)asc_uqd(hd->c_mtime,sizeof(hd->c_mtime),HEX);
603#endif
604	arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
605#ifdef NET2_STAT
606	arcn->sb.st_size = (off_t)asc_ul(hd->c_filesize,
607	    sizeof(hd->c_filesize), HEX);
608#else
609	arcn->sb.st_size = (off_t)asc_uqd(hd->c_filesize,
610	    sizeof(hd->c_filesize), HEX);
611#endif
612	arcn->sb.st_nlink = (nlink_t)asc_ul(hd->c_nlink, sizeof(hd->c_nlink),
613	    HEX);
614	devmajor = (dev_t)asc_ul(hd->c_maj, sizeof(hd->c_maj), HEX);
615	devminor = (dev_t)asc_ul(hd->c_min, sizeof(hd->c_min), HEX);
616	arcn->sb.st_dev = TODEV(devmajor, devminor);
617	devmajor = (dev_t)asc_ul(hd->c_rmaj, sizeof(hd->c_maj), HEX);
618	devminor = (dev_t)asc_ul(hd->c_rmin, sizeof(hd->c_min), HEX);
619	arcn->sb.st_rdev = TODEV(devmajor, devminor);
620	arcn->crc = asc_ul(hd->c_chksum, sizeof(hd->c_chksum), HEX);
621
622	/*
623	 * check the length of the file name, if ok read it in, return -1 if
624	 * bogus
625	 */
626	if ((nsz = (int)asc_ul(hd->c_namesize,sizeof(hd->c_namesize),HEX)) < 2)
627		return(-1);
628	arcn->nlen = nsz - 1;
629	if (rd_nm(arcn, nsz) < 0)
630		return(-1);
631
632	/*
633	 * skip padding. header + filename is aligned to 4 byte boundries
634	 */
635	if (rd_skip((off_t)(VCPIO_PAD(sizeof(HD_VCPIO) + nsz))) < 0)
636		return(-1);
637
638	/*
639	 * if not a link (or a file with no data), calculate pad size (for
640	 * padding which follows the file data), clear the link name and return
641	 */
642	if (((arcn->sb.st_mode&C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)) {
643		/*
644		 * we have a valid header (not a link)
645		 */
646		arcn->ln_nlen = 0;
647		arcn->ln_name[0] = '\0';
648		arcn->pad = VCPIO_PAD(arcn->sb.st_size);
649		return(com_rd(arcn));
650	}
651
652	/*
653	 * read in the link name and skip over the padding
654	 */
655	if ((rd_ln_nm(arcn) < 0) ||
656	    (rd_skip((off_t)(VCPIO_PAD(arcn->sb.st_size))) < 0))
657		return(-1);
658
659	/*
660	 * we have a valid header (with a link)
661	 */
662	return(com_rd(arcn));
663}
664
665/*
666 * vcpio_endrd()
667 *      no cleanup needed here, just return size of the trailer (for append)
668 * Return:
669 *      size of trailer header in this format
670 */
671
672off_t
673vcpio_endrd(void)
674{
675	return((off_t)(sizeof(HD_VCPIO) + sizeof(TRAILER) +
676		(VCPIO_PAD(sizeof(HD_VCPIO) + sizeof(TRAILER)))));
677}
678
679/*
680 * crc_stwr()
681 *	start up the device mapping table, enable crc file calculation
682 * Return:
683 *	0 if ok, -1 otherwise (what dev_start() returns)
684 */
685
686int
687crc_stwr(void)
688{
689	docrc = 1;
690	return(dev_start());
691}
692
693/*
694 * vcpio_wr()
695 *	copy the data in the ARCHD to buffer in system VR4 cpio
696 *	(with/without crc) format.
697 * Return
698 *	0 if file has data to be written after the header, 1 if file has
699 *	NO data to write after the header, -1 if archive write failed
700 */
701
702int
703vcpio_wr(ARCHD *arcn)
704{
705	HD_VCPIO *hd;
706	unsigned int nsz;
707	char hdblk[sizeof(HD_VCPIO)];
708
709	/*
710	 * check and repair truncated device and inode fields in the cpio
711	 * header
712	 */
713	if (map_dev(arcn, (u_long)VCPIO_MASK, (u_long)VCPIO_MASK) < 0)
714		return(-1);
715	nsz = arcn->nlen + 1;
716	hd = (HD_VCPIO *)hdblk;
717	if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR))
718		arcn->sb.st_rdev = 0;
719
720	/*
721	 * add the proper magic value depending whether we were asked for
722	 * file data crc's, and the crc if needed.
723	 */
724	if (docrc) {
725		if (ul_asc((u_long)VCMAGIC, hd->c_magic, sizeof(hd->c_magic),
726	    		OCT) ||
727		    ul_asc((u_long)arcn->crc,hd->c_chksum,sizeof(hd->c_chksum),
728	    		HEX))
729			goto out;
730	} else {
731		if (ul_asc((u_long)VMAGIC, hd->c_magic, sizeof(hd->c_magic),
732	    		OCT) ||
733		    ul_asc((u_long)0L, hd->c_chksum, sizeof(hd->c_chksum),HEX))
734			goto out;
735	}
736
737	switch(arcn->type) {
738	case PAX_CTG:
739	case PAX_REG:
740	case PAX_HRG:
741		/*
742		 * caller will copy file data to the archive. tell him how
743		 * much to pad.
744		 */
745		arcn->pad = VCPIO_PAD(arcn->sb.st_size);
746#		ifdef NET2_STAT
747		if (ul_asc((u_long)arcn->sb.st_size, hd->c_filesize,
748		    sizeof(hd->c_filesize), HEX)) {
749#		else
750		if (uqd_asc((u_quad_t)arcn->sb.st_size, hd->c_filesize,
751		    sizeof(hd->c_filesize), HEX)) {
752#		endif
753			paxwarn(1,"File is too large for sv4cpio format %s",
754			    arcn->org_name);
755			return(1);
756		}
757		break;
758	case PAX_SLK:
759		/*
760		 * no file data for the caller to process, the file data has
761		 * the size of the link
762		 */
763		arcn->pad = 0L;
764		if (ul_asc((u_long)arcn->ln_nlen, hd->c_filesize,
765		    sizeof(hd->c_filesize), HEX))
766			goto out;
767		break;
768	default:
769		/*
770		 * no file data for the caller to process
771		 */
772		arcn->pad = 0L;
773		if (ul_asc((u_long)0L, hd->c_filesize, sizeof(hd->c_filesize),
774		    HEX))
775			goto out;
776		break;
777	}
778
779	/*
780	 * set the other fields in the header
781	 */
782	if (ul_asc((u_long)arcn->sb.st_ino, hd->c_ino, sizeof(hd->c_ino),
783		HEX) ||
784	    ul_asc((u_long)arcn->sb.st_mode, hd->c_mode, sizeof(hd->c_mode),
785		HEX) ||
786	    ul_asc((u_long)arcn->sb.st_uid, hd->c_uid, sizeof(hd->c_uid),
787		HEX) ||
788	    ul_asc((u_long)arcn->sb.st_gid, hd->c_gid, sizeof(hd->c_gid),
789    		HEX) ||
790	    ul_asc((u_long)arcn->sb.st_mtime, hd->c_mtime, sizeof(hd->c_mtime),
791    		HEX) ||
792	    ul_asc((u_long)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink),
793    		HEX) ||
794	    ul_asc((u_long)MAJOR(arcn->sb.st_dev),hd->c_maj, sizeof(hd->c_maj),
795		HEX) ||
796	    ul_asc((u_long)MINOR(arcn->sb.st_dev),hd->c_min, sizeof(hd->c_min),
797		HEX) ||
798	    ul_asc((u_long)MAJOR(arcn->sb.st_rdev),hd->c_rmaj,sizeof(hd->c_maj),
799		HEX) ||
800	    ul_asc((u_long)MINOR(arcn->sb.st_rdev),hd->c_rmin,sizeof(hd->c_min),
801		HEX) ||
802	    ul_asc((u_long)nsz, hd->c_namesize, sizeof(hd->c_namesize), HEX))
803		goto out;
804
805	/*
806	 * write the header, the file name and padding as required.
807	 */
808	if ((wr_rdbuf(hdblk, (int)sizeof(HD_VCPIO)) < 0) ||
809	    (wr_rdbuf(arcn->name, (int)nsz) < 0)  ||
810	    (wr_skip((off_t)(VCPIO_PAD(sizeof(HD_VCPIO) + nsz))) < 0)) {
811		paxwarn(1,"Could not write sv4cpio header for %s",arcn->org_name);
812		return(-1);
813	}
814
815	/*
816	 * if we have file data, tell the caller we are done, copy the file
817	 */
818	if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) ||
819	    (arcn->type == PAX_HRG))
820		return(0);
821
822	/*
823	 * if we are not a link, tell the caller we are done, go to next file
824	 */
825	if (arcn->type != PAX_SLK)
826		return(1);
827
828	/*
829	 * write the link name, tell the caller we are done.
830	 */
831	if ((wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) ||
832	    (wr_skip((off_t)(VCPIO_PAD(arcn->ln_nlen))) < 0)) {
833		paxwarn(1,"Could not write sv4cpio link name for %s",
834		    arcn->org_name);
835		return(-1);
836	}
837	return(1);
838
839    out:
840	/*
841	 * header field is out of range
842	 */
843	paxwarn(1,"Sv4cpio header field is too small for file %s",arcn->org_name);
844	return(1);
845}
846
847/*
848 * Routines common to the old binary header cpio
849 */
850
851/*
852 * bcpio_id()
853 *      determine if a block given to us is a old binary cpio header
854 *	(with/without header byte swapping)
855 * Return:
856 *      0 if a valid header, -1 otherwise
857 */
858
859int
860bcpio_id(char *blk, int size)
861{
862	if (size < sizeof(HD_BCPIO))
863		return(-1);
864
865	/*
866	 * check both normal and byte swapped magic cookies
867	 */
868	if (((u_short)SHRT_EXT(blk)) == MAGIC)
869		return(0);
870	if (((u_short)RSHRT_EXT(blk)) == MAGIC) {
871		if (!swp_head)
872			++swp_head;
873		return(0);
874	}
875	return(-1);
876}
877
878/*
879 * bcpio_rd()
880 *	determine if a buffer is a old binary archive entry. (it may have byte
881 *	swapped header) convert and store the values in the ARCHD parameter.
882 *	This is a very old header format and should not really be used.
883 * Return:
884 *	0 if a valid header, -1 otherwise.
885 */
886
887int
888bcpio_rd(ARCHD *arcn, char *buf)
889{
890	HD_BCPIO *hd;
891	int nsz;
892
893	/*
894	 * check the header
895	 */
896	if (bcpio_id(buf, sizeof(HD_BCPIO)) < 0)
897		return(-1);
898
899	arcn->pad = 0L;
900	hd = (HD_BCPIO *)buf;
901	if (swp_head) {
902		/*
903		 * header has swapped bytes on 16 bit boundaries
904		 */
905		arcn->sb.st_dev = (dev_t)(RSHRT_EXT(hd->h_dev));
906		arcn->sb.st_ino = (ino_t)(RSHRT_EXT(hd->h_ino));
907		arcn->sb.st_mode = (mode_t)(RSHRT_EXT(hd->h_mode));
908		arcn->sb.st_uid = (uid_t)(RSHRT_EXT(hd->h_uid));
909		arcn->sb.st_gid = (gid_t)(RSHRT_EXT(hd->h_gid));
910		arcn->sb.st_nlink = (nlink_t)(RSHRT_EXT(hd->h_nlink));
911		arcn->sb.st_rdev = (dev_t)(RSHRT_EXT(hd->h_rdev));
912		arcn->sb.st_mtime = (time_t)(RSHRT_EXT(hd->h_mtime_1));
913		arcn->sb.st_mtime =  (arcn->sb.st_mtime << 16) |
914			((time_t)(RSHRT_EXT(hd->h_mtime_2)));
915		arcn->sb.st_size = (off_t)(RSHRT_EXT(hd->h_filesize_1));
916		arcn->sb.st_size = (arcn->sb.st_size << 16) |
917			((off_t)(RSHRT_EXT(hd->h_filesize_2)));
918		nsz = (int)(RSHRT_EXT(hd->h_namesize));
919	} else {
920		arcn->sb.st_dev = (dev_t)(SHRT_EXT(hd->h_dev));
921		arcn->sb.st_ino = (ino_t)(SHRT_EXT(hd->h_ino));
922		arcn->sb.st_mode = (mode_t)(SHRT_EXT(hd->h_mode));
923		arcn->sb.st_uid = (uid_t)(SHRT_EXT(hd->h_uid));
924		arcn->sb.st_gid = (gid_t)(SHRT_EXT(hd->h_gid));
925		arcn->sb.st_nlink = (nlink_t)(SHRT_EXT(hd->h_nlink));
926		arcn->sb.st_rdev = (dev_t)(SHRT_EXT(hd->h_rdev));
927		arcn->sb.st_mtime = (time_t)(SHRT_EXT(hd->h_mtime_1));
928		arcn->sb.st_mtime =  (arcn->sb.st_mtime << 16) |
929			((time_t)(SHRT_EXT(hd->h_mtime_2)));
930		arcn->sb.st_size = (off_t)(SHRT_EXT(hd->h_filesize_1));
931		arcn->sb.st_size = (arcn->sb.st_size << 16) |
932			((off_t)(SHRT_EXT(hd->h_filesize_2)));
933		nsz = (int)(SHRT_EXT(hd->h_namesize));
934	}
935	arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
936
937	/*
938	 * check the file name size, if bogus give up. otherwise read the file
939	 * name
940	 */
941	if (nsz < 2)
942		return(-1);
943	arcn->nlen = nsz - 1;
944	if (rd_nm(arcn, nsz) < 0)
945		return(-1);
946
947	/*
948	 * header + file name are aligned to 2 byte boundries, skip if needed
949	 */
950	if (rd_skip((off_t)(BCPIO_PAD(sizeof(HD_BCPIO) + nsz))) < 0)
951		return(-1);
952
953	/*
954	 * if not a link (or a file with no data), calculate pad size (for
955	 * padding which follows the file data), clear the link name and return
956	 */
957	if (((arcn->sb.st_mode & C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)){
958		/*
959		 * we have a valid header (not a link)
960		 */
961		arcn->ln_nlen = 0;
962		arcn->ln_name[0] = '\0';
963		arcn->pad = BCPIO_PAD(arcn->sb.st_size);
964		return(com_rd(arcn));
965	}
966
967	if ((rd_ln_nm(arcn) < 0) ||
968	    (rd_skip((off_t)(BCPIO_PAD(arcn->sb.st_size))) < 0))
969		return(-1);
970
971	/*
972	 * we have a valid header (with a link)
973	 */
974	return(com_rd(arcn));
975}
976
977/*
978 * bcpio_endrd()
979 *      no cleanup needed here, just return size of the trailer (for append)
980 * Return:
981 *      size of trailer header in this format
982 */
983
984off_t
985bcpio_endrd(void)
986{
987	return((off_t)(sizeof(HD_BCPIO) + sizeof(TRAILER) +
988		(BCPIO_PAD(sizeof(HD_BCPIO) + sizeof(TRAILER)))));
989}
990
991/*
992 * bcpio_wr()
993 *	copy the data in the ARCHD to buffer in old binary cpio format
994 *	There is a real chance of field overflow with this critter. So we
995 *	always check the conversion is ok. nobody in his their right mind
996 *	should write an achive in this format...
997 * Return
998 *      0 if file has data to be written after the header, 1 if file has NO
999 *	data to write after the header, -1 if archive write failed
1000 */
1001
1002int
1003bcpio_wr(ARCHD *arcn)
1004{
1005	HD_BCPIO *hd;
1006	int nsz;
1007	char hdblk[sizeof(HD_BCPIO)];
1008	off_t t_offt;
1009	int t_int;
1010	time_t t_timet;
1011
1012	/*
1013	 * check and repair truncated device and inode fields in the cpio
1014	 * header
1015	 */
1016	if (map_dev(arcn, (u_long)BCPIO_MASK, (u_long)BCPIO_MASK) < 0)
1017		return(-1);
1018
1019	if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR))
1020		arcn->sb.st_rdev = 0;
1021	hd = (HD_BCPIO *)hdblk;
1022
1023	switch(arcn->type) {
1024	case PAX_CTG:
1025	case PAX_REG:
1026	case PAX_HRG:
1027		/*
1028		 * caller will copy file data to the archive. tell him how
1029		 * much to pad.
1030		 */
1031		arcn->pad = BCPIO_PAD(arcn->sb.st_size);
1032		hd->h_filesize_1[0] = CHR_WR_0(arcn->sb.st_size);
1033		hd->h_filesize_1[1] = CHR_WR_1(arcn->sb.st_size);
1034		hd->h_filesize_2[0] = CHR_WR_2(arcn->sb.st_size);
1035		hd->h_filesize_2[1] = CHR_WR_3(arcn->sb.st_size);
1036		t_offt = (off_t)(SHRT_EXT(hd->h_filesize_1));
1037		t_offt = (t_offt<<16) | ((off_t)(SHRT_EXT(hd->h_filesize_2)));
1038		if (arcn->sb.st_size != t_offt) {
1039			paxwarn(1,"File is too large for bcpio format %s",
1040			    arcn->org_name);
1041			return(1);
1042		}
1043		break;
1044	case PAX_SLK:
1045		/*
1046		 * no file data for the caller to process, the file data has
1047		 * the size of the link
1048		 */
1049		arcn->pad = 0L;
1050		hd->h_filesize_1[0] = CHR_WR_0(arcn->ln_nlen);
1051		hd->h_filesize_1[1] = CHR_WR_1(arcn->ln_nlen);
1052		hd->h_filesize_2[0] = CHR_WR_2(arcn->ln_nlen);
1053		hd->h_filesize_2[1] = CHR_WR_3(arcn->ln_nlen);
1054		t_int = (int)(SHRT_EXT(hd->h_filesize_1));
1055		t_int = (t_int << 16) | ((int)(SHRT_EXT(hd->h_filesize_2)));
1056		if (arcn->ln_nlen != t_int)
1057			goto out;
1058		break;
1059	default:
1060		/*
1061		 * no file data for the caller to process
1062		 */
1063		arcn->pad = 0L;
1064		hd->h_filesize_1[0] = (char)0;
1065		hd->h_filesize_1[1] = (char)0;
1066		hd->h_filesize_2[0] = (char)0;
1067		hd->h_filesize_2[1] = (char)0;
1068		break;
1069	}
1070
1071	/*
1072	 * build up the rest of the fields
1073	 */
1074	hd->h_magic[0] = CHR_WR_2(MAGIC);
1075	hd->h_magic[1] = CHR_WR_3(MAGIC);
1076	hd->h_dev[0] = CHR_WR_2(arcn->sb.st_dev);
1077	hd->h_dev[1] = CHR_WR_3(arcn->sb.st_dev);
1078	if (arcn->sb.st_dev != (dev_t)(SHRT_EXT(hd->h_dev)))
1079		goto out;
1080	hd->h_ino[0] = CHR_WR_2(arcn->sb.st_ino);
1081	hd->h_ino[1] = CHR_WR_3(arcn->sb.st_ino);
1082	if (arcn->sb.st_ino != (ino_t)(SHRT_EXT(hd->h_ino)))
1083		goto out;
1084	hd->h_mode[0] = CHR_WR_2(arcn->sb.st_mode);
1085	hd->h_mode[1] = CHR_WR_3(arcn->sb.st_mode);
1086	if (arcn->sb.st_mode != (mode_t)(SHRT_EXT(hd->h_mode)))
1087		goto out;
1088	hd->h_uid[0] = CHR_WR_2(arcn->sb.st_uid);
1089	hd->h_uid[1] = CHR_WR_3(arcn->sb.st_uid);
1090	if (arcn->sb.st_uid != (uid_t)(SHRT_EXT(hd->h_uid)))
1091		goto out;
1092	hd->h_gid[0] = CHR_WR_2(arcn->sb.st_gid);
1093	hd->h_gid[1] = CHR_WR_3(arcn->sb.st_gid);
1094	if (arcn->sb.st_gid != (gid_t)(SHRT_EXT(hd->h_gid)))
1095		goto out;
1096	hd->h_nlink[0] = CHR_WR_2(arcn->sb.st_nlink);
1097	hd->h_nlink[1] = CHR_WR_3(arcn->sb.st_nlink);
1098	if (arcn->sb.st_nlink != (nlink_t)(SHRT_EXT(hd->h_nlink)))
1099		goto out;
1100	hd->h_rdev[0] = CHR_WR_2(arcn->sb.st_rdev);
1101	hd->h_rdev[1] = CHR_WR_3(arcn->sb.st_rdev);
1102	if (arcn->sb.st_rdev != (dev_t)(SHRT_EXT(hd->h_rdev)))
1103		goto out;
1104	hd->h_mtime_1[0] = CHR_WR_0(arcn->sb.st_mtime);
1105	hd->h_mtime_1[1] = CHR_WR_1(arcn->sb.st_mtime);
1106	hd->h_mtime_2[0] = CHR_WR_2(arcn->sb.st_mtime);
1107	hd->h_mtime_2[1] = CHR_WR_3(arcn->sb.st_mtime);
1108	t_timet = (time_t)(SHRT_EXT(hd->h_mtime_1));
1109	t_timet =  (t_timet << 16) | ((time_t)(SHRT_EXT(hd->h_mtime_2)));
1110	if (arcn->sb.st_mtime != t_timet)
1111		goto out;
1112	nsz = arcn->nlen + 1;
1113	hd->h_namesize[0] = CHR_WR_2(nsz);
1114	hd->h_namesize[1] = CHR_WR_3(nsz);
1115	if (nsz != (int)(SHRT_EXT(hd->h_namesize)))
1116		goto out;
1117
1118	/*
1119	 * write the header, the file name and padding as required.
1120	 */
1121	if ((wr_rdbuf(hdblk, (int)sizeof(HD_BCPIO)) < 0) ||
1122	    (wr_rdbuf(arcn->name, nsz) < 0) ||
1123	    (wr_skip((off_t)(BCPIO_PAD(sizeof(HD_BCPIO) + nsz))) < 0)) {
1124		paxwarn(1, "Could not write bcpio header for %s", arcn->org_name);
1125		return(-1);
1126	}
1127
1128	/*
1129	 * if we have file data, tell the caller we are done
1130	 */
1131	if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) ||
1132	    (arcn->type == PAX_HRG))
1133		return(0);
1134
1135	/*
1136	 * if we are not a link, tell the caller we are done, go to next file
1137	 */
1138	if (arcn->type != PAX_SLK)
1139		return(1);
1140
1141	/*
1142	 * write the link name, tell the caller we are done.
1143	 */
1144	if ((wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) ||
1145	    (wr_skip((off_t)(BCPIO_PAD(arcn->ln_nlen))) < 0)) {
1146		paxwarn(1,"Could not write bcpio link name for %s",arcn->org_name);
1147		return(-1);
1148	}
1149	return(1);
1150
1151    out:
1152	/*
1153	 * header field is out of range
1154	 */
1155	paxwarn(1,"Bcpio header field is too small for file %s", arcn->org_name);
1156	return(1);
1157}
1158