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 ;; |