2 * Copyright (C) 2010 Red Hat Inc.
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.
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.
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.
23 (* See struct/field description in .mli file. *)
26 model : GTree.tree_store;
27 hash : (int, hdata) Hashtbl.t;
28 index_col : int GTree.column;
29 mode_col : string GTree.column;
30 name_col : string GTree.column;
31 size_col : string GTree.column;
32 date_col : string GTree.column;
36 mutable state : state_t;
38 mutable visited : bool;
39 mutable hiveh : Hivex.t option;
50 | ErrorMessage of string
53 | TopWinReg of source * string * string * string
54 | Directory of direntry
56 | RegKey of Hivex.node
57 | RegValue of Hivex.value
59 (* Store hdata into a row. *)
60 let store_hdata {model = model; hash = hash; index_col = index_col} row hdata =
61 let index = unique () in
62 Hashtbl.add hash index hdata;
63 model#set ~row ~column:index_col index
65 (* Retrieve previously stored hdata from a row. *)
66 let get_hdata { model = model; hash = hash; index_col = index_col } row =
67 let index = model#get ~row ~column:index_col in
68 try Hashtbl.find hash index
69 with Not_found -> assert false
71 (* Iterate over children of node, looking for matching hdata. *)
72 let find_child_node_by_content ({ model = model } as t) row c =
74 if (get_hdata t row).content = c then
76 else if model#iter_next row then
82 if not (model#iter_has_child row) then
85 let first_child = model#iter_children (Some row) in
88 (* Search up to the top of the tree so we know if this directory
89 * comes from an OS or a volume, and the full path to here.
91 * The path up the tree will always look something like:
95 * \_ Loading <--- you are here
97 * Note this function cannot be called on registry keys. See
98 * {!get_registry_path} for that.
100 let rec get_pathname ({ model = model } as t) row =
101 let hdata = get_hdata t row in
102 let parent = model#iter_parent row in
104 match hdata, parent with
105 | { state=IsLeaf; content=(Loading|ErrorMessage _|Info _) }, Some parent ->
106 get_pathname t parent
107 | { state=IsLeaf; content=(Loading|ErrorMessage _|Info _) }, None ->
109 | { content=Directory { dent_name = name }}, Some parent
110 | { content=File { dent_name = name }}, Some parent ->
111 let src, parent_name = get_pathname t parent in
113 if parent_name = "/" then "/" ^ name
114 else parent_name ^ "/" ^ name in
116 | { content=Top src }, _ -> src, "/"
117 | { content=Directory _ }, None -> assert false
118 | { content=File _ }, None -> assert false
119 | { content=Loading }, _ -> assert false
120 | { content=ErrorMessage _ }, _ -> assert false
121 | { content=Info _ }, _ -> assert false
122 | { content=TopWinReg _ }, _ -> assert false
123 | { content=RegKey _ }, _ -> assert false
124 | { content=RegValue _ }, _ -> assert false
126 (* Search up to the top of the tree from a registry key.
128 * The path up the tree will always look something like:
131 * \_ RegKey <--- you are here
132 * \_ Loading <--- or here
134 * Note this function cannot be called on ordinary paths. Use
135 * {!get_pathname} for that.
137 let rec get_registry_path ({ model = model } as t) row =
138 let hdata = get_hdata t row in
139 let parent = model#iter_parent row in
141 match hdata, parent with
142 | { state=IsLeaf; content=(Loading|ErrorMessage _|Info _) }, Some parent ->
143 get_registry_path t parent
144 | { state=IsLeaf; content=(Loading|ErrorMessage _|Info _) }, None ->
146 | { content=RegKey node; hiveh = Some h }, Some parent ->
147 let top, path = get_registry_path t parent in
148 let path = Hivex.node_name h node :: path in
150 | { content=TopWinReg (a,b,c,d) }, None -> (a,b,c,d), []
151 | { content=TopWinReg _ }, _ -> assert false
152 | { content=RegKey _}, _ -> assert false
153 | { content=Top _ }, _ -> assert false
154 | { content=Directory _ }, _ -> assert false
155 | { content=File _ }, _ -> assert false
156 | { content=Loading }, _ -> assert false
157 | { content=ErrorMessage _ }, _ -> assert false
158 | { content=Info _ }, _ -> assert false
159 | { content=RegValue _ }, _ -> assert false
161 let rec cache_registry_file ?fail t path src remotefile cachefile cb =
162 Slave.download_file_if_not_exist ?fail src remotefile cachefile
163 (when_cached_registry ?fail t path cb)
165 and when_cached_registry ?fail ({ model = model } as t) path cb () =
166 debug "when_cached_registry";
167 let row = model#get_iter path in
168 let hdata = get_hdata t row in
171 | { hiveh=Some _; content=TopWinReg _ } ->
172 (* Hive handle already opened. *)
175 | { hiveh=None; content=TopWinReg (src, rootkey, remotefile, cachefile) } ->
176 (* Hive handle not opened, open it and save it in the handle. *)
178 let flags = if verbose () then [ Hivex.OPEN_VERBOSE ] else [] in
179 let h = Hivex.open_file cachefile flags in
180 hdata.hiveh <- Some h;
183 Hivex.Error _ as exn ->
185 | Some fail -> fail exn