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