You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
205 lines
7.3 KiB
205 lines
7.3 KiB
8 months ago
|
From 690c7cdadd1033bfb47e8de5cc9db781a6055e2a Mon Sep 17 00:00:00 2001
|
||
|
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||
|
Date: Wed, 9 Aug 2023 16:36:38 +0200
|
||
|
Subject: [PATCH] basic/errno-util: add wrappers which only accept negative
|
||
|
errno
|
||
|
|
||
|
We do 'IN_SET(r, -CONST1, -CONST2)', instead of 'IN_SET(-r, CONST1, CONST2)'
|
||
|
because -r is undefined if r is the minimum value (i.e. INT_MIN). But we know
|
||
|
that the constants are small, so their negative values are fine.
|
||
|
|
||
|
(cherry picked from commit b0be985cdd5e51f5f16d6bf541435c225f7c0633)
|
||
|
|
||
|
Related: RHEL-22443
|
||
|
---
|
||
|
src/basic/errno-util.h | 129 +++++++++++++++++++++----------------
|
||
|
src/test/test-errno-util.c | 7 ++
|
||
|
2 files changed, 80 insertions(+), 56 deletions(-)
|
||
|
|
||
|
diff --git a/src/basic/errno-util.h b/src/basic/errno-util.h
|
||
|
index 091f99c590..be5c04e285 100644
|
||
|
--- a/src/basic/errno-util.h
|
||
|
+++ b/src/basic/errno-util.h
|
||
|
@@ -84,12 +84,21 @@ static inline int errno_or_else(int fallback) {
|
||
|
return -abs(fallback);
|
||
|
}
|
||
|
|
||
|
+/* abs(3) says: Trying to take the absolute value of the most negative integer is not defined. */
|
||
|
+#define _DEFINE_ABS_WRAPPER(name) \
|
||
|
+ static inline bool ERRNO_IS_##name(int r) { \
|
||
|
+ if (r == INT_MIN) \
|
||
|
+ return false; \
|
||
|
+ return ERRNO_IS_NEG_##name(-abs(r)); \
|
||
|
+ }
|
||
|
+
|
||
|
/* For send()/recv() or read()/write(). */
|
||
|
-static inline bool ERRNO_IS_TRANSIENT(int r) {
|
||
|
- return IN_SET(abs(r),
|
||
|
- EAGAIN,
|
||
|
- EINTR);
|
||
|
+static inline bool ERRNO_IS_NEG_TRANSIENT(int r) {
|
||
|
+ return IN_SET(r,
|
||
|
+ -EAGAIN,
|
||
|
+ -EINTR);
|
||
|
}
|
||
|
+_DEFINE_ABS_WRAPPER(TRANSIENT);
|
||
|
|
||
|
/* Hint #1: ENETUNREACH happens if we try to connect to "non-existing" special IP addresses, such as ::5.
|
||
|
*
|
||
|
@@ -98,79 +107,87 @@ static inline bool ERRNO_IS_TRANSIENT(int r) {
|
||
|
*
|
||
|
* Hint #3: When asynchronous connect() on TCP fails because the host never acknowledges a single packet,
|
||
|
* kernel tells us that with ETIMEDOUT, see tcp(7). */
|
||
|
-static inline bool ERRNO_IS_DISCONNECT(int r) {
|
||
|
- return IN_SET(abs(r),
|
||
|
- ECONNABORTED,
|
||
|
- ECONNREFUSED,
|
||
|
- ECONNRESET,
|
||
|
- EHOSTDOWN,
|
||
|
- EHOSTUNREACH,
|
||
|
- ENETDOWN,
|
||
|
- ENETRESET,
|
||
|
- ENETUNREACH,
|
||
|
- ENONET,
|
||
|
- ENOPROTOOPT,
|
||
|
- ENOTCONN,
|
||
|
- EPIPE,
|
||
|
- EPROTO,
|
||
|
- ESHUTDOWN,
|
||
|
- ETIMEDOUT);
|
||
|
+static inline bool ERRNO_IS_NEG_DISCONNECT(int r) {
|
||
|
+ return IN_SET(r,
|
||
|
+ -ECONNABORTED,
|
||
|
+ -ECONNREFUSED,
|
||
|
+ -ECONNRESET,
|
||
|
+ -EHOSTDOWN,
|
||
|
+ -EHOSTUNREACH,
|
||
|
+ -ENETDOWN,
|
||
|
+ -ENETRESET,
|
||
|
+ -ENETUNREACH,
|
||
|
+ -ENONET,
|
||
|
+ -ENOPROTOOPT,
|
||
|
+ -ENOTCONN,
|
||
|
+ -EPIPE,
|
||
|
+ -EPROTO,
|
||
|
+ -ESHUTDOWN,
|
||
|
+ -ETIMEDOUT);
|
||
|
}
|
||
|
+_DEFINE_ABS_WRAPPER(DISCONNECT);
|
||
|
|
||
|
/* Transient errors we might get on accept() that we should ignore. As per error handling comment in
|
||
|
* the accept(2) man page. */
|
||
|
-static inline bool ERRNO_IS_ACCEPT_AGAIN(int r) {
|
||
|
- return ERRNO_IS_DISCONNECT(r) ||
|
||
|
- ERRNO_IS_TRANSIENT(r) ||
|
||
|
- abs(r) == EOPNOTSUPP;
|
||
|
+static inline bool ERRNO_IS_NEG_ACCEPT_AGAIN(int r) {
|
||
|
+ return ERRNO_IS_NEG_DISCONNECT(r) ||
|
||
|
+ ERRNO_IS_NEG_TRANSIENT(r) ||
|
||
|
+ r == -EOPNOTSUPP;
|
||
|
}
|
||
|
+_DEFINE_ABS_WRAPPER(ACCEPT_AGAIN);
|
||
|
|
||
|
/* Resource exhaustion, could be our fault or general system trouble */
|
||
|
-static inline bool ERRNO_IS_RESOURCE(int r) {
|
||
|
- return IN_SET(abs(r),
|
||
|
- EMFILE,
|
||
|
- ENFILE,
|
||
|
- ENOMEM);
|
||
|
+static inline bool ERRNO_IS_NEG_RESOURCE(int r) {
|
||
|
+ return IN_SET(r,
|
||
|
+ -EMFILE,
|
||
|
+ -ENFILE,
|
||
|
+ -ENOMEM);
|
||
|
}
|
||
|
+_DEFINE_ABS_WRAPPER(RESOURCE);
|
||
|
|
||
|
/* Seven different errors for "operation/system call/ioctl/socket feature not supported" */
|
||
|
-static inline bool ERRNO_IS_NOT_SUPPORTED(int r) {
|
||
|
- return IN_SET(abs(r),
|
||
|
- EOPNOTSUPP,
|
||
|
- ENOTTY,
|
||
|
- ENOSYS,
|
||
|
- EAFNOSUPPORT,
|
||
|
- EPFNOSUPPORT,
|
||
|
- EPROTONOSUPPORT,
|
||
|
- ESOCKTNOSUPPORT);
|
||
|
+static inline bool ERRNO_IS_NEG_NOT_SUPPORTED(int r) {
|
||
|
+ return IN_SET(r,
|
||
|
+ -EOPNOTSUPP,
|
||
|
+ -ENOTTY,
|
||
|
+ -ENOSYS,
|
||
|
+ -EAFNOSUPPORT,
|
||
|
+ -EPFNOSUPPORT,
|
||
|
+ -EPROTONOSUPPORT,
|
||
|
+ -ESOCKTNOSUPPORT);
|
||
|
}
|
||
|
+_DEFINE_ABS_WRAPPER(NOT_SUPPORTED);
|
||
|
|
||
|
/* Two different errors for access problems */
|
||
|
-static inline bool ERRNO_IS_PRIVILEGE(int r) {
|
||
|
- return IN_SET(abs(r),
|
||
|
- EACCES,
|
||
|
- EPERM);
|
||
|
+static inline bool ERRNO_IS_NEG_PRIVILEGE(int r) {
|
||
|
+ return IN_SET(r,
|
||
|
+ -EACCES,
|
||
|
+ -EPERM);
|
||
|
}
|
||
|
+_DEFINE_ABS_WRAPPER(PRIVILEGE);
|
||
|
|
||
|
/* Three different errors for "not enough disk space" */
|
||
|
-static inline bool ERRNO_IS_DISK_SPACE(int r) {
|
||
|
- return IN_SET(abs(r),
|
||
|
- ENOSPC,
|
||
|
- EDQUOT,
|
||
|
- EFBIG);
|
||
|
+static inline bool ERRNO_IS_NEG_DISK_SPACE(int r) {
|
||
|
+ return IN_SET(r,
|
||
|
+ -ENOSPC,
|
||
|
+ -EDQUOT,
|
||
|
+ -EFBIG);
|
||
|
}
|
||
|
+_DEFINE_ABS_WRAPPER(DISK_SPACE);
|
||
|
|
||
|
/* Three different errors for "this device does not quite exist" */
|
||
|
-static inline bool ERRNO_IS_DEVICE_ABSENT(int r) {
|
||
|
- return IN_SET(abs(r),
|
||
|
- ENODEV,
|
||
|
- ENXIO,
|
||
|
- ENOENT);
|
||
|
+static inline bool ERRNO_IS_NEG_DEVICE_ABSENT(int r) {
|
||
|
+ return IN_SET(r,
|
||
|
+ -ENODEV,
|
||
|
+ -ENXIO,
|
||
|
+ -ENOENT);
|
||
|
}
|
||
|
+_DEFINE_ABS_WRAPPER(DEVICE_ABSENT);
|
||
|
|
||
|
/* Quite often we want to handle cases where the backing FS doesn't support extended attributes at all and
|
||
|
* where it simply doesn't have the requested xattr the same way */
|
||
|
-static inline bool ERRNO_IS_XATTR_ABSENT(int r) {
|
||
|
- return abs(r) == ENODATA ||
|
||
|
- ERRNO_IS_NOT_SUPPORTED(r);
|
||
|
+static inline bool ERRNO_IS_NEG_XATTR_ABSENT(int r) {
|
||
|
+ return r == -ENODATA ||
|
||
|
+ ERRNO_IS_NEG_NOT_SUPPORTED(r);
|
||
|
}
|
||
|
+_DEFINE_ABS_WRAPPER(XATTR_ABSENT);
|
||
|
diff --git a/src/test/test-errno-util.c b/src/test/test-errno-util.c
|
||
|
index f858927c92..507d53df7a 100644
|
||
|
--- a/src/test/test-errno-util.c
|
||
|
+++ b/src/test/test-errno-util.c
|
||
|
@@ -47,4 +47,11 @@ TEST(STRERROR_OR_ELSE) {
|
||
|
log_info("STRERROR_OR_ELSE(-EPERM, \"EOF\") → %s", STRERROR_OR_EOF(-EPERM));
|
||
|
}
|
||
|
|
||
|
+TEST(ERRNO_IS_TRANSIENT) {
|
||
|
+ assert_se( ERRNO_IS_NEG_TRANSIENT(-EINTR));
|
||
|
+ assert_se(!ERRNO_IS_NEG_TRANSIENT(EINTR));
|
||
|
+ assert_se( ERRNO_IS_TRANSIENT(-EINTR));
|
||
|
+ assert_se( ERRNO_IS_TRANSIENT(EINTR));
|
||
|
+}
|
||
|
+
|
||
|
DEFINE_TEST_MAIN(LOG_INFO);
|