2 # Copyright (c) 2008-2012 Zmanda, Inc. All Rights Reserved.
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
9 # This program is distributed in the hope that it will be useful, but
10 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 # You should have received a copy of the GNU General Public License along
15 # with this program; if not, write to the Free Software Foundation, Inc.,
16 # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 # Contact information: Zmanda Inc., 465 S. Mathilda Ave., Suite 300
19 # Sunnyvale, CA 94086, USA, or: http://www.zmanda.com
21 use lib '@amperldir@';
26 package Amanda::Application::Amsamba;
27 use base qw(Amanda::Application);
36 use Amanda::Constants;
37 use Amanda::Config qw( :init :getconf config_dir_relative );
38 use Amanda::Debug qw( :logging );
40 use Amanda::Util qw( :constants :quoting);
41 use Amanda::MainLoop qw( :GIOCondition );
45 my ($config, $host, $disk, $device, $level, $index, $message, $collection, $record, $calcsize, $gnutar_path, $smbclient_path, $amandapass, $exclude_file, $exclude_list, $exclude_optional, $include_file, $include_list, $include_optional, $recover_mode, $allow_anonymous, $directory) = @_;
46 my $self = $class->SUPER::new($config);
48 if (defined $gnutar_path) {
49 $self->{gnutar} = $gnutar_path;
51 $self->{gnutar} = $Amanda::Constants::GNUTAR;
53 if (defined $smbclient_path) {
54 $self->{smbclient} = $smbclient_path;
56 $self->{smbclient} = $Amanda::Constants::SAMBA_CLIENT;
58 if (defined $amandapass) {
59 $self->{amandapass} = config_dir_relative($amandapass);
61 $self->{amandapass} = "$Amanda::Paths::CONFIG_DIR/amandapass";
64 $self->{config} = $config;
65 $self->{host} = $host;
67 $self->{disk} = $disk;
69 $self->{disk} = $device;
71 if (defined $device) {
72 $self->{device} = $device;
74 $self->{device} = $disk;
76 $self->{level} = [ @{$level} ];
77 $self->{index} = $index;
78 $self->{message} = $message;
79 $self->{collection} = $collection;
80 $self->{record} = $record;
81 $self->{calcsize} = $calcsize;
82 $self->{exclude_file} = [ @{$exclude_file} ];
83 $self->{exclude_list} = [ @{$exclude_list} ];
84 $self->{exclude_optional} = $exclude_optional;
85 $self->{include_file} = [ @{$include_file} ];
86 $self->{include_list} = [ @{$include_list} ];
87 $self->{include_optional} = $include_optional;
88 $self->{recover_mode} = $recover_mode;
89 $self->{allow_anonymous} = $allow_anonymous;
90 $self->{directory} = $directory;
96 # $self->{exclude_file}
97 # $self->{exclude_list}
98 # $self->{include_file}
99 # $self->{include_list}
103 # $self->{include_filename}
104 sub validate_inexclude {
107 if ($#{$self->{exclude_file}} + $#{$self->{exclude_list}} >= -1 &&
108 $#{$self->{include_file}} + $#{$self->{include_list}} >= -1) {
109 $self->print_to_server_and_die("Can't have both include and exclude",
110 $Amanda::Script_App::ERROR);
113 if ($#{$self->{exclude_file}} >= 0) {
114 $self->{exclude} = [ @{$self->{exclude_file}} ];
116 foreach my $file (@{$self->{exclude_list}}) {
117 if (!open(FF, $file)) {
118 if ($self->{action} eq 'check' && !$self->{exclude_optional}) {
119 $self->print_to_server("Open of '$file' failed: $!",
120 $Amanda::Script_App::ERROR);
126 push @{$self->{exclude}}, $_;
131 if ($self->{action} eq "restore" and defined $self->{'include_list'}) {
132 # put all include in a single file $self->{'include_filename'}
133 $self->{'include_filename'} = "$AMANDA_TMPDIR/amsamba.$$.include";
134 open INC_FILE, ">$self->{'include_filename'}";
135 if ($#{$self->{include_file}} >= 0) {
136 print INC_FILE "$self->{include_file}\n";
138 foreach my $file (@{$self->{include_list}}) {
139 if (!open(FF, $file)) {
140 if ($self->{action} eq 'check' && !$self->{include_optional}) {
141 $self->print_to_server("Open of '$file' failed: $!",
142 $Amanda::Script_App::ERROR);
147 if (defined $self->{'subdir'}) {
148 $_ =~ s/^\./$self->{'subdir'}/;
155 # add command line include for amrestore
156 for(my $i=1;defined $ARGV[$i]; $i++) {
157 my $param = $ARGV[$i];
160 if (defined $self->{'subdir'}) {
161 $_ =~ s/^\./$self->{'subdir'}/;
163 print INC_FILE "$_\n";
168 # put all include in $self->{'include'} they will be added on
170 if ($#{$self->{include_file}} >= 0) {
171 $self->{include} = [ @{$self->{include_file}} ];
174 foreach my $file (@{$self->{include_list}}) {
175 if (!open(FF, $file)) {
176 if ($self->{action} eq 'check' && !$self->{include_optional}) {
177 $self->print_to_server("Open of '$file' failed: $!",
178 $Amanda::Script_App::ERROR);
184 if ($self->{action} eq "restore" and
185 defined $self->{'subdir'}) {
186 $_ =~ s/^\./$self->{'subdir'}/;
188 push @{$self->{include}}, $_;
193 # add command line include for amrestore
194 if ($self->{action} eq "restore") {
195 for(my $i=1;defined $ARGV[$i]; $i++) {
196 my $param = $ARGV[$i];
199 if (defined $self->{'subdir'}) {
200 $_ =~ s/^\./$self->{'subdir'}/;
202 push @{$self->{include}}, $1;
209 # $self->{directory} == //host/share/subdir \\host\share\subdir
211 # $self->{device} == //host/share/subdir \\host\share\subdir
213 # $self->{cifshost} = //host \\host
214 # $self->{share} = //host/share \\host\share
215 # $self->{sambashare} = \\host\share \\host\share
216 # $self->{subdir} = subdir subdir
219 my $to_parse = $self->{directory};
220 $to_parse = $self->{device} if !defined $to_parse;;
222 return if !defined $to_parse;
223 if ($to_parse =~ /^\\\\/) {
230 if ($to_parse =~ m,^(\\\\[^\\]+\\[^\\]+)\\(.*)$,) {
234 $self->{share} = $to_parse
236 $self->{sambashare} = $self->{share};
237 $to_parse =~ m,^(\\\\[^\\]+)\\[^\\]+,;
238 $self->{cifshost} = $1;
240 if ($to_parse =~ m,^(//[^/]+/[^/]+)/(.*)$,) {
244 $self->{share} = $to_parse
246 $self->{sambashare} = $self->{share};
247 $self->{sambashare} =~ s,/,\\,g;
248 $to_parse =~ m,^(//[^/]+)/[^/]+,;
249 $self->{cifshost} = $1;
254 # Read $self->{amandapass} file.
256 # $self->{cifshost} == //host/share
257 # $self->{share} == //host/share
259 # $self->{domain} = domain to connect to.
260 # $self->{username} = username (-U)
261 # $self->{password} = password
268 $self->{domain} = undef;
269 $self->{username} = undef;
270 $self->{password} = undef;
272 debug("amandapass: $self->{amandapass}");
273 if (!open($amandapass, $self->{amandapass})) {
274 if ($self->{allow_anonymous}) {
275 $self->{username} = $self->{allow_anonymous};
276 debug("cannot open password file '$self->{amandapass}': $!\n");
277 debug("Using anonymous user: $self->{username}");
280 $self->print_to_server_and_die(
281 "cannot open password file '$self->{amandapass}': $!",
282 $Amanda::Script_App::ERROR);
286 while ($line = <$amandapass>) {
288 next if $line =~ /^#/;
289 my ($diskname, $userpasswd, $domain, $extra) = Amanda::Util::split_quoted_string_friendly($line);
291 debug("Trailling characters ignored in amandapass line");
293 if (defined $diskname &&
295 ($self->{unc}==0 && $diskname =~ m,^(//[^/]+)/\*$, && $1 eq $self->{cifshost}) ||
296 ($self->{unc}==1 && $diskname =~ m,^(\\\\[^\\]+)\\\*$, && $1 eq $self->{cifshost}) ||
297 $diskname eq $self->{share} ||
298 $diskname eq $self->{sambashare})) {
299 if (defined $userpasswd && $userpasswd ne "") {
300 $self->{domain} = $domain if defined $domain && $domain ne "";
301 my ($username, $password) = split('%', $userpasswd, 2);
302 $self->{username} = $username;
303 if ($password =~ /^6G\!dr(.*)/) {
305 $password = MIME::Base64::decode($base64);
307 $self->{password} = $password;
308 $self->{password} = undef if (defined $password && $password eq "");
310 $self->{username} = "guest";
317 if ($self->{allow_anonymous}) {
318 $self->{username} = $self->{allow_anonymous};
319 debug("Cannot find password for share $self->{share} in $self->{amandapass}");
320 debug("Using anonymous user: $self->{username}");
323 $self->print_to_server_and_die(
324 "Cannot find password for share $self->{share} in $self->{amandapass}",
325 $Amanda::Script_App::ERROR);
328 sub command_support {
331 print "CONFIG YES\n";
334 print "MAX-LEVEL 1\n";
335 print "INDEX-LINE YES\n";
336 print "INDEX-XML NO\n";
337 print "MESSAGE-LINE YES\n";
338 print "MESSAGE-XML NO\n";
339 print "RECORD YES\n";
340 print "COLLECTION NO\n";
341 print "MULTI-ESTIMATE NO\n";
342 print "CALCSIZE NO\n";
343 print "CLIENT-ESTIMATE YES\n";
344 print "EXCLUDE-FILE YES\n";
345 print "EXCLUDE-LIST YES\n";
346 print "EXCLUDE-OPTIONAL YES\n";
347 print "INCLUDE-FILE YES\n";
348 print "INCLUDE-LIST YES\n";
349 print "INCLUDE-OPTIONAL YES\n";
350 print "RECOVER-MODE SMB\n";
353 sub command_selfcheck {
356 $self->print_to_server("disk " . quote_string($self->{disk}),
357 $Amanda::Script_App::GOOD);
359 $self->print_to_server("amsamba version " . $Amanda::Constants::VERSION,
360 $Amanda::Script_App::GOOD);
362 if (!defined($self->{smbclient}) || $self->{smbclient} eq "") {
363 $self->print_to_server(
364 "smbclient not set; you must define the SMBCLIENT-PATH property",
365 $Amanda::Script_App::ERROR);
367 elsif (! -e $self->{smbclient}) {
368 $self->print_to_server("$self->{smbclient} doesn't exist",
369 $Amanda::Script_App::ERROR);
371 elsif (! -x $self->{smbclient}) {
372 $self->print_to_server("$self->{smbclient} is not executable",
373 $Amanda::Script_App::ERROR);
375 my @sv = `$self->{smbclient} --version`;
377 $sv[0] =~ /^[^0-9]*(.*)$/;
379 $self->print_to_server("amsamba smbclient-version $sv",
380 $Amanda::Script_App::GOOD);
382 $self->print_to_server(
383 "[Can't get " . $self->{smbclient} . " version]\n",
384 $Amanda::Script_App::ERROR);
388 $self->print_to_server("$self->{smbclient}",
389 $Amanda::Script_App::GOOD);
390 if (!defined $self->{disk} || !defined $self->{device}) {
393 $self->parsesharename();
395 $self->validate_inexclude();
397 print "OK " . $self->{share} . "\n";
398 print "OK " . $self->{device} . "\n";
399 print "OK " . $self->{directory} . "\n" if defined $self->{directory};
401 my ($password_rdr, $password_wtr);
402 if (defined $self->{password}) {
403 # Don't set close-on-exec
405 pipe($password_rdr, $password_wtr);
407 $password_wtr->autoflush(1);
409 my($wtr, $rdr, $err);
410 $err = Symbol::gensym;
411 my $pid = open3($wtr, $rdr, $err, "-");
414 if (defined $self->{password}) {
415 my $ff = $password_rdr->fileno;
416 debug("password_rdr $ff");
417 $password_wtr->close();
418 $ENV{PASSWD_FD} = $password_rdr->fileno;
423 push @ARGV, $self->{smbclient}, $self->{share};
424 push @ARGV, "" if (!defined $self->{password});
425 push @ARGV, "-U", $self->{username},
427 if (defined $self->{domain}) {
428 push @ARGV, "-W", $self->{domain},
430 if (defined $self->{subdir}) {
431 push @ARGV, "-D", $self->{subdir},
433 push @ARGV, "-c", "quit";
434 debug("execute: " . $self->{smbclient} . " " .
436 exec {$self->{smbclient}} @ARGV;
439 if (defined $self->{password}) {
440 my $ff = $password_wtr->fileno;
441 debug("password_wtr $ff");
442 $password_wtr->print($self->{password});
443 $password_wtr->close();
444 $password_rdr->close();
446 debug("No password");
452 debug("stderr: " . $_);
454 # message if samba server is configured with 'security = share'
455 next if /Server not using user level security and no password supplied./;
456 $self->print_to_server("smbclient: $_",
457 $Amanda::Script_App::ERROR);
465 sub command_estimate {
468 $self->parsesharename();
470 $self->validate_inexclude();
472 my $level = $self->{level}[0];
473 my ($password_rdr, $password_wtr);
474 if (defined $self->{password}) {
475 # Don't set close-on-exec
477 pipe($password_rdr, $password_wtr);
479 $password_wtr->autoflush(1);
481 my($wtr, $rdr, $err);
482 $err = Symbol::gensym;
483 my $pid = open3($wtr, $rdr, $err, "-");
486 if (defined $self->{password}) {
487 my $ff = $password_rdr->fileno;
488 debug("password_rdr $ff");
489 $password_wtr->close();
490 $ENV{PASSWD_FD} = $password_rdr->fileno;
495 push @ARGV, $self->{smbclient}, $self->{share};
496 push @ARGV, "" if (!defined($self->{password}));
497 push @ARGV, "-d", "0",
498 "-U", $self->{username},
500 if (defined $self->{domain}) {
501 push @ARGV, "-W", $self->{domain},
503 if (defined $self->{subdir}) {
504 push @ARGV, "-D", $self->{subdir},
507 push @ARGV, "-c", "archive 0;recurse;du";
509 push @ARGV, "-c", "archive 1;recurse;du";
511 debug("execute: " . $self->{smbclient} . " " .
513 exec {$self->{smbclient}} @ARGV;
516 if (defined $self->{password}) {
517 my $ff = $password_wtr->fileno;
518 debug("password_wtr $ff");
519 debug("password $self->{password}");
520 $password_wtr->print($self->{password});
521 $password_wtr->close();
522 $password_rdr->close();
526 my $size = $self->parse_estimate($err);
528 output_size($level, $size);
539 next if /blocks of size/;
540 next if /blocks available/;
543 next if /dumped \d+ files and directories/;
544 # message if samba server is configured with 'security = share'
545 next if /Server not using user level security and no password supplied./;
547 if ($_ =~ /^Total number of bytes: (\d*)/) {
551 $self->print_to_server("smbclient: $_",
552 $Amanda::Script_App::ERROR);
562 print "$level -1 -1\n";
566 my($ksize) = int $size / (1024);
567 $ksize=32 if ($ksize<32);
568 print "$level $ksize 1\n";
572 sub send_empty_tar_file {
574 my ($out1, $out2) = @_;
579 Amanda::Debug::debug("Create empty archive with: tar --create --file=- --files-from=/dev/null");
580 open2($out, undef, "tar", "--create", "--file=-", "--files-from=/dev/null");
582 while(($size = sysread($out, $buf, 32768))) {
583 syswrite($out1, $buf, $size);
584 syswrite($out2, $buf, $size);
591 my $level = $self->{level}[0];
593 $self->parsesharename();
595 $self->validate_inexclude();
597 my ($password_rdr, $password_wtr);
598 if (defined $self->{password}) {
599 # Don't set close-on-exec
601 pipe($password_rdr, $password_wtr);
603 $password_wtr->autoflush(1);
605 my($smbclient_wtr, $smbclient_rdr, $smbclient_err);
606 $smbclient_err = Symbol::gensym;
607 my $pid = open3($smbclient_wtr, $smbclient_rdr, $smbclient_err, "-");
610 if (defined $self->{password}) {
611 my $ff = $password_rdr->fileno;
612 debug("password_rdr $ff");
613 $password_wtr->close();
614 $ENV{PASSWD_FD} = $password_rdr->fileno;
617 push @ARGV, $self->{smbclient}, $self->{share};
618 push @ARGV, "" if (!defined($self->{password}));
619 push @ARGV, "-d", "0",
620 "-U", $self->{username},
622 if (defined $self->{domain}) {
623 push @ARGV, "-W", $self->{domain},
625 if (defined $self->{subdir}) {
626 push @ARGV, "-D", $self->{subdir},
631 $comm = "tarmode full reset hidden system quiet;";
633 $comm = "tarmode inc noreset hidden system quiet;";
636 if ($#{$self->{exclude}} >= 0) {
639 if ($#{$self->{include}} >= 0) {
643 if ($#{$self->{exclude}} >= 0) {
644 $comm .= " " . join(" ", @{$self->{exclude}});
646 if ($#{$self->{include}} >= 0) {
647 $comm .= " " . join(" ", @{$self->{include}});
649 push @ARGV, "-c", $comm;
650 debug("execute: " . $self->{smbclient} . " " .
652 exec {$self->{smbclient}} @ARGV;
655 if (defined $self->{password}) {
656 my $ff = $password_wtr->fileno;
657 debug("password_wtr $ff");
658 $password_wtr->print($self->{password});
659 $password_wtr->close();
660 $password_rdr->close();
662 debug("No password");
664 close($smbclient_wtr);
669 debug("$self->{gnutar} -tf -");
670 my $pid_index1 = open2($index_rdr, $index_wtr, $self->{gnutar}, "-tf", "-");
672 my $index_fd = $index_rdr->fileno;
673 debug("index $index_fd");
675 if (defined($self->{index})) {
676 open($indexout_fd, '>&=4') ||
677 $self->print_to_server_and_die("Can't open indexout_fd: $!",
678 $Amanda::Script_App::ERROR);
681 my $file_to_close = 3;
682 my $smbclient_stdout_src = Amanda::MainLoop::fd_source($smbclient_rdr,
683 $G_IO_IN|$G_IO_HUP|$G_IO_ERR);
684 my $smbclient_stderr_src = Amanda::MainLoop::fd_source($smbclient_err,
685 $G_IO_IN|$G_IO_HUP|$G_IO_ERR);
686 my $index_tar_stdout_src = Amanda::MainLoop::fd_source($index_rdr,
687 $G_IO_IN|$G_IO_HUP|$G_IO_ERR);
689 my $smbclient_stdout_done = 0;
690 my $smbclient_stderr_done = 0;
693 $smbclient_stdout_src->set_callback(sub {
696 $blocksize = sysread($smbclient_rdr, $buf, 32768);
699 $smbclient_stdout_src->remove();
700 $smbclient_stdout_done = 1;
701 if ($smbclient_stderr_done) {
702 if ($data_size == 0 and $nb_files == 0 and $size == 0) {
703 $self->send_empty_tar_file(*STDOUT, $index_wtr);
708 close($smbclient_rdr);
709 Amanda::MainLoop::quit() if $file_to_close == 0;
712 $data_size += $blocksize;
713 syswrite(STDOUT, $buf, $blocksize);
714 syswrite($index_wtr, $buf, $blocksize);
717 $smbclient_stderr_src->set_callback(sub {
718 my $line = <$smbclient_err>;
719 if (!defined $line) {
721 $smbclient_stderr_src->remove();
722 $smbclient_stderr_done = 1;
723 if ($smbclient_stdout_done) {
724 if ($data_size == 0 and $nb_files == 0 and $size == 0) {
725 $self->send_empty_tar_file(*STDOUT, $index_wtr);
730 close ($smbclient_err);
731 Amanda::MainLoop::quit() if $file_to_close == 0;
735 debug("stderr: " . $line);
736 return if $line =~ /^Domain=/;
737 return if $line =~ /^tarmode is now /;
738 if ($line =~ /dumped (\d+) files and directories/) {
742 # message if samba server is configured with 'security = share'
743 return if $line =~$line =~ /Server not using user level security and no password supplied./;
744 if ($line =~ /^Total bytes written: (\d*)/) {
748 $self->print_to_server("smbclient: $line", $Amanda::Script_App::ERROR);
751 $index_tar_stdout_src->set_callback(sub {
752 my $line = <$index_rdr>;
753 if (!defined $line) {
755 $index_tar_stdout_src->remove();
758 Amanda::MainLoop::quit() if $file_to_close == 0;
761 if ($line =~ /^\.\//) {
762 if(defined($indexout_fd)) {
763 if(defined($self->{index})) {
765 print $indexout_fd $line;
770 $self->print_to_server($line, $Amanda::Script_App::ERROR);
774 Amanda::MainLoop::run();
777 my $ksize = $size / 1024;
781 print {$self->{mesgout}} "sendbackup: size $ksize\n";
782 print {$self->{mesgout}} "sendbackup: end\n";
787 $self->print_to_server_and_die("smbclient returned error",
788 $Amanda::Script_App::ERROR);
795 my($fhin, $fhout, $indexout) = @_;
799 if(defined($indexout)) {
800 if(defined($self->{index})) {
812 sub command_index_from_output {
813 index_from_output(0, 1);
817 sub index_from_output {
818 my($fhin, $fhout) = @_;
821 next if /^Total bytes written:/;
828 sub command_index_from_image {
831 open($index_fd, "$self->{gnutar} --list --file - |") ||
832 $self->print_to_server_and_die("Can't run $self->{gnutar}: $!",
833 $Amanda::Script_App::ERROR);
834 index_from_output($index_fd, 1);
837 sub command_restore {
841 $self->parsesharename();
842 chdir(Amanda::Util::get_original_cwd());
844 if ($self->{recover_mode} eq "smb") {
845 $self->validate_inexclude();
847 push @cmd, $self->{smbclient}, $self->{share};
848 push @cmd, "-D", $self->{'subdir'} if defined $self->{'subdir'};
849 push @cmd, "" if (!defined $self->{password});
850 push @cmd, "-d", "0",
851 "-U", $self->{username};
853 if (defined $self->{domain}) {
854 push @cmd, "-W", $self->{domain};
856 if (defined $self->{'include_filename'}) {
857 push @cmd, "-TFx", "-", "$self->{'include_filename'}";
859 push @cmd, "-Tx", "-";
860 if ($#{$self->{include}} >= 0) {
861 push @cmd, @{$self->{include}};
863 for(my $i=1;defined $ARGV[$i]; $i++) {
864 my $param = $ARGV[$i];
869 my ($parent_rdr, $child_wtr);
870 if (defined $self->{password}) {
871 # Don't set close-on-exec
873 pipe($parent_rdr, $child_wtr);
875 $child_wtr->autoflush(1);
877 my($wtr, $rdr, $err);
878 $err = Symbol::gensym;
879 my $pid = open3($wtr, $rdr, $err, "-");
881 $child_wtr->print($self->{password});
885 if (defined $self->{password}) {
887 $ENV{PASSWD_FD} = $parent_rdr->fileno;
889 debug("cmd:" . join(" ", @cmd));
890 exec { $cmd[0] } @cmd;
891 die("Can't exec '", $cmd[0], "'");
893 push @cmd, $self->{gnutar}, "-xpvf", "-";
894 if (defined $self->{directory}) {
895 if (!-d $self->{directory}) {
896 $self->print_to_server_and_die(
897 "Directory $self->{directory}: $!",
898 $Amanda::Script_App::ERROR);
900 if (!-w $self->{directory}) {
901 $self->print_to_server_and_die(
902 "Directory $self->{directory}: $!",
903 $Amanda::Script_App::ERROR);
905 push @cmd, "--directory", $self->{directory};
907 if ($#{$self->{include_list}} == 0) {
908 push @cmd, "--files-from", $self->{include_list}[0];
910 if ($#{$self->{exclude_list}} == 0) {
911 push @cmd, "--exclude-from", $self->{exclude_list}[0];
913 for(my $i=1;defined $ARGV[$i]; $i++) {
914 my $param = $ARGV[$i];
918 debug("cmd:" . join(" ", @cmd));
919 exec { $cmd[0] } @cmd;
920 die("Can't exec '", $cmd[0], "'");
924 sub command_validate {
927 if (!defined($self->{gnutar}) || !-x $self->{gnutar}) {
928 return $self->default_validate();
931 my(@cmd) = ($self->{gnutar}, "-tf", "-");
932 debug("cmd:" . join(" ", @cmd));
933 my $pid = open3('>&STDIN', '>&STDOUT', '>&STDERR', @cmd) ||
934 $self->print_to_server_and_die("Unable to run @cmd: $!",
935 $Amanda::Script_App::ERROR);
938 $self->print_to_server_and_die("$self->{gnutar} returned error",
939 $Amanda::Script_App::ERROR);
944 sub command_print_command {
951 Usage: amsamba <command> --config=<config> --host=<host> --disk=<disk> --device=<device> --level=<level> --index=<yes|no> --message=<text> --collection=<no> --record=<yes|no> --calcsize.
968 my $opt_smbclient_path;
970 my @opt_exclude_file;
971 my @opt_exclude_list;
972 my $opt_exclude_optional;
973 my @opt_include_file;
974 my @opt_include_list;
975 my $opt_include_optional;
976 my $opt_recover_mode;
977 my $opt_allow_anonymous;
980 Getopt::Long::Configure(qw{bundling});
982 'version' => \$opt_version,
983 'config=s' => \$opt_config,
984 'host=s' => \$opt_host,
985 'disk=s' => \$opt_disk,
986 'device=s' => \$opt_device,
987 'level=s' => \@opt_level,
988 'index=s' => \$opt_index,
989 'message=s' => \$opt_message,
990 'collection=s' => \$opt_collection,
991 'record' => \$opt_record,
992 'calcsize' => \$opt_calcsize,
993 'gnutar-path=s' => \$opt_gnutar_path,
994 'smbclient-path=s' => \$opt_smbclient_path,
995 'amandapass=s' => \$opt_amandapass,
996 'exclude-file=s' => \@opt_exclude_file,
997 'exclude-list=s' => \@opt_exclude_list,
998 'exclude-optional=s' => \$opt_exclude_optional,
999 'include-file=s' => \@opt_include_file,
1000 'include-list=s' => \@opt_include_list,
1001 'include-optional=s' => \$opt_include_optional,
1002 'recover-mode=s' => \$opt_recover_mode,
1003 'allow-anonymous=s' => \$opt_allow_anonymous,
1004 'directory=s' => \$opt_directory,
1007 if (defined $opt_version) {
1008 print "amsamba-" . $Amanda::Constants::VERSION , "\n";
1012 my $application = Amanda::Application::Amsamba->new($opt_config, $opt_host, $opt_disk, $opt_device, \@opt_level, $opt_index, $opt_message, $opt_collection, $opt_record, $opt_calcsize, $opt_gnutar_path, $opt_smbclient_path, $opt_amandapass, \@opt_exclude_file, \@opt_exclude_list, $opt_exclude_optional, \@opt_include_file, \@opt_include_list, $opt_include_optional, $opt_recover_mode, $opt_allow_anonymous, $opt_directory);
1014 $application->do($ARGV[0]);