systemd/SOURCES/0465-errno-util-allow-ERRNO...

149 lines
6.0 KiB
Diff

From 7c5ece0b649ebea23ebb28eb3cafdb28ba49a9d0 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 18:21:13 +0200
Subject: [PATCH] errno-util: allow ERRNO_IS_* to accept types wider than int
This is useful if the variable is ssize_t and we don't want to trigger a
warning or truncation.
With gcc (gcc-13.2.1-1.fc38.x86_64), the resulting systemd binary is identical,
so I assume that the compiler is able to completely optimize away the type.
(cherry picked from commit fe0feacb9e9641874fde459af4067d9b7e9d7462)
Related: RHEL-22443
---
src/basic/errno-util.h | 27 +++++++++++++++------------
src/test/test-errno-util.c | 13 +++++++++++++
2 files changed, 28 insertions(+), 12 deletions(-)
diff --git a/src/basic/errno-util.h b/src/basic/errno-util.h
index be5c04e285..b10dd755c9 100644
--- a/src/basic/errno-util.h
+++ b/src/basic/errno-util.h
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
+#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
@@ -86,14 +87,16 @@ static inline int errno_or_else(int 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) \
+ static inline bool ERRNO_IS_##name(intmax_t r) { \
+ if (r == INTMAX_MIN) \
return false; \
- return ERRNO_IS_NEG_##name(-abs(r)); \
+ return ERRNO_IS_NEG_##name(-imaxabs(r)); \
}
+assert_cc(INT_MAX <= INTMAX_MAX);
+
/* For send()/recv() or read()/write(). */
-static inline bool ERRNO_IS_NEG_TRANSIENT(int r) {
+static inline bool ERRNO_IS_NEG_TRANSIENT(intmax_t r) {
return IN_SET(r,
-EAGAIN,
-EINTR);
@@ -107,7 +110,7 @@ _DEFINE_ABS_WRAPPER(TRANSIENT);
*
* 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_NEG_DISCONNECT(int r) {
+static inline bool ERRNO_IS_NEG_DISCONNECT(intmax_t r) {
return IN_SET(r,
-ECONNABORTED,
-ECONNREFUSED,
@@ -129,7 +132,7 @@ _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_NEG_ACCEPT_AGAIN(int r) {
+static inline bool ERRNO_IS_NEG_ACCEPT_AGAIN(intmax_t r) {
return ERRNO_IS_NEG_DISCONNECT(r) ||
ERRNO_IS_NEG_TRANSIENT(r) ||
r == -EOPNOTSUPP;
@@ -137,7 +140,7 @@ static inline bool ERRNO_IS_NEG_ACCEPT_AGAIN(int r) {
_DEFINE_ABS_WRAPPER(ACCEPT_AGAIN);
/* Resource exhaustion, could be our fault or general system trouble */
-static inline bool ERRNO_IS_NEG_RESOURCE(int r) {
+static inline bool ERRNO_IS_NEG_RESOURCE(intmax_t r) {
return IN_SET(r,
-EMFILE,
-ENFILE,
@@ -146,7 +149,7 @@ static inline bool ERRNO_IS_NEG_RESOURCE(int r) {
_DEFINE_ABS_WRAPPER(RESOURCE);
/* Seven different errors for "operation/system call/ioctl/socket feature not supported" */
-static inline bool ERRNO_IS_NEG_NOT_SUPPORTED(int r) {
+static inline bool ERRNO_IS_NEG_NOT_SUPPORTED(intmax_t r) {
return IN_SET(r,
-EOPNOTSUPP,
-ENOTTY,
@@ -159,7 +162,7 @@ static inline bool ERRNO_IS_NEG_NOT_SUPPORTED(int r) {
_DEFINE_ABS_WRAPPER(NOT_SUPPORTED);
/* Two different errors for access problems */
-static inline bool ERRNO_IS_NEG_PRIVILEGE(int r) {
+static inline bool ERRNO_IS_NEG_PRIVILEGE(intmax_t r) {
return IN_SET(r,
-EACCES,
-EPERM);
@@ -167,7 +170,7 @@ static inline bool ERRNO_IS_NEG_PRIVILEGE(int r) {
_DEFINE_ABS_WRAPPER(PRIVILEGE);
/* Three different errors for "not enough disk space" */
-static inline bool ERRNO_IS_NEG_DISK_SPACE(int r) {
+static inline bool ERRNO_IS_NEG_DISK_SPACE(intmax_t r) {
return IN_SET(r,
-ENOSPC,
-EDQUOT,
@@ -176,7 +179,7 @@ static inline bool ERRNO_IS_NEG_DISK_SPACE(int r) {
_DEFINE_ABS_WRAPPER(DISK_SPACE);
/* Three different errors for "this device does not quite exist" */
-static inline bool ERRNO_IS_NEG_DEVICE_ABSENT(int r) {
+static inline bool ERRNO_IS_NEG_DEVICE_ABSENT(intmax_t r) {
return IN_SET(r,
-ENODEV,
-ENXIO,
@@ -186,7 +189,7 @@ _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_NEG_XATTR_ABSENT(int r) {
+static inline bool ERRNO_IS_NEG_XATTR_ABSENT(intmax_t r) {
return r == -ENODATA ||
ERRNO_IS_NEG_NOT_SUPPORTED(r);
}
diff --git a/src/test/test-errno-util.c b/src/test/test-errno-util.c
index 507d53df7a..cac0d5402b 100644
--- a/src/test/test-errno-util.c
+++ b/src/test/test-errno-util.c
@@ -52,6 +52,19 @@ TEST(ERRNO_IS_TRANSIENT) {
assert_se(!ERRNO_IS_NEG_TRANSIENT(EINTR));
assert_se( ERRNO_IS_TRANSIENT(-EINTR));
assert_se( ERRNO_IS_TRANSIENT(EINTR));
+
+ /* Test with type wider than int */
+ ssize_t r = -EAGAIN;
+ assert_se( ERRNO_IS_NEG_TRANSIENT(r));
+
+ /* On 64-bit arches, now (int) r == EAGAIN */
+ r = SSIZE_MAX - EAGAIN + 1;
+ assert_se(!ERRNO_IS_NEG_TRANSIENT(r));
+
+ assert_se(!ERRNO_IS_NEG_TRANSIENT(INT_MAX));
+ assert_se(!ERRNO_IS_NEG_TRANSIENT(INT_MIN));
+ assert_se(!ERRNO_IS_NEG_TRANSIENT(INTMAX_MAX));
+ assert_se(!ERRNO_IS_NEG_TRANSIENT(INTMAX_MIN));
}
DEFINE_TEST_MAIN(LOG_INFO);