diff options
author | 2013-04-09 18:30:34 +0000 | |
---|---|---|
committer | 2013-04-09 18:30:34 +0000 | |
commit | 734dd9a41ea3a0dd876d365aac081d6da7743640 (patch) | |
tree | 195827f2695ac8f3a41744595fd8ef321b7f0f5e | |
parent | do not store a time_t or the result of a time_t division in an int (diff) | |
download | wireguard-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.c | 122 | ||||
-rw-r--r-- | bin/pax/tar.h | 8 |
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 */ |