/* * moduleinfo.c - module info functionality * * Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Author(s): Erik Troan * Matt Wilson */ #include #include #include #include #include #include #include #include #include "moduleinfo.h" struct moduleInfo * getModuleList(moduleInfoSet mis, enum driverMajor major) { struct moduleInfo * miList, * next; int i; next = miList = malloc(sizeof(*miList) * mis->numModules + 1); for (i = 0; i < mis->numModules; i++) { if (mis->moduleList[i].major == major || major == DRIVER_NONE) { *next = mis->moduleList[i]; next++; } } if (next == miList) { free(next); return NULL; } next->moduleName = NULL; next++; miList = realloc(miList, sizeof(*miList) * (next - miList)); return miList; } struct moduleInfo * findModuleInfo(moduleInfoSet mis, const char * moduleName) { int i; struct moduleInfo * found = NULL; for (i = 0; i < mis->numModules; i++) { if (!strcmp(moduleName, mis->moduleList[i].moduleName)) { if (!found) found = mis->moduleList + i; else if (found->locationID && !mis->moduleList[i].locationID) ; else found = mis->moduleList + i; } } return found; } moduleInfoSet newModuleInfoSet(void) { return calloc(sizeof(struct moduleInfoSet_s), 1); } /* filename: file to read module-info from * mis: moduleInfoSet * location: moduleBallLocation struct describing the location of * these modules. (may be NULL) * override: 1 if modules from this module ball should override old ones * of the same name. */ int readModuleInfo(const char * filename, moduleInfoSet mis, void * location, int override) { int fd, isIndented; char * buf, * start, * next = NULL, * chptr; struct stat sb; struct moduleInfo * nextModule; int modulesAlloced; int i; int found = 0, skipModule = 0; fd = open(filename, O_RDONLY); if (fd < 0) return -1; fstat(fd, &sb); buf = alloca(sb.st_size + 1); i = read(fd, buf, sb.st_size); buf[sb.st_size] = '\0'; close(fd); if (i != sb.st_size) return -1; nextModule = NULL; modulesAlloced = mis->numModules; if (strncmp(buf, "Version 0\n", 10)) return -1; start = buf + 10; while (start && *start) { chptr = strchr(start, '\n'); if (chptr) { /* slice and dice */ next = chptr + 1; } else { chptr += strlen(start) - 1; } chptr--; while (isspace(*chptr)) chptr--; chptr++; *chptr = '\0'; isIndented = 0; if (isspace(*start)) { while (isspace(*start) && *start != '\n') start++; isIndented = 1; } if (*start != '\n' && *start && *start != '#') { if (!isIndented) { if (nextModule && nextModule->moduleName && nextModule == (mis->moduleList + mis->numModules)) { mis->numModules++; } if (mis->numModules == modulesAlloced) { modulesAlloced += 5; mis->moduleList = realloc(mis->moduleList, modulesAlloced * sizeof(*mis->moduleList)); } nextModule = NULL; found = 0; skipModule = 0; for (i = 0; i < mis->numModules; i++) { if (!strcmp(mis->moduleList[i].moduleName, start)) { if (override) nextModule = mis->moduleList + i; else skipModule = 1; found = 1; break; } } if (!found && !nextModule) { nextModule = mis->moduleList + mis->numModules; nextModule->moduleName = strdup(start); } if (nextModule) { nextModule->major = DRIVER_NONE; nextModule->minor = DRIVER_MINOR_NONE; nextModule->description = NULL; nextModule->flags = 0; nextModule->args = NULL; nextModule->numArgs = 0; nextModule->locationID = location; } } else if (!nextModule && skipModule) { /* we're skipping this one (not overriding), do nothing */ } else if (!nextModule && skipModule) { /* ACK! syntax error */ fprintf(stderr, "module-info syntax error in %s\n", filename); return 1; } else if (nextModule->major == DRIVER_NONE) { chptr = start + strlen(start) - 1; while (!isspace(*chptr) && chptr > start) chptr--; if (chptr != start) chptr++; if (!strcmp(chptr, "eth")) { nextModule->major = DRIVER_NET; nextModule->minor = DRIVER_MINOR_ETHERNET; } else if (!strcmp(chptr, "tr")) { nextModule->major = DRIVER_NET; nextModule->minor = DRIVER_MINOR_TR; } else if (!strcmp(chptr, "scsi_hostadapter") || !strcmp(chptr, "scsi")) { nextModule->major = DRIVER_SCSI; } else if (!strcmp(chptr, "pcmcia")) { nextModule->major = DRIVER_PCMCIA; } else if (!strcmp(chptr, "fs")) { nextModule->major = DRIVER_FS; } else if (!strcmp(chptr, "cdrom")) { nextModule->major = DRIVER_CDROM; } else if (!strcmp(chptr, "ide")) { nextModule->major = DRIVER_IDE; } else { nextModule->major = DRIVER_OTHER; } } else if (!nextModule->description) { chptr = start + strlen(start) - 1; if (*start == '"' && *chptr == '"') { start++; *chptr = '\0'; nextModule->description = strdup(start); } } else { nextModule->args = realloc(nextModule->args, sizeof(*nextModule->args) * (nextModule->numArgs + 1)); chptr = start; while (!isspace(*chptr) && *chptr) chptr++; if (*chptr) { *chptr = '\0'; nextModule->args[nextModule->numArgs].arg = strdup(start); start = chptr + 1; while (*start && isspace(*start)) start++; if (*start == '"') { start++; chptr = strchr(start, '"'); if (chptr) { *chptr = '\0'; nextModule->args[nextModule->numArgs].description = strdup(start); nextModule->numArgs++; } } } } } start = next; } /* do we need to add in this last module? */ if (nextModule && ((nextModule - mis->moduleList) == mis->numModules)) mis->numModules++; return 0; } void freeModuleInfoSet(moduleInfoSet mis) { int i, j; for (i = 0; i < mis->numModules; i++) { if (mis->moduleList[i].moduleName) free(mis->moduleList[i].moduleName); if (mis->moduleList[i].description) free(mis->moduleList[i].description); for (j = 0; i < mis->moduleList[i].numArgs; j++) { if (mis->moduleList[i].args[j].arg) free(mis->moduleList[i].args[j].arg) ; if (mis->moduleList[i].args[j].description) free(mis->moduleList[i].args[j].description) ; } } free(mis); }