X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=tar.c;h=97639346d557bddd16a12bf7c7b9cedc5cceb397;hb=a547751988577b94d9cefd260173ec7e69b8669c;hp=af7f2141f8a4614ce3d795d2dc570637e34fd17c;hpb=13a3cb98a66bd66bb6627ccd5a5da35070c86f15;p=debian%2Fpax diff --git a/tar.c b/tar.c index af7f214..9763934 100644 --- a/tar.c +++ b/tar.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tar.c,v 1.13 1998/09/26 21:29:41 millert Exp $ */ +/* $OpenBSD: tar.c,v 1.41 2006/03/04 20:24:55 otto Exp $ */ /* $NetBSD: tar.c,v 1.5 1995/03/21 09:07:49 cgd Exp $ */ /*- @@ -17,11 +17,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -40,9 +36,9 @@ #ifndef lint #if 0 -static char sccsid[] = "@(#)tar.c 8.2 (Berkeley) 4/18/94"; +static const char sccsid[] = "@(#)tar.c 8.2 (Berkeley) 4/18/94"; #else -static char rcsid[] = "$OpenBSD: tar.c,v 1.13 1998/09/26 21:29:41 millert Exp $"; +static const char rcsid[] = "$OpenBSD: tar.c,v 1.41 2006/03/04 20:24:55 otto Exp $"; #endif #endif /* not lint */ @@ -63,18 +59,26 @@ static char rcsid[] = "$OpenBSD: tar.c,v 1.13 1998/09/26 21:29:41 millert Exp $" * Routines for reading, writing and header identify of various versions of tar */ -static u_long tar_chksm __P((register char *, register int)); -static char *name_split __P((register char *, register int)); -static int ul_oct __P((u_long, register char *, register int, int)); -#ifndef NET2_STAT -static int uqd_oct __P((u_quad_t, register char *, register int, int)); +static size_t expandname(char *, size_t, char **, const char *, size_t); +static u_long tar_chksm(char *, int); +static char *name_split(char *, int); +static int ul_oct(u_long, char *, int, int); +#ifndef LONG_OFF_T +static int uqd_oct(u_quad_t, char *, int, int); #endif +static uid_t uid_nobody; +static uid_t uid_warn; +static gid_t gid_nobody; +static gid_t gid_warn; + /* * Routines common to all versions of tar */ static int tar_nodir; /* do not write dirs under old tar */ +char *gnu_name_string; /* GNU ././@LongLink hackery name */ +char *gnu_link_string; /* GNU ././@LongLink hackery link */ /* * tar_endwr() @@ -83,13 +87,8 @@ static int tar_nodir; /* do not write dirs under old tar */ * 0 if ok, -1 otherwise (what wr_skip returns) */ -#ifdef __STDC__ int tar_endwr(void) -#else -int -tar_endwr() -#endif { return(wr_skip((off_t)(NULLCNT*BLKMULT))); } @@ -101,13 +100,8 @@ tar_endwr() * size of trailer (2 * BLKMULT) */ -#ifdef __STDC__ off_t tar_endrd(void) -#else -off_t -tar_endrd() -#endif { return((off_t)(NULLCNT*BLKMULT)); } @@ -123,18 +117,10 @@ tar_endrd() * could never contain a header. */ -#ifdef __STDC__ -int -tar_trail(register char *buf, register int in_resync, register int *cnt) -#else int -tar_trail(buf, in_resync, cnt) - register char *buf; - register int in_resync; - register int *cnt; -#endif +tar_trail(ARCHD *ignore, char *buf, int in_resync, int *cnt) { - register int i; + int i; /* * look for all zero, trailer is two consecutive blocks of zero @@ -174,25 +160,16 @@ tar_trail(buf, in_resync, cnt) * 0 if the number fit into the string, -1 otherwise */ -#ifdef __STDC__ -static int -ul_oct(u_long val, register char *str, register int len, int term) -#else static int -ul_oct(val, str, len, term) - u_long val; - register char *str; - register int len; - int term; -#endif +ul_oct(u_long val, char *str, int len, int term) { - register char *pt; + char *pt; /* * term selects the appropriate character(s) for the end of the string */ pt = str + len - 1; - switch(term) { + switch (term) { case 3: *pt-- = '\0'; break; @@ -226,7 +203,7 @@ ul_oct(val, str, len, term) return(0); } -#ifndef NET2_STAT +#ifndef LONG_OFF_T /* * uqd_oct() * convert an u_quad_t to an octal string. one of many oddball field @@ -238,25 +215,16 @@ ul_oct(val, str, len, term) * 0 if the number fit into the string, -1 otherwise */ -#ifdef __STDC__ -static int -uqd_oct(u_quad_t val, register char *str, register int len, int term) -#else static int -uqd_oct(val, str, len, term) - u_quad_t val; - register char *str; - register int len; - int term; -#endif +uqd_oct(u_quad_t val, char *str, int len, int term) { - register char *pt; + char *pt; /* * term selects the appropriate character(s) for the end of the string */ pt = str + len - 1; - switch(term) { + switch (term) { case 3: *pt-- = '\0'; break; @@ -294,26 +262,19 @@ uqd_oct(val, str, len, term) /* * tar_chksm() * calculate the checksum for a tar block counting the checksum field as - * all blanks (BLNKSUM is that value pre-calculated, the sume of 8 blanks). + * all blanks (BLNKSUM is that value pre-calculated, the sum of 8 blanks). * NOTE: we use len to short circuit summing 0's on write since we ALWAYS * pad headers with 0. * Return: * unsigned long checksum */ -#ifdef __STDC__ static u_long -tar_chksm(register char *blk, register int len) -#else -static u_long -tar_chksm(blk, len) - register char *blk; - register int len; -#endif +tar_chksm(char *blk, int len) { - register char *stop; - register char *pt; - u_long chksm = BLNKSUM; /* inital value is checksum field sum */ + char *stop; + char *pt; + u_long chksm = BLNKSUM; /* initial value is checksum field sum */ /* * add the part of the block before the checksum field @@ -349,18 +310,11 @@ tar_chksm(blk, len) * 0 if a tar header, -1 otherwise */ -#ifdef __STDC__ int -tar_id(register char *blk, int size) -#else -int -tar_id(blk, size) - register char *blk; - int size; -#endif +tar_id(char *blk, int size) { - register HD_TAR *hd; - register HD_USTAR *uhd; + HD_TAR *hd; + HD_USTAR *uhd; if (size < BLKMULT) return(-1); @@ -380,6 +334,7 @@ tar_id(blk, size) return(-1); if (asc_ul(hd->chksum,sizeof(hd->chksum),OCT) != tar_chksm(blk,BLKMULT)) return(-1); + force_one_volume = 1; return(0); } @@ -390,13 +345,8 @@ tar_id(blk, size) * 0 if ok -1 otherwise */ -#ifdef __STDC__ int tar_opt(void) -#else -int -tar_opt() -#endif { OPLIST *opt; @@ -432,39 +382,40 @@ tar_opt() * 0 */ -#ifdef __STDC__ int -tar_rd(register ARCHD *arcn, register char *buf) -#else -int -tar_rd(arcn, buf) - register ARCHD *arcn; - register char *buf; -#endif +tar_rd(ARCHD *arcn, char *buf) { - register HD_TAR *hd; - register char *pt; + HD_TAR *hd; + char *pt; /* * we only get proper sized buffers passed to us */ if (tar_id(buf, BLKMULT) < 0) return(-1); + memset(arcn, 0, sizeof(*arcn)); arcn->org_name = arcn->name; arcn->sb.st_nlink = 1; - arcn->pat = NULL; /* * copy out the name and values in the stat buffer */ hd = (HD_TAR *)buf; - arcn->nlen = l_strncpy(arcn->name, hd->name, sizeof(arcn->name) - 1); - arcn->name[arcn->nlen] = '\0'; + if (hd->linkflag != LONGLINKTYPE && hd->linkflag != LONGNAMETYPE) { + arcn->nlen = expandname(arcn->name, sizeof(arcn->name), + &gnu_name_string, hd->name, sizeof(hd->name)); + arcn->ln_nlen = expandname(arcn->ln_name, sizeof(arcn->ln_name), + &gnu_link_string, hd->linkname, sizeof(hd->linkname)); + } arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode,sizeof(hd->mode),OCT) & 0xfff); arcn->sb.st_uid = (uid_t)asc_ul(hd->uid, sizeof(hd->uid), OCT); arcn->sb.st_gid = (gid_t)asc_ul(hd->gid, sizeof(hd->gid), OCT); - arcn->sb.st_size = (size_t)asc_ul(hd->size, sizeof(hd->size), OCT); +#ifdef LONG_OFF_T + arcn->sb.st_size = (off_t)asc_ul(hd->size, sizeof(hd->size), OCT); +#else + arcn->sb.st_size = (off_t)asc_uqd(hd->size, sizeof(hd->size), OCT); +#endif arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT); arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime; @@ -475,16 +426,13 @@ tar_rd(arcn, buf) pt = &(arcn->name[arcn->nlen - 1]); arcn->pad = 0; arcn->skip = 0; - switch(hd->linkflag) { + switch (hd->linkflag) { case SYMTYPE: /* * symbolic link, need to get the link name and set the type in * the st_mode so -v printing will look correct. */ arcn->type = PAX_SLK; - arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname, - sizeof(arcn->ln_name) - 1); - arcn->ln_name[arcn->ln_nlen] = '\0'; arcn->sb.st_mode |= S_IFLNK; break; case LNKTYPE: @@ -494,9 +442,6 @@ tar_rd(arcn, buf) */ arcn->type = PAX_HLK; arcn->sb.st_nlink = 2; - arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname, - sizeof(arcn->ln_name) - 1); - arcn->ln_name[arcn->ln_nlen] = '\0'; /* * no idea of what type this thing really points at, but @@ -504,6 +449,17 @@ tar_rd(arcn, buf) */ arcn->sb.st_mode |= S_IFREG; break; + case LONGLINKTYPE: + case LONGNAMETYPE: + /* + * GNU long link/file; we tag these here and let the + * pax internals deal with it -- too ugly otherwise. + */ + arcn->type = + hd->linkflag == LONGLINKTYPE ? PAX_GLL : PAX_GLF; + arcn->pad = TAR_PAD(arcn->sb.st_size); + arcn->skip = arcn->sb.st_size; + break; case DIRTYPE: /* * It is a directory, set the mode for -v printing @@ -511,8 +467,6 @@ tar_rd(arcn, buf) arcn->type = PAX_DIR; arcn->sb.st_mode |= S_IFDIR; arcn->sb.st_nlink = 2; - arcn->ln_name[0] = '\0'; - arcn->ln_nlen = 0; break; case AREGTYPE: case REGTYPE: @@ -532,7 +486,7 @@ tar_rd(arcn, buf) } else { /* * have a file that will be followed by data. Set the - * skip value to the size field and caluculate the size + * skip value to the size field and calculate the size * of the padding. */ arcn->type = PAX_REG; @@ -547,7 +501,7 @@ tar_rd(arcn, buf) * strip off any trailing slash. */ if (*pt == '/') { - *pt = '\0'; + *pt = '\0'; --arcn->nlen; } return(0); @@ -565,23 +519,17 @@ tar_rd(arcn, buf) * data to write after the header, -1 if archive write failed */ -#ifdef __STDC__ int -tar_wr(register ARCHD *arcn) -#else -int -tar_wr(arcn) - register ARCHD *arcn; -#endif +tar_wr(ARCHD *arcn) { - register HD_TAR *hd; + HD_TAR *hd; int len; char hdblk[sizeof(HD_TAR)]; /* * check for those file system types which tar cannot store */ - switch(arcn->type) { + switch (arcn->type) { case PAX_DIR: /* * user asked that dirs not be written to the archive @@ -606,7 +554,8 @@ tar_wr(arcn) case PAX_HLK: case PAX_HRG: if (arcn->ln_nlen > sizeof(hd->linkname)) { - paxwarn(1,"Link name too long for tar %s", arcn->ln_name); + paxwarn(1, "Link name too long for tar %s", + arcn->ln_name); return(1); } break; @@ -622,32 +571,31 @@ tar_wr(arcn) len = arcn->nlen; if (arcn->type == PAX_DIR) ++len; - if (len >= sizeof(hd->name)) { + if (len > sizeof(hd->name)) { paxwarn(1, "File name too long for tar %s", arcn->name); return(1); } /* - * copy the data out of the ARCHD into the tar header based on the type - * of the file. Remember many tar readers want the unused fields to be - * padded with zero. We set the linkflag field (type), the linkname - * (or zero if not used),the size, and set the padding (if any) to be - * added after the file data (0 for all other types, as they only have - * a header) + * Copy the data out of the ARCHD into the tar header based on the type + * of the file. Remember, many tar readers want all fields to be + * padded with zero so we zero the header first. We then set the + * linkflag field (type), the linkname, the size, and set the padding + * (if any) to be added after the file data (0 for all other types, + * as they only have a header). */ + memset(hdblk, 0, sizeof(hdblk)); hd = (HD_TAR *)hdblk; - l_strncpy(hd->name, arcn->name, sizeof(hd->name) - 1); - hd->name[sizeof(hd->name) - 1] = '\0'; + fieldcpy(hd->name, sizeof(hd->name), arcn->name, sizeof(arcn->name)); arcn->pad = 0; if (arcn->type == PAX_DIR) { /* * directories are the same as files, except have a filename - * that ends with a /, we add the slash here. No data follows, + * that ends with a /, we add the slash here. No data follows * dirs, so no pad. */ hd->linkflag = AREGTYPE; - memset(hd->linkname, 0, sizeof(hd->linkname)); hd->name[len-1] = '/'; if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1)) goto out; @@ -656,8 +604,8 @@ tar_wr(arcn) * no data follows this file, so no pad */ hd->linkflag = SYMTYPE; - l_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname) - 1); - hd->linkname[sizeof(hd->linkname) - 1] = '\0'; + fieldcpy(hd->linkname, sizeof(hd->linkname), arcn->ln_name, + sizeof(arcn->ln_name)); if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1)) goto out; } else if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG)) { @@ -665,8 +613,8 @@ tar_wr(arcn) * no data follows this file, so no pad */ hd->linkflag = LNKTYPE; - l_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname) - 1); - hd->linkname[sizeof(hd->linkname) - 1] = '\0'; + fieldcpy(hd->linkname, sizeof(hd->linkname), arcn->ln_name, + sizeof(arcn->ln_name)); if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1)) goto out; } else { @@ -674,8 +622,7 @@ tar_wr(arcn) * data follows this file, so set the pad */ hd->linkflag = AREGTYPE; - memset(hd->linkname, 0, sizeof(hd->linkname)); -# ifdef NET2_STAT +# ifdef LONG_OFF_T if (ul_oct((u_long)arcn->sb.st_size, hd->size, sizeof(hd->size), 1)) { # else @@ -694,7 +641,7 @@ tar_wr(arcn) if (ul_oct((u_long)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 0) || ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 0) || ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 0) || - ul_oct((u_long)arcn->sb.st_mtime, hd->mtime, sizeof(hd->mtime), 1)) + ul_oct((u_long)(u_int)arcn->sb.st_mtime, hd->mtime, sizeof(hd->mtime), 1)) goto out; /* @@ -732,13 +679,8 @@ tar_wr(arcn) * 0 if ok, -1 otherwise */ -#ifdef __STDC__ int ustar_strd(void) -#else -int -ustar_strd() -#endif { if ((usrtb_start() < 0) || (grptb_start() < 0)) return(-1); @@ -752,13 +694,8 @@ ustar_strd() * 0 if ok, -1 otherwise */ -#ifdef __STDC__ int ustar_stwr(void) -#else -int -ustar_stwr() -#endif { if ((uidtb_start() < 0) || (gidtb_start() < 0)) return(-1); @@ -773,17 +710,10 @@ ustar_stwr() * 0 if a ustar header, -1 otherwise */ -#ifdef __STDC__ int ustar_id(char *blk, int size) -#else -int -ustar_id(blk, size) - char *blk; - int size; -#endif { - register HD_USTAR *hd; + HD_USTAR *hd; if (size < BLKMULT) return(-1); @@ -795,7 +725,7 @@ ustar_id(blk, size) * programs are fouled up and create archives missing the \0. Last we * check the checksum. If ok we have to assume it is a valid header. */ - if (hd->name[0] == '\0') + if (hd->prefix[0] == '\0' && hd->name[0] == '\0') return(-1); if (strncmp(hd->magic, TMAGIC, TMAGLEN - 1) != 0) return(-1); @@ -812,19 +742,12 @@ ustar_id(blk, size) * 0 */ -#ifdef __STDC__ int -ustar_rd(register ARCHD *arcn, register char *buf) -#else -int -ustar_rd(arcn, buf) - register ARCHD *arcn; - register char *buf; -#endif +ustar_rd(ARCHD *arcn, char *buf) { - register HD_USTAR *hd; - register char *dest; - register int cnt = 0; + HD_USTAR *hd; + char *dest; + int cnt = 0; dev_t devmajor; dev_t devminor; @@ -833,10 +756,9 @@ ustar_rd(arcn, buf) */ if (ustar_id(buf, BLKMULT) < 0) return(-1); + memset(arcn, 0, sizeof(*arcn)); arcn->org_name = arcn->name; arcn->sb.st_nlink = 1; - arcn->pat = NULL; - arcn->nlen = 0; hd = (HD_USTAR *)buf; /* @@ -851,13 +773,21 @@ ustar_rd(arcn, buf) */ dest = arcn->name; if (*(hd->prefix) != '\0') { - cnt = l_strncpy(dest, hd->prefix, sizeof(hd->prefix)); + cnt = fieldcpy(dest, sizeof(arcn->name) - 1, hd->prefix, + sizeof(hd->prefix)); dest += cnt; *dest++ = '/'; cnt++; + } else { + cnt = 0; + } + + if (hd->typeflag != LONGLINKTYPE && hd->typeflag != LONGNAMETYPE) { + arcn->nlen = cnt + expandname(dest, sizeof(arcn->name) - cnt, + &gnu_name_string, hd->name, sizeof(hd->name)); + arcn->ln_nlen = expandname(arcn->ln_name, sizeof(arcn->ln_name), + &gnu_link_string, hd->linkname, sizeof(hd->linkname)); } - arcn->nlen = cnt + l_strncpy(dest, hd->name, sizeof(hd->name)); - arcn->name[arcn->nlen] = '\0'; /* * follow the spec to the letter. we should only have mode bits, strip @@ -865,7 +795,11 @@ ustar_rd(arcn, buf) */ arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode, sizeof(hd->mode), OCT) & 0xfff); - arcn->sb.st_size = (size_t)asc_ul(hd->size, sizeof(hd->size), OCT); +#ifdef LONG_OFF_T + arcn->sb.st_size = (off_t)asc_ul(hd->size, sizeof(hd->size), OCT); +#else + arcn->sb.st_size = (off_t)asc_uqd(hd->size, sizeof(hd->size), OCT); +#endif arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT); arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime; @@ -885,8 +819,6 @@ ustar_rd(arcn, buf) /* * set the defaults, these may be changed depending on the file type */ - arcn->ln_name[0] = '\0'; - arcn->ln_nlen = 0; arcn->pad = 0; arcn->skip = 0; arcn->sb.st_rdev = (dev_t)0; @@ -894,7 +826,7 @@ ustar_rd(arcn, buf) /* * set the mode and PAX type according to the typeflag in the header */ - switch(hd->typeflag) { + switch (hd->typeflag) { case FIFOTYPE: arcn->type = PAX_FIF; arcn->sb.st_mode |= S_IFIFO; @@ -941,15 +873,17 @@ ustar_rd(arcn, buf) arcn->sb.st_mode |= S_IFREG; arcn->sb.st_nlink = 2; } + break; + case LONGLINKTYPE: + case LONGNAMETYPE: /* - * copy the link name - * - * see comment above (for hd->name) regarding the length - * passed to l_strncpy + * GNU long link/file; we tag these here and let the + * pax internals deal with it -- too ugly otherwise. */ - arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname, - sizeof(hd->linkname)); - arcn->ln_name[arcn->ln_nlen] = '\0'; + arcn->type = + hd->typeflag == LONGLINKTYPE ? PAX_GLL : PAX_GLF; + arcn->pad = TAR_PAD(arcn->sb.st_size); + arcn->skip = arcn->sb.st_size; break; case CONTTYPE: case AREGTYPE: @@ -980,17 +914,11 @@ ustar_rd(arcn, buf) * data to write after the header, -1 if archive write failed */ -#ifdef __STDC__ int -ustar_wr(register ARCHD *arcn) -#else -int -ustar_wr(arcn) - register ARCHD *arcn; -#endif +ustar_wr(ARCHD *arcn) { - register HD_USTAR *hd; - register char *pt; + HD_USTAR *hd; + char *pt; char hdblk[sizeof(HD_USTAR)]; /* @@ -1018,6 +946,11 @@ ustar_wr(arcn) paxwarn(1, "File name too long for ustar %s", arcn->name); return(1); } + + /* + * zero out the header so we don't have to worry about zero fill below + */ + memset(hdblk, 0, sizeof(hdblk)); hd = (HD_USTAR *)hdblk; arcn->pad = 0L; @@ -1030,28 +963,24 @@ ustar_wr(arcn) * occur, we remove the / and copy the first part to the prefix */ *pt = '\0'; - l_strncpy(hd->prefix, arcn->name, sizeof(hd->prefix)); + fieldcpy(hd->prefix, sizeof(hd->prefix), arcn->name, + sizeof(arcn->name)); *pt++ = '/'; - } else - memset(hd->prefix, 0, sizeof(hd->prefix)); + } /* * copy the name part. this may be the whole path or the part after * the prefix */ - l_strncpy(hd->name, pt, sizeof(hd->name)); + fieldcpy(hd->name, sizeof(hd->name), pt, + sizeof(arcn->name) - (pt - arcn->name)); /* * set the fields in the header that are type dependent */ - switch(arcn->type) { + switch (arcn->type) { case PAX_DIR: hd->typeflag = DIRTYPE; - memset(hd->linkname, 0, sizeof(hd->linkname)); - memset(hd->devmajor, 0, sizeof(hd->devmajor)); - hd->devmajor[0] = '0'; - memset(hd->devminor, 0, sizeof(hd->devminor)); - hd->devminor[0] = '0'; if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3)) goto out; break; @@ -1061,7 +990,6 @@ ustar_wr(arcn) hd->typeflag = CHRTYPE; else hd->typeflag = BLKTYPE; - memset(hd->linkname, 0, sizeof(hd->linkname)); if (ul_oct((u_long)MAJOR(arcn->sb.st_rdev), hd->devmajor, sizeof(hd->devmajor), 3) || ul_oct((u_long)MINOR(arcn->sb.st_rdev), hd->devminor, @@ -1071,11 +999,6 @@ ustar_wr(arcn) break; case PAX_FIF: hd->typeflag = FIFOTYPE; - memset(hd->linkname, 0, sizeof(hd->linkname)); - memset(hd->devmajor, 0, sizeof(hd->devmajor)); - hd->devmajor[0] = '0'; - memset(hd->devminor, 0, sizeof(hd->devminor)); - hd->devminor[0] = '0'; if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3)) goto out; break; @@ -1086,11 +1009,8 @@ ustar_wr(arcn) hd->typeflag = SYMTYPE; else hd->typeflag = LNKTYPE; - l_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname)); - memset(hd->devmajor, 0, sizeof(hd->devmajor)); - hd->devmajor[0] = '0'; - memset(hd->devminor, 0, sizeof(hd->devminor)); - hd->devminor[0] = '0'; + fieldcpy(hd->linkname, sizeof(hd->linkname), arcn->ln_name, + sizeof(arcn->ln_name)); if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3)) goto out; break; @@ -1104,13 +1024,8 @@ ustar_wr(arcn) hd->typeflag = CONTTYPE; else hd->typeflag = REGTYPE; - memset(hd->linkname, 0, sizeof(hd->linkname)); - memset(hd->devmajor, 0, sizeof(hd->devmajor)); - hd->devmajor[0] = '0'; - memset(hd->devminor, 0, sizeof(hd->devminor)); - hd->devminor[0] = '0'; arcn->pad = TAR_PAD(arcn->sb.st_size); -# ifdef NET2_STAT +# ifdef LONG_OFF_T if (ul_oct((u_long)arcn->sb.st_size, hd->size, sizeof(hd->size), 3)) { # else @@ -1123,20 +1038,46 @@ ustar_wr(arcn) break; } - l_strncpy(hd->magic, TMAGIC, TMAGLEN); - l_strncpy(hd->version, TVERSION, TVERSLEN); + strncpy(hd->magic, TMAGIC, TMAGLEN); + strncpy(hd->version, TVERSION, TVERSLEN); /* * set the remaining fields. Some versions want all 16 bits of mode * we better humor them (they really do not meet spec though).... */ + if (ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 3)) { + if (uid_nobody == 0) { + if (uid_name("nobody", &uid_nobody) == -1) + goto out; + } + if (uid_warn != arcn->sb.st_uid) { + uid_warn = arcn->sb.st_uid; + paxwarn(1, + "Ustar header field is too small for uid %lu, " + "using nobody", (u_long)arcn->sb.st_uid); + } + if (ul_oct((u_long)uid_nobody, hd->uid, sizeof(hd->uid), 3)) + goto out; + } + if (ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 3)) { + if (gid_nobody == 0) { + if (gid_name("nobody", &gid_nobody) == -1) + goto out; + } + if (gid_warn != arcn->sb.st_gid) { + gid_warn = arcn->sb.st_gid; + paxwarn(1, + "Ustar header field is too small for gid %lu, " + "using nobody", (u_long)arcn->sb.st_gid); + } + if (ul_oct((u_long)gid_nobody, hd->gid, sizeof(hd->gid), 3)) + goto out; + } if (ul_oct((u_long)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 3) || - ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 3) || - ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 3) || - ul_oct((u_long)arcn->sb.st_mtime,hd->mtime,sizeof(hd->mtime),3)) + ul_oct((u_long)(u_int)arcn->sb.st_mtime,hd->mtime,sizeof(hd->mtime),3)) goto out; - l_strncpy(hd->uname,name_uid(arcn->sb.st_uid, 0),sizeof(hd->uname)); - l_strncpy(hd->gname,name_gid(arcn->sb.st_gid, 0),sizeof(hd->gname)); + strncpy(hd->uname, name_uid(arcn->sb.st_uid, 0), sizeof(hd->uname)); + strncpy(hd->gname, name_gid(arcn->sb.st_gid, 0), sizeof(hd->gname)); /* * calculate and store the checksum write the header to the archive @@ -1155,7 +1096,7 @@ ustar_wr(arcn) return(1); out: - /* + /* * header field is out of range */ paxwarn(1, "Ustar header field is too small for %s", arcn->org_name); @@ -1174,21 +1115,16 @@ ustar_wr(arcn) * the file name is too long */ -#ifdef __STDC__ -static char * -name_split(register char *name, register int len) -#else static char * -name_split(name, len) - register char *name; - register int len; -#endif +name_split(char *name, int len) { - register char *start; + char *start; /* * check to see if the file name is small enough to fit in the name * field. if so just return a pointer to the name. + * The strings can fill the complete name and prefix fields + * without a NUL terminator. */ if (len <= TNMSZ) return(name); @@ -1197,7 +1133,7 @@ name_split(name, len) /* * we start looking at the biggest sized piece that fits in the name - * field. We walk foward looking for a slash to split at. The idea is + * field. We walk forward looking for a slash to split at. The idea is * to find the biggest piece to fit in the name field (or the smallest * prefix we can find) (the -1 is correct the biggest piece would * include the slash between the two parts that gets thrown away) @@ -1228,3 +1164,20 @@ name_split(name, len) */ return(start); } + +static size_t +expandname(char *buf, size_t len, char **gnu_name, const char *name, + size_t limit) +{ + size_t nlen; + + if (*gnu_name) { + /* *gnu_name is NUL terminated */ + if ((nlen = strlcpy(buf, *gnu_name, len)) >= len) + nlen = len - 1; + free(*gnu_name); + *gnu_name = NULL; + } else + nlen = fieldcpy(buf, len, name, limit); + return(nlen); +}