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