1*d653d57cSchristos /* $NetBSD: cpio.c,v 1.22 2012/08/09 08:09:21 christos Exp $ */
2b5b29542Sagc
3b5b29542Sagc /*-
4ed6ed8e6Sagc * Copyright (c) 1992 Keith Muller.
5b5b29542Sagc * Copyright (c) 1992, 1993
6b5b29542Sagc * The Regents of the University of California. All rights reserved.
7b5b29542Sagc *
8b5b29542Sagc * This code is derived from software contributed to Berkeley by
9b5b29542Sagc * Keith Muller of the University of California, San Diego.
10b5b29542Sagc *
11b5b29542Sagc * Redistribution and use in source and binary forms, with or without
12b5b29542Sagc * modification, are permitted provided that the following conditions
13b5b29542Sagc * are met:
14b5b29542Sagc * 1. Redistributions of source code must retain the above copyright
15b5b29542Sagc * notice, this list of conditions and the following disclaimer.
16b5b29542Sagc * 2. Redistributions in binary form must reproduce the above copyright
17b5b29542Sagc * notice, this list of conditions and the following disclaimer in the
18b5b29542Sagc * documentation and/or other materials provided with the distribution.
19b5b29542Sagc * 3. Neither the name of the University nor the names of its contributors
20b5b29542Sagc * may be used to endorse or promote products derived from this software
21b5b29542Sagc * without specific prior written permission.
22b5b29542Sagc *
23b5b29542Sagc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24b5b29542Sagc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25b5b29542Sagc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26b5b29542Sagc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27b5b29542Sagc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28b5b29542Sagc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29b5b29542Sagc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30b5b29542Sagc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31b5b29542Sagc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32b5b29542Sagc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33b5b29542Sagc * SUCH DAMAGE.
34b5b29542Sagc */
3549f0ad86Scgd
36171d6532Slukem #if HAVE_NBTOOL_CONFIG_H
37171d6532Slukem #include "nbtool_config.h"
38171d6532Slukem #endif
39171d6532Slukem
40f3cd6022Schristos #include <sys/cdefs.h>
41171d6532Slukem #if !defined(lint)
4249f0ad86Scgd #if 0
4349f0ad86Scgd static char sccsid[] = "@(#)cpio.c 8.1 (Berkeley) 5/31/93";
4449f0ad86Scgd #else
45*d653d57cSchristos __RCSID("$NetBSD: cpio.c,v 1.22 2012/08/09 08:09:21 christos Exp $");
4649f0ad86Scgd #endif
478b35abe2Sjtc #endif /* not lint */
488b35abe2Sjtc
498b35abe2Sjtc #include <sys/types.h>
508b35abe2Sjtc #include <sys/time.h>
518b35abe2Sjtc #include <sys/stat.h>
528b35abe2Sjtc #include <sys/param.h>
538b35abe2Sjtc #include <string.h>
548b35abe2Sjtc #include <ctype.h>
558b35abe2Sjtc #include <stdio.h>
568b35abe2Sjtc #include <unistd.h>
578b35abe2Sjtc #include <stdlib.h>
588b35abe2Sjtc #include "pax.h"
598b35abe2Sjtc #include "cpio.h"
608b35abe2Sjtc #include "extern.h"
618b35abe2Sjtc
62c1bd745cSlukem static int rd_nm(ARCHD *, int);
63c1bd745cSlukem static int rd_ln_nm(ARCHD *);
64c1bd745cSlukem static int com_rd(ARCHD *);
658b35abe2Sjtc
668b35abe2Sjtc /*
678b35abe2Sjtc * Routines which support the different cpio versions
688b35abe2Sjtc */
698b35abe2Sjtc
704b6f5a73Smrg int cpio_swp_head; /* binary cpio header byte swap */
718b35abe2Sjtc
728b35abe2Sjtc /*
738b35abe2Sjtc * Routines common to all versions of cpio
748b35abe2Sjtc */
758b35abe2Sjtc
768b35abe2Sjtc /*
778b35abe2Sjtc * cpio_strd()
788b35abe2Sjtc * Fire up the hard link detection code
798b35abe2Sjtc * Return:
808b35abe2Sjtc * 0 if ok -1 otherwise (the return values of lnk_start())
818b35abe2Sjtc */
828b35abe2Sjtc
838b35abe2Sjtc int
cpio_strd(void)848b35abe2Sjtc cpio_strd(void)
858b35abe2Sjtc {
86cdec4ac1Sdsl return lnk_start();
878b35abe2Sjtc }
888b35abe2Sjtc
898b35abe2Sjtc /*
90f3cd6022Schristos * cpio_subtrail()
918b35abe2Sjtc * Called to determine if a header block is a valid trailer. We are
928b35abe2Sjtc * passed the block, the in_sync flag (which tells us we are in resync
938b35abe2Sjtc * mode; looking for a valid header), and cnt (which starts at zero)
948b35abe2Sjtc * which is used to count the number of empty blocks we have seen so far.
958b35abe2Sjtc * Return:
968b35abe2Sjtc * 0 if a valid trailer, -1 if not a valid trailer,
978b35abe2Sjtc */
988b35abe2Sjtc
998b35abe2Sjtc int
cpio_subtrail(ARCHD * arcn)100f3cd6022Schristos cpio_subtrail(ARCHD *arcn)
1018b35abe2Sjtc {
1028b35abe2Sjtc /*
1038b35abe2Sjtc * look for trailer id in file we are about to process
1048b35abe2Sjtc */
1058b35abe2Sjtc if ((strcmp(arcn->name, TRAILER) == 0) && (arcn->sb.st_size == 0))
106cdec4ac1Sdsl return 0;
107cdec4ac1Sdsl return -1;
1088b35abe2Sjtc }
1098b35abe2Sjtc
1108b35abe2Sjtc /*
1118b35abe2Sjtc * com_rd()
1128b35abe2Sjtc * operations common to all cpio read functions.
1138b35abe2Sjtc * Return:
1148b35abe2Sjtc * 0
1158b35abe2Sjtc */
1168b35abe2Sjtc
1178b35abe2Sjtc static int
com_rd(ARCHD * arcn)11848250187Stls com_rd(ARCHD *arcn)
1198b35abe2Sjtc {
1208b35abe2Sjtc arcn->skip = 0;
1218b35abe2Sjtc arcn->pat = NULL;
1228b35abe2Sjtc arcn->org_name = arcn->name;
1238b35abe2Sjtc switch(arcn->sb.st_mode & C_IFMT) {
1248b35abe2Sjtc case C_ISFIFO:
1258b35abe2Sjtc arcn->type = PAX_FIF;
1268b35abe2Sjtc break;
1278b35abe2Sjtc case C_ISDIR:
1288b35abe2Sjtc arcn->type = PAX_DIR;
1298b35abe2Sjtc break;
1308b35abe2Sjtc case C_ISBLK:
1318b35abe2Sjtc arcn->type = PAX_BLK;
1328b35abe2Sjtc break;
1338b35abe2Sjtc case C_ISCHR:
1348b35abe2Sjtc arcn->type = PAX_CHR;
1358b35abe2Sjtc break;
1368b35abe2Sjtc case C_ISLNK:
1378b35abe2Sjtc arcn->type = PAX_SLK;
1388b35abe2Sjtc break;
1398b35abe2Sjtc case C_ISOCK:
1408b35abe2Sjtc arcn->type = PAX_SCK;
1418b35abe2Sjtc break;
1428b35abe2Sjtc case C_ISCTG:
1438b35abe2Sjtc case C_ISREG:
1448b35abe2Sjtc default:
1458b35abe2Sjtc /*
1468b35abe2Sjtc * we have file data, set up skip (pad is set in the format
1478b35abe2Sjtc * specific sections)
1488b35abe2Sjtc */
1498b35abe2Sjtc arcn->sb.st_mode = (arcn->sb.st_mode & 0xfff) | C_ISREG;
1508b35abe2Sjtc arcn->type = PAX_REG;
1518b35abe2Sjtc arcn->skip = arcn->sb.st_size;
1528b35abe2Sjtc break;
1538b35abe2Sjtc }
1548b35abe2Sjtc if (chk_lnk(arcn) < 0)
155cdec4ac1Sdsl return -1;
156cdec4ac1Sdsl return 0;
1578b35abe2Sjtc }
1588b35abe2Sjtc
1598b35abe2Sjtc /*
1608b35abe2Sjtc * cpio_end_wr()
1618b35abe2Sjtc * write the special file with the name trailer in the proper format
1628b35abe2Sjtc * Return:
1638b35abe2Sjtc * result of the write of the trailer from the cpio specific write func
1648b35abe2Sjtc */
1658b35abe2Sjtc
1668b35abe2Sjtc int
cpio_endwr(void)1678b35abe2Sjtc cpio_endwr(void)
1688b35abe2Sjtc {
1698b35abe2Sjtc ARCHD last;
1708b35abe2Sjtc
1718b35abe2Sjtc /*
1728b35abe2Sjtc * create a trailer request and call the proper format write function
1738b35abe2Sjtc */
17406f53b68Smycroft memset(&last, 0, sizeof(last));
1758b35abe2Sjtc last.nlen = sizeof(TRAILER) - 1;
1768b35abe2Sjtc last.type = PAX_REG;
1778b35abe2Sjtc last.sb.st_nlink = 1;
1788b35abe2Sjtc (void)strcpy(last.name, TRAILER);
179cdec4ac1Sdsl return (*frmt->wr)(&last);
1808b35abe2Sjtc }
1818b35abe2Sjtc
1828b35abe2Sjtc /*
1838b35abe2Sjtc * rd_nam()
1848b35abe2Sjtc * read in the file name which follows the cpio header
1858b35abe2Sjtc * Return:
1868b35abe2Sjtc * 0 if ok, -1 otherwise
1878b35abe2Sjtc */
1888b35abe2Sjtc
1898b35abe2Sjtc static int
rd_nm(ARCHD * arcn,int nsz)19048250187Stls rd_nm(ARCHD *arcn, int nsz)
1918b35abe2Sjtc {
1928b35abe2Sjtc /*
1938b35abe2Sjtc * do not even try bogus values
1948b35abe2Sjtc */
195990d25a9Slukem if ((nsz <= 0) || (nsz > (int)sizeof(arcn->name))) {
196f3cd6022Schristos tty_warn(1, "Cpio file name length %d is out of range", nsz);
197cdec4ac1Sdsl return -1;
1988b35abe2Sjtc }
1998b35abe2Sjtc
2008b35abe2Sjtc /*
2018b35abe2Sjtc * read the name and make sure it is not empty and is \0 terminated
2028b35abe2Sjtc */
2038b35abe2Sjtc if ((rd_wrbuf(arcn->name,nsz) != nsz) || (arcn->name[nsz-1] != '\0') ||
2048b35abe2Sjtc (arcn->name[0] == '\0')) {
205f3cd6022Schristos tty_warn(1, "Cpio file name in header is corrupted");
206cdec4ac1Sdsl return -1;
2078b35abe2Sjtc }
208cdec4ac1Sdsl return 0;
2098b35abe2Sjtc }
2108b35abe2Sjtc
2118b35abe2Sjtc /*
2128b35abe2Sjtc * rd_ln_nm()
2138b35abe2Sjtc * read in the link name for a file with links. The link name is stored
2148b35abe2Sjtc * like file data (and is NOT \0 terminated!)
2158b35abe2Sjtc * Return:
2168b35abe2Sjtc * 0 if ok, -1 otherwise
2178b35abe2Sjtc */
2188b35abe2Sjtc
2198b35abe2Sjtc static int
rd_ln_nm(ARCHD * arcn)22048250187Stls rd_ln_nm(ARCHD *arcn)
2218b35abe2Sjtc {
2228b35abe2Sjtc /*
2238b35abe2Sjtc * check the length specified for bogus values
2248b35abe2Sjtc */
2258b35abe2Sjtc if ((arcn->sb.st_size == 0) ||
226990d25a9Slukem (arcn->sb.st_size >= (off_t)sizeof(arcn->ln_name))) {
227c1bd745cSlukem tty_warn(1, "Cpio link name length is invalid: " OFFT_F,
228c1bd745cSlukem (OFFT_T) arcn->sb.st_size);
229cdec4ac1Sdsl return -1;
2308b35abe2Sjtc }
2318b35abe2Sjtc
2328b35abe2Sjtc /*
2338b35abe2Sjtc * read in the link name and \0 terminate it
2348b35abe2Sjtc */
2358b35abe2Sjtc if (rd_wrbuf(arcn->ln_name, (int)arcn->sb.st_size) !=
2368b35abe2Sjtc (int)arcn->sb.st_size) {
237f3cd6022Schristos tty_warn(1, "Cpio link name read error");
238cdec4ac1Sdsl return -1;
2398b35abe2Sjtc }
2408b35abe2Sjtc arcn->ln_nlen = arcn->sb.st_size;
2418b35abe2Sjtc arcn->ln_name[arcn->ln_nlen] = '\0';
2428b35abe2Sjtc
2438b35abe2Sjtc /*
2448b35abe2Sjtc * watch out for those empty link names
2458b35abe2Sjtc */
2468b35abe2Sjtc if (arcn->ln_name[0] == '\0') {
247f3cd6022Schristos tty_warn(1, "Cpio link name is corrupt");
248cdec4ac1Sdsl return -1;
2498b35abe2Sjtc }
250cdec4ac1Sdsl return 0;
2518b35abe2Sjtc }
2528b35abe2Sjtc
2538b35abe2Sjtc /*
2548b35abe2Sjtc * Routines common to the extended byte oriented cpio format
2558b35abe2Sjtc */
2568b35abe2Sjtc
2578b35abe2Sjtc /*
2588b35abe2Sjtc * cpio_id()
2598b35abe2Sjtc * determine if a block given to us is a valid extended byte oriented
2608b35abe2Sjtc * cpio header
2618b35abe2Sjtc * Return:
2628b35abe2Sjtc * 0 if a valid header, -1 otherwise
2638b35abe2Sjtc */
2648b35abe2Sjtc
2658b35abe2Sjtc int
cpio_id(char * blk,int size)2668b35abe2Sjtc cpio_id(char *blk, int size)
2678b35abe2Sjtc {
268990d25a9Slukem if ((size < (int)sizeof(HD_CPIO)) ||
2698b35abe2Sjtc (strncmp(blk, AMAGIC, sizeof(AMAGIC) - 1) != 0))
270cdec4ac1Sdsl return -1;
271cdec4ac1Sdsl return 0;
2728b35abe2Sjtc }
2738b35abe2Sjtc
2748b35abe2Sjtc /*
2758b35abe2Sjtc * cpio_rd()
2768b35abe2Sjtc * determine if a buffer is a byte oriented extended cpio archive entry.
2778b35abe2Sjtc * convert and store the values in the ARCHD parameter.
2788b35abe2Sjtc * Return:
2798b35abe2Sjtc * 0 if a valid header, -1 otherwise.
2808b35abe2Sjtc */
2818b35abe2Sjtc
2828b35abe2Sjtc int
cpio_rd(ARCHD * arcn,char * buf)28348250187Stls cpio_rd(ARCHD *arcn, char *buf)
2848b35abe2Sjtc {
28548250187Stls int nsz;
28648250187Stls HD_CPIO *hd;
2878b35abe2Sjtc
2888b35abe2Sjtc /*
2898b35abe2Sjtc * check that this is a valid header, if not return -1
2908b35abe2Sjtc */
2918b35abe2Sjtc if (cpio_id(buf, sizeof(HD_CPIO)) < 0)
292cdec4ac1Sdsl return -1;
2938b35abe2Sjtc hd = (HD_CPIO *)buf;
2948b35abe2Sjtc
2958b35abe2Sjtc /*
2968b35abe2Sjtc * byte oriented cpio (posix) does not have padding! extract the octal
2978b35abe2Sjtc * ascii fields from the header
2988b35abe2Sjtc */
2998b35abe2Sjtc arcn->pad = 0L;
300*d653d57cSchristos arcn->sb.st_dev = (dev_t)asc_u32(hd->c_dev, sizeof(hd->c_dev), OCT);
301*d653d57cSchristos arcn->sb.st_ino = (ino_t)asc_u32(hd->c_ino, sizeof(hd->c_ino), OCT);
302*d653d57cSchristos arcn->sb.st_mode = (mode_t)asc_u32(hd->c_mode, sizeof(hd->c_mode), OCT);
303*d653d57cSchristos arcn->sb.st_uid = (uid_t)asc_u32(hd->c_uid, sizeof(hd->c_uid), OCT);
304*d653d57cSchristos arcn->sb.st_gid = (gid_t)asc_u32(hd->c_gid, sizeof(hd->c_gid), OCT);
305*d653d57cSchristos arcn->sb.st_nlink = (nlink_t)asc_u32(hd->c_nlink, sizeof(hd->c_nlink),
3068b35abe2Sjtc OCT);
307*d653d57cSchristos arcn->sb.st_rdev = (dev_t)asc_u32(hd->c_rdev, sizeof(hd->c_rdev), OCT);
308*d653d57cSchristos arcn->sb.st_mtime = (time_t)(int32_t)asc_u32(hd->c_mtime, sizeof(hd->c_mtime),
3098b35abe2Sjtc OCT);
3108b35abe2Sjtc arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
311c1bd745cSlukem arcn->sb.st_size = (off_t)ASC_OFFT(hd->c_filesize,
312c1bd745cSlukem sizeof(hd->c_filesize), OCT);
3138b35abe2Sjtc
3148b35abe2Sjtc /*
3158b35abe2Sjtc * check name size and if valid, read in the name of this entry (name
3168b35abe2Sjtc * follows header in the archive)
3178b35abe2Sjtc */
318*d653d57cSchristos if ((nsz = (int)asc_u32(hd->c_namesize,sizeof(hd->c_namesize),OCT)) < 2)
319cdec4ac1Sdsl return -1;
3208b35abe2Sjtc arcn->nlen = nsz - 1;
3218b35abe2Sjtc if (rd_nm(arcn, nsz) < 0)
322cdec4ac1Sdsl return -1;
3238b35abe2Sjtc
3248b35abe2Sjtc if (((arcn->sb.st_mode&C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)) {
3258b35abe2Sjtc /*
3268b35abe2Sjtc * no link name to read for this file
3278b35abe2Sjtc */
3288b35abe2Sjtc arcn->ln_nlen = 0;
3298b35abe2Sjtc arcn->ln_name[0] = '\0';
330cdec4ac1Sdsl return com_rd(arcn);
3318b35abe2Sjtc }
3328b35abe2Sjtc
3338b35abe2Sjtc /*
3348b35abe2Sjtc * check link name size and read in the link name. Link names are
3358b35abe2Sjtc * stored like file data.
3368b35abe2Sjtc */
3378b35abe2Sjtc if (rd_ln_nm(arcn) < 0)
338cdec4ac1Sdsl return -1;
3398b35abe2Sjtc
3408b35abe2Sjtc /*
3418b35abe2Sjtc * we have a valid header (with a link)
3428b35abe2Sjtc */
343cdec4ac1Sdsl return com_rd(arcn);
3448b35abe2Sjtc }
3458b35abe2Sjtc
3468b35abe2Sjtc /*
3478b35abe2Sjtc * cpio_endrd()
3488b35abe2Sjtc * no cleanup needed here, just return size of the trailer (for append)
3498b35abe2Sjtc * Return:
3508b35abe2Sjtc * size of trailer header in this format
3518b35abe2Sjtc */
3528b35abe2Sjtc
3538b35abe2Sjtc off_t
cpio_endrd(void)3548b35abe2Sjtc cpio_endrd(void)
3558b35abe2Sjtc {
356cdec4ac1Sdsl return (off_t)(sizeof(HD_CPIO) + sizeof(TRAILER));
3578b35abe2Sjtc }
3588b35abe2Sjtc
3598b35abe2Sjtc /*
3608b35abe2Sjtc * cpio_stwr()
3618b35abe2Sjtc * start up the device mapping table
3628b35abe2Sjtc * Return:
3638b35abe2Sjtc * 0 if ok, -1 otherwise (what dev_start() returns)
3648b35abe2Sjtc */
3658b35abe2Sjtc
3668b35abe2Sjtc int
cpio_stwr(void)3678b35abe2Sjtc cpio_stwr(void)
3688b35abe2Sjtc {
369cdec4ac1Sdsl return dev_start();
3708b35abe2Sjtc }
3718b35abe2Sjtc
3728b35abe2Sjtc /*
3738b35abe2Sjtc * cpio_wr()
3748b35abe2Sjtc * copy the data in the ARCHD to buffer in extended byte oriented cpio
3758b35abe2Sjtc * format.
3768b35abe2Sjtc * Return
3778b35abe2Sjtc * 0 if file has data to be written after the header, 1 if file has NO
3788b35abe2Sjtc * data to write after the header, -1 if archive write failed
3798b35abe2Sjtc */
3808b35abe2Sjtc
3818b35abe2Sjtc int
cpio_wr(ARCHD * arcn)38248250187Stls cpio_wr(ARCHD *arcn)
3838b35abe2Sjtc {
38448250187Stls HD_CPIO *hd;
38548250187Stls int nsz;
3868b35abe2Sjtc char hdblk[sizeof(HD_CPIO)];
3878b35abe2Sjtc
3888b35abe2Sjtc /*
3898b35abe2Sjtc * check and repair truncated device and inode fields in the header
3908b35abe2Sjtc */
3918b35abe2Sjtc if (map_dev(arcn, (u_long)CPIO_MASK, (u_long)CPIO_MASK) < 0)
392cdec4ac1Sdsl return -1;
3938b35abe2Sjtc
3948b35abe2Sjtc arcn->pad = 0L;
3958b35abe2Sjtc nsz = arcn->nlen + 1;
3968b35abe2Sjtc hd = (HD_CPIO *)hdblk;
3978b35abe2Sjtc if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR))
3988b35abe2Sjtc arcn->sb.st_rdev = 0;
3998b35abe2Sjtc
4008b35abe2Sjtc switch(arcn->type) {
4018b35abe2Sjtc case PAX_CTG:
4028b35abe2Sjtc case PAX_REG:
4038b35abe2Sjtc case PAX_HRG:
4048b35abe2Sjtc /*
4058b35abe2Sjtc * set data size for file data
4068b35abe2Sjtc */
407c1bd745cSlukem if (OFFT_ASC(arcn->sb.st_size, hd->c_filesize,
4088b35abe2Sjtc sizeof(hd->c_filesize), OCT)) {
409f3cd6022Schristos tty_warn(1,"File is too large for cpio format %s",
4108b35abe2Sjtc arcn->org_name);
411cdec4ac1Sdsl return 1;
4128b35abe2Sjtc }
4138b35abe2Sjtc break;
4148b35abe2Sjtc case PAX_SLK:
4158b35abe2Sjtc /*
4168b35abe2Sjtc * set data size to hold link name
4178b35abe2Sjtc */
418*d653d57cSchristos if (u32_asc((uintmax_t)arcn->ln_nlen, hd->c_filesize,
4198b35abe2Sjtc sizeof(hd->c_filesize), OCT))
4208b35abe2Sjtc goto out;
4218b35abe2Sjtc break;
4228b35abe2Sjtc default:
4238b35abe2Sjtc /*
4248b35abe2Sjtc * all other file types have no file data
4258b35abe2Sjtc */
426*d653d57cSchristos if (u32_asc((uintmax_t)0, hd->c_filesize, sizeof(hd->c_filesize),
4278b35abe2Sjtc OCT))
4288b35abe2Sjtc goto out;
4298b35abe2Sjtc break;
4308b35abe2Sjtc }
4318b35abe2Sjtc
4328b35abe2Sjtc /*
4338b35abe2Sjtc * copy the values to the header using octal ascii
4348b35abe2Sjtc */
435*d653d57cSchristos if (u32_asc((uintmax_t)MAGIC, hd->c_magic, sizeof(hd->c_magic), OCT) ||
436*d653d57cSchristos u32_asc((uintmax_t)arcn->sb.st_dev, hd->c_dev, sizeof(hd->c_dev),
4378b35abe2Sjtc OCT) ||
438*d653d57cSchristos u32_asc((uintmax_t)arcn->sb.st_ino, hd->c_ino, sizeof(hd->c_ino),
4398b35abe2Sjtc OCT) ||
440*d653d57cSchristos u32_asc((uintmax_t)arcn->sb.st_mode, hd->c_mode, sizeof(hd->c_mode),
4418b35abe2Sjtc OCT) ||
442*d653d57cSchristos u32_asc((uintmax_t)arcn->sb.st_uid, hd->c_uid, sizeof(hd->c_uid),
4438b35abe2Sjtc OCT) ||
444*d653d57cSchristos u32_asc((uintmax_t)arcn->sb.st_gid, hd->c_gid, sizeof(hd->c_gid),
4458b35abe2Sjtc OCT) ||
446*d653d57cSchristos u32_asc((uintmax_t)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink),
4478b35abe2Sjtc OCT) ||
448*d653d57cSchristos u32_asc((uintmax_t)arcn->sb.st_rdev, hd->c_rdev, sizeof(hd->c_rdev),
4498b35abe2Sjtc OCT) ||
450*d653d57cSchristos u32_asc((uintmax_t)arcn->sb.st_mtime,hd->c_mtime,sizeof(hd->c_mtime),
4518b35abe2Sjtc OCT) ||
452*d653d57cSchristos u32_asc((uintmax_t)nsz, hd->c_namesize, sizeof(hd->c_namesize), OCT))
4538b35abe2Sjtc goto out;
4548b35abe2Sjtc
4558b35abe2Sjtc /*
4568b35abe2Sjtc * write the file name to the archive
4578b35abe2Sjtc */
4588b35abe2Sjtc if ((wr_rdbuf(hdblk, (int)sizeof(HD_CPIO)) < 0) ||
4598b35abe2Sjtc (wr_rdbuf(arcn->name, nsz) < 0)) {
460f3cd6022Schristos tty_warn(1, "Unable to write cpio header for %s",
461f3cd6022Schristos arcn->org_name);
462cdec4ac1Sdsl return -1;
4638b35abe2Sjtc }
4648b35abe2Sjtc
4658b35abe2Sjtc /*
4668b35abe2Sjtc * if this file has data, we are done. The caller will write the file
4678b35abe2Sjtc * data, if we are link tell caller we are done, go to next file
4688b35abe2Sjtc */
469f57592cdSmatt if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG))
470cdec4ac1Sdsl return 0;
4718b35abe2Sjtc if (arcn->type != PAX_SLK)
472cdec4ac1Sdsl return 1;
4738b35abe2Sjtc
4748b35abe2Sjtc /*
4758b35abe2Sjtc * write the link name to the archive, tell the caller to go to the
4768b35abe2Sjtc * next file as we are done.
4778b35abe2Sjtc */
4788b35abe2Sjtc if (wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) {
479f3cd6022Schristos tty_warn(1,"Unable to write cpio link name for %s",
480f3cd6022Schristos arcn->org_name);
481cdec4ac1Sdsl return -1;
4828b35abe2Sjtc }
483cdec4ac1Sdsl return 1;
4848b35abe2Sjtc
4858b35abe2Sjtc out:
4868b35abe2Sjtc /*
4878b35abe2Sjtc * header field is out of range
4888b35abe2Sjtc */
489f3cd6022Schristos tty_warn(1, "Cpio header field is too small to store file %s",
4908b35abe2Sjtc arcn->org_name);
491cdec4ac1Sdsl return 1;
4928b35abe2Sjtc }
4938b35abe2Sjtc
4948b35abe2Sjtc /*
4958b35abe2Sjtc * Routines common to the system VR4 version of cpio (with/without file CRC)
4968b35abe2Sjtc */
4978b35abe2Sjtc
4988b35abe2Sjtc /*
4998b35abe2Sjtc * vcpio_id()
5008b35abe2Sjtc * determine if a block given to us is a valid system VR4 cpio header
5018b35abe2Sjtc * WITHOUT crc. WATCH it the magic cookies are in OCTAL, the header
5028b35abe2Sjtc * uses HEX
5038b35abe2Sjtc * Return:
5048b35abe2Sjtc * 0 if a valid header, -1 otherwise
5058b35abe2Sjtc */
5068b35abe2Sjtc
5078b35abe2Sjtc int
vcpio_id(char * blk,int size)5088b35abe2Sjtc vcpio_id(char *blk, int size)
5098b35abe2Sjtc {
510990d25a9Slukem if ((size < (int)sizeof(HD_VCPIO)) ||
5118b35abe2Sjtc (strncmp(blk, AVMAGIC, sizeof(AVMAGIC) - 1) != 0))
512cdec4ac1Sdsl return -1;
513cdec4ac1Sdsl return 0;
5148b35abe2Sjtc }
5158b35abe2Sjtc
5168b35abe2Sjtc /*
5178b35abe2Sjtc * crc_id()
5188b35abe2Sjtc * determine if a block given to us is a valid system VR4 cpio header
5198b35abe2Sjtc * WITH crc. WATCH it the magic cookies are in OCTAL the header uses HEX
5208b35abe2Sjtc * Return:
5218b35abe2Sjtc * 0 if a valid header, -1 otherwise
5228b35abe2Sjtc */
5238b35abe2Sjtc
5248b35abe2Sjtc int
crc_id(char * blk,int size)5258b35abe2Sjtc crc_id(char *blk, int size)
5268b35abe2Sjtc {
527990d25a9Slukem if ((size < (int)sizeof(HD_VCPIO)) ||
5288b35abe2Sjtc (strncmp(blk, AVCMAGIC, sizeof(AVCMAGIC) - 1) != 0))
529cdec4ac1Sdsl return -1;
530cdec4ac1Sdsl return 0;
5318b35abe2Sjtc }
5328b35abe2Sjtc
5338b35abe2Sjtc /*
5348b35abe2Sjtc * crc_strd()
535f8adf56dSitohy * set file data CRC calculations. Fire up the hard link detection code
5368b35abe2Sjtc * Return:
5378b35abe2Sjtc * 0 if ok -1 otherwise (the return values of lnk_start())
5388b35abe2Sjtc */
5398b35abe2Sjtc
5408b35abe2Sjtc int
crc_strd(void)5418b35abe2Sjtc crc_strd(void)
5428b35abe2Sjtc {
5438b35abe2Sjtc docrc = 1;
544cdec4ac1Sdsl return lnk_start();
5458b35abe2Sjtc }
5468b35abe2Sjtc
5478b35abe2Sjtc /*
5488b35abe2Sjtc * vcpio_rd()
5498b35abe2Sjtc * determine if a buffer is a system VR4 archive entry. (with/without CRC)
5508b35abe2Sjtc * convert and store the values in the ARCHD parameter.
5518b35abe2Sjtc * Return:
5528b35abe2Sjtc * 0 if a valid header, -1 otherwise.
5538b35abe2Sjtc */
5548b35abe2Sjtc
5558b35abe2Sjtc int
vcpio_rd(ARCHD * arcn,char * buf)55648250187Stls vcpio_rd(ARCHD *arcn, char *buf)
5578b35abe2Sjtc {
55848250187Stls HD_VCPIO *hd;
5598b35abe2Sjtc dev_t devminor;
5608b35abe2Sjtc dev_t devmajor;
56148250187Stls int nsz;
5628b35abe2Sjtc
5638b35abe2Sjtc /*
5648b35abe2Sjtc * during the id phase it was determined if we were using CRC, use the
5658b35abe2Sjtc * proper id routine.
5668b35abe2Sjtc */
5678b35abe2Sjtc if (docrc) {
5688b35abe2Sjtc if (crc_id(buf, sizeof(HD_VCPIO)) < 0)
569cdec4ac1Sdsl return -1;
5708b35abe2Sjtc } else {
5718b35abe2Sjtc if (vcpio_id(buf, sizeof(HD_VCPIO)) < 0)
572cdec4ac1Sdsl return -1;
5738b35abe2Sjtc }
5748b35abe2Sjtc
5758b35abe2Sjtc hd = (HD_VCPIO *)buf;
5768b35abe2Sjtc arcn->pad = 0L;
5778b35abe2Sjtc
5788b35abe2Sjtc /*
5798b35abe2Sjtc * extract the hex ascii fields from the header
5808b35abe2Sjtc */
581*d653d57cSchristos arcn->sb.st_ino = (ino_t)asc_u32(hd->c_ino, sizeof(hd->c_ino), HEX);
582*d653d57cSchristos arcn->sb.st_mode = (mode_t)asc_u32(hd->c_mode, sizeof(hd->c_mode), HEX);
583*d653d57cSchristos arcn->sb.st_uid = (uid_t)asc_u32(hd->c_uid, sizeof(hd->c_uid), HEX);
584*d653d57cSchristos arcn->sb.st_gid = (gid_t)asc_u32(hd->c_gid, sizeof(hd->c_gid), HEX);
585*d653d57cSchristos arcn->sb.st_mtime = (time_t)(int32_t)asc_u32(hd->c_mtime,sizeof(hd->c_mtime),HEX);
5868b35abe2Sjtc arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
587c1bd745cSlukem arcn->sb.st_size = (off_t)ASC_OFFT(hd->c_filesize,
5888b35abe2Sjtc sizeof(hd->c_filesize), HEX);
589*d653d57cSchristos arcn->sb.st_nlink = (nlink_t)asc_u32(hd->c_nlink, sizeof(hd->c_nlink),
5908b35abe2Sjtc HEX);
591*d653d57cSchristos devmajor = (dev_t)asc_u32(hd->c_maj, sizeof(hd->c_maj), HEX);
592*d653d57cSchristos devminor = (dev_t)asc_u32(hd->c_min, sizeof(hd->c_min), HEX);
5938b35abe2Sjtc arcn->sb.st_dev = TODEV(devmajor, devminor);
594*d653d57cSchristos devmajor = (dev_t)asc_u32(hd->c_rmaj, sizeof(hd->c_maj), HEX);
595*d653d57cSchristos devminor = (dev_t)asc_u32(hd->c_rmin, sizeof(hd->c_min), HEX);
5968b35abe2Sjtc arcn->sb.st_rdev = TODEV(devmajor, devminor);
597*d653d57cSchristos arcn->crc = asc_u32(hd->c_chksum, sizeof(hd->c_chksum), HEX);
5988b35abe2Sjtc
5998b35abe2Sjtc /*
6008b35abe2Sjtc * check the length of the file name, if ok read it in, return -1 if
6018b35abe2Sjtc * bogus
6028b35abe2Sjtc */
603*d653d57cSchristos if ((nsz = (int)asc_u32(hd->c_namesize,sizeof(hd->c_namesize),HEX)) < 2)
604cdec4ac1Sdsl return -1;
6058b35abe2Sjtc arcn->nlen = nsz - 1;
6068b35abe2Sjtc if (rd_nm(arcn, nsz) < 0)
607cdec4ac1Sdsl return -1;
6088b35abe2Sjtc
6098b35abe2Sjtc /*
610f8adf56dSitohy * skip padding. header + filename is aligned to 4 byte boundaries
6118b35abe2Sjtc */
6128b35abe2Sjtc if (rd_skip((off_t)(VCPIO_PAD(sizeof(HD_VCPIO) + nsz))) < 0)
613cdec4ac1Sdsl return -1;
6148b35abe2Sjtc
6158b35abe2Sjtc /*
6168b35abe2Sjtc * if not a link (or a file with no data), calculate pad size (for
6178b35abe2Sjtc * padding which follows the file data), clear the link name and return
6188b35abe2Sjtc */
6198b35abe2Sjtc if (((arcn->sb.st_mode&C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)) {
6208b35abe2Sjtc /*
6218b35abe2Sjtc * we have a valid header (not a link)
6228b35abe2Sjtc */
6238b35abe2Sjtc arcn->ln_nlen = 0;
6248b35abe2Sjtc arcn->ln_name[0] = '\0';
6258b35abe2Sjtc arcn->pad = VCPIO_PAD(arcn->sb.st_size);
626cdec4ac1Sdsl return com_rd(arcn);
6278b35abe2Sjtc }
6288b35abe2Sjtc
6298b35abe2Sjtc /*
6308b35abe2Sjtc * read in the link name and skip over the padding
6318b35abe2Sjtc */
6328b35abe2Sjtc if ((rd_ln_nm(arcn) < 0) ||
6338b35abe2Sjtc (rd_skip((off_t)(VCPIO_PAD(arcn->sb.st_size))) < 0))
634cdec4ac1Sdsl return -1;
6358b35abe2Sjtc
6368b35abe2Sjtc /*
6378b35abe2Sjtc * we have a valid header (with a link)
6388b35abe2Sjtc */
639cdec4ac1Sdsl return com_rd(arcn);
6408b35abe2Sjtc }
6418b35abe2Sjtc
6428b35abe2Sjtc /*
6438b35abe2Sjtc * vcpio_endrd()
6448b35abe2Sjtc * no cleanup needed here, just return size of the trailer (for append)
6458b35abe2Sjtc * Return:
6468b35abe2Sjtc * size of trailer header in this format
6478b35abe2Sjtc */
6488b35abe2Sjtc
6498b35abe2Sjtc off_t
vcpio_endrd(void)6508b35abe2Sjtc vcpio_endrd(void)
6518b35abe2Sjtc {
65266001421Smartin return (off_t)(sizeof(HD_VCPIO) + sizeof(TRAILER) +
65366001421Smartin (VCPIO_PAD(sizeof(HD_VCPIO) + sizeof(TRAILER))));
6548b35abe2Sjtc }
6558b35abe2Sjtc
6568b35abe2Sjtc /*
6578b35abe2Sjtc * crc_stwr()
6588b35abe2Sjtc * start up the device mapping table, enable crc file calculation
6598b35abe2Sjtc * Return:
6608b35abe2Sjtc * 0 if ok, -1 otherwise (what dev_start() returns)
6618b35abe2Sjtc */
6628b35abe2Sjtc
6638b35abe2Sjtc int
crc_stwr(void)6648b35abe2Sjtc crc_stwr(void)
6658b35abe2Sjtc {
6668b35abe2Sjtc docrc = 1;
667cdec4ac1Sdsl return dev_start();
6688b35abe2Sjtc }
6698b35abe2Sjtc
6708b35abe2Sjtc /*
6718b35abe2Sjtc * vcpio_wr()
6728b35abe2Sjtc * copy the data in the ARCHD to buffer in system VR4 cpio
6738b35abe2Sjtc * (with/without crc) format.
6748b35abe2Sjtc * Return
6758b35abe2Sjtc * 0 if file has data to be written after the header, 1 if file has
6768b35abe2Sjtc * NO data to write after the header, -1 if archive write failed
6778b35abe2Sjtc */
6788b35abe2Sjtc
6798b35abe2Sjtc int
vcpio_wr(ARCHD * arcn)68048250187Stls vcpio_wr(ARCHD *arcn)
6818b35abe2Sjtc {
68248250187Stls HD_VCPIO *hd;
6838b35abe2Sjtc unsigned int nsz;
6848b35abe2Sjtc char hdblk[sizeof(HD_VCPIO)];
6858b35abe2Sjtc
6868b35abe2Sjtc /*
6878b35abe2Sjtc * check and repair truncated device and inode fields in the cpio
6888b35abe2Sjtc * header
6898b35abe2Sjtc */
6908b35abe2Sjtc if (map_dev(arcn, (u_long)VCPIO_MASK, (u_long)VCPIO_MASK) < 0)
691cdec4ac1Sdsl return -1;
6928b35abe2Sjtc nsz = arcn->nlen + 1;
6938b35abe2Sjtc hd = (HD_VCPIO *)hdblk;
6948b35abe2Sjtc if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR))
6958b35abe2Sjtc arcn->sb.st_rdev = 0;
6968b35abe2Sjtc
6978b35abe2Sjtc /*
6988b35abe2Sjtc * add the proper magic value depending whether we were asked for
6998b35abe2Sjtc * file data crc's, and the crc if needed.
7008b35abe2Sjtc */
7018b35abe2Sjtc if (docrc) {
702*d653d57cSchristos if (u32_asc((uintmax_t)VCMAGIC, hd->c_magic, sizeof(hd->c_magic),
7038b35abe2Sjtc OCT) ||
704*d653d57cSchristos u32_asc((uintmax_t)arcn->crc,hd->c_chksum,sizeof(hd->c_chksum),
7058b35abe2Sjtc HEX))
7068b35abe2Sjtc goto out;
7078b35abe2Sjtc } else {
708*d653d57cSchristos if (u32_asc((uintmax_t)VMAGIC, hd->c_magic, sizeof(hd->c_magic),
7098b35abe2Sjtc OCT) ||
710*d653d57cSchristos u32_asc((uintmax_t)0, hd->c_chksum, sizeof(hd->c_chksum),HEX))
7118b35abe2Sjtc goto out;
7128b35abe2Sjtc }
7138b35abe2Sjtc
7148b35abe2Sjtc switch(arcn->type) {
7158b35abe2Sjtc case PAX_CTG:
7168b35abe2Sjtc case PAX_REG:
7178b35abe2Sjtc case PAX_HRG:
7188b35abe2Sjtc /*
7198b35abe2Sjtc * caller will copy file data to the archive. tell him how
7208b35abe2Sjtc * much to pad.
7218b35abe2Sjtc */
7228b35abe2Sjtc arcn->pad = VCPIO_PAD(arcn->sb.st_size);
723c1bd745cSlukem if (OFFT_ASC(arcn->sb.st_size, hd->c_filesize,
7248b35abe2Sjtc sizeof(hd->c_filesize), HEX)) {
725f3cd6022Schristos tty_warn(1,"File is too large for sv4cpio format %s",
7268b35abe2Sjtc arcn->org_name);
727cdec4ac1Sdsl return 1;
7288b35abe2Sjtc }
7298b35abe2Sjtc break;
7308b35abe2Sjtc case PAX_SLK:
7318b35abe2Sjtc /*
7328b35abe2Sjtc * no file data for the caller to process, the file data has
7338b35abe2Sjtc * the size of the link
7348b35abe2Sjtc */
7358b35abe2Sjtc arcn->pad = 0L;
736*d653d57cSchristos if (u32_asc((uintmax_t)arcn->ln_nlen, hd->c_filesize,
7378b35abe2Sjtc sizeof(hd->c_filesize), HEX))
7388b35abe2Sjtc goto out;
7398b35abe2Sjtc break;
7408b35abe2Sjtc default:
7418b35abe2Sjtc /*
7428b35abe2Sjtc * no file data for the caller to process
7438b35abe2Sjtc */
7448b35abe2Sjtc arcn->pad = 0L;
745*d653d57cSchristos if (u32_asc((uintmax_t)0, hd->c_filesize, sizeof(hd->c_filesize),
7468b35abe2Sjtc HEX))
7478b35abe2Sjtc goto out;
7488b35abe2Sjtc break;
7498b35abe2Sjtc }
7508b35abe2Sjtc
7518b35abe2Sjtc /*
7528b35abe2Sjtc * set the other fields in the header
7538b35abe2Sjtc */
754*d653d57cSchristos if (u32_asc((uintmax_t)arcn->sb.st_ino, hd->c_ino, sizeof(hd->c_ino),
7558b35abe2Sjtc HEX) ||
756*d653d57cSchristos u32_asc((uintmax_t)arcn->sb.st_mode, hd->c_mode, sizeof(hd->c_mode),
7578b35abe2Sjtc HEX) ||
758*d653d57cSchristos u32_asc((uintmax_t)arcn->sb.st_uid, hd->c_uid, sizeof(hd->c_uid),
7598b35abe2Sjtc HEX) ||
760*d653d57cSchristos u32_asc((uintmax_t)arcn->sb.st_gid, hd->c_gid, sizeof(hd->c_gid),
7618b35abe2Sjtc HEX) ||
762*d653d57cSchristos u32_asc((uintmax_t)arcn->sb.st_mtime, hd->c_mtime, sizeof(hd->c_mtime),
7638b35abe2Sjtc HEX) ||
764*d653d57cSchristos u32_asc((uintmax_t)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink),
7658b35abe2Sjtc HEX) ||
766*d653d57cSchristos u32_asc((uintmax_t)MAJOR(arcn->sb.st_dev),hd->c_maj, sizeof(hd->c_maj),
7678b35abe2Sjtc HEX) ||
768*d653d57cSchristos u32_asc((uintmax_t)MINOR(arcn->sb.st_dev),hd->c_min, sizeof(hd->c_min),
7698b35abe2Sjtc HEX) ||
770*d653d57cSchristos u32_asc((uintmax_t)MAJOR(arcn->sb.st_rdev),hd->c_rmaj,sizeof(hd->c_maj),
7718b35abe2Sjtc HEX) ||
772*d653d57cSchristos u32_asc((uintmax_t)MINOR(arcn->sb.st_rdev),hd->c_rmin,sizeof(hd->c_min),
7738b35abe2Sjtc HEX) ||
774*d653d57cSchristos u32_asc((uintmax_t)nsz, hd->c_namesize, sizeof(hd->c_namesize), HEX))
7758b35abe2Sjtc goto out;
7768b35abe2Sjtc
7778b35abe2Sjtc /*
7788b35abe2Sjtc * write the header, the file name and padding as required.
7798b35abe2Sjtc */
7808b35abe2Sjtc if ((wr_rdbuf(hdblk, (int)sizeof(HD_VCPIO)) < 0) ||
7818b35abe2Sjtc (wr_rdbuf(arcn->name, (int)nsz) < 0) ||
7828b35abe2Sjtc (wr_skip((off_t)(VCPIO_PAD(sizeof(HD_VCPIO) + nsz))) < 0)) {
783f3cd6022Schristos tty_warn(1,"Could not write sv4cpio header for %s",
784f3cd6022Schristos arcn->org_name);
785cdec4ac1Sdsl return -1;
7868b35abe2Sjtc }
7878b35abe2Sjtc
7888b35abe2Sjtc /*
7898b35abe2Sjtc * if we have file data, tell the caller we are done, copy the file
7908b35abe2Sjtc */
7918b35abe2Sjtc if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) ||
7928b35abe2Sjtc (arcn->type == PAX_HRG))
793cdec4ac1Sdsl return 0;
7948b35abe2Sjtc
7958b35abe2Sjtc /*
7968b35abe2Sjtc * if we are not a link, tell the caller we are done, go to next file
7978b35abe2Sjtc */
7988b35abe2Sjtc if (arcn->type != PAX_SLK)
799cdec4ac1Sdsl return 1;
8008b35abe2Sjtc
8018b35abe2Sjtc /*
8028b35abe2Sjtc * write the link name, tell the caller we are done.
8038b35abe2Sjtc */
8048b35abe2Sjtc if ((wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) ||
8058b35abe2Sjtc (wr_skip((off_t)(VCPIO_PAD(arcn->ln_nlen))) < 0)) {
806f3cd6022Schristos tty_warn(1,"Could not write sv4cpio link name for %s",
8078b35abe2Sjtc arcn->org_name);
808cdec4ac1Sdsl return -1;
8098b35abe2Sjtc }
810cdec4ac1Sdsl return 1;
8118b35abe2Sjtc
8128b35abe2Sjtc out:
8138b35abe2Sjtc /*
8148b35abe2Sjtc * header field is out of range
8158b35abe2Sjtc */
816f3cd6022Schristos tty_warn(1,"Sv4cpio header field is too small for file %s",
817f3cd6022Schristos arcn->org_name);
818cdec4ac1Sdsl return 1;
8198b35abe2Sjtc }
8208b35abe2Sjtc
8218b35abe2Sjtc /*
8228b35abe2Sjtc * Routines common to the old binary header cpio
8238b35abe2Sjtc */
8248b35abe2Sjtc
8258b35abe2Sjtc /*
8268b35abe2Sjtc * bcpio_id()
8278b35abe2Sjtc * determine if a block given to us is a old binary cpio header
8288b35abe2Sjtc * (with/without header byte swapping)
8298b35abe2Sjtc * Return:
8308b35abe2Sjtc * 0 if a valid header, -1 otherwise
8318b35abe2Sjtc */
8328b35abe2Sjtc
8338b35abe2Sjtc int
bcpio_id(char * blk,int size)8348b35abe2Sjtc bcpio_id(char *blk, int size)
8358b35abe2Sjtc {
836990d25a9Slukem if (size < (int)sizeof(HD_BCPIO))
837cdec4ac1Sdsl return -1;
8388b35abe2Sjtc
8398b35abe2Sjtc /*
8408b35abe2Sjtc * check both normal and byte swapped magic cookies
8418b35abe2Sjtc */
8428b35abe2Sjtc if (((u_short)SHRT_EXT(blk)) == MAGIC)
843cdec4ac1Sdsl return 0;
8448b35abe2Sjtc if (((u_short)RSHRT_EXT(blk)) == MAGIC) {
8454b6f5a73Smrg if (!cpio_swp_head)
8464b6f5a73Smrg ++cpio_swp_head;
847cdec4ac1Sdsl return 0;
8488b35abe2Sjtc }
849cdec4ac1Sdsl return -1;
8508b35abe2Sjtc }
8518b35abe2Sjtc
8528b35abe2Sjtc /*
8538b35abe2Sjtc * bcpio_rd()
8548b35abe2Sjtc * determine if a buffer is a old binary archive entry. (it may have byte
8558b35abe2Sjtc * swapped header) convert and store the values in the ARCHD parameter.
8568b35abe2Sjtc * This is a very old header format and should not really be used.
8578b35abe2Sjtc * Return:
8588b35abe2Sjtc * 0 if a valid header, -1 otherwise.
8598b35abe2Sjtc */
8608b35abe2Sjtc
8618b35abe2Sjtc int
bcpio_rd(ARCHD * arcn,char * buf)86248250187Stls bcpio_rd(ARCHD *arcn, char *buf)
8638b35abe2Sjtc {
86448250187Stls HD_BCPIO *hd;
86548250187Stls int nsz;
8668b35abe2Sjtc
8678b35abe2Sjtc /*
8688b35abe2Sjtc * check the header
8698b35abe2Sjtc */
8708b35abe2Sjtc if (bcpio_id(buf, sizeof(HD_BCPIO)) < 0)
871cdec4ac1Sdsl return -1;
8728b35abe2Sjtc
8738b35abe2Sjtc arcn->pad = 0L;
8748b35abe2Sjtc hd = (HD_BCPIO *)buf;
8754b6f5a73Smrg if (cpio_swp_head) {
8768b35abe2Sjtc /*
877f8adf56dSitohy * header has swapped bytes on 16 bit boundaries
8788b35abe2Sjtc */
8798b35abe2Sjtc arcn->sb.st_dev = (dev_t)(RSHRT_EXT(hd->h_dev));
8808b35abe2Sjtc arcn->sb.st_ino = (ino_t)(RSHRT_EXT(hd->h_ino));
8818b35abe2Sjtc arcn->sb.st_mode = (mode_t)(RSHRT_EXT(hd->h_mode));
8828b35abe2Sjtc arcn->sb.st_uid = (uid_t)(RSHRT_EXT(hd->h_uid));
8838b35abe2Sjtc arcn->sb.st_gid = (gid_t)(RSHRT_EXT(hd->h_gid));
8848b35abe2Sjtc arcn->sb.st_nlink = (nlink_t)(RSHRT_EXT(hd->h_nlink));
8858b35abe2Sjtc arcn->sb.st_rdev = (dev_t)(RSHRT_EXT(hd->h_rdev));
8868b35abe2Sjtc arcn->sb.st_mtime = (time_t)(RSHRT_EXT(hd->h_mtime_1));
8878b35abe2Sjtc arcn->sb.st_mtime = (arcn->sb.st_mtime << 16) |
8888b35abe2Sjtc ((time_t)(RSHRT_EXT(hd->h_mtime_2)));
8898b35abe2Sjtc arcn->sb.st_size = (off_t)(RSHRT_EXT(hd->h_filesize_1));
8908b35abe2Sjtc arcn->sb.st_size = (arcn->sb.st_size << 16) |
8918b35abe2Sjtc ((off_t)(RSHRT_EXT(hd->h_filesize_2)));
8928b35abe2Sjtc nsz = (int)(RSHRT_EXT(hd->h_namesize));
8938b35abe2Sjtc } else {
8948b35abe2Sjtc arcn->sb.st_dev = (dev_t)(SHRT_EXT(hd->h_dev));
8958b35abe2Sjtc arcn->sb.st_ino = (ino_t)(SHRT_EXT(hd->h_ino));
8968b35abe2Sjtc arcn->sb.st_mode = (mode_t)(SHRT_EXT(hd->h_mode));
8978b35abe2Sjtc arcn->sb.st_uid = (uid_t)(SHRT_EXT(hd->h_uid));
8988b35abe2Sjtc arcn->sb.st_gid = (gid_t)(SHRT_EXT(hd->h_gid));
8998b35abe2Sjtc arcn->sb.st_nlink = (nlink_t)(SHRT_EXT(hd->h_nlink));
9008b35abe2Sjtc arcn->sb.st_rdev = (dev_t)(SHRT_EXT(hd->h_rdev));
9018b35abe2Sjtc arcn->sb.st_mtime = (time_t)(SHRT_EXT(hd->h_mtime_1));
9028b35abe2Sjtc arcn->sb.st_mtime = (arcn->sb.st_mtime << 16) |
9038b35abe2Sjtc ((time_t)(SHRT_EXT(hd->h_mtime_2)));
9048b35abe2Sjtc arcn->sb.st_size = (off_t)(SHRT_EXT(hd->h_filesize_1));
9058b35abe2Sjtc arcn->sb.st_size = (arcn->sb.st_size << 16) |
9068b35abe2Sjtc ((off_t)(SHRT_EXT(hd->h_filesize_2)));
9078b35abe2Sjtc nsz = (int)(SHRT_EXT(hd->h_namesize));
9088b35abe2Sjtc }
9098b35abe2Sjtc arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
9108b35abe2Sjtc
9118b35abe2Sjtc /*
9128b35abe2Sjtc * check the file name size, if bogus give up. otherwise read the file
9138b35abe2Sjtc * name
9148b35abe2Sjtc */
9158b35abe2Sjtc if (nsz < 2)
916cdec4ac1Sdsl return -1;
9178b35abe2Sjtc arcn->nlen = nsz - 1;
9188b35abe2Sjtc if (rd_nm(arcn, nsz) < 0)
919cdec4ac1Sdsl return -1;
9208b35abe2Sjtc
9218b35abe2Sjtc /*
922f8adf56dSitohy * header + file name are aligned to 2 byte boundaries, skip if needed
9238b35abe2Sjtc */
9248b35abe2Sjtc if (rd_skip((off_t)(BCPIO_PAD(sizeof(HD_BCPIO) + nsz))) < 0)
925cdec4ac1Sdsl return -1;
9268b35abe2Sjtc
9278b35abe2Sjtc /*
9288b35abe2Sjtc * if not a link (or a file with no data), calculate pad size (for
9298b35abe2Sjtc * padding which follows the file data), clear the link name and return
9308b35abe2Sjtc */
9318b35abe2Sjtc if (((arcn->sb.st_mode & C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)){
9328b35abe2Sjtc /*
9338b35abe2Sjtc * we have a valid header (not a link)
9348b35abe2Sjtc */
9358b35abe2Sjtc arcn->ln_nlen = 0;
9368b35abe2Sjtc arcn->ln_name[0] = '\0';
9378b35abe2Sjtc arcn->pad = BCPIO_PAD(arcn->sb.st_size);
938cdec4ac1Sdsl return com_rd(arcn);
9398b35abe2Sjtc }
9408b35abe2Sjtc
9418b35abe2Sjtc if ((rd_ln_nm(arcn) < 0) ||
9428b35abe2Sjtc (rd_skip((off_t)(BCPIO_PAD(arcn->sb.st_size))) < 0))
943cdec4ac1Sdsl return -1;
9448b35abe2Sjtc
9458b35abe2Sjtc /*
9468b35abe2Sjtc * we have a valid header (with a link)
9478b35abe2Sjtc */
948cdec4ac1Sdsl return com_rd(arcn);
9498b35abe2Sjtc }
9508b35abe2Sjtc
9518b35abe2Sjtc /*
9528b35abe2Sjtc * bcpio_endrd()
9538b35abe2Sjtc * no cleanup needed here, just return size of the trailer (for append)
9548b35abe2Sjtc * Return:
9558b35abe2Sjtc * size of trailer header in this format
9568b35abe2Sjtc */
9578b35abe2Sjtc
9588b35abe2Sjtc off_t
bcpio_endrd(void)9598b35abe2Sjtc bcpio_endrd(void)
9608b35abe2Sjtc {
96166001421Smartin return (off_t)(sizeof(HD_BCPIO) + sizeof(TRAILER) +
96266001421Smartin (BCPIO_PAD(sizeof(HD_BCPIO) + sizeof(TRAILER))));
9638b35abe2Sjtc }
9648b35abe2Sjtc
9658b35abe2Sjtc /*
9668b35abe2Sjtc * bcpio_wr()
9678b35abe2Sjtc * copy the data in the ARCHD to buffer in old binary cpio format
9688b35abe2Sjtc * There is a real chance of field overflow with this critter. So we
9693ac7ce18Swiz * always check the conversion is ok. nobody in their right mind
970f78eb76cSwiz * should write an archive in this format...
9718b35abe2Sjtc * Return
9728b35abe2Sjtc * 0 if file has data to be written after the header, 1 if file has NO
9738b35abe2Sjtc * data to write after the header, -1 if archive write failed
9748b35abe2Sjtc */
9758b35abe2Sjtc
9768b35abe2Sjtc int
bcpio_wr(ARCHD * arcn)97748250187Stls bcpio_wr(ARCHD *arcn)
9788b35abe2Sjtc {
97948250187Stls HD_BCPIO *hd;
98048250187Stls int nsz;
9818b35abe2Sjtc char hdblk[sizeof(HD_BCPIO)];
9828b35abe2Sjtc off_t t_offt;
9838b35abe2Sjtc int t_int;
9848b35abe2Sjtc time_t t_timet;
9858b35abe2Sjtc
9868b35abe2Sjtc /*
9878b35abe2Sjtc * check and repair truncated device and inode fields in the cpio
9888b35abe2Sjtc * header
9898b35abe2Sjtc */
9908b35abe2Sjtc if (map_dev(arcn, (u_long)BCPIO_MASK, (u_long)BCPIO_MASK) < 0)
991cdec4ac1Sdsl return -1;
9928b35abe2Sjtc
9938b35abe2Sjtc if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR))
9948b35abe2Sjtc arcn->sb.st_rdev = 0;
9958b35abe2Sjtc hd = (HD_BCPIO *)hdblk;
9968b35abe2Sjtc
9978b35abe2Sjtc switch(arcn->type) {
9988b35abe2Sjtc case PAX_CTG:
9998b35abe2Sjtc case PAX_REG:
10008b35abe2Sjtc case PAX_HRG:
10018b35abe2Sjtc /*
10028b35abe2Sjtc * caller will copy file data to the archive. tell him how
10038b35abe2Sjtc * much to pad.
10048b35abe2Sjtc */
10058b35abe2Sjtc arcn->pad = BCPIO_PAD(arcn->sb.st_size);
10068b35abe2Sjtc hd->h_filesize_1[0] = CHR_WR_0(arcn->sb.st_size);
10078b35abe2Sjtc hd->h_filesize_1[1] = CHR_WR_1(arcn->sb.st_size);
10088b35abe2Sjtc hd->h_filesize_2[0] = CHR_WR_2(arcn->sb.st_size);
10098b35abe2Sjtc hd->h_filesize_2[1] = CHR_WR_3(arcn->sb.st_size);
10108b35abe2Sjtc t_offt = (off_t)(SHRT_EXT(hd->h_filesize_1));
10118b35abe2Sjtc t_offt = (t_offt<<16) | ((off_t)(SHRT_EXT(hd->h_filesize_2)));
10128b35abe2Sjtc if (arcn->sb.st_size != t_offt) {
1013f3cd6022Schristos tty_warn(1,"File is too large for bcpio format %s",
10148b35abe2Sjtc arcn->org_name);
1015cdec4ac1Sdsl return 1;
10168b35abe2Sjtc }
10178b35abe2Sjtc break;
10188b35abe2Sjtc case PAX_SLK:
10198b35abe2Sjtc /*
10208b35abe2Sjtc * no file data for the caller to process, the file data has
10218b35abe2Sjtc * the size of the link
10228b35abe2Sjtc */
10238b35abe2Sjtc arcn->pad = 0L;
10248b35abe2Sjtc hd->h_filesize_1[0] = CHR_WR_0(arcn->ln_nlen);
10258b35abe2Sjtc hd->h_filesize_1[1] = CHR_WR_1(arcn->ln_nlen);
10268b35abe2Sjtc hd->h_filesize_2[0] = CHR_WR_2(arcn->ln_nlen);
10278b35abe2Sjtc hd->h_filesize_2[1] = CHR_WR_3(arcn->ln_nlen);
10288b35abe2Sjtc t_int = (int)(SHRT_EXT(hd->h_filesize_1));
10298b35abe2Sjtc t_int = (t_int << 16) | ((int)(SHRT_EXT(hd->h_filesize_2)));
10308b35abe2Sjtc if (arcn->ln_nlen != t_int)
10318b35abe2Sjtc goto out;
10328b35abe2Sjtc break;
10338b35abe2Sjtc default:
10348b35abe2Sjtc /*
10358b35abe2Sjtc * no file data for the caller to process
10368b35abe2Sjtc */
10378b35abe2Sjtc arcn->pad = 0L;
10388b35abe2Sjtc hd->h_filesize_1[0] = (char)0;
10398b35abe2Sjtc hd->h_filesize_1[1] = (char)0;
10408b35abe2Sjtc hd->h_filesize_2[0] = (char)0;
10418b35abe2Sjtc hd->h_filesize_2[1] = (char)0;
10428b35abe2Sjtc break;
10438b35abe2Sjtc }
10448b35abe2Sjtc
10458b35abe2Sjtc /*
10468b35abe2Sjtc * build up the rest of the fields
10478b35abe2Sjtc */
10488b35abe2Sjtc hd->h_magic[0] = CHR_WR_2(MAGIC);
10498b35abe2Sjtc hd->h_magic[1] = CHR_WR_3(MAGIC);
10508b35abe2Sjtc hd->h_dev[0] = CHR_WR_2(arcn->sb.st_dev);
10518b35abe2Sjtc hd->h_dev[1] = CHR_WR_3(arcn->sb.st_dev);
10528b35abe2Sjtc if (arcn->sb.st_dev != (dev_t)(SHRT_EXT(hd->h_dev)))
10538b35abe2Sjtc goto out;
10548b35abe2Sjtc hd->h_ino[0] = CHR_WR_2(arcn->sb.st_ino);
10558b35abe2Sjtc hd->h_ino[1] = CHR_WR_3(arcn->sb.st_ino);
10568b35abe2Sjtc if (arcn->sb.st_ino != (ino_t)(SHRT_EXT(hd->h_ino)))
10578b35abe2Sjtc goto out;
10588b35abe2Sjtc hd->h_mode[0] = CHR_WR_2(arcn->sb.st_mode);
10598b35abe2Sjtc hd->h_mode[1] = CHR_WR_3(arcn->sb.st_mode);
10608b35abe2Sjtc if (arcn->sb.st_mode != (mode_t)(SHRT_EXT(hd->h_mode)))
10618b35abe2Sjtc goto out;
10628b35abe2Sjtc hd->h_uid[0] = CHR_WR_2(arcn->sb.st_uid);
10638b35abe2Sjtc hd->h_uid[1] = CHR_WR_3(arcn->sb.st_uid);
10648b35abe2Sjtc if (arcn->sb.st_uid != (uid_t)(SHRT_EXT(hd->h_uid)))
10658b35abe2Sjtc goto out;
10668b35abe2Sjtc hd->h_gid[0] = CHR_WR_2(arcn->sb.st_gid);
10678b35abe2Sjtc hd->h_gid[1] = CHR_WR_3(arcn->sb.st_gid);
10688b35abe2Sjtc if (arcn->sb.st_gid != (gid_t)(SHRT_EXT(hd->h_gid)))
10698b35abe2Sjtc goto out;
10708b35abe2Sjtc hd->h_nlink[0] = CHR_WR_2(arcn->sb.st_nlink);
10718b35abe2Sjtc hd->h_nlink[1] = CHR_WR_3(arcn->sb.st_nlink);
10728b35abe2Sjtc if (arcn->sb.st_nlink != (nlink_t)(SHRT_EXT(hd->h_nlink)))
10738b35abe2Sjtc goto out;
10748b35abe2Sjtc hd->h_rdev[0] = CHR_WR_2(arcn->sb.st_rdev);
10758b35abe2Sjtc hd->h_rdev[1] = CHR_WR_3(arcn->sb.st_rdev);
10768b35abe2Sjtc if (arcn->sb.st_rdev != (dev_t)(SHRT_EXT(hd->h_rdev)))
10778b35abe2Sjtc goto out;
10788b35abe2Sjtc hd->h_mtime_1[0] = CHR_WR_0(arcn->sb.st_mtime);
10798b35abe2Sjtc hd->h_mtime_1[1] = CHR_WR_1(arcn->sb.st_mtime);
10808b35abe2Sjtc hd->h_mtime_2[0] = CHR_WR_2(arcn->sb.st_mtime);
10818b35abe2Sjtc hd->h_mtime_2[1] = CHR_WR_3(arcn->sb.st_mtime);
10828b35abe2Sjtc t_timet = (time_t)(SHRT_EXT(hd->h_mtime_1));
10838b35abe2Sjtc t_timet = (t_timet << 16) | ((time_t)(SHRT_EXT(hd->h_mtime_2)));
10848b35abe2Sjtc if (arcn->sb.st_mtime != t_timet)
10858b35abe2Sjtc goto out;
10868b35abe2Sjtc nsz = arcn->nlen + 1;
10878b35abe2Sjtc hd->h_namesize[0] = CHR_WR_2(nsz);
10888b35abe2Sjtc hd->h_namesize[1] = CHR_WR_3(nsz);
10898b35abe2Sjtc if (nsz != (int)(SHRT_EXT(hd->h_namesize)))
10908b35abe2Sjtc goto out;
10918b35abe2Sjtc
10928b35abe2Sjtc /*
10938b35abe2Sjtc * write the header, the file name and padding as required.
10948b35abe2Sjtc */
10958b35abe2Sjtc if ((wr_rdbuf(hdblk, (int)sizeof(HD_BCPIO)) < 0) ||
10968b35abe2Sjtc (wr_rdbuf(arcn->name, nsz) < 0) ||
10978b35abe2Sjtc (wr_skip((off_t)(BCPIO_PAD(sizeof(HD_BCPIO) + nsz))) < 0)) {
1098f3cd6022Schristos tty_warn(1, "Could not write bcpio header for %s",
1099f3cd6022Schristos arcn->org_name);
1100cdec4ac1Sdsl return -1;
11018b35abe2Sjtc }
11028b35abe2Sjtc
11038b35abe2Sjtc /*
11048b35abe2Sjtc * if we have file data, tell the caller we are done
11058b35abe2Sjtc */
11068b35abe2Sjtc if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) ||
11078b35abe2Sjtc (arcn->type == PAX_HRG))
1108cdec4ac1Sdsl return 0;
11098b35abe2Sjtc
11108b35abe2Sjtc /*
11118b35abe2Sjtc * if we are not a link, tell the caller we are done, go to next file
11128b35abe2Sjtc */
11138b35abe2Sjtc if (arcn->type != PAX_SLK)
1114cdec4ac1Sdsl return 1;
11158b35abe2Sjtc
11168b35abe2Sjtc /*
11178b35abe2Sjtc * write the link name, tell the caller we are done.
11188b35abe2Sjtc */
11198b35abe2Sjtc if ((wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) ||
11208b35abe2Sjtc (wr_skip((off_t)(BCPIO_PAD(arcn->ln_nlen))) < 0)) {
1121f3cd6022Schristos tty_warn(1,"Could not write bcpio link name for %s",
1122f3cd6022Schristos arcn->org_name);
1123cdec4ac1Sdsl return -1;
11248b35abe2Sjtc }
1125cdec4ac1Sdsl return 1;
11268b35abe2Sjtc
11278b35abe2Sjtc out:
11288b35abe2Sjtc /*
11298b35abe2Sjtc * header field is out of range
11308b35abe2Sjtc */
1131f3cd6022Schristos tty_warn(1,"Bcpio header field is too small for file %s",
1132f3cd6022Schristos arcn->org_name);
1133cdec4ac1Sdsl return 1;
11348b35abe2Sjtc }
1135