return ret;
}
+/* Collect possible errors in <acc>, so that the first error can be returned.
+ * Returns (possibly updated) <acc>. */
+#define RET_GATHER(acc, err) \
+ ({ \
+ int *__a = &(acc), __e = (err); \
+ if (*__a >= 0 && __e < 0) \
+ *__a = __e; \
+ *__a; \
+ })
+
static inline int errno_or_else(int fallback) {
/* To be used when invoking library calls where errno handling is not defined clearly: we return
* errno if it is set, and the specified error otherwise. The idea is that the caller initializes
/* Continues adding after failure, and returns the first failure. */
- STRV_FOREACH(i, l) {
- int k;
-
- k = sd_bus_track_add_name(t, *i);
- if (k < 0 && r >= 0)
- r = k;
- }
-
+ STRV_FOREACH(i, l)
+ RET_GATHER(r, sd_bus_track_add_name(t, *i));
return r;
}
k = devnode_acl(n, flush, del, old_uid, add, new_uid);
if (k == -ENOENT)
log_debug("Device %s disappeared while setting ACLs", n);
- else if (k < 0 && r == 0)
- r = k;
+ else
+ RET_GATHER(r, k);
}
return r;
}
int nscd_flush_cache(char **databases) {
- usec_t end;
int r = 0;
- /* Tries to invalidate the specified database in nscd. We do this carefully, with a 5s timeout, so that we
- * don't block indefinitely on another service. */
+ /* Tries to invalidate the specified database in nscd. We do this carefully, with a 5s timeout,
+ * so that we don't block indefinitely on another service. */
- end = usec_add(now(CLOCK_MONOTONIC), NSCD_FLUSH_CACHE_TIMEOUT_USEC);
+ usec_t end = usec_add(now(CLOCK_MONOTONIC), NSCD_FLUSH_CACHE_TIMEOUT_USEC);
- STRV_FOREACH(i, databases) {
- int k;
-
- k = nscd_flush_cache_one(*i, end);
- if (k < 0 && r >= 0)
- r = k;
- }
+ STRV_FOREACH(i, databases)
+ RET_GATHER(r, nscd_flush_cache_one(*i, end));
return r;
}
assert_se(errno == 4711);
}
+TEST(RET_GATHER) {
+ int x = 0, y = 2;
+
+ assert_se(RET_GATHER(x, 5) == 0);
+ assert_se(RET_GATHER(x, -5) == -5);
+ assert_se(RET_GATHER(x, -1) == -5);
+
+ assert_se(RET_GATHER(x, y++) == -5);
+ assert_se(y == 3);
+}
+
DEFINE_TEST_MAIN(LOG_INFO);