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