edit: Add -e 'expr' option to non-interactively apply expression to the file.
[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 __x("virt-tar: {tarball}: file not found\n",
206             tarball => $tarball) unless -f $tarball;
207 }
208 die __x("virt-tar: {dir}: directory name must start with '/' character\n",
209         dir => $directory)
210     unless substr ($directory, 0, 1) eq "/";
211
212 my @args = (\@ARGV);
213 push @args, address => $uri if $uri;
214 push @args, rw => 1 if $mode eq "u";
215
216 my $g = open_guest (@args);
217 $g->launch ();
218
219 # List of possible filesystems.
220 my @partitions = get_partitions ($g);
221
222 # Now query each one to build up a picture of what's in it.
223 my %fses =
224     inspect_all_partitions ($g, \@partitions,
225       use_windows_registry => 0);
226
227 my $oses = inspect_operating_systems ($g, \%fses);
228
229 my @roots = keys %$oses;
230 die __"multiboot operating systems are not supported by virt-tar\n" if @roots > 1;
231 my $root_dev = $roots[0];
232
233 my $os = $oses->{$root_dev};
234 mount_operating_system ($g, $os, $mode eq "u" ? 0 : 1);
235
236 # Do the tar command.
237 if ($mode eq "x") {
238     if ($gzip) {
239         $g->tgz_out ($directory, $tarball);
240     } else {
241         $g->tar_out ($directory, $tarball);
242     }
243 } else { # mode eq "u"
244     if ($gzip) {
245         $g->tgz_in ($tarball, $directory);
246     } else {
247         $g->tar_in ($tarball, $directory);
248     }
249 }
250
251 $g->sync ();
252 $g->umount_all ();
253
254 undef $g;
255
256 exit 0;
257
258 =head1 SEE ALSO
259
260 L<guestfs(3)>,
261 L<guestfish(1)>,
262 L<virt-cat(1)>,
263 L<virt-edit(1)>,
264 L<Sys::Guestfs(3)>,
265 L<Sys::Guestfs::Lib(3)>,
266 L<Sys::Virt(3)>,
267 L<http://libguestfs.org/>.
268
269 =head1 AUTHOR
270
271 Richard W.M. Jones L<http://people.redhat.com/~rjones/>
272
273 =head1 COPYRIGHT
274
275 Copyright (C) 2009 Red Hat Inc.
276
277 This program is free software; you can redistribute it and/or modify
278 it under the terms of the GNU General Public License as published by
279 the Free Software Foundation; either version 2 of the License, or
280 (at your option) any later version.
281
282 This program is distributed in the hope that it will be useful,
283 but WITHOUT ANY WARRANTY; without even the implied warranty of
284 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
285 GNU General Public License for more details.
286
287 You should have received a copy of the GNU General Public License
288 along with this program; if not, write to the Free Software
289 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.