File: scandir.ml

package info (click to toggle)
camlimages 2.00-3
  • links: PTS
  • area: main
  • in suites: woody
  • size: 3,536 kB
  • ctags: 2,325
  • sloc: ml: 10,848; ansic: 2,396; makefile: 599; sh: 30
file content (55 lines) | stat: -rw-r--r-- 2,036 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
(***********************************************************************)
(*                                                                     *)
(*                           Objective Caml                            *)
(*                                                                     *)
(*            Jun Furuse, projet Cristal, INRIA Rocquencourt           *)
(*                                                                     *)
(*  Copyright 1999,2000,2001,2002,2001,2002                            *)
(*  Institut National de Recherche en Informatique et en Automatique.  *)
(*  Distributed only by permission.                                    *)
(*                                                                     *)
(***********************************************************************)
open Unix

let ignore_dirs = ref [".xvpics"]

let scan_dir f fn = 
  let scanned = ref [] in
  let rec sub fn =
    let st = stat fn in
    match st.st_kind with
    | S_DIR ->
	if List.mem st.st_ino !scanned then ()
	else begin
	  scanned := st.st_ino :: !scanned;
	  let dh = opendir fn in
	  let files = ref [] in
	  begin try while true do 
	    files := (readdir dh) :: !files
	  done with End_of_file -> () 
	  | e -> prerr_endline ("readdir: " ^Printexc.to_string e) end;
	  closedir dh;
	  let files = Sort.list (>) !files in
	  let subdirs = ref [] in
	  List.iter (fun fn' ->
	    if not (fn' = ".." || fn' = ".") then begin
	      let fn'' = Filename.concat (if fn = "." then "" else fn) fn' in
	      try
		let st = Unix.stat fn'' in
	      	match st.st_kind with
	      	| S_DIR -> (* sub-dir check is delayed *)
		    if not (List.mem fn' !ignore_dirs) then
		      subdirs := fn'' :: !subdirs
	      	| _ -> 
		    f fn'' (* or sub fn', but it's more efficient *)
	      with
		Unix.Unix_error(_,"stat",_) ->
		  prerr_endline (fn''^": stat failed")
	      |	e -> prerr_endline (fn''^": "^Printexc.to_string e)
	    end) files;
	  List.iter  sub (List.rev !subdirs);
	end
    | _ -> f fn
  in
    sub fn
;;