New tool: virt-list-filesystems
[libguestfs.git] / tools / virt-list-filesystems
diff --git a/tools/virt-list-filesystems b/tools/virt-list-filesystems
new file mode 100755 (executable)
index 0000000..50024aa
--- /dev/null
@@ -0,0 +1,223 @@
+#!/usr/bin/perl -w
+# virt-list-filesystems
+# Copyright (C) 2009 Red Hat Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+use warnings;
+use strict;
+
+use Sys::Guestfs;
+use Sys::Guestfs::Lib qw(open_guest get_partitions);
+use Pod::Usage;
+use Getopt::Long;
+use Locale::TextDomain 'libguestfs';
+use File::Temp qw/tempdir/;
+
+=encoding utf8
+
+=head1 NAME
+
+virt-list-filesystems - List filesystems in a virtual machine or disk image
+
+=head1 SYNOPSIS
+
+ virt-list-filesystems [--options] domname
+
+ virt-list-filesystems [--options] disk.img [disk.img ...]
+
+=head1 DESCRIPTION
+
+C<virt-list-filesystems> is a command line tool to list
+the filesystems that are contained in a virtual machine or
+disk image.
+
+C<virt-list-filesystems> is just a simple wrapper around
+L<libguestfs(3)> functionality.  For more complex cases you should
+look at the L<guestfish(1)> tool.
+
+=head1 OPTIONS
+
+=over 4
+
+=cut
+
+my $help;
+
+=item B<--help>
+
+Display brief help.
+
+=cut
+
+my $version;
+
+=item B<--version>
+
+Display version number and exit.
+
+=cut
+
+my $uri;
+
+=item B<--connect URI> | B<-c URI>
+
+If using libvirt, connect to the given I<URI>.  If omitted, then we
+connect to the default libvirt hypervisor.
+
+If you specify guest block devices directly, then libvirt is not used
+at all.
+
+=cut
+
+my $long;
+
+=item B<-l> | B<--long>
+
+With this option, C<virt-list-filesystems> displays the type of
+each filesystem too (where "type" means C<ext3>, C<xfs> etc.)
+
+=cut
+
+my $all;
+
+=item B<-a> | B<--all>
+
+Normally we only show mountable filesystems.  If this option
+is given then swap devices are shown too.
+
+=back
+
+=cut
+
+# Configure bundling, otherwise '-al' is treated as '--all'.
+Getopt::Long::Configure ("bundling");
+
+GetOptions ("help|?" => \$help,
+            "version" => \$version,
+            "connect|c=s" => \$uri,
+            "long|l" => \$long,
+            "all|a" => \$all,
+    ) or pod2usage (2);
+pod2usage (1) if $help;
+if ($version) {
+    my $g = Sys::Guestfs->new ();
+    my %h = $g->version ();
+    print "$h{major}.$h{minor}.$h{release}$h{extra}\n";
+    exit
+}
+
+pod2usage (__"virt-list-filesystems: no image or VM name given")
+    if @ARGV <= 0;
+
+my $g;
+if ($uri) {
+    $g = open_guest (\@ARGV, address => $uri);
+} else {
+    $g = open_guest (\@ARGV);
+}
+
+$g->launch ();
+
+# List of partitions, LVs etc.
+my @partitions = get_partitions ($g);
+
+my @fses;
+my @not_mountable;
+my $dev;
+
+# Try and mount each one, to see what's mountable.
+foreach $dev (@partitions) {
+    eval { $g->mount_ro ($dev, "/"); };
+    my $mountable = $@ ? 0 : 1;
+    $g->umount_all ();
+    if ($mountable) {
+       push @fses, $dev;
+    } else {
+       push @not_mountable, $dev;
+    }
+}
+
+foreach $dev (@fses) {
+    print canonicalize($dev);
+    if ($long) {
+       my $fstype;
+       eval { $fstype = $g->vfs_type ($dev); };
+       if ($fstype) {
+           print " $fstype";
+       } else {
+           print " unknown";
+       }
+    }
+    print "\n";
+}
+
+# If asked, look in the not_mountable list for potential swap devices.
+if ($all) {
+    foreach $dev (@not_mountable) {
+       my $file;
+       eval { $file = $g->file ($dev); };
+       if ($file && $file =~ /\bswap\b/) {
+           print canonicalize($dev);
+           print " swap" if $long;
+           print "\n"
+       }
+    }
+}
+
+# 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 SEE ALSO
+
+L<guestfs(3)>,
+L<guestfish(1)>,
+L<virt-cat(1)>,
+L<virt-tar(1)>,
+L<Sys::Guestfs(3)>,
+L<Sys::Guestfs::Lib(3)>,
+L<Sys::Virt(3)>,
+L<http://libguestfs.org/>.
+
+=head1 AUTHOR
+
+Richard W.M. Jones L<http://et.redhat.com/~rjones/>
+
+=head1 COPYRIGHT
+
+Copyright (C) 2009 Red Hat Inc.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.