1998-10-02 16:37:31 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
1998-10-02 16:37:31 +04:00
SMB wrapper functions
Copyright ( C ) Andrew Tridgell 1998
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"
1998-10-07 11:55:14 +04:00
# include "realcalls.h"
1998-10-02 16:37:31 +04:00
1998-10-06 14:24:22 +04:00
pstring smbw_cwd ;
1998-10-02 16:37:31 +04:00
static struct smbw_file * smbw_files ;
static struct smbw_server * smbw_srvs ;
1998-10-04 07:28:43 +04:00
struct bitmap * smbw_file_bmap ;
extern pstring global_myname ;
1998-10-02 16:37:31 +04:00
1998-10-06 14:24:22 +04:00
fstring smbw_prefix = SMBW_PREFIX ;
1998-10-04 07:28:43 +04:00
int smbw_busy = 0 ;
1998-10-03 12:34:35 +04:00
1998-10-07 13:57:22 +04:00
/* needs to be here because of dumb include files on some systems */
int creat_bits = O_WRONLY | O_CREAT | O_TRUNC ;
1998-10-20 10:45:18 +04:00
1998-10-02 16:37:31 +04:00
/*****************************************************
initialise structures
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void smbw_init ( void )
{
extern BOOL in_client ;
static int initialised ;
char * p ;
1998-10-07 15:07:24 +04:00
int eno ;
1998-10-23 05:27:23 +04:00
pstring line ;
1998-10-02 16:37:31 +04:00
if ( initialised ) return ;
initialised = 1 ;
1998-10-07 15:07:24 +04:00
eno = errno ;
1998-10-03 12:34:35 +04:00
smbw_busy + + ;
1998-10-02 16:37:31 +04:00
DEBUGLEVEL = 0 ;
1998-10-19 05:03:00 +04:00
setup_logging ( " smbsh " , True ) ;
1998-10-02 16:37:31 +04:00
2001-09-10 15:08:57 +04:00
dbf = x_stderr ;
1998-10-02 16:37:31 +04:00
1998-10-19 05:03:00 +04:00
if ( ( p = smbw_getshared ( " LOGFILE " ) ) ) {
1998-11-17 23:50:07 +03:00
dbf = sys_fopen ( p , " a " ) ;
1998-10-03 12:34:35 +04:00
}
1998-10-04 07:28:43 +04:00
smbw_file_bmap = bitmap_allocate ( SMBW_MAX_OPEN ) ;
if ( ! smbw_file_bmap ) {
1998-10-02 16:37:31 +04:00
exit ( 1 ) ;
}
in_client = True ;
1998-10-04 05:10:18 +04:00
load_interfaces ( ) ;
2000-12-13 07:19:48 +03:00
if ( ( p = smbw_getshared ( " SERVICESF " ) ) ) {
2001-11-19 05:49:53 +03:00
pstrcpy ( dyn_CONFIGFILE , p ) ;
2000-12-13 07:19:48 +03:00
}
2001-11-19 05:49:53 +03:00
lp_load ( dyn_CONFIGFILE , True , False , False ) ;
1998-10-02 16:37:31 +04:00
1999-12-13 16:27:58 +03:00
get_myname ( global_myname ) ;
1998-10-02 16:37:31 +04:00
1998-10-19 05:03:00 +04:00
if ( ( p = smbw_getshared ( " DEBUG " ) ) ) {
1998-10-02 16:37:31 +04:00
DEBUGLEVEL = atoi ( p ) ;
}
1998-10-19 06:49:48 +04:00
if ( ( p = smbw_getshared ( " RESOLVE_ORDER " ) ) ) {
lp_set_name_resolve_order ( p ) ;
}
1998-10-19 05:03:00 +04:00
if ( ( p = smbw_getshared ( " PREFIX " ) ) ) {
1998-10-06 14:24:22 +04:00
slprintf ( smbw_prefix , sizeof ( fstring ) - 1 , " /%s/ " , p ) ;
1999-12-13 16:27:58 +03:00
all_string_sub ( smbw_prefix , " // " , " / " , 0 ) ;
1998-10-06 14:24:22 +04:00
DEBUG ( 2 , ( " SMBW_PREFIX is %s \n " , smbw_prefix ) ) ;
}
1999-12-13 16:27:58 +03:00
slprintf ( line , sizeof ( line ) - 1 , " PWD_%d " , ( int ) getpid ( ) ) ;
1998-10-23 05:27:23 +04:00
p = smbw_getshared ( line ) ;
if ( ! p ) {
1998-10-24 12:14:17 +04:00
sys_getwd ( smbw_cwd ) ;
1998-10-02 16:37:31 +04:00
}
1998-10-23 05:27:23 +04:00
pstrcpy ( smbw_cwd , p ) ;
DEBUG ( 4 , ( " Initial cwd is %s \n " , smbw_cwd ) ) ;
1998-10-03 12:34:35 +04:00
smbw_busy - - ;
1998-10-05 05:57:03 +04:00
1998-10-19 05:03:00 +04:00
set_maxfiles ( SMBW_MAX_OPEN ) ;
1998-10-07 15:07:24 +04:00
1998-10-19 06:49:48 +04:00
BlockSignals ( True , SIGPIPE ) ;
1998-10-07 15:07:24 +04:00
errno = eno ;
1998-10-02 16:37:31 +04:00
}
/*****************************************************
determine if a file descriptor is a smb one
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-10-04 05:36:40 +04:00
int smbw_fd ( int fd )
1998-10-02 16:37:31 +04:00
{
1998-10-04 05:36:40 +04:00
if ( smbw_busy ) return 0 ;
1998-10-04 08:48:17 +04:00
return smbw_file_bmap & & bitmap_query ( smbw_file_bmap , fd ) ;
1998-10-02 16:37:31 +04:00
}
1998-10-24 10:36:22 +04:00
/*****************************************************
determine if a file descriptor is an internal smbw fd
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int smbw_local_fd ( int fd )
{
struct smbw_server * srv ;
smbw_init ( ) ;
if ( smbw_busy ) return 0 ;
if ( smbw_shared_fd ( fd ) ) return 1 ;
for ( srv = smbw_srvs ; srv ; srv = srv - > next ) {
if ( srv - > cli . fd = = fd ) return 1 ;
}
return 0 ;
}
1998-10-03 17:12:08 +04:00
/*****************************************************
a crude inode number generator
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
ino_t smbw_inode ( const char * name )
{
1998-10-24 12:08:05 +04:00
if ( ! * name ) return 2 ;
1998-10-03 17:12:08 +04:00
return ( ino_t ) str_checksum ( name ) ;
}
1998-10-02 16:37:31 +04:00
/*****************************************************
remove redundent stuff from a filename
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void clean_fname ( char * name )
{
char * p , * p2 ;
int l ;
int modified = 1 ;
if ( ! name ) return ;
while ( modified ) {
modified = 0 ;
1998-10-03 12:34:35 +04:00
DEBUG ( 5 , ( " cleaning %s \n " , name ) ) ;
1998-10-02 16:37:31 +04:00
if ( ( p = strstr ( name , " /./ " ) ) ) {
modified = 1 ;
while ( * p ) {
p [ 0 ] = p [ 2 ] ;
p + + ;
}
}
if ( ( p = strstr ( name , " // " ) ) ) {
modified = 1 ;
while ( * p ) {
p [ 0 ] = p [ 1 ] ;
p + + ;
}
}
if ( strcmp ( name , " /../ " ) = = 0 ) {
modified = 1 ;
name [ 1 ] = 0 ;
}
if ( ( p = strstr ( name , " /../ " ) ) ) {
modified = 1 ;
for ( p2 = ( p > name ? p - 1 : p ) ; p2 > name ; p2 - - ) {
if ( p2 [ 0 ] = = ' / ' ) break ;
}
while ( * p2 ) {
p2 [ 0 ] = p2 [ 3 ] ;
p2 + + ;
}
}
if ( strcmp ( name , " /.. " ) = = 0 ) {
modified = 1 ;
name [ 1 ] = 0 ;
}
l = strlen ( name ) ;
p = l > = 3 ? ( name + l - 3 ) : name ;
if ( strcmp ( p , " /.. " ) = = 0 ) {
modified = 1 ;
for ( p2 = p - 1 ; p2 > name ; p2 - - ) {
if ( p2 [ 0 ] = = ' / ' ) break ;
}
if ( p2 = = name ) {
p [ 0 ] = ' / ' ;
p [ 1 ] = 0 ;
} else {
p2 [ 0 ] = 0 ;
}
}
l = strlen ( name ) ;
p = l > = 2 ? ( name + l - 2 ) : name ;
if ( strcmp ( p , " /. " ) = = 0 ) {
if ( p = = name ) {
p [ 1 ] = 0 ;
} else {
p [ 0 ] = 0 ;
}
}
if ( strncmp ( p = name , " ./ " , 2 ) = = 0 ) {
modified = 1 ;
do {
p [ 0 ] = p [ 2 ] ;
} while ( * p + + ) ;
}
l = strlen ( p = name ) ;
if ( l > 1 & & p [ l - 1 ] = = ' / ' ) {
modified = 1 ;
p [ l - 1 ] = 0 ;
}
}
}
2000-12-11 03:09:06 +03:00
/*****************************************************
find a workgroup ( any workgroup ! ) that has a master
browser on the local network
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static char * smbw_find_workgroup ( void )
{
fstring server ;
char * p ;
struct in_addr * ip_list = NULL ;
int count = 0 ;
2000-12-20 06:22:51 +03:00
int i ;
2000-12-11 03:09:06 +03:00
/* first off see if an existing workgroup name exists */
p = smbw_getshared ( " WORKGROUP " ) ;
if ( ! p ) p = lp_workgroup ( ) ;
slprintf ( server , sizeof ( server ) , " %s#1D " , p ) ;
if ( smbw_server ( server , " IPC$ " ) ) return p ;
/* go looking for workgroups */
if ( ! name_resolve_bcast ( MSBROWSE , 1 , & ip_list , & count ) ) {
DEBUG ( 1 , ( " No workgroups found! " ) ) ;
return p ;
}
2000-12-20 06:22:51 +03:00
for ( i = 0 ; i < count ; i + + ) {
static fstring name ;
2001-11-22 02:00:59 +03:00
if ( name_status_find ( " * " , 0 , 0x1d , ip_list [ i ] , name ) ) {
2000-12-20 06:22:51 +03:00
slprintf ( server , sizeof ( server ) , " %s#1D " , name ) ;
if ( smbw_server ( server , " IPC$ " ) ) {
2001-02-20 13:13:48 +03:00
smbw_setshared ( " WORKGROUP " , name ) ;
2001-09-17 15:25:41 +04:00
SAFE_FREE ( ip_list ) ;
2000-12-20 06:22:51 +03:00
return name ;
}
}
}
2001-09-17 15:25:41 +04:00
SAFE_FREE ( ip_list ) ;
2000-12-11 03:09:06 +03:00
return p ;
}
1998-10-02 16:37:31 +04:00
/*****************************************************
parse a smb path into its components .
2000-12-11 03:09:06 +03:00
server is one of
1 ) the name of the SMB server
2 ) WORKGROUP # 1 D for share listing
3 ) WORKGROUP # __ for workgroup listing
share is the share on the server to query
path is the SMB path on the server
return the full path ( ie . add cwd if needed )
1998-10-02 16:37:31 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-10-03 13:39:11 +04:00
char * smbw_parse_path ( const char * fname , char * server , char * share , char * path )
1998-10-02 16:37:31 +04:00
{
1998-10-03 13:39:11 +04:00
static pstring s ;
2000-12-11 03:09:06 +03:00
char * p ;
int len ;
fstring workgroup ;
1998-10-03 14:24:49 +04:00
2000-12-11 03:09:06 +03:00
/* add cwd if necessary */
if ( fname [ 0 ] ! = ' / ' ) {
slprintf ( s , sizeof ( s ) , " %s/%s " , smbw_cwd , fname ) ;
1998-10-02 16:37:31 +04:00
} else {
2000-12-11 03:09:06 +03:00
pstrcpy ( s , fname ) ;
1998-10-02 16:37:31 +04:00
}
clean_fname ( s ) ;
2000-12-11 03:09:06 +03:00
/* see if it has the right prefix */
len = strlen ( smbw_prefix ) - 1 ;
1998-10-06 14:24:22 +04:00
if ( strncmp ( s , smbw_prefix , len ) | |
1998-10-04 15:25:06 +04:00
( s [ len ] ! = ' / ' & & s [ len ] ! = 0 ) ) return s ;
2000-12-11 03:09:06 +03:00
/* ok, its for us. Now parse out the workgroup, share etc. */
p = s + len ;
1998-10-04 15:25:06 +04:00
if ( * p = = ' / ' ) p + + ;
2000-12-11 03:09:06 +03:00
if ( ! next_token ( & p , workgroup , " / " , sizeof ( fstring ) ) ) {
/* we're in /smb - give a list of workgroups */
slprintf ( server , sizeof ( fstring ) , " %s#01 " , smbw_find_workgroup ( ) ) ;
1998-10-03 13:39:11 +04:00
fstrcpy ( share , " IPC$ " ) ;
pstrcpy ( path , " " ) ;
2000-12-11 03:09:06 +03:00
return s ;
1998-10-02 16:37:31 +04:00
}
2000-12-11 03:09:06 +03:00
if ( ! next_token ( & p , server , " / " , sizeof ( fstring ) ) ) {
/* we are in /smb/WORKGROUP */
slprintf ( server , sizeof ( fstring ) , " %s#1D " , workgroup ) ;
fstrcpy ( share , " IPC$ " ) ;
pstrcpy ( path , " " ) ;
1998-10-02 16:37:31 +04:00
}
1998-10-03 13:39:11 +04:00
2000-12-11 03:09:06 +03:00
if ( ! next_token ( & p , share , " / " , sizeof ( fstring ) ) ) {
/* we are in /smb/WORKGROUP/SERVER */
fstrcpy ( share , " IPC$ " ) ;
pstrcpy ( path , " " ) ;
1998-10-02 16:37:31 +04:00
}
2000-12-11 03:09:06 +03:00
pstrcpy ( path , p ) ;
1998-10-02 16:37:31 +04:00
1999-12-13 16:27:58 +03:00
all_string_sub ( path , " / " , " \\ " , 0 ) ;
1998-10-02 16:37:31 +04:00
return s ;
}
/*****************************************************
determine if a path name ( possibly relative ) is in the
smb name space
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-10-04 05:36:40 +04:00
int smbw_path ( const char * path )
1998-10-02 16:37:31 +04:00
{
1998-10-03 13:39:11 +04:00
fstring server , share ;
pstring s ;
1998-10-02 16:37:31 +04:00
char * cwd ;
1998-10-06 14:24:22 +04:00
int len ;
1999-12-13 16:27:58 +03:00
if ( ! path )
return 0 ;
1998-11-13 06:37:01 +03:00
/* this is needed to prevent recursion with the BSD malloc which
opens / etc / malloc . conf on the first call */
if ( strncmp ( path , " /etc/ " , 5 ) = = 0 ) {
return 0 ;
}
1998-10-06 14:24:22 +04:00
smbw_init ( ) ;
len = strlen ( smbw_prefix ) - 1 ;
1998-10-03 14:24:49 +04:00
1998-10-06 14:24:22 +04:00
if ( path [ 0 ] = = ' / ' & & strncmp ( path , smbw_prefix , len ) ) {
1998-10-04 05:36:40 +04:00
return 0 ;
1998-10-03 14:24:49 +04:00
}
1998-10-03 12:34:35 +04:00
1998-10-04 05:36:40 +04:00
if ( smbw_busy ) return 0 ;
1998-10-03 12:34:35 +04:00
DEBUG ( 3 , ( " smbw_path(%s) \n " , path ) ) ;
1998-10-03 13:39:11 +04:00
cwd = smbw_parse_path ( path , server , share , s ) ;
1998-10-03 12:34:35 +04:00
1998-10-06 14:24:22 +04:00
if ( strncmp ( cwd , smbw_prefix , len ) = = 0 & &
( cwd [ len ] = = ' / ' | | cwd [ len ] = = 0 ) ) {
1998-10-04 05:36:40 +04:00
return 1 ;
1998-10-03 12:34:35 +04:00
}
1998-10-04 05:36:40 +04:00
return 0 ;
1998-10-02 16:37:31 +04:00
}
/*****************************************************
return a unix errno from a SMB error pair
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-10-03 12:34:35 +04:00
int smbw_errno ( struct cli_state * c )
1998-10-02 16:37:31 +04:00
{
2001-09-16 07:49:15 +04:00
return cli_errno ( c ) ;
1998-10-02 16:37:31 +04:00
}
2000-11-01 07:31:19 +03:00
/* Return a username and password given a server and share name */
void get_envvar_auth_data ( char * server , char * share , char * * workgroup ,
char * * username , char * * password )
{
/* Fall back to shared memory/environment variables */
* username = smbw_getshared ( " USER " ) ;
if ( ! * username ) * username = getenv ( " USER " ) ;
if ( ! * username ) * username = " guest " ;
* workgroup = smbw_getshared ( " WORKGROUP " ) ;
if ( ! * workgroup ) * workgroup = lp_workgroup ( ) ;
* password = smbw_getshared ( " PASSWORD " ) ;
if ( ! * password ) * password = " " ;
}
static smbw_get_auth_data_fn get_auth_data_fn = get_envvar_auth_data ;
/*****************************************************
set the get auth data function
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void smbw_set_auth_data_fn ( smbw_get_auth_data_fn fn )
{
get_auth_data_fn = fn ;
}
1998-10-02 16:37:31 +04:00
/*****************************************************
return a connection to a server ( existing or new )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
struct smbw_server * smbw_server ( char * server , char * share )
{
struct smbw_server * srv = NULL ;
1998-10-04 07:28:43 +04:00
struct cli_state c ;
1998-10-02 16:37:31 +04:00
char * username ;
char * password ;
char * workgroup ;
struct nmb_name called , calling ;
1998-10-04 15:25:06 +04:00
char * p , * server_n = server ;
fstring group ;
1998-10-19 05:03:00 +04:00
pstring ipenv ;
struct in_addr ip ;
1998-10-02 16:37:31 +04:00
2001-11-26 06:11:44 +03:00
zero_ip ( & ip ) ;
1998-10-04 07:28:43 +04:00
ZERO_STRUCT ( c ) ;
2000-11-11 04:21:31 +03:00
get_auth_data_fn ( server , share , & workgroup , & username , & password ) ;
1998-10-02 16:37:31 +04:00
/* try to use an existing connection */
for ( srv = smbw_srvs ; srv ; srv = srv - > next ) {
if ( strcmp ( server , srv - > server_name ) = = 0 & &
2000-11-01 07:31:19 +03:00
strcmp ( share , srv - > share_name ) = = 0 & &
strcmp ( workgroup , srv - > workgroup ) = = 0 & &
strcmp ( username , srv - > username ) = = 0 )
return srv ;
1998-10-02 16:37:31 +04:00
}
1998-10-03 12:34:35 +04:00
if ( server [ 0 ] = = 0 ) {
errno = EPERM ;
return NULL ;
}
2000-03-16 20:58:08 +03:00
make_nmb_name ( & calling , global_myname , 0x0 ) ;
make_nmb_name ( & called , server , 0x20 ) ;
1998-10-04 14:46:52 +04:00
1998-10-17 03:05:19 +04:00
DEBUG ( 4 , ( " server_n=[%s] server=[%s] \n " , server_n , server ) ) ;
1998-10-04 16:00:40 +04:00
2001-07-04 11:36:09 +04:00
if ( ( p = strchr_m ( server_n , ' # ' ) ) & &
2000-12-11 03:09:06 +03:00
( strcmp ( p + 1 , " 1D " ) = = 0 | | strcmp ( p + 1 , " 01 " ) = = 0 ) ) {
1998-10-20 07:17:43 +04:00
struct in_addr sip ;
1998-10-19 05:03:00 +04:00
pstring s ;
1998-10-04 15:25:06 +04:00
fstrcpy ( group , server_n ) ;
2001-07-04 11:36:09 +04:00
p = strchr_m ( group , ' # ' ) ;
1998-10-04 15:25:06 +04:00
* p = 0 ;
1998-10-19 05:03:00 +04:00
/* cache the workgroup master lookup */
slprintf ( s , sizeof ( s ) - 1 , " MASTER_%s " , group ) ;
if ( ! ( server_n = smbw_getshared ( s ) ) ) {
1998-10-20 07:17:43 +04:00
if ( ! find_master_ip ( group , & sip ) ) {
1998-10-19 05:03:00 +04:00
errno = ENOENT ;
return NULL ;
}
1998-10-20 07:17:43 +04:00
fstrcpy ( group , inet_ntoa ( sip ) ) ;
1998-10-19 05:03:00 +04:00
server_n = group ;
smbw_setshared ( s , server_n ) ;
1998-10-04 15:25:06 +04:00
}
}
1998-10-17 03:05:19 +04:00
DEBUG ( 4 , ( " -> server_n=[%s] server=[%s] \n " , server_n , server ) ) ;
1998-10-04 16:00:40 +04:00
again :
1998-10-19 05:03:00 +04:00
slprintf ( ipenv , sizeof ( ipenv ) - 1 , " HOST_%s " , server_n ) ;
2001-11-26 06:11:44 +03:00
zero_ip ( & ip ) ;
1998-10-19 05:03:00 +04:00
if ( ( p = smbw_getshared ( ipenv ) ) ) {
ip = * ( interpret_addr2 ( p ) ) ;
}
1998-10-02 16:37:31 +04:00
/* have to open a new connection */
1998-10-19 05:03:00 +04:00
if ( ! cli_initialise ( & c ) | | ! cli_connect ( & c , server_n , & ip ) ) {
1998-10-02 16:37:31 +04:00
errno = ENOENT ;
return NULL ;
}
if ( ! cli_session_request ( & c , & calling , & called ) ) {
cli_shutdown ( & c ) ;
1998-10-04 14:46:52 +04:00
if ( strcmp ( called . name , " *SMBSERVER " ) ) {
2000-03-16 20:58:08 +03:00
make_nmb_name ( & called , " *SMBSERVER " , 0x20 ) ;
1998-10-04 14:46:52 +04:00
goto again ;
}
1998-10-02 16:37:31 +04:00
errno = ENOENT ;
return NULL ;
}
1998-10-17 03:05:19 +04:00
DEBUG ( 4 , ( " session request ok \n " ) ) ;
1998-10-04 14:46:52 +04:00
1998-10-02 16:37:31 +04:00
if ( ! cli_negprot ( & c ) ) {
cli_shutdown ( & c ) ;
errno = ENOENT ;
return NULL ;
}
if ( ! cli_session_setup ( & c , username ,
1999-01-29 22:31:52 +03:00
password , strlen ( password ) ,
password , strlen ( password ) ,
1998-10-07 04:40:18 +04:00
workgroup ) & &
/* try an anonymous login if it failed */
! cli_session_setup ( & c , " " , " " , 1 , " " , 0 , workgroup ) ) {
1998-10-02 16:37:31 +04:00
cli_shutdown ( & c ) ;
errno = EPERM ;
return NULL ;
}
1998-10-17 03:05:19 +04:00
DEBUG ( 4 , ( " session setup ok \n " ) ) ;
1998-10-04 13:42:51 +04:00
if ( ! cli_send_tconX ( & c , share , " ????? " ,
1998-10-02 16:37:31 +04:00
password , strlen ( password ) + 1 ) ) {
1998-10-03 12:34:35 +04:00
errno = smbw_errno ( & c ) ;
1998-10-02 16:37:31 +04:00
cli_shutdown ( & c ) ;
return NULL ;
}
1998-10-19 05:03:00 +04:00
smbw_setshared ( ipenv , inet_ntoa ( ip ) ) ;
1998-10-17 03:05:19 +04:00
DEBUG ( 4 , ( " tconx ok \n " ) ) ;
1998-10-02 16:37:31 +04:00
srv = ( struct smbw_server * ) malloc ( sizeof ( * srv ) ) ;
if ( ! srv ) {
errno = ENOMEM ;
goto failed ;
}
ZERO_STRUCTP ( srv ) ;
srv - > cli = c ;
1998-10-03 17:12:08 +04:00
srv - > dev = ( dev_t ) ( str_checksum ( server ) ^ str_checksum ( share ) ) ;
1998-10-02 16:37:31 +04:00
srv - > server_name = strdup ( server ) ;
if ( ! srv - > server_name ) {
errno = ENOMEM ;
goto failed ;
}
srv - > share_name = strdup ( share ) ;
if ( ! srv - > share_name ) {
errno = ENOMEM ;
goto failed ;
}
2000-11-01 07:31:19 +03:00
srv - > workgroup = strdup ( workgroup ) ;
if ( ! srv - > workgroup ) {
errno = ENOMEM ;
goto failed ;
}
srv - > username = strdup ( username ) ;
if ( ! srv - > username ) {
errno = ENOMEM ;
goto failed ;
}
1998-10-03 14:24:49 +04:00
/* some programs play with file descriptors fairly intimately. We
try to get out of the way by duping to a high fd number */
1998-10-03 15:54:20 +04:00
if ( fcntl ( SMBW_CLI_FD + srv - > cli . fd , F_GETFD ) & & errno = = EBADF ) {
if ( dup2 ( srv - > cli . fd , SMBW_CLI_FD + srv - > cli . fd ) = =
srv - > cli . fd + SMBW_CLI_FD ) {
1998-10-03 14:24:49 +04:00
close ( srv - > cli . fd ) ;
1998-10-03 15:54:20 +04:00
srv - > cli . fd + = SMBW_CLI_FD ;
1998-10-03 14:24:49 +04:00
}
}
1998-10-02 16:37:31 +04:00
DLIST_ADD ( smbw_srvs , srv ) ;
return srv ;
failed :
cli_shutdown ( & c ) ;
if ( ! srv ) return NULL ;
2001-09-17 15:25:41 +04:00
SAFE_FREE ( srv - > server_name ) ;
SAFE_FREE ( srv - > share_name ) ;
SAFE_FREE ( srv ) ;
1998-10-02 16:37:31 +04:00
return NULL ;
}
/*****************************************************
map a fd to a smbw_file structure
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
struct smbw_file * smbw_file ( int fd )
{
struct smbw_file * file ;
for ( file = smbw_files ; file ; file = file - > next ) {
if ( file - > fd = = fd ) return file ;
}
return NULL ;
}
/*****************************************************
a wrapper for open ( )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-10-03 13:39:11 +04:00
int smbw_open ( const char * fname , int flags , mode_t mode )
1998-10-02 16:37:31 +04:00
{
1998-10-03 13:39:11 +04:00
fstring server , share ;
pstring path ;
1998-10-02 16:37:31 +04:00
struct smbw_server * srv = NULL ;
1998-10-05 16:17:01 +04:00
int eno = 0 , fd = - 1 ;
1998-10-02 16:37:31 +04:00
struct smbw_file * file = NULL ;
1998-10-03 12:34:35 +04:00
smbw_init ( ) ;
1998-10-02 16:37:31 +04:00
if ( ! fname ) {
errno = EINVAL ;
return - 1 ;
}
1998-10-03 12:34:35 +04:00
smbw_busy + + ;
1998-10-02 16:37:31 +04:00
/* work out what server they are after */
1998-10-03 13:39:11 +04:00
smbw_parse_path ( fname , server , share , path ) ;
1998-10-02 16:37:31 +04:00
/* get a connection to the server */
srv = smbw_server ( server , share ) ;
if ( ! srv ) {
/* smbw_server sets errno */
goto failed ;
}
1998-10-03 12:34:35 +04:00
if ( path [ strlen ( path ) - 1 ] = = ' \\ ' ) {
fd = - 1 ;
} else {
fd = cli_open ( & srv - > cli , path , flags , DENY_NONE ) ;
}
1998-10-02 16:37:31 +04:00
if ( fd = = - 1 ) {
/* it might be a directory. Maybe we should use chkpath? */
1998-10-06 07:12:40 +04:00
eno = smbw_errno ( & srv - > cli ) ;
1998-10-03 20:34:57 +04:00
fd = smbw_dir_open ( fname ) ;
1998-10-05 17:51:19 +04:00
if ( fd = = - 1 ) errno = eno ;
1998-10-03 12:34:35 +04:00
smbw_busy - - ;
return fd ;
1998-10-02 16:37:31 +04:00
}
file = ( struct smbw_file * ) malloc ( sizeof ( * file ) ) ;
if ( ! file ) {
errno = ENOMEM ;
goto failed ;
}
ZERO_STRUCTP ( file ) ;
1998-10-04 11:52:00 +04:00
file - > f = ( struct smbw_filedes * ) malloc ( sizeof ( * ( file - > f ) ) ) ;
if ( ! file - > f ) {
errno = ENOMEM ;
goto failed ;
}
ZERO_STRUCTP ( file - > f ) ;
file - > f - > cli_fd = fd ;
file - > f - > fname = strdup ( path ) ;
if ( ! file - > f - > fname ) {
1998-10-02 16:37:31 +04:00
errno = ENOMEM ;
goto failed ;
}
file - > srv = srv ;
1998-10-04 10:22:08 +04:00
file - > fd = open ( SMBW_DUMMY , O_WRONLY ) ;
1998-10-02 16:37:31 +04:00
if ( file - > fd = = - 1 ) {
errno = EMFILE ;
goto failed ;
}
1998-10-04 08:48:17 +04:00
if ( bitmap_query ( smbw_file_bmap , file - > fd ) ) {
DEBUG ( 0 , ( " ERROR: fd used in smbw_open \n " ) ) ;
errno = EIO ;
goto failed ;
}
1998-10-02 16:37:31 +04:00
1998-10-04 11:52:00 +04:00
file - > f - > ref_count = 1 ;
1998-10-04 08:48:17 +04:00
bitmap_set ( smbw_file_bmap , file - > fd ) ;
1998-10-02 16:37:31 +04:00
DLIST_ADD ( smbw_files , file ) ;
1998-10-03 13:39:11 +04:00
DEBUG ( 4 , ( " opened %s \n " , fname ) ) ;
1998-10-02 16:37:31 +04:00
1998-10-03 12:34:35 +04:00
smbw_busy - - ;
1998-10-02 16:37:31 +04:00
return file - > fd ;
failed :
if ( fd ! = - 1 ) {
cli_close ( & srv - > cli , fd ) ;
}
if ( file ) {
1998-10-04 11:52:00 +04:00
if ( file - > f ) {
2001-09-17 15:25:41 +04:00
SAFE_FREE ( file - > f - > fname ) ;
SAFE_FREE ( file - > f ) ;
1998-10-02 16:37:31 +04:00
}
2001-09-17 15:25:41 +04:00
SAFE_FREE ( file ) ;
1998-10-02 16:37:31 +04:00
}
1998-10-03 12:34:35 +04:00
smbw_busy - - ;
1998-10-02 16:37:31 +04:00
return - 1 ;
}
1998-10-05 06:31:39 +04:00
/*****************************************************
a wrapper for pread ( )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
ssize_t smbw_pread ( int fd , void * buf , size_t count , off_t ofs )
{
struct smbw_file * file ;
int ret ;
smbw_busy + + ;
file = smbw_file ( fd ) ;
if ( ! file ) {
errno = EBADF ;
smbw_busy - - ;
return - 1 ;
}
ret = cli_read ( & file - > srv - > cli , file - > f - > cli_fd , buf , ofs , count ) ;
if ( ret = = - 1 ) {
errno = smbw_errno ( & file - > srv - > cli ) ;
smbw_busy - - ;
return - 1 ;
}
smbw_busy - - ;
return ret ;
}
1998-10-02 16:37:31 +04:00
/*****************************************************
a wrapper for read ( )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
ssize_t smbw_read ( int fd , void * buf , size_t count )
{
struct smbw_file * file ;
int ret ;
1998-10-06 17:10:06 +04:00
DEBUG ( 4 , ( " smbw_read(%d, %d) \n " , fd , ( int ) count ) ) ;
1998-10-03 12:34:35 +04:00
smbw_busy + + ;
1998-10-02 16:37:31 +04:00
file = smbw_file ( fd ) ;
if ( ! file ) {
errno = EBADF ;
1998-10-03 12:34:35 +04:00
smbw_busy - - ;
1998-10-02 16:37:31 +04:00
return - 1 ;
}
1998-10-05 06:31:39 +04:00
ret = cli_read ( & file - > srv - > cli , file - > f - > cli_fd , buf ,
file - > f - > offset , count ) ;
1998-10-02 16:37:31 +04:00
if ( ret = = - 1 ) {
1998-10-03 12:34:35 +04:00
errno = smbw_errno ( & file - > srv - > cli ) ;
smbw_busy - - ;
1998-10-02 16:37:31 +04:00
return - 1 ;
}
1998-10-04 11:52:00 +04:00
file - > f - > offset + = ret ;
1998-10-06 17:10:06 +04:00
DEBUG ( 4 , ( " -> %d \n " , ret ) ) ;
1998-10-02 16:37:31 +04:00
1998-10-03 12:34:35 +04:00
smbw_busy - - ;
1998-10-02 16:37:31 +04:00
return ret ;
}
1998-10-05 06:31:39 +04:00
1998-10-02 16:37:31 +04:00
/*****************************************************
a wrapper for write ( )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
ssize_t smbw_write ( int fd , void * buf , size_t count )
{
struct smbw_file * file ;
int ret ;
1998-10-03 12:34:35 +04:00
smbw_busy + + ;
1998-10-02 16:37:31 +04:00
file = smbw_file ( fd ) ;
if ( ! file ) {
errno = EBADF ;
1998-10-03 12:34:35 +04:00
smbw_busy - - ;
1998-10-02 16:37:31 +04:00
return - 1 ;
}
1998-10-09 03:57:46 +04:00
ret = cli_write ( & file - > srv - > cli , file - > f - > cli_fd , 0 , buf , file - > f - > offset , count ) ;
1998-10-02 16:37:31 +04:00
if ( ret = = - 1 ) {
1998-10-03 12:34:35 +04:00
errno = smbw_errno ( & file - > srv - > cli ) ;
smbw_busy - - ;
1998-10-02 16:37:31 +04:00
return - 1 ;
}
1998-10-04 11:52:00 +04:00
file - > f - > offset + = ret ;
1998-10-02 16:37:31 +04:00
1998-10-03 12:34:35 +04:00
smbw_busy - - ;
1998-10-02 16:37:31 +04:00
return ret ;
}
1998-10-05 06:31:39 +04:00
/*****************************************************
a wrapper for pwrite ( )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
ssize_t smbw_pwrite ( int fd , void * buf , size_t count , off_t ofs )
{
struct smbw_file * file ;
int ret ;
smbw_busy + + ;
file = smbw_file ( fd ) ;
if ( ! file ) {
errno = EBADF ;
smbw_busy - - ;
return - 1 ;
}
1998-10-10 00:17:11 +04:00
ret = cli_write ( & file - > srv - > cli , file - > f - > cli_fd , 0 , buf , ofs , count ) ;
1998-10-05 06:31:39 +04:00
if ( ret = = - 1 ) {
errno = smbw_errno ( & file - > srv - > cli ) ;
smbw_busy - - ;
return - 1 ;
}
smbw_busy - - ;
return ret ;
}
1998-10-02 16:37:31 +04:00
/*****************************************************
a wrapper for close ( )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int smbw_close ( int fd )
{
struct smbw_file * file ;
1998-10-03 12:34:35 +04:00
smbw_busy + + ;
1998-10-02 16:37:31 +04:00
file = smbw_file ( fd ) ;
if ( ! file ) {
1998-10-03 12:34:35 +04:00
int ret = smbw_dir_close ( fd ) ;
smbw_busy - - ;
return ret ;
1998-10-02 16:37:31 +04:00
}
1998-10-04 11:52:00 +04:00
if ( file - > f - > ref_count = = 1 & &
! cli_close ( & file - > srv - > cli , file - > f - > cli_fd ) ) {
1998-10-03 12:34:35 +04:00
errno = smbw_errno ( & file - > srv - > cli ) ;
smbw_busy - - ;
1998-10-02 16:37:31 +04:00
return - 1 ;
}
1998-10-04 08:48:17 +04:00
bitmap_clear ( smbw_file_bmap , file - > fd ) ;
close ( file - > fd ) ;
1998-10-02 16:37:31 +04:00
DLIST_REMOVE ( smbw_files , file ) ;
1998-10-04 11:52:00 +04:00
file - > f - > ref_count - - ;
if ( file - > f - > ref_count = = 0 ) {
2001-09-17 15:25:41 +04:00
SAFE_FREE ( file - > f - > fname ) ;
SAFE_FREE ( file - > f ) ;
1998-10-04 11:52:00 +04:00
}
1998-10-02 16:37:31 +04:00
ZERO_STRUCTP ( file ) ;
2001-09-17 15:25:41 +04:00
SAFE_FREE ( file ) ;
1998-10-03 12:34:35 +04:00
smbw_busy - - ;
1998-10-02 16:37:31 +04:00
return 0 ;
}
/*****************************************************
a wrapper for fcntl ( )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int smbw_fcntl ( int fd , int cmd , long arg )
{
return 0 ;
}
/*****************************************************
a wrapper for access ( )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-10-03 13:39:11 +04:00
int smbw_access ( const char * name , int mode )
1998-10-02 16:37:31 +04:00
{
struct stat st ;
1998-10-06 17:10:06 +04:00
DEBUG ( 4 , ( " smbw_access(%s, 0x%x) \n " , name , mode ) ) ;
if ( smbw_stat ( name , & st ) ) return - 1 ;
if ( ( ( mode & R_OK ) & & ! ( st . st_mode & S_IRUSR ) ) | |
( ( mode & W_OK ) & & ! ( st . st_mode & S_IWUSR ) ) | |
( ( mode & X_OK ) & & ! ( st . st_mode & S_IXUSR ) ) ) {
errno = EACCES ;
return - 1 ;
}
return 0 ;
1998-10-02 16:37:31 +04:00
}
1998-10-03 12:34:35 +04:00
/*****************************************************
a wrapper for realink ( ) - needed for correct errno setting
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-10-03 13:39:11 +04:00
int smbw_readlink ( const char * path , char * buf , size_t bufsize )
1998-10-03 12:34:35 +04:00
{
struct stat st ;
int ret ;
ret = smbw_stat ( path , & st ) ;
if ( ret ! = 0 ) {
DEBUG ( 4 , ( " readlink(%s) failed \n " , path ) ) ;
return - 1 ;
}
/* it exists - say it isn't a link */
DEBUG ( 4 , ( " readlink(%s) not a link \n " , path ) ) ;
errno = EINVAL ;
return - 1 ;
}
1998-10-02 16:37:31 +04:00
1998-10-03 13:39:11 +04:00
/*****************************************************
a wrapper for unlink ( )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int smbw_unlink ( const char * fname )
{
struct smbw_server * srv ;
fstring server , share ;
pstring path ;
if ( ! fname ) {
errno = EINVAL ;
return - 1 ;
}
smbw_init ( ) ;
smbw_busy + + ;
/* work out what server they are after */
smbw_parse_path ( fname , server , share , path ) ;
/* get a connection to the server */
srv = smbw_server ( server , share ) ;
if ( ! srv ) {
/* smbw_server sets errno */
goto failed ;
}
1998-10-04 14:14:21 +04:00
if ( strncmp ( srv - > cli . dev , " LPT " , 3 ) = = 0 ) {
int job = smbw_stat_printjob ( srv , path , NULL , NULL ) ;
if ( job = = - 1 ) {
goto failed ;
}
if ( cli_printjob_del ( & srv - > cli , job ) ! = 0 ) {
goto failed ;
}
} else if ( ! cli_unlink ( & srv - > cli , path ) ) {
1998-10-03 13:39:11 +04:00
errno = smbw_errno ( & srv - > cli ) ;
goto failed ;
}
smbw_busy - - ;
return 0 ;
failed :
smbw_busy - - ;
return - 1 ;
}
/*****************************************************
a wrapper for rename ( )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int smbw_rename ( const char * oldname , const char * newname )
{
struct smbw_server * srv ;
fstring server1 , share1 ;
pstring path1 ;
fstring server2 , share2 ;
pstring path2 ;
if ( ! oldname | | ! newname ) {
errno = EINVAL ;
return - 1 ;
}
smbw_init ( ) ;
1998-10-06 17:10:06 +04:00
DEBUG ( 4 , ( " smbw_rename(%s,%s) \n " , oldname , newname ) ) ;
1998-10-03 13:39:11 +04:00
smbw_busy + + ;
/* work out what server they are after */
smbw_parse_path ( oldname , server1 , share1 , path1 ) ;
smbw_parse_path ( newname , server2 , share2 , path2 ) ;
if ( strcmp ( server1 , server2 ) | | strcmp ( share1 , share2 ) ) {
/* can't cross filesystems */
errno = EXDEV ;
return - 1 ;
}
/* get a connection to the server */
srv = smbw_server ( server1 , share1 ) ;
if ( ! srv ) {
/* smbw_server sets errno */
goto failed ;
}
if ( ! cli_rename ( & srv - > cli , path1 , path2 ) ) {
1998-10-06 17:10:06 +04:00
int eno = smbw_errno ( & srv - > cli ) ;
if ( eno ! = EEXIST | |
! cli_unlink ( & srv - > cli , path2 ) | |
! cli_rename ( & srv - > cli , path1 , path2 ) ) {
errno = eno ;
goto failed ;
}
1998-10-03 13:39:11 +04:00
}
smbw_busy - - ;
return 0 ;
failed :
smbw_busy - - ;
return - 1 ;
}
1998-10-03 14:24:49 +04:00
/*****************************************************
1998-10-05 12:44:46 +04:00
a wrapper for utime and utimes
1998-10-03 14:24:49 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-10-05 12:44:46 +04:00
static int smbw_settime ( const char * fname , time_t t )
1998-10-03 14:24:49 +04:00
{
struct smbw_server * srv ;
fstring server , share ;
pstring path ;
1998-11-09 23:33:37 +03:00
uint16 mode ;
1998-10-03 14:24:49 +04:00
if ( ! fname ) {
errno = EINVAL ;
return - 1 ;
}
smbw_init ( ) ;
smbw_busy + + ;
/* work out what server they are after */
smbw_parse_path ( fname , server , share , path ) ;
/* get a connection to the server */
srv = smbw_server ( server , share ) ;
if ( ! srv ) {
/* smbw_server sets errno */
goto failed ;
}
if ( ! cli_getatr ( & srv - > cli , path , & mode , NULL , NULL ) ) {
errno = smbw_errno ( & srv - > cli ) ;
goto failed ;
}
1998-10-05 12:44:46 +04:00
if ( ! cli_setatr ( & srv - > cli , path , mode , t ) ) {
1998-10-06 15:56:44 +04:00
/* some servers always refuse directory changes */
if ( ! ( mode & aDIR ) ) {
errno = smbw_errno ( & srv - > cli ) ;
goto failed ;
}
1998-10-03 14:24:49 +04:00
}
smbw_busy - - ;
return 0 ;
failed :
smbw_busy - - ;
return - 1 ;
}
1998-10-05 12:44:46 +04:00
/*****************************************************
a wrapper for utime
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int smbw_utime ( const char * fname , void * buf )
{
struct utimbuf * tbuf = ( struct utimbuf * ) buf ;
return smbw_settime ( fname , tbuf ? tbuf - > modtime : time ( NULL ) ) ;
}
/*****************************************************
a wrapper for utime
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int smbw_utimes ( const char * fname , void * buf )
{
struct timeval * tbuf = ( struct timeval * ) buf ;
return smbw_settime ( fname , tbuf ? tbuf - > tv_sec : time ( NULL ) ) ;
}
1998-10-03 14:24:49 +04:00
/*****************************************************
a wrapper for chown ( )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int smbw_chown ( const char * fname , uid_t owner , gid_t group )
{
struct smbw_server * srv ;
fstring server , share ;
pstring path ;
1998-11-09 23:33:37 +03:00
uint16 mode ;
1998-10-03 14:24:49 +04:00
if ( ! fname ) {
errno = EINVAL ;
return - 1 ;
}
smbw_init ( ) ;
smbw_busy + + ;
/* work out what server they are after */
smbw_parse_path ( fname , server , share , path ) ;
/* get a connection to the server */
srv = smbw_server ( server , share ) ;
if ( ! srv ) {
/* smbw_server sets errno */
goto failed ;
}
if ( ! cli_getatr ( & srv - > cli , path , & mode , NULL , NULL ) ) {
errno = smbw_errno ( & srv - > cli ) ;
goto failed ;
}
/* assume success */
smbw_busy - - ;
return 0 ;
failed :
smbw_busy - - ;
return - 1 ;
}
/*****************************************************
a wrapper for chmod ( )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int smbw_chmod ( const char * fname , mode_t newmode )
{
struct smbw_server * srv ;
fstring server , share ;
pstring path ;
uint32 mode ;
if ( ! fname ) {
errno = EINVAL ;
return - 1 ;
}
smbw_init ( ) ;
smbw_busy + + ;
/* work out what server they are after */
smbw_parse_path ( fname , server , share , path ) ;
/* get a connection to the server */
srv = smbw_server ( server , share ) ;
if ( ! srv ) {
/* smbw_server sets errno */
goto failed ;
}
1998-10-06 15:14:52 +04:00
mode = 0 ;
if ( ! ( newmode & ( S_IWUSR | S_IWGRP | S_IWOTH ) ) ) mode | = aRONLY ;
if ( ( newmode & S_IXUSR ) & & lp_map_archive ( - 1 ) ) mode | = aARCH ;
if ( ( newmode & S_IXGRP ) & & lp_map_system ( - 1 ) ) mode | = aSYSTEM ;
if ( ( newmode & S_IXOTH ) & & lp_map_hidden ( - 1 ) ) mode | = aHIDDEN ;
if ( ! cli_setatr ( & srv - > cli , path , mode , 0 ) ) {
1998-10-03 14:24:49 +04:00
errno = smbw_errno ( & srv - > cli ) ;
goto failed ;
}
smbw_busy - - ;
return 0 ;
failed :
smbw_busy - - ;
return - 1 ;
}
1998-10-03 15:54:20 +04:00
/*****************************************************
a wrapper for lseek ( )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-10-03 16:33:34 +04:00
off_t smbw_lseek ( int fd , off_t offset , int whence )
1998-10-03 15:54:20 +04:00
{
struct smbw_file * file ;
1998-10-05 16:17:01 +04:00
size_t size ;
1998-10-03 15:54:20 +04:00
smbw_busy + + ;
file = smbw_file ( fd ) ;
if ( ! file ) {
1998-10-03 16:33:34 +04:00
off_t ret = smbw_dir_lseek ( fd , offset , whence ) ;
1998-10-03 15:54:20 +04:00
smbw_busy - - ;
1998-10-03 16:33:34 +04:00
return ret ;
1998-10-03 15:54:20 +04:00
}
switch ( whence ) {
case SEEK_SET :
1998-10-04 11:52:00 +04:00
file - > f - > offset = offset ;
1998-10-03 15:54:20 +04:00
break ;
case SEEK_CUR :
1998-10-04 11:52:00 +04:00
file - > f - > offset + = offset ;
1998-10-03 15:54:20 +04:00
break ;
case SEEK_END :
1998-10-04 11:52:00 +04:00
if ( ! cli_qfileinfo ( & file - > srv - > cli , file - > f - > cli_fd ,
1998-10-24 12:08:05 +04:00
NULL , & size , NULL , NULL , NULL ,
NULL , NULL ) & &
1998-10-04 11:52:00 +04:00
! cli_getattrE ( & file - > srv - > cli , file - > f - > cli_fd ,
1998-10-03 15:54:20 +04:00
NULL , & size , NULL , NULL , NULL ) ) {
errno = EINVAL ;
smbw_busy - - ;
return - 1 ;
}
1998-10-04 11:52:00 +04:00
file - > f - > offset = size + offset ;
1998-10-03 15:54:20 +04:00
break ;
}
smbw_busy - - ;
1998-10-04 11:52:00 +04:00
return file - > f - > offset ;
}
/*****************************************************
a wrapper for dup ( )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int smbw_dup ( int fd )
{
int fd2 ;
struct smbw_file * file , * file2 ;
smbw_busy + + ;
file = smbw_file ( fd ) ;
if ( ! file ) {
errno = EBADF ;
goto failed ;
}
fd2 = dup ( file - > fd ) ;
if ( fd2 = = - 1 ) {
goto failed ;
}
if ( bitmap_query ( smbw_file_bmap , fd2 ) ) {
DEBUG ( 0 , ( " ERROR: fd already open in dup! \n " ) ) ;
errno = EIO ;
goto failed ;
}
file2 = ( struct smbw_file * ) malloc ( sizeof ( * file2 ) ) ;
if ( ! file2 ) {
close ( fd2 ) ;
errno = ENOMEM ;
goto failed ;
}
ZERO_STRUCTP ( file2 ) ;
* file2 = * file ;
file2 - > fd = fd2 ;
file - > f - > ref_count + + ;
bitmap_set ( smbw_file_bmap , fd2 ) ;
DLIST_ADD ( smbw_files , file2 ) ;
smbw_busy - - ;
return fd2 ;
failed :
smbw_busy - - ;
return - 1 ;
}
/*****************************************************
a wrapper for dup2 ( )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int smbw_dup2 ( int fd , int fd2 )
{
struct smbw_file * file , * file2 ;
smbw_busy + + ;
file = smbw_file ( fd ) ;
if ( ! file ) {
errno = EBADF ;
goto failed ;
}
if ( bitmap_query ( smbw_file_bmap , fd2 ) ) {
DEBUG ( 0 , ( " ERROR: fd already open in dup2! \n " ) ) ;
errno = EIO ;
goto failed ;
}
if ( dup2 ( file - > fd , fd2 ) ! = fd2 ) {
goto failed ;
}
file2 = ( struct smbw_file * ) malloc ( sizeof ( * file2 ) ) ;
if ( ! file2 ) {
close ( fd2 ) ;
errno = ENOMEM ;
goto failed ;
}
ZERO_STRUCTP ( file2 ) ;
* file2 = * file ;
file2 - > fd = fd2 ;
file - > f - > ref_count + + ;
bitmap_set ( smbw_file_bmap , fd2 ) ;
DLIST_ADD ( smbw_files , file2 ) ;
smbw_busy - - ;
return fd2 ;
failed :
smbw_busy - - ;
return - 1 ;
1998-10-03 15:54:20 +04:00
}
1998-10-03 17:27:56 +04:00
1998-10-06 16:23:37 +04:00
/*****************************************************
close a connection to a server
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void smbw_srv_close ( struct smbw_server * srv )
{
smbw_busy + + ;
cli_shutdown ( & srv - > cli ) ;
2001-09-17 15:25:41 +04:00
SAFE_FREE ( srv - > server_name ) ;
SAFE_FREE ( srv - > share_name ) ;
1998-10-06 16:23:37 +04:00
DLIST_REMOVE ( smbw_srvs , srv ) ;
ZERO_STRUCTP ( srv ) ;
2001-09-17 15:25:41 +04:00
SAFE_FREE ( srv ) ;
1998-10-06 16:23:37 +04:00
smbw_busy - - ;
}
/*****************************************************
when we fork we have to close all connections and files
in the child
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int smbw_fork ( void )
{
pid_t child ;
int p [ 2 ] ;
char c = 0 ;
1998-10-23 05:27:23 +04:00
pstring line ;
1998-10-06 16:23:37 +04:00
struct smbw_file * file , * next_file ;
struct smbw_server * srv , * next_srv ;
if ( pipe ( p ) ) return real_fork ( ) ;
child = real_fork ( ) ;
if ( child ) {
/* block the parent for a moment until the sockets are
closed */
close ( p [ 1 ] ) ;
read ( p [ 0 ] , & c , 1 ) ;
close ( p [ 0 ] ) ;
return child ;
}
close ( p [ 0 ] ) ;
/* close all files */
for ( file = smbw_files ; file ; file = next_file ) {
next_file = file - > next ;
close ( file - > fd ) ;
}
/* close all server connections */
for ( srv = smbw_srvs ; srv ; srv = next_srv ) {
next_srv = srv - > next ;
smbw_srv_close ( srv ) ;
}
1999-12-13 16:27:58 +03:00
slprintf ( line , sizeof ( line ) - 1 , " PWD_%d " , ( int ) getpid ( ) ) ;
1998-10-23 05:27:23 +04:00
smbw_setshared ( line , smbw_cwd ) ;
1998-10-06 16:23:37 +04:00
/* unblock the parent */
write ( p [ 1 ] , & c , 1 ) ;
close ( p [ 1 ] ) ;
/* and continue in the child */
return 0 ;
}
1998-10-07 13:57:22 +04:00
1998-10-07 14:35:18 +04:00
# ifndef NO_ACL_WRAPPER
1998-10-07 13:57:22 +04:00
/*****************************************************
say no to acls
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-10-08 03:57:02 +04:00
int smbw_acl ( const char * pathp , int cmd , int nentries , aclent_t * aclbufp )
1998-10-07 13:57:22 +04:00
{
if ( cmd = = GETACL | | cmd = = GETACLCNT ) return 0 ;
errno = ENOSYS ;
return - 1 ;
}
# endif
1998-10-07 14:35:18 +04:00
# ifndef NO_FACL_WRAPPER
1998-10-07 13:57:22 +04:00
/*****************************************************
say no to acls
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-10-08 03:57:02 +04:00
int smbw_facl ( int fd , int cmd , int nentries , aclent_t * aclbufp )
1998-10-07 13:57:22 +04:00
{
if ( cmd = = GETACL | | cmd = = GETACLCNT ) return 0 ;
errno = ENOSYS ;
return - 1 ;
}
# endif
2000-07-06 06:28:44 +04:00
# ifdef HAVE_EXPLICIT_LARGEFILE_SUPPORT
1998-10-07 13:57:22 +04:00
# ifdef HAVE_STAT64
/* this can't be in wrapped.c because of include conflicts */
1998-10-08 03:57:02 +04:00
void stat64_convert ( struct stat * st , struct stat64 * st64 )
1998-10-07 13:57:22 +04:00
{
st64 - > st_size = st - > st_size ;
st64 - > st_mode = st - > st_mode ;
st64 - > st_ino = st - > st_ino ;
st64 - > st_dev = st - > st_dev ;
st64 - > st_rdev = st - > st_rdev ;
st64 - > st_nlink = st - > st_nlink ;
st64 - > st_uid = st - > st_uid ;
st64 - > st_gid = st - > st_gid ;
st64 - > st_atime = st - > st_atime ;
st64 - > st_mtime = st - > st_mtime ;
st64 - > st_ctime = st - > st_ctime ;
st64 - > st_blksize = st - > st_blksize ;
st64 - > st_blocks = st - > st_blocks ;
}
# endif
# ifdef HAVE_READDIR64
1998-10-08 03:57:02 +04:00
void dirent64_convert ( struct dirent * d , struct dirent64 * d64 )
1998-10-07 13:57:22 +04:00
{
d64 - > d_ino = d - > d_ino ;
d64 - > d_off = d - > d_off ;
d64 - > d_reclen = d - > d_reclen ;
pstrcpy ( d64 - > d_name , d - > d_name ) ;
}
# endif
2000-07-06 06:28:44 +04:00
# endif
1998-10-07 13:57:22 +04:00
# ifdef HAVE___XSTAT
/* Definition of `struct stat' used in the linux kernel.. */
struct kernel_stat {
unsigned short int st_dev ;
unsigned short int __pad1 ;
unsigned long int st_ino ;
unsigned short int st_mode ;
unsigned short int st_nlink ;
unsigned short int st_uid ;
unsigned short int st_gid ;
unsigned short int st_rdev ;
unsigned short int __pad2 ;
unsigned long int st_size ;
unsigned long int st_blksize ;
unsigned long int st_blocks ;
unsigned long int st_atime ;
unsigned long int __unused1 ;
unsigned long int st_mtime ;
unsigned long int __unused2 ;
unsigned long int st_ctime ;
unsigned long int __unused3 ;
unsigned long int __unused4 ;
unsigned long int __unused5 ;
} ;
1998-10-17 21:41:13 +04:00
/*
* Prototype for gcc in ' fussy ' mode .
*/
void xstat_convert ( int vers , struct stat * st , struct kernel_stat * kbuf ) ;
1998-10-08 03:57:02 +04:00
void xstat_convert ( int vers , struct stat * st , struct kernel_stat * kbuf )
1998-10-07 13:57:22 +04:00
{
1998-10-14 11:16:00 +04:00
# ifdef _STAT_VER_LINUX_OLD
1998-10-07 13:57:22 +04:00
if ( vers = = _STAT_VER_LINUX_OLD ) {
memcpy ( st , kbuf , sizeof ( * st ) ) ;
return ;
}
1998-10-14 11:16:00 +04:00
# endif
1998-10-07 13:57:22 +04:00
ZERO_STRUCTP ( st ) ;
st - > st_dev = kbuf - > st_dev ;
st - > st_ino = kbuf - > st_ino ;
st - > st_mode = kbuf - > st_mode ;
st - > st_nlink = kbuf - > st_nlink ;
st - > st_uid = kbuf - > st_uid ;
st - > st_gid = kbuf - > st_gid ;
st - > st_rdev = kbuf - > st_rdev ;
st - > st_size = kbuf - > st_size ;
st - > st_blksize = kbuf - > st_blksize ;
st - > st_blocks = kbuf - > st_blocks ;
st - > st_atime = kbuf - > st_atime ;
st - > st_mtime = kbuf - > st_mtime ;
st - > st_ctime = kbuf - > st_ctime ;
}
# endif