X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=src%2Fguestfs.c;h=e10463309bf625fae4b91d3903a82cf96da3ee2a;hb=0c2376a5c05053ce6a0479ade544be860c400fdb;hp=aa0aadbf26b4698c75060712934aec1796087a45;hpb=6941420efeefc48100a545806271af2de92dda26;p=libguestfs.git diff --git a/src/guestfs.c b/src/guestfs.c index aa0aadb..e104633 100644 --- a/src/guestfs.c +++ b/src/guestfs.c @@ -58,9 +58,10 @@ static void error (guestfs_h *g, const char *fs, ...); static void perrorf (guestfs_h *g, const char *fs, ...); -static void *safe_malloc (guestfs_h *g, int nbytes); +static void *safe_malloc (guestfs_h *g, size_t nbytes); static void *safe_realloc (guestfs_h *g, void *ptr, int nbytes); static char *safe_strdup (guestfs_h *g, const char *str); +static void *safe_memdup (guestfs_h *g, void *ptr, size_t size); static void default_error_cb (guestfs_h *g, void *data, const char *msg); static void stdout_event (void *data, int watch, int fd, int events); @@ -120,6 +121,8 @@ struct guestfs_h const char *path; + char *last_error; + /* Callbacks. */ guestfs_abort_cb abort_cb; guestfs_error_handler_cb error_cb; @@ -263,6 +266,7 @@ guestfs_close (guestfs_h *g) } /* release mutex (XXX) */ + free (g->last_error); free (g); } @@ -273,6 +277,19 @@ close_handles (void) while (handles) guestfs_close (handles); } +const char * +guestfs_last_error (guestfs_h *g) +{ + return g->last_error; +} + +static void +set_last_error (guestfs_h *g, const char *msg) +{ + free (g->last_error); + g->last_error = strdup (msg); +} + static void default_error_cb (guestfs_h *g, void *data, const char *msg) { @@ -285,13 +302,12 @@ error (guestfs_h *g, const char *fs, ...) va_list args; char *msg; - if (!g->error_cb) return; - va_start (args, fs); vasprintf (&msg, fs, args); va_end (args); - g->error_cb (g, g->error_cb_data, msg); + if (g->error_cb) g->error_cb (g, g->error_cb_data, msg); + set_last_error (g, msg); free (msg); } @@ -303,8 +319,6 @@ perrorf (guestfs_h *g, const char *fs, ...) char *msg; int err = errno; - if (!g->error_cb) return; - va_start (args, fs); vasprintf (&msg, fs, args); va_end (args); @@ -322,13 +336,14 @@ perrorf (guestfs_h *g, const char *fs, ...) strcat (msg, ": "); strcat (msg, buf); - g->error_cb (g, g->error_cb_data, msg); + if (g->error_cb) g->error_cb (g, g->error_cb_data, msg); + set_last_error (g, msg); free (msg); } static void * -safe_malloc (guestfs_h *g, int nbytes) +safe_malloc (guestfs_h *g, size_t nbytes) { void *ptr = malloc (nbytes); if (!ptr) g->abort_cb (); @@ -351,6 +366,15 @@ safe_strdup (guestfs_h *g, const char *str) return s; } +static void * +safe_memdup (guestfs_h *g, void *ptr, size_t size) +{ + void *p = malloc (size); + if (!p) g->abort_cb (); + memcpy (p, ptr, size); + return p; +} + void guestfs_set_out_of_memory_handler (guestfs_h *g, guestfs_abort_cb cb) { @@ -377,10 +401,11 @@ guestfs_get_error_handler (guestfs_h *g, void **data_rtn) return g->error_cb; } -void +int guestfs_set_verbose (guestfs_h *g, int v) { - g->verbose = v; + g->verbose = !!v; + return 0; } int @@ -389,10 +414,11 @@ guestfs_get_verbose (guestfs_h *g) return g->verbose; } -void +int guestfs_set_autosync (guestfs_h *g, int a) { - g->autosync = a; + g->autosync = !!a; + return 0; } int @@ -401,13 +427,14 @@ guestfs_get_autosync (guestfs_h *g) return g->autosync; } -void +int guestfs_set_path (guestfs_h *g, const char *path) { if (path == NULL) g->path = GUESTFS_DEFAULT_PATH; else g->path = path; + return 0; } const char * @@ -488,6 +515,11 @@ guestfs_add_drive (guestfs_h *g, const char *filename) return -1; } + if (access (filename, F_OK) == -1) { + perrorf (g, "%s", filename); + return -1; + } + snprintf (buf, len, "file=%s", filename); return guestfs_config (g, "-drive", buf); @@ -501,6 +533,11 @@ guestfs_add_cdrom (guestfs_h *g, const char *filename) return -1; } + if (access (filename, F_OK) == -1) { + perrorf (g, "%s", filename); + return -1; + } + return guestfs_config (g, "-cdrom", filename); } @@ -1009,6 +1046,28 @@ sock_read_event (void *data, int watch, int fd, int events) goto cleanup; } + /* Got the full message, begin processing it. */ + if (g->verbose) { + int i, j; + + for (i = 0; i < g->msg_in_size; i += 16) { + printf ("%04x: ", i); + for (j = i; j < MIN (i+16, g->msg_in_size); ++j) + printf ("%02x ", (unsigned char) g->msg_in[j]); + for (; j < i+16; ++j) + printf (" "); + printf ("|"); + for (j = i; j < MIN (i+16, g->msg_in_size); ++j) + if (isprint (g->msg_in[j])) + printf ("%c", g->msg_in[j]); + else + printf ("."); + for (; j < i+16; ++j) + printf (" "); + printf ("|\n"); + } + } + /* Not in the expected state. */ if (g->state != BUSY) error (g, "state %d != BUSY", g->state); @@ -1221,6 +1280,37 @@ check_reply_header (guestfs_h *g, */ #include "guestfs-actions.c" +/* 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); +} + /* This is the default main loop implementation, using select(2). */ struct handle_cb_data {