aboutsummaryrefslogtreecommitdiffstats
path: root/testing/apparmor/0005-libapparmor-fix-scandirat-with-musl-libc.patch
blob: 895cd98d711ce857065558d1c8e3d4dfdb16ab17 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
From 1b918a4af49ae4a2644b089ff3263018157365ab Mon Sep 17 00:00:00 2001
From: allgdante <allan.garret@gmail.com>
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 <inttypes.h>
+
+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