--- tar.1 | 15 +++++++++++---- tar.c | 42 +++++++++++++++++++++++------------------- 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/tar.1 b/tar.1 index be480f6..4f07007 100644 --- a/tar.1 +++ b/tar.1 _AT_@ -6,16 +6,18 @@ .Nd create, list or extract a tape archive .Sh SYNOPSIS .Nm +.Cm x | Cm t | Fl x | Fl t .Op Fl C Ar dir .Op Fl J | Fl Z | Fl a | Fl j | Fl z -.Fl x Op Fl m | Fl t +.Op Fl m +.Op Fl p .Op Fl f Ar file .Op Ar file ... .Nm -.Op Fl C Ar dir +.Cm c | Fl c Op Fl C Ar dir .Op Fl J | Fl Z | Fl a | Fl j | Fl z .Op Fl h -.Fl c Ar path ... +.Ar path ... .Op Fl f Ar file .Sh DESCRIPTION .Nm _AT_@ -66,4 +68,9 @@ The utility is compliant with the UStar (Uniform Standard Tape ARchive) format defined in the .St -p1003.1-88 -specification. +specification. For long file paths (>99 bytes), the UStar, 'L' and 'x' +header formats are supported for reading (to a maximum size of PATH_MAX +or 255 bytes, depending on format), and the 'L' format is supported for +writing (with unlimited path size). Link targets are limited to the +UStar maximum of 100 bytes. + diff --git a/tar.c b/tar.c index b0a0e2e..4d44ec0 100644 --- a/tar.c +++ b/tar.c _AT_@ -186,15 +186,15 @@ static void putoctal(char *dst, unsigned num, int size) { if (snprintf(dst, size, "%.*o", size - 1, num) >= size) - eprintf("snprintf: input number too large\n"); + eprintf("putoctal: input number '%o' too large\n", num); } static int archive(const char *path) { static const struct header blank = { - "././_AT_LongLink", "0000000" , "0000000", "0000000", "00000000000", - "00000000000" , " ", AREG , "" , "ustar", "00", + "././_AT_LongLink", "0000600", "0000000", "0000000", "00000000000", + "00000000000" , " ", AREG , "" , "ustar", "00", }; char b[BLKSIZ + BLKSIZ], *p; struct header *h = (struct header *)b; _AT_@ -221,8 +221,8 @@ archive(const char *path) h->type = 'L'; putoctal(h->size, n, sizeof(h->size)); putoctal(h->chksum, chksum(h), sizeof(h->chksum)); - ewrite(tarfd, (char *)h, BLKSIZ); + for (p = (char *)path; n > 0; n -= BLKSIZ, p += BLKSIZ) { if (n < BLKSIZ) { p = memcpy(h--, p, n); _AT_@ -285,7 +285,7 @@ unarchive(char *fname, ssize_t l, char b[BLKSIZ]) int fd = -1, lnk = h->type == SYMLINK; if (!mflag && ((mtime = strtol(h->mtime, &p, 8)) < 0 || *p != '\0')) - eprintf("strtol %s: invalid number\n", h->mtime); + eprintf("strtol %s: invalid mtime\n", h->mtime); if (strcmp(fname, ".") && strcmp(fname, "./") && remove(fname) < 0) if (errno != ENOENT) weprintf("remove %s:", fname); _AT_@ -298,7 +298,7 @@ unarchive(char *fname, ssize_t l, char b[BLKSIZ]) case AREG: case RESERVED: if ((mode = strtol(h->mode, &p, 8)) < 0 || *p != '\0') - eprintf("strtol %s: invalid number\n", h->mode); + eprintf("strtol %s: invalid mode\n", h->mode); fd = open(fname, O_WRONLY | O_TRUNC | O_CREAT, 0600); if (fd < 0) eprintf("open %s:", fname); _AT_@ -313,7 +313,7 @@ unarchive(char *fname, ssize_t l, char b[BLKSIZ]) break; case DIRECTORY: if ((mode = strtol(h->mode, &p, 8)) < 0 || *p != '\0') - eprintf("strtol %s: invalid number\n", h->mode); + eprintf("strtol %s: invalid mode\n", h->mode); if (mkdir(fname, (mode_t)mode) < 0 && errno != EEXIST) eprintf("mkdir %s:", fname); pushdirtime(fname, mtime); _AT_@ -321,18 +321,18 @@ unarchive(char *fname, ssize_t l, char b[BLKSIZ]) case CHARDEV: case BLOCKDEV: if ((mode = strtol(h->mode, &p, 8)) < 0 || *p != '\0') - eprintf("strtol %s: invalid number\n", h->mode); + eprintf("strtol %s: invalid mode\n", h->mode); if ((major = strtol(h->major, &p, 8)) < 0 || *p != '\0') - eprintf("strtol %s: invalid number\n", h->major); + eprintf("strtol %s: invalid major device\n", h->major); if ((minor = strtol(h->minor, &p, 8)) < 0 || *p != '\0') - eprintf("strtol %s: invalid number\n", h->minor); + eprintf("strtol %s: invalid minor device\n", h->minor); type = (h->type == CHARDEV) ? S_IFCHR : S_IFBLK; if (mknod(fname, type | mode, makedev(major, minor)) < 0) eprintf("mknod %s:", fname); break; case FIFO: if ((mode = strtol(h->mode, &p, 8)) < 0 || *p != '\0') - eprintf("strtol %s: invalid number\n", h->mode); + eprintf("strtol %s: invalid mode\n", h->mode); if (mknod(fname, S_IFIFO | mode, 0) < 0) eprintf("mknod %s:", fname); break; _AT_@ -341,9 +341,9 @@ unarchive(char *fname, ssize_t l, char b[BLKSIZ]) } if ((uid = strtol(h->uid, &p, 8)) < 0 || *p != '\0') - eprintf("strtol %s: invalid number\n", h->uid); + eprintf("strtol %s: invalid uid\n", h->uid); if ((gid = strtol(h->gid, &p, 8)) < 0 || *p != '\0') - eprintf("strtol %s: invalid number\n", h->gid); + eprintf("strtol %s: invalid gid\n", h->gid); if (fd != -1) { for (; l > 0; l -= BLKSIZ) _AT_@ -404,7 +404,7 @@ c(int dirfd, const char *name, struct stat *st, void *data, struct recursor *r) static void sanitize(struct header *h) { - size_t i, j; + size_t i, j, l; struct { char *f; size_t l; _AT_@ -423,10 +423,14 @@ sanitize(struct header *h) * NULs as per the ustar specification. Patch all of them to * use NULs so we can perform string operations on them. */ for (i = 0; i < LEN(fields); i++){ - for (j = 0; j < fields[i].l && fields[i].f[j] == ' '; j++); - for (; j < fields[i].l; j++) + j = 0, l = fields[i].l - 1; + for (; j < l && fields[i].f[j] == ' '; j++); + for (; j <= l; j++) if (fields[i].f[j] == ' ') fields[i].f[j] = '\0'; + if (fields[i].f[l]) + eprintf("numeric field #%d (%.*s) is not null or space terminated\n", + i, l+1, fields[i].f); } } _AT_@ -434,7 +438,7 @@ static void chktar(struct header *h) { const char *reason; - char tmp[sizeof h->chksum], *err = ""; + char tmp[sizeof h->chksum], *err; long sum, i; if (h->prefix[0] == '\0' && h->name[0] == '\0') { _AT_@ -482,13 +486,13 @@ xt(int argc, char *argv[], int mode) if ((size = strtol(h->size, &p, 8)) < 0 || *p != '\0') eprintf("strtol %s: invalid size\n", h->size); - /* Long file path is read direcly into fname*/ + /* Long file path is read directly into fname*/ if (h->type == 'L' || h->type == 'x' || h->type == 'g') { /* Read header only up to size of fname buffer */ for (q = fname; q < fname+size; q += BLKSIZ) { if (q + BLKSIZ >= fname + l) - eprintf("name exceeds buffer: %s\n", fname); + eprintf("name exceeds buffer: %.*s\n", q-fname, fname); eread(tarfd, q, BLKSIZ); } -- 2.49.0Received on Sun Jun 01 2025 - 14:09:11 CEST
This archive was generated by hypermail 2.3.0 : Sun Jun 01 2025 - 22:36:37 CEST