File Offsets for SCP (patch revised)

rapier rapier at psc.edu
Tue Nov 23 09:46:50 EST 2010


Just a follow up patch. You now just specify the byte length you want to 
transfer and a little more error checking. Again, don't know if this 
would be useful to anyone but I thought I'd share just in case. Also, 
just to make sure this is clear, this only works on the source side.

--- ../canonical-openssh5.6/scp.c	2010-07-01 23:37:33.000000000 -0400
+++ ./scp.c	2010-11-22 19:48:46.000000000 -0500
@@ -302,6 +302,8 @@ struct passwd *pwd;
  uid_t userid;
  int errs, remin, remout;
  int pflag, iamremote, iamrecursive, targetshouldbedirectory;
+// user requested file offset and amount of data to xfer
+double fd_offset, fd_length;

  #define	CMDNEEDS	64
  char cmd[CMDNEEDS];		/* must hold "rcp -r -p -d\0" */
@@ -324,6 +326,9 @@ main(int argc, char **argv)
  	extern char *optarg;
  	extern int optind;

+	fd_length = 0;
+	fd_offset = 0;
+
  	/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
  	sanitise_stdfd();

@@ -344,7 +349,7 @@ main(int argc, char **argv)
  	addargs(&args, "-oClearAllForwardings yes");

  	fflag = tflag = 0;
-	while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q1246S:o:F:")) != -1)
+	while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q1246S:o:F:A:L:")) != -1)
  		switch (ch) {
  		/* User-visible flags. */
  		case '1':
@@ -407,6 +412,16 @@ main(int argc, char **argv)
  			setmode(0, O_BINARY);
  #endif
  			break;
+		case 'A':
+			fd_offset = strtod(optarg, &endp);
+			if (fd_offset < 0 || *endp != '\0')
+                                usage();
+			break;
+		case 'L':
+			fd_length = strtod(optarg, &endp);
+			if (fd_length < 0 || *endp != '\0')
+                                usage();
+			break;
  		default:
  			usage();
  		}
@@ -680,6 +695,34 @@ syserr:			run_err("%s: %s", name, strerr
  			run_err("%s: %s", name, "Negative file size");
  			goto next;
  		}
+
+		// if the offset is greater than the file size
+		// we can't do this
+		if (fd_offset > stb.st_size) {
+			run_err("Offset greater than file size");
+			goto next;
+		}
+		
+		// if the offset plus the requested length are greater
+		// than the file size then we have to quit
+		if (fd_length + fd_offset > stb.st_size) {
+			run_err("Length greater than file size");
+			goto next;
+		}
+
+		// if the user only has an offset then we reduce
+		// the file size by the offset. if they have a length
+		// then we use stb.st_size and the length
+		// to determine the actual stopping point
+		if (fd_length != 0) {
+			stb.st_size -= (stb.st_size - fd_length);
+		} else {
+			stb.st_size -= fd_offset;
+		}
+		
+		// seek to the position as requested by user
+		lseek (fd, fd_offset, SEEK_SET);
+
  		unset_nonblock(fd);
  		switch (stb.st_mode & S_IFMT) {
  		case S_IFREG:





More information about the openssh-unix-dev mailing list