Branch data Line data Source code
1 : : /* SPDX-License-Identifier: LGPL-2.1+ */ 2 : : #pragma once 3 : : 4 : : #include <stdlib.h> 5 : : #include <string.h> 6 : : 7 : : #include "macro.h" 8 : : 9 : 926127 : static inline void _reset_errno_(int *saved_errno) { 10 [ + + ]: 926127 : if (*saved_errno < 0) /* Invalidated by UNPROTECT_ERRNO? */ 11 : 4 : return; 12 : : 13 : 926123 : 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 : : 25 : 0 : static 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 [ # # # # ]: 0 : assert_return(errno > 0, -EINVAL); 31 : 0 : return -errno; 32 : : } 33 : : 34 : 448 : static inline const char *strerror_safe(int error) { 35 : : /* 'safe' here does NOT mean thread safety. */ 36 : 448 : return strerror(abs(error)); 37 : : } 38 : : 39 : 568 : static 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 [ + + ]: 568 : if (errno > 0) 45 : 16 : return -errno; 46 : : 47 : 552 : return -abs(fallback); 48 : : } 49 : : 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 53 : : * icmp_err_convert[] in net/ipv4/icmp.c in the kernel sources */ 54 : 1215 : static inline bool ERRNO_IS_DISCONNECT(int r) { 55 [ + + ]: 1215 : return IN_SET(abs(r), 56 : : ECONNABORTED, 57 : : ECONNREFUSED, 58 : : ECONNRESET, 59 : : EHOSTDOWN, 60 : : EHOSTUNREACH, 61 : : ENETDOWN, 62 : : ENETRESET, 63 : : ENETUNREACH, 64 : : ENONET, 65 : : ENOPROTOOPT, 66 : : ENOTCONN, 67 : : EPIPE, 68 : : EPROTO, 69 : : ESHUTDOWN); 70 : : } 71 : : 72 : : /* Transient errors we might get on accept() that we should ignore. As per error handling comment in 73 : : * the accept(2) man page. */ 74 : 0 : static inline bool ERRNO_IS_ACCEPT_AGAIN(int r) { 75 [ # # ]: 0 : return ERRNO_IS_DISCONNECT(r) || 76 [ # # # # ]: 0 : IN_SET(abs(r), 77 : : EAGAIN, 78 : : EINTR, 79 : : EOPNOTSUPP); 80 : : } 81 : : 82 : : /* Resource exhaustion, could be our fault or general system trouble */ 83 : 328 : static inline bool ERRNO_IS_RESOURCE(int r) { 84 [ - + ]: 328 : return IN_SET(abs(r), 85 : : EMFILE, 86 : : ENFILE, 87 : : ENOMEM); 88 : : }