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>