+
+char *
+guestfs__inspect_get_package_format (guestfs_h *g, const char *root)
+{
+ struct inspect_fs *fs = search_for_root (g, root);
+ if (!fs)
+ return NULL;
+
+ char *ret;
+ switch (fs->package_format) {
+ case OS_PACKAGE_FORMAT_RPM: ret = safe_strdup (g, "rpm"); break;
+ case OS_PACKAGE_FORMAT_DEB: ret = safe_strdup (g, "deb"); break;
+ case OS_PACKAGE_FORMAT_PACMAN: ret = safe_strdup (g, "pacman"); break;
+ case OS_PACKAGE_FORMAT_EBUILD: ret = safe_strdup (g, "ebuild"); break;
+ case OS_PACKAGE_FORMAT_PISI: ret = safe_strdup (g, "pisi"); break;
+ case OS_PACKAGE_FORMAT_UNKNOWN:
+ default:
+ ret = safe_strdup (g, "unknown");
+ break;
+ }
+
+ return ret;
+}
+
+char *
+guestfs__inspect_get_package_management (guestfs_h *g, const char *root)
+{
+ struct inspect_fs *fs = search_for_root (g, root);
+ if (!fs)
+ return NULL;
+
+ char *ret;
+ switch (fs->package_management) {
+ case OS_PACKAGE_MANAGEMENT_YUM: ret = safe_strdup (g, "yum"); break;
+ case OS_PACKAGE_MANAGEMENT_UP2DATE: ret = safe_strdup (g, "up2date"); break;
+ case OS_PACKAGE_MANAGEMENT_APT: ret = safe_strdup (g, "apt"); break;
+ case OS_PACKAGE_MANAGEMENT_PACMAN: ret = safe_strdup (g, "pacman"); break;
+ case OS_PACKAGE_MANAGEMENT_PORTAGE: ret = safe_strdup (g, "portage"); break;
+ case OS_PACKAGE_MANAGEMENT_PISI: ret = safe_strdup (g, "pisi"); break;
+ case OS_PACKAGE_MANAGEMENT_UNKNOWN:
+ default:
+ ret = safe_strdup (g, "unknown");
+ break;
+ }
+
+ return ret;
+}
+
+#else /* no PCRE or hivex at compile time */
+
+/* XXX These functions should be in an optgroup. */
+
+#define NOT_IMPL(r) \
+ error (g, _("inspection API not available since this version of libguestfs was compiled without PCRE or hivex libraries")); \
+ return r
+
+char **
+guestfs__inspect_os (guestfs_h *g)
+{
+ NOT_IMPL(NULL);
+}
+
+char **
+guestfs__inspect_get_roots (guestfs_h *g)
+{
+ NOT_IMPL(NULL);
+}
+
+char *
+guestfs__inspect_get_type (guestfs_h *g, const char *root)
+{
+ NOT_IMPL(NULL);
+}
+
+char *
+guestfs__inspect_get_arch (guestfs_h *g, const char *root)
+{
+ NOT_IMPL(NULL);
+}
+
+char *
+guestfs__inspect_get_distro (guestfs_h *g, const char *root)
+{
+ NOT_IMPL(NULL);
+}
+
+int
+guestfs__inspect_get_major_version (guestfs_h *g, const char *root)
+{
+ NOT_IMPL(-1);
+}
+
+int
+guestfs__inspect_get_minor_version (guestfs_h *g, const char *root)
+{
+ NOT_IMPL(-1);
+}
+
+char *
+guestfs__inspect_get_product_name (guestfs_h *g, const char *root)
+{
+ NOT_IMPL(NULL);
+}
+
+char *
+guestfs__inspect_get_windows_systemroot (guestfs_h *g, const char *root)
+{
+ NOT_IMPL(NULL);
+}
+
+char **
+guestfs__inspect_get_mountpoints (guestfs_h *g, const char *root)
+{
+ NOT_IMPL(NULL);
+}
+
+char **
+guestfs__inspect_get_filesystems (guestfs_h *g, const char *root)
+{
+ NOT_IMPL(NULL);
+}
+
+char *
+guestfs__inspect_get_package_format (guestfs_h *g, const char *root)
+{
+ NOT_IMPL(NULL);
+}
+
+char *
+guestfs__inspect_get_package_management (guestfs_h *g, const char *root)
+{
+ NOT_IMPL(NULL);
+}
+
+#endif /* no PCRE or hivex at compile time */
+
+void
+guestfs___free_inspect_info (guestfs_h *g)
+{
+ size_t i;
+ for (i = 0; i < g->nr_fses; ++i) {
+ free (g->fses[i].device);
+ free (g->fses[i].product_name);
+ free (g->fses[i].arch);
+ free (g->fses[i].windows_systemroot);
+ size_t j;
+ for (j = 0; j < g->fses[i].nr_fstab; ++j) {
+ free (g->fses[i].fstab[j].device);
+ free (g->fses[i].fstab[j].mountpoint);
+ }
+ free (g->fses[i].fstab);
+ }
+ free (g->fses);
+ g->nr_fses = 0;
+ g->fses = NULL;
+}
+
+/* In the Perl code this is a public function. */
+int
+guestfs___feature_available (guestfs_h *g, const char *feature)
+{
+ /* If there's an error we should ignore it, so to do that we have to
+ * temporarily replace the error handler with a null one.
+ */
+ guestfs_error_handler_cb old_error_cb = g->error_cb;
+ g->error_cb = NULL;
+
+ const char *groups[] = { feature, NULL };
+ int r = guestfs_available (g, (char * const *) groups);
+
+ g->error_cb = old_error_cb;
+
+ return r == 0 ? 1 : 0;
+}
+
+#ifdef HAVE_PCRE
+
+/* Match a regular expression which contains no captures. Returns
+ * true if it matches or false if it doesn't.
+ */
+int
+guestfs___match (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 0;
+ if (r != 1) {
+ /* Internal error -- should not happen. */
+ fprintf (stderr, "libguestfs: %s: %s: internal error: pcre_exec returned unexpected error code %d when matching against the string \"%s\"\n",
+ __FILE__, __func__, r, str);
+ return 0;
+ }
+
+ return 1;
+}
+
+/* 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;
+ if (r != 2) {
+ /* Internal error -- should not happen. */
+ fprintf (stderr, "libguestfs: %s: %s: internal error: pcre_exec returned unexpected error code %d when matching against the string \"%s\"\n",
+ __FILE__, __func__, r, str);
+ return NULL;
+ }
+
+ return safe_strndup (g, &str[vec[2]], vec[3]-vec[2]);
+}
+
+/* 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;
+ if (r != 3) {
+ /* Internal error -- should not happen. */
+ fprintf (stderr, "libguestfs: %s: %s: internal error: pcre_exec returned unexpected error code %d when matching against the string \"%s\"\n",
+ __FILE__, __func__, r, str);
+ return 0;
+ }
+
+ *ret1 = safe_strndup (g, &str[vec[2]], vec[3]-vec[2]);
+ *ret2 = safe_strndup (g, &str[vec[4]], vec[5]-vec[4]);
+
+ return 1;
+}
+
+/* Match a regular expression which contains exactly three captures. */
+int
+guestfs___match3 (guestfs_h *g, const char *str, const pcre *re,
+ char **ret1, char **ret2, char **ret3)
+{
+ 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;
+ if (r != 4) {
+ /* Internal error -- should not happen. */
+ fprintf (stderr, "libguestfs: %s: %s: internal error: pcre_exec returned unexpected error code %d when matching against the string \"%s\"\n",
+ __FILE__, __func__, r, str);
+ return 0;
+ }
+
+ *ret1 = safe_strndup (g, &str[vec[2]], vec[3]-vec[2]);
+ *ret2 = safe_strndup (g, &str[vec[4]], vec[5]-vec[4]);
+ *ret3 = safe_strndup (g, &str[vec[6]], vec[7]-vec[6]);
+
+ return 1;
+}
+
+#endif /* HAVE_PCRE */