diff options
Diffstat (limited to 'setup_native/scripts/admin.pl')
-rw-r--r-- | setup_native/scripts/admin.pl | 1443 |
1 files changed, 0 insertions, 1443 deletions
diff --git a/setup_native/scripts/admin.pl b/setup_native/scripts/admin.pl deleted file mode 100644 index 57cae516b..000000000 --- a/setup_native/scripts/admin.pl +++ /dev/null @@ -1,1443 +0,0 @@ -#************************************************************************* -# -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# Copyright 2000, 2010 Oracle and/or its affiliates. -# -# OpenOffice.org - a multi-platform office productivity suite -# -# This file is part of OpenOffice.org. -# -# OpenOffice.org is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License version 3 -# only, as published by the Free Software Foundation. -# -# OpenOffice.org is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License version 3 for more details -# (a copy is included in the LICENSE file that accompanied this code). -# -# You should have received a copy of the GNU Lesser General Public License -# version 3 along with OpenOffice.org. If not, see -# <http://www.openoffice.org/license.html> -# for a copy of the LGPLv3 License. -# -#************************************************************************* - -use Cwd; -use File::Copy; - -################################################################################# -# Global settings -################################################################################# - -BEGIN -{ - $prog = "msi installer"; - $targetdir = ""; - $databasepath = ""; - $starttime = ""; - $globaltempdirname = "ooopackaging"; - $savetemppath = ""; - $msiinfo_available = 0; - $path_displayed = 0; - $localmsidbpath = ""; - - $plat = $^O; - - if ( $plat =~ /cygwin/i ) - { - $separator = "/"; - $pathseparator = "\:"; - } - else - { - $separator = "\\"; - $pathseparator = "\;"; - } -} - -################################################################################# -# Program information -################################################################################# - -sub usage -{ - print <<Ende; ----------------------------------------------------------------------- -This program installs a Windows Installer installation set -without using msiexec.exe. The installation is comparable -with an administrative installation using the Windows Installer -service. -Required parameter: --d Path to installation set or msi database --t Target directory ---------------------------------------------------------------------- -Ende - exit(-1); -} - -################################################################################# -# Collecting parameter -################################################################################# - -sub getparameter -{ - if (( $#ARGV < 3 ) || ( $#ARGV > 3 )) { usage(); } - - while ( $#ARGV >= 0 ) - { - my $param = shift(@ARGV); - - if ($param eq "-t") { $targetdir = shift(@ARGV); } - elsif ($param eq "-d") { $databasepath = shift(@ARGV); } - else - { - print "\n**********************************************\n"; - print "Error: Unknows parameter: $param"; - print "\n**********************************************\n"; - usage(); - exit(-1); - } - } -} - -################################################################################# -# Checking content of parameter -################################################################################# - -sub controlparameter -{ - if ( $targetdir eq "" ) - { - print "\n******************************************************\n"; - print "Error: Target directory not defined (parameter -t)!"; - print "\n******************************************************\n"; - usage(); - exit(-1); - } - - if ( $databasepath eq "" ) - { - print "\n******************************************************\n"; - print "Error: Path to msi database not defined (parameter -d)!"; - print "\n******************************************************\n"; - usage(); - exit(-1); - } - - if ( -d $databasepath ) - { - $databasepath =~ s/\\\s*$//; - $databasepath =~ s/\/\s*$//; - - my $msifiles = find_file_with_file_extension("msi", $databasepath); - - if ( $#{$msifiles} < 0 ) { exit_program("ERROR: Did not find msi database in directory $installationdir"); } - if ( $#{$msifiles} > 0 ) { exit_program("ERROR: Did find more than one msi database in directory $installationdir"); } - - $databasepath = $databasepath . $separator . ${$msifiles}[0]; - } - - if ( ! -f $databasepath ) { exit_program("ERROR: Did not find msi database in directory $databasepath."); } - - if ( ! -d $targetdir ) { create_directories($targetdir); } -} - -############################################################################# -# The program msidb.exe can be located next to the Perl program. Then it is -# not neccessary to find it in the PATH variable. -############################################################################# - -sub check_local_msidb -{ - my $msidbname = "msidb.exe"; - my $perlprogramm = $0; - my $path = $perlprogramm; - - get_path_from_fullqualifiedname(\$path); - - $path =~ s/\\\s*$//; - $path =~ s/\/\s*$//; - - my $msidbpath = ""; - if ( $path =~ /^\s*$/ ) { $msidbpath = $msidbname; } - else { $msidbpath = $path . $separator . $msidbname; } - - if ( -f $msidbpath ) - { - $localmsidbpath = $msidbpath; - print "Using $msidbpath (next to \"admin.pl\")\n"; - } -} - -############################################################################# -# Converting a string list with separator $listseparator -# into an array -############################################################################# - -sub convert_stringlist_into_array -{ - my ( $includestringref, $listseparator ) = @_; - - my @newarray = (); - my $first; - my $last = ${$includestringref}; - - while ( $last =~ /^\s*(.+?)\Q$listseparator\E(.+)\s*$/) # "$" for minimal matching - { - $first = $1; - $last = $2; - # Problem with two directly following listseparators. For example a path with two ";;" directly behind each other - $first =~ s/^$listseparator//; - push(@newarray, "$first\n"); - } - - push(@newarray, "$last\n"); - - return \@newarray; -} - -######################################################### -# Checking the local system -# Checking existence of needed files in include path -######################################################### - -sub check_system_path -{ - my $onefile; - my $error = 0; - my $pathvariable = $ENV{'PATH'}; - my $local_pathseparator = $pathseparator; - - if( $^O =~ /cygwin/i ) - { # When using cygwin's perl the PATH variable is POSIX style and ... - $pathvariable = qx{cygpath -mp "$pathvariable"} ; - # has to be converted to DOS style for further use. - $local_pathseparator = ';'; - } - my $patharrayref = convert_stringlist_into_array(\$pathvariable, $local_pathseparator); - - my @needed_files_in_path = ("expand.exe"); - if ( $localmsidbpath eq "" ) { push(@needed_files_in_path, "msidb.exe"); } # not found locally -> search in path - my @optional_files_in_path = ("msiinfo.exe"); - - print("\nChecking required files:\n"); - - foreach $onefile ( @needed_files_in_path ) - { - print("...... searching $onefile ..."); - - my $fileref = get_sourcepath_from_filename_and_includepath(\$onefile, $patharrayref); - - if ( $$fileref eq "" ) - { - $error = 1; - print( "$onefile not found\n" ); - } - else - { - print( "\tFound: $$fileref\n" ); - } - } - - if ( $error ) { exit_program("ERROR: Could not find all needed files in path (using setsolar should help)!"); } - - print("\nChecking optional files:\n"); - - foreach $onefile ( @optional_files_in_path ) - { - print("...... searching $onefile ..."); - - my $fileref = get_sourcepath_from_filename_and_includepath(\$onefile, $patharrayref); - - if ( $$fileref eq "" ) - { - print( "$onefile not found\n" ); - if ( $onefile eq "msiinfo.exe" ) { $msiinfo_available = 0; } - } - else - { - print( "\tFound: $$fileref\n" ); - if ( $onefile eq "msiinfo.exe" ) { $msiinfo_available = 1; } - } - } - -} - -########################################################################## -# Searching a file in a list of pathes -########################################################################## - -sub get_sourcepath_from_filename_and_includepath -{ - my ($searchfilenameref, $includepatharrayref) = @_; - - my $onefile = ""; - my $foundsourcefile = 0; - - for ( my $j = 0; $j <= $#{$includepatharrayref}; $j++ ) - { - my $includepath = ${$includepatharrayref}[$j]; - $includepath =~ s/^\s*//; - $includepath =~ s/\s*$//; - - $onefile = $includepath . $separator . $$searchfilenameref; - - if ( -f $onefile ) - { - $foundsourcefile = 1; - last; - } - } - - if (!($foundsourcefile)) { $onefile = ""; } - - return \$onefile; -} - -############################################################## -# Removing all empty directories below a specified directory -############################################################## - -sub remove_empty_dirs_in_folder -{ - my ( $dir, $firstrun ) = @_; - - if ( $firstrun ) - { - print "Removing superfluous directories\n"; - } - - my @content = (); - - $dir =~ s/\Q$separator\E\s*$//; - - if ( -d $dir ) - { - opendir(DIR, $dir); - @content = readdir(DIR); - closedir(DIR); - - my $oneitem; - - foreach $oneitem (@content) - { - if ((!($oneitem eq ".")) && (!($oneitem eq ".."))) - { - my $item = $dir . $separator . $oneitem; - - if ( -d $item ) # recursive - { - remove_empty_dirs_in_folder($item, 0); - } - } - } - - # try to remove empty directory - my $returnvalue = rmdir $dir; - - # if ( $returnvalue ) { print "Successfully removed empty dir $dir\n"; } - } -} - -#################################################### -# Detecting the directory with extensions -#################################################### - -sub get_extensions_dir -{ - my ( $unopkgfile ) = @_; - - my $localbranddir = $unopkgfile; - get_path_from_fullqualifiedname(\$localbranddir); # "program" dir in brand layer - get_path_from_fullqualifiedname(\$localbranddir); # root dir in brand layer - $localbranddir =~ s/\Q$separator\E\s*$//; - my $extensiondir = $localbranddir . $separator . "share" . $separator . "extensions"; - my $preregdir = $localbranddir . $separator . "share" . $separator . "prereg" . $separator . "bundled"; - - return ($extensiondir, $preregdir); -} - -######################################################## -# Finding all files with a specified file extension -# in a specified directory. -######################################################## - -sub find_file_with_file_extension -{ - my ($extension, $dir) = @_; - - my @allfiles = (); - my @sourcefiles = (); - - $dir =~ s/\Q$separator\E\s*$//; - - opendir(DIR, $dir); - @sourcefiles = readdir(DIR); - closedir(DIR); - - my $onefile; - - foreach $onefile (@sourcefiles) - { - if ((!($onefile eq ".")) && (!($onefile eq ".."))) - { - if ( $onefile =~ /^\s*(\S.*?)\.$extension\s*$/ ) - { - push(@allfiles, $onefile) - } - } - } - - return \@allfiles; -} - -############################################################## -# Creating a directory with all parent directories -############################################################## - -sub create_directories -{ - my ($directory) = @_; - - if ( ! try_to_create_directory($directory) ) - { - my $parentdir = $directory; - get_path_from_fullqualifiedname(\$parentdir); - create_directories($parentdir); # recursive - } - - create_directory($directory); # now it has to succeed -} - -############################################################## -# Creating one directory -############################################################## - -sub create_directory -{ - my ($directory) = @_; - - if ( ! -d $directory ) { mkdir($directory, 0775); } -} - -############################################################## -# Trying to create a directory, no error if this fails -############################################################## - -sub try_to_create_directory -{ - my ($directory) = @_; - - my $returnvalue = 1; - my $created_directory = 0; - - if (!(-d $directory)) - { - $returnvalue = mkdir($directory, 0775); - - if ($returnvalue) - { - $created_directory = 1; - - my $localcall = "chmod 775 $directory \>\/dev\/null 2\>\&1"; - system($localcall); - } - else - { - $created_directory = 0; - } - } - else - { - $created_directory = 1; - } - - return $created_directory; -} - -########################################### -# Getting path from full file name -########################################### - -sub get_path_from_fullqualifiedname -{ - my ($longfilenameref) = @_; - - if ( $$longfilenameref =~ /\Q$separator\E/ ) # Is there a separator in the path? Otherwise the path is empty. - { - if ( $$longfilenameref =~ /^\s*(\S.*\Q$separator\E)(\S.+\S?)/ ) - { - $$longfilenameref = $1; - } - } - else - { - $$longfilenameref = ""; # there is no path - } -} - -############################################################## -# Getting file name from full file name -############################################################## - -sub make_absolute_filename_to_relative_filename -{ - my ($longfilenameref) = @_; - - # Either '/' or '\'. - if ( $$longfilenameref =~ /^.*[\/\\](\S.+\S?)/ ) - { - $$longfilenameref = $1; - } -} - -############################################ -# Exiting the program with an error -# This function is used instead of "die" -############################################ - -sub exit_program -{ - my ($message) = @_; - - print "\n***************************************************************\n"; - print "$message\n"; - print "***************************************************************\n"; - remove_complete_directory($savetemppath, 1); - print "\n" . get_time_string(); - exit(-1); -} - -################################################################################# -# Unpacking cabinet files with expand -################################################################################# - -sub unpack_cabinet_file -{ - my ($cabfilename, $unpackdir) = @_; - - my $expandfile = "expand.exe"; # has to be in the PATH - - # expand.exe has to be located in the system directory. - # Cygwin has another tool expand.exe, that converts tabs to spaces. This cannot be used of course. - # But this wrong expand.exe is typically in the PATH before this expand.exe, to unpack - # cabinet files. - - if ( $^O =~ /cygwin/i ) - { - $expandfile = $ENV{'SYSTEMROOT'} . "/system32/expand.exe"; # Has to be located in the systemdirectory - $expandfile =~ s/\\/\//; - if ( ! -f $expandfile ) { exit_program("ERROR: Did not find file $expandfile in the Windows system folder!"); } - } - - my $expandlogfile = $unpackdir . $separator . "expand.log"; - - # exclude cabinet file - # my $systemcall = $cabarc . " -o X " . $mergemodulehash->{'cabinetfile'}; - - my $systemcall = ""; - if ( $^O =~ /cygwin/i ) { - my $localunpackdir = qx{cygpath -w "$unpackdir"}; - $localunpackdir =~ s/\\/\\\\/g; - - my $localcabfilename = qx{cygpath -w "$cabfilename"}; - $localcabfilename =~ s/\\/\\\\/g; - $localcabfilename =~ s/\s*$//g; - - $systemcall = $expandfile . " " . $localcabfilename . " -F:\* " . $localunpackdir . " \>\/dev\/null 2\>\&1"; - } - else - { - $systemcall = $expandfile . " " . $cabfilename . " -F:\* " . $unpackdir . " \> " . $expandlogfile; - } - - my $returnvalue = system($systemcall); - - if ($returnvalue) { exit_program("ERROR: Could not execute $systemcall !"); } -} - -################################################################################# -# Extracting tables from msi database -################################################################################# - -sub extract_tables_from_database -{ - my ($fullmsidatabasepath, $workdir, $tablelist) = @_; - - my $msidb = "msidb.exe"; # Has to be in the path - if ( $localmsidbpath ) { $msidb = $localmsidbpath; } - my $infoline = ""; - my $systemcall = ""; - my $returnvalue = ""; - - if ( $^O =~ /cygwin/i ) { - chomp( $fullmsidatabasepath = qx{cygpath -w "$fullmsidatabasepath"} ); - # msidb.exe really wants backslashes. (And double escaping because system() expands the string.) - $fullmsidatabasepath =~ s/\\/\\\\/g; - $workdir =~ s/\\/\\\\/g; - # and if there are still slashes, they also need to be double backslash - $fullmsidatabasepath =~ s/\//\\\\/g; - $workdir =~ s/\//\\\\/g; - } - - # Export of all tables by using "*" - - $systemcall = $msidb . " -d " . $fullmsidatabasepath . " -f " . $workdir . " -e $tablelist"; - print "\nAnalyzing msi database\n"; - $returnvalue = system($systemcall); - - if ($returnvalue) - { - $infoline = "ERROR: Could not execute $systemcall !\n"; - exit_program($infoline); - } -} - -######################################################## -# Check, if this installation set contains -# internal cabinet files included into the msi -# database. -######################################################## - -sub check_for_internal_cabfiles -{ - my ($cabfilehash) = @_; - - my $contains_internal_cabfiles = 0; - my %allcabfileshash = (); - - foreach my $filename ( keys %{$cabfilehash} ) - { - if ( $filename =~ /^\s*\#/ ) # starting with a hash - { - $contains_internal_cabfiles = 1; - # setting real filename without hash as key and name with hash as value - my $realfilename = $filename; - $realfilename =~ s/^\s*\#//; - $allcabfileshash{$realfilename} = $filename; - } - } - - return ( $contains_internal_cabfiles, \%allcabfileshash ); -} - -################################################################# -# Exclude all cab files from the msi database. -################################################################# - -sub extract_cabs_from_database -{ - my ($msidatabase, $allcabfiles) = @_; - - my $infoline = ""; - my $fullsuccess = 1; - my $msidb = "msidb.exe"; # Has to be in the path - if ( $localmsidbpath ) { $msidb = $localmsidbpath; } - - my @all_excluded_cabfiles = (); - - if( $^O =~ /cygwin/i ) - { - $msidatabase = qx{cygpath -w "$msidatabase"}; - $msidatabase =~ s/\\/\\\\/g; - $msidatabase =~ s/\s*$//g; - } - else - { - # msidb.exe really wants backslashes. (And double escaping because system() expands the string.) - $msidatabase =~ s/\//\\\\/g; - } - - foreach my $onefile ( keys %{$allcabfiles} ) - { - my $systemcall = $msidb . " -d " . $msidatabase . " -x " . $onefile; - system($systemcall); - push(@all_excluded_cabfiles, $onefile); - } - - \@all_excluded_cabfiles; -} - -################################################################################ -# Collect all DiskIds to the corresponding cabinet files from Media.idt. -################################################################################ - -sub analyze_media_file -{ - my ($filecontent) = @_; - - my %diskidhash = (); - - for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) - { - if ( $i < 3 ) { next; } - - if ( ${$filecontent}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) - { - my $diskid = $1; - my $cabfile = $4; - - $diskidhash{$cabfile} = $diskid; - } - } - - return \%diskidhash; -} - -sub analyze_customaction_file -{ - my ($filecontent) = @_; - - my $register_extensions_exists = 0; - - my %table = (); - - for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) - { - if ( ${$filecontent}[$i] =~ /^\s*RegisterExtensions\s+/ ) - { - $register_extensions_exists = 1; - last; - } - } - - return $register_extensions_exists; -} - -################################################################################ -# Analyzing the content of Directory.idt -################################################################################# - -sub analyze_directory_file -{ - my ($filecontent) = @_; - - my %table = (); - - for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) - { - if (( $i == 0 ) || ( $i == 1 ) || ( $i == 2 )) { next; } - - if ( ${$filecontent}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\s*$/ ) - { - my $dir = $1; - my $parent = $2; - my $name = $3; - - if ( $name =~ /^\s*(.*?)\s*\:\s*(.*?)\s*$/ ) { $name = $2; } - if ( $name =~ /^\s*(.*?)\s*\|\s*(.*?)\s*$/ ) { $name = $2; } - - my %helphash = (); - $helphash{'Directory_Parent'} = $parent; - $helphash{'DefaultDir'} = $name; - $table{$dir} = \%helphash; - } - } - - return \%table; -} - -################################################################################# -# Analyzing the content of Component.idt -################################################################################# - -sub analyze_component_file -{ - my ($filecontent) = @_; - - my %table = (); - - for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) - { - if (( $i == 0 ) || ( $i == 1 ) || ( $i == 2 )) { next; } - - if ( ${$filecontent}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) - { - my $component = $1; - my $dir = $3; - - $table{$component} = $dir; - } - } - - return \%table; -} - -################################################################################# -# Analyzing the content of File.idt -################################################################################# - -sub analyze_file_file -{ - my ($filecontent) = @_; - - my %table = (); - my %fileorder = (); - my $maxsequence = 0; - - for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) - { - if (( $i == 0 ) || ( $i == 1 ) || ( $i == 2 )) { next; } - - if ( ${$filecontent}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) - { - my $file = $1; - my $comp = $2; - my $filename = $3; - my $sequence = $8; - - if ( $filename =~ /^\s*(.*?)\s*\|\s*(.*?)\s*$/ ) { $filename = $2; } - - my %helphash = (); - $helphash{'Component'} = $comp; - $helphash{'FileName'} = $filename; - $helphash{'Sequence'} = $sequence; - - $table{$file} = \%helphash; - - $fileorder{$sequence} = $file; - - if ( $sequence > $maxsequence ) { $maxsequence = $sequence; } - } - } - - return (\%table, \%fileorder, $maxsequence); -} - -#################################################################################### -# Recursively creating the directory tree -#################################################################################### - -sub create_directory_tree -{ - my ($parent, $pathcollector, $fulldir, $dirhash) = @_; - - foreach my $dir ( keys %{$dirhash} ) - { - if (( $dirhash->{$dir}->{'Directory_Parent'} eq $parent ) && ( $dirhash->{$dir}->{'DefaultDir'} ne "." )) - { - my $dirname = $dirhash->{$dir}->{'DefaultDir'}; - # Create the directory - my $newdir = $fulldir . $separator . $dirname; - if ( ! -f $newdir ) { mkdir $newdir; } - # Saving in collector - $pathcollector->{$dir} = $newdir; - # Iteration - create_directory_tree($dir, $pathcollector, $newdir, $dirhash); - } - } -} - -#################################################################################### -# Creating the directory tree -#################################################################################### - -sub create_directory_structure -{ - my ($dirhash, $targetdir) = @_; - - print "Creating directories\n"; - - my %fullpathhash = (); - - my @startparents = ("TARGETDIR", "INSTALLLOCATION"); - - foreach $dir (@startparents) { create_directory_tree($dir, \%fullpathhash, $targetdir, $dirhash); } - - # Also adding the pathes of the startparents - foreach $dir (@startparents) - { - if ( ! exists($fullpathhash{$dir}) ) { $fullpathhash{$dir} = $targetdir; } - } - - return \%fullpathhash; -} - -#################################################################################### -# Cygwin: Setting privileges for files -#################################################################################### - -sub change_privileges -{ - my ($destfile, $privileges) = @_; - - my $localcall = "chmod $privileges " . "\"" . $destfile . "\""; - system($localcall); -} - -#################################################################################### -# Cygwin: Setting privileges for files recursively -#################################################################################### - -sub change_privileges_full -{ - my ($target) = @_; - - print "Changing privileges\n"; - - my $localcall = "chmod -R 755 " . "\"" . $target . "\""; - system($localcall); -} - -###################################################### -# Creating a new directory with defined privileges -###################################################### - -sub create_directory_with_privileges -{ - my ($directory, $privileges) = @_; - - my $returnvalue = 1; - my $infoline = ""; - - if (!(-d $directory)) - { - my $localprivileges = oct("0".$privileges); # changes "777" to 0777 - $returnvalue = mkdir($directory, $localprivileges); - - if ($returnvalue) - { - my $localcall = "chmod $privileges $directory \>\/dev\/null 2\>\&1"; - system($localcall); - } - } - else - { - my $localcall = "chmod $privileges $directory \>\/dev\/null 2\>\&1"; - system($localcall); - } -} - -###################################################### -# Creating a unique directory with pid extension -###################################################### - -sub create_pid_directory -{ - my ($directory) = @_; - - $directory =~ s/\Q$separator\E\s*$//; - my $pid = $$; # process id - my $time = time(); # time - - $directory = $directory . "_" . $pid . $time; - - if ( ! -d $directory ) { create_directory($directory); } - else { exit_program("ERROR: Directory $directory already exists!"); } - - return $directory; -} - -#################################################################################### -# Copying files into installation set -#################################################################################### - -sub copy_files_into_directory_structure -{ - my ($fileorder, $filehash, $componenthash, $fullpathhash, $maxsequence, $unpackdir, $installdir, $dirhash) = @_; - - print "Copying files\n"; - - my $unopkgfile = ""; - - for ( my $i = 1; $i <= $maxsequence; $i++ ) - { - if ( exists($fileorder->{$i}) ) - { - my $file = $fileorder->{$i}; - if ( ! exists($filehash->{$file}->{'Component'}) ) { exit_program("ERROR: Did not find component for file: \"$file\"."); } - my $component = $filehash->{$file}->{'Component'}; - if ( ! exists($componenthash->{$component}) ) { exit_program("ERROR: Did not find directory for component: \"$component\"."); } - my $dirname = $componenthash->{$component}; - if ( ! exists($fullpathhash->{$dirname}) ) { exit_program("ERROR: Did not find full directory path for dir: \"$dirname\"."); } - my $destdir = $fullpathhash->{$dirname}; - if ( ! exists($filehash->{$file}->{'FileName'}) ) { exit_program("ERROR: Did not find \"FileName\" for file: \"$file\"."); } - my $destfile = $filehash->{$file}->{'FileName'}; - - $destfile = $destdir . $separator . $destfile; - my $sourcefile = $unpackdir . $separator . $file; - - if ( ! -f $sourcefile ) - { - # It is possible, that this was an unpacked file - # Looking in the dirhash, to find the subdirectory in the installation set (the id is $dirname) - # subdir is not recursively analyzed, only one directory. - - my $oldsourcefile = $sourcefile; - my $subdir = ""; - if ( exists($dirhash->{$dirname}->{'DefaultDir'}) ) { $subdir = $dirhash->{$dirname}->{'DefaultDir'} . $separator; } - my $realfilename = $filehash->{$file}->{'FileName'}; - my $localinstalldir = $installdir; - - $localinstalldir =~ s/\\\s*$//; - $localinstalldir =~ s/\/\s*$//; - - $sourcefile = $localinstalldir . $separator . $subdir . $realfilename; - - if ( ! -f $sourcefile ) { exit_program("ERROR: File not found: \"$oldsourcefile\" (or \"$sourcefile\")."); } - } - - my $copyreturn = copy($sourcefile, $destfile); - - if ( ! $copyreturn) { exit_program("ERROR: Could not copy $source to $dest\n"); } - - # Searching unopkg.exe - if ( $destfile =~ /unopkg\.exe\s*$/ ) { $unopkgfile = $destfile; } - # if (( $^O =~ /cygwin/i ) && ( $destfile =~ /\.exe\s*$/ )) { change_privileges($destfile, "775"); } - } - # else # allowing missing sequence numbers ? - # { - # exit_program("ERROR: No file assigned to sequence $i"); - # } - } - - return ($unopkgfile); -} - -###################################################### -# Removing a complete directory with subdirectories -###################################################### - -sub remove_complete_directory -{ - my ($directory, $start) = @_; - - my @content = (); - my $infoline = ""; - - $directory =~ s/\Q$separator\E\s*$//; - - if ( -d $directory ) - { - if ( $start ) { print "Removing directory $directory\n"; } - - opendir(DIR, $directory); - @content = readdir(DIR); - closedir(DIR); - - my $oneitem; - - foreach $oneitem (@content) - { - if ((!($oneitem eq ".")) && (!($oneitem eq ".."))) - { - my $item = $directory . $separator . $oneitem; - - if ( -f $item || -l $item ) # deleting files or links - { - unlink($item); - } - - if ( -d $item ) # recursive - { - remove_complete_directory($item, 0); - } - } - } - - # try to remove empty directory - my $returnvalue = rmdir $directory; - if ( ! $returnvalue ) { print "Warning: Problem with removing empty dir $directory\n"; } - } -} - -#################################################################################### -# Defining a temporary path -#################################################################################### - -sub get_temppath -{ - my $temppath = ""; - - if (( $ENV{'TMP'} ) || ( $ENV{'TEMP'} )) - { - if ( $ENV{'TMP'} ) { $temppath = $ENV{'TMP'}; } - elsif ( $ENV{'TEMP'} ) { $temppath = $ENV{'TEMP'}; } - - $temppath =~ s/\Q$separator\E\s*$//; # removing ending slashes and backslashes - $temppath = $temppath . $separator . $globaltempdirname; - create_directory_with_privileges($temppath, "777"); - - my $dirsave = $temppath; - - $temppath = $temppath . $separator . "a"; - $temppath = create_pid_directory($temppath); - - if ( ! -d $temppath ) { exit_program("ERROR: Failed to create directory $temppath ! Possible reason: Wrong privileges in directory $dirsave."); } - - if ( $^O =~ /cygwin/i ) - { - $temppath =~ s/\\/\\\\/g; - chomp( $temppath = qx{cygpath -w "$temppath"} ); - } - - $savetemppath = $temppath; - } - else - { - exit_program("ERROR: Could not set temporary directory (TMP and TEMP not set!)."); - } - - return $temppath; -} - -#################################################################################### -# Registering extensions -#################################################################################### - -sub register_extensions_sync -{ - my ($unopkgfile, $localtemppath, $preregdir) = @_; - - if ( $preregdir eq "" ) - { - my $logtext = "ERROR: Failed to determine \"prereg\" folder for extension registration! Please check your installation set."; - print $logtext . "\n"; - exit_program($logtext); - } - - my $from = cwd(); - - my $path = $unopkgfile; - get_path_from_fullqualifiedname(\$path); - $path =~ s/\\\s*$//; - $path =~ s/\/\s*$//; - - my $executable = $unopkgfile; - make_absolute_filename_to_relative_filename(\$executable); - - chdir($path); - - if ( ! $path_displayed ) - { - print "... current dir: $path ...\n"; - $path_displayed = 1; - } - - $localtemppath =~ s/\\/\//g; - - if ( $^O =~ /cygwin/i ) { - $executable = "./" . $executable; - $preregdir = qx{cygpath -m "$preregdir"}; - chomp($preregdir); - } - - $preregdir =~ s/\/\s*$//g; - - my $systemcall = $executable . " sync --verbose 2\>\&1 |"; - - print "... $systemcall\n"; - - my @unopkgoutput = (); - - open (UNOPKG, $systemcall); - while (<UNOPKG>) {push(@unopkgoutput, $_); } - close (UNOPKG); - - my $returnvalue = $?; # $? contains the return value of the systemcall - - if ($returnvalue) - { - print "ERROR: Could not execute \"$systemcall\"!\nExitcode: '$returnvalue'\n"; - for ( my $j = 0; $j <= $#unopkgoutput; $j++ ) { print "$unopkgoutput[$j]"; } - exit_program("ERROR: $systemcall failed!"); - } - - chdir($from); -} - -#################################################################################### -# Registering all extensions located in /share/extension/install -#################################################################################### - -sub register_extensions -{ - my ($unopkgfile, $temppath, $preregdir) = @_; - - print "Registering extensions:\n"; - - if (( ! -f $unopkgfile ) || ( $unopkgfile eq "" )) - { - print("WARNING: Could not find unopkg.exe (Language Pack?)!\n"); - } - else - { - register_extensions_sync($unopkgfile, $temppath, $preregdir); - remove_complete_directory($temppath, 1); - } - -} - -#################################################################################### -# Reading one file -#################################################################################### - -sub read_file -{ - my ($localfile) = @_; - - my @localfile = (); - - open( IN, "<$localfile" ) || exit_program("ERROR: Cannot open file $localfile for reading"); - - # Don't use "my @localfile = <IN>" here, because - # perl has a problem with the internal "large_and_huge_malloc" function - # when calling perl using MacOS 10.5 with a perl built with MacOS 10.4 - while ( $line = <IN> ) { - push @localfile, $line; - } - - close( IN ); - - return \@localfile; -} - -############################################################### -# Setting the time string for the -# Summary Information stream in the -# msi database of the admin installations. -############################################################### - -sub get_sis_time_string -{ - # Syntax: <yyyy/mm/dd hh:mm:ss> - my $second = (localtime())[0]; - my $minute = (localtime())[1]; - my $hour = (localtime())[2]; - my $day = (localtime())[3]; - my $month = (localtime())[4]; - my $year = 1900 + (localtime())[5]; - $month++; - - if ( $second < 10 ) { $second = "0" . $second; } - if ( $minute < 10 ) { $minute = "0" . $minute; } - if ( $hour < 10 ) { $hour = "0" . $hour; } - if ( $day < 10 ) { $day = "0" . $day; } - if ( $month < 10 ) { $month = "0" . $month; } - - my $timestring = $year . "/" . $month . "/" . $day . " " . $hour . ":" . $minute . ":" . $second; - - return $timestring; -} - -############################################################### -# Writing content of administrative installations into -# Summary Information Stream of msi database. -# This is required for example for following -# patch processes using Windows Installer service. -############################################################### - -sub write_sis_info -{ - my ($msidatabase) = @_; - - print "Setting SIS in msi database\n"; - - if ( ! -f $msidatabase ) { exit_program("ERROR: Cannot find file $msidatabase"); } - - my $msiinfo = "msiinfo.exe"; # Has to be in the path - my $infoline = ""; - my $systemcall = ""; - my $returnvalue = ""; - - # Required setting for administrative installations: - # -w 4 (source files are unpacked), wordcount - # -s <date of admin installation>, LastPrinted, Syntax: <yyyy/mm/dd hh:mm:ss> - # -l <person_making_admin_installation>, LastSavedBy - - my $wordcount = 4; # Unpacked files - my $lastprinted = get_sis_time_string(); - my $lastsavedby = "Installer"; - - my $localmsidatabase = $msidatabase; - - if( $^O =~ /cygwin/i ) - { - $localmsidatabase = qx{cygpath -w "$localmsidatabase"}; - $localmsidatabase =~ s/\\/\\\\/g; - $localmsidatabase =~ s/\s*$//g; - } - - $systemcall = $msiinfo . " " . "\"" . $localmsidatabase . "\"" . " -w " . $wordcount . " -s " . "\"" . $lastprinted . "\"" . " -l $lastsavedby"; - - $returnvalue = system($systemcall); - - if ($returnvalue) - { - $infoline = "ERROR: Could not execute $systemcall !\n"; - exit_program($infoline); - } -} - -############################################################### -# Convert time string -############################################################### - -sub convert_timestring -{ - my ($secondstring) = @_; - - my $timestring = ""; - - if ( $secondstring < 60 ) # less than a minute - { - if ( $secondstring < 10 ) { $secondstring = "0" . $secondstring; } - $timestring = "00\:$secondstring min\."; - } - elsif ( $secondstring < 3600 ) - { - my $minutes = $secondstring / 60; - my $seconds = $secondstring % 60; - if ( $minutes =~ /(\d*)\.\d*/ ) { $minutes = $1; } - if ( $minutes < 10 ) { $minutes = "0" . $minutes; } - if ( $seconds < 10 ) { $seconds = "0" . $seconds; } - $timestring = "$minutes\:$seconds min\."; - } - else # more than one hour - { - my $hours = $secondstring / 3600; - my $secondstring = $secondstring % 3600; - my $minutes = $secondstring / 60; - my $seconds = $secondstring % 60; - if ( $hours =~ /(\d*)\.\d*/ ) { $hours = $1; } - if ( $minutes =~ /(\d*)\.\d*/ ) { $minutes = $1; } - if ( $hours < 10 ) { $hours = "0" . $hours; } - if ( $minutes < 10 ) { $minutes = "0" . $minutes; } - if ( $seconds < 10 ) { $seconds = "0" . $seconds; } - $timestring = "$hours\:$minutes\:$seconds hours"; - } - - return $timestring; -} - -############################################################### -# Returning time string for logging -############################################################### - -sub get_time_string -{ - my $currenttime = time(); - $currenttime = $currenttime - $starttime; - $currenttime = convert_timestring($currenttime); - $currenttime = localtime() . " \(" . $currenttime . "\)\n"; - return $currenttime; -} - -#################################################################################### -# Simulating an administrative installation -#################################################################################### - -$starttime = time(); - -getparameter(); -controlparameter(); -check_local_msidb(); -check_system_path(); -my $temppath = get_temppath(); - -print("\nmsi database: $databasepath\n"); -print("Destination directory: $targetdir\n" ); - -my $helperdir = $temppath . $separator . "installhelper"; -create_directory($helperdir); - -# Get File.idt, Component.idt and Directory.idt from database - -my $tablelist = "File Directory Component Media CustomAction"; -extract_tables_from_database($databasepath, $helperdir, $tablelist); - -# Set unpackdir -my $unpackdir = $helperdir . $separator . "unpack"; -create_directory($unpackdir); - -# Reading media table to check for internal cabinet files -my $filename = $helperdir . $separator . "Media.idt"; -if ( ! -f $filename ) { exit_program("ERROR: Could not find required file: $filename !"); } -my $filecontent = read_file($filename); -my $cabfilehash = analyze_media_file($filecontent); - -# Check, if there are internal cab files -my ( $contains_internal_cabfiles, $all_internal_cab_files) = check_for_internal_cabfiles($cabfilehash); - -if ( $contains_internal_cabfiles ) -{ - # Set unpackdir - my $cabdir = $helperdir . $separator . "internal_cabs"; - create_directory($cabdir); - my $from = cwd(); - chdir($cabdir); - # Exclude all cabinet files from database - my $all_excluded_cabs = extract_cabs_from_database($databasepath, $all_internal_cab_files); - print "Unpacking files from internal cabinet file(s)\n"; - foreach my $cabfile ( @{$all_excluded_cabs} ) { unpack_cabinet_file($cabfile, $unpackdir); } - chdir($from); -} - -# Unpack all cab files into $helperdir, cab files must be located next to msi database -my $installdir = $databasepath; - -get_path_from_fullqualifiedname(\$installdir); - -my $databasefilename = $databasepath; -make_absolute_filename_to_relative_filename(\$databasefilename); - -my $cabfiles = find_file_with_file_extension("cab", $installdir); - -if (( $#{$cabfiles} < 0 ) && ( ! $contains_internal_cabfiles )) { exit_program("ERROR: Did not find any cab file in directory $installdir"); } - -print "Unpacking files from cabinet file(s)\n"; -for ( my $i = 0; $i <= $#{$cabfiles}; $i++ ) -{ - my $cabfile = $installdir . $separator . ${$cabfiles}[$i]; - unpack_cabinet_file($cabfile, $unpackdir); -} - -# Reading tables -$filename = $helperdir . $separator . "Directory.idt"; -$filecontent = read_file($filename); -my $dirhash = analyze_directory_file($filecontent); - -$filename = $helperdir . $separator . "Component.idt"; -$filecontent = read_file($filename); -my $componenthash = analyze_component_file($filecontent); - -$filename = $helperdir . $separator . "File.idt"; -$filecontent = read_file($filename); -my ( $filehash, $fileorder, $maxsequence ) = analyze_file_file($filecontent); - -# Creating the directory structure -my $fullpathhash = create_directory_structure($dirhash, $targetdir); - -# Copying files -my ($unopkgfile) = copy_files_into_directory_structure($fileorder, $filehash, $componenthash, $fullpathhash, $maxsequence, $unpackdir, $installdir, $dirhash); -if ( $^O =~ /cygwin/i ) { change_privileges_full($targetdir); } - -my $msidatabase = $targetdir . $separator . $databasefilename; -my $copyreturn = copy($databasepath, $msidatabase); -if ( ! $copyreturn) { exit_program("ERROR: Could not copy $source to $dest\n"); } - -# Reading tables -$filename = $helperdir . $separator . "CustomAction.idt"; -$filecontent = read_file($filename); -my $register_extensions_exists = analyze_customaction_file($filecontent); - -# Removing empty dirs in extension folder -my ( $extensionfolder, $preregdir ) = get_extensions_dir($unopkgfile); -if ( -d $extensionfolder ) { remove_empty_dirs_in_folder($extensionfolder, 1); } - -if ( $register_extensions_exists ) -{ - # Registering extensions - register_extensions($unopkgfile, $temppath, $preregdir); -} - -# Saving info in Summary Information Stream of msi database (required for following patches) -if ( $msiinfo_available ) { write_sis_info($msidatabase); } - -# Removing the helper directory -remove_complete_directory($temppath, 1); - -print "\nSuccessful installation: " . get_time_string(); |