Python bindings.
authorRichard W.M. Jones <rjones@redhat.com>
Sun, 28 Nov 2010 11:14:11 +0000 (11:14 +0000)
committerRichard W.M. Jones <rjones@redhat.com>
Sun, 28 Nov 2010 16:11:14 +0000 (16:11 +0000)
Makefile.am
configure.ac
generator/generator.ml
po/POTFILES.in
python/t/010-import.py [new file with mode: 0644]
python/t/020-open.py [new file with mode: 0644]
python/t/021-close.py [new file with mode: 0644]
python/t/200-write.py [new file with mode: 0644]
python/t/210-setvalue.py [new file with mode: 0644]

index b8b980f..43b4fbc 100644 (file)
@@ -27,10 +27,9 @@ if HAVE_PERL
 SUBDIRS += perl regedit
 endif
 
-# Not yet written.
-#if HAVE_PYTHON
-#SUBDIRS += python
-#endif
+if HAVE_PYTHON
+SUBDIRS += python
+endif
 
 EXTRA_DIST = hivex.pc hivex.pc.in README LICENSE
 
index 05c4c13..a09be07 100644 (file)
@@ -227,54 +227,66 @@ fi
 AM_CONDITIONAL([HAVE_PERL],
     [test "x$PERL" != "xno" -a "x$missing_perl_modules" != "xyes"])
 
-dnl dnl Check for Python (optional, for Python bindings).
-dnl AC_CHECK_PROG([PYTHON],[python],[python],[no])
-
-dnl PYTHON_PREFIX=
-dnl PYTHON_VERSION=
-dnl PYTHON_INCLUDEDIR=
-dnl PYTHON_SITE_PACKAGES=
-
-dnl if test "x$PYTHON" != "xno"; then
-dnl     PYTHON_PREFIX=`$PYTHON -c "import sys; print sys.prefix"`
-dnl     PYTHON_VERSION=`$PYTHON -c "import sys; print sys.version[[0:3]]"`
-dnl     for d in \
-dnl         $PYTHON_PREFIX/include/python$PYTHON_VERSION \
-dnl         /usr/include/python$PYTHON_VERSION \
-dnl         /usr/local/include/python$PYTHON_VERSION
-dnl     do
-dnl         AC_MSG_CHECKING([Python.h in $d])
-dnl         if test -r "$d/Python.h"; then
-dnl             AC_MSG_RESULT([found])
-dnl             PYTHON_INCLUDEDIR=$d
-dnl             break
-dnl         fi
-dnl         AC_MSG_RESULT([not found])
-dnl     done
-dnl     for d in \
-dnl         $PYTHON_PREFIX/lib64/python$PYTHON_VERSION/site-packages \
-dnl         $PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages \
-dnl         /usr/lib64/python$PYTHON_VERSION/site-packages \
-dnl         /usr/lib/python$PYTHON_VERSION/site-packages \
-dnl         /usr/local/lib/python$PYTHON_VERSION/site-packages
-dnl     do
-dnl         AC_MSG_CHECKING([for $d])
-dnl         if test -d "$d"; then
-dnl             AC_MSG_RESULT([found])
-dnl             PYTHON_SITE_PACKAGES=$d
-dnl             break
-dnl         fi
-dnl         AC_MSG_RESULT([not found])
-dnl     done
-dnl fi
+dnl Check for Python (optional, for Python bindings).
+AC_CHECK_PROG([PYTHON],[python],[python],[no])
+
+PYTHON_PREFIX=
+PYTHON_VERSION=
+PYTHON_INCLUDEDIR=
+PYTHON_SITE_PACKAGES=
+
+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]]"`
+    for d in \
+        $PYTHON_PREFIX/include/python$PYTHON_VERSION \
+        /usr/include/python$PYTHON_VERSION \
+        /usr/local/include/python$PYTHON_VERSION
+    do
+        AC_MSG_CHECKING([Python.h in $d])
+        if test -r "$d/Python.h"; then
+            AC_MSG_RESULT([found])
+            PYTHON_INCLUDEDIR=$d
+            break
+        fi
+        AC_MSG_RESULT([not found])
+    done
+    if test "x$PYTHON_INCLUDEDIR" = "x"; then
+        AC_MSG_WARN([Python include directory not found])
+    fi
+
+    for d in \
+        $PYTHON_PREFIX/lib64/python$PYTHON_VERSION/site-packages \
+        $PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages \
+        /usr/lib64/python$PYTHON_VERSION/site-packages \
+        /usr/lib/python$PYTHON_VERSION/site-packages \
+        /usr/local/lib/python$PYTHON_VERSION/site-packages
+    do
+        AC_MSG_CHECKING([for $d])
+        if test -d "$d"; then
+            AC_MSG_RESULT([found])
+            PYTHON_SITE_PACKAGES=$d
+            break
+        fi
+        AC_MSG_RESULT([not found])
+    done
+    if test "x$PYTHON_SITE_PACKAGES" = "x"; then
+        AC_MSG_WARN([Python site-packages directory not found])
+    fi
+
+    old_LIBS="$LIBS"
+    LIBS="$LIBS -lpython$PYTHON_VERSION"
+    AC_CHECK_FUNCS([PyCapsule_New])
+    LIBS="$old_LIBS"
+fi
 
-dnl AC_SUBST(PYTHON_PREFIX)
-dnl AC_SUBST(PYTHON_VERSION)
-dnl AC_SUBST(PYTHON_INCLUDEDIR)
-dnl AC_SUBST(PYTHON_SITE_PACKAGES)
+AC_SUBST(PYTHON_PREFIX)
+AC_SUBST(PYTHON_VERSION)
+AC_SUBST(PYTHON_INCLUDEDIR)
+AC_SUBST(PYTHON_SITE_PACKAGES)
 
-dnl AM_CONDITIONAL([HAVE_PYTHON],
-dnl     [test "x$PYTHON_INCLUDEDIR" != "x" -a "x$PYTHON_SITE_PACKAGES" != "x"])
+AM_CONDITIONAL([HAVE_PYTHON],
+    [test "x$PYTHON_INCLUDEDIR" != "x" -a "x$PYTHON_SITE_PACKAGES" != "x"])
 
 dnl dnl Check for Ruby and rake (optional, for Ruby bindings).
 dnl AC_CHECK_LIB([ruby],[ruby_init],[HAVE_LIBRUBY=1],[HAVE_LIBRUBY=0])
@@ -440,6 +452,7 @@ AC_CONFIG_FILES([Makefile
                  lib/tools/Makefile
                  ocaml/Makefile ocaml/META
                  perl/Makefile perl/Makefile.PL
+                 python/Makefile
                  po/Makefile.in
                  regedit/Makefile
                  sh/Makefile
@@ -458,8 +471,8 @@ echo -n "OCaml bindings ...................... "
 if test "x$HAVE_OCAML_TRUE" = "x"; then echo "yes"; else echo "no"; fi
 echo -n "Perl bindings ....................... "
 if test "x$HAVE_PERL_TRUE" = "x"; then echo "yes"; else echo "no"; fi
-dnl echo -n "Python bindings ..................... "
-dnl if test "x$HAVE_PYTHON_TRUE" = "x"; then echo "yes"; else echo "no"; fi
+echo -n "Python bindings ..................... "
+if test "x$HAVE_PYTHON_TRUE" = "x"; then echo "yes"; else echo "no"; fi
 dnl echo -n "Ruby bindings ....................... "
 dnl if test "x$HAVE_RUBY_TRUE" = "x"; then echo "yes"; else echo "no"; fi
 dnl echo -n "Java bindings ....................... "
index 5bd46ee..37e5b5c 100755 (executable)
@@ -36,8 +36,6 @@
 
 #load "unix.cma";;
 #load "str.cma";;
-#directory "+xml-light";;
-#load "xml-light.cma";;
 
 open Unix
 open Printf
@@ -2575,11 +2573,510 @@ DESTROY (h)
       )
   ) functions
 
+and generate_python_c () =
+  generate_header CStyle LGPLv2plus;
+
+  pr "\
+#define PY_SSIZE_T_CLEAN 1
+#include <Python.h>
+
+#if PY_VERSION_HEX < 0x02050000
+typedef int Py_ssize_t;
+#define PY_SSIZE_T_MAX INT_MAX
+#define PY_SSIZE_T_MIN INT_MIN
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include \"hivex.h\"
+
+#ifndef HAVE_PYCAPSULE_NEW
+typedef struct {
+  PyObject_HEAD
+  hive_h *h;
+} Pyhivex_Object;
+#endif
+
+static hive_h *
+get_handle (PyObject *obj)
+{
+  assert (obj);
+  assert (obj != Py_None);
+#ifndef HAVE_PYCAPSULE_NEW
+  return ((Pyhivex_Object *) obj)->h;
+#else
+  return (hive_h *) PyCapsule_GetPointer(obj, \"hive_h\");
+#endif
+}
+
+static PyObject *
+put_handle (hive_h *h)
+{
+  assert (h);
+#ifndef HAVE_PYCAPSULE_NEW
+  return
+    PyCObject_FromVoidPtrAndDesc ((void *) h, (char *) \"hive_h\", NULL);
+#else
+  return PyCapsule_New ((void *) h, \"hive_h\", NULL);
+#endif
+}
+
+/* This returns pointers into the Python objects, which should
+ * not be freed.
+ */
+static int
+get_value (PyObject *v, hive_set_value *ret)
+{
+  PyObject *obj;
+
+  obj = PyDict_GetItemString (v, \"key\");
+  if (!obj) {
+    PyErr_SetString (PyExc_RuntimeError, \"no 'key' element in dictionary\");
+    return -1;
+  }
+  if (!PyString_Check (obj)) {
+    PyErr_SetString (PyExc_RuntimeError, \"'key' element is not a string\");
+    return -1;
+  }
+  ret->key = PyString_AsString (obj);
+
+  obj = PyDict_GetItemString (v, \"t\");
+  if (!obj) {
+    PyErr_SetString (PyExc_RuntimeError, \"no 't' element in dictionary\");
+    return -1;
+  }
+  if (!PyInt_Check (obj)) {
+    PyErr_SetString (PyExc_RuntimeError, \"'t' element is not an integer\");
+    return -1;
+  }
+  ret->t = PyInt_AsLong (obj);
+
+  obj = PyDict_GetItemString (v, \"value\");
+  if (!obj) {
+    PyErr_SetString (PyExc_RuntimeError, \"no 'value' element in dictionary\");
+    return -1;
+  }
+  if (!PyString_Check (obj)) {
+    PyErr_SetString (PyExc_RuntimeError, \"'value' element is not a string\");
+    return -1;
+  }
+  ret->value = PyString_AsString (obj);
+  ret->len = PyString_Size (obj);
+
+  return 0;
+}
+
+typedef struct py_set_values {
+  size_t nr_values;
+  hive_set_value *values;
+} py_set_values;
+
+static int
+get_values (PyObject *v, py_set_values *ret)
+{
+  Py_ssize_t slen;
+  size_t len, i;
+
+  if (!PyList_Check (v)) {
+    PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
+    return -1;
+  }
+
+  slen = PyList_Size (v);
+  if (slen < 0) {
+    PyErr_SetString (PyExc_RuntimeError, \"get_string_list: PyList_Size failure\");
+    return -1;
+  }
+  len = (size_t) slen;
+  ret->nr_values = len;
+  ret->values = malloc (len * sizeof (hive_set_value));
+  if (!ret->values) {
+    PyErr_SetString (PyExc_RuntimeError, strerror (errno));
+    return -1;
+  }
+
+  for (i = 0; i < len; ++i) {
+    if (get_value (PyList_GetItem (v, i), &(ret->values[i])) == -1) {
+      free (ret->values);
+      return -1;
+    }
+  }
+
+  return 0;
+}
+
+static PyObject *
+put_string_list (char * const * const argv)
+{
+  PyObject *list;
+  size_t argc, i;
+
+  for (argc = 0; argv[argc] != NULL; ++argc)
+    ;
+
+  list = PyList_New (argc);
+  for (i = 0; i < argc; ++i)
+    PyList_SetItem (list, i, PyString_FromString (argv[i]));
+
+  return list;
+}
+
+static void
+free_strings (char **argv)
+{
+  size_t argc;
+
+  for (argc = 0; argv[argc] != NULL; ++argc)
+    free (argv[argc]);
+  free (argv);
+}
+
+/* Since hive_node_t is the same as hive_value_t this also works for values. */
+static PyObject *
+put_node_list (hive_node_h *nodes)
+{
+  PyObject *list;
+  size_t argc, i;
+
+  for (argc = 0; nodes[argc] != 0; ++argc)
+    ;
+
+  list = PyList_New (argc);
+  for (i = 0; i < argc; ++i)
+    PyList_SetItem (list, i, PyLong_FromLongLong ((long) nodes[i]));
+
+  return list;
+}
+
+static PyObject *
+put_len_type (size_t len, hive_type t)
+{
+  PyObject *r = PyTuple_New (2);
+  PyTuple_SetItem (r, 0, PyInt_FromLong ((long) t));
+  PyTuple_SetItem (r, 1, PyLong_FromLongLong ((long) len));
+  return r;
+}
+
+static PyObject *
+put_val_type (char *val, size_t len, hive_type t)
+{
+  PyObject *r = PyTuple_New (2);
+  PyTuple_SetItem (r, 0, PyInt_FromLong ((long) t));
+  PyTuple_SetItem (r, 1, PyString_FromStringAndSize (val, len));
+  return r;
+}
+
+";
+
+  (* Generate functions. *)
+  List.iter (
+    fun (name, style, _, longdesc) ->
+      pr "static PyObject *\n";
+      pr "py_hivex_%s (PyObject *self, PyObject *args)\n" name;
+      pr "{\n";
+      pr "  PyObject *py_r;\n";
+
+      let error_code =
+       match fst style with
+        | RErr -> pr "  int r;\n"; "-1"
+       | RErrDispose -> pr "  int r;\n"; "-1"
+       | RHive -> pr "  hive_h *r;\n"; "NULL"
+        | RNode -> pr "  hive_node_h r;\n"; "0"
+        | RNodeNotFound ->
+            pr "  errno = 0;\n";
+            pr "  hive_node_h r;\n";
+            "0 && errno != 0"
+        | RNodeList -> pr "  hive_node_h *r;\n"; "NULL"
+        | RValue -> pr "  hive_value_h r;\n"; "0"
+        | RValueList -> pr "  hive_value_h *r;\n"; "NULL"
+        | RString -> pr "  char *r;\n"; "NULL"
+        | RStringList -> pr "  char **r;\n"; "NULL"
+        | RLenType ->
+            pr "  int r;\n";
+            pr "  size_t len;\n";
+            pr "  hive_type t;\n";
+            "-1"
+        | RLenTypeVal ->
+            pr "  char *r;\n";
+            pr "  size_t len;\n";
+            pr "  hive_type t;\n";
+            "NULL"
+        | RInt32 ->
+            pr "  errno = 0;\n";
+            pr "  int32_t r;\n";
+            "-1 && errno != 0"
+        | RInt64 ->
+            pr "  errno = 0;\n";
+            pr "  int64_t r;\n";
+            "-1 && errno != 0" in
+
+      (* Call and arguments. *)
+      let c_params =
+       List.map (function
+                 | AUnusedFlags -> "0"
+                 | ASetValues -> "values.nr_values, values.values"
+                  | ASetValue -> "&val"
+                 | arg -> name_of_argt arg) (snd style) in
+      let c_params =
+        match fst style with
+        | RLenType | RLenTypeVal -> c_params @ ["&t"; "&len"]
+        | _ -> c_params in
+
+      List.iter (
+        function
+        | AHive ->
+           pr "  hive_h *h;\n";
+            pr "  PyObject *py_h;\n"
+       | ANode n
+       | AValue n ->
+           pr "  long %s;\n" n
+       | AString n
+        | AStringNullable n ->
+           pr "  char *%s;\n" n
+       | AOpenFlags ->
+           pr "  int flags;\n"
+       | AUnusedFlags -> ()
+       | ASetValues ->
+           pr "  py_set_values values;\n";
+           pr "  PyObject *py_values;\n"
+       | ASetValue ->
+           pr "  hive_set_value val;\n";
+           pr "  PyObject *py_val;\n"
+      ) (snd style);
+
+      pr "\n";
+
+      (* Convert the required parameters. *)
+      pr "  if (!PyArg_ParseTuple (args, (char *) \"";
+      List.iter (
+        function
+        | AHive ->
+           pr "O"
+       | ANode n
+       | AValue n ->
+           pr "L"
+       | AString n ->
+           pr "s"
+        | AStringNullable n ->
+           pr "z"
+       | AOpenFlags ->
+           pr "i"
+       | AUnusedFlags -> ()
+       | ASetValues
+       | ASetValue ->
+            pr "O"
+      ) (snd style);
+
+      pr ":hivex_%s\"" name;
+
+      List.iter (
+        function
+        | AHive ->
+           pr ", &py_h"
+       | ANode n
+       | AValue n ->
+           pr ", &%s" n
+       | AString n
+        | AStringNullable n ->
+           pr ", &%s" n
+       | AOpenFlags ->
+           pr ", &flags"
+       | AUnusedFlags -> ()
+       | ASetValues ->
+            pr ", &py_values"
+       | ASetValue ->
+            pr ", &py_val"
+        ) (snd style);
+
+      pr "))\n";
+      pr "    return NULL;\n";
+
+      (* Convert some Python argument types to C. *)
+      List.iter (
+        function
+        | AHive ->
+            pr "  h = get_handle (py_h);\n"
+       | ANode _
+       | AValue _
+       | AString _
+        | AStringNullable _
+       | AOpenFlags
+       | AUnusedFlags -> ()
+       | ASetValues ->
+            pr "  if (get_values (py_values, &values) == -1)\n";
+            pr "    return NULL;\n"
+       | ASetValue ->
+            pr "  if (get_value (py_val, &val) == -1)\n";
+            pr "    return NULL;\n"
+      ) (snd style);
+
+      (* Call the C function. *)
+      pr "  r = hivex_%s (%s);\n" name (String.concat ", " c_params);
+
+      (* Free up arguments. *)
+      List.iter (
+        function
+       | AHive | ANode _ | AValue _
+        | AString _ | AStringNullable _
+       | AOpenFlags | AUnusedFlags -> ()
+       | ASetValues ->
+           pr "  free (values.values);\n"
+       | ASetValue -> ()
+      ) (snd style);
+
+      (* Check for errors from C library. *)
+      pr "  if (r == %s) {\n" error_code;
+      pr "    PyErr_SetString (PyExc_RuntimeError,\n";
+      pr "                     strerror (errno));\n";
+      pr "    return NULL;\n";
+      pr "  }\n";
+      pr "\n";
+
+      (* Convert return value to Python. *)
+      (match fst style with
+       | RErr
+       | RErrDispose ->
+           pr "  Py_INCREF (Py_None);\n";
+           pr "  py_r = Py_None;\n"
+       | RHive ->
+           pr "  py_r = put_handle (r);\n"
+       | RNode ->
+           pr "  py_r = PyLong_FromLongLong (r);\n"
+       | RNodeNotFound ->
+           pr "  if (r)\n";
+           pr "    py_r = PyLong_FromLongLong (r);\n";
+           pr "  else {\n";
+           pr "    Py_INCREF (Py_None);\n";
+           pr "    py_r = Py_None;\n";
+           pr "  }\n";
+       | RNodeList
+       | RValueList ->
+           pr "  py_r = put_node_list (r);\n";
+           pr "  free (r);\n"
+       | RValue ->
+           pr "  py_r = PyLong_FromLongLong (r);\n"
+       | RString ->
+           pr "  py_r = PyString_FromString (r);\n";
+           pr "  free (r);"
+       | RStringList ->
+           pr "  py_r = put_string_list (r);\n";
+           pr "  free_strings (r);\n"
+       | RLenType ->
+           pr "  py_r = put_len_type (len, t);\n"
+       | RLenTypeVal ->
+           pr "  py_r = put_val_type (r, len, t);\n";
+           pr "  free (r);\n"
+       | RInt32 ->
+           pr "  py_r = PyInt_FromLong ((long) r);\n"
+       | RInt64 ->
+           pr "  py_r = PyLong_FromLongLong (r);\n"
+      );
+      pr "  return py_r;\n";
+      pr "}\n";
+      pr "\n"
+  ) functions;
+
+  (* Table of functions. *)
+  pr "static PyMethodDef methods[] = {\n";
+  List.iter (
+    fun (name, _, _, _) ->
+      pr "  { (char *) \"%s\", py_hivex_%s, METH_VARARGS, NULL },\n"
+        name name
+  ) functions;
+  pr "  { NULL, NULL, 0, NULL }\n";
+  pr "};\n";
+  pr "\n";
+
+  (* Init function. *)
+  pr "\
+void
+initlibhivexmod (void)
+{
+  static int initialized = 0;
+
+  if (initialized) return;
+  Py_InitModule ((char *) \"libhivexmod\", methods);
+  initialized = 1;
+}
+"
+  
 and generate_python_py () =
-  generate_header HashStyle LGPLv2plus
+  generate_header HashStyle LGPLv2plus;
 
-and generate_python_c () =
-  generate_header CStyle LGPLv2plus
+  pr "\
+u\"\"\"Python bindings for hivex
+
+import hivex
+h = hivex.Hivex (filename)
+
+The hivex module provides Python bindings to the hivex API for
+examining and modifying Windows Registry 'hive' files.
+
+Read the hivex(3) man page to find out how to use the API.
+\"\"\"
+
+import libhivexmod
+
+class Hivex:
+    \"\"\"Instances of this class are hivex API handles.\"\"\"
+
+    def __init__ (self, filename";
+
+  List.iter (
+    fun (_, flag, _) -> pr ", %s = False" (String.lowercase flag)
+  ) open_flags;
+
+  pr "):
+        \"\"\"Create a new hivex handle.\"\"\"
+        flags = 0
+";
+
+  List.iter (
+    fun (n, flag, description) ->
+      pr "        # %s\n" description;
+      pr "        if %s: flags += %d\n" (String.lowercase flag) n
+  ) open_flags;
+
+  pr "        self._o = libhivexmod.open (filename, flags)
+
+    def __del__ (self):
+        libhivexmod.close (self._o)
+
+";
+
+  List.iter (
+    fun (name, style, shortdesc, _) ->
+      (* The close and open calls are handled specially above. *)
+      if fst style <> RErrDispose && List.hd (snd style) = AHive then (
+        let args = List.tl (snd style) in
+        let args = List.filter (
+          function AOpenFlags | AUnusedFlags -> false
+          | _ -> true
+        ) args in
+
+        pr "    def %s (self" name;
+        List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
+        pr "):\n";
+        pr "        u\"\"\"%s\"\"\"\n" shortdesc;
+        pr "        return libhivexmod.%s (self._o" name;
+        List.iter (
+          fun arg ->
+            pr ", ";
+            match arg with
+           | AHive -> assert false
+            | ANode n | AValue n
+            | AString n | AStringNullable n -> pr "%s" n
+           | AOpenFlags
+            | AUnusedFlags -> assert false
+           | ASetValues -> pr "values"
+           | ASetValue -> pr "val"
+        ) args;
+        pr ")\n";
+        pr "\n"
+      )
+  ) functions
 
 let output_to filename k =
   let filename_new = filename ^ ".new" in
@@ -2645,11 +3142,8 @@ Run it from the top source directory using the command
   output_to "perl/lib/Win/Hivex.pm" generate_perl_pm;
   output_to "perl/Hivex.xs" generate_perl_xs;
 
-(*
-  We ran out of time before we could write the Python bindings.
   output_to "python/hivex.py" generate_python_py;
   output_to "python/hivex-py.c" generate_python_c;
-*)
 
   (* Always generate this file last, and unconditionally.  It's used
    * by the Makefile to know when we must re-run the generator.
index 6ad1bcb..92b36f0 100644 (file)
@@ -4,5 +4,6 @@ ocaml/hivex_c.c
 perl/Hivex.c
 perl/lib/Win/Hivex.pm
 perl/lib/Win/Hivex/Regedit.pm
+python/hivex-py.c
 sh/hivexsh.c
 xml/hivexml.c
diff --git a/python/t/010-import.py b/python/t/010-import.py
new file mode 100644 (file)
index 0000000..9979914
--- /dev/null
@@ -0,0 +1,18 @@
+# hivex Python bindings
+# 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.
+
+import hivex
diff --git a/python/t/020-open.py b/python/t/020-open.py
new file mode 100644 (file)
index 0000000..57339a7
--- /dev/null
@@ -0,0 +1,26 @@
+# hivex Python bindings
+# 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.
+
+import os
+import hivex
+
+srcdir = os.environ["srcdir"]
+if not srcdir:
+    srcdir = "."
+
+h = hivex.Hivex ("%s/../images/minimal" % srcdir)
+assert h
diff --git a/python/t/021-close.py b/python/t/021-close.py
new file mode 100644 (file)
index 0000000..876836d
--- /dev/null
@@ -0,0 +1,28 @@
+# hivex Python bindings
+# 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.
+
+import os
+import hivex
+
+srcdir = os.environ["srcdir"]
+if not srcdir:
+    srcdir = "."
+
+h = hivex.Hivex ("%s/../images/minimal" % srcdir)
+assert h
+
+del h
diff --git a/python/t/200-write.py b/python/t/200-write.py
new file mode 100644 (file)
index 0000000..0692f11
--- /dev/null
@@ -0,0 +1,43 @@
+# hivex Python bindings
+# 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.
+
+import os
+import hivex
+
+srcdir = os.environ["srcdir"]
+if not srcdir:
+    srcdir = "."
+
+h = hivex.Hivex ("%s/../images/minimal" % srcdir,
+                 write = True)
+assert h
+
+root = h.root ()
+assert root
+
+h.node_add_child (root, "A")
+
+h.node_add_child (root, "B")
+
+b = h.node_get_child (root, "B")
+assert b
+
+values = [
+    { "key": "Key1", "t": 3, "value": "ABC" },
+    { "key": "Key2", "t": 3, "value": "DEF" }
+]
+h.node_set_values (b, values)
diff --git a/python/t/210-setvalue.py b/python/t/210-setvalue.py
new file mode 100644 (file)
index 0000000..1cb8c52
--- /dev/null
@@ -0,0 +1,57 @@
+# hivex Python bindings
+# 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.
+
+import os
+import hivex
+
+srcdir = os.environ["srcdir"]
+if not srcdir:
+    srcdir = "."
+
+h = hivex.Hivex ("%s/../images/minimal" % srcdir,
+                 write = True)
+assert h
+
+root = h.root ()
+assert root
+
+h.node_add_child (root, "B")
+
+b = h.node_get_child (root, "B")
+assert b
+
+values = [
+    { "key": "Key1", "t": 3, "value": "ABC" },
+    { "key": "Key2", "t": 3, "value": "DEF" }
+]
+h.node_set_values (b, values)
+
+value1 = { "key": "Key3", "t": 3, "value": "GHI" }
+h.node_set_value (b, value1)
+
+value1 = { "key": "Key1", "t": 3, "value": "JKL" }
+h.node_set_value (b, value1)
+
+val = h.node_get_value (b, "Key1")
+t_data = h.value_value (val)
+assert t_data[0] == 3
+assert t_data[1] == "JKL"
+
+val = h.node_get_value (b, "Key3")
+t_data = h.value_value (val)
+assert t_data[0] == 3
+assert t_data[1] == "GHI"