diff options
| author | Conrad Meyer <cemeyer@cs.washington.edu> | 2010-07-08 11:12:42 +0100 |
|---|---|---|
| committer | Richard Jones <rjones@redhat.com> | 2010-07-08 11:12:42 +0100 |
| commit | 77d38592f59f146c5ef249a3f7036cf2a1e45acd (patch) | |
| tree | da04d7fabd78a8c9f0a980cacbf2ffb8a3747257 /lib | |
| parent | 5e804d7c421c344c0363e94206a38b0a0d06d493 (diff) | |
| download | hivex-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.c | 80 |
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; +} |
