157198Smuller /*-
257198Smuller * Copyright (c) 1992 Keith Muller.
3*60676Sbostic * Copyright (c) 1992, 1993
4*60676Sbostic * The Regents of the University of California. All rights reserved.
557198Smuller *
657198Smuller * This code is derived from software contributed to Berkeley by
757198Smuller * Keith Muller of the University of California, San Diego.
857198Smuller *
957198Smuller * %sccs.include.redist.c%
1057198Smuller */
1157198Smuller
1257198Smuller #ifndef lint
13*60676Sbostic static char sccsid[] = "@(#)cpio.c 8.1 (Berkeley) 05/31/93";
1457198Smuller #endif /* not lint */
1557198Smuller
1657198Smuller #include <sys/types.h>
1757198Smuller #include <sys/time.h>
1857198Smuller #include <sys/stat.h>
1957198Smuller #include <sys/param.h>
2057198Smuller #include <string.h>
2157198Smuller #include <ctype.h>
2257198Smuller #include <stdio.h>
2357198Smuller #include <unistd.h>
2457198Smuller #include <stdlib.h>
2557198Smuller #include "pax.h"
2657198Smuller #include "cpio.h"
2757198Smuller #include "extern.h"
2857499Smuller
2957198Smuller static int rd_nm __P((register ARCHD *, int));
3057198Smuller static int rd_ln_nm __P((register ARCHD *));
3157198Smuller static int com_rd __P((register ARCHD *));
3257198Smuller
3357198Smuller /*
3457198Smuller * Routines which support the different cpio versions
3557198Smuller */
3657198Smuller
3757198Smuller static int swp_head; /* binary cpio header byte swap */
3857198Smuller
3957198Smuller /*
4057198Smuller * Routines common to all versions of cpio
4157198Smuller */
4257198Smuller
4357198Smuller /*
4457198Smuller * cpio_strd()
4557198Smuller * Fire up the hard link detection code
4657198Smuller * Return:
4757198Smuller * 0 if ok -1 otherwise (the return values of lnk_start())
4857198Smuller */
4957198Smuller
5057198Smuller #if __STDC__
5157198Smuller int
cpio_strd(void)5257198Smuller cpio_strd(void)
5357198Smuller #else
5457198Smuller int
5557198Smuller cpio_strd()
5657198Smuller #endif
5757198Smuller {
5857198Smuller return(lnk_start());
5957198Smuller }
6057198Smuller
6157198Smuller /*
6257198Smuller * cpio_trail()
6357198Smuller * Called to determine if a header block is a valid trailer. We are
6457198Smuller * passed the block, the in_sync flag (which tells us we are in resync
6557198Smuller * mode; looking for a valid header), and cnt (which starts at zero)
6657198Smuller * which is used to count the number of empty blocks we have seen so far.
6757198Smuller * Return:
6857198Smuller * 0 if a valid trailer, -1 if not a valid trailer,
6957198Smuller */
7057198Smuller
7157198Smuller #if __STDC__
7257198Smuller int
cpio_trail(register ARCHD * arcn)7357198Smuller cpio_trail(register ARCHD *arcn)
7457198Smuller #else
7557198Smuller int
7657198Smuller cpio_trail(arcn)
7757198Smuller register ARCHD *arcn;
7857198Smuller #endif
7957198Smuller {
8057198Smuller /*
8157198Smuller * look for trailer id in file we are about to process
8257198Smuller */
8357198Smuller if ((strcmp(arcn->name, TRAILER) == 0) && (arcn->sb.st_size == 0))
8457198Smuller return(0);
8557198Smuller return(-1);
8657198Smuller }
8757198Smuller
8857198Smuller /*
8957198Smuller * com_rd()
9057198Smuller * operations common to all cpio read functions.
9157198Smuller * Return:
9257198Smuller * 0
9357198Smuller */
9457198Smuller
9557198Smuller #if __STDC__
9657198Smuller static int
com_rd(register ARCHD * arcn)9757198Smuller com_rd(register ARCHD *arcn)
9857198Smuller #else
9957198Smuller static int
10057198Smuller com_rd(arcn)
10157198Smuller register ARCHD *arcn;
10257198Smuller #endif
10357198Smuller {
10457198Smuller arcn->skip = 0;
10557198Smuller arcn->pat = NULL;
10657198Smuller arcn->org_name = arcn->name;
10757198Smuller switch(arcn->sb.st_mode & C_IFMT) {
10857198Smuller case C_ISFIFO:
10957198Smuller arcn->type = PAX_FIF;
11057198Smuller break;
11157198Smuller case C_ISDIR:
11257198Smuller arcn->type = PAX_DIR;
11357198Smuller break;
11457198Smuller case C_ISBLK:
11557198Smuller arcn->type = PAX_BLK;
11657198Smuller break;
11757198Smuller case C_ISCHR:
11857198Smuller arcn->type = PAX_CHR;
11957198Smuller break;
12057198Smuller case C_ISLNK:
12157198Smuller arcn->type = PAX_SLK;
12257198Smuller break;
12357198Smuller case C_ISOCK:
12457198Smuller arcn->type = PAX_SCK;
12557198Smuller break;
12657198Smuller case C_ISCTG:
12757198Smuller case C_ISREG:
12857198Smuller default:
12957198Smuller /*
13057198Smuller * we have file data, set up skip (pad is set in the format
13157198Smuller * specific sections)
13257198Smuller */
13357198Smuller arcn->sb.st_mode = (arcn->sb.st_mode & 0xfff) | C_ISREG;
13457198Smuller arcn->type = PAX_REG;
13557198Smuller arcn->skip = arcn->sb.st_size;
13657198Smuller break;
13757198Smuller }
13857198Smuller if (chk_lnk(arcn) < 0)
13957198Smuller return(-1);
14057198Smuller return(0);
14157198Smuller }
14257198Smuller
14357198Smuller /*
14457198Smuller * cpio_end_wr()
14557198Smuller * write the special file with the name trailer in the proper format
14657198Smuller * Return:
14757198Smuller * result of the write of the trailer from the cpio specific write func
14857198Smuller */
14957198Smuller
15057198Smuller #if __STDC__
15157198Smuller int
cpio_endwr(void)15257198Smuller cpio_endwr(void)
15357198Smuller #else
15457198Smuller int
15557198Smuller cpio_endwr()
15657198Smuller #endif
15757198Smuller {
15857198Smuller ARCHD last;
15957198Smuller
16057198Smuller /*
16157198Smuller * create a trailer request and call the proper format write function
16257198Smuller */
16357198Smuller bzero((char *)&last, sizeof(last));
16457198Smuller last.nlen = sizeof(TRAILER) - 1;
16557198Smuller last.type = PAX_REG;
16657198Smuller last.sb.st_nlink = 1;
16757198Smuller (void)strcpy(last.name, TRAILER);
16857198Smuller return((*frmt->wr)(&last));
16957198Smuller }
17057198Smuller
17157198Smuller /*
17257198Smuller * rd_nam()
17357198Smuller * read in the file name which follows the cpio header
17457198Smuller * Return:
17557198Smuller * 0 if ok, -1 otherwise
17657198Smuller */
17757198Smuller
17857198Smuller #if __STDC__
17957198Smuller static int
rd_nm(register ARCHD * arcn,int nsz)18057198Smuller rd_nm(register ARCHD *arcn, int nsz)
18157198Smuller #else
18257198Smuller static int
18357198Smuller rd_nm(arcn, nsz)
18457198Smuller register ARCHD *arcn;
18557198Smuller int nsz;
18657198Smuller #endif
18757198Smuller {
18857198Smuller /*
18957198Smuller * do not even try bogus values
19057198Smuller */
19157198Smuller if ((nsz == 0) || (nsz > sizeof(arcn->name))) {
19257198Smuller warn(1, "Cpio file name length %d is out of range", nsz);
19357198Smuller return(-1);
19457198Smuller }
19557198Smuller
19657198Smuller /*
19757198Smuller * read the name and make sure it is not empty and is \0 terminated
19857198Smuller */
19957198Smuller if ((rd_wrbuf(arcn->name,nsz) != nsz) || (arcn->name[nsz-1] != '\0') ||
20057198Smuller (arcn->name[0] == '\0')) {
20157198Smuller warn(1, "Cpio file name in header is corrupted");
20257198Smuller return(-1);
20357198Smuller }
20457198Smuller return(0);
20557198Smuller }
20657198Smuller
20757198Smuller /*
20857198Smuller * rd_ln_nm()
20957198Smuller * read in the link name for a file with links. The link name is stored
21057198Smuller * like file data (and is NOT \0 terminated!)
21157198Smuller * Return:
21257198Smuller * 0 if ok, -1 otherwise
21357198Smuller */
21457198Smuller
21557198Smuller #if __STDC__
21657198Smuller static int
rd_ln_nm(register ARCHD * arcn)21757198Smuller rd_ln_nm(register ARCHD *arcn)
21857198Smuller #else
21957198Smuller static int
22057198Smuller rd_ln_nm(arcn)
22157198Smuller register ARCHD *arcn;
22257198Smuller #endif
22357198Smuller {
22457198Smuller /*
22557198Smuller * check the length specified for bogus values
22657198Smuller */
22757198Smuller if ((arcn->sb.st_size == 0) ||
22857198Smuller (arcn->sb.st_size >= sizeof(arcn->ln_name))) {
22957198Smuller # ifdef NET2_STAT
23057198Smuller warn(1, "Cpio link name length is invalid: %lu",
23157198Smuller arcn->sb.st_size);
23257198Smuller # else
23357198Smuller warn(1, "Cpio link name length is invalid: %qu",
23457198Smuller arcn->sb.st_size);
23557198Smuller # endif
23657198Smuller return(-1);
23757198Smuller }
23857198Smuller
23957198Smuller /*
24057198Smuller * read in the link name and \0 terminate it
24157198Smuller */
24257198Smuller if (rd_wrbuf(arcn->ln_name, (int)arcn->sb.st_size) !=
24357198Smuller (int)arcn->sb.st_size) {
24457198Smuller warn(1, "Cpio link name read error");
24557198Smuller return(-1);
24657198Smuller }
24757198Smuller arcn->ln_nlen = arcn->sb.st_size;
24857198Smuller arcn->ln_name[arcn->ln_nlen] = '\0';
24957198Smuller
25057198Smuller /*
25157198Smuller * watch out for those empty link names
25257198Smuller */
25357198Smuller if (arcn->ln_name[0] == '\0') {
25457198Smuller warn(1, "Cpio link name is corrupt");
25557198Smuller return(-1);
25657198Smuller }
25757198Smuller return(0);
25857198Smuller }
25957198Smuller
26057198Smuller /*
26157198Smuller * Routines common to the extended byte oriented cpio format
26257198Smuller */
26357198Smuller
26457198Smuller /*
26557198Smuller * cpio_id()
26657198Smuller * determine if a block given to us is a valid extended byte oriented
26757198Smuller * cpio header
26857198Smuller * Return:
26957198Smuller * 0 if a valid header, -1 otherwise
27057198Smuller */
27157198Smuller
27257198Smuller #if __STDC__
27357198Smuller int
cpio_id(char * blk,int size)27457198Smuller cpio_id(char *blk, int size)
27557198Smuller #else
27657198Smuller int
27757198Smuller cpio_id(blk, size)
27857198Smuller char *blk;
27957198Smuller int size;
28057198Smuller #endif
28157198Smuller {
28257198Smuller if ((size < sizeof(HD_CPIO)) ||
28357198Smuller (strncmp(blk, AMAGIC, sizeof(AMAGIC) - 1) != 0))
28457198Smuller return(-1);
28557198Smuller return(0);
28657198Smuller }
28757198Smuller
28857198Smuller /*
28957198Smuller * cpio_rd()
29057198Smuller * determine if a buffer is a byte oriented extended cpio archive entry.
29157198Smuller * convert and store the values in the ARCHD parameter.
29257198Smuller * Return:
29357198Smuller * 0 if a valid header, -1 otherwise.
29457198Smuller */
29557198Smuller
29657198Smuller #if __STDC__
29757198Smuller int
cpio_rd(register ARCHD * arcn,register char * buf)29857198Smuller cpio_rd(register ARCHD *arcn, register char *buf)
29957198Smuller #else
30057198Smuller int
30157198Smuller cpio_rd(arcn, buf)
30257198Smuller register ARCHD *arcn;
30357198Smuller register char *buf;
30457198Smuller #endif
30557198Smuller {
30657198Smuller register int nsz;
30757198Smuller register HD_CPIO *hd;
30857198Smuller
30957198Smuller /*
31057198Smuller * check that this is a valid header, if not return -1
31157198Smuller */
31257198Smuller if (cpio_id(buf, sizeof(HD_CPIO)) < 0)
31357198Smuller return(-1);
31457198Smuller hd = (HD_CPIO *)buf;
31557198Smuller
31657198Smuller /*
31757198Smuller * byte oriented cpio (posix) does not have padding! extract the octal
31857198Smuller * ascii fields from the header
31957198Smuller */
32057198Smuller arcn->pad = 0L;
32157198Smuller arcn->sb.st_dev = (dev_t)asc_ul(hd->c_dev, sizeof(hd->c_dev), OCT);
32257198Smuller arcn->sb.st_ino = (ino_t)asc_ul(hd->c_ino, sizeof(hd->c_ino), OCT);
32357198Smuller arcn->sb.st_mode = (mode_t)asc_ul(hd->c_mode, sizeof(hd->c_mode), OCT);
32457198Smuller arcn->sb.st_uid = (uid_t)asc_ul(hd->c_uid, sizeof(hd->c_uid), OCT);
32557198Smuller arcn->sb.st_gid = (gid_t)asc_ul(hd->c_gid, sizeof(hd->c_gid), OCT);
32657198Smuller arcn->sb.st_nlink = (nlink_t)asc_ul(hd->c_nlink, sizeof(hd->c_nlink),
32757198Smuller OCT);
32857198Smuller arcn->sb.st_rdev = (dev_t)asc_ul(hd->c_rdev, sizeof(hd->c_rdev), OCT);
32957198Smuller arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime, sizeof(hd->c_mtime),
33057198Smuller OCT);
33157499Smuller arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
33257198Smuller # ifdef NET2_STAT
33357198Smuller arcn->sb.st_size = (off_t)asc_ul(hd->c_filesize,sizeof(hd->c_filesize),
33457198Smuller OCT);
33557198Smuller # else
33657198Smuller arcn->sb.st_size = (off_t)asc_uqd(hd->c_filesize,sizeof(hd->c_filesize),
33757198Smuller OCT);
33857198Smuller # endif
33957198Smuller
34057198Smuller /*
34157198Smuller * check name size and if valid, read in the name of this entry (name
34257198Smuller * follows header in the archive)
34357198Smuller */
34457198Smuller if ((nsz = (int)asc_ul(hd->c_namesize,sizeof(hd->c_namesize),OCT)) < 2)
34557198Smuller return(-1);
34657198Smuller arcn->nlen = nsz - 1;
34757198Smuller if (rd_nm(arcn, nsz) < 0)
34857198Smuller return(-1);
34957198Smuller
35057198Smuller if (((arcn->sb.st_mode&C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)) {
35157198Smuller /*
35257198Smuller * no link name to read for this file
35357198Smuller */
35457198Smuller arcn->ln_nlen = 0;
35557198Smuller arcn->ln_name[0] = '\0';
35657198Smuller return(com_rd(arcn));
35757198Smuller }
35857198Smuller
35957198Smuller /*
36057198Smuller * check link name size and read in the link name. Link names are
36157198Smuller * stored like file data.
36257198Smuller */
36357198Smuller if (rd_ln_nm(arcn) < 0)
36457198Smuller return(-1);
36557198Smuller
36657198Smuller /*
36757198Smuller * we have a valid header (with a link)
36857198Smuller */
36957198Smuller return(com_rd(arcn));
37057198Smuller }
37157198Smuller
37257198Smuller /*
37357198Smuller * cpio_endrd()
37457198Smuller * no cleanup needed here, just return size of the trailer (for append)
37557198Smuller * Return:
37657198Smuller * size of trailer header in this format
37757198Smuller */
37857198Smuller
37957198Smuller #if __STDC__
38057198Smuller off_t
cpio_endrd(void)38157198Smuller cpio_endrd(void)
38257198Smuller #else
38357198Smuller off_t
38457198Smuller cpio_endrd()
38557198Smuller #endif
38657198Smuller {
38757198Smuller return((off_t)(sizeof(HD_CPIO) + sizeof(TRAILER)));
38857198Smuller }
38957198Smuller
39057198Smuller /*
39157198Smuller * cpio_stwr()
39257198Smuller * start up the device mapping table
39357198Smuller * Return:
39457198Smuller * 0 if ok, -1 otherwise (what dev_start() returns)
39557198Smuller */
39657198Smuller
39757198Smuller #if __STDC__
39857198Smuller int
cpio_stwr(void)39957198Smuller cpio_stwr(void)
40057198Smuller #else
40157198Smuller int
40257198Smuller cpio_stwr()
40357198Smuller #endif
40457198Smuller {
40557198Smuller return(dev_start());
40657198Smuller }
40757198Smuller
40857198Smuller /*
40957198Smuller * cpio_wr()
41057198Smuller * copy the data in the ARCHD to buffer in extended byte oriented cpio
41157198Smuller * format.
41257198Smuller * Return
41357198Smuller * 0 if file has data to be written after the header, 1 if file has NO
41457198Smuller * data to write after the header, -1 if archive write failed
41557198Smuller */
41657198Smuller
41757198Smuller #if __STDC__
41857198Smuller int
cpio_wr(register ARCHD * arcn)41957198Smuller cpio_wr(register ARCHD *arcn)
42057198Smuller #else
42157198Smuller int
42257198Smuller cpio_wr(arcn)
42357198Smuller register ARCHD *arcn;
42457198Smuller #endif
42557198Smuller {
42657198Smuller register HD_CPIO *hd;
42757198Smuller register int nsz;
42857198Smuller char hdblk[sizeof(HD_CPIO)];
42957198Smuller
43057198Smuller /*
43157198Smuller * check and repair truncated device and inode fields in the header
43257198Smuller */
43357198Smuller if (map_dev(arcn, (u_long)CPIO_MASK, (u_long)CPIO_MASK) < 0)
43457198Smuller return(-1);
43557198Smuller
43657198Smuller arcn->pad = 0L;
43757198Smuller nsz = arcn->nlen + 1;
43857198Smuller hd = (HD_CPIO *)hdblk;
43957198Smuller if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR))
44057198Smuller arcn->sb.st_rdev = 0;
44157198Smuller
44257198Smuller switch(arcn->type) {
44357198Smuller case PAX_CTG:
44457198Smuller case PAX_REG:
44557198Smuller case PAX_HRG:
44657198Smuller /*
44757198Smuller * set data size for file data
44857198Smuller */
44957198Smuller # ifdef NET2_STAT
45057198Smuller if (ul_asc((u_long)arcn->sb.st_size, hd->c_filesize,
45157198Smuller sizeof(hd->c_filesize), OCT)) {
45257198Smuller # else
45357198Smuller if (uqd_asc((u_quad_t)arcn->sb.st_size, hd->c_filesize,
45457198Smuller sizeof(hd->c_filesize), OCT)) {
45557198Smuller # endif
45657198Smuller warn(1,"File is too large for cpio format %s",
45757198Smuller arcn->org_name);
45857198Smuller return(1);
45957198Smuller }
46057198Smuller break;
46157198Smuller case PAX_SLK:
46257198Smuller /*
46357198Smuller * set data size to hold link name
46457198Smuller */
46557198Smuller if (ul_asc((u_long)arcn->ln_nlen, hd->c_filesize,
46657198Smuller sizeof(hd->c_filesize), OCT))
46757198Smuller goto out;
46857198Smuller break;
46957198Smuller default:
47057198Smuller /*
47157198Smuller * all other file types have no file data
47257198Smuller */
47357198Smuller if (ul_asc((u_long)0, hd->c_filesize, sizeof(hd->c_filesize),
47457198Smuller OCT))
47557198Smuller goto out;
47657198Smuller break;
47757198Smuller }
47857198Smuller
47957198Smuller /*
48057198Smuller * copy the values to the header using octal ascii
48157198Smuller */
48257198Smuller if (ul_asc((u_long)MAGIC, hd->c_magic, sizeof(hd->c_magic), OCT) ||
48357198Smuller ul_asc((u_long)arcn->sb.st_dev, hd->c_dev, sizeof(hd->c_dev),
48457198Smuller OCT) ||
48557198Smuller ul_asc((u_long)arcn->sb.st_ino, hd->c_ino, sizeof(hd->c_ino),
48657198Smuller OCT) ||
48757198Smuller ul_asc((u_long)arcn->sb.st_mode, hd->c_mode, sizeof(hd->c_mode),
48857198Smuller OCT) ||
48957198Smuller ul_asc((u_long)arcn->sb.st_uid, hd->c_uid, sizeof(hd->c_uid),
49057198Smuller OCT) ||
49157198Smuller ul_asc((u_long)arcn->sb.st_gid, hd->c_gid, sizeof(hd->c_gid),
49257198Smuller OCT) ||
49357198Smuller ul_asc((u_long)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink),
49457198Smuller OCT) ||
49557198Smuller ul_asc((u_long)arcn->sb.st_rdev, hd->c_rdev, sizeof(hd->c_rdev),
49657198Smuller OCT) ||
49757198Smuller ul_asc((u_long)arcn->sb.st_mtime,hd->c_mtime,sizeof(hd->c_mtime),
49857198Smuller OCT) ||
49957198Smuller ul_asc((u_long)nsz, hd->c_namesize, sizeof(hd->c_namesize), OCT))
50057198Smuller goto out;
50157198Smuller
50257198Smuller /*
50357198Smuller * write the file name to the archive
50457198Smuller */
50557198Smuller if ((wr_rdbuf(hdblk, (int)sizeof(HD_CPIO)) < 0) ||
50657198Smuller (wr_rdbuf(arcn->name, nsz) < 0)) {
50757198Smuller warn(1, "Unable to write cpio header for %s", arcn->org_name);
50857198Smuller return(-1);
50957198Smuller }
51057198Smuller
51157198Smuller /*
51257198Smuller * if this file has data, we are done. The caller will write the file
51357198Smuller * data, if we are link tell caller we are done, go to next file
51457198Smuller */
51557198Smuller if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) ||
51657198Smuller (arcn->type == PAX_HRG))
51757198Smuller return(0);
51857198Smuller if (arcn->type != PAX_SLK)
51957198Smuller return(1);
52057198Smuller
52157198Smuller /*
52257198Smuller * write the link name to the archive, tell the caller to go to the
52357198Smuller * next file as we are done.
52457198Smuller */
52557198Smuller if (wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) {
52657198Smuller warn(1,"Unable to write cpio link name for %s",arcn->org_name);
52757198Smuller return(-1);
52857198Smuller }
52957198Smuller return(1);
53057198Smuller
53157198Smuller out:
53257198Smuller /*
53357198Smuller * header field is out of range
53457198Smuller */
53557198Smuller warn(1, "Cpio header field is too small to store file %s",
53657198Smuller arcn->org_name);
53757198Smuller return(1);
53857198Smuller }
53957198Smuller
54057198Smuller /*
54157198Smuller * Routines common to the system VR4 version of cpio (with/without file CRC)
54257198Smuller */
54357198Smuller
54457198Smuller /*
54557198Smuller * vcpio_id()
54657198Smuller * determine if a block given to us is a valid system VR4 cpio header
54757198Smuller * WITHOUT crc. WATCH it the magic cookies are in OCTAL, the header
54857198Smuller * uses HEX
54957198Smuller * Return:
55057198Smuller * 0 if a valid header, -1 otherwise
55157198Smuller */
55257198Smuller
55357198Smuller #if __STDC__
55457198Smuller int
vcpio_id(char * blk,int size)55557198Smuller vcpio_id(char *blk, int size)
55657198Smuller #else
55757198Smuller int
55857198Smuller vcpio_id(blk, size)
55957198Smuller char *blk;
56057198Smuller int size;
56157198Smuller #endif
56257198Smuller {
56357198Smuller if ((size < sizeof(HD_VCPIO)) ||
56457198Smuller (strncmp(blk, AVMAGIC, sizeof(AVMAGIC) - 1) != 0))
56557198Smuller return(-1);
56657198Smuller return(0);
56757198Smuller }
56857198Smuller
56957198Smuller /*
57057198Smuller * crc_id()
57157198Smuller * determine if a block given to us is a valid system VR4 cpio header
57257198Smuller * WITH crc. WATCH it the magic cookies are in OCTAL the header uses HEX
57357198Smuller * Return:
57457198Smuller * 0 if a valid header, -1 otherwise
57557198Smuller */
57657198Smuller
57757198Smuller #if __STDC__
57857198Smuller int
crc_id(char * blk,int size)57957198Smuller crc_id(char *blk, int size)
58057198Smuller #else
58157198Smuller int
58257198Smuller crc_id(blk, size)
58357198Smuller char *blk;
58457198Smuller int size;
58557198Smuller #endif
58657198Smuller {
58757198Smuller if ((size < sizeof(HD_VCPIO)) ||
58857198Smuller (strncmp(blk, AVCMAGIC, sizeof(AVCMAGIC) - 1) != 0))
58957198Smuller return(-1);
59057198Smuller return(0);
59157198Smuller }
59257198Smuller
59357198Smuller /*
59457198Smuller * crc_strd()
59557198Smuller w set file data CRC calculations. Fire up the hard link detection code
59657198Smuller * Return:
59757198Smuller * 0 if ok -1 otherwise (the return values of lnk_start())
59857198Smuller */
59957198Smuller
60057198Smuller #if __STDC__
60157198Smuller int
crc_strd(void)60257198Smuller crc_strd(void)
60357198Smuller #else
60457198Smuller int
60557198Smuller crc_strd()
60657198Smuller #endif
60757198Smuller {
60857198Smuller docrc = 1;
60957198Smuller return(lnk_start());
61057198Smuller }
61157198Smuller
61257198Smuller /*
61357198Smuller * vcpio_rd()
61457198Smuller * determine if a buffer is a system VR4 archive entry. (with/without CRC)
61557198Smuller * convert and store the values in the ARCHD parameter.
61657198Smuller * Return:
61757198Smuller * 0 if a valid header, -1 otherwise.
61857198Smuller */
61957198Smuller
62057198Smuller #if __STDC__
62157198Smuller int
vcpio_rd(register ARCHD * arcn,register char * buf)62257198Smuller vcpio_rd(register ARCHD *arcn, register char *buf)
62357198Smuller #else
62457198Smuller int
62557198Smuller vcpio_rd(arcn, buf)
62657198Smuller register ARCHD *arcn;
62757198Smuller register char *buf;
62857198Smuller #endif
62957198Smuller {
63057198Smuller register HD_VCPIO *hd;
63157198Smuller dev_t devminor;
63257198Smuller dev_t devmajor;
63357198Smuller register int nsz;
63457198Smuller
63557198Smuller /*
63657198Smuller * during the id phase it was determined if we were using CRC, use the
63757198Smuller * proper id routine.
63857198Smuller */
63957198Smuller if (docrc) {
64057198Smuller if (crc_id(buf, sizeof(HD_VCPIO)) < 0)
64157198Smuller return(-1);
64257198Smuller } else {
64357198Smuller if (vcpio_id(buf, sizeof(HD_VCPIO)) < 0)
64457198Smuller return(-1);
64557198Smuller }
64657198Smuller
64757198Smuller hd = (HD_VCPIO *)buf;
64857198Smuller arcn->pad = 0L;
64957198Smuller
65057198Smuller /*
65157198Smuller * extract the hex ascii fields from the header
65257198Smuller */
65357198Smuller arcn->sb.st_ino = (ino_t)asc_ul(hd->c_ino, sizeof(hd->c_ino), HEX);
65457198Smuller arcn->sb.st_mode = (mode_t)asc_ul(hd->c_mode, sizeof(hd->c_mode), HEX);
65557198Smuller arcn->sb.st_uid = (uid_t)asc_ul(hd->c_uid, sizeof(hd->c_uid), HEX);
65657198Smuller arcn->sb.st_gid = (gid_t)asc_ul(hd->c_gid, sizeof(hd->c_gid), HEX);
65757198Smuller arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime,sizeof(hd->c_mtime),HEX);
65857499Smuller arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
65957198Smuller # ifdef NET2_STAT
66057198Smuller arcn->sb.st_size = (off_t)asc_ul(hd->c_filesize,
66157198Smuller sizeof(hd->c_filesize), HEX);
66257198Smuller # else
66357198Smuller arcn->sb.st_size = (off_t)asc_uqd(hd->c_filesize,
66457198Smuller sizeof(hd->c_filesize), HEX);
66557198Smuller # endif
66657198Smuller arcn->sb.st_nlink = (nlink_t)asc_ul(hd->c_nlink, sizeof(hd->c_nlink),
66757198Smuller HEX);
66857198Smuller devmajor = (dev_t)asc_ul(hd->c_maj, sizeof(hd->c_maj), HEX);
66957198Smuller devminor = (dev_t)asc_ul(hd->c_min, sizeof(hd->c_min), HEX);
67057198Smuller arcn->sb.st_dev = TODEV(devmajor, devminor);
67157198Smuller devmajor = (dev_t)asc_ul(hd->c_rmaj, sizeof(hd->c_maj), HEX);
67257198Smuller devminor = (dev_t)asc_ul(hd->c_rmin, sizeof(hd->c_min), HEX);
67357198Smuller arcn->sb.st_rdev = TODEV(devmajor, devminor);
67457198Smuller arcn->crc = asc_ul(hd->c_chksum, sizeof(hd->c_chksum), HEX);
67557198Smuller
67657198Smuller /*
67757198Smuller * check the length of the file name, if ok read it in, return -1 if
67857198Smuller * bogus
67957198Smuller */
68057198Smuller if ((nsz = (int)asc_ul(hd->c_namesize,sizeof(hd->c_namesize),HEX)) < 2)
68157198Smuller return(-1);
68257198Smuller arcn->nlen = nsz - 1;
68357198Smuller if (rd_nm(arcn, nsz) < 0)
68457198Smuller return(-1);
68557198Smuller
68657198Smuller /*
68757198Smuller * skip padding. header + filename is aligned to 4 byte boundries
68857198Smuller */
68957198Smuller if (rd_skip((off_t)(VCPIO_PAD(sizeof(HD_VCPIO) + nsz))) < 0)
69057198Smuller return(-1);
69157198Smuller
69257198Smuller /*
69357198Smuller * if not a link (or a file with no data), calculate pad size (for
69457198Smuller * padding which follows the file data), clear the link name and return
69557198Smuller */
69657198Smuller if (((arcn->sb.st_mode&C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)) {
69757198Smuller /*
69857198Smuller * we have a valid header (not a link)
69957198Smuller */
70057198Smuller arcn->ln_nlen = 0;
70157198Smuller arcn->ln_name[0] = '\0';
70257198Smuller arcn->pad = VCPIO_PAD(arcn->sb.st_size);
70357198Smuller return(com_rd(arcn));
70457198Smuller }
70557198Smuller
70657198Smuller /*
70757198Smuller * read in the link name and skip over the padding
70857198Smuller */
70957198Smuller if ((rd_ln_nm(arcn) < 0) ||
71057198Smuller (rd_skip((off_t)(VCPIO_PAD(arcn->sb.st_size))) < 0))
71157198Smuller return(-1);
71257198Smuller
71357198Smuller /*
71457198Smuller * we have a valid header (with a link)
71557198Smuller */
71657198Smuller return(com_rd(arcn));
71757198Smuller }
71857198Smuller
71957198Smuller /*
72057198Smuller * vcpio_endrd()
72157198Smuller * no cleanup needed here, just return size of the trailer (for append)
72257198Smuller * Return:
72357198Smuller * size of trailer header in this format
72457198Smuller */
72557198Smuller
72657198Smuller #if __STDC__
72757198Smuller off_t
vcpio_endrd(void)72857198Smuller vcpio_endrd(void)
72957198Smuller #else
73057198Smuller off_t
73157198Smuller vcpio_endrd()
73257198Smuller #endif
73357198Smuller {
73457198Smuller return((off_t)(sizeof(HD_VCPIO) + sizeof(TRAILER) +
73557198Smuller (VCPIO_PAD(sizeof(HD_VCPIO) + sizeof(TRAILER)))));
73657198Smuller }
73757198Smuller
73857198Smuller /*
73957198Smuller * crc_stwr()
74057198Smuller * start up the device mapping table, enable crc file calculation
74157198Smuller * Return:
74257198Smuller * 0 if ok, -1 otherwise (what dev_start() returns)
74357198Smuller */
74457198Smuller
74557198Smuller #if __STDC__
74657198Smuller int
crc_stwr(void)74757198Smuller crc_stwr(void)
74857198Smuller #else
74957198Smuller int
75057198Smuller crc_stwr()
75157198Smuller #endif
75257198Smuller {
75357198Smuller docrc = 1;
75457198Smuller return(dev_start());
75557198Smuller }
75657198Smuller
75757198Smuller /*
75857198Smuller * vcpio_wr()
75957198Smuller * copy the data in the ARCHD to buffer in system VR4 cpio
76057198Smuller * (with/without crc) format.
76157198Smuller * Return
76257499Smuller * 0 if file has data to be written after the header, 1 if file has
76357499Smuller * NO data to write after the header, -1 if archive write failed
76457198Smuller */
76557198Smuller
76657198Smuller #if __STDC__
76757198Smuller int
vcpio_wr(register ARCHD * arcn)76857198Smuller vcpio_wr(register ARCHD *arcn)
76957198Smuller #else
77057198Smuller int
77157198Smuller vcpio_wr(arcn)
77257198Smuller register ARCHD *arcn;
77357198Smuller #endif
77457198Smuller {
77557198Smuller register HD_VCPIO *hd;
77657198Smuller unsigned int nsz;
77757198Smuller char hdblk[sizeof(HD_VCPIO)];
77857198Smuller
77957198Smuller /*
78057198Smuller * check and repair truncated device and inode fields in the cpio
78157198Smuller * header
78257198Smuller */
78357198Smuller if (map_dev(arcn, (u_long)VCPIO_MASK, (u_long)VCPIO_MASK) < 0)
78457198Smuller return(-1);
78557198Smuller nsz = arcn->nlen + 1;
78657198Smuller hd = (HD_VCPIO *)hdblk;
78757198Smuller if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR))
78857198Smuller arcn->sb.st_rdev = 0;
78957198Smuller
79057198Smuller /*
79157198Smuller * add the proper magic value depending whether we were asked for
79257198Smuller * file data crc's, and the crc if needed.
79357198Smuller */
79457198Smuller if (docrc) {
79557198Smuller if (ul_asc((u_long)VCMAGIC, hd->c_magic, sizeof(hd->c_magic),
79657198Smuller OCT) ||
79757198Smuller ul_asc((u_long)arcn->crc,hd->c_chksum,sizeof(hd->c_chksum),
79857198Smuller HEX))
79957198Smuller goto out;
80057198Smuller } else {
80157198Smuller if (ul_asc((u_long)VMAGIC, hd->c_magic, sizeof(hd->c_magic),
80257198Smuller OCT) ||
80357198Smuller ul_asc((u_long)0L, hd->c_chksum, sizeof(hd->c_chksum),HEX))
80457198Smuller goto out;
80557198Smuller }
80657198Smuller
80757198Smuller switch(arcn->type) {
80857198Smuller case PAX_CTG:
80957198Smuller case PAX_REG:
81057198Smuller case PAX_HRG:
81157198Smuller /*
81257198Smuller * caller will copy file data to the archive. tell him how
81357198Smuller * much to pad.
81457198Smuller */
81557198Smuller arcn->pad = VCPIO_PAD(arcn->sb.st_size);
81657198Smuller # ifdef NET2_STAT
81757198Smuller if (ul_asc((u_long)arcn->sb.st_size, hd->c_filesize,
81857198Smuller sizeof(hd->c_filesize), HEX)) {
81957198Smuller # else
82057198Smuller if (uqd_asc((u_quad_t)arcn->sb.st_size, hd->c_filesize,
82157198Smuller sizeof(hd->c_filesize), HEX)) {
82257198Smuller # endif
82357198Smuller warn(1,"File is too large for sv4cpio format %s",
82457198Smuller arcn->org_name);
82557198Smuller return(1);
82657198Smuller }
82757198Smuller break;
82857198Smuller case PAX_SLK:
82957198Smuller /*
83057198Smuller * no file data for the caller to process, the file data has
83157198Smuller * the size of the link
83257198Smuller */
83357198Smuller arcn->pad = 0L;
83457198Smuller if (ul_asc((u_long)arcn->ln_nlen, hd->c_filesize,
83557198Smuller sizeof(hd->c_filesize), HEX))
83657198Smuller goto out;
83757198Smuller break;
83857198Smuller default:
83957198Smuller /*
84057198Smuller * no file data for the caller to process
84157198Smuller */
84257198Smuller arcn->pad = 0L;
84357198Smuller if (ul_asc((u_long)0L, hd->c_filesize, sizeof(hd->c_filesize),
84457198Smuller HEX))
84557198Smuller goto out;
84657198Smuller break;
84757198Smuller }
84857198Smuller
84957198Smuller /*
85057198Smuller * set the other fields in the header
85157198Smuller */
85257198Smuller if (ul_asc((u_long)arcn->sb.st_ino, hd->c_ino, sizeof(hd->c_ino),
85357198Smuller HEX) ||
85457198Smuller ul_asc((u_long)arcn->sb.st_mode, hd->c_mode, sizeof(hd->c_mode),
85557198Smuller HEX) ||
85657198Smuller ul_asc((u_long)arcn->sb.st_uid, hd->c_uid, sizeof(hd->c_uid),
85757198Smuller HEX) ||
85857198Smuller ul_asc((u_long)arcn->sb.st_gid, hd->c_gid, sizeof(hd->c_gid),
85957198Smuller HEX) ||
86057198Smuller ul_asc((u_long)arcn->sb.st_mtime, hd->c_mtime, sizeof(hd->c_mtime),
86157198Smuller HEX) ||
86257198Smuller ul_asc((u_long)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink),
86357198Smuller HEX) ||
86457198Smuller ul_asc((u_long)MAJOR(arcn->sb.st_dev),hd->c_maj, sizeof(hd->c_maj),
86557198Smuller HEX) ||
86657198Smuller ul_asc((u_long)MINOR(arcn->sb.st_dev),hd->c_min, sizeof(hd->c_min),
86757198Smuller HEX) ||
86857198Smuller ul_asc((u_long)MAJOR(arcn->sb.st_rdev),hd->c_rmaj,sizeof(hd->c_maj),
86957198Smuller HEX) ||
87057198Smuller ul_asc((u_long)MINOR(arcn->sb.st_rdev),hd->c_rmin,sizeof(hd->c_min),
87157198Smuller HEX) ||
87257198Smuller ul_asc((u_long)nsz, hd->c_namesize, sizeof(hd->c_namesize), HEX))
87357198Smuller goto out;
87457198Smuller
87557198Smuller /*
87657198Smuller * write the header, the file name and padding as required.
87757198Smuller */
87857198Smuller if ((wr_rdbuf(hdblk, (int)sizeof(HD_VCPIO)) < 0) ||
87957198Smuller (wr_rdbuf(arcn->name, (int)nsz) < 0) ||
88057198Smuller (wr_skip((off_t)(VCPIO_PAD(sizeof(HD_VCPIO) + nsz))) < 0)) {
88157198Smuller warn(1,"Could not write sv4cpio header for %s",arcn->org_name);
88257198Smuller return(-1);
88357198Smuller }
88457198Smuller
88557198Smuller /*
88657198Smuller * if we have file data, tell the caller we are done, copy the file
88757198Smuller */
88857198Smuller if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) ||
88957198Smuller (arcn->type == PAX_HRG))
89057198Smuller return(0);
89157198Smuller
89257198Smuller /*
89357198Smuller * if we are not a link, tell the caller we are done, go to next file
89457198Smuller */
89557198Smuller if (arcn->type != PAX_SLK)
89657198Smuller return(1);
89757198Smuller
89857198Smuller /*
89957198Smuller * write the link name, tell the caller we are done.
90057198Smuller */
90157198Smuller if ((wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) ||
90257198Smuller (wr_skip((off_t)(VCPIO_PAD(arcn->ln_nlen))) < 0)) {
90357198Smuller warn(1,"Could not write sv4cpio link name for %s",
90457198Smuller arcn->org_name);
90557198Smuller return(-1);
90657198Smuller }
90757198Smuller return(1);
90857198Smuller
90957198Smuller out:
91057198Smuller /*
91157198Smuller * header field is out of range
91257198Smuller */
91357198Smuller warn(1,"Sv4cpio header field is too small for file %s",arcn->org_name);
91457198Smuller return(1);
91557198Smuller }
91657198Smuller
91757198Smuller /*
91857198Smuller * Routines common to the old binary header cpio
91957198Smuller */
92057198Smuller
92157198Smuller /*
92257198Smuller * bcpio_id()
92357198Smuller * determine if a block given to us is a old binary cpio header
92457198Smuller * (with/without header byte swapping)
92557198Smuller * Return:
92657198Smuller * 0 if a valid header, -1 otherwise
92757198Smuller */
92857198Smuller
92957198Smuller #if __STDC__
93057198Smuller int
bcpio_id(char * blk,int size)93157198Smuller bcpio_id(char *blk, int size)
93257198Smuller #else
93357198Smuller int
93457198Smuller bcpio_id(blk, size)
93557198Smuller char *blk;
93657198Smuller int size;
93757198Smuller #endif
93857198Smuller {
93957198Smuller if (size < sizeof(HD_BCPIO))
94057198Smuller return(-1);
94157198Smuller
94257198Smuller /*
94357198Smuller * check both normal and byte swapped magic cookies
94457198Smuller */
94557198Smuller if (((u_short)SHRT_EXT(blk)) == MAGIC)
94657198Smuller return(0);
94757198Smuller if (((u_short)RSHRT_EXT(blk)) == MAGIC) {
94857198Smuller if (!swp_head)
94957198Smuller ++swp_head;
95057198Smuller return(0);
95157198Smuller }
95257198Smuller return(-1);
95357198Smuller }
95457198Smuller
95557198Smuller /*
95657198Smuller * bcpio_rd()
95757198Smuller * determine if a buffer is a old binary archive entry. (it may have byte
95857198Smuller * swapped header) convert and store the values in the ARCHD parameter.
95957198Smuller * This is a very old header format and should not really be used.
96057198Smuller * Return:
96157198Smuller * 0 if a valid header, -1 otherwise.
96257198Smuller */
96357198Smuller
96457198Smuller #if __STDC__
96557198Smuller int
bcpio_rd(register ARCHD * arcn,register char * buf)96657198Smuller bcpio_rd(register ARCHD *arcn, register char *buf)
96757198Smuller #else
96857198Smuller int
96957198Smuller bcpio_rd(arcn, buf)
97057198Smuller register ARCHD *arcn;
97157198Smuller register char *buf;
97257198Smuller #endif
97357198Smuller {
97457198Smuller register HD_BCPIO *hd;
97557198Smuller register int nsz;
97657198Smuller
97757198Smuller /*
97857198Smuller * check the header
97957198Smuller */
98057198Smuller if (bcpio_id(buf, sizeof(HD_BCPIO)) < 0)
98157198Smuller return(-1);
98257198Smuller
98357198Smuller arcn->pad = 0L;
98457198Smuller hd = (HD_BCPIO *)buf;
98557198Smuller if (swp_head) {
98657198Smuller /*
98757198Smuller * header has swapped bytes on 16 bit boundries
98857198Smuller */
98957198Smuller arcn->sb.st_dev = (dev_t)(RSHRT_EXT(hd->h_dev));
99057198Smuller arcn->sb.st_ino = (ino_t)(RSHRT_EXT(hd->h_ino));
99157198Smuller arcn->sb.st_mode = (mode_t)(RSHRT_EXT(hd->h_mode));
99257198Smuller arcn->sb.st_uid = (uid_t)(RSHRT_EXT(hd->h_uid));
99357198Smuller arcn->sb.st_gid = (gid_t)(RSHRT_EXT(hd->h_gid));
99457198Smuller arcn->sb.st_nlink = (nlink_t)(RSHRT_EXT(hd->h_nlink));
99557198Smuller arcn->sb.st_rdev = (dev_t)(RSHRT_EXT(hd->h_rdev));
99657198Smuller arcn->sb.st_mtime = (time_t)(RSHRT_EXT(hd->h_mtime_1));
99757198Smuller arcn->sb.st_mtime = (arcn->sb.st_mtime << 16) |
99857198Smuller ((time_t)(RSHRT_EXT(hd->h_mtime_2)));
99957198Smuller arcn->sb.st_size = (off_t)(RSHRT_EXT(hd->h_filesize_1));
100057198Smuller arcn->sb.st_size = (arcn->sb.st_size << 16) |
100157198Smuller ((off_t)(RSHRT_EXT(hd->h_filesize_2)));
100257198Smuller nsz = (int)(RSHRT_EXT(hd->h_namesize));
100357198Smuller } else {
100457198Smuller arcn->sb.st_dev = (dev_t)(SHRT_EXT(hd->h_dev));
100557198Smuller arcn->sb.st_ino = (ino_t)(SHRT_EXT(hd->h_ino));
100657198Smuller arcn->sb.st_mode = (mode_t)(SHRT_EXT(hd->h_mode));
100757198Smuller arcn->sb.st_uid = (uid_t)(SHRT_EXT(hd->h_uid));
100857198Smuller arcn->sb.st_gid = (gid_t)(SHRT_EXT(hd->h_gid));
100957198Smuller arcn->sb.st_nlink = (nlink_t)(SHRT_EXT(hd->h_nlink));
101057198Smuller arcn->sb.st_rdev = (dev_t)(SHRT_EXT(hd->h_rdev));
101157198Smuller arcn->sb.st_mtime = (time_t)(SHRT_EXT(hd->h_mtime_1));
101257198Smuller arcn->sb.st_mtime = (arcn->sb.st_mtime << 16) |
101357198Smuller ((time_t)(SHRT_EXT(hd->h_mtime_2)));
101457198Smuller arcn->sb.st_size = (off_t)(SHRT_EXT(hd->h_filesize_1));
101557198Smuller arcn->sb.st_size = (arcn->sb.st_size << 16) |
101657198Smuller ((off_t)(SHRT_EXT(hd->h_filesize_2)));
101757198Smuller nsz = (int)(SHRT_EXT(hd->h_namesize));
101857198Smuller }
101957499Smuller arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
102057198Smuller
102157198Smuller /*
102257198Smuller * check the file name size, if bogus give up. otherwise read the file
102357198Smuller * name
102457198Smuller */
102557198Smuller if (nsz < 2)
102657198Smuller return(-1);
102757198Smuller arcn->nlen = nsz - 1;
102857198Smuller if (rd_nm(arcn, nsz) < 0)
102957198Smuller return(-1);
103057198Smuller
103157198Smuller /*
103257198Smuller * header + file name are aligned to 2 byte boundries, skip if needed
103357198Smuller */
103457198Smuller if (rd_skip((off_t)(BCPIO_PAD(sizeof(HD_BCPIO) + nsz))) < 0)
103557198Smuller return(-1);
103657198Smuller
103757198Smuller /*
103857198Smuller * if not a link (or a file with no data), calculate pad size (for
103957198Smuller * padding which follows the file data), clear the link name and return
104057198Smuller */
104157198Smuller if (((arcn->sb.st_mode & C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)){
104257198Smuller /*
104357198Smuller * we have a valid header (not a link)
104457198Smuller */
104557198Smuller arcn->ln_nlen = 0;
104657198Smuller arcn->ln_name[0] = '\0';
104757198Smuller arcn->pad = BCPIO_PAD(arcn->sb.st_size);
104857198Smuller return(com_rd(arcn));
104957198Smuller }
105057198Smuller
105157198Smuller if ((rd_ln_nm(arcn) < 0) ||
105257198Smuller (rd_skip((off_t)(BCPIO_PAD(arcn->sb.st_size))) < 0))
105357198Smuller return(-1);
105457198Smuller
105557198Smuller /*
105657198Smuller * we have a valid header (with a link)
105757198Smuller */
105857198Smuller return(com_rd(arcn));
105957198Smuller }
106057198Smuller
106157198Smuller /*
106257198Smuller * bcpio_endrd()
106357198Smuller * no cleanup needed here, just return size of the trailer (for append)
106457198Smuller * Return:
106557198Smuller * size of trailer header in this format
106657198Smuller */
106757198Smuller
106857198Smuller #if __STDC__
106957198Smuller off_t
bcpio_endrd(void)107057198Smuller bcpio_endrd(void)
107157198Smuller #else
107257198Smuller off_t
107357198Smuller bcpio_endrd()
107457198Smuller #endif
107557198Smuller {
107657198Smuller return((off_t)(sizeof(HD_BCPIO) + sizeof(TRAILER) +
107757198Smuller (BCPIO_PAD(sizeof(HD_BCPIO) + sizeof(TRAILER)))));
107857198Smuller }
107957198Smuller
108057198Smuller /*
108157198Smuller * bcpio_wr()
108257198Smuller * copy the data in the ARCHD to buffer in old binary cpio format
108357198Smuller * There is a real chance of field overflow with this critter. So we
108457198Smuller * always check the conversion is ok. nobody in his their right mind
108557198Smuller * should write an achive in this format...
108657198Smuller * Return
108757198Smuller * 0 if file has data to be written after the header, 1 if file has NO
108857198Smuller * data to write after the header, -1 if archive write failed
108957198Smuller */
109057198Smuller
109157198Smuller #if __STDC__
109257198Smuller int
bcpio_wr(register ARCHD * arcn)109357198Smuller bcpio_wr(register ARCHD *arcn)
109457198Smuller #else
109557198Smuller int
109657198Smuller bcpio_wr(arcn)
109757198Smuller register ARCHD *arcn;
109857198Smuller #endif
109957198Smuller {
110057198Smuller register HD_BCPIO *hd;
110157198Smuller register int nsz;
110257198Smuller char hdblk[sizeof(HD_BCPIO)];
110357198Smuller off_t t_offt;
110457198Smuller int t_int;
110557198Smuller time_t t_timet;
110657198Smuller
110757198Smuller /*
110857198Smuller * check and repair truncated device and inode fields in the cpio
110957198Smuller * header
111057198Smuller */
111157198Smuller if (map_dev(arcn, (u_long)BCPIO_MASK, (u_long)BCPIO_MASK) < 0)
111257198Smuller return(-1);
111357198Smuller
111457198Smuller if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR))
111557198Smuller arcn->sb.st_rdev = 0;
111657198Smuller hd = (HD_BCPIO *)hdblk;
111757198Smuller
111857198Smuller switch(arcn->type) {
111957198Smuller case PAX_CTG:
112057198Smuller case PAX_REG:
112157198Smuller case PAX_HRG:
112257198Smuller /*
112357198Smuller * caller will copy file data to the archive. tell him how
112457198Smuller * much to pad.
112557198Smuller */
112657198Smuller arcn->pad = BCPIO_PAD(arcn->sb.st_size);
112757198Smuller hd->h_filesize_1[0] = CHR_WR_0(arcn->sb.st_size);
112857198Smuller hd->h_filesize_1[1] = CHR_WR_1(arcn->sb.st_size);
112957198Smuller hd->h_filesize_2[0] = CHR_WR_2(arcn->sb.st_size);
113057198Smuller hd->h_filesize_2[1] = CHR_WR_3(arcn->sb.st_size);
113157198Smuller t_offt = (off_t)(SHRT_EXT(hd->h_filesize_1));
113257198Smuller t_offt = (t_offt<<16) | ((off_t)(SHRT_EXT(hd->h_filesize_2)));
113357198Smuller if (arcn->sb.st_size != t_offt) {
113457198Smuller warn(1,"File is too large for bcpio format %s",
113557198Smuller arcn->org_name);
113657198Smuller return(1);
113757198Smuller }
113857198Smuller break;
113957198Smuller case PAX_SLK:
114057198Smuller /*
114157198Smuller * no file data for the caller to process, the file data has
114257198Smuller * the size of the link
114357198Smuller */
114457198Smuller arcn->pad = 0L;
114557198Smuller hd->h_filesize_1[0] = CHR_WR_0(arcn->ln_nlen);
114657198Smuller hd->h_filesize_1[1] = CHR_WR_1(arcn->ln_nlen);
114757198Smuller hd->h_filesize_2[0] = CHR_WR_2(arcn->ln_nlen);
114857198Smuller hd->h_filesize_2[1] = CHR_WR_3(arcn->ln_nlen);
114957198Smuller t_int = (int)(SHRT_EXT(hd->h_filesize_1));
115057198Smuller t_int = (t_int << 16) | ((int)(SHRT_EXT(hd->h_filesize_2)));
115157198Smuller if (arcn->ln_nlen != t_int)
115257198Smuller goto out;
115357198Smuller break;
115457198Smuller default:
115557198Smuller /*
115657198Smuller * no file data for the caller to process
115757198Smuller */
115857198Smuller arcn->pad = 0L;
115957198Smuller hd->h_filesize_1[0] = (char)0;
116057198Smuller hd->h_filesize_1[1] = (char)0;
116157198Smuller hd->h_filesize_2[0] = (char)0;
116257198Smuller hd->h_filesize_2[1] = (char)0;
116357198Smuller break;
116457198Smuller }
116557198Smuller
116657198Smuller /*
116757198Smuller * build up the rest of the fields
116857198Smuller */
116957198Smuller hd->h_magic[0] = CHR_WR_2(MAGIC);
117057198Smuller hd->h_magic[1] = CHR_WR_3(MAGIC);
117157198Smuller hd->h_dev[0] = CHR_WR_2(arcn->sb.st_dev);
117257198Smuller hd->h_dev[1] = CHR_WR_3(arcn->sb.st_dev);
117357198Smuller if (arcn->sb.st_dev != (dev_t)(SHRT_EXT(hd->h_dev)))
117457198Smuller goto out;
117557198Smuller hd->h_ino[0] = CHR_WR_2(arcn->sb.st_ino);
117657198Smuller hd->h_ino[1] = CHR_WR_3(arcn->sb.st_ino);
117757198Smuller if (arcn->sb.st_ino != (ino_t)(SHRT_EXT(hd->h_ino)))
117857198Smuller goto out;
117957198Smuller hd->h_mode[0] = CHR_WR_2(arcn->sb.st_mode);
118057198Smuller hd->h_mode[1] = CHR_WR_3(arcn->sb.st_mode);
118157198Smuller if (arcn->sb.st_mode != (mode_t)(SHRT_EXT(hd->h_mode)))
118257198Smuller goto out;
118357198Smuller hd->h_uid[0] = CHR_WR_2(arcn->sb.st_uid);
118457198Smuller hd->h_uid[1] = CHR_WR_3(arcn->sb.st_uid);
118557198Smuller if (arcn->sb.st_uid != (uid_t)(SHRT_EXT(hd->h_uid)))
118657198Smuller goto out;
118757198Smuller hd->h_gid[0] = CHR_WR_2(arcn->sb.st_gid);
118857198Smuller hd->h_gid[1] = CHR_WR_3(arcn->sb.st_gid);
118957198Smuller if (arcn->sb.st_gid != (gid_t)(SHRT_EXT(hd->h_gid)))
119057198Smuller goto out;
119157198Smuller hd->h_nlink[0] = CHR_WR_2(arcn->sb.st_nlink);
119257198Smuller hd->h_nlink[1] = CHR_WR_3(arcn->sb.st_nlink);
119357198Smuller if (arcn->sb.st_nlink != (nlink_t)(SHRT_EXT(hd->h_nlink)))
119457198Smuller goto out;
119557198Smuller hd->h_rdev[0] = CHR_WR_2(arcn->sb.st_rdev);
119657198Smuller hd->h_rdev[1] = CHR_WR_3(arcn->sb.st_rdev);
119757198Smuller if (arcn->sb.st_rdev != (dev_t)(SHRT_EXT(hd->h_rdev)))
119857198Smuller goto out;
119957198Smuller hd->h_mtime_1[0] = CHR_WR_0(arcn->sb.st_mtime);
120057198Smuller hd->h_mtime_1[1] = CHR_WR_1(arcn->sb.st_mtime);
120157198Smuller hd->h_mtime_2[0] = CHR_WR_2(arcn->sb.st_mtime);
120257198Smuller hd->h_mtime_2[1] = CHR_WR_3(arcn->sb.st_mtime);
120357198Smuller t_timet = (time_t)(SHRT_EXT(hd->h_mtime_1));
120457198Smuller t_timet = (t_timet << 16) | ((time_t)(SHRT_EXT(hd->h_mtime_2)));
120557198Smuller if (arcn->sb.st_mtime != t_timet)
120657198Smuller goto out;
120757198Smuller nsz = arcn->nlen + 1;
120857198Smuller hd->h_namesize[0] = CHR_WR_2(nsz);
120957198Smuller hd->h_namesize[1] = CHR_WR_3(nsz);
121057198Smuller if (nsz != (int)(SHRT_EXT(hd->h_namesize)))
121157198Smuller goto out;
121257198Smuller
121357198Smuller /*
121457198Smuller * write the header, the file name and padding as required.
121557198Smuller */
121657198Smuller if ((wr_rdbuf(hdblk, (int)sizeof(HD_BCPIO)) < 0) ||
121757198Smuller (wr_rdbuf(arcn->name, nsz) < 0) ||
121857198Smuller (wr_skip((off_t)(BCPIO_PAD(sizeof(HD_BCPIO) + nsz))) < 0)) {
121957198Smuller warn(1, "Could not write bcpio header for %s", arcn->org_name);
122057198Smuller return(-1);
122157198Smuller }
122257198Smuller
122357198Smuller /*
122457198Smuller * if we have file data, tell the caller we are done
122557198Smuller */
122657198Smuller if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) ||
122757198Smuller (arcn->type == PAX_HRG))
122857198Smuller return(0);
122957198Smuller
123057198Smuller /*
123157198Smuller * if we are not a link, tell the caller we are done, go to next file
123257198Smuller */
123357198Smuller if (arcn->type != PAX_SLK)
123457198Smuller return(1);
123557198Smuller
123657198Smuller /*
123757198Smuller * write the link name, tell the caller we are done.
123857198Smuller */
123957198Smuller if ((wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) ||
124057198Smuller (wr_skip((off_t)(BCPIO_PAD(arcn->ln_nlen))) < 0)) {
124157198Smuller warn(1,"Could not write bcpio link name for %s",arcn->org_name);
124257198Smuller return(-1);
124357198Smuller }
124457198Smuller return(1);
124557198Smuller
124657198Smuller out:
124757198Smuller /*
124857198Smuller * header field is out of range
124957198Smuller */
125057198Smuller warn(1,"Bcpio header field is too small for file %s", arcn->org_name);
125157198Smuller return(1);
125257198Smuller }
1253