freebsd-dev/sbin/sysinstall/label.c
Jordan K. Hubbard a0c7a3b3cf Sigh. My error message printing was still wrong. Wipe the sleep from
my eyes and do this properly (debugging is especially difficult when you have
to burn a floppy every time you want to test your changes! :-( ).
1994-11-06 02:24:45 +00:00

630 lines
18 KiB
C

/* Stopgap, until Paul does the right thing */
#define ESC 27
#define TAB 9
#include <stdlib.h>
#include <limits.h>
#define DKTYPENAMES
#include <sys/param.h>
#include <ufs/ffs/fs.h>
#include <sys/types.h>
#include <string.h>
#include <sys/disklabel.h>
#include <ufs/ffs/fs.h>
#include <string.h>
#include <dialog.h>
#include "sysinstall.h"
/* Forward decls */
int disk_size(struct disklabel *);
int getfstype(char *);
int sectstoMb(int, int);
char *partname[MAXPARTITIONS] = {"a", "b", "c", "d", "e", "f", "g", "h"};
#define EDITABLES 3
#define FSTYPE 0
#define UPARTSIZES 1
#define MOUNTPOINTS 2
struct field {
int y;
int x;
int width;
char field[80];
} field;
struct field label_fields[MAXPARTITIONS][EDITABLES];
int allocated_space;
int ourpart_offset;
int ourpart_size;
void
yelp(char *str)
{
standout();
mvprintw(24, 0, str);
standend();
beep();
}
void
setup_label_fields(struct disklabel *lbl)
{
int i;
for (i = 0; i < MAXPARTITIONS; i++) {
label_fields[i][0].y = 4 + (i * 2);
label_fields[i][0].x = 15;
label_fields[i][0].width = 15;
sprintf(label_fields[i][0].field, "%s",
fstypenames[lbl->d_partitions[i].p_fstype]);
label_fields[i][1].y = 4 + (i * 2);
label_fields[i][1].x = 35;
label_fields[i][1].width = 9;
sprintf(label_fields[i][1].field, "%d",
sectstoMb(lbl->d_partitions[i].p_size, lbl->d_secsize));
label_fields[i][2].y = 4 + (i * 2);
label_fields[i][2].x = 45;
label_fields[i][2].width = 30;
}
sprintf(label_fields[0][2].field, "%s", "/");
sprintf(label_fields[1][2].field, "%s", "swap");
sprintf(label_fields[4][2].field, "%s", "/usr");
}
void
update_label_form(WINDOW *window, struct disklabel *lbl)
{
int i;
long used = 0,ul;
mvwprintw(window, 2, 2, "Partition");
mvwprintw(window, 2, 15, "Filesystem Type");
mvwprintw(window, 2, 35, "Size");
mvwprintw(window, 2, 45, "Mount point");
for (i=0; i < MAXPARTITIONS; i++) {
mvwprintw(window, 4+(i*2), 6, "%s", partname[i]);
mvwprintw(window, label_fields[i][0].y, label_fields[i][0].x, "%s",
&label_fields[i][0].field);
if (i < 2 || i > 3) {
ul = strtol(label_fields[i][1].field,0,0);
sprintf(label_fields[i][1].field, "%lu",ul);
used += ul;
}
mvwprintw(window, label_fields[i][1].y, label_fields[i][1].x, "%-5s",
&label_fields[i][1].field);
if (label_fields[i][2].field)
mvwprintw(window, label_fields[i][2].y, label_fields[i][2].x, "%s",
&label_fields[i][2].field);
}
mvwprintw(window, 20, 10, "Allocated %5luMb, Unallocated %5lu Mb",
used, disk_size(lbl) - used);
wrefresh(window);
}
int
disk_size(struct disklabel *lbl)
{
int size;
size = lbl->d_secsize * lbl->d_nsectors *
lbl->d_ntracks * lbl->d_ncylinders;
return (size / 1024 / 1024);
}
int
sectstoMb(int nsects, int secsize)
{
int size;
size = nsects * secsize;
if (size)
size /= 1024 * 1024;
return (size);
}
int
Mbtosects(int Mb, int secsize)
{
int nsects;
nsects = (Mb * 1024 * 1024) / secsize;
return(nsects);
}
int
rndtocylbdry(int size, int secpercyl)
{
int nocyls;
nocyls = size / secpercyl;
if ((nocyls * secpercyl) < size)
nocyls++;
return (nocyls * secpercyl);
}
void
default_disklabel(struct disklabel *lbl, int avail_sects, int offset)
{
int nsects;
/* Fill in default label entries */
lbl->d_magic = DISKMAGIC;
bcopy("INSTALLATION", lbl->d_typename, strlen("INSTALLATION"));
lbl->d_rpm = 3600;
lbl->d_interleave = 1;
lbl->d_trackskew = 0;
lbl->d_cylskew = 0;
lbl->d_magic2 = DISKMAGIC;
lbl->d_checksum = 0;
lbl->d_bbsize = BBSIZE;
lbl->d_sbsize = SBSIZE;
lbl->d_npartitions = 5;
/* Set up c and d as raw partitions for now */
lbl->d_partitions[2].p_size = avail_sects;
lbl->d_partitions[2].p_offset = offset;
lbl->d_partitions[2].p_fsize = DEFFSIZE; /* XXX */
lbl->d_partitions[2].p_fstype = FS_UNUSED;
lbl->d_partitions[2].p_frag = DEFFRAG;
lbl->d_partitions[3].p_size = lbl->d_secperunit;
lbl->d_partitions[3].p_offset = 0;
lbl->d_partitions[3].p_fsize = DEFFSIZE;
lbl->d_partitions[3].p_fstype = FS_UNUSED;
lbl->d_partitions[3].p_frag = DEFFRAG;
/* Default root */
nsects = rndtocylbdry(Mbtosects(DEFROOTSIZE, lbl->d_secsize),
lbl->d_secpercyl);
offset = rndtocylbdry(offset, lbl->d_secpercyl);
lbl->d_partitions[0].p_size = nsects;
lbl->d_partitions[0].p_offset = offset;
lbl->d_partitions[0].p_fsize = DEFFSIZE;
lbl->d_partitions[0].p_fstype = FS_BSDFFS;
lbl->d_partitions[0].p_frag = DEFFRAG;
avail_sects -= nsects;
offset += nsects;
nsects = rndtocylbdry(Mbtosects(DEFSWAPSIZE, lbl->d_secsize),
lbl->d_secpercyl);
lbl->d_partitions[1].p_size = nsects;
lbl->d_partitions[1].p_offset = offset;
lbl->d_partitions[1].p_fsize = DEFFSIZE;
lbl->d_partitions[1].p_fstype = FS_SWAP;
lbl->d_partitions[1].p_frag = DEFFRAG;
avail_sects -= nsects;
offset += nsects;
nsects = rndtocylbdry(Mbtosects(DEFUSRSIZE, lbl->d_secsize),
lbl->d_secpercyl);
if (avail_sects > nsects)
nsects = avail_sects;
lbl->d_partitions[4].p_size = nsects;
lbl->d_partitions[4].p_offset = offset;
lbl->d_partitions[4].p_fsize = DEFFSIZE;
lbl->d_partitions[4].p_fstype = FS_BSDFFS;
lbl->d_partitions[4].p_frag = DEFFRAG;
}
void
edit_disklabel(struct disklabel *lbl)
{
int key=0;
int x_pos = 0;
int y_pos = 0;
WINDOW *window;
if (use_shadow)
draw_shadow(stdscr, 1, 1, LINES-3, COLS-5);
window = newwin(LINES - 2, COLS - 4, 0, 0);
keypad(window, TRUE);
draw_box(window, 1, 1, LINES - 3, COLS - 5, dialog_attr, border_attr);
wattrset(window, dialog_attr);
setup_label_fields(lbl);
do {
update_label_form(window, lbl);
key = edit_line(window, label_fields[y_pos][x_pos].y,
label_fields[y_pos][x_pos].x,
label_fields[y_pos][x_pos].field,
label_fields[y_pos][x_pos].width,
20);
switch(key) {
case KEY_UP:
if (y_pos != 0)
y_pos--;
break;
case KEY_DOWN:
if (++y_pos == MAXPARTITIONS)
y_pos--;
break;
case '\n':
case TAB:
x_pos++;
if (x_pos == EDITABLES) {
x_pos = 0;
if (++y_pos == MAXPARTITIONS)
y_pos--;
}
break;
case KEY_BTAB:
x_pos--;
if (x_pos < 0) {
x_pos = EDITABLES - 1;
if (--y_pos < 0)
y_pos++;
}
break;
default:
break;
}
} while (key != '\033');
dialog_clear();
}
int
build_disklabel(struct disklabel *lbl)
{
int i, offset;
int nsects;
int total_sects;
/* Get start of FreeBSD partition from default label */
offset = lbl->d_partitions[2].p_offset;
for (i=0; i < MAXPARTITIONS; i++) {
if (strlen(label_fields[i][MOUNTPOINTS].field) &&
atoi(label_fields[i][UPARTSIZES].field)) {
sprintf(scratch, "%s%s", avail_disknames[inst_disk], partname[i]);
Fname[Nfs] = StrAlloc(scratch);
Fmount[Nfs] = StrAlloc(label_fields[i][MOUNTPOINTS].field);
Nfs++;
nsects = Mbtosects(atoi(label_fields[i][UPARTSIZES].field),
lbl->d_secsize);
lbl->d_partitions[i].p_size = nsects;
lbl->d_partitions[i].p_offset = offset;
offset += nsects;
total_sects += nsects;
lbl->d_partitions[i].p_fstype =
getfstype(label_fields[i][FSTYPE].field);
lbl->d_npartitions = i+1;
} else if (i < 2 || i > 3) {
lbl->d_partitions[i].p_size = 0;
lbl->d_partitions[i].p_offset = 0;
lbl->d_partitions[i].p_fstype = 0;
}
Debug("Part%d: %d sects, %d offset, %d end, %d type", i,
lbl->d_partitions[i].p_size,
lbl->d_partitions[i].p_offset,
lbl->d_partitions[i].p_size+
lbl->d_partitions[i].p_offset,
lbl->d_partitions[i].p_fstype);
}
return 0;
}
int
getfstype(char *fstype)
{
int i;
for (i=0; i < FSMAXTYPES; i++)
if (!strcasecmp(fstype, fstypenames[i]))
return(i);
return(FS_OTHER);
}
void
display_disklabel(int disk)
{
int i, key=0;
WINDOW *window;
if (use_shadow)
draw_shadow(stdscr, 1, 1, LINES-2, COLS-2);
window = newwin(LINES-2, COLS-2, 1, 1);
keypad(window, TRUE);
draw_box(window, 1, 1, LINES - 2, COLS - 2, dialog_attr, border_attr);
wattrset(window, dialog_attr);
mvwprintw(window, 2, 2, "Dumping label for disk %d, %s\n", disk, avail_disklabels[disk].d_typename);
mvwprintw(window, 3, 2, "magic = %lu",avail_disklabels[disk].d_magic);
mvwprintw(window, 3, 22, "type = %x",avail_disklabels[disk].d_type);
mvwprintw(window, 3, 32, "subtype = %x\n",avail_disklabels[disk].d_subtype);
mvwprintw(window, 4, 2, "Typename = %s",avail_disklabels[disk].d_typename);
mvwprintw(window, 4, 38, "Packname = %s",avail_disklabels[disk].d_packname);
mvwprintw(window, 5, 74, "boot0 = %s",avail_disklabels[disk].d_boot0);
mvwprintw(window, 5, 50, "boot1 = %s\n",avail_disklabels[disk].d_boot1);
mvwprintw(window, 5, 2, "secsize = %ld",avail_disklabels[disk].d_secsize);
mvwprintw(window, 5, 20, "nsectors = %ld",avail_disklabels[disk].d_nsectors);
mvwprintw(window, 5, 30, "ntracks = %ld",avail_disklabels[disk].d_ntracks);
mvwprintw(window, 5, 50, "ncylinders = %ld\n",avail_disklabels[disk].d_ncylinders);
mvwprintw(window, 6, 2, "secpercyl = %ld",avail_disklabels[disk].d_secpercyl);
mvwprintw(window, 6, 40, "secperunit = %ld\n",avail_disklabels[disk].d_secperunit);
mvwprintw(window, 7, 2, "sparespertrack = %d",avail_disklabels[disk].d_sparespertrack);
mvwprintw(window, 7, 20, "sparespercyl = %d",avail_disklabels[disk].d_sparespercyl);
mvwprintw(window, 7, 40, "acylinders = %ld\n",avail_disklabels[disk].d_acylinders);
mvwprintw(window, 8, 2, "rpm = %d",avail_disklabels[disk].d_rpm);
mvwprintw(window, 8, 20, "interleave = %d",avail_disklabels[disk].d_interleave);
mvwprintw(window, 8, 40, "trackskew = %d",avail_disklabels[disk].d_trackskew);
mvwprintw(window, 8, 60, "cylskew = %d\n",avail_disklabels[disk].d_cylskew);
mvwprintw(window, 9, 2, "headswitch = %ld",avail_disklabels[disk].d_headswitch);
mvwprintw(window, 9, 30, "trkseek = %ld",avail_disklabels[disk].d_trkseek);
mvwprintw(window, 9, 55, "flags = %ld\n",avail_disklabels[disk].d_flags);
mvwprintw(window, 10, 2, "Drivedata");
for (i=0; i< NDDATA; i++) {
mvwprintw(window, 10, 11 + (i*10), " : %d = %ld",i,avail_disklabels[disk].d_drivedata[i]);
}
mvwprintw(window, 11, 2, "Spare");
for (i=0; i< NSPARE; i++) {
mvwprintw(window, 11, 7 + (i*10), " : %d = %ld",i,avail_disklabels[disk].d_spare[i]);
}
mvwprintw(window, 12, 2, "magic2 = %lu",avail_disklabels[disk].d_magic2);
mvwprintw(window, 12, 40, "checksum = %d\n",avail_disklabels[disk].d_checksum);
mvwprintw(window, 13, 2, "npartitions = %d",avail_disklabels[disk].d_npartitions);
mvwprintw(window, 13, 25, "bbsize = %lu",avail_disklabels[disk].d_bbsize);
mvwprintw(window, 13, 50, "sbsize = %lu\n",avail_disklabels[disk].d_sbsize);
for (i=0; i< MAXPARTITIONS; i++) {
mvwprintw(window, 14+i, 2, "%d: size: %ld",i,avail_disklabels[disk].d_partitions[i].p_size);
mvwprintw(window, 14+i, 20, "offset: %ld",avail_disklabels[disk].d_partitions[i].p_offset);
mvwprintw(window, 14+i, 36, "fsize: %ld",avail_disklabels[disk].d_partitions[i].p_fsize);
mvwprintw(window, 14+i, 49, "fstype: %d",avail_disklabels[disk].d_partitions[i].p_fstype);
mvwprintw(window, 14+i, 60, "frag: %d",avail_disklabels[disk].d_partitions[i].p_frag);
mvwprintw(window, 14+i, 70, "cpg: %d",avail_disklabels[disk].d_partitions[i].p_cpg);
}
dialog_update();
while (key != '\n' && key != ' ' && key != '\033')
key = wgetch(window);
delwin(window);
dialog_clear();
}
static int
AskWhichPartition(char *prompt)
{
char buf[10];
int i;
*buf = 0;
i = AskEm(stdscr, prompt, buf, 2);
if (i != '\n' && i != '\r') return -1;
if (!strchr("abefghABEFGH",*buf)) return -1;
return tolower(*buf) - 'a';
}
void
DiskLabel()
{
int i, j, done = 0, diskno, flag, k;
char buf[128],*p;
struct disklabel *lbl, olbl;
u_long cyl, hd, sec, tsec;
u_long l1, l2, l3, l4;
char *yip = NULL;
*buf = 0;
i = AskEm(stdscr, "Enter number of disk to Disklabel> ", buf, 2);
printf("%d", i);
if (i != '\n' && i != '\r') return;
diskno = atoi(buf);
if (!(diskno >= 0 && diskno < MAX_NO_DISKS && Dname[diskno]))
return;
olbl = *Dlbl[diskno];
lbl = &olbl;
cyl = lbl->d_ncylinders;
hd = lbl->d_ntracks;
sec = lbl->d_nsectors;
tsec = lbl->d_secperunit;
while(!done) {
clear(); standend();
if (yip) {
yelp(yip);
yip = NULL;
}
j = 0;
mvprintw(j++, 0, "%s -- Diskspace editor -- DISKLABEL", TITLE);
j++;
allocated_space = 0;
ourpart_size = lbl->d_partitions[OURPART].p_size;
ourpart_offset = lbl->d_partitions[OURPART].p_offset;
mvprintw(j++, 0, "Part Start End Blocks MB Type Mountpoint");
for (i = 0; i < MAXPARTITIONS; i++) {
mvprintw(j++, 0, "%c ", 'a'+i);
if (i >= lbl->d_npartitions)
continue;
printw(" %8u %8u %8u %5u ",
lbl->d_partitions[i].p_offset,
lbl->d_partitions[i].p_offset+
(lbl->d_partitions[i].p_size ?
lbl->d_partitions[i].p_size-1 : 0),
lbl->d_partitions[i].p_size,
(lbl->d_partitions[i].p_size + 1024)/2048);
k = lbl->d_partitions[i].p_fstype;
if (k > FSMAXTYPES)
printw(" %04x ", k);
else
printw("%-10s ", fstypenames[k]);
if (i == OURPART)
printw("<Entire FreeBSD slice>");
else if (i == RAWPART)
printw("<Entire Disk>");
else {
if (Fmount[MP[diskno][i]])
printw(Fmount[MP[diskno][i]]);
if ((lbl->d_partitions[i].p_offset >= ourpart_offset) &&
((lbl->d_partitions[i].p_offset +
lbl->d_partitions[i].p_size) <=
(ourpart_offset + ourpart_size)))
allocated_space += lbl->d_partitions[i].p_size;
}
}
mvprintw(18, 0, "Total size: %d blocks", ourpart_size);
mvprintw(19, 0, "Space allocated: %d blocks", allocated_space);
mvprintw(21, 0, "Commands available:");
mvprintw(22, 0, "(H)elp (S)ize (M)ountpoint (D)elete (R)eread (W)rite (Q)uit");
mvprintw(23, 0, "Enter Command> ");
i=getch();
switch(i) {
case 'h': case 'H':
ShowFile(HELPME_FILE,"Help file for disklayout");
break;
case 'd': case 'D':
j = AskWhichPartition("Delete which partition? ");
if (j < 0) {
yip = "Invalid partition";
break;
}
CleanMount(diskno, j);
lbl->d_partitions[j].p_fstype = FS_UNUSED;
lbl->d_partitions[j].p_size = 0;
lbl->d_partitions[j].p_offset = 0;
break;
case 's': case 'S':
j = AskWhichPartition("Change size of which partition? ");
if (j < 0) {
yip = "Invalid partition";
break;
}
if (lbl->d_partitions[j].p_fstype != FS_BSDFFS &&
lbl->d_partitions[j].p_fstype != FS_UNUSED &&
lbl->d_partitions[j].p_fstype != FS_SWAP) {
yip = "Invalid partition type";
break;
}
if (lbl->d_partitions[OURPART].p_size == 0) {
yip = "No FreeBSD partition defined?";
break;
}
l1=lbl->d_partitions[OURPART].p_offset;
l2=lbl->d_partitions[OURPART].p_offset +
lbl->d_partitions[OURPART].p_size;
for (i = 0; i < MAXPARTITIONS; i++) {
if (i == OURPART) continue;
if (i == RAWPART) continue;
if (i == j) continue;
if (lbl->d_partitions[i].p_size == 0) continue;
if (lbl->d_partitions[i].p_offset >= l2) continue;
if ((lbl->d_partitions[i].p_offset+
lbl->d_partitions[i].p_size) <= l1) continue;
l3 = lbl->d_partitions[i].p_offset - l1;
l4 = l2 - (lbl->d_partitions[i].p_offset+
lbl->d_partitions[i].p_size);
if (l3 > 0 && l3 >= l4)
l2 = l1+l3;
else if (l4 > 0 && l4 > l3)
l1 = l2-l4;
else
l2 = l1;
}
if (!(l2 - l1)) {
yip = "Oh god, I'm so confused!";
break;
}
sprintf(buf, "%lu", (l2-l1+1024L)/2048L);
i = AskEm(stdscr, "Size of partition in MB> ", buf, 10);
l3= strtol(buf, 0, 0) * 2048L;
if (!l3) {
yip = "Invalid size given";
break;
}
if (l3 > l2 - l1)
l3 = l2 - l1;
lbl->d_partitions[j].p_size = l3;
lbl->d_partitions[j].p_offset = l1;
if (j == 1)
lbl->d_partitions[j].p_fstype = FS_SWAP;
else
lbl->d_partitions[j].p_fstype = FS_BSDFFS;
break;
case 'r': case 'R':
olbl = *Dlbl[diskno];
/* XXX be more selective here */
for (i = 0; i < MAXPARTITIONS; i++)
CleanMount(diskno, i);
break;
case 'm': case 'M':
j = AskWhichPartition("Mountpoint of which partition ? ");
if (j < 0) {
yip = "Invalid partition";
break;
}
k = lbl->d_partitions[j].p_fstype;
if (k != FS_BSDFFS && k != FS_MSDOS && k != FS_SWAP) {
yip = "Invalid partition type";
break;
}
if (!lbl->d_partitions[j].p_size) {
yip = "Zero partition size";
break;
}
if (k == FS_SWAP)
strcpy(buf, "swap");
else if (Fmount[MP[diskno][j]])
strcpy(buf, Fmount[MP[diskno][j]]);
else
*buf = 0;
if (k != FS_SWAP) {
i = AskEm(stdscr, "Mount on directory> ", buf, 28);
if (i != '\n' && i != '\r') {
yip ="Invalid directory name";
break;
}
}
CleanMount(diskno, j);
p = SetMount(diskno,j,buf);
yip = p;
break;
case 'w': case 'W':
*Dlbl[diskno] = *lbl;
Dlbl[diskno]->d_magic = DISKMAGIC;
Dlbl[diskno]->d_magic2 = DISKMAGIC;
Dlbl[diskno]->d_checksum = 0;
Dlbl[diskno]->d_checksum = dkcksum(Dlbl[diskno]);
*lbl= *Dlbl[diskno];
flag=1;
if (ioctl(Dfd[diskno], DIOCWLABEL, &flag) < 0)
Fatal("Couldn't enable writing of labels");
if (ioctl(Dfd[diskno], DIOCSDINFO, Dlbl[diskno]) == -1)
Fatal("Couldn't set label: %s", strerror(errno));
if (ioctl(Dfd[diskno], DIOCWDINFO, Dlbl[diskno]) == -1)
Fatal("Couldn't write label: %s", strerror(errno));
flag=0;
if (ioctl(Dfd[diskno], DIOCWLABEL, &flag) < 0)
Fatal("Couldn't disable writing of labels");
yip = "Label written successfully.";
break;
case 'q': case 'Q':
if (!memcmp(lbl, Dlbl[diskno], sizeof *lbl))
return;
/* XXX be more selective here */
for (i = 0; i < MAXPARTITIONS; i++)
CleanMount(diskno, i);
return;
break;
}
}
}