sftp client reget reput
Greg.Hayes
ghayes at usi.net
Fri Oct 31 01:49:37 EST 2003
we have implemented this function for 3.1p1, and have been using it in
production sense may 2002. The patch has been ported to 3.7.1p2, we have
been using it in 3.7.1p2 for awhile, if anyone is interested, here it is.
This is the same patch David Bradford talked about on 2002-06-05
Regards,
Greg Hayes
diff -u -r openssh-3.7.1p2/sftp-client.c openssh-3.7.1p2_sftp/sftp-client.c
--- openssh-3.7.1p2/sftp-client.c 2003-07-02 22:46:57.000000000 -0500
+++ openssh-3.7.1p2_sftp/sftp-client.c 2003-10-16 10:09:51.000000000 -0500
@@ -735,8 +735,13 @@
}
int
+#ifdef REGET
+do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
+ int pflag, int rflag)
+#else
do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
int pflag)
+#endif
{
Attrib junk, *a;
Buffer msg;
@@ -798,8 +803,17 @@
return(-1);
}
- local_fd = open(local_path, O_WRONLY | O_CREAT | O_TRUNC,
- mode | S_IWRITE);
+#ifdef REGET
+ if (rflag)
+ local_fd = open(local_path, O_WRONLY, mode | S_IWRITE);
+ else {
+ local_fd = open(local_path, O_WRONLY | O_CREAT | O_TRUNC,
+ mode | S_IWRITE);
+ }
+#else
+ local_fd = open(local_path, O_WRONLY | O_CREAT | O_TRUNC,
+ mode | S_IWRITE);
+#endif
if (local_fd == -1) {
error("Couldn't open local file \"%s\" for writing: %s",
local_path, strerror(errno));
@@ -810,6 +821,16 @@
/* Read from remote and write to local */
write_error = read_error = write_errno = num_req = offset = 0;
+
+#ifdef REGET
+ if (rflag) {
+ long posn;
+ posn = lseek(local_fd, 0L, SEEK_END);
+ debug3("reget: restarting at file position %ld\n", posn);
+ offset = (u_int64_t)posn;
+ }
+#endif
+
max_req = 1;
progress_counter = 0;
@@ -969,8 +990,13 @@
}
int
+#ifdef REGET
+do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
+ int pflag, int rflag)
+#else
do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
int pflag)
+#endif
{
int local_fd, status;
u_int handle_len, id, type;
@@ -1023,6 +1049,13 @@
buffer_put_char(&msg, SSH2_FXP_OPEN);
buffer_put_int(&msg, id);
buffer_put_cstring(&msg, remote_path);
+
+#ifdef REGET
+ if(rflag)
+ buffer_put_int(&msg, SSH2_FXF_WRITE);
+ else
+#endif
+
buffer_put_int(&msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC);
encode_attrib(&msg, &a);
send_msg(conn->fd_out, &msg);
@@ -1041,7 +1074,44 @@
data = xmalloc(conn->transfer_buflen);
/* Read from local and write to remote */
+#ifdef REGET
+ if(rflag) {
+ Attrib *attrs;
+ if (!(attrs = do_fstat(conn, handle, handle_len, 0))) {
+ error("read size of \"%s\": %s",
+ local_path, strerror(errno));
+ close(local_fd);
+ buffer_free(&msg);
+ return(-1);
+ }
+ if (!(attrs->flags & SSH2_FILEXFER_ATTR_SIZE)) {
+ error("read size of %s: size was not given\n", local_path);
+ close(local_fd);
+ buffer_free(&msg);
+ return(-1);
+ }
+ offset = attrs->size;
+ debug3("reput: restarting at file position %d\n", (int)offset);
+ if (offset > LONG_MAX) {
+ error("reput: remote file is larger than we can deal with\n");
+ close(local_fd);
+ buffer_free(&msg);
+ return(-1);
+ }
+ if(lseek(local_fd, offset, SEEK_SET) == -1) {
+ error("seek on local file %s failed: %s\n", local_path, strerror(errno));
+ close(local_fd);
+ buffer_free(&msg);
+ return(-1);
+ }
+ /* if (lseek(local_fd, offset, SEEK_SET) != 0)
+ lseek(local_fd, 0, SEEK_END); */
+ } else {
+ offset = 0;
+ }
+#else
offset = 0;
+#endif
if (showprogress)
start_progress_meter(local_path, sb.st_size, &offset);
else
diff -u -r openssh-3.7.1p2/sftp-client.h openssh-3.7.1p2_sftp/sftp-client.h
--- openssh-3.7.1p2/sftp-client.h 2002-09-11 18:54:26.000000000 -0500
+++ openssh-3.7.1p2_sftp/sftp-client.h 2003-10-16 10:11:34.000000000 -0500
@@ -96,12 +96,24 @@
* Download 'remote_path' to 'local_path'. Preserve permissions and times
* if 'pflag' is set
*/
+
+/* undef this to completely remove the reget functionality */
+#define REGET
+
+#ifdef REGET
+int do_download(struct sftp_conn *, char *, char *, int, int);
+#else
int do_download(struct sftp_conn *, char *, char *, int);
+#endif
/*
* Upload 'local_path' to 'remote_path'. Preserve permissions and times
* if 'pflag' is set
*/
+#ifdef REGET
+int do_upload(struct sftp_conn *, char *, char *, int, int);
+#else
int do_upload(struct sftp_conn *, char *, char *, int);
+#endif
#endif
diff -u -r openssh-3.7.1p2/sftp-int.c openssh-3.7.1p2_sftp/sftp-int.c
--- openssh-3.7.1p2/sftp-int.c 2003-09-23 04:24:21.000000000 -0500
+++ openssh-3.7.1p2_sftp/sftp-int.c 2003-10-16 10:52:02.000000000 -0500
@@ -82,6 +82,11 @@
#define I_VERSION 22
#define I_PROGRESS 23
+#ifdef REGET
+# define I_REGET 24
+# define I_REPUT 25
+#endif
+
struct CMD {
const char *c;
const int n;
@@ -118,6 +123,10 @@
{ "rmdir", I_RMDIR },
{ "symlink", I_SYMLINK },
{ "version", I_VERSION },
+#ifdef REGET
+ { "reget", I_REGET },
+ { "reput", I_REPUT },
+#endif
{ "!", I_SHELL },
{ "?", I_HELP },
{ NULL, -1}
@@ -134,6 +143,9 @@
printf("chown own path Change owner of file 'path' to 'own'\n");
printf("help Display this help text\n");
printf("get remote-path [local-path] Download file\n");
+#ifdef REGET
+ printf("reget remote-path [local-path] Resume an interupted download\n");
+#endif
printf("lls [ls-options [path]] Display local directory listing\n");
printf("ln oldpath newpath Symlink remote file\n");
printf("lmkdir path Create local directory\n");
@@ -143,6 +155,9 @@
printf("mkdir path Create remote directory\n");
printf("progress Toggle display of progress meter\n");
printf("put local-path [remote-path] Upload file\n");
+#ifdef USI_MODS
+ printf("reput local-path [remote-path] Resume an interupted upload\n");
+#endif
printf("pwd Display remote working directory\n");
printf("exit Quit sftp\n");
printf("quit Quit sftp\n");
@@ -430,7 +445,11 @@
}
static int
+#ifdef REGET
+process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd, int pflag, int rflag)
+#else
process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd, int pflag)
+#endif
{
char *abs_src = NULL;
char *abs_dst = NULL;
@@ -482,7 +501,11 @@
abs_dst = tmp;
printf("Fetching %s to %s\n", g.gl_pathv[i], abs_dst);
+#ifdef REGET
+ if (do_download(conn, g.gl_pathv[i], abs_dst, pflag, rflag) == -1)
+#else
if (do_download(conn, g.gl_pathv[i], abs_dst, pflag) == -1)
+#endif
err = -1;
xfree(abs_dst);
abs_dst = NULL;
@@ -497,7 +520,11 @@
}
static int
+#ifdef REGET
+process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd, int pflag, int rflag)
+#else
process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd, int pflag)
+#endif
{
char *tmp_dst = NULL;
char *abs_dst = NULL;
@@ -557,7 +584,11 @@
abs_dst = make_absolute(tmp, pwd);
printf("Uploading %s to %s\n", g.gl_pathv[i], abs_dst);
+#ifdef REGET
+ if (do_upload(conn, g.gl_pathv[i], abs_dst, pflag, rflag) == -1)
+#else
if (do_upload(conn, g.gl_pathv[i], abs_dst, pflag) == -1)
+#endif
err = -1;
}
@@ -789,6 +820,10 @@
switch (cmdnum) {
case I_GET:
case I_PUT:
+#ifdef REGET
+ case I_REGET:
+ case I_REPUT:
+#endif
if (parse_getput_flags(&cp, pflag))
return(-1);
/* Get first pathname (mandatory) */
@@ -921,10 +956,24 @@
err = -1;
break;
case I_GET:
+#ifdef REGET
+ err = process_get(conn, path1, path2, *pwd, pflag, 0);
+#else
err = process_get(conn, path1, path2, *pwd, pflag);
+#endif
break;
case I_PUT:
+#ifdef REGET
+ err = process_put(conn, path1, path2, *pwd, pflag, 0);
+ break;
+ case I_REGET:
+ err = process_get(conn, path1, path2, *pwd, pflag, 1);
+ break;
+ case I_REPUT:
+ err = process_put(conn, path1, path2, *pwd, pflag, 1);
+#else
err = process_put(conn, path1, path2, *pwd, pflag);
+#endif
break;
case I_RENAME:
path1 = make_absolute(path1, *pwd);
More information about the openssh-unix-dev
mailing list