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