summaryrefslogtreecommitdiff
path: root/source3/smbd/vfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbd/vfs.c')
-rw-r--r--source3/smbd/vfs.c143
1 files changed, 110 insertions, 33 deletions
diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index 3bbe8a737a..cdff26ed1e 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -27,6 +27,13 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_VFS
+struct vfs_init_function_entry {
+ char *name;
+ vfs_op_tuple *ops, *(*init)(const struct vfs_ops *, struct smb_vfs_handle_struct *);
+ struct vfs_init_function_entry *prev, *next;
+};
+
+static struct vfs_init_function_entry *backends = NULL;
/* Some structures to help us initialise the vfs operations table */
@@ -128,6 +135,56 @@ static struct vfs_ops default_vfs_ops = {
};
/****************************************************************************
+ maintain the list of available backends
+****************************************************************************/
+
+struct vfs_init_function_entry *vfs_find_backend_entry(const char *name)
+{
+ struct vfs_init_function_entry *entry = backends;
+
+ while(entry) {
+ if (strequal(entry->name, name)) return entry;
+ entry = entry->next;
+ }
+
+ return NULL;
+}
+
+BOOL smb_register_vfs(const char *name, vfs_op_tuple *(*init)(const struct vfs_ops *, struct smb_vfs_handle_struct *), int version)
+{
+ struct vfs_init_function_entry *entry = backends;
+
+ if ((version < SMB_VFS_INTERFACE_CASCADED)) {
+ DEBUG(0, ("vfs_init() returned wrong interface version info (was %d, should be no less than %d)\n",
+ version, SMB_VFS_INTERFACE_VERSION ));
+ return False;
+ }
+
+ if ((version < SMB_VFS_INTERFACE_VERSION)) {
+ DEBUG(0, ("Warning: vfs_init() states that module confirms interface version #%d, current interface version is #%d.\n\
+ Proceeding in compatibility mode, new operations (since version #%d) will fallback to default ones.\n",
+ version, SMB_VFS_INTERFACE_VERSION, version ));
+ return False;
+ }
+
+ while(entry) {
+ if (strequal(entry->name, name)) {
+ DEBUG(0,("VFS module %s already loaded!\n", name));
+ return False;
+ }
+ entry = entry->next;
+ }
+
+ entry = smb_xmalloc(sizeof(struct vfs_init_function_entry));
+ entry->name = smb_xstrdup(name);
+ entry->init = init;
+
+ DLIST_ADD(backends, entry);
+ DEBUG(5, ("Successfully added vfs backend '%s'\n", name));
+ return True;
+}
+
+/****************************************************************************
initialise default vfs hooks
****************************************************************************/
@@ -148,48 +205,68 @@ BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object)
int vfs_version = -1;
vfs_op_tuple *ops, *(*init_fptr)(int *, const struct vfs_ops *, struct smb_vfs_handle_struct *);
int i;
+ struct vfs_init_function_entry *entry;
DEBUG(3, ("Initialising custom vfs hooks from %s\n", vfs_object));
- /* Open object file */
+ if(!backends) static_init_vfs;
+
+ /* First, try to load the module with the new module system */
+ if((entry = vfs_find_backend_entry(vfs_object)) ||
+ (smb_probe_module("vfs", vfs_object) &&
+ (entry = vfs_find_backend_entry(vfs_object)))) {
+
+ DEBUG(0,("Successfully loaded %s with the new modules system\n", vfs_object));
+
+ if ((ops = entry->init(&conn->vfs_ops, conn->vfs_private)) == NULL) {
+ DEBUG(0, ("vfs init function from %s failed\n", vfs_object));
+ sys_dlclose(conn->vfs_private->handle);
+ return False;
+ }
+ } else {
+ /* If that doesn't work, fall back to the old system
+ * (This part should go away after a while, it's only here
+ * for backwards compatibility) */
- if ((conn->vfs_private->handle = sys_dlopen(vfs_object, RTLD_NOW)) == NULL) {
- DEBUG(0, ("Error opening %s: %s\n", vfs_object, sys_dlerror()));
- return False;
- }
+ /* Open object file */
- /* Get handle on vfs_init() symbol */
+ if ((conn->vfs_private->handle = sys_dlopen(vfs_object, RTLD_NOW)) == NULL) {
+ DEBUG(0, ("Error opening %s: %s\n", vfs_object, sys_dlerror()));
+ return False;
+ }
- init_fptr = (vfs_op_tuple *(*)(int *, const struct vfs_ops *, struct smb_vfs_handle_struct *))sys_dlsym(conn->vfs_private->handle, "vfs_init");
+ /* Get handle on vfs_init() symbol */
- if (init_fptr == NULL) {
- DEBUG(0, ("No vfs_init() symbol found in %s\n", vfs_object));
- sys_dlclose(conn->vfs_private->handle);
- return False;
- }
+ init_fptr = (vfs_op_tuple *(*)(int *, const struct vfs_ops *, struct smb_vfs_handle_struct *))sys_dlsym(conn->vfs_private->handle, "vfs_init");
- /* Initialise vfs_ops structure */
+ if (init_fptr == NULL) {
+ DEBUG(0, ("No vfs_init() symbol found in %s\n", vfs_object));
+ sys_dlclose(conn->vfs_private->handle);
+ return False;
+ }
- if ((ops = init_fptr(&vfs_version, &conn->vfs_ops, conn->vfs_private)) == NULL) {
- DEBUG(0, ("vfs_init() function from %s failed\n", vfs_object));
- sys_dlclose(conn->vfs_private->handle);
- return False;
- }
-
- if ((vfs_version < SMB_VFS_INTERFACE_CASCADED)) {
- DEBUG(0, ("vfs_init() returned wrong interface version info (was %d, should be no less than %d)\n",
- vfs_version, SMB_VFS_INTERFACE_VERSION ));
- sys_dlclose(conn->vfs_private->handle);
- return False;
- }
-
- if ((vfs_version < SMB_VFS_INTERFACE_VERSION)) {
- DEBUG(0, ("Warning: vfs_init() states that module confirms interface version #%d, current interface version is #%d.\n\
-Proceeding in compatibility mode, new operations (since version #%d) will fallback to default ones.\n",
- vfs_version, SMB_VFS_INTERFACE_VERSION, vfs_version ));
- sys_dlclose(conn->vfs_private->handle);
- return False;
- }
+ /* Initialise vfs_ops structure */
+ if ((ops = init_fptr(&vfs_version, &conn->vfs_ops, conn->vfs_private)) == NULL) {
+ DEBUG(0, ("vfs_init() function from %s failed\n", vfs_object));
+ sys_dlclose(conn->vfs_private->handle);
+ return False;
+ }
+
+ if ((vfs_version < SMB_VFS_INTERFACE_CASCADED)) {
+ DEBUG(0, ("vfs_init() returned wrong interface version info (was %d, should be no less than %d)\n",
+ vfs_version, SMB_VFS_INTERFACE_VERSION ));
+ sys_dlclose(conn->vfs_private->handle);
+ return False;
+ }
+
+ if ((vfs_version < SMB_VFS_INTERFACE_VERSION)) {
+ DEBUG(0, ("Warning: vfs_init() states that module confirms interface version #%d, current interface version is #%d.\n\
+ Proceeding in compatibility mode, new operations (since version #%d) will fallback to default ones.\n",
+ vfs_version, SMB_VFS_INTERFACE_VERSION, vfs_version ));
+ sys_dlclose(conn->vfs_private->handle);
+ return False;
+ }
+ }
for(i=0; ops[i].op != NULL; i++) {
DEBUG(3, ("Checking operation #%d (type %d, layer %d)\n", i, ops[i].type, ops[i].layer));