Module Name:    src
Committed By:   jmcneill
Date:           Sat Nov 25 23:23:39 UTC 2017

Added Files:
        src/sbin/mount_qemufwcfg: Makefile defs.h fwcfg.c virtdir.c virtdir.h

Log Message:
Add virtual filesystem for QEMU Firmware Configuration interface.


To generate a diff of this commit:
cvs rdiff -u -r0 -r1.1 src/sbin/mount_qemufwcfg/Makefile \
    src/sbin/mount_qemufwcfg/defs.h src/sbin/mount_qemufwcfg/fwcfg.c \
    src/sbin/mount_qemufwcfg/virtdir.c src/sbin/mount_qemufwcfg/virtdir.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Added files:

Index: src/sbin/mount_qemufwcfg/Makefile
diff -u /dev/null src/sbin/mount_qemufwcfg/Makefile:1.1
--- /dev/null	Sat Nov 25 23:23:39 2017
+++ src/sbin/mount_qemufwcfg/Makefile	Sat Nov 25 23:23:39 2017
@@ -0,0 +1,12 @@
+# $NetBSD: Makefile,v 1.1 2017/11/25 23:23:39 jmcneill Exp $
+
+PROG=	mount_qemufwcfg
+SRCS=	fwcfg.c virtdir.c
+DPADD+=	${LIBREFUSE}
+LDADD=	-lrefuse
+NOMAN=	# defined
+WARNS=	3
+
+CPPFLAGS+=	-D_KERNTYPES
+
+.include <bsd.prog.mk>
Index: src/sbin/mount_qemufwcfg/defs.h
diff -u /dev/null src/sbin/mount_qemufwcfg/defs.h:1.1
--- /dev/null	Sat Nov 25 23:23:39 2017
+++ src/sbin/mount_qemufwcfg/defs.h	Sat Nov 25 23:23:39 2017
@@ -0,0 +1,88 @@
+/* $NetBSD: defs.h,v 1.1 2017/11/25 23:23:39 jmcneill Exp $ */
+
+/*
+ * Copyright (c) 1999-2005 Alistair Crooks.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef DEFS_H_
+#define DEFS_H_
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define NEWARRAY(type,ptr,size,where,action) do {			\
+	if ((ptr = (type *) calloc(sizeof(type), (unsigned)(size))) == NULL) { \
+		(void) fprintf(stderr, "%s: can't allocate %lu bytes\n", \
+			where, (unsigned long)(size * sizeof(type)));	\
+		action;							\
+	}								\
+} while( /* CONSTCOND */ 0)
+
+#define RENEW(type,ptr,size,where,action) do {				\
+	type *_newptr;							\
+	if ((_newptr = (type *) realloc(ptr, sizeof(type) * (size))) == NULL) { \
+		(void) fprintf(stderr, "%s: can't realloc %lu bytes\n",	\
+			where, (unsigned long)(size * sizeof(type)));	\
+		action;							\
+	} else {							\
+		ptr = _newptr;						\
+	}								\
+} while( /* CONSTCOND */ 0)
+
+#define NEW(type, ptr, where, action)	NEWARRAY(type, ptr, 1, where, action)
+
+#define FREE(ptr)	(void) free(ptr)
+
+#define ALLOC(type, v, size, c, init, incr, where, action) do {		\
+	uint32_t	_newsize = size;				\
+	if (size == 0) {						\
+		_newsize = init;					\
+		NEWARRAY(type, v, _newsize, where ": new", action);	\
+	} else if (c == size) {						\
+		_newsize = size + incr;					\
+		RENEW(type, v, _newsize, where ": renew", action);	\
+	}								\
+	size = _newsize;						\
+} while( /* CONSTCOND */ 0)
+
+/*		(void) memset(&v[size], 0x0, sizeof(type) * incr);	\*/
+
+#define DEFINE_ARRAY(name, type)					\
+typedef struct name {							\
+	uint32_t	c;						\
+	uint32_t	size;						\
+	type	       *v;						\
+} name
+
+#endif /* !DEFS_H_ */
Index: src/sbin/mount_qemufwcfg/fwcfg.c
diff -u /dev/null src/sbin/mount_qemufwcfg/fwcfg.c:1.1
--- /dev/null	Sat Nov 25 23:23:39 2017
+++ src/sbin/mount_qemufwcfg/fwcfg.c	Sat Nov 25 23:23:39 2017
@@ -0,0 +1,259 @@
+/* $NetBSD: fwcfg.c,v 1.1 2017/11/25 23:23:39 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: fwcfg.c,v 1.1 2017/11/25 23:23:39 jmcneill Exp $");
+
+#include <sys/ioctl.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <fuse.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <dev/ic/qemufwcfgio.h>
+
+#include "virtdir.h"
+
+#define _PATH_FWCFG	"/dev/qemufwcfg"
+
+struct fwcfg_file {
+	uint32_t size;
+	uint16_t select;
+	uint16_t reserved;
+	char name[56];
+};
+
+static int fwcfg_fd;
+static mode_t fwcfg_dir_mask = 0555;
+static mode_t fwcfg_file_mask = 0444;
+static uid_t fwcfg_uid;
+static gid_t fwcfg_gid;
+
+static virtdir_t fwcfg_virtdir;
+
+static void
+set_index(uint16_t index)
+{
+	if (ioctl(fwcfg_fd, FWCFGIO_SET_INDEX, &index) != 0)
+		err(EXIT_FAILURE, "failed to set index 0x%04x", index);
+}
+
+static void
+read_data(void *buf, size_t buflen)
+{
+	if (read(fwcfg_fd, buf, buflen) != (ssize_t)buflen)
+		err(EXIT_FAILURE, "failed to read data");
+}
+
+static int
+fwcfg_getattr(const char *path, struct stat *st)
+{
+	virt_dirent_t *ep;
+
+	if (strcmp(path, "/") == 0) {
+		memset(st, 0, sizeof(*st));
+		st->st_mode = S_IFDIR | fwcfg_dir_mask;
+		st->st_nlink = 2;
+		return 0;
+	}
+
+	if ((ep = virtdir_find(&fwcfg_virtdir, path, strlen(path))) == NULL)
+		return -ENOENT;
+
+	switch (ep->type) {
+	case 'f':
+		memcpy(st, &fwcfg_virtdir.file, sizeof(*st));
+		st->st_size = ep->tgtlen;
+		st->st_mode = S_IFREG | fwcfg_file_mask;
+		break;
+	case 'd':
+		memcpy(st, &fwcfg_virtdir.dir, sizeof(*st));
+		st->st_mode = S_IFDIR | fwcfg_dir_mask;
+		break;
+	}
+	st->st_ino = virtdir_offset(&fwcfg_virtdir, ep) + 10;
+
+	return 0;
+}
+
+static int
+fwcfg_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
+    off_t offset, struct fuse_file_info *fi)
+{
+	static VIRTDIR *dirp;
+	virt_dirent_t *dp;
+
+	if (offset == 0) {
+		if ((dirp = openvirtdir(&fwcfg_virtdir, path)) == NULL)
+			return 0;
+		filler(buf, ".", NULL, 0);
+		filler(buf, "..", NULL, 0);
+	}
+	while ((dp = readvirtdir(dirp)) != NULL) {
+		if (filler(buf, dp->d_name, NULL, 0) != 0)
+			return 0;
+	}
+	closevirtdir(dirp);
+	dirp = NULL;
+
+	return 0;
+}
+
+static int
+fwcfg_open(const char *path, struct fuse_file_info *fi)
+{
+	return 0;
+}
+
+static int
+fwcfg_read(const char *path, char *buf, size_t size, off_t offset,
+    struct fuse_file_info *fi)
+{
+	virt_dirent_t *ep;
+	uint8_t tmp[64];
+
+	if ((ep = virtdir_find(&fwcfg_virtdir, path, strlen(path))) == NULL)
+		return -ENOENT;
+
+	if (ep->select == 0)
+		return -ENOENT;
+
+	set_index(ep->select);
+
+	/* Seek to correct offset */
+	while (offset > 0) {
+		const int len = MIN(sizeof(tmp), (size_t)offset);
+		read_data(tmp, len);
+		offset -= len;
+	}
+
+	/* Read the data */
+	read_data(buf, size);
+
+	return size;
+}
+
+static int
+fwcfg_statfs(const char *path, struct statvfs *st)
+{
+	uint32_t count;
+
+	set_index(FW_CFG_FILE_DIR);
+	read_data(&count, sizeof(count));
+
+	memset(st, 0, sizeof(*st));
+	st->f_files = be32toh(count);
+
+	return 0;
+}
+
+static struct fuse_operations fwcfg_ops = {
+	.getattr = fwcfg_getattr,
+	.readdir = fwcfg_readdir,
+	.open = fwcfg_open,
+	.read = fwcfg_read,
+	.statfs = fwcfg_statfs,
+};
+
+static void
+build_tree(virtdir_t *v)
+{
+	char path[PATH_MAX];
+	struct fwcfg_file f;
+	uint32_t count, n;
+	struct stat st;
+
+	memset(&st, 0, sizeof(st));
+	st.st_uid = fwcfg_uid;
+	st.st_gid = fwcfg_gid;
+	virtdir_init(v, NULL, &st, &st, &st);
+
+printf("init with uid = %d, gid = %d\n", st.st_uid, st.st_gid);
+
+	set_index(FW_CFG_FILE_DIR);
+	read_data(&count, sizeof(count));
+	for (n = 0; n < be32toh(count); n++) {
+		read_data(&f, sizeof(f));
+		snprintf(path, sizeof(path), "/%s", f.name);
+		virtdir_add(v, path, strlen(path), 'f', NULL,
+		    be32toh(f.size), be16toh(f.select));
+	}
+}
+
+int
+main(int argc, char *argv[])
+{
+	const char *path = _PATH_FWCFG;
+	int ch, m;
+	char *ep;
+
+	fwcfg_uid = geteuid();
+	fwcfg_gid = getegid();
+
+	while ((ch = getopt(argc, argv, "F:g:m:M:u:")) != -1) {
+		switch (ch) {
+		case 'F':
+			path = optarg;
+			break;
+		case 'g':
+			fwcfg_gid = atoi(optarg);
+			break;
+		case 'm':
+			m = strtol(optarg, &ep, 8);
+			if (optarg == ep || *ep || m < 0)
+				errx(1, "invalid file mode: %s", optarg);
+			fwcfg_file_mask = m;
+			break;
+		case 'M':
+			m = strtol(optarg, &ep, 8);
+			if (optarg == ep || *ep || m < 0)
+				errx(1, "invalid file mode: %s", optarg);
+			fwcfg_dir_mask = m;
+			break;
+		case 'u':
+			fwcfg_uid = atoi(optarg);
+			break;
+		}
+	}
+
+	fwcfg_fd = open(path, O_RDWR);
+	if (fwcfg_fd == -1)
+		err(EXIT_FAILURE, "failed to open %s", path);
+
+	build_tree(&fwcfg_virtdir);
+
+	for (int i = 0; i < argc; i++)
+		printf("argv[%d] = \"%s\"\n", i, argv[i]);
+
+	return fuse_main(argc, argv, &fwcfg_ops, NULL);
+}
Index: src/sbin/mount_qemufwcfg/virtdir.c
diff -u /dev/null src/sbin/mount_qemufwcfg/virtdir.c:1.1
--- /dev/null	Sat Nov 25 23:23:39 2017
+++ src/sbin/mount_qemufwcfg/virtdir.c	Sat Nov 25 23:23:39 2017
@@ -0,0 +1,226 @@
+/* $NetBSD: virtdir.c,v 1.1 2017/11/25 23:23:39 jmcneill Exp $ */
+
+/*
+ * Copyright © 2007 Alistair Crooks.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "virtdir.h"
+#include "defs.h"
+
+ /* utility comparison routine for sorting and searching */
+static int
+compare(const void *vp1, const void *vp2)
+{
+	const virt_dirent_t	*tp1 = (const virt_dirent_t *) vp1;
+	const virt_dirent_t	*tp2 = (const virt_dirent_t *) vp2;
+
+	return strcmp(tp1->name, tp2->name);
+}
+
+/* save `n' chars of `s' in allocated storage */
+static char *
+strnsave(const char *s, int n)
+{
+	char	*cp;
+
+	if (n < 0) {
+		n = strlen(s);
+	}
+	NEWARRAY(char, cp, n + 1, "strnsave", return NULL);
+	(void) memcpy(cp, s, n);
+	cp[n] = 0x0;
+	return cp;
+}
+
+/* ensure intermediate directories exist */
+static void
+mkdirs(virtdir_t *tp, const char *path, size_t size)
+{
+	virt_dirent_t	*ep;
+	char		 name[MAXPATHLEN];
+	char		*slash;
+
+	(void) strlcpy(name, path, sizeof(name));
+	for (slash = name + 1 ; (slash = strchr(slash + 1, '/')) != NULL ; ) {
+		*slash = 0x0;
+		if ((ep = virtdir_find(tp, name, strlen(name))) == NULL) {
+			virtdir_add(tp, name, strlen(name), 'd', NULL, 0, 0);
+		}
+		*slash = '/';
+	}
+}
+
+/* get rid of multiple slashes in input */
+static int
+normalise(const char *name, size_t namelen, char *path, size_t pathsize)
+{
+	const char	*np;
+	char		*pp;
+	int		 done;
+
+	for (pp = path, np = name, done = 0 ; !done && (int)(pp - path) < pathsize - 1 && (int)(np - name) <= namelen ; ) {
+		switch(*np) {
+		case '/':
+			if (pp == path || *(pp - 1) != '/') {
+				*pp++ = *np;
+			}
+			np += 1;
+			break;
+		case 0x0:
+			done = 1;
+			break;
+		default:
+			*pp++ = *np++;
+			break;
+		}
+	}
+	/* XXX - trailing slash? */
+	*pp = 0x0;
+	return (int)(pp - path);
+}
+
+/* initialise the tree */
+int
+virtdir_init(virtdir_t *tp, const char *rootdir, struct stat *d, struct stat *f, struct stat *l)
+{
+	(void) memcpy(&tp->dir, d, sizeof(tp->dir));
+	tp->dir.st_mode = S_IFDIR | 0755;
+	tp->dir.st_nlink = 2;
+	(void) memcpy(&tp->file, f, sizeof(tp->file));
+	tp->file.st_mode = S_IFREG | 0644;
+	tp->file.st_nlink = 1;
+	(void) memcpy(&tp->lnk, l, sizeof(tp->lnk));
+	tp->lnk.st_mode = S_IFLNK | 0644;
+	tp->lnk.st_nlink = 1;
+	if (rootdir != NULL) {
+		tp->rootdir = strdup(rootdir);
+	}
+	return 1;
+}
+
+/* add an entry to the tree */
+int
+virtdir_add(virtdir_t *tp, const char *name, size_t size, uint8_t type, const char *tgt, size_t tgtlen, uint16_t select)
+{
+	char		path[MAXPATHLEN];
+	int		pathlen;
+
+	pathlen = normalise(name, size, path, sizeof(path));
+	if (virtdir_find(tp, path, pathlen) != NULL) {
+		/* attempt to add a duplicate directory entry */
+		return 0;
+	}
+	ALLOC(virt_dirent_t, tp->v, tp->size, tp->c, 10, 10, "virtdir_add",
+			return 0);
+	tp->v[tp->c].namelen = pathlen;
+	if ((tp->v[tp->c].name = strnsave(path, pathlen)) == NULL) {
+		return 0;
+	}
+	tp->v[tp->c].d_name = strrchr(tp->v[tp->c].name, '/') + 1;
+	tp->v[tp->c].type = type;
+	tp->v[tp->c].ino = (ino_t) random() & 0xfffff;
+	tp->v[tp->c].tgtlen = tgtlen;
+	if (tgt != NULL) {
+		tp->v[tp->c].tgt = strnsave(tgt, tgtlen);
+	}
+	tp->v[tp->c].select = select;
+	tp->c += 1;
+	qsort(tp->v, tp->c, sizeof(tp->v[0]), compare);
+	mkdirs(tp, path, pathlen);
+	return 1;
+}
+
+/* find an entry in the tree */
+virt_dirent_t *
+virtdir_find(virtdir_t *tp, const char *name, size_t namelen)
+{
+	virt_dirent_t	e;
+	char		path[MAXPATHLEN];
+
+	(void) memset(&e, 0x0, sizeof(e));
+	e.namelen = normalise(name, namelen, path, sizeof(path));
+	e.name = path;
+	return bsearch(&e, tp->v, tp->c, sizeof(tp->v[0]), compare);
+}
+
+/* return the virtual offset in the tree */
+int
+virtdir_offset(virtdir_t *tp, virt_dirent_t *dp)
+{
+	return (int)(dp - tp->v);
+}
+
+/* analogous to opendir(3) - open a directory, save information, and
+* return a pointer to the dynamically allocated structure */
+VIRTDIR *
+openvirtdir(virtdir_t *tp, const char *d)
+{
+	VIRTDIR	*dirp;
+
+	NEW(VIRTDIR, dirp, "openvirtdir", exit(EXIT_FAILURE));
+	dirp->dirname = strdup(d);
+	dirp->dirnamelen = strlen(d);
+	dirp->tp = tp;
+	dirp->i = 0;
+	return dirp;
+}
+
+/* analogous to readdir(3) - read the next entry in the directory that
+* was opened, and return a pointer to it */
+virt_dirent_t *
+readvirtdir(VIRTDIR *dirp)
+{
+	char	*from;
+
+	for ( ; dirp->i < dirp->tp->c ; dirp->i++) {
+		from = (strcmp(dirp->dirname, "/") == 0) ?
+			&dirp->tp->v[dirp->i].name[1] :
+			&dirp->tp->v[dirp->i].name[dirp->dirnamelen + 1];
+		if (strncmp(dirp->tp->v[dirp->i].name, dirp->dirname,
+				dirp->dirnamelen) == 0 &&
+		    *from != 0x0 &&
+		    strchr(from, '/') == NULL) {
+			return &dirp->tp->v[dirp->i++];
+		}
+	}
+	return NULL;
+}
+
+/* free the storage associated with the virtual directory structure */
+void
+closevirtdir(VIRTDIR *dirp)
+{
+	free(dirp->dirname);
+	FREE(dirp);
+}
Index: src/sbin/mount_qemufwcfg/virtdir.h
diff -u /dev/null src/sbin/mount_qemufwcfg/virtdir.h:1.1
--- /dev/null	Sat Nov 25 23:23:39 2017
+++ src/sbin/mount_qemufwcfg/virtdir.h	Sat Nov 25 23:23:39 2017
@@ -0,0 +1,81 @@
+/* $NetBSD: virtdir.h,v 1.1 2017/11/25 23:23:39 jmcneill Exp $ */
+
+/*
+ * Copyright © 2007 Alistair Crooks.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef VIRTDIR_H_
+#define VIRTDIR_H_	20070405
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "defs.h"
+
+/* this struct keeps a note of all the info related to a virtual directory entry */
+typedef struct virt_dirent_t {
+	char		*name;		/* entry name - used as key */
+	size_t		 namelen;	/* length of name */
+	char		*d_name;	/* component in this directory */
+	char		*tgt;		/* any symlink target */
+	size_t		 tgtlen;	/* length of symlink target */
+	uint8_t		 type;		/* entry type - file, dir, lnk */
+	ino_t		 ino;		/* inode number */
+	uint16_t	 select;	/* selector */
+} virt_dirent_t;
+
+/* this defines the list of virtual directory entries,
+   sorted in name alpha order */
+typedef struct virtdir_t {
+	uint32_t	 c;		/* count of entries */
+	uint32_t	 size;		/* size of allocated list */
+	virt_dirent_t	*v;		/* list */
+	char		*rootdir;	/* root directory of virtual fs */
+	struct stat	 file;		/* stat struct for file entries */
+	struct stat	 dir;		/* stat struct for dir entries */
+	struct stat	 lnk;		/* stat struct for symlinks */
+} virtdir_t;
+
+/* this struct is used to walk through directories */
+typedef struct VIRTDIR {
+	char		*dirname;	/* directory name */
+	int		 dirnamelen;	/* length of directory name */
+	virtdir_t	*tp;		/* the directory tree */
+	int		 i;		/* current offset in dir tree */
+} VIRTDIR;
+
+int virtdir_init(virtdir_t *, const char *, struct stat *, struct stat *, struct stat *);
+int virtdir_add(virtdir_t *, const char *, size_t, uint8_t, const char *, size_t, uint16_t);
+virt_dirent_t *virtdir_find(virtdir_t *, const char *, size_t);
+
+VIRTDIR *openvirtdir(virtdir_t *, const char *);
+virt_dirent_t *readvirtdir(VIRTDIR *);
+void closevirtdir(VIRTDIR *);
+
+int virtdir_offset(virtdir_t *, virt_dirent_t *);
+
+#endif

Reply via email to