cpio.c revision 46684
11556Srgrimes/*-
21556Srgrimes * Copyright (c) 1992 Keith Muller.
31556Srgrimes * Copyright (c) 1992, 1993
41556Srgrimes *	The Regents of the University of California.  All rights reserved.
51556Srgrimes *
61556Srgrimes * This code is derived from software contributed to Berkeley by
71556Srgrimes * Keith Muller of the University of California, San Diego.
81556Srgrimes *
91556Srgrimes * Redistribution and use in source and binary forms, with or without
101556Srgrimes * modification, are permitted provided that the following conditions
111556Srgrimes * are met:
121556Srgrimes * 1. Redistributions of source code must retain the above copyright
131556Srgrimes *    notice, this list of conditions and the following disclaimer.
141556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
151556Srgrimes *    notice, this list of conditions and the following disclaimer in the
161556Srgrimes *    documentation and/or other materials provided with the distribution.
171556Srgrimes * 3. All advertising materials mentioning features or use of this software
181556Srgrimes *    must display the following acknowledgement:
191556Srgrimes *	This product includes software developed by the University of
201556Srgrimes *	California, Berkeley and its contributors.
211556Srgrimes * 4. Neither the name of the University nor the names of its contributors
221556Srgrimes *    may be used to endorse or promote products derived from this software
231556Srgrimes *    without specific prior written permission.
241556Srgrimes *
251556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
261556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
271556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
281556Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
291556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
301556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
311556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
321556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
331556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
341556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
351556Srgrimes * SUCH DAMAGE.
361556Srgrimes */
371556Srgrimes
381556Srgrimes#ifndef lint
3936049Scharnier#if 0
4036049Scharnierstatic char sccsid[] = "@(#)cpio.c	8.1 (Berkeley) 5/31/93";
4136049Scharnier#endif
4236049Scharnierstatic const char rcsid[] =
4346684Skris	"$Id: cpio.c,v 1.10 1998/05/15 06:27:38 charnier Exp $";
441556Srgrimes#endif /* not lint */
451556Srgrimes
461556Srgrimes#include <sys/types.h>
471556Srgrimes#include <sys/time.h>
481556Srgrimes#include <sys/stat.h>
491556Srgrimes#include <string.h>
501556Srgrimes#include <stdio.h>
511556Srgrimes#include <unistd.h>
521556Srgrimes#include <stdlib.h>
531556Srgrimes#include "pax.h"
541556Srgrimes#include "cpio.h"
551556Srgrimes#include "extern.h"
561556Srgrimes
571556Srgrimesstatic int rd_nm __P((register ARCHD *, int));
581556Srgrimesstatic int rd_ln_nm __P((register ARCHD *));
591556Srgrimesstatic int com_rd __P((register ARCHD *));
601556Srgrimes
611556Srgrimes/*
621556Srgrimes * Routines which support the different cpio versions
631556Srgrimes */
641556Srgrimes
651556Srgrimesstatic int swp_head;		/* binary cpio header byte swap */
661556Srgrimes
671556Srgrimes/*
681556Srgrimes * Routines common to all versions of cpio
691556Srgrimes */
701556Srgrimes
711556Srgrimes/*
721556Srgrimes * cpio_strd()
731556Srgrimes *	Fire up the hard link detection code
741556Srgrimes * Return:
751556Srgrimes *      0 if ok -1 otherwise (the return values of lnk_start())
761556Srgrimes */
771556Srgrimes
781556Srgrimes#if __STDC__
791556Srgrimesint
801556Srgrimescpio_strd(void)
811556Srgrimes#else
821556Srgrimesint
831556Srgrimescpio_strd()
841556Srgrimes#endif
851556Srgrimes{
861556Srgrimes	return(lnk_start());
871556Srgrimes}
881556Srgrimes
891556Srgrimes/*
901556Srgrimes * cpio_trail()
911556Srgrimes *	Called to determine if a header block is a valid trailer. We are
921556Srgrimes *	passed the block, the in_sync flag (which tells us we are in resync
931556Srgrimes *	mode; looking for a valid header), and cnt (which starts at zero)
941556Srgrimes *	which is used to count the number of empty blocks we have seen so far.
951556Srgrimes * Return:
968855Srgrimes *	0 if a valid trailer, -1 if not a valid trailer,
971556Srgrimes */
981556Srgrimes
991556Srgrimes#if __STDC__
1001556Srgrimesint
1011556Srgrimescpio_trail(register ARCHD *arcn)
1021556Srgrimes#else
1031556Srgrimesint
1041556Srgrimescpio_trail(arcn)
1051556Srgrimes	register ARCHD *arcn;
1061556Srgrimes#endif
1071556Srgrimes{
1081556Srgrimes	/*
1091556Srgrimes	 * look for trailer id in file we are about to process
1101556Srgrimes	 */
1111556Srgrimes	if ((strcmp(arcn->name, TRAILER) == 0) && (arcn->sb.st_size == 0))
1121556Srgrimes		return(0);
1131556Srgrimes	return(-1);
1141556Srgrimes}
1151556Srgrimes
1161556Srgrimes/*
1171556Srgrimes * com_rd()
1181556Srgrimes *	operations common to all cpio read functions.
1191556Srgrimes * Return:
1201556Srgrimes *	0
1211556Srgrimes */
1221556Srgrimes
1231556Srgrimes#if __STDC__
1241556Srgrimesstatic int
1251556Srgrimescom_rd(register ARCHD *arcn)
1261556Srgrimes#else
1271556Srgrimesstatic int
1281556Srgrimescom_rd(arcn)
1291556Srgrimes	register ARCHD *arcn;
1301556Srgrimes#endif
1311556Srgrimes{
1321556Srgrimes	arcn->skip = 0;
1331556Srgrimes	arcn->pat = NULL;
1341556Srgrimes	arcn->org_name = arcn->name;
1351556Srgrimes	switch(arcn->sb.st_mode & C_IFMT) {
1361556Srgrimes	case C_ISFIFO:
1371556Srgrimes		arcn->type = PAX_FIF;
1381556Srgrimes		break;
1391556Srgrimes	case C_ISDIR:
1401556Srgrimes		arcn->type = PAX_DIR;
1411556Srgrimes		break;
1421556Srgrimes	case C_ISBLK:
1431556Srgrimes		arcn->type = PAX_BLK;
1441556Srgrimes		break;
1451556Srgrimes	case C_ISCHR:
1461556Srgrimes		arcn->type = PAX_CHR;
1471556Srgrimes		break;
1481556Srgrimes	case C_ISLNK:
1491556Srgrimes		arcn->type = PAX_SLK;
1501556Srgrimes		break;
1511556Srgrimes	case C_ISOCK:
1521556Srgrimes		arcn->type = PAX_SCK;
1531556Srgrimes		break;
1541556Srgrimes	case C_ISCTG:
1551556Srgrimes	case C_ISREG:
1561556Srgrimes	default:
1571556Srgrimes		/*
1581556Srgrimes		 * we have file data, set up skip (pad is set in the format
1591556Srgrimes		 * specific sections)
1601556Srgrimes		 */
1611556Srgrimes		arcn->sb.st_mode = (arcn->sb.st_mode & 0xfff) | C_ISREG;
1621556Srgrimes		arcn->type = PAX_REG;
1631556Srgrimes		arcn->skip = arcn->sb.st_size;
1641556Srgrimes		break;
1651556Srgrimes	}
1661556Srgrimes	if (chk_lnk(arcn) < 0)
1671556Srgrimes		return(-1);
1681556Srgrimes	return(0);
1691556Srgrimes}
1701556Srgrimes
1711556Srgrimes/*
1721556Srgrimes * cpio_end_wr()
1731556Srgrimes *	write the special file with the name trailer in the proper format
1741556Srgrimes * Return:
1751556Srgrimes *	result of the write of the trailer from the cpio specific write func
1761556Srgrimes */
1771556Srgrimes
1781556Srgrimes#if __STDC__
1791556Srgrimesint
1801556Srgrimescpio_endwr(void)
1811556Srgrimes#else
1821556Srgrimesint
1831556Srgrimescpio_endwr()
1841556Srgrimes#endif
1851556Srgrimes{
1861556Srgrimes	ARCHD last;
1871556Srgrimes
1881556Srgrimes	/*
1891556Srgrimes	 * create a trailer request and call the proper format write function
1901556Srgrimes	 */
1911556Srgrimes	bzero((char *)&last, sizeof(last));
1921556Srgrimes	last.nlen = sizeof(TRAILER) - 1;
1931556Srgrimes	last.type = PAX_REG;
1941556Srgrimes	last.sb.st_nlink = 1;
1951556Srgrimes	(void)strcpy(last.name, TRAILER);
1961556Srgrimes	return((*frmt->wr)(&last));
1971556Srgrimes}
1981556Srgrimes
1991556Srgrimes/*
2001556Srgrimes * rd_nam()
2011556Srgrimes *	read in the file name which follows the cpio header
2021556Srgrimes * Return:
2031556Srgrimes *	0 if ok, -1 otherwise
2041556Srgrimes */
2051556Srgrimes
2061556Srgrimes#if __STDC__
2071556Srgrimesstatic int
2081556Srgrimesrd_nm(register ARCHD *arcn, int nsz)
2091556Srgrimes#else
2101556Srgrimesstatic int
2111556Srgrimesrd_nm(arcn, nsz)
2121556Srgrimes	register ARCHD *arcn;
2131556Srgrimes	int nsz;
2141556Srgrimes#endif
2151556Srgrimes{
2161556Srgrimes	/*
2171556Srgrimes	 * do not even try bogus values
2181556Srgrimes	 */
2191556Srgrimes	if ((nsz == 0) || (nsz > sizeof(arcn->name))) {
22028904Ssos		pax_warn(1, "Cpio file name length %d is out of range", nsz);
2211556Srgrimes		return(-1);
2221556Srgrimes	}
2231556Srgrimes
2241556Srgrimes	/*
2251556Srgrimes	 * read the name and make sure it is not empty and is \0 terminated
2261556Srgrimes	 */
2271556Srgrimes	if ((rd_wrbuf(arcn->name,nsz) != nsz) || (arcn->name[nsz-1] != '\0') ||
2281556Srgrimes	    (arcn->name[0] == '\0')) {
22928904Ssos		pax_warn(1, "Cpio file name in header is corrupted");
2301556Srgrimes		return(-1);
2311556Srgrimes	}
2321556Srgrimes	return(0);
2331556Srgrimes}
2341556Srgrimes
2351556Srgrimes/*
2361556Srgrimes * rd_ln_nm()
2371556Srgrimes *	read in the link name for a file with links. The link name is stored
2381556Srgrimes *	like file data (and is NOT \0 terminated!)
2391556Srgrimes * Return:
2401556Srgrimes *	0 if ok, -1 otherwise
2411556Srgrimes */
2421556Srgrimes
2431556Srgrimes#if __STDC__
2441556Srgrimesstatic int
2451556Srgrimesrd_ln_nm(register ARCHD *arcn)
2461556Srgrimes#else
2471556Srgrimesstatic int
2481556Srgrimesrd_ln_nm(arcn)
2491556Srgrimes	register ARCHD *arcn;
2501556Srgrimes#endif
2511556Srgrimes{
2521556Srgrimes	/*
2531556Srgrimes	 * check the length specified for bogus values
2541556Srgrimes	 */
2551556Srgrimes	if ((arcn->sb.st_size == 0) ||
2561556Srgrimes	    (arcn->sb.st_size >= sizeof(arcn->ln_name))) {
2571556Srgrimes#		ifdef NET2_STAT
25828904Ssos		pax_warn(1, "Cpio link name length is invalid: %lu",
2591556Srgrimes		    arcn->sb.st_size);
2601556Srgrimes#		else
26128904Ssos		pax_warn(1, "Cpio link name length is invalid: %qu",
2621556Srgrimes		    arcn->sb.st_size);
2631556Srgrimes#		endif
2641556Srgrimes		return(-1);
2651556Srgrimes	}
2661556Srgrimes
2671556Srgrimes	/*
2681556Srgrimes	 * read in the link name and \0 terminate it
2691556Srgrimes	 */
2701556Srgrimes	if (rd_wrbuf(arcn->ln_name, (int)arcn->sb.st_size) !=
2711556Srgrimes	    (int)arcn->sb.st_size) {
27228904Ssos		pax_warn(1, "Cpio link name read error");
2731556Srgrimes		return(-1);
2741556Srgrimes	}
2751556Srgrimes	arcn->ln_nlen = arcn->sb.st_size;
2761556Srgrimes	arcn->ln_name[arcn->ln_nlen] = '\0';
2771556Srgrimes
2781556Srgrimes	/*
2791556Srgrimes	 * watch out for those empty link names
2801556Srgrimes	 */
2811556Srgrimes	if (arcn->ln_name[0] == '\0') {
28228904Ssos		pax_warn(1, "Cpio link name is corrupt");
2831556Srgrimes		return(-1);
2841556Srgrimes	}
2851556Srgrimes	return(0);
2861556Srgrimes}
2871556Srgrimes
2881556Srgrimes/*
2891556Srgrimes * Routines common to the extended byte oriented cpio format
2901556Srgrimes */
2911556Srgrimes
2921556Srgrimes/*
2931556Srgrimes * cpio_id()
2941556Srgrimes *      determine if a block given to us is a valid extended byte oriented
2951556Srgrimes *	cpio header
2961556Srgrimes * Return:
2971556Srgrimes *      0 if a valid header, -1 otherwise
2981556Srgrimes */
2991556Srgrimes
3001556Srgrimes#if __STDC__
3011556Srgrimesint
3021556Srgrimescpio_id(char *blk, int size)
3031556Srgrimes#else
3041556Srgrimesint
3051556Srgrimescpio_id(blk, size)
3061556Srgrimes	char *blk;
3071556Srgrimes	int size;
3081556Srgrimes#endif
3091556Srgrimes{
3101556Srgrimes	if ((size < sizeof(HD_CPIO)) ||
3111556Srgrimes	    (strncmp(blk, AMAGIC, sizeof(AMAGIC) - 1) != 0))
3121556Srgrimes		return(-1);
3131556Srgrimes	return(0);
3141556Srgrimes}
3151556Srgrimes
3161556Srgrimes/*
3171556Srgrimes * cpio_rd()
3181556Srgrimes *	determine if a buffer is a byte oriented extended cpio archive entry.
3191556Srgrimes *	convert and store the values in the ARCHD parameter.
3201556Srgrimes * Return:
3211556Srgrimes *	0 if a valid header, -1 otherwise.
3221556Srgrimes */
3231556Srgrimes
3241556Srgrimes#if __STDC__
3251556Srgrimesint
3261556Srgrimescpio_rd(register ARCHD *arcn, register char *buf)
3271556Srgrimes#else
3281556Srgrimesint
3291556Srgrimescpio_rd(arcn, buf)
3301556Srgrimes	register ARCHD *arcn;
3311556Srgrimes	register char *buf;
3321556Srgrimes#endif
3331556Srgrimes{
3341556Srgrimes	register int nsz;
3351556Srgrimes	register HD_CPIO *hd;
3361556Srgrimes
3371556Srgrimes	/*
3381556Srgrimes	 * check that this is a valid header, if not return -1
3391556Srgrimes	 */
3401556Srgrimes	if (cpio_id(buf, sizeof(HD_CPIO)) < 0)
3411556Srgrimes		return(-1);
3421556Srgrimes	hd = (HD_CPIO *)buf;
3431556Srgrimes
3441556Srgrimes	/*
3451556Srgrimes	 * byte oriented cpio (posix) does not have padding! extract the octal
3461556Srgrimes	 * ascii fields from the header
3471556Srgrimes	 */
3481556Srgrimes	arcn->pad = 0L;
3491556Srgrimes	arcn->sb.st_dev = (dev_t)asc_ul(hd->c_dev, sizeof(hd->c_dev), OCT);
3501556Srgrimes	arcn->sb.st_ino = (ino_t)asc_ul(hd->c_ino, sizeof(hd->c_ino), OCT);
3511556Srgrimes	arcn->sb.st_mode = (mode_t)asc_ul(hd->c_mode, sizeof(hd->c_mode), OCT);
3521556Srgrimes	arcn->sb.st_uid = (uid_t)asc_ul(hd->c_uid, sizeof(hd->c_uid), OCT);
3531556Srgrimes	arcn->sb.st_gid = (gid_t)asc_ul(hd->c_gid, sizeof(hd->c_gid), OCT);
3541556Srgrimes	arcn->sb.st_nlink = (nlink_t)asc_ul(hd->c_nlink, sizeof(hd->c_nlink),
3551556Srgrimes	    OCT);
3561556Srgrimes	arcn->sb.st_rdev = (dev_t)asc_ul(hd->c_rdev, sizeof(hd->c_rdev), OCT);
3571556Srgrimes	arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime, sizeof(hd->c_mtime),
3581556Srgrimes	    OCT);
3591556Srgrimes	arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
3601556Srgrimes#	ifdef NET2_STAT
3611556Srgrimes	arcn->sb.st_size = (off_t)asc_ul(hd->c_filesize,sizeof(hd->c_filesize),
3621556Srgrimes	    OCT);
3631556Srgrimes#	else
3641556Srgrimes	arcn->sb.st_size = (off_t)asc_uqd(hd->c_filesize,sizeof(hd->c_filesize),
3651556Srgrimes	    OCT);
3661556Srgrimes#	endif
3671556Srgrimes
3681556Srgrimes	/*
3691556Srgrimes	 * check name size and if valid, read in the name of this entry (name
3701556Srgrimes	 * follows header in the archive)
3711556Srgrimes	 */
3721556Srgrimes	if ((nsz = (int)asc_ul(hd->c_namesize,sizeof(hd->c_namesize),OCT)) < 2)
3731556Srgrimes		return(-1);
3741556Srgrimes	arcn->nlen = nsz - 1;
3751556Srgrimes	if (rd_nm(arcn, nsz) < 0)
3761556Srgrimes		return(-1);
3771556Srgrimes
3781556Srgrimes	if (((arcn->sb.st_mode&C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)) {
3791556Srgrimes		/*
3801556Srgrimes	 	 * no link name to read for this file
3811556Srgrimes	 	 */
3821556Srgrimes		arcn->ln_nlen = 0;
3831556Srgrimes		arcn->ln_name[0] = '\0';
3841556Srgrimes		return(com_rd(arcn));
3851556Srgrimes	}
3861556Srgrimes
3871556Srgrimes	/*
3881556Srgrimes	 * check link name size and read in the link name. Link names are
3891556Srgrimes	 * stored like file data.
3901556Srgrimes	 */
3911556Srgrimes	if (rd_ln_nm(arcn) < 0)
3921556Srgrimes		return(-1);
3931556Srgrimes
3941556Srgrimes	/*
3951556Srgrimes	 * we have a valid header (with a link)
3961556Srgrimes	 */
3971556Srgrimes	return(com_rd(arcn));
3981556Srgrimes}
3991556Srgrimes
4001556Srgrimes/*
4011556Srgrimes * cpio_endrd()
4021556Srgrimes *      no cleanup needed here, just return size of the trailer (for append)
4031556Srgrimes * Return:
4041556Srgrimes *      size of trailer header in this format
4051556Srgrimes */
4061556Srgrimes
4071556Srgrimes#if __STDC__
4081556Srgrimesoff_t
4091556Srgrimescpio_endrd(void)
4101556Srgrimes#else
4111556Srgrimesoff_t
4121556Srgrimescpio_endrd()
4131556Srgrimes#endif
4141556Srgrimes{
4151556Srgrimes	return((off_t)(sizeof(HD_CPIO) + sizeof(TRAILER)));
4161556Srgrimes}
4171556Srgrimes
4181556Srgrimes/*
4191556Srgrimes * cpio_stwr()
4201556Srgrimes *	start up the device mapping table
4211556Srgrimes * Return:
4221556Srgrimes *	0 if ok, -1 otherwise (what dev_start() returns)
4231556Srgrimes */
4241556Srgrimes
4251556Srgrimes#if __STDC__
4261556Srgrimesint
4271556Srgrimescpio_stwr(void)
4281556Srgrimes#else
4291556Srgrimesint
4301556Srgrimescpio_stwr()
4311556Srgrimes#endif
4321556Srgrimes{
4331556Srgrimes	return(dev_start());
4341556Srgrimes}
4351556Srgrimes
4361556Srgrimes/*
4371556Srgrimes * cpio_wr()
4381556Srgrimes *	copy the data in the ARCHD to buffer in extended byte oriented cpio
4391556Srgrimes *	format.
4401556Srgrimes * Return
4411556Srgrimes *      0 if file has data to be written after the header, 1 if file has NO
4421556Srgrimes *	data to write after the header, -1 if archive write failed
4431556Srgrimes */
4441556Srgrimes
4451556Srgrimes#if __STDC__
4461556Srgrimesint
4471556Srgrimescpio_wr(register ARCHD *arcn)
4481556Srgrimes#else
4491556Srgrimesint
4501556Srgrimescpio_wr(arcn)
4511556Srgrimes	register ARCHD *arcn;
4521556Srgrimes#endif
4531556Srgrimes{
4541556Srgrimes	register HD_CPIO *hd;
4551556Srgrimes	register int nsz;
4561556Srgrimes	char hdblk[sizeof(HD_CPIO)];
4571556Srgrimes
4581556Srgrimes	/*
4591556Srgrimes	 * check and repair truncated device and inode fields in the header
4601556Srgrimes	 */
4611556Srgrimes	if (map_dev(arcn, (u_long)CPIO_MASK, (u_long)CPIO_MASK) < 0)
4621556Srgrimes		return(-1);
4631556Srgrimes
4641556Srgrimes	arcn->pad = 0L;
4651556Srgrimes	nsz = arcn->nlen + 1;
4661556Srgrimes	hd = (HD_CPIO *)hdblk;
4671556Srgrimes	if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR))
4681556Srgrimes		arcn->sb.st_rdev = 0;
4691556Srgrimes
4701556Srgrimes	switch(arcn->type) {
4711556Srgrimes	case PAX_CTG:
4721556Srgrimes	case PAX_REG:
4731556Srgrimes	case PAX_HRG:
4741556Srgrimes		/*
4751556Srgrimes		 * set data size for file data
4761556Srgrimes		 */
4771556Srgrimes#		ifdef NET2_STAT
4781556Srgrimes		if (ul_asc((u_long)arcn->sb.st_size, hd->c_filesize,
4791556Srgrimes		    sizeof(hd->c_filesize), OCT)) {
4801556Srgrimes#		else
4811556Srgrimes		if (uqd_asc((u_quad_t)arcn->sb.st_size, hd->c_filesize,
4821556Srgrimes		    sizeof(hd->c_filesize), OCT)) {
4831556Srgrimes#		endif
48428904Ssos			pax_warn(1,"File is too large for cpio format %s",
4851556Srgrimes			    arcn->org_name);
4861556Srgrimes			return(1);
4871556Srgrimes		}
4881556Srgrimes		break;
4891556Srgrimes	case PAX_SLK:
4901556Srgrimes		/*
4911556Srgrimes		 * set data size to hold link name
4921556Srgrimes		 */
4931556Srgrimes		if (ul_asc((u_long)arcn->ln_nlen, hd->c_filesize,
4941556Srgrimes		    sizeof(hd->c_filesize), OCT))
4951556Srgrimes			goto out;
4961556Srgrimes		break;
4971556Srgrimes	default:
4981556Srgrimes		/*
4991556Srgrimes		 * all other file types have no file data
5001556Srgrimes		 */
5011556Srgrimes		if (ul_asc((u_long)0, hd->c_filesize, sizeof(hd->c_filesize),
5021556Srgrimes		     OCT))
5031556Srgrimes			goto out;
5041556Srgrimes		break;
5051556Srgrimes	}
5061556Srgrimes
5071556Srgrimes	/*
5081556Srgrimes	 * copy the values to the header using octal ascii
5091556Srgrimes	 */
5101556Srgrimes	if (ul_asc((u_long)MAGIC, hd->c_magic, sizeof(hd->c_magic), OCT) ||
5111556Srgrimes	    ul_asc((u_long)arcn->sb.st_dev, hd->c_dev, sizeof(hd->c_dev),
5121556Srgrimes	        OCT) ||
5131556Srgrimes	    ul_asc((u_long)arcn->sb.st_ino, hd->c_ino, sizeof(hd->c_ino),
5141556Srgrimes		OCT) ||
5151556Srgrimes	    ul_asc((u_long)arcn->sb.st_mode, hd->c_mode, sizeof(hd->c_mode),
5161556Srgrimes		OCT) ||
5171556Srgrimes	    ul_asc((u_long)arcn->sb.st_uid, hd->c_uid, sizeof(hd->c_uid),
5181556Srgrimes		OCT) ||
5191556Srgrimes	    ul_asc((u_long)arcn->sb.st_gid, hd->c_gid, sizeof(hd->c_gid),
5201556Srgrimes		OCT) ||
5211556Srgrimes	    ul_asc((u_long)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink),
5221556Srgrimes		 OCT) ||
5231556Srgrimes	    ul_asc((u_long)arcn->sb.st_rdev, hd->c_rdev, sizeof(hd->c_rdev),
5241556Srgrimes		OCT) ||
5251556Srgrimes	    ul_asc((u_long)arcn->sb.st_mtime,hd->c_mtime,sizeof(hd->c_mtime),
5261556Srgrimes		OCT) ||
5271556Srgrimes	    ul_asc((u_long)nsz, hd->c_namesize, sizeof(hd->c_namesize), OCT))
5281556Srgrimes		goto out;
5291556Srgrimes
5301556Srgrimes	/*
5311556Srgrimes	 * write the file name to the archive
5321556Srgrimes	 */
5331556Srgrimes	if ((wr_rdbuf(hdblk, (int)sizeof(HD_CPIO)) < 0) ||
5341556Srgrimes	    (wr_rdbuf(arcn->name, nsz) < 0)) {
53528904Ssos		pax_warn(1, "Unable to write cpio header for %s", arcn->org_name);
5361556Srgrimes		return(-1);
5371556Srgrimes	}
5381556Srgrimes
5391556Srgrimes	/*
5401556Srgrimes	 * if this file has data, we are done. The caller will write the file
5411556Srgrimes	 * data, if we are link tell caller we are done, go to next file
5421556Srgrimes	 */
5431556Srgrimes	if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) ||
5441556Srgrimes	    (arcn->type == PAX_HRG))
5451556Srgrimes		return(0);
5461556Srgrimes	if (arcn->type != PAX_SLK)
5471556Srgrimes		return(1);
5481556Srgrimes
5491556Srgrimes	/*
5501556Srgrimes	 * write the link name to the archive, tell the caller to go to the
5511556Srgrimes	 * next file as we are done.
5521556Srgrimes	 */
5531556Srgrimes	if (wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) {
55428904Ssos		pax_warn(1,"Unable to write cpio link name for %s",arcn->org_name);
5551556Srgrimes		return(-1);
5561556Srgrimes	}
5571556Srgrimes	return(1);
5581556Srgrimes
5591556Srgrimes    out:
5601556Srgrimes	/*
5611556Srgrimes	 * header field is out of range
5621556Srgrimes	 */
56328904Ssos	pax_warn(1, "Cpio header field is too small to store file %s",
5641556Srgrimes	    arcn->org_name);
5651556Srgrimes	return(1);
5661556Srgrimes}
5671556Srgrimes
5681556Srgrimes/*
5691556Srgrimes * Routines common to the system VR4 version of cpio (with/without file CRC)
5701556Srgrimes */
5711556Srgrimes
5721556Srgrimes/*
5731556Srgrimes * vcpio_id()
5741556Srgrimes *      determine if a block given to us is a valid system VR4 cpio header
5758855Srgrimes *	WITHOUT crc. WATCH it the magic cookies are in OCTAL, the header
5761556Srgrimes *	uses HEX
5771556Srgrimes * Return:
5781556Srgrimes *      0 if a valid header, -1 otherwise
5791556Srgrimes */
5801556Srgrimes
5811556Srgrimes#if __STDC__
5821556Srgrimesint
5831556Srgrimesvcpio_id(char *blk, int size)
5841556Srgrimes#else
5851556Srgrimesint
5861556Srgrimesvcpio_id(blk, size)
5871556Srgrimes	char *blk;
5881556Srgrimes	int size;
5891556Srgrimes#endif
5901556Srgrimes{
5911556Srgrimes	if ((size < sizeof(HD_VCPIO)) ||
5921556Srgrimes	    (strncmp(blk, AVMAGIC, sizeof(AVMAGIC) - 1) != 0))
5931556Srgrimes		return(-1);
5941556Srgrimes	return(0);
5951556Srgrimes}
5961556Srgrimes
5971556Srgrimes/*
5981556Srgrimes * crc_id()
5991556Srgrimes *      determine if a block given to us is a valid system VR4 cpio header
6001556Srgrimes *	WITH crc. WATCH it the magic cookies are in OCTAL the header uses HEX
6011556Srgrimes * Return:
6021556Srgrimes *      0 if a valid header, -1 otherwise
6031556Srgrimes */
6041556Srgrimes
6051556Srgrimes#if __STDC__
6061556Srgrimesint
6071556Srgrimescrc_id(char *blk, int size)
6081556Srgrimes#else
6091556Srgrimesint
6101556Srgrimescrc_id(blk, size)
6111556Srgrimes	char *blk;
6121556Srgrimes	int size;
6131556Srgrimes#endif
6141556Srgrimes{
6151556Srgrimes	if ((size < sizeof(HD_VCPIO)) ||
6161556Srgrimes	    (strncmp(blk, AVCMAGIC, sizeof(AVCMAGIC) - 1) != 0))
6171556Srgrimes		return(-1);
6181556Srgrimes	return(0);
6191556Srgrimes}
6201556Srgrimes
6211556Srgrimes/*
6221556Srgrimes * crc_strd()
6231556Srgrimes w	set file data CRC calculations. Fire up the hard link detection code
6241556Srgrimes * Return:
6251556Srgrimes *      0 if ok -1 otherwise (the return values of lnk_start())
6261556Srgrimes */
6271556Srgrimes
6281556Srgrimes#if __STDC__
6291556Srgrimesint
6301556Srgrimescrc_strd(void)
6311556Srgrimes#else
6321556Srgrimesint
6331556Srgrimescrc_strd()
6341556Srgrimes#endif
6351556Srgrimes{
6361556Srgrimes	docrc = 1;
6371556Srgrimes	return(lnk_start());
6381556Srgrimes}
6391556Srgrimes
6401556Srgrimes/*
6411556Srgrimes * vcpio_rd()
6421556Srgrimes *	determine if a buffer is a system VR4 archive entry. (with/without CRC)
6431556Srgrimes *	convert and store the values in the ARCHD parameter.
6441556Srgrimes * Return:
6451556Srgrimes *	0 if a valid header, -1 otherwise.
6461556Srgrimes */
6471556Srgrimes
6481556Srgrimes#if __STDC__
6491556Srgrimesint
6501556Srgrimesvcpio_rd(register ARCHD *arcn, register char *buf)
6511556Srgrimes#else
6521556Srgrimesint
6531556Srgrimesvcpio_rd(arcn, buf)
6541556Srgrimes	register ARCHD *arcn;
6551556Srgrimes	register char *buf;
6561556Srgrimes#endif
6571556Srgrimes{
6581556Srgrimes	register HD_VCPIO *hd;
6591556Srgrimes	dev_t devminor;
6601556Srgrimes	dev_t devmajor;
6611556Srgrimes	register int nsz;
6621556Srgrimes
6631556Srgrimes	/*
6641556Srgrimes	 * during the id phase it was determined if we were using CRC, use the
6651556Srgrimes	 * proper id routine.
6661556Srgrimes	 */
6671556Srgrimes	if (docrc) {
6681556Srgrimes		if (crc_id(buf, sizeof(HD_VCPIO)) < 0)
6691556Srgrimes			return(-1);
6701556Srgrimes	} else {
6711556Srgrimes		if (vcpio_id(buf, sizeof(HD_VCPIO)) < 0)
6721556Srgrimes			return(-1);
6731556Srgrimes	}
6741556Srgrimes
6751556Srgrimes	hd = (HD_VCPIO *)buf;
6761556Srgrimes	arcn->pad = 0L;
6771556Srgrimes
6781556Srgrimes	/*
6791556Srgrimes	 * extract the hex ascii fields from the header
6801556Srgrimes	 */
6811556Srgrimes	arcn->sb.st_ino = (ino_t)asc_ul(hd->c_ino, sizeof(hd->c_ino), HEX);
6821556Srgrimes	arcn->sb.st_mode = (mode_t)asc_ul(hd->c_mode, sizeof(hd->c_mode), HEX);
6831556Srgrimes	arcn->sb.st_uid = (uid_t)asc_ul(hd->c_uid, sizeof(hd->c_uid), HEX);
6841556Srgrimes	arcn->sb.st_gid = (gid_t)asc_ul(hd->c_gid, sizeof(hd->c_gid), HEX);
6851556Srgrimes	arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime,sizeof(hd->c_mtime),HEX);
6861556Srgrimes	arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
6871556Srgrimes#	ifdef NET2_STAT
6881556Srgrimes	arcn->sb.st_size = (off_t)asc_ul(hd->c_filesize,
6891556Srgrimes	    sizeof(hd->c_filesize), HEX);
6901556Srgrimes#	else
6911556Srgrimes	arcn->sb.st_size = (off_t)asc_uqd(hd->c_filesize,
6921556Srgrimes	    sizeof(hd->c_filesize), HEX);
6931556Srgrimes#	endif
6941556Srgrimes	arcn->sb.st_nlink = (nlink_t)asc_ul(hd->c_nlink, sizeof(hd->c_nlink),
6951556Srgrimes	    HEX);
6961556Srgrimes	devmajor = (dev_t)asc_ul(hd->c_maj, sizeof(hd->c_maj), HEX);
6971556Srgrimes	devminor = (dev_t)asc_ul(hd->c_min, sizeof(hd->c_min), HEX);
6981556Srgrimes	arcn->sb.st_dev = TODEV(devmajor, devminor);
6991556Srgrimes	devmajor = (dev_t)asc_ul(hd->c_rmaj, sizeof(hd->c_maj), HEX);
7001556Srgrimes	devminor = (dev_t)asc_ul(hd->c_rmin, sizeof(hd->c_min), HEX);
7011556Srgrimes	arcn->sb.st_rdev = TODEV(devmajor, devminor);
7021556Srgrimes	arcn->crc = asc_ul(hd->c_chksum, sizeof(hd->c_chksum), HEX);
7031556Srgrimes
7041556Srgrimes	/*
7051556Srgrimes	 * check the length of the file name, if ok read it in, return -1 if
7061556Srgrimes	 * bogus
7071556Srgrimes	 */
7081556Srgrimes	if ((nsz = (int)asc_ul(hd->c_namesize,sizeof(hd->c_namesize),HEX)) < 2)
7091556Srgrimes		return(-1);
7101556Srgrimes	arcn->nlen = nsz - 1;
7111556Srgrimes	if (rd_nm(arcn, nsz) < 0)
7121556Srgrimes		return(-1);
7131556Srgrimes
7141556Srgrimes	/*
7151556Srgrimes	 * skip padding. header + filename is aligned to 4 byte boundries
7161556Srgrimes	 */
7171556Srgrimes	if (rd_skip((off_t)(VCPIO_PAD(sizeof(HD_VCPIO) + nsz))) < 0)
7181556Srgrimes		return(-1);
7191556Srgrimes
7201556Srgrimes	/*
7211556Srgrimes	 * if not a link (or a file with no data), calculate pad size (for
7221556Srgrimes	 * padding which follows the file data), clear the link name and return
7231556Srgrimes	 */
7241556Srgrimes	if (((arcn->sb.st_mode&C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)) {
7251556Srgrimes		/*
7261556Srgrimes		 * we have a valid header (not a link)
7271556Srgrimes		 */
7281556Srgrimes		arcn->ln_nlen = 0;
7291556Srgrimes		arcn->ln_name[0] = '\0';
7301556Srgrimes		arcn->pad = VCPIO_PAD(arcn->sb.st_size);
7311556Srgrimes		return(com_rd(arcn));
7321556Srgrimes	}
7331556Srgrimes
7341556Srgrimes	/*
7351556Srgrimes	 * read in the link name and skip over the padding
7361556Srgrimes	 */
7371556Srgrimes	if ((rd_ln_nm(arcn) < 0) ||
7381556Srgrimes	    (rd_skip((off_t)(VCPIO_PAD(arcn->sb.st_size))) < 0))
7391556Srgrimes		return(-1);
7401556Srgrimes
7411556Srgrimes	/*
7421556Srgrimes	 * we have a valid header (with a link)
7431556Srgrimes	 */
7441556Srgrimes	return(com_rd(arcn));
7451556Srgrimes}
7461556Srgrimes
7471556Srgrimes/*
7481556Srgrimes * vcpio_endrd()
7491556Srgrimes *      no cleanup needed here, just return size of the trailer (for append)
7501556Srgrimes * Return:
7511556Srgrimes *      size of trailer header in this format
7521556Srgrimes */
7531556Srgrimes
7541556Srgrimes#if __STDC__
7551556Srgrimesoff_t
7561556Srgrimesvcpio_endrd(void)
7571556Srgrimes#else
7581556Srgrimesoff_t
7591556Srgrimesvcpio_endrd()
7601556Srgrimes#endif
7611556Srgrimes{
7621556Srgrimes	return((off_t)(sizeof(HD_VCPIO) + sizeof(TRAILER) +
7631556Srgrimes		(VCPIO_PAD(sizeof(HD_VCPIO) + sizeof(TRAILER)))));
7641556Srgrimes}
7651556Srgrimes
7661556Srgrimes/*
7671556Srgrimes * crc_stwr()
7681556Srgrimes *	start up the device mapping table, enable crc file calculation
7691556Srgrimes * Return:
7701556Srgrimes *	0 if ok, -1 otherwise (what dev_start() returns)
7711556Srgrimes */
7721556Srgrimes
7731556Srgrimes#if __STDC__
7741556Srgrimesint
7751556Srgrimescrc_stwr(void)
7761556Srgrimes#else
7771556Srgrimesint
7781556Srgrimescrc_stwr()
7791556Srgrimes#endif
7801556Srgrimes{
7811556Srgrimes	docrc = 1;
7821556Srgrimes	return(dev_start());
7831556Srgrimes}
7841556Srgrimes
7851556Srgrimes/*
7861556Srgrimes * vcpio_wr()
7871556Srgrimes *	copy the data in the ARCHD to buffer in system VR4 cpio
7881556Srgrimes *	(with/without crc) format.
7891556Srgrimes * Return
7901556Srgrimes *	0 if file has data to be written after the header, 1 if file has
7911556Srgrimes *	NO data to write after the header, -1 if archive write failed
7921556Srgrimes */
7931556Srgrimes
7941556Srgrimes#if __STDC__
7951556Srgrimesint
7961556Srgrimesvcpio_wr(register ARCHD *arcn)
7971556Srgrimes#else
7981556Srgrimesint
7991556Srgrimesvcpio_wr(arcn)
8001556Srgrimes	register ARCHD *arcn;
8011556Srgrimes#endif
8021556Srgrimes{
8031556Srgrimes	register HD_VCPIO *hd;
8041556Srgrimes	unsigned int nsz;
8051556Srgrimes	char hdblk[sizeof(HD_VCPIO)];
8061556Srgrimes
8071556Srgrimes	/*
8081556Srgrimes	 * check and repair truncated device and inode fields in the cpio
8091556Srgrimes	 * header
8101556Srgrimes	 */
8111556Srgrimes	if (map_dev(arcn, (u_long)VCPIO_MASK, (u_long)VCPIO_MASK) < 0)
8121556Srgrimes		return(-1);
8131556Srgrimes	nsz = arcn->nlen + 1;
8141556Srgrimes	hd = (HD_VCPIO *)hdblk;
8151556Srgrimes	if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR))
8161556Srgrimes		arcn->sb.st_rdev = 0;
8171556Srgrimes
8181556Srgrimes	/*
8191556Srgrimes	 * add the proper magic value depending whether we were asked for
8201556Srgrimes	 * file data crc's, and the crc if needed.
8211556Srgrimes	 */
8221556Srgrimes	if (docrc) {
8231556Srgrimes		if (ul_asc((u_long)VCMAGIC, hd->c_magic, sizeof(hd->c_magic),
8241556Srgrimes	    		OCT) ||
8251556Srgrimes		    ul_asc((u_long)arcn->crc,hd->c_chksum,sizeof(hd->c_chksum),
8261556Srgrimes	    		HEX))
8271556Srgrimes			goto out;
8281556Srgrimes	} else {
8291556Srgrimes		if (ul_asc((u_long)VMAGIC, hd->c_magic, sizeof(hd->c_magic),
8301556Srgrimes	    		OCT) ||
8311556Srgrimes		    ul_asc((u_long)0L, hd->c_chksum, sizeof(hd->c_chksum),HEX))
8321556Srgrimes			goto out;
8331556Srgrimes	}
8341556Srgrimes
8351556Srgrimes	switch(arcn->type) {
8361556Srgrimes	case PAX_CTG:
8371556Srgrimes	case PAX_REG:
8381556Srgrimes	case PAX_HRG:
8391556Srgrimes		/*
8401556Srgrimes		 * caller will copy file data to the archive. tell him how
8411556Srgrimes		 * much to pad.
8421556Srgrimes		 */
8431556Srgrimes		arcn->pad = VCPIO_PAD(arcn->sb.st_size);
8441556Srgrimes#		ifdef NET2_STAT
8451556Srgrimes		if (ul_asc((u_long)arcn->sb.st_size, hd->c_filesize,
8461556Srgrimes		    sizeof(hd->c_filesize), HEX)) {
8471556Srgrimes#		else
8481556Srgrimes		if (uqd_asc((u_quad_t)arcn->sb.st_size, hd->c_filesize,
8491556Srgrimes		    sizeof(hd->c_filesize), HEX)) {
8501556Srgrimes#		endif
85128904Ssos			pax_warn(1,"File is too large for sv4cpio format %s",
8521556Srgrimes			    arcn->org_name);
8531556Srgrimes			return(1);
8541556Srgrimes		}
8551556Srgrimes		break;
8561556Srgrimes	case PAX_SLK:
8571556Srgrimes		/*
8581556Srgrimes		 * no file data for the caller to process, the file data has
8591556Srgrimes		 * the size of the link
8601556Srgrimes		 */
8611556Srgrimes		arcn->pad = 0L;
8621556Srgrimes		if (ul_asc((u_long)arcn->ln_nlen, hd->c_filesize,
8631556Srgrimes		    sizeof(hd->c_filesize), HEX))
8641556Srgrimes			goto out;
8651556Srgrimes		break;
8661556Srgrimes	default:
8671556Srgrimes		/*
8681556Srgrimes		 * no file data for the caller to process
8691556Srgrimes		 */
8701556Srgrimes		arcn->pad = 0L;
8711556Srgrimes		if (ul_asc((u_long)0L, hd->c_filesize, sizeof(hd->c_filesize),
8721556Srgrimes		    HEX))
8731556Srgrimes			goto out;
8741556Srgrimes		break;
8751556Srgrimes	}
8761556Srgrimes
8771556Srgrimes	/*
8781556Srgrimes	 * set the other fields in the header
8791556Srgrimes	 */
8801556Srgrimes	if (ul_asc((u_long)arcn->sb.st_ino, hd->c_ino, sizeof(hd->c_ino),
8811556Srgrimes		HEX) ||
8821556Srgrimes	    ul_asc((u_long)arcn->sb.st_mode, hd->c_mode, sizeof(hd->c_mode),
8831556Srgrimes		HEX) ||
8841556Srgrimes	    ul_asc((u_long)arcn->sb.st_uid, hd->c_uid, sizeof(hd->c_uid),
8851556Srgrimes		HEX) ||
8861556Srgrimes	    ul_asc((u_long)arcn->sb.st_gid, hd->c_gid, sizeof(hd->c_gid),
8871556Srgrimes    		HEX) ||
8881556Srgrimes	    ul_asc((u_long)arcn->sb.st_mtime, hd->c_mtime, sizeof(hd->c_mtime),
8891556Srgrimes    		HEX) ||
8901556Srgrimes	    ul_asc((u_long)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink),
8911556Srgrimes    		HEX) ||
8921556Srgrimes	    ul_asc((u_long)MAJOR(arcn->sb.st_dev),hd->c_maj, sizeof(hd->c_maj),
8931556Srgrimes		HEX) ||
8941556Srgrimes	    ul_asc((u_long)MINOR(arcn->sb.st_dev),hd->c_min, sizeof(hd->c_min),
8951556Srgrimes		HEX) ||
8961556Srgrimes	    ul_asc((u_long)MAJOR(arcn->sb.st_rdev),hd->c_rmaj,sizeof(hd->c_maj),
8971556Srgrimes		HEX) ||
8981556Srgrimes	    ul_asc((u_long)MINOR(arcn->sb.st_rdev),hd->c_rmin,sizeof(hd->c_min),
8991556Srgrimes		HEX) ||
9001556Srgrimes	    ul_asc((u_long)nsz, hd->c_namesize, sizeof(hd->c_namesize), HEX))
9011556Srgrimes		goto out;
9021556Srgrimes
9031556Srgrimes	/*
9041556Srgrimes	 * write the header, the file name and padding as required.
9051556Srgrimes	 */
9061556Srgrimes	if ((wr_rdbuf(hdblk, (int)sizeof(HD_VCPIO)) < 0) ||
9071556Srgrimes	    (wr_rdbuf(arcn->name, (int)nsz) < 0)  ||
9081556Srgrimes	    (wr_skip((off_t)(VCPIO_PAD(sizeof(HD_VCPIO) + nsz))) < 0)) {
90928904Ssos		pax_warn(1,"Could not write sv4cpio header for %s",arcn->org_name);
9101556Srgrimes		return(-1);
9111556Srgrimes	}
9121556Srgrimes
9131556Srgrimes	/*
9141556Srgrimes	 * if we have file data, tell the caller we are done, copy the file
9151556Srgrimes	 */
9161556Srgrimes	if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) ||
9171556Srgrimes	    (arcn->type == PAX_HRG))
9181556Srgrimes		return(0);
9191556Srgrimes
9201556Srgrimes	/*
9211556Srgrimes	 * if we are not a link, tell the caller we are done, go to next file
9221556Srgrimes	 */
9231556Srgrimes	if (arcn->type != PAX_SLK)
9241556Srgrimes		return(1);
9251556Srgrimes
9261556Srgrimes	/*
9271556Srgrimes	 * write the link name, tell the caller we are done.
9281556Srgrimes	 */
9291556Srgrimes	if ((wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) ||
9301556Srgrimes	    (wr_skip((off_t)(VCPIO_PAD(arcn->ln_nlen))) < 0)) {
93128904Ssos		pax_warn(1,"Could not write sv4cpio link name for %s",
9321556Srgrimes		    arcn->org_name);
9331556Srgrimes		return(-1);
9341556Srgrimes	}
9351556Srgrimes	return(1);
9361556Srgrimes
9371556Srgrimes    out:
9381556Srgrimes	/*
9391556Srgrimes	 * header field is out of range
9401556Srgrimes	 */
94128904Ssos	pax_warn(1,"Sv4cpio header field is too small for file %s",arcn->org_name);
9421556Srgrimes	return(1);
9431556Srgrimes}
9441556Srgrimes
9451556Srgrimes/*
9461556Srgrimes * Routines common to the old binary header cpio
9471556Srgrimes */
9481556Srgrimes
9491556Srgrimes/*
9501556Srgrimes * bcpio_id()
9511556Srgrimes *      determine if a block given to us is a old binary cpio header
9521556Srgrimes *	(with/without header byte swapping)
9531556Srgrimes * Return:
9541556Srgrimes *      0 if a valid header, -1 otherwise
9551556Srgrimes */
9561556Srgrimes
9571556Srgrimes#if __STDC__
9581556Srgrimesint
9591556Srgrimesbcpio_id(char *blk, int size)
9601556Srgrimes#else
9611556Srgrimesint
9621556Srgrimesbcpio_id(blk, size)
9631556Srgrimes	char *blk;
9641556Srgrimes	int size;
9651556Srgrimes#endif
9661556Srgrimes{
9671556Srgrimes	if (size < sizeof(HD_BCPIO))
9681556Srgrimes		return(-1);
9691556Srgrimes
9701556Srgrimes	/*
9711556Srgrimes	 * check both normal and byte swapped magic cookies
9721556Srgrimes	 */
9731556Srgrimes	if (((u_short)SHRT_EXT(blk)) == MAGIC)
9741556Srgrimes		return(0);
9751556Srgrimes	if (((u_short)RSHRT_EXT(blk)) == MAGIC) {
9761556Srgrimes		if (!swp_head)
9771556Srgrimes			++swp_head;
9781556Srgrimes		return(0);
9791556Srgrimes	}
9801556Srgrimes	return(-1);
9811556Srgrimes}
9821556Srgrimes
9831556Srgrimes/*
9841556Srgrimes * bcpio_rd()
9851556Srgrimes *	determine if a buffer is a old binary archive entry. (it may have byte
9861556Srgrimes *	swapped header) convert and store the values in the ARCHD parameter.
9871556Srgrimes *	This is a very old header format and should not really be used.
9881556Srgrimes * Return:
9891556Srgrimes *	0 if a valid header, -1 otherwise.
9901556Srgrimes */
9911556Srgrimes
9921556Srgrimes#if __STDC__
9931556Srgrimesint
9941556Srgrimesbcpio_rd(register ARCHD *arcn, register char *buf)
9951556Srgrimes#else
9961556Srgrimesint
9971556Srgrimesbcpio_rd(arcn, buf)
9981556Srgrimes	register ARCHD *arcn;
9991556Srgrimes	register char *buf;
10001556Srgrimes#endif
10011556Srgrimes{
10021556Srgrimes	register HD_BCPIO *hd;
10031556Srgrimes	register int nsz;
10041556Srgrimes
10051556Srgrimes	/*
10061556Srgrimes	 * check the header
10071556Srgrimes	 */
10081556Srgrimes	if (bcpio_id(buf, sizeof(HD_BCPIO)) < 0)
10091556Srgrimes		return(-1);
10101556Srgrimes
10111556Srgrimes	arcn->pad = 0L;
10121556Srgrimes	hd = (HD_BCPIO *)buf;
10131556Srgrimes	if (swp_head) {
10141556Srgrimes		/*
101546684Skris		 * header has swapped bytes on 16 bit boundaries
10161556Srgrimes		 */
10171556Srgrimes		arcn->sb.st_dev = (dev_t)(RSHRT_EXT(hd->h_dev));
10181556Srgrimes		arcn->sb.st_ino = (ino_t)(RSHRT_EXT(hd->h_ino));
10191556Srgrimes		arcn->sb.st_mode = (mode_t)(RSHRT_EXT(hd->h_mode));
10201556Srgrimes		arcn->sb.st_uid = (uid_t)(RSHRT_EXT(hd->h_uid));
10211556Srgrimes		arcn->sb.st_gid = (gid_t)(RSHRT_EXT(hd->h_gid));
10221556Srgrimes		arcn->sb.st_nlink = (nlink_t)(RSHRT_EXT(hd->h_nlink));
10231556Srgrimes		arcn->sb.st_rdev = (dev_t)(RSHRT_EXT(hd->h_rdev));
10241556Srgrimes		arcn->sb.st_mtime = (time_t)(RSHRT_EXT(hd->h_mtime_1));
10251556Srgrimes		arcn->sb.st_mtime =  (arcn->sb.st_mtime << 16) |
10261556Srgrimes			((time_t)(RSHRT_EXT(hd->h_mtime_2)));
10271556Srgrimes		arcn->sb.st_size = (off_t)(RSHRT_EXT(hd->h_filesize_1));
10281556Srgrimes		arcn->sb.st_size = (arcn->sb.st_size << 16) |
10291556Srgrimes			((off_t)(RSHRT_EXT(hd->h_filesize_2)));
10301556Srgrimes		nsz = (int)(RSHRT_EXT(hd->h_namesize));
10311556Srgrimes	} else {
10321556Srgrimes		arcn->sb.st_dev = (dev_t)(SHRT_EXT(hd->h_dev));
10331556Srgrimes		arcn->sb.st_ino = (ino_t)(SHRT_EXT(hd->h_ino));
10341556Srgrimes		arcn->sb.st_mode = (mode_t)(SHRT_EXT(hd->h_mode));
10351556Srgrimes		arcn->sb.st_uid = (uid_t)(SHRT_EXT(hd->h_uid));
10361556Srgrimes		arcn->sb.st_gid = (gid_t)(SHRT_EXT(hd->h_gid));
10371556Srgrimes		arcn->sb.st_nlink = (nlink_t)(SHRT_EXT(hd->h_nlink));
10381556Srgrimes		arcn->sb.st_rdev = (dev_t)(SHRT_EXT(hd->h_rdev));
10391556Srgrimes		arcn->sb.st_mtime = (time_t)(SHRT_EXT(hd->h_mtime_1));
10401556Srgrimes		arcn->sb.st_mtime =  (arcn->sb.st_mtime << 16) |
10411556Srgrimes			((time_t)(SHRT_EXT(hd->h_mtime_2)));
10421556Srgrimes		arcn->sb.st_size = (off_t)(SHRT_EXT(hd->h_filesize_1));
10431556Srgrimes		arcn->sb.st_size = (arcn->sb.st_size << 16) |
10441556Srgrimes			((off_t)(SHRT_EXT(hd->h_filesize_2)));
10451556Srgrimes		nsz = (int)(SHRT_EXT(hd->h_namesize));
10461556Srgrimes	}
10471556Srgrimes	arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
10481556Srgrimes
10491556Srgrimes	/*
10501556Srgrimes	 * check the file name size, if bogus give up. otherwise read the file
10511556Srgrimes	 * name
10521556Srgrimes	 */
10531556Srgrimes	if (nsz < 2)
10541556Srgrimes		return(-1);
10551556Srgrimes	arcn->nlen = nsz - 1;
10561556Srgrimes	if (rd_nm(arcn, nsz) < 0)
10571556Srgrimes		return(-1);
10581556Srgrimes
10591556Srgrimes	/*
10601556Srgrimes	 * header + file name are aligned to 2 byte boundries, skip if needed
10611556Srgrimes	 */
10621556Srgrimes	if (rd_skip((off_t)(BCPIO_PAD(sizeof(HD_BCPIO) + nsz))) < 0)
10631556Srgrimes		return(-1);
10641556Srgrimes
10651556Srgrimes	/*
10661556Srgrimes	 * if not a link (or a file with no data), calculate pad size (for
10671556Srgrimes	 * padding which follows the file data), clear the link name and return
10681556Srgrimes	 */
10691556Srgrimes	if (((arcn->sb.st_mode & C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)){
10701556Srgrimes		/*
10711556Srgrimes		 * we have a valid header (not a link)
10721556Srgrimes		 */
10731556Srgrimes		arcn->ln_nlen = 0;
10741556Srgrimes		arcn->ln_name[0] = '\0';
10751556Srgrimes		arcn->pad = BCPIO_PAD(arcn->sb.st_size);
10761556Srgrimes		return(com_rd(arcn));
10771556Srgrimes	}
10781556Srgrimes
10791556Srgrimes	if ((rd_ln_nm(arcn) < 0) ||
10801556Srgrimes	    (rd_skip((off_t)(BCPIO_PAD(arcn->sb.st_size))) < 0))
10811556Srgrimes		return(-1);
10821556Srgrimes
10831556Srgrimes	/*
10841556Srgrimes	 * we have a valid header (with a link)
10851556Srgrimes	 */
10861556Srgrimes	return(com_rd(arcn));
10871556Srgrimes}
10881556Srgrimes
10891556Srgrimes/*
10901556Srgrimes * bcpio_endrd()
10911556Srgrimes *      no cleanup needed here, just return size of the trailer (for append)
10921556Srgrimes * Return:
10931556Srgrimes *      size of trailer header in this format
10941556Srgrimes */
10951556Srgrimes
10961556Srgrimes#if __STDC__
10971556Srgrimesoff_t
10981556Srgrimesbcpio_endrd(void)
10991556Srgrimes#else
11001556Srgrimesoff_t
11011556Srgrimesbcpio_endrd()
11021556Srgrimes#endif
11031556Srgrimes{
11041556Srgrimes	return((off_t)(sizeof(HD_BCPIO) + sizeof(TRAILER) +
11051556Srgrimes		(BCPIO_PAD(sizeof(HD_BCPIO) + sizeof(TRAILER)))));
11061556Srgrimes}
11071556Srgrimes
11081556Srgrimes/*
11091556Srgrimes * bcpio_wr()
11101556Srgrimes *	copy the data in the ARCHD to buffer in old binary cpio format
11111556Srgrimes *	There is a real chance of field overflow with this critter. So we
11121556Srgrimes *	always check the conversion is ok. nobody in his their right mind
11131556Srgrimes *	should write an achive in this format...
11141556Srgrimes * Return
11151556Srgrimes *      0 if file has data to be written after the header, 1 if file has NO
11161556Srgrimes *	data to write after the header, -1 if archive write failed
11171556Srgrimes */
11181556Srgrimes
11191556Srgrimes#if __STDC__
11201556Srgrimesint
11211556Srgrimesbcpio_wr(register ARCHD *arcn)
11221556Srgrimes#else
11231556Srgrimesint
11241556Srgrimesbcpio_wr(arcn)
11251556Srgrimes	register ARCHD *arcn;
11261556Srgrimes#endif
11271556Srgrimes{
11281556Srgrimes	register HD_BCPIO *hd;
11291556Srgrimes	register int nsz;
11301556Srgrimes	char hdblk[sizeof(HD_BCPIO)];
11311556Srgrimes	off_t t_offt;
11321556Srgrimes	int t_int;
11331556Srgrimes	time_t t_timet;
11341556Srgrimes
11351556Srgrimes	/*
11361556Srgrimes	 * check and repair truncated device and inode fields in the cpio
11371556Srgrimes	 * header
11381556Srgrimes	 */
11391556Srgrimes	if (map_dev(arcn, (u_long)BCPIO_MASK, (u_long)BCPIO_MASK) < 0)
11401556Srgrimes		return(-1);
11411556Srgrimes
11421556Srgrimes	if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR))
11431556Srgrimes		arcn->sb.st_rdev = 0;
11441556Srgrimes	hd = (HD_BCPIO *)hdblk;
11451556Srgrimes
11461556Srgrimes	switch(arcn->type) {
11471556Srgrimes	case PAX_CTG:
11481556Srgrimes	case PAX_REG:
11491556Srgrimes	case PAX_HRG:
11501556Srgrimes		/*
11511556Srgrimes		 * caller will copy file data to the archive. tell him how
11521556Srgrimes		 * much to pad.
11531556Srgrimes		 */
11541556Srgrimes		arcn->pad = BCPIO_PAD(arcn->sb.st_size);
11551556Srgrimes		hd->h_filesize_1[0] = CHR_WR_0(arcn->sb.st_size);
11561556Srgrimes		hd->h_filesize_1[1] = CHR_WR_1(arcn->sb.st_size);
11571556Srgrimes		hd->h_filesize_2[0] = CHR_WR_2(arcn->sb.st_size);
11581556Srgrimes		hd->h_filesize_2[1] = CHR_WR_3(arcn->sb.st_size);
11591556Srgrimes		t_offt = (off_t)(SHRT_EXT(hd->h_filesize_1));
11601556Srgrimes		t_offt = (t_offt<<16) | ((off_t)(SHRT_EXT(hd->h_filesize_2)));
11611556Srgrimes		if (arcn->sb.st_size != t_offt) {
116228904Ssos			pax_warn(1,"File is too large for bcpio format %s",
11631556Srgrimes			    arcn->org_name);
11641556Srgrimes			return(1);
11651556Srgrimes		}
11661556Srgrimes		break;
11671556Srgrimes	case PAX_SLK:
11681556Srgrimes		/*
11691556Srgrimes		 * no file data for the caller to process, the file data has
11701556Srgrimes		 * the size of the link
11711556Srgrimes		 */
11721556Srgrimes		arcn->pad = 0L;
11731556Srgrimes		hd->h_filesize_1[0] = CHR_WR_0(arcn->ln_nlen);
11741556Srgrimes		hd->h_filesize_1[1] = CHR_WR_1(arcn->ln_nlen);
11751556Srgrimes		hd->h_filesize_2[0] = CHR_WR_2(arcn->ln_nlen);
11761556Srgrimes		hd->h_filesize_2[1] = CHR_WR_3(arcn->ln_nlen);
11771556Srgrimes		t_int = (int)(SHRT_EXT(hd->h_filesize_1));
11781556Srgrimes		t_int = (t_int << 16) | ((int)(SHRT_EXT(hd->h_filesize_2)));
11791556Srgrimes		if (arcn->ln_nlen != t_int)
11801556Srgrimes			goto out;
11811556Srgrimes		break;
11821556Srgrimes	default:
11831556Srgrimes		/*
11841556Srgrimes		 * no file data for the caller to process
11851556Srgrimes		 */
11861556Srgrimes		arcn->pad = 0L;
11871556Srgrimes		hd->h_filesize_1[0] = (char)0;
11881556Srgrimes		hd->h_filesize_1[1] = (char)0;
11891556Srgrimes		hd->h_filesize_2[0] = (char)0;
11901556Srgrimes		hd->h_filesize_2[1] = (char)0;
11911556Srgrimes		break;
11921556Srgrimes	}
11931556Srgrimes
11941556Srgrimes	/*
11951556Srgrimes	 * build up the rest of the fields
11961556Srgrimes	 */
11971556Srgrimes	hd->h_magic[0] = CHR_WR_2(MAGIC);
11981556Srgrimes	hd->h_magic[1] = CHR_WR_3(MAGIC);
11991556Srgrimes	hd->h_dev[0] = CHR_WR_2(arcn->sb.st_dev);
12001556Srgrimes	hd->h_dev[1] = CHR_WR_3(arcn->sb.st_dev);
12011556Srgrimes	if (arcn->sb.st_dev != (dev_t)(SHRT_EXT(hd->h_dev)))
12021556Srgrimes		goto out;
12031556Srgrimes	hd->h_ino[0] = CHR_WR_2(arcn->sb.st_ino);
12041556Srgrimes	hd->h_ino[1] = CHR_WR_3(arcn->sb.st_ino);
12051556Srgrimes	if (arcn->sb.st_ino != (ino_t)(SHRT_EXT(hd->h_ino)))
12061556Srgrimes		goto out;
12071556Srgrimes	hd->h_mode[0] = CHR_WR_2(arcn->sb.st_mode);
12081556Srgrimes	hd->h_mode[1] = CHR_WR_3(arcn->sb.st_mode);
12091556Srgrimes	if (arcn->sb.st_mode != (mode_t)(SHRT_EXT(hd->h_mode)))
12101556Srgrimes		goto out;
12111556Srgrimes	hd->h_uid[0] = CHR_WR_2(arcn->sb.st_uid);
12121556Srgrimes	hd->h_uid[1] = CHR_WR_3(arcn->sb.st_uid);
12131556Srgrimes	if (arcn->sb.st_uid != (uid_t)(SHRT_EXT(hd->h_uid)))
12141556Srgrimes		goto out;
12151556Srgrimes	hd->h_gid[0] = CHR_WR_2(arcn->sb.st_gid);
12161556Srgrimes	hd->h_gid[1] = CHR_WR_3(arcn->sb.st_gid);
12171556Srgrimes	if (arcn->sb.st_gid != (gid_t)(SHRT_EXT(hd->h_gid)))
12181556Srgrimes		goto out;
12191556Srgrimes	hd->h_nlink[0] = CHR_WR_2(arcn->sb.st_nlink);
12201556Srgrimes	hd->h_nlink[1] = CHR_WR_3(arcn->sb.st_nlink);
12211556Srgrimes	if (arcn->sb.st_nlink != (nlink_t)(SHRT_EXT(hd->h_nlink)))
12221556Srgrimes		goto out;
12231556Srgrimes	hd->h_rdev[0] = CHR_WR_2(arcn->sb.st_rdev);
12241556Srgrimes	hd->h_rdev[1] = CHR_WR_3(arcn->sb.st_rdev);
12251556Srgrimes	if (arcn->sb.st_rdev != (dev_t)(SHRT_EXT(hd->h_rdev)))
12261556Srgrimes		goto out;
12271556Srgrimes	hd->h_mtime_1[0] = CHR_WR_0(arcn->sb.st_mtime);
12281556Srgrimes	hd->h_mtime_1[1] = CHR_WR_1(arcn->sb.st_mtime);
12291556Srgrimes	hd->h_mtime_2[0] = CHR_WR_2(arcn->sb.st_mtime);
12301556Srgrimes	hd->h_mtime_2[1] = CHR_WR_3(arcn->sb.st_mtime);
12311556Srgrimes	t_timet = (time_t)(SHRT_EXT(hd->h_mtime_1));
12321556Srgrimes	t_timet =  (t_timet << 16) | ((time_t)(SHRT_EXT(hd->h_mtime_2)));
12331556Srgrimes	if (arcn->sb.st_mtime != t_timet)
12341556Srgrimes		goto out;
12351556Srgrimes	nsz = arcn->nlen + 1;
12361556Srgrimes	hd->h_namesize[0] = CHR_WR_2(nsz);
12371556Srgrimes	hd->h_namesize[1] = CHR_WR_3(nsz);
12381556Srgrimes	if (nsz != (int)(SHRT_EXT(hd->h_namesize)))
12391556Srgrimes		goto out;
12401556Srgrimes
12411556Srgrimes	/*
12421556Srgrimes	 * write the header, the file name and padding as required.
12431556Srgrimes	 */
12441556Srgrimes	if ((wr_rdbuf(hdblk, (int)sizeof(HD_BCPIO)) < 0) ||
12451556Srgrimes	    (wr_rdbuf(arcn->name, nsz) < 0) ||
12461556Srgrimes	    (wr_skip((off_t)(BCPIO_PAD(sizeof(HD_BCPIO) + nsz))) < 0)) {
124728904Ssos		pax_warn(1, "Could not write bcpio header for %s", arcn->org_name);
12481556Srgrimes		return(-1);
12491556Srgrimes	}
12501556Srgrimes
12511556Srgrimes	/*
12521556Srgrimes	 * if we have file data, tell the caller we are done
12531556Srgrimes	 */
12541556Srgrimes	if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) ||
12551556Srgrimes	    (arcn->type == PAX_HRG))
12561556Srgrimes		return(0);
12571556Srgrimes
12581556Srgrimes	/*
12591556Srgrimes	 * if we are not a link, tell the caller we are done, go to next file
12601556Srgrimes	 */
12611556Srgrimes	if (arcn->type != PAX_SLK)
12621556Srgrimes		return(1);
12631556Srgrimes
12641556Srgrimes	/*
12651556Srgrimes	 * write the link name, tell the caller we are done.
12661556Srgrimes	 */
12671556Srgrimes	if ((wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) ||
12681556Srgrimes	    (wr_skip((off_t)(BCPIO_PAD(arcn->ln_nlen))) < 0)) {
126928904Ssos		pax_warn(1,"Could not write bcpio link name for %s",arcn->org_name);
12701556Srgrimes		return(-1);
12711556Srgrimes	}
12721556Srgrimes	return(1);
12731556Srgrimes
12741556Srgrimes    out:
12751556Srgrimes	/*
12761556Srgrimes	 * header field is out of range
12771556Srgrimes	 */
127828904Ssos	pax_warn(1,"Bcpio header field is too small for file %s", arcn->org_name);
12791556Srgrimes	return(1);
12801556Srgrimes}
1281