diff options
Diffstat (limited to 'setup_native/scripts/admin.pl')
-rw-r--r-- | setup_native/scripts/admin.pl | 203 |
1 files changed, 190 insertions, 13 deletions
diff --git a/setup_native/scripts/admin.pl b/setup_native/scripts/admin.pl index 81d5649ffec6..ebb16d0ef008 100644 --- a/setup_native/scripts/admin.pl +++ b/setup_native/scripts/admin.pl @@ -46,6 +46,7 @@ BEGIN $savetemppath = ""; $msiinfo_available = 0; $path_displayed = 0; + $localmsidbpath = ""; $plat = $^O; @@ -69,7 +70,7 @@ sub usage { print <<Ende; ---------------------------------------------------------------------- -$prog V1.0 (c) Sun Microsystems 2008 +$prog V1.0 (c) Sun Microsystems 2009 This program installs a Windows Installer installation set without using msiexec.exe. The installation is comparable with an administrative installation using the Windows Installer @@ -150,6 +151,33 @@ sub controlparameter } ############################################################################# +# 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 ############################################################################# @@ -198,7 +226,8 @@ sub check_system_path } my $patharrayref = convert_stringlist_into_array(\$pathvariable, $local_pathseparator); - my @needed_files_in_path = ("msidb.exe", "expand.exe"); + 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"); @@ -386,7 +415,7 @@ sub get_path_from_fullqualifiedname if ( $$longfilenameref =~ /\Q$separator\E/ ) # Is there a separator in the path? Otherwise the path is empty. { - if ( $$longfilenameref =~ /^\s*(\S.*\S\Q$separator\E)(\S.+\S?)/ ) + if ( $$longfilenameref =~ /^\s*(\S.*\Q$separator\E)(\S.+\S?)/ ) { $$longfilenameref = $1; } @@ -486,6 +515,7 @@ 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 = ""; @@ -513,6 +543,117 @@ sub extract_tables_from_database } } +######################################################## +# 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 ################################################################################# @@ -930,6 +1071,10 @@ sub register_one_extension $localextension =~ s/\\/\\\\/g; } + if ( $^O =~ /cygwin/i ) { + $executable = "./" . $executable; + } + my $systemcall = $executable . " add --shared --verbose " . "\"" . $localextension . "\"" . " -env:UserInstallation=file://" . $temppath . " 2\>\&1 |"; print "... $systemcall\n"; @@ -1142,6 +1287,7 @@ $starttime = time(); getparameter(); controlparameter(); +check_local_msidb(); check_system_path(); my $temppath = get_temppath(); @@ -1153,9 +1299,36 @@ create_directory($helperdir); # Get File.idt, Component.idt and Directory.idt from database -my $tablelist = "File Directory Component"; +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; @@ -1166,11 +1339,7 @@ make_absolute_filename_to_relative_filename(\$databasefilename); my $cabfiles = find_file_with_file_extension("cab", $installdir); -if ( $#{$cabfiles} < 0 ) { exit_program("ERROR: Did not find any cab file in directory $installdir"); } - -# Set unpackdir -my $unpackdir = $helperdir . $separator . "unpack"; -create_directory($unpackdir); +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++ ) @@ -1180,8 +1349,8 @@ for ( my $i = 0; $i <= $#{$cabfiles}; $i++ ) } # Reading tables -my $filename = $helperdir . $separator . "Directory.idt"; -my $filecontent = read_file($filename); +$filename = $helperdir . $separator . "Directory.idt"; +$filecontent = read_file($filename); my $dirhash = analyze_directory_file($filecontent); $filename = $helperdir . $separator . "Component.idt"; @@ -1203,8 +1372,16 @@ my $msidatabase = $targetdir . $separator . $databasefilename; my $copyreturn = copy($databasepath, $msidatabase); if ( ! $copyreturn) { exit_program("ERROR: Could not copy $source to $dest\n"); } -# Registering extensions -register_extensions($unopkgfile, $extensions, $temppath); +# Reading tables +$filename = $helperdir . $separator . "CustomAction.idt"; +$filecontent = read_file($filename); +my $register_extensions_exists = analyze_customaction_file($filecontent); + +if ( $register_extensions_exists ) +{ + # Registering extensions + register_extensions($unopkgfile, $extensions, $temppath); +} # Saving info in Summary Information Stream of msi database (required for following patches) if ( $msiinfo_available ) { write_sis_info($msidatabase); } |