+
+/* 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);
+}
+
+void
+guestfs___free_drives (struct drive **drives)
+{
+ struct drive *i = *drives;
+ *drives = NULL;
+
+ while (i != NULL) {
+ struct drive *next = i->next;
+
+ free (i->path);
+ free (i->format);
+ free (i->iface);
+ free (i->name);
+ free (i);
+
+ i = next;
+ }
+}