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