From 1b918a4af49ae4a2644b089ff3263018157365ab Mon Sep 17 00:00:00 2001 From: allgdante Date: Wed, 4 Jul 2018 16:50:24 +0200 Subject: [PATCH 05/11] libapparmor: fix scandirat with musl libc This commits adds a configure check for scandirat() and if it's not available, provides it an implementation based on scandir() from musl libc --- libraries/libapparmor/configure.ac | 2 +- libraries/libapparmor/src/private.c | 56 +++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/libraries/libapparmor/configure.ac b/libraries/libapparmor/configure.ac index 73d99398..699f7477 100644 --- a/libraries/libapparmor/configure.ac +++ b/libraries/libapparmor/configure.ac @@ -81,7 +81,7 @@ AM_CONDITIONAL(HAVE_RUBY, test x$with_ruby = xyes) AC_HEADER_STDC AC_CHECK_HEADERS(unistd.h stdint.h syslog.h) -AC_CHECK_FUNCS([asprintf __secure_getenv secure_getenv reallocarray]) +AC_CHECK_FUNCS([asprintf __secure_getenv secure_getenv reallocarray scandirat]) AM_PROG_CC_C_O AC_C_CONST diff --git a/libraries/libapparmor/src/private.c b/libraries/libapparmor/src/private.c index f5cc2a4c..5c023d32 100644 --- a/libraries/libapparmor/src/private.c +++ b/libraries/libapparmor/src/private.c @@ -45,6 +45,62 @@ #endif #endif +/** + * Allow libapparmor to build on other libcs that do not support scandirat + */ +#ifndef HAVE_SCANDIRAT +#include + +int scandirat(int dir_fd, const char *dirp, struct dirent ***namelist, + int (*filter)(const struct dirent *), + int (*compar)(const struct dirent **, const struct dirent **)) +{ + int fd; + DIR *d; + struct dirent *de, **names=0, **tmp; + size_t cnt=0, len=0; + int old_errno = errno; + + + fd = openat(dir_fd, dirp, O_RDONLY|O_CLOEXEC); + if (fd == -1) return -1; + + d = fdopendir(fd); + + if (!d) { + close(fd); + return -1; + } + + while ((errno=0), (de = readdir(d))) { + if (filter && !filter(de)) continue; + if (cnt >= len) { + len = 2*len+1; + if (len > SIZE_MAX/sizeof *names) break; + tmp = realloc(names, len * sizeof *names); + if (!tmp) break; + names = tmp; + } + names[cnt] = malloc(de->d_reclen); + if (!names[cnt]) break; + memcpy(names[cnt++], de, de->d_reclen); + } + + closedir(d); + + if (errno) { + if (names) while (cnt-->0) free(names[cnt]); + free(names); + return -1; + } + errno = old_errno; + + if (compar) qsort(names, cnt, sizeof *names, (int (*)(const void *, const void *))compar); + *namelist = names; + return cnt; +} +#endif + /** * Allow libapparmor to build on older glibcs and other libcs that do * not support reallocarray. -- 2.17.1