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>
This commit is contained in:
Marc-André Lureau 2022-04-07 17:53:54 +04:00
parent 982b074fa9
commit c984db650f
4 changed files with 71 additions and 0 deletions

View File

@ -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__ */

View File

@ -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
};

View File

@ -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

View File

@ -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;
}