[hackers] [sbase] Fix tar(1) handling of archives with improper internal order || sin

From: <git_AT_suckless.org>
Date: Mon, 20 Apr 2015 17:36:12 +0200 (CEST)

commit 97905f699111f114218b736ccd3979bce3095d9d
Author: sin <sin_AT_2f30.org>
Date: Mon Apr 20 16:31:51 2015 +0100

    Fix tar(1) handling of archives with improper internal order
    
    Not all archives are packed in such way to be generated without
    having to recursively generate the output path.
    
    For now, reuse the function from mkdir.c and later move it to
    libutil.

diff --git a/tar.c b/tar.c
index afe7854..d680d46 100644
--- a/tar.c
+++ b/tar.c
_AT_@ -4,6 +4,7 @@
 
 #include <errno.h>
 #include <grp.h>
+#include <libgen.h>
 #include <pwd.h>
 #include <stdio.h>
 #include <stdlib.h>
_AT_@ -173,19 +174,46 @@ archive(const char *path)
 }
 
 static int
+mkdirp(char *path)
+{
+ char *p;
+
+ for (p = path; *p; p++) {
+ if (*p != '/')
+ continue;
+ *p = '\0';
+ if (mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO) < 0 && errno != EEXIST) {
+ weprintf("mkdir %s:", path);
+ *p = '/';
+ return -1;
+ }
+ *p = '/';
+ }
+ if (mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO) < 0 && errno != EEXIST) {
+ weprintf("mkdir %s:", path);
+ return -1;
+ }
+ return 0;
+}
+
+static int
 unarchive(char *fname, ssize_t l, char b[BLKSIZ])
 {
         FILE *f = NULL;
         struct timeval times[2];
         struct header *h = (void *)b;
         long mode, major, minor, type, mtime, uid, gid;
- char lname[101], *p;
+ char lname[101], *tmp, *p;
 
         if (!mflag && ((mtime = strtoul(h->mtime, &p, 8)) < 0 || *p != '\0'))
                 eprintf("strtoul %s: invalid number\n", h->mtime);
         if (unlink(fname) < 0 && errno != ENOENT && errno != EISDIR)
                 eprintf("unlink %s:", fname);
 
+ tmp = strdup(fname);
+ mkdirp(dirname(tmp));
+ free(tmp);
+
         switch (h->type) {
         case REG:
         case AREG:
Received on Mon Apr 20 2015 - 17:36:12 CEST

This archive was generated by hypermail 2.3.0 : Mon Apr 20 2015 - 17:48:14 CEST