[Haskell-cafe] File path programme

Ben Rudiak-Gould Benjamin.Rudiak-Gould at cl.cam.ac.uk
Thu Jan 27 10:40:44 EST 2005


Robert Dockins wrote:

 >This is true in a sense, but I think making the distinction explicit is
 >helpful for a number of the operations we want to do.  For example, what
 >is the parent of the relative path "."?  Answer is "..".  What is the
 >parent of "/." on unix?  Answer is "/.".

While true, I don't see what this has to do with the choice between 
PathStart and Maybe PathRoot. The types are isomorphic; we can detect 
and simplify the /.. case either way.

 >Relative paths can refer to different things in the filesystem depending
 >on process-local state, whereas absolute paths will always refer to the
 >same thing (until the filesystem changes, or if you do something
 >esoteric like "chroot").  Relative paths are really "path fragments."

Okay, this is a good point. There is a difference between a path 
fragment (i.e. a path with no starting point specified) and a path which 
explicitly starts in the process's default directory. You're right that 
the pathname "foo/bar" can only sensibly be put in the former category.

The problem is that where Posix has just

       Absolute
          |
       Relative

Win32 has

       Absolute
       /     \
      /       \
  Rel:Abs   Abs:Rel
      \       /
       \     /
       Relative

where "Rel:Abs" means something like "\foo" and "Abs:Rel" means 
something like "c:foo". I never realized before what a nightmare it is 
to handle this sensibly. The problem is that pathAppend "c:\foo\bar" 
"d:." == "d:.", but pathAppend "d:\foo\bar" "d:." == "d:\foo\bar\.". 
Therefore, pathAppend "\foo\bar" "d:." doesn't have a value at all, 
since its meaning depends on the current drive in a way that can't be 
expressed in the Win32 path syntax.

Because of the above problem, I'm willing to treat path fragments 
(Relative in both lattices) as a special case. But we still need to be 
able to round-trip rel:abs and abs:rel pathnames, meaning that the 
PathRoot type won't necessarily be a genuine cwd-independent root any more.

 >There are a few others.  I took a look at MSDN earlier and was
 >astounded.

Is there an MSDN page that actually gives a grammar, or at least a 
taxonomy, of Win32 pathnames? That would be useful.

Incidentally, NT doesn't do a perfect job of parsing its own pathnames. 
While experimenting I managed to create a file named "..", different 
from the directory ".." (both show up in the directory listing), which I 
was subsequently unable to read or delete. The command was something 
like "cat > ..:foo". I doubt that this behavior is by design.

 >> > pathCleanup :: p -> p           -- remove .. and suchlike
 >>
 >>This can't be done safely except in a few special cases (e.g. "/.." ->
 >>"/"). I'm not sure it should be here.
 >
 >More than you would think, if you follow the conventions of modern unix
 >shells.

It's not a general convention even in the shell, just a peculiarity of 
the cd builtin:

  GNU bash, version 2.05b.0(1)-release (i386-pc-linux-gnu)
  # mkdir /bar
  # mkdir /bar/baz
  # ln -s /bar/baz /foo
  # echo /file > /file
  # echo /bar/file > /bar/file
  # cat /foo/../file
  /bar/file
  # ls /foo/..
  baz  file
  # cd /foo
  # cat ../file
  /bar/file

In the vast majority of cases it's not safe to collapse "/foo/.." to "/".

On reflection I think the function should be provided, but with a name 
like pathCancel and a usage warning in the documentation. If it's not 
provided people will write it themselves without realizing that it's unsafe.

-- Ben



More information about the Haskell-Cafe mailing list