Пример #1
0
static void
read_all (guestfs_h *g, void *retv, const char *buf, size_t len)
{
  char **ret = retv;

  *ret = safe_strndup (g, buf, len);
}
Пример #2
0
/* Match a regular expression which contains exactly two captures. */
int
guestfs___match2 (guestfs_h *g, const char *str, const pcre *re,
                  char **ret1, char **ret2)
{
  size_t len = strlen (str);
  int vec[30], r;

  r = pcre_exec (re, NULL, str, len, 0, 0, vec, 30);
  if (r == PCRE_ERROR_NOMATCH)
    return 0;

  *ret1 = NULL;
  *ret2 = NULL;

  if (r > 1) *ret1 = safe_strndup (g, &str[vec[2]], vec[3]-vec[2]);
  if (r > 2) *ret2 = safe_strndup (g, &str[vec[4]], vec[5]-vec[4]);

  return 1;
}
Пример #3
0
/* Match a regular expression which contains exactly one capture.  If
 * the string matches, return the capture, otherwise return NULL.  The
 * caller must free the result.
 */
char *
guestfs___match1 (guestfs_h *g, const char *str, const pcre *re)
{
  size_t len = strlen (str);
  int vec[30], r;

  r = pcre_exec (re, NULL, str, len, 0, 0, vec, sizeof vec / sizeof vec[0]);
  if (r == PCRE_ERROR_NOMATCH)
    return NULL;

  return r == 2 ? safe_strndup (g, &str[vec[2]], vec[3]-vec[2]) : NULL;
}
Пример #4
0
/* Match a regular expression which contains exactly six captures. */
int
guestfs___match6 (guestfs_h *g, const char *str, const pcre *re,
                  char **ret1, char **ret2, char **ret3, char **ret4,
                  char **ret5, char **ret6)
{
  size_t len = strlen (str);
  int vec[30], r;

  r = pcre_exec (re, NULL, str, len, 0, 0, vec, 30);
  if (r == PCRE_ERROR_NOMATCH)
    return 0;

  *ret1 = NULL;
  *ret2 = NULL;
  *ret3 = NULL;
  *ret4 = NULL;
  *ret5 = NULL;
  *ret6 = NULL;

  if (r > 1) *ret1 = safe_strndup (g, &str[vec[2]], vec[3]-vec[2]);
  if (r > 2) *ret2 = safe_strndup (g, &str[vec[4]], vec[5]-vec[4]);
  if (r > 3) *ret3 = safe_strndup (g, &str[vec[6]], vec[7]-vec[6]);
  if (r > 4) *ret4 = safe_strndup (g, &str[vec[8]], vec[9]-vec[8]);
  if (r > 5) *ret5 = safe_strndup (g, &str[vec[10]], vec[11]-vec[10]);
  if (r > 6) *ret6 = safe_strndup (g, &str[vec[12]], vec[13]-vec[12]);

  return 1;
}
Пример #5
0
/* Parse the hostname from /etc/rc.conf.  On FreeBSD this file
 * contains comments, blank lines and:
 *   hostname="freebsd8.example.com"
 *   ifconfig_re0="DHCP"
 *   keymap="uk.iso"
 *   sshd_enable="YES"
 */
static int
check_hostname_freebsd (guestfs_h *g, struct inspect_fs *fs)
{
  const char *filename = "/etc/rc.conf";
  int64_t size;
  CLEANUP_FREE_STRING_LIST char **lines = NULL;
  size_t i;

  /* Don't trust guestfs_read_lines 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_read_lines (g, filename);
  if (lines == NULL)
    return -1;

  for (i = 0; lines[i] != NULL; ++i) {
    if (STRPREFIX (lines[i], "hostname=\"") ||
        STRPREFIX (lines[i], "hostname='")) {
      size_t len = strlen (lines[i]) - 10 - 1;
      fs->hostname = safe_strndup (g, &lines[i][10], len);
      break;
    } else if (STRPREFIX (lines[i], "hostname=")) {
      size_t len = strlen (lines[i]) - 9;
      fs->hostname = safe_strndup (g, &lines[i][9], len);
      break;
    }
  }

  return 0;
}
Пример #6
0
/* Like 'add_cmdline' but allowing a shell-quoted string of zero or
 * more options.  XXX The unquoting is not very clever.
 */
static void
add_cmdline_shell_unquoted (guestfs_h *g, struct stringsbuf *sb,
                            const char *options)
{
  char quote;
  const char *startp, *endp, *nextp;

  while (*options) {
    quote = *options;
    if (quote == '\'' || quote == '"')
      startp = options+1;
    else {
      startp = options;
      quote = ' ';
    }

    endp = strchr (options, quote);
    if (endp == NULL) {
      if (quote != ' ') {
        fprintf (stderr,
                 _("unclosed quote character (%c) in command line near: %s"),
                 quote, options);
        _exit (EXIT_FAILURE);
      }
      endp = options + strlen (options);
    }

    if (quote == ' ') {
      if (endp[0] == '\0')
        nextp = endp;
      else
        nextp = endp+1;
    }
    else {
      if (!endp[1])
        nextp = endp+1;
      else if (endp[1] == ' ')
        nextp = endp+2;
      else {
        fprintf (stderr, _("cannot parse quoted string near: %s"), options);
        _exit (EXIT_FAILURE);
      }
    }
    while (*nextp && *nextp == ' ')
      nextp++;

    guestfs___add_string_nodup (g, sb,
                                safe_strndup (g, startp, endp-startp));

    options = nextp;
  }
}
Пример #7
0
/* Search elements of g->path, returning the first path element which
 * matches the predicate function 'pred'.
 *
 * Function 'pred' must return a true or false value.  If it returns
 * -1 then the entire search is aborted.
 *
 * Return values:
 * 1 = a path element matched, it is returned in *pelem_ret and must be
 *     freed by the caller,
 * 0 = no path element matched, *pelem_ret is set to NULL, or
 * -1 = error which aborts the launch process
 */
static int
find_path (guestfs_h *g,
           int (*pred) (guestfs_h *g, const char *pelem, void *data),
           void *data,
           char **pelem_ret)
{
  size_t len;
  int r;
  const char *pelem = g->path;

  /* Note that if g->path is an empty string, we want to check the
   * current directory (for backwards compatibility with
   * libguestfs < 1.5.4).
   */
  do {
    len = strcspn (pelem, PATH_SEPARATOR);

    /* Empty element or "." means current directory. */
    if (len == 0)
      *pelem_ret = safe_strdup (g, ".");
    else
      *pelem_ret = safe_strndup (g, pelem, len);

    r = pred (g, *pelem_ret, data);
    if (r == -1) {
      free (*pelem_ret);
      return -1;
    }

    if (r != 0)                 /* predicate matched */
      return 1;

    free (*pelem_ret);

    if (pelem[len] == PATH_SEPARATOR[0])
      pelem += len + 1;
    else
      pelem += len;
  } while (*pelem);

  /* Predicate didn't match on any path element. */
  *pelem_ret = NULL;
  return 0;
}
Пример #8
0
char *
guestfs_impl_disk_format (guestfs_h *g, const char *filename)
{
  CLEANUP_JSON_T_DECREF json_t *tree = get_json_output (g, filename);
  json_t *node;

  if (tree == NULL)
    return NULL;

  if (!json_is_object (tree))
    goto bad_type;

  node = json_object_get (tree, "format");
  if (!json_is_string (node))
    goto bad_type;

  return safe_strndup (g, json_string_value (node),
                          json_string_length (node)); /* caller frees */

 bad_type:
  error (g, _("qemu-img info: JSON output did not contain ‘format’ key"));
  return NULL;
}
static int
check_windows_system_registry (guestfs_h *g, struct inspect_fs *fs)
{
  int r;
  size_t len = strlen (fs->windows_systemroot) + 64;
  char system[len];
  snprintf (system, len, "%s/system32/config/system",
            fs->windows_systemroot);

  CLEANUP_FREE char *system_path = guestfs_case_sensitive_path (g, system);
  if (!system_path)
    return -1;

  r = guestfs_is_file (g, system_path);
  if (r == -1)
    return -1;
  /* If the system hive doesn't exist, just accept that we cannot
   * find hostname etc.
   */
  if (r == 0)
    return 0;

  int ret = -1;
  int64_t root, node, value;
  CLEANUP_FREE_HIVEX_VALUE_LIST struct guestfs_hivex_value_list *values = NULL;
  CLEANUP_FREE_HIVEX_VALUE_LIST struct guestfs_hivex_value_list *values2 = NULL;
  int32_t dword;
  size_t i, count;
  CLEANUP_FREE void *buf = NULL;
  size_t buflen;
  const char *hivepath[] =
    { NULL /* current control set */, "Services", "Tcpip", "Parameters" };

  if (guestfs_hivex_open (g, system_path,
                          GUESTFS_HIVEX_OPEN_VERBOSE, g->verbose, -1) == -1)
    goto out;

  root = guestfs_hivex_root (g);
  if (root == 0)
    goto out;

  /* Get the CurrentControlSet. */
  node = guestfs_hivex_node_get_child (g, root, "Select");
  if (node == -1)
    goto out;

  if (node == 0) {
    error (g, "hivex: could not locate HKLM\\SYSTEM\\Select");
    goto out;
  }

  value = guestfs_hivex_node_get_value (g, node, "Current");
  if (value == -1)
    goto out;

  if (value == 0) {
    error (g, "hivex: HKLM\\System\\Select Default entry not found");
    goto out;
  }

  /* XXX Should check the type. */
  buf = guestfs_hivex_value_value (g, value, &buflen);
  if (buflen != 4) {
    error (g, "hivex: HKLM\\System\\Select\\Current expected to be DWORD");
    goto out;
  }
  dword = le32toh (*(int32_t *)buf);
  fs->windows_current_control_set = safe_asprintf (g, "ControlSet%03d", dword);

  /* Get the drive mappings.
   * This page explains the contents of HKLM\System\MountedDevices:
   * http://www.goodells.net/multiboot/partsigs.shtml
   */
  node = guestfs_hivex_node_get_child (g, root, "MountedDevices");
  if (node == -1)
    goto out;

  if (node == 0)
    /* Not found: skip getting drive letter mappings (RHBZ#803664). */
    goto skip_drive_letter_mappings;

  values = guestfs_hivex_node_values (g, node);

  /* Count how many DOS drive letter mappings there are.  This doesn't
   * ignore removable devices, so it overestimates, but that doesn't
   * matter because it just means we'll allocate a few bytes extra.
   */
  for (i = count = 0; i < values->len; ++i) {
    CLEANUP_FREE char *key =
      guestfs_hivex_value_key (g, values->val[i].hivex_value_h);
    if (key == NULL)
      goto out;
    if (STRCASEEQLEN (key, "\\DosDevices\\", 12) &&
        c_isalpha (key[12]) && key[13] == ':')
      count++;
  }

  fs->drive_mappings = safe_calloc (g, 2*count + 1, sizeof (char *));

  for (i = count = 0; i < values->len; ++i) {
    int64_t v = values->val[i].hivex_value_h;
    CLEANUP_FREE char *key = guestfs_hivex_value_key (g, v);
    if (key == NULL)
      goto out;
    if (STRCASEEQLEN (key, "\\DosDevices\\", 12) &&
        c_isalpha (key[12]) && key[13] == ':') {
      /* Get the binary value.  Is it a fixed disk? */
      CLEANUP_FREE char *blob = NULL;
      char *device;
      size_t len;
      int64_t type;

      type = guestfs_hivex_value_type (g, v);
      blob = guestfs_hivex_value_value (g, v, &len);
      if (blob != NULL && type == 3 && len == 12) {
        /* Try to map the blob to a known disk and partition. */
        device = map_registry_disk_blob (g, blob);
        if (device != NULL) {
          fs->drive_mappings[count++] = safe_strndup (g, &key[12], 1);
          fs->drive_mappings[count++] = device;
        }
      }
    }
  }

 skip_drive_letter_mappings:;
  /* Get the hostname. */
  hivepath[0] = fs->windows_current_control_set;
  for (node = root, i = 0;
       node > 0 && i < sizeof hivepath / sizeof hivepath[0];
       ++i) {
    node = guestfs_hivex_node_get_child (g, node, hivepath[i]);
  }

  if (node == -1)
    goto out;

  if (node == 0) {
    perrorf (g, "hivex: cannot locate HKLM\\SYSTEM\\%s\\Services\\Tcpip\\Parameters",
             fs->windows_current_control_set);
    goto out;
  }

  values2 = guestfs_hivex_node_values (g, node);
  if (values2 == NULL)
    goto out;

  for (i = 0; i < values2->len; ++i) {
    int64_t v = values2->val[i].hivex_value_h;
    CLEANUP_FREE char *key = guestfs_hivex_value_key (g, v);
    if (key == NULL)
      goto out;

    if (STRCASEEQ (key, "Hostname")) {
      fs->hostname = guestfs_hivex_value_utf8 (g, v);
      if (!fs->hostname)
        goto out;
    }
    /* many other interesting fields here ... */
  }

  ret = 0;

 out:
  guestfs_hivex_close (g);

  return ret;
}
Пример #10
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;
}