| Filename | /cygdrive/c/lo/libo-master/instsetoo_native/util/C:/lo/libo-master/solenv/bin/modules/installer/windows/admin.pm |
| Statements | Executed 17 statements in 5.31ms |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 1 | 1 | 1 | 400µs | 455µs | installer::windows::admin::BEGIN@30 |
| 1 | 1 | 1 | 17µs | 23µs | installer::windows::admin::BEGIN@36 |
| 1 | 1 | 1 | 15µs | 18µs | installer::windows::admin::BEGIN@37 |
| 1 | 1 | 1 | 14µs | 16µs | installer::windows::admin::BEGIN@31 |
| 1 | 1 | 1 | 13µs | 15µs | installer::windows::admin::BEGIN@33 |
| 1 | 1 | 1 | 13µs | 16µs | installer::windows::admin::BEGIN@35 |
| 1 | 1 | 1 | 13µs | 15µs | installer::windows::admin::BEGIN@32 |
| 1 | 1 | 1 | 13µs | 16µs | installer::windows::admin::BEGIN@34 |
| 0 | 0 | 0 | 0s | 0s | installer::windows::admin::analyze_component_file |
| 0 | 0 | 0 | 0s | 0s | installer::windows::admin::analyze_directory_file |
| 0 | 0 | 0 | 0s | 0s | installer::windows::admin::analyze_file_file |
| 0 | 0 | 0 | 0s | 0s | installer::windows::admin::copy_files_into_directory_structure |
| 0 | 0 | 0 | 0s | 0s | installer::windows::admin::create_directory_structure |
| 0 | 0 | 0 | 0s | 0s | installer::windows::admin::create_directory_tree |
| 0 | 0 | 0 | 0s | 0s | installer::windows::admin::extract_tables_from_pcpfile |
| 0 | 0 | 0 | 0s | 0s | installer::windows::admin::get_sis_time_string |
| 0 | 0 | 0 | 0s | 0s | installer::windows::admin::make_admin_install |
| 0 | 0 | 0 | 0s | 0s | installer::windows::admin::unpack_cabinet_file |
| 0 | 0 | 0 | 0s | 0s | installer::windows::admin::write_sis_info |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | #************************************************************************* | ||||
| 2 | # | ||||
| 3 | # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | ||||
| 4 | # | ||||
| 5 | # Copyright 2000, 2010 Oracle and/or its affiliates. | ||||
| 6 | # | ||||
| 7 | # OpenOffice.org - a multi-platform office productivity suite | ||||
| 8 | # | ||||
| 9 | # This file is part of OpenOffice.org. | ||||
| 10 | # | ||||
| 11 | # OpenOffice.org is free software: you can redistribute it and/or modify | ||||
| 12 | # it under the terms of the GNU Lesser General Public License version 3 | ||||
| 13 | # only, as published by the Free Software Foundation. | ||||
| 14 | # | ||||
| 15 | # OpenOffice.org is distributed in the hope that it will be useful, | ||||
| 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
| 18 | # GNU Lesser General Public License version 3 for more details | ||||
| 19 | # (a copy is included in the LICENSE file that accompanied this code). | ||||
| 20 | # | ||||
| 21 | # You should have received a copy of the GNU Lesser General Public License | ||||
| 22 | # version 3 along with OpenOffice.org. If not, see | ||||
| 23 | # <http://www.openoffice.org/license.html> | ||||
| 24 | # for a copy of the LGPLv3 License. | ||||
| 25 | # | ||||
| 26 | #************************************************************************* | ||||
| 27 | |||||
| 28 | package installer::windows::admin; | ||||
| 29 | |||||
| 30 | 2 | 59µs | 2 | 510µs | # spent 455µs (400+55) within installer::windows::admin::BEGIN@30 which was called:
# once (400µs+55µs) by installer::windows::msp::BEGIN@39 at line 30 # spent 455µs making 1 call to installer::windows::admin::BEGIN@30
# spent 55µs making 1 call to Exporter::import |
| 31 | 2 | 52µs | 2 | 19µs | # spent 16µs (14+3) within installer::windows::admin::BEGIN@31 which was called:
# once (14µs+3µs) by installer::windows::msp::BEGIN@39 at line 31 # spent 16µs making 1 call to installer::windows::admin::BEGIN@31
# spent 2µs making 1 call to UNIVERSAL::import |
| 32 | 2 | 52µs | 2 | 17µs | # spent 15µs (13+2) within installer::windows::admin::BEGIN@32 which was called:
# once (13µs+2µs) by installer::windows::msp::BEGIN@39 at line 32 # spent 15µs making 1 call to installer::windows::admin::BEGIN@32
# spent 2µs making 1 call to UNIVERSAL::import |
| 33 | 2 | 51µs | 2 | 16µs | # spent 15µs (13+1) within installer::windows::admin::BEGIN@33 which was called:
# once (13µs+1µs) by installer::windows::msp::BEGIN@39 at line 33 # spent 15µs making 1 call to installer::windows::admin::BEGIN@33
# spent 2µs making 1 call to UNIVERSAL::import |
| 34 | 2 | 51µs | 2 | 18µs | # spent 16µs (13+3) within installer::windows::admin::BEGIN@34 which was called:
# once (13µs+3µs) by installer::windows::msp::BEGIN@39 at line 34 # spent 16µs making 1 call to installer::windows::admin::BEGIN@34
# spent 3µs making 1 call to UNIVERSAL::import |
| 35 | 2 | 52µs | 2 | 18µs | # spent 16µs (13+3) within installer::windows::admin::BEGIN@35 which was called:
# once (13µs+3µs) by installer::windows::msp::BEGIN@39 at line 35 # spent 16µs making 1 call to installer::windows::admin::BEGIN@35
# spent 3µs making 1 call to UNIVERSAL::import |
| 36 | 2 | 58µs | 2 | 29µs | # spent 23µs (17+6) within installer::windows::admin::BEGIN@36 which was called:
# once (17µs+6µs) by installer::windows::msp::BEGIN@39 at line 36 # spent 23µs making 1 call to installer::windows::admin::BEGIN@36
# spent 6µs making 1 call to UNIVERSAL::import |
| 37 | 2 | 4.92ms | 2 | 20µs | # spent 18µs (15+3) within installer::windows::admin::BEGIN@37 which was called:
# once (15µs+3µs) by installer::windows::msp::BEGIN@39 at line 37 # spent 18µs making 1 call to installer::windows::admin::BEGIN@37
# spent 2µs making 1 call to UNIVERSAL::import |
| 38 | |||||
| 39 | ################################################################################# | ||||
| 40 | # Unpacking cabinet files with expand | ||||
| 41 | ################################################################################# | ||||
| 42 | |||||
| 43 | sub unpack_cabinet_file | ||||
| 44 | { | ||||
| 45 | my ($cabfilename, $unpackdir) = @_; | ||||
| 46 | |||||
| 47 | my $infoline = "Unpacking cabinet file: $cabfilename\n"; | ||||
| 48 | push( @installer::globals::logfileinfo, $infoline); | ||||
| 49 | |||||
| 50 | my $expandfile = "expand.exe"; # Has to be in the path | ||||
| 51 | if ( $installer::globals::isunix ) | ||||
| 52 | { | ||||
| 53 | $infoline = "ERROR: We need to change this to use cabextract instead of expand.exe\n"; | ||||
| 54 | push( @installer::globals::logfileinfo, $infoline); | ||||
| 55 | } | ||||
| 56 | |||||
| 57 | # expand.exe has to be located in the system directory. | ||||
| 58 | # Cygwin has another tool expand.exe, that converts tabs to spaces. This cannot be used of course. | ||||
| 59 | # But this wrong expand.exe is typically in the PATH before this expand.exe, to unpack | ||||
| 60 | # cabinet files. | ||||
| 61 | |||||
| 62 | if ( $^O =~ /cygwin/i ) | ||||
| 63 | { | ||||
| 64 | $expandfile = qx(cygpath -u "$ENV{WINDIR}"/System32/expand.exe); | ||||
| 65 | chomp $expandfile; | ||||
| 66 | } | ||||
| 67 | |||||
| 68 | my $expandlogfile = $unpackdir . $installer::globals::separator . "expand.log"; | ||||
| 69 | |||||
| 70 | # exclude cabinet file | ||||
| 71 | |||||
| 72 | my $systemcall = ""; | ||||
| 73 | if ( $^O =~ /cygwin/i ) { | ||||
| 74 | my $localunpackdir = qx{cygpath -w "$unpackdir"}; | ||||
| 75 | chomp ($localunpackdir); | ||||
| 76 | $localunpackdir =~ s/\\/\\\\/g; | ||||
| 77 | $cabfilename =~ s/\\/\\\\/g; | ||||
| 78 | $cabfilename =~ s/\s*$//g; | ||||
| 79 | $systemcall = $expandfile . " " . $cabfilename . " -F:\* " . $localunpackdir . " \> " . $expandlogfile; | ||||
| 80 | } | ||||
| 81 | else | ||||
| 82 | { | ||||
| 83 | $systemcall = $expandfile . " " . $cabfilename . " -F:\* " . $unpackdir . " \> " . $expandlogfile; | ||||
| 84 | } | ||||
| 85 | |||||
| 86 | my $returnvalue = system($systemcall); | ||||
| 87 | $infoline = "Systemcall: $systemcall\n"; | ||||
| 88 | push( @installer::globals::logfileinfo, $infoline); | ||||
| 89 | |||||
| 90 | if ($returnvalue) | ||||
| 91 | { | ||||
| 92 | $infoline = "ERROR: Could not execute $systemcall !\n"; | ||||
| 93 | push( @installer::globals::logfileinfo, $infoline); | ||||
| 94 | installer::exiter::exit_program("ERROR: Could not extract cabinet file: $mergemodulehash->{'cabinetfile'} !", "change_file_table"); | ||||
| 95 | } | ||||
| 96 | else | ||||
| 97 | { | ||||
| 98 | $infoline = "Success: Executed $systemcall successfully!\n"; | ||||
| 99 | push( @installer::globals::logfileinfo, $infoline); | ||||
| 100 | } | ||||
| 101 | } | ||||
| 102 | |||||
| 103 | ################################################################################# | ||||
| 104 | # Extracting tables from msi database | ||||
| 105 | ################################################################################# | ||||
| 106 | |||||
| 107 | sub extract_tables_from_pcpfile | ||||
| 108 | { | ||||
| 109 | my ($fullmsidatabasepath, $workdir, $tablelist) = @_; | ||||
| 110 | |||||
| 111 | my $msidb = "msidb.exe"; # Has to be in the path | ||||
| 112 | if ( $installer::globals::isunix ) | ||||
| 113 | { | ||||
| 114 | $msidb = "$ENV{'OUTDIR_FOR_BUILD'}/bin/msidb.exe"; | ||||
| 115 | } | ||||
| 116 | my $infoline = ""; | ||||
| 117 | my $systemcall = ""; | ||||
| 118 | my $returnvalue = ""; | ||||
| 119 | |||||
| 120 | my $localfullmsidatabasepath = $fullmsidatabasepath; | ||||
| 121 | |||||
| 122 | # Export of all tables by using "*" | ||||
| 123 | |||||
| 124 | if ( $^O =~ /cygwin/i ) { | ||||
| 125 | # Copying the msi database locally guarantees the format of the directory. | ||||
| 126 | # Otherwise it is defined in the file of UPDATE_DATABASE_LISTNAME | ||||
| 127 | |||||
| 128 | my $msifilename = $localfullmsidatabasepath; | ||||
| 129 | installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$msifilename); | ||||
| 130 | my $destdatabasename = $workdir . $installer::globals::separator . $msifilename; | ||||
| 131 | installer::systemactions::copy_one_file($localfullmsidatabasepath, $destdatabasename); | ||||
| 132 | $localfullmsidatabasepath = $destdatabasename; | ||||
| 133 | |||||
| 134 | chomp( $localfullmsidatabasepath = qx{cygpath -w "$localfullmsidatabasepath"} ); | ||||
| 135 | chomp( $workdir = qx{cygpath -w "$workdir"} ); | ||||
| 136 | |||||
| 137 | # msidb.exe really wants backslashes. (And double escaping because system() expands the string.) | ||||
| 138 | $localfullmsidatabasepath =~ s/\\/\\\\/g; | ||||
| 139 | $workdir =~ s/\\/\\\\/g; | ||||
| 140 | |||||
| 141 | # and if there are still slashes, they also need to be double backslash | ||||
| 142 | $localfullmsidatabasepath =~ s/\//\\\\/g; | ||||
| 143 | $workdir =~ s/\//\\\\/g; | ||||
| 144 | } | ||||
| 145 | |||||
| 146 | $systemcall = $msidb . " -d " . $localfullmsidatabasepath . " -f " . $workdir . " -e $tablelist"; | ||||
| 147 | $returnvalue = system($systemcall); | ||||
| 148 | |||||
| 149 | $infoline = "Systemcall: $systemcall\n"; | ||||
| 150 | push( @installer::globals::logfileinfo, $infoline); | ||||
| 151 | |||||
| 152 | if ($returnvalue) | ||||
| 153 | { | ||||
| 154 | $infoline = "ERROR: Could not execute $systemcall !\n"; | ||||
| 155 | push( @installer::globals::logfileinfo, $infoline); | ||||
| 156 | installer::exiter::exit_program("ERROR: Could not exclude tables from pcp file: $localfullmsidatabasepath !", "extract_tables_from_pcpfile"); | ||||
| 157 | } | ||||
| 158 | else | ||||
| 159 | { | ||||
| 160 | $infoline = "Success: Executed $systemcall successfully!\n"; | ||||
| 161 | push( @installer::globals::logfileinfo, $infoline); | ||||
| 162 | } | ||||
| 163 | } | ||||
| 164 | |||||
| 165 | ################################################################################ | ||||
| 166 | # Analyzing the content of Directory.idt | ||||
| 167 | ################################################################################# | ||||
| 168 | |||||
| 169 | sub analyze_directory_file | ||||
| 170 | { | ||||
| 171 | my ($filecontent) = @_; | ||||
| 172 | |||||
| 173 | my %table = (); | ||||
| 174 | |||||
| 175 | for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) | ||||
| 176 | { | ||||
| 177 | if (( $i == 0 ) || ( $i == 1 ) || ( $i == 2 )) { next; } | ||||
| 178 | |||||
| 179 | if ( ${$filecontent}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\s*$/ ) | ||||
| 180 | { | ||||
| 181 | my $dir = $1; | ||||
| 182 | my $parent = $2; | ||||
| 183 | my $name = $3; | ||||
| 184 | |||||
| 185 | if ( $name =~ /^\s*(.*?)\s*\:\s*(.*?)\s*$/ ) { $name = $2; } | ||||
| 186 | if ( $name =~ /^\s*(.*?)\s*\|\s*(.*?)\s*$/ ) { $name = $2; } | ||||
| 187 | |||||
| 188 | my %helphash = (); | ||||
| 189 | $helphash{'Directory_Parent'} = $parent; | ||||
| 190 | $helphash{'DefaultDir'} = $name; | ||||
| 191 | $table{$dir} = \%helphash; | ||||
| 192 | } | ||||
| 193 | } | ||||
| 194 | |||||
| 195 | return \%table; | ||||
| 196 | } | ||||
| 197 | |||||
| 198 | ################################################################################# | ||||
| 199 | # Analyzing the content of Component.idt | ||||
| 200 | ################################################################################# | ||||
| 201 | |||||
| 202 | sub analyze_component_file | ||||
| 203 | { | ||||
| 204 | my ($filecontent) = @_; | ||||
| 205 | |||||
| 206 | my %table = (); | ||||
| 207 | |||||
| 208 | for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) | ||||
| 209 | { | ||||
| 210 | if (( $i == 0 ) || ( $i == 1 ) || ( $i == 2 )) { next; } | ||||
| 211 | |||||
| 212 | if ( ${$filecontent}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) | ||||
| 213 | { | ||||
| 214 | my $component = $1; | ||||
| 215 | my $dir = $3; | ||||
| 216 | |||||
| 217 | $table{$component} = $dir; | ||||
| 218 | } | ||||
| 219 | } | ||||
| 220 | |||||
| 221 | return \%table; | ||||
| 222 | } | ||||
| 223 | |||||
| 224 | ################################################################################# | ||||
| 225 | # Analyzing the content of File.idt | ||||
| 226 | ################################################################################# | ||||
| 227 | |||||
| 228 | sub analyze_file_file | ||||
| 229 | { | ||||
| 230 | my ($filecontent) = @_; | ||||
| 231 | |||||
| 232 | my %table = (); | ||||
| 233 | my %fileorder = (); | ||||
| 234 | my $maxsequence = 0; | ||||
| 235 | |||||
| 236 | for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) | ||||
| 237 | { | ||||
| 238 | if (( $i == 0 ) || ( $i == 1 ) || ( $i == 2 )) { next; } | ||||
| 239 | |||||
| 240 | if ( ${$filecontent}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) | ||||
| 241 | { | ||||
| 242 | my $file = $1; | ||||
| 243 | my $comp = $2; | ||||
| 244 | my $filename = $3; | ||||
| 245 | my $sequence = $8; | ||||
| 246 | |||||
| 247 | if ( $filename =~ /^\s*(.*?)\s*\|\s*(.*?)\s*$/ ) { $filename = $2; } | ||||
| 248 | |||||
| 249 | my %helphash = (); | ||||
| 250 | $helphash{'Component'} = $comp; | ||||
| 251 | $helphash{'FileName'} = $filename; | ||||
| 252 | $helphash{'Sequence'} = $sequence; | ||||
| 253 | |||||
| 254 | $table{$file} = \%helphash; | ||||
| 255 | |||||
| 256 | $fileorder{$sequence} = $file; | ||||
| 257 | |||||
| 258 | if ( $sequence > $maxsequence ) { $maxsequence = $sequence; } | ||||
| 259 | } | ||||
| 260 | } | ||||
| 261 | |||||
| 262 | return (\%table, \%fileorder, $maxsequence); | ||||
| 263 | } | ||||
| 264 | |||||
| 265 | #################################################################################### | ||||
| 266 | # Recursively creating the directory tree | ||||
| 267 | #################################################################################### | ||||
| 268 | |||||
| 269 | sub create_directory_tree | ||||
| 270 | { | ||||
| 271 | my ($parent, $pathcollector, $fulldir, $dirhash) = @_; | ||||
| 272 | |||||
| 273 | foreach my $dir ( keys %{$dirhash} ) | ||||
| 274 | { | ||||
| 275 | if (( $dirhash->{$dir}->{'Directory_Parent'} eq $parent ) && ( $dirhash->{$dir}->{'DefaultDir'} ne "." )) | ||||
| 276 | { | ||||
| 277 | my $dirname = $dirhash->{$dir}->{'DefaultDir'}; | ||||
| 278 | # Create the directory | ||||
| 279 | my $newdir = $fulldir . $installer::globals::separator . $dirname; | ||||
| 280 | if ( ! -f $newdir ) { mkdir $newdir; } | ||||
| 281 | # Saving in collector | ||||
| 282 | $pathcollector->{$dir} = $newdir; | ||||
| 283 | # Iteration | ||||
| 284 | create_directory_tree($dir, $pathcollector, $newdir, $dirhash); | ||||
| 285 | } | ||||
| 286 | } | ||||
| 287 | } | ||||
| 288 | |||||
| 289 | #################################################################################### | ||||
| 290 | # Creating the directory tree | ||||
| 291 | #################################################################################### | ||||
| 292 | |||||
| 293 | sub create_directory_structure | ||||
| 294 | { | ||||
| 295 | my ($dirhash, $targetdir) = @_; | ||||
| 296 | |||||
| 297 | my %fullpathhash = (); | ||||
| 298 | |||||
| 299 | my @startparents = ("TARGETDIR", "INSTALLLOCATION"); | ||||
| 300 | |||||
| 301 | foreach $dir (@startparents) { create_directory_tree($dir, \%fullpathhash, $targetdir, $dirhash); } | ||||
| 302 | |||||
| 303 | # Also adding the paths of the startparents | ||||
| 304 | foreach $dir (@startparents) | ||||
| 305 | { | ||||
| 306 | if ( ! exists($fullpathhash{$dir}) ) { $fullpathhash{$dir} = $targetdir; } | ||||
| 307 | } | ||||
| 308 | |||||
| 309 | return \%fullpathhash; | ||||
| 310 | } | ||||
| 311 | |||||
| 312 | #################################################################################### | ||||
| 313 | # Copying files into installation set | ||||
| 314 | #################################################################################### | ||||
| 315 | |||||
| 316 | sub copy_files_into_directory_structure | ||||
| 317 | { | ||||
| 318 | my ($fileorder, $filehash, $componenthash, $fullpathhash, $maxsequence, $unpackdir, $installdir, $dirhash) = @_; | ||||
| 319 | |||||
| 320 | for ( my $i = 1; $i <= $maxsequence; $i++ ) | ||||
| 321 | { | ||||
| 322 | if ( exists($fileorder->{$i}) ) | ||||
| 323 | { | ||||
| 324 | my $file = $fileorder->{$i}; | ||||
| 325 | if ( ! exists($filehash->{$file}->{'Component'}) ) { installer::exiter::exit_program("ERROR: Did not find component for file: \"$file\".", "copy_files_into_directory_structure"); } | ||||
| 326 | my $component = $filehash->{$file}->{'Component'}; | ||||
| 327 | if ( ! exists($componenthash->{$component}) ) { installer::exiter::exit_program("ERROR: Did not find directory for component: \"$component\".", "copy_files_into_directory_structure"); } | ||||
| 328 | my $dirname = $componenthash->{$component}; | ||||
| 329 | if ( ! exists($fullpathhash->{$dirname}) ) { installer::exiter::exit_program("ERROR: Did not find full directory path for dir: \"$dirname\".", "copy_files_into_directory_structure"); } | ||||
| 330 | my $destdir = $fullpathhash->{$dirname}; | ||||
| 331 | if ( ! exists($filehash->{$file}->{'FileName'}) ) { installer::exiter::exit_program("ERROR: Did not find \"FileName\" for file: \"$file\".", "copy_files_into_directory_structure"); } | ||||
| 332 | my $destfile = $filehash->{$file}->{'FileName'}; | ||||
| 333 | |||||
| 334 | $destfile = $destdir . $installer::globals::separator . $destfile; | ||||
| 335 | my $sourcefile = $unpackdir . $installer::globals::separator . $file; | ||||
| 336 | |||||
| 337 | if ( ! -f $sourcefile ) | ||||
| 338 | { | ||||
| 339 | # It is possible, that this was an unpacked file | ||||
| 340 | # Looking in the dirhash, to find the subdirectory in the installation set (the id is $dirname) | ||||
| 341 | # subdir is not recursively analyzed, only one directory. | ||||
| 342 | |||||
| 343 | my $oldsourcefile = $sourcefile; | ||||
| 344 | my $subdir = ""; | ||||
| 345 | if ( exists($dirhash->{$dirname}->{'DefaultDir'}) ) { $subdir = $dirhash->{$dirname}->{'DefaultDir'} . $installer::globals::separator; } | ||||
| 346 | my $realfilename = $filehash->{$file}->{'FileName'}; | ||||
| 347 | my $localinstalldir = $installdir; | ||||
| 348 | |||||
| 349 | $localinstalldir =~ s/\\\s*$//; | ||||
| 350 | $localinstalldir =~ s/\/\s*$//; | ||||
| 351 | |||||
| 352 | $sourcefile = $localinstalldir . $installer::globals::separator . $subdir . $realfilename; | ||||
| 353 | |||||
| 354 | if ( ! -f $sourcefile ) | ||||
| 355 | { | ||||
| 356 | installer::exiter::exit_program("ERROR: File not found: \"$oldsourcefile\" (or \"$sourcefile\").", "copy_files_into_directory_structure"); | ||||
| 357 | } | ||||
| 358 | } | ||||
| 359 | |||||
| 360 | my $copyreturn = copy($sourcefile, $destfile); | ||||
| 361 | |||||
| 362 | if ( ! $copyreturn) # only logging problems | ||||
| 363 | { | ||||
| 364 | my $infoline = "ERROR: Could not copy $sourcefile to $destfile (insufficient disc space for $destfile ?)\n"; | ||||
| 365 | $returnvalue = 0; | ||||
| 366 | push(@installer::globals::logfileinfo, $infoline); | ||||
| 367 | installer::exiter::exit_program($infoline, "copy_files_into_directory_structure"); | ||||
| 368 | } | ||||
| 369 | } | ||||
| 370 | } | ||||
| 371 | } | ||||
| 372 | |||||
| 373 | |||||
| 374 | ############################################################### | ||||
| 375 | # Setting the time string for the | ||||
| 376 | # Summary Information stream in the | ||||
| 377 | # msi database of the admin installations. | ||||
| 378 | ############################################################### | ||||
| 379 | |||||
| 380 | sub get_sis_time_string | ||||
| 381 | { | ||||
| 382 | # Syntax: <yyyy/mm/dd hh:mm:ss> | ||||
| 383 | my $second = (localtime())[0]; | ||||
| 384 | my $minute = (localtime())[1]; | ||||
| 385 | my $hour = (localtime())[2]; | ||||
| 386 | my $day = (localtime())[3]; | ||||
| 387 | my $month = (localtime())[4]; | ||||
| 388 | my $year = 1900 + (localtime())[5]; | ||||
| 389 | |||||
| 390 | $month++; # zero based month | ||||
| 391 | |||||
| 392 | if ( $second < 10 ) { $second = "0" . $second; } | ||||
| 393 | if ( $minute < 10 ) { $minute = "0" . $minute; } | ||||
| 394 | if ( $hour < 10 ) { $hour = "0" . $hour; } | ||||
| 395 | if ( $day < 10 ) { $day = "0" . $day; } | ||||
| 396 | if ( $month < 10 ) { $month = "0" . $month; } | ||||
| 397 | |||||
| 398 | my $timestring = $year . "/" . $month . "/" . $day . " " . $hour . ":" . $minute . ":" . $second; | ||||
| 399 | |||||
| 400 | return $timestring; | ||||
| 401 | } | ||||
| 402 | |||||
| 403 | ############################################################### | ||||
| 404 | # Writing content of administrative installations into | ||||
| 405 | # Summary Information Stream of msi database. | ||||
| 406 | # This is required for example for following | ||||
| 407 | # patch processes using Windows Installer service. | ||||
| 408 | ############################################################### | ||||
| 409 | |||||
| 410 | sub write_sis_info | ||||
| 411 | { | ||||
| 412 | my ($msidatabase) = @_ ; | ||||
| 413 | |||||
| 414 | if ( ! -f $msidatabase ) { installer::exiter::exit_program("ERROR: Cannot find file $msidatabase", "write_sis_info"); } | ||||
| 415 | |||||
| 416 | my $msiinfo = "msiinfo.exe"; # Has to be in the path | ||||
| 417 | if ( $installer::globals::isunix ) | ||||
| 418 | { | ||||
| 419 | $msiinfo = "$ENV{'OUTDIR_FOR_BUILD'}/bin/msiinfo.exe"; | ||||
| 420 | } | ||||
| 421 | my $infoline = ""; | ||||
| 422 | my $systemcall = ""; | ||||
| 423 | my $returnvalue = ""; | ||||
| 424 | |||||
| 425 | # Required setting for administrative installations: | ||||
| 426 | # -w 4 (source files are unpacked), wordcount | ||||
| 427 | # -s <date of admin installation>, LastPrinted, Syntax: <yyyy/mm/dd hh:mm:ss> | ||||
| 428 | # -l <person_making_admin_installation>, LastSavedBy | ||||
| 429 | |||||
| 430 | my $wordcount = 4; # Unpacked files | ||||
| 431 | my $lastprinted = get_sis_time_string(); | ||||
| 432 | my $lastsavedby = "Installer"; | ||||
| 433 | |||||
| 434 | my $localmsidatabase = $msidatabase; | ||||
| 435 | |||||
| 436 | if( $^O =~ /cygwin/i ) | ||||
| 437 | { | ||||
| 438 | $localmsidatabase = qx{cygpath -w "$localmsidatabase"}; | ||||
| 439 | $localmsidatabase =~ s/\\/\\\\/g; | ||||
| 440 | $localmsidatabase =~ s/\s*$//g; | ||||
| 441 | } | ||||
| 442 | |||||
| 443 | $systemcall = $msiinfo . " " . "\"" . $localmsidatabase . "\"" . " -w " . $wordcount . " -s " . "\"" . $lastprinted . "\"" . " -l $lastsavedby"; | ||||
| 444 | push(@installer::globals::logfileinfo, $systemcall); | ||||
| 445 | $returnvalue = system($systemcall); | ||||
| 446 | |||||
| 447 | if ($returnvalue) | ||||
| 448 | { | ||||
| 449 | $infoline = "ERROR: Could not execute $systemcall !\n"; | ||||
| 450 | push(@installer::globals::logfileinfo, $infoline); | ||||
| 451 | installer::exiter::exit_program($infoline, "write_sis_info"); | ||||
| 452 | } | ||||
| 453 | } | ||||
| 454 | |||||
| 455 | #################################################################################### | ||||
| 456 | # Simulating an administrative installation | ||||
| 457 | #################################################################################### | ||||
| 458 | |||||
| 459 | sub make_admin_install | ||||
| 460 | { | ||||
| 461 | my ($databasepath, $targetdir) = @_; | ||||
| 462 | |||||
| 463 | # Create helper directory | ||||
| 464 | |||||
| 465 | installer::logger::print_message( "... installing $databasepath in directory $targetdir ...\n" ); | ||||
| 466 | |||||
| 467 | my $helperdir = $targetdir . $installer::globals::separator . "installhelper"; | ||||
| 468 | installer::systemactions::create_directory($helperdir); | ||||
| 469 | |||||
| 470 | # Get File.idt, Component.idt and Directory.idt from database | ||||
| 471 | |||||
| 472 | my $tablelist = "File Directory Component Registry"; | ||||
| 473 | extract_tables_from_pcpfile($databasepath, $helperdir, $tablelist); | ||||
| 474 | |||||
| 475 | # Unpack all cab files into $helperdir, cab files must be located next to msi database | ||||
| 476 | my $installdir = $databasepath; | ||||
| 477 | |||||
| 478 | if ( $^O =~ /cygwin/i ) { $installdir =~ s/\\/\//g; } # backslash to slash | ||||
| 479 | |||||
| 480 | installer::pathanalyzer::get_path_from_fullqualifiedname(\$installdir); | ||||
| 481 | |||||
| 482 | if ( $^O =~ /cygwin/i ) { $installdir =~ s/\//\\/g; } # slash to backslash | ||||
| 483 | |||||
| 484 | my $databasefilename = $databasepath; | ||||
| 485 | installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$databasefilename); | ||||
| 486 | |||||
| 487 | my $cabfiles = installer::systemactions::find_file_with_file_extension("cab", $installdir); | ||||
| 488 | |||||
| 489 | if ( $#{$cabfiles} < 0 ) { installer::exiter::exit_program("ERROR: Did not find any cab file in directory $installdir", "make_admin_install"); } | ||||
| 490 | |||||
| 491 | # Set unpackdir | ||||
| 492 | my $unpackdir = $helperdir . $installer::globals::separator . "unpack"; | ||||
| 493 | installer::systemactions::create_directory($unpackdir); | ||||
| 494 | |||||
| 495 | for ( my $i = 0; $i <= $#{$cabfiles}; $i++ ) | ||||
| 496 | { | ||||
| 497 | my $cabfile = ""; | ||||
| 498 | if ( $^O =~ /cygwin/i ) | ||||
| 499 | { | ||||
| 500 | $cabfile = $installdir . ${$cabfiles}[$i]; | ||||
| 501 | } | ||||
| 502 | else | ||||
| 503 | { | ||||
| 504 | $cabfile = $installdir . $installer::globals::separator . ${$cabfiles}[$i]; | ||||
| 505 | } | ||||
| 506 | unpack_cabinet_file($cabfile, $unpackdir); | ||||
| 507 | } | ||||
| 508 | |||||
| 509 | # Reading tables | ||||
| 510 | my $filename = $helperdir . $installer::globals::separator . "Directory.idt"; | ||||
| 511 | my $filecontent = installer::files::read_file($filename); | ||||
| 512 | my $dirhash = analyze_directory_file($filecontent); | ||||
| 513 | |||||
| 514 | $filename = $helperdir . $installer::globals::separator . "Component.idt"; | ||||
| 515 | my $componentfilecontent = installer::files::read_file($filename); | ||||
| 516 | my $componenthash = analyze_component_file($componentfilecontent); | ||||
| 517 | |||||
| 518 | $filename = $helperdir . $installer::globals::separator . "File.idt"; | ||||
| 519 | $filecontent = installer::files::read_file($filename); | ||||
| 520 | my ( $filehash, $fileorder, $maxsequence ) = analyze_file_file($filecontent); | ||||
| 521 | |||||
| 522 | # Creating the directory structure | ||||
| 523 | my $fullpathhash = create_directory_structure($dirhash, $targetdir); | ||||
| 524 | |||||
| 525 | # Copying files | ||||
| 526 | copy_files_into_directory_structure($fileorder, $filehash, $componenthash, $fullpathhash, $maxsequence, $unpackdir, $installdir, $dirhash); | ||||
| 527 | |||||
| 528 | my $msidatabase = $targetdir . $installer::globals::separator . $databasefilename; | ||||
| 529 | installer::systemactions::copy_one_file($databasepath, $msidatabase); | ||||
| 530 | |||||
| 531 | # Saving info in Summary Information Stream of msi database (required for following patches) | ||||
| 532 | write_sis_info($msidatabase); | ||||
| 533 | |||||
| 534 | return $msidatabase; | ||||
| 535 | } | ||||
| 536 | |||||
| 537 | 1 | 10µs | 1; |