#include <sys/types.h> #include <sys/module.h> #include <sys/systm.h> /* uprintf */ #include <sys/param.h> /* defines used in kernel.h */ #include <sys/kernel.h> /* types used in module initialization */ #include <sys/conf.h> /* cdevsw struct */ #include <sys/uio.h> /* uio struct */ #include <sys/sysctl.h> #include <sys/malloc.h> #include "lockdoc_internal.h" /* * Big thanks to the authors of the FreeBSD architecture handbook. * This driver is based on the echo example. * https://www.freebsd.org/doc/en/books/arch-handbook/driverbasics-char.html */ /* Function prototypes */ static d_read_t lockdoc_version_read; static struct cdev *lockdoc_version_dev; /* Character device entry points */ static struct cdevsw lockdoc_version_cdevsw = { .d_version = D_VERSION, .d_read = lockdoc_version_read, .d_name = "lockdoc_version", }; static int lockdoc_version_loader(struct module *m __unused, int what, void *arg __unused) { int error = 0; switch (what) { case MOD_LOAD: /* kldload */ error = make_dev_p(MAKEDEV_CHECKNAME | MAKEDEV_WAITOK, &lockdoc_version_dev, &lockdoc_version_cdevsw, 0, UID_ROOT, GID_WHEEL, 0400, DEV_DIR_NAME "/version"); if (error != 0) { break; } break; case MOD_UNLOAD: destroy_dev(lockdoc_version_dev); break; default: error = EOPNOTSUPP; break; } return (error); } #define BUFSIZE 70 static int lockdoc_version_read(struct cdev *dev __unused, struct uio *uio, int ioflag __unused) { size_t amt, len; int error; char *buffer; buffer = malloc(BUFSIZE, M_TEMP, M_WAITOK | M_ZERO); if (buffer == NULL) { return (ENOMEM); } len = snprintf(buffer, BUFSIZE, "%s\n", lockdoc_version); if (len >= BUFSIZE) { len = BUFSIZE; } /* * How big is this read operation? Either as big as the user wants, * or as big as the remaining data. Note that the 'len' does not * include the trailing null character. */ amt = MIN(uio->uio_resid, uio->uio_offset >= len ? 0 : len - uio->uio_offset); error = uiomove(buffer, amt, uio); if (error != 0) { uprintf("uiomove failed!\n"); } free(buffer, M_TEMP); return (error); } #undef BUFSIZE DEV_MODULE(lockdoc_version, lockdoc_version_loader, NULL); |