summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard W.M. Jones <rjones@redhat.com>2012-11-12 12:56:39 +0000
committerRichard W.M. Jones <rjones@redhat.com>2012-11-12 13:40:25 +0000
commit02ecd048d3caf7804361bb0f5dca071f97aefaa1 (patch)
tree2b17e6b2037297bc1bc93b4371be15a3b9d3aef6
parentf9ab256f0e4c1197b505b0249e66e7614644bd0b (diff)
downloadlibguestfs-02ecd048d3caf7804361bb0f5dca071f97aefaa1.tar.gz
libguestfs-02ecd048d3caf7804361bb0f5dca071f97aefaa1.tar.xz
libguestfs-02ecd048d3caf7804361bb0f5dca071f97aefaa1.zip
lib: Split up huge src/guestfs.c into logical compilation units.
This file had grown by accretion to include: - code related to handles (now in src/handle.c) - safe allocation (src/alloc.c) - debug, errors, warnings (src/errors.c) - private data (src/private-data.c) - miscellaneous functions (src/canonical-name.c, src/utils.c) This commit also removes about a dozen #include files which were probably not really used. This is just code motion.
-rw-r--r--po/POTFILES7
-rw-r--r--src/Makefile.am7
-rw-r--r--src/alloc.c124
-rw-r--r--src/canonical-name.c50
-rw-r--r--src/errors.c282
-rw-r--r--src/guestfs-internal.h39
-rw-r--r--src/handle.c (renamed from src/guestfs.c)523
-rw-r--r--src/private-data.c148
-rw-r--r--src/utils.c36
9 files changed, 675 insertions, 541 deletions
diff --git a/po/POTFILES b/po/POTFILES
index fcaa77ce..622c0158 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -225,18 +225,21 @@ src/actions-5.c
src/actions-6.c
src/actions-support.c
src/actions-variants.c
+src/alloc.c
src/appliance.c
src/bindtests.c
+src/canonical-name.c
src/command.c
src/dbdump.c
src/errnostring-gperf.c
src/errnostring.c
+src/errors.c
src/events.c
src/file.c
src/filearch.c
src/free-structs.c
src/fuse.c
-src/guestfs.c
+src/handle.c
src/info.c
src/inspect-apps.c
src/inspect-fs-cd.c
@@ -253,8 +256,10 @@ src/libvirt-auth.c
src/libvirt-domain.c
src/listfs.c
src/match.c
+src/private-data.c
src/proto.c
src/tmpdirs.c
+src/utils.c
test-tool/test-tool.c
tools/virt-list-filesystems.pl
tools/virt-list-partitions.pl
diff --git a/src/Makefile.am b/src/Makefile.am
index 7b7f6065..d979e251 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -126,7 +126,6 @@ libguestfs_la_LDFLAGS = -version-info $(MAX_PROC_NR):0:$(MAX_PROC_NR)
libguestfs_la_LDFLAGS += $(VERSION_SCRIPT_FLAGS)$(srcdir)/libguestfs.syms
libguestfs_la_SOURCES = \
- guestfs.c \
guestfs.h \
guestfs-internal.h \
guestfs_protocol.h \
@@ -139,15 +138,19 @@ libguestfs_la_SOURCES = \
actions-6.c \
actions-support.c \
actions-variants.c \
+ alloc.c \
appliance.c \
bindtests.c \
command.c \
+ canonical-name.c \
dbdump.c \
+ errors.c \
events.c \
file.c \
filearch.c \
free-structs.c \
fuse.c \
+ handle.c \
info.c \
inspect.c \
inspect-apps.c \
@@ -164,8 +167,10 @@ libguestfs_la_SOURCES = \
libvirt-domain.c \
listfs.c \
match.c \
+ private-data.c \
proto.c \
tmpdirs.c \
+ utils.c \
libguestfs.syms
libguestfs_la_LIBADD = \
diff --git a/src/alloc.c b/src/alloc.c
new file mode 100644
index 00000000..dc64bbd8
--- /dev/null
+++ b/src/alloc.c
@@ -0,0 +1,124 @@
+/* libguestfs
+ * Copyright (C) 2009-2012 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; 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 <unistd.h>
+#include <string.h>
+
+#include "guestfs.h"
+#include "guestfs-internal.h"
+
+void *
+guestfs_safe_malloc (guestfs_h *g, size_t nbytes)
+{
+ void *ptr = malloc (nbytes);
+ if (nbytes > 0 && !ptr) g->abort_cb ();
+ return ptr;
+}
+
+/* Return 1 if an array of N objects, each of size S, cannot exist due
+ to size arithmetic overflow. S must be positive and N must be
+ nonnegative. This is a macro, not an inline function, so that it
+ works correctly even when SIZE_MAX < N.
+
+ By gnulib convention, SIZE_MAX represents overflow in size
+ calculations, so the conservative dividend to use here is
+ SIZE_MAX - 1, since SIZE_MAX might represent an overflowed value.
+ However, malloc (SIZE_MAX) fails on all known hosts where
+ sizeof (ptrdiff_t) <= sizeof (size_t), so do not bother to test for
+ exactly-SIZE_MAX allocations on such hosts; this avoids a test and
+ branch when S is known to be 1. */
+# define xalloc_oversized(n, s) \
+ ((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n))
+
+/* Technically we should add an autoconf test for this, testing for the desired
+ functionality, like what's done in gnulib, but for now, this is fine. */
+#if defined(__GLIBC__)
+#define HAVE_GNU_CALLOC (__GLIBC__ >= 2)
+#else
+#define HAVE_GNU_CALLOC 0
+#endif
+
+/* Allocate zeroed memory for N elements of S bytes, with error
+ checking. S must be nonzero. */
+void *
+guestfs_safe_calloc (guestfs_h *g, size_t n, size_t s)
+{
+ /* From gnulib's calloc function in xmalloc.c. */
+ void *p;
+ /* Test for overflow, since some calloc implementations don't have
+ proper overflow checks. But omit overflow and size-zero tests if
+ HAVE_GNU_CALLOC, since GNU calloc catches overflow and never
+ returns NULL if successful. */
+ if ((! HAVE_GNU_CALLOC && xalloc_oversized (n, s))
+ || (! (p = calloc (n, s)) && (HAVE_GNU_CALLOC || n != 0)))
+ g->abort_cb ();
+ return p;
+}
+
+void *
+guestfs_safe_realloc (guestfs_h *g, void *ptr, size_t nbytes)
+{
+ void *p = realloc (ptr, nbytes);
+ if (nbytes > 0 && !p) g->abort_cb ();
+ return p;
+}
+
+char *
+guestfs_safe_strdup (guestfs_h *g, const char *str)
+{
+ char *s = strdup (str);
+ if (!s) g->abort_cb ();
+ return s;
+}
+
+char *
+guestfs_safe_strndup (guestfs_h *g, const char *str, size_t n)
+{
+ char *s = strndup (str, n);
+ if (!s) g->abort_cb ();
+ return s;
+}
+
+void *
+guestfs_safe_memdup (guestfs_h *g, const void *ptr, size_t size)
+{
+ void *p = malloc (size);
+ if (!p) g->abort_cb ();
+ memcpy (p, ptr, size);
+ return p;
+}
+
+char *
+guestfs_safe_asprintf (guestfs_h *g, const char *fs, ...)
+{
+ va_list args;
+ char *msg;
+
+ va_start (args, fs);
+ int err = vasprintf (&msg, fs, args);
+ va_end (args);
+
+ if (err == -1)
+ g->abort_cb ();
+
+ return msg;
+}
diff --git a/src/canonical-name.c b/src/canonical-name.c
new file mode 100644
index 00000000..b7176072
--- /dev/null
+++ b/src/canonical-name.c
@@ -0,0 +1,50 @@
+/* libguestfs
+ * Copyright (C) 2009-2012 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; 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 "guestfs.h"
+#include "guestfs-internal.h"
+#include "guestfs-internal-actions.h"
+
+char *
+guestfs__canonical_device_name (guestfs_h *g, const char *device)
+{
+ char *ret;
+
+ if (STRPREFIX (device, "/dev/hd") ||
+ STRPREFIX (device, "/dev/vd")) {
+ ret = safe_strdup (g, device);
+ ret[5] = 's';
+ }
+ else if (STRPREFIX (device, "/dev/mapper/") ||
+ STRPREFIX (device, "/dev/dm-")) {
+ /* XXX hide errors */
+ ret = guestfs_lvm_canonical_lv_name (g, device);
+ if (ret == NULL)
+ ret = safe_strdup (g, device);
+ }
+ else
+ ret = safe_strdup (g, device);
+
+ return ret; /* caller frees */
+}
diff --git a/src/errors.c b/src/errors.c
new file mode 100644
index 00000000..d12a4a3a
--- /dev/null
+++ b/src/errors.c
@@ -0,0 +1,282 @@
+/* libguestfs
+ * Copyright (C) 2009-2012 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; 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 <stdarg.h>
+#include <string.h>
+#include <errno.h>
+
+#include "c-ctype.h"
+
+#include "guestfs.h"
+#include "guestfs-internal.h"
+
+const char *
+guestfs_last_error (guestfs_h *g)
+{
+ return g->last_error;
+}
+
+int
+guestfs_last_errno (guestfs_h *g)
+{
+ return g->last_errnum;
+}
+
+static void
+set_last_error (guestfs_h *g, int errnum, const char *msg)
+{
+ free (g->last_error);
+ g->last_error = strdup (msg);
+ g->last_errnum = errnum;
+}
+
+/* Warning are printed unconditionally. We try to make these rare.
+ * Generally speaking, a warning should either be an error, or if it's
+ * not important for end users then it should be a debug message.
+ */
+void
+guestfs___warning (guestfs_h *g, const char *fs, ...)
+{
+ va_list args;
+ char *msg, *msg2;
+ int len;
+
+ va_start (args, fs);
+ len = vasprintf (&msg, fs, args);
+ va_end (args);
+
+ if (len < 0) return;
+
+ len = asprintf (&msg2, _("warning: %s"), msg);
+ free (msg);
+
+ if (len < 0) return;
+
+ guestfs___call_callbacks_message (g, GUESTFS_EVENT_LIBRARY, msg2, len);
+
+ free (msg2);
+}
+
+/* Debug messages. */
+void
+guestfs___debug (guestfs_h *g, const char *fs, ...)
+{
+ va_list args;
+ char *msg;
+ int len;
+
+ /* The cpp macro "debug" has already checked that g->verbose is true
+ * before calling this function, but we check it again just in case
+ * anyone calls this function directly.
+ */
+ if (!g->verbose)
+ return;
+
+ va_start (args, fs);
+ len = vasprintf (&msg, fs, args);
+ va_end (args);
+
+ if (len < 0) return;
+
+ guestfs___call_callbacks_message (g, GUESTFS_EVENT_LIBRARY, msg, len);
+
+ free (msg);
+}
+
+/* Call trace messages. These are enabled by setting g->trace, and
+ * calls to this function should only happen from the generated code
+ * in src/actions.c
+ */
+void
+guestfs___trace (guestfs_h *g, const char *fs, ...)
+{
+ va_list args;
+ char *msg;
+ int len;
+
+ va_start (args, fs);
+ len = vasprintf (&msg, fs, args);
+ va_end (args);
+
+ if (len < 0) return;
+
+ guestfs___call_callbacks_message (g, GUESTFS_EVENT_TRACE, msg, len);
+
+ free (msg);
+}
+
+void
+guestfs_error_errno (guestfs_h *g, int errnum, const char *fs, ...)
+{
+ va_list args;
+ char *msg;
+
+ va_start (args, fs);
+ int err = vasprintf (&msg, fs, args);
+ va_end (args);
+
+ if (err < 0) return;
+
+ /* set_last_error first so that the callback can access the error
+ * message and errno through the handle if it wishes.
+ */
+ set_last_error (g, errnum, msg);
+ if (g->error_cb) g->error_cb (g, g->error_cb_data, msg);
+
+ free (msg);
+}
+
+void
+guestfs_perrorf (guestfs_h *g, const char *fs, ...)
+{
+ va_list args;
+ char *msg;
+ int errnum = errno;
+
+ va_start (args, fs);
+ int err = vasprintf (&msg, fs, args);
+ va_end (args);
+
+ if (err < 0) return;
+
+ char buf[256];
+ strerror_r (errnum, buf, sizeof buf);
+
+ msg = safe_realloc (g, msg, strlen (msg) + 2 + strlen (buf) + 1);
+ strcat (msg, ": ");
+ strcat (msg, buf);
+
+ /* set_last_error first so that the callback can access the error
+ * message and errno through the handle if it wishes.
+ */
+ set_last_error (g, errnum, msg);
+ if (g->error_cb) g->error_cb (g, g->error_cb_data, msg);
+
+ free (msg);
+}
+
+void
+guestfs_set_out_of_memory_handler (guestfs_h *g, guestfs_abort_cb cb)
+{
+ g->abort_cb = cb;
+}
+
+guestfs_abort_cb
+guestfs_get_out_of_memory_handler (guestfs_h *g)
+{
+ return g->abort_cb;
+}
+
+void
+guestfs_set_error_handler (guestfs_h *g,
+ guestfs_error_handler_cb cb, void *data)
+{
+ g->error_cb = cb;
+ g->error_cb_data = data;
+}
+
+guestfs_error_handler_cb
+guestfs_get_error_handler (guestfs_h *g, void **data_rtn)
+{
+ if (data_rtn) *data_rtn = g->error_cb_data;
+ return g->error_cb;
+}
+
+void
+guestfs_push_error_handler (guestfs_h *g,
+ guestfs_error_handler_cb cb, void *data)
+{
+ struct error_cb_stack *old_stack;
+
+ old_stack = g->error_cb_stack;
+ g->error_cb_stack = safe_malloc (g, sizeof (struct error_cb_stack));
+ g->error_cb_stack->next = old_stack;
+ g->error_cb_stack->error_cb = g->error_cb;
+ g->error_cb_stack->error_cb_data = g->error_cb_data;
+
+ guestfs_set_error_handler (g, cb, data);
+}
+
+void
+guestfs_pop_error_handler (guestfs_h *g)
+{
+ struct error_cb_stack *next_stack;
+
+ if (g->error_cb_stack) {
+ next_stack = g->error_cb_stack->next;
+ guestfs_set_error_handler (g, g->error_cb_stack->error_cb,
+ g->error_cb_stack->error_cb_data);
+ free (g->error_cb_stack);
+ g->error_cb_stack = next_stack;
+ }
+ else
+ guestfs___init_error_handler (g);
+}
+
+static void default_error_cb (guestfs_h *g, void *data, const char *msg);
+
+void
+guestfs___init_error_handler (guestfs_h *g)
+{
+ g->error_cb = default_error_cb;
+ g->error_cb_data = NULL;
+}
+
+static void
+default_error_cb (guestfs_h *g, void *data, const char *msg)
+{
+ fprintf (stderr, _("libguestfs: error: %s\n"), msg);
+}
+
+/* When tracing, be careful how we print BufferIn parameters which
+ * usually contain large amounts of binary data (RHBZ#646822).
+ */
+void
+guestfs___print_BufferIn (FILE *out, const char *buf, size_t buf_size)
+{
+ size_t i;
+ size_t orig_size = buf_size;
+
+ if (buf_size > 256)
+ buf_size = 256;
+
+ fputc ('"', out);
+
+ for (i = 0; i < buf_size; ++i) {
+ if (c_isprint (buf[i]))
+ fputc (buf[i], out);
+ else
+ fprintf (out, "\\x%02x", (unsigned char) buf[i]);
+ }
+
+ fputc ('"', out);
+
+ if (orig_size > buf_size)
+ fprintf (out,
+ _("<truncated, original size %zu bytes>"), orig_size);
+}
+
+void
+guestfs___print_BufferOut (FILE *out, const char *buf, size_t buf_size)
+{
+ guestfs___print_BufferIn (out, buf, buf_size);
+}
diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h
index 4a12de76..6e0b3685 100644
--- a/src/guestfs-internal.h
+++ b/src/guestfs-internal.h
@@ -472,14 +472,7 @@ struct guestfs_message_header;
struct guestfs_message_error;
struct guestfs_progress;
-/* guestfs.c */
-extern void guestfs_error (guestfs_h *g, const char *fs, ...)
- __attribute__((format (printf,2,3)));
-extern void guestfs_error_errno (guestfs_h *g, int errnum, const char *fs, ...)
- __attribute__((format (printf,3,4)));
-extern void guestfs_perrorf (guestfs_h *g, const char *fs, ...)
- __attribute__((format (printf,2,3)));
-
+/* alloc.c */
extern void *guestfs_safe_realloc (guestfs_h *g, void *ptr, size_t nbytes);
extern char *guestfs_safe_strdup (guestfs_h *g, const char *str);
extern char *guestfs_safe_strndup (guestfs_h *g, const char *str, size_t n);
@@ -487,6 +480,24 @@ extern void *guestfs_safe_memdup (guestfs_h *g, const void *ptr, size_t size);
extern char *guestfs_safe_asprintf (guestfs_h *g, const char *fs, ...)
__attribute__((format (printf,2,3)));
+#define safe_calloc guestfs_safe_calloc
+#define safe_malloc guestfs_safe_malloc
+#define safe_realloc guestfs_safe_realloc
+#define safe_strdup guestfs_safe_strdup
+#define safe_strndup guestfs_safe_strndup
+#define safe_memdup guestfs_safe_memdup
+#define safe_asprintf guestfs_safe_asprintf
+
+/* errors.c */
+extern void guestfs___init_error_handler (guestfs_h *g);
+
+extern void guestfs_error (guestfs_h *g, const char *fs, ...)
+ __attribute__((format (printf,2,3)));
+extern void guestfs_error_errno (guestfs_h *g, int errnum, const char *fs, ...)
+ __attribute__((format (printf,3,4)));
+extern void guestfs_perrorf (guestfs_h *g, const char *fs, ...)
+ __attribute__((format (printf,2,3)));
+
extern void guestfs___warning (guestfs_h *g, const char *fs, ...)
__attribute__((format (printf,2,3)));
extern void guestfs___debug (guestfs_h *g, const char *fs, ...)
@@ -494,8 +505,6 @@ extern void guestfs___debug (guestfs_h *g, const char *fs, ...)
extern void guestfs___trace (guestfs_h *g, const char *fs, ...)
__attribute__((format (printf,2,3)));
-extern void guestfs___free_string_list (char **);
-
extern void guestfs___print_BufferIn (FILE *out, const char *buf, size_t buf_size);
extern void guestfs___print_BufferOut (FILE *out, const char *buf, size_t buf_size);
@@ -504,13 +513,9 @@ extern void guestfs___print_BufferOut (FILE *out, const char *buf, size_t buf_si
#define warning(g,...) guestfs___warning((g),__VA_ARGS__)
#define debug(g,...) \
do { if ((g)->verbose) guestfs___debug ((g),__VA_ARGS__); } while (0)
-#define safe_calloc guestfs_safe_calloc
-#define safe_malloc guestfs_safe_malloc
-#define safe_realloc guestfs_safe_realloc
-#define safe_strdup guestfs_safe_strdup
-#define safe_strndup guestfs_safe_strndup
-#define safe_memdup guestfs_safe_memdup
-#define safe_asprintf guestfs_safe_asprintf
+
+/* utils.c */
+extern void guestfs___free_string_list (char **);
/* actions-support.c */
extern int guestfs___check_reply_header (guestfs_h *g, const struct guestfs_message_header *hdr, unsigned int proc_nr, unsigned int serial);
diff --git a/src/guestfs.c b/src/handle.c
index f8eb76c7..fd7db698 100644
--- a/src/guestfs.c
+++ b/src/handle.c
@@ -18,29 +18,10 @@
#include <config.h>
-#define _BSD_SOURCE /* for mkdtemp, usleep */
-
#include <stdio.h>
#include <stdlib.h>
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <inttypes.h>
#include <unistd.h>
#include <string.h>
-#include <fcntl.h>
-#include <time.h>
-#include <assert.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <sys/select.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/un.h>
-#include <sys/wait.h>
-
-#include <rpc/types.h>
-#include <rpc/xdr.h>
#ifdef HAVE_LIBVIRT
#include <libvirt/libvirt.h>
@@ -51,10 +32,7 @@
#include <libxml/xmlversion.h>
#endif
-#include "c-ctype.h"
#include "glthread/lock.h"
-#include "hash.h"
-#include "hash-pjw.h"
#include "guestfs.h"
#include "guestfs-internal.h"
@@ -62,7 +40,6 @@
#include "guestfs_protocol.h"
static int parse_attach_method (guestfs_h *g, const char *method);
-static void init_error_handler (guestfs_h *g);
static int shutdown_backend (guestfs_h *g, int check_for_errors);
static void close_handles (void);
@@ -117,7 +94,7 @@ guestfs_create_flags (unsigned flags, ...)
g->fd[1] = -1;
g->sock = -1;
- init_error_handler (g);
+ guestfs___init_error_handler (g);
g->abort_cb = abort;
g->recovery_proc = 1;
@@ -410,321 +387,6 @@ close_handles (void)
while (handles) guestfs_close (handles);
}
-const char *
-guestfs_last_error (guestfs_h *g)
-{
- return g->last_error;
-}
-
-int
-guestfs_last_errno (guestfs_h *g)
-{
- return g->last_errnum;
-}
-
-static void
-set_last_error (guestfs_h *g, int errnum, const char *msg)
-{
- free (g->last_error);
- g->last_error = strdup (msg);
- g->last_errnum = errnum;
-}
-
-/* Warning are printed unconditionally. We try to make these rare.
- * Generally speaking, a warning should either be an error, or if it's
- * not important for end users then it should be a debug message.
- */
-void
-guestfs___warning (guestfs_h *g, const char *fs, ...)
-{
- va_list args;
- char *msg, *msg2;
- int len;
-
- va_start (args, fs);
- len = vasprintf (&msg, fs, args);
- va_end (args);
-
- if (len < 0) return;
-
- len = asprintf (&msg2, _("warning: %s"), msg);
- free (msg);
-
- if (len < 0) return;
-
- guestfs___call_callbacks_message (g, GUESTFS_EVENT_LIBRARY, msg2, len);
-
- free (msg2);
-}
-
-/* Debug messages. */
-void
-guestfs___debug (guestfs_h *g, const char *fs, ...)
-{
- va_list args;
- char *msg;
- int len;
-
- /* The cpp macro "debug" has already checked that g->verbose is true
- * before calling this function, but we check it again just in case
- * anyone calls this function directly.
- */
- if (!g->verbose)
- return;
-
- va_start (args, fs);
- len = vasprintf (&msg, fs, args);
- va_end (args);
-
- if (len < 0) return;
-
- guestfs___call_callbacks_message (g, GUESTFS_EVENT_LIBRARY, msg, len);
-
- free (msg);
-}
-
-/* Call trace messages. These are enabled by setting g->trace, and
- * calls to this function should only happen from the generated code
- * in src/actions.c
- */
-void
-guestfs___trace (guestfs_h *g, const char *fs, ...)
-{
- va_list args;
- char *msg;
- int len;
-
- va_start (args, fs);
- len = vasprintf (&msg, fs, args);
- va_end (args);
-
- if (len < 0) return;
-
- guestfs___call_callbacks_message (g, GUESTFS_EVENT_TRACE, msg, len);
-
- free (msg);
-}
-
-void
-guestfs_error_errno (guestfs_h *g, int errnum, const char *fs, ...)
-{
- va_list args;
- char *msg;
-
- va_start (args, fs);
- int err = vasprintf (&msg, fs, args);
- va_end (args);
-
- if (err < 0) return;
-
- /* set_last_error first so that the callback can access the error
- * message and errno through the handle if it wishes.
- */
- set_last_error (g, errnum, msg);
- if (g->error_cb) g->error_cb (g, g->error_cb_data, msg);
-
- free (msg);
-}
-
-void
-guestfs_perrorf (guestfs_h *g, const char *fs, ...)
-{
- va_list args;
- char *msg;
- int errnum = errno;
-
- va_start (args, fs);
- int err = vasprintf (&msg, fs, args);
- va_end (args);
-
- if (err < 0) return;
-
- char buf[256];
- strerror_r (errnum, buf, sizeof buf);
-
- msg = safe_realloc (g, msg, strlen (msg) + 2 + strlen (buf) + 1);
- strcat (msg, ": ");
- strcat (msg, buf);
-
- /* set_last_error first so that the callback can access the error
- * message and errno through the handle if it wishes.
- */
- set_last_error (g, errnum, msg);
- if (g->error_cb) g->error_cb (g, g->error_cb_data, msg);
-
- free (msg);
-}
-
-void *
-guestfs_safe_malloc (guestfs_h *g, size_t nbytes)
-{
- void *ptr = malloc (nbytes);
- if (nbytes > 0 && !ptr) g->abort_cb ();
- return ptr;
-}
-
-/* Return 1 if an array of N objects, each of size S, cannot exist due
- to size arithmetic overflow. S must be positive and N must be
- nonnegative. This is a macro, not an inline function, so that it
- works correctly even when SIZE_MAX < N.
-
- By gnulib convention, SIZE_MAX represents overflow in size
- calculations, so the conservative dividend to use here is
- SIZE_MAX - 1, since SIZE_MAX might represent an overflowed value.
- However, malloc (SIZE_MAX) fails on all known hosts where
- sizeof (ptrdiff_t) <= sizeof (size_t), so do not bother to test for
- exactly-SIZE_MAX allocations on such hosts; this avoids a test and
- branch when S is known to be 1. */
-# define xalloc_oversized(n, s) \
- ((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n))
-
-/* Technically we should add an autoconf test for this, testing for the desired
- functionality, like what's done in gnulib, but for now, this is fine. */
-#if defined(__GLIBC__)
-#define HAVE_GNU_CALLOC (__GLIBC__ >= 2)
-#else
-#define HAVE_GNU_CALLOC 0
-#endif
-
-/* Allocate zeroed memory for N elements of S bytes, with error
- checking. S must be nonzero. */
-void *
-guestfs_safe_calloc (guestfs_h *g, size_t n, size_t s)
-{
- /* From gnulib's calloc function in xmalloc.c. */
- void *p;
- /* Test for overflow, since some calloc implementations don't have
- proper overflow checks. But omit overflow and size-zero tests if
- HAVE_GNU_CALLOC, since GNU calloc catches overflow and never
- returns NULL if successful. */
- if ((! HAVE_GNU_CALLOC && xalloc_oversized (n, s))
- || (! (p = calloc (n, s)) && (HAVE_GNU_CALLOC || n != 0)))
- g->abort_cb ();
- return p;
-}
-
-void *
-guestfs_safe_realloc (guestfs_h *g, void *ptr, size_t nbytes)
-{
- void *p = realloc (ptr, nbytes);
- if (nbytes > 0 && !p) g->abort_cb ();
- return p;
-}
-
-char *
-guestfs_safe_strdup (guestfs_h *g, const char *str)
-{
- char *s = strdup (str);
- if (!s) g->abort_cb ();
- return s;
-}
-
-char *
-guestfs_safe_strndup (guestfs_h *g, const char *str, size_t n)
-{
- char *s = strndup (str, n);
- if (!s) g->abort_cb ();
- return s;
-}
-
-void *
-guestfs_safe_memdup (guestfs_h *g, const void *ptr, size_t size)
-{
- void *p = malloc (size);
- if (!p) g->abort_cb ();
- memcpy (p, ptr, size);
- return p;
-}
-
-char *
-guestfs_safe_asprintf (guestfs_h *g, const char *fs, ...)
-{
- va_list args;
- char *msg;
-
- va_start (args, fs);
- int err = vasprintf (&msg, fs, args);
- va_end (args);
-
- if (err == -1)
- g->abort_cb ();
-
- return msg;
-}
-
-void
-guestfs_set_out_of_memory_handler (guestfs_h *g, guestfs_abort_cb cb)
-{
- g->abort_cb = cb;
-}
-
-guestfs_abort_cb
-guestfs_get_out_of_memory_handler (guestfs_h *g)
-{
- return g->abort_cb;
-}
-
-void
-guestfs_set_error_handler (guestfs_h *g,
- guestfs_error_handler_cb cb, void *data)
-{
- g->error_cb = cb;
- g->error_cb_data = data;
-}
-
-guestfs_error_handler_cb
-guestfs_get_error_handler (guestfs_h *g, void **data_rtn)
-{
- if (data_rtn) *data_rtn = g->error_cb_data;
- return g->error_cb;
-}
-
-void
-guestfs_push_error_handler (guestfs_h *g,
- guestfs_error_handler_cb cb, void *data)
-{
- struct error_cb_stack *old_stack;
-
- old_stack = g->error_cb_stack;
- g->error_cb_stack = safe_malloc (g, sizeof (struct error_cb_stack));
- g->error_cb_stack->next = old_stack;
- g->error_cb_stack->error_cb = g->error_cb;
- g->error_cb_stack->error_cb_data = g->error_cb_data;
-
- guestfs_set_error_handler (g, cb, data);
-}
-
-void
-guestfs_pop_error_handler (guestfs_h *g)
-{
- struct error_cb_stack *next_stack;
-
- if (g->error_cb_stack) {
- next_stack = g->error_cb_stack->next;
- guestfs_set_error_handler (g, g->error_cb_stack->error_cb,
- g->error_cb_stack->error_cb_data);
- free (g->error_cb_stack);
- g->error_cb_stack = next_stack;
- }
- else
- init_error_handler (g);
-}
-
-static void default_error_cb (guestfs_h *g, void *data, const char *msg);
-
-static void
-init_error_handler (guestfs_h *g)
-{
- g->error_cb = default_error_cb;
- g->error_cb_data = NULL;
-}
-
-static void
-default_error_cb (guestfs_h *g, void *data, const char *msg)
-{
- fprintf (stderr, _("libguestfs: error: %s\n"), msg);
-}
-
void
guestfs_user_cancel (guestfs_h *g)
{
@@ -1005,186 +667,3 @@ guestfs__get_smp (guestfs_h *g)
{
return g->smp;
}
-
-/* Note the private data area is allocated lazily, since the vast
- * majority of callers will never use it. This means g->pda is
- * likely to be NULL.
- */
-struct pda_entry {
- char *key; /* key */
- void *data; /* opaque user data pointer */
-};
-
-static size_t
-hasher (void const *x, size_t table_size)
-{
- struct pda_entry const *p = x;
- return hash_pjw (p->key, table_size);
-}
-
-static bool
-comparator (void const *x, void const *y)
-{
- struct pda_entry const *a = x;
- struct pda_entry const *b = y;
- return STREQ (a->key, b->key);
-}
-
-static void
-freer (void *x)
-{
- if (x) {
- struct pda_entry *p = x;
- free (p->key);
- free (p);
- }
-}
-
-void
-guestfs_set_private (guestfs_h *g, const char *key, void *data)
-{
- if (g->pda == NULL) {
- g->pda = hash_initialize (16, NULL, hasher, comparator, freer);
- if (g->pda == NULL)
- g->abort_cb ();
- }
-
- struct pda_entry *new_entry = safe_malloc (g, sizeof *new_entry);
- new_entry->key = safe_strdup (g, key);
- new_entry->data = data;
-
- struct pda_entry *old_entry = hash_delete (g->pda, new_entry);
- freer (old_entry);
-
- struct pda_entry *entry = hash_insert (g->pda, new_entry);
- if (entry == NULL)
- g->abort_cb ();
- assert (entry == new_entry);
-}
-
-static inline char *
-bad_cast (char const *s)
-{
- return (char *) s;
-}
-
-void *
-guestfs_get_private (guestfs_h *g, const char *key)
-{
- if (g->pda == NULL)
- return NULL; /* no keys have been set */
-
- const struct pda_entry k = { .key = bad_cast (key) };
- struct pda_entry *entry = hash_lookup (g->pda, &k);
- if (entry)
- return entry->data;
- else
- return NULL;
-}
-
-/* Iterator. */
-void *
-guestfs_first_private (guestfs_h *g, const char **key_rtn)
-{
- if (g->pda == NULL)
- return NULL;
-
- g->pda_next = hash_get_first (g->pda);
-
- /* Ignore any keys with NULL data pointers. */
- while (g->pda_next && g->pda_next->data == NULL)
- g->pda_next = hash_get_next (g->pda, g->pda_next);
-
- if (g->pda_next == NULL)
- return NULL;
-
- *key_rtn = g->pda_next->key;
- return g->pda_next->data;
-}
-
-void *
-guestfs_next_private (guestfs_h *g, const char **key_rtn)
-{
- if (g->pda == NULL)
- return NULL;
-
- if (g->pda_next == NULL)
- return NULL;
-
- /* Walk to the next key with a non-NULL data pointer. */
- do {
- g->pda_next = hash_get_next (g->pda, g->pda_next);
- } while (g->pda_next && g->pda_next->data == NULL);
-
- if (g->pda_next == NULL)
- return NULL;
-
- *key_rtn = g->pda_next->key;
- return g->pda_next->data;
-}
-
-/* When tracing, be careful how we print BufferIn parameters which
- * usually contain large amounts of binary data (RHBZ#646822).
- */
-void
-guestfs___print_BufferIn (FILE *out, const char *buf, size_t buf_size)
-{
- size_t i;
- size_t orig_size = buf_size;
-
- if (buf_size > 256)
- buf_size = 256;
-
- fputc ('"', out);
-
- for (i = 0; i < buf_size; ++i) {
- if (c_isprint (buf[i]))
- fputc (buf[i], out);
- else
- fprintf (out, "\\x%02x", (unsigned char) buf[i]);
- }
-
- fputc ('"', out);
-
- if (orig_size > buf_size)
- fprintf (out,
- _("<truncated, original size %zu bytes>"), orig_size);
-}
-
-void
-guestfs___print_BufferOut (FILE *out, const char *buf, size_t buf_size)
-{
- guestfs___print_BufferIn (out, buf, buf_size);
-}
-
-void
-guestfs___free_string_list (char **argv)
-{
- size_t i;
- for (i = 0; argv[i] != NULL; ++i)
- free (argv[i]);
- free (argv);
-}
-
-char *
-guestfs__canonical_device_name (guestfs_h *g, const char *device)
-{
- char *ret;
-
- if (STRPREFIX (device, "/dev/hd") ||
- STRPREFIX (device, "/dev/vd")) {
- ret = safe_strdup (g, device);
- ret[5] = 's';
- }
- else if (STRPREFIX (device, "/dev/mapper/") ||
- STRPREFIX (device, "/dev/dm-")) {
- /* XXX hide errors */
- ret = guestfs_lvm_canonical_lv_name (g, device);
- if (ret == NULL)
- ret = safe_strdup (g, device);
- }
- else
- ret = safe_strdup (g, device);
-
- return ret; /* caller frees */
-}
diff --git a/src/private-data.c b/src/private-data.c
new file mode 100644
index 00000000..870ec101
--- /dev/null
+++ b/src/private-data.c
@@ -0,0 +1,148 @@
+/* libguestfs
+ * Copyright (C) 2009-2012 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; 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 <assert.h>
+
+#include "c-ctype.h"
+#include "hash.h"
+#include "hash-pjw.h"
+
+#include "guestfs.h"
+#include "guestfs-internal.h"
+
+/* Note the private data area is allocated lazily, since the vast
+ * majority of callers will never use it. This means g->pda is
+ * likely to be NULL.
+ */
+struct pda_entry {
+ char *key; /* key */
+ void *data; /* opaque user data pointer */
+};
+
+static size_t
+hasher (void const *x, size_t table_size)
+{
+ struct pda_entry const *p = x;
+ return hash_pjw (p->key, table_size);
+}
+
+static bool
+comparator (void const *x, void const *y)
+{
+ struct pda_entry const *a = x;
+ struct pda_entry const *b = y;
+ return STREQ (a->key, b->key);
+}
+
+static void
+freer (void *x)
+{
+ if (x) {
+ struct pda_entry *p = x;
+ free (p->key);
+ free (p);
+ }
+}
+
+void
+guestfs_set_private (guestfs_h *g, const char *key, void *data)
+{
+ if (g->pda == NULL) {
+ g->pda = hash_initialize (16, NULL, hasher, comparator, freer);
+ if (g->pda == NULL)
+ g->abort_cb ();
+ }
+
+ struct pda_entry *new_entry = safe_malloc (g, sizeof *new_entry);
+ new_entry->key = safe_strdup (g, key);
+ new_entry->data = data;
+
+ struct pda_entry *old_entry = hash_delete (g->pda, new_entry);
+ freer (old_entry);
+
+ struct pda_entry *entry = hash_insert (g->pda, new_entry);
+ if (entry == NULL)
+ g->abort_cb ();
+ assert (entry == new_entry);
+}
+
+static inline char *
+bad_cast (char const *s)
+{
+ return (char *) s;
+}
+
+void *
+guestfs_get_private (guestfs_h *g, const char *key)
+{
+ if (g->pda == NULL)
+ return NULL; /* no keys have been set */
+
+ const struct pda_entry k = { .key = bad_cast (key) };
+ struct pda_entry *entry = hash_lookup (g->pda, &k);
+ if (entry)
+ return entry->data;
+ else
+ return NULL;
+}
+
+/* Iterator. */
+void *
+guestfs_first_private (guestfs_h *g, const char **key_rtn)
+{
+ if (g->pda == NULL)
+ return NULL;
+
+ g->pda_next = hash_get_first (g->pda);
+
+ /* Ignore any keys with NULL data pointers. */
+ while (g->pda_next && g->pda_next->data == NULL)
+ g->pda_next = hash_get_next (g->pda, g->pda_next);
+
+ if (g->pda_next == NULL)
+ return NULL;
+
+ *key_rtn = g->pda_next->key;
+ return g->pda_next->data;
+}
+
+void *
+guestfs_next_private (guestfs_h *g, const char **key_rtn)
+{
+ if (g->pda == NULL)
+ return NULL;
+
+ if (g->pda_next == NULL)
+ return NULL;
+
+ /* Walk to the next key with a non-NULL data pointer. */
+ do {
+ g->pda_next = hash_get_next (g->pda, g->pda_next);
+ } while (g->pda_next && g->pda_next->data == NULL);
+
+ if (g->pda_next == NULL)
+ return NULL;
+
+ *key_rtn = g->pda_next->key;
+ return g->pda_next->data;
+}
diff --git a/src/utils.c b/src/utils.c
new file mode 100644
index 00000000..aaf4fa5d
--- /dev/null
+++ b/src/utils.c
@@ -0,0 +1,36 @@
+/* libguestfs
+ * Copyright (C) 2009-2012 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; 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 <unistd.h>
+#include <string.h>
+
+#include "guestfs.h"
+#include "guestfs-internal.h"
+
+void
+guestfs___free_string_list (char **argv)
+{
+ size_t i;
+ for (i = 0; argv[i] != NULL; ++i)
+ free (argv[i]);
+ free (argv);
+}