summaryrefslogtreecommitdiffstats
path: root/stream.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2021-05-31 07:49:38 -0700
committerKaz Kylheku <kaz@kylheku.com>2021-05-31 07:49:38 -0700
commitfdb8f90b22f8d4993b5937d55f5cbffc45ae940c (patch)
tree30f6c8cd4f9318010f8bbe0d8558806af7358cc8 /stream.c
parent93454f1fc069d7d5a0af7b2aa1c773949b59d106 (diff)
downloadtxr-fdb8f90b22f8d4993b5937d55f5cbffc45ae940c.tar.gz
txr-fdb8f90b22f8d4993b5937d55f5cbffc45ae940c.tar.bz2
txr-fdb8f90b22f8d4993b5937d55f5cbffc45ae940c.zip
New: mkdtemp and mkstemp functions.
* configure: check for mkstemp and mkdtemp. * stream.c (stdio_set_prop): Implement setting the :name property. We need this in mkstemp_wrap in order to punch in the temporary name, so that the application can retrieve it. (mkdtemp_wrap, mkstemp_wrap): New functions. (stream_init): Register mkdtemp and mkstemp intrinsics. * stream.h (mkdtemp_wrap, mkstemp_wrap): Declared. * txr.1: Documented. * share/txr/stdlib/doc-syms.tl: Updated.
Diffstat (limited to 'stream.c')
-rw-r--r--stream.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/stream.c b/stream.c
index 14e1f725..34509f87 100644
--- a/stream.c
+++ b/stream.c
@@ -738,6 +738,8 @@ static val stdio_set_prop(val stream, val ind, val prop)
} else if (ind == byte_oriented_k) {
h->is_byte_oriented = prop ? 1 : 0;
return t;
+ } else if (ind == name_k) {
+ h->descr = prop;
}
return nil;
}
@@ -4952,6 +4954,55 @@ val tmpfile_wrap(void)
num(errno), errno_to_str(errno), nao);
}
+#if HAVE_MKSTEMP
+
+val mkdtemp_wrap(val template)
+{
+ char *tmpl = utf8_dup_to(c_str(scat2(template, lit("XXXXXX"))));
+
+ if (mkdtemp(tmpl) != 0) {
+ val ret = string_utf8(tmpl);
+ free(tmpl);
+ return ret;
+ }
+
+ free(tmpl);
+ uw_throwf(file_error_s, lit("mkdtemp failed: ~d/~s"),
+ num(errno), errno_to_str(errno), nao);
+}
+
+val mkstemp_wrap(val prefix, val suffix)
+{
+ val self = lit("mkstemp");
+ val suff = default_arg(suffix, null_string);
+ val template = scat3(prefix, lit("XXXXXX"), suff);
+ cnum slen = c_num(length(suffix), self);
+ char *tmpl = utf8_dup_to(c_str(template));
+ val name;
+ int fd;
+
+#if HAVE_MKSTEMPS
+ fd = mkstemps(tmpl, slen);
+#else
+ if (slen > 0) {
+ free(tmpl);
+ uw_throwf(system_error_s, lit("~a: suffix not supported"), self, nao);
+ }
+ fd = mkstemps(tmpl);
+#endif
+ name = string_utf8(tmpl);
+ free(tmpl);
+ if (fd != -1) {
+ val stream = open_fileno(num(fd), lit("w+b"));
+ stream_set_prop(stream, name_k, name);
+ return stream;
+ }
+ uw_throwf(file_error_s, lit("~a failed: ~d/~s"),
+ self, num(errno), errno_to_str(errno), nao);
+}
+
+#endif
+
static val iobuf_free_list;
val iobuf_get(void)
@@ -5145,6 +5196,10 @@ void stream_init(void)
reg_varl(intern(lit("indent-code"), user_package), num_fast(indent_code));
reg_varl(intern(lit("indent-foff"), user_package), num_fast(indent_foff));
reg_fun(intern(lit("tmpfile"), user_package), func_n0(tmpfile_wrap));
+#if HAVE_MKSTEMP
+ reg_fun(intern(lit("mkdtemp"), user_package), func_n1(mkdtemp_wrap));
+ reg_fun(intern(lit("mkstemp"), user_package), func_n2o(mkstemp_wrap, 1));
+#endif
#if HAVE_SOCKETS
uw_register_subtype(socket_error_s, error_s);