---
tar.c | 44 ++++++++++++++++++++++++++++++++++----------
1 file changed, 34 insertions(+), 10 deletions(-)
diff --git a/tar.c b/tar.c
index 934b9c6..ee75e6c 100644
--- a/tar.c
+++ b/tar.c
_AT_@ -30,7 +30,8 @@ enum Type {
BLOCKDEV = '4',
DIRECTORY = '5',
FIFO = '6',
- RESERVED = '7'
+ RESERVED = '7',
+ LONGNAME = 'L',
};
struct header {
_AT_@ -449,15 +450,15 @@ xt(int argc, char *argv[], int mode)
struct timespec times[2];
struct header *h = (struct header *)b;
struct dirtime *dirtime;
- long size;
- int i, n;
+ long n, size;
+ int i;
int (*fn)(char *, ssize_t, char[BLKSIZ]) = (mode == 'x') ? unarchive : print;
long fnmax = 256 + 1;
char *fname = ecalloc(1, fnmax);
while (eread(tarfd, b, BLKSIZ) > 0 && h->name[0]) {
chktar(h);
- sanitize(h), n = 0;
+ sanitize(h);
if ((size = strtol(h->size, &p, 8)) < 0 || *p != '\0')
eprintf("strtol %s: invalid number\n", h->size);
_AT_@ -468,14 +469,35 @@ xt(int argc, char *argv[], int mode)
case 'x':
skipblk(size);
continue;
+
+ /* GNU tar long filename */
+ case LONGNAME:
+ if (size > fnmax) {
+ fnmax = size;
+ free(fname);
+ fname = ecalloc(1, fnmax);
+ }
+ for (n = 0; n < size; n += BLKSIZ) {
+ if (!(eread(tarfd, b, BLKSIZ) > 0))
+ eprintf("corrupt long filename\n");
+ memcpy(fname + n, b, MIN(size - n, BLKSIZ));
+ }
+ /* the filename must already be NUL-terminated in the archive */
+ if (!size || fname[size-1])
+ eprintf("corrupt long filename\n");
+ continue;
}
- /* small dance around non-null terminated fields */
- if (h->prefix[0])
- n = snprintf(fname, fnmax, "%.*s/",
- (int)sizeof(h->prefix), h->prefix);
- snprintf(fname + n, fnmax - n, "%.*s",
- (int)sizeof(h->name), h->name);
+ /* only read filename if we don't already have a long name queued up */
+ if (!fname[0]) {
+ /* small dance around non-null terminated fields */
+ n = 0;
+ if (h->prefix[0])
+ n = snprintf(fname, fnmax, "%.*s/",
+ (int)sizeof(h->prefix), h->prefix);
+ snprintf(fname + n, fnmax - n, "%.*s",
+ (int)sizeof(h->name), h->name);
+ }
if (argc) {
/* only extract the given files */
_AT_@ -491,6 +513,8 @@ xt(int argc, char *argv[], int mode)
fn(fname, size, b);
if (vflag && mode != 't')
puts(fname);
+
+ fname[0] = 0;
}
free(fname);
--
2.28.0
Received on Thu Nov 26 2020 - 14:53:46 CET
This archive was generated by hypermail 2.3.0 : Thu Nov 26 2020 - 15:00:37 CET