diff --git a/direct.c b/direct.c index 84f40ef..fee733d 100644 --- a/direct.c +++ b/direct.c @@ -160,7 +160,7 @@ direct_readlinkat (struct ovl_layer *l, const char *path, char *buf, size_t bufs } static int -direct_load_data_source (struct ovl_layer *l, const char *opaque, const char *path) +direct_load_data_source (struct ovl_layer *l, const char *opaque, const char *path, int n_layer) { l->path = realpath (path, NULL); if (l->path == NULL) @@ -186,8 +186,15 @@ direct_cleanup (struct ovl_layer *l) return 0; } +static int +direct_num_of_layers (const char *opaque, const char *path) +{ + return 1; +} + struct data_source direct_access_ds = { + .num_of_layers = direct_num_of_layers, .load_data_source = direct_load_data_source, .cleanup = direct_cleanup, .file_exists = direct_file_exists, diff --git a/fuse-overlayfs.h b/fuse-overlayfs.h index 7a3f884..37673a9 100644 --- a/fuse-overlayfs.h +++ b/fuse-overlayfs.h @@ -119,7 +119,8 @@ struct ovl_layer /* a data_source defines the methods for accessing a lower layer. */ struct data_source { - int (*load_data_source)(struct ovl_layer *l, const char *opaque, const char *path); + int (*num_of_layers) (const char *opaque, const char *path); + int (*load_data_source)(struct ovl_layer *l, const char *opaque, const char *path, int n_layer); int (*cleanup)(struct ovl_layer *l); int (*file_exists)(struct ovl_layer *l, const char *pathname); int (*statat)(struct ovl_layer *l, const char *path, struct stat *st, int flags, unsigned int mask); diff --git a/main.c b/main.c index bb912d2..44ba072 100644 --- a/main.c +++ b/main.c @@ -1549,16 +1549,14 @@ read_dirs (struct ovl_data *lo, char *path, bool low, struct ovl_layer *layers) { char *name, *data; char *it_path = it; + int i, n_layers; cleanup_layer struct ovl_layer *l = NULL; - - l = calloc (1, sizeof (*l)); - if (l == NULL) - return NULL; + struct data_source *ds; if (it[0] != '/' || it[1] != '/') { /* By default use the direct access data store. */ - l->ds = &direct_access_ds; + ds = &direct_access_ds; data = NULL; path = it_path; @@ -1603,43 +1601,59 @@ read_dirs (struct ovl_data *lo, char *path, bool low, struct ovl_layer *layers) return NULL; } - l->ds = p->load (l, data, path); - if (l->ds == NULL) + ds = p->load (data, path); + if (ds == NULL) { fprintf (stderr, "cannot load plugin %s\n", name); return NULL; } } - l->ovl_data = lo; - - l->path = NULL; - l->fd = -1; - - if (l->ds->load_data_source (l, data, path) < 0) + n_layers = ds->num_of_layers (data, path); + if (n_layers < 0) { - fprintf (stderr, "cannot load store %s at %s\n", data, path); + fprintf (stderr, "cannot retrieve number of layers for %s\n", path); return NULL; } - l->low = low; - if (low) + for (i = 0; i < n_layers; i++) { - l->next = NULL; - if (last == NULL) - last = layers = l; + l = calloc (1, sizeof (*l)); + if (l == NULL) + return NULL; + + l->ds = ds; + + l->ovl_data = lo; + + l->path = NULL; + l->fd = -1; + + if (l->ds->load_data_source (l, data, path, i) < 0) + { + fprintf (stderr, "cannot load store %s at %s\n", data, path); + return NULL; + } + + l->low = low; + if (low) + { + l->next = NULL; + if (last == NULL) + last = layers = l; + else + { + last->next = l; + last = l; + } + } else { - last->next = l; - last = l; + l->next = layers; + layers = l; } + l = NULL; } - else - { - l->next = layers; - layers = l; - } - l = NULL; } return layers; } diff --git a/plugin-manager.c b/plugin-manager.c index 1d1e4c6..1dea66c 100644 --- a/plugin-manager.c +++ b/plugin-manager.c @@ -110,7 +110,10 @@ plugin_free_all (struct ovl_plugin_context *context) { next = it->next; - dlclose (it->handle); + it->release (); + + /* Skip dlclose (it->handle) as it causes plugins written in Go to crash. */ + free (it); it = next; diff --git a/plugin.h b/plugin.h index ffe3218..a4b444f 100644 --- a/plugin.h +++ b/plugin.h @@ -23,8 +23,8 @@ # include # include -typedef struct data_source *(*plugin_load_data_source)(struct ovl_layer *layer, const char *opaque, const char *path); -typedef int (*plugin_release)(struct ovl_layer *layer); +typedef struct data_source *(*plugin_load_data_source)(const char *opaque, const char *path); +typedef int (*plugin_release)(); typedef const char *(*plugin_name)(); typedef int (*plugin_version)();