]> git.sur5r.net Git - i3/i3/commitdiff
mkdirp: do not throw an error if directory exists
authorTheo Buehler <theo@math.ethz.ch>
Sat, 23 May 2015 11:12:18 +0000 (13:12 +0200)
committerMichael Stapelberg <michael@stapelberg.de>
Thu, 30 Jul 2015 19:41:24 +0000 (21:41 +0200)
If I restart i3 4.10.2 twice, e.g. with

$ i3-msg restart; sleep 3; i3-msg restart

the second time I get the following two errors:

05/22/15 10:46:03 - ERROR: mkdir(/tmp/i3-theo.toAK7N) failed: File exists
05/22/15 10:46:03 - ERROR: Could not create "/tmp/i3-theo.toAK7N" for storing the restart layout, layout will be lost.

The first one is from mkdirp() in src/ipc.c and the second one is from
store_restart_layout() in src/util.c.

Notice that I do _not_ get the ``open()'' or ``Could not write restart layout to
...'' error messages, so the layout writing code after line 260 in
store_restart_layout() succeeded and the layout isn't actually lost.  Thus,
these error messages are a bit misleading, especially the second one (which is
triggered by the failure of mkdirp()).

POSIX says about `mkdir -p':

``Each dir operand that names an existing directory shall be ignored without
error.''

Therefore, I suggest the following simple patch that makes mkdirp() succeed if
the named file exists and actually is a directory.  This silences the second
error as well.

libi3/mkdirp.c

index a0d35f961dbfcbd35687f051bcdd010ffc812282..95c31b59d5634bc6a1026195aaabad7d1b68942d 100644 (file)
 bool mkdirp(const char *path) {
     if (mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == 0)
         return true;
-    if (errno != ENOENT) {
+    if (errno == EEXIST) {
+        struct stat st;
+        /* Check that the named file actually is a directory. */
+        if (stat(path, &st)) {
+            ELOG("stat(%s) failed: %s\n", path, strerror(errno));
+            return false;
+        }
+        if (!S_ISDIR(st.st_mode)) {
+            ELOG("mkdir(%s) failed: %s\n", path, strerror(ENOTDIR));
+            return false;
+        }
+        return true;
+    } else if (errno != ENOENT) {
         ELOG("mkdir(%s) failed: %s\n", path, strerror(errno));
         return false;
     }