Esempio n. 1
0
/* Note: This is testing characters in the Latin2 set, but the
 * encoding is still UTF-8 as it must be for libguestfs.
 */
static void
test_latin2 (guestfs_h *g, const struct filesystem *fs)
{
  /* LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */
  const char O_dacute[] = { 0xc5, 0x90, 0 };
  const char slash_O_dacute[] = { '/', 0xc5, 0x90, 0 };
  /* LATIN SMALL LETTER O WITH DOUBLE ACUTE */
  const char o_dacute[] = { 0xc5, 0x91, 0 };
  const char slash_o_dacute[] = { '/', 0xc5, 0x91, 0 };

  char **files;
  size_t count;

  if (guestfs_touch (g, slash_O_dacute) == -1)
    exit (EXIT_FAILURE);
  if (guestfs_touch (g, slash_o_dacute) == -1)
    exit (EXIT_FAILURE);

  /* Read list of files, check for case sensitivity. */
  files = guestfs_ls (g, "/");
  if (files == NULL)
    exit (EXIT_FAILURE);
  ignore_lost_and_found (files);
  count = guestfs___count_strings (files);

  if (fs->fs_case_insensitive) { /* case insensitive */
    if (count != 1)
      error (EXIT_FAILURE, 0,
             "error: %s: %s is supposed to be case-insensitive, but %zu files "
             "(instead of 1) were returned",
             __func__, fs->fs_name, count);

    if (memcmp (files[0], o_dacute, 3) != 0 &&
        memcmp (files[0], O_dacute, 3) != 0)
      error (EXIT_FAILURE, 0,
             "error: %s: %s returned unexpected filename '%s'",
             __func__, fs->fs_name, files[0]);
  }
  else {                        /* case sensitive */
    if (count != 2)
      error (EXIT_FAILURE, 0,
             "error: %s: %s is supposed to be case-sensitive, but %zu files "
             "(instead of 2) were returned",
             __func__, fs->fs_name, count);

    if (memcmp (files[0], O_dacute, 3) != 0 ||
        memcmp (files[1], o_dacute, 3) != 0)
      error (EXIT_FAILURE, 0,
             "error: %s: %s returned unexpected filenames '%s' and '%s'",
             __func__, fs->fs_name, files[0], files[1]);

    if (guestfs_rm (g, slash_O_dacute) == -1)
      exit (EXIT_FAILURE);
  }

  if (guestfs_rm (g, slash_o_dacute) == -1)
    exit (EXIT_FAILURE);
}
Esempio n. 2
0
static void
test_ascii (guestfs_h *g, const struct filesystem *fs)
{
  char **files;
  size_t count;

  /* Create various ASCII-named files. */
  if (guestfs_touch (g, "/ABC") == -1)
    exit (EXIT_FAILURE);
  if (guestfs_touch (g, "/def") == -1)
    exit (EXIT_FAILURE);
  if (guestfs_touch (g, "/abc") == -1)
    exit (EXIT_FAILURE);

  /* Read list of files, check for case sensitivity. */
  files = guestfs_ls (g, "/");
  if (files == NULL)
    exit (EXIT_FAILURE);
  ignore_lost_and_found (files);
  count = guestfs___count_strings (files);

  if (fs->fs_case_insensitive) { /* case insensitive */
    if (count != 2)
      error (EXIT_FAILURE, 0,
             "error: %s: %s is supposed to be case-insensitive, but %zu files "
             "(instead of 2) were returned",
             __func__, fs->fs_name, count);

    if (STRCASENEQ (files[0], "abc") ||
        STRCASENEQ (files[1], "def"))
      error (EXIT_FAILURE, 0,
             "error: %s: %s returned unexpected filenames '%s' and '%s'",
             __func__, fs->fs_name, files[0], files[1]);
  }
  else {                        /* case sensitive */
    if (count != 3)
      error (EXIT_FAILURE, 0,
             "error: %s: %s is supposed to be case-sensitive, but %zu files "
             "(instead of 3) were returned",
             __func__, fs->fs_name, count);

    if (STRNEQ (files[0], "ABC") == -1 ||
        STRNEQ (files[1], "abc") == -1 ||
        STRNEQ (files[2], "def") == -1)
      error (EXIT_FAILURE, 0,
             "error: %s: %s returned unexpected filenames '%s', '%s', '%s'",
             __func__, fs->fs_name, files[0], files[1], files[2]);

    if (guestfs_rm (g, "/abc") == -1)
      exit (EXIT_FAILURE);
  }

  if (guestfs_rm (g, "/ABC") == -1)
    exit (EXIT_FAILURE);
  if (guestfs_rm (g, "/def") == -1)
    exit (EXIT_FAILURE);
}
Esempio n. 3
0
static void
test_chinese (guestfs_h *g, const struct filesystem *fs)
{
  /* Various Simplified Chinese characters from:
   * https://secure.wikimedia.org/wikipedia/en/wiki/Chinese_characters#Comparisons_of_traditional_Chinese.2C_simplified_Chinese.2C_and_Japanese
   */
  char filenames[][5] = {
    { '/', 0xe7, 0x94, 0xb5, 0 },
    { '/', 0xe4, 0xb9, 0xb0, 0 },
    { '/', 0xe5, 0xbc, 0x80, 0 },
    { '/', 0xe4, 0xb8, 0x9c, 0 },
    { '/', 0xe8, 0xbd, 0xa6, 0 },
    { '/', 0xe7, 0xba, 0xa2, 0 },
  };
  const size_t nr_filenames = sizeof filenames / sizeof filenames[0];
  size_t i, j;
  char **files;
  size_t count;

  for (i = 0; i < nr_filenames; ++i) {
    if (guestfs_touch (g, filenames[i]) == -1)
      exit (EXIT_FAILURE);
  }

  /* Check the filenames. */
  files = guestfs_ls (g, "/");
  if (files == NULL)
    exit (EXIT_FAILURE);
  ignore_lost_and_found (files);
  count = guestfs___count_strings (files);

  if (count != nr_filenames)
    error (EXIT_FAILURE, 0,
           "error: %s: %s returned unexpected number of files "
           "(%zu, expecting %zu)",
           __func__, fs->fs_name, count, nr_filenames);

  for (j = 0; j < count; ++j) {
    for (i = 0; i < nr_filenames; ++i)
      if (memcmp (files[j], &filenames[i][1], 4) == 0)
        goto next;
    error (EXIT_FAILURE, 0,
           "error: %s: %s returned unexpected filename '%s'",
           __func__, fs->fs_name, files[j]);

  next:;
  }

  for (i = 0; i < nr_filenames; ++i)
    if (guestfs_rm (g, filenames[i]) == -1)
      exit (EXIT_FAILURE);
}
Esempio n. 4
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);
}
Esempio n. 5
0
static void
test_virtio_serial (void)
{
  int fd, r, eh;
  char tmpfile[] = "/tmp/speedtestXXXXXX";
  struct sigaction sa, old_sa;

  if (!virtio_serial_upload && !virtio_serial_download)
    return;

  /* Create a sparse file.  We could upload from /dev/zero, but we
   * won't get progress messages because libguestfs tests if the
   * source file is a regular file.
   */
  fd = mkstemp (tmpfile);
  if (fd == -1)
    error (EXIT_FAILURE, errno, "mkstemp: %s", tmpfile);
  if (ftruncate (fd, TEST_SERIAL_MAX_SIZE) == -1)
    error (EXIT_FAILURE, errno, "ftruncate");
  if (close (fd) == -1)
    error (EXIT_FAILURE, errno, "close");

  g = guestfs_create ();
  if (!g)
    error (EXIT_FAILURE, errno, "guestfs_create");

  if (guestfs_add_drive_scratch (g, INT64_C (100*1024*1024), -1) == -1)
    exit (EXIT_FAILURE);

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

  /* Make and mount a filesystem which will be used by the download test. */
  if (guestfs_mkfs (g, "ext4", "/dev/sda") == -1)
    exit (EXIT_FAILURE);
  if (guestfs_mount (g, "/dev/sda", "/") == -1)
    exit (EXIT_FAILURE);

  /* Time out the upload after TEST_SERIAL_MAX_TIME seconds have passed. */
  memset (&sa, 0, sizeof sa);
  sa.sa_handler = stop_transfer;
  sa.sa_flags = SA_RESTART;
  sigaction (SIGALRM, &sa, &old_sa);

  /* Get progress messages, which will tell us how much data has been
   * transferred.
   */
  eh = guestfs_set_event_callback (g, progress_cb, GUESTFS_EVENT_PROGRESS,
                                   0, NULL);
  if (eh == -1)
    exit (EXIT_FAILURE);

  if (virtio_serial_upload) {
    gettimeofday (&start, NULL);
    rate = -1;
    operation = "upload";
    alarm (max_time_override > 0 ? max_time_override : TEST_SERIAL_MAX_TIME);

    /* For the upload test, upload the sparse file to /dev/null in the
     * appliance.  Hopefully this is mostly testing just virtio-serial.
     */
    guestfs_push_error_handler (g, NULL, NULL);
    r = guestfs_upload (g, tmpfile, "/dev/null");
    alarm (0);
    unlink (tmpfile);
    guestfs_pop_error_handler (g);

    /* It's possible that the upload will finish before the alarm fires,
     * or that the upload will be stopped by the alarm.
     */
    if (r == -1 && guestfs_last_errno (g) != EINTR) {
      fprintf (stderr,
               "%s: expecting upload command to return EINTR\n%s\n",
               guestfs_int_program_name, guestfs_last_error (g));
      exit (EXIT_FAILURE);
    }

    if (rate == -1) {
    rate_error:
      fprintf (stderr, "%s: internal error: progress callback was not called! (r=%d, errno=%d)\n",
               guestfs_int_program_name,
               r, guestfs_last_errno (g));
      exit (EXIT_FAILURE);
    }

    print_rate ("virtio-serial upload rate:", rate);
  }

  if (virtio_serial_download) {
    /* For the download test, download a sparse file within the
     * appliance to /dev/null on the host.
     */
    if (guestfs_touch (g, "/sparse") == -1)
      exit (EXIT_FAILURE);
    if (guestfs_truncate_size (g, "/sparse", TEST_SERIAL_MAX_SIZE) == -1)
      exit (EXIT_FAILURE);

    gettimeofday (&start, NULL);
    rate = -1;
    operation = "download";
    alarm (max_time_override > 0 ? max_time_override : TEST_SERIAL_MAX_TIME);
    guestfs_push_error_handler (g, NULL, NULL);
    r = guestfs_download (g, "/sparse", "/dev/null");
    alarm (0);
    guestfs_pop_error_handler (g);

    if (r == -1 && guestfs_last_errno (g) != EINTR) {
      fprintf (stderr,
               "%s: expecting download command to return EINTR\n%s\n",
               guestfs_int_program_name, guestfs_last_error (g));
      exit (EXIT_FAILURE);
    }

    if (rate == -1)
      goto rate_error;

    print_rate ("virtio-serial download rate:", rate);
  }

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

  guestfs_close (g);

  /* Restore SIGALRM signal handler. */
  sigaction (SIGALRM, &old_sa, NULL);
}
Esempio n. 6
0
int
main (int argc, char *argv[])
{
  guestfs_h *g;
  int r, err;
  struct guestfs_stat *stat;

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

  if (guestfs_add_drive_scratch (g, 524288000, -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 read-only, and check that errno == EROFS is passed back when
   * we create a file.
   */
  if (guestfs_mount_ro (g, "/dev/sda1", "/") == -1)
    exit (EXIT_FAILURE);

  r = guestfs_touch (g, "/test");
  if (r != -1) {
    fprintf (stderr,
             "guestfs_touch: expected error for read-only filesystem\n");
    exit (EXIT_FAILURE);
  }

  err = guestfs_last_errno (g);
  if (err != EROFS) {
    fprintf (stderr,
             "guestfs_touch: expected errno == EROFS, but got %d\n", err);
    exit (EXIT_FAILURE);
  }

  if (guestfs_umount (g, "/") == -1)
    exit (EXIT_FAILURE);

  /* Mount it writable and test some other errors. */
  if (guestfs_mount (g, "/dev/sda1", "/") == -1)
    exit (EXIT_FAILURE);

  stat = guestfs_lstat (g, "/nosuchfile");
  if (stat != NULL) {
    fprintf (stderr,
             "guestfs_lstat: expected error for missing file\n");
    exit (EXIT_FAILURE);
  }

  err = guestfs_last_errno (g);
  if (err != ENOENT) {
    fprintf (stderr,
             "guestfs_lstat: expected errno == ENOENT, but got %d\n", err);
    exit (EXIT_FAILURE);
  }

  if (guestfs_touch (g, "/test") == -1)
    exit (EXIT_FAILURE);

  r = guestfs_mkdir (g, "/test");
  if (r != -1) {
    fprintf (stderr,
             "guestfs_mkdir: expected error for file which exists\n");
    exit (EXIT_FAILURE);
  }

  err = guestfs_last_errno (g);
  if (err != EEXIST) {
    fprintf (stderr,
             "guestfs_mkdir: expected errno == EEXIST, but got %d\n", err);
    exit (EXIT_FAILURE);
  }

  guestfs_close (g);

  exit (EXIT_SUCCESS);
}