scp host:file* /tmp/nonexistent

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

scp host:file* /tmp/nonexistent

Jan Stary
This is current/amd64.

When copying multiple files from a remote host using scp(1)
into a local directory that does not exist, or to local file,
the result is that the last copied file wins.

For example, with file1 and file2 at host,
and /tmp/nonexistent not existing at the destination,

        scp host:file* /tmp/nonexistent

will result in /tmp/nonexistent being a copy of file2
and file1 being nowhere.

In case /tmp/nonexistent exists and is a file,
the same happens.

In case /tmp/nonexistent exists and is a dir,
both file1 and file2 get copied there, as with cp(1).

Is this behaviour intended?

Reading the output of 'scp -v' I see

        Sending command: scp -v -f file*

Reading the scp(1) manpage and the getopt() in scp.c,
i see the undocummented -d -f options; with -d,
scp exists immediately with

         /tmp/nonexistent: No such file or directory
         /tmp/nonexistent: Not a directory

respectively; but it seems strange that the user has to
explicitly say "I am copying multiple files into a directory",
as opposed cp(1) doing that automatically.

Jan

Reply | Threaded
Open this post in threaded view
|

Re: scp host:file* /tmp/nonexistent

Theo de Raadt-2
Unfortunately, that is how it works.

I think you are making an assumption that 'scp' means 'cp over ssh'.
You think it should therefore work maximum like cp.  But it doesn't.
It has hundreds of ways it doesn't work like cp.  It is totally
different code.  It is just a 20 year mangle of the old CSRG rcp code.

You need to think of "scp" meaning "secure file copy" not
"ssh version of cp(1)".

You want us to change that behaviour?  I hope you understand that
changing the behaviour will break scripts, and the things people
type.  You might immediately think the consequences are irrelevant,
but 20 years of patterning tends to be heavy.

So the behaviour cannot be changed!  If you read the code, you'll see
how it iterates it's copying method over each of the source arguments,
to the target.  "scp host1:a host2:b c/".  This is how it worked *since
day one* as rcp, and as a result in scp.

So if you are just expressing surprise, I don't understand where it
comes from.  scp is not cp.  It's just 3 letters hinting that it is
somewhat like cp, but you are the only one making the assumption about
which specific cp behaviours you expect here.

People should really use rsync (which has it's own oddities), and really
openrsync should get some love and become a 100% compatible and viable
replacement that works the same.  Not that this can plausibly result in
the deletion of scp, tho.

Jan Stary <[hidden email]> wrote:

> This is current/amd64.
>
> When copying multiple files from a remote host using scp(1)
> into a local directory that does not exist, or to local file,
> the result is that the last copied file wins.
>
> For example, with file1 and file2 at host,
> and /tmp/nonexistent not existing at the destination,
>
> scp host:file* /tmp/nonexistent
>
> will result in /tmp/nonexistent being a copy of file2
> and file1 being nowhere.
>
> In case /tmp/nonexistent exists and is a file,
> the same happens.
>
> In case /tmp/nonexistent exists and is a dir,
> both file1 and file2 get copied there, as with cp(1).
>
> Is this behaviour intended?
>
> Reading the output of 'scp -v' I see
>
> Sending command: scp -v -f file*
>
> Reading the scp(1) manpage and the getopt() in scp.c,
> i see the undocummented -d -f options; with -d,
> scp exists immediately with
>
> /tmp/nonexistent: No such file or directory
> /tmp/nonexistent: Not a directory
>
> respectively; but it seems strange that the user has to
> explicitly say "I am copying multiple files into a directory",
> as opposed cp(1) doing that automatically.
>
> Jan
>

Reply | Threaded
Open this post in threaded view
|

Re: scp host:file* /tmp/nonexistent

Jan Stary
On Aug 01 09:34:52, [hidden email] wrote:
> Unfortunately, that is how it works.
>
> I think you are making an assumption that 'scp' means 'cp over ssh'.
> You think it should therefore work maximum like cp.  But it doesn't.
> It has hundreds of ways it doesn't work like cp.  It is totally
> different code.  It is just a 20 year mangle of the old CSRG rcp code.
>
> You need to think of "scp" meaning "secure file copy" not
> "ssh version of cp(1)".

Indeed, that was my expectation, naively.
Thanks for the insight.

        Jan

Reply | Threaded
Open this post in threaded view
|

Re: scp host:file* /tmp/nonexistent

Roderick
In reply to this post by Theo de Raadt-2

On Sat, 1 Aug 2020, Theo de Raadt wrote:

> People should really use rsync (which has it's own oddities), ...

For example the ugly behaviour when the source file ends with / ?

Also FreeBSD's cp behave like rsync and is documented in its man page:

-R  If source_file designates a directory, cp copies the directory and
     the entire subtree connected at that point. If the source_file
     ends in a /, ...

It is not documented in 4.4BSD. I suppose this is not original BSD?

Rod.

Reply | Threaded
Open this post in threaded view
|

Re: scp host:file* /tmp/nonexistent

Christian Weisgerber
On 2020-08-01, Roderick <[hidden email]> wrote:

> It is not documented in 4.4BSD. I suppose this is not original BSD?

Public service announcement: The original BSD repository can be
browsed here (converted from SCCS):
https://svnweb.freebsd.org/csrg/

Wanna know what those hippies at Berkeley really did?
You can look it up.

--
Christian "naddy" Weisgerber                          [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: scp host:file* /tmp/nonexistent

Stuart Henderson
In reply to this post by Roderick
On 2020-08-01, Roderick <[hidden email]> wrote:
>
> On Sat, 1 Aug 2020, Theo de Raadt wrote:
>
>> People should really use rsync (which has it's own oddities), ...
>
> For example the ugly behaviour when the source file ends with / ?

That's not ugly, it's flexible! And it teaches you to type what you mean.


Reply | Threaded
Open this post in threaded view
|

Re: scp host:file* /tmp/nonexistent

Theo de Raadt-2
In reply to this post by Christian Weisgerber
Christian Weisgerber <[hidden email]> wrote:

> On 2020-08-01, Roderick <[hidden email]> wrote:
>
> > It is not documented in 4.4BSD. I suppose this is not original BSD?
>
> Public service announcement: The original BSD repository can be
> browsed here (converted from SCCS):
> https://svnweb.freebsd.org/csrg/
>
> Wanna know what those hippies at Berkeley really did?
> You can look it up.

I'm not sure you're talking to READERS...

Reply | Threaded
Open this post in threaded view
|

Re: scp host:file* /tmp/nonexistent

Roderick

On Sat, 1 Aug 2020, Theo de Raadt wrote:

> Christian Weisgerber <[hidden email]> wrote:
>
>> On 2020-08-01, Roderick <[hidden email]> wrote:
>>
>>> It is not documented in 4.4BSD. I suppose this is not original BSD?
>>
>> Public service announcement: The original BSD repository can be
>> browsed here (converted from SCCS):
>> https://svnweb.freebsd.org/csrg/
>>
>> Wanna know what those hippies at Berkeley really did?
>> You can look it up.
>
> I'm not sure you're talking to READERS...

I suppose not, because everyone that is not a kernel developer, left
long ago ashamed the list.

Reply | Threaded
Open this post in threaded view
|

Re: scp host:file* /tmp/nonexistent

Roderick
In reply to this post by Christian Weisgerber

On Sat, 1 Aug 2020, Christian Weisgerber wrote:

> Public service announcement: The original BSD repository can be
> browsed here (converted from SCCS):
> https://svnweb.freebsd.org/csrg/
>
> Wanna know what those hippies at Berkeley really did?
> You can look it up.

Thanks for the nice repo with the commentaries!

Here is the code for cp:

https://svnweb.freebsd.org/csrg/bin/cp/cp.c?revision=69112&view=markup
https://svnweb.freebsd.org/csrg/bin/cp/utils.c?revision=66606&view=markup

A challenge: where does the code distinguish src from src/ ?

Indeed it behaves like rsync, but we read in the source something
that seems to contradict it:

/*
   * Cp has two distinct cases:
   *
   * cp [-R] source target
   * cp [-R] source1 ... sourceN directory
   *
   * In both cases, source can be either a file or a directory.
   *
   * In (1), the target becomes a copy of the source. That is, if the
   * source is a file, the target will be a file, and likewise for
   * directories.
   *
   * In (2), the real target is not directory, but "directory/source".
   */

Was it a bug?

BTW, I do not remember this behaviour in SunOS, but also not in
FreeBSD when I used it many years ago, although it was there.

Rodrigo