Subject: Re: realpath doesn't preserve '..' consistently as per POSIX, nor '/.'

From: L A Walsh <[email-masked]>
Date: Sat, 29 Jun 2019 12:21:23 -0700

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.