/*
- Unix SMB/Netbios implementation.
- Version 3.0.
+ Unix SMB/CIFS implementation.
SMB client
Copyright (C) Andrew Tridgell 1994-1998
- Copyright (C) Simo Sorce 2001
+ Copyright (C) Simo Sorce 2001-2002
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#define NO_SYSLOG
#include "includes.h"
-
+#include "../client/client_proto.h"
#ifndef REGISTER
#define REGISTER 0
#endif
extern BOOL AllowDebugChange;
static int port = 0;
pstring cur_dir = "\\";
-pstring cd_path = "";
+static pstring cd_path = "";
static pstring service;
static pstring desthost;
extern pstring global_myname;
#define FID_UNUSED (0xFFFF)
time_t newer_than = 0;
-int archive_level = 0;
+static int archive_level = 0;
-BOOL translation = False;
+static BOOL translation = False;
static BOOL have_ip;
/* clitar bits end */
-mode_t myumask = 0755;
+static mode_t myumask = 0755;
-BOOL prompt = True;
+static BOOL prompt = True;
-int printmode = 1;
+static int printmode = 1;
static BOOL recurse = False;
BOOL lowercase = False;
-struct in_addr dest_ip;
+static struct in_addr dest_ip;
#define SEPARATORS " \t\n\r"
-BOOL abort_mget = True;
+static BOOL abort_mget = True;
-pstring fileselection = "";
+static pstring fileselection = "";
extern file_info def_finfo;
/* timing globals */
int get_total_size = 0;
int get_total_time_ms = 0;
-int put_total_size = 0;
-int put_total_time_ms = 0;
+static int put_total_size = 0;
+static int put_total_time_ms = 0;
/* totals globals */
static double dir_total;
#define USENMB
+/* some forward declarations */
+static struct cli_state *do_connect(const char *server, const char *share);
+
/****************************************************************************
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.
if (*fileselection &&
!mask_match(finfo->name,fileselection,False)) {
- DEBUG(3,("match_match %s failed\n", finfo->name));
+ DEBUG(3,("mask_match %s failed\n", finfo->name));
return False;
}
/****************************************************************************
get a file from rname to lname
****************************************************************************/
-static int do_get(char *rname,char *lname)
+static int do_get(char *rname, char *lname, BOOL reget)
{
- int handle=0,fnum;
+ int handle = 0, fnum;
BOOL newhandle = False;
char *data;
struct timeval tp_start;
int read_size = io_bufsize;
uint16 attr;
size_t size;
+ off_t start = 0;
off_t nread = 0;
int rc = 0;
if(!strcmp(lname,"-")) {
handle = fileno(stdout);
} else {
- handle = sys_open(lname,O_WRONLY|O_CREAT|O_TRUNC,0644);
+ if (reget) {
+ handle = sys_open(lname, O_WRONLY|O_CREAT, 0644);
+ if (handle >= 0) {
+ start = sys_lseek(handle, 0, SEEK_END);
+ if (start == -1) {
+ d_printf("Error seeking local file\n");
+ return 1;
+ }
+ }
+ } else {
+ handle = sys_open(lname, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+ }
newhandle = True;
}
if (handle < 0) {
}
DEBUG(2,("getting file %s of size %.0f as %s ",
- lname, (double)size, lname));
+ rname, (double)size, lname));
if(!(data = (char *)malloc(read_size))) {
d_printf("malloc fail for size %d\n", read_size);
}
while (1) {
- int n = cli_read(cli, fnum, data, nread, read_size);
+ int n = cli_read(cli, fnum, data, nread + start, read_size);
if (n <= 0) break;
nread += n;
}
- if (nread < size) {
+ if (nread + start < size) {
DEBUG (0, ("Short read when getting file %s. Only got %ld bytes.\n",
rname, (long)nread));
next_token_nr(NULL,lname,NULL,sizeof(lname));
- return do_get(rname, lname);
+ return do_get(rname, lname, False);
}
if (!(finfo->mode & aDIR)) {
pstrcpy(rname,cur_dir);
pstrcat(rname,finfo->name);
- do_get(rname,finfo->name);
+ do_get(rname, finfo->name, False);
return;
}
}
dos_clean_name(rname);
- rc = do_get(rname,lname);
+ rc = do_get(rname, lname, False);
pager=getenv("PAGER");
/****************************************************************************
put a single file
****************************************************************************/
-static int do_put(char *rname,char *lname)
+static int do_put(char *rname, char *lname, BOOL reput)
{
int fnum;
XFILE *f;
- int nread=0;
- char *buf=NULL;
- int maxwrite=io_bufsize;
+ int start = 0;
+ int nread = 0;
+ char *buf = NULL;
+ int maxwrite = io_bufsize;
int rc = 0;
struct timeval tp_start;
GetTimeOfDay(&tp_start);
- fnum = cli_open(cli, rname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
+ if (reput) {
+ fnum = cli_open(cli, rname, O_RDWR|O_CREAT, DENY_NONE);
+ if (fnum >= 0) {
+ if (!cli_qfileinfo(cli, fnum, NULL, &start, NULL, NULL, NULL, NULL, NULL) &&
+ !cli_getattrE(cli, fnum, NULL, &start, NULL, NULL, NULL)) {
+ d_printf("getattrib: %s\n",cli_errstr(cli));
+ return 1;
+ }
+ }
+ } else {
+ fnum = cli_open(cli, rname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
+ }
if (fnum == -1) {
d_printf("%s opening remote file %s\n",cli_errstr(cli),rname);
}
/* allow files to be piped into smbclient
- jdblair 24.jun.98 */
+ 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) {
break;
}
- ret = cli_write(cli, fnum, 0, buf, nread, n);
+ ret = cli_write(cli, fnum, 0, buf, nread + start, n);
if (n != ret) {
d_printf("Error writing file: %s\n", cli_errstr(cli));
}
- x_fclose(f);
+ if (f != x_stdin) {
+ x_fclose(f);
+ }
+
SAFE_FREE(buf);
{
}
}
- return do_put(rname,lname);
+ return do_put(rname, lname, False);
}
/*************************************
/* if (!recurse) continue; */
SAFE_FREE(quest);
- asprintf(&quest, "Put directory %s? ", lname);
+ if (asprintf(&quest, "Put directory %s? ", lname) < 0) break;
if (prompt && !yesno(quest)) { /* No */
/* Skip the directory */
lname[strlen(lname)-1] = '/';
break;
} else { /* Yes */
SAFE_FREE(rname);
- asprintf(&rname, "%s%s", cur_dir, lname);
+ if(asprintf(&rname, "%s%s", cur_dir, lname) < 0) break;
dos_format(rname);
if (!cli_chkpath(cli, rname) &&
!do_mkdir(rname)) {
continue;
} else {
SAFE_FREE(quest);
- asprintf(&quest,"Put file %s? ", lname);
+ if (asprintf(&quest,"Put file %s? ", lname) < 0) break;
if (prompt && !yesno(quest)) /* No */
continue;
/* Yes */
SAFE_FREE(rname);
- asprintf(&rname, "%s%s", cur_dir, lname);
+ if (asprintf(&rname, "%s%s", cur_dir, lname) < 0) break;
}
dos_format(rname);
- do_put(rname, lname);
+ do_put(rname, lname, False);
}
free_file_list(file_list);
SAFE_FREE(quest);
slprintf(rname, sizeof(rname)-1, "stdin-%d", (int)sys_getpid());
}
- return do_put(rname, lname);
+ return do_put(rname, lname, False);
}
}
/****************************************************************************
-do the lcd command
-****************************************************************************/
+ do the lcd command
+ ****************************************************************************/
static int cmd_lcd(void)
{
fstring buf;
}
/****************************************************************************
-list a share name
-****************************************************************************/
+ get a file restarting at end of local file
+ ****************************************************************************/
+static int cmd_reget(void)
+{
+ pstring local_name;
+ pstring remote_name;
+ char *p;
+
+ pstrcpy(remote_name, cur_dir);
+ pstrcat(remote_name, "\\");
+
+ p = remote_name + strlen(remote_name);
+
+ if (!next_token_nr(NULL, p, NULL, sizeof(remote_name) - strlen(remote_name))) {
+ d_printf("reget <filename>\n");
+ return 1;
+ }
+ pstrcpy(local_name, p);
+ dos_clean_name(remote_name);
+
+ next_token_nr(NULL, local_name, NULL, sizeof(local_name));
+
+ return do_get(remote_name, local_name, True);
+}
+
+/****************************************************************************
+ put a file restarting at end of local file
+ ****************************************************************************/
+static int cmd_reput(void)
+{
+ pstring local_name;
+ pstring remote_name;
+ fstring buf;
+ char *p = buf;
+ SMB_STRUCT_STAT st;
+
+ pstrcpy(remote_name, cur_dir);
+ pstrcat(remote_name, "\\");
+
+ if (!next_token_nr(NULL, p, NULL, sizeof(buf))) {
+ d_printf("reput <filename>\n");
+ return 1;
+ }
+ pstrcpy(local_name, p);
+
+ if (!file_exist(local_name, &st)) {
+ d_printf("%s does not exist\n", local_name);
+ return 1;
+ }
+
+ if (next_token_nr(NULL, p, NULL, sizeof(buf)))
+ pstrcat(remote_name, p);
+ else
+ pstrcat(remote_name, local_name);
+
+ dos_clean_name(remote_name);
+
+ return do_put(remote_name, local_name, True);
+}
+
+
+/****************************************************************************
+ list a share name
+ ****************************************************************************/
static void browse_fn(const char *name, uint32 m,
const char *comment, void *state)
{
* field is NULL, and NULL in that field is used in process_tok()
* (below) to indicate the end of the list. crh
*/
-struct
+static struct
{
char *name;
int (*fn)(void);
} commands[] =
{
{"?",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}},
- {"!",NULL,"run a shell command on the local system",{COMPL_NONE,COMPL_NONE}},
{"altname",cmd_altname,"<file> show alt name",{COMPL_NONE,COMPL_NONE}},
{"archive",cmd_archive,"<level>\n0=ignore archive bit\n1=only get archive files\n2=only get archive files and reset archive bit\n3=get all files and reset archive bit",{COMPL_NONE,COMPL_NONE}},
{"blocksize",cmd_block,"blocksize <number> (default 20)",{COMPL_NONE,COMPL_NONE}},
{"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}},
{"setmode",cmd_setmode,"filename <setmode string> change modes of file",{COMPL_REMOTE,COMPL_NONE}},
{"tar",cmd_tar,"tar <c|x>[IXFqbgNan] current directory to/from <file name>",{COMPL_NONE,COMPL_NONE}},
{"tarmode",cmd_tarmode,"<full|inc|reset|noreset> tar's behaviour towards archive bits",{COMPL_NONE,COMPL_NONE}},
{"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,{COMPL_NONE,COMPL_NONE}}
};
char *ptr;
int rc = 0;
+ /* establish the connection if not already */
+
+ if (!cli) {
+ cli = do_connect(desthost, service);
+ if (!cli)
+ return 0;
+ }
+
while (cmd[0] != '\0') {
char *p;
fstring tok;
timeout.tv_sec = 0;
timeout.tv_usec = 0;
- sys_select_intr(cli->fd+1,&fds,&timeout);
+ sys_select_intr(cli->fd+1,&fds,NULL,NULL,&timeout);
/* We deliberately use receive_smb instead of
client_receive_smb as we want to receive
/*****************************************************
return a connection to a server
*******************************************************/
-struct cli_state *do_connect(const char *server, const char *share)
+static struct cli_state *do_connect(const char *server, const char *share)
{
struct cli_state *c;
struct nmb_name called, calling;
if (!cli_send_tconX(c, sharename, "?????",
password, strlen(password)+1)) {
- d_printf("tree connect failed: %s\n", cli_errstr(c));
- cli_shutdown(c);
- return NULL;
+ pstring full_share;
+
+ /*
+ * Some servers require \\server\share for the share
+ * while others are happy with share as we gave above
+ * Lets see if we give it the long form if it works
+ */
+ pstrcpy(full_share, "\\\\");
+ pstrcat(full_share, server);
+ pstrcat(full_share, "\\");
+ pstrcat(full_share, sharename);
+ if (!cli_send_tconX(c, full_share, "?????", password,
+ strlen(password) + 1)) {
+
+ d_printf("tree connect failed: %s\n", cli_errstr(c));
+ cli_shutdown(c);
+ return NULL;
+ }
}
DEBUG(4,(" tconx ok\n"));
static int do_tar_op(char *base_directory)
{
int ret;
- cli = do_connect(desthost, service);
- if (!cli)
- return 1;
+
+ /* do we already have a connection? */
+ if (!cli) {
+ cli = do_connect(desthost, service);
+ if (!cli)
+ return 1;
+ }
recurse=True;
{
struct in_addr ip;
struct nmb_name called, calling;
-
- zero_ip(&ip);
+ fstring server_name;
+ char name_type_hex[10];
make_nmb_name(&calling, global_myname, 0x0);
make_nmb_name(&called , desthost, name_type);
+ safe_strcpy(server_name, desthost, sizeof(server_name));
+ snprintf(name_type_hex, sizeof(name_type_hex), "#%X", name_type);
+ safe_strcat(server_name, name_type_hex, sizeof(server_name));
+
zero_ip(&ip);
if (have_ip) ip = dest_ip;
- if (!(cli=cli_initialise(NULL)) || (cli_set_port(cli, port) != port) || !cli_connect(cli, desthost, &ip)) {
+ if (!(cli=cli_initialise(NULL)) || (cli_set_port(cli, port) != port) ||
+ !cli_connect(cli, server_name, &ip)) {
d_printf("Connection to %s failed\n", desthost);
return 1;
}
}
+/**
+ * Process "-L hostname" option.
+ *
+ * We don't actually do anything yet -- we just stash the name in a
+ * global variable and do the query when all options have been read.
+ **/
+static void remember_query_host(const char *arg,
+ pstring query_host)
+{
+ char *slash;
+
+ while (*arg == '\\' || *arg == '/')
+ arg++;
+ pstrcpy(query_host, arg);
+ if ((slash = strchr(query_host, '/'))
+ || (slash = strchr(query_host, '\\'))) {
+ *slash = 0;
+ }
+}
+
+
/****************************************************************************
main program
****************************************************************************/
}
DEBUGLEVEL = old_debug;
-#ifdef WITH_SSL
- sslutil_init(0);
-#endif
-
pstrcpy(workgroup,lp_workgroup());
load_interfaces();
got_pass = True;
memset(strchr_m(getenv("USER"),'%')+1,'X',strlen(password));
}
- strupper(username);
}
/* modification to support PASSWD environmental var
if (*username == 0 && getenv("LOGNAME")) {
pstrcpy(username,getenv("LOGNAME"));
- strupper(username);
}
if (*username == 0) {
break;
case 'L':
- p = optarg;
- while(*p == '\\' || *p == '/')
- p++;
- pstrcpy(query_host,p);
+ remember_query_host(optarg, query_host);
break;
case 't':
pstrcpy(term_code, optarg);