summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Nelson <ajnelson@cs.ucsc.edu>2011-09-01 18:17:36 -0700
committerRichard W.M. Jones <rjones@redhat.com>2011-09-06 14:58:14 +0100
commite85b1eaa268caea316f6aa8e02738b3d94297250 (patch)
tree37f8f2b2f6977a4b4ffd07503b21229baaf00c9b
parent2929a0053a56e1d3b0bed26f16a1e1ad83141891 (diff)
downloadhivex-e85b1eaa268caea316f6aa8e02738b3d94297250.tar.gz
hivex-e85b1eaa268caea316f6aa8e02738b3d94297250.tar.xz
hivex-e85b1eaa268caea316f6aa8e02738b3d94297250.zip
hivex: Add metadata length functions for nodes and values
This patch adds hivex_node_struct_length and hivex_value_struct_length to the hivex ABI, to report the amount of hive space used for each stored structure. Signed-off-by: Alex Nelson <ajnelson@cs.ucsc.edu> A fix added by RWMJ.
-rwxr-xr-xgenerator/generator.ml12
-rw-r--r--lib/hivex.c38
2 files changed, 50 insertions, 0 deletions
diff --git a/generator/generator.ml b/generator/generator.ml
index 6f318ac..b6fb8b3 100755
--- a/generator/generator.ml
+++ b/generator/generator.ml
@@ -262,6 +262,18 @@ information, and the value itself. Also, C<hivex_value_*> functions
below which can be used to return the value in a more useful form when
you know the type in advance.";
+ "node_struct_length", (RSize, [AHive; ANode "node"]),
+ "return the length of a node",
+ "\
+Return the length of the node data structure. Returns 0
+and sets errno on error.";
+
+ "value_struct_length", (RSize, [AHive; AValue "val"]),
+ "return the length of a value data structure",
+ "\
+Return the length of the value data structure. Returns 0
+and sets errno on error.";
+
"value_value", (RLenTypeVal, [AHive; AValue "val"]),
"return data length, data type and data of a value",
"\
diff --git a/lib/hivex.c b/lib/hivex.c
index a183527..3063c45 100644
--- a/lib/hivex.c
+++ b/lib/hivex.c
@@ -585,6 +585,30 @@ hivex_root (hive_h *h)
return ret;
}
+size_t
+hivex_node_struct_length (hive_h *h, hive_node_h node)
+{
+ if (!IS_VALID_BLOCK (h, node) || !BLOCK_ID_EQ (h, node, "nk")) {
+ errno = EINVAL;
+ return 0;
+ }
+
+ struct ntreg_nk_record *nk = (struct ntreg_nk_record *) (h->addr + node);
+ size_t name_len = le16toh (nk->name_len);
+ /* -1 to avoid double-counting the first name character */
+ size_t ret = name_len + sizeof (struct ntreg_nk_record) - 1;
+ int used;
+ size_t seg_len = block_len (h, node, &used);
+ if (ret > seg_len) {
+ if (h->msglvl >= 2)
+ fprintf (stderr, "hivex_node_struct_length: returning EFAULT because"
+ " node name is too long (%zu, %zu)\n", name_len, seg_len);
+ errno = EFAULT;
+ return 0;
+ }
+ return ret;
+}
+
char *
hivex_node_name (hive_h *h, hive_node_h node)
{
@@ -1190,6 +1214,20 @@ hivex_node_get_value (hive_h *h, hive_node_h node, const char *key)
}
size_t
+hivex_value_struct_length (hive_h *h, hive_value_h value)
+{
+ size_t key_len;
+
+ errno = 0;
+ key_len = hivex_value_key_len (h, value);
+ if (key_len == 0 && errno != 0)
+ return 0;
+
+ /* -1 to avoid double-counting the first name character */
+ return key_len + sizeof (struct ntreg_vk_record) - 1;
+}
+
+size_t
hivex_value_key_len (hive_h *h, hive_value_h value)
{
if (!IS_VALID_BLOCK (h, value) || !BLOCK_ID_EQ (h, value, "vk")) {