More minor IPI work.
[dragonfly/vkernel-mp.git] / bin / pax / cpio.c
blob2d29f8908ba85b9c961607df9c55ea6ce7e12e6b
1 /*-
2 * Copyright (c) 1992 Keith Muller.
3 * Copyright (c) 1992, 1993
4 * The Regents of the University of California. All rights reserved.
6 * This code is derived from software contributed to Berkeley by
7 * Keith Muller of the University of California, San Diego.
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.
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.
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.8 2006/09/27 23:58:08 pavalos Exp $
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"
53 static int rd_nm (ARCHD *, int);
54 static int rd_ln_nm (ARCHD *);
55 static int com_rd (ARCHD *);
58 * Routines which support the different cpio versions
61 static int swp_head; /* binary cpio header byte swap */
64 * Routines common to all versions of cpio
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())
74 int
75 cpio_strd(void)
77 return(lnk_start());
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,
90 int
91 cpio_trail(ARCHD *arcn)
94 * look for trailer id in file we are about to process
96 if ((strcmp(arcn->name, TRAILER) == 0) && (arcn->sb.st_size == 0))
97 return(0);
98 return(-1);
102 * com_rd()
103 * operations common to all cpio read functions.
104 * Return:
108 static int
109 com_rd(ARCHD *arcn)
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:
137 * we have file data, set up skip (pad is set in the format
138 * specific sections)
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;
145 if (chk_lnk(arcn) < 0)
146 return(-1);
147 return(0);
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
158 cpio_endwr(void)
160 ARCHD last;
163 * create a trailer request and call the proper format write function
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));
174 * rd_nam()
175 * read in the file name which follows the cpio header
176 * Return:
177 * 0 if ok, -1 otherwise
180 static int
181 rd_nm(ARCHD *arcn, int nsz)
184 * do not even try bogus values
186 if ((nsz == 0) || (nsz > sizeof(arcn->name))) {
187 paxwarn(1, "Cpio file name length %d is out of range", nsz);
188 return(-1);
192 * read the name and make sure it is not empty and is \0 terminated
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);
199 return(0);
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
210 static int
211 rd_ln_nm(ARCHD *arcn)
214 * check the length specified for bogus values
216 if ((arcn->sb.st_size == 0) ||
217 (arcn->sb.st_size >= sizeof(arcn->ln_name))) {
218 paxwarn(1, "Cpio link name length is invalid: %qu",
219 arcn->sb.st_size);
220 return(-1);
224 * read in the link name and \0 terminate it
226 if (rd_wrbuf(arcn->ln_name, (int)arcn->sb.st_size) !=
227 (int)arcn->sb.st_size) {
228 paxwarn(1, "Cpio link name read error");
229 return(-1);
231 arcn->ln_nlen = arcn->sb.st_size;
232 arcn->ln_name[arcn->ln_nlen] = '\0';
235 * watch out for those empty link names
237 if (arcn->ln_name[0] == '\0') {
238 paxwarn(1, "Cpio link name is corrupt");
239 return(-1);
241 return(0);
245 * Routines common to the extended byte oriented cpio format
249 * cpio_id()
250 * determine if a block given to us is a valid extended byte oriented
251 * cpio header
252 * Return:
253 * 0 if a valid header, -1 otherwise
257 cpio_id(char *blk, int size)
259 if ((size < sizeof(HD_CPIO)) ||
260 (strncmp(blk, AMAGIC, sizeof(AMAGIC) - 1) != 0))
261 return(-1);
262 return(0);
266 * cpio_rd()
267 * determine if a buffer is a byte oriented extended cpio archive entry.
268 * convert and store the values in the ARCHD parameter.
269 * Return:
270 * 0 if a valid header, -1 otherwise.
274 cpio_rd(ARCHD *arcn, char *buf)
276 int nsz;
277 HD_CPIO *hd;
280 * check that this is a valid header, if not return -1
282 if (cpio_id(buf, sizeof(HD_CPIO)) < 0)
283 return(-1);
284 hd = (HD_CPIO *)buf;
287 * byte oriented cpio (posix) does not have padding! extract the octal
288 * ascii fields from the header
290 arcn->pad = 0L;
291 arcn->sb.st_dev = (dev_t)asc_ul(hd->c_dev, sizeof(hd->c_dev), OCT);
292 arcn->sb.st_ino = (ino_t)asc_ul(hd->c_ino, sizeof(hd->c_ino), OCT);
293 arcn->sb.st_mode = (mode_t)asc_ul(hd->c_mode, sizeof(hd->c_mode), OCT);
294 arcn->sb.st_uid = (uid_t)asc_ul(hd->c_uid, sizeof(hd->c_uid), OCT);
295 arcn->sb.st_gid = (gid_t)asc_ul(hd->c_gid, sizeof(hd->c_gid), OCT);
296 arcn->sb.st_nlink = (nlink_t)asc_ul(hd->c_nlink, sizeof(hd->c_nlink),
297 OCT);
298 arcn->sb.st_rdev = (dev_t)asc_ul(hd->c_rdev, sizeof(hd->c_rdev), OCT);
299 arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime, sizeof(hd->c_mtime),
300 OCT);
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);
306 * check name size and if valid, read in the name of this entry (name
307 * follows header in the archive)
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);
315 if (((arcn->sb.st_mode&C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)) {
317 * no link name to read for this file
319 arcn->ln_nlen = 0;
320 arcn->ln_name[0] = '\0';
321 return(com_rd(arcn));
325 * check link name size and read in the link name. Link names are
326 * stored like file data.
328 if (rd_ln_nm(arcn) < 0)
329 return(-1);
332 * we have a valid header (with a link)
334 return(com_rd(arcn));
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
344 off_t
345 cpio_endrd(void)
347 return((off_t)(sizeof(HD_CPIO) + sizeof(TRAILER)));
351 * cpio_stwr()
352 * start up the device mapping table
353 * Return:
354 * 0 if ok, -1 otherwise (what dev_start() returns)
358 cpio_stwr(void)
360 return(dev_start());
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
373 cpio_wr(ARCHD *arcn)
375 HD_CPIO *hd;
376 int nsz;
377 char hdblk[sizeof(HD_CPIO)];
380 * check and repair truncated device and inode fields in the header
382 if (map_dev(arcn, (u_long)CPIO_MASK, (u_long)CPIO_MASK) < 0)
383 return(-1);
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;
391 switch(arcn->type) {
392 case PAX_CTG:
393 case PAX_REG:
394 case PAX_HRG:
396 * set data size for file data
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);
404 break;
405 case PAX_SLK:
407 * set data size to hold link name
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:
415 * all other file types have no file data
417 if (ul_asc((u_long)0, hd->c_filesize, sizeof(hd->c_filesize),
418 OCT))
419 goto out;
420 break;
424 * copy the values to the header using octal ascii
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 ul_asc((u_long)arcn->sb.st_mtime,hd->c_mtime,sizeof(hd->c_mtime),
442 OCT) ||
443 ul_asc((u_long)nsz, hd->c_namesize, sizeof(hd->c_namesize), OCT))
444 goto out;
447 * write the file name to the archive
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);
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
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);
466 * write the link name to the archive, tell the caller to go to the
467 * next file as we are done.
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);
473 return(1);
475 out:
477 * header field is out of range
479 paxwarn(1, "Cpio header field is too small to store file %s",
480 arcn->org_name);
481 return(1);
485 * Routines common to the system VR4 version of cpio (with/without file CRC)
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
498 vcpio_id(char *blk, int size)
500 if ((size < sizeof(HD_VCPIO)) ||
501 (strncmp(blk, AVMAGIC, sizeof(AVMAGIC) - 1) != 0))
502 return(-1);
503 return(0);
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
515 crc_id(char *blk, int size)
517 if ((size < sizeof(HD_VCPIO)) ||
518 (strncmp(blk, AVCMAGIC, sizeof(AVCMAGIC) - 1) != 0))
519 return(-1);
520 return(0);
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())
531 crc_strd(void)
533 docrc = 1;
534 return(lnk_start());
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.
546 vcpio_rd(ARCHD *arcn, char *buf)
548 HD_VCPIO *hd;
549 dev_t devminor;
550 dev_t devmajor;
551 int nsz;
554 * during the id phase it was determined if we were using CRC, use the
555 * proper id routine.
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);
565 hd = (HD_VCPIO *)buf;
566 arcn->pad = 0L;
569 * extract the hex ascii fields from the header
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);
590 * check the length of the file name, if ok read it in, return -1 if
591 * bogus
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);
600 * skip padding. header + filename is aligned to 4 byte boundaries
602 if (rd_skip((off_t)(VCPIO_PAD(sizeof(HD_VCPIO) + nsz))) < 0)
603 return(-1);
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
609 if (((arcn->sb.st_mode&C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)) {
611 * we have a valid header (not a link)
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));
620 * read in the link name and skip over the padding
622 if ((rd_ln_nm(arcn) < 0) ||
623 (rd_skip((off_t)(VCPIO_PAD(arcn->sb.st_size))) < 0))
624 return(-1);
627 * we have a valid header (with a link)
629 return(com_rd(arcn));
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
639 off_t
640 vcpio_endrd(void)
642 return((off_t)(sizeof(HD_VCPIO) + sizeof(TRAILER) +
643 (VCPIO_PAD(sizeof(HD_VCPIO) + sizeof(TRAILER)))));
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)
654 crc_stwr(void)
656 docrc = 1;
657 return(dev_start());
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
670 vcpio_wr(ARCHD *arcn)
672 HD_VCPIO *hd;
673 unsigned int nsz;
674 char hdblk[sizeof(HD_VCPIO)];
677 * check and repair truncated device and inode fields in the cpio
678 * header
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;
688 * add the proper magic value depending whether we were asked for
689 * file data crc's, and the crc if needed.
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;
704 switch(arcn->type) {
705 case PAX_CTG:
706 case PAX_REG:
707 case PAX_HRG:
709 * caller will copy file data to the archive. tell him how
710 * much to pad.
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);
719 break;
720 case PAX_SLK:
722 * no file data for the caller to process, the file data has
723 * the size of the link
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:
732 * no file data for the caller to process
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;
742 * set the other fields in the header
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((u_long)arcn->sb.st_mtime, hd->c_mtime, sizeof(hd->c_mtime),
753 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;
768 * write the header, the file name and padding as required.
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);
778 * if we have file data, tell the caller we are done, copy the file
780 if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) ||
781 (arcn->type == PAX_HRG))
782 return(0);
785 * if we are not a link, tell the caller we are done, go to next file
787 if (arcn->type != PAX_SLK)
788 return(1);
791 * write the link name, tell the caller we are done.
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);
799 return(1);
801 out:
803 * header field is out of range
805 paxwarn(1,"Sv4cpio header field is too small for file %s",arcn->org_name);
806 return(1);
810 * Routines common to the old binary header cpio
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
822 bcpio_id(char *blk, int size)
824 if (size < sizeof(HD_BCPIO))
825 return(-1);
828 * check both normal and byte swapped magic cookies
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);
837 return(-1);
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.
850 bcpio_rd(ARCHD *arcn, char *buf)
852 HD_BCPIO *hd;
853 int nsz;
856 * check the header
858 if (bcpio_id(buf, sizeof(HD_BCPIO)) < 0)
859 return(-1);
861 arcn->pad = 0L;
862 hd = (HD_BCPIO *)buf;
863 if (swp_head) {
865 * header has swapped bytes on 16 bit boundaries
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));
897 arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
900 * check the file name size, if bogus give up. otherwise read the file
901 * name
903 if (nsz < 2)
904 return(-1);
905 arcn->nlen = nsz - 1;
906 if (rd_nm(arcn, nsz) < 0)
907 return(-1);
910 * header + file name are aligned to 2 byte boundaries, skip if needed
912 if (rd_skip((off_t)(BCPIO_PAD(sizeof(HD_BCPIO) + nsz))) < 0)
913 return(-1);
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
919 if (((arcn->sb.st_mode & C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)){
921 * we have a valid header (not a link)
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));
929 if ((rd_ln_nm(arcn) < 0) ||
930 (rd_skip((off_t)(BCPIO_PAD(arcn->sb.st_size))) < 0))
931 return(-1);
934 * we have a valid header (with a link)
936 return(com_rd(arcn));
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
946 off_t
947 bcpio_endrd(void)
949 return((off_t)(sizeof(HD_BCPIO) + sizeof(TRAILER) +
950 (BCPIO_PAD(sizeof(HD_BCPIO) + sizeof(TRAILER)))));
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
965 bcpio_wr(ARCHD *arcn)
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;
975 * check and repair truncated device and inode fields in the cpio
976 * header
978 if (map_dev(arcn, (u_long)BCPIO_MASK, (u_long)BCPIO_MASK) < 0)
979 return(-1);
981 if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR))
982 arcn->sb.st_rdev = 0;
983 hd = (HD_BCPIO *)hdblk;
985 switch(arcn->type) {
986 case PAX_CTG:
987 case PAX_REG:
988 case PAX_HRG:
990 * caller will copy file data to the archive. tell him how
991 * much to pad.
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);
1005 break;
1006 case PAX_SLK:
1008 * no file data for the caller to process, the file data has
1009 * the size of the link
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:
1023 * no file data for the caller to process
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;
1034 * build up the rest of the fields
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 hd->h_mtime_1[0] = CHR_WR_0(arcn->sb.st_mtime);
1067 hd->h_mtime_1[1] = CHR_WR_1(arcn->sb.st_mtime);
1068 hd->h_mtime_2[0] = CHR_WR_2(arcn->sb.st_mtime);
1069 hd->h_mtime_2[1] = CHR_WR_3(arcn->sb.st_mtime);
1070 t_timet = (time_t)(SHRT_EXT(hd->h_mtime_1));
1071 t_timet = (t_timet << 16) | ((time_t)(SHRT_EXT(hd->h_mtime_2)));
1072 if (arcn->sb.st_mtime != t_timet)
1073 goto out;
1074 nsz = arcn->nlen + 1;
1075 hd->h_namesize[0] = CHR_WR_2(nsz);
1076 hd->h_namesize[1] = CHR_WR_3(nsz);
1077 if (nsz != (int)(SHRT_EXT(hd->h_namesize)))
1078 goto out;
1081 * write the header, the file name and padding as required.
1083 if ((wr_rdbuf(hdblk, (int)sizeof(HD_BCPIO)) < 0) ||
1084 (wr_rdbuf(arcn->name, nsz) < 0) ||
1085 (wr_skip((off_t)(BCPIO_PAD(sizeof(HD_BCPIO) + nsz))) < 0)) {
1086 paxwarn(1, "Could not write bcpio header for %s", arcn->org_name);
1087 return(-1);
1091 * if we have file data, tell the caller we are done
1093 if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) ||
1094 (arcn->type == PAX_HRG))
1095 return(0);
1098 * if we are not a link, tell the caller we are done, go to next file
1100 if (arcn->type != PAX_SLK)
1101 return(1);
1104 * write the link name, tell the caller we are done.
1106 if ((wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) ||
1107 (wr_skip((off_t)(BCPIO_PAD(arcn->ln_nlen))) < 0)) {
1108 paxwarn(1,"Could not write bcpio link name for %s",arcn->org_name);
1109 return(-1);
1111 return(1);
1113 out:
1115 * header field is out of range
1117 paxwarn(1,"Bcpio header field is too small for file %s", arcn->org_name);
1118 return(1);