strange interaction between open and cwd

Baz Walter bazwal at ftml.net
Tue May 4 09:36:06 EDT 2010


On 04/05/10 09:23, Gregory Ewing wrote:
> Grant Edwards wrote:
>
>> In your example, it's simply not possible to determine the file's
>> absolute path within the filesystem given the relative path you
>> provided.
>
> Actually, I think it *is* theoretically possible to find an
> absolute path for the file in this case.
>
> I suspect that what realpath() is doing for a relative path is
> something like:
>
> 1. Use getcwd() to find an absolute path for the current
> directory.
> 2. Chop off a trailing pathname component for each ".."
> on the front of the original path.
> 3. Tack the filename on the end of what's left.
>
> Step 1 fails because the current directory no longer has
> an absolute pathname -- specifically, it has no name in
> what used to be its parent directory.
>
> What realpath() is failing to realise is that it doesn't
> actually need to know the full path of the current directory,
> only of its parent directory, which is still reachable via
> ".." (if it weren't, the file wouldn't be reachable either,
> and we wouldn't be having this discussion).
>
> A smarter version of realpath() wouldn't try to find the
> path of the *current* directory, but would follow the
> ".." links until it got to a directory that it did need to
> know an absolute path for, and start with that.
>
> Unfortunately, there is no C stdlib routine that does the
> equivalent of getcwd() for an arbitrary directory, so
> this would require realpath() to duplicate much of
> getcwd()'s functionality, which is probably why it's
> done the way it is.

actually, this part of the problem can be achieved using pure python. 
given the basename of a file, all you have to do is use os.stat and 
os.listdir to recursively climb up the tree and build a dirpath for it. 
start by doing os.stat(basename) to make sure you have a legal file in 
the current directory; then use os.stat('..') to get the parent 
directory inode, and stat each of the items in os.listdir('../..') to 
find a name matching that inode etc. (note that the possibility of 
hard-linked directories doesn't really spoil this - for relative paths, 
we don't care exactly which absolute path is found).

this will work so long as the file is in a part of the filesystem that 
can be traversed from the current directory to the root. what i'm not 
sure about is whether it's possible to cross filesystem boundaries using 
this kind of technique.




More information about the Python-list mailing list