package Mkcd::Functions;

our $VERSION = '0.1.1';

use strict;
use File::Path;
use rpmtools;
use Mkcd::Tools qw(cpal du checkDiscs imageSize printDiscsFile config);

=head1 NAME

Functions - mkcd module

=head1 SYNOPSYS

    require Mkcd::Functions;

=head1 DESCRIPTION

C<Mkcd::Functions> include the disc building standard functions.

=head1 SEE ALSO

mkcd

=head1 COPYRIGHT

Copyright (C) 2000,2001 MandrakeSoft <warly@mandrakesoft.com>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

=cut

my $config;
# need to do it to have its address
my %functions = ();
# [ function name, matching regexp, [arguments list (same as above)]] 
$functions{dir} =
	[
	    ["","dir",2,"<directory name> <directory location>", "Set directory name",
	    sub { 	my ($cd,$fn,$repname,$reploc) = @_;
		my @a = ("dir", { repname => $repname, reploc => $reploc});
		$config->{disc}[$cd]{function}{data}{dir}{$repname} and print {$config->{LOG}} "WARNING: disc $cd: duplicate directory $repname ($reploc)\n";
		$config->{disc}[$cd]{function}{list}[$fn] = \@a;
		$config->{disc}[$cd]{function}{data}{dir}{$repname} = $reploc;
		print {$config->{LOG}} "dir: $repname ($reploc)\n";
		push @{$config->{disc}[$cd]{steps}}, \@a;
		1
	    }, "Setting directory" ]
];
#
# generic options
#
# source => source dir
#
# done  => done
#

$functions{generic} =
	[ 
	    ["","generic", 2, "<directory name> <list name>","Copy rpms from a list to a directory", 
		sub {	my ($cd,$fn,$repname,$list) = @_; 
		    my @a = ("generic", { repname => $repname, list => $list});
		    $config->{disc}[$cd]{function}{data}{dir}{$repname} or print {$config->{LOG}} "ERROR: disc $cd: $repname not defined\n";
		    $config->{list}[$list] or print {$config->{LOG}} "ERROR: lists $list does not exist, ignoring\n" and return 0;
		    $config->{disc}[$cd]{function}{list}[$fn] = \@a;
		    push @{$config->{disc}[$cd]{function}{data}{generic}{$repname}}, \@a ;
		    push @{$config->{disc}[$cd]{fastgeneric}}, \@a; # [$a[1],$repname,$list];
		    push @{$config->{disc}[$cd]{steps}}, \@a;
		    1
		}, "Copying rpms to directory"],
	    ["s","source", [
	    [ "", "source", 0, "","Source mode configuration", 
		sub { 	my ($tmp) = @_;
		    $tmp->[0]{source} = 1;
		}, "Source mode"],
# 2002 03 14 deprecated
#	    [ "p", "priority", 1, "<priority>","Set the repository priority", sub { my ($tmp,$prio) = @_; $tmp->[0]{priority} = $prio}, "Setting source repository priority"]
	    ], "[options]","Source mode setting", 
		sub { my ($cd,$fn,$options) = @_; 
		    foreach (keys %$options){ $config->{disc}[$cd]{function}{list}[$fn][1]{$_} = $options->{$_}}
	    	    1
		}, "Source mode option configuration"],
	    [ "", "synthesis", 0, "","Add synthesis file in the repository", sub { my ($cd,$fn) = @_; $config->{disc}[$cd]{function}{list}[$fn][1]{synthesis} = 1 }, "Setting synthesis tag"],
	    [ "l", "limit", [
	        [ "", "limit", 1, "<limit>","Source mode configuration", 
	    	    sub { 	my ($tmp,$limit) = @_;
		        $tmp->[0]{limit} = 1;
		        $tmp->[0]{value} = $limit;
		    }, "Limit mode"],
		[ "s", "soft",0, "","Soft mode, do not limit size if disc is not full", sub { my ($tmp) = @_; $tmp->[0]{soft} = 1 } , "Setting soft limit flag"]
	    
	    ], "[options] <limit>","Limit the space of this directory on the disc", 
	        sub { my ($cd,$fn,$options) = @_; 
		    $config->{disc}[$cd]{function}{list}[$fn][1]{limit} = $options
		}, "Setting limit option"]
	];
	    
	    
	#
	# installation data
	#
	#       install => install source path
	#
	# 	rpmsdir => rpm repositories list
	#
	# 	bootimg => boot image
	#
	#	tag => tag 
	#
	# 	lang  => langage list
	#
	# 	rpmsrate => rpmsrate file to use
	#
	# 	compssUsers => compssUsers file to use
	#
	# 	score => score weights
	#
	# Installation options 
	#
	#	nosources
	#
	#	nosrcfit
	#
$functions{installation} = 
	[ 
	# 0
	    [ "", "installation", -1, "<rpms directory name 1> <rpms directory name 2> ... <rpms directory name n>","Preparing the installation directory and dependencies files", 
		sub {	my ($cd,$fn,@rpms) = @_; 
		    my @rpmsdir;
		    foreach (@rpms){
			my ($cdrep,$repname,$list) = m,(\d+)/([^/]+)(?:/(\d+))?,;
			push @rpmsdir, [$list,$cdrep,$repname]	
		    }
		    my @a = ('installation', { rpmsdir => \@rpmsdir});
		    ref $config->{disc}[$cd]{function}{data}{installation} and print {$config->{LOG}} "ERROR: disc $cd: duplicate installation procedure, ignored\n" and return 0;
		    $config->{disc}[$cd]{function}{list}[$fn] = \@a;
		    $config->{disc}[$cd]{function}{data}{installation} = \@a;
		    push @{$config->{disc}[$cd]{steps}}, \@a;
		    1
		}, "Setting up installation files"],
    # 1
	    [ "b", "bootimg", 1, "<boot image>","boot image for the cd", sub { my ($cd,$fn,$img) = @_; $config->{disc}[$cd]{function}{list}[$fn][1]{bootimg} = $img; 1}, "Setting boot image"],
    # 2
	    [ "c", "compss", 1, "<compsUser file>", "Choose alternative compssUser file", sub { my ($cd,$fn,$compss) = @_; $config->{disc}[$cd]{function}{list}[$fn][1]{compssUsers} = $compss; 1 }, "Setting alternative compssUser file"],
    # 3
	    [ "f", "fixed", [
		["", "fixed", -1, "<repository> <extra RPMS directory 1> <extra RPMS directory 2> ... <extra RPMS directory n>","Fixed repository option configuration", 
		    sub { 	my ($tmp,@arg) = @_;
		       	$tmp->[0]{fixed} = 1;
	    		push @$tmp, @arg;
    			1
    		    },"Setting fixed option arguments"],
    		["d", "dup", 0, "","Duplicate mode, accept to put package present in already done discs", sub { my ($tmp) = @_; $tmp->[0]{dup} = 1; 1 },"Setting duplicate mode"],
    		["", "nodeps", 0, "","Do not handle other discs dependencies", sub { my ($tmp) = @_; $tmp->[0]{nodeps} = 1; 1 },"Setting nodeps mode"],
    		["", "update", 0, "","Update mode, update already done packages", sub { my ($tmp) = @_; $tmp->[0]{update} = 1; 1 },"Setting update mode"]
    		], "<options> <fixed coma separated repositories>","repositories that must not be computed but integrated in the installation group", 
		    sub { my ($cd,$fn,$options,@fixed) = @_; 
		    foreach (@fixed){
			my ($cdrep,$repname,$list) = m,(\d+)/([^/]+)(?:/(\d+))?,;
			push @{$config->{disc}[$cd]{function}{list}[$fn][1]{rpmsdir}}, [ $list, $cdrep, $repname, $options ]
		    }
		    $config->{disc}[$cd]{function}{list}[$fn][1]{fixed} = 1;
		    1}, "Setting fixed option"],
	    # 4  
	    [ "l", "lang", 1, "<languages to include>","languages that are conisdered by the install", sub { my ($cd,$fn,$lang) = @_; my @l = split ',',$lang; push @{$config->{disc}[$cd]{function}{list}[$fn][1]{lang}},  @l; 1}, "Setting language supported"],
	    # 5
	    [ "i", "installdir", 1, "<installation directory source>","Installation directory source", sub { my ($cd,$fn,$dir) = @_; $config->{disc}[$cd]{function}{list}[$fn][1]{install} = $dir; 1}, "Setting install source directory"],
	    # 6 
	    [ "", "nosources", 0, "","Do not add source rpm for this installation group", sub { my ($cd,$fn) = @_; $config->{disc}[$cd]{function}{list}[$fn][1]{nosources} = 1; 1}, "Setting nosources tag for this installation group"],
	    # 7
	    [ "", "nosrcfit", 0, "","Do not stop if sources discs are full", sub { my ($cd,$fn) = @_; $config->{disc}[$cd]{function}{list}[$fn][1]{nosrcfit} = 1; 1}, "Setting nosourcefit tag for this installation group"],
	    # 8
	    [ "o", "sortweight", 1, "<list of respective ordering weight (size,dependencies,rpmsrate)>","Set the weight for automatic sorting rules", sub { my ($cd,$fn,$weight) = @_; $config->{disc}[$cd]{function}{list}[$fn][1]{score} = [split ',', $weight]; 1}, "Setting sorting weights"],
	    # 9
	    [ "r", "rpmsrate", 1, "<rpmsrate file>", "Choose alternative rpmsrate", sub { my ($cd,$fn,$rpmsrate) = @_; $config->{disc}[$cd]{function}{list}[$fn][1]{rpmsrate} = $rpmsrate }, "Setting alternative rpmsrate file"],
	    # 10
	    [ "t", "tag name", 1, "<tag name>", "Tag added to the VERSION file", sub { my ($cd,$fn,$tag) = @_; $config->{disc}[$cd]{function}{list}[$fn][1]{tag} = $tag }, "Setting the tag name"],
	    # 11
	    [ "", "dup", 0, "", "Authorize duplicate version for this install", sub { my ($cd,$fn) = @_; $config->{disc}[$cd]{function}{data}[$fn][1]{dup} = 1 }, "Setting the tag name"],
	    # 12
	    [ "", "nodeps", 0, "", "Do not include deps", sub { my ($cd,$fn) = @_; $config->{disc}[$cd]{function}{list}[$fn][1]{nodeps} = 1 }, "Setting nodeps flag for this installation"],
	    # 13
	    [ "", "isolinux", 0, "", "Isolinux mode", sub { my ($cd,$fn) = @_; $config->{disc}[$cd]{function}{list}[$fn][1]{isolinux} = 1 }, "Build an isolinux install"],
	    # 14
	    [ "", "synthesis", 0, "","Add synthesis file in the repository", sub { my ($cd,$fn) = @_; $config->{disc}[$cd]{function}{list}[$fn][1]{synthesis} = 1 }, "Setting synthesis tag"],
	    # 15
	    [ "", "sequential", 0, "","Build disc in a sequential way", sub { my ($cd,$fn) = @_; $config->{disc}[$cd]{function}{list}[$fn][1]{sequential} = 1 }, "Setting sequential tag"],
	    # 16
	    [ "", "oem", [
		["", "oem", 0, "[options]","OEM mode configuration", 
		    sub { 	my ($tmp,@arg) = @_;
		       	$tmp->[0]{oem} = 1;
	    		push @$tmp, @arg;
    			1
    		    },"Setting fixed option arguments"],
	        ["d", "dir", 1, "<root dir 1> <root dir 2> ... <root dir n>","Create OEM disc based on existing directories list", 
		    sub { 
		        my ($tmp,@dir) = @_; 
			$tmp->[0]{file} and print {$config->{LOG}} "ERROR installation oem: could not use file and dir option in the same time, ignoring dir\n" and return 0;
			$tmp->[0]{dir} = \@dir; 
			1 },"Selecting directories"],
	        ["h", "hdlists", 1, "<hdlists to include>","Select hdlists to include (all if omitted)", sub { my ($tmp,$hdlists) = @_; $tmp->[0]{hdlists} = $hdlists; 1 },"Selecting hdlists to include"],
    		["f", "file", 1, "<script file>","Script file describing the discs (generated with printscript)", 
		    sub { 
			my ($tmp,$file) = @_; 
			$tmp->[0]{dir} and print {$config->{LOG}} "ERROR installation oem: could not use file and dir option in the same time, ignoring file\n" and return 0;
			$tmp->[0]{file} = $file; 1 
		    },"Setting update mode"],
		["l", "listfile", 1, "<list of package to choose>","Choose an alternative method to select package to select in OEM mode (default is to use packages with rate greater than 2 in rpmsrate ", sub { my ($tmp,$file) = @_; $tmp->[0]{file} = $file; 1 },"Selecting list file"],
    		["n", "norebuild", 0, "","Do not rebuild hdlists", sub { my ($tmp,$file) = @_; $tmp->[0]{norebtuild} = 1; 1 },"Setting no rebuilding flag"],
    		["r", "rpmsrate", 1, "<rpmsrate file>","Rpmsrate file to use for OEM mode (use the installation one if omitted)", sub { my ($tmp,$rpmsrate) = @_; $tmp->[0]{rpmsrate} = $rpmsrate; 1 },"Setting rpmsrate file OEM file"]
    		], "[options]","OEM mode", 
		    sub { my ($cd,$fn,$options) = @_; 
		    $config->{disc}[$cd]{function}{list}[$fn][1]{oem} = $options;
		    if ($options->{dir}){

		    }elsif ($options->{file}){
			my $oemconfig;
			config($options->{file},$oemconfig,\%functions);
			my ($discsFiles) = readBatchFile($options->{file}) or print {$config->{LOG}} "ERROR installation oem: cannot read script file $options->{file}\n" and return 0;
			my $dir;
			my $list = @{$config->{list}};
			print {$config->{LOG}} "installation oem: adding list $list for OEM mode\n";
			$config->{list}[$list]{packages} = 0; # TODO
			push @{$config->{disc}[$cd]{fastgeneric}}, [ '', { repname => $dir ,list => $list}];
			my $gfn = @{$config->{disc}[$cd]{function}{list}};
			print {$config->{LOG}} "installation oem: adding function $gfn for generic oem packages\n";
			$functions{generic}[5]($cd,$gfn,$dir,$list);
		    }else{
			print {$config->{LOG}} "ERROR installation oem: no disc to build OEM on (either file or dir option are needed)\n";
			$config->{disc}[$cd]{function}{list}[$fn][1]{oem} = 0;
			return 0
		    }
		    1}, "Setting oem option"],
            # 17
	    [ "s", "sources", -1, "<srpms directory name 1> <srpms directory name 2> ... <srpms directory name n>","Select the sources list where to put packages", 
		sub { my ($cd,$fn,@sources) = @_; 
		    foreach (@sources){
			my ($cdrep,$repname,$list) = m,(\d+)/([^/]+)(?:/(\d+))?,;
			push @{$config->{disc}[$cd]{function}{list}[$fn][1]{srpmsdir}}, [ $list, $cdrep, $repname ]
		    }
		    $config->{disc}[$cd]{function}{list}[$fn][1]{sources} = 1;
		    1}, "Setting fixed option"],
];
#
#
# advertising option
#
#    img
#    lang (new advertising mode in 8.2 deprecates this option)
#    

$functions{advertising} =
	[
	    [ "", "advertising", -1, "<picture 1> <picture 2> ... <picture n>", "Setting the advertising pictures used by the installation", 
		sub { my ($cd,$fn,@img) = @_;
		    my @a = ('advertising',{ img => \@img});	
		    $config->{disc}[$cd]{function}{list}[$fn] = \@a;
		    push @{$config->{disc}[$cd]{function}{data}{advertising}}, \@a;
		    push @{$config->{disc}[$cd]{steps}}, \@a
	 	}, "Setting the advertising pictures"],
	 [ "l", "lang", 1, "<language>", "Set the advertising picture language", sub { my ($cd,$fn,$lang) = @_; $config->{disc}[$cd]{function}{list}[$fn][1]{lang} = $lang; 1}, "Setting the picture language"]
];

#
# cdcom data
#
#      dir
#
#      source
#
$functions{cdcom} =
	 [
   	    [ "", "cdcom", 2, "<directory name> <disc directory location>", "Commercial disc",
       		sub { my ($cd,$fn,$dir,$source) = @_;
	   	    my @a = ('cdcom',{ dir => $dir, source => $source});
		    $config->{disc}[$cd]{function}{list}[$fn] = \@a;
		    push @{$config->{disc}[$cd]{function}{data}{cdcom}}, \@a;
		    my $list = @{$config->{list}};
		    print {$config->{LOG}} "cdcom: adding list $list for $source/Mandrake/RPMS\n";
		    $config->{list}[$list]{packages} = [[ "$source/Mandrake/RPMS" ]];
		    $config->{list}[$list]{done} = 1;
		    push @{$config->{disc}[$cd]{fastgeneric}}, [ '', { repname => $dir ,list => $list}];
		    push @{$config->{disc}[$cd]{steps}}, \@a;
		    1
		}, "Configuring a commercial disc"],
	    [ "d", "dest", 1, "<destination on the disc>", "Select the destination directory on the disc", sub { my ($cd,$fn,$dest) = @_; $config->{disc}[$cd]{function}{list}[$fn][1]{dest} = $dest; 1}, "Selecting destination directory"]
];
#
# cp 
#
$functions{cp} =
	[
	    [ "", "cp", 2, "<file source> <file destination>", "Copy",
	       	sub { my ($cd,$fn,$src,$dest) = @_;
		    my @a = ('cp',{ src => $src, dest => $dest});
		    $config->{disc}[$cd]{function}{list}[$fn] = \@a;
		    push @{$config->{disc}[$cd]{function}{data}{cp}}, \@a;
		    push @{$config->{disc}[$cd]{steps}}, \@a;
		    1
	}, "Copying files"]
];
 #
 # isolinux
 #
$functions{isolinux} = 
    [ 
    # 0
	[ "", "isolinux", 1, "<source dir of the isolinux files","Create an isolinux bootable disc", 
	    sub {   my ($cd,$fn,$source) = @_; 
		    my @a = ('isolinux', { isolinux => $source});
		    ref $config->{disc}[$cd]{function}{data}{isolinux} and print {$config->{LOG}} "ERROR: disc $cd: duplicate isolinux procedure, ignored\n" and return 0;
		    $config->{disc}[$cd]{function}{list}[$fn] = \@a;
		    $config->{disc}[$cd]{function}{data}{isolinux} = \@a;
		    push @{$config->{disc}[$cd]{steps}}, \@a;
		    1
	  }, "Setting an isolinux boot disc"],
	  # 1
	[ "b", "bootimg", 1, "<isolinux boot file>","boot file for isolinux", sub { my ($cd,$fn,$img) = @_; $config->{disc}[$cd]{function}{list}[$fn][1]{bootimg} = $img; 1}, "Setting isolinux boot file"],
];
 #
 # boot 
 #
$functions{boot} = 
    [ 
    # 0
	[ "", "boot", 0, "<options> <files or dir to copy 1> <files or dir to copy 2> .. <files or dir to copy 3>","Boot parameters and files", 
	    sub {   my ($cd,$fn) = @_; 
		    my @a = ('boot', {});
		    $config->{disc}[$cd]{function}{list}[$fn] = \@a;
		    push @{$config->{disc}[$cd]{function}{data}{boot}}, \@a;
		    push @{$config->{disc}[$cd]{steps}}, \@a;
		    1
	  }, "Setting boot parameters"
	],
	  # 1
	[ "", "isolinux", [
		["", "isolinux", 1, "<isolinux directory>", "Create an isolinux bootable disc", 
		    sub { 	my ($tmp,@args) = @_;
		       	$tmp->[0]{isolinux} = 1;
			push @$tmp, @args
    		    },"Setting an isolinux boot disc"],
    		], "<options> <isolinux directory>","isolinux boot disc", 
		    sub { my ($cd,$fn,$options,$dir) = @_; 
			foreach (@{ $config->{disc}[$cd]{function}{data}{boot}}){
				ref $_->[1]{isolinux} and print {$config->{LOG}} "ERROR: disc $cd: duplicate isolinux boot image, ignored\n" and return 0;
		    	}
		      	$config->{disc}[$cd]{function}{list}[$fn][1]{isolinux} =  [$dir,$options]
		    }, "Setting isolinux image"
	],
	  #2
	[ "b", "bootimg", [
	    [ "", "bootimg", 1, "<boot image name>","set boot image name",
		    sub {my ($tmp,@args) = @_;
			$tmp->[0]{bootimg} = 1;
			push @$tmp, @args
		    }, "setting boot image name"
	    ],
	    [ "d", "dir", 1, "<directory>", "duplicate the boot image in directory and put it first in the ISO",
	       sub { my ($tmp,$dir) = @_; $tmp->[0]{dir} = $dir }, ""	
	    ]
		], "<options> <boot image>", "Create a bootable iso with given image", 
		    sub { my ($cd,$fn,$options,$img) = @_;
			foreach (@{ $config->{disc}[$cd]{function}{data}{boot}}){
				ref $_->[1]{bootimg} and print {$config->{LOG}} "ERROR: disc $cd: duplicate boot image, ignored\n" and return 0;
		    	}
			$config->{disc}[$cd]{function}{list}[$fn][1]{bootimg} = [$img,$options]
		    },"Setting boot image options"
	],
	  #3
	[ "d", "dest", [
		[ "", "dest", -2, "<destination> <file 1> <file 2> .. <file n>","Set options for files copied to a given destination",
		    sub{ my ($tmp, @args) = @_;
			$tmp->[0]{dest} = $args[0];
			push @$tmp, @args
		    
		    },"Setting dest options"],
		[ "f", "first", 0 , "", "Put this files first in the ISO", sub { my ($tmp) = @_; $tmp->[0]{first} = 1; 1}, "Setting first flag for files"]
	    ], "<options> <destination> <files 1> <files 2> .. <files n>","Copy files to a special destination", 
		sub { my ($cd,$fn,$options, @files) = @_; 
		    foreach (@files){
			push @{$config->{disc}[$cd]{function}{list}[$fn][1]{files}}, [ $_, $options ]
		    }
		}, 
	    "Setting isolinux boot file"
	    ],
	  #4
	[ "f", "files", -1, "<file 1> <file 2> <file 3>","Files to copy", 
	    sub { my ($cd,$fn,@files) = @_; 
		foreach (@files){
		    push @{$config->{disc}[$cd]{function}{list}[$fn][1]{files}}, [ $_ ]
		}; 1
	    }, "files to copy"
	],
	  #5
	[ "", "first", -1, "<file 1> <file 2> <file 3>","Set first flag to put files in the beginning of the ISO", 
	    sub { my ($cd,$fn,@files) = @_; 
		foreach (@files){
		    push @{$config->{disc}[$cd]{function}{list}[$fn][1]{files}}, [ $_, { first => 1 } ]
		}
	    }, "Setting first flag"
	]
];

sub new {
    my ($class, $conf) = @_;
    $config = $conf;
    bless {
	config       => $conf,
	functions    => \%functions
    }, $class;
}


sub template {
    my ($class,$dir,$fixed,$nolive,$cdnum,$cd,$cdfile,$list,$mkisos) = @_;
    if (!$fixed){
	my $size;
	if ($nolive){
	    return $size
	}else {
	}
    }elsif ($fixed == 1){
	my $mkiso;
	if ($nolive){
	}else {
	}
    }elsif ($fixed == 2){
	my $mkiso;
	if ($nolive){
	}else {
	}
    }
}

sub cp {
    my ($class,$fct,$dir,$fixed,$nolive,$cdnum,$cd,$cdfile,$list,$mkisos) = @_;
    if (!$fixed){
	my $size;
	my $source = $fct->[1]{src};
	my $dest = $fct->[1]{dest};
	if ($nolive){
	    $size += du($source);
	    print {$config->{LOG}} "cp: copying $source => $dest (size $size)\n";
	    $mkisos->[$cdnum] .= " /$dest=$source";
	    return $size
	}else {
	    cpal($source, "$dir/$cdnum/$dest");
	    return
	}
    }
}

sub cdcom {
    my ($class,$fct,$dir,$fixed,$nolive,$cdnum,$cd,$cdfile,$list,$mkisos) = @_;
    if (!$fixed){
	my $size;
	my $source = $fct->[1]{source};
	my $dest = $config->{disc}[$cdnum]{function}{data}{dir}{$fct->[1]{dir}};
	my $destination = $fct->[1]{dest};
	my $uppath = $destination;
	$uppath =~ s,([^/]+),../,g;
	$uppath =~ s,/+,/,g;
	print {$config->{LOG}} "DEST: $destination uppath $uppath dest $dest\n";
	my $fdest = "$dir/$cdnum/$destination";
	if ($nolive){
	    my $path = "$dir/$cdnum/$dest";
	    -d $path or mkpath "$path";
	    local *A; opendir A, "$source";
	    $config->{verbose} and print {$config->{LOG}} "cdcom: $source\n";
	    foreach (readdir A){
		/^\.{1,2}$/ and next;
		if (! /^Mandrake$/){
		    $size += du("$source/$_");
		    print {$config->{LOG}} "cdcom: adding $_ (size $size)\n";
		    $mkisos->[$cdnum] .= " /$destination/$_/=$source/$_"
		}else {
		    $mkisos->[$cdnum] .= " /$dest/=$source/Mandrake/RPMS/"
		}
	    }
	    local *A; opendir A, "$source/Mandrake/RPMS";
	    foreach (readdir A){
		/^\.{1,2}$/ and next;
		my $newdest = readlink "$source/Mandrake/RPMS/$_";
		$newdest =~ s,((?:../))*(.*),$1/$destination/$2,;
		print {$config->{LOG}} "cdcom: creating symlink $dest/$_ => $newdest\n";
		my $err = symlink $newdest, "$dir/$cdnum/$dest/$_";
		!$err and print {$config->{LOG}} "ERROR cdcom: $!\n" and next;
		$mkisos->[$cdnum] .= " /$dest/=$dir/$cdnum/$dest/$_"
	    }
	    print {$config->{LOG}} "cdcom: creating symlink $uppath$dest => $fdest/RPMS\n";
	    my $err = symlink "$uppath$dest", "$fdest/RPMS";                                            
	    !$err and print {$config->{LOG}} "ERROR cdcom: $!\n";
	    $mkisos->[$cdnum] .= " /=$fdest/RPMS";
	    return $size
	}else {
	    -f $fdest or mkpath $fdest;
	    cpal($source, $fdest, "Mandrake/RPMS");
	    local *A; opendir A, "$source/Mandrake/RPMS";
	    foreach (readdir A){
		/^\.{1,2}$/ and next;
		my $newdest = readlink "$source/Mandrake/RPMS/$_";
		$newdest =~ s,((?:../)*)(.*),$1$destination/$2,;
		print {$config->{LOG}} "cdcom: creating symlink $dest/$_ => $newdest\n";
		my $err = symlink $newdest, "$dir/$cdnum/$dest/$_";
		!$err and print {$config->{LOG}} "ERROR cdcom: $!\n"
	    }
	    print {$config->{LOG}} "cdcom: creating symlink $uppath$dest => $fdest/RPMS\n";
	    my $err = symlink "$uppath$dest", "$fdest/RPMS";                                            
	    !$err and print {$config->{LOG}} "ERROR cdcom: $!\n";
	    return
	}
    }
}

sub printSize {
    my ($img,$file) = @_;
    local *A; open A, "$file";
    my $size = imageSize("$img");
    if ($size) {
	print A <<EOF
#!/usr/bin/pel

\$width = $size->[0];
\$height = $size->[1];
\@data = ()
EOF
	;
    }else{
	print "ERROR advertising: $size/n";
	return 0
    }
}

sub advertising {
    my ($class,$fct,$dir,$fixed,$nolive,$cdnum,$cd,$cdfile,$list,$mkisos) = @_;
    if (!$fixed){
	my $size;
	if ($nolive){
	    print {$config->{LOG}} "Getting advertising images size\n";
	    my $addir = "Mandrake/share/advertising" . ($fct->[1]{lang} ? ".$fct->[1]{lang}" : "");
	    my $rep = "$dir/$cdnum/$addir";
	    -d "$rep" or mkpath "$rep";
	    local *L; open L, ">$rep/list";
	    foreach (@{$fct->[1]{img}}){
		s/\.png$//;
		my ($name) = /([^\/]*)$/;
		$size += du($_);
		print L "$name\n";
		if (-f "$_.png") { $mkisos->[$cdnum] .= " $addir/$name.png=$_.png" } else { next }
		if (-f "$_.pl") { $mkisos->[$cdnum] .= " $addir/$name.pl=$_.pl"
		} else {
		    printSize("$_.png","$rep/$name.pl");
		    $mkisos->[$cdnum] .= " $addir/$name.pl=$_.pl"
	    	}
		-f "${_}_icon.png" and $mkisos->[$cdnum] .= " $addir/$name-icon.png=${_}_icon.png"
	    } 
	    close L;
	    $mkisos->[$cdnum] .= " $addir/list=$rep/list";
	    $size += du("$rep/list");
	    return $size
	}else {
	    print {$config->{LOG}} "Creating advertising images directory\n";
	    my $rep = "$dir/$cdnum/Mandrake/share/advertising" . ($fct->[1]{lang} ? ".$fct->[1]{lang}" : "");
	    -d "$rep" or mkpath "$rep";
	    local *L; open L, ">$rep/list";
	    foreach (@{$fct->[1]{img}}){
		s/\.png$//;
		my ($name) = /([^\/]*)$/;
		if (-f "$_.png") { cpal("$_.png","$rep/$name.png") } else { next }
		if (-f "$_.pl") { cpal("$_.pl","$rep/$name.pl") } else { printSize("$_.png","$rep/$name.pl") }
		-f "${_}_icon.png" and cpal("${_}_icon.png","$rep/${name}_icon.png");
		print L "$name.png\n"
	    }
	    close L;
	    return
	}
    }
}

sub dir {
    my ($class,$fct,$dir,$fixed,$nolive,$cdnum,$cd) = @_;
    if (!$fixed){
	if ($nolive){
	    return 0
	}else {
	    my $reploc = "$dir/$cdnum/$fct->[1]{reploc}";
	    print {$config->{LOG}} "dir: creating $reploc\n";
	    -d $reploc or mkpath $reploc;
	    return 0	
	}
    }
}

sub genSynthesis{
    my ($params,$hdlist,$synthesis) = @_;
    $config->{verbose} and print {$config->{LOG}} "GenSynthesis: generating $synthesis (based on $hdlist)\n";
    #    system("parsehdlist --synthesis $hdlist | gzip -9 > $synthesis");
    my $params_sense = new rpmtools(qw(sense));

    $params_sense->read_hdlists($hdlist);
    foreach my $file (keys %{$params->{provides}}) {
	$file =~ /^\// or next;
	foreach (keys %{$params->{provides}{$file} || {}}) {
	    my $pkg = $params_sense->{info}{$_} or next;
	    push @{$pkg->{provides}}, $file;
	}
    }

    open F, "| gzip -9 >$synthesis" or print "ERROR genSynthesis: could not open $synthesis\n" and return 0;
    $params_sense->write_synthesis_hdlist(\*F);
    close F or print {$config->{LOG}} "ERROR: genSynthesis: unable to build $synthesis\n";
}

sub generic {
    my ($class,$fct,$dir,$fixed,$nolive,$cdnum,$cd,$cdfile,$list,$mkisos,$discFiles) = @_;
    if ($fixed){
	my $rep = $fct->[1]{repname};
	my $list = $fct->[1]{list};
	print {$config->{LOG}} "generic: rep $rep\n";
	my $reploc = "$dir/$cdnum/$cd->{function}{data}{dir}{$rep}/";
	if ($nolive){
	    my $size;
	    my $mkiso;
	    if ($fixed == 1){
		local *A; open A, ">>$dir/$cdnum.list";
		foreach my $src (keys %{$cdfile->[$cdnum]{$rep}{$list}}){
		    print {$config->{LOG}} "generic: src $src\n";
		    foreach (@{$cdfile->[$cdnum]{$rep}{$list}{$src}}){
			if ($_->[0] == 1){
			    print A "$cd->{function}{data}{dir}{$rep}/$_->[1]=$src/$_->[1]\n";
			}
		    }
		}
		close A
	    }elsif ($fixed == 2){
		my %todo;
		foreach my $src (keys %{$cdfile->[$cdnum]{$rep}{$list}}){
		    print {$config->{LOG}} "generic: src $src\n";
		    foreach (@{$cdfile->[$cdnum]{$rep}{$list}{$src}}){
			if ($_->[0] == 1){
			    push @{$todo{add}} , "$cd->{function}{data}{dir}{$rep}/$_->[1]=$src/$_->[1]"
			}elsif ($_->[0] == 2){
			    $todo{del}{"$cd->{function}{data}{dir}{$rep}/$_->[1]=$src/$_->[1]"} = 1
			}
		    }
		}
		link "$dir/$cdnum.list", "$dir/$cdnum.list.tmp";
		unlink "$dir/$cdnum.list";
		local *A; open A, "$dir/$cdnum.list.tmp";
		local *B; open B, ">>$dir/$cdnum.list";
		while (<A>){
		    chomp;
		    if (!$todo{del}{$_}) { print B "$_\n"}
		}
		close A;
		foreach (@{$todo{add}}){
		    print B "$_\n"
		}
		close B
	    }
	    if ($fct->[1]{synthesis} || $fct->[1]{hdlist}){
		buildGenericHdlist($dir,$cdnum,$fct,$rep,$reploc,$discFiles->[$cdnum]{$rep}{$list});
		if ($fct->[1]{hdlist}){
		    $size += du ("$dir/$cdnum/$reploc/hdlist$cdnum$rep.cz");
		    $mkiso .= " Mandrake/base/hdlist$cdnum$rep.cz=$reploc/hdlist$cdnum$rep.cz";
		}
		if ($fct->[1]{synthesis}){
		    $size += du ("$dir/$cdnum/$reploc/synthesis.hdlist$cdnum$rep.cz");
		    $mkiso .= " $cd->{function}{data}{dir}{$rep}/synthesis.hdlist$cdnum$rep.cz=$reploc/synthesis.hdlist$cdnum$rep.cz";
		}
	    }
	    $mkisos->[$cdnum] .= " $mkiso";
	    return $size
	}else {
	    foreach my $src (keys %{$cdfile->[$cdnum]{$rep}{$list}}){
		print {$config->{LOG}} "generic: src $src\n";
		foreach (@{$cdfile->[$cdnum]{$rep}{$list}{$src}}){
		    if ($_->[0] == 1){
			cpal("$src/$_->[1]",$reploc)	
		    }elsif ($_->[1] == 2){
			unlink "$reploc/$_->[1]";
		    }
		}
	    }
	    if ($fct->[1]{synthesis} || $fct->[1]{hdlist}){
		buildGenericHdlist($dir,$cdnum,$fct,$rep,$reploc,$discFiles->[$cdnum]{$rep}{$list});
	    }
	    return 0
	}
    }
}

sub printVERSION {
    my ($name,$file, $tag) = @_;
    local *A; open A, ">$file";
    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
    $year += 1900;
    printf A "Mandrake Linux $name $tag %04d%02d%02d $hour:%02d\n", $year, $mon+1, $mday, $min;
}

sub buildGenericHdlist{
    my ($dir,$cdnum,$fct,$rep,$reploc,$discFilescdrep,$hdlist) = @_;
    my $hdlist;
    if ($fct->[1]{hdlist}) { 
	$hdlist = "$reploc/hdlist$cdnum$rep.cz";
    } else { 
	my $path = "$config->{tmp}/build/$config->{name}/tmp/$cdnum/";
	$hdlist = "$path/hdlist$cdnum$rep.cz";
	-d $path or mkpath "$path"
    }
    my $params = new rpmtools();
    my @rpm = map { "$discFilescdrep->{$_}/$_.rpm" } keys %{$discFilescdrep};
    print {$config->{LOG}} "buildGenericHdlists: $hdlist\n";
    $params->build_hdlist(1,9,"$config->{tmp}/.mkcd_build_hdlist",$hdlist, @rpm);
    if ($fct->[1]{synthesis}){
	$params->clean();
	$params->read_hdlists($_->[0]);
	$params->compute_depslist();
	my @unresolved = $params->get_unresolved_provides_files();
	if (@unresolved > 0) {
	    $params->clean();
	    $params->read_hdlists($_->[0]);
	    $params->keep_only_cleaned_provides_files();
	    $params->read_hdlists($_->[0]);
	    $params->compute_depslist();
	}
	-d $reploc or mkpath "$reploc";
	genSynthesis($params,$hdlist,"$reploc/synthesis.hdlist$cdnum$rep.cz")
    }
}

sub buildInstallHdlist{
    my ($dir,$cdnum,$inst,$list,$discsFiles) = @_;
    my $params = new rpmtools();
    my @hdlist;
    my @rpm;
    -d "$dir/$cdnum/Mandrake/base/" or mkpath "$dir/$cdnum/Mandrake/base/";
    local *A; open A, ">$dir/$cdnum/Mandrake/base/hdlists";
    my %rpmdone;
    my $repnum = 1;
    my @thisInstallRep;
    my %instlist;
    my @check;
    foreach my $rd (@{$inst->[1]{rpmsdir}}){
	my ($ls,$cdrep,$repname,$opts) = @$rd;
	$list->{$cdrep} or print {$config->{LOG}} "WARNING buildInstallHdlist: disc $cdrep not in list, ignoring\n" and next;
	(keys %{$discsFiles->[$cdrep]{$repname}}) or print {$config->{LOG}} "WARNING buildInstallHdlist: $cdrep/$repname is empty\n" and next;
	my $realcd = $config->{disc}[$cdrep]{name};
	my $rpmdir = $config->{disc}[$cdrep]{function}{data}{dir}{$repname};
	$rpmdir or print {$config->{LOG}} "ERROR buildInstallHdlist: disc $cdrep: $repname not defined\n" and next;
	print {$config->{LOG}} "BUILDING $cdrep -- $repname -- $rpmdir\n";
	if ($realcd){
	    print A "hdlist$repnum.cz $rpmdir disc $realcd $config->{disc}[$cdrep]{longname}\n";
	}else{
	    print A "hdlist$repnum.cz $rpmdir $config->{disc}[$cdrep]{longname}\n";
	}
	my $hdlist = "$dir/$cdnum/Mandrake/base/hdlist$repnum.cz";
	$hdlist[$repnum] = $hdlist;
	#
	# even for live sources rpm are taken, this may lead to errors in some special case, where
	# the sources change after the live is created, but this could help in combined live/nolive
	# situation
	#
	foreach my $list (keys %{$discsFiles->[$cdrep]{$repname}}){
	    next if $ls && $ls == $list;
	    $instlist{$list} = 1;
	    $thisInstallRep[$cdrep]{$repname}{$list} = $discsFiles->[$cdrep]{$repname}{$list};
	    push @{$check[$repnum]}, [$cdrep,$repname,$list];
	    my $cdsfilesrpms = $discsFiles->[$cdrep]{$repname}{$list};
	    if ($opts->{update}){
		my %localdone;
		print {$config->{LOG}} "buildInstallHdlist: update mode for $cdrep/$repname list $list\n";
		push @{$rpm[$repnum]}, map { /(.*)-[^-]+-[^-]+\.[^.]+$/; $rpmdone{$_} = 1; $rpmdone{$1} = 1;  "$cdsfilesrpms->{$_}/$_.rpm" } grep { /(.*)-[^-]+-[^-]+\.[^.]+$/; if ($localdone{$1}) { 0 } else { $localdone{$1} = 1;! $rpmdone{$_} } } keys %{$cdsfilesrpms};
	    } else {
		my %localdone;
		print {$config->{LOG}} "buildInstallHdlist: normal mode for $cdrep/$repname list $list\n";
		push @{$rpm[$repnum]}, map { /(.*)-[^-]+-[^-]+\.[^.]+$/; $rpmdone{$_} = 1; $rpmdone{$1} = 1;  "$cdsfilesrpms->{$_}/$_.rpm" } grep { /(.*)-[^-]+-[^-]+\.[^.]+$/; if ($localdone{$1}) { 0 } else { $localdone{$1} = 1; ! ($rpmdone{$_} || $rpmdone{$1})} } keys %{$cdsfilesrpms};
	    }
	}
	print {$config->{LOG}} "installation: $cdrep - $repname\n";
	$params->build_hdlist(1,9,"$config->{tmp}/.mkcd_build_hdlist",$hdlist,@{$rpm[$repnum]});
	$repnum++
    }
    foreach my $n (1 .. $repnum - 1){
	$params->read_hdlists($hdlist[$n]);
	$params->compute_depslist();
    }

    my @unresolved = $params->get_unresolved_provides_files();
    if (@unresolved > 0) {
	$params->clean();

	foreach my $n (1 .. $repnum - 1){
	    $params->read_hdlists($hdlist[$n]);
	}
	$params->keep_only_cleaned_provides_files();
	foreach my $n (1 .. $repnum - 1){
	    $params->read_hdlists($hdlist[$n]);
	    $params->compute_depslist();
	}
    }
    close A;
    my $path = "$dir/$cdnum/Mandrake/base";
    my $depslist = "$path/depslist.ordered";
    print {$config->{LOG}} "writing $depslist\n";
    open F, ">$depslist" or print {$config->{LOG}} "ERROR: unable to write depslist file $depslist\n" and return;
    $params->write_depslist(\*F);
    close F;
    my $provides = "$path/provides";
    print {$config->{LOG}} "writing $provides\n";
    open F, ">$provides" or die "unable to write provides file $provides\n";
    $params->write_provides(\*F);
    close F;
    my $file = "$path/compss";
    print {$config->{LOG}} "writing $file\n";
    open F, ">$file" or die "unable to write compss file $file";
    $params->write_compss(\*F);
    close F;

    checkDiscs(\@hdlist,$depslist,\@thisInstallRep,\@check,$config->{LOG}) or die "depslist.ordered, hdlists and RPMS mismatch\n";
    # Add sources
    foreach my $cd (keys %{$list}){
	$list->{$cd} > 1 or next;
	foreach (@{$config->{disc}[$cd]{fastgeneric}}){
	    my $l = $_->[1]{list};
	    if ($instlist{$l} && $_->[1]{source}) {
		$thisInstallRep[$cd]{$_->[1]{repname}}{$l} = $discsFiles->[$cd]{$_->[1]{repname}}{$l};
	    }
	}
    }
    my $pfile = "$dir/$cdnum/pkg-$config->{name}" . ($inst->[1]{tag} ? "-$inst->[1]{tag}" : "") . ".idx";
    printDiscsFile($config,\@thisInstallRep,$pfile);
    $params->read_depslist($depslist);
    $params->read_provides_files($provides);
    foreach my $n (1 .. $repnum - 1){
	$params->build_hdlist(1,9,"$config->{tmp}/.mkcd_build_hdlist","$path/hdlist$n.cz",@{$rpm[$n]});
	if ($inst->[1]{synthesis}){
	    genSynthesis($params,"$path/hdlist$n.cz","$path/synthesis.hdlist$n.cz")
	}
    }
    return ($repnum,$path,$pfile);
}

sub isolinux {
    my ($class,$fct,$dir,$fixed,$nolive,$cdnum,$cd,$cdfile,$list,$mkisos,$discsFiles) = @_;
    my $isolinux = $fct->[1]{isolinux};
    my $bootimg = $fct->[1]{bootimg} ? $fct->[1]{bootimg} : "isolinux.bin";
    if (!$fixed){
	my $size;
	if ($nolive){
	    my $mkiso;
	    $mkiso .= qq{ -b isolinux/$bootimg -c isolinux/boot.cat isolinux/=$isolinux/$bootimg -no-emul-boot -boot-load-size 4 -boot-info-table $mkisos->[$cdnum]};
	    $size += du($isolinux);
	    local *A; opendir A, $isolinux;
	    foreach (readdir A){
		/~$/ and next;
		$size += du ("$isolinux/$_");
		if (-d "$isolinux/$_"){ $mkiso .= " /$_/=$isolinux/$_"; next }
		$mkiso .= " /=$isolinux/$_"
	    }
	    $mkisos->[$cdnum] .= " $mkiso";
	}else{
	    my $isolinuxdest = "$dir/isolinux/$cdnum/isolinux/";
	    rmtree $isolinuxdest;
	    -d $isolinuxdest or mkpath $isolinuxdest;
	    cpal("$isolinux/", $isolinuxdest);
	    $size = du($isolinuxdest);
	}
	return $size
    }else{
	if (!$nolive){
	    if ($bootimg){
		$mkisos->[$cdnum] = qq| -b isolinux/$bootimg -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table "$config->{topdir}/build/$config->{name}/isolinux/$cdnum" "$config->{topdir}/build/$config->{name}/$cdnum"|;
	    }
	}
    }

}

sub boot {
    my ($class,$fct,$dir,$fixed,$nolive,$cdnum,$cd,$cdfile,$list,$mkisos,$discsFiles) = @_;
    my $isolinux = $fct->[1]{isolinux};
    my $bootimg = $fct->[1]{bootimg};
    print {$config->{LOG}} "Boot: $fixed nolive $nolive\n";
    if (!$fixed){
	my $size;
	if ($nolive){
	    my $mkiso;
	    my $img;
	    my $dir;
	    my $path;
	    if ($isolinux){
		my $dir = $isolinux->[0];
		my $img = $bootimg ? $bootimg->[0] : "isolinux/isolinux.bin"; 
		$mkiso = qq{ -b $img -c $dir/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table};
	    }elsif ($bootimg){
		$img = $bootimg->[0];
		$dir = $bootimg->[1]{dir};
		$img =~ s/(.*)\/([^\/]+)$/$2/;
		$dir or ($dir) = $1;
		$mkiso = qq{ -b $dir/$img };
		$mkiso .= qq{ -c ${dir}/boot.cat }
	    }
	    foreach (@{$fct->[1]{files}}){
		my ($files,$opt) = @$_;
		my $dest = $opt->{dest};
		$size += du ($files);
		my ($dirname) = $files =~ /([^\/]*)$/;
		print {$config->{LOG}} "boot: files $files dest $dest dirname $dirname\n";
		if ($img) { 
		    my $bimg = $bootimg->[0];
		    $bimg =~ s/^$dirname//;
		    print {$config->{LOG}} "boot: boot image $files/$bimg in $dir/$img (",(stat "$files/$bimg")[7],")\n";
		    if (-f "$files/$bimg") { 
			if ((stat "$files/$bimg")[7] > 3000000){ 
			    $mkiso .= qq{ -no-emul-boot}
			}
		    	$mkiso .= qq{ $dir/$img=$files/$bimg}
		    }
		}
		if (-d "$files"){ $mkiso .= " $dest/$dirname/=$files"; next }
		$mkiso .= " $dest/=$files";
		
	    }
	    # it is = and not .= because mkcdisos->[$cdnum] has been added already at the beginning
	    $mkisos->[$cdnum] = "$mkiso $mkisos->[$cdnum]";
	}else{
	    print {$config->{LOG}} "FILES $fct->[1]{files}\n";
	    foreach (@{$fct->[1]{files}}){
		my ($files,$opt) = @$_;
		print {$config->{LOG}} "boot: file $files\n";
		my $dest = "$config->{topdir}/build/$config->{name}/" . ($opt->{first} ? "first/" : "") . "$cdnum/";
		-d $dest or mkpath $dest;
		my $odest = $opt->{dest};
		if ($odest){
		    $dest .= "/$odest";
		}else{
		    my ($dirname) = $files =~ /([^\/]*)$/;
		    $dest .= "/$dirname"
		}
		cpal($files,$dest,0,1);
	    }
	    $size = du("$dir/first/$cdnum/");
	}
	return $size
    }else{
	if (!$nolive){
	    if ($isolinux){
		my $dir = $isolinux->[0];
		my $img = $bootimg ? $bootimg->[0] : "isolinux/isolinux.bin"; 
		$mkisos->[$cdnum] .= qq| -b $img -c $dir/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table "$config->{topdir}/build/$config->{name}/first/$cdnum" "$config->{topdir}/build/$config->{name}/$cdnum"|;
	    }elsif ($bootimg){
		my $img = $bootimg->[0];
		my $sdir = $bootimg->[1]{dir};
		$img =~ s/(.*\/)([^\/]+)$/$2/;
		$sdir or ($sdir) = $1;
		print {$config->{LOG}} "boot: boot image $sdir/$img\n";
		$mkisos->[$cdnum] .= qq{-b $sdir/$img};
		if ((stat "$img")[7] > 3000000){ 
		    $mkisos->[$cdnum] .= qq{ -no-emul-boot}
		}
		my $cdimages = "$dir/$cdnum/";
		my $Bootdir = "$dir/first/$cdnum/$sdir/";
		if (! -f "$Bootdir/$img") {
		    if (! -d $Bootdir ) { mkpath $Bootdir or die "cannot create $Bootdir\n" }
		    my $err = link "$cdimages/$bootimg->[0]","$Bootdir/$img";
		    if (!$err) { print {$config->{LOG}} "Linking failed $cdimages/$bootimg->[0]: $!\n"};
		}
		$mkisos->[$cdnum] .= qq{ -c $sdir/boot.cat "$dir/first/$cdnum" "$dir/$cdnum"};
		print {$config->{LOG}} "BOOT $mkisos->[$cdnum]\n";
	    }
	}
    }
}

sub installation {
    my ($class,$inst,$dir,$fixed,$nolive,$cdnum,$cd,$cdfile,$list,$mkisos,$discsFiles) = @_;
    my $install = $inst->[1]{install};
    if (!$fixed){
	$install or return;
	my $size;
	if ($nolive){
	    my $mkiso;

	    local *A; opendir A, "$install";
	    foreach (readdir A){
		/~$/ and next;
		/^(\.{1,2}|Mandrake|LICENSE-APPS.txt|isolinux|images|VERSION)$/ and next;
		$size += du ("$install/$_");
		if (-d "$install/$_"){ $mkiso .= " /$_/=$install/$_"; next }
		$mkiso .= " /=$install/$_"
	    }

	    local *A; opendir A, "$install/Mandrake";
	    foreach (readdir A){
		print {$config->{LOG}} "Mandrake -- $_\n";
		/~$/ and next;
		/(^(\.{1,2}|base)$|RPMS|share)/ and next;
		$size += du ("$install/Mandrake/$_");
		if (-d "$install/Mandrake/$_") { $mkiso .= " Mandrake/$_/=$install/Mandrake/$_"; next }
		$mkiso .= " Mandrake/=$install/Mandrake/$_";
	    }

	    local *A; opendir A, "$install/Mandrake/base";
	    foreach (readdir A){
		/~$/ and next; 
		/(^(\.{1,2}|compss|provides|depslist.ordered|synthesis|compssUsers|rpmsrate|rpmslist|filelist|Serial|hashfile)|hdlist|cooker)/ and next;
		$size += du ("$install/Mandrake/base/$_");
		if (-d "$install/Mandrake/base/$_"){ $mkiso .= " Mandrake/base/$_/=$install/Mandrake/base/$_"; next}
		$mkiso .= " Mandrake/base/=$install/Mandrake/base/$_";
	    }
	    my $compss= $cd->{function}{data}{installation}[1]{compssUsers} || "$install/Mandrake/base/compssUsers";
	    if (-f $compss){ 
		$size += du ($compss);
	    	$mkiso .= " Mandrake/base/compssUsers=$compss"
	    } else { print {$config->{LOG}} "ERROR installation: $compss file does not exist" }
	    $mkisos->[$cdnum] .= " $mkiso";
	}else {
	    cpal("$install/","$dir/$cdnum","($install/+(Mandrake/+base/+(hdlist|depslist|synthesis|rpmslist|filelist|Serial|hashfile|compssUsers|rpmsrate)|Mandrake/+RPMS|Mandrake/+share|isolinux|images|LICENSE-APPS.txt))");
	    my $compss = $cd->{function}{data}{installation}[1]{compssUsers} || "$install/Mandrake/base/compssUsers";
	    if (-f $compss){
		print {$config->{LOG}} "installation: compssUsers $compss\n";
		cpal($compss,"$dir/$cdnum/Mandrake/base/compssUsers");
	    }else { print {$config->{LOG}} "ERROR installation: $compss file does not exist" }
	}
	return $size
    }elsif ($fixed == 1){
	if ($nolive){
	    my $size;
	    my $mkiso;
	    my $rpmsrate = $cd->{function}{data}{installation}[1]{rpmsrate} || "$install/Mandrake/base/rpmsrate";
	    if (-f $rpmsrate){
		$size += du ($rpmsrate);
		$mkiso .= " Mandrake/base/rpmsrate=$rpmsrate"
	    } else { print {$config->{LOG}} "ERROR installation: $rpmsrate file does not exist" }
	    my ($repnum,$path,$pfile) = buildInstallHdlist($dir, $cdnum,$inst,$list,$discsFiles);
	    if ($install){
		$mkiso = " Mandrake/base/=$path/compss Mandrake/base/=$path/depslist.ordered Mandrake/base/=$path/provides Mandrake/base/=$path/hdlists /=$pfile";
		$size += du("$path/compss");
		$size += du("$path/depslist.ordered");
		$size += du("$path/provides");
		$size += du($pfile);
		my $version = "$dir/$cdnum/VERSION";
		printVERSION($config->{name},$version,$inst->[1]{tag});
		$mkiso .= " VERSION=$version";
		$size += du($version);	
		$size += du("$path/hdlists");
	    }	
	    foreach my $n (1 .. $repnum - 1){
		$mkiso .= " Mandrake/base/=$path/hdlist$n.cz";
		$size += du("Mandrake/base/=$path/hdlist$n.cz");
		if ($inst->[1]{synthesis}){
		    $mkiso .= " Mandrake/base/=$path/synthesis.hdlist$n.cz";
		    $size += du("Mandrake/base/=$path/synthesys.hdlist$n.cz")
		}
	    }
	    $mkisos->[$cdnum] .= " $mkiso";
	    return $size;
	} else {
	    if (!$install){ mkpath "$dir/$cdnum/Mandrake/base/" }
	    my $rpmsrate = $cd->{function}{data}{installation}[1]{rpmsrate} || "$install/Mandrake/base/rpmsrate";
	    if (-f $rpmsrate){
		print {$config->{LOG}} "installation: rpmsrate: $rpmsrate\n";
		cpal($rpmsrate,"$dir/$cdnum/Mandrake/base/rpmsrate");
	    }else { print {$config->{LOG}} "ERROR installation: $rpmsrate file does not exist" }
	    unlink "$dir/$cdnum/Mandrake/base/hdlists";
#
# removed to always use buildInstallHDlist, more generic.
#
#	    if (!$inst->[1]{fixed}){
#		my @check;
#		local *A; open A, ">$dir/$cdnum/Mandrake/base/hdlists";
#		my $cmddep = qq{gendistrib --noclean --distrib "$dir/$cdnum" };
#		my $repnum = 1;
#		my @synth;
#		foreach my $rd (@{$inst->[1]{rpmsdir}}){
#		    my ($cdrep,$repname) = @$rd;
#		    (keys %{$discsFiles->[$cdrep]{$repname}}) or print {$config->{LOG}} "WARNING installation: $cdrep/$repname is empty\n" and next;
#		    $list->{$cdrep} or print {$config->{LOG}} "WARNING installation: disc $cdrep not in list, ignoring\n" and next;
#		    my $rpmdir = $config->{disc}[$cdrep]{function}{data}{dir}{$repname};
#		    $rpmdir or print {$config->{LOG}} "ERROR: disc $cdrep: $repname not defined\n" and next;
#		    print {$config->{LOG}} "BUILDING $cdrep -- $repname -- $rpmdir\n";
#		    my $realcd = $config->{disc}[$cdrep]{name};
#		    if ($realcd) { 
#			print A "hdlist$repnum.cz $rpmdir disc $realcd $config->{disc}[$cdrep]{longname}\n";
#		    }else{
#			print A "hdlist$repnum.cz $rpmdir $config->{disc}[$cdrep]{longname}\n";
#		    }
#		    push @synth, "hdlist$repnum.cz";
#		    if ($cdnum != $cdrep){ 
#			$cmddep .= qq{ "$dir/$cdrep/"}
#		    }
#		    $check[$repnum] = qq{$dir/$cdrep/};
#		    $repnum++
#		}
#		close A;
#		print {$config->{LOG}} "Building hdlists $cmddep\n";
#		system($cmddep);
#		system($cmddep);
#		if ($inst->[1]{synthesis}){
#		    foreach my $s (@synth){
#			genSynthesis("$dir/$cdnum/Mandrake/base/$s","$dir/$cdnum/Mandrake/base/synthesis.$s")
#		    }
#		}
#	    }else{
#		buildInstallHdlist($dir, $cdnum,$inst,$list,$discsFiles);
#	    }
	    buildInstallHdlist($dir, $cdnum,$inst,$list,$discsFiles);
	    if ($install){
		my $version = "$dir/$cdnum/VERSION";
		unlink $version;
		printVERSION($config->{name},$version,$inst->[1]{tag});
	    }
	}
    }
}


1

# 
# Changeloh
#
# 2002 03 15
#
# new sources handling in installation
