diff options
-rwxr-xr-x | configure | 21 | ||||
-rw-r--r-- | share/txr/stdlib/doc-syms.tl | 2 | ||||
-rw-r--r-- | stream.c | 55 | ||||
-rw-r--r-- | stream.h | 2 | ||||
-rw-r--r-- | txr.1 | 85 |
5 files changed, 165 insertions, 0 deletions
@@ -3228,6 +3228,27 @@ if [ -z "$have_winsize" ] ; then printf "no\n" fi +printf "Checking for mkstemp/mkdtemp ... " + +cat > conftest.c <<! +#include <stdlib.h> + +int main(int argc, char **argv) +{ + char templ[] = "abcXXXXXX"; + int fd = mkstemp(templ); + char *s = mkdtemp(templ); + return 0; +} +! + +if conftest ; then + printf "yes\n" + printf "#define HAVE_MKSTEMP 1\n" >> config.h +else + printf "no\n" +fi + printf "Checking for mkstemps ... " cat > conftest.c <<! diff --git a/share/txr/stdlib/doc-syms.tl b/share/txr/stdlib/doc-syms.tl index 223eb987..177ac266 100644 --- a/share/txr/stdlib/doc-syms.tl +++ b/share/txr/stdlib/doc-syms.tl @@ -1222,8 +1222,10 @@ ("minusp" "D-0050") ("mismatch" "N-03164F4F") ("mkdir" "N-00C543B8") + ("mkdtemp" "N-026E4871") ("mkfifo" "N-0091FD43") ("mknod" "N-00F93A39") + ("mkstemp" "N-026E0471") ("mkstring" "N-033DD796") ("mlet" "N-008216E0") ("mmakunbound" "N-02964FC0") @@ -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); @@ -252,4 +252,6 @@ val iobuf_get(void); void iobuf_put(val buf); void iobuf_list_empty(void); val tmpfile_wrap(void); +val mkdtemp_wrap(val template); +val mkstemp_wrap(val prefix, val suffix); void stream_init(void); @@ -55048,6 +55048,14 @@ in the file system. POSIX (IEEE Std 1003.1-2017) notes that in some implementations, "a permanent file may be left behind if the process calling tmpfile() is killed while it is processing a call to tmpfile". +Notes: if a unique file is required which exists in the file system under a +known name until explicitly deleted, the +.code mkstemp +function may be used. If a unique directory needs to be created, the +.code mkdtemp +function may be used. These two functions are described in the Unix Filesystem +Complex Operations section of the manual. + .coNP Function @ make-string-input-stream .synb .mets (make-string-input-stream << string ) @@ -65556,6 +65564,83 @@ is a symbolic link, it is dereferenced; .code touch operates on the target of the link. +.coNP Function @ mkdtemp +.synb +.mets (mkdtemp << prefix ) +.syne +.desc +The +.code mkdtemp +function combines the +.metn prefix , +which is a string, with a generated suffix to create a unique directory +name. The directory is created, and the name is returned. + +If the +.code prefix +argument ends in with a sequence of one or more +.code X +characters, the behavior is unspecified. + +Note: this function is implemented using the same-named POSIX function. +Whereas the POSIX function requires the template to end in a sequence of +at least six +.code X +characters, which are replaced by the generated suffix, the \*(TL function +handles this detail internally, requiring only the prefix part without those +characters. + +.coNP Function @ mkstemp +.synb +.mets (mkstemp << prefix <> [ suffix ]) +.syne +.desc +The +.code mkdtemp +create a unique file name by adding a generated infix between the +.meta prefix +and +.meta suffix +strings. +The file is created, and a stream open in +.str w+b +mode for the file is returned. + +If either the +.meta prefix +or +.meta suffix +contain +.code X +characters, the behavior is unspecified. + +If +.meta suffix +is omitted, it defaults to the empty string. + +The name of the file is available by interrogating the returned stream's +.code :name +property using the function +.codn stream-get-prop . + +Notes: this function is implemented using the POSIX function +.code mkstemp +or, if available, using the +.code mkstemps +function which is not standardized, but appears in the GNU C Library +and some other systems. If +.code mkstemps +is unavailable, then the suffix functionality is not available: the +.meta suffix +argument must either be omitted, or must be an empty string. + +Whereas the C library functions require the template to contain a sequence +at least six +.code X +characters, which are replaced by the generated portion, the \*(TL function +handles this detail internally, requiring no such characters in any of its +inputs. + .SS* Unix Filesystem Object Existence, Type and Access Tests Functions in this category perform various tests on the attributes of |