caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* absolute_name ?
@ 2007-07-20 16:55 Christophe Raffalli
  2007-07-20 21:23 ` Sylvain Le Gall
       [not found] ` <46B1BCD1.9030004@trusted-labs.fr>
  0 siblings, 2 replies; 4+ messages in thread
From: Christophe Raffalli @ 2007-07-20 16:55 UTC (permalink / raw)
  To: caml-list


Is this the best (and only) way to get the absolute name to a file in a way that would work on all 
system (windonws, OS X, unix, ...) ?


let absolute_name str =
   let base = Filename.basename str in
   let dir = Filename.dirname str in
   let saved_dir = Sys.getcwd () in
   Sys.chdir dir;
   let res = Filename.concat (Sys.getcwd ()) base in
   Sys.chdir saved_dir;
   res

I find this a bit complicated, so I may be missing some functions in Sys, Filename or some other lib ...

-- 
Christophe Raffalli
Université de Savoie
Batiment Le Chablais, bureau 21
73376 Le Bourget-du-Lac Cedex

tél: (33) 4 79 75 81 03
fax: (33) 4 79 75 87 42
mail: Christophe.Raffalli@univ-savoie.fr
www: http://www.lama.univ-savoie.fr/~RAFFALLI
---------------------------------------------
IMPORTANT: this mail is signed using PGP/MIME
At least Enigmail/Mozilla, mutt or evolution
can check this signature. The public key is
stored on www.keyserver.net
---------------------------------------------


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: absolute_name ?
  2007-07-20 16:55 absolute_name ? Christophe Raffalli
@ 2007-07-20 21:23 ` Sylvain Le Gall
       [not found] ` <46B1BCD1.9030004@trusted-labs.fr>
  1 sibling, 0 replies; 4+ messages in thread
From: Sylvain Le Gall @ 2007-07-20 21:23 UTC (permalink / raw)
  To: caml-list

On 20-07-2007, Christophe Raffalli <christophe.raffalli@univ-savoie.fr> wrote:
>
> Is this the best (and only) way to get the absolute name to a file in a way that would work on all 
> system (windonws, OS X, unix, ...) ?
>
>
> let absolute_name str =
>    let base = Filename.basename str in
>    let dir = Filename.dirname str in
>    let saved_dir = Sys.getcwd () in
>    Sys.chdir dir;
>    let res = Filename.concat (Sys.getcwd ()) base in
>    Sys.chdir saved_dir;
>    res
>
> I find this a bit complicated, so I may be missing some functions in Sys, Filename or some other lib ...
>

Maybe, you can have a look at ocaml-fileutils.

http://le-gall.net/sylvain+violaine/ocaml-fileutils.html

You can use either "readlink" if you want to solve the link and the
current working dir (the file need to exist)

(you have also FileUtil.Default.make_absolute which can apply to a non
existing file)

Here is an example:

$> ocaml

# #use "topfind";;
# #require "fileutils";;
# open FilePath.DefaultPath;;
# open FileUtil.StrUtil;;
# ls ".";;
- : FileUtil.filename list =
["./ocaml_3.10.0-5.dsc"; "./ocaml_3.10.0-5.dsc.asc";
 "./ocaml-base-nox_3.10.0-5_i386.deb"; "./ocaml_3.10.0-5_i386.deb";
 "./ocaml-source_3.10.0-5_all.deb"; "./camlp4_3.10.0-5_i386.deb";
 "./camlp4-extra_3.10.0-5_i386.deb"; "./ocaml_3.10.0-5.dsc.gpg";
 "./ocaml_3.10.0.orig.tar.gz"; "./ocaml-base_3.10.0-5_i386.deb";
 "./ocaml_3.10.0-5.diff.gz"; "./ocaml-interp_3.10.0-5_i386.deb";
 "./ocaml-mode_3.10.0-5_all.deb";
"./ocaml-compiler-libs_3.10.0-5_i386.deb";
 "./ocaml-nox_3.10.0-5_i386.deb";
 "./ocaml-native-compilers_3.10.0-5_i386.deb"]
# readlink "./ocaml_3.10.0-5.dsc";;
- : FileUtil.filename =
"/home/gildor/public_html/debstage/builder/queue/ocaml/ocaml_3.10.0-5.dsc"
# make_absolute (pwd ()) "./toto";;
- : FilePath.DefaultPath.filename =
"/home/gildor/public_html/debstage/builder/queue/ocaml/toto"

DefaultPath stands for the path for the current OS. You can use
UnixPath, MacOSPath, Win32Path or CygwinPath if you want to bypass OS
detection.

The documentation is a bit complicated, i need to rewrite it at some
point in the future.

Regards,
Sylvain Le Gall


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Caml-list] absolute_name ?
       [not found] ` <46B1BCD1.9030004@trusted-labs.fr>
@ 2007-08-02 14:36   ` Christophe Raffalli
  2007-08-02 16:21     ` skaller
  0 siblings, 1 reply; 4+ messages in thread
From: Christophe Raffalli @ 2007-08-02 14:36 UTC (permalink / raw)
  To: Correnson Loïc, caml-list


[-- Attachment #1.1: Type: text/plain, Size: 1985 bytes --]

Correnson Loïc a écrit :
> On Win32, you may have to handle short vs long names.
> For instance, 'C:\PROGRA~2' may be the same path to 'C:\Program Files',
> or may be not. When using absolute paths for equality, you can go into
> troubles.
> L.
> 

I just want a name that can be saved and is independent from the current directory.
Testing absolute filename for equality is always a bad idea, here are a few reasons:
- symbolic link
- physical link
- case insensitive system (like OS X)
- short names on windows (the one you mentionned)

However, you can store an absolute name, together with a MD5 to check if a file has changed
since the last access. I think this is pretty safe.

You can use the following code (which is simpler than the one I submitted previously)

let absolute_name str =
  if Filename.is_relative str then
    Filename.concat (Sys.getcwd ()) str
  else
    str

But it can produce filename not in "normal form" (like "/home/user/./folder/toto.ml").
Moreover, I wanted to check that the folder exists but I did not want to check is the file
itself exists. So my original code is not so bad:

let absolute_name str =
  let base = Filename.basename str in
  let dir = Filename.dirname str in
  let saved_dir = Sys.getcwd () in
  try Sys.chdir dir;
    let res = Filename.concat (Sys.getcwd ()) base in
    Sys.chdir saved_dir;
    res
  with
  | Sys_error _ -> str

In fact this function is not too far from converting any filename
to a unique absolute filename independent from the original filename.
It deals with symbolic link for folder correctly because Sys.getcwd () gives
a "real" path. It does not solve the problem of physical link (I am not sure
one want to solve that one) nor the problem of case insensitive filesystem, nor symbolic link
for the basename itself.

Anyway, the second function above seems to suits my needs
(although I have not tested it under windows yet).

Cheers,
Christophe




[-- Attachment #1.2: Christophe.Raffalli.vcf --]
[-- Type: text/x-vcard, Size: 380 bytes --]

begin:vcard
fn:Christophe Raffalli
n:Raffalli;Christophe
org:LAMA (UMR 5127)
email;internet:Christophe.Raffalli@univ-savoie.fr
title;quoted-printable:Ma=C3=AEtre de conf=C3=A9rences
tel;work:+33 4 79 75 81 03
note;quoted-printable:Message sign=C3=A9 cryptographiquement avec pgp, la clef publique est sur=
	 subkeys.pgp.net
x-mozilla-html:TRUE
version:2.1
end:vcard


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 252 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Caml-list] absolute_name ?
  2007-08-02 14:36   ` [Caml-list] " Christophe Raffalli
@ 2007-08-02 16:21     ` skaller
  0 siblings, 0 replies; 4+ messages in thread
From: skaller @ 2007-08-02 16:21 UTC (permalink / raw)
  To: Christophe Raffalli; +Cc: Correnson Loïc, caml-list

On Thu, 2007-08-02 at 16:36 +0200, Christophe Raffalli wrote:
> So my original code is not so bad:

yes it is:

> let absolute_name str =
>   let base = Filename.basename str in
>   let dir = Filename.dirname str in
>   let saved_dir = Sys.getcwd () in
>   try Sys.chdir dir;
>     let res = Filename.concat (Sys.getcwd ()) base in
>     Sys.chdir saved_dir;
>     res
>   with
>   | Sys_error _ -> str
> 

NEVER change the current directory in a program (unless the program
is specifically designed to do that, eg 'chdir' program .. :)

Doing so creates a side-effect, which will interfere with
multi-threading.

Even worse .. your error recovery routine forgets to reset
the current directory. You would have to be very sure that
the only failure possible is in the first Sys.chdir and it results
in Sys_error without changing the current directory ..

At least, you should write:

let absolute_name str =
  let base = Filename.basename str in
  let dir = Filename.dirname str in  
  let saved_dir = Sys.getcwd () in
  let res = 
    try Sys.chdir dir;
      `Some (Filename.concat (Sys.getcwd ()) base)
    with
    | Sys_error _ -> `Some str
    | x -> `Error x
  in
  begin try Sys.chdir saved_dir with _ -> () end;
  match res with
  | `Error x -> raise x
  | `Some filename -> filename

The guarantees the current directory is at least attempted to be
reset.

The result is still quite suspicious!

For a start Windows does not HAVE a current directory!
In fact it has a current directory for EVERY drive letter,
independently, and it isn't only possible for two letters
to map the same drive: it is stock standard practice to
do that with shared drives (a shared global letter and 
a local one).

Secondly, it doesn't account for LAN manager network mounts on Windows,
or just plain old mounts on Linux.

So what is the answer? There is one:

let absolute_name str = str

Simple. Two files are the same if, and only if, the user
spelled their names the same. You cannot solve the problem:
throw the responsibility back on the user.



-- 
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2007-08-02 16:21 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-07-20 16:55 absolute_name ? Christophe Raffalli
2007-07-20 21:23 ` Sylvain Le Gall
     [not found] ` <46B1BCD1.9030004@trusted-labs.fr>
2007-08-02 14:36   ` [Caml-list] " Christophe Raffalli
2007-08-02 16:21     ` skaller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).