summaryrefslogtreecommitdiffstats
path: root/source/smbwrapper/smbw_cache.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/smbwrapper/smbw_cache.c')
-rw-r--r--source/smbwrapper/smbw_cache.c207
1 files changed, 207 insertions, 0 deletions
diff --git a/source/smbwrapper/smbw_cache.c b/source/smbwrapper/smbw_cache.c
new file mode 100644
index 00000000000..fcb0eda8050
--- /dev/null
+++ b/source/smbwrapper/smbw_cache.c
@@ -0,0 +1,207 @@
+/*
+ Unix SMB/CIFS implementation.
+ 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;
+
+ SAFE_FREE(tmp->name);
+ SAFE_FREE(tmp->comment);
+ SAFE_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;
+}