The function names must be prepended with "_aa_" since they're going to
be exported from libapparmor. The code bases using the _aa_autofree(),
_aa_autoclose(), and _aa_autofclose() will need to internally alias
those functions to the previously used autofree, autoclose, and
autofclose names.

Signed-off-by: Tyler Hicks <[email protected]>
---
 .../libapparmor/include/sys/apparmor_private.h     |  11 ++
 libraries/libapparmor/src/Makefile.am              |   2 +-
 libraries/libapparmor/src/libapparmor.map          |   4 +
 libraries/libapparmor/src/private.c                | 135 +++++++++++++++++++++
 libraries/libapparmor/src/private.h                |  26 ++++
 parser/lib.c                                       | 133 +-------------------
 parser/lib.h                                       |  11 +-
 7 files changed, 187 insertions(+), 135 deletions(-)
 create mode 100644 libraries/libapparmor/src/private.h

diff --git a/libraries/libapparmor/include/sys/apparmor_private.h 
b/libraries/libapparmor/include/sys/apparmor_private.h
index 6138b2c..5cf4c25 100644
--- a/libraries/libapparmor/include/sys/apparmor_private.h
+++ b/libraries/libapparmor/include/sys/apparmor_private.h
@@ -17,10 +17,21 @@
 #ifndef _SYS_APPARMOR_PRIVATE_H
 #define _SYS_APPARMOR_PRIVATE_H        1
 
+#include <dirent.h>
+#include <stdio.h>
+#include <sys/stat.h>
+
 __BEGIN_DECLS
 
 int _aa_is_blacklisted(const char *name, const char *path);
 
+void _aa_autofree(void *p);
+void _aa_autoclose(int *fd);
+void _aa_autofclose(FILE **f);
+
+int _aa_dirat_for_each(DIR *dir, const char *name, void *data,
+                      int (* cb)(DIR *, const char *, struct stat *, void *));
+
 __END_DECLS
 
 #endif /* sys/apparmor_private.h */
diff --git a/libraries/libapparmor/src/Makefile.am 
b/libraries/libapparmor/src/Makefile.am
index 2a7f600..0a55b34 100644
--- a/libraries/libapparmor/src/Makefile.am
+++ b/libraries/libapparmor/src/Makefile.am
@@ -46,7 +46,7 @@ af_protos.h: /usr/include/netinet/in.h
         LC_ALL=C  sed  -n -e "/IPPROTO_MAX/d"  -e "s/^\#define[ 
\\t]\\+IPPROTO_\\([A-Z0-9_]\\+\\)\\(.*\\)$$/AA_GEN_PROTO_ENT(\\UIPPROTO_\\1, 
\"\\L\\1\")/p" $< > $@
 
 lib_LTLIBRARIES = libapparmor.la
-noinst_HEADERS = grammar.h parser.h scanner.h af_protos.h
+noinst_HEADERS = grammar.h parser.h scanner.h af_protos.h private.h
 
 libapparmor_la_SOURCES = grammar.y libaalogparse.c kernel_interface.c 
scanner.c private.c
 libapparmor_la_LDFLAGS = -version-info 
$(AA_LIB_CURRENT):$(AA_LIB_REVISION):$(AA_LIB_AGE) -XCClinker -dynamic -pthread 
\
diff --git a/libraries/libapparmor/src/libapparmor.map 
b/libraries/libapparmor/src/libapparmor.map
index c7bc606..1ea221f 100644
--- a/libraries/libapparmor/src/libapparmor.map
+++ b/libraries/libapparmor/src/libapparmor.map
@@ -55,6 +55,10 @@ APPARMOR_2.9 {
 PRIVATE {
        global:
                _aa_is_blacklisted;
+               _aa_autofree;
+               _aa_autoclose;
+               _aa_autofclose;
+               _aa_dirat_for_each;
        local:
                *;
 };
diff --git a/libraries/libapparmor/src/private.c 
b/libraries/libapparmor/src/private.c
index f6f40b5..1143a34 100644
--- a/libraries/libapparmor/src/private.c
+++ b/libraries/libapparmor/src/private.c
@@ -14,7 +14,18 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
 #include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "private.h"
 
 struct ignored_suffix_t {
        const char * text;
@@ -64,3 +75,127 @@ int _aa_is_blacklisted(const char *name, const char *path)
 
        return 0;
 }
+
+/* automaticly free allocated variables tagged with autofree on fn exit */
+void _aa_autofree(void *p)
+{
+       void **_p = (void**)p;
+       free(*_p);
+}
+
+void _aa_autoclose(int *fd)
+{
+       if (*fd != -1) {
+               /* if close was interrupted retry */
+               while(close(*fd) == -1 && errno == EINTR);
+               *fd = -1;
+       }
+}
+
+void _aa_autofclose(FILE **f)
+{
+       if (*f) {
+               fclose(*f);
+               *f = NULL;
+       }
+}
+
+/**
+ * dirat_for_each: iterate over a directory calling cb for each entry
+ * @dir: already opened directory (MAY BE NULL)
+ * @name: name of the directory (MAY BE NULL)
+ * @data: data pointer to pass to the callback fn (MAY BE NULL)
+ * @cb: the callback to pass entry too (NOT NULL)
+ *
+ * Iterate over the entries in a directory calling cb for each entry.
+ * The directory to iterate is determined by a combination of @dir and
+ * @name.
+ *
+ * IF @name is a relative path it is determine relative to at @dir if it
+ * is specified, else it the lookup is done relative to the current
+ * working directory.
+ *
+ * If @name is not specified then @dir is used as the directory to iterate
+ * over.
+ *
+ * It is an error if both @name and @dir are null
+ *
+ * The cb function is called with the DIR in use and the name of the
+ * file in that directory.  If the file is to be opened it should
+ * use the openat, fstatat, and related fns.
+ *
+ * Returns: 0 on success, else -1 and errno is set to the error code
+ */
+int _aa_dirat_for_each(DIR *dir, const char *name, void *data,
+                      int (* cb)(DIR *, const char *, struct stat *, void *))
+{
+       autofree struct dirent *dirent = NULL;
+       struct dirent *ent;
+       DIR *d = NULL;
+       int error = 0;
+
+       if (!cb || (!dir && !name)) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       if (dir && (!name || *name != '/')) {
+               dirent = (struct dirent *)
+                       malloc(offsetof(struct dirent, d_name) +
+                              fpathconf(dirfd(dir), _PC_NAME_MAX) + 1);
+       } else {
+               dirent = (struct dirent *)
+                       malloc(offsetof(struct dirent, d_name) +
+                              pathconf(name, _PC_NAME_MAX) + 1);
+       }
+       if (!dirent) {
+               errno = ENOMEM;
+               return -1;
+       }
+
+       if (name) {
+               if (dir && *name != '/') {
+                       int fd = openat(dirfd(dir), name, O_RDONLY);
+                       if (fd == -1)
+                               goto fail;
+                       d = fdopendir(fd);
+               } else {
+                       d = opendir(name);
+               }
+               if (!(d))
+                       goto fail;
+       } else { /* dir && !name */
+               d = dir;
+       }
+
+       for (error = readdir_r(d, dirent, &ent);
+            error == 0 && ent != NULL;
+            error = readdir_r(d, dirent, &ent)) {
+               struct stat my_stat;
+
+               if (strcmp(ent->d_name, ".") == 0 ||
+                   strcmp(ent->d_name, "..") == 0)
+                       continue;
+
+               if (fstatat(dirfd(d), ent->d_name, &my_stat, 0)) {
+                       goto fail;
+               }
+
+               if (cb(d, ent->d_name, &my_stat, data)) {
+                       goto fail;
+               }
+       }
+
+       if (d != dir)
+               closedir(d);
+
+       return error;
+
+fail:
+       error = errno;
+       if (d && d != dir)
+               closedir(d);
+       errno = error;
+
+       return -1;
+}
diff --git a/libraries/libapparmor/src/private.h 
b/libraries/libapparmor/src/private.h
new file mode 100644
index 0000000..3007294
--- /dev/null
+++ b/libraries/libapparmor/src/private.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2014 Canonical Ltd.
+ *
+ * The libapparmor library is licensed under the terms of the GNU
+ * Lesser General Public License, version 2.1. Please see the file
+ * COPYING.LGPL.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _AA_PRIVATE_H
+#define _AA_PRIVATE_H 1
+
+#include <sys/apparmor_private.h>
+
+#define autofree __attribute((cleanup(_aa_autofree)))
+#define autoclose __attribute((cleanup(_aa_autoclose)))
+#define autofclose __attribute((cleanup(_aa_autofclose)))
+
+#endif /* _AA_PRIVATE_H */
diff --git a/parser/lib.c b/parser/lib.c
index 37d0172..15e975d 100644
--- a/parser/lib.c
+++ b/parser/lib.c
@@ -17,46 +17,18 @@
  */
 
 #include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
 #include <string.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <unistd.h>
 
 #include <sys/stat.h>
 #include <sys/types.h>
 
 #include <cstdint>
 
+#include <sys/apparmor_private.h>
+
 #include "lib.h"
 #include "parser.h"
 
-/* automaticly free allocated variables tagged with autofree on fn exit */
-void __autofree(void *p)
-{
-       void **_p = (void**)p;
-       free(*_p);
-}
-
-void __autoclose(int *fd)
-{
-       if (*fd != -1) {
-               /* if close was interrupted retry */
-               while(close(*fd) == -1 && errno == EINTR);
-               *fd = -1;
-       }
-}
-
-void __autofclose(FILE **f)
-{
-       if (*f) {
-               fclose(*f);
-               *f = NULL;
-       }
-}
-
 void atomic_inc(unsigned int *v)
 {
        __sync_add_and_fetch(v, 1);
@@ -67,108 +39,15 @@ bool atomic_dec_and_test(unsigned int *v)
        return __sync_sub_and_fetch(v, 1) == 0;
 }
 
-/**
- * dirat_for_each: iterate over a directory calling cb for each entry
- * @dir: already opened directory (MAY BE NULL)
- * @name: name of the directory (MAY BE NULL)
- * @data: data pointer to pass to the callback fn (MAY BE NULL)
- * @cb: the callback to pass entry too (NOT NULL)
- *
- * Iterate over the entries in a directory calling cb for each entry.
- * The directory to iterate is determined by a combination of @dir and
- * @name.
- *
- * IF @name is a relative path it is determine relative to at @dir if it
- * is specified, else it the lookup is done relative to the current
- * working directory.
- *
- * If @name is not specified then @dir is used as the directory to iterate
- * over.
- *
- * It is an error if both @name and @dir are null
- *
- * The cb function is called with the DIR in use and the name of the
- * file in that directory.  If the file is to be opened it should
- * use the openat, fstatat, and related fns.
- *
- * Returns: 0 on success, else -1 and errno is set to the error code
- */
 int dirat_for_each(DIR *dir, const char *name, void *data,
                   int (* cb)(DIR *, const char *, struct stat *, void *))
 {
-       autofree struct dirent *dirent = NULL;
-       struct dirent *ent;
-       DIR *d = NULL;
-       int error = 0;
-
-       if (!cb || (!dir && !name)) {
-               errno = EINVAL;
-               return -1;
-       }
-
-       if (dir && (!name || *name != '/')) {
-               dirent = (struct dirent *)
-                       malloc(offsetof(struct dirent, d_name) +
-                              fpathconf(dirfd(dir), _PC_NAME_MAX) + 1);
-       } else {
-               dirent = (struct dirent *)
-                       malloc(offsetof(struct dirent, d_name) +
-                              pathconf(name, _PC_NAME_MAX) + 1);
-       }
-       if (!dirent) {
-               PDEBUG("could not alloc dirent");
-               return -1;
-       }
+       int retval = _aa_dirat_for_each(dir, name, data, cb);
 
-       if (name) {
-               if (dir && *name != '/') {
-                       int fd = openat(dirfd(dir), name, O_RDONLY);
-                       if (fd == -1)
-                               goto fail;
-                       d = fdopendir(fd);
-               } else {
-                       d = opendir(name);
-               }
-               PDEBUG("Open dir '%s': %s\n", name, d ? "succeeded" : "failed");
-               if (!(d))
-                       goto fail;
-       } else { /* dir && !name */
-               PDEBUG("Recieved cache directory\n");
-               d = dir;
-       }
-
-       for (error = readdir_r(d, dirent, &ent);
-            error == 0 && ent != NULL;
-            error = readdir_r(d, dirent, &ent)) {
-               struct stat my_stat;
-
-               if (strcmp(ent->d_name, ".") == 0 ||
-                   strcmp(ent->d_name, "..") == 0)
-                       continue;
+       if (retval)
+               PDEBUG("dirat_for_each failed: %m\n");
 
-               if (fstatat(dirfd(d), ent->d_name, &my_stat, 0)) {
-                       PDEBUG("stat failed for '%s'", name);
-                       goto fail;
-               }
-
-               if (cb(d, ent->d_name, &my_stat, data)) {
-                       PDEBUG("dir_for_each callback failed\n");
-                       goto fail;
-               }
-       }
-
-       if (d != dir)
-               closedir(d);
-
-       return error;
-
-fail:
-       error = errno;
-       if (d && d != dir)
-               closedir(d);
-       errno = error;
-
-       return -1;
+       return retval;
 }
 
 /**
diff --git a/parser/lib.h b/parser/lib.h
index bfe53f8..2ec745c 100644
--- a/parser/lib.h
+++ b/parser/lib.h
@@ -1,14 +1,11 @@
 #ifndef __AA_LIB_H_
 #define __AA_LIB_H_
 
-#include <dirent.h>
+#include <sys/apparmor_private.h>
 
-#define autofree __attribute((cleanup(__autofree)))
-#define autoclose __attribute((cleanup(__autoclose)))
-#define autofclose __attribute((cleanup(__autofclose)))
-void __autofree(void *p);
-void __autoclose(int *fd);
-void __autofclose(FILE **f);
+#define autofree __attribute((cleanup(_aa_autofree)))
+#define autoclose __attribute((cleanup(_aa_autoclose)))
+#define autofclose __attribute((cleanup(_aa_autofclose)))
 
 void atomic_inc(unsigned int *v);
 bool atomic_dec_and_test(unsigned int *v);
-- 
2.1.0


-- 
AppArmor mailing list
[email protected]
Modify settings or unsubscribe at: 
https://lists.ubuntu.com/mailman/listinfo/apparmor

Reply via email to