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