Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 13 Aug 2001 19:51:57 +0100
From:      Ian Dowse <iedowse@maths.tcd.ie>
To:        Sansonetti Laurent <lorenzo@linuxbe.org>
Cc:        freebsd-hackers@freebsd.org
Subject:   Reading files within the kernel (was Re: allocating userland space...)
Message-ID:   <200108131951.aa91431@salmon.maths.tcd.ie>
In-Reply-To: Your message of "Mon, 13 Aug 2001 18:01:00 %2B0200." <003101c12411$294adaa0$0201a8c0@teledisnet.be> 

next in thread | previous in thread | raw e-mail | index | archive | help
In message <003101c12411$294adaa0$0201a8c0@teledisnet.be>, Sansonetti Laurent w
rites:
>Hello hackers,
>I'm currently working on a kld syscall module which needs to read a config
>file at startup (MOD_LOAD).
>Following the advice of Eugene L. Vorokov, I tried to allocate some userland
>space with mmap() to store a open_args struct, fill-it with copyout() /
>subyte()... and call open with curproc on first argument.

I really don't understand why people try these obscure mechanisms
to read files within the kernel. There are existing kernel interfaces
for accessing files that are much cleaner than these hacks. You
can't use the familiour open/read/close calls, but using the vnode
interface is really not that hard.

Below is a simple KLD that prints /etc/motd on the console. There's
not a lot involved really, since vn_open(), vn_rdwr() and vn_close()
do most of the hard bits. The most strange stuff is probably the
setting up of the nameidata structure, but even it isn't too
complicated.

To try it, just save the two files below in a directory, and run

	make depend
	make
	kldload ./kernio.ko

(WARNING: not highly tested, so it may crash your machine!)

For further reference, most of the VOP_* functions are documented
in section 9 man pages.

Ian

---------------- Makefile ------------------------------
KLDMOD= true
KMOD=	kernio
SRCS= 	vnode_if.h kernio.c

NOMAN=
CFLAGS+= -I${.CURDIR}/.. -I/usr/src/sys

.include <bsd.kmod.mk>

----------------- kernio.c ------------------------------
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/fcntl.h>
#include <sys/namei.h>
#include <sys/vnode.h>
#include <sys/proc.h>
#include <sys/malloc.h>
#include <sys/kernel.h>

static int kernio_example(void);
static int kernio_open(int pathseg, const char *path, int flags,
    struct proc *p, struct vnode **vpp);
static void kernio_close(struct vnode *vp, int flags, struct proc *p);

static int
kernio_modevent(module_t mod, int type, void *unused) {
	switch (type) {
	case MOD_LOAD:
		return kernio_example();

	case MOD_UNLOAD:
		break;
	default:
		break;
	}
	return 0;
}

static int
kernio_example(void) {
	struct vattr vattr;
	struct proc *p;
	struct vnode *vp;
	char *buf, *cp;
	int error, filesize, flags, pos, resid;

	p = curproc;
	flags = FREAD;
	buf = NULL;

	/* Open the file, and get its size. */
	error = kernio_open(UIO_SYSSPACE, "/etc/motd", flags, p, &vp);
	if (error)
		return (error);
	error = VOP_GETATTR(vp, &vattr, p->p_ucred, p);
	if (error)
		goto errout;
	filesize = vattr.va_size;
	printf("file size = %d\n", filesize);

	/* Allocate space for the file contents. */
	MALLOC(buf, char *, filesize, M_TEMP, M_WAITOK);
	if (buf == NULL)
		goto errout;

	/* Read in the complete file to `buf'. */
	error = vn_rdwr(UIO_READ, vp, buf, filesize, 0, UIO_SYSSPACE,
	    IO_NODELOCKED, p->p_ucred, &resid, p);
	if (error)
		goto errout;

	/* Silly example; print out the file line by line. */
	cp = buf;
	for (pos = 0; pos < filesize; pos++) {
		if (buf[pos] != '\n')
			continue;

		buf[pos] = '\0';
		printf("%s\n", cp);
		cp = &buf[pos] + 1;
	}

errout:
	if (buf != NULL)
		FREE(buf, M_TEMP);
	kernio_close(vp, flags, p);
	return (error);
}


static int
kernio_open(int pathseg, const char *path, int flags, struct proc *p,
    struct vnode **vpp)
{
	struct nameidata nd;
	struct vnode *vp;
	int error;

	NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, p);
#if __FreeBSD_version < 500000
	error = vn_open(&nd, flags, 0);
#else
	error = vn_open(&nd, &flags, 0);
#endif
	if (error)
		return (error);
	NDFREE(&nd, NDF_ONLY_PNBUF);
	vp = nd.ni_vp;
	if (vp->v_type != VREG) {
		VOP_UNLOCK(vp, 0, p);
		vn_close(vp, flags, p->p_ucred, p);
		return (EACCES);
	}
	*vpp = vp;
	return (0);
}

static void
kernio_close(struct vnode *vp, int flags, struct proc *p)
{
	VOP_UNLOCK(vp, 0, p);
	vn_close(vp, flags, p->p_ucred, p);
}


moduledata_t kernio_mod = {
	"kernio",
	kernio_modevent,
	0
};
DECLARE_MODULE(kernio, kernio_mod, SI_SUB_DRIVERS, SI_ORDER_ANY);


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi? <200108131951.aa91431>