---
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.0
Received 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