/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
+#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
/* 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);
*
* 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,
/* 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;
_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,
_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,
_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);
_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,
_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,
/* 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);
}
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);