From 28335cdb5d72c63d52c83fe00a67b8aa28558677 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 10 Apr 2024 13:07:56 +0200 Subject: [PATCH] lib: Add fdopen_keepfd() Capture the dup/fdopen pattern Signed-off-by: Volker Lendecke Reviewed-by: Martin Schwenke --- lib/util/util_file.c | 36 ++++++++++++++++++++++++++++-------- lib/util/util_file.h | 2 ++ 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/lib/util/util_file.c b/lib/util/util_file.c index 221d5a49fdb..46e67f0a4a6 100644 --- a/lib/util/util_file.c +++ b/lib/util/util_file.c @@ -176,20 +176,13 @@ _PUBLIC_ char *fd_load(int fd, size_t *psize, size_t maxsize, TALLOC_CTX *mem_ct size_t size = 0; size_t chunk = 1024; int err; - int fd_dup; if (maxsize == 0) { maxsize = SIZE_MAX; } - fd_dup = dup(fd); - if (fd_dup == -1) { - return NULL; - } - - file = fdopen(fd_dup, "r"); + file = fdopen_keepfd(fd, "r"); if (file == NULL) { - close(fd_dup); return NULL; } @@ -497,3 +490,30 @@ char *file_ploadv(char * const argl[], size_t *size) return p; } + +/* + * fopen a dup'ed fd. Prevent fclose to close the fd passed in. + * + * Don't use on fd's that have fcntl locks, on error it will close the + * dup'ed fd, thus killing your fcntl locks. + */ +FILE *fdopen_keepfd(int fd, const char *mode) +{ + FILE *f = NULL; + int dup_fd; + + dup_fd = dup(fd); + if (dup_fd == -1) { + return NULL; + } + + f = fdopen(dup_fd, mode); + if (f == NULL) { + int err = errno; + close(dup_fd); + errno = err; + return NULL; + } + + return f; +} diff --git a/lib/util/util_file.h b/lib/util/util_file.h index fa8c599d1af..8de75da5ed1 100644 --- a/lib/util/util_file.h +++ b/lib/util/util_file.h @@ -77,4 +77,6 @@ bool file_compare(const char *path1, const char *path2); */ char *file_ploadv(char * const argl[], size_t *size); +FILE *fdopen_keepfd(int fd, const char *mode); + #endif