xref: /netbsd-src/bin/pax/tar.c (revision 2b9c0f9f43ba74451b873b59bedeb267f2fc4a30)
1*2b9c0f9fSriastradh /*	$NetBSD: tar.c,v 1.76 2024/08/05 13:37:27 riastradh Exp $	*/
2b5b29542Sagc 
3b5b29542Sagc /*-
4ed6ed8e6Sagc  * Copyright (c) 1992 Keith Muller.
5b5b29542Sagc  * Copyright (c) 1992, 1993
6b5b29542Sagc  *	The Regents of the University of California.  All rights reserved.
7b5b29542Sagc  *
8b5b29542Sagc  * This code is derived from software contributed to Berkeley by
9b5b29542Sagc  * Keith Muller of the University of California, San Diego.
10b5b29542Sagc  *
11b5b29542Sagc  * Redistribution and use in source and binary forms, with or without
12b5b29542Sagc  * modification, are permitted provided that the following conditions
13b5b29542Sagc  * are met:
14b5b29542Sagc  * 1. Redistributions of source code must retain the above copyright
15b5b29542Sagc  *    notice, this list of conditions and the following disclaimer.
16b5b29542Sagc  * 2. Redistributions in binary form must reproduce the above copyright
17b5b29542Sagc  *    notice, this list of conditions and the following disclaimer in the
18b5b29542Sagc  *    documentation and/or other materials provided with the distribution.
19b5b29542Sagc  * 3. Neither the name of the University nor the names of its contributors
20b5b29542Sagc  *    may be used to endorse or promote products derived from this software
21b5b29542Sagc  *    without specific prior written permission.
22b5b29542Sagc  *
23b5b29542Sagc  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24b5b29542Sagc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25b5b29542Sagc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26b5b29542Sagc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27b5b29542Sagc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28b5b29542Sagc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29b5b29542Sagc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30b5b29542Sagc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31b5b29542Sagc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32b5b29542Sagc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33b5b29542Sagc  * SUCH DAMAGE.
34b5b29542Sagc  */
3549f0ad86Scgd 
36171d6532Slukem #if HAVE_NBTOOL_CONFIG_H
37171d6532Slukem #include "nbtool_config.h"
38171d6532Slukem #endif
39171d6532Slukem 
40f3cd6022Schristos #include <sys/cdefs.h>
41171d6532Slukem #if !defined(lint)
4249f0ad86Scgd #if 0
4349f0ad86Scgd static char sccsid[] = "@(#)tar.c	8.2 (Berkeley) 4/18/94";
4449f0ad86Scgd #else
45*2b9c0f9fSriastradh __RCSID("$NetBSD: tar.c,v 1.76 2024/08/05 13:37:27 riastradh Exp $");
4649f0ad86Scgd #endif
478b35abe2Sjtc #endif /* not lint */
488b35abe2Sjtc 
498b35abe2Sjtc #include <sys/types.h>
508b35abe2Sjtc #include <sys/time.h>
518b35abe2Sjtc #include <sys/stat.h>
528b35abe2Sjtc #include <sys/param.h>
53d0e267dcSmycroft 
548b35abe2Sjtc #include <ctype.h>
55ce6b1876Smrg #include <errno.h>
56d0e267dcSmycroft #include <grp.h>
57d0e267dcSmycroft #include <pwd.h>
58d0e267dcSmycroft #include <stdio.h>
598b35abe2Sjtc #include <stdlib.h>
60d0e267dcSmycroft #include <string.h>
61d0e267dcSmycroft #include <unistd.h>
62d0e267dcSmycroft 
638b35abe2Sjtc #include "pax.h"
648b35abe2Sjtc #include "extern.h"
658b35abe2Sjtc #include "tar.h"
668b35abe2Sjtc 
679158fb65Schristos extern struct stat tst;
689158fb65Schristos 
698b35abe2Sjtc /*
708b35abe2Sjtc  * Routines for reading, writing and header identify of various versions of tar
718b35abe2Sjtc  */
728b35abe2Sjtc 
73d980bf34Schristos static int expandname(char *, size_t,  char **, size_t *, const char *, size_t);
74393b592bSchristos static void longlink(ARCHD *, int);
75d653d57cSchristos static uint32_t tar_chksm(char *, int);
76c1bd745cSlukem static char *name_split(char *, int);
77d653d57cSchristos static int u32_oct(uintmax_t, char *, int, int);
78d653d57cSchristos static int umax_oct(uintmax_t, char *, int, int);
79c3510d14Smrg static int tar_gnutar_exclude_one(const char *, size_t);
802d72f725Smatt static int check_sum(char *, size_t, char *, size_t, int);
818b35abe2Sjtc 
828b35abe2Sjtc /*
838b35abe2Sjtc  * Routines common to all versions of tar
848b35abe2Sjtc  */
858b35abe2Sjtc 
868b35abe2Sjtc static int tar_nodir;			/* do not write dirs under old tar */
87f830cb18Schristos int is_gnutar;				/* behave like gnu tar; enable gnu
88702d1ca5Schristos 					 * extensions and skip end-of-volume
89f70dfaafSchristos 					 * checks
90f70dfaafSchristos 					 */
912665f9c6Schristos static int seen_gnu_warning;		/* Have we warned yet? */
924472ef15Schristos static char *gnu_hack_string;		/* ././@LongLink hackery */
934472ef15Schristos static int gnu_hack_len;		/* len of gnu_hack_string */
944472ef15Schristos char *gnu_name_string;			/* ././@LongLink hackery name */
95ed254499Schristos char *gnu_link_string;			/* ././@LongLink hackery link */
96d980bf34Schristos size_t gnu_name_length;			/* ././@LongLink hackery name */
97d980bf34Schristos size_t gnu_link_length;			/* ././@LongLink hackery link */
9857c1f1cfSchristos static int gnu_short_trailer;		/* gnu short trailer */
998b35abe2Sjtc 
10044eb0ccaSchristos static const char LONG_LINK[] = "././@LongLink";
10144eb0ccaSchristos 
1025820cbfaSchristos #ifdef _PAX_
1035820cbfaSchristos char DEV_0[] = "/dev/rst0";
1045820cbfaSchristos char DEV_1[] = "/dev/rst1";
1055820cbfaSchristos char DEV_4[] = "/dev/rst4";
1065820cbfaSchristos char DEV_5[] = "/dev/rst5";
1075820cbfaSchristos char DEV_7[] = "/dev/rst7";
1085820cbfaSchristos char DEV_8[] = "/dev/rst8";
1095820cbfaSchristos #endif
1105820cbfaSchristos 
111e1a41a0eSchristos static int
1122d72f725Smatt check_sum(char *hd, size_t hdlen, char *bl, size_t bllen, int quiet)
113e1a41a0eSchristos {
114d653d57cSchristos 	uint32_t hdck, blck;
115e1a41a0eSchristos 
116d653d57cSchristos 	hdck = asc_u32(hd, hdlen, OCT);
117e1a41a0eSchristos 	blck = tar_chksm(bl, bllen);
118e1a41a0eSchristos 
119e1a41a0eSchristos 	if (hdck != blck) {
1202d72f725Smatt 		if (!quiet)
121d653d57cSchristos 			tty_warn(0, "Header checksum %o does not match %o",
122e1a41a0eSchristos 			    hdck, blck);
123cdec4ac1Sdsl 		return -1;
124e1a41a0eSchristos 	}
125cdec4ac1Sdsl 	return 0;
126e1a41a0eSchristos }
127e1a41a0eSchristos 
128e1a41a0eSchristos 
1298b35abe2Sjtc /*
1308b35abe2Sjtc  * tar_endwr()
1318b35abe2Sjtc  *	add the tar trailer of two null blocks
1328b35abe2Sjtc  * Return:
1338b35abe2Sjtc  *	0 if ok, -1 otherwise (what wr_skip returns)
1348b35abe2Sjtc  */
1358b35abe2Sjtc 
1368b35abe2Sjtc int
1378b35abe2Sjtc tar_endwr(void)
1388b35abe2Sjtc {
139cdec4ac1Sdsl 	return wr_skip((off_t)(NULLCNT * BLKMULT));
1408b35abe2Sjtc }
1418b35abe2Sjtc 
1428b35abe2Sjtc /*
1438b35abe2Sjtc  * tar_endrd()
1448b35abe2Sjtc  *	no cleanup needed here, just return size of trailer (for append)
1458b35abe2Sjtc  * Return:
14692ffc695Schristos  *	size of trailer BLKMULT
1478b35abe2Sjtc  */
1488b35abe2Sjtc 
1498b35abe2Sjtc off_t
1508b35abe2Sjtc tar_endrd(void)
1518b35abe2Sjtc {
152cdec4ac1Sdsl 	return (off_t)((gnu_short_trailer ? 1 : NULLCNT) * BLKMULT);
1538b35abe2Sjtc }
1548b35abe2Sjtc 
1558b35abe2Sjtc /*
1568b35abe2Sjtc  * tar_trail()
1578b35abe2Sjtc  *	Called to determine if a header block is a valid trailer. We are passed
1588b35abe2Sjtc  *	the block, the in_sync flag (which tells us we are in resync mode;
1598b35abe2Sjtc  *	looking for a valid header), and cnt (which starts at zero) which is
1608b35abe2Sjtc  *	used to count the number of empty blocks we have seen so far.
1618b35abe2Sjtc  * Return:
1628b35abe2Sjtc  *	0 if a valid trailer, -1 if not a valid trailer, or 1 if the block
1638b35abe2Sjtc  *	could never contain a header.
1648b35abe2Sjtc  */
1658b35abe2Sjtc 
1668b35abe2Sjtc int
16748250187Stls tar_trail(char *buf, int in_resync, int *cnt)
1688b35abe2Sjtc {
16948250187Stls 	int i;
1708b35abe2Sjtc 
17157c1f1cfSchristos 	gnu_short_trailer = 0;
1728b35abe2Sjtc 	/*
1738b35abe2Sjtc 	 * look for all zero, trailer is two consecutive blocks of zero
1748b35abe2Sjtc 	 */
1758b35abe2Sjtc 	for (i = 0; i < BLKMULT; ++i) {
176096c9d63Schristos 		if (buf[i] != '\0')
1778b35abe2Sjtc 			break;
1788b35abe2Sjtc 	}
1798b35abe2Sjtc 
1808b35abe2Sjtc 	/*
1818b35abe2Sjtc 	 * if not all zero it is not a trailer, but MIGHT be a header.
1828b35abe2Sjtc 	 */
1838b35abe2Sjtc 	if (i != BLKMULT)
184cdec4ac1Sdsl 		return -1;
1858b35abe2Sjtc 
1868b35abe2Sjtc 	/*
1878b35abe2Sjtc 	 * When given a zero block, we must be careful!
1888b35abe2Sjtc 	 * If we are not in resync mode, check for the trailer. Have to watch
1898b35abe2Sjtc 	 * out that we do not mis-identify file data as the trailer, so we do
1908b35abe2Sjtc 	 * NOT try to id a trailer during resync mode. During resync mode we
1918b35abe2Sjtc 	 * might as well throw this block out since a valid header can NEVER be
1928b35abe2Sjtc 	 * a block of all 0 (we must have a valid file name).
1938b35abe2Sjtc 	 */
1942cdcd6caSchristos 	if (!in_resync) {
1952cdcd6caSchristos 		++*cnt;
1962cdcd6caSchristos 		/*
1972cdcd6caSchristos 		 * old GNU tar (up through 1.13) only writes one block of
1982cdcd6caSchristos 		 * trailers, so we pretend we got another
1992cdcd6caSchristos 		 */
20057c1f1cfSchristos 		if (is_gnutar) {
20157c1f1cfSchristos 			gnu_short_trailer = 1;
2022cdcd6caSchristos 			++*cnt;
20357c1f1cfSchristos 		}
2042cdcd6caSchristos 		if (*cnt >= NULLCNT)
205cdec4ac1Sdsl 			return 0;
2062cdcd6caSchristos 	}
207cdec4ac1Sdsl 	return 1;
2088b35abe2Sjtc }
2098b35abe2Sjtc 
2108b35abe2Sjtc /*
211d653d57cSchristos  * u32_oct()
212d653d57cSchristos  *	convert an uintmax_t to an octal string. many oddball field
2138b35abe2Sjtc  *	termination characters are used by the various versions of tar in the
214e5b01aa2Skleink  *	different fields. term selects which kind to use. str is '0' padded
2158b35abe2Sjtc  *	at the front to len. we are unable to use only one format as many old
2168b35abe2Sjtc  *	tar readers are very cranky about this.
2178b35abe2Sjtc  * Return:
2188b35abe2Sjtc  *	0 if the number fit into the string, -1 otherwise
2198b35abe2Sjtc  */
2208b35abe2Sjtc 
2218b35abe2Sjtc static int
222d653d57cSchristos u32_oct(uintmax_t val, char *str, int len, int term)
2238b35abe2Sjtc {
22448250187Stls 	char *pt;
225d653d57cSchristos 	uint64_t p;
226d653d57cSchristos 
227d653d57cSchristos 	p = val & TOP_HALF;
228d653d57cSchristos 	if (p && p != TOP_HALF)
229d653d57cSchristos 		return -1;
230d653d57cSchristos 
231d653d57cSchristos 	val &= BOTTOM_HALF;
2328b35abe2Sjtc 
2338b35abe2Sjtc 	/*
2348b35abe2Sjtc 	 * term selects the appropriate character(s) for the end of the string
2358b35abe2Sjtc 	 */
2368b35abe2Sjtc 	pt = str + len - 1;
2378b35abe2Sjtc 	switch(term) {
2388b35abe2Sjtc 	case 3:
2398b35abe2Sjtc 		*pt-- = '\0';
2408b35abe2Sjtc 		break;
2418b35abe2Sjtc 	case 2:
2428b35abe2Sjtc 		*pt-- = ' ';
2438b35abe2Sjtc 		*pt-- = '\0';
2448b35abe2Sjtc 		break;
2458b35abe2Sjtc 	case 1:
2468b35abe2Sjtc 		*pt-- = ' ';
2478b35abe2Sjtc 		break;
2488b35abe2Sjtc 	case 0:
2498b35abe2Sjtc 	default:
2508b35abe2Sjtc 		*pt-- = '\0';
2518b35abe2Sjtc 		*pt-- = ' ';
2528b35abe2Sjtc 		break;
2538b35abe2Sjtc 	}
2548b35abe2Sjtc 
2558b35abe2Sjtc 	/*
2568b35abe2Sjtc 	 * convert and blank pad if there is space
2578b35abe2Sjtc 	 */
2588b35abe2Sjtc 	while (pt >= str) {
2598b35abe2Sjtc 		*pt-- = '0' + (char)(val & 0x7);
260d653d57cSchristos 		if ((val = val >> 3) == 0)
2618b35abe2Sjtc 			break;
2628b35abe2Sjtc 	}
2638b35abe2Sjtc 
2648b35abe2Sjtc 	while (pt >= str)
265e5b01aa2Skleink 		*pt-- = '0';
266d653d57cSchristos 	if (val != 0)
267cdec4ac1Sdsl 		return -1;
268cdec4ac1Sdsl 	return 0;
2698b35abe2Sjtc }
2708b35abe2Sjtc 
2718b35abe2Sjtc /*
272d653d57cSchristos  * umax_oct()
2739ee82d31Slukem  *	convert an unsigned long long to an octal string. one of many oddball
2749ee82d31Slukem  *	field termination characters are used by the various versions of tar
2759ee82d31Slukem  *	in the different fields. term selects which kind to use. str is '0'
2769ee82d31Slukem  *	padded at the front to len. we are unable to use only one format as
2779ee82d31Slukem  *	many old tar readers are very cranky about this.
2788b35abe2Sjtc  * Return:
2798b35abe2Sjtc  *	0 if the number fit into the string, -1 otherwise
2808b35abe2Sjtc  */
2818b35abe2Sjtc 
2828b35abe2Sjtc static int
283d653d57cSchristos umax_oct(uintmax_t val, char *str, int len, int term)
2848b35abe2Sjtc {
28548250187Stls 	char *pt;
2868b35abe2Sjtc 
2878b35abe2Sjtc 	/*
2888b35abe2Sjtc 	 * term selects the appropriate character(s) for the end of the string
2898b35abe2Sjtc 	 */
2908b35abe2Sjtc 	pt = str + len - 1;
2918b35abe2Sjtc 	switch(term) {
2928b35abe2Sjtc 	case 3:
2938b35abe2Sjtc 		*pt-- = '\0';
2948b35abe2Sjtc 		break;
2958b35abe2Sjtc 	case 2:
2968b35abe2Sjtc 		*pt-- = ' ';
2978b35abe2Sjtc 		*pt-- = '\0';
2988b35abe2Sjtc 		break;
2998b35abe2Sjtc 	case 1:
3008b35abe2Sjtc 		*pt-- = ' ';
3018b35abe2Sjtc 		break;
3028b35abe2Sjtc 	case 0:
3038b35abe2Sjtc 	default:
3048b35abe2Sjtc 		*pt-- = '\0';
3058b35abe2Sjtc 		*pt-- = ' ';
3068b35abe2Sjtc 		break;
3078b35abe2Sjtc 	}
3088b35abe2Sjtc 
3098b35abe2Sjtc 	/*
3108b35abe2Sjtc 	 * convert and blank pad if there is space
3118b35abe2Sjtc 	 */
3128b35abe2Sjtc 	while (pt >= str) {
3138b35abe2Sjtc 		*pt-- = '0' + (char)(val & 0x7);
3148b35abe2Sjtc 		if ((val = val >> 3) == 0)
3158b35abe2Sjtc 			break;
3168b35abe2Sjtc 	}
3178b35abe2Sjtc 
3188b35abe2Sjtc 	while (pt >= str)
319e5b01aa2Skleink 		*pt-- = '0';
320d653d57cSchristos 	if (val != 0)
321cdec4ac1Sdsl 		return -1;
322cdec4ac1Sdsl 	return 0;
3238b35abe2Sjtc }
3248b35abe2Sjtc 
3258b35abe2Sjtc /*
3268b35abe2Sjtc  * tar_chksm()
3278b35abe2Sjtc  *	calculate the checksum for a tar block counting the checksum field as
328f8adf56dSitohy  *	all blanks (BLNKSUM is that value pre-calculated, the sum of 8 blanks).
3298b35abe2Sjtc  *	NOTE: we use len to short circuit summing 0's on write since we ALWAYS
3308b35abe2Sjtc  *	pad headers with 0.
3318b35abe2Sjtc  * Return:
3328b35abe2Sjtc  *	unsigned long checksum
3338b35abe2Sjtc  */
3348b35abe2Sjtc 
335d653d57cSchristos static uint32_t
33648250187Stls tar_chksm(char *blk, int len)
3378b35abe2Sjtc {
33848250187Stls 	char *stop;
33948250187Stls 	char *pt;
340d653d57cSchristos 	uint32_t chksm = BLNKSUM;	/* initial value is checksum field sum */
3418b35abe2Sjtc 
3428b35abe2Sjtc 	/*
3438b35abe2Sjtc 	 * add the part of the block before the checksum field
3448b35abe2Sjtc 	 */
3458b35abe2Sjtc 	pt = blk;
3468b35abe2Sjtc 	stop = blk + CHK_OFFSET;
3478b35abe2Sjtc 	while (pt < stop)
348d653d57cSchristos 		chksm += (uint32_t)(*pt++ & 0xff);
3498b35abe2Sjtc 	/*
3508b35abe2Sjtc 	 * move past the checksum field and keep going, spec counts the
3518b35abe2Sjtc 	 * checksum field as the sum of 8 blanks (which is pre-computed as
3528b35abe2Sjtc 	 * BLNKSUM).
3538b35abe2Sjtc 	 * ASSUMED: len is greater than CHK_OFFSET. (len is where our 0 padding
354ee05db82Sgutteridge 	 * starts, no point in summing zeros)
3558b35abe2Sjtc 	 */
3568b35abe2Sjtc 	pt += CHK_LEN;
3578b35abe2Sjtc 	stop = blk + len;
3588b35abe2Sjtc 	while (pt < stop)
359d653d57cSchristos 		chksm += (uint32_t)(*pt++ & 0xff);
360cdec4ac1Sdsl 	return chksm;
3618b35abe2Sjtc }
3628b35abe2Sjtc 
3638b35abe2Sjtc /*
3648b35abe2Sjtc  * Routines for old BSD style tar (also made portable to sysV tar)
3658b35abe2Sjtc  */
3668b35abe2Sjtc 
3678b35abe2Sjtc /*
3688b35abe2Sjtc  * tar_id()
3698b35abe2Sjtc  *	determine if a block given to us is a valid tar header (and not a USTAR
3708b35abe2Sjtc  *	header). We have to be on the lookout for those pesky blocks of	all
371ee05db82Sgutteridge  *	zeros.
3728b35abe2Sjtc  * Return:
3738b35abe2Sjtc  *	0 if a tar header, -1 otherwise
3748b35abe2Sjtc  */
3758b35abe2Sjtc 
3768b35abe2Sjtc int
37748250187Stls tar_id(char *blk, int size)
3788b35abe2Sjtc {
37948250187Stls 	HD_TAR *hd;
38048250187Stls 	HD_USTAR *uhd;
381128abffcSchristos 	static int is_ustar = -1;
3828b35abe2Sjtc 
3838b35abe2Sjtc 	if (size < BLKMULT)
384cdec4ac1Sdsl 		return -1;
3858b35abe2Sjtc 	hd = (HD_TAR *)blk;
3868b35abe2Sjtc 	uhd = (HD_USTAR *)blk;
3878b35abe2Sjtc 
3888b35abe2Sjtc 	/*
389ee05db82Sgutteridge 	 * check for block of zeros first, a simple and fast test, then make
3908b35abe2Sjtc 	 * sure this is not a ustar header by looking for the ustar magic
3918b35abe2Sjtc 	 * cookie. We should use TMAGLEN, but some USTAR archive programs are
3928b35abe2Sjtc 	 * wrong and create archives missing the \0. Last we check the
3938b35abe2Sjtc 	 * checksum. If this is ok we have to assume it is a valid header.
3948b35abe2Sjtc 	 */
3958b35abe2Sjtc 	if (hd->name[0] == '\0')
396cdec4ac1Sdsl 		return -1;
397128abffcSchristos 	if (strncmp(uhd->magic, TMAGIC, TMAGLEN - 1) == 0) {
398128abffcSchristos 		if (is_ustar == -1) {
399128abffcSchristos 			is_ustar = 1;
400cdec4ac1Sdsl 			return -1;
401128abffcSchristos 		} else
402128abffcSchristos 			tty_warn(0,
403128abffcSchristos 			    "Busted tar archive: has both ustar and old tar "
404128abffcSchristos 			    "records");
405128abffcSchristos 	} else
406128abffcSchristos 		is_ustar = 0;
4072d72f725Smatt 	return check_sum(hd->chksum, sizeof(hd->chksum), blk, BLKMULT, 1);
4088b35abe2Sjtc }
4098b35abe2Sjtc 
4108b35abe2Sjtc /*
4118b35abe2Sjtc  * tar_opt()
4128b35abe2Sjtc  *	handle tar format specific -o options
4138b35abe2Sjtc  * Return:
4148b35abe2Sjtc  *	0 if ok -1 otherwise
4158b35abe2Sjtc  */
4168b35abe2Sjtc 
4178b35abe2Sjtc int
4188b35abe2Sjtc tar_opt(void)
4198b35abe2Sjtc {
4208b35abe2Sjtc 	OPLIST *opt;
4218b35abe2Sjtc 
4228b35abe2Sjtc 	while ((opt = opt_next()) != NULL) {
4238b35abe2Sjtc 		if (strcmp(opt->name, TAR_OPTION) ||
4248b35abe2Sjtc 		    strcmp(opt->value, TAR_NODIR)) {
425f3cd6022Schristos 			tty_warn(1,
426f3cd6022Schristos 			    "Unknown tar format -o option/value pair %s=%s",
4278b35abe2Sjtc 			    opt->name, opt->value);
428f3cd6022Schristos 			tty_warn(1,
429f3cd6022Schristos 			    "%s=%s is the only supported tar format option",
4308b35abe2Sjtc 			    TAR_OPTION, TAR_NODIR);
431cdec4ac1Sdsl 			return -1;
4328b35abe2Sjtc 		}
4338b35abe2Sjtc 
4348b35abe2Sjtc 		/*
4358b35abe2Sjtc 		 * we only support one option, and only when writing
4368b35abe2Sjtc 		 */
4378b35abe2Sjtc 		if ((act != APPND) && (act != ARCHIVE)) {
438f3cd6022Schristos 			tty_warn(1, "%s=%s is only supported when writing.",
4398b35abe2Sjtc 			    opt->name, opt->value);
440cdec4ac1Sdsl 			return -1;
4418b35abe2Sjtc 		}
4428b35abe2Sjtc 		tar_nodir = 1;
4438b35abe2Sjtc 	}
444cdec4ac1Sdsl 	return 0;
4458b35abe2Sjtc }
4468b35abe2Sjtc 
4478b35abe2Sjtc 
4488b35abe2Sjtc /*
4498b35abe2Sjtc  * tar_rd()
4508b35abe2Sjtc  *	extract the values out of block already determined to be a tar header.
4518b35abe2Sjtc  *	store the values in the ARCHD parameter.
4528b35abe2Sjtc  * Return:
4538b35abe2Sjtc  *	0
4548b35abe2Sjtc  */
4558b35abe2Sjtc 
4568b35abe2Sjtc int
45748250187Stls tar_rd(ARCHD *arcn, char *buf)
4588b35abe2Sjtc {
45948250187Stls 	HD_TAR *hd;
46048250187Stls 	char *pt;
4618b35abe2Sjtc 
4628b35abe2Sjtc 	/*
4638b35abe2Sjtc 	 * we only get proper sized buffers passed to us
4648b35abe2Sjtc 	 */
4658b35abe2Sjtc 	if (tar_id(buf, BLKMULT) < 0)
466cdec4ac1Sdsl 		return -1;
4674472ef15Schristos 	memset(arcn, 0, sizeof(*arcn));
4688b35abe2Sjtc 	arcn->org_name = arcn->name;
4698b35abe2Sjtc 	arcn->pat = NULL;
4704472ef15Schristos 	arcn->sb.st_nlink = 1;
4718b35abe2Sjtc 
4728b35abe2Sjtc 	/*
4738b35abe2Sjtc 	 * copy out the name and values in the stat buffer
4748b35abe2Sjtc 	 */
4758b35abe2Sjtc 	hd = (HD_TAR *)buf;
476ed254499Schristos 	if (hd->linkflag != LONGLINKTYPE && hd->linkflag != LONGNAMETYPE) {
477ed254499Schristos 		arcn->nlen = expandname(arcn->name, sizeof(arcn->name),
478d980bf34Schristos 		    &gnu_name_string, &gnu_name_length, hd->name,
479d980bf34Schristos 		    sizeof(hd->name));
480ed254499Schristos 		arcn->ln_nlen = expandname(arcn->ln_name, sizeof(arcn->ln_name),
481d980bf34Schristos 		    &gnu_link_string, &gnu_link_length, hd->linkname,
482d980bf34Schristos 		    sizeof(hd->linkname));
483ed254499Schristos 	}
484d653d57cSchristos 	arcn->sb.st_mode = (mode_t)(asc_u32(hd->mode,sizeof(hd->mode),OCT) &
4858b35abe2Sjtc 	    0xfff);
486d653d57cSchristos 	arcn->sb.st_uid = (uid_t)asc_u32(hd->uid, sizeof(hd->uid), OCT);
487d653d57cSchristos 	arcn->sb.st_gid = (gid_t)asc_u32(hd->gid, sizeof(hd->gid), OCT);
488c1bd745cSlukem 	arcn->sb.st_size = (off_t)ASC_OFFT(hd->size, sizeof(hd->size), OCT);
489a4c163faSchristos 	if (arcn->sb.st_size == -1)
490a4c163faSchristos 		return -1;
491d653d57cSchristos 	arcn->sb.st_mtime = (time_t)(int32_t)asc_u32(hd->mtime, sizeof(hd->mtime), OCT);
4928b35abe2Sjtc 	arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
4938b35abe2Sjtc 
4948b35abe2Sjtc 	/*
4958b35abe2Sjtc 	 * have to look at the last character, it may be a '/' and that is used
4968b35abe2Sjtc 	 * to encode this as a directory
4978b35abe2Sjtc 	 */
4988b35abe2Sjtc 	pt = &(arcn->name[arcn->nlen - 1]);
4998b35abe2Sjtc 	arcn->pad = 0;
5008b35abe2Sjtc 	arcn->skip = 0;
5018b35abe2Sjtc 	switch(hd->linkflag) {
5028b35abe2Sjtc 	case SYMTYPE:
5038b35abe2Sjtc 		/*
5048b35abe2Sjtc 		 * symbolic link, need to get the link name and set the type in
5058b35abe2Sjtc 		 * the st_mode so -v printing will look correct.
5068b35abe2Sjtc 		 */
5078b35abe2Sjtc 		arcn->type = PAX_SLK;
5088b35abe2Sjtc 		arcn->sb.st_mode |= S_IFLNK;
5098b35abe2Sjtc 		break;
5108b35abe2Sjtc 	case LNKTYPE:
5118b35abe2Sjtc 		/*
5128b35abe2Sjtc 		 * hard link, need to get the link name, set the type in the
5138b35abe2Sjtc 		 * st_mode and st_nlink so -v printing will look better.
5148b35abe2Sjtc 		 */
5158b35abe2Sjtc 		arcn->type = PAX_HLK;
5168b35abe2Sjtc 		arcn->sb.st_nlink = 2;
5178b35abe2Sjtc 
5188b35abe2Sjtc 		/*
5198b35abe2Sjtc 		 * no idea of what type this thing really points at, but
5208b35abe2Sjtc 		 * we set something for printing only.
5218b35abe2Sjtc 		 */
5228b35abe2Sjtc 		arcn->sb.st_mode |= S_IFREG;
5238b35abe2Sjtc 		break;
52478e294d1Smrg 	case LONGLINKTYPE:
52578e294d1Smrg 	case LONGNAMETYPE:
52678e294d1Smrg 		/*
52778e294d1Smrg 		 * GNU long link/file; we tag these here and let the
52878e294d1Smrg 		 * pax internals deal with it -- too ugly otherwise.
52978e294d1Smrg 		 */
53078e294d1Smrg 		if (hd->linkflag != LONGLINKTYPE)
53178e294d1Smrg 			arcn->type = PAX_GLF;
53244eb0ccaSchristos 		else
53344eb0ccaSchristos 			arcn->type = PAX_GLL;
53478e294d1Smrg 		arcn->pad = TAR_PAD(arcn->sb.st_size);
53578e294d1Smrg 		arcn->skip = arcn->sb.st_size;
53678e294d1Smrg 		break;
5378b35abe2Sjtc 	case AREGTYPE:
5388b35abe2Sjtc 	case REGTYPE:
5399d3e4494Skleink 	case DIRTYPE:	/* see below */
5408b35abe2Sjtc 	default:
5418b35abe2Sjtc 		/*
5428b35abe2Sjtc 		 * If we have a trailing / this is a directory and NOT a file.
5439d3e4494Skleink 		 * Note: V7 tar doesn't actually have DIRTYPE, but it was
5449d3e4494Skleink 		 * reported that V7 archives using USTAR directories do exist.
5458b35abe2Sjtc 		 */
5469d3e4494Skleink 		if (*pt == '/' || hd->linkflag == DIRTYPE) {
5478b35abe2Sjtc 			/*
5488b35abe2Sjtc 			 * it is a directory, set the mode for -v printing
5498b35abe2Sjtc 			 */
5508b35abe2Sjtc 			arcn->type = PAX_DIR;
5518b35abe2Sjtc 			arcn->sb.st_mode |= S_IFDIR;
5528b35abe2Sjtc 			arcn->sb.st_nlink = 2;
5538b35abe2Sjtc 		} else {
5548b35abe2Sjtc 			/*
5558b35abe2Sjtc 			 * have a file that will be followed by data. Set the
556f8adf56dSitohy 			 * skip value to the size field and calculate the size
5578b35abe2Sjtc 			 * of the padding.
5588b35abe2Sjtc 			 */
5598b35abe2Sjtc 			arcn->type = PAX_REG;
5608b35abe2Sjtc 			arcn->sb.st_mode |= S_IFREG;
5618b35abe2Sjtc 			arcn->pad = TAR_PAD(arcn->sb.st_size);
5628b35abe2Sjtc 			arcn->skip = arcn->sb.st_size;
5638b35abe2Sjtc 		}
5648b35abe2Sjtc 		break;
5658b35abe2Sjtc 	}
5668b35abe2Sjtc 
5678b35abe2Sjtc 	/*
5688b35abe2Sjtc 	 * strip off any trailing slash.
5698b35abe2Sjtc 	 */
5708b35abe2Sjtc 	if (*pt == '/') {
5718b35abe2Sjtc 		*pt = '\0';
5728b35abe2Sjtc 		--arcn->nlen;
5738b35abe2Sjtc 	}
574cdec4ac1Sdsl 	return 0;
5758b35abe2Sjtc }
5768b35abe2Sjtc 
5778b35abe2Sjtc /*
5788b35abe2Sjtc  * tar_wr()
5798b35abe2Sjtc  *	write a tar header for the file specified in the ARCHD to the archive.
5808b35abe2Sjtc  *	Have to check for file types that cannot be stored and file names that
581d653d57cSchristos  *	are too long. Be careful of the term (last arg) to u32_oct, each field
5828b35abe2Sjtc  *	of tar has it own spec for the termination character(s).
5838b35abe2Sjtc  *	ASSUMED: space after header in header block is zero filled
5848b35abe2Sjtc  * Return:
5858b35abe2Sjtc  *	0 if file has data to be written after the header, 1 if file has NO
5868b35abe2Sjtc  *	data to write after the header, -1 if archive write failed
5878b35abe2Sjtc  */
5888b35abe2Sjtc 
5898b35abe2Sjtc int
59048250187Stls tar_wr(ARCHD *arcn)
5918b35abe2Sjtc {
59248250187Stls 	HD_TAR *hd;
5938b35abe2Sjtc 	int len;
5949158fb65Schristos 	uintmax_t mtime;
5958b35abe2Sjtc 	char hdblk[sizeof(HD_TAR)];
5968b35abe2Sjtc 
5978b35abe2Sjtc 	/*
5988b35abe2Sjtc 	 * check for those file system types which tar cannot store
5998b35abe2Sjtc 	 */
6008b35abe2Sjtc 	switch(arcn->type) {
6018b35abe2Sjtc 	case PAX_DIR:
6028b35abe2Sjtc 		/*
6038b35abe2Sjtc 		 * user asked that dirs not be written to the archive
6048b35abe2Sjtc 		 */
6058b35abe2Sjtc 		if (tar_nodir)
606cdec4ac1Sdsl 			return 1;
6078b35abe2Sjtc 		break;
6088b35abe2Sjtc 	case PAX_CHR:
609f3cd6022Schristos 		tty_warn(1, "Tar cannot archive a character device %s",
6108b35abe2Sjtc 		    arcn->org_name);
611cdec4ac1Sdsl 		return 1;
6128b35abe2Sjtc 	case PAX_BLK:
613f3cd6022Schristos 		tty_warn(1,
614f3cd6022Schristos 		    "Tar cannot archive a block device %s", arcn->org_name);
615cdec4ac1Sdsl 		return 1;
6168b35abe2Sjtc 	case PAX_SCK:
617f3cd6022Schristos 		tty_warn(1, "Tar cannot archive a socket %s", arcn->org_name);
618cdec4ac1Sdsl 		return 1;
6198b35abe2Sjtc 	case PAX_FIF:
620f3cd6022Schristos 		tty_warn(1, "Tar cannot archive a fifo %s", arcn->org_name);
621cdec4ac1Sdsl 		return 1;
6228b35abe2Sjtc 	case PAX_SLK:
6238b35abe2Sjtc 	case PAX_HLK:
6248b35abe2Sjtc 	case PAX_HRG:
625990d25a9Slukem 		if (arcn->ln_nlen > (int)sizeof(hd->linkname)) {
626f3cd6022Schristos 			tty_warn(1,"Link name too long for tar %s",
627f3cd6022Schristos 			    arcn->ln_name);
628cdec4ac1Sdsl 			return 1;
6298b35abe2Sjtc 		}
6308b35abe2Sjtc 		break;
6318b35abe2Sjtc 	case PAX_REG:
6328b35abe2Sjtc 	case PAX_CTG:
6338b35abe2Sjtc 	default:
6348b35abe2Sjtc 		break;
6358b35abe2Sjtc 	}
6368b35abe2Sjtc 
6378b35abe2Sjtc 	/*
6388b35abe2Sjtc 	 * check file name len, remember extra char for dirs (the / at the end)
6398b35abe2Sjtc 	 */
6408b35abe2Sjtc 	len = arcn->nlen;
6418b35abe2Sjtc 	if (arcn->type == PAX_DIR)
6428b35abe2Sjtc 		++len;
643990d25a9Slukem 	if (len >= (int)sizeof(hd->name)) {
644f3cd6022Schristos 		tty_warn(1, "File name too long for tar %s", arcn->name);
645cdec4ac1Sdsl 		return 1;
6468b35abe2Sjtc 	}
6478b35abe2Sjtc 
6488b35abe2Sjtc 	/*
6498b35abe2Sjtc 	 * copy the data out of the ARCHD into the tar header based on the type
6508b35abe2Sjtc 	 * of the file. Remember many tar readers want the unused fields to be
6518b35abe2Sjtc 	 * padded with zero. We set the linkflag field (type), the linkname
6528b35abe2Sjtc 	 * (or zero if not used),the size, and set the padding (if any) to be
6538b35abe2Sjtc 	 * added after the file data (0 for all other types, as they only have
6548b35abe2Sjtc 	 * a header)
6558b35abe2Sjtc 	 */
65635bdad4eSchristos 	memset(hdblk, 0, sizeof(hdblk));
6578b35abe2Sjtc 	hd = (HD_TAR *)hdblk;
65835bdad4eSchristos 	strlcpy(hd->name, arcn->name, sizeof(hd->name));
6598b35abe2Sjtc 	arcn->pad = 0;
6608b35abe2Sjtc 
6618b35abe2Sjtc 	if (arcn->type == PAX_DIR) {
6628b35abe2Sjtc 		/*
6638b35abe2Sjtc 		 * directories are the same as files, except have a filename
6648b35abe2Sjtc 		 * that ends with a /, we add the slash here. No data follows,
6658b35abe2Sjtc 		 * dirs, so no pad.
6668b35abe2Sjtc 		 */
6678b35abe2Sjtc 		hd->linkflag = AREGTYPE;
6688b35abe2Sjtc 		hd->name[len-1] = '/';
669d653d57cSchristos 		if (u32_oct((uintmax_t)0L, hd->size, sizeof(hd->size), 1))
6708b35abe2Sjtc 			goto out;
6718b35abe2Sjtc 	} else if (arcn->type == PAX_SLK) {
6728b35abe2Sjtc 		/*
6738b35abe2Sjtc 		 * no data follows this file, so no pad
6748b35abe2Sjtc 		 */
6758b35abe2Sjtc 		hd->linkflag = SYMTYPE;
67635bdad4eSchristos 		strlcpy(hd->linkname, arcn->ln_name, sizeof(hd->linkname));
677d653d57cSchristos 		if (u32_oct((uintmax_t)0L, hd->size, sizeof(hd->size), 1))
6788b35abe2Sjtc 			goto out;
6798b35abe2Sjtc 	} else if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG)) {
6808b35abe2Sjtc 		/*
6818b35abe2Sjtc 		 * no data follows this file, so no pad
6828b35abe2Sjtc 		 */
6838b35abe2Sjtc 		hd->linkflag = LNKTYPE;
68435bdad4eSchristos 		strlcpy(hd->linkname, arcn->ln_name, sizeof(hd->linkname));
685d653d57cSchristos 		if (u32_oct((uintmax_t)0L, hd->size, sizeof(hd->size), 1))
6868b35abe2Sjtc 			goto out;
6878b35abe2Sjtc 	} else {
6888b35abe2Sjtc 		/*
6898b35abe2Sjtc 		 * data follows this file, so set the pad
6908b35abe2Sjtc 		 */
6918b35abe2Sjtc 		hd->linkflag = AREGTYPE;
692c1bd745cSlukem 		if (OFFT_OCT(arcn->sb.st_size, hd->size, sizeof(hd->size), 1)) {
693f3cd6022Schristos 			tty_warn(1,"File is too large for tar %s",
694f3cd6022Schristos 			    arcn->org_name);
695cdec4ac1Sdsl 			return 1;
6968b35abe2Sjtc 		}
6978b35abe2Sjtc 		arcn->pad = TAR_PAD(arcn->sb.st_size);
6988b35abe2Sjtc 	}
6998b35abe2Sjtc 
7008b35abe2Sjtc 	/*
7018b35abe2Sjtc 	 * copy those fields that are independent of the type
7028b35abe2Sjtc 	 */
7039158fb65Schristos 	mtime = tst.st_ino ? tst.st_mtime : arcn->sb.st_mtime;
704d653d57cSchristos 	if (u32_oct((uintmax_t)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 0) ||
705d653d57cSchristos 	    u32_oct((uintmax_t)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 0) ||
706d653d57cSchristos 	    u32_oct((uintmax_t)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 0) ||
7079158fb65Schristos 	    u32_oct(mtime, hd->mtime, sizeof(hd->mtime), 1))
7088b35abe2Sjtc 		goto out;
7098b35abe2Sjtc 
7108b35abe2Sjtc 	/*
7118b35abe2Sjtc 	 * calculate and add the checksum, then write the header. A return of
7128b35abe2Sjtc 	 * 0 tells the caller to now write the file data, 1 says no data needs
7138b35abe2Sjtc 	 * to be written
7148b35abe2Sjtc 	 */
715d653d57cSchristos 	if (u32_oct(tar_chksm(hdblk, sizeof(HD_TAR)), hd->chksum,
71635bdad4eSchristos 	    sizeof(hd->chksum), 3))
7170c612021Schristos 		goto out;			/* XXX Something's wrong here
7180c612021Schristos 						 * because a zero-byte file can
7190c612021Schristos 						 * cause this to be done and
7200c612021Schristos 						 * yet the resulting warning
7210c612021Schristos 						 * seems incorrect */
7220c612021Schristos 
7238b35abe2Sjtc 	if (wr_rdbuf(hdblk, sizeof(HD_TAR)) < 0)
724cdec4ac1Sdsl 		return -1;
7258b35abe2Sjtc 	if (wr_skip((off_t)(BLKMULT - sizeof(HD_TAR))) < 0)
726cdec4ac1Sdsl 		return -1;
7278b35abe2Sjtc 	if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG))
728cdec4ac1Sdsl 		return 0;
729cdec4ac1Sdsl 	return 1;
7308b35abe2Sjtc 
7318b35abe2Sjtc     out:
7328b35abe2Sjtc 	/*
7338b35abe2Sjtc 	 * header field is out of range
7348b35abe2Sjtc 	 */
735f3cd6022Schristos 	tty_warn(1, "Tar header field is too small for %s", arcn->org_name);
736cdec4ac1Sdsl 	return 1;
7378b35abe2Sjtc }
7388b35abe2Sjtc 
7398b35abe2Sjtc /*
7408b35abe2Sjtc  * Routines for POSIX ustar
7418b35abe2Sjtc  */
7428b35abe2Sjtc 
7438b35abe2Sjtc /*
7448b35abe2Sjtc  * ustar_strd()
7458b35abe2Sjtc  *	initialization for ustar read
7468b35abe2Sjtc  * Return:
7478b35abe2Sjtc  *	0 if ok, -1 otherwise
7488b35abe2Sjtc  */
7498b35abe2Sjtc 
7508b35abe2Sjtc int
7518b35abe2Sjtc ustar_strd(void)
7528b35abe2Sjtc {
753cdec4ac1Sdsl 	return 0;
7548b35abe2Sjtc }
7558b35abe2Sjtc 
7568b35abe2Sjtc /*
7578b35abe2Sjtc  * ustar_stwr()
7588b35abe2Sjtc  *	initialization for ustar write
7598b35abe2Sjtc  * Return:
7608b35abe2Sjtc  *	0 if ok, -1 otherwise
7618b35abe2Sjtc  */
7628b35abe2Sjtc 
7638b35abe2Sjtc int
7648b35abe2Sjtc ustar_stwr(void)
7658b35abe2Sjtc {
766cdec4ac1Sdsl 	return 0;
7678b35abe2Sjtc }
7688b35abe2Sjtc 
7698b35abe2Sjtc /*
7708b35abe2Sjtc  * ustar_id()
7718b35abe2Sjtc  *	determine if a block given to us is a valid ustar header. We have to
772ee05db82Sgutteridge  *	be on the lookout for those pesky blocks of all zeros
7738b35abe2Sjtc  * Return:
7748b35abe2Sjtc  *	0 if a ustar header, -1 otherwise
7758b35abe2Sjtc  */
7768b35abe2Sjtc 
7778b35abe2Sjtc int
7788b35abe2Sjtc ustar_id(char *blk, int size)
7798b35abe2Sjtc {
78048250187Stls 	HD_USTAR *hd;
7818b35abe2Sjtc 
782096c9d63Schristos 	if (size < BLKMULT)
783cdec4ac1Sdsl 		return -1;
7848b35abe2Sjtc 	hd = (HD_USTAR *)blk;
7858b35abe2Sjtc 
7868b35abe2Sjtc 	/*
787ee05db82Sgutteridge 	 * check for block of zeros first, a simple and fast test then check
7888b35abe2Sjtc 	 * ustar magic cookie. We should use TMAGLEN, but some USTAR archive
7898b35abe2Sjtc 	 * programs are fouled up and create archives missing the \0. Last we
7908b35abe2Sjtc 	 * check the checksum. If ok we have to assume it is a valid header.
7918b35abe2Sjtc 	 */
792096c9d63Schristos 	if (hd->name[0] == '\0')
793cdec4ac1Sdsl 		return -1;
794096c9d63Schristos 	if (strncmp(hd->magic, TMAGIC, TMAGLEN - 1) != 0)
795cdec4ac1Sdsl 		return -1;
796f70dfaafSchristos 	/* This is GNU tar */
7972665f9c6Schristos 	if (strncmp(hd->magic, "ustar  ", 8) == 0 && !is_gnutar &&
7982665f9c6Schristos 	    !seen_gnu_warning) {
7992665f9c6Schristos 		seen_gnu_warning = 1;
8000ec6ea57Schristos 		tty_warn(0,
801702d1ca5Schristos 		    "Trying to read GNU tar archive with GNU extensions and end-of-volume checks off");
8022665f9c6Schristos 	}
8032d72f725Smatt 	return check_sum(hd->chksum, sizeof(hd->chksum), blk, BLKMULT, 0);
8048b35abe2Sjtc }
8058b35abe2Sjtc 
8068b35abe2Sjtc /*
8078b35abe2Sjtc  * ustar_rd()
8088b35abe2Sjtc  *	extract the values out of block already determined to be a ustar header.
8098b35abe2Sjtc  *	store the values in the ARCHD parameter.
8108b35abe2Sjtc  * Return:
8118b35abe2Sjtc  *	0
8128b35abe2Sjtc  */
8138b35abe2Sjtc 
8148b35abe2Sjtc int
81548250187Stls ustar_rd(ARCHD *arcn, char *buf)
8168b35abe2Sjtc {
81748250187Stls 	HD_USTAR *hd;
81848250187Stls 	char *dest;
81955124093Smycroft 	int cnt;
8208b35abe2Sjtc 	dev_t devmajor;
8218b35abe2Sjtc 	dev_t devminor;
8228b35abe2Sjtc 
8238b35abe2Sjtc 	/*
8248b35abe2Sjtc 	 * we only get proper sized buffers
8258b35abe2Sjtc 	 */
8268b35abe2Sjtc 	if (ustar_id(buf, BLKMULT) < 0)
827cdec4ac1Sdsl 		return -1;
8284472ef15Schristos 
8294472ef15Schristos 	memset(arcn, 0, sizeof(*arcn));
8308b35abe2Sjtc 	arcn->org_name = arcn->name;
8318b35abe2Sjtc 	arcn->pat = NULL;
8324472ef15Schristos 	arcn->sb.st_nlink = 1;
8338b35abe2Sjtc 	hd = (HD_USTAR *)buf;
8348b35abe2Sjtc 
8358b35abe2Sjtc 	/*
8368b35abe2Sjtc 	 * see if the filename is split into two parts. if, so joint the parts.
8378b35abe2Sjtc 	 * we copy the prefix first and add a / between the prefix and name.
8388b35abe2Sjtc 	 */
8398b35abe2Sjtc 	dest = arcn->name;
8408b35abe2Sjtc 	if (*(hd->prefix) != '\0') {
84135bdad4eSchristos 		cnt = strlcpy(arcn->name, hd->prefix, sizeof(arcn->name));
84255124093Smycroft 		dest += cnt;
8438b35abe2Sjtc 		*dest++ = '/';
84435bdad4eSchristos 		cnt++;
845f70dfaafSchristos 	} else {
846ed254499Schristos 		cnt = 0;
847ed254499Schristos 	}
848ed254499Schristos 
849ed254499Schristos 	if (hd->typeflag != LONGLINKTYPE && hd->typeflag != LONGNAMETYPE) {
850ed254499Schristos 		arcn->nlen = expandname(dest, sizeof(arcn->name) - cnt,
851d980bf34Schristos 		    &gnu_name_string, &gnu_name_length, hd->name,
852d980bf34Schristos 		    sizeof(hd->name)) + cnt;
8531f747cc9Schristos 		arcn->ln_nlen = expandname(arcn->ln_name,
854d980bf34Schristos 		    sizeof(arcn->ln_name), &gnu_link_string, &gnu_link_length,
855d980bf34Schristos 		    hd->linkname, sizeof(hd->linkname));
856f70dfaafSchristos 	}
8578b35abe2Sjtc 
8588b35abe2Sjtc 	/*
8598b35abe2Sjtc 	 * follow the spec to the letter. we should only have mode bits, strip
8608b35abe2Sjtc 	 * off all other crud we may be passed.
8618b35abe2Sjtc 	 */
862d653d57cSchristos 	arcn->sb.st_mode = (mode_t)(asc_u32(hd->mode, sizeof(hd->mode), OCT) &
8638b35abe2Sjtc 	    0xfff);
864c1bd745cSlukem 	arcn->sb.st_size = (off_t)ASC_OFFT(hd->size, sizeof(hd->size), OCT);
865a4c163faSchristos 	if (arcn->sb.st_size == -1)
866a4c163faSchristos 		return -1;
867d653d57cSchristos 	arcn->sb.st_mtime = (time_t)(int32_t)asc_u32(hd->mtime, sizeof(hd->mtime), OCT);
8688b35abe2Sjtc 	arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
8698b35abe2Sjtc 
8708b35abe2Sjtc 	/*
8718b35abe2Sjtc 	 * If we can find the ascii names for gname and uname in the password
8728b35abe2Sjtc 	 * and group files we will use the uid's and gid they bind. Otherwise
8738b35abe2Sjtc 	 * we use the uid and gid values stored in the header. (This is what
8748b35abe2Sjtc 	 * the posix spec wants).
8758b35abe2Sjtc 	 */
8768b35abe2Sjtc 	hd->gname[sizeof(hd->gname) - 1] = '\0';
877d0e267dcSmycroft 	if (gid_from_group(hd->gname, &(arcn->sb.st_gid)) < 0)
878d653d57cSchristos 		arcn->sb.st_gid = (gid_t)asc_u32(hd->gid, sizeof(hd->gid), OCT);
8798b35abe2Sjtc 	hd->uname[sizeof(hd->uname) - 1] = '\0';
880d0e267dcSmycroft 	if (uid_from_user(hd->uname, &(arcn->sb.st_uid)) < 0)
881d653d57cSchristos 		arcn->sb.st_uid = (uid_t)asc_u32(hd->uid, sizeof(hd->uid), OCT);
8828b35abe2Sjtc 
8838b35abe2Sjtc 	/*
8848b35abe2Sjtc 	 * set the defaults, these may be changed depending on the file type
8858b35abe2Sjtc 	 */
8868b35abe2Sjtc 	arcn->pad = 0;
8878b35abe2Sjtc 	arcn->skip = 0;
8888b35abe2Sjtc 	arcn->sb.st_rdev = (dev_t)0;
8898b35abe2Sjtc 
8908b35abe2Sjtc 	/*
8918b35abe2Sjtc 	 * set the mode and PAX type according to the typeflag in the header
8928b35abe2Sjtc 	 */
8938b35abe2Sjtc 	switch(hd->typeflag) {
8948b35abe2Sjtc 	case FIFOTYPE:
8958b35abe2Sjtc 		arcn->type = PAX_FIF;
8968b35abe2Sjtc 		arcn->sb.st_mode |= S_IFIFO;
8978b35abe2Sjtc 		break;
8988b35abe2Sjtc 	case DIRTYPE:
8998b35abe2Sjtc 		arcn->type = PAX_DIR;
9008b35abe2Sjtc 		arcn->sb.st_mode |= S_IFDIR;
9018b35abe2Sjtc 		arcn->sb.st_nlink = 2;
9028b35abe2Sjtc 
9038b35abe2Sjtc 		/*
9048b35abe2Sjtc 		 * Some programs that create ustar archives append a '/'
9058b35abe2Sjtc 		 * to the pathname for directories. This clearly violates
9068b35abe2Sjtc 		 * ustar specs, but we will silently strip it off anyway.
9078b35abe2Sjtc 		 */
9088b35abe2Sjtc 		if (arcn->name[arcn->nlen - 1] == '/')
9098b35abe2Sjtc 			arcn->name[--arcn->nlen] = '\0';
9108b35abe2Sjtc 		break;
9118b35abe2Sjtc 	case BLKTYPE:
9128b35abe2Sjtc 	case CHRTYPE:
9138b35abe2Sjtc 		/*
9148b35abe2Sjtc 		 * this type requires the rdev field to be set.
9158b35abe2Sjtc 		 */
9168b35abe2Sjtc 		if (hd->typeflag == BLKTYPE) {
9178b35abe2Sjtc 			arcn->type = PAX_BLK;
9188b35abe2Sjtc 			arcn->sb.st_mode |= S_IFBLK;
9198b35abe2Sjtc 		} else {
9208b35abe2Sjtc 			arcn->type = PAX_CHR;
9218b35abe2Sjtc 			arcn->sb.st_mode |= S_IFCHR;
9228b35abe2Sjtc 		}
923d653d57cSchristos 		devmajor = (dev_t)asc_u32(hd->devmajor,sizeof(hd->devmajor),OCT);
924d653d57cSchristos 		devminor = (dev_t)asc_u32(hd->devminor,sizeof(hd->devminor),OCT);
9258b35abe2Sjtc 		arcn->sb.st_rdev = TODEV(devmajor, devminor);
9268b35abe2Sjtc 		break;
9278b35abe2Sjtc 	case SYMTYPE:
9288b35abe2Sjtc 	case LNKTYPE:
9298b35abe2Sjtc 		if (hd->typeflag == SYMTYPE) {
9308b35abe2Sjtc 			arcn->type = PAX_SLK;
9318b35abe2Sjtc 			arcn->sb.st_mode |= S_IFLNK;
9328b35abe2Sjtc 		} else {
9338b35abe2Sjtc 			arcn->type = PAX_HLK;
9348b35abe2Sjtc 			/*
9358b35abe2Sjtc 			 * so printing looks better
9368b35abe2Sjtc 			 */
9378b35abe2Sjtc 			arcn->sb.st_mode |= S_IFREG;
9388b35abe2Sjtc 			arcn->sb.st_nlink = 2;
9398b35abe2Sjtc 		}
9408b35abe2Sjtc 		break;
941f70dfaafSchristos 	case LONGLINKTYPE:
942f70dfaafSchristos 	case LONGNAMETYPE:
943f70dfaafSchristos 		if (is_gnutar) {
944f70dfaafSchristos 			/*
945f70dfaafSchristos 			 * GNU long link/file; we tag these here and let the
946f70dfaafSchristos 			 * pax internals deal with it -- too ugly otherwise.
947f70dfaafSchristos 			 */
948f70dfaafSchristos 			if (hd->typeflag != LONGLINKTYPE)
949f70dfaafSchristos 				arcn->type = PAX_GLF;
95044eb0ccaSchristos 			else
95144eb0ccaSchristos 				arcn->type = PAX_GLL;
952f70dfaafSchristos 			arcn->pad = TAR_PAD(arcn->sb.st_size);
953f70dfaafSchristos 			arcn->skip = arcn->sb.st_size;
954f70dfaafSchristos 		} else {
955f70dfaafSchristos 			tty_warn(1, "GNU Long %s found in posix ustar archive.",
956f70dfaafSchristos 			    hd->typeflag == LONGLINKTYPE ? "Link" : "File");
957f70dfaafSchristos 		}
958f70dfaafSchristos 		break;
95954f7a5dbSchristos 	case FILEXTYPE:
96054f7a5dbSchristos 	case GLOBXTYPE:
96154f7a5dbSchristos 		    tty_warn(0, "%s extended headers posix ustar archive."
96254f7a5dbSchristos 		    " Extracting as plain files. Following files might be"
96354f7a5dbSchristos 		    " in the wrong directory or have wrong attributes.",
96454f7a5dbSchristos 			hd->typeflag == FILEXTYPE ? "File" : "Global");
96554f7a5dbSchristos 		    /*FALLTHROUGH*/
9668b35abe2Sjtc 	case CONTTYPE:
9678b35abe2Sjtc 	case AREGTYPE:
9688b35abe2Sjtc 	case REGTYPE:
9698b35abe2Sjtc 	default:
9708b35abe2Sjtc 		/*
9718b35abe2Sjtc 		 * these types have file data that follows. Set the skip and
9728b35abe2Sjtc 		 * pad fields.
9738b35abe2Sjtc 		 */
9748b35abe2Sjtc 		arcn->type = PAX_REG;
9758b35abe2Sjtc 		arcn->pad = TAR_PAD(arcn->sb.st_size);
9768b35abe2Sjtc 		arcn->skip = arcn->sb.st_size;
9778b35abe2Sjtc 		arcn->sb.st_mode |= S_IFREG;
9788b35abe2Sjtc 		break;
9798b35abe2Sjtc 	}
980cdec4ac1Sdsl 	return 0;
9818b35abe2Sjtc }
9828b35abe2Sjtc 
983ed254499Schristos static int
984d980bf34Schristos expandname(char *buf, size_t len, char **gnu_name, size_t *gnu_length,
985d980bf34Schristos     const char *name, size_t nlen)
9864472ef15Schristos {
987ed254499Schristos 	if (*gnu_name) {
988ed254499Schristos 		len = strlcpy(buf, *gnu_name, len);
989ed254499Schristos 		free(*gnu_name);
990ed254499Schristos 		*gnu_name = NULL;
991d980bf34Schristos 		*gnu_length = 0;
9924472ef15Schristos 	} else {
993c59371a0Schristos 		if (len > ++nlen)
994c59371a0Schristos 			len = nlen;
995ed254499Schristos 		len = strlcpy(buf, name, len);
9964472ef15Schristos 	}
997ed254499Schristos 	return len;
9984472ef15Schristos }
999f70dfaafSchristos 
1000f70dfaafSchristos static void
1001393b592bSchristos longlink(ARCHD *arcn, int type)
1002f70dfaafSchristos {
1003f70dfaafSchristos 	ARCHD larc;
1004f70dfaafSchristos 
10050deda961Schristos 	(void)memset(&larc, 0, sizeof(larc));
1006f70dfaafSchristos 
1007393b592bSchristos 	larc.type = type;
10080deda961Schristos 	larc.nlen = strlcpy(larc.name, LONG_LINK, sizeof(larc.name));
10090deda961Schristos 
10100deda961Schristos 	switch (type) {
10110deda961Schristos 	case PAX_GLL:
1012f70dfaafSchristos 		gnu_hack_string = arcn->ln_name;
1013f70dfaafSchristos 		gnu_hack_len = arcn->ln_nlen + 1;
1014f70dfaafSchristos 		break;
10150deda961Schristos 	case PAX_GLF:
1016f70dfaafSchristos 		gnu_hack_string = arcn->name;
1017f70dfaafSchristos 		gnu_hack_len = arcn->nlen + 1;
10180deda961Schristos 		break;
10190deda961Schristos 	default:
10207da746abSchristos 		errx(1, "Invalid type in GNU longlink %d", type);
1021f70dfaafSchristos 	}
10220deda961Schristos 
1023f70dfaafSchristos 	/*
1024f70dfaafSchristos 	 * We need a longlink now.
1025f70dfaafSchristos 	 */
1026f70dfaafSchristos 	ustar_wr(&larc);
1027f70dfaafSchristos }
1028f70dfaafSchristos 
10298b35abe2Sjtc /*
10308b35abe2Sjtc  * ustar_wr()
10318b35abe2Sjtc  *	write a ustar header for the file specified in the ARCHD to the archive
10328b35abe2Sjtc  *	Have to check for file types that cannot be stored and file names that
1033d653d57cSchristos  *	are too long. Be careful of the term (last arg) to u32_oct, we only use
10348b35abe2Sjtc  *	'\0' for the termination character (this is different than picky tar)
10358b35abe2Sjtc  *	ASSUMED: space after header in header block is zero filled
10368b35abe2Sjtc  * Return:
10378b35abe2Sjtc  *	0 if file has data to be written after the header, 1 if file has NO
10388b35abe2Sjtc  *	data to write after the header, -1 if archive write failed
10398b35abe2Sjtc  */
10408b35abe2Sjtc 
10417404af49Sdsl static int
10427404af49Sdsl size_err(const char *what, ARCHD *arcn)
10437404af49Sdsl {
10447404af49Sdsl 	/*
10457404af49Sdsl 	 * header field is out of range
10467404af49Sdsl 	 */
10477404af49Sdsl 	tty_warn(1, "Ustar %s header field is too small for %s",
10487404af49Sdsl 		what, arcn->org_name);
10497404af49Sdsl 	return 1;
10507404af49Sdsl }
10517404af49Sdsl 
10528b35abe2Sjtc int
105348250187Stls ustar_wr(ARCHD *arcn)
10548b35abe2Sjtc {
105548250187Stls 	HD_USTAR *hd;
105648250187Stls 	char *pt;
10579158fb65Schristos 	uintmax_t mtime;
10588b35abe2Sjtc 	char hdblk[sizeof(HD_USTAR)];
1059d0e267dcSmycroft 	const char *user, *group;
10608b35abe2Sjtc 
106144eb0ccaSchristos 	switch (arcn->type) {
106244eb0ccaSchristos 	case PAX_SCK:
10638b35abe2Sjtc 		/*
10648b35abe2Sjtc 		 * check for those file system types ustar cannot store
10658b35abe2Sjtc 		 */
1066051306e2Schristos 		if (!is_gnutar)
1067051306e2Schristos 			tty_warn(1, "Ustar cannot archive a socket %s",
1068051306e2Schristos 			    arcn->org_name);
1069cdec4ac1Sdsl 		return 1;
10708b35abe2Sjtc 
107144eb0ccaSchristos 	case PAX_SLK:
107244eb0ccaSchristos 	case PAX_HLK:
107344eb0ccaSchristos 	case PAX_HRG:
10748b35abe2Sjtc 		/*
10758b35abe2Sjtc 		 * check the length of the linkname
10768b35abe2Sjtc 		 */
1077990d25a9Slukem 		if (arcn->ln_nlen >= (int)sizeof(hd->linkname)) {
1078f70dfaafSchristos 			if (is_gnutar) {
1079393b592bSchristos 				longlink(arcn, PAX_GLL);
1080f70dfaafSchristos 			} else {
1081f70dfaafSchristos 				tty_warn(1, "Link name too long for ustar %s",
1082f70dfaafSchristos 				    arcn->ln_name);
1083cdec4ac1Sdsl 				return 1;
10848b35abe2Sjtc 			}
1085f70dfaafSchristos 		}
108644eb0ccaSchristos 		break;
108744eb0ccaSchristos 	default:
108844eb0ccaSchristos 		break;
108944eb0ccaSchristos 	}
10908b35abe2Sjtc 
10918b35abe2Sjtc 	/*
10928b35abe2Sjtc 	 * split the path name into prefix and name fields (if needed). if
10938b35abe2Sjtc 	 * pt != arcn->name, the name has to be split
10948b35abe2Sjtc 	 */
10958b35abe2Sjtc 	if ((pt = name_split(arcn->name, arcn->nlen)) == NULL) {
1096f70dfaafSchristos 		if (is_gnutar) {
1097393b592bSchristos 			longlink(arcn, PAX_GLF);
1098f70dfaafSchristos 			pt = arcn->name;
1099f70dfaafSchristos 		} else {
1100f70dfaafSchristos 			tty_warn(1, "File name too long for ustar %s",
1101f70dfaafSchristos 			    arcn->name);
1102cdec4ac1Sdsl 			return 1;
11038b35abe2Sjtc 		}
1104f70dfaafSchristos 	}
110535bdad4eSchristos 
110635bdad4eSchristos 	/*
110735bdad4eSchristos 	 * zero out the header so we don't have to worry about zero fill below
110835bdad4eSchristos 	 */
110935bdad4eSchristos 	memset(hdblk, 0, sizeof(hdblk));
11108b35abe2Sjtc 	hd = (HD_USTAR *)hdblk;
11118b35abe2Sjtc 	arcn->pad = 0L;
11128b35abe2Sjtc 
11138b35abe2Sjtc 	/*
11148b35abe2Sjtc 	 * split the name, or zero out the prefix
11158b35abe2Sjtc 	 */
11168b35abe2Sjtc 	if (pt != arcn->name) {
11178b35abe2Sjtc 		/*
11188b35abe2Sjtc 		 * name was split, pt points at the / where the split is to
11198b35abe2Sjtc 		 * occur, we remove the / and copy the first part to the prefix
11208b35abe2Sjtc 		 */
11218b35abe2Sjtc 		*pt = '\0';
112235bdad4eSchristos 		strlcpy(hd->prefix, arcn->name, sizeof(hd->prefix));
11238b35abe2Sjtc 		*pt++ = '/';
112435bdad4eSchristos 	}
11258b35abe2Sjtc 
11268b35abe2Sjtc 	/*
11278b35abe2Sjtc 	 * copy the name part. this may be the whole path or the part after
11288b35abe2Sjtc 	 * the prefix
11298b35abe2Sjtc 	 */
113035bdad4eSchristos 	strlcpy(hd->name, pt, sizeof(hd->name));
11318b35abe2Sjtc 
11328b35abe2Sjtc 	/*
11338b35abe2Sjtc 	 * set the fields in the header that are type dependent
11348b35abe2Sjtc 	 */
11358b35abe2Sjtc 	switch(arcn->type) {
11368b35abe2Sjtc 	case PAX_DIR:
11378b35abe2Sjtc 		hd->typeflag = DIRTYPE;
1138d653d57cSchristos 		if (u32_oct((uintmax_t)0L, hd->size, sizeof(hd->size), 3))
11397404af49Sdsl 			return size_err("DIRTYPE", arcn);
11408b35abe2Sjtc 		break;
11418b35abe2Sjtc 	case PAX_CHR:
11428b35abe2Sjtc 	case PAX_BLK:
11438b35abe2Sjtc 		if (arcn->type == PAX_CHR)
11448b35abe2Sjtc 			hd->typeflag = CHRTYPE;
11458b35abe2Sjtc 		else
11468b35abe2Sjtc 			hd->typeflag = BLKTYPE;
1147d653d57cSchristos 		if (u32_oct((uintmax_t)MAJOR(arcn->sb.st_rdev), hd->devmajor,
11488b35abe2Sjtc 		   sizeof(hd->devmajor), 3) ||
1149d653d57cSchristos 		   u32_oct((uintmax_t)MINOR(arcn->sb.st_rdev), hd->devminor,
11508b35abe2Sjtc 		   sizeof(hd->devminor), 3) ||
1151d653d57cSchristos 		   u32_oct((uintmax_t)0L, hd->size, sizeof(hd->size), 3))
11527404af49Sdsl 			return size_err("DEVTYPE", arcn);
11538b35abe2Sjtc 		break;
11548b35abe2Sjtc 	case PAX_FIF:
11558b35abe2Sjtc 		hd->typeflag = FIFOTYPE;
1156d653d57cSchristos 		if (u32_oct((uintmax_t)0L, hd->size, sizeof(hd->size), 3))
11577404af49Sdsl 			return size_err("FIFOTYPE", arcn);
11588b35abe2Sjtc 		break;
1159f70dfaafSchristos 	case PAX_GLL:
11608b35abe2Sjtc 	case PAX_SLK:
11618b35abe2Sjtc 	case PAX_HLK:
11628b35abe2Sjtc 	case PAX_HRG:
11638b35abe2Sjtc 		if (arcn->type == PAX_SLK)
11648b35abe2Sjtc 			hd->typeflag = SYMTYPE;
1165f70dfaafSchristos 		else if (arcn->type == PAX_GLL)
1166f70dfaafSchristos 			hd->typeflag = LONGLINKTYPE;
11678b35abe2Sjtc 		else
11688b35abe2Sjtc 			hd->typeflag = LNKTYPE;
116935bdad4eSchristos 		strlcpy(hd->linkname, arcn->ln_name, sizeof(hd->linkname));
1170d653d57cSchristos 		if (u32_oct((uintmax_t)gnu_hack_len, hd->size,
1171f70dfaafSchristos 		    sizeof(hd->size), 3))
11727404af49Sdsl 			return size_err("LINKTYPE", arcn);
11738b35abe2Sjtc 		break;
1174f70dfaafSchristos 	case PAX_GLF:
11758b35abe2Sjtc 	case PAX_REG:
11768b35abe2Sjtc 	case PAX_CTG:
11778b35abe2Sjtc 	default:
11788b35abe2Sjtc 		/*
11798b35abe2Sjtc 		 * file data with this type, set the padding
11808b35abe2Sjtc 		 */
1181f70dfaafSchristos 		if (arcn->type == PAX_GLF) {
1182f70dfaafSchristos 			hd->typeflag = LONGNAMETYPE;
1183f70dfaafSchristos 			arcn->pad = TAR_PAD(gnu_hack_len);
1184d653d57cSchristos 			if (OFFT_OCT((uint32_t)gnu_hack_len, hd->size,
1185f70dfaafSchristos 			    sizeof(hd->size), 3)) {
1186f70dfaafSchristos 				tty_warn(1,"File is too long for ustar %s",
1187f70dfaafSchristos 				    arcn->org_name);
1188cdec4ac1Sdsl 				return 1;
1189f70dfaafSchristos 			}
1190f70dfaafSchristos 		} else {
11918b35abe2Sjtc 			if (arcn->type == PAX_CTG)
11928b35abe2Sjtc 				hd->typeflag = CONTTYPE;
11938b35abe2Sjtc 			else
11948b35abe2Sjtc 				hd->typeflag = REGTYPE;
11958b35abe2Sjtc 			arcn->pad = TAR_PAD(arcn->sb.st_size);
1196f70dfaafSchristos 			if (OFFT_OCT(arcn->sb.st_size, hd->size,
1197f70dfaafSchristos 			    sizeof(hd->size), 3)) {
1198f3cd6022Schristos 				tty_warn(1,"File is too long for ustar %s",
1199f3cd6022Schristos 				    arcn->org_name);
1200cdec4ac1Sdsl 				return 1;
12018b35abe2Sjtc 			}
1202f70dfaafSchristos 		}
12038b35abe2Sjtc 		break;
12048b35abe2Sjtc 	}
12058b35abe2Sjtc 
120635bdad4eSchristos 	strncpy(hd->magic, TMAGIC, TMAGLEN);
1207f70dfaafSchristos 	if (is_gnutar)
1208ee17e957Schristos 		hd->magic[TMAGLEN - 1] = hd->version[0] = ' ';
1209f70dfaafSchristos 	else
121035bdad4eSchristos 		strncpy(hd->version, TVERSION, TVERSLEN);
12118b35abe2Sjtc 
12128b35abe2Sjtc 	/*
12138b35abe2Sjtc 	 * set the remaining fields. Some versions want all 16 bits of mode
12148b35abe2Sjtc 	 * we better humor them (they really do not meet spec though)....
12158b35abe2Sjtc 	 */
1216d653d57cSchristos 	if (u32_oct((uintmax_t)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 3))
12177404af49Sdsl 		return size_err("MODE", arcn);
1218d653d57cSchristos 	if (u32_oct((uintmax_t)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 3))
12197404af49Sdsl 		return size_err("UID", arcn);
1220d653d57cSchristos 	if (u32_oct((uintmax_t)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 3))
12217404af49Sdsl 		return size_err("GID", arcn);
12229158fb65Schristos 	mtime = tst.st_ino ? tst.st_mtime : arcn->sb.st_mtime;
12239158fb65Schristos 	if (u32_oct(mtime, hd->mtime, sizeof(hd->mtime), 3))
12247404af49Sdsl 		return size_err("MTIME", arcn);
1225a47ed375Sgrant 	user = user_from_uid(arcn->sb.st_uid, 1);
1226a47ed375Sgrant 	group = group_from_gid(arcn->sb.st_gid, 1);
122735bdad4eSchristos 	strncpy(hd->uname, user ? user : "", sizeof(hd->uname));
122835bdad4eSchristos 	strncpy(hd->gname, group ? group : "", sizeof(hd->gname));
12298b35abe2Sjtc 
12308b35abe2Sjtc 	/*
12318b35abe2Sjtc 	 * calculate and store the checksum write the header to the archive
12328b35abe2Sjtc 	 * return 0 tells the caller to now write the file data, 1 says no data
12338b35abe2Sjtc 	 * needs to be written
12348b35abe2Sjtc 	 */
1235d653d57cSchristos 	if (u32_oct(tar_chksm(hdblk, sizeof(HD_USTAR)), hd->chksum,
12368b35abe2Sjtc 	   sizeof(hd->chksum), 3))
12377404af49Sdsl 		return size_err("CHKSUM", arcn);
12388b35abe2Sjtc 	if (wr_rdbuf(hdblk, sizeof(HD_USTAR)) < 0)
1239cdec4ac1Sdsl 		return -1;
12408b35abe2Sjtc 	if (wr_skip((off_t)(BLKMULT - sizeof(HD_USTAR))) < 0)
1241cdec4ac1Sdsl 		return -1;
1242f70dfaafSchristos 	if (gnu_hack_string) {
1243f70dfaafSchristos 		int res = wr_rdbuf(gnu_hack_string, gnu_hack_len);
1244f70dfaafSchristos 		int pad = gnu_hack_len;
1245f70dfaafSchristos 		gnu_hack_string = NULL;
1246f70dfaafSchristos 		gnu_hack_len = 0;
1247f70dfaafSchristos 		if (res < 0)
1248cdec4ac1Sdsl 			return -1;
1249f70dfaafSchristos 		if (wr_skip((off_t)(BLKMULT - (pad % BLKMULT))) < 0)
1250cdec4ac1Sdsl 			return -1;
1251f70dfaafSchristos 	}
12528b35abe2Sjtc 	if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG))
1253cdec4ac1Sdsl 		return 0;
1254cdec4ac1Sdsl 	return 1;
12558b35abe2Sjtc }
12568b35abe2Sjtc 
12578b35abe2Sjtc /*
12588b35abe2Sjtc  * name_split()
12598b35abe2Sjtc  *	see if the name has to be split for storage in a ustar header. We try
12608b35abe2Sjtc  *	to fit the entire name in the name field without splitting if we can.
12618b35abe2Sjtc  *	The split point is always at a /
12628b35abe2Sjtc  * Return
12638b35abe2Sjtc  *	character pointer to split point (always the / that is to be removed
12648b35abe2Sjtc  *	if the split is not needed, the points is set to the start of the file
12658b35abe2Sjtc  *	name (it would violate the spec to split there). A NULL is returned if
12668b35abe2Sjtc  *	the file name is too long
12678b35abe2Sjtc  */
12688b35abe2Sjtc 
12698b35abe2Sjtc static char *
127048250187Stls name_split(char *name, int len)
12718b35abe2Sjtc {
127248250187Stls 	char *start;
12738b35abe2Sjtc 
12748b35abe2Sjtc 	/*
12758b35abe2Sjtc 	 * check to see if the file name is small enough to fit in the name
12768b35abe2Sjtc 	 * field. if so just return a pointer to the name.
12778b35abe2Sjtc 	 */
127835bdad4eSchristos 	if (len < TNMSZ)
1279cdec4ac1Sdsl 		return name;
12806885f6baSchristos 	/*
12816885f6baSchristos 	 * GNU tar does not honor the prefix+name mode if the magic
12826885f6baSchristos 	 * is not "ustar\0". So in GNU tar compatibility mode, we don't
12836885f6baSchristos 	 * split the filename into prefix+name because we are setting
12846885f6baSchristos 	 * the magic to "ustar " as GNU tar does. This of course will
12856885f6baSchristos 	 * end up creating a LongLink record in cases where it does not
12866885f6baSchristos 	 * really need do, but we are behaving like GNU tar after all.
12876885f6baSchristos 	 */
12886885f6baSchristos 	if (is_gnutar || len > (TPFSZ + TNMSZ))
1289cdec4ac1Sdsl 		return NULL;
12908b35abe2Sjtc 
12918b35abe2Sjtc 	/*
12928b35abe2Sjtc 	 * we start looking at the biggest sized piece that fits in the name
1293f8adf56dSitohy 	 * field. We walk forward looking for a slash to split at. The idea is
12948b35abe2Sjtc 	 * to find the biggest piece to fit in the name field (or the smallest
12958b35abe2Sjtc 	 * prefix we can find) (the -1 is correct the biggest piece would
12968b35abe2Sjtc 	 * include the slash between the two parts that gets thrown away)
12978b35abe2Sjtc 	 */
129835bdad4eSchristos 	start = name + len - TNMSZ;
12998b35abe2Sjtc 	while ((*start != '\0') && (*start != '/'))
13008b35abe2Sjtc 		++start;
13018b35abe2Sjtc 
13028b35abe2Sjtc 	/*
13038b35abe2Sjtc 	 * if we hit the end of the string, this name cannot be split, so we
13048b35abe2Sjtc 	 * cannot store this file.
13058b35abe2Sjtc 	 */
13068b35abe2Sjtc 	if (*start == '\0')
1307cdec4ac1Sdsl 		return NULL;
13088b35abe2Sjtc 	len = start - name;
13098b35abe2Sjtc 
13108b35abe2Sjtc 	/*
13118b35abe2Sjtc 	 * NOTE: /str where the length of str == TNMSZ cannot be stored under
13128b35abe2Sjtc 	 * the p1003.1-1990 spec for ustar. We could force a prefix of / and
13138b35abe2Sjtc 	 * the file would then expand on extract to //str. The len == 0 below
13148b35abe2Sjtc 	 * makes this special case follow the spec to the letter.
13158b35abe2Sjtc 	 */
131635bdad4eSchristos 	if ((len >= TPFSZ) || (len == 0))
1317cdec4ac1Sdsl 		return NULL;
13188b35abe2Sjtc 
13198b35abe2Sjtc 	/*
13208b35abe2Sjtc 	 * ok have a split point, return it to the caller
13218b35abe2Sjtc 	 */
1322cdec4ac1Sdsl 	return start;
13238b35abe2Sjtc }
1324ce6b1876Smrg 
13250ade019dSmrg /*
13260ade019dSmrg  * convert a glob into a RE, and add it to the list.  we convert to
13270ade019dSmrg  * four different RE's (because we're using BRE's and can't use |
13280ade019dSmrg  * alternation :-() with this padding:
13290ade019dSmrg  *	.*\/ and $
13300ade019dSmrg  *	.*\/ and \/.*
13310ade019dSmrg  *	^ and $
13320ade019dSmrg  *	^ and \/.*
13330ade019dSmrg  */
1334c3510d14Smrg static int
1335c3510d14Smrg tar_gnutar_exclude_one(const char *line, size_t len)
1336c3510d14Smrg {
1337fa97f055Smrg 	/* 2 * buffer len + nul */
1338fa97f055Smrg 	char sbuf[MAXPATHLEN * 2 + 1];
1339fa97f055Smrg 	/* + / + // + .*""/\/ + \/.* */
1340fa97f055Smrg 	char rabuf[MAXPATHLEN * 2 + 1 + 1 + 2 + 4 + 4];
1341990d25a9Slukem 	size_t i;
1342990d25a9Slukem 	int j = 0;
1343c3510d14Smrg 
1344c3510d14Smrg 	if (line[len - 1] == '\n')
1345c3510d14Smrg 		len--;
1346fa97f055Smrg 	for (i = 0; i < len; i++) {
1347ce6b1876Smrg 		/*
1348c3510d14Smrg 		 * convert glob to regexp, escaping everything
1349ce6b1876Smrg 		 */
1350c3510d14Smrg 		if (line[i] == '*')
1351c3510d14Smrg 			sbuf[j++] = '.';
1352c3510d14Smrg 		else if (line[i] == '?') {
1353c3510d14Smrg 			sbuf[j++] = '.';
1354c3510d14Smrg 			continue;
135571f73d16Schristos 		} else if (!isalnum((unsigned char)line[i]) &&
135671f73d16Schristos 		    !isblank((unsigned char)line[i]))
1357c3510d14Smrg 			sbuf[j++] = '\\';
1358c3510d14Smrg 		sbuf[j++] = line[i];
1359c3510d14Smrg 	}
136071f73d16Schristos 	sbuf[j] = '\0';
1361fa97f055Smrg 	/* don't need the .*\/ ones if we start with /, i guess */
1362fa97f055Smrg 	if (line[0] != '/') {
13631f747cc9Schristos 		(void)snprintf(rabuf, sizeof rabuf, "/.*\\/%s$//", sbuf);
1364fa97f055Smrg 		if (rep_add(rabuf) < 0)
1365c3510d14Smrg 			return (-1);
13661f747cc9Schristos 		(void)snprintf(rabuf, sizeof rabuf, "/.*\\/%s\\/.*//", sbuf);
1367fa97f055Smrg 		if (rep_add(rabuf) < 0)
13680ade019dSmrg 			return (-1);
1369fa97f055Smrg 	}
13700ade019dSmrg 
13711f747cc9Schristos 	(void)snprintf(rabuf, sizeof rabuf, "/^%s$//", sbuf);
1372fa97f055Smrg 	if (rep_add(rabuf) < 0)
13730ade019dSmrg 		return (-1);
13741f747cc9Schristos 	(void)snprintf(rabuf, sizeof rabuf, "/^%s\\/.*//", sbuf);
1375fa97f055Smrg 	if (rep_add(rabuf) < 0)
13760ade019dSmrg 		return (-1);
1377c3510d14Smrg 
1378c3510d14Smrg 	return (0);
1379c3510d14Smrg }
1380c3510d14Smrg 
1381c3510d14Smrg /*
1382ee05db82Sgutteridge  * deal with GNU tar -X/--exclude-from & --exclude switches.  basically,
1383c3510d14Smrg  * we go through each line of the file, building a string from the "glob"
1384c3510d14Smrg  * lines in the file into RE lines, of the form `/^RE$//', which we pass
1385c3510d14Smrg  * to rep_add(), which will add a empty replacement (exclusion), for the
1386c3510d14Smrg  * named files.
1387c3510d14Smrg  */
1388c3510d14Smrg int
1389da4f7877Smatt tar_gnutar_minus_minus_exclude(const char *path)
1390c3510d14Smrg {
1391c3510d14Smrg 	size_t	len = strlen(path);
1392c3510d14Smrg 
1393c3510d14Smrg 	if (len > MAXPATHLEN)
1394c3510d14Smrg 		tty_warn(0, "pathname too long: %s", path);
1395c3510d14Smrg 
1396c3510d14Smrg 	return (tar_gnutar_exclude_one(path, len));
1397c3510d14Smrg }
1398c3510d14Smrg 
1399ce6b1876Smrg int
1400da4f7877Smatt tar_gnutar_X_compat(const char *path)
1401ce6b1876Smrg {
1402c3510d14Smrg 	char *line;
1403ce6b1876Smrg 	FILE *fp;
1404c3510d14Smrg 	int lineno = 0;
140575e40b37Smycroft 	size_t len;
1406ce6b1876Smrg 
1407ce978720Schristos 	if (path[0] == '-' && path[1] == '\0')
1408ce978720Schristos 		fp = stdin;
1409ce978720Schristos 	else {
1410ce6b1876Smrg 		fp = fopen(path, "r");
1411ce6b1876Smrg 		if (fp == NULL) {
1412ce6b1876Smrg 			tty_warn(1, "cannot open %s: %s", path,
1413ce6b1876Smrg 			    strerror(errno));
1414cdec4ac1Sdsl 			return -1;
1415ce6b1876Smrg 		}
1416ce978720Schristos 	}
1417ce6b1876Smrg 
1418ce6b1876Smrg 	while ((line = fgetln(fp, &len))) {
1419ce6b1876Smrg 		lineno++;
1420ce6b1876Smrg 		if (len > MAXPATHLEN) {
1421ce6b1876Smrg 			tty_warn(0, "pathname too long, line %d of %s",
1422ce6b1876Smrg 			    lineno, path);
1423ce6b1876Smrg 		}
1424c3510d14Smrg 		if (tar_gnutar_exclude_one(line, len))
1425ce978720Schristos 			return -1;
1426ce6b1876Smrg 	}
1427ce978720Schristos 	if (fp != stdin)
1428ce978720Schristos 		fclose(fp);
1429ce978720Schristos 	return 0;
1430ce6b1876Smrg }
1431