/**
 * Module:		auto_part_create.ycp
 *
 * Authors:		Andreas Schwab (schwab@suse.de)
 *			Klaus Kämpf (kkaempf@suse.de)
 *
 * Purpose:		This module creates the neccessary partitions
 *			in the targetMap
 *
 * $Id: auto_part_create.ycp 20155 2004-11-03 16:35:04Z fehr $
 *
 * used globals
 *
 * defined functions
 */
{
    textdomain "storage";

    import "Storage";
    import "Partitions";


    // --------------------------------------------------------------
    // Add new partition entries for the boot, swap and root parititions.
    // Each new entry is marked with "create":true. They key "mount"
    // contains the mount point or "swap" for the swap partition.

define list<map<string, any> > create_partitions( map disk, list<map<string, any> > partitions,
			       list<integer> selected_region )
    ``{
    y2milestone ("disk:%1 partitions %2 selected_region %3)", disk, partitions,
                 selected_region);
    integer bpu = disk["cyl_size"]:1;

    partitions = filter( map<string, any> pentry, partitions, 
                         ``(pentry["type"]:`unknown != `free));
    partitions = renumber_logical_partitions (partitions);
    symbol ptype = `primary;

    boolean empty_disk = (partitions == []);

    map<string, any> absd_partition = $["create":true, "format":true,
			   "type": `primary, 
			   "fsid":Partitions::fsid_empty,
			   "nr":3,
			   "region":full_region ];

    if( selected_region != full_region && disk["max_primary"]:4 == 4)
	{
	ptype = `logical;
	}

    // If any partitions are left to be preserved, create the new
    // partitions in an extended partition.
    list used_primaries = 
	maplist( map<string, any> entry, 
	    filter( map<string, any> pentry, partitions,
		    ``(!pentry["delete"]:false &&
		       pentry["nr"]:0<disk["max_primary"]:4)),
	    ``(entry["nr"]:0) );
    if( disk["label"]:""=="bsd" || disk["label"]:""=="sun" )
	{
	used_primaries = add( used_primaries, 3 );
	}

    // Add the extended partition if necessary
    list use_pnrs = [];
    list<integer> poss_primary = [ 1, 2, 3, 4 ];
    integer i = 5;
    while( i<disk["max_primary"]:4 )
	{
	poss_primary = add( poss_primary, i );
	i = i+1;
	}
    poss_primary = filter( integer n, poss_primary, ``(!contains(used_primaries,n)));
    poss_primary = sort(poss_primary);
    y2milestone( "used_primaries %1 poss_primary %2", used_primaries, 
		 poss_primary );

    if (ptype == `logical)
	{
	if (!contains_extended (partitions))
	    {
	    // Find unused primary number
	    list used_primaries =
		maplist( map<string, any> pentry, filter( map<string, any> p, partitions,
					     ``(!p["delete"]:false)),
			 ``(pentry["nr"]:0));

	    integer unused_primary_pnr = poss_primary[0]:0;

	    // create new extended partition
	    // if it starts above cyl 1024, create it as fsid_extended_win
	    integer ext_fsid = Partitions::fsid_extended_win;
	    partitions = add (partitions,
			    $[ "create":true,
			       "type":`extended, "fsid":ext_fsid,
			       "fstype" : Partitions::FsIdToString( ext_fsid ),
			       "nr":unused_primary_pnr,
			       "region":selected_region ]);

	    use_pnrs = [ 5, 6, 7 ];
	    }
	else
	    {
	    // Find the last used logical partition number.
	    // We know that these partitions are numbered contiguously
	    integer last_pnr = 4;
	    foreach (map<string, any> pentry, partitions, 
		``{
		if( !pentry["delete"]:false &&
		    pentry["type"]:`unknown == `logical &&
		    pentry["nr"]:0 > last_pnr )
		    last_pnr = pentry["nr"]:0;
		});
	    use_pnrs = [ last_pnr+1, last_pnr+2, last_pnr+3 ];
	    }
	} // ptyle == `logical
    else
	{
	use_pnrs = poss_primary;
	}

    y2milestone( "use_pnrs %1", use_pnrs );

    integer boot_add = 1;

    list<integer> boot_region = [ selected_region[0]:0, 
                         size_to_units( size_of_boot, bpu ) ];
    if( !need_boot_partititon(selected_region) )
	{
	boot_region[1] = 0;
	boot_add = 0;
	}
    list<integer> swap_region = [ end_of_region( boot_region ), 
                         size_to_units( 1024*1024*Partitions::SwapSizeMb(size_of_region(selected_region,bpu)/1024/1024), bpu ) ];
    list<integer> root_region = [ end_of_region(swap_region),
			 end_of_region(selected_region) - 
			     end_of_region(swap_region) ];

    if( boot_add>0 )
	{
	// add /boot for all partitions
	map<string, any> boot_part = $[ "create":true, "format":true,
			   "type": ptype, "fsid":Partitions::FsidBoot(),
			   "fstype" : Partitions::FsIdToString( Partitions::FsidBoot() ),
			   "nr":use_pnrs[0]:0,
			   "region":boot_region,
			   "mount":Partitions::BootMount(),
			   "used_fs":Partitions::DefaultBootFs()];
	boot_part["fstopt"] = FileSystems::DefaultFstabOptions( boot_part );
	partitions = add (partitions, boot_part);
	}

    partitions = add (partitions,
		    $[ "create":true, "format":true,
		       "type": ptype, "fsid":Partitions::fsid_swap,
		       "fstype" : Partitions::FsIdToString( Partitions::fsid_swap ),
		       "nr":use_pnrs[0+boot_add]:0,
		       "region":swap_region,
		       "mount":"swap" ]);

    map<string, any> p = $[ "create":true, "format":true,
	       "type": ptype, "fsid":Partitions::fsid_native,
	       "fstype" : Partitions::FsIdToString( Partitions::fsid_native ),
	       "used_fs" : Partitions::default_fs,
	       "nr":use_pnrs[1+boot_add]:0,
	       "region":root_region,
	       "mount":"/" ];
    p["fstopt"] = FileSystems::DefaultFstabOptions( p );
    partitions = add (partitions, p );

    // create #3 on bsd if needed

    if( (disk["label"]:""=="bsd" || disk["label"]:""=="sun") && empty_disk)
	{
	partitions = add( partitions, absd_partition );
	}
    
    // Add flag whether using the entire disk
    Storage::SetWholeDisk( selected_region == full_region );
    partitions = maplist( map<string, any> part, partitions,
	``{
	part["device"] = Storage::GetDeviceName( target_is, part["nr"]:0 );
	return( part );
	});
    y2milestone( "ret part %1", partitions );

    return( partitions );
    }; // create_partitions

}
