2 Unix SMB/CIFS implementation.
3 SMB wrapper directory functions
4 Copyright (C) Tim Potter 2000
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 /* We cache lists of workgroups, lists of servers in workgroups, and lists
24 of shares exported by servers. */
26 #define CACHE_TIMEOUT 30
29 struct name_list *prev, *next;
36 struct cached_names *prev, *next;
38 struct name_list *name_list;
43 static struct cached_names *cached_names = NULL;
45 /* Find a list of cached name for a workgroup, server or share list */
47 static struct cached_names *find_cached_names(char *key)
49 struct cached_names *tmp;
51 for (tmp = cached_names; tmp; tmp = tmp->next) {
52 if (strequal(tmp->key, key)) {
60 /* Add a name to a list stored in the state variable */
62 static void add_cached_names(const char *name, uint32 stype,
63 const char *comment, void *state)
65 struct name_list **name_list = (struct name_list **)state;
66 struct name_list *new_name;
68 new_name = SMB_MALLOC_P(struct name_list);
69 if (!new_name) return;
71 ZERO_STRUCTP(new_name);
73 new_name->name = SMB_STRDUP(name);
74 new_name->stype = stype;
75 new_name->comment = SMB_STRDUP(comment);
77 DLIST_ADD(*name_list, new_name);
80 static void free_name_list(struct name_list *name_list)
82 struct name_list *tmp = name_list;
85 struct name_list *next;
90 SAFE_FREE(tmp->comment);
97 /* Wrapper for NetServerEnum function */
99 BOOL smbw_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
100 void (*fn)(const char *, uint32, const char *, void *),
103 struct cached_names *names;
104 struct name_list *tmp;
105 time_t now = time(NULL);
109 slprintf(key, PATH_MAX - 1, "%s/%s#%s", cli->desthost,
110 workgroup, (stype == SV_TYPE_DOMAIN_ENUM ? "DOM" : "SRV"));
112 names = find_cached_names(key);
114 if (names == NULL || (now - names->cache_timeout) > CACHE_TIMEOUT) {
115 struct cached_names *new_names = NULL;
117 /* No names cached for this workgroup */
120 new_names = SMB_MALLOC_P(struct cached_names);
122 ZERO_STRUCTP(new_names);
123 DLIST_ADD(cached_names, new_names);
127 /* Dispose of out of date name list */
129 free_name_list(names->name_list);
130 names->name_list = NULL;
135 result = cli_NetServerEnum(cli, workgroup, stype,
137 &new_names->name_list);
139 new_names->cache_timeout = now;
140 new_names->result = result;
141 new_names->key = SMB_STRDUP(key);
146 /* Return names by running callback function. */
148 for (tmp = names->name_list; tmp; tmp = tmp->next)
149 fn(tmp->name, stype, tmp->comment, state);
151 return names->result;
154 /* Wrapper for RNetShareEnum function */
156 int smbw_RNetShareEnum(struct cli_state *cli,
157 void (*fn)(const char *, uint32, const char *, void *),
160 struct cached_names *names;
161 struct name_list *tmp;
162 time_t now = time(NULL);
165 slprintf(key, PATH_MAX - 1, "SHARE/%s", cli->desthost);
167 names = find_cached_names(key);
169 if (names == NULL || (now - names->cache_timeout) > CACHE_TIMEOUT) {
170 struct cached_names *new_names = NULL;
172 /* No names cached for this server */
175 new_names = SMB_MALLOC_P(struct cached_names);
177 ZERO_STRUCTP(new_names);
178 DLIST_ADD(cached_names, new_names);
182 /* Dispose of out of date name list */
184 free_name_list(names->name_list);
185 names->name_list = NULL;
190 new_names->result = cli_RNetShareEnum(cli, add_cached_names,
191 &new_names->name_list);
193 new_names->cache_timeout = now;
194 new_names->key = SMB_STRDUP(key);
199 /* Return names by running callback function. */
201 for (tmp = names->name_list; tmp; tmp = tmp->next)
202 fn(tmp->name, tmp->stype, tmp->comment, state);
204 return names->result;