Beispiel #1
0
static void
output_mountpoints (xmlTextWriterPtr xo, char *root)
{
  size_t i;

  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, and then name, so the
   * output is stable.
   */
  qsort (mountpoints, guestfs_int_count_strings (mountpoints) / 2,
         2 * sizeof (char *),
         compare_keys_len);

  XMLERROR (-1, xmlTextWriterStartElement (xo, BAD_CAST "mountpoints"));

  for (i = 0; mountpoints[i] != NULL; i += 2) {
    CLEANUP_FREE char *p = guestfs_canonical_device_name (g, mountpoints[i+1]);
    if (!p)
      exit (EXIT_FAILURE);

    XMLERROR (-1,
              xmlTextWriterStartElement (xo, BAD_CAST "mountpoint"));
    XMLERROR (-1,
              xmlTextWriterWriteAttribute (xo, BAD_CAST "dev", BAD_CAST p));
    XMLERROR (-1,
              xmlTextWriterWriteString (xo, BAD_CAST mountpoints[i]));
    XMLERROR (-1, xmlTextWriterEndElement (xo));
  }

  XMLERROR (-1, xmlTextWriterEndElement (xo));
}
static void
do_output_blockdevs (void)
{
  size_t i;

  CLEANUP_FREE_STRING_LIST char **devices = guestfs_list_devices (g);
  if (devices == NULL)
    exit (EXIT_FAILURE);

  for (i = 0; devices[i] != NULL; ++i) {
    int64_t size = -1;
    CLEANUP_FREE_STRING_LIST char **parents = NULL;
    CLEANUP_FREE char *dev;

    dev = guestfs_canonical_device_name (g, devices[i]);
    if (!dev)
      exit (EXIT_FAILURE);

    if ((columns & COLUMN_SIZE)) {
      size = guestfs_blockdev_getsize64 (g, devices[i]);
      if (size == -1)
        exit (EXIT_FAILURE);
    }

    if (is_md (devices[i]))
      parents = parents_of_md (devices[i]);
    else
      parents = no_parents ();

    write_row (dev, "device",
               NULL, NULL, -1, size, parents, NULL);
  }
}
Beispiel #3
0
/* If the -m option fails on any command, display a useful error
 * message listing the mountpoints.
 */
static void
display_mountpoints_on_failure (const char *mp_device,
                                const char *user_supplied_options)
{
  CLEANUP_FREE_STRING_LIST char **fses = guestfs_list_filesystems (g);
  size_t i;

  if (fses == NULL || fses[0] == NULL)
    return;

  fprintf (stderr, _("%s: '%s' could not be mounted.\n"),
           program_name, mp_device);

  if (user_supplied_options)
    fprintf (stderr, _("%s: Check mount(8) man page to ensure options '%s'\n"
                       "%s: are supported by the filesystem that is being mounted.\n"),
             program_name, user_supplied_options, program_name);

  fprintf (stderr, _("%s: Did you mean to mount one of these filesystems?\n"),
           program_name);

  for (i = 0; fses[i] != NULL; i += 2) {
    CLEANUP_FREE char *p = guestfs_canonical_device_name (g, fses[i]);
    fprintf (stderr, "%s: \t%s (%s)\n", program_name,
             p ? p : fses[i], fses[i+1]);
  }
}
Beispiel #4
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]);
  }
}
Beispiel #5
0
static void
output_filesystems (xmlTextWriterPtr xo, char *root)
{
  char *str;
  size_t i;

  CLEANUP_FREE_STRING_LIST char **filesystems =
    guestfs_inspect_get_filesystems (g, root);
  if (filesystems == NULL)
    exit (EXIT_FAILURE);

  /* Sort by name so the output is stable. */
  qsort (filesystems, guestfs_int_count_strings (filesystems), sizeof (char *),
         compare_keys);

  XMLERROR (-1, xmlTextWriterStartElement (xo, BAD_CAST "filesystems"));

  for (i = 0; filesystems[i] != NULL; ++i) {
    str = guestfs_canonical_device_name (g, filesystems[i]);
    if (!str)
      exit (EXIT_FAILURE);

    XMLERROR (-1, xmlTextWriterStartElement (xo, BAD_CAST "filesystem"));
    XMLERROR (-1,
              xmlTextWriterWriteAttribute (xo, BAD_CAST "dev", BAD_CAST str));
    free (str);

    guestfs_push_error_handler (g, NULL, NULL);

    str = guestfs_vfs_type (g, filesystems[i]);
    if (str && str[0])
      XMLERROR (-1,
                xmlTextWriterWriteElement (xo, BAD_CAST "type",
                                           BAD_CAST str));
    free (str);

    str = guestfs_vfs_label (g, filesystems[i]);
    if (str && str[0])
      XMLERROR (-1,
                xmlTextWriterWriteElement (xo, BAD_CAST "label",
                                           BAD_CAST str));
    free (str);

    str = guestfs_vfs_uuid (g, filesystems[i]);
    if (str && str[0])
      XMLERROR (-1,
                xmlTextWriterWriteElement (xo, BAD_CAST "uuid",
                                           BAD_CAST str));
    free (str);

    guestfs_pop_error_handler (g);

    XMLERROR (-1, xmlTextWriterEndElement (xo));
  }

  XMLERROR (-1, xmlTextWriterEndElement (xo));
}
static void
do_output_partitions (void)
{
  size_t i;

  CLEANUP_FREE_STRING_LIST char **parts = guestfs_list_partitions (g);
  if (parts == NULL)
    exit (EXIT_FAILURE);

  for (i = 0; parts[i] != NULL; ++i) {
    CLEANUP_FREE char *dev = NULL, *parent_name = NULL, *canonical_name = NULL;
    const char *parents[2];
    int64_t size = -1;
    int mbr_id = -1;

    dev = guestfs_canonical_device_name (g, parts[i]);
    if (!dev)
      exit (EXIT_FAILURE);

    if ((columns & COLUMN_SIZE)) {
      size = guestfs_blockdev_getsize64 (g, parts[i]);
      if (size == -1)
        exit (EXIT_FAILURE);
    }
    if ((columns & COLUMN_PARENTS)) {
      parent_name = guestfs_part_to_dev (g, parts[i]);
      if (parent_name == NULL)
        exit (EXIT_FAILURE);

      if ((columns & COLUMN_MBR))
        mbr_id = get_mbr_id (parts[i], parent_name);

      canonical_name = guestfs_canonical_device_name (g, parent_name);
      if (!canonical_name)
        exit (EXIT_FAILURE);

      parents[0] = canonical_name;
      parents[1] = NULL;
    }

    write_row (dev, "partition",
               NULL, NULL, mbr_id, size, (char **) parents, NULL);
  }
}
Beispiel #7
0
static void
output_drive_mappings (xmlTextWriterPtr xo, char *root)
{
  CLEANUP_FREE_STRING_LIST char **drive_mappings = NULL;
  char *str;
  size_t i;

  guestfs_push_error_handler (g, NULL, NULL);
  drive_mappings = guestfs_inspect_get_drive_mappings (g, root);
  guestfs_pop_error_handler (g);
  if (drive_mappings == NULL)
    return;

  if (drive_mappings[0] == NULL)
    return;

  /* Sort by key. */
  qsort (drive_mappings,
         guestfs_int_count_strings (drive_mappings) / 2, 2 * sizeof (char *),
         compare_keys_nocase);

  XMLERROR (-1, xmlTextWriterStartElement (xo, BAD_CAST "drive_mappings"));

  for (i = 0; drive_mappings[i] != NULL; i += 2) {
    str = guestfs_canonical_device_name (g, drive_mappings[i+1]);
    if (!str)
      exit (EXIT_FAILURE);

    XMLERROR (-1,
              xmlTextWriterStartElement (xo, BAD_CAST "drive_mapping"));
    XMLERROR (-1,
              xmlTextWriterWriteAttribute (xo, BAD_CAST "name",
                                           BAD_CAST drive_mappings[i]));
    XMLERROR (-1,
              xmlTextWriterWriteString (xo, BAD_CAST str));
    XMLERROR (-1, xmlTextWriterEndElement (xo));

    free (str);
  }

  XMLERROR (-1, xmlTextWriterEndElement (xo));
}
static void
do_output_pvs (void)
{
  size_t i;
  struct guestfs_lvm_pv_list *pvs = get_pvs ();

  for (i = 0; i < pvs->len; ++i) {
    char uuid[33];
    const char *parents[1] = { NULL };

    CLEANUP_FREE char *dev =
      guestfs_canonical_device_name (g, pvs->val[i].pv_name);
    if (!dev)
      exit (EXIT_FAILURE);

    memcpy (uuid, pvs->val[i].pv_uuid, 32);
    uuid[32] = '\0';
    write_row (dev, "pv",
               NULL, NULL, -1, (int64_t) pvs->val[i].pv_size,
               (char **) parents, uuid);
  }
}
Beispiel #9
0
static void
output_root (xmlTextWriterPtr xo, char *root)
{
  char *str;
  int i, r;
  char buf[32];
  char *canonical_root;
  size_t size;

  XMLERROR (-1, xmlTextWriterStartElement (xo, BAD_CAST "operatingsystem"));

  canonical_root = guestfs_canonical_device_name (g, root);
  if (canonical_root == NULL)
    exit (EXIT_FAILURE);
  XMLERROR (-1,
	    xmlTextWriterWriteElement (xo, BAD_CAST "root", BAD_CAST canonical_root));
  free (canonical_root);

  str = guestfs_inspect_get_type (g, root);
  if (!str) exit (EXIT_FAILURE);
  if (STRNEQ (str, "unknown"))
    XMLERROR (-1,
	      xmlTextWriterWriteElement (xo, BAD_CAST "name", BAD_CAST str));
  free (str);

  str = guestfs_inspect_get_arch (g, root);
  if (!str) exit (EXIT_FAILURE);
  if (STRNEQ (str, "unknown"))
    XMLERROR (-1,
	      xmlTextWriterWriteElement (xo, BAD_CAST "arch", BAD_CAST str));
  free (str);

  str = guestfs_inspect_get_distro (g, root);
  if (!str) exit (EXIT_FAILURE);
  if (STRNEQ (str, "unknown"))
    XMLERROR (-1,
	      xmlTextWriterWriteElement (xo, BAD_CAST "distro", BAD_CAST str));
  free (str);

  str = guestfs_inspect_get_product_name (g, root);
  if (!str) exit (EXIT_FAILURE);
  if (STRNEQ (str, "unknown"))
    XMLERROR (-1,
	      xmlTextWriterWriteElement (xo, BAD_CAST "product_name", BAD_CAST str));
  free (str);

  str = guestfs_inspect_get_product_variant (g, root);
  if (!str) exit (EXIT_FAILURE);
  if (STRNEQ (str, "unknown"))
    XMLERROR (-1,
	      xmlTextWriterWriteElement (xo, BAD_CAST "product_variant", BAD_CAST str));
  free (str);

  i = guestfs_inspect_get_major_version (g, root);
  snprintf (buf, sizeof buf, "%d", i);
  XMLERROR (-1,
	    xmlTextWriterWriteElement (xo, BAD_CAST "major_version", BAD_CAST buf));
  i = guestfs_inspect_get_minor_version (g, root);
  snprintf (buf, sizeof buf, "%d", i);
  XMLERROR (-1,
	    xmlTextWriterWriteElement (xo, BAD_CAST "minor_version", BAD_CAST buf));

  str = guestfs_inspect_get_package_format (g, root);
  if (!str) exit (EXIT_FAILURE);
  if (STRNEQ (str, "unknown"))
    XMLERROR (-1,
	      xmlTextWriterWriteElement (xo, BAD_CAST "package_format", BAD_CAST str));
  free (str);

  str = guestfs_inspect_get_package_management (g, root);
  if (!str) exit (EXIT_FAILURE);
  if (STRNEQ (str, "unknown"))
    XMLERROR (-1,
	      xmlTextWriterWriteElement (xo, BAD_CAST "package_management",
					 BAD_CAST str));
  free (str);

  /* inspect-get-windows-systemroot will fail with non-windows guests,
   * or if the systemroot could not be determined for a windows guest.
   * Disable error output around this call.
   */
  guestfs_push_error_handler (g, NULL, NULL);
  str = guestfs_inspect_get_windows_systemroot (g, root);
  if (str)
    XMLERROR (-1,
              xmlTextWriterWriteElement (xo, BAD_CAST "windows_systemroot",
                                         BAD_CAST str));
  free (str);
  str = guestfs_inspect_get_windows_current_control_set (g, root);
  if (str)
    XMLERROR (-1,
              xmlTextWriterWriteElement (xo, BAD_CAST "windows_current_control_set",
                                         BAD_CAST str));
  free (str);
  guestfs_pop_error_handler (g);

  str = guestfs_inspect_get_hostname (g, root);
  if (!str) exit (EXIT_FAILURE);
  if (STRNEQ (str, "unknown"))
    XMLERROR (-1,
	      xmlTextWriterWriteElement (xo, BAD_CAST "hostname",
					 BAD_CAST str));
  free (str);

  str = guestfs_inspect_get_format (g, root);
  if (!str) exit (EXIT_FAILURE);
  if (STRNEQ (str, "unknown"))
    XMLERROR (-1,
	      xmlTextWriterWriteElement (xo, BAD_CAST "format",
					 BAD_CAST str));
  free (str);

  r = guestfs_inspect_is_live (g, root);
  if (r > 0) {
    XMLERROR (-1,
              xmlTextWriterStartElement (xo, BAD_CAST "live"));
    XMLERROR (-1, xmlTextWriterEndElement (xo));
  }

  r = guestfs_inspect_is_netinst (g, root);
  if (r > 0) {
    XMLERROR (-1,
              xmlTextWriterStartElement (xo, BAD_CAST "netinst"));
    XMLERROR (-1, xmlTextWriterEndElement (xo));
  }

  r = guestfs_inspect_is_multipart (g, root);
  if (r > 0) {
    XMLERROR (-1,
              xmlTextWriterStartElement (xo, BAD_CAST "multipart"));
    XMLERROR (-1, xmlTextWriterEndElement (xo));
  }

  output_mountpoints (xo, root);

  output_filesystems (xo, root);

  output_drive_mappings (xo, root);

  /* We need to mount everything up in order to read out the list of
   * applications and the icon, ie. everything below this point.
   */
  inspect_mount_root (g, root);

  output_applications (xo, root);

  /* Don't return favicon.  RHEL 7 and Fedora have crappy 16x16
   * favicons in the base distro.
   */
  str = guestfs_inspect_get_icon (g, root, &size,
                                  GUESTFS_INSPECT_GET_ICON_FAVICON, 0,
                                  -1);
  if (!str) exit (EXIT_FAILURE);
  if (size > 0) {
    XMLERROR (-1, xmlTextWriterStartElement (xo, BAD_CAST "icon"));
    XMLERROR (-1, xmlTextWriterWriteBase64 (xo, str, 0, size));
    XMLERROR (-1, xmlTextWriterEndElement (xo));
  }
  /* Note we must free (str) even if size == 0, because that indicates
   * there was no icon.
   */
  free (str);

  /* Unmount (see inspect_mount_root above). */
  if (guestfs_umount_all (g) == -1)
    exit (EXIT_FAILURE);

  XMLERROR (-1, xmlTextWriterEndElement (xo));
}
Beispiel #10
0
static void
do_output_filesystems (void)
{
  size_t i;

  CLEANUP_FREE_STRING_LIST char **fses = guestfs_list_filesystems (g);
  if (fses == NULL)
    exit (EXIT_FAILURE);

  for (i = 0; fses[i] != NULL; i += 2) {
    CLEANUP_FREE char *dev = NULL, *vfs_label = NULL, *vfs_uuid = NULL;
    CLEANUP_FREE_STRING_LIST char **parents = NULL;
    int64_t size = -1;

    /* Skip swap and unknown, unless --extra flag was given. */
    if (!(output & OUTPUT_FILESYSTEMS_EXTRA) &&
        (STREQ (fses[i+1], "swap") || STREQ (fses[i+1], "unknown")))
      continue;

    dev = guestfs_canonical_device_name (g, fses[i]);
    if (dev == NULL)
      exit (EXIT_FAILURE);

    /* Only bother to look these up if we will be displaying them,
     * otherwise pass them as NULL.
     */
    if ((columns & COLUMN_VFS_LABEL)) {
      guestfs_push_error_handler (g, NULL, NULL);
      vfs_label = guestfs_vfs_label (g, fses[i]);
      guestfs_pop_error_handler (g);
      if (vfs_label == NULL) {
        vfs_label = strdup ("");
        if (!vfs_label) {
          perror ("strdup");
          exit (EXIT_FAILURE);
        }
      }
    }
    if ((columns & COLUMN_UUID)) {
      guestfs_push_error_handler (g, NULL, NULL);
      vfs_uuid = guestfs_vfs_uuid (g, fses[i]);
      guestfs_pop_error_handler (g);
      if (vfs_uuid == NULL) {
        vfs_uuid = strdup ("");
        if (!vfs_uuid) {
          perror ("strdup");
          exit (EXIT_FAILURE);
        }
      }
    }
    if ((columns & COLUMN_SIZE)) {
      size = guestfs_blockdev_getsize64 (g, fses[i]);
      if (size == -1)
        exit (EXIT_FAILURE);
    }

    if (is_md (fses[i]))
      parents = parents_of_md (fses[i]);
    else
      parents = no_parents ();

    write_row (dev, "filesystem",
               fses[i+1], vfs_label, -1, size, parents, vfs_uuid);
  }
}
Beispiel #11
0
void
scan (size_t *worst_alignment, const char *prefix)
{
  char **devices, *p;
  size_t i, j;
  size_t alignment;
  uint64_t start;
  struct guestfs_partition_list *parts;

  devices = guestfs_list_devices (g);
  if (devices == NULL)
    exit (EXIT_FAILURE);

  for (i = 0; devices[i] != NULL; ++i) {
    parts = guestfs_part_list (g, devices[i]);
    if (parts == NULL)
      exit (EXIT_FAILURE);

    /* Canonicalize the name of the device for printing. */
    p = guestfs_canonical_device_name (g, devices[i]);
    if (p == NULL)
      exit (EXIT_FAILURE);
    free (devices[i]);
    devices[i] = p;

    for (j = 0; j < parts->len; ++j) {
      /* Start offset of the partition in bytes. */
      start = parts->val[j].part_start;

      if (!quiet) {
        if (prefix)
          printf ("%s:", prefix);

        printf ("%s%d %12" PRIu64 " ",
                devices[i], (int) parts->val[j].part_num, start);
      }

      /* What's the alignment? */
      if (start == 0)           /* Probably not possible, but anyway. */
        alignment = 64;
      else
        for (alignment = 0; (start & 1) == 0; alignment++, start /= 2)
          ;

      if (!quiet) {
        if (alignment < 10)
          printf ("%12" PRIu64 "    ", UINT64_C(1) << alignment);
        else if (alignment < 64)
          printf ("%12" PRIu64 "K   ", UINT64_C(1) << (alignment - 10));
        else
          printf ("- ");
      }

      if (alignment < *worst_alignment)
        *worst_alignment = alignment;

      if (alignment < 12) {     /* Bad in general: < 4K alignment */
        if (!quiet)
          printf ("bad (%s)\n", _("alignment < 4K"));
      } else if (alignment < 16) { /* Bad on NetApps: < 64K alignment */
        if (!quiet)
          printf ("bad (%s)\n", _("alignment < 64K"));
      } else {
        if (!quiet)
          printf ("ok\n");
      }
    }

    guestfs_free_partition_list (parts);
    free (devices[i]);
  }
  free (devices);
}
Beispiel #12
0
static int
scan (guestfs_h *g, const char *prefix, FILE *fp)
{
  size_t i, j;
  size_t alignment;
  uint64_t start;
  int err;

  CLEANUP_FREE_STRING_LIST char **devices = guestfs_list_devices (g);
  if (devices == NULL)
    return -1;

  for (i = 0; devices[i] != NULL; ++i) {
    CLEANUP_FREE char *name = NULL;

    CLEANUP_FREE_PARTITION_LIST struct guestfs_partition_list *parts =
      guestfs_part_list (g, devices[i]);
    if (parts == NULL)
      return -1;

    /* Canonicalize the name of the device for printing. */
    name = guestfs_canonical_device_name (g, devices[i]);
    if (name == NULL)
      return -1;

    for (j = 0; j < parts->len; ++j) {
      /* Start offset of the partition in bytes. */
      start = parts->val[j].part_start;

      if (!quiet) {
        if (prefix)
          fprintf (fp, "%s:", prefix);

        fprintf (fp, "%s%d %12" PRIu64 " ",
                 name, (int) parts->val[j].part_num, start);
      }

      /* What's the alignment? */
      if (start == 0)           /* Probably not possible, but anyway. */
        alignment = 64;
      else
        for (alignment = 0; (start & 1) == 0; alignment++, start /= 2)
          ;

      if (!quiet) {
        if (alignment < 10)
          fprintf (fp, "%12" PRIu64 "    ", UINT64_C(1) << alignment);
        else if (alignment < 64)
          fprintf (fp, "%12" PRIu64 "K   ", UINT64_C(1) << (alignment - 10));
        else
          fprintf (fp, "- ");
      }

      err = pthread_mutex_lock (&worst_alignment_mutex);
      assert (err == 0);
      if (alignment < worst_alignment)
        worst_alignment = alignment;
      err = pthread_mutex_unlock (&worst_alignment_mutex);
      assert (err == 0);

      if (alignment < 12) {     /* Bad in general: < 4K alignment */
        if (!quiet)
          fprintf (fp, "bad (%s)\n", _("alignment < 4K"));
      } else if (alignment < 16) { /* Bad on NetApps: < 64K alignment */
        if (!quiet)
          fprintf (fp, "bad (%s)\n", _("alignment < 64K"));
      } else {
        if (!quiet)
          fprintf (fp, "ok\n");
      }
    }
  }

  return 0;
}