Use glib's data structures and string functions in modules.c since we already have glib. Add in some safety checks as well. --- loader/kickstart.c | 3 +- loader/loader.c | 6 +- loader/loader.h | 2 +- loader/modules.c | 497 +++++++++++++++++++++++++--------------------------- loader/modules.h | 25 ++- 5 files changed, 267 insertions(+), 266 deletions(-) diff --git a/loader/kickstart.c b/loader/kickstart.c index b92c6da..764df5d 100644 --- a/loader/kickstart.c +++ b/loader/kickstart.c @@ -39,6 +39,7 @@ #include "lang.h" #include "log.h" #include "kickstart.h" +#include "modules.h" #include "kbd.h" #include "driverdisk.h" @@ -86,8 +87,6 @@ static void setMediaCheck(struct loaderData_s * loaderData, int argc, char ** argv); static void setUpdates(struct loaderData_s * loaderData, int argc, char ** argv); -void loadKickstartModule(struct loaderData_s * loaderData, int argc, - char ** argv); struct ksCommandNames ksTable[] = { { KS_CMD_NFS, "nfs", setKickstartNfs }, diff --git a/loader/loader.c b/loader/loader.c index dea600f..0ea57cb 100644 --- a/loader/loader.c +++ b/loader/loader.c @@ -1987,7 +1987,11 @@ int main(int argc, char ** argv) { * FIXME: this syntax is likely to change in a future release * but is done as a quick hack for the present. */ - mlInitModuleConfig(); + if (!mlInitModuleConfig()) { + logMessage(ERROR, "unable to initialize kernel module loading"); + abort(); + } + earlyModuleLoad(0); busProbe(FL_NOPROBE(flags)); diff --git a/loader/loader.h b/loader/loader.h index f942b7e..ffb4087 100644 --- a/loader/loader.h +++ b/loader/loader.h @@ -115,7 +115,7 @@ char * getProductName(void); char * getProductPath(void); char * getProductArch(void); -#include "modules.h" +#include "moduleinfo.h" #include "../isys/devices.h" /* JKFIXME: I don't like all of the _set attribs, but without them, * we can't tell if it was explicitly set by kickstart/cmdline or diff --git a/loader/modules.c b/loader/modules.c index fbdd0c9..4577244 100644 --- a/loader/modules.c +++ b/loader/modules.c @@ -1,7 +1,8 @@ /* * modules.c - module loading functionality * - * Copyright (C) 1999, 2000, 2001, 2002, 2003 Red Hat, Inc. + * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, + * 2008, 2009 Red Hat, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify @@ -21,6 +22,7 @@ * Matt Wilson <msw@xxxxxxxxxx> * Michael Fulbright <msf@xxxxxxxxxx> * Jeremy Katz <katzj@xxxxxxxxxx> + * David Cantrell <dcantrell@xxxxxxxxxx> */ #include <ctype.h> @@ -37,339 +39,342 @@ #include <sys/utsname.h> #include <sys/wait.h> #include <unistd.h> +#include <glib.h> #include "loader.h" #include "log.h" #include "modules.h" #include "windows.h" -#include "../isys/cpio.h" - /* boot flags */ extern uint64_t flags; -static int writeModulesConf(char *conf); -struct moduleOptions { - char *name; - int numopts; - char **options; -}; +static GSList *modopts = NULL; +static GSList *blacklist = NULL; -static struct moduleOptions * modopts = NULL; -static int nummodopts = -1; +static gboolean _isValidModule(gchar *module) { + gint fd = -1, i = 0; + gchar *path = NULL, *buf = NULL, *modname = NULL; + gchar *ends[] = { ".ko.gz:", ".ko:", NULL }; + struct utsname utsbuf; + struct stat sbuf; -static char ** blacklists = NULL; -static int numblacklists = 0; + if (uname(&utsbuf) == -1) { + logMessage(ERROR, "%s (%d): %m", __func__, __LINE__); + return FALSE; + } -static void readBlacklist() { - int fd; - size_t len = 0; - char buf[1024]; - char *start, *end; + if (asprintf(&path, "/lib/modules/%s/modules.dep", utsbuf.release) == -1) { + logMessage(ERROR, "%s (%d): %m", __func__, __LINE__); + return FALSE; + } - if ((fd = open("/proc/cmdline", O_RDONLY)) < 0) - return; + if (stat(path, &sbuf) == -1) { + logMessage(ERROR, "%s (%d): %m", __func__, __LINE__); + free(path); + return FALSE; + } + + if ((fd = open(path, O_RDONLY)) == -1) { + logMessage(ERROR, "%s (%d): %m", __func__, __LINE__); + free(path); + return FALSE; + } else { + free(path); + } + + buf = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, fd, 0); + if (!buf || buf == MAP_FAILED) { + close(fd); + return FALSE; + } - len = read(fd, buf, sizeof(buf) - 1); close(fd); - buf[len] = '\0'; - start = buf; - - while (start) { - end = strstr(start, " "); - if (end) - *end = '\0'; - if (strncmp(start,"blacklist=",10)) { - if (!end) - break; - start = end + 1; - continue; + + while (ends[i] != NULL) { + if (asprintf(&modname, "/%s%s", module, ends[i]) == -1) { + logMessage(ERROR, "%s (%d): %m", __func__, __LINE__); + return FALSE; } - printf("found %s\n",start); - blacklists = realloc(blacklists, sizeof(*blacklists) * (numblacklists + 1)); - blacklists[numblacklists] = strdup(start+10); - numblacklists++; + if (g_strstr_len(buf, -1, modname) != NULL) { + munmap(buf, sbuf.st_size); + free(modname); + return TRUE; + } - if (!end) - break; - start = end + 1; + free(modname); + modname = NULL; + i++; } -} -void mlAddBlacklist(char *module) { - blacklists = realloc(blacklists, sizeof(*blacklists) * (numblacklists + 1)); - blacklists[numblacklists] = strdup(module); - numblacklists++; - writeModulesConf("/etc/modprobe.d/anaconda.conf"); + munmap(buf, sbuf.st_size); + return FALSE; } -static void addOption(const char *module, const char *option) { - int found = 0, i, sz; +static void _addOption(const gchar *module, const gchar *option) { + gboolean found = FALSE; + GSList *iterator = modopts; + module_t *modopt = NULL; + gchar *tmpopt = g_strdup(option); - found = 0; - for (i = 0; i < nummodopts; i++) { - if (strncmp(modopts[i].name, module, strlen(modopts[i].name))) - continue; - modopts[i].numopts++; - found = 1; - break; - } - - if (found) { - modopts[i].options = realloc(modopts[i].options, - sizeof(modopts[i].options) * - (modopts[i].numopts + 1)); - if (modopts[i].options == NULL) { - logMessage(ERROR, "%s (%d): %m", __func__, __LINE__); - abort(); - } + while (iterator != NULL) { + modopt = (module_t *) iterator->data; - modopts[i].options[modopts[i].numopts - 1] = strdup(option); - modopts[i].options[modopts[i].numopts] = NULL; - } else { - if (modopts == NULL) { - modopts = malloc(sizeof(struct moduleOptions) * (nummodopts + 1)); - } else { - modopts = realloc(modopts, sizeof(*modopts) * (nummodopts + 1)); - } - - if (modopts == NULL) { - logMessage(ERROR, "%s (%d): %m", __func__, __LINE__); - abort(); + if (!strncmp(modopt->name, module, strlen(modopt->name))) { + found = TRUE; + break; } - modopts[nummodopts].name = strdup(module); - modopts[nummodopts].numopts = 1; + iterator = g_slist_next(iterator); + } - sz = sizeof(modopts[nummodopts].options) * 2; - if ((modopts[nummodopts].options = malloc(sz)) == NULL) { + if (found) { + modopt->options = g_slist_append(modopt->options, tmpopt); + } else { + if ((modopt = g_malloc0(sizeof(module_t))) == NULL) { logMessage(ERROR, "%s (%d): %m", __func__, __LINE__); abort(); } - modopts[nummodopts].options[0] = strdup(option); - modopts[nummodopts].options[1] = NULL; - - nummodopts++; + modopt->name = g_strdup(module); + modopt->options = NULL; + modopt->options = g_slist_append(modopt->options, tmpopt); + modopts = g_slist_append(modopts, modopt); } return; } -static int isValidModule(char *module) { - char mod_name[64], path[512]; - struct utsname utsbuf; - struct stat sbuf; - char *buf; - - uname(&utsbuf); - snprintf(path, 512, "/lib/modules/%s/modules.dep", utsbuf.release); - if (!stat(path, &sbuf)) { - int fd; - - fd = open(path, O_RDONLY); - buf = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, fd, 0); - if (!buf || buf == MAP_FAILED) - return 0; - close(fd); - snprintf(mod_name, 64, "/%s.ko.gz:", module); - if (strstr(buf, mod_name)) { - munmap(buf, sbuf.st_size); - return 1; - } - snprintf(mod_name, 64, "/%s.ko:", module); - if (strstr(buf, mod_name)) { - munmap(buf, sbuf.st_size); - return 1; - } - munmap(buf, sbuf.st_size); +static gboolean _writeModulesConf(gchar *conf) { + gint fd = -1, rc = 0, len = 0; + GSList *iterator = modopts; + GString *buf = g_string_new("# Module options and blacklists written by anaconda\n"); + + if (conf == NULL) { + /* XXX: should this use mkstemp() ? */ + conf = "/tmp/modprobe.conf"; } - return 0; -} -/* read module options out of /proc/cmdline and into a structure */ -static void readModuleOpts() { - int fd; - size_t len = 0; - char buf[1024]; - char *start, *end, *sep; + if ((fd = open(conf, O_WRONLY | O_CREAT, 0644)) == -1) { + logMessage(ERROR, "error opening to %s: %m", conf); + return FALSE; + } - nummodopts = 0; - if ((fd = open("/proc/cmdline", O_RDONLY)) < 0) - return; + while (iterator != NULL) { + module_t *modopt = iterator->data; + GSList *optiterator = modopt->options; + g_string_append_printf(buf, "options %s", modopt->name); - len = read(fd, buf, sizeof(buf) - 1); - close(fd); - buf[len] = '\0'; - start = buf; - - while (start) { - end = strstr(start, " "); - if (end) - *end = '\0'; - sep = strstr(start, "="); - if (sep == NULL) { - if (!end) - break; - start = end + 1; - continue; + while (optiterator != NULL) { + gchar *option = (gchar *) optiterator->data; + g_string_append_printf(buf, " %s", option); + optiterator = g_slist_next(optiterator); } - sep = strstr(start, "."); - if (sep == NULL) { - if (!end) - break; - start = end + 1; - continue; - } - *sep = '\0'; sep++; - if (isValidModule(start)) - addOption(start, sep); + g_string_append(buf, "\n"); + iterator = g_slist_next(iterator); + } + + iterator = blacklist; - if (!end) - break; - start = end + 1; + while (iterator != NULL) { + gchar *module = (gchar *) iterator->data; + g_string_append_printf(buf, "blacklist %s\n", module); + iterator = g_slist_next(iterator); } + + len = buf->len; + rc = write(fd, buf->str, len); + close(fd); + g_string_free(buf, TRUE); + + return (rc == len); } -static int doLoadModule(const char *module, char ** args) { - int child; - int status; +static gboolean _doLoadModule(const gchar *module, gchar **args) { + gint child; + gint status; if (!(child = fork())) { - int i, rc; - char **argv = malloc(3 * sizeof(*argv)); - int fd = open("/dev/tty3", O_RDWR); + gint i, rc; + gchar **argv = NULL; + gint fd = -1; - dup2(fd, 0); - dup2(fd, 1); - dup2(fd, 2); - close(fd); + if ((argv = g_malloc0(3 * sizeof(*argv))) == NULL) { + logMessage(ERROR, "%s (%d): %m", __func__, __LINE__); + abort(); + } + + if ((fd = open("/dev/tty3", O_RDWR)) == -1) { + logMessage(ERROR, "%s (%d): %m", __func__, __LINE__); + } else { + dup2(fd, 0); + dup2(fd, 1); + dup2(fd, 2); + close(fd); + } argv[0] = "/sbin/modprobe"; - argv[1] = strdup(module); + argv[1] = g_strdup(module); argv[2] = NULL; + if (args) { for (i = 0; args[i] ; i++) { - addOption(module, args[i]); + _addOption(module, args[i]); } - writeModulesConf("/etc/modprobe.d/anaconda.conf"); + _writeModulesConf(MODULES_CONF); } + rc = execv("/sbin/modprobe", argv); + g_strfreev(argv); _exit(rc); } waitpid(child, &status, 0); if (!WIFEXITED(status) || (WIFEXITED(status) && WEXITSTATUS(status))) { - return 1; + return TRUE; } else { - return 0; + return FALSE; } } -void mlRemoveBlacklist(char *module) { - int i; +gboolean mlInitModuleConfig(void) { + gint fd; + size_t len = 0; + gchar buf[1024]; + gchar **options = NULL, **optiter = NULL; + + /* read module options out of /proc/cmdline and into a structure */ + if ((fd = open("/proc/cmdline", O_RDONLY)) < 0) { + logMessage(ERROR, "unable to read /proc/cmdline: %s", strerror(errno)); + } else { + len = read(fd, buf, sizeof(buf) - 1); + close(fd); + buf[len] = '\0'; + options = g_strsplit(buf, " ", 0); + optiter = options; + + while (*optiter != NULL) { + gchar **fields = NULL; + + if (g_strstr_len(*optiter, -1, "=") == NULL) { + optiter++; + continue; + } + + if (!strncmp(*optiter, "blacklist=", 10)) { + if ((fields = g_strsplit(*optiter, "=", 0)) != NULL) { + if (g_strv_length(fields) == 2) { + blacklist = g_slist_append(blacklist, fields[1]); + } + } + } else if ((fields = g_strsplit(*optiter, ".", 0)) != NULL) { + if (g_strv_length(fields) == 2) { + if (_isValidModule(fields[0])) { + _addOption(fields[0], fields[1]); + } + } + } + + g_strfreev(fields); + optiter++; + } - for (i = 0 ; i < numblacklists ; i++) { - if (!strcmp(blacklists[i], module)) - blacklists[i] = NULL; + if (options != NULL) { + g_strfreev(options); + } } -} -void mlInitModuleConfig() { - readModuleOpts(); - readBlacklist(); - writeModulesConf("/etc/modprobe.d/anaconda.conf"); + return _writeModulesConf(MODULES_CONF); } /* load a module with a given list of arguments */ -int mlLoadModule(const char * module, char ** args) { - return doLoadModule(module, args); +gboolean mlLoadModule(const gchar *module, gchar **args) { + return _doLoadModule(module, args); } /* loads a : separated list of modules */ -int mlLoadModuleSet(const char * modNames) { - char *ptr, *name; - int rc = 0; - - if (!modNames) return 1; - name = strdup(modNames); while (name) { - ptr = strchr(name, ':'); - if (ptr) *ptr = '\0'; - rc |= doLoadModule(name, NULL); - if (ptr) - name = ptr+1; - else - name = NULL; +gboolean mlLoadModuleSet(const gchar *modNames) { + gchar **mods = NULL, **iterator = NULL; + gboolean rc = FALSE; + + if (modNames == NULL) { + return FALSE; + } + + if ((mods = g_strsplit(modNames, ":", 0)) != NULL) { + iterator = mods; + + while (*iterator != NULL) { + rc |= _doLoadModule(*iterator, NULL); + iterator++; + } + } else { + return FALSE; } + + g_strfreev(mods); return rc; } -static int writeModulesConf(char *conf) { - int i; - char buf[16384]; - int fd, rc; +gboolean mlAddBlacklist(gchar *module) { + gchar *tmpmod = NULL; - if (!conf) - conf = "/tmp/modprobe.conf"; - - fd = open(conf, O_WRONLY | O_CREAT, 0644); - if (fd == -1) { - logMessage(ERROR, "error opening to %s: %m\n", conf); - return 0; + if (module == NULL) { + return FALSE; } - strcat(buf, "# Module options and blacklists written by anaconda\n"); - for (i = 0; i < nummodopts ; i++) { - int j; - - strcat(buf, "options "); - strcat(buf, modopts[i].name); - for (j = 0; j < modopts[i].numopts ; j++) { - strcat(buf, " "); - strcat(buf, modopts[i].options[j]); - } - strcat(buf, "\n"); + + tmpmod = g_strdup(module); + blacklist = g_slist_append(blacklist, tmpmod); + return _writeModulesConf(MODULES_CONF); +} + +gboolean mlRemoveBlacklist(gchar *module) { + GSList *iterator = blacklist; + + if (module == NULL) { + return FALSE; } - for (i = 0; i < numblacklists ; i++) { - if (blacklists[i]) { - strcat(buf, "blacklist "); - strcat(buf, blacklists[i]); - strcat(buf, "\n"); + + while (iterator != NULL) { + if (!strcmp((gchar *) iterator->data, module)) { + iterator = g_slist_delete_link(blacklist, iterator); + continue; + } else { + iterator = g_slist_next(iterator); } } - - rc = write(fd, buf, strlen(buf)); - close(fd); - return (rc != strlen(buf)); + + return TRUE; } -void loadKickstartModule(struct loaderData_s * loaderData, int argc, - char ** argv) { - char * opts = NULL; - char * module = NULL; - char ** args = NULL; +void loadKickstartModule(struct loaderData_s * loaderData, + int argc, char **argv) { + gchar *opts = NULL; + gchar *module = NULL; + gchar **args = NULL; poptContext optCon; - int rc; + gboolean rc; struct poptOption ksDeviceOptions[] = { { "opts", '\0', POPT_ARG_STRING, &opts, 0, NULL, NULL }, { 0, 0, 0, 0, 0, 0, 0 } }; - - optCon = poptGetContext(NULL, argc, (const char **) argv, + + optCon = poptGetContext(NULL, argc, (const char **) argv, ksDeviceOptions, 0); if ((rc = poptGetNextOpt(optCon)) < -1) { startNewt(); newtWinMessage(_("Kickstart Error"), _("OK"), _("Bad argument to device kickstart method " "command %s: %s"), - poptBadOption(optCon, POPT_BADOPTION_NOALIAS), + poptBadOption(optCon, POPT_BADOPTION_NOALIAS), poptStrerror(rc)); return; } - module = (char *) poptGetArg(optCon); + module = (gchar *) poptGetArg(optCon); if (!module) { startNewt(); @@ -380,30 +385,10 @@ void loadKickstartModule(struct loaderData_s * loaderData, int argc, } if (opts) { - int numAlloced = 5, i = 0; - char * start; - char * end; - - args = malloc((numAlloced + 1) * sizeof(args)); - start = opts; - while (start && *start) { - end = start; - while (!isspace(*end) && *end) end++; - *end = '\0'; - (args)[i++] = strdup(start); - start = end + 1; - *end = ' '; - start = strchr(end, ' '); - if (start) start++; - - if (i >= numAlloced) { - numAlloced += 5; - args = realloc(args, sizeof(args) * (numAlloced + 1)); - } - } - args[i] = NULL; + args = g_strsplit(opts, " ", 0); } - - mlLoadModule(module, args); + rc = mlLoadModule(module, args); + g_strfreev(args); + return; } diff --git a/loader/modules.h b/loader/modules.h index 6c0d8ad..88fa25f 100644 --- a/loader/modules.h +++ b/loader/modules.h @@ -1,7 +1,7 @@ /* * modules.h * - * Copyright (C) 2007 Red Hat, Inc. All rights reserved. + * Copyright (C) 2007, 2009 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 @@ -15,16 +15,29 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Author(s): David Cantrell <dcantrell@xxxxxxxxxx> */ #ifndef H_MODULES #define H_MODULES +#include <glib.h> +#include "loader.h" #include "moduleinfo.h" -void mlInitModuleConfig(); -int mlLoadModule(const char * module, char ** args); -int mlLoadModuleSet(const char * modNames); -void mlAddBlacklist(char *module); -void mlRemoveBlacklist(char *module); +#define MODULES_CONF "/etc/modprobe.d/anaconda.conf" + +typedef struct _module_t { + gchar *name; + GSList *options; +} module_t; + +gboolean mlInitModuleConfig(void); +gboolean mlLoadModule(const gchar *, gchar **); +gboolean mlLoadModuleSet(const gchar *); +gboolean mlAddBlacklist(gchar *); +gboolean mlRemoveBlacklist(gchar *); +void loadKickstartModule(struct loaderData_s *, int, char **); + #endif -- 1.6.5.2 _______________________________________________ Anaconda-devel-list mailing list Anaconda-devel-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/anaconda-devel-list