Пример #1
0
/* Get the first line of a small file, without any trailing newline
 * character.
 *
 * NOTE: If the file is completely empty or begins with a '\n'
 * character, this returns an empty string (not NULL).  The caller
 * will usually need to check for this case.
 */
char *
guestfs_int_first_line_of_file (guestfs_h *g, const char *filename)
{
  char **lines = NULL; /* sic: not CLEANUP_FREE_STRING_LIST */
  int64_t size;
  char *ret;

  /* Don't trust guestfs_head_n not to break with very large files.
   * Check the file size is something reasonable first.
   */
  size = guestfs_filesize (g, filename);
  if (size == -1)
    /* guestfs_filesize failed and has already set error in handle */
    return NULL;
  if (size > MAX_SMALL_FILE_SIZE) {
    error (g, _("size of %s is unreasonably large (%" PRIi64 " bytes)"),
           filename, size);
    return NULL;
  }

  lines = guestfs_head_n (g, 1, filename);
  if (lines == NULL)
    return NULL;
  if (lines[0] == NULL) {
    guestfs_int_free_string_list (lines);
    /* Empty file: Return an empty string as explained above. */
    return safe_strdup (g, "");
  }
  /* lines[1] should be NULL because of '1' argument above ... */

  ret = lines[0];               /* caller frees */

  free (lines);

  return ret;
}
Пример #2
0
static int
parse_suse_release (guestfs_h *g, struct inspect_fs *fs, const char *filename)
{
  int64_t size;
  char *major, *minor;
  CLEANUP_FREE_STRING_LIST char **lines = NULL;
  int r = -1;

  /* Don't trust guestfs_head_n not to break with very large files.
   * Check the file size is something reasonable first.
   */
  size = guestfs_filesize (g, filename);
  if (size == -1)
    /* guestfs_filesize failed and has already set error in handle */
    return -1;
  if (size > MAX_SMALL_FILE_SIZE) {
    error (g, _("size of %s is unreasonably large (%" PRIi64 " bytes)"),
           filename, size);
    return -1;
  }

  lines = guestfs_head_n (g, 10, filename);
  if (lines == NULL)
    return -1;

  if (lines[0] == NULL)
    goto out;

  /* First line is dist release name */
  fs->product_name = safe_strdup (g, lines[0]);

  /* Match SLES first because openSuSE regex overlaps some SLES release strings */
  if (match (g, fs->product_name, re_sles) || match (g, fs->product_name, re_nld)) {
    fs->distro = OS_DISTRO_SLES;

    /* Second line contains version string */
    if (lines[1] == NULL)
      goto out;
    major = match1 (g, lines[1], re_sles_version);
    if (major == NULL)
      goto out;
    fs->major_version = guestfs___parse_unsigned_int (g, major);
    free (major);
    if (fs->major_version == -1)
      goto out;

    /* Third line contains service pack string */
    if (lines[2] == NULL)
      goto out;
    minor = match1 (g, lines[2], re_sles_patchlevel);
    if (minor == NULL)
      goto out;
    fs->minor_version = guestfs___parse_unsigned_int (g, minor);
    free (minor);
    if (fs->minor_version == -1)
      goto out;
  }
  else if (match (g, fs->product_name, re_opensuse)) {
    fs->distro = OS_DISTRO_OPENSUSE;

    /* Second line contains version string */
    if (lines[1] == NULL)
      goto out;
    if (match2 (g, lines[1], re_opensuse_version, &major, &minor)) {
      fs->major_version = guestfs___parse_unsigned_int (g, major);
      fs->minor_version = guestfs___parse_unsigned_int (g, minor);
      free (major);
      free (minor);
      if (fs->major_version == -1 || fs->minor_version == -1)
        goto out;
    }
  }

  r = 0;

out:
  return r;
}
Пример #3
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);
}
Пример #4
0
/* Ubuntu has /etc/lsb-release containing:
 *   DISTRIB_ID=Ubuntu                                # Distro
 *   DISTRIB_RELEASE=10.04                            # Version
 *   DISTRIB_CODENAME=lucid
 *   DISTRIB_DESCRIPTION="Ubuntu 10.04.1 LTS"         # Product name
 *
 * [Ubuntu-derived ...] Linux Mint was found to have this:
 *   DISTRIB_ID=LinuxMint
 *   DISTRIB_RELEASE=10
 *   DISTRIB_CODENAME=julia
 *   DISTRIB_DESCRIPTION="Linux Mint 10 Julia"
 * Linux Mint also has /etc/linuxmint/info with more information,
 * but we can use the LSB file.
 *
 * Mandriva has:
 *   LSB_VERSION=lsb-4.0-amd64:lsb-4.0-noarch
 *   DISTRIB_ID=MandrivaLinux
 *   DISTRIB_RELEASE=2010.1
 *   DISTRIB_CODENAME=Henry_Farman
 *   DISTRIB_DESCRIPTION="Mandriva Linux 2010.1"
 * Mandriva also has a normal release file called /etc/mandriva-release.
 */
static int
parse_lsb_release (guestfs_h *g, struct inspect_fs *fs)
{
  const char *filename = "/etc/lsb-release";
  int64_t size;
  CLEANUP_FREE_STRING_LIST char **lines = NULL;
  size_t i;
  int r = 0;

  /* Don't trust guestfs_head_n not to break with very large files.
   * Check the file size is something reasonable first.
   */
  size = guestfs_filesize (g, filename);
  if (size == -1)
    /* guestfs_filesize failed and has already set error in handle */
    return -1;
  if (size > MAX_SMALL_FILE_SIZE) {
    error (g, _("size of %s is unreasonably large (%" PRIi64 " bytes)"),
           filename, size);
    return -1;
  }

  lines = guestfs_head_n (g, 10, filename);
  if (lines == NULL)
    return -1;

  for (i = 0; lines[i] != NULL; ++i) {
    if (fs->distro == 0 &&
        STREQ (lines[i], "DISTRIB_ID=Ubuntu")) {
      fs->distro = OS_DISTRO_UBUNTU;
      r = 1;
    }
    else if (fs->distro == 0 &&
             STREQ (lines[i], "DISTRIB_ID=LinuxMint")) {
      fs->distro = OS_DISTRO_LINUX_MINT;
      r = 1;
    }
    else if (fs->distro == 0 &&
             STREQ (lines[i], "DISTRIB_ID=MandrivaLinux")) {
      fs->distro = OS_DISTRO_MANDRIVA;
      r = 1;
    }
    else if (fs->distro == 0 &&
             STREQ (lines[i], "DISTRIB_ID=\"Mageia\"")) {
      fs->distro = OS_DISTRO_MAGEIA;
      r = 1;
    }
    else if (STRPREFIX (lines[i], "DISTRIB_RELEASE=")) {
      char *major, *minor;
      if (match2 (g, &lines[i][16], re_major_minor, &major, &minor)) {
        fs->major_version = guestfs___parse_unsigned_int (g, major);
        free (major);
        if (fs->major_version == -1) {
          free (minor);
          return -1;
        }
        fs->minor_version = guestfs___parse_unsigned_int (g, minor);
        free (minor);
        if (fs->minor_version == -1)
          return -1;
      }
    }
    else if (fs->product_name == NULL &&
             (STRPREFIX (lines[i], "DISTRIB_DESCRIPTION=\"") ||
              STRPREFIX (lines[i], "DISTRIB_DESCRIPTION='"))) {
      size_t len = strlen (lines[i]) - 21 - 1;
      fs->product_name = safe_strndup (g, &lines[i][21], len);
      r = 1;
    }
    else if (fs->product_name == NULL &&
             STRPREFIX (lines[i], "DISTRIB_DESCRIPTION=")) {
      size_t len = strlen (lines[i]) - 20;
      fs->product_name = safe_strndup (g, &lines[i][20], len);
      r = 1;
    }
  }

  /* The unnecessary construct in the next line is required to
   * workaround -Wstrict-overflow warning in gcc 4.5.1.
   */
  return r ? 1 : 0;
}