LCOV - code coverage report
Current view: top level - glib - glib-unix.c (source / functions) Coverage Total Hit
Test: unnamed Lines: 58.3 % 156 91
Test Date: 2025-03-04 05:20:05 Functions: 73.7 % 19 14
Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* GLIB - Library of useful routines for C programming
       2                 :             :  * Copyright 2000-2022 Red Hat, Inc.
       3                 :             :  * Copyright 2006-2007 Matthias Clasen
       4                 :             :  * Copyright 2006 Padraig O'Briain
       5                 :             :  * Copyright 2007 Lennart Poettering
       6                 :             :  * Copyright 2018-2022 Endless OS Foundation, LLC
       7                 :             :  * Copyright 2018 Peter Wu
       8                 :             :  * Copyright 2019 Ting-Wei Lan
       9                 :             :  * Copyright 2019 Sebastian Schwarz
      10                 :             :  * Copyright 2020 Matt Rose
      11                 :             :  * Copyright 2021 Casper Dik
      12                 :             :  * Copyright 2022 Alexander Richardson
      13                 :             :  * Copyright 2022 Ray Strode
      14                 :             :  * Copyright 2022 Thomas Haller
      15                 :             :  * Copyright 2023-2024 Collabora Ltd.
      16                 :             :  * Copyright 2023 Sebastian Wilhelmi
      17                 :             :  * Copyright 2023 CaiJingLong
      18                 :             :  *
      19                 :             :  * glib-unix.c: UNIX specific API wrappers and convenience functions
      20                 :             :  *
      21                 :             :  * SPDX-License-Identifier: LGPL-2.1-or-later
      22                 :             :  *
      23                 :             :  * This library is free software; you can redistribute it and/or
      24                 :             :  * modify it under the terms of the GNU Lesser General Public
      25                 :             :  * License as published by the Free Software Foundation; either
      26                 :             :  * version 2.1 of the License, or (at your option) any later version.
      27                 :             :  *
      28                 :             :  * This library is distributed in the hope that it will be useful,
      29                 :             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      30                 :             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      31                 :             :  * Lesser General Public License for more details.
      32                 :             :  *
      33                 :             :  * You should have received a copy of the GNU Lesser General Public
      34                 :             :  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
      35                 :             :  *
      36                 :             :  * Authors: Colin Walters <walters@verbum.org>
      37                 :             :  */
      38                 :             : 
      39                 :             : #include "config.h"
      40                 :             : 
      41                 :             : #include "glib-private.h"
      42                 :             : #include "glib-unix.h"
      43                 :             : #include "glib-unixprivate.h"
      44                 :             : #include "gmain-internal.h"
      45                 :             : 
      46                 :             : #include <dirent.h>
      47                 :             : #include <errno.h>
      48                 :             : #include <fcntl.h>
      49                 :             : #include <stdlib.h>   /* for fdwalk */
      50                 :             : #include <string.h>
      51                 :             : #include <sys/types.h>
      52                 :             : #include <pwd.h>
      53                 :             : #include <unistd.h>
      54                 :             : 
      55                 :             : #if defined(__linux__) || defined(__DragonFly__)
      56                 :             : #include <sys/syscall.h>  /* for syscall and SYS_getdents64 */
      57                 :             : #endif
      58                 :             : 
      59                 :             : #ifdef HAVE_SYS_RESOURCE_H
      60                 :             : #include <sys/resource.h>
      61                 :             : #endif /* HAVE_SYS_RESOURCE_H */
      62                 :             : 
      63                 :             : #if defined(__APPLE__) && defined(HAVE_LIBPROC_H)
      64                 :             : #include <libproc.h>
      65                 :             : #include <sys/proc_info.h>
      66                 :             : #endif
      67                 :             : 
      68                 :             : G_STATIC_ASSERT (sizeof (ssize_t) == GLIB_SIZEOF_SSIZE_T);
      69                 :             : G_STATIC_ASSERT (G_ALIGNOF (gssize) == G_ALIGNOF (ssize_t));
      70                 :             : G_STATIC_ASSERT (G_SIGNEDNESS_OF (ssize_t) == 1);
      71                 :             : 
      72                 :             : G_STATIC_ASSERT (sizeof (GPid) == sizeof (pid_t));
      73                 :             : G_STATIC_ASSERT (G_ALIGNOF (GPid) == G_ALIGNOF (pid_t));
      74                 :             : /* It's platform-dependent whether pid_t is signed, so no assertion */
      75                 :             : 
      76                 :             : /* If this assertion fails, then the ABI of g_unix_open_pipe() would be
      77                 :             :  * ambiguous on this platform.
      78                 :             :  * On Linux, usually O_NONBLOCK == 04000 and FD_CLOEXEC == 1, but the same
      79                 :             :  * might not be true everywhere. */
      80                 :             : G_STATIC_ASSERT (O_NONBLOCK != FD_CLOEXEC);
      81                 :             : 
      82                 :           7 : G_DEFINE_QUARK (g-unix-error-quark, g_unix_error)
      83                 :             : 
      84                 :             : static gboolean
      85                 :           3 : g_unix_set_error_from_errno (GError **error,
      86                 :             :                              gint     saved_errno)
      87                 :             : {
      88                 :           3 :   g_set_error_literal (error,
      89                 :             :                        G_UNIX_ERROR,
      90                 :             :                        0,
      91                 :             :                        g_strerror (saved_errno));
      92                 :           3 :   errno = saved_errno;
      93                 :           3 :   return FALSE;
      94                 :             : }
      95                 :             : 
      96                 :             : /**
      97                 :             :  * g_unix_open_pipe:
      98                 :             :  * @fds: (array fixed-size=2): Array of two integers
      99                 :             :  * @flags: Bitfield of file descriptor flags, as for fcntl()
     100                 :             :  * @error: a #GError
     101                 :             :  *
     102                 :             :  * Similar to the UNIX pipe() call, but on modern systems like Linux
     103                 :             :  * uses the pipe2() system call, which atomically creates a pipe with
     104                 :             :  * the configured flags.
     105                 :             :  *
     106                 :             :  * As of GLib 2.78, the supported flags are `O_CLOEXEC`/`FD_CLOEXEC` (see below)
     107                 :             :  * and `O_NONBLOCK`. Prior to GLib 2.78, only `FD_CLOEXEC` was supported — if
     108                 :             :  * you wanted to configure `O_NONBLOCK` then that had to be done separately with
     109                 :             :  * `fcntl()`.
     110                 :             :  *
     111                 :             :  * Since GLib 2.80, the constants %G_UNIX_PIPE_END_READ and
     112                 :             :  * %G_UNIX_PIPE_END_WRITE can be used as mnemonic indexes in @fds.
     113                 :             :  *
     114                 :             :  * It is a programmer error to call this function with unsupported flags, and a
     115                 :             :  * critical warning will be raised.
     116                 :             :  *
     117                 :             :  * As of GLib 2.78, it is preferred to pass `O_CLOEXEC` in, rather than
     118                 :             :  * `FD_CLOEXEC`, as that matches the underlying `pipe()` API more closely. Prior
     119                 :             :  * to 2.78, only `FD_CLOEXEC` was supported. Support for `FD_CLOEXEC` may be
     120                 :             :  * deprecated and removed in future.
     121                 :             :  *
     122                 :             :  * Returns: %TRUE on success, %FALSE if not (and errno will be set).
     123                 :             :  *
     124                 :             :  * Since: 2.30
     125                 :             :  */
     126                 :             : gboolean
     127                 :        2870 : g_unix_open_pipe (int     *fds,
     128                 :             :                   int      flags,
     129                 :             :                   GError **error)
     130                 :             : {
     131                 :             :   /* We only support O_CLOEXEC/FD_CLOEXEC and O_NONBLOCK */
     132                 :        2870 :   g_return_val_if_fail ((flags & (O_CLOEXEC | FD_CLOEXEC | O_NONBLOCK)) == flags, FALSE);
     133                 :             : 
     134                 :             : #if O_CLOEXEC != FD_CLOEXEC && !defined(G_DISABLE_CHECKS)
     135                 :        2870 :   if (flags & FD_CLOEXEC)
     136                 :           1 :     g_debug ("g_unix_open_pipe() called with FD_CLOEXEC; please migrate to using O_CLOEXEC instead");
     137                 :             : #endif
     138                 :             : 
     139                 :        2870 :   if (!g_unix_open_pipe_internal (fds,
     140                 :        2870 :                                   (flags & (O_CLOEXEC | FD_CLOEXEC)) != 0,
     141                 :        2870 :                                   (flags & O_NONBLOCK) != 0))
     142                 :           0 :     return g_unix_set_error_from_errno (error, errno);
     143                 :             : 
     144                 :        2870 :   return TRUE;
     145                 :             : }
     146                 :             : 
     147                 :             : /**
     148                 :             :  * g_unix_set_fd_nonblocking:
     149                 :             :  * @fd: A file descriptor
     150                 :             :  * @nonblock: If %TRUE, set the descriptor to be non-blocking
     151                 :             :  * @error: a #GError
     152                 :             :  *
     153                 :             :  * Control the non-blocking state of the given file descriptor,
     154                 :             :  * according to @nonblock. On most systems this uses %O_NONBLOCK, but
     155                 :             :  * on some older ones may use %O_NDELAY.
     156                 :             :  *
     157                 :             :  * Returns: %TRUE if successful
     158                 :             :  *
     159                 :             :  * Since: 2.30
     160                 :             :  */
     161                 :             : gboolean
     162                 :         499 : g_unix_set_fd_nonblocking (gint       fd,
     163                 :             :                            gboolean   nonblock,
     164                 :             :                            GError   **error)
     165                 :             : {
     166                 :             : #ifdef F_GETFL
     167                 :             :   glong fcntl_flags;
     168                 :         499 :   fcntl_flags = fcntl (fd, F_GETFL);
     169                 :             : 
     170                 :         499 :   if (fcntl_flags == -1)
     171                 :           1 :     return g_unix_set_error_from_errno (error, errno);
     172                 :             : 
     173                 :         498 :   if (nonblock)
     174                 :         497 :     fcntl_flags |= O_NONBLOCK;
     175                 :             :   else
     176                 :           1 :     fcntl_flags &= ~O_NONBLOCK;
     177                 :             : 
     178                 :         498 :   if (fcntl (fd, F_SETFL, fcntl_flags) == -1)
     179                 :           0 :     return g_unix_set_error_from_errno (error, errno);
     180                 :         498 :   return TRUE;
     181                 :             : #else
     182                 :             :   return g_unix_set_error_from_errno (error, EINVAL);
     183                 :             : #endif
     184                 :             : }
     185                 :             : 
     186                 :             : /**
     187                 :             :  * g_unix_signal_source_new:
     188                 :             :  * @signum: A signal number
     189                 :             :  *
     190                 :             :  * Create a #GSource that will be dispatched upon delivery of the UNIX
     191                 :             :  * signal @signum.  In GLib versions before 2.36, only `SIGHUP`, `SIGINT`,
     192                 :             :  * `SIGTERM` can be monitored.  In GLib 2.36, `SIGUSR1` and `SIGUSR2`
     193                 :             :  * were added. In GLib 2.54, `SIGWINCH` was added.
     194                 :             :  *
     195                 :             :  * Note that unlike the UNIX default, all sources which have created a
     196                 :             :  * watch will be dispatched, regardless of which underlying thread
     197                 :             :  * invoked g_unix_signal_source_new().
     198                 :             :  *
     199                 :             :  * For example, an effective use of this function is to handle `SIGTERM`
     200                 :             :  * cleanly; flushing any outstanding files, and then calling
     201                 :             :  * g_main_loop_quit().  It is not safe to do any of this from a regular
     202                 :             :  * UNIX signal handler; such a handler may be invoked while malloc() or
     203                 :             :  * another library function is running, causing reentrancy issues if the
     204                 :             :  * handler attempts to use those functions.  None of the GLib/GObject
     205                 :             :  * API is safe against this kind of reentrancy.
     206                 :             :  *
     207                 :             :  * The interaction of this source when combined with native UNIX
     208                 :             :  * functions like sigprocmask() is not defined.
     209                 :             :  *
     210                 :             :  * The source will not initially be associated with any #GMainContext
     211                 :             :  * and must be added to one with g_source_attach() before it will be
     212                 :             :  * executed.
     213                 :             :  *
     214                 :             :  * Returns: A newly created #GSource
     215                 :             :  *
     216                 :             :  * Since: 2.30
     217                 :             :  */
     218                 :             : GSource *
     219                 :          32 : g_unix_signal_source_new (int signum)
     220                 :             : {
     221                 :          32 :   g_return_val_if_fail (signum == SIGHUP || signum == SIGINT || signum == SIGTERM ||
     222                 :             :                         signum == SIGUSR1 || signum == SIGUSR2 || signum == SIGWINCH,
     223                 :             :                         NULL);
     224                 :             : 
     225                 :          32 :   return _g_main_create_unix_signal_watch (signum);
     226                 :             : }
     227                 :             : 
     228                 :             : /**
     229                 :             :  * g_unix_signal_add_full: (rename-to g_unix_signal_add)
     230                 :             :  * @priority: the priority of the signal source. Typically this will be in
     231                 :             :  *            the range between %G_PRIORITY_DEFAULT and %G_PRIORITY_HIGH.
     232                 :             :  * @signum: Signal number
     233                 :             :  * @handler: Callback
     234                 :             :  * @user_data: Data for @handler
     235                 :             :  * @notify: #GDestroyNotify for @handler
     236                 :             :  *
     237                 :             :  * A convenience function for g_unix_signal_source_new(), which
     238                 :             :  * attaches to the default #GMainContext.  You can remove the watch
     239                 :             :  * using g_source_remove().
     240                 :             :  *
     241                 :             :  * Returns: An ID (greater than 0) for the event source
     242                 :             :  *
     243                 :             :  * Since: 2.30
     244                 :             :  */
     245                 :             : guint
     246                 :          29 : g_unix_signal_add_full (int            priority,
     247                 :             :                         int            signum,
     248                 :             :                         GSourceFunc    handler,
     249                 :             :                         gpointer       user_data,
     250                 :             :                         GDestroyNotify notify)
     251                 :             : {
     252                 :             :   guint id;
     253                 :             :   GSource *source;
     254                 :             : 
     255                 :          29 :   source = g_unix_signal_source_new (signum);
     256                 :             : 
     257                 :          29 :   if (priority != G_PRIORITY_DEFAULT)
     258                 :           0 :     g_source_set_priority (source, priority);
     259                 :             : 
     260                 :          29 :   g_source_set_callback (source, handler, user_data, notify);
     261                 :          29 :   id = g_source_attach (source, NULL);
     262                 :          29 :   g_source_unref (source);
     263                 :             : 
     264                 :          29 :   return id;
     265                 :             : }
     266                 :             : 
     267                 :             : /**
     268                 :             :  * g_unix_signal_add:
     269                 :             :  * @signum: Signal number
     270                 :             :  * @handler: Callback
     271                 :             :  * @user_data: Data for @handler
     272                 :             :  *
     273                 :             :  * A convenience function for g_unix_signal_source_new(), which
     274                 :             :  * attaches to the default #GMainContext.  You can remove the watch
     275                 :             :  * using g_source_remove().
     276                 :             :  *
     277                 :             :  * Returns: An ID (greater than 0) for the event source
     278                 :             :  *
     279                 :             :  * Since: 2.30
     280                 :             :  */
     281                 :             : guint
     282                 :          29 : g_unix_signal_add (int         signum,
     283                 :             :                    GSourceFunc handler,
     284                 :             :                    gpointer    user_data)
     285                 :             : {
     286                 :          29 :   return g_unix_signal_add_full (G_PRIORITY_DEFAULT, signum, handler, user_data, NULL);
     287                 :             : }
     288                 :             : 
     289                 :             : typedef struct
     290                 :             : {
     291                 :             :   GSource source;
     292                 :             : 
     293                 :             :   gint     fd;
     294                 :             :   gpointer tag;
     295                 :             : } GUnixFDSource;
     296                 :             : 
     297                 :             : static gboolean
     298                 :      262659 : g_unix_fd_source_dispatch (GSource     *source,
     299                 :             :                            GSourceFunc  callback,
     300                 :             :                            gpointer     user_data)
     301                 :             : {
     302                 :      262659 :   GUnixFDSource *fd_source = (GUnixFDSource *) source;
     303                 :      262659 :   GUnixFDSourceFunc func = (GUnixFDSourceFunc) callback;
     304                 :             : 
     305                 :      262659 :   if (!callback)
     306                 :             :     {
     307                 :           1 :       g_warning ("GUnixFDSource dispatched without callback. "
     308                 :             :                  "You must call g_source_set_callback().");
     309                 :           1 :       return FALSE;
     310                 :             :     }
     311                 :             : 
     312                 :      262658 :   return (* func) (fd_source->fd, g_source_query_unix_fd (source, fd_source->tag), user_data);
     313                 :             : }
     314                 :             : 
     315                 :             : GSourceFuncs g_unix_fd_source_funcs = {
     316                 :             :   NULL, NULL, g_unix_fd_source_dispatch, NULL, NULL, NULL
     317                 :             : };
     318                 :             : 
     319                 :             : /**
     320                 :             :  * g_unix_fd_source_new:
     321                 :             :  * @fd: a file descriptor
     322                 :             :  * @condition: I/O conditions to watch for on @fd
     323                 :             :  *
     324                 :             :  * Creates a #GSource to watch for a particular I/O condition on a file
     325                 :             :  * descriptor.
     326                 :             :  *
     327                 :             :  * The source will never close the @fd — you must do it yourself.
     328                 :             :  *
     329                 :             :  * Any callback attached to the returned #GSource must have type
     330                 :             :  * #GUnixFDSourceFunc.
     331                 :             :  *
     332                 :             :  * Returns: the newly created #GSource
     333                 :             :  *
     334                 :             :  * Since: 2.36
     335                 :             :  **/
     336                 :             : GSource *
     337                 :         628 : g_unix_fd_source_new (gint         fd,
     338                 :             :                       GIOCondition condition)
     339                 :             : {
     340                 :             :   GUnixFDSource *fd_source;
     341                 :             :   GSource *source;
     342                 :             : 
     343                 :         628 :   source = g_source_new (&g_unix_fd_source_funcs, sizeof (GUnixFDSource));
     344                 :         628 :   fd_source = (GUnixFDSource *) source;
     345                 :             : 
     346                 :         628 :   fd_source->fd = fd;
     347                 :         628 :   fd_source->tag = g_source_add_unix_fd (source, fd, condition);
     348                 :             : 
     349                 :         628 :   return source;
     350                 :             : }
     351                 :             : 
     352                 :             : /**
     353                 :             :  * g_unix_fd_add_full:
     354                 :             :  * @priority: the priority of the source
     355                 :             :  * @fd: a file descriptor
     356                 :             :  * @condition: IO conditions to watch for on @fd
     357                 :             :  * @function: a #GUnixFDSourceFunc
     358                 :             :  * @user_data: data to pass to @function
     359                 :             :  * @notify: function to call when the idle is removed, or %NULL
     360                 :             :  *
     361                 :             :  * Sets a function to be called when the IO condition, as specified by
     362                 :             :  * @condition becomes true for @fd.
     363                 :             :  *
     364                 :             :  * This is the same as g_unix_fd_add(), except that it allows you to
     365                 :             :  * specify a non-default priority and a provide a #GDestroyNotify for
     366                 :             :  * @user_data.
     367                 :             :  *
     368                 :             :  * Returns: the ID (greater than 0) of the event source
     369                 :             :  *
     370                 :             :  * Since: 2.36
     371                 :             :  **/
     372                 :             : guint
     373                 :           2 : g_unix_fd_add_full (gint              priority,
     374                 :             :                     gint              fd,
     375                 :             :                     GIOCondition      condition,
     376                 :             :                     GUnixFDSourceFunc function,
     377                 :             :                     gpointer          user_data,
     378                 :             :                     GDestroyNotify    notify)
     379                 :             : {
     380                 :             :   GSource *source;
     381                 :             :   guint id;
     382                 :             : 
     383                 :           2 :   g_return_val_if_fail (function != NULL, 0);
     384                 :             : 
     385                 :           2 :   source = g_unix_fd_source_new (fd, condition);
     386                 :             : 
     387                 :           2 :   if (priority != G_PRIORITY_DEFAULT)
     388                 :           1 :     g_source_set_priority (source, priority);
     389                 :             : 
     390                 :           2 :   g_source_set_callback (source, (GSourceFunc) function, user_data, notify);
     391                 :           2 :   id = g_source_attach (source, NULL);
     392                 :           2 :   g_source_unref (source);
     393                 :             : 
     394                 :           2 :   return id;
     395                 :             : }
     396                 :             : 
     397                 :             : /**
     398                 :             :  * g_unix_fd_add:
     399                 :             :  * @fd: a file descriptor
     400                 :             :  * @condition: IO conditions to watch for on @fd
     401                 :             :  * @function: a #GUnixFDSourceFunc
     402                 :             :  * @user_data: data to pass to @function
     403                 :             :  *
     404                 :             :  * Sets a function to be called when the IO condition, as specified by
     405                 :             :  * @condition becomes true for @fd.
     406                 :             :  *
     407                 :             :  * @function will be called when the specified IO condition becomes
     408                 :             :  * %TRUE.  The function is expected to clear whatever event caused the
     409                 :             :  * IO condition to become true and return %TRUE in order to be notified
     410                 :             :  * when it happens again.  If @function returns %FALSE then the watch
     411                 :             :  * will be cancelled.
     412                 :             :  *
     413                 :             :  * The return value of this function can be passed to g_source_remove()
     414                 :             :  * to cancel the watch at any time that it exists.
     415                 :             :  *
     416                 :             :  * The source will never close the fd -- you must do it yourself.
     417                 :             :  *
     418                 :             :  * Returns: the ID (greater than 0) of the event source
     419                 :             :  *
     420                 :             :  * Since: 2.36
     421                 :             :  **/
     422                 :             : guint
     423                 :           1 : g_unix_fd_add (gint              fd,
     424                 :             :                GIOCondition      condition,
     425                 :             :                GUnixFDSourceFunc function,
     426                 :             :                gpointer          user_data)
     427                 :             : {
     428                 :           1 :   return g_unix_fd_add_full (G_PRIORITY_DEFAULT, fd, condition, function, user_data, NULL);
     429                 :             : }
     430                 :             : 
     431                 :             : /**
     432                 :             :  * g_unix_get_passwd_entry:
     433                 :             :  * @user_name: the username to get the passwd file entry for
     434                 :             :  * @error: return location for a #GError, or %NULL
     435                 :             :  *
     436                 :             :  * Get the `passwd` file entry for the given @user_name using `getpwnam_r()`.
     437                 :             :  * This can fail if the given @user_name doesn’t exist.
     438                 :             :  *
     439                 :             :  * The returned `struct passwd` has been allocated using g_malloc() and should
     440                 :             :  * be freed using g_free(). The strings referenced by the returned struct are
     441                 :             :  * included in the same allocation, so are valid until the `struct passwd` is
     442                 :             :  * freed.
     443                 :             :  *
     444                 :             :  * This function is safe to call from multiple threads concurrently.
     445                 :             :  *
     446                 :             :  * You will need to include `pwd.h` to get the definition of `struct passwd`.
     447                 :             :  *
     448                 :             :  * Returns: (transfer full): passwd entry, or %NULL on error; free the returned
     449                 :             :  *    value with g_free()
     450                 :             :  * Since: 2.64
     451                 :             :  */
     452                 :             : struct passwd *
     453                 :           3 : g_unix_get_passwd_entry (const gchar  *user_name,
     454                 :             :                          GError      **error)
     455                 :             : {
     456                 :             :   struct passwd *passwd_file_entry;
     457                 :             :   struct
     458                 :             :     {
     459                 :             :       struct passwd pwd;
     460                 :             :       char string_buffer[];
     461                 :           3 :     } *buffer = NULL;
     462                 :           3 :   gsize string_buffer_size = 0;
     463                 :           3 :   GError *local_error = NULL;
     464                 :             : 
     465                 :           3 :   g_return_val_if_fail (user_name != NULL, NULL);
     466                 :           3 :   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
     467                 :             : 
     468                 :             : #ifdef _SC_GETPW_R_SIZE_MAX
     469                 :             :     {
     470                 :             :       /* Get the recommended buffer size */
     471                 :           3 :       glong string_buffer_size_long = sysconf (_SC_GETPW_R_SIZE_MAX);
     472                 :           3 :       if (string_buffer_size_long > 0)
     473                 :           3 :         string_buffer_size = string_buffer_size_long;
     474                 :             :     }
     475                 :             : #endif /* _SC_GETPW_R_SIZE_MAX */
     476                 :             : 
     477                 :             :   /* Default starting size. */
     478                 :           3 :   if (string_buffer_size == 0)
     479                 :           0 :     string_buffer_size = 64;
     480                 :             : 
     481                 :             :   do
     482                 :             :     {
     483                 :             :       int retval;
     484                 :             : 
     485                 :           3 :       g_free (buffer);
     486                 :             :       /* Allocate space for the `struct passwd`, and then a buffer for all its
     487                 :             :        * strings (whose size is @string_buffer_size, which increases in this
     488                 :             :        * loop until it’s big enough). Add 6 extra bytes to work around a bug in
     489                 :             :        * macOS < 10.3. See #156446.
     490                 :             :        */
     491                 :           3 :       buffer = g_malloc0 (sizeof (*buffer) + string_buffer_size + 6);
     492                 :             : 
     493                 :           3 :       retval = getpwnam_r (user_name, &buffer->pwd, buffer->string_buffer,
     494                 :             :                            string_buffer_size, &passwd_file_entry);
     495                 :             : 
     496                 :             :       /* Bail out if: the lookup was successful, or if the user id can't be
     497                 :             :        * found (should be pretty rare case actually), or if the buffer should be
     498                 :             :        * big enough and yet lookups are still not successful.
     499                 :             :        */
     500                 :           3 :       if (passwd_file_entry != NULL)
     501                 :             :         {
     502                 :             :           /* Success. */
     503                 :           1 :           break;
     504                 :             :         }
     505                 :           2 :       else if (retval == 0 ||
     506                 :           0 :           retval == ENOENT || retval == ESRCH ||
     507                 :           0 :           retval == EBADF || retval == EPERM)
     508                 :             :         {
     509                 :             :           /* Username not found. */
     510                 :           2 :           g_unix_set_error_from_errno (&local_error, retval);
     511                 :           2 :           break;
     512                 :             :         }
     513                 :           0 :       else if (retval == ERANGE)
     514                 :             :         {
     515                 :             :           /* Can’t allocate enough string buffer space. */
     516                 :           0 :           if (string_buffer_size > 32 * 1024)
     517                 :             :             {
     518                 :           0 :               g_unix_set_error_from_errno (&local_error, retval);
     519                 :           0 :               break;
     520                 :             :             }
     521                 :             : 
     522                 :           0 :           string_buffer_size *= 2;
     523                 :           0 :           continue;
     524                 :             :         }
     525                 :             :       else
     526                 :             :         {
     527                 :           0 :           g_unix_set_error_from_errno (&local_error, retval);
     528                 :           0 :           break;
     529                 :             :         }
     530                 :             :     }
     531                 :           0 :   while (passwd_file_entry == NULL);
     532                 :             : 
     533                 :           3 :   g_assert (passwd_file_entry == NULL ||
     534                 :             :             (gpointer) passwd_file_entry == (gpointer) buffer);
     535                 :             : 
     536                 :             :   /* Success or error. */
     537                 :           3 :   if (local_error != NULL)
     538                 :             :     {
     539                 :           2 :       g_clear_pointer (&buffer, g_free);
     540                 :           2 :       g_propagate_error (error, g_steal_pointer (&local_error));
     541                 :             :     }
     542                 :             : 
     543                 :           3 :   return (struct passwd *) g_steal_pointer (&buffer);
     544                 :             : }
     545                 :             : 
     546                 :             : /* This function is called between fork() and exec() and hence must be
     547                 :             :  * async-signal-safe (see signal-safety(7)). */
     548                 :             : static int
     549                 :           0 : set_cloexec (void *data, gint fd)
     550                 :             : {
     551                 :           0 :   if (fd >= GPOINTER_TO_INT (data))
     552                 :           0 :     fcntl (fd, F_SETFD, FD_CLOEXEC);
     553                 :             : 
     554                 :           0 :   return 0;
     555                 :             : }
     556                 :             : 
     557                 :             : /* fdwalk()-compatible callback to close a fd for non-compliant
     558                 :             :  * implementations of fdwalk() that potentially pass already
     559                 :             :  * closed fds.
     560                 :             :  *
     561                 :             :  * It is not an error to pass an invalid fd to this function.
     562                 :             :  *
     563                 :             :  * This function is called between fork() and exec() and hence must be
     564                 :             :  * async-signal-safe (see signal-safety(7)).
     565                 :             :  */
     566                 :             : G_GNUC_UNUSED static int
     567                 :           0 : close_func_with_invalid_fds (void *data, int fd)
     568                 :             : {
     569                 :             :   /* We use close and not g_close here because on some platforms, we
     570                 :             :    * don't know how to close only valid, open file descriptors, so we
     571                 :             :    * have to pass bad fds to close too. g_close warns if given a bad
     572                 :             :    * fd.
     573                 :             :    *
     574                 :             :    * This function returns no error, because there is nothing that the caller
     575                 :             :    * could do with that information. That is even the case for EINTR. See
     576                 :             :    * g_close() about the specialty of EINTR and why that is correct.
     577                 :             :    * If g_close() ever gets extended to handle EINTR specially, then this place
     578                 :             :    * should get updated to do the same handling.
     579                 :             :    */
     580                 :           0 :   if (fd >= GPOINTER_TO_INT (data))
     581                 :           0 :     close (fd);
     582                 :             : 
     583                 :           0 :   return 0;
     584                 :             : }
     585                 :             : 
     586                 :             : #ifdef __linux__
     587                 :             : struct linux_dirent64
     588                 :             : {
     589                 :             :   guint64        d_ino;    /* 64-bit inode number */
     590                 :             :   guint64        d_off;    /* 64-bit offset to next structure */
     591                 :             :   unsigned short d_reclen; /* Size of this dirent */
     592                 :             :   unsigned char  d_type;   /* File type */
     593                 :             :   char           d_name[]; /* Filename (null-terminated) */
     594                 :             : };
     595                 :             : 
     596                 :             : /* This function is called between fork() and exec() and hence must be
     597                 :             :  * async-signal-safe (see signal-safety(7)). */
     598                 :             : static gint
     599                 :           0 : filename_to_fd (const char *p)
     600                 :             : {
     601                 :             :   char c;
     602                 :           0 :   int fd = 0;
     603                 :           0 :   const int cutoff = G_MAXINT / 10;
     604                 :           0 :   const int cutlim = G_MAXINT % 10;
     605                 :             : 
     606                 :           0 :   if (*p == '\0')
     607                 :           0 :     return -1;
     608                 :             : 
     609                 :           0 :   while ((c = *p++) != '\0')
     610                 :             :     {
     611                 :           0 :       if (c < '0' || c > '9')
     612                 :           0 :         return -1;
     613                 :           0 :       c -= '0';
     614                 :             : 
     615                 :             :       /* Check for overflow. */
     616                 :           0 :       if (fd > cutoff || (fd == cutoff && c > cutlim))
     617                 :           0 :         return -1;
     618                 :             : 
     619                 :           0 :       fd = fd * 10 + c;
     620                 :             :     }
     621                 :             : 
     622                 :           0 :   return fd;
     623                 :             : }
     624                 :             : #endif
     625                 :             : 
     626                 :             : static int safe_fdwalk_with_invalid_fds (int (*cb)(void *data, int fd), void *data);
     627                 :             : 
     628                 :             : /* This function is called between fork() and exec() and hence must be
     629                 :             :  * async-signal-safe (see signal-safety(7)). */
     630                 :             : static int
     631                 :           0 : safe_fdwalk (int (*cb)(void *data, int fd), void *data)
     632                 :             : {
     633                 :             : #if 0
     634                 :             :   /* Use fdwalk function provided by the system if it is known to be
     635                 :             :    * async-signal safe.
     636                 :             :    *
     637                 :             :    * Currently there are no operating systems known to provide a safe
     638                 :             :    * implementation, so this section is not used for now.
     639                 :             :    */
     640                 :             :   return fdwalk (cb, data);
     641                 :             : #else
     642                 :             :   /* Fallback implementation of fdwalk. It should be async-signal safe, but it
     643                 :             :    * may fail on non-Linux operating systems. See safe_fdwalk_with_invalid_fds
     644                 :             :    * for a slower alternative.
     645                 :             :    */
     646                 :             : 
     647                 :             : #ifdef __linux__
     648                 :             :   gint fd;
     649                 :           0 :   gint res = 0;
     650                 :             : 
     651                 :             :   /* Avoid use of opendir/closedir since these are not async-signal-safe. */
     652                 :           0 :   int dir_fd = open ("/proc/self/fd", O_RDONLY | O_DIRECTORY);
     653                 :           0 :   if (dir_fd >= 0)
     654                 :             :     {
     655                 :             :       /* buf needs to be aligned correctly to receive linux_dirent64.
     656                 :             :        * C11 has _Alignof for this purpose, but for now a
     657                 :             :        * union serves the same purpose. */
     658                 :             :       union
     659                 :             :       {
     660                 :             :         char buf[4096];
     661                 :             :         struct linux_dirent64 alignment;
     662                 :             :       } u;
     663                 :             :       int pos, nread;
     664                 :             :       struct linux_dirent64 *de;
     665                 :             : 
     666                 :           0 :       while ((nread = syscall (SYS_getdents64, dir_fd, u.buf, sizeof (u.buf))) > 0)
     667                 :             :         {
     668                 :           0 :           for (pos = 0; pos < nread; pos += de->d_reclen)
     669                 :             :             {
     670                 :           0 :               de = (struct linux_dirent64 *) (u.buf + pos);
     671                 :             : 
     672                 :           0 :               fd = filename_to_fd (de->d_name);
     673                 :           0 :               if (fd < 0 || fd == dir_fd)
     674                 :           0 :                   continue;
     675                 :             : 
     676                 :           0 :               if ((res = cb (data, fd)) != 0)
     677                 :           0 :                   break;
     678                 :             :             }
     679                 :             :         }
     680                 :             : 
     681                 :           0 :       g_close (dir_fd, NULL);
     682                 :           0 :       return res;
     683                 :             :     }
     684                 :             : 
     685                 :             :   /* If /proc is not mounted or not accessible we fail here and rely on
     686                 :             :    * safe_fdwalk_with_invalid_fds to fall back to the old
     687                 :             :    * rlimit trick. */
     688                 :             : 
     689                 :             : #endif
     690                 :             : 
     691                 :             : #if defined(__sun__) && defined(F_PREVFD) && defined(F_NEXTFD)
     692                 :             : /*
     693                 :             :  * Solaris 11.4 has a signal-safe way which allows
     694                 :             :  * us to find all file descriptors in a process.
     695                 :             :  *
     696                 :             :  * fcntl(fd, F_NEXTFD, maxfd)
     697                 :             :  * - returns the first allocated file descriptor <= maxfd  > fd.
     698                 :             :  *
     699                 :             :  * fcntl(fd, F_PREVFD)
     700                 :             :  * - return highest allocated file descriptor < fd.
     701                 :             :  */
     702                 :             :   gint open_max;
     703                 :             :   gint fd;
     704                 :             :   gint res = 0;
     705                 :             : 
     706                 :             :   open_max = fcntl (INT_MAX, F_PREVFD); /* find the maximum fd */
     707                 :             :   if (open_max < 0) /* No open files */
     708                 :             :     return 0;
     709                 :             : 
     710                 :             :   for (fd = -1; (fd = fcntl (fd, F_NEXTFD, open_max)) != -1; )
     711                 :             :     if ((res = cb (data, fd)) != 0 || fd == open_max)
     712                 :             :       break;
     713                 :             : 
     714                 :             :   return res;
     715                 :             : #endif
     716                 :             : 
     717                 :           0 :   return safe_fdwalk_with_invalid_fds (cb, data);
     718                 :             : #endif
     719                 :             : }
     720                 :             : 
     721                 :             : /* This function is called between fork() and exec() and hence must be
     722                 :             :  * async-signal-safe (see signal-safety(7)). */
     723                 :             : static int
     724                 :           0 : safe_fdwalk_with_invalid_fds (int (*cb)(void *data, int fd), void *data)
     725                 :             : {
     726                 :             :   /* Fallback implementation of fdwalk. It should be async-signal safe, but it
     727                 :             :    * may be slow, especially on systems allowing very high number of open file
     728                 :             :    * descriptors.
     729                 :             :    */
     730                 :           0 :   gint open_max = -1;
     731                 :             :   gint fd;
     732                 :           0 :   gint res = 0;
     733                 :             : 
     734                 :             : #if 0 && defined(HAVE_SYS_RESOURCE_H)
     735                 :             :   struct rlimit rl;
     736                 :             : 
     737                 :             :   /* Use getrlimit() function provided by the system if it is known to be
     738                 :             :    * async-signal safe.
     739                 :             :    *
     740                 :             :    * Currently there are no operating systems known to provide a safe
     741                 :             :    * implementation, so this section is not used for now.
     742                 :             :    */
     743                 :             :   if (getrlimit (RLIMIT_NOFILE, &rl) == 0 && rl.rlim_max != RLIM_INFINITY)
     744                 :             :     open_max = rl.rlim_max;
     745                 :             : #endif
     746                 :             : #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
     747                 :             :   /* Use sysconf() function provided by the system if it is known to be
     748                 :             :    * async-signal safe.
     749                 :             :    *
     750                 :             :    * FreeBSD: sysconf() is included in the list of async-signal safe functions
     751                 :             :    * found in https://man.freebsd.org/sigaction(2).
     752                 :             :    *
     753                 :             :    * OpenBSD: sysconf() is included in the list of async-signal safe functions
     754                 :             :    * found in https://man.openbsd.org/sigaction.2.
     755                 :             :    *
     756                 :             :    * Apple: sysconf() is included in the list of async-signal safe functions
     757                 :             :    * found in https://opensource.apple.com/source/xnu/xnu-517.12.7/bsd/man/man2/sigaction.2
     758                 :             :    */
     759                 :             :   if (open_max < 0)
     760                 :             :     open_max = sysconf (_SC_OPEN_MAX);
     761                 :             : #endif
     762                 :             :   /* Hardcoded fallback: the default process hard limit in Linux as of 2020 */
     763                 :           0 :   if (open_max < 0)
     764                 :           0 :     open_max = 4096;
     765                 :             : 
     766                 :             : #if defined(__APPLE__) && defined(HAVE_LIBPROC_H)
     767                 :             :   /* proc_pidinfo isn't documented as async-signal-safe but looking at the implementation
     768                 :             :    * in the darwin tree here:
     769                 :             :    *
     770                 :             :    * https://opensource.apple.com/source/Libc/Libc-498/darwin/libproc.c.auto.html
     771                 :             :    *
     772                 :             :    * It's just a thin wrapper around a syscall, so it's probably okay.
     773                 :             :    */
     774                 :             :   {
     775                 :             :     char buffer[4096 * PROC_PIDLISTFD_SIZE];
     776                 :             :     ssize_t buffer_size;
     777                 :             : 
     778                 :             :     buffer_size = proc_pidinfo (getpid (), PROC_PIDLISTFDS, 0, buffer, sizeof (buffer));
     779                 :             : 
     780                 :             :     if (buffer_size > 0 &&
     781                 :             :         sizeof (buffer) >= (size_t) buffer_size &&
     782                 :             :         (buffer_size % PROC_PIDLISTFD_SIZE) == 0)
     783                 :             :       {
     784                 :             :         const struct proc_fdinfo *fd_info = (const struct proc_fdinfo *) buffer;
     785                 :             :         size_t number_of_fds = (size_t) buffer_size / PROC_PIDLISTFD_SIZE;
     786                 :             : 
     787                 :             :         for (size_t i = 0; i < number_of_fds; i++)
     788                 :             :           if ((res = cb (data, fd_info[i].proc_fd)) != 0)
     789                 :             :             break;
     790                 :             : 
     791                 :             :         return res;
     792                 :             :       }
     793                 :             :   }
     794                 :             : #endif
     795                 :             : 
     796                 :           0 :   for (fd = 0; fd < open_max; fd++)
     797                 :           0 :       if ((res = cb (data, fd)) != 0)
     798                 :           0 :           break;
     799                 :             : 
     800                 :           0 :   return res;
     801                 :             : }
     802                 :             : 
     803                 :             : /**
     804                 :             :  * g_fdwalk_set_cloexec:
     805                 :             :  * @lowfd: Minimum fd to act on, which must be non-negative
     806                 :             :  *
     807                 :             :  * Mark every file descriptor equal to or greater than @lowfd to be closed
     808                 :             :  * at the next `execve()` or similar, as if via the `FD_CLOEXEC` flag.
     809                 :             :  *
     810                 :             :  * Typically @lowfd will be 3, to leave standard input, standard output
     811                 :             :  * and standard error open after exec.
     812                 :             :  *
     813                 :             :  * This is the same as Linux `close_range (lowfd, ~0U, CLOSE_RANGE_CLOEXEC)`,
     814                 :             :  * but portable to other OSs and to older versions of Linux.
     815                 :             :  *
     816                 :             :  * This function is async-signal safe, making it safe to call from a
     817                 :             :  * signal handler or a [callback@GLib.SpawnChildSetupFunc], as long as @lowfd is
     818                 :             :  * non-negative.
     819                 :             :  * See [`signal(7)`](man:signal(7)) and
     820                 :             :  * [`signal-safety(7)`](man:signal-safety(7)) for more details.
     821                 :             :  *
     822                 :             :  * Returns: 0 on success, -1 with errno set on error
     823                 :             :  * Since: 2.80
     824                 :             :  */
     825                 :             : int
     826                 :           9 : g_fdwalk_set_cloexec (int lowfd)
     827                 :             : {
     828                 :             :   int ret;
     829                 :             : 
     830                 :           9 :   g_return_val_if_fail (lowfd >= 0, (errno = EINVAL, -1));
     831                 :             : 
     832                 :             : #if defined(HAVE_CLOSE_RANGE) && defined(CLOSE_RANGE_CLOEXEC)
     833                 :             :   /* close_range() is available in Linux since kernel 5.9, and on FreeBSD at
     834                 :             :    * around the same time. It was designed for use in async-signal-safe
     835                 :             :    * situations: https://bugs.python.org/issue38061
     836                 :             :    *
     837                 :             :    * The `CLOSE_RANGE_CLOEXEC` flag was added in Linux 5.11, and is not yet
     838                 :             :    * present in FreeBSD.
     839                 :             :    *
     840                 :             :    * Handle ENOSYS in case it’s supported in libc but not the kernel; if so,
     841                 :             :    * fall back to safe_fdwalk(). Handle EINVAL in case `CLOSE_RANGE_CLOEXEC`
     842                 :             :    * is not supported. */
     843                 :           8 :   ret = close_range (lowfd, G_MAXUINT, CLOSE_RANGE_CLOEXEC);
     844                 :           8 :   if (ret == 0 || !(errno == ENOSYS || errno == EINVAL))
     845                 :           8 :     return ret;
     846                 :             : #endif  /* HAVE_CLOSE_RANGE */
     847                 :             : 
     848                 :           0 :   ret = safe_fdwalk (set_cloexec, GINT_TO_POINTER (lowfd));
     849                 :             : 
     850                 :           0 :   return ret;
     851                 :             : }
     852                 :             : 
     853                 :             : /**
     854                 :             :  * g_closefrom:
     855                 :             :  * @lowfd: Minimum fd to close, which must be non-negative
     856                 :             :  *
     857                 :             :  * Close every file descriptor equal to or greater than @lowfd.
     858                 :             :  *
     859                 :             :  * Typically @lowfd will be 3, to leave standard input, standard output
     860                 :             :  * and standard error open.
     861                 :             :  *
     862                 :             :  * This is the same as Linux `close_range (lowfd, ~0U, 0)`,
     863                 :             :  * but portable to other OSs and to older versions of Linux.
     864                 :             :  * Equivalently, it is the same as BSD `closefrom (lowfd)`, but portable,
     865                 :             :  * and async-signal-safe on all OSs.
     866                 :             :  *
     867                 :             :  * This function is async-signal safe, making it safe to call from a
     868                 :             :  * signal handler or a [callback@GLib.SpawnChildSetupFunc], as long as @lowfd is
     869                 :             :  * non-negative.
     870                 :             :  * See [`signal(7)`](man:signal(7)) and
     871                 :             :  * [`signal-safety(7)`](man:signal-safety(7)) for more details.
     872                 :             :  *
     873                 :             :  * Returns: 0 on success, -1 with errno set on error
     874                 :             :  * Since: 2.80
     875                 :             :  */
     876                 :             : int
     877                 :         958 : g_closefrom (int lowfd)
     878                 :             : {
     879                 :             :   int ret;
     880                 :             : 
     881                 :         958 :   g_return_val_if_fail (lowfd >= 0, (errno = EINVAL, -1));
     882                 :             : 
     883                 :             : #if defined(HAVE_CLOSE_RANGE)
     884                 :             :   /* close_range() is available in Linux since kernel 5.9, and on FreeBSD at
     885                 :             :    * around the same time. It was designed for use in async-signal-safe
     886                 :             :    * situations: https://bugs.python.org/issue38061
     887                 :             :    *
     888                 :             :    * Handle ENOSYS in case it’s supported in libc but not the kernel; if so,
     889                 :             :    * fall back to safe_fdwalk(). */
     890                 :         957 :   ret = close_range (lowfd, G_MAXUINT, 0);
     891                 :         957 :   if (ret == 0 || errno != ENOSYS)
     892                 :         957 :     return ret;
     893                 :             : #endif  /* HAVE_CLOSE_RANGE */
     894                 :             : 
     895                 :             : #if defined(__FreeBSD__) || defined(__OpenBSD__) || \
     896                 :             :   (defined(__sun__) && defined(F_CLOSEFROM))
     897                 :             :   /* Use closefrom function provided by the system if it is known to be
     898                 :             :    * async-signal safe.
     899                 :             :    *
     900                 :             :    * FreeBSD: closefrom is included in the list of async-signal safe functions
     901                 :             :    * found in https://man.freebsd.org/sigaction(2).
     902                 :             :    *
     903                 :             :    * OpenBSD: closefrom is not included in the list, but a direct system call
     904                 :             :    * should be safe to use.
     905                 :             :    *
     906                 :             :    * In Solaris as of 11.3 SRU 31, closefrom() is also a direct system call.
     907                 :             :    * On such systems, F_CLOSEFROM is defined.
     908                 :             :    */
     909                 :             :   (void) closefrom (lowfd);
     910                 :             :   return 0;
     911                 :             : #elif defined(__DragonFly__)
     912                 :             :   /* It is unclear whether closefrom function included in DragonFlyBSD libc_r
     913                 :             :    * is safe to use because it calls a lot of library functions. It is also
     914                 :             :    * unclear whether libc_r itself is still being used. Therefore, we do a
     915                 :             :    * direct system call here ourselves to avoid possible issues.
     916                 :             :    */
     917                 :             :   (void) syscall (SYS_closefrom, lowfd);
     918                 :             :   return 0;
     919                 :             : #elif defined(F_CLOSEM)
     920                 :             :   /* NetBSD and AIX have a special fcntl command which does the same thing as
     921                 :             :    * closefrom. NetBSD also includes closefrom function, which seems to be a
     922                 :             :    * simple wrapper of the fcntl command.
     923                 :             :    */
     924                 :             :   return fcntl (lowfd, F_CLOSEM);
     925                 :             : #else
     926                 :           0 :   ret = safe_fdwalk (close_func_with_invalid_fds, GINT_TO_POINTER (lowfd));
     927                 :             : 
     928                 :           0 :   return ret;
     929                 :             : #endif
     930                 :             : }
        

Generated by: LCOV version 2.0-1