11556Srgrimes/*- 21556Srgrimes * Copyright (c) 1992 Keith Muller. 31556Srgrimes * Copyright (c) 1992, 1993 41556Srgrimes * The Regents of the University of California. All rights reserved. 51556Srgrimes * 61556Srgrimes * This code is derived from software contributed to Berkeley by 71556Srgrimes * Keith Muller of the University of California, San Diego. 81556Srgrimes * 91556Srgrimes * Redistribution and use in source and binary forms, with or without 101556Srgrimes * modification, are permitted provided that the following conditions 111556Srgrimes * are met: 121556Srgrimes * 1. Redistributions of source code must retain the above copyright 131556Srgrimes * notice, this list of conditions and the following disclaimer. 141556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 151556Srgrimes * notice, this list of conditions and the following disclaimer in the 161556Srgrimes * documentation and/or other materials provided with the distribution. 171556Srgrimes * 4. Neither the name of the University nor the names of its contributors 181556Srgrimes * may be used to endorse or promote products derived from this software 191556Srgrimes * without specific prior written permission. 201556Srgrimes * 211556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311556Srgrimes * SUCH DAMAGE. 321556Srgrimes */ 331556Srgrimes 341556Srgrimes#ifndef lint 3536049Scharnier#if 0 3636049Scharnierstatic char sccsid[] = "@(#)tar.c 8.2 (Berkeley) 4/18/94"; 3736049Scharnier#endif 381556Srgrimes#endif /* not lint */ 3999110Sobrien#include <sys/cdefs.h> 4099110Sobrien__FBSDID("$FreeBSD$"); 411556Srgrimes 421556Srgrimes#include <sys/types.h> 431556Srgrimes#include <sys/time.h> 441556Srgrimes#include <sys/stat.h> 451556Srgrimes#include <string.h> 461556Srgrimes#include <stdio.h> 471556Srgrimes#include "pax.h" 481556Srgrimes#include "extern.h" 491556Srgrimes#include "tar.h" 501556Srgrimes 511556Srgrimes/* 521556Srgrimes * Routines for reading, writing and header identify of various versions of tar 531556Srgrimes */ 541556Srgrimes 5590113Simpstatic u_long tar_chksm(char *, int); 5690113Simpstatic char *name_split(char *, int); 5790113Simpstatic int ul_oct(u_long, char *, int, int); 581556Srgrimes#ifndef NET2_STAT 5990113Simpstatic int uqd_oct(u_quad_t, char *, int, int); 601556Srgrimes#endif 611556Srgrimes 621556Srgrimes/* 631556Srgrimes * Routines common to all versions of tar 641556Srgrimes */ 651556Srgrimes 661556Srgrimesstatic int tar_nodir; /* do not write dirs under old tar */ 671556Srgrimes 681556Srgrimes/* 691556Srgrimes * tar_endwr() 701556Srgrimes * add the tar trailer of two null blocks 711556Srgrimes * Return: 721556Srgrimes * 0 if ok, -1 otherwise (what wr_skip returns) 731556Srgrimes */ 741556Srgrimes 751556Srgrimesint 761556Srgrimestar_endwr(void) 771556Srgrimes{ 781556Srgrimes return(wr_skip((off_t)(NULLCNT*BLKMULT))); 791556Srgrimes} 801556Srgrimes 811556Srgrimes/* 821556Srgrimes * tar_endrd() 831556Srgrimes * no cleanup needed here, just return size of trailer (for append) 841556Srgrimes * Return: 851556Srgrimes * size of trailer (2 * BLKMULT) 861556Srgrimes */ 871556Srgrimes 881556Srgrimesoff_t 891556Srgrimestar_endrd(void) 901556Srgrimes{ 911556Srgrimes return((off_t)(NULLCNT*BLKMULT)); 921556Srgrimes} 931556Srgrimes 941556Srgrimes/* 951556Srgrimes * tar_trail() 961556Srgrimes * Called to determine if a header block is a valid trailer. We are passed 971556Srgrimes * the block, the in_sync flag (which tells us we are in resync mode; 981556Srgrimes * looking for a valid header), and cnt (which starts at zero) which is 991556Srgrimes * used to count the number of empty blocks we have seen so far. 1001556Srgrimes * Return: 1011556Srgrimes * 0 if a valid trailer, -1 if not a valid trailer, or 1 if the block 1021556Srgrimes * could never contain a header. 1031556Srgrimes */ 1041556Srgrimes 1051556Srgrimesint 10690113Simptar_trail(char *buf, int in_resync, int *cnt) 1071556Srgrimes{ 10890113Simp int i; 1091556Srgrimes 1101556Srgrimes /* 1111556Srgrimes * look for all zero, trailer is two consecutive blocks of zero 1121556Srgrimes */ 1131556Srgrimes for (i = 0; i < BLKMULT; ++i) { 1141556Srgrimes if (buf[i] != '\0') 1151556Srgrimes break; 1161556Srgrimes } 1171556Srgrimes 1181556Srgrimes /* 1191556Srgrimes * if not all zero it is not a trailer, but MIGHT be a header. 1201556Srgrimes */ 1211556Srgrimes if (i != BLKMULT) 1221556Srgrimes return(-1); 1231556Srgrimes 1241556Srgrimes /* 1251556Srgrimes * When given a zero block, we must be careful! 1261556Srgrimes * If we are not in resync mode, check for the trailer. Have to watch 1271556Srgrimes * out that we do not mis-identify file data as the trailer, so we do 1281556Srgrimes * NOT try to id a trailer during resync mode. During resync mode we 1291556Srgrimes * might as well throw this block out since a valid header can NEVER be 1301556Srgrimes * a block of all 0 (we must have a valid file name). 1311556Srgrimes */ 1321556Srgrimes if (!in_resync && (++*cnt >= NULLCNT)) 1331556Srgrimes return(0); 1341556Srgrimes return(1); 1351556Srgrimes} 1361556Srgrimes 1371556Srgrimes/* 1381556Srgrimes * ul_oct() 1391556Srgrimes * convert an unsigned long to an octal string. many oddball field 1401556Srgrimes * termination characters are used by the various versions of tar in the 14176351Skris * different fields. term selects which kind to use. str is '0' padded 1421556Srgrimes * at the front to len. we are unable to use only one format as many old 1431556Srgrimes * tar readers are very cranky about this. 1441556Srgrimes * Return: 1451556Srgrimes * 0 if the number fit into the string, -1 otherwise 1461556Srgrimes */ 1471556Srgrimes 1481556Srgrimesstatic int 14990113Simpul_oct(u_long val, char *str, int len, int term) 1501556Srgrimes{ 15190113Simp char *pt; 1528855Srgrimes 1531556Srgrimes /* 1541556Srgrimes * term selects the appropriate character(s) for the end of the string 1551556Srgrimes */ 1561556Srgrimes pt = str + len - 1; 1571556Srgrimes switch(term) { 1581556Srgrimes case 3: 1591556Srgrimes *pt-- = '\0'; 1601556Srgrimes break; 1611556Srgrimes case 2: 1621556Srgrimes *pt-- = ' '; 1631556Srgrimes *pt-- = '\0'; 1641556Srgrimes break; 1651556Srgrimes case 1: 1661556Srgrimes *pt-- = ' '; 1671556Srgrimes break; 1681556Srgrimes case 0: 1691556Srgrimes default: 1701556Srgrimes *pt-- = '\0'; 1711556Srgrimes *pt-- = ' '; 1721556Srgrimes break; 1731556Srgrimes } 1741556Srgrimes 1751556Srgrimes /* 1761556Srgrimes * convert and blank pad if there is space 1771556Srgrimes */ 1781556Srgrimes while (pt >= str) { 1791556Srgrimes *pt-- = '0' + (char)(val & 0x7); 1801556Srgrimes if ((val = val >> 3) == (u_long)0) 1811556Srgrimes break; 1821556Srgrimes } 1831556Srgrimes 1841556Srgrimes while (pt >= str) 18576351Skris *pt-- = '0'; 1861556Srgrimes if (val != (u_long)0) 1871556Srgrimes return(-1); 1881556Srgrimes return(0); 1891556Srgrimes} 1901556Srgrimes 1911556Srgrimes#ifndef NET2_STAT 1921556Srgrimes/* 1931556Srgrimes * uqd_oct() 1941556Srgrimes * convert an u_quad_t to an octal string. one of many oddball field 1951556Srgrimes * termination characters are used by the various versions of tar in the 19676351Skris * different fields. term selects which kind to use. str is '0' padded 1971556Srgrimes * at the front to len. we are unable to use only one format as many old 1981556Srgrimes * tar readers are very cranky about this. 1991556Srgrimes * Return: 2001556Srgrimes * 0 if the number fit into the string, -1 otherwise 2011556Srgrimes */ 2021556Srgrimes 2031556Srgrimesstatic int 20490113Simpuqd_oct(u_quad_t val, char *str, int len, int term) 2051556Srgrimes{ 20690113Simp char *pt; 2078855Srgrimes 2081556Srgrimes /* 2091556Srgrimes * term selects the appropriate character(s) for the end of the string 2101556Srgrimes */ 2111556Srgrimes pt = str + len - 1; 2121556Srgrimes switch(term) { 2131556Srgrimes case 3: 2141556Srgrimes *pt-- = '\0'; 2151556Srgrimes break; 2161556Srgrimes case 2: 2171556Srgrimes *pt-- = ' '; 2181556Srgrimes *pt-- = '\0'; 2191556Srgrimes break; 2201556Srgrimes case 1: 2211556Srgrimes *pt-- = ' '; 2221556Srgrimes break; 2231556Srgrimes case 0: 2241556Srgrimes default: 2251556Srgrimes *pt-- = '\0'; 2261556Srgrimes *pt-- = ' '; 2271556Srgrimes break; 2281556Srgrimes } 2291556Srgrimes 2301556Srgrimes /* 2311556Srgrimes * convert and blank pad if there is space 2321556Srgrimes */ 2331556Srgrimes while (pt >= str) { 2341556Srgrimes *pt-- = '0' + (char)(val & 0x7); 2351556Srgrimes if ((val = val >> 3) == 0) 2361556Srgrimes break; 2371556Srgrimes } 2381556Srgrimes 2391556Srgrimes while (pt >= str) 24076351Skris *pt-- = '0'; 2411556Srgrimes if (val != (u_quad_t)0) 2421556Srgrimes return(-1); 2431556Srgrimes return(0); 2441556Srgrimes} 2451556Srgrimes#endif 2461556Srgrimes 2471556Srgrimes/* 2481556Srgrimes * tar_chksm() 2491556Srgrimes * calculate the checksum for a tar block counting the checksum field as 25046684Skris * all blanks (BLNKSUM is that value pre-calculated, the sum of 8 blanks). 2511556Srgrimes * NOTE: we use len to short circuit summing 0's on write since we ALWAYS 2521556Srgrimes * pad headers with 0. 2531556Srgrimes * Return: 2541556Srgrimes * unsigned long checksum 2551556Srgrimes */ 2561556Srgrimes 2571556Srgrimesstatic u_long 25890113Simptar_chksm(char *blk, int len) 2591556Srgrimes{ 26090113Simp char *stop; 26190113Simp char *pt; 26246684Skris u_long chksm = BLNKSUM; /* initial value is checksum field sum */ 2631556Srgrimes 2641556Srgrimes /* 2651556Srgrimes * add the part of the block before the checksum field 2661556Srgrimes */ 2671556Srgrimes pt = blk; 2681556Srgrimes stop = blk + CHK_OFFSET; 2698855Srgrimes while (pt < stop) 2708855Srgrimes chksm += (u_long)(*pt++ & 0xff); 2711556Srgrimes /* 2721556Srgrimes * move past the checksum field and keep going, spec counts the 2731556Srgrimes * checksum field as the sum of 8 blanks (which is pre-computed as 2741556Srgrimes * BLNKSUM). 2751556Srgrimes * ASSUMED: len is greater than CHK_OFFSET. (len is where our 0 padding 2761556Srgrimes * starts, no point in summing zero's) 2771556Srgrimes */ 2781556Srgrimes pt += CHK_LEN; 2791556Srgrimes stop = blk + len; 2801556Srgrimes while (pt < stop) 2818855Srgrimes chksm += (u_long)(*pt++ & 0xff); 2821556Srgrimes return(chksm); 2831556Srgrimes} 2841556Srgrimes 2851556Srgrimes/* 2861556Srgrimes * Routines for old BSD style tar (also made portable to sysV tar) 2871556Srgrimes */ 2881556Srgrimes 2891556Srgrimes/* 2901556Srgrimes * tar_id() 2911556Srgrimes * determine if a block given to us is a valid tar header (and not a USTAR 292222177Suqs * header). We have to be on the lookout for those pesky blocks of all 2931556Srgrimes * zero's. 2941556Srgrimes * Return: 2951556Srgrimes * 0 if a tar header, -1 otherwise 2961556Srgrimes */ 2971556Srgrimes 2981556Srgrimesint 29990113Simptar_id(char *blk, int size) 3001556Srgrimes{ 30190113Simp HD_TAR *hd; 30290113Simp HD_USTAR *uhd; 3031556Srgrimes 3041556Srgrimes if (size < BLKMULT) 3051556Srgrimes return(-1); 3061556Srgrimes hd = (HD_TAR *)blk; 3071556Srgrimes uhd = (HD_USTAR *)blk; 3081556Srgrimes 3091556Srgrimes /* 3101556Srgrimes * check for block of zero's first, a simple and fast test, then make 3111556Srgrimes * sure this is not a ustar header by looking for the ustar magic 3121556Srgrimes * cookie. We should use TMAGLEN, but some USTAR archive programs are 3131556Srgrimes * wrong and create archives missing the \0. Last we check the 3141556Srgrimes * checksum. If this is ok we have to assume it is a valid header. 3151556Srgrimes */ 3161556Srgrimes if (hd->name[0] == '\0') 3171556Srgrimes return(-1); 3181556Srgrimes if (strncmp(uhd->magic, TMAGIC, TMAGLEN - 1) == 0) 3191556Srgrimes return(-1); 3201556Srgrimes if (asc_ul(hd->chksum,sizeof(hd->chksum),OCT) != tar_chksm(blk,BLKMULT)) 3211556Srgrimes return(-1); 3221556Srgrimes return(0); 3231556Srgrimes} 3241556Srgrimes 3251556Srgrimes/* 3261556Srgrimes * tar_opt() 3271556Srgrimes * handle tar format specific -o options 3281556Srgrimes * Return: 3291556Srgrimes * 0 if ok -1 otherwise 3301556Srgrimes */ 3311556Srgrimes 3321556Srgrimesint 3331556Srgrimestar_opt(void) 3341556Srgrimes{ 3351556Srgrimes OPLIST *opt; 3361556Srgrimes 3371556Srgrimes while ((opt = opt_next()) != NULL) { 3381556Srgrimes if (strcmp(opt->name, TAR_OPTION) || 3391556Srgrimes strcmp(opt->value, TAR_NODIR)) { 34076017Skris paxwarn(1, "Unknown tar format -o option/value pair %s=%s", 3411556Srgrimes opt->name, opt->value); 34276017Skris paxwarn(1,"%s=%s is the only supported tar format option", 3431556Srgrimes TAR_OPTION, TAR_NODIR); 3441556Srgrimes return(-1); 3451556Srgrimes } 3461556Srgrimes 3471556Srgrimes /* 3481556Srgrimes * we only support one option, and only when writing 3491556Srgrimes */ 3501556Srgrimes if ((act != APPND) && (act != ARCHIVE)) { 35176017Skris paxwarn(1, "%s=%s is only supported when writing.", 3521556Srgrimes opt->name, opt->value); 3531556Srgrimes return(-1); 3541556Srgrimes } 3551556Srgrimes tar_nodir = 1; 3561556Srgrimes } 3571556Srgrimes return(0); 3581556Srgrimes} 3591556Srgrimes 3601556Srgrimes 3611556Srgrimes/* 3621556Srgrimes * tar_rd() 3631556Srgrimes * extract the values out of block already determined to be a tar header. 3641556Srgrimes * store the values in the ARCHD parameter. 3651556Srgrimes * Return: 3661556Srgrimes * 0 3671556Srgrimes */ 3681556Srgrimes 3691556Srgrimesint 37090113Simptar_rd(ARCHD *arcn, char *buf) 3711556Srgrimes{ 37290113Simp HD_TAR *hd; 37390113Simp char *pt; 3741556Srgrimes 3751556Srgrimes /* 3761556Srgrimes * we only get proper sized buffers passed to us 3771556Srgrimes */ 3781556Srgrimes if (tar_id(buf, BLKMULT) < 0) 3791556Srgrimes return(-1); 3801556Srgrimes arcn->org_name = arcn->name; 3811556Srgrimes arcn->sb.st_nlink = 1; 3821556Srgrimes arcn->pat = NULL; 3831556Srgrimes 3841556Srgrimes /* 3851556Srgrimes * copy out the name and values in the stat buffer 3861556Srgrimes */ 3871556Srgrimes hd = (HD_TAR *)buf; 388137645Syar /* 389137645Syar * old tar format specifies the name always be null-terminated, 390137645Syar * but let's be robust to broken archives. 391137645Syar * the same applies to handling links below. 392137645Syar */ 393137645Syar arcn->nlen = l_strncpy(arcn->name, hd->name, 394137645Syar MIN(sizeof(hd->name), sizeof(arcn->name)) - 1); 3951556Srgrimes arcn->name[arcn->nlen] = '\0'; 3961556Srgrimes arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode,sizeof(hd->mode),OCT) & 3971556Srgrimes 0xfff); 3981556Srgrimes arcn->sb.st_uid = (uid_t)asc_ul(hd->uid, sizeof(hd->uid), OCT); 3991556Srgrimes arcn->sb.st_gid = (gid_t)asc_ul(hd->gid, sizeof(hd->gid), OCT); 40076351Skris#ifdef NET2_STAT 40176351Skris arcn->sb.st_size = (off_t)asc_ul(hd->size, sizeof(hd->size), OCT); 40285618Sdillon arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT); 40376351Skris#else 40476351Skris arcn->sb.st_size = (off_t)asc_uqd(hd->size, sizeof(hd->size), OCT); 40585618Sdillon arcn->sb.st_mtime = (time_t)asc_uqd(hd->mtime, sizeof(hd->mtime), OCT); 40676351Skris#endif 4071556Srgrimes arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime; 4081556Srgrimes 4091556Srgrimes /* 4101556Srgrimes * have to look at the last character, it may be a '/' and that is used 4111556Srgrimes * to encode this as a directory 4121556Srgrimes */ 4131556Srgrimes pt = &(arcn->name[arcn->nlen - 1]); 4141556Srgrimes arcn->pad = 0; 4151556Srgrimes arcn->skip = 0; 4161556Srgrimes switch(hd->linkflag) { 4171556Srgrimes case SYMTYPE: 4181556Srgrimes /* 4191556Srgrimes * symbolic link, need to get the link name and set the type in 4201556Srgrimes * the st_mode so -v printing will look correct. 4211556Srgrimes */ 4221556Srgrimes arcn->type = PAX_SLK; 4231556Srgrimes arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname, 424137645Syar MIN(sizeof(hd->linkname), sizeof(arcn->ln_name)) - 1); 4251556Srgrimes arcn->ln_name[arcn->ln_nlen] = '\0'; 4261556Srgrimes arcn->sb.st_mode |= S_IFLNK; 4271556Srgrimes break; 4281556Srgrimes case LNKTYPE: 4291556Srgrimes /* 4301556Srgrimes * hard link, need to get the link name, set the type in the 4311556Srgrimes * st_mode and st_nlink so -v printing will look better. 4321556Srgrimes */ 4331556Srgrimes arcn->type = PAX_HLK; 4341556Srgrimes arcn->sb.st_nlink = 2; 4351556Srgrimes arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname, 436137645Syar MIN(sizeof(hd->linkname), sizeof(arcn->ln_name)) - 1); 4371556Srgrimes arcn->ln_name[arcn->ln_nlen] = '\0'; 4381556Srgrimes 4391556Srgrimes /* 4401556Srgrimes * no idea of what type this thing really points at, but 4411556Srgrimes * we set something for printing only. 4421556Srgrimes */ 4431556Srgrimes arcn->sb.st_mode |= S_IFREG; 4441556Srgrimes break; 44576351Skris case DIRTYPE: 44676351Skris /* 44776351Skris * It is a directory, set the mode for -v printing 44876351Skris */ 44976351Skris arcn->type = PAX_DIR; 45076351Skris arcn->sb.st_mode |= S_IFDIR; 45176351Skris arcn->sb.st_nlink = 2; 45276351Skris arcn->ln_name[0] = '\0'; 45376351Skris arcn->ln_nlen = 0; 45476351Skris break; 4551556Srgrimes case AREGTYPE: 4561556Srgrimes case REGTYPE: 4571556Srgrimes default: 4581556Srgrimes /* 4591556Srgrimes * If we have a trailing / this is a directory and NOT a file. 4601556Srgrimes */ 4611556Srgrimes arcn->ln_name[0] = '\0'; 4621556Srgrimes arcn->ln_nlen = 0; 4631556Srgrimes if (*pt == '/') { 4641556Srgrimes /* 4651556Srgrimes * it is a directory, set the mode for -v printing 4661556Srgrimes */ 4671556Srgrimes arcn->type = PAX_DIR; 4681556Srgrimes arcn->sb.st_mode |= S_IFDIR; 4691556Srgrimes arcn->sb.st_nlink = 2; 4701556Srgrimes } else { 4711556Srgrimes /* 4721556Srgrimes * have a file that will be followed by data. Set the 47346684Skris * skip value to the size field and calculate the size 4741556Srgrimes * of the padding. 4751556Srgrimes */ 4761556Srgrimes arcn->type = PAX_REG; 4771556Srgrimes arcn->sb.st_mode |= S_IFREG; 4781556Srgrimes arcn->pad = TAR_PAD(arcn->sb.st_size); 4791556Srgrimes arcn->skip = arcn->sb.st_size; 4801556Srgrimes } 4811556Srgrimes break; 4821556Srgrimes } 4831556Srgrimes 4841556Srgrimes /* 4851556Srgrimes * strip off any trailing slash. 4861556Srgrimes */ 4871556Srgrimes if (*pt == '/') { 4888855Srgrimes *pt = '\0'; 4891556Srgrimes --arcn->nlen; 4901556Srgrimes } 4911556Srgrimes return(0); 4921556Srgrimes} 4931556Srgrimes 4941556Srgrimes/* 4951556Srgrimes * tar_wr() 4961556Srgrimes * write a tar header for the file specified in the ARCHD to the archive. 4971556Srgrimes * Have to check for file types that cannot be stored and file names that 4981556Srgrimes * are too long. Be careful of the term (last arg) to ul_oct, each field 4991556Srgrimes * of tar has it own spec for the termination character(s). 5001556Srgrimes * ASSUMED: space after header in header block is zero filled 5011556Srgrimes * Return: 5021556Srgrimes * 0 if file has data to be written after the header, 1 if file has NO 5031556Srgrimes * data to write after the header, -1 if archive write failed 5041556Srgrimes */ 5051556Srgrimes 5061556Srgrimesint 50790113Simptar_wr(ARCHD *arcn) 5081556Srgrimes{ 50990113Simp HD_TAR *hd; 5101556Srgrimes int len; 511164699Sru HD_TAR hdblk; 5121556Srgrimes 5131556Srgrimes /* 514102230Strhodes * check for those file system types which tar cannot store 5151556Srgrimes */ 5161556Srgrimes switch(arcn->type) { 5171556Srgrimes case PAX_DIR: 5181556Srgrimes /* 5191556Srgrimes * user asked that dirs not be written to the archive 5201556Srgrimes */ 5211556Srgrimes if (tar_nodir) 5221556Srgrimes return(1); 5231556Srgrimes break; 5241556Srgrimes case PAX_CHR: 52576017Skris paxwarn(1, "Tar cannot archive a character device %s", 5261556Srgrimes arcn->org_name); 5271556Srgrimes return(1); 5281556Srgrimes case PAX_BLK: 52976017Skris paxwarn(1, "Tar cannot archive a block device %s", arcn->org_name); 5301556Srgrimes return(1); 5311556Srgrimes case PAX_SCK: 53276017Skris paxwarn(1, "Tar cannot archive a socket %s", arcn->org_name); 5331556Srgrimes return(1); 5341556Srgrimes case PAX_FIF: 53576017Skris paxwarn(1, "Tar cannot archive a fifo %s", arcn->org_name); 5361556Srgrimes return(1); 5371556Srgrimes case PAX_SLK: 5381556Srgrimes case PAX_HLK: 5391556Srgrimes case PAX_HRG: 540137645Syar if (arcn->ln_nlen >= (int)sizeof(hd->linkname)) { 54176017Skris paxwarn(1,"Link name too long for tar %s", arcn->ln_name); 5421556Srgrimes return(1); 5431556Srgrimes } 5441556Srgrimes break; 5451556Srgrimes case PAX_REG: 5461556Srgrimes case PAX_CTG: 5471556Srgrimes default: 5481556Srgrimes break; 5491556Srgrimes } 5501556Srgrimes 5511556Srgrimes /* 5521556Srgrimes * check file name len, remember extra char for dirs (the / at the end) 5531556Srgrimes */ 5541556Srgrimes len = arcn->nlen; 5551556Srgrimes if (arcn->type == PAX_DIR) 5561556Srgrimes ++len; 557114469Sobrien if (len >= (int)sizeof(hd->name)) { 55876017Skris paxwarn(1, "File name too long for tar %s", arcn->name); 5591556Srgrimes return(1); 5601556Srgrimes } 5611556Srgrimes 5621556Srgrimes /* 5631556Srgrimes * copy the data out of the ARCHD into the tar header based on the type 5641556Srgrimes * of the file. Remember many tar readers want the unused fields to be 5651556Srgrimes * padded with zero. We set the linkflag field (type), the linkname 5661556Srgrimes * (or zero if not used),the size, and set the padding (if any) to be 5671556Srgrimes * added after the file data (0 for all other types, as they only have 5681556Srgrimes * a header) 5691556Srgrimes */ 570164699Sru hd = &hdblk; 57176351Skris l_strncpy(hd->name, arcn->name, sizeof(hd->name) - 1); 57276351Skris hd->name[sizeof(hd->name) - 1] = '\0'; 5731556Srgrimes arcn->pad = 0; 5741556Srgrimes 5751556Srgrimes if (arcn->type == PAX_DIR) { 5761556Srgrimes /* 5771556Srgrimes * directories are the same as files, except have a filename 5781556Srgrimes * that ends with a /, we add the slash here. No data follows, 5791556Srgrimes * dirs, so no pad. 5801556Srgrimes */ 5811556Srgrimes hd->linkflag = AREGTYPE; 58276017Skris memset(hd->linkname, 0, sizeof(hd->linkname)); 5831556Srgrimes hd->name[len-1] = '/'; 5841556Srgrimes if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1)) 5851556Srgrimes goto out; 5861556Srgrimes } else if (arcn->type == PAX_SLK) { 5871556Srgrimes /* 5881556Srgrimes * no data follows this file, so no pad 5891556Srgrimes */ 5901556Srgrimes hd->linkflag = SYMTYPE; 59176351Skris l_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname) - 1); 59276351Skris hd->linkname[sizeof(hd->linkname) - 1] = '\0'; 5931556Srgrimes if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1)) 5941556Srgrimes goto out; 5951556Srgrimes } else if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG)) { 5961556Srgrimes /* 5971556Srgrimes * no data follows this file, so no pad 5981556Srgrimes */ 5991556Srgrimes hd->linkflag = LNKTYPE; 60076351Skris l_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname) - 1); 60176351Skris hd->linkname[sizeof(hd->linkname) - 1] = '\0'; 6021556Srgrimes if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1)) 6031556Srgrimes goto out; 6041556Srgrimes } else { 6051556Srgrimes /* 6061556Srgrimes * data follows this file, so set the pad 6071556Srgrimes */ 6081556Srgrimes hd->linkflag = AREGTYPE; 60976017Skris memset(hd->linkname, 0, sizeof(hd->linkname)); 6101556Srgrimes# ifdef NET2_STAT 6111556Srgrimes if (ul_oct((u_long)arcn->sb.st_size, hd->size, 6121556Srgrimes sizeof(hd->size), 1)) { 6131556Srgrimes# else 6141556Srgrimes if (uqd_oct((u_quad_t)arcn->sb.st_size, hd->size, 6151556Srgrimes sizeof(hd->size), 1)) { 6161556Srgrimes# endif 61776017Skris paxwarn(1,"File is too large for tar %s", arcn->org_name); 6181556Srgrimes return(1); 6191556Srgrimes } 6201556Srgrimes arcn->pad = TAR_PAD(arcn->sb.st_size); 6211556Srgrimes } 6221556Srgrimes 6231556Srgrimes /* 6241556Srgrimes * copy those fields that are independent of the type 6251556Srgrimes */ 6261556Srgrimes if (ul_oct((u_long)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 0) || 6271556Srgrimes ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 0) || 6281556Srgrimes ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 0) || 6291556Srgrimes ul_oct((u_long)arcn->sb.st_mtime, hd->mtime, sizeof(hd->mtime), 1)) 6301556Srgrimes goto out; 6311556Srgrimes 6321556Srgrimes /* 6331556Srgrimes * calculate and add the checksum, then write the header. A return of 6341556Srgrimes * 0 tells the caller to now write the file data, 1 says no data needs 6351556Srgrimes * to be written 6361556Srgrimes */ 637164699Sru if (ul_oct(tar_chksm((char *)&hdblk, sizeof(HD_TAR)), hd->chksum, 63876351Skris sizeof(hd->chksum), 3)) 6391556Srgrimes goto out; 640164699Sru if (wr_rdbuf((char *)&hdblk, sizeof(HD_TAR)) < 0) 6411556Srgrimes return(-1); 6421556Srgrimes if (wr_skip((off_t)(BLKMULT - sizeof(HD_TAR))) < 0) 6431556Srgrimes return(-1); 6441556Srgrimes if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG)) 6451556Srgrimes return(0); 6461556Srgrimes return(1); 6471556Srgrimes 6481556Srgrimes out: 6491556Srgrimes /* 6501556Srgrimes * header field is out of range 6511556Srgrimes */ 65276017Skris paxwarn(1, "Tar header field is too small for %s", arcn->org_name); 6531556Srgrimes return(1); 6541556Srgrimes} 6551556Srgrimes 6561556Srgrimes/* 6571556Srgrimes * Routines for POSIX ustar 6581556Srgrimes */ 6591556Srgrimes 6601556Srgrimes/* 6611556Srgrimes * ustar_strd() 6621556Srgrimes * initialization for ustar read 6631556Srgrimes * Return: 6641556Srgrimes * 0 if ok, -1 otherwise 6651556Srgrimes */ 6661556Srgrimes 6671556Srgrimesint 6681556Srgrimesustar_strd(void) 6691556Srgrimes{ 6701556Srgrimes if ((usrtb_start() < 0) || (grptb_start() < 0)) 6711556Srgrimes return(-1); 6721556Srgrimes return(0); 6731556Srgrimes} 6741556Srgrimes 6751556Srgrimes/* 6761556Srgrimes * ustar_stwr() 6771556Srgrimes * initialization for ustar write 6781556Srgrimes * Return: 6791556Srgrimes * 0 if ok, -1 otherwise 6801556Srgrimes */ 6811556Srgrimes 6821556Srgrimesint 6831556Srgrimesustar_stwr(void) 6841556Srgrimes{ 6851556Srgrimes if ((uidtb_start() < 0) || (gidtb_start() < 0)) 6861556Srgrimes return(-1); 6871556Srgrimes return(0); 6881556Srgrimes} 6891556Srgrimes 6901556Srgrimes/* 6911556Srgrimes * ustar_id() 6921556Srgrimes * determine if a block given to us is a valid ustar header. We have to 6931556Srgrimes * be on the lookout for those pesky blocks of all zero's 6941556Srgrimes * Return: 6951556Srgrimes * 0 if a ustar header, -1 otherwise 6961556Srgrimes */ 6971556Srgrimes 6981556Srgrimesint 6991556Srgrimesustar_id(char *blk, int size) 7001556Srgrimes{ 70190113Simp HD_USTAR *hd; 7021556Srgrimes 7031556Srgrimes if (size < BLKMULT) 7041556Srgrimes return(-1); 7051556Srgrimes hd = (HD_USTAR *)blk; 7061556Srgrimes 7071556Srgrimes /* 7081556Srgrimes * check for block of zero's first, a simple and fast test then check 7091556Srgrimes * ustar magic cookie. We should use TMAGLEN, but some USTAR archive 7101556Srgrimes * programs are fouled up and create archives missing the \0. Last we 7111556Srgrimes * check the checksum. If ok we have to assume it is a valid header. 7121556Srgrimes */ 7131556Srgrimes if (hd->name[0] == '\0') 7141556Srgrimes return(-1); 7151556Srgrimes if (strncmp(hd->magic, TMAGIC, TMAGLEN - 1) != 0) 7161556Srgrimes return(-1); 7171556Srgrimes if (asc_ul(hd->chksum,sizeof(hd->chksum),OCT) != tar_chksm(blk,BLKMULT)) 7181556Srgrimes return(-1); 7191556Srgrimes return(0); 7201556Srgrimes} 7211556Srgrimes 7221556Srgrimes/* 7231556Srgrimes * ustar_rd() 7241556Srgrimes * extract the values out of block already determined to be a ustar header. 7251556Srgrimes * store the values in the ARCHD parameter. 7261556Srgrimes * Return: 7271556Srgrimes * 0 7281556Srgrimes */ 7291556Srgrimes 7301556Srgrimesint 73190113Simpustar_rd(ARCHD *arcn, char *buf) 7321556Srgrimes{ 73390113Simp HD_USTAR *hd; 73490113Simp char *dest; 73590113Simp int cnt = 0; 7361556Srgrimes dev_t devmajor; 7371556Srgrimes dev_t devminor; 7381556Srgrimes 7391556Srgrimes /* 7401556Srgrimes * we only get proper sized buffers 7411556Srgrimes */ 7421556Srgrimes if (ustar_id(buf, BLKMULT) < 0) 7431556Srgrimes return(-1); 7441556Srgrimes arcn->org_name = arcn->name; 7451556Srgrimes arcn->sb.st_nlink = 1; 7461556Srgrimes arcn->pat = NULL; 74776351Skris arcn->nlen = 0; 7481556Srgrimes hd = (HD_USTAR *)buf; 7491556Srgrimes 7501556Srgrimes /* 7511556Srgrimes * see if the filename is split into two parts. if, so joint the parts. 7521556Srgrimes * we copy the prefix first and add a / between the prefix and name. 7531556Srgrimes */ 7541556Srgrimes dest = arcn->name; 7551556Srgrimes if (*(hd->prefix) != '\0') { 756137645Syar cnt = l_strncpy(dest, hd->prefix, 757137645Syar MIN(sizeof(hd->prefix), sizeof(arcn->name) - 2)); 75876351Skris dest += cnt; 7591556Srgrimes *dest++ = '/'; 76076351Skris cnt++; 7611556Srgrimes } 762137645Syar /* 763137645Syar * ustar format specifies the name may be unterminated 764137645Syar * if it fills the entire field. this also applies to 765137645Syar * the prefix and the linkname. 766137645Syar */ 767137645Syar arcn->nlen = cnt + l_strncpy(dest, hd->name, 768137645Syar MIN(sizeof(hd->name), sizeof(arcn->name) - cnt - 1)); 7691556Srgrimes arcn->name[arcn->nlen] = '\0'; 7701556Srgrimes 7711556Srgrimes /* 7721556Srgrimes * follow the spec to the letter. we should only have mode bits, strip 7731556Srgrimes * off all other crud we may be passed. 7741556Srgrimes */ 7751556Srgrimes arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode, sizeof(hd->mode), OCT) & 7761556Srgrimes 0xfff); 77776351Skris#ifdef NET2_STAT 77876351Skris arcn->sb.st_size = (off_t)asc_ul(hd->size, sizeof(hd->size), OCT); 77985618Sdillon arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT); 78076351Skris#else 78176351Skris arcn->sb.st_size = (off_t)asc_uqd(hd->size, sizeof(hd->size), OCT); 78285618Sdillon arcn->sb.st_mtime = (time_t)asc_uqd(hd->mtime, sizeof(hd->mtime), OCT); 78376351Skris#endif 7841556Srgrimes arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime; 7851556Srgrimes 7861556Srgrimes /* 7871556Srgrimes * If we can find the ascii names for gname and uname in the password 7881556Srgrimes * and group files we will use the uid's and gid they bind. Otherwise 7891556Srgrimes * we use the uid and gid values stored in the header. (This is what 79046684Skris * the POSIX spec wants). 7911556Srgrimes */ 7921556Srgrimes hd->gname[sizeof(hd->gname) - 1] = '\0'; 7931556Srgrimes if (gid_name(hd->gname, &(arcn->sb.st_gid)) < 0) 7941556Srgrimes arcn->sb.st_gid = (gid_t)asc_ul(hd->gid, sizeof(hd->gid), OCT); 7951556Srgrimes hd->uname[sizeof(hd->uname) - 1] = '\0'; 7961556Srgrimes if (uid_name(hd->uname, &(arcn->sb.st_uid)) < 0) 7971556Srgrimes arcn->sb.st_uid = (uid_t)asc_ul(hd->uid, sizeof(hd->uid), OCT); 7981556Srgrimes 7991556Srgrimes /* 8001556Srgrimes * set the defaults, these may be changed depending on the file type 8011556Srgrimes */ 8021556Srgrimes arcn->ln_name[0] = '\0'; 8031556Srgrimes arcn->ln_nlen = 0; 8041556Srgrimes arcn->pad = 0; 8051556Srgrimes arcn->skip = 0; 8061556Srgrimes arcn->sb.st_rdev = (dev_t)0; 8071556Srgrimes 8081556Srgrimes /* 8091556Srgrimes * set the mode and PAX type according to the typeflag in the header 8101556Srgrimes */ 8111556Srgrimes switch(hd->typeflag) { 8121556Srgrimes case FIFOTYPE: 8131556Srgrimes arcn->type = PAX_FIF; 8141556Srgrimes arcn->sb.st_mode |= S_IFIFO; 8151556Srgrimes break; 8161556Srgrimes case DIRTYPE: 8171556Srgrimes arcn->type = PAX_DIR; 8181556Srgrimes arcn->sb.st_mode |= S_IFDIR; 8191556Srgrimes arcn->sb.st_nlink = 2; 8201556Srgrimes 8211556Srgrimes /* 8221556Srgrimes * Some programs that create ustar archives append a '/' 8231556Srgrimes * to the pathname for directories. This clearly violates 8241556Srgrimes * ustar specs, but we will silently strip it off anyway. 8251556Srgrimes */ 8261556Srgrimes if (arcn->name[arcn->nlen - 1] == '/') 8271556Srgrimes arcn->name[--arcn->nlen] = '\0'; 8281556Srgrimes break; 8291556Srgrimes case BLKTYPE: 8301556Srgrimes case CHRTYPE: 8311556Srgrimes /* 8321556Srgrimes * this type requires the rdev field to be set. 8331556Srgrimes */ 8341556Srgrimes if (hd->typeflag == BLKTYPE) { 8351556Srgrimes arcn->type = PAX_BLK; 8361556Srgrimes arcn->sb.st_mode |= S_IFBLK; 8371556Srgrimes } else { 8381556Srgrimes arcn->type = PAX_CHR; 8391556Srgrimes arcn->sb.st_mode |= S_IFCHR; 8401556Srgrimes } 8411556Srgrimes devmajor = (dev_t)asc_ul(hd->devmajor,sizeof(hd->devmajor),OCT); 8421556Srgrimes devminor = (dev_t)asc_ul(hd->devminor,sizeof(hd->devminor),OCT); 8431556Srgrimes arcn->sb.st_rdev = TODEV(devmajor, devminor); 8441556Srgrimes break; 8451556Srgrimes case SYMTYPE: 8461556Srgrimes case LNKTYPE: 8471556Srgrimes if (hd->typeflag == SYMTYPE) { 8481556Srgrimes arcn->type = PAX_SLK; 8491556Srgrimes arcn->sb.st_mode |= S_IFLNK; 8501556Srgrimes } else { 8511556Srgrimes arcn->type = PAX_HLK; 8521556Srgrimes /* 8531556Srgrimes * so printing looks better 8541556Srgrimes */ 8551556Srgrimes arcn->sb.st_mode |= S_IFREG; 8561556Srgrimes arcn->sb.st_nlink = 2; 8571556Srgrimes } 8581556Srgrimes /* 8591556Srgrimes * copy the link name 8601556Srgrimes */ 8611556Srgrimes arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname, 862137645Syar MIN(sizeof(hd->linkname), sizeof(arcn->ln_name) - 1)); 8631556Srgrimes arcn->ln_name[arcn->ln_nlen] = '\0'; 8641556Srgrimes break; 8651556Srgrimes case CONTTYPE: 8661556Srgrimes case AREGTYPE: 8671556Srgrimes case REGTYPE: 8681556Srgrimes default: 8691556Srgrimes /* 8701556Srgrimes * these types have file data that follows. Set the skip and 8711556Srgrimes * pad fields. 8721556Srgrimes */ 8731556Srgrimes arcn->type = PAX_REG; 8741556Srgrimes arcn->pad = TAR_PAD(arcn->sb.st_size); 8751556Srgrimes arcn->skip = arcn->sb.st_size; 8761556Srgrimes arcn->sb.st_mode |= S_IFREG; 8771556Srgrimes break; 8781556Srgrimes } 8791556Srgrimes return(0); 8801556Srgrimes} 8811556Srgrimes 8821556Srgrimes/* 8831556Srgrimes * ustar_wr() 8841556Srgrimes * write a ustar header for the file specified in the ARCHD to the archive 8851556Srgrimes * Have to check for file types that cannot be stored and file names that 8861556Srgrimes * are too long. Be careful of the term (last arg) to ul_oct, we only use 8871556Srgrimes * '\0' for the termination character (this is different than picky tar) 8881556Srgrimes * ASSUMED: space after header in header block is zero filled 8891556Srgrimes * Return: 8901556Srgrimes * 0 if file has data to be written after the header, 1 if file has NO 8911556Srgrimes * data to write after the header, -1 if archive write failed 8921556Srgrimes */ 8931556Srgrimes 8941556Srgrimesint 89590113Simpustar_wr(ARCHD *arcn) 8961556Srgrimes{ 89790113Simp HD_USTAR *hd; 89890113Simp char *pt; 899164699Sru HD_USTAR hdblk; 9001556Srgrimes 9011556Srgrimes /* 902102230Strhodes * check for those file system types ustar cannot store 9031556Srgrimes */ 9041556Srgrimes if (arcn->type == PAX_SCK) { 90576017Skris paxwarn(1, "Ustar cannot archive a socket %s", arcn->org_name); 9061556Srgrimes return(1); 9071556Srgrimes } 9081556Srgrimes 9091556Srgrimes /* 9101556Srgrimes * check the length of the linkname 9111556Srgrimes */ 9121556Srgrimes if (((arcn->type == PAX_SLK) || (arcn->type == PAX_HLK) || 913114469Sobrien (arcn->type == PAX_HRG)) && 914137645Syar (arcn->ln_nlen > (int)sizeof(hd->linkname))) { 91576017Skris paxwarn(1, "Link name too long for ustar %s", arcn->ln_name); 9161556Srgrimes return(1); 9171556Srgrimes } 9181556Srgrimes 9191556Srgrimes /* 9201556Srgrimes * split the path name into prefix and name fields (if needed). if 9211556Srgrimes * pt != arcn->name, the name has to be split 9221556Srgrimes */ 9231556Srgrimes if ((pt = name_split(arcn->name, arcn->nlen)) == NULL) { 92476017Skris paxwarn(1, "File name too long for ustar %s", arcn->name); 9251556Srgrimes return(1); 9261556Srgrimes } 927164699Sru hd = &hdblk; 9281556Srgrimes arcn->pad = 0L; 9291556Srgrimes 9301556Srgrimes /* 9311556Srgrimes * split the name, or zero out the prefix 9321556Srgrimes */ 9331556Srgrimes if (pt != arcn->name) { 9341556Srgrimes /* 9351556Srgrimes * name was split, pt points at the / where the split is to 9361556Srgrimes * occur, we remove the / and copy the first part to the prefix 9371556Srgrimes */ 9381556Srgrimes *pt = '\0'; 939137645Syar l_strncpy(hd->prefix, arcn->name, sizeof(hd->prefix)); 9401556Srgrimes *pt++ = '/'; 9411556Srgrimes } else 94276017Skris memset(hd->prefix, 0, sizeof(hd->prefix)); 9431556Srgrimes 9441556Srgrimes /* 9451556Srgrimes * copy the name part. this may be the whole path or the part after 946137645Syar * the prefix. both the name and prefix may fill the entire field. 9471556Srgrimes */ 948137645Syar l_strncpy(hd->name, pt, sizeof(hd->name)); 9491556Srgrimes 9508855Srgrimes /* 9511556Srgrimes * set the fields in the header that are type dependent 9521556Srgrimes */ 9531556Srgrimes switch(arcn->type) { 9541556Srgrimes case PAX_DIR: 9551556Srgrimes hd->typeflag = DIRTYPE; 95676017Skris memset(hd->linkname, 0, sizeof(hd->linkname)); 95776017Skris memset(hd->devmajor, 0, sizeof(hd->devmajor)); 95876017Skris memset(hd->devminor, 0, sizeof(hd->devminor)); 9591556Srgrimes if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3)) 9601556Srgrimes goto out; 9611556Srgrimes break; 9621556Srgrimes case PAX_CHR: 9631556Srgrimes case PAX_BLK: 9641556Srgrimes if (arcn->type == PAX_CHR) 9651556Srgrimes hd->typeflag = CHRTYPE; 9661556Srgrimes else 9671556Srgrimes hd->typeflag = BLKTYPE; 96876017Skris memset(hd->linkname, 0, sizeof(hd->linkname)); 9691556Srgrimes if (ul_oct((u_long)MAJOR(arcn->sb.st_rdev), hd->devmajor, 9701556Srgrimes sizeof(hd->devmajor), 3) || 9711556Srgrimes ul_oct((u_long)MINOR(arcn->sb.st_rdev), hd->devminor, 9721556Srgrimes sizeof(hd->devminor), 3) || 9731556Srgrimes ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3)) 9741556Srgrimes goto out; 9751556Srgrimes break; 9761556Srgrimes case PAX_FIF: 9771556Srgrimes hd->typeflag = FIFOTYPE; 97876017Skris memset(hd->linkname, 0, sizeof(hd->linkname)); 97976017Skris memset(hd->devmajor, 0, sizeof(hd->devmajor)); 98076017Skris memset(hd->devminor, 0, sizeof(hd->devminor)); 9811556Srgrimes if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3)) 9821556Srgrimes goto out; 9831556Srgrimes break; 9841556Srgrimes case PAX_SLK: 9851556Srgrimes case PAX_HLK: 9861556Srgrimes case PAX_HRG: 9871556Srgrimes if (arcn->type == PAX_SLK) 9881556Srgrimes hd->typeflag = SYMTYPE; 9891556Srgrimes else 9901556Srgrimes hd->typeflag = LNKTYPE; 991137645Syar /* the link name may occupy the entire field in ustar */ 992137645Syar l_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname)); 99376017Skris memset(hd->devmajor, 0, sizeof(hd->devmajor)); 99476017Skris memset(hd->devminor, 0, sizeof(hd->devminor)); 9951556Srgrimes if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3)) 9961556Srgrimes goto out; 9971556Srgrimes break; 9981556Srgrimes case PAX_REG: 9991556Srgrimes case PAX_CTG: 10001556Srgrimes default: 10011556Srgrimes /* 10021556Srgrimes * file data with this type, set the padding 10031556Srgrimes */ 10041556Srgrimes if (arcn->type == PAX_CTG) 10051556Srgrimes hd->typeflag = CONTTYPE; 10061556Srgrimes else 10071556Srgrimes hd->typeflag = REGTYPE; 100876017Skris memset(hd->linkname, 0, sizeof(hd->linkname)); 100976017Skris memset(hd->devmajor, 0, sizeof(hd->devmajor)); 101076017Skris memset(hd->devminor, 0, sizeof(hd->devminor)); 10111556Srgrimes arcn->pad = TAR_PAD(arcn->sb.st_size); 10121556Srgrimes# ifdef NET2_STAT 10131556Srgrimes if (ul_oct((u_long)arcn->sb.st_size, hd->size, 10141556Srgrimes sizeof(hd->size), 3)) { 10151556Srgrimes# else 10161556Srgrimes if (uqd_oct((u_quad_t)arcn->sb.st_size, hd->size, 10171556Srgrimes sizeof(hd->size), 3)) { 10181556Srgrimes# endif 101976017Skris paxwarn(1,"File is too long for ustar %s",arcn->org_name); 10201556Srgrimes return(1); 10211556Srgrimes } 10221556Srgrimes break; 10231556Srgrimes } 10241556Srgrimes 102576351Skris l_strncpy(hd->magic, TMAGIC, TMAGLEN); 102676351Skris l_strncpy(hd->version, TVERSION, TVERSLEN); 10271556Srgrimes 10281556Srgrimes /* 10291556Srgrimes * set the remaining fields. Some versions want all 16 bits of mode 10301556Srgrimes * we better humor them (they really do not meet spec though).... 10311556Srgrimes */ 10321556Srgrimes if (ul_oct((u_long)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 3) || 10331556Srgrimes ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 3) || 10341556Srgrimes ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 3) || 10351556Srgrimes ul_oct((u_long)arcn->sb.st_mtime,hd->mtime,sizeof(hd->mtime),3)) 10361556Srgrimes goto out; 103776351Skris l_strncpy(hd->uname,name_uid(arcn->sb.st_uid, 0),sizeof(hd->uname)); 103876351Skris l_strncpy(hd->gname,name_gid(arcn->sb.st_gid, 0),sizeof(hd->gname)); 10391556Srgrimes 10401556Srgrimes /* 10411556Srgrimes * calculate and store the checksum write the header to the archive 10421556Srgrimes * return 0 tells the caller to now write the file data, 1 says no data 10431556Srgrimes * needs to be written 10441556Srgrimes */ 1045164699Sru if (ul_oct(tar_chksm((char *)&hdblk, sizeof(HD_USTAR)), hd->chksum, 10461556Srgrimes sizeof(hd->chksum), 3)) 10471556Srgrimes goto out; 1048164699Sru if (wr_rdbuf((char *)&hdblk, sizeof(HD_USTAR)) < 0) 10491556Srgrimes return(-1); 10501556Srgrimes if (wr_skip((off_t)(BLKMULT - sizeof(HD_USTAR))) < 0) 10511556Srgrimes return(-1); 10521556Srgrimes if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG)) 10531556Srgrimes return(0); 10541556Srgrimes return(1); 10551556Srgrimes 10561556Srgrimes out: 10571556Srgrimes /* 10581556Srgrimes * header field is out of range 10591556Srgrimes */ 106076017Skris paxwarn(1, "Ustar header field is too small for %s", arcn->org_name); 10611556Srgrimes return(1); 10621556Srgrimes} 10631556Srgrimes 10641556Srgrimes/* 10651556Srgrimes * name_split() 10661556Srgrimes * see if the name has to be split for storage in a ustar header. We try 10671556Srgrimes * to fit the entire name in the name field without splitting if we can. 10681556Srgrimes * The split point is always at a / 10691556Srgrimes * Return 10701556Srgrimes * character pointer to split point (always the / that is to be removed 10711556Srgrimes * if the split is not needed, the points is set to the start of the file 10721556Srgrimes * name (it would violate the spec to split there). A NULL is returned if 10731556Srgrimes * the file name is too long 10741556Srgrimes */ 10751556Srgrimes 10761556Srgrimesstatic char * 107790113Simpname_split(char *name, int len) 10781556Srgrimes{ 107990113Simp char *start; 10801556Srgrimes 10811556Srgrimes /* 10821556Srgrimes * check to see if the file name is small enough to fit in the name 10831556Srgrimes * field. if so just return a pointer to the name. 10841556Srgrimes */ 1085137645Syar if (len <= TNMSZ) 10861556Srgrimes return(name); 1087211963Sbrian if (len > TPFSZ + TNMSZ) 10881556Srgrimes return(NULL); 10891556Srgrimes 10901556Srgrimes /* 10911556Srgrimes * we start looking at the biggest sized piece that fits in the name 109246684Skris * field. We walk forward looking for a slash to split at. The idea is 10931556Srgrimes * to find the biggest piece to fit in the name field (or the smallest 109440533Smsmith * prefix we can find) 10951556Srgrimes */ 1096211864Sbrian start = name + len - TNMSZ; 10971556Srgrimes while ((*start != '\0') && (*start != '/')) 10981556Srgrimes ++start; 10991556Srgrimes 11001556Srgrimes /* 11011556Srgrimes * if we hit the end of the string, this name cannot be split, so we 11021556Srgrimes * cannot store this file. 11031556Srgrimes */ 11041556Srgrimes if (*start == '\0') 11051556Srgrimes return(NULL); 11061556Srgrimes len = start - name; 11071556Srgrimes 11081556Srgrimes /* 11091556Srgrimes * NOTE: /str where the length of str == TNMSZ can not be stored under 11101556Srgrimes * the p1003.1-1990 spec for ustar. We could force a prefix of / and 11111556Srgrimes * the file would then expand on extract to //str. The len == 0 below 11121556Srgrimes * makes this special case follow the spec to the letter. 11131556Srgrimes */ 1114137645Syar if ((len > TPFSZ) || (len == 0)) 11151556Srgrimes return(NULL); 11161556Srgrimes 11171556Srgrimes /* 11181556Srgrimes * ok have a split point, return it to the caller 11191556Srgrimes */ 11201556Srgrimes return(start); 11211556Srgrimes} 1122