157197Smuller /*- 257197Smuller * Copyright (c) 1992 Keith Muller. 357197Smuller * Copyright (c) 1992 The Regents of the University of California. 457197Smuller * All rights reserved. 557197Smuller * 657197Smuller * This code is derived from software contributed to Berkeley by 757197Smuller * Keith Muller of the University of California, San Diego. 857197Smuller * 957197Smuller * %sccs.include.redist.c% 1057197Smuller */ 1157197Smuller 1257197Smuller #ifndef lint 13*57788Smuller static char sccsid[] = "@(#)tar.c 1.3 (Berkeley) 02/02/93"; 1457197Smuller #endif /* not lint */ 1557197Smuller 1657197Smuller #include <sys/types.h> 1757197Smuller #include <sys/time.h> 1857197Smuller #include <sys/stat.h> 1957197Smuller #include <sys/param.h> 2057197Smuller #include <string.h> 2157197Smuller #include <stdio.h> 2257197Smuller #include <ctype.h> 2357197Smuller #include <unistd.h> 2457197Smuller #include <stdlib.h> 2557197Smuller #include "pax.h" 2657197Smuller #include "extern.h" 2757197Smuller #include "tar.h" 2857197Smuller 2957197Smuller /* 3057197Smuller * Routines for reading, writing and header identify of various versions of tar 3157197Smuller */ 3257197Smuller 3357197Smuller static u_long tar_chksm __P((register char *, register int)); 3457197Smuller static char *name_split __P((register char *, register int)); 3557197Smuller static int ul_oct __P((u_long, register char *, register int, int)); 3657197Smuller #ifndef NET2_STAT 3757197Smuller static int uqd_oct __P((u_quad_t, register char *, register int, int)); 3857197Smuller #endif 3957197Smuller 4057197Smuller /* 4157197Smuller * Routines common to all versions of tar 4257197Smuller */ 4357197Smuller 4457197Smuller static int tar_nodir; /* do not write dirs under old tar */ 4557197Smuller 4657197Smuller /* 4757197Smuller * tar_endwr() 4857197Smuller * add the tar trailer of two null blocks 4957197Smuller * Return: 5057197Smuller * 0 if ok, -1 otherwise (what wr_skip returns) 5157197Smuller */ 5257197Smuller 5357197Smuller #if __STDC__ 5457197Smuller int 5557197Smuller tar_endwr(void) 5657197Smuller #else 5757197Smuller int 5857197Smuller tar_endwr() 5957197Smuller #endif 6057197Smuller { 6157197Smuller return(wr_skip((off_t)(NULLCNT*BLKMULT))); 6257197Smuller } 6357197Smuller 6457197Smuller /* 6557197Smuller * tar_endrd() 6657197Smuller * no cleanup needed here, just return size of trailer (for append) 6757197Smuller * Return: 6857197Smuller * size of trailer (2 * BLKMULT) 6957197Smuller */ 7057197Smuller 7157197Smuller #if __STDC__ 7257197Smuller off_t 7357197Smuller tar_endrd(void) 7457197Smuller #else 7557197Smuller off_t 7657197Smuller tar_endrd() 7757197Smuller #endif 7857197Smuller { 7957197Smuller return((off_t)(NULLCNT*BLKMULT)); 8057197Smuller } 8157197Smuller 8257197Smuller /* 8357197Smuller * tar_trail() 8457197Smuller * Called to determine if a header block is a valid trailer. We are passed 8557197Smuller * the block, the in_sync flag (which tells us we are in resync mode; 8657197Smuller * looking for a valid header), and cnt (which starts at zero) which is 8757197Smuller * used to count the number of empty blocks we have seen so far. 8857197Smuller * Return: 8957197Smuller * 0 if a valid trailer, -1 if not a valid trailer, or 1 if the block 9057197Smuller * could never contain a header. 9157197Smuller */ 9257197Smuller 9357197Smuller #if __STDC__ 9457197Smuller int 9557197Smuller tar_trail(register char *buf, register int in_resync, register int *cnt) 9657197Smuller #else 9757197Smuller int 9857197Smuller tar_trail(buf, in_resync, cnt) 9957197Smuller register char *buf; 10057197Smuller register int in_resync; 10157197Smuller register int *cnt; 10257197Smuller #endif 10357197Smuller { 10457197Smuller register int i; 10557197Smuller 10657197Smuller /* 10757197Smuller * look for all zero, trailer is two consecutive blocks of zero 10857197Smuller */ 10957197Smuller for (i = 0; i < BLKMULT; ++i) { 11057197Smuller if (buf[i] != '\0') 11157197Smuller break; 11257197Smuller } 11357197Smuller 11457197Smuller /* 11557197Smuller * if not all zero it is not a trailer, but MIGHT be a header. 11657197Smuller */ 11757197Smuller if (i != BLKMULT) 11857197Smuller return(-1); 11957197Smuller 12057197Smuller /* 12157197Smuller * When given a zero block, we must be careful! 12257197Smuller * If we are not in resync mode, check for the trailer. Have to watch 12357197Smuller * out that we do not mis-identify file data as the trailer, so we do 12457197Smuller * NOT try to id a trailer during resync mode. During resync mode we 12557197Smuller * might as well throw this block out since a valid header can NEVER be 12657197Smuller * a block of all 0 (we must have a valid file name). 12757197Smuller */ 12857197Smuller if (!in_resync && (++*cnt >= NULLCNT)) 12957197Smuller return(0); 13057197Smuller return(1); 13157197Smuller } 13257197Smuller 13357197Smuller /* 13457197Smuller * ul_oct() 13557503Smuller * convert an unsigned long to an octal string. many oddball field 13657197Smuller * termination characters are used by the various versions of tar in the 13757197Smuller * different fields. term selects which kind to use. str is BLANK padded 13857197Smuller * at the front to len. we are unable to use only one format as many old 13957197Smuller * tar readers are very cranky about this. 14057197Smuller * Return: 14157197Smuller * 0 if the number fit into the string, -1 otherwise 14257197Smuller */ 14357197Smuller 14457197Smuller #if __STDC__ 14557197Smuller static int 14657197Smuller ul_oct(u_long val, register char *str, register int len, int term) 14757197Smuller #else 14857197Smuller static int 14957197Smuller ul_oct(val, str, len, term) 15057197Smuller u_long val; 15157197Smuller register char *str; 15257197Smuller register int len; 15357197Smuller int term; 15457197Smuller #endif 15557197Smuller { 15657197Smuller register char *pt; 15757197Smuller 15857197Smuller /* 15957197Smuller * term selects the appropriate character(s) for the end of the string 16057197Smuller */ 16157197Smuller pt = str + len - 1; 16257197Smuller switch(term) { 16357197Smuller case 3: 16457197Smuller *pt-- = '\0'; 16557197Smuller break; 16657197Smuller case 2: 16757197Smuller *pt-- = ' '; 16857197Smuller *pt-- = '\0'; 16957197Smuller break; 17057197Smuller case 1: 17157197Smuller *pt-- = ' '; 17257197Smuller break; 17357197Smuller case 0: 17457197Smuller default: 17557197Smuller *pt-- = '\0'; 17657197Smuller *pt-- = ' '; 17757197Smuller break; 17857197Smuller } 17957197Smuller 18057197Smuller /* 18157197Smuller * convert and blank pad if there is space 18257197Smuller */ 18357197Smuller while (pt >= str) { 18457197Smuller *pt-- = '0' + (char)(val & 0x7); 18557197Smuller if ((val = val >> 3) == (u_long)0) 18657197Smuller break; 18757197Smuller } 18857197Smuller 18957197Smuller while (pt >= str) 19057197Smuller *pt-- = ' '; 19157197Smuller if (val != (u_long)0) 19257197Smuller return(-1); 19357197Smuller return(0); 19457197Smuller } 19557197Smuller 19657197Smuller #ifndef NET2_STAT 19757197Smuller /* 19857197Smuller * uqd_oct() 19957197Smuller * convert an u_quad_t to an octal string. one of many oddball field 20057197Smuller * termination characters are used by the various versions of tar in the 20157197Smuller * different fields. term selects which kind to use. str is BLANK padded 20257197Smuller * at the front to len. we are unable to use only one format as many old 20357197Smuller * tar readers are very cranky about this. 20457197Smuller * Return: 20557197Smuller * 0 if the number fit into the string, -1 otherwise 20657197Smuller */ 20757197Smuller 20857197Smuller #if __STDC__ 20957197Smuller static int 21057197Smuller uqd_oct(u_quad_t val, register char *str, register int len, int term) 21157197Smuller #else 21257197Smuller static int 21357197Smuller uqd_oct(val, str, len, term) 21457197Smuller u_quad_t val; 21557197Smuller register char *str; 21657197Smuller register int len; 21757197Smuller int term; 21857197Smuller #endif 21957197Smuller { 22057197Smuller register char *pt; 22157197Smuller 22257197Smuller /* 22357197Smuller * term selects the appropriate character(s) for the end of the string 22457197Smuller */ 22557197Smuller pt = str + len - 1; 22657197Smuller switch(term) { 22757197Smuller case 3: 22857197Smuller *pt-- = '\0'; 22957197Smuller break; 23057197Smuller case 2: 23157197Smuller *pt-- = ' '; 23257197Smuller *pt-- = '\0'; 23357197Smuller break; 23457197Smuller case 1: 23557197Smuller *pt-- = ' '; 23657197Smuller break; 23757197Smuller case 0: 23857197Smuller default: 23957197Smuller *pt-- = '\0'; 24057197Smuller *pt-- = ' '; 24157197Smuller break; 24257197Smuller } 24357197Smuller 24457197Smuller /* 24557197Smuller * convert and blank pad if there is space 24657197Smuller */ 24757197Smuller while (pt >= str) { 24857197Smuller *pt-- = '0' + (char)(val & 0x7); 24957197Smuller if ((val = val >> 3) == 0) 25057197Smuller break; 25157197Smuller } 25257197Smuller 25357197Smuller while (pt >= str) 25457197Smuller *pt-- = ' '; 25557197Smuller if (val != (u_quad_t)0) 25657197Smuller return(-1); 25757197Smuller return(0); 25857197Smuller } 25957197Smuller #endif 26057197Smuller 26157197Smuller /* 26257197Smuller * tar_chksm() 26357197Smuller * calculate the checksum for a tar block counting the checksum field as 26457197Smuller * all blanks (BLNKSUM is that value pre-calculated, the sume of 8 blanks). 26557197Smuller * NOTE: we use len to short circuit summing 0's on write since we ALWAYS 26657197Smuller * pad headers with 0. 26757197Smuller * Return: 26857197Smuller * unsigned long checksum 26957197Smuller */ 27057197Smuller 27157197Smuller #if __STDC__ 27257197Smuller static u_long 27357197Smuller tar_chksm(register char *blk, register int len) 27457197Smuller #else 27557197Smuller static u_long 27657197Smuller tar_chksm(blk, len) 27757197Smuller register char *blk; 27857197Smuller register int len; 27957197Smuller #endif 28057197Smuller { 28157197Smuller register char *stop; 28257197Smuller register char *pt; 28357197Smuller u_long chksm = BLNKSUM; /* inital value is checksum field sum */ 28457197Smuller 28557197Smuller /* 28657197Smuller * add the part of the block before the checksum field 28757197Smuller */ 28857197Smuller pt = blk; 28957197Smuller stop = blk + CHK_OFFSET; 29057197Smuller while (pt < stop) 29157197Smuller chksm += (u_long)(*pt++ & 0xff); 29257197Smuller /* 29357197Smuller * move past the checksum field and keep going, spec counts the 29457197Smuller * checksum field as the sum of 8 blanks (which is pre-computed as 29557197Smuller * BLNKSUM). 29657197Smuller * ASSUMED: len is greater than CHK_OFFSET. (len is where our 0 padding 29757197Smuller * starts, no point in summing zero's) 29857197Smuller */ 29957197Smuller pt += CHK_LEN; 30057197Smuller stop = blk + len; 30157197Smuller while (pt < stop) 30257197Smuller chksm += (u_long)(*pt++ & 0xff); 30357197Smuller return(chksm); 30457197Smuller } 30557197Smuller 30657197Smuller /* 30757197Smuller * Routines for old BSD style tar (also made portable to sysV tar) 30857197Smuller */ 30957197Smuller 31057197Smuller /* 31157197Smuller * tar_id() 31257197Smuller * determine if a block given to us is a valid tar header (and not a USTAR 31357197Smuller * header). We have to be on the lookout for those pesky blocks of all 31457197Smuller * zero's. 31557197Smuller * Return: 31657197Smuller * 0 if a tar header, -1 otherwise 31757197Smuller */ 31857197Smuller 31957197Smuller #if __STDC__ 32057197Smuller int 32157197Smuller tar_id(register char *blk, int size) 32257197Smuller #else 32357197Smuller int 32457197Smuller tar_id(blk, size) 32557197Smuller register char *blk; 32657197Smuller int size; 32757197Smuller #endif 32857197Smuller { 32957197Smuller register HD_TAR *hd; 33057197Smuller register HD_USTAR *uhd; 33157197Smuller 33257197Smuller if (size < BLKMULT) 33357197Smuller return(-1); 33457197Smuller hd = (HD_TAR *)blk; 33557197Smuller uhd = (HD_USTAR *)blk; 33657197Smuller 33757197Smuller /* 33857197Smuller * check for block of zero's first, a simple and fast test, then make 33957197Smuller * sure this is not a ustar header by looking for the ustar magic 34057197Smuller * cookie. We should use TMAGLEN, but some USTAR archive programs are 34157197Smuller * wrong and create archives missing the \0. Last we check the 34257197Smuller * checksum. If this is ok we have to assume it is a valid header. 34357197Smuller */ 34457197Smuller if (hd->name[0] == '\0') 34557197Smuller return(-1); 34657197Smuller if (strncmp(uhd->magic, TMAGIC, TMAGLEN - 1) == 0) 34757197Smuller return(-1); 34857197Smuller if (asc_ul(hd->chksum,sizeof(hd->chksum),OCT) != tar_chksm(blk,BLKMULT)) 34957197Smuller return(-1); 35057197Smuller return(0); 35157197Smuller } 35257197Smuller 35357197Smuller /* 35457197Smuller * tar_opt() 35557197Smuller * handle tar format specific -o options 35657197Smuller * Return: 35757197Smuller * 0 if ok -1 otherwise 35857197Smuller */ 35957197Smuller 36057197Smuller #if __STDC__ 36157197Smuller int 36257197Smuller tar_opt(void) 36357197Smuller #else 36457197Smuller int 36557197Smuller tar_opt() 36657197Smuller #endif 36757197Smuller { 36857197Smuller OPLIST *opt; 36957197Smuller 37057197Smuller while ((opt = opt_next()) != NULL) { 37157197Smuller if (strcmp(opt->name, TAR_OPTION) || 37257197Smuller strcmp(opt->value, TAR_NODIR)) { 37357197Smuller warn(1, "Unknown tar format -o option/value pair %s=%s", 37457197Smuller opt->name, opt->value); 37557197Smuller warn(1,"%s=%s is the only supported tar format option", 37657197Smuller TAR_OPTION, TAR_NODIR); 37757197Smuller return(-1); 37857197Smuller } 37957197Smuller 38057197Smuller /* 38157197Smuller * we only support one option, and only when writing 38257197Smuller */ 38357197Smuller if ((act != APPND) && (act != ARCHIVE)) { 38457197Smuller warn(1, "%s=%s is only supported when writing.", 38557197Smuller opt->name, opt->value); 38657197Smuller return(-1); 38757197Smuller } 38857197Smuller tar_nodir = 1; 38957197Smuller } 39057197Smuller return(0); 39157197Smuller } 39257197Smuller 39357197Smuller 39457197Smuller /* 39557197Smuller * tar_rd() 39657197Smuller * extract the values out of block already determined to be a tar header. 39757197Smuller * store the values in the ARCHD parameter. 39857197Smuller * Return: 39957197Smuller * 0 40057197Smuller */ 40157197Smuller 40257197Smuller #if __STDC__ 40357197Smuller int 40457197Smuller tar_rd(register ARCHD *arcn, register char *buf) 40557197Smuller #else 40657197Smuller int 40757197Smuller tar_rd(arcn, buf) 40857197Smuller register ARCHD *arcn; 40957197Smuller register char *buf; 41057197Smuller #endif 41157197Smuller { 41257197Smuller register HD_TAR *hd; 41357197Smuller register char *pt; 41457197Smuller 41557197Smuller /* 41657197Smuller * we only get proper sized buffers passed to us 41757197Smuller */ 41857197Smuller if (tar_id(buf, BLKMULT) < 0) 41957197Smuller return(-1); 42057197Smuller arcn->org_name = arcn->name; 42157197Smuller arcn->sb.st_nlink = 1; 42257197Smuller arcn->pat = NULL; 42357197Smuller 42457197Smuller /* 42557197Smuller * copy out the name and values in the stat buffer 42657197Smuller */ 42757197Smuller hd = (HD_TAR *)buf; 42857197Smuller arcn->nlen = l_strncpy(arcn->name, hd->name, sizeof(hd->name)); 42957197Smuller arcn->name[arcn->nlen] = '\0'; 43057197Smuller arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode,sizeof(hd->mode),OCT) & 43157197Smuller 0xfff); 43257197Smuller arcn->sb.st_uid = (uid_t)asc_ul(hd->uid, sizeof(hd->uid), OCT); 43357197Smuller arcn->sb.st_gid = (gid_t)asc_ul(hd->gid, sizeof(hd->gid), OCT); 43457197Smuller arcn->sb.st_size = (size_t)asc_ul(hd->size, sizeof(hd->size), OCT); 43557197Smuller arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT); 43657503Smuller arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime; 43757197Smuller 43857197Smuller /* 43957197Smuller * have to look at the last character, it may be a '/' and that is used 44057197Smuller * to encode this as a directory 44157197Smuller */ 44257197Smuller pt = &(arcn->name[arcn->nlen - 1]); 44357197Smuller arcn->pad = 0; 44457197Smuller arcn->skip = 0; 44557197Smuller switch(hd->linkflag) { 44657197Smuller case SYMTYPE: 44757197Smuller /* 44857197Smuller * symbolic link, need to get the link name and set the type in 44957197Smuller * the st_mode so -v printing will look correct. 45057197Smuller */ 45157197Smuller arcn->type = PAX_SLK; 45257197Smuller arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname, 45357197Smuller sizeof(hd->linkname)); 45457197Smuller arcn->ln_name[arcn->ln_nlen] = '\0'; 45557197Smuller arcn->sb.st_mode |= S_IFLNK; 45657197Smuller break; 45757197Smuller case LNKTYPE: 45857197Smuller /* 45957197Smuller * hard link, need to get the link name, set the type in the 46057197Smuller * st_mode and st_nlink so -v printing will look better. 46157197Smuller */ 46257197Smuller arcn->type = PAX_HLK; 46357197Smuller arcn->sb.st_nlink = 2; 46457197Smuller arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname, 46557197Smuller sizeof(hd->linkname)); 46657197Smuller arcn->ln_name[arcn->ln_nlen] = '\0'; 46757503Smuller 46857197Smuller /* 46957197Smuller * no idea of what type this thing really points at, but 47057197Smuller * we set something for printing only. 47157197Smuller */ 47257197Smuller arcn->sb.st_mode |= S_IFREG; 47357197Smuller break; 47457197Smuller case AREGTYPE: 47557197Smuller case REGTYPE: 47657197Smuller default: 47757197Smuller /* 47857197Smuller * If we have a trailing / this is a directory and NOT a file. 47957197Smuller */ 48057197Smuller arcn->ln_name[0] = '\0'; 48157197Smuller arcn->ln_nlen = 0; 48257197Smuller if (*pt == '/') { 48357197Smuller /* 48457197Smuller * it is a directory, set the mode for -v printing 48557197Smuller */ 48657197Smuller arcn->type = PAX_DIR; 48757197Smuller arcn->sb.st_mode |= S_IFDIR; 48857197Smuller arcn->sb.st_nlink = 2; 48957197Smuller } else { 49057197Smuller /* 49157197Smuller * have a file that will be followed by data. Set the 49257197Smuller * skip value to the size field and caluculate the size 49357197Smuller * of the padding. 49457197Smuller */ 49557197Smuller arcn->type = PAX_REG; 49657197Smuller arcn->sb.st_mode |= S_IFREG; 49757197Smuller arcn->pad = TAR_PAD(arcn->sb.st_size); 49857197Smuller arcn->skip = arcn->sb.st_size; 49957197Smuller } 50057197Smuller break; 50157197Smuller } 50257197Smuller 50357197Smuller /* 50457197Smuller * strip off any trailing slash. 50557197Smuller */ 50657197Smuller if (*pt == '/') { 50757503Smuller *pt = '\0'; 50857197Smuller --arcn->nlen; 50957197Smuller } 51057197Smuller return(0); 51157197Smuller } 51257197Smuller 51357197Smuller /* 51457197Smuller * tar_wr() 51557197Smuller * write a tar header for the file specified in the ARCHD to the archive. 51657197Smuller * Have to check for file types that cannot be stored and file names that 51757197Smuller * are too long. Be careful of the term (last arg) to ul_oct, each field 51857197Smuller * of tar has it own spec for the termination character(s). 51957197Smuller * ASSUMED: space after header in header block is zero filled 52057197Smuller * Return: 52157197Smuller * 0 if file has data to be written after the header, 1 if file has NO 52257197Smuller * data to write after the header, -1 if archive write failed 52357197Smuller */ 52457197Smuller 52557197Smuller #if __STDC__ 52657197Smuller int 52757197Smuller tar_wr(register ARCHD *arcn) 52857197Smuller #else 52957197Smuller int 53057197Smuller tar_wr(arcn) 53157197Smuller register ARCHD *arcn; 53257197Smuller #endif 53357197Smuller { 53457197Smuller register HD_TAR *hd; 53557197Smuller int len; 53657197Smuller char hdblk[sizeof(HD_TAR)]; 53757197Smuller 53857197Smuller /* 53957197Smuller * check for those file system types which tar cannot store 54057197Smuller */ 54157197Smuller switch(arcn->type) { 54257197Smuller case PAX_DIR: 54357197Smuller /* 54457197Smuller * user asked that dirs not be written to the archive 54557197Smuller */ 54657197Smuller if (tar_nodir) 54757197Smuller return(1); 54857197Smuller break; 54957197Smuller case PAX_CHR: 55057197Smuller warn(1, "Tar cannot archive a character device %s", 55157197Smuller arcn->org_name); 55257197Smuller return(1); 55357197Smuller case PAX_BLK: 55457197Smuller warn(1, "Tar cannot archive a block device %s", arcn->org_name); 55557197Smuller return(1); 55657197Smuller case PAX_SCK: 55757197Smuller warn(1, "Tar cannot archive a socket %s", arcn->org_name); 55857197Smuller return(1); 55957197Smuller case PAX_FIF: 56057197Smuller warn(1, "Tar cannot archive a fifo %s", arcn->org_name); 56157197Smuller return(1); 56257197Smuller case PAX_SLK: 56357197Smuller case PAX_HLK: 56457197Smuller case PAX_HRG: 56557197Smuller if (arcn->ln_nlen > sizeof(hd->linkname)) { 56657197Smuller warn(1,"Link name too long for tar %s", arcn->ln_name); 56757197Smuller return(1); 56857197Smuller } 56957197Smuller break; 57057197Smuller case PAX_REG: 57157197Smuller case PAX_CTG: 57257197Smuller default: 57357197Smuller break; 57457197Smuller } 57557197Smuller 57657197Smuller /* 57757197Smuller * check file name len, remember extra char for dirs (the / at the end) 57857197Smuller */ 57957197Smuller len = arcn->nlen; 58057197Smuller if (arcn->type == PAX_DIR) 58157197Smuller ++len; 58257197Smuller if (len > sizeof(hd->name)) { 58357197Smuller warn(1, "File name too long for tar %s", arcn->name); 58457197Smuller return(1); 58557197Smuller } 58657197Smuller 58757197Smuller /* 58857197Smuller * copy the data out of the ARCHD into the tar header based on the type 58957197Smuller * of the file. Remember many tar readers want the unused fields to be 59057197Smuller * padded with zero. We set the linkflag field (type), the linkname 59157197Smuller * (or zero if not used),the size, and set the padding (if any) to be 59257197Smuller * added after the file data (0 for all other types, as they only have 59357197Smuller * a header) 59457197Smuller */ 59557197Smuller hd = (HD_TAR *)hdblk; 59657197Smuller zf_strncpy(hd->name, arcn->name, sizeof(hd->name)); 59757197Smuller arcn->pad = 0; 59857197Smuller 59957197Smuller if (arcn->type == PAX_DIR) { 60057197Smuller /* 60157197Smuller * directories are the same as files, except have a filename 60257197Smuller * that ends with a /, we add the slash here. No data follows, 60357197Smuller * dirs, so no pad. 60457197Smuller */ 60557197Smuller hd->linkflag = AREGTYPE; 60657197Smuller bzero(hd->linkname, sizeof(hd->linkname)); 60757197Smuller hd->name[len-1] = '/'; 60857197Smuller if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1)) 60957197Smuller goto out; 61057197Smuller } else if (arcn->type == PAX_SLK) { 61157197Smuller /* 61257197Smuller * no data follows this file, so no pad 61357197Smuller */ 61457197Smuller hd->linkflag = SYMTYPE; 61557197Smuller zf_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname)); 61657197Smuller if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1)) 61757197Smuller goto out; 61857197Smuller } else if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG)) { 61957197Smuller /* 62057197Smuller * no data follows this file, so no pad 62157197Smuller */ 62257197Smuller hd->linkflag = LNKTYPE; 62357197Smuller zf_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname)); 62457197Smuller if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1)) 62557197Smuller goto out; 62657197Smuller } else { 62757197Smuller /* 62857197Smuller * data follows this file, so set the pad 62957197Smuller */ 63057197Smuller hd->linkflag = AREGTYPE; 63157197Smuller bzero(hd->linkname, sizeof(hd->linkname)); 63257197Smuller # ifdef NET2_STAT 63357197Smuller if (ul_oct((u_long)arcn->sb.st_size, hd->size, 63457197Smuller sizeof(hd->size), 1)) { 63557197Smuller # else 63657197Smuller if (uqd_oct((u_quad_t)arcn->sb.st_size, hd->size, 63757197Smuller sizeof(hd->size), 1)) { 63857197Smuller # endif 63957197Smuller warn(1,"File is too large for tar %s", arcn->org_name); 64057197Smuller return(1); 64157197Smuller } 64257197Smuller arcn->pad = TAR_PAD(arcn->sb.st_size); 64357197Smuller } 64457197Smuller 64557197Smuller /* 64657197Smuller * copy those fields that are independent of the type 64757197Smuller */ 64857197Smuller if (ul_oct((u_long)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 0) || 64957197Smuller ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 0) || 65057197Smuller ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 0) || 65157197Smuller ul_oct((u_long)arcn->sb.st_mtime, hd->mtime, sizeof(hd->mtime), 1)) 65257197Smuller goto out; 65357197Smuller 65457197Smuller /* 65557197Smuller * calculate and add the checksum, then write the header. A return of 65657197Smuller * 0 tells the caller to now write the file data, 1 says no data needs 65757197Smuller * to be written 65857197Smuller */ 65957197Smuller if (ul_oct(tar_chksm(hdblk, sizeof(HD_TAR)), hd->chksum, 66057197Smuller sizeof(hd->chksum), 2)) 66157197Smuller goto out; 66257197Smuller if (wr_rdbuf(hdblk, sizeof(HD_TAR)) < 0) 66357197Smuller return(-1); 66457197Smuller if (wr_skip((off_t)(BLKMULT - sizeof(HD_TAR))) < 0) 66557197Smuller return(-1); 66657197Smuller if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG)) 66757197Smuller return(0); 66857197Smuller return(1); 66957197Smuller 67057197Smuller out: 67157197Smuller /* 67257197Smuller * header field is out of range 67357197Smuller */ 67457197Smuller warn(1, "Tar header field is too small for %s", arcn->org_name); 67557197Smuller return(1); 67657197Smuller } 67757197Smuller 67857197Smuller /* 67957197Smuller * Routines for POSIX ustar 68057197Smuller */ 68157197Smuller 68257197Smuller /* 68357197Smuller * ustar_strd() 68457197Smuller * initialization for ustar read 68557197Smuller * Return: 68657197Smuller * 0 if ok, -1 otherwise 68757197Smuller */ 68857197Smuller 68957197Smuller #if __STDC__ 69057197Smuller int 69157197Smuller ustar_strd(void) 69257197Smuller #else 69357197Smuller int 69457197Smuller ustar_strd() 69557197Smuller #endif 69657197Smuller { 69757197Smuller if ((usrtb_start() < 0) || (grptb_start() < 0)) 69857197Smuller return(-1); 69957197Smuller return(0); 70057197Smuller } 70157197Smuller 70257197Smuller /* 70357197Smuller * ustar_stwr() 70457197Smuller * initialization for ustar write 70557197Smuller * Return: 70657197Smuller * 0 if ok, -1 otherwise 70757197Smuller */ 70857197Smuller 70957197Smuller #if __STDC__ 71057197Smuller int 71157197Smuller ustar_stwr(void) 71257197Smuller #else 71357197Smuller int 71457197Smuller ustar_stwr() 71557197Smuller #endif 71657197Smuller { 71757197Smuller if ((uidtb_start() < 0) || (gidtb_start() < 0)) 71857197Smuller return(-1); 71957197Smuller return(0); 72057197Smuller } 72157197Smuller 72257197Smuller /* 72357197Smuller * ustar_id() 72457197Smuller * determine if a block given to us is a valid ustar header. We have to 72557197Smuller * be on the lookout for those pesky blocks of all zero's 72657197Smuller * Return: 72757197Smuller * 0 if a ustar header, -1 otherwise 72857197Smuller */ 72957197Smuller 73057197Smuller #if __STDC__ 73157197Smuller int 73257197Smuller ustar_id(char *blk, int size) 73357197Smuller #else 73457197Smuller int 73557197Smuller ustar_id(blk, size) 73657197Smuller char *blk; 73757197Smuller int size; 73857197Smuller #endif 73957197Smuller { 74057197Smuller register HD_USTAR *hd; 74157197Smuller 74257197Smuller if (size < BLKMULT) 74357197Smuller return(-1); 74457197Smuller hd = (HD_USTAR *)blk; 74557197Smuller 74657197Smuller /* 74757197Smuller * check for block of zero's first, a simple and fast test then check 74857197Smuller * ustar magic cookie. We should use TMAGLEN, but some USTAR archive 74957197Smuller * programs are fouled up and create archives missing the \0. Last we 75057197Smuller * check the checksum. If ok we have to assume it is a valid header. 75157197Smuller */ 75257197Smuller if (hd->name[0] == '\0') 75357197Smuller return(-1); 75457197Smuller if (strncmp(hd->magic, TMAGIC, TMAGLEN - 1) != 0) 75557197Smuller return(-1); 75657197Smuller if (asc_ul(hd->chksum,sizeof(hd->chksum),OCT) != tar_chksm(blk,BLKMULT)) 75757197Smuller return(-1); 75857197Smuller return(0); 75957197Smuller } 76057197Smuller 76157197Smuller /* 76257197Smuller * ustar_rd() 76357197Smuller * extract the values out of block already determined to be a ustar header. 76457197Smuller * store the values in the ARCHD parameter. 76557197Smuller * Return: 76657197Smuller * 0 76757197Smuller */ 76857197Smuller 76957197Smuller #if __STDC__ 77057197Smuller int 77157197Smuller ustar_rd(register ARCHD *arcn, register char *buf) 77257197Smuller #else 77357197Smuller int 77457197Smuller ustar_rd(arcn, buf) 77557197Smuller register ARCHD *arcn; 77657197Smuller register char *buf; 77757197Smuller #endif 77857197Smuller { 77957197Smuller register HD_USTAR *hd; 78057197Smuller register char *dest; 78157197Smuller register int cnt = 0; 78257197Smuller dev_t devmajor; 78357197Smuller dev_t devminor; 78457197Smuller 78557197Smuller /* 78657197Smuller * we only get proper sized buffers 78757197Smuller */ 78857197Smuller if (ustar_id(buf, BLKMULT) < 0) 78957197Smuller return(-1); 79057197Smuller arcn->org_name = arcn->name; 79157197Smuller arcn->sb.st_nlink = 1; 79257197Smuller arcn->pat = NULL; 79357197Smuller hd = (HD_USTAR *)buf; 79457197Smuller 79557197Smuller /* 79657197Smuller * see if the filename is split into two parts. if, so joint the parts. 79757197Smuller * we copy the prefix first and add a / between the prefix and name. 79857197Smuller */ 79957197Smuller dest = arcn->name; 80057197Smuller if (*(hd->prefix) != '\0') { 80157197Smuller cnt = l_strncpy(arcn->name, hd->prefix, sizeof(hd->prefix)); 80257197Smuller dest = arcn->name + arcn->nlen; 80357197Smuller *dest++ = '/'; 80457197Smuller } 80557197Smuller arcn->nlen = l_strncpy(dest, hd->name, sizeof(hd->name)); 80657197Smuller arcn->nlen += cnt; 80757197Smuller arcn->name[arcn->nlen] = '\0'; 80857197Smuller 80957197Smuller /* 81057503Smuller * follow the spec to the letter. we should only have mode bits, strip 81157197Smuller * off all other crud we may be passed. 81257197Smuller */ 81357197Smuller arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode, sizeof(hd->mode), OCT) & 81457197Smuller 0xfff); 81557197Smuller arcn->sb.st_size = (size_t)asc_ul(hd->size, sizeof(hd->size), OCT); 81657197Smuller arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT); 81757503Smuller arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime; 81857197Smuller 81957197Smuller /* 82057197Smuller * If we can find the ascii names for gname and uname in the password 82157197Smuller * and group files we will use the uid's and gid they bind. Otherwise 82257503Smuller * we use the uid and gid values stored in the header. (This is what 82357503Smuller * the posix spec wants). 82457197Smuller */ 82557197Smuller hd->gname[sizeof(hd->gname) - 1] = '\0'; 82657197Smuller if (gid_name(hd->gname, &(arcn->sb.st_gid)) < 0) 82757197Smuller arcn->sb.st_gid = (gid_t)asc_ul(hd->gid, sizeof(hd->gid), OCT); 82857197Smuller hd->uname[sizeof(hd->uname) - 1] = '\0'; 82957197Smuller if (uid_name(hd->uname, &(arcn->sb.st_uid)) < 0) 83057197Smuller arcn->sb.st_uid = (uid_t)asc_ul(hd->uid, sizeof(hd->uid), OCT); 83157197Smuller 83257197Smuller /* 83357197Smuller * set the defaults, these may be changed depending on the file type 83457197Smuller */ 83557197Smuller arcn->ln_name[0] = '\0'; 83657197Smuller arcn->ln_nlen = 0; 83757197Smuller arcn->pad = 0; 83857197Smuller arcn->skip = 0; 83957197Smuller arcn->sb.st_rdev = (dev_t)0; 84057197Smuller 84157197Smuller /* 84257197Smuller * set the mode and PAX type according to the typeflag in the header 84357197Smuller */ 84457197Smuller switch(hd->typeflag) { 84557197Smuller case FIFOTYPE: 84657197Smuller arcn->type = PAX_FIF; 84757197Smuller arcn->sb.st_mode |= S_IFIFO; 84857197Smuller break; 84957197Smuller case DIRTYPE: 85057197Smuller arcn->type = PAX_DIR; 85157197Smuller arcn->sb.st_mode |= S_IFDIR; 85257197Smuller arcn->sb.st_nlink = 2; 853*57788Smuller 854*57788Smuller /* 855*57788Smuller * Some programs that create ustar archives append a '/' 856*57788Smuller * to the pathname for directories. This clearly violates 857*57788Smuller * ustar specs, but we will silently strip it off anyway. 858*57788Smuller */ 859*57788Smuller if (arcn->name[arcn->nlen - 1] == '/') 860*57788Smuller arcn->name[--arcn->nlen] = '\0'; 86157197Smuller break; 86257197Smuller case BLKTYPE: 86357197Smuller case CHRTYPE: 86457197Smuller /* 86557197Smuller * this type requires the rdev field to be set. 86657197Smuller */ 86757197Smuller if (hd->typeflag == BLKTYPE) { 86857197Smuller arcn->type = PAX_BLK; 86957197Smuller arcn->sb.st_mode |= S_IFBLK; 87057197Smuller } else { 87157197Smuller arcn->type = PAX_CHR; 87257197Smuller arcn->sb.st_mode |= S_IFCHR; 87357197Smuller } 87457197Smuller devmajor = (dev_t)asc_ul(hd->devmajor,sizeof(hd->devmajor),OCT); 87557197Smuller devminor = (dev_t)asc_ul(hd->devminor,sizeof(hd->devminor),OCT); 87657197Smuller arcn->sb.st_rdev = TODEV(devmajor, devminor); 87757197Smuller break; 87857197Smuller case SYMTYPE: 87957197Smuller case LNKTYPE: 88057197Smuller if (hd->typeflag == SYMTYPE) { 88157197Smuller arcn->type = PAX_SLK; 88257197Smuller arcn->sb.st_mode |= S_IFLNK; 88357197Smuller } else { 88457197Smuller arcn->type = PAX_HLK; 88557197Smuller /* 88657197Smuller * so printing looks better 88757197Smuller */ 88857197Smuller arcn->sb.st_mode |= S_IFREG; 88957197Smuller arcn->sb.st_nlink = 2; 89057197Smuller } 89157197Smuller /* 89257197Smuller * copy the link name 89357197Smuller */ 89457197Smuller arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname, 89557197Smuller sizeof(hd->linkname)); 89657197Smuller arcn->ln_name[arcn->ln_nlen] = '\0'; 89757197Smuller break; 89857197Smuller case CONTTYPE: 89957197Smuller case AREGTYPE: 90057197Smuller case REGTYPE: 90157197Smuller default: 90257197Smuller /* 90357197Smuller * these types have file data that follows. Set the skip and 90457197Smuller * pad fields. 90557197Smuller */ 90657197Smuller arcn->type = PAX_REG; 90757197Smuller arcn->pad = TAR_PAD(arcn->sb.st_size); 90857197Smuller arcn->skip = arcn->sb.st_size; 90957197Smuller arcn->sb.st_mode |= S_IFREG; 91057197Smuller break; 91157197Smuller } 91257197Smuller return(0); 91357197Smuller } 91457197Smuller 91557197Smuller /* 91657197Smuller * ustar_wr() 91757197Smuller * write a ustar header for the file specified in the ARCHD to the archive 91857197Smuller * Have to check for file types that cannot be stored and file names that 91957197Smuller * are too long. Be careful of the term (last arg) to ul_oct, we only use 92057197Smuller * '\0' for the termination character (this is different than picky tar) 92157197Smuller * ASSUMED: space after header in header block is zero filled 92257197Smuller * Return: 92357197Smuller * 0 if file has data to be written after the header, 1 if file has NO 92457197Smuller * data to write after the header, -1 if archive write failed 92557197Smuller */ 92657197Smuller 92757197Smuller #if __STDC__ 92857197Smuller int 92957197Smuller ustar_wr(register ARCHD *arcn) 93057197Smuller #else 93157197Smuller int 93257197Smuller ustar_wr(arcn) 93357197Smuller register ARCHD *arcn; 93457197Smuller #endif 93557197Smuller { 93657197Smuller register HD_USTAR *hd; 93757197Smuller register char *pt; 93857197Smuller char hdblk[sizeof(HD_USTAR)]; 93957197Smuller 94057197Smuller /* 94157197Smuller * check for those file system types ustar cannot store 94257197Smuller */ 94357197Smuller if (arcn->type == PAX_SCK) { 94457197Smuller warn(1, "Ustar cannot archive a socket %s", arcn->org_name); 94557197Smuller return(1); 94657197Smuller } 94757197Smuller 94857197Smuller /* 94957197Smuller * check the length of the linkname 95057197Smuller */ 95157197Smuller if (((arcn->type == PAX_SLK) || (arcn->type == PAX_HLK) || 95257197Smuller (arcn->type == PAX_HRG)) && (arcn->ln_nlen > sizeof(hd->linkname))){ 95357197Smuller warn(1, "Link name too long for ustar %s", arcn->ln_name); 95457197Smuller return(1); 95557197Smuller } 95657197Smuller 95757197Smuller /* 95857197Smuller * split the path name into prefix and name fields (if needed). if 95957197Smuller * pt != arcn->name, the name has to be split 96057197Smuller */ 96157197Smuller if ((pt = name_split(arcn->name, arcn->nlen)) == NULL) { 96257197Smuller warn(1, "File name too long for ustar %s", arcn->name); 96357197Smuller return(1); 96457197Smuller } 96557197Smuller hd = (HD_USTAR *)hdblk; 96657197Smuller arcn->pad = 0L; 96757197Smuller 96857197Smuller /* 96957197Smuller * split the name, or zero out the prefix 97057197Smuller */ 97157197Smuller if (pt != arcn->name) { 97257197Smuller /* 97357197Smuller * name was split, pt points at the / where the split is to 97457197Smuller * occur, we remove the / and copy the first part to the prefix 97557197Smuller */ 97657197Smuller *pt = '\0'; 97757197Smuller zf_strncpy(hd->prefix, arcn->name, sizeof(hd->prefix)); 97857197Smuller *pt++ = '/'; 97957197Smuller } else 98057197Smuller bzero(hd->prefix, sizeof(hd->prefix)); 98157197Smuller 98257197Smuller /* 98357197Smuller * copy the name part. this may be the whole path or the part after 98457197Smuller * the prefix 98557197Smuller */ 98657197Smuller zf_strncpy(hd->name, pt, sizeof(hd->name)); 98757197Smuller 98857197Smuller /* 98957197Smuller * set the fields in the header that are type dependent 99057197Smuller */ 99157197Smuller switch(arcn->type) { 99257197Smuller case PAX_DIR: 99357197Smuller hd->typeflag = DIRTYPE; 99457197Smuller bzero(hd->linkname, sizeof(hd->linkname)); 99557197Smuller bzero(hd->devmajor, sizeof(hd->devmajor)); 99657197Smuller bzero(hd->devminor, sizeof(hd->devminor)); 99757197Smuller if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3)) 99857197Smuller goto out; 99957197Smuller break; 100057197Smuller case PAX_CHR: 100157197Smuller case PAX_BLK: 100257197Smuller if (arcn->type == PAX_CHR) 100357197Smuller hd->typeflag = CHRTYPE; 100457197Smuller else 100557197Smuller hd->typeflag = BLKTYPE; 100657197Smuller bzero(hd->linkname, sizeof(hd->linkname)); 100757197Smuller if (ul_oct((u_long)MAJOR(arcn->sb.st_rdev), hd->devmajor, 100857197Smuller sizeof(hd->devmajor), 3) || 100957197Smuller ul_oct((u_long)MINOR(arcn->sb.st_rdev), hd->devminor, 101057197Smuller sizeof(hd->devminor), 3) || 101157197Smuller ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3)) 101257197Smuller goto out; 101357197Smuller break; 101457197Smuller case PAX_FIF: 101557197Smuller hd->typeflag = FIFOTYPE; 101657197Smuller bzero(hd->linkname, sizeof(hd->linkname)); 101757197Smuller bzero(hd->devmajor, sizeof(hd->devmajor)); 101857197Smuller bzero(hd->devminor, sizeof(hd->devminor)); 101957197Smuller if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3)) 102057197Smuller goto out; 102157197Smuller break; 102257197Smuller case PAX_SLK: 102357197Smuller case PAX_HLK: 102457197Smuller case PAX_HRG: 102557197Smuller if (arcn->type == PAX_SLK) 102657197Smuller hd->typeflag = SYMTYPE; 102757197Smuller else 102857197Smuller hd->typeflag = LNKTYPE; 102957197Smuller zf_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname)); 103057197Smuller bzero(hd->devmajor, sizeof(hd->devmajor)); 103157197Smuller bzero(hd->devminor, sizeof(hd->devminor)); 103257197Smuller if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3)) 103357197Smuller goto out; 103457197Smuller break; 103557197Smuller case PAX_REG: 103657197Smuller case PAX_CTG: 103757197Smuller default: 103857197Smuller /* 103957197Smuller * file data with this type, set the padding 104057197Smuller */ 104157197Smuller if (arcn->type == PAX_CTG) 104257197Smuller hd->typeflag = CONTTYPE; 104357197Smuller else 104457197Smuller hd->typeflag = REGTYPE; 104557197Smuller bzero(hd->linkname, sizeof(hd->linkname)); 104657197Smuller bzero(hd->devmajor, sizeof(hd->devmajor)); 104757197Smuller bzero(hd->devminor, sizeof(hd->devminor)); 104857197Smuller arcn->pad = TAR_PAD(arcn->sb.st_size); 104957197Smuller # ifdef NET2_STAT 105057197Smuller if (ul_oct((u_long)arcn->sb.st_size, hd->size, 105157197Smuller sizeof(hd->size), 3)) { 105257197Smuller # else 105357197Smuller if (uqd_oct((u_quad_t)arcn->sb.st_size, hd->size, 105457197Smuller sizeof(hd->size), 3)) { 105557197Smuller # endif 105657197Smuller warn(1,"File is too long for ustar %s",arcn->org_name); 105757197Smuller return(1); 105857197Smuller } 105957197Smuller break; 106057197Smuller } 106157197Smuller 106257197Smuller zf_strncpy(hd->magic, TMAGIC, TMAGLEN); 106357197Smuller zf_strncpy(hd->version, TVERSION, TVERSLEN); 106457197Smuller 106557197Smuller /* 106657197Smuller * set the remaining fields. Some versions want all 16 bits of mode 106757197Smuller * we better humor them (they really do not meet spec though).... 106857197Smuller */ 106957197Smuller if (ul_oct((u_long)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 3) || 107057197Smuller ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 3) || 107157197Smuller ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 3) || 107257197Smuller ul_oct((u_long)arcn->sb.st_mtime,hd->mtime,sizeof(hd->mtime),3)) 107357197Smuller goto out; 107457197Smuller zf_strncpy(hd->uname,name_uid(arcn->sb.st_uid, 0),sizeof(hd->uname)); 107557197Smuller zf_strncpy(hd->gname,name_gid(arcn->sb.st_gid, 0),sizeof(hd->gname)); 107657197Smuller 107757197Smuller /* 107857197Smuller * calculate and store the checksum write the header to the archive 107957197Smuller * return 0 tells the caller to now write the file data, 1 says no data 108057197Smuller * needs to be written 108157197Smuller */ 108257197Smuller if (ul_oct(tar_chksm(hdblk, sizeof(HD_USTAR)), hd->chksum, 108357197Smuller sizeof(hd->chksum), 3)) 108457197Smuller goto out; 108557197Smuller if (wr_rdbuf(hdblk, sizeof(HD_USTAR)) < 0) 108657197Smuller return(-1); 108757197Smuller if (wr_skip((off_t)(BLKMULT - sizeof(HD_USTAR))) < 0) 108857197Smuller return(-1); 108957197Smuller if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG)) 109057197Smuller return(0); 109157197Smuller return(1); 109257197Smuller 109357197Smuller out: 109457197Smuller /* 109557197Smuller * header field is out of range 109657197Smuller */ 109757197Smuller warn(1, "Ustar header field is too small for %s", arcn->org_name); 109857197Smuller return(1); 109957197Smuller } 110057197Smuller 110157197Smuller /* 110257197Smuller * name_split() 110357197Smuller * see if the name has to be split for storage in a ustar header. We try 110457197Smuller * to fit the entire name in the name field without splitting if we can. 110557197Smuller * The split point is always at a / 110657197Smuller * Return 110757197Smuller * character pointer to split point (always the / that is to be removed 110857197Smuller * if the split is not needed, the points is set to the start of the file 110957197Smuller * name (it would violate the spec to split there). A NULL is returned if 111057197Smuller * the file name is too long 111157197Smuller */ 111257197Smuller 111357197Smuller #if __STDC__ 111457197Smuller static char * 111557197Smuller name_split(register char *name, register int len) 111657197Smuller #else 111757197Smuller static char * 111857197Smuller name_split(name, len) 111957197Smuller register char *name; 112057197Smuller register int len; 112157197Smuller #endif 112257197Smuller { 112357197Smuller register char *start; 112457197Smuller 112557197Smuller /* 112657197Smuller * check to see if the file name is small enough to fit in the name 112757197Smuller * field. if so just return a pointer to the name. 112857197Smuller */ 112957197Smuller if (len <= TNMSZ) 113057197Smuller return(name); 113157197Smuller if (len > (TPFSZ + TNMSZ + 1)) 113257197Smuller return(NULL); 113357197Smuller 113457197Smuller /* 113557197Smuller * we start looking at the biggest sized piece that fits in the name 113657197Smuller * field. We walk foward looking for a slash to split at. The idea is 113757197Smuller * to find the biggest piece to fit in the name field (or the smallest 113857197Smuller * prefix we can find) (the -1 is correct the biggest piece would 113957197Smuller * include the slash between the two parts that gets thrown away) 114057197Smuller */ 114157197Smuller start = name + len - TNMSZ - 1; 114257197Smuller while ((*start != '\0') && (*start != '/')) 114357197Smuller ++start; 114457197Smuller 114557197Smuller /* 114657197Smuller * if we hit the end of the string, this name cannot be split, so we 114757197Smuller * cannot store this file. 114857197Smuller */ 114957197Smuller if (*start == '\0') 115057197Smuller return(NULL); 115157197Smuller len = start - name; 115257197Smuller 115357197Smuller /* 115457197Smuller * NOTE: /str where the length of str == TNMSZ can not be stored under 115557197Smuller * the p1003.1-1990 spec for ustar. We could force a prefix of / and 115657197Smuller * the file would then expand on extract to //str. The len == 0 below 115757197Smuller * makes this special case follow the spec to the letter. 115857197Smuller */ 115957197Smuller if ((len > TPFSZ) || (len == 0)) 116057197Smuller return(NULL); 116157197Smuller 116257197Smuller /* 116357197Smuller * ok have a split point, return it to the caller 116457197Smuller */ 116557197Smuller return(start); 116657197Smuller } 1167