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 * 3. All advertising materials mentioning features or use of this software 184b88c807SRodney W. Grimes * must display the following acknowledgement: 194b88c807SRodney W. Grimes * This product includes software developed by the University of 204b88c807SRodney W. Grimes * California, Berkeley and its contributors. 214b88c807SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 224b88c807SRodney W. Grimes * may be used to endorse or promote products derived from this software 234b88c807SRodney W. Grimes * without specific prior written permission. 244b88c807SRodney W. Grimes * 254b88c807SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 264b88c807SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 274b88c807SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 284b88c807SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 294b88c807SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 304b88c807SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 314b88c807SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 324b88c807SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 334b88c807SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 344b88c807SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 354b88c807SRodney W. Grimes * SUCH DAMAGE. 364b88c807SRodney W. Grimes */ 374b88c807SRodney W. Grimes 384b88c807SRodney W. Grimes #ifndef lint 39c9a8d1f4SPhilippe Charnier #if 0 40c9a8d1f4SPhilippe Charnier static char sccsid[] = "@(#)tar.c 8.2 (Berkeley) 4/18/94"; 41c9a8d1f4SPhilippe Charnier #endif 42c9a8d1f4SPhilippe Charnier static const char rcsid[] = 432a456239SPeter Wemm "$FreeBSD$"; 444b88c807SRodney W. Grimes #endif /* not lint */ 454b88c807SRodney W. Grimes 464b88c807SRodney W. Grimes #include <sys/types.h> 474b88c807SRodney W. Grimes #include <sys/time.h> 484b88c807SRodney W. Grimes #include <sys/stat.h> 494b88c807SRodney W. Grimes #include <string.h> 504b88c807SRodney W. Grimes #include <stdio.h> 514b88c807SRodney W. Grimes #include <unistd.h> 524b88c807SRodney W. Grimes #include <stdlib.h> 534b88c807SRodney W. Grimes #include "pax.h" 544b88c807SRodney W. Grimes #include "extern.h" 554b88c807SRodney W. Grimes #include "tar.h" 564b88c807SRodney W. Grimes 574b88c807SRodney W. Grimes /* 584b88c807SRodney W. Grimes * Routines for reading, writing and header identify of various versions of tar 594b88c807SRodney W. Grimes */ 604b88c807SRodney W. Grimes 614b88c807SRodney W. Grimes static u_long tar_chksm __P((register char *, register int)); 624b88c807SRodney W. Grimes static char *name_split __P((register char *, register int)); 634b88c807SRodney W. Grimes static int ul_oct __P((u_long, register char *, register int, int)); 644b88c807SRodney W. Grimes #ifndef NET2_STAT 654b88c807SRodney W. Grimes static int uqd_oct __P((u_quad_t, register char *, register int, int)); 664b88c807SRodney W. Grimes #endif 674b88c807SRodney W. Grimes 684b88c807SRodney W. Grimes /* 694b88c807SRodney W. Grimes * Routines common to all versions of tar 704b88c807SRodney W. Grimes */ 714b88c807SRodney W. Grimes 724b88c807SRodney W. Grimes static int tar_nodir; /* do not write dirs under old tar */ 734b88c807SRodney W. Grimes 744b88c807SRodney W. Grimes /* 754b88c807SRodney W. Grimes * tar_endwr() 764b88c807SRodney W. Grimes * add the tar trailer of two null blocks 774b88c807SRodney W. Grimes * Return: 784b88c807SRodney W. Grimes * 0 if ok, -1 otherwise (what wr_skip returns) 794b88c807SRodney W. Grimes */ 804b88c807SRodney W. Grimes 81778766feSKris Kennaway #ifdef __STDC__ 824b88c807SRodney W. Grimes int 834b88c807SRodney W. Grimes tar_endwr(void) 844b88c807SRodney W. Grimes #else 854b88c807SRodney W. Grimes int 864b88c807SRodney W. Grimes tar_endwr() 874b88c807SRodney W. Grimes #endif 884b88c807SRodney W. Grimes { 894b88c807SRodney W. Grimes return(wr_skip((off_t)(NULLCNT*BLKMULT))); 904b88c807SRodney W. Grimes } 914b88c807SRodney W. Grimes 924b88c807SRodney W. Grimes /* 934b88c807SRodney W. Grimes * tar_endrd() 944b88c807SRodney W. Grimes * no cleanup needed here, just return size of trailer (for append) 954b88c807SRodney W. Grimes * Return: 964b88c807SRodney W. Grimes * size of trailer (2 * BLKMULT) 974b88c807SRodney W. Grimes */ 984b88c807SRodney W. Grimes 99778766feSKris Kennaway #ifdef __STDC__ 1004b88c807SRodney W. Grimes off_t 1014b88c807SRodney W. Grimes tar_endrd(void) 1024b88c807SRodney W. Grimes #else 1034b88c807SRodney W. Grimes off_t 1044b88c807SRodney W. Grimes tar_endrd() 1054b88c807SRodney W. Grimes #endif 1064b88c807SRodney W. Grimes { 1074b88c807SRodney W. Grimes return((off_t)(NULLCNT*BLKMULT)); 1084b88c807SRodney W. Grimes } 1094b88c807SRodney W. Grimes 1104b88c807SRodney W. Grimes /* 1114b88c807SRodney W. Grimes * tar_trail() 1124b88c807SRodney W. Grimes * Called to determine if a header block is a valid trailer. We are passed 1134b88c807SRodney W. Grimes * the block, the in_sync flag (which tells us we are in resync mode; 1144b88c807SRodney W. Grimes * looking for a valid header), and cnt (which starts at zero) which is 1154b88c807SRodney W. Grimes * used to count the number of empty blocks we have seen so far. 1164b88c807SRodney W. Grimes * Return: 1174b88c807SRodney W. Grimes * 0 if a valid trailer, -1 if not a valid trailer, or 1 if the block 1184b88c807SRodney W. Grimes * could never contain a header. 1194b88c807SRodney W. Grimes */ 1204b88c807SRodney W. Grimes 121778766feSKris Kennaway #ifdef __STDC__ 1224b88c807SRodney W. Grimes int 1234b88c807SRodney W. Grimes tar_trail(register char *buf, register int in_resync, register int *cnt) 1244b88c807SRodney W. Grimes #else 1254b88c807SRodney W. Grimes int 1264b88c807SRodney W. Grimes tar_trail(buf, in_resync, cnt) 1274b88c807SRodney W. Grimes register char *buf; 1284b88c807SRodney W. Grimes register int in_resync; 1294b88c807SRodney W. Grimes register int *cnt; 1304b88c807SRodney W. Grimes #endif 1314b88c807SRodney W. Grimes { 1324b88c807SRodney W. Grimes register int i; 1334b88c807SRodney W. Grimes 1344b88c807SRodney W. Grimes /* 1354b88c807SRodney W. Grimes * look for all zero, trailer is two consecutive blocks of zero 1364b88c807SRodney W. Grimes */ 1374b88c807SRodney W. Grimes for (i = 0; i < BLKMULT; ++i) { 1384b88c807SRodney W. Grimes if (buf[i] != '\0') 1394b88c807SRodney W. Grimes break; 1404b88c807SRodney W. Grimes } 1414b88c807SRodney W. Grimes 1424b88c807SRodney W. Grimes /* 1434b88c807SRodney W. Grimes * if not all zero it is not a trailer, but MIGHT be a header. 1444b88c807SRodney W. Grimes */ 1454b88c807SRodney W. Grimes if (i != BLKMULT) 1464b88c807SRodney W. Grimes return(-1); 1474b88c807SRodney W. Grimes 1484b88c807SRodney W. Grimes /* 1494b88c807SRodney W. Grimes * When given a zero block, we must be careful! 1504b88c807SRodney W. Grimes * If we are not in resync mode, check for the trailer. Have to watch 1514b88c807SRodney W. Grimes * out that we do not mis-identify file data as the trailer, so we do 1524b88c807SRodney W. Grimes * NOT try to id a trailer during resync mode. During resync mode we 1534b88c807SRodney W. Grimes * might as well throw this block out since a valid header can NEVER be 1544b88c807SRodney W. Grimes * a block of all 0 (we must have a valid file name). 1554b88c807SRodney W. Grimes */ 1564b88c807SRodney W. Grimes if (!in_resync && (++*cnt >= NULLCNT)) 1574b88c807SRodney W. Grimes return(0); 1584b88c807SRodney W. Grimes return(1); 1594b88c807SRodney W. Grimes } 1604b88c807SRodney W. Grimes 1614b88c807SRodney W. Grimes /* 1624b88c807SRodney W. Grimes * ul_oct() 1634b88c807SRodney W. Grimes * convert an unsigned long to an octal string. many oddball field 1644b88c807SRodney W. Grimes * termination characters are used by the various versions of tar in the 165b1787decSKris Kennaway * different fields. term selects which kind to use. str is '0' padded 1664b88c807SRodney W. Grimes * at the front to len. we are unable to use only one format as many old 1674b88c807SRodney W. Grimes * tar readers are very cranky about this. 1684b88c807SRodney W. Grimes * Return: 1694b88c807SRodney W. Grimes * 0 if the number fit into the string, -1 otherwise 1704b88c807SRodney W. Grimes */ 1714b88c807SRodney W. Grimes 172778766feSKris Kennaway #ifdef __STDC__ 1734b88c807SRodney W. Grimes static int 1744b88c807SRodney W. Grimes ul_oct(u_long val, register char *str, register int len, int term) 1754b88c807SRodney W. Grimes #else 1764b88c807SRodney W. Grimes static int 1774b88c807SRodney W. Grimes ul_oct(val, str, len, term) 1784b88c807SRodney W. Grimes u_long val; 1794b88c807SRodney W. Grimes register char *str; 1804b88c807SRodney W. Grimes register int len; 1814b88c807SRodney W. Grimes int term; 1824b88c807SRodney W. Grimes #endif 1834b88c807SRodney W. Grimes { 1844b88c807SRodney W. Grimes register char *pt; 1854b88c807SRodney W. Grimes 1864b88c807SRodney W. Grimes /* 1874b88c807SRodney W. Grimes * term selects the appropriate character(s) for the end of the string 1884b88c807SRodney W. Grimes */ 1894b88c807SRodney W. Grimes pt = str + len - 1; 1904b88c807SRodney W. Grimes switch(term) { 1914b88c807SRodney W. Grimes case 3: 1924b88c807SRodney W. Grimes *pt-- = '\0'; 1934b88c807SRodney W. Grimes break; 1944b88c807SRodney W. Grimes case 2: 1954b88c807SRodney W. Grimes *pt-- = ' '; 1964b88c807SRodney W. Grimes *pt-- = '\0'; 1974b88c807SRodney W. Grimes break; 1984b88c807SRodney W. Grimes case 1: 1994b88c807SRodney W. Grimes *pt-- = ' '; 2004b88c807SRodney W. Grimes break; 2014b88c807SRodney W. Grimes case 0: 2024b88c807SRodney W. Grimes default: 2034b88c807SRodney W. Grimes *pt-- = '\0'; 2044b88c807SRodney W. Grimes *pt-- = ' '; 2054b88c807SRodney W. Grimes break; 2064b88c807SRodney W. Grimes } 2074b88c807SRodney W. Grimes 2084b88c807SRodney W. Grimes /* 2094b88c807SRodney W. Grimes * convert and blank pad if there is space 2104b88c807SRodney W. Grimes */ 2114b88c807SRodney W. Grimes while (pt >= str) { 2124b88c807SRodney W. Grimes *pt-- = '0' + (char)(val & 0x7); 2134b88c807SRodney W. Grimes if ((val = val >> 3) == (u_long)0) 2144b88c807SRodney W. Grimes break; 2154b88c807SRodney W. Grimes } 2164b88c807SRodney W. Grimes 2174b88c807SRodney W. Grimes while (pt >= str) 218b1787decSKris Kennaway *pt-- = '0'; 2194b88c807SRodney W. Grimes if (val != (u_long)0) 2204b88c807SRodney W. Grimes return(-1); 2214b88c807SRodney W. Grimes return(0); 2224b88c807SRodney W. Grimes } 2234b88c807SRodney W. Grimes 2244b88c807SRodney W. Grimes #ifndef NET2_STAT 2254b88c807SRodney W. Grimes /* 2264b88c807SRodney W. Grimes * uqd_oct() 2274b88c807SRodney W. Grimes * convert an u_quad_t to an octal string. one of many oddball field 2284b88c807SRodney W. Grimes * termination characters are used by the various versions of tar in the 229b1787decSKris Kennaway * different fields. term selects which kind to use. str is '0' padded 2304b88c807SRodney W. Grimes * at the front to len. we are unable to use only one format as many old 2314b88c807SRodney W. Grimes * tar readers are very cranky about this. 2324b88c807SRodney W. Grimes * Return: 2334b88c807SRodney W. Grimes * 0 if the number fit into the string, -1 otherwise 2344b88c807SRodney W. Grimes */ 2354b88c807SRodney W. Grimes 236778766feSKris Kennaway #ifdef __STDC__ 2374b88c807SRodney W. Grimes static int 2384b88c807SRodney W. Grimes uqd_oct(u_quad_t val, register char *str, register int len, int term) 2394b88c807SRodney W. Grimes #else 2404b88c807SRodney W. Grimes static int 2414b88c807SRodney W. Grimes uqd_oct(val, str, len, term) 2424b88c807SRodney W. Grimes u_quad_t val; 2434b88c807SRodney W. Grimes register char *str; 2444b88c807SRodney W. Grimes register int len; 2454b88c807SRodney W. Grimes int term; 2464b88c807SRodney W. Grimes #endif 2474b88c807SRodney W. Grimes { 2484b88c807SRodney W. Grimes register char *pt; 2494b88c807SRodney W. Grimes 2504b88c807SRodney W. Grimes /* 2514b88c807SRodney W. Grimes * term selects the appropriate character(s) for the end of the string 2524b88c807SRodney W. Grimes */ 2534b88c807SRodney W. Grimes pt = str + len - 1; 2544b88c807SRodney W. Grimes switch(term) { 2554b88c807SRodney W. Grimes case 3: 2564b88c807SRodney W. Grimes *pt-- = '\0'; 2574b88c807SRodney W. Grimes break; 2584b88c807SRodney W. Grimes case 2: 2594b88c807SRodney W. Grimes *pt-- = ' '; 2604b88c807SRodney W. Grimes *pt-- = '\0'; 2614b88c807SRodney W. Grimes break; 2624b88c807SRodney W. Grimes case 1: 2634b88c807SRodney W. Grimes *pt-- = ' '; 2644b88c807SRodney W. Grimes break; 2654b88c807SRodney W. Grimes case 0: 2664b88c807SRodney W. Grimes default: 2674b88c807SRodney W. Grimes *pt-- = '\0'; 2684b88c807SRodney W. Grimes *pt-- = ' '; 2694b88c807SRodney W. Grimes break; 2704b88c807SRodney W. Grimes } 2714b88c807SRodney W. Grimes 2724b88c807SRodney W. Grimes /* 2734b88c807SRodney W. Grimes * convert and blank pad if there is space 2744b88c807SRodney W. Grimes */ 2754b88c807SRodney W. Grimes while (pt >= str) { 2764b88c807SRodney W. Grimes *pt-- = '0' + (char)(val & 0x7); 2774b88c807SRodney W. Grimes if ((val = val >> 3) == 0) 2784b88c807SRodney W. Grimes break; 2794b88c807SRodney W. Grimes } 2804b88c807SRodney W. Grimes 2814b88c807SRodney W. Grimes while (pt >= str) 282b1787decSKris Kennaway *pt-- = '0'; 2834b88c807SRodney W. Grimes if (val != (u_quad_t)0) 2844b88c807SRodney W. Grimes return(-1); 2854b88c807SRodney W. Grimes return(0); 2864b88c807SRodney W. Grimes } 2874b88c807SRodney W. Grimes #endif 2884b88c807SRodney W. Grimes 2894b88c807SRodney W. Grimes /* 2904b88c807SRodney W. Grimes * tar_chksm() 2914b88c807SRodney W. Grimes * calculate the checksum for a tar block counting the checksum field as 29246be34b9SKris Kennaway * all blanks (BLNKSUM is that value pre-calculated, the sum of 8 blanks). 2934b88c807SRodney W. Grimes * NOTE: we use len to short circuit summing 0's on write since we ALWAYS 2944b88c807SRodney W. Grimes * pad headers with 0. 2954b88c807SRodney W. Grimes * Return: 2964b88c807SRodney W. Grimes * unsigned long checksum 2974b88c807SRodney W. Grimes */ 2984b88c807SRodney W. Grimes 299778766feSKris Kennaway #ifdef __STDC__ 3004b88c807SRodney W. Grimes static u_long 3014b88c807SRodney W. Grimes tar_chksm(register char *blk, register int len) 3024b88c807SRodney W. Grimes #else 3034b88c807SRodney W. Grimes static u_long 3044b88c807SRodney W. Grimes tar_chksm(blk, len) 3054b88c807SRodney W. Grimes register char *blk; 3064b88c807SRodney W. Grimes register int len; 3074b88c807SRodney W. Grimes #endif 3084b88c807SRodney W. Grimes { 3094b88c807SRodney W. Grimes register char *stop; 3104b88c807SRodney W. Grimes register char *pt; 31146be34b9SKris Kennaway u_long chksm = BLNKSUM; /* initial value is checksum field sum */ 3124b88c807SRodney W. Grimes 3134b88c807SRodney W. Grimes /* 3144b88c807SRodney W. Grimes * add the part of the block before the checksum field 3154b88c807SRodney W. Grimes */ 3164b88c807SRodney W. Grimes pt = blk; 3174b88c807SRodney W. Grimes stop = blk + CHK_OFFSET; 3184b88c807SRodney W. Grimes while (pt < stop) 3194b88c807SRodney W. Grimes chksm += (u_long)(*pt++ & 0xff); 3204b88c807SRodney W. Grimes /* 3214b88c807SRodney W. Grimes * move past the checksum field and keep going, spec counts the 3224b88c807SRodney W. Grimes * checksum field as the sum of 8 blanks (which is pre-computed as 3234b88c807SRodney W. Grimes * BLNKSUM). 3244b88c807SRodney W. Grimes * ASSUMED: len is greater than CHK_OFFSET. (len is where our 0 padding 3254b88c807SRodney W. Grimes * starts, no point in summing zero's) 3264b88c807SRodney W. Grimes */ 3274b88c807SRodney W. Grimes pt += CHK_LEN; 3284b88c807SRodney W. Grimes stop = blk + len; 3294b88c807SRodney W. Grimes while (pt < stop) 3304b88c807SRodney W. Grimes chksm += (u_long)(*pt++ & 0xff); 3314b88c807SRodney W. Grimes return(chksm); 3324b88c807SRodney W. Grimes } 3334b88c807SRodney W. Grimes 3344b88c807SRodney W. Grimes /* 3354b88c807SRodney W. Grimes * Routines for old BSD style tar (also made portable to sysV tar) 3364b88c807SRodney W. Grimes */ 3374b88c807SRodney W. Grimes 3384b88c807SRodney W. Grimes /* 3394b88c807SRodney W. Grimes * tar_id() 3404b88c807SRodney W. Grimes * determine if a block given to us is a valid tar header (and not a USTAR 3414b88c807SRodney W. Grimes * header). We have to be on the lookout for those pesky blocks of all 3424b88c807SRodney W. Grimes * zero's. 3434b88c807SRodney W. Grimes * Return: 3444b88c807SRodney W. Grimes * 0 if a tar header, -1 otherwise 3454b88c807SRodney W. Grimes */ 3464b88c807SRodney W. Grimes 347778766feSKris Kennaway #ifdef __STDC__ 3484b88c807SRodney W. Grimes int 3494b88c807SRodney W. Grimes tar_id(register char *blk, int size) 3504b88c807SRodney W. Grimes #else 3514b88c807SRodney W. Grimes int 3524b88c807SRodney W. Grimes tar_id(blk, size) 3534b88c807SRodney W. Grimes register char *blk; 3544b88c807SRodney W. Grimes int size; 3554b88c807SRodney W. Grimes #endif 3564b88c807SRodney W. Grimes { 3574b88c807SRodney W. Grimes register HD_TAR *hd; 3584b88c807SRodney W. Grimes register HD_USTAR *uhd; 3594b88c807SRodney W. Grimes 3604b88c807SRodney W. Grimes if (size < BLKMULT) 3614b88c807SRodney W. Grimes return(-1); 3624b88c807SRodney W. Grimes hd = (HD_TAR *)blk; 3634b88c807SRodney W. Grimes uhd = (HD_USTAR *)blk; 3644b88c807SRodney W. Grimes 3654b88c807SRodney W. Grimes /* 3664b88c807SRodney W. Grimes * check for block of zero's first, a simple and fast test, then make 3674b88c807SRodney W. Grimes * sure this is not a ustar header by looking for the ustar magic 3684b88c807SRodney W. Grimes * cookie. We should use TMAGLEN, but some USTAR archive programs are 3694b88c807SRodney W. Grimes * wrong and create archives missing the \0. Last we check the 3704b88c807SRodney W. Grimes * checksum. If this is ok we have to assume it is a valid header. 3714b88c807SRodney W. Grimes */ 3724b88c807SRodney W. Grimes if (hd->name[0] == '\0') 3734b88c807SRodney W. Grimes return(-1); 3744b88c807SRodney W. Grimes if (strncmp(uhd->magic, TMAGIC, TMAGLEN - 1) == 0) 3754b88c807SRodney W. Grimes return(-1); 3764b88c807SRodney W. Grimes if (asc_ul(hd->chksum,sizeof(hd->chksum),OCT) != tar_chksm(blk,BLKMULT)) 3774b88c807SRodney W. Grimes return(-1); 3784b88c807SRodney W. Grimes return(0); 3794b88c807SRodney W. Grimes } 3804b88c807SRodney W. Grimes 3814b88c807SRodney W. Grimes /* 3824b88c807SRodney W. Grimes * tar_opt() 3834b88c807SRodney W. Grimes * handle tar format specific -o options 3844b88c807SRodney W. Grimes * Return: 3854b88c807SRodney W. Grimes * 0 if ok -1 otherwise 3864b88c807SRodney W. Grimes */ 3874b88c807SRodney W. Grimes 388778766feSKris Kennaway #ifdef __STDC__ 3894b88c807SRodney W. Grimes int 3904b88c807SRodney W. Grimes tar_opt(void) 3914b88c807SRodney W. Grimes #else 3924b88c807SRodney W. Grimes int 3934b88c807SRodney W. Grimes tar_opt() 3944b88c807SRodney W. Grimes #endif 3954b88c807SRodney W. Grimes { 3964b88c807SRodney W. Grimes OPLIST *opt; 3974b88c807SRodney W. Grimes 3984b88c807SRodney W. Grimes while ((opt = opt_next()) != NULL) { 3994b88c807SRodney W. Grimes if (strcmp(opt->name, TAR_OPTION) || 4004b88c807SRodney W. Grimes strcmp(opt->value, TAR_NODIR)) { 401778766feSKris Kennaway paxwarn(1, "Unknown tar format -o option/value pair %s=%s", 4024b88c807SRodney W. Grimes opt->name, opt->value); 403778766feSKris Kennaway paxwarn(1,"%s=%s is the only supported tar format option", 4044b88c807SRodney W. Grimes TAR_OPTION, TAR_NODIR); 4054b88c807SRodney W. Grimes return(-1); 4064b88c807SRodney W. Grimes } 4074b88c807SRodney W. Grimes 4084b88c807SRodney W. Grimes /* 4094b88c807SRodney W. Grimes * we only support one option, and only when writing 4104b88c807SRodney W. Grimes */ 4114b88c807SRodney W. Grimes if ((act != APPND) && (act != ARCHIVE)) { 412778766feSKris Kennaway paxwarn(1, "%s=%s is only supported when writing.", 4134b88c807SRodney W. Grimes opt->name, opt->value); 4144b88c807SRodney W. Grimes return(-1); 4154b88c807SRodney W. Grimes } 4164b88c807SRodney W. Grimes tar_nodir = 1; 4174b88c807SRodney W. Grimes } 4184b88c807SRodney W. Grimes return(0); 4194b88c807SRodney W. Grimes } 4204b88c807SRodney W. Grimes 4214b88c807SRodney W. Grimes 4224b88c807SRodney W. Grimes /* 4234b88c807SRodney W. Grimes * tar_rd() 4244b88c807SRodney W. Grimes * extract the values out of block already determined to be a tar header. 4254b88c807SRodney W. Grimes * store the values in the ARCHD parameter. 4264b88c807SRodney W. Grimes * Return: 4274b88c807SRodney W. Grimes * 0 4284b88c807SRodney W. Grimes */ 4294b88c807SRodney W. Grimes 430778766feSKris Kennaway #ifdef __STDC__ 4314b88c807SRodney W. Grimes int 4324b88c807SRodney W. Grimes tar_rd(register ARCHD *arcn, register char *buf) 4334b88c807SRodney W. Grimes #else 4344b88c807SRodney W. Grimes int 4354b88c807SRodney W. Grimes tar_rd(arcn, buf) 4364b88c807SRodney W. Grimes register ARCHD *arcn; 4374b88c807SRodney W. Grimes register char *buf; 4384b88c807SRodney W. Grimes #endif 4394b88c807SRodney W. Grimes { 4404b88c807SRodney W. Grimes register HD_TAR *hd; 4414b88c807SRodney W. Grimes register char *pt; 4424b88c807SRodney W. Grimes 4434b88c807SRodney W. Grimes /* 4444b88c807SRodney W. Grimes * we only get proper sized buffers passed to us 4454b88c807SRodney W. Grimes */ 4464b88c807SRodney W. Grimes if (tar_id(buf, BLKMULT) < 0) 4474b88c807SRodney W. Grimes return(-1); 4484b88c807SRodney W. Grimes arcn->org_name = arcn->name; 4494b88c807SRodney W. Grimes arcn->sb.st_nlink = 1; 4504b88c807SRodney W. Grimes arcn->pat = NULL; 4514b88c807SRodney W. Grimes 4524b88c807SRodney W. Grimes /* 4534b88c807SRodney W. Grimes * copy out the name and values in the stat buffer 4544b88c807SRodney W. Grimes */ 4554b88c807SRodney W. Grimes hd = (HD_TAR *)buf; 456b1787decSKris Kennaway arcn->nlen = l_strncpy(arcn->name, hd->name, sizeof(arcn->name) - 1); 4574b88c807SRodney W. Grimes arcn->name[arcn->nlen] = '\0'; 4584b88c807SRodney W. Grimes arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode,sizeof(hd->mode),OCT) & 4594b88c807SRodney W. Grimes 0xfff); 4604b88c807SRodney W. Grimes arcn->sb.st_uid = (uid_t)asc_ul(hd->uid, sizeof(hd->uid), OCT); 4614b88c807SRodney W. Grimes arcn->sb.st_gid = (gid_t)asc_ul(hd->gid, sizeof(hd->gid), OCT); 462b1787decSKris Kennaway #ifdef NET2_STAT 463b1787decSKris Kennaway arcn->sb.st_size = (off_t)asc_ul(hd->size, sizeof(hd->size), OCT); 464b1787decSKris Kennaway #else 465b1787decSKris Kennaway arcn->sb.st_size = (off_t)asc_uqd(hd->size, sizeof(hd->size), OCT); 466b1787decSKris Kennaway #endif 4674b88c807SRodney W. Grimes arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT); 4684b88c807SRodney W. Grimes arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime; 4694b88c807SRodney W. Grimes 4704b88c807SRodney W. Grimes /* 4714b88c807SRodney W. Grimes * have to look at the last character, it may be a '/' and that is used 4724b88c807SRodney W. Grimes * to encode this as a directory 4734b88c807SRodney W. Grimes */ 4744b88c807SRodney W. Grimes pt = &(arcn->name[arcn->nlen - 1]); 4754b88c807SRodney W. Grimes arcn->pad = 0; 4764b88c807SRodney W. Grimes arcn->skip = 0; 4774b88c807SRodney W. Grimes switch(hd->linkflag) { 4784b88c807SRodney W. Grimes case SYMTYPE: 4794b88c807SRodney W. Grimes /* 4804b88c807SRodney W. Grimes * symbolic link, need to get the link name and set the type in 4814b88c807SRodney W. Grimes * the st_mode so -v printing will look correct. 4824b88c807SRodney W. Grimes */ 4834b88c807SRodney W. Grimes arcn->type = PAX_SLK; 4844b88c807SRodney W. Grimes arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname, 485b1787decSKris Kennaway sizeof(arcn->ln_name) - 1); 4864b88c807SRodney W. Grimes arcn->ln_name[arcn->ln_nlen] = '\0'; 4874b88c807SRodney W. Grimes arcn->sb.st_mode |= S_IFLNK; 4884b88c807SRodney W. Grimes break; 4894b88c807SRodney W. Grimes case LNKTYPE: 4904b88c807SRodney W. Grimes /* 4914b88c807SRodney W. Grimes * hard link, need to get the link name, set the type in the 4924b88c807SRodney W. Grimes * st_mode and st_nlink so -v printing will look better. 4934b88c807SRodney W. Grimes */ 4944b88c807SRodney W. Grimes arcn->type = PAX_HLK; 4954b88c807SRodney W. Grimes arcn->sb.st_nlink = 2; 4964b88c807SRodney W. Grimes arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname, 497b1787decSKris Kennaway sizeof(arcn->ln_name) - 1); 4984b88c807SRodney W. Grimes arcn->ln_name[arcn->ln_nlen] = '\0'; 4994b88c807SRodney W. Grimes 5004b88c807SRodney W. Grimes /* 5014b88c807SRodney W. Grimes * no idea of what type this thing really points at, but 5024b88c807SRodney W. Grimes * we set something for printing only. 5034b88c807SRodney W. Grimes */ 5044b88c807SRodney W. Grimes arcn->sb.st_mode |= S_IFREG; 5054b88c807SRodney W. Grimes break; 506b1787decSKris Kennaway case DIRTYPE: 507b1787decSKris Kennaway /* 508b1787decSKris Kennaway * It is a directory, set the mode for -v printing 509b1787decSKris Kennaway */ 510b1787decSKris Kennaway arcn->type = PAX_DIR; 511b1787decSKris Kennaway arcn->sb.st_mode |= S_IFDIR; 512b1787decSKris Kennaway arcn->sb.st_nlink = 2; 513b1787decSKris Kennaway arcn->ln_name[0] = '\0'; 514b1787decSKris Kennaway arcn->ln_nlen = 0; 515b1787decSKris Kennaway break; 5164b88c807SRodney W. Grimes case AREGTYPE: 5174b88c807SRodney W. Grimes case REGTYPE: 5184b88c807SRodney W. Grimes default: 5194b88c807SRodney W. Grimes /* 5204b88c807SRodney W. Grimes * If we have a trailing / this is a directory and NOT a file. 5214b88c807SRodney W. Grimes */ 5224b88c807SRodney W. Grimes arcn->ln_name[0] = '\0'; 5234b88c807SRodney W. Grimes arcn->ln_nlen = 0; 5244b88c807SRodney W. Grimes if (*pt == '/') { 5254b88c807SRodney W. Grimes /* 5264b88c807SRodney W. Grimes * it is a directory, set the mode for -v printing 5274b88c807SRodney W. Grimes */ 5284b88c807SRodney W. Grimes arcn->type = PAX_DIR; 5294b88c807SRodney W. Grimes arcn->sb.st_mode |= S_IFDIR; 5304b88c807SRodney W. Grimes arcn->sb.st_nlink = 2; 5314b88c807SRodney W. Grimes } else { 5324b88c807SRodney W. Grimes /* 5334b88c807SRodney W. Grimes * have a file that will be followed by data. Set the 53446be34b9SKris Kennaway * skip value to the size field and calculate the size 5354b88c807SRodney W. Grimes * of the padding. 5364b88c807SRodney W. Grimes */ 5374b88c807SRodney W. Grimes arcn->type = PAX_REG; 5384b88c807SRodney W. Grimes arcn->sb.st_mode |= S_IFREG; 5394b88c807SRodney W. Grimes arcn->pad = TAR_PAD(arcn->sb.st_size); 5404b88c807SRodney W. Grimes arcn->skip = arcn->sb.st_size; 5414b88c807SRodney W. Grimes } 5424b88c807SRodney W. Grimes break; 5434b88c807SRodney W. Grimes } 5444b88c807SRodney W. Grimes 5454b88c807SRodney W. Grimes /* 5464b88c807SRodney W. Grimes * strip off any trailing slash. 5474b88c807SRodney W. Grimes */ 5484b88c807SRodney W. Grimes if (*pt == '/') { 5494b88c807SRodney W. Grimes *pt = '\0'; 5504b88c807SRodney W. Grimes --arcn->nlen; 5514b88c807SRodney W. Grimes } 5524b88c807SRodney W. Grimes return(0); 5534b88c807SRodney W. Grimes } 5544b88c807SRodney W. Grimes 5554b88c807SRodney W. Grimes /* 5564b88c807SRodney W. Grimes * tar_wr() 5574b88c807SRodney W. Grimes * write a tar header for the file specified in the ARCHD to the archive. 5584b88c807SRodney W. Grimes * Have to check for file types that cannot be stored and file names that 5594b88c807SRodney W. Grimes * are too long. Be careful of the term (last arg) to ul_oct, each field 5604b88c807SRodney W. Grimes * of tar has it own spec for the termination character(s). 5614b88c807SRodney W. Grimes * ASSUMED: space after header in header block is zero filled 5624b88c807SRodney W. Grimes * Return: 5634b88c807SRodney W. Grimes * 0 if file has data to be written after the header, 1 if file has NO 5644b88c807SRodney W. Grimes * data to write after the header, -1 if archive write failed 5654b88c807SRodney W. Grimes */ 5664b88c807SRodney W. Grimes 567778766feSKris Kennaway #ifdef __STDC__ 5684b88c807SRodney W. Grimes int 5694b88c807SRodney W. Grimes tar_wr(register ARCHD *arcn) 5704b88c807SRodney W. Grimes #else 5714b88c807SRodney W. Grimes int 5724b88c807SRodney W. Grimes tar_wr(arcn) 5734b88c807SRodney W. Grimes register ARCHD *arcn; 5744b88c807SRodney W. Grimes #endif 5754b88c807SRodney W. Grimes { 5764b88c807SRodney W. Grimes register HD_TAR *hd; 5774b88c807SRodney W. Grimes int len; 5784b88c807SRodney W. Grimes char hdblk[sizeof(HD_TAR)]; 5794b88c807SRodney W. Grimes 5804b88c807SRodney W. Grimes /* 5814b88c807SRodney W. Grimes * check for those file system types which tar cannot store 5824b88c807SRodney W. Grimes */ 5834b88c807SRodney W. Grimes switch(arcn->type) { 5844b88c807SRodney W. Grimes case PAX_DIR: 5854b88c807SRodney W. Grimes /* 5864b88c807SRodney W. Grimes * user asked that dirs not be written to the archive 5874b88c807SRodney W. Grimes */ 5884b88c807SRodney W. Grimes if (tar_nodir) 5894b88c807SRodney W. Grimes return(1); 5904b88c807SRodney W. Grimes break; 5914b88c807SRodney W. Grimes case PAX_CHR: 592778766feSKris Kennaway paxwarn(1, "Tar cannot archive a character device %s", 5934b88c807SRodney W. Grimes arcn->org_name); 5944b88c807SRodney W. Grimes return(1); 5954b88c807SRodney W. Grimes case PAX_BLK: 596778766feSKris Kennaway paxwarn(1, "Tar cannot archive a block device %s", arcn->org_name); 5974b88c807SRodney W. Grimes return(1); 5984b88c807SRodney W. Grimes case PAX_SCK: 599778766feSKris Kennaway paxwarn(1, "Tar cannot archive a socket %s", arcn->org_name); 6004b88c807SRodney W. Grimes return(1); 6014b88c807SRodney W. Grimes case PAX_FIF: 602778766feSKris Kennaway paxwarn(1, "Tar cannot archive a fifo %s", arcn->org_name); 6034b88c807SRodney W. Grimes return(1); 6044b88c807SRodney W. Grimes case PAX_SLK: 6054b88c807SRodney W. Grimes case PAX_HLK: 6064b88c807SRodney W. Grimes case PAX_HRG: 6074b88c807SRodney W. Grimes if (arcn->ln_nlen > sizeof(hd->linkname)) { 608778766feSKris Kennaway paxwarn(1,"Link name too long for tar %s", arcn->ln_name); 6094b88c807SRodney W. Grimes return(1); 6104b88c807SRodney W. Grimes } 6114b88c807SRodney W. Grimes break; 6124b88c807SRodney W. Grimes case PAX_REG: 6134b88c807SRodney W. Grimes case PAX_CTG: 6144b88c807SRodney W. Grimes default: 6154b88c807SRodney W. Grimes break; 6164b88c807SRodney W. Grimes } 6174b88c807SRodney W. Grimes 6184b88c807SRodney W. Grimes /* 6194b88c807SRodney W. Grimes * check file name len, remember extra char for dirs (the / at the end) 6204b88c807SRodney W. Grimes */ 6214b88c807SRodney W. Grimes len = arcn->nlen; 6224b88c807SRodney W. Grimes if (arcn->type == PAX_DIR) 6234b88c807SRodney W. Grimes ++len; 624b1787decSKris Kennaway if (len >= sizeof(hd->name)) { 625778766feSKris Kennaway paxwarn(1, "File name too long for tar %s", arcn->name); 6264b88c807SRodney W. Grimes return(1); 6274b88c807SRodney W. Grimes } 6284b88c807SRodney W. Grimes 6294b88c807SRodney W. Grimes /* 6304b88c807SRodney W. Grimes * copy the data out of the ARCHD into the tar header based on the type 6314b88c807SRodney W. Grimes * of the file. Remember many tar readers want the unused fields to be 6324b88c807SRodney W. Grimes * padded with zero. We set the linkflag field (type), the linkname 6334b88c807SRodney W. Grimes * (or zero if not used),the size, and set the padding (if any) to be 6344b88c807SRodney W. Grimes * added after the file data (0 for all other types, as they only have 6354b88c807SRodney W. Grimes * a header) 6364b88c807SRodney W. Grimes */ 6374b88c807SRodney W. Grimes hd = (HD_TAR *)hdblk; 638b1787decSKris Kennaway l_strncpy(hd->name, arcn->name, sizeof(hd->name) - 1); 639b1787decSKris Kennaway hd->name[sizeof(hd->name) - 1] = '\0'; 6404b88c807SRodney W. Grimes arcn->pad = 0; 6414b88c807SRodney W. Grimes 6424b88c807SRodney W. Grimes if (arcn->type == PAX_DIR) { 6434b88c807SRodney W. Grimes /* 6444b88c807SRodney W. Grimes * directories are the same as files, except have a filename 6454b88c807SRodney W. Grimes * that ends with a /, we add the slash here. No data follows, 6464b88c807SRodney W. Grimes * dirs, so no pad. 6474b88c807SRodney W. Grimes */ 6484b88c807SRodney W. Grimes hd->linkflag = AREGTYPE; 649778766feSKris Kennaway memset(hd->linkname, 0, sizeof(hd->linkname)); 6504b88c807SRodney W. Grimes hd->name[len-1] = '/'; 6514b88c807SRodney W. Grimes if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1)) 6524b88c807SRodney W. Grimes goto out; 6534b88c807SRodney W. Grimes } else if (arcn->type == PAX_SLK) { 6544b88c807SRodney W. Grimes /* 6554b88c807SRodney W. Grimes * no data follows this file, so no pad 6564b88c807SRodney W. Grimes */ 6574b88c807SRodney W. Grimes hd->linkflag = SYMTYPE; 658b1787decSKris Kennaway l_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname) - 1); 659b1787decSKris Kennaway hd->linkname[sizeof(hd->linkname) - 1] = '\0'; 6604b88c807SRodney W. Grimes if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1)) 6614b88c807SRodney W. Grimes goto out; 6624b88c807SRodney W. Grimes } else if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG)) { 6634b88c807SRodney W. Grimes /* 6644b88c807SRodney W. Grimes * no data follows this file, so no pad 6654b88c807SRodney W. Grimes */ 6664b88c807SRodney W. Grimes hd->linkflag = LNKTYPE; 667b1787decSKris Kennaway l_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname) - 1); 668b1787decSKris Kennaway hd->linkname[sizeof(hd->linkname) - 1] = '\0'; 6694b88c807SRodney W. Grimes if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1)) 6704b88c807SRodney W. Grimes goto out; 6714b88c807SRodney W. Grimes } else { 6724b88c807SRodney W. Grimes /* 6734b88c807SRodney W. Grimes * data follows this file, so set the pad 6744b88c807SRodney W. Grimes */ 6754b88c807SRodney W. Grimes hd->linkflag = AREGTYPE; 676778766feSKris Kennaway memset(hd->linkname, 0, sizeof(hd->linkname)); 6774b88c807SRodney W. Grimes # ifdef NET2_STAT 6784b88c807SRodney W. Grimes if (ul_oct((u_long)arcn->sb.st_size, hd->size, 6794b88c807SRodney W. Grimes sizeof(hd->size), 1)) { 6804b88c807SRodney W. Grimes # else 6814b88c807SRodney W. Grimes if (uqd_oct((u_quad_t)arcn->sb.st_size, hd->size, 6824b88c807SRodney W. Grimes sizeof(hd->size), 1)) { 6834b88c807SRodney W. Grimes # endif 684778766feSKris Kennaway paxwarn(1,"File is too large for tar %s", arcn->org_name); 6854b88c807SRodney W. Grimes return(1); 6864b88c807SRodney W. Grimes } 6874b88c807SRodney W. Grimes arcn->pad = TAR_PAD(arcn->sb.st_size); 6884b88c807SRodney W. Grimes } 6894b88c807SRodney W. Grimes 6904b88c807SRodney W. Grimes /* 6914b88c807SRodney W. Grimes * copy those fields that are independent of the type 6924b88c807SRodney W. Grimes */ 6934b88c807SRodney W. Grimes if (ul_oct((u_long)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 0) || 6944b88c807SRodney W. Grimes ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 0) || 6954b88c807SRodney W. Grimes ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 0) || 6964b88c807SRodney W. Grimes ul_oct((u_long)arcn->sb.st_mtime, hd->mtime, sizeof(hd->mtime), 1)) 6974b88c807SRodney W. Grimes goto out; 6984b88c807SRodney W. Grimes 6994b88c807SRodney W. Grimes /* 7004b88c807SRodney W. Grimes * calculate and add the checksum, then write the header. A return of 7014b88c807SRodney W. Grimes * 0 tells the caller to now write the file data, 1 says no data needs 7024b88c807SRodney W. Grimes * to be written 7034b88c807SRodney W. Grimes */ 7044b88c807SRodney W. Grimes if (ul_oct(tar_chksm(hdblk, sizeof(HD_TAR)), hd->chksum, 705b1787decSKris Kennaway sizeof(hd->chksum), 3)) 7064b88c807SRodney W. Grimes goto out; 7074b88c807SRodney W. Grimes if (wr_rdbuf(hdblk, sizeof(HD_TAR)) < 0) 7084b88c807SRodney W. Grimes return(-1); 7094b88c807SRodney W. Grimes if (wr_skip((off_t)(BLKMULT - sizeof(HD_TAR))) < 0) 7104b88c807SRodney W. Grimes return(-1); 7114b88c807SRodney W. Grimes if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG)) 7124b88c807SRodney W. Grimes return(0); 7134b88c807SRodney W. Grimes return(1); 7144b88c807SRodney W. Grimes 7154b88c807SRodney W. Grimes out: 7164b88c807SRodney W. Grimes /* 7174b88c807SRodney W. Grimes * header field is out of range 7184b88c807SRodney W. Grimes */ 719778766feSKris Kennaway paxwarn(1, "Tar header field is too small for %s", arcn->org_name); 7204b88c807SRodney W. Grimes return(1); 7214b88c807SRodney W. Grimes } 7224b88c807SRodney W. Grimes 7234b88c807SRodney W. Grimes /* 7244b88c807SRodney W. Grimes * Routines for POSIX ustar 7254b88c807SRodney W. Grimes */ 7264b88c807SRodney W. Grimes 7274b88c807SRodney W. Grimes /* 7284b88c807SRodney W. Grimes * ustar_strd() 7294b88c807SRodney W. Grimes * initialization for ustar read 7304b88c807SRodney W. Grimes * Return: 7314b88c807SRodney W. Grimes * 0 if ok, -1 otherwise 7324b88c807SRodney W. Grimes */ 7334b88c807SRodney W. Grimes 734778766feSKris Kennaway #ifdef __STDC__ 7354b88c807SRodney W. Grimes int 7364b88c807SRodney W. Grimes ustar_strd(void) 7374b88c807SRodney W. Grimes #else 7384b88c807SRodney W. Grimes int 7394b88c807SRodney W. Grimes ustar_strd() 7404b88c807SRodney W. Grimes #endif 7414b88c807SRodney W. Grimes { 7424b88c807SRodney W. Grimes if ((usrtb_start() < 0) || (grptb_start() < 0)) 7434b88c807SRodney W. Grimes return(-1); 7444b88c807SRodney W. Grimes return(0); 7454b88c807SRodney W. Grimes } 7464b88c807SRodney W. Grimes 7474b88c807SRodney W. Grimes /* 7484b88c807SRodney W. Grimes * ustar_stwr() 7494b88c807SRodney W. Grimes * initialization for ustar write 7504b88c807SRodney W. Grimes * Return: 7514b88c807SRodney W. Grimes * 0 if ok, -1 otherwise 7524b88c807SRodney W. Grimes */ 7534b88c807SRodney W. Grimes 754778766feSKris Kennaway #ifdef __STDC__ 7554b88c807SRodney W. Grimes int 7564b88c807SRodney W. Grimes ustar_stwr(void) 7574b88c807SRodney W. Grimes #else 7584b88c807SRodney W. Grimes int 7594b88c807SRodney W. Grimes ustar_stwr() 7604b88c807SRodney W. Grimes #endif 7614b88c807SRodney W. Grimes { 7624b88c807SRodney W. Grimes if ((uidtb_start() < 0) || (gidtb_start() < 0)) 7634b88c807SRodney W. Grimes return(-1); 7644b88c807SRodney W. Grimes return(0); 7654b88c807SRodney W. Grimes } 7664b88c807SRodney W. Grimes 7674b88c807SRodney W. Grimes /* 7684b88c807SRodney W. Grimes * ustar_id() 7694b88c807SRodney W. Grimes * determine if a block given to us is a valid ustar header. We have to 7704b88c807SRodney W. Grimes * be on the lookout for those pesky blocks of all zero's 7714b88c807SRodney W. Grimes * Return: 7724b88c807SRodney W. Grimes * 0 if a ustar header, -1 otherwise 7734b88c807SRodney W. Grimes */ 7744b88c807SRodney W. Grimes 775778766feSKris Kennaway #ifdef __STDC__ 7764b88c807SRodney W. Grimes int 7774b88c807SRodney W. Grimes ustar_id(char *blk, int size) 7784b88c807SRodney W. Grimes #else 7794b88c807SRodney W. Grimes int 7804b88c807SRodney W. Grimes ustar_id(blk, size) 7814b88c807SRodney W. Grimes char *blk; 7824b88c807SRodney W. Grimes int size; 7834b88c807SRodney W. Grimes #endif 7844b88c807SRodney W. Grimes { 7854b88c807SRodney W. Grimes register HD_USTAR *hd; 7864b88c807SRodney W. Grimes 7874b88c807SRodney W. Grimes if (size < BLKMULT) 7884b88c807SRodney W. Grimes return(-1); 7894b88c807SRodney W. Grimes hd = (HD_USTAR *)blk; 7904b88c807SRodney W. Grimes 7914b88c807SRodney W. Grimes /* 7924b88c807SRodney W. Grimes * check for block of zero's first, a simple and fast test then check 7934b88c807SRodney W. Grimes * ustar magic cookie. We should use TMAGLEN, but some USTAR archive 7944b88c807SRodney W. Grimes * programs are fouled up and create archives missing the \0. Last we 7954b88c807SRodney W. Grimes * check the checksum. If ok we have to assume it is a valid header. 7964b88c807SRodney W. Grimes */ 7974b88c807SRodney W. Grimes if (hd->name[0] == '\0') 7984b88c807SRodney W. Grimes return(-1); 7994b88c807SRodney W. Grimes if (strncmp(hd->magic, TMAGIC, TMAGLEN - 1) != 0) 8004b88c807SRodney W. Grimes return(-1); 8014b88c807SRodney W. Grimes if (asc_ul(hd->chksum,sizeof(hd->chksum),OCT) != tar_chksm(blk,BLKMULT)) 8024b88c807SRodney W. Grimes return(-1); 8034b88c807SRodney W. Grimes return(0); 8044b88c807SRodney W. Grimes } 8054b88c807SRodney W. Grimes 8064b88c807SRodney W. Grimes /* 8074b88c807SRodney W. Grimes * ustar_rd() 8084b88c807SRodney W. Grimes * extract the values out of block already determined to be a ustar header. 8094b88c807SRodney W. Grimes * store the values in the ARCHD parameter. 8104b88c807SRodney W. Grimes * Return: 8114b88c807SRodney W. Grimes * 0 8124b88c807SRodney W. Grimes */ 8134b88c807SRodney W. Grimes 814778766feSKris Kennaway #ifdef __STDC__ 8154b88c807SRodney W. Grimes int 8164b88c807SRodney W. Grimes ustar_rd(register ARCHD *arcn, register char *buf) 8174b88c807SRodney W. Grimes #else 8184b88c807SRodney W. Grimes int 8194b88c807SRodney W. Grimes ustar_rd(arcn, buf) 8204b88c807SRodney W. Grimes register ARCHD *arcn; 8214b88c807SRodney W. Grimes register char *buf; 8224b88c807SRodney W. Grimes #endif 8234b88c807SRodney W. Grimes { 8244b88c807SRodney W. Grimes register HD_USTAR *hd; 8254b88c807SRodney W. Grimes register char *dest; 8264b88c807SRodney W. Grimes register int cnt = 0; 8274b88c807SRodney W. Grimes dev_t devmajor; 8284b88c807SRodney W. Grimes dev_t devminor; 8294b88c807SRodney W. Grimes 8304b88c807SRodney W. Grimes /* 8314b88c807SRodney W. Grimes * we only get proper sized buffers 8324b88c807SRodney W. Grimes */ 8334b88c807SRodney W. Grimes if (ustar_id(buf, BLKMULT) < 0) 8344b88c807SRodney W. Grimes return(-1); 8354b88c807SRodney W. Grimes arcn->org_name = arcn->name; 8364b88c807SRodney W. Grimes arcn->sb.st_nlink = 1; 8374b88c807SRodney W. Grimes arcn->pat = NULL; 838b1787decSKris Kennaway arcn->nlen = 0; 8394b88c807SRodney W. Grimes hd = (HD_USTAR *)buf; 8404b88c807SRodney W. Grimes 8414b88c807SRodney W. Grimes /* 8424b88c807SRodney W. Grimes * see if the filename is split into two parts. if, so joint the parts. 8434b88c807SRodney W. Grimes * we copy the prefix first and add a / between the prefix and name. 8444b88c807SRodney W. Grimes */ 8454b88c807SRodney W. Grimes dest = arcn->name; 8464b88c807SRodney W. Grimes if (*(hd->prefix) != '\0') { 847b1787decSKris Kennaway cnt = l_strncpy(dest, hd->prefix, sizeof(arcn->name) - 2); 848b1787decSKris Kennaway dest += cnt; 8494b88c807SRodney W. Grimes *dest++ = '/'; 850b1787decSKris Kennaway cnt++; 8514b88c807SRodney W. Grimes } 852b1787decSKris Kennaway arcn->nlen = cnt + l_strncpy(dest, hd->name, sizeof(arcn->name) - cnt); 8534b88c807SRodney W. Grimes arcn->name[arcn->nlen] = '\0'; 8544b88c807SRodney W. Grimes 8554b88c807SRodney W. Grimes /* 8564b88c807SRodney W. Grimes * follow the spec to the letter. we should only have mode bits, strip 8574b88c807SRodney W. Grimes * off all other crud we may be passed. 8584b88c807SRodney W. Grimes */ 8594b88c807SRodney W. Grimes arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode, sizeof(hd->mode), OCT) & 8604b88c807SRodney W. Grimes 0xfff); 861b1787decSKris Kennaway #ifdef NET2_STAT 862b1787decSKris Kennaway arcn->sb.st_size = (off_t)asc_ul(hd->size, sizeof(hd->size), OCT); 863b1787decSKris Kennaway #else 864b1787decSKris Kennaway arcn->sb.st_size = (off_t)asc_uqd(hd->size, sizeof(hd->size), OCT); 865b1787decSKris Kennaway #endif 8664b88c807SRodney W. Grimes arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT); 8674b88c807SRodney W. Grimes arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime; 8684b88c807SRodney W. Grimes 8694b88c807SRodney W. Grimes /* 8704b88c807SRodney W. Grimes * If we can find the ascii names for gname and uname in the password 8714b88c807SRodney W. Grimes * and group files we will use the uid's and gid they bind. Otherwise 8724b88c807SRodney W. Grimes * we use the uid and gid values stored in the header. (This is what 87346be34b9SKris Kennaway * the POSIX spec wants). 8744b88c807SRodney W. Grimes */ 8754b88c807SRodney W. Grimes hd->gname[sizeof(hd->gname) - 1] = '\0'; 8764b88c807SRodney W. Grimes if (gid_name(hd->gname, &(arcn->sb.st_gid)) < 0) 8774b88c807SRodney W. Grimes arcn->sb.st_gid = (gid_t)asc_ul(hd->gid, sizeof(hd->gid), OCT); 8784b88c807SRodney W. Grimes hd->uname[sizeof(hd->uname) - 1] = '\0'; 8794b88c807SRodney W. Grimes if (uid_name(hd->uname, &(arcn->sb.st_uid)) < 0) 8804b88c807SRodney W. Grimes arcn->sb.st_uid = (uid_t)asc_ul(hd->uid, sizeof(hd->uid), OCT); 8814b88c807SRodney W. Grimes 8824b88c807SRodney W. Grimes /* 8834b88c807SRodney W. Grimes * set the defaults, these may be changed depending on the file type 8844b88c807SRodney W. Grimes */ 8854b88c807SRodney W. Grimes arcn->ln_name[0] = '\0'; 8864b88c807SRodney W. Grimes arcn->ln_nlen = 0; 8874b88c807SRodney W. Grimes arcn->pad = 0; 8884b88c807SRodney W. Grimes arcn->skip = 0; 8894b88c807SRodney W. Grimes arcn->sb.st_rdev = (dev_t)0; 8904b88c807SRodney W. Grimes 8914b88c807SRodney W. Grimes /* 8924b88c807SRodney W. Grimes * set the mode and PAX type according to the typeflag in the header 8934b88c807SRodney W. Grimes */ 8944b88c807SRodney W. Grimes switch(hd->typeflag) { 8954b88c807SRodney W. Grimes case FIFOTYPE: 8964b88c807SRodney W. Grimes arcn->type = PAX_FIF; 8974b88c807SRodney W. Grimes arcn->sb.st_mode |= S_IFIFO; 8984b88c807SRodney W. Grimes break; 8994b88c807SRodney W. Grimes case DIRTYPE: 9004b88c807SRodney W. Grimes arcn->type = PAX_DIR; 9014b88c807SRodney W. Grimes arcn->sb.st_mode |= S_IFDIR; 9024b88c807SRodney W. Grimes arcn->sb.st_nlink = 2; 9034b88c807SRodney W. Grimes 9044b88c807SRodney W. Grimes /* 9054b88c807SRodney W. Grimes * Some programs that create ustar archives append a '/' 9064b88c807SRodney W. Grimes * to the pathname for directories. This clearly violates 9074b88c807SRodney W. Grimes * ustar specs, but we will silently strip it off anyway. 9084b88c807SRodney W. Grimes */ 9094b88c807SRodney W. Grimes if (arcn->name[arcn->nlen - 1] == '/') 9104b88c807SRodney W. Grimes arcn->name[--arcn->nlen] = '\0'; 9114b88c807SRodney W. Grimes break; 9124b88c807SRodney W. Grimes case BLKTYPE: 9134b88c807SRodney W. Grimes case CHRTYPE: 9144b88c807SRodney W. Grimes /* 9154b88c807SRodney W. Grimes * this type requires the rdev field to be set. 9164b88c807SRodney W. Grimes */ 9174b88c807SRodney W. Grimes if (hd->typeflag == BLKTYPE) { 9184b88c807SRodney W. Grimes arcn->type = PAX_BLK; 9194b88c807SRodney W. Grimes arcn->sb.st_mode |= S_IFBLK; 9204b88c807SRodney W. Grimes } else { 9214b88c807SRodney W. Grimes arcn->type = PAX_CHR; 9224b88c807SRodney W. Grimes arcn->sb.st_mode |= S_IFCHR; 9234b88c807SRodney W. Grimes } 9244b88c807SRodney W. Grimes devmajor = (dev_t)asc_ul(hd->devmajor,sizeof(hd->devmajor),OCT); 9254b88c807SRodney W. Grimes devminor = (dev_t)asc_ul(hd->devminor,sizeof(hd->devminor),OCT); 9264b88c807SRodney W. Grimes arcn->sb.st_rdev = TODEV(devmajor, devminor); 9274b88c807SRodney W. Grimes break; 9284b88c807SRodney W. Grimes case SYMTYPE: 9294b88c807SRodney W. Grimes case LNKTYPE: 9304b88c807SRodney W. Grimes if (hd->typeflag == SYMTYPE) { 9314b88c807SRodney W. Grimes arcn->type = PAX_SLK; 9324b88c807SRodney W. Grimes arcn->sb.st_mode |= S_IFLNK; 9334b88c807SRodney W. Grimes } else { 9344b88c807SRodney W. Grimes arcn->type = PAX_HLK; 9354b88c807SRodney W. Grimes /* 9364b88c807SRodney W. Grimes * so printing looks better 9374b88c807SRodney W. Grimes */ 9384b88c807SRodney W. Grimes arcn->sb.st_mode |= S_IFREG; 9394b88c807SRodney W. Grimes arcn->sb.st_nlink = 2; 9404b88c807SRodney W. Grimes } 9414b88c807SRodney W. Grimes /* 9424b88c807SRodney W. Grimes * copy the link name 9434b88c807SRodney W. Grimes */ 9444b88c807SRodney W. Grimes arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname, 945b1787decSKris Kennaway sizeof(arcn->ln_name) - 1); 9464b88c807SRodney W. Grimes arcn->ln_name[arcn->ln_nlen] = '\0'; 9474b88c807SRodney W. Grimes break; 9484b88c807SRodney W. Grimes case CONTTYPE: 9494b88c807SRodney W. Grimes case AREGTYPE: 9504b88c807SRodney W. Grimes case REGTYPE: 9514b88c807SRodney W. Grimes default: 9524b88c807SRodney W. Grimes /* 9534b88c807SRodney W. Grimes * these types have file data that follows. Set the skip and 9544b88c807SRodney W. Grimes * pad fields. 9554b88c807SRodney W. Grimes */ 9564b88c807SRodney W. Grimes arcn->type = PAX_REG; 9574b88c807SRodney W. Grimes arcn->pad = TAR_PAD(arcn->sb.st_size); 9584b88c807SRodney W. Grimes arcn->skip = arcn->sb.st_size; 9594b88c807SRodney W. Grimes arcn->sb.st_mode |= S_IFREG; 9604b88c807SRodney W. Grimes break; 9614b88c807SRodney W. Grimes } 9624b88c807SRodney W. Grimes return(0); 9634b88c807SRodney W. Grimes } 9644b88c807SRodney W. Grimes 9654b88c807SRodney W. Grimes /* 9664b88c807SRodney W. Grimes * ustar_wr() 9674b88c807SRodney W. Grimes * write a ustar header for the file specified in the ARCHD to the archive 9684b88c807SRodney W. Grimes * Have to check for file types that cannot be stored and file names that 9694b88c807SRodney W. Grimes * are too long. Be careful of the term (last arg) to ul_oct, we only use 9704b88c807SRodney W. Grimes * '\0' for the termination character (this is different than picky tar) 9714b88c807SRodney W. Grimes * ASSUMED: space after header in header block is zero filled 9724b88c807SRodney W. Grimes * Return: 9734b88c807SRodney W. Grimes * 0 if file has data to be written after the header, 1 if file has NO 9744b88c807SRodney W. Grimes * data to write after the header, -1 if archive write failed 9754b88c807SRodney W. Grimes */ 9764b88c807SRodney W. Grimes 977778766feSKris Kennaway #ifdef __STDC__ 9784b88c807SRodney W. Grimes int 9794b88c807SRodney W. Grimes ustar_wr(register ARCHD *arcn) 9804b88c807SRodney W. Grimes #else 9814b88c807SRodney W. Grimes int 9824b88c807SRodney W. Grimes ustar_wr(arcn) 9834b88c807SRodney W. Grimes register ARCHD *arcn; 9844b88c807SRodney W. Grimes #endif 9854b88c807SRodney W. Grimes { 9864b88c807SRodney W. Grimes register HD_USTAR *hd; 9874b88c807SRodney W. Grimes register char *pt; 9884b88c807SRodney W. Grimes char hdblk[sizeof(HD_USTAR)]; 9894b88c807SRodney W. Grimes 9904b88c807SRodney W. Grimes /* 9914b88c807SRodney W. Grimes * check for those file system types ustar cannot store 9924b88c807SRodney W. Grimes */ 9934b88c807SRodney W. Grimes if (arcn->type == PAX_SCK) { 994778766feSKris Kennaway paxwarn(1, "Ustar cannot archive a socket %s", arcn->org_name); 9954b88c807SRodney W. Grimes return(1); 9964b88c807SRodney W. Grimes } 9974b88c807SRodney W. Grimes 9984b88c807SRodney W. Grimes /* 9994b88c807SRodney W. Grimes * check the length of the linkname 10004b88c807SRodney W. Grimes */ 10014b88c807SRodney W. Grimes if (((arcn->type == PAX_SLK) || (arcn->type == PAX_HLK) || 10024757e526SMike Smith (arcn->type == PAX_HRG)) && (arcn->ln_nlen >= sizeof(hd->linkname))){ 1003778766feSKris Kennaway paxwarn(1, "Link name too long for ustar %s", arcn->ln_name); 10044b88c807SRodney W. Grimes return(1); 10054b88c807SRodney W. Grimes } 10064b88c807SRodney W. Grimes 10074b88c807SRodney W. Grimes /* 10084b88c807SRodney W. Grimes * split the path name into prefix and name fields (if needed). if 10094b88c807SRodney W. Grimes * pt != arcn->name, the name has to be split 10104b88c807SRodney W. Grimes */ 10114b88c807SRodney W. Grimes if ((pt = name_split(arcn->name, arcn->nlen)) == NULL) { 1012778766feSKris Kennaway paxwarn(1, "File name too long for ustar %s", arcn->name); 10134b88c807SRodney W. Grimes return(1); 10144b88c807SRodney W. Grimes } 10154b88c807SRodney W. Grimes hd = (HD_USTAR *)hdblk; 10164b88c807SRodney W. Grimes arcn->pad = 0L; 10174b88c807SRodney W. Grimes 10184b88c807SRodney W. Grimes /* 10194b88c807SRodney W. Grimes * split the name, or zero out the prefix 10204b88c807SRodney W. Grimes */ 10214b88c807SRodney W. Grimes if (pt != arcn->name) { 10224b88c807SRodney W. Grimes /* 10234b88c807SRodney W. Grimes * name was split, pt points at the / where the split is to 10244b88c807SRodney W. Grimes * occur, we remove the / and copy the first part to the prefix 10254b88c807SRodney W. Grimes */ 10264b88c807SRodney W. Grimes *pt = '\0'; 1027b1787decSKris Kennaway l_strncpy(hd->prefix, arcn->name, sizeof(hd->prefix) - 1); 10284b88c807SRodney W. Grimes *pt++ = '/'; 10294b88c807SRodney W. Grimes } else 1030778766feSKris Kennaway memset(hd->prefix, 0, sizeof(hd->prefix)); 10314b88c807SRodney W. Grimes 10324b88c807SRodney W. Grimes /* 10334b88c807SRodney W. Grimes * copy the name part. this may be the whole path or the part after 10344b88c807SRodney W. Grimes * the prefix 10354b88c807SRodney W. Grimes */ 1036b1787decSKris Kennaway l_strncpy(hd->name, pt, sizeof(hd->name) - 1); 1037b1787decSKris Kennaway hd->name[sizeof(hd->name) - 1] = '\0'; 10384b88c807SRodney W. Grimes 10394b88c807SRodney W. Grimes /* 10404b88c807SRodney W. Grimes * set the fields in the header that are type dependent 10414b88c807SRodney W. Grimes */ 10424b88c807SRodney W. Grimes switch(arcn->type) { 10434b88c807SRodney W. Grimes case PAX_DIR: 10444b88c807SRodney W. Grimes hd->typeflag = DIRTYPE; 1045778766feSKris Kennaway memset(hd->linkname, 0, sizeof(hd->linkname)); 1046778766feSKris Kennaway memset(hd->devmajor, 0, sizeof(hd->devmajor)); 1047778766feSKris Kennaway memset(hd->devminor, 0, sizeof(hd->devminor)); 10484b88c807SRodney W. Grimes if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3)) 10494b88c807SRodney W. Grimes goto out; 10504b88c807SRodney W. Grimes break; 10514b88c807SRodney W. Grimes case PAX_CHR: 10524b88c807SRodney W. Grimes case PAX_BLK: 10534b88c807SRodney W. Grimes if (arcn->type == PAX_CHR) 10544b88c807SRodney W. Grimes hd->typeflag = CHRTYPE; 10554b88c807SRodney W. Grimes else 10564b88c807SRodney W. Grimes hd->typeflag = BLKTYPE; 1057778766feSKris Kennaway memset(hd->linkname, 0, sizeof(hd->linkname)); 10584b88c807SRodney W. Grimes if (ul_oct((u_long)MAJOR(arcn->sb.st_rdev), hd->devmajor, 10594b88c807SRodney W. Grimes sizeof(hd->devmajor), 3) || 10604b88c807SRodney W. Grimes ul_oct((u_long)MINOR(arcn->sb.st_rdev), hd->devminor, 10614b88c807SRodney W. Grimes sizeof(hd->devminor), 3) || 10624b88c807SRodney W. Grimes ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3)) 10634b88c807SRodney W. Grimes goto out; 10644b88c807SRodney W. Grimes break; 10654b88c807SRodney W. Grimes case PAX_FIF: 10664b88c807SRodney W. Grimes hd->typeflag = FIFOTYPE; 1067778766feSKris Kennaway memset(hd->linkname, 0, sizeof(hd->linkname)); 1068778766feSKris Kennaway memset(hd->devmajor, 0, sizeof(hd->devmajor)); 1069778766feSKris Kennaway memset(hd->devminor, 0, sizeof(hd->devminor)); 10704b88c807SRodney W. Grimes if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3)) 10714b88c807SRodney W. Grimes goto out; 10724b88c807SRodney W. Grimes break; 10734b88c807SRodney W. Grimes case PAX_SLK: 10744b88c807SRodney W. Grimes case PAX_HLK: 10754b88c807SRodney W. Grimes case PAX_HRG: 10764b88c807SRodney W. Grimes if (arcn->type == PAX_SLK) 10774b88c807SRodney W. Grimes hd->typeflag = SYMTYPE; 10784b88c807SRodney W. Grimes else 10794b88c807SRodney W. Grimes hd->typeflag = LNKTYPE; 1080b1787decSKris Kennaway l_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname) - 1); 1081b1787decSKris Kennaway hd->linkname[sizeof(hd->linkname) - 1] = '\0'; 1082778766feSKris Kennaway memset(hd->devmajor, 0, sizeof(hd->devmajor)); 1083778766feSKris Kennaway memset(hd->devminor, 0, sizeof(hd->devminor)); 10844b88c807SRodney W. Grimes if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3)) 10854b88c807SRodney W. Grimes goto out; 10864b88c807SRodney W. Grimes break; 10874b88c807SRodney W. Grimes case PAX_REG: 10884b88c807SRodney W. Grimes case PAX_CTG: 10894b88c807SRodney W. Grimes default: 10904b88c807SRodney W. Grimes /* 10914b88c807SRodney W. Grimes * file data with this type, set the padding 10924b88c807SRodney W. Grimes */ 10934b88c807SRodney W. Grimes if (arcn->type == PAX_CTG) 10944b88c807SRodney W. Grimes hd->typeflag = CONTTYPE; 10954b88c807SRodney W. Grimes else 10964b88c807SRodney W. Grimes hd->typeflag = REGTYPE; 1097778766feSKris Kennaway memset(hd->linkname, 0, sizeof(hd->linkname)); 1098778766feSKris Kennaway memset(hd->devmajor, 0, sizeof(hd->devmajor)); 1099778766feSKris Kennaway memset(hd->devminor, 0, sizeof(hd->devminor)); 11004b88c807SRodney W. Grimes arcn->pad = TAR_PAD(arcn->sb.st_size); 11014b88c807SRodney W. Grimes # ifdef NET2_STAT 11024b88c807SRodney W. Grimes if (ul_oct((u_long)arcn->sb.st_size, hd->size, 11034b88c807SRodney W. Grimes sizeof(hd->size), 3)) { 11044b88c807SRodney W. Grimes # else 11054b88c807SRodney W. Grimes if (uqd_oct((u_quad_t)arcn->sb.st_size, hd->size, 11064b88c807SRodney W. Grimes sizeof(hd->size), 3)) { 11074b88c807SRodney W. Grimes # endif 1108778766feSKris Kennaway paxwarn(1,"File is too long for ustar %s",arcn->org_name); 11094b88c807SRodney W. Grimes return(1); 11104b88c807SRodney W. Grimes } 11114b88c807SRodney W. Grimes break; 11124b88c807SRodney W. Grimes } 11134b88c807SRodney W. Grimes 1114b1787decSKris Kennaway l_strncpy(hd->magic, TMAGIC, TMAGLEN); 1115b1787decSKris Kennaway l_strncpy(hd->version, TVERSION, TVERSLEN); 11164b88c807SRodney W. Grimes 11174b88c807SRodney W. Grimes /* 11184b88c807SRodney W. Grimes * set the remaining fields. Some versions want all 16 bits of mode 11194b88c807SRodney W. Grimes * we better humor them (they really do not meet spec though).... 11204b88c807SRodney W. Grimes */ 11214b88c807SRodney W. Grimes if (ul_oct((u_long)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 3) || 11224b88c807SRodney W. Grimes ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 3) || 11234b88c807SRodney W. Grimes ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 3) || 11244b88c807SRodney W. Grimes ul_oct((u_long)arcn->sb.st_mtime,hd->mtime,sizeof(hd->mtime),3)) 11254b88c807SRodney W. Grimes goto out; 1126b1787decSKris Kennaway l_strncpy(hd->uname,name_uid(arcn->sb.st_uid, 0),sizeof(hd->uname)); 1127b1787decSKris Kennaway l_strncpy(hd->gname,name_gid(arcn->sb.st_gid, 0),sizeof(hd->gname)); 11284b88c807SRodney W. Grimes 11294b88c807SRodney W. Grimes /* 11304b88c807SRodney W. Grimes * calculate and store the checksum write the header to the archive 11314b88c807SRodney W. Grimes * return 0 tells the caller to now write the file data, 1 says no data 11324b88c807SRodney W. Grimes * needs to be written 11334b88c807SRodney W. Grimes */ 11344b88c807SRodney W. Grimes if (ul_oct(tar_chksm(hdblk, sizeof(HD_USTAR)), hd->chksum, 11354b88c807SRodney W. Grimes sizeof(hd->chksum), 3)) 11364b88c807SRodney W. Grimes goto out; 11374b88c807SRodney W. Grimes if (wr_rdbuf(hdblk, sizeof(HD_USTAR)) < 0) 11384b88c807SRodney W. Grimes return(-1); 11394b88c807SRodney W. Grimes if (wr_skip((off_t)(BLKMULT - sizeof(HD_USTAR))) < 0) 11404b88c807SRodney W. Grimes return(-1); 11414b88c807SRodney W. Grimes if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG)) 11424b88c807SRodney W. Grimes return(0); 11434b88c807SRodney W. Grimes return(1); 11444b88c807SRodney W. Grimes 11454b88c807SRodney W. Grimes out: 11464b88c807SRodney W. Grimes /* 11474b88c807SRodney W. Grimes * header field is out of range 11484b88c807SRodney W. Grimes */ 1149778766feSKris Kennaway paxwarn(1, "Ustar header field is too small for %s", arcn->org_name); 11504b88c807SRodney W. Grimes return(1); 11514b88c807SRodney W. Grimes } 11524b88c807SRodney W. Grimes 11534b88c807SRodney W. Grimes /* 11544b88c807SRodney W. Grimes * name_split() 11554b88c807SRodney W. Grimes * see if the name has to be split for storage in a ustar header. We try 11564b88c807SRodney W. Grimes * to fit the entire name in the name field without splitting if we can. 11574b88c807SRodney W. Grimes * The split point is always at a / 11584b88c807SRodney W. Grimes * Return 11594b88c807SRodney W. Grimes * character pointer to split point (always the / that is to be removed 11604b88c807SRodney W. Grimes * if the split is not needed, the points is set to the start of the file 11614b88c807SRodney W. Grimes * name (it would violate the spec to split there). A NULL is returned if 11624b88c807SRodney W. Grimes * the file name is too long 11634b88c807SRodney W. Grimes */ 11644b88c807SRodney W. Grimes 1165778766feSKris Kennaway #ifdef __STDC__ 11664b88c807SRodney W. Grimes static char * 11674b88c807SRodney W. Grimes name_split(register char *name, register int len) 11684b88c807SRodney W. Grimes #else 11694b88c807SRodney W. Grimes static char * 11704b88c807SRodney W. Grimes name_split(name, len) 11714b88c807SRodney W. Grimes register char *name; 11724b88c807SRodney W. Grimes register int len; 11734b88c807SRodney W. Grimes #endif 11744b88c807SRodney W. Grimes { 11754b88c807SRodney W. Grimes register char *start; 11764b88c807SRodney W. Grimes 11774b88c807SRodney W. Grimes /* 11784b88c807SRodney W. Grimes * check to see if the file name is small enough to fit in the name 11794b88c807SRodney W. Grimes * field. if so just return a pointer to the name. 11804b88c807SRodney W. Grimes */ 1181b1787decSKris Kennaway if (len < TNMSZ) 11824b88c807SRodney W. Grimes return(name); 11834757e526SMike Smith if (len > (TPFSZ + TNMSZ)) 11844b88c807SRodney W. Grimes return(NULL); 11854b88c807SRodney W. Grimes 11864b88c807SRodney W. Grimes /* 11874b88c807SRodney W. Grimes * we start looking at the biggest sized piece that fits in the name 118846be34b9SKris Kennaway * field. We walk forward looking for a slash to split at. The idea is 11894b88c807SRodney W. Grimes * to find the biggest piece to fit in the name field (or the smallest 11904757e526SMike Smith * prefix we can find) 11914b88c807SRodney W. Grimes */ 11924757e526SMike Smith start = name + len - TNMSZ; 11934b88c807SRodney W. Grimes while ((*start != '\0') && (*start != '/')) 11944b88c807SRodney W. Grimes ++start; 11954b88c807SRodney W. Grimes 11964b88c807SRodney W. Grimes /* 11974b88c807SRodney W. Grimes * if we hit the end of the string, this name cannot be split, so we 11984b88c807SRodney W. Grimes * cannot store this file. 11994b88c807SRodney W. Grimes */ 12004b88c807SRodney W. Grimes if (*start == '\0') 12014b88c807SRodney W. Grimes return(NULL); 12024b88c807SRodney W. Grimes len = start - name; 12034b88c807SRodney W. Grimes 12044b88c807SRodney W. Grimes /* 12054b88c807SRodney W. Grimes * NOTE: /str where the length of str == TNMSZ can not be stored under 12064b88c807SRodney W. Grimes * the p1003.1-1990 spec for ustar. We could force a prefix of / and 12074b88c807SRodney W. Grimes * the file would then expand on extract to //str. The len == 0 below 12084b88c807SRodney W. Grimes * makes this special case follow the spec to the letter. 12094b88c807SRodney W. Grimes */ 12104757e526SMike Smith if ((len >= TPFSZ) || (len == 0)) 12114b88c807SRodney W. Grimes return(NULL); 12124b88c807SRodney W. Grimes 12134b88c807SRodney W. Grimes /* 12144b88c807SRodney W. Grimes * ok have a split point, return it to the caller 12154b88c807SRodney W. Grimes */ 12164b88c807SRodney W. Grimes return(start); 12174b88c807SRodney W. Grimes } 1218