Coverage Report

Created: 2025-11-24 06:16

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/rauc/subprojects/glib-2.76.5/glib/glib-unix.c
Line
Count
Source
1
/* GLIB - Library of useful routines for C programming
2
 * Copyright (C) 2011 Red Hat, Inc.
3
 *
4
 * glib-unix.c: UNIX specific API wrappers and convenience functions
5
 *
6
 * SPDX-License-Identifier: LGPL-2.1-or-later
7
 *
8
 * This library is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public
10
 * License as published by the Free Software Foundation; either
11
 * version 2.1 of the License, or (at your option) any later version.
12
 *
13
 * This library is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public
19
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
20
 *
21
 * Authors: Colin Walters <walters@verbum.org>
22
 */
23
24
#include "config.h"
25
26
#include "glib-unix.h"
27
#include "glib-unixprivate.h"
28
#include "gmain-internal.h"
29
30
#include <string.h>
31
#include <sys/types.h>
32
#include <pwd.h>
33
34
G_STATIC_ASSERT (sizeof (ssize_t) == GLIB_SIZEOF_SSIZE_T);
35
G_STATIC_ASSERT (G_ALIGNOF (gssize) == G_ALIGNOF (ssize_t));
36
37
G_STATIC_ASSERT (sizeof (GPid) == sizeof (pid_t));
38
G_STATIC_ASSERT (G_ALIGNOF (GPid) == G_ALIGNOF (pid_t));
39
40
/**
41
 * SECTION:gunix
42
 * @title: UNIX-specific utilities and integration
43
 * @short_description: pipes, signal handling
44
 * @include: glib-unix.h
45
 *
46
 * Most of GLib is intended to be portable; in contrast, this set of
47
 * functions is designed for programs which explicitly target UNIX,
48
 * or are using it to build higher level abstractions which would be
49
 * conditionally compiled if the platform matches %G_OS_UNIX.
50
 *
51
 * To use these functions, you must explicitly include the
52
 * "glib-unix.h" header.
53
 */
54
55
G_DEFINE_QUARK (g-unix-error-quark, g_unix_error)
56
57
static gboolean
58
g_unix_set_error_from_errno (GError **error,
59
                             gint     saved_errno)
60
0
{
61
0
  g_set_error_literal (error,
62
0
                       G_UNIX_ERROR,
63
0
                       0,
64
0
                       g_strerror (saved_errno));
65
0
  errno = saved_errno;
66
0
  return FALSE;
67
0
}
68
69
/**
70
 * g_unix_open_pipe:
71
 * @fds: (array fixed-size=2): Array of two integers
72
 * @flags: Bitfield of file descriptor flags, as for fcntl()
73
 * @error: a #GError
74
 *
75
 * Similar to the UNIX pipe() call, but on modern systems like Linux
76
 * uses the pipe2() system call, which atomically creates a pipe with
77
 * the configured flags. The only supported flag currently is
78
 * %FD_CLOEXEC. If for example you want to configure %O_NONBLOCK, that
79
 * must still be done separately with fcntl().
80
 *
81
 * This function does not take %O_CLOEXEC, it takes %FD_CLOEXEC as if
82
 * for fcntl(); these are different on Linux/glibc.
83
 *
84
 * Returns: %TRUE on success, %FALSE if not (and errno will be set).
85
 *
86
 * Since: 2.30
87
 */
88
gboolean
89
g_unix_open_pipe (int     *fds,
90
                  int      flags,
91
                  GError **error)
92
0
{
93
  /* We only support FD_CLOEXEC */
94
0
  g_return_val_if_fail ((flags & (FD_CLOEXEC)) == flags, FALSE);
95
96
0
  if (!g_unix_open_pipe_internal (fds,
97
0
                                  (flags & FD_CLOEXEC) != 0))
98
0
    return g_unix_set_error_from_errno (error, errno);
99
100
0
  return TRUE;
101
0
}
102
103
/**
104
 * g_unix_set_fd_nonblocking:
105
 * @fd: A file descriptor
106
 * @nonblock: If %TRUE, set the descriptor to be non-blocking
107
 * @error: a #GError
108
 *
109
 * Control the non-blocking state of the given file descriptor,
110
 * according to @nonblock. On most systems this uses %O_NONBLOCK, but
111
 * on some older ones may use %O_NDELAY.
112
 *
113
 * Returns: %TRUE if successful
114
 *
115
 * Since: 2.30
116
 */
117
gboolean
118
g_unix_set_fd_nonblocking (gint       fd,
119
                           gboolean   nonblock,
120
                           GError   **error)
121
0
{
122
0
#ifdef F_GETFL
123
0
  glong fcntl_flags;
124
0
  fcntl_flags = fcntl (fd, F_GETFL);
125
126
0
  if (fcntl_flags == -1)
127
0
    return g_unix_set_error_from_errno (error, errno);
128
129
0
  if (nonblock)
130
0
    {
131
0
#ifdef O_NONBLOCK
132
0
      fcntl_flags |= O_NONBLOCK;
133
#else
134
      fcntl_flags |= O_NDELAY;
135
#endif
136
0
    }
137
0
  else
138
0
    {
139
0
#ifdef O_NONBLOCK
140
0
      fcntl_flags &= ~O_NONBLOCK;
141
#else
142
      fcntl_flags &= ~O_NDELAY;
143
#endif
144
0
    }
145
146
0
  if (fcntl (fd, F_SETFL, fcntl_flags) == -1)
147
0
    return g_unix_set_error_from_errno (error, errno);
148
0
  return TRUE;
149
#else
150
  return g_unix_set_error_from_errno (error, EINVAL);
151
#endif
152
0
}
153
154
/**
155
 * g_unix_signal_source_new:
156
 * @signum: A signal number
157
 *
158
 * Create a #GSource that will be dispatched upon delivery of the UNIX
159
 * signal @signum.  In GLib versions before 2.36, only `SIGHUP`, `SIGINT`,
160
 * `SIGTERM` can be monitored.  In GLib 2.36, `SIGUSR1` and `SIGUSR2`
161
 * were added. In GLib 2.54, `SIGWINCH` was added.
162
 *
163
 * Note that unlike the UNIX default, all sources which have created a
164
 * watch will be dispatched, regardless of which underlying thread
165
 * invoked g_unix_signal_source_new().
166
 *
167
 * For example, an effective use of this function is to handle `SIGTERM`
168
 * cleanly; flushing any outstanding files, and then calling
169
 * g_main_loop_quit().  It is not safe to do any of this from a regular
170
 * UNIX signal handler; such a handler may be invoked while malloc() or
171
 * another library function is running, causing reentrancy issues if the
172
 * handler attempts to use those functions.  None of the GLib/GObject
173
 * API is safe against this kind of reentrancy.
174
 *
175
 * The interaction of this source when combined with native UNIX
176
 * functions like sigprocmask() is not defined.
177
 *
178
 * The source will not initially be associated with any #GMainContext
179
 * and must be added to one with g_source_attach() before it will be
180
 * executed.
181
 *
182
 * Returns: A newly created #GSource
183
 *
184
 * Since: 2.30
185
 */
186
GSource *
187
g_unix_signal_source_new (int signum)
188
0
{
189
0
  g_return_val_if_fail (signum == SIGHUP || signum == SIGINT || signum == SIGTERM ||
190
0
                        signum == SIGUSR1 || signum == SIGUSR2 || signum == SIGWINCH,
191
0
                        NULL);
192
193
0
  return _g_main_create_unix_signal_watch (signum);
194
0
}
195
196
/**
197
 * g_unix_signal_add_full: (rename-to g_unix_signal_add)
198
 * @priority: the priority of the signal source. Typically this will be in
199
 *            the range between %G_PRIORITY_DEFAULT and %G_PRIORITY_HIGH.
200
 * @signum: Signal number
201
 * @handler: Callback
202
 * @user_data: Data for @handler
203
 * @notify: #GDestroyNotify for @handler
204
 *
205
 * A convenience function for g_unix_signal_source_new(), which
206
 * attaches to the default #GMainContext.  You can remove the watch
207
 * using g_source_remove().
208
 *
209
 * Returns: An ID (greater than 0) for the event source
210
 *
211
 * Since: 2.30
212
 */
213
guint
214
g_unix_signal_add_full (int            priority,
215
                        int            signum,
216
                        GSourceFunc    handler,
217
                        gpointer       user_data,
218
                        GDestroyNotify notify)
219
0
{
220
0
  guint id;
221
0
  GSource *source;
222
223
0
  source = g_unix_signal_source_new (signum);
224
225
0
  if (priority != G_PRIORITY_DEFAULT)
226
0
    g_source_set_priority (source, priority);
227
228
0
  g_source_set_callback (source, handler, user_data, notify);
229
0
  id = g_source_attach (source, NULL);
230
0
  g_source_unref (source);
231
232
0
  return id;
233
0
}
234
235
/**
236
 * g_unix_signal_add:
237
 * @signum: Signal number
238
 * @handler: Callback
239
 * @user_data: Data for @handler
240
 *
241
 * A convenience function for g_unix_signal_source_new(), which
242
 * attaches to the default #GMainContext.  You can remove the watch
243
 * using g_source_remove().
244
 *
245
 * Returns: An ID (greater than 0) for the event source
246
 *
247
 * Since: 2.30
248
 */
249
guint
250
g_unix_signal_add (int         signum,
251
                   GSourceFunc handler,
252
                   gpointer    user_data)
253
0
{
254
0
  return g_unix_signal_add_full (G_PRIORITY_DEFAULT, signum, handler, user_data, NULL);
255
0
}
256
257
typedef struct
258
{
259
  GSource source;
260
261
  gint     fd;
262
  gpointer tag;
263
} GUnixFDSource;
264
265
static gboolean
266
g_unix_fd_source_dispatch (GSource     *source,
267
                           GSourceFunc  callback,
268
                           gpointer     user_data)
269
0
{
270
0
  GUnixFDSource *fd_source = (GUnixFDSource *) source;
271
0
  GUnixFDSourceFunc func = (GUnixFDSourceFunc) callback;
272
273
0
  if (!callback)
274
0
    {
275
0
      g_warning ("GUnixFDSource dispatched without callback. "
276
0
                 "You must call g_source_set_callback().");
277
0
      return FALSE;
278
0
    }
279
280
0
  return (* func) (fd_source->fd, g_source_query_unix_fd (source, fd_source->tag), user_data);
281
0
}
282
283
GSourceFuncs g_unix_fd_source_funcs = {
284
  NULL, NULL, g_unix_fd_source_dispatch, NULL, NULL, NULL
285
};
286
287
/**
288
 * g_unix_fd_source_new:
289
 * @fd: a file descriptor
290
 * @condition: IO conditions to watch for on @fd
291
 *
292
 * Creates a #GSource to watch for a particular IO condition on a file
293
 * descriptor.
294
 *
295
 * The source will never close the fd -- you must do it yourself.
296
 *
297
 * Returns: the newly created #GSource
298
 *
299
 * Since: 2.36
300
 **/
301
GSource *
302
g_unix_fd_source_new (gint         fd,
303
                      GIOCondition condition)
304
0
{
305
0
  GUnixFDSource *fd_source;
306
0
  GSource *source;
307
308
0
  source = g_source_new (&g_unix_fd_source_funcs, sizeof (GUnixFDSource));
309
0
  fd_source = (GUnixFDSource *) source;
310
311
0
  fd_source->fd = fd;
312
0
  fd_source->tag = g_source_add_unix_fd (source, fd, condition);
313
314
0
  return source;
315
0
}
316
317
/**
318
 * g_unix_fd_add_full:
319
 * @priority: the priority of the source
320
 * @fd: a file descriptor
321
 * @condition: IO conditions to watch for on @fd
322
 * @function: a #GUnixFDSourceFunc
323
 * @user_data: data to pass to @function
324
 * @notify: function to call when the idle is removed, or %NULL
325
 *
326
 * Sets a function to be called when the IO condition, as specified by
327
 * @condition becomes true for @fd.
328
 *
329
 * This is the same as g_unix_fd_add(), except that it allows you to
330
 * specify a non-default priority and a provide a #GDestroyNotify for
331
 * @user_data.
332
 *
333
 * Returns: the ID (greater than 0) of the event source
334
 *
335
 * Since: 2.36
336
 **/
337
guint
338
g_unix_fd_add_full (gint              priority,
339
                    gint              fd,
340
                    GIOCondition      condition,
341
                    GUnixFDSourceFunc function,
342
                    gpointer          user_data,
343
                    GDestroyNotify    notify)
344
0
{
345
0
  GSource *source;
346
0
  guint id;
347
348
0
  g_return_val_if_fail (function != NULL, 0);
349
350
0
  source = g_unix_fd_source_new (fd, condition);
351
352
0
  if (priority != G_PRIORITY_DEFAULT)
353
0
    g_source_set_priority (source, priority);
354
355
0
  g_source_set_callback (source, (GSourceFunc) function, user_data, notify);
356
0
  id = g_source_attach (source, NULL);
357
0
  g_source_unref (source);
358
359
0
  return id;
360
0
}
361
362
/**
363
 * g_unix_fd_add:
364
 * @fd: a file descriptor
365
 * @condition: IO conditions to watch for on @fd
366
 * @function: a #GUnixFDSourceFunc
367
 * @user_data: data to pass to @function
368
 *
369
 * Sets a function to be called when the IO condition, as specified by
370
 * @condition becomes true for @fd.
371
 *
372
 * @function will be called when the specified IO condition becomes
373
 * %TRUE.  The function is expected to clear whatever event caused the
374
 * IO condition to become true and return %TRUE in order to be notified
375
 * when it happens again.  If @function returns %FALSE then the watch
376
 * will be cancelled.
377
 *
378
 * The return value of this function can be passed to g_source_remove()
379
 * to cancel the watch at any time that it exists.
380
 *
381
 * The source will never close the fd -- you must do it yourself.
382
 *
383
 * Returns: the ID (greater than 0) of the event source
384
 *
385
 * Since: 2.36
386
 **/
387
guint
388
g_unix_fd_add (gint              fd,
389
               GIOCondition      condition,
390
               GUnixFDSourceFunc function,
391
               gpointer          user_data)
392
0
{
393
0
  return g_unix_fd_add_full (G_PRIORITY_DEFAULT, fd, condition, function, user_data, NULL);
394
0
}
395
396
/**
397
 * g_unix_get_passwd_entry:
398
 * @user_name: the username to get the passwd file entry for
399
 * @error: return location for a #GError, or %NULL
400
 *
401
 * Get the `passwd` file entry for the given @user_name using `getpwnam_r()`.
402
 * This can fail if the given @user_name doesn’t exist.
403
 *
404
 * The returned `struct passwd` has been allocated using g_malloc() and should
405
 * be freed using g_free(). The strings referenced by the returned struct are
406
 * included in the same allocation, so are valid until the `struct passwd` is
407
 * freed.
408
 *
409
 * This function is safe to call from multiple threads concurrently.
410
 *
411
 * You will need to include `pwd.h` to get the definition of `struct passwd`.
412
 *
413
 * Returns: (transfer full): passwd entry, or %NULL on error; free the returned
414
 *    value with g_free()
415
 * Since: 2.64
416
 */
417
struct passwd *
418
g_unix_get_passwd_entry (const gchar  *user_name,
419
                         GError      **error)
420
0
{
421
0
  struct passwd *passwd_file_entry;
422
0
  struct
423
0
    {
424
0
      struct passwd pwd;
425
0
      char string_buffer[];
426
0
    } *buffer = NULL;
427
0
  gsize string_buffer_size = 0;
428
0
  GError *local_error = NULL;
429
430
0
  g_return_val_if_fail (user_name != NULL, NULL);
431
0
  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
432
433
0
#ifdef _SC_GETPW_R_SIZE_MAX
434
0
    {
435
      /* Get the recommended buffer size */
436
0
      glong string_buffer_size_long = sysconf (_SC_GETPW_R_SIZE_MAX);
437
0
      if (string_buffer_size_long > 0)
438
0
        string_buffer_size = string_buffer_size_long;
439
0
    }
440
0
#endif /* _SC_GETPW_R_SIZE_MAX */
441
442
  /* Default starting size. */
443
0
  if (string_buffer_size == 0)
444
0
    string_buffer_size = 64;
445
446
0
  do
447
0
    {
448
0
      int retval;
449
450
0
      g_free (buffer);
451
      /* Allocate space for the `struct passwd`, and then a buffer for all its
452
       * strings (whose size is @string_buffer_size, which increases in this
453
       * loop until it’s big enough). Add 6 extra bytes to work around a bug in
454
       * macOS < 10.3. See #156446.
455
       */
456
0
      buffer = g_malloc0 (sizeof (*buffer) + string_buffer_size + 6);
457
458
0
      retval = getpwnam_r (user_name, &buffer->pwd, buffer->string_buffer,
459
0
                           string_buffer_size, &passwd_file_entry);
460
461
      /* Bail out if: the lookup was successful, or if the user id can't be
462
       * found (should be pretty rare case actually), or if the buffer should be
463
       * big enough and yet lookups are still not successful.
464
       */
465
0
      if (passwd_file_entry != NULL)
466
0
        {
467
          /* Success. */
468
0
          break;
469
0
        }
470
0
      else if (retval == 0 ||
471
0
          retval == ENOENT || retval == ESRCH ||
472
0
          retval == EBADF || retval == EPERM)
473
0
        {
474
          /* Username not found. */
475
0
          g_unix_set_error_from_errno (&local_error, retval);
476
0
          break;
477
0
        }
478
0
      else if (retval == ERANGE)
479
0
        {
480
          /* Can’t allocate enough string buffer space. */
481
0
          if (string_buffer_size > 32 * 1024)
482
0
            {
483
0
              g_unix_set_error_from_errno (&local_error, retval);
484
0
              break;
485
0
            }
486
487
0
          string_buffer_size *= 2;
488
0
          continue;
489
0
        }
490
0
      else
491
0
        {
492
0
          g_unix_set_error_from_errno (&local_error, retval);
493
0
          break;
494
0
        }
495
0
    }
496
0
  while (passwd_file_entry == NULL);
497
498
0
  g_assert (passwd_file_entry == NULL ||
499
0
            (gpointer) passwd_file_entry == (gpointer) buffer);
500
501
  /* Success or error. */
502
0
  if (local_error != NULL)
503
0
    {
504
0
      g_clear_pointer (&buffer, g_free);
505
0
      g_propagate_error (error, g_steal_pointer (&local_error));
506
0
    }
507
508
0
  return (struct passwd *) g_steal_pointer (&buffer);
509
0
}