Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Re: Absolute pathnames from relative?

by mojotoad (Monsignor)
on Jan 22, 2003 at 06:39 UTC ( [id://228956]=note: print w/replies, xml ) Need Help??


in reply to Absolute pathnames from relative?

This is a feature, not a bug. Or, rather, a symptom of dealing with ambiguity within differing filesystems on different versions of operating systems.

The short answer is that, without a physical file system check, you can use the no_upwards() method from File::Spec to strip your dots and double dots (or their respective equivalents on other filesystems).

The somewhat longer answer is that the OS (or filesystem implementation) is the ultimate authority on what the filesystem implementation really does. With a physical system check you can use the Cwd module and a cwd() combined with a pwd() to let the operating system figure out the correct interpretation.

The reason this is ambiguous is that soft links can span filesystems or volumes. A path involving a soft link across volumes and relative paths presents ambiguity -- if you switched volumes at some point in resolving the path, does the '..' mean backtrack to the prior volume or should it be one level up on the new volume? This is a question typically answered on the OS level.

Consider two volumes mounted thusly:

/mnt/disk_a /mnt/disk_b

and the following link/directory structure:

/mnt/disk_a/hubba /mnt/disk_a/opt -> /mnt/disk_b/opt /mnt/disk_b/opt /mnt/disk_b/hubba

Now what does /mnt/disk_a/opt/../hubba mean? It could mean either /mnt/disk_a/hubba or /mnt/disk_b/hubba depending on whether you take a tokenized or holistic approach to resolving relative directories. And to complicate matters further, soft links can also have relative paths embedded in them.

The real issue, however, is that the "proper" behavior is encoded at the filesystem implementation level. On most Unix variants, you can mount several different filesytem formats with their own interpretations of relative path resolution. But this does not prevent linking across these disparate filesystems. So though it may be more visually pleasing to eliminate those relative paths, they might be necessary to accurately resolve the behavior along OS and filesystem spec lines.

If you're relatively certain you will be operating on homogenous systems, OS as well as filesystem implementations, then by all means go for it without the physical check.

Incidentally, punting to the OS in order to let it decide what to do is the difference between cwd() and fastcwd() in the Cwd module.

Matt

Update: Also see my response below concerning the same issues regarding mount points across the network: Re^3: Absolute pathnames from relative?

Replies are listed 'Best First'.
Re: Re: Absolute pathnames from relative?
by rob_au (Abbot) on Jan 22, 2003 at 08:13 UTC
    The somewhat longer answer is that the OS (or filesystem implementation) is the ultimate authority on what the filesystem implementation really does. With a physical system check you can use the Cwd module and a cwd() combined with a pwd() to let the operating system figure out the correct interpretation.

    An easier method using the Cwd method, albeit with the same limitation of being a filesystem-based implementation, is through the use of the abs_path method. For example:

    # perl -MCwd=abs_path -le 'print abs_path("/usr/local/src/../bin/fnurg +le")' /usr/local/bin/fnurgle

     

    perl -le 'print+unpack("N",pack("B32","00000000000000000000001000100010"))'

      I'm bringing this thread back from the past but I'm doing something similar right now so I searched and found it.

      I already tried using abs_path. It works fine if the argument is a directory but not when the argument is a file.
Re: Re: Absolute pathnames from relative?
by grantm (Parson) on Jan 22, 2003 at 08:25 UTC

    Thanks Matt, I was guessing it had something to do with symlinks but hadn't put all the pieces together. Interestingly (or not) the colleague who originally asked me the question was working on Win32 which doesn't do symlinks but even on that platform, File::Spec::Win32 still leaves the '..' parts in place.

    The no_upwards() method doesn't quite seem to do what I need either (I had tried it before I posted originally). It takes a list of pathname components and all it does is eliminate the '.' and '..' components (ie: it doesn't remove the component before the '..') - I'm not sure when that would be useful. Even it it did what I wanted, by the time I'd called splitdir() to provide the right inputs and then catdir() to reassemble the output, the end result would hardly be a clear and concise piece of code.

    I guess I'll stick with my URI solution. Thanks again.

      The no_upwards() behavior sounds like a bug, in my mind. It makes no sense to eliminate '..' without considering the consequences.

      I neglected to mention in my initial writeup that soft links are not the only time this arises -- mount points will do it as well. Mounted disks might be local or remote -- they might even be on different operating systems. Same dynamic, though: system_a:/server_disk/home/hubba could be mounted on system_b:/home/hubba. Typically this depends on the NFS implementation (or whatever the remote disk sharing protocol might be).

      rob_au is correct that the abs_path() method of Cwd is the best way to perform this trick using a physical system check. abs_path() itself, last time I checked, is based on File::Spec and the Cwd methods cwd() and pwd() routines. There is an analogous fast_abs_path() that "does the right thing" that you expect, without a physical check. Entirely reliable, however, if you expect to be on a homogenous system.

      Matt

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://228956]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others perusing the Monastery: (5)
As of 2024-04-20 01:01 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found