# #
#############################################################################*/
+#include <dirent.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/queue.h>
#include <systemd/sd-bus.h>
#include <systemd/sd-daemon.h>
#include "config.h"
#include "daemon.h"
#include "logging.h"
+#include "zone.h"
+
+struct nw_daemon_zone {
+ struct nw_zone* zone;
+
+ // Link to the other zones
+ STAILQ_ENTRY(nw_daemon_zone) nodes;
+};
struct nw_daemon {
int nrefs;
// DBus Connection
sd_bus* bus;
+
+ // Zones
+ STAILQ_HEAD(zones, nw_daemon_zone) zones;
};
static int __nw_daemon_terminate(sd_event_source* source, const struct signalfd_siginfo* si,
return 0;
}
-static int nw_daemon_setup(struct nw_daemon* daemon) {
+static int nw_daemon_load_zone_filter(const struct dirent* path) {
+ const char* fn = path->d_name;
+
+ // Ignore everything starting with '.'
+ if (*fn == '.')
+ return 0;
+
+ // Ignore anything that isn't a directory
+ if (path->d_type != DT_DIR)
+ return 0;
+
+ return 1;
+}
+
+static int nw_daemon_add_zone(struct nw_daemon* daemon, struct nw_zone* zone) {
+ // Allocate a new entry
+ struct nw_daemon_zone* entry = calloc(1, sizeof(*entry));
+ if (!entry)
+ return 1;
+
+ // Reference the zone
+ entry->zone = nw_zone_ref(zone);
+
+ // Add it to the list
+ STAILQ_INSERT_TAIL(&daemon->zones, entry, nodes);
+
+ return 0;
+}
+
+static int nw_daemon_load_zones(struct nw_daemon* daemon) {
+ struct dirent** paths = NULL;
+ int n;
+ int r = 0;
+
+ struct nw_zone* zone = NULL;
+
+ // Scan the zones directory
+ n = scandir(CONFIG_DIR "/zones", &paths, nw_daemon_load_zone_filter, alphasort);
+ if (n < 0) {
+ ERROR("Could not load zones: %m\n");
+ return 1;
+ }
+
+ DEBUG("Found %d zone(s)\n", n);
+
+ // Load all zones
+ for (int i = 0; i < n; i++) {
+ const char* name = paths[i]->d_name;
+
+ DEBUG("Loading zone '%s'...\n", name);
+
+ // Create a new zone object
+ r = nw_zone_create(&zone, name);
+ if (r)
+ goto ERROR;
+
+ // Store the zone
+ r = nw_daemon_add_zone(daemon, zone);
+ if (r) {
+ nw_zone_unref(zone);
+ goto ERROR;
+ }
+
+ nw_zone_unref(zone);
+ }
+
+ERROR:
+ // Free paths
+ if (paths) {
+ for (int i = 0; i < n; i++) {
+ free(paths[i]);
+ }
+ free(paths);
+ }
+
+ return r;
+}
+
+static int nw_daemon_load_config(struct nw_daemon* daemon) {
int r;
// Read configuration file
if (r)
return r;
+ // Load zones
+ r = nw_daemon_load_zones(daemon);
+ if (r)
+ return r;
+
+ return r;
+}
+
+static int nw_daemon_setup(struct nw_daemon* daemon) {
+ int r;
+
+ // Read the configuration
+ r = nw_daemon_load_config(daemon);
+ if (r)
+ return r;
+
// Setup the event loop
r = nw_daemon_setup_loop(daemon);
if (r)
// Initialize reference counter
d->nrefs = 1;
+ // Initialize zones
+ STAILQ_INIT(&d->zones);
+
// Setup the daemon
r = nw_daemon_setup(d);
if (r)
return r;
}
+static void nw_daemon_free_zones(struct nw_daemon* daemon) {
+ struct nw_daemon_zone* entry = NULL;
+
+ while (!STAILQ_EMPTY(&daemon->zones)) {
+ entry = STAILQ_FIRST(&daemon->zones);
+
+ // Dereference the zone
+ nw_zone_unref(entry->zone);
+
+ // Remove the entry from the list
+ STAILQ_REMOVE_HEAD(&daemon->zones, nodes);
+
+ // Free the entry
+ free(entry);
+ }
+}
+
static void nw_daemon_free(struct nw_daemon* daemon) {
+ nw_daemon_free_zones(daemon);
+
if (daemon->config)
nw_config_unref(daemon->config);
if (daemon->bus)