2003-08-13 05:53:07 +04:00
/*
Unix SMB / CIFS implementation .
SMB client
Copyright ( C ) Andrew Tridgell 1994 - 1998
Copyright ( C ) Simo Sorce 2001 - 2002
2004-06-05 23:24:48 +04:00
Copyright ( C ) Jelmer Vernooij 2003 - 2004
2003-08-13 05:53:07 +04:00
Copyright ( C ) James J Myers 2003 < myersjj @ samba . org >
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"
2005-01-18 12:30:43 +03:00
# include "version.h"
2006-01-03 18:40:05 +03:00
# include "libcli/libcli.h"
2004-11-02 05:57:18 +03:00
# include "lib/cmdline/popt_common.h"
2006-03-15 02:35:30 +03:00
# include "librpc/gen_ndr/ndr_srvsvc_c.h"
2004-12-06 10:12:38 +03:00
# include "librpc/gen_ndr/ndr_lsa.h"
2006-04-29 21:34:49 +04:00
# include "librpc/gen_ndr/ndr_security.h"
2004-11-01 04:03:22 +03:00
# include "libcli/raw/libcliraw.h"
2006-03-07 17:34:32 +03:00
# include "libcli/util/clilsa.h"
2004-11-02 03:24:21 +03:00
# include "system/dir.h"
2004-11-02 15:55:38 +03:00
# include "system/filesys.h"
2004-11-02 09:42:15 +03:00
# include "dlinklist.h"
2005-09-26 19:59:43 +04:00
# include "system/readline.h"
2005-12-31 01:46:16 +03:00
# include "auth/gensec/gensec.h"
2005-12-31 05:03:26 +03:00
# include "system/time.h" /* needed by some systems for asctime() */
2006-03-07 14:07:23 +03:00
# include "libcli/resolve/resolve.h"
2006-04-02 16:02:01 +04:00
# include "libcli/security/security.h"
2006-05-01 17:20:05 +04:00
# include "lib/replace/smbreadline.h"
2006-03-16 03:23:11 +03:00
# include "librpc/gen_ndr/ndr_nbt.h"
2004-11-01 04:03:22 +03:00
2003-08-13 05:53:07 +04:00
static int io_bufsize = 64512 ;
2006-01-26 09:33:45 +03:00
struct smbclient_context {
char * remote_cur_dir ;
struct smbcli_state * cli ;
char * fileselection ;
time_t newer_than ;
BOOL prompt ;
BOOL recurse ;
int archive_level ;
BOOL lowercase ;
int printmode ;
BOOL translation ;
} ;
2003-08-13 05:53:07 +04:00
/* timing globals */
2005-09-28 18:38:07 +04:00
static uint64_t get_total_size = 0 ;
static uint_t get_total_time_ms = 0 ;
2004-05-25 17:57:39 +04:00
static uint64_t put_total_size = 0 ;
2004-06-01 12:12:45 +04:00
static uint_t put_total_time_ms = 0 ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
/* Unfortunately, there is no way to pass the a context to the completion function as an argument */
static struct smbclient_context * rl_ctx ;
2003-08-13 05:53:07 +04:00
/* totals globals */
static double dir_total ;
/*******************************************************************
Reduce a file name , removing . . elements .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void dos_clean_name ( char * s )
{
2006-01-26 09:33:45 +03:00
char * p = NULL , * r ;
2003-08-13 05:53:07 +04:00
DEBUG ( 3 , ( " dos_clean_name [%s] \n " , s ) ) ;
/* remove any double slashes */
all_string_sub ( s , " \\ \\ " , " \\ " , 0 ) ;
2006-01-26 09:33:45 +03:00
while ( ( p = strstr ( s , " \\ .. \\ " ) ) ! = NULL ) {
* p = ' \0 ' ;
if ( ( r = strrchr ( s , ' \\ ' ) ) ! = NULL )
memmove ( r , p + 3 , strlen ( p + 3 ) + 1 ) ;
}
2003-08-13 05:53:07 +04:00
trim_string ( s , NULL , " \\ .. " ) ;
all_string_sub ( s , " \\ . \\ " , " \\ " , 0 ) ;
}
/****************************************************************************
write to a local file with CR / LF - > LF translation if appropriate . return the
number taken from the buffer . This may not equal the number written .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int writefile ( int f , const void * _b , int n , BOOL translation )
2003-08-13 05:53:07 +04:00
{
2004-12-04 16:56:25 +03:00
const uint8_t * b = _b ;
2003-08-13 05:53:07 +04:00
int i ;
if ( ! translation ) {
return write ( f , b , n ) ;
}
i = 0 ;
while ( i < n ) {
if ( * b = = ' \r ' & & ( i < ( n - 1 ) ) & & * ( b + 1 ) = = ' \n ' ) {
b + + ; i + + ;
}
if ( write ( f , b , 1 ) ! = 1 ) {
break ;
}
b + + ;
i + + ;
}
return ( i ) ;
}
/****************************************************************************
read from a file with LF - > CR / LF translation if appropriate . return the
number read . read approx n bytes .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int readfile ( void * _b , int n , XFILE * f , BOOL translation )
2003-08-13 05:53:07 +04:00
{
2004-12-04 16:56:25 +03:00
uint8_t * b = _b ;
2003-08-13 05:53:07 +04:00
int i ;
int c ;
if ( ! translation )
return x_fread ( b , 1 , n , f ) ;
i = 0 ;
2004-11-30 08:37:57 +03:00
while ( i < ( n - 1 ) ) {
2003-08-13 05:53:07 +04:00
if ( ( c = x_getc ( f ) ) = = EOF ) {
break ;
}
if ( c = = ' \n ' ) { /* change all LFs to CR/LF */
b [ i + + ] = ' \r ' ;
}
b [ i + + ] = c ;
}
return ( i ) ;
}
/****************************************************************************
send a message
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static void send_message ( struct smbcli_state * cli , const char * desthost )
2003-08-13 05:53:07 +04:00
{
2006-01-26 09:33:45 +03:00
char msg [ 1600 ] ;
2003-08-13 05:53:07 +04:00
int total_len = 0 ;
int grp_id ;
2005-09-22 05:50:58 +04:00
if ( ! smbcli_message_start ( cli - > tree , desthost , cli_credentials_get_username ( cmdline_credentials ) , & grp_id ) ) {
2004-08-04 17:23:35 +04:00
d_printf ( " message start: %s \n " , smbcli_errstr ( cli - > tree ) ) ;
2003-08-13 05:53:07 +04:00
return ;
}
d_printf ( " Connected. Type your message, ending it with a Control-D \n " ) ;
while ( ! feof ( stdin ) & & total_len < 1600 ) {
int maxlen = MIN ( 1600 - total_len , 127 ) ;
int l = 0 ;
int c ;
for ( l = 0 ; l < maxlen & & ( c = fgetc ( stdin ) ) ! = EOF ; l + + ) {
if ( c = = ' \n ' )
msg [ l + + ] = ' \r ' ;
msg [ l ] = c ;
}
2004-08-04 17:23:35 +04:00
if ( ! smbcli_message_text ( cli - > tree , msg , l , grp_id ) ) {
d_printf ( " SMBsendtxt failed (%s) \n " , smbcli_errstr ( cli - > tree ) ) ;
2003-08-13 05:53:07 +04:00
return ;
}
total_len + = l ;
}
if ( total_len > = 1600 )
d_printf ( " the message was truncated to 1600 bytes \n " ) ;
else
d_printf ( " sent %d bytes \n " , total_len ) ;
2004-08-04 17:23:35 +04:00
if ( ! smbcli_message_end ( cli - > tree , grp_id ) ) {
d_printf ( " SMBsendend failed (%s) \n " , smbcli_errstr ( cli - > tree ) ) ;
2003-08-13 05:53:07 +04:00
return ;
}
}
/****************************************************************************
check the space on a device
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int do_dskattr ( struct smbclient_context * ctx )
2003-08-13 05:53:07 +04:00
{
int total , bsize , avail ;
2006-01-26 09:33:45 +03:00
if ( NT_STATUS_IS_ERR ( smbcli_dskattr ( ctx - > cli - > tree , & bsize , & total , & avail ) ) ) {
d_printf ( " Error in dskattr: %s \n " , smbcli_errstr ( ctx - > cli - > tree ) ) ;
2003-08-13 05:53:07 +04:00
return 1 ;
}
d_printf ( " \n \t \t %d blocks of size %d. %d blocks available \n " ,
total , bsize , avail ) ;
return 0 ;
}
/****************************************************************************
show cd / pwd
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_pwd ( struct smbclient_context * ctx , const char * * args )
2003-08-13 05:53:07 +04:00
{
2006-01-26 09:33:45 +03:00
d_printf ( " Current directory is %s \n " , ctx - > remote_cur_dir ) ;
2003-08-13 05:53:07 +04:00
return 0 ;
}
2004-09-21 05:43:53 +04:00
/*
convert a string to dos format
*/
static void dos_format ( char * s )
{
string_replace ( s , ' / ' , ' \\ ' ) ;
}
2003-08-13 05:53:07 +04:00
/****************************************************************************
change directory - inner section
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int do_cd ( struct smbclient_context * ctx , const char * newdir )
2003-08-13 05:53:07 +04:00
{
2006-01-26 09:33:45 +03:00
char * dname ;
2003-08-13 05:53:07 +04:00
/* Save the current directory in case the
new directory is invalid */
2006-01-26 09:33:45 +03:00
if ( newdir [ 0 ] = = ' \\ ' )
dname = talloc_strdup ( NULL , newdir ) ;
2003-08-13 05:53:07 +04:00
else
2006-01-26 09:33:45 +03:00
dname = talloc_asprintf ( NULL , " %s \\ %s " , ctx - > remote_cur_dir , newdir ) ;
dos_format ( dname ) ;
if ( * ( dname + strlen ( dname ) - 1 ) ! = ' \\ ' ) {
dname = talloc_append_string ( NULL , dname , " \\ " ) ;
}
dos_clean_name ( dname ) ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
if ( NT_STATUS_IS_ERR ( smbcli_chkpath ( ctx - > cli - > tree , dname ) ) ) {
d_printf ( " cd %s: %s \n " , dname , smbcli_errstr ( ctx - > cli - > tree ) ) ;
talloc_free ( dname ) ;
} else {
ctx - > remote_cur_dir = dname ;
2003-08-13 05:53:07 +04:00
}
return 0 ;
}
/****************************************************************************
change directory
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_cd ( struct smbclient_context * ctx , const char * * args )
2003-08-13 05:53:07 +04:00
{
int rc = 0 ;
2006-01-26 09:33:45 +03:00
if ( args [ 1 ] )
rc = do_cd ( ctx , args [ 1 ] ) ;
2003-08-13 05:53:07 +04:00
else
2006-01-26 09:33:45 +03:00
d_printf ( " Current directory is %s \n " , ctx - > remote_cur_dir ) ;
2003-08-13 05:53:07 +04:00
return rc ;
}
2006-01-26 09:33:45 +03:00
BOOL mask_match ( struct smbcli_state * c , const char * string , const char * pattern ,
2004-11-01 23:21:54 +03:00
BOOL is_case_sensitive )
{
2006-01-26 09:33:45 +03:00
char * p2 , * s2 ;
BOOL ret ;
2004-11-01 23:21:54 +03:00
2006-04-24 04:16:51 +04:00
if ( ISDOTDOT ( string ) )
2004-11-01 23:21:54 +03:00
string = " . " ;
2006-04-24 04:16:51 +04:00
if ( ISDOT ( pattern ) )
2004-11-01 23:21:54 +03:00
return False ;
if ( is_case_sensitive )
return ms_fnmatch ( pattern , string ,
c - > transport - > negotiate . protocol ) = = 0 ;
2006-01-26 09:33:45 +03:00
p2 = strlower_talloc ( NULL , pattern ) ;
s2 = strlower_talloc ( NULL , string ) ;
ret = ms_fnmatch ( p2 , s2 , c - > transport - > negotiate . protocol ) = = 0 ;
talloc_free ( p2 ) ;
talloc_free ( s2 ) ;
return ret ;
2004-11-01 23:21:54 +03:00
}
2003-08-13 05:53:07 +04:00
/*******************************************************************
decide if a file should be operated on
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static BOOL do_this_one ( struct smbclient_context * ctx , struct clilist_file_info * finfo )
2003-08-13 05:53:07 +04:00
{
2004-11-30 08:37:57 +03:00
if ( finfo - > attrib & FILE_ATTRIBUTE_DIRECTORY ) return ( True ) ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
if ( ctx - > fileselection & &
! mask_match ( ctx - > cli , finfo - > name , ctx - > fileselection , False ) ) {
2003-08-13 05:53:07 +04:00
DEBUG ( 3 , ( " mask_match %s failed \n " , finfo - > name ) ) ;
return False ;
}
2006-01-26 09:33:45 +03:00
if ( ctx - > newer_than & & finfo - > mtime < ctx - > newer_than ) {
2003-08-13 05:53:07 +04:00
DEBUG ( 3 , ( " newer_than %s failed \n " , finfo - > name ) ) ;
return ( False ) ;
}
2006-01-26 09:33:45 +03:00
if ( ( ctx - > archive_level = = 1 | | ctx - > archive_level = = 2 ) & & ! ( finfo - > attrib & FILE_ATTRIBUTE_ARCHIVE ) ) {
2003-08-13 05:53:07 +04:00
DEBUG ( 3 , ( " archive %s failed \n " , finfo - > name ) ) ;
return ( False ) ;
}
return ( True ) ;
}
/****************************************************************************
display info about a file
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static void display_finfo ( struct smbclient_context * ctx , struct clilist_file_info * finfo )
2003-08-13 05:53:07 +04:00
{
2006-01-26 09:33:45 +03:00
if ( do_this_one ( ctx , finfo ) ) {
2003-08-13 05:53:07 +04:00
time_t t = finfo - > mtime ; /* the time is assumed to be passed as GMT */
2004-11-30 08:37:57 +03:00
char * astr = attrib_string ( NULL , finfo - > attrib ) ;
2003-08-13 05:53:07 +04:00
d_printf ( " %-30s%7.7s %8.0f %s " ,
finfo - > name ,
2004-09-20 11:25:06 +04:00
astr ,
2003-08-13 05:53:07 +04:00
( double ) finfo - > size ,
2004-04-11 00:18:22 +04:00
asctime ( localtime ( & t ) ) ) ;
2003-08-13 05:53:07 +04:00
dir_total + = finfo - > size ;
2004-09-20 11:25:06 +04:00
talloc_free ( astr ) ;
2003-08-13 05:53:07 +04:00
}
}
/****************************************************************************
accumulate size of a file
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static void do_du ( struct smbclient_context * ctx , struct clilist_file_info * finfo )
2003-08-13 05:53:07 +04:00
{
2006-01-26 09:33:45 +03:00
if ( do_this_one ( ctx , finfo ) ) {
2003-08-13 05:53:07 +04:00
dir_total + = finfo - > size ;
}
}
static BOOL do_list_recurse ;
static BOOL do_list_dirs ;
static char * do_list_queue = 0 ;
static long do_list_queue_size = 0 ;
static long do_list_queue_start = 0 ;
static long do_list_queue_end = 0 ;
2006-01-26 09:33:45 +03:00
static void ( * do_list_fn ) ( struct smbclient_context * , struct clilist_file_info * ) ;
2003-08-13 05:53:07 +04:00
/****************************************************************************
functions for do_list_queue
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* The do_list_queue is a NUL - separated list of strings stored in a
* char * . Since this is a FIFO , we keep track of the beginning and
* ending locations of the data in the queue . When we overflow , we
* double the size of the char * . When the start of the data passes
* the midpoint , we move everything back . This is logically more
* complex than a linked list , but easier from a memory management
* angle . In any memory error condition , do_list_queue is reset .
* Functions check to ensure that do_list_queue is non - NULL before
* accessing it .
*/
static void reset_do_list_queue ( void )
{
SAFE_FREE ( do_list_queue ) ;
do_list_queue_size = 0 ;
do_list_queue_start = 0 ;
do_list_queue_end = 0 ;
}
static void init_do_list_queue ( void )
{
reset_do_list_queue ( ) ;
do_list_queue_size = 1024 ;
do_list_queue = malloc ( do_list_queue_size ) ;
if ( do_list_queue = = 0 ) {
d_printf ( " malloc fail for size %d \n " ,
( int ) do_list_queue_size ) ;
reset_do_list_queue ( ) ;
} else {
memset ( do_list_queue , 0 , do_list_queue_size ) ;
}
}
static void adjust_do_list_queue ( void )
{
2006-04-08 06:49:44 +04:00
if ( do_list_queue = = NULL ) return ;
2003-08-13 05:53:07 +04:00
/*
* If the starting point of the queue is more than half way through ,
* move everything toward the beginning .
*/
2006-04-08 06:49:44 +04:00
if ( do_list_queue_start = = do_list_queue_end )
2003-08-13 05:53:07 +04:00
{
DEBUG ( 4 , ( " do_list_queue is empty \n " ) ) ;
do_list_queue_start = do_list_queue_end = 0 ;
* do_list_queue = ' \0 ' ;
}
else if ( do_list_queue_start > ( do_list_queue_size / 2 ) )
{
DEBUG ( 4 , ( " sliding do_list_queue backward \n " ) ) ;
memmove ( do_list_queue ,
do_list_queue + do_list_queue_start ,
do_list_queue_end - do_list_queue_start ) ;
do_list_queue_end - = do_list_queue_start ;
do_list_queue_start = 0 ;
}
}
static void add_to_do_list_queue ( const char * entry )
{
char * dlq ;
long new_end = do_list_queue_end + ( ( long ) strlen ( entry ) ) + 1 ;
while ( new_end > do_list_queue_size )
{
do_list_queue_size * = 2 ;
DEBUG ( 4 , ( " enlarging do_list_queue to %d \n " ,
( int ) do_list_queue_size ) ) ;
2004-12-03 09:42:06 +03:00
dlq = realloc_p ( do_list_queue , char , do_list_queue_size ) ;
2003-08-13 05:53:07 +04:00
if ( ! dlq ) {
d_printf ( " failure enlarging do_list_queue to %d bytes \n " ,
( int ) do_list_queue_size ) ;
reset_do_list_queue ( ) ;
}
else
{
do_list_queue = dlq ;
memset ( do_list_queue + do_list_queue_size / 2 ,
0 , do_list_queue_size / 2 ) ;
}
}
if ( do_list_queue )
{
safe_strcpy ( do_list_queue + do_list_queue_end , entry ,
do_list_queue_size - do_list_queue_end - 1 ) ;
do_list_queue_end = new_end ;
DEBUG ( 4 , ( " added %s to do_list_queue (start=%d, end=%d) \n " ,
entry , ( int ) do_list_queue_start , ( int ) do_list_queue_end ) ) ;
}
}
static char * do_list_queue_head ( void )
{
return do_list_queue + do_list_queue_start ;
}
static void remove_do_list_queue_head ( void )
{
if ( do_list_queue_end > do_list_queue_start )
{
do_list_queue_start + = strlen ( do_list_queue_head ( ) ) + 1 ;
adjust_do_list_queue ( ) ;
DEBUG ( 4 , ( " removed head of do_list_queue (start=%d, end=%d) \n " ,
( int ) do_list_queue_start , ( int ) do_list_queue_end ) ) ;
}
}
static int do_list_queue_empty ( void )
{
return ( ! ( do_list_queue & & * do_list_queue ) ) ;
}
/****************************************************************************
a helper for do_list
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-11-30 08:37:57 +03:00
static void do_list_helper ( struct clilist_file_info * f , const char * mask , void * state )
2003-08-13 05:53:07 +04:00
{
2006-01-26 09:33:45 +03:00
struct smbclient_context * ctx = state ;
2004-11-30 08:37:57 +03:00
if ( f - > attrib & FILE_ATTRIBUTE_DIRECTORY ) {
2006-01-26 09:33:45 +03:00
if ( do_list_dirs & & do_this_one ( ctx , f ) ) {
do_list_fn ( ctx , f ) ;
2003-08-13 05:53:07 +04:00
}
if ( do_list_recurse & &
2006-04-24 04:16:51 +04:00
! ISDOT ( f - > name ) & &
! ISDOTDOT ( f - > name ) ) {
2006-01-26 09:33:45 +03:00
char * mask2 ;
2003-08-13 05:53:07 +04:00
char * p ;
2006-01-26 09:33:45 +03:00
mask2 = talloc_strdup ( NULL , mask ) ;
2003-08-13 05:53:07 +04:00
p = strrchr_m ( mask2 , ' \\ ' ) ;
if ( ! p ) return ;
p [ 1 ] = 0 ;
2006-01-26 09:33:45 +03:00
mask2 = talloc_asprintf_append ( mask2 , " %s \\ * " , f - > name ) ;
2003-08-13 05:53:07 +04:00
add_to_do_list_queue ( mask2 ) ;
}
return ;
}
2006-01-26 09:33:45 +03:00
if ( do_this_one ( ctx , f ) ) {
do_list_fn ( ctx , f ) ;
2003-08-13 05:53:07 +04:00
}
}
/****************************************************************************
2004-08-04 17:23:35 +04:00
a wrapper around smbcli_list that adds recursion
2003-08-13 05:53:07 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static void do_list ( struct smbclient_context * ctx , const char * mask , uint16_t attribute ,
void ( * fn ) ( struct smbclient_context * , struct clilist_file_info * ) , BOOL rec , BOOL dirs )
2003-08-13 05:53:07 +04:00
{
static int in_do_list = 0 ;
if ( in_do_list & & rec )
{
fprintf ( stderr , " INTERNAL ERROR: do_list called recursively when the recursive flag is true \n " ) ;
exit ( 1 ) ;
}
in_do_list = 1 ;
do_list_recurse = rec ;
do_list_dirs = dirs ;
do_list_fn = fn ;
if ( rec )
{
init_do_list_queue ( ) ;
add_to_do_list_queue ( mask ) ;
while ( ! do_list_queue_empty ( ) )
{
/*
* Need to copy head so that it doesn ' t become
2004-08-04 17:23:35 +04:00
* invalid inside the call to smbcli_list . This
2003-08-13 05:53:07 +04:00
* would happen if the list were expanded
* during the call .
* Fix from E . Jay Berkenbilt ( ejb @ ql . org )
*/
2006-01-26 09:33:45 +03:00
char * head ;
head = do_list_queue_head ( ) ;
smbcli_list ( ctx - > cli - > tree , head , attribute , do_list_helper , ctx ) ;
2003-08-13 05:53:07 +04:00
remove_do_list_queue_head ( ) ;
if ( ( ! do_list_queue_empty ( ) ) & & ( fn = = display_finfo ) )
{
char * next_file = do_list_queue_head ( ) ;
char * save_ch = 0 ;
if ( ( strlen ( next_file ) > = 2 ) & &
( next_file [ strlen ( next_file ) - 1 ] = = ' * ' ) & &
( next_file [ strlen ( next_file ) - 2 ] = = ' \\ ' ) )
{
save_ch = next_file +
strlen ( next_file ) - 2 ;
* save_ch = ' \0 ' ;
}
d_printf ( " \n %s \n " , next_file ) ;
if ( save_ch )
{
* save_ch = ' \\ ' ;
}
}
}
}
else
{
2006-01-26 09:33:45 +03:00
if ( smbcli_list ( ctx - > cli - > tree , mask , attribute , do_list_helper , ctx ) = = - 1 )
2003-08-13 05:53:07 +04:00
{
2006-01-26 09:33:45 +03:00
d_printf ( " %s listing %s \n " , smbcli_errstr ( ctx - > cli - > tree ) , mask ) ;
2003-08-13 05:53:07 +04:00
}
}
in_do_list = 0 ;
reset_do_list_queue ( ) ;
}
/****************************************************************************
get a directory listing
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_dir ( struct smbclient_context * ctx , const char * * args )
2003-08-13 05:53:07 +04:00
{
2004-05-25 21:24:24 +04:00
uint16_t attribute = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN ;
2006-01-26 09:33:45 +03:00
char * mask ;
2003-08-13 05:53:07 +04:00
int rc ;
dir_total = 0 ;
2006-01-26 09:33:45 +03:00
mask = talloc_strdup ( ctx , ctx - > remote_cur_dir ) ;
2003-08-13 05:53:07 +04:00
if ( mask [ strlen ( mask ) - 1 ] ! = ' \\ ' )
2006-01-26 09:33:45 +03:00
mask = talloc_append_string ( ctx , mask , " \\ " ) ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
if ( args [ 1 ] ) {
mask = talloc_strdup ( ctx , args [ 1 ] ) ;
if ( mask [ 0 ] ! = ' \\ ' )
mask = talloc_append_string ( ctx , mask , " \\ " ) ;
dos_format ( mask ) ;
2003-08-13 05:53:07 +04:00
}
else {
2006-01-26 09:33:45 +03:00
if ( ctx - > cli - > tree - > session - > transport - > negotiate . protocol < =
2004-09-22 09:15:56 +04:00
PROTOCOL_LANMAN1 ) {
2006-01-26 09:33:45 +03:00
mask = talloc_append_string ( ctx , mask , " *.* " ) ;
2004-09-22 09:15:56 +04:00
} else {
2006-01-26 09:33:45 +03:00
mask = talloc_append_string ( ctx , mask , " * " ) ;
2004-09-22 09:15:56 +04:00
}
2003-08-13 05:53:07 +04:00
}
2006-01-26 09:33:45 +03:00
do_list ( ctx , mask , attribute , display_finfo , ctx - > recurse , True ) ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
rc = do_dskattr ( ctx ) ;
2003-08-13 05:53:07 +04:00
DEBUG ( 3 , ( " Total bytes listed: %.0f \n " , dir_total ) ) ;
return rc ;
}
/****************************************************************************
get a directory listing
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_du ( struct smbclient_context * ctx , const char * * args )
2003-08-13 05:53:07 +04:00
{
2004-05-25 21:24:24 +04:00
uint16_t attribute = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN ;
2003-08-13 05:53:07 +04:00
int rc ;
2006-01-26 09:33:45 +03:00
char * mask ;
2003-08-13 05:53:07 +04:00
dir_total = 0 ;
2006-01-26 09:33:45 +03:00
if ( args [ 1 ] ) {
if ( args [ 1 ] [ 0 ] = = ' \\ ' )
mask = talloc_strdup ( ctx , args [ 1 ] ) ;
2003-08-13 05:53:07 +04:00
else
2006-01-26 09:33:45 +03:00
mask = talloc_asprintf ( ctx , " %s \\ %s " , ctx - > remote_cur_dir , args [ 1 ] ) ;
dos_format ( mask ) ;
2003-08-13 05:53:07 +04:00
} else {
2006-01-26 09:33:45 +03:00
mask = talloc_asprintf ( ctx , " %s \\ * " , ctx - > remote_cur_dir ) ;
2003-08-13 05:53:07 +04:00
}
2006-01-26 09:33:45 +03:00
do_list ( ctx , mask , attribute , do_du , ctx - > recurse , True ) ;
talloc_free ( mask ) ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
rc = do_dskattr ( ctx ) ;
2003-08-13 05:53:07 +04:00
d_printf ( " Total number of bytes: %.0f \n " , dir_total ) ;
return rc ;
}
/****************************************************************************
get a file from rname to lname
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int do_get ( struct smbclient_context * ctx , char * rname , const char * lname , BOOL reget )
2003-08-13 05:53:07 +04:00
{
int handle = 0 , fnum ;
BOOL newhandle = False ;
2004-12-04 16:56:25 +03:00
uint8_t * data ;
2003-08-13 05:53:07 +04:00
struct timeval tp_start ;
int read_size = io_bufsize ;
2004-05-25 21:24:24 +04:00
uint16_t attr ;
2003-08-13 05:53:07 +04:00
size_t size ;
off_t start = 0 ;
off_t nread = 0 ;
int rc = 0 ;
GetTimeOfDay ( & tp_start ) ;
2006-01-26 09:33:45 +03:00
if ( ctx - > lowercase ) {
2004-10-28 17:19:39 +04:00
strlower ( discard_const_p ( char , lname ) ) ;
2003-08-13 05:53:07 +04:00
}
2006-01-26 09:33:45 +03:00
fnum = smbcli_open ( ctx - > cli - > tree , rname , O_RDONLY , DENY_NONE ) ;
2003-08-13 05:53:07 +04:00
if ( fnum = = - 1 ) {
2006-01-26 09:33:45 +03:00
d_printf ( " %s opening remote file %s \n " , smbcli_errstr ( ctx - > cli - > tree ) , rname ) ;
2003-08-13 05:53:07 +04:00
return 1 ;
}
if ( ! strcmp ( lname , " - " ) ) {
handle = fileno ( stdout ) ;
} else {
if ( reget ) {
2004-11-01 23:21:54 +03:00
handle = open ( lname , O_WRONLY | O_CREAT , 0644 ) ;
2003-08-13 05:53:07 +04:00
if ( handle > = 0 ) {
2004-11-01 23:21:54 +03:00
start = lseek ( handle , 0 , SEEK_END ) ;
2003-08-13 05:53:07 +04:00
if ( start = = - 1 ) {
d_printf ( " Error seeking local file \n " ) ;
return 1 ;
}
}
} else {
2004-11-01 23:21:54 +03:00
handle = open ( lname , O_WRONLY | O_CREAT | O_TRUNC , 0644 ) ;
2003-08-13 05:53:07 +04:00
}
newhandle = True ;
}
if ( handle < 0 ) {
d_printf ( " Error opening local file %s \n " , lname ) ;
return 1 ;
}
2006-01-26 09:33:45 +03:00
if ( NT_STATUS_IS_ERR ( smbcli_qfileinfo ( ctx - > cli - > tree , fnum ,
2004-02-10 14:33:35 +03:00
& attr , & size , NULL , NULL , NULL , NULL , NULL ) ) & &
2006-01-26 09:33:45 +03:00
NT_STATUS_IS_ERR ( smbcli_getattrE ( ctx - > cli - > tree , fnum ,
2004-02-10 14:33:35 +03:00
& attr , & size , NULL , NULL , NULL ) ) ) {
2006-01-26 09:33:45 +03:00
d_printf ( " getattrib: %s \n " , smbcli_errstr ( ctx - > cli - > tree ) ) ;
2003-08-13 05:53:07 +04:00
return 1 ;
}
DEBUG ( 2 , ( " getting file %s of size %.0f as %s " ,
rname , ( double ) size , lname ) ) ;
2004-12-04 16:56:25 +03:00
if ( ! ( data = ( uint8_t * ) malloc ( read_size ) ) ) {
2003-08-13 05:53:07 +04:00
d_printf ( " malloc fail for size %d \n " , read_size ) ;
2006-01-26 09:33:45 +03:00
smbcli_close ( ctx - > cli - > tree , fnum ) ;
2003-08-13 05:53:07 +04:00
return 1 ;
}
while ( 1 ) {
2006-01-26 09:33:45 +03:00
int n = smbcli_read ( ctx - > cli - > tree , fnum , data , nread + start , read_size ) ;
2003-08-13 05:53:07 +04:00
if ( n < = 0 ) break ;
2006-01-26 09:33:45 +03:00
if ( writefile ( handle , data , n , ctx - > translation ) ! = n ) {
2003-08-13 05:53:07 +04:00
d_printf ( " Error writing local file \n " ) ;
rc = 1 ;
break ;
}
nread + = n ;
}
if ( nread + start < size ) {
DEBUG ( 0 , ( " Short read when getting file %s. Only got %ld bytes. \n " ,
rname , ( long ) nread ) ) ;
rc = 1 ;
}
SAFE_FREE ( data ) ;
2006-01-26 09:33:45 +03:00
if ( NT_STATUS_IS_ERR ( smbcli_close ( ctx - > cli - > tree , fnum ) ) ) {
d_printf ( " Error %s closing remote file \n " , smbcli_errstr ( ctx - > cli - > tree ) ) ;
2003-08-13 05:53:07 +04:00
rc = 1 ;
}
if ( newhandle ) {
close ( handle ) ;
}
2006-01-26 09:33:45 +03:00
if ( ctx - > archive_level > = 2 & & ( attr & FILE_ATTRIBUTE_ARCHIVE ) ) {
smbcli_setatr ( ctx - > cli - > tree , rname , attr & ~ ( uint16_t ) FILE_ATTRIBUTE_ARCHIVE , 0 ) ;
2003-08-13 05:53:07 +04:00
}
{
struct timeval tp_end ;
int this_time ;
GetTimeOfDay ( & tp_end ) ;
this_time =
( tp_end . tv_sec - tp_start . tv_sec ) * 1000 +
( tp_end . tv_usec - tp_start . tv_usec ) / 1000 ;
get_total_time_ms + = this_time ;
get_total_size + = nread ;
DEBUG ( 2 , ( " (%3.1f kb/s) (average %3.1f kb/s) \n " ,
nread / ( 1.024 * this_time + 1.0e-4 ) ,
get_total_size / ( 1.024 * get_total_time_ms ) ) ) ;
}
return rc ;
}
/****************************************************************************
get a file
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_get ( struct smbclient_context * ctx , const char * * args )
2003-08-13 05:53:07 +04:00
{
2006-01-26 09:33:45 +03:00
const char * lname ;
char * rname ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
if ( ! args [ 1 ] ) {
2003-08-13 05:53:07 +04:00
d_printf ( " get <filename> \n " ) ;
return 1 ;
}
2006-01-26 09:33:45 +03:00
rname = talloc_asprintf ( ctx , " %s \\ %s " , ctx - > remote_cur_dir , args [ 1 ] ) ;
if ( args [ 2 ] )
lname = args [ 2 ] ;
else
lname = args [ 1 ] ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
dos_clean_name ( rname ) ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
return do_get ( ctx , rname , lname , False ) ;
2003-08-13 05:53:07 +04:00
}
2004-11-01 23:21:54 +03:00
/****************************************************************************
Put up a yes / no prompt .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL yesno ( char * p )
{
2006-01-26 09:33:45 +03:00
char ans [ 4 ] ;
2004-11-01 23:21:54 +03:00
printf ( " %s " , p ) ;
if ( ! fgets ( ans , sizeof ( ans ) - 1 , stdin ) )
return ( False ) ;
if ( * ans = = ' y ' | | * ans = = ' Y ' )
return ( True ) ;
return ( False ) ;
}
2003-08-13 05:53:07 +04:00
/****************************************************************************
do a mget operation on one file
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static void do_mget ( struct smbclient_context * ctx , struct clilist_file_info * finfo )
2003-08-13 05:53:07 +04:00
{
2006-01-26 09:33:45 +03:00
char * rname ;
char * quest ;
char * mget_mask ;
char * saved_curdir ;
2003-08-13 05:53:07 +04:00
2006-04-24 04:16:51 +04:00
if ( ISDOT ( finfo - > name ) | | ISDOTDOT ( finfo - > name ) )
2003-08-13 05:53:07 +04:00
return ;
2004-11-30 08:37:57 +03:00
if ( finfo - > attrib & FILE_ATTRIBUTE_DIRECTORY )
2006-01-26 09:33:45 +03:00
asprintf ( & quest , " Get directory %s? " , finfo - > name ) ;
2003-08-13 05:53:07 +04:00
else
2006-01-26 09:33:45 +03:00
asprintf ( & quest , " Get file %s? " , finfo - > name ) ;
if ( ctx - > prompt & & ! yesno ( quest ) ) return ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
SAFE_FREE ( quest ) ;
2003-08-13 05:53:07 +04:00
2004-11-30 08:37:57 +03:00
if ( ! ( finfo - > attrib & FILE_ATTRIBUTE_DIRECTORY ) ) {
2006-01-26 09:33:45 +03:00
asprintf ( & rname , " %s%s " , ctx - > remote_cur_dir , finfo - > name ) ;
do_get ( ctx , rname , finfo - > name , False ) ;
SAFE_FREE ( rname ) ;
2003-08-13 05:53:07 +04:00
return ;
}
/* handle directories */
2006-01-26 09:33:45 +03:00
saved_curdir = talloc_strdup ( NULL , ctx - > remote_cur_dir ) ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
ctx - > remote_cur_dir = talloc_asprintf_append ( NULL , " %s \\ " , finfo - > name ) ;
2003-08-13 05:53:07 +04:00
2004-10-28 17:19:39 +04:00
string_replace ( discard_const_p ( char , finfo - > name ) , ' \\ ' , ' / ' ) ;
2006-01-26 09:33:45 +03:00
if ( ctx - > lowercase ) {
2004-10-28 17:19:39 +04:00
strlower ( discard_const_p ( char , finfo - > name ) ) ;
}
2003-08-13 05:53:07 +04:00
2005-02-10 09:36:30 +03:00
if ( ! directory_exist ( finfo - > name ) & &
2003-08-13 05:53:07 +04:00
mkdir ( finfo - > name , 0777 ) ! = 0 ) {
d_printf ( " failed to create directory %s \n " , finfo - > name ) ;
return ;
}
if ( chdir ( finfo - > name ) ! = 0 ) {
d_printf ( " failed to chdir to directory %s \n " , finfo - > name ) ;
return ;
}
2006-01-26 09:33:45 +03:00
mget_mask = talloc_asprintf ( NULL , " %s* " , ctx - > remote_cur_dir ) ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
do_list ( ctx , mget_mask , FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY , do_mget , False , True ) ;
2003-08-13 05:53:07 +04:00
chdir ( " .. " ) ;
2006-01-26 09:33:45 +03:00
talloc_free ( ctx - > remote_cur_dir ) ;
ctx - > remote_cur_dir = saved_curdir ;
2003-08-13 05:53:07 +04:00
}
/****************************************************************************
view the file using the pager
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_more ( struct smbclient_context * ctx , const char * * args )
2003-08-13 05:53:07 +04:00
{
2006-01-26 09:33:45 +03:00
char * rname ;
char * pager_cmd ;
char * lname ;
2003-08-13 05:53:07 +04:00
char * pager ;
int fd ;
int rc = 0 ;
2006-01-26 09:33:45 +03:00
lname = talloc_asprintf ( ctx , " %s/smbmore.XXXXXX " , tmpdir ( ) ) ;
2005-09-23 04:38:22 +04:00
fd = mkstemp ( lname ) ;
2003-08-13 05:53:07 +04:00
if ( fd = = - 1 ) {
d_printf ( " failed to create temporary file for more \n " ) ;
return 1 ;
}
close ( fd ) ;
2006-01-26 09:33:45 +03:00
if ( ! args [ 1 ] ) {
2003-08-13 05:53:07 +04:00
d_printf ( " more <filename> \n " ) ;
unlink ( lname ) ;
return 1 ;
}
2006-01-26 09:33:45 +03:00
rname = talloc_asprintf ( ctx , " %s%s " , ctx - > remote_cur_dir , args [ 1 ] ) ;
2003-08-13 05:53:07 +04:00
dos_clean_name ( rname ) ;
2006-01-26 09:33:45 +03:00
rc = do_get ( ctx , rname , lname , False ) ;
2003-08-13 05:53:07 +04:00
pager = getenv ( " PAGER " ) ;
2006-01-26 09:33:45 +03:00
pager_cmd = talloc_asprintf ( ctx , " %s %s " , ( pager ? pager : PAGER ) , lname ) ;
2003-08-13 05:53:07 +04:00
system ( pager_cmd ) ;
unlink ( lname ) ;
return rc ;
}
/****************************************************************************
do a mget command
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_mget ( struct smbclient_context * ctx , const char * * args )
2003-08-13 05:53:07 +04:00
{
2004-05-25 21:24:24 +04:00
uint16_t attribute = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN ;
2006-01-26 09:33:45 +03:00
char * mget_mask ;
int i ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
if ( ctx - > recurse )
2003-08-13 05:53:07 +04:00
attribute | = FILE_ATTRIBUTE_DIRECTORY ;
2006-01-26 09:33:45 +03:00
for ( i = 1 ; args [ i ] ; i + + ) {
mget_mask = talloc_strdup ( ctx , ctx - > remote_cur_dir ) ;
2003-08-13 05:53:07 +04:00
if ( mget_mask [ strlen ( mget_mask ) - 1 ] ! = ' \\ ' )
2006-01-26 09:33:45 +03:00
mget_mask = talloc_append_string ( ctx , mget_mask , " \\ " ) ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
mget_mask = talloc_strdup ( ctx , args [ i ] ) ;
if ( mget_mask [ 0 ] ! = ' \\ ' )
mget_mask = talloc_append_string ( ctx , mget_mask , " \\ " ) ;
do_list ( ctx , mget_mask , attribute , do_mget , False , True ) ;
2003-08-13 05:53:07 +04:00
}
if ( ! * mget_mask ) {
2006-01-26 09:33:45 +03:00
mget_mask = talloc_asprintf ( ctx , " %s \\ * " , ctx - > remote_cur_dir ) ;
do_list ( ctx , mget_mask , attribute , do_mget , False , True ) ;
2003-08-13 05:53:07 +04:00
}
2006-01-26 09:33:45 +03:00
talloc_free ( mget_mask ) ;
2003-08-13 05:53:07 +04:00
return 0 ;
}
/****************************************************************************
make a directory of name " name "
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static NTSTATUS do_mkdir ( struct smbclient_context * ctx , char * name )
2003-08-13 05:53:07 +04:00
{
2004-02-10 14:33:35 +03:00
NTSTATUS status ;
2006-01-26 09:33:45 +03:00
if ( NT_STATUS_IS_ERR ( status = smbcli_mkdir ( ctx - > cli - > tree , name ) ) ) {
2003-08-13 05:53:07 +04:00
d_printf ( " %s making remote directory %s \n " ,
2006-01-26 09:33:45 +03:00
smbcli_errstr ( ctx - > cli - > tree ) , name ) ;
2004-02-10 14:33:35 +03:00
return status ;
2003-08-13 05:53:07 +04:00
}
2004-02-10 14:33:35 +03:00
return status ;
2003-08-13 05:53:07 +04:00
}
/****************************************************************************
Exit client .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_quit ( struct smbclient_context * ctx , const char * * args )
2003-08-13 05:53:07 +04:00
{
2006-01-26 09:33:45 +03:00
talloc_free ( ctx ) ;
2003-08-13 05:53:07 +04:00
exit ( 0 ) ;
/* NOTREACHED */
return 0 ;
}
/****************************************************************************
make a directory
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_mkdir ( struct smbclient_context * ctx , const char * * args )
2003-08-13 05:53:07 +04:00
{
2006-01-26 14:48:45 +03:00
char * mask , * p ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
if ( ! args [ 1 ] ) {
if ( ! ctx - > recurse )
2003-08-13 05:53:07 +04:00
d_printf ( " mkdir <dirname> \n " ) ;
return 1 ;
}
2006-01-26 09:33:45 +03:00
mask = talloc_asprintf ( ctx , " %s%s " , ctx - > remote_cur_dir , args [ 1 ] ) ;
if ( ctx - > recurse ) {
dos_clean_name ( mask ) ;
trim_string ( mask , " . " , NULL ) ;
2006-01-26 14:48:45 +03:00
for ( p = strtok ( mask , " / \\ " ) ; p ; p = strtok ( p , " / \\ " ) ) {
char * parent = talloc_strndup ( ctx , mask , PTR_DIFF ( p , mask ) ) ;
2006-01-26 09:33:45 +03:00
if ( NT_STATUS_IS_ERR ( smbcli_chkpath ( ctx - > cli - > tree , parent ) ) ) {
do_mkdir ( ctx , parent ) ;
2003-08-13 05:53:07 +04:00
}
2006-01-26 09:33:45 +03:00
2006-01-26 14:48:45 +03:00
talloc_free ( parent ) ;
}
2003-08-13 05:53:07 +04:00
} else {
2006-01-26 14:48:45 +03:00
do_mkdir ( ctx , mask ) ;
2003-08-13 05:53:07 +04:00
}
return 0 ;
}
/****************************************************************************
2006-01-26 09:33:45 +03:00
show 8.3 name of a file
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int cmd_altname ( struct smbclient_context * ctx , const char * * args )
2003-08-13 05:53:07 +04:00
{
2006-01-26 09:33:45 +03:00
const char * altname ;
char * name ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
if ( ! args [ 1 ] ) {
2003-08-13 05:53:07 +04:00
d_printf ( " altname <file> \n " ) ;
return 1 ;
}
2006-01-26 09:33:45 +03:00
name = talloc_asprintf ( ctx , " %s%s " , ctx - > remote_cur_dir , args [ 1 ] ) ;
if ( ! NT_STATUS_IS_OK ( smbcli_qpathinfo_alt_name ( ctx - > cli - > tree , name , & altname ) ) ) {
d_printf ( " %s getting alt name for %s \n " ,
smbcli_errstr ( ctx - > cli - > tree ) , name ) ;
return ( False ) ;
}
d_printf ( " %s \n " , altname ) ;
2003-08-13 05:53:07 +04:00
return 0 ;
}
/****************************************************************************
put a single file
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int do_put ( struct smbclient_context * ctx , char * rname , char * lname , BOOL reput )
2003-08-13 05:53:07 +04:00
{
int fnum ;
XFILE * f ;
size_t start = 0 ;
off_t nread = 0 ;
2004-12-04 16:56:25 +03:00
uint8_t * buf = NULL ;
2003-08-13 05:53:07 +04:00
int maxwrite = io_bufsize ;
int rc = 0 ;
struct timeval tp_start ;
GetTimeOfDay ( & tp_start ) ;
if ( reput ) {
2006-01-26 09:33:45 +03:00
fnum = smbcli_open ( ctx - > cli - > tree , rname , O_RDWR | O_CREAT , DENY_NONE ) ;
2003-08-13 05:53:07 +04:00
if ( fnum > = 0 ) {
2006-01-26 09:33:45 +03:00
if ( NT_STATUS_IS_ERR ( smbcli_qfileinfo ( ctx - > cli - > tree , fnum , NULL , & start , NULL , NULL , NULL , NULL , NULL ) ) & &
NT_STATUS_IS_ERR ( smbcli_getattrE ( ctx - > cli - > tree , fnum , NULL , & start , NULL , NULL , NULL ) ) ) {
d_printf ( " getattrib: %s \n " , smbcli_errstr ( ctx - > cli - > tree ) ) ;
2003-08-13 05:53:07 +04:00
return 1 ;
}
}
} else {
2006-01-26 09:33:45 +03:00
fnum = smbcli_open ( ctx - > cli - > tree , rname , O_RDWR | O_CREAT | O_TRUNC ,
2004-02-08 03:51:07 +03:00
DENY_NONE ) ;
2003-08-13 05:53:07 +04:00
}
if ( fnum = = - 1 ) {
2006-01-26 09:33:45 +03:00
d_printf ( " %s opening remote file %s \n " , smbcli_errstr ( ctx - > cli - > tree ) , rname ) ;
2003-08-13 05:53:07 +04:00
return 1 ;
}
/* allow files to be piped into smbclient
jdblair 24. jun .98
Note that in this case this function will exit ( 0 ) rather
than returning . */
if ( ! strcmp ( lname , " - " ) ) {
f = x_stdin ;
/* size of file is not known */
} else {
f = x_fopen ( lname , O_RDONLY , 0 ) ;
if ( f & & reput ) {
if ( x_tseek ( f , start , SEEK_SET ) = = - 1 ) {
d_printf ( " Error seeking local file \n " ) ;
return 1 ;
}
}
}
if ( ! f ) {
d_printf ( " Error opening local file %s \n " , lname ) ;
return 1 ;
}
DEBUG ( 1 , ( " putting file %s as %s " , lname ,
rname ) ) ;
2004-12-04 16:56:25 +03:00
buf = ( uint8_t * ) malloc ( maxwrite ) ;
2003-08-13 05:53:07 +04:00
if ( ! buf ) {
d_printf ( " ERROR: Not enough memory! \n " ) ;
return 1 ;
}
while ( ! x_feof ( f ) ) {
int n = maxwrite ;
int ret ;
2006-01-26 09:33:45 +03:00
if ( ( n = readfile ( buf , n , f , ctx - > translation ) ) < 1 ) {
2003-08-13 05:53:07 +04:00
if ( ( n = = 0 ) & & x_feof ( f ) )
break ; /* Empty local file. */
d_printf ( " Error reading local file: %s \n " , strerror ( errno ) ) ;
rc = 1 ;
break ;
}
2006-01-26 09:33:45 +03:00
ret = smbcli_write ( ctx - > cli - > tree , fnum , 0 , buf , nread + start , n ) ;
2003-08-13 05:53:07 +04:00
if ( n ! = ret ) {
2006-01-26 09:33:45 +03:00
d_printf ( " Error writing file: %s \n " , smbcli_errstr ( ctx - > cli - > tree ) ) ;
2003-08-13 05:53:07 +04:00
rc = 1 ;
break ;
}
nread + = n ;
}
2006-01-26 09:33:45 +03:00
if ( NT_STATUS_IS_ERR ( smbcli_close ( ctx - > cli - > tree , fnum ) ) ) {
d_printf ( " %s closing remote file %s \n " , smbcli_errstr ( ctx - > cli - > tree ) , rname ) ;
2003-08-13 05:53:07 +04:00
x_fclose ( f ) ;
SAFE_FREE ( buf ) ;
return 1 ;
}
if ( f ! = x_stdin ) {
x_fclose ( f ) ;
}
SAFE_FREE ( buf ) ;
{
struct timeval tp_end ;
int this_time ;
GetTimeOfDay ( & tp_end ) ;
this_time =
( tp_end . tv_sec - tp_start . tv_sec ) * 1000 +
( tp_end . tv_usec - tp_start . tv_usec ) / 1000 ;
put_total_time_ms + = this_time ;
put_total_size + = nread ;
DEBUG ( 1 , ( " (%3.1f kb/s) (average %3.1f kb/s) \n " ,
nread / ( 1.024 * this_time + 1.0e-4 ) ,
put_total_size / ( 1.024 * put_total_time_ms ) ) ) ;
}
if ( f = = x_stdin ) {
2006-01-26 09:33:45 +03:00
talloc_free ( ctx ) ;
2003-08-13 05:53:07 +04:00
exit ( 0 ) ;
}
return rc ;
}
/****************************************************************************
put a file
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_put ( struct smbclient_context * ctx , const char * * args )
2003-08-13 05:53:07 +04:00
{
2006-01-26 09:33:45 +03:00
char * lname ;
char * rname ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
if ( ! args [ 1 ] ) {
2003-08-13 05:53:07 +04:00
d_printf ( " put <filename> \n " ) ;
return 1 ;
}
2006-01-26 09:33:45 +03:00
lname = talloc_asprintf ( ctx , " %s \\ %s " , ctx - > remote_cur_dir , args [ 1 ] ) ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
if ( args [ 2 ] )
rname = talloc_strdup ( ctx , args [ 2 ] ) ;
2003-08-13 05:53:07 +04:00
else
2006-01-26 09:33:45 +03:00
rname = talloc_strdup ( ctx , lname ) ;
2003-08-13 05:53:07 +04:00
dos_clean_name ( rname ) ;
2005-02-10 09:36:30 +03:00
/* allow '-' to represent stdin
jdblair , 24. jun .98 */
if ( ! file_exist ( lname ) & & ( strcmp ( lname , " - " ) ) ) {
d_printf ( " %s does not exist \n " , lname ) ;
return 1 ;
2003-08-13 05:53:07 +04:00
}
2006-01-26 09:33:45 +03:00
return do_put ( ctx , rname , lname , False ) ;
2003-08-13 05:53:07 +04:00
}
/*************************************
File list structure
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static struct file_list {
struct file_list * prev , * next ;
char * file_path ;
BOOL isdir ;
} * file_list ;
/****************************************************************************
Free a file_list structure
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void free_file_list ( struct file_list * list )
{
struct file_list * tmp ;
while ( list )
{
tmp = list ;
DLIST_REMOVE ( list , list ) ;
SAFE_FREE ( tmp - > file_path ) ;
SAFE_FREE ( tmp ) ;
}
}
/****************************************************************************
seek in a directory / file list until you get something that doesn ' t start with
the specified name
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL seek_list ( struct file_list * list , char * name )
{
while ( list ) {
trim_string ( list - > file_path , " ./ " , " \n " ) ;
if ( strncmp ( list - > file_path , name , strlen ( name ) ) ! = 0 ) {
return ( True ) ;
}
list = list - > next ;
}
return ( False ) ;
}
/****************************************************************************
set the file selection mask
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_select ( struct smbclient_context * ctx , const char * * args )
2003-08-13 05:53:07 +04:00
{
2006-01-26 09:33:45 +03:00
talloc_free ( ctx - > fileselection ) ;
ctx - > fileselection = talloc_strdup ( NULL , args [ 1 ] ) ;
2003-08-13 05:53:07 +04:00
return 0 ;
}
2004-11-01 23:21:54 +03:00
/*******************************************************************
A readdir wrapper which just returns the file name .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static const char * readdirname ( DIR * p )
{
struct dirent * ptr ;
char * dname ;
if ( ! p )
return ( NULL ) ;
2004-11-25 23:01:47 +03:00
ptr = ( struct dirent * ) readdir ( p ) ;
2004-11-01 23:21:54 +03:00
if ( ! ptr )
return ( NULL ) ;
dname = ptr - > d_name ;
# ifdef NEXT2
if ( telldir ( p ) < 0 )
return ( NULL ) ;
# endif
# ifdef HAVE_BROKEN_READDIR
/* using /usr/ucb/cc is BAD */
dname = dname - 2 ;
# endif
{
2006-01-26 09:33:45 +03:00
static char * buf ;
2004-11-01 23:21:54 +03:00
int len = NAMLEN ( ptr ) ;
2006-01-26 09:33:45 +03:00
buf = talloc_strndup ( NULL , dname , len ) ;
2004-11-01 23:21:54 +03:00
dname = buf ;
}
return ( dname ) ;
}
2003-08-13 05:53:07 +04:00
/****************************************************************************
Recursive file matching function act as find
match must be always set to True when calling this function
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int file_find ( struct smbclient_context * ctx , struct file_list * * list , const char * directory ,
2003-08-13 05:53:07 +04:00
const char * expression , BOOL match )
{
DIR * dir ;
struct file_list * entry ;
struct stat statbuf ;
int ret ;
char * path ;
BOOL isdir ;
const char * dname ;
dir = opendir ( directory ) ;
if ( ! dir ) return - 1 ;
while ( ( dname = readdirname ( dir ) ) ) {
2006-04-24 04:16:51 +04:00
if ( ISDOT ( dname ) | | ISDOTDOT ( dname ) ) {
continue ;
}
2003-08-13 05:53:07 +04:00
if ( asprintf ( & path , " %s/%s " , directory , dname ) < = 0 ) {
continue ;
}
isdir = False ;
if ( ! match | | ! gen_fnmatch ( expression , dname ) ) {
2006-01-26 09:33:45 +03:00
if ( ctx - > recurse ) {
2003-08-13 05:53:07 +04:00
ret = stat ( path , & statbuf ) ;
if ( ret = = 0 ) {
if ( S_ISDIR ( statbuf . st_mode ) ) {
isdir = True ;
2006-01-26 09:33:45 +03:00
ret = file_find ( ctx , list , path , expression , False ) ;
2003-08-13 05:53:07 +04:00
}
} else {
d_printf ( " file_find: cannot stat file %s \n " , path ) ;
}
if ( ret = = - 1 ) {
SAFE_FREE ( path ) ;
closedir ( dir ) ;
return - 1 ;
}
}
2004-12-03 09:24:38 +03:00
entry = malloc_p ( struct file_list ) ;
2003-08-13 05:53:07 +04:00
if ( ! entry ) {
d_printf ( " Out of memory in file_find \n " ) ;
closedir ( dir ) ;
return - 1 ;
}
entry - > file_path = path ;
entry - > isdir = isdir ;
DLIST_ADD ( * list , entry ) ;
} else {
SAFE_FREE ( path ) ;
}
}
closedir ( dir ) ;
return 0 ;
}
/****************************************************************************
mput some files
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_mput ( struct smbclient_context * ctx , const char * * args )
2003-08-13 05:53:07 +04:00
{
2006-01-26 09:33:45 +03:00
int i ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
for ( i = 1 ; args [ i ] ; i + + ) {
2003-08-13 05:53:07 +04:00
int ret ;
struct file_list * temp_list ;
char * quest , * lname , * rname ;
2006-01-26 09:33:45 +03:00
printf ( " %s \n " , args [ i ] ) ;
2003-08-13 05:53:07 +04:00
file_list = NULL ;
2006-01-26 09:33:45 +03:00
ret = file_find ( ctx , & file_list , " . " , args [ i ] , True ) ;
2003-08-13 05:53:07 +04:00
if ( ret ) {
free_file_list ( file_list ) ;
continue ;
}
quest = NULL ;
lname = NULL ;
rname = NULL ;
for ( temp_list = file_list ; temp_list ;
temp_list = temp_list - > next ) {
SAFE_FREE ( lname ) ;
if ( asprintf ( & lname , " %s/ " , temp_list - > file_path ) < = 0 )
continue ;
trim_string ( lname , " ./ " , " / " ) ;
/* check if it's a directory */
if ( temp_list - > isdir ) {
/* if (!recurse) continue; */
SAFE_FREE ( quest ) ;
if ( asprintf ( & quest , " Put directory %s? " , lname ) < 0 ) break ;
2006-01-26 09:33:45 +03:00
if ( ctx - > prompt & & ! yesno ( quest ) ) { /* No */
2003-08-13 05:53:07 +04:00
/* Skip the directory */
lname [ strlen ( lname ) - 1 ] = ' / ' ;
if ( ! seek_list ( temp_list , lname ) )
break ;
} else { /* Yes */
SAFE_FREE ( rname ) ;
2006-01-26 09:33:45 +03:00
if ( asprintf ( & rname , " %s%s " , ctx - > remote_cur_dir , lname ) < 0 ) break ;
2003-08-13 05:53:07 +04:00
dos_format ( rname ) ;
2006-01-26 09:33:45 +03:00
if ( NT_STATUS_IS_ERR ( smbcli_chkpath ( ctx - > cli - > tree , rname ) ) & &
NT_STATUS_IS_ERR ( do_mkdir ( ctx , rname ) ) ) {
2003-08-13 05:53:07 +04:00
DEBUG ( 0 , ( " Unable to make dir, skipping... " ) ) ;
/* Skip the directory */
lname [ strlen ( lname ) - 1 ] = ' / ' ;
if ( ! seek_list ( temp_list , lname ) )
break ;
}
}
continue ;
} else {
SAFE_FREE ( quest ) ;
if ( asprintf ( & quest , " Put file %s? " , lname ) < 0 ) break ;
2006-01-26 09:33:45 +03:00
if ( ctx - > prompt & & ! yesno ( quest ) ) /* No */
2003-08-13 05:53:07 +04:00
continue ;
/* Yes */
SAFE_FREE ( rname ) ;
2006-01-26 09:33:45 +03:00
if ( asprintf ( & rname , " %s%s " , ctx - > remote_cur_dir , lname ) < 0 ) break ;
2003-08-13 05:53:07 +04:00
}
dos_format ( rname ) ;
2006-01-26 09:33:45 +03:00
do_put ( ctx , rname , lname , False ) ;
2003-08-13 05:53:07 +04:00
}
free_file_list ( file_list ) ;
SAFE_FREE ( quest ) ;
SAFE_FREE ( lname ) ;
SAFE_FREE ( rname ) ;
}
return 0 ;
}
/****************************************************************************
print a file
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_print ( struct smbclient_context * ctx , const char * * args )
2003-08-13 05:53:07 +04:00
{
2006-01-26 09:33:45 +03:00
char * lname , * rname ;
2003-08-13 05:53:07 +04:00
char * p ;
2006-01-26 09:33:45 +03:00
if ( ! args [ 1 ] ) {
2003-08-13 05:53:07 +04:00
d_printf ( " print <filename> \n " ) ;
return 1 ;
}
2006-01-26 09:33:45 +03:00
lname = talloc_strdup ( ctx , args [ 1 ] ) ;
rname = talloc_strdup ( ctx , lname ) ;
2003-08-13 05:53:07 +04:00
p = strrchr_m ( rname , ' / ' ) ;
if ( p ) {
slprintf ( rname , sizeof ( rname ) - 1 , " %s-%d " , p + 1 , ( int ) getpid ( ) ) ;
}
if ( strequal ( lname , " - " ) ) {
slprintf ( rname , sizeof ( rname ) - 1 , " stdin-%d " , ( int ) getpid ( ) ) ;
}
2006-01-26 09:33:45 +03:00
return do_put ( ctx , rname , lname , False ) ;
2003-08-13 05:53:07 +04:00
}
2006-01-26 09:33:45 +03:00
static int cmd_rewrite ( struct smbclient_context * ctx , const char * * args )
2003-08-13 05:53:07 +04:00
{
2006-01-26 09:33:45 +03:00
d_printf ( " REWRITE: command not implemented (FIXME!) \n " ) ;
2003-08-13 05:53:07 +04:00
return 0 ;
}
/****************************************************************************
delete some files
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_del ( struct smbclient_context * ctx , const char * * args )
2003-08-13 05:53:07 +04:00
{
2006-01-26 09:33:45 +03:00
char * mask ;
2004-05-25 21:24:24 +04:00
uint16_t attribute = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
if ( ctx - > recurse )
2003-08-13 05:53:07 +04:00
attribute | = FILE_ATTRIBUTE_DIRECTORY ;
2006-01-26 09:33:45 +03:00
if ( ! args [ 1 ] ) {
2003-08-13 05:53:07 +04:00
d_printf ( " del <filename> \n " ) ;
return 1 ;
}
2006-01-26 09:33:45 +03:00
mask = talloc_asprintf ( ctx , " %s%s " , ctx - > remote_cur_dir , args [ 1 ] ) ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
if ( NT_STATUS_IS_ERR ( smbcli_unlink ( ctx - > cli - > tree , mask ) ) ) {
d_printf ( " %s deleting remote file %s \n " , smbcli_errstr ( ctx - > cli - > tree ) , mask ) ;
2004-09-22 09:15:56 +04:00
}
2003-08-13 05:53:07 +04:00
return 0 ;
}
/****************************************************************************
delete a whole directory tree
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_deltree ( struct smbclient_context * ctx , const char * * args )
2003-08-13 05:53:07 +04:00
{
2006-01-26 09:33:45 +03:00
char * dname ;
2003-08-13 05:53:07 +04:00
int ret ;
2006-01-26 09:33:45 +03:00
if ( ! args [ 1 ] ) {
2003-08-13 05:53:07 +04:00
d_printf ( " deltree <dirname> \n " ) ;
return 1 ;
}
2006-01-26 09:33:45 +03:00
dname = talloc_asprintf ( ctx , " %s%s " , ctx - > remote_cur_dir , args [ 1 ] ) ;
2005-05-03 17:02:14 +04:00
2006-01-26 09:33:45 +03:00
ret = smbcli_deltree ( ctx - > cli - > tree , dname ) ;
2003-08-13 05:53:07 +04:00
if ( ret = = - 1 ) {
2006-01-26 09:33:45 +03:00
printf ( " Failed to delete tree %s - %s \n " , dname , smbcli_errstr ( ctx - > cli - > tree ) ) ;
2003-08-13 05:53:07 +04:00
return - 1 ;
}
printf ( " Deleted %d files in %s \n " , ret , dname ) ;
return 0 ;
}
2005-05-03 13:57:34 +04:00
typedef struct {
2005-05-03 17:02:14 +04:00
const char * level_name ;
enum smb_fsinfo_level level ;
2005-05-03 13:57:34 +04:00
} fsinfo_level_t ;
fsinfo_level_t fsinfo_levels [ ] = {
2005-05-03 17:02:14 +04:00
{ " dskattr " , RAW_QFS_DSKATTR } ,
{ " allocation " , RAW_QFS_ALLOCATION } ,
{ " volume " , RAW_QFS_VOLUME } ,
{ " volumeinfo " , RAW_QFS_VOLUME_INFO } ,
{ " sizeinfo " , RAW_QFS_SIZE_INFO } ,
{ " deviceinfo " , RAW_QFS_DEVICE_INFO } ,
{ " attributeinfo " , RAW_QFS_ATTRIBUTE_INFO } ,
{ " unixinfo " , RAW_QFS_UNIX_INFO } ,
{ " volume-information " , RAW_QFS_VOLUME_INFORMATION } ,
{ " size-information " , RAW_QFS_SIZE_INFORMATION } ,
{ " device-information " , RAW_QFS_DEVICE_INFORMATION } ,
{ " attribute-information " , RAW_QFS_ATTRIBUTE_INFORMATION } ,
{ " quota-information " , RAW_QFS_QUOTA_INFORMATION } ,
{ " fullsize-information " , RAW_QFS_FULL_SIZE_INFORMATION } ,
{ " objectid " , RAW_QFS_OBJECTID_INFORMATION } ,
{ NULL , RAW_QFS_GENERIC }
2005-05-03 13:57:34 +04:00
} ;
2005-05-03 17:02:14 +04:00
2005-05-03 13:57:34 +04:00
2006-01-26 09:33:45 +03:00
static int cmd_fsinfo ( struct smbclient_context * ctx , const char * * args )
2005-05-03 13:57:34 +04:00
{
2005-05-03 17:02:14 +04:00
union smb_fsinfo fsinfo ;
NTSTATUS status ;
fsinfo_level_t * fsinfo_level ;
2006-01-26 09:33:45 +03:00
if ( ! args [ 1 ] ) {
2005-05-03 17:02:14 +04:00
d_printf ( " fsinfo <level>, where level is one of following: \n " ) ;
fsinfo_level = fsinfo_levels ;
while ( fsinfo_level - > level_name ) {
d_printf ( " %s \n " , fsinfo_level - > level_name ) ;
fsinfo_level + + ;
}
return 1 ;
}
fsinfo_level = fsinfo_levels ;
2006-01-26 09:33:45 +03:00
while ( fsinfo_level - > level_name & & ! strequal ( args [ 1 ] , fsinfo_level - > level_name ) ) {
2005-05-03 17:02:14 +04:00
fsinfo_level + + ;
}
2005-05-03 13:57:34 +04:00
2005-05-03 17:02:14 +04:00
if ( ! fsinfo_level - > level_name ) {
d_printf ( " wrong level name! \n " ) ;
return 1 ;
}
2005-05-03 13:57:34 +04:00
2005-05-03 17:02:14 +04:00
fsinfo . generic . level = fsinfo_level - > level ;
2006-01-26 09:33:45 +03:00
status = smb_raw_fsinfo ( ctx - > cli - > tree , ctx , & fsinfo ) ;
2005-05-03 17:02:14 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
d_printf ( " fsinfo-level-%s - %s \n " , fsinfo_level - > level_name , nt_errstr ( status ) ) ;
2006-01-26 09:33:45 +03:00
return 1 ;
2005-05-03 17:02:14 +04:00
}
d_printf ( " fsinfo-level-%s: \n " , fsinfo_level - > level_name ) ;
switch ( fsinfo . generic . level ) {
case RAW_QFS_DSKATTR :
d_printf ( " \t units_total: %hu \n " ,
( unsigned short ) fsinfo . dskattr . out . units_total ) ;
d_printf ( " \t blocks_per_unit: %hu \n " ,
( unsigned short ) fsinfo . dskattr . out . blocks_per_unit ) ;
d_printf ( " \t blocks_size: %hu \n " ,
( unsigned short ) fsinfo . dskattr . out . block_size ) ;
d_printf ( " \t units_free: %hu \n " ,
( unsigned short ) fsinfo . dskattr . out . units_free ) ;
break ;
case RAW_QFS_ALLOCATION :
d_printf ( " \t fs_id: %lu \n " ,
( unsigned long ) fsinfo . allocation . out . fs_id ) ;
d_printf ( " \t sectors_per_unit: %lu \n " ,
( unsigned long ) fsinfo . allocation . out . sectors_per_unit ) ;
d_printf ( " \t total_alloc_units: %lu \n " ,
( unsigned long ) fsinfo . allocation . out . total_alloc_units ) ;
d_printf ( " \t avail_alloc_units: %lu \n " ,
( unsigned long ) fsinfo . allocation . out . avail_alloc_units ) ;
d_printf ( " \t bytes_per_sector: %hu \n " ,
( unsigned short ) fsinfo . allocation . out . bytes_per_sector ) ;
break ;
case RAW_QFS_VOLUME :
d_printf ( " \t serial_number: %lu \n " ,
( unsigned long ) fsinfo . volume . out . serial_number ) ;
d_printf ( " \t volume_name: %s \n " , fsinfo . volume . out . volume_name . s ) ;
break ;
case RAW_QFS_VOLUME_INFO :
case RAW_QFS_VOLUME_INFORMATION :
d_printf ( " \t create_time: %s \n " ,
2006-01-26 09:33:45 +03:00
nt_time_string ( ctx , fsinfo . volume_info . out . create_time ) ) ;
2005-05-03 17:02:14 +04:00
d_printf ( " \t serial_number: %lu \n " ,
( unsigned long ) fsinfo . volume_info . out . serial_number ) ;
d_printf ( " \t volume_name: %s \n " , fsinfo . volume_info . out . volume_name . s ) ;
break ;
case RAW_QFS_SIZE_INFO :
case RAW_QFS_SIZE_INFORMATION :
d_printf ( " \t total_alloc_units: %llu \n " ,
( unsigned long long ) fsinfo . size_info . out . total_alloc_units ) ;
d_printf ( " \t avail_alloc_units: %llu \n " ,
( unsigned long long ) fsinfo . size_info . out . avail_alloc_units ) ;
d_printf ( " \t sectors_per_unit: %lu \n " ,
( unsigned long ) fsinfo . size_info . out . sectors_per_unit ) ;
d_printf ( " \t bytes_per_sector: %lu \n " ,
( unsigned long ) fsinfo . size_info . out . bytes_per_sector ) ;
break ;
case RAW_QFS_DEVICE_INFO :
case RAW_QFS_DEVICE_INFORMATION :
d_printf ( " \t device_type: %lu \n " ,
( unsigned long ) fsinfo . device_info . out . device_type ) ;
d_printf ( " \t characteristics: 0x%lx \n " ,
( unsigned long ) fsinfo . device_info . out . characteristics ) ;
break ;
case RAW_QFS_ATTRIBUTE_INFORMATION :
case RAW_QFS_ATTRIBUTE_INFO :
d_printf ( " \t fs_attr: 0x%lx \n " ,
( unsigned long ) fsinfo . attribute_info . out . fs_attr ) ;
d_printf ( " \t max_file_component_length: %lu \n " ,
( unsigned long ) fsinfo . attribute_info . out . max_file_component_length ) ;
d_printf ( " \t fs_type: %s \n " , fsinfo . attribute_info . out . fs_type . s ) ;
break ;
case RAW_QFS_UNIX_INFO :
d_printf ( " \t major_version: %hu \n " ,
( unsigned short ) fsinfo . unix_info . out . major_version ) ;
d_printf ( " \t minor_version: %hu \n " ,
( unsigned short ) fsinfo . unix_info . out . minor_version ) ;
d_printf ( " \t capability: 0x%llx \n " ,
( unsigned long long ) fsinfo . unix_info . out . capability ) ;
break ;
case RAW_QFS_QUOTA_INFORMATION :
d_printf ( " \t unknown[3]: [%llu,%llu,%llu] \n " ,
( unsigned long long ) fsinfo . quota_information . out . unknown [ 0 ] ,
( unsigned long long ) fsinfo . quota_information . out . unknown [ 1 ] ,
( unsigned long long ) fsinfo . quota_information . out . unknown [ 2 ] ) ;
d_printf ( " \t quota_soft: %llu \n " ,
( unsigned long long ) fsinfo . quota_information . out . quota_soft ) ;
d_printf ( " \t quota_hard: %llu \n " ,
( unsigned long long ) fsinfo . quota_information . out . quota_hard ) ;
d_printf ( " \t quota_flags: 0x%llx \n " ,
( unsigned long long ) fsinfo . quota_information . out . quota_flags ) ;
break ;
case RAW_QFS_FULL_SIZE_INFORMATION :
d_printf ( " \t total_alloc_units: %llu \n " ,
( unsigned long long ) fsinfo . full_size_information . out . total_alloc_units ) ;
d_printf ( " \t call_avail_alloc_units: %llu \n " ,
( unsigned long long ) fsinfo . full_size_information . out . call_avail_alloc_units ) ;
d_printf ( " \t actual_avail_alloc_units: %llu \n " ,
( unsigned long long ) fsinfo . full_size_information . out . actual_avail_alloc_units ) ;
d_printf ( " \t sectors_per_unit: %lu \n " ,
( unsigned long ) fsinfo . full_size_information . out . sectors_per_unit ) ;
d_printf ( " \t bytes_per_sector: %lu \n " ,
( unsigned long ) fsinfo . full_size_information . out . bytes_per_sector ) ;
break ;
case RAW_QFS_OBJECTID_INFORMATION :
d_printf ( " \t GUID: %s \n " ,
2006-01-26 09:33:45 +03:00
GUID_string ( ctx , & fsinfo . objectid_information . out . guid ) ) ;
2005-05-03 17:02:14 +04:00
d_printf ( " \t unknown[6]: [%llu,%llu,%llu,%llu,%llu,%llu] \n " ,
( unsigned long long ) fsinfo . objectid_information . out . unknown [ 0 ] ,
( unsigned long long ) fsinfo . objectid_information . out . unknown [ 2 ] ,
( unsigned long long ) fsinfo . objectid_information . out . unknown [ 3 ] ,
( unsigned long long ) fsinfo . objectid_information . out . unknown [ 4 ] ,
( unsigned long long ) fsinfo . objectid_information . out . unknown [ 5 ] ,
( unsigned long long ) fsinfo . objectid_information . out . unknown [ 6 ] ) ;
break ;
2005-11-10 06:48:56 +03:00
case RAW_QFS_GENERIC :
d_printf ( " \t wrong level returned \n " ) ;
break ;
2005-05-03 17:02:14 +04:00
}
2005-05-03 13:57:34 +04:00
2006-01-26 09:33:45 +03:00
return 0 ;
2005-05-03 13:57:34 +04:00
}
2003-08-13 05:53:07 +04:00
/****************************************************************************
show as much information as possible about a file
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_allinfo ( struct smbclient_context * ctx , const char * * args )
2003-08-13 05:53:07 +04:00
{
2006-01-26 09:33:45 +03:00
char * fname ;
2003-08-13 05:53:07 +04:00
union smb_fileinfo finfo ;
NTSTATUS status ;
2006-01-26 09:33:45 +03:00
if ( ! args [ 1 ] ) {
2003-08-14 08:14:49 +04:00
d_printf ( " allinfo <filename> \n " ) ;
2003-08-13 05:53:07 +04:00
return 1 ;
}
2006-01-26 09:33:45 +03:00
fname = talloc_asprintf ( ctx , " %s%s " , ctx - > remote_cur_dir , args [ 1 ] ) ;
2003-08-13 05:53:07 +04:00
/* first a ALL_INFO QPATHINFO */
finfo . generic . level = RAW_FILEINFO_ALL_INFO ;
2006-03-13 01:48:25 +03:00
finfo . generic . in . file . path = fname ;
2006-01-26 09:33:45 +03:00
status = smb_raw_pathinfo ( ctx - > cli - > tree , ctx , & finfo ) ;
2003-08-13 05:53:07 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
d_printf ( " %s - %s \n " , fname , nt_errstr ( status ) ) ;
2006-01-26 09:33:45 +03:00
return 1 ;
2003-08-13 05:53:07 +04:00
}
2006-01-26 09:33:45 +03:00
d_printf ( " \t create_time: %s \n " , nt_time_string ( ctx , finfo . all_info . out . create_time ) ) ;
d_printf ( " \t access_time: %s \n " , nt_time_string ( ctx , finfo . all_info . out . access_time ) ) ;
d_printf ( " \t write_time: %s \n " , nt_time_string ( ctx , finfo . all_info . out . write_time ) ) ;
d_printf ( " \t change_time: %s \n " , nt_time_string ( ctx , finfo . all_info . out . change_time ) ) ;
2003-08-13 05:53:07 +04:00
d_printf ( " \t attrib: 0x%x \n " , finfo . all_info . out . attrib ) ;
d_printf ( " \t alloc_size: %lu \n " , ( unsigned long ) finfo . all_info . out . alloc_size ) ;
d_printf ( " \t size: %lu \n " , ( unsigned long ) finfo . all_info . out . size ) ;
d_printf ( " \t nlink: %u \n " , finfo . all_info . out . nlink ) ;
d_printf ( " \t delete_pending: %u \n " , finfo . all_info . out . delete_pending ) ;
d_printf ( " \t directory: %u \n " , finfo . all_info . out . directory ) ;
d_printf ( " \t ea_size: %u \n " , finfo . all_info . out . ea_size ) ;
d_printf ( " \t fname: '%s' \n " , finfo . all_info . out . fname . s ) ;
/* 8.3 name if any */
finfo . generic . level = RAW_FILEINFO_ALT_NAME_INFO ;
2006-01-26 09:33:45 +03:00
status = smb_raw_pathinfo ( ctx - > cli - > tree , ctx , & finfo ) ;
2003-08-13 05:53:07 +04:00
if ( NT_STATUS_IS_OK ( status ) ) {
d_printf ( " \t alt_name: %s \n " , finfo . alt_name_info . out . fname . s ) ;
}
2003-09-02 08:37:33 +04:00
/* file_id if available */
2003-08-13 05:53:07 +04:00
finfo . generic . level = RAW_FILEINFO_INTERNAL_INFORMATION ;
2006-01-26 09:33:45 +03:00
status = smb_raw_pathinfo ( ctx - > cli - > tree , ctx , & finfo ) ;
2003-08-13 05:53:07 +04:00
if ( NT_STATUS_IS_OK ( status ) ) {
2003-11-28 12:05:44 +03:00
d_printf ( " \t file_id %.0f \n " ,
( double ) finfo . internal_information . out . file_id ) ;
2003-08-13 05:53:07 +04:00
}
/* the EAs, if any */
finfo . generic . level = RAW_FILEINFO_ALL_EAS ;
2006-01-26 09:33:45 +03:00
status = smb_raw_pathinfo ( ctx - > cli - > tree , ctx , & finfo ) ;
2003-08-13 05:53:07 +04:00
if ( NT_STATUS_IS_OK ( status ) ) {
int i ;
for ( i = 0 ; i < finfo . all_eas . out . num_eas ; i + + ) {
2004-12-26 11:41:11 +03:00
d_printf ( " \t EA[%d] flags=%d len=%d '%s' \n " , i ,
2003-08-13 05:53:07 +04:00
finfo . all_eas . out . eas [ i ] . flags ,
2005-07-17 13:20:52 +04:00
( int ) finfo . all_eas . out . eas [ i ] . value . length ,
2004-12-26 11:41:11 +03:00
finfo . all_eas . out . eas [ i ] . name . s ) ;
2003-08-13 05:53:07 +04:00
}
}
/* streams, if available */
finfo . generic . level = RAW_FILEINFO_STREAM_INFO ;
2006-01-26 09:33:45 +03:00
status = smb_raw_pathinfo ( ctx - > cli - > tree , ctx , & finfo ) ;
2003-08-13 05:53:07 +04:00
if ( NT_STATUS_IS_OK ( status ) ) {
int i ;
for ( i = 0 ; i < finfo . stream_info . out . num_streams ; i + + ) {
d_printf ( " \t stream %d: \n " , i ) ;
d_printf ( " \t \t size %ld \n " ,
( long ) finfo . stream_info . out . streams [ i ] . size ) ;
d_printf ( " \t \t alloc size %ld \n " ,
( long ) finfo . stream_info . out . streams [ i ] . alloc_size ) ;
d_printf ( " \t \t name %s \n " , finfo . stream_info . out . streams [ i ] . stream_name . s ) ;
}
}
/* dev/inode if available */
finfo . generic . level = RAW_FILEINFO_COMPRESSION_INFORMATION ;
2006-01-26 09:33:45 +03:00
status = smb_raw_pathinfo ( ctx - > cli - > tree , ctx , & finfo ) ;
2003-08-13 05:53:07 +04:00
if ( NT_STATUS_IS_OK ( status ) ) {
d_printf ( " \t compressed size %ld \n " , ( long ) finfo . compression_info . out . compressed_size ) ;
d_printf ( " \t format %ld \n " , ( long ) finfo . compression_info . out . format ) ;
d_printf ( " \t unit_shift %ld \n " , ( long ) finfo . compression_info . out . unit_shift ) ;
d_printf ( " \t chunk_shift %ld \n " , ( long ) finfo . compression_info . out . chunk_shift ) ;
d_printf ( " \t cluster_shift %ld \n " , ( long ) finfo . compression_info . out . cluster_shift ) ;
}
2006-01-26 09:33:45 +03:00
return 0 ;
2003-08-13 05:53:07 +04:00
}
2004-12-26 11:41:11 +03:00
/****************************************************************************
shows EA contents
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_eainfo ( struct smbclient_context * ctx , const char * * args )
2004-12-26 11:41:11 +03:00
{
2006-01-26 09:33:45 +03:00
char * fname ;
2004-12-26 11:41:11 +03:00
union smb_fileinfo finfo ;
NTSTATUS status ;
int i ;
2006-01-26 09:33:45 +03:00
if ( ! args [ 1 ] ) {
2004-12-26 11:41:11 +03:00
d_printf ( " eainfo <filename> \n " ) ;
return 1 ;
}
2006-01-26 09:33:45 +03:00
fname = talloc_strdup ( ctx , args [ 1 ] ) ;
2004-12-26 11:41:11 +03:00
finfo . generic . level = RAW_FILEINFO_ALL_EAS ;
2006-03-13 01:48:25 +03:00
finfo . generic . in . file . path = fname ;
2006-01-26 09:33:45 +03:00
status = smb_raw_pathinfo ( ctx - > cli - > tree , ctx , & finfo ) ;
2004-12-26 11:41:11 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
d_printf ( " RAW_FILEINFO_ALL_EAS - %s \n " , nt_errstr ( status ) ) ;
return 1 ;
}
d_printf ( " %s has %d EAs \n " , fname , finfo . all_eas . out . num_eas ) ;
for ( i = 0 ; i < finfo . all_eas . out . num_eas ; i + + ) {
d_printf ( " \t EA[%d] flags=%d len=%d '%s' \n " , i ,
finfo . all_eas . out . eas [ i ] . flags ,
2005-07-17 13:20:52 +04:00
( int ) finfo . all_eas . out . eas [ i ] . value . length ,
2004-12-26 11:41:11 +03:00
finfo . all_eas . out . eas [ i ] . name . s ) ;
fflush ( stdout ) ;
dump_data ( 0 ,
finfo . all_eas . out . eas [ i ] . value . data ,
finfo . all_eas . out . eas [ i ] . value . length ) ;
}
2006-01-26 09:33:45 +03:00
return 0 ;
2004-12-26 11:41:11 +03:00
}
2003-10-30 11:32:26 +03:00
/****************************************************************************
show any ACL on a file
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_acl ( struct smbclient_context * ctx , const char * * args )
2003-10-30 11:32:26 +03:00
{
2006-01-26 09:33:45 +03:00
char * fname ;
2004-11-18 04:41:43 +03:00
union smb_fileinfo query ;
2003-10-30 11:32:26 +03:00
NTSTATUS status ;
int fnum ;
2006-01-26 09:33:45 +03:00
if ( ! args [ 1 ] ) {
2003-10-30 11:32:26 +03:00
d_printf ( " acl <filename> \n " ) ;
return 1 ;
}
2006-01-26 09:33:45 +03:00
fname = talloc_asprintf ( ctx , " %s%s " , ctx - > remote_cur_dir , args [ 1 ] ) ;
2003-10-30 11:32:26 +03:00
2006-01-26 09:33:45 +03:00
fnum = smbcli_nt_create_full ( ctx - > cli - > tree , fname , 0 ,
2004-12-31 06:54:49 +03:00
SEC_STD_READ_CONTROL ,
0 ,
NTCREATEX_SHARE_ACCESS_DELETE |
NTCREATEX_SHARE_ACCESS_READ |
NTCREATEX_SHARE_ACCESS_WRITE ,
NTCREATEX_DISP_OPEN ,
0 , 0 ) ;
2003-10-30 11:32:26 +03:00
if ( fnum = = - 1 ) {
2006-01-26 09:33:45 +03:00
d_printf ( " %s - %s \n " , fname , smbcli_errstr ( ctx - > cli - > tree ) ) ;
2003-10-30 11:32:26 +03:00
return - 1 ;
}
2004-11-18 04:41:43 +03:00
query . query_secdesc . level = RAW_FILEINFO_SEC_DESC ;
2006-03-13 01:48:25 +03:00
query . query_secdesc . in . file . fnum = fnum ;
2006-03-10 23:49:20 +03:00
query . query_secdesc . in . secinfo_flags = 0x7 ;
2003-10-30 11:32:26 +03:00
2006-01-26 09:33:45 +03:00
status = smb_raw_fileinfo ( ctx - > cli - > tree , ctx , & query ) ;
2003-10-30 11:32:26 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
d_printf ( " %s - %s \n " , fname , nt_errstr ( status ) ) ;
2006-01-26 09:33:45 +03:00
return 1 ;
2003-10-30 11:32:26 +03:00
}
2004-11-18 04:41:43 +03:00
NDR_PRINT_DEBUG ( security_descriptor , query . query_secdesc . out . sd ) ;
2004-08-20 04:03:13 +04:00
2006-01-26 09:33:45 +03:00
return 0 ;
2003-10-30 11:32:26 +03:00
}
2004-12-06 10:12:38 +03:00
/****************************************************************************
2004-12-15 01:24:56 +03:00
lookup a name or sid
2004-12-06 10:12:38 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_lookup ( struct smbclient_context * ctx , const char * * args )
2004-12-06 10:12:38 +03:00
{
NTSTATUS status ;
2004-12-15 01:24:56 +03:00
struct dom_sid * sid ;
2004-12-06 10:12:38 +03:00
2006-01-26 09:33:45 +03:00
if ( ! args [ 1 ] ) {
2004-12-21 06:29:09 +03:00
d_printf ( " lookup <sid|name> \n " ) ;
2004-12-06 10:12:38 +03:00
return 1 ;
}
2006-01-26 09:33:45 +03:00
sid = dom_sid_parse_talloc ( ctx , args [ 1 ] ) ;
2004-12-15 01:24:56 +03:00
if ( sid = = NULL ) {
const char * sidstr ;
2006-01-26 09:33:45 +03:00
status = smblsa_lookup_name ( ctx - > cli , args [ 1 ] , ctx , & sidstr ) ;
2004-12-15 01:24:56 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
d_printf ( " lsa_LookupNames - %s \n " , nt_errstr ( status ) ) ;
return 1 ;
}
2004-12-06 10:12:38 +03:00
2004-12-15 01:24:56 +03:00
d_printf ( " %s \n " , sidstr ) ;
} else {
const char * name ;
2006-01-26 09:33:45 +03:00
status = smblsa_lookup_sid ( ctx - > cli , args [ 1 ] , ctx , & name ) ;
2004-12-15 01:24:56 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
d_printf ( " lsa_LookupSids - %s \n " , nt_errstr ( status ) ) ;
return 1 ;
}
2004-12-06 10:12:38 +03:00
2004-12-15 01:24:56 +03:00
d_printf ( " %s \n " , name ) ;
2004-12-06 10:12:38 +03:00
}
return 0 ;
}
/****************************************************************************
show privileges for a user
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_privileges ( struct smbclient_context * ctx , const char * * args )
2004-12-06 10:12:38 +03:00
{
NTSTATUS status ;
struct dom_sid * sid ;
struct lsa_RightSet rights ;
unsigned i ;
2006-01-26 09:33:45 +03:00
if ( ! args [ 1 ] ) {
2004-12-14 09:31:20 +03:00
d_printf ( " privileges <sid|name> \n " ) ;
2004-12-06 10:12:38 +03:00
return 1 ;
}
2006-01-26 09:33:45 +03:00
sid = dom_sid_parse_talloc ( ctx , args [ 1 ] ) ;
2004-12-06 10:12:38 +03:00
if ( sid = = NULL ) {
const char * sid_str ;
2006-01-26 09:33:45 +03:00
status = smblsa_lookup_name ( ctx - > cli , args [ 1 ] , ctx , & sid_str ) ;
2004-12-06 10:12:38 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
d_printf ( " lsa_LookupNames - %s \n " , nt_errstr ( status ) ) ;
return 1 ;
}
2006-01-26 09:33:45 +03:00
sid = dom_sid_parse_talloc ( ctx , sid_str ) ;
2004-12-06 10:12:38 +03:00
}
2006-01-26 09:33:45 +03:00
status = smblsa_sid_privileges ( ctx - > cli , sid , ctx , & rights ) ;
2004-12-06 10:12:38 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
d_printf ( " lsa_EnumAccountRights - %s \n " , nt_errstr ( status ) ) ;
return 1 ;
}
for ( i = 0 ; i < rights . count ; i + + ) {
d_printf ( " \t %s \n " , rights . names [ i ] . string ) ;
}
return 0 ;
}
2003-10-30 11:32:26 +03:00
2004-12-14 09:31:20 +03:00
/****************************************************************************
add privileges for a user
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_addprivileges ( struct smbclient_context * ctx , const char * * args )
2004-12-14 09:31:20 +03:00
{
NTSTATUS status ;
struct dom_sid * sid ;
struct lsa_RightSet rights ;
2006-01-26 09:33:45 +03:00
int i ;
2004-12-14 09:31:20 +03:00
2006-01-26 09:33:45 +03:00
if ( ! args [ 1 ] ) {
2004-12-21 06:29:09 +03:00
d_printf ( " addprivileges <sid|name> <privilege...> \n " ) ;
2004-12-14 09:31:20 +03:00
return 1 ;
}
2006-01-26 09:33:45 +03:00
sid = dom_sid_parse_talloc ( ctx , args [ 1 ] ) ;
2004-12-14 09:31:20 +03:00
if ( sid = = NULL ) {
const char * sid_str ;
2006-01-26 09:33:45 +03:00
status = smblsa_lookup_name ( ctx - > cli , args [ 1 ] , ctx , & sid_str ) ;
2004-12-14 09:31:20 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
d_printf ( " lsa_LookupNames - %s \n " , nt_errstr ( status ) ) ;
return 1 ;
}
2006-01-26 09:33:45 +03:00
sid = dom_sid_parse_talloc ( ctx , sid_str ) ;
2004-12-14 09:31:20 +03:00
}
ZERO_STRUCT ( rights ) ;
2006-01-26 09:33:45 +03:00
for ( i = 2 ; args [ i ] ; i + + ) {
rights . names = talloc_realloc ( ctx , rights . names ,
2006-01-18 19:01:13 +03:00
struct lsa_StringLarge , rights . count + 1 ) ;
2006-01-26 09:33:45 +03:00
rights . names [ rights . count ] . string = talloc_strdup ( ctx , args [ i ] ) ;
2004-12-14 09:31:20 +03:00
rights . count + + ;
}
2006-01-26 09:33:45 +03:00
status = smblsa_sid_add_privileges ( ctx - > cli , sid , ctx , & rights ) ;
2004-12-14 09:31:20 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
d_printf ( " lsa_AddAccountRights - %s \n " , nt_errstr ( status ) ) ;
return 1 ;
}
return 0 ;
}
/****************************************************************************
delete privileges for a user
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_delprivileges ( struct smbclient_context * ctx , const char * * args )
2004-12-14 09:31:20 +03:00
{
NTSTATUS status ;
struct dom_sid * sid ;
struct lsa_RightSet rights ;
2006-01-26 09:33:45 +03:00
int i ;
2004-12-14 09:31:20 +03:00
2006-01-26 09:33:45 +03:00
if ( ! args [ 1 ] ) {
2004-12-21 06:29:09 +03:00
d_printf ( " delprivileges <sid|name> <privilege...> \n " ) ;
2004-12-14 09:31:20 +03:00
return 1 ;
}
2006-01-26 09:33:45 +03:00
sid = dom_sid_parse_talloc ( ctx , args [ 1 ] ) ;
2004-12-14 09:31:20 +03:00
if ( sid = = NULL ) {
const char * sid_str ;
2006-01-26 09:33:45 +03:00
status = smblsa_lookup_name ( ctx - > cli , args [ 1 ] , ctx , & sid_str ) ;
2004-12-14 09:31:20 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
d_printf ( " lsa_LookupNames - %s \n " , nt_errstr ( status ) ) ;
return 1 ;
}
2006-01-26 09:33:45 +03:00
sid = dom_sid_parse_talloc ( ctx , sid_str ) ;
2004-12-14 09:31:20 +03:00
}
ZERO_STRUCT ( rights ) ;
2006-01-26 09:33:45 +03:00
for ( i = 2 ; args [ i ] ; i + + ) {
rights . names = talloc_realloc ( ctx , rights . names ,
2006-01-18 19:01:13 +03:00
struct lsa_StringLarge , rights . count + 1 ) ;
2006-01-26 09:33:45 +03:00
rights . names [ rights . count ] . string = talloc_strdup ( ctx , args [ i ] ) ;
2004-12-14 09:31:20 +03:00
rights . count + + ;
}
2006-01-26 09:33:45 +03:00
status = smblsa_sid_del_privileges ( ctx - > cli , sid , ctx , & rights ) ;
2004-12-14 09:31:20 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
d_printf ( " lsa_RemoveAccountRights - %s \n " , nt_errstr ( status ) ) ;
return 1 ;
}
return 0 ;
}
2003-08-13 05:53:07 +04:00
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_open ( struct smbclient_context * ctx , const char * * args )
2003-08-13 05:53:07 +04:00
{
2006-01-26 09:33:45 +03:00
char * mask ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
if ( ! args [ 1 ] ) {
2003-08-13 05:53:07 +04:00
d_printf ( " open <filename> \n " ) ;
return 1 ;
}
2006-01-26 09:33:45 +03:00
mask = talloc_asprintf ( ctx , " %s%s " , ctx - > remote_cur_dir , args [ 1 ] ) ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
smbcli_open ( ctx - > cli - > tree , mask , O_RDWR , DENY_ALL ) ;
2003-08-13 05:53:07 +04:00
return 0 ;
}
/****************************************************************************
remove a directory
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_rmdir ( struct smbclient_context * ctx , const char * * args )
2003-08-13 05:53:07 +04:00
{
2006-01-26 09:33:45 +03:00
char * mask ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
if ( ! args [ 1 ] ) {
2003-08-13 05:53:07 +04:00
d_printf ( " rmdir <dirname> \n " ) ;
return 1 ;
}
2006-01-26 09:33:45 +03:00
mask = talloc_asprintf ( ctx , " %s%s " , ctx - > remote_cur_dir , args [ 1 ] ) ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
if ( NT_STATUS_IS_ERR ( smbcli_rmdir ( ctx - > cli - > tree , mask ) ) ) {
2006-01-26 14:48:45 +03:00
d_printf ( " %s removing remote directory file %s \n " ,
2006-01-26 09:33:45 +03:00
smbcli_errstr ( ctx - > cli - > tree ) , mask ) ;
2003-08-13 05:53:07 +04:00
}
return 0 ;
}
/****************************************************************************
UNIX hardlink .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_link ( struct smbclient_context * ctx , const char * * args )
2003-08-13 05:53:07 +04:00
{
2006-01-26 09:33:45 +03:00
char * src , * dest ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
if ( ! ( ctx - > cli - > transport - > negotiate . capabilities & CAP_UNIX ) ) {
2003-08-13 05:53:07 +04:00
d_printf ( " Server doesn't support UNIX CIFS calls. \n " ) ;
return 1 ;
}
2006-01-26 09:33:45 +03:00
if ( ! args [ 1 ] | | ! args [ 2 ] ) {
2003-08-13 05:53:07 +04:00
d_printf ( " link <src> <dest> \n " ) ;
return 1 ;
}
2006-01-26 09:33:45 +03:00
src = talloc_asprintf ( ctx , " %s%s " , ctx - > remote_cur_dir , args [ 1 ] ) ;
dest = talloc_asprintf ( ctx , " %s%s " , ctx - > remote_cur_dir , args [ 2 ] ) ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
if ( NT_STATUS_IS_ERR ( smbcli_unix_hardlink ( ctx - > cli - > tree , src , dest ) ) ) {
d_printf ( " %s linking files (%s -> %s) \n " , smbcli_errstr ( ctx - > cli - > tree ) , src , dest ) ;
2003-08-13 05:53:07 +04:00
return 1 ;
}
return 0 ;
}
/****************************************************************************
UNIX symlink .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_symlink ( struct smbclient_context * ctx , const char * * args )
2003-08-13 05:53:07 +04:00
{
2006-01-26 09:33:45 +03:00
char * src , * dest ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
if ( ! ( ctx - > cli - > transport - > negotiate . capabilities & CAP_UNIX ) ) {
2003-08-13 05:53:07 +04:00
d_printf ( " Server doesn't support UNIX CIFS calls. \n " ) ;
return 1 ;
}
2006-01-26 09:33:45 +03:00
if ( ! args [ 1 ] | | ! args [ 2 ] ) {
2003-08-13 05:53:07 +04:00
d_printf ( " symlink <src> <dest> \n " ) ;
return 1 ;
}
2006-01-26 09:33:45 +03:00
src = talloc_asprintf ( ctx , " %s%s " , ctx - > remote_cur_dir , args [ 1 ] ) ;
dest = talloc_asprintf ( ctx , " %s%s " , ctx - > remote_cur_dir , args [ 2 ] ) ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
if ( NT_STATUS_IS_ERR ( smbcli_unix_symlink ( ctx - > cli - > tree , src , dest ) ) ) {
2003-08-13 05:53:07 +04:00
d_printf ( " %s symlinking files (%s -> %s) \n " ,
2006-01-26 09:33:45 +03:00
smbcli_errstr ( ctx - > cli - > tree ) , src , dest ) ;
2003-08-13 05:53:07 +04:00
return 1 ;
}
return 0 ;
}
/****************************************************************************
UNIX chmod .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_chmod ( struct smbclient_context * ctx , const char * * args )
2003-08-13 05:53:07 +04:00
{
2006-01-26 09:33:45 +03:00
char * src ;
2003-08-13 05:53:07 +04:00
mode_t mode ;
2006-01-26 09:33:45 +03:00
if ( ! ( ctx - > cli - > transport - > negotiate . capabilities & CAP_UNIX ) ) {
2003-08-13 05:53:07 +04:00
d_printf ( " Server doesn't support UNIX CIFS calls. \n " ) ;
return 1 ;
}
2006-01-26 09:33:45 +03:00
if ( ! args [ 1 ] | | ! args [ 2 ] ) {
2003-08-13 05:53:07 +04:00
d_printf ( " chmod mode file \n " ) ;
return 1 ;
}
2006-01-26 09:33:45 +03:00
src = talloc_asprintf ( ctx , " %s%s " , ctx - > remote_cur_dir , args [ 2 ] ) ;
mode = ( mode_t ) strtol ( args [ 1 ] , NULL , 8 ) ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
if ( NT_STATUS_IS_ERR ( smbcli_unix_chmod ( ctx - > cli - > tree , src , mode ) ) ) {
2003-08-13 05:53:07 +04:00
d_printf ( " %s chmod file %s 0%o \n " ,
2006-04-24 13:36:09 +04:00
smbcli_errstr ( ctx - > cli - > tree ) , src , ( mode_t ) mode ) ;
2003-08-13 05:53:07 +04:00
return 1 ;
}
return 0 ;
}
/****************************************************************************
UNIX chown .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_chown ( struct smbclient_context * ctx , const char * * args )
2003-08-13 05:53:07 +04:00
{
2006-01-26 09:33:45 +03:00
char * src ;
2003-08-13 05:53:07 +04:00
uid_t uid ;
gid_t gid ;
2006-01-26 09:33:45 +03:00
if ( ! ( ctx - > cli - > transport - > negotiate . capabilities & CAP_UNIX ) ) {
2003-08-13 05:53:07 +04:00
d_printf ( " Server doesn't support UNIX CIFS calls. \n " ) ;
return 1 ;
}
2006-01-26 09:33:45 +03:00
if ( ! args [ 1 ] | | ! args [ 2 ] | | ! args [ 3 ] ) {
2003-08-13 05:53:07 +04:00
d_printf ( " chown uid gid file \n " ) ;
return 1 ;
}
2006-01-26 09:33:45 +03:00
uid = ( uid_t ) atoi ( args [ 1 ] ) ;
gid = ( gid_t ) atoi ( args [ 2 ] ) ;
src = talloc_asprintf ( ctx , " %s%s " , ctx - > remote_cur_dir , args [ 3 ] ) ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
if ( NT_STATUS_IS_ERR ( smbcli_unix_chown ( ctx - > cli - > tree , src , uid , gid ) ) ) {
2003-08-13 05:53:07 +04:00
d_printf ( " %s chown file %s uid=%d, gid=%d \n " ,
2006-01-26 09:33:45 +03:00
smbcli_errstr ( ctx - > cli - > tree ) , src , ( int ) uid , ( int ) gid ) ;
2003-08-13 05:53:07 +04:00
return 1 ;
}
return 0 ;
}
/****************************************************************************
rename some files
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_rename ( struct smbclient_context * ctx , const char * * args )
2003-08-13 05:53:07 +04:00
{
2006-01-26 09:33:45 +03:00
char * src , * dest ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
if ( ! args [ 1 ] | | ! args [ 2 ] ) {
2003-08-13 05:53:07 +04:00
d_printf ( " rename <src> <dest> \n " ) ;
return 1 ;
}
2006-01-26 09:33:45 +03:00
src = talloc_asprintf ( ctx , " %s%s " , ctx - > remote_cur_dir , args [ 1 ] ) ;
dest = talloc_asprintf ( ctx , " %s%s " , ctx - > remote_cur_dir , args [ 2 ] ) ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
if ( NT_STATUS_IS_ERR ( smbcli_rename ( ctx - > cli - > tree , src , dest ) ) ) {
d_printf ( " %s renaming files \n " , smbcli_errstr ( ctx - > cli - > tree ) ) ;
2003-08-13 05:53:07 +04:00
return 1 ;
}
return 0 ;
}
/****************************************************************************
toggle the prompt flag
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_prompt ( struct smbclient_context * ctx , const char * * args )
2003-08-13 05:53:07 +04:00
{
2006-01-26 09:33:45 +03:00
ctx - > prompt = ! ctx - > prompt ;
DEBUG ( 2 , ( " prompting is now %s \n " , ctx - > prompt ? " on " : " off " ) ) ;
2003-08-13 05:53:07 +04:00
return 1 ;
}
/****************************************************************************
set the newer than time
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_newer ( struct smbclient_context * ctx , const char * * args )
2003-08-13 05:53:07 +04:00
{
2004-11-01 23:21:54 +03:00
struct stat sbuf ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
if ( args [ 1 ] & & ( stat ( args [ 1 ] , & sbuf ) = = 0 ) ) {
ctx - > newer_than = sbuf . st_mtime ;
2003-08-13 05:53:07 +04:00
DEBUG ( 1 , ( " Getting files newer than %s " ,
2006-01-26 09:33:45 +03:00
asctime ( localtime ( & ctx - > newer_than ) ) ) ) ;
2003-08-13 05:53:07 +04:00
} else {
2006-01-26 09:33:45 +03:00
ctx - > newer_than = 0 ;
2003-08-13 05:53:07 +04:00
}
2006-01-26 09:33:45 +03:00
if ( args [ 1 ] & & ctx - > newer_than = = 0 ) {
2003-08-13 05:53:07 +04:00
d_printf ( " Error setting newer-than time \n " ) ;
return 1 ;
}
return 0 ;
}
/****************************************************************************
set the archive level
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_archive ( struct smbclient_context * ctx , const char * * args )
2003-08-13 05:53:07 +04:00
{
2006-01-26 09:33:45 +03:00
if ( args [ 1 ] ) {
ctx - > archive_level = atoi ( args [ 1 ] ) ;
2003-08-13 05:53:07 +04:00
} else
2006-01-26 09:33:45 +03:00
d_printf ( " Archive level is %d \n " , ctx - > archive_level ) ;
2003-08-13 05:53:07 +04:00
return 0 ;
}
/****************************************************************************
toggle the lowercaseflag
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_lowercase ( struct smbclient_context * ctx , const char * * args )
2003-08-13 05:53:07 +04:00
{
2006-01-26 09:33:45 +03:00
ctx - > lowercase = ! ctx - > lowercase ;
DEBUG ( 2 , ( " filename lowercasing is now %s \n " , ctx - > lowercase ? " on " : " off " ) ) ;
2003-08-13 05:53:07 +04:00
return 0 ;
}
/****************************************************************************
toggle the recurse flag
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_recurse ( struct smbclient_context * ctx , const char * * args )
2003-08-13 05:53:07 +04:00
{
2006-01-26 09:33:45 +03:00
ctx - > recurse = ! ctx - > recurse ;
DEBUG ( 2 , ( " directory recursion is now %s \n " , ctx - > recurse ? " on " : " off " ) ) ;
2003-08-13 05:53:07 +04:00
return 0 ;
}
/****************************************************************************
toggle the translate flag
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_translate ( struct smbclient_context * ctx , const char * * args )
2003-08-13 05:53:07 +04:00
{
2006-01-26 09:33:45 +03:00
ctx - > translation = ! ctx - > translation ;
2003-08-13 05:53:07 +04:00
DEBUG ( 2 , ( " CR/LF<->LF and print text translation now %s \n " ,
2006-01-26 09:33:45 +03:00
ctx - > translation ? " on " : " off " ) ) ;
2003-08-13 05:53:07 +04:00
return 0 ;
}
/****************************************************************************
do a printmode command
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_printmode ( struct smbclient_context * ctx , const char * * args )
2003-08-13 05:53:07 +04:00
{
2006-01-26 09:33:45 +03:00
if ( args [ 1 ] ) {
if ( strequal ( args [ 1 ] , " text " ) ) {
ctx - > printmode = 0 ;
2003-08-13 05:53:07 +04:00
} else {
2006-01-26 09:33:45 +03:00
if ( strequal ( args [ 1 ] , " graphics " ) )
ctx - > printmode = 1 ;
2003-08-13 05:53:07 +04:00
else
2006-01-26 09:33:45 +03:00
ctx - > printmode = atoi ( args [ 1 ] ) ;
2003-08-13 05:53:07 +04:00
}
}
2006-01-26 09:33:45 +03:00
switch ( ctx - > printmode )
{
2003-08-13 05:53:07 +04:00
case 0 :
2006-01-26 09:33:45 +03:00
DEBUG ( 2 , ( " the printmode is now text \n " ) ) ;
2003-08-13 05:53:07 +04:00
break ;
case 1 :
2006-01-26 09:33:45 +03:00
DEBUG ( 2 , ( " the printmode is now graphics \n " ) ) ;
2003-08-13 05:53:07 +04:00
break ;
default :
2006-01-26 09:33:45 +03:00
DEBUG ( 2 , ( " the printmode is now %d \n " , ctx - > printmode ) ) ;
2003-08-13 05:53:07 +04:00
break ;
2006-01-26 09:33:45 +03:00
}
2003-08-13 05:53:07 +04:00
return 0 ;
}
/****************************************************************************
do the lcd command
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_lcd ( struct smbclient_context * ctx , const char * * args )
2003-08-13 05:53:07 +04:00
{
2005-09-23 04:38:22 +04:00
char d [ PATH_MAX ] ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
if ( args [ 1 ] )
chdir ( args [ 1 ] ) ;
2005-09-23 04:38:22 +04:00
DEBUG ( 2 , ( " the local directory is now %s \n " , getcwd ( d , PATH_MAX ) ) ) ;
2003-08-13 05:53:07 +04:00
return 0 ;
}
2005-09-26 19:15:50 +04:00
/****************************************************************************
history
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_history ( struct smbclient_context * ctx , const char * * args )
2005-09-26 19:15:50 +04:00
{
# if defined(HAVE_LIBREADLINE)
HIST_ENTRY * * hlist ;
int i ;
hlist = history_list ( ) ;
for ( i = 0 ; hlist & & hlist [ i ] ; i + + ) {
DEBUG ( 0 , ( " %d: %s \n " , i , hlist [ i ] - > line ) ) ;
}
# else
DEBUG ( 0 , ( " no history without readline support \n " ) ) ;
# endif
return 0 ;
}
2003-08-13 05:53:07 +04:00
/****************************************************************************
get a file restarting at end of local file
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_reget ( struct smbclient_context * ctx , const char * * args )
2003-08-13 05:53:07 +04:00
{
2006-01-26 09:33:45 +03:00
char * local_name ;
char * remote_name ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
if ( ! args [ 1 ] ) {
2003-08-13 05:53:07 +04:00
d_printf ( " reget <filename> \n " ) ;
return 1 ;
}
2006-01-26 09:33:45 +03:00
remote_name = talloc_asprintf ( ctx , " %s \\ %s " , ctx - > remote_cur_dir , args [ 1 ] ) ;
2003-08-13 05:53:07 +04:00
dos_clean_name ( remote_name ) ;
2006-01-26 09:33:45 +03:00
if ( args [ 2 ] )
local_name = talloc_strdup ( ctx , args [ 2 ] ) ;
else
local_name = talloc_strdup ( ctx , args [ 1 ] ) ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
return do_get ( ctx , remote_name , local_name , True ) ;
2003-08-13 05:53:07 +04:00
}
/****************************************************************************
put a file restarting at end of local file
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_reput ( struct smbclient_context * ctx , const char * * args )
2003-08-13 05:53:07 +04:00
{
2006-01-26 09:33:45 +03:00
char * local_name ;
char * remote_name ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
if ( ! args [ 1 ] ) {
2003-08-13 05:53:07 +04:00
d_printf ( " reput <filename> \n " ) ;
return 1 ;
}
2006-01-26 09:33:45 +03:00
local_name = talloc_asprintf ( ctx , " %s \\ %s " , ctx - > remote_cur_dir , args [ 1 ] ) ;
2003-08-13 05:53:07 +04:00
2005-02-10 09:36:30 +03:00
if ( ! file_exist ( local_name ) ) {
2003-08-13 05:53:07 +04:00
d_printf ( " %s does not exist \n " , local_name ) ;
return 1 ;
}
2006-01-26 09:33:45 +03:00
if ( args [ 2 ] )
remote_name = talloc_strdup ( ctx , args [ 2 ] ) ;
2003-08-13 05:53:07 +04:00
else
2006-01-26 09:33:45 +03:00
remote_name = talloc_strdup ( ctx , args [ 1 ] ) ;
2003-08-13 05:53:07 +04:00
dos_clean_name ( remote_name ) ;
2006-01-26 09:33:45 +03:00
return do_put ( ctx , remote_name , local_name , True ) ;
2003-08-13 05:53:07 +04:00
}
2004-04-26 04:27:01 +04:00
/*
return a string representing a share type
*/
2004-05-25 20:24:13 +04:00
static const char * share_type_str ( uint32_t type )
2004-04-26 04:27:01 +04:00
{
2004-04-26 04:33:17 +04:00
switch ( type & 0xF ) {
case STYPE_DISKTREE :
2004-04-26 04:27:01 +04:00
return " Disk " ;
2004-04-26 04:33:17 +04:00
case STYPE_PRINTQ :
2004-04-26 04:27:01 +04:00
return " Printer " ;
2004-04-26 04:33:17 +04:00
case STYPE_DEVICE :
return " Device " ;
case STYPE_IPC :
2004-04-26 04:27:01 +04:00
return " IPC " ;
default :
return " Unknown " ;
}
}
/*
display a list of shares from a level 1 share enum
*/
static void display_share_result ( struct srvsvc_NetShareCtr1 * ctr1 )
{
int i ;
for ( i = 0 ; i < ctr1 - > count ; i + + ) {
struct srvsvc_NetShareInfo1 * info = ctr1 - > array + i ;
printf ( " \t %-15s %-10.10s %s \n " ,
info - > name ,
share_type_str ( info - > type ) ,
info - > comment ) ;
}
}
2003-08-13 05:53:07 +04:00
/****************************************************************************
2004-04-26 04:27:01 +04:00
try and browse available shares on a host
2003-08-13 05:53:07 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-04-26 04:27:01 +04:00
static BOOL browse_host ( const char * query_host )
2003-08-13 05:53:07 +04:00
{
2004-04-26 04:27:01 +04:00
struct dcerpc_pipe * p ;
char * binding ;
NTSTATUS status ;
struct srvsvc_NetShareEnumAll r ;
2004-05-25 20:24:13 +04:00
uint32_t resume_handle = 0 ;
2004-04-26 04:27:01 +04:00
TALLOC_CTX * mem_ctx = talloc_init ( " browse_host " ) ;
struct srvsvc_NetShareCtr1 ctr1 ;
binding = talloc_asprintf ( mem_ctx , " ncacn_np:%s " , query_host ) ;
2005-03-22 11:00:45 +03:00
status = dcerpc_pipe_connect ( mem_ctx , & p , binding ,
2005-12-27 17:28:01 +03:00
& dcerpc_table_srvsvc ,
2005-06-16 15:36:09 +04:00
cmdline_credentials , NULL ) ;
2004-04-26 04:27:01 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
d_printf ( " Failed to connect to %s - %s \n " ,
binding , nt_errstr ( status ) ) ;
2005-01-27 10:08:20 +03:00
talloc_free ( mem_ctx ) ;
2004-04-26 04:27:01 +04:00
return False ;
}
r . in . server_unc = talloc_asprintf ( mem_ctx , " \\ \\ %s " , dcerpc_server_name ( p ) ) ;
r . in . level = 1 ;
r . in . ctr . ctr1 = & ctr1 ;
r . in . max_buffer = ~ 0 ;
r . in . resume_handle = & resume_handle ;
2004-04-26 04:43:23 +04:00
d_printf ( " \n \t Sharename Type Comment \n " ) ;
d_printf ( " \t --------- ---- ------- \n " ) ;
2004-04-26 04:27:01 +04:00
do {
ZERO_STRUCT ( ctr1 ) ;
status = dcerpc_srvsvc_NetShareEnumAll ( p , mem_ctx , & r ) ;
if ( NT_STATUS_IS_OK ( status ) & &
( W_ERROR_EQUAL ( r . out . result , WERR_MORE_DATA ) | |
W_ERROR_IS_OK ( r . out . result ) ) & &
r . out . ctr . ctr1 ) {
display_share_result ( r . out . ctr . ctr1 ) ;
resume_handle + = r . out . ctr . ctr1 - > count ;
}
} while ( NT_STATUS_IS_OK ( status ) & & W_ERROR_EQUAL ( r . out . result , WERR_MORE_DATA ) ) ;
2005-01-27 10:08:20 +03:00
talloc_free ( mem_ctx ) ;
2004-10-11 09:17:21 +04:00
2004-04-26 04:27:01 +04:00
if ( ! NT_STATUS_IS_OK ( status ) | | ! W_ERROR_IS_OK ( r . out . result ) ) {
d_printf ( " Failed NetShareEnumAll %s - %s/%s \n " ,
binding , nt_errstr ( status ) , win_errstr ( r . out . result ) ) ;
return False ;
}
2003-08-13 05:53:07 +04:00
return False ;
}
/****************************************************************************
try and browse available connections on a host
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-10-28 17:19:39 +04:00
static BOOL list_servers ( const char * wk_grp )
2003-08-13 05:53:07 +04:00
{
d_printf ( " REWRITE: list servers not implemented \n " ) ;
return False ;
}
/* Some constants for completing filename arguments */
# define COMPL_NONE 0 /* No completions */
# define COMPL_REMOTE 1 /* Complete remote filename */
# define COMPL_LOCAL 2 /* Complete local filename */
2006-01-26 09:33:45 +03:00
static int cmd_help ( struct smbclient_context * ctx , const char * * args ) ;
2003-08-13 05:53:07 +04:00
/* This defines the commands supported by this client.
* NOTE : The " ! " must be the last one in the list because it ' s fn pointer
* field is NULL , and NULL in that field is used in process_tok ( )
* ( below ) to indicate the end of the list . crh
*/
static struct
{
const char * name ;
2006-01-26 09:33:45 +03:00
int ( * fn ) ( struct smbclient_context * ctx , const char * * args ) ;
2003-08-13 05:53:07 +04:00
const char * description ;
char compl_args [ 2 ] ; /* Completion argument info */
} commands [ ] =
{
{ " ? " , cmd_help , " [command] give help on a command " , { COMPL_NONE , COMPL_NONE } } ,
2004-12-21 06:29:09 +03:00
{ " addprivileges " , cmd_addprivileges , " <sid|name> <privilege...> add privileges for a user " , { COMPL_NONE , COMPL_NONE } } ,
2003-08-13 05:53:07 +04:00
{ " altname " , cmd_altname , " <file> show alt name " , { COMPL_NONE , COMPL_NONE } } ,
2003-10-30 11:32:26 +03:00
{ " acl " , cmd_acl , " <file> show file ACL " , { COMPL_NONE , COMPL_NONE } } ,
2003-08-13 05:53:07 +04:00
{ " allinfo " , cmd_allinfo , " <file> show all possible info about a file " , { COMPL_NONE , COMPL_NONE } } ,
{ " archive " , cmd_archive , " <level> \n 0=ignore archive bit \n 1=only get archive files \n 2=only get archive files and reset archive bit \n 3=get all files and reset archive bit " , { COMPL_NONE , COMPL_NONE } } ,
2006-01-26 09:33:45 +03:00
{ " cancel " , cmd_rewrite , " <jobid> cancel a print queue entry " , { COMPL_NONE , COMPL_NONE } } ,
2003-08-13 05:53:07 +04:00
{ " cd " , cmd_cd , " [directory] change/report the remote directory " , { COMPL_REMOTE , COMPL_NONE } } ,
{ " chmod " , cmd_chmod , " <src> <mode> chmod a file using UNIX permission " , { COMPL_REMOTE , COMPL_REMOTE } } ,
{ " chown " , cmd_chown , " <src> <uid> <gid> chown a file using UNIX uids and gids " , { COMPL_REMOTE , COMPL_REMOTE } } ,
{ " del " , cmd_del , " <mask> delete all matching files " , { COMPL_REMOTE , COMPL_NONE } } ,
2004-12-21 06:29:09 +03:00
{ " delprivileges " , cmd_delprivileges , " <sid|name> <privilege...> remove privileges for a user " , { COMPL_NONE , COMPL_NONE } } ,
2003-08-13 05:53:07 +04:00
{ " deltree " , cmd_deltree , " <dir> delete a whole directory tree " , { COMPL_REMOTE , COMPL_NONE } } ,
{ " dir " , cmd_dir , " <mask> list the contents of the current directory " , { COMPL_REMOTE , COMPL_NONE } } ,
{ " du " , cmd_du , " <mask> computes the total size of the current directory " , { COMPL_REMOTE , COMPL_NONE } } ,
2004-12-26 11:41:11 +03:00
{ " eainfo " , cmd_eainfo , " <file> show EA contents for a file " , { COMPL_NONE , COMPL_NONE } } ,
2003-08-13 05:53:07 +04:00
{ " exit " , cmd_quit , " logoff the server " , { COMPL_NONE , COMPL_NONE } } ,
2005-05-03 13:57:34 +04:00
{ " fsinfo " , cmd_fsinfo , " query file system info " , { COMPL_NONE , COMPL_NONE } } ,
2003-08-13 05:53:07 +04:00
{ " get " , cmd_get , " <remote name> [local name] get a file " , { COMPL_REMOTE , COMPL_LOCAL } } ,
{ " help " , cmd_help , " [command] give help on a command " , { COMPL_NONE , COMPL_NONE } } ,
{ " history " , cmd_history , " displays the command history " , { COMPL_NONE , COMPL_NONE } } ,
{ " lcd " , cmd_lcd , " [directory] change/report the local current working directory " , { COMPL_LOCAL , COMPL_NONE } } ,
{ " link " , cmd_link , " <src> <dest> create a UNIX hard link " , { COMPL_REMOTE , COMPL_REMOTE } } ,
2004-12-21 06:29:09 +03:00
{ " lookup " , cmd_lookup , " <sid|name> show SID for name or name for SID " , { COMPL_NONE , COMPL_NONE } } ,
2003-08-13 05:53:07 +04:00
{ " lowercase " , cmd_lowercase , " toggle lowercasing of filenames for get " , { COMPL_NONE , COMPL_NONE } } ,
{ " ls " , cmd_dir , " <mask> list the contents of the current directory " , { COMPL_REMOTE , COMPL_NONE } } ,
{ " mask " , cmd_select , " <mask> mask all filenames against this " , { COMPL_REMOTE , COMPL_NONE } } ,
{ " md " , cmd_mkdir , " <directory> make a directory " , { COMPL_NONE , COMPL_NONE } } ,
{ " mget " , cmd_mget , " <mask> get all the matching files " , { COMPL_REMOTE , COMPL_NONE } } ,
{ " mkdir " , cmd_mkdir , " <directory> make a directory " , { COMPL_NONE , COMPL_NONE } } ,
{ " more " , cmd_more , " <remote name> view a remote file with your pager " , { COMPL_REMOTE , COMPL_NONE } } ,
{ " mput " , cmd_mput , " <mask> put all matching files " , { COMPL_REMOTE , COMPL_NONE } } ,
{ " newer " , cmd_newer , " <file> only mget files newer than the specified local file " , { COMPL_LOCAL , COMPL_NONE } } ,
{ " open " , cmd_open , " <mask> open a file " , { COMPL_REMOTE , COMPL_NONE } } ,
2004-12-06 10:12:38 +03:00
{ " privileges " , cmd_privileges , " <user> show privileges for a user " , { COMPL_NONE , COMPL_NONE } } ,
2003-08-13 05:53:07 +04:00
{ " print " , cmd_print , " <file name> print a file " , { COMPL_NONE , COMPL_NONE } } ,
{ " printmode " , cmd_printmode , " <graphics or text> set the print mode " , { COMPL_NONE , COMPL_NONE } } ,
{ " prompt " , cmd_prompt , " toggle prompting for filenames for mget and mput " , { COMPL_NONE , COMPL_NONE } } ,
{ " put " , cmd_put , " <local name> [remote name] put a file " , { COMPL_LOCAL , COMPL_REMOTE } } ,
{ " pwd " , cmd_pwd , " show current remote directory (same as 'cd' with no args) " , { COMPL_NONE , COMPL_NONE } } ,
{ " q " , cmd_quit , " logoff the server " , { COMPL_NONE , COMPL_NONE } } ,
2006-01-26 09:33:45 +03:00
{ " queue " , cmd_rewrite , " show the print queue " , { COMPL_NONE , COMPL_NONE } } ,
2003-08-13 05:53:07 +04:00
{ " quit " , cmd_quit , " logoff the server " , { COMPL_NONE , COMPL_NONE } } ,
{ " rd " , cmd_rmdir , " <directory> remove a directory " , { COMPL_NONE , COMPL_NONE } } ,
{ " recurse " , cmd_recurse , " toggle directory recursion for mget and mput " , { COMPL_NONE , COMPL_NONE } } ,
{ " reget " , cmd_reget , " <remote name> [local name] get a file restarting at end of local file " , { COMPL_REMOTE , COMPL_LOCAL } } ,
{ " rename " , cmd_rename , " <src> <dest> rename some files " , { COMPL_REMOTE , COMPL_REMOTE } } ,
{ " reput " , cmd_reput , " <local name> [remote name] put a file restarting at end of remote file " , { COMPL_LOCAL , COMPL_REMOTE } } ,
{ " rm " , cmd_del , " <mask> delete all matching files " , { COMPL_REMOTE , COMPL_NONE } } ,
{ " rmdir " , cmd_rmdir , " <directory> remove a directory " , { COMPL_NONE , COMPL_NONE } } ,
{ " symlink " , cmd_symlink , " <src> <dest> create a UNIX symlink " , { COMPL_REMOTE , COMPL_REMOTE } } ,
{ " translate " , cmd_translate , " toggle text translation for printing " , { COMPL_NONE , COMPL_NONE } } ,
/* Yes, this must be here, see crh's comment above. */
{ " ! " , NULL , " run a shell command on the local system " , { COMPL_NONE , COMPL_NONE } } ,
{ NULL , NULL , NULL , { COMPL_NONE , COMPL_NONE } }
} ;
/*******************************************************************
lookup a command string in the list of commands , including
abbreviations
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int process_tok ( const char * tok )
2003-08-13 05:53:07 +04:00
{
int i = 0 , matches = 0 ;
int cmd = 0 ;
int tok_len = strlen ( tok ) ;
while ( commands [ i ] . fn ! = NULL ) {
if ( strequal ( commands [ i ] . name , tok ) ) {
matches = 1 ;
cmd = i ;
break ;
2004-09-20 11:25:06 +04:00
} else if ( strncasecmp ( commands [ i ] . name , tok , tok_len ) = = 0 ) {
2003-08-13 05:53:07 +04:00
matches + + ;
cmd = i ;
}
i + + ;
}
if ( matches = = 0 )
return ( - 1 ) ;
else if ( matches = = 1 )
return ( cmd ) ;
else
return ( - 2 ) ;
}
/****************************************************************************
help
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int cmd_help ( struct smbclient_context * ctx , const char * * args )
2003-08-13 05:53:07 +04:00
{
int i = 0 , j ;
2006-01-26 09:33:45 +03:00
if ( args [ 1 ] ) {
if ( ( i = process_tok ( args [ 1 ] ) ) > = 0 )
2003-08-13 05:53:07 +04:00
d_printf ( " HELP %s: \n \t %s \n \n " , commands [ i ] . name , commands [ i ] . description ) ;
} else {
while ( commands [ i ] . description ) {
for ( j = 0 ; commands [ i ] . description & & ( j < 5 ) ; j + + ) {
d_printf ( " %-15s " , commands [ i ] . name ) ;
i + + ;
}
d_printf ( " \n " ) ;
}
}
return 0 ;
}
2006-01-26 09:33:45 +03:00
static int process_line ( struct smbclient_context * ctx , const char * cline ) ;
2003-08-13 05:53:07 +04:00
/****************************************************************************
process a - c command string
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int process_command_string ( struct smbclient_context * ctx , const char * cmd )
2003-08-13 05:53:07 +04:00
{
2006-01-26 09:33:45 +03:00
const char * * lines ;
2006-01-26 14:48:45 +03:00
int i , rc = 0 ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
lines = str_list_make ( NULL , cmd , " ; " ) ;
for ( i = 0 ; lines [ i ] ; i + + ) {
rc | = process_line ( ctx , lines [ i ] ) ;
2003-08-13 05:53:07 +04:00
}
2006-01-26 09:33:45 +03:00
talloc_free ( lines ) ;
2003-08-13 05:53:07 +04:00
return rc ;
}
# define MAX_COMPLETIONS 100
typedef struct {
2006-01-26 09:33:45 +03:00
char * dirmask ;
2003-08-13 05:53:07 +04:00
char * * matches ;
int count , samelen ;
const char * text ;
int len ;
} completion_remote_t ;
2004-11-30 08:37:57 +03:00
static void completion_remote_filter ( struct clilist_file_info * f , const char * mask , void * state )
2003-08-13 05:53:07 +04:00
{
completion_remote_t * info = ( completion_remote_t * ) state ;
2006-04-24 04:16:51 +04:00
if ( ( info - > count < MAX_COMPLETIONS - 1 ) & & ( strncmp ( info - > text , f - > name , info - > len ) = = 0 ) & & ( ! ISDOT ( f - > name ) ) & & ( ! ISDOTDOT ( f - > name ) ) ) {
2004-11-30 08:37:57 +03:00
if ( ( info - > dirmask [ 0 ] = = 0 ) & & ! ( f - > attrib & FILE_ATTRIBUTE_DIRECTORY ) )
2003-08-13 05:53:07 +04:00
info - > matches [ info - > count ] = strdup ( f - > name ) ;
else {
2006-01-26 09:33:45 +03:00
char * tmp ;
2003-08-13 05:53:07 +04:00
if ( info - > dirmask [ 0 ] ! = 0 )
2006-01-26 09:33:45 +03:00
tmp = talloc_asprintf ( NULL , " %s/%s " , info - > dirmask , f - > name ) ;
2003-08-13 05:53:07 +04:00
else
2006-01-26 09:33:45 +03:00
tmp = talloc_strdup ( NULL , f - > name ) ;
2004-11-30 08:37:57 +03:00
if ( f - > attrib & FILE_ATTRIBUTE_DIRECTORY )
2006-01-26 09:33:45 +03:00
tmp = talloc_append_string ( NULL , tmp , " / " ) ;
info - > matches [ info - > count ] = tmp ;
2003-08-13 05:53:07 +04:00
}
if ( info - > matches [ info - > count ] = = NULL )
return ;
2004-11-30 08:37:57 +03:00
if ( f - > attrib & FILE_ATTRIBUTE_DIRECTORY )
2003-08-13 05:53:07 +04:00
smb_readline_ca_char ( 0 ) ;
if ( info - > count = = 1 )
info - > samelen = strlen ( info - > matches [ info - > count ] ) ;
else
while ( strncmp ( info - > matches [ info - > count ] , info - > matches [ info - > count - 1 ] , info - > samelen ) ! = 0 )
info - > samelen - - ;
info - > count + + ;
}
}
static char * * remote_completion ( const char * text , int len )
{
2006-01-26 09:33:45 +03:00
char * dirmask ;
2003-08-13 05:53:07 +04:00
int i ;
2006-01-26 09:33:45 +03:00
completion_remote_t info ;
2003-08-13 05:53:07 +04:00
2003-08-15 01:56:26 +04:00
info . samelen = len ;
info . text = text ;
info . len = len ;
2003-08-13 05:53:07 +04:00
if ( len > = PATH_MAX )
return ( NULL ) ;
2004-12-03 10:20:30 +03:00
info . matches = malloc_array_p ( char * , MAX_COMPLETIONS ) ;
2003-08-13 05:53:07 +04:00
if ( ! info . matches ) return NULL ;
info . matches [ 0 ] = NULL ;
for ( i = len - 1 ; i > = 0 ; i - - )
if ( ( text [ i ] = = ' / ' ) | | ( text [ i ] = = ' \\ ' ) )
break ;
info . text = text + i + 1 ;
info . samelen = info . len = len - i - 1 ;
if ( i > 0 ) {
2006-01-26 09:33:45 +03:00
info . dirmask = talloc_strndup ( NULL , text , i + 1 ) ;
2003-08-13 05:53:07 +04:00
info . dirmask [ i + 1 ] = 0 ;
2006-01-26 09:33:45 +03:00
asprintf ( & dirmask , " %s%*s* " , rl_ctx - > remote_cur_dir , i - 1 , text ) ;
2003-08-13 05:53:07 +04:00
} else
2006-01-26 09:33:45 +03:00
asprintf ( & dirmask , " %s* " , rl_ctx - > remote_cur_dir ) ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
if ( smbcli_list ( rl_ctx - > cli - > tree , dirmask ,
2003-08-13 05:53:07 +04:00
FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN ,
completion_remote_filter , & info ) < 0 )
goto cleanup ;
if ( info . count = = 2 )
info . matches [ 0 ] = strdup ( info . matches [ 1 ] ) ;
else {
info . matches [ 0 ] = malloc ( info . samelen + 1 ) ;
if ( ! info . matches [ 0 ] )
goto cleanup ;
strncpy ( info . matches [ 0 ] , info . matches [ 1 ] , info . samelen ) ;
info . matches [ 0 ] [ info . samelen ] = 0 ;
}
info . matches [ info . count ] = NULL ;
return info . matches ;
cleanup :
for ( i = 0 ; i < info . count ; i + + )
free ( info . matches [ i ] ) ;
free ( info . matches ) ;
return NULL ;
}
static char * * completion_fn ( const char * text , int start , int end )
{
smb_readline_ca_char ( ' ' ) ;
if ( start ) {
const char * buf , * sp ;
int i ;
char compl_type ;
buf = smb_readline_get_line_buffer ( ) ;
if ( buf = = NULL )
return NULL ;
sp = strchr ( buf , ' ' ) ;
if ( sp = = NULL )
return NULL ;
for ( i = 0 ; commands [ i ] . name ; i + + )
if ( ( strncmp ( commands [ i ] . name , text , sp - buf ) = = 0 ) & & ( commands [ i ] . name [ sp - buf ] = = 0 ) )
break ;
if ( commands [ i ] . name = = NULL )
return NULL ;
while ( * sp = = ' ' )
sp + + ;
if ( sp = = ( buf + start ) )
compl_type = commands [ i ] . compl_args [ 0 ] ;
else
compl_type = commands [ i ] . compl_args [ 1 ] ;
if ( compl_type = = COMPL_REMOTE )
return remote_completion ( text , end - start ) ;
else /* fall back to local filename completion */
return NULL ;
} else {
char * * matches ;
2004-12-02 07:51:56 +03:00
int i , len , samelen = 0 , count = 1 ;
2003-08-13 05:53:07 +04:00
2004-12-03 10:20:30 +03:00
matches = malloc_array_p ( char * , MAX_COMPLETIONS ) ;
2003-08-13 05:53:07 +04:00
if ( ! matches ) return NULL ;
matches [ 0 ] = NULL ;
len = strlen ( text ) ;
for ( i = 0 ; commands [ i ] . fn & & count < MAX_COMPLETIONS - 1 ; i + + ) {
if ( strncmp ( text , commands [ i ] . name , len ) = = 0 ) {
matches [ count ] = strdup ( commands [ i ] . name ) ;
if ( ! matches [ count ] )
goto cleanup ;
if ( count = = 1 )
samelen = strlen ( matches [ count ] ) ;
else
while ( strncmp ( matches [ count ] , matches [ count - 1 ] , samelen ) ! = 0 )
samelen - - ;
count + + ;
}
}
switch ( count ) {
case 0 : /* should never happen */
case 1 :
goto cleanup ;
case 2 :
matches [ 0 ] = strdup ( matches [ 1 ] ) ;
break ;
default :
matches [ 0 ] = malloc ( samelen + 1 ) ;
if ( ! matches [ 0 ] )
goto cleanup ;
strncpy ( matches [ 0 ] , matches [ 1 ] , samelen ) ;
matches [ 0 ] [ samelen ] = 0 ;
}
matches [ count ] = NULL ;
return matches ;
cleanup :
while ( i > = 0 ) {
free ( matches [ i ] ) ;
i - - ;
}
free ( matches ) ;
return NULL ;
}
}
/****************************************************************************
make sure we swallow keepalives during idle time
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-10-28 17:19:39 +04:00
static void readline_callback ( void )
2003-08-13 05:53:07 +04:00
{
static time_t last_t ;
time_t t ;
t = time ( NULL ) ;
if ( t - last_t < 5 ) return ;
last_t = t ;
2006-01-26 09:33:45 +03:00
smbcli_transport_process ( rl_ctx - > cli - > transport ) ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
if ( rl_ctx - > cli - > tree ) {
smbcli_chkpath ( rl_ctx - > cli - > tree , " \\ " ) ;
2003-08-13 05:53:07 +04:00
}
}
2006-01-26 09:33:45 +03:00
static int process_line ( struct smbclient_context * ctx , const char * cline )
{
const char * * args ;
int i ;
/* and get the first part of the command */
args = str_list_make_shell ( ctx , cline , NULL ) ;
if ( ! args | | ! args [ 0 ] )
return 0 ;
if ( ( i = process_tok ( args [ 0 ] ) ) > = 0 ) {
i = commands [ i ] . fn ( ctx , args ) ;
} else if ( i = = - 2 ) {
d_printf ( " %s: command abbreviation ambiguous \n " , args [ 0 ] ) ;
} else {
d_printf ( " %s: command not found \n " , args [ 0 ] ) ;
}
talloc_free ( args ) ;
return i ;
}
2003-08-13 05:53:07 +04:00
/****************************************************************************
process commands on stdin
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int process_stdin ( struct smbclient_context * ctx )
2003-08-13 05:53:07 +04:00
{
2006-01-26 09:33:45 +03:00
int rc = 0 ;
2003-08-13 05:53:07 +04:00
while ( 1 ) {
/* display a prompt */
2006-01-26 14:48:45 +03:00
char * the_prompt = talloc_asprintf ( ctx , " smb: %s> " , ctx - > remote_cur_dir ) ;
char * cline = smb_readline ( the_prompt , readline_callback , completion_fn ) ;
2006-01-26 09:33:45 +03:00
talloc_free ( the_prompt ) ;
2003-08-13 05:53:07 +04:00
if ( ! cline ) break ;
/* special case - first char is ! */
2006-01-26 09:33:45 +03:00
if ( * cline = = ' ! ' ) {
system ( cline + 1 ) ;
2003-08-13 05:53:07 +04:00
continue ;
}
2006-01-26 09:33:45 +03:00
2006-01-26 14:48:45 +03:00
rc | = process_command_string ( ctx , cline ) ;
2003-08-13 05:53:07 +04:00
}
2006-01-26 09:33:45 +03:00
return rc ;
2003-08-13 05:53:07 +04:00
}
/*****************************************************
return a connection to a server
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static struct smbclient_context * do_connect ( TALLOC_CTX * mem_ctx ,
2006-03-25 19:23:42 +03:00
const char * specified_server , const char * specified_share , struct cli_credentials * cred )
2003-08-13 05:53:07 +04:00
{
2004-04-06 12:05:04 +04:00
NTSTATUS status ;
2006-01-26 09:33:45 +03:00
struct smbclient_context * ctx = talloc_zero ( mem_ctx , struct smbclient_context ) ;
2006-03-25 19:23:42 +03:00
char * server , * share ;
2006-01-26 09:33:45 +03:00
if ( ! ctx ) {
2005-11-02 06:08:52 +03:00
return NULL ;
}
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
rl_ctx = ctx ; /* Ugly hack */
2006-03-25 19:23:42 +03:00
if ( strncmp ( specified_share , " \\ \\ " , 2 ) = = 0 | |
strncmp ( specified_share , " // " , 2 ) = = 0 ) {
smbcli_parse_unc ( specified_share , ctx , & server , & share ) ;
} else {
share = talloc_strdup ( ctx , specified_share ) ;
server = talloc_strdup ( ctx , specified_server ) ;
2003-08-13 05:53:07 +04:00
}
2006-01-26 09:33:45 +03:00
ctx - > remote_cur_dir = talloc_strdup ( ctx , " \\ " ) ;
2005-01-15 14:58:52 +03:00
2006-01-26 09:33:45 +03:00
status = smbcli_full_connection ( ctx , & ctx - > cli , server ,
2005-06-16 15:36:09 +04:00
share , NULL , cred , NULL ) ;
2005-01-15 14:58:52 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
d_printf ( " Connection to \\ \\ %s \\ %s failed - %s \n " ,
server , share , nt_errstr ( status ) ) ;
2006-01-26 09:33:45 +03:00
talloc_free ( ctx ) ;
2003-08-13 05:53:07 +04:00
return NULL ;
}
2006-01-26 09:33:45 +03:00
return ctx ;
2003-08-13 05:53:07 +04:00
}
/****************************************************************************
handle a - L query
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int do_host_query ( const char * query_host )
2003-08-13 05:53:07 +04:00
{
2004-04-26 04:27:01 +04:00
browse_host ( query_host ) ;
2003-08-13 05:53:07 +04:00
list_servers ( lp_workgroup ( ) ) ;
return ( 0 ) ;
}
/****************************************************************************
handle a message operation
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-01-26 09:33:45 +03:00
static int do_message_op ( const char * desthost , const char * destip , int name_type )
2003-08-13 05:53:07 +04:00
{
2005-01-21 14:18:56 +03:00
struct nbt_name called , calling ;
2004-08-19 00:13:08 +04:00
const char * server_name ;
2006-01-26 09:33:45 +03:00
struct smbcli_state * cli ;
2003-08-13 05:53:07 +04:00
2005-05-22 14:23:01 +04:00
make_nbt_name_client ( & calling , lp_netbios_name ( ) ) ;
2005-01-21 14:18:56 +03:00
nbt_choose_called_name ( NULL , & called , desthost , name_type ) ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
server_name = destip ? destip : desthost ;
2003-08-13 05:53:07 +04:00
2004-09-28 09:44:59 +04:00
if ( ! ( cli = smbcli_state_init ( NULL ) ) | | ! smbcli_socket_connect ( cli , server_name ) ) {
2004-08-19 00:13:08 +04:00
d_printf ( " Connection to %s failed \n " , server_name ) ;
2003-08-13 05:53:07 +04:00
return 1 ;
}
2004-08-04 17:23:35 +04:00
if ( ! smbcli_transport_establish ( cli , & calling , & called ) ) {
2003-08-13 05:53:07 +04:00
d_printf ( " session request failed \n " ) ;
2005-06-18 04:02:36 +04:00
talloc_free ( cli ) ;
2003-08-13 05:53:07 +04:00
return 1 ;
}
2006-01-26 09:33:45 +03:00
send_message ( cli , desthost ) ;
2005-06-18 04:02:36 +04:00
talloc_free ( cli ) ;
2003-08-13 05:53:07 +04:00
return 0 ;
}
/****************************************************************************
main program
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int main ( int argc , char * argv [ ] )
{
2006-01-26 09:33:45 +03:00
const char * base_directory = NULL ;
const char * dest_ip ;
2003-08-13 05:53:07 +04:00
int opt ;
2006-01-26 09:33:45 +03:00
const char * query_host = NULL ;
2003-08-13 05:53:07 +04:00
BOOL message = False ;
2006-01-26 09:33:45 +03:00
const char * desthost ;
# ifdef KANJI
const char * term_code = KANJI ;
# else
const char * term_code = " " ;
# endif /* KANJI */
2003-08-13 05:53:07 +04:00
poptContext pc ;
2006-01-26 09:33:45 +03:00
const char * service = NULL ;
int port = 0 ;
2003-08-13 05:53:07 +04:00
char * p ;
int rc = 0 ;
2006-01-26 09:33:45 +03:00
int name_type = 0x20 ;
2003-08-13 05:53:07 +04:00
TALLOC_CTX * mem_ctx ;
2006-01-26 09:33:45 +03:00
struct smbclient_context * ctx ;
const char * cmdstr = NULL ;
2003-08-13 05:53:07 +04:00
struct poptOption long_options [ ] = {
POPT_AUTOHELP
{ " message " , ' M ' , POPT_ARG_STRING , NULL , ' M ' , " Send message " , " HOST " } ,
{ " ip-address " , ' I ' , POPT_ARG_STRING , NULL , ' I ' , " Use this IP to connect to " , " IP " } ,
{ " stderr " , ' E ' , POPT_ARG_NONE , NULL , ' E ' , " Write messages to stderr instead of stdout " } ,
{ " list " , ' L ' , POPT_ARG_STRING , NULL , ' L ' , " Get a list of shares available on a host " , " HOST " } ,
{ " terminal " , ' t ' , POPT_ARG_STRING , NULL , ' t ' , " Terminal I/O code {sjis|euc|jis7|jis8|junet|hex} " , " CODE " } ,
{ " directory " , ' D ' , POPT_ARG_STRING , NULL , ' D ' , " Start from directory " , " DIR " } ,
{ " command " , ' c ' , POPT_ARG_STRING , & cmdstr , ' c ' , " Execute semicolon separated commands " } ,
{ " send-buffer " , ' b ' , POPT_ARG_INT , NULL , ' b ' , " Changes the transmit/send buffer " , " BYTES " } ,
{ " port " , ' p ' , POPT_ARG_INT , & port , ' p ' , " Port to connect to " , " PORT " } ,
POPT_COMMON_SAMBA
POPT_COMMON_CONNECTION
POPT_COMMON_CREDENTIALS
2004-08-19 16:23:57 +04:00
POPT_COMMON_VERSION
2003-08-13 05:53:07 +04:00
POPT_TABLEEND
} ;
mem_ctx = talloc_init ( " client.c/main " ) ;
if ( ! mem_ctx ) {
d_printf ( " \n client.c: Not enough memory \n " ) ;
exit ( 1 ) ;
}
2004-06-05 23:24:48 +04:00
pc = poptGetContext ( " smbclient " , argc , ( const char * * ) argv , long_options , 0 ) ;
poptSetOtherOptionHelp ( pc , " [OPTIONS] service <password> " ) ;
2003-08-13 05:53:07 +04:00
while ( ( opt = poptGetNextOpt ( pc ) ) ! = - 1 ) {
switch ( opt ) {
case ' M ' :
/* Messages are sent to NetBIOS name type 0x3
* ( Messenger Service ) . Make sure we default
* to port 139 instead of port 445. srl , crh
*/
name_type = 0x03 ;
2006-01-26 09:33:45 +03:00
desthost = strdup ( poptGetOptArg ( pc ) ) ;
2003-08-13 05:53:07 +04:00
if ( 0 = = port ) port = 139 ;
message = True ;
break ;
case ' I ' :
2004-08-19 00:13:08 +04:00
dest_ip = poptGetOptArg ( pc ) ;
2003-08-13 05:53:07 +04:00
break ;
case ' L ' :
2006-01-26 09:33:45 +03:00
query_host = strdup ( poptGetOptArg ( pc ) ) ;
2003-08-13 05:53:07 +04:00
break ;
case ' t ' :
2006-01-26 09:33:45 +03:00
term_code = strdup ( poptGetOptArg ( pc ) ) ;
2003-08-13 05:53:07 +04:00
break ;
case ' D ' :
2006-01-26 09:33:45 +03:00
base_directory = strdup ( poptGetOptArg ( pc ) ) ;
2003-08-13 05:53:07 +04:00
break ;
case ' b ' :
io_bufsize = MAX ( 1 , atoi ( poptGetOptArg ( pc ) ) ) ;
break ;
}
}
2005-12-31 01:46:16 +03:00
gensec_init ( ) ;
2004-11-09 12:26:47 +03:00
2003-08-13 05:53:07 +04:00
if ( poptPeekArg ( pc ) ) {
2006-01-26 09:33:45 +03:00
char * s = strdup ( poptGetArg ( pc ) ) ;
2003-08-13 05:53:07 +04:00
/* Convert any '/' characters in the service name to '\' characters */
2006-01-26 09:33:45 +03:00
string_replace ( s , ' / ' , ' \\ ' ) ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
service = s ;
if ( count_chars ( s , ' \\ ' ) < 3 ) {
d_printf ( " \n %s: Not enough ' \\ ' characters in service \n " , s ) ;
2003-08-13 05:53:07 +04:00
poptPrintUsage ( pc , stderr , 0 ) ;
exit ( 1 ) ;
}
}
if ( poptPeekArg ( pc ) ) {
2005-03-21 05:08:38 +03:00
cli_credentials_set_password ( cmdline_credentials , poptGetArg ( pc ) , CRED_SPECIFIED ) ;
2003-08-13 05:53:07 +04:00
}
2003-10-30 11:32:26 +03:00
/*init_names(); */
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
if ( ! query_host & & ! service & & ! message ) {
2003-08-13 05:53:07 +04:00
poptPrintUsage ( pc , stderr , 0 ) ;
exit ( 1 ) ;
}
poptFreeContext ( pc ) ;
2004-01-28 15:47:52 +03:00
DEBUG ( 3 , ( " Client started (version %s). \n " , SAMBA_VERSION_STRING ) ) ;
2003-08-13 05:53:07 +04:00
2006-01-26 09:33:45 +03:00
if ( query_host & & ( p = strchr_m ( query_host , ' # ' ) ) ) {
2003-08-13 05:53:07 +04:00
* p = 0 ;
p + + ;
sscanf ( p , " %x " , & name_type ) ;
}
2006-01-26 09:33:45 +03:00
if ( query_host ) {
2003-08-13 05:53:07 +04:00
return do_host_query ( query_host ) ;
}
if ( message ) {
2006-01-26 09:33:45 +03:00
return do_message_op ( desthost , dest_ip , name_type ) ;
2003-08-13 05:53:07 +04:00
}
2006-01-26 09:33:45 +03:00
ctx = do_connect ( mem_ctx , desthost , service , cmdline_credentials ) ;
if ( ! ctx )
2003-08-13 05:53:07 +04:00
return 1 ;
2006-01-26 09:33:45 +03:00
if ( base_directory )
do_cd ( ctx , base_directory ) ;
if ( cmdstr ) {
rc = process_command_string ( ctx , cmdstr ) ;
} else {
rc = process_stdin ( ctx ) ;
2003-08-13 05:53:07 +04:00
}
2006-01-26 09:33:45 +03:00
talloc_free ( mem_ctx ) ;
2003-08-13 05:53:07 +04:00
return rc ;
}