ACC SHELL

Path : /usr/share/YaST2/include/partitioning/
File Upload :
Current File : //usr/share/YaST2/include/partitioning/custom_part_dialogs.ycp

/*
 *************************************************************
 *
 *     YaST2      SuSE Labs                        -o)
 *     --------------------                        /\\
 *                                                _\_v
 *           www.suse.de / www.suse.com
 * ----------------------------------------------------------
 *
 * Author:        Michael Hager <mike@suse.de>
 *                Johannes Buchhold <jbuch@suse.de>
 *
 *
 * Description:   Partitioner for experts.
 *                include for dialogs
 *
 *************************************************************

 $Id: custom_part_dialogs.ycp 61723 2010-04-16 08:33:56Z aschnell $

*/
{
  textdomain "storage";

  import "Storage";
  import "Partitions";
  import "FileSystems";
  import "Package";
  import "Mode";
  import "Arch";
  import "Label";
  import "Popup";
    import "StorageProposal";

  include "partitioning/custom_part_helptexts.ycp";


  // TODO: cleanup
  boolean check_unique_label( map<string,map> targetMap, map part );
  boolean CheckFstabOptions( map part );
  symbol check_devices_used( list<map> partitions, boolean not_cr );


define string DlgCreateCryptFs( string device, integer minpwlen, boolean format,
                                boolean tmpcrypt )
  ``{
    string helptext = GetCreateCryptFsHelptext(minpwlen, format, tmpcrypt);
    y2milestone( "DlgCreateCryptFs device:%1 minpwlen:%2 format:%3 tmpcrypt:%4",
                 device, minpwlen, format, tmpcrypt );

    // heading text
    string h = _("Enter your Password for the Encrypted File System.");
    // label text
    string label = _("Don't forget what you enter here!");
    if( tmpcrypt )
	{
	label = label + " ";
	label = label + _("Empty password allowed.");
	}

    if( size(device)>0 )
	// heading text, %1 is replaced by device name (e.g. /dev/hda1)
	h = sformat( _("Password for Encrypted File System on %1"), device );

    string ret = Storage::PasswdPopup( helptext, h, label, format, minpwlen, tmpcrypt );
    return( ret );
    }


    boolean QueryProposalPassword()
	      {
	if (!isempty(StorageProposal::GetProposalPassword()))
	    return true;

	UI::OpenDialog(`VBox(
			   `Label(_("Enter your password for the proposal encryption.")),
			   `MinWidth(40,
				     `Password(`id(`pw1),
					       // Label: get password for user root
					       // Please use newline if label is longer than 40 characters
					       _("Password:"), "")),
			   `VSpacing(0.5),
			   `MinWidth(40,
				     `Password(`id(`pw2),
					       // Label: get same password again for verification
					       // Please use newline if label is longer than 40 characters
					       _("Reenter the password for verification:"), "")),
			   `Label(_("Don't forget what you enter here!")),
			   `ButtonBox(
			       `PushButton(`id(`ok), `opt(`default), Label::OKButton()),
			       `PushButton(`id(`cancel), Label::CancelButton())
			       )
			   ));

	string password = "";
        symbol widget = nil;

	repeat
		  {
	    // Clear password fields on every round.
	    UI::ChangeWidget(`id(`pw1), `Value, "");
	    UI::ChangeWidget(`id(`pw2), `Value, "");

	    UI::SetFocus(`id(`pw1));

	    widget = (symbol) UI::UserInput();

	    switch (widget)
		  {
		case `ok:

		    password = (string) UI::QueryWidget(`id(`pw1), `Value);
		    string tmp = (string) UI::QueryWidget(`id(`pw2), `Value);

		    if (!Storage::CheckEncryptionPasswords(password, tmp, 8, false))
			widget = `again;

		    break;
		  }

	} until (widget == `cancel || widget == `ok);

      UI::CloseDialog();

	if (widget == `ok)
	  {
	    StorageProposal::SetProposalPassword(password);
	    return true;
	  }
	else
	{
	    return false;
  }

    }


//////////////////////////////////////////////////////////////////////////////
// Dialog Password for Crypted FS Update
//////////////////////////////////////////////////////////////////////////////


define string DlgUpdateCryptFs( string device, string mount )
    ``{
    string helptext = GetUpdateCryptFsHelptext();

// translator comment: %1 is the device name, %2 is a directory
//            example: "...password for device /dev/hda6 mounted on /var"
    string enter = sformat(_("Enter your crypt password for
device %1 mounted on %2.
"),device,mount);

    UI::OpenDialog(
	     `opt(`decorated ),
	     `HBox(
		   `HWeight(3, `RichText( helptext ) ),
		   `HWeight(6, `VBox(
				    `VSpacing(0.3),
				    `HBox(
					  `HSpacing(1),
					  // heading text
					  `Heading(_("Enter your password for the encrypted file system")),
					  `HSpacing(1)
					 ),
				    `VSpacing(2),
				    `HBox(
					  `HSpacing(4),
					  `VBox(
						// advise user to remember his new password
						`Label(enter),
						`VSpacing(),

						`HBox(
						    `Password(`id("pw1"),
						    // Label: get password for user root
						    // Please use newline if label is longer than 40 characters
								_("&Enter a password for your file system:"), ""),
						    `HSpacing(15)),
						`VSpacing(0.5),

						`HBox(
						    `Password(`id("pw2"),
						    // Label: get same password again for verification
						    // Please use newline if label is longer than 40 characters
								_("Reenter the password for &verification:"), ""),
						    `HSpacing(15))
						),
					  `HSpacing(4)
					  ),
				    `VSpacing(2),
				    `ButtonBox(
					  `PushButton(`id("ok"), `opt(`default),  Label::OKButton()),
					  // Cancel button
					  `PushButton(`id("cancel"),  _("&Skip") )
					  ),
				    `VSpacing(0.5)
				    )
			   )
	     ));

      string ret         = "";
      boolean input_is_ok = false;
      string pw1 	  = "";
      string pw2 	  = "";

      repeat
      {
	  // Clear password fields on every round.
	  UI::ChangeWidget(`id("pw1"), `Value, "");
	  UI::ChangeWidget(`id("pw2"), `Value, "");

	  UI::SetFocus(`id("pw1"));

	  ret = (string)UI::UserInput();


	  if (ret != "cancel")
	  {
	      pw1 = (string)UI::QueryWidget(`id("pw1"), `Value);
	      pw2 = (string)UI::QueryWidget(`id("pw2"), `Value);

	      if ( pw1 != pw2 )
	      {
		  // popup text
		  Popup::Message(_("The first and the second version\nof the password do not match!\nPlease try again."));
	      }
	      else  if (pw1 == "")
	      {
		  // popup text
		  Popup::Message(_("You did not enter a password.
Try again.
"));
	      }
	      else if ( size(pw1) >= 1 )
	      {
		  input_is_ok = true;
	      }
	      else
	      {
		  // popup text
		  Popup::Message(sformat(_("The password must have at least %1 characters.
Try again.
"),1));
	      }
	  }

      } until ( input_is_ok || ret == "cancel" );

      UI::CloseDialog();

      if (ret != "cancel")
      {
	  return( pw1 );
      }
      else
      {
	  return( "" );
      }

  }

define symbol DoInputChecks( map entry, string query )
    ``{
    symbol ret = `ok;
    list between = entry[`between]:[];
    string valid_chars = entry[`valid_chars]:"";
    integer str_length = entry[`str_length]:0;

    if( between != [] && (size(query)>0 || !entry[`empty_allowed]:false))
	{
	y2milestone( "DoInputChecks entry:%1 query:\"%2\"", entry, query );
	if( between[0]:0 > tointeger(query)  ||
	    ( (between[1]:0 != -1) && (between[1]:0 < tointeger(query) ) ) )
	    {
	    Popup::Error(entry[`error_text]:"");
	    ret = `error;
	    }
	}

    if( valid_chars != "" && size(query)>0 && ret != `error )
	{
	if( nil != findfirstnotof( query, valid_chars ))
	    {
	    Popup::Error(entry[`error_text]:"");
	    ret = `error;
	    }
	}

    if( str_length != 0 && size(query) > str_length && ret != `error )
	{
	Popup::Error(entry[`error_text]:"");
	ret = `error;
	}
    y2milestone( "DoInputChecks value %1 ret %2", query, ret );
    return( ret );
    }

  /**
   * Dialog: Filesystem options
   * @parm new_val map that contains a partition
   * @parm file_systems filesystem definitions
   */
map <any, map<string, any> > FileSystemOptions(map< any, map<string,any> > org_fs_options, 
					       map fs_define)
    ``{
    y2milestone( "FileSystemOptions org_fs_options:%1 fs_define:%2", org_fs_options, fs_define );
    map<any, map<string,any> > fs_options = org_fs_options;
    term contents 	= `VBox(`VSpacing (1));
    string helptext   = "";

    foreach( map option, fs_define[`options]:[],
	``{
	term emptyterm = `Empty();
	contents = add( contents, option[`widget]:emptyterm);
	string add_help = option[`help_text]:"";
	if( add_help != "")
	    helptext = helptext + add_help ;
	});

    UI::OpenDialog(`opt(`decorated),
		   `VBox(
		       `HSpacing(50),
		       // heading text
		       `Left(`Heading(_("File system options:"))),
		       `VStretch(),
		       `VSpacing(1),
		       `HBox(
			   `HStretch(),
			   `HSpacing(1),
			   contents,
			   `HStretch(),
			   `HSpacing(1)),
		       `VSpacing(1),
		       `VStretch(),
		       `ButtonBox(  
			   `PushButton(`id(`help), `opt(`helpButton), Label::HelpButton()),
			   `PushButton(`id(`ok), `opt(`default), Label::OKButton()),
			   `PushButton(`id(`cancel), Label::CancelButton())
			   )
		       )
	);

    UI::ChangeWidget(`help, `HelpText, helptext);

    foreach(any query_key, map<string, any> option_map, fs_options,
	``{
	UI::ChangeWidget( `id(query_key), `Value,
			  option_map["option_value"]:(any)"" );
	});

    list<any> iglist = ["auto", "none", "default"];
    symbol ret = `ok;
    repeat
	{
	ret = (symbol)UI::UserInput();
	if( ret == `ok )
	    {
	    foreach( map entry, fs_define[`options]:[],
		``{
		y2milestone( "FileSystemOptions entry %1", entry );
		if( ret != `error )
		    {
		    any query = UI::QueryWidget( `id(entry[`query_key]:nil),
		                                 `Value );
		    y2milestone( "FileSystemOptions query %1", query );
		    map<string,any> fs_option =
			$[ "option_str"   : entry[`option_str]:"",
			   "option_cmd"	  : entry[`option_cmd]:`mkfs,
			   "option_value" : query ];
		    y2milestone( "FileSystemOptions fs_option %1", fs_option );

		    if( entry[`option_blank]:false )
			{
			fs_option["option_blank"] = true;
			}

		    if( is( query, string) && !contains( iglist, query ))
			{
			ret = DoInputChecks( entry, (string)query );
			}

		    if( ret!=`error )
			{
			if( query!=entry[`default]:nil && 
			    !contains( iglist, query ))
			    {
			    fs_options[entry[`query_key]:nil] = fs_option;
			    }
			else if( haskey( fs_options, entry[`query_key]:nil ))
			    {
			    fs_options = remove( fs_options, 
			                         entry[`query_key]:nil );
			    }
			}
		    y2milestone( "FileSystemOptions fs_options %1", fs_options );
		    }
		});
	    }
	} until ( ret == `ok || ret == `cancel );

    UI::CloseDialog();

    if( ret != `ok )
	fs_options = org_fs_options;
    y2milestone("FileSystemOptions ret %1", fs_options );
    return( fs_options );
    }

void PopupNoSlashLabel()
    {
    // popup text
    Popup::Error( _("The character '/' is no longer permitted in a volume label.
Change your volume label so that it does not contain this character.
"));
    }

  /**
   * Dialog: Fstab options
   * @parm old map with original partition
   * @parm new map with changes filled in
   */
define map<string,any> FstabOptions( map<string,any> old, map<string,any> new )
    ``{
    string helptext = "";
    term contents = `VBox();
    term emptyterm = `Empty();

    if( new["enc_type"]:`none==`none) // && new["mount"]:"" != "swap" )
	{
	// help text, richtext format
	helptext = helptext + _("<p><b>Mount in /etc/fstab By:</b>
Normally, a file system to mount is identified in /etc/fstab
by the device name. This identification can be changed so the file system to mount
is found by searching for a UUID or a volume label. Not all file systems can be
mounted by UUID or a volume label. If an option is disabled, it is not possible.
");

	// help text, richtext format
	helptext = helptext + _("<p><b>Volume Label:</b>
The name entered in this field is used as the volume label. This usually makes sense only 
when you activate the option for mounting by volume label.
A volume label cannot contain the / character or spaces.
");

	contents = add( contents,
			`VBox(
			    `RadioButtonGroup(
				`id(`mt_group),
				`VBox(
				     // label text
				    `Left( `Label(_("Mount in /etc/fstab by"))),
				    `HBox(
					`VBox(
					    `Left( `RadioButton( `id(`device),
								 // label text
								 _("&Device name") )),
					    `Left( `RadioButton( `id(`label),
								 // label text
								 _("Volume &label") )),
					    `Left( `RadioButton( `id(`uuid),
								 // label text
								 "U&UID" ))
					    ),
					`Top(`VBox(
					    `Left( `RadioButton( `id(`id),
								 // label text
								 _("Device &ID") )),
					    `Left( `RadioButton( `id(`path),
								 // label text
								 _("Device &Path") ))
					    ))
					)
				     )
				),
			   `TextEntry( `id(`vol_label), `opt(`hstretch),
				       // label text
				       _("Volume &Label")),
			   `VSpacing(1)
		       ));
	}
    list<map> opt_list = [];
    if( new["mount"]:"" != "swap" )
	{
	foreach( map entry, FileSystems::GetGeneralFstabOptions(),
	    ``{
	    opt_list = add( opt_list, entry );

	    contents = add( contents, entry[`widget]:emptyterm );
	    helptext = helptext + entry[`help_text]:"";
	    });
	contents = add( contents, `VSpacing(1) );
	}
    foreach( map entry, FileSystems::GetFstabOptWidgets( new["used_fs"]:`ext2 ),
	``{
	opt_list = add( opt_list, entry );
	contents = add( contents, entry[`widget]:emptyterm );
	helptext = helptext + entry[`help_text]:"";
	});
    contents = add( contents, `VSpacing(1) );
    map entry = FileSystems::GetArbitraryOptionField();
    opt_list = add( opt_list, entry );
    contents = add( contents, entry[`widget]:emptyterm );
    helptext = helptext + entry[`help_text]:"";

    string fstopt = deletechars( new["fstopt"]:"", " \t" );
    if( fstopt == "defaults" )
	fstopt = "";

    list<string> opt_lstr = splitstring( fstopt, "," );
    map old_state = $[];
    integer pos = 0;
    foreach( map opt, opt_list,
	``{
	if( opt[`type]:`text == `boolean )
	    {
	    boolean value = opt[`default]:false;
	    pos = 0;
	    while( pos < size(opt_lstr) )
		{
		foreach( list list_el, opt[`str_scan]:[],
		    ``{
		    if( list_el[0]:""==opt_lstr[pos]:"" )
			{
			value = list_el[1]:0 == 1;
			opt_lstr[pos] = "";
			}
		    });
		pos = pos + 1;
		}
	    old_state[opt[`query_key]:""] = value;
	    }
	else
	    {
	    string value = opt[`default]:"";
	    integer pos = 0;
	    while( pos < size(opt_lstr) )
		{
		if( size(opt[`str_scan]:"")>0 &&
		    regexpmatch( opt_lstr[pos]:"", opt[`str_scan]:"" ))
		    {
		    value = regexpsub( opt_lstr[pos]:"",
		                       opt[`str_scan]:"", "\\1" );
		    opt_lstr[pos] = "";
		    }
		pos = pos + 1;
		}
	    old_state[opt[`query_key]:""] = value;
	    }
	});

    pos = size(opt_lstr)-1;
    while( pos>=0 )
	{
	if( size(opt_lstr[pos]:"")==0 )
	    {
	    opt_lstr = remove( opt_lstr, pos );
	    }
	pos = pos - 1;
	};
    y2milestone( "FstabOptions key=%1 val:%2", 
                 opt_list[size(opt_list)-1,`query_key]:"",
                 mergestring( opt_lstr, "," ) );
    string arb_opt = mergestring( opt_lstr, "," );
    if( !new["noauto"]:false && new["enc_type"]:`none!=`none )
	{
	arb_opt = FileSystems::RemoveCryptOpts( arb_opt );
	}
    if( FileSystems::CanDoQuota(new) && FileSystems::HasQuota(new) )
	old_state["opt_quota"] = true;
    arb_opt = FileSystems::RemoveQuotaOpts(arb_opt);
    old_state[opt_list[size(opt_list)-1,`query_key]:""] = arb_opt;
    y2milestone( "FstabOptions old_state=%1", old_state );

    UI::OpenDialog(`opt(`decorated),
		   `VBox(
		       `HSpacing(50),
		       // heading text
		       `Left(`Heading(_("Fstab options:"))),
		       `VStretch(),
		       `VSpacing(1),
		       `HBox(`HStretch(),
			     `HSpacing(1),
			     contents,
			     `HStretch(),
			     `HSpacing(1)),
		       `VSpacing(1),
		       `VStretch(),
		       `ButtonBox(
			   `PushButton(`id(`help), `opt(`helpButton), Label::HelpButton()),
			   `PushButton(`id(`ok), `opt(`default), Label::OKButton()),
			   `PushButton(`id(`cancel), Label::CancelButton())
			   )
		       )
	);

    UI::ChangeWidget(`help, `HelpText, helptext);

    if( UI::WidgetExists( `id(`mt_group) ))
	{
	list no_mountby_type = [ `loop ];
	list mountby_id_path_type = [ `primary, `logical ];
	map enab = $[];
	boolean tmp = !contains( no_mountby_type, new["type"]:`primary );
	enab[`label] = tmp && FileSystems::MountLabel( new["used_fs"]:`unknown ) &&
		       new["enc_type"]:`none==`none;
	enab[`uuid] = tmp && (new["format"]:false || size(new["uuid"]:"")>0) &&
		      FileSystems::MountUuid( new["used_fs"]:`unknown );
	tmp = contains(mountby_id_path_type, new["type"]:`none);
	enab[`id] = tmp && size(new["udev_id"]:[])>0;
	enab[`path] = tmp && size(new["udev_path"]:"")>0;
	y2milestone( "FstabOptions enab %1", enab );
	UI::ChangeWidget( `id(`label), `Enabled,  enab[`label]:false );
	UI::ChangeWidget( `id(`uuid), `Enabled, enab[`uuid]:false );
	UI::ChangeWidget( `id(`id), `Enabled, enab[`id]:false );
	UI::ChangeWidget( `id(`path), `Enabled, enab[`path]:false );
	symbol defmb = !Mode::config() ? Storage::GetMountBy( new["device"]:"" )
	                               : `device;
	y2milestone( "FstabOptions defmb %1", defmb );
	if( haskey( enab, defmb ) && !enab[defmb]:false )
	    defmb = `device;
	UI::ChangeWidget( `id(`mt_group), `CurrentButton,
	                  new["mountby"]:defmb );
	}

    if( UI::WidgetExists( `id(`vol_label) ))
	{
	UI::ChangeWidget( `id(`vol_label), `Enabled,
			  FileSystems::MountLabel( new["used_fs"]:`unknown ) &&
			  new["enc_type"]:`none==`none );
	UI::ChangeWidget( `id(`vol_label), `ValidChars,
			  FileSystems::nchars + "-._:/" );
	UI::ChangeWidget( `id(`vol_label), `Value, new["label"]:"" );
	}

    y2milestone( "FstabOptions Exists opt_user %1", 
                 UI::WidgetExists( `id("opt_user")));
    y2milestone( "FstabOptions new=%1", new );
    if( UI::WidgetExists( `id("opt_user") ))
	{
	UI::ChangeWidget( `id("opt_user"), `Enabled,
			  new["enc_type"]:`none==`none );
	}
    if( UI::WidgetExists( `id("opt_quota") ))
	{
	UI::ChangeWidget( `id("opt_quota"), `Enabled,
			  FileSystems::CanDoQuota(new) );
	}
    foreach( any key, any value, old_state,
	``{
	UI::ChangeWidget( `id(key), `Value, value );
	});

    any ret = `ok;
    repeat
	{
	ret = UI::UserInput();
	y2milestone( "FstabOptions ret %1", ret );
	if( ret == `ok )
	    {
	    if( UI::WidgetExists( `id(`mt_group) ))
		{
		new["mountby"] = UI::QueryWidget( `id(`mt_group),
		                                  `CurrentButton );
		if( !new["format"]:false && !new["create"]:false &&
		    new["mountby"]:`device != old["mountby"]:`device )
		    {
		    if( !haskey( new, "ori_mountby" ) )
			new["ori_mountby"] = old["mountby"]:`device;
		    }
		new["label"] = UI::QueryWidget( `id(`vol_label), `Value );
		if( new["label"]:"" != old["label"]:"" )
		    {
		    integer max_len =
			FileSystems::LabelLength( new["used_fs"]:`unknown );
		    if( size(new["label"]:"") > max_len )
			{
			new["label"] = substring( new["label"]:"", 0, max_len );
			// popup text %1 is a number
			Popup::Error( sformat(_("
Maximum volume label length for the selected file system
is %1. Your volume label was truncated to this size.
"), max_len ));
			}
		    if( search(new["label"]:"","/")!=nil )
			{
			PopupNoSlashLabel();
			ret = `again;
			}
		    if( !new["format"]:false && !new["create"]:false &&
			!haskey( new, "ori_label" ) )
			{
			new["ori_label"] = old["label"]:"";
			}
		    }
		if( new["mountby"]:`device == `label && size(new["label"]:"")==0 )
		    {
		    ret = `again;
		    // popup text
		    Popup::Error( _("Provide a volume label to mount by label."));
		    continue;
		    }
		if (size(new["label"]:"") > 0 && !check_unique_label(Storage::GetTargetMap(), new))
		    {
		    ret = `again;
		    // popup text
		    Popup::Error( _("This volume label is already in use. Select a different one."));
		    continue;
		    }
		if( new["mountby"]:`device == `label &&
		    search(new["label"]:"","/")!=nil )
		    {
		    ret = `again;
		    PopupNoSlashLabel();
		    continue;
		    }
		}
	    if( UI::WidgetExists( `id("opt_noauto") ))
		{
		new["noauto"] = UI::QueryWidget( `id("opt_noauto"), `Value );
		}
	    map new_state = $[];
	    string text = "";
	    string new_fstopt = "";
	    foreach( map entry, opt_list,
		``{
		text = "";
		any value = UI::QueryWidget( `id(entry[`query_key]:""),
		                             `Value );
		new_state[entry[`query_key]:""] = value;
		if( entry[`type]:`text == `boolean )
		    {
		    text = entry[`str_opt,"default"]:"";
		    if( value == true && haskey( entry[`str_opt]:$[], 1 ))
			{
			text = entry[`str_opt,1]:"";
			}
		    else if( value == false && haskey( entry[`str_opt]:$[], 0 ))
			{
			text = entry[`str_opt,0]:"";
			}
		    }
		else
		    {
		    if( DoInputChecks( entry, (string)value ) != `ok )
			{
			ret = `again;
			}
		    else if( size((string)value)>0 )
			{
			text = sformat( entry[`str_opt]:"%1", value );
			}
		    /* this is the default journal mode, no option needed for it */
		    if( text == "data=ordered" )
			{
			text = "";
			}
		    }
		if( size(text)>0 )
		    {
		    if( size(new_fstopt)>0 )
			new_fstopt = new_fstopt + ",";
		    new_fstopt = new_fstopt + text;
		    }
		});
	    if( UI::WidgetExists( `id("opt_quota") ) &&
	        UI::QueryWidget( `id("opt_quota"), `Value )==true )
		{
		new_fstopt = FileSystems::AddQuotaOpts(new,new_fstopt);
		if( !old_state["opt_quota"]:false && Mode::normal() )
		    {
		    Package::InstallAll( ["quota"] );
		    }
		}
	    y2milestone( "FstabOptions new_state=%1", new_state );
	    y2milestone( "FstabOptions old_fstopt=%1 new_fstopt=%2", 
	                 old["fstopt"]:"", new_fstopt );
	    if( old_state!=new_state && old["fstopt"]:"" != new_fstopt )
		{
		if( !new["format"]:false && !new["create"]:false &&
		    !haskey( new, "ori_fstopt" ) )
		    {
		    new["ori_fstopt"] = old["fstopt"]:"";
		    }
		new["fstopt"] = new_fstopt;
		}
	    if( !CheckFstabOptions( new ))
		{
		new["fstopt"] = old["fstopt"]:"";
		ret = `again;
		}
	    }
	} until ( ret == `ok || ret == `cancel );

    UI::CloseDialog();
    y2milestone( "FstabOptions fstopt %1 mountby:%2 label:%3", 
                 new["fstopt"]:"", new["mountby"]:`device, 
		 new["label"]:"" );
    return( new );
    };


/**
   * Dialogpart: Filesystem
   * @parm new_val map that contains a partition
   * @parm file_systems filesystem definitions
   * @return term the term contains a ComboBox with the different filesystems
   */
define term FileSystemsComboBox( map new_val, map<symbol,map> file_systems )
    ``{
    map<symbol,map> fs_sel = $[];
    list filesystems = [ ];
    boolean is_swap = new_val["fsid"]:0 == Partitions::fsid_swap;

    y2debug( "FileSystemsComboBox new=%1 swap=%2", new_val, is_swap );
    symbol ufs = new_val["used_fs"]:Partitions::DefaultFs();
    foreach( symbol file_system_name, map file_system_map, file_systems,
	``{
	if( file_system_map[`real_fs]:false &&
	    (file_system_name==ufs||file_system_map[`supports_format]:false))
	    {
	    fs_sel[file_system_name] = $[];
	    fs_sel[file_system_name,"text"] = file_system_map[`name]:"Ext2";
	    if( is_swap )
		fs_sel[file_system_name,"selected"] = file_system_name == `swap;
	    else
		fs_sel[file_system_name,"selected"] = file_system_name==ufs;
	    }
	});
    y2milestone( "FileSystemsComboBox fs_sel=%1", fs_sel );
    y2milestone( "FileSystemsComboBox DefFs=%1", Partitions::DefaultFs() );
    if( haskey( fs_sel, Partitions::DefaultFs() ) &&
	size(filter( any k, map e, fs_sel, ``(e["selected"]:false) ))==0 )
	{
	fs_sel[Partitions::DefaultFs(),"selected"] = true;
	y2milestone( "FileSystemsComboBox fs_sel=%1", fs_sel );
	}
    foreach( symbol fs_type, map entry, fs_sel,
	``{
	if( fs_type != `swap )
	    filesystems = add( filesystems,
		`item(`id(fs_type), entry["text"]:"Ext2", entry["selected"]:false ));
	});
    if( haskey( fs_sel, `swap ))
	{
	filesystems = add( filesystems,
	    `item( `id(`swap), fs_sel[`swap,"text"]:"Swap",
		    fs_sel[`swap,"selected"]:false ));
	}

    return `VBox(
	`ComboBox(`id(`fs), `opt(`hstretch, `notify),
		  // label text
		  _("File &system"), filesystems),
	`PushButton(`id(`fs_options), `opt(`hstretch),
		    // button text
		    _("O&ptions..."))
	);
    }


    term CryptButton(map new_val)
    { 
	if (Arch::s390())
	    return `Empty();

	boolean cr = new_val["enc_type"]:`none != `none;

	return `VBox(
	    `Left(`CheckBox(`id(`crypt_fs), `opt(`notify),
			    // button text
			    _("&Encrypt device"), cr)));
    }


/**
 * Dialogpart: Filesystem ID
 * @parm new_val map that contains a partition
 * @parm file_systems filesystem definitions
 * @return term the term contains a ComboBox that allow the user to  edit the filesystem ID
 */
define term FsidComboBox( map new_val, map<symbol, map> file_systems  )
    ``{
    list<term> items = [];
    list added_items = [];
    list added_fsids = [];
    foreach( any fs_name, map fs_map, file_systems,
	``{
	string fsid_item =  fs_map[`fsid_item]:" ";
	if( !contains( added_items, fsid_item ))
	    {
	    items = add( items,
		`item( `id(fsid_item), fsid_item,
			fs_map[`fsid]:0 == new_val["fsid"]:0));
	    added_fsids = add( added_fsids, fs_map[`fsid]:0 );
	    added_items = add( added_items, fsid_item );
	    }
	});

    integer id = new_val["fsid"]:0;
    if( id != 0 && !contains( added_fsids, id ) )
	{
	string part_id = Partitions::ToHexString(id) + " " +
			 Partitions::FsIdToString(id);
	items = add( items, `item( `id(part_id), part_id, true ));
	}

    map<string,integer> so = $[ "0x83" : 0, "0x8" : 1, "0xF" : 2, "0x0" : 3, 
                                "0x10" : 6 ];
    map<string,integer> val = $[];
    foreach( term t, items, ``{val[t[1]:""] = 5;} );
    foreach( string s, integer i, val,
	``{
	foreach( string match, integer w, so,
	    ``{
	    boolean found = false;
	    if( !found && search( s, match )==0 )
		{
		val[s] = w;
		found = true;
		}
	    });
	});
    items = sort( term a, term b, items, ``(val[a[1]:""]:5<=val[b[1]:""]:5));

    return( `ComboBox(`id(`fsid_point), `opt(`notify,`editable, `hstretch),
	    // label text
	    _("File system &ID:"), items ));
    };


// used by autoyast
define term FormatDlg( map new_val, map<symbol, map> file_systems )
    ``{
    y2debug( "FormatDlg val:%1", new_val );

    term fsid = `Empty();

    if( new_val["type"]:`primary != `lvm &&
	new_val["type"]:`primary != `sw_raid &&
	new_val["type"]:`primary != `loop && !Partitions::no_fsid_menu )
	{
	fsid = `VBox(
		`HBox( `HSpacing(2),
		    `ReplacePoint( `id(`fsid_dlg_rp),
			FsidComboBox( new_val, file_systems ))
		    ),
		`VSpacing(0.5),
		`VStretch()
		);
	}
    else
	{
	fsid = `VSpacing(0.5);
	}

		    // label text
    return `Frame (_("Format"),
	    `RadioButtonGroup(`id(`format),
		`VBox(
		    `VSpacing(1),
		    // button text
		    `Left(`RadioButton(`id(`format_false), `opt(`notify),
		                       _("Do &not format"), !new_val["format"]:false )),
		    fsid,
		    `Left(`RadioButton(`id(`format_true), `opt(`notify),
					// button text
		                        _("&Format"), new_val["format"]:false )),
		    `HBox(
			`HSpacing(2),
			FileSystemsComboBox( new_val, file_systems )),
		    CryptButton(new_val),
		    `VSpacing(0.5)
					 )));


    }


  /**
   * Change the state of all symbol from the list symbols
   * @parm symbols all symbols
   * @parm what true or false
   * @return nil
   */
define void ChangeExistingSymbolsState( list symbols , boolean what )
    ``{
    foreach( any sym, symbols, ``{
	  UI::ChangeWidget(`id(sym), `Enabled, what );
      });
    }


  /**
   * Dialogpart: Mount part
   * @parm new_val map that contains a partition
   * @parm file_systems filesystem definitions
   * @return term ComboBox with all mountpoints
   */
define term MountDlg( map new_val, list mountpoints )
    ``{
    if( mountpoints == nil  )
	mountpoints = [ "/", "/usr", Partitions::BootMount(), "/var", "/home",
	                "/opt" , ""];

    if( !contains( mountpoints, "" ) && new_val["enc_type"]:`none==`none )
	mountpoints = add( mountpoints , "");
    string mount = new_val["mount"]:"";

    if( !contains( mountpoints, mount ))
	mountpoints = union( [mount], mountpoints);

    term dlg = `VBox(
		   `PushButton( `id(`fstab_options), `opt(`hstretch),
			        // button text
				_("Fs&tab Options")),
		   `VSpacing(1),
		   `ComboBox(`id(`mount_point), `opt(`editable,`hstretch,`notify),
			     // label text
			     _("&Mount Point"), mountpoints  )
		   );
    // return term
    return ( dlg );
    }


define boolean ModifyPartitionInSystemWarningPopup( string part, string mount )
    ``{

    // popup text %1 is a partition name, %2 a dirctory
    string warning = sformat(_("
The selected partition (%1) is currently mounted on %2.
If you change parameters (such as the mount point or the file system type),
your Linux installation might be damaged.

Unmount the partition if possible. If you are unsure,
it is recommended to abort. Do not proceed unless you know
exactly what you are doing.

Continue?
"), part, mount );

      boolean ret = false;

      ret = Popup::YesNo( warning );

      return( ret );
  };


define boolean FsysCannotShrinkPopup( boolean ask, boolean lvm )
    ``{
    boolean ret = true;
    string txt = "";
    if( !lvm )
	// Popup text
	txt = _("
The file system on the partition cannot be shrunk by YaST2.
Only fat, ext2, ext3, ext4, and reiser allow shrinking of a file system.");
    else
	// Popup text
	txt = _("
The file system on the logical volume cannot be shrunk by YaST2.
Only fat, ext2, ext3, ext4, and reiser allow shrinking of a file system.");
    if( ask )
	{
	txt = txt + "\n";
	if( !lvm )
	    // Popup text
	    txt = txt + _("You risk losing data if you shrink this partition.");
	else
	    // Popup text
	    txt = txt + _("You risk losing data if you shrink this logical volume.");
	txt = txt + "\n\n";
	txt = txt + _("Continue?");
	}
    if( ask )
	{
	ret = Popup::YesNo( txt );
	}
    else
	{
	Popup::Error( txt );
	ret = false;
	}
    return( ret );
    }

define boolean FsysCannotGrowPopup( boolean ask, boolean lvm )
    ``{
    boolean ret = true;
    string txt = "";
    if( !lvm )
	// Popup text
	txt = _("
The file system on the selected partition cannot be extended by YaST2.
Only fat, ext2, ext3, ext4, xfs, and reiser allow extending a file system.");
    else
	// Popup text
	txt = _("
The file system on the selected logical volume cannot be extended by YaST2.
Only fat, ext2, ext3, ext4, xfs, and reiser allow extending a file system.");
    if( ask )
	{
	txt = txt + "\n\n";
	txt = txt + _("Continue resizing?");
	}
    if( ask )
	{
	ret = Popup::YesNo( txt );
	}
    else
	{
	Popup::Error( txt );
	ret = false;
	}
    return( ret );
    }

define void FsysCannotResizeMountPopup( boolean lvm, string mount )
    ``{
    // %1 is either replaced by "logical volume" or by "partition"
    string txt = sformat( _("
The file system is currently mounted on %1.
It is not possible to resize the file system while it is mounted.

Unmount the file system and retry resizing.
"),
                          mount );
    Popup::Error( txt );
    }

define boolean FsysShrinkReiserWarning( boolean lvm )
    ``{
    boolean ret = true;
    string txt = "";
    if( !lvm )
	// Popup text
	txt = _("You decreased a partition with a reiser file system on it.");
    else
	txt = _("You decreased a logical volume with a reiser file system on it.");
    txt = txt + "\n";
    txt = txt + _("
It is possible to shrink a reiser file system, but this feature is not
very thoroughly tested. A backup of your data is recommended.

Shrink the file system now?");
    ret = Popup::YesNo( txt );
    return( ret );
    }


//FIXME: y2-repair uses this, need to find
//a better place for it
symbol ReallyInstPrepdisk()
{
    symbol ret = `none;

    string doto = Storage::ChangeText();
    y2milestone("ReallyInstPrepdisk doto:%1", doto);

    if (size(doto) == 0)
    {
	// popup text
	Popup::Message(_("No unsaved changes exist."));
	ret = `back;
    }
    else
    {
	term dlg = `VBox(`VSpacing(1),
			 `HSpacing(60),
			 // label text
			 `Left(`Heading(_("Changes:"))),
			 `RichText(doto));

	UI::OpenDialog(`opt(`decorated, `warncolor),
		       `HBox(
			   `HSpacing(1),
			   `VBox(
			       dlg,
			       `VSpacing(1),
			       // popup text
			       `Heading(_(" Do you really want to execute these changes?")),
			       `VSpacing(1),
			       `HBox(
				   `PushButton(`id(`back), Label::CancelButton()),
				   `HStretch(),
				   // button text
				   `PushButton(`id(`apply), _("&Apply")),
				   `PushButton(`id(`finish), Label::FinishButton() )
				   ),
			       `VSpacing(0.2)
			       ),
			   `HSpacing(1)
			   )
	    );

	ret = (symbol) UI::UserInput();
	UI::CloseDialog();
    }

    y2milestone("ReallyInstPrepdisk ret=%1", ret);

    return ret;
}


/**
 * Delete all partition in targetMap from the device "del_dev" and return
 * a new targetMap.
 * Check if LVM partition exists on the device.
 * Check if at least on partition is mounted.
 * @return map targetMap
 */
boolean deleteAllDevPartitions(map<string, any> disk, boolean installation)
    {
    boolean go_on     = true;
    string del_dev = disk["device"]:"";
    y2milestone( "deleteAllDevPartitions disk:%1", remove( disk, "partitions" ));

    /////////////////////////////////////////////////////////////////
    // check mount points if not installation

    if( !installation )
	{
	list<map> mounts = Storage::mountedPartitionsOnDisk( del_dev );
	if( size( mounts ) != 0 )
	    {
	    /////////////////////////////////////////////////////////
	    // mount points found

	    string mounted_parts  = "";
	    foreach( map mount, mounts,
		``{
		//  %1 is replaced by device name, %1 by directory e.g /dev/hdd1 on /usr
		mounted_parts = mounted_parts +
		                sformat("%1 on %2", mount["device"]:"",
					mount["mount"]:"") + "\n";
		});

	    // popup text, %1 is replaced by device name
	    string message = sformat(_("The selected device contains partitions that are currently mounted:
%1
It is *strongly* recommended to unmount these partitions before deleting the partition table.
Choose Cancel unless you know exactly what you are doing.
"), mounted_parts );

	    if( !Popup::ContinueCancel(message))
		{
		go_on = false;
		}
	    }
	}

    if( go_on )
	{
	list<map> partitions = disk["partitions"]:[];

	symbol used = check_devices_used( partitions, false );

	go_on = used == `UB_NONE;

	if( used == `UB_LVM )
	    {
	    // popup text, Do not translate LVM.
	    Popup::Message(_("
The selected device contains at least one LVM partition
assigned to a volume group. Remove all
partitions from their respective volume groups
before deleting the device.
"));
	    }
	else if( used == `UB_MD )
	    {
	    // popup text, Do not translate RAID.
	    Popup::Message(_("
The selected device contains at least one partition
that is part of a RAID system. Unassign the
partitions from their respective RAID systems before
deleting the device.
"));
	    }
	else if( used != `UB_NONE )
	    {
	    // popup text
	    Popup::Message(_("
The selected device contains at least one partition
that is used by another volume. Delete the volume using it
before deleting the device.
"));
	    }

	if( go_on && disk["type"]:`CT_UNKNONW!=`CT_DMRAID )
	    {
	    /////////////////////////////////////////////////
	    // delete all partitions of disk
	    // logical partitions get removed when extended is deleted
	    list<map> dp = filter( map part, partitions, 
	                           ``(part["nr"]:0 <= disk["max_primary"]:4));
	    y2milestone( "deleteAllDevPartitions dp:%1", dp );
	    dp = sort( map a, map b, dp, ``(a["nr"]:0>b["nr"]:0));
	    y2milestone( "deleteAllDevPartitions dp:%1", dp );
	    foreach( map part, dp,
		``{
		go_on = go_on && Storage::DeleteDevice(part["device"]:"");
		});
	    }
	}
    y2milestone( "deleteAllDevPartitions ret:%1", go_on );
    return(go_on);
    }

}

ACC SHELL 2018