---
tar.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 71 insertions(+), 10 deletions(-)
diff --git a/tar.c b/tar.c
index d3a9f3b..f46b5be 100644
--- a/tar.c
+++ b/tar.c
_AT_@ -176,17 +176,51 @@ putoctal(char *dst, unsigned num, int size)
eprintf("snprintf: input number too large\n");
}
+static void
+fillchksum(struct header *h)
+{
+ char *b;
+ size_t i, chksum;
+
+ b = (char *)h;
+ memset(h->chksum, ' ', sizeof(h->chksum));
+ for (i = 0, chksum = 0; i < sizeof(*h); i++)
+ chksum += (unsigned char)b[i];
+ putoctal(h->chksum, chksum, sizeof(h->chksum));
+}
+
+static size_t
+xhdradd(char xhdr[], size_t max, const char *k, const char *v, size_t vlen)
+{
+ size_t sz, prevsz;
+
+ /* The size of the message includes itself, so compute it via iteration. */
+ prevsz = max;
+ while (1) {
+ sz = snprintf(xhdr, max, "%ld %s=%.*s\n", prevsz, k, (int)vlen, v);
+ if (sz == max)
+ eprintf("pax headers too large\n");
+ if (sz == prevsz)
+ return sz;
+ prevsz = sz;
+ }
+}
+
static int
archive(const char *path)
{
char b[BLKSIZ];
+ char xb[BLKSIZ];
+ char xhdr[8192];
+ char link[4096];
struct group *gr;
- struct header *h;
+ struct header *h, *xh;
struct passwd *pw;
struct stat st;
- size_t chksum, i;
+ size_t xhdroffset, pathlen;
ssize_t l, r;
int fd = -1;
+ xhdroffset = 0;
if (lstat(path, &st) < 0) {
weprintf("lstat %s:", path);
_AT_@ -201,7 +235,7 @@ archive(const char *path)
h = (struct header *)b;
memset(b, 0, sizeof(b));
- estrlcpy(h->name, path, sizeof(h->name));
+ strncpy (h->name, path, sizeof(h->name));
putoctal(h->mode, (unsigned)st.st_mode & 0777, sizeof(h->mode));
putoctal(h->uid, (unsigned)st.st_uid, sizeof(h->uid));
putoctal(h->gid, (unsigned)st.st_gid, sizeof(h->gid));
_AT_@ -212,6 +246,12 @@ archive(const char *path)
estrlcpy(h->uname, pw ? pw->pw_name : "", sizeof(h->uname));
estrlcpy(h->gname, gr ? gr->gr_name : "", sizeof(h->gname));
+ h->name[sizeof(h->name)-1] = 0;
+ pathlen = strlen(path);
+ if (pathlen >= sizeof(h->name)) {
+ xhdroffset += xhdradd(&xhdr[xhdroffset], sizeof(xhdr)-xhdroffset, "path", path, pathlen);
+ }
+
if (S_ISREG(st.st_mode)) {
h->type = REG;
putoctal(h->size, (unsigned)st.st_size, sizeof(h->size));
_AT_@ -222,9 +262,16 @@ archive(const char *path)
h->type = DIRECTORY;
} else if (S_ISLNK(st.st_mode)) {
h->type = SYMLINK;
- if ((r = readlink(path, h->linkname, sizeof(h->linkname) - 1)) < 0)
+ if ((r = readlink(path, link, sizeof(link) - 1)) < 0)
eprintf("readlink %s:", path);
- h->linkname[r] = '\0';
+ if (r == sizeof(link))
+ eprintf("link target too long\n");
+ link[r] = '\0';
+ strncpy(h->linkname, link, sizeof(h->linkname));
+ h->linkname[sizeof(h->linkname)-1] = 0;
+ if (r >= sizeof(h->linkname)) {
+ xhdroffset += xhdradd(&xhdr[xhdroffset], sizeof(xhdr)-xhdroffset, "linkpath", link, r);
+ }
} else if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
h->type = S_ISCHR(st.st_mode) ? CHARDEV : BLOCKDEV;
putoctal(h->major, (unsigned)major(st.st_dev), sizeof(h->major));
_AT_@ -233,10 +280,24 @@ archive(const char *path)
h->type = FIFO;
}
- memset(h->chksum, ' ', sizeof(h->chksum));
- for (i = 0, chksum = 0; i < sizeof(*h); i++)
- chksum += (unsigned char)b[i];
- putoctal(h->chksum, chksum, sizeof(h->chksum));
+ if (xhdroffset) {
+ xh = (struct header *)xb;
+ memset(xb, 0, sizeof(xb));
+ xh->type = 'x';
+ putoctal(xh->size, xhdroffset, sizeof(xh->size));
+ memcpy( xh->magic, "ustar", sizeof(h->magic));
+ memcpy( xh->version, "00", sizeof(h->version));
+ fillchksum(xh);
+ ewrite(tarfd, xb, BLKSIZ);
+ ewrite(tarfd, xhdr, xhdroffset);
+ if (xhdroffset % BLKSIZ) {
+ l = BLKSIZ - (xhdroffset % BLKSIZ);
+ memset(xb, 0, l);
+ ewrite(tarfd, xb, l);
+ }
+ }
+
+ fillchksum(h);
ewrite(tarfd, b, BLKSIZ);
if (fd != -1) {
_AT_@ -412,7 +473,7 @@ chktar(struct header *h)
const char *reason;
long s1, s2, i;
- if (h->prefix[0] == '\0' && h->name[0] == '\0') {
+ if (h->prefix[0] == '\0' && h->name[0] == '\0' && h->type != 'x') {
reason = "empty filename";
goto bad;
}
--
2.33.1
Received on Sun May 01 2022 - 14:25:18 CEST
This archive was generated by hypermail 2.3.0 : Sun May 01 2022 - 15:12:34 CEST