xref: /csrg-svn/bin/pax/tar.c (revision 66890)
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