Deleted Added
full compact
label.c (8622) label.c (8641)
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.9 1995/05/19 02:09:02 jkh Exp $
7 * $Id: label.c,v 1.10 1995/05/19 02:19:15 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
69/* The smallest filesystem we're willing to create */
70#define FS_MIN_SIZE 2048
71
72
73/* All the chunks currently displayed on the screen */
74static struct {
75 struct disk *d;
76 struct chunk *c;
77 PartType type;
78} label_chunk_info[MAX_CHUNKS + 1];
79static int here;
80
81/* See if we're already using a desired partition name */
82static Boolean
83check_conflict(char *name)
84{
85 int i;
86
87 for (i = 0; label_chunk_info[i].d; i++)
88 if (label_chunk_info[i].type == PART_FILESYSTEM
89 && label_chunk_info[i].c->private
90 && !strcmp(((PartInfo *)label_chunk_info[i].c->private)->mountpoint, name))
91 return TRUE;
92 return FALSE;
93}
94
95/* How much space is in this FreeBSD slice? */
96static int
97space_free(struct chunk *c)
98{
99 struct chunk *c1 = c->part;
100 int sz = c->size;
101
102 while (c1) {
103 if (c1->type != unused)
104 sz -= c1->size;
105 c1 = c1->next;
106 }
107 if (sz < 0)
108 msgFatal("Partitions are larger than actual chunk??");
109 return sz;
110}
111
112/* Snapshot the current situation into the displayed chunks structure */
113static void
114record_label_chunks()
115{
116 int i, j, p;
117 struct chunk *c1, *c2;
118 Device **devs;
119 Disk *d;
120
121 devs = deviceFind(NULL, DEVICE_TYPE_DISK);
122 if (!devs) {
123 msgConfirm("No disks found!");
124 return;
125 }
126
127 j = p = 0;
128 /* First buzz through and pick up the FreeBSD slices */
129 for (i = 0; devs[i]; i++) {
130 if (!devs[i]->enabled)
131 continue;
132 d = (Disk *)devs[i]->private;
133 if (!d->chunks)
134 msgFatal("No chunk list found for %s!", d->name);
135
136 /* Put the slice entries first */
137 for (c1 = d->chunks->part; c1; c1 = c1->next) {
138 if (c1->type == freebsd) {
139 label_chunk_info[j].type = PART_SLICE;
140 label_chunk_info[j].d = d;
141 label_chunk_info[j].c = c1;
142 ++j;
143 }
144 }
145 }
146 /* Now run through again and get the FreeBSD partition entries */
147 for (i = 0; devs[i]; i++) {
148 if (!devs[i]->enabled)
149 continue;
150 d = (Disk *)devs[i]->private;
151 /* Then buzz through and pick up the partitions */
152 for (c1 = d->chunks->part; c1; c1 = c1->next) {
153 if (c1->type == freebsd) {
154 for (c2 = c1->part; c2; c2 = c2->next) {
155 if (c2->type == part) {
156 if (c2->subtype == FS_SWAP)
157 label_chunk_info[j].type = PART_SWAP;
158 else
159 label_chunk_info[j].type = PART_FILESYSTEM;
160 label_chunk_info[j].d = d;
161 label_chunk_info[j].c = c2;
162 ++j;
163 }
164 }
165 }
166 else if (c1->type == fat) {
167 label_chunk_info[j].type = PART_FAT;
168 label_chunk_info[j].d = d;
169 label_chunk_info[j].c = c1;
170 }
171 }
172 }
173 label_chunk_info[j].d = NULL;
174 label_chunk_info[j].c = NULL;
175 if (here >= j)
176 here = j ? j - 1 : 0;
177}
178
179/* A new partition entry */
180static PartInfo *
181new_part(char *mpoint, Boolean newfs)
182{
183 PartInfo *ret;
184
185 ret = (PartInfo *)safe_malloc(sizeof(PartInfo));
186 strncpy(ret->mountpoint, mpoint, FILENAME_MAX);
187 strcpy(ret->newfs_cmd, "newfs");
188 ret->newfs = newfs;
189 return ret;
190}
191
192/* Get the mountpoint for a partition and save it away */
193PartInfo *
194get_mountpoint(struct chunk *old)
195{
196 char *val;
197 PartInfo *tmp;
198
199 val = msgGetInput(old && old->private ? ((PartInfo *)old->private)->mountpoint : NULL,
200 "Please specify a mount point for the partition");
201 if (val) {
202 /* Is it just the same value? */
203 if (old && old->private && !strcmp(((PartInfo *)old->private)->mountpoint, val))
204 return NULL;
205 if (check_conflict(val)) {
206 msgConfirm("You already have a mount point for %s assigned!", val);
207 return NULL;
208 }
209 else if (*val != '/') {
210 msgConfirm("Mount point must start with a / character");
211 return NULL;
212 }
213 else if (!strcmp(val, "/")) {
214 if (old)
215 old->flags |= CHUNK_IS_ROOT;
216 }
217 else if (old)
218 old->flags &= ~CHUNK_IS_ROOT;
219 safe_free(old ? old->private : NULL);
220 tmp = new_part(val, TRUE);
221 if (old) {
222 old->private = tmp;
223 old->private_free = safe_free;
224 }
225 return tmp;
226 }
227 return NULL;
228}
229
230/* Get the type of the new partiton */
231static PartType
232get_partition_type(void)
233{
234 char selection[20];
235 static unsigned char *fs_types[] = {
236 "FS",
237 "A file system",
238 "Swap",
239 "A swap partition.",
240 };
241
242 if (!dialog_menu("Please choose a partition type",
243 "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)) {
244 if (!strcmp(selection, "FS"))
245 return PART_FILESYSTEM;
246 else if (!strcmp(selection, "Swap"))
247 return PART_SWAP;
248 }
249 return PART_NONE;
250}
251
252/* If the user wants a special newfs command for this, set it */
253static void
254getNewfsCmd(PartInfo *p)
255{
256 char *val;
257
258 val = msgGetInput(p->newfs_cmd,
259 "Please enter the newfs command and options you'd like to use in\ncreating this file system.");
260 if (val)
261 strncpy(p->newfs_cmd, val, NEWFS_CMD_MAX);
262}
263
264
265#define MAX_MOUNT_NAME 12
266
267#define PART_PART_COL 0
268#define PART_MOUNT_COL 8
269#define PART_SIZE_COL (PART_MOUNT_COL + MAX_MOUNT_NAME + 3)
270#define PART_NEWFS_COL (PART_SIZE_COL + 7)
271#define PART_OFF 38
272
273/* How many mounted partitions to display in column before going to next */
274#define CHUNK_COLUMN_MAX 5
275
276/* stick this all up on the screen */
277static void
278print_label_chunks(void)
279{
280 int i, j, srow, prow, pcol;
281 int sz;
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/* The smallest filesystem we're willing to create */
70#define FS_MIN_SIZE 2048
71
72
73/* All the chunks currently displayed on the screen */
74static struct {
75 struct disk *d;
76 struct chunk *c;
77 PartType type;
78} label_chunk_info[MAX_CHUNKS + 1];
79static int here;
80
81/* See if we're already using a desired partition name */
82static Boolean
83check_conflict(char *name)
84{
85 int i;
86
87 for (i = 0; label_chunk_info[i].d; i++)
88 if (label_chunk_info[i].type == PART_FILESYSTEM
89 && label_chunk_info[i].c->private
90 && !strcmp(((PartInfo *)label_chunk_info[i].c->private)->mountpoint, name))
91 return TRUE;
92 return FALSE;
93}
94
95/* How much space is in this FreeBSD slice? */
96static int
97space_free(struct chunk *c)
98{
99 struct chunk *c1 = c->part;
100 int sz = c->size;
101
102 while (c1) {
103 if (c1->type != unused)
104 sz -= c1->size;
105 c1 = c1->next;
106 }
107 if (sz < 0)
108 msgFatal("Partitions are larger than actual chunk??");
109 return sz;
110}
111
112/* Snapshot the current situation into the displayed chunks structure */
113static void
114record_label_chunks()
115{
116 int i, j, p;
117 struct chunk *c1, *c2;
118 Device **devs;
119 Disk *d;
120
121 devs = deviceFind(NULL, DEVICE_TYPE_DISK);
122 if (!devs) {
123 msgConfirm("No disks found!");
124 return;
125 }
126
127 j = p = 0;
128 /* First buzz through and pick up the FreeBSD slices */
129 for (i = 0; devs[i]; i++) {
130 if (!devs[i]->enabled)
131 continue;
132 d = (Disk *)devs[i]->private;
133 if (!d->chunks)
134 msgFatal("No chunk list found for %s!", d->name);
135
136 /* Put the slice entries first */
137 for (c1 = d->chunks->part; c1; c1 = c1->next) {
138 if (c1->type == freebsd) {
139 label_chunk_info[j].type = PART_SLICE;
140 label_chunk_info[j].d = d;
141 label_chunk_info[j].c = c1;
142 ++j;
143 }
144 }
145 }
146 /* Now run through again and get the FreeBSD partition entries */
147 for (i = 0; devs[i]; i++) {
148 if (!devs[i]->enabled)
149 continue;
150 d = (Disk *)devs[i]->private;
151 /* Then buzz through and pick up the partitions */
152 for (c1 = d->chunks->part; c1; c1 = c1->next) {
153 if (c1->type == freebsd) {
154 for (c2 = c1->part; c2; c2 = c2->next) {
155 if (c2->type == part) {
156 if (c2->subtype == FS_SWAP)
157 label_chunk_info[j].type = PART_SWAP;
158 else
159 label_chunk_info[j].type = PART_FILESYSTEM;
160 label_chunk_info[j].d = d;
161 label_chunk_info[j].c = c2;
162 ++j;
163 }
164 }
165 }
166 else if (c1->type == fat) {
167 label_chunk_info[j].type = PART_FAT;
168 label_chunk_info[j].d = d;
169 label_chunk_info[j].c = c1;
170 }
171 }
172 }
173 label_chunk_info[j].d = NULL;
174 label_chunk_info[j].c = NULL;
175 if (here >= j)
176 here = j ? j - 1 : 0;
177}
178
179/* A new partition entry */
180static PartInfo *
181new_part(char *mpoint, Boolean newfs)
182{
183 PartInfo *ret;
184
185 ret = (PartInfo *)safe_malloc(sizeof(PartInfo));
186 strncpy(ret->mountpoint, mpoint, FILENAME_MAX);
187 strcpy(ret->newfs_cmd, "newfs");
188 ret->newfs = newfs;
189 return ret;
190}
191
192/* Get the mountpoint for a partition and save it away */
193PartInfo *
194get_mountpoint(struct chunk *old)
195{
196 char *val;
197 PartInfo *tmp;
198
199 val = msgGetInput(old && old->private ? ((PartInfo *)old->private)->mountpoint : NULL,
200 "Please specify a mount point for the partition");
201 if (val) {
202 /* Is it just the same value? */
203 if (old && old->private && !strcmp(((PartInfo *)old->private)->mountpoint, val))
204 return NULL;
205 if (check_conflict(val)) {
206 msgConfirm("You already have a mount point for %s assigned!", val);
207 return NULL;
208 }
209 else if (*val != '/') {
210 msgConfirm("Mount point must start with a / character");
211 return NULL;
212 }
213 else if (!strcmp(val, "/")) {
214 if (old)
215 old->flags |= CHUNK_IS_ROOT;
216 }
217 else if (old)
218 old->flags &= ~CHUNK_IS_ROOT;
219 safe_free(old ? old->private : NULL);
220 tmp = new_part(val, TRUE);
221 if (old) {
222 old->private = tmp;
223 old->private_free = safe_free;
224 }
225 return tmp;
226 }
227 return NULL;
228}
229
230/* Get the type of the new partiton */
231static PartType
232get_partition_type(void)
233{
234 char selection[20];
235 static unsigned char *fs_types[] = {
236 "FS",
237 "A file system",
238 "Swap",
239 "A swap partition.",
240 };
241
242 if (!dialog_menu("Please choose a partition type",
243 "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)) {
244 if (!strcmp(selection, "FS"))
245 return PART_FILESYSTEM;
246 else if (!strcmp(selection, "Swap"))
247 return PART_SWAP;
248 }
249 return PART_NONE;
250}
251
252/* If the user wants a special newfs command for this, set it */
253static void
254getNewfsCmd(PartInfo *p)
255{
256 char *val;
257
258 val = msgGetInput(p->newfs_cmd,
259 "Please enter the newfs command and options you'd like to use in\ncreating this file system.");
260 if (val)
261 strncpy(p->newfs_cmd, val, NEWFS_CMD_MAX);
262}
263
264
265#define MAX_MOUNT_NAME 12
266
267#define PART_PART_COL 0
268#define PART_MOUNT_COL 8
269#define PART_SIZE_COL (PART_MOUNT_COL + MAX_MOUNT_NAME + 3)
270#define PART_NEWFS_COL (PART_SIZE_COL + 7)
271#define PART_OFF 38
272
273/* How many mounted partitions to display in column before going to next */
274#define CHUNK_COLUMN_MAX 5
275
276/* stick this all up on the screen */
277static void
278print_label_chunks(void)
279{
280 int i, j, srow, prow, pcol;
281 int sz;
282 int label_attr;
283
284 clear();
285 attrset(A_REVERSE);
286 mvaddstr(0, 25, "FreeBSD Disklabel Editor");
287 attrset(A_NORMAL);
288
289 for (i = 0; i < 2; i++) {
290 mvaddstr(CHUNK_PART_START_ROW - 2, PART_PART_COL + (i * PART_OFF), "Part");
291 mvaddstr(CHUNK_PART_START_ROW - 1, PART_PART_COL + (i * PART_OFF), "----");
292
293 mvaddstr(CHUNK_PART_START_ROW - 2, PART_MOUNT_COL + (i * PART_OFF), "Mount");
294 mvaddstr(CHUNK_PART_START_ROW - 1, PART_MOUNT_COL + (i * PART_OFF), "-----");
295
296 mvaddstr(CHUNK_PART_START_ROW - 2, PART_SIZE_COL + (i * PART_OFF) + 2, "Size");
297 mvaddstr(CHUNK_PART_START_ROW - 1, PART_SIZE_COL + (i * PART_OFF) + 2, "----");
298
299 mvaddstr(CHUNK_PART_START_ROW - 2, PART_NEWFS_COL + (i * PART_OFF), "Newfs");
300 mvaddstr(CHUNK_PART_START_ROW - 1, PART_NEWFS_COL + (i * PART_OFF), "-----");
301 }
302 srow = CHUNK_SLICE_START_ROW;
303 prow = CHUNK_PART_START_ROW;
304 pcol = 0;
305
306 for (i = 0; label_chunk_info[i].d; i++) {
307 if (i == here)
308 attrset(A_REVERSE);
309 /* Is it a slice entry displayed at the top? */
310 if (label_chunk_info[i].type == PART_SLICE) {
311 sz = space_free(label_chunk_info[i].c);
312 mvprintw(srow++, 0,
313 "Disk: %s\tPartition name: %s\tFree: %d blocks (%dMB)",
314 label_chunk_info[i].d->name,
315 label_chunk_info[i].c->name, sz, (sz / 2048));
316 }
317 /* Otherwise it's a DOS, swap or filesystem entry, at the bottom */
318 else {
319 char onestr[PART_OFF], num[10], *mountpoint, *newfs;
320
321 /*
322 * We copy this into a blank-padded string so that it looks like
323 * a solid bar in reverse-video
324 */
325 memset(onestr, ' ', PART_OFF - 1);
326 onestr[PART_OFF - 1] = '\0';
327 /* Go for two columns */
328 if (prow == (CHUNK_PART_START_ROW + CHUNK_COLUMN_MAX)) {
329 pcol = PART_OFF;
330 prow = CHUNK_PART_START_ROW;
331 }
332 memcpy(onestr + PART_PART_COL, label_chunk_info[i].c->name,
333 strlen(label_chunk_info[i].c->name));
334 /* If it's a filesystem, display the mountpoint */
335 if (label_chunk_info[i].type == PART_FILESYSTEM) {
336 if (label_chunk_info[i].c->private == NULL) {
337 static int mnt = 0;
338 char foo[10];
339
340 /*
341 * Hmm! A partition that must have already been here.
342 * Fill in a fake mountpoint and register it
343 */
344 sprintf(foo, "/mnt%d", mnt++);
345 label_chunk_info[i].c->private = new_part(foo, FALSE);
346 label_chunk_info[i].c->private_free = safe_free;
347 }
348 mountpoint = ((PartInfo *)label_chunk_info[i].c->private)->mountpoint;
349 newfs = ((PartInfo *)label_chunk_info[i].c->private)->newfs ? "Y" : "N";
350 }
351 else if (label_chunk_info[i].type == PART_SWAP) {
352 mountpoint = "swap";
353 newfs = " ";
354 }
355 else if (label_chunk_info[i].type == PART_FAT) {
356 mountpoint = "DOS FAT";
357 newfs = "*";
358 }
359 else {
360 mountpoint = "<unknown>";
361 newfs = "*";
362 }
363 for (j = 0; j < MAX_MOUNT_NAME && mountpoint[j]; j++)
364 onestr[PART_MOUNT_COL + j] = mountpoint[j];
365 snprintf(num, 10, "%4ldMB", label_chunk_info[i].c->size ?
366 label_chunk_info[i].c->size / 2048 : 0);
367 memcpy(onestr + PART_SIZE_COL, num, strlen(num));
368 memcpy(onestr + PART_NEWFS_COL, newfs, strlen(newfs));
369 onestr[PART_NEWFS_COL + strlen(newfs)] = '\0';
370 mvaddstr(prow, pcol, onestr);
371 ++prow;
372 }
373 if (i == here)
374 attrset(A_NORMAL);
375 }
376}
377
378static void
379print_command_summary()
380{
381 mvprintw(17, 0,
382 "The following commands are valid here (upper or lower case):");
383 mvprintw(19, 0, "C = Create Partition D = Delete Partition M = Mount Partition");
384 mvprintw(20, 0, "N = Newfs Options T = Toggle Newfs ESC = Exit this screen");
385 mvprintw(21, 0, "The default target will be displayed in ");
386
387 attrset(A_REVERSE);
388 addstr("reverse video.");
389 attrset(A_NORMAL);
390 mvprintw(22, 0, "Use F1 or ? to get more help, arrow keys to move.");
391 move(0, 0);
392}
393
394int
395diskLabelEditor(char *str)
396{
397 int sz, key = 0;
398 Boolean labeling;
399 char *msg = NULL;
400 PartInfo *p;
401 PartType type;
402
403 labeling = TRUE;
404 keypad(stdscr, TRUE);
405 record_label_chunks();
406
407 if (!getenv(DISK_PARTITIONED)) {
408 msgConfirm("You need to partition your disk(s) before you can assign disk labels.");
409 return 0;
410 }
411 while (labeling) {
412 print_label_chunks();
413 print_command_summary();
414 if (msg) {
415 attrset(A_REVERSE); mvprintw(23, 0, msg); attrset(A_NORMAL);
416 beep();
417 msg = NULL;
418 }
419 refresh();
420 key = toupper(getch());
421 switch (key) {
422
423 case KEY_UP:
424 case '-':
425 if (here != 0)
426 --here;
427 break;
428
429 case KEY_DOWN:
430 case '+':
431 case '\r':
432 case '\n':
433 if (label_chunk_info[here + 1].d)
434 ++here;
435 break;
436
437 case KEY_HOME:
438 here = 0;
439 break;
440
441 case KEY_END:
442 while (label_chunk_info[here + 1].d)
443 ++here;
444 break;
445
446 case KEY_F(1):
447 case '?':
448 systemDisplayFile("disklabel.hlp");
449 break;
450
451 case 'C':
452 if (label_chunk_info[here].type != PART_SLICE) {
453 msg = "You can only do this in a master partition (see top of screen)";
454 break;
455 }
456 sz = space_free(label_chunk_info[here].c);
457 if (sz <= FS_MIN_SIZE)
458 msg = "Not enough space to create additional FreeBSD partition";
459 else {
460 char *val, *cp, tmp[20];
461 int size;
462
463 snprintf(tmp, 20, "%d", sz);
464 val = msgGetInput(tmp, "Please specify the size for new FreeBSD partition in blocks, or append\na trailing `M' for megabytes (e.g. 20M).");
465 if (val && (size = strtol(val, &cp, 0)) > 0) {
466 struct chunk *tmp;
467 u_long flags = 0;
468
469 if (*cp && toupper(*cp) == 'M')
470 size *= 2048;
471
472 type = get_partition_type();
473 if (type == PART_NONE)
474 break;
475 else if (type == PART_FILESYSTEM) {
476 if ((p = get_mountpoint(NULL)) == NULL)
477 break;
478 else if (!strcmp(p->mountpoint, "/"))
479 flags |= CHUNK_IS_ROOT;
480 else
481 flags &= ~CHUNK_IS_ROOT;
482 }
483 else
484 p = NULL;
485
486 if ((flags & CHUNK_IS_ROOT) && !(label_chunk_info[here].c->flags & CHUNK_BSD_COMPAT)) {
487 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!");
488 break;
489 }
490 tmp = Create_Chunk_DWIM(label_chunk_info[here].d,
491 label_chunk_info[here].c,
492 size, part,
493 (type == PART_SWAP) ? FS_SWAP : FS_BSDFFS,
494 flags);
495 if (!tmp) {
496 msgConfirm("Unable to create the partition. Too big?");
497 break;
498 }
499 else if ((flags & CHUNK_IS_ROOT) && (tmp->flags & CHUNK_PAST_1024)) {
500 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!");
501 Delete_Chunk(label_chunk_info[here].d, tmp);
502 break;
503 }
504 tmp->private = p;
505 tmp->private_free = safe_free;
506 record_label_chunks();
507 }
508 }
509 break;
510
511 case 'D': /* delete */
512 if (label_chunk_info[here].type == PART_SLICE) {
513 msg = MSG_NOT_APPLICABLE;
514 break;
515 }
516 else if (label_chunk_info[here].type == PART_FAT) {
517 msg = "Use the Disk Partition Editor to delete this";
518 break;
519 }
520 Delete_Chunk(label_chunk_info[here].d, label_chunk_info[here].c);
521 record_label_chunks();
522 break;
523
524 case 'M': /* mount */
525 switch(label_chunk_info[here].type) {
526 case PART_SLICE:
527 msg = MSG_NOT_APPLICABLE;
528 break;
529
530 case PART_SWAP:
531 msg = "You don't need to specify a mountpoint for a swap partition.";
532 break;
533
534 case PART_FAT:
535 case PART_FILESYSTEM:
536 p = get_mountpoint(label_chunk_info[here].c);
537 if (p) {
538 p->newfs = FALSE;
539 record_label_chunks();
540 }
541 break;
542
543 default:
544 msgFatal("Bogus partition under cursor???");
545 break;
546 }
547 break;
548
549 case 'N': /* Set newfs options */
550 if (label_chunk_info[here].c->private &&
551 ((PartInfo *)label_chunk_info[here].c->private)->newfs)
552 getNewfsCmd(label_chunk_info[here].c->private);
553 else
554 msg = MSG_NOT_APPLICABLE;
555 break;
556
557 case 'T': /* Toggle newfs state */
558 if (label_chunk_info[here].type == PART_FILESYSTEM &&
559 label_chunk_info[here].c->private)
560 ((PartInfo *)label_chunk_info[here].c->private)->newfs =
561 !((PartInfo *)label_chunk_info[here].c->private)->newfs;
562 else
563 msg = MSG_NOT_APPLICABLE;
564 break;
565
566 case 'W':
567 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!")) {
568 int i;
569 Device **devs;
570
571 dialog_clear();
572 end_dialog();
573 DialogActive = FALSE;
574 devs = deviceFind(NULL, DEVICE_TYPE_DISK);
575 if (!devs) {
576 msgConfirm("Can't find any disk devicse!");
577 break;
578 }
579 for (i = 0; ((Disk *)devs[i]->private); i++) {
580 if (devs[i]->enabled)
581 slice_wizard(((Disk *)devs[i]->private));
582 }
583 dialog_clear();
584 DialogActive = TRUE;
585 record_label_chunks();
586 }
587 else
588 msg = "A most prudent choice!";
589 break;
590
591 case 27: /* ESC */
592 labeling = FALSE;
593 break;
594
595 default:
596 beep();
597 msg = "Type F1 or ? for help";
598 break;
599 }
600 }
601 variable_set2(DISK_LABELLED, "yes");
602 dialog_clear();
603 refresh();
604 return 0;
605}
606
607
608
282
283 clear();
284 attrset(A_REVERSE);
285 mvaddstr(0, 25, "FreeBSD Disklabel Editor");
286 attrset(A_NORMAL);
287
288 for (i = 0; i < 2; i++) {
289 mvaddstr(CHUNK_PART_START_ROW - 2, PART_PART_COL + (i * PART_OFF), "Part");
290 mvaddstr(CHUNK_PART_START_ROW - 1, PART_PART_COL + (i * PART_OFF), "----");
291
292 mvaddstr(CHUNK_PART_START_ROW - 2, PART_MOUNT_COL + (i * PART_OFF), "Mount");
293 mvaddstr(CHUNK_PART_START_ROW - 1, PART_MOUNT_COL + (i * PART_OFF), "-----");
294
295 mvaddstr(CHUNK_PART_START_ROW - 2, PART_SIZE_COL + (i * PART_OFF) + 2, "Size");
296 mvaddstr(CHUNK_PART_START_ROW - 1, PART_SIZE_COL + (i * PART_OFF) + 2, "----");
297
298 mvaddstr(CHUNK_PART_START_ROW - 2, PART_NEWFS_COL + (i * PART_OFF), "Newfs");
299 mvaddstr(CHUNK_PART_START_ROW - 1, PART_NEWFS_COL + (i * PART_OFF), "-----");
300 }
301 srow = CHUNK_SLICE_START_ROW;
302 prow = CHUNK_PART_START_ROW;
303 pcol = 0;
304
305 for (i = 0; label_chunk_info[i].d; i++) {
306 if (i == here)
307 attrset(A_REVERSE);
308 /* Is it a slice entry displayed at the top? */
309 if (label_chunk_info[i].type == PART_SLICE) {
310 sz = space_free(label_chunk_info[i].c);
311 mvprintw(srow++, 0,
312 "Disk: %s\tPartition name: %s\tFree: %d blocks (%dMB)",
313 label_chunk_info[i].d->name,
314 label_chunk_info[i].c->name, sz, (sz / 2048));
315 }
316 /* Otherwise it's a DOS, swap or filesystem entry, at the bottom */
317 else {
318 char onestr[PART_OFF], num[10], *mountpoint, *newfs;
319
320 /*
321 * We copy this into a blank-padded string so that it looks like
322 * a solid bar in reverse-video
323 */
324 memset(onestr, ' ', PART_OFF - 1);
325 onestr[PART_OFF - 1] = '\0';
326 /* Go for two columns */
327 if (prow == (CHUNK_PART_START_ROW + CHUNK_COLUMN_MAX)) {
328 pcol = PART_OFF;
329 prow = CHUNK_PART_START_ROW;
330 }
331 memcpy(onestr + PART_PART_COL, label_chunk_info[i].c->name,
332 strlen(label_chunk_info[i].c->name));
333 /* If it's a filesystem, display the mountpoint */
334 if (label_chunk_info[i].type == PART_FILESYSTEM) {
335 if (label_chunk_info[i].c->private == NULL) {
336 static int mnt = 0;
337 char foo[10];
338
339 /*
340 * Hmm! A partition that must have already been here.
341 * Fill in a fake mountpoint and register it
342 */
343 sprintf(foo, "/mnt%d", mnt++);
344 label_chunk_info[i].c->private = new_part(foo, FALSE);
345 label_chunk_info[i].c->private_free = safe_free;
346 }
347 mountpoint = ((PartInfo *)label_chunk_info[i].c->private)->mountpoint;
348 newfs = ((PartInfo *)label_chunk_info[i].c->private)->newfs ? "Y" : "N";
349 }
350 else if (label_chunk_info[i].type == PART_SWAP) {
351 mountpoint = "swap";
352 newfs = " ";
353 }
354 else if (label_chunk_info[i].type == PART_FAT) {
355 mountpoint = "DOS FAT";
356 newfs = "*";
357 }
358 else {
359 mountpoint = "<unknown>";
360 newfs = "*";
361 }
362 for (j = 0; j < MAX_MOUNT_NAME && mountpoint[j]; j++)
363 onestr[PART_MOUNT_COL + j] = mountpoint[j];
364 snprintf(num, 10, "%4ldMB", label_chunk_info[i].c->size ?
365 label_chunk_info[i].c->size / 2048 : 0);
366 memcpy(onestr + PART_SIZE_COL, num, strlen(num));
367 memcpy(onestr + PART_NEWFS_COL, newfs, strlen(newfs));
368 onestr[PART_NEWFS_COL + strlen(newfs)] = '\0';
369 mvaddstr(prow, pcol, onestr);
370 ++prow;
371 }
372 if (i == here)
373 attrset(A_NORMAL);
374 }
375}
376
377static void
378print_command_summary()
379{
380 mvprintw(17, 0,
381 "The following commands are valid here (upper or lower case):");
382 mvprintw(19, 0, "C = Create Partition D = Delete Partition M = Mount Partition");
383 mvprintw(20, 0, "N = Newfs Options T = Toggle Newfs ESC = Exit this screen");
384 mvprintw(21, 0, "The default target will be displayed in ");
385
386 attrset(A_REVERSE);
387 addstr("reverse video.");
388 attrset(A_NORMAL);
389 mvprintw(22, 0, "Use F1 or ? to get more help, arrow keys to move.");
390 move(0, 0);
391}
392
393int
394diskLabelEditor(char *str)
395{
396 int sz, key = 0;
397 Boolean labeling;
398 char *msg = NULL;
399 PartInfo *p;
400 PartType type;
401
402 labeling = TRUE;
403 keypad(stdscr, TRUE);
404 record_label_chunks();
405
406 if (!getenv(DISK_PARTITIONED)) {
407 msgConfirm("You need to partition your disk(s) before you can assign disk labels.");
408 return 0;
409 }
410 while (labeling) {
411 print_label_chunks();
412 print_command_summary();
413 if (msg) {
414 attrset(A_REVERSE); mvprintw(23, 0, msg); attrset(A_NORMAL);
415 beep();
416 msg = NULL;
417 }
418 refresh();
419 key = toupper(getch());
420 switch (key) {
421
422 case KEY_UP:
423 case '-':
424 if (here != 0)
425 --here;
426 break;
427
428 case KEY_DOWN:
429 case '+':
430 case '\r':
431 case '\n':
432 if (label_chunk_info[here + 1].d)
433 ++here;
434 break;
435
436 case KEY_HOME:
437 here = 0;
438 break;
439
440 case KEY_END:
441 while (label_chunk_info[here + 1].d)
442 ++here;
443 break;
444
445 case KEY_F(1):
446 case '?':
447 systemDisplayFile("disklabel.hlp");
448 break;
449
450 case 'C':
451 if (label_chunk_info[here].type != PART_SLICE) {
452 msg = "You can only do this in a master partition (see top of screen)";
453 break;
454 }
455 sz = space_free(label_chunk_info[here].c);
456 if (sz <= FS_MIN_SIZE)
457 msg = "Not enough space to create additional FreeBSD partition";
458 else {
459 char *val, *cp, tmp[20];
460 int size;
461
462 snprintf(tmp, 20, "%d", sz);
463 val = msgGetInput(tmp, "Please specify the size for new FreeBSD partition in blocks, or append\na trailing `M' for megabytes (e.g. 20M).");
464 if (val && (size = strtol(val, &cp, 0)) > 0) {
465 struct chunk *tmp;
466 u_long flags = 0;
467
468 if (*cp && toupper(*cp) == 'M')
469 size *= 2048;
470
471 type = get_partition_type();
472 if (type == PART_NONE)
473 break;
474 else if (type == PART_FILESYSTEM) {
475 if ((p = get_mountpoint(NULL)) == NULL)
476 break;
477 else if (!strcmp(p->mountpoint, "/"))
478 flags |= CHUNK_IS_ROOT;
479 else
480 flags &= ~CHUNK_IS_ROOT;
481 }
482 else
483 p = NULL;
484
485 if ((flags & CHUNK_IS_ROOT) && !(label_chunk_info[here].c->flags & CHUNK_BSD_COMPAT)) {
486 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!");
487 break;
488 }
489 tmp = Create_Chunk_DWIM(label_chunk_info[here].d,
490 label_chunk_info[here].c,
491 size, part,
492 (type == PART_SWAP) ? FS_SWAP : FS_BSDFFS,
493 flags);
494 if (!tmp) {
495 msgConfirm("Unable to create the partition. Too big?");
496 break;
497 }
498 else if ((flags & CHUNK_IS_ROOT) && (tmp->flags & CHUNK_PAST_1024)) {
499 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!");
500 Delete_Chunk(label_chunk_info[here].d, tmp);
501 break;
502 }
503 tmp->private = p;
504 tmp->private_free = safe_free;
505 record_label_chunks();
506 }
507 }
508 break;
509
510 case 'D': /* delete */
511 if (label_chunk_info[here].type == PART_SLICE) {
512 msg = MSG_NOT_APPLICABLE;
513 break;
514 }
515 else if (label_chunk_info[here].type == PART_FAT) {
516 msg = "Use the Disk Partition Editor to delete this";
517 break;
518 }
519 Delete_Chunk(label_chunk_info[here].d, label_chunk_info[here].c);
520 record_label_chunks();
521 break;
522
523 case 'M': /* mount */
524 switch(label_chunk_info[here].type) {
525 case PART_SLICE:
526 msg = MSG_NOT_APPLICABLE;
527 break;
528
529 case PART_SWAP:
530 msg = "You don't need to specify a mountpoint for a swap partition.";
531 break;
532
533 case PART_FAT:
534 case PART_FILESYSTEM:
535 p = get_mountpoint(label_chunk_info[here].c);
536 if (p) {
537 p->newfs = FALSE;
538 record_label_chunks();
539 }
540 break;
541
542 default:
543 msgFatal("Bogus partition under cursor???");
544 break;
545 }
546 break;
547
548 case 'N': /* Set newfs options */
549 if (label_chunk_info[here].c->private &&
550 ((PartInfo *)label_chunk_info[here].c->private)->newfs)
551 getNewfsCmd(label_chunk_info[here].c->private);
552 else
553 msg = MSG_NOT_APPLICABLE;
554 break;
555
556 case 'T': /* Toggle newfs state */
557 if (label_chunk_info[here].type == PART_FILESYSTEM &&
558 label_chunk_info[here].c->private)
559 ((PartInfo *)label_chunk_info[here].c->private)->newfs =
560 !((PartInfo *)label_chunk_info[here].c->private)->newfs;
561 else
562 msg = MSG_NOT_APPLICABLE;
563 break;
564
565 case 'W':
566 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!")) {
567 int i;
568 Device **devs;
569
570 dialog_clear();
571 end_dialog();
572 DialogActive = FALSE;
573 devs = deviceFind(NULL, DEVICE_TYPE_DISK);
574 if (!devs) {
575 msgConfirm("Can't find any disk devicse!");
576 break;
577 }
578 for (i = 0; ((Disk *)devs[i]->private); i++) {
579 if (devs[i]->enabled)
580 slice_wizard(((Disk *)devs[i]->private));
581 }
582 dialog_clear();
583 DialogActive = TRUE;
584 record_label_chunks();
585 }
586 else
587 msg = "A most prudent choice!";
588 break;
589
590 case 27: /* ESC */
591 labeling = FALSE;
592 break;
593
594 default:
595 beep();
596 msg = "Type F1 or ? for help";
597 break;
598 }
599 }
600 variable_set2(DISK_LABELLED, "yes");
601 dialog_clear();
602 refresh();
603 return 0;
604}
605
606
607