2005-03-11 02:41:19 +03:00
0001-01-01 02:30:17 +02:30
/*
Unix SMB / CIFS implementation .
SMB client library implementation ( server cache )
Copyright ( C ) Andrew Tridgell 1998
Copyright ( C ) Richard Sharpe 2000
Copyright ( C ) John Terpstra 2000
Copyright ( C ) Tom Jansen ( Ninja ISD ) 2002
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 0213 9 , USA .
*/
# include "includes.h"
2004-10-07 08:01:18 +04:00
# include "include/libsmbclient.h"
2005-03-11 02:41:19 +03:00
# include "../include/libsmb_internal.h"
0001-01-01 02:30:17 +02:30
/*
* Structure we use if internal caching mechanism is used
* nothing fancy here .
*/
struct smbc_server_cache {
char * server_name ;
char * share_name ;
char * workgroup ;
char * username ;
SMBCSRV * server ;
struct smbc_server_cache * next , * prev ;
} ;
/*
* Add a new connection to the server cache .
* This function is only used if the external cache is not enabled
*/
2005-06-25 00:25:18 +04:00
static int smbc_add_cached_server ( SMBCCTX * context , SMBCSRV * newsrv ,
0001-01-01 02:30:17 +02:30
const char * server , const char * share ,
const char * workgroup , const char * username )
0001-01-01 02:30:17 +02:30
{
struct smbc_server_cache * srvcache = NULL ;
2004-12-07 21:25:53 +03:00
if ( ! ( srvcache = SMB_MALLOC_P ( struct smbc_server_cache ) ) ) {
0001-01-01 02:30:17 +02:30
errno = ENOMEM ;
DEBUG ( 3 , ( " Not enough space for server cache allocation \n " ) ) ;
return 1 ;
}
ZERO_STRUCTP ( srvcache ) ;
2005-06-25 00:25:18 +04:00
srvcache - > server = newsrv ;
0001-01-01 02:30:17 +02:30
2004-12-07 21:25:53 +03:00
srvcache - > server_name = SMB_STRDUP ( server ) ;
0001-01-01 02:30:17 +02:30
if ( ! srvcache - > server_name ) {
errno = ENOMEM ;
goto failed ;
}
2004-12-07 21:25:53 +03:00
srvcache - > share_name = SMB_STRDUP ( share ) ;
0001-01-01 02:30:17 +02:30
if ( ! srvcache - > share_name ) {
errno = ENOMEM ;
goto failed ;
}
2004-12-07 21:25:53 +03:00
srvcache - > workgroup = SMB_STRDUP ( workgroup ) ;
0001-01-01 02:30:17 +02:30
if ( ! srvcache - > workgroup ) {
errno = ENOMEM ;
goto failed ;
}
2004-12-07 21:25:53 +03:00
srvcache - > username = SMB_STRDUP ( username ) ;
0001-01-01 02:30:17 +02:30
if ( ! srvcache - > username ) {
errno = ENOMEM ;
goto failed ;
}
0001-01-01 02:30:17 +02:30
DLIST_ADD ( ( context - > server_cache ) , srvcache ) ;
0001-01-01 02:30:17 +02:30
return 0 ;
failed :
SAFE_FREE ( srvcache - > server_name ) ;
SAFE_FREE ( srvcache - > share_name ) ;
SAFE_FREE ( srvcache - > workgroup ) ;
SAFE_FREE ( srvcache - > username ) ;
return 1 ;
}
/*
* Search the server cache for a server
2005-06-02 00:17:16 +04:00
* returns server handle on success , NULL on error ( not found )
0001-01-01 02:30:17 +02:30
* This function is only used if the external cache is not enabled
*/
0001-01-01 02:30:17 +02:30
static SMBCSRV * smbc_get_cached_server ( SMBCCTX * context , const char * server ,
const char * share , const char * workgroup , const char * user )
0001-01-01 02:30:17 +02:30
{
struct smbc_server_cache * srv = NULL ;
/* Search the cache lines */
for ( srv = ( ( struct smbc_server_cache * ) context - > server_cache ) ; srv ; srv = srv - > next ) {
2005-03-11 02:41:19 +03:00
0001-01-01 02:30:17 +02:30
if ( strcmp ( server , srv - > server_name ) = = 0 & &
strcmp ( workgroup , srv - > workgroup ) = = 0 & &
2005-03-11 02:41:19 +03:00
strcmp ( user , srv - > username ) = = 0 ) {
/* If the share name matches, we're cool */
if ( strcmp ( share , srv - > share_name ) = = 0 ) {
return srv - > server ;
}
/*
* We only return an empty share name or the attribute
* server on an exact match ( which would have been
* caught above ) .
*/
if ( * share = = ' \0 ' | | strcmp ( share , " *IPC$ " ) = = 0 )
continue ;
/*
* Never return an empty share name or the attribute
* server if it wasn ' t what was requested .
*/
if ( * srv - > share_name = = ' \0 ' | |
strcmp ( srv - > share_name , " *IPC$ " ) = = 0 )
continue ;
/*
* If we ' re only allowing one share per server , then
* a connection to the server ( other than the
* attribute server connection ) is cool .
*/
2005-03-11 20:01:30 +03:00
if ( context - > options . one_share_per_server ) {
2005-03-11 02:41:19 +03:00
/*
* The currently connected share name
* doesn ' t match the requested share , so
* disconnect from the current share .
*/
if ( ! cli_tdis ( & srv - > server - > cli ) ) {
/* Sigh. Couldn't disconnect. */
cli_shutdown ( & srv - > server - > cli ) ;
context - > callbacks . remove_cached_srv_fn ( context , srv - > server ) ;
continue ;
}
return srv - > server ;
}
}
0001-01-01 02:30:17 +02:30
}
return NULL ;
}
/*
* Search the server cache for a server and remove it
* returns 0 on success
* This function is only used if the external cache is not enabled
*/
static int smbc_remove_cached_server ( SMBCCTX * context , SMBCSRV * server )
{
struct smbc_server_cache * srv = NULL ;
for ( srv = ( ( struct smbc_server_cache * ) context - > server_cache ) ; srv ; srv = srv - > next ) {
if ( server = = srv - > server ) {
/* remove this sucker */
0001-01-01 02:30:17 +02:30
DLIST_REMOVE ( context - > server_cache , srv ) ;
0001-01-01 02:30:17 +02:30
SAFE_FREE ( srv - > server_name ) ;
SAFE_FREE ( srv - > share_name ) ;
SAFE_FREE ( srv - > workgroup ) ;
SAFE_FREE ( srv - > username ) ;
SAFE_FREE ( srv ) ;
return 0 ;
}
}
/* server not found */
return 1 ;
}
/*
* Try to remove all the servers in cache
* returns 1 on failure and 0 if all servers could be removed .
*/
static int smbc_purge_cached ( SMBCCTX * context )
{
0001-01-01 02:30:17 +02:30
struct smbc_server_cache * srv ;
struct smbc_server_cache * next ;
0001-01-01 02:30:17 +02:30
int could_not_purge_all = 0 ;
0001-01-01 02:30:17 +02:30
for ( srv = ( ( struct smbc_server_cache * ) context - > server_cache ) ,
next = ( srv ? srv - > next : NULL ) ;
srv ;
srv = next , next = ( srv ? srv - > next : NULL ) ) {
0001-01-01 02:30:17 +02:30
if ( smbc_remove_unused_server ( context , srv - > server ) ) {
/* could not be removed */
could_not_purge_all = 1 ;
}
}
return could_not_purge_all ;
}
/*
* This functions initializes all server - cache related functions
* to the default ( internal ) system .
*
* We use this to make the rest of the cache system static .
*/
int smbc_default_cache_functions ( SMBCCTX * context )
{
context - > callbacks . add_cached_srv_fn = smbc_add_cached_server ;
context - > callbacks . get_cached_srv_fn = smbc_get_cached_server ;
context - > callbacks . remove_cached_srv_fn = smbc_remove_cached_server ;
context - > callbacks . purge_cached_fn = smbc_purge_cached ;
return 0 ;
}