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