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