Imported Upstream version 3.1.0
[debian/amanda] / application-src / amraw.pl
1 #!@PERL@ 
2 # Copyright (c) 2009 Zmanda, Inc.  All Rights Reserved.
3 #
4 # This program is free software; you can redistribute it and/or modify it
5 # under the terms of the GNU General Public License version 2 as published
6 # by the Free Software Foundation.
7 #
8 # This program is distributed in the hope that it will be useful, but
9 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
11 # for more details.
12 #
13 # You should have received a copy of the GNU General Public License along
14 # with this program; if not, write to the Free Software Foundation, Inc.,
15 # 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 #
17 # Contact information: Zmanda Inc., 465 S. Mathilda Ave., Suite 300
18 # Sunnyvale, CA 94086, USA, or: http://www.zmanda.com
19
20 use lib '@amperldir@';
21 use strict;
22 use Getopt::Long;
23
24 package Amanda::Application::Amraw;
25 use base qw(Amanda::Application);
26 use IPC::Open3;
27 use Sys::Hostname;
28 use Symbol;
29 use IO::Handle;
30 use Amanda::Constants;
31 use Amanda::Debug qw( :logging );
32 use Amanda::Util;
33
34 sub new {
35     my $class = shift;
36     my ($config, $host, $disk, $device, $level, $index, $message, $collection, $record, $calcsize, $include_list, $exclude_list, $directory) = @_;
37     my $self = $class->SUPER::new($config);
38
39     $self->{config}           = $config;
40     $self->{host}             = $host;
41     if (defined $disk) {
42         $self->{disk}         = $disk;
43     } else {
44         $self->{disk}         = $device;
45     }
46     if (defined $device) {
47         $self->{device}       = $device;
48     } else {
49         $self->{device}       = $disk;
50     }
51     $self->{level}            = [ @{$level} ];
52     $self->{index}            = $index;
53     $self->{message}          = $message;
54     $self->{collection}       = $collection;
55     $self->{record}           = $record;
56     $self->{calcsize}         = $calcsize;
57     $self->{exclude_list}     = [ @{$exclude_list} ];
58     $self->{include_list}     = [ @{$include_list} ];
59     $self->{directory}        = $directory;
60
61     return $self;
62 }
63
64 sub command_support {
65     my $self = shift;
66
67     print "CONFIG YES\n";
68     print "HOST YES\n";
69     print "DISK YES\n";
70     print "MAX-LEVEL 0\n";
71     print "INDEX-LINE YES\n";
72     print "INDEX-XML NO\n";
73     print "MESSAGE-LINE YES\n";
74     print "MESSAGE-XML NO\n";
75     print "RECORD YES\n";
76     print "COLLECTION NO\n";
77     print "MULTI-ESTIMATE NO\n";
78     print "CALCSIZE NO\n";
79     print "CLIENT-ESTIMATE YES\n";
80 }
81
82 sub command_selfcheck {
83     my $self = shift;
84
85     print "OK " . $self->{disk} . "\n";
86     print "OK " . $self->{device} . "\n";
87
88     if (! -r $self->{device}) {
89         $self->print_to_server("$self->{device} can't be read",
90                                $Amanda::Script_App::ERROR);
91     }
92
93     if ($#{$self->{include_list}} >= 0) {
94         $self->print_to_server("include-list not supported for backup",
95                                $Amanda::Script_App::ERROR);
96     }
97     if ($#{$self->{exclude_list}} >= 0) {
98         $self->print_to_server("exclude-list not supported for backup",
99                                $Amanda::Script_App::ERROR);
100     }
101     if ($self->{directory}) {
102         $self->print_to_server("directory PROPERTY not supported for backup",
103                                $Amanda::Script_App::ERROR);
104     }
105
106     #check statefile
107     #check amdevice
108 }
109
110 sub command_estimate {
111     my $self = shift;
112
113     my $level = $self->{level}[0];
114
115     if ($level != 0) {
116         $self->print_to_server("amraw can only do level 0 backup",
117                                $Amanda::Script_App::ERROR);
118     }
119
120     if ($#{$self->{include_list}} >= 0) {
121         $self->print_to_server("include-list not supported for backup",
122                                $Amanda::Script_App::ERROR);
123     }
124     if ($#{$self->{include_list}} >= 0) {
125         $self->print_to_server("exclude-list not supported for backup",
126                                $Amanda::Script_App::ERROR);
127     }
128     if ($self->{directory}) {
129         $self->print_to_server("directory PROPERTY not supported for backup",
130                                $Amanda::Script_App::ERROR);
131     }
132
133     my $fd = POSIX::open($self->{device}, &POSIX::O_RDONLY);
134     my $size = 0;
135     my $s;
136     my $buffer;
137     while (($s = POSIX::read($fd, $buffer, 32768)) > 0) {
138         $size += $s;
139     }
140     POSIX::close($fd);
141     output_size($level, $size);
142 }
143
144 sub output_size {
145    my($level) = shift;
146    my($size) = shift;
147    if($size == -1) {
148       print "$level -1 -1\n";
149    }
150    else {
151       my($ksize) = int $size / (1024);
152       $ksize=32 if ($ksize<32);
153       print "$level $ksize 1\n";
154    }
155 }
156
157 sub command_backup {
158     my $self = shift;
159
160     my $level = $self->{level}[0];
161     my $mesgout_fd;
162     open($mesgout_fd, '>&=3') ||
163         $self->print_to_server_and_die("Can't open mesgout_fd: $!",
164                                        $Amanda::Script_App::ERROR);
165     $self->{mesgout} = $mesgout_fd;
166
167     if (defined($self->{index})) {
168         $self->{'index_out'} = IO::Handle->new_from_fd(4, 'w');
169         $self->{'index_out'} or confess("Could not open index fd");
170     }
171
172     if ($level != 0) {
173         $self->print_to_server("amraw can only do level 0 backup",
174                                $Amanda::Script_App::ERROR);
175     }
176
177     if ($#{$self->{include_list}} >= 0) {
178         $self->print_to_server("include-list not supported for backup",
179                                $Amanda::Script_App::ERROR);
180     }
181     if ($#{$self->{include_list}} >= 0) {
182         $self->print_to_server("exclude-list not supported for backup",
183                                $Amanda::Script_App::ERROR);
184     }
185     if ($self->{directory}) {
186         $self->print_to_server("directory PROPERTY not supported for backup",
187                                $Amanda::Script_App::ERROR);
188     }
189
190     my $fd = POSIX::open($self->{device}, &POSIX::O_RDONLY);
191     my $size = 0;
192     my $s;
193     my $buffer;
194     my $out = 1;
195     while (($s = POSIX::read($fd, $buffer, 32768)) > 0) {
196         Amanda::Util::full_write($out, $buffer, $s);
197         $size += $s;
198     }
199     POSIX::close($fd);
200     close($out);
201     if (defined($self->{index})) {
202         $self->{'index_out'}->print("/\n");
203         $self->{'index_out'}->close;
204     }
205     if ($size >= 0) {
206         my $ksize = $size / 1024;
207         if ($ksize < 32) {
208             $ksize = 32;
209         }
210         print $mesgout_fd "sendbackup: size $ksize\n";
211         print $mesgout_fd "sendbackup: end\n";
212     }
213
214     exit 0;
215 }
216
217 sub command_restore {
218     my $self = shift;
219     my @cmd = ();
220
221     my $device = $self->{device};
222     if (defined $self->{directory}) {
223         $device = $self->{directory};
224     } else {
225         chdir(Amanda::Util::get_original_cwd());
226     }
227
228     # include-list and exclude-list are ignored, the complete dle is restored.
229
230     $device = "amraw-restored" if !defined $device;
231
232     my $fd = POSIX::open($device, &POSIX::O_CREAT | &POSIX::O_RDWR, 0600 );
233     if ($fd == -1) {
234         $self->print_to_server_and_die("Can't open '$device': $!",
235                                        $Amanda::Script_App::ERROR);
236     }
237     my $size = 0;
238     my $s;
239     my $buffer;
240     my $in = 0;
241     while (($s = POSIX::read($in, $buffer, 32768)) > 0) {
242         Amanda::Util::full_write($fd, $buffer, $s);
243         $size += $s;
244     }
245     POSIX::close($fd);
246     close($in);
247     exit(0);
248 }
249
250 sub command_validate {
251     my $self = shift;
252
253     $self->default_validate();
254 }
255
256 package main;
257
258 sub usage {
259     print <<EOF;
260 Usage: amraw <command> --config=<config> --host=<host> --disk=<disk> --device=<device> --level=<level> --index=<yes|no> --message=<text> --collection=<no> --record=<yes|no> --calcsize.
261 EOF
262     exit(1);
263 }
264
265 my $opt_version;
266 my $opt_config;
267 my $opt_host;
268 my $opt_disk;
269 my $opt_device;
270 my @opt_level;
271 my $opt_index;
272 my $opt_message;
273 my $opt_collection;
274 my $opt_record;
275 my $opt_calcsize;
276 my @opt_include_list;
277 my @opt_exclude_list;
278 my $opt_directory;
279
280 Getopt::Long::Configure(qw{bundling});
281 GetOptions(
282     'version'            => \$opt_version,
283     'config=s'           => \$opt_config,
284     'host=s'             => \$opt_host,
285     'disk=s'             => \$opt_disk,
286     'device=s'           => \$opt_device,
287     'level=s'            => \@opt_level,
288     'index=s'            => \$opt_index,
289     'message=s'          => \$opt_message,
290     'collection=s'       => \$opt_collection,
291     'record'             => \$opt_record,
292     'calcsize'           => \$opt_calcsize,
293     'include-list=s'     => \@opt_include_list,
294     'exclude-list=s'     => \@opt_exclude_list,
295     'directory'          => \$opt_directory,
296 ) or usage();
297
298 if (defined $opt_version) {
299     print "amraw-" . $Amanda::Constants::VERSION , "\n";
300     exit(0);
301 }
302
303 my $application = Amanda::Application::Amraw->new($opt_config, $opt_host, $opt_disk, $opt_device, \@opt_level, $opt_index, $opt_message, $opt_collection, $opt_record, $opt_calcsize, \@opt_include_list, \@opt_exclude_list, $opt_directory);
304
305 $application->do($ARGV[0]);