summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorfgsch <fgsch@openbsd.org>2013-04-09 18:30:34 +0000
committerfgsch <fgsch@openbsd.org>2013-04-09 18:30:34 +0000
commit734dd9a41ea3a0dd876d365aac081d6da7743640 (patch)
tree195827f2695ac8f3a41744595fd8ef321b7f0f5e
parentdo not store a time_t or the result of a time_t division in an int (diff)
downloadwireguard-openbsd-734dd9a41ea3a0dd876d365aac081d6da7743640.tar.xz
wireguard-openbsd-734dd9a41ea3a0dd876d365aac081d6da7743640.zip
Add extended header support for ustar. Currently only path and linkpath are
handled. input from zhuk and guenther. tested by zhuk and sthen on a bulk. ok guenther.
-rw-r--r--bin/pax/tar.c122
-rw-r--r--bin/pax/tar.h8
2 files changed, 112 insertions, 18 deletions
diff --git a/bin/pax/tar.c b/bin/pax/tar.c
index b52a1abb4c5..ec4c809b6ba 100644
--- a/bin/pax/tar.c
+++ b/bin/pax/tar.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tar.c,v 1.45 2013/03/27 17:14:10 zhuk Exp $ */
+/* $OpenBSD: tar.c,v 1.46 2013/04/09 18:30:34 fgsch Exp $ */
/* $NetBSD: tar.c,v 1.5 1995/03/21 09:07:49 cgd Exp $ */
/*-
@@ -37,6 +37,9 @@
#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
@@ -56,6 +59,9 @@ static int ul_oct(u_long, char *, int, int);
#ifndef LONG_OFF_T
static int uqd_oct(u_quad_t, char *, int, int);
#endif
+#ifndef SMALL
+static int rd_xheader(ARCHD *, char *, HD_USTAR **);
+#endif
static uid_t uid_nobody;
static uid_t uid_warn;
@@ -751,24 +757,40 @@ ustar_rd(ARCHD *arcn, char *buf)
arcn->sb.st_nlink = 1;
hd = (HD_USTAR *)buf;
- /*
- * see if the filename is split into two parts. if, so joint the parts.
- * we copy the prefix first and add a / between the prefix and name.
- */
- dest = arcn->name;
- if (*(hd->prefix) != '\0') {
- cnt = fieldcpy(dest, sizeof(arcn->name) - 1, hd->prefix,
- sizeof(hd->prefix));
- dest += cnt;
- *dest++ = '/';
- cnt++;
- } else {
- cnt = 0;
+#ifndef SMALL
+ /* Process the Extended header. */
+ if (hd->typeflag == XHDRTYPE || hd->typeflag == GHDRTYPE) {
+ if (rd_xheader(arcn, buf, &hd) < 0)
+ return (-1);
}
+#endif
- if (hd->typeflag != LONGLINKTYPE && hd->typeflag != LONGNAMETYPE) {
- arcn->nlen = cnt + expandname(dest, sizeof(arcn->name) - cnt,
- &gnu_name_string, hd->name, sizeof(hd->name));
+ if (!arcn->nlen) {
+ /*
+ * See if the filename is split into two parts. if, so join
+ * the parts. We copy the prefix first and add a / between
+ * the prefix and name.
+ */
+ dest = arcn->name;
+ if (*(hd->prefix) != '\0') {
+ 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));
+ }
+ }
+
+ if (!arcn->ln_nlen &&
+ hd->typeflag != LONGLINKTYPE && hd->typeflag != LONGNAMETYPE) {
arcn->ln_nlen = expandname(arcn->ln_name, sizeof(arcn->ln_name),
&gnu_link_string, hd->linkname, sizeof(hd->linkname));
}
@@ -1176,3 +1198,69 @@ expandname(char *buf, size_t len, char **gnu_name, const char *name,
nlen = fieldcpy(buf, len, name, limit);
return(nlen);
}
+
+#ifndef SMALL
+
+#define MINXHDRSZ 6
+
+static int
+rd_xheader(ARCHD *arcn, char *buf, HD_USTAR **hd)
+{
+ off_t len, size;
+ char *delim, *keyword;
+ char *nextp, *p;
+
+ size = (off_t)asc_ul((*hd)->size, sizeof((*hd)->size), OCT);
+ if (size < MINXHDRSZ) {
+ paxwarn(1, "Invalid extended header length");
+ return (-1);
+ }
+ if (rd_wrbuf(buf, size) != size)
+ return (-1);
+ if (rd_skip((off_t)BLKMULT - size) < 0)
+ return (-1);
+
+ for (p = buf; size > 0; size -= len, p = nextp) {
+ if (!isdigit(*p)) {
+ paxwarn(1, "Invalid extended header record");
+ return (-1);
+ }
+ errno = 0;
+ len = strtoll(p, &delim, 10);
+ if (*delim != ' ' || (errno == ERANGE &&
+ (len == LLONG_MIN || len == LLONG_MAX)) ||
+ len < MINXHDRSZ) {
+ paxwarn(1, "Invalid extended header record length");
+ return (-1);
+ }
+ if (len > size) {
+ paxwarn(1, "Extended header record length %j is "
+ "out of range", len);
+ return (-1);
+ }
+ nextp = p + len;
+ keyword = p = delim + 1;
+ p = memchr(p, '=', len);
+ if (!p || nextp[-1] != '\n') {
+ paxwarn(1, "Malformed extended header record");
+ return (-1);
+ }
+ *p++ = nextp[-1] = '\0';
+ if ((*hd)->typeflag == XHDRTYPE) {
+ if (!strcmp(keyword, "path")) {
+ arcn->nlen = strlcpy(arcn->name, p,
+ sizeof(arcn->name));
+ } else if (!strcmp(keyword, "linkpath")) {
+ arcn->ln_nlen = strlcpy(arcn->ln_name, p,
+ sizeof(arcn->ln_name));
+ }
+ }
+ }
+
+ /* Update the ustar header. */
+ if (rd_wrbuf(buf, BLKMULT) != BLKMULT)
+ return (-1);
+ *hd = (HD_USTAR *)buf;
+ return (0);
+}
+#endif
diff --git a/bin/pax/tar.h b/bin/pax/tar.h
index 506ce5818c4..1c0965c2602 100644
--- a/bin/pax/tar.h
+++ b/bin/pax/tar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tar.h,v 1.7 2003/06/02 23:32:09 millert Exp $ */
+/* $OpenBSD: tar.h,v 1.8 2013/04/09 18:30:34 fgsch Exp $ */
/* $NetBSD: tar.h,v 1.3 1995/03/21 09:07:51 cgd Exp $ */
/*-
@@ -62,6 +62,12 @@
#define CONTTYPE '7' /* high perf file */
/*
+ * Extended header - POSIX.1-2001
+ */
+#define XHDRTYPE 'x' /* Extended header */
+#define GHDRTYPE 'g' /* Global header*/
+
+/*
* GNU tar compatibility;
*/
#define LONGLINKTYPE 'K' /* Long Symlink */