summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2020-01-25 22:49:35 -0800
committerKaz Kylheku <kaz@kylheku.com>2020-01-25 22:49:35 -0800
commitb21778b7f432c9c5a9c3e5e442b2305cbcc0d524 (patch)
tree10953b0d2021da652277f9a033c3e33cb69563df
parent208319c21734bbb829fd6b8e2bc9da819b454bad (diff)
downloadtxr-b21778b7f432c9c5a9c3e5e442b2305cbcc0d524.tar.gz
txr-b21778b7f432c9c5a9c3e5e442b2305cbcc0d524.tar.bz2
txr-b21778b7f432c9c5a9c3e5e442b2305cbcc0d524.zip
ensure-dir: fail if exists and not dir.
* sysif.c (do_stat, do_lstat): Functions relocated before mkdir_nothrow_exists. (mkdir_nothrow_exists): In the EEXIST case, call stat on the object. If it's not a directory or a symlink to a directory, then do not suppress the error; propagate it to the caller, where it will become an exception. * txr.1: Specify the behavior of ensure-dir more precisely: that it only supresses the existence error for directories and directory symlinks.
-rw-r--r--sysif.c50
-rw-r--r--txr.15
2 files changed, 34 insertions, 21 deletions
diff --git a/sysif.c b/sysif.c
index dbaf8e59..369f1890 100644
--- a/sysif.c
+++ b/sysif.c
@@ -301,6 +301,28 @@ static val mkdir_wrap(val path, val mode)
}
#endif
+#if HAVE_SYS_STAT
+static int do_stat(val wpath, struct stat *buf)
+{
+ char *path = utf8_dup_to(c_str(wpath));
+ int res = stat(path, buf);
+ free(path);
+ return res;
+}
+
+#ifdef S_IFLNK
+static int do_lstat(val wpath, struct stat *buf)
+{
+ char *path = utf8_dup_to(c_str(wpath));
+ int res = lstat(path, buf);
+ free(path);
+ return res;
+}
+#else
+#define do_lstat do_stat
+#endif
+#endif
+
#if HAVE_MKDIR || HAVE_WINDOWS_H
static val mkdir_nothrow_exists(val path, val mode)
{
@@ -317,6 +339,14 @@ static val mkdir_nothrow_exists(val path, val mode)
ret = num(errno);
break;
case EEXIST:
+#if HAVE_SYS_STAT
+ {
+ struct stat st;
+ int err = do_stat(path, &st);
+ if (err == 0 && !S_ISDIR(st.st_mode))
+ ret = num(EEXIST);
+ }
+#endif
break;
default:
uw_throw(esym, eobj);
@@ -797,26 +827,6 @@ static val exit_star_wrap(val status)
#endif
#if HAVE_SYS_STAT
-static int do_stat(val wpath, struct stat *buf)
-{
- char *path = utf8_dup_to(c_str(wpath));
- int res = stat(path, buf);
- free(path);
- return res;
-}
-
-#ifdef S_IFLNK
-static int do_lstat(val wpath, struct stat *buf)
-{
- char *path = utf8_dup_to(c_str(wpath));
- int res = lstat(path, buf);
- free(path);
- return res;
-}
-#else
-#define do_lstat do_stat
-#endif
-
static int do_fstat(val stream, struct stat *buf)
{
val self = lit("fstat");
diff --git a/txr.1 b/txr.1
index 778d9994..ebee463c 100644
--- a/txr.1
+++ b/txr.1
@@ -57497,7 +57497,10 @@ The function
is similar to
.code mkdir
except that it attempts to create all the missing parent directories
-as necessary, and does not throw an error if the directory exists.
+as necessary, and does not throw an error if
+.meta path
+refers to an existing object, if that object is a directory or a symbolic
+link to a directory.
.coNP Function @ chdir
.synb