ACC SHELL

Path : /usr/share/YaST2/clients/
File Upload :
Current File : //usr/share/YaST2/clients/users_plugin_quota.ycp

/**
 * File:
 *	include/users/users_plugin_quota.ycp
 *
 * Package:
 *	Configuration of Users
 *
 * Summary:
 *	This is GUI part of UsersPluginQuota,
 *	plugin for configuration of user and group quotas
 *
 * Authors:
 *	Jiri Suchomel <jsuchome@suse.cz>
 *
 * $Id: users_plugin_quota.ycp 54847 2009-01-21 09:26:16Z jsuchome $
 */
{
    textdomain "users";

    import "Label";
    import "Report";
    import "Users";
    import "UsersPluginQuota"; // plugin module
    import "Wizard";

    any ret			= nil;
    string func			= "";
    map<string,any> config	= $[];
    map<string,any> data	= $[];

    // read arguments
    if(size(WFM::Args()) > 0 && is(WFM::Args(0), string)) {
	func = (string) WFM::Args(0);
	if(size(WFM::Args()) > 1 && is(WFM::Args(1), map))
	    config = (map<string,any>)WFM::Args(1);
	if(size(WFM::Args()) > 2 && is(WFM::Args(2), map))
	    data = (map<string,any>)WFM::Args(2);
    }
    y2milestone("----------------------------------------");
    y2milestone("users plugin started: UsersPluginQuota");

    y2debug ("func=%1", func);
    y2debug ("config=%1", config);
    y2debug ("data=%1", data);

    // maximal value of IntFields
    integer max	= 999999999;

    /**
     * helper for updating values of time widget from number of seconds
     * @param id string that preceedes the subwidgets id's
     * @param seconds number of seconds to be shown in the widget
     */
    void update_time_widget (string id, integer seconds) {

	integer days	= seconds / (24*60*60);
	if (days > 0) seconds	= seconds - (days * 24*60*60);
	integer	hours	= seconds / (60*60);
	if (hours > 0) seconds	= seconds - (hours * 60*60);
	integer minutes	= seconds / 60;
	if (minutes > 0) seconds	= seconds - (minutes * 60);
	UI::ChangeWidget (`id (id + "d"), `Value, days);
	UI::ChangeWidget (`id (id + "h"), `Value, hours);
	UI::ChangeWidget (`id (id + "m"), `Value, minutes);
	UI::ChangeWidget (`id (id + "s"), `Value, seconds);
    }

    /**
     * helper for creating widget with time settings
     * @param id string that preceedes the subwidgets id's
     * @param seconds number of seconds to be shown in the widget
     */
    term time_dialog (string id, integer seconds) {

	integer days	= seconds / (24*60*60);
	if (days > 0) seconds	= seconds - (days * 24*60*60);
	integer	hours	= seconds / (60*60);
	if (hours > 0) seconds	= seconds - (hours * 60*60);
	integer minutes	= seconds / 60;
	if (minutes > 0) seconds	= seconds - (minutes * 60);
	return `HBox (
	    `IntField (`id (id + "d"), _("Days"), 0, max, days),
	    `IntField (`id (id + "h"), _("Hours"), 0, 23, hours),
	    `IntField (`id (id + "m"), _("Minutes"), 0, 59, minutes),
	    `IntField (`id (id + "s"), _("Seconds"), 0, 59, seconds)
	);
    }

    /**
     * helper for reading the content of time widget
     * @param id string that preceedes the subwidgets id's
     * @return the number of seconds shown in the time widget
     */
    integer get_seconds_value (string id) {

	integer days	= (integer) UI::QueryWidget (`id (id + "d"), `Value);
	integer hours	= (integer) UI::QueryWidget (`id (id + "h"), `Value);
	integer minutes	= (integer) UI::QueryWidget (`id (id + "m"), `Value);
	integer seconds	= (integer) UI::QueryWidget (`id (id + "s"), `Value);
	return (days * 24*60*60) + (hours * 60*60) + (minutes *60) + seconds;
    }

    // ----------------------------- now, the main body ----------------

    if (func == "Summary") {
	ret = UsersPluginQuota::Summary (config, $[]);
    }
    else if (func == "Name") {
	ret = UsersPluginQuota::Name (config, $[]);
    }
    else if (func == "Dialog") {
	string caption			= UsersPluginQuota::Name (config, $[]);
	// list of edited settings (for each filesystem)
	list<map> quota_list		= [];
	string what			= config["what"]:"user";

	// helptext for quota
	string help_text = _("<p>Here, configure quota settings of the user on selected file systems.</p>") +

	// helptext for quota, cont.
	_("<p>Define a size limit by specifying the number of 1 KB blocks the
user may have on this file system. Additionally, you can define an inode limit specifying the number of inodes the user may have on the file system.</p>
") +

	// helptext for quota, cont.
	_("<p>You can specify both soft and hard limits for size and number of inodes. The soft limits define a warning level at which users are informed they are nearing their limit, whereas the hard limits define the limit at which write requests are denied.</p>") +

	// helptext for quota, cont.
	_("<p>As soon as the user has reached the soft limit, the input fields for the grace interval are activated. Specify the time period for which the user is allowed to exceed the soft limits set above. The countdown of the grace interval starts immediately.</p>");

	if (what == "group")
	{
	    // helptext for quota
	    help_text = _("<p>Here, configure quota settings of the group on selected file systems.</p>") +

	    // helptext for quota, cont.
	    _("<p>Define a size limit by specifying the number of 1 kB blocks the
group may have on this file system. Additionally, you can define an inode limit specifying the number of inodes the group may have on the file system.</p>
") +

	    // helptext for quota, cont.
	    _("<p>You can specify both soft and hard limits for size and number of inodes. The soft limits define a warning level at which groups are informed they are nearing their limit, whereas the hard limits define the limit at which write requests are denied.</p>") +

	    // helptext for quota, cont.
	    _("<p>As soon as the group has reached the soft limit, the input fields for the grace interval are activated. Specify the time period for which the group is allowed to exceed the soft limits set above. The countdown of the grace interval starts immediately.</p>");
	}

	boolean modified	= data["plugin_modified"]:0 == 1;
	integer current		= 0; // current fs (index in the list)
	list<map> current_quota	= data["quota"]:[];

	// map of quota settings for current fs
	map<string,any> quotamap = (map<string,any>) current_quota[current]:$[];

	// helper to obtain integer when value might be string or integer...
	integer get_int (string key) {
	    any value	= quotamap[key]:nil;
	    if (value == nil) return 0;
	    if (is (value, integer)) return (integer) value;
	    if (is (value, string) && value != "")
		return tointeger ((string)value);
	    return 0;
	}

	integer	quota_blocks_soft	= get_int ("quota_blocks_soft");
	integer	quota_blocks_hard	= get_int ("quota_blocks_hard");
	integer	quota_blocks_grace	= get_int ("quota_blocks_grace");
	integer	quota_inodes_soft	= get_int ("quota_inodes_soft");
	integer	quota_inodes_hard	= get_int ("quota_inodes_hard");
	integer	quota_inodes_grace	= get_int ("quota_inodes_grace");

	integer i	= -1;
	// go through whole quota list, generate items for filesystem combo,
	// and create tmp quota maps for each fs
	list fs_items = maplist (map q, current_quota, {
	    string fs	= q["quota_fs"]:"";
	    i	= i + 1;
	    // data that cannot be modified
	    map fixed	= $[ "quota_fs": fs ];
	    if (haskey (q, "quota_blocks_grace_exceeded"))
		fixed["quota_blocks_grace_exceeded"]	= 1;
	    if (haskey (q, "quota_inodes_grace_exceeded"))
		fixed["quota_inodes_grace_exceeded"]	= 1;
	    quota_list	= add (quota_list, fixed);
	    return `item (`id (i), fs, i == current);
	});

	term contents = `HBox (
	    `HSpacing (3),
            `VBox (
		`VSpacing (0.4),
		`Left (`ComboBox (`id ("quota_fs"), `opt (`notify),
		    // combo box label
		    _("&File System"), fs_items)),
		`VSpacing (0.4),
		// frame label
		`Frame (_("Size Limits"), `HBox (`HSpacing (0.5), `VBox (
		    `IntField (`id ("quota_blocks_soft"), `opt (`hstretch),
			// intfield label
			_("&Soft limit"), 0, max, quota_blocks_soft),
		    `IntField (`id ("quota_blocks_hard"),
			// intfield label
			_("&Hard limit"), 0, max, quota_blocks_hard),
		    `VSpacing (0.2),
		    `ReplacePoint (`id ("quota_blocks_grace"),
			time_dialog ("quota_blocks_grace", quota_blocks_grace)
		    ),
		    `VSpacing (0.2)
		), `HSpacing (0.5))),
		// 2 small spaces instead of one big because of ncurses:
		`VSpacing (0.4),
		`VSpacing (0.4),
		// frame label
		`Frame (_("I-nodes Limits"), `HBox (`HSpacing (0.5), `VBox (
		    `IntField (`id ("quota_inodes_soft"),
			// intfield label
			_("S&oft limit"), 0, max, quota_inodes_soft),
		    `IntField (`id ("quota_inodes_hard"),
			// intfield label
			_("Har&d limit"), 0, max, quota_inodes_hard),
		    `VSpacing (0.2),
		    `ReplacePoint (`id ("quota_inodes_grace"),
			time_dialog ("quota_inodes_grace", quota_inodes_grace)
		    ),
		    `VSpacing (0.2)
		), `HSpacing (0.5))),
		`VSpacing (0.4)
	    ),
            `HSpacing (3)
	);

	Wizard::CreateDialog ();
        Wizard::SetDesktopIcon("users");

	Wizard::SetContentsButtons(
	    UsersPluginQuota::Name (config, $[]), contents, help_text,
	    Label::CancelButton(), Label::OKButton()
	);

	Wizard::HideAbortButton ();

	// grace time widgets are only available when soft limit was passed
	if (!haskey (quotamap, "quota_blocks_grace_exceeded"))
	{
	    foreach (string k, [ "d", "h", "m", "s" ], {
		UI::ChangeWidget (`id ("quota_blocks_grace"+k),`Enabled, false);
	    });
	}
	if (!haskey (quotamap, "quota_inodes_grace_exceeded"))
	{
	    foreach (string k, [ "d", "h", "m", "s" ], {
		UI::ChangeWidget (`id ("quota_inodes_grace"+k),`Enabled, false);
	    });
	}

	ret = `next;
	repeat
	{
	    ret = UI::UserInput();
	    if (ret == "quota_fs" || ret == `next)
	    {
		integer sel = (integer)UI::QueryWidget(`id("quota_fs"), `Value);
		if (sel != current || ret == `next)
		{
		    // error popup
		    string msg	= _("Soft limit cannot be set higher than the hard limit.");
		    if ((integer)
			UI::QueryWidget(`id ("quota_blocks_soft"), `Value) >
			(integer)
			UI::QueryWidget(`id ("quota_blocks_hard"), `Value))
		    {
			Report::Error (msg);
			UI::SetFocus (`id ("quota_blocks_soft"));
			ret	= `notnext;
			continue;
		    }
		    if ((integer)
			UI::QueryWidget(`id ("quota_inodes_soft"), `Value) >
			(integer)
			UI::QueryWidget(`id ("quota_inodes_hard"), `Value))
		    {
			Report::Error (msg);
			UI::SetFocus (`id ("quota_inodes_soft"));
			ret	= `notnext;
			continue;
		    }

		    foreach (string key, ["quota_blocks_soft",
			"quota_blocks_hard", "quota_inodes_soft",
			"quota_inodes_hard", "quota_blocks_grace",
			"quota_inodes_grace" ],
		    {
			// read the new map for selected fs
			if (quota_list[sel,key]:nil != nil)
			    quotamap[key]	= quota_list[sel,key]:nil;
			else
			    quotamap[key]       = data["quota",sel,key]:nil;
			if (! issubstring (key, "grace"))
			{
			    // save current status (still in UI)
			    quota_list[current,key]	=
				UI::QueryWidget(`id(key),`Value);
			    // ... and update UI with the new one
			    if (ret != `next)
				UI::ChangeWidget(`id (key),`Value,get_int(key));
			}
			else
			{
			    // save the old
			    quota_list[current,key] = get_seconds_value (key);
			    // show the new
			    if (ret != `next)
				update_time_widget (key, get_int (key));
			}
		    });
		    if (ret != `next)
			UI::ChangeWidget (`id ("quota_fs"), `Value,
			    quota_list[sel,"quota_fs"]:"");
		    current		= sel;
		}
	    }
	    if (ret == `next)
	    {
		integer i		= 0;
		foreach (map qmap, quota_list, {
		    foreach (string key, any val, (map<string,any>) qmap, {
			if (key == "quota_fs") return;
			if (sformat ("%1", val) !=
			    tostring (current_quota[i,key]:"0"))
			{
			    modified	= true;
			}
		    });
		    i	= i + 1;
		});
		if (!modified)
		    break;

		// modified data to add to user/group
		map<string, any> tmp_data	= $[
		    "quota"		: quota_list,
		    "plugin_modified"	: 1,
		];

		// if this plugin wasn't in default set, we must save its name
		// (this is probably obsolete, users module should take care)
		if (!contains (data["plugins"]:[], "UsersPluginQuota"))
		{
		    tmp_data["plugins"] = add (tmp_data["plugins"]:[],
			"UsersPluginQuota");
		}
		if (data["what"]:"" == "edit_user")
		    Users::EditUser (tmp_data);
		else if (data["what"]:"" == "add_user")
		    Users::AddUser (tmp_data);
		else if (data["what"]:"" == "edit_group")
		    Users::EditGroup (tmp_data);
		else if (data["what"]:"" == "add_group")
		    Users::AddGroup (tmp_data);
	    }
	} until (is(ret,symbol) &&
	    contains ([`next, `abort, `back, `cancel], (symbol) ret));
	Wizard::CloseDialog ();
    }
    else {
	y2error("unknown function: %1", func);
	ret = false;
    }
    y2milestone("users plugin finished with %1", ret);
    y2milestone("----------------------------------------");
    return ret;
}

ACC SHELL 2018