[PATCH] Parametrical options for HEAD [v.2]

Alexander Bokovoy a.bokovoy at sam-solutions.net
Tue Dec 3 14:23:00 GMT 2002


Greetings!

Attached is the latest patch for improving parametrical options support in
HEAD after testing with Metze and Simo.

Changes since v.1:

- Fixed case in get_parametrics() when
  ServicePtrs[lookup_service]->param_opt was NULL

- Fixed debug level for freeing service's parametrics.

-- 
/ Alexander Bokovoy
---
You may already be a loser.
		-- Form letter received by Rodney Dangerfield.
-------------- next part --------------
--- samba-3.0.build/source/param/loadparm.c.parametric	2002-11-25 12:27:59 +0200
+++ samba-3.0.build/source/param/loadparm.c	2002-12-03 15:56:09 +0200
@@ -7,6 +7,7 @@
 
    Copyright (C) Simo Sorce 2001
    Copyright (C) Alexander Bokovoy 2002
+   Copyright (C) Stefan (metze) Metzmacher 2002
    
    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
@@ -80,6 +81,13 @@
 
 static BOOL defaults_saved = False;
 
+typedef struct _param_opt_struct param_opt_struct;
+struct _param_opt_struct {
+	param_opt_struct *prev, *next;
+	char *key;
+	char *value;
+};
+
 /* 
  * This structure describes global (ie., server-wide) parameters.
  */
@@ -266,6 +274,7 @@
 	BOOL bDisableNetbios;
 	int restrict_anonymous;
 	int name_cache_timeout;
+	param_opt_struct *param_opt;
 }
 global;
 
@@ -386,6 +395,7 @@
 	BOOL bNTAclSupport;
 	BOOL bUseSendfile;
 	BOOL bProfileAcls;
+	param_opt_struct *param_opt;
 
 	char dummy[3];		/* for alignment */
 }
@@ -504,6 +514,8 @@
 	True,			/* bNTAclSupport */
 	False,			/* bUseSendfile */
 	False,			/* bProfileAcls */
+	
+	NULL,			/* Parametric options */
 
 	""			/* dummy */
 };
@@ -1799,53 +1811,10 @@
 FN_GLOBAL_BOOL(lp_algorithmic_rid_base, &Globals.bAlgorithmicRidBase)
 FN_GLOBAL_INTEGER(lp_name_cache_timeout, &Globals.name_cache_timeout)
 
-typedef struct _param_opt_struct param_opt_struct;
-struct _param_opt_struct {
-	char *key;
-	char *value;
-	param_opt_struct *prev, *next;
-};
-
-static param_opt_struct *param_opt = NULL;
-
-/* Return parametric option from given service. Type is a part of option before ':' */
-/* Parametric option has following syntax: 'Type: option = value' */
-/* Returned value is allocated in 'lp_talloc' context */
-
-char *lp_parm_string(const char *servicename, const char *type, const char *option)
-{
-    param_opt_struct *data;
-    pstring vfskey;
-    
-    if (param_opt != NULL) {
-	    ZERO_STRUCT(vfskey);
-	    pstr_sprintf(vfskey, "%s:%s:%s", (servicename==NULL) ? "global" : servicename,
-		    type, option);
-	    data = param_opt;
-	    while (data) {
-		    if (strcmp(data->key, vfskey) == 0) {
-			    return lp_string(data->value);
-		    }
-		    data = data->next;
-	    }
-	    /* Try to fetch the same option but from globals */
-	    pstr_sprintf(vfskey, "global:%s:%s", type, option);
-	    data = param_opt;
-	    while (data) {
-		    if (strcmp(data->key, vfskey) == 0) {
-			    return lp_string(data->value);
-		    }
-		    data = data->next;
-	    }
-	
-    }
-    return NULL;
-}
-
 /* local prototypes */
 
 static int map_parameter(char *pszParmName);
-static BOOL set_boolean(BOOL *pb, char *pszParmValue);
+static BOOL set_boolean(BOOL *pb, const char *pszParmValue);
 static int getservicebyname(const char *pszServiceName,
 			    service * pserviceDest);
 static void copy_service(service * pserviceDest,
@@ -1855,6 +1824,198 @@
 static BOOL do_section(char *pszSectionName);
 static void init_copymap(service * pservice);
 
+/* This is a helper function for parametrical options support. */
+/* It returns a pointer to parametrical option value if it exists or NULL otherwise */
+/* Actual parametrical functions are quite simple */
+static const char *get_parametrics(int lookup_service, const char *type, const char *option)
+{
+	char* vfskey;
+        param_opt_struct *data;
+	
+	if (lookup_service >= iNumServices) return NULL;
+	
+	data = (lookup_service < 0) ? 
+		Globals.param_opt : ServicePtrs[lookup_service]->param_opt;
+    
+	asprintf(&vfskey, "%s:%s", type, option);
+	while (data) {
+		if (strcmp(data->key, vfskey) == 0) {
+			string_free(&vfskey);
+			return data->value;
+		}
+		data = data->next;
+	}
+
+	if (lookup_service >= 0) {
+		/* Try to fetch the same option but from globals */
+		/* but only if we are not already working with Globals */
+		data = Globals.param_opt;
+		while (data) {
+			if (strcmp(data->key, vfskey) == 0) {
+				string_free(&vfskey);
+				return data->value;
+			}
+			data = data->next;
+		}
+	}
+
+	string_free(&vfskey);
+	
+	return NULL;
+}
+
+
+/*******************************************************************
+convenience routine to return int parameters.
+********************************************************************/
+static int lp_int(const char *s)
+{
+
+	if (!s) {
+		DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
+		return (-1);
+	}
+
+	return atoi(s); 
+}
+
+/*******************************************************************
+convenience routine to return unsigned long parameters.
+********************************************************************/
+static int lp_ulong(const char *s)
+{
+
+	if (!s) {
+		DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
+		return (-1);
+	}
+
+	return strtoul(s, NULL, 10);
+}
+
+/*******************************************************************
+convenience routine to return boolean parameters.
+********************************************************************/
+static BOOL lp_bool(const char *s)
+{
+	BOOL ret = False;
+
+	if (!s) {
+		DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
+		return False;
+	}
+	
+	if (!set_boolean(&ret,s)) {
+		DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
+		return False;
+	}
+
+	return ret;
+}
+
+/*******************************************************************
+convenience routine to return enum parameters.
+********************************************************************/
+static int lp_enum(const char *s,const struct enum_list *_enum)
+{
+	int i;
+
+	if (!s || !_enum) {
+		DEBUG(0,("lp_enum(%s,enum): is called with NULL!\n",s));
+		return False;
+	}
+	
+	for (i=0; _enum[i].name; i++) {
+		if (strcasecmp(_enum[i].name,s)==0)
+			return _enum[i].value;
+	}
+
+	DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s));
+	return (-1);
+}
+
+/* Return parametric option from a given service. Type is a part of option before ':' */
+/* Parametric option has following syntax: 'Type: option = value' */
+/* Returned value is allocated in 'lp_talloc' context */
+
+char *lp_parm_string(int lookup_service, const char *type, const char *option)
+{
+	const char *value = get_parametrics(lookup_service, type, option);
+	
+	if (value)
+		return lp_string(value);
+
+	return NULL;
+}
+
+/* Return parametric option from a given service. Type is a part of option before ':' */
+/* Parametric option has following syntax: 'Type: option = value' */
+/* Returned value is allocated in 'lp_talloc' context */
+
+char **lp_parm_string_list(int lookup_service, const char *type, const char *option,
+			   const char *separator)
+{
+	const char *value = get_parametrics(lookup_service, type, option);
+	
+	if (value)
+		return str_list_make(value, separator);
+
+	return NULL;
+}
+
+/* Return parametric option from a given service. Type is a part of option before ':' */
+/* Parametric option has following syntax: 'Type: option = value' */
+
+int lp_parm_int(int lookup_service, const char *type, const char *option)
+{
+	const char *value = get_parametrics(lookup_service, type, option);
+	
+	if (value)
+		return lp_int(value);
+
+	return (-1);
+}
+
+/* Return parametric option from a given service. Type is a part of option before ':' */
+/* Parametric option has following syntax: 'Type: option = value' */
+
+unsigned long lp_parm_ulong(int lookup_service, const char *type, const char *option)
+{
+	const char *value = get_parametrics(lookup_service, type, option);
+	
+	if (value)
+		return lp_ulong(value);
+
+	return (0);
+}
+
+/* Return parametric option from a given service. Type is a part of option before ':' */
+/* Parametric option has following syntax: 'Type: option = value' */
+
+BOOL lp_parm_bool(int lookup_service, const char *type, const char *option)
+{
+	const char *value = get_parametrics(lookup_service, type, option);
+	
+	if (value)
+		return lp_bool(value);
+
+	return False;
+}
+
+/* Return parametric option from a given service. Type is a part of option before ':' */
+/* Parametric option has following syntax: 'Type: option = value' */
+
+int lp_parm_enum(int lookup_service, const char *type, const char *option,
+		 const struct enum_list *_enum)
+{
+	const char *value = get_parametrics(lookup_service, type, option);
+	
+	if (value)
+		return lp_enum(value, _enum);
+
+	return (-1);
+}
+
 
 /***************************************************************************
  Initialise a service to the defaults.
@@ -1873,6 +2034,7 @@
 static void free_service(service *pservice)
 {
 	int i;
+        param_opt_struct *data, *pdata;
 	if (!pservice)
 		return;
 
@@ -1897,6 +2059,16 @@
 					     PTR_DIFF(parm_table[i].ptr, &sDefault)));
 	}
 				
+	DEBUG(5,("Freeing parametrics:\n"));
+	data = pservice->param_opt;
+	while (data) {
+		DEBUG(5,("[%s = %s]\n", data->key, data->value));
+		string_free(&data->key);
+		string_free(&data->value);
+		pdata = data->next;
+		SAFE_FREE(data);
+		data = pdata;
+	}
 
 	ZERO_STRUCTP(pservice);
 }
@@ -1911,14 +2083,27 @@
 	int i;
 	service tservice;
 	int num_to_alloc = iNumServices + 1;
+	param_opt_struct *data, *pdata;
 
 	tservice = *pservice;
 
 	/* it might already exist */
 	if (name) {
 		i = getservicebyname(name, NULL);
-		if (i >= 0)
+		if (i >= 0) {
+			/* Clean all parametric options for service */
+			/* They will be added during parsing again */
+			data = ServicePtrs[i]->param_opt;
+			while (data) {
+				string_free(&data->key);
+				string_free(&data->value);
+				pdata = data->next;
+				SAFE_FREE(data);
+				data = pdata;
+			}
+			ServicePtrs[i]->param_opt = NULL;
 			return (i);
+		}
 	}
 
 	/* find an invalid one */
@@ -2111,7 +2296,7 @@
  represent a boolean.
 ***************************************************************************/
 
-static BOOL set_boolean(BOOL *pb, char *pszParmValue)
+static BOOL set_boolean(BOOL *pb, const char *pszParmValue)
 {
 	BOOL bRetval;
 
@@ -2161,6 +2346,8 @@
 {
 	int i;
 	BOOL bcopyall = (pcopymapDest == NULL);
+	param_opt_struct *data, *pdata, *paramo;
+	BOOL not_added;
 
 	for (i = 0; parm_table[i].label; i++)
 		if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
@@ -2214,6 +2401,30 @@
 			       (void *)pserviceSource->copymap,
 			       sizeof(BOOL) * NUMPARAMETERS);
 	}
+	
+	data = pserviceSource->param_opt;
+	while (data) {
+		not_added = True;
+		pdata = pserviceDest->param_opt;
+		/* Traverse destination */
+		while (pdata) {
+			/* If we already have same option, override it */
+			if (strcmp(pdata->key, data->key) == 0) {
+				string_free(&pdata->value);
+				pdata->value = strdup(data->value);
+				not_added = False;
+				break;
+			}
+			pdata = pdata->next;
+		}
+		if (not_added) {
+		    paramo = smb_xmalloc(sizeof(param_opt_struct));
+		    paramo->key = strdup(data->key);
+		    paramo->value = strdup(data->value);
+		    DLIST_ADD(pserviceDest->param_opt, paramo);
+		}
+		data = data->next;
+	}
 }
 
 /***************************************************************************
@@ -2815,7 +3026,8 @@
 	void *def_ptr = NULL;
 	pstring vfskey;
 	char *sep;
-	param_opt_struct *paramo;
+	param_opt_struct *paramo, *data;
+	BOOL not_added;
 
 	parmnum = map_parameter(pszParmName);
 
@@ -2823,15 +3035,35 @@
 		if ((sep=strchr(pszParmName, ':')) != NULL) {
 			*sep = 0;
 			ZERO_STRUCT(vfskey);
-			pstr_sprintf(vfskey, "%s:%s:", 
-				(snum >= 0) ? lp_servicename(snum) : "global", pszParmName);
+			pstr_sprintf(vfskey, "%s:", pszParmName);
 			slen = strlen(vfskey);
 			safe_strcat(vfskey, sep+1, sizeof(pstring));
 			trim_string(vfskey+slen, " ", " ");
-			paramo = smb_xmalloc(sizeof(param_opt_struct));
-			paramo->key = strdup(vfskey);
-			paramo->value = strdup(pszParmValue);
-			DLIST_ADD(param_opt, paramo);
+			not_added = True;
+			data = (snum < 0) ? Globals.param_opt : 
+				ServicePtrs[snum]->param_opt;
+			/* Traverse destination */
+			while (data) {
+				/* If we already have same option, override it */
+				if (strcmp(data->key, vfskey) == 0) {
+					string_free(&data->value);
+					data->value = strdup(pszParmValue);
+					not_added = False;
+					break;
+				}
+				data = data->next;
+			}
+			if (not_added) {
+				paramo = smb_xmalloc(sizeof(param_opt_struct));
+				paramo->key = strdup(vfskey);
+				paramo->value = strdup(pszParmValue);
+				if (snum < 0) {
+					DLIST_ADD(Globals.param_opt, paramo);
+				} else {
+					DLIST_ADD(ServicePtrs[snum]->param_opt, paramo);
+				}
+			}
+
 			*sep = ':';
 			return (True);
 		}
@@ -3180,7 +3412,6 @@
 {
 	int i;
 	param_opt_struct *data;
-	char *s;
 	
 	fprintf(f, "# Global parameters\n[global]\n");
 
@@ -3194,14 +3425,11 @@
 			print_parameter(&parm_table[i], parm_table[i].ptr, f);
 			fprintf(f, "\n");
 	}
-	if (param_opt != NULL) {
-		data = param_opt;
+	if (Globals.param_opt != NULL) {
+		data = Globals.param_opt;
 		while(data) {
-		    if (((s=strstr(data->key, "global")) == data->key) &&
-			(*(s+strlen("global")) == ':')) {
-			    fprintf(f, "\t%s = %s\n", s+strlen("global")+1, data->value);
-		    }
-		    data = data->next;
+			fprintf(f, "\t%s = %s\n", data->key, data->value);
+			data = data->next;
 		}
         }
 
@@ -3228,7 +3456,6 @@
 {
 	int i;
 	param_opt_struct *data;
-	char *s, *sn;
 	
 	if (pService != &sDefault)
 		fprintf(f, "\n[%s]\n", pService->szService);
@@ -3257,15 +3484,11 @@
 					((char *)pService) + pdiff, f);
 			fprintf(f, "\n");
 	}
-	if (param_opt != NULL) {
-		data = param_opt;
-		sn = (pService == &sDefault) ? "global" : pService->szService;
+	if (pService->param_opt != NULL) {
+		data = pService->param_opt;
 		while(data) {
-		    if (((s=strstr(data->key, sn)) == data->key) &&
-			(*(s+strlen(sn)) == ':')) {
-			    fprintf(f, "\t%s = %s\n", s+strlen(sn)+1, data->value);
-		    }
-		    data = data->next;
+			fprintf(f, "\t%s = %s\n", data->key, data->value);
+			data = data->next;
 		}
         }
 }
@@ -3600,16 +3823,16 @@
 		lp_save_defaults();
 	}
 
-	if (param_opt != NULL) {
-		data = param_opt;
+	if (Globals.param_opt != NULL) {
+		data = Globals.param_opt;
 		while (data) {
-			SAFE_FREE(data->key);
-			SAFE_FREE(data->value);
+			string_free(&data->key);
+			string_free(&data->value);
 			pdata = data->next;
 			SAFE_FREE(data);
 			data = pdata;
 		}
-		param_opt = NULL;
+		Globals.param_opt = NULL;
 	}
 	
 	/* We get sections first, so have to start 'behind' to make up */
--- samba-3.0.build/source/modules/vfs_recycle.c.parametric	2002-11-13 15:10:29 +0200
+++ samba-3.0.build/source/modules/vfs_recycle.c	2002-12-02 12:35:13 +0200
@@ -50,6 +50,7 @@
 
 /* VFS operations */
 static struct vfs_ops default_vfs_ops;   /* For passthrough operation */
+static struct smb_vfs_handle_struct *recycle_handle;
 
 static int recycle_connect(struct connection_struct *conn, const char *service, const char *user);
 static void recycle_disconnect(struct connection_struct *conn);
@@ -69,16 +70,6 @@
 	{NULL,				SMB_VFS_OP_NOOP,	SMB_VFS_LAYER_NOOP}
 };
 
-static BOOL check_bool_param(const char *value)
-{
-	if (strwicmp(value, "yes") == 0 ||
-	    strwicmp(value, "true") == 0 ||
-	    strwicmp(value, "1") == 0)
-		return True;
-
-	return False;
-}
-
 /**
  * VFS initialisation function.
  *
@@ -91,6 +82,7 @@
 	*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");
+	recycle_handle = vfs_handle;
 	if (vfs_recycle_debug_level == -1) {
 		vfs_recycle_debug_level = DBGC_VFS;
 		DEBUG(0, ("vfs_recycle: Couldn't register custom debugging class!\n"));
@@ -114,7 +106,6 @@
 {
 	TALLOC_CTX *ctx = NULL;
 	recycle_bin_struct *recbin;
-	char *servicename;
 	char *tmp_str;
 
 	DEBUG(10, ("Called for service %s (%d) as user %s\n", service, SNUM(conn), user));
@@ -143,55 +134,47 @@
 	recbin->maxsize = 0;
 
 	/* parse configuration options */
-	servicename = talloc_strdup(recbin->ctx, lp_servicename(SNUM(conn)));
-	DEBUG(10, ("servicename = %s\n",servicename));
-	if ((tmp_str = lp_parm_string(servicename, "vfs_recycle_bin", "repository")) != NULL) {
+	if ((tmp_str = lp_parm_string(SNUM(conn), "vfs_recycle_bin", "repository")) != NULL) {
 		recbin->repository = talloc_sub_conn(ctx, conn, tmp_str);
 		ALLOC_CHECK(recbin->repository, error);
 		trim_string(recbin->repository, "/", "/");
 		DEBUG(5, ("recycle.bin: repository = %s\n", recbin->repository));
 	}
-	if ((tmp_str = lp_parm_string(servicename, "vfs_recycle_bin", "keeptree")) != NULL) {
-		if (check_bool_param(tmp_str) == True)
-			recbin->keep_dir_tree = True;
-		DEBUG(5, ("recycle.bin: keeptree = %s\n", tmp_str));
-	}
-	if ((tmp_str = lp_parm_string(servicename, "vfs_recycle_bin", "versions")) != NULL) {
-		if (check_bool_param(tmp_str) == True)
-			recbin->versions = True;
-		DEBUG(5, ("recycle.bin: versions = %s\n", tmp_str));
-	}
-	if ((tmp_str = lp_parm_string(servicename, "vfs_recycle_bin", "touch")) != NULL) {
-		if (check_bool_param(tmp_str) == True)
-			recbin->touch = True;
-		DEBUG(5, ("recycle.bin: touch = %s\n", tmp_str));
-	}
-	if ((tmp_str = lp_parm_string(servicename, "vfs_recycle_bin", "maxsize")) != NULL) {
-		recbin->maxsize = strtoul(tmp_str, NULL, 10);
-		if (recbin->maxsize == 0) {
-			recbin->maxsize = -1;
-			DEBUG(5, ("recycle.bin: maxsize = -infinite-\n"));
-		} else {
-			DEBUG(5, ("recycle.bin: maxsize = %ld\n", (long int)recbin->maxsize));
-		}
+	
+	recbin->keep_dir_tree = lp_parm_bool(SNUM(conn), "vfs_recycle_bin", "keeptree");
+	DEBUG(5, ("recycle.bin: keeptree = %d\n", recbin->keep_dir_tree));
+	
+	recbin->versions = lp_parm_bool(SNUM(conn), "vfs_recycle_bin", "versions");
+	DEBUG(5, ("recycle.bin: versions = %d\n", recbin->versions));
+
+	recbin->touch = lp_parm_bool(SNUM(conn), "vfs_recycle_bin", "touch");
+	DEBUG(5, ("recycle.bin: touch = %d\n", recbin->touch));
+
+	recbin->maxsize = lp_parm_ulong(SNUM(conn), "vfs_recycle_bin", "maxsize");
+	if (recbin->maxsize == 0) {
+		recbin->maxsize = -1;
+		DEBUG(5, ("recycle.bin: maxsize = -infinite-\n"));
+	} else {
+		DEBUG(5, ("recycle.bin: maxsize = %ld\n", (long int)recbin->maxsize));
 	}
-	if ((tmp_str = lp_parm_string(servicename, "vfs_recycle_bin", "exclude")) != NULL) {
+
+	if ((tmp_str = lp_parm_string(SNUM(conn), "vfs_recycle_bin", "exclude")) != NULL) {
 		recbin->exclude = talloc_strdup(ctx, tmp_str);
 		ALLOC_CHECK(recbin->exclude, error);
 		DEBUG(5, ("recycle.bin: exclude = %s\n", recbin->exclude));
 	}
-	if ((tmp_str = lp_parm_string(servicename,"vfs_recycle_bin", "exclude_dir")) != NULL) {
+	if ((tmp_str = lp_parm_string(SNUM(conn),"vfs_recycle_bin", "exclude_dir")) != NULL) {
 		recbin->exclude_dir = talloc_strdup(ctx, tmp_str);
 		ALLOC_CHECK(recbin->exclude_dir, error);
 		DEBUG(5, ("recycle.bin: exclude_dir = %s\n", recbin->exclude_dir));
 	}
-	if ((tmp_str = lp_parm_string(servicename,"vfs_recycle_bin", "noversions")) != NULL) {
+	if ((tmp_str = lp_parm_string(SNUM(conn),"vfs_recycle_bin", "noversions")) != NULL) {
 		recbin->noversions = talloc_strdup(ctx, tmp_str);
 		ALLOC_CHECK(recbin->noversions, error);
 		DEBUG(5, ("recycle.bin: noversions = %s\n", recbin->noversions));
 	}
 
-	conn->vfs_private = (void *)recbin;
+	recycle_handle->data = (void *)recbin;
 	return default_vfs_ops.connect(conn, service, user);
 
 error:
@@ -202,9 +185,9 @@
 static void recycle_disconnect(struct connection_struct *conn)
 {
 	DEBUG(10, ("Disconnecting VFS module recycle bin\n"));
-	if (conn->vfs_private) {
-		talloc_destroy(((recycle_bin_struct *)conn->vfs_private)->ctx);
-		conn->vfs_private = NULL;
+	if (recycle_handle->data) {
+		talloc_destroy(((recycle_bin_struct *)recycle_handle->data)->ctx);
+		recycle_handle->data = NULL;
 	}
 	default_vfs_ops.disconnect(conn);
 }
@@ -398,16 +381,16 @@
 	char *final_name = NULL;
 	char *base;
 	int i;
-	SMB_BIG_UINT dfree, dsize, bsize;
-	SMB_OFF_T file_size, space_avail;
+	/* SMB_BIG_UINT dfree, dsize, bsize; */
+	SMB_OFF_T file_size /*, space_avail */ ;
 	BOOL exist;
 	int rc = -1;
 
 	file_name = strdup(inname);
 	ALLOC_CHECK(file_name, done);
 
-	if (conn->vfs_private)
-		recbin = (recycle_bin_struct *)conn->vfs_private;
+	if (recycle_handle->data)
+		recbin = (recycle_bin_struct *)recycle_handle->data;
 	else {
 		DEBUG(0, ("Recycle bin not initialized!\n"));
 		rc = default_vfs_ops.unlink(conn, file_name);


More information about the samba-technical mailing list