diff --git a/bin/check-requirements.c b/bin/check-requirements.c index a28c252106187ad2995d8f63cbac8e960d5093bb..3f26d11bbcf629d963410d1dbad97fa9c86f4bb1 100644 --- a/bin/check-requirements.c +++ b/bin/check-requirements.c @@ -81,56 +81,6 @@ usage (int code) exit (code); } -static FILE * -divert_stdout_to_stderr (GError **error) -{ - int original_stdout_fd; - FILE *original_stdout; - - /* Duplicate the original stdout so that we still have a way to write - * machine-readable output. */ - original_stdout_fd = dup (STDOUT_FILENO); - - if (original_stdout_fd < 0) - { - int saved_errno = errno; - - g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (saved_errno), - "Unable to duplicate fd %d: %s", - STDOUT_FILENO, g_strerror (saved_errno)); - return NULL; - } - - /* If something like g_debug writes to stdout, make it come out of - * our original stderr. */ - if (dup2 (STDERR_FILENO, STDOUT_FILENO) != STDOUT_FILENO) - { - int saved_errno = errno; - - close (original_stdout_fd); - g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (saved_errno), - "Unable to make fd %d a copy of fd %d: %s", - STDOUT_FILENO, STDERR_FILENO, g_strerror (saved_errno)); - return NULL; - } - - /* original_stdout takes ownership of original_stdout_fd on success */ - original_stdout = fdopen (original_stdout_fd, "w"); - - if (original_stdout == NULL) - { - int saved_errno = errno; - - close (original_stdout_fd); - g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (saved_errno), - "Unable to create a stdio wrapper for fd %d: %s", - original_stdout_fd, g_strerror (saved_errno)); - return NULL; - } - - return original_stdout; -} - static gboolean check_x86_features (SrtX86FeatureFlags features) { @@ -180,7 +130,7 @@ main (int argc, /* stdout is reserved for machine-readable output, so avoid having * things like g_debug() pollute it. */ - original_stdout = divert_stdout_to_stderr (&error); + original_stdout = _srt_divert_stdout_to_stderr (&error); if (original_stdout == NULL) { diff --git a/bin/system-info.c b/bin/system-info.c index e4a7bce3316bbd5be3b5baa781e46bdf4bd0cf08..9034e28a1136624757f2b37400f94409fbd27af8 100644 --- a/bin/system-info.c +++ b/bin/system-info.c @@ -166,56 +166,6 @@ usage (int code) exit (code); } -static FILE * -divert_stdout_to_stderr (GError **error) -{ - int original_stdout_fd; - FILE *original_stdout; - - /* Duplicate the original stdout so that we still have a way to write - * machine-readable output. */ - original_stdout_fd = dup (STDOUT_FILENO); - - if (original_stdout_fd < 0) - { - int saved_errno = errno; - - g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (saved_errno), - "Unable to duplicate fd %d: %s", - STDOUT_FILENO, g_strerror (saved_errno)); - return NULL; - } - - /* If something like g_debug writes to stdout, make it come out of - * our original stderr. */ - if (dup2 (STDERR_FILENO, STDOUT_FILENO) != STDOUT_FILENO) - { - int saved_errno = errno; - - close (original_stdout_fd); - g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (saved_errno), - "Unable to make fd %d a copy of fd %d: %s", - STDOUT_FILENO, STDERR_FILENO, g_strerror (saved_errno)); - return NULL; - } - - /* original_stdout takes ownership of original_stdout_fd on success */ - original_stdout = fdopen (original_stdout_fd, "w"); - - if (original_stdout == NULL) - { - int saved_errno = errno; - - close (original_stdout_fd); - g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (saved_errno), - "Unable to create a stdio wrapper for fd %d: %s", - original_stdout_fd, g_strerror (saved_errno)); - return NULL; - } - - return original_stdout; -} - static void jsonify_flags (JsonBuilder *builder, GType flags_type, @@ -895,7 +845,7 @@ main (int argc, /* stdout is reserved for machine-readable output, so avoid having * things like g_debug() pollute it. */ - original_stdout = divert_stdout_to_stderr (&error); + original_stdout = _srt_divert_stdout_to_stderr (&error); if (original_stdout == NULL) { diff --git a/pressure-vessel/adverb.c b/pressure-vessel/adverb.c index acfc40bd8629ff0f03cc06c106b2f2daed21c8cd..7a1e7a2017a4b836d2b8ff018dd2a03910e56e6c 100644 --- a/pressure-vessel/adverb.c +++ b/pressure-vessel/adverb.c @@ -678,7 +678,7 @@ main (int argc, G_LOG_LEVEL_DEBUG | G_LOG_LEVEL_INFO, cli_log_func, (void *) g_get_prgname ()); - original_stdout = pv_divert_stdout_to_stderr (error); + original_stdout = _srt_divert_stdout_to_stderr (error); if (original_stdout == NULL) { diff --git a/pressure-vessel/launch.c b/pressure-vessel/launch.c index 7cdbe216a91e57fe0593312f1d30fa6da18423a1..0015de161910ff8b2a018e58b28d0fd0cddd4b80 100644 --- a/pressure-vessel/launch.c +++ b/pressure-vessel/launch.c @@ -40,6 +40,7 @@ #include <gio/gunixfdlist.h> #include "steam-runtime-tools/glib-backports-internal.h" +#include "steam-runtime-tools/utils-internal.h" #include "libglnx/libglnx.h" #include "launcher.h" @@ -516,7 +517,7 @@ main (int argc, G_LOG_LEVEL_DEBUG | G_LOG_LEVEL_INFO, cli_log_func, (void *) g_get_prgname ()); - original_stdout = pv_divert_stdout_to_stderr (error); + original_stdout = _srt_divert_stdout_to_stderr (error); if (original_stdout == NULL) { diff --git a/pressure-vessel/launcher.c b/pressure-vessel/launcher.c index a30cdee0f671aab4789539d5383e8bd930d1baaf..dfc3af2ba209ec428f20c88a8707141e005e338c 100644 --- a/pressure-vessel/launcher.c +++ b/pressure-vessel/launcher.c @@ -41,6 +41,7 @@ #include <gio/gunixfdlist.h> #include "steam-runtime-tools/glib-backports-internal.h" +#include "steam-runtime-tools/utils-internal.h" #include "libglnx/libglnx.h" #include "flatpak-utils-base-private.h" @@ -1089,7 +1090,7 @@ main (int argc, G_LOG_LEVEL_DEBUG | G_LOG_LEVEL_INFO, cli_log_func, (void *) g_get_prgname ()); - original_stdout = pv_divert_stdout_to_stderr (error); + original_stdout = _srt_divert_stdout_to_stderr (error); if (original_stdout == NULL) { diff --git a/pressure-vessel/meson.build b/pressure-vessel/meson.build index ca2d1cc86f6ebd73075f18803cb2ddaac3005f9c..8281b56ddeaf66aaeb37d8ce0c6b46b3d3be143d 100644 --- a/pressure-vessel/meson.build +++ b/pressure-vessel/meson.build @@ -157,6 +157,7 @@ executable( threads, gio_unix, libglnx_dep, + json_glib, ], include_directories : pv_include_dirs, install : true, @@ -177,6 +178,7 @@ executable( threads, gio_unix, libglnx_dep, + json_glib, ], include_directories : pv_include_dirs, install : true, @@ -207,6 +209,7 @@ executable( gio_unix, xau, libglnx_dep, + json_glib, ], include_directories : pv_include_dirs, install : true, diff --git a/pressure-vessel/utils.c b/pressure-vessel/utils.c index ad256557fc50ef9849035a453c0b58ec9a6d06f5..4236f3328078d93194c642dfb3fb6e989fd1a0ad 100644 --- a/pressure-vessel/utils.c +++ b/pressure-vessel/utils.c @@ -306,63 +306,6 @@ pv_boolean_environment (const gchar *name, return def; } -/** - * pv_divert_stdout_to_stderr: - * @error: Used to raise an error on failure - * - * Duplicate file descriptors so that functions that would write to - * `stdout` instead write to a copy of the original `stderr`. Return - * a file handle that can be used to print structured output to the - * original `stdout`. - * - * Returns: (transfer full): A libc file handle for the original `stdout`, - * or %NULL on error. Free with `fclose()`. - */ -FILE * -pv_divert_stdout_to_stderr (GError **error) -{ - g_autoptr(FILE) original_stdout = NULL; - glnx_autofd int original_stdout_fd = -1; - int flags; - - g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - - /* Duplicate the original stdout so that we still have a way to write - * machine-readable output. */ - original_stdout_fd = dup (STDOUT_FILENO); - - if (original_stdout_fd < 0) - return glnx_null_throw_errno_prefix (error, - "Unable to duplicate fd %d", - STDOUT_FILENO); - - flags = fcntl (original_stdout_fd, F_GETFD, 0); - - if (flags < 0) - return glnx_null_throw_errno_prefix (error, - "Unable to get flags of new fd"); - - fcntl (original_stdout_fd, F_SETFD, flags|FD_CLOEXEC); - - /* If something like g_debug writes to stdout, make it come out of - * our original stderr. */ - if (dup2 (STDERR_FILENO, STDOUT_FILENO) != STDOUT_FILENO) - return glnx_null_throw_errno_prefix (error, - "Unable to make fd %d a copy of fd %d", - STDOUT_FILENO, STDERR_FILENO); - - original_stdout = fdopen (original_stdout_fd, "w"); - - if (original_stdout == NULL) - return glnx_null_throw_errno_prefix (error, - "Unable to create a stdio wrapper for fd %d", - original_stdout_fd); - else - original_stdout_fd = -1; /* ownership taken, do not close */ - - return g_steal_pointer (&original_stdout); -} - /** * pv_async_signal_safe_error: * @message: A human-readable message diff --git a/pressure-vessel/utils.h b/pressure-vessel/utils.h index 2e8ec6744027a7f96f5a29866a311563ffd6e694..3809104722f8c3475c3160270e14e5ec695ae9f8 100644 --- a/pressure-vessel/utils.h +++ b/pressure-vessel/utils.h @@ -57,8 +57,6 @@ gpointer pv_hash_table_get_arbitrary_key (GHashTable *table); gboolean pv_boolean_environment (const gchar *name, gboolean def); -FILE *pv_divert_stdout_to_stderr (GError **error); - void pv_async_signal_safe_error (const char *message, int exit_status) G_GNUC_NORETURN; diff --git a/pressure-vessel/wrap.c b/pressure-vessel/wrap.c index 831dabca34e7d3c2e35dbef34c6a3ca94ad22714..471560de161eeedd9bdad8e5ab7b9cac79876ccc 100644 --- a/pressure-vessel/wrap.c +++ b/pressure-vessel/wrap.c @@ -30,6 +30,7 @@ #include <stdlib.h> #include "steam-runtime-tools/glib-backports-internal.h" +#include "steam-runtime-tools/utils-internal.h" #include "libglnx/libglnx.h" #include "bwrap.h" @@ -1277,7 +1278,7 @@ main (int argc, goto out; } - original_stdout = pv_divert_stdout_to_stderr (error); + original_stdout = _srt_divert_stdout_to_stderr (error); if (original_stdout == NULL) { diff --git a/steam-runtime-tools/meson.build b/steam-runtime-tools/meson.build index eec30738c7f8eea4d68824a23af33ee7d34ce029..86e8b85cceaf0df574ade38a861e36b48931d867 100644 --- a/steam-runtime-tools/meson.build +++ b/steam-runtime-tools/meson.build @@ -105,6 +105,7 @@ libsteamrt = library( gio_unix, glib, gobject, + libglnx_dep, json_glib, ], objects : [libsteamrt_static.extract_all_objects()], diff --git a/steam-runtime-tools/utils-internal.h b/steam-runtime-tools/utils-internal.h index 16bfa423fa1919ff125b9699439b8050d95cc82f..308e60a1b9ec084a34820ab3d0ae549ae775e423 100644 --- a/steam-runtime-tools/utils-internal.h +++ b/steam-runtime-tools/utils-internal.h @@ -26,6 +26,8 @@ #pragma once +#include <stdio.h> + #include <glib.h> #include <json-glib/json-glib.h> @@ -83,3 +85,5 @@ gchar ** _srt_json_array_to_strv (JsonObject *json_obj, const gchar *array_member); gboolean _srt_rm_rf (const char *directory); + +FILE *_srt_divert_stdout_to_stderr (GError **error); diff --git a/steam-runtime-tools/utils.c b/steam-runtime-tools/utils.c index 425de4faaebe0b61fa4d11f03bc022a5bb71c794..cd059711b13c33d3820ee7a33a99befa83287921 100644 --- a/steam-runtime-tools/utils.c +++ b/steam-runtime-tools/utils.c @@ -805,3 +805,60 @@ _srt_json_array_to_strv (JsonObject *json_obj, return ret; } + +/* + * _srt_divert_stdout_to_stderr: + * @error: Used to raise an error on failure + * + * Duplicate file descriptors so that functions that would write to + * `stdout` instead write to a copy of the original `stderr`. Return + * a file handle that can be used to print structured output to the + * original `stdout`. + * + * Returns: (transfer full): A libc file handle for the original `stdout`, + * or %NULL on error. Free with `fclose()`. + */ +FILE * +_srt_divert_stdout_to_stderr (GError **error) +{ + g_autoptr(FILE) original_stdout = NULL; + glnx_autofd int original_stdout_fd = -1; + int flags; + + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + /* Duplicate the original stdout so that we still have a way to write + * machine-readable output. */ + original_stdout_fd = dup (STDOUT_FILENO); + + if (original_stdout_fd < 0) + return glnx_null_throw_errno_prefix (error, + "Unable to duplicate fd %d", + STDOUT_FILENO); + + flags = fcntl (original_stdout_fd, F_GETFD, 0); + + if (flags < 0) + return glnx_null_throw_errno_prefix (error, + "Unable to get flags of new fd"); + + fcntl (original_stdout_fd, F_SETFD, flags|FD_CLOEXEC); + + /* If something like g_debug writes to stdout, make it come out of + * our original stderr. */ + if (dup2 (STDERR_FILENO, STDOUT_FILENO) != STDOUT_FILENO) + return glnx_null_throw_errno_prefix (error, + "Unable to make fd %d a copy of fd %d", + STDOUT_FILENO, STDERR_FILENO); + + original_stdout = fdopen (original_stdout_fd, "w"); + + if (original_stdout == NULL) + return glnx_null_throw_errno_prefix (error, + "Unable to create a stdio wrapper for fd %d", + original_stdout_fd); + else + original_stdout_fd = -1; /* ownership taken, do not close */ + + return g_steal_pointer (&original_stdout); +} diff --git a/tests/adverb.c b/tests/adverb.c index 3928eda843a2a0c327187e35c921bf10ab184d0f..134c0849e5648795459ba86e907eafa33535922c 100644 --- a/tests/adverb.c +++ b/tests/adverb.c @@ -34,6 +34,7 @@ #include <gio/gio.h> #include "steam-runtime-tools/glib-backports-internal.h" +#include "steam-runtime-tools/utils-internal.h" static gboolean opt_print_version = FALSE; static gboolean opt_ignore_sigchld = FALSE; @@ -65,56 +66,20 @@ static GOptionEntry options[] = { NULL } }; -/* Return the original stdout fd. */ -static int -divert_stdout_to_stderr (GError **error) +static gboolean +put_back_original_stdout (FILE *original_stdout, + GError **error) { - int original_stdout_fd; - - /* Duplicate the original stdout so that we still have a way to write - * machine-readable output. */ - original_stdout_fd = dup (STDOUT_FILENO); + int original_stdout_fd = fileno (original_stdout); if (original_stdout_fd < 0) - { - int saved_errno = errno; - - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (saved_errno), - "Unable to duplicate fd %d: %s", - STDOUT_FILENO, g_strerror (saved_errno)); - return -1; - } - - /* If something like g_debug writes to stdout, make it come out of - * our original stderr. */ - if (dup2 (STDERR_FILENO, STDOUT_FILENO) != STDOUT_FILENO) - { - int saved_errno = errno; - - close (original_stdout_fd); - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (saved_errno), - "Unable to make fd %d a copy of fd %d: %s", - STDOUT_FILENO, STDERR_FILENO, g_strerror (saved_errno)); - return -1; - } + return glnx_throw_errno_prefix (error, + "Unable to get fileno of original stdout"); - return original_stdout_fd; -} - -static gboolean -put_back_original_stdout (int original_stdout_fd, - GError **error) -{ if (dup2 (original_stdout_fd, STDOUT_FILENO) != STDOUT_FILENO) - { - int saved_errno = errno; - - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (saved_errno), - "Unable to make fd %d a copy of fd %d: %s", - STDOUT_FILENO, original_stdout_fd, - g_strerror (saved_errno)); - return FALSE; - } + return glnx_throw_errno_prefix (error, + "Unable to make fd %d a copy of fd %d", + STDOUT_FILENO, original_stdout_fd); return TRUE; } @@ -124,7 +89,7 @@ main (int argc, char *argv[]) { GError *local_error = NULL; - int original_stdout_fd; + FILE *original_stdout = NULL; int ret = EX_USAGE; char **command_and_args; int saved_errno; @@ -158,9 +123,9 @@ main (int argc, goto out; } - original_stdout_fd = divert_stdout_to_stderr (&local_error); + original_stdout = _srt_divert_stdout_to_stderr (&local_error); - if (original_stdout_fd < 0) + if (original_stdout == NULL) { ret = EX_OSERR; goto out; @@ -352,7 +317,7 @@ main (int argc, } } - if (!put_back_original_stdout (original_stdout_fd, &local_error)) + if (!put_back_original_stdout (original_stdout, &local_error)) goto out; if (command_and_args == NULL) diff --git a/tests/meson.build b/tests/meson.build index 6f08fa9ddfc7ade04bc7ca5f3a6f2057e3bb87be..fbae1660f7930b117c52d7ca0acfb55cf769fb42 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -125,7 +125,7 @@ endforeach executable( 'adverb', 'adverb.c', - dependencies : [glib, gio, gio_unix, libglnx_dep], + dependencies : [glib, gio, gio_unix, libglnx_dep, json_glib, libsteamrt_dep], include_directories : project_include_dirs, install : get_option('installed_tests'), install_dir : tests_dir, diff --git a/tests/pressure-vessel/helper.c b/tests/pressure-vessel/helper.c index 63ff8b58acd037904d8820d7bc13970db9d2c70e..31a8de2f399b03a49372a7477751faf27255b079 100644 --- a/tests/pressure-vessel/helper.c +++ b/tests/pressure-vessel/helper.c @@ -30,6 +30,7 @@ #include <glib/gstdio.h> #include "steam-runtime-tools/glib-backports-internal.h" +#include "steam-runtime-tools/utils-internal.h" #include "libglnx/libglnx.h" #include "utils.h" @@ -40,7 +41,7 @@ try_divert_stdout (void) g_autoptr(GError) error = NULL; g_autoptr(FILE) original_stdout = NULL; - original_stdout = pv_divert_stdout_to_stderr (&error); + original_stdout = _srt_divert_stdout_to_stderr (&error); g_assert_no_error (error); g_setenv ("G_MESSAGES_DEBUG", "all", TRUE); diff --git a/tests/pressure-vessel/meson.build b/tests/pressure-vessel/meson.build index f60a2e77b5746a9724626ff033d0a304d7a6f67e..9fb290ce73bf461cc0cdcd7b8b0beb715f09bc5a 100644 --- a/tests/pressure-vessel/meson.build +++ b/tests/pressure-vessel/meson.build @@ -157,6 +157,7 @@ foreach helper : helpers ], dependencies : [ gio_unix, + json_glib, libglnx_dep, ], link_with : [