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