From: Richard W.M. Jones Date: Sun, 28 Nov 2010 11:14:11 +0000 (+0000) Subject: Python bindings. X-Git-Tag: 1.2.4~1 X-Git-Url: http://git.annexia.org/?a=commitdiff_plain;h=5094414d86f574a0dd061565bfad6526a9e0ea97;p=hivex.git Python bindings. --- diff --git a/Makefile.am b/Makefile.am index b8b980f..43b4fbc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 diff --git a/configure.ac b/configure.ac index 05c4c13..a09be07 100644 --- a/configure.ac +++ b/configure.ac @@ -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 ....................... " diff --git a/generator/generator.ml b/generator/generator.ml index 5bd46ee..37e5b5c 100755 --- a/generator/generator.ml +++ b/generator/generator.ml @@ -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 + +#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 +#include +#include + +#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. diff --git a/po/POTFILES.in b/po/POTFILES.in index 6ad1bcb..92b36f0 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -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 index 0000000..9979914 --- /dev/null +++ b/python/t/010-import.py @@ -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 index 0000000..57339a7 --- /dev/null +++ b/python/t/020-open.py @@ -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 index 0000000..876836d --- /dev/null +++ b/python/t/021-close.py @@ -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 index 0000000..0692f11 --- /dev/null +++ b/python/t/200-write.py @@ -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 index 0000000..1cb8c52 --- /dev/null +++ b/python/t/210-setvalue.py @@ -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"