[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#36416: realpath doesn't preserve '..' consistently as per POSIX, nor
From: |
L A Walsh |
Subject: |
bug#36416: realpath doesn't preserve '..' consistently as per POSIX, nor '/.' |
Date: |
Sat, 29 Jun 2019 12:21:23 -0700 |
User-agent: |
Thunderbird |
On 2019/06/28 12:02, Eric Blake wrote:
> If your application layer is on top of Linux, then yes, the underlying
> OS guarantees that your application processing a path beginning with
> "//" is correct whether it preserves or shortens that path to "/".
----
Linux doesn't forever guarantee that it will or won't
use '//'.
> If you port the source code of an application originally built on Linux
> to then operate on some other operating system, then the source code is
> buggy if it shortens the path to "/". But you have to actually check the
> source code to see if it has that bug - just because 'realpath' in
> coreutils shortens '//' to '/' on Linux does NOT mean that it is buggy,
> because the code for realpath has an explicit check (run at
> configure-time) for whether "//" is distinct from "/" - and on platforms
> where that check is answered differently than on Linux, the code behaves
> differently. That is, the coreutils code is self-adapting to the
> implementation definition of the implementation it is compiled on.
---
As long as realpath guarantees that the generated binary
won't work on any other version of linux, that would be true. However
the run-time binary isn't recompiled with each version of linux.
>
>
>> It would useful if bugs were not closed before asking for more
>> information.
>
> They can always be reopened if you provide enough relevant information
> to show it was closed prematurely. But so far in this case, you have
> not done so, but merely confirmed my suspicions - you noticed a
> difference in behavior between Linux and Cygwin, but both behaviors were
> POSIX-compliant when factoring in the implementation-defined nature of
> the underlying implementation.
----
And you confirm that there there is a design flaw in realpath.
Realpath is not part of the OS and is not regenerated as part
of the kernel build process. If a patch is applied to specifically
to enable or assign meaning to '//' separately that to '/', 'realpath'
will continue to run as it was configured to run on the earlier version.
Realpath can't assume either that it was configured properly
for the current linux binary -- neither that the user knows which is
correct, nor that some behavior that was true at compile time is
still true at run time.
Realpath also trims '.' off of "[dir]/." when these do not have
identical meaning within the linux or cygwin ecospheres. If I process
source and destination paths through realpath before passing them
to another user app, like 'cp', realpath will alter the behavior.
If you look at the historic behavior of cp w/relation to
to *nix, it behaves differently if the source comes from '<dir>' than
if it comes from '<dir>/.'.
Similarly if you look at the historic behavior of *nix, you
can't claim '//' and '/' are identical. Realpath fixes it's
path-modifying behaviors at compile time but doesn't disallow its
binary being run on differently compiled copies of linux.
FWIW, for device paths in /etc/fstab, the notation for CIFS remote
mounts is '//', as in:
mount -t cifs //Win_Desktop/C/ /Athenae -o rw,cifsacl,nocase,serverino,vers=2.1
It seems useful for '//' to made available on linux as an automounter path,
though with nothing mounted, refering to the local system.
I could see concatenating paths '//' & '/usr' being reduced to '/usr',
but concatenating '//' & svrname reducing to '//svrname'.
Other realpath problem:
----- -------- -------
But for a real case now where processing path-args with realpath resulting
in different and unwanted behavior:
using a function for shorthand:
rp() { declare p=(); for e in "$@"; do p+=($(realpath -m "$e")); done ; set
"${p[@]}"; printf "%s\n" "$@"; }; export rp
# && sample files && cd to /tmp:
mkdir /tmp/{a,b}; touch /tmp/a{1,2}; cd /tmp;
cp -a $(rp a/.) $(rp b/.)
#versus
cp -a a/. b/.
produce very different results. I would assert that reducing
'dir/.' to simply 'dir/'
is also incorrect.