/* * 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)); } } }
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); } } }
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); }
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); }
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); }
/* * 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); }