Re: [Libguestfs] [PATCH 5/5] inspect: gather info from /usr filesystems as well (RHBZ#1401474)

2016-12-07 Thread Richard W.M. Jones
On Tue, Dec 06, 2016 at 04:29:22PM +0100, Pino Toscano wrote:
> +static void
> +collect_linux_inspection_info_for (guestfs_h *g, struct inspect_fs *root)
> +{
> +  size_t i;
> +  struct inspect_fs *usr = NULL;
> +
> +  for (i = 0; i < g->nr_fses; ++i) {
> +struct inspect_fs *fs = >fses[i];
> +size_t j;
> +
> +if (!(fs->distro == root->distro || fs->distro == OS_DISTRO_UNKNOWN) ||
> +fs->role != OS_ROLE_USR)
> +  continue;
> +
> +for (j = 0; j < root->nr_fstab; ++j) {
> +  if (STREQ (fs->mountable, root->fstab[j].mountable)) {
> +usr = fs;
> +goto got_usr;
> +  }
> +}
> +  }
> +
> +  if (usr == NULL)

I think this should be:

  assert (usr == NULL);

unless there's some way to reach this point and usr != NULL.

> +return;
> +
> + got_usr:
> +  /* If the version information in /usr is not null, then most probably
> +   * there was an os-release file there, so reset what is in root
> +   * and pick the results from /usr.
> +   */
> +  if (!version_is_null (>version)) {
> +root->distro = OS_DISTRO_UNKNOWN;
> +free (root->product_name);
> +root->product_name = NULL;
> +  }
> +
> +  guestfs_int_merge_fs_inspections (g, root, usr);
> +}

Rich.

-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
Fedora Windows cross-compiler. Compile Windows programs, test, and
build Windows installers. Over 100 libraries supported.
http://fedoraproject.org/wiki/MinGW

___
Libguestfs mailing list
Libguestfs@redhat.com
https://www.redhat.com/mailman/listinfo/libguestfs


[Libguestfs] [PATCH 5/5] inspect: gather info from /usr filesystems as well (RHBZ#1401474)

2016-12-06 Thread Pino Toscano
Flag the filesystems for Linux /usr properly as USR role, and detect
some data out of it, like the distro information from an os-release
(if present), and the architecture (since the binaries used for our
architecture check will be available there only).

Later on, collect the results in a way similar to what is done for
CoreOS: for each non-CoreOS root, try to find its /usr filesystem, and
if found then merge what is missing from root; in the last case, also
override the distro inspection data (version, product name) if available
in /usr.
---
 src/guestfs-internal.h |  1 +
 src/inspect-fs-unix.c  | 26 ++
 src/inspect-fs.c   |  6 +++--
 src/inspect.c  | 73 ++
 4 files changed, 104 insertions(+), 2 deletions(-)

diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h
index d10191d..fbbfb90 100644
--- a/src/guestfs-internal.h
+++ b/src/guestfs-internal.h
@@ -864,6 +864,7 @@ extern void guestfs_int_merge_fs_inspections (guestfs_h *g, 
struct inspect_fs *d
 
 /* inspect-fs-unix.c */
 extern int guestfs_int_check_linux_root (guestfs_h *g, struct inspect_fs *fs);
+extern int guestfs_int_check_linux_usr (guestfs_h *g, struct inspect_fs *fs);
 extern int guestfs_int_check_freebsd_root (guestfs_h *g, struct inspect_fs 
*fs);
 extern int guestfs_int_check_netbsd_root (guestfs_h *g, struct inspect_fs *fs);
 extern int guestfs_int_check_openbsd_root (guestfs_h *g, struct inspect_fs 
*fs);
diff --git a/src/inspect-fs-unix.c b/src/inspect-fs-unix.c
index 7b54a4a..bb8e0ef 100644
--- a/src/inspect-fs-unix.c
+++ b/src/inspect-fs-unix.c
@@ -786,6 +786,32 @@ guestfs_int_check_linux_root (guestfs_h *g, struct 
inspect_fs *fs)
   return 0;
 }
 
+/* The currently mounted device looks like a Linux /usr. */
+int
+guestfs_int_check_linux_usr (guestfs_h *g, struct inspect_fs *fs)
+{
+  int r;
+
+  fs->type = OS_TYPE_LINUX;
+  fs->role = OS_ROLE_USR;
+
+  if (guestfs_is_file_opts (g, "/lib/os-release",
+GUESTFS_IS_FILE_OPTS_FOLLOWSYMLINKS, 1, -1) > 0) {
+r = parse_os_release (g, fs, "/lib/os-release");
+if (r == -1)/* error */
+  return -1;
+if (r == 1) /* ok - detected the release from this file */
+  goto skip_release_checks;
+  }
+
+ skip_release_checks:;
+
+  /* Determine the architecture. */
+  check_architecture (g, fs);
+
+  return 0;
+}
+
 /* The currently mounted device is known to be a FreeBSD root. */
 int
 guestfs_int_check_freebsd_root (guestfs_h *g, struct inspect_fs *fs)
diff --git a/src/inspect-fs.c b/src/inspect-fs.c
index 1951678..9f7630b 100644
--- a/src/inspect-fs.c
+++ b/src/inspect-fs.c
@@ -245,8 +245,10 @@ check_filesystem (guestfs_h *g, const char *mountable,
is_dir_bin &&
is_dir_share &&
guestfs_is_dir (g, "/local") > 0 &&
-   guestfs_is_file (g, "/etc/fstab") == 0)
-;
+   guestfs_is_file (g, "/etc/fstab") == 0) {
+if (guestfs_int_check_linux_usr (g, fs) == -1)
+  return -1;
+  }
   /* CoreOS /usr? */
   else if (is_dir_bin &&
is_dir_share &&
diff --git a/src/inspect.c b/src/inspect.c
index 9055226..5e904d2 100644
--- a/src/inspect.c
+++ b/src/inspect.c
@@ -46,6 +46,8 @@ COMPILE_REGEXP (re_primary_partition, 
"^/dev/(?:h|s|v)d.[1234]$", 0)
 
 static void check_for_duplicated_bsd_root (guestfs_h *g);
 static void collect_coreos_inspection_info (guestfs_h *g);
+static void collect_linux_inspection_info (guestfs_h *g);
+static void collect_linux_inspection_info_for (guestfs_h *g, struct inspect_fs 
*root);
 
 /**
  * The main inspection API.
@@ -88,6 +90,12 @@ guestfs_impl_inspect_os (guestfs_h *g)
*/
   check_for_duplicated_bsd_root (g);
 
+  /* For Linux guests with a separate /usr filesyste, merge some of the
+   * inspected information in that partition to the inspect_fs struct
+   * of the root filesystem.
+   */
+  collect_linux_inspection_info (g);
+
   /* At this point we have, in the handle, a list of all filesystems
* found and data about each one.  Now we assemble the list of
* filesystems which are root devices and return that to the user.
@@ -149,6 +157,71 @@ collect_coreos_inspection_info (guestfs_h *g)
 }
 
 /**
+ * Traverse through the filesystems and find the /usr filesystem for
+ * the specified C: if found, merge its basic inspection details
+ * to the root when they were set (i.e. because the /usr had os-release
+ * or other ways to identify the OS).
+ */
+static void
+collect_linux_inspection_info_for (guestfs_h *g, struct inspect_fs *root)
+{
+  size_t i;
+  struct inspect_fs *usr = NULL;
+
+  for (i = 0; i < g->nr_fses; ++i) {
+struct inspect_fs *fs = >fses[i];
+size_t j;
+
+if (!(fs->distro == root->distro || fs->distro == OS_DISTRO_UNKNOWN) ||
+fs->role != OS_ROLE_USR)
+  continue;
+
+for (j = 0; j < root->nr_fstab; ++j) {
+  if (STREQ (fs->mountable, root->fstab[j].mountable)) {
+usr = fs;
+goto got_usr;
+