summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Cantrell <dcantrell@redhat.com>2009-11-16 18:47:53 -1000
committerDavid Cantrell <dcantrell@redhat.com>2009-11-16 18:47:53 -1000
commit573aca728ffe5bd45ddc10763512c81d9c0275c8 (patch)
tree5dc076df77afc7d5a7fa0aff929f409a460a9870
parent01c22ad6ff057a9474da7fb8ac443fea4d04440a (diff)
downloadanaconda-573aca728ffe5bd45ddc10763512c81d9c0275c8.tar.gz
anaconda-573aca728ffe5bd45ddc10763512c81d9c0275c8.tar.xz
anaconda-573aca728ffe5bd45ddc10763512c81d9c0275c8.zip
Use glib data structures in loader's module handling code.
Use glib's data structures and string functions in modules.c since we already have glib. Add in some safety checks as well.
-rw-r--r--loader/kickstart.c3
-rw-r--r--loader/loader.c6
-rw-r--r--loader/loader.h2
-rw-r--r--loader/modules.c506
-rw-r--r--loader/modules.h25
5 files changed, 276 insertions, 266 deletions
diff --git a/loader/kickstart.c b/loader/kickstart.c
index b92c6da1d..764df5d69 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 dea600f74..0ea57cb31 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 f942b7e1d..ffb408772 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 fbdd0c94e..a174dc11b 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@redhat.com>
* Michael Fulbright <msf@redhat.com>
* Jeremy Katz <katzj@redhat.com>
+ * David Cantrell <dcantrell@redhat.com>
*/
#include <ctype.h>
@@ -37,339 +39,351 @@
#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;
-
- 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();
- }
+static void _addOption(const gchar *module, const gchar *option) {
+ gboolean found = FALSE;
+ GSList *iterator = modopts;
+ module_t *modopt = NULL;
+ gchar *tmpopt = g_strdup(option);
- 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));
- }
+ while (iterator != NULL) {
+ modopt = (module_t *) iterator->data;
- 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);
+ }
- if (!end)
- break;
- start = end + 1;
+ iterator = blacklist;
+
+ 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 i = 0;
+ gchar *cmdline = NULL;
+ gchar **options = NULL;
+ GError *readErr = NULL;
+
+ /* read module options out of /proc/cmdline and into a structure */
+ if (!g_file_get_contents("/proc/cmdline", &cmdline, NULL, &readErr)) {
+ logMessage(ERROR, "unable to read /proc/cmdline: %s", readErr->message);
+ g_error_free(readErr);
+ return _writeModulesConf(MODULES_CONF);
+ }
+
+ cmdline = g_strchomp(cmdline);
+ options = g_strsplit(cmdline, " ", 0);
+ g_free(cmdline);
- for (i = 0 ; i < numblacklists ; i++) {
- if (!strcmp(blacklists[i], module))
- blacklists[i] = NULL;
+ if (options == NULL) {
+ return _writeModulesConf(MODULES_CONF);
}
-}
-void mlInitModuleConfig() {
- readModuleOpts();
- readBlacklist();
- writeModulesConf("/etc/modprobe.d/anaconda.conf");
+ while (options[i] != NULL) {
+ gchar *tmpmod = NULL;
+ gchar **fields = NULL;
+
+ if (g_strstr_len(options[i], -1, "=") == NULL) {
+ i++;
+ continue;
+ }
+
+ if (!strncmp(options[i], "blacklist=", 10)) {
+ if ((fields = g_strsplit(options[i], "=", 0)) != NULL) {
+ if (g_strv_length(fields) == 2) {
+ tmpmod = g_strdup(fields[1]);
+ blacklist = g_slist_append(blacklist, tmpmod);
+ }
+ }
+ } else if ((fields = g_strsplit(options[i], ".", 0)) != NULL) {
+ if (g_strv_length(fields) == 2) {
+ if (_isValidModule(fields[0])) {
+ _addOption(fields[0], fields[1]);
+ }
+ }
+ }
+
+ if (fields != NULL) {
+ g_strfreev(fields);
+ }
+
+ i++;
+ }
+
+ if (options != NULL) {
+ g_strfreev(options);
+ }
+
+ 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 +394,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 6c0d8adcd..88fa25fc7 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@redhat.com>
*/
#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