int guestfs_sfdisk_N (guestfs_h *g,
const char *device,
- int n,
+ int partnum,
int cyls,
int heads,
int sectors,
memset (&ctx, 0, sizeof ctx);
args.device = (char *) device;
- args.n = n;
+ args.partnum = partnum;
args.cyls = cyls;
args.heads = heads;
args.sectors = sectors;
return ctx.ret.partitions; /* caller will free */
}
+struct vg_activate_all_ctx {
+ /* This flag is set by the callbacks, so we know we've done
+ * the callbacks as expected, and in the right sequence.
+ * 0 = not called, 1 = reply_cb called.
+ */
+ int cb_sequence;
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+};
+
+static void vg_activate_all_reply_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ struct vg_activate_all_ctx *ctx = (struct vg_activate_all_ctx *) data;
+
+ /* This should definitely not happen. */
+ if (ctx->cb_sequence != 0) {
+ ctx->cb_sequence = 9999;
+ error (g, "%s: internal error: reply callback called twice", "guestfs_vg_activate_all");
+ return;
+ }
+
+ ml->main_loop_quit (ml, g);
+
+ if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
+ error (g, "%s: failed to parse reply header", "guestfs_vg_activate_all");
+ return;
+ }
+ if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
+ error (g, "%s: failed to parse reply error", "guestfs_vg_activate_all");
+ return;
+ }
+ goto done;
+ }
+ done:
+ ctx->cb_sequence = 1;
+}
+
+int guestfs_vg_activate_all (guestfs_h *g,
+ int activate)
+{
+ struct guestfs_vg_activate_all_args args;
+ struct vg_activate_all_ctx ctx;
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ int serial;
+
+ if (check_state (g, "guestfs_vg_activate_all") == -1) return -1;
+ guestfs_set_busy (g);
+
+ memset (&ctx, 0, sizeof ctx);
+
+ args.activate = activate;
+ serial = guestfs__send_sync (g, GUESTFS_PROC_VG_ACTIVATE_ALL,
+ (xdrproc_t) xdr_guestfs_vg_activate_all_args, (char *) &args);
+ if (serial == -1) {
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ guestfs__switch_to_receiving (g);
+ ctx.cb_sequence = 0;
+ guestfs_set_reply_callback (g, vg_activate_all_reply_cb, &ctx);
+ (void) ml->main_loop_run (ml, g);
+ guestfs_set_reply_callback (g, NULL, NULL);
+ if (ctx.cb_sequence != 1) {
+ error (g, "%s reply failed, see earlier error messages", "guestfs_vg_activate_all");
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_VG_ACTIVATE_ALL, serial) == -1) {
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", ctx.err.error_message);
+ free (ctx.err.error_message);
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ guestfs_end_busy (g);
+ return 0;
+}
+
+struct vg_activate_ctx {
+ /* This flag is set by the callbacks, so we know we've done
+ * the callbacks as expected, and in the right sequence.
+ * 0 = not called, 1 = reply_cb called.
+ */
+ int cb_sequence;
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+};
+
+static void vg_activate_reply_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ struct vg_activate_ctx *ctx = (struct vg_activate_ctx *) data;
+
+ /* This should definitely not happen. */
+ if (ctx->cb_sequence != 0) {
+ ctx->cb_sequence = 9999;
+ error (g, "%s: internal error: reply callback called twice", "guestfs_vg_activate");
+ return;
+ }
+
+ ml->main_loop_quit (ml, g);
+
+ if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
+ error (g, "%s: failed to parse reply header", "guestfs_vg_activate");
+ return;
+ }
+ if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
+ error (g, "%s: failed to parse reply error", "guestfs_vg_activate");
+ return;
+ }
+ goto done;
+ }
+ done:
+ ctx->cb_sequence = 1;
+}
+
+int guestfs_vg_activate (guestfs_h *g,
+ int activate,
+ char * const* const volgroups)
+{
+ struct guestfs_vg_activate_args args;
+ struct vg_activate_ctx ctx;
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ int serial;
+
+ if (check_state (g, "guestfs_vg_activate") == -1) return -1;
+ guestfs_set_busy (g);
+
+ memset (&ctx, 0, sizeof ctx);
+
+ args.activate = activate;
+ args.volgroups.volgroups_val = (char **) volgroups;
+ for (args.volgroups.volgroups_len = 0; volgroups[args.volgroups.volgroups_len]; args.volgroups.volgroups_len++) ;
+ serial = guestfs__send_sync (g, GUESTFS_PROC_VG_ACTIVATE,
+ (xdrproc_t) xdr_guestfs_vg_activate_args, (char *) &args);
+ if (serial == -1) {
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ guestfs__switch_to_receiving (g);
+ ctx.cb_sequence = 0;
+ guestfs_set_reply_callback (g, vg_activate_reply_cb, &ctx);
+ (void) ml->main_loop_run (ml, g);
+ guestfs_set_reply_callback (g, NULL, NULL);
+ if (ctx.cb_sequence != 1) {
+ error (g, "%s reply failed, see earlier error messages", "guestfs_vg_activate");
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_VG_ACTIVATE, serial) == -1) {
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", ctx.err.error_message);
+ free (ctx.err.error_message);
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ guestfs_end_busy (g);
+ return 0;
+}
+
+struct lvresize_ctx {
+ /* This flag is set by the callbacks, so we know we've done
+ * the callbacks as expected, and in the right sequence.
+ * 0 = not called, 1 = reply_cb called.
+ */
+ int cb_sequence;
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+};
+
+static void lvresize_reply_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ struct lvresize_ctx *ctx = (struct lvresize_ctx *) data;
+
+ /* This should definitely not happen. */
+ if (ctx->cb_sequence != 0) {
+ ctx->cb_sequence = 9999;
+ error (g, "%s: internal error: reply callback called twice", "guestfs_lvresize");
+ return;
+ }
+
+ ml->main_loop_quit (ml, g);
+
+ if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
+ error (g, "%s: failed to parse reply header", "guestfs_lvresize");
+ return;
+ }
+ if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
+ error (g, "%s: failed to parse reply error", "guestfs_lvresize");
+ return;
+ }
+ goto done;
+ }
+ done:
+ ctx->cb_sequence = 1;
+}
+
+int guestfs_lvresize (guestfs_h *g,
+ const char *device,
+ int mbytes)
+{
+ struct guestfs_lvresize_args args;
+ struct lvresize_ctx ctx;
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ int serial;
+
+ if (check_state (g, "guestfs_lvresize") == -1) return -1;
+ guestfs_set_busy (g);
+
+ memset (&ctx, 0, sizeof ctx);
+
+ args.device = (char *) device;
+ args.mbytes = mbytes;
+ serial = guestfs__send_sync (g, GUESTFS_PROC_LVRESIZE,
+ (xdrproc_t) xdr_guestfs_lvresize_args, (char *) &args);
+ if (serial == -1) {
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ guestfs__switch_to_receiving (g);
+ ctx.cb_sequence = 0;
+ guestfs_set_reply_callback (g, lvresize_reply_cb, &ctx);
+ (void) ml->main_loop_run (ml, g);
+ guestfs_set_reply_callback (g, NULL, NULL);
+ if (ctx.cb_sequence != 1) {
+ error (g, "%s reply failed, see earlier error messages", "guestfs_lvresize");
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LVRESIZE, serial) == -1) {
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", ctx.err.error_message);
+ free (ctx.err.error_message);
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ guestfs_end_busy (g);
+ return 0;
+}
+
+struct resize2fs_ctx {
+ /* This flag is set by the callbacks, so we know we've done
+ * the callbacks as expected, and in the right sequence.
+ * 0 = not called, 1 = reply_cb called.
+ */
+ int cb_sequence;
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+};
+
+static void resize2fs_reply_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ struct resize2fs_ctx *ctx = (struct resize2fs_ctx *) data;
+
+ /* This should definitely not happen. */
+ if (ctx->cb_sequence != 0) {
+ ctx->cb_sequence = 9999;
+ error (g, "%s: internal error: reply callback called twice", "guestfs_resize2fs");
+ return;
+ }
+
+ ml->main_loop_quit (ml, g);
+
+ if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
+ error (g, "%s: failed to parse reply header", "guestfs_resize2fs");
+ return;
+ }
+ if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
+ error (g, "%s: failed to parse reply error", "guestfs_resize2fs");
+ return;
+ }
+ goto done;
+ }
+ done:
+ ctx->cb_sequence = 1;
+}
+
+int guestfs_resize2fs (guestfs_h *g,
+ const char *device)
+{
+ struct guestfs_resize2fs_args args;
+ struct resize2fs_ctx ctx;
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ int serial;
+
+ if (check_state (g, "guestfs_resize2fs") == -1) return -1;
+ guestfs_set_busy (g);
+
+ memset (&ctx, 0, sizeof ctx);
+
+ args.device = (char *) device;
+ serial = guestfs__send_sync (g, GUESTFS_PROC_RESIZE2FS,
+ (xdrproc_t) xdr_guestfs_resize2fs_args, (char *) &args);
+ if (serial == -1) {
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ guestfs__switch_to_receiving (g);
+ ctx.cb_sequence = 0;
+ guestfs_set_reply_callback (g, resize2fs_reply_cb, &ctx);
+ (void) ml->main_loop_run (ml, g);
+ guestfs_set_reply_callback (g, NULL, NULL);
+ if (ctx.cb_sequence != 1) {
+ error (g, "%s reply failed, see earlier error messages", "guestfs_resize2fs");
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_RESIZE2FS, serial) == -1) {
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", ctx.err.error_message);
+ free (ctx.err.error_message);
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ guestfs_end_busy (g);
+ return 0;
+}
+
+struct find_ctx {
+ /* This flag is set by the callbacks, so we know we've done
+ * the callbacks as expected, and in the right sequence.
+ * 0 = not called, 1 = reply_cb called.
+ */
+ int cb_sequence;
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+ struct guestfs_find_ret ret;
+};
+
+static void find_reply_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ struct find_ctx *ctx = (struct find_ctx *) data;
+
+ /* This should definitely not happen. */
+ if (ctx->cb_sequence != 0) {
+ ctx->cb_sequence = 9999;
+ error (g, "%s: internal error: reply callback called twice", "guestfs_find");
+ return;
+ }
+
+ ml->main_loop_quit (ml, g);
+
+ if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
+ error (g, "%s: failed to parse reply header", "guestfs_find");
+ return;
+ }
+ if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
+ error (g, "%s: failed to parse reply error", "guestfs_find");
+ return;
+ }
+ goto done;
+ }
+ if (!xdr_guestfs_find_ret (xdr, &ctx->ret)) {
+ error (g, "%s: failed to parse reply", "guestfs_find");
+ return;
+ }
+ done:
+ ctx->cb_sequence = 1;
+}
+
+char **guestfs_find (guestfs_h *g,
+ const char *directory)
+{
+ struct guestfs_find_args args;
+ struct find_ctx ctx;
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ int serial;
+
+ if (check_state (g, "guestfs_find") == -1) return NULL;
+ guestfs_set_busy (g);
+
+ memset (&ctx, 0, sizeof ctx);
+
+ args.directory = (char *) directory;
+ serial = guestfs__send_sync (g, GUESTFS_PROC_FIND,
+ (xdrproc_t) xdr_guestfs_find_args, (char *) &args);
+ if (serial == -1) {
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ guestfs__switch_to_receiving (g);
+ ctx.cb_sequence = 0;
+ guestfs_set_reply_callback (g, find_reply_cb, &ctx);
+ (void) ml->main_loop_run (ml, g);
+ guestfs_set_reply_callback (g, NULL, NULL);
+ if (ctx.cb_sequence != 1) {
+ error (g, "%s reply failed, see earlier error messages", "guestfs_find");
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_FIND, serial) == -1) {
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", ctx.err.error_message);
+ free (ctx.err.error_message);
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ guestfs_end_busy (g);
+ /* caller will free this, but we need to add a NULL entry */
+ ctx.ret.names.names_val =
+ safe_realloc (g, ctx.ret.names.names_val,
+ sizeof (char *) * (ctx.ret.names.names_len + 1));
+ ctx.ret.names.names_val[ctx.ret.names.names_len] = NULL;
+ return ctx.ret.names.names_val;
+}
+
+struct e2fsck_f_ctx {
+ /* This flag is set by the callbacks, so we know we've done
+ * the callbacks as expected, and in the right sequence.
+ * 0 = not called, 1 = reply_cb called.
+ */
+ int cb_sequence;
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+};
+
+static void e2fsck_f_reply_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ struct e2fsck_f_ctx *ctx = (struct e2fsck_f_ctx *) data;
+
+ /* This should definitely not happen. */
+ if (ctx->cb_sequence != 0) {
+ ctx->cb_sequence = 9999;
+ error (g, "%s: internal error: reply callback called twice", "guestfs_e2fsck_f");
+ return;
+ }
+
+ ml->main_loop_quit (ml, g);
+
+ if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
+ error (g, "%s: failed to parse reply header", "guestfs_e2fsck_f");
+ return;
+ }
+ if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
+ error (g, "%s: failed to parse reply error", "guestfs_e2fsck_f");
+ return;
+ }
+ goto done;
+ }
+ done:
+ ctx->cb_sequence = 1;
+}
+
+int guestfs_e2fsck_f (guestfs_h *g,
+ const char *device)
+{
+ struct guestfs_e2fsck_f_args args;
+ struct e2fsck_f_ctx ctx;
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ int serial;
+
+ if (check_state (g, "guestfs_e2fsck_f") == -1) return -1;
+ guestfs_set_busy (g);
+
+ memset (&ctx, 0, sizeof ctx);
+
+ args.device = (char *) device;
+ serial = guestfs__send_sync (g, GUESTFS_PROC_E2FSCK_F,
+ (xdrproc_t) xdr_guestfs_e2fsck_f_args, (char *) &args);
+ if (serial == -1) {
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ guestfs__switch_to_receiving (g);
+ ctx.cb_sequence = 0;
+ guestfs_set_reply_callback (g, e2fsck_f_reply_cb, &ctx);
+ (void) ml->main_loop_run (ml, g);
+ guestfs_set_reply_callback (g, NULL, NULL);
+ if (ctx.cb_sequence != 1) {
+ error (g, "%s reply failed, see earlier error messages", "guestfs_e2fsck_f");
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_E2FSCK_F, serial) == -1) {
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", ctx.err.error_message);
+ free (ctx.err.error_message);
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ guestfs_end_busy (g);
+ return 0;
+}
+
+struct sleep_ctx {
+ /* This flag is set by the callbacks, so we know we've done
+ * the callbacks as expected, and in the right sequence.
+ * 0 = not called, 1 = reply_cb called.
+ */
+ int cb_sequence;
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+};
+
+static void sleep_reply_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ struct sleep_ctx *ctx = (struct sleep_ctx *) data;
+
+ /* This should definitely not happen. */
+ if (ctx->cb_sequence != 0) {
+ ctx->cb_sequence = 9999;
+ error (g, "%s: internal error: reply callback called twice", "guestfs_sleep");
+ return;
+ }
+
+ ml->main_loop_quit (ml, g);
+
+ if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
+ error (g, "%s: failed to parse reply header", "guestfs_sleep");
+ return;
+ }
+ if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
+ error (g, "%s: failed to parse reply error", "guestfs_sleep");
+ return;
+ }
+ goto done;
+ }
+ done:
+ ctx->cb_sequence = 1;
+}
+
+int guestfs_sleep (guestfs_h *g,
+ int secs)
+{
+ struct guestfs_sleep_args args;
+ struct sleep_ctx ctx;
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ int serial;
+
+ if (check_state (g, "guestfs_sleep") == -1) return -1;
+ guestfs_set_busy (g);
+
+ memset (&ctx, 0, sizeof ctx);
+
+ args.secs = secs;
+ serial = guestfs__send_sync (g, GUESTFS_PROC_SLEEP,
+ (xdrproc_t) xdr_guestfs_sleep_args, (char *) &args);
+ if (serial == -1) {
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ guestfs__switch_to_receiving (g);
+ ctx.cb_sequence = 0;
+ guestfs_set_reply_callback (g, sleep_reply_cb, &ctx);
+ (void) ml->main_loop_run (ml, g);
+ guestfs_set_reply_callback (g, NULL, NULL);
+ if (ctx.cb_sequence != 1) {
+ error (g, "%s reply failed, see earlier error messages", "guestfs_sleep");
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_SLEEP, serial) == -1) {
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", ctx.err.error_message);
+ free (ctx.err.error_message);
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ guestfs_end_busy (g);
+ return 0;
+}
+
+struct ntfs_3g_probe_ctx {
+ /* This flag is set by the callbacks, so we know we've done
+ * the callbacks as expected, and in the right sequence.
+ * 0 = not called, 1 = reply_cb called.
+ */
+ int cb_sequence;
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+ struct guestfs_ntfs_3g_probe_ret ret;
+};
+
+static void ntfs_3g_probe_reply_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ struct ntfs_3g_probe_ctx *ctx = (struct ntfs_3g_probe_ctx *) data;
+
+ /* This should definitely not happen. */
+ if (ctx->cb_sequence != 0) {
+ ctx->cb_sequence = 9999;
+ error (g, "%s: internal error: reply callback called twice", "guestfs_ntfs_3g_probe");
+ return;
+ }
+
+ ml->main_loop_quit (ml, g);
+
+ if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
+ error (g, "%s: failed to parse reply header", "guestfs_ntfs_3g_probe");
+ return;
+ }
+ if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
+ error (g, "%s: failed to parse reply error", "guestfs_ntfs_3g_probe");
+ return;
+ }
+ goto done;
+ }
+ if (!xdr_guestfs_ntfs_3g_probe_ret (xdr, &ctx->ret)) {
+ error (g, "%s: failed to parse reply", "guestfs_ntfs_3g_probe");
+ return;
+ }
+ done:
+ ctx->cb_sequence = 1;
+}
+
+int guestfs_ntfs_3g_probe (guestfs_h *g,
+ int rw,
+ const char *device)
+{
+ struct guestfs_ntfs_3g_probe_args args;
+ struct ntfs_3g_probe_ctx ctx;
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ int serial;
+
+ if (check_state (g, "guestfs_ntfs_3g_probe") == -1) return -1;
+ guestfs_set_busy (g);
+
+ memset (&ctx, 0, sizeof ctx);
+
+ args.rw = rw;
+ args.device = (char *) device;
+ serial = guestfs__send_sync (g, GUESTFS_PROC_NTFS_3G_PROBE,
+ (xdrproc_t) xdr_guestfs_ntfs_3g_probe_args, (char *) &args);
+ if (serial == -1) {
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ guestfs__switch_to_receiving (g);
+ ctx.cb_sequence = 0;
+ guestfs_set_reply_callback (g, ntfs_3g_probe_reply_cb, &ctx);
+ (void) ml->main_loop_run (ml, g);
+ guestfs_set_reply_callback (g, NULL, NULL);
+ if (ctx.cb_sequence != 1) {
+ error (g, "%s reply failed, see earlier error messages", "guestfs_ntfs_3g_probe");
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_NTFS_3G_PROBE, serial) == -1) {
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", ctx.err.error_message);
+ free (ctx.err.error_message);
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ guestfs_end_busy (g);
+ return ctx.ret.status;
+}
+
+struct sh_ctx {
+ /* This flag is set by the callbacks, so we know we've done
+ * the callbacks as expected, and in the right sequence.
+ * 0 = not called, 1 = reply_cb called.
+ */
+ int cb_sequence;
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+ struct guestfs_sh_ret ret;
+};
+
+static void sh_reply_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ struct sh_ctx *ctx = (struct sh_ctx *) data;
+
+ /* This should definitely not happen. */
+ if (ctx->cb_sequence != 0) {
+ ctx->cb_sequence = 9999;
+ error (g, "%s: internal error: reply callback called twice", "guestfs_sh");
+ return;
+ }
+
+ ml->main_loop_quit (ml, g);
+
+ if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
+ error (g, "%s: failed to parse reply header", "guestfs_sh");
+ return;
+ }
+ if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
+ error (g, "%s: failed to parse reply error", "guestfs_sh");
+ return;
+ }
+ goto done;
+ }
+ if (!xdr_guestfs_sh_ret (xdr, &ctx->ret)) {
+ error (g, "%s: failed to parse reply", "guestfs_sh");
+ return;
+ }
+ done:
+ ctx->cb_sequence = 1;
+}
+
+char *guestfs_sh (guestfs_h *g,
+ const char *command)
+{
+ struct guestfs_sh_args args;
+ struct sh_ctx ctx;
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ int serial;
+
+ if (check_state (g, "guestfs_sh") == -1) return NULL;
+ guestfs_set_busy (g);
+
+ memset (&ctx, 0, sizeof ctx);
+
+ args.command = (char *) command;
+ serial = guestfs__send_sync (g, GUESTFS_PROC_SH,
+ (xdrproc_t) xdr_guestfs_sh_args, (char *) &args);
+ if (serial == -1) {
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ guestfs__switch_to_receiving (g);
+ ctx.cb_sequence = 0;
+ guestfs_set_reply_callback (g, sh_reply_cb, &ctx);
+ (void) ml->main_loop_run (ml, g);
+ guestfs_set_reply_callback (g, NULL, NULL);
+ if (ctx.cb_sequence != 1) {
+ error (g, "%s reply failed, see earlier error messages", "guestfs_sh");
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_SH, serial) == -1) {
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", ctx.err.error_message);
+ free (ctx.err.error_message);
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ guestfs_end_busy (g);
+ return ctx.ret.output; /* caller will free */
+}
+
+struct sh_lines_ctx {
+ /* This flag is set by the callbacks, so we know we've done
+ * the callbacks as expected, and in the right sequence.
+ * 0 = not called, 1 = reply_cb called.
+ */
+ int cb_sequence;
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+ struct guestfs_sh_lines_ret ret;
+};
+
+static void sh_lines_reply_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ struct sh_lines_ctx *ctx = (struct sh_lines_ctx *) data;
+
+ /* This should definitely not happen. */
+ if (ctx->cb_sequence != 0) {
+ ctx->cb_sequence = 9999;
+ error (g, "%s: internal error: reply callback called twice", "guestfs_sh_lines");
+ return;
+ }
+
+ ml->main_loop_quit (ml, g);
+
+ if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
+ error (g, "%s: failed to parse reply header", "guestfs_sh_lines");
+ return;
+ }
+ if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
+ error (g, "%s: failed to parse reply error", "guestfs_sh_lines");
+ return;
+ }
+ goto done;
+ }
+ if (!xdr_guestfs_sh_lines_ret (xdr, &ctx->ret)) {
+ error (g, "%s: failed to parse reply", "guestfs_sh_lines");
+ return;
+ }
+ done:
+ ctx->cb_sequence = 1;
+}
+
+char **guestfs_sh_lines (guestfs_h *g,
+ const char *command)
+{
+ struct guestfs_sh_lines_args args;
+ struct sh_lines_ctx ctx;
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ int serial;
+
+ if (check_state (g, "guestfs_sh_lines") == -1) return NULL;
+ guestfs_set_busy (g);
+
+ memset (&ctx, 0, sizeof ctx);
+
+ args.command = (char *) command;
+ serial = guestfs__send_sync (g, GUESTFS_PROC_SH_LINES,
+ (xdrproc_t) xdr_guestfs_sh_lines_args, (char *) &args);
+ if (serial == -1) {
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ guestfs__switch_to_receiving (g);
+ ctx.cb_sequence = 0;
+ guestfs_set_reply_callback (g, sh_lines_reply_cb, &ctx);
+ (void) ml->main_loop_run (ml, g);
+ guestfs_set_reply_callback (g, NULL, NULL);
+ if (ctx.cb_sequence != 1) {
+ error (g, "%s reply failed, see earlier error messages", "guestfs_sh_lines");
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_SH_LINES, serial) == -1) {
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", ctx.err.error_message);
+ free (ctx.err.error_message);
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ guestfs_end_busy (g);
+ /* caller will free this, but we need to add a NULL entry */
+ ctx.ret.lines.lines_val =
+ safe_realloc (g, ctx.ret.lines.lines_val,
+ sizeof (char *) * (ctx.ret.lines.lines_len + 1));
+ ctx.ret.lines.lines_val[ctx.ret.lines.lines_len] = NULL;
+ return ctx.ret.lines.lines_val;
+}
+
+struct glob_expand_ctx {
+ /* This flag is set by the callbacks, so we know we've done
+ * the callbacks as expected, and in the right sequence.
+ * 0 = not called, 1 = reply_cb called.
+ */
+ int cb_sequence;
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+ struct guestfs_glob_expand_ret ret;
+};
+
+static void glob_expand_reply_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ struct glob_expand_ctx *ctx = (struct glob_expand_ctx *) data;
+
+ /* This should definitely not happen. */
+ if (ctx->cb_sequence != 0) {
+ ctx->cb_sequence = 9999;
+ error (g, "%s: internal error: reply callback called twice", "guestfs_glob_expand");
+ return;
+ }
+
+ ml->main_loop_quit (ml, g);
+
+ if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
+ error (g, "%s: failed to parse reply header", "guestfs_glob_expand");
+ return;
+ }
+ if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
+ error (g, "%s: failed to parse reply error", "guestfs_glob_expand");
+ return;
+ }
+ goto done;
+ }
+ if (!xdr_guestfs_glob_expand_ret (xdr, &ctx->ret)) {
+ error (g, "%s: failed to parse reply", "guestfs_glob_expand");
+ return;
+ }
+ done:
+ ctx->cb_sequence = 1;
+}
+
+char **guestfs_glob_expand (guestfs_h *g,
+ const char *pattern)
+{
+ struct guestfs_glob_expand_args args;
+ struct glob_expand_ctx ctx;
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ int serial;
+
+ if (check_state (g, "guestfs_glob_expand") == -1) return NULL;
+ guestfs_set_busy (g);
+
+ memset (&ctx, 0, sizeof ctx);
+
+ args.pattern = (char *) pattern;
+ serial = guestfs__send_sync (g, GUESTFS_PROC_GLOB_EXPAND,
+ (xdrproc_t) xdr_guestfs_glob_expand_args, (char *) &args);
+ if (serial == -1) {
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ guestfs__switch_to_receiving (g);
+ ctx.cb_sequence = 0;
+ guestfs_set_reply_callback (g, glob_expand_reply_cb, &ctx);
+ (void) ml->main_loop_run (ml, g);
+ guestfs_set_reply_callback (g, NULL, NULL);
+ if (ctx.cb_sequence != 1) {
+ error (g, "%s reply failed, see earlier error messages", "guestfs_glob_expand");
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_GLOB_EXPAND, serial) == -1) {
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", ctx.err.error_message);
+ free (ctx.err.error_message);
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ guestfs_end_busy (g);
+ /* caller will free this, but we need to add a NULL entry */
+ ctx.ret.paths.paths_val =
+ safe_realloc (g, ctx.ret.paths.paths_val,
+ sizeof (char *) * (ctx.ret.paths.paths_len + 1));
+ ctx.ret.paths.paths_val[ctx.ret.paths.paths_len] = NULL;
+ return ctx.ret.paths.paths_val;
+}
+
+struct scrub_device_ctx {
+ /* This flag is set by the callbacks, so we know we've done
+ * the callbacks as expected, and in the right sequence.
+ * 0 = not called, 1 = reply_cb called.
+ */
+ int cb_sequence;
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+};
+
+static void scrub_device_reply_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ struct scrub_device_ctx *ctx = (struct scrub_device_ctx *) data;
+
+ /* This should definitely not happen. */
+ if (ctx->cb_sequence != 0) {
+ ctx->cb_sequence = 9999;
+ error (g, "%s: internal error: reply callback called twice", "guestfs_scrub_device");
+ return;
+ }
+
+ ml->main_loop_quit (ml, g);
+
+ if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
+ error (g, "%s: failed to parse reply header", "guestfs_scrub_device");
+ return;
+ }
+ if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
+ error (g, "%s: failed to parse reply error", "guestfs_scrub_device");
+ return;
+ }
+ goto done;
+ }
+ done:
+ ctx->cb_sequence = 1;
+}
+
+int guestfs_scrub_device (guestfs_h *g,
+ const char *device)
+{
+ struct guestfs_scrub_device_args args;
+ struct scrub_device_ctx ctx;
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ int serial;
+
+ if (check_state (g, "guestfs_scrub_device") == -1) return -1;
+ guestfs_set_busy (g);
+
+ memset (&ctx, 0, sizeof ctx);
+
+ args.device = (char *) device;
+ serial = guestfs__send_sync (g, GUESTFS_PROC_SCRUB_DEVICE,
+ (xdrproc_t) xdr_guestfs_scrub_device_args, (char *) &args);
+ if (serial == -1) {
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ guestfs__switch_to_receiving (g);
+ ctx.cb_sequence = 0;
+ guestfs_set_reply_callback (g, scrub_device_reply_cb, &ctx);
+ (void) ml->main_loop_run (ml, g);
+ guestfs_set_reply_callback (g, NULL, NULL);
+ if (ctx.cb_sequence != 1) {
+ error (g, "%s reply failed, see earlier error messages", "guestfs_scrub_device");
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_SCRUB_DEVICE, serial) == -1) {
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", ctx.err.error_message);
+ free (ctx.err.error_message);
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ guestfs_end_busy (g);
+ return 0;
+}
+
+struct scrub_file_ctx {
+ /* This flag is set by the callbacks, so we know we've done
+ * the callbacks as expected, and in the right sequence.
+ * 0 = not called, 1 = reply_cb called.
+ */
+ int cb_sequence;
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+};
+
+static void scrub_file_reply_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ struct scrub_file_ctx *ctx = (struct scrub_file_ctx *) data;
+
+ /* This should definitely not happen. */
+ if (ctx->cb_sequence != 0) {
+ ctx->cb_sequence = 9999;
+ error (g, "%s: internal error: reply callback called twice", "guestfs_scrub_file");
+ return;
+ }
+
+ ml->main_loop_quit (ml, g);
+
+ if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
+ error (g, "%s: failed to parse reply header", "guestfs_scrub_file");
+ return;
+ }
+ if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
+ error (g, "%s: failed to parse reply error", "guestfs_scrub_file");
+ return;
+ }
+ goto done;
+ }
+ done:
+ ctx->cb_sequence = 1;
+}
+
+int guestfs_scrub_file (guestfs_h *g,
+ const char *file)
+{
+ struct guestfs_scrub_file_args args;
+ struct scrub_file_ctx ctx;
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ int serial;
+
+ if (check_state (g, "guestfs_scrub_file") == -1) return -1;
+ guestfs_set_busy (g);
+
+ memset (&ctx, 0, sizeof ctx);
+
+ args.file = (char *) file;
+ serial = guestfs__send_sync (g, GUESTFS_PROC_SCRUB_FILE,
+ (xdrproc_t) xdr_guestfs_scrub_file_args, (char *) &args);
+ if (serial == -1) {
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ guestfs__switch_to_receiving (g);
+ ctx.cb_sequence = 0;
+ guestfs_set_reply_callback (g, scrub_file_reply_cb, &ctx);
+ (void) ml->main_loop_run (ml, g);
+ guestfs_set_reply_callback (g, NULL, NULL);
+ if (ctx.cb_sequence != 1) {
+ error (g, "%s reply failed, see earlier error messages", "guestfs_scrub_file");
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_SCRUB_FILE, serial) == -1) {
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", ctx.err.error_message);
+ free (ctx.err.error_message);
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ guestfs_end_busy (g);
+ return 0;
+}
+
+struct scrub_freespace_ctx {
+ /* This flag is set by the callbacks, so we know we've done
+ * the callbacks as expected, and in the right sequence.
+ * 0 = not called, 1 = reply_cb called.
+ */
+ int cb_sequence;
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+};
+
+static void scrub_freespace_reply_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ struct scrub_freespace_ctx *ctx = (struct scrub_freespace_ctx *) data;
+
+ /* This should definitely not happen. */
+ if (ctx->cb_sequence != 0) {
+ ctx->cb_sequence = 9999;
+ error (g, "%s: internal error: reply callback called twice", "guestfs_scrub_freespace");
+ return;
+ }
+
+ ml->main_loop_quit (ml, g);
+
+ if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
+ error (g, "%s: failed to parse reply header", "guestfs_scrub_freespace");
+ return;
+ }
+ if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
+ error (g, "%s: failed to parse reply error", "guestfs_scrub_freespace");
+ return;
+ }
+ goto done;
+ }
+ done:
+ ctx->cb_sequence = 1;
+}
+
+int guestfs_scrub_freespace (guestfs_h *g,
+ const char *dir)
+{
+ struct guestfs_scrub_freespace_args args;
+ struct scrub_freespace_ctx ctx;
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ int serial;
+
+ if (check_state (g, "guestfs_scrub_freespace") == -1) return -1;
+ guestfs_set_busy (g);
+
+ memset (&ctx, 0, sizeof ctx);
+
+ args.dir = (char *) dir;
+ serial = guestfs__send_sync (g, GUESTFS_PROC_SCRUB_FREESPACE,
+ (xdrproc_t) xdr_guestfs_scrub_freespace_args, (char *) &args);
+ if (serial == -1) {
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ guestfs__switch_to_receiving (g);
+ ctx.cb_sequence = 0;
+ guestfs_set_reply_callback (g, scrub_freespace_reply_cb, &ctx);
+ (void) ml->main_loop_run (ml, g);
+ guestfs_set_reply_callback (g, NULL, NULL);
+ if (ctx.cb_sequence != 1) {
+ error (g, "%s reply failed, see earlier error messages", "guestfs_scrub_freespace");
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_SCRUB_FREESPACE, serial) == -1) {
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", ctx.err.error_message);
+ free (ctx.err.error_message);
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ guestfs_end_busy (g);
+ return 0;
+}
+
+struct mkdtemp_ctx {
+ /* This flag is set by the callbacks, so we know we've done
+ * the callbacks as expected, and in the right sequence.
+ * 0 = not called, 1 = reply_cb called.
+ */
+ int cb_sequence;
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+ struct guestfs_mkdtemp_ret ret;
+};
+
+static void mkdtemp_reply_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ struct mkdtemp_ctx *ctx = (struct mkdtemp_ctx *) data;
+
+ /* This should definitely not happen. */
+ if (ctx->cb_sequence != 0) {
+ ctx->cb_sequence = 9999;
+ error (g, "%s: internal error: reply callback called twice", "guestfs_mkdtemp");
+ return;
+ }
+
+ ml->main_loop_quit (ml, g);
+
+ if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
+ error (g, "%s: failed to parse reply header", "guestfs_mkdtemp");
+ return;
+ }
+ if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
+ error (g, "%s: failed to parse reply error", "guestfs_mkdtemp");
+ return;
+ }
+ goto done;
+ }
+ if (!xdr_guestfs_mkdtemp_ret (xdr, &ctx->ret)) {
+ error (g, "%s: failed to parse reply", "guestfs_mkdtemp");
+ return;
+ }
+ done:
+ ctx->cb_sequence = 1;
+}
+
+char *guestfs_mkdtemp (guestfs_h *g,
+ const char *template)
+{
+ struct guestfs_mkdtemp_args args;
+ struct mkdtemp_ctx ctx;
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ int serial;
+
+ if (check_state (g, "guestfs_mkdtemp") == -1) return NULL;
+ guestfs_set_busy (g);
+
+ memset (&ctx, 0, sizeof ctx);
+
+ args.template = (char *) template;
+ serial = guestfs__send_sync (g, GUESTFS_PROC_MKDTEMP,
+ (xdrproc_t) xdr_guestfs_mkdtemp_args, (char *) &args);
+ if (serial == -1) {
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ guestfs__switch_to_receiving (g);
+ ctx.cb_sequence = 0;
+ guestfs_set_reply_callback (g, mkdtemp_reply_cb, &ctx);
+ (void) ml->main_loop_run (ml, g);
+ guestfs_set_reply_callback (g, NULL, NULL);
+ if (ctx.cb_sequence != 1) {
+ error (g, "%s reply failed, see earlier error messages", "guestfs_mkdtemp");
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MKDTEMP, serial) == -1) {
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", ctx.err.error_message);
+ free (ctx.err.error_message);
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ guestfs_end_busy (g);
+ return ctx.ret.dir; /* caller will free */
+}
+
+struct wc_l_ctx {
+ /* This flag is set by the callbacks, so we know we've done
+ * the callbacks as expected, and in the right sequence.
+ * 0 = not called, 1 = reply_cb called.
+ */
+ int cb_sequence;
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+ struct guestfs_wc_l_ret ret;
+};
+
+static void wc_l_reply_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ struct wc_l_ctx *ctx = (struct wc_l_ctx *) data;
+
+ /* This should definitely not happen. */
+ if (ctx->cb_sequence != 0) {
+ ctx->cb_sequence = 9999;
+ error (g, "%s: internal error: reply callback called twice", "guestfs_wc_l");
+ return;
+ }
+
+ ml->main_loop_quit (ml, g);
+
+ if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
+ error (g, "%s: failed to parse reply header", "guestfs_wc_l");
+ return;
+ }
+ if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
+ error (g, "%s: failed to parse reply error", "guestfs_wc_l");
+ return;
+ }
+ goto done;
+ }
+ if (!xdr_guestfs_wc_l_ret (xdr, &ctx->ret)) {
+ error (g, "%s: failed to parse reply", "guestfs_wc_l");
+ return;
+ }
+ done:
+ ctx->cb_sequence = 1;
+}
+
+int guestfs_wc_l (guestfs_h *g,
+ const char *path)
+{
+ struct guestfs_wc_l_args args;
+ struct wc_l_ctx ctx;
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ int serial;
+
+ if (check_state (g, "guestfs_wc_l") == -1) return -1;
+ guestfs_set_busy (g);
+
+ memset (&ctx, 0, sizeof ctx);
+
+ args.path = (char *) path;
+ serial = guestfs__send_sync (g, GUESTFS_PROC_WC_L,
+ (xdrproc_t) xdr_guestfs_wc_l_args, (char *) &args);
+ if (serial == -1) {
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ guestfs__switch_to_receiving (g);
+ ctx.cb_sequence = 0;
+ guestfs_set_reply_callback (g, wc_l_reply_cb, &ctx);
+ (void) ml->main_loop_run (ml, g);
+ guestfs_set_reply_callback (g, NULL, NULL);
+ if (ctx.cb_sequence != 1) {
+ error (g, "%s reply failed, see earlier error messages", "guestfs_wc_l");
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_WC_L, serial) == -1) {
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", ctx.err.error_message);
+ free (ctx.err.error_message);
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ guestfs_end_busy (g);
+ return ctx.ret.lines;
+}
+
+struct wc_w_ctx {
+ /* This flag is set by the callbacks, so we know we've done
+ * the callbacks as expected, and in the right sequence.
+ * 0 = not called, 1 = reply_cb called.
+ */
+ int cb_sequence;
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+ struct guestfs_wc_w_ret ret;
+};
+
+static void wc_w_reply_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ struct wc_w_ctx *ctx = (struct wc_w_ctx *) data;
+
+ /* This should definitely not happen. */
+ if (ctx->cb_sequence != 0) {
+ ctx->cb_sequence = 9999;
+ error (g, "%s: internal error: reply callback called twice", "guestfs_wc_w");
+ return;
+ }
+
+ ml->main_loop_quit (ml, g);
+
+ if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
+ error (g, "%s: failed to parse reply header", "guestfs_wc_w");
+ return;
+ }
+ if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
+ error (g, "%s: failed to parse reply error", "guestfs_wc_w");
+ return;
+ }
+ goto done;
+ }
+ if (!xdr_guestfs_wc_w_ret (xdr, &ctx->ret)) {
+ error (g, "%s: failed to parse reply", "guestfs_wc_w");
+ return;
+ }
+ done:
+ ctx->cb_sequence = 1;
+}
+
+int guestfs_wc_w (guestfs_h *g,
+ const char *path)
+{
+ struct guestfs_wc_w_args args;
+ struct wc_w_ctx ctx;
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ int serial;
+
+ if (check_state (g, "guestfs_wc_w") == -1) return -1;
+ guestfs_set_busy (g);
+
+ memset (&ctx, 0, sizeof ctx);
+
+ args.path = (char *) path;
+ serial = guestfs__send_sync (g, GUESTFS_PROC_WC_W,
+ (xdrproc_t) xdr_guestfs_wc_w_args, (char *) &args);
+ if (serial == -1) {
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ guestfs__switch_to_receiving (g);
+ ctx.cb_sequence = 0;
+ guestfs_set_reply_callback (g, wc_w_reply_cb, &ctx);
+ (void) ml->main_loop_run (ml, g);
+ guestfs_set_reply_callback (g, NULL, NULL);
+ if (ctx.cb_sequence != 1) {
+ error (g, "%s reply failed, see earlier error messages", "guestfs_wc_w");
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_WC_W, serial) == -1) {
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", ctx.err.error_message);
+ free (ctx.err.error_message);
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ guestfs_end_busy (g);
+ return ctx.ret.words;
+}
+
+struct wc_c_ctx {
+ /* This flag is set by the callbacks, so we know we've done
+ * the callbacks as expected, and in the right sequence.
+ * 0 = not called, 1 = reply_cb called.
+ */
+ int cb_sequence;
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+ struct guestfs_wc_c_ret ret;
+};
+
+static void wc_c_reply_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ struct wc_c_ctx *ctx = (struct wc_c_ctx *) data;
+
+ /* This should definitely not happen. */
+ if (ctx->cb_sequence != 0) {
+ ctx->cb_sequence = 9999;
+ error (g, "%s: internal error: reply callback called twice", "guestfs_wc_c");
+ return;
+ }
+
+ ml->main_loop_quit (ml, g);
+
+ if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
+ error (g, "%s: failed to parse reply header", "guestfs_wc_c");
+ return;
+ }
+ if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
+ error (g, "%s: failed to parse reply error", "guestfs_wc_c");
+ return;
+ }
+ goto done;
+ }
+ if (!xdr_guestfs_wc_c_ret (xdr, &ctx->ret)) {
+ error (g, "%s: failed to parse reply", "guestfs_wc_c");
+ return;
+ }
+ done:
+ ctx->cb_sequence = 1;
+}
+
+int guestfs_wc_c (guestfs_h *g,
+ const char *path)
+{
+ struct guestfs_wc_c_args args;
+ struct wc_c_ctx ctx;
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ int serial;
+
+ if (check_state (g, "guestfs_wc_c") == -1) return -1;
+ guestfs_set_busy (g);
+
+ memset (&ctx, 0, sizeof ctx);
+
+ args.path = (char *) path;
+ serial = guestfs__send_sync (g, GUESTFS_PROC_WC_C,
+ (xdrproc_t) xdr_guestfs_wc_c_args, (char *) &args);
+ if (serial == -1) {
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ guestfs__switch_to_receiving (g);
+ ctx.cb_sequence = 0;
+ guestfs_set_reply_callback (g, wc_c_reply_cb, &ctx);
+ (void) ml->main_loop_run (ml, g);
+ guestfs_set_reply_callback (g, NULL, NULL);
+ if (ctx.cb_sequence != 1) {
+ error (g, "%s reply failed, see earlier error messages", "guestfs_wc_c");
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_WC_C, serial) == -1) {
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", ctx.err.error_message);
+ free (ctx.err.error_message);
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ guestfs_end_busy (g);
+ return ctx.ret.chars;
+}
+
+struct head_ctx {
+ /* This flag is set by the callbacks, so we know we've done
+ * the callbacks as expected, and in the right sequence.
+ * 0 = not called, 1 = reply_cb called.
+ */
+ int cb_sequence;
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+ struct guestfs_head_ret ret;
+};
+
+static void head_reply_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ struct head_ctx *ctx = (struct head_ctx *) data;
+
+ /* This should definitely not happen. */
+ if (ctx->cb_sequence != 0) {
+ ctx->cb_sequence = 9999;
+ error (g, "%s: internal error: reply callback called twice", "guestfs_head");
+ return;
+ }
+
+ ml->main_loop_quit (ml, g);
+
+ if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
+ error (g, "%s: failed to parse reply header", "guestfs_head");
+ return;
+ }
+ if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
+ error (g, "%s: failed to parse reply error", "guestfs_head");
+ return;
+ }
+ goto done;
+ }
+ if (!xdr_guestfs_head_ret (xdr, &ctx->ret)) {
+ error (g, "%s: failed to parse reply", "guestfs_head");
+ return;
+ }
+ done:
+ ctx->cb_sequence = 1;
+}
+
+char **guestfs_head (guestfs_h *g,
+ const char *path)
+{
+ struct guestfs_head_args args;
+ struct head_ctx ctx;
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ int serial;
+
+ if (check_state (g, "guestfs_head") == -1) return NULL;
+ guestfs_set_busy (g);
+
+ memset (&ctx, 0, sizeof ctx);
+
+ args.path = (char *) path;
+ serial = guestfs__send_sync (g, GUESTFS_PROC_HEAD,
+ (xdrproc_t) xdr_guestfs_head_args, (char *) &args);
+ if (serial == -1) {
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ guestfs__switch_to_receiving (g);
+ ctx.cb_sequence = 0;
+ guestfs_set_reply_callback (g, head_reply_cb, &ctx);
+ (void) ml->main_loop_run (ml, g);
+ guestfs_set_reply_callback (g, NULL, NULL);
+ if (ctx.cb_sequence != 1) {
+ error (g, "%s reply failed, see earlier error messages", "guestfs_head");
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_HEAD, serial) == -1) {
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", ctx.err.error_message);
+ free (ctx.err.error_message);
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ guestfs_end_busy (g);
+ /* caller will free this, but we need to add a NULL entry */
+ ctx.ret.lines.lines_val =
+ safe_realloc (g, ctx.ret.lines.lines_val,
+ sizeof (char *) * (ctx.ret.lines.lines_len + 1));
+ ctx.ret.lines.lines_val[ctx.ret.lines.lines_len] = NULL;
+ return ctx.ret.lines.lines_val;
+}
+
+struct head_n_ctx {
+ /* This flag is set by the callbacks, so we know we've done
+ * the callbacks as expected, and in the right sequence.
+ * 0 = not called, 1 = reply_cb called.
+ */
+ int cb_sequence;
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+ struct guestfs_head_n_ret ret;
+};
+
+static void head_n_reply_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ struct head_n_ctx *ctx = (struct head_n_ctx *) data;
+
+ /* This should definitely not happen. */
+ if (ctx->cb_sequence != 0) {
+ ctx->cb_sequence = 9999;
+ error (g, "%s: internal error: reply callback called twice", "guestfs_head_n");
+ return;
+ }
+
+ ml->main_loop_quit (ml, g);
+
+ if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
+ error (g, "%s: failed to parse reply header", "guestfs_head_n");
+ return;
+ }
+ if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
+ error (g, "%s: failed to parse reply error", "guestfs_head_n");
+ return;
+ }
+ goto done;
+ }
+ if (!xdr_guestfs_head_n_ret (xdr, &ctx->ret)) {
+ error (g, "%s: failed to parse reply", "guestfs_head_n");
+ return;
+ }
+ done:
+ ctx->cb_sequence = 1;
+}
+
+char **guestfs_head_n (guestfs_h *g,
+ int nrlines,
+ const char *path)
+{
+ struct guestfs_head_n_args args;
+ struct head_n_ctx ctx;
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ int serial;
+
+ if (check_state (g, "guestfs_head_n") == -1) return NULL;
+ guestfs_set_busy (g);
+
+ memset (&ctx, 0, sizeof ctx);
+
+ args.nrlines = nrlines;
+ args.path = (char *) path;
+ serial = guestfs__send_sync (g, GUESTFS_PROC_HEAD_N,
+ (xdrproc_t) xdr_guestfs_head_n_args, (char *) &args);
+ if (serial == -1) {
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ guestfs__switch_to_receiving (g);
+ ctx.cb_sequence = 0;
+ guestfs_set_reply_callback (g, head_n_reply_cb, &ctx);
+ (void) ml->main_loop_run (ml, g);
+ guestfs_set_reply_callback (g, NULL, NULL);
+ if (ctx.cb_sequence != 1) {
+ error (g, "%s reply failed, see earlier error messages", "guestfs_head_n");
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_HEAD_N, serial) == -1) {
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", ctx.err.error_message);
+ free (ctx.err.error_message);
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ guestfs_end_busy (g);
+ /* caller will free this, but we need to add a NULL entry */
+ ctx.ret.lines.lines_val =
+ safe_realloc (g, ctx.ret.lines.lines_val,
+ sizeof (char *) * (ctx.ret.lines.lines_len + 1));
+ ctx.ret.lines.lines_val[ctx.ret.lines.lines_len] = NULL;
+ return ctx.ret.lines.lines_val;
+}
+
+struct tail_ctx {
+ /* This flag is set by the callbacks, so we know we've done
+ * the callbacks as expected, and in the right sequence.
+ * 0 = not called, 1 = reply_cb called.
+ */
+ int cb_sequence;
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+ struct guestfs_tail_ret ret;
+};
+
+static void tail_reply_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ struct tail_ctx *ctx = (struct tail_ctx *) data;
+
+ /* This should definitely not happen. */
+ if (ctx->cb_sequence != 0) {
+ ctx->cb_sequence = 9999;
+ error (g, "%s: internal error: reply callback called twice", "guestfs_tail");
+ return;
+ }
+
+ ml->main_loop_quit (ml, g);
+
+ if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
+ error (g, "%s: failed to parse reply header", "guestfs_tail");
+ return;
+ }
+ if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
+ error (g, "%s: failed to parse reply error", "guestfs_tail");
+ return;
+ }
+ goto done;
+ }
+ if (!xdr_guestfs_tail_ret (xdr, &ctx->ret)) {
+ error (g, "%s: failed to parse reply", "guestfs_tail");
+ return;
+ }
+ done:
+ ctx->cb_sequence = 1;
+}
+
+char **guestfs_tail (guestfs_h *g,
+ const char *path)
+{
+ struct guestfs_tail_args args;
+ struct tail_ctx ctx;
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ int serial;
+
+ if (check_state (g, "guestfs_tail") == -1) return NULL;
+ guestfs_set_busy (g);
+
+ memset (&ctx, 0, sizeof ctx);
+
+ args.path = (char *) path;
+ serial = guestfs__send_sync (g, GUESTFS_PROC_TAIL,
+ (xdrproc_t) xdr_guestfs_tail_args, (char *) &args);
+ if (serial == -1) {
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ guestfs__switch_to_receiving (g);
+ ctx.cb_sequence = 0;
+ guestfs_set_reply_callback (g, tail_reply_cb, &ctx);
+ (void) ml->main_loop_run (ml, g);
+ guestfs_set_reply_callback (g, NULL, NULL);
+ if (ctx.cb_sequence != 1) {
+ error (g, "%s reply failed, see earlier error messages", "guestfs_tail");
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_TAIL, serial) == -1) {
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", ctx.err.error_message);
+ free (ctx.err.error_message);
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ guestfs_end_busy (g);
+ /* caller will free this, but we need to add a NULL entry */
+ ctx.ret.lines.lines_val =
+ safe_realloc (g, ctx.ret.lines.lines_val,
+ sizeof (char *) * (ctx.ret.lines.lines_len + 1));
+ ctx.ret.lines.lines_val[ctx.ret.lines.lines_len] = NULL;
+ return ctx.ret.lines.lines_val;
+}
+
+struct tail_n_ctx {
+ /* This flag is set by the callbacks, so we know we've done
+ * the callbacks as expected, and in the right sequence.
+ * 0 = not called, 1 = reply_cb called.
+ */
+ int cb_sequence;
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+ struct guestfs_tail_n_ret ret;
+};
+
+static void tail_n_reply_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ struct tail_n_ctx *ctx = (struct tail_n_ctx *) data;
+
+ /* This should definitely not happen. */
+ if (ctx->cb_sequence != 0) {
+ ctx->cb_sequence = 9999;
+ error (g, "%s: internal error: reply callback called twice", "guestfs_tail_n");
+ return;
+ }
+
+ ml->main_loop_quit (ml, g);
+
+ if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
+ error (g, "%s: failed to parse reply header", "guestfs_tail_n");
+ return;
+ }
+ if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
+ error (g, "%s: failed to parse reply error", "guestfs_tail_n");
+ return;
+ }
+ goto done;
+ }
+ if (!xdr_guestfs_tail_n_ret (xdr, &ctx->ret)) {
+ error (g, "%s: failed to parse reply", "guestfs_tail_n");
+ return;
+ }
+ done:
+ ctx->cb_sequence = 1;
+}
+
+char **guestfs_tail_n (guestfs_h *g,
+ int nrlines,
+ const char *path)
+{
+ struct guestfs_tail_n_args args;
+ struct tail_n_ctx ctx;
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ int serial;
+
+ if (check_state (g, "guestfs_tail_n") == -1) return NULL;
+ guestfs_set_busy (g);
+
+ memset (&ctx, 0, sizeof ctx);
+
+ args.nrlines = nrlines;
+ args.path = (char *) path;
+ serial = guestfs__send_sync (g, GUESTFS_PROC_TAIL_N,
+ (xdrproc_t) xdr_guestfs_tail_n_args, (char *) &args);
+ if (serial == -1) {
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ guestfs__switch_to_receiving (g);
+ ctx.cb_sequence = 0;
+ guestfs_set_reply_callback (g, tail_n_reply_cb, &ctx);
+ (void) ml->main_loop_run (ml, g);
+ guestfs_set_reply_callback (g, NULL, NULL);
+ if (ctx.cb_sequence != 1) {
+ error (g, "%s reply failed, see earlier error messages", "guestfs_tail_n");
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_TAIL_N, serial) == -1) {
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", ctx.err.error_message);
+ free (ctx.err.error_message);
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ guestfs_end_busy (g);
+ /* caller will free this, but we need to add a NULL entry */
+ ctx.ret.lines.lines_val =
+ safe_realloc (g, ctx.ret.lines.lines_val,
+ sizeof (char *) * (ctx.ret.lines.lines_len + 1));
+ ctx.ret.lines.lines_val[ctx.ret.lines.lines_len] = NULL;
+ return ctx.ret.lines.lines_val;
+}
+
+struct df_ctx {
+ /* This flag is set by the callbacks, so we know we've done
+ * the callbacks as expected, and in the right sequence.
+ * 0 = not called, 1 = reply_cb called.
+ */
+ int cb_sequence;
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+ struct guestfs_df_ret ret;
+};
+
+static void df_reply_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ struct df_ctx *ctx = (struct df_ctx *) data;
+
+ /* This should definitely not happen. */
+ if (ctx->cb_sequence != 0) {
+ ctx->cb_sequence = 9999;
+ error (g, "%s: internal error: reply callback called twice", "guestfs_df");
+ return;
+ }
+
+ ml->main_loop_quit (ml, g);
+
+ if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
+ error (g, "%s: failed to parse reply header", "guestfs_df");
+ return;
+ }
+ if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
+ error (g, "%s: failed to parse reply error", "guestfs_df");
+ return;
+ }
+ goto done;
+ }
+ if (!xdr_guestfs_df_ret (xdr, &ctx->ret)) {
+ error (g, "%s: failed to parse reply", "guestfs_df");
+ return;
+ }
+ done:
+ ctx->cb_sequence = 1;
+}
+
+char *guestfs_df (guestfs_h *g)
+{
+ struct df_ctx ctx;
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ int serial;
+
+ if (check_state (g, "guestfs_df") == -1) return NULL;
+ guestfs_set_busy (g);
+
+ memset (&ctx, 0, sizeof ctx);
+
+ serial = guestfs__send_sync (g, GUESTFS_PROC_DF, NULL, NULL);
+ if (serial == -1) {
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ guestfs__switch_to_receiving (g);
+ ctx.cb_sequence = 0;
+ guestfs_set_reply_callback (g, df_reply_cb, &ctx);
+ (void) ml->main_loop_run (ml, g);
+ guestfs_set_reply_callback (g, NULL, NULL);
+ if (ctx.cb_sequence != 1) {
+ error (g, "%s reply failed, see earlier error messages", "guestfs_df");
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_DF, serial) == -1) {
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", ctx.err.error_message);
+ free (ctx.err.error_message);
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ guestfs_end_busy (g);
+ return ctx.ret.output; /* caller will free */
+}
+
+struct df_h_ctx {
+ /* This flag is set by the callbacks, so we know we've done
+ * the callbacks as expected, and in the right sequence.
+ * 0 = not called, 1 = reply_cb called.
+ */
+ int cb_sequence;
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+ struct guestfs_df_h_ret ret;
+};
+
+static void df_h_reply_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ struct df_h_ctx *ctx = (struct df_h_ctx *) data;
+
+ /* This should definitely not happen. */
+ if (ctx->cb_sequence != 0) {
+ ctx->cb_sequence = 9999;
+ error (g, "%s: internal error: reply callback called twice", "guestfs_df_h");
+ return;
+ }
+
+ ml->main_loop_quit (ml, g);
+
+ if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
+ error (g, "%s: failed to parse reply header", "guestfs_df_h");
+ return;
+ }
+ if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
+ error (g, "%s: failed to parse reply error", "guestfs_df_h");
+ return;
+ }
+ goto done;
+ }
+ if (!xdr_guestfs_df_h_ret (xdr, &ctx->ret)) {
+ error (g, "%s: failed to parse reply", "guestfs_df_h");
+ return;
+ }
+ done:
+ ctx->cb_sequence = 1;
+}
+
+char *guestfs_df_h (guestfs_h *g)
+{
+ struct df_h_ctx ctx;
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ int serial;
+
+ if (check_state (g, "guestfs_df_h") == -1) return NULL;
+ guestfs_set_busy (g);
+
+ memset (&ctx, 0, sizeof ctx);
+
+ serial = guestfs__send_sync (g, GUESTFS_PROC_DF_H, NULL, NULL);
+ if (serial == -1) {
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ guestfs__switch_to_receiving (g);
+ ctx.cb_sequence = 0;
+ guestfs_set_reply_callback (g, df_h_reply_cb, &ctx);
+ (void) ml->main_loop_run (ml, g);
+ guestfs_set_reply_callback (g, NULL, NULL);
+ if (ctx.cb_sequence != 1) {
+ error (g, "%s reply failed, see earlier error messages", "guestfs_df_h");
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_DF_H, serial) == -1) {
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", ctx.err.error_message);
+ free (ctx.err.error_message);
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ guestfs_end_busy (g);
+ return ctx.ret.output; /* caller will free */
+}
+
+struct du_ctx {
+ /* This flag is set by the callbacks, so we know we've done
+ * the callbacks as expected, and in the right sequence.
+ * 0 = not called, 1 = reply_cb called.
+ */
+ int cb_sequence;
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+ struct guestfs_du_ret ret;
+};
+
+static void du_reply_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ struct du_ctx *ctx = (struct du_ctx *) data;
+
+ /* This should definitely not happen. */
+ if (ctx->cb_sequence != 0) {
+ ctx->cb_sequence = 9999;
+ error (g, "%s: internal error: reply callback called twice", "guestfs_du");
+ return;
+ }
+
+ ml->main_loop_quit (ml, g);
+
+ if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
+ error (g, "%s: failed to parse reply header", "guestfs_du");
+ return;
+ }
+ if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
+ error (g, "%s: failed to parse reply error", "guestfs_du");
+ return;
+ }
+ goto done;
+ }
+ if (!xdr_guestfs_du_ret (xdr, &ctx->ret)) {
+ error (g, "%s: failed to parse reply", "guestfs_du");
+ return;
+ }
+ done:
+ ctx->cb_sequence = 1;
+}
+
+int64_t guestfs_du (guestfs_h *g,
+ const char *path)
+{
+ struct guestfs_du_args args;
+ struct du_ctx ctx;
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ int serial;
+
+ if (check_state (g, "guestfs_du") == -1) return -1;
+ guestfs_set_busy (g);
+
+ memset (&ctx, 0, sizeof ctx);
+
+ args.path = (char *) path;
+ serial = guestfs__send_sync (g, GUESTFS_PROC_DU,
+ (xdrproc_t) xdr_guestfs_du_args, (char *) &args);
+ if (serial == -1) {
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ guestfs__switch_to_receiving (g);
+ ctx.cb_sequence = 0;
+ guestfs_set_reply_callback (g, du_reply_cb, &ctx);
+ (void) ml->main_loop_run (ml, g);
+ guestfs_set_reply_callback (g, NULL, NULL);
+ if (ctx.cb_sequence != 1) {
+ error (g, "%s reply failed, see earlier error messages", "guestfs_du");
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_DU, serial) == -1) {
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", ctx.err.error_message);
+ free (ctx.err.error_message);
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ guestfs_end_busy (g);
+ return ctx.ret.sizekb;
+}
+
+struct initrd_list_ctx {
+ /* This flag is set by the callbacks, so we know we've done
+ * the callbacks as expected, and in the right sequence.
+ * 0 = not called, 1 = reply_cb called.
+ */
+ int cb_sequence;
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+ struct guestfs_initrd_list_ret ret;
+};
+
+static void initrd_list_reply_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ struct initrd_list_ctx *ctx = (struct initrd_list_ctx *) data;
+
+ /* This should definitely not happen. */
+ if (ctx->cb_sequence != 0) {
+ ctx->cb_sequence = 9999;
+ error (g, "%s: internal error: reply callback called twice", "guestfs_initrd_list");
+ return;
+ }
+
+ ml->main_loop_quit (ml, g);
+
+ if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
+ error (g, "%s: failed to parse reply header", "guestfs_initrd_list");
+ return;
+ }
+ if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
+ error (g, "%s: failed to parse reply error", "guestfs_initrd_list");
+ return;
+ }
+ goto done;
+ }
+ if (!xdr_guestfs_initrd_list_ret (xdr, &ctx->ret)) {
+ error (g, "%s: failed to parse reply", "guestfs_initrd_list");
+ return;
+ }
+ done:
+ ctx->cb_sequence = 1;
+}
+
+char **guestfs_initrd_list (guestfs_h *g,
+ const char *path)
+{
+ struct guestfs_initrd_list_args args;
+ struct initrd_list_ctx ctx;
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ int serial;
+
+ if (check_state (g, "guestfs_initrd_list") == -1) return NULL;
+ guestfs_set_busy (g);
+
+ memset (&ctx, 0, sizeof ctx);
+
+ args.path = (char *) path;
+ serial = guestfs__send_sync (g, GUESTFS_PROC_INITRD_LIST,
+ (xdrproc_t) xdr_guestfs_initrd_list_args, (char *) &args);
+ if (serial == -1) {
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ guestfs__switch_to_receiving (g);
+ ctx.cb_sequence = 0;
+ guestfs_set_reply_callback (g, initrd_list_reply_cb, &ctx);
+ (void) ml->main_loop_run (ml, g);
+ guestfs_set_reply_callback (g, NULL, NULL);
+ if (ctx.cb_sequence != 1) {
+ error (g, "%s reply failed, see earlier error messages", "guestfs_initrd_list");
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_INITRD_LIST, serial) == -1) {
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", ctx.err.error_message);
+ free (ctx.err.error_message);
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ guestfs_end_busy (g);
+ /* caller will free this, but we need to add a NULL entry */
+ ctx.ret.filenames.filenames_val =
+ safe_realloc (g, ctx.ret.filenames.filenames_val,
+ sizeof (char *) * (ctx.ret.filenames.filenames_len + 1));
+ ctx.ret.filenames.filenames_val[ctx.ret.filenames.filenames_len] = NULL;
+ return ctx.ret.filenames.filenames_val;
+}
+
+struct mount_loop_ctx {
+ /* This flag is set by the callbacks, so we know we've done
+ * the callbacks as expected, and in the right sequence.
+ * 0 = not called, 1 = reply_cb called.
+ */
+ int cb_sequence;
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+};
+
+static void mount_loop_reply_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ struct mount_loop_ctx *ctx = (struct mount_loop_ctx *) data;
+
+ /* This should definitely not happen. */
+ if (ctx->cb_sequence != 0) {
+ ctx->cb_sequence = 9999;
+ error (g, "%s: internal error: reply callback called twice", "guestfs_mount_loop");
+ return;
+ }
+
+ ml->main_loop_quit (ml, g);
+
+ if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
+ error (g, "%s: failed to parse reply header", "guestfs_mount_loop");
+ return;
+ }
+ if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
+ error (g, "%s: failed to parse reply error", "guestfs_mount_loop");
+ return;
+ }
+ goto done;
+ }
+ done:
+ ctx->cb_sequence = 1;
+}
+
+int guestfs_mount_loop (guestfs_h *g,
+ const char *file,
+ const char *mountpoint)
+{
+ struct guestfs_mount_loop_args args;
+ struct mount_loop_ctx ctx;
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ int serial;
+
+ if (check_state (g, "guestfs_mount_loop") == -1) return -1;
+ guestfs_set_busy (g);
+
+ memset (&ctx, 0, sizeof ctx);
+
+ args.file = (char *) file;
+ args.mountpoint = (char *) mountpoint;
+ serial = guestfs__send_sync (g, GUESTFS_PROC_MOUNT_LOOP,
+ (xdrproc_t) xdr_guestfs_mount_loop_args, (char *) &args);
+ if (serial == -1) {
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ guestfs__switch_to_receiving (g);
+ ctx.cb_sequence = 0;
+ guestfs_set_reply_callback (g, mount_loop_reply_cb, &ctx);
+ (void) ml->main_loop_run (ml, g);
+ guestfs_set_reply_callback (g, NULL, NULL);
+ if (ctx.cb_sequence != 1) {
+ error (g, "%s reply failed, see earlier error messages", "guestfs_mount_loop");
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MOUNT_LOOP, serial) == -1) {
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", ctx.err.error_message);
+ free (ctx.err.error_message);
+ guestfs_end_busy (g);
+ return -1;
+ }
+
+ guestfs_end_busy (g);
+ return 0;
+}
+