X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=src%2Fguestfs.c;h=f445adabcf073bb455517cb71470eae4eb7c4bcc;hb=4f3736162076419641a6225ac28b29d340020604;hp=5743a07181f9e4887f0e8589bd2725ac68d2bdbc;hpb=3d15f7e652340777514ff30c3cfc560a90b612ec;p=libguestfs.git diff --git a/src/guestfs.c b/src/guestfs.c index 5743a07..f445ada 100644 --- a/src/guestfs.c +++ b/src/guestfs.c @@ -1,5 +1,5 @@ /* libguestfs - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 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 @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -326,6 +327,25 @@ guestfs_close (guestfs_h *g) if (g->state != CONFIG) guestfs_kill_subprocess (g); + /* Close any sockets and deregister any handlers. */ + if (g->stdout_watch >= 0) + g->main_loop->remove_handle (g->main_loop, g, g->stdout_watch); + if (g->sock_watch >= 0) + g->main_loop->remove_handle (g->main_loop, g, g->sock_watch); + g->stdout_watch = -1; + g->sock_watch = -1; + + if (g->fd[0] >= 0) + close (g->fd[0]); + if (g->fd[1] >= 0) + close (g->fd[1]); + if (g->sock >= 0) + close (g->sock); + g->fd[0] = -1; + g->fd[1] = -1; + g->sock = -1; + + /* Remove tmpfiles. */ if (g->tmpdir) { snprintf (filename, sizeof filename, "%s/sock", g->tmpdir); unlink (filename); @@ -404,9 +424,11 @@ guestfs_error (guestfs_h *g, const char *fs, ...) char *msg; va_start (args, fs); - vasprintf (&msg, fs, args); + int err = vasprintf (&msg, fs, args); va_end (args); + if (err < 0) return; + if (g->error_cb) g->error_cb (g, g->error_cb_data, msg); set_last_error (g, msg); @@ -451,6 +473,42 @@ guestfs_safe_malloc (guestfs_h *g, size_t nbytes) 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. */ +#define HAVE_GNU_CALLOC (__GLIBC__ >= 2) + +/* 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, int nbytes) { @@ -628,6 +686,30 @@ guestfs_get_memsize (guestfs_h *g) return g->memsize; } +int +guestfs_get_pid (guestfs_h *g) +{ + if (g->pid > 0) + return g->pid; + else { + error (g, "get_pid: no qemu subprocess"); + return -1; + } +} + +struct guestfs_version * +guestfs_version (guestfs_h *g) +{ + struct guestfs_version *r; + + r = safe_malloc (g, sizeof *r); + r->major = PACKAGE_VERSION_MAJOR; + r->minor = PACKAGE_VERSION_MINOR; + r->release = PACKAGE_VERSION_RELEASE; + r->extra = safe_strdup (g, PACKAGE_VERSION_EXTRA); + return r; +} + /* Add a string to the current command line. */ static void incr_cmdline_size (guestfs_h *g) @@ -706,7 +788,7 @@ guestfs_add_drive (guestfs_h *g, const char *filename) } /* cache=off improves reliability in the event of a host crash. */ - snprintf (buf, len, "file=%s,cache=off", filename); + snprintf (buf, len, "file=%s,cache=off,if=%s", filename, DRIVE_IF); return guestfs_config (g, "-drive", buf); } @@ -727,7 +809,7 @@ guestfs_add_drive_ro (guestfs_h *g, const char *filename) return -1; } - snprintf (buf, len, "file=%s,snapshot=on", filename); + snprintf (buf, len, "file=%s,snapshot=on,if=%s", filename, DRIVE_IF); return guestfs_config (g, "-drive", buf); } @@ -1440,37 +1522,6 @@ guestfs_end_busy (guestfs_h *g) return 0; } -/* Structure-freeing functions. These rely on the fact that the - * structure format is identical to the XDR format. See note in - * generator.ml. - */ -void -guestfs_free_int_bool (struct guestfs_int_bool *x) -{ - free (x); -} - -void -guestfs_free_lvm_pv_list (struct guestfs_lvm_pv_list *x) -{ - xdr_free ((xdrproc_t) xdr_guestfs_lvm_int_pv_list, (char *) x); - free (x); -} - -void -guestfs_free_lvm_vg_list (struct guestfs_lvm_vg_list *x) -{ - xdr_free ((xdrproc_t) xdr_guestfs_lvm_int_vg_list, (char *) x); - free (x); -} - -void -guestfs_free_lvm_lv_list (struct guestfs_lvm_lv_list *x) -{ - xdr_free ((xdrproc_t) xdr_guestfs_lvm_int_lv_list, (char *) x); - free (x); -} - /* We don't know if stdout_event or sock_read_event will be the * first to receive EOF if the qemu process dies. This function * has the common cleanup code for both. @@ -2230,6 +2281,10 @@ guestfs__receive_file_sync (guestfs_h *g, const char *filename) char fbuf[4]; uint32_t flag = GUESTFS_CANCEL_FLAG; + if (g->verbose) + fprintf (stderr, "%s: waiting for daemon to acknowledge cancellation\n", + __func__); + xdrmem_create (&xdr, fbuf, sizeof fbuf, XDR_ENCODE); xdr_uint32_t (&xdr, &flag); xdr_destroy (&xdr);