On the windows box:
- install perl from http://strawberryperl.com on windows
- copy or export regress directory somewhere on your windows
+ You can use a network share to your regress directory on linux
+ Then, copy a link to this script to your desktop
+ And double-click on it, and always open .pl file with perl.exe
+
+ - If you export the regress directory to your windows box and you
+ make windows binaries available, this script can update bacula version.
+ You need to put your binaries on:
+ regress/release32 and regress/release64
+ or
+ regress/build/src/win32/release32 and regress/build/src/win32/release64
+
- start the regress/scripts/regress-win32.pl (open it with perl.exe)
- - create c:/tmp (not sure it's mandatory)
+ - create $WIN32_FILE
- make sure that the firewall is well configured or just disabled (needs
bacula and 8091/tcp)
use File::Find;
use Digest::MD5;
use Getopt::Long ;
+use POSIX;
+use File::Basename qw/dirname/;
my $base = 'x:';
my $src_ip = '';
}
if (! -d $bacula_prefix) {
- print "Could not find Bacula installation dir $bacula_prefix\n";
- print "Won't be able to upgrade the version or modify the configuration\n";
+ print "regress-win32.pl: Could not find Bacula installation dir $bacula_prefix\n";
+ print "regress-win32.pl: Won't be able to upgrade the version or modify the configuration\n";
}
if (-f "$bacula_prefix/bacula-fd.conf" and -f "$conf/bacula-fd.conf") {
- print "Unable to determine bacula-fd location $bacula_prefix or $conf ?\n";
+ print "regress-win32.pl: Unable to determine bacula-fd location $bacula_prefix or $conf ?\n";
} elsif (-f "$bacula_prefix/bacula-fd.conf") {
$conf = $bacula_prefix;
return `net stop bacula-fd`;
}
+my $arch;
+my $bin_path;
+sub find_binaries
+{
+ if ($_ =~ /bacula-fd.exe/i) {
+ if ($File::Find::dir =~ /release$arch/) {
+ $bin_path = $File::Find::dir;
+ }
+ }
+}
+
# copy binaries for a new fd
+# to work, you need to mount the regress directory
sub install_fd
{
- copy("$base/bacula/src/win32/release32/bacula-fd.exe",
- "c:/Program Files/bacula/bacula-fd.exe");
+ my ($r) = shift;
+ if ($r->url !~ m!^/install$!) {
+ return "ERR\nIncorrect url: " . $r->url . "\n";
+ }
+
+ if (-d "c:/Program Files (x86)") {
+ $arch = "64";
+ } else {
+ $arch = "32";
+ }
+
+ # X:/regress/scripts/regress-win32.pl
+ # X:/scripts/regress-win32.pl
+ # perl script location
+
+ my $dir = dirname(dirname($0));
+ print "searching bacula-fd.exe in $dir\n";
+ find(\&find_binaries, ("$dir\\build\\src\\win32\\release$arch",
+ "$dir\\release$arch"));
+
+ if (!$bin_path) {
+ return "ERR\nCan't find bacula-fd.exe in $dir\n";
+ }
+
+ print "Found binaries in $bin_path\n";
+
+ stop_fd();
+
+ system("del \"c:\\Program Files\\bacula\\bacula.dll\"");
+ system("del \"c:\\Program Files\\bacula\\bacula-fd.exe\"");
+ system("del \"c:\\Program Files\\bacula\\plugins\\vss-fd.dll\"");
+
+ my $ret="Ok\n";
+
+ copy("$bin_path/bacula-fd.exe",
+ "c:/Program Files/bacula/bacula-fd.exe") or $ret="ERR\n$!\n";
- copy("$base/bacula/src/win32/release32/bacula.dll",
- "c:/Program Files/bacula/bacula.dll");
+ copy("$bin_path/bacula.dll",
+ "c:/Program Files/bacula/bacula.dll") or $ret="ERR\n$!\n";
+
+ copy("$bin_path/vss-fd.dll",
+ "c:/Program Files/bacula/plugins/vss-fd.dll") or $ret="ERR\n$!\n";
+
+ start_fd();
+ return "OK\n";
}
# start the fd service
{
my ($r) = shift;
- if ($r->url !~ m!^/init_weird_runscript_test\?source=(\w:/[\w/]+)$!) {
- return "ERR\nIncorrect url\n";
+ if ($r->url !~ m!^/init_weird_runscript_test\?source=(\w:/[\w\d\-\./]+)$!) {
+ return "ERR\nIncorrect url: ". $r->url . "\n";
}
my $source = $1;
- if (!chdir($source)) {
+ # Create $source if needed
+ my $tmp = $source;
+ $tmp =~ s:/:\\:g;
+ system("mkdir $tmp");
+
+ if (!chdir($source)) {
return "ERR\nCan't access to $source $!\n";
}
copy("test.bat", "Éwith space") or return "ERR\n";
copy("testé.bat","Éwith space") or return "ERR\n";
copy("test2 space.bat", "Éwith space") or return "ERR\n";
+ mkdir("a"x200);
+ copy("test.bat", "a"x200);
+ system("mklink /J junc " . "a"x200); # TODO: need something for win2003
+ link("test.bat", "link.bat");
return "OK\n";
}
my ($r) = shift;
if ($r->url !~ m!^/init_attrib_test\?source=(\w:/[\w/]+)$!) {
- return "ERR\nIncorrect url\n";
+ return "ERR\nIncorrect url: " . $r->url . "\n";
}
my $source = $1;
+ system("mkdir $source");
if (!chdir($source)) {
return "ERR\nCan't access to $source $!\n";
}
}
+sub create_schedtask
+{
+ my ($r) = shift;
+ if ($r->url !~ m!^/create_schedtask\?name=([\w\d\-.]+)$!) {
+ return "ERR\nIncorrect url: " . $r->url . "\n";
+ }
+ my $ret='';
+ my ($task,$pass) = ($1, $2);
+ my (undef, undef, $version, undef) = POSIX::uname();
+ if ($version < 6) { # win2003
+ $ret = `echo pass | SCHTASKS /Create /TN $task /SC ONLOGON /TR C:\\windows\\system32\\calc.exe /F 2>&1`;
+ } else {
+ $ret=`SCHTASKS /Create /TN $task /SC ONLOGON /F /TR C:\\windows\\system32\\calc.exe`;
+ }
+
+ if ($ret =~ /SUCCESS|has been created/) {
+ return "OK\n$ret";
+ } else {
+ return "ERR\n$ret";
+ }
+#
+# SCHTASKS /Create [/S system [/U username [/P [password]]]]
+# [/RU username [/RP password]] /SC schedule [/MO modifier] [/D day]
+# [/M months] [/I idletime] /TN taskname /TR taskrun [/ST starttime]
+# [/RI interval] [ {/ET endtime | /DU duration} [/K] [/XML xmlfile] [/V1]]
+# [/SD startdate] [/ED enddate] [/IT | /NP] [/Z] [/F]
+}
+
+sub del_schedtask
+{
+ my ($r) = shift;
+ if ($r->url !~ m!^/del_schedtask\?name=([\w\d\-.]+)$!) {
+ return "ERR\nIncorrect url: " . $r->url . "\n";
+ }
+ my ($task) = ($1);
+ my $ret=`SCHTASKS /Delete /TN $task /F`;
+
+ if ($ret =~ /SUCCESS/) {
+ return "OK\n$ret";
+ } else {
+ return "ERR\n$ret";
+ }
+}
+
+sub check_schedtask
+{
+ my ($r) = shift;
+ if ($r->url !~ m!^/check_schedtask\?name=([\w\d\-.]+)$!) {
+ return "ERR\nIncorrect url: " . $r->url . "\n";
+ }
+
+ my ($task) = ($1);
+ my (undef, undef, $version, undef) = POSIX::uname();
+ my $ret;
+ if ($version < 6) { # win2003
+ $ret=`SCHTASKS /Query`;
+ } else {
+ $ret=`SCHTASKS /Query /TN $task`;
+ }
+
+ if ($ret =~ /^($task .+)$/m) {
+ return "OK\n$1\n";
+ } else {
+ return "ERR\n$ret";
+ }
+}
+
sub set_director_name
{
my ($r) = shift;
- if ($r->url !~ m!^/set_director_name\?name=([\w\d\.\-]+);pass=([\w\d+]+)$!)
+ if ($r->url !~ m!^/set_director_name\?name=([\w\d\.\-]+);pass=([\w\d+\-\.*]+)$!)
{
- return "ERR\nIncorrect url\n";
+ return "ERR\nIncorrect url: " . $r->url . "\n";
}
my ($name, $pass) = ($1, $2);
print NEW "${1}Name=$name$nb_dir\n";
} elsif ($l =~ /^(\s*)Password\s*=/ and $in_dir) {
print NEW "${1}Password=$pass\n";
+ } elsif ($l =~ /#(\s*Plugin.*)$/) {
+ print NEW $1;
} elsif ($l =~ /\s*}/ and $in_dir) {
print NEW $l;
$in_dir = 0;
move("$conf/bacula-fd.conf.new", "$conf/bacula-fd.conf")
and return "OK\n";
- return "ERR\n";
+ return "ERR\nCan't set the director name\n";
}
# convert \ to / and strip the path
my ($r) = shift;
if ($r->url !~ m!^/compare\?source=(\w:/[\w/]+);dest=(\w:/[\w/]+)$!) {
- return "ERR\nIncorrect url\n";
+ return "ERR\nIncorrect url: " . $r->url . "\n";
}
my ($source, $dest) = ($1, $2);
$dest_attrib = strip_base($dest_attrib, $dest);
if (lc($src_attrib) ne lc($dest_attrib)) {
+ print "ERR\n$src_attrib\n=========\n$dest_attrib\n";
return "ERR\n$src_attrib\n=========\n$dest_attrib\n";
}
my ($r) = shift;
if ($r->url !~ m!^/cleandir\?source=(\w:/[\w/]+)/restore$!) {
- return "ERR\nIncorrect url\n";
+ return "ERR\nIncorrect url: " . $r->url . "\n";
}
my $source = $1;
my ($r) = shift;
if ($r->url !~ m!^/set_service\?srv=([\w-]+);action=(\w+)$!) {
- return "ERR\nIncorrect url\n";
+ return "ERR\nIncorrect url: " . $r->url . "\n";
}
my $out = `sc config $1 start= $2`;
if ($out !~ /SUCCESS/) {
my ($r) = shift;
if ($r->url !~ m!^/get_service\?srv=([\w-]+);state=(\w+)$!) {
- return "ERR\nIncorrect url\n";
+ return "ERR\nIncorrect url: " . $r->url . "\n";
}
my $out = `sc query $1`;
if ($out !~ /$2/) {
{
my ($r) = shift;
if ($r->url !~ m!^/add_registry_key\?key=(\w+);val=(\w+)$!) {
- return "ERR\nIncorrect url\n";
+ return "ERR\nIncorrect url: " . $r->url . "\n";
}
my ($k, $v) = ($1,$2);
my $ret = "ERR";
sub set_auto_logon
{
my ($r) = shift;
- my $self = $0;
+ my $self = $0; # perl script location
$self =~ s/\\/\\\\/g;
- my $p = $^X;
+ my $p = $^X; # perl.exe location
$p =~ s/\\/\\\\/g;
- if ($r->url !~ m!^/set_auto_logon\?user=(\w+);pass=([\w\d\,:*+-]*)$!) {
- return "ERR\nIncorrect url\n";
+ if ($r->url !~ m!^/set_auto_logon\?user=([\w\d\-+\.]+);pass=([\w\d\.\,:*+%\-]*)$!) {
+ return "ERR\nIncorrect url: " . $r->url . "\n";
}
my $k = $1;
my $v = $2 || ''; # password can be empty
- my $ret = "ERR";
+ my $ret = "ERR\nCan't find AutoAdminLogon key\n";
open(FP, ">c:/autologon.reg")
- or return "ERR\nCan't open tmp.reg $!\n";
+ or return "ERR\nCan't open autologon.reg $!\n";
print FP "Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon]
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run]
\"regress\"=\"$p $self\"
+[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Reliability]
+\"ShutdownReasonUI\"=dword:00000000
+
+[HKEY_LOCAL_MACHINE\\SOFTWARE\\Policies\\Microsoft\\Windows NT\\Reliability]
+\"ShutdownReasonOn\"=dword:00000000
";
close(FP);
- system("regedit /s c:\autologon.reg");
+ system("regedit /s c:\\autologon.reg");
unlink("tmp2.reg");
system("regedit /e tmp2.reg \"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\"");
}
close(FP);
unlink("tmp2.reg");
- return "$ret\n";
+ return $ret;
}
sub del_registry_key
{
my ($r) = shift;
if ($r->url !~ m!^/del_registry_key\?key=(\w+)$!) {
- return "ERR\nIncorrect url\n";
+ return "ERR\nIncorrect url: " . $r->url . "\n";
}
my $k = $1;
- my $ret = "OK";
+ my $ret = "OK\n";
unlink("tmp2.reg");
open(FP, ">tmp.reg")
or return "ERR\nCan't open tmp2.reg $!\n";
while (my $l = <FP>) {
if ($l =~ /"$k"=/) {
- $ret = "ERR\n";
+ $ret = "ERR\nThe key $k is still present\n";
}
}
close(FP);
unlink("tmp.reg");
unlink("tmp2.reg");
- return "$ret\n";
+ return $ret;
}
sub get_registry_key
{
my ($r) = shift;
- my $ret = "ERR";
if ($r->url !~ m!^/get_registry_key\?key=(\w+);val=(\w+)$!) {
- return "ERR\nIncorrect url\n";
+ return "ERR\nIncorrect url: " . $r->url . "\n";
}
my ($k, $v) = ($1, $2);
+ my $ret = "ERR\nCan't get or verify registry key $k\n";
unlink("tmp2.reg");
system("regedit /e tmp2.reg HKEY_LOCAL_MACHINE\\SOFTWARE\\Bacula");
or return "ERR\nCan't open tmp2.reg $!\n";
while (my $l = <FP>) {
if ($l =~ /"$k"="$v"/) {
- $ret = "OK";
+ $ret = "OK\n";
}
}
close(FP);
unlink("tmp2.reg");
- return "$ret\n";
+ return $ret;
}
my $mssql_user;
my $mssql_pass;
+my $mssql_cred;
my $mssql_bin;
-use File::Find qw/find/;
sub find_mssql
{
if ($_ =~ /sqlcmd.exe/i) {
{
my ($r) = shift;
my $ret = "ERR";
- if ($r->url !~ m!^/check_mssql\?user=(\w+);pass=(.+)$!) {
- return "ERR\nIncorrect url\n";
+ if ($r->url !~ m!^/check_mssql\?user=(\w*);pass=(.*)$!) {
+ return "ERR\nIncorrect url: " . $r->url . "\n";
}
($mssql_user, $mssql_pass) = ($1, $2);
unless ($mssql_bin) {
find(\&find_mssql, 'c:/program files/microsoft sql server/');
}
+ unless ($mssql_bin) {
+ find(\&find_mssql, 'c:/program files (x86)/microsoft sql server/');
+ }
if (!$mssql_bin) {
- return "ERR\n";
+ return "ERR\nCan't find SQLCMD.exe in c:/program files\n";
}
print $mssql_bin, "\n";
-
- my $res = `"$mssql_bin" -U $mssql_user -P $mssql_pass -Q "SELECT 'OK';"`;
+ $mssql_cred = ($mssql_user)?"-U $mssql_user -P $mssql_pass":"";
+ my $res = `"$mssql_bin" $mssql_cred -Q "SELECT 'OK';"`;
if ($res !~ /OK/) {
- print "Can't run sql\n";
- return "ERR\n";
+ return "ERR\nCan't verify the SQLCMD result\n" .
+ "Please verify that MSSQL is accepting connection:\n" .
+ "$mssql_bin $mssql_cred -Q \"SELECT 1;\"\n";
}
return "OK\n";
}
my ($r) = shift;
my $ret = "ERR";
if ($r->url !~ m!^/setup_mssql_db\?db=([\w\d]+)$!) {
- return "ERR\nIncorrect url\n";
+ return "ERR\nIncorrect url: " . $r->url . "\n";
}
my $db = $1;
unless ($mssql_bin) {
- print "Can't find mssql bin\n";
- return "ERR\n";
+ return "ERR\nCan't find mssql bin (run check_mssql first)\n";
}
- my $res = `"$mssql_bin" -U $mssql_user -P $mssql_pass -Q "CREATE DATABASE $db;"`;
- $res = `"$mssql_bin" -U $mssql_user -P $mssql_pass -d $db -Q "CREATE TABLE table1 (a int, b int);"`;
- $res = `"$mssql_bin" -U $mssql_user -P $mssql_pass -d $db -Q "INSERT INTO table1 (a, b) VALUES (1,1);"`;
- $res = `"$mssql_bin" -U $mssql_user -P $mssql_pass -d $db -Q "SELECT 'OK' FROM table1;"`;
+ my $res = `"$mssql_bin" $mssql_cred -Q "CREATE DATABASE $db;"`;
+ $res = `"$mssql_bin" $mssql_cred -d $db -Q "CREATE TABLE table1 (a int, b int);"`;
+ $res = `"$mssql_bin" $mssql_cred -d $db -Q "INSERT INTO table1 (a, b) VALUES (1,1);"`;
+ $res = `"$mssql_bin" $mssql_cred -d $db -Q "SELECT 'OK' FROM table1;"`;
if ($res !~ /OK/) {
- print "Can't run sql\n";
- return "ERR\n";
+ return "ERR\nCan't verify the SQLCMD result\n" .
+ "Please verify that MSSQL is accepting connection:\n" .
+ "$mssql_bin $mssql_cred -Q \"SELECT 1;\"\n";
}
return "OK\n";
}
my ($r) = shift;
my $ret = "ERR";
if ($r->url !~ m!^/cleanup_mssql_db\?db=([\w\d]+)$!) {
- return "ERR\nIncorrect url\n";
+ return "ERR\nIncorrect url: " . $r->url . "\n";
}
my $db = $1;
unless ($mssql_bin) {
- print "Can't find mssql bin\n";
- return "ERR\n";
+ return "ERR\nCan't find mssql bin\n";
}
- my $res = `"$mssql_bin" -U $mssql_user -P $mssql_pass -Q "DROP DATABASE $db;"`;
+ my $res = `"$mssql_bin" $mssql_cred -Q "DROP DATABASE $db;"`;
return "OK\n";
}
my ($r) = shift;
my $ret = "ERR";
if ($r->url !~ m!^/truncate_mssql_table\?db=([\w\d]+)$!) {
- return "ERR\nIncorrect url\n";
+ return "ERR\nIncorrect url: " . $r->url . "\n";
}
my $db = $1;
unless ($mssql_bin) {
- print "Can't find mssql bin\n";
- return "ERR\n";
+ return "ERR\nCan't find mssql bin\n";
}
- my $res = `"$mssql_bin" -U $mssql_user -P $mssql_pass -d $db -Q "TRUNCATE TABLE table1;"`;
- $res = `"$mssql_bin" -U $mssql_user -P $mssql_pass -d $db -Q "SELECT 'OK' FROM table1;"`;
+ my $res = `"$mssql_bin" $mssql_cred -d $db -Q "TRUNCATE TABLE table1;"`;
+ $res = `"$mssql_bin" $mssql_cred -d $db -Q "SELECT 'OK' FROM table1;"`;
if ($res =~ /OK/) {
- print "Can't truncate\n";
- return "ERR\n";
+ return "ERR\nCan't truncate $db.table1\n";
}
return "OK\n";
}
my ($r) = shift;
my $ret = "ERR";
if ($r->url !~ m!^/test_mssql_content\?db=([\w\d]+)$!) {
- return "ERR\nIncorrect url\n";
+ return "ERR\nIncorrect url: " . $r->url . "\n";
}
my $db = $1;
unless ($mssql_bin) {
- print "Can't find mssql bin\n";
- return "ERR\n";
+ return "ERR\nCan't find mssql bin\n";
}
- my $res = `"$mssql_bin" -U $mssql_user -P $mssql_pass -d $db -Q "SELECT 'OK' FROM table1;"`;
+ my $res = `"$mssql_bin" $mssql_cred -d $db -Q "SELECT 'OK' FROM table1;"`;
if ($res !~ /OK/) {
- print "no content\n";
- return "ERR\n";
+ return "ERR\nNo content from $mssql_bin\n$res\n";
}
return "OK\n";
}
{
my ($r) = shift;
if ($r->url !~ m!^/online_mssql_db\?mdf=([\w\d]+);db=([\w\d]+)$!) {
- return "ERR\nIncorrect url\n";
+ return "ERR\nIncorrect url: " . $r->url . "\n";
}
my ($mdf, $db) = ($1, $2);
$mdf_to_find = "$mdf.mdf";
find(\&find_mdf, 'c:/program files/microsoft sql server/');
+ unless ($mssql_mdf) {
+ find(\&find_mssql, 'c:/program files (x86)/microsoft sql server/');
+ }
+ unless ($mssql_mdf) {
+ return "ERR\nCan't find $mdf.mdf in c:/program files\n";
+ }
$mssql_mdf =~ s:/:\\:g;
open(FP, ">c:/mssql.sql");
GO
";
close(FP);
- my $res = `"$mssql_bin" -U $mssql_user -P $mssql_pass -i c:\\mssql.sql`;
+ my $res = `"$mssql_bin" $mssql_cred -i c:\\mssql.sql`;
#unlink("c:/mssql.sql");
if ($res !~ /OK/) {
- print "no content\n";
- return "ERR\n";
+ return "ERR\nNo content from $mssql_bin\n";
+ }
+ return "OK\n";
+}
+
+# create a script c:/del.cmd to delete protected files with runscript
+sub remove_dir
+{
+ my ($r) = shift;
+ if ($r->url !~ m!^/remove_dir\?file=([\w\d:\/\.\-+*]+);dest=([\w\d\.:\/]+)$!) {
+ return "ERR\nIncorrect url: " . $r->url . "\n";
}
+ my ($file, $cmd) = ($1, $2);
+ $file =~ s:/:\\:g;
+
+ open(FP, ">$cmd") or return "ERR\nCan't open $file $!\n";
+ print FP "DEL /F /S /Q $file\n";
+ close(FP);
return "OK\n";
}
set_service => \&set_service,
get_service => \&get_service,
set_auto_logon => \&set_auto_logon,
+ remove_dir => \&remove_dir,
+ reload => \&reload,
+ create_schedtask => \&create_schedtask,
+ del_schedtask => \&del_schedtask,
+ check_schedtask => \&check_schedtask,
check_mssql => \&check_mssql,
setup_mssql_db => \&setup_mssql_db,
online_mssql_db => \&online_mssql_db,
);
+my $reload=0;
+sub reload
+{
+ $reload=1;
+ return "OK\n";
+}
+
# handle client request
sub handle_client
{
if (($r->method eq 'GET')
and $action_list{$action})
{
+ print "Exec $action:\n";
+
my $ret = $action_list{$action}($r);
my $h = HTTP::Headers->new('Content-Type' => 'text/plain') ;
my $r = HTTP::Response->new(HTTP::Status::RC_OK,
'OK', $h, $ret) ;
-
+ print $ret;
$c->send_response($r) ;
} else {
+ print "$action not found, probably a version problem\n";
$c->send_error(RC_NOT_FOUND) ;
}
$c->close;
}
+print "Starting regress-win32.pl daemon...\n";
my $d = HTTP::Daemon->new ( LocalPort => 8091,
ReuseAddr => 1)
|| die "Error: Can't bind $!" ;
my $olddir = Cwd::cwd();
while (1) {
- print "Starting daemon...\n";
my $c = $d->accept ;
my $ip = $c->peerhost;
if (!$ip) {
$c->send_error(RC_FORBIDDEN) ;
}
close($c) ;
+ undef $c;
chdir($olddir);
+
+ # When we have the reload command, just close the http daemon
+ # and exec ourself
+ if ($reload) {
+ $d->close();
+ undef $d;
+
+ exec("$^X $0");
+ }
}