#include <alloca.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "isys/isys.h"
#include "loader.h"
#include "log.h"
#include "modules.h"
struct moduleDependency_s {
char * name;
char ** deps;
};
int mlReadLoadedList(moduleList * mlp) {
int fd;
char * start;
char * end;
char buf[4096];
struct stat sb;
int i;
moduleList ml;
if ((fd = open("/proc/modules", O_RDONLY)) < 0)
return -1;
fstat(fd, &sb);
i = read(fd, buf, sizeof(buf));
buf[i] = '\0';
close(fd);
ml = malloc(sizeof(*ml));
ml->numModules = 0;
start = buf;
while (start && *start) {
end = start;
while (!isspace(*end) && *end != '\n') end++;
*end = '\0';
ml->mods[ml->numModules].name = strdup(start);
ml->mods[ml->numModules].args = NULL;
ml->mods[ml->numModules].weLoaded = 0;
*end = ' ';
ml->numModules++;
start = strchr(end, '\n');
if (start) start++;
}
*mlp = ml;
return 0;
}
void mlFreeList(moduleList ml) {
int i;
int j;
for (i = 0; i < ml->numModules; i++) {
free(ml->mods[i].name);
if (ml->mods[i].args) {
for (j = 0; ml->mods[j].args[j]; j++)
free(ml->mods[i].args[j]);
free(ml->mods[i].args);
}
}
free(ml);
}
moduleDeps mlNewDeps(void) {
moduleDeps md;
md = malloc(sizeof(*md));
md->name = NULL;
md->deps = NULL;
return md;
}
int mlLoadDeps(moduleDeps * moduleDepListPtr, const char * path) {
int fd;
char * buf;
struct stat sb;
char * start, * end, * chptr;
int i, numItems;
moduleDeps nextDep;
moduleDeps moduleDepList = *moduleDepListPtr;
fd = open(path, O_RDONLY);
if (fd < 0) {
return -1;
}
fstat(fd, &sb);
buf = alloca(sb.st_size + 1);
read(fd, buf, sb.st_size);
buf[sb.st_size] = '\0';
close(fd);
start = buf;
numItems = 0;
while (start) {
numItems++;
start = strchr(start + 1, '\n');
}
for (nextDep = moduleDepList; nextDep->name; nextDep++) numItems++;
moduleDepList = realloc(moduleDepList, sizeof(*moduleDepList) * numItems);
for (nextDep = moduleDepList; nextDep->name; nextDep++) ;
start = buf;
while (start < (buf + sb.st_size) && *start) {
end = strchr(start, '\n');
*end = '\0';
chptr = strchr(start, ':');
if (!chptr) {
start = end + 1;
continue;
}
*chptr++ = '\0';
while (*chptr && isspace(*chptr)) chptr++;
if (!*chptr) {
start = end + 1;
continue;
}
/* found something */
nextDep->name = strdup(start);
nextDep->deps = malloc(sizeof(char *) * (strlen(chptr) + 1));
start = chptr, i = 0;
while (start && *start) {
chptr = strchr(start, ' ');
if (chptr) *chptr = '\0';
nextDep->deps[i++] = strdup(start);
if (chptr)
start = chptr + 1;
else
start = NULL;
while (start && *start && isspace(*start)) start++;
}
nextDep->deps[i] = NULL;
nextDep->deps = realloc(nextDep->deps, sizeof(char *) * (i + 1));
nextDep++;
start = end + 1;
}
nextDep->name = NULL;
nextDep->deps = NULL;
moduleDepList = realloc(moduleDepList, sizeof(*moduleDepList) *
(nextDep - moduleDepList + 1));
*moduleDepListPtr = moduleDepList;
return 0;
}
int mlLoadModule(char * modName, char * path, moduleList modLoaded,
moduleDeps modDeps, char ** args, int flags) {
moduleDeps dep;
char ** nextDep, ** argPtr;
char fileName[200];
int rc, i;
char ** arg, ** newArgs;
if (mlModuleInList(modName, modLoaded)) {
return 0;
}
for (dep = modDeps; dep->name && strcmp(dep->name, modName);
dep++);
if (dep && dep->deps) {
nextDep = dep->deps;
while (*nextDep) {
mlLoadModule(*nextDep, NULL, modLoaded, modDeps, NULL, flags);
nextDep++;
}
}
sprintf(fileName, "%s.o", modName);
for (argPtr = args; argPtr && *argPtr; argPtr++) {
strcat(fileName, " ");
strcat(fileName, *argPtr);
}
sprintf(fileName, "%s.o", modName);
if (FL_TESTING(flags)) {
logMessage("would have insmod %s", fileName);
rc = 0;
} else {
logMessage("going to insmod %s (path is %s)", fileName,
path ? path : "NULL");
rc = insmod(fileName, path, args);
}
if (!rc) {
modLoaded->mods[modLoaded->numModules].name = strdup(modName);
modLoaded->mods[modLoaded->numModules].weLoaded = 1;
modLoaded->mods[modLoaded->numModules].path = path;
if (args) {
for (i = 0, arg = args; *arg; arg++, i++);
newArgs = malloc(sizeof(*newArgs) * (i + 1));
for (i = 0, arg = args; *arg; arg++, i++)
newArgs[i] = strdup(*arg);
newArgs[i] = NULL;
} else {
newArgs = NULL;
}
modLoaded->mods[modLoaded->numModules++].args = newArgs;
}
return rc;
}
char ** mlGetDeps(moduleDeps modDeps, const char * modName) {
moduleDeps dep;
for (dep = modDeps; dep->name && strcmp(dep->name, modName); dep++);
if (dep) return dep->deps;
return NULL;
}
int mlModuleInList(const char * modName, moduleList list) {
int i;
if (!list) return 0;
for (i = 0; i < list->numModules; i++)
if (!strcmp(list->mods[i].name, modName)) return 1;
return 0;
}
int mlWriteConfModules(moduleList list, moduleInfoSet modInfo, int fd) {
int i;
struct loadedModuleInfo * lm;
char buf[200], buf2[200];
struct moduleInfo * mi;
int scsiNum = 0;
int ethNum = 0;
char ** arg;
if (!list) return 0;
for (i = 0, lm = list->mods; i < list->numModules; i++, lm++) {
if (!lm->weLoaded) continue;
if ((mi = isysFindModuleInfo(modInfo, lm->name))) {
strcpy(buf, "alias ");
switch (mi->major) {
case DRIVER_SCSI:
if (scsiNum)
sprintf(buf2, "scsi_hostadapter%d ", scsiNum);
else
strcpy(buf2, "scsi_hostadapter ");
scsiNum++;
strcat(buf, buf2);
break;
case DRIVER_NET:
switch (mi->minor) {
case DRIVER_MINOR_ETHERNET:
sprintf(buf2, "eth%d ", ethNum++);
strcat(buf, buf2);
break;
case DRIVER_MINOR_TR:
strcat(buf, "tr ");
break;
default:
}
default:
}
strcat(buf, lm->name);
strcat(buf, "\n");
write(fd, buf, strlen(buf));
}
if (lm->args) {
strcpy(buf, "options ");
strcat(buf, lm->name);
for (arg = lm->args; *arg; arg++) {
strcat(buf, " ");
strcat(buf, *arg);
}
strcat(buf, "\n");
write(fd, buf, strlen(buf));
}
}
return 0;
}