18 #include <sys/types.h>
25 #if !__GCC_PREREQ (5, 0)
26 /* https://stackoverflow.com/a/1815371 */
27 static __warn_unused_result __force_inline
__nonnull ((3)) bool
28 __builtin_mul_overflow (size_t a
, size_t b
, size_t *c
)
30 # define SIZE_BIT (sizeof (size_t) * CHAR_BIT / 2)
31 # define HI(x) (x >> SIZE_BIT)
32 # define LO(x) ((((size_t)1 << SIZE_BIT) - 1) & x)
34 size_t s0
, s1
, s2
, s3
, x
, result
, carry
;
39 x
= HI (a
) * LO (b
) + HI (x
);
43 x
= s1
+ LO (a
) * HI (b
);
46 x
= s2
+ HI (a
) * HI (b
) + HI (x
);
50 result
= s1
<< SIZE_BIT
| s0
;
51 carry
= s3
<< SIZE_BIT
| s2
;
59 #define mul_overflow(n, m, s) __builtin_mul_overflow (n, m, s)
61 #define edie(e, ...) (error (EXIT_FAILURE, e, __VA_ARGS__), assume (false))
62 #define die(c, s) (fprintf (stderr, "%s\n", s), exit (c), assume (false))
64 static inline bool program_exited_successfully (int status
) __warn_unused_result __const
;
66 program_exited_successfully (int status
)
68 return WIFEXITED (status
) && WEXITSTATUS (status
) == EXIT_SUCCESS
;
70 static inline bool program_exited_unsuccessfully (int status
) __warn_unused_result __const
;
72 program_exited_unsuccessfully (int status
)
74 return !WIFEXITED (status
) || WEXITSTATUS (status
) != EXIT_SUCCESS
;
76 static inline bool program_terminated (int status
) __warn_unused_result __const
;
78 program_terminated (int status
)
80 return WIFEXITED (status
) || (WIFSIGNALED (status
) && !WIFSTOPPED (status
) && !WIFCONTINUED (status
));
83 static inline int xopenat (int dd
, const char *file
, int oflags
, int cflags
) __nonnull ((2));
85 xopenat (int dd
, const char *file
, int oflags
, int cflags
)
87 int fd
= openat (dd
, file
, oflags
, cflags
);
89 edie (errno
, "openat(%s)", file
);
93 static inline int xopen (const char *file
, int oflags
, int cflags
) __nonnull ((1));
95 xopen (const char *file
, int oflags
, int cflags
)
97 int fd
= open (file
, oflags
, cflags
);
100 edie (errno
, "open(%s)", file
);
105 static inline void xdup2 (int oldfd
, int newfd
);
107 xdup2 (int oldfd
, int newfd
)
109 if (dup2 (oldfd
, newfd
) < 0)
110 edie (errno
, "dup2(%d, %d)", oldfd
, newfd
);
113 static inline void xclose (int fd
);
118 edie (errno
, "close(%d)", fd
);
124 if (pipe (pipes
) != 0)
125 edie (errno
, "pipe()");
128 static inline size_t full_write (int fd
, const void *buf
, size_t len
) __nonnull ((2));
130 full_write (int fd
, const void *buf
, size_t len
)
143 int saved_errno
= errno
;
144 ssize_t ret
= write (fd
, s
, n
);
148 if (errno
== EINTR
|| errno
== EWOULDBLOCK
|| errno
== EAGAIN
)
158 /* According to gnulib note.
159 Some buggy drivers return 0 when one tries
160 to write beyond a device's end.
161 (Example: Linux 1.2.13 on /dev/fd0.)
162 Set errno to ENOSPC so they get a sensible
176 static inline size_t full_read (int fd
, void *buf
, size_t len
) __nonnull ((2));
178 full_read (int fd
, void *buf
, size_t len
)
191 int saved_errno
= errno
;
192 ssize_t ret
= read (fd
, s
, n
);
196 if (errno
== EWOULDBLOCK
|| (errno
!= EINTR
&& errno
!= EAGAIN
))
218 static inline size_t xread (int fd
, void *buf
, size_t len
);
220 xread (int fd
, void *buf
, size_t len
)
222 size_t r
= full_read (fd
, buf
, len
);
225 edie (errno
, "read(%d, %lu)", fd
, (unsigned long int) len
);
230 static inline size_t xwrite (int fd
, const void *buf
, size_t len
);
232 xwrite (int fd
, const void *buf
, size_t len
)
234 size_t r
= full_write (fd
, buf
, len
);
237 edie (errno
, "write(%d, %lu)", fd
, (unsigned long int) len
);
242 static inline const char *xttyname (int fd
) __returns_nonnull
;
243 static inline const char *
246 const char *name
= ttyname (fd
);
249 edie (errno
, "ttyname(%d)", fd
);
254 static inline void *xmalloc (size_t s
) __malloc
__alloc_size ((1)) __returns_nonnull __warn_unused_result
;
258 void *pointer
= malloc (s
);
260 if (unlikely (pointer
== NULL
))
261 edie (errno
, "malloc()");
266 static inline void *xmallocarray (size_t n
, size_t m
) __malloc
__alloc_size ((1, 2)) __returns_nonnull __warn_unused_result
;
268 xmallocarray (size_t n
, size_t m
)
272 if (unlikely (mul_overflow (n
, m
, &s
)))
273 edie (ENOMEM
, "malloc()");
278 static inline void *xrealloc (void *pointer
, size_t s
) __malloc
__nonnull ((1)) __alloc_size ((2)) __returns_nonnull __warn_unused_result
;
280 xrealloc (void *pointer
, size_t s
)
282 pointer
= realloc (pointer
, s
);
284 if (unlikely (pointer
== NULL
))
285 edie (errno
, "realloc()");
290 static inline void *xreallocarray (void *pointer
, size_t n
, size_t m
) __malloc
__nonnull ((1)) __alloc_size ((2, 3)) __returns_nonnull __warn_unused_result
;
292 xreallocarray (void *pointer
, size_t n
, size_t m
)
296 if (unlikely (mul_overflow (n
, m
, &s
)))
297 edie (ENOMEM
, "realloc()");
299 pointer
= realloc (pointer
, s
);
301 if (unlikely (pointer
== NULL
))
302 edie (errno
, "realloc()");
307 static inline pid_t
xfork (void) __warn_unused_result
;
313 if (unlikely (pid
< 0))
314 edie (errno
, "fork()");
319 static inline pid_t
xwaitpid (pid_t pid
, int *status
, int flags
) __nonnull ((2));
321 xwaitpid (pid_t pid
, int *status
, int flags
)
325 while (unlikely ((r
= waitpid (pid
, status
, flags
)) < 0))
326 if (unlikely (errno
!= EINTR
))
327 edie (errno
, "waitpid()");
332 static inline void xexecvpe (char *file
, char **argv
, char **envp
) __noreturn
__nonnull ((1, 2, 3));
334 xexecvpe (char *file
, char **argv
, char **envp
)
336 execvpe (file
, argv
, envp
);
337 /* Unreachable on success. */
338 edie (errno
, "execvpe(\"%s\")", file
);
341 static inline sighandler_t
342 xsignal (int signo
, sighandler_t handler
)
344 sighandler_t previous
= signal (signo
, handler
);
346 if (previous
== SIG_ERR
)
347 edie (errno
, "signal(%d)", signo
);
355 if (unlikely (raise (signo
) != 0))
356 edie (errno
, "raise(%d)", signo
);
360 xkill (pid_t pid
, int signo
)
362 if (unlikely (kill (pid
, signo
) != 0))
363 edie (errno
, "kill(%d, %d)", pid
, signo
);
366 static inline void xchmod (const char *file_name
, mode_t mode
) __nonnull ((1));
368 xchmod (const char *file_name
, mode_t mode
)
370 if (unlikely (chmod (file_name
, mode
) != 0))
371 edie (errno
, "chmod(%s, %o)", file_name
, mode
);
374 static inline void xmkdir (const char *directory_name
, mode_t mode
) __nonnull ((1));
376 xmkdir (const char *directory_name
, mode_t mode
)
378 if (unlikely (mode
& ~07777))
379 edie (EINVAL
, "mkdir(%s, %o)", directory_name
, mode
);
381 if (unlikely (mkdir (directory_name
, mode
) != 0))
385 if (unlikely (errno
!= EEXIST
))
386 edie (errno
, "mkdir(%s, %o)", directory_name
, mode
);
387 /* Do not die if there is directory with given name. */
389 if (unlikely (stat (directory_name
, &sb
) != 0))
390 edie (errno
, "stat(%s)", directory_name
);
392 if (unlikely (!S_ISDIR (sb
.st_mode
)))
393 edie (ENOTDIR
, "%s", directory_name
);
395 /* If directory exists make sure that it has required mode. */
396 if (unlikely ((sb
.st_mode
& 07777) != mode
))
397 xchmod (directory_name
, mode
);
401 static inline void xunlinkat (int dd
, const char *path
) __nonnull ((2));
403 xunlinkat (int dd
, const char *path
)
405 if (unlinkat (dd
, path
, 0) < 0 && errno
!= ENOENT
)
406 edie (errno
, "unlinkat(%s)", path
);
409 static inline void xrmdir (const char *directory_name
) __nonnull ((1));
411 xrmdir (const char *directory_name
)
413 if (rmdir (directory_name
) != 0 && errno
!= ENOENT
)
414 edie (errno
, "rmdir()");
417 static inline int xsprintf (char *s
, const char *fmt
, ...) __nonnull ((1, 2)) __format_printf (2, 3);
419 xsprintf (char *s
, const char *fmt
, ...)
425 n
= vsprintf (s
, fmt
, ap
);
429 edie (errno
, "sprintf()");
435 static inline int xasprintf (char **s
, const char *fmt
, ...) __nonnull ((1, 2)) __format_printf (2, 3);
437 xasprintf (char **s
, const char *fmt
, ...)
445 if (unlikely ((n
= vsnprintf (NULL
, 0, fmt
, ap
)) < 0))
446 edie (errno
, "vsnprintf()");
451 *s
= xmallocarray (n
+ 1, sizeof (char));
453 *s
= xreallocarray (*s
, n
+ 1, sizeof (char));
455 if (unlikely ((n
= vsnprintf (*s
, n
+ 1, fmt
, ap2
)) < 0))
456 edie (errno
, "vsnprintf()");
463 static inline void xastrcat (char **d
, const char *s
) __nonnull ((1, 2));
465 xastrcat (char **d
, const char *s
)
467 size_t s_length
= strlen (s
);
468 size_t d_length
= strlen (*d
);
469 *d
= xreallocarray (*d
, d_length
+ s_length
+ 1, sizeof (char));
470 strcpy (*d
+ d_length
, s
);
474 static inline uid_t
xgetuid (void) __warn_unused_result
;
479 int saved_errno
= errno
;
483 if (unlikely ((uid
= getuid ()) == (uid_t
) -1 && errno
!= 0))
484 edie (errno
, "getuid()");
491 static inline struct passwd
*xgetpwuid (uid_t uid
)
492 __warn_unused_result __malloc
;
493 static inline struct passwd
*
494 xgetpwuid (uid_t uid
)
498 char *p
= xmalloc (sizeof (struct passwd
) + size
);
499 struct passwd
*result
= NULL
;
503 s
= getpwuid_r (uid
, (struct passwd
*) p
, p
+ sizeof (struct passwd
), size
, &result
);
506 continue; /* Try again. */
510 if (mul_overflow (2, size
, &size
))
511 edie (ENOMEM
, "getpwuid_r(%lu)", (unsigned long int) uid
);
513 p
= xrealloc (p
, sizeof (struct passwd
) + size
);
517 /* We either got an error, or we succeeded and the
518 returned name fit in the buffer. */
527 edie (s
, "getpwuid_r(%lu)", (unsigned long int) uid
);
529 else if (result
== NULL
)
532 edie (0, "no matching password record was found for user with uid %lu",
533 (unsigned long int) uid
);
539 static inline char *xgetwd (void) __returns_nonnull __warn_unused_result __malloc
;
543 size_t size
= PATH_MAX
;
544 char *buffer
= xmalloc (PATH_MAX
);
547 while ((p
= getcwd (buffer
, size
)) == NULL
)
549 buffer
= xrealloc (buffer
, size
*= 2);
551 edie (errno
, "getcwd()");
553 return xrealloc (p
, strlen (p
) + 1);
556 static inline void xtcgetattr (int fd
, struct termios
*termiosp
) __nonnull ((2));
558 xtcgetattr (int fd
, struct termios
*termiosp
)
560 if (tcgetattr (fd
, termiosp
) < 0)
561 edie (errno
, "tcgetattr()");
564 static inline void xtcsetattr (int fd
, int optional_actions
, const struct termios
*termiosp
) __nonnull ((3));
566 xtcsetattr (int fd
, int optional_actions
, const struct termios
*termiosp
)
568 if (tcsetattr (fd
, optional_actions
, termiosp
) < 0)
569 edie (errno
, "tcsetattr()");
572 static inline void xatexit (void (*f
) (void)) __nonnull ((1));
574 xatexit (void (*f
) (void))
577 edie (errno
, "atexit()");
580 static inline int program_get_status (pid_t pid
, int flags
) __warn_unused_result
;
582 program_get_status (pid_t pid
, int flags
)
586 xwaitpid (pid
, &status
, flags
);
591 static inline int wait_program_termination (pid_t pid
) __warn_unused_result
;
593 wait_program_termination (pid_t pid
)
598 xwaitpid (pid
, &status
, 0);
599 while (unlikely (!program_terminated (status
)));
604 static inline bool program_is_executing (pid_t pid
) __warn_unused_result
;
606 program_is_executing (pid_t pid
)
611 xwaitpid (pid
, &status
, WNOHANG
);
612 return (!program_terminated (status
));
616 poison (malloc calloc realloc fork kill raise execvpe waitpid
);
617 poison (chmod chown fchown mkdir rmdir getuid geteuid getgid setuid seteuid
);
618 poison (sprintf snprintf asprintf
);
619 poison (tcgetattr tcsetattr atexit read write lseek unlink nice
);