Example #1
0
/* This function is called only if the above function was called,
 * and only after we've printed the prompt in interactive mode.
 */
void
print_inspect_prompt (void)
{
  size_t i;
  CLEANUP_FREE char *name = NULL;
  CLEANUP_FREE_STRING_LIST char **mountpoints;

  name = guestfs_inspect_get_product_name (g, root);
  if (name && STRNEQ (name, "unknown"))
    printf (_("Operating system: %s\n"), name);

  mountpoints = guestfs_inspect_get_mountpoints (g, root);
  if (mountpoints == NULL)
    return;

  /* Sort by key. */
  qsort (mountpoints, guestfs___count_strings (mountpoints) / 2,
         2 * sizeof (char *),
         compare_keys);

  for (i = 0; mountpoints[i] != NULL; i += 2) {
    /* Try to make the device name canonical for printing, but don't
     * worry if this fails.
     */
    CLEANUP_FREE char *dev =
      guestfs_canonical_device_name (g, mountpoints[i+1]);

    printf (_("%s mounted on %s\n"),
            dev ? dev : mountpoints[i+1], mountpoints[i]);
  }
}
/* 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);
}
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);
}
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);
}
Example #5
0
/* Start ssh subprocess with the standard arguments and possibly some
 * optional arguments.  Also handles password authentication.
 */
static mexp_h *
start_ssh (struct config *config, char **extra_args, int wait_prompt)
{
  size_t i, j, nr_args, count;
  char port_str[64];
  CLEANUP_FREE /* [sic] */ const char **args = NULL;
  mexp_h *h;
  const int ovecsize = 12;
  int ovector[ovecsize];
  int saved_timeout;

  /* Create the ssh argument array. */
  nr_args = 0;
  if (extra_args != NULL)
    nr_args = guestfs___count_strings (extra_args);

  nr_args += 11;
  args = malloc (sizeof (char *) * nr_args);
  if (args == NULL) {
    perror ("malloc");
    exit (EXIT_FAILURE);
  }
  j = 0;
  args[j++] = "ssh";
  args[j++] = "-p";             /* Port. */
  snprintf (port_str, sizeof port_str, "%d", config->port);
  args[j++] = port_str;
  args[j++] = "-l";             /* Username. */
  args[j++] = config->username ? config->username : "******";
  args[j++] = "-o";             /* Host key will always be novel. */
  args[j++] = "StrictHostKeyChecking=no";
  args[j++] = "-o";            /* Only use password authentication. */
  args[j++] = "PreferredAuthentications=keyboard-interactive,password";
  if (extra_args != NULL) {
    for (i = 0; extra_args[i] != NULL; ++i)
      args[j++] = extra_args[i];
  }
  args[j++] = config->server;   /* Conversion server. */
  args[j++] = NULL;
  assert (j == nr_args);

  h = mexp_spawnv ("ssh", (char **) args);
  if (h == NULL)
    return NULL;

  if (config->password && strlen (config->password) > 0) {
    /* Wait for the password prompt. */
    switch (mexp_expect (h,
                         (mexp_regexp[]) {
                           { 100, .re = password_re },
                           { 0 }
                         }, ovector, ovecsize)) {
Example #6
0
/* Test guestfs___split_string. */
static void
test_split (void)
{
  char **ret;

  ret = guestfs___split_string (':', "");
  assert (ret);
  assert (guestfs___count_strings (ret) == 0);
  guestfs___free_string_list (ret);

  ret = guestfs___split_string (':', "a");
  assert (ret);
  assert (guestfs___count_strings (ret) == 1);
  assert (STREQ (ret[0], "a"));
  guestfs___free_string_list (ret);

  ret = guestfs___split_string (':', ":");
  assert (ret);
  assert (guestfs___count_strings (ret) == 2);
  assert (STREQ (ret[0], ""));
  assert (STREQ (ret[1], ""));
  guestfs___free_string_list (ret);

  ret = guestfs___split_string (':', "::");
  assert (ret);
  assert (guestfs___count_strings (ret) == 3);
  assert (STREQ (ret[0], ""));
  assert (STREQ (ret[1], ""));
  assert (STREQ (ret[2], ""));
  guestfs___free_string_list (ret);

  ret = guestfs___split_string (':', ":a");
  assert (ret);
  assert (guestfs___count_strings (ret) == 2);
  assert (STREQ (ret[0], ""));
  assert (STREQ (ret[1], "a"));
  guestfs___free_string_list (ret);

  ret = guestfs___split_string (':', "a:");
  assert (ret);
  assert (guestfs___count_strings (ret) == 2);
  assert (STREQ (ret[0], "a"));
  assert (STREQ (ret[1], ""));
  guestfs___free_string_list (ret);

  ret = guestfs___split_string (':', "a:b:c");
  assert (ret);
  assert (guestfs___count_strings (ret) == 3);
  assert (STREQ (ret[0], "a"));
  assert (STREQ (ret[1], "b"));
  assert (STREQ (ret[2], "c"));
  guestfs___free_string_list (ret);
}
Example #7
0
struct guestfs_xattr_list *
guestfs__lxattrlist (guestfs_h *g, const char *dir, char *const *names)
{
  size_t len = guestfs___count_strings (names);
  size_t i, old_len;
  struct guestfs_xattr_list *ret;

  ret = safe_malloc (g, sizeof *ret);
  ret->len = 0;
  ret->val = NULL;

  while (len > 0) {
    CLEANUP_FREE_XATTR_LIST struct guestfs_xattr_list *xattrs = NULL;

    /* Note we don't need to free up the strings because take_strings
     * does not do a deep copy.
     */
    CLEANUP_FREE char **first = take_strings (g, names, LXATTRLIST_MAX, &names);
    len = len <= LXATTRLIST_MAX ? 0 : len - LXATTRLIST_MAX;

    xattrs = guestfs_internal_lxattrlist (g, dir, first);

    if (xattrs == NULL) {
      guestfs_free_xattr_list (ret);
      return NULL;
    }

    /* Append xattrs to ret. */
    old_len = ret->len;
    ret->len += xattrs->len;
    ret->val = safe_realloc (g, ret->val,
                             ret->len * sizeof (struct guestfs_xattr));
    for (i = 0; i < xattrs->len; ++i, ++old_len) {
      /* We have to make a deep copy of the attribute name and value.
       */
      ret->val[old_len].attrname = safe_strdup (g, xattrs->val[i].attrname);
      ret->val[old_len].attrval = safe_malloc (g, xattrs->val[i].attrval_len);
      ret->val[old_len].attrval_len = xattrs->val[i].attrval_len;
      memcpy (ret->val[old_len].attrval, xattrs->val[i].attrval,
              xattrs->val[i].attrval_len);
    }
  }

  return ret;
}
Example #8
0
struct guestfs_stat_list *
guestfs__lstatlist (guestfs_h *g, const char *dir, char * const*names)
{
  size_t len = guestfs___count_strings (names);
  size_t old_len;
  struct guestfs_stat_list *ret;

  ret = safe_malloc (g, sizeof *ret);
  ret->len = 0;
  ret->val = NULL;

  while (len > 0) {
    CLEANUP_FREE_STAT_LIST struct guestfs_stat_list *stats = NULL;

    /* Note we don't need to free up the strings because take_strings
     * does not do a deep copy.
     */
    CLEANUP_FREE char **first = take_strings (g, names, LSTATLIST_MAX, &names);

    len = len <= LSTATLIST_MAX ? 0 : len - LSTATLIST_MAX;

    stats = guestfs_internal_lstatlist (g, dir, first);

    if (stats == NULL) {
      guestfs_free_stat_list (ret);
      return NULL;
    }

    /* Append stats to ret. */
    old_len = ret->len;
    ret->len += stats->len;
    ret->val = safe_realloc (g, ret->val,
                             ret->len * sizeof (struct guestfs_stat));
    memcpy (&ret->val[old_len], stats->val,
            stats->len * sizeof (struct guestfs_stat));
  }

  return ret;
}
Example #9
0
void
inspect_mount_root (const char *root)
{
  CLEANUP_FREE_STRING_LIST char **mountpoints =
    guestfs_inspect_get_mountpoints (g, root);
  if (mountpoints == NULL)
    exit (EXIT_FAILURE);

  /* Sort by key length, shortest key first, so that we end up
   * mounting the filesystems in the correct order.
   */
  qsort (mountpoints, guestfs___count_strings (mountpoints) / 2,
         2 * sizeof (char *),
         compare_keys_len);

  size_t i;
  size_t mount_errors = 0;
  for (i = 0; mountpoints[i] != NULL; i += 2) {
    int r;
    if (!read_only)
      r = guestfs_mount (g, mountpoints[i+1], mountpoints[i]);
    else
      r = guestfs_mount_ro (g, mountpoints[i+1], mountpoints[i]);
    if (r == -1) {
      /* If the "/" filesystem could not be mounted, give up, else
       * just count the errors and print a warning.
       */
      if (STREQ (mountpoints[i], "/"))
        exit (EXIT_FAILURE);
      mount_errors++;
    }
  }

  if (mount_errors)
    fprintf (stderr, _("%s: some filesystems could not be mounted (ignored)\n"),
             program_name);
}