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