From 11db21cc1c00d63c6b23ec6b3a3bdb48728b2b64 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 27 Mar 2003 12:08:46 +0000 Subject: Use the new modules system in VFS. If a module can't be loaded with the new modules system, we still fall back to the old system. (This used to be commit cebe8d8b424f10006f2f791a8f086c6c8a7f5d57) --- source3/Makefile.in | 24 +++---- source3/configure.in | 7 ++ source3/include/vfs.h | 4 +- source3/modules/vfs_audit.c | 14 ++-- source3/modules/vfs_extd_audit.c | 15 ++-- source3/modules/vfs_fake_perms.c | 8 +-- source3/modules/vfs_netatalk.c | 8 +-- source3/modules/vfs_recycle.c | 41 ++--------- source3/smbd/server.c | 2 +- source3/smbd/vfs.c | 143 ++++++++++++++++++++++++++++++--------- 10 files changed, 155 insertions(+), 111 deletions(-) diff --git a/source3/Makefile.in b/source3/Makefile.in index 4e02eb8317..32c8e73b51 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -136,8 +136,7 @@ SCRIPTS = $(srcdir)/script/smbtar $(srcdir)/script/addtosmbpass $(srcdir)/script QUOTAOBJS=@QUOTAOBJS@ -VFS_MODULES = bin/vfs_audit.@SHLIBEXT@ bin/vfs_extd_audit.@SHLIBEXT@ bin/vfs_recycle.@SHLIBEXT@ \ - bin/vfs_netatalk.@SHLIBEXT@ bin/vfs_fake_perms.@SHLIBEXT@ +VFS_MODULES = @VFS_MODULES@ PDB_MODULES = @PDB_MODULES@ RPC_MODULES = @RPC_MODULES@ CHARSET_MODULES = @CHARSET_MODULES@ @@ -327,8 +326,8 @@ SMBD_OBJ_SRV = smbd/files.o smbd/chgpasswd.o smbd/connection.o \ smbd/change_trust_pw.o \ $(MANGLE_OBJ) -SMBD_OBJ_BASE = $(SMBD_OBJ_SRV) $(MSDFS_OBJ) $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) \ - $(RPC_SERVER_OBJ) $(RPC_PARSE_OBJ) $(SECRETS_OBJ) \ +SMBD_OBJ_BASE = $(PARAM_OBJ) $(SMBD_OBJ_SRV) $(MSDFS_OBJ) $(LIBSMB_OBJ) \ + $(RPC_SERVER_OBJ) $(RPC_PARSE_OBJ) $(SECRETS_OBJ) $(UBIQX_OBJ) \ $(LOCKING_OBJ) $(PASSDB_OBJ) $(PRINTING_OBJ) $(PROFILE_OBJ) \ $(LIB_OBJ) $(PRINTBACKEND_OBJ) $(QUOTAOBJS) $(OPLOCK_OBJ) \ $(NOTIFY_OBJ) $(GROUPDB_OBJ) $(AUTH_OBJ) \ @@ -346,8 +345,7 @@ PRINTBACKEND_OBJ = printing/printing.o printing/nt_printing.o printing/notify.o MSDFS_OBJ = msdfs/msdfs.o -SMBD_OBJ = $(SMBD_OBJ_MAIN) $(SMBD_OBJ_BASE) - +SMBD_OBJ = $(SMBD_OBJ_BASE) $(SMBD_OBJ_MAIN) NMBD_OBJ1 = nmbd/asyncdns.o nmbd/nmbd.o nmbd/nmbd_become_dmb.o \ nmbd/nmbd_become_lmb.o nmbd/nmbd_browserdb.o \ nmbd/nmbd_browsesync.o nmbd/nmbd_elections.o \ @@ -603,7 +601,7 @@ NTLM_AUTH_OBJ = utils/ntlm_auth.o $(LIBNTLMSSP_OBJ) $(LIBSAMBA_OBJ) $(POPT_LIB_O # now the rules... ###################################################################### all : SHOWFLAGS proto_exists $(SBIN_PROGS) $(BIN_PROGS) $(SHLIBS) \ - $(TORTURE_PROGS) @EXTRA_ALL_TARGETS@ + $(TORTURE_PROGS) $(MODULES) @EXTRA_ALL_TARGETS@ pam_smbpass : SHOWFLAGS bin/pam_smbpass.@SHLIBEXT@ @@ -1020,27 +1018,27 @@ bin/xml.@SHLIBEXT@: $(XML_OBJ) @$(SHLD) $(LDSHFLAGS) -o $@ $(XML_OBJ) @XML_LIBS@ \ @SONAMEFLAG@`basename $@` -bin/vfs_audit.@SHLIBEXT@: $(VFS_AUDIT_OBJ) +bin/audit.@SHLIBEXT@: $(VFS_AUDIT_OBJ) @echo "Building plugin $@" @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_AUDIT_OBJ) \ @SONAMEFLAG@`basename $@` -bin/vfs_extd_audit.@SHLIBEXT@: $(VFS_EXTD_AUDIT_OBJ) +bin/extd_audit.@SHLIBEXT@: $(VFS_EXTD_AUDIT_OBJ) @echo "Building plugin $@" @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_AUDIT_OBJ) \ @SONAMEFLAG@`basename $@` -bin/vfs_recycle.@SHLIBEXT@: $(VFS_RECYCLE_OBJ) +bin/recycle.@SHLIBEXT@: $(VFS_RECYCLE_OBJ) @echo "Building plugin $@" @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_RECYCLE_OBJ) \ @SONAMEFLAG@`basename $@` -bin/vfs_netatalk.@SHLIBEXT@: $(VFS_NETATALK_OBJ) +bin/netatalk.@SHLIBEXT@: $(VFS_NETATALK_OBJ) @echo "Building plugin $@" @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_NETATALK_OBJ) \ @SONAMEFLAG@`basename $@` -bin/vfs_fake_perms.@SHLIBEXT@: $(VFS_FAKE_PERMS_OBJ) +bin/fake_perms.@SHLIBEXT@: $(VFS_FAKE_PERMS_OBJ) @echo "Building plugin $@" @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_FAKE_PERMS_OBJ) \ @SONAMEFLAG@`basename $@` @@ -1074,7 +1072,7 @@ bin/t_strcmp@EXEEXT@: bin/libbigballofmud.@SHLIBEXT@ torture/t_strcmp.o bin/t_stringoverflow@EXEEXT@: bin/libbigballofmud.@SHLIBEXT@ torture/t_stringoverflow.o $(CC) $(FLAGS) -o $@ torture/t_stringoverflow.o -L./bin -lbigballofmud -install: installbin installman installscripts installdat installswat +install: installbin installman installscripts installdat installswat installmodules # DESTDIR is used here to prevent packagers wasting their time # duplicating the Makefile. Remove it and you will have the privelege diff --git a/source3/configure.in b/source3/configure.in index 82e4b9a50d..a299864068 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -3394,6 +3394,13 @@ SMB_MODULE(vfs_fake_perms, \$(VFS_FAKE_PERMS_OBJ), bin/fake_perms.so, VFS) SMB_MODULE(vfs_netatalk, \$(VFS_NETATALK), bin/netatalk.so, VFS) SMB_SUBSYSTEM(VFS) +SMB_MODULE(vfs_recycle, \$(VFS_RECYCLE_OBJ), bin/recycle.so, VFS) +SMB_MODULE(vfs_audit, \$(VFS_AUDIT_OBJ), bin/audit.so, VFS) +SMB_MODULE(vfs_extd_audit, \$(VFS_EXTD_AUDIT_OBJ), bin/extd_audit.so, VFS) +SMB_MODULE(vfs_fake_perms, \$(VFS_FAKE_PERMS_OBJ), bin/fake_perms.so, VFS) +SMB_MODULE(vfs_netatalk, \$(VFS_NETATALK), bin/netatalk.so, VFS) +SMB_SUBSYSTEM(VFS) + AC_DEFINE_UNQUOTED(STRING_STATIC_MODULES, "$string_static_modules", [String list of builtin modules]) AC_SUBST(MODULES_CLEAN) diff --git a/source3/include/vfs.h b/source3/include/vfs.h index 9a06764371..756e417814 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -48,7 +48,7 @@ #define SMB_VFS_INTERFACE_VERSION 5 -/* Version of supported cascaded interface backward copmatibility. +/* Version of supported cascaded interface backward compatibility. (version 5 corresponds to SMB_VFS_INTERFACE_VERSION 5) It is used in vfs_init_custom() to detect VFS modules which conform to cascaded VFS interface but implement elder version than current version of Samba uses. @@ -77,7 +77,7 @@ is unloaded from smbd process using sys_dlclose(). Prototypes: - vfs_op_tuple *vfs_init(int *vfs_version, const struct vfs_ops *def_vfs_ops, + vfs_op_tuple *vfs_init(const struct vfs_ops *def_vfs_ops, struct smb_vfs_handle_struct *vfs_handle); void vfs_done(connection_struct *conn); diff --git a/source3/modules/vfs_audit.c b/source3/modules/vfs_audit.c index 1944c98e53..fa9bf67a67 100644 --- a/source3/modules/vfs_audit.c +++ b/source3/modules/vfs_audit.c @@ -98,10 +98,9 @@ static vfs_op_tuple audit_ops[] = { /* VFS initialisation function. Return vfs_op_tuple array back to SAMBA. */ -vfs_op_tuple *vfs_init(int *vfs_version, struct vfs_ops *def_vfs_ops, +static vfs_op_tuple *audit_init(const struct vfs_ops *def_vfs_ops, struct smb_vfs_handle_struct *vfs_handle) { - *vfs_version = SMB_VFS_INTERFACE_VERSION; memcpy(&default_vfs_ops, def_vfs_ops, sizeof(struct vfs_ops)); audit_handle = vfs_handle; @@ -111,12 +110,6 @@ vfs_op_tuple *vfs_init(int *vfs_version, struct vfs_ops *def_vfs_ops, return audit_ops; } -/* VFS finalization function. */ -void vfs_done(connection_struct *conn) -{ - syslog(SYSLOG_PRIORITY, "VFS_DONE: vfs module unloaded\n"); -} - /* Implementation of vfs_ops. Pass everything on to the default operation but log event first. */ @@ -276,3 +269,8 @@ static int audit_fchmod_acl(struct files_struct *fsp, int fd, mode_t mode) return result; } + +int vfs_audit_init(void) +{ + return smb_register_vfs("audit", audit_init, SMB_VFS_INTERFACE_VERSION); +} diff --git a/source3/modules/vfs_extd_audit.c b/source3/modules/vfs_extd_audit.c index c75dc1d09c..f60acab36a 100644 --- a/source3/modules/vfs_extd_audit.c +++ b/source3/modules/vfs_extd_audit.c @@ -99,10 +99,9 @@ static vfs_op_tuple audit_ops[] = { /* VFS initialisation function. Return vfs_op_tuple array back to SAMBA. */ -vfs_op_tuple *vfs_init(int *vfs_version, struct vfs_ops *def_vfs_ops, +static vfs_op_tuple *audit_init(const struct vfs_ops *def_vfs_ops, struct smb_vfs_handle_struct *vfs_handle) { - *vfs_version = SMB_VFS_INTERFACE_VERSION; memcpy(&default_vfs_ops, def_vfs_ops, sizeof(struct vfs_ops)); audit_handle = vfs_handle; @@ -113,13 +112,6 @@ vfs_op_tuple *vfs_init(int *vfs_version, struct vfs_ops *def_vfs_ops, return audit_ops; } -/* VFS finalization function. */ - -void vfs_done(connection_struct *conn) -{ - syslog(SYSLOG_PRIORITY, "VFS_DONE: vfs module unloaded\n"); -} - /* Implementation of vfs_ops. Pass everything on to the default operation but log event first. */ @@ -317,3 +309,8 @@ static int audit_fchmod_acl(struct files_struct *fsp, int fd, mode_t mode) return result; } + +int vfs_extd_audit_init(void) +{ + return smb_register_vfs("extd_audit", audit_init, SMB_VFS_INTERFACE_VERSION); +} diff --git a/source3/modules/vfs_fake_perms.c b/source3/modules/vfs_fake_perms.c index 85515df21a..121a99a451 100644 --- a/source3/modules/vfs_fake_perms.c +++ b/source3/modules/vfs_fake_perms.c @@ -267,12 +267,11 @@ static vfs_op_tuple fake_perms_ops[] = { /* VFS initialisation - return initialized vfs_op_tuple array back to Samba */ -vfs_op_tuple *vfs_init(int *vfs_version, struct vfs_ops *def_vfs_ops, +static vfs_op_tuple *fake_perms_init(const struct vfs_ops *def_vfs_ops, struct smb_vfs_handle_struct *vfs_handle) { DEBUG(3, ("Initialising default vfs hooks\n")); - *vfs_version = SMB_VFS_INTERFACE_VERSION; memcpy(&default_vfs_ops, def_vfs_ops, sizeof(struct vfs_ops)); /* Remember vfs_handle for further allocation and referencing of private @@ -282,8 +281,7 @@ vfs_op_tuple *vfs_init(int *vfs_version, struct vfs_ops *def_vfs_ops, return fake_perms_ops; } -/* VFS finalization function */ -void vfs_done(connection_struct *conn) +int vfs_fake_perms_init(void) { - DEBUG(3, ("Finalizing default vfs hooks\n")); + return smb_register_vfs("fake_perms", fake_perms_init, SMB_VFS_INTERFACE_VERSION); } diff --git a/source3/modules/vfs_netatalk.c b/source3/modules/vfs_netatalk.c index b69a900e14..c9e3cde621 100644 --- a/source3/modules/vfs_netatalk.c +++ b/source3/modules/vfs_netatalk.c @@ -410,10 +410,9 @@ static vfs_op_tuple atalk_ops[] = { }; /* VFS initialisation function. Return vfs_op_tuple array back to SAMBA. */ -vfs_op_tuple *vfs_init(int *vfs_version, struct vfs_ops *def_vfs_ops, +static vfs_op_tuple *netatalk_init(const struct vfs_ops *def_vfs_ops, struct smb_vfs_handle_struct *vfs_handle) { - *vfs_version = SMB_VFS_INTERFACE_VERSION; memcpy(&default_vfs_ops, def_vfs_ops, sizeof(struct vfs_ops)); atalk_handle = vfs_handle; @@ -422,8 +421,7 @@ vfs_op_tuple *vfs_init(int *vfs_version, struct vfs_ops *def_vfs_ops, return atalk_ops; } -/* VFS finalization function. */ -void vfs_done(connection_struct *conn) +int vfs_netatalk_init(void) { - DEBUG(3, ("ATALK: vfs module unloaded\n")); + return smb_register_vfs("netatalk", netatalk_init, SMB_VFS_INTERFACE_VERSION); } diff --git a/source3/modules/vfs_recycle.c b/source3/modules/vfs_recycle.c index ba453bad2c..a669d864c6 100644 --- a/source3/modules/vfs_recycle.c +++ b/source3/modules/vfs_recycle.c @@ -87,13 +87,12 @@ static vfs_op_tuple recycle_ops[] = { * * @retval initialised vfs_op_tuple array **/ -vfs_op_tuple *vfs_init(int *vfs_version, struct vfs_ops *def_vfs_ops, +static vfs_op_tuple *recycle_init(const struct vfs_ops *def_vfs_ops, struct smb_vfs_handle_struct *vfs_handle) { TALLOC_CTX *mem_ctx = NULL; DEBUG(10, ("Initializing VFS module recycle\n")); - *vfs_version = SMB_VFS_INTERFACE_VERSION; memcpy(&default_vfs_ops, def_vfs_ops, sizeof(struct vfs_ops)); vfs_recycle_debug_level = debug_add_class("vfs_recycle_bin"); if (vfs_recycle_debug_level == -1) { @@ -120,39 +119,6 @@ vfs_op_tuple *vfs_init(int *vfs_version, struct vfs_ops *def_vfs_ops, return recycle_ops; } -/** - * VFS finalization function. - * - **/ -void vfs_done(void) -{ - recycle_bin_private_data *recdata; - recycle_bin_connections *recconn; - - DEBUG(10, ("Unloading/Cleaning VFS module recycle bin\n")); - - if (recycle_bin_private_handle) - recdata = (recycle_bin_private_data *)(recycle_bin_private_handle->data); - else { - DEBUG(0, ("Recycle bin not initialized!\n")); - return; - } - - if (recdata) { - if (recdata->conns) { - recconn = recdata->conns; - while (recconn) { - talloc_destroy(recconn->data->mem_ctx); - recconn = recconn->next; - } - } - if (recdata->mem_ctx) { - talloc_destroy(recdata->mem_ctx); - } - recdata = NULL; - } -} - static int recycle_connect(struct connection_struct *conn, const char *service, const char *user) { TALLOC_CTX *ctx = NULL; @@ -646,3 +612,8 @@ done: SAFE_FREE(final_name); return rc; } + +int vfs_recycle_init(void) +{ + return smb_register_vfs("recycle", recycle_init, SMB_VFS_INTERFACE_VERSION); +} diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 715e916263..7848e71db2 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -3,7 +3,7 @@ Main SMB server routines Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Martin Pool 2002 - Copyright (C) Jelmer Vernooij 2002 + Copyright (C) Jelmer Vernooij 2002-2003 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by 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 */ @@ -127,6 +134,56 @@ static struct vfs_ops default_vfs_ops = { vfswrap_sys_acl_free_qualifier }; +/**************************************************************************** + 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)); -- cgit