Commit Diff


commit - 98660df2502a6b2c92c651e6bc3f4a8be6143bb5
commit + f8d580d82be78a62ed75c348e2d487226992aa30
blob - af9a4ed2e614118cfc948480c5b9f8e3710e57f6
blob + 990e4b6dbbcb7f5e287f3a34b35bf26f5055aea4
--- src/cmd/gzip/unzip.c
+++ src/cmd/gzip/unzip.c
@@ -328,6 +328,32 @@ sunzip(Biobuf *bin)
 			return 1;
 		if(eok < 0)
 			return 0;
+	}
+}
+
+static int
+makedir(char *s)
+{
+	int f;
+
+	if (access(s, AEXIST) == 0)
+		return -1;
+	f = create(s, OREAD, DMDIR | 0777);
+	if (f >= 0)
+		close(f);
+	return f;
+}
+
+static void
+mkpdirs(char *s)
+{
+	int done = 0;
+	char *p = s;
+
+	while (!done && (p = strchr(p + 1, '/')) != nil) {
+		*p = '\0';
+		done = (access(s, AEXIST) < 0 && makedir(s) < 0);
+		*p = '/';
 	}
 }
 
@@ -379,6 +405,10 @@ unzipEntry(Biobuf *bin, ZipHead *czh)
 				fd = 1;
 		}else if(isdir){
 			fd = create(zh.file, OREAD, DMDIR | 0775);
+			if(fd < 0){
+				mkpdirs(zh.file);
+				fd = create(zh.file, OREAD, DMDIR | 0775);
+			}
 			if(fd < 0){
 				d = dirstat(zh.file);
 				if(d == nil || (d->mode & DMDIR) != DMDIR){
@@ -389,6 +419,10 @@ unzipEntry(Biobuf *bin, ZipHead *czh)
 			}
 		}else if(ok){
 			fd = create(zh.file, OWRITE, 0664);
+			if(fd < 0){
+				mkpdirs(zh.file);
+				fd = create(zh.file, OWRITE, 0664);
+			}
 			if(fd < 0){
 				fprint(2, "unzip: can't create %s: %r\n", zh.file);
 				ok = 0;