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