virt-df: Turn errors into warnings when listing all domains.
[libguestfs.git] / tools / virt-tar
1 #!/usr/bin/perl -w
2 # virt-tar
3 # Copyright (C) 2009 Red Hat Inc.
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
19 use warnings;
20 use strict;
21
22 use Sys::Guestfs;
23 use Sys::Guestfs::Lib qw(open_guest get_partitions resolve_windows_path
24   inspect_all_partitions inspect_partition
25   inspect_operating_systems mount_operating_system);
26 use Pod::Usage;
27 use Getopt::Long;
28 use File::Temp qw/tempfile/;
29 use Locale::TextDomain 'libguestfs';
30
31 =encoding utf8
32
33 =head1 NAME
34
35 virt-tar - Extract or upload files to a virtual machine
36
37 =head1 SYNOPSIS
38
39  virt-tar [--options] -x domname directory tarball
40
41  virt-tar [--options] -u domname tarball directory
42
43  virt-tar [--options] disk.img [disk.img ...] -x directory tarball
44
45  virt-tar [--options] disk.img [disk.img ...] -u tarball directory
46
47 =head1 EXAMPLES
48
49 Download C</home> from the VM into a local tarball:
50
51  virt-tar -x domname /home home.tar
52
53  virt-tar -zx domname /home home.tar.gz
54
55 Upload a local tarball and unpack it inside C</tmp> in the VM:
56
57  virt-tar -u domname uploadstuff.tar /tmp
58
59  virt-tar -zu domname uploadstuff.tar.gz /tmp
60
61 =head1 WARNING
62
63 You must I<not> use C<virt-tar> with the C<-u> option (upload) on live
64 virtual machines.  If you do this, you risk disk corruption in the VM.
65 C<virt-tar> tries to stop you from doing this, but doesn't catch all
66 cases.
67
68 You can use C<-x> (extract) on live virtual machines, but you might
69 get inconsistent results or errors if there is filesystem activity
70 inside the VM.  If the live VM is synched and quiescent, then
71 C<virt-tar> will usually work, but the only way to guarantee
72 consistent results is if the virtual machine is shut down.
73
74 =head1 DESCRIPTION
75
76 C<virt-tar> is a general purpose archive tool for downloading and
77 uploading parts of a guest filesystem.  There are many possibilities:
78 making backups, uploading data files, snooping on guest activity,
79 fixing or customizing guests, etc.
80
81 If you want to just view a single file, use L<virt-cat(1)>.  If you
82 just want to edit a single file, use L<virt-edit(1)>.  For more
83 complex cases you should look at the L<guestfish(1)> tool.
84
85 There are two modes of operation: C<-x> (eXtract) downloads a
86 directory and its contents (recursively) from the virtual machine into
87 a local tarball.  C<-u> uploads from a local tarball, unpacking it
88 into a directory inside the virtual machine.  You cannot use these two
89 options together.
90
91 In addition, you may need to use the C<-z> (gZip) option to enable
92 compression.  When uploading, you have to specify C<-z> if the upload
93 file is compressed because virt-tar won't detect this on its own.
94
95 C<virt-tar> can only handle tar (optionally gzipped) format tarballs.
96 For example it cannot do PKZip files or bzip2 compression.  If you
97 want that then you'll have to rebuild the tarballs yourself.  (This is
98 a limitation of the L<libguestfs(3)> API).
99
100 =head1 OPTIONS
101
102 =over 4
103
104 =cut
105
106 my $help;
107
108 =item B<--help>
109
110 Display brief help.
111
112 =cut
113
114 my $version;
115
116 =item B<--version>
117
118 Display version number and exit.
119
120 =cut
121
122 my $uri;
123
124 =item B<--connect URI> | B<-c URI>
125
126 If using libvirt, connect to the given I<URI>.  If omitted, then we
127 connect to the default libvirt hypervisor.
128
129 If you specify guest block devices directly, then libvirt is not used
130 at all.
131
132 =cut
133
134 my $mode;
135
136 =item B<-x> | B<--extract> | B<--download>
137
138 =item B<-u> | B<--upload>
139
140 Use C<-x> to extract (download) a directory from a virtual machine
141 to a local tarball.
142
143 Use C<-u> to upload and unpack from a local tarball into a virtual
144 machine.  Please read the L</WARNING> section above before using this
145 option.
146
147 You must specify exactly one of these options.
148
149 =cut
150
151 my $gzip;
152
153 =item B<-z> | B<--gzip>
154
155 Specify that the input or output tarball is gzip-compressed.
156
157 =back
158
159 =cut
160
161 sub set_mode_x
162 {
163     die __"virt-tar: extract/upload mode specified twice on the command line\n"
164         if $mode;
165     $mode = "x";
166 }
167
168 sub set_mode_u
169 {
170     die __"virt-tar: extract/upload mode specified twice on the command line\n"
171         if $mode;
172     $mode = "u";
173 }
174
175 Getopt::Long::Configure ("bundling");
176 GetOptions ("help|?" => \$help,
177             "version" => \$version,
178             "connect|c=s" => \$uri,
179             "extract|download|x" => \&set_mode_x,
180             "upload|u" => \&set_mode_u,
181             "gzip|z" => \$gzip,
182     ) or pod2usage (2);
183 pod2usage (1) if $help;
184 if ($version) {
185     my $g = Sys::Guestfs->new ();
186     my %h = $g->version ();
187     print "$h{major}.$h{minor}.$h{release}$h{extra}\n";
188     exit
189 }
190
191 pod2usage (__"virt-tar: no image, VM names, directory or filename given")
192     if @ARGV <= 2;
193
194 die __"virt-tar: either -x or -u must be specified on the command line\n"
195     unless $mode;
196
197 # Note: 'pop' reads arguments right to left.
198 my ($tarball, $directory);
199 if ($mode eq "x") {
200     $tarball = pop @ARGV;
201     $directory = pop @ARGV;
202 } else { # $mode eq "u"
203     $directory = pop @ARGV;
204     $tarball = pop @ARGV;
205     die __"virt-tar: $tarball: file not found\n" unless -f $tarball;
206 }
207 die __"virt-tar: $directory: directory name must start with '/' character\n"
208     unless substr ($directory, 0, 1) eq "/";
209
210 my @args = (\@ARGV);
211 push @args, address => $uri if $uri;
212 push @args, rw => 1 if $mode eq "u";
213
214 my $g = open_guest (@args);
215 $g->launch ();
216
217 # List of possible filesystems.
218 my @partitions = get_partitions ($g);
219
220 # Now query each one to build up a picture of what's in it.
221 my %fses =
222     inspect_all_partitions ($g, \@partitions,
223       use_windows_registry => 0);
224
225 my $oses = inspect_operating_systems ($g, \%fses);
226
227 my @roots = keys %$oses;
228 die __"no root device found in this operating system image\n" if @roots == 0;
229 die __"multiboot operating systems are not supported by virt-tar\n" if @roots > 1;
230 my $root_dev = $roots[0];
231
232 my $os = $oses->{$root_dev};
233 mount_operating_system ($g, $os, $mode eq "u" ? 0 : 1);
234
235 # Do the tar command.
236 if ($mode eq "x") {
237     if ($gzip) {
238         $g->tgz_out ($directory, $tarball);
239     } else {
240         $g->tar_out ($directory, $tarball);
241     }
242 } else { # mode eq "u"
243     if ($gzip) {
244         $g->tgz_in ($tarball, $directory);
245     } else {
246         $g->tar_in ($tarball, $directory);
247     }
248 }
249
250 $g->sync ();
251 $g->umount_all ();
252
253 undef $g;
254
255 exit 0;
256
257 =head1 SEE ALSO
258
259 L<guestfs(3)>,
260 L<guestfish(1)>,
261 L<virt-cat(1)>,
262 L<virt-edit(1)>,
263 L<Sys::Guestfs(3)>,
264 L<Sys::Guestfs::Lib(3)>,
265 L<Sys::Virt(3)>,
266 L<http://libguestfs.org/>.
267
268 =head1 AUTHOR
269
270 Richard W.M. Jones L<http://et.redhat.com/~rjones/>
271
272 =head1 COPYRIGHT
273
274 Copyright (C) 2009 Red Hat Inc.
275
276 This program is free software; you can redistribute it and/or modify
277 it under the terms of the GNU General Public License as published by
278 the Free Software Foundation; either version 2 of the License, or
279 (at your option) any later version.
280
281 This program is distributed in the hope that it will be useful,
282 but WITHOUT ANY WARRANTY; without even the implied warranty of
283 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
284 GNU General Public License for more details.
285
286 You should have received a copy of the GNU General Public License
287 along with this program; if not, write to the Free Software
288 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.