commit 3a332e026f17d8a078a1bcd25d8854a884fb9bef
parent f1a1af6c69114cc1e4d97c1681749fbb98618ad9
Author: Chris Bracken <chris@bracken.jp>
Date: Fri, 20 Feb 2026 15:06:19 +0900
FileSystem: add fdopen/close calls
Diffstat:
5 files changed, 30 insertions(+), 14 deletions(-)
diff --git a/src/fs_inmemory.c b/src/fs_inmemory.c
@@ -115,6 +115,14 @@ static int inmemory_mkstemp(char* template) {
return mkstemp(template);
}
+static FILE* inmemory_fdopen(int fd, const char* mode) {
+ return fdopen(fd, mode);
+}
+
+static int inmemory_close(int fd) {
+ return close(fd);
+}
+
static int inmemory_rename(const char* oldpath, const char* newpath) {
// If oldpath is a real file on disk (from mkstemp), we read it into our
// in-memory registry and then delete the disk file.
@@ -185,7 +193,9 @@ static const FileSystem kStdInmemoryFs = {
.mkdir = inmemory_mkdir,
.mkdirp = inmemory_mkdirp,
.fopen = inmemory_fopen,
+ .fdopen = inmemory_fdopen,
.fclose = inmemory_fclose,
+ .close = inmemory_close,
.mkstemp = inmemory_mkstemp,
.rename = inmemory_rename,
.chmod = inmemory_chmod,
diff --git a/src/fs_posix.c b/src/fs_posix.c
@@ -40,10 +40,18 @@ static FILE* posix_fopen(const char* path, const char* mode) {
return fopen(path, mode);
}
+static FILE* posix_fdopen(int fd, const char* mode) {
+ return fdopen(fd, mode);
+}
+
static int posix_fclose(FILE* stream) {
return fclose(stream);
}
+static int posix_close(int fd) {
+ return close(fd);
+}
+
static int posix_mkstemp(char* template) {
return mkstemp(template);
}
@@ -69,7 +77,9 @@ static const FileSystem kStdPosixFs = {
.mkdir = posix_mkdir,
.mkdirp = posix_mkdirp,
.fopen = posix_fopen,
+ .fdopen = posix_fdopen,
.fclose = posix_fclose,
+ .close = posix_close,
.mkstemp = posix_mkstemp,
.rename = posix_rename,
.chmod = posix_chmod,
diff --git a/src/utils.h b/src/utils.h
@@ -11,7 +11,9 @@ typedef struct FileSystem {
int (*mkdir)(const char* path, mode_t mode);
int (*mkdirp)(const char* path);
FILE* (*fopen)(const char* path, const char* mode);
+ FILE* (*fdopen)(int fd, const char* mode);
int (*fclose)(FILE* stream);
+ int (*close)(int fd);
int (*mkstemp)(char* template);
int (*rename)(const char* oldpath, const char* newpath);
int (*chmod)(const char* path, mode_t mode);
diff --git a/src/writer/gopher/log.c b/src/writer/gopher/log.c
@@ -60,8 +60,7 @@ void gopher_log_free(GopherLog* log) {
log->fs->fclose(log->cache_in);
}
if (log->cache_out) {
- /* TODO: When fdopen is added to FileSystem, update to fs->fclose. */
- fclose(log->cache_out);
+ log->fs->fclose(log->cache_out);
}
gopher_page_free(log->page);
log->page = NULL;
@@ -77,10 +76,9 @@ void gopher_log_set_cachefile(GopherLog* log, const char* cachefile) {
if (out_fd == -1) {
err(1, "mkstemp: %s", log->temp_cache_path);
}
- /* TODO: Consider adding fdopen to the FileSystem VTable. */
- log->cache_out = fdopen(out_fd, "w");
+ log->cache_out = log->fs->fdopen(out_fd, "w");
if (!log->cache_out) {
- close(out_fd);
+ log->fs->close(out_fd);
err(1, "fdopen: %s", log->temp_cache_path);
}
@@ -122,8 +120,7 @@ void gopher_log_end(GopherLog* log) {
log->fs->fclose(log->cache_in);
log->cache_in = NULL;
}
- /* TODO: Use fs->fclose() for consistency. */
- fclose(log->cache_out);
+ log->fs->fclose(log->cache_out);
log->cache_out = NULL;
if (log->fs->rename(log->temp_cache_path, log->cache_path)) {
diff --git a/src/writer/html/log.c b/src/writer/html/log.c
@@ -60,8 +60,7 @@ void html_log_free(HtmlLog* log) {
log->fs->fclose(log->cache_in);
}
if (log->cache_out) {
- /* TODO: When fdopen is added to FileSystem, update to fs->fclose. */
- fclose(log->cache_out);
+ log->fs->fclose(log->cache_out);
}
html_page_free(log->page);
log->page = NULL;
@@ -77,10 +76,9 @@ void html_log_set_cachefile(HtmlLog* log, const char* cachefile) {
if (out_fd == -1) {
err(1, "mkstemp: %s", log->temp_cache_path);
}
- /* TODO: Consider adding fdopen to the FileSystem VTable. */
- log->cache_out = fdopen(out_fd, "w");
+ log->cache_out = log->fs->fdopen(out_fd, "w");
if (!log->cache_out) {
- close(out_fd);
+ log->fs->close(out_fd);
err(1, "fdopen: %s", log->temp_cache_path);
}
@@ -129,8 +127,7 @@ void html_log_end(HtmlLog* log) {
log->fs->fclose(log->cache_in);
log->cache_in = NULL;
}
- /* TODO: Use fs->fclose() for consistency. */
- fclose(log->cache_out);
+ log->fs->fclose(log->cache_out);
log->cache_out = NULL;
if (log->fs->rename(log->temp_cache_path, log->cache_path)) {