summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/client/client.c138
-rw-r--r--source3/lib/xfile.c34
2 files changed, 150 insertions, 22 deletions
diff --git a/source3/client/client.c b/source3/client/client.c
index 894329a5d1..8d057573f3 100644
--- a/source3/client/client.c
+++ b/source3/client/client.c
@@ -2,7 +2,7 @@
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
@@ -649,15 +649,16 @@ static int cmd_du(void)
/****************************************************************************
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;
@@ -677,7 +678,18 @@ static int do_get(char *rname,char *lname)
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) {
@@ -704,7 +716,7 @@ static int do_get(char *rname,char *lname)
}
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;
@@ -717,7 +729,7 @@ static int do_get(char *rname,char *lname)
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));
@@ -782,7 +794,7 @@ static int cmd_get(void)
next_token_nr(NULL,lname,NULL,sizeof(lname));
- return do_get(rname, lname);
+ return do_get(rname, lname, False);
}
@@ -816,7 +828,7 @@ static void do_mget(file_info *finfo)
if (!(finfo->mode & aDIR)) {
pstrcpy(rname,cur_dir);
pstrcat(rname,finfo->name);
- do_get(rname,finfo->name);
+ do_get(rname, finfo->name, False);
return;
}
@@ -880,7 +892,7 @@ static int cmd_more(void)
}
dos_clean_name(rname);
- rc = do_get(rname,lname);
+ rc = do_get(rname, lname, False);
pager=getenv("PAGER");
@@ -1046,19 +1058,31 @@ static int cmd_altname(void)
/****************************************************************************
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);
@@ -1075,6 +1099,12 @@ static int do_put(char *rname,char *lname)
/* 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) {
@@ -1104,7 +1134,7 @@ static int do_put(char *rname,char *lname)
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));
@@ -1192,7 +1222,7 @@ static int cmd_put(void)
}
}
- return do_put(rname,lname);
+ return do_put(rname, lname, False);
}
/*************************************
@@ -1384,7 +1414,7 @@ static int cmd_mput(void)
dos_format(rname);
- do_put(rname, lname);
+ do_put(rname, lname, False);
}
free_file_list(file_list);
SAFE_FREE(quest);
@@ -1456,7 +1486,7 @@ static int cmd_print(void)
slprintf(rname, sizeof(rname)-1, "stdin-%d", (int)sys_getpid());
}
- return do_put(rname, lname);
+ return do_put(rname, lname, False);
}
@@ -1866,8 +1896,8 @@ static int cmd_printmode(void)
}
/****************************************************************************
-do the lcd command
-****************************************************************************/
+ do the lcd command
+ ****************************************************************************/
static int cmd_lcd(void)
{
fstring buf;
@@ -1881,8 +1911,70 @@ static int cmd_lcd(void)
}
/****************************************************************************
-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)
{
@@ -2009,7 +2101,9 @@ static struct
{"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}},
diff --git a/source3/lib/xfile.c b/source3/lib/xfile.c
index b5710f3a39..7621712e9a 100644
--- a/source3/lib/xfile.c
+++ b/source3/lib/xfile.c
@@ -43,6 +43,7 @@ XFILE *x_stderr = &_x_stderr;
#define X_FLAG_EOF 1
#define X_FLAG_ERROR 2
+#define X_FLAG_EINVAL 3
/* simulate setvbuf() */
int x_setvbuf(XFILE *f, char *buf, int mode, size_t size)
@@ -341,3 +342,36 @@ char *x_fgets(char *s, int size, XFILE *stream)
*s = 0;
return s0;
}
+
+/* trivial seek, works only for SEEK_SET and SEEK_END if SEEK_CUR is
+ * set then an error is returned */
+off_t x_tseek(XFILE *f, off_t offset, int whence)
+{
+ if (f->flags & X_FLAG_ERROR)
+ return -1;
+
+ /* only SEEK_SET and SEEK_END are supported */
+ /* SEEK_CUR needs internal offset counter */
+ if (whence != SEEK_SET && whence != SEEK_END) {
+ f->flags |= X_FLAG_EINVAL;
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* empty the buffer */
+ switch (f->open_flags & O_ACCMODE) {
+ case O_RDONLY:
+ f->bufused = 0;
+ break;
+ case O_WRONLY:
+ if (x_fflush(f) != 0)
+ return -1;
+ break;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+
+ f->flags &= ~X_FLAG_EOF;
+ return (off_t)sys_lseek(f->fd, offset, whence);
+}