lib: Add fdopen_keepfd()
authorVolker Lendecke <vl@samba.org>
Wed, 10 Apr 2024 11:07:56 +0000 (13:07 +0200)
committerMartin Schwenke <martins@samba.org>
Tue, 16 Apr 2024 23:51:45 +0000 (23:51 +0000)
Capture the dup/fdopen pattern

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Martin Schwenke <mschwenke@ddn.com>
lib/util/util_file.c
lib/util/util_file.h

index 221d5a49fdb85d9579a2252fc5646dd9690fc163..46e67f0a4a6d29e6d06cd280fa2ea36a9149d4bd 100644 (file)
@@ -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;
+}
index fa8c599d1afa2a78e57928efe6883905d2b1f1bc..8de75da5ed101153bb4796bab840a68450db9010 100644 (file)
@@ -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