Module Name: src
Committed By: jnemeth
Date: Sun Jun 7 09:47:31 UTC 2009
Modified Files:
src/sys/kern: kern_module.c
Log Message:
Read in a <module>.prop file if it exists and internalize then pass it
to the <module> being loaded.
XXX A <module>.prop file will override anything on the "command line".
This will be fixed in the next commit.
To generate a diff of this commit:
cvs rdiff -u -r1.45 -r1.46 src/sys/kern/kern_module.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/kern/kern_module.c
diff -u src/sys/kern/kern_module.c:1.45 src/sys/kern/kern_module.c:1.46
--- src/sys/kern/kern_module.c:1.45 Tue May 26 08:34:23 2009
+++ src/sys/kern/kern_module.c Sun Jun 7 09:47:31 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_module.c,v 1.45 2009/05/26 08:34:23 jnemeth Exp $ */
+/* $NetBSD: kern_module.c,v 1.46 2009/06/07 09:47:31 jnemeth Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_module.c,v 1.45 2009/05/26 08:34:23 jnemeth Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_module.c,v 1.46 2009/06/07 09:47:31 jnemeth Exp $");
#ifdef _KERNEL_OPT
#include "opt_ddb.h"
@@ -54,6 +54,9 @@
#include <sys/kthread.h>
#include <sys/sysctl.h>
#include <sys/namei.h>
+#include <sys/lock.h>
+#include <sys/vnode.h>
+#include <sys/stat.h>
#include <uvm/uvm_extern.h>
@@ -90,6 +93,8 @@
static int module_do_builtin(const char *, module_t **);
static int module_fetch_info(module_t *);
static void module_thread(void *);
+static int module_load_plist_file(const char *, const bool, void **,
+ size_t *);
/*
* module_error:
@@ -559,16 +564,20 @@
const int maxdepth = 6;
modinfo_t *mi;
module_t *mod, *mod2;
+ prop_dictionary_t filedict;
+ void *plist;
char buf[MAXMODNAME], *path;
const char *s, *p;
int error;
- size_t len;
+ size_t len, plistlen;
bool nochroot;
KASSERT(mutex_owned(&module_lock));
+ filedict = NULL;
+ path = NULL;
error = 0;
- path=NULL;
+ nochroot = false;
/*
* Avoid recursing too far.
@@ -775,10 +784,37 @@
goto fail2;
}
+ /*
+ * Load and process <module>.prop if it exists.
+ */
+ if (mod->mod_source == MODULE_SOURCE_FILESYS) {
+ error = module_load_plist_file(path, nochroot, &plist,
+ &plistlen);
+ if (error != 0) {
+ module_print("plist load returned error %d for `%s'",
+ error, path);
+ } else {
+ filedict = prop_dictionary_internalize(plist);
+ if (filedict == NULL) {
+ error = EINVAL;
+ }
+ }
+ if (plist != NULL) {
+ kmem_free(plist, PAGE_SIZE);
+ }
+ if ((error != 0) && (error != ENOENT)) {
+ goto fail;
+ }
+ }
+
KASSERT(module_active == NULL);
module_active = mod;
- error = (*mi->mi_modcmd)(MODULE_CMD_INIT, props);
+ error = (*mi->mi_modcmd)(MODULE_CMD_INIT, (filedict != NULL) ?
+ filedict : props);
module_active = NULL;
+ if (filedict != NULL) {
+ prop_object_release(filedict);
+ }
if (error != 0) {
module_error("modcmd function returned error %d for `%s'",
error, mi->mi_name);
@@ -1081,3 +1117,83 @@
}
}
#endif /* DDB */
+
+/*
+ * module_load_plist_file:
+ *
+ * Load a plist located in the file system into memory.
+ */
+static int
+module_load_plist_file(const char *modpath, const bool nochroot,
+ void **basep, size_t *length)
+{
+ struct nameidata nd;
+ struct stat sb;
+ void *base;
+ char *proppath;
+ size_t resid;
+ int error, pathlen;
+
+ base = NULL;
+ *length = 0;
+
+ proppath = PNBUF_GET();
+ strcpy(proppath, modpath);
+ pathlen = strlen(proppath);
+ if ((pathlen >= 5) && (strcmp(&proppath[pathlen - 5], ".kmod") == 0)) {
+ strcpy(&proppath[pathlen - 5], ".prop");
+ } else if (pathlen < MAXPATHLEN - 5) {
+ strcat(proppath, ".prop");
+ } else {
+ error = ENOENT;
+ goto out1;
+ }
+
+ NDINIT(&nd, LOOKUP, FOLLOW | (nochroot ? NOCHROOT : 0),
+ UIO_SYSSPACE, proppath);
+
+ error = namei(&nd);
+ if (error != 0) {
+ goto out1;
+ }
+
+ error = vn_stat(nd.ni_vp, &sb);
+ if (sb.st_size >= (PAGE_SIZE - 1)) { /* leave space for term \0 */
+ error = EINVAL;
+ }
+ if (error != 0) {
+ goto out1;
+ }
+
+ error = vn_open(&nd, FREAD, 0);
+ if (error != 0) {
+ goto out1;
+ }
+
+ base = kmem_alloc(PAGE_SIZE, KM_SLEEP);
+ if (base == NULL) {
+ error = ENOMEM;
+ goto out;
+ }
+
+ error = vn_rdwr(UIO_READ, nd.ni_vp, base, sb.st_size, 0,
+ UIO_SYSSPACE, IO_NODELOCKED, curlwp->l_cred, &resid, curlwp);
+ *((uint8_t *)base + sb.st_size) = '\0';
+ if (error == 0 && resid != 0) {
+ error = EINVAL;
+ }
+ if (error != 0) {
+ kmem_free(base, PAGE_SIZE);
+ base = NULL;
+ }
+ *length = sb.st_size;
+
+out:
+ VOP_UNLOCK(nd.ni_vp, 0);
+ vn_close(nd.ni_vp, FREAD, kauth_cred_get());
+
+out1:
+ PNBUF_PUT(proppath);
+ *basep = base;
+ return error;
+}