[Libguestfs] [PATCH v11 08/10] daemon: Implement inspection of Linux and other Unix-like operating systems.
Pino Toscano
ptoscano at redhat.com
Tue Aug 8 16:57:46 UTC 2017
On Monday, 31 July 2017 17:40:57 CEST Richard W.M. Jones wrote:
> +(* Parse a os-release file.
> + *
> + * Only few fields are parsed, falling back to the usual detection if we
> + * cannot read all of them.
> + *
> + * For the format of os-release, see also:
> + * http://www.freedesktop.org/software/systemd/man/os-release.html
> + *)
> +let rec parse_os_release release_file data =
> + let chroot = Chroot.create ~name:"parse_os_release" () in
> + let lines =
> + Chroot.f chroot (
> + fun () ->
> + if not (is_small_file release_file) then (
> + eprintf "%s: not a regular file or too large\n" release_file;
> + None
> + )
> + else
> + Some (read_whole_file release_file)
> + ) () in
I see this bit (chroot + read_whole_file) is common among various
functions in this file -- could you please place it in an helper
function?
> + match lines with
> + | None -> false
> + | Some lines ->
> + let lines = String.nsplit "\n" lines in
> +
> + List.iter (
> + fun line ->
> + let line = String.trim line in
> + if line = "" || line.[0] = '#' then
> + ()
> + else (
> + let key, value = String.split "=" line in
> + let value =
> + let n = String.length value in
> + if n >= 2 && value.[0] = '"' && value.[n-1] = '"' then
> + String.sub value 1 (n-2)
> + else
> + value in
> + if key = "ID" then (
> + let distro = distro_of_os_release_id value in
> + match distro with
> + | Some _ as distro -> data.distro <- distro
> + | None -> ()
> + )
> + else if key = "PRETTY_NAME" then
> + data.product_name <- Some value
> + else if key = "VERSION_ID" then
> + parse_version_from_major_minor value data
> + )
> + ) lines;
> +
> + (* If we haven't got all the fields, exit right away. *)
> + if data.distro = None || data.product_name = None then
> + false
> + else (
> + (* os-release in Debian and CentOS does not provide the full
> + * version number (VERSION_ID), just the major part of it. If
> + * we detect that situation then bail out and use the release
> + * files instead.
> + *)
> + match data with
> + | { distro = Some (DISTRO_DEBIAN|DISTRO_CENTOS);
> + version = Some (_, 0) } ->
> + false
> + | _ -> true
> + )
parse_os_release should also reset the version to Some (0, 0) (instead
of None) in case the distro is one of the "rolling" ones (only Void at
the moment) -- see also src/inspect-fs-unix.c, lines 240 and on.
> +(* 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.
> + *
> + * CoreOS has a /etc/lsb-release link to /usr/share/coreos/lsb-release containing:
> + * DISTRIB_ID=CoreOS
> + * DISTRIB_RELEASE=647.0.0
> + * DISTRIB_CODENAME="Red Dog"
> + * DISTRIB_DESCRIPTION="CoreOS 647.0.0"
> + *)
> +and parse_lsb_release release_file data =
TBH, since both parse_os_release and parse_lsb_release are rewritten
in OCaml, I'd try a better approach for them: add an helper function
that read such kind of files (ignoring empty lines, and those starting
with '#'), split them in lines, and map the lines into (key, value)
pairs, also un-quoting the value. It would not map 1:1 the C
implementations, but in OCaml it would be so much easier than in C
(and that is basically what I'd have liked to do in the first place
when implementing parse_os_release, but it'd have been so much memory
waste).
> +let rec check_linux_root mountable data =
> + let os_type = OS_TYPE_LINUX in
> + data.os_type <- Some os_type;
> +
> + let rec loop = function
> + | (release_file, parse_fun) :: tests ->
> + if verbose () then
> + eprintf "check_linux_root: checking %s\n%!" release_file;
> + if Is.is_file ~followsymlinks:true release_file then (
> + if parse_fun release_file data then () (* true => finished *)
> + else loop tests
> + ) else loop tests
> + | [] -> ()
> + in
> + loop linux_root_tests;
Would it be possible to move the above loop in an own helper function,
so the check_$OS functions of other OSes can have their own counterpart
of linux_root_tests? It is true that we don't add new identifications
often, but since it's already implemented here...
> +and check_fstab_entry md_map root_mountable os_type aug entry =
> + if verbose () then
> + eprintf "check_fstab_entry: augeas path: %s\n%!" entry;
> +
> + let is_bsd =
> + os_type = OS_TYPE_FREEBSD ||
> + os_type = OS_TYPE_NETBSD ||
> + os_type = OS_TYPE_OPENBSD in
'match' here?
--
Pino Toscano
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: This is a digitally signed message part.
URL: <http://listman.redhat.com/archives/libguestfs/attachments/20170808/1f8352b9/attachment.sig>
More information about the Libguestfs
mailing list