]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lib/caputils: split to multiple functions, add test
authorKarel Zak <kzak@redhat.com>
Fri, 20 Nov 2020 10:21:41 +0000 (11:21 +0100)
committerKarel Zak <kzak@redhat.com>
Fri, 20 Nov 2020 10:21:41 +0000 (11:21 +0100)
Let's split the code to make it possible to test separately bsearch as
well as procfs based cap_last_cap().

 $ ./test_caputils --last-by-bsearch
 last cap: 39
 $ ./test_caputils --last-by-procfs
 last cap: 39
 $ ./test_caputils --last
 last cap: 39

Signed-off-by: Karel Zak <kzak@redhat.com>
lib/Makemodule.am
lib/caputils.c

index bf389db0e2f81d2fc0dccadc59c548b1ba4f13f7..6db9aaf7719c606bdf2a144887ea94b1e4508769 100644 (file)
@@ -100,7 +100,8 @@ check_PROGRAMS += test_cpuset
 endif
 check_PROGRAMS += \
        test_sysfs \
-       test_pager
+       test_pager \
+       test_caputils
 endif
 
 if HAVE_OPENAT
@@ -110,6 +111,10 @@ check_PROGRAMS += test_path
 endif
 endif
 
+test_caputils_SOURCES = lib/caputils.c
+test_caputils_CFLAGS = $(AM_CFLAGS) -DTEST_PROGRAM_CAPUTILS
+test_caputils_LDADD = $(LDADD) libcommon.la
+
 test_ttyutils_SOURCES = lib/ttyutils.c
 test_ttyutils_CFLAGS = $(AM_CFLAGS) -DTEST_PROGRAM_TTYUTILS
 test_ttyutils_LDADD = $(LDADD) libcommon.la
index 669330c50bd4a92ea7f6a18a1802b7c369c2bf09..13a376bfce24adae37b8372671f8181e9944fa9c 100644 (file)
 
 #include <sys/prctl.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <limits.h>
+#include <errno.h>
 
+#include "c.h"
 #include "caputils.h"
 #include "procutils.h"
 #include "pathnames.h"
@@ -28,45 +31,88 @@ static int test_cap(unsigned int cap)
        return prctl(PR_CAPBSET_READ, cap, 0, 0, 0) >= 0;
 }
 
+static int cap_last_by_bsearch(int *ret)
+{
+       /* starting with cap=INT_MAX means we always know
+        * that cap1 is invalid after the first iteration */
+       int cap = INT_MAX;
+       unsigned int cap0 = 0, cap1 = INT_MAX;
+
+       while ((int)cap0 < cap) {
+               if (test_cap(cap))
+                       cap0 = cap;
+               else
+                       cap1 = cap;
+
+               cap = (cap0 + cap1) / 2U;
+       }
+
+       *ret = cap;
+       return 0;
+}
+
+static int cap_last_by_procfs(int *ret)
+{
+       FILE *f = fopen(_PATH_PROC_CAPLASTCAP, "r");
+       int rc = -EINVAL;
+
+       *ret = 0;
+
+       if (f && proc_is_procfs(fileno(f))) {
+               int cap;
+
+               /* we check if the cap after this one really isn't valid */
+               if (fscanf(f, "%d", &cap) == 1 &&
+                   cap < INT_MAX && !test_cap(cap + 1)) {
+
+                       *ret = cap;
+                       rc = 0;
+               }
+       }
+
+       if (f)
+               fclose(f);
+       return rc;
+}
+
 int cap_last_cap(void)
 {
        static int cap = -1;
-       FILE *f;
 
        if (cap != -1)
                return cap;
+       if (cap_last_by_procfs(&cap) < 0)
+               cap_last_by_bsearch(&cap);
 
-       /* try to read value from kernel, check that the path is
-        * indeed in a procfs mount */
-       f = fopen(_PATH_PROC_CAPLASTCAP, "r");
-       if (f) {
-               int matched = 0;
+       return cap;
+}
 
-               if (proc_is_procfs(fileno(f))) {
-                       matched = fscanf(f, "%d", &cap);
-               }
-               fclose(f);
+#ifdef TEST_PROGRAM_CAPUTILS
+int main(int argc, char *argv[])
+{
+       int rc = 0, cap;
 
-               /* we check if the cap after this one really isn't valid */
-               if (matched == 1 && cap < INT_MAX && !test_cap(cap + 1))
-                       return cap;
+       if (argc < 2) {
+               fprintf(stderr, "usage: %1$s --last-by-procfs\n"
+                               "       %1$s --last-by-bsearch\n"
+                               "       %1$s --last\n",
+                               program_invocation_short_name);
+               return EXIT_FAILURE;
        }
 
-       /* if it wasn't possible to read the file in /proc,
-        * fall back to binary search over capabilities */
+       if (strcmp(argv[1], "--last-by-procfs") == 0) {
+               rc = cap_last_by_procfs(&cap);
+               if (rc == 0)
+                       printf("last cap: %d\n", cap);
 
-       /* starting with cap=INT_MAX means we always know
-        * that cap1 is invalid after the first iteration */
-       unsigned int cap0 = 0, cap1 = INT_MAX;
-       cap = INT_MAX;
-       while ((int)cap0 < cap) {
-               if (test_cap(cap)) {
-                       cap0 = cap;
-               } else {
-                       cap1 = cap;
-               }
-               cap = (cap0 + cap1) / 2U;
-       }
+       } else if (strcmp(argv[1], "--last-by-bsearch") == 0) {
+               rc = cap_last_by_bsearch(&cap);
+               if (rc == 0)
+                       printf("last cap: %d\n", cap);
 
-       return cap;
+       } else if (strcmp(argv[1], "--last") == 0)
+               printf("last cap: %d\n", cap_last_cap());
+
+       return rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
 }
+#endif