diff options
-rw-r--r-- | stream.c | 13 | ||||
-rw-r--r-- | stream.h | 7 | ||||
-rw-r--r-- | txr.1 | 54 |
3 files changed, 70 insertions, 4 deletions
@@ -1132,6 +1132,9 @@ int w_open_mode(const wchar_t *wname, const struct stdio_mode m) if3(m.create, if3(!m.notrunc, O_TRUNC, 0) | O_CREAT, 0) | if3(m.append, O_APPEND, 0) | if3(m.excl, O_EXCL, 0) | +#if O_TMPFILE + if3(m.tmpfile, O_TMPFILE, 0) | +#endif if3(m.nonblock, O_NONBLOCK, 0)); char *stkname = coerce(char *, alloca(nsiz)); int fd; @@ -1464,6 +1467,16 @@ static struct stdio_mode do_parse_mode(val mode_str, struct stdio_mode m_dfl, m.create = 1; m.notrunc = 1; break; + case 'T': + ms++; +#if O_TMPFILE + m.read = 1; + m.write = 1; + m.tmpfile = 1; +#else + m.malformed = 1; +#endif + break; default: break; } @@ -118,13 +118,14 @@ struct stdio_mode { unsigned linebuf : 1; unsigned gzip : 1; unsigned gzlevel : 4; + unsigned tmpfile : 1; int buforder : 5; int redir[STDIO_MODE_NREDIRS][2]; }; -#define stdio_mode_init_blank { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, { { 0 } } } -#define stdio_mode_init_r { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, { { 0 } } } -#define stdio_mode_init_rpb { 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, { { 0 } } } +#define stdio_mode_init_blank { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, { { 0 } } } +#define stdio_mode_init_r { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, { { 0 } } } +#define stdio_mode_init_rpb { 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, { { 0 } } } #define std_input (deref(lookup_var_l(nil, stdin_s))) #define std_output (deref(lookup_var_l(nil, stdout_s))) @@ -61837,7 +61837,7 @@ Note that it permits no whitespace characters: .mono .mets < mode-string := [ < mode ] [ < options ] .mets < mode := { < selector [ + ] | + } -.mets < selector := { r | w | a | m } +.mets < selector := { r | w | a | m | T } .mets < options := { b | x | l | u | i | n | < digit | .mets \ \ \ \ \ \ \ \ \ \ \ \ \ \ <> z[ digit ] | < redirection } .mets < digit := { 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 } @@ -61898,6 +61898,17 @@ are appended. The file is opened for reading and writing. If it doesn't exist, it is created. The read position is at the beginning of the file, but writes are appended to the end regardless of the position. +.coIP T +This selector may be used on operating systems which support the +.code O_TMPFILE +mode of the +.code open +POSIX C library function. The +.meta path +must specify a directory to which the calling process has write permission. An +anonymous, unlinked file will be created in the filesystem which holds that +directory, open for reading and writing. See additional notes at the +end of this section. .RE .IP The meanings of the option characters are: @@ -62001,6 +62012,47 @@ function; the syntax performs I/O redirections in the child process created by that function, and is described in that function's documentation. .RE +.IP +The +.code O_TMPFILE +flag on which the +.str T +mode selector depends was introduced by the Linux kernel, and is likely only +supported on Linux systems. It is not supported on all filesystem types. + +The +.code T +mode offers a way to create temporary files in a robust way in any file system +which supports the mechanism. There is no concern about choosing a unique +file name, since the file doesn't have one. +The file is guaranteed to disappear if the process is terminated in any manner. +In contrast, traditional temporary files which are initially named a name and +then unlinked may remain if the process is abruptly terminated before it is +able to call +.codn unlink . + +On Linux, it is possible to link a file created with +.str T +into the filesystem, according to the following pattern: + +.verb + ;; atomically create file called "name" with content "hello" + + (let* ((stream (open-file "." "T")) + (fd (fileno stream))) + (put-string "hello\en" stream) + (flush-stream stream) + (rlink `/proc/self/fd/@fd` "name")) +.brev + +The atomic creation of a file can be simulated by the familiar pattern of +writing to a visible temporary file and then renaming. However, the above +pattern eliminates the risk that a temporary file will be left behind if the +procedure is interrupted for any reason before reaching the +.code rlink +call. Any reason includes process termination that +cannot be intercepted and handled, and operating +system failure or power loss. .coNP Function @ open-tail .synb |