appliance VM won't start, can't find /init, but /init is in the image.
by David Konerding
Hi,
Still trying to get libguestfs appliance test to work on Ubuntu Lucid. I
figured out my umask was causing problems and fixed that. now I'm on to a
new problem. libguestfs-test-tool reports the following:
febootstrap: mounting new root on /root
febootstrap: chroot
/proc/uptime: No such file or directory
execl: /init: No such file or directory
febootstrap: debug: listing directory /
2 d . 040755 4096 88619:5000
2 d .. 040755 4096 88619:5000
11 d lost+found 040700 16384 0:0
12 d bin 040755 4096 23083:5000
13 d boot 040755 4096 23083:5000
14 d etc 040755 4096 23083:5000
109 d lib 040755 4096 23083:5000
156 d sbin 040755 4096 23083:5000
157 d usr 040755 4096 23083:5000
534 d var 040755 4096 23083:5000
3701 - init 100750 3264 23083:5000
Note, init is indeed a file (a shell script). I checked the root and initrd
images, and they both have init (the initrd has an init binary, the root has
a shell script that starts udev etc).
13 years, 3 months
[PATCH] hivex: Add byte runs for nodes and values
by Alex Nelson
This patch adds byte run reporters for node and value metadata in the
hivexml program. Each byte run represents the offset and length of a
data structure within the hive, one per node, and one or two per value
depending on the length of the value data. In order to add this
metadata reporting, the following changes were put in place:
* Split value_key function into value_key and value_key_len.
* Add return types to the generator: RSize, RLenNode, and RLenValue.
* Add support for the new return types to all language bindings,
including an extra OCaml and Python function.
* Add metadata length functions for nodes and values: hivex_{node,value}
_struct_length.
* Add an offset-&-length function for long value data.
* Have value data be reported in attributes instead of text.
* Add byte run functions to hivexml: value_byte_runs and
node_byte_runs.
Signed-off-by: Alex Nelson <ajnelson(a)cs.ucsc.edu>
---
generator/generator.ml | 169 +++++++++++++++++++++++++++++++++++++++++++++++-
lib/hivex.c | 115 +++++++++++++++++++++++++++++---
xml/hivexml.c | 127 ++++++++++++++++++++++++++++++++----
3 files changed, 385 insertions(+), 26 deletions(-)
diff --git a/generator/generator.ml b/generator/generator.ml
index c98e625..b607421 100755
--- a/generator/generator.ml
+++ b/generator/generator.ml
@@ -45,11 +45,14 @@ and ret =
| RErr (* 0 = ok, -1 = error *)
| RErrDispose (* Disposes handle, see hivex_close. *)
| RHive (* Returns a hive_h or NULL. *)
+ | RSize (* Returns size_t or 0. *)
| RNode (* Returns hive_node_h or 0. *)
| RNodeNotFound (* See hivex_node_get_child. *)
| RNodeList (* Returns hive_node_h* or NULL. *)
+ | RLenNode (* See node_struct_length. *)
| RValue (* Returns hive_value_h or 0. *)
| RValueList (* Returns hive_value_h* or NULL. *)
+ | RLenValue (* See value_struct_length. *)
| RString (* Returns char* or NULL. *)
| RStringList (* Returns char** or NULL. *)
| RLenType (* See hivex_value_type. *)
@@ -228,6 +231,17 @@ string C<\"\"> here. The default key is often written C<\"@\">, but
inside hives that has no meaning and won't give you the
default key.";
+ "value_key_len", (RSize, [AHive; AValue "val"]),
+ "return the length of a value's key",
+ "\
+Return the length of the key (name) of a (key, value) pair. The
+length can legitimately be 0, so errno is the necesary mechanism
+to check for errors.
+
+In the context of Windows Registries, a zero-length name means
+that this value is the default key for this node in the tree.
+This is usually written as C<\"@\">.";
+
"value_key", (RString, [AHive; AValue "val"]),
"return the key of a (key, value) pair",
"\
@@ -250,6 +264,29 @@ 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_data_cell_offset", (RLenValue, [AHive; AValue "val"]),
+ "return the offset and length of a value data cell",
+ "\
+Return the offset and length of the value's data cell, not value cell.
+E.g. if the value were \"foobar\" then the length would be 6, and the
+offset would be to a value data cell, which is the data prefixed with
+4 bytes describing the size. If the length is not greater than 4,
+then 0 is returned, as the data are inline in the value.
+
+Returns 0 and sets errno on error.";
+
"value_value", (RLenTypeVal, [AHive; AValue "val"]),
"return data length, data type and data of a value",
"\
@@ -858,6 +895,7 @@ and generate_c_prototype ?(extern = false) name style =
| RErr -> pr "int "
| RErrDispose -> pr "int "
| RHive -> pr "hive_h *"
+ | RSize -> pr "size_t "
| RNode -> pr "hive_node_h "
| RNodeNotFound -> pr "hive_node_h "
| RNodeList -> pr "hive_node_h *"
@@ -865,6 +903,8 @@ and generate_c_prototype ?(extern = false) name style =
| RValueList -> pr "hive_value_h *"
| RString -> pr "char *"
| RStringList -> pr "char **"
+ | RLenNode -> pr "hive_node_h "
+ | RLenValue -> pr "hive_value_h "
| RLenType -> pr "int "
| RLenTypeVal -> pr "char *"
| RInt32 -> pr "int32_t "
@@ -886,6 +926,8 @@ and generate_c_prototype ?(extern = false) name style =
) (snd style);
(match fst style with
| RLenType | RLenTypeVal -> pr ", hive_type *t, size_t *len"
+ | RLenNode -> pr ", size_t *len"
+ | RLenValue -> pr ", size_t *len"
| _ -> ()
);
pr ");\n"
@@ -1046,6 +1088,10 @@ The hive handle must not be used again after calling this function.\n\n"
pr "\
Returns a new hive handle.
On error this returns NULL and sets errno.\n\n"
+ | RSize ->
+ pr "\
+Returns a size.
+On error this returns 0 and sets errno.\n\n"
| RNode ->
pr "\
Returns a node handle.
@@ -1084,6 +1130,14 @@ On error this returns NULL and sets errno.\n\n"
pr "\
Returns 0 on success.
On error this returns -1 and sets errno.\n\n"
+ | RLenNode ->
+ pr "\
+Returns a positive number on success.
+On error this returns 0 and sets errno.\n\n"
+ | RLenValue ->
+ pr "\
+Returns a positive number on success.
+On error this returns 0 and sets errno.\n\n"
| RLenTypeVal ->
pr "\
The value is returned as an array of bytes (of length C<len>).
@@ -1586,6 +1640,7 @@ and generate_ocaml_prototype ?(is_external = false) name style =
| RErr -> pr "unit" (* all errors are turned into exceptions *)
| RErrDispose -> pr "unit"
| RHive -> pr "t"
+ | RSize -> pr "size"
| RNode -> pr "node"
| RNodeNotFound -> pr "node"
| RNodeList -> pr "node array"
@@ -1594,6 +1649,8 @@ and generate_ocaml_prototype ?(is_external = false) name style =
| RString -> pr "string"
| RStringList -> pr "string array"
| RLenType -> pr "hive_type * int"
+ | RLenNode -> pr "node"
+ | RLenValue -> pr "value"
| RLenTypeVal -> pr "hive_type * string"
| RInt32 -> pr "int32"
| RInt64 -> pr "int64"
@@ -1679,6 +1736,8 @@ static void raise_closed (const char *) Noreturn;
let c_params =
match fst style with
| RLenType | RLenTypeVal -> c_params @ [["&t"; "&len"]]
+ | RLenNode -> c_params @ [["&len"]]
+ | RLenValue -> c_params @ [["&len"]]
| _ -> c_params in
let c_params = List.concat c_params in
@@ -1735,6 +1794,7 @@ static void raise_closed (const char *) Noreturn;
| RErr -> pr " int r;\n"; "-1"
| RErrDispose -> pr " int r;\n"; "-1"
| RHive -> pr " hive_h *r;\n"; "NULL"
+ | RSize -> pr " size_t r;\n"; "0"
| RNode -> pr " hive_node_h r;\n"; "0"
| RNodeNotFound ->
pr " errno = 0;\n";
@@ -1750,6 +1810,14 @@ static void raise_closed (const char *) Noreturn;
pr " size_t len;\n";
pr " hive_type t;\n";
"-1"
+ | RLenNode ->
+ pr " int r;\n";
+ pr " size_t len;\n";
+ "0"
+ | RLenValue ->
+ pr " int r;\n";
+ pr " size_t len;\n";
+ "0"
| RLenTypeVal ->
pr " char *r;\n";
pr " size_t len;\n";
@@ -1808,6 +1876,7 @@ static void raise_closed (const char *) Noreturn;
| RErr -> pr " rv = Val_unit;\n"
| RErrDispose -> pr " rv = Val_unit;\n"
| RHive -> pr " rv = Val_hiveh (r);\n"
+ | RSize -> pr " rv = Val_int (r);\n"
| RNode -> pr " rv = Val_int (r);\n"
| RNodeNotFound ->
pr " if (r == 0)\n";
@@ -1829,6 +1898,8 @@ static void raise_closed (const char *) Noreturn;
pr " for (int i = 0; r[i] != NULL; ++i) free (r[i]);\n";
pr " free (r);\n"
| RLenType -> pr " rv = copy_type_len (len, t);\n"
+ | RLenNode -> pr " rv = copy_len (len);\n"
+ | RLenValue -> pr " rv = copy_len (len);\n"
| RLenTypeVal ->
pr " rv = copy_type_value (r, len, t);\n";
pr " free (r);\n"
@@ -1951,6 +2022,18 @@ copy_type_len (size_t len, hive_type t)
}
static value
+copy_type (size_t len, hive_type t)
+{
+ CAMLparam0 ();
+ CAMLlocal2 (v, rv);
+
+ rv = caml_alloc (1, 0);
+ v = Val_int (len);
+ Store_field (rv, 0, v);
+ CAMLreturn (rv);
+}
+
+static value
copy_type_value (const char *r, size_t len, hive_type t)
{
CAMLparam0 ();
@@ -2140,9 +2223,14 @@ sub open {
| RString
| RStringList
| RLenType
+ | RLenNode
+ | RLenValue
| RLenTypeVal
| RInt32
| RInt64 -> ()
+ | RSize ->
+ pr "\
+This returns a size.\n\n"
| RNode ->
pr "\
This returns a node handle.\n\n"
@@ -2202,6 +2290,7 @@ and generate_perl_prototype name style =
| RErr
| RErrDispose -> ()
| RHive -> pr "$h = "
+ | RSize -> pr "$size = "
| RNode
| RNodeNotFound -> pr "$node = "
| RNodeList -> pr "@nodes = "
@@ -2210,6 +2299,8 @@ and generate_perl_prototype name style =
| RString -> pr "$string = "
| RStringList -> pr "@strings = "
| RLenType -> pr "($type, $len) = "
+ | RLenNode -> pr "($len) = "
+ | RLenValue -> pr "($len) = "
| RLenTypeVal -> pr "($type, $data) = "
| RInt32 -> pr "$int32 = "
| RInt64 -> pr "$int64 = "
@@ -2424,6 +2515,7 @@ DESTROY (h)
| RErr -> pr "void\n"
| RErrDispose -> failwith "perl bindings cannot handle a call which disposes of the handle"
| RHive -> failwith "perl bindings cannot handle a call which returns a handle"
+ | RSize
| RNode
| RNodeNotFound
| RValue
@@ -2432,6 +2524,8 @@ DESTROY (h)
| RValueList
| RStringList
| RLenType
+ | RLenNode
+ | RLenValue
| RLenTypeVal -> pr "void\n"
| RInt32 -> pr "SV *\n"
| RInt64 -> pr "SV *\n"
@@ -2500,6 +2594,7 @@ DESTROY (h)
| RErrDispose -> assert false
| RHive -> assert false
+ | RSize
| RNode
| RValue ->
pr "PREINIT:\n";
@@ -2603,6 +2698,34 @@ DESTROY (h)
pr " PUSHs (sv_2mortal (newSViv (type)));\n";
pr " PUSHs (sv_2mortal (newSViv (len)));\n";
+ | RLenNode ->
+ pr "PREINIT:\n";
+ pr " int r;\n";
+ pr " size_t len;\n";
+ pr " PPCODE:\n";
+ pr " r = hivex_%s (%s, &len);\n"
+ name (String.concat ", " c_params);
+ free_args ();
+ pr " if (r == 0)\n";
+ pr " croak (\"%%s: \", \"%s\", strerror (errno));\n"
+ name;
+ pr " EXTEND (SP, 2);\n";
+ pr " PUSHs (sv_2mortal (newSViv (len)));\n";
+
+ | RLenValue ->
+ pr "PREINIT:\n";
+ pr " int r;\n";
+ pr " size_t len;\n";
+ pr " PPCODE:\n";
+ pr " r = hivex_%s (%s, &len);\n"
+ name (String.concat ", " c_params);
+ free_args ();
+ pr " if (r == 0)\n";
+ pr " croak (\"%%s: \", \"%s\", strerror (errno));\n"
+ name;
+ pr " EXTEND (SP, 2);\n";
+ pr " PUSHs (sv_2mortal (newSViv (len)));\n";
+
| RLenTypeVal ->
pr "PREINIT:\n";
pr " char *r;\n";
@@ -2841,6 +2964,14 @@ put_len_type (size_t len, hive_type t)
}
static PyObject *
+put_len (size_t len)
+{
+ PyObject *r = PyTuple_New (1);
+ PyTuple_SetItem (r, 0, PyLong_FromLongLong ((long) len));
+ return r;
+}
+
+static PyObject *
put_val_type (char *val, size_t len, hive_type t)
{
PyObject *r = PyTuple_New (2);
@@ -2864,6 +2995,7 @@ put_val_type (char *val, size_t len, hive_type t)
| RErr -> pr " int r;\n"; "-1"
| RErrDispose -> pr " int r;\n"; "-1"
| RHive -> pr " hive_h *r;\n"; "NULL"
+ | RSize -> pr " size_t r;\n"; "0"
| RNode -> pr " hive_node_h r;\n"; "0"
| RNodeNotFound ->
pr " errno = 0;\n";
@@ -2879,6 +3011,14 @@ put_val_type (char *val, size_t len, hive_type t)
pr " size_t len;\n";
pr " hive_type t;\n";
"-1"
+ | RLenNode ->
+ pr " int r;\n";
+ pr " size_t len;\n";
+ "0"
+ | RLenValue ->
+ pr " int r;\n";
+ pr " size_t len;\n";
+ "0"
| RLenTypeVal ->
pr " char *r;\n";
pr " size_t len;\n";
@@ -2903,6 +3043,7 @@ put_val_type (char *val, size_t len, hive_type t)
let c_params =
match fst style with
| RLenType | RLenTypeVal -> c_params @ ["&t"; "&len"]
+ | RLenNode | RLenValue -> c_params @ ["&len"]
| _ -> c_params in
List.iter (
@@ -3023,6 +3164,7 @@ put_val_type (char *val, size_t len, hive_type t)
pr " py_r = Py_None;\n"
| RHive ->
pr " py_r = put_handle (r);\n"
+ | RSize
| RNode ->
pr " py_r = PyLong_FromLongLong (r);\n"
| RNodeNotFound ->
@@ -3046,6 +3188,10 @@ put_val_type (char *val, size_t len, hive_type t)
pr " free_strings (r);\n"
| RLenType ->
pr " py_r = put_len_type (len, t);\n"
+ | RLenNode ->
+ pr " py_r = put_len (len);\n"
+ | RLenValue ->
+ pr " py_r = put_len (len);\n"
| RLenTypeVal ->
pr " py_r = put_val_type (r, len, t);\n";
pr " free (r);\n"
@@ -3249,13 +3395,15 @@ get_values (VALUE valuesv, size_t *nr_values)
match ret with
| RErr | RErrDispose -> "nil"
| RHive -> "Hivex::Hivex"
- | RNode | RNodeNotFound -> "integer"
+ | RSize | RNode | RNodeNotFound -> "integer"
| RNodeList -> "list"
| RValue -> "integer"
| RValueList -> "list"
| RString -> "string"
| RStringList -> "list"
| RLenType -> "hash"
+ | RLenNode -> "integer"
+ | RLenValue -> "integer"
| RLenTypeVal -> "hash"
| RInt32 -> "integer"
| RInt64 -> "integer" in
@@ -3338,6 +3486,7 @@ get_values (VALUE valuesv, size_t *nr_values)
| RErr -> pr " int r;\n"; "-1"
| RErrDispose -> pr " int r;\n"; "-1"
| RHive -> pr " hive_h *r;\n"; "NULL"
+ | RSize -> pr " size_t r;\n"; "0"
| RNode -> pr " hive_node_h r;\n"; "0"
| RNodeNotFound ->
pr " errno = 0;\n";
@@ -3353,6 +3502,14 @@ get_values (VALUE valuesv, size_t *nr_values)
pr " size_t len;\n";
pr " hive_type t;\n";
"-1"
+ | RLenNode ->
+ pr " int r;\n";
+ pr " size_t len;\n";
+ "0"
+ | RLenValue ->
+ pr " int r;\n";
+ pr " size_t len;\n";
+ "0"
| RLenTypeVal ->
pr " char *r;\n";
pr " size_t len;\n";
@@ -3377,6 +3534,7 @@ get_values (VALUE valuesv, size_t *nr_values)
let c_params =
match ret with
| RLenType | RLenTypeVal -> c_params @ [["&t"; "&len"]]
+ | RLenNode | RLenValue -> c_params @ [["&len"]]
| _ -> c_params in
let c_params = List.concat c_params in
@@ -3418,6 +3576,7 @@ get_values (VALUE valuesv, size_t *nr_values)
pr " return Qnil;\n"
| RHive ->
pr " return Data_Wrap_Struct (c_hivex, NULL, ruby_hivex_free, r);\n"
+ | RSize
| RNode
| RValue
| RInt64 ->
@@ -3457,6 +3616,14 @@ get_values (VALUE valuesv, size_t *nr_values)
pr " rb_hash_aset (rv, ID2SYM (rb_intern (\"len\")), INT2NUM (len));\n";
pr " rb_hash_aset (rv, ID2SYM (rb_intern (\"type\")), INT2NUM (t));\n";
pr " return rv;\n"
+ | RLenNode ->
+ pr " VALUE rv = rb_hash_new ();\n";
+ pr " rb_hash_aset (rv, ID2SYM (rb_intern (\"len\")), INT2NUM (len));\n";
+ pr " return rv;\n"
+ | RLenValue ->
+ pr " VALUE rv = rb_hash_new ();\n";
+ pr " rb_hash_aset (rv, ID2SYM (rb_intern (\"len\")), INT2NUM (len));\n";
+ pr " return rv;\n"
| RLenTypeVal ->
pr " VALUE rv = rb_hash_new ();\n";
pr " rb_hash_aset (rv, ID2SYM (rb_intern (\"len\")), INT2NUM (len));\n";
diff --git a/lib/hivex.c b/lib/hivex.c
index 4b9fcf0..04ceed3 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)
{
@@ -1189,8 +1213,17 @@ hivex_node_get_value (hive_h *h, hive_node_h node, const char *key)
return ret;
}
-char *
-hivex_value_key (hive_h *h, hive_value_h value)
+size_t
+hivex_value_struct_length (hive_h *h, hive_value_h value) {
+ size_t key_len = hivex_value_key_len (h, value);
+ if (errno)
+ 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")) {
errno = EINVAL;
@@ -1199,24 +1232,39 @@ hivex_value_key (hive_h *h, hive_value_h value)
struct ntreg_vk_record *vk = (struct ntreg_vk_record *) (h->addr + value);
- /* AFAIK the key is always plain ASCII, so no conversion to UTF-8 is
- * necessary. However we do need to nul-terminate the string.
- */
-
/* vk->name_len is unsigned, 16 bit, so this is safe ... However
* we have to make sure the length doesn't exceed the block length.
*/
- size_t len = le16toh (vk->name_len);
+ size_t ret = le16toh (vk->name_len);
size_t seg_len = block_len (h, value, NULL);
- if (sizeof (struct ntreg_vk_record) + len - 1 > seg_len) {
+ if (sizeof (struct ntreg_vk_record) + ret - 1 > seg_len) {
if (h->msglvl >= 2)
- fprintf (stderr, "hivex_value_key: returning EFAULT"
+ fprintf (stderr, "hivex_value_key_len: returning EFAULT"
" because key length is too long (%zu, %zu)\n",
- len, seg_len);
+ ret, seg_len);
errno = EFAULT;
- return NULL;
+ return 0;
+ }
+ return ret;
+}
+
+char *
+hivex_value_key (hive_h *h, hive_value_h value)
+{
+ if (!IS_VALID_BLOCK (h, value) || !BLOCK_ID_EQ (h, value, "vk")) {
+ errno = EINVAL;
+ return 0;
}
+ struct ntreg_vk_record *vk = (struct ntreg_vk_record *) (h->addr + value);
+
+ /* AFAIK the key is always plain ASCII, so no conversion to UTF-8 is
+ * necessary. However we do need to nul-terminate the string.
+ */
+ size_t len = hivex_value_key_len (h, value);
+ if (errno != 0)
+ return NULL;
+
char *ret = malloc (len + 1);
if (ret == NULL)
return NULL;
@@ -1246,6 +1294,51 @@ hivex_value_type (hive_h *h, hive_value_h value, hive_type *t, size_t *len)
return 0;
}
+hive_value_h
+hivex_value_data_cell_offset (hive_h *h, hive_value_h value, size_t *len)
+{
+ if (!IS_VALID_BLOCK (h, value) || !BLOCK_ID_EQ (h, value, "vk")) {
+ errno = EINVAL;
+ return 0;
+ }
+
+ struct ntreg_vk_record *vk = (struct ntreg_vk_record *) (h->addr + value);
+
+ size_t data_len;
+ int is_inline;
+
+ data_len = le32toh (vk->data_len);
+ is_inline = !!(data_len & 0x80000000);
+ data_len &= 0x7fffffff;
+
+ if (is_inline && data_len > 4) {
+ errno = ENOTSUP;
+ return 0;
+ }
+
+ if (is_inline) {
+ /* There is no other location for the value data. */
+ if (len)
+ *len = 0;
+ return 0;
+ } else {
+ if (len)
+ *len = data_len + 4; /* Include 4 header length bytes */
+ }
+
+ size_t data_offset = le32toh (vk->data_offset);
+ data_offset += 0x1000; /* Add 0x1000 because everything's off by 4KiB */
+ if (!IS_VALID_BLOCK (h, data_offset)) {
+ if (h->msglvl >= 2)
+ fprintf (stderr, "hivex_value_data_cell_offset: returning EFAULT because data "
+ "offset is not a valid block (0x%zx)\n",
+ data_offset);
+ errno = EFAULT;
+ return 0;
+ }
+ return data_offset;
+}
+
char *
hivex_value_value (hive_h *h, hive_value_h value,
hive_type *t_rtn, size_t *len_rtn)
diff --git a/xml/hivexml.c b/xml/hivexml.c
index f29c80c..db9cd7d 100644
--- a/xml/hivexml.c
+++ b/xml/hivexml.c
@@ -194,11 +194,39 @@ filetime_to_8601 (int64_t windows_ticks)
return ret;
}
+#define BYTE_RUN_BUF_LEN 32
+
+static int
+node_byte_runs (hive_h *h, void *writer_v, hive_node_h node)
+{
+ xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v;
+ char buf[1+BYTE_RUN_BUF_LEN];
+ size_t node_struct_length = hivex_node_struct_length (h, node);
+ if (errno) {
+ if (errno == EINVAL) {
+ fprintf (stderr, "node_byte_runs: Invoked on what does not seem to be a node (%zu).\n", node);
+ }
+ return -1;
+ }
+ /* A node has one byte run. */
+ XML_CHECK (xmlTextWriterStartElement, (writer, BAD_CAST "byte_runs"));
+ XML_CHECK (xmlTextWriterStartElement, (writer, BAD_CAST "byte_run"));
+ memset (buf, 0, 1+BYTE_RUN_BUF_LEN);
+ snprintf (buf, 1+BYTE_RUN_BUF_LEN, "%d", node);
+ XML_CHECK (xmlTextWriterWriteAttribute, (writer, BAD_CAST "offset", BAD_CAST buf));
+ snprintf (buf, 1+BYTE_RUN_BUF_LEN, "%d", node_struct_length);
+ XML_CHECK (xmlTextWriterWriteAttribute, (writer, BAD_CAST "len", BAD_CAST buf));
+ XML_CHECK (xmlTextWriterEndElement, (writer));
+ XML_CHECK (xmlTextWriterEndElement, (writer));
+ return 0;
+}
+
static int
node_start (hive_h *h, void *writer_v, hive_node_h node, const char *name)
{
int64_t last_modified;
char *timebuf;
+ int ret = 0;
xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v;
XML_CHECK (xmlTextWriterStartElement, (writer, BAD_CAST "node"));
@@ -219,7 +247,8 @@ node_start (hive_h *h, void *writer_v, hive_node_h node, const char *name)
}
}
- return 0;
+ ret = node_byte_runs (h, writer_v, node);
+ return ret;
}
static int
@@ -251,11 +280,52 @@ end_value (xmlTextWriterPtr writer)
}
static int
+value_byte_runs (hive_h *h, void *writer_v, hive_value_h value) {
+ xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v;
+ char buf[1+BYTE_RUN_BUF_LEN];
+ size_t value_data_cell_length;
+ size_t value_data_structure_length = hivex_value_struct_length (h, value);
+ if (errno != 0) {
+ if (errno == EINVAL) {
+ fprintf (stderr, "value_byte_runs: Invoked on what does not seem to be a value (%zu).\n", value);
+ }
+ return -1;
+ }
+ hive_value_h value_data_cell_offset = hivex_value_data_cell_offset (h, value, &value_data_cell_length);
+ if (errno != 0)
+ return -1;
+
+ XML_CHECK (xmlTextWriterStartElement, (writer, BAD_CAST "byte_runs"));
+ memset (buf, 0, 1+BYTE_RUN_BUF_LEN);
+
+ /* Write first byte run for data structure */
+ XML_CHECK (xmlTextWriterStartElement, (writer, BAD_CAST "byte_run"));
+ snprintf (buf, 1+BYTE_RUN_BUF_LEN, "%d", value);
+ XML_CHECK (xmlTextWriterWriteAttribute, (writer, BAD_CAST "offset", BAD_CAST buf));
+ snprintf (buf, 1+BYTE_RUN_BUF_LEN, "%d", value_data_structure_length);
+ XML_CHECK (xmlTextWriterWriteAttribute, (writer, BAD_CAST "len", BAD_CAST buf));
+ XML_CHECK (xmlTextWriterEndElement, (writer));
+
+ /* Write second byte run for longer values */
+ if (value_data_cell_length > 4) {
+ XML_CHECK (xmlTextWriterStartElement, (writer, BAD_CAST "byte_run"));
+ snprintf (buf, 1+BYTE_RUN_BUF_LEN, "%d", value_data_cell_offset);
+ XML_CHECK (xmlTextWriterWriteAttribute, (writer, BAD_CAST "offset", BAD_CAST buf));
+ snprintf (buf, 1+BYTE_RUN_BUF_LEN, "%d", value_data_cell_length);
+ XML_CHECK (xmlTextWriterWriteAttribute, (writer, BAD_CAST "len", BAD_CAST buf));
+ XML_CHECK (xmlTextWriterEndElement, (writer));
+ }
+ XML_CHECK (xmlTextWriterEndElement, (writer));
+ return 0;
+}
+
+static int
value_string (hive_h *h, void *writer_v, hive_node_h node, hive_value_h value,
hive_type t, size_t len, const char *key, const char *str)
{
xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v;
const char *type;
+ int ret = 0;
switch (t) {
case hive_t_string: type = "string"; break;
@@ -278,9 +348,12 @@ value_string (hive_h *h, void *writer_v, hive_node_h node, hive_value_h value,
}
start_value (writer, key, type, NULL);
- XML_CHECK (xmlTextWriterWriteString, (writer, BAD_CAST str));
+ XML_CHECK (xmlTextWriterStartAttribute, (writer, BAD_CAST "value"));
+ XML_CHECK (xmlTextWriterWriteString, (writer, str));
+ XML_CHECK (xmlTextWriterEndAttribute, (writer));
+ ret = value_byte_runs (h, writer_v, value);
end_value (writer);
- return 0;
+ return ret;
}
static int
@@ -289,6 +362,7 @@ value_multiple_strings (hive_h *h, void *writer_v, hive_node_h node,
const char *key, char **argv)
{
xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v;
+ int ret = 0;
start_value (writer, key, "string-list", NULL);
size_t i;
@@ -298,8 +372,9 @@ value_multiple_strings (hive_h *h, void *writer_v, hive_node_h node,
XML_CHECK (xmlTextWriterEndElement, (writer));
}
+ ret = value_byte_runs (h, writer_v, value);
end_value (writer);
- return 0;
+ return ret;
}
static int
@@ -310,6 +385,7 @@ value_string_invalid_utf16 (hive_h *h, void *writer_v, hive_node_h node,
{
xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v;
const char *type;
+ int ret = 0;
switch (t) {
case hive_t_string: type = "bad-string"; break;
@@ -332,10 +408,13 @@ value_string_invalid_utf16 (hive_h *h, void *writer_v, hive_node_h node,
}
start_value (writer, key, type, "base64");
+ XML_CHECK (xmlTextWriterStartAttribute, (writer, BAD_CAST "value"));
XML_CHECK (xmlTextWriterWriteBase64, (writer, str, 0, len));
+ XML_CHECK (xmlTextWriterEndAttribute, (writer));
+ ret = value_byte_runs (h, writer_v, value);
end_value (writer);
- return 0;
+ return ret;
}
static int
@@ -343,10 +422,12 @@ value_dword (hive_h *h, void *writer_v, hive_node_h node, hive_value_h value,
hive_type t, size_t len, const char *key, int32_t v)
{
xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v;
+ int ret = 0;
start_value (writer, key, "int32", NULL);
- XML_CHECK (xmlTextWriterWriteFormatString, (writer, "%" PRIi32, v));
+ XML_CHECK (xmlTextWriterWriteFormatAttribute, (writer, BAD_CAST "value", "%" PRIi32, v));
+ ret = value_byte_runs (h, writer_v, value);
end_value (writer);
- return 0;
+ return ret;
}
static int
@@ -354,10 +435,12 @@ value_qword (hive_h *h, void *writer_v, hive_node_h node, hive_value_h value,
hive_type t, size_t len, const char *key, int64_t v)
{
xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v;
+ int ret = 0;
start_value (writer, key, "int64", NULL);
- XML_CHECK (xmlTextWriterWriteFormatString, (writer, "%" PRIi64, v));
+ XML_CHECK (xmlTextWriterWriteFormatAttribute, (writer, "value", "%" PRIi64, v));
+ ret = value_byte_runs (h, writer_v, value);
end_value (writer);
- return 0;
+ return ret;
}
static int
@@ -365,10 +448,14 @@ value_binary (hive_h *h, void *writer_v, hive_node_h node, hive_value_h value,
hive_type t, size_t len, const char *key, const char *v)
{
xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v;
+ int ret = 0;
start_value (writer, key, "binary", "base64");
+ XML_CHECK (xmlTextWriterStartAttribute, (writer, BAD_CAST "value"));
XML_CHECK (xmlTextWriterWriteBase64, (writer, v, 0, len));
+ XML_CHECK (xmlTextWriterEndAttribute, (writer));
+ ret = value_byte_runs (h, writer_v, value);
end_value (writer);
- return 0;
+ return ret;
}
static int
@@ -376,10 +463,16 @@ value_none (hive_h *h, void *writer_v, hive_node_h node, hive_value_h value,
hive_type t, size_t len, const char *key, const char *v)
{
xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v;
+ int ret = 0;
start_value (writer, key, "none", "base64");
- if (len > 0) XML_CHECK (xmlTextWriterWriteBase64, (writer, v, 0, len));
+ if (len > 0) {
+ XML_CHECK (xmlTextWriterStartAttribute, (writer, BAD_CAST "value"));
+ XML_CHECK (xmlTextWriterWriteBase64, (writer, v, 0, len));
+ XML_CHECK (xmlTextWriterEndAttribute, (writer));
+ ret = value_byte_runs (h, writer_v, value);
+ }
end_value (writer);
- return 0;
+ return ret;
}
static int
@@ -388,6 +481,7 @@ value_other (hive_h *h, void *writer_v, hive_node_h node, hive_value_h value,
{
xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v;
const char *type;
+ int ret = 0;
switch (t) {
case hive_t_none:
@@ -410,8 +504,13 @@ value_other (hive_h *h, void *writer_v, hive_node_h node, hive_value_h value,
}
start_value (writer, key, type, "base64");
- if (len > 0) XML_CHECK (xmlTextWriterWriteBase64, (writer, v, 0, len));
+ if (len > 0) {
+ XML_CHECK (xmlTextWriterStartAttribute, (writer, BAD_CAST "value"));
+ XML_CHECK (xmlTextWriterWriteBase64, (writer, v, 0, len));
+ XML_CHECK (xmlTextWriterEndAttribute, (writer));
+ ret = value_byte_runs (h, writer_v, value);
+ }
end_value (writer);
- return 0;
+ return ret;
}
--
1.7.6
13 years, 3 months
Re: [Libguestfs] Some more Virt-P2V CD results
by Richard W.M. Jones
On Wed, Aug 31, 2011 at 12:56:50PM -0500, Greg Scott wrote:
> OK, thanks. I just did a yum install virt-v2v on a Fedora 14 VM - but
> the man pages don't have anything about how to do physical machines. I
> already have a p2v CD built with virt-p2v-image-builder a while ago. I
> boot my source server from that CD - what do I do on the Fedora 14
> conversion VM? How do I tell it to get its input from a physical server
> instead of another VM?
Let's keep this on the upstream mailing list so that
discussion benefits everyone.
I'm not sure how compatible the protocol was between an old version of
the ISO and current versions. Matt will know in detail.
However I just pushed virt-p2v-image-builder to F14 quite recently.
The version in *F16* is known to be broken, but the version in F14 is
worth trying ...
https://rwmj.wordpress.com/2011/08/30/virt-p2v-virt-v2v-in-fedora-14/
Rich.
--
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
virt-top is 'top' for virtual machines. Tiny program with many
powerful monitoring features, net stats, disk stats, logging, etc.
http://et.redhat.com/~rjones/virt-top
13 years, 4 months
Trying to use virt-p2v
by Greg Scott
I should post this here -
I am trying to do a P2V migration for a Windows server and I want to use
virt-p2v and virt-v2v. But I obviously don't know what I'm doing. The
goal is to have this physical Windows server come alive as a RHEL
libvirt guest virtual machine.
I built a Virt-p2v-image-builder CD and successfully booted a source
Windows server from the CD. It prompts me for a conversion server, as
expected.
Now my struggle - what do I do on the conversion server? This is the
RHEL 6.1 host where the virtual machines will live. I've been
experimenting with virt-v2v commands but now I am out of ideas. Below
is the latest challenge - I'm sure I'm doing something wrong.
> [root@megahost gregs]# sh -v EOCHSP2V.sh
> date
> Wed Aug 31 11:53:39 CDT 2011
> virt-v2v -ic ssh://10.10.10.127/?no_verify=1 -o libvirt -os
EOCHSVMStorage --bridge br0 10.10.10.127
> virt-v2v: Failed to connect to ssh://10.10.10.127/?no_verify=1:
libvirt error code: 38, message: Cannot access CA certificate
'/etc/pki/CA/cacert.pem': No such file or directory
> date
> Wed Aug 31 11:53:40 CDT 2011
What's up with that? A certificate error???
With virt-v2v, I tell it the host and guest virtual machine to migrate.
But what if I am migrating a physical machine booted from that CD? So
any guidance or documentation would be greatly appreciated.
Thanks
- Greg Scott
13 years, 4 months
[hivex] OCaml binding error?
by Alex Nelson
Hello all,
I am in the process of adding a new return type for the hivex ABI, and I found what I think is an error. I'm not sure, because I don't understand the OCaml binding data structures. Can somebody inform me if the patch below actually corrects a problem?
--Alex
---
generator/generator.ml | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/generator/generator.ml b/generator/generator.ml
index de103ed..c98e625 100755
--- a/generator/generator.ml
+++ b/generator/generator.ml
@@ -1946,7 +1946,7 @@ copy_type_len (size_t len, hive_type t)
v = Val_hive_type (t);
Store_field (rv, 0, v);
v = Val_int (len);
- Store_field (rv, 1, len);
+ Store_field (rv, 1, v);
CAMLreturn (rv);
}
--
1.7.4.4
13 years, 4 months
[PATCH 0/3] ruby: Fix event handler failure
by Richard W.M. Jones
I won't pretend I really understand what's going on here. I've CC'd
this message to Chris since he might have a better idea.
https://bugzilla.redhat.com/show_bug.cgi?id=733297
In this bug, it appears that the event log callback goes out of scope
and is garbage collected. (This is despite the fact we registered it
as a global root). When we invoke the callback later, rb_funcall
raises this exception:
wrong argument type Proc (expected Data)
I checked the type of the callback, and indeed it changes from T_DATA
(normal) to T_NONE (raises this exception).
My workaround simply checks that the type != T_NONE before calling.
Rich.
13 years, 4 months
[PATCH] Correctly build febootstrap on systems without native OCaml compiler
by Hilko Bengen
On those systems "$(OCAMLFIND) $(OCAMLBEST)" was resolved as
"ocamlfind byte" which did not work.
---
Makefile.am | 16 ++++++++--------
1 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 109d2c8..4dc6f12 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -56,18 +56,18 @@ SOURCES_ML = $(filter %.ml,$(SOURCES))
BOBJECTS = $(SOURCES_ML:.ml=.cmo)
XOBJECTS = $(SOURCES_ML:.ml=.cmx)
-if !HAVE_OCAMLOPT
-OBJECTS = $(BOBJECTS)
-else
-OBJECTS = $(XOBJECTS)
-endif
-
OCAMLPACKAGES = -package unix,str
OCAMLFLAGS = -warn-error CDEFLMPSUVXYZ
-febootstrap: $(OBJECTS)
- $(OCAMLFIND) $(OCAMLBEST) $(OCAMLFLAGS) $(OCAMLPACKAGES) -linkpkg \
+if !HAVE_OCAMLOPT
+febootstrap: $(BOBJECTS)
+ $(OCAMLFIND) ocamlc $(OCAMLFLAGS) $(OCAMLPACKAGES) -linkpkg \
+ $^ -o $@
+else
+febootstrap: $(XOBJECTS)
+ $(OCAMLFIND) ocamlopt $(OCAMLFLAGS) $(OCAMLPACKAGES) -linkpkg \
$^ -o $@
+endif
.mli.cmi:
$(OCAMLFIND) ocamlc $(OCAMLFLAGS) $(OCAMLPACKAGES) -c $< -o $@
--
1.7.5.4
13 years, 4 months
[PATCH] febootstrap-supermin-helper: Replace objcopy call for embedding init binary
by Hilko Bengen
objcopy needs "output-target" and "binary-architecture" parameters
which makes it necessary to keep a list of known architectures.
The bin2s.pl script generates input for the GNU assembler which should
produce an object file that is equivalent to that produced by objcopy.
I have successfully tested the change on an amd64 Debian/unstable system.
---
helper/Makefile.am | 10 ++++++++--
helper/bin2s.pl | 45 +++++++++++++++++++++++++++++++++++++++++++++
helper/elf-default-arch | 32 --------------------------------
3 files changed, 53 insertions(+), 34 deletions(-)
create mode 100755 helper/bin2s.pl
delete mode 100755 helper/elf-default-arch
diff --git a/helper/Makefile.am b/helper/Makefile.am
index 01a6af1..ab7f692 100644
--- a/helper/Makefile.am
+++ b/helper/Makefile.am
@@ -45,11 +45,17 @@ init_LDFLAGS = -static
# http://www.doof.me.uk/2010/05/07/cute-objcopy-hack/
ELF_DEFAULT_ARCH = $(shell $(srcdir)/elf-default-arch | gawk '{ print $$1 }')
DEFAULT_ARCH = $(shell $(srcdir)/elf-default-arch | gawk '{ print $$2 }')
-ext2init.o: init
+
+CLEANFILES = ext2init.S
+
+ext2init.o: ext2init.S
+ $(CC) -o $@ -c $<
+
+ext2init.S: init
strip --strip-all $<
@file $< | grep -isq static || \
(echo "*** error: init is not staticly linked"; exit 1)
- objcopy -I binary -B $(DEFAULT_ARCH) -O $(ELF_DEFAULT_ARCH) $< $@
+ ./bin2s.pl $< $@
man_MANS = \
febootstrap-supermin-helper.8
diff --git a/helper/bin2s.pl b/helper/bin2s.pl
new file mode 100755
index 0000000..2c78b5e
--- /dev/null
+++ b/helper/bin2s.pl
@@ -0,0 +1,45 @@
+#!/usr/bin/perl
+
+# This script creates a source file for the GNU assembler which shuold
+# result in an object file equivalent to that of
+#
+# objcopy -I binary -B $(DEFAULT_ARCH) -O $(ELF_DEFAULT_ARCH) <in> <out>
+
+use strict;
+use warnings;
+
+die "usage: $0 <in> <out>\n" if @ARGV != 2;
+
+my ($infile, $outfile) = @ARGV;
+my ($buf, $i, $sz);
+open my $ifh, '<', $infile or die "open $infile: $!";
+open my $ofh, '>', $outfile or die "open $outfile: $!";
+
+print $ofh <<"EOF";
+/* This file has been automatically generated from $infile by $0 */
+
+\t.globl\t_binary_${infile}_start
+\t.globl\t_binary_${infile}_end
+\t.globl\t_binary_${infile}_size
+
+\t.section\t.data
+_binary_${infile}_start:
+EOF
+
+$sz = 0;
+while ( $i = read $ifh, $buf, 12 ) {
+ print $ofh "\t.byte\t"
+ . join( ',', map { sprintf '0x%02x', ord $_ } split //, $buf ) . "\n";
+ $sz += $i;
+}
+die "read $infile (at offset $sz): $!\n" if not defined $i;
+close $ifh;
+
+print $ofh <<"EOF";
+
+_binary_${infile}_end:
+
+\t.equ _binary_${infile}_size, $sz
+EOF
+
+close $ofh;
diff --git a/helper/elf-default-arch b/helper/elf-default-arch
deleted file mode 100755
index 54af14d..0000000
--- a/helper/elf-default-arch
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/bin/sh -
-# Copyright (C) 2010 Red Hat Inc.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-# Calculate the default ELF object architecture for this format.
-# There doesn't seem to be an easy way to derive this from binutils,
-# so instead we hard code it.
-
-case $(uname -m) in
- i[3456]86) echo "elf32-i386 i386" ;;
- x86_64) echo "elf64-x86-64 i386" ;;
- s390) echo "elf32-s390 s390:31-bit" ;;
- s390x) echo "elf64-s390 s390:31-bit" ;;
- ppc) echo "elf32-powerpc powerpc" ;;
- ppc64) echo "elf64-powerpc powerpc" ;;
- *)
- echo "This architecture is not recognized. Please update helper/elf-default-arch."
- exit 1
-esac
--
1.7.5.4
13 years, 4 months
[PATCH] hivex: Newer Python versions want parentheses around arguments of "print"
by Hilko Bengen
---
configure.ac | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/configure.ac b/configure.ac
index 261c44c..6c019e4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -237,8 +237,8 @@ PYTHON_PREFIX=
PYTHON_VERSION=
if test "x$PYTHON" != "xno"; then
- PYTHON_PREFIX=`$PYTHON -c "import sys; print sys.prefix"`
- PYTHON_VERSION=`$PYTHON -c "import sys; print sys.version[[0:3]]"`
+ PYTHON_PREFIX=`$PYTHON -c "import sys; print(sys.prefix)"`
+ PYTHON_VERSION=`$PYTHON -c "import sys; print(sys.version[[0:3]])"`
AC_MSG_CHECKING([for Python include path])
if test -z "$PYTHON_INCLUDEDIR"; then
--
1.7.5.4
13 years, 4 months
[PATCH 1/2] python: Don't build static library
by Hilko Bengen
---
python/Makefile.am | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/python/Makefile.am b/python/Makefile.am
index 5884762..82960d6 100644
--- a/python/Makefile.am
+++ b/python/Makefile.am
@@ -43,7 +43,7 @@ libguestfsmod_la_SOURCES = guestfs-py.c guestfs-py.h guestfs-py-byhand.c
libguestfsmod_la_CFLAGS = -Wall -I$(PYTHON_INCLUDEDIR) \
-I$(top_srcdir)/src -I$(top_builddir)/src
libguestfsmod_la_LIBADD = $(top_builddir)/src/libguestfs.la
-libguestfsmod_la_LDFLAGS = -avoid-version
+libguestfsmod_la_LDFLAGS = -avoid-version -shared
TESTS_ENVIRONMENT = \
LIBGUESTFS_PATH=$(top_builddir)/appliance \
--
1.7.5.4
13 years, 4 months