📄 modules.c
字号:
/* * modules.c - module loading functionality * * Erik Troan <ewt@redhat.com> * Matt Wilson <msw@redhat.com> * Michael Fulbright <msf@redhat.com> * Jeremy Katz <katzj@redhat.com> * * Copyright 1999 - 2003 Red Hat, Inc. * * This software may be freely redistributed under the terms of the GNU * General 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 <ctype.h>#include <errno.h>#include <fcntl.h>#include <kudzu/kudzu.h>#include <newt.h>#include <popt.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <sys/stat.h>#include <sys/types.h>#include <sys/utsname.h>#include <sys/wait.h>#include <unistd.h>#include "loader.h"#include "log.h"#include "modules.h"#include "modstubs.h"#include "windows.h"#include "usb.h"#include "../isys/cpio.h"/* boot flags */extern int flags;static int writeModulesConf(moduleList list, char *conf);static struct extractedModule * extractModules (char * const * modNames, struct extractedModule * oldPaths, struct moduleBallLocation * location);/* pass in the type of device (eth or tr) that you're looking for */static int ethCount(const char * type) { int fd; char buf[16384]; int i; char * chptr; int count = 0; fd = open("/proc/net/dev", O_RDONLY); i = read(fd, buf, sizeof(buf) - 1); buf[i] = '\0'; /* skip first two header lines */ chptr = strchr(buf, '\n') + 1; chptr = strchr(chptr, '\n') + 1; while (chptr) { while (*chptr && isspace(*chptr)) chptr++; if (!strncmp(chptr, type, strlen(type))) count++; chptr = strchr(chptr, '\n'); if (chptr) chptr++; } return count;}static int scsiCount(char *conf) { FILE *f; int count = 0; f = fopen(conf, "r"); if (!f) return 0; do { char *buf = NULL; size_t n = 0; if (getline(&buf, &n, f) < 0) break; if (!strncmp(buf, "alias scsi_hostadapter", 22)) count++; free(buf); } while (1); fclose(f); return count;}static int scsiDiskCount(void) { struct device ** devices; int i = 0; devices = probeDevices(CLASS_HD, BUS_SCSI, PROBE_LOADED); if (devices) { for (; devices[i]; i++); free(devices); } /* have to probe for usb floppies too */ devices = probeDevices(CLASS_FLOPPY, BUS_SCSI, PROBE_LOADED); if (devices) { for (; devices[i]; i++); free(devices); } /* have to probe for usb cdrom too */ devices = probeDevices(CLASS_CDROM, BUS_SCSI, PROBE_LOADED); if (devices) { for (; devices[i]; i++); free(devices); } return i;}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].path = NULL; ml->mods[ml->numModules].weLoaded = 0; *end = ' '; ml->numModules++; start = strchr(end, '\n'); if (start) start++; } *mlp = ml; return 0;}/* this leaks memory if their is a loop in the modules. oh well. */char ** tsortModules(moduleList modLoaded, moduleDeps ml, char ** args, int depth, char *** listPtr, int * listSizePtr) { int listSize; char ** list; char ** next; char ** deps; if (!depth) { int count; listSize = 5; list = malloc((listSize + 1) * sizeof(*list)); *list = NULL; listPtr = &list; listSizePtr = &listSize; for (deps = args, count = 0; *deps; deps++, count++); } else { list = *listPtr; listSize = *listSizePtr; } if (depth++ > 100) { return NULL; } while (*args) { /* don't load it twice */ next = list; while (*next && strcmp(*next, *args)) next++; if (*next || mlModuleInList(*args, modLoaded)) { args++; continue; } /* load everything this depends on */ deps = mlGetDeps(ml, *args); if (deps) { if (!tsortModules(modLoaded, ml, deps, depth, listPtr, listSizePtr)) return NULL; list = *listPtr; listSize = *listSizePtr; } /* add this to the list */ next = list; while (*next) next++; if ((next - list) >= listSize) { int count = next - list; listSize += 10; /* leave room for a NULL */ list = realloc(list, sizeof(*list) * (listSize + 1)); *listSizePtr = listSize; *listPtr = list; next = list + count; } next[0] = *args; next[1] = NULL; args++; } return list;}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;}static struct loadedModuleInfo * getLoadedModuleInfo(moduleList modLoaded, const char * modName) { int i = 0; for (i = 0; i < modLoaded->numModules; i++) if (!strcmp(modLoaded->mods[i].name, modName)) return &modLoaded->mods[i]; return NULL;}/* load a single module. this is the real workhorse of loading modules */static int loadModule(const char * modName, struct extractedModule * path, moduleList modLoaded, char ** args, moduleInfoSet modInfo) { char fileName[300]; char ** argPtr, ** newArgs, ** arg; struct moduleInfo * mi = NULL; int deviceCount = -1; int popWindow = 0; int rc, child, i, status; static int usbWasLoaded = 0; /* don't need to load a module that's already loaded */ if (mlModuleInList(modName, modLoaded)) return 0; if (modInfo && (mi = findModuleInfo(modInfo, modName))) { if ((mi->major == DRIVER_NET) && (mi->minor == DRIVER_MINOR_ETHERNET)) { deviceCount = ethCount("eth"); } else if ((mi->major == DRIVER_NET) && (mi->minor == DRIVER_MINOR_TR)) { deviceCount = ethCount("tr"); } if (mi->major == DRIVER_SCSI) { deviceCount = scsiDiskCount(); if (!FL_CMDLINE(flags)) { startNewt(); scsiWindow(modName); popWindow = 1; } } } if (!strcmp(modName, "libata") && FL_IGNOREHPA(flags)) { logMessage(INFO, "Ignoring host protected area"); args = malloc(sizeof(*args) * 2); args[0] = strdup("ignore_hpa=1"); args[1] = NULL; } sprintf(fileName, "%s.ko", modName); for (argPtr = args; argPtr && *argPtr; argPtr++) { strcat(fileName, " "); strcat(fileName, *argPtr); } if (FL_TESTING(flags)) { logMessage(INFO, "would have insmod %s (%s)", path->path, fileName); rc = 0; } else { if (!(child = fork())) { int fd = open("/dev/tty3", O_RDWR); dup2(fd, 0); dup2(fd, 1); dup2(fd, 2); close(fd); rc = insmod(path->path, NULL, args); _exit(rc); } waitpid(child, &status, 0); if (!WIFEXITED(status) || (WIFEXITED(status) && WEXITSTATUS(status))) { rc = 1; } else { rc = 0; } } if (!rc) { int num = modLoaded->numModules; modLoaded->mods[num].name = strdup(modName); modLoaded->mods[num].weLoaded = 1; modLoaded->mods[num].path = path->location ? strdup(path->location) : NULL; modLoaded->mods[num].firstDevNum = -1; modLoaded->mods[num].lastDevNum = -1; modLoaded->mods[num].written = 0; if (mi) { modLoaded->mods[num].major = mi->major; modLoaded->mods[num].minor = mi->minor; if (deviceCount >= 0) { if ((mi->major == DRIVER_NET) && (mi->minor == DRIVER_MINOR_ETHERNET)) { modLoaded->mods[num].firstDevNum = deviceCount; modLoaded->mods[num].lastDevNum = ethCount("eth") - 1; } else if ((mi->major == DRIVER_NET) && (mi->minor == DRIVER_MINOR_TR)) { modLoaded->mods[num].firstDevNum = deviceCount; modLoaded->mods[num].lastDevNum = ethCount("tr") - 1; } else if (mi->major == DRIVER_SCSI) { /* FIXME: this is a hack, but usb-storage seems to * like to take forever to enumerate. try to * give it some time */ if (!strcmp(modName, "usb-storage") && !usbWasLoaded) { int slp; usbWasLoaded = 1; for (slp = 0; slp < 10; slp++) { if (scsiDiskCount() > deviceCount) break; sleep(2); } logMessage(DEBUGLVL, "slept %d seconds", slp * 2);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -