1*cdd2d676SSascha Wildner /* 2*cdd2d676SSascha Wildner * Copyright (c)2004 The DragonFly Project. All rights reserved. 3*cdd2d676SSascha Wildner * 4*cdd2d676SSascha Wildner * Redistribution and use in source and binary forms, with or without 5*cdd2d676SSascha Wildner * modification, are permitted provided that the following conditions 6*cdd2d676SSascha Wildner * are met: 7*cdd2d676SSascha Wildner * 8*cdd2d676SSascha Wildner * Redistributions of source code must retain the above copyright 9*cdd2d676SSascha Wildner * notice, this list of conditions and the following disclaimer. 10*cdd2d676SSascha Wildner * 11*cdd2d676SSascha Wildner * Redistributions in binary form must reproduce the above copyright 12*cdd2d676SSascha Wildner * notice, this list of conditions and the following disclaimer in 13*cdd2d676SSascha Wildner * the documentation and/or other materials provided with the 14*cdd2d676SSascha Wildner * distribution. 15*cdd2d676SSascha Wildner * 16*cdd2d676SSascha Wildner * Neither the name of the DragonFly Project nor the names of its 17*cdd2d676SSascha Wildner * contributors may be used to endorse or promote products derived 18*cdd2d676SSascha Wildner * from this software without specific prior written permission. 19*cdd2d676SSascha Wildner * 20*cdd2d676SSascha Wildner * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21*cdd2d676SSascha Wildner * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22*cdd2d676SSascha Wildner * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23*cdd2d676SSascha Wildner * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24*cdd2d676SSascha Wildner * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 25*cdd2d676SSascha Wildner * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26*cdd2d676SSascha Wildner * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27*cdd2d676SSascha Wildner * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28*cdd2d676SSascha Wildner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29*cdd2d676SSascha Wildner * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30*cdd2d676SSascha Wildner * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31*cdd2d676SSascha Wildner * OF THE POSSIBILITY OF SUCH DAMAGE. 32*cdd2d676SSascha Wildner */ 33*cdd2d676SSascha Wildner 34*cdd2d676SSascha Wildner /* 35*cdd2d676SSascha Wildner * fn_subpart.c 36*cdd2d676SSascha Wildner * Installer Function : Create Subpartitions. 37*cdd2d676SSascha Wildner * $Id: fn_subpart.c,v 1.50 2005/04/07 20:22:40 cpressey Exp $ 38*cdd2d676SSascha Wildner */ 39*cdd2d676SSascha Wildner 40*cdd2d676SSascha Wildner #include <stdio.h> 41*cdd2d676SSascha Wildner #include <stdlib.h> 42*cdd2d676SSascha Wildner #include <string.h> 43*cdd2d676SSascha Wildner 44*cdd2d676SSascha Wildner #ifdef ENABLE_NLS 45*cdd2d676SSascha Wildner #include <libintl.h> 46*cdd2d676SSascha Wildner #define _(String) gettext (String) 47*cdd2d676SSascha Wildner #else 48*cdd2d676SSascha Wildner #define _(String) (String) 49*cdd2d676SSascha Wildner #endif 50*cdd2d676SSascha Wildner 51*cdd2d676SSascha Wildner #include "libaura/mem.h" 52*cdd2d676SSascha Wildner #include "libaura/buffer.h" 53*cdd2d676SSascha Wildner #include "libaura/dict.h" 54*cdd2d676SSascha Wildner #include "libaura/fspred.h" 55*cdd2d676SSascha Wildner 56*cdd2d676SSascha Wildner #include "libdfui/dfui.h" 57*cdd2d676SSascha Wildner #include "libdfui/dump.h" 58*cdd2d676SSascha Wildner #include "libdfui/system.h" 59*cdd2d676SSascha Wildner 60*cdd2d676SSascha Wildner #include "libinstaller/commands.h" 61*cdd2d676SSascha Wildner #include "libinstaller/diskutil.h" 62*cdd2d676SSascha Wildner #include "libinstaller/functions.h" 63*cdd2d676SSascha Wildner #include "libinstaller/uiutil.h" 64*cdd2d676SSascha Wildner 65*cdd2d676SSascha Wildner #include "fn.h" 66*cdd2d676SSascha Wildner #include "flow.h" 67*cdd2d676SSascha Wildner #include "pathnames.h" 68*cdd2d676SSascha Wildner 69*cdd2d676SSascha Wildner static int create_subpartitions(struct i_fn_args *); 70*cdd2d676SSascha Wildner static long default_capacity(struct storage *, int); 71*cdd2d676SSascha Wildner static int check_capacity(struct i_fn_args *); 72*cdd2d676SSascha Wildner static int check_subpartition_selections(struct dfui_response *, struct i_fn_args *); 73*cdd2d676SSascha Wildner static void save_subpartition_selections(struct dfui_response *, struct i_fn_args *); 74*cdd2d676SSascha Wildner static void populate_create_subpartitions_form(struct dfui_form *, struct i_fn_args *); 75*cdd2d676SSascha Wildner static int warn_subpartition_selections(struct i_fn_args *); 76*cdd2d676SSascha Wildner static struct dfui_form *make_create_subpartitions_form(struct i_fn_args *); 77*cdd2d676SSascha Wildner static int show_create_subpartitions_form(struct dfui_form *, struct i_fn_args *); 78*cdd2d676SSascha Wildner 79*cdd2d676SSascha Wildner static const char *def_mountpt[7] = {"/", "swap", "/var", "/tmp", "/usr", "/home", NULL}; 80*cdd2d676SSascha Wildner static int expert = 0; 81*cdd2d676SSascha Wildner 82*cdd2d676SSascha Wildner /* 83*cdd2d676SSascha Wildner * Given a set of subpartitions-to-be in the selected slice, 84*cdd2d676SSascha Wildner * create them. 85*cdd2d676SSascha Wildner */ 86*cdd2d676SSascha Wildner static int 87*cdd2d676SSascha Wildner create_subpartitions(struct i_fn_args *a) 88*cdd2d676SSascha Wildner { 89*cdd2d676SSascha Wildner struct subpartition *sp; 90*cdd2d676SSascha Wildner struct commands *cmds; 91*cdd2d676SSascha Wildner int result = 0; 92*cdd2d676SSascha Wildner int copied_original = 0; 93*cdd2d676SSascha Wildner int num_partitions; 94*cdd2d676SSascha Wildner 95*cdd2d676SSascha Wildner cmds = commands_new(); 96*cdd2d676SSascha Wildner if (!is_file("%sinstall.disklabel.%s", 97*cdd2d676SSascha Wildner a->tmp, 98*cdd2d676SSascha Wildner slice_get_device_name(storage_get_selected_slice(a->s)))) { 99*cdd2d676SSascha Wildner /* 100*cdd2d676SSascha Wildner * Get a copy of the 'virgin' disklabel. 101*cdd2d676SSascha Wildner * XXX It might make more sense for this to 102*cdd2d676SSascha Wildner * happen right after format_slice() instead. 103*cdd2d676SSascha Wildner */ 104*cdd2d676SSascha Wildner command_add(cmds, "%s%s -r %s >%sinstall.disklabel.%s", 105*cdd2d676SSascha Wildner a->os_root, cmd_name(a, "DISKLABEL"), 106*cdd2d676SSascha Wildner slice_get_device_name(storage_get_selected_slice(a->s)), 107*cdd2d676SSascha Wildner a->tmp, 108*cdd2d676SSascha Wildner slice_get_device_name(storage_get_selected_slice(a->s))); 109*cdd2d676SSascha Wildner } 110*cdd2d676SSascha Wildner 111*cdd2d676SSascha Wildner /* 112*cdd2d676SSascha Wildner * Weave together a new disklabel out the of the 'virgin' 113*cdd2d676SSascha Wildner * disklabel, and the user's subpartition choices. 114*cdd2d676SSascha Wildner */ 115*cdd2d676SSascha Wildner 116*cdd2d676SSascha Wildner /* 117*cdd2d676SSascha Wildner * Take everything from the 'virgin' disklabel up until the 118*cdd2d676SSascha Wildner * '16 partitions' line. 119*cdd2d676SSascha Wildner */ 120*cdd2d676SSascha Wildner num_partitions = 16; 121*cdd2d676SSascha Wildner command_add(cmds, "%s%s '$2==\"partitions:\" || cut { cut = 1 } !cut { print $0 }' <%sinstall.disklabel.%s >%sinstall.disklabel", 122*cdd2d676SSascha Wildner a->os_root, cmd_name(a, "AWK"), 123*cdd2d676SSascha Wildner a->tmp, 124*cdd2d676SSascha Wildner slice_get_device_name(storage_get_selected_slice(a->s)), 125*cdd2d676SSascha Wildner a->tmp); 126*cdd2d676SSascha Wildner 127*cdd2d676SSascha Wildner /* 128*cdd2d676SSascha Wildner * 16 partitions: 129*cdd2d676SSascha Wildner * # size offset fstype 130*cdd2d676SSascha Wildner * c: 16383969 0 unused # 7999.985MB 131*cdd2d676SSascha Wildner */ 132*cdd2d676SSascha Wildner 133*cdd2d676SSascha Wildner command_add(cmds, "%s%s '%d partitions:' >>%sinstall.disklabel", 134*cdd2d676SSascha Wildner a->os_root, cmd_name(a, "ECHO"), num_partitions ,a->tmp); 135*cdd2d676SSascha Wildner command_add(cmds, "%s%s '%s' >>%sinstall.disklabel", 136*cdd2d676SSascha Wildner a->os_root, cmd_name(a, "ECHO"), 137*cdd2d676SSascha Wildner "# size offset fstype", 138*cdd2d676SSascha Wildner a->tmp); 139*cdd2d676SSascha Wildner 140*cdd2d676SSascha Wildner #ifdef DEBUG 141*cdd2d676SSascha Wildner for (sp = slice_subpartition_first(storage_get_selected_slice(a->s)); 142*cdd2d676SSascha Wildner sp != NULL; sp = subpartition_next(sp)) { 143*cdd2d676SSascha Wildner command_add(cmds, "%s%s 'mountpoint: %s device: %s'", 144*cdd2d676SSascha Wildner a->os_root, cmd_name(a, "ECHO"), 145*cdd2d676SSascha Wildner subpartition_get_mountpoint(sp), 146*cdd2d676SSascha Wildner subpartition_get_device_name(sp)); 147*cdd2d676SSascha Wildner } 148*cdd2d676SSascha Wildner #endif 149*cdd2d676SSascha Wildner 150*cdd2d676SSascha Wildner /* 151*cdd2d676SSascha Wildner * Write a line for each subpartition the user wants. 152*cdd2d676SSascha Wildner */ 153*cdd2d676SSascha Wildner for (sp = slice_subpartition_first(storage_get_selected_slice(a->s)); 154*cdd2d676SSascha Wildner sp != NULL; sp = subpartition_next(sp)) { 155*cdd2d676SSascha Wildner if (subpartition_is_mfsbacked(sp)) { 156*cdd2d676SSascha Wildner continue; 157*cdd2d676SSascha Wildner } 158*cdd2d676SSascha Wildner if (subpartition_get_letter(sp) > 'c' && !copied_original) { 159*cdd2d676SSascha Wildner /* 160*cdd2d676SSascha Wildner * Copy the 'c' line from the 'virgin' disklabel. 161*cdd2d676SSascha Wildner */ 162*cdd2d676SSascha Wildner command_add(cmds, "%s%s '^ c:' %sinstall.disklabel.%s >>%sinstall.disklabel", 163*cdd2d676SSascha Wildner a->os_root, cmd_name(a, "GREP"), 164*cdd2d676SSascha Wildner a->tmp, 165*cdd2d676SSascha Wildner slice_get_device_name(storage_get_selected_slice(a->s)), 166*cdd2d676SSascha Wildner a->tmp); 167*cdd2d676SSascha Wildner copied_original = 1; 168*cdd2d676SSascha Wildner } 169*cdd2d676SSascha Wildner if (subpartition_is_swap(sp)) { 170*cdd2d676SSascha Wildner command_add(cmds, "%s%s ' %c:\t%s\t*\tswap' >>%sinstall.disklabel", 171*cdd2d676SSascha Wildner a->os_root, cmd_name(a, "ECHO"), 172*cdd2d676SSascha Wildner subpartition_get_letter(sp), 173*cdd2d676SSascha Wildner capacity_to_string(subpartition_get_capacity(sp)), 174*cdd2d676SSascha Wildner a->tmp); 175*cdd2d676SSascha Wildner } else { 176*cdd2d676SSascha Wildner command_add(cmds, "%s%s ' %c:\t%s\t%s\t4.2BSD' >>%sinstall.disklabel", 177*cdd2d676SSascha Wildner a->os_root, cmd_name(a, "ECHO"), 178*cdd2d676SSascha Wildner subpartition_get_letter(sp), 179*cdd2d676SSascha Wildner capacity_to_string(subpartition_get_capacity(sp)), 180*cdd2d676SSascha Wildner subpartition_get_letter(sp) == 'a' ? "0" : "*", 181*cdd2d676SSascha Wildner a->tmp); 182*cdd2d676SSascha Wildner } 183*cdd2d676SSascha Wildner } 184*cdd2d676SSascha Wildner if (!copied_original) { 185*cdd2d676SSascha Wildner /* 186*cdd2d676SSascha Wildner * Copy the 'c' line from the 'virgin' disklabel, 187*cdd2d676SSascha Wildner * if we haven't yet (less than 2 subpartitions.) 188*cdd2d676SSascha Wildner */ 189*cdd2d676SSascha Wildner command_add(cmds, "%s%s '^ c:' %sinstall.disklabel.%s >>%sinstall.disklabel", 190*cdd2d676SSascha Wildner a->os_root, cmd_name(a, "GREP"), 191*cdd2d676SSascha Wildner a->tmp, 192*cdd2d676SSascha Wildner slice_get_device_name(storage_get_selected_slice(a->s)), 193*cdd2d676SSascha Wildner a->tmp); 194*cdd2d676SSascha Wildner } 195*cdd2d676SSascha Wildner temp_file_add(a, "install.disklabel"); 196*cdd2d676SSascha Wildner 197*cdd2d676SSascha Wildner /* 198*cdd2d676SSascha Wildner * Label the slice from the disklabel we just wove together. 199*cdd2d676SSascha Wildner */ 200*cdd2d676SSascha Wildner command_add(cmds, "%s%s -R -B -r %s %sinstall.disklabel", 201*cdd2d676SSascha Wildner a->os_root, cmd_name(a, "DISKLABEL"), 202*cdd2d676SSascha Wildner slice_get_device_name(storage_get_selected_slice(a->s)), 203*cdd2d676SSascha Wildner a->tmp); 204*cdd2d676SSascha Wildner 205*cdd2d676SSascha Wildner /* 206*cdd2d676SSascha Wildner * Create a snapshot of the disklabel we just created 207*cdd2d676SSascha Wildner * for debugging inspection in the log. 208*cdd2d676SSascha Wildner */ 209*cdd2d676SSascha Wildner command_add(cmds, "%s%s %s", 210*cdd2d676SSascha Wildner a->os_root, cmd_name(a, "DISKLABEL"), 211*cdd2d676SSascha Wildner slice_get_device_name(storage_get_selected_slice(a->s))); 212*cdd2d676SSascha Wildner 213*cdd2d676SSascha Wildner /* 214*cdd2d676SSascha Wildner * Create filesystems on the newly-created subpartitions. 215*cdd2d676SSascha Wildner */ 216*cdd2d676SSascha Wildner for (sp = slice_subpartition_first(storage_get_selected_slice(a->s)); 217*cdd2d676SSascha Wildner sp != NULL; sp = subpartition_next(sp)) { 218*cdd2d676SSascha Wildner if (subpartition_is_swap(sp) || subpartition_is_mfsbacked(sp)) 219*cdd2d676SSascha Wildner continue; 220*cdd2d676SSascha Wildner 221*cdd2d676SSascha Wildner /* 222*cdd2d676SSascha Wildner * Ensure that all the needed device nodes exist. 223*cdd2d676SSascha Wildner */ 224*cdd2d676SSascha Wildner command_add_ensure_dev(a, cmds, 225*cdd2d676SSascha Wildner disk_get_device_name(storage_get_selected_disk(a->s))); 226*cdd2d676SSascha Wildner command_add_ensure_dev(a, cmds, 227*cdd2d676SSascha Wildner slice_get_device_name(storage_get_selected_slice(a->s))); 228*cdd2d676SSascha Wildner command_add_ensure_dev(a, cmds, 229*cdd2d676SSascha Wildner subpartition_get_device_name(sp)); 230*cdd2d676SSascha Wildner 231*cdd2d676SSascha Wildner command_add(cmds, "%s%s%s -b %ld -f %ld %sdev/%s", 232*cdd2d676SSascha Wildner a->os_root, cmd_name(a, "NEWFS"), 233*cdd2d676SSascha Wildner subpartition_is_softupdated(sp) ? " -U" : "", 234*cdd2d676SSascha Wildner subpartition_get_bsize(sp), 235*cdd2d676SSascha Wildner subpartition_get_fsize(sp), 236*cdd2d676SSascha Wildner a->os_root, 237*cdd2d676SSascha Wildner subpartition_get_device_name(sp)); 238*cdd2d676SSascha Wildner } 239*cdd2d676SSascha Wildner 240*cdd2d676SSascha Wildner result = commands_execute(a, cmds); 241*cdd2d676SSascha Wildner commands_free(cmds); 242*cdd2d676SSascha Wildner return(result); 243*cdd2d676SSascha Wildner } 244*cdd2d676SSascha Wildner 245*cdd2d676SSascha Wildner /* 246*cdd2d676SSascha Wildner * +-------+------------+--------------+-----------------+-----------------+ 247*cdd2d676SSascha Wildner * | Mtpt | Matt says | FreeBSD says | I got away with | A tiny system | 248*cdd2d676SSascha Wildner * +-------+------------+--------------+-----------------+-----------------+ 249*cdd2d676SSascha Wildner * | / | 256M | 100M | 256M | 64M | 250*cdd2d676SSascha Wildner * | swap | 1G | 2 or 3 * mem | (4 * mem) 256M | (1 * mem) 64M | 251*cdd2d676SSascha Wildner * | /var | 256M | 50M | 256M | 12M | 252*cdd2d676SSascha Wildner * | /tmp | 256M | --- | 256M | --- | 253*cdd2d676SSascha Wildner * | /usr | [4G to] 8G | (>160M) rest | 5G | 160M | 254*cdd2d676SSascha Wildner * | /home | rest | --- | 3.5G | --- | 255*cdd2d676SSascha Wildner * +-------+------------+--------------+-----------------+-----------------+ 256*cdd2d676SSascha Wildner * | total | 10G+ | ~430M+ | 9.5G | 300M | 257*cdd2d676SSascha Wildner * +-------+------------+--------------+-----------------+-----------------+ 258*cdd2d676SSascha Wildner */ 259*cdd2d676SSascha Wildner 260*cdd2d676SSascha Wildner static long 261*cdd2d676SSascha Wildner default_capacity(struct storage *s, int mtpt) 262*cdd2d676SSascha Wildner { 263*cdd2d676SSascha Wildner unsigned long swap; 264*cdd2d676SSascha Wildner unsigned long capacity; 265*cdd2d676SSascha Wildner 266*cdd2d676SSascha Wildner if (mtpt == MTPT_HOME) 267*cdd2d676SSascha Wildner return(-1); 268*cdd2d676SSascha Wildner 269*cdd2d676SSascha Wildner capacity = slice_get_capacity(storage_get_selected_slice(s)); 270*cdd2d676SSascha Wildner swap = 2 * storage_get_memsize(s); 271*cdd2d676SSascha Wildner if (storage_get_memsize(s) > (capacity / 2) || capacity < 4096) 272*cdd2d676SSascha Wildner swap = storage_get_memsize(s); 273*cdd2d676SSascha Wildner if (storage_get_memsize(s) > capacity) 274*cdd2d676SSascha Wildner swap = capacity / 2; 275*cdd2d676SSascha Wildner if (swap > 8192) 276*cdd2d676SSascha Wildner swap = 8192; 277*cdd2d676SSascha Wildner 278*cdd2d676SSascha Wildner if (capacity < DISK_MIN) { 279*cdd2d676SSascha Wildner /* 280*cdd2d676SSascha Wildner * For the purposes of this installer: 281*cdd2d676SSascha Wildner * can't be done. Sorry. 282*cdd2d676SSascha Wildner */ 283*cdd2d676SSascha Wildner return(-1); 284*cdd2d676SSascha Wildner } else if (capacity < 523) { 285*cdd2d676SSascha Wildner switch (mtpt) { 286*cdd2d676SSascha Wildner case MTPT_ROOT: return(70); 287*cdd2d676SSascha Wildner case MTPT_SWAP: return(swap); 288*cdd2d676SSascha Wildner case MTPT_VAR: return(32); 289*cdd2d676SSascha Wildner case MTPT_TMP: return(32); 290*cdd2d676SSascha Wildner case MTPT_USR: return(174); 291*cdd2d676SSascha Wildner } 292*cdd2d676SSascha Wildner } else if (capacity < 1024) { 293*cdd2d676SSascha Wildner switch (mtpt) { 294*cdd2d676SSascha Wildner case MTPT_ROOT: return(96); 295*cdd2d676SSascha Wildner case MTPT_SWAP: return(swap); 296*cdd2d676SSascha Wildner case MTPT_VAR: return(64); 297*cdd2d676SSascha Wildner case MTPT_TMP: return(64); 298*cdd2d676SSascha Wildner case MTPT_USR: return(256); 299*cdd2d676SSascha Wildner } 300*cdd2d676SSascha Wildner } else if (capacity < 4096) { 301*cdd2d676SSascha Wildner switch (mtpt) { 302*cdd2d676SSascha Wildner case MTPT_ROOT: return(128); 303*cdd2d676SSascha Wildner case MTPT_SWAP: return(swap); 304*cdd2d676SSascha Wildner case MTPT_VAR: return(128); 305*cdd2d676SSascha Wildner case MTPT_TMP: return(128); 306*cdd2d676SSascha Wildner case MTPT_USR: return(512); 307*cdd2d676SSascha Wildner } 308*cdd2d676SSascha Wildner } else if (capacity < 10240) { 309*cdd2d676SSascha Wildner switch (mtpt) { 310*cdd2d676SSascha Wildner case MTPT_ROOT: return(256); 311*cdd2d676SSascha Wildner case MTPT_SWAP: return(swap); 312*cdd2d676SSascha Wildner case MTPT_VAR: return(256); 313*cdd2d676SSascha Wildner case MTPT_TMP: return(256); 314*cdd2d676SSascha Wildner case MTPT_USR: return(3072); 315*cdd2d676SSascha Wildner } 316*cdd2d676SSascha Wildner } else { 317*cdd2d676SSascha Wildner switch (mtpt) { 318*cdd2d676SSascha Wildner case MTPT_ROOT: return(256); 319*cdd2d676SSascha Wildner case MTPT_SWAP: return(swap); 320*cdd2d676SSascha Wildner case MTPT_VAR: return(256); 321*cdd2d676SSascha Wildner case MTPT_TMP: return(256); 322*cdd2d676SSascha Wildner case MTPT_USR: return(8192); 323*cdd2d676SSascha Wildner } 324*cdd2d676SSascha Wildner } 325*cdd2d676SSascha Wildner /* shouldn't ever happen */ 326*cdd2d676SSascha Wildner return(-1); 327*cdd2d676SSascha Wildner } 328*cdd2d676SSascha Wildner 329*cdd2d676SSascha Wildner static int 330*cdd2d676SSascha Wildner check_capacity(struct i_fn_args *a) 331*cdd2d676SSascha Wildner { 332*cdd2d676SSascha Wildner struct subpartition *sp; 333*cdd2d676SSascha Wildner unsigned long min_capacity[7] = {70, 0, 8, 0, 174, 0, 0}; 334*cdd2d676SSascha Wildner unsigned long total_capacity = 0; 335*cdd2d676SSascha Wildner int mtpt; 336*cdd2d676SSascha Wildner 337*cdd2d676SSascha Wildner if (subpartition_find(storage_get_selected_slice(a->s), "/usr") == NULL) 338*cdd2d676SSascha Wildner min_capacity[MTPT_ROOT] += min_capacity[MTPT_USR]; 339*cdd2d676SSascha Wildner 340*cdd2d676SSascha Wildner for (sp = slice_subpartition_first(storage_get_selected_slice(a->s)); 341*cdd2d676SSascha Wildner sp != NULL; sp = subpartition_next(sp)) { 342*cdd2d676SSascha Wildner if (subpartition_get_capacity(sp) == -1) 343*cdd2d676SSascha Wildner total_capacity++; 344*cdd2d676SSascha Wildner else 345*cdd2d676SSascha Wildner total_capacity += subpartition_get_capacity(sp); 346*cdd2d676SSascha Wildner for (mtpt = 0; def_mountpt[mtpt] != NULL; mtpt++) { 347*cdd2d676SSascha Wildner if (strcmp(subpartition_get_mountpoint(sp), def_mountpt[mtpt]) == 0 && 348*cdd2d676SSascha Wildner min_capacity[mtpt] > 0 && 349*cdd2d676SSascha Wildner subpartition_get_capacity(sp) < min_capacity[mtpt]) { 350*cdd2d676SSascha Wildner inform(a->c, _("WARNING: the %s subpartition should " 351*cdd2d676SSascha Wildner "be at least %dM in size or you will " 352*cdd2d676SSascha Wildner "risk running out of space during " 353*cdd2d676SSascha Wildner "the installation."), 354*cdd2d676SSascha Wildner subpartition_get_mountpoint(sp), min_capacity[mtpt]); 355*cdd2d676SSascha Wildner } 356*cdd2d676SSascha Wildner } 357*cdd2d676SSascha Wildner } 358*cdd2d676SSascha Wildner 359*cdd2d676SSascha Wildner if (total_capacity > slice_get_capacity(storage_get_selected_slice(a->s))) { 360*cdd2d676SSascha Wildner inform(a->c, _("The space allocated to all of your selected " 361*cdd2d676SSascha Wildner "subpartitions (%dM) exceeds the total " 362*cdd2d676SSascha Wildner "capacity of the selected primary partition " 363*cdd2d676SSascha Wildner "(%dM). Remove some subpartitions or choose " 364*cdd2d676SSascha Wildner "a smaller size for them and try again."), 365*cdd2d676SSascha Wildner total_capacity, slice_get_capacity(storage_get_selected_slice(a->s))); 366*cdd2d676SSascha Wildner return(0); 367*cdd2d676SSascha Wildner } 368*cdd2d676SSascha Wildner 369*cdd2d676SSascha Wildner return(1); 370*cdd2d676SSascha Wildner } 371*cdd2d676SSascha Wildner 372*cdd2d676SSascha Wildner static int 373*cdd2d676SSascha Wildner check_subpartition_selections(struct dfui_response *r, struct i_fn_args *a) 374*cdd2d676SSascha Wildner { 375*cdd2d676SSascha Wildner struct dfui_dataset *ds; 376*cdd2d676SSascha Wildner struct dfui_dataset *star_ds = NULL; 377*cdd2d676SSascha Wildner struct aura_dict *d; 378*cdd2d676SSascha Wildner const char *mountpoint, *capstring; 379*cdd2d676SSascha Wildner long capacity = 0; 380*cdd2d676SSascha Wildner long bsize, fsize; 381*cdd2d676SSascha Wildner int found_root = 0; 382*cdd2d676SSascha Wildner int softupdates, mfsbacked; 383*cdd2d676SSascha Wildner int valid = 1; 384*cdd2d676SSascha Wildner 385*cdd2d676SSascha Wildner d = aura_dict_new(1, AURA_DICT_LIST); 386*cdd2d676SSascha Wildner 387*cdd2d676SSascha Wildner if ((ds = dfui_response_dataset_get_first(r)) == NULL) { 388*cdd2d676SSascha Wildner inform(a->c, _("Please set up at least one subpartition.")); 389*cdd2d676SSascha Wildner valid = 0; 390*cdd2d676SSascha Wildner } 391*cdd2d676SSascha Wildner 392*cdd2d676SSascha Wildner for (ds = dfui_response_dataset_get_first(r); valid && ds != NULL; 393*cdd2d676SSascha Wildner ds = dfui_dataset_get_next(ds)) { 394*cdd2d676SSascha Wildner #ifdef DEBUG 395*cdd2d676SSascha Wildner dfui_dataset_dump(ds); 396*cdd2d676SSascha Wildner #endif 397*cdd2d676SSascha Wildner mountpoint = dfui_dataset_get_value(ds, "mountpoint"); 398*cdd2d676SSascha Wildner capstring = dfui_dataset_get_value(ds, "capacity"); 399*cdd2d676SSascha Wildner 400*cdd2d676SSascha Wildner if (expert) { 401*cdd2d676SSascha Wildner softupdates = 402*cdd2d676SSascha Wildner (strcmp(dfui_dataset_get_value(ds, "softupdates"), "Y") == 0); 403*cdd2d676SSascha Wildner fsize = atol(dfui_dataset_get_value(ds, "fsize")); 404*cdd2d676SSascha Wildner bsize = atol(dfui_dataset_get_value(ds, "bsize")); 405*cdd2d676SSascha Wildner mfsbacked = (strcmp(dfui_dataset_get_value(ds, "mfsbacked"), "Y") == 0); 406*cdd2d676SSascha Wildner } else { 407*cdd2d676SSascha Wildner softupdates = (strcmp(mountpoint, "/") == 0 ? 0 : 1); 408*cdd2d676SSascha Wildner mfsbacked = (strcmp(mountpoint, "/tmp") == 0 ? 0 : 1); 409*cdd2d676SSascha Wildner fsize = -1; 410*cdd2d676SSascha Wildner bsize = -1; 411*cdd2d676SSascha Wildner } 412*cdd2d676SSascha Wildner 413*cdd2d676SSascha Wildner if (aura_dict_exists(d, mountpoint, strlen(mountpoint) + 1)) { 414*cdd2d676SSascha Wildner inform(a->c, _("The same mount point cannot be specified " 415*cdd2d676SSascha Wildner "for two different subpartitions.")); 416*cdd2d676SSascha Wildner valid = 0; 417*cdd2d676SSascha Wildner } 418*cdd2d676SSascha Wildner 419*cdd2d676SSascha Wildner if (strcmp(mountpoint, "/") == 0) 420*cdd2d676SSascha Wildner found_root = 1; 421*cdd2d676SSascha Wildner 422*cdd2d676SSascha Wildner if (strcmp(capstring, "*") == 0) { 423*cdd2d676SSascha Wildner if (star_ds != NULL) { 424*cdd2d676SSascha Wildner inform(a->c, _("You cannot have more than one subpartition " 425*cdd2d676SSascha Wildner "with a '*' capacity (meaning 'use the remainder " 426*cdd2d676SSascha Wildner "of the primary partition'.)")); 427*cdd2d676SSascha Wildner valid = 0; 428*cdd2d676SSascha Wildner } else { 429*cdd2d676SSascha Wildner star_ds = ds; 430*cdd2d676SSascha Wildner } 431*cdd2d676SSascha Wildner } 432*cdd2d676SSascha Wildner 433*cdd2d676SSascha Wildner if (!(!strcasecmp(mountpoint, "swap") || mountpoint[0] == '/')) { 434*cdd2d676SSascha Wildner inform(a->c, _("Mount point must be either 'swap', or it must " 435*cdd2d676SSascha Wildner "start with a '/'.")); 436*cdd2d676SSascha Wildner valid = 0; 437*cdd2d676SSascha Wildner } 438*cdd2d676SSascha Wildner 439*cdd2d676SSascha Wildner if (strpbrk(mountpoint, " \\\"'`") != NULL) { 440*cdd2d676SSascha Wildner inform(a->c, _("Mount point may not contain the following " 441*cdd2d676SSascha Wildner "characters: blank space, backslash, or " 442*cdd2d676SSascha Wildner "single, double, or back quotes.")); 443*cdd2d676SSascha Wildner valid = 0; 444*cdd2d676SSascha Wildner } 445*cdd2d676SSascha Wildner 446*cdd2d676SSascha Wildner if (strlen(capstring) == 0) { 447*cdd2d676SSascha Wildner inform(a->c, _("A capacity must be specified.")); 448*cdd2d676SSascha Wildner valid = 0; 449*cdd2d676SSascha Wildner } 450*cdd2d676SSascha Wildner 451*cdd2d676SSascha Wildner if (!string_to_capacity(capstring, &capacity)) { 452*cdd2d676SSascha Wildner inform(a->c, _("Capacity must be either a '*' symbol to indicate " 453*cdd2d676SSascha Wildner "'use the rest of the primary partition', or it " 454*cdd2d676SSascha Wildner "must be a series of decimal digits ending with a " 455*cdd2d676SSascha Wildner "'M' (indicating megabytes) or a 'G' (indicating " 456*cdd2d676SSascha Wildner "gigabytes.)")); 457*cdd2d676SSascha Wildner valid = 0; 458*cdd2d676SSascha Wildner } 459*cdd2d676SSascha Wildner 460*cdd2d676SSascha Wildner if ((strcasecmp(mountpoint, "swap") == 0) && (capacity > 8192)) { 461*cdd2d676SSascha Wildner inform(a->c, _("Swap capacity is limited to 8G.")); 462*cdd2d676SSascha Wildner valid = 0; 463*cdd2d676SSascha Wildner } 464*cdd2d676SSascha Wildner 465*cdd2d676SSascha Wildner /* 466*cdd2d676SSascha Wildner * If we made it through that obstacle course, all is well. 467*cdd2d676SSascha Wildner */ 468*cdd2d676SSascha Wildner 469*cdd2d676SSascha Wildner if (valid) 470*cdd2d676SSascha Wildner aura_dict_store(d, mountpoint, strlen(mountpoint) + 1, "", 1); 471*cdd2d676SSascha Wildner } 472*cdd2d676SSascha Wildner 473*cdd2d676SSascha Wildner if (!found_root) { 474*cdd2d676SSascha Wildner inform(a->c, _("You must include a / (root) subpartition.")); 475*cdd2d676SSascha Wildner valid = 0; 476*cdd2d676SSascha Wildner } 477*cdd2d676SSascha Wildner 478*cdd2d676SSascha Wildner if (aura_dict_size(d) > 16) { 479*cdd2d676SSascha Wildner inform(a->c, _("You cannot have more than 16 subpartitions " 480*cdd2d676SSascha Wildner "on a single primary partition. Remove some " 481*cdd2d676SSascha Wildner "and try again.")); 482*cdd2d676SSascha Wildner valid = 0; 483*cdd2d676SSascha Wildner } 484*cdd2d676SSascha Wildner 485*cdd2d676SSascha Wildner aura_dict_free(d); 486*cdd2d676SSascha Wildner 487*cdd2d676SSascha Wildner return(valid); 488*cdd2d676SSascha Wildner } 489*cdd2d676SSascha Wildner 490*cdd2d676SSascha Wildner static void 491*cdd2d676SSascha Wildner save_subpartition_selections(struct dfui_response *r, struct i_fn_args *a) 492*cdd2d676SSascha Wildner { 493*cdd2d676SSascha Wildner struct dfui_dataset *ds; 494*cdd2d676SSascha Wildner char mfsbacked; 495*cdd2d676SSascha Wildner const char *mountpoint, *capstring; 496*cdd2d676SSascha Wildner long capacity; 497*cdd2d676SSascha Wildner long bsize, fsize; 498*cdd2d676SSascha Wildner int softupdates; 499*cdd2d676SSascha Wildner int valid = 1; 500*cdd2d676SSascha Wildner 501*cdd2d676SSascha Wildner subpartitions_free(storage_get_selected_slice(a->s)); 502*cdd2d676SSascha Wildner 503*cdd2d676SSascha Wildner for (ds = dfui_response_dataset_get_first(r); valid && ds != NULL; 504*cdd2d676SSascha Wildner ds = dfui_dataset_get_next(ds)) { 505*cdd2d676SSascha Wildner mountpoint = dfui_dataset_get_value(ds, "mountpoint"); 506*cdd2d676SSascha Wildner capstring = dfui_dataset_get_value(ds, "capacity"); 507*cdd2d676SSascha Wildner 508*cdd2d676SSascha Wildner if (expert) { 509*cdd2d676SSascha Wildner softupdates = 510*cdd2d676SSascha Wildner (strcmp(dfui_dataset_get_value(ds, "softupdates"), "Y") == 0); 511*cdd2d676SSascha Wildner fsize = atol(dfui_dataset_get_value(ds, "fsize")); 512*cdd2d676SSascha Wildner bsize = atol(dfui_dataset_get_value(ds, "bsize")); 513*cdd2d676SSascha Wildner mfsbacked = (strcmp(dfui_dataset_get_value(ds, "mfsbacked"), "Y") == 0); 514*cdd2d676SSascha Wildner } else { 515*cdd2d676SSascha Wildner softupdates = (strcmp(mountpoint, "/") == 0 ? 0 : 1); 516*cdd2d676SSascha Wildner mfsbacked = 0; 517*cdd2d676SSascha Wildner fsize = -1; 518*cdd2d676SSascha Wildner bsize = -1; 519*cdd2d676SSascha Wildner } 520*cdd2d676SSascha Wildner 521*cdd2d676SSascha Wildner if (string_to_capacity(capstring, &capacity)) { 522*cdd2d676SSascha Wildner subpartition_new(storage_get_selected_slice(a->s), mountpoint, capacity, 523*cdd2d676SSascha Wildner softupdates, fsize, bsize, mfsbacked); 524*cdd2d676SSascha Wildner } 525*cdd2d676SSascha Wildner } 526*cdd2d676SSascha Wildner } 527*cdd2d676SSascha Wildner 528*cdd2d676SSascha Wildner static void 529*cdd2d676SSascha Wildner populate_create_subpartitions_form(struct dfui_form *f, struct i_fn_args *a) 530*cdd2d676SSascha Wildner { 531*cdd2d676SSascha Wildner struct subpartition *sp; 532*cdd2d676SSascha Wildner struct dfui_dataset *ds; 533*cdd2d676SSascha Wildner char temp[32]; 534*cdd2d676SSascha Wildner int mtpt; 535*cdd2d676SSascha Wildner long capacity; 536*cdd2d676SSascha Wildner 537*cdd2d676SSascha Wildner if (slice_subpartition_first(storage_get_selected_slice(a->s)) != NULL) { 538*cdd2d676SSascha Wildner /* 539*cdd2d676SSascha Wildner * The user has already given us their subpartition 540*cdd2d676SSascha Wildner * preferences, so use them here. 541*cdd2d676SSascha Wildner */ 542*cdd2d676SSascha Wildner for (sp = slice_subpartition_first(storage_get_selected_slice(a->s)); 543*cdd2d676SSascha Wildner sp != NULL; sp = subpartition_next(sp)) { 544*cdd2d676SSascha Wildner ds = dfui_dataset_new(); 545*cdd2d676SSascha Wildner dfui_dataset_celldata_add(ds, "mountpoint", 546*cdd2d676SSascha Wildner subpartition_get_mountpoint(sp)); 547*cdd2d676SSascha Wildner dfui_dataset_celldata_add(ds, "capacity", 548*cdd2d676SSascha Wildner capacity_to_string(subpartition_get_capacity(sp))); 549*cdd2d676SSascha Wildner if (expert) { 550*cdd2d676SSascha Wildner dfui_dataset_celldata_add(ds, "softupdates", 551*cdd2d676SSascha Wildner subpartition_is_softupdated(sp) ? "Y" : "N"); 552*cdd2d676SSascha Wildner dfui_dataset_celldata_add(ds, "mfsbacked", 553*cdd2d676SSascha Wildner subpartition_is_mfsbacked(sp) ? "Y" : "N"); 554*cdd2d676SSascha Wildner snprintf(temp, 32, "%ld", subpartition_get_fsize(sp)); 555*cdd2d676SSascha Wildner dfui_dataset_celldata_add(ds, "fsize", 556*cdd2d676SSascha Wildner temp); 557*cdd2d676SSascha Wildner snprintf(temp, 32, "%ld", subpartition_get_bsize(sp)); 558*cdd2d676SSascha Wildner dfui_dataset_celldata_add(ds, "bsize", 559*cdd2d676SSascha Wildner temp); 560*cdd2d676SSascha Wildner } 561*cdd2d676SSascha Wildner dfui_form_dataset_add(f, ds); 562*cdd2d676SSascha Wildner } 563*cdd2d676SSascha Wildner } else { 564*cdd2d676SSascha Wildner /* 565*cdd2d676SSascha Wildner * Otherwise, populate the form with datasets representing 566*cdd2d676SSascha Wildner * reasonably-calculated defaults. The defaults are chosen 567*cdd2d676SSascha Wildner * based on the slice's total capacity and the machine's 568*cdd2d676SSascha Wildner * total physical memory (for swap.) 569*cdd2d676SSascha Wildner */ 570*cdd2d676SSascha Wildner for (mtpt = 0; def_mountpt[mtpt] != NULL; mtpt++) { 571*cdd2d676SSascha Wildner capacity = default_capacity(a->s, mtpt); 572*cdd2d676SSascha Wildner ds = dfui_dataset_new(); 573*cdd2d676SSascha Wildner dfui_dataset_celldata_add(ds, "mountpoint", 574*cdd2d676SSascha Wildner def_mountpt[mtpt]); 575*cdd2d676SSascha Wildner dfui_dataset_celldata_add(ds, "capacity", 576*cdd2d676SSascha Wildner capacity_to_string(capacity)); 577*cdd2d676SSascha Wildner if (expert) { 578*cdd2d676SSascha Wildner dfui_dataset_celldata_add(ds, "softupdates", 579*cdd2d676SSascha Wildner strcmp(def_mountpt[mtpt], "/") != 0 ? "Y" : "N"); 580*cdd2d676SSascha Wildner dfui_dataset_celldata_add(ds, "mfsbacked", 581*cdd2d676SSascha Wildner "N"); 582*cdd2d676SSascha Wildner dfui_dataset_celldata_add(ds, "fsize", 583*cdd2d676SSascha Wildner capacity < 1024 ? "1024" : "2048"); 584*cdd2d676SSascha Wildner dfui_dataset_celldata_add(ds, "bsize", 585*cdd2d676SSascha Wildner capacity < 1024 ? "8192" : "16384"); 586*cdd2d676SSascha Wildner } 587*cdd2d676SSascha Wildner dfui_form_dataset_add(f, ds); 588*cdd2d676SSascha Wildner } 589*cdd2d676SSascha Wildner } 590*cdd2d676SSascha Wildner } 591*cdd2d676SSascha Wildner 592*cdd2d676SSascha Wildner static int 593*cdd2d676SSascha Wildner warn_subpartition_selections(struct i_fn_args *a) 594*cdd2d676SSascha Wildner { 595*cdd2d676SSascha Wildner int valid = 0; 596*cdd2d676SSascha Wildner struct aura_buffer *omit, *consequences; 597*cdd2d676SSascha Wildner 598*cdd2d676SSascha Wildner omit = aura_buffer_new(2048); 599*cdd2d676SSascha Wildner consequences = aura_buffer_new(2048); 600*cdd2d676SSascha Wildner 601*cdd2d676SSascha Wildner valid = check_capacity(a); 602*cdd2d676SSascha Wildner if (subpartition_find(storage_get_selected_slice(a->s), "/var") == NULL) { 603*cdd2d676SSascha Wildner aura_buffer_cat(omit, "/var "); 604*cdd2d676SSascha Wildner aura_buffer_cat(consequences, _("/var will be a plain dir in /\n")); 605*cdd2d676SSascha Wildner } 606*cdd2d676SSascha Wildner if (subpartition_find(storage_get_selected_slice(a->s), "/usr") == NULL) { 607*cdd2d676SSascha Wildner aura_buffer_cat(omit, "/usr "); 608*cdd2d676SSascha Wildner aura_buffer_cat(consequences, _("/usr will be a plain dir in /\n")); 609*cdd2d676SSascha Wildner } 610*cdd2d676SSascha Wildner if (subpartition_find(storage_get_selected_slice(a->s), "/tmp") == NULL) { 611*cdd2d676SSascha Wildner aura_buffer_cat(omit, "/tmp "); 612*cdd2d676SSascha Wildner aura_buffer_cat(consequences, _("/tmp will be symlinked to /var/tmp\n")); 613*cdd2d676SSascha Wildner } 614*cdd2d676SSascha Wildner if (subpartition_find(storage_get_selected_slice(a->s), "/home") == NULL) { 615*cdd2d676SSascha Wildner aura_buffer_cat(omit, "/home "); 616*cdd2d676SSascha Wildner aura_buffer_cat(consequences, _("/home will be symlinked to /usr/home\n")); 617*cdd2d676SSascha Wildner } 618*cdd2d676SSascha Wildner 619*cdd2d676SSascha Wildner if (valid && aura_buffer_len(omit) > 0) { 620*cdd2d676SSascha Wildner switch (dfui_be_present_dialog(a->c, _("Really omit?"), 621*cdd2d676SSascha Wildner _("Omit Subpartition(s)|Return to Create Subpartitions"), 622*cdd2d676SSascha Wildner _("You have elected to not have the following " 623*cdd2d676SSascha Wildner "subpartition(s):\n\n%s\n\n" 624*cdd2d676SSascha Wildner "The ramifications of these subpartition(s) being " 625*cdd2d676SSascha Wildner "missing will be:\n\n%s\n" 626*cdd2d676SSascha Wildner "Is this really what you want to do?"), 627*cdd2d676SSascha Wildner aura_buffer_buf(omit), aura_buffer_buf(consequences))) { 628*cdd2d676SSascha Wildner case 1: 629*cdd2d676SSascha Wildner valid = 1; 630*cdd2d676SSascha Wildner break; 631*cdd2d676SSascha Wildner case 2: 632*cdd2d676SSascha Wildner valid = 0; 633*cdd2d676SSascha Wildner break; 634*cdd2d676SSascha Wildner default: 635*cdd2d676SSascha Wildner abort_backend(); 636*cdd2d676SSascha Wildner } 637*cdd2d676SSascha Wildner } 638*cdd2d676SSascha Wildner 639*cdd2d676SSascha Wildner aura_buffer_free(omit); 640*cdd2d676SSascha Wildner aura_buffer_free(consequences); 641*cdd2d676SSascha Wildner 642*cdd2d676SSascha Wildner return(!valid); 643*cdd2d676SSascha Wildner } 644*cdd2d676SSascha Wildner 645*cdd2d676SSascha Wildner static struct dfui_form * 646*cdd2d676SSascha Wildner make_create_subpartitions_form(struct i_fn_args *a) 647*cdd2d676SSascha Wildner { 648*cdd2d676SSascha Wildner struct dfui_field *fi; 649*cdd2d676SSascha Wildner struct dfui_form *f; 650*cdd2d676SSascha Wildner char msg_buf[1][1024]; 651*cdd2d676SSascha Wildner 652*cdd2d676SSascha Wildner snprintf(msg_buf[0], sizeof(msg_buf[0]), 653*cdd2d676SSascha Wildner _("Subpartitions further divide a primary partition for " 654*cdd2d676SSascha Wildner "use with %s. Some reasons you may want " 655*cdd2d676SSascha Wildner "a set of subpartitions are:\n\n" 656*cdd2d676SSascha Wildner "- you want to restrict how much data can be written " 657*cdd2d676SSascha Wildner "to certain parts of the primary partition, to quell " 658*cdd2d676SSascha Wildner "denial-of-service attacks; and\n" 659*cdd2d676SSascha Wildner "- you want to speed up access to data on the disk." 660*cdd2d676SSascha Wildner ""), OPERATING_SYSTEM_NAME); 661*cdd2d676SSascha Wildner 662*cdd2d676SSascha Wildner f = dfui_form_create( 663*cdd2d676SSascha Wildner "create_subpartitions", 664*cdd2d676SSascha Wildner _("Create Subpartitions"), 665*cdd2d676SSascha Wildner _("Set up the subpartitions (also known as just `partitions' " 666*cdd2d676SSascha Wildner "in BSD tradition) you want to have on this primary " 667*cdd2d676SSascha Wildner "partition.\n\n" 668*cdd2d676SSascha Wildner "For Capacity, use 'M' to indicate megabytes, 'G' to " 669*cdd2d676SSascha Wildner "indicate gigabytes, or a single '*' to indicate " 670*cdd2d676SSascha Wildner "'use the remaining space on the primary partition'."), 671*cdd2d676SSascha Wildner 672*cdd2d676SSascha Wildner msg_buf[0], 673*cdd2d676SSascha Wildner 674*cdd2d676SSascha Wildner "p", "special", "dfinstaller_create_subpartitions", 675*cdd2d676SSascha Wildner "p", "minimum_width","64", 676*cdd2d676SSascha Wildner 677*cdd2d676SSascha Wildner "f", "mountpoint", _("Mountpoint"), "", "", 678*cdd2d676SSascha Wildner "f", "capacity", _("Capacity"), "", "", 679*cdd2d676SSascha Wildner 680*cdd2d676SSascha Wildner "a", "ok", _("Accept and Create"), "", "", 681*cdd2d676SSascha Wildner "a", "cancel", 682*cdd2d676SSascha Wildner (disk_get_formatted(storage_get_selected_disk(a->s)) ? 683*cdd2d676SSascha Wildner _("Return to Select Disk") : 684*cdd2d676SSascha Wildner _("Return to Select Primary Partition")), "", "", 685*cdd2d676SSascha Wildner "p", "accelerator", "ESC", 686*cdd2d676SSascha Wildner 687*cdd2d676SSascha Wildner NULL 688*cdd2d676SSascha Wildner ); 689*cdd2d676SSascha Wildner 690*cdd2d676SSascha Wildner dfui_form_set_multiple(f, 1); 691*cdd2d676SSascha Wildner dfui_form_set_extensible(f, 1); 692*cdd2d676SSascha Wildner 693*cdd2d676SSascha Wildner if (expert) { 694*cdd2d676SSascha Wildner fi = dfui_form_field_add(f, "softupdates", 695*cdd2d676SSascha Wildner dfui_info_new(_("Softupdates"), "", "")); 696*cdd2d676SSascha Wildner dfui_field_property_set(fi, "control", "checkbox"); 697*cdd2d676SSascha Wildner 698*cdd2d676SSascha Wildner fi = dfui_form_field_add(f, "mfsbacked", 699*cdd2d676SSascha Wildner dfui_info_new(_("MFS"), "", "")); 700*cdd2d676SSascha Wildner dfui_field_property_set(fi, "control", "checkbox"); 701*cdd2d676SSascha Wildner 702*cdd2d676SSascha Wildner fi = dfui_form_field_add(f, "fsize", 703*cdd2d676SSascha Wildner dfui_info_new(_("Frag Sz"), "", "")); 704*cdd2d676SSascha Wildner 705*cdd2d676SSascha Wildner fi = dfui_form_field_add(f, "bsize", 706*cdd2d676SSascha Wildner dfui_info_new(_("Block Sz"), "", "")); 707*cdd2d676SSascha Wildner 708*cdd2d676SSascha Wildner dfui_form_action_add(f, "switch", 709*cdd2d676SSascha Wildner dfui_info_new(_("Switch to Normal Mode"), "", "")); 710*cdd2d676SSascha Wildner } else { 711*cdd2d676SSascha Wildner dfui_form_action_add(f, "switch", 712*cdd2d676SSascha Wildner dfui_info_new(_("Switch to Expert Mode"), "", "")); 713*cdd2d676SSascha Wildner } 714*cdd2d676SSascha Wildner 715*cdd2d676SSascha Wildner return(f); 716*cdd2d676SSascha Wildner } 717*cdd2d676SSascha Wildner 718*cdd2d676SSascha Wildner /* 719*cdd2d676SSascha Wildner * Returns: 720*cdd2d676SSascha Wildner * -1 = the form should be redisplayed 721*cdd2d676SSascha Wildner * 0 = failure, function is over 722*cdd2d676SSascha Wildner * 1 = success, function is over 723*cdd2d676SSascha Wildner */ 724*cdd2d676SSascha Wildner static int 725*cdd2d676SSascha Wildner show_create_subpartitions_form(struct dfui_form *f, struct i_fn_args *a) 726*cdd2d676SSascha Wildner { 727*cdd2d676SSascha Wildner struct dfui_dataset *ds; 728*cdd2d676SSascha Wildner struct dfui_response *r; 729*cdd2d676SSascha Wildner 730*cdd2d676SSascha Wildner for (;;) { 731*cdd2d676SSascha Wildner if (dfui_form_dataset_get_first(f) == NULL) 732*cdd2d676SSascha Wildner populate_create_subpartitions_form(f, a); 733*cdd2d676SSascha Wildner 734*cdd2d676SSascha Wildner if (!dfui_be_present(a->c, f, &r)) 735*cdd2d676SSascha Wildner abort_backend(); 736*cdd2d676SSascha Wildner 737*cdd2d676SSascha Wildner if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) { 738*cdd2d676SSascha Wildner dfui_response_free(r); 739*cdd2d676SSascha Wildner return(0); 740*cdd2d676SSascha Wildner } else if (strcmp(dfui_response_get_action_id(r), "switch") == 0) { 741*cdd2d676SSascha Wildner if (check_subpartition_selections(r, a)) { 742*cdd2d676SSascha Wildner save_subpartition_selections(r, a); 743*cdd2d676SSascha Wildner expert = expert ? 0 : 1; 744*cdd2d676SSascha Wildner dfui_response_free(r); 745*cdd2d676SSascha Wildner return(-1); 746*cdd2d676SSascha Wildner } 747*cdd2d676SSascha Wildner } else { 748*cdd2d676SSascha Wildner if (check_subpartition_selections(r, a)) { 749*cdd2d676SSascha Wildner save_subpartition_selections(r, a); 750*cdd2d676SSascha Wildner if (!warn_subpartition_selections(a)) { 751*cdd2d676SSascha Wildner if (!create_subpartitions(a)) { 752*cdd2d676SSascha Wildner inform(a->c, _("The subpartitions you chose were " 753*cdd2d676SSascha Wildner "not correctly created, and the " 754*cdd2d676SSascha Wildner "primary partition may " 755*cdd2d676SSascha Wildner "now be in an inconsistent state. " 756*cdd2d676SSascha Wildner "We recommend re-formatting it " 757*cdd2d676SSascha Wildner "before proceeding.")); 758*cdd2d676SSascha Wildner dfui_response_free(r); 759*cdd2d676SSascha Wildner return(0); 760*cdd2d676SSascha Wildner } else { 761*cdd2d676SSascha Wildner dfui_response_free(r); 762*cdd2d676SSascha Wildner return(1); 763*cdd2d676SSascha Wildner } 764*cdd2d676SSascha Wildner } 765*cdd2d676SSascha Wildner } 766*cdd2d676SSascha Wildner } 767*cdd2d676SSascha Wildner 768*cdd2d676SSascha Wildner dfui_form_datasets_free(f); 769*cdd2d676SSascha Wildner /* dfui_form_datasets_add_from_response(f, r); */ 770*cdd2d676SSascha Wildner for (ds = dfui_response_dataset_get_first(r); ds != NULL; 771*cdd2d676SSascha Wildner ds = dfui_dataset_get_next(ds)) { 772*cdd2d676SSascha Wildner dfui_form_dataset_add(f, dfui_dataset_dup(ds)); 773*cdd2d676SSascha Wildner } 774*cdd2d676SSascha Wildner } 775*cdd2d676SSascha Wildner } 776*cdd2d676SSascha Wildner 777*cdd2d676SSascha Wildner /* 778*cdd2d676SSascha Wildner * fn_create_subpartitions: let the user specify what subpartitions they 779*cdd2d676SSascha Wildner * want on the disk, how large each should be, and where it should be mounted. 780*cdd2d676SSascha Wildner */ 781*cdd2d676SSascha Wildner void 782*cdd2d676SSascha Wildner fn_create_subpartitions(struct i_fn_args *a) 783*cdd2d676SSascha Wildner { 784*cdd2d676SSascha Wildner struct commands *cmds; 785*cdd2d676SSascha Wildner 786*cdd2d676SSascha Wildner cmds = commands_new(); 787*cdd2d676SSascha Wildner 788*cdd2d676SSascha Wildner /* 789*cdd2d676SSascha Wildner * Auto-disklabel the slice. 790*cdd2d676SSascha Wildner * NB: one cannot use "/dev/adXsY" here - 791*cdd2d676SSascha Wildner * it must be in the form "adXsY". 792*cdd2d676SSascha Wildner */ 793*cdd2d676SSascha Wildner if (use_hammer == 1) { 794*cdd2d676SSascha Wildner command_add(cmds, "%s%s if=/dev/zero of=/dev/%s bs=32k count=16", 795*cdd2d676SSascha Wildner a->os_root, cmd_name(a, "DD"), 796*cdd2d676SSascha Wildner slice_get_raw_device_name(storage_get_selected_slice(a->s))); 797*cdd2d676SSascha Wildner command_add(cmds, "%s%s -B -r -w %s auto", 798*cdd2d676SSascha Wildner a->os_root, cmd_name(a, "DISKLABEL64"), 799*cdd2d676SSascha Wildner slice_get_raw_device_name(storage_get_selected_slice(a->s))); 800*cdd2d676SSascha Wildner commands_execute(a, cmds); 801*cdd2d676SSascha Wildner commands_free(cmds); 802*cdd2d676SSascha Wildner fn_create_subpartitions_hammer(a); 803*cdd2d676SSascha Wildner } else { 804*cdd2d676SSascha Wildner command_add(cmds, "%s%s if=/dev/zero of=/dev/%s bs=32k count=16", 805*cdd2d676SSascha Wildner a->os_root, cmd_name(a, "DD"), 806*cdd2d676SSascha Wildner slice_get_raw_device_name(storage_get_selected_slice(a->s))); 807*cdd2d676SSascha Wildner command_add(cmds, "%s%s -B -r -w %s auto", 808*cdd2d676SSascha Wildner a->os_root, cmd_name(a, "DISKLABEL"), 809*cdd2d676SSascha Wildner slice_get_raw_device_name(storage_get_selected_slice(a->s))); 810*cdd2d676SSascha Wildner commands_execute(a, cmds); 811*cdd2d676SSascha Wildner commands_free(cmds); 812*cdd2d676SSascha Wildner fn_create_subpartitions_ufs(a); 813*cdd2d676SSascha Wildner } 814*cdd2d676SSascha Wildner } 815*cdd2d676SSascha Wildner 816*cdd2d676SSascha Wildner void 817*cdd2d676SSascha Wildner fn_create_subpartitions_ufs(struct i_fn_args *a) 818*cdd2d676SSascha Wildner { 819*cdd2d676SSascha Wildner struct dfui_form *f; 820*cdd2d676SSascha Wildner int done = 0; 821*cdd2d676SSascha Wildner 822*cdd2d676SSascha Wildner a->result = 0; 823*cdd2d676SSascha Wildner while (!done) { 824*cdd2d676SSascha Wildner f = make_create_subpartitions_form(a); 825*cdd2d676SSascha Wildner switch (show_create_subpartitions_form(f, a)) { 826*cdd2d676SSascha Wildner case -1: 827*cdd2d676SSascha Wildner done = 0; 828*cdd2d676SSascha Wildner break; 829*cdd2d676SSascha Wildner case 0: 830*cdd2d676SSascha Wildner done = 1; 831*cdd2d676SSascha Wildner a->result = 0; 832*cdd2d676SSascha Wildner break; 833*cdd2d676SSascha Wildner case 1: 834*cdd2d676SSascha Wildner done = 1; 835*cdd2d676SSascha Wildner a->result = 1; 836*cdd2d676SSascha Wildner break; 837*cdd2d676SSascha Wildner } 838*cdd2d676SSascha Wildner dfui_form_free(f); 839*cdd2d676SSascha Wildner } 840*cdd2d676SSascha Wildner } 841