Пример #1
0
int
main (int argc, char *argv[])
{
  guestfs_h *g = guestfs_create ();

  /* Call some non-daemon functions that have a String parameter, but
   * setting that parameter to NULL.  Previously this would cause a
   * segfault inside libguestfs.  After this bug was fixed, this
   * turned into an error message.
   */

  assert (guestfs_add_drive (g, NULL) == -1);
  assert (guestfs_config (g, NULL, NULL) == -1);

  /* This optional argument must not be NULL. */

  assert (guestfs_add_drive_opts (g, "/dev/null",
                                  GUESTFS_ADD_DRIVE_OPTS_FORMAT, NULL,
                                  -1) == -1);

  /* These can be safely set to NULL, should be no error. */

  assert (guestfs_set_path (g, NULL) == 0);
  assert (guestfs_set_append (g, NULL) == 0);
  assert (guestfs_set_qemu (g, NULL) == 0);

  guestfs_close (g);
  exit (EXIT_SUCCESS);
}
Пример #2
0
/* Common function to add the /dev/null drive. */
static void
add_drive (guestfs_h *g)
{
  if (guestfs_add_drive_opts (g, "/dev/null",
                              GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw",
                              GUESTFS_ADD_DRIVE_OPTS_READONLY, 1,
                              -1) == -1)
    exit (EXIT_FAILURE);
}
Пример #3
0
int
main (int argc, char *argv[])
{
  guestfs_h *g;
  int r;
  char *data;
  size_t i, size;

  if (test_start_nbdkit ("-n", NBDKIT_PLUGIN ("file"), "file=file-data",
                         NULL) == -1)
    exit (EXIT_FAILURE);

  g = guestfs_create ();
  if (g == NULL) {
    perror ("guestfs_create");
    exit (EXIT_FAILURE);
  }

  /* Using any exportname causes qemu to use the newstyle protocol. */
  r = guestfs_add_drive_opts (g, "/" /* exportname */,
                              GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw",
                              GUESTFS_ADD_DRIVE_OPTS_PROTOCOL, "nbd",
                              GUESTFS_ADD_DRIVE_OPTS_SERVER, server,
                              -1);
  if (r == -1)
    exit (EXIT_FAILURE);

  if (guestfs_launch (g) == -1)
    exit (EXIT_FAILURE);

  /* Check the data in the file is \x01-\x08 repeated 512 times. */
  data = guestfs_pread_device (g, "/dev/sda", 8 * 512, 0, &size);
  if (!data)
    exit (EXIT_FAILURE);
  if (size != 8 * 512) {
    fprintf (stderr, "%s FAILED: unexpected size (actual: %zu, expected: 512)\n",
             program_name, size);
    exit (EXIT_FAILURE);
  }

  for (i = 0; i < 512 * 8; i += 8) {
    if (data[i] != 1 || data[i+1] != 2 ||
        data[i+2] != 3 || data[i+3] != 4 ||
        data[i+4] != 5 || data[i+5] != 6 ||
        data[i+6] != 7 || data[i+7] != 8) {
      fprintf (stderr, "%s FAILED: unexpected data returned at offset %zu\n",
               program_name, i);
      exit (EXIT_FAILURE);
    }
  }

  free (data);

  guestfs_close (g);
  exit (EXIT_SUCCESS);
}
Пример #4
0
int
main (int argc, char *argv[])
{
  char *str;
  guestfs_h *g;
  char tmp[] = "/tmp/charsetXXXXXX";
  int fd;
  size_t i;
  struct filesystem *fs;

  /* Allow this test to be skipped. */
  str = getenv ("SKIP_TEST_CHARSET_FIDELITY");
  if (str && STREQ (str, "1")) {
    printf ("%s: test skipped because environment variable is set.\n",
            argv[0]);
    exit (77);
  }

  g = guestfs_create ();
  if (g == NULL)
    error (EXIT_FAILURE, 0, "failed to create handle");

  fd = mkstemp (tmp);
  if (fd == -1)
    error (EXIT_FAILURE, errno, "mkstemp");

  if (ftruncate (fd, 1024 * 1024 * 1024) == -1)
    error (EXIT_FAILURE, errno, "ftruncate: %s", tmp);

  if (close (fd) == -1)
    error (EXIT_FAILURE, errno, "close: %s", tmp);

  if (guestfs_add_drive_opts (g, tmp, -1) == -1)
    exit (EXIT_FAILURE);

  if (guestfs_launch (g) == -1)
    exit (EXIT_FAILURE);

  if (guestfs_part_disk (g, "/dev/sda", "mbr") == -1)
    exit (EXIT_FAILURE);

  for (i = 0; i < sizeof filesystems / sizeof filesystems[0]; ++i) {
    fs = &filesystems[i];
    test_filesystem (g, fs);
  }

  guestfs_close (g);
  unlink (tmp);

  exit (EXIT_SUCCESS);
}
Пример #5
0
int
main (int argc, char *argv[])
{
  guestfs_h *g;
  const char *filename = "test.log";
  FILE *debugfp;

  debugfp = fopen (filename, "w");
  if (debugfp == NULL) {
    perror (filename);
    exit (EXIT_FAILURE);
  }

  g = guestfs_create ();
  if (g == NULL) {
    fprintf (stderr, "failed to create handle\n");
    exit (EXIT_FAILURE);
  }

  if (guestfs_set_event_callback
      (g, debug_to_file,
       GUESTFS_EVENT_LIBRARY | GUESTFS_EVENT_APPLIANCE |
       GUESTFS_EVENT_WARNING | GUESTFS_EVENT_TRACE,
       0, debugfp) == -1)
    exit (EXIT_FAILURE);

  if (guestfs_set_verbose (g, 1) == -1)
    exit (EXIT_FAILURE);

  if (guestfs_set_trace (g, 1) == -1)
    exit (EXIT_FAILURE);

  if (guestfs_add_drive_opts (g, "/dev/null",
                              GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw",
                              GUESTFS_ADD_DRIVE_OPTS_READONLY, 1,
                              -1) == -1)
    exit (EXIT_FAILURE);

  if (guestfs_launch (g) == -1)
    exit (EXIT_FAILURE);

  guestfs_close (g);

  exit (EXIT_SUCCESS);
}
Пример #6
0
static void *
start_thread (void *vi)
{
  guestfs_h *g;
  int r, thread_id = *(int *)vi;
  const char *error;

  g = guestfs_create ();
  if (g == NULL) {
    perror ("guestfs_create");
    *(int *)vi = -1;
    pthread_exit (vi);
  }

  if (guestfs_add_drive_opts (g, "/dev/null",
                              GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw",
                              GUESTFS_ADD_DRIVE_OPTS_READONLY, 1,
                              -1) == -1) {
    *(int *)vi = -1;
    pthread_exit (vi);
  }

  /* Fake out qemu. */
  if (guestfs_set_qemu (g, "/bin/true") == -1) {
    *(int *)vi = -1;
    pthread_exit (vi);
  }

  /* Wait for the other threads to finish starting up. */
  r = pthread_barrier_wait (&barrier);
  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD) {
    fprintf (stderr, "pthread_barrier_wait: [thread %d]: %s\n",
             thread_id, strerror (r));
    *(int *)vi = -1;
    pthread_exit (vi);
  }

  /* Launch the handle.  Because of the faked out qemu, we expect this
   * will fail with "child process died unexpectedly".  We are
   * interested in other failures.
   */
  guestfs_push_error_handler (g, NULL, NULL);
  r = guestfs_launch (g);
  error = guestfs_last_error (g);

  if (r == 0) { /* This should NOT happen. */
    fprintf (stderr, "rhbz790721: [thread %d]: "
             "strangeness in test: expected launch to fail, but it didn't!\n",
             thread_id);
    *(int *)vi = -1;
    pthread_exit (vi);
  }

  if (error == NULL) { /* This also should NOT happen. */
    fprintf (stderr, "rhbz790721: [thread %d]: "
             "strangeness in test: no error message!\n",
             thread_id);
    *(int *)vi = -1;
    pthread_exit (vi);
  }

  /* If this happens, it indicates a bug/race in the appliance
   * building code which is what this regression test is designed to
   * spot.
   */
  if (STRNEQ (error, "child process died unexpectedly")) {
    fprintf (stderr, "rhbz790721: [thread %d]: error: %s\n", thread_id, error);
    *(int *)vi = -1;
    pthread_exit (vi);
  }

  guestfs_pop_error_handler (g);

  /* Close the handle. */
  guestfs_close (g);

  *(int *)vi = 0;
  pthread_exit (vi);
}
Пример #7
0
int
main (int argc, char *argv[])
{
    guestfs_h *g;
    int fd, r;
    char tempdir[] = "/tmp/mlXXXXXX";
    pid_t pid;
    char *shell, *p;

    if (argc != 2) {
        usage ();
        exit (EXIT_FAILURE);
    }

    printf ("\n"
            "This is the 'mount-local' demonstration program.  Follow the\n"
            "instructions on screen.\n"
            "\n"
            "Creating and formatting the disk image, please wait a moment ...\n");
    fflush (stdout);

    /* Create the output disk image: raw sparse. */
    fd = open (argv[1], O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0644);
    if (fd == -1) {
        perror (argv[1]);
        exit (EXIT_FAILURE);
    }
    if (ftruncate (fd, SIZE_MB * 1024 * 1024) == -1) {
        perror ("truncate");
        close (fd);
        exit (EXIT_FAILURE);
    }
    if (close (fd) == -1) {
        perror ("close");
        exit (EXIT_FAILURE);
    }

    /* Guestfs handle. */
    g = guestfs_create ();
    if (g == NULL) {
        perror ("could not create libguestfs handle");
        exit (EXIT_FAILURE);
    }

    /* Create the disk image and format it with a partition and a filesystem. */
    if (guestfs_add_drive_opts (g, argv[1],
                                GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw",
                                -1) == -1)
        exit (EXIT_FAILURE);

    if (guestfs_launch (g) == -1)
        exit (EXIT_FAILURE);

    if (guestfs_part_disk (g, "/dev/sda", "mbr") == -1)
        exit (EXIT_FAILURE);

    if (guestfs_mkfs (g, "ext2", "/dev/sda1") == -1)
        exit (EXIT_FAILURE);

    /* Mount the empty filesystem. */
    if (guestfs_mount_options (g, MOUNT_OPTIONS, "/dev/sda1", "/") == -1)
        exit (EXIT_FAILURE);

    /* Create a file in the new filesystem. */
    if (guestfs_touch (g, "/PUT_FILES_AND_DIRECTORIES_HERE") == -1)
        exit (EXIT_FAILURE);

    /* Create a temporary mount directory. */
    if (mkdtemp (tempdir) == NULL) {
        perror ("mkdtemp");
        exit (EXIT_FAILURE);
    }

    /* Mount the filesystem. */
    if (guestfs_mount_local (g, tempdir, -1) == -1)
        exit (EXIT_FAILURE);

    /* Fork the shell for the user. */
    pid = fork ();
    if (pid == -1) {
        perror ("fork");
        exit (EXIT_FAILURE);
    }

    if (pid == 0) {               /* Child. */
        if (chdir (tempdir) == -1) {
            perror (tempdir);
            _exit (EXIT_FAILURE);
        }

        printf ("\n"
                "The *current directory* is a FUSE filesystem backed by the disk\n"
                "image which is managed by libguestfs.  Any files or directories\n"
                "you copy into here (up to %d MB) will be saved into the disk\n"
                "image.  You can also delete files, create certain special files\n"
                "and so on.\n"
                "\n"
                "When you have finished adding files, hit ^D or type 'exit' to\n"
                "exit the shell and return to the mount-local program.\n"
                "\n",
                SIZE_MB);

        shell = getenv ("SHELL");
        if (!shell)
            r = system ("/bin/sh");
        else {
            /* Set a magic prompt.  We only know how to do this for bash. */
            p = strrchr (shell, '/');
            if (p && strcmp (p+1, "bash") == 0) {
                size_t len = 64 + strlen (shell);
                char buf[len];

                snprintf (buf, len, "PS1='mount-local-shell> ' %s --norc -i", shell);
                r = system (buf);
            } else
                r = system (shell);
        }
        if (r == -1) {
            fprintf (stderr, "error: failed to run sub-shell (%s) "
                     "(is $SHELL set correctly?)\n",
                     shell);
            //FALLTHROUGH
        }

        chdir ("/");
        guestfs_umount_local (g, GUESTFS_UMOUNT_LOCAL_RETRY, 1, -1);
        _exit (EXIT_SUCCESS);
    }

    /* Note that we are *not* waiting for the child yet.  We want to
     * run the FUSE code in parallel with the subshell.
     */

    /* We're going to hide libguestfs errors here, but in a real program
     * you would probably want to log them somewhere.
     */
    guestfs_push_error_handler (g, NULL, NULL);

    /* Now run the FUSE thread. */
    if (guestfs_mount_local_run (g) == -1)
        exit (EXIT_FAILURE);

    guestfs_pop_error_handler (g);

    waitpid (pid, NULL, 0);

    /* Shutdown the handle explicitly so write errors can be detected. */
    if (guestfs_shutdown (g) == -1)
        exit (EXIT_FAILURE);

    guestfs_close (g);

    printf ("\n"
            "Any files or directories that you copied in have been saved into\n"
            "the disk image called '%s'.\n"
            "\n"
            "Try opening the disk image with guestfish to see those files:\n"
            "\n"
            "  guestfish -a %s -m /dev/sda1\n"
            "\n",
            argv[1], argv[1]);

    exit (EXIT_SUCCESS);
}
Пример #8
0
/* This is the underlying allocation function.  It's called from
 * a few other places in guestfish.
 */
int
alloc_disk (const char *filename, const char *size_str, int add, int sparse)
{
  off_t size;
  int fd;
  char c = 0;

  if (parse_size (size_str, &size) == -1)
    return -1;

  fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_TRUNC|O_CLOEXEC, 0666);
  if (fd == -1) {
    perror (filename);
    return -1;
  }

  if (!sparse) {                /* Not sparse */
#ifdef HAVE_POSIX_FALLOCATE
    int err = posix_fallocate (fd, 0, size);
    if (err != 0) {
      errno = err;
      perror ("fallocate");
      close (fd);
      unlink (filename);
      return -1;
    }
#else
    /* Slow emulation of posix_fallocate on platforms which don't have it. */
    char buffer[BUFSIZ];
    memset (buffer, 0, sizeof buffer);

    size_t remaining = size;
    while (remaining > 0) {
      size_t n = remaining > sizeof buffer ? sizeof buffer : remaining;
      ssize_t r = write (fd, buffer, n);
      if (r == -1) {
        perror ("write");
        close (fd);
        unlink (filename);
        return -1;
      }
      remaining -= r;
    }
#endif
  } else {                      /* Sparse */
    if (lseek (fd, size-1, SEEK_SET) == (off_t) -1) {
      perror ("lseek");
      close (fd);
      unlink (filename);
      return -1;
    }

    if (write (fd, &c, 1) != 1) {
      perror ("write");
      close (fd);
      unlink (filename);
      return -1;
    }
  }

  if (close (fd) == -1) {
    perror (filename);
    unlink (filename);
    return -1;
  }

  if (add) {
    if (guestfs_add_drive_opts (g, filename,
                                GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw",
                                -1) == -1) {
      unlink (filename);
      return -1;
    }
  }

  return 0;
}
Пример #9
0
int
main (int argc, char *argv[])
{
  guestfs_h *g;
  const char *disk;
  char **roots, *root, *str, **mountpoints, **lines;
  size_t i, j;

  if (argc != 2) {
    fprintf (stderr, "usage: inspect_vm disk.img\n");
    exit (EXIT_FAILURE);
  }
  disk = argv[1];

  g = guestfs_create ();
  if (g == NULL) {
    perror ("failed to create libguestfs handle");
    exit (EXIT_FAILURE);
  }

  /* Attach the disk image read-only to libguestfs. */
  if (guestfs_add_drive_opts (g, disk,
			      /* GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw", */
			      GUESTFS_ADD_DRIVE_OPTS_READONLY, 1,
			      -1) /* this marks end of optional arguments */
      == -1)
    exit (EXIT_FAILURE);

  /* Run the libguestfs back-end. */
  if (guestfs_launch (g) == -1)
    exit (EXIT_FAILURE);

  /* Ask libguestfs to inspect for operating systems. */
  roots = guestfs_inspect_os (g);
  if (roots == NULL)
    exit (EXIT_FAILURE);
  if (roots[0] == NULL) {
    fprintf (stderr, "inspect_vm: no operating systems found\n");
    exit (EXIT_FAILURE);
  }

  for (j = 0; roots[j] != NULL; ++j) {
    root = roots[j];

    printf ("Root device: %s\n", root);

    /* Print basic information about the operating system. */
    str = guestfs_inspect_get_product_name (g, root);
    if (str)
      printf ("  Product name: %s\n", str);
    free (str);

    printf ("  Version:      %d.%d\n",
            guestfs_inspect_get_major_version (g, root),
            guestfs_inspect_get_minor_version (g, root));

    str = guestfs_inspect_get_type (g, root);
    if (str)
      printf ("  Type:         %s\n", str);
    free (str);
    str = guestfs_inspect_get_distro (g, root);
    if (str)
      printf ("  Distro:       %s\n", str);
    free (str);

    /* Mount up the disks, like guestfish -i.
     *
     * Sort keys by length, shortest first, so that we end up
     * mounting the filesystems in the correct order.
     */
    mountpoints = guestfs_inspect_get_mountpoints (g, root);
    if (mountpoints == NULL)
      exit (EXIT_FAILURE);

    qsort (mountpoints, count_strings (mountpoints) / 2, 2 * sizeof (char *),
           compare_keys_len);
    for (i = 0; mountpoints[i] != NULL; i += 2) {
      /* Ignore failures from this call, since bogus entries can
       * appear in the guest's /etc/fstab.
       */
      guestfs_mount_ro (g, mountpoints[i+1], mountpoints[i]);
      free (mountpoints[i]);
      free (mountpoints[i+1]);
    }
    free (mountpoints);

    /* If /etc/issue.net file exists, print up to 3 lines. */
    if (guestfs_is_file (g, "/etc/issue.net") > 0) {
      printf ("--- /etc/issue.net ---\n");
      lines = guestfs_head_n (g, 3, "/etc/issue.net");
      if (lines == NULL)
        exit (EXIT_FAILURE);
      for (i = 0; lines[i] != NULL; ++i) {
        printf ("%s\n", lines[i]);
        free (lines[i]);
      }
      free (lines);
    }

    /* Unmount everything. */
    if (guestfs_umount_all (g) == -1)
      exit (EXIT_FAILURE);

    free (root);
  }
  free (roots);

  guestfs_close (g);

  exit (EXIT_SUCCESS);
}
Пример #10
0
static int
do_make_fs (const char *input, const char *output_str)
{
  const char *dev, *options;
  CLEANUP_UNLINK_FREE char *output = NULL;
  uint64_t estimate, size;
  struct guestfs_disk_create_argv optargs;
  CLEANUP_FREE char *ifmt = NULL;
  CLEANUP_FREE char *ifile = NULL;
  pid_t pid;
  int status, fd;

  /* Use of CLEANUP_UNLINK_FREE *output ensures the output file is
   * deleted unless we successfully reach the end of this function.
   */
  output = strdup (output_str);
  if (output == NULL) {
    perror ("strdup");
    return -1;
  }

  /* Input.  What is it?  Estimate how much space it will need. */
  if (estimate_input (input, &estimate, &ifmt) == -1)
    return -1;

  if (verbose) {
    fprintf (stderr, "input format = %s\n", ifmt);
    fprintf (stderr, "estimate = %" PRIu64 " bytes "
             "(%" PRIu64 " 1K blocks, %" PRIu64 " 4K blocks)\n",
             estimate, estimate / 1024, estimate / 4096);
  }

  estimate += 256 * 1024;       /* For superblocks &c. */

  if (STRPREFIX (type, "ext") && type[3] >= '3') {
    /* For ext3+, add some more for the journal. */
    estimate += 1024 * 1024;
  }

  else if (STREQ (type, "ntfs")) {
    estimate += 4 * 1024 * 1024; /* NTFS journal. */
  }

  else if (STREQ (type, "btrfs")) {
    /* For BTRFS, the minimum metadata allocation is 256MB, with data
     * additional to that.  Note that we disable data and metadata
     * duplication below.
     */
    estimate += 256 * 1024 * 1024;
  }

  /* Add 10%, see above. */
  estimate *= 1.10;

  /* Calculate the output size. */
  if (size_str == NULL)
    size = estimate;
  else
    if (parse_size (size_str, estimate, &size) == -1)
      return -1;

  /* Create the output disk. */
  optargs.bitmask = 0;
  if (STREQ (format, "qcow2")) {
    optargs.bitmask |= GUESTFS_DISK_CREATE_PREALLOCATION_BITMASK;
    optargs.preallocation = "metadata";
  }
  if (guestfs_disk_create_argv (g, output, format, size, &optargs) == -1)
    return -1;

  if (guestfs_add_drive_opts (g, output,
                              GUESTFS_ADD_DRIVE_OPTS_FORMAT, format,
                              -1) == -1)
    return -1;

  if (guestfs_launch (g) == -1)
    return -1;

  if (check_ntfs_available () == -1)
    return -1;

  /* Partition the disk. */
  dev = "/dev/sda";
  if (partition) {
    int mbr_id = 0;

    if (STREQ (partition, ""))
      partition = "mbr";

    if (guestfs_part_disk (g, dev, partition) == -1)
      return -1;

    dev = "/dev/sda1";

    /* Set the partition type byte if it's MBR and the filesystem type
     * is one that we know about.
     */
    if (STREQ (partition, "mbr") || STREQ (partition, "msdos")) {
      if (STREQ (type, "msdos"))
        /* According to Wikipedia.  However I have not actually tried this. */
        mbr_id = 0x1;
      else if (STREQ (type, "vfat") || STREQ (type, "fat"))
        mbr_id = 0xb;
      else if (STREQ (type, "ntfs"))
        mbr_id = 0x7;
      else if (STRPREFIX (type, "ext"))
        mbr_id = 0x83;
      else if (STREQ (type, "minix"))
        mbr_id = 0x81;
    }
    if (mbr_id != 0) {
      if (guestfs_part_set_mbr_id (g, "/dev/sda", 1, mbr_id) == -1)
        return -1;
    }
  }

  if (verbose)
    fprintf (stderr, "creating %s filesystem on %s ...\n", type, dev);

  /* Create the filesystem. */
  if (STRNEQ (type, "btrfs")) {
    int r;
    struct guestfs_mkfs_opts_argv optargs = { .bitmask = 0 };

    if (label) {
      optargs.label = label;
      optargs.bitmask |= GUESTFS_MKFS_OPTS_LABEL_BITMASK;
    }

    guestfs_push_error_handler (g, NULL, NULL);
    r = guestfs_mkfs_opts_argv (g, type, dev, &optargs);
    guestfs_pop_error_handler (g);

    if (r == -1) {
      /* Provide more guidance in the error message (RHBZ#823883). */
      fprintf (stderr, "%s: 'mkfs' (create filesystem) operation failed: %s\n",
               guestfs_int_program_name, guestfs_last_error (g));
      if (STREQ (type, "fat"))
        fprintf (stderr, "Instead of 'fat', try 'vfat' (long filenames) or 'msdos' (short filenames).\n");
      else
        fprintf (stderr, "Is '%s' a correct filesystem type?\n", type);

      return -1;
    }
  }
  else {
Пример #11
0
char
add_drives (struct drv *drv, char next_drive)
{
  int r;
  struct guestfs_add_drive_opts_argv ad_optargs;

  if (next_drive > 'z') {
    fprintf (stderr,
             _("%s: too many drives added on the command line\n"),
             program_name);
    exit (EXIT_FAILURE);
  }

  if (drv) {
    next_drive = add_drives (drv->next, next_drive);

    free (drv->device);
    drv->device = NULL;

    if (asprintf (&drv->device, "/dev/sd%c", next_drive) == -1) {
      perror ("asprintf");
      exit (EXIT_FAILURE);
    }

    switch (drv->type) {
    case drv_a:
      ad_optargs.bitmask = 0;
      if (read_only) {
        ad_optargs.bitmask |= GUESTFS_ADD_DRIVE_OPTS_READONLY_BITMASK;
        ad_optargs.readonly = 1;
      }
      if (drv->a.format) {
        ad_optargs.bitmask |= GUESTFS_ADD_DRIVE_OPTS_FORMAT_BITMASK;
        ad_optargs.format = drv->a.format;
      }

      r = guestfs_add_drive_opts_argv (g, drv->a.filename, &ad_optargs);
      if (r == -1)
        exit (EXIT_FAILURE);

      drv->nr_drives = 1;
      next_drive++;
      break;

    case drv_uri:
      ad_optargs.bitmask = 0;
      if (read_only) {
        ad_optargs.bitmask |= GUESTFS_ADD_DRIVE_OPTS_READONLY_BITMASK;
        ad_optargs.readonly = 1;
      }
      if (drv->uri.format) {
        ad_optargs.bitmask |= GUESTFS_ADD_DRIVE_OPTS_FORMAT_BITMASK;
        ad_optargs.format = drv->uri.format;
      }
      ad_optargs.bitmask |= GUESTFS_ADD_DRIVE_OPTS_PROTOCOL_BITMASK;
      ad_optargs.protocol = drv->uri.protocol;
      if (drv->uri.server) {
        ad_optargs.bitmask |= GUESTFS_ADD_DRIVE_OPTS_SERVER_BITMASK;
        ad_optargs.server = drv->uri.server;
      }
      if (drv->uri.username) {
        ad_optargs.bitmask |= GUESTFS_ADD_DRIVE_OPTS_USERNAME_BITMASK;
        ad_optargs.username = drv->uri.username;
      }

      r = guestfs_add_drive_opts_argv (g, drv->uri.path, &ad_optargs);
      if (r == -1)
        exit (EXIT_FAILURE);

      drv->nr_drives = 1;
      next_drive++;
      break;

    case drv_d:
      r = add_libvirt_drives (drv->d.guest);
      if (r == -1)
        exit (EXIT_FAILURE);

      drv->nr_drives = r;
      next_drive += r;
      break;

#if COMPILING_GUESTFISH
    case drv_N:
      /* -N option is not affected by --ro */
      r = guestfs_add_drive_opts (g, drv->N.filename,
                                  GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw",
                                  -1);
      if (r == -1)
        exit (EXIT_FAILURE);

      drv->nr_drives = 1;
      next_drive++;
      break;
#endif

    default: /* keep GCC happy */
      abort ();
    }
  }

  return next_drive;
}
Пример #12
0
int
main (int argc, char *argv[])
{
  pid_t md5pid;
  guestfs_h *g;
  int r;
  size_t i;
  int pipefd[2];
  char md5[33];
  int status;

  unlink ("streaming.fifo");
  if (mknod ("streaming.fifo", S_IFIFO | 0600, 0) == -1) {
    perror ("streaming.fifo");
    exit (EXIT_FAILURE);
  }

  if (test_start_nbdkit (NBDKIT_PLUGIN ("streaming"),
                         "pipe=streaming.fifo",
                         "size=640k",
                         NULL) == -1)
    exit (EXIT_FAILURE);

  /* Fork to run a second process which reads from streaming.fifo
   * and checks that the content is correct.
   */
  if (pipe (pipefd) == -1) {
    perror ("pipe");
    exit (EXIT_FAILURE);
  }

  md5pid = fork ();
  if (md5pid == -1) {
    perror ("fork");
    exit (EXIT_FAILURE);
  }

  if (md5pid == 0) {
    /* Child: run md5sum on the pipe. */
    char *argv[] = { "md5sum", NULL };

    close (0);
    open ("streaming.fifo", O_RDONLY);
    close (1);
    dup2 (pipefd[1], 1);
    close (pipefd[0]);

    execvp ("md5sum", argv);
    perror ("md5sum");
    _exit (EXIT_FAILURE);
  }

  close (pipefd[1]);

  g = guestfs_create ();
  if (g == NULL) {
    perror ("guestfs_create");
    exit (EXIT_FAILURE);
  }

  r = guestfs_add_drive_opts (g, "",
                              GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw",
                              GUESTFS_ADD_DRIVE_OPTS_PROTOCOL, "nbd",
                              GUESTFS_ADD_DRIVE_OPTS_SERVER, server,
                              -1);
  if (r == -1)
    exit (EXIT_FAILURE);

  if (guestfs_launch (g) == -1)
    exit (EXIT_FAILURE);

  /* Write linearly to the virtual disk. */
  memset (data, 1, sizeof data);
  for (i = 0; i < 10; ++i) {
    guestfs_pwrite_device (g, "/dev/sda", data, sizeof data,
                           i * sizeof data);
  }

  if (guestfs_shutdown (g) == -1)
    exit (EXIT_FAILURE);

  guestfs_close (g);

  /* We have to explicitly kill nbdkit here so that it closes the
   * pipe.
   */
  kill (pid, SIGINT);

  /* Check the hash computed by the child process. */
  if (read (pipefd[0], md5, 32) != 32) {
    perror ("read");
    exit (EXIT_FAILURE);
  }
  md5[32] = '\0';

  if (strcmp (md5, "2c7f81c580f7f9eb52c1bd2f6f493b6f") != 0) {
    fprintf (stderr, "unexpected hash: %s\n", md5);
    exit (EXIT_FAILURE);
  }

  if (waitpid (md5pid, &status, 0) == -1) {
    perror ("waitpid");
    exit (EXIT_FAILURE);
  }
  if (status != 0) {
    fprintf (stderr, "md5sum subprocess failed\n");
    exit (EXIT_FAILURE);
  }

  exit (EXIT_SUCCESS);
}