summaryrefslogtreecommitdiffstats
path: root/stream.c
diff options
context:
space:
mode:
authorPaul A. Patience <paul@apatience.com>2021-08-29 04:42:04 -0400
committerKaz Kylheku <kaz@kylheku.com>2021-08-29 08:06:58 -0700
commit469cd5ab27bba7679bebe60cd0617e09f4838e50 (patch)
treef4b10bd2b1555a274ecdf9df9d3d63511d8b60c3 /stream.c
parent702d02d7958a20e8cd0e6872ca12540c84cdca55 (diff)
downloadtxr-469cd5ab27bba7679bebe60cd0617e09f4838e50.tar.gz
txr-469cd5ab27bba7679bebe60cd0617e09f4838e50.tar.bz2
txr-469cd5ab27bba7679bebe60cd0617e09f4838e50.zip
open-file: add mode option "x".
* stream.h (struct stdio_mode): New member, excl flag. (stdio_mode_init_blank, stdio_mode_init_r, stdio_mode_init_rpb): Add initializer for excl flag. * stream.c (do_parse_mode): Handle 'x' in mode string. (w_fopen_mode): Add O_EXCL flag if m.excl is set. Throw an error if we don't HAVE_FCNTL and m.excl is set. * txr.1: Document mode option "x".
Diffstat (limited to 'stream.c')
-rw-r--r--stream.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/stream.c b/stream.c
index f055a987..1183f7f5 100644
--- a/stream.c
+++ b/stream.c
@@ -1130,6 +1130,7 @@ static FILE *w_fopen_mode(const wchar_t *wname, const wchar_t *mode,
if3(m.create || m.append,
if3(!m.notrunc, O_TRUNC, 0) | O_CREAT, 0) |
if3(m.append, O_APPEND, 0) |
+ if3(m.excl, O_EXCL, 0) |
if3(m.nonblock, O_NONBLOCK, 0));
char *stkname = coerce(char *, alloca(nsiz));
int fd;
@@ -1143,7 +1144,8 @@ static FILE *w_fopen_mode(const wchar_t *wname, const wchar_t *mode,
return (fd < 0) ? NULL : w_fdopen(fd, mode);
#else
- if (m.notrunc || m.nonblock)
+ /* TODO: detect if fopen supports "x" in mode */
+ if (m.notrunc || m.excl || m.nonblock)
uw_throwf(file_error_s,
lit("open-file: specified mode not supported on this system"),
nao);
@@ -1484,6 +1486,14 @@ static struct stdio_mode do_parse_mode(val mode_str, struct stdio_mode m_dfl,
case 'b':
m.binary = 1;
break;
+ case 'x':
+ /* Ensure only "w" and "w+" can have the "x" option. */
+ if (!m.write || !m.create || m.notrunc) {
+ m.malformed = 1;
+ return m;
+ }
+ m.excl = 1;
+ break;
case 'i':
m.interactive = 1;
break;