]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/errno-util.h
license: LGPL-2.1+ -> LGPL-2.1-or-later
[thirdparty/systemd.git] / src / basic / errno-util.h
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
2b2fec7d
LP
2#pragma once
3
4bbccb02
YW
4#include <stdlib.h>
5#include <string.h>
6
2b2fec7d
LP
7#include "macro.h"
8
9static inline void _reset_errno_(int *saved_errno) {
10 if (*saved_errno < 0) /* Invalidated by UNPROTECT_ERRNO? */
11 return;
12
13 errno = *saved_errno;
14}
15
16#define PROTECT_ERRNO \
17 _cleanup_(_reset_errno_) _unused_ int _saved_errno_ = errno
18
19#define UNPROTECT_ERRNO \
20 do { \
21 errno = _saved_errno_; \
22 _saved_errno_ = -1; \
23 } while (false)
24
25static inline int negative_errno(void) {
26 /* This helper should be used to shut up gcc if you know 'errno' is
27 * negative. Instead of "return -errno;", use "return negative_errno();"
28 * It will suppress bogus gcc warnings in case it assumes 'errno' might
29 * be 0 and thus the caller's error-handling might not be triggered. */
30 assert_return(errno > 0, -EINVAL);
31 return -errno;
32}
c3fecddf 33
6fd79cca 34static inline const char *strerror_safe(int error) {
4bbccb02
YW
35 /* 'safe' here does NOT mean thread safety. */
36 return strerror(abs(error));
37}
38
fed81377
LP
39static inline int errno_or_else(int fallback) {
40 /* To be used when invoking library calls where errno handling is not defined clearly: we return
41 * errno if it is set, and the specified error otherwise. The idea is that the caller initializes
42 * errno to zero before doing an API call, and then uses this helper to retrieve a somewhat useful
43 * error code */
44 if (errno > 0)
45 return -errno;
46
47 return -abs(fallback);
48}
49
c3fecddf
LP
50/* Hint #1: ENETUNREACH happens if we try to connect to "non-existing" special IP addresses, such as ::5.
51 *
52 * Hint #2: The kernel sends e.g., EHOSTUNREACH or ENONET to userspace in some ICMP error cases. See the
8d50c142
LP
53 * icmp_err_convert[] in net/ipv4/icmp.c in the kernel sources.
54 *
55 * Hint #3: When asynchronous connect() on TCP fails because the host never acknowledges a single packet,
56 * kernel tells us that with ETIMEDOUT, see tcp(7). */
916a9ec7
LP
57static inline bool ERRNO_IS_DISCONNECT(int r) {
58 return IN_SET(abs(r),
59 ECONNABORTED,
60 ECONNREFUSED,
61 ECONNRESET,
62 EHOSTDOWN,
63 EHOSTUNREACH,
64 ENETDOWN,
65 ENETRESET,
66 ENETUNREACH,
67 ENONET,
68 ENOPROTOOPT,
69 ENOTCONN,
70 EPIPE,
71 EPROTO,
8d50c142
LP
72 ESHUTDOWN,
73 ETIMEDOUT);
916a9ec7 74}
c3fecddf 75
fb0302dd
LP
76/* Transient errors we might get on accept() that we should ignore. As per error handling comment in
77 * the accept(2) man page. */
78static inline bool ERRNO_IS_ACCEPT_AGAIN(int r) {
79 return ERRNO_IS_DISCONNECT(r) ||
80 IN_SET(abs(r),
81 EAGAIN,
82 EINTR,
83 EOPNOTSUPP);
84}
85
c3fecddf 86/* Resource exhaustion, could be our fault or general system trouble */
7f000106
LP
87static inline bool ERRNO_IS_RESOURCE(int r) {
88 return IN_SET(abs(r),
89 EMFILE,
90 ENFILE,
91 ENOMEM);
92}
e6376b6a 93
0648f9be 94/* Seven different errors for "operation/system call/ioctl/socket feature not supported" */
e6376b6a
LP
95static inline bool ERRNO_IS_NOT_SUPPORTED(int r) {
96 return IN_SET(abs(r),
97 EOPNOTSUPP,
98 ENOTTY,
0648f9be
LP
99 ENOSYS,
100 EAFNOSUPPORT,
101 EPFNOSUPPORT,
102 EPROTONOSUPPORT,
103 ESOCKTNOSUPPORT);
e6376b6a 104}
e884e000
LP
105
106/* Two different errors for access problems */
107static inline bool ERRNO_IS_PRIVILEGE(int r) {
108 return IN_SET(abs(r),
109 EACCES,
110 EPERM);
111}
9933a478
LP
112
113/* Three difference errors for "not enough disk space" */
114static inline bool ERRNO_IS_DISK_SPACE(int r) {
115 return IN_SET(abs(r),
116 ENOSPC,
117 EDQUOT,
118 EFBIG);
119}