1*cdf0e10cSrcweir#************************************************************************* 2*cdf0e10cSrcweir# 3*cdf0e10cSrcweir# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir# 5*cdf0e10cSrcweir# Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir# 7*cdf0e10cSrcweir# OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir# 9*cdf0e10cSrcweir# This file is part of OpenOffice.org. 10*cdf0e10cSrcweir# 11*cdf0e10cSrcweir# OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir# it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir# only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir# 15*cdf0e10cSrcweir# OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir# but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir# GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir# (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir# 21*cdf0e10cSrcweir# You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir# version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir# <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir# for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir# 26*cdf0e10cSrcweir#************************************************************************* 27*cdf0e10cSrcweir 28*cdf0e10cSrcweiruse Cwd; 29*cdf0e10cSrcweiruse File::Copy; 30*cdf0e10cSrcweir 31*cdf0e10cSrcweir################################################################################# 32*cdf0e10cSrcweir# Global settings 33*cdf0e10cSrcweir################################################################################# 34*cdf0e10cSrcweir 35*cdf0e10cSrcweirBEGIN 36*cdf0e10cSrcweir{ 37*cdf0e10cSrcweir $prog = "msi installer"; 38*cdf0e10cSrcweir $targetdir = ""; 39*cdf0e10cSrcweir $databasepath = ""; 40*cdf0e10cSrcweir $starttime = ""; 41*cdf0e10cSrcweir $globaltempdirname = "ooopackaging"; 42*cdf0e10cSrcweir $savetemppath = ""; 43*cdf0e10cSrcweir $msiinfo_available = 0; 44*cdf0e10cSrcweir $path_displayed = 0; 45*cdf0e10cSrcweir $localmsidbpath = ""; 46*cdf0e10cSrcweir 47*cdf0e10cSrcweir $plat = $^O; 48*cdf0e10cSrcweir 49*cdf0e10cSrcweir if ( $plat =~ /cygwin/i ) 50*cdf0e10cSrcweir { 51*cdf0e10cSrcweir $separator = "/"; 52*cdf0e10cSrcweir $pathseparator = "\:"; 53*cdf0e10cSrcweir } 54*cdf0e10cSrcweir else 55*cdf0e10cSrcweir { 56*cdf0e10cSrcweir $separator = "\\"; 57*cdf0e10cSrcweir $pathseparator = "\;"; 58*cdf0e10cSrcweir } 59*cdf0e10cSrcweir} 60*cdf0e10cSrcweir 61*cdf0e10cSrcweir################################################################################# 62*cdf0e10cSrcweir# Program information 63*cdf0e10cSrcweir################################################################################# 64*cdf0e10cSrcweir 65*cdf0e10cSrcweirsub usage 66*cdf0e10cSrcweir{ 67*cdf0e10cSrcweir print <<Ende; 68*cdf0e10cSrcweir---------------------------------------------------------------------- 69*cdf0e10cSrcweirThis program installs a Windows Installer installation set 70*cdf0e10cSrcweirwithout using msiexec.exe. The installation is comparable 71*cdf0e10cSrcweirwith an administrative installation using the Windows Installer 72*cdf0e10cSrcweirservice. 73*cdf0e10cSrcweirRequired parameter: 74*cdf0e10cSrcweir-d Path to installation set or msi database 75*cdf0e10cSrcweir-t Target directory 76*cdf0e10cSrcweir--------------------------------------------------------------------- 77*cdf0e10cSrcweirEnde 78*cdf0e10cSrcweir exit(-1); 79*cdf0e10cSrcweir} 80*cdf0e10cSrcweir 81*cdf0e10cSrcweir################################################################################# 82*cdf0e10cSrcweir# Collecting parameter 83*cdf0e10cSrcweir################################################################################# 84*cdf0e10cSrcweir 85*cdf0e10cSrcweirsub getparameter 86*cdf0e10cSrcweir{ 87*cdf0e10cSrcweir if (( $#ARGV < 3 ) || ( $#ARGV > 3 )) { usage(); } 88*cdf0e10cSrcweir 89*cdf0e10cSrcweir while ( $#ARGV >= 0 ) 90*cdf0e10cSrcweir { 91*cdf0e10cSrcweir my $param = shift(@ARGV); 92*cdf0e10cSrcweir 93*cdf0e10cSrcweir if ($param eq "-t") { $targetdir = shift(@ARGV); } 94*cdf0e10cSrcweir elsif ($param eq "-d") { $databasepath = shift(@ARGV); } 95*cdf0e10cSrcweir else 96*cdf0e10cSrcweir { 97*cdf0e10cSrcweir print "\n**********************************************\n"; 98*cdf0e10cSrcweir print "Error: Unknows parameter: $param"; 99*cdf0e10cSrcweir print "\n**********************************************\n"; 100*cdf0e10cSrcweir usage(); 101*cdf0e10cSrcweir exit(-1); 102*cdf0e10cSrcweir } 103*cdf0e10cSrcweir } 104*cdf0e10cSrcweir} 105*cdf0e10cSrcweir 106*cdf0e10cSrcweir################################################################################# 107*cdf0e10cSrcweir# Checking content of parameter 108*cdf0e10cSrcweir################################################################################# 109*cdf0e10cSrcweir 110*cdf0e10cSrcweirsub controlparameter 111*cdf0e10cSrcweir{ 112*cdf0e10cSrcweir if ( $targetdir eq "" ) 113*cdf0e10cSrcweir { 114*cdf0e10cSrcweir print "\n******************************************************\n"; 115*cdf0e10cSrcweir print "Error: Target directory not defined (parameter -t)!"; 116*cdf0e10cSrcweir print "\n******************************************************\n"; 117*cdf0e10cSrcweir usage(); 118*cdf0e10cSrcweir exit(-1); 119*cdf0e10cSrcweir } 120*cdf0e10cSrcweir 121*cdf0e10cSrcweir if ( $databasepath eq "" ) 122*cdf0e10cSrcweir { 123*cdf0e10cSrcweir print "\n******************************************************\n"; 124*cdf0e10cSrcweir print "Error: Path to msi database not defined (parameter -d)!"; 125*cdf0e10cSrcweir print "\n******************************************************\n"; 126*cdf0e10cSrcweir usage(); 127*cdf0e10cSrcweir exit(-1); 128*cdf0e10cSrcweir } 129*cdf0e10cSrcweir 130*cdf0e10cSrcweir if ( -d $databasepath ) 131*cdf0e10cSrcweir { 132*cdf0e10cSrcweir $databasepath =~ s/\\\s*$//; 133*cdf0e10cSrcweir $databasepath =~ s/\/\s*$//; 134*cdf0e10cSrcweir 135*cdf0e10cSrcweir my $msifiles = find_file_with_file_extension("msi", $databasepath); 136*cdf0e10cSrcweir 137*cdf0e10cSrcweir if ( $#{$msifiles} < 0 ) { exit_program("ERROR: Did not find msi database in directory $installationdir"); } 138*cdf0e10cSrcweir if ( $#{$msifiles} > 0 ) { exit_program("ERROR: Did find more than one msi database in directory $installationdir"); } 139*cdf0e10cSrcweir 140*cdf0e10cSrcweir $databasepath = $databasepath . $separator . ${$msifiles}[0]; 141*cdf0e10cSrcweir } 142*cdf0e10cSrcweir 143*cdf0e10cSrcweir if ( ! -f $databasepath ) { exit_program("ERROR: Did not find msi database in directory $databasepath."); } 144*cdf0e10cSrcweir 145*cdf0e10cSrcweir if ( ! -d $targetdir ) { create_directories($targetdir); } 146*cdf0e10cSrcweir} 147*cdf0e10cSrcweir 148*cdf0e10cSrcweir############################################################################# 149*cdf0e10cSrcweir# The program msidb.exe can be located next to the Perl program. Then it is 150*cdf0e10cSrcweir# not neccessary to find it in the PATH variable. 151*cdf0e10cSrcweir############################################################################# 152*cdf0e10cSrcweir 153*cdf0e10cSrcweirsub check_local_msidb 154*cdf0e10cSrcweir{ 155*cdf0e10cSrcweir my $msidbname = "msidb.exe"; 156*cdf0e10cSrcweir my $perlprogramm = $0; 157*cdf0e10cSrcweir my $path = $perlprogramm; 158*cdf0e10cSrcweir 159*cdf0e10cSrcweir get_path_from_fullqualifiedname(\$path); 160*cdf0e10cSrcweir 161*cdf0e10cSrcweir $path =~ s/\\\s*$//; 162*cdf0e10cSrcweir $path =~ s/\/\s*$//; 163*cdf0e10cSrcweir 164*cdf0e10cSrcweir my $msidbpath = ""; 165*cdf0e10cSrcweir if ( $path =~ /^\s*$/ ) { $msidbpath = $msidbname; } 166*cdf0e10cSrcweir else { $msidbpath = $path . $separator . $msidbname; } 167*cdf0e10cSrcweir 168*cdf0e10cSrcweir if ( -f $msidbpath ) 169*cdf0e10cSrcweir { 170*cdf0e10cSrcweir $localmsidbpath = $msidbpath; 171*cdf0e10cSrcweir print "Using $msidbpath (next to \"admin.pl\")\n"; 172*cdf0e10cSrcweir } 173*cdf0e10cSrcweir} 174*cdf0e10cSrcweir 175*cdf0e10cSrcweir############################################################################# 176*cdf0e10cSrcweir# Converting a string list with separator $listseparator 177*cdf0e10cSrcweir# into an array 178*cdf0e10cSrcweir############################################################################# 179*cdf0e10cSrcweir 180*cdf0e10cSrcweirsub convert_stringlist_into_array 181*cdf0e10cSrcweir{ 182*cdf0e10cSrcweir my ( $includestringref, $listseparator ) = @_; 183*cdf0e10cSrcweir 184*cdf0e10cSrcweir my @newarray = (); 185*cdf0e10cSrcweir my $first; 186*cdf0e10cSrcweir my $last = ${$includestringref}; 187*cdf0e10cSrcweir 188*cdf0e10cSrcweir while ( $last =~ /^\s*(.+?)\Q$listseparator\E(.+)\s*$/) # "$" for minimal matching 189*cdf0e10cSrcweir { 190*cdf0e10cSrcweir $first = $1; 191*cdf0e10cSrcweir $last = $2; 192*cdf0e10cSrcweir # Problem with two directly following listseparators. For example a path with two ";;" directly behind each other 193*cdf0e10cSrcweir $first =~ s/^$listseparator//; 194*cdf0e10cSrcweir push(@newarray, "$first\n"); 195*cdf0e10cSrcweir } 196*cdf0e10cSrcweir 197*cdf0e10cSrcweir push(@newarray, "$last\n"); 198*cdf0e10cSrcweir 199*cdf0e10cSrcweir return \@newarray; 200*cdf0e10cSrcweir} 201*cdf0e10cSrcweir 202*cdf0e10cSrcweir######################################################### 203*cdf0e10cSrcweir# Checking the local system 204*cdf0e10cSrcweir# Checking existence of needed files in include path 205*cdf0e10cSrcweir######################################################### 206*cdf0e10cSrcweir 207*cdf0e10cSrcweirsub check_system_path 208*cdf0e10cSrcweir{ 209*cdf0e10cSrcweir my $onefile; 210*cdf0e10cSrcweir my $error = 0; 211*cdf0e10cSrcweir my $pathvariable = $ENV{'PATH'}; 212*cdf0e10cSrcweir my $local_pathseparator = $pathseparator; 213*cdf0e10cSrcweir 214*cdf0e10cSrcweir if( $^O =~ /cygwin/i ) 215*cdf0e10cSrcweir { # When using cygwin's perl the PATH variable is POSIX style and ... 216*cdf0e10cSrcweir $pathvariable = qx{cygpath -mp "$pathvariable"} ; 217*cdf0e10cSrcweir # has to be converted to DOS style for further use. 218*cdf0e10cSrcweir $local_pathseparator = ';'; 219*cdf0e10cSrcweir } 220*cdf0e10cSrcweir my $patharrayref = convert_stringlist_into_array(\$pathvariable, $local_pathseparator); 221*cdf0e10cSrcweir 222*cdf0e10cSrcweir my @needed_files_in_path = ("expand.exe"); 223*cdf0e10cSrcweir if ( $localmsidbpath eq "" ) { push(@needed_files_in_path, "msidb.exe"); } # not found locally -> search in path 224*cdf0e10cSrcweir my @optional_files_in_path = ("msiinfo.exe"); 225*cdf0e10cSrcweir 226*cdf0e10cSrcweir print("\nChecking required files:\n"); 227*cdf0e10cSrcweir 228*cdf0e10cSrcweir foreach $onefile ( @needed_files_in_path ) 229*cdf0e10cSrcweir { 230*cdf0e10cSrcweir print("...... searching $onefile ..."); 231*cdf0e10cSrcweir 232*cdf0e10cSrcweir my $fileref = get_sourcepath_from_filename_and_includepath(\$onefile, $patharrayref); 233*cdf0e10cSrcweir 234*cdf0e10cSrcweir if ( $$fileref eq "" ) 235*cdf0e10cSrcweir { 236*cdf0e10cSrcweir $error = 1; 237*cdf0e10cSrcweir print( "$onefile not found\n" ); 238*cdf0e10cSrcweir } 239*cdf0e10cSrcweir else 240*cdf0e10cSrcweir { 241*cdf0e10cSrcweir print( "\tFound: $$fileref\n" ); 242*cdf0e10cSrcweir } 243*cdf0e10cSrcweir } 244*cdf0e10cSrcweir 245*cdf0e10cSrcweir if ( $error ) { exit_program("ERROR: Could not find all needed files in path (using setsolar should help)!"); } 246*cdf0e10cSrcweir 247*cdf0e10cSrcweir print("\nChecking optional files:\n"); 248*cdf0e10cSrcweir 249*cdf0e10cSrcweir foreach $onefile ( @optional_files_in_path ) 250*cdf0e10cSrcweir { 251*cdf0e10cSrcweir print("...... searching $onefile ..."); 252*cdf0e10cSrcweir 253*cdf0e10cSrcweir my $fileref = get_sourcepath_from_filename_and_includepath(\$onefile, $patharrayref); 254*cdf0e10cSrcweir 255*cdf0e10cSrcweir if ( $$fileref eq "" ) 256*cdf0e10cSrcweir { 257*cdf0e10cSrcweir print( "$onefile not found\n" ); 258*cdf0e10cSrcweir if ( $onefile eq "msiinfo.exe" ) { $msiinfo_available = 0; } 259*cdf0e10cSrcweir } 260*cdf0e10cSrcweir else 261*cdf0e10cSrcweir { 262*cdf0e10cSrcweir print( "\tFound: $$fileref\n" ); 263*cdf0e10cSrcweir if ( $onefile eq "msiinfo.exe" ) { $msiinfo_available = 1; } 264*cdf0e10cSrcweir } 265*cdf0e10cSrcweir } 266*cdf0e10cSrcweir 267*cdf0e10cSrcweir} 268*cdf0e10cSrcweir 269*cdf0e10cSrcweir########################################################################## 270*cdf0e10cSrcweir# Searching a file in a list of pathes 271*cdf0e10cSrcweir########################################################################## 272*cdf0e10cSrcweir 273*cdf0e10cSrcweirsub get_sourcepath_from_filename_and_includepath 274*cdf0e10cSrcweir{ 275*cdf0e10cSrcweir my ($searchfilenameref, $includepatharrayref) = @_; 276*cdf0e10cSrcweir 277*cdf0e10cSrcweir my $onefile = ""; 278*cdf0e10cSrcweir my $foundsourcefile = 0; 279*cdf0e10cSrcweir 280*cdf0e10cSrcweir for ( my $j = 0; $j <= $#{$includepatharrayref}; $j++ ) 281*cdf0e10cSrcweir { 282*cdf0e10cSrcweir my $includepath = ${$includepatharrayref}[$j]; 283*cdf0e10cSrcweir $includepath =~ s/^\s*//; 284*cdf0e10cSrcweir $includepath =~ s/\s*$//; 285*cdf0e10cSrcweir 286*cdf0e10cSrcweir $onefile = $includepath . $separator . $$searchfilenameref; 287*cdf0e10cSrcweir 288*cdf0e10cSrcweir if ( -f $onefile ) 289*cdf0e10cSrcweir { 290*cdf0e10cSrcweir $foundsourcefile = 1; 291*cdf0e10cSrcweir last; 292*cdf0e10cSrcweir } 293*cdf0e10cSrcweir } 294*cdf0e10cSrcweir 295*cdf0e10cSrcweir if (!($foundsourcefile)) { $onefile = ""; } 296*cdf0e10cSrcweir 297*cdf0e10cSrcweir return \$onefile; 298*cdf0e10cSrcweir} 299*cdf0e10cSrcweir 300*cdf0e10cSrcweir############################################################## 301*cdf0e10cSrcweir# Removing all empty directories below a specified directory 302*cdf0e10cSrcweir############################################################## 303*cdf0e10cSrcweir 304*cdf0e10cSrcweirsub remove_empty_dirs_in_folder 305*cdf0e10cSrcweir{ 306*cdf0e10cSrcweir my ( $dir, $firstrun ) = @_; 307*cdf0e10cSrcweir 308*cdf0e10cSrcweir if ( $firstrun ) 309*cdf0e10cSrcweir { 310*cdf0e10cSrcweir print "Removing superfluous directories\n"; 311*cdf0e10cSrcweir } 312*cdf0e10cSrcweir 313*cdf0e10cSrcweir my @content = (); 314*cdf0e10cSrcweir 315*cdf0e10cSrcweir $dir =~ s/\Q$separator\E\s*$//; 316*cdf0e10cSrcweir 317*cdf0e10cSrcweir if ( -d $dir ) 318*cdf0e10cSrcweir { 319*cdf0e10cSrcweir opendir(DIR, $dir); 320*cdf0e10cSrcweir @content = readdir(DIR); 321*cdf0e10cSrcweir closedir(DIR); 322*cdf0e10cSrcweir 323*cdf0e10cSrcweir my $oneitem; 324*cdf0e10cSrcweir 325*cdf0e10cSrcweir foreach $oneitem (@content) 326*cdf0e10cSrcweir { 327*cdf0e10cSrcweir if ((!($oneitem eq ".")) && (!($oneitem eq ".."))) 328*cdf0e10cSrcweir { 329*cdf0e10cSrcweir my $item = $dir . $separator . $oneitem; 330*cdf0e10cSrcweir 331*cdf0e10cSrcweir if ( -d $item ) # recursive 332*cdf0e10cSrcweir { 333*cdf0e10cSrcweir remove_empty_dirs_in_folder($item, 0); 334*cdf0e10cSrcweir } 335*cdf0e10cSrcweir } 336*cdf0e10cSrcweir } 337*cdf0e10cSrcweir 338*cdf0e10cSrcweir # try to remove empty directory 339*cdf0e10cSrcweir my $returnvalue = rmdir $dir; 340*cdf0e10cSrcweir 341*cdf0e10cSrcweir # if ( $returnvalue ) { print "Successfully removed empty dir $dir\n"; } 342*cdf0e10cSrcweir } 343*cdf0e10cSrcweir} 344*cdf0e10cSrcweir 345*cdf0e10cSrcweir#################################################### 346*cdf0e10cSrcweir# Detecting the directory with extensions 347*cdf0e10cSrcweir#################################################### 348*cdf0e10cSrcweir 349*cdf0e10cSrcweirsub get_extensions_dir 350*cdf0e10cSrcweir{ 351*cdf0e10cSrcweir my ( $unopkgfile ) = @_; 352*cdf0e10cSrcweir 353*cdf0e10cSrcweir my $localbranddir = $unopkgfile; 354*cdf0e10cSrcweir get_path_from_fullqualifiedname(\$localbranddir); # "program" dir in brand layer 355*cdf0e10cSrcweir get_path_from_fullqualifiedname(\$localbranddir); # root dir in brand layer 356*cdf0e10cSrcweir $localbranddir =~ s/\Q$separator\E\s*$//; 357*cdf0e10cSrcweir my $extensiondir = $localbranddir . $separator . "share" . $separator . "extensions"; 358*cdf0e10cSrcweir my $preregdir = $localbranddir . $separator . "share" . $separator . "prereg" . $separator . "bundled"; 359*cdf0e10cSrcweir 360*cdf0e10cSrcweir return ($extensiondir, $preregdir); 361*cdf0e10cSrcweir} 362*cdf0e10cSrcweir 363*cdf0e10cSrcweir######################################################## 364*cdf0e10cSrcweir# Finding all files with a specified file extension 365*cdf0e10cSrcweir# in a specified directory. 366*cdf0e10cSrcweir######################################################## 367*cdf0e10cSrcweir 368*cdf0e10cSrcweirsub find_file_with_file_extension 369*cdf0e10cSrcweir{ 370*cdf0e10cSrcweir my ($extension, $dir) = @_; 371*cdf0e10cSrcweir 372*cdf0e10cSrcweir my @allfiles = (); 373*cdf0e10cSrcweir my @sourcefiles = (); 374*cdf0e10cSrcweir 375*cdf0e10cSrcweir $dir =~ s/\Q$separator\E\s*$//; 376*cdf0e10cSrcweir 377*cdf0e10cSrcweir opendir(DIR, $dir); 378*cdf0e10cSrcweir @sourcefiles = readdir(DIR); 379*cdf0e10cSrcweir closedir(DIR); 380*cdf0e10cSrcweir 381*cdf0e10cSrcweir my $onefile; 382*cdf0e10cSrcweir 383*cdf0e10cSrcweir foreach $onefile (@sourcefiles) 384*cdf0e10cSrcweir { 385*cdf0e10cSrcweir if ((!($onefile eq ".")) && (!($onefile eq ".."))) 386*cdf0e10cSrcweir { 387*cdf0e10cSrcweir if ( $onefile =~ /^\s*(\S.*?)\.$extension\s*$/ ) 388*cdf0e10cSrcweir { 389*cdf0e10cSrcweir push(@allfiles, $onefile) 390*cdf0e10cSrcweir } 391*cdf0e10cSrcweir } 392*cdf0e10cSrcweir } 393*cdf0e10cSrcweir 394*cdf0e10cSrcweir return \@allfiles; 395*cdf0e10cSrcweir} 396*cdf0e10cSrcweir 397*cdf0e10cSrcweir############################################################## 398*cdf0e10cSrcweir# Creating a directory with all parent directories 399*cdf0e10cSrcweir############################################################## 400*cdf0e10cSrcweir 401*cdf0e10cSrcweirsub create_directories 402*cdf0e10cSrcweir{ 403*cdf0e10cSrcweir my ($directory) = @_; 404*cdf0e10cSrcweir 405*cdf0e10cSrcweir if ( ! try_to_create_directory($directory) ) 406*cdf0e10cSrcweir { 407*cdf0e10cSrcweir my $parentdir = $directory; 408*cdf0e10cSrcweir get_path_from_fullqualifiedname(\$parentdir); 409*cdf0e10cSrcweir create_directories($parentdir); # recursive 410*cdf0e10cSrcweir } 411*cdf0e10cSrcweir 412*cdf0e10cSrcweir create_directory($directory); # now it has to succeed 413*cdf0e10cSrcweir} 414*cdf0e10cSrcweir 415*cdf0e10cSrcweir############################################################## 416*cdf0e10cSrcweir# Creating one directory 417*cdf0e10cSrcweir############################################################## 418*cdf0e10cSrcweir 419*cdf0e10cSrcweirsub create_directory 420*cdf0e10cSrcweir{ 421*cdf0e10cSrcweir my ($directory) = @_; 422*cdf0e10cSrcweir 423*cdf0e10cSrcweir if ( ! -d $directory ) { mkdir($directory, 0775); } 424*cdf0e10cSrcweir} 425*cdf0e10cSrcweir 426*cdf0e10cSrcweir############################################################## 427*cdf0e10cSrcweir# Trying to create a directory, no error if this fails 428*cdf0e10cSrcweir############################################################## 429*cdf0e10cSrcweir 430*cdf0e10cSrcweirsub try_to_create_directory 431*cdf0e10cSrcweir{ 432*cdf0e10cSrcweir my ($directory) = @_; 433*cdf0e10cSrcweir 434*cdf0e10cSrcweir my $returnvalue = 1; 435*cdf0e10cSrcweir my $created_directory = 0; 436*cdf0e10cSrcweir 437*cdf0e10cSrcweir if (!(-d $directory)) 438*cdf0e10cSrcweir { 439*cdf0e10cSrcweir $returnvalue = mkdir($directory, 0775); 440*cdf0e10cSrcweir 441*cdf0e10cSrcweir if ($returnvalue) 442*cdf0e10cSrcweir { 443*cdf0e10cSrcweir $created_directory = 1; 444*cdf0e10cSrcweir 445*cdf0e10cSrcweir my $localcall = "chmod 775 $directory \>\/dev\/null 2\>\&1"; 446*cdf0e10cSrcweir system($localcall); 447*cdf0e10cSrcweir } 448*cdf0e10cSrcweir else 449*cdf0e10cSrcweir { 450*cdf0e10cSrcweir $created_directory = 0; 451*cdf0e10cSrcweir } 452*cdf0e10cSrcweir } 453*cdf0e10cSrcweir else 454*cdf0e10cSrcweir { 455*cdf0e10cSrcweir $created_directory = 1; 456*cdf0e10cSrcweir } 457*cdf0e10cSrcweir 458*cdf0e10cSrcweir return $created_directory; 459*cdf0e10cSrcweir} 460*cdf0e10cSrcweir 461*cdf0e10cSrcweir########################################### 462*cdf0e10cSrcweir# Getting path from full file name 463*cdf0e10cSrcweir########################################### 464*cdf0e10cSrcweir 465*cdf0e10cSrcweirsub get_path_from_fullqualifiedname 466*cdf0e10cSrcweir{ 467*cdf0e10cSrcweir my ($longfilenameref) = @_; 468*cdf0e10cSrcweir 469*cdf0e10cSrcweir if ( $$longfilenameref =~ /\Q$separator\E/ ) # Is there a separator in the path? Otherwise the path is empty. 470*cdf0e10cSrcweir { 471*cdf0e10cSrcweir if ( $$longfilenameref =~ /^\s*(\S.*\Q$separator\E)(\S.+\S?)/ ) 472*cdf0e10cSrcweir { 473*cdf0e10cSrcweir $$longfilenameref = $1; 474*cdf0e10cSrcweir } 475*cdf0e10cSrcweir } 476*cdf0e10cSrcweir else 477*cdf0e10cSrcweir { 478*cdf0e10cSrcweir $$longfilenameref = ""; # there is no path 479*cdf0e10cSrcweir } 480*cdf0e10cSrcweir} 481*cdf0e10cSrcweir 482*cdf0e10cSrcweir############################################################## 483*cdf0e10cSrcweir# Getting file name from full file name 484*cdf0e10cSrcweir############################################################## 485*cdf0e10cSrcweir 486*cdf0e10cSrcweirsub make_absolute_filename_to_relative_filename 487*cdf0e10cSrcweir{ 488*cdf0e10cSrcweir my ($longfilenameref) = @_; 489*cdf0e10cSrcweir 490*cdf0e10cSrcweir # Either '/' or '\'. 491*cdf0e10cSrcweir if ( $$longfilenameref =~ /^.*[\/\\](\S.+\S?)/ ) 492*cdf0e10cSrcweir { 493*cdf0e10cSrcweir $$longfilenameref = $1; 494*cdf0e10cSrcweir } 495*cdf0e10cSrcweir} 496*cdf0e10cSrcweir 497*cdf0e10cSrcweir############################################ 498*cdf0e10cSrcweir# Exiting the program with an error 499*cdf0e10cSrcweir# This function is used instead of "die" 500*cdf0e10cSrcweir############################################ 501*cdf0e10cSrcweir 502*cdf0e10cSrcweirsub exit_program 503*cdf0e10cSrcweir{ 504*cdf0e10cSrcweir my ($message) = @_; 505*cdf0e10cSrcweir 506*cdf0e10cSrcweir print "\n***************************************************************\n"; 507*cdf0e10cSrcweir print "$message\n"; 508*cdf0e10cSrcweir print "***************************************************************\n"; 509*cdf0e10cSrcweir remove_complete_directory($savetemppath, 1); 510*cdf0e10cSrcweir print "\n" . get_time_string(); 511*cdf0e10cSrcweir exit(-1); 512*cdf0e10cSrcweir} 513*cdf0e10cSrcweir 514*cdf0e10cSrcweir################################################################################# 515*cdf0e10cSrcweir# Unpacking cabinet files with expand 516*cdf0e10cSrcweir################################################################################# 517*cdf0e10cSrcweir 518*cdf0e10cSrcweirsub unpack_cabinet_file 519*cdf0e10cSrcweir{ 520*cdf0e10cSrcweir my ($cabfilename, $unpackdir) = @_; 521*cdf0e10cSrcweir 522*cdf0e10cSrcweir my $expandfile = "expand.exe"; # has to be in the PATH 523*cdf0e10cSrcweir 524*cdf0e10cSrcweir # expand.exe has to be located in the system directory. 525*cdf0e10cSrcweir # Cygwin has another tool expand.exe, that converts tabs to spaces. This cannot be used of course. 526*cdf0e10cSrcweir # But this wrong expand.exe is typically in the PATH before this expand.exe, to unpack 527*cdf0e10cSrcweir # cabinet files. 528*cdf0e10cSrcweir 529*cdf0e10cSrcweir if ( $^O =~ /cygwin/i ) 530*cdf0e10cSrcweir { 531*cdf0e10cSrcweir $expandfile = $ENV{'SYSTEMROOT'} . "/system32/expand.exe"; # Has to be located in the systemdirectory 532*cdf0e10cSrcweir $expandfile =~ s/\\/\//; 533*cdf0e10cSrcweir if ( ! -f $expandfile ) { exit_program("ERROR: Did not find file $expandfile in the Windows system folder!"); } 534*cdf0e10cSrcweir } 535*cdf0e10cSrcweir 536*cdf0e10cSrcweir my $expandlogfile = $unpackdir . $separator . "expand.log"; 537*cdf0e10cSrcweir 538*cdf0e10cSrcweir # exclude cabinet file 539*cdf0e10cSrcweir # my $systemcall = $cabarc . " -o X " . $mergemodulehash->{'cabinetfile'}; 540*cdf0e10cSrcweir 541*cdf0e10cSrcweir my $systemcall = ""; 542*cdf0e10cSrcweir if ( $^O =~ /cygwin/i ) { 543*cdf0e10cSrcweir my $localunpackdir = qx{cygpath -w "$unpackdir"}; 544*cdf0e10cSrcweir $localunpackdir =~ s/\\/\\\\/g; 545*cdf0e10cSrcweir 546*cdf0e10cSrcweir my $localcabfilename = qx{cygpath -w "$cabfilename"}; 547*cdf0e10cSrcweir $localcabfilename =~ s/\\/\\\\/g; 548*cdf0e10cSrcweir $localcabfilename =~ s/\s*$//g; 549*cdf0e10cSrcweir 550*cdf0e10cSrcweir $systemcall = $expandfile . " " . $localcabfilename . " -F:\* " . $localunpackdir . " \>\/dev\/null 2\>\&1"; 551*cdf0e10cSrcweir } 552*cdf0e10cSrcweir else 553*cdf0e10cSrcweir { 554*cdf0e10cSrcweir $systemcall = $expandfile . " " . $cabfilename . " -F:\* " . $unpackdir . " \> " . $expandlogfile; 555*cdf0e10cSrcweir } 556*cdf0e10cSrcweir 557*cdf0e10cSrcweir my $returnvalue = system($systemcall); 558*cdf0e10cSrcweir 559*cdf0e10cSrcweir if ($returnvalue) { exit_program("ERROR: Could not execute $systemcall !"); } 560*cdf0e10cSrcweir} 561*cdf0e10cSrcweir 562*cdf0e10cSrcweir################################################################################# 563*cdf0e10cSrcweir# Extracting tables from msi database 564*cdf0e10cSrcweir################################################################################# 565*cdf0e10cSrcweir 566*cdf0e10cSrcweirsub extract_tables_from_database 567*cdf0e10cSrcweir{ 568*cdf0e10cSrcweir my ($fullmsidatabasepath, $workdir, $tablelist) = @_; 569*cdf0e10cSrcweir 570*cdf0e10cSrcweir my $msidb = "msidb.exe"; # Has to be in the path 571*cdf0e10cSrcweir if ( $localmsidbpath ) { $msidb = $localmsidbpath; } 572*cdf0e10cSrcweir my $infoline = ""; 573*cdf0e10cSrcweir my $systemcall = ""; 574*cdf0e10cSrcweir my $returnvalue = ""; 575*cdf0e10cSrcweir 576*cdf0e10cSrcweir if ( $^O =~ /cygwin/i ) { 577*cdf0e10cSrcweir chomp( $fullmsidatabasepath = qx{cygpath -w "$fullmsidatabasepath"} ); 578*cdf0e10cSrcweir # msidb.exe really wants backslashes. (And double escaping because system() expands the string.) 579*cdf0e10cSrcweir $fullmsidatabasepath =~ s/\\/\\\\/g; 580*cdf0e10cSrcweir $workdir =~ s/\\/\\\\/g; 581*cdf0e10cSrcweir # and if there are still slashes, they also need to be double backslash 582*cdf0e10cSrcweir $fullmsidatabasepath =~ s/\//\\\\/g; 583*cdf0e10cSrcweir $workdir =~ s/\//\\\\/g; 584*cdf0e10cSrcweir } 585*cdf0e10cSrcweir 586*cdf0e10cSrcweir # Export of all tables by using "*" 587*cdf0e10cSrcweir 588*cdf0e10cSrcweir $systemcall = $msidb . " -d " . $fullmsidatabasepath . " -f " . $workdir . " -e $tablelist"; 589*cdf0e10cSrcweir print "\nAnalyzing msi database\n"; 590*cdf0e10cSrcweir $returnvalue = system($systemcall); 591*cdf0e10cSrcweir 592*cdf0e10cSrcweir if ($returnvalue) 593*cdf0e10cSrcweir { 594*cdf0e10cSrcweir $infoline = "ERROR: Could not execute $systemcall !\n"; 595*cdf0e10cSrcweir exit_program($infoline); 596*cdf0e10cSrcweir } 597*cdf0e10cSrcweir} 598*cdf0e10cSrcweir 599*cdf0e10cSrcweir######################################################## 600*cdf0e10cSrcweir# Check, if this installation set contains 601*cdf0e10cSrcweir# internal cabinet files included into the msi 602*cdf0e10cSrcweir# database. 603*cdf0e10cSrcweir######################################################## 604*cdf0e10cSrcweir 605*cdf0e10cSrcweirsub check_for_internal_cabfiles 606*cdf0e10cSrcweir{ 607*cdf0e10cSrcweir my ($cabfilehash) = @_; 608*cdf0e10cSrcweir 609*cdf0e10cSrcweir my $contains_internal_cabfiles = 0; 610*cdf0e10cSrcweir my %allcabfileshash = (); 611*cdf0e10cSrcweir 612*cdf0e10cSrcweir foreach my $filename ( keys %{$cabfilehash} ) 613*cdf0e10cSrcweir { 614*cdf0e10cSrcweir if ( $filename =~ /^\s*\#/ ) # starting with a hash 615*cdf0e10cSrcweir { 616*cdf0e10cSrcweir $contains_internal_cabfiles = 1; 617*cdf0e10cSrcweir # setting real filename without hash as key and name with hash as value 618*cdf0e10cSrcweir my $realfilename = $filename; 619*cdf0e10cSrcweir $realfilename =~ s/^\s*\#//; 620*cdf0e10cSrcweir $allcabfileshash{$realfilename} = $filename; 621*cdf0e10cSrcweir } 622*cdf0e10cSrcweir } 623*cdf0e10cSrcweir 624*cdf0e10cSrcweir return ( $contains_internal_cabfiles, \%allcabfileshash ); 625*cdf0e10cSrcweir} 626*cdf0e10cSrcweir 627*cdf0e10cSrcweir################################################################# 628*cdf0e10cSrcweir# Exclude all cab files from the msi database. 629*cdf0e10cSrcweir################################################################# 630*cdf0e10cSrcweir 631*cdf0e10cSrcweirsub extract_cabs_from_database 632*cdf0e10cSrcweir{ 633*cdf0e10cSrcweir my ($msidatabase, $allcabfiles) = @_; 634*cdf0e10cSrcweir 635*cdf0e10cSrcweir my $infoline = ""; 636*cdf0e10cSrcweir my $fullsuccess = 1; 637*cdf0e10cSrcweir my $msidb = "msidb.exe"; # Has to be in the path 638*cdf0e10cSrcweir if ( $localmsidbpath ) { $msidb = $localmsidbpath; } 639*cdf0e10cSrcweir 640*cdf0e10cSrcweir my @all_excluded_cabfiles = (); 641*cdf0e10cSrcweir 642*cdf0e10cSrcweir if( $^O =~ /cygwin/i ) 643*cdf0e10cSrcweir { 644*cdf0e10cSrcweir $msidatabase = qx{cygpath -w "$msidatabase"}; 645*cdf0e10cSrcweir $msidatabase =~ s/\\/\\\\/g; 646*cdf0e10cSrcweir $msidatabase =~ s/\s*$//g; 647*cdf0e10cSrcweir } 648*cdf0e10cSrcweir else 649*cdf0e10cSrcweir { 650*cdf0e10cSrcweir # msidb.exe really wants backslashes. (And double escaping because system() expands the string.) 651*cdf0e10cSrcweir $msidatabase =~ s/\//\\\\/g; 652*cdf0e10cSrcweir } 653*cdf0e10cSrcweir 654*cdf0e10cSrcweir foreach my $onefile ( keys %{$allcabfiles} ) 655*cdf0e10cSrcweir { 656*cdf0e10cSrcweir my $systemcall = $msidb . " -d " . $msidatabase . " -x " . $onefile; 657*cdf0e10cSrcweir system($systemcall); 658*cdf0e10cSrcweir push(@all_excluded_cabfiles, $onefile); 659*cdf0e10cSrcweir } 660*cdf0e10cSrcweir 661*cdf0e10cSrcweir \@all_excluded_cabfiles; 662*cdf0e10cSrcweir} 663*cdf0e10cSrcweir 664*cdf0e10cSrcweir################################################################################ 665*cdf0e10cSrcweir# Collect all DiskIds to the corresponding cabinet files from Media.idt. 666*cdf0e10cSrcweir################################################################################ 667*cdf0e10cSrcweir 668*cdf0e10cSrcweirsub analyze_media_file 669*cdf0e10cSrcweir{ 670*cdf0e10cSrcweir my ($filecontent) = @_; 671*cdf0e10cSrcweir 672*cdf0e10cSrcweir my %diskidhash = (); 673*cdf0e10cSrcweir 674*cdf0e10cSrcweir for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) 675*cdf0e10cSrcweir { 676*cdf0e10cSrcweir if ( $i < 3 ) { next; } 677*cdf0e10cSrcweir 678*cdf0e10cSrcweir if ( ${$filecontent}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) 679*cdf0e10cSrcweir { 680*cdf0e10cSrcweir my $diskid = $1; 681*cdf0e10cSrcweir my $cabfile = $4; 682*cdf0e10cSrcweir 683*cdf0e10cSrcweir $diskidhash{$cabfile} = $diskid; 684*cdf0e10cSrcweir } 685*cdf0e10cSrcweir } 686*cdf0e10cSrcweir 687*cdf0e10cSrcweir return \%diskidhash; 688*cdf0e10cSrcweir} 689*cdf0e10cSrcweir 690*cdf0e10cSrcweirsub analyze_customaction_file 691*cdf0e10cSrcweir{ 692*cdf0e10cSrcweir my ($filecontent) = @_; 693*cdf0e10cSrcweir 694*cdf0e10cSrcweir my $register_extensions_exists = 0; 695*cdf0e10cSrcweir 696*cdf0e10cSrcweir my %table = (); 697*cdf0e10cSrcweir 698*cdf0e10cSrcweir for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) 699*cdf0e10cSrcweir { 700*cdf0e10cSrcweir if ( ${$filecontent}[$i] =~ /^\s*RegisterExtensions\s+/ ) 701*cdf0e10cSrcweir { 702*cdf0e10cSrcweir $register_extensions_exists = 1; 703*cdf0e10cSrcweir last; 704*cdf0e10cSrcweir } 705*cdf0e10cSrcweir } 706*cdf0e10cSrcweir 707*cdf0e10cSrcweir return $register_extensions_exists; 708*cdf0e10cSrcweir} 709*cdf0e10cSrcweir 710*cdf0e10cSrcweir################################################################################ 711*cdf0e10cSrcweir# Analyzing the content of Directory.idt 712*cdf0e10cSrcweir################################################################################# 713*cdf0e10cSrcweir 714*cdf0e10cSrcweirsub analyze_directory_file 715*cdf0e10cSrcweir{ 716*cdf0e10cSrcweir my ($filecontent) = @_; 717*cdf0e10cSrcweir 718*cdf0e10cSrcweir my %table = (); 719*cdf0e10cSrcweir 720*cdf0e10cSrcweir for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) 721*cdf0e10cSrcweir { 722*cdf0e10cSrcweir if (( $i == 0 ) || ( $i == 1 ) || ( $i == 2 )) { next; } 723*cdf0e10cSrcweir 724*cdf0e10cSrcweir if ( ${$filecontent}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\s*$/ ) 725*cdf0e10cSrcweir { 726*cdf0e10cSrcweir my $dir = $1; 727*cdf0e10cSrcweir my $parent = $2; 728*cdf0e10cSrcweir my $name = $3; 729*cdf0e10cSrcweir 730*cdf0e10cSrcweir if ( $name =~ /^\s*(.*?)\s*\:\s*(.*?)\s*$/ ) { $name = $2; } 731*cdf0e10cSrcweir if ( $name =~ /^\s*(.*?)\s*\|\s*(.*?)\s*$/ ) { $name = $2; } 732*cdf0e10cSrcweir 733*cdf0e10cSrcweir my %helphash = (); 734*cdf0e10cSrcweir $helphash{'Directory_Parent'} = $parent; 735*cdf0e10cSrcweir $helphash{'DefaultDir'} = $name; 736*cdf0e10cSrcweir $table{$dir} = \%helphash; 737*cdf0e10cSrcweir } 738*cdf0e10cSrcweir } 739*cdf0e10cSrcweir 740*cdf0e10cSrcweir return \%table; 741*cdf0e10cSrcweir} 742*cdf0e10cSrcweir 743*cdf0e10cSrcweir################################################################################# 744*cdf0e10cSrcweir# Analyzing the content of Component.idt 745*cdf0e10cSrcweir################################################################################# 746*cdf0e10cSrcweir 747*cdf0e10cSrcweirsub analyze_component_file 748*cdf0e10cSrcweir{ 749*cdf0e10cSrcweir my ($filecontent) = @_; 750*cdf0e10cSrcweir 751*cdf0e10cSrcweir my %table = (); 752*cdf0e10cSrcweir 753*cdf0e10cSrcweir for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) 754*cdf0e10cSrcweir { 755*cdf0e10cSrcweir if (( $i == 0 ) || ( $i == 1 ) || ( $i == 2 )) { next; } 756*cdf0e10cSrcweir 757*cdf0e10cSrcweir if ( ${$filecontent}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) 758*cdf0e10cSrcweir { 759*cdf0e10cSrcweir my $component = $1; 760*cdf0e10cSrcweir my $dir = $3; 761*cdf0e10cSrcweir 762*cdf0e10cSrcweir $table{$component} = $dir; 763*cdf0e10cSrcweir } 764*cdf0e10cSrcweir } 765*cdf0e10cSrcweir 766*cdf0e10cSrcweir return \%table; 767*cdf0e10cSrcweir} 768*cdf0e10cSrcweir 769*cdf0e10cSrcweir################################################################################# 770*cdf0e10cSrcweir# Analyzing the content of File.idt 771*cdf0e10cSrcweir################################################################################# 772*cdf0e10cSrcweir 773*cdf0e10cSrcweirsub analyze_file_file 774*cdf0e10cSrcweir{ 775*cdf0e10cSrcweir my ($filecontent) = @_; 776*cdf0e10cSrcweir 777*cdf0e10cSrcweir my %table = (); 778*cdf0e10cSrcweir my %fileorder = (); 779*cdf0e10cSrcweir my $maxsequence = 0; 780*cdf0e10cSrcweir 781*cdf0e10cSrcweir for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) 782*cdf0e10cSrcweir { 783*cdf0e10cSrcweir if (( $i == 0 ) || ( $i == 1 ) || ( $i == 2 )) { next; } 784*cdf0e10cSrcweir 785*cdf0e10cSrcweir if ( ${$filecontent}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) 786*cdf0e10cSrcweir { 787*cdf0e10cSrcweir my $file = $1; 788*cdf0e10cSrcweir my $comp = $2; 789*cdf0e10cSrcweir my $filename = $3; 790*cdf0e10cSrcweir my $sequence = $8; 791*cdf0e10cSrcweir 792*cdf0e10cSrcweir if ( $filename =~ /^\s*(.*?)\s*\|\s*(.*?)\s*$/ ) { $filename = $2; } 793*cdf0e10cSrcweir 794*cdf0e10cSrcweir my %helphash = (); 795*cdf0e10cSrcweir $helphash{'Component'} = $comp; 796*cdf0e10cSrcweir $helphash{'FileName'} = $filename; 797*cdf0e10cSrcweir $helphash{'Sequence'} = $sequence; 798*cdf0e10cSrcweir 799*cdf0e10cSrcweir $table{$file} = \%helphash; 800*cdf0e10cSrcweir 801*cdf0e10cSrcweir $fileorder{$sequence} = $file; 802*cdf0e10cSrcweir 803*cdf0e10cSrcweir if ( $sequence > $maxsequence ) { $maxsequence = $sequence; } 804*cdf0e10cSrcweir } 805*cdf0e10cSrcweir } 806*cdf0e10cSrcweir 807*cdf0e10cSrcweir return (\%table, \%fileorder, $maxsequence); 808*cdf0e10cSrcweir} 809*cdf0e10cSrcweir 810*cdf0e10cSrcweir#################################################################################### 811*cdf0e10cSrcweir# Recursively creating the directory tree 812*cdf0e10cSrcweir#################################################################################### 813*cdf0e10cSrcweir 814*cdf0e10cSrcweirsub create_directory_tree 815*cdf0e10cSrcweir{ 816*cdf0e10cSrcweir my ($parent, $pathcollector, $fulldir, $dirhash) = @_; 817*cdf0e10cSrcweir 818*cdf0e10cSrcweir foreach my $dir ( keys %{$dirhash} ) 819*cdf0e10cSrcweir { 820*cdf0e10cSrcweir if (( $dirhash->{$dir}->{'Directory_Parent'} eq $parent ) && ( $dirhash->{$dir}->{'DefaultDir'} ne "." )) 821*cdf0e10cSrcweir { 822*cdf0e10cSrcweir my $dirname = $dirhash->{$dir}->{'DefaultDir'}; 823*cdf0e10cSrcweir # Create the directory 824*cdf0e10cSrcweir my $newdir = $fulldir . $separator . $dirname; 825*cdf0e10cSrcweir if ( ! -f $newdir ) { mkdir $newdir; } 826*cdf0e10cSrcweir # Saving in collector 827*cdf0e10cSrcweir $pathcollector->{$dir} = $newdir; 828*cdf0e10cSrcweir # Iteration 829*cdf0e10cSrcweir create_directory_tree($dir, $pathcollector, $newdir, $dirhash); 830*cdf0e10cSrcweir } 831*cdf0e10cSrcweir } 832*cdf0e10cSrcweir} 833*cdf0e10cSrcweir 834*cdf0e10cSrcweir#################################################################################### 835*cdf0e10cSrcweir# Creating the directory tree 836*cdf0e10cSrcweir#################################################################################### 837*cdf0e10cSrcweir 838*cdf0e10cSrcweirsub create_directory_structure 839*cdf0e10cSrcweir{ 840*cdf0e10cSrcweir my ($dirhash, $targetdir) = @_; 841*cdf0e10cSrcweir 842*cdf0e10cSrcweir print "Creating directories\n"; 843*cdf0e10cSrcweir 844*cdf0e10cSrcweir my %fullpathhash = (); 845*cdf0e10cSrcweir 846*cdf0e10cSrcweir my @startparents = ("TARGETDIR", "INSTALLLOCATION"); 847*cdf0e10cSrcweir 848*cdf0e10cSrcweir foreach $dir (@startparents) { create_directory_tree($dir, \%fullpathhash, $targetdir, $dirhash); } 849*cdf0e10cSrcweir 850*cdf0e10cSrcweir # Also adding the pathes of the startparents 851*cdf0e10cSrcweir foreach $dir (@startparents) 852*cdf0e10cSrcweir { 853*cdf0e10cSrcweir if ( ! exists($fullpathhash{$dir}) ) { $fullpathhash{$dir} = $targetdir; } 854*cdf0e10cSrcweir } 855*cdf0e10cSrcweir 856*cdf0e10cSrcweir return \%fullpathhash; 857*cdf0e10cSrcweir} 858*cdf0e10cSrcweir 859*cdf0e10cSrcweir#################################################################################### 860*cdf0e10cSrcweir# Cygwin: Setting privileges for files 861*cdf0e10cSrcweir#################################################################################### 862*cdf0e10cSrcweir 863*cdf0e10cSrcweirsub change_privileges 864*cdf0e10cSrcweir{ 865*cdf0e10cSrcweir my ($destfile, $privileges) = @_; 866*cdf0e10cSrcweir 867*cdf0e10cSrcweir my $localcall = "chmod $privileges " . "\"" . $destfile . "\""; 868*cdf0e10cSrcweir system($localcall); 869*cdf0e10cSrcweir} 870*cdf0e10cSrcweir 871*cdf0e10cSrcweir#################################################################################### 872*cdf0e10cSrcweir# Cygwin: Setting privileges for files recursively 873*cdf0e10cSrcweir#################################################################################### 874*cdf0e10cSrcweir 875*cdf0e10cSrcweirsub change_privileges_full 876*cdf0e10cSrcweir{ 877*cdf0e10cSrcweir my ($target) = @_; 878*cdf0e10cSrcweir 879*cdf0e10cSrcweir print "Changing privileges\n"; 880*cdf0e10cSrcweir 881*cdf0e10cSrcweir my $localcall = "chmod -R 755 " . "\"" . $target . "\""; 882*cdf0e10cSrcweir system($localcall); 883*cdf0e10cSrcweir} 884*cdf0e10cSrcweir 885*cdf0e10cSrcweir###################################################### 886*cdf0e10cSrcweir# Creating a new directory with defined privileges 887*cdf0e10cSrcweir###################################################### 888*cdf0e10cSrcweir 889*cdf0e10cSrcweirsub create_directory_with_privileges 890*cdf0e10cSrcweir{ 891*cdf0e10cSrcweir my ($directory, $privileges) = @_; 892*cdf0e10cSrcweir 893*cdf0e10cSrcweir my $returnvalue = 1; 894*cdf0e10cSrcweir my $infoline = ""; 895*cdf0e10cSrcweir 896*cdf0e10cSrcweir if (!(-d $directory)) 897*cdf0e10cSrcweir { 898*cdf0e10cSrcweir my $localprivileges = oct("0".$privileges); # changes "777" to 0777 899*cdf0e10cSrcweir $returnvalue = mkdir($directory, $localprivileges); 900*cdf0e10cSrcweir 901*cdf0e10cSrcweir if ($returnvalue) 902*cdf0e10cSrcweir { 903*cdf0e10cSrcweir my $localcall = "chmod $privileges $directory \>\/dev\/null 2\>\&1"; 904*cdf0e10cSrcweir system($localcall); 905*cdf0e10cSrcweir } 906*cdf0e10cSrcweir } 907*cdf0e10cSrcweir else 908*cdf0e10cSrcweir { 909*cdf0e10cSrcweir my $localcall = "chmod $privileges $directory \>\/dev\/null 2\>\&1"; 910*cdf0e10cSrcweir system($localcall); 911*cdf0e10cSrcweir } 912*cdf0e10cSrcweir} 913*cdf0e10cSrcweir 914*cdf0e10cSrcweir###################################################### 915*cdf0e10cSrcweir# Creating a unique directory with pid extension 916*cdf0e10cSrcweir###################################################### 917*cdf0e10cSrcweir 918*cdf0e10cSrcweirsub create_pid_directory 919*cdf0e10cSrcweir{ 920*cdf0e10cSrcweir my ($directory) = @_; 921*cdf0e10cSrcweir 922*cdf0e10cSrcweir $directory =~ s/\Q$separator\E\s*$//; 923*cdf0e10cSrcweir my $pid = $$; # process id 924*cdf0e10cSrcweir my $time = time(); # time 925*cdf0e10cSrcweir 926*cdf0e10cSrcweir $directory = $directory . "_" . $pid . $time; 927*cdf0e10cSrcweir 928*cdf0e10cSrcweir if ( ! -d $directory ) { create_directory($directory); } 929*cdf0e10cSrcweir else { exit_program("ERROR: Directory $directory already exists!"); } 930*cdf0e10cSrcweir 931*cdf0e10cSrcweir return $directory; 932*cdf0e10cSrcweir} 933*cdf0e10cSrcweir 934*cdf0e10cSrcweir#################################################################################### 935*cdf0e10cSrcweir# Copying files into installation set 936*cdf0e10cSrcweir#################################################################################### 937*cdf0e10cSrcweir 938*cdf0e10cSrcweirsub copy_files_into_directory_structure 939*cdf0e10cSrcweir{ 940*cdf0e10cSrcweir my ($fileorder, $filehash, $componenthash, $fullpathhash, $maxsequence, $unpackdir, $installdir, $dirhash) = @_; 941*cdf0e10cSrcweir 942*cdf0e10cSrcweir print "Copying files\n"; 943*cdf0e10cSrcweir 944*cdf0e10cSrcweir my $unopkgfile = ""; 945*cdf0e10cSrcweir 946*cdf0e10cSrcweir for ( my $i = 1; $i <= $maxsequence; $i++ ) 947*cdf0e10cSrcweir { 948*cdf0e10cSrcweir if ( exists($fileorder->{$i}) ) 949*cdf0e10cSrcweir { 950*cdf0e10cSrcweir my $file = $fileorder->{$i}; 951*cdf0e10cSrcweir if ( ! exists($filehash->{$file}->{'Component'}) ) { exit_program("ERROR: Did not find component for file: \"$file\"."); } 952*cdf0e10cSrcweir my $component = $filehash->{$file}->{'Component'}; 953*cdf0e10cSrcweir if ( ! exists($componenthash->{$component}) ) { exit_program("ERROR: Did not find directory for component: \"$component\"."); } 954*cdf0e10cSrcweir my $dirname = $componenthash->{$component}; 955*cdf0e10cSrcweir if ( ! exists($fullpathhash->{$dirname}) ) { exit_program("ERROR: Did not find full directory path for dir: \"$dirname\"."); } 956*cdf0e10cSrcweir my $destdir = $fullpathhash->{$dirname}; 957*cdf0e10cSrcweir if ( ! exists($filehash->{$file}->{'FileName'}) ) { exit_program("ERROR: Did not find \"FileName\" for file: \"$file\"."); } 958*cdf0e10cSrcweir my $destfile = $filehash->{$file}->{'FileName'}; 959*cdf0e10cSrcweir 960*cdf0e10cSrcweir $destfile = $destdir . $separator . $destfile; 961*cdf0e10cSrcweir my $sourcefile = $unpackdir . $separator . $file; 962*cdf0e10cSrcweir 963*cdf0e10cSrcweir if ( ! -f $sourcefile ) 964*cdf0e10cSrcweir { 965*cdf0e10cSrcweir # It is possible, that this was an unpacked file 966*cdf0e10cSrcweir # Looking in the dirhash, to find the subdirectory in the installation set (the id is $dirname) 967*cdf0e10cSrcweir # subdir is not recursively analyzed, only one directory. 968*cdf0e10cSrcweir 969*cdf0e10cSrcweir my $oldsourcefile = $sourcefile; 970*cdf0e10cSrcweir my $subdir = ""; 971*cdf0e10cSrcweir if ( exists($dirhash->{$dirname}->{'DefaultDir'}) ) { $subdir = $dirhash->{$dirname}->{'DefaultDir'} . $separator; } 972*cdf0e10cSrcweir my $realfilename = $filehash->{$file}->{'FileName'}; 973*cdf0e10cSrcweir my $localinstalldir = $installdir; 974*cdf0e10cSrcweir 975*cdf0e10cSrcweir $localinstalldir =~ s/\\\s*$//; 976*cdf0e10cSrcweir $localinstalldir =~ s/\/\s*$//; 977*cdf0e10cSrcweir 978*cdf0e10cSrcweir $sourcefile = $localinstalldir . $separator . $subdir . $realfilename; 979*cdf0e10cSrcweir 980*cdf0e10cSrcweir if ( ! -f $sourcefile ) { exit_program("ERROR: File not found: \"$oldsourcefile\" (or \"$sourcefile\")."); } 981*cdf0e10cSrcweir } 982*cdf0e10cSrcweir 983*cdf0e10cSrcweir my $copyreturn = copy($sourcefile, $destfile); 984*cdf0e10cSrcweir 985*cdf0e10cSrcweir if ( ! $copyreturn) { exit_program("ERROR: Could not copy $source to $dest\n"); } 986*cdf0e10cSrcweir 987*cdf0e10cSrcweir # Searching unopkg.exe 988*cdf0e10cSrcweir if ( $destfile =~ /unopkg\.exe\s*$/ ) { $unopkgfile = $destfile; } 989*cdf0e10cSrcweir # if (( $^O =~ /cygwin/i ) && ( $destfile =~ /\.exe\s*$/ )) { change_privileges($destfile, "775"); } 990*cdf0e10cSrcweir } 991*cdf0e10cSrcweir # else # allowing missing sequence numbers ? 992*cdf0e10cSrcweir # { 993*cdf0e10cSrcweir # exit_program("ERROR: No file assigned to sequence $i"); 994*cdf0e10cSrcweir # } 995*cdf0e10cSrcweir } 996*cdf0e10cSrcweir 997*cdf0e10cSrcweir return ($unopkgfile); 998*cdf0e10cSrcweir} 999*cdf0e10cSrcweir 1000*cdf0e10cSrcweir###################################################### 1001*cdf0e10cSrcweir# Removing a complete directory with subdirectories 1002*cdf0e10cSrcweir###################################################### 1003*cdf0e10cSrcweir 1004*cdf0e10cSrcweirsub remove_complete_directory 1005*cdf0e10cSrcweir{ 1006*cdf0e10cSrcweir my ($directory, $start) = @_; 1007*cdf0e10cSrcweir 1008*cdf0e10cSrcweir my @content = (); 1009*cdf0e10cSrcweir my $infoline = ""; 1010*cdf0e10cSrcweir 1011*cdf0e10cSrcweir $directory =~ s/\Q$separator\E\s*$//; 1012*cdf0e10cSrcweir 1013*cdf0e10cSrcweir if ( -d $directory ) 1014*cdf0e10cSrcweir { 1015*cdf0e10cSrcweir if ( $start ) { print "Removing directory $directory\n"; } 1016*cdf0e10cSrcweir 1017*cdf0e10cSrcweir opendir(DIR, $directory); 1018*cdf0e10cSrcweir @content = readdir(DIR); 1019*cdf0e10cSrcweir closedir(DIR); 1020*cdf0e10cSrcweir 1021*cdf0e10cSrcweir my $oneitem; 1022*cdf0e10cSrcweir 1023*cdf0e10cSrcweir foreach $oneitem (@content) 1024*cdf0e10cSrcweir { 1025*cdf0e10cSrcweir if ((!($oneitem eq ".")) && (!($oneitem eq ".."))) 1026*cdf0e10cSrcweir { 1027*cdf0e10cSrcweir my $item = $directory . $separator . $oneitem; 1028*cdf0e10cSrcweir 1029*cdf0e10cSrcweir if ( -f $item || -l $item ) # deleting files or links 1030*cdf0e10cSrcweir { 1031*cdf0e10cSrcweir unlink($item); 1032*cdf0e10cSrcweir } 1033*cdf0e10cSrcweir 1034*cdf0e10cSrcweir if ( -d $item ) # recursive 1035*cdf0e10cSrcweir { 1036*cdf0e10cSrcweir remove_complete_directory($item, 0); 1037*cdf0e10cSrcweir } 1038*cdf0e10cSrcweir } 1039*cdf0e10cSrcweir } 1040*cdf0e10cSrcweir 1041*cdf0e10cSrcweir # try to remove empty directory 1042*cdf0e10cSrcweir my $returnvalue = rmdir $directory; 1043*cdf0e10cSrcweir if ( ! $returnvalue ) { print "Warning: Problem with removing empty dir $directory\n"; } 1044*cdf0e10cSrcweir } 1045*cdf0e10cSrcweir} 1046*cdf0e10cSrcweir 1047*cdf0e10cSrcweir#################################################################################### 1048*cdf0e10cSrcweir# Defining a temporary path 1049*cdf0e10cSrcweir#################################################################################### 1050*cdf0e10cSrcweir 1051*cdf0e10cSrcweirsub get_temppath 1052*cdf0e10cSrcweir{ 1053*cdf0e10cSrcweir my $temppath = ""; 1054*cdf0e10cSrcweir 1055*cdf0e10cSrcweir if (( $ENV{'TMP'} ) || ( $ENV{'TEMP'} )) 1056*cdf0e10cSrcweir { 1057*cdf0e10cSrcweir if ( $ENV{'TMP'} ) { $temppath = $ENV{'TMP'}; } 1058*cdf0e10cSrcweir elsif ( $ENV{'TEMP'} ) { $temppath = $ENV{'TEMP'}; } 1059*cdf0e10cSrcweir 1060*cdf0e10cSrcweir $temppath =~ s/\Q$separator\E\s*$//; # removing ending slashes and backslashes 1061*cdf0e10cSrcweir $temppath = $temppath . $separator . $globaltempdirname; 1062*cdf0e10cSrcweir create_directory_with_privileges($temppath, "777"); 1063*cdf0e10cSrcweir 1064*cdf0e10cSrcweir my $dirsave = $temppath; 1065*cdf0e10cSrcweir 1066*cdf0e10cSrcweir $temppath = $temppath . $separator . "a"; 1067*cdf0e10cSrcweir $temppath = create_pid_directory($temppath); 1068*cdf0e10cSrcweir 1069*cdf0e10cSrcweir if ( ! -d $temppath ) { exit_program("ERROR: Failed to create directory $temppath ! Possible reason: Wrong privileges in directory $dirsave."); } 1070*cdf0e10cSrcweir 1071*cdf0e10cSrcweir if ( $^O =~ /cygwin/i ) 1072*cdf0e10cSrcweir { 1073*cdf0e10cSrcweir $temppath =~ s/\\/\\\\/g; 1074*cdf0e10cSrcweir chomp( $temppath = qx{cygpath -w "$temppath"} ); 1075*cdf0e10cSrcweir } 1076*cdf0e10cSrcweir 1077*cdf0e10cSrcweir $savetemppath = $temppath; 1078*cdf0e10cSrcweir } 1079*cdf0e10cSrcweir else 1080*cdf0e10cSrcweir { 1081*cdf0e10cSrcweir exit_program("ERROR: Could not set temporary directory (TMP and TEMP not set!)."); 1082*cdf0e10cSrcweir } 1083*cdf0e10cSrcweir 1084*cdf0e10cSrcweir return $temppath; 1085*cdf0e10cSrcweir} 1086*cdf0e10cSrcweir 1087*cdf0e10cSrcweir#################################################################################### 1088*cdf0e10cSrcweir# Registering extensions 1089*cdf0e10cSrcweir#################################################################################### 1090*cdf0e10cSrcweir 1091*cdf0e10cSrcweirsub register_extensions_sync 1092*cdf0e10cSrcweir{ 1093*cdf0e10cSrcweir my ($unopkgfile, $localtemppath, $preregdir) = @_; 1094*cdf0e10cSrcweir 1095*cdf0e10cSrcweir if ( $preregdir eq "" ) 1096*cdf0e10cSrcweir { 1097*cdf0e10cSrcweir my $logtext = "ERROR: Failed to determine \"prereg\" folder for extension registration! Please check your installation set."; 1098*cdf0e10cSrcweir print $logtext . "\n"; 1099*cdf0e10cSrcweir exit_program($logtext); 1100*cdf0e10cSrcweir } 1101*cdf0e10cSrcweir 1102*cdf0e10cSrcweir my $from = cwd(); 1103*cdf0e10cSrcweir 1104*cdf0e10cSrcweir my $path = $unopkgfile; 1105*cdf0e10cSrcweir get_path_from_fullqualifiedname(\$path); 1106*cdf0e10cSrcweir $path =~ s/\\\s*$//; 1107*cdf0e10cSrcweir $path =~ s/\/\s*$//; 1108*cdf0e10cSrcweir 1109*cdf0e10cSrcweir my $executable = $unopkgfile; 1110*cdf0e10cSrcweir make_absolute_filename_to_relative_filename(\$executable); 1111*cdf0e10cSrcweir 1112*cdf0e10cSrcweir chdir($path); 1113*cdf0e10cSrcweir 1114*cdf0e10cSrcweir if ( ! $path_displayed ) 1115*cdf0e10cSrcweir { 1116*cdf0e10cSrcweir print "... current dir: $path ...\n"; 1117*cdf0e10cSrcweir $path_displayed = 1; 1118*cdf0e10cSrcweir } 1119*cdf0e10cSrcweir 1120*cdf0e10cSrcweir $localtemppath =~ s/\\/\//g; 1121*cdf0e10cSrcweir 1122*cdf0e10cSrcweir if ( $^O =~ /cygwin/i ) { 1123*cdf0e10cSrcweir $executable = "./" . $executable; 1124*cdf0e10cSrcweir $preregdir = qx{cygpath -m "$preregdir"}; 1125*cdf0e10cSrcweir chomp($preregdir); 1126*cdf0e10cSrcweir } 1127*cdf0e10cSrcweir 1128*cdf0e10cSrcweir $preregdir =~ s/\/\s*$//g; 1129*cdf0e10cSrcweir 1130*cdf0e10cSrcweir my $systemcall = $executable . " sync --verbose 2\>\&1 |"; 1131*cdf0e10cSrcweir 1132*cdf0e10cSrcweir print "... $systemcall\n"; 1133*cdf0e10cSrcweir 1134*cdf0e10cSrcweir my @unopkgoutput = (); 1135*cdf0e10cSrcweir 1136*cdf0e10cSrcweir open (UNOPKG, $systemcall); 1137*cdf0e10cSrcweir while (<UNOPKG>) {push(@unopkgoutput, $_); } 1138*cdf0e10cSrcweir close (UNOPKG); 1139*cdf0e10cSrcweir 1140*cdf0e10cSrcweir my $returnvalue = $?; # $? contains the return value of the systemcall 1141*cdf0e10cSrcweir 1142*cdf0e10cSrcweir if ($returnvalue) 1143*cdf0e10cSrcweir { 1144*cdf0e10cSrcweir print "ERROR: Could not execute \"$systemcall\"!\nExitcode: '$returnvalue'\n"; 1145*cdf0e10cSrcweir for ( my $j = 0; $j <= $#unopkgoutput; $j++ ) { print "$unopkgoutput[$j]"; } 1146*cdf0e10cSrcweir exit_program("ERROR: $systemcall failed!"); 1147*cdf0e10cSrcweir } 1148*cdf0e10cSrcweir 1149*cdf0e10cSrcweir chdir($from); 1150*cdf0e10cSrcweir} 1151*cdf0e10cSrcweir 1152*cdf0e10cSrcweir#################################################################################### 1153*cdf0e10cSrcweir# Registering all extensions located in /share/extension/install 1154*cdf0e10cSrcweir#################################################################################### 1155*cdf0e10cSrcweir 1156*cdf0e10cSrcweirsub register_extensions 1157*cdf0e10cSrcweir{ 1158*cdf0e10cSrcweir my ($unopkgfile, $temppath, $preregdir) = @_; 1159*cdf0e10cSrcweir 1160*cdf0e10cSrcweir print "Registering extensions:\n"; 1161*cdf0e10cSrcweir 1162*cdf0e10cSrcweir if (( ! -f $unopkgfile ) || ( $unopkgfile eq "" )) 1163*cdf0e10cSrcweir { 1164*cdf0e10cSrcweir print("WARNING: Could not find unopkg.exe (Language Pack?)!\n"); 1165*cdf0e10cSrcweir } 1166*cdf0e10cSrcweir else 1167*cdf0e10cSrcweir { 1168*cdf0e10cSrcweir register_extensions_sync($unopkgfile, $temppath, $preregdir); 1169*cdf0e10cSrcweir remove_complete_directory($temppath, 1); 1170*cdf0e10cSrcweir } 1171*cdf0e10cSrcweir 1172*cdf0e10cSrcweir} 1173*cdf0e10cSrcweir 1174*cdf0e10cSrcweir#################################################################################### 1175*cdf0e10cSrcweir# Reading one file 1176*cdf0e10cSrcweir#################################################################################### 1177*cdf0e10cSrcweir 1178*cdf0e10cSrcweirsub read_file 1179*cdf0e10cSrcweir{ 1180*cdf0e10cSrcweir my ($localfile) = @_; 1181*cdf0e10cSrcweir 1182*cdf0e10cSrcweir my @localfile = (); 1183*cdf0e10cSrcweir 1184*cdf0e10cSrcweir open( IN, "<$localfile" ) || exit_program("ERROR: Cannot open file $localfile for reading"); 1185*cdf0e10cSrcweir 1186*cdf0e10cSrcweir # Don't use "my @localfile = <IN>" here, because 1187*cdf0e10cSrcweir # perl has a problem with the internal "large_and_huge_malloc" function 1188*cdf0e10cSrcweir # when calling perl using MacOS 10.5 with a perl built with MacOS 10.4 1189*cdf0e10cSrcweir while ( $line = <IN> ) { 1190*cdf0e10cSrcweir push @localfile, $line; 1191*cdf0e10cSrcweir } 1192*cdf0e10cSrcweir 1193*cdf0e10cSrcweir close( IN ); 1194*cdf0e10cSrcweir 1195*cdf0e10cSrcweir return \@localfile; 1196*cdf0e10cSrcweir} 1197*cdf0e10cSrcweir 1198*cdf0e10cSrcweir############################################################### 1199*cdf0e10cSrcweir# Setting the time string for the 1200*cdf0e10cSrcweir# Summary Information stream in the 1201*cdf0e10cSrcweir# msi database of the admin installations. 1202*cdf0e10cSrcweir############################################################### 1203*cdf0e10cSrcweir 1204*cdf0e10cSrcweirsub get_sis_time_string 1205*cdf0e10cSrcweir{ 1206*cdf0e10cSrcweir # Syntax: <yyyy/mm/dd hh:mm:ss> 1207*cdf0e10cSrcweir my $second = (localtime())[0]; 1208*cdf0e10cSrcweir my $minute = (localtime())[1]; 1209*cdf0e10cSrcweir my $hour = (localtime())[2]; 1210*cdf0e10cSrcweir my $day = (localtime())[3]; 1211*cdf0e10cSrcweir my $month = (localtime())[4]; 1212*cdf0e10cSrcweir my $year = 1900 + (localtime())[5]; 1213*cdf0e10cSrcweir $month++; 1214*cdf0e10cSrcweir 1215*cdf0e10cSrcweir if ( $second < 10 ) { $second = "0" . $second; } 1216*cdf0e10cSrcweir if ( $minute < 10 ) { $minute = "0" . $minute; } 1217*cdf0e10cSrcweir if ( $hour < 10 ) { $hour = "0" . $hour; } 1218*cdf0e10cSrcweir if ( $day < 10 ) { $day = "0" . $day; } 1219*cdf0e10cSrcweir if ( $month < 10 ) { $month = "0" . $month; } 1220*cdf0e10cSrcweir 1221*cdf0e10cSrcweir my $timestring = $year . "/" . $month . "/" . $day . " " . $hour . ":" . $minute . ":" . $second; 1222*cdf0e10cSrcweir 1223*cdf0e10cSrcweir return $timestring; 1224*cdf0e10cSrcweir} 1225*cdf0e10cSrcweir 1226*cdf0e10cSrcweir############################################################### 1227*cdf0e10cSrcweir# Writing content of administrative installations into 1228*cdf0e10cSrcweir# Summary Information Stream of msi database. 1229*cdf0e10cSrcweir# This is required for example for following 1230*cdf0e10cSrcweir# patch processes using Windows Installer service. 1231*cdf0e10cSrcweir############################################################### 1232*cdf0e10cSrcweir 1233*cdf0e10cSrcweirsub write_sis_info 1234*cdf0e10cSrcweir{ 1235*cdf0e10cSrcweir my ($msidatabase) = @_; 1236*cdf0e10cSrcweir 1237*cdf0e10cSrcweir print "Setting SIS in msi database\n"; 1238*cdf0e10cSrcweir 1239*cdf0e10cSrcweir if ( ! -f $msidatabase ) { exit_program("ERROR: Cannot find file $msidatabase"); } 1240*cdf0e10cSrcweir 1241*cdf0e10cSrcweir my $msiinfo = "msiinfo.exe"; # Has to be in the path 1242*cdf0e10cSrcweir my $infoline = ""; 1243*cdf0e10cSrcweir my $systemcall = ""; 1244*cdf0e10cSrcweir my $returnvalue = ""; 1245*cdf0e10cSrcweir 1246*cdf0e10cSrcweir # Required setting for administrative installations: 1247*cdf0e10cSrcweir # -w 4 (source files are unpacked), wordcount 1248*cdf0e10cSrcweir # -s <date of admin installation>, LastPrinted, Syntax: <yyyy/mm/dd hh:mm:ss> 1249*cdf0e10cSrcweir # -l <person_making_admin_installation>, LastSavedBy 1250*cdf0e10cSrcweir 1251*cdf0e10cSrcweir my $wordcount = 4; # Unpacked files 1252*cdf0e10cSrcweir my $lastprinted = get_sis_time_string(); 1253*cdf0e10cSrcweir my $lastsavedby = "Installer"; 1254*cdf0e10cSrcweir 1255*cdf0e10cSrcweir my $localmsidatabase = $msidatabase; 1256*cdf0e10cSrcweir 1257*cdf0e10cSrcweir if( $^O =~ /cygwin/i ) 1258*cdf0e10cSrcweir { 1259*cdf0e10cSrcweir $localmsidatabase = qx{cygpath -w "$localmsidatabase"}; 1260*cdf0e10cSrcweir $localmsidatabase =~ s/\\/\\\\/g; 1261*cdf0e10cSrcweir $localmsidatabase =~ s/\s*$//g; 1262*cdf0e10cSrcweir } 1263*cdf0e10cSrcweir 1264*cdf0e10cSrcweir $systemcall = $msiinfo . " " . "\"" . $localmsidatabase . "\"" . " -w " . $wordcount . " -s " . "\"" . $lastprinted . "\"" . " -l $lastsavedby"; 1265*cdf0e10cSrcweir 1266*cdf0e10cSrcweir $returnvalue = system($systemcall); 1267*cdf0e10cSrcweir 1268*cdf0e10cSrcweir if ($returnvalue) 1269*cdf0e10cSrcweir { 1270*cdf0e10cSrcweir $infoline = "ERROR: Could not execute $systemcall !\n"; 1271*cdf0e10cSrcweir exit_program($infoline); 1272*cdf0e10cSrcweir } 1273*cdf0e10cSrcweir} 1274*cdf0e10cSrcweir 1275*cdf0e10cSrcweir############################################################### 1276*cdf0e10cSrcweir# Convert time string 1277*cdf0e10cSrcweir############################################################### 1278*cdf0e10cSrcweir 1279*cdf0e10cSrcweirsub convert_timestring 1280*cdf0e10cSrcweir{ 1281*cdf0e10cSrcweir my ($secondstring) = @_; 1282*cdf0e10cSrcweir 1283*cdf0e10cSrcweir my $timestring = ""; 1284*cdf0e10cSrcweir 1285*cdf0e10cSrcweir if ( $secondstring < 60 ) # less than a minute 1286*cdf0e10cSrcweir { 1287*cdf0e10cSrcweir if ( $secondstring < 10 ) { $secondstring = "0" . $secondstring; } 1288*cdf0e10cSrcweir $timestring = "00\:$secondstring min\."; 1289*cdf0e10cSrcweir } 1290*cdf0e10cSrcweir elsif ( $secondstring < 3600 ) 1291*cdf0e10cSrcweir { 1292*cdf0e10cSrcweir my $minutes = $secondstring / 60; 1293*cdf0e10cSrcweir my $seconds = $secondstring % 60; 1294*cdf0e10cSrcweir if ( $minutes =~ /(\d*)\.\d*/ ) { $minutes = $1; } 1295*cdf0e10cSrcweir if ( $minutes < 10 ) { $minutes = "0" . $minutes; } 1296*cdf0e10cSrcweir if ( $seconds < 10 ) { $seconds = "0" . $seconds; } 1297*cdf0e10cSrcweir $timestring = "$minutes\:$seconds min\."; 1298*cdf0e10cSrcweir } 1299*cdf0e10cSrcweir else # more than one hour 1300*cdf0e10cSrcweir { 1301*cdf0e10cSrcweir my $hours = $secondstring / 3600; 1302*cdf0e10cSrcweir my $secondstring = $secondstring % 3600; 1303*cdf0e10cSrcweir my $minutes = $secondstring / 60; 1304*cdf0e10cSrcweir my $seconds = $secondstring % 60; 1305*cdf0e10cSrcweir if ( $hours =~ /(\d*)\.\d*/ ) { $hours = $1; } 1306*cdf0e10cSrcweir if ( $minutes =~ /(\d*)\.\d*/ ) { $minutes = $1; } 1307*cdf0e10cSrcweir if ( $hours < 10 ) { $hours = "0" . $hours; } 1308*cdf0e10cSrcweir if ( $minutes < 10 ) { $minutes = "0" . $minutes; } 1309*cdf0e10cSrcweir if ( $seconds < 10 ) { $seconds = "0" . $seconds; } 1310*cdf0e10cSrcweir $timestring = "$hours\:$minutes\:$seconds hours"; 1311*cdf0e10cSrcweir } 1312*cdf0e10cSrcweir 1313*cdf0e10cSrcweir return $timestring; 1314*cdf0e10cSrcweir} 1315*cdf0e10cSrcweir 1316*cdf0e10cSrcweir############################################################### 1317*cdf0e10cSrcweir# Returning time string for logging 1318*cdf0e10cSrcweir############################################################### 1319*cdf0e10cSrcweir 1320*cdf0e10cSrcweirsub get_time_string 1321*cdf0e10cSrcweir{ 1322*cdf0e10cSrcweir my $currenttime = time(); 1323*cdf0e10cSrcweir $currenttime = $currenttime - $starttime; 1324*cdf0e10cSrcweir $currenttime = convert_timestring($currenttime); 1325*cdf0e10cSrcweir $currenttime = localtime() . " \(" . $currenttime . "\)\n"; 1326*cdf0e10cSrcweir return $currenttime; 1327*cdf0e10cSrcweir} 1328*cdf0e10cSrcweir 1329*cdf0e10cSrcweir#################################################################################### 1330*cdf0e10cSrcweir# Simulating an administrative installation 1331*cdf0e10cSrcweir#################################################################################### 1332*cdf0e10cSrcweir 1333*cdf0e10cSrcweir$starttime = time(); 1334*cdf0e10cSrcweir 1335*cdf0e10cSrcweirgetparameter(); 1336*cdf0e10cSrcweircontrolparameter(); 1337*cdf0e10cSrcweircheck_local_msidb(); 1338*cdf0e10cSrcweircheck_system_path(); 1339*cdf0e10cSrcweirmy $temppath = get_temppath(); 1340*cdf0e10cSrcweir 1341*cdf0e10cSrcweirprint("\nmsi database: $databasepath\n"); 1342*cdf0e10cSrcweirprint("Destination directory: $targetdir\n" ); 1343*cdf0e10cSrcweir 1344*cdf0e10cSrcweirmy $helperdir = $temppath . $separator . "installhelper"; 1345*cdf0e10cSrcweircreate_directory($helperdir); 1346*cdf0e10cSrcweir 1347*cdf0e10cSrcweir# Get File.idt, Component.idt and Directory.idt from database 1348*cdf0e10cSrcweir 1349*cdf0e10cSrcweirmy $tablelist = "File Directory Component Media CustomAction"; 1350*cdf0e10cSrcweirextract_tables_from_database($databasepath, $helperdir, $tablelist); 1351*cdf0e10cSrcweir 1352*cdf0e10cSrcweir# Set unpackdir 1353*cdf0e10cSrcweirmy $unpackdir = $helperdir . $separator . "unpack"; 1354*cdf0e10cSrcweircreate_directory($unpackdir); 1355*cdf0e10cSrcweir 1356*cdf0e10cSrcweir# Reading media table to check for internal cabinet files 1357*cdf0e10cSrcweirmy $filename = $helperdir . $separator . "Media.idt"; 1358*cdf0e10cSrcweirif ( ! -f $filename ) { exit_program("ERROR: Could not find required file: $filename !"); } 1359*cdf0e10cSrcweirmy $filecontent = read_file($filename); 1360*cdf0e10cSrcweirmy $cabfilehash = analyze_media_file($filecontent); 1361*cdf0e10cSrcweir 1362*cdf0e10cSrcweir# Check, if there are internal cab files 1363*cdf0e10cSrcweirmy ( $contains_internal_cabfiles, $all_internal_cab_files) = check_for_internal_cabfiles($cabfilehash); 1364*cdf0e10cSrcweir 1365*cdf0e10cSrcweirif ( $contains_internal_cabfiles ) 1366*cdf0e10cSrcweir{ 1367*cdf0e10cSrcweir # Set unpackdir 1368*cdf0e10cSrcweir my $cabdir = $helperdir . $separator . "internal_cabs"; 1369*cdf0e10cSrcweir create_directory($cabdir); 1370*cdf0e10cSrcweir my $from = cwd(); 1371*cdf0e10cSrcweir chdir($cabdir); 1372*cdf0e10cSrcweir # Exclude all cabinet files from database 1373*cdf0e10cSrcweir my $all_excluded_cabs = extract_cabs_from_database($databasepath, $all_internal_cab_files); 1374*cdf0e10cSrcweir print "Unpacking files from internal cabinet file(s)\n"; 1375*cdf0e10cSrcweir foreach my $cabfile ( @{$all_excluded_cabs} ) { unpack_cabinet_file($cabfile, $unpackdir); } 1376*cdf0e10cSrcweir chdir($from); 1377*cdf0e10cSrcweir} 1378*cdf0e10cSrcweir 1379*cdf0e10cSrcweir# Unpack all cab files into $helperdir, cab files must be located next to msi database 1380*cdf0e10cSrcweirmy $installdir = $databasepath; 1381*cdf0e10cSrcweir 1382*cdf0e10cSrcweirget_path_from_fullqualifiedname(\$installdir); 1383*cdf0e10cSrcweir 1384*cdf0e10cSrcweirmy $databasefilename = $databasepath; 1385*cdf0e10cSrcweirmake_absolute_filename_to_relative_filename(\$databasefilename); 1386*cdf0e10cSrcweir 1387*cdf0e10cSrcweirmy $cabfiles = find_file_with_file_extension("cab", $installdir); 1388*cdf0e10cSrcweir 1389*cdf0e10cSrcweirif (( $#{$cabfiles} < 0 ) && ( ! $contains_internal_cabfiles )) { exit_program("ERROR: Did not find any cab file in directory $installdir"); } 1390*cdf0e10cSrcweir 1391*cdf0e10cSrcweirprint "Unpacking files from cabinet file(s)\n"; 1392*cdf0e10cSrcweirfor ( my $i = 0; $i <= $#{$cabfiles}; $i++ ) 1393*cdf0e10cSrcweir{ 1394*cdf0e10cSrcweir my $cabfile = $installdir . $separator . ${$cabfiles}[$i]; 1395*cdf0e10cSrcweir unpack_cabinet_file($cabfile, $unpackdir); 1396*cdf0e10cSrcweir} 1397*cdf0e10cSrcweir 1398*cdf0e10cSrcweir# Reading tables 1399*cdf0e10cSrcweir$filename = $helperdir . $separator . "Directory.idt"; 1400*cdf0e10cSrcweir$filecontent = read_file($filename); 1401*cdf0e10cSrcweirmy $dirhash = analyze_directory_file($filecontent); 1402*cdf0e10cSrcweir 1403*cdf0e10cSrcweir$filename = $helperdir . $separator . "Component.idt"; 1404*cdf0e10cSrcweir$filecontent = read_file($filename); 1405*cdf0e10cSrcweirmy $componenthash = analyze_component_file($filecontent); 1406*cdf0e10cSrcweir 1407*cdf0e10cSrcweir$filename = $helperdir . $separator . "File.idt"; 1408*cdf0e10cSrcweir$filecontent = read_file($filename); 1409*cdf0e10cSrcweirmy ( $filehash, $fileorder, $maxsequence ) = analyze_file_file($filecontent); 1410*cdf0e10cSrcweir 1411*cdf0e10cSrcweir# Creating the directory structure 1412*cdf0e10cSrcweirmy $fullpathhash = create_directory_structure($dirhash, $targetdir); 1413*cdf0e10cSrcweir 1414*cdf0e10cSrcweir# Copying files 1415*cdf0e10cSrcweirmy ($unopkgfile) = copy_files_into_directory_structure($fileorder, $filehash, $componenthash, $fullpathhash, $maxsequence, $unpackdir, $installdir, $dirhash); 1416*cdf0e10cSrcweirif ( $^O =~ /cygwin/i ) { change_privileges_full($targetdir); } 1417*cdf0e10cSrcweir 1418*cdf0e10cSrcweirmy $msidatabase = $targetdir . $separator . $databasefilename; 1419*cdf0e10cSrcweirmy $copyreturn = copy($databasepath, $msidatabase); 1420*cdf0e10cSrcweirif ( ! $copyreturn) { exit_program("ERROR: Could not copy $source to $dest\n"); } 1421*cdf0e10cSrcweir 1422*cdf0e10cSrcweir# Reading tables 1423*cdf0e10cSrcweir$filename = $helperdir . $separator . "CustomAction.idt"; 1424*cdf0e10cSrcweir$filecontent = read_file($filename); 1425*cdf0e10cSrcweirmy $register_extensions_exists = analyze_customaction_file($filecontent); 1426*cdf0e10cSrcweir 1427*cdf0e10cSrcweir# Removing empty dirs in extension folder 1428*cdf0e10cSrcweirmy ( $extensionfolder, $preregdir ) = get_extensions_dir($unopkgfile); 1429*cdf0e10cSrcweirif ( -d $extensionfolder ) { remove_empty_dirs_in_folder($extensionfolder, 1); } 1430*cdf0e10cSrcweir 1431*cdf0e10cSrcweirif ( $register_extensions_exists ) 1432*cdf0e10cSrcweir{ 1433*cdf0e10cSrcweir # Registering extensions 1434*cdf0e10cSrcweir register_extensions($unopkgfile, $temppath, $preregdir); 1435*cdf0e10cSrcweir} 1436*cdf0e10cSrcweir 1437*cdf0e10cSrcweir# Saving info in Summary Information Stream of msi database (required for following patches) 1438*cdf0e10cSrcweirif ( $msiinfo_available ) { write_sis_info($msidatabase); } 1439*cdf0e10cSrcweir 1440*cdf0e10cSrcweir# Removing the helper directory 1441*cdf0e10cSrcweirremove_complete_directory($temppath, 1); 1442*cdf0e10cSrcweir 1443*cdf0e10cSrcweirprint "\nSuccessful installation: " . get_time_string(); 1444