2000-12-26 08:57:10 +03:00
/*
2002-07-15 14:35:28 +04:00
Unix SMB / Netbios implementation .
2000-12-26 08:57:10 +03:00
SMB client library implementation
Copyright ( C ) Andrew Tridgell 1998
2002-07-15 14:35:28 +04:00
Copyright ( C ) Richard Sharpe 2000 , 2002
2000-12-26 08:57:10 +03:00
Copyright ( C ) John Terpstra 2000
2002-07-15 14:35:28 +04:00
Copyright ( C ) Tom Jansen ( Ninja ISD ) 2002
2000-12-26 08:57:10 +03:00
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"
2002-07-15 14:35:28 +04:00
2003-01-13 23:04:40 +03:00
# include "../include/libsmb_internal.h"
2000-12-26 08:57:10 +03:00
2002-07-15 14:35:28 +04:00
/*
* Functions exported by libsmb_cache . c that we need here
2000-12-26 08:57:10 +03:00
*/
2002-07-15 14:35:28 +04:00
int smbc_default_cache_functions ( SMBCCTX * context ) ;
2000-12-26 08:57:10 +03:00
2002-07-15 14:35:28 +04:00
/*
* check if an element is part of the list .
* FIXME : Does not belong here !
* Can anyone put this in a macro in dlinklist . h ?
* - - Tom
*/
static int DLIST_CONTAINS ( SMBCFILE * list , SMBCFILE * p ) {
if ( ! p | | ! list ) return False ;
do {
if ( p = = list ) return True ;
list = list - > next ;
} while ( list ) ;
return False ;
}
2001-02-26 14:53:22 +03:00
2001-01-05 16:43:19 +03:00
extern BOOL in_client ;
2002-07-15 14:35:28 +04:00
/*
* Is the logging working / configfile read ?
*/
2000-12-26 08:57:10 +03:00
static int smbc_initialized = 0 ;
2003-04-16 18:45:11 +04:00
static int
hex2int ( unsigned int _char )
{
if ( _char > = ' A ' & & _char < = ' F ' )
return _char - ' A ' + 10 ;
if ( _char > = ' a ' & & _char < = ' f ' )
return _char - ' a ' + 10 ;
if ( _char > = ' 0 ' & & _char < = ' 9 ' )
return _char - ' 0 ' ;
return - 1 ;
}
static void
decode_urlpart ( char * segment , size_t sizeof_segment )
{
int old_length = strlen ( segment ) ;
int new_length = 0 ;
int new_length2 = 0 ;
int i = 0 ;
pstring new_segment ;
char * new_usegment = 0 ;
if ( ! old_length ) {
return ;
}
/* make a copy of the old one */
new_usegment = ( char * ) malloc ( old_length * 3 + 1 ) ;
while ( i < old_length ) {
int bReencode = False ;
unsigned char character = segment [ i + + ] ;
if ( ( character < = ' ' ) | | ( character > 127 ) )
bReencode = True ;
new_usegment [ new_length2 + + ] = character ;
if ( character = = ' % ' ) {
int a = i + 1 < old_length ? hex2int ( segment [ i ] ) : - 1 ;
int b = i + 1 < old_length ? hex2int ( segment [ i + 1 ] ) : - 1 ;
if ( ( a = = - 1 ) | | ( b = = - 1 ) ) { /* Only replace if sequence is valid */
/* Contains stray %, make sure to re-encode! */
bReencode = True ;
} else {
/* Valid %xx sequence */
character = a * 16 + b ; /* Replace with value of %dd */
if ( ! character )
break ; /* Stop at %00 */
new_usegment [ new_length2 + + ] = ( unsigned char ) segment [ i + + ] ;
new_usegment [ new_length2 + + ] = ( unsigned char ) segment [ i + + ] ;
}
}
if ( bReencode ) {
unsigned int c = character / 16 ;
new_length2 - - ;
new_usegment [ new_length2 + + ] = ' % ' ;
c + = ( c > 9 ) ? ( ' A ' - 10 ) : ' 0 ' ;
new_usegment [ new_length2 + + ] = c ;
c = character % 16 ;
c + = ( c > 9 ) ? ( ' A ' - 10 ) : ' 0 ' ;
new_usegment [ new_length2 + + ] = c ;
}
new_segment [ new_length + + ] = character ;
}
new_segment [ new_length ] = 0 ;
free ( new_usegment ) ;
/* realloc it with unix charset */
pull_utf8_allocate ( ( void * * ) & new_usegment , new_segment ) ;
/* this assumes (very safely) that removing %aa sequences
only shortens the string */
strncpy ( segment , new_usegment , sizeof_segment ) ;
free ( new_usegment ) ;
}
2000-12-26 08:57:10 +03:00
/*
* Function to parse a path and turn it into components
*
2001-01-05 16:43:19 +03:00
* We accept smb : //[[[domain;]user[:password@]]server[/share[/path[/file]]]]
*
* smb : // means show all the workgroups
2002-07-15 14:35:28 +04:00
* smb : //name/ means, if name<1D> or name<1B> exists, list servers in workgroup,
2001-01-05 16:43:19 +03:00
* else , if name < 20 > exists , list all shares for server . . .
2000-12-26 08:57:10 +03:00
*/
static const char * smbc_prefix = " smb: " ;
static int
2002-07-15 14:35:28 +04:00
smbc_parse_path ( SMBCCTX * context , const char * fname , char * server , char * share , char * path ,
2001-01-12 08:10:45 +03:00
char * user , char * password ) /* FIXME, lengths of strings */
2000-12-26 08:57:10 +03:00
{
2001-11-21 06:55:59 +03:00
static pstring s ;
pstring userinfo ;
2003-01-13 23:04:40 +03:00
const char * p ;
2001-11-21 06:55:59 +03:00
char * q , * r ;
int len ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
server [ 0 ] = share [ 0 ] = path [ 0 ] = user [ 0 ] = password [ 0 ] = ( char ) 0 ;
pstrcpy ( s , fname ) ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
/* clean_fname(s); causing problems ... */
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
/* see if it has the right prefix */
len = strlen ( smbc_prefix ) ;
if ( strncmp ( s , smbc_prefix , len ) | |
( s [ len ] ! = ' / ' & & s [ len ] ! = 0 ) ) return - 1 ; /* What about no smb: ? */
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
p = s + len ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
/* Watch the test below, we are testing to see if we should exit */
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
if ( strncmp ( p , " // " , 2 ) & & strncmp ( p , " \\ \\ " , 2 ) ) {
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
return - 1 ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
p + = 2 ; /* Skip the // or \\ */
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
if ( * p = = ( char ) 0 )
2003-04-16 18:45:11 +04:00
goto decoding ;
2001-01-06 15:15:46 +03:00
2001-11-21 06:55:59 +03:00
if ( * p = = ' / ' ) {
2001-01-06 15:15:46 +03:00
2002-07-15 14:35:28 +04:00
strncpy ( server , context - > workgroup ,
( strlen ( context - > workgroup ) < 16 ) ? strlen ( context - > workgroup ) : 16 ) ;
2001-11-21 06:55:59 +03:00
return 0 ;
}
2001-01-06 15:15:46 +03:00
2001-11-21 06:55:59 +03:00
/*
* ok , its for us . Now parse out the server , share etc .
*
* However , we want to parse out [ [ domain ; ] user [ : password ] @ ] if it
* exists . . .
*/
2001-01-29 12:34:24 +03:00
2001-11-21 06:55:59 +03:00
/* check that '@' occurs before '/', if '/' exists at all */
q = strchr_m ( p , ' @ ' ) ;
r = strchr_m ( p , ' / ' ) ;
if ( q & & ( ! r | | q < r ) ) {
pstring username , passwd , domain ;
2003-01-13 23:04:40 +03:00
const char * u = userinfo ;
2001-01-29 12:34:24 +03:00
2001-11-21 06:55:59 +03:00
next_token ( & p , userinfo , " @ " , sizeof ( fstring ) ) ;
2001-01-29 12:34:24 +03:00
2001-11-21 06:55:59 +03:00
username [ 0 ] = passwd [ 0 ] = domain [ 0 ] = 0 ;
2001-01-29 12:34:24 +03:00
2001-11-21 06:55:59 +03:00
if ( strchr_m ( u , ' ; ' ) ) {
2001-01-29 12:34:24 +03:00
2001-11-21 06:55:59 +03:00
next_token ( & u , domain , " ; " , sizeof ( fstring ) ) ;
2002-07-15 14:35:28 +04:00
2001-11-21 06:55:59 +03:00
}
2001-01-29 12:34:24 +03:00
2001-11-21 06:55:59 +03:00
if ( strchr_m ( u , ' : ' ) ) {
2001-01-29 12:34:24 +03:00
2001-11-21 06:55:59 +03:00
next_token ( & u , username , " : " , sizeof ( fstring ) ) ;
2001-01-29 12:34:24 +03:00
2001-11-21 06:55:59 +03:00
pstrcpy ( passwd , u ) ;
2001-01-29 12:34:24 +03:00
2001-11-21 06:55:59 +03:00
}
else {
2001-01-29 12:34:24 +03:00
2001-11-21 06:55:59 +03:00
pstrcpy ( username , u ) ;
2001-01-29 12:34:24 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-29 12:34:24 +03:00
2001-11-21 06:55:59 +03:00
if ( username [ 0 ] )
strncpy ( user , username , sizeof ( fstring ) ) ; /* FIXME, size and domain */
2001-01-29 12:34:24 +03:00
2001-11-21 06:55:59 +03:00
if ( passwd [ 0 ] )
strncpy ( password , passwd , sizeof ( fstring ) ) ; /* FIXME, size */
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
}
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
if ( ! next_token ( & p , server , " / " , sizeof ( fstring ) ) ) {
2002-07-15 14:35:28 +04:00
2001-11-21 06:55:59 +03:00
return - 1 ;
2002-07-15 14:35:28 +04:00
2001-11-21 06:55:59 +03:00
}
2001-01-05 16:43:19 +03:00
2003-04-16 18:45:11 +04:00
if ( * p = = ( char ) 0 ) goto decoding ; /* That's it ... */
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
if ( ! next_token ( & p , share , " / " , sizeof ( fstring ) ) ) {
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
return - 1 ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
pstrcpy ( path , p ) ;
2003-04-16 18:45:11 +04:00
2001-11-21 06:55:59 +03:00
all_string_sub ( path , " / " , " \\ " , 0 ) ;
2000-12-26 08:57:10 +03:00
2003-04-16 18:45:11 +04:00
decoding :
decode_urlpart ( path , sizeof ( pstring ) ) ;
decode_urlpart ( server , sizeof ( fstring ) ) ;
decode_urlpart ( share , sizeof ( fstring ) ) ;
decode_urlpart ( user , sizeof ( fstring ) ) ;
decode_urlpart ( password , sizeof ( fstring ) ) ;
2001-11-21 06:55:59 +03:00
return 0 ;
2000-12-26 08:57:10 +03:00
}
/*
* Convert an SMB error into a UNIX error . . .
*/
2002-07-15 14:35:28 +04:00
static int smbc_errno ( SMBCCTX * context , struct cli_state * c )
2000-12-26 08:57:10 +03:00
{
2002-09-25 19:19:00 +04:00
int ret = cli_errno ( c ) ;
2001-08-10 10:00:33 +04:00
if ( cli_is_dos_error ( c ) ) {
uint8 eclass ;
uint32 ecode ;
cli_dos_error ( c , & eclass , & ecode ) ;
DEBUG ( 3 , ( " smbc_error %d %d (0x%x) -> %d \n " ,
( int ) eclass , ( int ) ecode , ( int ) ecode , ret ) ) ;
} else {
2001-08-27 23:46:22 +04:00
NTSTATUS status ;
2001-08-10 10:00:33 +04:00
2001-08-10 10:16:05 +04:00
status = cli_nt_error ( c ) ;
2001-08-10 10:00:33 +04:00
2001-09-04 14:57:29 +04:00
DEBUG ( 3 , ( " smbc errno %s -> %d \n " ,
2002-09-25 19:19:00 +04:00
nt_errstr ( status ) , ret ) ) ;
2001-08-10 10:00:33 +04:00
}
2000-12-26 08:57:10 +03:00
return ret ;
}
2002-07-15 14:35:28 +04:00
/*
* Check a server_fd .
* returns 0 if the server is in shape . Returns 1 on error
*
* Also useable outside libsmbclient to enable external cache
* to do some checks too .
*/
int smbc_check_server ( SMBCCTX * context , SMBCSRV * server )
{
2002-09-25 19:19:00 +04:00
if ( send_keepalive ( server - > cli . fd ) = = False )
2002-07-15 14:35:28 +04:00
return 1 ;
/* connection is ok */
return 0 ;
}
/*
2003-01-13 23:04:40 +03:00
* Remove a server from the cached server list it ' s unused .
2002-07-15 14:35:28 +04:00
* On success , 0 is returned . 1 is returned if the server could not be removed .
*
* Also useable outside libsmbclient
*/
int smbc_remove_unused_server ( SMBCCTX * context , SMBCSRV * srv )
{
SMBCFILE * file ;
/* are we being fooled ? */
2003-01-13 23:04:40 +03:00
if ( ! context | | ! context - > internal | |
! context - > internal - > _initialized | | ! srv ) return 1 ;
2002-07-15 14:35:28 +04:00
/* Check all open files/directories for a relation with this server */
2003-01-13 23:04:40 +03:00
for ( file = context - > internal - > _files ; file ; file = file - > next ) {
2002-07-15 14:35:28 +04:00
if ( file - > srv = = srv ) {
/* Still used */
DEBUG ( 3 , ( " smbc_remove_usused_server: %p still used by %p. \n " ,
srv , file ) ) ;
return 1 ;
}
}
2003-01-13 23:04:40 +03:00
DLIST_REMOVE ( context - > internal - > _servers , srv ) ;
2002-07-15 14:35:28 +04:00
cli_shutdown ( & srv - > cli ) ;
DEBUG ( 3 , ( " smbc_remove_usused_server: %p removed. \n " , srv ) ) ;
context - > callbacks . remove_cached_srv_fn ( context , srv ) ;
SAFE_FREE ( srv ) ;
return 0 ;
}
2000-12-26 08:57:10 +03:00
/*
* Connect to a server , possibly on an existing connection
2001-01-12 08:10:45 +03:00
*
* Here , what we want to do is : If the server and username
* match an existing connection , reuse that , otherwise , establish a
* new connection .
*
* If we have to create a new connection , call the auth_fn to get the
* info we need , unless the username and password were passed in .
2000-12-26 08:57:10 +03:00
*/
2002-07-15 14:35:28 +04:00
SMBCSRV * smbc_server ( SMBCCTX * context ,
2003-04-16 18:45:11 +04:00
const char * server , const char * share ,
fstring workgroup , fstring username ,
fstring password )
2000-12-26 08:57:10 +03:00
{
2002-07-15 14:35:28 +04:00
SMBCSRV * srv = NULL ;
int auth_called = 0 ;
2001-11-21 06:55:59 +03:00
struct cli_state c ;
struct nmb_name called , calling ;
2003-04-16 18:45:11 +04:00
char * p ;
const char * server_n = server ;
2001-11-21 06:55:59 +03:00
fstring group ;
pstring ipenv ;
struct in_addr ip ;
2002-07-15 14:35:28 +04:00
int tried_reverse = 0 ;
2000-12-26 08:57:10 +03:00
2002-07-15 14:35:28 +04:00
zero_ip ( & ip ) ;
2001-11-21 06:55:59 +03:00
ZERO_STRUCT ( c ) ;
if ( server [ 0 ] = = 0 ) {
errno = EPERM ;
return NULL ;
}
2002-07-15 14:35:28 +04:00
check_server_cache :
2001-11-21 06:55:59 +03:00
2002-07-15 14:35:28 +04:00
srv = context - > callbacks . get_cached_srv_fn ( context , server , share ,
workgroup , username ) ;
if ( ! auth_called & & ! srv & & ( ! username [ 0 ] | | ! password [ 0 ] ) ) {
context - > callbacks . auth_fn ( server , share , workgroup , sizeof ( fstring ) ,
username , sizeof ( fstring ) , password , sizeof ( fstring ) ) ;
/*
* However , smbc_auth_fn may have picked up info relating to an
* existing connection , so try for an existing connection again . . .
*/
auth_called = 1 ;
goto check_server_cache ;
2001-11-21 06:55:59 +03:00
}
2002-07-15 14:35:28 +04:00
if ( srv ) {
if ( context - > callbacks . check_server_fn ( context , srv ) ) {
/*
* This server is no good anymore
* Try to remove it and check for more possible servers in the cache
*/
if ( context - > callbacks . remove_unused_server_fn ( context , srv ) ) {
/*
* We could not remove the server completely , remove it from the cache
* so we will not get it again . It will be removed when the last file / dir
* is closed .
*/
context - > callbacks . remove_cached_srv_fn ( context , srv ) ;
}
/*
* Maybe there are more cached connections to this server
*/
goto check_server_cache ;
}
return srv ;
}
2001-11-21 06:55:59 +03:00
2002-07-15 14:35:28 +04:00
make_nmb_name ( & calling , context - > netbios_name , 0x0 ) ;
2001-11-21 06:55:59 +03:00
make_nmb_name ( & called , server , 0x20 ) ;
DEBUG ( 4 , ( " smbc_server: server_n=[%s] server=[%s] \n " , server_n , server ) ) ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
if ( ( p = strchr_m ( server_n , ' # ' ) ) & &
( strcmp ( p + 1 , " 1D " ) = = 0 | | strcmp ( p + 1 , " 01 " ) = = 0 ) ) {
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
fstrcpy ( group , server_n ) ;
p = strchr_m ( group , ' # ' ) ;
* p = 0 ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
}
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
DEBUG ( 4 , ( " -> server_n=[%s] server=[%s] \n " , server_n , server ) ) ;
2000-12-26 08:57:10 +03:00
again :
2001-11-21 06:55:59 +03:00
slprintf ( ipenv , sizeof ( ipenv ) - 1 , " HOST_%s " , server_n ) ;
2002-07-15 14:35:28 +04:00
zero_ip ( & ip ) ;
2001-11-21 06:55:59 +03:00
/* have to open a new connection */
2002-07-15 14:35:28 +04:00
if ( ! cli_initialise ( & c ) ) {
2001-11-21 06:55:59 +03:00
errno = ENOENT ;
return NULL ;
}
2002-07-15 14:35:28 +04:00
c . timeout = context - > timeout ;
if ( ! cli_connect ( & c , server_n , & ip ) ) {
cli_shutdown ( & c ) ;
errno = ENOENT ;
return NULL ;
}
2001-11-21 06:55:59 +03:00
if ( ! cli_session_request ( & c , & calling , & called ) ) {
cli_shutdown ( & c ) ;
if ( strcmp ( called . name , " *SMBSERVER " ) ) {
make_nmb_name ( & called , " *SMBSERVER " , 0x20 ) ;
goto again ;
}
2002-07-15 14:35:28 +04:00
else { /* Try one more time, but ensure we don't loop */
/* Only try this if server is an IP address ... */
if ( is_ipaddress ( server ) & & ! tried_reverse ) {
fstring remote_name ;
struct in_addr rem_ip ;
2002-09-25 19:19:00 +04:00
if ( ( rem_ip . s_addr = inet_addr ( server ) ) = = INADDR_NONE ) {
2002-07-15 14:35:28 +04:00
DEBUG ( 4 , ( " Could not convert IP address %s to struct in_addr \n " , server ) ) ;
errno = ENOENT ;
return NULL ;
}
tried_reverse + + ; /* Yuck */
if ( name_status_find ( " * " , 0 , 0 , rem_ip , remote_name ) ) {
make_nmb_name ( & called , remote_name , 0x20 ) ;
goto again ;
}
}
}
2001-11-21 06:55:59 +03:00
errno = ENOENT ;
return NULL ;
}
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
DEBUG ( 4 , ( " session request ok \n " ) ) ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
if ( ! cli_negprot ( & c ) ) {
cli_shutdown ( & c ) ;
errno = ENOENT ;
return NULL ;
}
if ( ! cli_session_setup ( & c , username ,
password , strlen ( password ) ,
password , strlen ( password ) ,
workgroup ) & &
/* try an anonymous login if it failed */
! cli_session_setup ( & c , " " , " " , 1 , " " , 0 , workgroup ) ) {
cli_shutdown ( & c ) ;
errno = EPERM ;
return NULL ;
}
DEBUG ( 4 , ( " session setup ok \n " ) ) ;
if ( ! cli_send_tconX ( & c , share , " ????? " ,
password , strlen ( password ) + 1 ) ) {
2002-07-15 14:35:28 +04:00
errno = smbc_errno ( context , & c ) ;
2001-11-21 06:55:59 +03:00
cli_shutdown ( & c ) ;
return NULL ;
}
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
DEBUG ( 4 , ( " tconx ok \n " ) ) ;
2000-12-26 08:57:10 +03:00
2002-07-15 14:35:28 +04:00
/*
* Ok , we have got a nice connection
* Let ' s find a free server_fd
*/
srv = ( SMBCSRV * ) malloc ( sizeof ( * srv ) ) ;
2001-11-21 06:55:59 +03:00
if ( ! srv ) {
errno = ENOMEM ;
goto failed ;
}
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
ZERO_STRUCTP ( srv ) ;
srv - > cli = c ;
srv - > dev = ( dev_t ) ( str_checksum ( server ) ^ str_checksum ( share ) ) ;
2000-12-26 08:57:10 +03:00
2002-07-15 14:35:28 +04:00
/* now add it to the cache (internal or external) */
if ( context - > callbacks . add_cached_srv_fn ( context , srv , server , share , workgroup , username ) ) {
DEBUG ( 3 , ( " Failed to add server to cache \n " ) ) ;
2001-11-21 06:55:59 +03:00
goto failed ;
}
2000-12-26 08:57:10 +03:00
2002-07-15 14:35:28 +04:00
DEBUG ( 2 , ( " Server connect ok: //%s/%s: %p \n " ,
server , share , srv ) ) ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
return srv ;
2000-12-26 08:57:10 +03:00
failed :
2001-11-21 06:55:59 +03:00
cli_shutdown ( & c ) ;
if ( ! srv ) return NULL ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
SAFE_FREE ( srv ) ;
return NULL ;
}
2000-12-26 08:57:10 +03:00
/*
* Routine to open ( ) a file . . .
*/
2002-07-15 14:35:28 +04:00
static SMBCFILE * smbc_open_ctx ( SMBCCTX * context , const char * fname , int flags , mode_t mode )
2000-12-26 08:57:10 +03:00
{
2001-11-21 06:55:59 +03:00
fstring server , share , user , password , workgroup ;
pstring path ;
2002-07-15 14:35:28 +04:00
SMBCSRV * srv = NULL ;
SMBCFILE * file = NULL ;
2001-11-21 06:55:59 +03:00
int fd ;
2000-12-26 08:57:10 +03:00
2003-01-13 23:04:40 +03:00
if ( ! context | | ! context - > internal | |
! context - > internal - > _initialized ) {
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ; /* Best I can think of ... */
2002-07-15 14:35:28 +04:00
return NULL ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
}
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
if ( ! fname ) {
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ;
2002-07-15 14:35:28 +04:00
return NULL ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
}
2000-12-26 08:57:10 +03:00
2002-07-15 14:35:28 +04:00
smbc_parse_path ( context , fname , server , share , path , user , password ) ; /* FIXME, check errors */
2001-01-12 08:10:45 +03:00
2003-03-22 12:27:42 +03:00
if ( user [ 0 ] = = ( char ) 0 ) fstrcpy ( user , context - > user ) ;
2000-12-26 08:57:10 +03:00
2003-03-22 12:27:42 +03:00
fstrcpy ( workgroup , context - > workgroup ) ;
2001-11-17 10:30:19 +03:00
2002-07-15 14:35:28 +04:00
srv = smbc_server ( context , server , share , workgroup , user , password ) ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
if ( ! srv ) {
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
if ( errno = = EPERM ) errno = EACCES ;
2002-07-15 14:35:28 +04:00
return NULL ; /* smbc_server sets errno */
2001-11-21 06:55:59 +03:00
}
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
/* Hmmm, the test for a directory is suspect here ... FIXME */
2001-03-27 16:13:59 +04:00
2001-11-21 06:55:59 +03:00
if ( strlen ( path ) > 0 & & path [ strlen ( path ) - 1 ] = = ' \\ ' ) {
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
fd = - 1 ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
}
else {
2002-07-15 14:35:28 +04:00
file = malloc ( sizeof ( SMBCFILE ) ) ;
2000-12-26 08:57:10 +03:00
2002-07-15 14:35:28 +04:00
if ( ! file ) {
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
errno = ENOMEM ;
2002-07-15 14:35:28 +04:00
return NULL ;
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
}
2000-12-26 08:57:10 +03:00
2002-07-15 14:35:28 +04:00
ZERO_STRUCTP ( file ) ;
2001-11-21 06:55:59 +03:00
if ( ( fd = cli_open ( & srv - > cli , path , flags , DENY_NONE ) ) < 0 ) {
2001-01-24 15:32:20 +03:00
2001-11-21 06:55:59 +03:00
/* Handle the error ... */
2001-01-24 15:32:20 +03:00
2002-07-15 14:35:28 +04:00
SAFE_FREE ( file ) ;
errno = smbc_errno ( context , & srv - > cli ) ;
return NULL ;
2001-01-24 15:32:20 +03:00
2001-11-21 06:55:59 +03:00
}
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
/* Fill in file struct */
2000-12-26 08:57:10 +03:00
2002-07-15 14:35:28 +04:00
file - > cli_fd = fd ;
file - > fname = strdup ( fname ) ;
file - > srv = srv ;
file - > offset = 0 ;
file - > file = True ;
2000-12-26 08:57:10 +03:00
2003-01-13 23:04:40 +03:00
DLIST_ADD ( context - > internal - > _files , file ) ;
2002-07-15 14:35:28 +04:00
return file ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
}
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
/* Check if opendir needed ... */
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
if ( fd = = - 1 ) {
int eno = 0 ;
2000-12-26 08:57:10 +03:00
2002-07-15 14:35:28 +04:00
eno = smbc_errno ( context , & srv - > cli ) ;
file = context - > opendir ( context , fname ) ;
if ( ! file ) errno = eno ;
return file ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
}
2000-12-26 08:57:10 +03:00
2002-07-15 14:35:28 +04:00
errno = EINVAL ; /* FIXME, correct errno ? */
return NULL ;
2000-12-26 08:57:10 +03:00
}
/*
* Routine to create a file
*/
static int creat_bits = O_WRONLY | O_CREAT | O_TRUNC ; /* FIXME: Do we need this */
2002-07-15 14:35:28 +04:00
static SMBCFILE * smbc_creat_ctx ( SMBCCTX * context , const char * path , mode_t mode )
2000-12-26 08:57:10 +03:00
{
2001-01-07 10:10:50 +03:00
2003-01-13 23:04:40 +03:00
if ( ! context | | ! context - > internal | |
! context - > internal - > _initialized ) {
2001-01-07 10:10:50 +03:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ;
2002-07-15 14:35:28 +04:00
return NULL ;
2001-01-07 10:10:50 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-07 10:10:50 +03:00
2002-07-15 14:35:28 +04:00
return smbc_open_ctx ( context , path , creat_bits , mode ) ;
2000-12-26 08:57:10 +03:00
}
/*
* Routine to read ( ) a file . . .
*/
2002-07-15 14:35:28 +04:00
static ssize_t smbc_read_ctx ( SMBCCTX * context , SMBCFILE * file , void * buf , size_t count )
2000-12-26 08:57:10 +03:00
{
2001-11-21 06:55:59 +03:00
int ret ;
2000-12-26 08:57:10 +03:00
2003-01-13 23:04:40 +03:00
if ( ! context | | ! context - > internal | |
! context - > internal - > _initialized ) {
2001-01-07 10:10:50 +03:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ;
return - 1 ;
2001-01-07 10:10:50 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-07 10:10:50 +03:00
2002-07-15 14:35:28 +04:00
DEBUG ( 4 , ( " smbc_read(%p, %d) \n " , file , ( int ) count ) ) ;
2000-12-26 08:57:10 +03:00
2003-01-13 23:04:40 +03:00
if ( ! file | | ! DLIST_CONTAINS ( context - > internal - > _files , file ) ) {
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
errno = EBADF ;
return - 1 ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
}
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
/* Check that the buffer exists ... */
2001-03-01 22:21:57 +03:00
2001-11-21 06:55:59 +03:00
if ( buf = = NULL ) {
2001-03-01 22:21:57 +03:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ;
return - 1 ;
2001-03-01 22:21:57 +03:00
2001-11-21 06:55:59 +03:00
}
2001-03-01 22:21:57 +03:00
2002-07-15 14:35:28 +04:00
ret = cli_read ( & file - > srv - > cli , file - > cli_fd , buf , file - > offset , count ) ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
if ( ret < 0 ) {
2000-12-26 08:57:10 +03:00
2002-07-15 14:35:28 +04:00
errno = smbc_errno ( context , & file - > srv - > cli ) ;
2001-11-21 06:55:59 +03:00
return - 1 ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
}
2000-12-26 08:57:10 +03:00
2002-07-15 14:35:28 +04:00
file - > offset + = ret ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
DEBUG ( 4 , ( " --> %d \n " , ret ) ) ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
return ret ; /* Success, ret bytes of data ... */
2000-12-26 08:57:10 +03:00
}
/*
* Routine to write ( ) a file . . .
*/
2002-07-15 14:35:28 +04:00
static ssize_t smbc_write_ctx ( SMBCCTX * context , SMBCFILE * file , void * buf , size_t count )
2000-12-26 08:57:10 +03:00
{
2001-11-21 06:55:59 +03:00
int ret ;
2000-12-26 08:57:10 +03:00
2003-01-13 23:04:40 +03:00
if ( ! context | | ! context - > internal | |
! context - > internal - > _initialized ) {
2001-01-07 10:10:50 +03:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ;
return - 1 ;
2001-01-07 10:10:50 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-07 10:10:50 +03:00
2003-01-13 23:04:40 +03:00
if ( ! file | | ! DLIST_CONTAINS ( context - > internal - > _files , file ) ) {
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
errno = EBADF ;
return - 1 ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
}
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
/* Check that the buffer exists ... */
2001-02-26 14:53:22 +03:00
2001-11-21 06:55:59 +03:00
if ( buf = = NULL ) {
2001-02-26 14:53:22 +03:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ;
return - 1 ;
2001-02-26 14:53:22 +03:00
2001-11-21 06:55:59 +03:00
}
2001-02-26 14:53:22 +03:00
2002-07-15 14:35:28 +04:00
ret = cli_write ( & file - > srv - > cli , file - > cli_fd , 0 , buf , file - > offset , count ) ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
if ( ret < = 0 ) {
2000-12-26 08:57:10 +03:00
2002-07-15 14:35:28 +04:00
errno = smbc_errno ( context , & file - > srv - > cli ) ;
2001-11-21 06:55:59 +03:00
return - 1 ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
}
2000-12-26 08:57:10 +03:00
2002-07-15 14:35:28 +04:00
file - > offset + = ret ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
return ret ; /* Success, 0 bytes of data ... */
2000-12-26 08:57:10 +03:00
}
2001-01-05 16:43:19 +03:00
2000-12-26 08:57:10 +03:00
/*
* Routine to close ( ) a file . . .
*/
2002-07-15 14:35:28 +04:00
static int smbc_close_ctx ( SMBCCTX * context , SMBCFILE * file )
2000-12-26 08:57:10 +03:00
{
2002-07-15 14:35:28 +04:00
SMBCSRV * srv ;
2000-12-26 08:57:10 +03:00
2003-01-13 23:04:40 +03:00
if ( ! context | | ! context - > internal | |
! context - > internal - > _initialized ) {
2001-01-07 10:10:50 +03:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ;
return - 1 ;
2001-01-07 10:10:50 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-07 10:10:50 +03:00
2003-01-13 23:04:40 +03:00
if ( ! file | | ! DLIST_CONTAINS ( context - > internal - > _files , file ) ) {
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
errno = EBADF ;
return - 1 ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
}
2000-12-26 08:57:10 +03:00
2002-07-15 14:35:28 +04:00
/* IS a dir ... */
if ( ! file - > file ) {
return context - > closedir ( context , file ) ;
2000-12-26 08:57:10 +03:00
2002-07-15 14:35:28 +04:00
}
if ( ! cli_close ( & file - > srv - > cli , file - > cli_fd ) ) {
DEBUG ( 3 , ( " cli_close failed on %s. purging server. \n " ,
file - > fname ) ) ;
/* Deallocate slot and remove the server
* from the server cache if unused */
errno = smbc_errno ( context , & file - > srv - > cli ) ;
srv = file - > srv ;
2003-01-13 23:04:40 +03:00
DLIST_REMOVE ( context - > internal - > _files , file ) ;
2002-07-15 14:35:28 +04:00
SAFE_FREE ( file - > fname ) ;
SAFE_FREE ( file ) ;
context - > callbacks . remove_unused_server_fn ( context , srv ) ;
2001-03-01 22:21:57 +03:00
2001-11-21 06:55:59 +03:00
return - 1 ;
2001-03-01 22:21:57 +03:00
2001-11-21 06:55:59 +03:00
}
2001-03-01 22:21:57 +03:00
2003-01-13 23:04:40 +03:00
DLIST_REMOVE ( context - > internal - > _files , file ) ;
2002-07-15 14:35:28 +04:00
SAFE_FREE ( file - > fname ) ;
SAFE_FREE ( file ) ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
return 0 ;
2000-12-26 08:57:10 +03:00
}
2002-07-15 14:35:28 +04:00
/*
* Get info from an SMB server on a file . Use a qpathinfo call first
* and if that fails , use getatr , as Win95 sometimes refuses qpathinfo
*/
static BOOL smbc_getatr ( SMBCCTX * context , SMBCSRV * srv , char * path ,
uint16 * mode , size_t * size ,
time_t * c_time , time_t * a_time , time_t * m_time ,
SMB_INO_T * ino )
{
2003-01-13 23:04:40 +03:00
if ( ! context | | ! context - > internal | |
! context - > internal - > _initialized ) {
2002-07-15 14:35:28 +04:00
errno = EINVAL ;
return - 1 ;
}
DEBUG ( 4 , ( " smbc_getatr: sending qpathinfo \n " ) ) ;
if ( ! srv - > no_pathinfo2 & &
cli_qpathinfo2 ( & srv - > cli , path , c_time , a_time , m_time , NULL ,
size , mode , ino ) ) return True ;
/* if this is NT then don't bother with the getatr */
if ( srv - > cli . capabilities & CAP_NT_SMBS ) return False ;
if ( cli_getatr ( & srv - > cli , path , mode , size , m_time ) ) {
a_time = c_time = m_time ;
srv - > no_pathinfo2 = True ;
return True ;
}
return False ;
}
2000-12-26 08:57:10 +03:00
/*
* Routine to unlink ( ) a file
*/
2002-07-15 14:35:28 +04:00
static int smbc_unlink_ctx ( SMBCCTX * context , const char * fname )
2000-12-26 08:57:10 +03:00
{
2001-11-21 06:55:59 +03:00
fstring server , share , user , password , workgroup ;
pstring path ;
2002-07-15 14:35:28 +04:00
SMBCSRV * srv = NULL ;
2000-12-26 08:57:10 +03:00
2003-01-13 23:04:40 +03:00
if ( ! context | | ! context - > internal | |
! context - > internal - > _initialized ) {
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ; /* Best I can think of ... */
return - 1 ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
}
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
if ( ! fname ) {
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ;
return - 1 ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
}
2000-12-26 08:57:10 +03:00
2002-07-15 14:35:28 +04:00
smbc_parse_path ( context , fname , server , share , path , user , password ) ; /* FIXME, check errors */
2000-12-26 08:57:10 +03:00
2003-03-22 12:27:42 +03:00
if ( user [ 0 ] = = ( char ) 0 ) fstrcpy ( user , context - > user ) ;
2001-01-12 08:10:45 +03:00
2003-03-22 12:27:42 +03:00
fstrcpy ( workgroup , context - > workgroup ) ;
2001-11-17 10:30:19 +03:00
2002-07-15 14:35:28 +04:00
srv = smbc_server ( context , server , share , workgroup , user , password ) ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
if ( ! srv ) {
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
return - 1 ; /* smbc_server sets errno */
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
}
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
/* if (strncmp(srv->cli.dev, "LPT", 3) == 0) {
2000-12-26 08:57:10 +03:00
2002-07-15 14:35:28 +04:00
int job = smbc_stat_printjob ( srv , path , NULL , NULL ) ;
if ( job = = - 1 ) {
2000-12-26 08:57:10 +03:00
2002-07-15 14:35:28 +04:00
return - 1 ;
2000-12-26 08:57:10 +03:00
2002-07-15 14:35:28 +04:00
}
if ( ( err = cli_printjob_del ( & srv - > cli , job ) ) ! = 0 ) {
2000-12-26 08:57:10 +03:00
2001-03-05 16:34:48 +03:00
2002-07-15 14:35:28 +04:00
return - 1 ;
2000-12-26 08:57:10 +03:00
2002-07-15 14:35:28 +04:00
}
} else */
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
if ( ! cli_unlink ( & srv - > cli , path ) ) {
2000-12-26 08:57:10 +03:00
2002-07-15 14:35:28 +04:00
errno = smbc_errno ( context , & srv - > cli ) ;
2001-01-24 15:32:20 +03:00
2001-11-21 06:55:59 +03:00
if ( errno = = EACCES ) { /* Check if the file is a directory */
2001-01-24 15:32:20 +03:00
2001-11-21 06:55:59 +03:00
int saverr = errno ;
size_t size = 0 ;
uint16 mode = 0 ;
time_t m_time = 0 , a_time = 0 , c_time = 0 ;
SMB_INO_T ino = 0 ;
2001-01-24 15:32:20 +03:00
2002-07-15 14:35:28 +04:00
if ( ! smbc_getatr ( context , srv , path , & mode , & size ,
2001-11-21 06:55:59 +03:00
& c_time , & a_time , & m_time , & ino ) ) {
2001-01-24 15:32:20 +03:00
2001-11-21 06:55:59 +03:00
/* Hmmm, bad error ... What? */
2001-01-24 15:32:20 +03:00
2002-07-15 14:35:28 +04:00
errno = smbc_errno ( context , & srv - > cli ) ;
2001-11-21 06:55:59 +03:00
return - 1 ;
2001-01-24 15:32:20 +03:00
2001-11-21 06:55:59 +03:00
}
else {
2001-01-24 15:32:20 +03:00
2001-11-21 06:55:59 +03:00
if ( IS_DOS_DIR ( mode ) )
errno = EISDIR ;
else
errno = saverr ; /* Restore this */
2001-01-24 15:32:20 +03:00
2001-11-21 06:55:59 +03:00
}
}
2001-01-24 15:32:20 +03:00
2001-11-21 06:55:59 +03:00
return - 1 ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
}
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
return 0 ; /* Success ... */
2000-12-26 08:57:10 +03:00
}
/*
* Routine to rename ( ) a file
*/
2002-07-15 14:35:28 +04:00
static int smbc_rename_ctx ( SMBCCTX * ocontext , const char * oname ,
SMBCCTX * ncontext , const char * nname )
2000-12-26 08:57:10 +03:00
{
2001-11-21 06:55:59 +03:00
fstring server1 , share1 , server2 , share2 , user1 , user2 , password1 , password2 , workgroup ;
pstring path1 , path2 ;
2002-07-15 14:35:28 +04:00
SMBCSRV * srv = NULL ;
2000-12-26 08:57:10 +03:00
2003-01-13 23:04:40 +03:00
if ( ! ocontext | | ! ncontext | |
! ocontext - > internal | | ! ncontext - > internal | |
! ocontext - > internal - > _initialized | |
! ncontext - > internal - > _initialized ) {
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ; /* Best I can think of ... */
return - 1 ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
}
2002-07-15 14:35:28 +04:00
2001-11-21 06:55:59 +03:00
if ( ! oname | | ! nname ) {
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ;
return - 1 ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
}
2002-07-15 14:35:28 +04:00
2001-11-21 06:55:59 +03:00
DEBUG ( 4 , ( " smbc_rename(%s,%s) \n " , oname , nname ) ) ;
2000-12-26 08:57:10 +03:00
2002-07-15 14:35:28 +04:00
smbc_parse_path ( ocontext , oname , server1 , share1 , path1 , user1 , password1 ) ;
2001-01-12 08:10:45 +03:00
2003-03-22 12:27:42 +03:00
if ( user1 [ 0 ] = = ( char ) 0 ) fstrcpy ( user1 , ocontext - > user ) ;
2001-01-12 08:10:45 +03:00
2002-07-15 14:35:28 +04:00
smbc_parse_path ( ncontext , nname , server2 , share2 , path2 , user2 , password2 ) ;
2000-12-26 08:57:10 +03:00
2003-03-22 12:27:42 +03:00
if ( user2 [ 0 ] = = ( char ) 0 ) fstrcpy ( user2 , ncontext - > user ) ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
if ( strcmp ( server1 , server2 ) | | strcmp ( share1 , share2 ) | |
strcmp ( user1 , user2 ) ) {
2001-01-12 08:10:45 +03:00
2001-11-21 06:55:59 +03:00
/* Can't rename across file systems, or users?? */
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
errno = EXDEV ;
return - 1 ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
}
2000-12-26 08:57:10 +03:00
2003-03-22 12:27:42 +03:00
fstrcpy ( workgroup , ocontext - > workgroup ) ;
2002-07-15 14:35:28 +04:00
/* HELP !!! Which workgroup should I use ? Or are they always the same -- Tom */
srv = smbc_server ( ocontext , server1 , share1 , workgroup , user1 , password1 ) ;
2001-11-21 06:55:59 +03:00
if ( ! srv ) {
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
return - 1 ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
}
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
if ( ! cli_rename ( & srv - > cli , path1 , path2 ) ) {
2002-07-15 14:35:28 +04:00
int eno = smbc_errno ( ocontext , & srv - > cli ) ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
if ( eno ! = EEXIST | |
! cli_unlink ( & srv - > cli , path2 ) | |
! cli_rename ( & srv - > cli , path1 , path2 ) ) {
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
errno = eno ;
return - 1 ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
}
}
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
return 0 ; /* Success */
2000-12-26 08:57:10 +03:00
}
/*
* A routine to lseek ( ) a file
*/
2002-07-15 14:35:28 +04:00
static off_t smbc_lseek_ctx ( SMBCCTX * context , SMBCFILE * file , off_t offset , int whence )
2000-12-26 08:57:10 +03:00
{
2001-11-21 06:55:59 +03:00
size_t size ;
2000-12-26 08:57:10 +03:00
2003-01-13 23:04:40 +03:00
if ( ! context | | ! context - > internal | |
! context - > internal - > _initialized ) {
2001-01-07 10:10:50 +03:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ;
return - 1 ;
2002-07-15 14:35:28 +04:00
2001-11-21 06:55:59 +03:00
}
2000-12-26 08:57:10 +03:00
2003-01-13 23:04:40 +03:00
if ( ! file | | ! DLIST_CONTAINS ( context - > internal - > _files , file ) ) {
2001-03-01 22:21:57 +03:00
2001-11-21 06:55:59 +03:00
errno = EBADF ;
return - 1 ;
2001-03-01 22:21:57 +03:00
2001-11-21 06:55:59 +03:00
}
2001-03-01 22:21:57 +03:00
2002-07-15 14:35:28 +04:00
if ( ! file - > file ) {
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ;
return - 1 ; /* Can't lseek a dir ... */
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
}
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
switch ( whence ) {
case SEEK_SET :
2002-07-15 14:35:28 +04:00
file - > offset = offset ;
2001-11-21 06:55:59 +03:00
break ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
case SEEK_CUR :
2002-07-15 14:35:28 +04:00
file - > offset + = offset ;
2001-11-21 06:55:59 +03:00
break ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
case SEEK_END :
2002-07-15 14:35:28 +04:00
if ( ! cli_qfileinfo ( & file - > srv - > cli , file - > cli_fd , NULL , & size , NULL , NULL ,
2003-04-16 18:45:11 +04:00
NULL , NULL , NULL ) )
{
SMB_BIG_UINT b_size = size ;
if ( ! cli_getattrE ( & file - > srv - > cli , file - > cli_fd , NULL , & b_size , NULL , NULL ,
NULL ) )
{
2001-11-21 06:55:59 +03:00
errno = EINVAL ;
return - 1 ;
2003-04-16 18:45:11 +04:00
} else
size = b_size ;
2001-11-21 06:55:59 +03:00
}
2002-07-15 14:35:28 +04:00
file - > offset = size + offset ;
2001-11-21 06:55:59 +03:00
break ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
default :
errno = EINVAL ;
break ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
}
2000-12-26 08:57:10 +03:00
2002-07-15 14:35:28 +04:00
return file - > offset ;
2000-12-26 08:57:10 +03:00
}
/*
* Generate an inode number from file name for those things that need it
*/
static
2002-07-15 14:35:28 +04:00
ino_t smbc_inode ( SMBCCTX * context , const char * name )
2000-12-26 08:57:10 +03:00
{
2003-01-13 23:04:40 +03:00
if ( ! context | | ! context - > internal | |
! context - > internal - > _initialized ) {
2002-07-15 14:35:28 +04:00
errno = EINVAL ;
return - 1 ;
}
2001-11-21 06:55:59 +03:00
if ( ! * name ) return 2 ; /* FIXME, why 2 ??? */
return ( ino_t ) str_checksum ( name ) ;
2000-12-26 08:57:10 +03:00
}
/*
* Routine to put basic stat info into a stat structure . . . Used by stat and
* fstat below .
*/
static
2002-07-15 14:35:28 +04:00
int smbc_setup_stat ( SMBCCTX * context , struct stat * st , char * fname , size_t size , int mode )
2000-12-26 08:57:10 +03:00
{
2002-07-15 14:35:28 +04:00
2001-11-21 06:55:59 +03:00
st - > st_mode = 0 ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
if ( IS_DOS_DIR ( mode ) ) {
st - > st_mode = SMBC_DIR_MODE ;
} else {
st - > st_mode = SMBC_FILE_MODE ;
}
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
if ( IS_DOS_ARCHIVE ( mode ) ) st - > st_mode | = S_IXUSR ;
if ( IS_DOS_SYSTEM ( mode ) ) st - > st_mode | = S_IXGRP ;
if ( IS_DOS_HIDDEN ( mode ) ) st - > st_mode | = S_IXOTH ;
if ( ! IS_DOS_READONLY ( mode ) ) st - > st_mode | = S_IWUSR ;
st - > st_size = size ;
st - > st_blksize = 512 ;
st - > st_blocks = ( size + 511 ) / 512 ;
st - > st_uid = getuid ( ) ;
st - > st_gid = getgid ( ) ;
if ( IS_DOS_DIR ( mode ) ) {
st - > st_nlink = 2 ;
} else {
st - > st_nlink = 1 ;
}
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
if ( st - > st_ino = = 0 ) {
2002-07-15 14:35:28 +04:00
st - > st_ino = smbc_inode ( context , fname ) ;
2001-11-21 06:55:59 +03:00
}
2002-07-15 14:35:28 +04:00
2001-11-21 06:55:59 +03:00
return True ; /* FIXME: Is this needed ? */
2001-02-26 14:53:22 +03:00
2000-12-26 08:57:10 +03:00
}
/*
* Routine to stat a file given a name
*/
2002-07-15 14:35:28 +04:00
static int smbc_stat_ctx ( SMBCCTX * context , const char * fname , struct stat * st )
2000-12-26 08:57:10 +03:00
{
2002-07-15 14:35:28 +04:00
SMBCSRV * srv ;
2001-11-21 06:55:59 +03:00
fstring server , share , user , password , workgroup ;
pstring path ;
time_t m_time = 0 , a_time = 0 , c_time = 0 ;
size_t size = 0 ;
uint16 mode = 0 ;
SMB_INO_T ino = 0 ;
2000-12-26 08:57:10 +03:00
2003-01-13 23:04:40 +03:00
if ( ! context | | ! context - > internal | |
! context - > internal - > _initialized ) {
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ; /* Best I can think of ... */
return - 1 ;
2002-07-15 14:35:28 +04:00
2001-11-21 06:55:59 +03:00
}
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
if ( ! fname ) {
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ;
return - 1 ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
}
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
DEBUG ( 4 , ( " smbc_stat(%s) \n " , fname ) ) ;
2000-12-26 08:57:10 +03:00
2002-07-15 14:35:28 +04:00
smbc_parse_path ( context , fname , server , share , path , user , password ) ; /*FIXME, errors*/
2001-01-12 08:10:45 +03:00
2003-03-22 12:27:42 +03:00
if ( user [ 0 ] = = ( char ) 0 ) fstrcpy ( user , context - > user ) ;
2000-12-26 08:57:10 +03:00
2003-03-22 12:27:42 +03:00
fstrcpy ( workgroup , context - > workgroup ) ;
2001-11-17 10:30:19 +03:00
2002-07-15 14:35:28 +04:00
srv = smbc_server ( context , server , share , workgroup , user , password ) ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
if ( ! srv ) {
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
return - 1 ; /* errno set by smbc_server */
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
}
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
/* if (strncmp(srv->cli.dev, "IPC", 3) == 0) {
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
mode = aDIR | aRONLY ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
}
else if ( strncmp ( srv - > cli . dev , " LPT " , 3 ) = = 0 ) {
2002-07-15 14:35:28 +04:00
2001-11-21 06:55:59 +03:00
if ( strcmp ( path , " \\ " ) = = 0 ) {
2002-07-15 14:35:28 +04:00
2001-11-21 06:55:59 +03:00
mode = aDIR | aRONLY ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
}
else {
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
mode = aRONLY ;
smbc_stat_printjob ( srv , path , & size , & m_time ) ;
c_time = a_time = m_time ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
}
else { */
2000-12-26 08:57:10 +03:00
2002-07-15 14:35:28 +04:00
if ( ! smbc_getatr ( context , srv , path , & mode , & size ,
2001-11-21 06:55:59 +03:00
& c_time , & a_time , & m_time , & ino ) ) {
2000-12-26 08:57:10 +03:00
2002-07-15 14:35:28 +04:00
errno = smbc_errno ( context , & srv - > cli ) ;
2001-11-21 06:55:59 +03:00
return - 1 ;
2002-07-15 14:35:28 +04:00
2001-11-21 06:55:59 +03:00
}
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
st - > st_ino = ino ;
2000-12-26 08:57:10 +03:00
2002-07-15 14:35:28 +04:00
smbc_setup_stat ( context , st , path , size , mode ) ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
st - > st_atime = a_time ;
st - > st_ctime = c_time ;
st - > st_mtime = m_time ;
st - > st_dev = srv - > dev ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
return 0 ;
2000-12-26 08:57:10 +03:00
}
/*
* Routine to stat a file given an fd
*/
2002-07-15 14:35:28 +04:00
static int smbc_fstat_ctx ( SMBCCTX * context , SMBCFILE * file , struct stat * st )
2000-12-26 08:57:10 +03:00
{
2001-11-21 06:55:59 +03:00
time_t c_time , a_time , m_time ;
size_t size ;
uint16 mode ;
SMB_INO_T ino = 0 ;
2000-12-26 08:57:10 +03:00
2003-01-13 23:04:40 +03:00
if ( ! context | | ! context - > internal | |
! context - > internal - > _initialized ) {
2001-01-07 10:10:50 +03:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ;
return - 1 ;
2001-01-07 10:10:50 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-07 10:10:50 +03:00
2003-01-13 23:04:40 +03:00
if ( ! file | | ! DLIST_CONTAINS ( context - > internal - > _files , file ) ) {
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
errno = EBADF ;
return - 1 ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
}
2000-12-26 08:57:10 +03:00
2002-07-15 14:35:28 +04:00
if ( ! file - > file ) {
2000-12-26 08:57:10 +03:00
2002-07-15 14:35:28 +04:00
return context - > fstatdir ( context , file , st ) ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
}
2000-12-26 08:57:10 +03:00
2002-07-15 14:35:28 +04:00
if ( ! cli_qfileinfo ( & file - > srv - > cli , file - > cli_fd ,
2003-04-16 18:45:11 +04:00
& mode , & size , & c_time , & a_time , & m_time , NULL , & ino ) ) {
SMB_BIG_UINT b_size = size ;
if ( ! cli_getattrE ( & file - > srv - > cli , file - > cli_fd ,
& mode , & b_size , & c_time , & a_time , & m_time ) ) {
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ;
return - 1 ;
2003-04-16 18:45:11 +04:00
} else
size = b_size ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
}
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
st - > st_ino = ino ;
2000-12-26 08:57:10 +03:00
2002-07-15 14:35:28 +04:00
smbc_setup_stat ( context , st , file - > fname , size , mode ) ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
st - > st_atime = a_time ;
st - > st_ctime = c_time ;
st - > st_mtime = m_time ;
2002-07-15 14:35:28 +04:00
st - > st_dev = file - > srv - > dev ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
return 0 ;
2000-12-26 08:57:10 +03:00
}
/*
* Routine to open a directory
2001-01-05 16:43:19 +03:00
*
* We want to allow :
*
* smb : which should list all the workgroups available
* smb : workgroup
* smb : workgroup //server
* smb : //server
* smb : //server/share
2001-11-21 06:55:59 +03:00
* smb : //<IP-addr> which should list shares on server
* smb : //<IP-addr>/share which should list files on share
2000-12-26 08:57:10 +03:00
*/
2002-07-15 14:35:28 +04:00
static void smbc_remove_dir ( SMBCFILE * dir )
2001-01-05 16:43:19 +03:00
{
2001-11-21 06:55:59 +03:00
struct smbc_dir_list * d , * f ;
2001-01-07 10:10:50 +03:00
2001-11-21 06:55:59 +03:00
d = dir - > dir_list ;
while ( d ) {
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
f = d ; d = d - > next ;
2001-01-07 10:10:50 +03:00
2001-11-21 06:55:59 +03:00
SAFE_FREE ( f - > dirent ) ;
SAFE_FREE ( f ) ;
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
dir - > dir_list = dir - > dir_end = dir - > dir_next = NULL ;
2001-01-05 16:43:19 +03:00
}
2002-07-15 14:35:28 +04:00
static int add_dirent ( SMBCFILE * dir , const char * name , const char * comment , uint32 type )
2000-12-26 08:57:10 +03:00
{
2001-11-21 06:55:59 +03:00
struct smbc_dirent * dirent ;
int size ;
2003-04-16 18:45:11 +04:00
char * u_name = NULL , * u_comment = NULL ;
size_t u_name_len = 0 , u_comment_len = 0 ;
if ( name )
u_name_len = push_utf8_allocate ( & u_name , name ) ;
if ( comment )
u_comment_len = push_utf8_allocate ( & u_comment , comment ) ;
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
/*
* Allocate space for the dirent , which must be increased by the
* size of the name and the comment and 1 for the null on the comment .
* The null on the name is already accounted for .
*/
2001-01-05 16:43:19 +03:00
2003-04-16 18:45:11 +04:00
size = sizeof ( struct smbc_dirent ) + u_name_len + u_comment_len + 1 ;
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
dirent = malloc ( size ) ;
2001-01-07 10:10:50 +03:00
2001-11-21 06:55:59 +03:00
if ( ! dirent ) {
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
dir - > dir_error = ENOMEM ;
return - 1 ;
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-05 16:43:19 +03:00
2002-07-15 14:35:28 +04:00
ZERO_STRUCTP ( dirent ) ;
2001-11-21 06:55:59 +03:00
if ( dir - > dir_list = = NULL ) {
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
dir - > dir_list = malloc ( sizeof ( struct smbc_dir_list ) ) ;
if ( ! dir - > dir_list ) {
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
SAFE_FREE ( dirent ) ;
dir - > dir_error = ENOMEM ;
return - 1 ;
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
}
2002-07-15 14:35:28 +04:00
ZERO_STRUCTP ( dir - > dir_list ) ;
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
dir - > dir_end = dir - > dir_next = dir - > dir_list ;
2001-01-07 16:07:26 +03:00
2001-11-21 06:55:59 +03:00
}
else {
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
dir - > dir_end - > next = malloc ( sizeof ( struct smbc_dir_list ) ) ;
2002-07-15 14:35:28 +04:00
if ( ! dir - > dir_end - > next ) {
2001-11-21 06:55:59 +03:00
SAFE_FREE ( dirent ) ;
dir - > dir_error = ENOMEM ;
return - 1 ;
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
}
2002-07-15 14:35:28 +04:00
ZERO_STRUCTP ( dir - > dir_end - > next ) ;
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
dir - > dir_end = dir - > dir_end - > next ;
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
dir - > dir_end - > next = NULL ;
dir - > dir_end - > dirent = dirent ;
2002-07-15 14:35:28 +04:00
2001-11-21 06:55:59 +03:00
dirent - > smbc_type = type ;
2003-04-16 18:45:11 +04:00
dirent - > namelen = u_name_len ;
dirent - > commentlen = u_comment_len ;
2001-11-21 06:55:59 +03:00
dirent - > dirlen = size ;
2001-01-07 10:10:50 +03:00
2003-04-16 18:45:11 +04:00
strncpy ( dirent - > name , ( u_name ? u_name : " " ) , dirent - > namelen + 1 ) ;
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
dirent - > comment = ( char * ) ( & dirent - > name + dirent - > namelen + 1 ) ;
2003-04-16 18:45:11 +04:00
strncpy ( dirent - > comment , ( u_comment ? u_comment : " " ) , dirent - > commentlen + 1 ) ;
SAFE_FREE ( u_comment ) ;
SAFE_FREE ( u_name ) ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
return 0 ;
2000-12-26 08:57:10 +03:00
}
2001-01-05 16:43:19 +03:00
static void
list_fn ( const char * name , uint32 type , const char * comment , void * state )
{
2002-07-15 14:35:28 +04:00
SMBCFILE * dir = ( SMBCFILE * ) state ;
2001-11-21 06:55:59 +03:00
int dirent_type ;
2001-01-07 10:10:50 +03:00
2001-11-21 06:55:59 +03:00
/* We need to process the type a little ... */
2001-01-07 10:10:50 +03:00
2001-11-21 06:55:59 +03:00
if ( dir - > dir_type = = SMBC_FILE_SHARE ) {
2002-07-15 14:35:28 +04:00
2001-11-21 06:55:59 +03:00
switch ( type ) {
case 0 : /* Directory tree */
dirent_type = SMBC_FILE_SHARE ;
break ;
2001-01-07 10:10:50 +03:00
2001-11-21 06:55:59 +03:00
case 1 :
dirent_type = SMBC_PRINTER_SHARE ;
break ;
2001-01-07 10:10:50 +03:00
2001-11-21 06:55:59 +03:00
case 2 :
dirent_type = SMBC_COMMS_SHARE ;
break ;
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
case 3 :
dirent_type = SMBC_IPC_SHARE ;
break ;
2001-01-07 10:10:50 +03:00
2001-11-21 06:55:59 +03:00
default :
dirent_type = SMBC_FILE_SHARE ; /* FIXME, error? */
break ;
}
}
else dirent_type = dir - > dir_type ;
2001-01-07 10:10:50 +03:00
2001-11-21 06:55:59 +03:00
if ( add_dirent ( dir , name , comment , dirent_type ) < 0 ) {
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
/* An error occurred, what do we do? */
/* FIXME: Add some code here */
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-05 16:43:19 +03:00
}
2001-01-06 17:48:55 +03:00
static void
dir_list_fn ( file_info * finfo , const char * mask , void * state )
{
2002-07-15 14:35:28 +04:00
if ( add_dirent ( ( SMBCFILE * ) state , finfo - > name , " " ,
2001-11-21 06:55:59 +03:00
( finfo - > mode & aDIR ? SMBC_DIR : SMBC_FILE ) ) < 0 ) {
2001-01-06 17:48:55 +03:00
2001-11-21 06:55:59 +03:00
/* Handle an error ... */
2002-07-15 14:35:28 +04:00
2001-11-21 06:55:59 +03:00
/* FIXME: Add some code ... */
2001-01-06 17:48:55 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-06 17:48:55 +03:00
}
2002-07-15 14:35:28 +04:00
static SMBCFILE * smbc_opendir_ctx ( SMBCCTX * context , const char * fname )
2001-01-05 16:43:19 +03:00
{
2003-04-16 18:45:11 +04:00
fstring server , share , user , password ;
pstring workgroup ;
2001-11-21 06:55:59 +03:00
pstring path ;
2002-07-15 14:35:28 +04:00
SMBCSRV * srv = NULL ;
SMBCFILE * dir = NULL ;
2001-11-21 06:55:59 +03:00
struct in_addr rem_ip ;
2001-01-05 16:43:19 +03:00
2003-01-13 23:04:40 +03:00
if ( ! context | | ! context - > internal | |
! context - > internal - > _initialized ) {
2003-04-16 18:45:11 +04:00
DEBUG ( 4 , ( " no valid context \n " ) ) ;
2001-11-21 06:55:59 +03:00
errno = EINVAL ;
2002-07-15 14:35:28 +04:00
return NULL ;
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
if ( ! fname ) {
2003-04-16 18:45:11 +04:00
DEBUG ( 4 , ( " no valid fname \n " ) ) ;
2001-11-21 06:55:59 +03:00
errno = EINVAL ;
2002-07-15 14:35:28 +04:00
return NULL ;
2001-11-21 06:55:59 +03:00
}
2001-01-05 16:43:19 +03:00
2002-07-15 14:35:28 +04:00
if ( smbc_parse_path ( context , fname , server , share , path , user , password ) ) {
2003-04-16 18:45:11 +04:00
DEBUG ( 4 , ( " no valid path \n " ) ) ;
2001-11-21 06:55:59 +03:00
errno = EINVAL ;
2002-07-15 14:35:28 +04:00
return NULL ;
2001-11-21 06:55:59 +03:00
}
2001-01-05 16:43:19 +03:00
2003-04-16 18:45:11 +04:00
DEBUG ( 4 , ( " parsed path: fname='%s' server='%s' share='%s' path='%s' \n " , fname , server , share , path ) ) ;
2003-03-22 12:27:42 +03:00
if ( user [ 0 ] = = ( char ) 0 ) fstrcpy ( user , context - > user ) ;
2001-01-05 16:43:19 +03:00
2003-04-16 18:45:11 +04:00
pstrcpy ( workgroup , context - > workgroup ) ;
2001-01-05 16:43:19 +03:00
2002-07-15 14:35:28 +04:00
dir = malloc ( sizeof ( * dir ) ) ;
2001-01-05 16:43:19 +03:00
2002-07-15 14:35:28 +04:00
if ( ! dir ) {
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
errno = ENOMEM ;
2002-07-15 14:35:28 +04:00
return NULL ;
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-05 16:43:19 +03:00
2002-07-15 14:35:28 +04:00
ZERO_STRUCTP ( dir ) ;
dir - > cli_fd = 0 ;
dir - > fname = strdup ( fname ) ;
dir - > srv = NULL ;
dir - > offset = 0 ;
dir - > file = False ;
dir - > dir_list = dir - > dir_next = dir - > dir_end = NULL ;
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
if ( server [ 0 ] = = ( char ) 0 ) {
2003-04-16 18:45:11 +04:00
struct in_addr server_ip ;
2001-11-21 06:55:59 +03:00
if ( share [ 0 ] ! = ( char ) 0 | | path [ 0 ] ! = ( char ) 0 ) {
2003-04-16 18:45:11 +04:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ;
2002-07-15 14:35:28 +04:00
if ( dir ) {
SAFE_FREE ( dir - > fname ) ;
SAFE_FREE ( dir ) ;
2001-11-21 06:55:59 +03:00
}
2002-07-15 14:35:28 +04:00
return NULL ;
2001-11-21 06:55:59 +03:00
}
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
/* We have server and share and path empty ... so list the workgroups */
2002-07-15 14:35:28 +04:00
/* first try to get the LMB for our workgroup, and if that fails, */
/* try the DMB */
2001-02-19 08:50:09 +03:00
2003-04-16 18:45:11 +04:00
pstrcpy ( workgroup , lp_workgroup ( ) ) ;
2001-01-05 16:43:19 +03:00
2003-04-16 18:45:11 +04:00
if ( ! find_master_ip ( workgroup , & server_ip ) ) {
struct user_auth_info u_info ;
struct cli_state * cli ;
2001-01-05 16:43:19 +03:00
2003-04-16 18:45:11 +04:00
DEBUG ( 4 , ( " Unable to find master browser for workgroup %s \n " ,
workgroup ) ) ;
2001-02-19 08:50:09 +03:00
2003-04-16 18:45:11 +04:00
/* find the name of the server ... */
pstrcpy ( u_info . username , user ) ;
pstrcpy ( u_info . password , password ) ;
2001-02-26 14:53:22 +03:00
2003-04-16 18:45:11 +04:00
if ( ! ( cli = get_ipc_connect_master_ip_bcast ( workgroup , & u_info ) ) ) {
DEBUG ( 4 , ( " Unable to find master browser by "
" broadcast \n " ) ) ;
errno = ENOENT ;
2002-07-15 14:35:28 +04:00
return NULL ;
2003-04-16 18:45:11 +04:00
}
2001-02-26 14:53:22 +03:00
2003-04-16 18:45:11 +04:00
fstrcpy ( server , cli - > desthost ) ;
2001-01-05 16:43:19 +03:00
2003-04-16 18:45:11 +04:00
cli_shutdown ( cli ) ;
} else {
if ( ! name_status_find ( " * " , 0 , 0 , server_ip , server ) ) {
errno = ENOENT ;
return NULL ;
}
}
2001-01-05 16:43:19 +03:00
2003-04-16 18:45:11 +04:00
DEBUG ( 4 , ( " using workgroup %s %s \n " , workgroup , server ) ) ;
2001-01-05 16:43:19 +03:00
2003-04-16 18:45:11 +04:00
/*
* Get a connection to IPC $ on the server if we do not already have one
*/
2001-01-05 16:43:19 +03:00
2003-04-16 18:45:11 +04:00
srv = smbc_server ( context , server , " IPC$ " , workgroup , user , password ) ;
2001-01-05 16:43:19 +03:00
2003-04-16 18:45:11 +04:00
if ( ! srv ) {
if ( dir ) {
SAFE_FREE ( dir - > fname ) ;
SAFE_FREE ( dir ) ;
}
return NULL ;
}
2002-07-15 14:35:28 +04:00
dir - > srv = srv ;
2003-04-16 18:45:11 +04:00
dir - > dir_type = SMBC_WORKGROUP ;
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
/* Now, list the stuff ... */
2001-01-05 16:43:19 +03:00
2003-04-16 18:45:11 +04:00
if ( ! cli_NetServerEnum ( & srv - > cli , workgroup , SV_TYPE_DOMAIN_ENUM , list_fn ,
2002-07-15 14:35:28 +04:00
( void * ) dir ) ) {
2001-01-05 16:43:19 +03:00
2002-07-15 14:35:28 +04:00
if ( dir ) {
SAFE_FREE ( dir - > fname ) ;
SAFE_FREE ( dir ) ;
2001-11-21 06:55:59 +03:00
}
errno = cli_errno ( & srv - > cli ) ;
2002-07-15 14:35:28 +04:00
return NULL ;
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
}
}
else { /* Server not an empty string ... Check the rest and see what gives */
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
if ( share [ 0 ] = = ( char ) 0 ) {
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
if ( path [ 0 ] ! = ( char ) 0 ) { /* Should not have empty share with path */
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ;
2002-07-15 14:35:28 +04:00
if ( dir ) {
SAFE_FREE ( dir - > fname ) ;
SAFE_FREE ( dir ) ;
2001-11-21 06:55:59 +03:00
}
2002-07-15 14:35:28 +04:00
return NULL ;
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-05 16:43:19 +03:00
2002-07-15 14:35:28 +04:00
/* Check to see if <server><1D>, <server><1B>, or <server><20> translates */
2001-11-21 06:55:59 +03:00
/* However, we check to see if <server> is an IP address first */
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
if ( ! is_ipaddress ( server ) & & /* Not an IP addr so check next */
2002-07-15 14:35:28 +04:00
( resolve_name ( server , & rem_ip , 0x1d ) | | /* Found LMB */
resolve_name ( server , & rem_ip , 0x1b ) ) ) { /* Found DMB */
2001-11-21 06:55:59 +03:00
pstring buserver ;
2001-01-05 16:43:19 +03:00
2002-07-15 14:35:28 +04:00
dir - > dir_type = SMBC_SERVER ;
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
/*
* Get the backup list . . .
*/
2001-01-05 16:43:19 +03:00
2001-02-19 08:50:09 +03:00
2001-11-22 02:00:59 +03:00
if ( ! name_status_find ( " * " , 0 , 0 , rem_ip , buserver ) ) {
2001-02-26 14:53:22 +03:00
2002-07-15 14:35:28 +04:00
DEBUG ( 0 , ( " Could not get name of local/domain master browser for server %s \n " , server ) ) ;
2001-11-21 06:55:59 +03:00
errno = EPERM ; /* FIXME, is this correct */
2002-07-15 14:35:28 +04:00
return NULL ;
2001-02-26 14:53:22 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
/*
* Get a connection to IPC $ on the server if we do not already have one
*/
2001-01-05 16:43:19 +03:00
2002-07-15 14:35:28 +04:00
srv = smbc_server ( context , buserver , " IPC$ " , workgroup , user , password ) ;
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
if ( ! srv ) {
2003-04-16 18:45:11 +04:00
DEBUG ( 0 , ( " got no contact to IPC$ \n " ) ) ;
2002-07-15 14:35:28 +04:00
if ( dir ) {
SAFE_FREE ( dir - > fname ) ;
SAFE_FREE ( dir ) ;
2001-11-21 06:55:59 +03:00
}
2002-07-15 14:35:28 +04:00
return NULL ;
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-05 16:43:19 +03:00
2002-07-15 14:35:28 +04:00
dir - > srv = srv ;
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
/* Now, list the servers ... */
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
if ( ! cli_NetServerEnum ( & srv - > cli , server , 0x0000FFFE , list_fn ,
2002-07-15 14:35:28 +04:00
( void * ) dir ) ) {
2001-01-05 16:43:19 +03:00
2002-07-15 14:35:28 +04:00
if ( dir ) {
SAFE_FREE ( dir - > fname ) ;
SAFE_FREE ( dir ) ;
2001-11-21 06:55:59 +03:00
}
errno = cli_errno ( & srv - > cli ) ;
2002-07-15 14:35:28 +04:00
return NULL ;
2001-11-21 06:55:59 +03:00
}
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
}
else {
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
if ( resolve_name ( server , & rem_ip , 0x20 ) ) {
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
/* Now, list the shares ... */
2001-01-05 16:43:19 +03:00
2002-07-15 14:35:28 +04:00
dir - > dir_type = SMBC_FILE_SHARE ;
2001-01-05 16:43:19 +03:00
2002-07-15 14:35:28 +04:00
srv = smbc_server ( context , server , " IPC$ " , workgroup , user , password ) ;
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
if ( ! srv ) {
2001-01-05 16:43:19 +03:00
2002-07-15 14:35:28 +04:00
if ( dir ) {
SAFE_FREE ( dir - > fname ) ;
SAFE_FREE ( dir ) ;
2001-11-21 06:55:59 +03:00
}
2002-07-15 14:35:28 +04:00
return NULL ;
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-05 16:43:19 +03:00
2002-07-15 14:35:28 +04:00
dir - > srv = srv ;
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
/* Now, list the servers ... */
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
if ( cli_RNetShareEnum ( & srv - > cli , list_fn ,
2002-07-15 14:35:28 +04:00
( void * ) dir ) < 0 ) {
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
errno = cli_errno ( & srv - > cli ) ;
2002-07-15 14:35:28 +04:00
if ( dir ) {
SAFE_FREE ( dir - > fname ) ;
SAFE_FREE ( dir ) ;
2001-11-21 06:55:59 +03:00
}
2002-07-15 14:35:28 +04:00
return NULL ;
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
}
else {
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
errno = ENODEV ; /* Neither the workgroup nor server exists */
2002-07-15 14:35:28 +04:00
if ( dir ) {
SAFE_FREE ( dir - > fname ) ;
SAFE_FREE ( dir ) ;
2001-11-21 06:55:59 +03:00
}
2002-07-15 14:35:28 +04:00
return NULL ;
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
}
else { /* The server and share are specified ... work from there ... */
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
/* Well, we connect to the server and list the directory */
2001-01-06 17:48:55 +03:00
2002-07-15 14:35:28 +04:00
dir - > dir_type = SMBC_FILE_SHARE ;
2001-01-06 17:48:55 +03:00
2002-07-15 14:35:28 +04:00
srv = smbc_server ( context , server , share , workgroup , user , password ) ;
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
if ( ! srv ) {
2001-01-05 16:43:19 +03:00
2002-07-15 14:35:28 +04:00
if ( dir ) {
SAFE_FREE ( dir - > fname ) ;
SAFE_FREE ( dir ) ;
2001-11-21 06:55:59 +03:00
}
2002-07-15 14:35:28 +04:00
return NULL ;
2001-01-06 17:48:55 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-06 17:48:55 +03:00
2002-07-15 14:35:28 +04:00
dir - > srv = srv ;
2001-01-06 17:48:55 +03:00
2001-11-21 06:55:59 +03:00
/* Now, list the files ... */
2001-01-06 17:48:55 +03:00
2001-11-21 06:55:59 +03:00
pstrcat ( path , " \\ * " ) ;
2001-01-06 17:48:55 +03:00
2001-11-21 06:55:59 +03:00
if ( cli_list ( & srv - > cli , path , aDIR | aSYSTEM | aHIDDEN , dir_list_fn ,
2002-07-15 14:35:28 +04:00
( void * ) dir ) < 0 ) {
2001-01-06 17:48:55 +03:00
2002-07-15 14:35:28 +04:00
if ( dir ) {
SAFE_FREE ( dir - > fname ) ;
SAFE_FREE ( dir ) ;
2001-11-21 06:55:59 +03:00
}
2002-07-15 14:35:28 +04:00
errno = smbc_errno ( context , & srv - > cli ) ;
return NULL ;
2001-01-06 17:48:55 +03:00
2001-11-21 06:55:59 +03:00
}
}
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-05 16:43:19 +03:00
2003-01-13 23:04:40 +03:00
DLIST_ADD ( context - > internal - > _files , dir ) ;
2002-07-15 14:35:28 +04:00
return dir ;
2001-01-05 16:43:19 +03:00
}
2000-12-26 08:57:10 +03:00
/*
* Routine to close a directory
*/
2002-07-15 14:35:28 +04:00
static int smbc_closedir_ctx ( SMBCCTX * context , SMBCFILE * dir )
2000-12-26 08:57:10 +03:00
{
2001-01-07 10:10:50 +03:00
2003-01-13 23:04:40 +03:00
if ( ! context | | ! context - > internal | |
! context - > internal - > _initialized ) {
2001-01-07 10:10:50 +03:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ;
return - 1 ;
2001-01-07 10:10:50 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-07 10:10:50 +03:00
2003-01-13 23:04:40 +03:00
if ( ! dir | | ! DLIST_CONTAINS ( context - > internal - > _files , dir ) ) {
2001-01-07 10:10:50 +03:00
2001-11-21 06:55:59 +03:00
errno = EBADF ;
return - 1 ;
2002-07-15 14:35:28 +04:00
2001-11-21 06:55:59 +03:00
}
2001-01-07 10:10:50 +03:00
2002-07-15 14:35:28 +04:00
smbc_remove_dir ( dir ) ; /* Clean it up */
2001-01-07 10:10:50 +03:00
2003-01-13 23:04:40 +03:00
DLIST_REMOVE ( context - > internal - > _files , dir ) ;
2001-01-07 10:10:50 +03:00
2002-07-15 14:35:28 +04:00
if ( dir ) {
2001-03-27 16:13:59 +04:00
2002-07-15 14:35:28 +04:00
SAFE_FREE ( dir - > fname ) ;
SAFE_FREE ( dir ) ; /* Free the space too */
2001-03-27 16:13:59 +04:00
2001-11-21 06:55:59 +03:00
}
2001-01-07 10:10:50 +03:00
2001-11-21 06:55:59 +03:00
return 0 ;
2000-12-26 08:57:10 +03:00
}
/*
* Routine to get a directory entry
*/
2002-07-15 14:35:28 +04:00
struct smbc_dirent * smbc_readdir_ctx ( SMBCCTX * context , SMBCFILE * dir )
2001-01-12 08:10:45 +03:00
{
2001-11-21 06:55:59 +03:00
struct smbc_dirent * dirp , * dirent ;
2001-01-12 08:10:45 +03:00
2001-11-21 06:55:59 +03:00
/* Check that all is ok first ... */
2001-01-12 08:10:45 +03:00
2003-01-13 23:04:40 +03:00
if ( ! context | | ! context - > internal | |
! context - > internal - > _initialized ) {
2001-01-12 08:10:45 +03:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ;
return NULL ;
2001-01-12 08:10:45 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-12 08:10:45 +03:00
2003-01-13 23:04:40 +03:00
if ( ! dir | | ! DLIST_CONTAINS ( context - > internal - > _files , dir ) ) {
2001-03-01 22:21:57 +03:00
2001-11-21 06:55:59 +03:00
errno = EBADF ;
return NULL ;
2001-03-01 22:21:57 +03:00
2001-11-21 06:55:59 +03:00
}
2001-03-01 22:21:57 +03:00
2002-07-15 14:35:28 +04:00
if ( dir - > file ! = False ) { /* FIXME, should be dir, perhaps */
2001-01-12 08:10:45 +03:00
2001-11-21 06:55:59 +03:00
errno = ENOTDIR ;
return NULL ;
2001-01-12 08:10:45 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-12 08:10:45 +03:00
2002-07-15 14:35:28 +04:00
if ( ! dir - > dir_next )
2001-11-21 06:55:59 +03:00
return NULL ;
else {
2001-01-12 08:10:45 +03:00
2002-07-15 14:35:28 +04:00
dirent = dir - > dir_next - > dirent ;
2001-01-12 08:10:45 +03:00
2001-11-21 06:55:59 +03:00
if ( ! dirent ) {
2001-01-12 08:10:45 +03:00
2001-11-21 06:55:59 +03:00
errno = ENOENT ;
return NULL ;
2001-01-12 08:10:45 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-12 08:10:45 +03:00
2001-11-21 06:55:59 +03:00
/* Hmmm, do I even need to copy it? */
2001-01-12 08:10:45 +03:00
2003-01-13 23:04:40 +03:00
memcpy ( context - > internal - > _dirent , dirent , dirent - > dirlen ) ; /* Copy the dirent */
dirp = ( struct smbc_dirent * ) context - > internal - > _dirent ;
2001-11-21 06:55:59 +03:00
dirp - > comment = ( char * ) ( & dirp - > name + dirent - > namelen + 1 ) ;
2002-07-15 14:35:28 +04:00
dir - > dir_next = dir - > dir_next - > next ;
2001-01-12 08:10:45 +03:00
2003-01-13 23:04:40 +03:00
return ( struct smbc_dirent * ) context - > internal - > _dirent ;
2001-11-21 06:55:59 +03:00
}
2001-01-12 08:10:45 +03:00
}
/*
* Routine to get directory entries
*/
2002-07-15 14:35:28 +04:00
static int smbc_getdents_ctx ( SMBCCTX * context , SMBCFILE * dir , struct smbc_dirent * dirp , int count )
2000-12-26 08:57:10 +03:00
{
2002-07-15 14:35:28 +04:00
struct smbc_dir_list * dirlist ;
2001-11-21 06:55:59 +03:00
int rem = count , reqd ;
char * ndir = ( char * ) dirp ;
2000-12-26 08:57:10 +03:00
2001-11-21 06:55:59 +03:00
/* Check that all is ok first ... */
2001-01-05 16:43:19 +03:00
2003-01-13 23:04:40 +03:00
if ( ! context | | ! context - > internal | |
! context - > internal - > _initialized ) {
2001-01-07 10:10:50 +03:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ;
return - 1 ;
2001-01-07 10:10:50 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-07 10:10:50 +03:00
2003-01-13 23:04:40 +03:00
if ( ! dir | | ! DLIST_CONTAINS ( context - > internal - > _files , dir ) ) {
2001-03-01 22:21:57 +03:00
2001-11-21 06:55:59 +03:00
errno = EBADF ;
return - 1 ;
2002-07-15 14:35:28 +04:00
2001-11-21 06:55:59 +03:00
}
2001-03-01 22:21:57 +03:00
2002-07-15 14:35:28 +04:00
if ( dir - > file ! = False ) { /* FIXME, should be dir, perhaps */
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
errno = ENOTDIR ;
return - 1 ;
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
/*
* Now , retrieve the number of entries that will fit in what was passed
* We have to figure out if the info is in the list , or we need to
* send a request to the server to get the info .
*/
2001-01-05 16:43:19 +03:00
2002-07-15 14:35:28 +04:00
while ( ( dirlist = dir - > dir_next ) ) {
2001-11-21 06:55:59 +03:00
struct smbc_dirent * dirent ;
2001-01-05 16:43:19 +03:00
2002-07-15 14:35:28 +04:00
if ( ! dirlist - > dirent ) {
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
errno = ENOENT ; /* Bad error */
return - 1 ;
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-05 16:43:19 +03:00
2002-07-15 14:35:28 +04:00
if ( rem < ( reqd = ( sizeof ( struct smbc_dirent ) + dirlist - > dirent - > namelen +
dirlist - > dirent - > commentlen + 1 ) ) ) {
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
if ( rem < count ) { /* We managed to copy something */
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
errno = 0 ;
return count - rem ;
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
}
else { /* Nothing copied ... */
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ; /* Not enough space ... */
return - 1 ;
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-05 16:43:19 +03:00
2002-07-15 14:35:28 +04:00
dirent = dirlist - > dirent ;
2001-01-05 16:43:19 +03:00
2002-02-26 20:40:43 +03:00
memcpy ( ndir , dirent , reqd ) ; /* Copy the data in ... */
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
( ( struct smbc_dirent * ) ndir ) - > comment =
( char * ) ( & ( ( struct smbc_dirent * ) ndir ) - > name + dirent - > namelen + 1 ) ;
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
ndir + = reqd ;
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
rem - = reqd ;
2001-01-05 16:43:19 +03:00
2002-07-15 14:35:28 +04:00
dir - > dir_next = dirlist = dirlist - > next ;
2001-11-21 06:55:59 +03:00
}
2001-01-05 16:43:19 +03:00
2001-11-21 06:55:59 +03:00
if ( rem = = count )
return 0 ;
else
return count - rem ;
2000-12-26 08:57:10 +03:00
}
/*
* Routine to create a directory . . .
*/
2002-07-15 14:35:28 +04:00
static int smbc_mkdir_ctx ( SMBCCTX * context , const char * fname , mode_t mode )
2000-12-26 08:57:10 +03:00
{
2002-07-15 14:35:28 +04:00
SMBCSRV * srv ;
2001-11-21 06:55:59 +03:00
fstring server , share , user , password , workgroup ;
pstring path ;
2000-12-26 08:57:10 +03:00
2003-01-13 23:04:40 +03:00
if ( ! context | | ! context - > internal | |
! context - > internal - > _initialized ) {
2001-01-07 10:10:50 +03:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ;
return - 1 ;
2001-01-07 10:10:50 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-07 10:10:50 +03:00
2001-11-21 06:55:59 +03:00
if ( ! fname ) {
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ;
return - 1 ;
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
DEBUG ( 4 , ( " smbc_mkdir(%s) \n " , fname ) ) ;
2001-01-12 15:48:55 +03:00
2002-07-15 14:35:28 +04:00
smbc_parse_path ( context , fname , server , share , path , user , password ) ; /*FIXME, errors*/
2001-01-12 15:48:55 +03:00
2003-03-22 12:27:42 +03:00
if ( user [ 0 ] = = ( char ) 0 ) fstrcpy ( user , context - > user ) ;
2001-01-12 15:48:55 +03:00
2003-03-22 12:27:42 +03:00
fstrcpy ( workgroup , context - > workgroup ) ;
2001-11-17 10:30:19 +03:00
2002-07-15 14:35:28 +04:00
srv = smbc_server ( context , server , share , workgroup , user , password ) ;
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
if ( ! srv ) {
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
return - 1 ; /* errno set by smbc_server */
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
/* if (strncmp(srv->cli.dev, "IPC", 3) == 0) {
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
mode = aDIR | aRONLY ;
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
}
else if ( strncmp ( srv - > cli . dev , " LPT " , 3 ) = = 0 ) {
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
if ( strcmp ( path , " \\ " ) = = 0 ) {
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
mode = aDIR | aRONLY ;
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
}
else {
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
mode = aRONLY ;
smbc_stat_printjob ( srv , path , & size , & m_time ) ;
c_time = a_time = m_time ;
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
}
else { */
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
if ( ! cli_mkdir ( & srv - > cli , path ) ) {
2001-01-12 15:48:55 +03:00
2002-07-15 14:35:28 +04:00
errno = smbc_errno ( context , & srv - > cli ) ;
2001-11-21 06:55:59 +03:00
return - 1 ;
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
return 0 ;
2001-01-12 15:48:55 +03:00
}
2001-03-27 16:13:59 +04:00
/*
* Our list function simply checks to see if a directory is not empty
*/
static int smbc_rmdir_dirempty = True ;
static void rmdir_list_fn ( file_info * finfo , const char * mask , void * state )
{
2001-11-21 06:55:59 +03:00
if ( strncmp ( finfo - > name , " . " , 1 ) ! = 0 & & strncmp ( finfo - > name , " .. " , 2 ) ! = 0 )
smbc_rmdir_dirempty = False ;
2001-03-27 16:13:59 +04:00
}
2001-01-12 15:48:55 +03:00
/*
* Routine to remove a directory
*/
2002-07-15 14:35:28 +04:00
static int smbc_rmdir_ctx ( SMBCCTX * context , const char * fname )
2001-01-12 15:48:55 +03:00
{
2002-07-15 14:35:28 +04:00
SMBCSRV * srv ;
2001-11-21 06:55:59 +03:00
fstring server , share , user , password , workgroup ;
pstring path ;
2001-01-12 15:48:55 +03:00
2003-01-13 23:04:40 +03:00
if ( ! context | | ! context - > internal | |
! context - > internal - > _initialized ) {
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ;
return - 1 ;
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
if ( ! fname ) {
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ;
return - 1 ;
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
DEBUG ( 4 , ( " smbc_rmdir(%s) \n " , fname ) ) ;
2001-01-12 15:48:55 +03:00
2002-07-15 14:35:28 +04:00
smbc_parse_path ( context , fname , server , share , path , user , password ) ; /*FIXME, errors*/
2001-01-12 15:48:55 +03:00
2003-03-22 12:27:42 +03:00
if ( user [ 0 ] = = ( char ) 0 ) fstrcpy ( user , context - > user ) ;
2001-01-12 15:48:55 +03:00
2003-03-22 12:27:42 +03:00
fstrcpy ( workgroup , context - > workgroup ) ;
2001-11-17 10:30:19 +03:00
2002-07-15 14:35:28 +04:00
srv = smbc_server ( context , server , share , workgroup , user , password ) ;
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
if ( ! srv ) {
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
return - 1 ; /* errno set by smbc_server */
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
/* if (strncmp(srv->cli.dev, "IPC", 3) == 0) {
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
mode = aDIR | aRONLY ;
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
}
else if ( strncmp ( srv - > cli . dev , " LPT " , 3 ) = = 0 ) {
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
if ( strcmp ( path , " \\ " ) = = 0 ) {
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
mode = aDIR | aRONLY ;
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
}
else {
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
mode = aRONLY ;
smbc_stat_printjob ( srv , path , & size , & m_time ) ;
c_time = a_time = m_time ;
2002-07-15 14:35:28 +04:00
2001-11-21 06:55:59 +03:00
}
else { */
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
if ( ! cli_rmdir ( & srv - > cli , path ) ) {
2001-01-12 15:48:55 +03:00
2002-07-15 14:35:28 +04:00
errno = smbc_errno ( context , & srv - > cli ) ;
2001-03-27 16:13:59 +04:00
2001-11-21 06:55:59 +03:00
if ( errno = = EACCES ) { /* Check if the dir empty or not */
2001-03-27 16:13:59 +04:00
2001-11-21 06:55:59 +03:00
pstring lpath ; /* Local storage to avoid buffer overflows */
2001-03-27 16:13:59 +04:00
2001-11-21 06:55:59 +03:00
smbc_rmdir_dirempty = True ; /* Make this so ... */
2001-03-27 16:13:59 +04:00
2001-11-21 06:55:59 +03:00
pstrcpy ( lpath , path ) ;
pstrcat ( lpath , " \\ * " ) ;
2001-03-27 16:13:59 +04:00
2001-11-21 06:55:59 +03:00
if ( cli_list ( & srv - > cli , lpath , aDIR | aSYSTEM | aHIDDEN , rmdir_list_fn ,
NULL ) < 0 ) {
2001-03-27 16:13:59 +04:00
2001-11-21 06:55:59 +03:00
/* Fix errno to ignore latest error ... */
2001-03-27 16:13:59 +04:00
2001-11-21 06:55:59 +03:00
DEBUG ( 5 , ( " smbc_rmdir: cli_list returned an error: %d \n " ,
2002-07-15 14:35:28 +04:00
smbc_errno ( context , & srv - > cli ) ) ) ;
2001-11-21 06:55:59 +03:00
errno = EACCES ;
2001-03-27 16:13:59 +04:00
2001-11-21 06:55:59 +03:00
}
2001-03-27 16:13:59 +04:00
2001-11-21 06:55:59 +03:00
if ( smbc_rmdir_dirempty )
errno = EACCES ;
else
errno = ENOTEMPTY ;
2001-03-27 16:13:59 +04:00
2001-11-21 06:55:59 +03:00
}
2001-03-27 16:13:59 +04:00
2001-11-21 06:55:59 +03:00
return - 1 ;
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
return 0 ;
2001-01-07 10:10:50 +03:00
2000-12-26 08:57:10 +03:00
}
2001-01-12 15:48:55 +03:00
/*
* Routine to return the current directory position
*/
2002-07-15 14:35:28 +04:00
static off_t smbc_telldir_ctx ( SMBCCTX * context , SMBCFILE * dir )
2001-01-12 15:48:55 +03:00
{
2003-04-16 18:45:11 +04:00
off_t ret_val ; /* Squash warnings about cast */
2001-01-12 15:48:55 +03:00
2003-01-13 23:04:40 +03:00
if ( ! context | | ! context - > internal | |
! context - > internal - > _initialized ) {
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ;
return - 1 ;
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-12 15:48:55 +03:00
2003-01-13 23:04:40 +03:00
if ( ! dir | | ! DLIST_CONTAINS ( context - > internal - > _files , dir ) ) {
2001-03-01 22:21:57 +03:00
2001-11-21 06:55:59 +03:00
errno = EBADF ;
return - 1 ;
2001-03-01 22:21:57 +03:00
2001-11-21 06:55:59 +03:00
}
2001-03-01 22:21:57 +03:00
2002-07-15 14:35:28 +04:00
if ( dir - > file ! = False ) { /* FIXME, should be dir, perhaps */
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
errno = ENOTDIR ;
return - 1 ;
2001-01-12 15:48:55 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-12 15:48:55 +03:00
2003-04-16 18:45:11 +04:00
/*
* We return the pointer here as the offset
*/
ret_val = ( int ) dir - > dir_next ;
return ret_val ;
2001-01-12 15:48:55 +03:00
}
2001-03-06 17:00:48 +03:00
/*
* A routine to run down the list and see if the entry is OK
*/
struct smbc_dir_list * smbc_check_dir_ent ( struct smbc_dir_list * list ,
struct smbc_dirent * dirent )
{
2001-11-21 06:55:59 +03:00
/* Run down the list looking for what we want */
2001-03-06 17:00:48 +03:00
2001-11-21 06:55:59 +03:00
if ( dirent ) {
2001-03-06 17:00:48 +03:00
2001-11-21 06:55:59 +03:00
struct smbc_dir_list * tmp = list ;
2001-03-06 17:00:48 +03:00
2001-11-21 06:55:59 +03:00
while ( tmp ) {
2001-03-06 17:00:48 +03:00
2001-11-21 06:55:59 +03:00
if ( tmp - > dirent = = dirent )
return tmp ;
2001-03-06 17:00:48 +03:00
2001-11-21 06:55:59 +03:00
tmp = tmp - > next ;
2001-03-06 17:00:48 +03:00
2001-11-21 06:55:59 +03:00
}
2001-03-06 17:00:48 +03:00
2001-11-21 06:55:59 +03:00
}
2001-03-06 17:00:48 +03:00
2001-11-21 06:55:59 +03:00
return NULL ; /* Not found, or an error */
2001-03-06 17:00:48 +03:00
}
2000-12-26 08:57:10 +03:00
/*
* Routine to seek on a directory
*/
2002-07-15 14:35:28 +04:00
static int smbc_lseekdir_ctx ( SMBCCTX * context , SMBCFILE * dir , off_t offset )
2000-12-26 08:57:10 +03:00
{
2003-04-16 18:45:11 +04:00
long int l_offset = offset ; /* Handle problems of size */
struct smbc_dirent * dirent = ( struct smbc_dirent * ) l_offset ;
struct smbc_dir_list * list_ent = ( struct smbc_dir_list * ) NULL ;
2000-12-26 08:57:10 +03:00
2003-01-13 23:04:40 +03:00
if ( ! context | | ! context - > internal | |
! context - > internal - > _initialized ) {
2001-01-07 10:10:50 +03:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ;
return - 1 ;
2001-01-07 10:10:50 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-07 10:10:50 +03:00
2002-07-15 14:35:28 +04:00
if ( dir - > file ! = False ) { /* FIXME, should be dir, perhaps */
2001-03-05 16:34:48 +03:00
2001-11-21 06:55:59 +03:00
errno = ENOTDIR ;
return - 1 ;
2001-03-05 16:34:48 +03:00
2001-11-21 06:55:59 +03:00
}
2001-03-05 16:34:48 +03:00
2001-11-21 06:55:59 +03:00
/* Now, check what we were passed and see if it is OK ... */
2001-03-05 16:34:48 +03:00
2001-11-21 06:55:59 +03:00
if ( dirent = = NULL ) { /* Seek to the begining of the list */
2001-03-06 17:00:48 +03:00
2002-07-15 14:35:28 +04:00
dir - > dir_next = dir - > dir_list ;
2001-11-21 06:55:59 +03:00
return 0 ;
2001-03-06 17:00:48 +03:00
2001-11-21 06:55:59 +03:00
}
2001-03-06 17:00:48 +03:00
2001-11-21 06:55:59 +03:00
/* Now, run down the list and make sure that the entry is OK */
/* This may need to be changed if we change the format of the list */
2001-03-06 17:00:48 +03:00
2002-07-15 14:35:28 +04:00
if ( ( list_ent = smbc_check_dir_ent ( dir - > dir_list , dirent ) ) = = NULL ) {
2001-03-06 17:00:48 +03:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ; /* Bad entry */
return - 1 ;
2001-03-06 17:00:48 +03:00
2001-11-21 06:55:59 +03:00
}
2001-03-06 17:00:48 +03:00
2002-07-15 14:35:28 +04:00
dir - > dir_next = list_ent ;
2001-03-06 17:00:48 +03:00
2001-11-21 06:55:59 +03:00
return 0 ;
2000-12-26 08:57:10 +03:00
}
/*
* Routine to fstat a dir
*/
2002-07-15 14:35:28 +04:00
static int smbc_fstatdir_ctx ( SMBCCTX * context , SMBCFILE * dir , struct stat * st )
2000-12-26 08:57:10 +03:00
{
2003-01-13 23:04:40 +03:00
if ( ! context | | ! context - > internal | |
! context - > internal - > _initialized ) {
2001-01-07 10:10:50 +03:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ;
return - 1 ;
2001-01-07 10:10:50 +03:00
2001-11-21 06:55:59 +03:00
}
2001-01-07 10:10:50 +03:00
2001-11-21 06:55:59 +03:00
/* No code yet ... */
2001-02-26 14:53:22 +03:00
2001-11-21 06:55:59 +03:00
return 0 ;
2000-12-26 08:57:10 +03:00
2001-02-05 16:02:20 +03:00
}
2002-07-15 14:35:28 +04:00
/*
* Open a print file to be written to by other calls
*/
static SMBCFILE * smbc_open_print_job_ctx ( SMBCCTX * context , const char * fname )
{
fstring server , share , user , password ;
pstring path ;
2003-01-13 23:04:40 +03:00
if ( ! context | | ! context - > internal | |
! context - > internal - > _initialized ) {
2002-07-15 14:35:28 +04:00
errno = EINVAL ;
return NULL ;
}
if ( ! fname ) {
errno = EINVAL ;
return NULL ;
}
DEBUG ( 4 , ( " smbc_open_print_job_ctx(%s) \n " , fname ) ) ;
smbc_parse_path ( context , fname , server , share , path , user , password ) ; /*FIXME, errors*/
/* What if the path is empty, or the file exists? */
return context - > open ( context , fname , O_WRONLY , 666 ) ;
}
2001-02-05 16:02:20 +03:00
/*
* Routine to print a file on a remote server . . .
*
* We open the file , which we assume to be on a remote server , and then
* copy it to a print file on the share specified by printq .
*/
2002-07-15 14:35:28 +04:00
static int smbc_print_file_ctx ( SMBCCTX * c_file , const char * fname , SMBCCTX * c_print , const char * printq )
2001-02-05 16:02:20 +03:00
{
2002-07-15 14:35:28 +04:00
SMBCFILE * fid1 , * fid2 ;
int bytes , saverr , tot_bytes = 0 ;
2001-11-21 06:55:59 +03:00
char buf [ 4096 ] ;
2001-02-05 16:02:20 +03:00
2003-01-13 23:04:40 +03:00
if ( ! c_file | | ! c_file - > internal - > _initialized | | ! c_print | |
! c_print - > internal - > _initialized ) {
2001-02-06 22:25:12 +03:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ;
return - 1 ;
2001-02-06 22:25:12 +03:00
2001-11-21 06:55:59 +03:00
}
2001-02-06 22:25:12 +03:00
2001-11-21 06:55:59 +03:00
if ( ! fname & & ! printq ) {
2001-02-06 22:25:12 +03:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ;
return - 1 ;
2001-02-06 22:25:12 +03:00
2001-11-21 06:55:59 +03:00
}
2001-02-06 22:25:12 +03:00
2001-11-21 06:55:59 +03:00
/* Try to open the file for reading ... */
2001-02-06 22:25:12 +03:00
2003-04-05 02:16:50 +04:00
if ( ( int ) ( fid1 = c_file - > open ( c_file , fname , O_RDONLY , 0666 ) ) < 0 ) {
2002-07-15 14:35:28 +04:00
2001-11-21 06:55:59 +03:00
DEBUG ( 3 , ( " Error, fname=%s, errno=%i \n " , fname , errno ) ) ;
return - 1 ; /* smbc_open sets errno */
2002-07-15 14:35:28 +04:00
2001-11-21 06:55:59 +03:00
}
2001-02-06 22:25:12 +03:00
2001-11-21 06:55:59 +03:00
/* Now, try to open the printer file for writing */
2001-02-06 22:25:12 +03:00
2003-04-05 02:16:50 +04:00
if ( ( int ) ( fid2 = c_print - > open_print_job ( c_print , printq ) ) < 0 ) {
2001-02-06 22:25:12 +03:00
2001-11-21 06:55:59 +03:00
saverr = errno ; /* Save errno */
2002-07-15 14:35:28 +04:00
c_file - > close ( c_file , fid1 ) ;
2001-11-21 06:55:59 +03:00
errno = saverr ;
return - 1 ;
2001-02-06 22:25:12 +03:00
2001-11-21 06:55:59 +03:00
}
2001-02-06 22:25:12 +03:00
2002-07-15 14:35:28 +04:00
while ( ( bytes = c_file - > read ( c_file , fid1 , buf , sizeof ( buf ) ) ) > 0 ) {
2001-02-06 22:25:12 +03:00
2001-11-21 06:55:59 +03:00
tot_bytes + = bytes ;
2001-02-06 22:25:12 +03:00
2002-07-15 14:35:28 +04:00
if ( ( c_print - > write ( c_print , fid2 , buf , bytes ) ) < 0 ) {
2001-02-06 22:25:12 +03:00
2001-11-21 06:55:59 +03:00
saverr = errno ;
2002-07-15 14:35:28 +04:00
c_file - > close ( c_file , fid1 ) ;
c_print - > close ( c_print , fid2 ) ;
2001-11-21 06:55:59 +03:00
errno = saverr ;
2001-02-06 22:25:12 +03:00
2001-11-21 06:55:59 +03:00
}
2001-02-06 22:25:12 +03:00
2001-11-21 06:55:59 +03:00
}
2001-02-06 22:25:12 +03:00
2001-11-21 06:55:59 +03:00
saverr = errno ;
2001-02-06 22:25:12 +03:00
2002-07-15 14:35:28 +04:00
c_file - > close ( c_file , fid1 ) ; /* We have to close these anyway */
c_print - > close ( c_print , fid2 ) ;
2001-02-06 22:25:12 +03:00
2001-11-21 06:55:59 +03:00
if ( bytes < 0 ) {
2001-02-06 22:25:12 +03:00
2001-11-21 06:55:59 +03:00
errno = saverr ;
return - 1 ;
2001-02-06 22:25:12 +03:00
2001-11-21 06:55:59 +03:00
}
2001-02-06 22:25:12 +03:00
2001-11-21 06:55:59 +03:00
return tot_bytes ;
2001-02-06 22:25:12 +03:00
}
/*
2002-07-15 14:35:28 +04:00
* Routine to list print jobs on a printer share . . .
2001-02-06 22:25:12 +03:00
*/
2003-01-13 23:04:40 +03:00
static int smbc_list_print_jobs_ctx ( SMBCCTX * context , const char * fname , smbc_list_print_job_fn fn )
2001-02-06 22:25:12 +03:00
{
2002-07-15 14:35:28 +04:00
SMBCSRV * srv ;
fstring server , share , user , password , workgroup ;
2001-11-21 06:55:59 +03:00
pstring path ;
2001-02-06 22:25:12 +03:00
2003-01-13 23:04:40 +03:00
if ( ! context | | ! context - > internal | |
! context - > internal - > _initialized ) {
2001-02-06 22:25:12 +03:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ;
return - 1 ;
2001-02-06 22:25:12 +03:00
2001-11-21 06:55:59 +03:00
}
2001-02-06 22:25:12 +03:00
2001-11-21 06:55:59 +03:00
if ( ! fname ) {
2002-07-15 14:35:28 +04:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ;
return - 1 ;
2001-02-06 22:25:12 +03:00
2001-11-21 06:55:59 +03:00
}
2001-02-06 22:25:12 +03:00
2002-07-15 14:35:28 +04:00
DEBUG ( 4 , ( " smbc_list_print_jobs(%s) \n " , fname ) ) ;
2001-02-06 22:25:12 +03:00
2002-07-15 14:35:28 +04:00
smbc_parse_path ( context , fname , server , share , path , user , password ) ; /*FIXME, errors*/
2001-02-06 22:25:12 +03:00
2003-03-22 12:27:42 +03:00
if ( user [ 0 ] = = ( char ) 0 ) fstrcpy ( user , context - > user ) ;
2002-07-15 14:35:28 +04:00
2003-03-22 12:27:42 +03:00
fstrcpy ( workgroup , context - > workgroup ) ;
2002-07-15 14:35:28 +04:00
srv = smbc_server ( context , server , share , workgroup , user , password ) ;
if ( ! srv ) {
2001-02-05 16:02:20 +03:00
2002-07-15 14:35:28 +04:00
return - 1 ; /* errno set by smbc_server */
}
2003-01-13 23:04:40 +03:00
if ( cli_print_queue ( & srv - > cli , ( void ( * ) ( struct print_job_info * ) ) fn ) < 0 ) {
2002-07-15 14:35:28 +04:00
errno = smbc_errno ( context , & srv - > cli ) ;
return - 1 ;
}
return 0 ;
2001-02-05 16:02:20 +03:00
2000-12-26 08:57:10 +03:00
}
2001-02-04 22:48:26 +03:00
/*
2002-07-15 14:35:28 +04:00
* Delete a print job from a remote printer share
2001-02-04 22:48:26 +03:00
*/
2002-07-15 14:35:28 +04:00
static int smbc_unlink_print_job_ctx ( SMBCCTX * context , const char * fname , int id )
2001-02-04 22:48:26 +03:00
{
2002-07-15 14:35:28 +04:00
SMBCSRV * srv ;
2001-11-21 06:55:59 +03:00
fstring server , share , user , password , workgroup ;
pstring path ;
2002-07-15 14:35:28 +04:00
int err ;
2001-02-04 22:48:26 +03:00
2003-01-13 23:04:40 +03:00
if ( ! context | | ! context - > internal | |
! context - > internal - > _initialized ) {
2001-02-04 22:48:26 +03:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ;
return - 1 ;
2001-02-04 22:48:26 +03:00
2001-11-21 06:55:59 +03:00
}
2001-02-04 22:48:26 +03:00
2001-11-21 06:55:59 +03:00
if ( ! fname ) {
2001-02-04 22:48:26 +03:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ;
return - 1 ;
2001-02-04 22:48:26 +03:00
2001-11-21 06:55:59 +03:00
}
2001-02-04 22:48:26 +03:00
2002-07-15 14:35:28 +04:00
DEBUG ( 4 , ( " smbc_unlink_print_job(%s) \n " , fname ) ) ;
2001-02-04 22:48:26 +03:00
2002-07-15 14:35:28 +04:00
smbc_parse_path ( context , fname , server , share , path , user , password ) ; /*FIXME, errors*/
2001-02-04 22:48:26 +03:00
2003-03-22 12:27:42 +03:00
if ( user [ 0 ] = = ( char ) 0 ) fstrcpy ( user , context - > user ) ;
2001-02-04 22:48:26 +03:00
2003-03-22 12:27:42 +03:00
fstrcpy ( workgroup , context - > workgroup ) ;
2001-11-17 10:30:19 +03:00
2002-07-15 14:35:28 +04:00
srv = smbc_server ( context , server , share , workgroup , user , password ) ;
2001-02-04 22:48:26 +03:00
2001-11-21 06:55:59 +03:00
if ( ! srv ) {
2001-02-04 22:48:26 +03:00
2001-11-21 06:55:59 +03:00
return - 1 ; /* errno set by smbc_server */
2001-02-04 22:48:26 +03:00
2001-11-21 06:55:59 +03:00
}
2001-02-04 22:48:26 +03:00
2002-07-15 14:35:28 +04:00
if ( ( err = cli_printjob_del ( & srv - > cli , id ) ) ! = 0 ) {
2001-02-04 22:48:26 +03:00
2002-07-15 14:35:28 +04:00
if ( err < 0 )
errno = smbc_errno ( context , & srv - > cli ) ;
else if ( err = = ERRnosuchprintjob )
errno = EINVAL ;
2001-11-21 06:55:59 +03:00
return - 1 ;
2001-02-04 22:48:26 +03:00
2001-11-21 06:55:59 +03:00
}
2001-02-04 22:48:26 +03:00
2001-11-21 06:55:59 +03:00
return 0 ;
2001-02-04 22:48:26 +03:00
}
2001-02-05 16:02:20 +03:00
/*
2002-07-15 14:35:28 +04:00
* Get a new empty handle to fill in with your own info
2001-02-05 16:02:20 +03:00
*/
2002-07-15 14:35:28 +04:00
SMBCCTX * smbc_new_context ( void )
{
SMBCCTX * context ;
2001-02-05 16:02:20 +03:00
2003-01-13 23:04:40 +03:00
context = malloc ( sizeof ( SMBCCTX ) ) ;
2002-07-15 14:35:28 +04:00
if ( ! context ) {
errno = ENOMEM ;
return NULL ;
}
2003-01-13 23:04:40 +03:00
2002-07-15 14:35:28 +04:00
ZERO_STRUCTP ( context ) ;
2003-01-13 23:04:40 +03:00
context - > internal = malloc ( sizeof ( struct smbc_internal_data ) ) ;
if ( ! context - > internal ) {
errno = ENOMEM ;
return NULL ;
}
ZERO_STRUCTP ( context - > internal ) ;
2002-07-15 14:35:28 +04:00
/* ADD REASONABLE DEFAULTS */
context - > debug = 0 ;
context - > timeout = 20000 ; /* 20 seconds */
context - > open = smbc_open_ctx ;
context - > creat = smbc_creat_ctx ;
context - > read = smbc_read_ctx ;
context - > write = smbc_write_ctx ;
context - > close = smbc_close_ctx ;
context - > unlink = smbc_unlink_ctx ;
context - > rename = smbc_rename_ctx ;
context - > lseek = smbc_lseek_ctx ;
context - > stat = smbc_stat_ctx ;
context - > fstat = smbc_fstat_ctx ;
context - > opendir = smbc_opendir_ctx ;
context - > closedir = smbc_closedir_ctx ;
context - > readdir = smbc_readdir_ctx ;
context - > getdents = smbc_getdents_ctx ;
context - > mkdir = smbc_mkdir_ctx ;
context - > rmdir = smbc_rmdir_ctx ;
context - > telldir = smbc_telldir_ctx ;
context - > lseekdir = smbc_lseekdir_ctx ;
context - > fstatdir = smbc_fstatdir_ctx ;
context - > open_print_job = smbc_open_print_job_ctx ;
context - > print_file = smbc_print_file_ctx ;
context - > list_print_jobs = smbc_list_print_jobs_ctx ;
context - > unlink_print_job = smbc_unlink_print_job_ctx ;
context - > callbacks . check_server_fn = smbc_check_server ;
context - > callbacks . remove_unused_server_fn = smbc_remove_unused_server ;
smbc_default_cache_functions ( context ) ;
return context ;
}
/*
* Free a context
*
* Returns 0 on success . Otherwise returns 1 , the SMBCCTX is _not_ freed
* and thus you ' ll be leaking memory if not handled properly .
*
*/
int smbc_free_context ( SMBCCTX * context , int shutdown_ctx )
2001-02-05 16:02:20 +03:00
{
2002-07-15 14:35:28 +04:00
if ( ! context ) {
errno = EBADF ;
return 1 ;
}
if ( shutdown_ctx ) {
SMBCFILE * f ;
DEBUG ( 1 , ( " Performing aggressive shutdown. \n " ) ) ;
2003-01-13 23:04:40 +03:00
f = context - > internal - > _files ;
2002-07-15 14:35:28 +04:00
while ( f ) {
context - > close ( context , f ) ;
f = f - > next ;
}
2003-01-13 23:04:40 +03:00
context - > internal - > _files = NULL ;
2002-07-15 14:35:28 +04:00
/* First try to remove the servers the nice way. */
if ( context - > callbacks . purge_cached_fn ( context ) ) {
SMBCSRV * s ;
DEBUG ( 1 , ( " Could not purge all servers, Nice way shutdown failed. \n " ) ) ;
2003-01-13 23:04:40 +03:00
s = context - > internal - > _servers ;
2002-07-15 14:35:28 +04:00
while ( s ) {
cli_shutdown ( & s - > cli ) ;
context - > callbacks . remove_cached_srv_fn ( context , s ) ;
SAFE_FREE ( s ) ;
s = s - > next ;
}
2003-01-13 23:04:40 +03:00
context - > internal - > _servers = NULL ;
2002-07-15 14:35:28 +04:00
}
}
else {
/* This is the polite way */
if ( context - > callbacks . purge_cached_fn ( context ) ) {
DEBUG ( 1 , ( " Could not purge all servers, free_context failed. \n " ) ) ;
errno = EBUSY ;
return 1 ;
}
2003-01-13 23:04:40 +03:00
if ( context - > internal - > _servers ) {
2002-07-15 14:35:28 +04:00
DEBUG ( 1 , ( " Active servers in context, free_context failed. \n " ) ) ;
errno = EBUSY ;
return 1 ;
}
2003-01-13 23:04:40 +03:00
if ( context - > internal - > _files ) {
2002-07-15 14:35:28 +04:00
DEBUG ( 1 , ( " Active files in context, free_context failed. \n " ) ) ;
errno = EBUSY ;
return 1 ;
}
}
2001-02-05 16:02:20 +03:00
2002-07-15 14:35:28 +04:00
/* Things we have to clean up */
SAFE_FREE ( context - > workgroup ) ;
SAFE_FREE ( context - > netbios_name ) ;
SAFE_FREE ( context - > user ) ;
DEBUG ( 3 , ( " Context %p succesfully freed \n " , context ) ) ;
2003-01-13 23:04:40 +03:00
SAFE_FREE ( context - > internal ) ;
2002-07-15 14:35:28 +04:00
SAFE_FREE ( context ) ;
return 0 ;
}
2001-02-05 16:02:20 +03:00
2002-07-15 14:35:28 +04:00
/*
* Initialise the library etc
*
* We accept a struct containing handle information .
* valid values for info - > debug from 0 to 100 ,
* and insist that info - > fn must be non - null .
*/
SMBCCTX * smbc_init_context ( SMBCCTX * context )
{
pstring conf ;
int pid ;
char * user = NULL , * home = NULL ;
2003-01-13 23:04:40 +03:00
if ( ! context | | ! context - > internal ) {
2002-07-15 14:35:28 +04:00
errno = EBADF ;
return NULL ;
2001-11-21 06:55:59 +03:00
}
2001-02-05 16:02:20 +03:00
2002-07-15 14:35:28 +04:00
/* Do not initialise the same client twice */
2003-01-13 23:04:40 +03:00
if ( context - > internal - > _initialized ) {
2002-07-15 14:35:28 +04:00
return 0 ;
}
if ( ! context - > callbacks . auth_fn | | context - > debug < 0 | | context - > debug > 100 ) {
2001-02-05 16:02:20 +03:00
2001-11-21 06:55:59 +03:00
errno = EINVAL ;
2002-07-15 14:35:28 +04:00
return NULL ;
2001-02-05 16:02:20 +03:00
2001-11-21 06:55:59 +03:00
}
2001-02-05 16:02:20 +03:00
2002-07-15 14:35:28 +04:00
if ( ! smbc_initialized ) {
/* Do some library wide intialisations the first time we get called */
2001-02-05 16:02:20 +03:00
2003-04-16 18:45:11 +04:00
/* Set this to what the user wants */
DEBUGLEVEL = context - > debug ;
2002-07-15 14:35:28 +04:00
2003-04-16 18:45:11 +04:00
setup_logging ( " libsmbclient " , True ) ;
2001-11-17 10:30:19 +03:00
2002-07-15 14:35:28 +04:00
/* Here we would open the smb.conf file if needed ... */
home = getenv ( " HOME " ) ;
2001-02-05 16:02:20 +03:00
2002-07-15 14:35:28 +04:00
slprintf ( conf , sizeof ( conf ) , " %s/.smb/smb.conf " , home ) ;
load_interfaces ( ) ; /* Load the list of interfaces ... */
in_client = True ; /* FIXME, make a param */
2001-02-05 16:02:20 +03:00
2002-07-15 14:35:28 +04:00
if ( ! lp_load ( conf , True , False , False ) ) {
2001-02-05 16:02:20 +03:00
2002-07-15 14:35:28 +04:00
/*
2003-04-16 18:45:11 +04:00
* Well , if that failed , try the dyn_CONFIGFILE
* Which points to the standard locn , and if that
* fails , silently ignore it and use the internal
* defaults . . .
2002-07-15 14:35:28 +04:00
*/
2003-04-16 18:45:11 +04:00
if ( ! lp_load ( dyn_CONFIGFILE , True , False , False ) ) {
DEBUG ( 5 , ( " Could not load either config file: %s or %s \n " ,
conf , dyn_CONFIGFILE ) ) ;
}
2002-07-15 14:35:28 +04:00
}
2001-02-05 16:02:20 +03:00
2002-07-15 14:35:28 +04:00
reopen_logs ( ) ; /* Get logging working ... */
/*
* Block SIGPIPE ( from lib / util_sock . c : write ( ) )
* It is not needed and should not stop execution
*/
BlockSignals ( True , SIGPIPE ) ;
/* Done with one-time initialisation */
smbc_initialized = 1 ;
2001-02-05 16:02:20 +03:00
2002-07-15 14:35:28 +04:00
}
if ( ! context - > user ) {
/*
* FIXME : Is this the best way to get the user info ?
*/
user = getenv ( " USER " ) ;
/* walk around as "guest" if no username can be found */
if ( ! user ) context - > user = strdup ( " guest " ) ;
else context - > user = strdup ( user ) ;
}
2001-02-05 16:02:20 +03:00
2002-07-15 14:35:28 +04:00
if ( ! context - > netbios_name ) {
/*
* We try to get our netbios name from the config . If that fails we fall
* back on constructing our netbios name from our hostname etc
*/
2002-11-13 10:04:00 +03:00
if ( global_myname ( ) ) {
context - > netbios_name = strdup ( global_myname ( ) ) ;
2002-07-15 14:35:28 +04:00
}
else {
/*
* Hmmm , I want to get hostname as well , but I am too lazy for the moment
*/
pid = sys_getpid ( ) ;
context - > netbios_name = malloc ( 17 ) ;
if ( ! context - > netbios_name ) {
errno = ENOMEM ;
return NULL ;
}
slprintf ( context - > netbios_name , 16 , " smbc%s%d " , context - > user , pid ) ;
}
}
2003-04-16 18:45:11 +04:00
DEBUG ( 1 , ( " Using netbios name %s. \n " , context - > netbios_name ) ) ;
2001-03-05 16:34:48 +03:00
2002-07-15 14:35:28 +04:00
if ( ! context - > workgroup ) {
if ( lp_workgroup ( ) ) {
context - > workgroup = strdup ( lp_workgroup ( ) ) ;
}
else {
/* TODO: Think about a decent default workgroup */
context - > workgroup = strdup ( " samba " ) ;
}
2001-11-21 06:55:59 +03:00
}
2003-04-16 18:45:11 +04:00
DEBUG ( 1 , ( " Using workgroup %s. \n " , context - > workgroup ) ) ;
2002-07-15 14:35:28 +04:00
/* shortest timeout is 1 second */
if ( context - > timeout > 0 & & context - > timeout < 1000 )
context - > timeout = 1000 ;
2001-02-05 16:02:20 +03:00
2002-07-15 14:35:28 +04:00
/*
* FIXME : Should we check the function pointers here ?
*/
2001-02-05 16:02:20 +03:00
2003-01-13 23:04:40 +03:00
context - > internal - > _initialized = 1 ;
2002-07-15 14:35:28 +04:00
return context ;
2001-02-05 16:02:20 +03:00
}