Exemplo n.º 1
0
static int
read_osinfo_db (guestfs_h *g)
{
  DIR *dir = NULL;
  struct dirent *d;
  int r;
  size_t i;

  assert (osinfo_db_size == 0);

  dir = opendir (LIBOSINFO_DB_OS_PATH);
  if (!dir) {
    debug (g, "osinfo: %s: %s", LIBOSINFO_DB_OS_PATH, strerror (errno));
    return 0; /* This is not an error: RHBZ#948324. */
  }

  debug (g, "osinfo: loading database from %s", LIBOSINFO_DB_OS_PATH);

  for (;;) {
    errno = 0;
    d = readdir (dir);
    if (!d) break;

    if (STRSUFFIX (d->d_name, ".xml")) {
      r = read_osinfo_db_xml (g, d->d_name);
      if (r == -1)
        goto error;
    }
  }

  /* Check for failure in readdir. */
  if (errno != 0) {
    perrorf (g, "readdir: %s", LIBOSINFO_DB_OS_PATH);
    goto error;
  }

  /* Close the directory handle. */
  r = closedir (dir);
  dir = NULL;
  if (r == -1) {
    perrorf (g, "closedir: %s", LIBOSINFO_DB_OS_PATH);
    goto error;
  }

  return 0;

 error:
  if (dir)
    closedir (dir);

  /* Fatal error: free any database entries which have been read, and
   * mark the database as having a permanent error.
   */
  if (osinfo_db_size > 0) {
    for (i = 0; i < (size_t) osinfo_db_size; ++i)
      free_osinfo_db_entry (&osinfo_db[i]);
  }
  free (osinfo_db);
  osinfo_db = NULL;
  osinfo_db_size = -1;

  return -1;
}
Exemplo n.º 2
0
/* Read a single XML file from LIBOSINFO_DB_OS_PATH/filename.  Only
 * memory allocation failures are fatal errors here.
 */
static int
read_osinfo_db_xml (guestfs_h *g, const char *filename)
{
  const size_t pathname_len =
    strlen (LIBOSINFO_DB_OS_PATH) + strlen (filename) + 2;
  char pathname[pathname_len];
  CLEANUP_XMLFREEDOC xmlDocPtr doc = NULL;
  CLEANUP_XMLXPATHFREECONTEXT xmlXPathContextPtr xpathCtx = NULL;
  CLEANUP_XMLXPATHFREEOBJECT xmlXPathObjectPtr xpathObj = NULL;
  xmlNodeSetPtr nodes;
  xmlNodePtr iso_node, media_node, os_node;
  struct osinfo *osinfo;
  size_t i;

  snprintf (pathname, pathname_len, "%s/%s", LIBOSINFO_DB_OS_PATH, filename);

  doc = xmlReadFile (pathname, NULL, XML_PARSE_NONET);
  if (doc == NULL) {
    debug (g, "osinfo: unable to parse XML file %s", pathname);
    return 0;
  }

  xpathCtx = xmlXPathNewContext (doc);
  if (xpathCtx == NULL) {
    error (g, _("osinfo: unable to create new XPath context"));
    return -1;
  }

  /* Get all <iso> nodes at any depth, then use the parent pointers in
   * order to work back up the tree.
   */
  xpathObj = xmlXPathEvalExpression (BAD_CAST "/libosinfo/os/media/iso",
                                     xpathCtx);
  if (xpathObj == NULL) {
    error (g, _("osinfo: %s: unable to evaluate XPath expression"),
           pathname);
    return -1;
  }

  nodes = xpathObj->nodesetval;

  if (nodes != NULL) {
    for (i = 0; i < (size_t) nodes->nodeNr; ++i) {
      iso_node = nodes->nodeTab[i];
      assert (iso_node != NULL);
      assert (STREQ ((const char *) iso_node->name, "iso"));
      assert (iso_node->type == XML_ELEMENT_NODE);

      media_node = iso_node->parent;
      assert (media_node != NULL);
      assert (STREQ ((const char *) media_node->name, "media"));
      assert (media_node->type == XML_ELEMENT_NODE);

      os_node = media_node->parent;
      assert (os_node != NULL);
      assert (STREQ ((const char *) os_node->name, "os"));
      assert (os_node->type == XML_ELEMENT_NODE);

      /* Allocate an osinfo record. */
      osinfo_db_size++;
      osinfo_db = safe_realloc (g, osinfo_db,
                                sizeof (struct osinfo) * osinfo_db_size);
      osinfo = &osinfo_db[osinfo_db_size-1];
      memset (osinfo, 0, sizeof *osinfo);

      /* Read XML fields into the new osinfo record. */
      if (read_iso_node (g, iso_node, osinfo) == -1 ||
          read_media_node (g, xpathCtx, media_node, osinfo) == -1 ||
          read_os_node (g, xpathCtx, os_node, osinfo) == -1) {
        free_osinfo_db_entry (osinfo);
        osinfo_db_size--;
        return -1;
      }

#if 0
      debug (g, "osinfo: %s: %s%s%s%s=> arch %s live %s product %s type %d distro %d version %d.%d",
             filename,
             osinfo->re_system_id ? "<system-id/> " : "",
             osinfo->re_volume_id ? "<volume-id/> " : "",
             osinfo->re_publisher_id ? "<publisher-id/> " : "",
             osinfo->re_application_id ? "<application-id/> " : "",
             osinfo->arch ? osinfo->arch : "(none)",
             osinfo->is_live_disk ? "true" : "false",
             osinfo->product_name ? osinfo->product_name : "(none)",
             (int) osinfo->type, (int) osinfo->distro,
             osinfo->major_version, osinfo->minor_version);
#endif
    }
  }

  return 0;
}
Exemplo n.º 3
0
static int
read_osinfo_db (guestfs_h *g)
{
  int r;
  size_t i;

  assert (osinfo_db_size == 0);

  /* (1) Try the shared osinfo directory, using either the
   * $OSINFO_SYSTEM_DIR envvar or its default value.
   */
  {
    const char *path;
    CLEANUP_FREE char *os_path = NULL;

    path = getenv ("OSINFO_SYSTEM_DIR");
    if (path == NULL)
      path = "/usr/share/osinfo";
    os_path = safe_asprintf (g, "%s/os", path);
    r = read_osinfo_db_three_levels (g, os_path);
  }
  if (r == -1)
    goto error;
  else if (r == 1)
    return 0;

  /* (2) Try the libosinfo directory, using the newer three-directory
   * layout ($LIBOSINFO_DB_PATH / "os" / $group-ID / [file.xml]).
   */
  r = read_osinfo_db_three_levels (g, LIBOSINFO_DB_PATH "/os");
  if (r == -1)
    goto error;
  else if (r == 1)
    return 0;

  /* (3) Try the libosinfo directory, using the old flat directory
   * layout ($LIBOSINFO_DB_PATH / "oses" / [file.xml]).
   */
  r = read_osinfo_db_flat (g, LIBOSINFO_DB_PATH "/oses");
  if (r == -1)
    goto error;
  else if (r == 1)
    return 0;

  /* Nothing found. */
  return 0;

 error:
  /* Fatal error: free any database entries which have been read, and
   * mark the database as having a permanent error.
   */
  if (osinfo_db_size > 0) {
    for (i = 0; i < (size_t) osinfo_db_size; ++i)
      free_osinfo_db_entry (&osinfo_db[i]);
  }
  free (osinfo_db);
  osinfo_db = NULL;
  osinfo_db_size = -1;

  return -1;
}