root/source3/libsmb/libsmb_cache.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. SMBC_add_cached_server
  2. SMBC_get_cached_server
  3. SMBC_remove_cached_server
  4. SMBC_purge_cached_servers

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

/* [<][>][^][v][top][bottom][index][help] */