mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-21 22:53:37 +00:00
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.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 = \
|
||||
|
||||
124
src/alloc.c
Normal file
124
src/alloc.c
Normal file
@@ -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;
|
||||
}
|
||||
50
src/canonical-name.c
Normal file
50
src/canonical-name.c
Normal file
@@ -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 */
|
||||
}
|
||||
282
src/errors.c
Normal file
282
src/errors.c
Normal file
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
}
|
||||
148
src/private-data.c
Normal file
148
src/private-data.c
Normal file
@@ -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;
|
||||
}
|
||||
36
src/utils.c
Normal file
36
src/utils.c
Normal file
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user