Use bitstring, enable display of symlinks on NTFS.
[guestfs-browser.git] / filetree_type.ml
1 (* Guestfs Browser.
2  * Copyright (C) 2010 Red Hat Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  *)
18
19 open Utils
20
21 (* See struct/field description in .mli file. *)
22 type t = {
23   view : GTree.view;
24   model : GTree.tree_store;
25   hash : (int, hdata) Hashtbl.t;
26   index_col : int GTree.column;
27   mode_col : string GTree.column;
28   name_col : string GTree.column;
29   size_col : string GTree.column;
30   date_col : string GTree.column;
31 }
32
33 and hdata = {
34   mutable state : state_t;
35   content : content_t;
36   mutable visited : bool;
37   mutable hiveh : Hivex.t option;
38 }
39
40 and state_t =
41   | IsLeaf
42   | NodeNotStarted
43   | NodeLoading
44   | IsNode
45
46 and content_t =
47   | Loading
48   | ErrorMessage of string
49   | Info of string
50   | Top of Slave.source
51   | TopWinReg of Slave.source * string * string * string
52   | Directory of Slave.direntry
53   | File of Slave.direntry
54   | RegKey of Hivex.node
55   | RegValue of Hivex.value
56
57 (* Store hdata into a row. *)
58 let store_hdata {model = model; hash = hash; index_col = index_col} row hdata =
59   let index = unique () in
60   Hashtbl.add hash index hdata;
61   model#set ~row ~column:index_col index
62
63 (* Retrieve previously stored hdata from a row. *)
64 let get_hdata { model = model; hash = hash; index_col = index_col } row =
65   let index = model#get ~row ~column:index_col in
66   try Hashtbl.find hash index
67   with Not_found -> assert false
68
69 (* Iterate over children of node, looking for matching hdata. *)
70 let find_child_node_by_content ({ model = model } as t) row c =
71   let rec loop row =
72     if (get_hdata t row).content = c then
73       row
74     else if model#iter_next row then
75       loop row
76     else
77       raise Not_found
78   in
79
80   if not (model#iter_has_child row) then
81     raise Not_found;
82
83   let first_child = model#iter_children (Some row) in
84   loop first_child
85
86 (* Search up to the top of the tree so we know if this directory
87  * comes from an OS or a volume, and the full path to here.
88  *
89  * The path up the tree will always look something like:
90  *     Top
91  *       \_ Directory
92  *            \_ Directory
93  *                 \_ Loading    <--- you are here
94  *
95  * Note this function cannot be called on registry keys.
96  *)
97 let rec get_pathname ({ model = model } as t) row =
98   let hdata = get_hdata t row in
99   let parent = model#iter_parent row in
100
101   match hdata, parent with
102   | { state=IsLeaf; content=(Loading|ErrorMessage _|Info _) }, Some parent ->
103       get_pathname t parent
104   | { state=IsLeaf; content=(Loading|ErrorMessage _|Info _) }, None ->
105       assert false
106   | { content=Directory { Slave.dent_name = name }}, Some parent
107   | { content=File { Slave.dent_name = name }}, Some parent ->
108       let src, parent_name = get_pathname t parent in
109       let path =
110         if parent_name = "/" then "/" ^ name
111         else parent_name ^ "/" ^ name in
112       src, path
113   | { content=Top src }, _ -> src, "/"
114   | { content=Directory _ }, None -> assert false
115   | { content=File _ }, None -> assert false
116   | { content=Loading }, _ -> assert false
117   | { content=ErrorMessage _ }, _ -> assert false
118   | { content=Info _ }, _ -> assert false
119   | { content=TopWinReg _ }, _ -> assert false
120   | { content=RegKey _ }, _ -> assert false
121   | { content=RegValue _ }, _ -> assert false