diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2004-03-30 16:14:24 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2004-03-30 16:14:24 +0000 |
commit | 0ccf221b83339fcde130008ba0c5306f679fddf7 (patch) | |
tree | d619f0544bd01bce245871d86762901bc5fa7a2f | |
parent | 1ff124dac8cce67f02084deb53acb2bacc77c7a4 (diff) |
Add support for expanding GNU long links from NetBSD. I've had this
in my tree for ages but didn't have a proper test case. Thanks to
otto@ for providing one.
-rw-r--r-- | bin/pax/ar_subs.c | 10 | ||||
-rw-r--r-- | bin/pax/buf_subs.c | 6 | ||||
-rw-r--r-- | bin/pax/extern.h | 3 | ||||
-rw-r--r-- | bin/pax/file_subs.c | 30 | ||||
-rw-r--r-- | bin/pax/tar.c | 80 |
5 files changed, 71 insertions, 58 deletions
diff --git a/bin/pax/ar_subs.c b/bin/pax/ar_subs.c index d2d92c4c31c..10add9e75a2 100644 --- a/bin/pax/ar_subs.c +++ b/bin/pax/ar_subs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ar_subs.c,v 1.26 2004/03/15 22:18:15 djm Exp $ */ +/* $OpenBSD: ar_subs.c,v 1.27 2004/03/30 16:14:22 millert Exp $ */ /* $NetBSD: ar_subs.c,v 1.5 1995/03/21 09:07:06 cgd Exp $ */ /*- @@ -38,7 +38,7 @@ #if 0 static const char sccsid[] = "@(#)ar_subs.c 8.2 (Berkeley) 4/18/94"; #else -static const char rcsid[] = "$OpenBSD: ar_subs.c,v 1.26 2004/03/15 22:18:15 djm Exp $"; +static const char rcsid[] = "$OpenBSD: ar_subs.c,v 1.27 2004/03/30 16:14:22 millert Exp $"; #endif #endif /* not lint */ @@ -109,7 +109,8 @@ list(void) * we need to read, to get the real filename */ off_t cnt; - if (!(*frmt->rd_data)(arcn, -1, &cnt)) + if (!(*frmt->rd_data)(arcn, arcn->type == PAX_GLF + ? -1 : -2, &cnt)) (void)rd_skip(cnt + arcn->pad); continue; } @@ -201,7 +202,8 @@ extract(void) /* * we need to read, to get the real filename */ - if (!(*frmt->rd_data)(arcn, -1, &cnt)) + if (!(*frmt->rd_data)(arcn, arcn->type == PAX_GLF + ? -1 : -2, &cnt)) (void)rd_skip(cnt + arcn->pad); continue; } diff --git a/bin/pax/buf_subs.c b/bin/pax/buf_subs.c index ab8794e9d96..930566a9e6b 100644 --- a/bin/pax/buf_subs.c +++ b/bin/pax/buf_subs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: buf_subs.c,v 1.18 2003/10/20 06:22:27 jmc Exp $ */ +/* $OpenBSD: buf_subs.c,v 1.19 2004/03/30 16:14:22 millert Exp $ */ /* $NetBSD: buf_subs.c,v 1.5 1995/03/21 09:07:08 cgd Exp $ */ /*- @@ -38,7 +38,7 @@ #if 0 static const char sccsid[] = "@(#)buf_subs.c 8.2 (Berkeley) 4/18/94"; #else -static const char rcsid[] = "$OpenBSD: buf_subs.c,v 1.18 2003/10/20 06:22:27 jmc Exp $"; +static const char rcsid[] = "$OpenBSD: buf_subs.c,v 1.19 2004/03/30 16:14:22 millert Exp $"; #endif #endif /* not lint */ @@ -683,7 +683,7 @@ rd_wrfile(ARCHD *arcn, int ofd, off_t *left) * pass the blocksize of the file being written to the write routine, * if the size is zero, use the default MINFBSZ */ - if (ofd == -1) + if (ofd < 0) sz = PAXPATHLEN + 1; /* GNU tar long link/file */ else if (fstat(ofd, &sb) == 0) { if (sb.st_blksize > 0) diff --git a/bin/pax/extern.h b/bin/pax/extern.h index f8632177e07..a05050a9cf1 100644 --- a/bin/pax/extern.h +++ b/bin/pax/extern.h @@ -1,4 +1,4 @@ -/* $OpenBSD: extern.h,v 1.27 2003/06/26 00:10:17 deraadt Exp $ */ +/* $OpenBSD: extern.h,v 1.28 2004/03/30 16:14:22 millert Exp $ */ /* $NetBSD: extern.h,v 1.5 1996/03/26 23:54:16 mrg Exp $ */ /*- @@ -135,6 +135,7 @@ int bcpio_wr(ARCHD *); /* * file_subs.c */ +extern char *gnu_name_string, *gnu_link_string; int file_creat(ARCHD *); void file_close(ARCHD *, int); int lnk_creat(ARCHD *); diff --git a/bin/pax/file_subs.c b/bin/pax/file_subs.c index f1765f0f5c2..75314e6e913 100644 --- a/bin/pax/file_subs.c +++ b/bin/pax/file_subs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: file_subs.c,v 1.25 2003/10/20 06:22:27 jmc Exp $ */ +/* $OpenBSD: file_subs.c,v 1.26 2004/03/30 16:14:22 millert Exp $ */ /* $NetBSD: file_subs.c,v 1.4 1995/03/21 09:07:18 cgd Exp $ */ /*- @@ -38,7 +38,7 @@ #if 0 static const char sccsid[] = "@(#)file_subs.c 8.1 (Berkeley) 5/31/93"; #else -static const char rcsid[] = "$OpenBSD: file_subs.c,v 1.25 2003/10/20 06:22:27 jmc Exp $"; +static const char rcsid[] = "$OpenBSD: file_subs.c,v 1.26 2004/03/30 16:14:22 millert Exp $"; #endif #endif /* not lint */ @@ -814,6 +814,7 @@ file_write(int fd, char *str, int cnt, int *rem, int *isempt, int sz, char *end; int wcnt; char *st = str; + char **strp; /* * while we have data to process @@ -872,17 +873,28 @@ file_write(int fd, char *str, int cnt, int *rem, int *isempt, int sz, /* * have non-zero data in this file system block, have to write */ - if (fd == -1) { - /* GNU hack */ - if (gnu_hack_string) + switch (fd) { + case -1: + strp = &gnu_name_string; + break; + case -2: + strp = &gnu_link_string; + break; + default: + strp = NULL; + break; + } + if (strp) { + if (*strp) err(1, "WARNING! Major Internal Error! GNU hack Failing!"); - gnu_hack_string = malloc(wcnt + 1); - if (gnu_hack_string == NULL) { + *strp = malloc(wcnt + 1); + if (*strp == NULL) { paxwarn(1, "Out of memory"); return(-1); } - memcpy(gnu_hack_string, st, wcnt); - gnu_hack_string[wcnt] = '\0'; + memcpy(*strp, st, wcnt); + (*strp)[wcnt] = '\0'; + break; } else if (write(fd, st, wcnt) != wcnt) { syswarn(1, errno, "Failed write to file %s", name); return(-1); diff --git a/bin/pax/tar.c b/bin/pax/tar.c index b8b4eb3662c..e4005788794 100644 --- a/bin/pax/tar.c +++ b/bin/pax/tar.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tar.c,v 1.31 2003/06/26 00:10:18 deraadt Exp $ */ +/* $OpenBSD: tar.c,v 1.32 2004/03/30 16:14:23 millert Exp $ */ /* $NetBSD: tar.c,v 1.5 1995/03/21 09:07:49 cgd Exp $ */ /*- @@ -38,7 +38,7 @@ #if 0 static const char sccsid[] = "@(#)tar.c 8.2 (Berkeley) 4/18/94"; #else -static const char rcsid[] = "$OpenBSD: tar.c,v 1.31 2003/06/26 00:10:18 deraadt Exp $"; +static const char rcsid[] = "$OpenBSD: tar.c,v 1.32 2004/03/30 16:14:23 millert Exp $"; #endif #endif /* not lint */ @@ -58,6 +58,7 @@ static const char rcsid[] = "$OpenBSD: tar.c,v 1.31 2003/06/26 00:10:18 deraadt * Routines for reading, writing and header identify of various versions of tar */ +static size_t expandname(char *, size_t, char **, const char *); static u_long tar_chksm(char *, int); static char *name_split(char *, int); static int ul_oct(u_long, char *, int, int); @@ -70,7 +71,8 @@ static int uqd_oct(u_quad_t, char *, int, int); */ static int tar_nodir; /* do not write dirs under old tar */ -char *gnu_hack_string; /* GNU ././@LongLink hackery */ +char *gnu_name_string; /* GNU ././@LongLink hackery name */ +char *gnu_link_string; /* GNU ././@LongLink hackery link */ /* * tar_endwr() @@ -385,21 +387,19 @@ tar_rd(ARCHD *arcn, char *buf) */ 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; - if (gnu_hack_string) { - arcn->nlen = strlcpy(arcn->name, gnu_hack_string, - sizeof(arcn->name)); - free(gnu_hack_string); - gnu_hack_string = NULL; - } else { - arcn->nlen = strlcpy(arcn->name, hd->name, sizeof(arcn->name)); + if (hd->linkflag != LONGLINKTYPE && hd->linkflag != LONGNAMETYPE) { + arcn->nlen = expandname(arcn->name, sizeof(arcn->name), + &gnu_name_string, hd->name); + arcn->ln_nlen = expandname(arcn->ln_name, sizeof(arcn->ln_name), + &gnu_link_string, hd->linkname); } arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode,sizeof(hd->mode),OCT) & 0xfff); @@ -427,8 +427,6 @@ tar_rd(ARCHD *arcn, char *buf) * the st_mode so -v printing will look correct. */ arcn->type = PAX_SLK; - arcn->ln_nlen = strlcpy(arcn->ln_name, hd->linkname, - sizeof(arcn->ln_name)); arcn->sb.st_mode |= S_IFLNK; break; case LNKTYPE: @@ -438,8 +436,6 @@ tar_rd(ARCHD *arcn, char *buf) */ arcn->type = PAX_HLK; arcn->sb.st_nlink = 2; - arcn->ln_nlen = strlcpy(arcn->ln_name, hd->linkname, - sizeof(arcn->ln_name)); /* * no idea of what type this thing really points at, but @@ -448,19 +444,15 @@ tar_rd(ARCHD *arcn, char *buf) arcn->sb.st_mode |= S_IFREG; break; case LONGLINKTYPE: - arcn->type = PAX_GLL; - /* FALLTHROUGH */ case LONGNAMETYPE: /* * GNU long link/file; we tag these here and let the * pax internals deal with it -- too ugly otherwise. */ - if (hd->linkflag != LONGLINKTYPE) - arcn->type = PAX_GLF; + arcn->type = + hd->linkflag == LONGLINKTYPE ? PAX_GLL : PAX_GLF; arcn->pad = TAR_PAD(arcn->sb.st_size); arcn->skip = arcn->sb.st_size; - arcn->ln_name[0] = '\0'; - arcn->ln_nlen = 0; break; case DIRTYPE: /* @@ -469,8 +461,6 @@ tar_rd(ARCHD *arcn, char *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: @@ -757,10 +747,9 @@ ustar_rd(ARCHD *arcn, char *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; /* @@ -773,14 +762,15 @@ ustar_rd(ARCHD *arcn, char *buf) dest += cnt; *dest++ = '/'; cnt++; - } - if (gnu_hack_string) { - arcn->nlen = strlcpy(dest, gnu_hack_string, - sizeof(arcn->name) - cnt); - free(gnu_hack_string); - gnu_hack_string = NULL; } else { - arcn->nlen = strlcpy(dest, hd->name, sizeof(arcn->name) - cnt); + cnt = 0; + } + + if (hd->typeflag != LONGLINKTYPE && hd->typeflag != LONGNAMETYPE) { + arcn->nlen = expandname(dest, sizeof(arcn->name) - cnt, + &gnu_name_string, hd->name); + arcn->ln_nlen = expandname(arcn->ln_name, sizeof(arcn->ln_name), + &gnu_link_string, hd->linkname); } /* @@ -813,8 +803,6 @@ ustar_rd(ARCHD *arcn, char *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; @@ -869,11 +857,6 @@ ustar_rd(ARCHD *arcn, char *buf) arcn->sb.st_mode |= S_IFREG; arcn->sb.st_nlink = 2; } - /* - * copy the link name - */ - arcn->ln_nlen = strlcpy(arcn->ln_name, hd->linkname, - sizeof(arcn->ln_name)); break; case LONGLINKTYPE: case LONGNAMETYPE: @@ -885,8 +868,6 @@ ustar_rd(ARCHD *arcn, char *buf) hd->typeflag == LONGLINKTYPE ? PAX_GLL : PAX_GLF; arcn->pad = TAR_PAD(arcn->sb.st_size); arcn->skip = arcn->sb.st_size; - arcn->ln_name[0] = '\0'; - arcn->ln_nlen = 0; break; case CONTTYPE: case AREGTYPE: @@ -1135,3 +1116,20 @@ name_split(char *name, int len) */ return(start); } + +static size_t +expandname(char *buf, size_t len, char **gnu_name, const char *name) +{ + size_t nlen; + + if (*gnu_name) { + if ((nlen = strlcpy(buf, *gnu_name, len)) >= len) + nlen = len - 1; + free(*gnu_name); + *gnu_name = NULL; + } else { + if ((nlen = strlcpy(buf, name, len)) >= len) + nlen = len - 1; + } + return(nlen); +} |