Module Name:    src
Committed By:   agc
Date:           Mon Jun 22 14:44:13 UTC 2009

Modified Files:
        src/external/bsd/iscsi: Makefile
Added Files:
        src/external/bsd/iscsi/dist/include: libkmod.h virtdir.h
        src/external/bsd/iscsi/dist/src: iscsi-initiator.8 iscsi-initiator.c
            libkmod.c virtdir.c
Removed Files:
        src/external/bsd/iscsi: Makefile.inc
        src/external/bsd/iscsi/initiator: iscsi-initiator.8 iscsi-initiator.c
            libkmod.c libkmod.h virtdir.c virtdir.h

Log Message:
Move source files from the reachover framework to the dist framework.


To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 src/external/bsd/iscsi/Makefile
cvs rdiff -u -r1.1 -r0 src/external/bsd/iscsi/Makefile.inc
cvs rdiff -u -r0 -r1.1 src/external/bsd/iscsi/dist/include/libkmod.h \
    src/external/bsd/iscsi/dist/include/virtdir.h
cvs rdiff -u -r0 -r1.1 src/external/bsd/iscsi/dist/src/iscsi-initiator.8 \
    src/external/bsd/iscsi/dist/src/iscsi-initiator.c \
    src/external/bsd/iscsi/dist/src/libkmod.c \
    src/external/bsd/iscsi/dist/src/virtdir.c
cvs rdiff -u -r1.1 -r0 src/external/bsd/iscsi/initiator/iscsi-initiator.8 \
    src/external/bsd/iscsi/initiator/iscsi-initiator.c \
    src/external/bsd/iscsi/initiator/libkmod.c \
    src/external/bsd/iscsi/initiator/libkmod.h \
    src/external/bsd/iscsi/initiator/virtdir.c \
    src/external/bsd/iscsi/initiator/virtdir.h

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

Modified files:

Index: src/external/bsd/iscsi/Makefile
diff -u src/external/bsd/iscsi/Makefile:1.2 src/external/bsd/iscsi/Makefile:1.3
--- src/external/bsd/iscsi/Makefile:1.2	Mon Jun 22 06:52:18 2009
+++ src/external/bsd/iscsi/Makefile	Mon Jun 22 14:44:12 2009
@@ -1,6 +1,6 @@
-# $NetBSD: Makefile,v 1.2 2009/06/22 06:52:18 agc Exp $
+# $NetBSD: Makefile,v 1.3 2009/06/22 14:44:12 agc Exp $
 
-.sinclude "${.CURDIR}/Makefile.inc"
+BINDIR=/usr/sbin
 
 SUBDIR=	lib .WAIT
 

Added files:

Index: src/external/bsd/iscsi/dist/include/libkmod.h
diff -u /dev/null src/external/bsd/iscsi/dist/include/libkmod.h:1.1
--- /dev/null	Mon Jun 22 14:44:13 2009
+++ src/external/bsd/iscsi/dist/include/libkmod.h	Mon Jun 22 14:44:12 2009
@@ -0,0 +1,63 @@
+/*	$NetBSD: libkmod.h,v 1.1 2009/06/22 14:44:12 agc Exp $	*/
+
+/*-
+ * Copyright (c) 2008 The NetBSD Foundation, Inc.
+ * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``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 FOUNDATION OR CONTRIBUTORS
+ * 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 LIBKMOD_H_
+#define LIBKMOD_H_	20090619
+
+#include <sys/module.h>
+
+#include <stdio.h>
+
+/* this struct describes the loaded modules in the kernel */
+typedef struct kernel_t {
+	size_t	 	size;	/* size of iovec array */
+	size_t		c;	/* counter during "read" operations */
+	struct iovec	iov;	/* iovecs from the modctl operation */
+} kernel_t;
+
+/* this struct describes a module */
+typedef struct kmod_t {
+	char		*name;		/* module name */
+	char		*class;		/* module class */
+	char		*source;	/* source of module loading */
+	int		 refcnt;	/* reference count */
+	unsigned	 size;		/* size of binary module */
+	char		*required;	/* any pre-reqs module has */
+} kmod_t;
+
+/* low level open, read, write ops */
+int openkmod(kernel_t *);
+int readkmod(kernel_t *, kmod_t *);
+void freekmod(kmod_t *);
+int closekmod(kernel_t *);
+
+/* high-level kmod operations */
+int kmodstat(const char *, FILE *);
+int kmodload(const char *);
+int kmodunload(const char *);
+
+#endif
Index: src/external/bsd/iscsi/dist/include/virtdir.h
diff -u /dev/null src/external/bsd/iscsi/dist/include/virtdir.h:1.1
--- /dev/null	Mon Jun 22 14:44:13 2009
+++ src/external/bsd/iscsi/dist/include/virtdir.h	Mon Jun 22 14:44:12 2009
@@ -0,0 +1,83 @@
+/*
+ * 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 FUSE_TREE_H_
+#define FUSE_TREE_H_	20070405
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <fuse.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 */
+} 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 */
+	unsigned	 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);
+int virtdir_del(virtdir_t *, const char *, size_t);
+virt_dirent_t *virtdir_find(virtdir_t *, const char *, size_t);
+virt_dirent_t *virtdir_find_tgt(virtdir_t *, const char *, size_t);
+void virtdir_drop(virtdir_t *);
+char *virtdir_rootdir(virtdir_t *);
+
+VIRTDIR *openvirtdir(virtdir_t *, const char *);
+virt_dirent_t *readvirtdir(VIRTDIR *);
+void closevirtdir(VIRTDIR *);
+
+int virtdir_offset(virtdir_t *, virt_dirent_t *);
+
+#endif

Index: src/external/bsd/iscsi/dist/src/iscsi-initiator.8
diff -u /dev/null src/external/bsd/iscsi/dist/src/iscsi-initiator.8:1.1
--- /dev/null	Mon Jun 22 14:44:13 2009
+++ src/external/bsd/iscsi/dist/src/iscsi-initiator.8	Mon Jun 22 14:44:12 2009
@@ -0,0 +1,150 @@
+.\" $NetBSD: iscsi-initiator.8,v 1.1 2009/06/22 14:44:12 agc 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.
+.\"
+.Dd September 20, 2007
+.Dt ISCSI-INITIATOR 8
+.Os
+.Sh NAME
+.Nm iscsi-initiator
+.Nd refuse-based iSCSI initiator
+.Sh SYNOPSIS
+.Nm
+.Op Fl 46bcfVv
+.Op Fl a Ar authentication-type
+.Op Fl d Ar digest-type
+.Op Fl h Ar target-hostname
+.Op Fl p Ar target-port-number
+.Op Fl t Ar target-number
+.Op Fl u Ar username
+.Ar mount_point
+.Sh DESCRIPTION
+The
+.Nm
+utility can be used to access an iSCSI target, such as
+.Xr iscsi-target 8 ,
+to access block storage which has been exported.
+Information pertaining to the target is displayed underneath
+the mount point, along with the device corresponding
+to the storage which the target exports.
+.Pp
+The various arguments are as follows:
+.Bl -tag -width Ds
+.It Fl 4
+Use an IPv4 connection to the target.
+.It Fl 6
+Use an IPv6 connection to the target.
+.It Fl a Ar authentication-type
+Use the specified authentication type when communicating with the target.
+The possible values are chap, kerberos, srp or none.
+The default value is none.
+.It Fl b
+Show the storage as a block device.
+.It Fl c
+Show the storage as a character device.
+.It Fl d Ar digest-type
+Use the specified digest type when communicating with the target.
+The possible values are header, data, both, all or none.
+The default value is none.
+.It Fl f
+Show the storage as a regular file.
+.It Fl h Ar hostname
+Connect to the iSCSI target running on the host specified as the argument.
+.It Fl p Ar port-number
+Connect to the iSCSI target running on the port specified as the argument.
+The default value is 3260.
+.It Fl t Ar target
+Connect to the number of the iSCSI target running as the argument.
+.It Fl u Ar username
+Use the specified user's credentials when logging in to the iSCSI target.
+There is no default.
+.It Fl V
+Print out the version number and then exit.
+.It Fl v
+Be verbose in operation.
+.El
+.Pp
+The
+.Xr refuse 3
+library is used to provide the file system features.
+.Pp
+The mandatory parameter is the local mount point.
+.Pp
+This iSCSI initiator presents a view of the targets underneath the
+mount point.
+Firstly, it creates a directory tree with the hostname of the target,
+and, in that directory, a virtual directory is created for each
+target name exported by the iSCSI target program.
+Within that virtual target directory, symbolic links exist for
+the hostname (for convenience),
+a textual representation of the IP address,
+the iSCSI target product name,
+the iSCSI target IQN,
+the iSCSI target vendor and version number.
+One other directory entry is presented in the virtual target
+directory, relating to the storage presented by the iSCSI target.
+This can be in the form of a regular file, which is also the
+default, a block device or a character device.
+.Pp
+Please note that the
+.Nm
+utility needs the
+.Dq puffs
+kernel module loaded via
+.Xr modload 8
+to operate.
+.Sh EXAMPLES
+.Bd -literal
+# ./iscsi-initiator -u agc iscsi-target0.alistaircrooks.co.uk /mnt
+# ls -al /mnt/iscsi-target0.alistaircrooks.co.uk/target0
+total 576
+drwxr-xr-x  2 agc  agc        512 May 11 22:24 .
+drwxr-xr-x  2 agc  agc        512 May 11 22:24 ..
+lrw-r--r--  1 agc  agc         39 May 11 22:24 hostname -\*[Gt] iscsi-target0.alistaircrooks.co.uk
+lrw-r--r--  1 agc  agc         14 May 11 22:24 ip -\*[Gt] 172.16.135.130
+lrw-r--r--  1 agc  agc         16 May 11 22:24 product -\*[Gt] NetBSD iSCSI
+-rw-r--r--  1 agc  agc  104857600 May 11 22:24 storage
+lrw-r--r--  1 agc  agc         43 May 11 22:24 targetname -\*[Gt] iqn.1994-04.org.netbsd.iscsi-target:target0
+lrw-r--r--  1 agc  agc          8 May 11 22:24 vendor -\*[Gt] NetBSD
+lrw-r--r--  1 agc  agc          4 May 11 22:24 version -\*[Gt] 0
+#
+.Ed
+.Sh SEE ALSO
+.Xr puffs 3 ,
+.Xr refuse 3 ,
+.Xr iscsi-target 8
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.Nx 5.0 .
+.Sh AUTHORS
+The
+.Nm
+utility was written by
+.An Alistair Crooks
+.Aq [email protected] .
Index: src/external/bsd/iscsi/dist/src/iscsi-initiator.c
diff -u /dev/null src/external/bsd/iscsi/dist/src/iscsi-initiator.c:1.1
--- /dev/null	Mon Jun 22 14:44:13 2009
+++ src/external/bsd/iscsi/dist/src/iscsi-initiator.c	Mon Jun 22 14:44:12 2009
@@ -0,0 +1,715 @@
+/*
+ * 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>
+
+#define FUSE_USE_VERSION	26
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <fuse.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define EXTERN
+
+#include "scsi_cmd_codes.h"
+#include "iscsi.h"
+#include "initiator.h"
+#include "tests.h"
+
+#include "virtdir.h"
+
+#if defined(__NetBSD__) && defined(USE_LIBKMOD)
+#include "libkmod.h"
+#endif
+
+#include "defs.h"
+
+static int		 verbose; /* how chatty are we? */
+
+static virtdir_t	 iscsi;
+
+enum {
+	VendorLen = 8,
+	ProductLen = 16,
+	VersionLen = 4,
+
+	SGsize = 131072
+};
+
+
+/* this struct keeps information on the target */
+typedef struct targetinfo_t {
+	 char			*host;		/* resolvable host name */
+	 char			*ip;		/* textual IP address */
+	 char			*targetname;	/* name of iSCSI target prog */
+	 char			*stargetname;   /* short name of the target */ 
+	 uint64_t		 target;	/* target number */
+	 uint32_t		 lun;		/* LUN number */
+	 uint32_t		 lbac;		/* number of LBAs */
+	 uint32_t		 blocksize;	/* size of device blocks */
+	 uint32_t		 devicetype;	/* SCSI device type */
+	 char			 vendor[VendorLen + 1];
+	 					/* device vendor information */
+	 char			 product[ProductLen + 1];
+	 					/* device product information */
+	 char			 version[VersionLen + 1];
+	 					/* device version information */
+	 char			*serial;	/* unit serial number */
+} targetinfo_t;
+
+DEFINE_ARRAY(targetv_t, targetinfo_t);
+
+static targetv_t	tv;	/* target vector of targetinfo_t structs */
+
+/* iqns and target addresses are returned as pairs in this dynamic array */
+static strv_t		all_targets;
+
+/* Small Target Info... */
+typedef struct sti_t {
+	struct stat             st;		/* normal stat info */
+	uint64_t                target;		/* cached target number, so we don't have an expensive pathname-based lookup */
+} sti_t;
+
+#ifndef __UNCONST
+#define __UNCONST(x)	(x)
+#endif
+
+/* read the capacity (maximum LBA and blocksize) from the target */
+int 
+read_capacity(uint64_t target, uint32_t lun, uint32_t *maxlba, uint32_t *blocklen)
+{
+	iscsi_scsi_cmd_args_t	args;
+	initiator_cmd_t		cmd;
+	uint8_t			data[8];
+	uint8_t			cdb[16];
+
+	(void) memset(cdb, 0x0, sizeof(cdb));
+	cdb[0] = READ_CAPACITY;
+	cdb[1] = lun << 5;
+
+	(void) memset(&args, 0x0, sizeof(args));
+	args.recv_data = data;
+	args.input = 1;
+	args.lun = lun;
+	args.trans_len = 8;
+	args.cdb = cdb;
+
+	(void) memset(&cmd, 0, sizeof(initiator_cmd_t));
+
+	cmd.isid = target;
+	cmd.type = ISCSI_SCSI_CMD;
+	cmd.ptr = &args;
+
+	if (initiator_command(&cmd) != 0) {
+		iscsi_trace_error(__FILE__, __LINE__, "initiator_command() failed\n");
+		return -1;
+	}
+	if (args.status) {
+		iscsi_trace_error(__FILE__, __LINE__, "READ_CAPACITY failed (status %#x)\n", args.status);
+		return -1;
+	}
+	*maxlba = ISCSI_NTOHL(*((uint32_t *) (data)));
+	*blocklen = ISCSI_NTOHL(*((uint32_t *) (data + 4)));
+	if (*maxlba == 0) {
+		iscsi_trace_error(__FILE__, __LINE__, "Device returned Maximum LBA of zero\n");
+		return -1;
+	}
+	if (*blocklen % 2) {
+		iscsi_trace_error(__FILE__, __LINE__, "Device returned strange block len: %u\n", *blocklen);
+		return -1;
+	}
+	return 0;
+}
+
+/* send inquiry command to the target, to get it to identify itself */
+static int 
+inquiry(uint64_t target, uint32_t lun, uint8_t type, uint8_t inquire, uint8_t *data)
+{
+	iscsi_scsi_cmd_args_t	args;
+	initiator_cmd_t		cmd;
+	uint8_t			cdb[16];
+
+	(void) memset(cdb, 0x0, sizeof(cdb));
+	cdb[0] = INQUIRY;
+	cdb[1] = type | (lun << 5);
+	cdb[2] = inquire;
+	cdb[4] = 256 - 1;
+
+	(void) memset(&args, 0x0, sizeof(args));
+	args.input = 1;
+	args.trans_len = 256;
+	args.cdb = cdb;
+	args.lun = lun;
+	args.recv_data = data;
+	(void) memset(&cmd, 0x0, sizeof(cmd));
+	cmd.isid = target;
+	cmd.type = ISCSI_SCSI_CMD;
+	cmd.ptr = &args;
+
+	if (initiator_command(&cmd) != 0) {
+		iscsi_trace_error(__FILE__, __LINE__, "initiator_command() failed\n");
+		return -1;
+	}
+	if (args.status) {
+		iscsi_trace_error(__FILE__, __LINE__, "INQUIRY failed (status %#x)\n", args.status);
+		return -1;
+	}
+
+	return 0;
+}
+
+/* read or write a single block of information */
+static int 
+blockop(uint64_t target, uint32_t lun, uint32_t lba, uint32_t len,
+	      uint32_t blocklen, uint8_t *data, int writing)
+{
+	iscsi_scsi_cmd_args_t	args;
+	initiator_cmd_t		cmd;
+	uint16_t   		readlen;
+	uint8_t   		cdb[16];
+
+	/* Build CDB */
+	(void) memset(cdb, 0, 16);
+	cdb[0] = (writing) ? WRITE_10 : READ_10;
+	cdb[1] = lun << 5;
+	readlen = (uint16_t) len;
+	lba2cdb(cdb, &lba, &readlen);
+
+	/* Build SCSI command */
+	(void) memset(&args, 0x0, sizeof(args));
+	if (writing) {
+		args.send_data = data;
+		args.output = 1;
+	} else {
+		args.recv_data = data;
+		args.input = 1;
+	}
+	args.lun = lun;
+	args.trans_len = len*blocklen;
+	args.length = len*blocklen;
+	args.cdb = cdb;
+	(void) memset(&cmd, 0, sizeof(initiator_cmd_t));
+	cmd.isid = target;
+	cmd.type = ISCSI_SCSI_CMD;
+	cmd.ptr = &args;
+	/* Execute iSCSI command */
+	if (initiator_command(&cmd) != 0) {
+		iscsi_trace_error(__FILE__, __LINE__, "initiator_command() failed\n");
+		return -1;
+	}
+
+	if (args.status) {
+		iscsi_trace_error(__FILE__, __LINE__, "scsi_command() failed (status %#x)\n", args.status);
+		return -1;
+	}
+	return 0;
+}
+
+/* perform a scatter/gather block operation */
+static int 
+sgblockop(uint64_t target, uint32_t lun, uint32_t lba, uint32_t len,
+	      uint32_t blocklen, uint8_t *data, int sglen, int writing)
+{
+	iscsi_scsi_cmd_args_t	args;
+	initiator_cmd_t		cmd;
+	uint16_t		readlen;
+	uint8_t			cdb[16];
+
+	/* Build CDB */
+
+	(void) memset(cdb, 0, 16);
+	cdb[0] = (writing) ? WRITE_10 : READ_10;
+	cdb[1] = lun << 5;
+	readlen = (uint16_t) len;
+	lba2cdb(cdb, &lba, &readlen);
+
+	/* Build iSCSI command */
+	(void) memset(&args, 0x0, sizeof(args));
+	args.lun = lun;
+	args.output = (writing) ? 1 : 0;
+	args.input = (writing) ? 0 : 1;
+	args.trans_len = len * blocklen;
+	args.length = len * blocklen;
+	args.send_data = (writing) ? data : NULL;
+	args.send_sg_len = (writing) ? sglen : 0;
+	args.recv_data = (writing) ? NULL : data;
+	args.recv_sg_len = (writing) ? 0 : sglen;
+	args.cdb = cdb;
+	memset(&cmd, 0, sizeof(initiator_cmd_t));
+	cmd.isid = target;
+	cmd.ptr = &args;
+	cmd.type = ISCSI_SCSI_CMD;
+
+	/* Execute iSCSI command */
+
+	if (initiator_command(&cmd) != 0) {
+		iscsi_trace_error(__FILE__, __LINE__, "initiator_command() failed\n");
+		return -1;
+	}
+	if (args.status) {
+		iscsi_trace_error(__FILE__, __LINE__, "scsi_command() failed (status %#x)\n", args.status);
+		return -1;
+	}
+	return 0;
+}
+
+/* read info from the target - method depends on size of data being read */
+static int 
+targetop(uint32_t t, uint64_t offset, uint32_t length, uint32_t request, char *buf, int writing)
+{
+	struct iovec 	*iov;
+	uint32_t	 ioc;
+	uint32_t	 i;
+	int		 req_len;
+
+	if (request > SGsize) {
+		/* split up request into blocksize chunks */
+		ioc = request / SGsize;
+		if ((ioc * SGsize) < request)
+			ioc++;
+		if ((iov = iscsi_malloc(ioc * sizeof(*iov))) == NULL) {
+			iscsi_trace_error(__FILE__, __LINE__, "out of memory\n");
+			return -1;
+		}
+
+		for (i = 0 ; i < ioc ; i++) {
+			iov[i].iov_base = &buf[i * SGsize];
+			if (i == (ioc - 1)) { /* last one */
+				iov[i].iov_len = request - (i * SGsize);
+			} else {
+				iov[i].iov_len = SGsize;
+			}
+		}
+
+		if (sgblockop(tv.v[t].target, tv.v[t].lun, offset / tv.v[t].blocksize, (length / tv.v[t].blocksize), tv.v[t].blocksize, (uint8_t *) iov, ioc, writing) != 0) {
+			iscsi_free(iov);
+			iscsi_trace_error(__FILE__, __LINE__, "read_10() failed\n");
+			return -1;
+		}
+		iscsi_free(iov);
+	} else {
+		req_len = length / tv.v[t].blocksize;
+		if ((req_len * tv.v[t].blocksize) < length)
+			req_len++;
+		if (blockop(tv.v[t].target, tv.v[t].lun, offset / tv.v[t].blocksize, 
+				req_len, tv.v[t].blocksize, (uint8_t *) buf, writing) != 0) {
+			iscsi_trace_error(__FILE__, __LINE__, "read_10() failed\n");
+			return -1;
+		}
+	}
+	return 0;
+}
+
+
+/****************************************************************************/
+
+/* perform the stat operation */
+/* if this is the root, then just synthesise the data */
+/* otherwise, retrieve the data, and be sure to fill in the size */
+static int 
+iscsifs_getattr(const char *path, struct stat *st)
+{
+	virt_dirent_t	*ep;
+	sti_t		*p;
+
+	if (strcmp(path, "/") == 0) {
+		(void) memset(st, 0x0, sizeof(*st));
+		st->st_mode = S_IFDIR | 0755;
+		st->st_nlink = 2;
+		return 0;
+	}
+	if ((ep = virtdir_find(&iscsi, path, strlen(path))) == NULL) {
+		return -ENOENT;
+	}
+	switch(ep->type) {
+	case 'b':
+		(void) memcpy(st, &iscsi.file, sizeof(*st));
+		st->st_mode = (S_IFBLK | 0644);
+		break;
+	case 'c':
+		(void) memcpy(st, &iscsi.file, sizeof(*st));
+		st->st_mode = (S_IFCHR | 0644);
+		break;
+	case 'd':
+		(void) memcpy(st, &iscsi.dir, sizeof(*st));
+		break;
+	case 'f':
+		(void) memcpy(st, &iscsi.file, sizeof(*st));
+		p = (sti_t *) ep->tgt;
+		st->st_size = p->st.st_size;
+		break;
+	case 'l':
+		(void) memcpy(st, &iscsi.lnk, sizeof(*st));
+		st->st_size = ep->tgtlen;
+		break;
+	default:
+		warn("unknown directory type `%c'", ep->type);
+		return -ENOENT;
+	}
+	st->st_ino = ep->ino;
+	return 0;
+}
+
+/* readdir operation */
+static int 
+iscsifs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
+	      off_t offset, struct fuse_file_info * fi)
+{
+	virt_dirent_t	*dp;
+	VIRTDIR		*dirp;
+
+	if ((dirp = openvirtdir(&iscsi, path)) == NULL) {
+		return 0;
+	}
+	filler(buf, ".", NULL, 0);
+	filler(buf, "..", NULL, 0);
+	while ((dp = readvirtdir(dirp)) != NULL) {
+		filler(buf, dp->d_name, NULL, 0);
+	}
+	closevirtdir(dirp);
+	return 0;
+}
+
+/* open the file in the file system */
+static int 
+iscsifs_open(const char *path, struct fuse_file_info *fi)
+{
+	virt_dirent_t	*ep;
+	const char	*slash;
+
+	if ((ep = virtdir_find(&iscsi, path, strlen(path))) == NULL) {
+		return -ENOENT;
+	}
+	/* check path is the correct one */
+	if ((slash = strrchr(path, '/')) == NULL) {
+		slash = path;
+	} else {
+		slash += 1;
+	}
+	if (strcmp(slash, "storage") != 0) {
+		return -ENOENT;
+	}
+	return 0;
+}
+
+/* read the storage from the iSCSI target */
+static int 
+iscsifs_read(const char *path, char *buf, size_t size, off_t offset,
+	   struct fuse_file_info * fi)
+{
+	virt_dirent_t	*ep;
+	uint64_t target;
+	sti_t *p;
+
+	if ((ep = virtdir_find(&iscsi, path, strlen(path))) == NULL) {
+		return -ENOENT;
+	}
+
+	p = (sti_t *)ep->tgt;
+	target = p->target;
+
+	if (targetop(target, offset, size, size, buf, 0) < 0) {
+		return -EPERM;
+	}
+	return size;
+}
+
+/* write the file's contents to the file system */
+static int 
+iscsifs_write(const char *path, const char *buf, size_t size, off_t offset,
+	   struct fuse_file_info * fi)
+{
+	virt_dirent_t	*ep;
+        uint64_t	 target;   
+        sti_t		*p;
+
+	if ((ep = virtdir_find(&iscsi, path, strlen(path))) == NULL) {
+		return -ENOENT;
+	}
+	
+	p = (sti_t *)ep->tgt;
+	target = p->target;
+
+	if (targetop(target, offset, size, size, __UNCONST(buf), 1) < 0) {
+		return -EPERM;
+	}
+	return size;
+}
+
+/* fill in the statvfs struct */
+static int
+iscsifs_statfs(const char *path, struct statvfs *st)
+{
+	(void) memset(st, 0x0, sizeof(*st));
+	return 0;
+}
+
+/* read the symbolic link */
+static int
+iscsifs_readlink(const char *path, char *buf, size_t size)
+{
+	virt_dirent_t	*ep;
+
+	if ((ep = virtdir_find(&iscsi, path, strlen(path))) == NULL) {
+		return -ENOENT;
+	}
+	if (ep->tgt == NULL) {
+		return -ENOENT;
+	}
+	(void) strlcpy(buf, ep->tgt, size);
+	return 0;
+}
+
+/* operations struct */
+static struct fuse_operations iscsiops = {
+	.getattr = iscsifs_getattr,
+	.readlink = iscsifs_readlink,
+	.readdir = iscsifs_readdir,
+	.open = iscsifs_open,
+	.read = iscsifs_read,
+	.write = iscsifs_write,
+	.statfs = iscsifs_statfs
+};
+
+int 
+main(int argc, char **argv)
+{
+	initiator_target_t	tinfo;
+	unsigned		u;
+	uint32_t		lbac;
+	uint32_t		blocksize;
+	uint8_t			data[256];
+	sti_t			sti;
+	char			hostname[1024];
+	char			name[1024];
+	char			*colon;
+	char		       *host;
+	char		       *user;
+	int			address_family;
+	char			devtype;
+	int			port;
+	int             	target = -1;
+        int			digest_type;
+	int			discover;
+        int			mutual_auth;
+        int			auth_type;
+	int			cc;
+	int			i;
+
+	(void) memset(&tinfo, 0x0, sizeof(tinfo));
+	user = NULL;
+	(void) gethostname(host = hostname, sizeof(hostname));
+	digest_type = DigestNone;
+	auth_type = AuthNone;
+	address_family = ISCSI_UNSPEC;
+	port = ISCSI_PORT;
+	mutual_auth = 0;
+	discover = 0;
+	(void) stat("/etc/hosts", &sti.st);
+	devtype = 'f';
+	while ((i = getopt(argc, argv, "46a:bcd:Dfh:p:t:u:vV")) != -1) {
+		switch(i) {
+		case '4':
+			address_family = ISCSI_IPv4;
+			break;
+		case '6':
+			address_family = ISCSI_IPv6;
+			break;
+		case 'a':
+			if (strcasecmp(optarg, "chap") == 0) {
+				auth_type = AuthCHAP;
+			} else if (strcasecmp(optarg, "kerberos") == 0) {
+				auth_type = AuthKerberos;
+			} else if (strcasecmp(optarg, "srp") == 0) {
+				auth_type = AuthSRP;
+			}
+			break;
+		case 'b':
+			devtype = 'b';
+			break;
+		case 'c':
+			devtype = 'c';
+			break;
+		case 'd':
+			if (strcasecmp(optarg, "header") == 0) {
+				digest_type = DigestHeader;
+			} else if (strcasecmp(optarg, "data") == 0) {
+				digest_type = DigestData;
+			} else if (strcasecmp(optarg, "both") == 0 || strcasecmp(optarg, "all") == 0) {
+				digest_type = (DigestHeader | DigestData);
+			}
+			break;
+		case 'D':
+			discover = 1;
+			break;
+		case 'f':
+			devtype = 'f';
+			break;
+		case 'h':
+			host = optarg;
+			break;
+		case 'p':
+			port = atoi(optarg);
+			break;
+		case 't':
+			target = atoi(optarg);
+			break;
+		case 'u':
+			user = optarg;
+			break;
+		case 'V':
+			(void) printf("\"%s\" %s\nPlease send all bug reports to %s\n", PACKAGE_NAME, PACKAGE_VERSION, PACKAGE_BUGREPORT);
+			exit(EXIT_SUCCESS);
+			/* NOTREACHED */
+		case 'v':
+			verbose += 1;
+			break;
+		default:
+			(void) fprintf(stderr, "%s: unknown option `%c'", *argv, i);
+		}
+	}
+	if (user == NULL) {
+		iscsi_trace_error(__FILE__, __LINE__, "user must be specified with -u");
+		exit(EXIT_FAILURE);
+	}
+
+	if (initiator_init(host, port, address_family, user, auth_type, mutual_auth, digest_type) == -1) {
+		iscsi_trace_error(__FILE__, __LINE__, "initiator_init() failed\n");
+		exit(EXIT_FAILURE);
+	}
+
+
+        if (initiator_discover(host, 0, 0) < 0) {
+                printf("initiator_discover() in discover failed\n");
+		exit(EXIT_FAILURE);
+	}
+
+        if (initiator_get_targets(0,&all_targets) == -1) {
+ 		iscsi_trace_error(__FILE__, __LINE__, "initiator_get_targets() failed\n");
+               	exit(EXIT_FAILURE);
+	}
+
+
+        if (discover) {
+		printf("Targets available from host %s:\n",host);
+		for (u = 0; u < all_targets.c ; u += 2) {
+			printf("%s at %s\n", all_targets.v[u],
+				all_targets.v[u + 1]);
+		}
+
+                exit(EXIT_SUCCESS);
+        }
+
+	if (all_targets.c/2 > CONFIG_INITIATOR_NUM_TARGETS) {
+		(void) fprintf(stderr, "CONFIG_INITIATOR_NUM_TARGETS in initiator.h is too small.  %d targets available, only %d configurable.\n", all_targets.c/2, CONFIG_INITIATOR_NUM_TARGETS);
+		(void) fprintf(stderr, "Truncating number of targets to %d.\n", CONFIG_INITIATOR_NUM_TARGETS);
+		all_targets.c = CONFIG_INITIATOR_NUM_TARGETS;
+	}
+
+	sti.st.st_ino = 0x15c51;
+
+#if defined(__NetBSD__) && defined(USE_LIBKMOD)
+	/* check that the puffs module is loaded on NetBSD */
+	if (kmodstat("puffs", NULL) == 0 && !kmodload("puffs")) {
+		(void) fprintf(stderr, "initiator: can't load puffs module\n");
+	}
+#endif
+
+	for (u = 0 ; u < all_targets.c / 2 ; u++) {
+		ALLOC(targetinfo_t, tv.v, tv.size, tv.c, 10, 10, "iscsifs",
+				exit(EXIT_FAILURE));
+
+		initiator_set_target_name(u, all_targets.v[u * 2]);
+
+		if (initiator_discover(host, u, 0) < 0) {
+			printf("initiator_discover() failed\n");
+			break;
+		}
+
+		get_target_info(u, &tinfo);
+		if ((colon = strrchr(tinfo.TargetName, ':')) == NULL) {
+			colon = tinfo.TargetName;
+		} else {
+			colon += 1;
+		}
+
+		/* stuff size into st.st_size */
+		(void) read_capacity(u, 0, &lbac, &blocksize);
+		sti.st.st_size = ((uint64_t)lbac + 1) * blocksize;
+		sti.target = u;
+
+		tv.v[tv.c].host = strdup(tinfo.name);
+		tv.v[tv.c].ip = strdup(tinfo.ip);
+		tv.v[tv.c].targetname = strdup(tinfo.TargetName);
+		tv.v[tv.c].stargetname = strdup(colon);
+		tv.v[tv.c].target = u;
+		tv.v[tv.c].lun = 0;
+		tv.v[tv.c].lbac = lbac;
+		tv.v[tv.c].blocksize = blocksize;
+
+		/* get iSCSI target information */
+		(void) memset(data, 0x0, sizeof(data));
+		inquiry(u, 0, 0, 0, data);
+		tv.v[tv.c].devicetype = (data[0] & 0x1f);
+		(void) memcpy(tv.v[tv.c].vendor, &data[8], VendorLen);
+		(void) memcpy(tv.v[tv.c].product, &data[8 + VendorLen], ProductLen);
+		(void) memcpy(tv.v[tv.c].version, &data[8 + VendorLen + ProductLen], VersionLen);
+		(void) memset(data, 0x0, sizeof(data));
+		inquiry(u, 0, INQUIRY_EVPD_BIT, INQUIRY_UNIT_SERIAL_NUMBER_VPD, data);
+		tv.v[tv.c].serial = strdup((char *)&data[4]);
+
+		cc = snprintf(name, sizeof(name), "/%s/%s", host, colon);
+		virtdir_add(&iscsi, name, cc, 'd', name, cc);
+		cc = snprintf(name, sizeof(name), "/%s/%s/storage", host, colon);
+		virtdir_add(&iscsi, name, cc, devtype, (void *)&sti, sizeof(sti));
+		cc = snprintf(name, sizeof(name), "/%s/%s/hostname", host, colon);
+		virtdir_add(&iscsi, name, cc, 'l', tinfo.name, strlen(tinfo.name));
+		cc = snprintf(name, sizeof(name), "/%s/%s/ip", host, colon);
+		virtdir_add(&iscsi, name, cc, 'l', tinfo.ip, strlen(tinfo.ip));
+		cc = snprintf(name, sizeof(name), "/%s/%s/targetname", host, colon);
+		virtdir_add(&iscsi, name, cc, 'l', tinfo.TargetName, strlen(tinfo.TargetName));
+		cc = snprintf(name, sizeof(name), "/%s/%s/vendor", host, colon);
+		virtdir_add(&iscsi, name, cc, 'l', tv.v[tv.c].vendor, strlen(tv.v[tv.c].vendor));
+		cc = snprintf(name, sizeof(name), "/%s/%s/product", host, colon);
+		virtdir_add(&iscsi, name, cc, 'l', tv.v[tv.c].product, strlen(tv.v[tv.c].product));
+		cc = snprintf(name, sizeof(name), "/%s/%s/version", host, colon);
+		virtdir_add(&iscsi, name, cc, 'l', tv.v[tv.c].version, strlen(tv.v[tv.c].version));
+		if (tv.v[tv.c].serial[0] && tv.v[tv.c].serial[0] != ' ') {
+			cc = snprintf(name, sizeof(name), "/%s/%s/serial", host, colon);
+			virtdir_add(&iscsi, name, cc, 'l', tv.v[tv.c].serial, strlen(tv.v[tv.c].serial));
+		}
+
+
+		tv.c += 1;
+	}
+	return fuse_main(argc - optind, argv + optind, &iscsiops, NULL);
+}
Index: src/external/bsd/iscsi/dist/src/libkmod.c
diff -u /dev/null src/external/bsd/iscsi/dist/src/libkmod.c:1.1
--- /dev/null	Mon Jun 22 14:44:13 2009
+++ src/external/bsd/iscsi/dist/src/libkmod.c	Mon Jun 22 14:44:12 2009
@@ -0,0 +1,219 @@
+/*	$NetBSD: libkmod.c,v 1.1 2009/06/22 14:44:12 agc Exp $	*/
+
+/*-
+ * Copyright (c) 2008 The NetBSD Foundation, Inc.
+ * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``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 FOUNDATION OR CONTRIBUTORS
+ * 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>
+#ifndef lint
+__RCSID("$NetBSD: libkmod.c,v 1.1 2009/06/22 14:44:12 agc Exp $");
+#endif /* !lint */
+
+#include <sys/module.h>
+
+#include <prop/proplib.h>
+
+#include <assert.h>
+#include <err.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "libkmod.h"
+
+#ifdef USE_LIBKMOD
+
+static const char *classes[] = {
+	"any",
+	"misc",
+	"vfs",
+	"driver",
+	"exec",
+};
+
+static const char *sources[] = {
+	"builtin",
+	"boot",
+	"filesys",
+};
+
+/* comparison routine for qsort */
+static int
+modcmp(const void *a, const void *b)
+{
+	const modstat_t *msa, *msb;
+
+	msa = a;
+	msb = b;
+	return strcmp(msa->ms_name, msb->ms_name);
+}
+
+/* function which "opens" a module */
+int
+openkmod(kernel_t *kernel)
+{
+	kernel->size = 4096;
+	for (;;) {
+		kernel->iov.iov_base = malloc(kernel->size);
+		kernel->iov.iov_len = kernel->size;
+		if (modctl(MODCTL_STAT, &kernel->iov)) {
+			warn("modctl(MODCTL_STAT)");
+			return 0;
+		}
+		if (kernel->size >= kernel->iov.iov_len) {
+			break;
+		}
+		free(kernel->iov.iov_base);
+		kernel->size = kernel->iov.iov_len;
+	}
+	kernel->size = kernel->iov.iov_len / sizeof(modstat_t);
+	qsort(kernel->iov.iov_base, kernel->size, sizeof(modstat_t), modcmp);
+	return 1;
+}
+
+/* return details on the module */
+int
+readkmod(kernel_t *kernel, kmod_t *module)
+{
+	modstat_t *ms;
+
+	if (kernel->c * sizeof(*ms) >= kernel->iov.iov_len) {
+		return 0;
+	}
+	ms = kernel->iov.iov_base;
+	ms += kernel->c++;
+	(void) memset(module, 0x0, sizeof(*module));
+	module->name = strdup(ms->ms_name);
+	module->class = strdup(classes[ms->ms_class]);
+	module->source = strdup(sources[ms->ms_source]);
+	module->refcnt = ms->ms_refcnt;
+	module->size = ms->ms_size;
+	if (ms->ms_required[0]) {
+		module->required = strdup(ms->ms_required);
+	}
+	return 1;
+}
+
+/* free up all resources allocated in a module read */
+void
+freekmod(kmod_t *module)
+{
+	(void) free(module->name);
+	(void) free(module->class);
+	(void) free(module->source);
+	if (module->required) {
+		(void) free(module->required);
+	}
+}
+
+/* "close" the module */
+int
+closekmod(kernel_t *kernel)
+{
+	(void) free(kernel->iov.iov_base);
+	return 1;
+}
+
+/* do the modstat operation */
+int
+kmodstat(const char *modname, FILE *fp)
+{
+	kernel_t	kernel;
+	kmod_t		module;
+	int		modc;
+
+	(void) memset(&kernel, 0x0, sizeof(kernel));
+	(void) memset(&module, 0x0, sizeof(module));
+	if (!openkmod(&kernel)) {
+		(void) fprintf(stderr, "can't read kernel modules\n");
+		return 0;
+	}
+	for (modc = 0 ; readkmod(&kernel, &module) ; ) {
+		if (modname == NULL || strcmp(modname, module.name) == 0) {
+			if (modc++ == 0) {
+				if (fp) {
+					(void) fprintf(fp,
+						"NAME\t\tCLASS\tSOURCE\tREFS"
+						"\tSIZE\tREQUIRES\n");
+				}
+			}
+			if (fp) {
+				(void) fprintf(fp, "%-16s%s\t%s\t%d\t%u\t%s\n",
+				module.name,
+				module.class,
+				module.source,
+				module.refcnt,
+				module.size,
+				(module.required) ? module.required : "-");
+			}
+			freekmod(&module);
+		}
+	}
+	(void) closekmod(&kernel);
+	return modc;
+}
+
+/* load the named module into the kernel */
+int
+kmodload(const char *module)
+{
+	prop_dictionary_t	 props;
+	modctl_load_t		 cmdargs;
+	char			*propsstr;
+
+	props = prop_dictionary_create();
+
+	propsstr = prop_dictionary_externalize(props);
+	if (propsstr == NULL) {
+		(void) fprintf(stderr, "Failed to process properties");
+		return 0;
+	}
+
+	cmdargs.ml_filename = module;
+	cmdargs.ml_flags = 0;
+	cmdargs.ml_props = propsstr;
+	cmdargs.ml_propslen = strlen(propsstr);
+
+	if (modctl(MODCTL_LOAD, &cmdargs)) {
+		(void) fprintf(stderr, "modctl failure\n");
+		return 0;
+	}
+
+	(void) free(propsstr);
+	prop_object_release(props);
+
+	return 1;
+}
+
+/* and unload the module from the kernel */
+int
+kmodunload(const char *name)
+{
+	return modctl(MODCTL_UNLOAD, __UNCONST(name)) == 0;
+}
+
+#endif /* USE_LIBKMOD */
Index: src/external/bsd/iscsi/dist/src/virtdir.c
diff -u /dev/null src/external/bsd/iscsi/dist/src/virtdir.c:1.1
--- /dev/null	Mon Jun 22 14:44:13 2009
+++ src/external/bsd/iscsi/dist/src/virtdir.c	Mon Jun 22 14:44:12 2009
@@ -0,0 +1,332 @@
+/*
+ * 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>
+
+#define FUSE_USE_VERSION	26
+
+#include <fuse.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);
+		}
+		*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 && (unsigned)(pp - path) < pathsize - 1 &&
+	     (unsigned)(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)
+{
+	struct stat	st;
+	char		path[MAXPATHLEN];
+	int		pathlen;
+
+	if (tp->v == NULL) {
+		(void) stat(".", &st);
+		virtdir_init(tp, NULL, &st, &st, &st);
+	}
+	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;
+	if (tgt != NULL) {
+		tp->v[tp->c].tgtlen = tgtlen;
+		tp->v[tp->c].tgt = strnsave(tgt, tgtlen);
+	}
+	tp->c += 1;
+	qsort(tp->v, tp->c, sizeof(tp->v[0]), compare);
+	mkdirs(tp, path, pathlen);
+	return 1;
+}
+
+/* delete an entry from the tree */
+int
+virtdir_del(virtdir_t *tp, const char *name, size_t size)
+{
+	virt_dirent_t	*ep;
+	unsigned	 i;
+
+	if ((ep = virtdir_find(tp, name, size)) == NULL) {
+		return 0;
+	}
+	i = (int)(ep - tp->v);
+	for (tp->c -= 1 ; i < tp->c ; i++) {
+		tp->v[i] = tp->v[i + 1];
+	}
+	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);
+}
+
+/* find a target in the tree -- not quick! */
+virt_dirent_t *
+virtdir_find_tgt(virtdir_t *tp, const char *tgt, size_t tgtlen)
+{
+	/* we don't need no stinking binary searches */
+	unsigned	i;
+	char		path[MAXPATHLEN];
+
+	(void) normalise(tgt, tgtlen, path, sizeof(path));
+	for (i = 0 ; i < tp->c ; i++) {
+		if (tp->v[i].tgt && strcmp(tp->v[i].tgt, path) == 0) {
+			return &tp->v[i];
+		}
+	}
+	return NULL;
+}
+
+/* kill all of the space allocated to the tree */
+void
+virtdir_drop(virtdir_t *tp)
+{
+	unsigned	i;
+
+	for (i = 0 ; i < tp->c ; i++) {
+		FREE(tp->v[i].name);
+		if (tp->v[i].tgt) {
+			FREE(tp->v[i].tgt);
+		}
+	}
+	FREE(tp->v);
+}
+
+/* return the value of the root directory of the tree */
+char *
+virtdir_rootdir(virtdir_t *tp)
+{
+	return tp->rootdir;
+}
+
+#ifdef VIRTDIR_DEBUG
+static void
+ptree(virtdir_t * tp)
+{
+	int	i;
+
+	for (i = 0 ; i < tp->c ; i++) {
+		printf("%s, tgt %s\n", tp->v[i].name, tp->v[i].tgt);
+	}
+}
+#endif
+
+#ifdef VIRTDIR_DEBUG
+int
+main(int argc, char **argv)
+{
+	virt_dirent_t	*tp;
+	virtdir_t		 t;
+	struct stat		 st;
+
+	(void) memset(&t, 0x0, sizeof(t));
+	stat(".", &st);
+	virtdir_add(&t, ".", 1, 'd', NULL, 0);
+	stat("..", &st);
+	virtdir_add(&t, "..", 2, 'd', NULL, 0);
+	st.st_mode = S_IFREG | 0644;
+	virtdir_add(&t, "file1", 5, 'f', NULL, 0);
+	ptree(&t);
+	virtdir_add(&t, "file2", 5, 'f', NULL, 0);
+	virtdir_add(&t, "file0", 5, 'f', NULL, 0);
+	virtdir_add(&t, "abcde", 5, 'f', NULL, 0);
+	virtdir_add(&t, "bcdef", 5, 'f', NULL, 0);
+	virtdir_add(&t, "a", 1, 'f', NULL, 0);
+	ptree(&t);
+	if ((tp = virtdir_find(&t, "a", 1)) == NULL) {
+		printf("borked2\n");
+	} else {
+		printf("a found\n");
+	}
+	virtdir_drop(&t);
+	exit(EXIT_SUCCESS);
+}
+#endif

Reply via email to