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