about summary refs log tree commit diff
path: root/misc
diff options
context:
space:
mode:
Diffstat (limited to 'misc')
-rw-r--r--misc/subr.c31
-rw-r--r--misc/subr.h2
2 files changed, 19 insertions, 14 deletions
diff --git a/misc/subr.c b/misc/subr.c
index 70a04af..22ed6e2 100644
--- a/misc/subr.c
+++ b/misc/subr.c
@@ -97,24 +97,24 @@ set_blocking(int fd)
 }
 
 int
-mkdirs(char *path)
+mkdirs(char *path, int mode)
 {
     int err = 0;
-    char *spos = strchr(path + 1, '/'); // Must ignore the root
+    char *spos = strchr(path + 1, '/'); // Skip leading '/'
 
     while (spos != NULL) {
         *spos = '\0';
-        err = mkdir(path, 0777);
+        err = mkdir(path, mode);
         *spos = '/';
 
-        if (err != 0 && errno != EEXIST) {
-            err = errno;
-            break;
-        }
+        if (err != 0 && errno != EEXIST)
+            return errno;
 
         spos = strchr(spos + 1, '/');
     }
-    return err;
+    if (mkdir(path, mode) != 0)
+        return errno;
+    return 0;
 }
 
 int
@@ -130,11 +130,16 @@ vaopen(int *res, int flags, const char *fmt, va_list ap)
 again:
     fd = open(path, flags, 0666);
     if (fd < 0 && errno == ENOENT && (flags & O_CREAT) != 0 && !didmkdirs) {
-        if (mkdirs(path) == 0) {
-            didmkdirs = 1;
-            goto again;
-        } else
-            return errno;
+        char *rs = rindex(path, '/');
+        if (rs != NULL) {
+            *rs = '\0';
+            if (mkdirs(path, 0777) == 0) {
+                *rs = '/';
+                didmkdirs = 1;
+                goto again;
+            }
+        }
+        return errno;
     }
 
     if (fd >= 0) {
diff --git a/misc/subr.h b/misc/subr.h
index fd9e002..25bca0d 100644
--- a/misc/subr.h
+++ b/misc/subr.h
@@ -10,7 +10,7 @@
 int set_nonblocking(int fd);
 int set_blocking(int fd);
 
-int mkdirs(char *path);
+int mkdirs(char *path, int mode);
 
 __attribute__((format (printf, 3, 0)))
 int vaopen(int *resfd, int flags, const char *fmt, va_list ap);