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: Thomas Hood
Subject: Re: "readlink -f foo" fails if the target of foo does not exist
Date: Sat, 10 Jan 2004 09:50:42 +0100

On Sat, 2004-01-10 at 08:14, Paul Eggert wrote:
> Jim Meyering <address@hidden> writes:
> 
> > So here's a better spec:
> >   If canonicalize_file_name (FILE) succeeds, work exactly as now.
> >   else if lstat (FILE) succeeds,
> >     linkname = readlink (FILE)
> >     if linkname starts with `/', print linkname
> >     otherwise, print $(readlink -f $(dirname FILE))/linkname
> >   else, work exactly as now.

The shortcoming with this pseudocode is that if canonicalize_file_name()
fails then it does not canonicalize as much of readlink (FILE) as it
can.  (Perhaps I am misreading it.)

What I would like it to do (not necessarily in -f mode ... perhaps in
a new -r mode) is to print A/B where A is the longest path portion
of FILE that can be canonicalized and B is the remaining portion of
FILE, verbatim.


> Hmm, the above algorithm doesn't canonicalize linkname.  If linkname
> contains "." or ".." components, shouldn't they be canonicalized out?

I don't think so.  See below.


> For example, linkname might be "../bar", and if so the above algorithm
> would print /a/b/c/../bar when it should print /a/b/bar.

No.  If /a/b/c were a symlink with value "d/e" then /a/b/c/../bar would
actually be /a/b/d/e/../bar, i.e., /a/b/d/bar.

If /a/b/c does not exist then there is no way to know where it would
point if it did exist.  It is impossible to give the canonical name
of something that doesn't exist.

However it would still be useful to have a readlink operation mode
that canonicalized as much as possible.

Maybe it is time for me to explain where I want to apply this.
Debian's checkroot.sh initscript wants to delete the mtab backup
file.  This backup file will be stored by the mount program in
the same directory as the mtab file itself.  This directory is
only known to checkroot.sh and to mount as the parent of the
ultimate target of /etc/mtab.  Now, the mount program has no
trouble finding out what this directory is because it creates
the mtab file before asking for its canonical path.  However,
checkroot.sh has to deal with the case where mtab does not
exist but the backup file does exist.  The current "readlink -f"
is useless for this.  However, a "readlink -r" as I described
it would do the trick.  Suppose /etc/mtab is a symlink to 
"mount/mtab".  The proposed "readlink -r /etc/mtab" would print
"/etc/mount/mtab" from which the name of the parent, "/etc/mount"
could be extracted.  Take a more complicated example.  Suppose
we have

    /etc/
    /etc/mtab -> /cfg/mount/mtab
    /cfg/
    /cfg/mount/
    /cfg/mount/mtab -> ../mtab

Mount will create mtab at /cfg/mtab.  If this file does not 
exist then "readlink -f" will fail.  But "readlink -r" would go
through the following conversion steps:

    /etc/mtab
/etc exists and isn't a symlink
mtab is a symlink: evaluate
    /cfg/mount/mtab
/cfg exists and isn't a symlink
/cfg/mount exists and isn't a symlink
mtab is a symlink: evaluate
    /cfg/mtab
cfg exists and isn't a symlink
mtab doesn't exist: print "/cfg/mtab"

Then checkroot.sh would know that mtab's dir is /cfg/.

An even more complicated example.  Suppose we have:

    /etc/
    /etc/mtab -> /cfg/mount/v3/../mtab
    /etc/mount/
    /etc/mount/v3/
    /cfg -> /etc

Mount will create mtab at /etc/mount/mtab.  "readlink -r" would go
through the following conversion steps:

    /etc/mtab
/etc exists and isn't a symlink
mtab is a symlink: evaluate
    /cfg/mount/v3/../mtab
/cfg is a symlink: evaluate
    /etc/mount/v3/../mtab
/etc exists and isn't a symlink
/etc/mount exists and isn't a symlink
/etc/mount/v3 exists and isn't a symlink
/etc/mount/v3/.. : abbreviate
    /etc/mount/mtab
/etc/mount/mtab doesn't exist: print "/etc/mount/mtab"

Then checkroot.sh would know that mtab's dir is /etc/mount.


> Ouch!  My head is spinning.

I find it confusing too.  Another reason, perhaps, not to change the
behavior of "-f" but to add a new option.  I can only hope that it
wouldn't be too hard to add; I haven't looked at the code yet.

-- 
Thomas Hood <address@hidden>





reply via email to

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