Пример #1
0
/*
 * Returns:
 *	-1 = the form should be redisplayed
 *	 0 = failure, function is over
 *	 1 = success, function is over
 */
static int
show_create_subpartitions_form(struct dfui_form *f, struct i_fn_args *a)
{
	struct dfui_dataset *ds;
	struct dfui_response *r;

	for (;;) {
		if (dfui_form_dataset_get_first(f) == NULL)
			populate_create_subpartitions_form(f, a);

		if (!dfui_be_present(a->c, f, &r))
			abort_backend();

		if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
			dfui_response_free(r);
			return(0);
		} else if (strcmp(dfui_response_get_action_id(r), "switch") == 0) {
			if (check_subpartition_selections(r, a)) {
				save_subpartition_selections(r, a);
				expert = expert ? 0 : 1;
				dfui_response_free(r);
				return(-1);
			}
		} else {
			if (check_subpartition_selections(r, a)) {
				save_subpartition_selections(r, a);
				if (!warn_subpartition_selections(a) &&
				    !warn_encrypted_boot(a)) {
					if (!create_subpartitions(a)) {
						inform(a->c, _("The subpartitions you chose were "
							"not correctly created, and the "
							"primary partition may "
							"now be in an inconsistent state. "
							"We recommend re-formatting it "
							"before proceeding."));
						dfui_response_free(r);
						return(0);
					} else {
						dfui_response_free(r);
						return(1);
					}
				}
			}
		}

		dfui_form_datasets_free(f);
		/* dfui_form_datasets_add_from_response(f, r); */
		for (ds = dfui_response_dataset_get_first(r); ds != NULL;
		    ds = dfui_dataset_get_next(ds)) {
			dfui_form_dataset_add(f, dfui_dataset_dup(ds));
		}
	}
}
Пример #2
0
static void
save_subpartition_selections(struct dfui_response *r, struct i_fn_args *a)
{
	struct dfui_dataset *ds;
	const char *mountpoint, *capstring;
	long capacity;
	int valid = 1;

	subpartitions_free(storage_get_selected_slice(a->s));

	for (ds = dfui_response_dataset_get_first(r); valid && ds != NULL;
	    ds = dfui_dataset_get_next(ds)) {
		mountpoint = dfui_dataset_get_value(ds, "mountpoint");
		capstring = dfui_dataset_get_value(ds, "capacity");

		if (string_to_capacity(capstring, &capacity)) {
			subpartition_new_hammer(storage_get_selected_slice(a->s),
			    mountpoint, capacity,
			    strcasecmp(dfui_dataset_get_value(ds, "encrypted"), "Y") == 0);
		}
	}
}
Пример #3
0
static struct curses_form *
curses_form_construct_from_dfui_form_multiple(const struct dfui_form *f)
{
	struct curses_form *cf;
	struct curses_form_userdata *cfu;
	const char *min_width_str;
	unsigned int desc_width, min_width = 0;
	unsigned int len, max_label_width, total_label_width;
	unsigned int max_button_width, total_button_width;
	struct dfui_field *fi;
	struct dfui_action *a;
	struct curses_widget *label, *button;
	struct dfui_dataset *ds;
	const char *name;
	int left_acc, top_acc;
	int row = 1, col = 0, ins_x = 1, is_menu = 0;

	dfui_debug("-----\nconstructing multiple form: %s\n",
	    dfui_info_get_name(dfui_form_get_info(f)));

	cf = curses_form_new(dfui_info_get_name(dfui_form_get_info(f)));
	AURA_MALLOC(cfu, curses_form_userdata);
	cfu->f = f;
	cf->userdata = cfu;
	cf->cleanup = 1;

	set_help(f, cf);

	/* Calculate offsets for nice positioning of labels and buttons. */

	/*
	 * Determine the widths of the widest field and the widest
	 * button, and the total widths of all fields and all buttons.
	 */

	max_label_width = 0;
	total_label_width = 0;
	max_button_width = 0;
	total_button_width = 0;

	for (fi = dfui_form_field_get_first(f); fi != NULL;
	     fi = dfui_field_get_next(fi)) {
		len = MIN(60, strlen(dfui_info_get_name(dfui_field_get_info(fi))));
		if (len > max_label_width)
			max_label_width = len;
		total_label_width += (len + 2);
	}
	for (a = dfui_form_action_get_first(f); a != NULL;
	     a = dfui_action_get_next(a)) {
		len = strlen(dfui_info_get_name(dfui_action_get_info(a)));
		if (len > max_button_width)
			max_button_width = len;
		total_button_width += (len + 6);
	}

	/* Take the short description and turn it into a set of labels. */

	if ((min_width_str = dfui_form_property_get(f, "minimum_width")) != NULL)
		min_width = atoi(min_width_str);

	desc_width = 40;
	desc_width = MAX(desc_width, min_width);
	desc_width = MAX(desc_width, total_button_width);
	desc_width = MAX(desc_width, total_label_width);
	desc_width = MIN(desc_width, xmax - 3);

	dfui_debug("min width: %d\n", min_width);
	dfui_debug("button width: %d\n", total_button_width);
	dfui_debug("label width: %d\n", total_label_width);
	dfui_debug("resulting width: %d\n", desc_width);
	dfui_debug("form width: %d\n", cf->width);

	cf->height = curses_form_descriptive_labels_add(cf,
	    dfui_info_get_short_desc(dfui_form_get_info(f)),
	    1, cf->height + 1, desc_width);

	dfui_debug("form width now: %d\n", cf->width);

	/* Add the fields. */

	top_acc = cf->height + 1;
	cf->height += dfui_form_dataset_count(f) + 2;

	/*
	 * Create the widgets for a multiple=true form.  For each field
	 * in the form, a label containing the field's name, which serves
	 * as a heading, is created.  Underneath these labels, for each
	 * dataset in the form, a row of input widgets (typically textboxes)
	 * is added.  Non-action, manipulation buttons are also added to
	 * the right of each row.
	 */
	left_acc = 1;
	for (fi = dfui_form_field_get_first(f); fi != NULL;
	     fi = dfui_field_get_next(fi)) {
		/*
		 * Create a label to serve as a heading for the column.
		 */
		name = dfui_info_get_name(dfui_field_get_info(fi));
		label = curses_form_widget_add(cf, left_acc,
		    top_acc, 0, CURSES_LABEL, name, 0,
		    CURSES_WIDGET_WIDEN);
		cfu->widths[col++] = label->width + 2;
		left_acc += (label->width + 2);
	}

	/*
	 * Create a row of widgets for each dataset.
	 */
	top_acc++;
	for (ds = dfui_form_dataset_get_first(f); ds != NULL;
	     ds = dfui_dataset_get_next(ds)) {
		ins_x = curses_form_create_widget_row(cf, NULL, ds,
		     1, top_acc++, row++);
	}

	/*
	 * Finally, create an 'Add' button to add a new row
	 * if this is an extensible form.
	 */
	if (dfui_form_is_extensible(f)) {
		button = curses_form_widget_add(cf,
		    ins_x, top_acc, 0,
		    CURSES_BUTTON, "Add", 0, CURSES_WIDGET_WIDEN);
		button->user_id = row;
		curses_widget_set_click_cb(button, cb_click_insert_row);
		cf->height++;
	}

	cf->height++;

	/* Add the buttons. */

	create_buttons(f, cf, is_menu);

	cf->height++;

	curses_form_finalize(cf);

	return(cf);
}
Пример #4
0
void
fn_install_bootblocks(struct i_fn_args *a, const char *device)
{
	struct dfui_form *f;
	struct dfui_response *r;
	struct dfui_dataset *ds;
	struct disk *d;
	struct commands *cmds;
	struct command *cmd;
	char disk[64], boot0cfg[32], packet[32];
	char msg_buf[1][1024];

	snprintf(msg_buf[0], sizeof(msg_buf[0]),
	    "'Packet Mode' refers to using newer BIOS calls to boot "
	    "from a partition of the disk.  It is generally not "
	    "required unless:\n\n"
	    "- your BIOS does not support legacy mode; or\n"
	    "- your %s primary partition resides on a "
	    "cylinder of the disk beyond cylinder 1024; or\n"
	    "- you just can't get it to boot without it.",
	    OPERATING_SYSTEM_NAME);

	f = dfui_form_create(
	    "install_bootstrap",
	    _("Install Bootblock(s)"),
	    a->short_desc,

	    msg_buf[0],

	    "p", "special", "dfinstaller_install_bootstrap",

	    "f", "disk", _("Disk Drive"),
	    _("The disk on which you wish to install a bootblock"), "",
	    "p", "editable", "false",
	    "f", "boot0cfg", _("Install Bootblock?"),
	    _("Install a bootblock on this disk"), "",
	    "p", "control", "checkbox",
	    "f", "packet", _("Packet Mode?"),
	    _("Select this to use 'packet mode' to boot the disk"), "",
	    "p", "control", "checkbox",

	    "a", "ok", _("Accept and Install Bootblocks"), "", "",
	    "a", "cancel", a->cancel_desc, "", "",
	    "p", "accelerator", "ESC",

	    NULL
	);

	dfui_form_set_multiple(f, 1);

	if (device != NULL) {
		ds = dfui_dataset_new();
		dfui_dataset_celldata_add(ds, "disk", device);
		dfui_dataset_celldata_add(ds, "boot0cfg", "Y");
		dfui_dataset_celldata_add(ds, "packet", "Y");
		dfui_form_dataset_add(f, ds);
	} else {
		for (d = storage_disk_first(a->s); d != NULL; d = disk_next(d)) {
			ds = dfui_dataset_new();
			dfui_dataset_celldata_add(ds, "disk",
			    disk_get_device_name(d));
			dfui_dataset_celldata_add(ds, "boot0cfg", "Y");
			dfui_dataset_celldata_add(ds, "packet", "Y");
			dfui_form_dataset_add(f, ds);
		}
	}

	if (!dfui_be_present(a->c, f, &r))
		abort_backend();

	a->result = 0;
	if (strcmp(dfui_response_get_action_id(r), "ok") == 0) {
		cmds = commands_new();

		for (ds = dfui_response_dataset_get_first(r); ds != NULL;
		     ds = dfui_dataset_get_next(ds)) {
			strlcpy(disk, dfui_dataset_get_value(ds, "disk"), 64);
			strlcpy(boot0cfg, dfui_dataset_get_value(ds, "boot0cfg"), 32);
			strlcpy(packet, dfui_dataset_get_value(ds, "packet"), 32);

			if (strcasecmp(boot0cfg, "Y") == 0) {
				cmd = command_add(cmds, "%s%s -B -o %spacket %s",
				    a->os_root, cmd_name(a, "BOOT0CFG"),
				    strcasecmp(packet, "Y") == 0 ? "" : "no",
				    disk);
				command_set_failure_mode(cmd, COMMAND_FAILURE_WARN);
				command_set_tag(cmd, "%s", disk);
				cmd = command_add(cmds, "%s%s -v %s",
				    a->os_root, cmd_name(a, "BOOT0CFG"),
				    disk);
				command_set_failure_mode(cmd, COMMAND_FAILURE_WARN);
				command_set_tag(cmd, "%s", disk);
			}
		}

		if (!commands_execute(a, cmds)) {
			ask_to_wipe_boot_sector(a, cmds);
		} else {
			inform(a->c, _("Bootblocks were successfully installed!"));
			a->result = 1;
		}
		commands_free(cmds);
	}

	dfui_form_free(f);
	dfui_response_free(r);
}
Пример #5
0
static int
check_subpartition_selections(struct dfui_response *r, struct i_fn_args *a)
{
	struct dfui_dataset *ds;
	struct dfui_dataset *star_ds = NULL;
	struct aura_dict *d;
	const char *mountpoint, *capstring;
	long capacity = 0;
	int found_root = 0;
	int valid = 1;

	d = aura_dict_new(1, AURA_DICT_LIST);

	if ((ds = dfui_response_dataset_get_first(r)) == NULL) {
		inform(a->c, _("Please set up at least one subpartition."));
		valid = 0;
	}

	for (ds = dfui_response_dataset_get_first(r); valid && ds != NULL;
	    ds = dfui_dataset_get_next(ds)) {
#ifdef DEBUG
		dfui_dataset_dump(ds);
#endif
		mountpoint = dfui_dataset_get_value(ds, "mountpoint");
		capstring = dfui_dataset_get_value(ds, "capacity");

		if (aura_dict_exists(d, mountpoint, strlen(mountpoint) + 1)) {
			inform(a->c, _("The same mount point cannot be specified "
			    "for two different subpartitions."));
			valid = 0;
		}

		if (strcmp(mountpoint, "/") == 0)
			found_root = 1;

		if (strcmp(capstring, "*") == 0) {
			if (star_ds != NULL) {
				inform(a->c, _("You cannot have more than one subpartition "
				    "with a '*' capacity (meaning 'use the remainder "
				    "of the primary partition'.)"));
				valid = 0;
			} else {
				star_ds = ds;
			}
		}

		if (!(!strcasecmp(mountpoint, "swap") || mountpoint[0] == '/')) {
			inform(a->c, _("Mount point must be either 'swap', or it must "
			    "start with a '/'."));
			valid = 0;
		}

		if (strpbrk(mountpoint, " \\\"'`") != NULL) {
			inform(a->c, _("Mount point may not contain the following "
			    "characters: blank space, backslash, or "
			    "single, double, or back quotes."));
			valid = 0;
		}

		if (strlen(capstring) == 0) {
			inform(a->c, _("A capacity must be specified."));
			valid = 0;
		}

		if (!string_to_capacity(capstring, &capacity)) {
			inform(a->c, _("Capacity must be either a '*' symbol "
			    "to indicate 'use the rest of the primary "
			    "partition', or it must be a series of decimal "
			    "digits ending with an 'M' (indicating "
			    "megabytes), a 'G' (indicating gigabytes) and "
			    "so on (up to 'E'.)"));
			valid = 0;
		}

		/*
		 * Maybe remove this limit entirely?
		 */
		if ((strcasecmp(mountpoint, "swap") == 0) &&
		    (capacity > SWAP_MAX)) {
			inform(a->c, _("Swap capacity is limited to %dG."),
			    SWAP_MAX / 1024);
			valid = 0;
		}

		/*
		 * If we made it through that obstacle course, all is well.
		 */

		if (valid)
			aura_dict_store(d, mountpoint, strlen(mountpoint) + 1, "", 1);
	}

	if (!found_root) {
		inform(a->c, _("You must include a / (root) subpartition."));
		valid = 0;
	}

	if (aura_dict_size(d) > 16) {
		inform(a->c, _("You cannot have more than 16 subpartitions "
		    "on a single primary partition.  Remove some "
		    "and try again."));
		valid = 0;
	}

	aura_dict_free(d);

	return(valid);
}
Пример #6
0
/*
 * Push a new Lua table representing the given DFUI response
 * onto the Lua stack.
 */
static int
lua_table_from_dfui_response(lua_State *L, struct dfui_response *r)
{
	int table_idx, list_idx, subtable_idx;
	struct dfui_dataset *ds;
	struct dfui_celldata *cd;
	const char *value;
	int counter = 1;
	const char *f_id, *a_id;

	lua_newtable(L);
	table_idx = lua_gettop(L);

	/*
	 * Add response id's to the table.
	 */
	f_id = dfui_response_get_form_id(r);
	a_id = dfui_response_get_action_id(r);

	lua_pushliteral(L, "form_id");
	lua_pushlstring(L, f_id, strlen(f_id));
	lua_settable(L, table_idx);

	lua_pushliteral(L, "action_id");
	lua_pushlstring(L, a_id, strlen(a_id));
	lua_settable(L, table_idx);

	/*
	 * Create 'datasets' lists to the table.
	 */
	lua_pushliteral(L, "datasets");
	lua_newtable(L);
	list_idx = lua_gettop(L);
	
	/*
	 * Add response datasets to the 'datasets' list.
	 */
	for (ds = dfui_response_dataset_get_first(r); ds != NULL;
	     ds = dfui_dataset_get_next(ds)) {
		lua_pushnumber(L, counter++);
		lua_newtable(L);
		subtable_idx = lua_gettop(L);
		/*
		 * Populate this subtable with the celldatas...
		 */
		for (cd = dfui_dataset_celldata_get_first(ds); cd != NULL;
		     cd = dfui_celldata_get_next(cd)) {
			f_id = dfui_celldata_get_field_id(cd);
			value = dfui_celldata_get_value(cd);
			lua_pushlstring(L, f_id, strlen(f_id));
			lua_pushlstring(L, value, strlen(value));
			lua_settable(L, subtable_idx);
		}
		/*
		 * Add this subtable to the list
		 */
		lua_settable(L, list_idx);
	}

	/*
	 * Add the 'datasets' list to the table.
	 */
	lua_settable(L, table_idx);

	return(table_idx);
}