LCOV - code coverage report
Current view: top level - glib/glib - glib-unix.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 91 156 58.3 %
Date: 2024-04-16 05:15:53 Functions: 14 19 73.7 %
Branches: 24 88 27.3 %

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

Generated by: LCOV version 1.14