[Pkg-ocaml-maint-commits] [SCM] approx upstream and debian packaging branch, upstream, updated. upstream/3.5-46-gd97ea77

Eric Cooper ecc at cmu.edu
Wed Jul 14 03:10:38 UTC 2010


The following commit has been merged in the upstream branch:
commit d97ea77f1a506e94e190513c574c5524f3fa71be
Author: Eric Cooper <ecc at cmu.edu>
Date:   Tue Jul 13 21:35:43 2010 -0400

    detect cycles when traversing directory trees
    
    closes: #582294

diff --git a/tests/dir_test.ml b/tests/dir_test.ml
new file mode 100644
index 0000000..29747d5
--- /dev/null
+++ b/tests/dir_test.ml
@@ -0,0 +1,33 @@
+(* approx: proxy server for Debian archive files
+   Copyright (C) 2010  Eric C. Cooper <ecc at cmu.edu>
+   Released under the GNU General Public License *)
+
+open Printf
+open Unix
+open Util
+
+let non_dirs, path =
+  match Sys.argv with
+  | [| _ |] -> false, "."
+  | [| _; "-n" |] -> true, "."
+  | [| _; dir |] -> false, dir
+  | [| _; "-n"; dir |] -> true, dir
+  | _ ->
+      eprintf "Usage: %s [-n] [path]\n" Sys.argv.(0);
+      exit 1
+
+let () =
+  if non_dirs then
+    let bigger (path, n as orig) path' =
+      let n' = file_size path' in
+      if n >= n' then orig else (path', n')
+    in
+    let biggest, n = fold_non_dirs bigger ("", 0L) path in
+    printf "%Ld\t%s\n" n biggest
+  else
+    let bigger (path, n as orig) path' =
+      let n' = (stat path').st_nlink in
+      if n >= n' then orig else (path', n')
+    in
+    let biggest, n = fold_dirs bigger ("", 0) path in
+    printf "%d\t%s\n" n biggest
diff --git a/util.ml b/util.ml
index 78ebc70..6420527 100644
--- a/util.ml
+++ b/util.ml
@@ -251,25 +251,37 @@ let directory_exists dir =
 
 let is_symlink name = (lstat name).st_kind = S_LNK
 
-let rec fold_dirs f init path =
-  let visit acc name =
-    fold_dirs f acc (path ^/ name)
-  in
-  if directory_exists path && not (is_symlink path) then
-    Array.fold_left visit (f init path) (try Sys.readdir path with _ -> [||])
-  else
-    init
-
-let rec fold_non_dirs f init path =
-  let visit acc name =
-    fold_non_dirs f acc (path ^/ name)
+let directory_uid name =
+  try
+    let stats = stat name in
+    if stats.st_kind = S_DIR then Some (stats.st_dev, stats.st_ino)
+    else None
+  with _ -> None
+
+let fold_fs_tree non_dirs f init path =
+  let rec walk uids_seen init path =
+    let visit uids acc name =
+      walk uids acc (path ^/ name)
+    in
+    let uid = directory_uid path in
+    if uid <> None then
+      if List.mem uid uids_seen then (* cycle detected *)
+        init
+      else
+        let uids_seen = uid :: uids_seen in
+        let children = try Sys.readdir path with _ -> [||] in
+        let init = if non_dirs then init else f init path in
+        Array.fold_left (visit uids_seen) init children
+    else if non_dirs && Sys.file_exists path then
+      f init path
+    else
+      init
   in
-  if directory_exists path && not (is_symlink path) then
-    Array.fold_left visit init (try Sys.readdir path with _ -> [||])
-  else if Sys.file_exists path && not (is_symlink path) then
-    f init path
-  else
-    init
+  walk [] init path
+
+let fold_dirs f = fold_fs_tree false f
+
+let fold_non_dirs f = fold_fs_tree true f
 
 let iter_of_fold fold proc = fold (fun () -> proc) ()
 

-- 
approx upstream and debian packaging



More information about the Pkg-ocaml-maint-commits mailing list