tar.c revision 90113
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 * 3. All advertising materials mentioning features or use of this software 181556Srgrimes * must display the following acknowledgement: 191556Srgrimes * This product includes software developed by the University of 201556Srgrimes * California, Berkeley and its contributors. 211556Srgrimes * 4. Neither the name of the University nor the names of its contributors 221556Srgrimes * may be used to endorse or promote products derived from this software 231556Srgrimes * without specific prior written permission. 241556Srgrimes * 251556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 261556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 271556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 281556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 291556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 301556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 311556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 321556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 331556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 341556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 351556Srgrimes * SUCH DAMAGE. 361556Srgrimes */ 371556Srgrimes 381556Srgrimes#ifndef lint 3936049Scharnier#if 0 4036049Scharnierstatic char sccsid[] = "@(#)tar.c 8.2 (Berkeley) 4/18/94"; 4136049Scharnier#endif 4236049Scharnierstatic const char rcsid[] = 4350471Speter "$FreeBSD: head/bin/pax/tar.c 90113 2002-02-02 07:07:59Z imp $"; 441556Srgrimes#endif /* not lint */ 451556Srgrimes 461556Srgrimes#include <sys/types.h> 471556Srgrimes#include <sys/time.h> 481556Srgrimes#include <sys/stat.h> 491556Srgrimes#include <string.h> 501556Srgrimes#include <stdio.h> 511556Srgrimes#include <unistd.h> 521556Srgrimes#include <stdlib.h> 531556Srgrimes#include "pax.h" 541556Srgrimes#include "extern.h" 551556Srgrimes#include "tar.h" 561556Srgrimes 571556Srgrimes/* 581556Srgrimes * Routines for reading, writing and header identify of various versions of tar 591556Srgrimes */ 601556Srgrimes 6190113Simpstatic u_long tar_chksm(char *, int); 6290113Simpstatic char *name_split(char *, int); 6390113Simpstatic int ul_oct(u_long, char *, int, int); 641556Srgrimes#ifndef NET2_STAT 6590113Simpstatic int uqd_oct(u_quad_t, char *, int, int); 661556Srgrimes#endif 671556Srgrimes 681556Srgrimes/* 691556Srgrimes * Routines common to all versions of tar 701556Srgrimes */ 711556Srgrimes 721556Srgrimesstatic int tar_nodir; /* do not write dirs under old tar */ 731556Srgrimes 741556Srgrimes/* 751556Srgrimes * tar_endwr() 761556Srgrimes * add the tar trailer of two null blocks 771556Srgrimes * Return: 781556Srgrimes * 0 if ok, -1 otherwise (what wr_skip returns) 791556Srgrimes */ 801556Srgrimes 811556Srgrimesint 821556Srgrimestar_endwr(void) 831556Srgrimes{ 841556Srgrimes return(wr_skip((off_t)(NULLCNT*BLKMULT))); 851556Srgrimes} 861556Srgrimes 871556Srgrimes/* 881556Srgrimes * tar_endrd() 891556Srgrimes * no cleanup needed here, just return size of trailer (for append) 901556Srgrimes * Return: 911556Srgrimes * size of trailer (2 * BLKMULT) 921556Srgrimes */ 931556Srgrimes 941556Srgrimesoff_t 951556Srgrimestar_endrd(void) 961556Srgrimes{ 971556Srgrimes return((off_t)(NULLCNT*BLKMULT)); 981556Srgrimes} 991556Srgrimes 1001556Srgrimes/* 1011556Srgrimes * tar_trail() 1021556Srgrimes * Called to determine if a header block is a valid trailer. We are passed 1031556Srgrimes * the block, the in_sync flag (which tells us we are in resync mode; 1041556Srgrimes * looking for a valid header), and cnt (which starts at zero) which is 1051556Srgrimes * used to count the number of empty blocks we have seen so far. 1061556Srgrimes * Return: 1071556Srgrimes * 0 if a valid trailer, -1 if not a valid trailer, or 1 if the block 1081556Srgrimes * could never contain a header. 1091556Srgrimes */ 1101556Srgrimes 1111556Srgrimesint 11290113Simptar_trail(char *buf, int in_resync, int *cnt) 1131556Srgrimes{ 11490113Simp int i; 1151556Srgrimes 1161556Srgrimes /* 1171556Srgrimes * look for all zero, trailer is two consecutive blocks of zero 1181556Srgrimes */ 1191556Srgrimes for (i = 0; i < BLKMULT; ++i) { 1201556Srgrimes if (buf[i] != '\0') 1211556Srgrimes break; 1221556Srgrimes } 1231556Srgrimes 1241556Srgrimes /* 1251556Srgrimes * if not all zero it is not a trailer, but MIGHT be a header. 1261556Srgrimes */ 1271556Srgrimes if (i != BLKMULT) 1281556Srgrimes return(-1); 1291556Srgrimes 1301556Srgrimes /* 1311556Srgrimes * When given a zero block, we must be careful! 1321556Srgrimes * If we are not in resync mode, check for the trailer. Have to watch 1331556Srgrimes * out that we do not mis-identify file data as the trailer, so we do 1341556Srgrimes * NOT try to id a trailer during resync mode. During resync mode we 1351556Srgrimes * might as well throw this block out since a valid header can NEVER be 1361556Srgrimes * a block of all 0 (we must have a valid file name). 1371556Srgrimes */ 1381556Srgrimes if (!in_resync && (++*cnt >= NULLCNT)) 1391556Srgrimes return(0); 1401556Srgrimes return(1); 1411556Srgrimes} 1421556Srgrimes 1431556Srgrimes/* 1441556Srgrimes * ul_oct() 1451556Srgrimes * convert an unsigned long to an octal string. many oddball field 1461556Srgrimes * termination characters are used by the various versions of tar in the 14776351Skris * different fields. term selects which kind to use. str is '0' padded 1481556Srgrimes * at the front to len. we are unable to use only one format as many old 1491556Srgrimes * tar readers are very cranky about this. 1501556Srgrimes * Return: 1511556Srgrimes * 0 if the number fit into the string, -1 otherwise 1521556Srgrimes */ 1531556Srgrimes 1541556Srgrimesstatic int 15590113Simpul_oct(u_long val, char *str, int len, int term) 1561556Srgrimes{ 15790113Simp char *pt; 1588855Srgrimes 1591556Srgrimes /* 1601556Srgrimes * term selects the appropriate character(s) for the end of the string 1611556Srgrimes */ 1621556Srgrimes pt = str + len - 1; 1631556Srgrimes switch(term) { 1641556Srgrimes case 3: 1651556Srgrimes *pt-- = '\0'; 1661556Srgrimes break; 1671556Srgrimes case 2: 1681556Srgrimes *pt-- = ' '; 1691556Srgrimes *pt-- = '\0'; 1701556Srgrimes break; 1711556Srgrimes case 1: 1721556Srgrimes *pt-- = ' '; 1731556Srgrimes break; 1741556Srgrimes case 0: 1751556Srgrimes default: 1761556Srgrimes *pt-- = '\0'; 1771556Srgrimes *pt-- = ' '; 1781556Srgrimes break; 1791556Srgrimes } 1801556Srgrimes 1811556Srgrimes /* 1821556Srgrimes * convert and blank pad if there is space 1831556Srgrimes */ 1841556Srgrimes while (pt >= str) { 1851556Srgrimes *pt-- = '0' + (char)(val & 0x7); 1861556Srgrimes if ((val = val >> 3) == (u_long)0) 1871556Srgrimes break; 1881556Srgrimes } 1891556Srgrimes 1901556Srgrimes while (pt >= str) 19176351Skris *pt-- = '0'; 1921556Srgrimes if (val != (u_long)0) 1931556Srgrimes return(-1); 1941556Srgrimes return(0); 1951556Srgrimes} 1961556Srgrimes 1971556Srgrimes#ifndef NET2_STAT 1981556Srgrimes/* 1991556Srgrimes * uqd_oct() 2001556Srgrimes * convert an u_quad_t to an octal string. one of many oddball field 2011556Srgrimes * termination characters are used by the various versions of tar in the 20276351Skris * different fields. term selects which kind to use. str is '0' padded 2031556Srgrimes * at the front to len. we are unable to use only one format as many old 2041556Srgrimes * tar readers are very cranky about this. 2051556Srgrimes * Return: 2061556Srgrimes * 0 if the number fit into the string, -1 otherwise 2071556Srgrimes */ 2081556Srgrimes 2091556Srgrimesstatic int 21090113Simpuqd_oct(u_quad_t val, char *str, int len, int term) 2111556Srgrimes{ 21290113Simp char *pt; 2138855Srgrimes 2141556Srgrimes /* 2151556Srgrimes * term selects the appropriate character(s) for the end of the string 2161556Srgrimes */ 2171556Srgrimes pt = str + len - 1; 2181556Srgrimes switch(term) { 2191556Srgrimes case 3: 2201556Srgrimes *pt-- = '\0'; 2211556Srgrimes break; 2221556Srgrimes case 2: 2231556Srgrimes *pt-- = ' '; 2241556Srgrimes *pt-- = '\0'; 2251556Srgrimes break; 2261556Srgrimes case 1: 2271556Srgrimes *pt-- = ' '; 2281556Srgrimes break; 2291556Srgrimes case 0: 2301556Srgrimes default: 2311556Srgrimes *pt-- = '\0'; 2321556Srgrimes *pt-- = ' '; 2331556Srgrimes break; 2341556Srgrimes } 2351556Srgrimes 2361556Srgrimes /* 2371556Srgrimes * convert and blank pad if there is space 2381556Srgrimes */ 2391556Srgrimes while (pt >= str) { 2401556Srgrimes *pt-- = '0' + (char)(val & 0x7); 2411556Srgrimes if ((val = val >> 3) == 0) 2421556Srgrimes break; 2431556Srgrimes } 2441556Srgrimes 2451556Srgrimes while (pt >= str) 24676351Skris *pt-- = '0'; 2471556Srgrimes if (val != (u_quad_t)0) 2481556Srgrimes return(-1); 2491556Srgrimes return(0); 2501556Srgrimes} 2511556Srgrimes#endif 2521556Srgrimes 2531556Srgrimes/* 2541556Srgrimes * tar_chksm() 2551556Srgrimes * calculate the checksum for a tar block counting the checksum field as 25646684Skris * all blanks (BLNKSUM is that value pre-calculated, the sum of 8 blanks). 2571556Srgrimes * NOTE: we use len to short circuit summing 0's on write since we ALWAYS 2581556Srgrimes * pad headers with 0. 2591556Srgrimes * Return: 2601556Srgrimes * unsigned long checksum 2611556Srgrimes */ 2621556Srgrimes 2631556Srgrimesstatic u_long 26490113Simptar_chksm(char *blk, int len) 2651556Srgrimes{ 26690113Simp char *stop; 26790113Simp char *pt; 26846684Skris u_long chksm = BLNKSUM; /* initial value is checksum field sum */ 2691556Srgrimes 2701556Srgrimes /* 2711556Srgrimes * add the part of the block before the checksum field 2721556Srgrimes */ 2731556Srgrimes pt = blk; 2741556Srgrimes stop = blk + CHK_OFFSET; 2758855Srgrimes while (pt < stop) 2768855Srgrimes chksm += (u_long)(*pt++ & 0xff); 2771556Srgrimes /* 2781556Srgrimes * move past the checksum field and keep going, spec counts the 2791556Srgrimes * checksum field as the sum of 8 blanks (which is pre-computed as 2801556Srgrimes * BLNKSUM). 2811556Srgrimes * ASSUMED: len is greater than CHK_OFFSET. (len is where our 0 padding 2821556Srgrimes * starts, no point in summing zero's) 2831556Srgrimes */ 2841556Srgrimes pt += CHK_LEN; 2851556Srgrimes stop = blk + len; 2861556Srgrimes while (pt < stop) 2878855Srgrimes chksm += (u_long)(*pt++ & 0xff); 2881556Srgrimes return(chksm); 2891556Srgrimes} 2901556Srgrimes 2911556Srgrimes/* 2921556Srgrimes * Routines for old BSD style tar (also made portable to sysV tar) 2931556Srgrimes */ 2941556Srgrimes 2951556Srgrimes/* 2961556Srgrimes * tar_id() 2971556Srgrimes * determine if a block given to us is a valid tar header (and not a USTAR 2981556Srgrimes * header). We have to be on the lookout for those pesky blocks of all 2991556Srgrimes * zero's. 3001556Srgrimes * Return: 3011556Srgrimes * 0 if a tar header, -1 otherwise 3021556Srgrimes */ 3031556Srgrimes 3041556Srgrimesint 30590113Simptar_id(char *blk, int size) 3061556Srgrimes{ 30790113Simp HD_TAR *hd; 30890113Simp HD_USTAR *uhd; 3091556Srgrimes 3101556Srgrimes if (size < BLKMULT) 3111556Srgrimes return(-1); 3121556Srgrimes hd = (HD_TAR *)blk; 3131556Srgrimes uhd = (HD_USTAR *)blk; 3141556Srgrimes 3151556Srgrimes /* 3161556Srgrimes * check for block of zero's first, a simple and fast test, then make 3171556Srgrimes * sure this is not a ustar header by looking for the ustar magic 3181556Srgrimes * cookie. We should use TMAGLEN, but some USTAR archive programs are 3191556Srgrimes * wrong and create archives missing the \0. Last we check the 3201556Srgrimes * checksum. If this is ok we have to assume it is a valid header. 3211556Srgrimes */ 3221556Srgrimes if (hd->name[0] == '\0') 3231556Srgrimes return(-1); 3241556Srgrimes if (strncmp(uhd->magic, TMAGIC, TMAGLEN - 1) == 0) 3251556Srgrimes return(-1); 3261556Srgrimes if (asc_ul(hd->chksum,sizeof(hd->chksum),OCT) != tar_chksm(blk,BLKMULT)) 3271556Srgrimes return(-1); 3281556Srgrimes return(0); 3291556Srgrimes} 3301556Srgrimes 3311556Srgrimes/* 3321556Srgrimes * tar_opt() 3331556Srgrimes * handle tar format specific -o options 3341556Srgrimes * Return: 3351556Srgrimes * 0 if ok -1 otherwise 3361556Srgrimes */ 3371556Srgrimes 3381556Srgrimesint 3391556Srgrimestar_opt(void) 3401556Srgrimes{ 3411556Srgrimes OPLIST *opt; 3421556Srgrimes 3431556Srgrimes while ((opt = opt_next()) != NULL) { 3441556Srgrimes if (strcmp(opt->name, TAR_OPTION) || 3451556Srgrimes strcmp(opt->value, TAR_NODIR)) { 34676017Skris paxwarn(1, "Unknown tar format -o option/value pair %s=%s", 3471556Srgrimes opt->name, opt->value); 34876017Skris paxwarn(1,"%s=%s is the only supported tar format option", 3491556Srgrimes TAR_OPTION, TAR_NODIR); 3501556Srgrimes return(-1); 3511556Srgrimes } 3521556Srgrimes 3531556Srgrimes /* 3541556Srgrimes * we only support one option, and only when writing 3551556Srgrimes */ 3561556Srgrimes if ((act != APPND) && (act != ARCHIVE)) { 35776017Skris paxwarn(1, "%s=%s is only supported when writing.", 3581556Srgrimes opt->name, opt->value); 3591556Srgrimes return(-1); 3601556Srgrimes } 3611556Srgrimes tar_nodir = 1; 3621556Srgrimes } 3631556Srgrimes return(0); 3641556Srgrimes} 3651556Srgrimes 3661556Srgrimes 3671556Srgrimes/* 3681556Srgrimes * tar_rd() 3691556Srgrimes * extract the values out of block already determined to be a tar header. 3701556Srgrimes * store the values in the ARCHD parameter. 3711556Srgrimes * Return: 3721556Srgrimes * 0 3731556Srgrimes */ 3741556Srgrimes 3751556Srgrimesint 37690113Simptar_rd(ARCHD *arcn, char *buf) 3771556Srgrimes{ 37890113Simp HD_TAR *hd; 37990113Simp char *pt; 3801556Srgrimes 3811556Srgrimes /* 3821556Srgrimes * we only get proper sized buffers passed to us 3831556Srgrimes */ 3841556Srgrimes if (tar_id(buf, BLKMULT) < 0) 3851556Srgrimes return(-1); 3861556Srgrimes arcn->org_name = arcn->name; 3871556Srgrimes arcn->sb.st_nlink = 1; 3881556Srgrimes arcn->pat = NULL; 3891556Srgrimes 3901556Srgrimes /* 3911556Srgrimes * copy out the name and values in the stat buffer 3921556Srgrimes */ 3931556Srgrimes hd = (HD_TAR *)buf; 39476351Skris arcn->nlen = l_strncpy(arcn->name, 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, 42476351Skris 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, 43676351Skris 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; 5111556Srgrimes char hdblk[sizeof(HD_TAR)]; 5121556Srgrimes 5131556Srgrimes /* 5141556Srgrimes * 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: 5401556Srgrimes if (arcn->ln_nlen > 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; 55776351Skris if (len >= 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 */ 5701556Srgrimes hd = (HD_TAR *)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 */ 6371556Srgrimes if (ul_oct(tar_chksm(hdblk, sizeof(HD_TAR)), hd->chksum, 63876351Skris sizeof(hd->chksum), 3)) 6391556Srgrimes goto out; 6401556Srgrimes if (wr_rdbuf(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') { 75676351Skris cnt = l_strncpy(dest, hd->prefix, sizeof(arcn->name) - 2); 75776351Skris dest += cnt; 7581556Srgrimes *dest++ = '/'; 75976351Skris cnt++; 7601556Srgrimes } 76176351Skris arcn->nlen = cnt + l_strncpy(dest, hd->name, sizeof(arcn->name) - cnt); 7621556Srgrimes arcn->name[arcn->nlen] = '\0'; 7631556Srgrimes 7641556Srgrimes /* 7651556Srgrimes * follow the spec to the letter. we should only have mode bits, strip 7661556Srgrimes * off all other crud we may be passed. 7671556Srgrimes */ 7681556Srgrimes arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode, sizeof(hd->mode), OCT) & 7691556Srgrimes 0xfff); 77076351Skris#ifdef NET2_STAT 77176351Skris arcn->sb.st_size = (off_t)asc_ul(hd->size, sizeof(hd->size), OCT); 77285618Sdillon arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT); 77376351Skris#else 77476351Skris arcn->sb.st_size = (off_t)asc_uqd(hd->size, sizeof(hd->size), OCT); 77585618Sdillon arcn->sb.st_mtime = (time_t)asc_uqd(hd->mtime, sizeof(hd->mtime), OCT); 77676351Skris#endif 7771556Srgrimes arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime; 7781556Srgrimes 7791556Srgrimes /* 7801556Srgrimes * If we can find the ascii names for gname and uname in the password 7811556Srgrimes * and group files we will use the uid's and gid they bind. Otherwise 7821556Srgrimes * we use the uid and gid values stored in the header. (This is what 78346684Skris * the POSIX spec wants). 7841556Srgrimes */ 7851556Srgrimes hd->gname[sizeof(hd->gname) - 1] = '\0'; 7861556Srgrimes if (gid_name(hd->gname, &(arcn->sb.st_gid)) < 0) 7871556Srgrimes arcn->sb.st_gid = (gid_t)asc_ul(hd->gid, sizeof(hd->gid), OCT); 7881556Srgrimes hd->uname[sizeof(hd->uname) - 1] = '\0'; 7891556Srgrimes if (uid_name(hd->uname, &(arcn->sb.st_uid)) < 0) 7901556Srgrimes arcn->sb.st_uid = (uid_t)asc_ul(hd->uid, sizeof(hd->uid), OCT); 7911556Srgrimes 7921556Srgrimes /* 7931556Srgrimes * set the defaults, these may be changed depending on the file type 7941556Srgrimes */ 7951556Srgrimes arcn->ln_name[0] = '\0'; 7961556Srgrimes arcn->ln_nlen = 0; 7971556Srgrimes arcn->pad = 0; 7981556Srgrimes arcn->skip = 0; 7991556Srgrimes arcn->sb.st_rdev = (dev_t)0; 8001556Srgrimes 8011556Srgrimes /* 8021556Srgrimes * set the mode and PAX type according to the typeflag in the header 8031556Srgrimes */ 8041556Srgrimes switch(hd->typeflag) { 8051556Srgrimes case FIFOTYPE: 8061556Srgrimes arcn->type = PAX_FIF; 8071556Srgrimes arcn->sb.st_mode |= S_IFIFO; 8081556Srgrimes break; 8091556Srgrimes case DIRTYPE: 8101556Srgrimes arcn->type = PAX_DIR; 8111556Srgrimes arcn->sb.st_mode |= S_IFDIR; 8121556Srgrimes arcn->sb.st_nlink = 2; 8131556Srgrimes 8141556Srgrimes /* 8151556Srgrimes * Some programs that create ustar archives append a '/' 8161556Srgrimes * to the pathname for directories. This clearly violates 8171556Srgrimes * ustar specs, but we will silently strip it off anyway. 8181556Srgrimes */ 8191556Srgrimes if (arcn->name[arcn->nlen - 1] == '/') 8201556Srgrimes arcn->name[--arcn->nlen] = '\0'; 8211556Srgrimes break; 8221556Srgrimes case BLKTYPE: 8231556Srgrimes case CHRTYPE: 8241556Srgrimes /* 8251556Srgrimes * this type requires the rdev field to be set. 8261556Srgrimes */ 8271556Srgrimes if (hd->typeflag == BLKTYPE) { 8281556Srgrimes arcn->type = PAX_BLK; 8291556Srgrimes arcn->sb.st_mode |= S_IFBLK; 8301556Srgrimes } else { 8311556Srgrimes arcn->type = PAX_CHR; 8321556Srgrimes arcn->sb.st_mode |= S_IFCHR; 8331556Srgrimes } 8341556Srgrimes devmajor = (dev_t)asc_ul(hd->devmajor,sizeof(hd->devmajor),OCT); 8351556Srgrimes devminor = (dev_t)asc_ul(hd->devminor,sizeof(hd->devminor),OCT); 8361556Srgrimes arcn->sb.st_rdev = TODEV(devmajor, devminor); 8371556Srgrimes break; 8381556Srgrimes case SYMTYPE: 8391556Srgrimes case LNKTYPE: 8401556Srgrimes if (hd->typeflag == SYMTYPE) { 8411556Srgrimes arcn->type = PAX_SLK; 8421556Srgrimes arcn->sb.st_mode |= S_IFLNK; 8431556Srgrimes } else { 8441556Srgrimes arcn->type = PAX_HLK; 8451556Srgrimes /* 8461556Srgrimes * so printing looks better 8471556Srgrimes */ 8481556Srgrimes arcn->sb.st_mode |= S_IFREG; 8491556Srgrimes arcn->sb.st_nlink = 2; 8501556Srgrimes } 8511556Srgrimes /* 8521556Srgrimes * copy the link name 8531556Srgrimes */ 8541556Srgrimes arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname, 85576351Skris sizeof(arcn->ln_name) - 1); 8561556Srgrimes arcn->ln_name[arcn->ln_nlen] = '\0'; 8571556Srgrimes break; 8581556Srgrimes case CONTTYPE: 8591556Srgrimes case AREGTYPE: 8601556Srgrimes case REGTYPE: 8611556Srgrimes default: 8621556Srgrimes /* 8631556Srgrimes * these types have file data that follows. Set the skip and 8641556Srgrimes * pad fields. 8651556Srgrimes */ 8661556Srgrimes arcn->type = PAX_REG; 8671556Srgrimes arcn->pad = TAR_PAD(arcn->sb.st_size); 8681556Srgrimes arcn->skip = arcn->sb.st_size; 8691556Srgrimes arcn->sb.st_mode |= S_IFREG; 8701556Srgrimes break; 8711556Srgrimes } 8721556Srgrimes return(0); 8731556Srgrimes} 8741556Srgrimes 8751556Srgrimes/* 8761556Srgrimes * ustar_wr() 8771556Srgrimes * write a ustar header for the file specified in the ARCHD to the archive 8781556Srgrimes * Have to check for file types that cannot be stored and file names that 8791556Srgrimes * are too long. Be careful of the term (last arg) to ul_oct, we only use 8801556Srgrimes * '\0' for the termination character (this is different than picky tar) 8811556Srgrimes * ASSUMED: space after header in header block is zero filled 8821556Srgrimes * Return: 8831556Srgrimes * 0 if file has data to be written after the header, 1 if file has NO 8841556Srgrimes * data to write after the header, -1 if archive write failed 8851556Srgrimes */ 8861556Srgrimes 8871556Srgrimesint 88890113Simpustar_wr(ARCHD *arcn) 8891556Srgrimes{ 89090113Simp HD_USTAR *hd; 89190113Simp char *pt; 8921556Srgrimes char hdblk[sizeof(HD_USTAR)]; 8931556Srgrimes 8941556Srgrimes /* 8951556Srgrimes * check for those file system types ustar cannot store 8961556Srgrimes */ 8971556Srgrimes if (arcn->type == PAX_SCK) { 89876017Skris paxwarn(1, "Ustar cannot archive a socket %s", arcn->org_name); 8991556Srgrimes return(1); 9001556Srgrimes } 9011556Srgrimes 9021556Srgrimes /* 9031556Srgrimes * check the length of the linkname 9041556Srgrimes */ 9051556Srgrimes if (((arcn->type == PAX_SLK) || (arcn->type == PAX_HLK) || 90640533Smsmith (arcn->type == PAX_HRG)) && (arcn->ln_nlen >= sizeof(hd->linkname))){ 90776017Skris paxwarn(1, "Link name too long for ustar %s", arcn->ln_name); 9081556Srgrimes return(1); 9091556Srgrimes } 9101556Srgrimes 9111556Srgrimes /* 9121556Srgrimes * split the path name into prefix and name fields (if needed). if 9131556Srgrimes * pt != arcn->name, the name has to be split 9141556Srgrimes */ 9151556Srgrimes if ((pt = name_split(arcn->name, arcn->nlen)) == NULL) { 91676017Skris paxwarn(1, "File name too long for ustar %s", arcn->name); 9171556Srgrimes return(1); 9181556Srgrimes } 9191556Srgrimes hd = (HD_USTAR *)hdblk; 9201556Srgrimes arcn->pad = 0L; 9211556Srgrimes 9221556Srgrimes /* 9231556Srgrimes * split the name, or zero out the prefix 9241556Srgrimes */ 9251556Srgrimes if (pt != arcn->name) { 9261556Srgrimes /* 9271556Srgrimes * name was split, pt points at the / where the split is to 9281556Srgrimes * occur, we remove the / and copy the first part to the prefix 9291556Srgrimes */ 9301556Srgrimes *pt = '\0'; 93176351Skris l_strncpy(hd->prefix, arcn->name, sizeof(hd->prefix) - 1); 9321556Srgrimes *pt++ = '/'; 9331556Srgrimes } else 93476017Skris memset(hd->prefix, 0, sizeof(hd->prefix)); 9351556Srgrimes 9361556Srgrimes /* 9371556Srgrimes * copy the name part. this may be the whole path or the part after 9381556Srgrimes * the prefix 9391556Srgrimes */ 94076351Skris l_strncpy(hd->name, pt, sizeof(hd->name) - 1); 94176351Skris hd->name[sizeof(hd->name) - 1] = '\0'; 9421556Srgrimes 9438855Srgrimes /* 9441556Srgrimes * set the fields in the header that are type dependent 9451556Srgrimes */ 9461556Srgrimes switch(arcn->type) { 9471556Srgrimes case PAX_DIR: 9481556Srgrimes hd->typeflag = DIRTYPE; 94976017Skris memset(hd->linkname, 0, sizeof(hd->linkname)); 95076017Skris memset(hd->devmajor, 0, sizeof(hd->devmajor)); 95176017Skris memset(hd->devminor, 0, sizeof(hd->devminor)); 9521556Srgrimes if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3)) 9531556Srgrimes goto out; 9541556Srgrimes break; 9551556Srgrimes case PAX_CHR: 9561556Srgrimes case PAX_BLK: 9571556Srgrimes if (arcn->type == PAX_CHR) 9581556Srgrimes hd->typeflag = CHRTYPE; 9591556Srgrimes else 9601556Srgrimes hd->typeflag = BLKTYPE; 96176017Skris memset(hd->linkname, 0, sizeof(hd->linkname)); 9621556Srgrimes if (ul_oct((u_long)MAJOR(arcn->sb.st_rdev), hd->devmajor, 9631556Srgrimes sizeof(hd->devmajor), 3) || 9641556Srgrimes ul_oct((u_long)MINOR(arcn->sb.st_rdev), hd->devminor, 9651556Srgrimes sizeof(hd->devminor), 3) || 9661556Srgrimes ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3)) 9671556Srgrimes goto out; 9681556Srgrimes break; 9691556Srgrimes case PAX_FIF: 9701556Srgrimes hd->typeflag = FIFOTYPE; 97176017Skris memset(hd->linkname, 0, sizeof(hd->linkname)); 97276017Skris memset(hd->devmajor, 0, sizeof(hd->devmajor)); 97376017Skris memset(hd->devminor, 0, sizeof(hd->devminor)); 9741556Srgrimes if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3)) 9751556Srgrimes goto out; 9761556Srgrimes break; 9771556Srgrimes case PAX_SLK: 9781556Srgrimes case PAX_HLK: 9791556Srgrimes case PAX_HRG: 9801556Srgrimes if (arcn->type == PAX_SLK) 9811556Srgrimes hd->typeflag = SYMTYPE; 9821556Srgrimes else 9831556Srgrimes hd->typeflag = LNKTYPE; 98476351Skris l_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname) - 1); 98576351Skris hd->linkname[sizeof(hd->linkname) - 1] = '\0'; 98676017Skris memset(hd->devmajor, 0, sizeof(hd->devmajor)); 98776017Skris memset(hd->devminor, 0, sizeof(hd->devminor)); 9881556Srgrimes if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3)) 9891556Srgrimes goto out; 9901556Srgrimes break; 9911556Srgrimes case PAX_REG: 9921556Srgrimes case PAX_CTG: 9931556Srgrimes default: 9941556Srgrimes /* 9951556Srgrimes * file data with this type, set the padding 9961556Srgrimes */ 9971556Srgrimes if (arcn->type == PAX_CTG) 9981556Srgrimes hd->typeflag = CONTTYPE; 9991556Srgrimes else 10001556Srgrimes hd->typeflag = REGTYPE; 100176017Skris memset(hd->linkname, 0, sizeof(hd->linkname)); 100276017Skris memset(hd->devmajor, 0, sizeof(hd->devmajor)); 100376017Skris memset(hd->devminor, 0, sizeof(hd->devminor)); 10041556Srgrimes arcn->pad = TAR_PAD(arcn->sb.st_size); 10051556Srgrimes# ifdef NET2_STAT 10061556Srgrimes if (ul_oct((u_long)arcn->sb.st_size, hd->size, 10071556Srgrimes sizeof(hd->size), 3)) { 10081556Srgrimes# else 10091556Srgrimes if (uqd_oct((u_quad_t)arcn->sb.st_size, hd->size, 10101556Srgrimes sizeof(hd->size), 3)) { 10111556Srgrimes# endif 101276017Skris paxwarn(1,"File is too long for ustar %s",arcn->org_name); 10131556Srgrimes return(1); 10141556Srgrimes } 10151556Srgrimes break; 10161556Srgrimes } 10171556Srgrimes 101876351Skris l_strncpy(hd->magic, TMAGIC, TMAGLEN); 101976351Skris l_strncpy(hd->version, TVERSION, TVERSLEN); 10201556Srgrimes 10211556Srgrimes /* 10221556Srgrimes * set the remaining fields. Some versions want all 16 bits of mode 10231556Srgrimes * we better humor them (they really do not meet spec though).... 10241556Srgrimes */ 10251556Srgrimes if (ul_oct((u_long)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 3) || 10261556Srgrimes ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 3) || 10271556Srgrimes ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 3) || 10281556Srgrimes ul_oct((u_long)arcn->sb.st_mtime,hd->mtime,sizeof(hd->mtime),3)) 10291556Srgrimes goto out; 103076351Skris l_strncpy(hd->uname,name_uid(arcn->sb.st_uid, 0),sizeof(hd->uname)); 103176351Skris l_strncpy(hd->gname,name_gid(arcn->sb.st_gid, 0),sizeof(hd->gname)); 10321556Srgrimes 10331556Srgrimes /* 10341556Srgrimes * calculate and store the checksum write the header to the archive 10351556Srgrimes * return 0 tells the caller to now write the file data, 1 says no data 10361556Srgrimes * needs to be written 10371556Srgrimes */ 10381556Srgrimes if (ul_oct(tar_chksm(hdblk, sizeof(HD_USTAR)), hd->chksum, 10391556Srgrimes sizeof(hd->chksum), 3)) 10401556Srgrimes goto out; 10411556Srgrimes if (wr_rdbuf(hdblk, sizeof(HD_USTAR)) < 0) 10421556Srgrimes return(-1); 10431556Srgrimes if (wr_skip((off_t)(BLKMULT - sizeof(HD_USTAR))) < 0) 10441556Srgrimes return(-1); 10451556Srgrimes if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG)) 10461556Srgrimes return(0); 10471556Srgrimes return(1); 10481556Srgrimes 10491556Srgrimes out: 10501556Srgrimes /* 10511556Srgrimes * header field is out of range 10521556Srgrimes */ 105376017Skris paxwarn(1, "Ustar header field is too small for %s", arcn->org_name); 10541556Srgrimes return(1); 10551556Srgrimes} 10561556Srgrimes 10571556Srgrimes/* 10581556Srgrimes * name_split() 10591556Srgrimes * see if the name has to be split for storage in a ustar header. We try 10601556Srgrimes * to fit the entire name in the name field without splitting if we can. 10611556Srgrimes * The split point is always at a / 10621556Srgrimes * Return 10631556Srgrimes * character pointer to split point (always the / that is to be removed 10641556Srgrimes * if the split is not needed, the points is set to the start of the file 10651556Srgrimes * name (it would violate the spec to split there). A NULL is returned if 10661556Srgrimes * the file name is too long 10671556Srgrimes */ 10681556Srgrimes 10691556Srgrimesstatic char * 107090113Simpname_split(char *name, int len) 10711556Srgrimes{ 107290113Simp char *start; 10731556Srgrimes 10741556Srgrimes /* 10751556Srgrimes * check to see if the file name is small enough to fit in the name 10761556Srgrimes * field. if so just return a pointer to the name. 10771556Srgrimes */ 107876351Skris if (len < TNMSZ) 10791556Srgrimes return(name); 108040533Smsmith if (len > (TPFSZ + TNMSZ)) 10811556Srgrimes return(NULL); 10821556Srgrimes 10831556Srgrimes /* 10841556Srgrimes * we start looking at the biggest sized piece that fits in the name 108546684Skris * field. We walk forward looking for a slash to split at. The idea is 10861556Srgrimes * to find the biggest piece to fit in the name field (or the smallest 108740533Smsmith * prefix we can find) 10881556Srgrimes */ 108940533Smsmith start = name + len - TNMSZ; 10901556Srgrimes while ((*start != '\0') && (*start != '/')) 10911556Srgrimes ++start; 10921556Srgrimes 10931556Srgrimes /* 10941556Srgrimes * if we hit the end of the string, this name cannot be split, so we 10951556Srgrimes * cannot store this file. 10961556Srgrimes */ 10971556Srgrimes if (*start == '\0') 10981556Srgrimes return(NULL); 10991556Srgrimes len = start - name; 11001556Srgrimes 11011556Srgrimes /* 11021556Srgrimes * NOTE: /str where the length of str == TNMSZ can not be stored under 11031556Srgrimes * the p1003.1-1990 spec for ustar. We could force a prefix of / and 11041556Srgrimes * the file would then expand on extract to //str. The len == 0 below 11051556Srgrimes * makes this special case follow the spec to the letter. 11061556Srgrimes */ 110740533Smsmith if ((len >= TPFSZ) || (len == 0)) 11081556Srgrimes return(NULL); 11091556Srgrimes 11101556Srgrimes /* 11111556Srgrimes * ok have a split point, return it to the caller 11121556Srgrimes */ 11131556Srgrimes return(start); 11141556Srgrimes} 1115