[PATCH] quick hack for 'resume' support in sftp
Thomas Wouters
thomas at xs4all.net
Tue Sep 11 06:58:20 EST 2001
I saw several questions regarding 'resume transfer' support in sftp come up,
in the archives, but no real satisfying answer. I had a particular itch
myself, so I scratched it with a quick hack. Patch attached, since it's not
really big.
To explain, I need to use ssh (scp or sftp) to transfer files to and from a
Windows box. No other method is available. And the Windows machine has no
rsync or unixlike tools or cygwin or anything else I can use to fake
resuming transfers, so I really have to have the resume support in sftp
itself. I noticed the protocol supported it just fine, so I did a little
dirty hacking and added a '-r' option to sftp that enables resuming.
It's very rough: it triggers off (local) name alone, though it refuses to
append to a file that's already larger than the new file. It cuts a bit off
the end of the local file before resuming, but that's mostly out of
paranoia. It should really compare a couple of blocks of the end of the
local file with the remote file, but I didn't want to bother with that. It
should really present a choice when it discovers a possibly partial local
file with the same name, the way NcFTP does, but, again, I didn't want to
bother with that. (And, frankly, the rest of sftp could do with a little
more NcFTP or (Net)BSD FTP interface sprinkled in ;) But one thing at a
time.)
If there's any interest in getting this in the distributed sftp (in a more
mature form, of course) I can get it in better shape, but I'm honestly
clueless on the direction of ssh and sftp development. If this kind of thing
is really not wanted, I guess I'll keep a patch somewhere on a website
instead. I'd like to note, though, that in searching for an sftp version
with resume support I found a number of Windows clients that claimed to
support resuming in their sftp clients :-)
Regards,
Thomas.
PS: Please include me in any responses, I'm not on the list right now.
--
Thomas Wouters <thomas at xs4all.net>
Hi! I'm a .signature virus! copy me into your .signature file to help me spread!
-------------- next part --------------
diff -cr openssh-2.9p2/sftp-client.c openssh-2.9p2.resume/sftp-client.c
*** openssh-2.9p2/sftp-client.c Fri Apr 6 01:26:33 2001
--- openssh-2.9p2.resume/sftp-client.c Mon Sep 10 18:04:36 2001
***************
*** 48,53 ****
--- 48,56 ----
/* XXX: what should this be? */
#define COPY_SIZE 8192
+ /* resume or not (from sftp.c) */
+ extern int enable_resume;
+
/* Message ID */
static u_int msg_id = 1;
***************
*** 682,687 ****
--- 685,691 ----
Buffer msg;
Attrib junk, *a;
int status;
+ struct stat localfile;
a = do_stat(fd_in, fd_out, remote_path, 0);
if (a == NULL)
***************
*** 698,705 ****
error("Cannot download a directory: %s", remote_path);
return(-1);
}
!
! local_fd = open(local_path, O_WRONLY | O_CREAT | O_TRUNC, mode);
if (local_fd == -1) {
error("Couldn't open local file \"%s\" for writing: %s",
local_path, strerror(errno));
--- 702,720 ----
error("Cannot download a directory: %s", remote_path);
return(-1);
}
!
! if (enable_resume && (stat(local_path, &localfile) == 0) &&
! S_ISREG(localfile.st_mode) && (localfile.st_size < a->size)) {
! local_fd = open(local_path, O_WRONLY, mode);
! offset = localfile.st_size - (localfile.st_size % 16384);
! if (local_fd != -1) {
! ftruncate(local_fd, offset);
! lseek(local_fd, 0, SEEK_END);
! }
! } else {
! local_fd = open(local_path, O_WRONLY | O_CREAT | O_TRUNC, mode);
! offset = 0;
! }
if (local_fd == -1) {
error("Couldn't open local file \"%s\" for writing: %s",
local_path, strerror(errno));
***************
*** 727,733 ****
}
/* Read from remote and write to local */
- offset = 0;
for(;;) {
u_int len;
char *data;
--- 742,747 ----
diff -cr openssh-2.9p2/sftp.1 openssh-2.9p2.resume/sftp.1
*** openssh-2.9p2/sftp.1 Sun Apr 22 19:17:46 2001
--- openssh-2.9p2.resume/sftp.1 Mon Sep 10 18:07:56 2001
***************
*** 82,87 ****
--- 82,89 ----
.Xr ssh 1 .
.It Fl v
Raise logging level. This option is also passed to ssh.
+ .It Fl r
+ Enable resuming of downloads. This might not work correctly.
.El
.Sh INTERACTIVE COMMANDS
Once in interactive mode,
diff -cr openssh-2.9p2/sftp.c openssh-2.9p2.resume/sftp.c
*** openssh-2.9p2/sftp.c Mon Apr 16 10:26:42 2001
--- openssh-2.9p2.resume/sftp.c Mon Sep 10 17:52:39 2001
***************
*** 48,53 ****
--- 48,54 ----
#include "scp-common.h"
int use_ssh1 = 0;
+ int enable_resume = 0;
char *ssh_program = _PATH_SSH_PROGRAM;
char *sftp_server = NULL;
FILE* infile;
***************
*** 148,154 ****
void
usage(void)
{
! fprintf(stderr, "usage: sftp [-1vC] [-b batchfile] [-osshopt=value] [user@]host[:file [file]]\n");
exit(1);
}
--- 149,155 ----
void
usage(void)
{
! fprintf(stderr, "usage: sftp [-1vCr] [-b batchfile] [-osshopt=value] [user@]host[:file [file]]\n");
exit(1);
}
***************
*** 167,173 ****
infile = stdin; /* Read from STDIN unless changed by -b */
debug_level = compress_flag = 0;
! while ((ch = getopt(argc, argv, "1hvCo:s:S:b:")) != -1) {
switch (ch) {
case 'C':
compress_flag = 1;
--- 168,174 ----
infile = stdin; /* Read from STDIN unless changed by -b */
debug_level = compress_flag = 0;
! while ((ch = getopt(argc, argv, "1hvCro:s:S:b:")) != -1) {
switch (ch) {
case 'C':
compress_flag = 1;
***************
*** 197,202 ****
--- 198,206 ----
fatal("%s (%s).", strerror(errno), optarg);
} else
fatal("Filename already specified.");
+ break;
+ case 'r':
+ enable_resume = 1;
break;
case 'h':
default:
More information about the openssh-unix-dev
mailing list