[glib: 7/12] glib/win32: introduce private g_win32_reopen_noninherited()




commit c984db650f3bd56ec21bccb0fb88efca99efbd07
Author: Marc-André Lureau <marcandre lureau redhat com>
Date:   Thu Apr 7 17:53:54 2022 +0400

    glib/win32: introduce private g_win32_reopen_noninherited()
    
    Used in following commits, including in some GIO experiments, so make it
    a private API.
    
    For now, this implementation is similar to the glib/gspawn-win32.c one,
    with mroe error checking and better on error behaviour. A following
    patch will also fix the case of duplicating sockets.
    
    Signed-off-by: Marc-André Lureau <marcandre lureau redhat com>

 glib/glib-init.h    |  2 ++
 glib/glib-private.c |  1 +
 glib/glib-private.h |  4 ++++
 glib/gwin32.c       | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 71 insertions(+)
---
diff --git a/glib/glib-init.h b/glib/glib-init.h
index b77164c731..b01d256b98 100644
--- a/glib/glib-init.h
+++ b/glib/glib-init.h
@@ -43,6 +43,8 @@ gboolean _g_win32_call_rtl_version (OSVERSIONINFOEXW *info);
 
 extern HMODULE glib_dll;
 gchar *g_win32_find_helper_executable_path (const gchar *process_name, void *dll_handle);
+int g_win32_reopen_noninherited (int fd, int mode, GError **err);
+
 #endif
 
 #endif /* __GLIB_INIT_H__ */
diff --git a/glib/glib-private.c b/glib/glib-private.c
index 0a59c6f165..357a43a30d 100644
--- a/glib/glib-private.c
+++ b/glib/glib-private.c
@@ -55,6 +55,7 @@ glib__private__ (void)
     g_win32_readlink_utf8,
     g_win32_fstat,
     g_win32_find_helper_executable_path,
+    g_win32_reopen_noninherited,
 #endif
   };
 
diff --git a/glib/glib-private.h b/glib/glib-private.h
index 943252f1be..787f8f1fab 100644
--- a/glib/glib-private.h
+++ b/glib/glib-private.h
@@ -171,6 +171,10 @@ typedef struct {
   /* See gwin32.c */
   gchar *(*g_win32_find_helper_executable_path) (const gchar *process_name,
                                                  void *dll_handle);
+
+  int                   (* g_win32_reopen_noninherited) (int      fd,
+                                                         int      mode,
+                                                         GError **err);
 #endif
 
 
diff --git a/glib/gwin32.c b/glib/gwin32.c
index 691a487367..a4ed386bae 100644
--- a/glib/gwin32.c
+++ b/glib/gwin32.c
@@ -31,6 +31,7 @@
 
 #include "glibconfig.h"
 
+#include <glib/gstdio.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -1448,3 +1449,66 @@ g_win32_find_helper_executable_path (const gchar *executable_name, void *dll_han
 
   return executable_path;
 }
+
+/*
+ * g_win32_reopen_noninherited:
+ * @fd: (transfer full): A file descriptor
+ * @mode: _open_osfhandle flags
+ * @error: A location to return an error of type %G_FILE_ERROR
+ *
+ * Reopen the given @fd with `_O_NOINHERIT`.
+ *
+ * The @fd is closed on success.
+ *
+ * Returns: (transfer full): The new file-descriptor, or -1 on error.
+ */
+int
+g_win32_reopen_noninherited (int fd,
+                             int mode,
+                             GError **error)
+{
+  HANDLE h;
+  HANDLE duph;
+  int dupfd, errsv;
+
+  h = (HANDLE) _get_osfhandle (fd);
+  errsv = errno;
+
+  if (h == INVALID_HANDLE_VALUE)
+    {
+      const char *emsg = g_strerror (errsv);
+      g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errsv),
+                   "_get_osfhandle() failed: %s", emsg);
+      return -1;
+    }
+
+  if (DuplicateHandle (GetCurrentProcess (), h,
+                       GetCurrentProcess (), &duph,
+                       0, FALSE, DUPLICATE_SAME_ACCESS) == 0)
+    {
+      char *emsg = g_win32_error_message (GetLastError ());
+      g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+                   "DuplicateHandle() failed: %s", emsg);
+      g_free (emsg);
+      return -1;
+    }
+
+  /* the duph ownership is transferred to dupfd */
+  dupfd = _open_osfhandle ((gintptr) duph, mode | _O_NOINHERIT);
+  if (dupfd < 0)
+    {
+      g_set_error_literal (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+                           "_open_osfhandle() failed");
+      CloseHandle (duph);
+      return -1;
+    }
+
+  if (!g_close (fd, error))
+    {
+      /* ignore extra errors in this case */
+      g_close (dupfd, NULL);
+      return -1;
+    }
+
+  return dupfd;
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]