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