Use the new modules system in VFS. If a module can't be loaded with the
authorJelmer Vernooij <jelmer@samba.org>
Thu, 27 Mar 2003 12:08:46 +0000 (12:08 +0000)
committerJelmer Vernooij <jelmer@samba.org>
Thu, 27 Mar 2003 12:08:46 +0000 (12:08 +0000)
new modules system, we still fall back to the old system.
(This used to be commit cebe8d8b424f10006f2f791a8f086c6c8a7f5d57)

source3/Makefile.in
source3/configure.in
source3/include/vfs.h
source3/modules/vfs_audit.c
source3/modules/vfs_extd_audit.c
source3/modules/vfs_fake_perms.c
source3/modules/vfs_netatalk.c
source3/modules/vfs_recycle.c
source3/smbd/server.c
source3/smbd/vfs.c

index 4e02eb8317793ddb0c6e6bff3ed9bd69db6427f3..32c8e73b516d62b43fcda852b7129cf5b14da632 100644 (file)
@@ -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
index 82e4b9a50d0949726e940c881f9476e2452cfa0b..a299864068eab197895b5728fe028652d28402a5 100644 (file)
@@ -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)
index 9a0676437138a45fc5d81188d1c525c1b2b2411e..756e417814d0e2bff70833245aafbc4d1c734d2f 100644 (file)
@@ -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);
     
index 1944c98e531c65a2ddf2ea0588da22405673020b..fa9bf67a6720127e5a5f837991faca4cde2b3b99 100644 (file)
@@ -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);
+}
index c75dc1d09c2057db639738e67e371515b38b92f0..f60acab36af71c8f0b1054215d9feca28cd39905 100644 (file)
@@ -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);
+}
index 85515df21af605e875c8e0a00d7e3ec4a184090c..121a99a451927b611013c7d009439bed113c5417 100644 (file)
@@ -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);
 }
index b69a900e14411775482a906b05f258481e4eafef..c9e3cde6210e689430b298d9106e37677a3acec6 100644 (file)
@@ -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);
 }
index ba453bad2cb8135dc684b02f8f98c15e0208e75e..a669d864c6b0b4cdc9d7d0573dbddd7b7ed7b221 100644 (file)
@@ -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);
+}
index 715e9162631f06490e879d961464a3162478149d..7848e71db208be75bcc48515741beab3d012e8df 100644 (file)
@@ -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
index 3bbe8a737a888766cc4205b63c831c7e43c30ec6..cdff26ed1eeb67379f7f23fb318e6df44034ee9e 100644 (file)
 #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));