diff options
| -rw-r--r-- | source3/Makefile.in | 1 | ||||
| -rw-r--r-- | source3/smbwrapper/smbw_cache.c | 208 | ||||
| -rw-r--r-- | source3/smbwrapper/smbw_dir.c | 13 | 
3 files changed, 215 insertions, 7 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in index b3723223ee..d6a2cfed1f 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -275,6 +275,7 @@ PAM_WINBIND_OBJ = nsswitch/pam_winbind.po nsswitch/wb_common.po  SMBW_OBJ = smbwrapper/smbw.o \  		smbwrapper/smbw_dir.o smbwrapper/smbw_stat.o \  		smbwrapper/realcalls.o smbwrapper/shared.o \ +		smbwrapper/smbw_cache.o \  		$(LIBSMB_OBJ) $(PARAM_OBJ) \                  $(UBIQX_OBJ) $(LIB_OBJ) diff --git a/source3/smbwrapper/smbw_cache.c b/source3/smbwrapper/smbw_cache.c new file mode 100644 index 0000000000..3213d99941 --- /dev/null +++ b/source3/smbwrapper/smbw_cache.c @@ -0,0 +1,208 @@ +/*  +   Unix SMB/Netbios implementation. +   Version 2.0 +   SMB wrapper directory functions +   Copyright (C) Tim Potter 2000 +    +   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 +   the Free Software Foundation; either version 2 of the License, or +   (at your option) any later version. +    +   This program is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +   GNU General Public License for more details. +    +   You should have received a copy of the GNU General Public License +   along with this program; if not, write to the Free Software +   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* We cache lists of workgroups, lists of servers in workgroups, and lists +   of shares exported by servers. */ + +#define CACHE_TIMEOUT 30 + +struct name_list { +	struct name_list *prev, *next; +	char *name; +	uint32 stype; +	char *comment; +}; + +struct cached_names { +	struct cached_names *prev, *next; +	char *key; +	struct name_list *name_list; +	time_t cache_timeout; +	int result; +}; + +static struct cached_names *cached_names = NULL; + +/* Find a list of cached name for a workgroup, server or share list */ + +static struct cached_names *find_cached_names(char *key) +{ +	struct cached_names *tmp; + +	for (tmp = cached_names; tmp; tmp = tmp->next) { +		if (strequal(tmp->key, key)) { +			return tmp; +		} +	} + +	return NULL; +} + +/* Add a name to a list stored in the state variable */ + +static void add_cached_names(const char *name, uint32 stype,  +			     const char *comment, void *state) +{ +	struct name_list **name_list = (struct name_list **)state; +	struct name_list *new_name; + +	new_name = (struct name_list *)malloc(sizeof(struct name_list)); +	if (!new_name) return; + +	ZERO_STRUCTP(new_name); + +	new_name->name = strdup(name); +	new_name->stype = stype; +	new_name->comment = strdup(comment); + +	DLIST_ADD(*name_list, new_name); +} + +static void free_name_list(struct name_list *name_list) +{ +	struct name_list *tmp = name_list; + +	while(tmp) { +		struct name_list *next; + +		next = tmp->next; + +		free(tmp->name); +		free(tmp->comment); +		free(tmp); +		 +		tmp = next; +	} +} + +/* Wrapper for NetServerEnum function */ + +BOOL smbw_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype, +			void (*fn)(const char *, uint32, const char *, void *), +			void *state) +{ +	struct cached_names *names; +	struct name_list *tmp; +	time_t now = time(NULL); +	char key[PATH_MAX]; +	BOOL result = True; + +	slprintf(key, PATH_MAX - 1, "%s/%s#%s", cli->desthost,  +		 workgroup, (stype == SV_TYPE_DOMAIN_ENUM ? "DOM" : "SRV")); + +	names = find_cached_names(key); + +	if (names == NULL || (now - names->cache_timeout) > CACHE_TIMEOUT) { +		struct cached_names *new_names = NULL; + +		/* No names cached for this workgroup */ + +		if (names == NULL) { +			new_names = (struct cached_names *) +				malloc(sizeof(struct cached_names)); + +			ZERO_STRUCTP(new_names); +			DLIST_ADD(cached_names, new_names); + +		} else { + +			/* Dispose of out of date name list */ + +			free_name_list(names->name_list); +			names->name_list = NULL; + +			new_names = names; +		}		 + +		result = cli_NetServerEnum(cli, workgroup, stype,  +					   add_cached_names,  +					   &new_names->name_list); +					    +		new_names->cache_timeout = now; +		new_names->result = result; +		new_names->key = strdup(key); + +		names = new_names; +	} + +	/* Return names by running callback function. */ + +	for (tmp = names->name_list; tmp; tmp = tmp->next) +		fn(tmp->name, stype, tmp->comment, state); +	 +	return names->result; +} + +/* Wrapper for RNetShareEnum function */ + +int smbw_RNetShareEnum(struct cli_state *cli,  +		       void (*fn)(const char *, uint32, const char *, void *),  +		       void *state) +{ +	struct cached_names *names; +	struct name_list *tmp; +	time_t now = time(NULL); +	char key[PATH_MAX]; + +	slprintf(key, PATH_MAX - 1, "SHARE/%s", cli->desthost); + +	names = find_cached_names(key); + +	if (names == NULL || (now - names->cache_timeout) > CACHE_TIMEOUT) { +		struct cached_names *new_names = NULL; + +		/* No names cached for this server */ + +		if (names == NULL) { +			new_names = (struct cached_names *) +				malloc(sizeof(struct cached_names)); + +			ZERO_STRUCTP(new_names); +			DLIST_ADD(cached_names, new_names); + +		} else { + +			/* Dispose of out of date name list */ + +			free_name_list(names->name_list); +			names->name_list = NULL; + +			new_names = names; +		} + +		new_names->result = cli_RNetShareEnum(cli, add_cached_names,  +						      &new_names->name_list); +		 +		new_names->cache_timeout = now; +		new_names->key = strdup(key); + +		names = new_names; +	} + +	/* Return names by running callback function. */ + +	for (tmp = names->name_list; tmp; tmp = tmp->next) +		fn(tmp->name, tmp->stype, tmp->comment, state); +	 +	return names->result; +} diff --git a/source3/smbwrapper/smbw_dir.c b/source3/smbwrapper/smbw_dir.c index d94ea6ec87..4f6c18eb7f 100644 --- a/source3/smbwrapper/smbw_dir.c +++ b/source3/smbwrapper/smbw_dir.c @@ -72,7 +72,6 @@ static void free_dir(struct smbw_dir *dir)  	free(dir);  } -  static struct smbw_dir *cur_dir;  /*****************************************************  @@ -102,7 +101,7 @@ static void smbw_dir_add(struct file_info *finfo, const char *mask,  add a entry to a directory listing  *******************************************************/  static void smbw_share_add(const char *share, uint32 type,  -                           const char *comment, void *state) +			   const char *comment, void *state)  {  	struct file_info finfo; @@ -205,22 +204,22 @@ int smbw_dir_open(const char *fname)  		*p = 0;  		smbw_server_add(".",0,"", NULL);  		smbw_server_add("..",0,"", NULL); -		cli_NetServerEnum(&srv->cli, srv->server_name, SV_TYPE_DOMAIN_ENUM, -				  smbw_server_add, NULL); +		smbw_NetServerEnum(&srv->cli, srv->server_name,  +				   SV_TYPE_DOMAIN_ENUM, smbw_server_add, NULL);  		*p = '#';  	} else if ((p=strstr(srv->server_name,"#1D"))) {  		DEBUG(4,("doing NetServerEnum\n"));  		*p = 0;  		smbw_server_add(".",0,"", NULL);  		smbw_server_add("..",0,"", NULL); -		cli_NetServerEnum(&srv->cli, srv->server_name, SV_TYPE_ALL, -				  smbw_server_add, NULL); +		smbw_NetServerEnum(&srv->cli, srv->server_name, SV_TYPE_ALL, +				   smbw_server_add, NULL);  		*p = '#';  	} else if (strcmp(srv->cli.dev,"IPC") == 0) {  		DEBUG(4,("doing NetShareEnum\n"));  		smbw_share_add(".",0,"", NULL);  		smbw_share_add("..",0,"", NULL); -		if (cli_RNetShareEnum(&srv->cli, smbw_share_add, NULL) < 0) { +		if (smbw_RNetShareEnum(&srv->cli, smbw_share_add, NULL) < 0) {  			errno = smbw_errno(&srv->cli);  			goto failed;  		}  | 
