From: Karel Zak Date: Fri, 20 Nov 2020 10:21:41 +0000 (+0100) Subject: lib/caputils: split to multiple functions, add test X-Git-Tag: v2.37-rc1~276 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=966420219cde98e72dd518e4f0005cb0c090a00d;p=thirdparty%2Futil-linux.git lib/caputils: split to multiple functions, add test 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 --- diff --git a/lib/Makemodule.am b/lib/Makemodule.am index bf389db0e2..6db9aaf771 100644 --- a/lib/Makemodule.am +++ b/lib/Makemodule.am @@ -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 diff --git a/lib/caputils.c b/lib/caputils.c index 669330c50b..13a376bfce 100644 --- a/lib/caputils.c +++ b/lib/caputils.c @@ -16,8 +16,11 @@ #include #include +#include #include +#include +#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