summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorConrad Meyer <cemeyer@cs.washington.edu>2010-07-08 11:12:42 +0100
committerRichard Jones <rjones@redhat.com>2010-07-08 11:12:42 +0100
commit77d38592f59f146c5ef249a3f7036cf2a1e45acd (patch)
treeda04d7fabd78a8c9f0a980cacbf2ffb8a3747257 /lib
parent5e804d7c421c344c0363e94206a38b0a0d06d493 (diff)
downloadhivex-77d38592f59f146c5ef249a3f7036cf2a1e45acd.tar.gz
hivex-77d38592f59f146c5ef249a3f7036cf2a1e45acd.tar.xz
hivex-77d38592f59f146c5ef249a3f7036cf2a1e45acd.zip
Add hivex_set_value API call, and ocaml and perl bindings, and tests.
Diffstat (limited to 'lib')
-rw-r--r--lib/hivex.c80
1 files changed, 80 insertions, 0 deletions
diff --git a/lib/hivex.c b/lib/hivex.c
index 74a7f55..c65f6de 100644
--- a/lib/hivex.c
+++ b/lib/hivex.c
@@ -2606,3 +2606,83 @@ hivex_node_set_values (hive_h *h, hive_node_h node,
return 0;
}
+
+int
+hivex_node_set_value (hive_h *h, hive_node_h node,
+ const hive_set_value *val, int flags)
+{
+ hive_value_h *prev_values = hivex_node_values (h, node);
+ if (prev_values == NULL)
+ return -1;
+
+ int retval = -1;
+
+ size_t nr_values = 0;
+ for (hive_value_h *itr = prev_values; *itr != 0; ++itr)
+ ++nr_values;
+
+ hive_set_value *values = malloc ((nr_values + 1) * (sizeof (hive_set_value)));
+ if (values == NULL)
+ goto leave_prev_values;
+
+ int alloc_ct = 0;
+ int idx_of_val = -1;
+ hive_value_h *prev_val;
+ for (prev_val = prev_values; *prev_val != 0; ++prev_val) {
+ size_t len;
+ hive_type t;
+
+ hive_set_value *value = &values[prev_val - prev_values];
+
+ char *valval = hivex_value_value (h, *prev_val, &t, &len);
+ if (valval == NULL) goto leave_partial;
+
+ ++alloc_ct;
+ value->value = valval;
+ value->t = t;
+ value->len = len;
+
+ char *valkey = hivex_value_key (h, *prev_val);
+ if (valkey == NULL) goto leave_partial;
+
+ ++alloc_ct;
+ value->key = valkey;
+
+ if (STRCASEEQ (valkey, val->key))
+ idx_of_val = prev_val - prev_values;
+ }
+
+ if (idx_of_val > -1) {
+ free (values[idx_of_val].key);
+ free (values[idx_of_val].value);
+ } else {
+ idx_of_val = nr_values;
+ ++nr_values;
+ }
+
+ hive_set_value *value = &values[idx_of_val];
+ *value = (hive_set_value){
+ .key = strdup (val->key),
+ .value = malloc (val->len),
+ .len = val->len,
+ .t = val->t
+ };
+
+ if (value->key == NULL || value->value == NULL) goto leave_partial;
+ memcpy (value->value, val->value, val->len);
+
+ retval = hivex_node_set_values (h, node, nr_values, values, 0);
+
+ leave_partial:
+ for (int i = 0; i < alloc_ct; i += 2) {
+ if (values[i / 2].value != NULL)
+ free (values[i / 2].value);
+ if (i + 1 < alloc_ct && values[i / 2].key != NULL)
+ free (values[i / 2].key);
+ }
+ free (values);
+
+ leave_prev_values:
+ free (prev_values);
+ return retval;
+}