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;
+}

Reply via email to