LCOV - code coverage report
Current view: top level - source3/libsmb - libsmb_cache.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 49 84 58.3 %
Date: 2024-02-28 12:06:22 Functions: 4 4 100.0 %

          Line data    Source code
       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 "libsmb/libsmb.h"
      25             : #include "libsmbclient.h"
      26             : #include "libsmb_internal.h"
      27             : 
      28             : /*
      29             :  * Structure we use if internal caching mechanism is used
      30             :  * nothing fancy here.
      31             :  */
      32             : struct smbc_server_cache {
      33             :         char *server_name;
      34             :         char *share_name;
      35             :         char *workgroup;
      36             :         char *username;
      37             :         SMBCSRV *server;
      38             : 
      39             :         struct smbc_server_cache *next, *prev;
      40             : };
      41             : 
      42             : 
      43             : 
      44             : /*
      45             :  * Add a new connection to the server cache.
      46             :  * This function is only used if the external cache is not enabled
      47             :  */
      48             : int
      49          99 : SMBC_add_cached_server(SMBCCTX * context,
      50             :                        SMBCSRV * newsrv,
      51             :                        const char * server,
      52             :                        const char * share,
      53             :                        const char * workgroup,
      54             :                        const char * username)
      55             : {
      56          99 :         struct smbc_server_cache * srvcache = NULL;
      57             : 
      58          99 :         srvcache = SMB_CALLOC_ARRAY(struct smbc_server_cache, 1);
      59          99 :         if (srvcache == NULL) {
      60           0 :                 DEBUG(3, ("Not enough space for server cache allocation\n"));
      61           0 :                 errno = ENOMEM;
      62           0 :                 return 1;
      63             :         }
      64             : 
      65          99 :         srvcache->server = newsrv;
      66             : 
      67          99 :         srvcache->server_name = SMB_STRDUP(server);
      68          99 :         if (!srvcache->server_name) {
      69           0 :                 goto nomem;
      70             :         }
      71             : 
      72          99 :         srvcache->share_name = SMB_STRDUP(share);
      73          99 :         if (!srvcache->share_name) {
      74           0 :                 goto nomem;
      75             :         }
      76             : 
      77          99 :         srvcache->workgroup = SMB_STRDUP(workgroup);
      78          99 :         if (!srvcache->workgroup) {
      79           0 :                 goto nomem;
      80             :         }
      81             : 
      82          99 :         srvcache->username = SMB_STRDUP(username);
      83          99 :         if (!srvcache->username) {
      84           0 :                 goto nomem;
      85             :         }
      86             : 
      87          99 :         DLIST_ADD(context->internal->server_cache, srvcache);
      88          99 :         return 0;
      89             : 
      90           0 : nomem:
      91           0 :         SAFE_FREE(srvcache->server_name);
      92           0 :         SAFE_FREE(srvcache->share_name);
      93           0 :         SAFE_FREE(srvcache->workgroup);
      94           0 :         SAFE_FREE(srvcache->username);
      95           0 :         SAFE_FREE(srvcache);
      96           0 :         errno = ENOMEM;
      97             : 
      98           0 :         return 1;
      99             : }
     100             : 
     101             : 
     102             : 
     103             : /*
     104             :  * Search the server cache for a server
     105             :  * returns server handle on success, NULL on error (not found)
     106             :  * This function is only used if the external cache is not enabled
     107             :  */
     108             : SMBCSRV *
     109        1596 : SMBC_get_cached_server(SMBCCTX * context,
     110             :                        const char * server,
     111             :                        const char * share,
     112             :                        const char * workgroup,
     113             :                        const char * user)
     114             : {
     115        1596 :         struct smbc_server_cache * srv = NULL;
     116             : 
     117             :         /* Search the cache lines */
     118        1722 :         for (srv = context->internal->server_cache; srv; srv = srv->next) {
     119             : 
     120        1502 :                 if (strcmp(server,srv->server_name)  == 0 &&
     121        1454 :                     strcmp(workgroup,srv->workgroup) == 0 &&
     122        1412 :                     strcmp(user, srv->username)  == 0) {
     123             : 
     124             :                         /* If the share name matches, we're cool */
     125        1412 :                         if (strcmp(share, srv->share_name) == 0) {
     126        1376 :                                 return srv->server;
     127             :                         }
     128             : 
     129             :                         /*
     130             :                          * We only return an empty share name or the attribute
     131             :                          * server on an exact match (which would have been
     132             :                          * caught above).
     133             :                          */
     134          36 :                         if (*share == '\0' || strcmp(share, "*IPC$") == 0)
     135           4 :                                 continue;
     136             : 
     137             :                         /*
     138             :                          * Never return an empty share name or the attribute
     139             :                          * server if it wasn't what was requested.
     140             :                          */
     141          32 :                         if (*srv->share_name == '\0' ||
     142          32 :                             strcmp(srv->share_name, "*IPC$") == 0)
     143          32 :                                 continue;
     144             : 
     145             :                         /*
     146             :                          * If we're only allowing one share per server, then
     147             :                          * a connection to the server (other than the
     148             :                          * attribute server connection) is cool.
     149             :                          */
     150           0 :                         if (smbc_getOptionOneSharePerServer(context)) {
     151           0 :                                 NTSTATUS status;
     152             :                                 /*
     153             :                                  * The currently connected share name
     154             :                                  * doesn't match the requested share, so
     155             :                                  * disconnect from the current share.
     156             :                                  */
     157           0 :                                 status = cli_tdis(srv->server->cli);
     158           0 :                                 if (!NT_STATUS_IS_OK(status)) {
     159             :                                         /* Sigh. Couldn't disconnect. */
     160           0 :                                         cli_shutdown(srv->server->cli);
     161           0 :                                         srv->server->cli = NULL;
     162           0 :                                         smbc_getFunctionRemoveCachedServer(context)(context, srv->server);
     163           0 :                                         continue;
     164             :                                 }
     165             : 
     166             :                                 /*
     167             :                                  * Save the new share name.  We've
     168             :                                  * disconnected from the old share, and are
     169             :                                  * about to connect to the new one.
     170             :                                  */
     171           0 :                                 SAFE_FREE(srv->share_name);
     172           0 :                                 srv->share_name = SMB_STRDUP(share);
     173           0 :                                 if (!srv->share_name) {
     174             :                                         /* Out of memory. */
     175           0 :                                         cli_shutdown(srv->server->cli);
     176           0 :                                         srv->server->cli = NULL;
     177           0 :                                         smbc_getFunctionRemoveCachedServer(context)(context, srv->server);
     178           0 :                                         continue;
     179             :                                 }
     180             : 
     181           0 :                                 return srv->server;
     182             :                         }
     183             :                 }
     184             :         }
     185             : 
     186         220 :         return NULL;
     187             : }
     188             : 
     189             : 
     190             : /*
     191             :  * Search the server cache for a server and remove it
     192             :  * returns 0 on success
     193             :  * This function is only used if the external cache is not enabled
     194             :  */
     195             : int
     196          33 : SMBC_remove_cached_server(SMBCCTX * context,
     197             :                           SMBCSRV * server)
     198             : {
     199          33 :         struct smbc_server_cache * srv = NULL;
     200             : 
     201          33 :         for (srv = context->internal->server_cache; srv; srv = srv->next) {
     202          33 :                 if (server == srv->server) {
     203             : 
     204             :                         /* remove this sucker */
     205          33 :                         DLIST_REMOVE(context->internal->server_cache, srv);
     206          33 :                         SAFE_FREE(srv->server_name);
     207          33 :                         SAFE_FREE(srv->share_name);
     208          33 :                         SAFE_FREE(srv->workgroup);
     209          33 :                         SAFE_FREE(srv->username);
     210          33 :                         SAFE_FREE(srv);
     211          33 :                         return 0;
     212             :                 }
     213             :         }
     214             :         /* server not found */
     215           0 :         return 1;
     216             : }
     217             : 
     218             : 
     219             : /*
     220             :  * Try to remove all the servers in cache
     221             :  * returns 1 on failure and 0 if all servers could be removed.
     222             :  */
     223             : int
     224          40 : SMBC_purge_cached_servers(SMBCCTX * context)
     225             : {
     226           0 :         struct smbc_server_cache * srv;
     227           0 :         struct smbc_server_cache * next;
     228          40 :         int could_not_purge_all = 0;
     229             : 
     230          80 :         for (srv = context->internal->server_cache,
     231          40 :                      next = (srv ? srv->next :NULL);
     232          73 :              srv;
     233          33 :              srv = next,
     234          33 :                      next = (srv ? srv->next : NULL)) {
     235             : 
     236          33 :                 if (SMBC_remove_unused_server(context, srv->server)) {
     237             :                         /* could not be removed */
     238           0 :                         could_not_purge_all = 1;
     239             :                 }
     240             :         }
     241          40 :         return could_not_purge_all;
     242             : }

Generated by: LCOV version 1.14