157197Smuller /*-
257197Smuller * Copyright (c) 1992 Keith Muller.
360676Sbostic * Copyright (c) 1992, 1993
460676Sbostic * The Regents of the University of California. All rights reserved.
557197Smuller *
657197Smuller * This code is derived from software contributed to Berkeley by
757197Smuller * Keith Muller of the University of California, San Diego.
857197Smuller *
957197Smuller * %sccs.include.redist.c%
1057197Smuller */
1157197Smuller
1257197Smuller #ifndef lint
13*66890Sbostic static char sccsid[] = "@(#)tar.c 8.2 (Berkeley) 04/18/94";
1457197Smuller #endif /* not lint */
1557197Smuller
1657197Smuller #include <sys/types.h>
1757197Smuller #include <sys/time.h>
1857197Smuller #include <sys/stat.h>
1957197Smuller #include <sys/param.h>
2057197Smuller #include <string.h>
2157197Smuller #include <stdio.h>
2257197Smuller #include <ctype.h>
2357197Smuller #include <unistd.h>
2457197Smuller #include <stdlib.h>
2557197Smuller #include "pax.h"
2657197Smuller #include "extern.h"
2757197Smuller #include "tar.h"
2857197Smuller
2957197Smuller /*
3057197Smuller * Routines for reading, writing and header identify of various versions of tar
3157197Smuller */
3257197Smuller
3357197Smuller static u_long tar_chksm __P((register char *, register int));
3457197Smuller static char *name_split __P((register char *, register int));
3557197Smuller static int ul_oct __P((u_long, register char *, register int, int));
3657197Smuller #ifndef NET2_STAT
3757197Smuller static int uqd_oct __P((u_quad_t, register char *, register int, int));
3857197Smuller #endif
3957197Smuller
4057197Smuller /*
4157197Smuller * Routines common to all versions of tar
4257197Smuller */
4357197Smuller
4457197Smuller static int tar_nodir; /* do not write dirs under old tar */
4557197Smuller
4657197Smuller /*
4757197Smuller * tar_endwr()
4857197Smuller * add the tar trailer of two null blocks
4957197Smuller * Return:
5057197Smuller * 0 if ok, -1 otherwise (what wr_skip returns)
5157197Smuller */
5257197Smuller
5357197Smuller #if __STDC__
5457197Smuller int
tar_endwr(void)5557197Smuller tar_endwr(void)
5657197Smuller #else
5757197Smuller int
5857197Smuller tar_endwr()
5957197Smuller #endif
6057197Smuller {
6157197Smuller return(wr_skip((off_t)(NULLCNT*BLKMULT)));
6257197Smuller }
6357197Smuller
6457197Smuller /*
6557197Smuller * tar_endrd()
6657197Smuller * no cleanup needed here, just return size of trailer (for append)
6757197Smuller * Return:
6857197Smuller * size of trailer (2 * BLKMULT)
6957197Smuller */
7057197Smuller
7157197Smuller #if __STDC__
7257197Smuller off_t
tar_endrd(void)7357197Smuller tar_endrd(void)
7457197Smuller #else
7557197Smuller off_t
7657197Smuller tar_endrd()
7757197Smuller #endif
7857197Smuller {
7957197Smuller return((off_t)(NULLCNT*BLKMULT));
8057197Smuller }
8157197Smuller
8257197Smuller /*
8357197Smuller * tar_trail()
8457197Smuller * Called to determine if a header block is a valid trailer. We are passed
8557197Smuller * the block, the in_sync flag (which tells us we are in resync mode;
8657197Smuller * looking for a valid header), and cnt (which starts at zero) which is
8757197Smuller * used to count the number of empty blocks we have seen so far.
8857197Smuller * Return:
8957197Smuller * 0 if a valid trailer, -1 if not a valid trailer, or 1 if the block
9057197Smuller * could never contain a header.
9157197Smuller */
9257197Smuller
9357197Smuller #if __STDC__
9457197Smuller int
tar_trail(register char * buf,register int in_resync,register int * cnt)9557197Smuller tar_trail(register char *buf, register int in_resync, register int *cnt)
9657197Smuller #else
9757197Smuller int
9857197Smuller tar_trail(buf, in_resync, cnt)
9957197Smuller register char *buf;
10057197Smuller register int in_resync;
10157197Smuller register int *cnt;
10257197Smuller #endif
10357197Smuller {
10457197Smuller register int i;
10557197Smuller
10657197Smuller /*
10757197Smuller * look for all zero, trailer is two consecutive blocks of zero
10857197Smuller */
10957197Smuller for (i = 0; i < BLKMULT; ++i) {
11057197Smuller if (buf[i] != '\0')
11157197Smuller break;
11257197Smuller }
11357197Smuller
11457197Smuller /*
11557197Smuller * if not all zero it is not a trailer, but MIGHT be a header.
11657197Smuller */
11757197Smuller if (i != BLKMULT)
11857197Smuller return(-1);
11957197Smuller
12057197Smuller /*
12157197Smuller * When given a zero block, we must be careful!
12257197Smuller * If we are not in resync mode, check for the trailer. Have to watch
12357197Smuller * out that we do not mis-identify file data as the trailer, so we do
12457197Smuller * NOT try to id a trailer during resync mode. During resync mode we
12557197Smuller * might as well throw this block out since a valid header can NEVER be
12657197Smuller * a block of all 0 (we must have a valid file name).
12757197Smuller */
12857197Smuller if (!in_resync && (++*cnt >= NULLCNT))
12957197Smuller return(0);
13057197Smuller return(1);
13157197Smuller }
13257197Smuller
13357197Smuller /*
13457197Smuller * ul_oct()
13557503Smuller * convert an unsigned long to an octal string. many oddball field
13657197Smuller * termination characters are used by the various versions of tar in the
13757197Smuller * different fields. term selects which kind to use. str is BLANK padded
13857197Smuller * at the front to len. we are unable to use only one format as many old
13957197Smuller * tar readers are very cranky about this.
14057197Smuller * Return:
14157197Smuller * 0 if the number fit into the string, -1 otherwise
14257197Smuller */
14357197Smuller
14457197Smuller #if __STDC__
14557197Smuller static int
ul_oct(u_long val,register char * str,register int len,int term)14657197Smuller ul_oct(u_long val, register char *str, register int len, int term)
14757197Smuller #else
14857197Smuller static int
14957197Smuller ul_oct(val, str, len, term)
15057197Smuller u_long val;
15157197Smuller register char *str;
15257197Smuller register int len;
15357197Smuller int term;
15457197Smuller #endif
15557197Smuller {
15657197Smuller register char *pt;
15757197Smuller
15857197Smuller /*
15957197Smuller * term selects the appropriate character(s) for the end of the string
16057197Smuller */
16157197Smuller pt = str + len - 1;
16257197Smuller switch(term) {
16357197Smuller case 3:
16457197Smuller *pt-- = '\0';
16557197Smuller break;
16657197Smuller case 2:
16757197Smuller *pt-- = ' ';
16857197Smuller *pt-- = '\0';
16957197Smuller break;
17057197Smuller case 1:
17157197Smuller *pt-- = ' ';
17257197Smuller break;
17357197Smuller case 0:
17457197Smuller default:
17557197Smuller *pt-- = '\0';
17657197Smuller *pt-- = ' ';
17757197Smuller break;
17857197Smuller }
17957197Smuller
18057197Smuller /*
18157197Smuller * convert and blank pad if there is space
18257197Smuller */
18357197Smuller while (pt >= str) {
18457197Smuller *pt-- = '0' + (char)(val & 0x7);
18557197Smuller if ((val = val >> 3) == (u_long)0)
18657197Smuller break;
18757197Smuller }
18857197Smuller
18957197Smuller while (pt >= str)
19057197Smuller *pt-- = ' ';
19157197Smuller if (val != (u_long)0)
19257197Smuller return(-1);
19357197Smuller return(0);
19457197Smuller }
19557197Smuller
19657197Smuller #ifndef NET2_STAT
19757197Smuller /*
19857197Smuller * uqd_oct()
19957197Smuller * convert an u_quad_t to an octal string. one of many oddball field
20057197Smuller * termination characters are used by the various versions of tar in the
20157197Smuller * different fields. term selects which kind to use. str is BLANK padded
20257197Smuller * at the front to len. we are unable to use only one format as many old
20357197Smuller * tar readers are very cranky about this.
20457197Smuller * Return:
20557197Smuller * 0 if the number fit into the string, -1 otherwise
20657197Smuller */
20757197Smuller
20857197Smuller #if __STDC__
20957197Smuller static int
uqd_oct(u_quad_t val,register char * str,register int len,int term)21057197Smuller uqd_oct(u_quad_t val, register char *str, register int len, int term)
21157197Smuller #else
21257197Smuller static int
21357197Smuller uqd_oct(val, str, len, term)
21457197Smuller u_quad_t val;
21557197Smuller register char *str;
21657197Smuller register int len;
21757197Smuller int term;
21857197Smuller #endif
21957197Smuller {
22057197Smuller register char *pt;
22157197Smuller
22257197Smuller /*
22357197Smuller * term selects the appropriate character(s) for the end of the string
22457197Smuller */
22557197Smuller pt = str + len - 1;
22657197Smuller switch(term) {
22757197Smuller case 3:
22857197Smuller *pt-- = '\0';
22957197Smuller break;
23057197Smuller case 2:
23157197Smuller *pt-- = ' ';
23257197Smuller *pt-- = '\0';
23357197Smuller break;
23457197Smuller case 1:
23557197Smuller *pt-- = ' ';
23657197Smuller break;
23757197Smuller case 0:
23857197Smuller default:
23957197Smuller *pt-- = '\0';
24057197Smuller *pt-- = ' ';
24157197Smuller break;
24257197Smuller }
24357197Smuller
24457197Smuller /*
24557197Smuller * convert and blank pad if there is space
24657197Smuller */
24757197Smuller while (pt >= str) {
24857197Smuller *pt-- = '0' + (char)(val & 0x7);
24957197Smuller if ((val = val >> 3) == 0)
25057197Smuller break;
25157197Smuller }
25257197Smuller
25357197Smuller while (pt >= str)
25457197Smuller *pt-- = ' ';
25557197Smuller if (val != (u_quad_t)0)
25657197Smuller return(-1);
25757197Smuller return(0);
25857197Smuller }
25957197Smuller #endif
26057197Smuller
26157197Smuller /*
26257197Smuller * tar_chksm()
26357197Smuller * calculate the checksum for a tar block counting the checksum field as
26457197Smuller * all blanks (BLNKSUM is that value pre-calculated, the sume of 8 blanks).
26557197Smuller * NOTE: we use len to short circuit summing 0's on write since we ALWAYS
26657197Smuller * pad headers with 0.
26757197Smuller * Return:
26857197Smuller * unsigned long checksum
26957197Smuller */
27057197Smuller
27157197Smuller #if __STDC__
27257197Smuller static u_long
tar_chksm(register char * blk,register int len)27357197Smuller tar_chksm(register char *blk, register int len)
27457197Smuller #else
27557197Smuller static u_long
27657197Smuller tar_chksm(blk, len)
27757197Smuller register char *blk;
27857197Smuller register int len;
27957197Smuller #endif
28057197Smuller {
28157197Smuller register char *stop;
28257197Smuller register char *pt;
28357197Smuller u_long chksm = BLNKSUM; /* inital value is checksum field sum */
28457197Smuller
28557197Smuller /*
28657197Smuller * add the part of the block before the checksum field
28757197Smuller */
28857197Smuller pt = blk;
28957197Smuller stop = blk + CHK_OFFSET;
29057197Smuller while (pt < stop)
29157197Smuller chksm += (u_long)(*pt++ & 0xff);
29257197Smuller /*
29357197Smuller * move past the checksum field and keep going, spec counts the
29457197Smuller * checksum field as the sum of 8 blanks (which is pre-computed as
29557197Smuller * BLNKSUM).
29657197Smuller * ASSUMED: len is greater than CHK_OFFSET. (len is where our 0 padding
29757197Smuller * starts, no point in summing zero's)
29857197Smuller */
29957197Smuller pt += CHK_LEN;
30057197Smuller stop = blk + len;
30157197Smuller while (pt < stop)
30257197Smuller chksm += (u_long)(*pt++ & 0xff);
30357197Smuller return(chksm);
30457197Smuller }
30557197Smuller
30657197Smuller /*
30757197Smuller * Routines for old BSD style tar (also made portable to sysV tar)
30857197Smuller */
30957197Smuller
31057197Smuller /*
31157197Smuller * tar_id()
31257197Smuller * determine if a block given to us is a valid tar header (and not a USTAR
31357197Smuller * header). We have to be on the lookout for those pesky blocks of all
31457197Smuller * zero's.
31557197Smuller * Return:
31657197Smuller * 0 if a tar header, -1 otherwise
31757197Smuller */
31857197Smuller
31957197Smuller #if __STDC__
32057197Smuller int
tar_id(register char * blk,int size)32157197Smuller tar_id(register char *blk, int size)
32257197Smuller #else
32357197Smuller int
32457197Smuller tar_id(blk, size)
32557197Smuller register char *blk;
32657197Smuller int size;
32757197Smuller #endif
32857197Smuller {
32957197Smuller register HD_TAR *hd;
33057197Smuller register HD_USTAR *uhd;
33157197Smuller
33257197Smuller if (size < BLKMULT)
33357197Smuller return(-1);
33457197Smuller hd = (HD_TAR *)blk;
33557197Smuller uhd = (HD_USTAR *)blk;
33657197Smuller
33757197Smuller /*
33857197Smuller * check for block of zero's first, a simple and fast test, then make
33957197Smuller * sure this is not a ustar header by looking for the ustar magic
34057197Smuller * cookie. We should use TMAGLEN, but some USTAR archive programs are
34157197Smuller * wrong and create archives missing the \0. Last we check the
34257197Smuller * checksum. If this is ok we have to assume it is a valid header.
34357197Smuller */
34457197Smuller if (hd->name[0] == '\0')
34557197Smuller return(-1);
34657197Smuller if (strncmp(uhd->magic, TMAGIC, TMAGLEN - 1) == 0)
34757197Smuller return(-1);
34857197Smuller if (asc_ul(hd->chksum,sizeof(hd->chksum),OCT) != tar_chksm(blk,BLKMULT))
34957197Smuller return(-1);
35057197Smuller return(0);
35157197Smuller }
35257197Smuller
35357197Smuller /*
35457197Smuller * tar_opt()
35557197Smuller * handle tar format specific -o options
35657197Smuller * Return:
35757197Smuller * 0 if ok -1 otherwise
35857197Smuller */
35957197Smuller
36057197Smuller #if __STDC__
36157197Smuller int
tar_opt(void)36257197Smuller tar_opt(void)
36357197Smuller #else
36457197Smuller int
36557197Smuller tar_opt()
36657197Smuller #endif
36757197Smuller {
36857197Smuller OPLIST *opt;
36957197Smuller
37057197Smuller while ((opt = opt_next()) != NULL) {
37157197Smuller if (strcmp(opt->name, TAR_OPTION) ||
37257197Smuller strcmp(opt->value, TAR_NODIR)) {
37357197Smuller warn(1, "Unknown tar format -o option/value pair %s=%s",
37457197Smuller opt->name, opt->value);
37557197Smuller warn(1,"%s=%s is the only supported tar format option",
37657197Smuller TAR_OPTION, TAR_NODIR);
37757197Smuller return(-1);
37857197Smuller }
37957197Smuller
38057197Smuller /*
38157197Smuller * we only support one option, and only when writing
38257197Smuller */
38357197Smuller if ((act != APPND) && (act != ARCHIVE)) {
38457197Smuller warn(1, "%s=%s is only supported when writing.",
38557197Smuller opt->name, opt->value);
38657197Smuller return(-1);
38757197Smuller }
38857197Smuller tar_nodir = 1;
38957197Smuller }
39057197Smuller return(0);
39157197Smuller }
39257197Smuller
39357197Smuller
39457197Smuller /*
39557197Smuller * tar_rd()
39657197Smuller * extract the values out of block already determined to be a tar header.
39757197Smuller * store the values in the ARCHD parameter.
39857197Smuller * Return:
39957197Smuller * 0
40057197Smuller */
40157197Smuller
40257197Smuller #if __STDC__
40357197Smuller int
tar_rd(register ARCHD * arcn,register char * buf)40457197Smuller tar_rd(register ARCHD *arcn, register char *buf)
40557197Smuller #else
40657197Smuller int
40757197Smuller tar_rd(arcn, buf)
40857197Smuller register ARCHD *arcn;
40957197Smuller register char *buf;
41057197Smuller #endif
41157197Smuller {
41257197Smuller register HD_TAR *hd;
41357197Smuller register char *pt;
41457197Smuller
41557197Smuller /*
41657197Smuller * we only get proper sized buffers passed to us
41757197Smuller */
41857197Smuller if (tar_id(buf, BLKMULT) < 0)
41957197Smuller return(-1);
42057197Smuller arcn->org_name = arcn->name;
42157197Smuller arcn->sb.st_nlink = 1;
42257197Smuller arcn->pat = NULL;
42357197Smuller
42457197Smuller /*
42557197Smuller * copy out the name and values in the stat buffer
42657197Smuller */
42757197Smuller hd = (HD_TAR *)buf;
42857197Smuller arcn->nlen = l_strncpy(arcn->name, hd->name, sizeof(hd->name));
42957197Smuller arcn->name[arcn->nlen] = '\0';
43057197Smuller arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode,sizeof(hd->mode),OCT) &
43157197Smuller 0xfff);
43257197Smuller arcn->sb.st_uid = (uid_t)asc_ul(hd->uid, sizeof(hd->uid), OCT);
43357197Smuller arcn->sb.st_gid = (gid_t)asc_ul(hd->gid, sizeof(hd->gid), OCT);
43457197Smuller arcn->sb.st_size = (size_t)asc_ul(hd->size, sizeof(hd->size), OCT);
43557197Smuller arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT);
43657503Smuller arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
43757197Smuller
43857197Smuller /*
43957197Smuller * have to look at the last character, it may be a '/' and that is used
44057197Smuller * to encode this as a directory
44157197Smuller */
44257197Smuller pt = &(arcn->name[arcn->nlen - 1]);
44357197Smuller arcn->pad = 0;
44457197Smuller arcn->skip = 0;
44557197Smuller switch(hd->linkflag) {
44657197Smuller case SYMTYPE:
44757197Smuller /*
44857197Smuller * symbolic link, need to get the link name and set the type in
44957197Smuller * the st_mode so -v printing will look correct.
45057197Smuller */
45157197Smuller arcn->type = PAX_SLK;
45257197Smuller arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname,
45357197Smuller sizeof(hd->linkname));
45457197Smuller arcn->ln_name[arcn->ln_nlen] = '\0';
45557197Smuller arcn->sb.st_mode |= S_IFLNK;
45657197Smuller break;
45757197Smuller case LNKTYPE:
45857197Smuller /*
45957197Smuller * hard link, need to get the link name, set the type in the
46057197Smuller * st_mode and st_nlink so -v printing will look better.
46157197Smuller */
46257197Smuller arcn->type = PAX_HLK;
46357197Smuller arcn->sb.st_nlink = 2;
46457197Smuller arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname,
46557197Smuller sizeof(hd->linkname));
46657197Smuller arcn->ln_name[arcn->ln_nlen] = '\0';
46757503Smuller
46857197Smuller /*
46957197Smuller * no idea of what type this thing really points at, but
47057197Smuller * we set something for printing only.
47157197Smuller */
47257197Smuller arcn->sb.st_mode |= S_IFREG;
47357197Smuller break;
47457197Smuller case AREGTYPE:
47557197Smuller case REGTYPE:
47657197Smuller default:
47757197Smuller /*
47857197Smuller * If we have a trailing / this is a directory and NOT a file.
47957197Smuller */
48057197Smuller arcn->ln_name[0] = '\0';
48157197Smuller arcn->ln_nlen = 0;
48257197Smuller if (*pt == '/') {
48357197Smuller /*
48457197Smuller * it is a directory, set the mode for -v printing
48557197Smuller */
48657197Smuller arcn->type = PAX_DIR;
48757197Smuller arcn->sb.st_mode |= S_IFDIR;
48857197Smuller arcn->sb.st_nlink = 2;
48957197Smuller } else {
49057197Smuller /*
49157197Smuller * have a file that will be followed by data. Set the
49257197Smuller * skip value to the size field and caluculate the size
49357197Smuller * of the padding.
49457197Smuller */
49557197Smuller arcn->type = PAX_REG;
49657197Smuller arcn->sb.st_mode |= S_IFREG;
49757197Smuller arcn->pad = TAR_PAD(arcn->sb.st_size);
49857197Smuller arcn->skip = arcn->sb.st_size;
49957197Smuller }
50057197Smuller break;
50157197Smuller }
50257197Smuller
50357197Smuller /*
50457197Smuller * strip off any trailing slash.
50557197Smuller */
50657197Smuller if (*pt == '/') {
50757503Smuller *pt = '\0';
50857197Smuller --arcn->nlen;
50957197Smuller }
51057197Smuller return(0);
51157197Smuller }
51257197Smuller
51357197Smuller /*
51457197Smuller * tar_wr()
51557197Smuller * write a tar header for the file specified in the ARCHD to the archive.
51657197Smuller * Have to check for file types that cannot be stored and file names that
51757197Smuller * are too long. Be careful of the term (last arg) to ul_oct, each field
51857197Smuller * of tar has it own spec for the termination character(s).
51957197Smuller * ASSUMED: space after header in header block is zero filled
52057197Smuller * Return:
52157197Smuller * 0 if file has data to be written after the header, 1 if file has NO
52257197Smuller * data to write after the header, -1 if archive write failed
52357197Smuller */
52457197Smuller
52557197Smuller #if __STDC__
52657197Smuller int
tar_wr(register ARCHD * arcn)52757197Smuller tar_wr(register ARCHD *arcn)
52857197Smuller #else
52957197Smuller int
53057197Smuller tar_wr(arcn)
53157197Smuller register ARCHD *arcn;
53257197Smuller #endif
53357197Smuller {
53457197Smuller register HD_TAR *hd;
53557197Smuller int len;
53657197Smuller char hdblk[sizeof(HD_TAR)];
53757197Smuller
53857197Smuller /*
53957197Smuller * check for those file system types which tar cannot store
54057197Smuller */
54157197Smuller switch(arcn->type) {
54257197Smuller case PAX_DIR:
54357197Smuller /*
54457197Smuller * user asked that dirs not be written to the archive
54557197Smuller */
54657197Smuller if (tar_nodir)
54757197Smuller return(1);
54857197Smuller break;
54957197Smuller case PAX_CHR:
55057197Smuller warn(1, "Tar cannot archive a character device %s",
55157197Smuller arcn->org_name);
55257197Smuller return(1);
55357197Smuller case PAX_BLK:
55457197Smuller warn(1, "Tar cannot archive a block device %s", arcn->org_name);
55557197Smuller return(1);
55657197Smuller case PAX_SCK:
55757197Smuller warn(1, "Tar cannot archive a socket %s", arcn->org_name);
55857197Smuller return(1);
55957197Smuller case PAX_FIF:
56057197Smuller warn(1, "Tar cannot archive a fifo %s", arcn->org_name);
56157197Smuller return(1);
56257197Smuller case PAX_SLK:
56357197Smuller case PAX_HLK:
56457197Smuller case PAX_HRG:
56557197Smuller if (arcn->ln_nlen > sizeof(hd->linkname)) {
56657197Smuller warn(1,"Link name too long for tar %s", arcn->ln_name);
56757197Smuller return(1);
56857197Smuller }
56957197Smuller break;
57057197Smuller case PAX_REG:
57157197Smuller case PAX_CTG:
57257197Smuller default:
57357197Smuller break;
57457197Smuller }
57557197Smuller
57657197Smuller /*
57757197Smuller * check file name len, remember extra char for dirs (the / at the end)
57857197Smuller */
57957197Smuller len = arcn->nlen;
58057197Smuller if (arcn->type == PAX_DIR)
58157197Smuller ++len;
58257197Smuller if (len > sizeof(hd->name)) {
58357197Smuller warn(1, "File name too long for tar %s", arcn->name);
58457197Smuller return(1);
58557197Smuller }
58657197Smuller
58757197Smuller /*
58857197Smuller * copy the data out of the ARCHD into the tar header based on the type
58957197Smuller * of the file. Remember many tar readers want the unused fields to be
59057197Smuller * padded with zero. We set the linkflag field (type), the linkname
59157197Smuller * (or zero if not used),the size, and set the padding (if any) to be
59257197Smuller * added after the file data (0 for all other types, as they only have
59357197Smuller * a header)
59457197Smuller */
59557197Smuller hd = (HD_TAR *)hdblk;
59657197Smuller zf_strncpy(hd->name, arcn->name, sizeof(hd->name));
59757197Smuller arcn->pad = 0;
59857197Smuller
59957197Smuller if (arcn->type == PAX_DIR) {
60057197Smuller /*
60157197Smuller * directories are the same as files, except have a filename
60257197Smuller * that ends with a /, we add the slash here. No data follows,
60357197Smuller * dirs, so no pad.
60457197Smuller */
60557197Smuller hd->linkflag = AREGTYPE;
60657197Smuller bzero(hd->linkname, sizeof(hd->linkname));
60757197Smuller hd->name[len-1] = '/';
60857197Smuller if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1))
60957197Smuller goto out;
61057197Smuller } else if (arcn->type == PAX_SLK) {
61157197Smuller /*
61257197Smuller * no data follows this file, so no pad
61357197Smuller */
61457197Smuller hd->linkflag = SYMTYPE;
61557197Smuller zf_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname));
61657197Smuller if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1))
61757197Smuller goto out;
61857197Smuller } else if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG)) {
61957197Smuller /*
62057197Smuller * no data follows this file, so no pad
62157197Smuller */
62257197Smuller hd->linkflag = LNKTYPE;
62357197Smuller zf_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname));
62457197Smuller if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1))
62557197Smuller goto out;
62657197Smuller } else {
62757197Smuller /*
62857197Smuller * data follows this file, so set the pad
62957197Smuller */
63057197Smuller hd->linkflag = AREGTYPE;
63157197Smuller bzero(hd->linkname, sizeof(hd->linkname));
63257197Smuller # ifdef NET2_STAT
63357197Smuller if (ul_oct((u_long)arcn->sb.st_size, hd->size,
63457197Smuller sizeof(hd->size), 1)) {
63557197Smuller # else
63657197Smuller if (uqd_oct((u_quad_t)arcn->sb.st_size, hd->size,
63757197Smuller sizeof(hd->size), 1)) {
63857197Smuller # endif
63957197Smuller warn(1,"File is too large for tar %s", arcn->org_name);
64057197Smuller return(1);
64157197Smuller }
64257197Smuller arcn->pad = TAR_PAD(arcn->sb.st_size);
64357197Smuller }
64457197Smuller
64557197Smuller /*
64657197Smuller * copy those fields that are independent of the type
64757197Smuller */
64857197Smuller if (ul_oct((u_long)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 0) ||
64957197Smuller ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 0) ||
65057197Smuller ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 0) ||
65157197Smuller ul_oct((u_long)arcn->sb.st_mtime, hd->mtime, sizeof(hd->mtime), 1))
65257197Smuller goto out;
65357197Smuller
65457197Smuller /*
65557197Smuller * calculate and add the checksum, then write the header. A return of
65657197Smuller * 0 tells the caller to now write the file data, 1 says no data needs
65757197Smuller * to be written
65857197Smuller */
65957197Smuller if (ul_oct(tar_chksm(hdblk, sizeof(HD_TAR)), hd->chksum,
66057197Smuller sizeof(hd->chksum), 2))
66157197Smuller goto out;
66257197Smuller if (wr_rdbuf(hdblk, sizeof(HD_TAR)) < 0)
66357197Smuller return(-1);
66457197Smuller if (wr_skip((off_t)(BLKMULT - sizeof(HD_TAR))) < 0)
66557197Smuller return(-1);
66657197Smuller if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG))
66757197Smuller return(0);
66857197Smuller return(1);
66957197Smuller
67057197Smuller out:
67157197Smuller /*
67257197Smuller * header field is out of range
67357197Smuller */
67457197Smuller warn(1, "Tar header field is too small for %s", arcn->org_name);
67557197Smuller return(1);
67657197Smuller }
67757197Smuller
67857197Smuller /*
67957197Smuller * Routines for POSIX ustar
68057197Smuller */
68157197Smuller
68257197Smuller /*
68357197Smuller * ustar_strd()
68457197Smuller * initialization for ustar read
68557197Smuller * Return:
68657197Smuller * 0 if ok, -1 otherwise
68757197Smuller */
68857197Smuller
68957197Smuller #if __STDC__
69057197Smuller int
ustar_strd(void)69157197Smuller ustar_strd(void)
69257197Smuller #else
69357197Smuller int
69457197Smuller ustar_strd()
69557197Smuller #endif
69657197Smuller {
69757197Smuller if ((usrtb_start() < 0) || (grptb_start() < 0))
69857197Smuller return(-1);
69957197Smuller return(0);
70057197Smuller }
70157197Smuller
70257197Smuller /*
70357197Smuller * ustar_stwr()
70457197Smuller * initialization for ustar write
70557197Smuller * Return:
70657197Smuller * 0 if ok, -1 otherwise
70757197Smuller */
70857197Smuller
70957197Smuller #if __STDC__
71057197Smuller int
ustar_stwr(void)71157197Smuller ustar_stwr(void)
71257197Smuller #else
71357197Smuller int
71457197Smuller ustar_stwr()
71557197Smuller #endif
71657197Smuller {
71757197Smuller if ((uidtb_start() < 0) || (gidtb_start() < 0))
71857197Smuller return(-1);
71957197Smuller return(0);
72057197Smuller }
72157197Smuller
72257197Smuller /*
72357197Smuller * ustar_id()
72457197Smuller * determine if a block given to us is a valid ustar header. We have to
72557197Smuller * be on the lookout for those pesky blocks of all zero's
72657197Smuller * Return:
72757197Smuller * 0 if a ustar header, -1 otherwise
72857197Smuller */
72957197Smuller
73057197Smuller #if __STDC__
73157197Smuller int
ustar_id(char * blk,int size)73257197Smuller ustar_id(char *blk, int size)
73357197Smuller #else
73457197Smuller int
73557197Smuller ustar_id(blk, size)
73657197Smuller char *blk;
73757197Smuller int size;
73857197Smuller #endif
73957197Smuller {
74057197Smuller register HD_USTAR *hd;
74157197Smuller
74257197Smuller if (size < BLKMULT)
74357197Smuller return(-1);
74457197Smuller hd = (HD_USTAR *)blk;
74557197Smuller
74657197Smuller /*
74757197Smuller * check for block of zero's first, a simple and fast test then check
74857197Smuller * ustar magic cookie. We should use TMAGLEN, but some USTAR archive
74957197Smuller * programs are fouled up and create archives missing the \0. Last we
75057197Smuller * check the checksum. If ok we have to assume it is a valid header.
75157197Smuller */
75257197Smuller if (hd->name[0] == '\0')
75357197Smuller return(-1);
75457197Smuller if (strncmp(hd->magic, TMAGIC, TMAGLEN - 1) != 0)
75557197Smuller return(-1);
75657197Smuller if (asc_ul(hd->chksum,sizeof(hd->chksum),OCT) != tar_chksm(blk,BLKMULT))
75757197Smuller return(-1);
75857197Smuller return(0);
75957197Smuller }
76057197Smuller
76157197Smuller /*
76257197Smuller * ustar_rd()
76357197Smuller * extract the values out of block already determined to be a ustar header.
76457197Smuller * store the values in the ARCHD parameter.
76557197Smuller * Return:
76657197Smuller * 0
76757197Smuller */
76857197Smuller
76957197Smuller #if __STDC__
77057197Smuller int
ustar_rd(register ARCHD * arcn,register char * buf)77157197Smuller ustar_rd(register ARCHD *arcn, register char *buf)
77257197Smuller #else
77357197Smuller int
77457197Smuller ustar_rd(arcn, buf)
77557197Smuller register ARCHD *arcn;
77657197Smuller register char *buf;
77757197Smuller #endif
77857197Smuller {
77957197Smuller register HD_USTAR *hd;
78057197Smuller register char *dest;
78157197Smuller register int cnt = 0;
78257197Smuller dev_t devmajor;
78357197Smuller dev_t devminor;
78457197Smuller
78557197Smuller /*
78657197Smuller * we only get proper sized buffers
78757197Smuller */
78857197Smuller if (ustar_id(buf, BLKMULT) < 0)
78957197Smuller return(-1);
79057197Smuller arcn->org_name = arcn->name;
79157197Smuller arcn->sb.st_nlink = 1;
79257197Smuller arcn->pat = NULL;
79357197Smuller hd = (HD_USTAR *)buf;
79457197Smuller
79557197Smuller /*
79657197Smuller * see if the filename is split into two parts. if, so joint the parts.
79757197Smuller * we copy the prefix first and add a / between the prefix and name.
79857197Smuller */
79957197Smuller dest = arcn->name;
80057197Smuller if (*(hd->prefix) != '\0') {
80157197Smuller cnt = l_strncpy(arcn->name, hd->prefix, sizeof(hd->prefix));
80257197Smuller dest = arcn->name + arcn->nlen;
80357197Smuller *dest++ = '/';
80457197Smuller }
80557197Smuller arcn->nlen = l_strncpy(dest, hd->name, sizeof(hd->name));
80657197Smuller arcn->nlen += cnt;
80757197Smuller arcn->name[arcn->nlen] = '\0';
80857197Smuller
80957197Smuller /*
81057503Smuller * follow the spec to the letter. we should only have mode bits, strip
81157197Smuller * off all other crud we may be passed.
81257197Smuller */
81357197Smuller arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode, sizeof(hd->mode), OCT) &
81457197Smuller 0xfff);
81557197Smuller arcn->sb.st_size = (size_t)asc_ul(hd->size, sizeof(hd->size), OCT);
81657197Smuller arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT);
81757503Smuller arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
81857197Smuller
81957197Smuller /*
82057197Smuller * If we can find the ascii names for gname and uname in the password
82157197Smuller * and group files we will use the uid's and gid they bind. Otherwise
82257503Smuller * we use the uid and gid values stored in the header. (This is what
82357503Smuller * the posix spec wants).
82457197Smuller */
82557197Smuller hd->gname[sizeof(hd->gname) - 1] = '\0';
82657197Smuller if (gid_name(hd->gname, &(arcn->sb.st_gid)) < 0)
82757197Smuller arcn->sb.st_gid = (gid_t)asc_ul(hd->gid, sizeof(hd->gid), OCT);
82857197Smuller hd->uname[sizeof(hd->uname) - 1] = '\0';
82957197Smuller if (uid_name(hd->uname, &(arcn->sb.st_uid)) < 0)
83057197Smuller arcn->sb.st_uid = (uid_t)asc_ul(hd->uid, sizeof(hd->uid), OCT);
83157197Smuller
83257197Smuller /*
83357197Smuller * set the defaults, these may be changed depending on the file type
83457197Smuller */
83557197Smuller arcn->ln_name[0] = '\0';
83657197Smuller arcn->ln_nlen = 0;
83757197Smuller arcn->pad = 0;
83857197Smuller arcn->skip = 0;
83957197Smuller arcn->sb.st_rdev = (dev_t)0;
84057197Smuller
84157197Smuller /*
84257197Smuller * set the mode and PAX type according to the typeflag in the header
84357197Smuller */
84457197Smuller switch(hd->typeflag) {
84557197Smuller case FIFOTYPE:
84657197Smuller arcn->type = PAX_FIF;
84757197Smuller arcn->sb.st_mode |= S_IFIFO;
84857197Smuller break;
84957197Smuller case DIRTYPE:
85057197Smuller arcn->type = PAX_DIR;
85157197Smuller arcn->sb.st_mode |= S_IFDIR;
85257197Smuller arcn->sb.st_nlink = 2;
85357788Smuller
85457788Smuller /*
855*66890Sbostic * Some programs that create ustar archives append a '/'
856*66890Sbostic * to the pathname for directories. This clearly violates
857*66890Sbostic * ustar specs, but we will silently strip it off anyway.
858*66890Sbostic */
859*66890Sbostic if (arcn->name[arcn->nlen - 1] == '/')
860*66890Sbostic arcn->name[--arcn->nlen] = '\0';
86157197Smuller break;
86257197Smuller case BLKTYPE:
86357197Smuller case CHRTYPE:
86457197Smuller /*
86557197Smuller * this type requires the rdev field to be set.
86657197Smuller */
86757197Smuller if (hd->typeflag == BLKTYPE) {
86857197Smuller arcn->type = PAX_BLK;
86957197Smuller arcn->sb.st_mode |= S_IFBLK;
87057197Smuller } else {
87157197Smuller arcn->type = PAX_CHR;
87257197Smuller arcn->sb.st_mode |= S_IFCHR;
87357197Smuller }
87457197Smuller devmajor = (dev_t)asc_ul(hd->devmajor,sizeof(hd->devmajor),OCT);
87557197Smuller devminor = (dev_t)asc_ul(hd->devminor,sizeof(hd->devminor),OCT);
87657197Smuller arcn->sb.st_rdev = TODEV(devmajor, devminor);
87757197Smuller break;
87857197Smuller case SYMTYPE:
87957197Smuller case LNKTYPE:
88057197Smuller if (hd->typeflag == SYMTYPE) {
88157197Smuller arcn->type = PAX_SLK;
88257197Smuller arcn->sb.st_mode |= S_IFLNK;
88357197Smuller } else {
88457197Smuller arcn->type = PAX_HLK;
88557197Smuller /*
88657197Smuller * so printing looks better
88757197Smuller */
88857197Smuller arcn->sb.st_mode |= S_IFREG;
88957197Smuller arcn->sb.st_nlink = 2;
89057197Smuller }
89157197Smuller /*
89257197Smuller * copy the link name
89357197Smuller */
89457197Smuller arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname,
89557197Smuller sizeof(hd->linkname));
89657197Smuller arcn->ln_name[arcn->ln_nlen] = '\0';
89757197Smuller break;
89857197Smuller case CONTTYPE:
89957197Smuller case AREGTYPE:
90057197Smuller case REGTYPE:
90157197Smuller default:
90257197Smuller /*
90357197Smuller * these types have file data that follows. Set the skip and
90457197Smuller * pad fields.
90557197Smuller */
90657197Smuller arcn->type = PAX_REG;
90757197Smuller arcn->pad = TAR_PAD(arcn->sb.st_size);
90857197Smuller arcn->skip = arcn->sb.st_size;
90957197Smuller arcn->sb.st_mode |= S_IFREG;
91057197Smuller break;
91157197Smuller }
91257197Smuller return(0);
91357197Smuller }
91457197Smuller
91557197Smuller /*
91657197Smuller * ustar_wr()
91757197Smuller * write a ustar header for the file specified in the ARCHD to the archive
91857197Smuller * Have to check for file types that cannot be stored and file names that
91957197Smuller * are too long. Be careful of the term (last arg) to ul_oct, we only use
92057197Smuller * '\0' for the termination character (this is different than picky tar)
92157197Smuller * ASSUMED: space after header in header block is zero filled
92257197Smuller * Return:
92357197Smuller * 0 if file has data to be written after the header, 1 if file has NO
92457197Smuller * data to write after the header, -1 if archive write failed
92557197Smuller */
92657197Smuller
92757197Smuller #if __STDC__
92857197Smuller int
ustar_wr(register ARCHD * arcn)92957197Smuller ustar_wr(register ARCHD *arcn)
93057197Smuller #else
93157197Smuller int
93257197Smuller ustar_wr(arcn)
93357197Smuller register ARCHD *arcn;
93457197Smuller #endif
93557197Smuller {
93657197Smuller register HD_USTAR *hd;
93757197Smuller register char *pt;
93857197Smuller char hdblk[sizeof(HD_USTAR)];
93957197Smuller
94057197Smuller /*
94157197Smuller * check for those file system types ustar cannot store
94257197Smuller */
94357197Smuller if (arcn->type == PAX_SCK) {
94457197Smuller warn(1, "Ustar cannot archive a socket %s", arcn->org_name);
94557197Smuller return(1);
94657197Smuller }
94757197Smuller
94857197Smuller /*
94957197Smuller * check the length of the linkname
95057197Smuller */
95157197Smuller if (((arcn->type == PAX_SLK) || (arcn->type == PAX_HLK) ||
95257197Smuller (arcn->type == PAX_HRG)) && (arcn->ln_nlen > sizeof(hd->linkname))){
95357197Smuller warn(1, "Link name too long for ustar %s", arcn->ln_name);
95457197Smuller return(1);
95557197Smuller }
95657197Smuller
95757197Smuller /*
95857197Smuller * split the path name into prefix and name fields (if needed). if
95957197Smuller * pt != arcn->name, the name has to be split
96057197Smuller */
96157197Smuller if ((pt = name_split(arcn->name, arcn->nlen)) == NULL) {
96257197Smuller warn(1, "File name too long for ustar %s", arcn->name);
96357197Smuller return(1);
96457197Smuller }
96557197Smuller hd = (HD_USTAR *)hdblk;
96657197Smuller arcn->pad = 0L;
96757197Smuller
96857197Smuller /*
96957197Smuller * split the name, or zero out the prefix
97057197Smuller */
97157197Smuller if (pt != arcn->name) {
97257197Smuller /*
97357197Smuller * name was split, pt points at the / where the split is to
97457197Smuller * occur, we remove the / and copy the first part to the prefix
97557197Smuller */
97657197Smuller *pt = '\0';
97757197Smuller zf_strncpy(hd->prefix, arcn->name, sizeof(hd->prefix));
97857197Smuller *pt++ = '/';
97957197Smuller } else
98057197Smuller bzero(hd->prefix, sizeof(hd->prefix));
98157197Smuller
98257197Smuller /*
98357197Smuller * copy the name part. this may be the whole path or the part after
98457197Smuller * the prefix
98557197Smuller */
98657197Smuller zf_strncpy(hd->name, pt, sizeof(hd->name));
98757197Smuller
98857197Smuller /*
98957197Smuller * set the fields in the header that are type dependent
99057197Smuller */
99157197Smuller switch(arcn->type) {
99257197Smuller case PAX_DIR:
99357197Smuller hd->typeflag = DIRTYPE;
99457197Smuller bzero(hd->linkname, sizeof(hd->linkname));
99557197Smuller bzero(hd->devmajor, sizeof(hd->devmajor));
99657197Smuller bzero(hd->devminor, sizeof(hd->devminor));
99757197Smuller if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
99857197Smuller goto out;
99957197Smuller break;
100057197Smuller case PAX_CHR:
100157197Smuller case PAX_BLK:
100257197Smuller if (arcn->type == PAX_CHR)
100357197Smuller hd->typeflag = CHRTYPE;
100457197Smuller else
100557197Smuller hd->typeflag = BLKTYPE;
100657197Smuller bzero(hd->linkname, sizeof(hd->linkname));
100757197Smuller if (ul_oct((u_long)MAJOR(arcn->sb.st_rdev), hd->devmajor,
100857197Smuller sizeof(hd->devmajor), 3) ||
100957197Smuller ul_oct((u_long)MINOR(arcn->sb.st_rdev), hd->devminor,
101057197Smuller sizeof(hd->devminor), 3) ||
101157197Smuller ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
101257197Smuller goto out;
101357197Smuller break;
101457197Smuller case PAX_FIF:
101557197Smuller hd->typeflag = FIFOTYPE;
101657197Smuller bzero(hd->linkname, sizeof(hd->linkname));
101757197Smuller bzero(hd->devmajor, sizeof(hd->devmajor));
101857197Smuller bzero(hd->devminor, sizeof(hd->devminor));
101957197Smuller if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
102057197Smuller goto out;
102157197Smuller break;
102257197Smuller case PAX_SLK:
102357197Smuller case PAX_HLK:
102457197Smuller case PAX_HRG:
102557197Smuller if (arcn->type == PAX_SLK)
102657197Smuller hd->typeflag = SYMTYPE;
102757197Smuller else
102857197Smuller hd->typeflag = LNKTYPE;
102957197Smuller zf_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname));
103057197Smuller bzero(hd->devmajor, sizeof(hd->devmajor));
103157197Smuller bzero(hd->devminor, sizeof(hd->devminor));
103257197Smuller if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
103357197Smuller goto out;
103457197Smuller break;
103557197Smuller case PAX_REG:
103657197Smuller case PAX_CTG:
103757197Smuller default:
103857197Smuller /*
103957197Smuller * file data with this type, set the padding
104057197Smuller */
104157197Smuller if (arcn->type == PAX_CTG)
104257197Smuller hd->typeflag = CONTTYPE;
104357197Smuller else
104457197Smuller hd->typeflag = REGTYPE;
104557197Smuller bzero(hd->linkname, sizeof(hd->linkname));
104657197Smuller bzero(hd->devmajor, sizeof(hd->devmajor));
104757197Smuller bzero(hd->devminor, sizeof(hd->devminor));
104857197Smuller arcn->pad = TAR_PAD(arcn->sb.st_size);
104957197Smuller # ifdef NET2_STAT
105057197Smuller if (ul_oct((u_long)arcn->sb.st_size, hd->size,
105157197Smuller sizeof(hd->size), 3)) {
105257197Smuller # else
105357197Smuller if (uqd_oct((u_quad_t)arcn->sb.st_size, hd->size,
105457197Smuller sizeof(hd->size), 3)) {
105557197Smuller # endif
105657197Smuller warn(1,"File is too long for ustar %s",arcn->org_name);
105757197Smuller return(1);
105857197Smuller }
105957197Smuller break;
106057197Smuller }
106157197Smuller
106257197Smuller zf_strncpy(hd->magic, TMAGIC, TMAGLEN);
106357197Smuller zf_strncpy(hd->version, TVERSION, TVERSLEN);
106457197Smuller
106557197Smuller /*
106657197Smuller * set the remaining fields. Some versions want all 16 bits of mode
106757197Smuller * we better humor them (they really do not meet spec though)....
106857197Smuller */
106957197Smuller if (ul_oct((u_long)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 3) ||
107057197Smuller ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 3) ||
107157197Smuller ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 3) ||
107257197Smuller ul_oct((u_long)arcn->sb.st_mtime,hd->mtime,sizeof(hd->mtime),3))
107357197Smuller goto out;
107457197Smuller zf_strncpy(hd->uname,name_uid(arcn->sb.st_uid, 0),sizeof(hd->uname));
107557197Smuller zf_strncpy(hd->gname,name_gid(arcn->sb.st_gid, 0),sizeof(hd->gname));
107657197Smuller
107757197Smuller /*
107857197Smuller * calculate and store the checksum write the header to the archive
107957197Smuller * return 0 tells the caller to now write the file data, 1 says no data
108057197Smuller * needs to be written
108157197Smuller */
108257197Smuller if (ul_oct(tar_chksm(hdblk, sizeof(HD_USTAR)), hd->chksum,
108357197Smuller sizeof(hd->chksum), 3))
108457197Smuller goto out;
108557197Smuller if (wr_rdbuf(hdblk, sizeof(HD_USTAR)) < 0)
108657197Smuller return(-1);
108757197Smuller if (wr_skip((off_t)(BLKMULT - sizeof(HD_USTAR))) < 0)
108857197Smuller return(-1);
108957197Smuller if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG))
109057197Smuller return(0);
109157197Smuller return(1);
109257197Smuller
109357197Smuller out:
109457197Smuller /*
109557197Smuller * header field is out of range
109657197Smuller */
109757197Smuller warn(1, "Ustar header field is too small for %s", arcn->org_name);
109857197Smuller return(1);
109957197Smuller }
110057197Smuller
110157197Smuller /*
110257197Smuller * name_split()
110357197Smuller * see if the name has to be split for storage in a ustar header. We try
110457197Smuller * to fit the entire name in the name field without splitting if we can.
110557197Smuller * The split point is always at a /
110657197Smuller * Return
110757197Smuller * character pointer to split point (always the / that is to be removed
110857197Smuller * if the split is not needed, the points is set to the start of the file
110957197Smuller * name (it would violate the spec to split there). A NULL is returned if
111057197Smuller * the file name is too long
111157197Smuller */
111257197Smuller
111357197Smuller #if __STDC__
111457197Smuller static char *
name_split(register char * name,register int len)111557197Smuller name_split(register char *name, register int len)
111657197Smuller #else
111757197Smuller static char *
111857197Smuller name_split(name, len)
111957197Smuller register char *name;
112057197Smuller register int len;
112157197Smuller #endif
112257197Smuller {
112357197Smuller register char *start;
112457197Smuller
112557197Smuller /*
112657197Smuller * check to see if the file name is small enough to fit in the name
112757197Smuller * field. if so just return a pointer to the name.
112857197Smuller */
112957197Smuller if (len <= TNMSZ)
113057197Smuller return(name);
113157197Smuller if (len > (TPFSZ + TNMSZ + 1))
113257197Smuller return(NULL);
113357197Smuller
113457197Smuller /*
113557197Smuller * we start looking at the biggest sized piece that fits in the name
113657197Smuller * field. We walk foward looking for a slash to split at. The idea is
113757197Smuller * to find the biggest piece to fit in the name field (or the smallest
113857197Smuller * prefix we can find) (the -1 is correct the biggest piece would
113957197Smuller * include the slash between the two parts that gets thrown away)
114057197Smuller */
114157197Smuller start = name + len - TNMSZ - 1;
114257197Smuller while ((*start != '\0') && (*start != '/'))
114357197Smuller ++start;
114457197Smuller
114557197Smuller /*
114657197Smuller * if we hit the end of the string, this name cannot be split, so we
114757197Smuller * cannot store this file.
114857197Smuller */
114957197Smuller if (*start == '\0')
115057197Smuller return(NULL);
115157197Smuller len = start - name;
115257197Smuller
115357197Smuller /*
115457197Smuller * NOTE: /str where the length of str == TNMSZ can not be stored under
115557197Smuller * the p1003.1-1990 spec for ustar. We could force a prefix of / and
115657197Smuller * the file would then expand on extract to //str. The len == 0 below
115757197Smuller * makes this special case follow the spec to the letter.
115857197Smuller */
115957197Smuller if ((len > TPFSZ) || (len == 0))
116057197Smuller return(NULL);
116157197Smuller
116257197Smuller /*
116357197Smuller * ok have a split point, return it to the caller
116457197Smuller */
116557197Smuller return(start);
116657197Smuller }
1167