home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 1998 February
/
CHIP_2_98.iso
/
misc
/
src
/
install
/
fsedit.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-11-03
|
75KB
|
2,717 lines
/* Newt based fdisk program
*
* Michael Fulbright (msf@redhat.com)
*
* Copyright 1997 Red Hat Software
*
* This software may be freely redistributed under the terms of the GNU
* public license.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <alloca.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <malloc.h>
#include <ctype.h>
#include <fcntl.h>
#include <errno.h>
#include <newt.h>
#include "kickstart.h"
#include "fs.h"
#include "fsedit.h"
#include "hd.h"
#include "install.h"
#include "libfdisk/libfdisk.h"
#include "devices.h"
#include "windows.h"
#include <popt.h>
#define VERSION_STR "1.00"
extern int testing;
/* static char version[] = "0.01"; */
/* need to move somewhere else eventually! */
/* mostly gleamed from fdisk.[ch] */
struct parttypes {
unsigned char index;
char *name;
};
static struct parttypes allparttypes[] = {
{0, "Empty"},
{1, "DOS 12-bit FAT"},
{2, "XENIX root"},
{3, "XENIX usr"},
{4, "DOS 16-bit <32M"},
{5, "Extended"},
{6, "DOS 16-bit >=32M"},
{7, "OS/2 HPFS"}, /* or QNX? */
{8, "AIX"},
{9, "AIX bootable"},
{10, "OS/2 Boot Manager"},
{0xb, "Win95 FAT32"},
{0x40, "Venix 80286"},
{0x51, "Novell?"},
{0x52, "Microport"}, /* or CPM? */
{0x63, "GNU HURD"}, /* or System V/386? */
{0x64, "Novell Netware 286"},
{0x65, "Novell Netware 386"},
{0x75, "PC/IX"},
{0x80, "Old MINIX"}, /* Minix 1.4a and earlier */
{0x81, "Linux/MINIX"}, /* Minix 1.4b and later */
{0x82, "Linux swap"},
{0x83, "Linux native"},
{0x93, "Amoeba"},
{0x94, "Amoeba BBT"}, /* (bad block table) */
{0xa5, "BSD/386"},
{0xb7, "BSDI fs"},
{0xb8, "BSDI swap"},
{0xc7, "Syrinx"},
{0xdb, "CP/M"}, /* or Concurrent DOS? */
{0xe1, "DOS access"},
{0xe3, "DOS R/O"},
{0xf2, "DOS secondary"},
{0xff, "BBT"} /* (bad track table) */
};
int nparttypes = sizeof (allparttypes) / sizeof (struct parttypes);
/* hardcoded, maybe someday we'll get these from tty ? */
int screen_width=80;
int screen_height=25;
#define MAX_HARDDRIVES 16
#define SECPERMEG 2048
/* clean up that string */
static void TrimWhitespace( char *s ) {
char *f, *l, *p, *q;
if (!(*s))
return;
for (f=s; *f && isspace(*f); f++) ;
if (!*f) {
*s = '\0';
return;
}
for (l=f+strlen(f)-1; isspace(*l) ; l--)
*l = '\0';
q = s, p = f;
while (*p)
*q++ = *p++;
*q = '\0';
}
/* fill in the */
/* position in the status line, up to length characters */
/* if cen=1, center it */
static void BuildTableField( char *line, char *val,
int pos, int length, int cen ) {
char *p, *q;
int i;
int c;
/* lets center field value in the field */
if (cen) {
c = strlen(val);
c = (length-c)/2;
if (c < 0)
c = 0;
} else
c=0;
/* first setup device name */
for (p=val, q=line+pos+c, i=c; *p && i<length; p++, q++, i++)
*q = *p;
}
/* some fdisk functions which don't have homes yet */
static int fdiskPartitionIsBootable( HardDrive *hd, Partition *p ) {
unsigned int i, bootable;
/* see if drive #1 or #2 is a possible drive for partition */
bootable = fdiskThisDriveSetIsActive( &p->drive, 1 ) ||
fdiskThisDriveSetIsActive( &p->drive, 2 );
/* if so, see if rest are EXCLUDED */
if (bootable) {
for (i=3; i<MAX_DRIVESET_NUM; i++) {
if (fdiskThisDriveSetIsActive( &p->drive, i)) {
bootable = 0;
break;
}
}
}
if (bootable) {
if (p->endcyl.active && p->endcyl.max < 1024) {
bootable = 1;
} else if (p->immutable) {
unsigned int end, c, h, s;
end = p->start.current + p->size.current - 1;
fdiskSectorToCHS( hd, end, &c, &h, &s );
if (c < 1024)
bootable = 1;
else
bootable = 0;
} else {
bootable = 0;
}
}
return bootable;
}
/* check a mount point to make sure its valid */
/* returns non-zero if bad mount point */
static int badMountPoint(unsigned int type, char * item) {
char * chptr = item;
if (*chptr != '/') {
newtWinMessage("Bad Mount Point", "Ok",
"The mount point %s is illegal.\n\n"
"Mount points must begin with a leading /.", item);
return 1;
}
if (*(chptr + 1) && *(chptr + strlen(chptr) - 1) == '/') {
newtWinMessage("Bad Mount Point", "Ok",
"The mount point %s is illegal.\n\n"
"Mount points may not end with a /.", item);
return 1;
}
while (*chptr && isprint(*chptr)) chptr++;
if (*chptr) {
newtWinMessage("Bad Mount Point", "Ok",
"The mount point %s is illegal.\n\n"
"Mount points may only printable characters.",item);
return 1;
}
if (type != LINUX_NATIVE_PARTITION && (
!strncmp(item, "/var", 4) ||
!strncmp(item, "/tmp", 4) ||
!strncmp(item, "/bin", 4) ||
!strncmp(item, "/sbin", 4) ||
!strncmp(item, "/etc", 4) ||
!strncmp(item, "/boot", 4) ||
!strncmp(item, "/dev", 4) ||
!strncmp(item, "/root", 4) ||
!strncmp(item, "/lib", 4))) {
newtWinMessage("Bad Mount Point", "Ok",
"The mount point %s is illegal.\n\n"
"System partitions must be on Linux Native "
"partitions.",item);
return 1;
}
if (type != LINUX_NATIVE_PARTITION &&
type != NFS_REMOTE_PARTITION &&
!strncmp(item, "/usr", 4)) {
newtWinMessage("Bad Mount Point", "Ok",
"The mount point %s is illegal.\n\n"
"/usr must be on a Linux Native partition "
"or an NFS volume.",item);
return 1;
}
return 0;
}
/* */
/* NEWT/screen related routines */
/* */
#if 0
/* get newt initialized, set help line, etc */
static void NewtStartUp( void ) {
char roottext[80];
newtInit();
newtCls();
newtPushHelpLine(" <Tab>/<Alt-Tab> between elements |"
" Use <Enter> to edit a selection" );
snprintf(roottext, 80, "Disk Partitioning Program Version %s - (C)"
" 1997 Red Hat Software", version);
newtDrawRootText(0, 0, roottext);
}
#endif
/* handles standard fdisk type errors */
/* returns non-zero if user picked "yes" response, and zero if "no" */
static int ErrorDialog(char *title, char *errbody, char *errmsg,
char *yesmsg, char *nomsg,
int width, int height) {
newtComponent form, yes, no, box, answer;
int cx, cy;
int buflen;
int retcode;
int pos;
char *buf;
if (!height)
height = 10;
if (!width)
width = 55;
cx = (screen_width-width)/2;
cy = (screen_height-height)/2;
newtOpenWindow(cx, cy, width, height, title);
form = newtForm(NULL, NULL, 0);
box = newtTextbox(1, 1, width-4, height-2, NEWT_FLAG_WRAP);
buflen = strlen(errbody)+strlen(errmsg)+80;
buf = alloca(buflen);
snprintf(buf, buflen, "%s\n\n",errbody);
pos = (width-strlen(errmsg))/2;
memset(buf+strlen(errbody)+2, ' ', pos);
strcpy(buf+strlen(errbody)+2+pos, errmsg);
newtTextboxSetText( box, buf );
yes = newtButton( width/3-strlen(yesmsg)/2-1, height-4, yesmsg);
no = newtButton( (2*width)/3 - strlen(nomsg)/2-1, height-4, nomsg);
newtFormAddComponents( form, box, yes, no, NULL );
answer = newtRunForm( form );
if (answer == yes)
retcode = 1;
else
retcode = 0;
newtPopWindow();
newtFormDestroy(form);
return retcode;
}
static int HandleFdiskError( int status, char *errbody, char *y, char *n ) {
char errmsg[250];
char yesmsg[]="Yes";
char nomsg[] ="No";
if (status < 0) {
if (errno < sys_nerr-1)
strncpy(errmsg,sys_errlist[errno],sizeof(errmsg));
else
snprintf(errmsg,sizeof(errmsg), "System error %d",errno);
} else {
if (status < fdisk_nerr)
strcpy(errmsg, fdisk_errlist[status]);
else
snprintf(errmsg,sizeof(errmsg), "libfdisk error %d",errno);
}
if (y != NULL && n != NULL)
return ErrorDialog( "Fdisk Error", errbody, errmsg, y, n, 0, 0 );
else
return ErrorDialog( "Fdisk Error", errbody,errmsg,yesmsg,nomsg, 0, 0 );
}
/* give summary of why partitions weren't allocated */
static void showReasons( PartitionSpec *spec ) {
newtComponent tbox, form, ok, lbox;
int i;
for (i=0; i<spec->num; i++)
if (spec->entry[i].status == REQUEST_DENIED)
break;
/* nothing going on here, keep moving along */
if (i == spec->num)
return;
/* build list of why they all failed */
newtCenteredWindow(60, 18, "Unallocated Partitions");
form = newtForm(NULL,NULL,0);
tbox = newtTextbox(5, 1, 50, 5, NEWT_FLAG_WRAP );
newtTextboxSetText(tbox, "There are currently unallocated partiton(s) "
"present in the list of requested partitions. The "
"unallocated partition(s) are shown below, along with "
"the reason they were not allocated.");
lbox = newtListbox(10, 6, 5, NEWT_FLAG_RETURNEXIT );
for (i=0; i<spec->num; i++)
if (spec->entry[i].status == REQUEST_DENIED) {
char tmpstr[80];
char *pname = spec->entry[i].name;
char *s, *t;
memset(tmpstr, ' ', 80);
if (strncmp("Exist", pname, 5) && strncmp("Swap", pname, 4) &&
strncmp("Dos", pname, 3))
t = pname;
else
t = NULL;
for (s=tmpstr;t && *t; t++,s++)
*s = *t;
t = GetReasonString(spec->entry[i].reason);
for (s=tmpstr+20;t && *t; t++,s++)
*s = *t;
*s = '\0';
newtListboxAddEntry(lbox, tmpstr, NULL);
}
ok = newtButton(25, 13, "Ok");
newtFormAddComponents(form, tbox, lbox, ok, NULL);
newtFormSetCurrent(form, ok);
newtRunForm(form);
newtPopWindow();
newtFormDestroy(form);
}
/* read in the requested drives */
/* pass an array of names of block devices, returns 0 if ok */
static int ReadDrives( char **drives, int numdrives,
HardDrive **hdarr, unsigned int *numhd,
int forcezero) {
char errbody[250];
int i, done, status;
/* loop over all specified block devices */
*numhd = 0;
for (i=0; i < numdrives; ) {
status = fdiskOpenDevice(drives[i], *numhd+1, &hdarr[*numhd]);
if (status != FDISK_SUCCESS) {
snprintf(errbody, sizeof(errbody),
"An error occurred reading the partition table for the "
"block device %s. The error was:", drives[i]);
if (HandleFdiskError( status, errbody, "Retry", "Skip Drive" ))
continue;
else {
i++;
continue;
}
} else {
done = 0;
while (!done) {
status = fdiskReadPartitions( hdarr[*numhd] );
if (status != FDISK_SUCCESS) {
int rc;
if (status == FDISK_ERR_BADMAGIC) {
if (forcezero) {
if (!testing)
fdiskZeroMBR(hdarr[*numhd]);
fdiskCloseDevice(hdarr[*numhd]);
done = 1;
} else {
if (kickstart) {
newtWinMessage("Bad Partition Table", "Ok",
"The partition table on device %s is "
"corrupted. To create new partitions "
"it must be initialized. You can "
"specify \"zerombr yes\" in the "
"kickstart file to have this done "
"automatically", drives[i]+5);
return INST_ERROR;
}
rc = newtWinChoice("Bad Partition Table",
"Initialize", "Skip Drive",
"The partition table on device %s is "
"corrupted. To create new partitions "
"it must be initialized,"
" causing the loss of ALL DATA on this "
"drive.", drives[i]+5);
if (rc != 1) {
if (!testing)
fdiskZeroMBR(hdarr[*numhd]);
fdiskCloseDevice(hdarr[*numhd]);
done = 1;
} else {
i++;
fdiskCloseDevice(hdarr[*numhd]);
done = 1;
}
}
} else {
snprintf(errbody, sizeof(errbody),
"An error occurred reading the partition table "
"for the block device %s. The error was:",
drives[i]+5);
if (HandleFdiskError(status,errbody,
"Retry","Skip Drive")){
fdiskCloseDevice(hdarr[*numhd]);
done = 1;
} else {
i++;
fdiskCloseDevice(hdarr[*numhd]);
done = 1;
}
}
} else {
*numhd += 1;
i++;
done = 1;
}
}
}
}
return FDISK_SUCCESS;
}
/* see if anything really changed */
int DisksChanged( HardDrive **oldhd, HardDrive **newhd, unsigned int numhd ) {
int i, j;
/* see if partition tables are identical */
for (i=0; i<numhd; i++)
for (j=0; j<MAX_PARTITIONS; j++) {
if (memcmp(&oldhd[i]->table[j],&newhd[i]->table[j],
sizeof(Partition)))
return 1;
if (memcmp(&oldhd[i]->eptable[j],&newhd[i]->eptable[j],
sizeof(Partition)))
return 1;
}
return 0;
}
/* edit an existing partition spec */
/* callback for type listbox */
struct typebox_cbstruct {
newtComponent *entry;
char *val;
};
static char typebox_mp[100];
static int inswapentry;
static void typebox_scroll(newtComponent box, struct typebox_cbstruct *s ) {
int type;
type = (long) newtListboxGetCurrent(box);
if (type == LINUX_SWAP_PARTITION && !inswapentry) {
strncpy(typebox_mp, s->val, 100);
newtEntrySet(*s->entry, "Swap Partition", 0);
inswapentry = 1;
newtEntrySetFlags(*s->entry, NEWT_FLAG_DISABLED, NEWT_FLAGS_SET);
} else if (inswapentry) {
newtEntrySetFlags(*s->entry, NEWT_FLAG_DISABLED, NEWT_FLAGS_RESET);
if (typebox_mp[0] == -1) /* just clear string if it isnt initialized */
typebox_mp[0] = '\0';
newtEntrySet(*s->entry, typebox_mp, 1);
inswapentry = 0;
}
}
struct driveentry_struct {
newtComponent cb;
char state;
};
struct entrybox_cbstruct {
newtComponent *form;
char *val;
unsigned char *val2;
DriveSet curds, origds;
int numhd;
HardDrive **hdarr;
struct driveentry_struct *de;
int dobootable;
};
static void entrybox_cb(newtComponent box, struct entrybox_cbstruct *s) {
unsigned char boot;
int j;
if (s->dobootable) {
boot = (!strcmp(s->val, "/") || !strcmp(s->val, "/boot")) ? '*' : ' ';
if (boot == '*' && *(s->val2) == ' ')
memcpy(&s->origds, &s->curds, sizeof(DriveSet));
*(s->val2) = boot;
if (boot == '*') {
fdiskDeactivateAllDriveSet( &s->curds );
fdiskActivateDriveSet( &s->curds, 1 );
fdiskActivateDriveSet( &s->curds, 2 );
} else {
memcpy(&s->curds, &s->origds, sizeof(DriveSet));
}
for (j=0; j<s->numhd; j++)
s->de[j].state=fdiskThisDriveSetIsActive(&s->curds,
s->hdarr[j]->num)?'*':' ';
newtDrawForm(*s->form);
}
}
#define NEW_PARTSPEC "NewPartition"
static int EditPartitionSpec(HardDrive **hdarr, unsigned int numhd,
PartitionSpec *spec,
PartitionSpecEntry *entry) {
int j;
unsigned int hdidx, tmpuint;
int tmpint;
char tmpstr[80];
Partition *p;
newtComponent form, mntptentry;
newtComponent sizeentry, growentry, bootentry, typeentry;
newtComponent sb, driveform;
newtComponent ok, cancel, answer;
struct typebox_cbstruct cb1;
struct entrybox_cbstruct cb2;
struct driveentry_struct driveentry[MAX_HARDDRIVES];
char *mntpt=NULL, *size=NULL, *eptr;
char titlestr[80];
unsigned char boot, grow;
int row, col;
int status=0;
int done;
int newpartition;
int cval;
int numfstypes = 4;
char fstypesnames[][20] = { "Linux Swap", "Linux Native",
"DOS 16-bit <32M", "DOS 16-bit >=32M"};
int fstypes[] = {0x82, 0x83, 0x4, 0x6};
p = (Partition *) alloca(sizeof(Partition));
memcpy(p, &entry->partition, sizeof(Partition));
newpartition = (strcmp(entry->name, NEW_PARTSPEC) == 0);
if (p->immutable)
cval = -2;
else
cval = ((numhd > 3) ? 4 : numhd);
/* make title line a little more descriptive */
if (newpartition) {
strcpy(titlestr, "Edit New Partition");
} else if (p->immutable) {
for (hdidx=0; hdidx < numhd &&
hdarr[hdidx]->num != p->drive.current; hdidx++);
if (hdidx != numhd) {
snprintf(titlestr, 80, "Edit Partition: /dev/%s%d",
hdarr[hdidx]->name+5, p->num.current);
if (entry->name && *entry->name && strncmp(entry->name, "Exist", 5))
snprintf(titlestr+strlen(titlestr), 80-strlen(titlestr),
" (%s)", entry->name);
} else {
strcpy(titlestr, "Edit Partition");
}
} else {
if (entry->name && *entry->name)
snprintf(titlestr, 80, "Edit Partition: %s", entry->name);
else
strcpy(titlestr, "Edit Partition");
}
newtOpenWindow( 5, 5-(cval+1)/2, 70, 13+cval, titlestr );
form = newtForm(NULL,NULL,0);
/* mount point goes at top and is centered */
row = 1;
col = 3;
newtFormAddComponent(form, newtLabel(col, row, "Mount Point:"));
if (p->type.current != LINUX_SWAP_PARTITION) {
if (!newpartition && strncmp("Exist", entry->name, 5) &&
strncmp("Dos", entry->name, 3)) {
mntptentry = newtEntry(22, row, entry->name, 30,
&mntpt, NEWT_FLAG_RETURNEXIT);
} else {
mntptentry = newtEntry(22, row, "", 30,
&mntpt, NEWT_FLAG_RETURNEXIT);
}
} else {
mntptentry = newtEntry(22, row, "Swap Partition", 30, &mntpt,
NEWT_FLAG_RETURNEXIT | NEWT_FLAG_DISABLED);
}
/* size, grow and boot flags on left under mount point */
row = 3;
newtFormAddComponent(form, newtLabel(col, row, "Size (Megs):"));
if (p->immutable) {
sizeentry = NULL;
snprintf(tmpstr,sizeof(tmpstr),"%d", p->size.current/SECPERMEG);
newtFormAddComponent(form, newtLabel(22, row, tmpstr));
} else {
snprintf(tmpstr,sizeof(tmpstr),"%d", p->size.min/SECPERMEG);
sizeentry = newtEntry(22, row, tmpstr, 8,
&size, NEWT_FLAG_RETURNEXIT);
}
row++;
if (!newpartition) {
grow = p->size.min != p->size.max;
} else {
grow = 0;
}
grow = (grow) ? '*' : ' ';
newtFormAddComponent(form, newtLabel(col, row, "Growable?:"));
if (p->immutable) {
growentry = NULL;
newtFormAddComponent(form, newtLabel(22, row, "[ ]"));
} else {
growentry = newtCheckbox(22, row, "", grow, NULL, &grow);
}
row++;
/* give status */
if (!newpartition) {
newtFormAddComponent(form, newtLabel(col, row, "Allocation Status:"));
if (entry->status != REQUEST_DENIED)
newtFormAddComponent(form, newtLabel(22, row, "Successful"));
else
newtFormAddComponent(form, newtLabel(22, row, "Failed"));
row++;
if (entry->status == REQUEST_DENIED) {
newtFormAddComponent(form, newtLabel(col, row, "Failure Reason:"));
newtFormAddComponent(form,
newtLabel(22,row,GetReasonString(entry->reason)));
}
row++;
}
/* blow this bootable stuff for now, its confusing */
bootentry = NULL;
#if 0
if (!newpartition) {
for (hdidx=0; hdidx < numhd; hdidx++)
if (hdarr[hdidx]->num == p->drive.current)
break;
if (hdidx != numhd)
boot = fdiskPartitionIsBootable( hdarr[hdidx], p );
else
boot = 0;
} else {
boot = 0;
}
boot = (boot) ? '*' : ' ';
newtFormAddComponent(form, newtLabel(col, row, "Bootable?:"));
if (p->immutable) {
bootentry = NULL;
if (boot == '*')
newtFormAddComponent(form, newtLabel(22, row, "[*]"));
else
newtFormAddComponent(form, newtLabel(22, row, "[ ]"));
} else {
bootentry = newtCheckbox(22, row, "", boot, NULL, &boot);
}
row++;
#endif
/* type goes on right side under the mount point */
row = 3;
newtFormAddComponent(form, newtLabel(43, row, "Type:"));
if (p->immutable) {
typeentry = NULL;
for (j=0; j<nparttypes; j++)
if (allparttypes[j].index == p->type.current)
break;
if (j != nparttypes)
snprintf(tmpstr, sizeof(tmpstr), "%s", allparttypes[j].name);
else
snprintf(tmpstr,sizeof(tmpstr),"%6s (0x%x)",
"Unknown", p->type.current);
newtFormAddComponent(form, newtLabel(48, row, tmpstr));
row++;
} else {
typeentry = newtListbox( 48, row, 4, NEWT_FLAG_RETURNEXIT);
for (j=0; j<numfstypes; j++) {
snprintf(tmpstr,sizeof(tmpstr),"%s", fstypesnames[j]);
newtListboxAddEntry(typeentry, tmpstr,
(void *)fstypes[j]);
if (fstypes[j] == p->type.current)
newtListboxSetCurrent(typeentry, j);
else if (p->type.current == 0 &&
fstypes[j] == LINUX_NATIVE_PARTITION)
newtListboxSetCurrent(typeentry, j);
}
}
/* have to fix this later */
/* allowable drives goes in center under rest */
row = 8;
driveform = NULL;
if (!p->immutable) {
newtFormAddComponent(form, newtLabel(col, row, "Allowable Drives:"));
sb = newtVerticalScrollbar(40, row, 4, 9, 10);
driveform = newtForm(sb, NULL, 0);
newtFormSetBackground(driveform, NEWT_COLORSET_CHECKBOX);
for (j=0; j<numhd; j++) {
driveentry[j].state = fdiskThisDriveSetIsActive(&p->drive,
hdarr[j]->num);
driveentry[j].cb = newtCheckbox(22, row+j, hdarr[j]->name+5,
(driveentry[j].state) ? '*' : ' ',
NULL,
&driveentry[j].state);
newtFormAddComponent(driveform, driveentry[j].cb);
}
if (j > 4) {
newtFormSetHeight(driveform, 4);
newtFormAddComponent(driveform, sb);
} else {
newtFormSetWidth(driveform, 10);
}
}
/* setup type box callback */
if (typeentry) {
cb1.entry = &mntptentry;
cb1.val = mntpt;
/* yuck but it works */
typebox_mp[0] = -1;
inswapentry = (p->type.current == LINUX_SWAP_PARTITION);
newtComponentAddCallback(typeentry,(newtCallback) typebox_scroll,&cb1);
}
/* setup mount point callback */
if (!p->immutable) {
cb2.form = &form;
cb2.val = mntpt;
cb2.val2 = &boot;
memset(&cb2.curds, 0, sizeof(DriveSet));
memcpy(&cb2.origds, &p->drive, sizeof(DriveSet));
cb2.numhd = numhd;
cb2.hdarr = hdarr;
cb2.de = driveentry;
cb2.dobootable = (fdiskIndexPartitionSpec(spec, "/boot", &j) !=
FDISK_SUCCESS);
newtComponentAddCallback(mntptentry,(newtCallback) entrybox_cb,&cb2);
}
row = 9+cval;
ok = newtButton( 20, row, "Ok");
cancel = newtButton( 40, row, "Cancel");
if (mntptentry)
newtFormAddComponents( form, mntptentry, NULL );
if (sizeentry)
newtFormAddComponents( form, sizeentry, NULL);
if (growentry)
newtFormAddComponents( form, growentry, NULL);
#if 0
if (bootentry)
newtFormAddComponents( form, bootentry, NULL);
#endif
if (typeentry)
newtFormAddComponents( form, typeentry, NULL );
if (driveform)
newtFormAddComponents( form, driveform, NULL );
newtFormAddComponents( form, ok, cancel, NULL);
done = 0;
while (!done) {
answer = newtRunForm(form);
if (answer != cancel) {
/* modify partition request based on the entry boxes */
if (typeentry) {
tmpuint = (long) newtListboxGetCurrent( typeentry );
fdiskSetConstraint(&p->type, tmpuint, tmpuint, tmpuint, 1);
}
/* make sure mount point is valid */
if (p->type.current != LINUX_SWAP_PARTITION) {
int valid=1;
int skiprest=0;
TrimWhitespace(mntpt);
/* see if they even gave the partition a name */
/* we will ask them if they really want to not */
/* assign the partition a name at this time if */
/* they have just created a non-ext2 partition */
if (!*mntpt && p->type.current != LINUX_NATIVE_PARTITION) {
if (newtWinChoice("No Mount Point", "Yes", "No",
"You have not selected a mount point "
"for this partition. Are you sure you "
"want to do this?") == 1)
continue;
else {
/* we need a name for this partition */
/* we'll name them like swap partitions */
/* except use 'DOSxxx' */
if (strncmp("Dos", entry->name, 4)) {
char *t;
fdiskMakeUniqSpecName( spec, "Dos", &t );
fdiskRenamePartitionSpec(spec, entry->name, t);
}
skiprest = 1;
}
}
/* do old test first */
if (!skiprest) {
if (entry->status != REQUEST_ORIGINAL || *mntpt)
if (badMountPoint(p->type.current, mntpt))
continue;
if (entry->status == REQUEST_ORIGINAL) {
/* this is an original partition, should have a */
/* mount point of "" or a valid path */
if (*mntpt &&
(*mntpt != '/' || ((strcmp(entry->name, mntpt) &&
!fdiskIndexPartitionSpec(spec, mntpt, &tmpuint))))) {
valid = 0;
}
} else if (*mntpt != '/' || (strcmp(entry->name, mntpt) &&
!fdiskIndexPartitionSpec(spec, mntpt, &tmpuint))) {
valid = 0;
}
}
if (!valid) {
newtWinMessage("Mount Point Error", "Ok",
"The mount point requested is either an illegal "
"path or is already in use. Please select a "
"valid mount point." );
continue;
}
}
if (sizeentry) {
tmpint=strtol(size, &eptr, 10);
if (eptr != size && *eptr == 0 && tmpint > 0) {
tmpint *= SECPERMEG;
if (growentry && grow != ' ')
fdiskSetConstraint(&p->size,0,tmpint,FDISK_SIZE_MAX,1);
else
fdiskSetConstraint(&p->size,0,tmpint,tmpint,1);
} else {
newtWinMessage("Size Error", "Ok",
"The size requested is illegal. Make sure the "
"size is greater and zero (0), and is specified "
"int decimal (base 10) format.");
continue;
}
}
/* make sure swap partitions are not too large */
/* (PAGESIZE - 10)*8*PAGESIZE */
/* on the right arch's */
if (p->type.current == LINUX_SWAP_PARTITION) {
unsigned int maxswap;
#if defined(__alpha__)
maxswap = (8192-10)*8*8192;
#else
maxswap = (4096-10)*8*4096;
#endif
if (p->size.min*SECTORSIZE > maxswap) {
newtWinMessage("Swap Size Error", "Ok",
"You have created a swap partition which is too large. "
"The maximum size of a swap partition is 128 Megabytes.");
continue;
}
}
if (driveform) {
fdiskDeactivateAllDriveSet( &p->drive );
for (j=0; j<numhd; j++)
if (driveentry[j].state == '*')
fdiskActivateDriveSet( &p->drive, hdarr[j]->num );
}
/* fdiskHandleSpecialPartitions() will do this for us */
/* so I'm taking the boot entry out for now */
#if 0
if (bootentry) {
if (boot != ' ') {
fdiskSetConstraint(&p->endcyl, 0, 0, 1023, 1);
fdiskDeactivateAllDriveSet( &p->drive );
fdiskActivateDriveSet( &p->drive, 1 );
fdiskActivateDriveSet( &p->drive, 2 );
} else {
fdiskSetConstraint(&p->endcyl,
0,FDISK_ENDCYL_MIN,FDISK_ENDCYL_MAX,0);
/* fdiskActivateAllDriveSet( &p->drive ); */
}
}
#endif
if (p->type.current == LINUX_SWAP_PARTITION) {
/* make sure we have a valid swap partition name */
if (strncmp("Swap", entry->name, 4)) {
char *t;
fdiskMakeSwapSpecName( spec, &t );
fdiskRenamePartitionSpec(spec, entry->name, t);
free(t);
}
}
/* first see if they changed the mount point */
/* we only worry about ext2 and dos partitions */
/* which have a valid mntpt */
/* LOGIC is not the word for how all this works */
if (p->type.current != LINUX_SWAP_PARTITION &&
strncmp("Dos", mntpt, 3)) {
TrimWhitespace(mntpt);
if (p->immutable)
status = REQUEST_ORIGINAL;
else
status = REQUEST_PENDING;
if (strcmp(mntpt, entry->name)) {
/* if this is an original partition which we just set */
/* the name back to '' from a real name, set name back */
/* to the 'Existxxxxx' name */
if (entry->status == REQUEST_ORIGINAL && !*mntpt) {
for (hdidx=0; hdidx < numhd; hdidx++)
if (hdarr[hdidx]->num == p->drive.current)
break;
if (hdidx != numhd)
sprintf(tmpstr, "Exist%03d%03d",
hdarr[hdidx]->num, p->num.current);
else
strcpy(tmpstr,"Exist999999");
fdiskRenamePartitionSpec( spec, entry->name, tmpstr );
fdiskModifyPartitionSpec( spec, tmpstr, p, status);
} else {
fdiskRenamePartitionSpec( spec, entry->name, mntpt );
fdiskModifyPartitionSpec( spec, mntpt, p, status);
}
} else {
fdiskModifyPartitionSpec( spec, mntpt, p, status);
}
} else {
fdiskModifyPartitionSpec( spec, entry->name, p, status);
}
fdiskHandleSpecialPartitions( spec );
status = FDISK_SUCCESS;
done = 1;
} else {
status = FDISK_ERR_USERABORT;
done = 1;
}
}
newtPopWindow();
newtFormDestroy(form);
return status;
}
/* add a partition spec */
static int AddPartitionSpec(HardDrive **hdarr, unsigned int numhd,
PartitionSpec *spec) {
Partition template;
int status;
unsigned int i;
/* create a template partitionspec to send to editpartition */
memset(&template, 0, sizeof(Partition));
template.size.min = SECPERMEG;
/* insert with a name we know to mean its a new partition */
fdiskInsertPartitionSpec(spec, NEW_PARTSPEC, &template, REQUEST_PENDING);
fdiskIndexPartitionSpec( spec, NEW_PARTSPEC, &i );
status = EditPartitionSpec(hdarr, numhd, spec, &spec->entry[i]);
if (status == FDISK_SUCCESS) {
return FDISK_SUCCESS;
} else {
fdiskDeletePartitionSpec(spec, NEW_PARTSPEC);
return FDISK_ERR_USERABORT;
}
}
/* delete a partition spec */
static int DeletePartitionSpec( HardDrive **hdarr, unsigned int numhd,
PartitionSpec *spec, PartitionSpecEntry *entry,
int force) {
Partition *p;
int status;
unsigned int c, l, m, n, t;
char *tmpstr;
p = &entry->partition;
tmpstr=strdup(entry->name);
if (!force && newtWinChoice("Delete Partition", "Yes", "No",
"Are you sure you want to delete "
"this partiton?") == 1)
return FDISK_ERR_USERABORT;
if (p->immutable) {
fdiskGetCurrentConstraint(&p->num, &c);
fdiskGetCurrentConstraint(&p->type, &t);
fdiskGetCurrentDriveSet(&p->drive, &l);
for (m=0; m<numhd; m++)
if (hdarr[m]->num == l)
break;
fdiskRemovePartition(hdarr[m], c);
/* make it so we can delete this partition now */
p->immutable = 0;
fdiskModifyPartitionSpec( spec, tmpstr, p, REQUEST_PENDING );
/* ok, see if this was the last immutable logical partition */
/* in an immutable primary extended partition */
/* we pray that fdiskCleanOriginal... will get rid of the */
/* spec entry for the pep */
if (c > 4) {
if (fdiskLastLogical( hdarr[m], &n ) != FDISK_SUCCESS) {
/* all logicals are gone, blow away pep */
if (hdarr[m]->pep && hdarr[m]->table[hdarr[m]->pep].immutable){
fdiskRemovePartition(hdarr[m], hdarr[m]->pep);
}
}
}
}
status = fdiskDeletePartitionSpec( spec, tmpstr );
fdiskHandleSpecialPartitions( spec );
free(tmpstr);
return FDISK_SUCCESS;
}
/* edit/add an NFS partition -> set index to -1 if adding new */
int EditNFSMount( struct fstab *remotefs, int index,
struct netInterface *intf, struct netConfig *netc,
struct driversLoaded **dl ) {
int rc;
struct fstabEntry entry;
if (!intf->isConfigured) {
rc = bringUpNetworking(intf, netc, dl);
} else {
rc = 0;
}
if (rc)
return 1;
if (index == -1) {
initFstabEntry(&entry);
entry.type = PART_NFS;
entry.tagName = "NFS Mount";
entry.device = NULL;
entry.mntpoint = NULL;
rc = editNetMountPoint(&entry);
if (!rc)
addFstabEntry(remotefs, entry);
} else {
rc = editNetMountPoint(&remotefs->entries[index]);
}
return rc;
}
/* remote fstab entry */
int DeleteNFSMount(struct fstab *remotefs, int index) {
int i;
if (remotefs->numEntries < 1)
return 0;
for (i=index; i<remotefs->numEntries-1; i++)
remotefs->entries[i] = remotefs->entries[i+1];
remotefs->numEntries -= 1;
return 0;
}
/* used for each line in partbox - tells us what is on that line */
enum partbox_types {PARTBOX_COMMENT, PARTBOX_NFS, PARTBOX_PART};
struct partbox_entry {
enum partbox_types type; /* what is on this line */
int index; /* index in nfs or partition arrays */
int hilite; /* element in drive window to hilight */
};
/* simple callback for scrollbox skipping non-entries */
struct partbox_struct {
unsigned int len; /* total entries allocated */
unsigned int num; /* number in use */
newtComponent *dbox; /* drive box */
struct partbox_entry *entry; /* describes use of this line */
};
/* this is some ugly sh*t, don't try this at home kids */
static void partbox_scroll(newtComponent list, struct partbox_struct *status) {
static int last=-1;
static int dontforce=0;
int sel;
int i;
int odir, dir;
int done;
int lasttry;
/* get the index into the partbox_struct array */
sel = (long) newtListboxGetCurrent(list);
/* see if this callback occurred because we were forcing */
/* listbox to scroll */
if (dontforce) {
dontforce = 0;
return;
}
/* if the element is ok then just return */
if (status->entry[sel].type != PARTBOX_COMMENT) {
if (status->entry[sel].type == PARTBOX_PART &&
status->entry[sel].hilite >= 0 && status->dbox != NULL)
newtListboxSetCurrent(*status->dbox, status->entry[sel].hilite);
return;
}
/* see which direction we're heading , >0 means down, < 0 means up */
if (last == -1)
dir = 1;
else {
if (sel > last)
dir = 1;
else
dir = -1;
}
odir = dir;
done = 0;
lasttry = 0;
while (!done) {
if (dir > 0) {
for (i=sel; i < status->num; i++)
if (status->entry[i].type != PARTBOX_COMMENT)
break;
if (i!=status->num) {
dontforce = 1;
newtListboxSetCurrent(list, i);
last = i;
done = 1;
if (lasttry) {
/* scroll to top, since this is last try so original */
/* direction was going up */
dontforce = 1;
newtListboxSetCurrent(list, 0);
dontforce = 1;
newtListboxSetCurrent(list,last);
}
} else {
if (!lasttry) {
dir = -1;
lasttry = 1;
} else {
done = 1;
}
}
} else {
for (i=sel; i >= 0; i--)
if (status->entry[i].type != PARTBOX_COMMENT)
break;
if (i >= 0) {
dontforce = 1;
newtListboxSetCurrent(list, i);
last = i;
done = 1;
if (lasttry) {
/* scroll to bottom, since this is last try so original */
/* direction was going up */
dontforce = 1;
newtListboxSetCurrent(list, status->num-1);
dontforce = 1;
newtListboxSetCurrent(list,last);
}
} else {
if (!lasttry) {
dir = 1;
lasttry = 1;
} else {
done = 1;
}
}
}
}
/* if we found a valid line then move drive box selection too */
sel = (long) newtListboxGetCurrent(list);
if (status->entry[sel].type == PARTBOX_PART &&
status->entry[sel].hilite >= 0 && status->dbox != NULL)
newtListboxSetCurrent(*status->dbox, status->entry[sel].hilite);
}
static int MakeDriveBox( HardDrive **hdarr, unsigned int numhd,
unsigned int *drvused,
int x, int y, int dheight,
newtComponent *dbox ) {
int hdidx, i, per;
char tmpstr[80];
*dbox = newtListbox( 1, y, dheight, 0 );
newtComponentTakesFocus( *dbox, 0 );
for (hdidx=0; hdidx < numhd; hdidx++) {
snprintf(tmpstr,sizeof(tmpstr),
" %s [%5d/%3d/%2d] "
"%6dM %6dM %6dM"
" ",
hdarr[hdidx]->name+5,
hdarr[hdidx]->geom.cylinders,
hdarr[hdidx]->geom.heads,
hdarr[hdidx]->geom.sectors,
hdarr[hdidx]->totalsectors/SECPERMEG,
drvused[hdidx]/SECPERMEG,
hdarr[hdidx]->totalsectors/SECPERMEG-drvused[hdidx]/SECPERMEG
);
tmpstr[58]='[';
tmpstr[69]=']';
per = (100*drvused[hdidx])/hdarr[hdidx]->totalsectors;
if (per >= 99)
per = 10;
else
per = per/10;
for (i=0; i < per; i++)
tmpstr[59+i] = '#';
tmpstr[74]=0;
newtListboxAddEntry(*dbox, tmpstr, (void *) 0);
}
return FDISK_SUCCESS;
}
/* given partitoins/hard drives, returns a listbox for use */
/* includes the callback function to skip over headings */
static int MakePartBox( HardDrive **hdarr, unsigned int numhd,
PartitionSpec *spec, struct fstab *remotefs,
int x, int y, int pheight, int dheight,
newtComponent *list, struct partbox_struct *status,
newtComponent *dbox) {
newtComponent partbox;
unsigned int drivenum;
unsigned int totalused;
int col;
int i, k, hdidx;
unsigned int listlen;
unsigned int foundpart;
char tmpstr[80];
unsigned int *drvused=alloca(numhd*sizeof(unsigned int));
memset(drvused, 0, numhd*sizeof(unsigned int));
/* check if there are *any* partitions to display */
if (spec->num == 0 && remotefs->numEntries == 0) {
*list = NULL;
MakeDriveBox( hdarr, numhd, drvused, x, y+pheight+1, dheight, dbox );
return FDISK_ERR_BADNUM;
}
partbox = newtListbox( 1, 1, pheight, NEWT_FLAG_RETURNEXIT );
listlen = 0;
status->entry=(struct partbox_entry *)malloc(100*
sizeof(struct partbox_entry));
status->len = 100;
memset(status->entry, 0, status->len*sizeof(struct partbox_entry));
status->dbox = NULL;
for (hdidx=0; hdidx < numhd; hdidx++) {
drivenum = hdarr[hdidx]->num;
/* display all spec'd partitions for this drive */
foundpart = 0;
totalused = 0;
for (i=0; i<spec->num; i++) {
unsigned int num, minsize, actsize, drive, totsize;
char statstr[80];
char *pname, *devname;
Partition *p;
if (spec->entry[i].status == REQUEST_DENIED)
continue;
p = &spec->entry[i].partition;
if ((drive = p->drive.current) != drivenum)
continue;
if (fdiskIsExtended(p->type.current))
continue;
num = p->num.current;
actsize = p->size.current;
minsize = p->size.min;
pname = spec->entry[i].name;
devname = hdarr[hdidx]->name;
totsize = hdarr[hdidx]->totalsectors;
if (!foundpart)
foundpart = 1;
/* increment amount of space used */
totalused += actsize;
/* mount point */
col = 3;
memset(statstr, ' ', sizeof(statstr));
if (strncmp("Exist", pname, 5) && strncmp("Swap", pname, 4) &&
strncmp("Dos", pname, 3))
BuildTableField( statstr, pname, col, 16, 0 );
/* Block device */
snprintf(tmpstr, sizeof(tmpstr), "%s%d", devname+5, num );
col += 22;
BuildTableField( statstr, tmpstr, col, 10, 0 );
/* Size */
snprintf(tmpstr, sizeof(tmpstr), "%5dM", minsize/SECPERMEG);
col += 10;
BuildTableField( statstr, tmpstr, col, 9, 1 );
snprintf(tmpstr, sizeof(tmpstr), "%5dM", actsize/SECPERMEG);
col += 10;
BuildTableField( statstr, tmpstr, col, 9, 1 );
/* we dont want to see all that stuff, just English label */
/* for the type */
/* Type */
col += 13;
for (k=0; k<nparttypes; k++)
if (allparttypes[k].index == p->type.current)
break;
if (k != nparttypes)
snprintf(tmpstr, sizeof(tmpstr), "%s", allparttypes[k].name);
else
snprintf(tmpstr, sizeof(tmpstr), "0x%02x", p->type.current);
BuildTableField( statstr, tmpstr, col, 18, 0);
/* now stick it in listbox */
statstr[73]=0;
status->entry[listlen].type = PARTBOX_PART;
status->entry[listlen].index = i;
status->entry[listlen].hilite = hdidx;
newtListboxAddEntry(partbox, statstr,(void *) listlen);
listlen++;
}
drvused[hdidx] = totalused;
}
for (i=0; i<remotefs->numEntries; i++) {
char statstr[80];
/* mount point */
col = 2;
memset(statstr, ' ', sizeof(statstr));
BuildTableField( statstr, remotefs->entries[i].mntpoint, col, 16, 0 );
/* Block device */
col += 17;
snprintf(tmpstr, sizeof(tmpstr), "%s:%s",
remotefs->entries[i].netHost, remotefs->entries[i].netPath);
BuildTableField( statstr, tmpstr, col, 40, 0 );
/* Size */
/* snprintf(tmpstr, sizeof(tmpstr), "%5dM/NA ", minsize/SECPERMEG);*/
*tmpstr=0;
col += 12;
BuildTableField( statstr, "", col, 15, 0 );
/* Type */
col += 26;
BuildTableField( statstr, "NFS", col, 18, 0);
/* now stick it in listbox */
statstr[70]=0;
status->entry[listlen].type = PARTBOX_NFS;
status->entry[listlen].index = i;
newtListboxAddEntry(partbox, statstr,(void *) (listlen));
listlen++;
}
/* now display any partition specs which WERE NOT allocated */
foundpart = 0;
for (i=0; i<spec->num && !foundpart; i++)
if (spec->entry[i].status == REQUEST_DENIED)
foundpart = 1;
if (foundpart) {
status->entry[listlen].type = PARTBOX_COMMENT;
newtListboxAddEntry(partbox,"", (void *)listlen);
listlen++;
status->entry[listlen].type = PARTBOX_COMMENT;
newtListboxAddEntry(partbox,"Unallocated requested partitions",
(void *)listlen);
listlen++;
status->entry[listlen].type = PARTBOX_COMMENT;
newtListboxAddEntry(partbox,"--------------------------------",
(void *)listlen);
listlen++;
for (i=0; i<spec->num; i++) {
if (spec->entry[i].status == REQUEST_DENIED) {
unsigned int num, minsize, actsize;
char statstr[80];
char *pname;
Partition *p;
foundpart = 1;
p = &spec->entry[i].partition;
if (fdiskIsExtended(p->type.current))
continue;
num = p->num.current;
minsize = p->size.min;
actsize = p->size.current;
pname = spec->entry[i].name;
/* mount point */
col = 3;
memset(statstr, ' ', sizeof(statstr));
if (strncmp("Exist", pname, 5) && strncmp("Swap", pname, 4) &&
strncmp("Dos", pname, 3))
BuildTableField( statstr, pname, col, 16, 0 );
/* Reasons */
col += 17;
BuildTableField( statstr,
GetReasonString(spec->entry[i].reason),
col, 25, 0 );
/* Size */
snprintf(tmpstr, sizeof(tmpstr), "%5dM/NA ",
minsize/SECPERMEG);
col += 23;
BuildTableField( statstr, tmpstr, col, 15, 0 );
/* we dont want to see all that stuff, just English label */
/* for the type */
/* Type */
col += 15;
for (k=0; k<nparttypes; k++)
if (allparttypes[k].index == p->type.current)
break;
if (k != nparttypes)
snprintf(tmpstr, sizeof(tmpstr),"%s",allparttypes[k].name);
else
snprintf(tmpstr, sizeof(tmpstr),"0x%02x", p->type.current);
BuildTableField( statstr, tmpstr, col, 18, 0);
/* now stick it in listbox */
statstr[70]=0;
status->entry[listlen].type = PARTBOX_PART;
status->entry[listlen].index = i;
status->entry[listlen].hilite = -1;
newtListboxAddEntry(partbox, statstr,(void *) (listlen));
listlen++;
}
}
}
/* mark the VERY end of listbox */
status->num = listlen;
/* setup the callback for the listbox */
newtComponentAddCallback(partbox, (newtCallback) partbox_scroll, status);
for (i=0; i<status->num-1;i++)
if (status->entry[i].type != PARTBOX_COMMENT)
break;
if (i!=status->num)
newtListboxSetCurrent(partbox,i);
*list = partbox;
/* now make the drive box IF desired */
MakeDriveBox( hdarr, numhd, drvused, x, y+pheight+1, dheight, dbox );
if (partbox)
status->dbox = dbox;
return 0;
}
/* do a operation on a partition */
static int DoMenuFunction( char *function,
HardDrive **orighd, unsigned int numhd,
HardDrive **curhd,
newtComponent partbox,
struct partbox_struct *partbox_status,
PartitionSpec *spec ) {
unsigned int sel;
int num=0;
int status;
int i;
HardDrive *tmphdarr[MAX_HARDDRIVES];
if (partbox) {
sel = (long) newtListboxGetCurrent(partbox);
if (partbox_status->entry[sel].type != PARTBOX_COMMENT)
num = partbox_status->entry[sel].index;
else
num = -1;
} else {
num = -1;
}
for (i=0; i<numhd; i++) {
tmphdarr[i] = (HardDrive *) alloca(sizeof(HardDrive));
memcpy(tmphdarr[i], orighd[i], sizeof(HardDrive));
}
if (!strcmp("ADD", function)) {
status = AddPartitionSpec(tmphdarr, numhd, spec);
} else if (num >= 0 && !strcmp("EDIT", function)) {
status = EditPartitionSpec(tmphdarr, numhd, spec, &spec->entry[num]);
} else if (num >= 0 && !strcmp("DEL", function)) {
status = DeletePartitionSpec(orighd, numhd, spec, &spec->entry[num],0);
} else {
status = FDISK_ERR_BADNUM;
}
if (status == FDISK_SUCCESS) {
fdiskAutoInsertPartitions(orighd, numhd, tmphdarr, 1, spec );
showReasons( spec );
fdiskGrowPartitions(orighd, numhd, tmphdarr, spec);
/* if any original partitions were REMOVED we have to */
/* sync up their entries in the partition spec table */
/* with their actual representation in 'orighd'. */
/* Mainly fixes up logical partition #'s which change */
/* when other logical partitions are removed */
if (!strcmp("DEL", function))
fdiskCleanOriginalSpecs( orighd, numhd, spec );
for (i=0; i<numhd; i++)
memcpy(curhd[i],tmphdarr[i], sizeof(HardDrive));
return FDISK_SUCCESS;
} else {
return FDISK_ERR_BADNUM;
}
}
/* main loop of the program, builds the display of all drives/partitions */
static int StartMaster( HardDrive **hdarr, unsigned int numhd,
PartitionSpec *spec,
struct fstab *remotefs,
struct netInterface *intf, struct netConfig *netc,
struct driversLoaded **dl ) {
newtComponent form, add, addnfs, del, edit, reset, ok, cancel, answer;
newtComponent partbox, staticpartbox, curcomponent;
newtComponent dbox;
HardDrive *newhdarr[MAX_HARDDRIVES];
HardDrive *prestinehdarr[MAX_HARDDRIVES];
int formdone, totallydone, i, status;
int currentselection;
struct newtExitStruct event;
char tmpstr[80];
unsigned int width, height;
int changesmade=0;
int retcode = FDISK_SUCCESS; /* i'm optimistic */
struct partbox_struct partbox_status;
enum mywidgets {PARTBOX, ADD, ADDNFS, EDIT, DELETE,
RESET, OK, CANCEL, NONE};
enum mywidgets curwidget;
width = 78;
height = 20;
/* copy original hard drive configurations into work spaces */
for (i=0; i<numhd; i++) {
newhdarr[i] = (HardDrive *) alloca(sizeof(HardDrive));
memcpy(newhdarr[i], hdarr[i], sizeof(HardDrive));
prestinehdarr[i] = (HardDrive *) alloca(sizeof(HardDrive));
memcpy(prestinehdarr[i], hdarr[i], sizeof(HardDrive));
}
/* build the main list of installed/probed devices */
totallydone = 0;
currentselection = -1;
curwidget = NONE;
newtOpenWindow((screen_width-width)/2,
(screen_height-height)/2,
width, height, "Current Disk Partitions");
while (!totallydone) {
form = newtForm(NULL, NULL, 0);
/* are there ANY defined partitions ? */
staticpartbox = partbox = NULL;
newtFormAddComponent(form, newtLabel(1,0,
" Mount Point Device Requested Actual Type"));
MakePartBox(newhdarr, numhd, spec, remotefs,
1, 2, height-12, 4,
&partbox, &partbox_status, &dbox);
/* all my beautiful buttons */
add = newtButton( 1, height-4, "Add");
addnfs = newtButton(10, height-4, "Add NFS");
edit = newtButton(23, height-4, "Edit");
del = newtButton(33, height-4, "Delete");
reset = newtButton(45, height-4, "Reset");
ok = newtButton(57, height-4, "Ok");
cancel = newtButton(66, height-4, "Cancel");
/* and the hotkeys */
newtFormAddHotKey(form, NEWT_KEY_F1);
newtFormAddHotKey(form, NEWT_KEY_F2);
newtFormAddHotKey(form, NEWT_KEY_F3);
newtFormAddHotKey(form, NEWT_KEY_F4);
newtFormAddHotKey(form, NEWT_KEY_F5);
/* and how to use this plus info on version */
snprintf(tmpstr, sizeof(tmpstr),
" F1-Add F2-Add NFS F3-Edit "
"F4-Delete F5-Reset F12-Ok v%5s", VERSION_STR);
newtPushHelpLine(tmpstr);
if (partbox)
newtFormAddComponents(form, partbox, NULL);
else if (staticpartbox)
newtFormAddComponents(form, staticpartbox, NULL);
if (dbox) {
newtFormAddComponent(form, newtLabel(1, 9, "Drive Summaries"));
newtFormAddComponent(form, newtLabel(1, 10,
" Drive Geom [C/H/S] Total Used Free"));
newtFormAddComponents(form, dbox, NULL);
}
newtFormAddComponents(form, add, addnfs, edit, del,
reset, ok, cancel, NULL);
if (partbox) {
if (currentselection < 0)
currentselection = (long) newtListboxGetCurrent(partbox);
else
newtListboxSetCurrent(partbox, currentselection);
}
/* see if no partitions are present */
if (spec->num == 0)
curwidget = ADD;
/* set current widget if necessary */
if (partbox != NULL && curwidget == PARTBOX)
newtFormSetCurrent(form, partbox);
else if (curwidget == ADD)
newtFormSetCurrent(form, add);
else if (curwidget == ADDNFS)
newtFormSetCurrent(form, addnfs);
else if (curwidget == EDIT)
newtFormSetCurrent(form, edit);
else if (curwidget == DELETE)
newtFormSetCurrent(form, del);
else if (curwidget == RESET)
newtFormSetCurrent(form, reset);
/* setup main screen */
formdone = 0;
answer = NULL;
while (!formdone) {
newtFormRun(form, &event);
/* store the current widget so we can reset it */
/* if we have to destroy and recreate form */
/* GetCurrent(), SetCurrent() use a ptr to */
/* newtcomponent, so when we recreate form it */
/* will be meaningless! */
curcomponent = newtFormGetCurrent( form );
curwidget = NONE;
if (partbox != NULL && curcomponent == partbox)
curwidget = PARTBOX;
else if (curcomponent == add)
curwidget = ADD;
else if (curcomponent == addnfs)
curwidget = ADDNFS;
else if (curcomponent == edit)
curwidget = EDIT;
else if (curcomponent == del)
curwidget = DELETE;
else if (curcomponent == reset)
curwidget = RESET;
else
curwidget = NONE;
if (event.reason == NEWT_EXIT_HOTKEY) {
event.reason = NEWT_EXIT_COMPONENT;
if (event.u.key == NEWT_KEY_F12)
event.u.co = ok;
else if (event.u.key == NEWT_KEY_F1)
event.u.co = add;
else if (event.u.key == NEWT_KEY_F2)
event.u.co = addnfs;
else if (event.u.key == NEWT_KEY_F3)
event.u.co = edit;
else if (event.u.key == NEWT_KEY_F4)
event.u.co = del;
else if (event.u.key == NEWT_KEY_F5)
event.u.co = reset;
else
continue;
}
if (event.reason == NEWT_EXIT_COMPONENT) {
if (event.u.co != partbox) {
if (event.u.co == ok || event.u.co == cancel) {
if (event.u.co == ok) {
/* make sure '/' is defined */
status = fdiskIndexPartitionSpec(spec, "/", &i);
if (!status)
if (spec->entry[i].partition.type.current !=
LINUX_NATIVE_PARTITION ||
spec->entry[i].status == REQUEST_DENIED)
status = 1;
if (status) {
newtWinMessage("No Root Partition", "Ok",
"You must assign a root (/) "
"partition "
"to a Linux native partition (ext2) "
"for the install to proceed.");
continue;
}
/* make sure some swapspace is defined */
status = 1;
for (i=0; i < spec->num; i++)
if (spec->entry[i].partition.type.current ==
LINUX_SWAP_PARTITION &&
spec->entry[i].status != REQUEST_DENIED) {
status = 0;
break;
}
if (status) {
newtWinMessage("No Swap Partition", "Ok",
"You must assign a swap "
"partition "
"for the install to proceed.");
continue;
}
}
/* make sure there are no unallocated partitions */
status = 0;
for (i=0; i < spec->num; i++)
if (spec->entry[i].status == REQUEST_DENIED) {
status = 1;
break;
}
if (status) {
if (newtWinChoice("Unallocated Partitions",
"Yes", "No",
"There are unallocated partitions "
"left. If you quit now they will "
"not be written to the disk.\n\n"
"Are you sure you want to exit?") == 1)
continue;
}
/* dont trust the changes made I keep up with */
/* above, compute it straight from the hd's */
changesmade = DisksChanged( prestinehdarr,
newhdarr,
numhd );
if (changesmade) {
int rc;
rc = newtWinTernary("Save Changes",
"Yes", "No", "Cancel",
"Save changes to "
"partition table(s)?");
if (rc == 1) {
retcode = FDISK_SUCCESS;
/* copy changes */
if (changesmade) {
for (i=0; i<numhd; i++) {
memcpy(hdarr[i],
newhdarr[i],
sizeof(HardDrive));
}
}
} else if (rc == 2) {
retcode = FDISK_ERR_USERABORT;
} else {
continue;
}
} else {
retcode = FDISK_SUCCESS; /* no changes made */
}
/* make sure we indicate they canceled */
if (event.u.co == cancel)
retcode = FDISK_ERR_USERABORT;
formdone = 1;
totallydone = 1;
} else if (event.u.co == add) {
status=DoMenuFunction("ADD", hdarr, numhd, newhdarr,
partbox, &partbox_status, spec );
if (status == FDISK_SUCCESS) {
formdone = 1;
changesmade = 1;
}
} else if (event.u.co == del) {
/* see if its NFS or local mount */
int sel;
sel = (long) newtListboxGetCurrent(partbox);
if (partbox_status.entry[sel].type == PARTBOX_PART)
status=DoMenuFunction("DEL", hdarr, numhd,
newhdarr,
partbox, &partbox_status,
spec );
else
status=DeleteNFSMount(remotefs,
partbox_status.entry[sel].index);
if (status == FDISK_SUCCESS) {
formdone = 1;
changesmade = 1;
}
} else if (event.u.co == edit) {
/* see if its NFS or local mount */
int sel;
sel = (long) newtListboxGetCurrent(partbox);
if (partbox_status.entry[sel].type == PARTBOX_PART)
status=DoMenuFunction("EDIT", hdarr, numhd,
newhdarr,
partbox, &partbox_status,
spec );
else
status=EditNFSMount(remotefs,
partbox_status.entry[sel].index,
intf, netc, dl);
if (status == FDISK_SUCCESS) {
formdone = 1;
changesmade = 1;
}
} else if (event.u.co == reset) {
if (newtWinChoice("Reset Partition Table",
"Yes", "No",
"Reset partition table to original "
"contents? ") != 1) {
for (i=0; i<numhd; i++)
memcpy(hdarr[i],prestinehdarr[i],
sizeof(HardDrive));
fdiskWipePartitionSpec(spec);
fdiskSetupPartitionSpec( hdarr, numhd, spec );
changesmade = 0;
formdone = 1;
}
} else if (event.u.co == addnfs) {
status=EditNFSMount(remotefs, -1, intf, netc, dl);
if (status == FDISK_SUCCESS) {
formdone = 1;
changesmade = 1;
}
}
} else {
/* see if its NFS or local mount */
int sel;
sel = (long) newtListboxGetCurrent(partbox);
if (partbox_status.entry[sel].type == PARTBOX_PART)
status=DoMenuFunction("EDIT", hdarr, numhd, newhdarr,
partbox, &partbox_status, spec );
else
status=EditNFSMount(remotefs,
partbox_status.entry[sel].index,
intf, netc, dl);
if (status == FDISK_SUCCESS) {
formdone = 1;
changesmade = 1;
}
}
}
/* save current line if leaving */
if (partbox)
currentselection = (long) newtListboxGetCurrent(partbox);
}
newtPopHelpLine();
if (partbox)
free(partbox_status.entry);
newtFormDestroy(form);
}
newtPopWindow();
return retcode;
}
/* converts a PartionSpec to an equivalent struct fstab */
/* Creates fstab from scratch */
static int PartitionSpecToFstab( HardDrive **hdarr, int numhd,
PartitionSpec *spec, struct fstab *fstab ) {
int i, j;
struct fstabEntry entry;
fstab->entries = malloc(sizeof(*fstab->entries) * spec->num);
fstab->numEntries = 0;
for (i = 0; i < spec->num; i++) {
if (!spec->entry[i].name) continue;
if (spec->entry[i].status != REQUEST_ORIGINAL &&
spec->entry[i].status != REQUEST_GRANTED)
continue;
/* FIXME: hack, hack, hack */
if (*spec->entry[i].name != '/' &&
*spec->entry[i].name != 'S') continue;
for (j=0; j<numhd; j++)
if (hdarr[j]->num == spec->entry[i].partition.drive.current)
break;
if (j == numhd)
continue;
initFstabEntry(&entry);
entry.mntpoint = strdup(spec->entry[i].name);
entry.size = spec->entry[i].partition.size.current / 2;
entry.device = malloc(6);
sprintf(entry.device, "%s%d",
hdarr[j]->name + 5, spec->entry[i].partition.num.current);
switch (spec->entry[i].partition.type.current) {
case LINUX_NATIVE_PARTITION:
entry.type = PART_EXT2;
entry.tagName = "Linux native";
break;
case LINUX_SWAP_PARTITION:
entry.type = PART_SWAP;
entry.tagName = "Linux swap";
break;
case DOS_PRIMARY_lt32MEG_PARTITION:
case DOS_PRIMARY_gt32MEG_PARTITION:
entry.type = PART_DOS;
entry.tagName = "DOS 16-bit >=32";
break;
default:
entry.type = PART_OTHER;
entry.tagName = "Other";
break;
}
addFstabEntry(fstab, entry);
}
fstabSort(fstab);
return 0;
}
/* merges mount point info from existing struct fstab into a PartionSpec */
/* PartitionSpec should already exist and be primed with existing partitions */
/* Note - remote fs ARE NOT stored in the PartitionSpec */
static int MergeFstabEntries( HardDrive **hdarr, int numhd,
PartitionSpec *spec, struct fstab *fstab ) {
int i, j, k;
char device[6];
for (j = 0; j < spec->num; j++) {
for (k=0; k<numhd; k++)
if (hdarr[k]->num == spec->entry[j].partition.drive.current)
break;
if (k == numhd)
continue;
sprintf(device, "%s%d",
hdarr[k]->name + 5, spec->entry[j].partition.num.current);
for (i = 0; i < fstab->numEntries; i++)
if (!strcmp(fstab->entries[i].device, device))
break;
if ( i == fstab->numEntries )
continue;
/* we found a matching entry in the PartitionSpec */
/* see if the old fstab file had any info we need */
/* to use (like mount point, etc) */
if (spec->entry[j].name)
free(spec->entry[j].name);
spec->entry[j].name = strdup(fstab->entries[i].mntpoint);
}
return 0;
}
/* suck out just the remote fs entries from an fstab */
/* pretty much CopyFstab, with filter on type */
struct fstab copyRemoteFSFstab(struct fstab * fstab) {
struct fstab newfstab;
int i, j;
if (!fstab->numEntries) {
newfstab.numEntries = 0;
newfstab.entries = malloc(1);
return newfstab;
}
/* duplicate the current fstab */
newfstab.numEntries = fstab->numEntries;
newfstab.entries = malloc(fstab->numEntries * sizeof(struct fstabEntry));
for (i = j = 0; i < newfstab.numEntries; i++) {
if (fstab->entries[i].type != PART_NFS)
continue;
if (fstab->entries[i].mntpoint) {
newfstab.entries[j] = fstab->entries[i];
newfstab.entries[j].mntpoint=nstrdup(fstab->entries[i].mntpoint);
newfstab.entries[j].device = nstrdup(fstab->entries[i].device);
newfstab.entries[j].netPath = nstrdup(fstab->entries[i].netPath);
newfstab.entries[j].netHost = nstrdup(fstab->entries[i].netHost);
j++;
}
}
newfstab.numEntries = j;
/* return the memory we don't actually need */
newfstab.entries=realloc(newfstab.entries, j * sizeof(struct fstabEntry));
return newfstab;
}
/* suck out just the remote fs entries from an fstab */
/* pretty much CopyFstab, with filter on type */
void MergeRemoteFSFstab(struct fstab *oldfstab, struct fstab *newfstab) {
int i, j;
/* copy remote fs entries */
for (i = 0; i < oldfstab->numEntries; i++) {
if (oldfstab->entries[i].type != PART_NFS)
continue;
if (oldfstab->entries[i].mntpoint) {
j = newfstab->numEntries;
newfstab->entries = realloc(newfstab->entries,
(j+1)*sizeof(struct fstabEntry));
newfstab->entries[j] = oldfstab->entries[i];
newfstab->entries[j].mntpoint=nstrdup(oldfstab->entries[i].mntpoint);
newfstab->entries[j].device=nstrdup(oldfstab->entries[i].device);
newfstab->entries[j].netPath=nstrdup(oldfstab->entries[i].netPath);
newfstab->entries[j].netHost=nstrdup(oldfstab->entries[i].netHost);
newfstab->numEntries = j+1;
}
}
}
int kickstartPartitioning(struct partitionTable * parts, struct fstab * fstab,
char **drives) {
HardDrive *hd[MAX_HARDDRIVES];
HardDrive *tmphd[MAX_HARDDRIVES]; /* ORIGINAL HD partition data */
unsigned int numhd; /* total # of drives to consider */
Partition template;
PartitionSpec spec;
unsigned int i;
struct fstab remotefstab;
char ** deviceList;
int rc;
int numDrives;
int size, maxsize, grow, clearall, clearlinux, zerombr;
int argc;
char *mntpt;
char *eptr;
char *sizestr, *maxsizestr;
char **argv;
poptContext optCon;
struct poptOption ksPartOptions[] = {
{ "size", '\0', POPT_ARG_STRING, &sizestr, 0 },
{ "maxsize", '\0', POPT_ARG_STRING, &maxsize, 0 },
{ "grow", '\0', POPT_ARG_NONE, &grow, 0 },
{ 0, 0, 0, 0, 0 }
};
struct poptOption ksClearOptions[] = {
{ "linux", '\0', POPT_ARG_NONE, &clearlinux, 0},
{ "all", '\0', POPT_ARG_NONE, &clearall, 0},
{ 0, 0, 0, 0, 0 }
};
struct poptOption ksZeroMBROptions[] = {
{ 0, 0, 0, 0, 0 }
};
numDrives = 0;
for (i = 0; drives[i]; i++, numDrives++);
if (numDrives >= MAX_HARDDRIVES) {
newtWinMessage("Too Many Drives", "Ok",
"You have more drives than this program supports. "
"Please use the standard fdisk program to setup your "
"drives and please notify Red Hat Software that you "
"saw this message.");
return INST_ERROR;
}
deviceList = alloca(numDrives * sizeof(char *));
for (i = 0; i < numDrives; i++) {
deviceList[i] = alloca(15);
strcpy(deviceList[i], "/tmp/");
strcat(deviceList[i], drives[i]);
if ((rc = devMakeInode(drives[i], deviceList[i]))) return INST_ERROR;
}
/* see if they want bad partition tables automatically zero'd */
argv = NULL;
zerombr = 0;
while (1) {
if (!ksGetCommand(KS_CMD_ZEROMBR, argv, &argc, &argv)) {
char *t;
optCon = poptGetContext(NULL, argc, argv, ksZeroMBROptions, 0);
/* no options, but just a 'on' or 'off' command */
/* have to parse options anyway to make popt see the leftover? */
poptGetNextOpt(optCon);
t = poptGetArg(optCon);
if (*t && (!strcasecmp(t,"no") || !strcasecmp(t,"off") || !strcmp(t,"0")))
zerombr = 0;
else if (*t && (!strcasecmp(t,"yes") || !strcasecmp(t,"on") || !strcmp(t,"1")))
zerombr = 1;
else
newtWinMessage("Zero Partition Table", "Ok",
"bad argument to kickstart "
"zerombr command: %s.\nMust be "
"'on', '1', or 'yes' to enable, "
"or 'off', '0', or 'no' to disable.",t);
poptFreeContext(optCon);
} else {
break;
}
}
/* Read in the partition tables from the requested drive(s) */
/* first clear all entries */
memset(hd, 0, MAX_HARDDRIVES*sizeof(HardDrive *));
ReadDrives(deviceList, numDrives, hd, &numhd, zerombr);
if (numhd <1) {
newtWinMessage("No Drives Found", "Ok",
"An error has occurred - no valid devices were found "
"on which to create new filesystems. Please check "
"your hardware for the cause of this problem.");
for (i = 0; i < numDrives; i++)
unlink(deviceList[i]);
return INST_ERROR;
}
/* Translate into a PartitionSpec */
memset(&spec, 0, sizeof(PartitionSpec));
fdiskSetupPartitionSpec( hd, numhd, &spec );
/* copy the fstab they passed, we'll use it until we're done */
/* if they dont cancel it will be new fstab */
remotefstab = copyRemoteFSFstab( fstab );
MergeFstabEntries( hd, numhd, &spec, fstab );
/* see if they want anything removed from disk */
argv = NULL;
clearall = 0;
clearlinux = 0;
if (!ksGetCommand(KS_CMD_CLEARPART, argv, &argc, &argv)) {
optCon = poptGetContext(NULL, argc, argv, ksClearOptions, 0);
rc = poptGetNextOpt(optCon);
if ( rc < -1) {
newtWinMessage("Clear Partition Command", "Ok",
"bad argument to kickstart "
"clearpart command %s: %s",
poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
poptStrerror(rc));
for (i=0; i<numhd; i++)
fdiskCloseDevice(hd[i]);
for (i = 0; i < numDrives; i++)
unlink(deviceList[i]);
return INST_ERROR; /* may not clear what they intended */
}
for (i = 0; i < spec.num; ) {
int deleteit;
deleteit = clearall;
if (!clearall && clearlinux) {
switch (spec.entry[i].partition.type.current) {
case LINUX_SWAP_PARTITION:
case LINUX_NATIVE_PARTITION:
deleteit = 1;
break;
default:
break;
}
}
if (deleteit) {
DeletePartitionSpec(hd, numhd, &spec, &spec.entry[i], 1);
fdiskCleanOriginalSpecs( hd, numhd, &spec );
i=0; /* restart cause entries changed */
continue;
} else {
i++;
}
}
poptFreeContext(optCon);
}
/* copy original hard drive configurations into work spaces */
for (i=0; i<numhd; i++) {
tmphd[i] = (HardDrive *) alloca(sizeof(HardDrive));
memcpy(tmphd[i], hd[i], sizeof(HardDrive));
}
/* now stick their requests into the partition spec and allocate */
/* the partitions */
argv = NULL;
while (1) {
sizestr = NULL;
maxsizestr = NULL;
grow = 0;
if (!ksGetCommand(KS_CMD_PART, argv, &argc, &argv)) {
optCon = poptGetContext(NULL, argc, argv, ksPartOptions, 0);
rc = poptGetNextOpt(optCon);
if ( rc < -1) {
newtWinMessage("Partition Command", "Ok",
"bad argument to kickstart "
"part command %s: %s",
poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
poptStrerror(rc));
}
mntpt = poptGetArg(optCon);
if (sizestr) {
size=strtol(sizestr,&eptr, 10);
if (eptr != sizestr && *eptr == 0 && size > 0)
size *= SECPERMEG;
else
size = 0;
} else {
size=0;
}
if (maxsizestr) {
maxsize=strtol(maxsizestr,&eptr, 10);
if (eptr != maxsizestr && *eptr == 0 && maxsize > 0)
maxsize *= SECPERMEG;
else
maxsize = 0;
} else {
maxsize=0;
}
if (maxsizestr && !maxsize)
newtWinMessage("Option Ignored", "Ok",
"The --maxsize option for the partition "
"%s was ignored. Check that it is larger "
"than the --size option.", mntpt);
/* all done with current context */
poptFreeContext(optCon);
if (!mntpt || size == 0) {
for (i=0; i<numhd; i++)
fdiskCloseDevice(hd[i]);
for (i = 0; i < numDrives; i++)
unlink(deviceList[i]);
return INST_ERROR;
}
/* fill in the requested partition */
memset(&template, 0, sizeof(Partition));
/* set the size */
if (grow)
fdiskSetConstraint(&template.size,
0,
size,
(maxsize) ? maxsize : FDISK_SIZE_MAX,
1);
else
fdiskSetConstraint(&template.size,
0,
size,
size,
1);
/* set the type */
if (!strcasecmp(mntpt, "swap"))
fdiskSetConstraint(&template.type,
LINUX_SWAP_PARTITION,
LINUX_SWAP_PARTITION,
LINUX_SWAP_PARTITION,
1);
else {
fdiskSetConstraint(&template.type,
LINUX_NATIVE_PARTITION,
LINUX_NATIVE_PARTITION,
LINUX_NATIVE_PARTITION,
1);
/* test mntpt */
if (badMountPoint(template.type.current, mntpt)) {
for (i=0; i<numhd; i++)
fdiskCloseDevice(hd[i]);
for (i = 0; i < numDrives; i++)
unlink(deviceList[i]);
return INST_ERROR;
}
if (!fdiskIndexPartitionSpec(&spec, mntpt, &rc)) {
newtWinMessage("Mount Point Error", "Ok"
"The mount point %s is already in use.", mntpt);
for (i=0; i<numhd; i++)
fdiskCloseDevice(hd[i]);
for (i = 0; i < numDrives; i++)
unlink(deviceList[i]);
return INST_ERROR;
}
}
/* make sure we have a valid swap partition name */
if (template.type.current == LINUX_SWAP_PARTITION) {
if (strcasecmp("swap", mntpt)) {
fdiskMakeSwapSpecName( &spec, &mntpt );
}
}
/* make an entry */
fdiskInsertPartitionSpec(&spec, mntpt,&template, REQUEST_PENDING);
fdiskHandleSpecialPartitions( &spec );
} else {
break;
}
}
/* insert the new partition spec */
fdiskAutoInsertPartitions(hd, numhd, tmphd, 1, &spec);
showReasons( &spec );
fdiskGrowPartitions(hd, numhd, tmphd, &spec);
rc = REQUEST_GRANTED;
for (i=0; i<spec.num; i++)
if (spec.entry[i].status == REQUEST_DENIED) {
rc = REQUEST_DENIED;
newtWinMessage("Failed Allocation", "Ok",
"The partition %s could not be allocated.",
spec.entry[i].name);
}
if (rc == REQUEST_DENIED) {
for (i=0; i<numhd; i++)
fdiskCloseDevice(hd[i]);
for (i = 0; i < numDrives; i++)
unlink(deviceList[i]);
return INST_ERROR;
}
/* Write partitions to disk */
for (i=0; i<numhd; i++)
memcpy(hd[i], tmphd[i], sizeof(HardDrive));
if (!testing) {
for (i=0; i<numhd; i++)
fdiskWritePartitions(hd[i]);
}
if ((rc = findAllPartitions(NULL, parts))) {
for (i=0; i<numhd; i++)
fdiskCloseDevice(hd[i]);
for (i = 0; i < numDrives; i++)
unlink(deviceList[i]);
return INST_ERROR;
}
/* free up old fstab */
if (fstab)
freeFstab(*fstab);
PartitionSpecToFstab( hd, numhd, &spec, fstab );
MergeRemoteFSFstab( &remotefstab, fstab );
freeFstab(remotefstab);
for (i=0; i<numhd; i++)
fdiskCloseDevice(hd[i]);
for (i = 0; i < numDrives; i++)
unlink(deviceList[i]);
return 0;
}
#if 1
/* main program */
int FSEditPartitions(struct partitionTable * parts, struct fstab * fstab,
char **drives,
struct netInterface * intf, struct netConfig * netc,
struct driversLoaded ** dl) {
HardDrive *prestinehdarr[MAX_HARDDRIVES];
HardDrive *hdarr[MAX_HARDDRIVES]; /* ORIGINAL HD partition data */
unsigned int numhd; /* total # of drives to consider */
PartitionSpec spec;
unsigned int i;
struct fstab remotefstab;
char ** deviceList;
int rc;
int numDrives;
numDrives = 0;
for (i = 0; drives[i]; i++, numDrives++);
if (numDrives >= MAX_HARDDRIVES) {
newtWinMessage("Too Many Drives", "Ok",
"You have more drives than this program supports. "
"Please use the standard fdisk program to setup your "
"drives and please notify Red Hat Software that you "
"saw this message.");
return INST_ERROR;
}
deviceList = alloca(numDrives * sizeof(char *));
for (i = 0; i < numDrives; i++) {
deviceList[i] = alloca(15);
strcpy(deviceList[i], "/tmp/");
strcat(deviceList[i], drives[i]);
if ((rc = devMakeInode(drives[i], deviceList[i]))) return rc;
}
/* Read in the partition tables from the requested drive(s) */
/* first clear all entries */
memset(hdarr, 0, MAX_HARDDRIVES*sizeof(HardDrive *));
ReadDrives(deviceList, numDrives, hdarr, &numhd,0);
if (numhd <1) {
newtWinMessage("No Drives Found", "Ok",
"An error has occurred - no valid devices were found "
"on which to create new filesystems. Please check "
"your hardware for the cause of this problem.");
for (i = 0; i < numDrives; i++)
unlink(deviceList[i]);
return INST_ERROR;
}
/* Translate into a PartitionSpec */
memset(&spec, 0, sizeof(PartitionSpec));
fdiskSetupPartitionSpec( hdarr, numhd, &spec );
/* copy the fstab they passed, we'll use it until we're done */
/* if they dont cancel it will be new fstab */
remotefstab = copyRemoteFSFstab( fstab );
MergeFstabEntries( hdarr, numhd, &spec, fstab );
/* make backup of hdarr before user mucked with it */
for (i=0; i<numhd; i++) {
prestinehdarr[i] = (HardDrive *) alloca(sizeof(HardDrive));
memcpy(prestinehdarr[i], hdarr[i], sizeof(HardDrive));
}
/* Goto master screen */
if ((rc = StartMaster(hdarr, numhd, &spec,
&remotefstab, intf, netc, dl)) == FDISK_SUCCESS) {
/* Write partitions to disk */
if (!testing) {
if (DisksChanged(prestinehdarr, hdarr, numhd))
for (i=0; i<numhd; i++)
fdiskWritePartitions(hdarr[i]);
}
if ((rc = findAllPartitions(NULL, parts))) {
for (i=0; i<numhd; i++)
fdiskCloseDevice(hdarr[i]);
for (i = 0; i < numDrives; i++)
unlink(deviceList[i]);
return INST_ERROR;
}
/* free up old fstab */
if (fstab)
freeFstab(*fstab);
PartitionSpecToFstab( hdarr, numhd, &spec, fstab );
MergeRemoteFSFstab( &remotefstab, fstab );
freeFstab(remotefstab);
rc = 0;
} else if (rc == FDISK_ERR_USERABORT) {
rc = INST_CANCEL;
} else {
rc = INST_ERROR;
}
for (i=0; i<numhd; i++)
fdiskCloseDevice(hdarr[i]);
for (i = 0; i < numDrives; i++)
unlink(deviceList[i]);
return rc;
}
#else
/* main program */
int main (int argc, char **argv) {
HardDrive *hdarr[MAX_HARDDRIVES]; /* ORIGINAL HD partition data */
unsigned int numhd; /* total # of drives to consider */
PartitionSpec spec;
/* make sure we should even be running */
if (getuid()) {
fprintf(stderr,"\nERROR - You must be root to run newtfdisk.\n");
exit(1);
}
/* newt startup */
NewtStartUp();
/* Set up intro screen with info */
if (!IntroScreen()) {
newtFinished();
exit(1);
}
/* Read in the partition tables from the requested drive(s) */
/* first clear all entries */
memset(hdarr, 0, MAX_HARDDRIVES*sizeof(HardDrive *));
ReadDrives(argv+1, argc-1, hdarr, &numhd, 0);
if (numhd <1) {
newtWinMessage("No Drives Found", "Ok",
"An error has occurred - no valid devices were found "
"on which to create new filesystems. Please check "
"your hardware for the cause of this problem." );
newtFinished();
exit(1);
}
/* Translate into a PartitionSpec */
fdiskSetupPartitionSpec( hdarr, numhd, &spec );
/* Goto master screen */
StartMaster(hdarr, numhd, &spec);
newtFinished();
exit(0);
}
#endif