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