gout

A static git page generator
git clone https://git.bracken.jp/gout.git
Log | Files | Refs | README | LICENSE

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:
Msrc/fs_inmemory.c | 10++++++++++
Msrc/fs_posix.c | 10++++++++++
Msrc/utils.h | 2++
Msrc/writer/gopher/log.c | 11++++-------
Msrc/writer/html/log.c | 11++++-------
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)) {