~vcs-imports/samba/main

« back to all changes in this revision

Viewing changes to source/libsmb/libsmb_cache.c

  • Committer: jerry
  • Date: 2006-07-14 21:48:39 UTC
  • Revision ID: vcs-imports@canonical.com-20060714214839-586d8c489a8fcead
gutting trunk to move to svn:externals

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
 
2
 
/* 
3
 
   Unix SMB/CIFS implementation.
4
 
   SMB client library implementation (server cache)
5
 
   Copyright (C) Andrew Tridgell 1998
6
 
   Copyright (C) Richard Sharpe 2000
7
 
   Copyright (C) John Terpstra 2000
8
 
   Copyright (C) Tom Jansen (Ninja ISD) 2002 
9
 
   
10
 
   This program is free software; you can redistribute it and/or modify
11
 
   it under the terms of the GNU General Public License as published by
12
 
   the Free Software Foundation; either version 2 of the License, or
13
 
   (at your option) any later version.
14
 
   
15
 
   This program is distributed in the hope that it will be useful,
16
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 
   GNU General Public License for more details.
19
 
   
20
 
   You should have received a copy of the GNU General Public License
21
 
   along with this program; if not, write to the Free Software
22
 
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23
 
*/
24
 
 
25
 
#include "includes.h"
26
 
 
27
 
#include "include/libsmbclient.h"
28
 
#include "../include/libsmb_internal.h"
29
 
/*
30
 
 * Structure we use if internal caching mechanism is used 
31
 
 * nothing fancy here.
32
 
 */
33
 
struct smbc_server_cache {
34
 
        char *server_name;
35
 
        char *share_name;
36
 
        char *workgroup;
37
 
        char *username;
38
 
        SMBCSRV *server;
39
 
        
40
 
        struct smbc_server_cache *next, *prev;
41
 
};
42
 
        
43
 
 
44
 
 
45
 
/*
46
 
 * Add a new connection to the server cache.
47
 
 * This function is only used if the external cache is not enabled 
48
 
 */
49
 
static int smbc_add_cached_server(SMBCCTX * context, SMBCSRV * newsrv,
50
 
                                  const char * server, const char * share, 
51
 
                                  const char * workgroup, const char * username)
52
 
{
53
 
        struct smbc_server_cache * srvcache = NULL;
54
 
 
55
 
        if (!(srvcache = SMB_MALLOC_P(struct smbc_server_cache))) {
56
 
                errno = ENOMEM;
57
 
                DEBUG(3, ("Not enough space for server cache allocation\n"));
58
 
                return 1;
59
 
        }
60
 
       
61
 
        ZERO_STRUCTP(srvcache);
62
 
 
63
 
        srvcache->server = newsrv;
64
 
 
65
 
        srvcache->server_name = SMB_STRDUP(server);
66
 
        if (!srvcache->server_name) {
67
 
                errno = ENOMEM;
68
 
                goto failed;
69
 
        }
70
 
 
71
 
        srvcache->share_name = SMB_STRDUP(share);
72
 
        if (!srvcache->share_name) {
73
 
                errno = ENOMEM;
74
 
                goto failed;
75
 
        }
76
 
 
77
 
        srvcache->workgroup = SMB_STRDUP(workgroup);
78
 
        if (!srvcache->workgroup) {
79
 
                errno = ENOMEM;
80
 
                goto failed;
81
 
        }
82
 
 
83
 
        srvcache->username = SMB_STRDUP(username);
84
 
        if (!srvcache->username) {
85
 
                errno = ENOMEM;
86
 
                goto failed;
87
 
        }
88
 
 
89
 
        DLIST_ADD((context->server_cache), srvcache);
90
 
        return 0;
91
 
 
92
 
 failed:
93
 
        SAFE_FREE(srvcache->server_name);
94
 
        SAFE_FREE(srvcache->share_name);
95
 
        SAFE_FREE(srvcache->workgroup);
96
 
        SAFE_FREE(srvcache->username);
97
 
        SAFE_FREE(srvcache);
98
 
        
99
 
        return 1;
100
 
}
101
 
 
102
 
 
103
 
 
104
 
/*
105
 
 * Search the server cache for a server 
106
 
 * returns server handle on success, NULL on error (not found)
107
 
 * This function is only used if the external cache is not enabled 
108
 
 */
109
 
static SMBCSRV * smbc_get_cached_server(SMBCCTX * context, const char * server, 
110
 
                                  const char * share, const char * workgroup, const char * user)
111
 
{
112
 
        struct smbc_server_cache * srv = NULL;
113
 
        
114
 
        /* Search the cache lines */
115
 
        for (srv=((struct smbc_server_cache *)context->server_cache);srv;srv=srv->next) {
116
 
 
117
 
                if (strcmp(server,srv->server_name)  == 0 &&
118
 
                    strcmp(workgroup,srv->workgroup) == 0 &&
119
 
                    strcmp(user, srv->username)  == 0) {
120
 
 
121
 
                        /* If the share name matches, we're cool */
122
 
                        if (strcmp(share, srv->share_name) == 0) {
123
 
                                return srv->server;
124
 
                        }
125
 
 
126
 
                        /*
127
 
                         * We only return an empty share name or the attribute
128
 
                         * server on an exact match (which would have been
129
 
                         * caught above).
130
 
                         */
131
 
                        if (*share == '\0' || strcmp(share, "*IPC$") == 0)
132
 
                                continue;
133
 
 
134
 
                        /*
135
 
                         * Never return an empty share name or the attribute
136
 
                         * server if it wasn't what was requested.
137
 
                         */
138
 
                        if (*srv->share_name == '\0' ||
139
 
                            strcmp(srv->share_name, "*IPC$") == 0)
140
 
                                continue;
141
 
 
142
 
                        /*
143
 
                         * If we're only allowing one share per server, then
144
 
                         * a connection to the server (other than the
145
 
                         * attribute server connection) is cool.
146
 
                         */
147
 
                        if (context->options.one_share_per_server) {
148
 
                                /*
149
 
                                 * The currently connected share name
150
 
                                 * doesn't match the requested share, so
151
 
                                 * disconnect from the current share.
152
 
                                 */
153
 
                                if (! cli_tdis(srv->server->cli)) {
154
 
                                        /* Sigh. Couldn't disconnect. */
155
 
                                        cli_shutdown(srv->server->cli);
156
 
                                        srv->server->cli = NULL;
157
 
                                        context->callbacks.remove_cached_srv_fn(context, srv->server);
158
 
                                        continue;
159
 
                                }
160
 
 
161
 
                                /*
162
 
                                 * Save the new share name.  We've
163
 
                                 * disconnected from the old share, and are
164
 
                                 * about to connect to the new one.
165
 
                                 */
166
 
                                SAFE_FREE(srv->share_name);
167
 
                                srv->share_name = SMB_STRDUP(share);
168
 
                                if (!srv->share_name) {
169
 
                                        /* Out of memory. */
170
 
                                        cli_shutdown(srv->server->cli);
171
 
                                        srv->server->cli = NULL;
172
 
                                        context->callbacks.remove_cached_srv_fn(context, srv->server);
173
 
                                        continue;
174
 
                                }
175
 
 
176
 
 
177
 
                                return srv->server;
178
 
                        }
179
 
                }
180
 
        }
181
 
 
182
 
        return NULL;
183
 
}
184
 
 
185
 
 
186
 
/* 
187
 
 * Search the server cache for a server and remove it
188
 
 * returns 0 on success
189
 
 * This function is only used if the external cache is not enabled 
190
 
 */
191
 
static int smbc_remove_cached_server(SMBCCTX * context, SMBCSRV * server)
192
 
{
193
 
        struct smbc_server_cache * srv = NULL;
194
 
        
195
 
        for (srv=((struct smbc_server_cache *)context->server_cache);srv;srv=srv->next) {
196
 
                if (server == srv->server) { 
197
 
 
198
 
                        /* remove this sucker */
199
 
                        DLIST_REMOVE(context->server_cache, srv);
200
 
                        SAFE_FREE(srv->server_name);
201
 
                        SAFE_FREE(srv->share_name);
202
 
                        SAFE_FREE(srv->workgroup);
203
 
                        SAFE_FREE(srv->username);
204
 
                        SAFE_FREE(srv);
205
 
                        return 0;
206
 
                }
207
 
        }
208
 
        /* server not found */
209
 
        return 1;
210
 
}
211
 
 
212
 
 
213
 
/*
214
 
 * Try to remove all the servers in cache
215
 
 * returns 1 on failure and 0 if all servers could be removed.
216
 
 */
217
 
static int smbc_purge_cached(SMBCCTX * context)
218
 
{
219
 
        struct smbc_server_cache * srv;
220
 
        struct smbc_server_cache * next;
221
 
        int could_not_purge_all = 0;
222
 
 
223
 
        for (srv = ((struct smbc_server_cache *) context->server_cache),
224
 
                 next = (srv ? srv->next :NULL);
225
 
             srv;
226
 
             srv = next, next = (srv ? srv->next : NULL)) {
227
 
 
228
 
                if (smbc_remove_unused_server(context, srv->server)) {
229
 
                        /* could not be removed */
230
 
                        could_not_purge_all = 1;
231
 
                }
232
 
        }
233
 
        return could_not_purge_all;
234
 
}
235
 
 
236
 
 
237
 
 
238
 
/*
239
 
 * This functions initializes all server-cache related functions 
240
 
 * to the default (internal) system.
241
 
 *
242
 
 * We use this to make the rest of the cache system static.
243
 
 */
244
 
 
245
 
int smbc_default_cache_functions(SMBCCTX * context)
246
 
{
247
 
        context->callbacks.add_cached_srv_fn    = smbc_add_cached_server;
248
 
        context->callbacks.get_cached_srv_fn    = smbc_get_cached_server;
249
 
        context->callbacks.remove_cached_srv_fn = smbc_remove_cached_server;
250
 
        context->callbacks.purge_cached_fn      = smbc_purge_cached;
251
 
 
252
 
        return 0;
253
 
}