AFAIK, the scp protocol isn't documented anywhere else than it the source code of scp.c
, so here is an attempt to an outline of how scp
works.
When either the source or the destination is a remote machine, scp
will use ssh
to connect and start a scp
program on it: if the copy direction is from the remote to the local, it will be started as scp -f src
(from / source), otherwise it will be started as scp -t dst
(to / sink), and the local scp
will assume the opposite posture.
After this the two scp processes are running on both ends of the scp connection, using it as their stdin/stdout and passing the file data and metadata over it.
Both ends could use the following responses to acknowledge messages or signal some error condition:
"\0"
: OK
"\1%s\n", err_msg
: non-fatal error
"\2%s\n", err_msg
: fatal error
The transfer starts by the to / sink scp sending a \0
(OK) ack.
Then the from / source scp will use the following messages:
"C%04o %lld %s\n", mode, size, filename
: create a file
this is followed by size
bytes of file data, and an ack (\0
= OK)
"D%04o 0 %.1024s\n", mode, dirname
: start of directory
recursively followed by C
, D
or T
messages, until a
"E\n"
: end of directory
"T%llu 0 %llu 0\n", mtime, atime
: file times
this is sent before the C
or D
messages, if the -p
switch was used.
These messages will have to be ack'ed by the other side before proceding further, including the C
before sending the file data, and the ack sent after it.
In the C
and D
messages above, newlines and other control chars (except \t
and \x7f
) in the file/dir name will be escaped as eg. \^J
, but will not be unescaped at the destination; a literal \^J
or \^M
in the original name will be left as-is.
The difference between fatal and non-fatal errors is not consistent; only \1
(non-fatal) errors will be generated by either side, but some of them will be considered fatal, and scp
will exit upon sending or receiving them, leaving the other side to hold both pieces. Both sides will exit upon a \2
(fatal) error or anything unexpected.
Unlike in http, there are no provisions for sending the file data by chunks; if the source scp
is no longer able to read some big file it has started sending after the C
message, it will send up to its size
NUL bytes before the \1
error message / nak.
-t
,-f
and-d
options are not documented because they're not user-serviceable; they're only used when starting the "server" scp on the remote machine. – mosvy Sep 7 '19 at 2:51