/*************************************************************
 *
 *     YaST2      SuSE Labs                        -o)
 *     --------------------                        /\\
 *                                                _\_v
 *           www.suse.de / www.suse.com
 * ----------------------------------------------------------
 *
 * Author:        Johannes Buchhold <jbuch@suse.de>
 *
 * Description:   lib
 *
 *
 *************************************************************
 *
 $Id: custom_part_lib.ycp 22007 2005-02-28 15:10:54Z fehr $
 *
*/

{
  textdomain "storage";
  import "Mode";
  import "Arch";
  import "Installation";
  import "Partitions";
  import "FileSystems";

  #include "partitioning/partition_defines.ycp";

  /**
   * Find and read fstab by installation. Scan existing partitions.
   * @parm targetMap all targets
   * @parm search_point mount point where partitions can be mounted
   * @return list list with fstab data found
   */
define list<list> findExistingFstab( map<string,map> targetMap, string search_point )
    ``{
    /////////////////////////////////////////////////////////////////
    // foreach partition on each target
    list<list>    fstab = [];
    list    skip_fs = [ `unknown, `swap, `fat32, `fat16, `ntfs ];

    if( Stage::initial () )
	Storage::SetMdOn( true );

    foreach( string dev, map disk, targetMap, 
	``{
	foreach( map partition, filter( map p, disk["partitions"]:[], 
	                             ``(!contains( skip_fs, p["detected_fs"]:`unknown) )),
	    ``{
	    symbol fs = partition["detected_fs"]:`ext2;
	    /////////////////////////////////////////////////////
	    // try to mount

	    FileSystems::LoadModule( fs );
	    string cmd = sformat( "/bin/mount %1 %2 %3 2>&1", 
	                          FileSystems::GetMountOption( fs ),
				  partition["device"]:"", search_point );
	    y2milestone( "cmd %1", cmd );
	    map bc = (map)SCR::Execute(.target.bash_output, cmd );
	    y2milestone( "%1", bc );
	    boolean mount_success = bc["exit"]:1 == 0;

	    if( mount_success &&
		SCR::Read(.target.size, search_point+"/etc/fstab") > 0 )
		{
		if( SCR::Read(.target.size, "/etc/fstab") > 0 )
		    SCR::Execute(.target.unlink, "/etc/fstab" );
		cmd = "/bin/cp " + Installation::scr_destdir + "/etc/fstab /etc";
		y2milestone( "cmd %1", cmd );
		if( SCR::Execute(.target.bash, cmd ) == 0)
		    {
		    SCR::UnmountAgent(.etc.fstab);
		    list tmp = (list)SCR::Read( .etc.fstab );
		    y2milestone( "fstab %1", tmp );
		    if( size(tmp)>0 )
			{
			fstab = add( fstab, tmp );
			}
		    }
		}

	    /////////////////////////////////////////////////////
	    // unmount

	    if( mount_success )
		SCR::Execute(.target.bash, "/bin/umount " + search_point );
	    });
	});
    if( Stage::initial () )
	Storage::SetMdOn( false );
    y2milestone( "count_fstab_found %1", size(fstab) );
    y2milestone( "fstab %1", fstab );
    return fstab;
    };


/**
  * Scan and Read and return fstab.
  * @parm targetMap all targets
  * @parm file_systems filesystem map
  * @return list list with fstab
  */
define list<list> scanAndReadExistingFstab( map<string,map> targetMap )
    ``{
    string search_point = "/mnt";

    /////////////////////////////////////////////////////////////////
    // make search dir

    if( SCR::Execute(.target.bash, "/usr/bin/test -d " + search_point ) != 0)
	{
	SCR::Execute(.target.mkdir, search_point );
	}

    list<list> fstab = findExistingFstab( targetMap, search_point );

    return fstab;
    };




    /**
     * Only for check in installed system.
     * Please do not use this define by installation.
     * @parm part1 partition 1
     * @parm part2 partition 2
     * @return boolean
     */
define boolean arePartitionsEqual( map part1, map part2 )``{

	if( part1["create"]:false )
	    return true;

	y2debug("part1 : %1", part1);
	y2debug("part2 : %1", part2);

	// -> not all keys
	if( part1["nr"]:0 	       == part2["nr"]:0 &&
	    part1["fsid"]:0 	       == part2["fsid"]:0 &&
	    part1["region"]:[] 	       == part2["region"]:[] &&
	    part1["create"]:false      == part2["create"]:false &&
	    part1["format"]:false      == part2["format"]:false &&
	    part1["used_fs"]:`unknown  == part2["used_fs"]:`unknown &&
	    part1["loop_fs"]:false     == part2["loop_fs"]:false &&
	    part1["crypt"]:""          == part2["crypt"]:"" &&
	    part1["fstab_mnt"]:`device == part2["fstab_mnt"]:`device &&
	    part1["label"]:""          == part2["label"]:"" &&
	    part1["mount"]:""          == part2["mount"]:""
	  )
	{
	    return true;
	}
	return false;
    }

  /**
   * Check lvm mount points
   * @param mount mount point
   * @return boolean
   */
define boolean check_lvm_mount_points( string mount ) ``{

       list not_allowed_lvm_mount_points  = [ Partitions::BootMount() ];
       y2milestone( " check lvm mount");
       if( contains(  not_allowed_lvm_mount_points , mount ))
       {
           // error popup text
	   Popup::Error(sformat(_("You cannot use the mount point \"%1\" for LVM.\n"), Partitions::BootMount()));

	    return false;
	}
	return true;
   };


  /**
   * Check raid mount points
   * @param mount mount point
   * @return boolean
   **/
define boolean check_raid_mount_points( string mount )
    ``{
	list not_allowed_raid_mount_points  = [ ];
	if( Arch::ppc () || Arch::s390 () || Arch::ia64 () || Arch::sparc () )
	    {
	    not_allowed_raid_mount_points = 
		add( not_allowed_raid_mount_points, Partitions::BootMount() );
	    }
	y2milestone( " check raid mount");
	if( contains( not_allowed_raid_mount_points, mount ))
	{
           // error popup text
	    Popup::Error(sformat(_("You cannot use the mount point %1 for RAID."), Partitions::BootMount()));

	    return false;
	}
	return true;
    };



  /**
   * Check if the noauto option is permitted for this mount point.
   * @param mount mount point
   * @return boolean
   **/
define boolean check_noauto_mount( string mount )
    ``{
    boolean ret = true;
    if( FileSystems::IsSystemMp( mount, true ) )
	{
        // error popup text
	ret = Popup::YesNo(
_("You have selected not to mount automatically at start-up a file system  
that may contain files that the system needs to work properly.

This might lead to trouble.
 
Really do this?
"));
	y2milestone( "ret %1", ret );
	}
    return ret;
    };

  /**
   * Check crypted mount points and return true if the mount point is ok.
   * @param mount mount point
   * @param crypt_fs boolean
   * @return boolean
   **/
define boolean check_crypt_fs_mount_points( string mount, boolean crypt_fs )
    ``{
    if( crypt_fs && 
        (FileSystems::IsCryptMp( mount, false ) || mount=="swap" ))
	{
        // error popup text
	Popup::Error(
_("You have assigned a loopbacked file system to a partition 
with one of the following mount points: \"/\", \"/usr\", \"/boot\", 
\"swap\".  This is not possible. Change the mount point or use a 
non-loopbacked file system.
"));
	    return false;
	}
    return true;
    };


    /**
     * Check all label and return true if the label is unique.
     * @param targetMap the TargetMap
     * @param part      partition to check
     * @return boolean
     **/
define boolean check_unique_label( map<string,map> targetMap, map part )
    ``{
    boolean unique = true;

    // check if the label is already in use
    foreach( string disk, map diskinfo, targetMap, ``{
	foreach( map p, diskinfo["partitions"]:[], ``{
	    if ( !p["delete"]:false && p["device"]:"" != part["device"]:"" )
		{
		// all valid partitions
		if ( p["label"]:"" == part["label"]:"" ) unique = false;
		}
	    });
	});
    return( unique );
    };

define boolean CheckFstabOptions( map part )
    ``{
    boolean ret = true;
    if( part["mount"]:"" == "/" && part["used_fs"]:`none == `ext3 &&
	find(part["fstopt"]:"","data=")>=0 )
	{
        // error popup text
	Popup::Error(_("Data journaling mode for ext3 on the root file system
must not be specified.
"));
	ret = false;
	}
    if( part["noauto"]:false )
	{
	ret = check_noauto_mount( part["mount"]:"" );
	}
    y2milestone( "ret %1 part %2", ret, part );
    return( ret );
    }

    /**
     * Check all mount points and return true if the mount point is ok.
     * @param targetMap the TargetMap
     * @param mount mount point
     * @return boolean
     **/
define boolean check_mount_point( map<string,map> targetMap, string dev, map part )
    ``{
    string mount = part["mount"]:"";
    symbol used_fs = part["used_fs"]:`unknown;

    boolean allowed = true;
    list not_allowed_system_mount_points  = 
	[ "/proc", "/dev", "/mnt", "/var/adm/mnt", "/lost+found", "/lib", 
	  "/bin", "/etc", "/sbin" ];

    if ( mount != ""  && mount != "swap"  )
	{
	// check if the mount point is already in use
	foreach( string disk, map diskinfo, targetMap, ``{
	    foreach( map part, diskinfo["partitions"]:[], ``{
		if ( !part["delete"]:false &&
		     Storage::GetDeviceName( disk, part["nr"]:(any)0 ) != dev )
		    {
		    // all valid partitions
		    if ( part["mount"]:"" == mount )   allowed = false;
		    }
		});
	    });

	if( allowed == false )
	    {
	    // error popup text
	    Popup::Error(_("This mount point is already in use. Select a different one."));
	    }
	// check if a dos filesystem is used for system purposes
	else if( (used_fs == `fat16 || used_fs == `fat32) &&
		 (mount == "/" || mount == "/usr" || mount == "/opt" ||
		  mount == "/var" || mount == "/home"))
	    {
	    allowed = false;
	    // error popup text
	    Popup::Error(_("FAT filesystem used for system mount point (/, /usr, /opt, /var, /home).\nThis is not possible."));
	    }
	// check if the mount countains chars making trouble
	else if( findfirstof( mount, " `'´!\"%#" ) != nil )
	    {
	    allowed = false;
	    // error popup text
	    Popup::Error(_("Invalid character in mount point. Dont use \"`'!\"%#\" in a mount point."));
	    }

	// check if the mount point is a system mount point
	else if ( contains( not_allowed_system_mount_points , mount) )
	    {
	    allowed = false;
	    // error popup text
	    Popup::Error(_("You cannot use any of the following mount points:
/proc, /dev, /lib, /bin, /etc, /sbin, /mnt, /var/adm/mnt, /lost+found
"));
	    }
	else if ( substring( mount, 0, 1 ) != "/"  )
	    {
	    allowed = false;
	    // error popup text
	    Popup::Error(_("Your mount point must start with a \"/\" "));
	    }
	}
    else if( !part["format"]:false && part["detected_fs"]:`none != `swap )
	{
	// error popup text
string message = _("
WARNING:

You chose a swap partition but did not direct YaST2 to format it.
This swap partition will probably not be usable.

Change the setup?
");

	allowed = !Popup::YesNo(message);
	}
    else
	{
	allowed = true;
	}
    if( allowed )
	{
	allowed = CheckFstabOptions( part );
	}
    return( allowed );
    };

define boolean check_ok_fssize( integer siz, map part )
    ``{
    boolean ret = true;
    if( part["format"]:false )
	{
	y2milestone( "check_ok_fssize size:%1", siz );
	if( part["used_fs"]:`ext2==`reiser && siz<60000000 )
	    {
	    // popup text
	    Popup::Warning(_("Your partition is too small to use ReiserFS.
ReiserFS is a journaling file system that requires
at least 30 MB space for the journal alone.
Use ReiserFS on larger partitions.
"));
	    ret = false;
	    }
	if( part["used_fs"]:`ext2==`jfs && siz<32000000 )
	    {
	    Popup::Warning(_("Your partition is too small to use JFS.
JFS is a journaling file system that requires
at least 16 MB space for the journal alone.
Use JFS on larger partitions.
"));
	    ret = false;
	    }
	}
    return( ret );
    };

    /**
     * Do all checks concerning mount points, uuid, volume labels and
     * fstab options
     * @param targetMap the TargetMap
     * @param mount mount point
     * @return map
     **/
define map CheckOkMount( string dev, map old, map<string,any> new )
    ``{
    y2milestone( "old:%1 new:%2", old, new );
    map ret = $[];
    ret["ok"] = true;
    new["mount"] = UI::QueryWidget(`id(`mount_point), `Value);
    new["mount"] = deletechars( new["mount"]:"", " \t" );
    if( ret["ok"]:false && size(new["mount"]:"")>0 )
	{
	boolean crypt_fs = false;
	if( !check_mount_point( Storage::GetTargetMap(), dev, new ))
	    {
	    ret["ok"] = false;
	    ret["field"] = `mount_point;
	    }
	if( UI::WidgetExists( `id(`crypt_fs) ))
	    {
	    crypt_fs = (boolean)UI::QueryWidget(`id(`crypt_fs), `Value );
	    }
	if( !check_crypt_fs_mount_points(new["mount"]:"", crypt_fs ))
	    {
	    ret["ok"] = false;
	    ret["field"] = `mount_point;
	    }
	if( new["noauto"]:false && !check_noauto_mount( new["mount"]:"" ))
	    {
	    ret["ok"] = false;
	    ret["field"] = `mount_point;
	    }
	if( new["type"]:`primary == `sw_raid )
	    {
	    if( !check_raid_mount_points(new["mount"]:""))
		{
		ret["ok"] = false;
		ret["field"] = `mount_point;
		}
	    }
	else if( new["type"]:`primary == `lvm )
	    {
	    if( !check_lvm_mount_points(new["mount"]:""))
		{
		ret["ok"] = false;
		ret["field"] = `mount_point;
		}
	    }
	}
    if( !new["format"]:false && !new["create"]:false &&
        old["mount"]:"" != new["mount"]:"" && ret["ok"]:false )
	{
	if( !haskey( new, "ori_mount" ) )
	    new["ori_mount"] = old["mount"]:"";
	}
    if( !new["format"]:false )
	{
	new = filter(string key, any value, new, ``( key != "fs_options"));
	}
    y2milestone( "ret:%1 new:%2", ret, new );
    ret["map"] = new;
    return( ret );
    };

/**
  * Do all checks concerning handling of crypt fs
  * @param new partition map
  * @return map
  **/
define map CheckCryptOk( map new )
    ``{
    map ret = $[];
    ret["ok"] = true;
    y2milestone( "CheckCryptOk new:%1", new );
    boolean crypt_fs = false;
    if( UI::WidgetExists( `id(`crypt_fs) ))
	{
	crypt_fs = (boolean)UI::QueryWidget(`id(`crypt_fs), `Value );
	}
    new["loop_fs"] = crypt_fs || new["type"]:`none==`loop;
    if( crypt_fs )
	{
	new["crypt"] = new["format"]:false?"twofish256":"twofish";
	if( new["format"]:false && new["noauto"]:false )
	    {
	    new["phash"] = "sha512";
	    new["itercountk"] = "100";
	    }
	}
    if( crypt_fs && size(new["crypt_key"]:"")==0 && 
        (!new["noauto"]:false||new["format"]:false) )
	{
	string fs_passwd = DlgCreateCryptFs( new["format"]:false?8:5 );
	// Ask the user for a password for cryptofs, else set crypto to nil??
	if( fs_passwd != nil && size(fs_passwd)>0 )
	    {
	    string crypt_key = Storage::AddCryptToClassified( fs_passwd );
	    new["crypt_key"] = crypt_key;
	    }
	else
	    {
	    ret["ok"] = false;
	    }
	}
    ret["map"] = new;
    y2milestone( "CheckCryptOk ret:%1", ret );
    return( ret );
    };

define map<string,any> HandleFsChanged( boolean init, map<string,any> new, map file_systems )
    ``{
    list<string> not_used_mp = [];
    symbol used_fs = new["used_fs"]:`unknown;
    map selected_fs = file_systems[used_fs]:$[];
    y2milestone( "init:%1 used_fs:%2 new:%3", init, used_fs, new );

    if( UI::WidgetExists( `id(`crypt_fs) ))
	{
	boolean cr = selected_fs[`crypt]:true;

	UI::ChangeWidget( `id(`crypt_fs), `Enabled, cr );
	if( !cr )
	    {
	    y2milestone( "crypt set to false" );
	    UI::ChangeWidget(`id(`crypt_fs), `Value, false );
	    }
	}

    ////////////////////////////////////////////////
    // switch between swap and other mountpoints
    string mount = (string)UI::QueryWidget( `id(`mount_point), `Value);
    new["mount"] = mount;
    if( used_fs == `swap )
	{
	not_used_mp = selected_fs[`mountpoints]:[];
	if( mount != "swap" )
	    new["mount"] = "swap";
	}
    else
	{
	not_used_mp =
	    notUsedMountpoints( Storage::GetTargetMap(),
				selected_fs[`mountpoints]:[] );
	if( new["type"]:`primary == `lvm || new["type"]:`primary == `sw_raid )
	    {
	    not_used_mp = filter( string mp, not_used_mp, 
	                          ``( mp != Partitions::BootMount() ));
	    }
	else if( new["type"]:`primary == `loop )
	    {
	    not_used_mp = 
		filter( string mp, not_used_mp, 
			``(!contains( FileSystems::system_m_points, mp)));
	    }
	if(mount == "swap")
	    new["mount"] = "";
	}
    UI::ReplaceWidget(`id(`mount_dlg_rp), MountDlg( new, not_used_mp));
    UI::ChangeWidget( `id(`mount_point), `Value, new["mount"]:"" );

    UI::ChangeWidget(`id(`fstab_options), `Enabled, true );
    UI::ChangeWidget(`id(`fs_options), `Enabled,
                     new["format"]:false && selected_fs[`options]:[] != [] );
    string fstopt = FileSystems::DefaultFstabOptions( new );
    if( size(fstopt)>0 && size(new["fstopt"]:"")==0 )
	new["fstopt"] = fstopt;
    if( !init )
	{
	new["fs_options"] = $[];
	new["fstopt"] = fstopt;

	integer max_len = FileSystems::LabelLength( used_fs );
	if( size(new["label"]:"") > max_len )
	    {
	    new["label"] = substring( new["label"]:"", 0, max_len );
	    }
	symbol mountby = new["mountby"]:`device;
	if( (mountby == `uuid && !FileSystems::MountUuid( used_fs )) ||
	    (mountby == `label && !FileSystems::MountLabel( used_fs )) )
	    {
	    new["mountby"] = `device;
	    }
	if( !FileSystems::MountLabel( used_fs ) && size(new["label"]:"")>0 )
	    {
	    new["label"] = "";
	    }
	}
    y2debug( "HandleFsChanged new %1", new );
    return( new );
    };


define map<string,any> HandlePartWidgetChanges( boolean init, any ret, 
                                                map file_systems, 
						map<string,any> old, 
						map<string,any> new )
    ``{
    y2milestone( "init:%1 ret:%2 new:%3", init, ret, new );
    symbol used_fs = new["used_fs"]:`unknown;
    map selected_fs = file_systems[used_fs]:$[];
    /////////////////////////////////////////////////////////
    // configure main dialog and modify map new
    if( !init && new["mount"]:"" != old["mount"]:"" )
	{
	if( Arch::ia64 () && new["mount"]:"" == Partitions::BootMount() )
	    {
	    new = filter(string key, any value, new, ``( key != "fstopt"));
	    }
	}
    if( init || ret == `format_true || ret == `format_false )
	{
	boolean format = UI::QueryWidget(`id(`format), `CurrentButton) == 
	                 `format_true;

	boolean old_format = new["format"]:false;

	////////////////////////////////////////////////
	// format partition
	new["format"] = format;

	////////////////////////////////////////////////
	// modify widgets
	UI::ChangeWidget( `id(`fs), `Enabled, format );
	UI::ChangeWidget( `id(`fs_options), `Enabled,
			  format && selected_fs[`options]:[] != [] );
	if( UI::WidgetExists( `id(`crypt_fs) ))
	    {
	    UI::ChangeWidget( `id(`crypt_fs), `Enabled, 
			      selected_fs[`crypt]:true );
	    }
	if( UI::WidgetExists( `id(`fsid_point) ))
	    {
	    UI::ChangeWidget( `id(`fsid_point), `Enabled, !format);
	    }

	if( old_format != format )
	    {
	    symbol dfs = `none;
	    if( format )
		{
		dfs = (symbol)UI::QueryWidget(`id(`fs), `Value);
		}
	    else
		{
		if( new["detected_fs"]:`unknown != `unknown )
		    {
		    dfs = new["detected_fs"]:Partitions::default_fs;
		    }
		else
		    {
		    dfs = new["used_fs"]:Partitions::default_fs;
		    }
		UI::ChangeWidget( `id(`fs), `Value, dfs );
		}
	    map selected_fs = file_systems[dfs]:$[];
	    new["used_fs"] = dfs;
	    y2milestone( "used_fs %1", dfs );
	    if( new["used_fs"]:`unknown != old["used_fs"]:`unknown )
		new = HandleFsChanged( init, new, file_systems );
	    if( format )
		{
		new["fsid"] = selected_fs[`fsid]:Partitions::fsid_native;
		}
	    else
		{
		if( haskey( new, "ori_fsid" ) )
		    {
		    new["fsid"] = new["ori_fsid"]:0;
		    }
		else
		    {
		    new["fsid"] = old["fsid"]:0;
		    }
		}
	    if( UI::WidgetExists( `id(`fsid_point) ))
		{
		if( size(selected_fs)>0 &&
		    new["fsid"]:0 != selected_fs[`fsid]:0 && 
		    !contains( selected_fs[`alt_fsid]:[], new["fsid"]:0 ))
		    {
		    UI::ChangeWidget( `id(`fsid_point), `Value,
				      selected_fs[`fsid_item]:"");
		    }
		}
	    if( Arch::s390 () && format )
		{
		if (new["used_fs"]:`unknown != `jfs)
		    {
		    new["fs_options"] = $["opt_blocksize":$["option_str":"-b",
							    "option_value":"4096"]];
		    }
		else
		    {
		    new["fs_options"] = $[];
		    }
		}
	    if( !format )
		{
		new["fs_options"] = $[];
		}
	    new["fstopt"] = FileSystems::DefaultFstabOptions( new );
	    }
	}
    if( init || ret == `fs )
	{
	symbol new_fs = (symbol)UI::QueryWidget(`id(`fs), `Value);
	if( init && !new["format"]:false && new["detected_fs"]:`none != `none )
	    {
	    new_fs = new["detected_fs"]:`none;
	    }
	y2milestone( "new_fs %1", UI::QueryWidget(`id(`fs), `Value) );
	y2milestone( "ret==fs init=%1 used_fs:%2 new_fs:%3", init, used_fs,
	             new_fs );
	if( init || used_fs != new_fs )
	    {
	    used_fs = new_fs;
	    map selected_fs = file_systems[used_fs]:$[];
	    new["used_fs"] = used_fs;

	    new = HandleFsChanged( init, new, file_systems );

	    if( !init )
		{
		new["fsid"] = selected_fs[`fsid]:Partitions::fsid_native;
		if( UI::WidgetExists( `id(`fsid_point) ))
		    {
		    UI::ChangeWidget( `id(`fsid_point), `Value,
				      selected_fs[`fsid_item]:"");
		    }
		if( Arch::s390 () && new["format"]:false )
		    {
		    if (new["used_fs"]:`unknown != `jfs)
			{
			new["fs_options"] =
			    $["opt_blocksize":$["option_str":"-b",
						"option_value":"4096"]];
			}
		    else
			{
			new["fs_options"] = $[];
			}
		    }
		}
	    }
	}
    if( (init && UI::WidgetExists(`id(`fsid_point))) || ret == `fsid_point )
	{
	////////////////////////////////////////////////
	// modify map new
	string fs_string = (string)UI::QueryWidget(`id(`fsid_point ), `Value);
	fs_string        = substring( fs_string, 0, 5  );
	integer fs_int   = tointeger( fs_string );
	integer old_id   = new["fsid"]:0;

	y2milestone( "fs_int:%1 old_id:%2", fs_int, old_id );

	if( fs_int != old_id )
	    {
	    new["fsid"] = fs_int;
	    boolean no_fs = contains( [ Partitions::fsid_lvm,
	                                Partitions::fsid_raid,
					Partitions::fsid_hibernation,
					Partitions::fsid_prep_chrp_boot ],
				      fs_int );

	    UI::ChangeWidget( `id(`fstab_options), `Enabled, !no_fs );
	    UI::ChangeWidget( `id(`format_true), `Enabled, !no_fs );
	    UI::ChangeWidget( `id(`mount_point), `Enabled, !no_fs );
	    if( no_fs )
		{
		new["mount"] = "";
		UI::ChangeWidget( `id(`mount_point), `Value, new["mount"]:"" );
		if( UI::WidgetExists( `id(`crypt_fs) ))
		    {
		    UI::ChangeWidget( `id(`crypt_fs), `Enabled, false );
		    }
		ChangeExistingSymbolsState( [ `fs_options, `fs ], false );
		}
	    else if( fs_int == Partitions::fsid_native )
		{
		new["used_fs"] = Partitions::default_fs;
		UI::ChangeWidget( `id(`fs), `Value, new["used_fs"]:`unknown );
		new = HandleFsChanged( init, new, file_systems );
		}
	    else if( fs_int == Partitions::fsid_swap )
		{
		new["used_fs"] = `swap;
		UI::ChangeWidget( `id(`fs), `Value, new["used_fs"]:`unknown );
		new = HandleFsChanged( init, new, file_systems );
		}
	    else if( contains( Partitions::fsid_wintypes, fs_int ) ||
	             fs_int==Partitions::fsid_gpt_boot )
		{
		new["mount"] = "";
		new["used_fs"] = `fat32;
		UI::ChangeWidget( `id(`fs), `Value, new["used_fs"]:`unknown );
		new = HandleFsChanged( init, new, file_systems );
		}
	    else if( fs_int == Partitions::fsid_mac_hfs )
		{
		new["mount"] = "";
		new["used_fs"] = `hfs;
		UI::ChangeWidget( `id(`fs), `Value, new["used_fs"]:`unknown );
		new = HandleFsChanged( init, new, file_systems );
		}
	    }
	}
    if( ret == `fstab_options )
	{
	new["mount"] = UI::QueryWidget( `id(`mount_point), `Value );
	new = FstabOptions( old, new );
	}
    if( ret == `crypt_fs )
	{
	boolean val = (boolean)UI::QueryWidget( `id(`crypt_fs), `Value );
	new["crypt"] = val?(new["format"]:false?"twofish256":"twofish"):"none";
	}
    if( ret == `fs_options )
	{
	new["fs_options"] = FileSystemOptions( new["fs_options"]:$[],
	                                       selected_fs );
	}
    if( Mode::repair () )
        {
        UI::ChangeWidget(`id(`mount_point),   `Enabled, false);
        UI::ChangeWidget(`id(`fstab_options), `Enabled, false);
        UI::ChangeWidget(`id(`crypt_fs) ,     `Enabled, false);
        }
    
    y2debug( "HandlePartWidgetChanges old:%1", old );
    y2debug( "HandlePartWidgetChanges new:%1", new );
    return( new );
    };

/**
 * Merge readed list fstab with targetMap
 * @parm targetMap all targets
 * @parm fstab readed fstab list
 * @return return ( [ targetMap, table_input ]
 *
 */
define list AddFstabToData( map<string,map> targetMap, list<map> fstab )
    ``{
    if( fstab == nil )
	return [targetMap] ;

    fstab = maplist( map e, fstab,
	``{
	string name = e["spec"]:"";
	integer pos = findlastof( name, "=" );
	if( find( name, "LABEL" )==0 && pos>0 )
	    {
	    e["label"] = substring( name, pos+1 );
	    }
	else if( find( name, "UUID" )==0 && pos>0 )
	    {
	    e["uuid"] = substring( name, pos+1 );
	    }
	return( e );
	});

    y2milestone( "AddFstabToData fstab = %1", fstab );

    map new_targetMap = (map)eval( targetMap );
    map table_input = $["tbl":[]];

    foreach( string dev, map disk, targetMap,
	``{
	list new_partitions = [];
	map target = disk;
	foreach( map partition, disk["partitions"]:[],
	    ``{
	    map new_partition = partition;

	    /////////////////////////////////////////////////////////
	    // if the partition is not to delete
	    if( !partition["delete"]:false )
		{
		foreach( map fstab_entry, fstab,
		    ``{
		    string dev_fstab   = fstab_entry["spec"]:"";
		    string mount_fstab = fstab_entry["file"]:"";
		    boolean found = false;

		    if( size(fstab_entry["label"]:"")>0 && 
		        partition["label"]:"" == fstab_entry["label"]:"" )
			{
			found = true;
			new_partition["mountby"] = `label;
			}
		    if( size(fstab_entry["uuid"]:"")>0 && 
		        partition["uuid"]:"" == fstab_entry["uuid"]:"" )
			{
			found = true;
			new_partition["mountby"] = `uuid;
			}
		    else if( dev_fstab == partition["device"]:"" )
			{
			found = true;
			}
		    if( found )
			{
			new_partition["mount"] = mount_fstab;
			if( size(fstab_entry["mntops"]:"")>0 &&
			    fstab_entry["mntops"]:"" != "default" )
			    {
			    new_partition["fstopt"] = fstab_entry["mntops"]:"";
			    }

			/////////////////////////////////////////////
			// entries for table
			term a = `item(`id(dev_fstab));
			a = add( a, dev_fstab );
			a = add( a, mount_fstab );
			if( mount_fstab=="/" )
			    {
			    table_input["root"] = dev_fstab;
			    }
			table_input["tbl"] = add( table_input["tbl"]:[], a );
			}
		    });
		}
	    new_partitions = add( new_partitions, new_partition);
	    });
	target["partitions"] = new_partitions;
	new_targetMap[dev] = target;
	});

    y2milestone( "AddFstabToData table_input %1", table_input );
    y2milestone( "AddFstabToData tbl %1", table_input["tbl"]:[] );

    if( size( table_input["tbl"]:[] )>1 )
	{
	table_input["tbl"] = sort( term a, term b, table_input["tbl"]:[],
	                           ``(a[2]:""<b[2]:""));
	}
    y2milestone( "AddFstabToData ret %1", [ new_targetMap, table_input ] );

    return [ new_targetMap, table_input ];
    };

define boolean check_max_size( integer byte_size, integer max_size )
    ``{
    y2milestone( "icheck_lv_size byte_size=%1 max_size=%2", byte_size,
                 max_size );
   
    if( byte_size == 0 )
        {
	if( max_size>0 )
	    // error popup text
	    Popup::Error(sformat(_("The size entered is invalid.
Enter a size from 1M to %1. For example, 40M or 1G."),
				   ByteToHumanStringWithZero(max_size)) );
	else
	    // error popup text
	    Popup::Error(_("The size entered is invalid.
Enter a valid size, such as 500k, 40M, or 1G.
"));
        return( false );
        }

    if( max_size>0 && byte_size>max_size )
        {
	// error popup text
        Popup::Error(sformat(_("The size entered is too large.
Enter a size from 1M to %1."),
                               ByteToHumanStringWithZero(max_size)) );
        return( false );
        }

    return( true );
    };

define boolean CheckResizePossible( boolean ask, boolean lvm, integer resize, 
                                    symbol fsys, string mount )
    ``{
    map poss = FileSystems::IsResizable( fsys );
    boolean ret = true;

    y2milestone( "CheckResizePossible resize %1 ask %2 lvm %3 fsys %4 mount %5",
                 resize, ask, lvm, fsys, mount );
    if( size(mount)>0 && !Stage::initial () && resize < 0 && 
        !poss["mount_shrink"]:false && poss["shrink"]:false )
        {
	FsysCannotResizeMountPopup( lvm, mount );
	ret = false;
	}
    else if( size(mount)>0 && !Stage::initial () && resize > 0 && 
             !poss["mount_extend"]:false && poss["extend"]:false )
        {
	FsysCannotResizeMountPopup( lvm, mount );
	ret = false;
	}
    else if( resize < 0 && !poss["shrink"]:false )
	{
	ret = FsysCannotShrinkPopup( ask, lvm );
	}
    else if( resize < 0 && fsys==`reiser )
	{
	ret = FsysShrinkReiserWarning( lvm );
	}
    else if( resize>0 && !poss["extend"]:false )
	{
	ret = FsysCannotGrowPopup( ask, lvm );
	}
    y2milestone( "ret %1", ret );
    return( ret );
    }


}
