xref: /AOO41X/main/solenv/bin/modules/installer/worker.pm (revision 43c75f1d068f8e69f57d055e6d8a8fc2b9ad3743)
1#**************************************************************
2#
3#  Licensed to the Apache Software Foundation (ASF) under one
4#  or more contributor license agreements.  See the NOTICE file
5#  distributed with this work for additional information
6#  regarding copyright ownership.  The ASF licenses this file
7#  to you under the Apache License, Version 2.0 (the
8#  "License"); you may not use this file except in compliance
9#  with the License.  You may obtain a copy of the License at
10#
11#    http://www.apache.org/licenses/LICENSE-2.0
12#
13#  Unless required by applicable law or agreed to in writing,
14#  software distributed under the License is distributed on an
15#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16#  KIND, either express or implied.  See the License for the
17#  specific language governing permissions and limitations
18#  under the License.
19#
20#**************************************************************
21
22
23
24package installer::worker;
25
26use Cwd;
27use File::Copy;
28use File::stat;
29use File::Temp qw(tmpnam);
30use installer::control;
31use installer::converter;
32use installer::existence;
33use installer::exiter;
34use installer::files;
35use installer::globals;
36use installer::logger;
37use installer::mail;
38use installer::pathanalyzer;
39use installer::scpzipfiles;
40use installer::scriptitems;
41use installer::sorter;
42use installer::systemactions;
43use installer::windows::language;
44
45#####################################################################
46# Unpacking all files ending with tar.gz in a specified directory
47#####################################################################
48
49sub unpack_all_targzfiles_in_directory
50{
51    my ( $directory ) = @_;
52
53    installer::logger::include_header_into_logfile("Unpacking tar.gz files:");
54
55    $installer::logger::Info->print( "... unpacking tar.gz files ... \n" );
56
57    my $localdirectory = $directory . $installer::globals::separator . "packages";
58    my $alltargzfiles = installer::systemactions::find_file_with_file_extension("tar.gz", $localdirectory);
59
60    for ( my $i = 0; $i <= $#{$alltargzfiles}; $i++ )
61    {
62        my $onefile = $localdirectory . $installer::globals::separator . ${$alltargzfiles}[$i];
63
64        my $systemcall = "cd $localdirectory; cat ${$alltargzfiles}[$i] \| gunzip \| tar -xf -";
65        $returnvalue = system($systemcall);
66
67        my $infoline = "Systemcall: $systemcall\n";
68        $installer::logger::Lang->print($infoline);
69
70        if ($returnvalue)
71        {
72            $infoline = "ERROR: Could not execute \"$systemcall\"!\n";
73            $installer::logger::Lang->print($infoline);
74        }
75        else
76        {
77            $infoline = "Success: Executed \"$systemcall\" successfully!\n";
78            $installer::logger::Lang->print($infoline);
79        }
80    }
81}
82
83#########################################
84# Copying installation sets to ship
85#########################################
86
87sub copy_install_sets_to_ship
88{
89    my ( $destdir, $shipinstalldir  ) = @_;
90
91    installer::logger::include_header_into_logfile("Copying installation set to ship:");
92
93    my $dirname = $destdir;
94    installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$dirname);
95    $dirname = $dirname . "_inprogress";
96    my $localshipinstalldir = $shipinstalldir . $installer::globals::separator . $dirname;
97    if ( ! -d $localshipinstalldir ) { installer::systemactions::create_directory_structure($localshipinstalldir); }
98
99    # copy installation set to /ship ($localshipinstalldir)
100    $installer::logger::Info->print( "... copy installation set from " . $destdir . " to " . $localshipinstalldir . "\n" );
101    installer::systemactions::copy_complete_directory($destdir, $localshipinstalldir);
102
103    if (( ! $installer::globals::iswindowsbuild ) && ( $installer::globals::addjavainstaller ))
104    {
105        # Setting Unix rights for Java starter ("setup")
106        my $localcall = "chmod 775 $localshipinstalldir/setup \>\/dev\/null 2\>\&1";
107        system($localcall);
108    }
109
110    # unpacking the tar.gz file for Solaris
111    if ( $installer::globals::issolarisbuild ) { unpack_all_targzfiles_in_directory($localshipinstalldir); }
112
113    $localshipinstalldir = installer::systemactions::rename_string_in_directory($localshipinstalldir, "_inprogress", "");
114
115    return $localshipinstalldir;
116}
117
118#########################################
119# Copying installation sets to ship
120#########################################
121
122sub link_install_sets_to_ship
123{
124    my ( $destdir, $shipinstalldir  ) = @_;
125
126    installer::logger::include_header_into_logfile("Linking installation set to ship:");
127
128    my $infoline = "... destination directory: $shipinstalldir ...\n";
129    $installer::logger::Info->print( $infoline );
130    $installer::logger::Lang->print($infoline);
131
132    if ( ! -d $shipinstalldir)
133    {
134        $infoline = "Creating directory: $shipinstalldir\n";
135        $installer::logger::Lang->print($infoline);
136        installer::systemactions::create_directory_structure($shipinstalldir);
137        $infoline = "Created directory: $shipinstalldir\n";
138        $installer::logger::Lang->print($infoline);
139    }
140
141    my $dirname = $destdir;
142    installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$dirname);
143
144    my $localshipinstalldir = $shipinstalldir . $installer::globals::separator . $dirname;
145
146    # link installation set to /ship ($localshipinstalldir)
147    $installer::logger::Lang->print( "... linking installation set from " . $destdir . " to " . $localshipinstalldir . "\n" );
148
149    my $systemcall = "ln -s $destdir $localshipinstalldir";
150
151    $returnvalue = system($systemcall);
152
153    $infoline = "Systemcall: $systemcall\n";
154    $installer::logger::Lang->print($infoline);
155
156    if ($returnvalue)
157    {
158        $infoline = "ERROR: Could not create link \"$localshipinstalldir\"!\n";
159        $installer::logger::Lang->print($infoline);
160    }
161    else
162    {
163        $infoline = "Success: Created link \"$localshipinstalldir\"!\n";
164        $installer::logger::Lang->print($infoline);
165    }
166
167    return $localshipinstalldir;
168}
169
170#########################################
171# Create checksum file
172#########################################
173
174sub make_checksum_file
175{
176    my ( $filesref, $includepatharrayref ) = @_;
177
178    my @checksum = ();
179
180    my $checksumfileref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$installer::globals::checksumfile, $includepatharrayref, 1);
181    if ( $$checksumfileref eq "" ) { installer::exiter::exit_program("ERROR: Could not find file $installer::globals::checksumfile !", "make_checksum_file"); }
182
183#   # very slow on Windows
184#   for ( my $i = 0; $i <= $#{$filesref}; $i++ )
185#   {
186#       my $onefile = ${$filesref}[$i];
187#       my $systemcall = "$$checksumfileref $onefile->{'sourcepath'} |";
188#       open (CHECK, "$systemcall");
189#       my $localchecksum = <CHECK>;
190#       close (CHECK);
191#       push(@checksum, $localchecksum);
192#   }
193
194    my $systemcall = "$$checksumfileref";
195
196    for ( my $i = 0; $i <= $#{$filesref}; $i++ )
197    {
198        my $onefile = ${$filesref}[$i];
199        $systemcall = $systemcall . " " . $onefile->{'sourcepath'};     # very very long systemcall
200
201        if ((( $i > 0 ) &&  ( $i%100 == 0 )) || ( $i == $#{$filesref} ))    # limiting to 100 files
202        {
203            $systemcall = $systemcall . " \|";
204
205            my @localchecksum = ();
206            open (CHECK, "$systemcall");
207            @localchecksum = <CHECK>;
208            close (CHECK);
209
210            for ( my $j = 0; $j <= $#localchecksum; $j++ ) { push(@checksum, $localchecksum[$j]); }
211
212            $systemcall = "$$checksumfileref";  # reset the system call
213        }
214    }
215
216    return \@checksum;
217}
218
219#########################################
220# Saving the checksum file
221#########################################
222
223sub save_checksum_file
224{
225    my ($current_install_number, $installchecksumdir, $checksumfile) = @_;
226
227    my $numberedchecksumfilename = $installer::globals::checksumfilename;
228    $numberedchecksumfilename =~ s/\./_$current_install_number\./;  # checksum.txt -> checksum_01.txt
229    installer::files::save_file($installchecksumdir . $installer::globals::separator . $numberedchecksumfilename, $checksumfile);
230}
231
232#################################################
233# Writing some global information into
234# the list of files without flag PATCH
235#################################################
236
237sub write_nopatchlist_header
238{
239    my ( $content ) = @_;
240
241    my @header = ();
242    my $infoline = "This is a list of files, that are defined in scp-projects without\n";
243    push(@header, $infoline);
244    $infoline = "flag \"PATCH\". Important: This does not mean in any case, that \n";
245    push(@header, $infoline);
246    $infoline = "this files are included into or excluded from a patch. \n\n";
247    push(@header, $infoline);
248    $infoline = "Exception Linux: A patch rpm is a complete rpm. This means that all \n";
249    push(@header, $infoline);
250    $infoline = "files are included into a patch rpm, if only one file of the rpm has the \n";
251    push(@header, $infoline);
252    $infoline = "style \"PATCH\". \n\n";
253    push(@header, $infoline);
254
255    for ( my $i = 0; $i <= $#header; $i++ ) { push(@{$content},$header[$i]); }
256}
257
258#################################################
259# Creating the content of the list of files
260# without flag PATCH.
261# All files are saved in
262# @{$installer::globals::nopatchfilecollector}
263#################################################
264
265sub create_nopatchlist
266{
267    my @content =();
268
269    write_nopatchlist_header(\@content);
270
271    for ( my $i = 0; $i <= $#{$installer::globals::nopatchfilecollector}; $i++ )
272    {
273        my $onefile = ${$installer::globals::nopatchfilecollector}[$i];
274        my $oneline = $onefile->{'destination'};
275        if ( $onefile->{'zipfilename'} ) { $oneline = $oneline . " (" . $onefile->{'zipfilename'} . ")"; }
276        $oneline = $oneline . "\n";
277        push(@content, $oneline);
278    }
279
280    return \@content;
281}
282
283#########################################
284# Saving the patchlist file
285#########################################
286
287sub save_patchlist_file
288{
289    my ($installlogdir, $patchlistfilename) = @_;
290
291    my $installpatchlistdir = installer::systemactions::create_directory_next_to_directory($installlogdir, "patchlist");
292    $patchlistfilename =~ s/log\_/patchfiles\_/;
293    $patchlistfilename =~ s/\.log/\.txt/;
294    installer::files::save_file($installpatchlistdir . $installer::globals::separator . $patchlistfilename, \@installer::globals::patchfilecollector);
295    $installer::logger::Info->print( "... creating patchlist file $patchlistfilename \n" );
296
297    if (( $installer::globals::patch ) && ( ! $installer::globals::creating_windows_installer_patch ))  # only for non-Windows patches
298    {
299        $patchlistfilename =~ s/patchfiles\_/nopatchfiles\_/;
300        my $nopatchlist = create_nopatchlist();
301        installer::files::save_file($installpatchlistdir . $installer::globals::separator . $patchlistfilename, $nopatchlist);
302        $installer::logger::Info->print( "... creating patch exclusion file $patchlistfilename \n" );
303    }
304
305}
306
307###############################################################
308# Removing all directories of a special language
309# in the directory $basedir
310###############################################################
311
312sub remove_old_installation_sets
313{
314    my ($basedir) = @_;
315
316    $installer::logger::Info->print( "... removing old installation directories ...\n" );
317
318    my $removedir = $basedir;
319
320    if ( -d $removedir ) { installer::systemactions::remove_complete_directory($removedir, 1); }
321
322    # looking for non successful old installation sets
323
324    $removedir = $basedir . "_witherror";
325    if ( -d $removedir ) { installer::systemactions::remove_complete_directory($removedir, 1); }
326
327    $removedir = $basedir . "_inprogress";
328    if ( -d $removedir ) { installer::systemactions::remove_complete_directory($removedir, 1); }
329
330    # finally the $basedir can be created empty
331
332    if ( $installer::globals::localinstalldirset ) { installer::systemactions::create_directory_structure($basedir); }
333
334    installer::systemactions::create_directory($basedir);
335}
336
337###############################################################
338# Removing all non successful installation sets on ship
339###############################################################
340
341sub remove_old_ship_installation_sets
342{
343    my ($fulldir, $counter) = @_;
344
345    $installer::logger::Info->print( "... removing old installation directories ...\n" );
346
347    my $basedir = $fulldir;
348    installer::pathanalyzer::get_path_from_fullqualifiedname(\$basedir);
349
350    # collecting all directories next to the new installation directory
351    my $alldirs = installer::systemactions::get_all_directories($basedir);
352
353    if ( $fulldir =~ /^\s*(.*?inprogress\-)(\d+)(.*?)\s*$/ )
354    {
355        my $pre_inprogress = $1;        # $pre still contains "inprogress"
356        my $number = $2;
357        my $post = $3;
358        my $pre_witherror = $pre_inprogress;
359        $pre_witherror =~ s/inprogress/witherror/;
360
361        for ( my $i = 0; $i <= $#{$alldirs}; $i++ )
362        {
363            if ( ${$alldirs}[$i] eq $fulldir ) { next; }    # do not delete the newly created directory
364
365            if ( ${$alldirs}[$i] =~ /^\s*\Q$pre_inprogress\E\d+\Q$post\E\s*$/ ) # removing old "inprogress" directories
366            {
367                installer::systemactions::remove_complete_directory(${$alldirs}[$i], 1);
368            }
369
370            if ( ${$alldirs}[$i] =~ /^\s*\Q$pre_witherror\E\d+\Q$post\E\s*$/ )  # removing old "witherror" directories
371            {
372                installer::systemactions::remove_complete_directory(${$alldirs}[$i], 1);
373            }
374        }
375    }
376}
377
378###############################################################
379# Creating the installation directory structure
380###############################################################
381
382sub create_installation_directory
383{
384    my ($shipinstalldir, $languagestringref, $current_install_number_ref) = @_;
385
386    my $installdir = "";
387
388    my $languageref = $languagestringref;
389
390    if ( $installer::globals::updatepack )
391    {
392        $installdir = $shipinstalldir;
393        installer::systemactions::create_directory_structure($installdir);
394        $$current_install_number_ref = installer::systemactions::determine_maximum_number($installdir, $languageref);
395        $installdir = installer::systemactions::rename_string_in_directory($installdir, "number", $$current_install_number_ref);
396        remove_old_ship_installation_sets($installdir);
397    }
398    else
399    {
400        $installdir = installer::systemactions::create_directories("install", $languageref);
401        $installer::logger::Info->print( "... creating installation set in $installdir ...\n" );
402        remove_old_installation_sets($installdir);
403        my $inprogressinstalldir = $installdir . "_inprogress";
404        installer::systemactions::rename_directory($installdir, $inprogressinstalldir);
405        $installdir = $inprogressinstalldir;
406    }
407
408    $installer::globals::saveinstalldir = $installdir;  # saving directory globally, in case of exiting
409
410    return $installdir;
411}
412
413###############################################################
414# Analyzing and creating the log file
415###############################################################
416
417sub analyze_and_save_logfile
418{
419    my ($loggingdir, $installdir, $installlogdir, $allsettingsarrayref, $languagestringref, $current_install_number) = @_;
420
421    my $is_success = 1;
422    my $finalinstalldir = "";
423
424    $installer::logger::Info->print( "... checking log file " . $loggingdir . $installer::globals::logfilename . "\n" );
425
426    my $contains_error = installer::control::check_logfile();
427
428    # Dependent from the success, the installation directory can be renamed and mails can be send.
429
430    if ($contains_error)
431    {
432        my $errordir = installer::systemactions::rename_string_in_directory($installdir, "_inprogress", "_witherror");
433        if ($installer::globals::updatepack)
434        {
435            installer::mail::send_fail_mail($allsettingsarrayref, $languagestringref, $errordir);
436        }
437        # Error output to STDERR
438        for ( my $j = 0; $j <= $#installer::globals::errorlogfileinfo; $j++ )
439        {
440            my $line = $installer::globals::errorlogfileinfo[$j];
441            $line =~ s/\s*$//g;
442            installer::logger::print_error( $line );
443        }
444        $is_success = 0;
445
446        $finalinstalldir = $errordir;
447    }
448    else
449    {
450        my $destdir = "";
451
452        if ( $installer::globals::updatepack )
453        {
454            if ( $installdir =~ /_download_inprogress/ ) { $destdir = installer::systemactions::rename_string_in_directory($installdir, "_download_inprogress", "_download"); }
455            elsif ( $installdir =~ /_jds_inprogress/ ) { $destdir = installer::systemactions::rename_string_in_directory($installdir, "_jds_inprogress", "_jds"); }
456            elsif ( $installdir =~ /_msp_inprogress/ ) { $destdir = installer::systemactions::rename_string_in_directory($installdir, "_msp_inprogress", "_msp"); }
457            else
458            {
459                if ( $installdir =~ /_packed/ ) { $destdir = installer::systemactions::rename_string_in_directory($installdir, "_inprogress", ""); }
460                else { $destdir = installer::systemactions::rename_string_in_directory($installdir, "_inprogress", "_packed"); }
461            }
462            installer::mail::send_success_mail($allsettingsarrayref, $languagestringref, $destdir);
463        }
464        else
465        {
466            $destdir = installer::systemactions::rename_string_in_directory($installdir, "_inprogress", "");
467        }
468
469        $finalinstalldir = $destdir;
470    }
471
472    # Saving the logfile in the log file directory and additionally in a log directory in the install directory
473
474    my $numberedlogfilename = $installer::globals::logfilename;
475    if ( $installer::globals::updatepack )
476    {
477        $numberedlogfilename =~ s /log_/log_$current_install_number\_/;
478    }
479    foreach my $log_file_name (
480        $loggingdir . $numberedlogfilename,
481        $installlogdir . $installer::globals::separator . $numberedlogfilename)
482    {
483        if ($log_file_name ne $installer::logger::Lang->{'filename'})
484        {
485            $installer::logger::Info->printf("    copying log file to %s\n", $log_file_name);
486            installer::systemactions::copy_one_file($installer::logger::Lang->{'filename'}, $log_file_name);
487        }
488    }
489
490    # Saving the list of patchfiles in a patchlist directory in the install directory
491    if (( $installer::globals::patch ) || ( $installer::globals::creating_windows_installer_patch )) { installer::worker::save_patchlist_file($installlogdir, $numberedlogfilename); }
492
493    if ( $installer::globals::creating_windows_installer_patch ) { $installer::globals::creating_windows_installer_patch = 0; }
494
495    # Exiting the packaging process, if an error occured.
496    # This is important, to get an error code "-1", if an error was found in the log file,
497    # that did not break the packaging process
498
499    if ( ! $is_success) { installer::exiter::exit_program("ERROR: Found an error in the logfile. Packaging failed.", "analyze_and_save_logfile"); }
500
501    return ($is_success, $finalinstalldir);
502}
503
504###############################################################
505# Analyzing and creating the log file
506###############################################################
507
508sub save_logfile_after_linking
509{
510    my ($loggingdir, $installlogdir, $current_install_number) = @_;
511
512    # Saving the logfile in the log file directory and additionally in a log directory in the install directory
513    my $numberedlogfilename = $installer::globals::logfilename;
514    if ( $installer::globals::updatepack ) { $numberedlogfilename =~ s /log_/log_$current_install_number\_/; }
515    $installer::logger::Info->print( "... creating log file $numberedlogfilename \n" );
516    installer::files::save_file($loggingdir . $numberedlogfilename, \@installer::globals::logfileinfo);
517    installer::files::save_file($installlogdir . $installer::globals::separator . $numberedlogfilename, \@installer::globals::logfileinfo);
518}
519
520###############################################################
521# Removing all directories that are saved in the
522# global directory @installer::globals::removedirs
523###############################################################
524
525sub clean_output_tree
526{
527    $installer::logger::Info->print( "... cleaning the output tree ...\n" );
528
529    for ( my $i = 0; $i <= $#installer::globals::removedirs; $i++ )
530    {
531        if ( -d $installer::globals::removedirs[$i] )
532        {
533            $installer::logger::Info->print( "... removing directory $installer::globals::removedirs[$i] ...\n" );
534            installer::systemactions::remove_complete_directory($installer::globals::removedirs[$i], 1);
535        }
536    }
537
538    # Last try to remove the ship test directory
539
540    if ( $installer::globals::shiptestdirectory )
541    {
542        if ( -d $installer::globals::shiptestdirectory )
543        {
544            my $infoline = "Last try to remove $installer::globals::shiptestdirectory . \n";
545            $installer::logger::Lang->print($infoline);
546            my $systemcall = "rmdir $installer::globals::shiptestdirectory";
547            my $returnvalue = system($systemcall);
548        }
549    }
550}
551
552###############################################################
553# Removing all directories that are saved in the
554# global directory @installer::globals::jdsremovedirs
555###############################################################
556
557sub clean_jds_temp_dirs
558{
559    $installer::logger::Info->print( "... cleaning jds directories ...\n" );
560
561    for ( my $i = 0; $i <= $#installer::globals::jdsremovedirs; $i++ )
562    {
563        if ( -d $installer::globals::jdsremovedirs[$i] )
564        {
565            $installer::logger::Info->print( "... removing directory $installer::globals::jdsremovedirs[$i] ...\n" );
566            installer::systemactions::remove_complete_directory($installer::globals::jdsremovedirs[$i], 1);
567        }
568    }
569}
570
571###########################################################
572# Copying a reference array
573###########################################################
574
575sub copy_array_from_references
576{
577    my ( $arrayref ) = @_;
578
579    my @newarray = ();
580
581    for ( my $i = 0; $i <= $#{$arrayref}; $i++ )
582    {
583        push(@newarray, ${$arrayref}[$i]);
584    }
585
586    return \@newarray;
587}
588
589###########################################################
590# Copying a reference hash
591###########################################################
592
593sub copy_hash_from_references
594{
595    my ($hashref) = @_;
596
597    my %newhash = ();
598    my $key;
599
600    foreach $key (keys %{$hashref})
601    {
602        $newhash{$key} = $hashref->{$key};
603    }
604
605    return \%newhash;
606}
607
608###########################################################
609# Setting one language in the language independent
610# array of include pathes with $(LANG)
611###########################################################
612
613sub get_language_specific_include_pathes
614{
615    my ( $patharrayref, $onelanguage ) = @_;
616
617    my @patharray = ();
618
619    for ( my $i = 0; $i <= $#{$patharrayref}; $i++ )
620    {
621        my $line = ${$patharrayref}[$i];
622        $line =~ s/\$\(LANG\)/$onelanguage/g;
623        push(@patharray ,$line);
624    }
625
626    return \@patharray;
627}
628
629##############################################################
630# Returning the first item with a defined flag
631##############################################################
632
633sub return_first_item_with_special_flag
634{
635    my ($itemsref, $flag) = @_;
636
637    my $firstitem = "";
638
639    for ( my $i = 0; $i <= $#{$itemsref}; $i++ )
640    {
641        my $oneitem = ${$itemsref}[$i];
642        my $styles = "";
643        if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'} };
644
645        if ( $styles =~ /\b$flag\b/ )
646        {
647            $firstitem = $oneitem;
648            last;
649        }
650    }
651
652    return $firstitem;
653}
654
655##############################################################
656# Collecting all items with a defined flag
657##############################################################
658
659sub collect_all_items_with_special_flag
660{
661    my ($itemsref, $flag) = @_;
662
663    my @allitems = ();
664
665    for ( my $i = 0; $i <= $#{$itemsref}; $i++ )
666    {
667        my $oneitem = ${$itemsref}[$i];
668        my $styles = "";
669        if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'} };
670
671        if ( $styles =~ /\b$flag\b/ )
672        {
673            push( @allitems, $oneitem );
674        }
675    }
676
677    return \@allitems;
678}
679
680##############################################################
681# Collecting all files without patch flag in
682# $installer::globals::nopatchfilecollector
683##############################################################
684
685sub collect_all_files_without_patch_flag
686{
687    my ($filesref) = @_;
688
689    my $newfiles = collect_all_items_without_special_flag($filesref, "PATCH");
690
691    for ( my $i = 0; $i <= $#{$newfiles}; $i++ ) { push(@{$installer::globals::nopatchfilecollector}, ${$newfiles}[$i]); }
692}
693
694##############################################################
695# Collecting all items without a defined flag
696##############################################################
697
698sub collect_all_items_without_special_flag
699{
700    my ($itemsref, $flag) = @_;
701
702    my @allitems = ();
703
704    for ( my $i = 0; $i <= $#{$itemsref}; $i++ )
705    {
706        my $oneitem = ${$itemsref}[$i];
707        my $styles = "";
708        if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'} };
709
710        if ( !( $styles =~ /\b$flag\b/ ))
711        {
712            push( @allitems, $oneitem );
713        }
714    }
715
716    return \@allitems;
717}
718
719##############################################################
720# Removing all items with a defined flag from collector
721##############################################################
722
723sub remove_all_items_with_special_flag
724{
725    my ($itemsref, $flag) = @_;
726
727    my @allitems = ();
728
729    for ( my $i = 0; $i <= $#{$itemsref}; $i++ )
730    {
731        my $oneitem = ${$itemsref}[$i];
732        my $styles = "";
733        if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'} };
734        if ( $styles =~ /\b$flag\b/ )
735        {
736            $installer::logger::Lang->printf(
737                "Attention: Removing from collector '%s' because it has flag %s\n",
738                $oneitem->{'Name'},
739                $flag);
740            if ( $flag eq "BINARYTABLE_ONLY" ) { push(@installer::globals::binarytableonlyfiles, $oneitem); }
741            next;
742        }
743        push( @allitems, $oneitem );
744    }
745
746    return \@allitems;
747}
748
749###########################################################
750# Mechanism for simple installation without packing
751###########################################################
752
753sub install_simple ($$$$$$)
754{
755    my ($packagename, $languagestring, $directoriesarray, $filesarray, $linksarray, $unixlinksarray) = @_;
756
757        # locate GNU cp on the system
758        my $gnucp = 'cp';
759        if ( $ENV{'GNUCOPY'} ) { $gnucp = $ENV{'GNUCOPY'}; }
760    my $copyopts = '-af';
761    $copyopts = '-PpRf' unless ( $ENV{'GNUCOPY'} ); # if not gnucopy, assume POSIX copy
762
763    $installer::logger::Info->print( "... installing module $packagename ...\n" );
764
765    my $destdir = $installer::globals::destdir;
766    my @lines = ();
767
768    $installer::logger::Info->print( "DestDir: $destdir \n" );
769    $installer::logger::Info->print( "Rootpath: $installer::globals::rootpath \n" );
770
771    `mkdir -p $destdir` if $destdir ne "";
772    `mkdir -p $destdir$installer::globals::rootpath`;
773
774    # Create Directories
775    for ( my $i = 0; $i <= $#{$directoriesarray}; $i++ )
776    {
777        my $onedir = ${$directoriesarray}[$i];
778        my $dir = "";
779
780        if ( $onedir->{'Dir'} ) { $dir = $onedir->{'Dir'}; }
781
782        if ((!($dir =~ /\bPREDEFINED_/ )) || ( $dir =~ /\bPREDEFINED_PROGDIR\b/ ))
783        {
784            # printf "mkdir $destdir$onedir->{'HostName'}\n";
785            mkdir $destdir . $onedir->{'HostName'};
786            push @lines, "%dir " . $onedir->{'HostName'} . "\n";
787        }
788    }
789
790    for ( my $i = 0; $i <= $#{$filesarray}; $i++ )
791    {
792        my $onefile = ${$filesarray}[$i];
793        my $unixrights = $onefile->{'UnixRights'};
794        my $destination = $onefile->{'destination'};
795        my $sourcepath = $onefile->{'sourcepath'};
796
797        # This is necessary to install SDK that includes files with $ in its name
798        # Otherwise, the following shell commands does not work and the file list
799        # is not correct
800        $destination =~ s/\$\$/\$/;
801        $sourcepath =~ s/\$\$/\$/;
802
803        push @lines, "$destination\n";
804        # printf "cp $sourcepath $destdir$destination\n";
805        copy ("$sourcepath", "$destdir$destination") || die "Can't copy file: $sourcepath -> $destdir$destination $!";
806        my $sourcestat = stat($sourcepath);
807        utime ($sourcestat->atime, $sourcestat->mtime, "$destdir$destination");
808        chmod (oct($unixrights), "$destdir$destination") || die "Can't change permissions: $!";
809        push @lines, "$destination\n";
810    }
811
812    for ( my $i = 0; $i <= $#{$linksarray}; $i++ )
813    {
814        my $onelink = ${$linksarray}[$i];
815        my $destination = $onelink->{'destination'};
816        my $destinationfile = $onelink->{'destinationfile'};
817
818        # print "link $destinationfile -> $destdir$destination\n";
819        symlink ("$destinationfile", "$destdir$destination") || die "Can't create symlink: $!";
820        push @lines, "$destination\n";
821    }
822
823    for ( my $i = 0; $i <= $#{$unixlinksarray}; $i++ )
824    {
825        my $onelink = ${$unixlinksarray}[$i];
826        my $target = $onelink->{'Target'};
827        my $destination = $onelink->{'destination'};
828
829        # print "Unix link $target -> $destdir$destination\n";
830        `ln -sf '$target' '$destdir$destination'`;
831        push @lines, "$destination\n";
832    }
833
834    if ( $destdir ne "" )
835    {
836        my $filelist;
837        my $fname = $installer::globals::destdir . "/$packagename";
838        if ($installer::globals::languagepack) { $fname .= ".$languagestring"; }
839        open ($filelist, ">$fname") || die "Can't open $fname: $!";
840        print $filelist @lines;
841        close ($filelist);
842    }
843
844}
845
846###########################################################
847# Adding shellnew files into files collector for
848# user installation
849###########################################################
850
851sub add_shellnewfile_into_filesarray
852{
853    my ($filesref, $onefile, $inffile) = @_;
854
855    my %shellnewfile = ();
856    my $shellnewfileref = \%shellnewfile;
857
858    installer::converter::copy_item_object($inffile, $shellnewfileref);
859
860    $shellnewfileref->{'Name'} = $onefile->{'Name'};
861    $shellnewfileref->{'sourcepath'} = $onefile->{'sourcepath'};
862    $shellnewfileref->{'gid'} = $onefile->{'gid'} . "_Userinstall";
863
864    # the destination has to be adapted
865    my $destination = $inffile->{'destination'};
866    installer::pathanalyzer::get_path_from_fullqualifiedname(\$destination);
867    $destination = $destination . $onefile->{'Name'};
868    $shellnewfileref->{'destination'} = $destination;
869
870    # add language specific inffile into filesarray
871    push(@{$filesref}, $shellnewfileref);
872}
873
874###########################################################
875# Replacing one placehoder in template file
876###########################################################
877
878sub replace_in_template_file
879{
880    my ($templatefile, $placeholder, $newstring) = @_;
881
882    for ( my $i = 0; $i <= $#{$templatefile}; $i++ )
883    {
884        ${$templatefile}[$i] =~ s/\Q$placeholder\E/$newstring/g;
885    }
886}
887
888###########################################################
889# Replacing one placehoder with an array in template file
890###########################################################
891
892sub replace_array_in_template_file
893{
894    my ($templatefile, $placeholder, $arrayref) = @_;
895
896    for ( my $i = 0; $i <= $#{$templatefile}; $i++ )
897    {
898        if ( ${$templatefile}[$i] =~ /\Q$placeholder\E/ )
899        {
900            my @return = splice(@{$templatefile}, $i, 1, @{$arrayref});
901        }
902    }
903}
904
905###########################################################
906# Collecting all modules from registry items
907###########################################################
908
909sub collect_all_modules
910{
911    my ($registryitemsref) = @_;
912
913    my @allmodules = ();
914
915    for ( my $i = 0; $i <= $#{$registryitemsref}; $i++ )
916    {
917        $registryitem = ${$registryitemsref}[$i];
918        my $module = $registryitem->{'ModuleID'};
919
920        if ( ! installer::existence::exists_in_array($module, \@allmodules) )
921        {
922            push(@allmodules, $module);
923        }
924    }
925
926    return \@allmodules;
927}
928
929###########################################################
930# Changing the content of the inf file
931###########################################################
932
933sub write_content_into_inf_file
934{
935    my ($templatefile, $filesref, $registryitemsref, $folderref, $folderitemsref, $modulesref, $onelanguage, $inffile, $firstlanguage, $allvariableshashref) = @_;
936
937    # First part: Shellnew files
938    # SHELLNEWFILESPLACEHOLDER
939
940    my $rootmodule = 0;
941    # inf files can be assigned to "gid_Module_Root_Files_2"
942    if ( $inffile->{'modules'} =~ /Module_Root/i ) { $rootmodule = 1; }
943
944    if ( $rootmodule )
945    {
946        my $shellnewstring = "";
947
948        for ( my $i = 0; $i <= $#{$filesref}; $i++ )
949        {
950            my $onefile = ${$filesref}[$i];
951            my $directory = $onefile->{'Dir'};
952
953            if ( $directory =~ /\bPREDEFINED_OSSHELLNEWDIR\b/ )
954            {
955                $shellnewstring = $shellnewstring . $onefile->{'Name'} . "\n";
956                if (( $firstlanguage ) && ( ! $installer::globals::shellnewfilesadded )) { add_shellnewfile_into_filesarray($filesref, $onefile, $inffile); }
957            }
958        }
959
960        $shellnewstring =~ s/\s*$//;
961        replace_in_template_file($templatefile, "SHELLNEWFILESPLACEHOLDER", $shellnewstring);
962
963        $installer::globals::shellnewfilesadded = 1;
964    }
965
966    # Second part: Start menu entries
967
968    # The OfficeMenuFolder is defined as: $productname . " " . $productversion;
969
970    my $productname = $allvariableshashref->{'PRODUCTNAME'};
971    my $productversion = $allvariableshashref->{'PRODUCTVERSION'};
972    my $productkey = $productname . " " . $productversion;
973
974    replace_in_template_file($templatefile, "OFFICEFOLDERPLACEHOLDER", $productkey);
975
976    # Setting name target and infotip for all applications
977
978    for ( my $i = 0; $i <= $#{$folderitemsref}; $i++ )
979    {
980        my $folderitem = ${$folderitemsref}[$i];
981
982        my $styles = "";
983        if ( $folderitem->{'Styles'} ) { $styles = $folderitem->{'Styles'}; }
984        if ( $styles =~ /\bNON_ADVERTISED\b/ ) { next; }    # no entry for non-advertised shortcuts
985
986        if (( ! $folderitem->{'ismultilingual'} ) || (( $folderitem->{'ismultilingual'} ) && ( $folderitem->{'specificlanguage'} eq $onelanguage )))
987        {
988            my $gid = $folderitem->{'gid'};
989            my $app = $gid;
990            $app =~ s/gid_Folderitem_//;
991            $app = uc($app);
992
993            my $name = $folderitem->{'Name'};
994            my $placeholder = "PLACEHOLDER_FOLDERITEM_NAME_" . $app;
995            replace_in_template_file($templatefile, $placeholder, $name);
996
997            my $tooltip = $folderitem->{'Tooltip'};
998            $placeholder = "PLACEHOLDER_FOLDERITEM_TOOLTIP_" . $app;
999            replace_in_template_file($templatefile, $placeholder, $tooltip);
1000
1001            my $executablegid = $folderitem->{'FileID'};
1002            my $exefile = installer::existence::get_specified_file($filesref, $executablegid);
1003            my $exefilename = $exefile->{'Name'};
1004            $placeholder = "PLACEHOLDER_FOLDERITEM_TARGET_" . $app;
1005            replace_in_template_file($templatefile, $placeholder, $exefilename);
1006        }
1007    }
1008
1009    # Third part: Windows registry entries
1010
1011    # collecting all modules
1012
1013    my $allmodules = collect_all_modules($registryitemsref);
1014
1015    my @registryitems = ();
1016    my $allsectionsstring = "";
1017
1018    for ( my $j = 0; $j <= $#{$allmodules}; $j++ )
1019    {
1020        my $moduleid = ${$allmodules}[$j];
1021
1022        my $inffilemodule = $inffile->{'modules'};
1023        # inf files can be assigned to "gid_Module_Root_Files_2", but RegistryItems to "gid_Module_Root"
1024        if ( $inffilemodule =~ /Module_Root/i ) { $inffilemodule = $installer::globals::rootmodulegid; }
1025
1026        if ( ! ( $moduleid eq $inffilemodule )) { next; }
1027
1028        my $shortmodulename = $moduleid;
1029        $shortmodulename =~ s/gid_Module_//;
1030        my $sectionname = "InstRegKeys." . $shortmodulename;
1031        $allsectionsstring = $allsectionsstring . $sectionname . ",";
1032        my $sectionheader = "\[" . $sectionname . "\]" . "\n";
1033        push(@registryitems, $sectionheader);
1034
1035        for ( my $i = 0; $i <= $#{$registryitemsref}; $i++ )
1036        {
1037            my $registryitem = ${$registryitemsref}[$i];
1038
1039            if ( ! ( $registryitem->{'ModuleID'} eq $moduleid )) { next; }
1040
1041            if (( ! $registryitem->{'ismultilingual'} ) || (( $registryitem->{'ismultilingual'} ) && ( $registryitem->{'specificlanguage'} eq $onelanguage )))
1042            {
1043                # Syntax: HKCR,".bau",,,"soffice.StarConfigFile.6"
1044
1045                my $regroot = "";
1046                my $parentid = "";
1047                if ( $registryitem->{'ParentID'} ) { $parentid = $registryitem->{'ParentID'}; }
1048                if ( $parentid eq "PREDEFINED_HKEY_CLASSES_ROOT" ) { $regroot = "HKCR"; }
1049                if ( $parentid eq "PREDEFINED_HKEY_LOCAL_MACHINE" ) { $regroot = "HKCU"; }
1050
1051                my $subkey = "";
1052                if ( $registryitem->{'Subkey'} ) { $subkey = $registryitem->{'Subkey'}; }
1053                if ( $subkey ne "" ) { $subkey = "\"" . $subkey . "\""; }
1054
1055                my $valueentryname = "";
1056                if ( $registryitem->{'Name'} ) { $valueentryname = $registryitem->{'Name'}; }
1057                if ( $valueentryname ne "" ) { $valueentryname = "\"" . $valueentryname . "\""; }
1058
1059                my $flag = "";
1060
1061                my $value = "";
1062                if ( $registryitem->{'Value'} ) { $value = $registryitem->{'Value'}; }
1063                if ( $value =~ /\<progpath\>/ ) { $value =~ s/\\\"/\"\"/g; } # Quoting for INF is done by double ""
1064                $value =~ s/\\\"/\"/g;  # no more masquerading of '"'
1065                $value =~ s/\<progpath\>/\%INSTALLLOCATION\%/g;
1066                if ( $value ne "" ) { $value = "\"" . $value . "\""; }
1067
1068                my $oneline = $regroot . "," . $subkey . "," . $valueentryname . "," . $flag . "," . $value . "\n";
1069
1070                push(@registryitems, $oneline);
1071            }
1072        }
1073
1074        push(@registryitems, "\n"); # empty line after each section
1075    }
1076
1077    # replacing the $allsectionsstring
1078    $allsectionsstring =~ s/\,\s*$//;
1079    replace_in_template_file($templatefile, "ALLREGISTRYSECTIONSPLACEHOLDER", $allsectionsstring);
1080
1081    # replacing the placeholder for all registry keys
1082    replace_array_in_template_file($templatefile, "REGISTRYKEYSPLACEHOLDER", \@registryitems);
1083
1084}
1085
1086###########################################################
1087# Creating inf files for local user system integration
1088###########################################################
1089
1090sub create_inf_file
1091{
1092    my ($filesref, $registryitemsref, $folderref, $folderitemsref, $modulesref, $languagesarrayref, $languagestringref, $allvariableshashref) = @_;
1093
1094    # collecting all files with flag INFFILE
1095
1096    my $inf_files = collect_all_items_with_special_flag($filesref ,"INFFILE");
1097
1098    if ( $#{$inf_files} > -1 )
1099    {
1100        # create new language specific inffile
1101        installer::logger::include_header_into_logfile("Creating inf files:");
1102
1103        my $infdirname = "inffiles";
1104        my $infdir = installer::systemactions::create_directories($infdirname, $languagestringref);
1105
1106        my $infoline = "Number of inf files: $#{$inf_files} + 1 \n";
1107        $installer::logger::Lang->print($infoline);
1108
1109        # there are inffiles for all modules
1110
1111        for ( my $i = 0; $i <= $#{$inf_files}; $i++ )
1112        {
1113            my $inffile = ${$inf_files}[$i];
1114            my $inf_file_name = $inffile->{'Name'};
1115
1116            my $templatefilename = $inffile->{'sourcepath'};
1117
1118            if ( ! -f $templatefilename ) { installer::exiter::exit_program("ERROR: Could not find file $templatefilename !", "create_inf_file");  }
1119
1120            # iterating over all languages
1121
1122            for ( my $j = 0; $j <= $#{$languagesarrayref}; $j++ )   # iterating over all languages
1123            {
1124                my $firstlanguage = 0;
1125                if ( $j == 0 ) { $firstlanguage = 1; }
1126
1127                my $onelanguage = ${$languagesarrayref}[$j];
1128
1129                $infoline = "Templatefile: $inf_file_name, Language: $onelanguage \n";
1130                $installer::logger::Lang->print($infoline);
1131
1132                my $templatefile = installer::files::read_file($templatefilename);
1133
1134                my $linesbefore = $#{$templatefile};
1135
1136                write_content_into_inf_file($templatefile, $filesref, $registryitemsref, $folderref, $folderitemsref, $modulesref, $onelanguage, $inffile, $firstlanguage, $allvariableshashref);
1137
1138                $infoline = "Lines change: From $linesbefore to $#{$templatefile}.\n";
1139                $installer::logger::Lang->print($infoline);
1140
1141                # rename language specific inffile
1142                my $language_inf_file_name = $inf_file_name;
1143                my $windowslanguage = installer::windows::language::get_windows_language($onelanguage);
1144                $language_inf_file_name =~ s/\.inf/_$windowslanguage\.inf/;
1145
1146                my $sourcepath = $infdir . $installer::globals::separator . $language_inf_file_name;
1147                installer::files::save_file($sourcepath, $templatefile);
1148
1149                $infoline = "Saving file: $sourcepath\n";
1150                $installer::logger::Lang->print($infoline);
1151
1152                # creating new file object
1153
1154                my %languageinffile = ();
1155                my $languageinifileref = \%languageinffile;
1156
1157                if ( $j < $#{$languagesarrayref} ) { installer::converter::copy_item_object($inffile, $languageinifileref); }
1158                else { $languageinifileref = $inffile; }
1159
1160                $languageinifileref->{'Name'} = $language_inf_file_name;
1161                $languageinifileref->{'sourcepath'} = $sourcepath;
1162                # destination and gid also have to be adapted
1163                $languageinifileref->{'gid'} = $languageinifileref->{'gid'} . "_" . $onelanguage;
1164                my $destination = $languageinifileref->{'destination'};
1165                installer::pathanalyzer::get_path_from_fullqualifiedname(\$destination);
1166                $destination = $destination . $language_inf_file_name;
1167                $languageinifileref->{'destination'} = $destination;
1168
1169                # add language specific inffile into filesarray
1170                if ( $j < $#{$languagesarrayref} ) { push(@{$filesref}, $languageinifileref); }
1171            }
1172        }
1173    }
1174}
1175
1176###########################################################
1177# Selecting patch items
1178###########################################################
1179
1180sub select_patch_items
1181{
1182    my ( $itemsref, $itemname ) = @_;
1183
1184    installer::logger::include_header_into_logfile("Selecting items for patches. Item: $itemname");
1185
1186    my @itemsarray = ();
1187
1188    for ( my $i = 0; $i <= $#{$itemsref}; $i++ )
1189    {
1190        my $oneitem = ${$itemsref}[$i];
1191
1192        my $name = $oneitem->{'Name'};
1193        if (( $name =~ /\bLICENSE/ ) || ( $name =~ /\bREADME/ ))
1194        {
1195            push(@itemsarray, $oneitem);
1196            next;
1197        }
1198
1199        # Items with style "PATCH" have to be included into the patch
1200        my $styles = "";
1201        if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'}; }
1202        if ( $styles =~ /\bPATCH\b/ ) { push(@itemsarray, $oneitem); }
1203    }
1204
1205    return \@itemsarray;
1206}
1207
1208###########################################################
1209# Selecting patch items
1210###########################################################
1211
1212sub select_patch_items_without_name
1213{
1214    my ( $itemsref, $itemname ) = @_;
1215
1216    installer::logger::include_header_into_logfile("Selecting RegistryItems for patches");
1217
1218    my @itemsarray = ();
1219
1220    for ( my $i = 0; $i <= $#{$itemsref}; $i++ )
1221    {
1222        my $oneitem = ${$itemsref}[$i];
1223
1224        # Items with style "PATCH" have to be included into the patch
1225        my $styles = "";
1226        if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'}; }
1227        if ( $styles =~ /\bPATCH\b/ ) { push(@itemsarray, $oneitem); }
1228    }
1229
1230    return \@itemsarray;
1231}
1232
1233###########################################################
1234# Selecting patch items
1235###########################################################
1236
1237sub select_langpack_items
1238{
1239    my ( $itemsref, $itemname ) = @_;
1240
1241    installer::logger::include_header_into_logfile("Selecting RegistryItems for Language Packs");
1242
1243    my @itemsarray = ();
1244
1245    for ( my $i = 0; $i <= $#{$itemsref}; $i++ )
1246    {
1247        my $oneitem = ${$itemsref}[$i];
1248
1249        # Items with style "LANGUAGEPACK" have to be included into the patch
1250        my $styles = "";
1251        if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'}; }
1252        if (( $styles =~ /\bLANGUAGEPACK\b/ ) || ( $styles =~ /\bFORCELANGUAGEPACK\b/ )) { push(@itemsarray, $oneitem); }
1253    }
1254
1255    return \@itemsarray;
1256}
1257
1258###########################################################
1259# Searching if LICENSE and README, which are not removed
1260# in select_patch_items are really needed for the patch.
1261# If not, they are removed now.
1262###########################################################
1263
1264sub analyze_patch_files
1265{
1266    my ( $filesref ) = @_;
1267
1268    installer::logger::include_header_into_logfile("Analyzing patch files");
1269
1270    my @filesarray = ();
1271
1272    for ( my $i = 0; $i <= $#{$filesref}; $i++ )
1273    {
1274        my $onefile = ${$filesref}[$i];
1275        my $styles = "";
1276        if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; }
1277        if ( !( $styles =~ /\bPATCH\b/) ) { next; } # removing all files without flag PATCH (LICENSE, README, ...)
1278
1279        if ( $installer::globals::iswindowsbuild )
1280        {
1281            # all files of the Windows patch belong to the root module
1282            $onefile->{'modules'} = $installer::globals::rootmodulegid;
1283        }
1284
1285        push(@filesarray, $onefile);
1286    }
1287
1288    return \@filesarray;
1289}
1290
1291###########################################################
1292# Sorting an array
1293###########################################################
1294
1295sub sort_array
1296{
1297    my ( $arrayref ) = @_;
1298
1299    for ( my $i = 0; $i <= $#{$arrayref}; $i++ )
1300    {
1301        my $under = ${$arrayref}[$i];
1302
1303        for ( my $j = $i + 1; $j <= $#{$arrayref}; $j++ )
1304        {
1305            my $over = ${$arrayref}[$j];
1306
1307            if ( $under gt $over)
1308            {
1309                ${$arrayref}[$i] = $over;
1310                ${$arrayref}[$j] = $under;
1311                $under = $over;
1312            }
1313        }
1314    }
1315}
1316
1317###########################################################
1318# Renaming linux files with flag LINUXLINK
1319###########################################################
1320
1321sub prepare_linuxlinkfiles
1322{
1323    my ( $filesref ) = @_;
1324
1325    @installer::globals::linuxlinks = (); # empty this array, because it could be already used
1326    @installer::globals::linuxpatchfiles = (); # empty this array, because it could be already used
1327    @installer::globals::allfilessav = (); # empty this array, because it could be already used. Required for forced links
1328
1329    my @filesarray = ();
1330
1331    for ( my $i = 0; $i <= $#{$filesref}; $i++ )
1332    {
1333        my $onefile = ${$filesref}[$i];
1334        my %linkfilehash = ();
1335        my $linkfile = \%linkfilehash;
1336        installer::converter::copy_item_object($onefile, $linkfile);
1337
1338        my $ispatchfile = 0;
1339        my $styles = "";
1340        if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; }
1341        if ( $styles =~ /\bPATCH\b/ ) { $ispatchfile = 1; }
1342
1343        # Collecting all files for the mechanism with forced links
1344        # Saving a copy
1345        my %copyfilehash = ();
1346        my $copyfile = \%copyfilehash;
1347        installer::converter::copy_item_object($onefile, $copyfile);
1348        push( @installer::globals::allfilessav, $copyfile);
1349
1350        my $original_destination = $onefile->{'destination'};
1351        # $onefile->{'destination'} is used in the epm list file. This value can be changed now!
1352
1353        if ( $ispatchfile ) { $onefile->{'destination'} = $onefile->{'destination'} . "\.$installer::globals::linuxlibrarypatchlevel"; }
1354        else { $onefile->{'destination'} = $onefile->{'destination'} . "\.$installer::globals::linuxlibrarybaselevel"; }
1355
1356        my $infoline = "LINUXLINK: Changing file destination from $original_destination to $onefile->{'destination'} !\n";
1357        $installer::logger::Lang->print($infoline);
1358
1359        # all files without PATCH flag are included into the RPM
1360        if ( ! $ispatchfile ) { push( @filesarray, $onefile); }
1361        else { push( @installer::globals::linuxpatchfiles, $onefile); }
1362
1363        # Preparing the collector for the links
1364        # Setting the new file name as destination of the link
1365        my $linkdestination = $linkfile->{'Name'};
1366        installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$linkdestination);
1367        if ( $ispatchfile ) { $linkfile->{'destinationfile'} = $linkdestination . "\.$installer::globals::linuxlibrarypatchlevel"; }
1368        else { $linkfile->{'destinationfile'} = $linkdestination . "\.$installer::globals::linuxlibrarybaselevel"; }
1369        push( @installer::globals::linuxlinks, $linkfile );
1370
1371        $infoline = "LINUXLINK: Created link: $linkfile->{'destination'} pointing to $linkfile->{'destinationfile'} !\n";
1372        $installer::logger::Lang->print($infoline);
1373    }
1374
1375    return \@filesarray;
1376}
1377
1378###########################################################
1379# Adding links into "u-RPMs", that have the flag
1380# FORCE_INTO_UPDATE_PACKAGE
1381# This is only relevant for Linux
1382###########################################################
1383
1384sub prepare_forced_linuxlinkfiles
1385{
1386    my ( $linksref ) = @_;
1387
1388    my @linksarray = ();
1389
1390    for ( my $i = 0; $i <= $#{$linksref}; $i++ )
1391    {
1392        my $onelink = ${$linksref}[$i];
1393
1394        my $isforcedlink = 0;
1395        my $styles = "";
1396        if ( $onelink->{'Styles'} ) { $styles = $onelink->{'Styles'}; }
1397        if ( $styles =~ /\bFORCE_INTO_UPDATE_PACKAGE\b/ ) { $isforcedlink = 1; }
1398
1399        if ( $isforcedlink )
1400        {
1401            my $fileid = "";
1402
1403            if ( $onelink->{'ShortcutID'} )
1404            {
1405                $fileid = $onelink->{'ShortcutID'};
1406
1407                my $searchedlinkfile = find_file_by_id($linksref, $fileid);
1408
1409                # making a copy!
1410                my %linkfilehash = ();
1411                my $linkfile = \%linkfilehash;
1412                installer::converter::copy_item_object($searchedlinkfile, $linkfile);
1413
1414                $linkfile->{'Name'} = $onelink->{'Name'};
1415                $linkfile->{'destinationfile'} = $linkfile->{'destination'};
1416                my $linkdestination = $linkfile->{'destinationfile'};
1417                installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$linkdestination);
1418                $linkfile->{'destinationfile'} = $linkdestination;
1419
1420                my $localdestination = $linkfile->{'destination'};
1421                # Getting the path
1422                installer::pathanalyzer::get_path_from_fullqualifiedname(\$localdestination);
1423                $localdestination =~ s/\Q$installer::globals::separator\E\s*$//;
1424                $linkfile->{'destination'} = $localdestination . $installer::globals::separator . $onelink->{'Name'};
1425
1426                $infoline = "Forced link into update file: $linkfile->{'destination'} pointing to $linkfile->{'destinationfile'} !\n";
1427                $installer::logger::Lang->print($infoline);
1428
1429                # The file, defined by the link, has to be included into the
1430                # link array @installer::globals::linuxlinks
1431                push( @installer::globals::linuxlinks, $linkfile );
1432            }
1433
1434            if ( $onelink->{'FileID'} )
1435            {
1436                $fileid = $onelink->{'FileID'};
1437
1438                my $searchedlinkfile = find_file_by_id(\@installer::globals::allfilessav, $fileid);
1439
1440                # making a copy!
1441                my %linkfilehash = ();
1442                my $linkfile = \%linkfilehash;
1443                installer::converter::copy_item_object($searchedlinkfile, $linkfile);
1444
1445                $linkfile->{'Name'} = $onelink->{'Name'};
1446                $linkfile->{'destinationfile'} = $linkfile->{'destination'};
1447                my $linkdestination = $linkfile->{'destinationfile'};
1448                installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$linkdestination);
1449                $linkfile->{'destinationfile'} = $linkdestination;
1450
1451                my $localdestination = $linkfile->{'destination'};
1452                # Getting the path
1453                installer::pathanalyzer::get_path_from_fullqualifiedname(\$localdestination);
1454                $localdestination =~ s/\Q$installer::globals::separator\E\s*$//;
1455                $linkfile->{'destination'} = $localdestination . $installer::globals::separator . $onelink->{'Name'};
1456
1457                $infoline = "Forced link into update file: $linkfile->{'destination'} pointing to $linkfile->{'destinationfile'} !\n";
1458                $installer::logger::Lang->print($infoline);
1459
1460                # The file, defined by the link, has to be included into the
1461                # link array @installer::globals::linuxlinks
1462                push( @installer::globals::linuxlinks, $linkfile );
1463             }
1464
1465            if ( $fileid eq "" ) { installer::exiter::exit_program("ERROR: No FileID assigned to forced link $onelink->{'gid'} !", "prepare_forced_linuxlinkfiles"); }
1466
1467        }
1468        else
1469        {
1470            # Links with flag FORCE_INTO_UPDATE_PACKAGE are forced into "u"-RPM. All other
1471            # links are included into the non-"u"-package.
1472            push( @linksarray, $onelink );
1473        }
1474    }
1475
1476    return \@linksarray;
1477}
1478
1479###########################################################
1480# reorganizing the patchfile content,
1481# sorting for directory to decrease the file size
1482###########################################################
1483
1484sub reorg_patchfile
1485{
1486    my ($patchfiles, $patchfiledirectories) = @_;
1487
1488    my @patchfilesarray = ();
1489    my $line = "";
1490    my $directory = "";
1491
1492    # iterating over all directories, writing content into new patchfiles list
1493
1494    for ( my $i = 0; $i <= $#{$patchfiledirectories}; $i++ )
1495    {
1496        $directory = ${$patchfiledirectories}[$i];
1497        $line = "[" . $directory . "]" . "\n";
1498        push(@patchfilesarray, $line);
1499
1500        for ( my $j = 0; $j <= $#{$patchfiles}; $j++ )
1501        {
1502            # "\tXXXXX\t" . $olddestination . "\n";
1503            if ( ${$patchfiles}[$j] =~ /^\s*(.*?)\s*\tXXXXX\t\Q$directory\E\s*$/ )
1504            {
1505                $line = $1 . "\n";
1506                push(@patchfilesarray, $line);
1507            }
1508        }
1509    }
1510
1511    return \@patchfilesarray;
1512}
1513
1514###########################################################
1515# One special file has to be the last in patchfile.txt.
1516# Controlling this file, guarantees, that all files were
1517# patch correctly. Using version.ini makes it easy to
1518# control this by looking into the about box
1519# -> shifting one section to the end
1520###########################################################
1521
1522sub shift_section_to_end
1523{
1524    my ($patchfilelist) = @_;
1525
1526    my @patchfile = ();
1527    my @lastsection = ();
1528    my $lastsection = "program";
1529    my $notlastsection = "Basis\\program";
1530    my $record = 0;
1531
1532    for ( my $i = 0; $i <= $#{$patchfilelist}; $i++ )
1533    {
1534        my $line = ${$patchfilelist}[$i];
1535
1536        if (( $record ) && ( $line =~ /^\s*\[/ )) { $record = 0; }
1537
1538        if (( $line =~ /^\s*\[\Q$lastsection\E\\\]\s*$/ ) && ( ! ( $line =~ /\Q$notlastsection\E\\\]\s*$/ ))) { $record = 1; }
1539
1540        if ( $record ) { push(@lastsection, $line); }
1541        else { push(@patchfile, $line); }
1542    }
1543
1544    if ( $#lastsection > -1 )
1545    {
1546        for ( my $i = 0; $i <= $#lastsection; $i++ )
1547        {
1548            push(@patchfile, $lastsection[$i]);
1549        }
1550    }
1551
1552    return \@patchfile;
1553}
1554
1555###########################################################
1556# One special file has to be the last in patchfile.txt.
1557# Controlling this file, guarantees, that all files were
1558# patch correctly. Using version.ini makes it easy to
1559# control this by looking into the about box
1560# -> shifting one file of the last section to the end
1561###########################################################
1562
1563sub shift_file_to_end
1564{
1565    my ($patchfilelist) = @_;
1566
1567    my @patchfile = ();
1568    my $lastfilename = "version.ini";
1569    my $lastfileline = "";
1570    my $foundfile = 0;
1571
1572    # Only searching this file in the last section
1573    my $lastsectionname = "";
1574
1575    for ( my $i = 0; $i <= $#{$patchfilelist}; $i++ )
1576    {
1577        my $line = ${$patchfilelist}[$i];
1578        if ( $line =~ /^\s*\[(.*?)\]\s*$/ ) { $lastsectionname = $1; }
1579    }
1580
1581    my $record = 0;
1582    for ( my $i = 0; $i <= $#{$patchfilelist}; $i++ )
1583    {
1584        my $line = ${$patchfilelist}[$i];
1585
1586        if ( $line =~ /^\s*\[\Q$lastsectionname\E\]\s*$/ ) { $record = 1; }
1587
1588        if (( $line =~ /^\s*\"\Q$lastfilename\E\"\=/ ) && ( $record ))
1589        {
1590            $lastfileline = $line;
1591            $foundfile = 1;
1592            $record = 0;
1593            next;
1594        }
1595
1596        push(@patchfile, $line);
1597    }
1598
1599    if ( $foundfile ) { push(@patchfile, $lastfileline); }
1600
1601    return  \@patchfile;
1602}
1603
1604###########################################################
1605# Putting hash content into array and sorting it
1606###########################################################
1607
1608sub sort_hash
1609{
1610    my ( $hashref ) =  @_;
1611
1612    my $item = "";
1613    my @sortedarray = ();
1614
1615    foreach $item (keys %{$hashref}) { push(@sortedarray, $item); }
1616    installer::sorter::sorting_array_of_strings(\@sortedarray);
1617
1618    return \@sortedarray;
1619}
1620
1621###########################################################
1622# Renaming Windows files in Patch and creating file
1623# patchfiles.txt
1624###########################################################
1625
1626sub prepare_windows_patchfiles
1627{
1628    my ( $filesref, $languagestringref, $allvariableshashref ) = @_;
1629
1630    my @patchfiles = ();
1631    my %patchfiledirectories = ();
1632    my $patchfilename = "patchlist.txt";
1633    my $patchfilename2 = "patchmsi.dll";
1634
1635    if ( ! $allvariableshashref->{'WINDOWSPATCHLEVEL'} ) { installer::exiter::exit_program("ERROR: No Windows patch level defined in list file (WINDOWSPATCHLEVEL) !", "prepare_windows_patchfiles"); }
1636    # my $windowspatchlevel = $allvariableshashref->{'WINDOWSPATCHLEVEL'};
1637    my $windowspatchlevel = $installer::globals::buildid;
1638
1639    # the environment variable CWS_WORK_STAMP is set only in CWS
1640    if ( $ENV{'CWS_WORK_STAMP'} ) { $windowspatchlevel = $ENV{'CWS_WORK_STAMP'} . $windowspatchlevel; }
1641
1642    for ( my $i = 0; $i <= $#{$filesref}; $i++ )
1643    {
1644        my $onefile = ${$filesref}[$i];
1645
1646        my $filename = $onefile->{'Name'};
1647        if (( $filename eq $patchfilename ) || ( $filename eq $patchfilename2 )) { next; }
1648
1649        my $styles = "";
1650        if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; }
1651        if ( $styles =~ /\bDONTRENAMEINPATCH\b/ ) { next; }
1652
1653        # special handling for files with flag DONTSHOW. This files get the extension ".dontshow" to be filtered by dialogs.
1654        my $localwindowspatchlevel = $windowspatchlevel;
1655        if ( $styles =~ /\bDONTSHOW\b/ ) { $localwindowspatchlevel = $localwindowspatchlevel . "\.dontshow"; }
1656
1657        my $olddestination = $onefile->{'destination'};
1658        my $newdestination = $olddestination . "." . $localwindowspatchlevel;
1659        my $localfilename = $olddestination;
1660        installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$localfilename);  # file name part
1661        my $line = "\"" . $localfilename . "\"" . "=" . "\"" . "\." . $localwindowspatchlevel . "\"";
1662        $onefile->{'destination'} = $newdestination;
1663
1664        my $newfilename = $onefile->{'Name'} . "." . $localwindowspatchlevel;
1665        $onefile->{'Name'} = $newfilename;
1666
1667        # adding section information (section is the directory)
1668        my $origolddestination = $olddestination;
1669        installer::pathanalyzer::get_path_from_fullqualifiedname(\$olddestination); # directory part
1670        if ( ! $olddestination ) { $olddestination = "_root";  }
1671        if ( ! exists($patchfiledirectories{$olddestination}) ) { $patchfiledirectories{$olddestination} = 1; }
1672        $line = $line . "\tXXXXX\t" . $olddestination . "\n";
1673
1674        push(@patchfiles, $line);
1675
1676        # also collecting all files from patch in @installer::globals::patchfilecollector
1677        my $patchfileline = $origolddestination . "\n";
1678        push(@installer::globals::patchfilecollector, $patchfileline);
1679    }
1680
1681    my $winpatchdirname = "winpatch";
1682    my $winpatchdir = installer::systemactions::create_directories($winpatchdirname, $languagestringref);
1683
1684    my $patchlistfile = installer::existence::get_specified_file_by_name($filesref, $patchfilename);
1685
1686    # reorganizing the patchfile content, sorting for directory to decrease the file size
1687    my $sorteddirectorylist = sort_hash(\%patchfiledirectories);
1688    my $patchfilelist = reorg_patchfile(\@patchfiles, $sorteddirectorylist);
1689
1690    # shifting version.ini to the end of the list, to guarantee, that all files are patched
1691    # if the correct version is shown in the about box
1692    $patchfilelist = shift_section_to_end($patchfilelist);
1693    $patchfilelist = shift_file_to_end($patchfilelist);
1694
1695    # saving the file
1696    $patchfilename = $winpatchdir . $installer::globals::separator . $patchfilename;
1697    installer::files::save_file($patchfilename, $patchfilelist);
1698
1699    $installer::logger::Lang->print("\n");
1700    $installer::logger::Lang->printf("Created list of patch files: %s\n", $patchfilename);
1701
1702    # and assigning the new source
1703    $patchlistfile->{'sourcepath'} = $patchfilename;
1704
1705    # and finally checking the file size
1706    if ( -f $patchfilename )    # test of existence
1707    {
1708        my $filesize = ( -s $patchfilename );
1709        $infoline = "Size of patch file list: $filesize\n\n";
1710        $installer::logger::Lang->print($infoline);
1711        $installer::logger::Info->print( "... size of patch list file: $filesize Byte ... \n" );
1712
1713        # Win 98: Maximum size of ini file is 65 kB
1714        # if ( $filesize > 64000 ) { installer::exiter::exit_program("ERROR: Maximum size of patch file list is 65 kB (Win98), now reached: $filesize Byte !", "prepare_windows_patchfiles"); }
1715    }
1716
1717}
1718
1719###########################################################
1720# Replacing %-variables with the content
1721# of $allvariableshashref
1722###########################################################
1723
1724sub replace_variables_in_string
1725{
1726    my ( $string, $variableshashref ) = @_;
1727
1728    if ( $string =~ /^.*\%\w+.*$/ )
1729    {
1730        my $key;
1731
1732        foreach $key (keys %{$variableshashref})
1733        {
1734            my $value = $variableshashref->{$key};
1735            $key = "\%" . $key;
1736            $string =~ s/\Q$key\E/$value/g;
1737        }
1738    }
1739
1740    return $string;
1741}
1742
1743###########################################################
1744# Replacing %-variables with the content
1745# of $allvariableshashref
1746###########################################################
1747
1748sub replace_dollar_variables_in_string
1749{
1750    my ( $string, $variableshashref ) = @_;
1751
1752    if ( $string =~ /^.*\$\{\w+\}.*$/ )
1753    {
1754        my $key;
1755
1756        foreach $key (keys %{$variableshashref})
1757        {
1758            my $value = $variableshashref->{$key};
1759            $key = "\$\{" . $key . "\}";
1760            $string =~ s/\Q$key\E/$value/g;
1761        }
1762    }
1763
1764    return $string;
1765}
1766
1767###########################################################
1768# The list file contains the list of packages/RPMs that
1769# have to be copied.
1770###########################################################
1771
1772sub get_all_files_from_filelist
1773{
1774    my ( $listfile, $section ) = @_;
1775
1776    my @allpackages = ();
1777
1778    for ( my $i = 0; $i <= $#{$listfile}; $i++ )
1779    {
1780        my $line = ${$listfile}[$i];
1781        if ( $line =~ /^\s*\#/ ) { next; } # this is a comment line
1782        if ( $line =~ /^\s*$/ ) { next; } # empty line
1783        $line =~ s/^\s*//;
1784        $line =~ s/\s*$//;
1785        push(@allpackages, $line);
1786    }
1787
1788    return \@allpackages;
1789}
1790
1791###########################################################
1792# Getting one section from a file. Section begins with
1793# [xyz] and ends with file end or next [abc].
1794###########################################################
1795
1796sub get_section_from_file
1797{
1798    my ($file, $sectionname) = @_;
1799
1800    my @section = ();
1801    my $record = 0;
1802
1803    for ( my $i = 0; $i <= $#{$file}; $i++ )
1804    {
1805        my $line = ${$file}[$i];
1806
1807        if (( $record ) && ( $line =~ /^\s*\[/ ))
1808        {
1809            $record = 0;
1810            last;
1811        }
1812
1813        if ( $line =~ /^\s*\[\Q$sectionname\E\]\s*$/ ) { $record = 1; }
1814
1815        if ( $line =~ /^\s*\[/ ) { next; } # this is a section line
1816        if ( $line =~ /^\s*\#/ ) { next; } # this is a comment line
1817        if ( $line =~ /^\s*$/ ) { next; }  # empty line
1818        $line =~ s/^\s*//;
1819        $line =~ s/\s*$//;
1820        if ( $record ) { push(@section, $line); }
1821    }
1822
1823    return \@section;
1824
1825}
1826
1827#######################################################
1828# Substituting one variable in the xml file
1829#######################################################
1830
1831sub replace_one_dollar_variable
1832{
1833    my ($file, $variable, $searchstring) = @_;
1834
1835    for ( my $i = 0; $i <= $#{$file}; $i++ )
1836    {
1837        ${$file}[$i] =~ s/\$\{$searchstring\}/$variable/g;
1838    }
1839}
1840
1841#######################################################
1842# Substituting the variables in the xml file
1843#######################################################
1844
1845sub substitute_dollar_variables
1846{
1847    my ($file, $variableshashref) = @_;
1848
1849    my $key;
1850
1851    foreach $key (keys %{$variableshashref})
1852    {
1853        my $value = $variableshashref->{$key};
1854        replace_one_dollar_variable($file, $value, $key);
1855    }
1856}
1857
1858#############################################################################
1859# Collecting all packages or rpms located in the installation directory
1860#############################################################################
1861
1862sub get_all_packages_in_installdir
1863{
1864    my ($directory) = @_;
1865
1866    my $infoline = "";
1867
1868    my @allpackages = ();
1869    my $allpackages = \@allpackages;
1870
1871    if ( $installer::globals::islinuxrpmbuild )
1872    {
1873        $allpackages = installer::systemactions::find_file_with_file_extension("rpm", $directory);
1874    }
1875
1876    if ( $installer::globals::issolarisbuild )
1877    {
1878        $allpackages = installer::systemactions::get_all_directories($directory);
1879    }
1880
1881    return $allpackages;
1882}
1883
1884###############################################################
1885# The list of exclude packages can contain the
1886# beginning of the package name, not the complete name.
1887###############################################################
1888
1889sub is_matching
1890{
1891    my ($onepackage, $allexcludepackages ) = @_;
1892
1893    my $matches = 0;
1894
1895    for ( my $i = 0; $i <= $#{$allexcludepackages}; $i++ )
1896    {
1897        my $oneexcludepackage = ${$allexcludepackages}[$i];
1898
1899        if ( $onepackage =~ /^\s*$oneexcludepackage/ )
1900        {
1901            $matches = 1;
1902            last;
1903        }
1904    }
1905
1906    return $matches;
1907}
1908
1909###############################################################
1910# Copying all Solaris packages or RPMs from installation set
1911###############################################################
1912
1913sub copy_all_packages
1914{
1915    my ($allexcludepackages, $sourcedir, $destdir) = @_;
1916
1917    my $infoline = "";
1918
1919    $sourcedir =~ s/\/\s*$//;
1920    $destdir =~ s/\/\s*$//;
1921
1922    # $allexcludepackages is a list of RPMs and packages, that shall NOT be included into jds product
1923    my $allpackages = get_all_packages_in_installdir($sourcedir);
1924
1925    for ( my $i = 0; $i <= $#{$allpackages}; $i++ )
1926    {
1927        my $onepackage = ${$allpackages}[$i];
1928
1929        my $packagename = $onepackage;
1930
1931        if ( $installer::globals::issolarispkgbuild )   # on Solaris $onepackage contains the complete path
1932        {
1933            installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$packagename);
1934        }
1935
1936        if ( ! installer::existence::exists_in_array($packagename, $allexcludepackages))
1937        {
1938            if ( ! is_matching($packagename, $allexcludepackages ) )
1939            {
1940
1941                if ( $installer::globals::islinuxrpmbuild )
1942                {
1943                    my $sourcepackage = $sourcedir . $installer::globals::separator . $packagename;
1944                    my $destfile = $destdir . $installer::globals::separator . $packagename;
1945                    if ( ! -f $sourcepackage ) { installer::exiter::exit_program("ERROR: Could not find RPM $sourcepackage!", "copy_all_packages"); }
1946                    installer::systemactions::hardlink_one_file($sourcepackage, $destfile);
1947                }
1948
1949                if ( $installer::globals::issolarispkgbuild )
1950                {
1951                    my $destinationdir = $destdir . $installer::globals::separator . $packagename;
1952                    if ( ! -d $onepackage ) { installer::exiter::exit_program("ERROR: Could not find Solaris package $onepackage!", "copy_all_packages"); }
1953                    # installer::systemactions::hardlink_complete_directory($onepackage, $destinationdir);
1954                    # installer::systemactions::copy_complete_directory($onepackage, $destinationdir);
1955
1956                    my $systemcall = "cp -p -R $onepackage $destinationdir";
1957                    make_systemcall($systemcall);
1958                }
1959            }
1960            else
1961            {
1962                $infoline = "Excluding package (matching): $onepackage\n";
1963                $installer::logger::Lang->print($infoline);
1964            }
1965        }
1966        else
1967        {
1968            $infoline = "Excluding package (precise name): $onepackage\n";
1969            $installer::logger::Lang->print($infoline);
1970        }
1971    }
1972}
1973
1974######################################################
1975# Making systemcall
1976######################################################
1977
1978sub make_systemcall
1979{
1980    my ($systemcall) = @_;
1981
1982    my $returnvalue = system($systemcall);
1983
1984    my $infoline = "Systemcall: $systemcall\n";
1985    $installer::logger::Lang->print($infoline);
1986
1987    if ($returnvalue)
1988    {
1989        $infoline = "ERROR: Could not execute \"$systemcall\"!\n";
1990        $installer::logger::Lang->print($infoline);
1991    }
1992    else
1993    {
1994        $infoline = "Success: Executed \"$systemcall\" successfully!\n";
1995        $installer::logger::Lang->print($infoline);
1996    }
1997}
1998
1999###########################################################
2000# Copying all Solaris packages or RPMs from solver
2001###########################################################
2002
2003sub copy_additional_packages
2004{
2005    my ($allcopypackages, $destdir, $includepatharrayref) = @_;
2006
2007    my $infoline = "Copy additional packages into installation set.\n";
2008    $installer::logger::Lang->print($infoline);
2009
2010    $destdir =~ s/\/\s*$//;
2011
2012    for ( my $i = 0; $i <= $#{$allcopypackages}; $i++ )
2013    {
2014        my $onepackage = ${$allcopypackages}[$i];
2015        $infoline = "Copy package: $onepackage\n";
2016        $installer::logger::Lang->print($infoline);
2017
2018        # this package must be delivered into the solver
2019
2020        my $packagesourceref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$onepackage, $includepatharrayref, 0);
2021        if ($$packagesourceref eq "") { installer::exiter::exit_program("ERROR: Could not find jds file $onepackage!", "copy_additional_packages"); }
2022
2023        if ( $onepackage =~ /\.tar\.gz\s*$/ )
2024        {
2025            my $systemcall = "cd $destdir; cat $$packagesourceref | gunzip | tar -xf -";
2026            make_systemcall($systemcall);
2027        }
2028        else
2029        {
2030            my $destfile = $destdir . $installer::globals::separator . $onepackage;
2031            installer::systemactions::copy_one_file($$packagesourceref, $destfile);
2032        }
2033    }
2034}
2035
2036###########################################################
2037# Creating jds installation sets
2038###########################################################
2039
2040sub create_jds_sets
2041{
2042    my ($installationdir, $allvariableshashref, $languagestringref, $languagesarrayref, $includepatharrayref) = @_;
2043
2044    $installer::logger::Info->print("\n");
2045    $installer::logger::Info->print("******************************************\n");
2046    $installer::logger::Info->print("... creating jds installation set ...\n");
2047    $installer::logger::Info->print("******************************************\n");
2048
2049    installer::logger::include_header_into_logfile("Creating jds installation sets:");
2050
2051    my $firstdir = $installationdir;
2052    installer::pathanalyzer::get_path_from_fullqualifiedname(\$firstdir);
2053
2054    my $lastdir = $installationdir;
2055    installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$lastdir);
2056
2057    if ( $lastdir =~ /\./ ) { $lastdir =~ s/\./_jds_inprogress\./ }
2058    else { $lastdir = $lastdir . "_jds_inprogress"; }
2059
2060    # removing existing directory "_native_packed_inprogress" and "_native_packed_witherror" and "_native_packed"
2061
2062    my $jdsdir = $firstdir . $lastdir;
2063    if ( -d $jdsdir ) { installer::systemactions::remove_complete_directory($jdsdir); }
2064
2065    my $olddir = $jdsdir;
2066    $olddir =~ s/_inprogress/_witherror/;
2067    if ( -d $olddir ) { installer::systemactions::remove_complete_directory($olddir); }
2068
2069    $olddir = $jdsdir;
2070    $olddir =~ s/_inprogress//;
2071    if ( -d $olddir ) { installer::systemactions::remove_complete_directory($olddir); }
2072
2073    # creating the new directory
2074
2075    installer::systemactions::create_directory($jdsdir);
2076
2077    $installer::globals::saveinstalldir = $jdsdir;
2078
2079    # find and read jds files list
2080    my $filelistname = $installer::globals::jdsexcludefilename;
2081
2082    my $filelistnameref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$filelistname, "", 0);
2083    if ($$filelistnameref eq "") { installer::exiter::exit_program("ERROR: Could not find jds list file $filelistname!", "create_jds_sets"); }
2084
2085    my $listfile = installer::files::read_file($$filelistnameref);
2086
2087    my $infoline = "Found jds list file: $$filelistnameref\n";
2088    $installer::logger::Lang->print($infoline);
2089
2090    # substituting the variables
2091    substitute_dollar_variables($listfile, $allvariableshashref);
2092
2093    # determining the packages/RPMs to copy
2094    my $allexcludepackages = get_section_from_file($listfile, "excludefiles");
2095    my $allcopypackages = get_section_from_file($listfile, "copyfiles");
2096
2097    # determining the source directory
2098    my $alldirs = installer::systemactions::get_all_directories($installationdir);
2099    my $sourcedir = ${$alldirs}[0]; # there is only one directory
2100
2101    if ( $installer::globals::issolarisbuild ) { $sourcedir = $installer::globals::saved_packages_path; }
2102
2103    # copy all packages/RPMs
2104    copy_all_packages($allexcludepackages, $sourcedir, $jdsdir);
2105    copy_additional_packages($allcopypackages, $jdsdir, $includepatharrayref);
2106
2107    return $jdsdir;
2108}
2109
2110#############################################################################
2111# Checking, whether this installation set contains the correct languages
2112#############################################################################
2113
2114sub check_jds_language
2115{
2116    my ($allvariableshashref, $languagestringref) = @_;
2117
2118    my $infoline = "";
2119
2120    # languagesarrayref and $allvariableshashref->{'JDSLANG'}
2121
2122    if ( ! $allvariableshashref->{'JDSLANG'} ) { installer::exiter::exit_program("ERROR: For building JDS installation sets \"JDSLANG\" must be defined!", "check_jds_language"); }
2123    my $languagestring = $allvariableshashref->{'JDSLANG'};
2124
2125    my $sortedarray1 = installer::converter::convert_stringlist_into_array(\$languagestring, ",");
2126
2127    installer::sorter::sorting_array_of_strings($sortedarray1);
2128
2129    my $sortedarray2 = installer::converter::convert_stringlist_into_array($languagestringref, "_");
2130    installer::sorter::sorting_array_of_strings($sortedarray2);
2131
2132    my $string1 = installer::converter::convert_array_to_comma_separated_string($sortedarray1);
2133    my $string2 = installer::converter::convert_array_to_comma_separated_string($sortedarray2);
2134
2135    my $arrays_are_equal = compare_arrays($sortedarray1, $sortedarray2);
2136
2137    return $arrays_are_equal;
2138}
2139
2140###################################################################################
2141# Comparing two arrays. The arrays are equal, if the complete content is equal.
2142###################################################################################
2143
2144sub compare_arrays
2145{
2146    my ($array1, $array2) = @_;
2147
2148    my $arrays_are_equal = 1;
2149
2150    # checking the size
2151
2152    if ( ! ( $#{$array1} == $#{$array2} )) { $arrays_are_equal = 0; }   # different size
2153
2154    if ( $arrays_are_equal ) # only make further investigations if size is equal
2155    {
2156        for ( my $i = 0; $i <= $#{$array1}; $i++ )
2157        {
2158            # ingnoring whitespaces at end and beginning
2159            ${$array1}[$i] =~ s/^\s*//;
2160            ${$array2}[$i] =~ s/^\s*//;
2161            ${$array1}[$i] =~ s/\s*$//;
2162            ${$array2}[$i] =~ s/\s*$//;
2163
2164            if ( ! ( ${$array1}[$i] eq ${$array2}[$i] ))
2165            {
2166                $arrays_are_equal = 0;
2167                last;
2168            }
2169        }
2170    }
2171
2172    return $arrays_are_equal;
2173}
2174
2175#################################################################
2176# Copying the files defined as ScpActions into the
2177# installation set.
2178#################################################################
2179
2180sub put_scpactions_into_installset
2181{
2182    my ($installdir) = @_;
2183
2184    installer::logger::include_header_into_logfile("Start: Copying scp action files into installation set");
2185
2186    for ( my $i = 0; $i <= $#installer::globals::allscpactions; $i++ )
2187    {
2188        my $onescpaction = $installer::globals::allscpactions[$i];
2189
2190        my $subdir = "";
2191        if ( $onescpaction->{'Subdir'} ) { $subdir = $onescpaction->{'Subdir'}; }
2192
2193        if ( $onescpaction->{'Name'} eq "loader.exe" ) { next; }    # do not copy this ScpAction loader
2194
2195        my $destdir = $installdir;
2196        $destdir =~ s/\Q$installer::globals::separator\E\s*$//;
2197        if ( $subdir ) { $destdir = $destdir . $installer::globals::separator . $subdir; }
2198
2199        my $sourcefile = $onescpaction->{'sourcepath'};
2200        my $destfile = $destdir . $installer::globals::separator . $onescpaction->{'DestinationName'};
2201
2202        my $styles = "";
2203        if ( $onescpaction->{'Styles'} ) { $styles = $onescpaction->{'Styles'}; }
2204        if (( $styles =~ /\bFILE_CAN_MISS\b/ ) && ( $sourcefile eq "" )) { next; }
2205
2206        if (( $subdir =~ /\// ) || ( $subdir =~ /\\/ ))
2207        {
2208            installer::systemactions::create_directory_structure($destdir);
2209        }
2210        else
2211        {
2212            installer::systemactions::create_directory($destdir);
2213        }
2214
2215        installer::systemactions::copy_one_file($sourcefile, $destfile);
2216
2217        if ( $onescpaction->{'UnixRights'} )
2218        {
2219            my $localcall = "chmod $onescpaction->{'UnixRights'} $destfile \>\/dev\/null 2\>\&1";
2220            system($localcall);
2221        }
2222
2223    }
2224
2225    installer::logger::include_header_into_logfile("End: Copying scp action files into installation set");
2226
2227}
2228
2229#################################################################
2230# Collecting scp actions for all languages
2231#################################################################
2232
2233sub collect_scpactions
2234{
2235    my ($allscpactions) = @_;
2236
2237    for ( my $i = 0; $i <= $#{$allscpactions}; $i++ )
2238    {
2239        push(@installer::globals::allscpactions, ${$allscpactions}[$i]);
2240    }
2241}
2242
2243#################################################################
2244# Setting the platform name for download
2245#################################################################
2246
2247sub get_platform_name
2248{
2249    my $platformname = "";
2250
2251    if (( $installer::globals::islinuxintelrpmbuild ) || ( $installer::globals::islinuxinteldebbuild ))
2252    {
2253        $platformname = "LinuxIntel";
2254    }
2255    elsif (( $installer::globals::islinuxppcrpmbuild ) || ( $installer::globals::islinuxppcdebbuild ))
2256    {
2257        $platformname = "LinuxPowerPC";
2258    }
2259    elsif (( $installer::globals::islinuxx86_64rpmbuild ) || ( $installer::globals::islinuxx86_64debbuild ))
2260    {
2261        $platformname = "LinuxX86-64";
2262    }
2263    elsif ( $installer::globals::issolarissparcbuild )
2264    {
2265        $platformname = "SolarisSparc";
2266    }
2267    elsif ( $installer::globals::issolarisx86build )
2268    {
2269        $platformname = "Solarisx86";
2270    }
2271    elsif ( $installer::globals::iswindowsbuild )
2272    {
2273        $platformname = "Win32Intel";
2274    }
2275    elsif(( $installer::globals::compiler =~ /^unxmac.i/ ))
2276    {
2277        $platformname = "MacOSXIntel";
2278    }
2279    elsif ( $installer::globals::compiler =~ /^unxmaccx/ )
2280    {
2281        $platformname = "MacOSXX86-64";
2282    }
2283    elsif ( $installer::globals::compiler =~ /^unxmacxp/ )
2284    {
2285        $platformname = "MacOSXPowerPC";
2286    }
2287    else
2288    {
2289        # $platformname = $installer::globals::packageformat;
2290        $platformname = $installer::globals::compiler;
2291    }
2292
2293    return $platformname;
2294}
2295
2296###########################################################
2297# Adding additional variables into the variableshashref,
2298# that are defined in include files in the solver. The
2299# names of the include files are stored in
2300# ADD_INCLUDE_FILES (comma separated list).
2301###########################################################
2302
2303sub add_variables_from_inc_to_hashref
2304{
2305    my ($allvariables, $includepatharrayref) = @_;
2306
2307    my $infoline = "";
2308    my $includefilelist = "";
2309    if ( $allvariables->{'ADD_INCLUDE_FILES'} ) { $includefilelist = $allvariables->{'ADD_INCLUDE_FILES'}; }
2310
2311    my $includefiles = installer::converter::convert_stringlist_into_array_without_linebreak_and_quotes(\$includefilelist, ",");
2312
2313    for ( my $i = 0; $i <= $#{$includefiles}; $i++ )
2314    {
2315        my $includefilename = ${$includefiles}[$i];
2316        $includefilename =~ s/^\s*//;
2317        $includefilename =~ s/\s*$//;
2318        $includefilenameref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$includefilename, $includepatharrayref, 1);
2319        if ( $$includefilenameref eq "" ) { installer::exiter::exit_program("Include file $includefilename not found!\nADD_INCLUDE_FILES = $allvariables->{'ADD_INCLUDE_FILES'}", "add_variables_from_inc_to_hashref"); }
2320
2321        $installer::logger::Global->printf("Including inc file: %s\n", $$includefilenameref);
2322
2323        my $includefile = installer::files::read_file($$includefilenameref);
2324
2325        for ( my $j = 0; $j <= $#{$includefile}; $j++ )
2326        {
2327            # Analyzing all "key=value" lines
2328            my $oneline = ${$includefile}[$j];
2329
2330            if ( $oneline =~ /^\s*(\S+)\s*\=\s*(.*?)\s*$/ ) # no white space allowed in key
2331            {
2332                my $key = $1;
2333                my $value = $2;
2334                $allvariables->{$key} = $value;
2335                $installer::logger::Global->printf("Setting of variable: %s = %s\n",
2336                    $key, $value);
2337            }
2338        }
2339    }
2340
2341    # Allowing different Java versions for Windows and Unix. Instead of "JAVAVERSION"
2342    # the property "WINDOWSJAVAVERSION" has to be used, if it is set.
2343
2344    if ( $installer::globals::iswindowsbuild )
2345    {
2346        if (( exists($allvariables->{'WINDOWSJAVAVERSION'})) && ( $allvariables->{'WINDOWSJAVAVERSION'} ne "" ))
2347        {
2348            $allvariables->{'JAVAVERSION'} = $allvariables->{'WINDOWSJAVAVERSION'};
2349            $installer::logger::Global->printf(
2350                "Changing value of property \"JAVAVERSION\" to %s (property \"WINDOWSJAVAVERSION\").\n",
2351                $allvariables->{'JAVAVERSION'});
2352        }
2353    }
2354}
2355
2356##############################################
2357# Collecting all files from include pathes
2358##############################################
2359
2360sub collect_all_files_from_includepathes
2361{
2362    my ($patharrayref) = @_;
2363
2364    installer::logger::globallog("Reading all directories: Start");
2365    $installer::logger::Info->print( "... reading include pathes ...\n" );
2366    # empty the global
2367
2368    @installer::globals::allincludepathes =();
2369    my $infoline;
2370
2371    for ( my $i = 0; $i <= $#{$patharrayref}; $i++ )
2372    {
2373        $includepath = ${$patharrayref}[$i];
2374        installer::remover::remove_leading_and_ending_whitespaces(\$includepath);
2375
2376        if ( ! -d $includepath )
2377        {
2378            $installer::logger::Global->printf(
2379                "%s does not exist. (Can be removed from include path list?)\n",
2380                $includepath);
2381            next;
2382        }
2383
2384        my @sourcefiles = ();
2385        my $pathstring = "";
2386        installer::systemactions::read_full_directory($includepath, $pathstring, \@sourcefiles);
2387
2388        if ( ! ( $#sourcefiles > -1 ))
2389        {
2390            $installer::logger::Global->printf(
2391                "%s is empty. (Can be removed from include path list?)\n",
2392                $includepath);
2393        }
2394        else
2395        {
2396            my $number = $#sourcefiles + 1;
2397            $installer::logger::Global->printf(
2398                "Directory %s contains $number files (including subdirs)\n",
2399                $includepath);
2400
2401            my %allfileshash = ();
2402            $allfileshash{'includepath'} = $includepath;
2403
2404            for ( my $j = 0; $j <= $#sourcefiles; $j++ )
2405            {
2406                $allfileshash{$sourcefiles[$j]} = 1;
2407            }
2408
2409            push(@installer::globals::allincludepathes, \%allfileshash);
2410        }
2411    }
2412
2413    $installer::globals::include_pathes_read = 1;
2414
2415    installer::logger::globallog("Reading all directories: End");
2416    $installer::logger::Global->print("\n");
2417}
2418
2419##############################################
2420# Searching for a file with the gid
2421##############################################
2422
2423sub find_file_by_id
2424{
2425    my ( $filesref, $gid ) = @_;
2426
2427    my $foundfile = 0;
2428    my $onefile;
2429
2430    for ( my $i = 0; $i <= $#{$filesref}; $i++ )
2431    {
2432        $onefile = ${$filesref}[$i];
2433        my $filegid = $onefile->{'gid'};
2434
2435        if ( $filegid eq $gid )
2436        {
2437            $foundfile = 1;
2438            last;
2439        }
2440    }
2441
2442    # It does not need to exist. For example products that do not contain the libraries.
2443    # if (! $foundfile ) { installer::exiter::exit_program("ERROR: No unique file name found for $filename !", "get_selfreg_file"); }
2444
2445    if (! $foundfile ) { $onefile  = ""; }
2446
2447    return $onefile;
2448}
2449
2450##############################################
2451# Searching for an item with the gid
2452##############################################
2453
2454sub find_item_by_gid
2455{
2456    my ( $itemsref, $gid ) = @_;
2457
2458    my $founditem = 0;
2459    my $oneitem = "";
2460
2461    for ( my $i = 0; $i <= $#{$itemsref}; $i++ )
2462    {
2463        my $localitem = ${$itemsref}[$i];
2464        my $itemgid = $localitem->{'gid'};
2465
2466        if ( $itemgid eq $gid )
2467        {
2468            $oneitem = $localitem;
2469            $founditem = 1;
2470            last;
2471        }
2472    }
2473
2474    return $oneitem;
2475}
2476
2477#########################################################
2478# Calling sum
2479#########################################################
2480
2481sub call_sum
2482{
2483    my ($filename) = @_;
2484
2485    $sumfile = "/usr/bin/sum";
2486
2487    if ( ! -f $sumfile ) { installer::exiter::exit_program("ERROR: No file /usr/bin/sum", "call_sum"); }
2488
2489    my $systemcall = "$sumfile $filename |";
2490
2491    my $sumoutput = "";
2492
2493    open (SUM, "$systemcall");
2494    $sumoutput = <SUM>;
2495    close (SUM);
2496
2497    my $returnvalue = $?;   # $? contains the return value of the systemcall
2498
2499    my $infoline = "Systemcall: $systemcall\n";
2500    $installer::logger::Lang->print($infoline);
2501
2502    if ($returnvalue)
2503    {
2504        $infoline = "ERROR: Could not execute \"$systemcall\"!\n";
2505        $installer::logger::Lang->print($infoline);
2506    }
2507    else
2508    {
2509        $infoline = "Success: Executed \"$systemcall\" successfully!\n";
2510        $installer::logger::Lang->print($infoline);
2511    }
2512
2513    return $sumoutput;
2514}
2515
2516#########################################################
2517# Calling wc
2518# wc -c pkginfo | cut -f6 -d' '
2519#########################################################
2520
2521sub call_wc
2522{
2523    my ($filename) = @_;
2524
2525    $wcfile = "/usr/bin/wc";
2526
2527    if ( ! -f $wcfile ) { installer::exiter::exit_program("ERROR: No file /usr/bin/wc", "call_wc"); }
2528
2529    my $systemcall = "$wcfile -c $filename |";
2530
2531    my $wcoutput = "";
2532
2533    open (WC, "$systemcall");
2534    $wcoutput = <WC>;
2535    close (WC);
2536
2537    my $returnvalue = $?;   # $? contains the return value of the systemcall
2538
2539    my $infoline = "Systemcall: $systemcall\n";
2540    $installer::logger::Lang->print($infoline);
2541
2542    if ($returnvalue)
2543    {
2544        $infoline = "ERROR: Could not execute \"$systemcall\"!\n";
2545        $installer::logger::Lang->print($infoline);
2546    }
2547    else
2548    {
2549        $infoline = "Success: Executed \"$systemcall\" successfully!\n";
2550        $installer::logger::Lang->print($infoline);
2551    }
2552
2553    return $wcoutput;
2554}
2555
2556##############################################
2557# Setting architecture ARCH=i86pc
2558# instead of ARCH=i386.
2559##############################################
2560
2561sub set_old_architecture_string
2562{
2563    my ($pkginfofile) = @_;
2564
2565    for ( my $i = 0; $i <= $#{$pkginfofile}; $i++ )
2566    {
2567        if ( ${$pkginfofile}[$i] =~ /^\s*ARCH=i386\s*$/ )
2568        {
2569            ${$pkginfofile}[$i] =~ s/i386/i86pc/;
2570            last;
2571        }
2572    }
2573}
2574
2575##############################################
2576# For the new copied package, it is necessary
2577# that a value for the key SUNW_REQUIRES
2578# is set. Otherwise this copied package
2579# with ARCH=i86pc would be useless.
2580##############################################
2581
2582sub check_requires_setting
2583{
2584    my ($pkginfofile) = @_;
2585
2586    my $found = 0;
2587    my $patchid = "";
2588
2589    for ( my $i = 0; $i <= $#{$pkginfofile}; $i++ )
2590    {
2591        if ( ${$pkginfofile}[$i] =~ /^\s*SUNW_REQUIRES=(\S*?)\s*$/ )
2592        {
2593            $patchid = $1;
2594            $found = 1;
2595            last;
2596        }
2597    }
2598
2599    if (( ! $found ) || ( $patchid eq "" )) { installer::exiter::exit_program("ERROR: No patch id defined for SUNW_REQUIRES in patch pkginfo file!", "check_requires_setting"); }
2600}
2601
2602##############################################
2603# Setting checksum and wordcount for changed
2604# pkginfo file into pkgmap.
2605##############################################
2606
2607sub set_pkginfo_line
2608{
2609    my ($pkgmapfile, $pkginfofilename) = @_;
2610
2611    # 1 i pkginfo 442 34577 1166716297
2612    # ->
2613    # 1 i pkginfo 443 34737 1166716297
2614    #
2615    # wc -c pkginfo | cut -f6 -d' '  -> 442  (variable)
2616    # sum pkginfo | cut -f1 -d' '  -> 34577  (variable)
2617    # grep 'pkginfo' pkgmap | cut -f6 -d' '  -> 1166716297  (fix)
2618
2619    my $checksum = call_sum($pkginfofilename);
2620    if ( $checksum =~ /^\s*(\d+)\s+.*$/ ) { $checksum = $1; }
2621
2622    my $wordcount = call_wc($pkginfofilename);
2623    if ( $wordcount =~ /^\s*(\d+)\s+.*$/ ) { $wordcount = $1; }
2624
2625    for ( my $i = 0; $i <= $#{$pkgmapfile}; $i++ )
2626    {
2627        if ( ${$pkgmapfile}[$i] =~ /(^.*\bpkginfo\b\s+)(\d+)(\s+)(\d+)(\s+)(\d+)(\s*$)/ )
2628        {
2629            my $newline = $1 . $wordcount . $3 . $checksum . $5 . $6 . $7;
2630            ${$pkgmapfile}[$i] = $newline;
2631            last;
2632        }
2633    }
2634}
2635
2636##############################################
2637# Setting time stamp of copied files to avoid
2638# errors from pkgchk.
2639##############################################
2640
2641sub set_time_stamp
2642{
2643    my ($olddir, $newdir, $copyfiles) = @_;
2644
2645    for ( my $i = 0; $i <= $#{$copyfiles}; $i++ )
2646    {
2647        my $sourcefile = $olddir . $installer::globals::separator . ${$copyfiles}[$i];
2648        my $destfile = $newdir . $installer::globals::separator . ${$copyfiles}[$i];
2649
2650        my $systemcall = "touch -r $sourcefile $destfile";
2651
2652        my $returnvalue = system($systemcall);
2653
2654        my $infoline = "Systemcall: $systemcall\n";
2655        $installer::logger::Lang->print($infoline);
2656
2657        if ($returnvalue)
2658        {
2659            $infoline = "ERROR: \"$systemcall\" failed!\n";
2660            $installer::logger::Lang->print($infoline);
2661        }
2662        else
2663        {
2664            $infoline = "Success: \"$systemcall\" !\n";
2665            $installer::logger::Lang->print($infoline);
2666        }
2667    }
2668}
2669
2670############################################################
2671# Generating pathes for cygwin (first version)
2672# This function has problems with cygwin, if $tmpfilename
2673# contains many thousand files (OpenOffice SDK).
2674############################################################
2675
2676sub generate_cygwin_pathes_old
2677{
2678    my ($filesref) = @_;
2679
2680    my ($tmpfilehandle, $tmpfilename) = tmpnam();
2681    open SOURCEPATHLIST, ">$tmpfilename" or die "oops...\n";
2682    for ( my $i = 0; $i <= $#{$filesref}; $i++ )
2683    {
2684        print SOURCEPATHLIST "${$filesref}[$i]->{'sourcepath'}\n";
2685    }
2686    close SOURCEPATHLIST;
2687    my @cyg_sourcepathlist = qx{cygpath -w -f "$tmpfilename"};
2688    chomp @cyg_sourcepathlist;
2689    unlink "$tmpfilename" or die "oops\n";
2690    for ( my $i = 0; $i <= $#{$filesref}; $i++ )
2691    {
2692        ${$filesref}[$i]->{'cyg_sourcepath'} = $cyg_sourcepathlist[$i];
2693    }
2694
2695}
2696
2697#################################################
2698# Generating pathes for cygwin (second version)
2699# This function generates smaller files for
2700#################################################
2701
2702sub generate_cygwin_pathes
2703{
2704    my ($filesref) = @_;
2705
2706    $installer::logger::Lang->add_timestamp("Starting generating cygwin pathes");
2707
2708    my $infoline = "Generating cygwin pathes (generate_cygwin_pathes)\n";
2709    $installer::logger::Lang->print($infoline);
2710
2711    my $max = 5000;  # number of pathes in one file
2712
2713    my @pathcollector = ();
2714    my $startnumber = 0;
2715    my $counter = 0;
2716
2717    for ( my $i = 0; $i <= $#{$filesref}; $i++ )
2718    {
2719        my $filename = ${$filesref}[$i]->{'sourcepath'};
2720        push(@pathcollector, $filename . "\n");
2721        $counter++;
2722
2723        if (( $i == $#{$filesref} ) || ((( $counter % $max ) == 0 ) && ( $i > 0 )))
2724        {
2725            my $tmpfilename = "cygwinhelper_" . $i . ".txt";
2726            my $temppath = $installer::globals::temppath;
2727            $temppath =~ s/\Q$installer::globals::separator\E\s*$//;
2728            $tmpfilename = $temppath . $installer::globals::separator . $tmpfilename;
2729            $infoline = "Creating temporary file for cygwin conversion: $tmpfilename (contains $counter pathes)\n";
2730            $installer::logger::Lang->print($infoline);
2731            if ( -f $tmpfilename ) { unlink $tmpfilename; }
2732
2733            installer::files::save_file($tmpfilename, \@pathcollector);
2734
2735            my $success = 0;
2736            $installer::logger::Lang->printf(
2737                "Converting %d filenames to cygwin notation\n",
2738                $counter);
2739            my @cyg_sourcepathlist = qx{cygpath -w -f "$tmpfilename"};
2740            chomp @cyg_sourcepathlist;
2741
2742            # Validating the array, it has to contain the correct number of values
2743            my $new_pathes = $#cyg_sourcepathlist + 1;
2744            if ( $new_pathes == $counter ) { $success = 1; }
2745
2746            if ($success)
2747            {
2748                $installer::logger::Lang->printf(
2749                    "Successfully converted %d paths to cygwin notation\n",
2750                    $counter);
2751            }
2752            else
2753            {
2754                $installer::logger::Lang->print("ERROR: Failed to convert to cygwin pathes!\n");
2755                installer::exiter::exit_program(
2756                    "ERROR: Failed to convert to cygwin pathes!",
2757                    "generate_cygwin_pathes");
2758            }
2759
2760            for ( my $j = 0; $j <= $#cyg_sourcepathlist; $j++ )
2761            {
2762                my $number = $startnumber + $j;
2763                ${$filesref}[$number]->{'cyg_sourcepath'} = $cyg_sourcepathlist[$j];
2764            }
2765
2766            if ( -f $tmpfilename ) { unlink $tmpfilename; }
2767
2768            @pathcollector = ();
2769            $startnumber = $startnumber + $max;
2770            $counter = 0;
2771        }
2772    }
2773
2774    # Checking existence fo cyg_sourcepath for every file
2775    for ( my $i = 0; $i <= $#{$filesref}; $i++ )
2776    {
2777        if (( ! exists(${$filesref}[$i]->{'cyg_sourcepath'}) ) || ( ${$filesref}[$i]->{'cyg_sourcepath'} eq "" ))
2778        {
2779            $infoline = "ERROR: No cygwin sourcepath defined for file ${$filesref}[$i]->{'sourcepath'}\n";
2780            $installer::logger::Lang->print($infoline);
2781            installer::exiter::exit_program("ERROR: No cygwin sourcepath defined for file ${$filesref}[$i]->{'sourcepath'}!", "generate_cygwin_pathes");
2782        }
2783    }
2784
2785    $installer::logger::Lang->add_timestamp("Ending generating cygwin pathes");
2786}
2787
2788##############################################
2789# Include only files from install directory
2790# in pkgmap file.
2791##############################################
2792
2793sub filter_pkgmapfile
2794{
2795    my ($pkgmapfile) = @_;
2796
2797    my @pkgmap = ();
2798
2799    my $line = ": 1 10\n";
2800    push(@pkgmap, $line);
2801
2802    for ( my $i = 0; $i <= $#{$pkgmapfile}; $i++ )
2803    {
2804        $line = ${$pkgmapfile}[$i];
2805        if ( $line =~ /^\s*1\si\s/ ) { push(@pkgmap, $line); }
2806    }
2807
2808    return \@pkgmap;
2809}
2810
2811##############################################
2812# Creating double packages for Solaris x86.
2813# One package with ARCH=i386 and one with
2814# ARCH=i86pc.
2815##############################################
2816
2817sub fix_solaris_x86_patch
2818{
2819    my ($packagename, $subdir) = @_;
2820
2821    # changing into directory of packages, important for soft linking
2822    my $startdir = cwd();
2823    chdir($subdir);
2824
2825    # $packagename is: "SUNWstaroffice-core01"
2826    # Current working directory is: "<path>/install/en-US_inprogress"
2827
2828    # create new folder in "packages": $packagename . ".i"
2829    my $newpackagename = $packagename . "\.i";
2830    my $newdir = $newpackagename;
2831    installer::systemactions::create_directory($newdir);
2832
2833    # collecting all directories in the package
2834    my $olddir = $packagename;
2835    my $allsubdirs = installer::systemactions::get_all_directories_without_path($olddir);
2836
2837    # link all directories from $packagename to $packagename . ".i"
2838    for ( my $i = 0; $i <= $#{$allsubdirs}; $i++ )
2839    {
2840        my $sourcedir = $olddir . $installer::globals::separator . ${$allsubdirs}[$i];
2841        my $destdir = $newdir . $installer::globals::separator . ${$allsubdirs}[$i];
2842        my $directory_depth = 2; # important for soft links, two directories already exist
2843        installer::systemactions::softlink_complete_directory($sourcedir, $destdir, $directory_depth);
2844    }
2845
2846    # copy "pkginfo" and "pkgmap" from $packagename to $packagename . ".i"
2847    my @allcopyfiles = ("pkginfo", "pkgmap");
2848    for ( my $i = 0; $i <= $#allcopyfiles; $i++ )
2849    {
2850        my $sourcefile = $olddir . $installer::globals::separator . $allcopyfiles[$i];
2851        my $destfile = $newdir . $installer::globals::separator . $allcopyfiles[$i];
2852        installer::systemactions::copy_one_file($sourcefile, $destfile);
2853    }
2854
2855    # change in pkginfo in $packagename . ".i" the value for ARCH from i386 to i86pc
2856    my $pkginfofilename = "pkginfo";
2857    $pkginfofilename = $newdir . $installer::globals::separator . $pkginfofilename;
2858
2859    my $pkginfofile = installer::files::read_file($pkginfofilename);
2860    set_old_architecture_string($pkginfofile);
2861    installer::files::save_file($pkginfofilename, $pkginfofile);
2862
2863    # adapt the values in pkgmap for pkginfo file, because this file was edited
2864    my $pkgmapfilename = "pkgmap";
2865    $pkgmapfilename = $newdir . $installer::globals::separator . $pkgmapfilename;
2866
2867    my $pkgmapfile = installer::files::read_file($pkgmapfilename);
2868    set_pkginfo_line($pkgmapfile, $pkginfofilename);
2869    installer::files::save_file($pkgmapfilename, $pkgmapfile);
2870
2871    # changing back to startdir
2872    chdir($startdir);
2873}
2874
2875###################################################
2876# Creating double core01 package for Solaris x86.
2877# One package with ARCH=i386 and one with
2878# ARCH=i86pc. This is necessary, to inform the
2879# user about the missing "small patch", if
2880# packages with ARCH=i86pc are installed.
2881###################################################
2882
2883sub fix2_solaris_x86_patch
2884{
2885    my ($packagename, $subdir) = @_;
2886
2887    if ( $packagename =~ /-core01\s*$/ )    # only this one package needs to be duplicated
2888    {
2889        my $startdir = cwd();
2890        chdir($subdir);
2891
2892        # $packagename is: "SUNWstaroffice-core01"
2893        # Current working directory is: "<path>/install/en-US_inprogress"
2894
2895        # create new package in "packages": $packagename . ".i"
2896        my $olddir = $packagename;
2897        my $newpackagename = $packagename . "\.i";
2898        my $newdir = $newpackagename;
2899
2900        installer::systemactions::create_directory($newdir);
2901
2902        my $oldinstalldir = $olddir . $installer::globals::separator . "install";
2903        my $newinstalldir = $newdir . $installer::globals::separator . "install";
2904
2905        installer::systemactions::copy_complete_directory($oldinstalldir, $newinstalldir);
2906
2907        # setting time stamp of all copied files to avoid errors from pkgchk
2908        my $allinstallfiles = installer::systemactions::get_all_files_from_one_directory_without_path($newinstalldir);
2909        set_time_stamp($oldinstalldir, $newinstalldir, $allinstallfiles);
2910
2911        # copy "pkginfo" and "pkgmap" from $packagename to $packagename . ".i"
2912        my @allcopyfiles = ("pkginfo", "pkgmap");
2913        for ( my $i = 0; $i <= $#allcopyfiles; $i++ )
2914        {
2915            my $sourcefile = $olddir . $installer::globals::separator . $allcopyfiles[$i];
2916            my $destfile = $newdir . $installer::globals::separator . $allcopyfiles[$i];
2917            installer::systemactions::copy_one_file($sourcefile, $destfile);
2918        }
2919
2920        # change in pkginfo in $packagename . ".i" the value for ARCH from i386 to i86pc
2921        my $pkginfofilename = "pkginfo";
2922        $pkginfofilename = $newdir . $installer::globals::separator . $pkginfofilename;
2923
2924        my $pkginfofile = installer::files::read_file($pkginfofilename);
2925        set_old_architecture_string($pkginfofile);
2926        check_requires_setting($pkginfofile);
2927        installer::files::save_file($pkginfofilename, $pkginfofile);
2928
2929        # adapt the values in pkgmap for pkginfo file, because this file was edited
2930        my $pkgmapfilename = "pkgmap";
2931        $pkgmapfilename = $newdir . $installer::globals::separator . $pkgmapfilename;
2932
2933        my $pkgmapfile = installer::files::read_file($pkgmapfilename);
2934        set_pkginfo_line($pkgmapfile, $pkginfofilename);
2935        $pkgmapfile = filter_pkgmapfile($pkgmapfile);
2936        installer::files::save_file($pkgmapfilename, $pkgmapfile);
2937
2938        # setting time stamp of all copied files to avoid errors from pkgchk
2939        set_time_stamp($olddir, $newdir, \@allcopyfiles);
2940
2941        # changing back to startdir
2942        chdir($startdir);
2943    }
2944}
2945
2946################################################
2947# Files with flag HIDDEN get a dot at the
2948# beginning of the file name. This cannot be
2949# defined in scp2 project, because tooling
2950# cannot handle files with beginning dot
2951# correctly.
2952################################################
2953
2954sub resolving_hidden_flag
2955{
2956    my ($filesarrayref, $variableshashref, $item, $languagestringref) = @_;
2957
2958    my $diritem = lc($item);
2959    my $infoline = "";
2960
2961    my $hiddendirbase = installer::systemactions::create_directories("hidden_$diritem", $languagestringref);
2962
2963    installer::logger::include_header_into_logfile("$item with flag HIDDEN:");
2964
2965    for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ )
2966    {
2967        my $onefile = ${$filesarrayref}[$i];
2968        my $styles = "";
2969
2970        if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; }
2971
2972        if ( $styles =~ /\bHIDDEN\b/ )
2973        {
2974            # Language specific subdirectory
2975
2976            my $onelanguage = $onefile->{'specificlanguage'};
2977
2978            if ($onelanguage eq "")
2979            {
2980                $onelanguage = "00";    # files without language into directory "00"
2981            }
2982
2983            my $hiddendir = $hiddendirbase . $installer::globals::separator . $onelanguage . $installer::globals::separator;
2984            installer::systemactions::create_directory($hiddendir); # creating language specific directories
2985
2986            # copy files and edit them with the variables defined in the zip.lst
2987
2988            my $onefilename = $onefile->{'Name'};
2989            my $newfilename = "\." . $onefilename;
2990            my $sourcefile = $onefile->{'sourcepath'};
2991            my $destfile = $hiddendir . $newfilename;
2992
2993            my $copysuccess = installer::systemactions::copy_one_file($sourcefile, $destfile);
2994
2995            if ( $copysuccess )
2996            {
2997                # $onefile->{'Name'} = $newfilename;
2998                $onefile->{'sourcepath'} = $destfile;
2999                $destination = $onefile->{'destination'};
3000                installer::pathanalyzer::get_path_from_fullqualifiedname(\$destination);
3001                if ( $destination eq "" ) { $onefile->{'destination'} = $newfilename; }
3002                else { $onefile->{'destination'} = $destination . $installer::globals::separator . $newfilename; }
3003
3004                $infoline = "Success: Using file with flag HIDDEN from \"$onefile->{'sourcepath'}\"!\n";
3005                $installer::logger::Lang->print($infoline);
3006            }
3007            else
3008            {
3009                $infoline = "Error: Failed to copy HIDDEN file from \"$sourcefile\" to \"$destfile\"!\n";
3010                $installer::logger::Lang->print($infoline);
3011            }
3012        }
3013    }
3014
3015    $infoline = "\n";
3016    $installer::logger::Lang->print($infoline);
3017}
3018
3019################################################
3020# Controlling that all keys in hash A are
3021# also key in hash B.
3022################################################
3023
3024sub key_in_a_is_also_key_in_b
3025{
3026    my ( $hashref_a, $hashref_b) = @_;
3027
3028    my $returnvalue = 1;
3029
3030    my $key;
3031    foreach $key ( keys %{$hashref_a} )
3032    {
3033        if ( ! exists($hashref_b->{$key}) )
3034        {
3035            print "*****\n";
3036            foreach $keyb ( keys %{$hashref_b} ) { print "$keyb : $hashref_b->{$keyb}\n"; }
3037            print "*****\n";
3038            $returnvalue = 0;
3039        }
3040    }
3041
3042    return $returnvalue;
3043}
3044
3045######################################################
3046# Getting the first entry from a list of languages
3047######################################################
3048
3049sub get_first_from_list
3050{
3051    my ( $list ) = @_;
3052
3053    my $first = $list;
3054
3055    if ( $list =~ /^\s*(.+?),(.+)\s*$/) # "?" for minimal matching
3056    {
3057        $first = $1;
3058    }
3059
3060    return $first;
3061}
3062
3063################################################
3064# Setting all spellchecker languages
3065################################################
3066
3067sub set_spellcheckerlanguages
3068{
3069    my ( $productlanguagesarrayref, $allvariables ) = @_;
3070
3071    my %productlanguages = ();
3072    for ( my $i = 0; $i <= $#{$productlanguagesarrayref}; $i++ ) { $productlanguages{${$productlanguagesarrayref}[$i]} = 1;  }
3073
3074    my $spellcheckfilename = $allvariables->{'SPELLCHECKERFILE'};
3075
3076    my $spellcheckfileref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$spellcheckfilename, "", 1);
3077
3078    if ($$spellcheckfileref eq "") { installer::exiter::exit_program("ERROR: Could not find $spellcheckfilename!", "set_spellcheckerlanguages"); }
3079
3080    $installer::logger::Global->printf("Using spellchecker file: %s\n", $$spellcheckfileref);
3081
3082    my $spellcheckfile = installer::files::read_file($$spellcheckfileref);
3083    my %spellcheckhash = ();
3084
3085    for ( my $j = 0; $j <= $#{$spellcheckfile}; $j++ )
3086    {
3087        # Analyzing all "key=value" lines
3088        my $oneline = ${$spellcheckfile}[$j];
3089
3090        if ( $oneline =~ /^\s*(\S+)\s*\=\s*\"(.*?)\"\s*$/ ) # no white space allowed in key
3091        {
3092            my $onelang = $1;
3093            my $languagelist = $2;
3094
3095            # Special handling for language packs. Only include the first language of the language list.
3096            # If no spellchecker shall be included, the keyword "EMPTY" can be used.
3097
3098            if ( $installer::globals::languagepack )
3099            {
3100                my $first = get_first_from_list($languagelist);
3101
3102                if ( $first eq "EMPTY" )     # no spellchecker into language pack
3103                {
3104                    $languagelist = "";
3105                }
3106                else
3107                {
3108                    $languagelist = $first;
3109                }
3110            }
3111            else  # no language pack, so EMPTY is not required
3112            {
3113                $languagelist =~ s/^\s*EMPTY\s*,//; # removing the entry EMPTY
3114            }
3115
3116            $spellcheckhash{$onelang} = $languagelist;
3117        }
3118    }
3119
3120    # Collecting all required languages in %installer::globals::spellcheckerlanguagehash
3121
3122    foreach my $lang (keys %productlanguages)
3123    {
3124        my $languagelist = "";
3125        if ( exists($spellcheckhash{$lang}) ) { $languagelist = $spellcheckhash{$lang}; }
3126        else { $languagelist = $spellcheckhash{'en-US'}; }  # defaulting to English
3127
3128        my $langlisthash = installer::converter::convert_stringlist_into_hash(\$languagelist, ",");
3129        foreach my $onelang ( keys %{$langlisthash} ) { $installer::globals::spellcheckerlanguagehash{$onelang} = 1; }
3130    }
3131
3132    $installer::globals::analyze_spellcheckerlanguage = 1;
3133
3134    # Logging
3135
3136    my $langstring = "";
3137    foreach my $lang (sort keys %installer::globals::spellcheckerlanguagehash) { $langstring = $langstring . "," . $lang }
3138    $langstring =~ s/^\s*,//;
3139
3140    $installer::logger::Global->printf("Collected spellchecker languages for spellchecker: %s\n", $langstring);
3141}
3142
3143################################################
3144# Including a license text into setup script
3145################################################
3146
3147sub put_license_into_setup
3148{
3149    my ($installdir, $includepatharrayref) = @_;
3150
3151    # find and read the license file
3152    my $licenselanguage = "en-US";                  # always english !
3153    my $licensefilename = "LICENSE";
3154#   my $licensefilename = "LICENSE" . ".txt";
3155    my $licenseincludepatharrayref = get_language_specific_include_pathes($includepatharrayref, $licenselanguage);
3156
3157    my $licenseref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$licensefilename, $licenseincludepatharrayref, 0);
3158    if ($$licenseref eq "") { installer::exiter::exit_program("ERROR: Could not find License file $licensefilename!", "put_license_into_setup"); }
3159    my $licensefile = installer::files::read_file($$licenseref);
3160
3161    # Read setup
3162    my $setupfilename = $installdir . $installer::globals::separator . "setup";
3163    my $setupfile = installer::files::read_file($setupfilename);
3164
3165    # Replacement
3166    my $infoline = "Adding licensefile into setup script\n";
3167    $installer::logger::Lang->print($infoline);
3168
3169    my $includestring = "";
3170    for ( my $i = 0; $i <= $#{$licensefile}; $i++ ) { $includestring = $includestring . ${$licensefile}[$i]; }
3171    for ( my $i = 0; $i <= $#{$setupfile}; $i++ ) { ${$setupfile}[$i] =~ s/LICENSEFILEPLACEHOLDER/$includestring/; }
3172
3173    # Write setup
3174    installer::files::save_file($setupfilename, $setupfile);
3175}
3176
3177################################################
3178# Setting global path to getuid.so library
3179################################################
3180
3181sub set_getuid_path
3182{
3183    my ($includepatharrayref) = @_;
3184
3185    my $getuidlibraryname = "getuid.so";
3186    my $getuidlibraryref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$getuidlibraryname, $includepatharrayref, 0);
3187    if ($$getuidlibraryref eq "") { installer::exiter::exit_program("ERROR: Could not find $getuidlibraryname!", "set_getuid_path"); }
3188
3189    $installer::globals::getuidpath = $$getuidlibraryref;
3190    $installer::globals::getuidpathset = 1;
3191}
3192
3193#########################################################
3194# Create a tar file from the binary package
3195#########################################################
3196
3197sub tar_package
3198{
3199    my ( $installdir, $packagename, $tarfilename, $getuidlibrary) = @_;
3200
3201    my $ldpreloadstring = "";
3202
3203    if (($ENV{'FAKEROOT'} ne "no") && ($ENV{'FAKEROOT'} ne "")) {
3204        $ldpreloadstring = $ENV{'FAKEROOT'};
3205    } else {
3206        if ( $getuidlibrary ne "" ) { $ldpreloadstring = "LD_PRELOAD=" . $getuidlibrary; }
3207    }
3208
3209    my $systemcall = "cd $installdir; $ldpreloadstring tar -cf - $packagename > $tarfilename";
3210    # my $systemcall = "cd $installdir; $ldpreloadstring tar -cf - * > $tarfilename";
3211
3212    my $returnvalue = system($systemcall);
3213
3214    my $infoline = "Systemcall: $systemcall\n";
3215    $installer::logger::Lang->print($infoline);
3216
3217    if ($returnvalue)
3218    {
3219        $infoline = "ERROR: Could not execute \"$systemcall\"!\n";
3220        $installer::logger::Lang->print($infoline);
3221    }
3222    else
3223    {
3224        $infoline = "Success: Executed \"$systemcall\" successfully!\n";
3225        $installer::logger::Lang->print($infoline);
3226    }
3227
3228    my $localcall = "chmod 775 $tarfilename \>\/dev\/null 2\>\&1";
3229    $returnvalue = system($localcall);
3230
3231    my $fulltarfile = $installdir . $installer::globals::separator . $tarfilename;
3232    my $filesize = ( -s $fulltarfile );
3233
3234    return $filesize;
3235}
3236
3237#########################################################
3238# Create a tar file from the binary package
3239#########################################################
3240
3241sub untar_package
3242{
3243    my ( $installdir, $tarfilename, $getuidlibrary) = @_;
3244
3245    my $ldpreloadstring = "";
3246
3247    if (($ENV{'FAKEROOT'} ne "no") && ($ENV{'FAKEROOT'} ne "")) {
3248        $ldpreloadstring = $ENV{'FAKEROOT'};
3249    } else {
3250        if ( $getuidlibrary ne "" ) { $ldpreloadstring = "LD_PRELOAD=" . $getuidlibrary; }
3251    }
3252
3253    my $systemcall = "cd $installdir; $ldpreloadstring tar -xf $tarfilename";
3254
3255    my $returnvalue = system($systemcall);
3256
3257    my $infoline = "Systemcall: $systemcall\n";
3258    $installer::logger::Lang->print($infoline);
3259
3260    if ($returnvalue)
3261    {
3262        $infoline = "ERROR: Could not execute \"$systemcall\"!\n";
3263        $installer::logger::Lang->print($infoline);
3264    }
3265    else
3266    {
3267        $infoline = "Success: Executed \"$systemcall\" successfully!\n";
3268        $installer::logger::Lang->print($infoline);
3269    }
3270
3271    my $localcall = "chmod 775 $tarfilename \>\/dev\/null 2\>\&1";
3272    $returnvalue = system($localcall);
3273}
3274
3275#########################################################
3276# Shuffle an array (Fisher Yates shuffle)
3277#########################################################
3278
3279sub shuffle_array
3280{
3281    my ( $arrayref ) = @_;
3282
3283    # my $counter = 0;
3284    # my $infoline = "Old package order: \n";
3285    # $installer::logger::Lang->print($infoline);
3286    # foreach my $onepackage ( @{$arrayref} )
3287    # {
3288    #   $counter++;
3289    #   $infoline = "$counter: $onepackage->{'module'}\n";
3290    #   $installer::logger::Lang->print($infoline);
3291    # }
3292
3293    my $i = @$arrayref;
3294    while (--$i)
3295    {
3296        my $j = int rand ($i+1);
3297        @$arrayref[$i,$j] = @$arrayref[$j,$i];
3298    }
3299
3300    # $counter = 0;
3301    # $infoline = "New package order: \n";
3302    # $installer::logger::Lang->print($infoline);
3303    # foreach my $onepackage ( @{$arrayref} )
3304    # {
3305    #   $counter++;
3306    #   $infoline = "$counter: $onepackage->{'module'}\n";
3307    #   $installer::logger::Lang->print($infoline);
3308    # }
3309}
3310
3311################################################
3312# Defining the English license text to add
3313# it into Solaris packages.
3314################################################
3315
3316sub set_english_license
3317{
3318    my $additional_license_name = $installer::globals::englishsolarislicensename;   # always the English file
3319    my $licensefileref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$additional_license_name, "" , 0);
3320    if ( $$licensefileref eq "" ) { installer::exiter::exit_program("ERROR: Could not find license file $additional_license_name!", "set_english_license"); }
3321    $installer::globals::englishlicenseset = 1;
3322    $installer::globals::englishlicense = installer::files::read_file($$licensefileref);
3323    installer::scpzipfiles::replace_all_ziplistvariables_in_file($installer::globals::englishlicense, $variableshashref);
3324}
3325
3326##############################################
3327# Setting time stamp of copied files to avoid
3328# errors from pkgchk.
3329##############################################
3330
3331sub set_time_stamp_for_file
3332{
3333    my ($sourcefile, $destfile) = @_;
3334
3335    my $systemcall = "touch -r $sourcefile $destfile";
3336
3337    my $returnvalue = system($systemcall);
3338
3339    my $infoline = "Systemcall: $systemcall\n";
3340    $installer::logger::Lang->print($infoline);
3341
3342    if ($returnvalue)
3343    {
3344        $infoline = "ERROR: \"$systemcall\" failed!\n";
3345        $installer::logger::Lang->print($infoline);
3346    }
3347    else
3348    {
3349        $infoline = "Success: \"$systemcall\" !\n";
3350        $installer::logger::Lang->print($infoline);
3351    }
3352}
3353
3354##############################################
3355# Setting checksum and wordcount for changed
3356# pkginfo file into pkgmap.
3357##############################################
3358
3359sub change_onefile_in_pkgmap
3360{
3361    my ($pkgmapfile, $fullfilename, $shortfilename) = @_;
3362
3363    # 1 i pkginfo 442 34577 1166716297
3364    # ->
3365    # 1 i pkginfo 443 34737 1166716297
3366    #
3367    # wc -c pkginfo | cut -f6 -d' '  -> 442  (variable)
3368    # sum pkginfo | cut -f1 -d' '  -> 34577  (variable)
3369    # grep 'pkginfo' pkgmap | cut -f6 -d' '  -> 1166716297  (fix)
3370
3371    my $checksum = call_sum($fullfilename);
3372    if ( $checksum =~ /^\s*(\d+)\s+.*$/ ) { $checksum = $1; }
3373
3374    my $wordcount = call_wc($fullfilename);
3375    if ( $wordcount =~ /^\s*(\d+)\s+.*$/ ) { $wordcount = $1; }
3376
3377    for ( my $i = 0; $i <= $#{$pkgmapfile}; $i++ )
3378    {
3379        if ( ${$pkgmapfile}[$i] =~ /(^.*\b\Q$shortfilename\E\b\s+)(\d+)(\s+)(\d+)(\s+)(\d+)(\s*$)/ )
3380        {
3381            my $newline = $1 . $wordcount . $3 . $checksum . $5 . $6 . $7;
3382            ${$pkgmapfile}[$i] = $newline;
3383            last;
3384        }
3385    }
3386}
3387
3388################################################
3389# Adding the content of the English license
3390# file into the system integration packages.
3391################################################
3392
3393sub add_license_into_systemintegrationpackages
3394{
3395    my ($destdir, $packages) = @_;
3396
3397    for ( my $i = 0; $i <= $#{$packages}; $i++ )
3398    {
3399        my $copyrightfilename = ${$packages}[$i] . $installer::globals::separator . "install" . $installer::globals::separator . "copyright";
3400        if ( ! -f $copyrightfilename ) { installer::exiter::exit_program("ERROR: Could not find license file in system integration package: $copyrightfilename!", "add_license_into_systemintegrationpackages"); }
3401        my $copyrightfile = installer::files::read_file($copyrightfilename);
3402
3403        # Saving time stamp of old copyrightfile
3404        my $savcopyrightfilename = $copyrightfilename . ".sav";
3405        installer::systemactions::copy_one_file($copyrightfilename, $savcopyrightfilename);
3406        set_time_stamp_for_file($copyrightfilename, $savcopyrightfilename); # now $savcopyrightfile has the time stamp of $copyrightfile
3407
3408        # Adding license content to copyright file
3409        push(@{$copyrightfile}, "\n");
3410        for ( my $i = 0; $i <= $#{$installer::globals::englishlicense}; $i++ ) { push(@{$copyrightfile}, ${$installer::globals::englishlicense}[$i]); }
3411        installer::files::save_file($copyrightfilename, $copyrightfile);
3412
3413        # Setting the old time stamp saved with $savcopyrightfilename
3414        set_time_stamp_for_file($savcopyrightfilename, $copyrightfilename); # now $copyrightfile has the time stamp of $savcopyrightfile
3415        unlink($savcopyrightfilename);
3416
3417        # Changing content of copyright file in pkgmap
3418        my $pkgmapfilename = ${$packages}[$i] . $installer::globals::separator . "pkgmap";
3419        if ( ! -f $pkgmapfilename ) { installer::exiter::exit_program("ERROR: Could not find pkgmap in system integration package: $pkgmapfilename!", "add_license_into_systemintegrationpackages"); }
3420        my $pkgmap = installer::files::read_file($pkgmapfilename);
3421        change_onefile_in_pkgmap($pkgmap, $copyrightfilename, "copyright");
3422        installer::files::save_file($pkgmapfilename, $pkgmap);
3423    }
3424}
3425
3426#########################################################
3427# Collecting all pkgmap files from an installation set
3428#########################################################
3429
3430sub collectpackagemaps
3431{
3432    my ( $installdir, $languagestringref, $allvariables ) = @_;
3433
3434    installer::logger::include_header_into_logfile("Collecing all packagemaps (pkgmap):");
3435
3436    my $pkgmapdir = installer::systemactions::create_directories("pkgmap", $languagestringref);
3437    my $subdirname = $allvariables->{'UNIXPRODUCTNAME'} . "_pkgmaps";
3438    my $pkgmapsubdir = $pkgmapdir . $installer::globals::separator . $subdirname;
3439    if ( -d $pkgmapsubdir ) { installer::systemactions::remove_complete_directory($pkgmapsubdir); }
3440    if ( ! -d $pkgmapsubdir ) { installer::systemactions::create_directory($pkgmapsubdir); }
3441
3442    $installdir =~ s/\/\s*$//;
3443    # Collecting all packages in $installdir and its sub package ("packages")
3444    my $searchdir = $installdir . $installer::globals::separator . $installer::globals::epmoutpath;
3445
3446    my $allpackages = installer::systemactions::get_all_directories_without_path($searchdir);
3447
3448    for ( my $i = 0; $i <= $#{$allpackages}; $i++ )
3449    {
3450        my $pkgmapfile = $searchdir . $installer::globals::separator . ${$allpackages}[$i] . $installer::globals::separator . "pkgmap";
3451        my $destfilename = $pkgmapsubdir . $installer::globals::separator . ${$allpackages}[$i] . "_pkgmap";
3452        installer::systemactions::copy_one_file($pkgmapfile, $destfilename);
3453    }
3454
3455    # Create a tar gz file with all package maps
3456    my $tarfilename = $subdirname . ".tar";
3457    my $targzname = $tarfilename . ".gz";
3458    # my $systemcall = "cd $pkgmapdir; tar -cf - $subdirname > $tarfilename";
3459    $systemcall = "cd $pkgmapdir; tar -cf - $subdirname | gzip > $targzname";
3460    make_systemcall($systemcall);
3461    installer::systemactions::remove_complete_directory($pkgmapsubdir, 1);
3462}
3463
34641;
3465