util.h: add new UNPROTECT_ERRNO macro
authorLennart Poettering <lennart@poettering.net>
Fri, 18 Jan 2019 19:04:13 +0000 (20:04 +0100)
committerLennart Poettering <lennart@poettering.net>
Fri, 8 Feb 2019 09:34:47 +0000 (10:34 +0100)
THis is inspired by #11395, but much simpler.

src/basic/util.h
src/test/test-fs-util.c
src/test/test-util.c

index f009d37..dc33d66 100644 (file)
@@ -174,12 +174,21 @@ static inline void *mempset(void *s, int c, size_t n) {
 }
 
 static inline void _reset_errno_(int *saved_errno) {
+        if (*saved_errno < 0) /* Invalidated by UNPROTECT_ERRNO? */
+                return;
+
         errno = *saved_errno;
 }
 
 #define PROTECT_ERRNO                                                   \
         _cleanup_(_reset_errno_) _unused_ int _saved_errno_ = errno
 
+#define UNPROTECT_ERRNO                         \
+        do {                                    \
+                errno = _saved_errno_;          \
+                _saved_errno_ = -1;             \
+        } while (false)
+
 static inline int negative_errno(void) {
         /* This helper should be used to shut up gcc if you know 'errno' is
          * negative. Instead of "return -errno;", use "return negative_errno();"
index b3a4b17..e049abc 100644 (file)
@@ -361,11 +361,11 @@ static void test_unlink_noerrno(void) {
 
         {
                 PROTECT_ERRNO;
-                errno = -42;
+                errno = 42;
                 assert_se(unlink_noerrno(name) >= 0);
-                assert_se(errno == -42);
+                assert_se(errno == 42);
                 assert_se(unlink_noerrno(name) < 0);
-                assert_se(errno == -42);
+                assert_se(errno == 42);
         }
 }
 
index 40c1f4a..ffacd65 100644 (file)
@@ -213,6 +213,30 @@ static void test_protect_errno(void) {
         assert_se(errno == 12);
 }
 
+static void test_unprotect_errno_inner_function(void) {
+        PROTECT_ERRNO;
+
+        errno = 2222;
+}
+
+static void test_unprotect_errno(void) {
+        log_info("/* %s */", __func__);
+
+        errno = 4711;
+
+        PROTECT_ERRNO;
+
+        errno = 815;
+
+        UNPROTECT_ERRNO;
+
+        assert_se(errno == 4711);
+
+        test_unprotect_errno_inner_function();
+
+        assert_se(errno == 4711);
+}
+
 static void test_in_set(void) {
         log_info("/* %s */", __func__);
 
@@ -383,6 +407,7 @@ int main(int argc, char *argv[]) {
         test_div_round_up();
         test_u64log2();
         test_protect_errno();
+        test_unprotect_errno();
         test_in_set();
         test_log2i();
         test_eqzero();