1/* 2 * The new sysinstall program. 3 * 4 * This is probably the last program in the `sysinstall' line - the next 5 * generation being essentially a complete rewrite. 6 *
| 1/* 2 * The new sysinstall program. 3 * 4 * This is probably the last program in the `sysinstall' line - the next 5 * generation being essentially a complete rewrite. 6 *
|
7 * $Id: label.c,v 1.19 1995/05/21 17:53:27 jkh Exp $
| 7 * $Id: label.c,v 1.20 1995/05/21 18:24:33 jkh Exp $
|
8 * 9 * Copyright (c) 1995 10 * Jordan Hubbard. All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer, 17 * verbatim and that no modifications are made prior to this 18 * point in the file. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution. 22 * 3. All advertising materials mentioning features or use of this software 23 * must display the following acknowledgement: 24 * This product includes software developed by Jordan Hubbard 25 * for the FreeBSD Project. 26 * 4. The name of Jordan Hubbard or the FreeBSD project may not be used to 27 * endorse or promote products derived from this software without specific 28 * prior written permission. 29 * 30 * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND 31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33 * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE 34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 36 * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) 37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 40 * SUCH DAMAGE. 41 * 42 */ 43 44#include "sysinstall.h" 45#include <ctype.h> 46#include <sys/disklabel.h> 47 48/* 49 * Everything to do with editing the contents of disk labels. 50 */ 51 52/* A nice message we use a lot in the disklabel editor */ 53#define MSG_NOT_APPLICABLE "That option is not applicable here" 54 55/* 56 * I make some pretty gross assumptions about having a max of 50 chunks 57 * total - 8 slices and 42 partitions. I can't easily display many more 58 * than that on the screen at once! 59 * 60 * For 2.1 I'll revisit this and try to make it more dynamic, but since 61 * this will catch 99.99% of all possible cases, I'm not too worried. 62 */ 63#define MAX_CHUNKS 50 64 65/* Where to start printing the freebsd slices */ 66#define CHUNK_SLICE_START_ROW 2 67#define CHUNK_PART_START_ROW 11 68
| 8 * 9 * Copyright (c) 1995 10 * Jordan Hubbard. All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer, 17 * verbatim and that no modifications are made prior to this 18 * point in the file. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution. 22 * 3. All advertising materials mentioning features or use of this software 23 * must display the following acknowledgement: 24 * This product includes software developed by Jordan Hubbard 25 * for the FreeBSD Project. 26 * 4. The name of Jordan Hubbard or the FreeBSD project may not be used to 27 * endorse or promote products derived from this software without specific 28 * prior written permission. 29 * 30 * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND 31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33 * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE 34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 36 * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) 37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 40 * SUCH DAMAGE. 41 * 42 */ 43 44#include "sysinstall.h" 45#include <ctype.h> 46#include <sys/disklabel.h> 47 48/* 49 * Everything to do with editing the contents of disk labels. 50 */ 51 52/* A nice message we use a lot in the disklabel editor */ 53#define MSG_NOT_APPLICABLE "That option is not applicable here" 54 55/* 56 * I make some pretty gross assumptions about having a max of 50 chunks 57 * total - 8 slices and 42 partitions. I can't easily display many more 58 * than that on the screen at once! 59 * 60 * For 2.1 I'll revisit this and try to make it more dynamic, but since 61 * this will catch 99.99% of all possible cases, I'm not too worried. 62 */ 63#define MAX_CHUNKS 50 64 65/* Where to start printing the freebsd slices */ 66#define CHUNK_SLICE_START_ROW 2 67#define CHUNK_PART_START_ROW 11 68
|
| 69/* One MB worth of blocks */ 70#define ONE_MEG 2048 71
|
69/* The smallest filesystem we're willing to create */
| 72/* The smallest filesystem we're willing to create */
|
70#define FS_MIN_SIZE 2048
| 73#define FS_MIN_SIZE ONE_MEG
|
71 72/* The smallest root filesystem we're willing to create */
| 74 75/* The smallest root filesystem we're willing to create */
|
73#define ROOT_MIN_SIZE 40960 /* 20MB */
| 76#define ROOT_MIN_SIZE (20 * ONE_MEG)
|
74 75/* All the chunks currently displayed on the screen */ 76static struct { 77 struct disk *d; 78 struct chunk *c; 79 PartType type; 80} label_chunk_info[MAX_CHUNKS + 1]; 81static int here; 82 83/* See if we're already using a desired partition name */ 84static Boolean 85check_conflict(char *name) 86{ 87 int i; 88 89 for (i = 0; label_chunk_info[i].d; i++) 90 if (label_chunk_info[i].type == PART_FILESYSTEM 91 && label_chunk_info[i].c->private 92 && !strcmp(((PartInfo *)label_chunk_info[i].c->private)->mountpoint, name)) 93 return TRUE; 94 return FALSE; 95} 96 97/* How much space is in this FreeBSD slice? */ 98static int 99space_free(struct chunk *c) 100{ 101 struct chunk *c1 = c->part; 102 int sz = c->size; 103 104 while (c1) { 105 if (c1->type != unused) 106 sz -= c1->size; 107 c1 = c1->next; 108 } 109 if (sz < 0) 110 msgFatal("Partitions are larger than actual chunk??"); 111 return sz; 112} 113 114/* Snapshot the current situation into the displayed chunks structure */ 115static void 116record_label_chunks() 117{ 118 int i, j, p; 119 struct chunk *c1, *c2; 120 Device **devs; 121 Disk *d; 122 123 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 124 if (!devs) { 125 msgConfirm("No disks found!"); 126 return; 127 } 128 129 j = p = 0; 130 /* First buzz through and pick up the FreeBSD slices */ 131 for (i = 0; devs[i]; i++) { 132 if (!devs[i]->enabled) 133 continue; 134 d = (Disk *)devs[i]->private; 135 if (!d->chunks) 136 msgFatal("No chunk list found for %s!", d->name); 137 138 /* Put the slice entries first */ 139 for (c1 = d->chunks->part; c1; c1 = c1->next) { 140 if (c1->type == freebsd) { 141 label_chunk_info[j].type = PART_SLICE; 142 label_chunk_info[j].d = d; 143 label_chunk_info[j].c = c1; 144 ++j; 145 } 146 } 147 } 148 /* Now run through again and get the FreeBSD partition entries */ 149 for (i = 0; devs[i]; i++) { 150 if (!devs[i]->enabled) 151 continue; 152 d = (Disk *)devs[i]->private; 153 /* Then buzz through and pick up the partitions */ 154 for (c1 = d->chunks->part; c1; c1 = c1->next) { 155 if (c1->type == freebsd) { 156 for (c2 = c1->part; c2; c2 = c2->next) { 157 if (c2->type == part) { 158 if (c2->subtype == FS_SWAP) 159 label_chunk_info[j].type = PART_SWAP; 160 else 161 label_chunk_info[j].type = PART_FILESYSTEM; 162 label_chunk_info[j].d = d; 163 label_chunk_info[j].c = c2; 164 ++j; 165 } 166 } 167 } 168 else if (c1->type == fat) { 169 label_chunk_info[j].type = PART_FAT; 170 label_chunk_info[j].d = d; 171 label_chunk_info[j].c = c1;
| 77 78/* All the chunks currently displayed on the screen */ 79static struct { 80 struct disk *d; 81 struct chunk *c; 82 PartType type; 83} label_chunk_info[MAX_CHUNKS + 1]; 84static int here; 85 86/* See if we're already using a desired partition name */ 87static Boolean 88check_conflict(char *name) 89{ 90 int i; 91 92 for (i = 0; label_chunk_info[i].d; i++) 93 if (label_chunk_info[i].type == PART_FILESYSTEM 94 && label_chunk_info[i].c->private 95 && !strcmp(((PartInfo *)label_chunk_info[i].c->private)->mountpoint, name)) 96 return TRUE; 97 return FALSE; 98} 99 100/* How much space is in this FreeBSD slice? */ 101static int 102space_free(struct chunk *c) 103{ 104 struct chunk *c1 = c->part; 105 int sz = c->size; 106 107 while (c1) { 108 if (c1->type != unused) 109 sz -= c1->size; 110 c1 = c1->next; 111 } 112 if (sz < 0) 113 msgFatal("Partitions are larger than actual chunk??"); 114 return sz; 115} 116 117/* Snapshot the current situation into the displayed chunks structure */ 118static void 119record_label_chunks() 120{ 121 int i, j, p; 122 struct chunk *c1, *c2; 123 Device **devs; 124 Disk *d; 125 126 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 127 if (!devs) { 128 msgConfirm("No disks found!"); 129 return; 130 } 131 132 j = p = 0; 133 /* First buzz through and pick up the FreeBSD slices */ 134 for (i = 0; devs[i]; i++) { 135 if (!devs[i]->enabled) 136 continue; 137 d = (Disk *)devs[i]->private; 138 if (!d->chunks) 139 msgFatal("No chunk list found for %s!", d->name); 140 141 /* Put the slice entries first */ 142 for (c1 = d->chunks->part; c1; c1 = c1->next) { 143 if (c1->type == freebsd) { 144 label_chunk_info[j].type = PART_SLICE; 145 label_chunk_info[j].d = d; 146 label_chunk_info[j].c = c1; 147 ++j; 148 } 149 } 150 } 151 /* Now run through again and get the FreeBSD partition entries */ 152 for (i = 0; devs[i]; i++) { 153 if (!devs[i]->enabled) 154 continue; 155 d = (Disk *)devs[i]->private; 156 /* Then buzz through and pick up the partitions */ 157 for (c1 = d->chunks->part; c1; c1 = c1->next) { 158 if (c1->type == freebsd) { 159 for (c2 = c1->part; c2; c2 = c2->next) { 160 if (c2->type == part) { 161 if (c2->subtype == FS_SWAP) 162 label_chunk_info[j].type = PART_SWAP; 163 else 164 label_chunk_info[j].type = PART_FILESYSTEM; 165 label_chunk_info[j].d = d; 166 label_chunk_info[j].c = c2; 167 ++j; 168 } 169 } 170 } 171 else if (c1->type == fat) { 172 label_chunk_info[j].type = PART_FAT; 173 label_chunk_info[j].d = d; 174 label_chunk_info[j].c = c1;
|
| 175 ++j;
|
172 } 173 } 174 } 175 label_chunk_info[j].d = NULL; 176 label_chunk_info[j].c = NULL; 177 if (here >= j) 178 here = j ? j - 1 : 0; 179} 180 181/* A new partition entry */ 182static PartInfo * 183new_part(char *mpoint, Boolean newfs, u_long size) 184{ 185 PartInfo *ret; 186 u_long target,divisor; 187 188 ret = (PartInfo *)safe_malloc(sizeof(PartInfo)); 189 strncpy(ret->mountpoint, mpoint, FILENAME_MAX); 190 strcpy(ret->newfs_cmd, "newfs"); 191 ret->newfs = newfs; 192 if (!size) 193 return ret; 194 for(target = size; target; target--) { 195 for(divisor = 4096 ; divisor > 1023; divisor--) { 196 if (!(target % divisor)) { 197 sprintf(ret->newfs_cmd+strlen(ret->newfs_cmd), 198 " -u %ld",divisor); 199 return ret; 200 } 201 } 202 } 203 return ret; 204} 205 206/* Get the mountpoint for a partition and save it away */ 207PartInfo * 208get_mountpoint(struct chunk *old) 209{ 210 char *val; 211 PartInfo *tmp; 212
| 176 } 177 } 178 } 179 label_chunk_info[j].d = NULL; 180 label_chunk_info[j].c = NULL; 181 if (here >= j) 182 here = j ? j - 1 : 0; 183} 184 185/* A new partition entry */ 186static PartInfo * 187new_part(char *mpoint, Boolean newfs, u_long size) 188{ 189 PartInfo *ret; 190 u_long target,divisor; 191 192 ret = (PartInfo *)safe_malloc(sizeof(PartInfo)); 193 strncpy(ret->mountpoint, mpoint, FILENAME_MAX); 194 strcpy(ret->newfs_cmd, "newfs"); 195 ret->newfs = newfs; 196 if (!size) 197 return ret; 198 for(target = size; target; target--) { 199 for(divisor = 4096 ; divisor > 1023; divisor--) { 200 if (!(target % divisor)) { 201 sprintf(ret->newfs_cmd+strlen(ret->newfs_cmd), 202 " -u %ld",divisor); 203 return ret; 204 } 205 } 206 } 207 return ret; 208} 209 210/* Get the mountpoint for a partition and save it away */ 211PartInfo * 212get_mountpoint(struct chunk *old) 213{ 214 char *val; 215 PartInfo *tmp; 216
|
213 dialog_clear(); clear();
| |
214 val = msgGetInput(old && old->private ? ((PartInfo *)old->private)->mountpoint : NULL, 215 "Please specify a mount point for the partition"); 216 if (!val) 217 return NULL; 218 219 /* Is it just the same value? */ 220 if (old && old->private && !strcmp(((PartInfo *)old->private)->mountpoint, val)) 221 return NULL; 222 if (check_conflict(val)) { 223 msgConfirm("You already have a mount point for %s assigned!", val); 224 return NULL; 225 } 226 if (*val != '/') { 227 msgConfirm("Mount point must start with a / character"); 228 return NULL; 229 } 230 if (!strcmp(val, "/")) { 231 if (old) 232 old->flags |= CHUNK_IS_ROOT; 233 } else if (old) { 234 old->flags &= ~CHUNK_IS_ROOT; 235 } 236 safe_free(old ? old->private : NULL); 237 tmp = new_part(val, TRUE, 0); 238 if (old) { 239 old->private = tmp; 240 old->private_free = safe_free; 241 } 242 return tmp; 243} 244 245/* Get the type of the new partiton */ 246static PartType 247get_partition_type(void) 248{ 249 char selection[20]; 250 int i; 251 252 static unsigned char *fs_types[] = { 253 "FS", 254 "A file system", 255 "Swap", 256 "A swap partition.", 257 };
| 217 val = msgGetInput(old && old->private ? ((PartInfo *)old->private)->mountpoint : NULL, 218 "Please specify a mount point for the partition"); 219 if (!val) 220 return NULL; 221 222 /* Is it just the same value? */ 223 if (old && old->private && !strcmp(((PartInfo *)old->private)->mountpoint, val)) 224 return NULL; 225 if (check_conflict(val)) { 226 msgConfirm("You already have a mount point for %s assigned!", val); 227 return NULL; 228 } 229 if (*val != '/') { 230 msgConfirm("Mount point must start with a / character"); 231 return NULL; 232 } 233 if (!strcmp(val, "/")) { 234 if (old) 235 old->flags |= CHUNK_IS_ROOT; 236 } else if (old) { 237 old->flags &= ~CHUNK_IS_ROOT; 238 } 239 safe_free(old ? old->private : NULL); 240 tmp = new_part(val, TRUE, 0); 241 if (old) { 242 old->private = tmp; 243 old->private_free = safe_free; 244 } 245 return tmp; 246} 247 248/* Get the type of the new partiton */ 249static PartType 250get_partition_type(void) 251{ 252 char selection[20]; 253 int i; 254 255 static unsigned char *fs_types[] = { 256 "FS", 257 "A file system", 258 "Swap", 259 "A swap partition.", 260 };
|
258 dialog_clear(); clear();
| |
259 i = dialog_menu("Please choose a partition type", 260 "If you want to use this partition for swap space, select Swap.\nIf you want to put a filesystem on it, choose FS.", -1, -1, 2, 2, fs_types, selection, NULL, NULL); 261 if (!i) { 262 if (!strcmp(selection, "FS")) 263 return PART_FILESYSTEM; 264 else if (!strcmp(selection, "Swap")) 265 return PART_SWAP; 266 } 267 return PART_NONE; 268} 269 270/* If the user wants a special newfs command for this, set it */ 271static void 272getNewfsCmd(PartInfo *p) 273{ 274 char *val; 275 276 val = msgGetInput(p->newfs_cmd, 277 "Please enter the newfs command and options you'd like to use in\ncreating this file system."); 278 if (val) 279 strncpy(p->newfs_cmd, val, NEWFS_CMD_MAX); 280} 281 282 283#define MAX_MOUNT_NAME 12 284 285#define PART_PART_COL 0 286#define PART_MOUNT_COL 8 287#define PART_SIZE_COL (PART_MOUNT_COL + MAX_MOUNT_NAME + 3) 288#define PART_NEWFS_COL (PART_SIZE_COL + 7) 289#define PART_OFF 38 290 291/* How many mounted partitions to display in column before going to next */ 292#define CHUNK_COLUMN_MAX 5 293 294/* stick this all up on the screen */ 295static void 296print_label_chunks(void) 297{ 298 int i, j, srow, prow, pcol; 299 int sz; 300 301 attrset(A_REVERSE); 302 mvaddstr(0, 25, "FreeBSD Disklabel Editor"); 303 clrtobot(); 304 attrset(A_NORMAL); 305 306 for (i = 0; i < 2; i++) { 307 mvaddstr(CHUNK_PART_START_ROW - 2, PART_PART_COL + (i * PART_OFF), "Part"); 308 mvaddstr(CHUNK_PART_START_ROW - 1, PART_PART_COL + (i * PART_OFF), "----"); 309 310 mvaddstr(CHUNK_PART_START_ROW - 2, PART_MOUNT_COL + (i * PART_OFF), "Mount"); 311 mvaddstr(CHUNK_PART_START_ROW - 1, PART_MOUNT_COL + (i * PART_OFF), "-----"); 312 313 mvaddstr(CHUNK_PART_START_ROW - 2, PART_SIZE_COL + (i * PART_OFF) + 2, "Size"); 314 mvaddstr(CHUNK_PART_START_ROW - 1, PART_SIZE_COL + (i * PART_OFF) + 2, "----"); 315 316 mvaddstr(CHUNK_PART_START_ROW - 2, PART_NEWFS_COL + (i * PART_OFF), "Newfs"); 317 mvaddstr(CHUNK_PART_START_ROW - 1, PART_NEWFS_COL + (i * PART_OFF), "-----"); 318 } 319 srow = CHUNK_SLICE_START_ROW; 320 prow = CHUNK_PART_START_ROW; 321 pcol = 0; 322 323 for (i = 0; label_chunk_info[i].d; i++) { 324 if (i == here) 325 attrset(A_REVERSE); 326 /* Is it a slice entry displayed at the top? */ 327 if (label_chunk_info[i].type == PART_SLICE) { 328 sz = space_free(label_chunk_info[i].c); 329 mvprintw(srow++, 0, 330 "Disk: %s\tPartition name: %s\tFree: %d blocks (%dMB)", 331 label_chunk_info[i].d->name,
| 261 i = dialog_menu("Please choose a partition type", 262 "If you want to use this partition for swap space, select Swap.\nIf you want to put a filesystem on it, choose FS.", -1, -1, 2, 2, fs_types, selection, NULL, NULL); 263 if (!i) { 264 if (!strcmp(selection, "FS")) 265 return PART_FILESYSTEM; 266 else if (!strcmp(selection, "Swap")) 267 return PART_SWAP; 268 } 269 return PART_NONE; 270} 271 272/* If the user wants a special newfs command for this, set it */ 273static void 274getNewfsCmd(PartInfo *p) 275{ 276 char *val; 277 278 val = msgGetInput(p->newfs_cmd, 279 "Please enter the newfs command and options you'd like to use in\ncreating this file system."); 280 if (val) 281 strncpy(p->newfs_cmd, val, NEWFS_CMD_MAX); 282} 283 284 285#define MAX_MOUNT_NAME 12 286 287#define PART_PART_COL 0 288#define PART_MOUNT_COL 8 289#define PART_SIZE_COL (PART_MOUNT_COL + MAX_MOUNT_NAME + 3) 290#define PART_NEWFS_COL (PART_SIZE_COL + 7) 291#define PART_OFF 38 292 293/* How many mounted partitions to display in column before going to next */ 294#define CHUNK_COLUMN_MAX 5 295 296/* stick this all up on the screen */ 297static void 298print_label_chunks(void) 299{ 300 int i, j, srow, prow, pcol; 301 int sz; 302 303 attrset(A_REVERSE); 304 mvaddstr(0, 25, "FreeBSD Disklabel Editor"); 305 clrtobot(); 306 attrset(A_NORMAL); 307 308 for (i = 0; i < 2; i++) { 309 mvaddstr(CHUNK_PART_START_ROW - 2, PART_PART_COL + (i * PART_OFF), "Part"); 310 mvaddstr(CHUNK_PART_START_ROW - 1, PART_PART_COL + (i * PART_OFF), "----"); 311 312 mvaddstr(CHUNK_PART_START_ROW - 2, PART_MOUNT_COL + (i * PART_OFF), "Mount"); 313 mvaddstr(CHUNK_PART_START_ROW - 1, PART_MOUNT_COL + (i * PART_OFF), "-----"); 314 315 mvaddstr(CHUNK_PART_START_ROW - 2, PART_SIZE_COL + (i * PART_OFF) + 2, "Size"); 316 mvaddstr(CHUNK_PART_START_ROW - 1, PART_SIZE_COL + (i * PART_OFF) + 2, "----"); 317 318 mvaddstr(CHUNK_PART_START_ROW - 2, PART_NEWFS_COL + (i * PART_OFF), "Newfs"); 319 mvaddstr(CHUNK_PART_START_ROW - 1, PART_NEWFS_COL + (i * PART_OFF), "-----"); 320 } 321 srow = CHUNK_SLICE_START_ROW; 322 prow = CHUNK_PART_START_ROW; 323 pcol = 0; 324 325 for (i = 0; label_chunk_info[i].d; i++) { 326 if (i == here) 327 attrset(A_REVERSE); 328 /* Is it a slice entry displayed at the top? */ 329 if (label_chunk_info[i].type == PART_SLICE) { 330 sz = space_free(label_chunk_info[i].c); 331 mvprintw(srow++, 0, 332 "Disk: %s\tPartition name: %s\tFree: %d blocks (%dMB)", 333 label_chunk_info[i].d->name,
|
332 label_chunk_info[i].c->name, sz, (sz / 2048));
| 334 label_chunk_info[i].c->name, sz, (sz / ONE_MEG));
|
333 } 334 /* Otherwise it's a DOS, swap or filesystem entry, at the bottom */ 335 else { 336 char onestr[PART_OFF], num[10], *mountpoint, *newfs; 337 338 /* 339 * We copy this into a blank-padded string so that it looks like 340 * a solid bar in reverse-video 341 */ 342 memset(onestr, ' ', PART_OFF - 1); 343 onestr[PART_OFF - 1] = '\0'; 344 /* Go for two columns */ 345 if (prow == (CHUNK_PART_START_ROW + CHUNK_COLUMN_MAX)) { 346 pcol = PART_OFF; 347 prow = CHUNK_PART_START_ROW; 348 } 349 memcpy(onestr + PART_PART_COL, label_chunk_info[i].c->name, 350 strlen(label_chunk_info[i].c->name)); 351 /* If it's a filesystem, display the mountpoint */ 352 if (label_chunk_info[i].type == PART_FILESYSTEM) { 353 if (label_chunk_info[i].c->private == NULL) { 354 static int mnt = 0; 355 char foo[10]; 356 357 /* 358 * Hmm! A partition that must have already been here. 359 * Fill in a fake mountpoint and register it 360 */ 361 sprintf(foo, "/mnt%d", mnt++); 362 label_chunk_info[i].c->private = 363 new_part(foo, FALSE,label_chunk_info[i].c->size); 364 label_chunk_info[i].c->private_free = safe_free; 365 } 366 mountpoint = ((PartInfo *)label_chunk_info[i].c->private)->mountpoint; 367 newfs = ((PartInfo *)label_chunk_info[i].c->private)->newfs ? "Y" : "N"; 368 } 369 else if (label_chunk_info[i].type == PART_SWAP) { 370 mountpoint = "swap"; 371 newfs = " "; 372 } 373 else if (label_chunk_info[i].type == PART_FAT) { 374 mountpoint = "DOS FAT"; 375 newfs = "*"; 376 } 377 else { 378 mountpoint = "<unknown>"; 379 newfs = "*"; 380 } 381 for (j = 0; j < MAX_MOUNT_NAME && mountpoint[j]; j++) 382 onestr[PART_MOUNT_COL + j] = mountpoint[j]; 383 snprintf(num, 10, "%4ldMB", label_chunk_info[i].c->size ?
| 335 } 336 /* Otherwise it's a DOS, swap or filesystem entry, at the bottom */ 337 else { 338 char onestr[PART_OFF], num[10], *mountpoint, *newfs; 339 340 /* 341 * We copy this into a blank-padded string so that it looks like 342 * a solid bar in reverse-video 343 */ 344 memset(onestr, ' ', PART_OFF - 1); 345 onestr[PART_OFF - 1] = '\0'; 346 /* Go for two columns */ 347 if (prow == (CHUNK_PART_START_ROW + CHUNK_COLUMN_MAX)) { 348 pcol = PART_OFF; 349 prow = CHUNK_PART_START_ROW; 350 } 351 memcpy(onestr + PART_PART_COL, label_chunk_info[i].c->name, 352 strlen(label_chunk_info[i].c->name)); 353 /* If it's a filesystem, display the mountpoint */ 354 if (label_chunk_info[i].type == PART_FILESYSTEM) { 355 if (label_chunk_info[i].c->private == NULL) { 356 static int mnt = 0; 357 char foo[10]; 358 359 /* 360 * Hmm! A partition that must have already been here. 361 * Fill in a fake mountpoint and register it 362 */ 363 sprintf(foo, "/mnt%d", mnt++); 364 label_chunk_info[i].c->private = 365 new_part(foo, FALSE,label_chunk_info[i].c->size); 366 label_chunk_info[i].c->private_free = safe_free; 367 } 368 mountpoint = ((PartInfo *)label_chunk_info[i].c->private)->mountpoint; 369 newfs = ((PartInfo *)label_chunk_info[i].c->private)->newfs ? "Y" : "N"; 370 } 371 else if (label_chunk_info[i].type == PART_SWAP) { 372 mountpoint = "swap"; 373 newfs = " "; 374 } 375 else if (label_chunk_info[i].type == PART_FAT) { 376 mountpoint = "DOS FAT"; 377 newfs = "*"; 378 } 379 else { 380 mountpoint = "<unknown>"; 381 newfs = "*"; 382 } 383 for (j = 0; j < MAX_MOUNT_NAME && mountpoint[j]; j++) 384 onestr[PART_MOUNT_COL + j] = mountpoint[j]; 385 snprintf(num, 10, "%4ldMB", label_chunk_info[i].c->size ?
|
384 label_chunk_info[i].c->size / 2048 : 0);
| 386 label_chunk_info[i].c->size / ONE_MEG : 0);
|
385 memcpy(onestr + PART_SIZE_COL, num, strlen(num)); 386 memcpy(onestr + PART_NEWFS_COL, newfs, strlen(newfs)); 387 onestr[PART_NEWFS_COL + strlen(newfs)] = '\0'; 388 mvaddstr(prow, pcol, onestr); 389 ++prow; 390 } 391 if (i == here) 392 attrset(A_NORMAL); 393 } 394} 395 396static void 397print_command_summary() 398{ 399 mvprintw(17, 0, 400 "The following commands are valid here (upper or lower case):"); 401 mvprintw(19, 0, "C = Create Partition D = Delete Partition M = Mount Partition"); 402 mvprintw(20, 0, "N = Newfs Options T = Toggle Newfs ESC = Exit this screen"); 403 mvprintw(21, 0, "The default target will be displayed in "); 404 405 attrset(A_REVERSE); 406 addstr("reverse video."); 407 attrset(A_NORMAL); 408 mvprintw(22, 0, "Use F1 or ? to get more help, arrow keys to move."); 409 move(0, 0); 410} 411 412int 413diskLabelEditor(char *str) 414{ 415 int sz, key = 0; 416 Boolean labeling; 417 char *msg = NULL; 418 PartInfo *p; 419 PartType type; 420 421 labeling = TRUE; 422 keypad(stdscr, TRUE); 423 record_label_chunks(); 424 425 if (!getenv(DISK_PARTITIONED)) { 426 msgConfirm("You need to partition your disk(s) before you can assign disk labels."); 427 return 0; 428 }
| 387 memcpy(onestr + PART_SIZE_COL, num, strlen(num)); 388 memcpy(onestr + PART_NEWFS_COL, newfs, strlen(newfs)); 389 onestr[PART_NEWFS_COL + strlen(newfs)] = '\0'; 390 mvaddstr(prow, pcol, onestr); 391 ++prow; 392 } 393 if (i == here) 394 attrset(A_NORMAL); 395 } 396} 397 398static void 399print_command_summary() 400{ 401 mvprintw(17, 0, 402 "The following commands are valid here (upper or lower case):"); 403 mvprintw(19, 0, "C = Create Partition D = Delete Partition M = Mount Partition"); 404 mvprintw(20, 0, "N = Newfs Options T = Toggle Newfs ESC = Exit this screen"); 405 mvprintw(21, 0, "The default target will be displayed in "); 406 407 attrset(A_REVERSE); 408 addstr("reverse video."); 409 attrset(A_NORMAL); 410 mvprintw(22, 0, "Use F1 or ? to get more help, arrow keys to move."); 411 move(0, 0); 412} 413 414int 415diskLabelEditor(char *str) 416{ 417 int sz, key = 0; 418 Boolean labeling; 419 char *msg = NULL; 420 PartInfo *p; 421 PartType type; 422 423 labeling = TRUE; 424 keypad(stdscr, TRUE); 425 record_label_chunks(); 426 427 if (!getenv(DISK_PARTITIONED)) { 428 msgConfirm("You need to partition your disk(s) before you can assign disk labels."); 429 return 0; 430 }
|
429 clear();
| 431 dialog_clear(); clear();
|
430 while (labeling) {
| 432 while (labeling) {
|
| 433 clear();
|
431 print_label_chunks(); 432 print_command_summary(); 433 if (msg) { 434 attrset(A_REVERSE); mvprintw(23, 0, msg); attrset(A_NORMAL); 435 beep(); 436 msg = NULL; 437 } 438 refresh(); 439 key = toupper(getch()); 440 switch (key) { 441 442 case KEY_UP: 443 case '-': 444 if (here != 0) 445 --here; 446 break; 447 448 case KEY_DOWN: 449 case '+': 450 case '\r': 451 case '\n': 452 if (label_chunk_info[here + 1].d) 453 ++here; 454 break; 455 456 case KEY_HOME: 457 here = 0; 458 break; 459 460 case KEY_END: 461 while (label_chunk_info[here + 1].d) 462 ++here; 463 break; 464 465 case KEY_F(1): 466 case '?': 467 systemDisplayFile("disklabel.hlp"); 468 break; 469 470 case 'C': 471 if (label_chunk_info[here].type != PART_SLICE) { 472 msg = "You can only do this in a master partition (see top of screen)"; 473 break; 474 } 475 sz = space_free(label_chunk_info[here].c); 476 if (sz <= FS_MIN_SIZE) { 477 msg = "Not enough space to create additional FreeBSD partition"; 478 break; 479 } 480 {
| 434 print_label_chunks(); 435 print_command_summary(); 436 if (msg) { 437 attrset(A_REVERSE); mvprintw(23, 0, msg); attrset(A_NORMAL); 438 beep(); 439 msg = NULL; 440 } 441 refresh(); 442 key = toupper(getch()); 443 switch (key) { 444 445 case KEY_UP: 446 case '-': 447 if (here != 0) 448 --here; 449 break; 450 451 case KEY_DOWN: 452 case '+': 453 case '\r': 454 case '\n': 455 if (label_chunk_info[here + 1].d) 456 ++here; 457 break; 458 459 case KEY_HOME: 460 here = 0; 461 break; 462 463 case KEY_END: 464 while (label_chunk_info[here + 1].d) 465 ++here; 466 break; 467 468 case KEY_F(1): 469 case '?': 470 systemDisplayFile("disklabel.hlp"); 471 break; 472 473 case 'C': 474 if (label_chunk_info[here].type != PART_SLICE) { 475 msg = "You can only do this in a master partition (see top of screen)"; 476 break; 477 } 478 sz = space_free(label_chunk_info[here].c); 479 if (sz <= FS_MIN_SIZE) { 480 msg = "Not enough space to create additional FreeBSD partition"; 481 break; 482 } 483 {
|
481 char *val, *cp, tmpb[20]; 482 int size; 483 struct chunk *tmp; 484 u_long flags = 0;
| 484 char *val, *cp, tmpb[20]; 485 int size; 486 struct chunk *tmp; 487 u_long flags = 0;
|
485
| 488
|
486 snprintf(tmpb, 20, "%d", sz); 487 val = msgGetInput(tmpb, "Please specify the size for new FreeBSD partition in blocks, or append\na trailing `M' for megabytes (e.g. 20M)."); 488 if (!val || (size = strtol(val, &cp, 0)) <= 0) 489 break;
| 489 snprintf(tmpb, 20, "%d", sz); 490 val = msgGetInput(tmpb, "Please specify the size for new FreeBSD partition in blocks, or append\na trailing `M' for megabytes (e.g. 20M)."); 491 if (!val || (size = strtol(val, &cp, 0)) <= 0) 492 break;
|
490
| 493
|
491 if (*cp && toupper(*cp) == 'M') 492 size *= 2048;
| 494 if (sz <= FS_MIN_SIZE) { 495 msgConfirm("The minimum filesystem size is %dMB", FS_MIN_SIZE / ONE_MEG); 496 break; 497 } 498 if (*cp && toupper(*cp) == 'M') 499 size *= ONE_MEG;
|
493
| 500
|
494 type = get_partition_type(); 495 if (type == PART_NONE) 496 break; 497 498 if (type == PART_FILESYSTEM) { 499 if ((p = get_mountpoint(NULL)) == NULL)
| 501 type = get_partition_type(); 502 if (type == PART_NONE)
|
500 break;
| 503 break;
|
501 else if (!strcmp(p->mountpoint, "/")) 502 flags |= CHUNK_IS_ROOT; 503 else 504 flags &= ~CHUNK_IS_ROOT; 505 } else 506 p = NULL;
| |
507
| 504
|
508 if ((flags & CHUNK_IS_ROOT)) { 509 if (!(label_chunk_info[here].c->flags & CHUNK_BSD_COMPAT)) { 510 msgConfirm("This region cannot be used for your root partition as\nthe FreeBSD boot code cannot deal with a root partition created in\nsuch a location. Please choose another location for your root\npartition and try again!"); 511 break;
| 505 if (type == PART_FILESYSTEM) { 506 if ((p = get_mountpoint(NULL)) == NULL) 507 break; 508 else if (!strcmp(p->mountpoint, "/")) 509 flags |= CHUNK_IS_ROOT; 510 else 511 flags &= ~CHUNK_IS_ROOT; 512 } else 513 p = NULL; 514 515 if ((flags & CHUNK_IS_ROOT)) { 516 if (!(label_chunk_info[here].c->flags & CHUNK_BSD_COMPAT)) { 517 msgConfirm("This region cannot be used for your root partition as\nthe FreeBSD boot code cannot deal with a root partition created in\nsuch a location. Please choose another location for your root\npartition and try again!"); 518 break; 519 } 520 if (size < ROOT_MIN_SIZE) { 521 msgConfirm("This is too small a size for a root partition. For a variety of\nreasons, root partitions should be at least %dMB in size", ROOT_MIN_SIZE / ONE_MEG); 522 break; 523 }
|
512 }
| 524 }
|
513 if (size < ROOT_MIN_SIZE) { 514 msgConfirm("This is too small a size for a root partition. For a variety of\nreasons, root partitions should be at least %dMB in size", ROOT_MIN_SIZE / 2048);
| 525 tmp = Create_Chunk_DWIM(label_chunk_info[here].d, 526 label_chunk_info[here].c, 527 size, part, 528 (type == PART_SWAP) ? FS_SWAP : FS_BSDFFS, 529 flags); 530 if (!tmp) { 531 msgConfirm("Unable to create the partition. Too big?");
|
515 break; 516 }
| 532 break; 533 }
|
517 } 518 tmp = Create_Chunk_DWIM(label_chunk_info[here].d, 519 label_chunk_info[here].c, 520 size, part, 521 (type == PART_SWAP) ? FS_SWAP : FS_BSDFFS, 522 flags); 523 if (!tmp) { 524 msgConfirm("Unable to create the partition. Too big?"); 525 break; 526 } 527 if ((flags & CHUNK_IS_ROOT) && (tmp->flags & CHUNK_PAST_1024)) {
| 534 if ((flags & CHUNK_IS_ROOT) && (tmp->flags & CHUNK_PAST_1024)) {
|
528 msgConfirm("This region cannot be used for your root partition as it starts\nor extends past the 1024'th cylinder mark and is thus a\npoor location to boot from. Please choose another\nlocation for your root partition and try again!"); 529 Delete_Chunk(label_chunk_info[here].d, tmp); 530 break;
| 535 msgConfirm("This region cannot be used for your root partition as it starts\nor extends past the 1024'th cylinder mark and is thus a\npoor location to boot from. Please choose another\nlocation for your root partition and try again!"); 536 Delete_Chunk(label_chunk_info[here].d, tmp); 537 break;
|
531 } 532 if (type != PART_SWAP) {
| 538 } 539 if (type != PART_SWAP) {
|
533 /* This is needed to tell the newfs -u about the size */ 534 tmp->private = new_part(p->mountpoint,p->newfs,tmp->size); 535 safe_free(p);
| 540 /* This is needed to tell the newfs -u about the size */ 541 tmp->private = new_part(p->mountpoint,p->newfs,tmp->size); 542 safe_free(p);
|
536 } else {
| 543 } else {
|
537 tmp->private = p;
| 544 tmp->private = p;
|
538 } 539 tmp->private_free = safe_free; 540 record_label_chunks();
| 545 } 546 tmp->private_free = safe_free; 547 record_label_chunks();
|
541 } 542 break; 543 544 case 'D': /* delete */ 545 if (label_chunk_info[here].type == PART_SLICE) { 546 msg = MSG_NOT_APPLICABLE; 547 break; 548 } 549 else if (label_chunk_info[here].type == PART_FAT) { 550 msg = "Use the Disk Partition Editor to delete this"; 551 break; 552 } 553 Delete_Chunk(label_chunk_info[here].d, label_chunk_info[here].c); 554 record_label_chunks(); 555 break; 556 557 case 'M': /* mount */ 558 switch(label_chunk_info[here].type) { 559 case PART_SLICE: 560 msg = MSG_NOT_APPLICABLE; 561 break; 562 563 case PART_SWAP: 564 msg = "You don't need to specify a mountpoint for a swap partition."; 565 break; 566 567 case PART_FAT: 568 case PART_FILESYSTEM: 569 p = get_mountpoint(label_chunk_info[here].c); 570 if (p) { 571 p->newfs = FALSE; 572 record_label_chunks(); 573 } 574 break; 575 576 default: 577 msgFatal("Bogus partition under cursor???"); 578 break; 579 } 580 break; 581 582 case 'N': /* Set newfs options */ 583 if (label_chunk_info[here].c->private && 584 ((PartInfo *)label_chunk_info[here].c->private)->newfs) 585 getNewfsCmd(label_chunk_info[here].c->private); 586 else 587 msg = MSG_NOT_APPLICABLE; 588 break; 589 590 case 'T': /* Toggle newfs state */ 591 if (label_chunk_info[here].type == PART_FILESYSTEM && 592 label_chunk_info[here].c->private) { 593 PartInfo *pi = ((PartInfo *) 594 label_chunk_info[here].c->private); 595 label_chunk_info[here].c->private = new_part( 596 pi->mountpoint, 597 !pi->newfs, 598 label_chunk_info[here].c->size); 599 safe_free(pi); 600 } 601 else 602 msg = MSG_NOT_APPLICABLE; 603 break; 604 605 case 'W': 606 if (!msgYesNo("Are you sure you want to go into Wizard mode?\n\nThis is an entirely undocumented feature which you are not\nexpected to understand!")) { 607 int i; 608 Device **devs; 609 610 dialog_clear(); 611 end_dialog(); 612 DialogActive = FALSE; 613 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 614 if (!devs) { 615 msgConfirm("Can't find any disk devicse!"); 616 break; 617 } 618 for (i = 0; devs[i] && ((Disk *)devs[i]->private); i++) { 619 if (devs[i]->enabled) 620 slice_wizard(((Disk *)devs[i]->private)); 621 } 622 DialogActive = TRUE; 623 dialog_clear(); 624 record_label_chunks(); 625 } 626 else 627 msg = "A most prudent choice!"; 628 break; 629 630 case 27: /* ESC */ 631 labeling = FALSE; 632 break; 633 634 default: 635 beep(); 636 msg = "Type F1 or ? for help"; 637 break; 638 } 639 } 640 variable_set2(DISK_LABELLED, "yes"); 641 dialog_clear();
| 548 } 549 break; 550 551 case 'D': /* delete */ 552 if (label_chunk_info[here].type == PART_SLICE) { 553 msg = MSG_NOT_APPLICABLE; 554 break; 555 } 556 else if (label_chunk_info[here].type == PART_FAT) { 557 msg = "Use the Disk Partition Editor to delete this"; 558 break; 559 } 560 Delete_Chunk(label_chunk_info[here].d, label_chunk_info[here].c); 561 record_label_chunks(); 562 break; 563 564 case 'M': /* mount */ 565 switch(label_chunk_info[here].type) { 566 case PART_SLICE: 567 msg = MSG_NOT_APPLICABLE; 568 break; 569 570 case PART_SWAP: 571 msg = "You don't need to specify a mountpoint for a swap partition."; 572 break; 573 574 case PART_FAT: 575 case PART_FILESYSTEM: 576 p = get_mountpoint(label_chunk_info[here].c); 577 if (p) { 578 p->newfs = FALSE; 579 record_label_chunks(); 580 } 581 break; 582 583 default: 584 msgFatal("Bogus partition under cursor???"); 585 break; 586 } 587 break; 588 589 case 'N': /* Set newfs options */ 590 if (label_chunk_info[here].c->private && 591 ((PartInfo *)label_chunk_info[here].c->private)->newfs) 592 getNewfsCmd(label_chunk_info[here].c->private); 593 else 594 msg = MSG_NOT_APPLICABLE; 595 break; 596 597 case 'T': /* Toggle newfs state */ 598 if (label_chunk_info[here].type == PART_FILESYSTEM && 599 label_chunk_info[here].c->private) { 600 PartInfo *pi = ((PartInfo *) 601 label_chunk_info[here].c->private); 602 label_chunk_info[here].c->private = new_part( 603 pi->mountpoint, 604 !pi->newfs, 605 label_chunk_info[here].c->size); 606 safe_free(pi); 607 } 608 else 609 msg = MSG_NOT_APPLICABLE; 610 break; 611 612 case 'W': 613 if (!msgYesNo("Are you sure you want to go into Wizard mode?\n\nThis is an entirely undocumented feature which you are not\nexpected to understand!")) { 614 int i; 615 Device **devs; 616 617 dialog_clear(); 618 end_dialog(); 619 DialogActive = FALSE; 620 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 621 if (!devs) { 622 msgConfirm("Can't find any disk devicse!"); 623 break; 624 } 625 for (i = 0; devs[i] && ((Disk *)devs[i]->private); i++) { 626 if (devs[i]->enabled) 627 slice_wizard(((Disk *)devs[i]->private)); 628 } 629 DialogActive = TRUE; 630 dialog_clear(); 631 record_label_chunks(); 632 } 633 else 634 msg = "A most prudent choice!"; 635 break; 636 637 case 27: /* ESC */ 638 labeling = FALSE; 639 break; 640 641 default: 642 beep(); 643 msg = "Type F1 or ? for help"; 644 break; 645 } 646 } 647 variable_set2(DISK_LABELLED, "yes"); 648 dialog_clear();
|
642 refresh();
| |
643 return 0; 644} 645 646 647
| 649 return 0; 650} 651 652 653
|