File Offsets for SCP (patch)
rapier
rapier at psc.edu
Tue Nov 23 07:03:05 EST 2010
Good question. I just tested this out. If you set either A or Z to the
file size then it creates a zero byte file on the remote end. Which is
exactly what you'd expect. If you set either A or Z greater than the
file size then you get an error 'Offset greater than file size'. If the
combination of A and Z are greater than the file size you get a protocol
error 'scp: protocol error: size not delimited'. So I need to add some
math in there.
Bert Wesarg wrote:
> On Fri, Nov 19, 2010 at 21:27, rapier <rapier at psc.edu> wrote:
>> I don't know if anyone would be interested in this but I'm including a patch
>> to allow for offsets when transferring files with SCP.
>>
>> It's pretty simple and assumes the user knows what they are doing (for
>> example, if transferring with a wild card the offset would apply to all
>> files). -A is the number of bytes offset from the beginning of the files. -Z
>> is the number of bytes inset from the end of the file.
>>
>> We may be using this when transferring very large files (100GB+) over
>> multiple parallel TCP streams by instantiating multiple SSH connections by
>> means of a management application.
>>
>> Any comments, questions, or suggestions are welcome.
>>
>>
>> --- ../canonical-openssh5.6/scp.c 2010-07-01 23:37:33.000000000 -0400
>> +++ scp.c 2010-11-19 17:17:26.000000000 -0500
>> @@ -302,6 +302,7 @@ struct passwd *pwd;
>> uid_t userid;
>> int errs, remin, remout;
>> int pflag, iamremote, iamrecursive, targetshouldbedirectory;
>> +double fd_offset, fd_inset;
>>
>> #define CMDNEEDS 64
>> char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */
>> @@ -324,6 +325,9 @@ main(int argc, char **argv)
>> extern char *optarg;
>> extern int optind;
>>
>> + fd_inset = 0;
>> + fd_offset = 0;
>> +
>> /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
>> sanitise_stdfd();
>>
>> @@ -344,7 +348,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:Z:"))
>> != -1)
>> switch (ch) {
>> /* User-visible flags. */
>> case '1':
>> @@ -407,6 +411,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 'Z':
>> + fd_inset = strtod(optarg, &endp);
>> + if (fd_inset < 0 || *endp != '\0')
>> + usage();
>> + break;
>> default:
>> usage();
>> }
>> @@ -680,6 +694,16 @@ syserr: run_err("%s: %s", name,
>> strerr
>> run_err("%s: %s", name, "Negative file size");
>> goto next;
>> }
>> + if (fd_offset > stb.st_size) {
>> + run_err("Offset greater than file size");
>> + goto next;
>> + }
>> + if (fd_inset > stb.st_size) {
>> + run_err("Inset greater than file size");
>> + goto next;
>> + }
>> + lseek (fd, fd_offset, SEEK_SET);
>> + stb.st_size -= (fd_offset + fd_inset);
>
> What happen if you set fd_offset == fd_inset == stb.st_size?
>
> Bert
>
>> unset_nonblock(fd);
>> switch (stb.st_mode & S_IFMT) {
>> case S_IFREG:
>> _______________________________________________
>> openssh-unix-dev mailing list
>> openssh-unix-dev at mindrot.org
>> https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev
>>
> _______________________________________________
> openssh-unix-dev mailing list
> openssh-unix-dev at mindrot.org
> https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev
More information about the openssh-unix-dev
mailing list