home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 1998 February
/
CHIP_2_98.iso
/
misc
/
src
/
install
/
fs.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-10-14
|
32KB
|
1,242 lines
#include <alloca.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <newt.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <unistd.h>
#include "devices.h"
#include "fs.h"
#include "install.h"
#include "log.h"
#include "mkswap.h"
#include "perror.h"
#include "run.h"
#include "smb.h"
#include "windows.h"
int nfsmount(const char *spec, const char *node, int *flags,
char **extra_opts, char **mount_opts);
static int selectRootPartition(struct partitionTable table, int * rootPartNum);
static int fstabCmp(const void * a, const void * b);
static int mkdirChain(char * chain);
static int mkdirIfNone(char * directory);
int canEnableSwap = 1;
int badBlocks = 0;
char * nstrdup(const char * foo) {
return foo ? strdup(foo) : NULL;
}
static int fstabCmp(const void * a, const void * b) {
const struct fstabEntry * first = a;
const struct fstabEntry * second = b;
if (first->type != second->type) {
if (first->type == PART_NFS)
return 1;
else if (second->type == PART_NFS)
return -1;
}
return strcmp(first->mntpoint, second->mntpoint);
}
void fstabSort(struct fstab * fstab) {
qsort(fstab->entries, fstab->numEntries,
sizeof(*fstab->entries), fstabCmp);
}
void initFstabEntry(struct fstabEntry * e) {
e->device = NULL;
e->netHost = NULL;
e->netPath = NULL;
e->mntpoint = NULL;
e->tagName = NULL;
e->size = 0;
e->type = PART_OTHER;
e->isMounted = 0;
e->doFormat = 0;
}
newtComponent addPartitionListbox(struct partitionTable table,
newtComponent form, int left, int top,
int height, int type,
int (*filter)(struct partition * part),
int * numItems) {
newtComponent listbox, label;
int i;
char buf[80];
listbox = newtListbox(left, top + 1, height, NEWT_LISTBOX_RETURNEXIT);
label = newtLabel(left, top, "Device Begin End "
"Size (k)");
if (numItems) *numItems = 0;
for (i = 0; i < table.count; i++) {
if (table.parts[i].type == type) {
if (!filter || filter(table.parts + i)) {
sprintf(buf, "/dev/%-5s %9d %9d %9d", table.parts[i].device,
table.parts[i].begin, table.parts[i].end,
table.parts[i].size);
newtListboxAddEntry(listbox, buf, &table.parts[i]);
if (numItems) (*numItems)++;
}
}
}
newtFormAddComponents(form, label, listbox, NULL);
return listbox;
}
static int selectRootPartition(struct partitionTable table, int * rootPartNum) {
newtComponent okay, cancel, form, text, listbox, answer;
int i;
struct partition * rootPart = NULL;
for (i = 0; i < table.count; i++)
if (table.parts[i].type == PART_EXT2) break;
if (i == table.count) {
newtWinMessage("Select Root", "Ok",
"You don't have any Linux native partitions "
"defined. You must return to repartition "
"your hard drive.");
return INST_CANCEL;
}
*rootPartNum = i;
newtCenteredWindow(64, 19, "Select Root Partition");
text = newtTextbox(1, 1, 62, 4, NEWT_TEXTBOX_WRAP);
newtTextboxSetText(text, "The root partition forms the base of your Linux "
"filesystem. It must hold everything necessary for "
"booting and initializing your system. What partition "
"would you like to use for the root filesystem?");
okay = newtButton(15, 15, "Ok");
cancel = newtButton(38, 15, "Cancel");
form = newtForm(NULL, NULL, 0);
listbox = addPartitionListbox(table, form, 7, 6, 7, PART_EXT2, NULL, NULL);
newtFormAddComponents(form, text, okay, cancel, NULL);
answer = newtRunForm(form);
if (answer != cancel) {
rootPart = newtListboxGetCurrent(listbox);
}
newtFormDestroy(form);
newtPopWindow();
*rootPartNum = (rootPart - table.parts);
if (!rootPart)
return INST_CANCEL;
else
return 0;
}
static int badMountPoint(enum partitionTypes type, char * item) {
char * chptr = item;
if (*chptr != '/') {
newtWinMessage("Bad Mount Point", "Ok",
"Mount points must begin with a leading /.");
return INST_ERROR;
}
if (*(chptr + 1) && *(chptr + strlen(chptr) - 1) == '/') {
newtWinMessage("Bad Mount Point", "Ok",
"Mount points may not end with a /.");
return INST_ERROR;
}
while (*chptr && isprint(*chptr)) chptr++;
if (*chptr) {
newtWinMessage("Bad Mount Point", "Ok",
"Mount points may only printable characters.");
return INST_ERROR;
}
if (type != PART_EXT2 && (
!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",
"System partitions must be on Linux Native "
"partitions.");
return INST_ERROR;
}
if (type != PART_EXT2 && type != PART_NFS &&
!strncmp(item, "/usr", 4)) {
newtWinMessage("Bad Mount Point", "Ok",
"/usr must be on a Linux Native partition "
"or an NFS volume.");
return INST_ERROR;
}
return 0;
}
static char * restrdup(char * old, char * new) {
if (old) free(old);
if (new) return strdup(new); else return NULL;
}
void nfsMountCallback(newtComponent co, void * arg) {
struct nfsMountCallbackInfo * nfsinfo = arg;
char * chptr;
char * copy;
if (!strlen(nfsinfo->netpathVal)) {
if (strchr(nfsinfo->serverVal, ':')) {
chptr = copy = alloca(strlen(nfsinfo->serverVal) + 1);
strcpy(copy, nfsinfo->serverVal);
chptr = strchr(copy, ':');
*chptr = '\0';
chptr++;
newtEntrySet(nfsinfo->server, copy, 1);
newtEntrySet(nfsinfo->netpath, chptr, 1);
}
}
if (nfsinfo->mntpoint) {
if (strlen(nfsinfo->netpathVal) && !strlen(nfsinfo->mntpointVal)) {
newtEntrySet(nfsinfo->mntpoint, nfsinfo->netpathVal, 1);
}
}
}
int editNetMountPoint(struct fstabEntry * item) {
newtComponent form, server, path, point, okay, cancel, answer;
char * pointValue, * pathValue, * serverValue;
int done = 0;
struct nfsMountCallbackInfo nfsinfo;
newtCenteredWindow(50, 10, "Edit Network Mount Point");
form = newtForm(NULL, NULL, 0);
newtFormAddComponent(form, newtLabel(1, 1, "NFS Server :"));
newtFormAddComponent(form, newtLabel(1, 2, "NFS Path :"));
newtFormAddComponent(form, newtLabel(1, 3, "Mount point :"));
server = newtEntry(17, 1, item->netHost, 20, &serverValue,
NEWT_ENTRY_SCROLL | NEWT_ENTRY_RETURNEXIT);
path = newtEntry(17, 2, item->netPath, 20, &pathValue,
NEWT_ENTRY_SCROLL | NEWT_ENTRY_RETURNEXIT);
point = newtEntry(17, 3, item->mntpoint, 20, &pointValue,
NEWT_ENTRY_SCROLL | NEWT_ENTRY_RETURNEXIT);
nfsinfo.server = server;
nfsinfo.mntpoint = point;
nfsinfo.netpath = path;
nfsinfo.serverVal = serverValue;
nfsinfo.netpathVal = pathValue;
nfsinfo.mntpointVal = pointValue;
newtComponentAddCallback(server, nfsMountCallback, &nfsinfo);
newtComponentAddCallback(path, nfsMountCallback, &nfsinfo);
okay = newtButton(10, 6, "Ok");
cancel = newtButton(30, 6, "Cancel");
newtFormAddComponents(form, server, path, point, okay, cancel, NULL);
do {
answer = newtRunForm(form);
if (answer == cancel) {
done = 1;
} else if (*pointValue) {
if (!badMountPoint(item->type, pointValue))
done = 1;
}
} while (!done);
if (answer != cancel) {
item->mntpoint = restrdup(item->mntpoint, pointValue);
item->netPath = restrdup(item->netPath, pathValue);
item->netHost = restrdup(item->netHost, serverValue);
if (item->device) free(item->device);
item->device = malloc(strlen(pathValue) + strlen(serverValue) + 5);
sprintf(item->device, "%s:%s", serverValue, pathValue);
}
newtPopWindow();
if (answer == cancel)
return INST_CANCEL;
return 0;
}
static void editDeviceMountPoint(struct fstabEntry * item) {
newtComponent form, entry, okay, cancel, clear, answer;
char buf[50];
char * entryValue;
int done = 0;
newtCenteredWindow(50, 10, "Edit Mount Point");
form = newtForm(NULL, NULL, 0);
strcpy(buf,"Device : /dev/");
strcat(buf, item->device);
newtFormAddComponent(form, newtLabel(1, 1, buf));
newtFormAddComponent(form, newtLabel(1, 3, "Mount point :"));
entry = newtEntry(17, 3, item->mntpoint, 20, &entryValue,
NEWT_ENTRY_SCROLL | NEWT_ENTRY_RETURNEXIT);
okay = newtButton(5, 6, "Ok");
clear = newtButton(20, 6, "Clear");
cancel = newtButton(35, 6, "Cancel");
newtFormAddComponents(form, entry, okay, clear, cancel, NULL);
do {
newtFormSetCurrent(form, entry);
answer = newtRunForm(form);
if (answer == clear)
newtEntrySet(entry, "", 1);
else if (answer == cancel || !*entryValue) {
done = 1;
} else if (*entryValue) {
if (!badMountPoint(item->type, entryValue))
done = 1;
}
} while (!done);
if (answer != cancel) {
item->mntpoint = restrdup(item->mntpoint, entryValue);
}
newtPopWindow();
}
void freeFstabEntry( struct fstabEntry *e ) {
if (e->mntpoint) free(e->mntpoint);
if (e->device) free(e->device);
if (e->netPath) free(e->netPath);
if (e->netHost) free(e->netHost);
}
void freeFstab(struct fstab fstab) {
int i;
for (i = 0; i < fstab.numEntries; i++) {
freeFstabEntry( &fstab.entries[i] );
}
if (fstab.numEntries) free(fstab.entries);
}
struct fstab copyFstab(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].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;
}
int setupMountTable(struct partitionTable table, struct fstab * finalFstab,
struct netInterface * intf, struct netConfig * netc,
struct driversLoaded ** dl) {
int rootPartNum = -1;
int rc, hasdups;
newtComponent f, okay, text, listbox, label, cancel, edit, answer;
newtComponent addnfs;
char buf[80];
int i, j, numMountable, numLinux;
int partNum;
struct fstab fstab;
int fstabNum;
struct fstabEntry entry, * curr;
int * fstabEntNum, * numptr;
static int firstTime = 1;
const char * basicFormat = "%-10s %14s %-20s %-18s";
const char * devFormat = "/dev/%-5s %14d %-20s %-18s";
const char * nfsFormat = "%-27s %-20s %-18s";
fstab = copyFstab(finalFstab);
if (firstTime) {
/* First, make them pick a root partition */
if ((rc = selectRootPartition(table, &rootPartNum))) {
freeFstab(fstab);
return rc;
}
firstTime = 0;
for (i = partNum = 0; i < table.count; i++) {
if (i == rootPartNum) {
initFstabEntry(&entry);
entry.device = strdup(table.parts[i].device);
entry.size = table.parts[i].size;
entry.type = table.parts[i].type;
entry.tagName = table.parts[i].tagName;
entry.mntpoint = strdup("/");
addFstabEntry(&fstab, entry);
break;
}
}
freeFstab(*finalFstab);
*finalFstab = copyFstab(&fstab);
}
/* If only one mountable partition exists, it would have been set up
as root above so we can stop here */
numLinux = numMountable = 0;
for (i = partNum = 0; i < table.count; i++) {
if (table.parts[i].type == PART_EXT2)
numMountable++, numLinux++;
else if (table.parts[i].type == PART_DOS ||
table.parts[i].type == PART_HPFS)
numMountable++;
}
if (!numMountable) {
errorWindow("You don't have any mountable partitions!");
return INST_ERROR;
} else if (!numLinux) {
errorWindow("You don't have any Linux partitions available!");
return INST_ERROR;
} else if (numMountable == 1)
return 0;
newtCenteredWindow(75, 19, "Partition Disk");
f = newtForm(NULL, NULL, 0);
text = newtTextbox(1, 1, 72, 4, NEWT_TEXTBOX_WRAP);
newtTextboxSetText(text, "You may now mount other partitions within "
"your filesystem. Many users like to use separate "
"partitions for /usr and /home for example. You may "
"also mount your DOS or OS/2 partitions to make them "
"visible to Linux.");
okay = newtButton(6, 15, "Ok");
addnfs = newtButton(20, 15, "Add NFS");
edit = newtButton(38, 15, "Edit");
cancel = newtButton(54, 15, "Cancel");
sprintf(buf, basicFormat, "Device", "Size", "Partition type",
"Mount point");
label = newtLabel(1, 5, buf);
listbox = newtListbox(1, 6, 8, NEWT_LISTBOX_RETURNEXIT);
fstabEntNum = malloc(table.count * sizeof(*fstabEntNum));
for (i = partNum = 0; i < table.count; i++) {
if (table.parts[i].type == PART_EXT2 ||
table.parts[i].type == PART_DOS ||
table.parts[i].type == PART_HPFS) {
for (j = 0; j < fstab.numEntries; j++)
if (!strcmp(table.parts[i].device, fstab.entries[j].device))
break;
if (j < fstab.numEntries) {
fstabNum = j;
} else {
initFstabEntry(&entry);
entry.device = strdup(table.parts[i].device);
entry.size = table.parts[i].size;
entry.type = table.parts[i].type;
entry.tagName = table.parts[i].tagName;
fstabNum = addFstabEntry(&fstab, entry);
}
sprintf(buf, devFormat, table.parts[i].device,
table.parts[i].size, table.parts[i].tagName,
fstab.entries[fstabNum].mntpoint ?
fstab.entries[fstabNum].mntpoint : "");
fstabEntNum[partNum] = fstabNum;
newtListboxAddEntry(listbox, buf, fstabEntNum + partNum);
partNum++;
}
}
newtFormAddComponents(f, text, label, listbox, okay, addnfs, edit, cancel,
NULL);
do {
answer = newtRunForm(f);
if (answer == listbox || answer == edit) {
numptr = newtListboxGetCurrent(listbox);
curr = fstab.entries + *numptr;
if (curr->type == PART_NFS) {
editNetMountPoint(curr);
sprintf(buf, nfsFormat, curr->device, curr->tagName,
curr->mntpoint);
} else {
editDeviceMountPoint(curr);
sprintf(buf, devFormat, curr->device, curr->size,
curr->tagName, curr->mntpoint ? curr->mntpoint : "");
}
newtListboxSetEntry(listbox, numptr - fstabEntNum, buf);
} else if (answer == addnfs) {
initFstabEntry(&entry);
entry.type = PART_NFS;
entry.tagName = "NFS Mount";
entry.device = NULL;
entry.mntpoint = NULL;
if (!intf->isConfigured) {
rc = bringUpNetworking(intf, netc, dl);
} else {
rc = 0;
}
if (!rc && !editNetMountPoint(&entry)) {
fstabNum = addFstabEntry(&fstab, entry);
fstabEntNum = realloc(fstabEntNum,
sizeof(*fstabEntNum) * fstabNum);
sprintf(buf, nfsFormat, entry.device, entry.tagName,
entry.mntpoint);
newtListboxAddEntry(listbox, buf, fstabEntNum + fstabNum);
/*newtListboxSetCurrent(listbox, fstabNum);*/
}
} else if (answer != cancel) {
answer = okay;
for (i = 0; i < fstab.numEntries; i++)
if (fstab.entries[i].mntpoint &&
!strcmp(fstab.entries[i].mntpoint, "/")) break;
if (i == fstab.numEntries) {
newtWinMessage("No Root Partition", "Ok",
"You must assign a root (/) partition for the "
"install to proceed.");
answer = NULL;
continue;
}
hasdups = 0;
for (i = 0; i < fstab.numEntries; i++)
for (j = i + 1; j < fstab.numEntries; j++)
if (fstab.entries[i].type != PART_SWAP &&
fstab.entries[i].mntpoint &&
fstab.entries[j].mntpoint &&
!strcmp(fstab.entries[i].mntpoint,
fstab.entries[j].mntpoint))
hasdups = 1;
if (hasdups) {
newtWinMessage("Duplicate Mounts", "Ok",
"You may not use the same mount point multiple "
"times.");
answer = NULL;
}
}
} while (answer != okay && answer != cancel);
newtFormDestroy(f);
newtPopWindow();
free(fstabEntNum);
if (answer == cancel) {
freeFstab(fstab);
return INST_CANCEL;
}
freeFstab(*finalFstab);
*finalFstab = copyFstab(&fstab);
freeFstab(fstab);
/* Sort by mount point. This makes mounting everything in the proper
order trivial */
fstabSort(finalFstab);
return 0;
}
static int mkExt2Filesystem(char * dev) {
char * mke2fsargs[] = { "mke2fs", NULL, NULL, NULL};
int rc;
char message[80];
mke2fsargs[1] = alloca(strlen(dev) + 6);
strcpy(mke2fsargs[1], "/tmp/");
strcat(mke2fsargs[1], dev);
if (badBlocks)
mke2fsargs[2] = "-c";
sprintf(message, "Making ext2 filesystem on /dev/%s...", dev);
winStatus(45, 3, "Running", message);
devMakeInode(dev, mke2fsargs[1]);
rc = runProgram(RUN_LOG, "/usr/bin/mke2fs", mke2fsargs);
devRemoveInode(mke2fsargs[1]);
newtPopWindow();
if (rc)
return INST_ERROR;
else
return 0;
}
int queryFormatFilesystems(struct fstab * fstab) {
newtComponent form, checkList, okay, cancel, sb, text, answer;
newtComponent checkbox;
char * states;
char doCheck = ' ';
newtComponent * checks;
char buf[80];
int i, top;
newtCenteredWindow(57, 19, "Format Partitions");
form = newtForm(NULL, NULL, 0);
if (fstab->numEntries > 4)
sb = newtVerticalScrollbar(47, 7, 4, 9, 10);
else
sb = NULL;
checkList = newtForm(sb, NULL, 0);
newtFormSetHeight(checkList, 4);
if (sb)
newtFormAddComponent(checkList, sb);
text = newtTextbox(1, 1, 55, 6, NEWT_TEXTBOX_WRAP);
newtTextboxSetText(text, "What partitions would you like to "
"format? We strongly suggest formatting all of the "
"system partitions, including /, /usr, and /var. There "
"is no need to format /home or /usr/local if they "
"have already been configured during a previous "
"install.");
checks = alloca(sizeof(newtComponent) * fstab->numEntries);
states = alloca(sizeof(char) * fstab->numEntries);
for (i = 0, top = 0; i < fstab->numEntries; i++) {
if (fstab->entries[i].doFormat)
states[i] = '*';
else
states[i] = ' ';
if (fstab->entries[i].type == PART_EXT2) {
sprintf(buf, "/dev/%-5s %-33s", fstab->entries[i].device,
fstab->entries[i].mntpoint);
checks[i] = newtCheckbox(3, 7 + top++, buf, states[i], NULL,
&states[i]);
newtFormAddComponent(checkList, checks[i]);
} else {
checks[i] = NULL;
}
}
okay = newtButton(12, 14, "Ok");
cancel = newtButton(34, 14, "Cancel");
checkbox = newtCheckbox(10, 12, "Check for bad blocks during format",
badBlocks ? '*' : ' ', NULL, &doCheck);
newtFormAddComponents(form, text, checkList, checkbox, okay, cancel, NULL);
answer = newtRunForm(form);
newtFormDestroy(form);
newtPopWindow();
if (answer == cancel) return INST_CANCEL;
for (i = 0; i < fstab->numEntries; i++) {
if (states[i] != ' ')
fstab->entries[i].doFormat = 1;
}
if (doCheck == ' ')
badBlocks = 0;
else
badBlocks = 1;
return 0;
}
int formatFilesystems(struct fstab * fstab) {
int i;
for (i = 0; i < fstab->numEntries; i++) {
if (fstab->entries[i].doFormat)
mkExt2Filesystem(fstab->entries[i].device);
}
return 0;
}
int doMount(char * dev, char * where, char * fs, int rdonly, int istty) {
return doPwMount(dev, where, fs, rdonly, istty, NULL, NULL);
}
int doPwMount(char * dev, char * where, char * fs, int rdonly, int istty,
char * acct, char * pw) {
char * buf = NULL;
int isnfs = 0;
char * mount_opt = NULL;
long int flag;
char * chptr;
if (!strcmp(fs, "nfs")) isnfs = 1;
logMessage("mounting %s on %s as type %s", dev, where, fs);
if (testing) {
newtWinMessage("Test mount", "Ok", "I would mount /dev/%s on %s",
"using a(n) %s filesystem.", dev, where, fs);
} else if (!strcmp(fs, "smb")) {
mkdirChain(where);
if (!acct) acct = "guest";
if (!pw) pw = "";
buf = alloca(strlen(dev) + 1);
strcpy(buf, dev);
chptr = buf;
while (*chptr && *chptr != ':') chptr++;
if (!*chptr) {
logMessage("bad smb mount point %s", where);
return 0;
}
*chptr = '\0';
chptr++;
#ifdef __i386__
logMessage("mounting smb filesystem from %s path %s on %s",
buf, chptr, where);
return smbmount(buf, chptr, acct, pw, "localhost", where);
#else
errorWindow("smbfs only works on Intel machines");
#endif
} else {
mkdirChain(where);
if (!isnfs && *dev == '/') {
buf = dev;
} else if (!isnfs) {
buf = alloca(200);
strcpy(buf, "/tmp/");
strcat(buf, dev);
if (devMakeInode(dev, buf)) return 1;
} else {
char * junk = NULL;
int morejunk = 0;
buf = dev;
logMessage("calling nfsmount(%s, %s, &morejunk, &junk, &mount_opt)",
buf, where);
if (nfsmount(buf, where, &morejunk, &junk, &mount_opt))
logMessage("\tnfsmount returned non-zero");
}
flag = MS_MGC_VAL;
if (rdonly)
flag |= MS_RDONLY;
logMessage("calling mount(%s, %s, %s, %ld, %p)", buf, where, fs,
flag, mount_opt);
if (mount(buf, where, fs, flag, mount_opt)) {
if (istty) {
fprintf(stderr, "mount failed: %s\n", strerror(errno));
} else {
newtWinMessage("Error", "Ok", perrorstr("mount failed"));
}
return 1;
}
if (!isnfs) devRemoveInode(buf);
}
return 0;
}
int mountFilesystems(struct fstab * fstab) {
int i;
char buf[1000];
/* don't bother mounting odd (non-ext2) filesystems - we don't need
them for installs */
/* what about NFS? we should probably mount them to check mount integrity,
but we don't know if networking is working well enough for us to do
this */
chdir("/");
for (i = 0; i < fstab->numEntries; i++) {
strcpy(buf, "/mnt");
strcat(buf, fstab->entries[i].mntpoint);
if (fstab->entries[i].type == PART_EXT2 ||
fstab->entries[i].type == PART_NFS ) {
if (fstab->entries[i].type == PART_EXT2 &&
!doMount(fstab->entries[i].device, buf, "ext2", 0, 0))
fstab->entries[i].isMounted = 1;
else if (fstab->entries[i].type == PART_NFS &&
!doMount(fstab->entries[i].device, buf, "nfs", 0, 0))
fstab->entries[i].isMounted = 1;
else {
logMessage("unmounting all filesystems due to mount error");
umountFilesystems(fstab);
return INST_ERROR;
}
} else {
logMessage("creating directory %s", buf);
mkdirChain(buf);
}
}
return 0;
}
int umountFilesystems(struct fstab * fstab) {
char buf[1000];
int i;
int olderrno;
logMessage("unmounting all filesystems");
chdir("/");
if (testing) return 0;
for (i = fstab->numEntries - 1; i >= 0; i--) {
if (fstab->entries[i].isMounted) {
strcpy(buf, "/mnt");
strcat(buf, fstab->entries[i].mntpoint);
fstab->entries[i].isMounted = 0;
if (umount(buf)) {
olderrno = errno;
logMessage("error unmounting %s: %s\n", buf, strerror(errno));
errno = olderrno;
errorWindow("error unmounting filesystem: %s");
}
}
}
return 0;
}
static int mkdirChain(char * origChain) {
char * chain;
char * chptr;
chain = alloca(strlen(origChain) + 1);
strcpy(chain, origChain);
chptr = chain;
if (testing) return 0;
while ((chptr = strchr(chptr, '/'))) {
*chptr = '\0';
if (mkdirIfNone(chain)) {
*chptr = '/';
return INST_ERROR;
}
*chptr = '/';
chptr++;
}
if (mkdirIfNone(chain))
return INST_ERROR;
return 0;
}
static int mkdirIfNone(char * directory) {
int rc, mkerr;
char * chptr;
/* If the file exists it *better* be a directory -- I'm not going to
actually check or anything */
if (!access(directory, X_OK)) return 0;
/* if the path is '/' we get ENOFILE not found" from mkdir, rather
then EEXIST which is weird */
for (chptr = directory; *chptr; chptr++)
if (*chptr != '/') break;
if (!*chptr) return 0;
rc = mkdir(directory, 0755);
mkerr = errno;
logMessage("creating directory %s rc = %d", directory, rc);
if (!rc || mkerr == EEXIST) return 0;
logMessage(" error: %s", strerror(mkerr));
return INST_ERROR;
}
int writeFstab(struct fstab * fstab) {
int i;
FILE * f;
int fd;
char * fs = NULL;
int freq = 0;
int passno = 0;
int bad;
char buf[4096];
char * chptr, * cddev = NULL;
char * devFormat = "/dev/%-18s %-23s %-7s %-15s %d %d\n";
char * nfsFormat = "%-23s %-23s %-7s %-15s %d %d\n";
char * procFormat = "%-23s %-23s %-7s %-15s %d %d\n";
char * options;
char * format;
logMessage("scanning /proc/mounts for iso9660 filesystems");
fd = open("/proc/mounts", O_RDONLY);
if (fd < 0) {
logMessage("\terror opening /proc/mounts -- skipping check: %s",
strerror(errno));
} else {
i = read(fd, buf, sizeof(buf) - 1);
if (i < 0) {
logMessage("\terror reading /proc/mounts -- skipping check: %s",
strerror(errno));
} else {
buf[i] = 0;
if ((chptr = strstr(buf, "iso9660"))) {
chptr--;
/* skip the mount point */
while (*chptr == ' ') chptr--;
while (*chptr != ' ') chptr--;
while (*chptr == ' ') chptr--;
chptr++;
*chptr = '\0';
while (*chptr != '/') chptr--;
cddev = strdup(chptr + 1);
logMessage("found mounted cdrom drive %s", cddev);
}
}
}
#ifndef __sparc__
if (!cddev) {
if (findAtapi(&cddev)) cddev = NULL;
}
#endif
if (!cddev) {
if (findSCSIcdrom(&cddev)) cddev = NULL;
}
if (testing) {
if (cddev) free(cddev);
return 0;
}
logMessage("touching /etc/mtab");
f = fopen("/mnt/etc/mtab", "w+");
if (!f) {
errorWindow("error touching /mnt/etc/mtab");
} else {
fclose(f);
}
logMessage("creating /etc/fstab");
f = fopen("/mnt/etc/fstab", "w");
if (!f) {
if (cddev) free(cddev);
errorWindow("error creating /mnt/etc/fstab");
return INST_ERROR;
}
for (i = 0; i < fstab->numEntries; i++) {
if (!fstab->entries[i].mntpoint) continue;
passno = 0;
freq = 0;
format = devFormat;
options = "defaults";
bad = 0;
switch (fstab->entries[i].type) {
case PART_EXT2:
freq = 1;
fs = "ext2";
if (!strcmp(fstab->entries[i].mntpoint, "/"))
passno = 1;
else
passno = 2;
break;
case PART_NFS:
fs = "nfs";
options = "ro";
format = nfsFormat;
break;
case PART_SWAP:
fs = "swap";
break;
case PART_DOS:
fs = "msdos";
break;
case PART_HPFS:
fs = "hpfs";
break;
default:
bad = 1;
}
if (!bad)
fprintf(f, format, fstab->entries[i].device,
fstab->entries[i].mntpoint, fs, options, freq, passno);
}
fprintf(f, devFormat, "fd0", "/mnt/floppy", "ext2", "noauto", 0, 0);
if (cddev) {
if (mkdir("/mnt/mnt/cdrom", 0755))
logMessage("failed to mkdir /mnt/mnt/cdrom: %s", strerror(errno));
if (symlink(cddev, "/mnt/dev/cdrom"))
logMessage("failed to symlink /mnt/dev/cdrom: %s", strerror(errno));
fprintf(f, devFormat, "cdrom", "/mnt/cdrom", "iso9660", "noauto,ro",
0, 0);
free(cddev);
}
fprintf(f, procFormat, "none", "/proc", "proc", "defaults", 0, 0);
fclose(f);
return 0;
}
int addFstabEntry(struct fstab * fstab, struct fstabEntry entry) {
int i;
for (i = 0; i < fstab->numEntries; i++)
if (!strcmp(entry.device, fstab->entries[i].device))
break;
if (i == fstab->numEntries) {
fstab->numEntries++;
if (fstab->numEntries > 1)
fstab->entries = realloc(fstab->entries,
sizeof(entry) * fstab->numEntries);
else
fstab->entries = malloc(sizeof(entry));
}
fstab->entries[i] = entry;
return i;
}
int activeSwapSpace(struct partitionTable * table, struct fstab * finalFstab) {
newtComponent form, checkList, okay, cancel, sb, text, answer, label;
newtComponent check, checkbox;
char * states;
char buf[80];
int i, top, j, rc;
struct fstabEntry entry;
struct fstabEntry ** entries;
struct fstab fstab;
static int firstTime = 1;
static int chkBadBlocks = 1;
char doCheck = ' ';
fstab = copyFstab(finalFstab);
form = newtForm(NULL, NULL, 0);
for (i = j = 0; i < table->count; i++)
if (table->parts[i].type == PART_SWAP)
j++;
if (!j) {
rc = newtWinChoice("No Swap Space", "Repartition", "Continue",
"You don't have any swap space defined. Would "
"you like to continue, or repartition your disk?");
if (rc != 1)
return INST_CANCEL;
return 0;
}
if (!kickstart) {
newtCenteredWindow(54, 15, "Active Swap Space");
if (j > 3)
sb = newtVerticalScrollbar(47, 7, 3, 9, 10);
else
sb = NULL;
checkList = newtForm(sb, NULL, 0);
newtFormSetHeight(checkList, 3);
if (sb)
newtFormAddComponent(checkList, sb);
text = newtTextbox(1, 1, 52, 4, NEWT_TEXTBOX_WRAP);
newtTextboxSetText(text, "What partitions would you like to "
"use for swap space? This will destroy any "
"information already on the partition.");
label = newtLabel(4, 5, " Device Begin End Size (k)");
states = alloca(sizeof(char) * table->count);
entries = alloca(sizeof(*entries) * table->count);
for (i = 0, top = 0; i < table->count; i++) {
if (table->parts[i].type != PART_SWAP) continue;
for (j = 0; j < fstab.numEntries; j++)
if (!strcmp(table->parts[i].device, fstab.entries[j].device))
break;
if ((j < fstab.numEntries && fstab.entries[j].mntpoint) ||
(firstTime && !testing))
states[i] = '*';
else
states[i] = ' ';
if (j < fstab.numEntries)
entries[i] = fstab.entries + j;
else
entries[i] = NULL;
sprintf(buf, "/dev/%-5s %9d %9d %9d", table->parts[i].device,
table->parts[i].begin, table->parts[i].end,
table->parts[i].size);
check = newtCheckbox(2, 6 + top++, buf, states[i], NULL,
&states[i]);
newtFormAddComponent(checkList, check);
}
firstTime = 0;
checkbox = newtCheckbox(2, 9, "Check for bad blocks during format",
chkBadBlocks ? '*' : ' ', NULL, &doCheck);
okay = newtButton(9, 11, "Ok");
cancel = newtButton(28, 11, "Cancel");
newtFormAddComponents(form, text, label, checkList, checkbox, okay,
cancel, NULL);
answer = newtRunForm(form);
newtFormDestroy(form);
newtPopWindow();
chkBadBlocks = (doCheck != ' ');
if (answer == cancel) {
freeFstab(fstab);
return INST_CANCEL;
}
}
for (i = 0; i < table->count; i++) {
if (table->parts[i].type != PART_SWAP) continue;
if (kickstart || states[i] != ' ') {
if (!kickstart && entries[i])
entries[i]->mntpoint = strdup("swap");
else {
initFstabEntry(&entry);
entry.device = strdup(table->parts[i].device);
entry.size = table->parts[i].size;
entry.type = table->parts[i].type;
entry.tagName = table->parts[i].tagName;
entry.mntpoint = strdup("swap");
addFstabEntry(&fstab, entry);
}
} else if (entries[i]) {
free(entries[i]->mntpoint);
entries[i]->mntpoint = NULL;
}
}
if (canEnableSwap) {
for (i = 0; i < fstab.numEntries; i++) {
if (fstab.entries[i].type == PART_SWAP &&
fstab.entries[i].mntpoint) {
enableswap(fstab.entries[i].device, 0, chkBadBlocks);
canEnableSwap = 0;
}
}
}
freeFstab(*finalFstab);
*finalFstab = copyFstab(&fstab);
freeFstab(fstab);
return 0;
}