summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2022-05-26 22:53:51 -0700
committerKaz Kylheku <kaz@kylheku.com>2022-05-26 22:53:51 -0700
commite23478755d418e5f80384dbfa2536f2aaa3c888b (patch)
tree104c35ac486eb0d312835616096e5036152558af
parente48572f574e24bae076c909c066f42c4d1f3b3aa (diff)
downloadtxr-e23478755d418e5f80384dbfa2536f2aaa3c888b.tar.gz
txr-e23478755d418e5f80384dbfa2536f2aaa3c888b.tar.bz2
txr-e23478755d418e5f80384dbfa2536f2aaa3c888b.zip
gzio: support more modes in open-file.
* gzio.c (w_gzopen_mode): Use w_open_mode if available, in order to support most of the flags (including "x" which Zlib has, but which we are not passing through). * stream.c (w_open_mode): New function formed from w_fopen_mode content. (w_fopen_mode): Call w_open_mode. * stream.c (w_open_mode): Declared.
-rw-r--r--gzio.c35
-rw-r--r--gzio.h2
-rw-r--r--stream.c14
-rw-r--r--stream.h1
4 files changed, 49 insertions, 3 deletions
diff --git a/gzio.c b/gzio.c
index fc025e9a..ef1e21ba 100644
--- a/gzio.c
+++ b/gzio.c
@@ -479,6 +479,13 @@ gzFile w_gzopen_mode(const wchar_t *wname, const wchar_t *wmode,
uw_throwf(file_error_s,
lit("~a: gzip stream cannot both read and write"), self, nao);
}
+
+#if HAVE_FCNTL
+ {
+ int fd = w_open_mode(wname, m);
+ return (fd < 0) ? NULL : w_gzdopen_mode(fd, wmode, m, self);
+ }
+#else
{
char *name = utf8_dup_to(wname);
char *mode = utf8_dup_to(wmode);
@@ -487,6 +494,34 @@ gzFile w_gzopen_mode(const wchar_t *wname, const wchar_t *wmode,
free(mode);
return f;
}
+#endif
+}
+
+gzFile w_gzdopen_mode(int fd, const wchar_t *wmode,
+ const struct stdio_mode m, val self)
+{
+ if (m.buforder >= 0 || m.nonblock || m.notrunc || m.unbuf ||
+ m.linebuf || m.interactive)
+ {
+ goto badmode;
+ }
+
+ if (m.read && m.write) {
+ uw_throwf(file_error_s,
+ lit("~a: gzip stream cannot both read and write"), self, nao);
+ }
+
+ {
+ char *mode = utf8_dup_to(wmode);
+ gzFile f = gzdopen(fd, mode);
+ free(mode);
+ if (f)
+ return f;
+ }
+
+badmode:
+ uw_throwf(file_error_s,
+ lit("~a: invalid modes for gzip stream"), self, nao);
}
val make_gzio_stream(gzFile f, int fd, val descr, int is_output)
diff --git a/gzio.h b/gzio.h
index bbcd1e1a..2f9cf164 100644
--- a/gzio.h
+++ b/gzio.h
@@ -30,4 +30,6 @@ val gzio_stream_s;
void gzio_init(void);
gzFile w_gzopen_mode(const wchar_t *wname, const wchar_t *wmode,
const struct stdio_mode m, val self);
+gzFile w_gzdopen_mode(int fd, const wchar_t *wmode,
+ const struct stdio_mode m, val self);
val make_gzio_stream(gzFile f, int fd, val descr, int is_output);
diff --git a/stream.c b/stream.c
index d3118955..e336d35f 100644
--- a/stream.c
+++ b/stream.c
@@ -1127,10 +1127,9 @@ static struct strm_ops stdio_ops =
static struct strm_ops stdio_sock_ops;
#endif
-static FILE *w_fopen_mode(const wchar_t *wname, const wchar_t *mode,
- const struct stdio_mode m)
-{
#if HAVE_FCNTL
+int w_open_mode(const wchar_t *wname, const struct stdio_mode m)
+{
char *name = utf8_dup_to(wname);
size_t nsiz = strlen(name) + 1;
int flags = (if3(m.read && m.write, O_RDWR, 0) |
@@ -1150,6 +1149,15 @@ static FILE *w_fopen_mode(const wchar_t *wname, const wchar_t *mode,
fd = open(stkname, flags, 0666);
sig_restore_enable;
+ return fd;
+}
+#endif
+
+static FILE *w_fopen_mode(const wchar_t *wname, const wchar_t *mode,
+ const struct stdio_mode m)
+{
+#if HAVE_FCNTL
+ int fd = w_open_mode(wname, m);
return (fd < 0) ? NULL : w_fdopen(fd, mode);
#else
/* TODO: detect if fopen supports "x" in mode */
diff --git a/stream.h b/stream.h
index 83534617..b735dd07 100644
--- a/stream.h
+++ b/stream.h
@@ -167,6 +167,7 @@ void fill_stream_ops(struct strm_ops *ops);
void stream_print_op(val stream, val out, val pretty, struct strm_ctx *);
void stream_mark_op(val stream);
void stream_destroy_op(val stream);
+int w_open_mode(const wchar_t *wname, const struct stdio_mode m);
struct stdio_mode parse_mode(val mode_str, struct stdio_mode m_dfl, val self);
val normalize_mode(struct stdio_mode *m, val mode_str,
struct stdio_mode m_dfl, val self);