X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=filetree_type.ml;h=285677f6f415d3db388ce89d522fdfa7ed8a6e84;hb=a4317d06454daae173209204137998838c73807a;hp=9f2bc64e7ea590bdd192e7d53db61d9d5b6f61b3;hpb=c79fc07ff71926b3bf956ff296336f6f71bb3b1e;p=guestfs-browser.git diff --git a/filetree_type.ml b/filetree_type.ml index 9f2bc64..285677f 100644 --- a/filetree_type.ml +++ b/filetree_type.ml @@ -18,39 +18,43 @@ open Utils +open Slave_types + +(* See struct/field description in .mli file. *) type t = { view : GTree.view; model : GTree.tree_store; - hash : (int, hdata) Hashtbl.t; (* hash from index_col -> hdata *) + hash : (int, hdata) Hashtbl.t; index_col : int GTree.column; mode_col : string GTree.column; name_col : string GTree.column; - size_col : int64 GTree.column; + size_col : string GTree.column; date_col : string GTree.column; - link_col : string GTree.column; } -and hdata = state_t * content_t +and hdata = { + mutable state : state_t; + content : content_t; + mutable visited : bool; + mutable hiveh : Hivex.t option; +} -(* The type of the hidden column used to implement on-demand loading. - * All rows are classified as either nodes or leafs (eg. a "node" might - * be a directory, or a top-level operating system, or anything else - * which the user could open and look inside). - *) and state_t = - | IsLeaf (* there are no children *) - | NodeNotStarted (* user has not tried to open this *) - | NodeLoading (* user tried to open it, still loading *) - | IsNode (* we've loaded the children of this directory *) + | IsLeaf + | NodeNotStarted + | NodeLoading + | IsNode -(* The actual content of a row. *) and content_t = - | Loading (* special "loading ..." node *) - | ErrorMessage of string (* error message node *) - | Info of string (* information node (eg. disk usage) *) - | Top of Slave.source (* top level OS or volume node *) - | Directory of Slave.direntry (* a directory *) - | File of Slave.direntry (* a file inc. special files *) + | Loading + | ErrorMessage of string + | Info of string + | Top of source + | TopWinReg of source * string * string * string + | Directory of direntry + | File of direntry + | RegKey of Hivex.node + | RegValue of Hivex.value (* Store hdata into a row. *) let store_hdata {model = model; hash = hash; index_col = index_col} row hdata = @@ -65,9 +69,9 @@ let get_hdata { model = model; hash = hash; index_col = index_col } row = with Not_found -> assert false (* Iterate over children of node, looking for matching hdata. *) -let find_child_node_by_hdata ({ model = model } as t) row hdata = +let find_child_node_by_content ({ model = model } as t) row c = let rec loop row = - if hdata = get_hdata t row then + if (get_hdata t row).content = c then row else if model#iter_next row then loop row @@ -89,26 +93,96 @@ let find_child_node_by_hdata ({ model = model } as t) row hdata = * \_ Directory * \_ Directory * \_ Loading <--- you are here + * + * Note this function cannot be called on registry keys. See + * {!get_registry_path} for that. *) let rec get_pathname ({ model = model } as t) row = let hdata = get_hdata t row in let parent = model#iter_parent row in match hdata, parent with - | (IsLeaf, (Loading|ErrorMessage _|Info _)), Some parent -> + | { state=IsLeaf; content=(Loading|ErrorMessage _|Info _) }, Some parent -> get_pathname t parent - | (IsLeaf, (Loading|ErrorMessage _|Info _)), None -> + | { state=IsLeaf; content=(Loading|ErrorMessage _|Info _) }, None -> assert false - | (_, Directory { Slave.dent_name = name }), Some parent - | (_, File { Slave.dent_name = name }), Some parent -> + | { content=Directory { dent_name = name }}, Some parent + | { content=File { dent_name = name }}, Some parent -> let src, parent_name = get_pathname t parent in let path = if parent_name = "/" then "/" ^ name else parent_name ^ "/" ^ name in src, path - | (_, Top src), _ -> src, "/" - | (_, Directory _), None -> assert false - | (_, File _), None -> assert false - | (_, Loading), _ -> assert false - | (_, ErrorMessage _), _ -> assert false - | (_, Info _), _ -> assert false + | { content=Top src }, _ -> src, "/" + | { content=Directory _ }, None -> assert false + | { content=File _ }, None -> assert false + | { content=Loading }, _ -> assert false + | { content=ErrorMessage _ }, _ -> assert false + | { content=Info _ }, _ -> assert false + | { content=TopWinReg _ }, _ -> assert false + | { content=RegKey _ }, _ -> assert false + | { content=RegValue _ }, _ -> assert false + +(* Search up to the top of the tree from a registry key. + * + * The path up the tree will always look something like: + * TopWinReg + * \_ RegKey + * \_ RegKey <--- you are here + * \_ Loading <--- or here + * + * Note this function cannot be called on ordinary paths. Use + * {!get_pathname} for that. + *) +let rec get_registry_path ({ model = model } as t) row = + let hdata = get_hdata t row in + let parent = model#iter_parent row in + + match hdata, parent with + | { state=IsLeaf; content=(Loading|ErrorMessage _|Info _) }, Some parent -> + get_registry_path t parent + | { state=IsLeaf; content=(Loading|ErrorMessage _|Info _) }, None -> + assert false + | { content=RegKey node; hiveh = Some h }, Some parent -> + let top, path = get_registry_path t parent in + let path = Hivex.node_name h node :: path in + top, path + | { content=TopWinReg (a,b,c,d) }, None -> (a,b,c,d), [] + | { content=TopWinReg _ }, _ -> assert false + | { content=RegKey _}, _ -> assert false + | { content=Top _ }, _ -> assert false + | { content=Directory _ }, _ -> assert false + | { content=File _ }, _ -> assert false + | { content=Loading }, _ -> assert false + | { content=ErrorMessage _ }, _ -> assert false + | { content=Info _ }, _ -> assert false + | { content=RegValue _ }, _ -> assert false + +let rec cache_registry_file ?fail t path src remotefile cachefile cb = + Slave.download_file_if_not_exist ?fail src remotefile cachefile + (when_cached_registry ?fail t path cb) + +and when_cached_registry ?fail ({ model = model } as t) path cb () = + debug "when_cached_registry"; + let row = model#get_iter path in + let hdata = get_hdata t row in + + match hdata with + | { hiveh=Some _; content=TopWinReg _ } -> + (* Hive handle already opened. *) + cb () + + | { hiveh=None; content=TopWinReg (src, rootkey, remotefile, cachefile) } -> + (* Hive handle not opened, open it and save it in the handle. *) + (try + let flags = if verbose () then [ Hivex.OPEN_VERBOSE ] else [] in + let h = Hivex.open_file cachefile flags in + hdata.hiveh <- Some h; + cb () + with + Hivex.Error _ as exn -> + match fail with + | Some fail -> fail exn + | None -> raise exn + ) + | _ -> assert false