+sub output_applications_deb
+{
+ local $_;
+ my $root = shift;
+
+ my @applications;
+
+ eval {
+ my ($fh, $filename) = tempfile (UNLINK => 1);
+ my $fddev = "/dev/fd/" . fileno ($fh);
+ $g->download ("/var/lib/dpkg/status", $fddev);
+ close $fh or die "close: $!";
+
+ # Read the file. Each package is separated by a blank line.
+ open FILE, $filename or die "$filename: $!";
+ my ($name, $installed, $version, $release);
+ while (<FILE>) {
+ chomp;
+ if (/^Package: (.*)/) {
+ $name = $1;
+ } elsif (/^Status: .*\binstalled\b/) {
+ $installed = 1;
+ } elsif (/^Version: (.*?)-(.*)/) {
+ $version = $1;
+ $release = $2;
+ } elsif ($_ eq "") {
+ if ($installed &&
+ defined $name && defined $version && defined $release) {
+ push @applications, [ $name, $version, $release ];
+ }
+ $name = undef;
+ $installed = undef;
+ $version = undef;
+ $release = undef;
+ }
+ }
+ close FILE or die "$filename: $!";
+ };
+ if (!$@ && @applications > 0) {
+ @applications = sort { $a->[0] cmp $b->[0] } @applications;
+ $xml->startTag ("applications");
+ foreach (@applications) {
+ $xml->startTag ("application");
+ $xml->dataElement (name => $_->[0]);
+ $xml->dataElement (version => $_->[1]);
+ $xml->dataElement (release => $_->[2]);
+ $xml->endTag ("application");
+ }
+ $xml->endTag ("applications");
+ }
+}
+
+# The reverse of device name translation, see
+# BLOCK DEVICE NAMING in guestfs(3).
+sub canonicalize
+{
+ local $_ = shift;
+
+ if (m{^/dev/[hv]d([a-z]\d)$}) {
+ return "/dev/sd$1";
+ }
+ $_;
+}
+
+=head1 USING XPATH
+
+You can use the XPath query language, and/or the xpath tool, in order
+to select parts of the XML.
+
+For example:
+
+ $ virt-inspector Guest | xpath //filesystems
+ Found 1 nodes:
+ -- NODE --
+ <filesystems>
+ <filesystem dev="/dev/vg_f13x64/lv_root">
+ <type>ext4</type>
+ [etc]
+
+ $ virt-inspector Guest | \
+ xpath "string(//filesystem[@dev='/dev/sda1']/type)"
+ Query didn't return a nodeset. Value: ext4
+