From ea6af1312700db89ca22b4d05a6343b2bebf1894 Mon Sep 17 00:00:00 2001 From: Theo Buehler Date: Sat, 23 May 2015 13:12:18 +0200 Subject: [PATCH] mkdirp: do not throw an error if directory exists 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 | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/libi3/mkdirp.c b/libi3/mkdirp.c index a0d35f96..95c31b59 100644 --- a/libi3/mkdirp.c +++ b/libi3/mkdirp.c @@ -11,7 +11,19 @@ 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; }