mirror of
				https://gitlab.gnome.org/GNOME/glib.git
				synced 2025-10-31 00:12:19 +01:00 
			
		
		
		
	glib-unix: Add convenience API for pipes
We can't easily use g_autofd with g_unix_open_pipe, because its parameter is an array of two fds that both need closing. Add an inline convenience wrapper providing the obvious semantics. Signed-off-by: Simon McVittie <smcv@collabora.com>
This commit is contained in:
		
				
					committed by
					
						 Philip Withnall
						Philip Withnall
					
				
			
			
				
	
			
			
			
						parent
						
							6fd1037361
						
					
				
				
					commit
					f31db7d370
				
			
							
								
								
									
										208
									
								
								glib/glib-unix.h
									
									
									
									
									
								
							
							
						
						
									
										208
									
								
								glib/glib-unix.h
									
									
									
									
									
								
							| @@ -1,5 +1,6 @@ | ||||
| /* glib-unix.h - Unix specific integration | ||||
|  * Copyright (C) 2011 Red Hat, Inc. | ||||
|  * Copyright 2023 Collabora Ltd. | ||||
|  * | ||||
|  * SPDX-License-Identifier: LGPL-2.1-or-later | ||||
|  * | ||||
| @@ -33,6 +34,7 @@ | ||||
| #include <fcntl.h> | ||||
|  | ||||
| #include <glib.h> | ||||
| #include <gstdio.h> | ||||
|  | ||||
| #ifndef G_OS_UNIX | ||||
| #error "This header may only be used on UNIX" | ||||
| @@ -120,6 +122,212 @@ GLIB_AVAILABLE_IN_2_64 | ||||
| struct passwd *g_unix_get_passwd_entry (const gchar  *user_name, | ||||
|                                         GError      **error); | ||||
|  | ||||
| /** | ||||
|  * GUnixPipe: | ||||
|  * @fds: A pair of file descriptors, each negative if closed or not yet opened. | ||||
|  *  The file descriptor with index %G_UNIX_PIPE_END_READ is readable. | ||||
|  *  The file descriptor with index %G_UNIX_PIPE_END_WRITE is writable. | ||||
|  * | ||||
|  * A Unix pipe. The advantage of this type over `int[2]` is that it can | ||||
|  * be closed automatically when it goes out of scope, using `g_auto(GUnixPipe)`, | ||||
|  * on compilers that support that feature. | ||||
|  * | ||||
|  * Since: 2.80 | ||||
|  */ | ||||
| GLIB_AVAILABLE_TYPE_IN_2_80 | ||||
| typedef struct { | ||||
|   int fds[2]; | ||||
| } GUnixPipe; | ||||
|  | ||||
| /** | ||||
|  * GUnixPipeEnd: | ||||
|  * @G_UNIX_PIPE_END_READ: The readable file descriptor 0 | ||||
|  * @G_UNIX_PIPE_END_WRITE: The writable file descriptor 1 | ||||
|  * | ||||
|  * Mnemonic constants for the ends of a Unix pipe. | ||||
|  * | ||||
|  * Since: 2.80 | ||||
|  */ | ||||
| GLIB_AVAILABLE_TYPE_IN_2_80 | ||||
| typedef enum | ||||
| { | ||||
|   G_UNIX_PIPE_END_READ = 0, | ||||
|   G_UNIX_PIPE_END_WRITE = 1 | ||||
| } GUnixPipeEnd; | ||||
|  | ||||
| /** | ||||
|  * G_UNIX_PIPE_INIT: | ||||
|  * | ||||
|  * Initializer for a #GUnixPipe that has not yet been opened. | ||||
|  * Both of its file descriptors are initialized to `-1` (invalid), | ||||
|  * the same as if they had been closed. | ||||
|  * | ||||
|  * Since: 2.80 | ||||
|  */ | ||||
| #define G_UNIX_PIPE_INIT { { -1, -1 } } GLIB_AVAILABLE_MACRO_IN_2_80 | ||||
|  | ||||
| /* Suppress "Not available before" warnings when declaring the | ||||
|  * implementations */ | ||||
| G_GNUC_BEGIN_IGNORE_DEPRECATIONS | ||||
|  | ||||
| /** | ||||
|  * g_unix_pipe_open: | ||||
|  * @self: A pair of file descriptors | ||||
|  * @flags: Flags to pass to g_unix_open_pipe(), typically `FD_CLOEXEC` | ||||
|  * @error: Used to report an error on failure | ||||
|  * | ||||
|  * Open a pipe. This is the same as g_unix_open_pipe(), but uses the | ||||
|  * #GUnixPipe data structure. | ||||
|  * | ||||
|  * Returns: %TRUE on success | ||||
|  * | ||||
|  * Since: 2.80 | ||||
|  */ | ||||
| GLIB_AVAILABLE_STATIC_INLINE_IN_2_80 | ||||
| static inline gboolean | ||||
| g_unix_pipe_open (GUnixPipe *self, | ||||
|                   int flags, | ||||
|                   GError **error) | ||||
| { | ||||
|   return g_unix_open_pipe (self->fds, flags, error); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * g_unix_pipe_get: | ||||
|  * @self: A pair of file descriptors | ||||
|  * @end: One of the ends of the pipe | ||||
|  * | ||||
|  * Return one of the ends of the pipe. It remains owned by @self. | ||||
|  * | ||||
|  * This function is async-signal safe (see [`signal(7)`](man:signal(7)) and | ||||
|  * [`signal-safety(7)`](man:signal-safety(7))), making it safe to call from a | ||||
|  * signal handler or a #GSpawnChildSetupFunc. | ||||
|  * | ||||
|  * This function preserves the value of `errno`. | ||||
|  * | ||||
|  * Returns: a non-negative file descriptor owned by @self, which must not | ||||
|  *  be closed by the caller, or a negative number if the corresponding | ||||
|  *  end of the pipe was already closed or stolen | ||||
|  * | ||||
|  * Since: 2.80 | ||||
|  */ | ||||
| GLIB_AVAILABLE_STATIC_INLINE_IN_2_80 | ||||
| static inline int | ||||
| g_unix_pipe_get (GUnixPipe *self, | ||||
|                  GUnixPipeEnd end) | ||||
| { | ||||
|   return self->fds[end]; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * g_unix_pipe_steal: | ||||
|  * @self: A pair of file descriptors | ||||
|  * @end: One of the ends of the pipe | ||||
|  * | ||||
|  * Return one of the ends of the pipe. It becomes owned by the caller, | ||||
|  * and the file descriptor in the data structure is set to `-1`, | ||||
|  * similar to g_steal_fd(). | ||||
|  * | ||||
|  * This function is async-signal safe (see [`signal(7)`](man:signal(7)) and | ||||
|  * [`signal-safety(7)`](man:signal-safety(7))), making it safe to call from a | ||||
|  * signal handler or a #GSpawnChildSetupFunc. | ||||
|  * | ||||
|  * This function preserves the value of `errno`. | ||||
|  * | ||||
|  * Returns: a non-negative file descriptor, which becomes owned by the | ||||
|  *  caller and must be closed by the caller if required, or a negative | ||||
|  *  number if the corresponding end of the pipe was already closed or stolen | ||||
|  * | ||||
|  * Since: 2.80 | ||||
|  */ | ||||
| GLIB_AVAILABLE_STATIC_INLINE_IN_2_80 | ||||
| static inline int | ||||
| g_unix_pipe_steal (GUnixPipe *self, | ||||
|                    GUnixPipeEnd end) | ||||
| { | ||||
|   return g_steal_fd (&self->fds[end]); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * g_unix_pipe_close: | ||||
|  * @self: A pair of file descriptors | ||||
|  * @end: One of the ends of the pipe | ||||
|  * @error: Optionally used to report an error on failure | ||||
|  * | ||||
|  * Close one of the ends of the pipe and set the relevant member of @fds | ||||
|  * to `-1` before returning, equivalent to g_clear_fd(). | ||||
|  * | ||||
|  * Like g_close(), if closing the file descriptor fails, the error is | ||||
|  * stored in both %errno and @error. If this function succeeds, | ||||
|  * %errno is undefined. | ||||
|  * | ||||
|  * This function is async-signal safe if @error is %NULL and the relevant | ||||
|  * member of @fds is either negative or a valid open file descriptor. | ||||
|  * This makes it safe to call from a signal handler or a #GSpawnChildSetupFunc | ||||
|  * under those conditions. | ||||
|  * See [`signal(7)`](man:signal(7)) and | ||||
|  * [`signal-safety(7)`](man:signal-safety(7)) for more details. | ||||
|  * | ||||
|  * To close both file descriptors and ignore any errors, use | ||||
|  * g_unix_pipe_clear() instead. | ||||
|  * | ||||
|  * Returns: %TRUE on success | ||||
|  * | ||||
|  * Since: 2.80 | ||||
|  */ | ||||
| GLIB_AVAILABLE_STATIC_INLINE_IN_2_80 | ||||
| static inline gboolean | ||||
| g_unix_pipe_close (GUnixPipe *self, | ||||
|                    GUnixPipeEnd end, | ||||
|                    GError **error) | ||||
| { | ||||
|   return g_clear_fd (&self->fds[end], error); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * g_unix_pipe_clear: | ||||
|  * @self: a #GUnixPipe | ||||
|  * | ||||
|  * Close both ends of the pipe, unless they have already been closed or | ||||
|  * stolen. Any errors are ignored: use g_unix_pipe_close() or g_clear_fd() | ||||
|  * if error-handling is required. | ||||
|  * | ||||
|  * This function is async-signal safe if @error is %NULL and each member | ||||
|  * of @fds are either negative or a valid open file descriptor. | ||||
|  * As a result, it is safe to call this function or use `g_auto(GUnixPipe)` | ||||
|  * (on compilers that support it) in a signal handler or a | ||||
|  * #GSpawnChildSetupFunc, as long as those conditions are ensured to be true. | ||||
|  * See [`signal(7)`](man:signal(7)) and | ||||
|  * [`signal-safety(7)`](man:signal-safety(7)) for more details. | ||||
|  * | ||||
|  * This function preserves the value of `errno`. | ||||
|  * | ||||
|  * Since: 2.80 | ||||
|  */ | ||||
| GLIB_AVAILABLE_STATIC_INLINE_IN_2_80 | ||||
| static inline void | ||||
| g_unix_pipe_clear (GUnixPipe *self) | ||||
| { | ||||
|   /* Don't overwrite thread-local errno if closing the fd fails */ | ||||
|   int errsv = errno; | ||||
|  | ||||
|   if (!g_unix_pipe_close (self, G_UNIX_PIPE_END_READ, NULL)) | ||||
|     { | ||||
|       /* ignore */ | ||||
|     } | ||||
|  | ||||
|   if (!g_unix_pipe_close (self, G_UNIX_PIPE_END_WRITE, NULL)) | ||||
|     { | ||||
|       /* ignore */ | ||||
|     } | ||||
|  | ||||
|   errno = errsv; | ||||
| } | ||||
|  | ||||
| G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC (GUnixPipe, g_unix_pipe_clear) | ||||
|  | ||||
| G_GNUC_END_IGNORE_DEPRECATIONS | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif  /* __G_UNIX_H__ */ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user