diff options
author | Richard W.M. Jones <rjones@redhat.com> | 2012-08-28 16:03:50 +0100 |
---|---|---|
committer | Richard W.M. Jones <rjones@redhat.com> | 2012-08-29 17:08:01 +0100 |
commit | 8a723ca62eb4f93f19c5c66beffaf70997afb64c (patch) | |
tree | 4a6768046b45c498506c79dd1fd629f725cc5780 /daemon/hivex.c | |
parent | 228d49bb842cda517b414bbfab460e8be429cc5f (diff) | |
download | libguestfs-8a723ca62eb4f93f19c5c66beffaf70997afb64c.tar.gz libguestfs-8a723ca62eb4f93f19c5c66beffaf70997afb64c.tar.xz libguestfs-8a723ca62eb4f93f19c5c66beffaf70997afb64c.zip |
New APIs: hivex_*
Transscribe many hivex(3) APIs into the libguestfs API.
There is one hive handle per libguestfs handle, as with Augeas.
Note that hivex uses iconv_open for some APIs (eg. hivex_value_string).
But since we delete all the i18n files from the appliance, this
doesn't work -- iconv_open returns EINVAL. Therefore hivex APIs which
require iconv cannot be bound in the daemon.
Diffstat (limited to 'daemon/hivex.c')
-rw-r--r-- | daemon/hivex.c | 509 |
1 files changed, 509 insertions, 0 deletions
diff --git a/daemon/hivex.c b/daemon/hivex.c new file mode 100644 index 00000000..f13d3d7e --- /dev/null +++ b/daemon/hivex.c @@ -0,0 +1,509 @@ +/* libguestfs - the guestfsd daemon + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <limits.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/stat.h> + +#include "guestfs_protocol.h" +#include "daemon.h" +#include "actions.h" +#include "optgroups.h" + +#ifdef HAVE_HIVEX + +#include <hivex.h> + +int +optgroup_hivex_available (void) +{ + return 1; +} + +/* The hivex handle. As with Augeas, there is one per guestfs handle / + * daemon. + */ +static hive_h *h = NULL; + +/* Clean up the hivex handle on daemon exit. */ +static void hivex_finalize (void) __attribute__((destructor)); +static void +hivex_finalize (void) +{ + if (h) { + hivex_close (h); + h = NULL; + } +} + +#define NEED_HANDLE(errcode) \ + do { \ + if (!h) { \ + reply_with_error ("%s: you must call 'hivex-open' first to initialize the hivex handle", __func__); \ + return (errcode); \ + } \ + } \ + while (0) + +/* Takes optional arguments, consult optargs_bitmask. */ +int +do_hivex_open (const char *filename, int verbose, int debug, int write) +{ + char *buf; + int flags = 0; + + if (h) { + hivex_close (h); + h = NULL; + } + + buf = sysroot_path (filename); + if (!buf) { + reply_with_perror ("malloc"); + return -1; + } + + if (optargs_bitmask & GUESTFS_HIVEX_OPEN_VERBOSE_BITMASK) { + if (verbose) + flags |= HIVEX_OPEN_VERBOSE; + } + if (optargs_bitmask & GUESTFS_HIVEX_OPEN_DEBUG_BITMASK) { + if (debug) + flags |= HIVEX_OPEN_DEBUG; + } + if (optargs_bitmask & GUESTFS_HIVEX_OPEN_WRITE_BITMASK) { + if (write) + flags |= HIVEX_OPEN_WRITE; + } + + h = hivex_open (buf, flags); + if (!h) { + reply_with_perror ("hivex failed to open %s", filename); + free (buf); + return -1; + } + + free (buf); + return 0; +} + +int +do_hivex_close (void) +{ + NEED_HANDLE (-1); + + hivex_close (h); + h = NULL; + + return 0; +} + +int64_t +do_hivex_root (void) +{ + int64_t r; + + NEED_HANDLE (-1); + + r = hivex_root (h); + if (r == 0) { + reply_with_perror ("failed"); + return -1; + } + + return r; +} + +char * +do_hivex_node_name (int64_t nodeh) +{ + char *r; + + NEED_HANDLE (NULL); + + r = hivex_node_name (h, nodeh); + if (r == NULL) { + reply_with_perror ("failed"); + return NULL; + } + + return r; +} + +guestfs_int_hivex_node_list * +do_hivex_node_children (int64_t nodeh) +{ + guestfs_int_hivex_node_list *ret; + hive_node_h *r; + size_t i, len; + + NEED_HANDLE (NULL); + + r = hivex_node_children (h, nodeh); + if (r == NULL) { + reply_with_perror ("failed"); + return NULL; + } + + len = 0; + for (i = 0; r[i] != 0; ++i) + len++; + + ret = malloc (sizeof *ret); + if (!ret) { + reply_with_perror ("malloc"); + free (r); + return NULL; + } + + ret->guestfs_int_hivex_node_list_len = len; + ret->guestfs_int_hivex_node_list_val = + malloc (len * sizeof (guestfs_int_hivex_node)); + if (ret->guestfs_int_hivex_node_list_val == NULL) { + reply_with_perror ("malloc"); + free (ret); + free (r); + return NULL; + } + + for (i = 0; i < len; ++i) + ret->guestfs_int_hivex_node_list_val[i].hivex_node_h = r[i]; + + free (r); + + return ret; +} + +int64_t +do_hivex_node_get_child (int64_t nodeh, const char *name) +{ + int64_t r; + + NEED_HANDLE (-1); + + errno = 0; + r = hivex_node_get_child (h, nodeh, name); + if (r == 0 && errno != 0) { + reply_with_perror ("failed"); + return -1; + } + + return r; +} + +int64_t +do_hivex_node_parent (int64_t nodeh) +{ + int64_t r; + + NEED_HANDLE (-1); + + r = hivex_node_parent (h, nodeh); + if (r == 0) { + reply_with_perror ("failed"); + return -1; + } + + return r; +} + +guestfs_int_hivex_value_list * +do_hivex_node_values (int64_t nodeh) +{ + guestfs_int_hivex_value_list *ret; + hive_value_h *r; + size_t i, len; + + NEED_HANDLE (NULL); + + r = hivex_node_values (h, nodeh); + if (r == NULL) { + reply_with_perror ("failed"); + return NULL; + } + + len = 0; + for (i = 0; r[i] != 0; ++i) + len++; + + ret = malloc (sizeof *ret); + if (!ret) { + reply_with_perror ("malloc"); + free (r); + return NULL; + } + + ret->guestfs_int_hivex_value_list_len = len; + ret->guestfs_int_hivex_value_list_val = + malloc (len * sizeof (guestfs_int_hivex_value)); + if (ret->guestfs_int_hivex_value_list_val == NULL) { + reply_with_perror ("malloc"); + free (ret); + free (r); + return NULL; + } + + for (i = 0; i < len; ++i) + ret->guestfs_int_hivex_value_list_val[i].hivex_value_h = (int64_t) r[i]; + + free (r); + + return ret; +} + +int64_t +do_hivex_node_get_value (int64_t nodeh, const char *key) +{ + int64_t r; + + NEED_HANDLE (-1); + + errno = 0; + r = hivex_node_get_value (h, nodeh, key); + if (r == 0 && errno != 0) { + reply_with_perror ("failed"); + return -1; + } + + return r; +} + +char * +do_hivex_value_key (int64_t valueh) +{ + char *r; + + NEED_HANDLE (NULL); + + r = hivex_value_key (h, valueh); + if (r == NULL) { + reply_with_perror ("failed"); + return NULL; + } + + return r; +} + +int64_t +do_hivex_value_type (int64_t valueh) +{ + hive_type r; + + NEED_HANDLE (-1); + + if (hivex_value_type (h, valueh, &r, NULL) == -1) { + reply_with_perror ("failed"); + return -1; + } + + return r; +} + +char * +do_hivex_value_value (int64_t valueh, size_t *size_r) +{ + char *r; + size_t size; + + NEED_HANDLE (NULL); + + r = hivex_value_value (h, valueh, NULL, &size); + if (r == NULL) { + reply_with_perror ("failed"); + return NULL; + } + + *size_r = size; + return r; +} + +int +do_hivex_commit (const char *filename) +{ + NEED_HANDLE (-1); + + if (hivex_commit (h, filename, 0) == -1) { + reply_with_perror ("failed"); + return -1; + } + + return 0; +} + +int64_t +do_hivex_node_add_child (int64_t parent, const char *name) +{ + int64_t r; + + NEED_HANDLE (-1); + + r = hivex_node_add_child (h, parent, name); + if (r == 0) { + reply_with_perror ("failed"); + return -1; + } + + return r; +} + +int +do_hivex_node_delete_child (int64_t nodeh) +{ + NEED_HANDLE (-1); + + if (hivex_node_delete_child (h, nodeh) == -1) { + reply_with_perror ("failed"); + return -1; + } + + return 0; +} + +int +do_hivex_node_set_value (int64_t nodeh, + const char *key, int64_t t, + const char *val, size_t val_size) +{ + const hive_set_value v = + { .key = (char *) key, .t = t, .len = val_size, .value = (char *) val }; + + NEED_HANDLE (-1); + + if (hivex_node_set_value (h, nodeh, &v, 0) == -1) { + reply_with_perror ("failed"); + return -1; + } + + return 0; +} + +#else /* !HAVE_HIVEX */ + +/* Note that the wrapper code (daemon/stubs.c) ensures that the + * functions below are never called because optgroup_hivex_available + * returns false. + */ +int +optgroup_hivex_available (void) +{ + return 0; +} + +int __attribute__((noreturn)) +do_hivex_open (const char *filename, int verbose, int debug, int write) +{ + abort (); +} + +int __attribute__((noreturn)) +do_hivex_close (void) +{ + abort (); +} + +int64_t __attribute__((noreturn)) +do_hivex_root (void) +{ + abort (); +} + +char * __attribute__((noreturn)) +do_hivex_node_name (int64_t nodeh) +{ + abort (); +} + +guestfs_int_hivex_node_list * __attribute__((noreturn)) +do_hivex_node_children (int64_t nodeh) +{ + abort (); +} + +int64_t __attribute__((noreturn)) +do_hivex_node_get_child (int64_t nodeh, const char *name) +{ + abort (); +} + +int64_t __attribute__((noreturn)) +do_hivex_node_parent (int64_t nodeh) +{ + abort (); +} + +guestfs_int_hivex_value_list * __attribute__((noreturn)) +do_hivex_node_values (int64_t nodeh) +{ + abort (); +} + +int64_t __attribute__((noreturn)) +do_hivex_node_get_value (int64_t nodeh, const char *key) +{ + abort (); +} + +char * __attribute__((noreturn)) +do_hivex_value_key (int64_t valueh) +{ + abort (); +} + +int64_t __attribute__((noreturn)) +do_hivex_value_type (int64_t valueh) +{ + abort (); +} + +char * __attribute__((noreturn)) +do_hivex_value_value (int64_t valueh, size_t *size_r) +{ + abort (); +} + +int __attribute__((noreturn)) +do_hivex_commit (const char *filename) +{ + abort (); +} + +int64_t __attribute__((noreturn)) +do_hivex_node_add_child (int64_t parent, const char *name) +{ + abort (); +} + +int __attribute__((noreturn)) +do_hivex_node_delete_child (int64_t nodeh) +{ + abort (); +} + +int __attribute__((noreturn)) +do_hivex_node_set_value (int64_t nodeh, const char *key, int64_t t, const char *val, size_t val_size) +{ + abort (); +} + +#endif /* !HAVE_HIVEX */ |