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);
const char *path;
+ char *last_error;
+
/* Callbacks. */
guestfs_abort_cb abort_cb;
guestfs_error_handler_cb error_cb;
}
/* release mutex (XXX) */
+ free (g->last_error);
free (g);
}
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)
{
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);
}
char *msg;
int err = errno;
- if (!g->error_cb) return;
-
va_start (args, fs);
vasprintf (&msg, fs, args);
va_end (args);
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 ();
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)
{
return g->error_cb;
}
-void
+int
guestfs_set_verbose (guestfs_h *g, int v)
{
- g->verbose = v;
+ g->verbose = !!v;
+ return 0;
}
int
return g->verbose;
}
-void
+int
guestfs_set_autosync (guestfs_h *g, int a)
{
- g->autosync = a;
+ g->autosync = !!a;
+ return 0;
}
int
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 *
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);
return -1;
}
+ if (access (filename, F_OK) == -1) {
+ perrorf (g, "%s", filename);
+ return -1;
+ }
+
return guestfs_config (g, "-cdrom", filename);
}
guestfs_launch (guestfs_h *g)
{
static const char *dir_template = "/tmp/libguestfsXXXXXX";
- int r, i, len;
+ int r, i, len, pmore;
int wfd[2], rfd[2];
int tries;
const char *kernel_name = "vmlinuz." REPO "." host_cpu;
pelem = path = safe_strdup (g, g->path);
do {
pend = strchrnul (pelem, ':');
+ pmore = *pend == ':';
*pend = '\0';
len = pend - pelem;
kernel = initrd = NULL;
}
- pelem = pend;
- } while (*pelem++ != '\0');
+ pelem = pend + 1;
+ } while (pmore);
free (path);
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);
*/
#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 {