2 # Copyright (c) 2008-2012 Zmanda, Inc. All Rights Reserved.
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.
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
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
17 # Contact information: Zmanda Inc., 465 S. Mathilda Ave., Suite 300
18 # Sunnyvale, CA 94086, USA, or: http://www.zmanda.com
20 use lib '@amperldir@';
25 package Amanda::Application::Amsamba;
26 use base qw(Amanda::Application);
34 use Amanda::Constants;
35 use Amanda::Config qw( :init :getconf config_dir_relative );
36 use Amanda::Debug qw( :logging );
38 use Amanda::Util qw( :constants :quoting);
39 use Amanda::MainLoop qw( :GIOCondition );
43 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) = @_;
44 my $self = $class->SUPER::new($config);
46 if (defined $gnutar_path) {
47 $self->{gnutar} = $gnutar_path;
49 $self->{gnutar} = $Amanda::Constants::GNUTAR;
51 if (defined $smbclient_path) {
52 $self->{smbclient} = $smbclient_path;
54 $self->{smbclient} = $Amanda::Constants::SAMBA_CLIENT;
56 if (defined $amandapass) {
57 $self->{amandapass} = config_dir_relative($amandapass);
59 $self->{amandapass} = "$Amanda::Paths::CONFIG_DIR/amandapass";
62 $self->{config} = $config;
63 $self->{host} = $host;
65 $self->{disk} = $disk;
67 $self->{disk} = $device;
69 if (defined $device) {
70 $self->{device} = $device;
72 $self->{device} = $disk;
74 $self->{level} = [ @{$level} ];
75 $self->{index} = $index;
76 $self->{message} = $message;
77 $self->{collection} = $collection;
78 $self->{record} = $record;
79 $self->{calcsize} = $calcsize;
80 $self->{exclude_file} = [ @{$exclude_file} ];
81 $self->{exclude_list} = [ @{$exclude_list} ];
82 $self->{exclude_optional} = $exclude_optional;
83 $self->{include_file} = [ @{$include_file} ];
84 $self->{include_list} = [ @{$include_list} ];
85 $self->{include_optional} = $include_optional;
86 $self->{recover_mode} = $recover_mode;
87 $self->{allow_anonymous} = $allow_anonymous;
88 $self->{directory} = $directory;
94 # $self->{exclude_file}
95 # $self->{exclude_list}
96 # $self->{include_file}
97 # $self->{include_list}
101 # $self->{include_filename}
102 sub validate_inexclude {
105 if ($#{$self->{exclude_file}} + $#{$self->{exclude_list}} >= -1 &&
106 $#{$self->{include_file}} + $#{$self->{include_list}} >= -1) {
107 $self->print_to_server_and_die("Can't have both include and exclude",
108 $Amanda::Script_App::ERROR);
111 if ($#{$self->{exclude_file}} >= 0) {
112 $self->{exclude} = [ @{$self->{exclude_file}} ];
114 foreach my $file (@{$self->{exclude_list}}) {
115 if (!open(FF, $file)) {
116 if ($self->{action} eq 'check' && !$self->{exclude_optional}) {
117 $self->print_to_server("Open of '$file' failed: $!",
118 $Amanda::Script_App::ERROR);
124 push @{$self->{exclude}}, $_;
129 if ($self->{action} eq "restore" and defined $self->{'include_list'}) {
130 # put all include in a single file $self->{'include_filename'}
131 $self->{'include_filename'} = "$AMANDA_TMPDIR/amsamba.$$.include";
132 open INC_FILE, ">$self->{'include_filename'}";
133 if ($#{$self->{include_file}} >= 0) {
134 print INC_FILE "$self->{include_file}\n";
136 foreach my $file (@{$self->{include_list}}) {
137 if (!open(FF, $file)) {
138 if ($self->{action} eq 'check' && !$self->{include_optional}) {
139 $self->print_to_server("Open of '$file' failed: $!",
140 $Amanda::Script_App::ERROR);
145 if (defined $self->{'subdir'}) {
146 $_ =~ s/^\./$self->{'subdir'}/;
153 # add command line include for amrestore
154 for(my $i=1;defined $ARGV[$i]; $i++) {
155 my $param = $ARGV[$i];
158 if (defined $self->{'subdir'}) {
159 $_ =~ s/^\./$self->{'subdir'}/;
161 print INC_FILE "$_\n";
166 # put all include in $self->{'include'} they will be added on
168 if ($#{$self->{include_file}} >= 0) {
169 $self->{include} = [ @{$self->{include_file}} ];
172 foreach my $file (@{$self->{include_list}}) {
173 if (!open(FF, $file)) {
174 if ($self->{action} eq 'check' && !$self->{include_optional}) {
175 $self->print_to_server("Open of '$file' failed: $!",
176 $Amanda::Script_App::ERROR);
182 if ($self->{action} eq "restore" and
183 defined $self->{'subdir'}) {
184 $_ =~ s/^\./$self->{'subdir'}/;
186 push @{$self->{include}}, $_;
191 # add command line include for amrestore
192 if ($self->{action} eq "restore") {
193 for(my $i=1;defined $ARGV[$i]; $i++) {
194 my $param = $ARGV[$i];
197 if (defined $self->{'subdir'}) {
198 $_ =~ s/^\./$self->{'subdir'}/;
200 push @{$self->{include}}, $1;
207 # $self->{directory} == //host/share/subdir \\host\share\subdir
209 # $self->{device} == //host/share/subdir \\host\share\subdir
211 # $self->{cifshost} = //host \\host
212 # $self->{share} = //host/share \\host\share
213 # $self->{sambashare} = \\host\share \\host\share
214 # $self->{subdir} = subdir subdir
217 my $to_parse = $self->{directory};
218 $to_parse = $self->{device} if !defined $to_parse;;
220 return if !defined $to_parse;
221 if ($to_parse =~ /^\\\\/) {
228 if ($to_parse =~ m,^(\\\\[^\\]+\\[^\\]+)\\(.*)$,) {
232 $self->{share} = $to_parse
234 $self->{sambashare} = $self->{share};
235 $to_parse =~ m,^(\\\\[^\\]+)\\[^\\]+,;
236 $self->{cifshost} = $1;
238 if ($to_parse =~ m,^(//[^/]+/[^/]+)/(.*)$,) {
242 $self->{share} = $to_parse
244 $self->{sambashare} = $self->{share};
245 $self->{sambashare} =~ s,/,\\,g;
246 $to_parse =~ m,^(//[^/]+)/[^/]+,;
247 $self->{cifshost} = $1;
252 # Read $self->{amandapass} file.
254 # $self->{cifshost} == //host/share
255 # $self->{share} == //host/share
257 # $self->{domain} = domain to connect to.
258 # $self->{username} = username (-U)
259 # $self->{password} = password
266 $self->{domain} = undef;
267 $self->{username} = undef;
268 $self->{password} = undef;
270 debug("amandapass: $self->{amandapass}");
271 if (!open($amandapass, $self->{amandapass})) {
272 if ($self->{allow_anonymous}) {
273 $self->{username} = $self->{allow_anonymous};
274 debug("cannot open password file '$self->{amandapass}': $!\n");
275 debug("Using anonymous user: $self->{username}");
278 $self->print_to_server_and_die(
279 "cannot open password file '$self->{amandapass}': $!",
280 $Amanda::Script_App::ERROR);
284 while ($line = <$amandapass>) {
286 next if $line =~ /^#/;
287 my ($diskname, $userpasswd, $domain, $extra) = Amanda::Util::split_quoted_string_friendly($line);
289 debug("Trailling characters ignored in amandapass line");
291 if (defined $diskname &&
293 ($self->{unc}==0 && $diskname =~ m,^(//[^/]+)/\*$, && $1 eq $self->{cifshost}) ||
294 ($self->{unc}==1 && $diskname =~ m,^(\\\\[^\\]+)\\\*$, && $1 eq $self->{cifshost}) ||
295 $diskname eq $self->{share} ||
296 $diskname eq $self->{sambashare})) {
297 if (defined $userpasswd && $userpasswd ne "") {
298 $self->{domain} = $domain if defined $domain && $domain ne "";
299 my ($username, $password) = split('%', $userpasswd, 2);
300 $self->{username} = $username;
301 $self->{password} = $password;
302 $self->{password} = undef if (defined $password && $password eq "");
304 $self->{username} = "guest";
311 if ($self->{allow_anonymous}) {
312 $self->{username} = $self->{allow_anonymous};
313 debug("Cannot find password for share $self->{share} in $self->{amandapass}");
314 debug("Using anonymous user: $self->{username}");
317 $self->print_to_server_and_die(
318 "Cannot find password for share $self->{share} in $self->{amandapass}",
319 $Amanda::Script_App::ERROR);
322 sub command_support {
325 print "CONFIG YES\n";
328 print "MAX-LEVEL 1\n";
329 print "INDEX-LINE YES\n";
330 print "INDEX-XML NO\n";
331 print "MESSAGE-LINE YES\n";
332 print "MESSAGE-XML NO\n";
333 print "RECORD YES\n";
334 print "COLLECTION NO\n";
335 print "MULTI-ESTIMATE NO\n";
336 print "CALCSIZE NO\n";
337 print "CLIENT-ESTIMATE YES\n";
338 print "EXCLUDE-FILE YES\n";
339 print "EXCLUDE-LIST YES\n";
340 print "EXCLUDE-OPTIONAL YES\n";
341 print "INCLUDE-FILE YES\n";
342 print "INCLUDE-LIST YES\n";
343 print "INCLUDE-OPTIONAL YES\n";
344 print "RECOVER-MODE SMB\n";
347 sub command_selfcheck {
350 $self->print_to_server("disk " . quote_string($self->{disk}));
352 $self->print_to_server("amsamba version " . $Amanda::Constants::VERSION,
353 $Amanda::Script_App::GOOD);
355 if (!defined($self->{smbclient}) || $self->{smbclient} eq "") {
356 $self->print_to_server(
357 "smbclient not set; you must define the SMBCLIENT-PATH property",
358 $Amanda::Script_App::ERROR);
360 elsif (! -e $self->{smbclient}) {
361 $self->print_to_server("$self->{smbclient} doesn't exist",
362 $Amanda::Script_App::ERROR);
364 elsif (! -x $self->{smbclient}) {
365 $self->print_to_server("$self->{smbclient} is not executable",
366 $Amanda::Script_App::ERROR);
368 my @sv = `$self->{smbclient} --version`;
370 $sv[0] =~ /^[^0-9]*(.*)$/;
372 $self->print_to_server("amsamba smbclient-version $sv",
373 $Amanda::Script_App::GOOD);
375 $self->print_to_server(
376 "[Can't get " . $self->{smbclient} . " version]\n",
377 $Amanda::Script_App::ERROR);
381 $self->print_to_server("$self->{smbclient}",
382 $Amanda::Script_App::GOOD);
383 if (!defined $self->{disk} || !defined $self->{device}) {
386 $self->parsesharename();
388 $self->validate_inexclude();
390 print "OK " . $self->{share} . "\n";
391 print "OK " . $self->{device} . "\n";
392 print "OK " . $self->{directory} . "\n" if defined $self->{directory};
394 my ($password_rdr, $password_wtr);
395 if (defined $self->{password}) {
396 # Don't set close-on-exec
398 pipe($password_rdr, $password_wtr);
400 $password_wtr->autoflush(1);
402 my($wtr, $rdr, $err);
403 $err = Symbol::gensym;
404 my $pid = open3($wtr, $rdr, $err, "-");
407 if (defined $self->{password}) {
408 my $ff = $password_rdr->fileno;
409 debug("password_rdr $ff");
410 $password_wtr->close();
411 $ENV{PASSWD_FD} = $password_rdr->fileno;
416 push @ARGV, $self->{smbclient}, $self->{share};
417 push @ARGV, "" if (!defined $self->{password});
418 push @ARGV, "-U", $self->{username},
420 if (defined $self->{domain}) {
421 push @ARGV, "-W", $self->{domain},
423 if (defined $self->{subdir}) {
424 push @ARGV, "-D", $self->{subdir},
426 push @ARGV, "-c", "quit";
427 debug("execute: " . $self->{smbclient} . " " .
429 exec {$self->{smbclient}} @ARGV;
432 if (defined $self->{password}) {
433 my $ff = $password_wtr->fileno;
434 debug("password_wtr $ff");
435 $password_wtr->print($self->{password});
436 $password_wtr->close();
437 $password_rdr->close();
439 debug("No password");
445 debug("stderr: " . $_);
447 # message if samba server is configured with 'security = share'
448 next if /Server not using user level security and no password supplied./;
449 $self->print_to_server("smbclient: $_",
450 $Amanda::Script_App::ERROR);
458 sub command_estimate {
461 $self->parsesharename();
463 $self->validate_inexclude();
465 my $level = $self->{level}[0];
466 my ($password_rdr, $password_wtr);
467 if (defined $self->{password}) {
468 # Don't set close-on-exec
470 pipe($password_rdr, $password_wtr);
472 $password_wtr->autoflush(1);
474 my($wtr, $rdr, $err);
475 $err = Symbol::gensym;
476 my $pid = open3($wtr, $rdr, $err, "-");
479 if (defined $self->{password}) {
480 my $ff = $password_rdr->fileno;
481 debug("password_rdr $ff");
482 $password_wtr->close();
483 $ENV{PASSWD_FD} = $password_rdr->fileno;
488 push @ARGV, $self->{smbclient}, $self->{share};
489 push @ARGV, "" if (!defined($self->{password}));
490 push @ARGV, "-d", "0",
491 "-U", $self->{username},
493 if (defined $self->{domain}) {
494 push @ARGV, "-W", $self->{domain},
496 if (defined $self->{subdir}) {
497 push @ARGV, "-D", $self->{subdir},
500 push @ARGV, "-c", "archive 0;recurse;du";
502 push @ARGV, "-c", "archive 1;recurse;du";
504 debug("execute: " . $self->{smbclient} . " " .
506 exec {$self->{smbclient}} @ARGV;
509 if (defined $self->{password}) {
510 my $ff = $password_wtr->fileno;
511 debug("password_wtr $ff");
512 debug("password $self->{password}");
513 $password_wtr->print($self->{password});
514 $password_wtr->close();
515 $password_rdr->close();
519 my $size = $self->parse_estimate($err);
521 output_size($level, $size);
532 next if /blocks of size/;
533 next if /blocks available/;
536 next if /dumped \d+ files and directories/;
537 # message if samba server is configured with 'security = share'
538 next if /Server not using user level security and no password supplied./;
540 if ($_ =~ /^Total number of bytes: (\d*)/) {
544 $self->print_to_server("smbclient: $_",
545 $Amanda::Script_App::ERROR);
555 print "$level -1 -1\n";
559 my($ksize) = int $size / (1024);
560 $ksize=32 if ($ksize<32);
561 print "$level $ksize 1\n";
565 sub send_empty_tar_file {
567 my ($out1, $out2) = @_;
572 Amanda::Debug::debug("Create empty archive with: tar --create --file=- --files-from=/dev/null");
573 open2($out, undef, "tar", "--create", "--file=-", "--files-from=/dev/null");
575 while(($size = sysread($out, $buf, 32768))) {
576 syswrite($out1, $buf, $size);
577 syswrite($out2, $buf, $size);
584 my $level = $self->{level}[0];
586 $self->parsesharename();
588 $self->validate_inexclude();
590 my ($password_rdr, $password_wtr);
591 if (defined $self->{password}) {
592 # Don't set close-on-exec
594 pipe($password_rdr, $password_wtr);
596 $password_wtr->autoflush(1);
598 my($smbclient_wtr, $smbclient_rdr, $smbclient_err);
599 $smbclient_err = Symbol::gensym;
600 my $pid = open3($smbclient_wtr, $smbclient_rdr, $smbclient_err, "-");
603 if (defined $self->{password}) {
604 my $ff = $password_rdr->fileno;
605 debug("password_rdr $ff");
606 $password_wtr->close();
607 $ENV{PASSWD_FD} = $password_rdr->fileno;
610 push @ARGV, $self->{smbclient}, $self->{share};
611 push @ARGV, "" if (!defined($self->{password}));
612 push @ARGV, "-d", "0",
613 "-U", $self->{username},
615 if (defined $self->{domain}) {
616 push @ARGV, "-W", $self->{domain},
618 if (defined $self->{subdir}) {
619 push @ARGV, "-D", $self->{subdir},
624 $comm = "tarmode full reset hidden system quiet;";
626 $comm = "tarmode inc noreset hidden system quiet;";
629 if ($#{$self->{exclude}} >= 0) {
632 if ($#{$self->{include}} >= 0) {
636 if ($#{$self->{exclude}} >= 0) {
637 $comm .= " " . join(" ", @{$self->{exclude}});
639 if ($#{$self->{include}} >= 0) {
640 $comm .= " " . join(" ", @{$self->{include}});
642 push @ARGV, "-c", $comm;
643 debug("execute: " . $self->{smbclient} . " " .
645 exec {$self->{smbclient}} @ARGV;
648 if (defined $self->{password}) {
649 my $ff = $password_wtr->fileno;
650 debug("password_wtr $ff");
651 $password_wtr->print($self->{password});
652 $password_wtr->close();
653 $password_rdr->close();
655 debug("No password");
657 close($smbclient_wtr);
662 debug("$self->{gnutar} -tf -");
663 my $pid_index1 = open2($index_rdr, $index_wtr, $self->{gnutar}, "-tf", "-");
665 my $index_fd = $index_rdr->fileno;
666 debug("index $index_fd");
668 if (defined($self->{index})) {
669 open($indexout_fd, '>&=4') ||
670 $self->print_to_server_and_die("Can't open indexout_fd: $!",
671 $Amanda::Script_App::ERROR);
674 my $file_to_close = 3;
675 my $smbclient_stdout_src = Amanda::MainLoop::fd_source($smbclient_rdr,
676 $G_IO_IN|$G_IO_HUP|$G_IO_ERR);
677 my $smbclient_stderr_src = Amanda::MainLoop::fd_source($smbclient_err,
678 $G_IO_IN|$G_IO_HUP|$G_IO_ERR);
679 my $index_tar_stdout_src = Amanda::MainLoop::fd_source($index_rdr,
680 $G_IO_IN|$G_IO_HUP|$G_IO_ERR);
682 my $smbclient_stdout_done = 0;
683 my $smbclient_stderr_done = 0;
686 $smbclient_stdout_src->set_callback(sub {
689 $blocksize = sysread($smbclient_rdr, $buf, 32768);
692 $smbclient_stdout_src->remove();
693 $smbclient_stdout_done = 1;
694 if ($smbclient_stderr_done) {
695 if ($data_size == 0 and $nb_files == 0 and $size == 0) {
696 $self->send_empty_tar_file(*STDOUT, $index_wtr);
701 close($smbclient_rdr);
702 Amanda::MainLoop::quit() if $file_to_close == 0;
705 $data_size += $blocksize;
706 syswrite(STDOUT, $buf, $blocksize);
707 syswrite($index_wtr, $buf, $blocksize);
710 $smbclient_stderr_src->set_callback(sub {
711 my $line = <$smbclient_err>;
712 if (!defined $line) {
714 $smbclient_stderr_src->remove();
715 $smbclient_stderr_done = 1;
716 if ($smbclient_stdout_done) {
717 if ($data_size == 0 and $nb_files == 0 and $size == 0) {
718 $self->send_empty_tar_file(*STDOUT, $index_wtr);
723 close ($smbclient_err);
724 Amanda::MainLoop::quit() if $file_to_close == 0;
728 debug("stderr: " . $line);
729 return if $line =~ /^Domain=/;
730 return if $line =~ /^tarmode is now /;
731 if ($line =~ /dumped (\d+) files and directories/) {
735 # message if samba server is configured with 'security = share'
736 return if $line =~$line =~ /Server not using user level security and no password supplied./;
737 if ($line =~ /^Total bytes written: (\d*)/) {
741 $self->print_to_server("smbclient: $line", $Amanda::Script_App::ERROR);
744 $index_tar_stdout_src->set_callback(sub {
745 my $line = <$index_rdr>;
746 if (!defined $line) {
748 $index_tar_stdout_src->remove();
751 Amanda::MainLoop::quit() if $file_to_close == 0;
754 if ($line =~ /^\.\//) {
755 if(defined($indexout_fd)) {
756 if(defined($self->{index})) {
758 print $indexout_fd $line;
763 $self->print_to_server($line, $Amanda::Script_App::ERROR);
767 Amanda::MainLoop::run();
770 my $ksize = $size / 1024;
774 print {$self->{mesgout}} "sendbackup: size $ksize\n";
775 print {$self->{mesgout}} "sendbackup: end\n";
780 $self->print_to_server_and_die("smbclient returned error",
781 $Amanda::Script_App::ERROR);
788 my($fhin, $fhout, $indexout) = @_;
792 if(defined($indexout)) {
793 if(defined($self->{index})) {
805 sub command_index_from_output {
806 index_from_output(0, 1);
810 sub index_from_output {
811 my($fhin, $fhout) = @_;
814 next if /^Total bytes written:/;
821 sub command_index_from_image {
824 open($index_fd, "$self->{gnutar} --list --file - |") ||
825 $self->print_to_server_and_die("Can't run $self->{gnutar}: $!",
826 $Amanda::Script_App::ERROR);
827 index_from_output($index_fd, 1);
830 sub command_restore {
834 $self->parsesharename();
835 chdir(Amanda::Util::get_original_cwd());
837 if ($self->{recover_mode} eq "smb") {
838 $self->validate_inexclude();
840 push @cmd, $self->{smbclient}, $self->{share};
841 push @cmd, "-D", $self->{'subdir'} if defined $self->{'subdir'};
842 push @cmd, "" if (!defined $self->{password});
843 push @cmd, "-d", "0",
844 "-U", $self->{username};
846 if (defined $self->{domain}) {
847 push @cmd, "-W", $self->{domain};
849 if (defined $self->{'include_filename'}) {
850 push @cmd, "-TFx", "-", "$self->{'include_filename'}";
852 push @cmd, "-Tx", "-";
853 if ($#{$self->{include}} >= 0) {
854 push @cmd, @{$self->{include}};
856 for(my $i=1;defined $ARGV[$i]; $i++) {
857 my $param = $ARGV[$i];
862 my ($parent_rdr, $child_wtr);
863 if (defined $self->{password}) {
864 # Don't set close-on-exec
866 pipe($parent_rdr, $child_wtr);
868 $child_wtr->autoflush(1);
870 my($wtr, $rdr, $err);
871 $err = Symbol::gensym;
872 my $pid = open3($wtr, $rdr, $err, "-");
874 $child_wtr->print($self->{password});
878 if (defined $self->{password}) {
880 $ENV{PASSWD_FD} = $parent_rdr->fileno;
882 debug("cmd:" . join(" ", @cmd));
883 exec { $cmd[0] } @cmd;
884 die("Can't exec '", $cmd[0], "'");
886 push @cmd, $self->{gnutar}, "-xpvf", "-";
887 if (defined $self->{directory}) {
888 if (!-d $self->{directory}) {
889 $self->print_to_server_and_die(
890 "Directory $self->{directory}: $!",
891 $Amanda::Script_App::ERROR);
893 if (!-w $self->{directory}) {
894 $self->print_to_server_and_die(
895 "Directory $self->{directory}: $!",
896 $Amanda::Script_App::ERROR);
898 push @cmd, "--directory", $self->{directory};
900 if ($#{$self->{include_list}} == 0) {
901 push @cmd, "--files-from", $self->{include_list}[0];
903 if ($#{$self->{exclude_list}} == 0) {
904 push @cmd, "--exclude-from", $self->{exclude_list}[0];
906 for(my $i=1;defined $ARGV[$i]; $i++) {
907 my $param = $ARGV[$i];
911 debug("cmd:" . join(" ", @cmd));
912 exec { $cmd[0] } @cmd;
913 die("Can't exec '", $cmd[0], "'");
917 sub command_validate {
920 if (!defined($self->{gnutar}) || !-x $self->{gnutar}) {
921 return $self->default_validate();
924 my(@cmd) = ($self->{gnutar}, "-tf", "-");
925 debug("cmd:" . join(" ", @cmd));
926 my $pid = open3('>&STDIN', '>&STDOUT', '>&STDERR', @cmd) ||
927 $self->print_to_server_and_die("Unable to run @cmd: $!",
928 $Amanda::Script_App::ERROR);
931 $self->print_to_server_and_die("$self->{gnutar} returned error",
932 $Amanda::Script_App::ERROR);
937 sub command_print_command {
944 Usage: amsamba <command> --config=<config> --host=<host> --disk=<disk> --device=<device> --level=<level> --index=<yes|no> --message=<text> --collection=<no> --record=<yes|no> --calcsize.
961 my $opt_smbclient_path;
963 my @opt_exclude_file;
964 my @opt_exclude_list;
965 my $opt_exclude_optional;
966 my @opt_include_file;
967 my @opt_include_list;
968 my $opt_include_optional;
969 my $opt_recover_mode;
970 my $opt_allow_anonymous;
973 Getopt::Long::Configure(qw{bundling});
975 'version' => \$opt_version,
976 'config=s' => \$opt_config,
977 'host=s' => \$opt_host,
978 'disk=s' => \$opt_disk,
979 'device=s' => \$opt_device,
980 'level=s' => \@opt_level,
981 'index=s' => \$opt_index,
982 'message=s' => \$opt_message,
983 'collection=s' => \$opt_collection,
984 'record' => \$opt_record,
985 'calcsize' => \$opt_calcsize,
986 'gnutar-path=s' => \$opt_gnutar_path,
987 'smbclient-path=s' => \$opt_smbclient_path,
988 'amandapass=s' => \$opt_amandapass,
989 'exclude-file=s' => \@opt_exclude_file,
990 'exclude-list=s' => \@opt_exclude_list,
991 'exclude-optional=s' => \$opt_exclude_optional,
992 'include-file=s' => \@opt_include_file,
993 'include-list=s' => \@opt_include_list,
994 'include-optional=s' => \$opt_include_optional,
995 'recover-mode=s' => \$opt_recover_mode,
996 'allow-anonymous=s' => \$opt_allow_anonymous,
997 'directory=s' => \$opt_directory,
1000 if (defined $opt_version) {
1001 print "amsamba-" . $Amanda::Constants::VERSION , "\n";
1005 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);
1007 $application->do($ARGV[0]);