some zip files appear not to have directory entries so files cannot be extracted untile the apropriate hierarchy has been made (by hand). This patch adds a -a, auto create directories option to unzip which does this for you. -Steve Reference: /n/sources/patch/applied/zip-auto-dirs Date: Thu Aug 9 12:24:29 CES 2007 Signed-off-by: steve@quintile.net --- /sys/man/1/gzip Thu Aug 9 12:21:15 2007 +++ /sys/man/1/gzip Thu Aug 9 12:21:12 2007 @@ -39,7 +39,7 @@ ] .PP .B zip -.RB [ -vD [ 1-9 ]] +.RB [ -avD [ 1-9 ]] .RB [ -f .IR zipfile ] .I file @@ -131,6 +131,10 @@ .PP The options are: .TP 0.6i +.B -a +Automaticialy creates directories as needed, needed for zip files +created by broken implementations which omit directories. +.TP .B -c Write to standard output rather than creating an output file. .TP --- /sys/src/cmd/gzip/unzip.c Thu Aug 9 12:21:31 2007 +++ /sys/src/cmd/gzip/unzip.c Thu Aug 9 12:21:27 2007 @@ -47,6 +47,7 @@ static ulong wlen; static jmp_buf zjmp; static jmp_buf seekjmp; +static int autodir; static void usage(void) @@ -65,6 +66,9 @@ stream = 0; zfile = nil; ARGBEGIN{ + case 'a': + autodir++; + break; case 'D': debug++; break; @@ -338,6 +342,55 @@ } } +static int mkdirs(char *); + +/* + * if any directories leading up to path don't exist, create them. + * modifies but restores path. + */ +static int +mkpdirs(char *path) +{ + int rv = 0; + char *sl = strrchr(path, '/'); +print("%s\n", path); + if (sl != nil) { + *sl = '\0'; + rv = mkdirs(path); + *sl = '/'; + } + return rv; +} + +/* + * if path or any directories leading up to it don't exist, create them. + * modifies but restores path. + */ +static int +mkdirs(char *path) +{ + int fd; + + if (access(path, AEXIST) >= 0) + return 0; + + /* make presumed-missing intermediate directories */ + if (mkpdirs(path) < 0) + return -1; + + /* make final directory */ + fd = create(path, OREAD, 0755|DMDIR); + if (fd < 0) + /* + * we may have lost a race; if the directory now exists, + * it's okay. + */ + return access(path, AEXIST) < 0? -1: 0; + close(fd); + return 0; +} + + /* * extracts a single entry from a zip file * czh is the optional corresponding central directory entry @@ -395,6 +448,8 @@ free(d); } }else if(ok){ + if(autodir) + mkpdirs(zh.file); fd = create(zh.file, OWRITE, 0664); if(fd < 0){ fprint(2, "unzip: can't create %s: %r\n", zh.file);