bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: "readlink -f foo" fails if the target of foo does not exist


From: Dmitry V. Levin
Subject: Re: "readlink -f foo" fails if the target of foo does not exist
Date: Sun, 28 Mar 2004 01:17:36 +0300

Hi,

On Mon, Mar 22, 2004 at 11:56:12PM +0100, Thomas Hood wrote:
> On Mon, 2004-03-22 at 20:48, Dmitry V. Levin wrote:
> > I'd suggest to leave current "readlink -f" behaviour unchanged.
> > If you need to add new mode for readlink(1), please consider adding
> > new option.
> 
> The difference with the current readlink appears only in a case
> that the existing readlink(1) man page does not describe -- the
> case where the target file does not exist.  We want to extend
> the program at this undocumented margin.
> 
> In Debian, at least, the behavior of the readlink program is not
> established by tradition either.  The readlink program in
> woody behaved like Miquel's new readlink program: it printed the
> canonicalization of a symlink chain without requiring that the
> chain point to an existing file.

Well, history of the "readlink -f" is not so trivial.

AWAIK, this option first appeared in OpenBSD (September, 1997 according
to cvs).  Later it was imported into debianutils-1.13.1 (November, 1999
according to changelog).

However, due to difference between realpath(3) implementations in BSD and
glibc, result of readlink -f differs in certain circumstances.
For example, assuming that /tmp is empty writable directory, we will get

bsd$ ln -s dst /tmp/src
bsd$ readlink -f /tmp/src 
/tmp/dst
bsd$ readlink -f /tmp/src/1      
/tmp/src
bsd$ readlink -f /tmp/src/1/2
/tmp/src/1
bsd$ readlink -f /tmp/src/1/2/3
/tmp/src/1/2

deb$ ln -s dst /tmp/src
deb$ readlink -f /tmp/src      
/tmp/dst
deb$ readlink -f /tmp/src/1
/tmp/dst
deb$ readlink -f /tmp/src/1/2
/tmp/dst
deb$ readlink -f /tmp/src/1/2/3
/tmp/dst

You can see the difference then symlink is not last component of the path.
I think that both implementations does wrong thing in this case.

When prepared readlink utility for coreutils (August, 2002), I've decided
to simplify the canonicalize mode by using canonicalize_file_name() which
succeeds only when given path exists.

> The new program is consistent with the ordinary behavior of the
> readlink program.  When you have a symlink foo and you run:
> 
>     readlink foo
> 
> the program does not fail if the target of foo fails to exist.
> The program simply prints the value of symlink foo.  In the same
> manner the new program gives the canonicalized value of a symlink
> chain without requiring that the target of the chain exist.

I'm agree that this behaviour is more compatible with old implementations
and does not repeat their errors (see my example above).

> The new program conforms to the documentation for the realpath()
> and canonicalize_file_name() functions that exist in various
> places including stdlib.h and the info for readlink.  (That those
> functions don't conform to their documentation is another issue.)
> 
> The new readlink program is more useful than the current readlink.
> The current readlink can't tell you the canonical name that a
> file would have if it were created through a symlink chain whereas
> the new readlink can tell you that.  On the other hand, the
> current readlink is easily emulated using the new readlink.  In sh
> code:
> 
>     [ -f $ARG ] && new-readlink -f $ARG

Rather
    [ -e $ARG ] && new-readlink -f $ARG

Emulation becomes less trivial when readlink -v option is used.
This option was first introduced in coreutils, so it is probably not
widely used yet, though.

> Jim Meyering wrote[1] on the bug-coreutils list in January that he
> would be happy to apply a patch that restored this feature of
> the "old" readlink implementation.  I don't know the history but
> I gather that the old readlink program was buggy and the feature
> in question disappeared when the program was rewritten.  Now
> Miquel has rewritten it again in such a way that the feature is
> restored.  I don't see this as a disruptive change.
> 
> [1]http://mail.gnu.org/archive/html/bug-coreutils/2004-01/msg00053.html

You suggest to change "readlink -f" behaviour to more compatible way, i.e.
"readlink -f /path/to/foo" will also succeed when "/path/to" exists and
"/path/to/foo" points to some target "/another/path/to/bar" where
"/another/path/to" is a directory", right?

This change could be implemented using slightly modified version of the
canonicalize_file_name() function, which is IMHO more clean than Miquel's
implementation.

> Of course, if a consensus is reached here that the current behavior
> of "readlink -f" must not be changed then of course it wouldn't be
> hard to modify the new readlink such that "-f" works as it does
> currently and the print-path-even-if-target-doesn't-exist behavior
> is turned on by some other option.

I suppose that current "readlink -f" behaviour is not widely used yet,
so we probably could change it to more compatible way, and either drop
current canonicalize behaviour, or save it in some other option.
I'd prefer to choose second alternative.


-- 
ldv

Attachment: pgpdMx9STETXy.pgp
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]