14b88c807SRodney W. Grimes /*- 24b88c807SRodney W. Grimes * Copyright (c) 1992 Keith Muller. 34b88c807SRodney W. Grimes * Copyright (c) 1992, 1993 44b88c807SRodney W. Grimes * The Regents of the University of California. All rights reserved. 54b88c807SRodney W. Grimes * 64b88c807SRodney W. Grimes * This code is derived from software contributed to Berkeley by 74b88c807SRodney W. Grimes * Keith Muller of the University of California, San Diego. 84b88c807SRodney W. Grimes * 94b88c807SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 104b88c807SRodney W. Grimes * modification, are permitted provided that the following conditions 114b88c807SRodney W. Grimes * are met: 124b88c807SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 134b88c807SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 144b88c807SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 154b88c807SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 164b88c807SRodney W. Grimes * documentation and/or other materials provided with the distribution. 174b88c807SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 184b88c807SRodney W. Grimes * may be used to endorse or promote products derived from this software 194b88c807SRodney W. Grimes * without specific prior written permission. 204b88c807SRodney W. Grimes * 214b88c807SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 224b88c807SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 234b88c807SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 244b88c807SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 254b88c807SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 264b88c807SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 274b88c807SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 284b88c807SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 294b88c807SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 304b88c807SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 314b88c807SRodney W. Grimes * SUCH DAMAGE. 324b88c807SRodney W. Grimes */ 334b88c807SRodney W. Grimes 344b88c807SRodney W. Grimes #ifndef lint 35c9a8d1f4SPhilippe Charnier #if 0 36c9a8d1f4SPhilippe Charnier static char sccsid[] = "@(#)tar.c 8.2 (Berkeley) 4/18/94"; 37c9a8d1f4SPhilippe Charnier #endif 384b88c807SRodney W. Grimes #endif /* not lint */ 392749b141SDavid E. O'Brien #include <sys/cdefs.h> 402749b141SDavid E. O'Brien __FBSDID("$FreeBSD$"); 414b88c807SRodney W. Grimes 424b88c807SRodney W. Grimes #include <sys/types.h> 434b88c807SRodney W. Grimes #include <sys/time.h> 444b88c807SRodney W. Grimes #include <sys/stat.h> 454b88c807SRodney W. Grimes #include <string.h> 464b88c807SRodney W. Grimes #include <stdio.h> 474b88c807SRodney W. Grimes #include <unistd.h> 484b88c807SRodney W. Grimes #include <stdlib.h> 494b88c807SRodney W. Grimes #include "pax.h" 504b88c807SRodney W. Grimes #include "extern.h" 514b88c807SRodney W. Grimes #include "tar.h" 524b88c807SRodney W. Grimes 534b88c807SRodney W. Grimes /* 544b88c807SRodney W. Grimes * Routines for reading, writing and header identify of various versions of tar 554b88c807SRodney W. Grimes */ 564b88c807SRodney W. Grimes 57f789b261SWarner Losh static u_long tar_chksm(char *, int); 58f789b261SWarner Losh static char *name_split(char *, int); 59f789b261SWarner Losh static int ul_oct(u_long, char *, int, int); 604b88c807SRodney W. Grimes #ifndef NET2_STAT 61f789b261SWarner Losh static int uqd_oct(u_quad_t, char *, int, int); 624b88c807SRodney W. Grimes #endif 634b88c807SRodney W. Grimes 644b88c807SRodney W. Grimes /* 654b88c807SRodney W. Grimes * Routines common to all versions of tar 664b88c807SRodney W. Grimes */ 674b88c807SRodney W. Grimes 684b88c807SRodney W. Grimes static int tar_nodir; /* do not write dirs under old tar */ 694b88c807SRodney W. Grimes 704b88c807SRodney W. Grimes /* 714b88c807SRodney W. Grimes * tar_endwr() 724b88c807SRodney W. Grimes * add the tar trailer of two null blocks 734b88c807SRodney W. Grimes * Return: 744b88c807SRodney W. Grimes * 0 if ok, -1 otherwise (what wr_skip returns) 754b88c807SRodney W. Grimes */ 764b88c807SRodney W. Grimes 774b88c807SRodney W. Grimes int 784b88c807SRodney W. Grimes tar_endwr(void) 794b88c807SRodney W. Grimes { 804b88c807SRodney W. Grimes return(wr_skip((off_t)(NULLCNT*BLKMULT))); 814b88c807SRodney W. Grimes } 824b88c807SRodney W. Grimes 834b88c807SRodney W. Grimes /* 844b88c807SRodney W. Grimes * tar_endrd() 854b88c807SRodney W. Grimes * no cleanup needed here, just return size of trailer (for append) 864b88c807SRodney W. Grimes * Return: 874b88c807SRodney W. Grimes * size of trailer (2 * BLKMULT) 884b88c807SRodney W. Grimes */ 894b88c807SRodney W. Grimes 904b88c807SRodney W. Grimes off_t 914b88c807SRodney W. Grimes tar_endrd(void) 924b88c807SRodney W. Grimes { 934b88c807SRodney W. Grimes return((off_t)(NULLCNT*BLKMULT)); 944b88c807SRodney W. Grimes } 954b88c807SRodney W. Grimes 964b88c807SRodney W. Grimes /* 974b88c807SRodney W. Grimes * tar_trail() 984b88c807SRodney W. Grimes * Called to determine if a header block is a valid trailer. We are passed 994b88c807SRodney W. Grimes * the block, the in_sync flag (which tells us we are in resync mode; 1004b88c807SRodney W. Grimes * looking for a valid header), and cnt (which starts at zero) which is 1014b88c807SRodney W. Grimes * used to count the number of empty blocks we have seen so far. 1024b88c807SRodney W. Grimes * Return: 1034b88c807SRodney W. Grimes * 0 if a valid trailer, -1 if not a valid trailer, or 1 if the block 1044b88c807SRodney W. Grimes * could never contain a header. 1054b88c807SRodney W. Grimes */ 1064b88c807SRodney W. Grimes 1074b88c807SRodney W. Grimes int 108f789b261SWarner Losh tar_trail(char *buf, int in_resync, int *cnt) 1094b88c807SRodney W. Grimes { 110f789b261SWarner Losh int i; 1114b88c807SRodney W. Grimes 1124b88c807SRodney W. Grimes /* 1134b88c807SRodney W. Grimes * look for all zero, trailer is two consecutive blocks of zero 1144b88c807SRodney W. Grimes */ 1154b88c807SRodney W. Grimes for (i = 0; i < BLKMULT; ++i) { 1164b88c807SRodney W. Grimes if (buf[i] != '\0') 1174b88c807SRodney W. Grimes break; 1184b88c807SRodney W. Grimes } 1194b88c807SRodney W. Grimes 1204b88c807SRodney W. Grimes /* 1214b88c807SRodney W. Grimes * if not all zero it is not a trailer, but MIGHT be a header. 1224b88c807SRodney W. Grimes */ 1234b88c807SRodney W. Grimes if (i != BLKMULT) 1244b88c807SRodney W. Grimes return(-1); 1254b88c807SRodney W. Grimes 1264b88c807SRodney W. Grimes /* 1274b88c807SRodney W. Grimes * When given a zero block, we must be careful! 1284b88c807SRodney W. Grimes * If we are not in resync mode, check for the trailer. Have to watch 1294b88c807SRodney W. Grimes * out that we do not mis-identify file data as the trailer, so we do 1304b88c807SRodney W. Grimes * NOT try to id a trailer during resync mode. During resync mode we 1314b88c807SRodney W. Grimes * might as well throw this block out since a valid header can NEVER be 1324b88c807SRodney W. Grimes * a block of all 0 (we must have a valid file name). 1334b88c807SRodney W. Grimes */ 1344b88c807SRodney W. Grimes if (!in_resync && (++*cnt >= NULLCNT)) 1354b88c807SRodney W. Grimes return(0); 1364b88c807SRodney W. Grimes return(1); 1374b88c807SRodney W. Grimes } 1384b88c807SRodney W. Grimes 1394b88c807SRodney W. Grimes /* 1404b88c807SRodney W. Grimes * ul_oct() 1414b88c807SRodney W. Grimes * convert an unsigned long to an octal string. many oddball field 1424b88c807SRodney W. Grimes * termination characters are used by the various versions of tar in the 143b1787decSKris Kennaway * different fields. term selects which kind to use. str is '0' padded 1444b88c807SRodney W. Grimes * at the front to len. we are unable to use only one format as many old 1454b88c807SRodney W. Grimes * tar readers are very cranky about this. 1464b88c807SRodney W. Grimes * Return: 1474b88c807SRodney W. Grimes * 0 if the number fit into the string, -1 otherwise 1484b88c807SRodney W. Grimes */ 1494b88c807SRodney W. Grimes 1504b88c807SRodney W. Grimes static int 151f789b261SWarner Losh ul_oct(u_long val, char *str, int len, int term) 1524b88c807SRodney W. Grimes { 153f789b261SWarner Losh char *pt; 1544b88c807SRodney W. Grimes 1554b88c807SRodney W. Grimes /* 1564b88c807SRodney W. Grimes * term selects the appropriate character(s) for the end of the string 1574b88c807SRodney W. Grimes */ 1584b88c807SRodney W. Grimes pt = str + len - 1; 1594b88c807SRodney W. Grimes switch(term) { 1604b88c807SRodney W. Grimes case 3: 1614b88c807SRodney W. Grimes *pt-- = '\0'; 1624b88c807SRodney W. Grimes break; 1634b88c807SRodney W. Grimes case 2: 1644b88c807SRodney W. Grimes *pt-- = ' '; 1654b88c807SRodney W. Grimes *pt-- = '\0'; 1664b88c807SRodney W. Grimes break; 1674b88c807SRodney W. Grimes case 1: 1684b88c807SRodney W. Grimes *pt-- = ' '; 1694b88c807SRodney W. Grimes break; 1704b88c807SRodney W. Grimes case 0: 1714b88c807SRodney W. Grimes default: 1724b88c807SRodney W. Grimes *pt-- = '\0'; 1734b88c807SRodney W. Grimes *pt-- = ' '; 1744b88c807SRodney W. Grimes break; 1754b88c807SRodney W. Grimes } 1764b88c807SRodney W. Grimes 1774b88c807SRodney W. Grimes /* 1784b88c807SRodney W. Grimes * convert and blank pad if there is space 1794b88c807SRodney W. Grimes */ 1804b88c807SRodney W. Grimes while (pt >= str) { 1814b88c807SRodney W. Grimes *pt-- = '0' + (char)(val & 0x7); 1824b88c807SRodney W. Grimes if ((val = val >> 3) == (u_long)0) 1834b88c807SRodney W. Grimes break; 1844b88c807SRodney W. Grimes } 1854b88c807SRodney W. Grimes 1864b88c807SRodney W. Grimes while (pt >= str) 187b1787decSKris Kennaway *pt-- = '0'; 1884b88c807SRodney W. Grimes if (val != (u_long)0) 1894b88c807SRodney W. Grimes return(-1); 1904b88c807SRodney W. Grimes return(0); 1914b88c807SRodney W. Grimes } 1924b88c807SRodney W. Grimes 1934b88c807SRodney W. Grimes #ifndef NET2_STAT 1944b88c807SRodney W. Grimes /* 1954b88c807SRodney W. Grimes * uqd_oct() 1964b88c807SRodney W. Grimes * convert an u_quad_t to an octal string. one of many oddball field 1974b88c807SRodney W. Grimes * termination characters are used by the various versions of tar in the 198b1787decSKris Kennaway * different fields. term selects which kind to use. str is '0' padded 1994b88c807SRodney W. Grimes * at the front to len. we are unable to use only one format as many old 2004b88c807SRodney W. Grimes * tar readers are very cranky about this. 2014b88c807SRodney W. Grimes * Return: 2024b88c807SRodney W. Grimes * 0 if the number fit into the string, -1 otherwise 2034b88c807SRodney W. Grimes */ 2044b88c807SRodney W. Grimes 2054b88c807SRodney W. Grimes static int 206f789b261SWarner Losh uqd_oct(u_quad_t val, char *str, int len, int term) 2074b88c807SRodney W. Grimes { 208f789b261SWarner Losh char *pt; 2094b88c807SRodney W. Grimes 2104b88c807SRodney W. Grimes /* 2114b88c807SRodney W. Grimes * term selects the appropriate character(s) for the end of the string 2124b88c807SRodney W. Grimes */ 2134b88c807SRodney W. Grimes pt = str + len - 1; 2144b88c807SRodney W. Grimes switch(term) { 2154b88c807SRodney W. Grimes case 3: 2164b88c807SRodney W. Grimes *pt-- = '\0'; 2174b88c807SRodney W. Grimes break; 2184b88c807SRodney W. Grimes case 2: 2194b88c807SRodney W. Grimes *pt-- = ' '; 2204b88c807SRodney W. Grimes *pt-- = '\0'; 2214b88c807SRodney W. Grimes break; 2224b88c807SRodney W. Grimes case 1: 2234b88c807SRodney W. Grimes *pt-- = ' '; 2244b88c807SRodney W. Grimes break; 2254b88c807SRodney W. Grimes case 0: 2264b88c807SRodney W. Grimes default: 2274b88c807SRodney W. Grimes *pt-- = '\0'; 2284b88c807SRodney W. Grimes *pt-- = ' '; 2294b88c807SRodney W. Grimes break; 2304b88c807SRodney W. Grimes } 2314b88c807SRodney W. Grimes 2324b88c807SRodney W. Grimes /* 2334b88c807SRodney W. Grimes * convert and blank pad if there is space 2344b88c807SRodney W. Grimes */ 2354b88c807SRodney W. Grimes while (pt >= str) { 2364b88c807SRodney W. Grimes *pt-- = '0' + (char)(val & 0x7); 2374b88c807SRodney W. Grimes if ((val = val >> 3) == 0) 2384b88c807SRodney W. Grimes break; 2394b88c807SRodney W. Grimes } 2404b88c807SRodney W. Grimes 2414b88c807SRodney W. Grimes while (pt >= str) 242b1787decSKris Kennaway *pt-- = '0'; 2434b88c807SRodney W. Grimes if (val != (u_quad_t)0) 2444b88c807SRodney W. Grimes return(-1); 2454b88c807SRodney W. Grimes return(0); 2464b88c807SRodney W. Grimes } 2474b88c807SRodney W. Grimes #endif 2484b88c807SRodney W. Grimes 2494b88c807SRodney W. Grimes /* 2504b88c807SRodney W. Grimes * tar_chksm() 2514b88c807SRodney W. Grimes * calculate the checksum for a tar block counting the checksum field as 25246be34b9SKris Kennaway * all blanks (BLNKSUM is that value pre-calculated, the sum of 8 blanks). 2534b88c807SRodney W. Grimes * NOTE: we use len to short circuit summing 0's on write since we ALWAYS 2544b88c807SRodney W. Grimes * pad headers with 0. 2554b88c807SRodney W. Grimes * Return: 2564b88c807SRodney W. Grimes * unsigned long checksum 2574b88c807SRodney W. Grimes */ 2584b88c807SRodney W. Grimes 2594b88c807SRodney W. Grimes static u_long 260f789b261SWarner Losh tar_chksm(char *blk, int len) 2614b88c807SRodney W. Grimes { 262f789b261SWarner Losh char *stop; 263f789b261SWarner Losh char *pt; 26446be34b9SKris Kennaway u_long chksm = BLNKSUM; /* initial value is checksum field sum */ 2654b88c807SRodney W. Grimes 2664b88c807SRodney W. Grimes /* 2674b88c807SRodney W. Grimes * add the part of the block before the checksum field 2684b88c807SRodney W. Grimes */ 2694b88c807SRodney W. Grimes pt = blk; 2704b88c807SRodney W. Grimes stop = blk + CHK_OFFSET; 2714b88c807SRodney W. Grimes while (pt < stop) 2724b88c807SRodney W. Grimes chksm += (u_long)(*pt++ & 0xff); 2734b88c807SRodney W. Grimes /* 2744b88c807SRodney W. Grimes * move past the checksum field and keep going, spec counts the 2754b88c807SRodney W. Grimes * checksum field as the sum of 8 blanks (which is pre-computed as 2764b88c807SRodney W. Grimes * BLNKSUM). 2774b88c807SRodney W. Grimes * ASSUMED: len is greater than CHK_OFFSET. (len is where our 0 padding 2784b88c807SRodney W. Grimes * starts, no point in summing zero's) 2794b88c807SRodney W. Grimes */ 2804b88c807SRodney W. Grimes pt += CHK_LEN; 2814b88c807SRodney W. Grimes stop = blk + len; 2824b88c807SRodney W. Grimes while (pt < stop) 2834b88c807SRodney W. Grimes chksm += (u_long)(*pt++ & 0xff); 2844b88c807SRodney W. Grimes return(chksm); 2854b88c807SRodney W. Grimes } 2864b88c807SRodney W. Grimes 2874b88c807SRodney W. Grimes /* 2884b88c807SRodney W. Grimes * Routines for old BSD style tar (also made portable to sysV tar) 2894b88c807SRodney W. Grimes */ 2904b88c807SRodney W. Grimes 2914b88c807SRodney W. Grimes /* 2924b88c807SRodney W. Grimes * tar_id() 2934b88c807SRodney W. Grimes * determine if a block given to us is a valid tar header (and not a USTAR 2944b88c807SRodney W. Grimes * header). We have to be on the lookout for those pesky blocks of all 2954b88c807SRodney W. Grimes * zero's. 2964b88c807SRodney W. Grimes * Return: 2974b88c807SRodney W. Grimes * 0 if a tar header, -1 otherwise 2984b88c807SRodney W. Grimes */ 2994b88c807SRodney W. Grimes 3004b88c807SRodney W. Grimes int 301f789b261SWarner Losh tar_id(char *blk, int size) 3024b88c807SRodney W. Grimes { 303f789b261SWarner Losh HD_TAR *hd; 304f789b261SWarner Losh HD_USTAR *uhd; 3054b88c807SRodney W. Grimes 3064b88c807SRodney W. Grimes if (size < BLKMULT) 3074b88c807SRodney W. Grimes return(-1); 3084b88c807SRodney W. Grimes hd = (HD_TAR *)blk; 3094b88c807SRodney W. Grimes uhd = (HD_USTAR *)blk; 3104b88c807SRodney W. Grimes 3114b88c807SRodney W. Grimes /* 3124b88c807SRodney W. Grimes * check for block of zero's first, a simple and fast test, then make 3134b88c807SRodney W. Grimes * sure this is not a ustar header by looking for the ustar magic 3144b88c807SRodney W. Grimes * cookie. We should use TMAGLEN, but some USTAR archive programs are 3154b88c807SRodney W. Grimes * wrong and create archives missing the \0. Last we check the 3164b88c807SRodney W. Grimes * checksum. If this is ok we have to assume it is a valid header. 3174b88c807SRodney W. Grimes */ 3184b88c807SRodney W. Grimes if (hd->name[0] == '\0') 3194b88c807SRodney W. Grimes return(-1); 3204b88c807SRodney W. Grimes if (strncmp(uhd->magic, TMAGIC, TMAGLEN - 1) == 0) 3214b88c807SRodney W. Grimes return(-1); 3224b88c807SRodney W. Grimes if (asc_ul(hd->chksum,sizeof(hd->chksum),OCT) != tar_chksm(blk,BLKMULT)) 3234b88c807SRodney W. Grimes return(-1); 3244b88c807SRodney W. Grimes return(0); 3254b88c807SRodney W. Grimes } 3264b88c807SRodney W. Grimes 3274b88c807SRodney W. Grimes /* 3284b88c807SRodney W. Grimes * tar_opt() 3294b88c807SRodney W. Grimes * handle tar format specific -o options 3304b88c807SRodney W. Grimes * Return: 3314b88c807SRodney W. Grimes * 0 if ok -1 otherwise 3324b88c807SRodney W. Grimes */ 3334b88c807SRodney W. Grimes 3344b88c807SRodney W. Grimes int 3354b88c807SRodney W. Grimes tar_opt(void) 3364b88c807SRodney W. Grimes { 3374b88c807SRodney W. Grimes OPLIST *opt; 3384b88c807SRodney W. Grimes 3394b88c807SRodney W. Grimes while ((opt = opt_next()) != NULL) { 3404b88c807SRodney W. Grimes if (strcmp(opt->name, TAR_OPTION) || 3414b88c807SRodney W. Grimes strcmp(opt->value, TAR_NODIR)) { 342778766feSKris Kennaway paxwarn(1, "Unknown tar format -o option/value pair %s=%s", 3434b88c807SRodney W. Grimes opt->name, opt->value); 344778766feSKris Kennaway paxwarn(1,"%s=%s is the only supported tar format option", 3454b88c807SRodney W. Grimes TAR_OPTION, TAR_NODIR); 3464b88c807SRodney W. Grimes return(-1); 3474b88c807SRodney W. Grimes } 3484b88c807SRodney W. Grimes 3494b88c807SRodney W. Grimes /* 3504b88c807SRodney W. Grimes * we only support one option, and only when writing 3514b88c807SRodney W. Grimes */ 3524b88c807SRodney W. Grimes if ((act != APPND) && (act != ARCHIVE)) { 353778766feSKris Kennaway paxwarn(1, "%s=%s is only supported when writing.", 3544b88c807SRodney W. Grimes opt->name, opt->value); 3554b88c807SRodney W. Grimes return(-1); 3564b88c807SRodney W. Grimes } 3574b88c807SRodney W. Grimes tar_nodir = 1; 3584b88c807SRodney W. Grimes } 3594b88c807SRodney W. Grimes return(0); 3604b88c807SRodney W. Grimes } 3614b88c807SRodney W. Grimes 3624b88c807SRodney W. Grimes 3634b88c807SRodney W. Grimes /* 3644b88c807SRodney W. Grimes * tar_rd() 3654b88c807SRodney W. Grimes * extract the values out of block already determined to be a tar header. 3664b88c807SRodney W. Grimes * store the values in the ARCHD parameter. 3674b88c807SRodney W. Grimes * Return: 3684b88c807SRodney W. Grimes * 0 3694b88c807SRodney W. Grimes */ 3704b88c807SRodney W. Grimes 3714b88c807SRodney W. Grimes int 372f789b261SWarner Losh tar_rd(ARCHD *arcn, char *buf) 3734b88c807SRodney W. Grimes { 374f789b261SWarner Losh HD_TAR *hd; 375f789b261SWarner Losh char *pt; 3764b88c807SRodney W. Grimes 3774b88c807SRodney W. Grimes /* 3784b88c807SRodney W. Grimes * we only get proper sized buffers passed to us 3794b88c807SRodney W. Grimes */ 3804b88c807SRodney W. Grimes if (tar_id(buf, BLKMULT) < 0) 3814b88c807SRodney W. Grimes return(-1); 3824b88c807SRodney W. Grimes arcn->org_name = arcn->name; 3834b88c807SRodney W. Grimes arcn->sb.st_nlink = 1; 3844b88c807SRodney W. Grimes arcn->pat = NULL; 3854b88c807SRodney W. Grimes 3864b88c807SRodney W. Grimes /* 3874b88c807SRodney W. Grimes * copy out the name and values in the stat buffer 3884b88c807SRodney W. Grimes */ 3894b88c807SRodney W. Grimes hd = (HD_TAR *)buf; 3905512dc54SYaroslav Tykhiy /* 3915512dc54SYaroslav Tykhiy * old tar format specifies the name always be null-terminated, 3925512dc54SYaroslav Tykhiy * but let's be robust to broken archives. 3935512dc54SYaroslav Tykhiy * the same applies to handling links below. 3945512dc54SYaroslav Tykhiy */ 3955512dc54SYaroslav Tykhiy arcn->nlen = l_strncpy(arcn->name, hd->name, 3965512dc54SYaroslav Tykhiy MIN(sizeof(hd->name), sizeof(arcn->name)) - 1); 3974b88c807SRodney W. Grimes arcn->name[arcn->nlen] = '\0'; 3984b88c807SRodney W. Grimes arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode,sizeof(hd->mode),OCT) & 3994b88c807SRodney W. Grimes 0xfff); 4004b88c807SRodney W. Grimes arcn->sb.st_uid = (uid_t)asc_ul(hd->uid, sizeof(hd->uid), OCT); 4014b88c807SRodney W. Grimes arcn->sb.st_gid = (gid_t)asc_ul(hd->gid, sizeof(hd->gid), OCT); 402b1787decSKris Kennaway #ifdef NET2_STAT 403b1787decSKris Kennaway arcn->sb.st_size = (off_t)asc_ul(hd->size, sizeof(hd->size), OCT); 404dbd9746fSMatthew Dillon arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT); 405b1787decSKris Kennaway #else 406b1787decSKris Kennaway arcn->sb.st_size = (off_t)asc_uqd(hd->size, sizeof(hd->size), OCT); 407dbd9746fSMatthew Dillon arcn->sb.st_mtime = (time_t)asc_uqd(hd->mtime, sizeof(hd->mtime), OCT); 408b1787decSKris Kennaway #endif 4094b88c807SRodney W. Grimes arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime; 4104b88c807SRodney W. Grimes 4114b88c807SRodney W. Grimes /* 4124b88c807SRodney W. Grimes * have to look at the last character, it may be a '/' and that is used 4134b88c807SRodney W. Grimes * to encode this as a directory 4144b88c807SRodney W. Grimes */ 4154b88c807SRodney W. Grimes pt = &(arcn->name[arcn->nlen - 1]); 4164b88c807SRodney W. Grimes arcn->pad = 0; 4174b88c807SRodney W. Grimes arcn->skip = 0; 4184b88c807SRodney W. Grimes switch(hd->linkflag) { 4194b88c807SRodney W. Grimes case SYMTYPE: 4204b88c807SRodney W. Grimes /* 4214b88c807SRodney W. Grimes * symbolic link, need to get the link name and set the type in 4224b88c807SRodney W. Grimes * the st_mode so -v printing will look correct. 4234b88c807SRodney W. Grimes */ 4244b88c807SRodney W. Grimes arcn->type = PAX_SLK; 4254b88c807SRodney W. Grimes arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname, 4265512dc54SYaroslav Tykhiy MIN(sizeof(hd->linkname), sizeof(arcn->ln_name)) - 1); 4274b88c807SRodney W. Grimes arcn->ln_name[arcn->ln_nlen] = '\0'; 4284b88c807SRodney W. Grimes arcn->sb.st_mode |= S_IFLNK; 4294b88c807SRodney W. Grimes break; 4304b88c807SRodney W. Grimes case LNKTYPE: 4314b88c807SRodney W. Grimes /* 4324b88c807SRodney W. Grimes * hard link, need to get the link name, set the type in the 4334b88c807SRodney W. Grimes * st_mode and st_nlink so -v printing will look better. 4344b88c807SRodney W. Grimes */ 4354b88c807SRodney W. Grimes arcn->type = PAX_HLK; 4364b88c807SRodney W. Grimes arcn->sb.st_nlink = 2; 4374b88c807SRodney W. Grimes arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname, 4385512dc54SYaroslav Tykhiy MIN(sizeof(hd->linkname), sizeof(arcn->ln_name)) - 1); 4394b88c807SRodney W. Grimes arcn->ln_name[arcn->ln_nlen] = '\0'; 4404b88c807SRodney W. Grimes 4414b88c807SRodney W. Grimes /* 4424b88c807SRodney W. Grimes * no idea of what type this thing really points at, but 4434b88c807SRodney W. Grimes * we set something for printing only. 4444b88c807SRodney W. Grimes */ 4454b88c807SRodney W. Grimes arcn->sb.st_mode |= S_IFREG; 4464b88c807SRodney W. Grimes break; 447b1787decSKris Kennaway case DIRTYPE: 448b1787decSKris Kennaway /* 449b1787decSKris Kennaway * It is a directory, set the mode for -v printing 450b1787decSKris Kennaway */ 451b1787decSKris Kennaway arcn->type = PAX_DIR; 452b1787decSKris Kennaway arcn->sb.st_mode |= S_IFDIR; 453b1787decSKris Kennaway arcn->sb.st_nlink = 2; 454b1787decSKris Kennaway arcn->ln_name[0] = '\0'; 455b1787decSKris Kennaway arcn->ln_nlen = 0; 456b1787decSKris Kennaway break; 4574b88c807SRodney W. Grimes case AREGTYPE: 4584b88c807SRodney W. Grimes case REGTYPE: 4594b88c807SRodney W. Grimes default: 4604b88c807SRodney W. Grimes /* 4614b88c807SRodney W. Grimes * If we have a trailing / this is a directory and NOT a file. 4624b88c807SRodney W. Grimes */ 4634b88c807SRodney W. Grimes arcn->ln_name[0] = '\0'; 4644b88c807SRodney W. Grimes arcn->ln_nlen = 0; 4654b88c807SRodney W. Grimes if (*pt == '/') { 4664b88c807SRodney W. Grimes /* 4674b88c807SRodney W. Grimes * it is a directory, set the mode for -v printing 4684b88c807SRodney W. Grimes */ 4694b88c807SRodney W. Grimes arcn->type = PAX_DIR; 4704b88c807SRodney W. Grimes arcn->sb.st_mode |= S_IFDIR; 4714b88c807SRodney W. Grimes arcn->sb.st_nlink = 2; 4724b88c807SRodney W. Grimes } else { 4734b88c807SRodney W. Grimes /* 4744b88c807SRodney W. Grimes * have a file that will be followed by data. Set the 47546be34b9SKris Kennaway * skip value to the size field and calculate the size 4764b88c807SRodney W. Grimes * of the padding. 4774b88c807SRodney W. Grimes */ 4784b88c807SRodney W. Grimes arcn->type = PAX_REG; 4794b88c807SRodney W. Grimes arcn->sb.st_mode |= S_IFREG; 4804b88c807SRodney W. Grimes arcn->pad = TAR_PAD(arcn->sb.st_size); 4814b88c807SRodney W. Grimes arcn->skip = arcn->sb.st_size; 4824b88c807SRodney W. Grimes } 4834b88c807SRodney W. Grimes break; 4844b88c807SRodney W. Grimes } 4854b88c807SRodney W. Grimes 4864b88c807SRodney W. Grimes /* 4874b88c807SRodney W. Grimes * strip off any trailing slash. 4884b88c807SRodney W. Grimes */ 4894b88c807SRodney W. Grimes if (*pt == '/') { 4904b88c807SRodney W. Grimes *pt = '\0'; 4914b88c807SRodney W. Grimes --arcn->nlen; 4924b88c807SRodney W. Grimes } 4934b88c807SRodney W. Grimes return(0); 4944b88c807SRodney W. Grimes } 4954b88c807SRodney W. Grimes 4964b88c807SRodney W. Grimes /* 4974b88c807SRodney W. Grimes * tar_wr() 4984b88c807SRodney W. Grimes * write a tar header for the file specified in the ARCHD to the archive. 4994b88c807SRodney W. Grimes * Have to check for file types that cannot be stored and file names that 5004b88c807SRodney W. Grimes * are too long. Be careful of the term (last arg) to ul_oct, each field 5014b88c807SRodney W. Grimes * of tar has it own spec for the termination character(s). 5024b88c807SRodney W. Grimes * ASSUMED: space after header in header block is zero filled 5034b88c807SRodney W. Grimes * Return: 5044b88c807SRodney W. Grimes * 0 if file has data to be written after the header, 1 if file has NO 5054b88c807SRodney W. Grimes * data to write after the header, -1 if archive write failed 5064b88c807SRodney W. Grimes */ 5074b88c807SRodney W. Grimes 5084b88c807SRodney W. Grimes int 509f789b261SWarner Losh tar_wr(ARCHD *arcn) 5104b88c807SRodney W. Grimes { 511f789b261SWarner Losh HD_TAR *hd; 5124b88c807SRodney W. Grimes int len; 513c65bb135SRuslan Ermilov HD_TAR hdblk; 5144b88c807SRodney W. Grimes 5154b88c807SRodney W. Grimes /* 5164b88c807SRodney W. Grimes * check for those file system types which tar cannot store 5174b88c807SRodney W. Grimes */ 5184b88c807SRodney W. Grimes switch(arcn->type) { 5194b88c807SRodney W. Grimes case PAX_DIR: 5204b88c807SRodney W. Grimes /* 5214b88c807SRodney W. Grimes * user asked that dirs not be written to the archive 5224b88c807SRodney W. Grimes */ 5234b88c807SRodney W. Grimes if (tar_nodir) 5244b88c807SRodney W. Grimes return(1); 5254b88c807SRodney W. Grimes break; 5264b88c807SRodney W. Grimes case PAX_CHR: 527778766feSKris Kennaway paxwarn(1, "Tar cannot archive a character device %s", 5284b88c807SRodney W. Grimes arcn->org_name); 5294b88c807SRodney W. Grimes return(1); 5304b88c807SRodney W. Grimes case PAX_BLK: 531778766feSKris Kennaway paxwarn(1, "Tar cannot archive a block device %s", arcn->org_name); 5324b88c807SRodney W. Grimes return(1); 5334b88c807SRodney W. Grimes case PAX_SCK: 534778766feSKris Kennaway paxwarn(1, "Tar cannot archive a socket %s", arcn->org_name); 5354b88c807SRodney W. Grimes return(1); 5364b88c807SRodney W. Grimes case PAX_FIF: 537778766feSKris Kennaway paxwarn(1, "Tar cannot archive a fifo %s", arcn->org_name); 5384b88c807SRodney W. Grimes return(1); 5394b88c807SRodney W. Grimes case PAX_SLK: 5404b88c807SRodney W. Grimes case PAX_HLK: 5414b88c807SRodney W. Grimes case PAX_HRG: 5425512dc54SYaroslav Tykhiy if (arcn->ln_nlen >= (int)sizeof(hd->linkname)) { 543778766feSKris Kennaway paxwarn(1,"Link name too long for tar %s", arcn->ln_name); 5444b88c807SRodney W. Grimes return(1); 5454b88c807SRodney W. Grimes } 5464b88c807SRodney W. Grimes break; 5474b88c807SRodney W. Grimes case PAX_REG: 5484b88c807SRodney W. Grimes case PAX_CTG: 5494b88c807SRodney W. Grimes default: 5504b88c807SRodney W. Grimes break; 5514b88c807SRodney W. Grimes } 5524b88c807SRodney W. Grimes 5534b88c807SRodney W. Grimes /* 5544b88c807SRodney W. Grimes * check file name len, remember extra char for dirs (the / at the end) 5554b88c807SRodney W. Grimes */ 5564b88c807SRodney W. Grimes len = arcn->nlen; 5574b88c807SRodney W. Grimes if (arcn->type == PAX_DIR) 5584b88c807SRodney W. Grimes ++len; 559cee22cbdSDavid E. O'Brien if (len >= (int)sizeof(hd->name)) { 560778766feSKris Kennaway paxwarn(1, "File name too long for tar %s", arcn->name); 5614b88c807SRodney W. Grimes return(1); 5624b88c807SRodney W. Grimes } 5634b88c807SRodney W. Grimes 5644b88c807SRodney W. Grimes /* 5654b88c807SRodney W. Grimes * copy the data out of the ARCHD into the tar header based on the type 5664b88c807SRodney W. Grimes * of the file. Remember many tar readers want the unused fields to be 5674b88c807SRodney W. Grimes * padded with zero. We set the linkflag field (type), the linkname 5684b88c807SRodney W. Grimes * (or zero if not used),the size, and set the padding (if any) to be 5694b88c807SRodney W. Grimes * added after the file data (0 for all other types, as they only have 5704b88c807SRodney W. Grimes * a header) 5714b88c807SRodney W. Grimes */ 572c65bb135SRuslan Ermilov hd = &hdblk; 573b1787decSKris Kennaway l_strncpy(hd->name, arcn->name, sizeof(hd->name) - 1); 574b1787decSKris Kennaway hd->name[sizeof(hd->name) - 1] = '\0'; 5754b88c807SRodney W. Grimes arcn->pad = 0; 5764b88c807SRodney W. Grimes 5774b88c807SRodney W. Grimes if (arcn->type == PAX_DIR) { 5784b88c807SRodney W. Grimes /* 5794b88c807SRodney W. Grimes * directories are the same as files, except have a filename 5804b88c807SRodney W. Grimes * that ends with a /, we add the slash here. No data follows, 5814b88c807SRodney W. Grimes * dirs, so no pad. 5824b88c807SRodney W. Grimes */ 5834b88c807SRodney W. Grimes hd->linkflag = AREGTYPE; 584778766feSKris Kennaway memset(hd->linkname, 0, sizeof(hd->linkname)); 5854b88c807SRodney W. Grimes hd->name[len-1] = '/'; 5864b88c807SRodney W. Grimes if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1)) 5874b88c807SRodney W. Grimes goto out; 5884b88c807SRodney W. Grimes } else if (arcn->type == PAX_SLK) { 5894b88c807SRodney W. Grimes /* 5904b88c807SRodney W. Grimes * no data follows this file, so no pad 5914b88c807SRodney W. Grimes */ 5924b88c807SRodney W. Grimes hd->linkflag = SYMTYPE; 593b1787decSKris Kennaway l_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname) - 1); 594b1787decSKris Kennaway hd->linkname[sizeof(hd->linkname) - 1] = '\0'; 5954b88c807SRodney W. Grimes if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1)) 5964b88c807SRodney W. Grimes goto out; 5974b88c807SRodney W. Grimes } else if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG)) { 5984b88c807SRodney W. Grimes /* 5994b88c807SRodney W. Grimes * no data follows this file, so no pad 6004b88c807SRodney W. Grimes */ 6014b88c807SRodney W. Grimes hd->linkflag = LNKTYPE; 602b1787decSKris Kennaway l_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname) - 1); 603b1787decSKris Kennaway hd->linkname[sizeof(hd->linkname) - 1] = '\0'; 6044b88c807SRodney W. Grimes if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1)) 6054b88c807SRodney W. Grimes goto out; 6064b88c807SRodney W. Grimes } else { 6074b88c807SRodney W. Grimes /* 6084b88c807SRodney W. Grimes * data follows this file, so set the pad 6094b88c807SRodney W. Grimes */ 6104b88c807SRodney W. Grimes hd->linkflag = AREGTYPE; 611778766feSKris Kennaway memset(hd->linkname, 0, sizeof(hd->linkname)); 6124b88c807SRodney W. Grimes # ifdef NET2_STAT 6134b88c807SRodney W. Grimes if (ul_oct((u_long)arcn->sb.st_size, hd->size, 6144b88c807SRodney W. Grimes sizeof(hd->size), 1)) { 6154b88c807SRodney W. Grimes # else 6164b88c807SRodney W. Grimes if (uqd_oct((u_quad_t)arcn->sb.st_size, hd->size, 6174b88c807SRodney W. Grimes sizeof(hd->size), 1)) { 6184b88c807SRodney W. Grimes # endif 619778766feSKris Kennaway paxwarn(1,"File is too large for tar %s", arcn->org_name); 6204b88c807SRodney W. Grimes return(1); 6214b88c807SRodney W. Grimes } 6224b88c807SRodney W. Grimes arcn->pad = TAR_PAD(arcn->sb.st_size); 6234b88c807SRodney W. Grimes } 6244b88c807SRodney W. Grimes 6254b88c807SRodney W. Grimes /* 6264b88c807SRodney W. Grimes * copy those fields that are independent of the type 6274b88c807SRodney W. Grimes */ 6284b88c807SRodney W. Grimes if (ul_oct((u_long)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 0) || 6294b88c807SRodney W. Grimes ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 0) || 6304b88c807SRodney W. Grimes ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 0) || 6314b88c807SRodney W. Grimes ul_oct((u_long)arcn->sb.st_mtime, hd->mtime, sizeof(hd->mtime), 1)) 6324b88c807SRodney W. Grimes goto out; 6334b88c807SRodney W. Grimes 6344b88c807SRodney W. Grimes /* 6354b88c807SRodney W. Grimes * calculate and add the checksum, then write the header. A return of 6364b88c807SRodney W. Grimes * 0 tells the caller to now write the file data, 1 says no data needs 6374b88c807SRodney W. Grimes * to be written 6384b88c807SRodney W. Grimes */ 639c65bb135SRuslan Ermilov if (ul_oct(tar_chksm((char *)&hdblk, sizeof(HD_TAR)), hd->chksum, 640b1787decSKris Kennaway sizeof(hd->chksum), 3)) 6414b88c807SRodney W. Grimes goto out; 642c65bb135SRuslan Ermilov if (wr_rdbuf((char *)&hdblk, sizeof(HD_TAR)) < 0) 6434b88c807SRodney W. Grimes return(-1); 6444b88c807SRodney W. Grimes if (wr_skip((off_t)(BLKMULT - sizeof(HD_TAR))) < 0) 6454b88c807SRodney W. Grimes return(-1); 6464b88c807SRodney W. Grimes if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG)) 6474b88c807SRodney W. Grimes return(0); 6484b88c807SRodney W. Grimes return(1); 6494b88c807SRodney W. Grimes 6504b88c807SRodney W. Grimes out: 6514b88c807SRodney W. Grimes /* 6524b88c807SRodney W. Grimes * header field is out of range 6534b88c807SRodney W. Grimes */ 654778766feSKris Kennaway paxwarn(1, "Tar header field is too small for %s", arcn->org_name); 6554b88c807SRodney W. Grimes return(1); 6564b88c807SRodney W. Grimes } 6574b88c807SRodney W. Grimes 6584b88c807SRodney W. Grimes /* 6594b88c807SRodney W. Grimes * Routines for POSIX ustar 6604b88c807SRodney W. Grimes */ 6614b88c807SRodney W. Grimes 6624b88c807SRodney W. Grimes /* 6634b88c807SRodney W. Grimes * ustar_strd() 6644b88c807SRodney W. Grimes * initialization for ustar read 6654b88c807SRodney W. Grimes * Return: 6664b88c807SRodney W. Grimes * 0 if ok, -1 otherwise 6674b88c807SRodney W. Grimes */ 6684b88c807SRodney W. Grimes 6694b88c807SRodney W. Grimes int 6704b88c807SRodney W. Grimes ustar_strd(void) 6714b88c807SRodney W. Grimes { 6724b88c807SRodney W. Grimes if ((usrtb_start() < 0) || (grptb_start() < 0)) 6734b88c807SRodney W. Grimes return(-1); 6744b88c807SRodney W. Grimes return(0); 6754b88c807SRodney W. Grimes } 6764b88c807SRodney W. Grimes 6774b88c807SRodney W. Grimes /* 6784b88c807SRodney W. Grimes * ustar_stwr() 6794b88c807SRodney W. Grimes * initialization for ustar write 6804b88c807SRodney W. Grimes * Return: 6814b88c807SRodney W. Grimes * 0 if ok, -1 otherwise 6824b88c807SRodney W. Grimes */ 6834b88c807SRodney W. Grimes 6844b88c807SRodney W. Grimes int 6854b88c807SRodney W. Grimes ustar_stwr(void) 6864b88c807SRodney W. Grimes { 6874b88c807SRodney W. Grimes if ((uidtb_start() < 0) || (gidtb_start() < 0)) 6884b88c807SRodney W. Grimes return(-1); 6894b88c807SRodney W. Grimes return(0); 6904b88c807SRodney W. Grimes } 6914b88c807SRodney W. Grimes 6924b88c807SRodney W. Grimes /* 6934b88c807SRodney W. Grimes * ustar_id() 6944b88c807SRodney W. Grimes * determine if a block given to us is a valid ustar header. We have to 6954b88c807SRodney W. Grimes * be on the lookout for those pesky blocks of all zero's 6964b88c807SRodney W. Grimes * Return: 6974b88c807SRodney W. Grimes * 0 if a ustar header, -1 otherwise 6984b88c807SRodney W. Grimes */ 6994b88c807SRodney W. Grimes 7004b88c807SRodney W. Grimes int 7014b88c807SRodney W. Grimes ustar_id(char *blk, int size) 7024b88c807SRodney W. Grimes { 703f789b261SWarner Losh HD_USTAR *hd; 7044b88c807SRodney W. Grimes 7054b88c807SRodney W. Grimes if (size < BLKMULT) 7064b88c807SRodney W. Grimes return(-1); 7074b88c807SRodney W. Grimes hd = (HD_USTAR *)blk; 7084b88c807SRodney W. Grimes 7094b88c807SRodney W. Grimes /* 7104b88c807SRodney W. Grimes * check for block of zero's first, a simple and fast test then check 7114b88c807SRodney W. Grimes * ustar magic cookie. We should use TMAGLEN, but some USTAR archive 7124b88c807SRodney W. Grimes * programs are fouled up and create archives missing the \0. Last we 7134b88c807SRodney W. Grimes * check the checksum. If ok we have to assume it is a valid header. 7144b88c807SRodney W. Grimes */ 7154b88c807SRodney W. Grimes if (hd->name[0] == '\0') 7164b88c807SRodney W. Grimes return(-1); 7174b88c807SRodney W. Grimes if (strncmp(hd->magic, TMAGIC, TMAGLEN - 1) != 0) 7184b88c807SRodney W. Grimes return(-1); 7194b88c807SRodney W. Grimes if (asc_ul(hd->chksum,sizeof(hd->chksum),OCT) != tar_chksm(blk,BLKMULT)) 7204b88c807SRodney W. Grimes return(-1); 7214b88c807SRodney W. Grimes return(0); 7224b88c807SRodney W. Grimes } 7234b88c807SRodney W. Grimes 7244b88c807SRodney W. Grimes /* 7254b88c807SRodney W. Grimes * ustar_rd() 7264b88c807SRodney W. Grimes * extract the values out of block already determined to be a ustar header. 7274b88c807SRodney W. Grimes * store the values in the ARCHD parameter. 7284b88c807SRodney W. Grimes * Return: 7294b88c807SRodney W. Grimes * 0 7304b88c807SRodney W. Grimes */ 7314b88c807SRodney W. Grimes 7324b88c807SRodney W. Grimes int 733f789b261SWarner Losh ustar_rd(ARCHD *arcn, char *buf) 7344b88c807SRodney W. Grimes { 735f789b261SWarner Losh HD_USTAR *hd; 736f789b261SWarner Losh char *dest; 737f789b261SWarner Losh int cnt = 0; 7384b88c807SRodney W. Grimes dev_t devmajor; 7394b88c807SRodney W. Grimes dev_t devminor; 7404b88c807SRodney W. Grimes 7414b88c807SRodney W. Grimes /* 7424b88c807SRodney W. Grimes * we only get proper sized buffers 7434b88c807SRodney W. Grimes */ 7444b88c807SRodney W. Grimes if (ustar_id(buf, BLKMULT) < 0) 7454b88c807SRodney W. Grimes return(-1); 7464b88c807SRodney W. Grimes arcn->org_name = arcn->name; 7474b88c807SRodney W. Grimes arcn->sb.st_nlink = 1; 7484b88c807SRodney W. Grimes arcn->pat = NULL; 749b1787decSKris Kennaway arcn->nlen = 0; 7504b88c807SRodney W. Grimes hd = (HD_USTAR *)buf; 7514b88c807SRodney W. Grimes 7524b88c807SRodney W. Grimes /* 7534b88c807SRodney W. Grimes * see if the filename is split into two parts. if, so joint the parts. 7544b88c807SRodney W. Grimes * we copy the prefix first and add a / between the prefix and name. 7554b88c807SRodney W. Grimes */ 7564b88c807SRodney W. Grimes dest = arcn->name; 7574b88c807SRodney W. Grimes if (*(hd->prefix) != '\0') { 7585512dc54SYaroslav Tykhiy cnt = l_strncpy(dest, hd->prefix, 7595512dc54SYaroslav Tykhiy MIN(sizeof(hd->prefix), sizeof(arcn->name) - 2)); 760b1787decSKris Kennaway dest += cnt; 7614b88c807SRodney W. Grimes *dest++ = '/'; 762b1787decSKris Kennaway cnt++; 7634b88c807SRodney W. Grimes } 7645512dc54SYaroslav Tykhiy /* 7655512dc54SYaroslav Tykhiy * ustar format specifies the name may be unterminated 7665512dc54SYaroslav Tykhiy * if it fills the entire field. this also applies to 7675512dc54SYaroslav Tykhiy * the prefix and the linkname. 7685512dc54SYaroslav Tykhiy */ 7695512dc54SYaroslav Tykhiy arcn->nlen = cnt + l_strncpy(dest, hd->name, 7705512dc54SYaroslav Tykhiy MIN(sizeof(hd->name), sizeof(arcn->name) - cnt - 1)); 7714b88c807SRodney W. Grimes arcn->name[arcn->nlen] = '\0'; 7724b88c807SRodney W. Grimes 7734b88c807SRodney W. Grimes /* 7744b88c807SRodney W. Grimes * follow the spec to the letter. we should only have mode bits, strip 7754b88c807SRodney W. Grimes * off all other crud we may be passed. 7764b88c807SRodney W. Grimes */ 7774b88c807SRodney W. Grimes arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode, sizeof(hd->mode), OCT) & 7784b88c807SRodney W. Grimes 0xfff); 779b1787decSKris Kennaway #ifdef NET2_STAT 780b1787decSKris Kennaway arcn->sb.st_size = (off_t)asc_ul(hd->size, sizeof(hd->size), OCT); 781dbd9746fSMatthew Dillon arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT); 782b1787decSKris Kennaway #else 783b1787decSKris Kennaway arcn->sb.st_size = (off_t)asc_uqd(hd->size, sizeof(hd->size), OCT); 784dbd9746fSMatthew Dillon arcn->sb.st_mtime = (time_t)asc_uqd(hd->mtime, sizeof(hd->mtime), OCT); 785b1787decSKris Kennaway #endif 7864b88c807SRodney W. Grimes arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime; 7874b88c807SRodney W. Grimes 7884b88c807SRodney W. Grimes /* 7894b88c807SRodney W. Grimes * If we can find the ascii names for gname and uname in the password 7904b88c807SRodney W. Grimes * and group files we will use the uid's and gid they bind. Otherwise 7914b88c807SRodney W. Grimes * we use the uid and gid values stored in the header. (This is what 79246be34b9SKris Kennaway * the POSIX spec wants). 7934b88c807SRodney W. Grimes */ 7944b88c807SRodney W. Grimes hd->gname[sizeof(hd->gname) - 1] = '\0'; 7954b88c807SRodney W. Grimes if (gid_name(hd->gname, &(arcn->sb.st_gid)) < 0) 7964b88c807SRodney W. Grimes arcn->sb.st_gid = (gid_t)asc_ul(hd->gid, sizeof(hd->gid), OCT); 7974b88c807SRodney W. Grimes hd->uname[sizeof(hd->uname) - 1] = '\0'; 7984b88c807SRodney W. Grimes if (uid_name(hd->uname, &(arcn->sb.st_uid)) < 0) 7994b88c807SRodney W. Grimes arcn->sb.st_uid = (uid_t)asc_ul(hd->uid, sizeof(hd->uid), OCT); 8004b88c807SRodney W. Grimes 8014b88c807SRodney W. Grimes /* 8024b88c807SRodney W. Grimes * set the defaults, these may be changed depending on the file type 8034b88c807SRodney W. Grimes */ 8044b88c807SRodney W. Grimes arcn->ln_name[0] = '\0'; 8054b88c807SRodney W. Grimes arcn->ln_nlen = 0; 8064b88c807SRodney W. Grimes arcn->pad = 0; 8074b88c807SRodney W. Grimes arcn->skip = 0; 8084b88c807SRodney W. Grimes arcn->sb.st_rdev = (dev_t)0; 8094b88c807SRodney W. Grimes 8104b88c807SRodney W. Grimes /* 8114b88c807SRodney W. Grimes * set the mode and PAX type according to the typeflag in the header 8124b88c807SRodney W. Grimes */ 8134b88c807SRodney W. Grimes switch(hd->typeflag) { 8144b88c807SRodney W. Grimes case FIFOTYPE: 8154b88c807SRodney W. Grimes arcn->type = PAX_FIF; 8164b88c807SRodney W. Grimes arcn->sb.st_mode |= S_IFIFO; 8174b88c807SRodney W. Grimes break; 8184b88c807SRodney W. Grimes case DIRTYPE: 8194b88c807SRodney W. Grimes arcn->type = PAX_DIR; 8204b88c807SRodney W. Grimes arcn->sb.st_mode |= S_IFDIR; 8214b88c807SRodney W. Grimes arcn->sb.st_nlink = 2; 8224b88c807SRodney W. Grimes 8234b88c807SRodney W. Grimes /* 8244b88c807SRodney W. Grimes * Some programs that create ustar archives append a '/' 8254b88c807SRodney W. Grimes * to the pathname for directories. This clearly violates 8264b88c807SRodney W. Grimes * ustar specs, but we will silently strip it off anyway. 8274b88c807SRodney W. Grimes */ 8284b88c807SRodney W. Grimes if (arcn->name[arcn->nlen - 1] == '/') 8294b88c807SRodney W. Grimes arcn->name[--arcn->nlen] = '\0'; 8304b88c807SRodney W. Grimes break; 8314b88c807SRodney W. Grimes case BLKTYPE: 8324b88c807SRodney W. Grimes case CHRTYPE: 8334b88c807SRodney W. Grimes /* 8344b88c807SRodney W. Grimes * this type requires the rdev field to be set. 8354b88c807SRodney W. Grimes */ 8364b88c807SRodney W. Grimes if (hd->typeflag == BLKTYPE) { 8374b88c807SRodney W. Grimes arcn->type = PAX_BLK; 8384b88c807SRodney W. Grimes arcn->sb.st_mode |= S_IFBLK; 8394b88c807SRodney W. Grimes } else { 8404b88c807SRodney W. Grimes arcn->type = PAX_CHR; 8414b88c807SRodney W. Grimes arcn->sb.st_mode |= S_IFCHR; 8424b88c807SRodney W. Grimes } 8434b88c807SRodney W. Grimes devmajor = (dev_t)asc_ul(hd->devmajor,sizeof(hd->devmajor),OCT); 8444b88c807SRodney W. Grimes devminor = (dev_t)asc_ul(hd->devminor,sizeof(hd->devminor),OCT); 8454b88c807SRodney W. Grimes arcn->sb.st_rdev = TODEV(devmajor, devminor); 8464b88c807SRodney W. Grimes break; 8474b88c807SRodney W. Grimes case SYMTYPE: 8484b88c807SRodney W. Grimes case LNKTYPE: 8494b88c807SRodney W. Grimes if (hd->typeflag == SYMTYPE) { 8504b88c807SRodney W. Grimes arcn->type = PAX_SLK; 8514b88c807SRodney W. Grimes arcn->sb.st_mode |= S_IFLNK; 8524b88c807SRodney W. Grimes } else { 8534b88c807SRodney W. Grimes arcn->type = PAX_HLK; 8544b88c807SRodney W. Grimes /* 8554b88c807SRodney W. Grimes * so printing looks better 8564b88c807SRodney W. Grimes */ 8574b88c807SRodney W. Grimes arcn->sb.st_mode |= S_IFREG; 8584b88c807SRodney W. Grimes arcn->sb.st_nlink = 2; 8594b88c807SRodney W. Grimes } 8604b88c807SRodney W. Grimes /* 8614b88c807SRodney W. Grimes * copy the link name 8624b88c807SRodney W. Grimes */ 8634b88c807SRodney W. Grimes arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname, 8645512dc54SYaroslav Tykhiy MIN(sizeof(hd->linkname), sizeof(arcn->ln_name) - 1)); 8654b88c807SRodney W. Grimes arcn->ln_name[arcn->ln_nlen] = '\0'; 8664b88c807SRodney W. Grimes break; 8674b88c807SRodney W. Grimes case CONTTYPE: 8684b88c807SRodney W. Grimes case AREGTYPE: 8694b88c807SRodney W. Grimes case REGTYPE: 8704b88c807SRodney W. Grimes default: 8714b88c807SRodney W. Grimes /* 8724b88c807SRodney W. Grimes * these types have file data that follows. Set the skip and 8734b88c807SRodney W. Grimes * pad fields. 8744b88c807SRodney W. Grimes */ 8754b88c807SRodney W. Grimes arcn->type = PAX_REG; 8764b88c807SRodney W. Grimes arcn->pad = TAR_PAD(arcn->sb.st_size); 8774b88c807SRodney W. Grimes arcn->skip = arcn->sb.st_size; 8784b88c807SRodney W. Grimes arcn->sb.st_mode |= S_IFREG; 8794b88c807SRodney W. Grimes break; 8804b88c807SRodney W. Grimes } 8814b88c807SRodney W. Grimes return(0); 8824b88c807SRodney W. Grimes } 8834b88c807SRodney W. Grimes 8844b88c807SRodney W. Grimes /* 8854b88c807SRodney W. Grimes * ustar_wr() 8864b88c807SRodney W. Grimes * write a ustar header for the file specified in the ARCHD to the archive 8874b88c807SRodney W. Grimes * Have to check for file types that cannot be stored and file names that 8884b88c807SRodney W. Grimes * are too long. Be careful of the term (last arg) to ul_oct, we only use 8894b88c807SRodney W. Grimes * '\0' for the termination character (this is different than picky tar) 8904b88c807SRodney W. Grimes * ASSUMED: space after header in header block is zero filled 8914b88c807SRodney W. Grimes * Return: 8924b88c807SRodney W. Grimes * 0 if file has data to be written after the header, 1 if file has NO 8934b88c807SRodney W. Grimes * data to write after the header, -1 if archive write failed 8944b88c807SRodney W. Grimes */ 8954b88c807SRodney W. Grimes 8964b88c807SRodney W. Grimes int 897f789b261SWarner Losh ustar_wr(ARCHD *arcn) 8984b88c807SRodney W. Grimes { 899f789b261SWarner Losh HD_USTAR *hd; 900f789b261SWarner Losh char *pt; 901c65bb135SRuslan Ermilov HD_USTAR hdblk; 9024b88c807SRodney W. Grimes 9034b88c807SRodney W. Grimes /* 9044b88c807SRodney W. Grimes * check for those file system types ustar cannot store 9054b88c807SRodney W. Grimes */ 9064b88c807SRodney W. Grimes if (arcn->type == PAX_SCK) { 907778766feSKris Kennaway paxwarn(1, "Ustar cannot archive a socket %s", arcn->org_name); 9084b88c807SRodney W. Grimes return(1); 9094b88c807SRodney W. Grimes } 9104b88c807SRodney W. Grimes 9114b88c807SRodney W. Grimes /* 9124b88c807SRodney W. Grimes * check the length of the linkname 9134b88c807SRodney W. Grimes */ 9144b88c807SRodney W. Grimes if (((arcn->type == PAX_SLK) || (arcn->type == PAX_HLK) || 915cee22cbdSDavid E. O'Brien (arcn->type == PAX_HRG)) && 9165512dc54SYaroslav Tykhiy (arcn->ln_nlen > (int)sizeof(hd->linkname))) { 917778766feSKris Kennaway paxwarn(1, "Link name too long for ustar %s", arcn->ln_name); 9184b88c807SRodney W. Grimes return(1); 9194b88c807SRodney W. Grimes } 9204b88c807SRodney W. Grimes 9214b88c807SRodney W. Grimes /* 9224b88c807SRodney W. Grimes * split the path name into prefix and name fields (if needed). if 9234b88c807SRodney W. Grimes * pt != arcn->name, the name has to be split 9244b88c807SRodney W. Grimes */ 9254b88c807SRodney W. Grimes if ((pt = name_split(arcn->name, arcn->nlen)) == NULL) { 926778766feSKris Kennaway paxwarn(1, "File name too long for ustar %s", arcn->name); 9274b88c807SRodney W. Grimes return(1); 9284b88c807SRodney W. Grimes } 929c65bb135SRuslan Ermilov hd = &hdblk; 9304b88c807SRodney W. Grimes arcn->pad = 0L; 9314b88c807SRodney W. Grimes 9324b88c807SRodney W. Grimes /* 9334b88c807SRodney W. Grimes * split the name, or zero out the prefix 9344b88c807SRodney W. Grimes */ 9354b88c807SRodney W. Grimes if (pt != arcn->name) { 9364b88c807SRodney W. Grimes /* 9374b88c807SRodney W. Grimes * name was split, pt points at the / where the split is to 9384b88c807SRodney W. Grimes * occur, we remove the / and copy the first part to the prefix 9394b88c807SRodney W. Grimes */ 9404b88c807SRodney W. Grimes *pt = '\0'; 9415512dc54SYaroslav Tykhiy l_strncpy(hd->prefix, arcn->name, sizeof(hd->prefix)); 9424b88c807SRodney W. Grimes *pt++ = '/'; 9434b88c807SRodney W. Grimes } else 944778766feSKris Kennaway memset(hd->prefix, 0, sizeof(hd->prefix)); 9454b88c807SRodney W. Grimes 9464b88c807SRodney W. Grimes /* 9474b88c807SRodney W. Grimes * copy the name part. this may be the whole path or the part after 9485512dc54SYaroslav Tykhiy * the prefix. both the name and prefix may fill the entire field. 9494b88c807SRodney W. Grimes */ 9505512dc54SYaroslav Tykhiy l_strncpy(hd->name, pt, sizeof(hd->name)); 9514b88c807SRodney W. Grimes 9524b88c807SRodney W. Grimes /* 9534b88c807SRodney W. Grimes * set the fields in the header that are type dependent 9544b88c807SRodney W. Grimes */ 9554b88c807SRodney W. Grimes switch(arcn->type) { 9564b88c807SRodney W. Grimes case PAX_DIR: 9574b88c807SRodney W. Grimes hd->typeflag = DIRTYPE; 958778766feSKris Kennaway memset(hd->linkname, 0, sizeof(hd->linkname)); 959778766feSKris Kennaway memset(hd->devmajor, 0, sizeof(hd->devmajor)); 960778766feSKris Kennaway memset(hd->devminor, 0, sizeof(hd->devminor)); 9614b88c807SRodney W. Grimes if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3)) 9624b88c807SRodney W. Grimes goto out; 9634b88c807SRodney W. Grimes break; 9644b88c807SRodney W. Grimes case PAX_CHR: 9654b88c807SRodney W. Grimes case PAX_BLK: 9664b88c807SRodney W. Grimes if (arcn->type == PAX_CHR) 9674b88c807SRodney W. Grimes hd->typeflag = CHRTYPE; 9684b88c807SRodney W. Grimes else 9694b88c807SRodney W. Grimes hd->typeflag = BLKTYPE; 970778766feSKris Kennaway memset(hd->linkname, 0, sizeof(hd->linkname)); 9714b88c807SRodney W. Grimes if (ul_oct((u_long)MAJOR(arcn->sb.st_rdev), hd->devmajor, 9724b88c807SRodney W. Grimes sizeof(hd->devmajor), 3) || 9734b88c807SRodney W. Grimes ul_oct((u_long)MINOR(arcn->sb.st_rdev), hd->devminor, 9744b88c807SRodney W. Grimes sizeof(hd->devminor), 3) || 9754b88c807SRodney W. Grimes ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3)) 9764b88c807SRodney W. Grimes goto out; 9774b88c807SRodney W. Grimes break; 9784b88c807SRodney W. Grimes case PAX_FIF: 9794b88c807SRodney W. Grimes hd->typeflag = FIFOTYPE; 980778766feSKris Kennaway memset(hd->linkname, 0, sizeof(hd->linkname)); 981778766feSKris Kennaway memset(hd->devmajor, 0, sizeof(hd->devmajor)); 982778766feSKris Kennaway memset(hd->devminor, 0, sizeof(hd->devminor)); 9834b88c807SRodney W. Grimes if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3)) 9844b88c807SRodney W. Grimes goto out; 9854b88c807SRodney W. Grimes break; 9864b88c807SRodney W. Grimes case PAX_SLK: 9874b88c807SRodney W. Grimes case PAX_HLK: 9884b88c807SRodney W. Grimes case PAX_HRG: 9894b88c807SRodney W. Grimes if (arcn->type == PAX_SLK) 9904b88c807SRodney W. Grimes hd->typeflag = SYMTYPE; 9914b88c807SRodney W. Grimes else 9924b88c807SRodney W. Grimes hd->typeflag = LNKTYPE; 9935512dc54SYaroslav Tykhiy /* the link name may occupy the entire field in ustar */ 9945512dc54SYaroslav Tykhiy l_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname)); 995778766feSKris Kennaway memset(hd->devmajor, 0, sizeof(hd->devmajor)); 996778766feSKris Kennaway memset(hd->devminor, 0, sizeof(hd->devminor)); 9974b88c807SRodney W. Grimes if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3)) 9984b88c807SRodney W. Grimes goto out; 9994b88c807SRodney W. Grimes break; 10004b88c807SRodney W. Grimes case PAX_REG: 10014b88c807SRodney W. Grimes case PAX_CTG: 10024b88c807SRodney W. Grimes default: 10034b88c807SRodney W. Grimes /* 10044b88c807SRodney W. Grimes * file data with this type, set the padding 10054b88c807SRodney W. Grimes */ 10064b88c807SRodney W. Grimes if (arcn->type == PAX_CTG) 10074b88c807SRodney W. Grimes hd->typeflag = CONTTYPE; 10084b88c807SRodney W. Grimes else 10094b88c807SRodney W. Grimes hd->typeflag = REGTYPE; 1010778766feSKris Kennaway memset(hd->linkname, 0, sizeof(hd->linkname)); 1011778766feSKris Kennaway memset(hd->devmajor, 0, sizeof(hd->devmajor)); 1012778766feSKris Kennaway memset(hd->devminor, 0, sizeof(hd->devminor)); 10134b88c807SRodney W. Grimes arcn->pad = TAR_PAD(arcn->sb.st_size); 10144b88c807SRodney W. Grimes # ifdef NET2_STAT 10154b88c807SRodney W. Grimes if (ul_oct((u_long)arcn->sb.st_size, hd->size, 10164b88c807SRodney W. Grimes sizeof(hd->size), 3)) { 10174b88c807SRodney W. Grimes # else 10184b88c807SRodney W. Grimes if (uqd_oct((u_quad_t)arcn->sb.st_size, hd->size, 10194b88c807SRodney W. Grimes sizeof(hd->size), 3)) { 10204b88c807SRodney W. Grimes # endif 1021778766feSKris Kennaway paxwarn(1,"File is too long for ustar %s",arcn->org_name); 10224b88c807SRodney W. Grimes return(1); 10234b88c807SRodney W. Grimes } 10244b88c807SRodney W. Grimes break; 10254b88c807SRodney W. Grimes } 10264b88c807SRodney W. Grimes 1027b1787decSKris Kennaway l_strncpy(hd->magic, TMAGIC, TMAGLEN); 1028b1787decSKris Kennaway l_strncpy(hd->version, TVERSION, TVERSLEN); 10294b88c807SRodney W. Grimes 10304b88c807SRodney W. Grimes /* 10314b88c807SRodney W. Grimes * set the remaining fields. Some versions want all 16 bits of mode 10324b88c807SRodney W. Grimes * we better humor them (they really do not meet spec though).... 10334b88c807SRodney W. Grimes */ 10344b88c807SRodney W. Grimes if (ul_oct((u_long)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 3) || 10354b88c807SRodney W. Grimes ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 3) || 10364b88c807SRodney W. Grimes ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 3) || 10374b88c807SRodney W. Grimes ul_oct((u_long)arcn->sb.st_mtime,hd->mtime,sizeof(hd->mtime),3)) 10384b88c807SRodney W. Grimes goto out; 1039b1787decSKris Kennaway l_strncpy(hd->uname,name_uid(arcn->sb.st_uid, 0),sizeof(hd->uname)); 1040b1787decSKris Kennaway l_strncpy(hd->gname,name_gid(arcn->sb.st_gid, 0),sizeof(hd->gname)); 10414b88c807SRodney W. Grimes 10424b88c807SRodney W. Grimes /* 10434b88c807SRodney W. Grimes * calculate and store the checksum write the header to the archive 10444b88c807SRodney W. Grimes * return 0 tells the caller to now write the file data, 1 says no data 10454b88c807SRodney W. Grimes * needs to be written 10464b88c807SRodney W. Grimes */ 1047c65bb135SRuslan Ermilov if (ul_oct(tar_chksm((char *)&hdblk, sizeof(HD_USTAR)), hd->chksum, 10484b88c807SRodney W. Grimes sizeof(hd->chksum), 3)) 10494b88c807SRodney W. Grimes goto out; 1050c65bb135SRuslan Ermilov if (wr_rdbuf((char *)&hdblk, sizeof(HD_USTAR)) < 0) 10514b88c807SRodney W. Grimes return(-1); 10524b88c807SRodney W. Grimes if (wr_skip((off_t)(BLKMULT - sizeof(HD_USTAR))) < 0) 10534b88c807SRodney W. Grimes return(-1); 10544b88c807SRodney W. Grimes if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG)) 10554b88c807SRodney W. Grimes return(0); 10564b88c807SRodney W. Grimes return(1); 10574b88c807SRodney W. Grimes 10584b88c807SRodney W. Grimes out: 10594b88c807SRodney W. Grimes /* 10604b88c807SRodney W. Grimes * header field is out of range 10614b88c807SRodney W. Grimes */ 1062778766feSKris Kennaway paxwarn(1, "Ustar header field is too small for %s", arcn->org_name); 10634b88c807SRodney W. Grimes return(1); 10644b88c807SRodney W. Grimes } 10654b88c807SRodney W. Grimes 10664b88c807SRodney W. Grimes /* 10674b88c807SRodney W. Grimes * name_split() 10684b88c807SRodney W. Grimes * see if the name has to be split for storage in a ustar header. We try 10694b88c807SRodney W. Grimes * to fit the entire name in the name field without splitting if we can. 10704b88c807SRodney W. Grimes * The split point is always at a / 10714b88c807SRodney W. Grimes * Return 10724b88c807SRodney W. Grimes * character pointer to split point (always the / that is to be removed 10734b88c807SRodney W. Grimes * if the split is not needed, the points is set to the start of the file 10744b88c807SRodney W. Grimes * name (it would violate the spec to split there). A NULL is returned if 10754b88c807SRodney W. Grimes * the file name is too long 10764b88c807SRodney W. Grimes */ 10774b88c807SRodney W. Grimes 10784b88c807SRodney W. Grimes static char * 1079f789b261SWarner Losh name_split(char *name, int len) 10804b88c807SRodney W. Grimes { 1081f789b261SWarner Losh char *start; 10824b88c807SRodney W. Grimes 10834b88c807SRodney W. Grimes /* 10844b88c807SRodney W. Grimes * check to see if the file name is small enough to fit in the name 10854b88c807SRodney W. Grimes * field. if so just return a pointer to the name. 10864b88c807SRodney W. Grimes */ 10875512dc54SYaroslav Tykhiy if (len <= TNMSZ) 10884b88c807SRodney W. Grimes return(name); 10895512dc54SYaroslav Tykhiy if (len > (TPFSZ + TNMSZ + 1)) 10904b88c807SRodney W. Grimes return(NULL); 10914b88c807SRodney W. Grimes 10924b88c807SRodney W. Grimes /* 10934b88c807SRodney W. Grimes * we start looking at the biggest sized piece that fits in the name 109446be34b9SKris Kennaway * field. We walk forward looking for a slash to split at. The idea is 10954b88c807SRodney W. Grimes * to find the biggest piece to fit in the name field (or the smallest 10964757e526SMike Smith * prefix we can find) 10974b88c807SRodney W. Grimes */ 10985512dc54SYaroslav Tykhiy start = name + len - TNMSZ - 1; 10994b88c807SRodney W. Grimes while ((*start != '\0') && (*start != '/')) 11004b88c807SRodney W. Grimes ++start; 11014b88c807SRodney W. Grimes 11024b88c807SRodney W. Grimes /* 11034b88c807SRodney W. Grimes * if we hit the end of the string, this name cannot be split, so we 11044b88c807SRodney W. Grimes * cannot store this file. 11054b88c807SRodney W. Grimes */ 11064b88c807SRodney W. Grimes if (*start == '\0') 11074b88c807SRodney W. Grimes return(NULL); 11084b88c807SRodney W. Grimes len = start - name; 11094b88c807SRodney W. Grimes 11104b88c807SRodney W. Grimes /* 11114b88c807SRodney W. Grimes * NOTE: /str where the length of str == TNMSZ can not be stored under 11124b88c807SRodney W. Grimes * the p1003.1-1990 spec for ustar. We could force a prefix of / and 11134b88c807SRodney W. Grimes * the file would then expand on extract to //str. The len == 0 below 11144b88c807SRodney W. Grimes * makes this special case follow the spec to the letter. 11154b88c807SRodney W. Grimes */ 11165512dc54SYaroslav Tykhiy if ((len > TPFSZ) || (len == 0)) 11174b88c807SRodney W. Grimes return(NULL); 11184b88c807SRodney W. Grimes 11194b88c807SRodney W. Grimes /* 11204b88c807SRodney W. Grimes * ok have a split point, return it to the caller 11214b88c807SRodney W. Grimes */ 11224b88c807SRodney W. Grimes return(start); 11234b88c807SRodney W. Grimes } 1124