testfile
utilise les appels systèmes access
et
stat
/"lstat". Ceux-ci peuvent lever les exceptions EACCES
, EROFS
,
ENOENT
, ENOTDIR
, ELOOP
qui contribuent à la réponse et ne doivent donc
pas être rapportées par la fonction testfile
.
Les exceptions EINVAL
et EFAULT
ne devraient pas être levées en OCaml,
Les execptions ENAMETOOLONG
, ENOMEM
et EIO
indiquent une erreur
pendant le calcul lui-même et doivent être rapportées par la fonction
testfile
.
type filetest = | Fexists (* file exists *) | Freadable (* file exists and is readable *) | Fwritable (* file exists and is writable *) | Fexecutable (* file exists and is executable *) | Fdir (* file exists and is a directory *) | Freg (* file exists and is a regular file *) | Flnk (* file exists and is a symbolic link *) | Fnonempty (* file exists and is non empty *) | Fnewer of string (* files exists and is newer than *) | Folder of string (* files exists and is older than *) | Fequal of string (* files is identical (sams st_ino and st_dev) than *) let access_map = [ Freadable, R_OK; Fwritable, W_OK; Fexecutable, X_OK; Fexists, F_OK; ] let access_ok_errors = [ EACCES ; EROFS; ENOENT; ENOTDIR; ELOOP ] ;; let testfile flags filename = let rec split ( (found, left) as both) = function [] -> both | h :: t -> let found_left = try List.assoc h access_map :: found, left with Not_found -> found, h::left in split found_left t in let access_flags, flags = split ([],[]) flags in let access_flags = if access_flags = [] then [ F_OK ] else access_flags in try access filename access_flags; flags = [] || begin let st = (if List.mem Flnk flags then stat else lstat) filename in let rec test = function | Fdir -> st.st_kind = S_DIR | Freg -> st.st_kind = S_REG | Flnk -> st.st_kind = S_LNK | Fnonempty -> st.st_size > 0 | Fnewer string -> st.st_mtime > (stat string).st_mtime | Folder string -> st.st_mtime < (stat string).st_mtime | Fequal string -> let st' = stat string in st.st_ino = st'.st_ino && st.st_dev = st'.st_dev | _ -> assert false in List.for_all test flags end; with Unix.Unix_error (err, _, _) when List.mem err access_ok_errors -> false ;; |