]> git.sur5r.net Git - bacula/bacula/blob - regress/scripts/regress-win32.pl
f220927c7ee69dd3242589d7ba19632c48493167
[bacula/bacula] / regress / scripts / regress-win32.pl
1 #!/usr/bin/perl -w
2
3 =head1 NAME
4
5     regress-win32.pl -- Helper for Windows regression tests
6
7 =head2 DESCRIPTION
8
9     This perl script permits to run test Bacula Client Daemon on Windows.
10     It allows to:
11        - stop/start/upgrade the Bacula Client Daemon
12        - compare to subtree with checksums, attribs and ACL
13        - create test environments
14
15 =head2 USAGE
16
17   X:\> regress-win32.pl [-b basedir] [-i ip_address] [-p c:/bacula]
18    or
19   X:\> perl regress-win32.pl ...
20
21     -b|--base=path      Where to find regress and bacula directories
22     -i|--ip=ip          Restrict access to this tool to this ip address
23     -p|--prefix=path    Path to the windows installation
24     -h|--help           Print this help
25
26 =head2 EXAMPLE
27
28     regress-win32.pl -b z:/git         # will find z:/git/regress z:/git/bacula
29
30     regress-win32.pl -i 192.168.0.1 -b z:
31
32 =head2 INSTALL
33
34     This perl script needs a Perl distribution on the Windows Client
35     (http://strawberryperl.com)
36
37     You need to have the following subtree on x:
38     x:/
39       bacula/
40       regress/
41
42 =cut
43
44 use strict;
45 use HTTP::Daemon;
46 use HTTP::Status;
47 use HTTP::Response;
48 use HTTP::Headers;
49 use File::Copy;
50 use Pod::Usage;
51 use Cwd 'chdir';
52 use File::Find;
53 use Digest::MD5;
54 use Getopt::Long ;
55
56 my $base = 'x:';
57 my $src_ip = '';
58 my $help;
59 my $bacula_prefix="c:/Program Files/Bacula";
60 my $conf = "C:/Documents and Settings/All Users/Application Data/Bacula";
61 GetOptions("base=s"   => \$base,
62            "help"     => \$help,
63            "prefix=s" => \$bacula_prefix,
64            "ip=s"     => \$src_ip);
65
66 if ($help) {
67     pod2usage(-verbose => 2, 
68               -exitval => 0);
69 }
70
71 if (! -d $bacula_prefix) {
72     print "Could not find Bacula installation dir $bacula_prefix\n";
73     print "Won't be able to upgrade the version or modify the configuration\n";
74 }
75
76 if (-f "$bacula_prefix/bacula-fd.conf" and -f "$conf/bacula-fd.conf") {
77     print "Unable to determine bacula-fd location $bacula_prefix or $conf ?\n";
78
79 } elsif (-f "$bacula_prefix/bacula-fd.conf") {
80     $conf = $bacula_prefix;
81 }
82
83 #if (! -d "$base/bacula" || ! -d "$base/regress") {
84 #    pod2usage(-verbose => 2, 
85 #              -exitval => 1,
86 #              -message => "Can't find bacula or regress dir on $base\n");
87 #} 
88
89 # stop the fd service
90 sub stop_fd
91 {
92     return `net stop bacula-fd`;
93 }
94
95 # copy binaries for a new fd
96 sub install_fd
97 {
98     copy("$base/bacula/src/win32/release32/bacula-fd.exe", 
99          "c:/Program Files/bacula/bacula-fd.exe"); 
100
101     copy("$base/bacula/src/win32/release32/bacula.dll", 
102          "c:/Program Files/bacula/bacula.dll"); 
103 }
104
105 # start the fd service
106 sub start_fd
107 {
108     return `net start bacula-fd`;
109 }
110
111 # convert \ to / and strip the path
112 sub strip_base
113 {
114     my ($data, $path) = @_;
115     $data =~ s!\\!/!sg;
116     $data =~ s!\Q$path!!sig;
117     return $data;
118 }
119
120 # initialize the weird directory for runscript test
121 sub init_weird_runscript_test
122 {
123     my ($r) = shift;
124
125     if ($r->url !~ m!^/init_weird_runscript_test\?source=(\w:/[\w/]+)$!) {
126         return "ERR\nIncorrect url\n";
127     }
128     my $source = $1;
129
130     if (!chdir($source)) {
131         return "ERR\nCan't access to $source $!\n";
132     }
133     
134     if (-d "weird_runcript") {
135         system("rmdir /Q /S weird_runcript");
136     }
137
138     mkdir("weird_runcript");
139     if (!chdir("weird_runcript")) {
140         return "ERR\nCan't access to $source $!\n";
141     }
142    
143     open(FP, ">test.bat")                 or return "ERR\n";
144     print FP "\@echo off\n";
145     print FP "echo hello \%1\n";
146     close(FP);
147     
148     copy("test.bat", "test space.bat")    or return "ERR\n";
149     copy("test.bat", "test2 space.bat")   or return "ERR\n";
150     copy("test.bat", "testé.bat")         or return "ERR\n";
151
152     mkdir("dir space")                    or return "ERR\n";
153     copy("test.bat", "dir space")         or return "ERR\n";
154     copy("testé.bat","dir space")         or return "ERR\n"; 
155     copy("test2 space.bat", "dir space")  or return "ERR\n";
156
157     mkdir("Évoilà")                       or return "ERR\n";
158     copy("test.bat", "Évoilà")            or return "ERR\n";
159     copy("testé.bat","Évoilà")            or return "ERR\n"; 
160     copy("test2 space.bat", "Évoilà")     or return "ERR\n";
161
162     mkdir("Éwith space")                  or return "ERR\n";
163     copy("test.bat", "Éwith space")       or return "ERR\n";
164     copy("testé.bat","Éwith space")       or return "ERR\n"; 
165     copy("test2 space.bat", "Éwith space") or return "ERR\n";
166     return "OK\n";
167 }
168
169 # init the Attrib test by creating some files and settings attributes
170 sub init_attrib_test
171 {
172     my ($r) = shift;
173
174     if ($r->url !~ m!^/init_attrib_test\?source=(\w:/[\w/]+)$!) {
175         return "ERR\nIncorrect url\n";
176     }
177   
178     my $source = $1;
179  
180     if (!chdir($source)) {
181         return "ERR\nCan't access to $source $!\n";
182     }
183
184     # cleanup the old directory if any
185     if (-d "attrib_test") {
186         system("rmdir /Q /S attrib_test");
187     }
188
189     mkdir("attrib_test");
190     chdir("attrib_test");
191     
192     mkdir("hidden");
193     mkdir("hidden/something");
194     system("attrib +H hidden");
195
196     mkdir("readonly");
197     mkdir("readonly/something");
198     system("attrib +R readonly");
199
200     mkdir("normal");
201     mkdir("normal/something");
202     system("attrib -R -H -S normal");
203
204     mkdir("system");
205     mkdir("system/something");
206     system("attrib +S system");
207
208     mkdir("readonly_hidden");
209     mkdir("readonly_hidden/something");
210     system("attrib +R +H readonly_hidden");
211
212     my $ret = `attrib /S /D`;
213     $ret = strip_base($ret, $source);
214
215     return "OK\n$ret\n";
216 }
217
218 sub md5sum
219 {
220     my $file = shift;
221     open(FILE, $file) or return "Can't open $file $!";
222     binmode(FILE);
223     return Digest::MD5->new->addfile(*FILE)->hexdigest;
224 }
225
226 # set $src and $dst before using Find call
227 my ($src, $dst);
228 my $error="";
229 sub wanted
230 {
231     my $f = $File::Find::name;
232     $f =~ s!^\Q$src\E/?!!i;
233     
234     if (-f "$src/$f") {
235         if (! -f "$dst/$f") {
236             $error .= "$dst/$f is missing\n";
237         } else {
238             my $a = md5sum("$src/$f");
239             my $b = md5sum("$dst/$f");
240             if ($a ne $b) {
241                 $error .= "$src/$f $a\n$dst/$f $b\n";
242             }
243         }
244     }
245 }
246
247 # Compare two directories, make checksums, compare attribs and ACLs
248 sub set_director_name
249 {
250     my ($r) = shift;
251
252     if ($r->url !~ m!^/set_director_name\?name=([\w\d\.\-]+);pass=([\w\d+]+)$!)
253     {
254         return "ERR\nIncorrect url\n";
255     }
256
257     my ($name, $pass) = ($1, $2);
258
259     open(ORG, "$conf/bacula-fd.conf") or return "ERR\nORG $!\n";
260     open(NEW, ">$conf/bacula-fd.conf.new") or return "ERR\nNEW $!\n";
261     
262     my $in_dir=0;
263     while (my $l = <ORG>)
264     {
265         if ($l =~ /^\s*Director\s+{/i) {
266             print NEW $l; 
267             $in_dir = 1;
268         } elsif ($l =~ /^(\s*)Name\s*=/ and $in_dir) {
269             print NEW "${1}Name=$name\n";
270         } elsif ($l =~ /^(\s*)Password\s*=/ and $in_dir) {
271             print NEW "${1}Password=$pass\n";
272         } elsif ($l =~ /\s*}/ and $in_dir) {
273             print NEW $l; 
274             $in_dir = 0;
275         } elsif (!$in_dir) {
276             print NEW $l;
277         }
278     }
279
280     close(ORG);
281     close(NEW);
282     move("$conf/bacula-fd.conf.new", "$conf/bacula-fd.conf")
283         and return "OK\n";
284
285     return "ERR\n";
286
287
288 # Compare two directories, make checksums, compare attribs and ACLs
289 sub compare
290 {
291     my ($r) = shift;
292
293     if ($r->url !~ m!^/compare\?source=([\w:/]+);dest=([\w:/]+)$!) {
294         return "ERR\nIncorrect url\n";
295     }
296
297     my ($source, $dest) = ($1, $2);
298     
299     if (!Cwd::chdir($source)) {
300         return "ERR\nCan't access to $source $!\n";
301     }
302     
303     my $src_attrib = `attrib /D /S`;
304     $src_attrib = strip_base($src_attrib, $source);
305
306     if (!Cwd::chdir($dest)) {
307         return "ERR\nCan't access to $dest $!\n";
308     }
309     
310     my $dest_attrib = `attrib /D /S`;
311     $dest_attrib = strip_base($dest_attrib, $dest);
312
313     if ($src_attrib ne $dest_attrib) {
314         return "ERR\n$src_attrib\n=========\n$dest_attrib\n";
315     } 
316
317     ($src, $dst, $error) = ($source, $dest, '');
318     find(\&wanted, $source);
319     if ($error) {
320         return "ERR\n$error";
321     } else {
322         return "OK\n";
323     }
324 }
325
326 # When adding an action, fill this hash with the right function
327 my %action_list = (
328     stop    => \&stop_fd,
329     start   => \&start_fd,
330     install => \&install_fd,
331     compare => \&compare,
332     init_attrib_test => \&init_attrib_test,
333     init_weird_runscript_test => \&init_weird_runscript_test,
334     set_director_name => \&set_director_name,
335     );
336
337 # handle client request
338 sub handle_client
339 {
340     my ($c, $ip) = @_ ;
341     my $action;
342     my $r = $c->get_request ;
343
344     if (!$r) {
345         $c->send_error(RC_FORBIDDEN) ;
346         return;
347     }
348     if ($r->url->path !~ m!^/(\w+)!) {
349         $c->send_error(RC_NOT_FOUND) ;
350         return;
351     }
352     $action = $1;
353
354     if (($r->method eq 'GET') 
355         and $action_list{$action})       
356     {
357         my $ret = $action_list{$action}($r);
358         my $h = HTTP::Headers->new('Content-Type' => 'text/plain') ;
359         my $r = HTTP::Response->new(HTTP::Status::RC_OK,
360                                     'OK', $h, $ret) ;
361
362         $c->send_response($r) ;
363     } else {
364         $c->send_error(RC_NOT_FOUND) ;
365     }
366
367     $c->close;
368 }
369
370 my $d = HTTP::Daemon->new ( LocalPort =>  8091,
371                             ReuseAddr => 1) 
372     || die "E : Can't bind $!" ;
373
374 my $olddir = Cwd::cwd();
375 while (1) {
376     my ($c, $ip) = $d->accept ;
377 #    print "Connexion from $ip\n";
378 #    if (!$ip) {
379 #        $c->send_error(RC_FORBIDDEN) ;
380 #    } elsif ($src_ip && $ip ne $src_ip) {
381 #        $c->send_error(RC_FORBIDDEN) ;
382 #    } elsif ($c) {
383         handle_client($c, $ip) ;
384 #    } else {
385 #        $c->send_error(RC_FORBIDDEN) ;
386 #    }
387     close($c) ;
388     chdir($olddir);
389 }