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