summaryrefslogtreecommitdiffstats
path: root/sysif.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2015-03-10 22:23:17 -0700
committerKaz Kylheku <kaz@kylheku.com>2015-03-10 22:23:17 -0700
commit89e46f760a11140db3cc4a4becd7a6941989c89a (patch)
treed23a73928d32640d4f64f6b6ae3b4780e903d703 /sysif.c
parent34d4a240a1c7db27d56e65cbe7a5e9030c5c0377 (diff)
downloadtxr-89e46f760a11140db3cc4a4becd7a6941989c89a.tar.gz
txr-89e46f760a11140db3cc4a4becd7a6941989c89a.tar.bz2
txr-89e46f760a11140db3cc4a4becd7a6941989c89a.zip
* sysif.c (mkdir_nothrow_exists): New static function.
(ensure_dir): New function. (sysif_init): ensure_dir registered as intrinsic. * txr.1: ensure_dir documented.
Diffstat (limited to 'sysif.c')
-rw-r--r--sysif.c64
1 files changed, 64 insertions, 0 deletions
diff --git a/sysif.c b/sysif.c
index c401b23a..04466896 100644
--- a/sysif.c
+++ b/sysif.c
@@ -58,6 +58,7 @@
#include "signal.h"
#include "utf8.h"
#include "unwind.h"
+#include "gc.h"
#include "eval.h"
#include "sysif.h"
@@ -180,6 +181,68 @@ static val mkdir_wrap(val path, val mode)
}
#endif
+#if HAVE_MKDIR || HAVE_WINDOWS_H
+static val mkdir_nothrow_exists(val path, val mode)
+{
+ val ret = t;
+
+ uw_catch_begin(cons(file_error_s, nil), esym, eobj);
+
+ ret = mkdir_wrap(path, mode);
+
+ uw_catch (esym, eobj) {
+ switch (errno) {
+ case EACCES:
+ case EPERM:
+ ret = num(errno);
+ break;
+ case EEXIST:
+ break;
+ default:
+ uw_throw(esym, eobj);
+ }
+ }
+
+ uw_unwind;
+
+ uw_catch_end;
+
+ return ret;
+}
+
+static val ensure_dir(val path, val mode)
+{
+#if HAVE_WINDOWS_H
+ val sep = lit("\\");
+ val sep_set = lit("\\/");
+#else
+ val sep = lit("/");
+ val sep_set = lit("/");
+#endif
+ val split_path = split_str_set(path, sep_set);
+ val partial_path = pop(&split_path);
+ val ret = t;
+
+ for (;;) {
+ if (length(partial_path) != zero)
+ ret = mkdir_nothrow_exists(partial_path, mode);
+
+ if (!split_path)
+ break;
+
+ partial_path = format(nil, lit("~a~a~a"),
+ partial_path, sep, pop(&split_path), nao);
+ }
+
+ if (ret != t)
+ uw_throwf(file_error_s,
+ lit("ensure-dir: ~a: ~a/~s"), path, ret,
+ string_utf8(strerror(c_num(ret))), nao);
+
+ return ret;
+}
+#endif
+
#if HAVE_UNISTD_H
static val chdir_wrap(val path)
{
@@ -388,6 +451,7 @@ void sysif_init(void)
#if HAVE_MKDIR || HAVE_WINDOWS_H
reg_fun(intern(lit("mkdir"), user_package), func_n2o(mkdir_wrap, 1));
+ reg_fun(intern(lit("ensure-dir"), user_package), func_n2o(ensure_dir, 1));
#endif
#if HAVE_UNISTD_H