label.c revision 88996
18549Sjkh/* 28549Sjkh * The new sysinstall program. 38549Sjkh * 48549Sjkh * This is probably the last program in the `sysinstall' line - the next 58549Sjkh * generation being essentially a complete rewrite. 68549Sjkh * 750479Speter * $FreeBSD: head/usr.sbin/sysinstall/label.c 88996 2002-01-07 07:51:24Z dillon $ 88549Sjkh * 98549Sjkh * Copyright (c) 1995 108549Sjkh * Jordan Hubbard. All rights reserved. 118549Sjkh * 128549Sjkh * Redistribution and use in source and binary forms, with or without 138549Sjkh * modification, are permitted provided that the following conditions 148549Sjkh * are met: 158549Sjkh * 1. Redistributions of source code must retain the above copyright 168881Srgrimes * notice, this list of conditions and the following disclaimer, 178881Srgrimes * verbatim and that no modifications are made prior to this 188549Sjkh * point in the file. 198549Sjkh * 2. Redistributions in binary form must reproduce the above copyright 208549Sjkh * notice, this list of conditions and the following disclaimer in the 218549Sjkh * documentation and/or other materials provided with the distribution. 228549Sjkh * 238549Sjkh * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND 248549Sjkh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 258549Sjkh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 268549Sjkh * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE 278549Sjkh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 288549Sjkh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 298549Sjkh * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) 308549Sjkh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 318549Sjkh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 328549Sjkh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 338549Sjkh * SUCH DAMAGE. 348549Sjkh * 358549Sjkh */ 368549Sjkh 378549Sjkh#include "sysinstall.h" 388549Sjkh#include <ctype.h> 398549Sjkh#include <sys/disklabel.h> 4010882Speter#include <sys/param.h> 4110882Speter#include <sys/sysctl.h> 428549Sjkh 4388996Sdillon#define AUTO_HOME 0 /* do not create /home automatically */ 4488996Sdillon 458549Sjkh/* 468549Sjkh * Everything to do with editing the contents of disk labels. 478549Sjkh */ 488549Sjkh 498549Sjkh/* A nice message we use a lot in the disklabel editor */ 508549Sjkh#define MSG_NOT_APPLICABLE "That option is not applicable here" 518549Sjkh 528549Sjkh/* Where to start printing the freebsd slices */ 538549Sjkh#define CHUNK_SLICE_START_ROW 2 548622Sjkh#define CHUNK_PART_START_ROW 11 558549Sjkh 568549Sjkh/* The smallest filesystem we're willing to create */ 578702Sjkh#define FS_MIN_SIZE ONE_MEG 588549Sjkh 5987557Sdillon/* 6087557Sdillon * Minimum partition sizes 6187557Sdillon */ 6244601Sjkh#ifdef __alpha__ 6345127Sjkh#define ROOT_MIN_SIZE 40 6444601Sjkh#else 6545127Sjkh#define ROOT_MIN_SIZE 30 6644601Sjkh#endif 6787557Sdillon#define SWAP_MIN_SIZE 32 6887557Sdillon#define USR_MIN_SIZE 80 6987557Sdillon#define VAR_MIN_SIZE 20 7087583Sdillon#define TMP_MIN_SIZE 20 7187557Sdillon#define HOME_MIN_SIZE 20 728549Sjkh 7387557Sdillon/* 7487557Sdillon * Swap size limit for auto-partitioning (4G). 7587557Sdillon */ 7687557Sdillon#define SWAP_AUTO_LIMIT_SIZE 4096 7744601Sjkh 7887557Sdillon/* 7987557Sdillon * Default partition sizes. If we do not have sufficient disk space 8087557Sdillon * for this configuration we scale things relative to the NOM vs DEFAULT 8187557Sdillon * sizes. If the disk is larger then /home will get any remaining space. 8287557Sdillon */ 8387557Sdillon#define ROOT_DEFAULT_SIZE 128 8487557Sdillon#define USR_DEFAULT_SIZE 3072 8587557Sdillon#define VAR_DEFAULT_SIZE 256 8687583Sdillon#define TMP_DEFAULT_SIZE 256 8787557Sdillon#define HOME_DEFAULT_SIZE USR_DEFAULT_SIZE 8812661Speter 8987557Sdillon/* 9087557Sdillon * Nominal partition sizes. These are used to scale the default sizes down 9187557Sdillon * when we have insufficient disk space. If this isn't sufficient we scale 9287557Sdillon * down using the MIN sizes instead. 9387557Sdillon */ 9487557Sdillon#define ROOT_NOMINAL_SIZE 128 9587557Sdillon#define USR_NOMINAL_SIZE 512 9687557Sdillon#define VAR_NOMINAL_SIZE 64 9787583Sdillon#define TMP_NOMINAL_SIZE 64 9887557Sdillon#define HOME_NOMINAL_SIZE USR_NOMINAL_SIZE 9912661Speter 10015440Sjkh/* The bottom-most row we're allowed to scribble on */ 10129249Sjkh#define CHUNK_ROW_MAX 16 10215440Sjkh 10315440Sjkh 1048549Sjkh/* All the chunks currently displayed on the screen */ 1058549Sjkhstatic struct { 1068549Sjkh struct chunk *c; 1078549Sjkh PartType type; 1088549Sjkh} label_chunk_info[MAX_CHUNKS + 1]; 1098549Sjkhstatic int here; 1108549Sjkh 11129249Sjkh/*** with this value we try to track the most recently added label ***/ 11229249Sjkhstatic int label_focus = 0, pslice_focus = 0; 11329249Sjkh 11430345Sjkhstatic int diskLabel(Device *dev); 11530345Sjkhstatic int diskLabelNonInteractive(Device *dev); 11687557Sdillonstatic char *try_auto_label(Device **devs, Device *dev, int perc, int *req); 11712661Speter 11830345Sjkhstatic int 11930345SjkhlabelHook(dialogMenuItem *selected) 12030345Sjkh{ 12130345Sjkh Device **devs = NULL; 12230345Sjkh 12330345Sjkh devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK); 12430345Sjkh if (!devs) { 12530345Sjkh msgConfirm("Unable to find disk %s!", selected->prompt); 12630345Sjkh return DITEM_FAILURE; 12730345Sjkh } 12830345Sjkh /* Toggle enabled status? */ 12930345Sjkh if (!devs[0]->enabled) { 13030345Sjkh devs[0]->enabled = TRUE; 13130345Sjkh diskLabel(devs[0]); 13230345Sjkh } 13330345Sjkh else 13430345Sjkh devs[0]->enabled = FALSE; 13554587Sjkh return DITEM_SUCCESS; 13630345Sjkh} 13730345Sjkh 13830345Sjkhstatic int 13930345SjkhlabelCheck(dialogMenuItem *selected) 14030345Sjkh{ 14130345Sjkh Device **devs = NULL; 14230345Sjkh 14330345Sjkh devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK); 14430345Sjkh if (!devs || devs[0]->enabled == FALSE) 14530345Sjkh return FALSE; 14630345Sjkh return TRUE; 14730345Sjkh} 14830345Sjkh 14912661Speterint 15015091SjkhdiskLabelEditor(dialogMenuItem *self) 15112661Speter{ 15230345Sjkh DMenu *menu; 15312661Speter Device **devs; 15430345Sjkh int i, cnt; 15512661Speter 15630345Sjkh i = 0; 15730345Sjkh cnt = diskGetSelectCount(&devs); 15830345Sjkh if (cnt == -1) { 15912661Speter msgConfirm("No disks found! Please verify that your disk controller is being\n" 16012661Speter "properly probed at boot time. See the Hardware Guide on the\n" 16112661Speter "Documentation menu for clues on diagnosing this type of problem."); 16215242Sjkh return DITEM_FAILURE; 16312661Speter } 16430345Sjkh else if (cnt) { 16530345Sjkh /* Some are already selected */ 16630381Sjkh if (variable_get(VAR_NONINTERACTIVE)) 16734543Sjkh i = diskLabelNonInteractive(NULL); 16830381Sjkh else 16934543Sjkh i = diskLabel(NULL); 17012661Speter } 17130345Sjkh else { 17230345Sjkh /* No disks are selected, fall-back case now */ 17330345Sjkh cnt = deviceCount(devs); 17430345Sjkh if (cnt == 1) { 17530345Sjkh devs[0]->enabled = TRUE; 17630345Sjkh if (variable_get(VAR_NONINTERACTIVE)) 17730345Sjkh i = diskLabelNonInteractive(devs[0]); 17830345Sjkh else 17930345Sjkh i = diskLabel(devs[0]); 18030345Sjkh } 18130345Sjkh else { 18230345Sjkh menu = deviceCreateMenu(&MenuDiskDevices, DEVICE_TYPE_DISK, labelHook, labelCheck); 18330345Sjkh if (!menu) { 18430345Sjkh msgConfirm("No devices suitable for installation found!\n\n" 18530345Sjkh "Please verify that your disk controller (and attached drives)\n" 18630345Sjkh "were detected properly. This can be done by pressing the\n" 18730345Sjkh "[Scroll Lock] key and using the Arrow keys to move back to\n" 18830345Sjkh "the boot messages. Press [Scroll Lock] again to return."); 18930345Sjkh i = DITEM_FAILURE; 19030345Sjkh } 19130345Sjkh else { 19230345Sjkh i = dmenuOpenSimple(menu, FALSE) ? DITEM_SUCCESS : DITEM_FAILURE; 19330345Sjkh free(menu); 19430345Sjkh } 19530345Sjkh } 19612661Speter } 19718744Sjkh if (DITEM_STATUS(i) != DITEM_FAILURE) { 19874156Sjkh if (variable_cmp(DISK_LABELLED, "written")) 19943685Sjkh variable_set2(DISK_LABELLED, "yes", 0); 20018744Sjkh } 20112661Speter return i; 20212661Speter} 20312661Speter 20412661Speterint 20515091SjkhdiskLabelCommit(dialogMenuItem *self) 20612661Speter{ 20712661Speter char *cp; 20812661Speter int i; 20912661Speter 21012661Speter /* Already done? */ 21117025Sjkh if ((cp = variable_get(DISK_LABELLED)) && strcmp(cp, "yes")) 21215242Sjkh i = DITEM_SUCCESS; 21312661Speter else if (!cp) { 21412661Speter msgConfirm("You must assign disk labels before this option can be used."); 21515242Sjkh i = DITEM_FAILURE; 21612661Speter } 21712661Speter /* The routine will guard against redundant writes, just as this one does */ 21815419Sjkh else if (DITEM_STATUS(diskPartitionWrite(self)) != DITEM_SUCCESS) 21915242Sjkh i = DITEM_FAILURE; 22015419Sjkh else if (DITEM_STATUS(installFilesystems(self)) != DITEM_SUCCESS) 22115242Sjkh i = DITEM_FAILURE; 22212661Speter else { 22312661Speter msgInfo("All filesystem information written successfully."); 22443685Sjkh variable_set2(DISK_LABELLED, "written", 0); 22515242Sjkh i = DITEM_SUCCESS; 22612661Speter } 22712661Speter return i; 22812661Speter} 22912661Speter 2308549Sjkh/* See if we're already using a desired partition name */ 2318549Sjkhstatic Boolean 2328549Sjkhcheck_conflict(char *name) 2338549Sjkh{ 2348549Sjkh int i; 2358549Sjkh 2368751Sjkh for (i = 0; label_chunk_info[i].c; i++) 23723729Sjkh if ((label_chunk_info[i].type == PART_FILESYSTEM || label_chunk_info[i].type == PART_FAT) 23823729Sjkh && label_chunk_info[i].c->private_data 23914793Sjoerg && !strcmp(((PartInfo *)label_chunk_info[i].c->private_data)->mountpoint, name)) 2408549Sjkh return TRUE; 2418549Sjkh return FALSE; 2428549Sjkh} 2438549Sjkh 2448549Sjkh/* How much space is in this FreeBSD slice? */ 2458549Sjkhstatic int 2468549Sjkhspace_free(struct chunk *c) 2478549Sjkh{ 24812661Speter struct chunk *c1; 2498549Sjkh int sz = c->size; 2508549Sjkh 25112661Speter for (c1 = c->part; c1; c1 = c1->next) { 2528549Sjkh if (c1->type != unused) 2538549Sjkh sz -= c1->size; 2548549Sjkh } 2558549Sjkh if (sz < 0) 2568549Sjkh msgFatal("Partitions are larger than actual chunk??"); 2578549Sjkh return sz; 2588549Sjkh} 2598549Sjkh 2608549Sjkh/* Snapshot the current situation into the displayed chunks structure */ 2618549Sjkhstatic void 26230345Sjkhrecord_label_chunks(Device **devs, Device *dev) 2638549Sjkh{ 2648549Sjkh int i, j, p; 2658549Sjkh struct chunk *c1, *c2; 2668556Sjkh Disk *d; 2678549Sjkh 2688549Sjkh j = p = 0; 2698556Sjkh /* First buzz through and pick up the FreeBSD slices */ 2708549Sjkh for (i = 0; devs[i]; i++) { 27130345Sjkh if ((dev && devs[i] != dev) || !devs[i]->enabled) 2728556Sjkh continue; 2738556Sjkh d = (Disk *)devs[i]->private; 2748556Sjkh if (!d->chunks) 2758556Sjkh msgFatal("No chunk list found for %s!", d->name); 2768549Sjkh 2778556Sjkh /* Put the slice entries first */ 2788556Sjkh for (c1 = d->chunks->part; c1; c1 = c1->next) { 2798549Sjkh if (c1->type == freebsd) { 2808549Sjkh label_chunk_info[j].type = PART_SLICE; 2818549Sjkh label_chunk_info[j].c = c1; 2828549Sjkh ++j; 2838549Sjkh } 2848549Sjkh } 2858549Sjkh } 28612661Speter 2878556Sjkh /* Now run through again and get the FreeBSD partition entries */ 2888556Sjkh for (i = 0; devs[i]; i++) { 2898556Sjkh if (!devs[i]->enabled) 2908556Sjkh continue; 2918556Sjkh d = (Disk *)devs[i]->private; 2928549Sjkh /* Then buzz through and pick up the partitions */ 2938556Sjkh for (c1 = d->chunks->part; c1; c1 = c1->next) { 2948549Sjkh if (c1->type == freebsd) { 2958549Sjkh for (c2 = c1->part; c2; c2 = c2->next) { 2968549Sjkh if (c2->type == part) { 2978549Sjkh if (c2->subtype == FS_SWAP) 2988549Sjkh label_chunk_info[j].type = PART_SWAP; 2998549Sjkh else 3008549Sjkh label_chunk_info[j].type = PART_FILESYSTEM; 3018549Sjkh label_chunk_info[j].c = c2; 3028549Sjkh ++j; 3038549Sjkh } 3048549Sjkh } 3058549Sjkh } 3068549Sjkh else if (c1->type == fat) { 3078549Sjkh label_chunk_info[j].type = PART_FAT; 3088549Sjkh label_chunk_info[j].c = c1; 3098702Sjkh ++j; 3108549Sjkh } 3118549Sjkh } 3128549Sjkh } 3138549Sjkh label_chunk_info[j].c = NULL; 31429249Sjkh if (here >= j) { 3158549Sjkh here = j ? j - 1 : 0; 31629249Sjkh } 3178549Sjkh} 3188549Sjkh 3198549Sjkh/* A new partition entry */ 3208549Sjkhstatic PartInfo * 3218665Sphknew_part(char *mpoint, Boolean newfs, u_long size) 3228549Sjkh{ 3238549Sjkh PartInfo *ret; 3248549Sjkh 3259202Srgrimes if (!mpoint) 3269202Srgrimes mpoint = "/change_me"; 3279202Srgrimes 3288549Sjkh ret = (PartInfo *)safe_malloc(sizeof(PartInfo)); 32920247Sjkh sstrncpy(ret->mountpoint, mpoint, FILENAME_MAX); 33049441Sphk strcpy(ret->newfs_cmd, "newfs "); 33149441Sphk strcat(ret->newfs_cmd, variable_get(VAR_NEWFS_ARGS)); 3328666Sphk ret->newfs = newfs; 33388321Sjkh ret->soft = strcmp(mpoint, "/") ? 1 : 0; 3348669Sphk if (!size) 33529249Sjkh return ret; 3368549Sjkh return ret; 3378549Sjkh} 3388549Sjkh 3398549Sjkh/* Get the mountpoint for a partition and save it away */ 34012661Speterstatic PartInfo * 3418589Sjkhget_mountpoint(struct chunk *old) 3428549Sjkh{ 3438549Sjkh char *val; 3448549Sjkh PartInfo *tmp; 3458549Sjkh 34614793Sjoerg if (old && old->private_data) 34714793Sjoerg tmp = old->private_data; 3488810Sjkh else 3498810Sjkh tmp = NULL; 3508810Sjkh val = msgGetInput(tmp ? tmp->mountpoint : NULL, "Please specify a mount point for the partition"); 3518764Sjkh if (!val || !*val) { 3528751Sjkh if (!old) 3538751Sjkh return NULL; 3548751Sjkh else { 35514793Sjoerg free(old->private_data); 35614793Sjoerg old->private_data = NULL; 3578751Sjkh } 3588669Sphk return NULL; 3598751Sjkh } 3608669Sphk 3618669Sphk /* Is it just the same value? */ 3628810Sjkh if (tmp && !strcmp(tmp->mountpoint, val)) 3638669Sphk return NULL; 3648810Sjkh 3658810Sjkh /* Did we use it already? */ 3668669Sphk if (check_conflict(val)) { 3678669Sphk msgConfirm("You already have a mount point for %s assigned!", val); 3688669Sphk return NULL; 3698549Sjkh } 3708810Sjkh 3718810Sjkh /* Is it bogus? */ 3728669Sphk if (*val != '/') { 3738669Sphk msgConfirm("Mount point must start with a / character"); 3748669Sphk return NULL; 3758669Sphk } 3768810Sjkh 3778810Sjkh /* Is it going to be mounted on root? */ 3788669Sphk if (!strcmp(val, "/")) { 3798669Sphk if (old) 3808669Sphk old->flags |= CHUNK_IS_ROOT; 3818810Sjkh } 3828810Sjkh else if (old) 3838669Sphk old->flags &= ~CHUNK_IS_ROOT; 3848810Sjkh 3858810Sjkh safe_free(tmp); 38646615Sjkh val = string_skipwhite(string_prune(val)); 3878669Sphk tmp = new_part(val, TRUE, 0); 3888669Sphk if (old) { 38914793Sjoerg old->private_data = tmp; 3908669Sphk old->private_free = safe_free; 3918669Sphk } 3928669Sphk return tmp; 3938549Sjkh} 3948549Sjkh 3958549Sjkh/* Get the type of the new partiton */ 3968549Sjkhstatic PartType 3978549Sjkhget_partition_type(void) 3988549Sjkh{ 3998549Sjkh char selection[20]; 4008669Sphk int i; 4018549Sjkh static unsigned char *fs_types[] = { 4028549Sjkh "FS", 4038549Sjkh "A file system", 4048549Sjkh "Swap", 4058549Sjkh "A swap partition.", 4068549Sjkh }; 40754587Sjkh WINDOW *w = savescr(); 40854587Sjkh 4098669Sphk i = dialog_menu("Please choose a partition type", 41012661Speter "If you want to use this partition for swap space, select Swap.\n" 41112661Speter "If you want to put a filesystem on it, choose FS.", 41212661Speter -1, -1, 2, 2, fs_types, selection, NULL, NULL); 41354587Sjkh restorescr(w); 4148669Sphk if (!i) { 4158549Sjkh if (!strcmp(selection, "FS")) 4168549Sjkh return PART_FILESYSTEM; 4178549Sjkh else if (!strcmp(selection, "Swap")) 4188549Sjkh return PART_SWAP; 4198549Sjkh } 4208549Sjkh return PART_NONE; 4218549Sjkh} 4228549Sjkh 4238549Sjkh/* If the user wants a special newfs command for this, set it */ 4248549Sjkhstatic void 4258549SjkhgetNewfsCmd(PartInfo *p) 4268549Sjkh{ 4278549Sjkh char *val; 4288549Sjkh 4298549Sjkh val = msgGetInput(p->newfs_cmd, 43012661Speter "Please enter the newfs command and options you'd like to use in\n" 43112661Speter "creating this file system."); 4328549Sjkh if (val) 43320247Sjkh sstrncpy(p->newfs_cmd, val, NEWFS_CMD_MAX); 4348549Sjkh} 4358549Sjkh 43676299Sjkh#define MAX_MOUNT_NAME 9 4378549Sjkh 4388549Sjkh#define PART_PART_COL 0 43954014Sjkh#define PART_MOUNT_COL 10 4408549Sjkh#define PART_SIZE_COL (PART_MOUNT_COL + MAX_MOUNT_NAME + 3) 44149202Sbrian#define PART_NEWFS_COL (PART_SIZE_COL + 8) 44276299Sjkh#define PART_OFF 38 4438549Sjkh 44429249Sjkh#define TOTAL_AVAIL_LINES (10) 44529249Sjkh#define PSLICE_SHOWABLE (4) 44629249Sjkh 44729249Sjkh 4488549Sjkh/* stick this all up on the screen */ 4498549Sjkhstatic void 4508549Sjkhprint_label_chunks(void) 4518549Sjkh{ 45229249Sjkh int i, j, srow, prow, pcol; 45329249Sjkh int sz; 45429249Sjkh char clrmsg[80]; 45529633Sjkh int ChunkPartStartRow; 45629633Sjkh WINDOW *ChunkWin; 4578549Sjkh 45829249Sjkh /********************************************************/ 45929249Sjkh /*** These values are for controling screen resources ***/ 46029249Sjkh /*** Each label line holds up to 2 labels, so beware! ***/ 46129249Sjkh /*** strategy will be to try to always make sure the ***/ 46229249Sjkh /*** highlighted label is in the active display area. ***/ 46329249Sjkh /********************************************************/ 46429249Sjkh int pslice_max, label_max; 46529249Sjkh int pslice_count, label_count, label_focus_found, pslice_focus_found; 46629249Sjkh 4678549Sjkh attrset(A_REVERSE); 4688549Sjkh mvaddstr(0, 25, "FreeBSD Disklabel Editor"); 4698549Sjkh attrset(A_NORMAL); 4708549Sjkh 47129633Sjkh /*** Count the number of parition slices ***/ 47229633Sjkh pslice_count = 0; 47329633Sjkh for (i = 0; label_chunk_info[i].c ; i++) { 47429633Sjkh if (label_chunk_info[i].type == PART_SLICE) 47529633Sjkh ++pslice_count; 47629633Sjkh } 47729633Sjkh pslice_max = pslice_count; 47829633Sjkh 47929633Sjkh /*** 4 line max for partition slices ***/ 48029633Sjkh if (pslice_max > PSLICE_SHOWABLE) { 48129633Sjkh pslice_max = PSLICE_SHOWABLE; 48229633Sjkh } 48329633Sjkh ChunkPartStartRow = CHUNK_SLICE_START_ROW + 3 + pslice_max; 48429633Sjkh 48529633Sjkh /*** View partition slices modulo pslice_max ***/ 48629633Sjkh label_max = TOTAL_AVAIL_LINES - pslice_max; 48729633Sjkh 4888549Sjkh for (i = 0; i < 2; i++) { 48915440Sjkh mvaddstr(ChunkPartStartRow - 2, PART_PART_COL + (i * PART_OFF), "Part"); 49015440Sjkh mvaddstr(ChunkPartStartRow - 1, PART_PART_COL + (i * PART_OFF), "----"); 4918549Sjkh 49215440Sjkh mvaddstr(ChunkPartStartRow - 2, PART_MOUNT_COL + (i * PART_OFF), "Mount"); 49315440Sjkh mvaddstr(ChunkPartStartRow - 1, PART_MOUNT_COL + (i * PART_OFF), "-----"); 4948549Sjkh 49549202Sbrian mvaddstr(ChunkPartStartRow - 2, PART_SIZE_COL + (i * PART_OFF) + 3, "Size"); 49649202Sbrian mvaddstr(ChunkPartStartRow - 1, PART_SIZE_COL + (i * PART_OFF) + 3, "----"); 4978549Sjkh 49815440Sjkh mvaddstr(ChunkPartStartRow - 2, PART_NEWFS_COL + (i * PART_OFF), "Newfs"); 49915440Sjkh mvaddstr(ChunkPartStartRow - 1, PART_NEWFS_COL + (i * PART_OFF), "-----"); 5008549Sjkh } 5018549Sjkh srow = CHUNK_SLICE_START_ROW; 50215440Sjkh prow = 0; 5038549Sjkh pcol = 0; 5048549Sjkh 50529249Sjkh /*** these variables indicate that the focused item is shown currently ***/ 50629249Sjkh label_focus_found = 0; 50729249Sjkh pslice_focus_found = 0; 50829249Sjkh 50929249Sjkh label_count = 0; 51029249Sjkh pslice_count = 0; 51129249Sjkh mvprintw(CHUNK_SLICE_START_ROW - 1, 0, " "); 51229249Sjkh mvprintw(CHUNK_SLICE_START_ROW + pslice_max, 0, " "); 51329249Sjkh 51429633Sjkh ChunkWin = newwin(CHUNK_ROW_MAX - ChunkPartStartRow, 76, ChunkPartStartRow, 0); 51529633Sjkh 51629633Sjkh wclear(ChunkWin); 51729633Sjkh /*** wrefresh(ChunkWin); ***/ 51829633Sjkh 5198751Sjkh for (i = 0; label_chunk_info[i].c; i++) { 5208549Sjkh /* Is it a slice entry displayed at the top? */ 5218549Sjkh if (label_chunk_info[i].type == PART_SLICE) { 52229249Sjkh /*** This causes the new pslice to replace the previous display ***/ 52329249Sjkh /*** focus must remain on the most recently active pslice ***/ 52429249Sjkh if (pslice_count == pslice_max) { 52529249Sjkh if (pslice_focus_found) { 52629249Sjkh /*** This is where we can mark the more following ***/ 52729249Sjkh attrset(A_BOLD); 52829249Sjkh mvprintw(CHUNK_SLICE_START_ROW + pslice_max, 0, "***MORE***"); 52929249Sjkh attrset(A_NORMAL); 53029249Sjkh continue; 53129249Sjkh } 53229249Sjkh else { 53329249Sjkh /*** this is where we set the more previous ***/ 53429249Sjkh attrset(A_BOLD); 53529249Sjkh mvprintw(CHUNK_SLICE_START_ROW - 1, 0, "***MORE***"); 53629249Sjkh attrset(A_NORMAL); 53729249Sjkh pslice_count = 0; 53829249Sjkh srow = CHUNK_SLICE_START_ROW; 53929249Sjkh } 54029249Sjkh } 54129249Sjkh 5428549Sjkh sz = space_free(label_chunk_info[i].c); 54315440Sjkh if (i == here) 54416208Sjkh attrset(ATTR_SELECTED); 54529249Sjkh if (i == pslice_focus) 54629249Sjkh pslice_focus_found = -1; 54729249Sjkh 54829249Sjkh mvprintw(srow++, 0, 54929249Sjkh "Disk: %s\tPartition name: %s\tFree: %d blocks (%dMB)", 55029249Sjkh label_chunk_info[i].c->disk->name, label_chunk_info[i].c->name, 55129249Sjkh sz, (sz / ONE_MEG)); 55215440Sjkh attrset(A_NORMAL); 55315440Sjkh clrtoeol(); 55415440Sjkh move(0, 0); 55529633Sjkh /*** refresh(); ***/ 55629249Sjkh ++pslice_count; 5578549Sjkh } 55815440Sjkh /* Otherwise it's a DOS, swap or filesystem entry in the Chunk window */ 5598549Sjkh else { 56074086Sjkh char onestr[PART_OFF], num[10], *mountpoint, newfs[10]; 5618549Sjkh 5628549Sjkh /* 5638549Sjkh * We copy this into a blank-padded string so that it looks like 5648549Sjkh * a solid bar in reverse-video 5658549Sjkh */ 5668549Sjkh memset(onestr, ' ', PART_OFF - 1); 5678549Sjkh onestr[PART_OFF - 1] = '\0'; 56829249Sjkh 56929249Sjkh /*** Track how many labels have been displayed ***/ 57029249Sjkh if (label_count == ((label_max - 1 ) * 2)) { 57129249Sjkh if (label_focus_found) { 57229249Sjkh continue; 57329249Sjkh } 57429249Sjkh else { 57529249Sjkh label_count = 0; 57629249Sjkh prow = 0; 57729249Sjkh pcol = 0; 57829249Sjkh } 57929249Sjkh } 58029249Sjkh 58115440Sjkh /* Go for two columns if we've written one full columns worth */ 58229249Sjkh /*** if (prow == (CHUNK_ROW_MAX - ChunkPartStartRow)) ***/ 58329249Sjkh if (label_count == label_max - 1) { 5848549Sjkh pcol = PART_OFF; 58515440Sjkh prow = 0; 5868549Sjkh } 5878705Sjkh memcpy(onestr + PART_PART_COL, label_chunk_info[i].c->name, strlen(label_chunk_info[i].c->name)); 5888549Sjkh /* If it's a filesystem, display the mountpoint */ 58914793Sjoerg if (label_chunk_info[i].c->private_data 59010882Speter && (label_chunk_info[i].type == PART_FILESYSTEM || label_chunk_info[i].type == PART_FAT)) 59114793Sjoerg mountpoint = ((PartInfo *)label_chunk_info[i].c->private_data)->mountpoint; 59223529Sjkh else if (label_chunk_info[i].type == PART_SWAP) 59323529Sjkh mountpoint = "swap"; 59410882Speter else 59510882Speter mountpoint = "<none>"; 59610882Speter 59710882Speter /* Now display the newfs field */ 59810882Speter if (label_chunk_info[i].type == PART_FAT) 59974086Sjkh strcpy(newfs, "DOS"); 60074086Sjkh else if (label_chunk_info[i].c->private_data && label_chunk_info[i].type == PART_FILESYSTEM) { 60174086Sjkh strcpy(newfs, "UFS"); 60276299Sjkh strcat(newfs, 60376299Sjkh ((PartInfo *)label_chunk_info[i].c->private_data)->soft ? 60476299Sjkh "+S" : " "); 60576299Sjkh strcat(newfs, 60676299Sjkh ((PartInfo *)label_chunk_info[i].c->private_data)->newfs ? 60776299Sjkh " Y" : " N"); 60874086Sjkh } 60910882Speter else if (label_chunk_info[i].type == PART_SWAP) 61074086Sjkh strcpy(newfs, "SWAP"); 61110882Speter else 61274086Sjkh strcpy(newfs, "*"); 6138549Sjkh for (j = 0; j < MAX_MOUNT_NAME && mountpoint[j]; j++) 6148549Sjkh onestr[PART_MOUNT_COL + j] = mountpoint[j]; 61549202Sbrian snprintf(num, 10, "%5ldMB", label_chunk_info[i].c->size ? label_chunk_info[i].c->size / ONE_MEG : 0); 6168549Sjkh memcpy(onestr + PART_SIZE_COL, num, strlen(num)); 6178549Sjkh memcpy(onestr + PART_NEWFS_COL, newfs, strlen(newfs)); 6188549Sjkh onestr[PART_NEWFS_COL + strlen(newfs)] = '\0'; 61929633Sjkh if (i == label_focus) { 62029633Sjkh label_focus_found = -1; 62129633Sjkh wattrset(ChunkWin, A_BOLD); 62229633Sjkh } 62315440Sjkh if (i == here) 62416208Sjkh wattrset(ChunkWin, ATTR_SELECTED); 62529249Sjkh 62674086Sjkh /*** lazy man's way of expensively padding this string ***/ 62774086Sjkh while (strlen(onestr) < 37) 62829249Sjkh strcat(onestr, " "); 62929249Sjkh 63015440Sjkh mvwaddstr(ChunkWin, prow, pcol, onestr); 63115440Sjkh wattrset(ChunkWin, A_NORMAL); 63215440Sjkh move(0, 0); 6338549Sjkh ++prow; 63429249Sjkh ++label_count; 6358549Sjkh } 6368549Sjkh } 63729249Sjkh 63829249Sjkh /*** this will erase all the extra stuff ***/ 63929249Sjkh memset(clrmsg, ' ', 37); 64029249Sjkh clrmsg[37] = '\0'; 64129249Sjkh 64229249Sjkh while (pslice_count < pslice_max) { 64329249Sjkh mvprintw(srow++, 0, clrmsg); 64429249Sjkh clrtoeol(); 64529249Sjkh ++pslice_count; 64629249Sjkh } 64729633Sjkh while (label_count < (2 * (label_max - 1))) { 64829633Sjkh mvwaddstr(ChunkWin, prow++, pcol, clrmsg); 64929633Sjkh ++label_count; 65029633Sjkh if (prow == (label_max - 1)) { 65129633Sjkh prow = 0; 65229633Sjkh pcol = PART_OFF; 65329633Sjkh } 65429249Sjkh } 65529633Sjkh refresh(); 65629633Sjkh wrefresh(ChunkWin); 6578549Sjkh} 6588549Sjkh 6598549Sjkhstatic void 66018619Sjkhprint_command_summary(void) 6618549Sjkh{ 6628820Sjkh mvprintw(17, 0, "The following commands are valid here (upper or lower case):"); 66374086Sjkh mvprintw(18, 0, "C = Create D = Delete M = Mount pt."); 66415440Sjkh if (!RunningAsInit) 66574086Sjkh mvprintw(18, 47, "W = Write"); 66674086Sjkh mvprintw(19, 0, "N = Newfs Opts Q = Finish S = Toggle SoftUpdates"); 66788996Sdillon mvprintw(20, 0, "T = Toggle Newfs U = Undo A = Auto Defaults R = Delete+Merge"); 66815695Sjkh mvprintw(22, 0, "Use F1 or ? to get more help, arrow keys to select."); 6698549Sjkh move(0, 0); 6708549Sjkh} 6718549Sjkh 67218619Sjkhstatic void 67318619Sjkhclear_wins(void) 67418619Sjkh{ 67529633Sjkh extern void print_label_chunks(); 67618619Sjkh clear(); 67729633Sjkh print_label_chunks(); 67818619Sjkh} 67918619Sjkh 68043392Sjkh#ifdef __alpha__ 68143392Sjkh 68243392Sjkh/* 68343392Sjkh * If there isn't a freebsd chunk already (i.e. there is no label), 68443392Sjkh * dedicate the disk. 68543392Sjkh */ 68643392Sjkhstatic void 68743392Sjkhmaybe_dedicate(Disk* d) 68843392Sjkh{ 68943392Sjkh struct chunk *c; 69043392Sjkh 69143392Sjkh for (c = d->chunks->part; c; c = c->next) { 69243392Sjkh if (c->type == freebsd) 69343392Sjkh break; 69443392Sjkh } 69543392Sjkh 69643392Sjkh if (!c) { 69743392Sjkh msgDebug("dedicating disk"); 69843392Sjkh All_FreeBSD(d, 1); 69943392Sjkh } 70043392Sjkh} 70143392Sjkh 70243392Sjkh#endif 70343392Sjkh 70412661Speterstatic int 70530345SjkhdiskLabel(Device *dev) 7068549Sjkh{ 70718619Sjkh int sz, key = 0; 7088549Sjkh Boolean labeling; 7098549Sjkh char *msg = NULL; 7109202Srgrimes PartInfo *p, *oldp; 7118549Sjkh PartType type; 7128824Sjkh Device **devs; 71342386Sjkh#ifdef __alpha__ 71442386Sjkh int i; 71542386Sjkh#endif 71654587Sjkh WINDOW *w = savescr(); 7178549Sjkh 71829628Sjkh label_focus = 0; 71929628Sjkh pslice_focus = 0; 72029633Sjkh here = 0; 72130345Sjkh 72212661Speter devs = deviceFind(NULL, DEVICE_TYPE_DISK); 72312661Speter if (!devs) { 72412661Speter msgConfirm("No disks found!"); 72554587Sjkh restorescr(w); 72615242Sjkh return DITEM_FAILURE; 72712661Speter } 7288549Sjkh labeling = TRUE; 7298549Sjkh keypad(stdscr, TRUE); 73042386Sjkh#ifdef __alpha__ 73142386Sjkh for (i = 0; devs[i]; i++) { 73243392Sjkh maybe_dedicate((Disk*) devs[i]->private); 73342386Sjkh } 73442386Sjkh#endif 73530345Sjkh record_label_chunks(devs, dev); 7368549Sjkh 73718619Sjkh clear(); 7388549Sjkh while (labeling) { 73918744Sjkh char *cp; 74088996Sdillon int rflags = DELCHUNK_NORMAL; 74118744Sjkh 7428549Sjkh print_label_chunks(); 74318619Sjkh print_command_summary(); 7448549Sjkh if (msg) { 74515695Sjkh attrset(title_attr); mvprintw(23, 0, msg); attrset(A_NORMAL); 74612661Speter clrtoeol(); 7478549Sjkh beep(); 7488549Sjkh msg = NULL; 7498549Sjkh } 75015442Sjkh else { 75115442Sjkh move(23, 0); 75215442Sjkh clrtoeol(); 75315442Sjkh } 75418744Sjkh 75518619Sjkh refresh(); 75617397Sjkh key = getch(); 75717397Sjkh switch (toupper(key)) { 75815440Sjkh int i; 75917362Sjkh static char _msg[40]; 7608549Sjkh 7618751Sjkh case '\014': /* ^L */ 76218619Sjkh clear_wins(); 76318619Sjkh break; 7648751Sjkh 76521698Sjkh case '\020': /* ^P */ 7668549Sjkh case KEY_UP: 7678549Sjkh case '-': 7688549Sjkh if (here != 0) 7698549Sjkh --here; 7708751Sjkh else 7718751Sjkh while (label_chunk_info[here + 1].c) 7728751Sjkh ++here; 7738549Sjkh break; 7748549Sjkh 77521698Sjkh case '\016': /* ^N */ 7768549Sjkh case KEY_DOWN: 7778549Sjkh case '+': 7788549Sjkh case '\r': 7798549Sjkh case '\n': 7808751Sjkh if (label_chunk_info[here + 1].c) 7818549Sjkh ++here; 7828751Sjkh else 7838751Sjkh here = 0; 7848549Sjkh break; 7858549Sjkh 7868549Sjkh case KEY_HOME: 7878549Sjkh here = 0; 7888549Sjkh break; 7898549Sjkh 7908549Sjkh case KEY_END: 7918751Sjkh while (label_chunk_info[here + 1].c) 7928549Sjkh ++here; 7938549Sjkh break; 7948549Sjkh 7958549Sjkh case KEY_F(1): 7968549Sjkh case '?': 79712661Speter systemDisplayHelp("partition"); 79818619Sjkh clear_wins(); 7998549Sjkh break; 8008549Sjkh 80110882Speter case 'A': 80210882Speter if (label_chunk_info[here].type != PART_SLICE) { 80315440Sjkh msg = "You can only do this in a disk slice (at top of screen)"; 80410882Speter break; 80510882Speter } 80687557Sdillon /* 80787557Sdillon * Generate standard partitions automatically. If we do not 80887557Sdillon * have sufficient space we attempt to scale-down the size 80987557Sdillon * of the partitions within certain bounds. 81087557Sdillon */ 81187557Sdillon { 81287557Sdillon int perc; 81387557Sdillon int req = 0; 81412661Speter 81587557Sdillon for (perc = 100; perc > 0; perc -= 5) { 81687557Sdillon req = 0; /* reset for each loop */ 81787557Sdillon if ((msg = try_auto_label(devs, dev, perc, &req)) == NULL) 81817362Sjkh break; 81915440Sjkh } 82087557Sdillon if (msg) { 82187557Sdillon if (req) { 82287557Sdillon msgConfirm(msg); 82318619Sjkh clear_wins(); 82487557Sdillon msg = NULL; 82517362Sjkh } 82615440Sjkh } 82710882Speter } 82815440Sjkh break; 82910882Speter 8308549Sjkh case 'C': 8318549Sjkh if (label_chunk_info[here].type != PART_SLICE) { 8328549Sjkh msg = "You can only do this in a master partition (see top of screen)"; 8338549Sjkh break; 8348549Sjkh } 8358549Sjkh sz = space_free(label_chunk_info[here].c); 8368669Sphk if (sz <= FS_MIN_SIZE) { 83712661Speter msg = "Not enough space to create an additional FreeBSD partition"; 8388669Sphk break; 8398669Sphk } 84015440Sjkh else { 84118744Sjkh char *val; 8428702Sjkh int size; 8438702Sjkh struct chunk *tmp; 8448820Sjkh char osize[80]; 8458702Sjkh u_long flags = 0; 8468549Sjkh 8478820Sjkh sprintf(osize, "%d", sz); 84818619Sjkh val = msgGetInput(osize, 84957617Sjkh "Please specify the partition size in blocks or append a trailing G for\n" 85057617Sjkh "gigabytes, M for megabytes, or C for cylinders.\n" 85157617Sjkh "%d blocks (%dMB) are free.", 85218619Sjkh sz, sz / ONE_MEG); 85318619Sjkh if (!val || (size = strtol(val, &cp, 0)) <= 0) { 85418619Sjkh clear_wins(); 8558702Sjkh break; 85618619Sjkh } 8578549Sjkh 8588751Sjkh if (*cp) { 8598751Sjkh if (toupper(*cp) == 'M') 8608751Sjkh size *= ONE_MEG; 86157617Sjkh else if (toupper(*cp) == 'G') 86257617Sjkh size *= ONE_GIG; 8638751Sjkh else if (toupper(*cp) == 'C') 8648751Sjkh size *= (label_chunk_info[here].c->disk->bios_hd * label_chunk_info[here].c->disk->bios_sect); 8658751Sjkh } 8668820Sjkh if (size <= FS_MIN_SIZE) { 8678820Sjkh msgConfirm("The minimum filesystem size is %dMB", FS_MIN_SIZE / ONE_MEG); 86818619Sjkh clear_wins(); 8698820Sjkh break; 8708820Sjkh } 8718702Sjkh type = get_partition_type(); 87218619Sjkh if (type == PART_NONE) { 87318619Sjkh clear_wins(); 87418619Sjkh beep(); 8758669Sphk break; 87618619Sjkh } 8778669Sphk 8788702Sjkh if (type == PART_FILESYSTEM) { 87918619Sjkh if ((p = get_mountpoint(NULL)) == NULL) { 88018619Sjkh clear_wins(); 88118619Sjkh beep(); 8828702Sjkh break; 88318619Sjkh } 8848702Sjkh else if (!strcmp(p->mountpoint, "/")) 8858702Sjkh flags |= CHUNK_IS_ROOT; 8868702Sjkh else 8878702Sjkh flags &= ~CHUNK_IS_ROOT; 88818619Sjkh } 88918619Sjkh else 8908702Sjkh p = NULL; 8918702Sjkh 89276237Sjkh if ((flags & CHUNK_IS_ROOT) && (size < (ROOT_MIN_SIZE * ONE_MEG))) { 89376237Sjkh msgConfirm("Warning: This is smaller than the recommended size for a\n" 89476237Sjkh "root partition. For a variety of reasons, root\n" 89576237Sjkh "partitions should usually be at least %dMB in size", ROOT_MIN_SIZE); 8968672Sjkh } 8978751Sjkh tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 8988702Sjkh label_chunk_info[here].c, 8998702Sjkh size, part, 9008702Sjkh (type == PART_SWAP) ? FS_SWAP : FS_BSDFFS, 9018702Sjkh flags); 9028702Sjkh if (!tmp) { 9038702Sjkh msgConfirm("Unable to create the partition. Too big?"); 90418619Sjkh clear_wins(); 9058672Sjkh break; 9068672Sjkh } 90779678Sobrien 90879678Sobrien#ifdef __alpha__ 90979678Sobrien /* 91079680Sobrien * SRM requires that the root partition is at the 91179678Sobrien * begining of the disk and cannot boot otherwise. 91279678Sobrien * Warn Alpha users if they are about to shoot themselves in 91379678Sobrien * the foot in this way. 91479678Sobrien * 91579678Sobrien * Since partitions may not start precisely at offset 0 we 91679678Sobrien * check for a "close to 0" instead. :-( 91779678Sobrien */ 91879678Sobrien if ((flags & CHUNK_IS_ROOT) && (tmp->offset > 1024)) { 91979680Sobrien msgConfirm("Your root partition `a' does not seem to be the first\n" 92079680Sobrien "partition. The Alpha's firmware can only boot from the\n" 92179680Sobrien "first partition. So it is unlikely that your current\n" 92279680Sobrien "disk layout will be bootable boot after installation.\n" 92379678Sobrien "\n" 92479678Sobrien "Please allocate the root partition before allocating\n" 92579678Sobrien "any others.\n"); 92679678Sobrien } 92779678Sobrien#endif /* alpha */ 92879678Sobrien 9298702Sjkh if (type != PART_SWAP) { 9308669Sphk /* This is needed to tell the newfs -u about the size */ 93114793Sjoerg tmp->private_data = new_part(p->mountpoint, p->newfs, tmp->size); 9328669Sphk safe_free(p); 93315355Sjkh } 93415355Sjkh else 93514793Sjoerg tmp->private_data = p; 9368702Sjkh tmp->private_free = safe_free; 93774156Sjkh if (variable_cmp(DISK_LABELLED, "written")) 93843685Sjkh variable_set2(DISK_LABELLED, "yes", 0); 93930345Sjkh record_label_chunks(devs, dev); 94018619Sjkh clear_wins(); 94179678Sobrien /* This is where we assign focus to new label so it shows. */ 94229249Sjkh { 94329249Sjkh int i; 94429249Sjkh label_focus = -1; 94529249Sjkh for (i = 0; label_chunk_info[i].c; ++i) { 94629249Sjkh if (label_chunk_info[i].c == tmp) { 94729249Sjkh label_focus = i; 94829249Sjkh break; 94929249Sjkh } 95029249Sjkh } 95129249Sjkh if (label_focus == -1) 95229249Sjkh label_focus = i - 1; 95329249Sjkh } 9548549Sjkh } 9558549Sjkh break; 9568549Sjkh 95717397Sjkh case KEY_DC: 95888996Sdillon case 'R': /* recover space (delete w/ recover) */ 95988996Sdillon /* 96088996Sdillon * Delete the partition w/ space recovery. 96188996Sdillon */ 96288996Sdillon rflags = DELCHUNK_RECOVER; 96388996Sdillon /* fall through */ 9648549Sjkh case 'D': /* delete */ 9658549Sjkh if (label_chunk_info[here].type == PART_SLICE) { 9668549Sjkh msg = MSG_NOT_APPLICABLE; 9678549Sjkh break; 9688549Sjkh } 9698549Sjkh else if (label_chunk_info[here].type == PART_FAT) { 9708705Sjkh msg = "Use the Disk Partition Editor to delete DOS partitions"; 9718549Sjkh break; 9728549Sjkh } 97388996Sdillon Delete_Chunk2(label_chunk_info[here].c->disk, label_chunk_info[here].c, rflags); 97474156Sjkh if (variable_cmp(DISK_LABELLED, "written")) 97543685Sjkh variable_set2(DISK_LABELLED, "yes", 0); 97630345Sjkh record_label_chunks(devs, dev); 9778549Sjkh break; 9788549Sjkh 9798549Sjkh case 'M': /* mount */ 9808549Sjkh switch(label_chunk_info[here].type) { 9818549Sjkh case PART_SLICE: 9828549Sjkh msg = MSG_NOT_APPLICABLE; 9838549Sjkh break; 9848549Sjkh 9858549Sjkh case PART_SWAP: 9868549Sjkh msg = "You don't need to specify a mountpoint for a swap partition."; 9878549Sjkh break; 9888549Sjkh 9898556Sjkh case PART_FAT: 9908549Sjkh case PART_FILESYSTEM: 99114793Sjoerg oldp = label_chunk_info[here].c->private_data; 9928589Sjkh p = get_mountpoint(label_chunk_info[here].c); 9938549Sjkh if (p) { 9949202Srgrimes if (!oldp) 9959202Srgrimes p->newfs = FALSE; 9968722Sjkh if (label_chunk_info[here].type == PART_FAT 9978722Sjkh && (!strcmp(p->mountpoint, "/") || !strcmp(p->mountpoint, "/usr") 9988722Sjkh || !strcmp(p->mountpoint, "/var"))) { 9998722Sjkh msgConfirm("%s is an invalid mount point for a DOS partition!", p->mountpoint); 10008722Sjkh strcpy(p->mountpoint, "/bogus"); 10018722Sjkh } 10028549Sjkh } 100374156Sjkh if (variable_cmp(DISK_LABELLED, "written")) 100443685Sjkh variable_set2(DISK_LABELLED, "yes", 0); 100530345Sjkh record_label_chunks(devs, dev); 100618636Sjkh clear_wins(); 10078549Sjkh break; 10088549Sjkh 10098549Sjkh default: 10108549Sjkh msgFatal("Bogus partition under cursor???"); 10118549Sjkh break; 10128549Sjkh } 10138549Sjkh break; 10148549Sjkh 10158549Sjkh case 'N': /* Set newfs options */ 101614793Sjoerg if (label_chunk_info[here].c->private_data && 101714793Sjoerg ((PartInfo *)label_chunk_info[here].c->private_data)->newfs) 101814793Sjoerg getNewfsCmd(label_chunk_info[here].c->private_data); 10198549Sjkh else 10208549Sjkh msg = MSG_NOT_APPLICABLE; 102118636Sjkh clear_wins(); 10228549Sjkh break; 10238549Sjkh 102474086Sjkh case 'S': /* Toggle soft updates flag */ 102574086Sjkh if (label_chunk_info[here].type == PART_FILESYSTEM) { 102674086Sjkh PartInfo *pi = ((PartInfo *)label_chunk_info[here].c->private_data); 102774086Sjkh if (pi) 102874086Sjkh pi->soft = !pi->soft; 102974086Sjkh else 103074086Sjkh msg = MSG_NOT_APPLICABLE; 103174086Sjkh } 103274156Sjkh else 103374156Sjkh msg = MSG_NOT_APPLICABLE; 103474086Sjkh break; 103574086Sjkh 10368549Sjkh case 'T': /* Toggle newfs state */ 10379202Srgrimes if (label_chunk_info[here].type == PART_FILESYSTEM) { 103823729Sjkh PartInfo *pi = ((PartInfo *)label_chunk_info[here].c->private_data); 103987581Sdillon if (!pi->newfs) 104087581Sdillon label_chunk_info[here].c->flags |= CHUNK_NEWFS; 104187581Sdillon else 104287581Sdillon label_chunk_info[here].c->flags &= ~CHUNK_NEWFS; 104387581Sdillon 104423729Sjkh label_chunk_info[here].c->private_data = 104523729Sjkh new_part(pi ? pi->mountpoint : NULL, pi ? !pi->newfs : TRUE, label_chunk_info[here].c->size); 104674156Sjkh if (pi && pi->soft) 104774156Sjkh ((PartInfo *)label_chunk_info[here].c->private_data)->soft = 1; 104823729Sjkh safe_free(pi); 104923729Sjkh label_chunk_info[here].c->private_free = safe_free; 105074156Sjkh if (variable_cmp(DISK_LABELLED, "written")) 105143685Sjkh variable_set2(DISK_LABELLED, "yes", 0); 105218619Sjkh } 10538549Sjkh else 10548549Sjkh msg = MSG_NOT_APPLICABLE; 10558549Sjkh break; 10568549Sjkh 10578820Sjkh case 'U': 105812661Speter clear(); 105974156Sjkh if (!variable_cmp(DISK_LABELLED, "written")) { 106018744Sjkh msgConfirm("You've already written out your changes -\n" 106118744Sjkh "it's too late to undo!"); 106218744Sjkh } 106370005Sjkh else if (!msgNoYes("Are you SURE you want to Undo everything?")) { 106418744Sjkh variable_unset(DISK_PARTITIONED); 106518744Sjkh variable_unset(DISK_LABELLED); 106618744Sjkh for (i = 0; devs[i]; i++) { 106718744Sjkh Disk *d; 106812661Speter 106918744Sjkh if (!devs[i]->enabled) 107018744Sjkh continue; 107118744Sjkh else if ((d = Open_Disk(devs[i]->name)) != NULL) { 107218744Sjkh Free_Disk(devs[i]->private); 107318744Sjkh devs[i]->private = d; 107430345Sjkh diskPartition(devs[i]); 107518744Sjkh } 10768824Sjkh } 107730345Sjkh record_label_chunks(devs, dev); 10788824Sjkh } 107918636Sjkh clear_wins(); 10808824Sjkh break; 10818820Sjkh 10828549Sjkh case 'W': 108374156Sjkh if (!variable_cmp(DISK_LABELLED, "written")) { 108418744Sjkh msgConfirm("You've already written out your changes - if you\n" 108574156Sjkh "wish to overwrite them, you'll have to restart\n" 108674156Sjkh "sysinstall first."); 108718744Sjkh } 108870005Sjkh else if (!msgNoYes("WARNING: This should only be used when modifying an EXISTING\n" 108918687Sjkh "installation. If you are installing FreeBSD for the first time\n" 109018687Sjkh "then you should simply type Q when you're finished here and your\n" 109118687Sjkh "changes will be committed in one batch automatically at the end of\n" 109218687Sjkh "these questions.\n\n" 109318687Sjkh "Are you absolutely sure you want to do this now?")) { 109443685Sjkh variable_set2(DISK_LABELLED, "yes", 0); 109512661Speter diskLabelCommit(NULL); 109612661Speter } 109718636Sjkh clear_wins(); 109810882Speter break; 109910882Speter 110010882Speter case '|': 110170005Sjkh if (!msgNoYes("Are you sure you want to go into Wizard mode?\n\n" 110212661Speter "This is an entirely undocumented feature which you are not\n" 110312661Speter "expected to understand!")) { 11048549Sjkh int i; 11058549Sjkh Device **devs; 11068549Sjkh 11078549Sjkh dialog_clear(); 11088549Sjkh end_dialog(); 11098549Sjkh DialogActive = FALSE; 11108549Sjkh devs = deviceFind(NULL, DEVICE_TYPE_DISK); 11118549Sjkh if (!devs) { 111212661Speter msgConfirm("Can't find any disk devices!"); 11138549Sjkh break; 11148549Sjkh } 11158668Sphk for (i = 0; devs[i] && ((Disk *)devs[i]->private); i++) { 11168613Sjkh if (devs[i]->enabled) 11178613Sjkh slice_wizard(((Disk *)devs[i]->private)); 11188613Sjkh } 111974156Sjkh if (variable_cmp(DISK_LABELLED, "written")) 112043685Sjkh variable_set2(DISK_LABELLED, "yes", 0); 11218665Sphk DialogActive = TRUE; 112230345Sjkh record_label_chunks(devs, dev); 112318636Sjkh clear_wins(); 11248549Sjkh } 11258549Sjkh else 11268549Sjkh msg = "A most prudent choice!"; 11278549Sjkh break; 11288549Sjkh 112921698Sjkh case '\033': /* ESC */ 11309202Srgrimes case 'Q': 11318549Sjkh labeling = FALSE; 11328549Sjkh break; 11338549Sjkh 11348549Sjkh default: 11358549Sjkh beep(); 113617362Sjkh sprintf(_msg, "Invalid key %d - Type F1 or ? for help", key); 113717362Sjkh msg = _msg; 11388549Sjkh break; 11398549Sjkh } 114029633Sjkh if (label_chunk_info[here].type == PART_SLICE) 114129633Sjkh pslice_focus = here; 114229633Sjkh else 114329633Sjkh label_focus = here; 11448549Sjkh } 114554587Sjkh restorescr(w); 114654587Sjkh return DITEM_SUCCESS; 11478549Sjkh} 114826456Sjkh 114987557Sdillonstatic __inline int 115087557Sdillonrequested_part_size(char *varName, int nom, int def, int perc) 115187557Sdillon{ 115287557Sdillon char *cp; 115387557Sdillon int sz; 115487557Sdillon 115587557Sdillon if ((cp = variable_get(VAR_ROOT_SIZE)) != NULL) 115687557Sdillon sz = atoi(cp); 115787557Sdillon else 115887557Sdillon sz = nom + (def - nom) * perc / 100; 115987557Sdillon return(sz * ONE_MEG); 116087557Sdillon} 116187557Sdillon 116287557Sdillon/* 116387557Sdillon * Attempt to auto-label the disk. 'perc' (0-100) scales 116487557Sdillon * the size of the various partitions within appropriate 116587557Sdillon * bounds (NOMINAL through DEFAULT sizes). The procedure 116687557Sdillon * succeeds of NULL is returned. A non-null return message 116787557Sdillon * is either a failure-status message (*req == 0), or 116887557Sdillon * a confirmation requestor (*req == 1). *req is 0 on 116987557Sdillon * entry to this call. 117087557Sdillon * 117187583Sdillon * We autolabel the following partitions: /, swap, /var, /tmp, /usr, 117287557Sdillon * and /home. /home receives any extra left over disk space. 117387557Sdillon */ 117487557Sdillonstatic char * 117587557Sdillontry_auto_label(Device **devs, Device *dev, int perc, int *req) 117687557Sdillon{ 117787557Sdillon int sz; 117887557Sdillon struct chunk *root_chunk = NULL; 117987557Sdillon struct chunk *swap_chunk = NULL; 118087557Sdillon struct chunk *usr_chunk = NULL; 118187557Sdillon struct chunk *var_chunk = NULL; 118287581Sdillon struct chunk *tmp_chunk = NULL; 118387557Sdillon struct chunk *home_chunk = NULL; 118487557Sdillon int mib[2]; 118587557Sdillon unsigned int physmem; 118687557Sdillon size_t size; 118787557Sdillon Chunk *rootdev, *swapdev, *usrdev, *vardev; 118887581Sdillon Chunk *tmpdev, *homedev; 118987557Sdillon char *msg = NULL; 119087557Sdillon 119187557Sdillon sz = space_free(label_chunk_info[here].c); 119287557Sdillon if (sz <= FS_MIN_SIZE) 119387557Sdillon return("Not enough free space to create a new partition in the slice"); 119487557Sdillon 119587557Sdillon (void)checkLabels(FALSE, &rootdev, &swapdev, &usrdev, 119687581Sdillon &vardev, &tmpdev, &homedev); 119787557Sdillon if (!rootdev) { 119887557Sdillon sz = requested_part_size(VAR_ROOT_SIZE, ROOT_NOMINAL_SIZE, ROOT_DEFAULT_SIZE, perc); 119987557Sdillon 120087581Sdillon root_chunk = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 120187581Sdillon label_chunk_info[here].c, sz, part, 120287581Sdillon FS_BSDFFS, CHUNK_IS_ROOT | CHUNK_AUTO_SIZE); 120387557Sdillon if (!root_chunk) { 120487557Sdillon *req = 1; 120587557Sdillon msg = "Unable to create the root partition. Too big?"; 120687557Sdillon goto done; 120787557Sdillon } 120887557Sdillon root_chunk->private_data = new_part("/", TRUE, root_chunk->size); 120987557Sdillon root_chunk->private_free = safe_free; 121087581Sdillon root_chunk->flags |= CHUNK_NEWFS; 121187557Sdillon record_label_chunks(devs, dev); 121287557Sdillon } 121387557Sdillon if (!swapdev) { 121487557Sdillon sz = requested_part_size(VAR_SWAP_SIZE, 0, 0, perc); 121587557Sdillon if (sz == 0) { 121687557Sdillon int nom; 121787557Sdillon int def; 121887557Sdillon 121987557Sdillon mib[0] = CTL_HW; 122087557Sdillon mib[1] = HW_PHYSMEM; 122187557Sdillon size = sizeof physmem; 122287557Sdillon sysctl(mib, 2, &physmem, &size, (void *)0, (size_t)0); 122387557Sdillon def = 2 * (int)(physmem / 512); 122487557Sdillon if (def < SWAP_MIN_SIZE * ONE_MEG) 122587557Sdillon def = SWAP_MIN_SIZE * ONE_MEG; 122687557Sdillon if (def > SWAP_AUTO_LIMIT_SIZE * ONE_MEG) 122787557Sdillon def = SWAP_AUTO_LIMIT_SIZE * ONE_MEG; 122887557Sdillon nom = (int)(physmem / 512) / 2; 122987557Sdillon sz = nom + (def - nom) * perc / 100; 123087557Sdillon } 123187581Sdillon swap_chunk = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 123287581Sdillon label_chunk_info[here].c, sz, part, 123387581Sdillon FS_SWAP, CHUNK_AUTO_SIZE); 123487557Sdillon if (!swap_chunk) { 123587557Sdillon *req = 1; 123687557Sdillon msg = "Unable to create the swap partition. Too big?"; 123787557Sdillon goto done; 123887557Sdillon } 123987557Sdillon swap_chunk->private_data = 0; 124087557Sdillon swap_chunk->private_free = safe_free; 124187557Sdillon record_label_chunks(devs, dev); 124287557Sdillon } 124387557Sdillon if (!vardev) { 124487557Sdillon sz = requested_part_size(VAR_VAR_SIZE, VAR_NOMINAL_SIZE, VAR_DEFAULT_SIZE, perc); 124587557Sdillon 124687581Sdillon var_chunk = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 124787581Sdillon label_chunk_info[here].c, sz, part, 124887581Sdillon FS_BSDFFS, CHUNK_AUTO_SIZE); 124987557Sdillon if (!var_chunk) { 125087557Sdillon *req = 1; 125187557Sdillon msg = "Not enough free space for /var - you will need to\n" 125287557Sdillon "partition your disk manually with a custom install!"; 125387557Sdillon goto done; 125487557Sdillon } 125587557Sdillon var_chunk->private_data = new_part("/var", TRUE, var_chunk->size); 125687557Sdillon var_chunk->private_free = safe_free; 125787581Sdillon var_chunk->flags |= CHUNK_NEWFS; 125887557Sdillon record_label_chunks(devs, dev); 125987557Sdillon } 126087583Sdillon if (!tmpdev && !variable_get(VAR_NO_TMP)) { 126187583Sdillon sz = requested_part_size(VAR_TMP_SIZE, TMP_NOMINAL_SIZE, TMP_DEFAULT_SIZE, perc); 126287557Sdillon 126387581Sdillon tmp_chunk = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 126487581Sdillon label_chunk_info[here].c, sz, part, 126587581Sdillon FS_BSDFFS, CHUNK_AUTO_SIZE); 126687581Sdillon if (!tmp_chunk) { 126787557Sdillon *req = 1; 126887583Sdillon msg = "Not enough free space for /tmp - you will need to\n" 126987557Sdillon "partition your disk manually with a custom install!"; 127087557Sdillon goto done; 127187557Sdillon } 127287581Sdillon tmp_chunk->private_data = new_part("/tmp", TRUE, tmp_chunk->size); 127387581Sdillon tmp_chunk->private_free = safe_free; 127487581Sdillon tmp_chunk->flags |= CHUNK_NEWFS; 127587557Sdillon record_label_chunks(devs, dev); 127687557Sdillon } 127787557Sdillon if (!usrdev && !variable_get(VAR_NO_USR)) { 127887557Sdillon sz = requested_part_size(VAR_USR_SIZE, USR_NOMINAL_SIZE, USR_DEFAULT_SIZE, perc); 127988996Sdillon#if AUTO_HOME == 0 128087557Sdillon sz = space_free(label_chunk_info[here].c); 128187557Sdillon#endif 128287557Sdillon if (sz) { 128387557Sdillon if (sz < (USR_MIN_SIZE * ONE_MEG)) { 128487557Sdillon *req = 1; 128587557Sdillon msg = "Not enough free space for /usr - you will need to\n" 128687557Sdillon "partition your disk manually with a custom install!"; 128787557Sdillon } 128887557Sdillon 128987557Sdillon usr_chunk = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 129087581Sdillon label_chunk_info[here].c, sz, part, 129187581Sdillon FS_BSDFFS, CHUNK_AUTO_SIZE); 129287557Sdillon if (!usr_chunk) { 129387557Sdillon msg = "Unable to create the /usr partition. Not enough space?\n" 129487557Sdillon "You will need to partition your disk manually with a custom install!"; 129587557Sdillon goto done; 129687557Sdillon } 129787557Sdillon usr_chunk->private_data = new_part("/usr", TRUE, usr_chunk->size); 129887557Sdillon usr_chunk->private_free = safe_free; 129987581Sdillon usr_chunk->flags |= CHUNK_NEWFS; 130087557Sdillon record_label_chunks(devs, dev); 130187557Sdillon } 130287557Sdillon } 130388996Sdillon#if AUTO_HOME == 1 130487557Sdillon if (!homedev && !variable_get(VAR_NO_HOME)) { 130587557Sdillon sz = requested_part_size(VAR_HOME_SIZE, HOME_NOMINAL_SIZE, HOME_DEFAULT_SIZE, perc); 130687557Sdillon if (sz < space_free(label_chunk_info[here].c)) 130787557Sdillon sz = space_free(label_chunk_info[here].c); 130887557Sdillon if (sz) { 130987557Sdillon if (sz < (HOME_MIN_SIZE * ONE_MEG)) { 131087557Sdillon *req = 1; 131187557Sdillon msg = "Not enough free space for /home - you will need to\n" 131287557Sdillon "partition your disk manually with a custom install!"; 131387557Sdillon goto done; 131487557Sdillon } 131587557Sdillon 131687557Sdillon home_chunk = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 131787581Sdillon label_chunk_info[here].c, sz, part, 131887581Sdillon FS_BSDFFS, CHUNK_AUTO_SIZE); 131987557Sdillon if (!home_chunk) { 132087557Sdillon msg = "Unable to create the /home partition. Not enough space?\n" 132187557Sdillon "You will need to partition your disk manually with a custom install!"; 132287557Sdillon goto done; 132387557Sdillon } 132487557Sdillon home_chunk->private_data = new_part("/home", TRUE, home_chunk->size); 132587557Sdillon home_chunk->private_free = safe_free; 132687581Sdillon home_chunk->flags |= CHUNK_NEWFS; 132787557Sdillon record_label_chunks(devs, dev); 132887557Sdillon } 132987557Sdillon } 133088996Sdillon#endif 133187557Sdillon 133287557Sdillon /* At this point, we're reasonably "labelled" */ 133387557Sdillon if (variable_cmp(DISK_LABELLED, "written")) 133487557Sdillon variable_set2(DISK_LABELLED, "yes", 0); 133587557Sdillon 133687557Sdillondone: 133787557Sdillon if (msg) { 133887557Sdillon if (root_chunk) 133987557Sdillon Delete_Chunk(root_chunk->disk, root_chunk); 134087557Sdillon if (swap_chunk) 134187557Sdillon Delete_Chunk(swap_chunk->disk, swap_chunk); 134287557Sdillon if (var_chunk) 134387557Sdillon Delete_Chunk(var_chunk->disk, var_chunk); 134487581Sdillon if (tmp_chunk) 134587581Sdillon Delete_Chunk(tmp_chunk->disk, tmp_chunk); 134687557Sdillon if (usr_chunk) 134787557Sdillon Delete_Chunk(usr_chunk->disk, usr_chunk); 134887557Sdillon if (home_chunk) 134987557Sdillon Delete_Chunk(home_chunk->disk, home_chunk); 135087557Sdillon record_label_chunks(devs, dev); 135187557Sdillon } 135287557Sdillon return(msg); 135387557Sdillon} 135487557Sdillon 135526456Sjkhstatic int 135630345SjkhdiskLabelNonInteractive(Device *dev) 135726456Sjkh{ 135826456Sjkh char *cp; 135926456Sjkh PartType type; 136026456Sjkh PartInfo *p; 136126456Sjkh u_long flags = 0; 136226456Sjkh int i, status; 136326456Sjkh Device **devs; 136426456Sjkh Disk *d; 136554587Sjkh 136626456Sjkh status = DITEM_SUCCESS; 136726456Sjkh cp = variable_get(VAR_DISK); 136826456Sjkh if (!cp) { 136926456Sjkh msgConfirm("diskLabel: No disk selected - can't label automatically."); 137026456Sjkh return DITEM_FAILURE; 137126456Sjkh } 137226456Sjkh devs = deviceFind(cp, DEVICE_TYPE_DISK); 137326456Sjkh if (!devs) { 137426456Sjkh msgConfirm("diskLabel: No disk device %s found!", cp); 137526456Sjkh return DITEM_FAILURE; 137626456Sjkh } 137730345Sjkh if (dev) 137830345Sjkh d = dev->private; 137930345Sjkh else 138030345Sjkh d = devs[0]->private; 138142386Sjkh#ifdef __alpha__ 138243392Sjkh maybe_dedicate(d); 138342386Sjkh#endif 138430345Sjkh record_label_chunks(devs, dev); 138526456Sjkh for (i = 0; label_chunk_info[i].c; i++) { 138626456Sjkh Chunk *c1 = label_chunk_info[i].c; 138726456Sjkh 138826456Sjkh if (label_chunk_info[i].type == PART_SLICE) { 138928075Sjkh char name[512]; 139074674Sjkh int entries = 1; 139126456Sjkh 139228075Sjkh while (entries) { 139328075Sjkh snprintf(name, sizeof name, "%s-%d", c1->name, entries); 139428075Sjkh if ((cp = variable_get(name)) != NULL) { 139574674Sjkh int sz, soft = 0; 139628075Sjkh char typ[10], mpoint[50]; 139726456Sjkh 139874156Sjkh if (sscanf(cp, "%s %d %s %d", typ, &sz, mpoint, &soft) < 3) { 139928075Sjkh msgConfirm("For slice entry %s, got an invalid detail entry of: %s", c1->name, cp); 140026456Sjkh status = DITEM_FAILURE; 140126456Sjkh continue; 140226456Sjkh } 140326456Sjkh else { 140428075Sjkh Chunk *tmp; 140528075Sjkh 140628075Sjkh if (!strcmp(typ, "swap")) { 140728075Sjkh type = PART_SWAP; 140828075Sjkh strcpy(mpoint, "SWAP"); 140928075Sjkh } 141028075Sjkh else { 141128075Sjkh type = PART_FILESYSTEM; 141228075Sjkh if (!strcmp(mpoint, "/")) 141328075Sjkh flags |= CHUNK_IS_ROOT; 141433132Sjkh else 141533132Sjkh flags &= ~CHUNK_IS_ROOT; 141628075Sjkh } 141728075Sjkh if (!sz) 141828075Sjkh sz = space_free(c1); 141928075Sjkh if (sz > space_free(c1)) { 142028075Sjkh msgConfirm("Not enough free space to create partition: %s", mpoint); 142128075Sjkh status = DITEM_FAILURE; 142228075Sjkh continue; 142328075Sjkh } 142428075Sjkh if (!(tmp = Create_Chunk_DWIM(d, c1, sz, part, 142528075Sjkh (type == PART_SWAP) ? FS_SWAP : FS_BSDFFS, flags))) { 142628075Sjkh msgConfirm("Unable to create from partition spec: %s. Too big?", cp); 142728075Sjkh status = DITEM_FAILURE; 142828075Sjkh break; 142928075Sjkh } 143028075Sjkh else { 143128075Sjkh tmp->private_data = new_part(mpoint, TRUE, sz); 143228075Sjkh tmp->private_free = safe_free; 143374674Sjkh ((PartInfo *)tmp->private_data)->soft = soft; 143428075Sjkh status = DITEM_SUCCESS; 143528075Sjkh } 143626456Sjkh } 143728075Sjkh entries++; 143826456Sjkh } 143928075Sjkh else { 144028075Sjkh /* No more matches, leave the loop */ 144128075Sjkh entries = 0; 144228075Sjkh } 144326456Sjkh } 144426456Sjkh } 144526456Sjkh else { 144628075Sjkh /* Must be something we can set a mountpoint for */ 144726456Sjkh cp = variable_get(c1->name); 144826456Sjkh if (cp) { 144928075Sjkh char mpoint[50], do_newfs[8]; 145026456Sjkh Boolean newfs = FALSE; 145126456Sjkh 145228075Sjkh do_newfs[0] = '\0'; 145328075Sjkh if (sscanf(cp, "%s %s", mpoint, do_newfs) != 2) { 145426456Sjkh msgConfirm("For slice entry %s, got an invalid detail entry of: %s", c1->name, cp); 145526456Sjkh status = DITEM_FAILURE; 145626456Sjkh continue; 145726456Sjkh } 145828075Sjkh newfs = toupper(do_newfs[0]) == 'Y' ? TRUE : FALSE; 145926456Sjkh if (c1->private_data) { 146026456Sjkh p = c1->private_data; 146126456Sjkh p->newfs = newfs; 146226456Sjkh strcpy(p->mountpoint, mpoint); 146326456Sjkh } 146426456Sjkh else { 146526456Sjkh c1->private_data = new_part(mpoint, newfs, 0); 146626456Sjkh c1->private_free = safe_free; 146726456Sjkh } 146826456Sjkh if (!strcmp(mpoint, "/")) 146926456Sjkh c1->flags |= CHUNK_IS_ROOT; 147026456Sjkh else 147126456Sjkh c1->flags &= ~CHUNK_IS_ROOT; 147226456Sjkh } 147326456Sjkh } 147426456Sjkh } 147526456Sjkh if (status == DITEM_SUCCESS) 147643685Sjkh variable_set2(DISK_LABELLED, "yes", 0); 147726456Sjkh return status; 147826456Sjkh} 1479