]> git.proxmox.com Git - systemd.git/blame - src/basic/errno-util.h
New upstream version 249~rc1
[systemd.git] / src / basic / errno-util.h
CommitLineData
a032b68d 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
bb4f798a
MB
2#pragma once
3
f2dec872
BR
4#include <stdlib.h>
5#include <string.h>
6
bb4f798a
MB
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}
33
f2dec872
BR
34static inline const char *strerror_safe(int error) {
35 /* 'safe' here does NOT mean thread safety. */
8b3d4ff0 36 return strerror(abs(error)); /* lgtm [cpp/potentially-dangerous-function] */
f2dec872
BR
37}
38
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
bb4f798a
MB
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
a032b68d
MB
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). */
bb4f798a
MB
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,
a032b68d
MB
72 ESHUTDOWN,
73 ETIMEDOUT);
bb4f798a
MB
74}
75
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
86/* Resource exhaustion, could be our fault or general system trouble */
87static inline bool ERRNO_IS_RESOURCE(int r) {
88 return IN_SET(abs(r),
89 EMFILE,
90 ENFILE,
91 ENOMEM);
92}
e1f67bc7 93
a10f5d05 94/* Seven different errors for "operation/system call/ioctl/socket feature not supported" */
e1f67bc7
MB
95static inline bool ERRNO_IS_NOT_SUPPORTED(int r) {
96 return IN_SET(abs(r),
97 EOPNOTSUPP,
98 ENOTTY,
a10f5d05
MB
99 ENOSYS,
100 EAFNOSUPPORT,
101 EPFNOSUPPORT,
102 EPROTONOSUPPORT,
103 ESOCKTNOSUPPORT);
e1f67bc7
MB
104}
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}
46cdbd49
BR
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}