summaryrefslogtreecommitdiffstats
path: root/sysif.c
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 /sysif.c
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.
Diffstat (limited to 'sysif.c')
-rw-r--r--sysif.c50
1 files changed, 30 insertions, 20 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");