[PATCH 1/3] build: Fix up sanitizer library detection
by Mat Martineau
The exported symbol names in libasan/liblsan/libubsan have changed over
time, which broke library detection. We really only care if the
sanitizer libraries are present, but the configure scripts require a
symbol name. '_init' is present in new and old sanitizer libraries.
---
configure.ac | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/configure.ac b/configure.ac
index 0e7cee2..cec3499 100644
--- a/configure.ac
+++ b/configure.ac
@@ -56,13 +56,13 @@ AC_ARG_ENABLE(pie, AC_HELP_STRING([--enable-pie],
])
save_LIBS=$LIBS
-AC_CHECK_LIB(asan, __sanitizer_cov_init)
+AC_CHECK_LIB(asan, _init)
LIBS=$save_LIBS
AC_ARG_ENABLE(asan, AC_HELP_STRING([--enable-asan],
[enable linking with address sanitizer]), [
if (test "${enableval}" = "yes" &&
- test "${ac_cv_lib_asan___sanitizer_cov_init}" = "yes" &&
+ test "${ac_cv_lib_asan__init}" = "yes" &&
test "${ac_cv_prog_cc_asan}" = "yes"); then
CFLAGS="$CFLAGS -fsanitize=address";
LDFLAGS="$LDFLAGS -fsanitize=address"
@@ -70,13 +70,13 @@ AC_ARG_ENABLE(asan, AC_HELP_STRING([--enable-asan],
])
save_LIBS=$LIBS
-AC_CHECK_LIB(lsan, __sanitizer_cov_init)
+AC_CHECK_LIB(lsan, _init)
LIBS=$save_LIBS
AC_ARG_ENABLE(lsan, AC_HELP_STRING([--enable-lsan],
[enable linking with leak sanitizer]), [
if (test "${enableval}" = "yes" &&
- test "${ac_cv_lib_lsan___sanitizer_cov_init}" = "yes" &&
+ test "${ac_cv_lib_lsan__init}" = "yes" &&
test "${ac_cv_prog_cc_lsan}" = "yes"); then
CFLAGS="$CFLAGS -fsanitize=leak";
LDFLAGS="$LDFLAGS -fsanitize=leak"
@@ -84,13 +84,13 @@ AC_ARG_ENABLE(lsan, AC_HELP_STRING([--enable-lsan],
])
save_LIBS=$LIBS
-AC_CHECK_LIB(ubsan, __sanitizer_cov_init)
+AC_CHECK_LIB(ubsan, _init)
LIBS=$save_LIBS
AC_ARG_ENABLE(ubsan, AC_HELP_STRING([--enable-ubsan],
[enable linking with undefined behavior sanitizer]), [
if (test "${enableval}" = "yes" &&
- test "${ac_cv_lib_ubsan___sanitizer_cov_init}" = "yes" &&
+ test "${ac_cv_lib_ubsan__init}" = "yes" &&
test "${ac_cv_prog_cc_ubsan}" = "yes"); then
CFLAGS="$CFLAGS -fsanitize=undefined";
LDFLAGS="$LDFLAGS -fsanitize=undefined"
--
2.18.0
2 years, 6 months
[PATCH] fswatch: add missing limits.h include for NAME_MAX
by maxice8
From: William Maxwell <thinkabit.ukim(a)gmail.com>
fixes compilation on stricter libcs like Musl.
ell/fswatch.c: In function 'inotify_read_cb':
ell/fswatch.c:80:45: error: 'NAME_MAX' undeclared (first use in this function); did you mean 'SIZE_MAX'?
uint8_t buf[sizeof(struct inotify_event) + NAME_MAX + 1]
^~~~~~~~
SIZE_MAX
---
ell/fswatch.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/ell/fswatch.c b/ell/fswatch.c
index c65a1b9..c5980d3 100644
--- a/ell/fswatch.c
+++ b/ell/fswatch.c
@@ -26,6 +26,7 @@
#include <dirent.h>
#include <unistd.h>
+#include <limits.h>
#include <sys/inotify.h>
#include "private.h"
--
2.18.0
2 years, 6 months
[PATCH] fswatch: add missing limits.h include for NAME_MAX
by maxice8
fixes compilation on stricter libcs like Musl.
ell/fswatch.c: In function 'inotify_read_cb':
ell/fswatch.c:80:45: error: 'NAME_MAX' undeclared (first use in this function); did you mean 'SIZE_MAX'?
uint8_t buf[sizeof(struct inotify_event) + NAME_MAX + 1]
^~~~~~~~
SIZE_MAX
---
ell/fswatch.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/ell/fswatch.c b/ell/fswatch.c
index c65a1b9..c5980d3 100644
--- a/ell/fswatch.c
+++ b/ell/fswatch.c
@@ -26,6 +26,7 @@
#include <dirent.h>
#include <unistd.h>
+#include <limits.h>
#include <sys/inotify.h>
#include "private.h"
--
2.18.0
2 years, 6 months
[PATCH 1/2] fswatch: Add fswatch API
by Andrew Zaborowski
Add the header and the implementation for a filesystem watch API. It's
a simple wrapper around the Linux inotify mechanism but not named inotify
so as not to preclude using other mechanisms in the implementation.
---
Makefile.am | 6 +-
ell/ell.h | 1 +
ell/fswatch.c | 255 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ell/fswatch.h | 44 ++++++++++
4 files changed, 304 insertions(+), 2 deletions(-)
create mode 100644 ell/fswatch.c
create mode 100644 ell/fswatch.h
diff --git a/Makefile.am b/Makefile.am
index 100e24c..8203fd4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -45,7 +45,8 @@ pkginclude_HEADERS = ell/ell.h \
ell/pkcs5.h \
ell/file.h \
ell/net.h \
- ell/dhcp.h
+ ell/dhcp.h \
+ ell/fswatch.h
lib_LTLIBRARIES = ell/libell.la
@@ -104,7 +105,8 @@ ell_libell_la_SOURCES = $(linux_headers) \
ell/dhcp-private.h \
ell/dhcp.c \
ell/dhcp-transport.c \
- ell/dhcp-lease.c
+ ell/dhcp-lease.c \
+ ell/fswatch.c
ell_libell_la_LDFLAGS = -no-undefined \
-version-info $(ELL_CURRENT):$(ELL_REVISION):$(ELL_AGE)
diff --git a/ell/ell.h b/ell/ell.h
index 03bb61d..c03faf2 100644
--- a/ell/ell.h
+++ b/ell/ell.h
@@ -53,3 +53,4 @@
#include <ell/dbus-service.h>
#include <ell/dbus-client.h>
#include <ell/dhcp.h>
+#include <ell/fswatch.h>
diff --git a/ell/fswatch.c b/ell/fswatch.c
new file mode 100644
index 0000000..c65a1b9
--- /dev/null
+++ b/ell/fswatch.c
@@ -0,0 +1,255 @@
+/*
+ *
+ * Embedded Linux library
+ *
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <dirent.h>
+#include <unistd.h>
+#include <sys/inotify.h>
+
+#include "private.h"
+#include "util.h"
+#include "io.h"
+#include "queue.h"
+#include "fswatch.h"
+
+static struct l_io *inotify_io;
+static struct l_queue *watches;
+static bool in_notify;
+static bool stale_items;
+
+struct l_fswatch {
+ int id;
+ l_fswatch_cb_t cb;
+ void *user_data;
+ l_fswatch_destroy_cb_t destroy;
+};
+
+#define EVENT_MASK (IN_CREATE | IN_DELETE | IN_DELETE_SELF | \
+ IN_MODIFY | IN_MOVE | IN_MOVE_SELF)
+
+static void l_fswatch_free(void *data)
+{
+ struct l_fswatch *watch = data;
+
+ if (watch->destroy)
+ watch->destroy(watch->user_data);
+
+ l_free(watch);
+}
+
+static void l_fswatch_shutdown(void)
+{
+ if (!inotify_io)
+ return;
+
+ l_io_destroy(inotify_io);
+ inotify_io = NULL;
+}
+
+static bool l_fswatch_remove_func(const void *a, const void *b)
+{
+ const struct l_fswatch *watch = a;
+
+ return !watch->cb;
+}
+
+static bool inotify_read_cb(struct l_io *io, void *user_data)
+{
+ uint8_t buf[sizeof(struct inotify_event) + NAME_MAX + 1]
+ __attribute__ ((aligned(__alignof__(struct inotify_event))));
+ const uint8_t *ptr;
+ const struct inotify_event *event;
+ ssize_t len;
+
+ len = TEMP_FAILURE_RETRY(read(l_io_get_fd(io), buf, sizeof(buf)));
+ if (unlikely(len <= 0))
+ return true;
+
+ in_notify = true;
+
+ for (ptr = buf; ptr < buf + len;
+ ptr += sizeof(struct inotify_event) + event->len) {
+ const struct l_queue_entry *entry;
+ const char *name = NULL;
+
+ event = (struct inotify_event *) ptr;
+
+ if (event->len)
+ name = event->name;
+
+ for (entry = l_queue_get_entries(watches); entry;
+ entry = entry->next) {
+ struct l_fswatch *watch = entry->data;
+
+ if (watch->id != event->wd)
+ continue;
+
+ if ((event->mask & IN_CREATE) && watch->cb)
+ watch->cb(watch, name, L_FSWATCH_EVENT_CREATE,
+ watch->user_data);
+
+ if ((event->mask & (IN_MOVE | IN_MOVE_SELF)) &&
+ watch->cb)
+ watch->cb(watch, name, L_FSWATCH_EVENT_MOVE,
+ watch->user_data);
+
+ if ((event->mask & IN_MODIFY) && watch->cb)
+ watch->cb(watch, name, L_FSWATCH_EVENT_MODIFY,
+ watch->user_data);
+
+ if ((event->mask & (IN_DELETE | IN_DELETE_SELF)) &&
+ watch->cb)
+ watch->cb(watch, name, L_FSWATCH_EVENT_DELETE,
+ watch->user_data);
+
+ if (event->mask & IN_IGNORED) {
+ stale_items = true;
+ watch->cb = NULL;
+ }
+ }
+ }
+
+ in_notify = false;
+
+ if (stale_items) {
+ struct l_fswatch *watch;
+
+ while ((watch = l_queue_remove_if(watches,
+ l_fswatch_remove_func, NULL)))
+ l_fswatch_free(watch);
+
+ stale_items = false;
+
+ if (l_queue_isempty(watches))
+ l_fswatch_shutdown();
+ }
+
+ return true;
+}
+
+static void l_fswatch_io_destroy(void *user_data)
+{
+ l_queue_destroy(watches, l_fswatch_free);
+ watches = NULL;
+}
+
+static bool l_fswatch_init(void)
+{
+ int inotify_fd = inotify_init1(IN_CLOEXEC);
+
+ if (unlikely(inotify_fd < 0))
+ return false;
+
+ inotify_io = l_io_new(inotify_fd);
+ if (unlikely(!inotify_io)) {
+ close(inotify_fd);
+ return false;
+ }
+
+ l_io_set_close_on_destroy(inotify_io, true);
+
+ if (unlikely(!l_io_set_read_handler(inotify_io, inotify_read_cb,
+ NULL, l_fswatch_io_destroy))) {
+ l_io_destroy(inotify_io);
+ return false;
+ }
+
+ return true;
+}
+
+LIB_EXPORT struct l_fswatch *l_fswatch_new(const char *path, l_fswatch_cb_t cb,
+ void *user_data,
+ l_fswatch_destroy_cb_t destroy)
+{
+ struct l_fswatch *watch;
+ int id;
+
+ if (unlikely(!cb))
+ return NULL;
+
+ if (!inotify_io && !l_fswatch_init())
+ return NULL;
+
+ /*
+ * inotify_watch_add already checks if the path is already being
+ * watched and will return the old watch ID so we're fine.
+ */
+ id = inotify_add_watch(l_io_get_fd(inotify_io), path,
+ EVENT_MASK | IN_EXCL_UNLINK);
+ if (unlikely(id < 0)) {
+ if (l_queue_isempty(watches))
+ l_fswatch_shutdown();
+
+ return NULL;
+ }
+
+ watch = l_new(struct l_fswatch, 1);
+ watch->id = id;
+ watch->cb = cb;
+ watch->user_data = user_data;
+ watch->destroy = destroy;
+
+ if (!watches)
+ watches = l_queue_new();
+
+ l_queue_push_tail(watches, watch);
+
+ return watch;
+}
+
+LIB_EXPORT void l_fswatch_destroy(struct l_fswatch *watch)
+{
+ const struct l_queue_entry *entry;
+ int id;
+
+ if (unlikely(!inotify_io || !watch))
+ return;
+
+ id = watch->id;
+
+ /* Check if we have any other watch with the same inotify ID */
+ for (entry = l_queue_get_entries(watches); entry;
+ entry = entry->next) {
+ struct l_fswatch *watch2 = entry->data;
+
+ if (watch2 != watch && watch2->id == id)
+ break;
+ }
+
+ if (!entry && id != -1)
+ inotify_rm_watch(l_io_get_fd(inotify_io), id);
+
+ if (in_notify) {
+ watch->cb = NULL;
+ stale_items = true;
+ return;
+ }
+
+ l_queue_remove(watches, watch);
+ l_fswatch_free(watch);
+
+ if (l_queue_isempty(watches))
+ l_fswatch_shutdown();
+}
diff --git a/ell/fswatch.h b/ell/fswatch.h
new file mode 100644
index 0000000..419df09
--- /dev/null
+++ b/ell/fswatch.h
@@ -0,0 +1,44 @@
+/*
+ *
+ * Embedded Linux library
+ *
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __ELL_FSWATCH_H
+#define __ELL_FSWATCH_H
+
+struct l_fswatch;
+
+enum l_fswatch_event {
+ L_FSWATCH_EVENT_CREATE,
+ L_FSWATCH_EVENT_MOVE,
+ L_FSWATCH_EVENT_MODIFY,
+ L_FSWATCH_EVENT_DELETE,
+};
+
+typedef void (*l_fswatch_cb_t) (struct l_fswatch *watch, const char *filename,
+ enum l_fswatch_event event, void *user_data);
+typedef void (*l_fswatch_destroy_cb_t) (void *user_data);
+
+struct l_fswatch *l_fswatch_new(const char *path, l_fswatch_cb_t cb,
+ void *user_data,
+ l_fswatch_destroy_cb_t destroy);
+void l_fswatch_destroy(struct l_fswatch *watch);
+
+#endif /* __ELL_FSWATCH_H */
--
2.14.1
2 years, 6 months
[PATCH 1/2] fswatch: Add fswatch API
by Andrew Zaborowski
Add the header and the implementation for a filesystem watch API. It's
a simple wrapper around the Linux inotify mechanism but not named inotify
so as not to preclude using other mechanisms in the implementation.
---
Makefile.am | 6 +-
ell/ell.h | 1 +
ell/fswatch.c | 257 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ell/fswatch.h | 45 ++++++++++
4 files changed, 307 insertions(+), 2 deletions(-)
create mode 100644 ell/fswatch.c
create mode 100644 ell/fswatch.h
diff --git a/Makefile.am b/Makefile.am
index 100e24c..8203fd4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -45,7 +45,8 @@ pkginclude_HEADERS = ell/ell.h \
ell/pkcs5.h \
ell/file.h \
ell/net.h \
- ell/dhcp.h
+ ell/dhcp.h \
+ ell/fswatch.h
lib_LTLIBRARIES = ell/libell.la
@@ -104,7 +105,8 @@ ell_libell_la_SOURCES = $(linux_headers) \
ell/dhcp-private.h \
ell/dhcp.c \
ell/dhcp-transport.c \
- ell/dhcp-lease.c
+ ell/dhcp-lease.c \
+ ell/fswatch.c
ell_libell_la_LDFLAGS = -no-undefined \
-version-info $(ELL_CURRENT):$(ELL_REVISION):$(ELL_AGE)
diff --git a/ell/ell.h b/ell/ell.h
index 03bb61d..c03faf2 100644
--- a/ell/ell.h
+++ b/ell/ell.h
@@ -53,3 +53,4 @@
#include <ell/dbus-service.h>
#include <ell/dbus-client.h>
#include <ell/dhcp.h>
+#include <ell/fswatch.h>
diff --git a/ell/fswatch.c b/ell/fswatch.c
new file mode 100644
index 0000000..638bdf0
--- /dev/null
+++ b/ell/fswatch.c
@@ -0,0 +1,257 @@
+/*
+ *
+ * Embedded Linux library
+ *
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <dirent.h>
+#include <unistd.h>
+#include <sys/inotify.h>
+
+#include "private.h"
+#include "util.h"
+#include "io.h"
+#include "queue.h"
+#include "fswatch.h"
+
+static struct l_io *inotify_io;
+static struct l_queue *watches;
+static bool in_notify;
+static bool stale_items;
+
+struct l_fswatch {
+ int id;
+ l_fswatch_cb_t cb;
+ void *user_data;
+ l_fswatch_destroy_cb_t destroy;
+};
+
+#define EVENT_MASK (IN_CREATE | IN_DELETE | IN_DELETE_SELF | \
+ IN_MODIFY | IN_MOVE | IN_MOVE_SELF)
+
+static void l_fswatch_free(void *data)
+{
+ struct l_fswatch *watch = data;
+
+ if (watch->destroy)
+ watch->destroy(watch, watch->user_data);
+
+ l_free(watch);
+}
+
+static void l_fswatch_shutdown(void)
+{
+ if (!inotify_io)
+ return;
+
+ l_io_destroy(inotify_io);
+ inotify_io = NULL;
+}
+
+static bool l_fswatch_remove_func(const void *a, const void *b)
+{
+ const struct l_fswatch *watch = a;
+
+ return !watch->cb;
+}
+
+static bool inotify_read_cb(struct l_io *io, void *user_data)
+{
+ uint8_t buf[sizeof(struct inotify_event) + NAME_MAX + 1];
+ const struct inotify_event *event;
+ ssize_t len;
+ enum l_fswatch_event event_type;
+
+ len = read(l_io_get_fd(io), buf, sizeof(buf));
+ if (unlikely(len <= 0))
+ return true;
+
+ event = (struct inotify_event *) buf;
+
+ if (event->mask & IN_CREATE)
+ event_type = L_FSWATCH_EVENT_CREATE;
+ else if (event->mask & (IN_DELETE | IN_DELETE_SELF))
+ event_type = L_FSWATCH_EVENT_DELETE;
+ else if (event->mask & (IN_MOVE | IN_MOVE_SELF))
+ event_type = L_FSWATCH_EVENT_MOVE;
+ else
+ event_type = L_FSWATCH_EVENT_MODIFY;
+
+ in_notify = true;
+
+ while ((size_t) len >= sizeof(struct inotify_event) + event->len) {
+ const struct l_queue_entry *entry;
+ const uint8_t *next_ptr;
+ const char *name = NULL;
+
+ if (event->len)
+ name = event->name;
+
+ for (entry = l_queue_get_entries(watches); entry;
+ entry = entry->next) {
+ struct l_fswatch *watch = entry->data;
+
+ if (watch->id != event->wd)
+ continue;
+
+ if ((event->mask & EVENT_MASK) && watch->cb)
+ watch->cb(watch, name, event_type,
+ watch->user_data);
+
+ if (event->mask & IN_IGNORED) {
+ stale_items = true;
+ watch->cb = NULL;
+ }
+ }
+
+ len -= sizeof(struct inotify_event) + event->len;
+ /* event->len is supposed to include alignment */
+ next_ptr = (const uint8_t *) (event + 1) + event->len;
+ event = (struct inotify_event *) next_ptr;
+ }
+
+ in_notify = false;
+
+ if (stale_items) {
+ struct l_fswatch *watch;
+
+ while ((watch = l_queue_remove_if(watches,
+ l_fswatch_remove_func, NULL)))
+ l_fswatch_free(watch);
+
+ stale_items = false;
+
+ if (l_queue_isempty(watches))
+ l_fswatch_shutdown();
+ }
+
+ return true;
+}
+
+static void l_fswatch_io_destroy(void *user_data)
+{
+ l_queue_destroy(watches, l_fswatch_free);
+ watches = NULL;
+}
+
+static bool l_fswatch_init(void)
+{
+ int inotify_fd = inotify_init1(IN_CLOEXEC);
+
+ if (unlikely(inotify_fd < 0))
+ return false;
+
+ inotify_io = l_io_new(inotify_fd);
+ if (unlikely(!inotify_io)) {
+ close(inotify_fd);
+ return false;
+ }
+
+ l_io_set_close_on_destroy(inotify_io, true);
+
+ if (unlikely(!l_io_set_read_handler(inotify_io, inotify_read_cb,
+ NULL, l_fswatch_io_destroy))) {
+ l_io_destroy(inotify_io);
+ return false;
+ }
+
+ return true;
+}
+
+LIB_EXPORT struct l_fswatch *l_fswatch_new(const char *path, l_fswatch_cb_t cb,
+ void *user_data,
+ l_fswatch_destroy_cb_t destroy)
+{
+ struct l_fswatch *watch;
+ int id;
+
+ if (unlikely(!cb))
+ return NULL;
+
+ if (!inotify_io && !l_fswatch_init())
+ return NULL;
+
+ /*
+ * inotify_watch_add already checks if the path is already being
+ * watched and will return the old watch ID so we're fine.
+ */
+ id = inotify_add_watch(l_io_get_fd(inotify_io), path,
+ EVENT_MASK | IN_EXCL_UNLINK);
+ if (unlikely(id < 0)) {
+ if (l_queue_isempty(watches))
+ l_fswatch_shutdown();
+
+ return NULL;
+ }
+
+ watch = l_new(struct l_fswatch, 1);
+ watch->id = id;
+ watch->cb = cb;
+ watch->user_data = user_data;
+ watch->destroy = destroy;
+
+ if (!watches)
+ watches = l_queue_new();
+
+ l_queue_push_tail(watches, watch);
+
+ return watch;
+}
+
+LIB_EXPORT bool l_fswatch_destroy(struct l_fswatch *watch)
+{
+ const struct l_queue_entry *entry;
+ int id;
+
+ if (unlikely(!inotify_io || !watch))
+ return false;
+
+ id = watch->id;
+
+ /* Check if we have any other watch with the same inotify ID */
+ for (entry = l_queue_get_entries(watches); entry;
+ entry = entry->next) {
+ struct l_fswatch *watch2 = entry->data;
+
+ if (watch2 != watch && watch2->id == id)
+ break;
+ }
+
+ if (!entry && id != -1)
+ if (inotify_rm_watch(l_io_get_fd(inotify_io), id) < 0)
+ return false;
+
+ if (in_notify) {
+ watch->cb = NULL;
+ stale_items = true;
+ return true;
+ }
+
+ l_queue_remove(watches, watch);
+ l_fswatch_free(watch);
+
+ if (l_queue_isempty(watches))
+ l_fswatch_shutdown();
+
+ return true;
+}
diff --git a/ell/fswatch.h b/ell/fswatch.h
new file mode 100644
index 0000000..79b379c
--- /dev/null
+++ b/ell/fswatch.h
@@ -0,0 +1,45 @@
+/*
+ *
+ * Embedded Linux library
+ *
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __ELL_FSWATCH_H
+#define __ELL_FSWATCH_H
+
+struct l_fswatch;
+
+enum l_fswatch_event {
+ L_FSWATCH_EVENT_CREATE,
+ L_FSWATCH_EVENT_MOVE,
+ L_FSWATCH_EVENT_MODIFY,
+ L_FSWATCH_EVENT_DELETE,
+};
+
+typedef void (*l_fswatch_cb_t) (struct l_fswatch *watch, const char *filename,
+ enum l_fswatch_event event, void *user_data);
+typedef void (*l_fswatch_destroy_cb_t) (struct l_fswatch *watch,
+ void *user_data);
+
+struct l_fswatch *l_fswatch_new(const char *path, l_fswatch_cb_t cb,
+ void *user_data,
+ l_fswatch_destroy_cb_t destroy);
+bool l_fswatch_destroy(struct l_fswatch *watch);
+
+#endif /* __ELL_FSWATCH_H */
--
2.14.1
2 years, 6 months
[PATCH 1/3] Move TEMP_FAILURE_RETRY outside dbus.h
by Andrew Zaborowski
Make this macro available for the rest of ell in private.h and on the
other hand remove from public header as it doesn't start with "L_".
Note that IWD does optionally use it in rfkill.c and storage.c.
---
ell/dbus.h | 10 ----------
ell/private.h | 11 +++++++++++
2 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/ell/dbus.h b/ell/dbus.h
index 3ff5e0f..a7c08d2 100644
--- a/ell/dbus.h
+++ b/ell/dbus.h
@@ -28,16 +28,6 @@
#include <stddef.h>
#include <stdarg.h>
-/* taken from glibc unistd.h for musl support */
-#ifndef TEMP_FAILURE_RETRY
-#define TEMP_FAILURE_RETRY(expression) \
- (__extension__ \
- ({ long int __result; \
- do __result = (long int) (expression); \
- while (__result == -1L && errno == EINTR); \
- __result; }))
-#endif
-
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/ell/private.h b/ell/private.h
index ed0297d..bf71f6d 100644
--- a/ell/private.h
+++ b/ell/private.h
@@ -21,6 +21,7 @@
*/
#include <stdint.h>
+#include <errno.h>
#include <ell/util.h>
@@ -34,6 +35,16 @@
#define LIB_EXPORT __attribute__ ((visibility("default")))
+/* taken from glibc unistd.h for musl support */
+#ifndef TEMP_FAILURE_RETRY
+#define TEMP_FAILURE_RETRY(expression) \
+ (__extension__ \
+ ({ long int __result; \
+ do __result = (long int) (expression); \
+ while (__result == -1L && errno == EINTR); \
+ __result; }))
+#endif
+
struct l_debug_desc;
void debug_enable(struct l_debug_desc *start, struct l_debug_desc *stop);
--
2.14.1
2 years, 6 months
[PATCH 1/2] fswatch: Add fswatch API
by Andrew Zaborowski
Add the header and the implementation for a filesystem watch API. It's
a simple wrapper around the Linux inotify mechanism but not named inotify
so as not to preclude using other mechanisms in the implemntation.
---
Makefile.am | 6 +-
ell/ell.h | 1 +
ell/fswatch.c | 231 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ell/fswatch.h | 35 +++++++++
4 files changed, 271 insertions(+), 2 deletions(-)
create mode 100644 ell/fswatch.c
create mode 100644 ell/fswatch.h
diff --git a/Makefile.am b/Makefile.am
index 100e24c..8203fd4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -45,7 +45,8 @@ pkginclude_HEADERS = ell/ell.h \
ell/pkcs5.h \
ell/file.h \
ell/net.h \
- ell/dhcp.h
+ ell/dhcp.h \
+ ell/fswatch.h
lib_LTLIBRARIES = ell/libell.la
@@ -104,7 +105,8 @@ ell_libell_la_SOURCES = $(linux_headers) \
ell/dhcp-private.h \
ell/dhcp.c \
ell/dhcp-transport.c \
- ell/dhcp-lease.c
+ ell/dhcp-lease.c \
+ ell/fswatch.c
ell_libell_la_LDFLAGS = -no-undefined \
-version-info $(ELL_CURRENT):$(ELL_REVISION):$(ELL_AGE)
diff --git a/ell/ell.h b/ell/ell.h
index 03bb61d..c03faf2 100644
--- a/ell/ell.h
+++ b/ell/ell.h
@@ -53,3 +53,4 @@
#include <ell/dbus-service.h>
#include <ell/dbus-client.h>
#include <ell/dhcp.h>
+#include <ell/fswatch.h>
diff --git a/ell/fswatch.c b/ell/fswatch.c
new file mode 100644
index 0000000..1ac80e4
--- /dev/null
+++ b/ell/fswatch.c
@@ -0,0 +1,231 @@
+/*
+ *
+ * Embedded Linux library
+ *
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <dirent.h>
+#include <unistd.h>
+#include <sys/inotify.h>
+
+#include "private.h"
+#include "util.h"
+#include "io.h"
+#include "queue.h"
+#include "fswatch.h"
+
+static struct l_io *inotify_io;
+static struct l_queue *watches;
+static bool in_notify;
+static bool stale_items;
+
+struct l_fswatch {
+ char *path;
+ int id;
+ l_fswatch_cb_t cb;
+ void *user_data;
+};
+
+#define EVENT_MASK (IN_CREATE | IN_DELETE | IN_DELETE_SELF | \
+ IN_MODIFY | IN_MOVE | IN_MOVE_SELF)
+
+typedef void (*l_fswatch_cb_t) (struct l_fswatch *watch, const char *filename,
+ void *user_data);
+
+static void l_fswatch_destroy(void *data)
+{
+ struct l_fswatch *watch = data;
+
+ l_free(watch->path);
+ l_free(watch);
+}
+
+static void l_fswatch_shutdown(void)
+{
+ if (!inotify_io)
+ return;
+
+ l_io_destroy(inotify_io);
+ inotify_io = NULL;
+
+ l_queue_destroy(watches, l_fswatch_destroy);
+ watches = NULL;
+}
+
+static bool l_fswatch_remove_func(void *data, void *user_data)
+{
+ struct l_fswatch *watch = data;
+
+ if (watch->cb)
+ return false;
+
+ l_fswatch_destroy(watch);
+
+ return true;
+}
+
+static bool inotify_read_cb(struct l_io *io, void *user_data)
+{
+ uint8_t buf[sizeof(struct inotify_event) + NAME_MAX + 1];
+ const struct inotify_event *event;
+ ssize_t len;
+
+ len = read(l_io_get_fd(io), buf, sizeof(buf));
+ if (unlikely(len <= 0))
+ return true;
+
+ event = (struct inotify_event *) buf;
+ in_notify = true;
+
+ while ((size_t) len >= sizeof(struct inotify_event) + event->len) {
+ const struct l_queue_entry *entry;
+ const uint8_t *next_ptr;
+ const char *name = NULL;
+
+ if (event->len)
+ name = event->name;
+
+ for (entry = l_queue_get_entries(watches); entry;
+ entry = entry->next) {
+ struct l_fswatch *watch = entry->data;
+
+ if (watch->id != event->wd)
+ continue;
+
+ if (event->mask & IN_IGNORED)
+ watch->id = -1;
+
+ if ((event->mask & EVENT_MASK) && watch->cb)
+ watch->cb(watch, name, watch->user_data);
+ }
+
+ len -= sizeof(struct inotify_event) + event->len;
+ /* event->len is supposed to include alignment */
+ next_ptr = (const uint8_t *) (event + 1) + event->len;
+ event = (struct inotify_event *) next_ptr;
+ }
+
+ in_notify = false;
+
+ if (stale_items) {
+ l_queue_foreach_remove(watches, l_fswatch_remove_func, NULL);
+ stale_items = false;
+
+ if (l_queue_isempty(watches))
+ l_fswatch_shutdown();
+ }
+
+ return true;
+}
+
+LIB_EXPORT struct l_fswatch *l_fswatch_new(const char *path, l_fswatch_cb_t cb,
+ void *user_data)
+{
+ struct l_fswatch *watch;
+ int id;
+
+ if (!inotify_io) {
+ int inotify_fd = inotify_init1(IN_CLOEXEC);
+
+ if (unlikely(inotify_fd < 0))
+ return NULL;
+
+ inotify_io = l_io_new(inotify_fd);
+ if (unlikely(!inotify_io)) {
+ close(inotify_fd);
+ return NULL;
+ }
+
+ l_io_set_close_on_destroy(inotify_io, true);
+
+ if (unlikely(!l_io_set_read_handler(inotify_io, inotify_read_cb,
+ NULL, NULL))) {
+ l_io_destroy(inotify_io);
+ return NULL;
+ }
+ }
+
+ /*
+ * inotify_watch_add already checks if the path is already being
+ * watched and will return the old watch ID so we're fine.
+ */
+ id = inotify_add_watch(l_io_get_fd(inotify_io), path,
+ EVENT_MASK | IN_EXCL_UNLINK);
+ if (unlikely(id < 0)) {
+ if (l_queue_isempty(watches))
+ l_fswatch_shutdown();
+
+ return NULL;
+ }
+
+ watch = l_new(struct l_fswatch, 1);
+ watch->path = l_strdup(path);
+ watch->id = id;
+ watch->cb = cb;
+ watch->user_data = user_data;
+
+ if (!watches)
+ watches = l_queue_new();
+
+ l_queue_push_tail(watches, watch);
+
+ return watch;
+}
+
+LIB_EXPORT bool l_fswatch_remove(struct l_fswatch *watch)
+{
+ const struct l_queue_entry *entry;
+ int id;
+
+ if (unlikely(!inotify_io || !watch))
+ return false;
+
+ id = watch->id;
+
+ /* Check if we have any other watch with the same inotify ID */
+ for (entry = l_queue_get_entries(watches); entry;
+ entry = entry->next) {
+ struct l_fswatch *watch2 = entry->data;
+
+ if (watch2 != watch && watch2->id == id)
+ break;
+ }
+
+ if (!entry && id != -1)
+ if (inotify_rm_watch(l_io_get_fd(inotify_io), id) < 0)
+ return false;
+
+ if (in_notify) {
+ watch->cb = NULL;
+ stale_items = false;
+ return true;
+ }
+
+ l_queue_remove(watches, watch);
+ l_fswatch_destroy(watch);
+
+ if (l_queue_isempty(watches))
+ l_fswatch_shutdown();
+
+ return true;
+}
diff --git a/ell/fswatch.h b/ell/fswatch.h
new file mode 100644
index 0000000..1aa18ad
--- /dev/null
+++ b/ell/fswatch.h
@@ -0,0 +1,35 @@
+/*
+ *
+ * Embedded Linux library
+ *
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __ELL_FSWATCH_H
+#define __ELL_FSWATCH_H
+
+struct l_fswatch;
+
+typedef void (*l_fswatch_cb_t) (struct l_fswatch *watch, const char *filename,
+ void *user_data);
+
+struct l_fswatch *l_fswatch_new(const char *path, l_fswatch_cb_t cb,
+ void *user_data);
+bool l_fswatch_remove(struct l_fswatch *watch);
+
+#endif /* __ELL_FSWATCH_H */
--
2.14.1
2 years, 6 months
[PATCHv2] dhcp: include if_arp.h from libc instead of linux headers
by Martin Hundebøll
Compilation with musl libc fails due to redefinition of 'struct
arp{req,req_old,hdr}' in linux/if_arp.h, since it is already defined and
included in net/if_arp.h (through net/ethernet.h -> net/if_ether.h).
The only symbols used from if_arp.h is ARPHRD_ETHER, so it should be
safe to avoid the compile error by including the if_arp.h header from
the c-library instead.
---
Changes in v2:
- Rebased on master
- Removed signed-of-by
ell/dhcp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ell/dhcp.c b/ell/dhcp.c
index 6c90370..0d99f74 100644
--- a/ell/dhcp.c
+++ b/ell/dhcp.c
@@ -27,7 +27,7 @@
#include <netinet/ip.h>
#include <net/ethernet.h>
#include <linux/types.h>
-#include <linux/if_arp.h>
+#include <net/if_arp.h>
#include <errno.h>
#include <time.h>
--
2.18.0
2 years, 6 months
[PATCH] dhcp: include if_arp.h from libc instead of linux headers
by Martin Hundebøll
Compilation with musl libc fails due to redefinition of 'struct
arp{req,req_old,hdr}' in linux/if_arp.h, since it is already defined and
included in net/if_arp.h (through net/ethernet.h -> net/if_ether.h).
The only symbols used from if_arp.h is ARPHRD_ETHER, so it should be
safe to avoid the compile error by including the if_arp.h header from
the c-library instead.
Signed-off-by: Martin Hundebøll <martin(a)geanix.com>
---
ell/dhcp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ell/dhcp.c b/ell/dhcp.c
index 6c90370..0d99f74 100644
--- a/ell/dhcp.c
+++ b/ell/dhcp.c
@@ -27,7 +27,7 @@
#include <netinet/ip.h>
#include <net/ethernet.h>
#include <linux/types.h>
-#include <linux/if_arp.h>
+#include <net/if_arp.h>
#include <errno.h>
#include <time.h>
-- 2.18.0
2 years, 6 months