summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2004-03-30 16:14:24 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2004-03-30 16:14:24 +0000
commit0ccf221b83339fcde130008ba0c5306f679fddf7 (patch)
treed619f0544bd01bce245871d86762901bc5fa7a2f
parent1ff124dac8cce67f02084deb53acb2bacc77c7a4 (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.c10
-rw-r--r--bin/pax/buf_subs.c6
-rw-r--r--bin/pax/extern.h3
-rw-r--r--bin/pax/file_subs.c30
-rw-r--r--bin/pax/tar.c80
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);
+}