2004-01-07 03:43:52 +03:00
/*
2016-01-24 13:17:20 +03:00
smbget : a wget - like utility with support for recursive downloading of
smb : // urls
2004-01-07 03:43:52 +03:00
Copyright ( C ) 2003 - 2004 Jelmer Vernooij < jelmer @ 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
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
2004-01-07 03:43:52 +03:00
( at your option ) any later version .
2010-07-04 13:02:21 +04:00
2004-01-07 03:43:52 +03:00
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 .
2010-07-04 13:02:21 +04:00
2004-01-07 03:43:52 +03:00
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>. */
2004-01-07 03:43:52 +03:00
# include "includes.h"
2011-04-26 16:58:01 +04:00
# include "system/filesys.h"
2021-01-13 16:23:31 +03:00
# include "lib/cmdline/cmdline.h"
2023-04-13 16:41:53 +03:00
# include "lib/param/param.h"
2004-01-07 03:43:52 +03:00
# include "libsmbclient.h"
2018-08-22 02:11:02 +03:00
# include "cmdline_contexts.h"
2023-03-30 12:19:01 +03:00
# include "auth/credentials/credentials.h"
2023-04-03 09:14:30 +03:00
# include "auth/gensec/gensec.h"
2004-01-07 03:43:52 +03:00
2008-03-09 15:50:56 +03:00
static int columns = 0 ;
2004-01-07 03:43:52 +03:00
2008-03-09 15:50:56 +03:00
static time_t total_start_time = 0 ;
static off_t total_bytes = 0 ;
2004-01-07 03:43:52 +03:00
# define SMB_MAXPATHLEN MAXPATHLEN
2016-01-24 13:17:20 +03:00
/*
* Number of bytes to read when checking whether local and remote file
* are really the same file
*/
# define RESUME_CHECK_SIZE 512
# define RESUME_DOWNLOAD_OFFSET 1024
# define RESUME_CHECK_OFFSET (RESUME_DOWNLOAD_OFFSET+RESUME_CHECK_SIZE)
2004-01-07 03:43:52 +03:00
/* Number of bytes to read at once */
2016-01-24 13:17:20 +03:00
# define SMB_DEFAULT_BLOCKSIZE 64000
2004-01-07 03:43:52 +03:00
2015-10-28 14:37:36 +03:00
struct opt {
char * outputfile ;
size_t blocksize ;
2023-05-01 06:36:53 +03:00
int quiet ;
int dots ;
int verbose ;
int send_stdout ;
int update ;
2022-10-02 00:45:18 +03:00
unsigned limit_rate ;
2015-10-28 14:37:36 +03:00
} ;
2016-02-04 23:39:47 +03:00
static struct opt opt = { . blocksize = SMB_DEFAULT_BLOCKSIZE } ;
2004-01-07 03:43:52 +03:00
2016-01-24 13:57:01 +03:00
static bool smb_download_file ( const char * base , const char * name ,
bool recursive , bool resume , bool toplevel ,
char * outfile ) ;
2004-01-07 03:43:52 +03:00
2006-12-19 23:16:52 +03:00
static int get_num_cols ( void )
2004-01-07 03:43:52 +03:00
{
# ifdef TIOCGWINSZ
struct winsize ws ;
2016-01-24 13:17:20 +03:00
if ( ioctl ( STDOUT_FILENO , TIOCGWINSZ , & ws ) < 0 ) {
2004-01-07 03:43:52 +03:00
return 0 ;
}
return ws . ws_col ;
# else
# warning No support for TIOCGWINSZ
char * cols = getenv ( " COLUMNS " ) ;
2016-01-24 13:17:20 +03:00
if ( ! cols ) {
return 0 ;
}
2004-01-07 03:43:52 +03:00
return atoi ( cols ) ;
# endif
}
2006-12-19 23:16:52 +03:00
static void change_columns ( int sig )
2004-01-07 03:43:52 +03:00
{
columns = get_num_cols ( ) ;
}
2006-12-19 23:16:52 +03:00
static void human_readable ( off_t s , char * buffer , int l )
2004-01-07 03:43:52 +03:00
{
2011-04-08 00:03:49 +04:00
if ( s > 1024 * 1024 * 1024 ) {
snprintf ( buffer , l , " %.2fGB " , 1.0 * s / ( 1024 * 1024 * 1024 ) ) ;
} else if ( s > 1024 * 1024 ) {
snprintf ( buffer , l , " %.2fMB " , 1.0 * s / ( 1024 * 1024 ) ) ;
} else if ( s > 1024 ) {
snprintf ( buffer , l , " %.2fkB " , 1.0 * s / 1024 ) ;
} else {
2016-01-24 13:45:59 +03:00
snprintf ( buffer , l , " %jdb " , ( intmax_t ) s ) ;
2011-04-08 00:03:49 +04:00
}
2004-01-07 03:43:52 +03:00
}
2023-03-30 12:19:01 +03:00
/*
* Authentication callback for libsmbclient .
*
* The command line parser will take care asking for a password interactively !
*/
2023-04-13 16:41:53 +03:00
static void get_auth_data_with_context_fn ( SMBCCTX * ctx ,
const char * srv ,
const char * shr ,
char * dom ,
int dom_len ,
char * usr ,
int usr_len ,
char * pwd ,
int pwd_len )
2004-01-07 03:43:52 +03:00
{
2023-03-30 12:19:01 +03:00
struct cli_credentials * creds = samba_cmdline_get_creds ( ) ;
const char * username = NULL ;
const char * password = NULL ;
const char * domain = NULL ;
username = cli_credentials_get_username ( creds ) ;
if ( username ! = NULL ) {
2023-04-13 16:41:53 +03:00
strncpy ( usr , username , usr_len - 1 ) ;
2023-03-30 12:19:01 +03:00
}
password = cli_credentials_get_password ( creds ) ;
if ( password ! = NULL ) {
2023-04-13 16:41:53 +03:00
strncpy ( pwd , password , pwd_len - 1 ) ;
2023-03-30 12:19:01 +03:00
}
domain = cli_credentials_get_domain ( creds ) ;
if ( domain ! = NULL ) {
2023-04-13 16:41:53 +03:00
strncpy ( dom , domain , dom_len - 1 ) ;
2023-03-30 12:19:01 +03:00
}
2023-04-13 16:41:53 +03:00
smbc_set_credentials_with_fallback ( ctx , domain , username , password ) ;
2023-03-30 12:19:01 +03:00
if ( ! opt . quiet & & username ! = NULL ) {
if ( username [ 0 ] = = ' \0 ' ) {
printf ( " Using guest user \n " ) ;
} else {
printf ( " Using domain: %s, user: %s \n " ,
domain ,
username ) ;
2009-01-01 05:06:57 +03:00
}
2016-01-24 13:17:20 +03:00
}
2004-01-07 03:43:52 +03:00
}
2016-02-09 01:24:36 +03:00
static bool smb_download_dir ( const char * base , const char * name , int resume )
2004-01-07 03:43:52 +03:00
{
char path [ SMB_MAXPATHLEN ] ;
int dirhandle ;
struct smbc_dirent * dirent ;
const char * relname = name ;
char * tmpname ;
2016-02-09 01:24:36 +03:00
bool ok = false ;
2010-01-28 21:38:24 +03:00
2016-01-24 13:17:20 +03:00
snprintf ( path , SMB_MAXPATHLEN - 1 , " %s%s%s " , base ,
( base [ 0 ] & & name [ 0 ] & & name [ 0 ] ! = ' / ' & &
base [ strlen ( base ) - 1 ] ! = ' / ' ) ? " / " : " " ,
name ) ;
2004-01-07 03:43:52 +03:00
/* List files in directory and call smb_download_file on them */
dirhandle = smbc_opendir ( path ) ;
2016-01-24 13:17:20 +03:00
if ( dirhandle < 1 ) {
2010-07-04 13:32:50 +04:00
if ( errno = = ENOTDIR ) {
2016-01-24 13:57:01 +03:00
return smb_download_file ( base , name , true , resume ,
false , NULL ) ;
2010-07-04 13:32:50 +04:00
}
2016-01-24 13:17:20 +03:00
fprintf ( stderr , " Can't open directory %s: %s \n " , path ,
strerror ( errno ) ) ;
2016-02-09 01:24:36 +03:00
return false ;
2004-01-07 03:43:52 +03:00
}
2016-01-24 13:17:20 +03:00
while ( * relname = = ' / ' ) {
relname + + ;
}
2018-10-22 17:28:21 +03:00
if ( strlen ( relname ) > 0 ) {
int rc = mkdir ( relname , 0755 ) ;
if ( rc = = - 1 & & errno ! = EEXIST ) {
fprintf ( stderr , " Can't create directory %s: %s \n " ,
relname , strerror ( errno ) ) ;
return false ;
}
}
2010-07-04 13:02:21 +04:00
2004-12-17 00:06:33 +03:00
tmpname = SMB_STRDUP ( name ) ;
2004-01-07 03:43:52 +03:00
2016-01-24 13:17:20 +03:00
while ( ( dirent = smbc_readdir ( dirhandle ) ) ) {
2004-01-07 03:43:52 +03:00
char * newname ;
2016-01-24 13:17:20 +03:00
if ( ! strcmp ( dirent - > name , " . " ) | | ! strcmp ( dirent - > name , " .. " ) ) {
2018-10-23 21:05:04 +03:00
ok = true ;
2016-01-24 13:17:20 +03:00
continue ;
}
2009-01-01 05:06:57 +03:00
if ( asprintf ( & newname , " %s/%s " , tmpname , dirent - > name ) = = - 1 ) {
2013-12-04 17:01:55 +04:00
free ( tmpname ) ;
2016-02-09 01:24:36 +03:00
return false ;
2009-01-01 05:06:57 +03:00
}
2016-01-24 13:17:20 +03:00
switch ( dirent - > smbc_type ) {
2004-01-07 03:43:52 +03:00
case SMBC_DIR :
2016-02-09 01:24:36 +03:00
ok = smb_download_dir ( base , newname , resume ) ;
2004-01-07 03:43:52 +03:00
break ;
case SMBC_WORKGROUP :
2016-02-09 01:24:36 +03:00
ok = smb_download_dir ( " smb:// " , dirent - > name , resume ) ;
2004-01-07 03:43:52 +03:00
break ;
case SMBC_SERVER :
2016-02-09 01:24:36 +03:00
ok = smb_download_dir ( " smb:// " , dirent - > name , resume ) ;
2004-01-07 03:43:52 +03:00
break ;
case SMBC_FILE :
2016-02-09 01:24:36 +03:00
ok = smb_download_file ( base , newname , true , resume ,
2016-01-24 13:57:01 +03:00
false , NULL ) ;
2004-01-07 03:43:52 +03:00
break ;
case SMBC_FILE_SHARE :
2016-02-09 01:24:36 +03:00
ok = smb_download_dir ( base , newname , resume ) ;
2004-01-07 03:43:52 +03:00
break ;
case SMBC_PRINTER_SHARE :
2015-10-28 14:37:36 +03:00
if ( ! opt . quiet ) {
2016-01-24 13:17:20 +03:00
printf ( " Ignoring printer share %s \n " ,
dirent - > name ) ;
}
2004-01-07 03:43:52 +03:00
break ;
case SMBC_COMMS_SHARE :
2015-10-28 14:37:36 +03:00
if ( ! opt . quiet ) {
2016-01-24 13:17:20 +03:00
printf ( " Ignoring comms share %s \n " ,
dirent - > name ) ;
}
2004-01-07 03:43:52 +03:00
break ;
2010-07-04 13:02:21 +04:00
2004-01-07 03:43:52 +03:00
case SMBC_IPC_SHARE :
2015-10-28 14:37:36 +03:00
if ( ! opt . quiet ) {
2016-01-24 13:17:20 +03:00
printf ( " Ignoring ipc$ share %s \n " ,
dirent - > name ) ;
}
2004-01-07 03:43:52 +03:00
break ;
default :
2016-01-24 13:17:20 +03:00
fprintf ( stderr , " Ignoring file '%s' of type '%d' \n " ,
newname , dirent - > smbc_type ) ;
2004-01-07 03:43:52 +03:00
break ;
}
2016-02-09 01:25:04 +03:00
if ( ! ok ) {
fprintf ( stderr , " Failed to download %s: %s \n " ,
newname , strerror ( errno ) ) ;
2023-06-27 12:19:59 +03:00
free ( newname ) ;
2016-06-21 16:56:23 +03:00
free ( tmpname ) ;
2016-02-09 01:25:04 +03:00
return false ;
}
2004-01-07 03:43:52 +03:00
free ( newname ) ;
}
free ( tmpname ) ;
smbc_closedir ( dirhandle ) ;
2016-02-09 01:24:36 +03:00
return ok ;
2004-01-07 03:43:52 +03:00
}
2006-12-19 23:16:52 +03:00
static char * print_time ( long t )
2004-01-07 03:43:52 +03:00
{
static char buffer [ 100 ] ;
int secs , mins , hours ;
2016-01-24 13:17:20 +03:00
if ( t < - 1 ) {
2004-01-07 03:43:52 +03:00
strncpy ( buffer , " Unknown " , sizeof ( buffer ) ) ;
return buffer ;
}
secs = ( int ) t % 60 ;
mins = ( int ) t / 60 % 60 ;
hours = ( int ) t / ( 60 * 60 ) ;
2016-01-24 13:17:20 +03:00
snprintf ( buffer , sizeof ( buffer ) - 1 , " %02d:%02d:%02d " , hours , mins ,
secs ) ;
2004-01-07 03:43:52 +03:00
return buffer ;
}
2016-01-24 13:17:20 +03:00
static void print_progress ( const char * name , time_t start , time_t now ,
off_t start_pos , off_t pos , off_t total )
2004-01-07 03:43:52 +03:00
{
double avg = 0.0 ;
2016-01-24 13:17:20 +03:00
long eta = - 1 ;
2004-01-07 03:43:52 +03:00
double prcnt = 0.0 ;
2018-06-18 11:43:53 +03:00
char hpos [ 22 ] , htotal [ 22 ] , havg [ 22 ] ;
2004-01-07 03:43:52 +03:00
char * status , * filename ;
int len ;
2016-01-24 13:17:20 +03:00
if ( now - start ) {
avg = 1.0 * ( pos - start_pos ) / ( now - start ) ;
}
2004-02-14 01:09:53 +03:00
eta = ( total - pos ) / avg ;
2016-01-24 13:17:20 +03:00
if ( total ) {
prcnt = 100.0 * pos / total ;
}
2004-01-07 03:43:52 +03:00
human_readable ( pos , hpos , sizeof ( hpos ) ) ;
human_readable ( total , htotal , sizeof ( htotal ) ) ;
human_readable ( avg , havg , sizeof ( havg ) ) ;
2016-01-24 13:17:20 +03:00
len = asprintf ( & status , " %s of %s (%.2f%%) at %s/s ETA: %s " , hpos ,
htotal , prcnt , havg , print_time ( eta ) ) ;
2009-01-01 05:06:57 +03:00
if ( len = = - 1 ) {
return ;
}
2010-07-04 13:02:21 +04:00
2016-01-24 13:17:20 +03:00
if ( columns ) {
int required = strlen ( name ) ,
available = columns - len - strlen ( " [] " ) ;
if ( required > available ) {
if ( asprintf ( & filename , " ...%s " ,
name + required - available + 3 ) = = - 1 ) {
2009-01-01 05:06:57 +03:00
return ;
}
} else {
filename = SMB_STRNDUP ( name , available ) ;
}
2016-01-24 13:17:20 +03:00
} else {
filename = SMB_STRDUP ( name ) ;
}
2004-01-07 03:43:52 +03:00
fprintf ( stderr , " \r [%s] %s " , filename , status ) ;
2016-01-24 13:17:20 +03:00
free ( filename ) ;
free ( status ) ;
2004-01-07 03:43:52 +03:00
}
2016-01-24 13:57:01 +03:00
/* Return false on error, true on success. */
2010-01-28 21:38:24 +03:00
2016-01-24 13:57:01 +03:00
static bool smb_download_file ( const char * base , const char * name ,
bool recursive , bool resume , bool toplevel ,
char * outfile )
2010-07-04 13:32:50 +04:00
{
2004-01-07 03:43:52 +03:00
int remotehandle , localhandle ;
2010-09-09 00:29:00 +04:00
time_t start_time = time_mono ( NULL ) ;
2004-01-07 03:43:52 +03:00
const char * newpath ;
char path [ SMB_MAXPATHLEN ] ;
char checkbuf [ 2 ] [ RESUME_CHECK_SIZE ] ;
char * readbuf = NULL ;
2016-01-24 13:17:20 +03:00
off_t offset_download = 0 , offset_check = 0 , curpos = 0 ,
start_offset = 0 ;
2004-01-07 03:43:52 +03:00
struct stat localstat , remotestat ;
2022-10-02 00:45:18 +03:00
clock_t start_of_bucket_ticks = 0 ;
size_t bytes_in_bucket = 0 ;
size_t bucket_size = 0 ;
clock_t ticks_to_fill_bucket = 0 ;
2004-01-07 03:43:52 +03:00
2016-01-24 13:17:20 +03:00
snprintf ( path , SMB_MAXPATHLEN - 1 , " %s%s%s " , base ,
( * base & & * name & & name [ 0 ] ! = ' / ' & &
base [ strlen ( base ) - 1 ] ! = ' / ' ) ? " / " : " " ,
name ) ;
2010-07-04 13:02:21 +04:00
2004-01-07 03:43:52 +03:00
remotehandle = smbc_open ( path , O_RDONLY , 0755 ) ;
2016-01-24 13:17:20 +03:00
if ( remotehandle < 0 ) {
switch ( errno ) {
case EISDIR :
if ( ! recursive ) {
fprintf ( stderr ,
" %s is a directory. Specify -R "
" to download recursively \n " ,
path ) ;
2016-01-24 13:57:01 +03:00
return false ;
2004-01-07 03:43:52 +03:00
}
2010-01-28 21:38:24 +03:00
return smb_download_dir ( base , name , resume ) ;
2004-01-07 03:43:52 +03:00
case ENOENT :
2016-01-24 13:17:20 +03:00
fprintf ( stderr ,
" %s can't be found on the remote server \n " ,
path ) ;
2016-01-24 13:57:01 +03:00
return false ;
2004-01-07 03:43:52 +03:00
case ENOMEM :
fprintf ( stderr , " Not enough memory \n " ) ;
2016-01-24 13:57:01 +03:00
return false ;
2004-01-07 03:43:52 +03:00
case ENODEV :
2016-01-24 13:17:20 +03:00
fprintf ( stderr ,
" The share name used in %s does not exist \n " ,
path ) ;
2016-01-24 13:57:01 +03:00
return false ;
2004-01-07 03:43:52 +03:00
case EACCES :
2016-01-24 13:17:20 +03:00
fprintf ( stderr , " You don't have enough permissions "
" to access %s \n " ,
path ) ;
2016-01-24 13:57:01 +03:00
return false ;
2004-01-07 03:43:52 +03:00
default :
perror ( " smbc_open " ) ;
2016-01-24 13:57:01 +03:00
return false ;
2004-01-07 03:43:52 +03:00
}
2016-01-24 13:17:20 +03:00
}
2004-01-07 03:43:52 +03:00
2016-01-24 13:17:20 +03:00
if ( smbc_fstat ( remotehandle , & remotestat ) < 0 ) {
2004-01-07 03:43:52 +03:00
fprintf ( stderr , " Can't stat %s: %s \n " , path , strerror ( errno ) ) ;
2016-01-24 13:57:01 +03:00
return false ;
2004-01-07 03:43:52 +03:00
}
2016-01-24 13:17:20 +03:00
if ( outfile ) {
newpath = outfile ;
} else if ( ! name [ 0 ] ) {
2004-01-07 03:43:52 +03:00
newpath = strrchr ( base , ' / ' ) ;
2016-01-24 13:17:20 +03:00
if ( newpath ) {
newpath + + ;
} else {
newpath = base ;
}
} else {
newpath = name ;
}
2004-01-07 03:43:52 +03:00
2010-07-04 13:32:50 +04:00
if ( ! toplevel & & ( newpath [ 0 ] = = ' / ' ) ) {
newpath + + ;
}
2010-07-04 13:02:21 +04:00
2008-03-05 17:20:29 +03:00
/* Open local file according to the mode */
2015-10-28 14:37:36 +03:00
if ( opt . update ) {
2008-03-05 17:20:29 +03:00
/* if it is up-to-date, skip */
2016-01-24 13:17:20 +03:00
if ( stat ( newpath , & localstat ) = = 0 & &
localstat . st_mtime > = remotestat . st_mtime ) {
2015-10-28 14:37:36 +03:00
if ( opt . verbose ) {
2008-03-05 17:20:29 +03:00
printf ( " %s is up-to-date, skipping \n " , newpath ) ;
2016-01-24 13:17:20 +03:00
}
2008-03-05 17:20:29 +03:00
smbc_close ( remotehandle ) ;
2016-01-24 13:57:01 +03:00
return true ;
2008-03-05 17:20:29 +03:00
}
2008-03-05 19:30:18 +03:00
/* else open it for writing and truncate if it exists */
2016-01-24 13:17:20 +03:00
localhandle = open (
newpath , O_CREAT | O_NONBLOCK | O_RDWR | O_TRUNC , 0775 ) ;
if ( localhandle < 0 ) {
2008-03-05 17:20:29 +03:00
fprintf ( stderr , " Can't open %s : %s \n " , newpath ,
2016-01-24 13:17:20 +03:00
strerror ( errno ) ) ;
2008-03-05 17:20:29 +03:00
smbc_close ( remotehandle ) ;
2016-01-24 13:57:01 +03:00
return false ;
2008-03-05 17:20:29 +03:00
}
/* no offset */
2015-10-28 14:37:36 +03:00
} else if ( ! opt . send_stdout ) {
2016-01-24 13:17:20 +03:00
localhandle = open ( newpath , O_CREAT | O_NONBLOCK | O_RDWR |
( ! resume ? O_EXCL : 0 ) ,
0755 ) ;
if ( localhandle < 0 ) {
fprintf ( stderr , " Can't open %s: %s \n " , newpath ,
strerror ( errno ) ) ;
2004-03-05 20:17:31 +03:00
smbc_close ( remotehandle ) ;
2016-01-24 13:57:01 +03:00
return false ;
2004-03-05 20:17:31 +03:00
}
2010-07-04 13:02:21 +04:00
2008-03-15 01:26:28 +03:00
if ( fstat ( localhandle , & localstat ) ! = 0 ) {
2016-01-24 13:17:20 +03:00
fprintf ( stderr , " Can't fstat %s: %s \n " , newpath ,
strerror ( errno ) ) ;
2008-03-15 01:26:28 +03:00
smbc_close ( remotehandle ) ;
close ( localhandle ) ;
2016-01-24 13:57:01 +03:00
return false ;
2008-03-15 01:26:28 +03:00
}
2004-01-07 03:43:52 +03:00
2004-03-05 20:17:31 +03:00
start_offset = localstat . st_size ;
2004-01-07 03:43:52 +03:00
2016-01-24 13:17:20 +03:00
if ( localstat . st_size & &
localstat . st_size = = remotestat . st_size ) {
2015-10-28 14:37:36 +03:00
if ( opt . verbose ) {
2016-01-24 13:17:20 +03:00
fprintf ( stderr , " %s is already downloaded "
" completely. \n " ,
path ) ;
2015-10-28 14:37:36 +03:00
} else if ( ! opt . quiet ) {
2016-01-24 13:17:20 +03:00
fprintf ( stderr , " %s \n " , path ) ;
}
2004-03-05 20:17:31 +03:00
smbc_close ( remotehandle ) ;
close ( localhandle ) ;
2016-01-24 13:57:01 +03:00
return true ;
2004-01-07 03:43:52 +03:00
}
2016-01-24 13:17:20 +03:00
if ( localstat . st_size > RESUME_CHECK_OFFSET & &
remotestat . st_size > RESUME_CHECK_OFFSET ) {
offset_download =
localstat . st_size - RESUME_DOWNLOAD_OFFSET ;
2004-03-05 20:17:31 +03:00
offset_check = localstat . st_size - RESUME_CHECK_OFFSET ;
2015-10-28 14:37:36 +03:00
if ( opt . verbose ) {
2016-01-24 13:45:59 +03:00
printf ( " Trying to start resume of %s at %jd \n "
" At the moment %jd of %jd bytes have "
" been retrieved \n " ,
newpath , ( intmax_t ) offset_check ,
( intmax_t ) localstat . st_size ,
( intmax_t ) remotestat . st_size ) ;
2016-01-24 13:17:20 +03:00
}
2004-01-07 03:43:52 +03:00
}
2016-01-24 13:17:20 +03:00
if ( offset_check ) {
2004-03-05 20:17:31 +03:00
off_t off1 , off2 ;
2016-01-24 13:17:20 +03:00
/* First, check all bytes from offset_check to
* offset_download */
2004-03-05 20:17:31 +03:00
off1 = lseek ( localhandle , offset_check , SEEK_SET ) ;
2016-01-24 13:17:20 +03:00
if ( off1 < 0 ) {
2016-01-24 13:45:59 +03:00
fprintf ( stderr ,
" Can't seek to %jd in local file %s \n " ,
( intmax_t ) offset_check , newpath ) ;
2016-01-24 13:17:20 +03:00
smbc_close ( remotehandle ) ;
close ( localhandle ) ;
2016-01-24 13:57:01 +03:00
return false ;
2004-03-05 20:17:31 +03:00
}
2004-01-07 03:43:52 +03:00
2016-01-24 13:17:20 +03:00
off2 = smbc_lseek ( remotehandle , offset_check , SEEK_SET ) ;
if ( off2 < 0 ) {
2016-01-24 13:45:59 +03:00
fprintf ( stderr ,
" Can't seek to %jd in remote file %s \n " ,
( intmax_t ) offset_check , newpath ) ;
2016-01-24 13:17:20 +03:00
smbc_close ( remotehandle ) ;
close ( localhandle ) ;
2016-01-24 13:57:01 +03:00
return false ;
2004-03-05 20:17:31 +03:00
}
2004-01-07 03:43:52 +03:00
2016-01-24 13:17:20 +03:00
if ( off1 ! = off2 ) {
fprintf ( stderr , " Offset in local and remote "
2016-01-24 13:45:59 +03:00
" files are different "
" (local: %jd, remote: %jd) \n " ,
( intmax_t ) off1 , ( intmax_t ) off2 ) ;
2016-01-24 13:17:20 +03:00
smbc_close ( remotehandle ) ;
close ( localhandle ) ;
2016-01-24 13:57:01 +03:00
return false ;
2004-03-05 20:17:31 +03:00
}
2004-01-07 03:43:52 +03:00
2016-01-24 13:17:20 +03:00
if ( smbc_read ( remotehandle , checkbuf [ 0 ] ,
RESUME_CHECK_SIZE ) ! = RESUME_CHECK_SIZE ) {
fprintf ( stderr , " Can't read %d bytes from "
" remote file %s \n " ,
RESUME_CHECK_SIZE , path ) ;
smbc_close ( remotehandle ) ;
close ( localhandle ) ;
2016-01-24 13:57:01 +03:00
return false ;
2004-03-05 20:17:31 +03:00
}
2016-01-24 13:17:20 +03:00
if ( read ( localhandle , checkbuf [ 1 ] , RESUME_CHECK_SIZE ) ! =
RESUME_CHECK_SIZE ) {
fprintf ( stderr , " Can't read %d bytes from "
" local file %s \n " ,
RESUME_CHECK_SIZE , name ) ;
smbc_close ( remotehandle ) ;
close ( localhandle ) ;
2016-01-24 13:57:01 +03:00
return false ;
2004-03-05 20:17:31 +03:00
}
2016-01-24 13:17:20 +03:00
if ( memcmp ( checkbuf [ 0 ] , checkbuf [ 1 ] ,
RESUME_CHECK_SIZE ) = = 0 ) {
2015-10-28 14:37:36 +03:00
if ( opt . verbose ) {
2016-01-24 13:45:59 +03:00
printf ( " Current local and remote file "
" appear to be the same. "
" Starting download from "
" offset %jd \n " ,
( intmax_t ) offset_download ) ;
2016-01-24 13:17:20 +03:00
}
2004-03-05 20:17:31 +03:00
} else {
2016-01-24 13:17:20 +03:00
fprintf ( stderr , " Local and remote file appear "
" to be different, not "
" doing resume for %s \n " ,
path ) ;
smbc_close ( remotehandle ) ;
close ( localhandle ) ;
2016-01-24 13:57:01 +03:00
return false ;
2004-03-05 20:17:31 +03:00
}
2004-01-07 03:43:52 +03:00
}
2004-03-05 20:17:31 +03:00
} else {
localhandle = STDOUT_FILENO ;
start_offset = 0 ;
offset_download = 0 ;
offset_check = 0 ;
2004-01-07 03:43:52 +03:00
}
2022-10-02 00:45:18 +03:00
/* We implement rate limiting by filling up a bucket with bytes and
* checking , once the bucket is filled , if it was filled too fast .
* If so , we sleep for some time to get an average transfer rate that
* equals to the one set by the user .
*
* The bucket size directly affects the traffic characteristics .
* The smaller the bucket the more frequent the pause / resume cycle .
* A large bucket can result in burst of high speed traffic and large
* pauses . A cycle of 100 ms looks like a good value . This value ( in
* ticks ) is held in ` ticks_to_fill_bucket ` . The ` bucket_size ` is
* calculated as :
* ` limit_rate * 1024 * / ( CLOCKS_PER_SEC / ticks_to_fill_bucket ) `
*
* After selecting the bucket size we also need to check the blocksize
* of the transfer , since this is the minimum unit of traffic that we
* can observe . Achieving a ~ 10 % precision requires a blocksize with a
* maximum size of ` bucket_size / 10 ` .
*/
if ( opt . limit_rate > 0 ) {
unsigned max_block_size ;
/* This is the time that the bucket should take to fill. */
ticks_to_fill_bucket = 100 /*ms*/ * CLOCKS_PER_SEC / 1000 ;
/* This is the size of the bucket in bytes.
* If we fill the bucket too quickly we should pause */
bucket_size = opt . limit_rate * 1024 / ( CLOCKS_PER_SEC / ticks_to_fill_bucket ) ;
max_block_size = bucket_size / 10 ;
max_block_size = max_block_size > 0 ? max_block_size : 1 ;
if ( opt . blocksize > max_block_size ) {
if ( opt . blocksize ! = SMB_DEFAULT_BLOCKSIZE ) {
fprintf ( stderr ,
2023-07-06 06:57:08 +03:00
" Warning: Overriding block size to %d "
" due to limit-rate " , max_block_size ) ;
2022-10-02 00:45:18 +03:00
}
opt . blocksize = max_block_size ;
}
start_of_bucket_ticks = clock ( ) ;
}
2015-10-28 14:37:36 +03:00
readbuf = ( char * ) SMB_MALLOC ( opt . blocksize ) ;
2010-09-10 22:56:26 +04:00
if ( ! readbuf ) {
2016-02-04 23:38:20 +03:00
fprintf ( stderr , " Failed to allocate %zu bytes for read "
" buffer (%s) " , opt . blocksize , strerror ( errno ) ) ;
2013-02-20 13:23:45 +04:00
if ( localhandle ! = STDOUT_FILENO ) {
close ( localhandle ) ;
}
2016-01-24 13:57:01 +03:00
return false ;
2010-09-10 22:56:26 +04:00
}
2004-01-07 03:43:52 +03:00
/* Now, download all bytes from offset_download to the end */
2016-01-24 13:17:20 +03:00
for ( curpos = offset_download ; curpos < remotestat . st_size ;
2015-10-28 14:37:36 +03:00
curpos + = opt . blocksize ) {
2016-02-09 01:27:09 +03:00
ssize_t bytesread ;
ssize_t byteswritten ;
2022-10-02 00:45:18 +03:00
/* Rate limiting. This pauses the transfer to limit traffic. */
if ( opt . limit_rate > 0 ) {
if ( bytes_in_bucket > bucket_size ) {
clock_t now_ticks = clock ( ) ;
clock_t diff_ticks = now_ticks
- start_of_bucket_ticks ;
/* Check if the bucket filled up too fast. */
if ( diff_ticks < ticks_to_fill_bucket ) {
/* Pause until `ticks_to_fill_bucket` */
double sleep_us
= ( ticks_to_fill_bucket - diff_ticks )
2023-05-01 05:15:26 +03:00
* 1000000.0 / CLOCKS_PER_SEC ;
2022-10-02 00:45:18 +03:00
usleep ( sleep_us ) ;
}
/* Reset the byte counter and the ticks. */
bytes_in_bucket = 0 ;
start_of_bucket_ticks = clock ( ) ;
}
}
2016-02-09 01:27:09 +03:00
bytesread = smbc_read ( remotehandle , readbuf , opt . blocksize ) ;
2022-10-02 00:45:18 +03:00
if ( opt . limit_rate > 0 ) {
bytes_in_bucket + = bytesread ;
}
2004-01-07 03:43:52 +03:00
if ( bytesread < 0 ) {
2016-01-24 13:45:59 +03:00
fprintf ( stderr ,
2015-10-28 14:37:36 +03:00
" Can't read %zu bytes at offset %jd, file %s \n " ,
opt . blocksize , ( intmax_t ) curpos , path ) ;
2004-03-05 20:17:31 +03:00
smbc_close ( remotehandle ) ;
2016-01-24 13:17:20 +03:00
if ( localhandle ! = STDOUT_FILENO ) {
close ( localhandle ) ;
}
2004-01-07 03:43:52 +03:00
free ( readbuf ) ;
2016-01-24 13:57:01 +03:00
return false ;
2004-01-07 03:43:52 +03:00
}
total_bytes + = bytesread ;
2016-02-09 01:27:09 +03:00
byteswritten = write ( localhandle , readbuf , bytesread ) ;
if ( byteswritten ! = bytesread ) {
2016-01-24 13:45:59 +03:00
fprintf ( stderr ,
" Can't write %zd bytes to local file %s at "
" offset %jd \n " , bytesread , path ,
( intmax_t ) curpos ) ;
2004-01-07 03:43:52 +03:00
free ( readbuf ) ;
2004-03-05 20:17:31 +03:00
smbc_close ( remotehandle ) ;
2016-01-24 13:17:20 +03:00
if ( localhandle ! = STDOUT_FILENO ) {
close ( localhandle ) ;
}
2016-01-24 13:57:01 +03:00
return false ;
2004-01-07 03:43:52 +03:00
}
2015-10-28 14:37:36 +03:00
if ( opt . dots ) {
2016-01-24 13:17:20 +03:00
fputc ( ' . ' , stderr ) ;
2015-10-28 14:37:36 +03:00
} else if ( ! opt . quiet ) {
2010-09-09 00:29:00 +04:00
print_progress ( newpath , start_time , time_mono ( NULL ) ,
2016-01-24 13:17:20 +03:00
start_offset , curpos ,
remotestat . st_size ) ;
2004-01-07 03:43:52 +03:00
}
}
free ( readbuf ) ;
2015-10-28 14:37:36 +03:00
if ( opt . dots ) {
2004-01-07 03:43:52 +03:00
fputc ( ' \n ' , stderr ) ;
printf ( " %s downloaded \n " , path ) ;
2015-10-28 14:37:36 +03:00
} else if ( ! opt . quiet ) {
2004-01-07 03:43:52 +03:00
int i ;
fprintf ( stderr , " \r %s " , path ) ;
2016-01-24 13:17:20 +03:00
if ( columns ) {
for ( i = strlen ( path ) ; i < columns ; i + + ) {
2004-01-07 03:43:52 +03:00
fputc ( ' ' , stderr ) ;
}
}
fputc ( ' \n ' , stderr ) ;
}
smbc_close ( remotehandle ) ;
2016-01-24 13:17:20 +03:00
if ( localhandle ! = STDOUT_FILENO ) {
close ( localhandle ) ;
}
2016-01-24 13:57:01 +03:00
return true ;
2004-01-07 03:43:52 +03:00
}
2006-12-19 23:16:52 +03:00
static void clean_exit ( void )
2004-01-07 03:43:52 +03:00
{
char bs [ 100 ] ;
human_readable ( total_bytes , bs , sizeof ( bs ) ) ;
2015-10-28 14:37:36 +03:00
if ( ! opt . quiet ) {
2016-01-24 13:17:20 +03:00
fprintf ( stderr , " Downloaded %s in %lu seconds \n " , bs ,
( unsigned long ) ( time_mono ( NULL ) - total_start_time ) ) ;
}
2004-01-07 03:43:52 +03:00
exit ( 0 ) ;
}
2006-12-19 23:16:52 +03:00
static void signal_quit ( int v )
2004-01-07 03:43:52 +03:00
{
clean_exit ( ) ;
}
2015-10-28 14:37:36 +03:00
int main ( int argc , char * * argv )
2004-01-07 03:43:52 +03:00
{
int c = 0 ;
const char * file = NULL ;
2023-05-01 06:36:53 +03:00
int smb_encrypt = false ;
2008-03-11 21:49:08 +03:00
int resume = 0 , recursive = 0 ;
2007-09-04 09:39:06 +04:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2023-03-30 12:14:26 +03:00
bool ok = false ;
2015-10-28 14:37:36 +03:00
const char * * argv_const = discard_const_p ( const char * , argv ) ;
2004-01-07 03:43:52 +03:00
struct poptOption long_options [ ] = {
POPT_AUTOHELP
2015-10-28 14:37:36 +03:00
2019-01-11 17:03:54 +03:00
{
. longName = " guest " ,
. shortName = ' a ' ,
. argInfo = POPT_ARG_NONE ,
. arg = NULL ,
. val = ' a ' ,
. descrip = " Work as user guest "
} ,
{
. longName = " encrypt " ,
. shortName = ' e ' ,
. argInfo = POPT_ARG_NONE ,
2023-03-30 12:19:01 +03:00
. arg = & smb_encrypt ,
. val = 1 ,
2019-01-11 17:03:54 +03:00
. descrip = " Encrypt SMB transport "
} ,
{
. longName = " resume " ,
. shortName = ' r ' ,
. argInfo = POPT_ARG_NONE ,
2023-03-30 12:19:01 +03:00
. arg = & resume ,
. val = 1 ,
2019-01-11 17:03:54 +03:00
. descrip = " Automatically resume aborted files "
} ,
{
. longName = " update " ,
. shortName = ' u ' ,
. argInfo = POPT_ARG_NONE ,
2023-03-30 12:19:01 +03:00
. arg = & opt . update ,
. val = 1 ,
2019-01-11 17:03:54 +03:00
. descrip = " Download only when remote file is "
" newer than local file or local file "
" is missing "
} ,
{
. longName = " recursive " ,
2023-03-30 12:19:01 +03:00
. shortName = 0 ,
2019-01-11 17:03:54 +03:00
. argInfo = POPT_ARG_NONE ,
2023-03-30 12:19:01 +03:00
. arg = & recursive ,
. val = true ,
2019-01-11 17:03:54 +03:00
. descrip = " Recursively download files "
} ,
{
. longName = " blocksize " ,
. shortName = ' b ' ,
. argInfo = POPT_ARG_INT ,
. arg = & opt . blocksize ,
. val = ' b ' ,
. descrip = " Change number of bytes in a block "
} ,
{
. longName = " outputfile " ,
. shortName = ' o ' ,
. argInfo = POPT_ARG_STRING ,
. arg = & opt . outputfile ,
. val = ' o ' ,
. descrip = " Write downloaded data to specified file "
} ,
{
. longName = " stdout " ,
2023-03-30 12:19:01 +03:00
. shortName = 0 ,
2019-01-11 17:03:54 +03:00
. argInfo = POPT_ARG_NONE ,
2023-03-30 12:19:01 +03:00
. arg = & opt . send_stdout ,
. val = true ,
2019-01-11 17:03:54 +03:00
. descrip = " Write data to stdout "
} ,
{
. longName = " dots " ,
. shortName = ' D ' ,
. argInfo = POPT_ARG_NONE ,
2023-03-30 12:19:01 +03:00
. arg = & opt . dots ,
. val = 1 ,
2019-01-11 17:03:54 +03:00
. descrip = " Show dots as progress indication "
} ,
{
. longName = " quiet " ,
. shortName = ' q ' ,
. argInfo = POPT_ARG_NONE ,
2023-03-30 12:19:01 +03:00
. arg = & opt . quiet ,
. val = 1 ,
2019-01-11 17:03:54 +03:00
. descrip = " Be quiet "
} ,
{
. longName = " verbose " ,
. shortName = ' v ' ,
. argInfo = POPT_ARG_NONE ,
2023-03-30 12:19:01 +03:00
. arg = & opt . verbose ,
. val = 1 ,
2019-01-11 17:03:54 +03:00
. descrip = " Be verbose "
} ,
2022-10-02 00:45:18 +03:00
{
. longName = " limit-rate " ,
2023-03-30 12:19:01 +03:00
. shortName = 0 ,
2022-10-02 00:45:18 +03:00
. argInfo = POPT_ARG_INT ,
. arg = & opt . limit_rate ,
. val = ' l ' ,
. descrip = " Limit download speed to this many KB/s "
} ,
2015-10-28 14:37:36 +03:00
2023-03-30 12:19:01 +03:00
POPT_COMMON_SAMBA
POPT_COMMON_CONNECTION
POPT_COMMON_CREDENTIALS
POPT_LEGACY_S3
POPT_COMMON_VERSION
2004-01-07 03:43:52 +03:00
POPT_TABLEEND
} ;
2023-03-30 12:14:26 +03:00
poptContext pc = NULL ;
2023-03-30 12:19:01 +03:00
struct cli_credentials * creds = NULL ;
2023-03-31 10:31:11 +03:00
enum smb_encryption_setting encryption_state = SMB_ENCRYPTION_DEFAULT ;
2023-03-31 10:32:02 +03:00
enum credentials_use_kerberos use_kerberos = CRED_USE_KERBEROS_DESIRED ;
2023-03-31 10:31:11 +03:00
smbc_smb_encrypt_level encrypt_level = SMBC_ENCRYPTLEVEL_DEFAULT ;
2023-04-13 16:41:53 +03:00
#if 0
enum smb_signing_setting signing_state = SMB_SIGNING_DEFAULT ;
const char * use_signing = " auto " ;
# endif
2023-03-31 10:49:44 +03:00
bool is_nt_hash = false ;
2023-04-03 09:14:30 +03:00
uint32_t gensec_features ;
bool use_wbccache = false ;
2023-03-31 10:31:11 +03:00
SMBCCTX * smb_ctx = NULL ;
2023-04-13 16:41:53 +03:00
int rc ;
2004-01-07 03:43:52 +03:00
2015-03-21 22:00:06 +03:00
smb_init_locale ( ) ;
2005-12-29 01:48:54 +03:00
2023-03-30 12:19:01 +03:00
ok = samba_cmdline_init ( frame ,
SAMBA_CMDLINE_CONFIG_CLIENT ,
false ) ;
2023-03-29 09:48:12 +03:00
if ( ! ok ) {
goto done ;
}
2004-01-07 03:43:52 +03:00
# ifdef SIGWINCH
signal ( SIGWINCH , change_columns ) ;
# endif
signal ( SIGINT , signal_quit ) ;
signal ( SIGTERM , signal_quit ) ;
2023-03-30 12:19:01 +03:00
pc = samba_popt_get_context ( getprogname ( ) ,
argc ,
argv_const ,
long_options ,
0 ) ;
if ( pc = = NULL ) {
ok = false ;
goto done ;
}
creds = samba_cmdline_get_creds ( ) ;
2004-01-07 03:43:52 +03:00
2023-03-30 12:19:01 +03:00
while ( ( c = poptGetNextOpt ( pc ) ) ! = - 1 ) {
2016-01-24 13:17:20 +03:00
switch ( c ) {
2004-01-07 03:43:52 +03:00
case ' a ' :
2023-03-30 12:19:01 +03:00
cli_credentials_set_anonymous ( creds ) ;
2016-02-20 23:11:51 +03:00
break ;
2021-09-10 08:12:57 +03:00
case POPT_ERROR_BADOPT :
fprintf ( stderr , " \n Invalid option %s: %s \n \n " ,
poptBadOption ( pc , 0 ) , poptStrerror ( c ) ) ;
poptPrintUsage ( pc , stderr , 0 ) ;
2023-03-30 12:14:26 +03:00
ok = false ;
goto done ;
2004-01-07 03:43:52 +03:00
}
2023-04-06 01:00:00 +03:00
if ( c < - 1 ) {
fprintf ( stderr , " %s: %s \n " ,
poptBadOption ( pc , POPT_BADOPTION_NOALIAS ) ,
poptStrerror ( c ) ) ;
ok = false ;
goto done ;
}
2016-02-20 23:11:51 +03:00
}
2015-10-28 14:37:36 +03:00
if ( ( opt . send_stdout | | resume | | opt . outputfile ) & & opt . update ) {
2016-01-24 13:17:20 +03:00
fprintf ( stderr , " The -o, -R or -O and -U options can not be "
" used together. \n " ) ;
2023-03-30 12:14:26 +03:00
ok = true ;
2019-08-19 14:29:03 +03:00
goto done ;
2008-03-05 17:20:29 +03:00
}
2015-10-28 14:37:36 +03:00
if ( ( opt . send_stdout | | opt . outputfile ) & & recursive ) {
2016-01-24 13:17:20 +03:00
fprintf ( stderr , " The -o or -O and -R options can not be "
" used together. \n " ) ;
2023-03-30 12:14:26 +03:00
ok = true ;
2019-08-19 14:29:03 +03:00
goto done ;
2004-03-05 20:17:31 +03:00
}
2015-10-28 14:37:36 +03:00
if ( opt . outputfile & & opt . send_stdout ) {
2016-01-24 13:17:20 +03:00
fprintf ( stderr , " The -o and -O options can not be "
" used together. \n " ) ;
2023-03-30 12:14:26 +03:00
ok = true ;
2019-08-19 14:29:03 +03:00
goto done ;
2004-01-07 03:43:52 +03:00
}
2021-01-13 16:23:31 +03:00
samba_cmdline_burn ( argc , argv ) ;
2015-10-28 14:37:36 +03:00
2023-04-13 16:41:53 +03:00
smb_ctx = smbc_new_context ( ) ;
if ( smb_ctx = = NULL ) {
2004-01-07 03:43:52 +03:00
fprintf ( stderr , " Unable to initialize libsmbclient \n " ) ;
2023-04-13 16:41:53 +03:00
ok = false ;
2019-08-19 14:29:03 +03:00
goto done ;
2004-01-07 03:43:52 +03:00
}
2023-04-13 16:41:53 +03:00
smbc_setDebug ( smb_ctx , debuglevel_get ( ) ) ;
rc = smbc_setConfiguration ( smb_ctx , lp_default_path ( ) ) ;
if ( rc < 0 ) {
ok = false ;
goto done ;
}
smbc_setFunctionAuthDataWithContext ( smb_ctx ,
get_auth_data_with_context_fn ) ;
ok = smbc_init_context ( smb_ctx ) ;
if ( ! ok ) {
2023-03-31 10:31:11 +03:00
goto done ;
}
2023-04-13 16:41:53 +03:00
smbc_set_context ( smb_ctx ) ;
2004-01-07 03:43:52 +03:00
2023-03-31 10:31:11 +03:00
encryption_state = cli_credentials_get_smb_encryption ( creds ) ;
switch ( encryption_state ) {
case SMB_ENCRYPTION_REQUIRED :
encrypt_level = SMBC_ENCRYPTLEVEL_REQUIRE ;
break ;
case SMB_ENCRYPTION_DESIRED :
case SMB_ENCRYPTION_IF_REQUIRED :
encrypt_level = SMBC_ENCRYPTLEVEL_REQUEST ;
break ;
case SMB_ENCRYPTION_OFF :
encrypt_level = SMBC_ENCRYPTLEVEL_NONE ;
break ;
case SMB_ENCRYPTION_DEFAULT :
encrypt_level = SMBC_ENCRYPTLEVEL_DEFAULT ;
break ;
}
2008-01-05 11:51:50 +03:00
if ( smb_encrypt ) {
2023-03-31 10:31:11 +03:00
encrypt_level = SMBC_ENCRYPTLEVEL_REQUIRE ;
2008-01-05 11:51:50 +03:00
}
2023-03-31 10:31:11 +03:00
smbc_setOptionSmbEncryptionLevel ( smb_ctx , encrypt_level ) ;
2010-07-04 13:02:21 +04:00
2023-04-13 16:41:53 +03:00
#if 0
signing_state = cli_credentials_get_smb_signing ( creds ) ;
if ( encryption_state > = SMB_ENCRYPTION_DESIRED ) {
signing_state = SMB_SIGNING_REQUIRED ;
}
switch ( signing_state ) {
case SMB_SIGNING_REQUIRED :
use_signing = " required " ;
break ;
case SMB_SIGNING_DEFAULT :
case SMB_SIGNING_DESIRED :
case SMB_SIGNING_IF_REQUIRED :
use_signing = " yes " ;
break ;
case SMB_SIGNING_OFF :
use_signing = " off " ;
break ;
default :
use_signing = " auto " ;
break ;
}
/* FIXME: There is no libsmbclient function to set signing state */
# endif
2023-03-31 10:32:02 +03:00
use_kerberos = cli_credentials_get_kerberos_state ( creds ) ;
switch ( use_kerberos ) {
case CRED_USE_KERBEROS_REQUIRED :
smbc_setOptionUseKerberos ( smb_ctx , true ) ;
smbc_setOptionFallbackAfterKerberos ( smb_ctx , false ) ;
break ;
case CRED_USE_KERBEROS_DESIRED :
smbc_setOptionUseKerberos ( smb_ctx , true ) ;
smbc_setOptionFallbackAfterKerberos ( smb_ctx , true ) ;
break ;
case CRED_USE_KERBEROS_DISABLED :
smbc_setOptionUseKerberos ( smb_ctx , false ) ;
break ;
}
2023-03-31 10:49:44 +03:00
/* Check if the password supplied is an NT hash */
is_nt_hash = cli_credentials_is_password_nt_hash ( creds ) ;
smbc_setOptionUseNTHash ( smb_ctx , is_nt_hash ) ;
2023-04-03 09:14:30 +03:00
/* Check if we should use the winbind ccache */
gensec_features = cli_credentials_get_gensec_features ( creds ) ;
use_wbccache = ( gensec_features & GENSEC_FEATURE_NTLM_CCACHE ) ;
smbc_setOptionUseCCache ( smb_ctx , use_wbccache ) ;
2004-01-07 03:43:52 +03:00
columns = get_num_cols ( ) ;
2010-09-09 00:29:00 +04:00
total_start_time = time_mono ( NULL ) ;
2004-01-07 03:43:52 +03:00
2016-01-24 13:17:20 +03:00
while ( ( file = poptGetArg ( pc ) ) ) {
if ( ! recursive ) {
2023-03-30 12:14:26 +03:00
ok = smb_download_file ( file , " " , recursive , resume ,
2015-10-28 14:37:36 +03:00
true , opt . outputfile ) ;
2016-01-24 13:17:20 +03:00
} else {
2023-03-30 12:14:26 +03:00
ok = smb_download_dir ( file , " " , resume ) ;
2016-01-24 13:17:20 +03:00
}
2004-01-07 03:43:52 +03:00
}
2019-08-19 14:29:03 +03:00
done :
poptFreeContext ( pc ) ;
2007-09-04 09:39:06 +04:00
TALLOC_FREE ( frame ) ;
2023-03-30 12:14:26 +03:00
if ( ok ) {
2010-01-28 21:38:24 +03:00
clean_exit ( ) ;
}
2023-03-30 12:14:26 +03:00
return ok ? 0 : 1 ;
2004-01-07 03:43:52 +03:00
}