mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-22 07:03:38 +00:00
inspection: Deprecate APIs and remove support for inspecting installer CDs.
This just duplicated libosinfo information, and because it was never tested it didn't work most of the time.
This commit is contained in:
@@ -312,7 +312,6 @@ lib/handle.c
|
||||
lib/hivex.c
|
||||
lib/info.c
|
||||
lib/inspect-apps.c
|
||||
lib/inspect-fs-cd.c
|
||||
lib/inspect-fs-unix.c
|
||||
lib/inspect-fs-windows.c
|
||||
lib/inspect-fs.c
|
||||
@@ -330,7 +329,6 @@ lib/libvirt-is-version.c
|
||||
lib/lpj.c
|
||||
lib/match.c
|
||||
lib/mountable.c
|
||||
lib/osinfo.c
|
||||
lib/private-data.c
|
||||
lib/proto.c
|
||||
lib/qemu.c
|
||||
|
||||
@@ -563,73 +563,6 @@ as found by inspection of the guest’s configuration files.
|
||||
If the hostname could not be determined, then the
|
||||
string C<unknown> is returned.
|
||||
|
||||
Please read L<guestfs(3)/INSPECTION> for more details." };
|
||||
|
||||
{ defaults with
|
||||
name = "inspect_get_format"; added = (1, 9, 4);
|
||||
style = RString (RPlainString, "format"), [String (Mountable, "root")], [];
|
||||
shortdesc = "get format of inspected operating system";
|
||||
longdesc = "\
|
||||
This returns the format of the inspected operating system. You
|
||||
can use it to detect install images, live CDs and similar.
|
||||
|
||||
Currently defined formats are:
|
||||
|
||||
=over 4
|
||||
|
||||
=item \"installed\"
|
||||
|
||||
This is an installed operating system.
|
||||
|
||||
=item \"installer\"
|
||||
|
||||
The disk image being inspected is not an installed operating system,
|
||||
but a I<bootable> install disk, live CD, or similar.
|
||||
|
||||
=item \"unknown\"
|
||||
|
||||
The format of this disk image is not known.
|
||||
|
||||
=back
|
||||
|
||||
Future versions of libguestfs may return other strings here.
|
||||
The caller should be prepared to handle any string.
|
||||
|
||||
Please read L<guestfs(3)/INSPECTION> for more details." };
|
||||
|
||||
{ defaults with
|
||||
name = "inspect_is_live"; added = (1, 9, 4);
|
||||
style = RBool "live", [String (Mountable, "root")], [];
|
||||
shortdesc = "get live flag for install disk";
|
||||
longdesc = "\
|
||||
If C<guestfs_inspect_get_format> returns C<installer> (this
|
||||
is an install disk), then this returns true if a live image
|
||||
was detected on the disk.
|
||||
|
||||
Please read L<guestfs(3)/INSPECTION> for more details." };
|
||||
|
||||
{ defaults with
|
||||
name = "inspect_is_netinst"; added = (1, 9, 4);
|
||||
style = RBool "netinst", [String (Mountable, "root")], [];
|
||||
shortdesc = "get netinst (network installer) flag for install disk";
|
||||
longdesc = "\
|
||||
If C<guestfs_inspect_get_format> returns C<installer> (this
|
||||
is an install disk), then this returns true if the disk is
|
||||
a network installer, ie. not a self-contained install CD but
|
||||
one which is likely to require network access to complete
|
||||
the install.
|
||||
|
||||
Please read L<guestfs(3)/INSPECTION> for more details." };
|
||||
|
||||
{ defaults with
|
||||
name = "inspect_is_multipart"; added = (1, 9, 4);
|
||||
style = RBool "multipart", [String (Mountable, "root")], [];
|
||||
shortdesc = "get multipart flag for install disk";
|
||||
longdesc = "\
|
||||
If C<guestfs_inspect_get_format> returns C<installer> (this
|
||||
is an install disk), then this returns true if the disk is
|
||||
part of a set.
|
||||
|
||||
Please read L<guestfs(3)/INSPECTION> for more details." };
|
||||
|
||||
{ defaults with
|
||||
|
||||
@@ -119,6 +119,67 @@ If unavailable this is returned as an empty string C<\"\">.
|
||||
|
||||
=back
|
||||
|
||||
Please read L<guestfs(3)/INSPECTION> for more details." };
|
||||
|
||||
{ defaults with
|
||||
name = "inspect_get_format"; added = (1, 9, 4);
|
||||
style = RString (RPlainString, "format"), [String (Mountable, "root")], [];
|
||||
deprecated_by = Deprecated_no_replacement;
|
||||
shortdesc = "get format of inspected operating system";
|
||||
longdesc = "\
|
||||
Before libguestfs 1.38, there was some unreliable support for detecting
|
||||
installer CDs. This API would return:
|
||||
|
||||
=over 4
|
||||
|
||||
=item \"installed\"
|
||||
|
||||
This is an installed operating system.
|
||||
|
||||
=item \"installer\"
|
||||
|
||||
The disk image being inspected is not an installed operating system,
|
||||
but a I<bootable> install disk, live CD, or similar.
|
||||
|
||||
=item \"unknown\"
|
||||
|
||||
The format of this disk image is not known.
|
||||
|
||||
=back
|
||||
|
||||
In libguestfs E<ge> 1.38, this only returns C<installed>.
|
||||
Use libosinfo directly to detect installer CDs.
|
||||
|
||||
Please read L<guestfs(3)/INSPECTION> for more details." };
|
||||
|
||||
{ defaults with
|
||||
name = "inspect_is_live"; added = (1, 9, 4);
|
||||
style = RBool "live", [String (Mountable, "root")], [];
|
||||
deprecated_by = Deprecated_no_replacement;
|
||||
shortdesc = "get live flag for install disk";
|
||||
longdesc = "\
|
||||
This is deprecated and always returns C<false>.
|
||||
|
||||
Please read L<guestfs(3)/INSPECTION> for more details." };
|
||||
|
||||
{ defaults with
|
||||
name = "inspect_is_netinst"; added = (1, 9, 4);
|
||||
style = RBool "netinst", [String (Mountable, "root")], [];
|
||||
deprecated_by = Deprecated_no_replacement;
|
||||
shortdesc = "get netinst (network installer) flag for install disk";
|
||||
longdesc = "\
|
||||
This is deprecated and always returns C<false>.
|
||||
|
||||
Please read L<guestfs(3)/INSPECTION> for more details." };
|
||||
|
||||
{ defaults with
|
||||
name = "inspect_is_multipart"; added = (1, 9, 4);
|
||||
style = RBool "multipart", [String (Mountable, "root")], [];
|
||||
deprecated_by = Deprecated_no_replacement;
|
||||
shortdesc = "get multipart flag for install disk";
|
||||
longdesc = "\
|
||||
This is deprecated and always returns C<false>.
|
||||
|
||||
Please read L<guestfs(3)/INSPECTION> for more details." };
|
||||
|
||||
]
|
||||
|
||||
@@ -22,16 +22,7 @@ example_xml = \
|
||||
example-fedora.xml \
|
||||
example-rhel-6.xml \
|
||||
example-ubuntu.xml \
|
||||
example-windows.xml \
|
||||
example-debian-netinst-cd.xml \
|
||||
example-fedora-dvd.xml \
|
||||
example-fedora-netinst-cd.xml \
|
||||
example-rhel-6-dvd.xml \
|
||||
example-rhel-6-netinst-cd.xml \
|
||||
example-ubuntu-live-cd.xml \
|
||||
example-windows-2003-x64-cd.xml \
|
||||
example-windows-2003-x86-cd.xml \
|
||||
example-windows-xp-cd.xml
|
||||
example-windows.xml
|
||||
|
||||
EXTRA_DIST = \
|
||||
expected-debian.img.xml \
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<operatingsystems>
|
||||
<operatingsystem>
|
||||
<root>/dev/sda</root>
|
||||
<name>linux</name>
|
||||
<distro>debian</distro>
|
||||
<product_name>Debian GNU/Linux 5.0.5 "Lenny" - Official amd64 NETINST Binary-1 20100627-10:37</product_name>
|
||||
<major_version>5</major_version>
|
||||
<minor_version>0</minor_version>
|
||||
<format>installer</format>
|
||||
<netinst/>
|
||||
<mountpoints>
|
||||
<mountpoint dev="/dev/sda">/</mountpoint>
|
||||
</mountpoints>
|
||||
<filesystems>
|
||||
<filesystem dev="/dev/sda">
|
||||
<type>iso9660</type>
|
||||
<label>Debian 5.0.5 amd64 Bin-1</label>
|
||||
</filesystem>
|
||||
</filesystems>
|
||||
<applications/>
|
||||
</operatingsystem>
|
||||
</operatingsystems>
|
||||
@@ -11,7 +11,6 @@
|
||||
<package_format>deb</package_format>
|
||||
<package_management>apt</package_management>
|
||||
<hostname>debian5x64.home.annexia.org</hostname>
|
||||
<format>installed</format>
|
||||
<mountpoints>
|
||||
<mountpoint dev="/dev/debian5x64.home.annexia.org/root">/</mountpoint>
|
||||
<mountpoint dev="/dev/debian5x64.home.annexia.org/tmp">/tmp</mountpoint>
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<operatingsystems>
|
||||
<operatingsystem>
|
||||
<root>/dev/sda</root>
|
||||
<name>linux</name>
|
||||
<arch>x86_64</arch>
|
||||
<distro>fedora</distro>
|
||||
<major_version>14</major_version>
|
||||
<minor_version>0</minor_version>
|
||||
<format>installer</format>
|
||||
<multipart/>
|
||||
<mountpoints>
|
||||
<mountpoint dev="/dev/sda">/</mountpoint>
|
||||
</mountpoints>
|
||||
<filesystems>
|
||||
<filesystem dev="/dev/sda">
|
||||
<type>iso9660</type>
|
||||
<label>Fedora 14 x86_64 DVD</label>
|
||||
</filesystem>
|
||||
</filesystems>
|
||||
<applications/>
|
||||
</operatingsystem>
|
||||
</operatingsystems>
|
||||
@@ -1,21 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<operatingsystems>
|
||||
<operatingsystem>
|
||||
<root>/dev/sda</root>
|
||||
<name>linux</name>
|
||||
<distro>fedora</distro>
|
||||
<major_version>14</major_version>
|
||||
<minor_version>0</minor_version>
|
||||
<format>installer</format>
|
||||
<mountpoints>
|
||||
<mountpoint dev="/dev/sda">/</mountpoint>
|
||||
</mountpoints>
|
||||
<filesystems>
|
||||
<filesystem dev="/dev/sda">
|
||||
<type>iso9660</type>
|
||||
<label>Fedora</label>
|
||||
</filesystem>
|
||||
</filesystems>
|
||||
<applications/>
|
||||
</operatingsystem>
|
||||
</operatingsystems>
|
||||
@@ -11,7 +11,6 @@
|
||||
<package_format>rpm</package_format>
|
||||
<package_management>yum</package_management>
|
||||
<hostname>f18x64homeannexiaorg</hostname>
|
||||
<format>installed</format>
|
||||
<mountpoints>
|
||||
<mountpoint dev="/dev/fedora/root">/</mountpoint>
|
||||
<mountpoint dev="/dev/sda1">/boot</mountpoint>
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<operatingsystems>
|
||||
<operatingsystem>
|
||||
<root>/dev/sda</root>
|
||||
<name>linux</name>
|
||||
<arch>x86_64</arch>
|
||||
<distro>rhel</distro>
|
||||
<major_version>6</major_version>
|
||||
<minor_version>0</minor_version>
|
||||
<format>installer</format>
|
||||
<multipart/>
|
||||
<mountpoints>
|
||||
<mountpoint dev="/dev/sda">/</mountpoint>
|
||||
</mountpoints>
|
||||
<filesystems>
|
||||
<filesystem dev="/dev/sda">
|
||||
<type>iso9660</type>
|
||||
<label>RHEL_6.0 x86_64 Disc 1</label>
|
||||
</filesystem>
|
||||
</filesystems>
|
||||
<applications/>
|
||||
</operatingsystem>
|
||||
</operatingsystems>
|
||||
@@ -1,21 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<operatingsystems>
|
||||
<operatingsystem>
|
||||
<root>/dev/sda</root>
|
||||
<name>linux</name>
|
||||
<distro>rhel</distro>
|
||||
<major_version>6</major_version>
|
||||
<minor_version>0</minor_version>
|
||||
<format>installer</format>
|
||||
<mountpoints>
|
||||
<mountpoint dev="/dev/sda">/</mountpoint>
|
||||
</mountpoints>
|
||||
<filesystems>
|
||||
<filesystem dev="/dev/sda">
|
||||
<type>iso9660</type>
|
||||
<label>RHEL_6.0 x86_64 boot</label>
|
||||
</filesystem>
|
||||
</filesystems>
|
||||
<applications/>
|
||||
</operatingsystem>
|
||||
</operatingsystems>
|
||||
@@ -11,7 +11,6 @@
|
||||
<package_format>rpm</package_format>
|
||||
<package_management>yum</package_management>
|
||||
<hostname>rhel6x32.home.annexia.org</hostname>
|
||||
<format>installed</format>
|
||||
<mountpoints>
|
||||
<mountpoint dev="/dev/vg_rhel6x32/lv_root">/</mountpoint>
|
||||
<mountpoint dev="/dev/sda1">/boot</mountpoint>
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<operatingsystems>
|
||||
<operatingsystem>
|
||||
<root>/dev/sda</root>
|
||||
<name>linux</name>
|
||||
<distro>ubuntu</distro>
|
||||
<product_name>Ubuntu 10.10 "Maverick Meerkat" - Release amd64 (20101007)</product_name>
|
||||
<major_version>10</major_version>
|
||||
<minor_version>10</minor_version>
|
||||
<format>installer</format>
|
||||
<live/>
|
||||
<mountpoints>
|
||||
<mountpoint dev="/dev/sda">/</mountpoint>
|
||||
</mountpoints>
|
||||
<filesystems>
|
||||
<filesystem dev="/dev/sda">
|
||||
<type>iso9660</type>
|
||||
<label>Ubuntu 10.10 amd64</label>
|
||||
</filesystem>
|
||||
</filesystems>
|
||||
<applications/>
|
||||
</operatingsystem>
|
||||
</operatingsystems>
|
||||
@@ -11,7 +11,6 @@
|
||||
<package_format>deb</package_format>
|
||||
<package_management>apt</package_management>
|
||||
<hostname>ubuntu1304.home.annexia.org</hostname>
|
||||
<format>installed</format>
|
||||
<mountpoints>
|
||||
<mountpoint dev="/dev/sda1">/</mountpoint>
|
||||
</mountpoints>
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<operatingsystems>
|
||||
<operatingsystem>
|
||||
<root>/dev/sda</root>
|
||||
<name>windows</name>
|
||||
<arch>x86_64</arch>
|
||||
<distro>windows</distro>
|
||||
<product_name>Windows Server 2003 Enterprise x64 Edition</product_name>
|
||||
<major_version>5</major_version>
|
||||
<minor_version>2</minor_version>
|
||||
<windows_systemroot>\WINDOWS</windows_systemroot>
|
||||
<format>installer</format>
|
||||
<mountpoints>
|
||||
<mountpoint dev="/dev/sda">/</mountpoint>
|
||||
</mountpoints>
|
||||
<filesystems>
|
||||
<filesystem dev="/dev/sda">
|
||||
<type>iso9660</type>
|
||||
<label>CRMEXFPP_EN</label>
|
||||
</filesystem>
|
||||
</filesystems>
|
||||
<applications/>
|
||||
</operatingsystem>
|
||||
</operatingsystems>
|
||||
@@ -1,24 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<operatingsystems>
|
||||
<operatingsystem>
|
||||
<root>/dev/sda</root>
|
||||
<name>windows</name>
|
||||
<arch>i386</arch>
|
||||
<distro>windows</distro>
|
||||
<product_name>Windows Server 2003, Enterprise</product_name>
|
||||
<major_version>5</major_version>
|
||||
<minor_version>2</minor_version>
|
||||
<windows_systemroot>\WINDOWS</windows_systemroot>
|
||||
<format>installer</format>
|
||||
<mountpoints>
|
||||
<mountpoint dev="/dev/sda">/</mountpoint>
|
||||
</mountpoints>
|
||||
<filesystems>
|
||||
<filesystem dev="/dev/sda">
|
||||
<type>iso9660</type>
|
||||
<label>CRMEFPP_EN</label>
|
||||
</filesystem>
|
||||
</filesystems>
|
||||
<applications/>
|
||||
</operatingsystem>
|
||||
</operatingsystems>
|
||||
@@ -1,24 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<operatingsystems>
|
||||
<operatingsystem>
|
||||
<root>/dev/sda</root>
|
||||
<name>windows</name>
|
||||
<arch>i386</arch>
|
||||
<distro>windows</distro>
|
||||
<product_name>Windows XP Professional</product_name>
|
||||
<major_version>5</major_version>
|
||||
<minor_version>1</minor_version>
|
||||
<windows_systemroot>\WINDOWS</windows_systemroot>
|
||||
<format>installer</format>
|
||||
<mountpoints>
|
||||
<mountpoint dev="/dev/sda">/</mountpoint>
|
||||
</mountpoints>
|
||||
<filesystems>
|
||||
<filesystem dev="/dev/sda">
|
||||
<type>iso9660</type>
|
||||
<label>GRTMPFPP_EN</label>
|
||||
</filesystem>
|
||||
</filesystems>
|
||||
<applications/>
|
||||
</operatingsystem>
|
||||
</operatingsystems>
|
||||
@@ -12,7 +12,6 @@
|
||||
<windows_systemroot>/Windows</windows_systemroot>
|
||||
<windows_current_control_set>ControlSet001</windows_current_control_set>
|
||||
<hostname>WIN-6AOV5N85H2F</hostname>
|
||||
<format>installed</format>
|
||||
<mountpoints>
|
||||
<mountpoint dev="/dev/sda2">/</mountpoint>
|
||||
</mountpoints>
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
<package_format>pacman</package_format>
|
||||
<package_management>pacman</package_management>
|
||||
<hostname>archlinux.test</hostname>
|
||||
<format>installed</format>
|
||||
<mountpoints>
|
||||
<mountpoint dev="/dev/sda1">/</mountpoint>
|
||||
</mountpoints>
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
<major_version>899</major_version>
|
||||
<minor_version>13</minor_version>
|
||||
<hostname>coreos.invalid</hostname>
|
||||
<format>installed</format>
|
||||
<mountpoints>
|
||||
<mountpoint dev="/dev/sda5">/</mountpoint>
|
||||
<mountpoint dev="/dev/sda3">/usr</mountpoint>
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
<package_format>deb</package_format>
|
||||
<package_management>apt</package_management>
|
||||
<hostname>debian.invalid</hostname>
|
||||
<format>installed</format>
|
||||
<mountpoints>
|
||||
<mountpoint dev="/dev/debian/root">/</mountpoint>
|
||||
<mountpoint dev="/dev/debian/usr">/usr</mountpoint>
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
<package_format>rpm</package_format>
|
||||
<package_management>yum</package_management>
|
||||
<hostname>fedora.invalid</hostname>
|
||||
<format>installed</format>
|
||||
<mountpoints>
|
||||
<mountpoint dev="/dev/VG/Root">/</mountpoint>
|
||||
<mountpoint dev="/dev/sda1">/boot</mountpoint>
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
<package_format>deb</package_format>
|
||||
<package_management>apt</package_management>
|
||||
<hostname>ubuntu.invalid</hostname>
|
||||
<format>installed</format>
|
||||
<mountpoints>
|
||||
<mountpoint dev="/dev/sda2">/</mountpoint>
|
||||
<mountpoint dev="/dev/sda1">/boot</mountpoint>
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
<windows_systemroot>/Windows</windows_systemroot>
|
||||
<windows_current_control_set>ControlSet001</windows_current_control_set>
|
||||
<hostname>windows.invalid</hostname>
|
||||
<format>installed</format>
|
||||
<mountpoints>
|
||||
<mountpoint dev="/dev/sda2">/</mountpoint>
|
||||
</mountpoints>
|
||||
|
||||
@@ -343,7 +343,7 @@ static void
|
||||
output_root (xmlTextWriterPtr xo, char *root)
|
||||
{
|
||||
char *str;
|
||||
int i, r;
|
||||
int i;
|
||||
char buf[32];
|
||||
char *canonical_root;
|
||||
size_t size;
|
||||
@@ -443,35 +443,6 @@ output_root (xmlTextWriterPtr xo, char *root)
|
||||
BAD_CAST str));
|
||||
free (str);
|
||||
|
||||
str = guestfs_inspect_get_format (g, root);
|
||||
if (!str) exit (EXIT_FAILURE);
|
||||
if (STRNEQ (str, "unknown"))
|
||||
XMLERROR (-1,
|
||||
xmlTextWriterWriteElement (xo, BAD_CAST "format",
|
||||
BAD_CAST str));
|
||||
free (str);
|
||||
|
||||
r = guestfs_inspect_is_live (g, root);
|
||||
if (r > 0) {
|
||||
XMLERROR (-1,
|
||||
xmlTextWriterStartElement (xo, BAD_CAST "live"));
|
||||
XMLERROR (-1, xmlTextWriterEndElement (xo));
|
||||
}
|
||||
|
||||
r = guestfs_inspect_is_netinst (g, root);
|
||||
if (r > 0) {
|
||||
XMLERROR (-1,
|
||||
xmlTextWriterStartElement (xo, BAD_CAST "netinst"));
|
||||
XMLERROR (-1, xmlTextWriterEndElement (xo));
|
||||
}
|
||||
|
||||
r = guestfs_inspect_is_multipart (g, root);
|
||||
if (r > 0) {
|
||||
XMLERROR (-1,
|
||||
xmlTextWriterStartElement (xo, BAD_CAST "multipart"));
|
||||
XMLERROR (-1, xmlTextWriterEndElement (xo));
|
||||
}
|
||||
|
||||
output_mountpoints (xo, root);
|
||||
|
||||
output_filesystems (xo, root);
|
||||
|
||||
@@ -202,7 +202,6 @@ describe the operating system, its architecture, the descriptive
|
||||
<major_version>6</major_version>
|
||||
<minor_version>1</minor_version>
|
||||
<windows_systemroot>/Windows</windows_systemroot>
|
||||
<format>installed</format>
|
||||
|
||||
In brief, E<lt>nameE<gt> is the class of operating system (something
|
||||
like C<linux> or C<windows>), E<lt>distroE<gt> is the distribution
|
||||
@@ -330,27 +329,6 @@ the conversion back to a PNG file:
|
||||
|
||||
base64 -i -d < icon.data > icon.png
|
||||
|
||||
=head2 INSPECTING INSTALL DISKS, LIVE CDs
|
||||
|
||||
Virt-inspector can detect some operating system installers on
|
||||
install disks, live CDs, bootable USB keys and more.
|
||||
|
||||
In this case the E<lt>formatE<gt> tag will contain C<installer>
|
||||
and other fields may be present to indicate a live CD, network
|
||||
installer, or one part of a multipart CD. For example:
|
||||
|
||||
<operatingsystems>
|
||||
<operatingsystem>
|
||||
<root>/dev/sda</root>
|
||||
<name>linux</name>
|
||||
<arch>i386</arch>
|
||||
<distro>ubuntu</distro>
|
||||
<product_name>Ubuntu 10.10 "Maverick Meerkat"</product_name>
|
||||
<major_version>10</major_version>
|
||||
<minor_version>10</minor_version>
|
||||
<format>installer</format>
|
||||
<live/>
|
||||
|
||||
=head1 XPATH QUERIES
|
||||
|
||||
Virt-inspector includes built in support for running XPath queries.
|
||||
|
||||
@@ -38,10 +38,6 @@
|
||||
<optional><ref name="ospackageformat"/></optional>
|
||||
<optional><ref name="ospackagemanagement"/></optional>
|
||||
<optional><element name="hostname"><text/></element></optional>
|
||||
<optional><ref name="osformat"/></optional>
|
||||
<optional><element name="live"><empty/></element></optional>
|
||||
<optional><element name="netinst"><empty/></element></optional>
|
||||
<optional><element name="multipart"><empty/></element></optional>
|
||||
|
||||
<ref name="mountpoints"/>
|
||||
<ref name="filesystems"/>
|
||||
@@ -152,17 +148,6 @@
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<!-- the operating system format -->
|
||||
<define name="osformat">
|
||||
<element name="format">
|
||||
<choice>
|
||||
<value>installed</value>
|
||||
<value>installer</value>
|
||||
<!-- "unknown" is intentionally left out -->
|
||||
</choice>
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<!-- how filesystems are mounted on mount points -->
|
||||
<define name="mountpoints">
|
||||
<element name="mountpoints">
|
||||
|
||||
@@ -97,7 +97,6 @@ libguestfs_la_SOURCES = \
|
||||
inspect.c \
|
||||
inspect-apps.c \
|
||||
inspect-fs.c \
|
||||
inspect-fs-cd.c \
|
||||
inspect-fs-unix.c \
|
||||
inspect-fs-windows.c \
|
||||
inspect-icon.c \
|
||||
@@ -112,7 +111,6 @@ libguestfs_la_SOURCES = \
|
||||
lpj.c \
|
||||
match.c \
|
||||
mountable.c \
|
||||
osinfo.c \
|
||||
private-data.c \
|
||||
proto.c \
|
||||
qemu.c \
|
||||
@@ -134,7 +132,6 @@ libguestfs_la_SOURCES = \
|
||||
libguestfs_la_CPPFLAGS = \
|
||||
-DGUESTFS_WARN_DEPRECATED=1 \
|
||||
-DGUESTFS_PRIVATE=1 \
|
||||
-DLIBOSINFO_DB_PATH='"$(datadir)/libosinfo/db"' \
|
||||
-I$(top_srcdir)/common/errnostring -I$(top_builddir)/common/errnostring \
|
||||
-I$(top_srcdir)/common/protocol -I$(top_builddir)/common/protocol \
|
||||
-I$(top_srcdir)/common/qemuopts -I$(top_builddir)/common/qemuopts \
|
||||
|
||||
@@ -889,10 +889,6 @@ extern char *guestfs_int_case_sensitive_path_silently (guestfs_h *g, const char
|
||||
extern char * guestfs_int_get_windows_systemroot (guestfs_h *g);
|
||||
extern int guestfs_int_check_windows_root (guestfs_h *g, struct inspect_fs *fs, char *windows_systemroot);
|
||||
|
||||
/* inspect-fs-cd.c */
|
||||
extern int guestfs_int_check_installer_root (guestfs_h *g, struct inspect_fs *fs);
|
||||
extern int guestfs_int_check_installer_iso (guestfs_h *g, struct inspect_fs *fs, const char *device);
|
||||
|
||||
/* dbdump.c */
|
||||
typedef int (*guestfs_int_db_dump_callback) (guestfs_h *g, const unsigned char *key, size_t keylen, const unsigned char *value, size_t valuelen, void *opaque);
|
||||
extern int guestfs_int_read_db_dump (guestfs_h *g, const char *dumpfile, void *opaque, guestfs_int_db_dump_callback callback);
|
||||
@@ -910,33 +906,6 @@ extern void guestfs_int_free_fuse (guestfs_h *g);
|
||||
extern virConnectPtr guestfs_int_open_libvirt_connection (guestfs_h *g, const char *uri, unsigned int flags);
|
||||
#endif
|
||||
|
||||
/* osinfo.c */
|
||||
struct osinfo {
|
||||
/* Data provided by libosinfo database. */
|
||||
enum inspect_os_type type;
|
||||
enum inspect_os_distro distro;
|
||||
char *product_name;
|
||||
int major_version;
|
||||
int minor_version;
|
||||
char *arch;
|
||||
int is_live_disk;
|
||||
bool is_installer;
|
||||
|
||||
#if 0
|
||||
/* Not yet available in libosinfo database. */
|
||||
char *product_variant;
|
||||
int is_netinst_disk;
|
||||
int is_multipart_disk;
|
||||
#endif
|
||||
|
||||
/* The regular expressions used to match ISOs. */
|
||||
pcre *re_system_id;
|
||||
pcre *re_volume_id;
|
||||
pcre *re_publisher_id;
|
||||
pcre *re_application_id;
|
||||
};
|
||||
extern int guestfs_int_osinfo_map (guestfs_h *g, const struct guestfs_isoinfo *isoinfo, const struct osinfo **osinfo_ret);
|
||||
|
||||
/* command.c */
|
||||
struct command;
|
||||
typedef void (*cmd_stdout_callback) (guestfs_h *g, void *data, const char *line, size_t len);
|
||||
|
||||
@@ -939,20 +939,11 @@ documentation for that function for details).
|
||||
Libguestfs (since 1.9.4) can detect some install disks, install
|
||||
CDs, live CDs and more.
|
||||
|
||||
Call L</guestfs_inspect_get_format> to return the format of the
|
||||
operating system, which currently can be C<installed> (a regular
|
||||
operating system) or C<installer> (some sort of install disk).
|
||||
|
||||
Further information is available about the operating system that can
|
||||
be installed using the regular inspection APIs like
|
||||
L</guestfs_inspect_get_product_name>,
|
||||
L</guestfs_inspect_get_major_version> etc.
|
||||
|
||||
Some additional information specific to installer disks is also
|
||||
available from the L</guestfs_inspect_is_live>,
|
||||
L</guestfs_inspect_is_netinst> and L</guestfs_inspect_is_multipart>
|
||||
calls.
|
||||
|
||||
=head2 SPECIAL CONSIDERATIONS FOR WINDOWS GUESTS
|
||||
|
||||
Libguestfs can mount NTFS partitions. It does this using the
|
||||
|
||||
@@ -1,607 +0,0 @@
|
||||
/* libguestfs
|
||||
* Copyright (C) 2010-2012 Red Hat Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <libintl.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifdef HAVE_ENDIAN_H
|
||||
#include <endian.h>
|
||||
#endif
|
||||
|
||||
#include "c-ctype.h"
|
||||
|
||||
#include "guestfs.h"
|
||||
#include "guestfs-internal.h"
|
||||
#include "structs-cleanups.h"
|
||||
|
||||
/* Debian/Ubuntu install disks are easy ...
|
||||
*
|
||||
* These files are added by the debian-cd program, and it is worth
|
||||
* looking at the source code to determine exact values, in
|
||||
* particular '/usr/share/debian-cd/tools/start_new_disc'
|
||||
*
|
||||
* XXX Architecture? We could parse it out of the product name
|
||||
* string, but that seems quite hairy. We could look for the names
|
||||
* of packages. Also note that some Debian install disks are
|
||||
* multiarch.
|
||||
*/
|
||||
static int
|
||||
check_debian_installer_root (guestfs_h *g, struct inspect_fs *fs)
|
||||
{
|
||||
fs->product_name = guestfs_int_first_line_of_file (g, "/.disk/info");
|
||||
if (!fs->product_name)
|
||||
return -1;
|
||||
|
||||
fs->type = OS_TYPE_LINUX;
|
||||
if (STRPREFIX (fs->product_name, "Ubuntu"))
|
||||
fs->distro = OS_DISTRO_UBUNTU;
|
||||
else if (STRPREFIX (fs->product_name, "Debian"))
|
||||
fs->distro = OS_DISTRO_DEBIAN;
|
||||
|
||||
(void) guestfs_int_parse_major_minor (g, fs);
|
||||
|
||||
if (guestfs_is_file (g, "/.disk/cd_type") > 0) {
|
||||
CLEANUP_FREE char *cd_type =
|
||||
guestfs_int_first_line_of_file (g, "/.disk/cd_type");
|
||||
if (!cd_type)
|
||||
return -1;
|
||||
|
||||
if (STRPREFIX (cd_type, "dvd/single") ||
|
||||
STRPREFIX (cd_type, "full_cd/single")) {
|
||||
fs->is_multipart_disk = 0;
|
||||
fs->is_netinst_disk = 0;
|
||||
}
|
||||
else if (STRPREFIX (cd_type, "dvd") ||
|
||||
STRPREFIX (cd_type, "full_cd")) {
|
||||
fs->is_multipart_disk = 1;
|
||||
fs->is_netinst_disk = 0;
|
||||
}
|
||||
else if (STRPREFIX (cd_type, "not_complete")) {
|
||||
fs->is_multipart_disk = 0;
|
||||
fs->is_netinst_disk = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Take string which must look like "key = value" and find the value.
|
||||
* There may or may not be spaces before and after the equals sign.
|
||||
* This function is used by both check_fedora_installer_root and
|
||||
* check_w2k3_installer_root.
|
||||
*/
|
||||
static const char *
|
||||
find_value (const char *kv)
|
||||
{
|
||||
const char *p;
|
||||
|
||||
p = strchr (kv, '=');
|
||||
if (!p)
|
||||
abort ();
|
||||
|
||||
do {
|
||||
++p;
|
||||
} while (c_isspace (*p));
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/* RHEL 5 has a DVD.iso and several CD-sized -discX-ftp.iso alternatives.
|
||||
*
|
||||
* The DVD.iso contains:
|
||||
* /.treeinfo:
|
||||
* [general]
|
||||
* family = Red Hat Enterprise Linux Server
|
||||
* timestamp = 1328200566.61
|
||||
* totaldiscs = 1
|
||||
* version = 5.8
|
||||
* discnum = 1
|
||||
* packagedir = Server
|
||||
* arch = x86_64
|
||||
* [...]
|
||||
*
|
||||
* /.discinfo:
|
||||
* 1328205744.315196
|
||||
* Red Hat Enterprise Linux Server 5.8 # product name
|
||||
* x86_64 # arch
|
||||
* 1 # disk number
|
||||
* Server/base
|
||||
* Server/RPMS
|
||||
* Server/pixmaps
|
||||
*
|
||||
* The alternative CD-sized ISOs contain:
|
||||
*
|
||||
* disc1:
|
||||
* /.treeinfo:
|
||||
* [general]
|
||||
* family = Red Hat Enterprise Linux Server
|
||||
* timestamp = 1328200566.61
|
||||
* totaldiscs = 1
|
||||
* version = 5.8
|
||||
* discnum = 1
|
||||
* packagedir = Server
|
||||
* arch = x86_64
|
||||
* [...]
|
||||
*
|
||||
* /.discinfo:
|
||||
* 1328205744.315196
|
||||
* Red Hat Enterprise Linux Server 5.8 # product name
|
||||
* x86_64 # arch
|
||||
* 1 # disk number
|
||||
* Server/base
|
||||
* Server/RPMS
|
||||
* Server/pixmaps
|
||||
*
|
||||
* discN (N > 1):
|
||||
* /.discinfo:
|
||||
* 1328205744.315196
|
||||
* Red Hat Enterprise Linux Server 5.8 # product name
|
||||
* x86_64 # arch
|
||||
* 2 # disk number
|
||||
* Server/base
|
||||
* Server/RPMS
|
||||
* Server/pixmaps
|
||||
*/
|
||||
|
||||
/* Fedora CDs and DVD (not netinst). The /.treeinfo file contains
|
||||
* an initial section somewhat like this:
|
||||
*
|
||||
* [general]
|
||||
* version = 14
|
||||
* arch = x86_64
|
||||
* family = Fedora
|
||||
* variant = Fedora
|
||||
* discnum = 1
|
||||
* totaldiscs = 1
|
||||
*/
|
||||
static int
|
||||
check_fedora_installer_root (guestfs_h *g, struct inspect_fs *fs)
|
||||
{
|
||||
char *str;
|
||||
const char *v;
|
||||
int r;
|
||||
int discnum = 0, totaldiscs = 0;
|
||||
|
||||
fs->type = OS_TYPE_LINUX;
|
||||
|
||||
r = guestfs_int_first_egrep_of_file (g, "/.treeinfo",
|
||||
"^family = Fedora$", 0, &str);
|
||||
if (r == -1)
|
||||
return -1;
|
||||
if (r > 0) {
|
||||
fs->distro = OS_DISTRO_FEDORA;
|
||||
free (str);
|
||||
}
|
||||
|
||||
r = guestfs_int_first_egrep_of_file (g, "/.treeinfo",
|
||||
"^family = Red Hat Enterprise Linux$",
|
||||
0, &str);
|
||||
if (r == -1)
|
||||
return -1;
|
||||
if (r > 0) {
|
||||
fs->distro = OS_DISTRO_RHEL;
|
||||
free (str);
|
||||
}
|
||||
|
||||
r = guestfs_int_first_egrep_of_file (g, "/.treeinfo",
|
||||
"^family = Oracle Linux Server$",
|
||||
0, &str);
|
||||
if (r == -1)
|
||||
return -1;
|
||||
if (r > 0) {
|
||||
fs->distro = OS_DISTRO_ORACLE_LINUX;
|
||||
free (str);
|
||||
}
|
||||
|
||||
/* XXX should do major.minor before this */
|
||||
r = guestfs_int_first_egrep_of_file (g, "/.treeinfo",
|
||||
"^version = [[:digit:]]+", 0, &str);
|
||||
if (r == -1)
|
||||
return -1;
|
||||
if (r > 0) {
|
||||
v = find_value (str);
|
||||
fs->version.v_major = guestfs_int_parse_unsigned_int_ignore_trailing (g, v);
|
||||
free (str);
|
||||
if (fs->version.v_major == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = guestfs_int_first_egrep_of_file (g, "/.treeinfo",
|
||||
"^arch = [-_[:alnum:]]+$", 0, &str);
|
||||
if (r == -1)
|
||||
return -1;
|
||||
if (r > 0) {
|
||||
v = find_value (str);
|
||||
fs->arch = safe_strdup (g, v);
|
||||
free (str);
|
||||
}
|
||||
|
||||
r = guestfs_int_first_egrep_of_file (g, "/.treeinfo",
|
||||
"^discnum = [[:digit:]]+$", 0, &str);
|
||||
if (r == -1)
|
||||
return -1;
|
||||
if (r > 0) {
|
||||
v = find_value (str);
|
||||
discnum = guestfs_int_parse_unsigned_int (g, v);
|
||||
free (str);
|
||||
if (discnum == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = guestfs_int_first_egrep_of_file (g, "/.treeinfo",
|
||||
"^totaldiscs = [[:digit:]]+$", 0, &str);
|
||||
if (r == -1)
|
||||
return -1;
|
||||
if (r > 0) {
|
||||
v = find_value (str);
|
||||
totaldiscs = guestfs_int_parse_unsigned_int (g, v);
|
||||
free (str);
|
||||
if (totaldiscs == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
fs->is_multipart_disk = totaldiscs > 1;
|
||||
/* and what about discnum? */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Linux with /isolinux/isolinux.cfg.
|
||||
*
|
||||
* This file is not easily parsable so we have to do our best.
|
||||
* Look for the "menu title" line which contains:
|
||||
* menu title Welcome to Fedora 14! # since at least Fedora 10
|
||||
* menu title Welcome to Red Hat Enterprise Linux 6.0!
|
||||
* menu title Welcome to RHEL6.2-20111117.0-Workstation-x!
|
||||
*/
|
||||
static int
|
||||
check_isolinux_installer_root (guestfs_h *g, struct inspect_fs *fs)
|
||||
{
|
||||
char *str;
|
||||
int r;
|
||||
|
||||
fs->type = OS_TYPE_LINUX;
|
||||
|
||||
r = guestfs_int_first_egrep_of_file (g, "/isolinux/isolinux.cfg",
|
||||
"^menu title Welcome to Fedora [[:digit:]]+",
|
||||
0, &str);
|
||||
if (r == -1)
|
||||
return -1;
|
||||
if (r > 0) {
|
||||
fs->distro = OS_DISTRO_FEDORA;
|
||||
fs->version.v_major =
|
||||
guestfs_int_parse_unsigned_int_ignore_trailing (g, &str[29]);
|
||||
free (str);
|
||||
if (fs->version.v_major == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* XXX parse major.minor */
|
||||
r = guestfs_int_first_egrep_of_file (g, "/isolinux/isolinux.cfg",
|
||||
"^menu title Welcome to Red Hat Enterprise Linux [[:digit:]]+",
|
||||
0, &str);
|
||||
if (r == -1)
|
||||
return -1;
|
||||
if (r > 0) {
|
||||
fs->distro = OS_DISTRO_RHEL;
|
||||
fs->version.v_major =
|
||||
guestfs_int_parse_unsigned_int_ignore_trailing (g, &str[47]);
|
||||
free (str);
|
||||
if (fs->version.v_major == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* XXX parse major.minor */
|
||||
r = guestfs_int_first_egrep_of_file (g, "/isolinux/isolinux.cfg",
|
||||
"^menu title Welcome to RHEL[[:digit:]]+",
|
||||
0, &str);
|
||||
if (r == -1)
|
||||
return -1;
|
||||
if (r > 0) {
|
||||
fs->distro = OS_DISTRO_RHEL;
|
||||
fs->version.v_major =
|
||||
guestfs_int_parse_unsigned_int_ignore_trailing (g, &str[26]);
|
||||
free (str);
|
||||
if (fs->version.v_major == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* XXX parse major.minor */
|
||||
r = guestfs_int_first_egrep_of_file (g, "/isolinux/isolinux.cfg",
|
||||
"^menu title Welcome to Oracle Linux Server [[:digit:]]+",
|
||||
0, &str);
|
||||
if (r == -1)
|
||||
return -1;
|
||||
if (r > 0) {
|
||||
fs->distro = OS_DISTRO_ORACLE_LINUX;
|
||||
fs->version.v_major =
|
||||
guestfs_int_parse_unsigned_int_ignore_trailing (g, &str[42]);
|
||||
free (str);
|
||||
if (fs->version.v_major == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Windows 2003 and similar versions.
|
||||
*
|
||||
* NB: txtsetup file contains Windows \r\n line endings, which guestfs_grep
|
||||
* does not remove. We have to remove them by hand here.
|
||||
*/
|
||||
static void
|
||||
trim_cr (char *str)
|
||||
{
|
||||
const size_t n = strlen (str);
|
||||
if (n > 0 && str[n-1] == '\r')
|
||||
str[n-1] = '\0';
|
||||
}
|
||||
|
||||
static void
|
||||
trim_quot (char *str)
|
||||
{
|
||||
const size_t n = strlen (str);
|
||||
if (n > 0 && str[n-1] == '"')
|
||||
str[n-1] = '\0';
|
||||
}
|
||||
|
||||
static int
|
||||
check_w2k3_installer_root (guestfs_h *g, struct inspect_fs *fs,
|
||||
const char *txtsetup)
|
||||
{
|
||||
char *str;
|
||||
const char *v;
|
||||
int r;
|
||||
|
||||
fs->type = OS_TYPE_WINDOWS;
|
||||
fs->distro = OS_DISTRO_WINDOWS;
|
||||
|
||||
r = guestfs_int_first_egrep_of_file (g, txtsetup,
|
||||
"^productname[[:space:]]*=[[:space:]]*\"", 1, &str);
|
||||
if (r == -1)
|
||||
return -1;
|
||||
if (r > 0) {
|
||||
trim_cr (str);
|
||||
trim_quot (str);
|
||||
v = find_value (str);
|
||||
fs->product_name = safe_strdup (g, v+1);
|
||||
free (str);
|
||||
}
|
||||
|
||||
r = guestfs_int_first_egrep_of_file (g, txtsetup,
|
||||
"^majorversion[[:space:]]*=[[:space:]]*[[:digit:]]+",
|
||||
1, &str);
|
||||
if (r == -1)
|
||||
return -1;
|
||||
if (r > 0) {
|
||||
trim_cr (str);
|
||||
v = find_value (str);
|
||||
fs->version.v_major = guestfs_int_parse_unsigned_int_ignore_trailing (g, v);
|
||||
free (str);
|
||||
if (fs->version.v_major == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = guestfs_int_first_egrep_of_file (g, txtsetup,
|
||||
"^minorversion[[:space:]]*=[[:space:]]*[[:digit:]]+",
|
||||
1, &str);
|
||||
if (r == -1)
|
||||
return -1;
|
||||
if (r > 0) {
|
||||
trim_cr (str);
|
||||
v = find_value (str);
|
||||
fs->version.v_minor = guestfs_int_parse_unsigned_int_ignore_trailing (g, v);
|
||||
free (str);
|
||||
if (fs->version.v_minor == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* This is the windows systemroot that would be chosen on
|
||||
* installation by default, although not necessarily the one that
|
||||
* the user will finally choose.
|
||||
*/
|
||||
r = guestfs_int_first_egrep_of_file (g, txtsetup,
|
||||
"^defaultpath[[:space:]]*=[[:space:]]*",
|
||||
1, &str);
|
||||
if (r == -1)
|
||||
return -1;
|
||||
if (r > 0) {
|
||||
trim_cr (str);
|
||||
v = find_value (str);
|
||||
fs->windows_systemroot = safe_strdup (g, v);
|
||||
free (str);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read the data from a product.id-like file.
|
||||
*
|
||||
* This is an old file, mostly used in Mandriva-based systems (still including
|
||||
* Mageia). A very minimal documentation for it is:
|
||||
* - https://wiki.mageia.org/en/Product_id
|
||||
* - http://wiki.mandriva.com/en/Product_id (old URL, defunct)
|
||||
*/
|
||||
static int
|
||||
check_product_id_installer_root (guestfs_h *g, struct inspect_fs *fs,
|
||||
const char *filename)
|
||||
{
|
||||
CLEANUP_FREE char *line = NULL;
|
||||
const char *elem;
|
||||
char *saveptr;
|
||||
|
||||
fs->type = OS_TYPE_LINUX;
|
||||
|
||||
line = guestfs_int_first_line_of_file (g, filename);
|
||||
if (line == NULL)
|
||||
return -1;
|
||||
|
||||
elem = strtok_r (line, ",", &saveptr);
|
||||
while (elem) {
|
||||
const char *equal = strchr (elem, '=');
|
||||
if (equal == NULL || equal == elem)
|
||||
return -1;
|
||||
|
||||
const char *value = equal + 1;
|
||||
|
||||
if (STRPREFIX (elem, "distribution=")) {
|
||||
if (STREQ (value, "Mageia"))
|
||||
fs->distro = OS_DISTRO_MAGEIA;
|
||||
} else if (STRPREFIX (elem, "version=")) {
|
||||
if (guestfs_int_version_from_x_y_or_x (g, &fs->version, value) == -1)
|
||||
return -1;
|
||||
} else if (STRPREFIX (elem, "arch=")) {
|
||||
fs->arch = safe_strdup (g, value);
|
||||
}
|
||||
|
||||
elem = strtok_r (NULL, ",", &saveptr);
|
||||
}
|
||||
|
||||
/* Not found. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The currently mounted device is very likely to be an installer. */
|
||||
int
|
||||
guestfs_int_check_installer_root (guestfs_h *g, struct inspect_fs *fs)
|
||||
{
|
||||
CLEANUP_FREE_STRING_LIST char **paths = NULL;
|
||||
|
||||
/* The presence of certain files indicates a live CD.
|
||||
*
|
||||
* XXX Fedora netinst contains a ~120MB squashfs called
|
||||
* /images/install.img. However this is not a live CD (unlike the
|
||||
* Fedora live CDs which contain the same, but larger file). We
|
||||
* need to unpack this and look inside to tell the difference.
|
||||
*/
|
||||
if (guestfs_is_file (g, "/casper/filesystem.squashfs") > 0 ||
|
||||
guestfs_is_file (g, "/live/filesystem.squashfs") > 0 ||
|
||||
guestfs_is_file (g, "/mfsroot.gz") > 0)
|
||||
fs->is_live_disk = 1;
|
||||
|
||||
/* Debian/Ubuntu. */
|
||||
if (guestfs_is_file (g, "/.disk/info") > 0) {
|
||||
if (check_debian_installer_root (g, fs) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Fedora CDs and DVD (not netinst). */
|
||||
else if (guestfs_is_file (g, "/.treeinfo") > 0) {
|
||||
if (check_fedora_installer_root (g, fs) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* FreeDOS install CD. */
|
||||
else if (guestfs_is_file (g, "/freedos/freedos.ico") > 0 &&
|
||||
guestfs_is_file (g, "/setup.bat") > 0) {
|
||||
fs->type = OS_TYPE_DOS;
|
||||
fs->distro = OS_DISTRO_FREEDOS;
|
||||
fs->arch = safe_strdup (g, "i386");
|
||||
}
|
||||
|
||||
/* Linux with /isolinux/isolinux.cfg (note that non-Linux can use
|
||||
* ISOLINUX too, eg. FreeDOS).
|
||||
*/
|
||||
else if (guestfs_is_file (g, "/isolinux/isolinux.cfg") > 0) {
|
||||
if (check_isolinux_installer_root (g, fs) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* FreeBSD with /boot/loader.rc. */
|
||||
else if (guestfs_is_file (g, "/boot/loader.rc") > 0) {
|
||||
fs->type = OS_TYPE_FREEBSD;
|
||||
}
|
||||
|
||||
/* Windows 2003 64 bit */
|
||||
else if (guestfs_is_file (g, "/amd64/txtsetup.sif") > 0) {
|
||||
fs->arch = safe_strdup (g, "x86_64");
|
||||
if (check_w2k3_installer_root (g, fs, "/amd64/txtsetup.sif") == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Windows 2003 32 bit */
|
||||
else if (guestfs_is_file (g, "/i386/txtsetup.sif") > 0) {
|
||||
fs->arch = safe_strdup (g, "i386");
|
||||
if (check_w2k3_installer_root (g, fs, "/i386/txtsetup.sif") == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Linux with /{i586,x86_64,etc}/product.id (typically found in Mandriva
|
||||
* and Mageia). Usually there should be just one around, so we use the
|
||||
* first one found.
|
||||
*/
|
||||
paths = guestfs_glob_expand (g, "/*/product.id");
|
||||
if (paths == NULL)
|
||||
return -1;
|
||||
if (paths[0] != NULL) {
|
||||
if (check_product_id_installer_root (g, fs, paths[0]) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This is called for whole block devices. See if the device is an
|
||||
* ISO and we are able to read the ISO info from it. In that case,
|
||||
* try using libosinfo to map from the volume ID and other strings
|
||||
* directly to the operating system type.
|
||||
*/
|
||||
int
|
||||
guestfs_int_check_installer_iso (guestfs_h *g, struct inspect_fs *fs,
|
||||
const char *device)
|
||||
{
|
||||
CLEANUP_FREE_ISOINFO struct guestfs_isoinfo *isoinfo = NULL;
|
||||
const struct osinfo *osinfo;
|
||||
int r;
|
||||
|
||||
guestfs_push_error_handler (g, NULL, NULL);
|
||||
isoinfo = guestfs_isoinfo_device (g, device);
|
||||
guestfs_pop_error_handler (g);
|
||||
if (!isoinfo)
|
||||
return 0;
|
||||
|
||||
r = guestfs_int_osinfo_map (g, isoinfo, &osinfo);
|
||||
if (r == -1) /* Fatal error. */
|
||||
return -1;
|
||||
if (r == 0) /* Could not locate any matching ISO. */
|
||||
return 0;
|
||||
|
||||
/* Otherwise we matched an ISO, so fill in the fs fields. */
|
||||
fs->mountable = safe_strdup (g, device);
|
||||
fs->role = OS_ROLE_ROOT;
|
||||
if (osinfo->is_installer)
|
||||
fs->format = OS_FORMAT_INSTALLER;
|
||||
fs->type = osinfo->type;
|
||||
fs->distro = osinfo->distro;
|
||||
fs->product_name =
|
||||
osinfo->product_name ? safe_strdup (g, osinfo->product_name) : NULL;
|
||||
guestfs_int_version_from_values (&fs->version, osinfo->major_version,
|
||||
osinfo->minor_version, 0);
|
||||
fs->arch = osinfo->arch ? safe_strdup (g, osinfo->arch) : NULL;
|
||||
fs->is_live_disk = osinfo->is_live_disk;
|
||||
|
||||
guestfs_int_check_package_format (g, fs);
|
||||
guestfs_int_check_package_management (g, fs);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -87,22 +87,6 @@ guestfs_int_check_for_filesystem_on (guestfs_h *g, const char *mountable)
|
||||
}
|
||||
}
|
||||
|
||||
if (whole_device) {
|
||||
extend_fses (g);
|
||||
fs = &g->fses[g->nr_fses-1];
|
||||
|
||||
r = guestfs_int_check_installer_iso (g, fs, m->im_device);
|
||||
if (r == -1) { /* Fatal error. */
|
||||
g->nr_fses--;
|
||||
return -1;
|
||||
}
|
||||
if (r > 0) /* Found something. */
|
||||
return 0;
|
||||
|
||||
/* Didn't find anything. Fall through ... */
|
||||
g->nr_fses--;
|
||||
}
|
||||
|
||||
/* Try mounting the device. As above, ignore errors. */
|
||||
guestfs_push_error_handler (g, NULL, NULL);
|
||||
if (vfs_type && STREQ (vfs_type, "ufs")) { /* Hack for the *BSDs. */
|
||||
@@ -290,30 +274,6 @@ check_filesystem (guestfs_h *g, const char *mountable,
|
||||
*/
|
||||
fs->arch = safe_strdup (g, "i386");
|
||||
}
|
||||
/* Install CD/disk?
|
||||
*
|
||||
* Note that we checked (above) for an install ISO, but there are
|
||||
* other types of install image (eg. USB keys) which that check
|
||||
* wouldn't have picked up.
|
||||
*
|
||||
* Skip these checks if it's not a whole device (eg. CD) or the
|
||||
* first partition (eg. bootable USB key).
|
||||
*/
|
||||
else if ((whole_device || (partnum == 1 && nr_partitions == 1)) &&
|
||||
(guestfs_is_file (g, "/isolinux/isolinux.cfg") > 0 ||
|
||||
guestfs_is_dir (g, "/EFI/BOOT") > 0 ||
|
||||
guestfs_is_file (g, "/images/install.img") > 0 ||
|
||||
guestfs_is_dir (g, "/.disk") > 0 ||
|
||||
guestfs_is_file (g, "/.discinfo") > 0 ||
|
||||
guestfs_is_file (g, "/i386/txtsetup.sif") > 0 ||
|
||||
guestfs_is_file (g, "/amd64/txtsetup.sif") > 0 ||
|
||||
guestfs_is_file (g, "/freedos/freedos.ico") > 0 ||
|
||||
guestfs_is_file (g, "/boot/loader.rc") > 0)) {
|
||||
fs->role = OS_ROLE_ROOT;
|
||||
fs->format = OS_FORMAT_INSTALLER;
|
||||
if (guestfs_int_check_installer_root (g, fs) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* The above code should have set fs->type and fs->distro fields, so
|
||||
* we can now guess the package management system.
|
||||
|
||||
655
lib/osinfo.c
655
lib/osinfo.c
@@ -1,655 +0,0 @@
|
||||
/* libguestfs
|
||||
* Copyright (C) 2012 Red Hat Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/* Read libosinfo XML files to parse out just the
|
||||
* os/media/iso/system-id and os/media/iso/volume-id fields, which we
|
||||
* can then use to map install media to operating systems.
|
||||
*
|
||||
* Note some assumptions here:
|
||||
*
|
||||
* (1) Ignore the libosinfo library itself, since we don't care
|
||||
* for GObject nonsense. The XML database contains all we need.
|
||||
*
|
||||
* (2) Ignore os/upgrades and os/derives-from fields. This is
|
||||
* safe(-ish) since the media identifiers always change for every
|
||||
* release of an OS. We can easily add support for this if it becomes
|
||||
* necessary.
|
||||
*
|
||||
* (3) We have to do some translation of the distro names and versions
|
||||
* stored in the libosinfo files and the standard names returned by
|
||||
* libguestfs.
|
||||
*
|
||||
* (4) Media detection is only part of the story. We may still need
|
||||
* to inspect inside the image.
|
||||
*
|
||||
* (5) We only read the XML database files (at most) once per process,
|
||||
* and keep them cached. They are only read at all if someone tries
|
||||
* to inspect a CD/DVD/ISO.
|
||||
*
|
||||
* XXX Currently the database is not freed when the program exits /
|
||||
* library is unloaded, although we should probably do that.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <assert.h>
|
||||
#include <sys/types.h>
|
||||
#include <libintl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <libxml/parser.h>
|
||||
#include <libxml/xpath.h>
|
||||
|
||||
#include "ignore-value.h"
|
||||
#include "glthread/lock.h"
|
||||
#include "c-ctype.h"
|
||||
|
||||
#include "guestfs.h"
|
||||
#include "guestfs-internal.h"
|
||||
|
||||
gl_lock_define_initialized (static, osinfo_db_lock);
|
||||
static ssize_t osinfo_db_size = 0; /* 0 = unread, -1 = error, >= 1 = #records */
|
||||
static struct osinfo *osinfo_db = NULL;
|
||||
|
||||
static int read_osinfo_db (guestfs_h *g);
|
||||
static void free_osinfo_db_entry (struct osinfo *);
|
||||
|
||||
#define XMLSTREQ(a,b) (xmlStrEqual((a),(b)) == 1)
|
||||
|
||||
/* Given one or more fields from the header of a CD/DVD/ISO, look up
|
||||
* the media in the libosinfo database and return our best guess for
|
||||
* the operating system.
|
||||
*
|
||||
* This returns:
|
||||
* -1 => a fatal error ('error' has been called, caller must not ignore it)
|
||||
* 0 => could not locate the OS
|
||||
* 1 => matching OS found, the osinfo_ret pointer has been filled in
|
||||
*/
|
||||
int
|
||||
guestfs_int_osinfo_map (guestfs_h *g, const struct guestfs_isoinfo *isoinfo,
|
||||
const struct osinfo **osinfo_ret)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
/* We only need to lock the database when reading it for the first time. */
|
||||
gl_lock_lock (osinfo_db_lock);
|
||||
if (osinfo_db_size == 0) {
|
||||
if (read_osinfo_db (g) == -1) {
|
||||
gl_lock_unlock (osinfo_db_lock);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
gl_lock_unlock (osinfo_db_lock);
|
||||
|
||||
if (osinfo_db_size <= 0)
|
||||
return 0;
|
||||
|
||||
/* Look in the database to see if we can find a match. */
|
||||
for (i = 0; i < (size_t) osinfo_db_size; ++i) {
|
||||
if (osinfo_db[i].re_system_id) {
|
||||
if (!isoinfo->iso_system_id ||
|
||||
!match (g, isoinfo->iso_system_id, osinfo_db[i].re_system_id))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (osinfo_db[i].re_volume_id) {
|
||||
if (!isoinfo->iso_volume_id ||
|
||||
!match (g, isoinfo->iso_volume_id, osinfo_db[i].re_volume_id))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (osinfo_db[i].re_publisher_id) {
|
||||
if (!isoinfo->iso_publisher_id ||
|
||||
!match (g, isoinfo->iso_publisher_id, osinfo_db[i].re_publisher_id))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (osinfo_db[i].re_application_id) {
|
||||
if (!isoinfo->iso_application_id ||
|
||||
!match (g, isoinfo->iso_application_id, osinfo_db[i].re_application_id))
|
||||
continue;
|
||||
}
|
||||
|
||||
debug (g, "osinfo: mapped disk to database entry %zu", i);
|
||||
|
||||
if (osinfo_ret)
|
||||
*osinfo_ret = &osinfo_db[i];
|
||||
return 1;
|
||||
}
|
||||
|
||||
debug (g, "osinfo: no mapping found");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read the libosinfo XML database files. The lock is held while
|
||||
* this is called.
|
||||
*
|
||||
* Returns:
|
||||
* -1 => a fatal error ('error' has been called)
|
||||
* 0 => OK
|
||||
*
|
||||
* Note that failure to find or parse the XML files is *not* a fatal
|
||||
* error, since we should fall back silently if these are not
|
||||
* available. Although we'll emit some debug if this happens.
|
||||
*
|
||||
* Try to use the shared osinfo database layout (and location) first:
|
||||
* https://gitlab.com/libosinfo/libosinfo/blob/master/docs/database-layout.txt
|
||||
*/
|
||||
static int read_osinfo_db_xml (guestfs_h *g, const char *filename);
|
||||
|
||||
static int read_osinfo_db_flat (guestfs_h *g, const char *directory);
|
||||
static int read_osinfo_db_three_levels (guestfs_h *g, const char *directory);
|
||||
static int read_osinfo_db_directory (guestfs_h *g, const char *directory);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static int
|
||||
read_osinfo_db_flat (guestfs_h *g, const char *directory)
|
||||
{
|
||||
debug (g, "osinfo: loading flat database from %s", directory);
|
||||
|
||||
return read_osinfo_db_directory (g, directory);
|
||||
}
|
||||
|
||||
static int
|
||||
read_osinfo_db_three_levels (guestfs_h *g, const char *directory)
|
||||
{
|
||||
DIR *dir;
|
||||
int r;
|
||||
|
||||
dir = opendir (directory);
|
||||
if (!dir) {
|
||||
debug (g, "osinfo: %s: %s", directory, strerror (errno));
|
||||
return 0; /* This is not an error: RHBZ#948324. */
|
||||
}
|
||||
|
||||
debug (g, "osinfo: loading 3-level-directories database from %s", directory);
|
||||
|
||||
for (;;) {
|
||||
struct dirent *d;
|
||||
CLEANUP_FREE char *pathname = NULL;
|
||||
struct stat sb;
|
||||
|
||||
errno = 0;
|
||||
d = readdir (dir);
|
||||
if (!d) break;
|
||||
|
||||
pathname = safe_asprintf (g, "%s/%s", directory, d->d_name);
|
||||
|
||||
/* Iterate only on directories. */
|
||||
if (stat (pathname, &sb) == 0 && S_ISDIR (sb.st_mode)) {
|
||||
r = read_osinfo_db_directory (g, pathname);
|
||||
if (r == -1)
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for failure in readdir. */
|
||||
if (errno != 0) {
|
||||
perrorf (g, "readdir: %s", directory);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Close the directory handle. */
|
||||
r = closedir (dir);
|
||||
dir = NULL;
|
||||
if (r == -1) {
|
||||
perrorf (g, "closedir: %s", directory);
|
||||
goto error;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
error:
|
||||
if (dir)
|
||||
closedir (dir);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
read_osinfo_db_directory (guestfs_h *g, const char *directory)
|
||||
{
|
||||
DIR *dir;
|
||||
int r;
|
||||
|
||||
dir = opendir (directory);
|
||||
if (!dir) {
|
||||
debug (g, "osinfo: %s: %s", directory, strerror (errno));
|
||||
return 0; /* This is not an error: RHBZ#948324. */
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
struct dirent *d;
|
||||
|
||||
errno = 0;
|
||||
d = readdir (dir);
|
||||
if (!d) break;
|
||||
|
||||
if (STRSUFFIX (d->d_name, ".xml")) {
|
||||
CLEANUP_FREE char *pathname = NULL;
|
||||
|
||||
pathname = safe_asprintf (g, "%s/%s", directory, d->d_name);
|
||||
r = read_osinfo_db_xml (g, pathname);
|
||||
if (r == -1)
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for failure in readdir. */
|
||||
if (errno != 0) {
|
||||
perrorf (g, "readdir: %s", directory);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Close the directory handle. */
|
||||
r = closedir (dir);
|
||||
dir = NULL;
|
||||
if (r == -1) {
|
||||
perrorf (g, "closedir: %s", directory);
|
||||
goto error;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
error:
|
||||
if (dir)
|
||||
closedir (dir);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int read_iso_node (guestfs_h *g, xmlNodePtr iso_node, struct osinfo *osinfo);
|
||||
static int read_media_node (guestfs_h *g, xmlXPathContextPtr xpathCtx, xmlNodePtr media_node, struct osinfo *osinfo);
|
||||
static int read_os_node (guestfs_h *g, xmlXPathContextPtr xpathCtx, xmlNodePtr os_node, struct osinfo *osinfo);
|
||||
|
||||
/* Read a single XML file from pathname (which is a full path).
|
||||
* Only memory allocation failures are fatal errors here.
|
||||
*/
|
||||
static int
|
||||
read_osinfo_db_xml (guestfs_h *g, const char *pathname)
|
||||
{
|
||||
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;
|
||||
|
||||
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 installer %s product %s type %d distro %d version %d.%d",
|
||||
pathname,
|
||||
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->is_installer ? "true" : "false",
|
||||
osinfo->product_name ? osinfo->product_name : "(none)",
|
||||
(int) osinfo->type, (int) osinfo->distro,
|
||||
osinfo->major_version, osinfo->minor_version);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int compile_re (guestfs_h *g, xmlNodePtr child, pcre **re);
|
||||
|
||||
/* Read the regular expressions under the <iso> node. libosinfo
|
||||
* itself uses the glib function 'g_regex_match_simple'. That appears
|
||||
* to implement PCRE, however I have not checked in detail.
|
||||
*/
|
||||
static int
|
||||
read_iso_node (guestfs_h *g, xmlNodePtr iso_node, struct osinfo *osinfo)
|
||||
{
|
||||
xmlNodePtr child;
|
||||
|
||||
for (child = iso_node->children; child; child = child->next) {
|
||||
if (STREQ ((const char *) child->name, "system-id")) {
|
||||
if (compile_re (g, child, &osinfo->re_system_id) == -1)
|
||||
return -1;
|
||||
}
|
||||
else if (STREQ ((const char *) child->name, "volume-id")) {
|
||||
if (compile_re (g, child, &osinfo->re_volume_id) == -1)
|
||||
return -1;
|
||||
}
|
||||
else if (STREQ ((const char *) child->name, "publisher-id")) {
|
||||
if (compile_re (g, child, &osinfo->re_publisher_id) == -1)
|
||||
return -1;
|
||||
}
|
||||
else if (STREQ ((const char *) child->name, "application-id")) {
|
||||
if (compile_re (g, child, &osinfo->re_application_id) == -1)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
compile_re (guestfs_h *g, xmlNodePtr node, pcre **re)
|
||||
{
|
||||
const char *err;
|
||||
int offset;
|
||||
CLEANUP_FREE char *content = (char *) xmlNodeGetContent (node);
|
||||
|
||||
if (content) {
|
||||
*re = pcre_compile (content, 0, &err, &offset, NULL);
|
||||
if (*re == NULL)
|
||||
debug (g, "osinfo: could not parse regular expression '%s': %s (ignored)",
|
||||
content, err);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read the attributes of the <media/> node. */
|
||||
static int
|
||||
read_media_node (guestfs_h *g, xmlXPathContextPtr xpathCtx,
|
||||
xmlNodePtr media_node, struct osinfo *osinfo)
|
||||
{
|
||||
osinfo->arch = (char *) xmlGetProp (media_node, BAD_CAST "arch");
|
||||
|
||||
osinfo->is_live_disk = 0; /* If no 'live' attr, defaults to false. */
|
||||
{
|
||||
CLEANUP_XMLFREE xmlChar *content = NULL;
|
||||
content = xmlGetProp (media_node, BAD_CAST "live");
|
||||
if (content)
|
||||
osinfo->is_live_disk = XMLSTREQ (content, BAD_CAST "true");
|
||||
}
|
||||
|
||||
osinfo->is_installer = true; /* If no 'installer' attr, defaults to true. */
|
||||
{
|
||||
CLEANUP_XMLFREE xmlChar *content = NULL;
|
||||
content = xmlGetProp (media_node, BAD_CAST "installer");
|
||||
if (content)
|
||||
osinfo->is_installer = XMLSTREQ (content, BAD_CAST "true");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_version (guestfs_h *g, xmlNodePtr node, struct osinfo *osinfo);
|
||||
static int parse_family (guestfs_h *g, xmlNodePtr node, struct osinfo *osinfo);
|
||||
static int parse_distro (guestfs_h *g, xmlNodePtr node, struct osinfo *osinfo);
|
||||
|
||||
/* Read some fields under the <os/> node. */
|
||||
static int
|
||||
read_os_node (guestfs_h *g, xmlXPathContextPtr xpathCtx,
|
||||
xmlNodePtr os_node, struct osinfo *osinfo)
|
||||
{
|
||||
xmlNodePtr child;
|
||||
|
||||
for (child = os_node->children; child; child = child->next) {
|
||||
if (STREQ ((const char *) child->name, "name"))
|
||||
osinfo->product_name = (char *) xmlNodeGetContent (child);
|
||||
else if (STREQ ((const char *) child->name, "version")) {
|
||||
if (parse_version (g, child, osinfo) == -1)
|
||||
return -1;
|
||||
}
|
||||
else if (STREQ ((const char *) child->name, "family")) {
|
||||
if (parse_family (g, child, osinfo) == -1)
|
||||
return -1;
|
||||
}
|
||||
else if (STREQ ((const char *) child->name, "distro")) {
|
||||
if (parse_distro (g, child, osinfo) == -1)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_version (guestfs_h *g, xmlNodePtr node, struct osinfo *osinfo)
|
||||
{
|
||||
CLEANUP_FREE char *content = NULL;
|
||||
|
||||
content = (char *) xmlNodeGetContent (node);
|
||||
/* We parse either "X.Y" or "X" as version strings, so try to parse
|
||||
* only if the first character is a digit.
|
||||
*/
|
||||
if (content && c_isdigit (content[0])) {
|
||||
struct version version;
|
||||
const int res = guestfs_int_version_from_x_y_or_x (g, &version, content);
|
||||
if (res < 0)
|
||||
return -1;
|
||||
else if (res > 0) {
|
||||
osinfo->major_version = version.v_major;
|
||||
osinfo->minor_version = version.v_minor;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_family (guestfs_h *g, xmlNodePtr node, struct osinfo *osinfo)
|
||||
{
|
||||
CLEANUP_FREE char *content = NULL;
|
||||
|
||||
osinfo->type = OS_TYPE_UNKNOWN;
|
||||
|
||||
content = (char *) xmlNodeGetContent (node);
|
||||
if (content) {
|
||||
if (STREQ (content, "linux"))
|
||||
osinfo->type = OS_TYPE_LINUX;
|
||||
else if (STRPREFIX (content, "win"))
|
||||
osinfo->type = OS_TYPE_WINDOWS;
|
||||
else if (STREQ (content, "freebsd"))
|
||||
osinfo->type = OS_TYPE_FREEBSD;
|
||||
else if (STREQ (content, "netbsd"))
|
||||
osinfo->type = OS_TYPE_NETBSD;
|
||||
else if (STREQ (content, "msdos"))
|
||||
osinfo->type = OS_TYPE_DOS;
|
||||
else if (STREQ (content, "openbsd"))
|
||||
osinfo->type = OS_TYPE_OPENBSD;
|
||||
else
|
||||
debug (g, "osinfo: warning: unknown <family> '%s'", content);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_distro (guestfs_h *g, xmlNodePtr node, struct osinfo *osinfo)
|
||||
{
|
||||
CLEANUP_FREE char *content = NULL;
|
||||
|
||||
osinfo->distro = OS_DISTRO_UNKNOWN;
|
||||
|
||||
content = (char *) xmlNodeGetContent (node);
|
||||
if (content) {
|
||||
if (STREQ (content, "altlinux"))
|
||||
osinfo->distro = OS_DISTRO_ALTLINUX;
|
||||
else if (STREQ (content, "centos"))
|
||||
osinfo->distro = OS_DISTRO_CENTOS;
|
||||
else if (STREQ (content, "debian"))
|
||||
osinfo->distro = OS_DISTRO_DEBIAN;
|
||||
else if (STREQ (content, "fedora"))
|
||||
osinfo->distro = OS_DISTRO_FEDORA;
|
||||
else if (STREQ (content, "freebsd"))
|
||||
osinfo->distro = OS_DISTRO_FREEBSD;
|
||||
else if (STREQ (content, "mageia"))
|
||||
osinfo->distro = OS_DISTRO_MAGEIA;
|
||||
else if (STREQ (content, "mandriva"))
|
||||
osinfo->distro = OS_DISTRO_MANDRIVA;
|
||||
else if (STREQ (content, "netbsd"))
|
||||
osinfo->distro = OS_DISTRO_NETBSD;
|
||||
else if (STREQ (content, "openbsd"))
|
||||
osinfo->distro = OS_DISTRO_OPENBSD;
|
||||
else if (STREQ (content, "opensuse"))
|
||||
osinfo->distro = OS_DISTRO_OPENSUSE;
|
||||
else if (STREQ (content, "rhel"))
|
||||
osinfo->distro = OS_DISTRO_RHEL;
|
||||
else if (STREQ (content, "sled") || STREQ (content, "sles"))
|
||||
osinfo->distro = OS_DISTRO_SLES;
|
||||
else if (STREQ (content, "ubuntu"))
|
||||
osinfo->distro = OS_DISTRO_UBUNTU;
|
||||
else if (STRPREFIX (content, "win"))
|
||||
osinfo->distro = OS_DISTRO_WINDOWS;
|
||||
else
|
||||
debug (g, "osinfo: warning: unknown <distro> '%s'", content);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
free_osinfo_db_entry (struct osinfo *osinfo)
|
||||
{
|
||||
free (osinfo->product_name);
|
||||
free (osinfo->arch);
|
||||
|
||||
if (osinfo->re_system_id)
|
||||
pcre_free (osinfo->re_system_id);
|
||||
if (osinfo->re_volume_id)
|
||||
pcre_free (osinfo->re_volume_id);
|
||||
if (osinfo->re_publisher_id)
|
||||
pcre_free (osinfo->re_publisher_id);
|
||||
if (osinfo->re_application_id)
|
||||
pcre_free (osinfo->re_application_id);
|
||||
}
|
||||
Reference in New Issue
Block a user