diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2015-03-10 22:23:17 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2015-03-10 22:23:17 -0700 |
commit | 89e46f760a11140db3cc4a4becd7a6941989c89a (patch) | |
tree | d23a73928d32640d4f64f6b6ae3b4780e903d703 /sysif.c | |
parent | 34d4a240a1c7db27d56e65cbe7a5e9030c5c0377 (diff) | |
download | txr-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.c | 64 |
1 files changed, 64 insertions, 0 deletions
@@ -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 |