summaryrefslogtreecommitdiff
path: root/usr/src/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd')
-rw-r--r--usr/src/cmd/stmfadm/stmfadm.c3514
-rw-r--r--usr/src/cmd/stmfadm/stmfadm.h73
-rw-r--r--usr/src/cmd/stmfsvc/stmf.xml119
-rw-r--r--usr/src/cmd/stmfsvc/stmfsvc.c307
4 files changed, 4013 insertions, 0 deletions
diff --git a/usr/src/cmd/stmfadm/stmfadm.c b/usr/src/cmd/stmfadm/stmfadm.c
new file mode 100644
index 0000000..0c98614
--- /dev/null
+++ b/usr/src/cmd/stmfadm/stmfadm.c
@@ -0,0 +1,3514 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ * Copyright 2012 Milan Jurik. All rights reserved.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <strings.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <wchar.h>
+#include <libintl.h>
+#include <errno.h>
+#include <time.h>
+#include <string.h>
+#include <assert.h>
+#include <getopt.h>
+#include <cmdparse.h>
+#include <stmfadm.h>
+#include <libstmf.h>
+#include <signal.h>
+#include <pthread.h>
+#include <locale.h>
+
+static int addHostGroupMemberFunc(int, char **, cmdOptions_t *, void *);
+static int addTargetGroupMemberFunc(int, char **, cmdOptions_t *, void *);
+static int addViewFunc(int, char **, cmdOptions_t *, void *);
+static int createHostGroupFunc(int, char **, cmdOptions_t *, void *);
+static int createLuFunc(int, char **, cmdOptions_t *, void *);
+static int modifyLuFunc(int, char **, cmdOptions_t *, void *);
+static int importLuFunc(int, char **, cmdOptions_t *, void *);
+static int deleteLuFunc(int, char **, cmdOptions_t *, void *);
+static int createTargetGroupFunc(int, char **, cmdOptions_t *, void *);
+static int deleteHostGroupFunc(int, char **, cmdOptions_t *, void *);
+static int deleteTargetGroupFunc(int, char **, cmdOptions_t *, void *);
+static int listLuFunc(int, char **, cmdOptions_t *, void *);
+static int listTargetFunc(int, char **, cmdOptions_t *, void *);
+static int listViewFunc(int, char **, cmdOptions_t *, void *);
+static int listHostGroupFunc(int, char **, cmdOptions_t *, void *);
+static int listStateFunc(int, char **, cmdOptions_t *, void *);
+static int listTargetGroupFunc(int, char **, cmdOptions_t *, void *);
+static int offlineTargetFunc(int, char **, cmdOptions_t *, void *);
+static int offlineLuFunc(int, char **, cmdOptions_t *, void *);
+static int onlineTargetFunc(int, char **, cmdOptions_t *, void *);
+static int onlineLuFunc(int, char **, cmdOptions_t *, void *);
+static int onlineOfflineTarget(char *, int);
+static int onlineOfflineLu(char *, int);
+static int removeHostGroupMemberFunc(int, char **, cmdOptions_t *, void *);
+static int removeTargetGroupMemberFunc(int, char **, cmdOptions_t *, void *);
+static int callModify(char *, stmfGuid *, uint32_t, const char *, const char *);
+static int removeViewFunc(int, char **, cmdOptions_t *, void *);
+static char *getExecBasename(char *);
+static int parseDevid(char *input, stmfDevid *devid);
+static void printGroupProps(stmfGroupProperties *groupProps);
+static int checkScsiNameString(wchar_t *, stmfDevid *);
+static int checkHexUpper(char *);
+static int checkIscsiName(wchar_t *);
+static void printLuProps(stmfLogicalUnitProperties *luProps);
+static int printExtLuProps(stmfGuid *guid);
+static void printGuid(stmfGuid *guid, FILE *printWhere);
+static void printTargetProps(stmfTargetProperties *);
+static void printSessionProps(stmfSessionList *);
+static int setLuPropFromInput(luResource, char *);
+static int convertCharToPropId(char *, uint32_t *);
+
+
+
+/*
+ * MAJOR - This should only change when there is an incompatible change made
+ * to the interfaces or the output.
+ *
+ * MINOR - This should change whenever there is a new command or new feature
+ * with no incompatible change.
+ */
+#define VERSION_STRING_MAJOR "1"
+#define VERSION_STRING_MINOR "0"
+#define MAX_DEVID_INPUT 256
+#define GUID_INPUT 32
+#define MAX_LU_NBR 16383
+#define ONLINE_LU 0
+#define OFFLINE_LU 1
+#define ONLINE_TARGET 2
+#define OFFLINE_TARGET 3
+#define PROPS_FORMAT " %-18s: "
+#define VIEW_FORMAT " %-13s: "
+#define LVL3_FORMAT " %s"
+#define LVL4_FORMAT " %s"
+#define DELAYED_EXEC_WAIT_INTERVAL 300 * 1000 * 1000 /* in nano sec */
+#define DELAYED_EXEC_WAIT_MAX 30 /* Maximum number of interval times */
+
+/* SCSI Name String length definitions */
+#define SNS_EUI_16 16
+#define SNS_EUI_24 24
+#define SNS_EUI_32 32
+#define SNS_NAA_16 16
+#define SNS_NAA_32 32
+#define SNS_WWN_16 16
+#define SNS_IQN_223 223
+
+/* LU Property strings */
+#define GUID "GUID"
+#define ALIAS "ALIAS"
+#define VID "VID"
+#define PID "PID"
+#define META_FILE "META"
+#define WRITE_PROTECT "WP"
+#define WRITEBACK_CACHE_DISABLE "WCD"
+#define COMPANY_ID "OUI"
+#define BLOCK_SIZE "BLK"
+#define SERIAL_NUMBER "SERIAL"
+#define MGMT_URL "MGMT-URL"
+#define HOST_ID "HOST-ID"
+
+#define STMFADM_SUCCESS 0
+#define STMFADM_FAILURE 1
+
+#define MODIFY_HELP "\n"\
+"Description: Modify properties of a logical unit. \n" \
+"Valid properties for -p, --lu-prop are: \n" \
+" alias - alias for logical unit (up to 255 chars)\n" \
+" mgmt-url - Management URL address\n" \
+" wcd - write cache disabled (true, false)\n" \
+" wp - write protect (true, false)\n\n" \
+"-f alters the meaning of the operand to be a file name\n" \
+"rather than a LU name. This allows for modification\n" \
+"of a logical unit that is not yet imported into stmf\n"
+
+#define CREATE_HELP "\n"\
+"Description: Create a logical unit. \n" \
+"Valid properties for -p, --lu-prop are: \n" \
+" alias - alias for logical unit (up to 255 chars)\n" \
+" blk - block size in bytes in 2^n\n" \
+" guid - 32 ascii hex characters in NAA format \n" \
+" host-id - host identifier to be used for GUID generation \n" \
+" 8 ascii hex characters\n" \
+" meta - separate meta data file name\n" \
+" mgmt-url - Management URL address\n" \
+" oui - organizational unique identifier\n" \
+" 6 ascii hex characters of valid format\n" \
+" pid - product identifier (up to 16 chars)\n" \
+" serial - serial number (up to 252 chars)\n" \
+" vid - vendor identifier (up to 8 chars)\n" \
+" wcd - write cache disabled (true, false)\n" \
+" wp - write protect (true, false)\n"
+#define ADD_VIEW_HELP "\n"\
+"Description: Add a view entry to a logical unit. \n" \
+"A view entry is comprised of three elements; the \n" \
+"logical unit number, the target group name and the\n" \
+"host group name. These three elements combine together\n" \
+"to form a view for a given COMSTAR logical unit.\n" \
+"This view is realized by a client, a SCSI initiator,\n" \
+"via a REPORT LUNS command. \n"
+
+
+
+/* tables set up based on cmdparse instructions */
+
+/* add new options here */
+optionTbl_t longOptions[] = {
+ {"all", no_arg, 'a', NULL},
+ {"group-name", required_arg, 'g', "group-name"},
+ {"keep-views", no_arg, 'k', NULL},
+ {"lu-name", required_arg, 'l', "LU-Name"},
+ {"lun", required_arg, 'n', "logical-unit-number"},
+ {"lu-prop", required_arg, 'p', "logical-unit-property=value"},
+ {"file", no_arg, 'f', "filename"},
+ {"size", required_arg, 's', "size K/M/G/T/P"},
+ {"target-group", required_arg, 't', "group-name"},
+ {"host-group", required_arg, 'h', "group-name"},
+ {"verbose", no_arg, 'v', NULL},
+ {NULL, 0, 0, 0}
+};
+
+/*
+ * Add new subcommands here
+ */
+subCommandProps_t subcommands[] = {
+ {"add-hg-member", addHostGroupMemberFunc, "g", "g", NULL,
+ OPERAND_MANDATORY_MULTIPLE, OPERANDSTRING_GROUP_MEMBER, NULL},
+ {"add-tg-member", addTargetGroupMemberFunc, "g", "g", NULL,
+ OPERAND_MANDATORY_MULTIPLE, OPERANDSTRING_GROUP_MEMBER, NULL},
+ {"add-view", addViewFunc, "nth", NULL, NULL,
+ OPERAND_MANDATORY_SINGLE, OPERANDSTRING_LU, ADD_VIEW_HELP},
+ {"create-hg", createHostGroupFunc, NULL, NULL, NULL,
+ OPERAND_MANDATORY_SINGLE, OPERANDSTRING_GROUP_NAME, NULL},
+ {"create-tg", createTargetGroupFunc, NULL, NULL, NULL,
+ OPERAND_MANDATORY_SINGLE, OPERANDSTRING_GROUP_NAME, NULL},
+ {"create-lu", createLuFunc, "ps", NULL, NULL, OPERAND_MANDATORY_SINGLE,
+ "lu file", CREATE_HELP},
+ {"delete-hg", deleteHostGroupFunc, NULL, NULL, NULL,
+ OPERAND_MANDATORY_SINGLE, OPERANDSTRING_GROUP_NAME, NULL},
+ {"modify-lu", modifyLuFunc, "psf", NULL, NULL, OPERAND_MANDATORY_SINGLE,
+ OPERANDSTRING_LU, MODIFY_HELP},
+ {"delete-lu", deleteLuFunc, "k", NULL, NULL,
+ OPERAND_MANDATORY_MULTIPLE, OPERANDSTRING_LU, NULL},
+ {"delete-tg", deleteTargetGroupFunc, NULL, NULL, NULL,
+ OPERAND_MANDATORY_SINGLE, OPERANDSTRING_GROUP_NAME, NULL},
+ {"import-lu", importLuFunc, NULL, NULL, NULL,
+ OPERAND_MANDATORY_SINGLE, "file name", NULL},
+ {"list-hg", listHostGroupFunc, "v", NULL, NULL,
+ OPERAND_OPTIONAL_MULTIPLE, OPERANDSTRING_GROUP_NAME, NULL},
+ {"list-lu", listLuFunc, "v", NULL, NULL, OPERAND_OPTIONAL_MULTIPLE,
+ OPERANDSTRING_LU, NULL},
+ {"list-state", listStateFunc, NULL, NULL, NULL, OPERAND_NONE, NULL},
+ {"list-target", listTargetFunc, "v", NULL, NULL,
+ OPERAND_OPTIONAL_MULTIPLE, OPERANDSTRING_TARGET, NULL},
+ {"list-tg", listTargetGroupFunc, "v", NULL, NULL,
+ OPERAND_OPTIONAL_MULTIPLE, OPERANDSTRING_GROUP_NAME, NULL},
+ {"list-view", listViewFunc, "l", "l", NULL,
+ OPERAND_OPTIONAL_MULTIPLE, OPERANDSTRING_VIEW_ENTRY, NULL},
+ {"online-lu", onlineLuFunc, NULL, NULL, NULL,
+ OPERAND_MANDATORY_SINGLE, OPERANDSTRING_LU, NULL},
+ {"offline-lu", offlineLuFunc, NULL, NULL, NULL,
+ OPERAND_MANDATORY_SINGLE, OPERANDSTRING_LU, NULL},
+ {"online-target", onlineTargetFunc, NULL, NULL, NULL,
+ OPERAND_MANDATORY_SINGLE, OPERANDSTRING_TARGET, NULL},
+ {"offline-target", offlineTargetFunc, NULL, NULL, NULL,
+ OPERAND_MANDATORY_SINGLE, OPERANDSTRING_TARGET, NULL},
+ {"remove-hg-member", removeHostGroupMemberFunc, "g", "g", NULL,
+ OPERAND_MANDATORY_MULTIPLE, OPERANDSTRING_GROUP_MEMBER, NULL},
+ {"remove-tg-member", removeTargetGroupMemberFunc, "g", "g", NULL,
+ OPERAND_MANDATORY_MULTIPLE, OPERANDSTRING_GROUP_MEMBER, NULL},
+ {"remove-view", removeViewFunc, "la", "l", NULL,
+ OPERAND_OPTIONAL_MULTIPLE, OPERANDSTRING_VIEW_ENTRY, NULL},
+ {NULL, 0, NULL, NULL, 0, NULL, 0, NULL, NULL}
+};
+
+/* globals */
+char *cmdName;
+
+/*
+ * addHostGroupMemberFunc
+ *
+ * Add members to a host group
+ *
+ */
+/*ARGSUSED*/
+static int
+addHostGroupMemberFunc(int operandLen, char *operands[], cmdOptions_t *options,
+ void *args)
+{
+ int i;
+ int ret = 0;
+ int stmfRet;
+ stmfGroupName groupName = {0};
+ wchar_t groupNamePrint[sizeof (stmfGroupName)] = {0};
+ stmfDevid devid;
+
+ for (; options->optval; options++) {
+ switch (options->optval) {
+ /* host group name */
+ case 'g':
+ (void) mbstowcs(groupNamePrint, options->optarg,
+ sizeof (stmfGroupName) - 1);
+ bcopy(options->optarg, groupName,
+ strlen(options->optarg));
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %c: %s\n",
+ cmdName, options->optval,
+ gettext("unknown option"));
+ return (1);
+ }
+ }
+
+ for (i = 0; i < operandLen; i++) {
+ if (parseDevid(operands[i], &devid) != 0) {
+ (void) fprintf(stderr, "%s: %s: %s\n",
+ cmdName, operands[i],
+ gettext("unrecognized device id"));
+ ret++;
+ continue;
+ }
+ stmfRet = stmfAddToHostGroup(&groupName, &devid);
+ switch (stmfRet) {
+ case STMF_STATUS_SUCCESS:
+ break;
+ case STMF_ERROR_EXISTS:
+ (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
+ operands[i], gettext("already exists"));
+ ret++;
+ break;
+ case STMF_ERROR_GROUP_NOT_FOUND:
+ (void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
+ groupNamePrint, gettext("not found"));
+ ret++;
+ break;
+ case STMF_ERROR_PERM:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("permission denied"));
+ ret++;
+ break;
+ case STMF_ERROR_BUSY:
+ (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
+ operands[i], gettext("resource busy"));
+ ret++;
+ break;
+ case STMF_ERROR_SERVICE_NOT_FOUND:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service not found"));
+ ret++;
+ break;
+ case STMF_ERROR_SERVICE_DATA_VERSION:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service version incorrect"));
+ ret++;
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
+ operands[i], gettext("unknown error"));
+ ret++;
+ break;
+ }
+ }
+
+ return (ret);
+}
+
+/*
+ * addTargetGroupMemberFunc
+ *
+ * Add members to a target group
+ *
+ */
+/*ARGSUSED*/
+static int
+addTargetGroupMemberFunc(int operandLen, char *operands[],
+ cmdOptions_t *options, void *args)
+{
+ int i;
+ int ret = 0;
+ int stmfRet;
+ stmfGroupName groupName = {0};
+ wchar_t groupNamePrint[sizeof (stmfGroupName)] = {0};
+ stmfDevid devid;
+
+ for (; options->optval; options++) {
+ switch (options->optval) {
+ /* target group name */
+ case 'g':
+ (void) mbstowcs(groupNamePrint, options->optarg,
+ sizeof (stmfGroupName) - 1);
+ bcopy(options->optarg, groupName,
+ strlen(options->optarg));
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %c: %s\n",
+ cmdName, options->optval,
+ gettext("unknown option"));
+ return (1);
+ }
+ }
+
+ for (i = 0; i < operandLen; i++) {
+ if (parseDevid(operands[i], &devid) != 0) {
+ (void) fprintf(stderr, "%s: %s: %s\n",
+ cmdName, operands[i],
+ gettext("unrecognized device id"));
+ ret++;
+ continue;
+ }
+ stmfRet = stmfAddToTargetGroup(&groupName, &devid);
+ switch (stmfRet) {
+ case STMF_STATUS_SUCCESS:
+ break;
+ case STMF_ERROR_EXISTS:
+ (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
+ operands[i], gettext("already exists"));
+ ret++;
+ break;
+ case STMF_ERROR_GROUP_NOT_FOUND:
+ (void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
+ groupNamePrint, gettext("not found"));
+ ret++;
+ break;
+ case STMF_ERROR_PERM:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("permission denied"));
+ ret++;
+ break;
+ case STMF_ERROR_BUSY:
+ (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
+ operands[i], gettext("resource busy"));
+ ret++;
+ break;
+ case STMF_ERROR_SERVICE_NOT_FOUND:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service not found"));
+ ret++;
+ break;
+ case STMF_ERROR_SERVICE_ONLINE:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service must be offline"));
+ ret++;
+ break;
+ case STMF_ERROR_SERVICE_DATA_VERSION:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service version incorrect"));
+ ret++;
+ break;
+ case STMF_ERROR_TG_ONLINE:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF target must be offline"));
+ ret++;
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
+ operands[i], gettext("unknown error"));
+ ret++;
+ break;
+ }
+ }
+
+ return (ret);
+}
+
+/*
+ * parseDevid
+ *
+ * Converts char * input to a stmfDevid
+ *
+ * input - this should be in the following format with either a
+ * wwn. iqn. or eui. representation.
+ * A name string of the format:
+ * wwn.<WWN> (FC/SAS address)
+ * iqn.<iSCSI name> (iSCSI iqn)
+ * eui.<WWN> (iSCSI eui name)
+ *
+ * devid - pointer to stmfDevid structure allocated by the caller.
+ *
+ * Returns:
+ * 0 on success
+ * non-zero on failure
+ */
+static int
+parseDevid(char *input, stmfDevid *devid)
+{
+ wchar_t inputWc[MAX_DEVID_INPUT + 1] = {0};
+
+ /* convert to wcs */
+ (void) mbstowcs(inputWc, input, MAX_DEVID_INPUT);
+
+ /*
+ * Check for known scsi name string formats
+ * If one is found, we're done
+ * If not, then it's a failure to parse
+ */
+ if (checkScsiNameString(inputWc, devid) == 0) {
+ return (0);
+ }
+
+ return (-1);
+}
+
+/*
+ * checkScsiNameString
+ *
+ * Validates known SCSI name string formats and converts to stmfDevid
+ * format
+ *
+ * input - input SCSI name string
+ * devid - pointer to stmfDevid structure allocated by the caller
+ * on successful return, contains the devid based on input
+ *
+ * returns:
+ * 0 on success
+ * -1 on failure
+ */
+static int
+checkScsiNameString(wchar_t *input, stmfDevid *devid)
+{
+ char *mbString = NULL;
+ int mbStringLen;
+ int len;
+ int i;
+
+ /*
+ * Convert to multi-byte string
+ *
+ * This is used for either eui or naa formats
+ */
+ mbString = calloc(1, (mbStringLen = wcstombs(mbString, input, 0)) + 1);
+ if (mbString == NULL) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, "Insufficient memory\n");
+ return (-1);
+ }
+ if (wcstombs(mbString, input, mbStringLen) == (size_t)-1) {
+ return (-1);
+ }
+
+ /*
+ * check for iqn format
+ */
+ if (strncmp(mbString, "iqn.", 4) == 0) {
+ if ((len = strlen(mbString)) > (SNS_IQN_223)) {
+ return (-1);
+ }
+ for (i = 0; i < len; i++) {
+ mbString[i] = tolower(mbString[i]);
+ }
+ if (checkIscsiName(input + 4) != 0) {
+ return (-1);
+ }
+ } else if (strncmp(mbString, "wwn.", 4) == 0) {
+ if ((len = strlen(mbString + 4)) != SNS_WWN_16) {
+ return (-1);
+ } else if (checkHexUpper(mbString + 4) != 0) {
+ return (-1);
+ }
+ } else if (strncmp(mbString, "eui.", 4) == 0) {
+ if ((len = strlen(mbString + 4)) != SNS_EUI_16) {
+ return (-1);
+ } else if (checkHexUpper(mbString + 4) != 0) {
+ return (-1);
+ }
+ } else {
+ return (-1);
+ }
+
+ /*
+ * We have a validated name string.
+ * Go ahead and set the length and copy it.
+ */
+ devid->identLength = strlen(mbString);
+ bzero(devid->ident, STMF_IDENT_LENGTH);
+ bcopy(mbString, devid->ident, devid->identLength);
+
+ return (0);
+}
+
+
+/*
+ * Checks whether the entire string is in hex and converts to upper
+ */
+static int
+checkHexUpper(char *input)
+{
+ int i;
+
+ for (i = 0; i < strlen(input); i++) {
+ if (isxdigit(input[i])) {
+ input[i] = toupper(input[i]);
+ continue;
+ }
+ return (-1);
+ }
+
+ return (0);
+}
+
+/*
+ * checkIscsiName
+ *
+ * Purpose: Basic string checking on name
+ */
+static int
+checkIscsiName(wchar_t *input)
+{
+ int i;
+
+ for (i = 0; input[i] != 0; i++) {
+ if (!iswalnum(input[i]) && input[i] != '-' &&
+ input[i] != '.' && input[i] != ':') {
+ return (-1);
+ }
+ }
+
+ return (0);
+}
+
+
+/*
+ * addViewFunc
+ *
+ * Adds a view entry to a logical unit
+ *
+ */
+/*ARGSUSED*/
+static int
+addViewFunc(int operandLen, char *operands[], cmdOptions_t *options,
+ void *args)
+{
+ stmfViewEntry viewEntry;
+ stmfGuid inGuid;
+ unsigned int guid[sizeof (stmfGuid)];
+ uint16_t inputLuNbr;
+ int ret = 0;
+ int stmfRet;
+ int i;
+ char sGuid[GUID_INPUT + 1];
+
+ bzero(&viewEntry, sizeof (viewEntry));
+ /* init view entry structure */
+ viewEntry.allHosts = B_TRUE;
+ viewEntry.allTargets = B_TRUE;
+ viewEntry.luNbrValid = B_FALSE;
+
+ /* check input length */
+ if (strlen(operands[0]) != GUID_INPUT) {
+ (void) fprintf(stderr, "%s: %s: %s%d%s\n", cmdName, operands[0],
+ gettext("must be "), GUID_INPUT,
+ gettext(" hexadecimal digits"));
+ return (1);
+ }
+
+ for (; options->optval; options++) {
+ switch (options->optval) {
+ /* logical unit number */
+ case 'n':
+ viewEntry.luNbrValid = B_TRUE;
+ inputLuNbr = atoi(options->optarg);
+ if (inputLuNbr > MAX_LU_NBR) {
+ (void) fprintf(stderr, "%s: %d: %s\n",
+ cmdName, inputLuNbr,
+ gettext("Logical unit number"
+ " must be less than 16384"));
+ return (1);
+ }
+ viewEntry.luNbr[0] = inputLuNbr >> 8;
+ viewEntry.luNbr[1] = inputLuNbr & 0xff;
+ break;
+ /* host group */
+ case 'h':
+ viewEntry.allHosts = B_FALSE;
+ bcopy(options->optarg, viewEntry.hostGroup,
+ strlen(options->optarg));
+ break;
+ /* target group */
+ case 't':
+ viewEntry.allTargets = B_FALSE;
+ bcopy(options->optarg, viewEntry.targetGroup,
+ strlen(options->optarg));
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %c: %s\n",
+ cmdName, options->optval,
+ gettext("unknown option"));
+ return (1);
+ }
+ }
+
+ /* convert to lower case for scan */
+ for (i = 0; i < 32; i++)
+ sGuid[i] = tolower(operands[0][i]);
+ sGuid[i] = 0;
+
+ (void) sscanf(sGuid, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
+ &guid[0], &guid[1], &guid[2], &guid[3], &guid[4], &guid[5],
+ &guid[6], &guid[7], &guid[8], &guid[9], &guid[10], &guid[11],
+ &guid[12], &guid[13], &guid[14], &guid[15]);
+
+ for (i = 0; i < sizeof (stmfGuid); i++) {
+ inGuid.guid[i] = guid[i];
+ }
+
+ /* add the view entry */
+ stmfRet = stmfAddViewEntry(&inGuid, &viewEntry);
+ switch (stmfRet) {
+ case STMF_STATUS_SUCCESS:
+ break;
+ case STMF_ERROR_EXISTS:
+ (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
+ operands[0], gettext("already exists"));
+ ret++;
+ break;
+ case STMF_ERROR_BUSY:
+ (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
+ operands[0], gettext("resource busy"));
+ ret++;
+ break;
+ case STMF_ERROR_SERVICE_NOT_FOUND:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service not found"));
+ ret++;
+ break;
+ case STMF_ERROR_PERM:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("permission denied"));
+ ret++;
+ break;
+ case STMF_ERROR_LUN_IN_USE:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("LUN already in use"));
+ ret++;
+ break;
+ case STMF_ERROR_VE_CONFLICT:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("view entry exists"));
+ ret++;
+ break;
+ case STMF_ERROR_CONFIG_NONE:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service is not initialized"));
+ ret++;
+ break;
+ case STMF_ERROR_SERVICE_DATA_VERSION:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service version incorrect"));
+ ret++;
+ break;
+ case STMF_ERROR_INVALID_HG:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("invalid host group"));
+ ret++;
+ break;
+ case STMF_ERROR_INVALID_TG:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("invalid target group"));
+ ret++;
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
+ operands[0], gettext("unknown error"));
+ ret++;
+ break;
+ }
+
+ return (ret);
+}
+
+/*
+ * createHostGroupFunc
+ *
+ * Create a host group
+ *
+ */
+/*ARGSUSED*/
+static int
+createHostGroupFunc(int operandLen, char *operands[],
+ cmdOptions_t *options, void *args)
+{
+ int ret = 0;
+ int stmfRet;
+ wchar_t groupNamePrint[sizeof (stmfGroupName)] = {0};
+ stmfGroupName groupName = {0};
+
+ (void) strlcpy(groupName, operands[0], sizeof (groupName));
+ (void) mbstowcs(groupNamePrint, (char *)groupName,
+ sizeof (stmfGroupName) - 1);
+ /* call create group */
+ stmfRet = stmfCreateHostGroup(&groupName);
+ switch (stmfRet) {
+ case STMF_STATUS_SUCCESS:
+ break;
+ case STMF_ERROR_EXISTS:
+ (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
+ operands[0], gettext("already exists"));
+ ret++;
+ break;
+ case STMF_ERROR_BUSY:
+ (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
+ operands[0], gettext("resource busy"));
+ ret++;
+ break;
+ case STMF_ERROR_SERVICE_NOT_FOUND:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service not found"));
+ ret++;
+ break;
+ case STMF_ERROR_PERM:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("permission denied"));
+ ret++;
+ break;
+ case STMF_ERROR_SERVICE_DATA_VERSION:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service version incorrect"));
+ ret++;
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
+ operands[0], gettext("unknown error"));
+ ret++;
+ break;
+ }
+
+ return (ret);
+}
+
+/*
+ * createLuFunc
+ *
+ * Create a logical unit
+ *
+ */
+/*ARGSUSED*/
+static int
+createLuFunc(int operandLen, char *operands[], cmdOptions_t *options,
+ void *args)
+{
+ luResource hdl = NULL;
+ int ret = 0;
+ int stmfRet = 0;
+ char guidAsciiBuf[33];
+ stmfGuid createdGuid;
+
+ stmfRet = stmfCreateLuResource(STMF_DISK, &hdl);
+
+ if (stmfRet != STMF_STATUS_SUCCESS) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("Failure to create lu resource\n"));
+ return (1);
+ }
+
+ for (; options->optval; options++) {
+ switch (options->optval) {
+ case 'p':
+ ret = setLuPropFromInput(hdl, options->optarg);
+ if (ret != 0) {
+ (void) stmfFreeLuResource(hdl);
+ return (1);
+ }
+ break;
+ case 's':
+ stmfRet = stmfSetLuProp(hdl, STMF_LU_PROP_SIZE,
+ options->optarg);
+ if (stmfRet != STMF_STATUS_SUCCESS) {
+ (void) fprintf(stderr, "%s: %c: %s\n",
+ cmdName, options->optval,
+ gettext("size param invalid"));
+ (void) stmfFreeLuResource(hdl);
+ return (1);
+ }
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %c: %s\n",
+ cmdName, options->optval,
+ gettext("unknown option"));
+ return (1);
+ }
+ }
+
+ stmfRet = stmfSetLuProp(hdl, STMF_LU_PROP_FILENAME, operands[0]);
+
+ if (stmfRet != STMF_STATUS_SUCCESS) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("could not set filename"));
+ return (1);
+ }
+
+ stmfRet = stmfCreateLu(hdl, &createdGuid);
+ switch (stmfRet) {
+ case STMF_STATUS_SUCCESS:
+ break;
+ case STMF_ERROR_BUSY:
+ case STMF_ERROR_LU_BUSY:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("resource busy"));
+ ret++;
+ break;
+ case STMF_ERROR_PERM:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("permission denied"));
+ ret++;
+ break;
+ case STMF_ERROR_FILE_IN_USE:
+ (void) fprintf(stderr, "%s: filename %s: %s\n", cmdName,
+ operands[0], gettext("in use"));
+ ret++;
+ break;
+ case STMF_ERROR_INVALID_BLKSIZE:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("invalid block size"));
+ ret++;
+ break;
+ case STMF_ERROR_GUID_IN_USE:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("guid in use"));
+ ret++;
+ break;
+ case STMF_ERROR_META_FILE_NAME:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("meta file error"));
+ ret++;
+ break;
+ case STMF_ERROR_DATA_FILE_NAME:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("data file error"));
+ ret++;
+ break;
+ case STMF_ERROR_FILE_SIZE_INVALID:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("file size invalid"));
+ ret++;
+ break;
+ case STMF_ERROR_SIZE_OUT_OF_RANGE:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("invalid size"));
+ ret++;
+ break;
+ case STMF_ERROR_META_CREATION:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("could not create meta file"));
+ ret++;
+ break;
+ case STMF_ERROR_WRITE_CACHE_SET:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("could not set write cache"));
+ ret++;
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("unknown error"));
+ ret++;
+ break;
+ }
+
+ if (ret != 0) {
+ goto done;
+ }
+
+ (void) snprintf(guidAsciiBuf, sizeof (guidAsciiBuf),
+ "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X"
+ "%02X%02X%02X%02X%02X%02X",
+ createdGuid.guid[0], createdGuid.guid[1], createdGuid.guid[2],
+ createdGuid.guid[3], createdGuid.guid[4], createdGuid.guid[5],
+ createdGuid.guid[6], createdGuid.guid[7], createdGuid.guid[8],
+ createdGuid.guid[9], createdGuid.guid[10], createdGuid.guid[11],
+ createdGuid.guid[12], createdGuid.guid[13], createdGuid.guid[14],
+ createdGuid.guid[15]);
+ (void) printf("Logical unit created: %s\n", guidAsciiBuf);
+
+done:
+ (void) stmfFreeLuResource(hdl);
+ return (ret);
+}
+
+/*
+ * createLuFunc
+ *
+ * Create a logical unit
+ *
+ */
+/*ARGSUSED*/
+static int
+modifyLuFunc(int operandLen, char *operands[], cmdOptions_t *options,
+ void *args)
+{
+ stmfGuid inGuid;
+ unsigned int guid[sizeof (stmfGuid)];
+ int ret = 0;
+ int i;
+ char *fname = NULL;
+ char *lasts = NULL;
+ char sGuid[GUID_INPUT + 1];
+ char *prop = NULL;
+ char *propVal = NULL;
+ boolean_t fnameUsed = B_FALSE;
+ uint32_t propId;
+ cmdOptions_t *optionStart = options;
+
+
+ for (; options->optval; options++) {
+ switch (options->optval) {
+ case 'f':
+ fnameUsed = B_TRUE;
+ fname = operands[0];
+ break;
+ }
+ }
+ options = optionStart;
+
+ /* check input length */
+ if (!fnameUsed && strlen(operands[0]) != GUID_INPUT) {
+ (void) fprintf(stderr, "%s: %s: %s%d%s\n", cmdName, operands[0],
+ gettext("must be "), GUID_INPUT,
+ gettext(" hexadecimal digits"));
+ return (1);
+ }
+
+ if (!fnameUsed) {
+ /* convert to lower case for scan */
+ for (i = 0; i < 32; i++)
+ sGuid[i] = tolower(operands[0][i]);
+ sGuid[i] = 0;
+ (void) sscanf(sGuid,
+ "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
+ &guid[0], &guid[1], &guid[2], &guid[3], &guid[4], &guid[5],
+ &guid[6], &guid[7], &guid[8], &guid[9], &guid[10],
+ &guid[11], &guid[12], &guid[13], &guid[14], &guid[15]);
+
+ for (i = 0; i < sizeof (stmfGuid); i++) {
+ inGuid.guid[i] = guid[i];
+ }
+ }
+
+ for (; options->optval; options++) {
+ switch (options->optval) {
+ case 'p':
+ prop = strtok_r(options->optarg, "=", &lasts);
+ propVal = strtok_r(NULL, "=", &lasts);
+ ret = convertCharToPropId(prop, &propId);
+ if (ret != 0) {
+ (void) fprintf(stderr, "%s: %s: %s\n",
+ cmdName,
+ gettext("invalid property specified"),
+ prop);
+ return (1);
+ }
+ if (propVal == NULL &&
+ propId != STMF_LU_PROP_MGMT_URL) {
+ (void) fprintf(stderr, "%s: %s: %s\n",
+ cmdName, options->optarg,
+ gettext("invalid property specifier"
+ "- prop=val\n"));
+ return (1);
+ }
+ if (propVal == NULL) {
+ ret = callModify(fname, &inGuid, propId,
+ "", prop);
+ } else {
+ ret = callModify(fname, &inGuid, propId,
+ propVal, prop);
+ }
+ if (ret != 0) {
+ return (1);
+ }
+ break;
+ case 's':
+ if (callModify(fname, &inGuid,
+ STMF_LU_PROP_SIZE, options->optarg,
+ "size") != 0) {
+ return (1);
+ }
+ break;
+ case 'f':
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %c: %s\n",
+ cmdName, options->optval,
+ gettext("unknown option"));
+ return (1);
+ }
+ }
+ return (ret);
+}
+
+static int
+callModify(char *fname, stmfGuid *luGuid, uint32_t prop, const char *propVal,
+ const char *propString)
+{
+ int ret = 0;
+ int stmfRet = 0;
+
+ if (!fname) {
+ stmfRet = stmfModifyLu(luGuid, prop, propVal);
+ } else {
+ stmfRet = stmfModifyLuByFname(STMF_DISK, fname, prop,
+ propVal);
+ }
+ switch (stmfRet) {
+ case STMF_STATUS_SUCCESS:
+ break;
+ case STMF_ERROR_BUSY:
+ case STMF_ERROR_LU_BUSY:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("resource busy"));
+ ret++;
+ break;
+ case STMF_ERROR_PERM:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("permission denied"));
+ ret++;
+ break;
+ case STMF_ERROR_INVALID_BLKSIZE:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("invalid block size"));
+ ret++;
+ break;
+ case STMF_ERROR_GUID_IN_USE:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("guid in use"));
+ ret++;
+ break;
+ case STMF_ERROR_META_FILE_NAME:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("meta file error"));
+ ret++;
+ break;
+ case STMF_ERROR_DATA_FILE_NAME:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("data file error"));
+ ret++;
+ break;
+ case STMF_ERROR_FILE_SIZE_INVALID:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("file size invalid"));
+ ret++;
+ break;
+ case STMF_ERROR_SIZE_OUT_OF_RANGE:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("invalid size"));
+ ret++;
+ break;
+ case STMF_ERROR_META_CREATION:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("could not create meta file"));
+ ret++;
+ break;
+ case STMF_ERROR_INVALID_PROP:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("invalid property for modify"));
+ ret++;
+ break;
+ case STMF_ERROR_WRITE_CACHE_SET:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("could not set write cache"));
+ ret++;
+ break;
+ case STMF_ERROR_ACCESS_STATE_SET:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("cannot modify while in standby mode"));
+ ret++;
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %s: %s: %d\n", cmdName,
+ gettext("could not set property"), propString,
+ stmfRet);
+ ret++;
+ break;
+ }
+
+ return (ret);
+}
+
+
+/*
+ * importLuFunc
+ *
+ * Create a logical unit
+ *
+ */
+/*ARGSUSED*/
+static int
+importLuFunc(int operandLen, char *operands[], cmdOptions_t *options,
+ void *args)
+{
+ int stmfRet = 0;
+ int ret = 0;
+ char guidAsciiBuf[33];
+ stmfGuid createdGuid;
+
+ stmfRet = stmfImportLu(STMF_DISK, operands[0], &createdGuid);
+ switch (stmfRet) {
+ case STMF_STATUS_SUCCESS:
+ break;
+ case STMF_ERROR_BUSY:
+ case STMF_ERROR_LU_BUSY:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("resource busy"));
+ ret++;
+ break;
+ case STMF_ERROR_PERM:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("permission denied"));
+ ret++;
+ break;
+ case STMF_ERROR_FILE_IN_USE:
+ (void) fprintf(stderr, "%s: filename %s: %s\n", cmdName,
+ operands[0], gettext("in use"));
+ ret++;
+ break;
+ case STMF_ERROR_GUID_IN_USE:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("guid in use"));
+ ret++;
+ break;
+ case STMF_ERROR_META_FILE_NAME:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("meta file error"));
+ ret++;
+ break;
+ case STMF_ERROR_DATA_FILE_NAME:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("data file error"));
+ ret++;
+ break;
+ case STMF_ERROR_META_CREATION:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("could not create meta file"));
+ ret++;
+ break;
+ case STMF_ERROR_WRITE_CACHE_SET:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("could not set write cache"));
+ ret++;
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("unknown error"));
+ ret++;
+ break;
+ }
+
+ if (ret != STMF_STATUS_SUCCESS) {
+ goto done;
+ }
+
+ (void) snprintf(guidAsciiBuf, sizeof (guidAsciiBuf),
+ "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X"
+ "%02X%02X%02X%02X%02X%02X",
+ createdGuid.guid[0], createdGuid.guid[1], createdGuid.guid[2],
+ createdGuid.guid[3], createdGuid.guid[4], createdGuid.guid[5],
+ createdGuid.guid[6], createdGuid.guid[7], createdGuid.guid[8],
+ createdGuid.guid[9], createdGuid.guid[10], createdGuid.guid[11],
+ createdGuid.guid[12], createdGuid.guid[13], createdGuid.guid[14],
+ createdGuid.guid[15]);
+ (void) printf("Logical unit imported: %s\n", guidAsciiBuf);
+
+done:
+ return (ret);
+}
+
+static int
+setLuPropFromInput(luResource hdl, char *optarg)
+{
+ char *prop = NULL;
+ char *propVal = NULL;
+ char *lasts = NULL;
+ uint32_t propId;
+ int ret = 0;
+
+ prop = strtok_r(optarg, "=", &lasts);
+ if ((propVal = strtok_r(NULL, "=", &lasts)) == NULL) {
+ (void) fprintf(stderr, "%s: %s: %s\n",
+ cmdName, optarg,
+ gettext("invalid property specifier - prop=val\n"));
+ return (1);
+ }
+
+ ret = convertCharToPropId(prop, &propId);
+ if (ret != 0) {
+ (void) fprintf(stderr, "%s: %s: %s\n",
+ cmdName, gettext("invalid property specified"), prop);
+ return (1);
+ }
+
+ ret = stmfSetLuProp(hdl, propId, propVal);
+ if (ret != STMF_STATUS_SUCCESS) {
+ (void) fprintf(stderr, "%s: %s %s: ",
+ cmdName, gettext("unable to set"), prop);
+ switch (ret) {
+ case STMF_ERROR_INVALID_PROPSIZE:
+ (void) fprintf(stderr, "invalid length\n");
+ break;
+ case STMF_ERROR_INVALID_ARG:
+ (void) fprintf(stderr, "bad format\n");
+ break;
+ default:
+ (void) fprintf(stderr, "\n");
+ break;
+ }
+ return (1);
+ }
+
+ return (0);
+}
+
+static int
+convertCharToPropId(char *prop, uint32_t *propId)
+{
+ if (strcasecmp(prop, GUID) == 0) {
+ *propId = STMF_LU_PROP_GUID;
+ } else if (strcasecmp(prop, ALIAS) == 0) {
+ *propId = STMF_LU_PROP_ALIAS;
+ } else if (strcasecmp(prop, VID) == 0) {
+ *propId = STMF_LU_PROP_VID;
+ } else if (strcasecmp(prop, PID) == 0) {
+ *propId = STMF_LU_PROP_PID;
+ } else if (strcasecmp(prop, WRITE_PROTECT) == 0) {
+ *propId = STMF_LU_PROP_WRITE_PROTECT;
+ } else if (strcasecmp(prop, WRITEBACK_CACHE_DISABLE) == 0) {
+ *propId = STMF_LU_PROP_WRITE_CACHE_DISABLE;
+ } else if (strcasecmp(prop, BLOCK_SIZE) == 0) {
+ *propId = STMF_LU_PROP_BLOCK_SIZE;
+ } else if (strcasecmp(prop, SERIAL_NUMBER) == 0) {
+ *propId = STMF_LU_PROP_SERIAL_NUM;
+ } else if (strcasecmp(prop, COMPANY_ID) == 0) {
+ *propId = STMF_LU_PROP_COMPANY_ID;
+ } else if (strcasecmp(prop, META_FILE) == 0) {
+ *propId = STMF_LU_PROP_META_FILENAME;
+ } else if (strcasecmp(prop, MGMT_URL) == 0) {
+ *propId = STMF_LU_PROP_MGMT_URL;
+ } else if (strcasecmp(prop, HOST_ID) == 0) {
+ *propId = STMF_LU_PROP_HOST_ID;
+ } else {
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * deleteLuFunc
+ *
+ * Delete a logical unit
+ *
+ */
+/*ARGSUSED*/
+static int
+deleteLuFunc(int operandLen, char *operands[], cmdOptions_t *options,
+ void *args)
+{
+ int i, j;
+ int ret = 0;
+ int stmfRet;
+ unsigned int inGuid[sizeof (stmfGuid)];
+ stmfGuid delGuid;
+ boolean_t keepViews = B_FALSE;
+ boolean_t viewEntriesRemoved = B_FALSE;
+ boolean_t noLunFound = B_FALSE;
+ boolean_t views = B_FALSE;
+ boolean_t notValidHexNumber = B_FALSE;
+ char sGuid[GUID_INPUT + 1];
+ stmfViewEntryList *viewEntryList = NULL;
+
+ for (; options->optval; options++) {
+ switch (options->optval) {
+ /* Keep views for logical unit */
+ case 'k':
+ keepViews = B_TRUE;
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %c: %s\n",
+ cmdName, options->optval,
+ gettext("unknown option"));
+ return (1);
+ }
+ }
+
+
+ for (i = 0; i < operandLen; i++) {
+ for (j = 0; j < GUID_INPUT; j++) {
+ if (!isxdigit(operands[i][j])) {
+ notValidHexNumber = B_TRUE;
+ break;
+ }
+ sGuid[j] = tolower(operands[i][j]);
+ }
+ if ((notValidHexNumber == B_TRUE) ||
+ (strlen(operands[i]) != GUID_INPUT)) {
+ (void) fprintf(stderr, "%s: %s: %s%d%s\n",
+ cmdName, operands[i], gettext("must be "),
+ GUID_INPUT,
+ gettext(" hexadecimal digits long"));
+ notValidHexNumber = B_FALSE;
+ ret++;
+ continue;
+ }
+
+ sGuid[j] = 0;
+
+ (void) sscanf(sGuid,
+ "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
+ &inGuid[0], &inGuid[1], &inGuid[2], &inGuid[3],
+ &inGuid[4], &inGuid[5], &inGuid[6], &inGuid[7],
+ &inGuid[8], &inGuid[9], &inGuid[10], &inGuid[11],
+ &inGuid[12], &inGuid[13], &inGuid[14], &inGuid[15]);
+
+ for (j = 0; j < sizeof (stmfGuid); j++) {
+ delGuid.guid[j] = inGuid[j];
+ }
+
+ stmfRet = stmfDeleteLu(&delGuid);
+ switch (stmfRet) {
+ case STMF_STATUS_SUCCESS:
+ break;
+ case STMF_ERROR_NOT_FOUND:
+ noLunFound = B_TRUE;
+ break;
+ case STMF_ERROR_BUSY:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("resource busy"));
+ ret++;
+ break;
+ case STMF_ERROR_PERM:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("permission denied"));
+ ret++;
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("unknown error"));
+ ret++;
+ break;
+ }
+
+ if (!keepViews) {
+ stmfRet = stmfGetViewEntryList(&delGuid,
+ &viewEntryList);
+ if (stmfRet == STMF_STATUS_SUCCESS) {
+ for (j = 0; j < viewEntryList->cnt; j++) {
+ (void) stmfRemoveViewEntry(&delGuid,
+ viewEntryList->ve[j].veIndex);
+ }
+ /* check if viewEntryList is empty */
+ if (viewEntryList->cnt != 0)
+ viewEntriesRemoved = B_TRUE;
+ stmfFreeMemory(viewEntryList);
+ } else {
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("unable to remove view entries\n"));
+ ret++;
+ }
+
+ }
+ if (keepViews) {
+ stmfRet = stmfGetViewEntryList(&delGuid,
+ &viewEntryList);
+ if (stmfRet == STMF_STATUS_SUCCESS) {
+ views = B_TRUE;
+ stmfFreeMemory(viewEntryList);
+ }
+ }
+
+ if ((!viewEntriesRemoved && noLunFound && !views) ||
+ (!views && keepViews && noLunFound)) {
+ (void) fprintf(stderr, "%s: %s: %s\n",
+ cmdName, sGuid,
+ gettext("not found"));
+ ret++;
+ }
+ noLunFound = viewEntriesRemoved = views = B_FALSE;
+ }
+ return (ret);
+}
+
+
+/*
+ * createTargetGroupFunc
+ *
+ * Create a target group
+ *
+ */
+/*ARGSUSED*/
+static int
+createTargetGroupFunc(int operandLen, char *operands[], cmdOptions_t *options,
+ void *args)
+{
+ int ret = 0;
+ int stmfRet;
+ wchar_t groupNamePrint[sizeof (stmfGroupName)] = {0};
+ stmfGroupName groupName = {0};
+
+ (void) strlcpy(groupName, operands[0], sizeof (groupName));
+ (void) mbstowcs(groupNamePrint, (char *)groupName,
+ sizeof (stmfGroupName) - 1);
+ /* call create group */
+ stmfRet = stmfCreateTargetGroup(&groupName);
+ switch (stmfRet) {
+ case STMF_STATUS_SUCCESS:
+ break;
+ case STMF_ERROR_EXISTS:
+ (void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
+ groupNamePrint, gettext("already exists"));
+ ret++;
+ break;
+ case STMF_ERROR_BUSY:
+ (void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
+ groupNamePrint, gettext("resource busy"));
+ ret++;
+ break;
+ case STMF_ERROR_PERM:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("permission denied"));
+ ret++;
+ break;
+ case STMF_ERROR_SERVICE_NOT_FOUND:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service not found"));
+ ret++;
+ break;
+ case STMF_ERROR_SERVICE_DATA_VERSION:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service version incorrect"));
+ ret++;
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
+ groupNamePrint, gettext("unknown error"));
+ ret++;
+ break;
+ }
+
+ return (ret);
+}
+
+/*
+ * deleteHostGroupFunc
+ *
+ * Delete a host group
+ *
+ */
+/*ARGSUSED*/
+static int
+deleteHostGroupFunc(int operandLen, char *operands[],
+ cmdOptions_t *options, void *args)
+{
+ int ret = 0;
+ int stmfRet;
+ wchar_t groupNamePrint[sizeof (stmfGroupName)] = {0};
+ stmfGroupName groupName = {0};
+
+ (void) strlcpy(groupName, operands[0], sizeof (groupName));
+ (void) mbstowcs(groupNamePrint, (char *)groupName,
+ sizeof (stmfGroupName) - 1);
+ /* call delete group */
+ stmfRet = stmfDeleteHostGroup(&groupName);
+ switch (stmfRet) {
+ case STMF_STATUS_SUCCESS:
+ break;
+ case STMF_ERROR_NOT_FOUND:
+ (void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
+ groupNamePrint, gettext("not found"));
+ ret++;
+ break;
+ case STMF_ERROR_BUSY:
+ (void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
+ groupNamePrint, gettext("resource busy"));
+ ret++;
+ break;
+ case STMF_ERROR_SERVICE_NOT_FOUND:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service not found"));
+ ret++;
+ break;
+ case STMF_ERROR_PERM:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("permission denied"));
+ ret++;
+ break;
+ case STMF_ERROR_GROUP_IN_USE:
+ (void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
+ groupNamePrint,
+ gettext("group is in use by existing view entry"));
+ ret++;
+ break;
+ case STMF_ERROR_SERVICE_DATA_VERSION:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service version incorrect"));
+ ret++;
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
+ groupNamePrint, gettext("unknown error"));
+ ret++;
+ break;
+ }
+
+ return (ret);
+}
+
+/*
+ * deleteTargetGroupFunc
+ *
+ * Delete a target group
+ *
+ */
+/*ARGSUSED*/
+static int
+deleteTargetGroupFunc(int operandLen, char *operands[], cmdOptions_t *options,
+ void *args)
+{
+ int ret = 0;
+ int stmfRet;
+ wchar_t groupNamePrint[sizeof (stmfGroupName)] = {0};
+ stmfGroupName groupName = {0};
+
+ (void) strlcpy(groupName, operands[0], sizeof (groupName));
+ (void) mbstowcs(groupNamePrint, (char *)groupName,
+ sizeof (stmfGroupName) - 1);
+ /* call delete group */
+ stmfRet = stmfDeleteTargetGroup(&groupName);
+ switch (stmfRet) {
+ case STMF_STATUS_SUCCESS:
+ break;
+ case STMF_ERROR_NOT_FOUND:
+ (void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
+ groupNamePrint, gettext("not found"));
+ ret++;
+ break;
+ case STMF_ERROR_BUSY:
+ (void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
+ groupNamePrint, gettext("resource busy"));
+ ret++;
+ break;
+ case STMF_ERROR_SERVICE_NOT_FOUND:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service not found"));
+ ret++;
+ break;
+ case STMF_ERROR_PERM:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("permission denied"));
+ ret++;
+ break;
+ case STMF_ERROR_GROUP_IN_USE:
+ (void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
+ groupNamePrint,
+ gettext("group is in use by existing view entry"));
+ ret++;
+ break;
+ case STMF_ERROR_SERVICE_DATA_VERSION:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service version incorrect"));
+ ret++;
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
+ groupNamePrint, gettext("unknown error"));
+ ret++;
+ break;
+ }
+
+ return (ret);
+}
+
+/*
+ * listHostGroupFunc
+ *
+ * Lists the specified host groups or all if none are specified
+ *
+ */
+/*ARGSUSED*/
+static int
+listHostGroupFunc(int operandLen, char *operands[], cmdOptions_t *options,
+ void *args)
+{
+ int ret = 0;
+ int stmfRet;
+ int i, j, outerLoop;
+ boolean_t verbose = B_FALSE;
+ boolean_t found = B_TRUE;
+ boolean_t operandEntered;
+ stmfGroupList *groupList;
+ stmfGroupProperties *groupProps;
+ wchar_t operandName[sizeof (stmfGroupName)];
+ wchar_t groupNamePrint[sizeof (stmfGroupName)];
+
+ for (; options->optval; options++) {
+ switch (options->optval) {
+ case 'v':
+ verbose = B_TRUE;
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %c: %s\n",
+ cmdName, options->optval,
+ gettext("unknown option"));
+ return (1);
+ }
+ }
+
+ if (operandLen > 0) {
+ outerLoop = operandLen;
+ operandEntered = B_TRUE;
+ } else {
+ outerLoop = 1;
+ operandEntered = B_FALSE;
+ }
+
+ stmfRet = stmfGetHostGroupList(&groupList);
+ if (stmfRet != STMF_STATUS_SUCCESS) {
+ switch (stmfRet) {
+ case STMF_ERROR_BUSY:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("resource busy"));
+ break;
+ case STMF_ERROR_SERVICE_NOT_FOUND:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service not found"));
+ break;
+ case STMF_ERROR_PERM:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("permission denied"));
+ break;
+ case STMF_ERROR_SERVICE_DATA_VERSION:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service version incorrect"));
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("unknown error"));
+ break;
+ }
+ return (1);
+ }
+
+ for (i = 0; i < outerLoop; i++) {
+ for (found = B_FALSE, j = 0; j < groupList->cnt; j++) {
+ (void) mbstowcs(groupNamePrint,
+ (char *)groupList->name[j],
+ sizeof (stmfGroupName) - 1);
+ groupNamePrint[sizeof (stmfGroupName) - 1] = 0;
+ if (operandEntered) {
+ (void) mbstowcs(operandName, operands[i],
+ sizeof (stmfGroupName) - 1);
+ operandName[sizeof (stmfGroupName) - 1] = 0;
+ if (wcscmp(operandName, groupNamePrint)
+ == 0) {
+ found = B_TRUE;
+ }
+ }
+ if ((found && operandEntered) || !operandEntered) {
+ (void) printf("Host Group: %ws\n",
+ groupNamePrint);
+ if (verbose) {
+ stmfRet = stmfGetHostGroupMembers(
+ &(groupList->name[j]), &groupProps);
+ if (stmfRet != STMF_STATUS_SUCCESS) {
+ return (1);
+ }
+ printGroupProps(groupProps);
+ }
+ if (found && operandEntered) {
+ break;
+ }
+ }
+
+ }
+ if (operandEntered && !found) {
+ (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
+ operands[i], gettext("not found"));
+ ret = 1;
+ }
+ }
+ return (ret);
+}
+
+/*
+ * printGroupProps
+ *
+ * Prints group members for target or host groups
+ *
+ */
+static void
+printGroupProps(stmfGroupProperties *groupProps)
+{
+ int i;
+ wchar_t memberIdent[sizeof (groupProps->name[0].ident) + 1] = {0};
+
+
+ for (i = 0; i < groupProps->cnt; i++) {
+ (void) mbstowcs(memberIdent, (char *)groupProps->name[i].ident,
+ sizeof (groupProps->name[0].ident));
+ (void) printf("\tMember: %ws\n", memberIdent);
+ }
+}
+
+/*
+ * listTargetGroupFunc
+ *
+ * Lists the specified target groups or all if none are specified
+ *
+ */
+/*ARGSUSED*/
+static int
+listTargetGroupFunc(int operandLen, char *operands[], cmdOptions_t *options,
+ void *args)
+{
+ int ret = 0;
+ int stmfRet;
+ int i, j, outerLoop;
+ boolean_t verbose = B_FALSE;
+ boolean_t found = B_TRUE;
+ boolean_t operandEntered;
+ stmfGroupList *groupList;
+ stmfGroupProperties *groupProps;
+ wchar_t operandName[sizeof (stmfGroupName)];
+ wchar_t groupNamePrint[sizeof (stmfGroupName)];
+
+ for (; options->optval; options++) {
+ switch (options->optval) {
+ case 'v':
+ verbose = B_TRUE;
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %c: %s\n",
+ cmdName, options->optval,
+ gettext("unknown option"));
+ return (1);
+ }
+ }
+
+ if (operandLen > 0) {
+ outerLoop = operandLen;
+ operandEntered = B_TRUE;
+ } else {
+ outerLoop = 1;
+ operandEntered = B_FALSE;
+ }
+
+ stmfRet = stmfGetTargetGroupList(&groupList);
+ if (stmfRet != STMF_STATUS_SUCCESS) {
+ switch (stmfRet) {
+ case STMF_ERROR_BUSY:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("resource busy"));
+ break;
+ case STMF_ERROR_SERVICE_NOT_FOUND:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service not found"));
+ break;
+ case STMF_ERROR_SERVICE_DATA_VERSION:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service version incorrect"));
+ break;
+ case STMF_ERROR_PERM:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("permission denied"));
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("unknown error"));
+ break;
+ }
+ return (1);
+ }
+
+ for (i = 0; i < outerLoop; i++) {
+ for (found = B_FALSE, j = 0; j < groupList->cnt; j++) {
+ (void) mbstowcs(groupNamePrint,
+ (char *)groupList->name[j],
+ sizeof (stmfGroupName) - 1);
+ groupNamePrint[sizeof (stmfGroupName) - 1] = 0;
+ if (operandEntered) {
+ (void) mbstowcs(operandName, operands[i],
+ sizeof (stmfGroupName) - 1);
+ operandName[sizeof (stmfGroupName) - 1] = 0;
+ if (wcscmp(operandName, groupNamePrint)
+ == 0) {
+ found = B_TRUE;
+ }
+ }
+ if ((found && operandEntered) || !operandEntered) {
+ (void) printf("Target Group: %ws\n",
+ groupNamePrint);
+ if (verbose) {
+ stmfRet = stmfGetTargetGroupMembers(
+ &(groupList->name[j]), &groupProps);
+ if (stmfRet != STMF_STATUS_SUCCESS) {
+ return (1);
+ }
+ printGroupProps(groupProps);
+ }
+ if (found && operandEntered) {
+ break;
+ }
+ }
+
+ }
+ if (operandEntered && !found) {
+ (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
+ operands[i], gettext("not found"));
+ ret = 1;
+ }
+ }
+ return (ret);
+}
+
+/*
+ * listLuFunc
+ *
+ * List the logical units and optionally the properties
+ *
+ */
+/*ARGSUSED*/
+static int
+listLuFunc(int operandLen, char *operands[], cmdOptions_t *options, void *args)
+{
+ cmdOptions_t *optionList = options;
+ boolean_t operandEntered;
+ int i, j;
+ int ret = 0;
+ int stmfRet;
+ int outerLoop;
+ unsigned int inGuid[sizeof (stmfGuid)];
+ stmfGuid cmpGuid;
+ boolean_t verbose = B_FALSE;
+ boolean_t found;
+ char sGuid[GUID_INPUT + 1];
+ stmfGuidList *luList;
+ stmfLogicalUnitProperties luProps;
+ boolean_t invalidInput = B_FALSE;
+ stmfViewEntryList *viewEntryList;
+
+ for (; optionList->optval; optionList++) {
+ switch (optionList->optval) {
+ case 'v':
+ verbose = B_TRUE;
+ break;
+ }
+ }
+
+ if ((stmfRet = stmfGetLogicalUnitList(&luList))
+ != STMF_STATUS_SUCCESS) {
+ switch (stmfRet) {
+ case STMF_ERROR_SERVICE_NOT_FOUND:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service not found"));
+ break;
+ case STMF_ERROR_BUSY:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("resource busy"));
+ break;
+ case STMF_ERROR_PERM:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("permission denied"));
+ break;
+ case STMF_ERROR_SERVICE_DATA_VERSION:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service version incorrect"));
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("list failed"));
+ break;
+ }
+ return (1);
+ }
+
+ if (operandLen > 0) {
+ operandEntered = B_TRUE;
+ outerLoop = operandLen;
+ } else {
+ operandEntered = B_FALSE;
+ outerLoop = 1;
+ }
+
+
+ for (invalidInput = B_FALSE, i = 0; i < outerLoop; i++) {
+ if (operandEntered) {
+ if (strlen(operands[i]) != GUID_INPUT) {
+ invalidInput = B_TRUE;
+ } else {
+ for (j = 0; j < GUID_INPUT; j++) {
+ if (!isxdigit(operands[i][j])) {
+ invalidInput = B_TRUE;
+ break;
+ }
+ }
+ }
+ if (invalidInput) {
+ (void) fprintf(stderr, "%s: %s: %s%d%s\n",
+ cmdName, operands[i], gettext("must be "),
+ GUID_INPUT,
+ gettext(" hexadecimal digits long"));
+ invalidInput = B_FALSE;
+ continue;
+ }
+
+ for (j = 0; j < GUID_INPUT; j++) {
+ sGuid[j] = tolower(operands[i][j]);
+ }
+ sGuid[j] = 0;
+
+ (void) sscanf(sGuid,
+ "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
+ &inGuid[0], &inGuid[1], &inGuid[2], &inGuid[3],
+ &inGuid[4], &inGuid[5], &inGuid[6], &inGuid[7],
+ &inGuid[8], &inGuid[9], &inGuid[10], &inGuid[11],
+ &inGuid[12], &inGuid[13], &inGuid[14], &inGuid[15]);
+
+ for (j = 0; j < sizeof (stmfGuid); j++) {
+ cmpGuid.guid[j] = inGuid[j];
+ }
+ }
+
+ for (found = B_FALSE, j = 0; j < luList->cnt; j++) {
+ if (operandEntered) {
+ if (bcmp(luList->guid[j].guid, cmpGuid.guid,
+ sizeof (stmfGuid)) == 0) {
+ found = B_TRUE;
+ }
+ }
+ if ((found && operandEntered) || !operandEntered) {
+ (void) printf("LU Name: ");
+ printGuid(&luList->guid[j], stdout);
+ (void) printf("\n");
+
+ if (verbose) {
+ stmfRet = stmfGetLogicalUnitProperties(
+ &(luList->guid[j]), &luProps);
+ if (stmfRet == STMF_STATUS_SUCCESS) {
+ printLuProps(&luProps);
+ } else {
+ (void) fprintf(stderr, "%s:",
+ cmdName);
+ printGuid(&luList->guid[j],
+ stderr);
+ (void) fprintf(stderr, "%s\n",
+ gettext(" get properties "
+ "failed"));
+ }
+ stmfRet = stmfGetViewEntryList(
+ &(luList->guid[j]),
+ &viewEntryList);
+ (void) printf(PROPS_FORMAT,
+ "View Entry Count");
+ if (stmfRet == STMF_STATUS_SUCCESS) {
+ (void) printf("%d",
+ viewEntryList->cnt);
+ } else {
+ (void) printf("unknown");
+ }
+ (void) printf("\n");
+ ret = printExtLuProps(
+ &(luList->guid[j]));
+ }
+ if (found && operandEntered) {
+ break;
+ }
+ }
+
+ }
+ if (operandEntered && !found) {
+ (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
+ operands[i], gettext("not found"));
+ ret = 1;
+ }
+ }
+
+ return (ret);
+}
+
+static void
+printGuid(stmfGuid *guid, FILE *stream)
+{
+ int i;
+ for (i = 0; i < 16; i++) {
+ (void) fprintf(stream, "%02X", guid->guid[i]);
+ }
+}
+
+static int
+printExtLuProps(stmfGuid *guid)
+{
+ int stmfRet;
+ luResource hdl = NULL;
+ int ret = 0;
+ char propVal[MAXNAMELEN];
+ size_t propValSize = sizeof (propVal);
+
+ if ((stmfRet = stmfGetLuResource(guid, &hdl))
+ != STMF_STATUS_SUCCESS) {
+ switch (stmfRet) {
+ case STMF_ERROR_BUSY:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("resource busy"));
+ break;
+ case STMF_ERROR_PERM:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("permission denied"));
+ break;
+ case STMF_ERROR_NOT_FOUND:
+ /* No error here */
+ return (0);
+ default:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("get extended properties failed"));
+ break;
+ }
+ return (1);
+ }
+
+ stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_FILENAME, propVal,
+ &propValSize);
+ (void) printf(PROPS_FORMAT, "Data File");
+ if (stmfRet == STMF_STATUS_SUCCESS) {
+ (void) printf("%s\n", propVal);
+ } else if (stmfRet == STMF_ERROR_NO_PROP) {
+ (void) printf("not set\n");
+ } else if (stmfRet == STMF_ERROR_NO_PROP_STANDBY) {
+ (void) printf("prop unavailable in standby\n");
+ } else {
+ (void) printf("<error retrieving property>\n");
+ ret++;
+ }
+
+ stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_META_FILENAME, propVal,
+ &propValSize);
+ (void) printf(PROPS_FORMAT, "Meta File");
+ if (stmfRet == STMF_STATUS_SUCCESS) {
+ (void) printf("%s\n", propVal);
+ } else if (stmfRet == STMF_ERROR_NO_PROP) {
+ (void) printf("not set\n");
+ } else if (stmfRet == STMF_ERROR_NO_PROP_STANDBY) {
+ (void) printf("prop unavailable in standby\n");
+ } else {
+ (void) printf("<error retrieving property>\n");
+ ret++;
+ }
+
+ stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_SIZE, propVal,
+ &propValSize);
+ (void) printf(PROPS_FORMAT, "Size");
+ if (stmfRet == STMF_STATUS_SUCCESS) {
+ (void) printf("%s\n", propVal);
+ } else if (stmfRet == STMF_ERROR_NO_PROP) {
+ (void) printf("not set\n");
+ } else if (stmfRet == STMF_ERROR_NO_PROP_STANDBY) {
+ (void) printf("prop unavailable in standby\n");
+ } else {
+ (void) printf("<error retrieving property>\n");
+ ret++;
+ }
+
+ stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_BLOCK_SIZE, propVal,
+ &propValSize);
+ (void) printf(PROPS_FORMAT, "Block Size");
+ if (stmfRet == STMF_STATUS_SUCCESS) {
+ (void) printf("%s\n", propVal);
+ } else if (stmfRet == STMF_ERROR_NO_PROP) {
+ (void) printf("not set\n");
+ } else if (stmfRet == STMF_ERROR_NO_PROP_STANDBY) {
+ (void) printf("prop unavailable in standby\n");
+ } else {
+ (void) printf("<error retrieving property>\n");
+ ret++;
+ }
+
+ stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_MGMT_URL, propVal,
+ &propValSize);
+ (void) printf(PROPS_FORMAT, "Management URL");
+ if (stmfRet == STMF_STATUS_SUCCESS) {
+ (void) printf("%s\n", propVal);
+ } else if (stmfRet == STMF_ERROR_NO_PROP) {
+ (void) printf("not set\n");
+ } else if (stmfRet == STMF_ERROR_NO_PROP_STANDBY) {
+ (void) printf("prop unavailable in standby\n");
+ } else {
+ (void) printf("<error retrieving property>\n");
+ ret++;
+ }
+
+ stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_VID, propVal,
+ &propValSize);
+ (void) printf(PROPS_FORMAT, "Vendor ID");
+ if (stmfRet == STMF_STATUS_SUCCESS) {
+ (void) printf("%s\n", propVal);
+ } else if (stmfRet == STMF_ERROR_NO_PROP) {
+ (void) printf("not set\n");
+ } else if (stmfRet == STMF_ERROR_NO_PROP_STANDBY) {
+ (void) printf("prop unavailable in standby\n");
+ } else {
+ (void) printf("<error retrieving property>\n");
+ ret++;
+ }
+
+ stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_PID, propVal,
+ &propValSize);
+ (void) printf(PROPS_FORMAT, "Product ID");
+ if (stmfRet == STMF_STATUS_SUCCESS) {
+ (void) printf("%s\n", propVal);
+ } else if (stmfRet == STMF_ERROR_NO_PROP) {
+ (void) printf("not set\n");
+ } else if (stmfRet == STMF_ERROR_NO_PROP_STANDBY) {
+ (void) printf("prop unavailable in standby\n");
+ } else {
+ (void) printf("<error retrieving property>\n");
+ ret++;
+ }
+
+ stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_SERIAL_NUM, propVal,
+ &propValSize);
+ (void) printf(PROPS_FORMAT, "Serial Num");
+ if (stmfRet == STMF_STATUS_SUCCESS) {
+ (void) printf("%s\n", propVal);
+ } else if (stmfRet == STMF_ERROR_NO_PROP) {
+ (void) printf("not set\n");
+ } else if (stmfRet == STMF_ERROR_NO_PROP_STANDBY) {
+ (void) printf("prop unavailable in standby\n");
+ } else {
+ (void) printf("<error retrieving property>\n");
+ ret++;
+ }
+
+ stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_WRITE_PROTECT, propVal,
+ &propValSize);
+ (void) printf(PROPS_FORMAT, "Write Protect");
+ if (stmfRet == STMF_STATUS_SUCCESS) {
+ (void) printf("%s\n",
+ strcasecmp(propVal, "true") ? "Disabled" : "Enabled");
+ } else if (stmfRet == STMF_ERROR_NO_PROP) {
+ (void) printf("not set\n");
+ } else if (stmfRet == STMF_ERROR_NO_PROP_STANDBY) {
+ (void) printf("prop unavailable in standby\n");
+ } else {
+ (void) printf("<error retrieving property>\n");
+ ret++;
+ }
+
+ stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_WRITE_CACHE_DISABLE, propVal,
+ &propValSize);
+ (void) printf(PROPS_FORMAT, "Writeback Cache");
+ if (stmfRet == STMF_STATUS_SUCCESS) {
+ (void) printf("%s\n",
+ strcasecmp(propVal, "true") ? "Enabled" : "Disabled");
+ } else if (stmfRet == STMF_ERROR_NO_PROP) {
+ (void) printf("not set\n");
+ } else if (stmfRet == STMF_ERROR_NO_PROP_STANDBY) {
+ (void) printf("prop unavailable in standby\n");
+ } else {
+ (void) printf("<error retrieving property>\n");
+ ret++;
+ }
+
+ stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_ACCESS_STATE, propVal,
+ &propValSize);
+ (void) printf(PROPS_FORMAT, "Access State");
+ if (stmfRet == STMF_STATUS_SUCCESS) {
+ if (strcmp(propVal, STMF_ACCESS_ACTIVE) == 0) {
+ (void) printf("%s\n", "Active");
+ } else if (strcmp(propVal,
+ STMF_ACCESS_ACTIVE_TO_STANDBY) == 0) {
+ (void) printf("%s\n", "Active->Standby");
+ } else if (strcmp(propVal, STMF_ACCESS_STANDBY) == 0) {
+ (void) printf("%s\n", "Standby");
+ } else if (strcmp(propVal,
+ STMF_ACCESS_STANDBY_TO_ACTIVE) == 0) {
+ (void) printf("%s\n", "Standby->Active");
+ } else {
+ (void) printf("%s\n", "Unknown");
+ }
+ } else if (stmfRet == STMF_ERROR_NO_PROP) {
+ (void) printf("not set\n");
+ } else {
+ (void) printf("<error retrieving property>\n");
+ ret++;
+ }
+
+done:
+ (void) stmfFreeLuResource(hdl);
+ return (ret);
+
+}
+
+
+/*
+ * printLuProps
+ *
+ * Prints the properties for a logical unit
+ *
+ */
+static void
+printLuProps(stmfLogicalUnitProperties *luProps)
+{
+ (void) printf(PROPS_FORMAT, "Operational Status");
+ switch (luProps->status) {
+ case STMF_LOGICAL_UNIT_ONLINE:
+ (void) printf("Online");
+ break;
+ case STMF_LOGICAL_UNIT_OFFLINE:
+ (void) printf("Offline");
+ break;
+ case STMF_LOGICAL_UNIT_ONLINING:
+ (void) printf("Onlining");
+ break;
+ case STMF_LOGICAL_UNIT_OFFLINING:
+ (void) printf("Offlining");
+ break;
+ case STMF_LOGICAL_UNIT_UNREGISTERED:
+ (void) printf("unregistered");
+ (void) strncpy(luProps->providerName, "unregistered",
+ sizeof (luProps->providerName));
+ break;
+ default:
+ (void) printf("unknown");
+ break;
+ }
+ (void) printf("\n");
+ (void) printf(PROPS_FORMAT, "Provider Name");
+ if (luProps->providerName[0] != 0) {
+ (void) printf("%s", luProps->providerName);
+ } else {
+ (void) printf("unknown");
+ }
+ (void) printf("\n");
+ (void) printf(PROPS_FORMAT, "Alias");
+ if (luProps->alias[0] != 0) {
+ (void) printf("%s", luProps->alias);
+ } else {
+ (void) printf("-");
+ }
+ (void) printf("\n");
+}
+
+/*
+ * printTargetProps
+ *
+ * Prints the properties for a target
+ *
+ */
+static void
+printTargetProps(stmfTargetProperties *targetProps)
+{
+ (void) printf(PROPS_FORMAT, "Operational Status");
+ switch (targetProps->status) {
+ case STMF_TARGET_PORT_ONLINE:
+ (void) printf("Online");
+ break;
+ case STMF_TARGET_PORT_OFFLINE:
+ (void) printf("Offline");
+ break;
+ case STMF_TARGET_PORT_ONLINING:
+ (void) printf("Onlining");
+ break;
+ case STMF_TARGET_PORT_OFFLINING:
+ (void) printf("Offlining");
+ break;
+ default:
+ (void) printf("unknown");
+ break;
+ }
+ (void) printf("\n");
+ (void) printf(PROPS_FORMAT, "Provider Name");
+ if (targetProps->providerName[0] != 0) {
+ (void) printf("%s", targetProps->providerName);
+ }
+ (void) printf("\n");
+ (void) printf(PROPS_FORMAT, "Alias");
+ if (targetProps->alias[0] != 0) {
+ (void) printf("%s", targetProps->alias);
+ } else {
+ (void) printf("-");
+ }
+ (void) printf("\n");
+ (void) printf(PROPS_FORMAT, "Protocol");
+ switch (targetProps->protocol) {
+ case STMF_PROTOCOL_FIBRE_CHANNEL:
+ (void) printf("%s", "Fibre Channel");
+ break;
+ case STMF_PROTOCOL_ISCSI:
+ (void) printf("%s", "iSCSI");
+ break;
+ case STMF_PROTOCOL_SRP:
+ (void) printf("%s", "SRP");
+ break;
+ case STMF_PROTOCOL_SAS:
+ (void) printf("%s", "SAS");
+ break;
+ default:
+ (void) printf("%s", "unknown");
+ break;
+ }
+
+ (void) printf("\n");
+}
+
+/*
+ * printSessionProps
+ *
+ * Prints the session data
+ *
+ */
+static void
+printSessionProps(stmfSessionList *sessionList)
+{
+ int i;
+ char *cTime;
+ wchar_t initiator[STMF_IDENT_LENGTH + 1];
+
+ (void) printf(PROPS_FORMAT, "Sessions");
+ (void) printf("%d\n", sessionList->cnt);
+ for (i = 0; i < sessionList->cnt; i++) {
+ (void) mbstowcs(initiator,
+ (char *)sessionList->session[i].initiator.ident,
+ STMF_IDENT_LENGTH);
+ initiator[STMF_IDENT_LENGTH] = 0;
+ (void) printf(LVL3_FORMAT, "Initiator: ");
+ (void) printf("%ws\n", initiator);
+ (void) printf(LVL4_FORMAT, "Alias: ");
+ if (sessionList->session[i].alias[0] != 0) {
+ (void) printf("%s", sessionList->session[i].alias);
+ } else {
+ (void) printf("-");
+ }
+ (void) printf("\n");
+ (void) printf(LVL4_FORMAT, "Logged in since: ");
+ cTime = ctime(&(sessionList->session[i].creationTime));
+ if (cTime != NULL) {
+ (void) printf("%s", cTime);
+ } else {
+ (void) printf("unknown\n");
+ }
+ }
+}
+
+static int
+getStmfState(stmfState *state)
+{
+ int ret;
+
+ ret = stmfGetState(state);
+ switch (ret) {
+ case STMF_STATUS_SUCCESS:
+ break;
+ case STMF_ERROR_PERM:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("permission denied"));
+ break;
+ case STMF_ERROR_SERVICE_NOT_FOUND:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service not found"));
+ break;
+ case STMF_ERROR_BUSY:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("resource busy"));
+ break;
+ case STMF_ERROR_SERVICE_DATA_VERSION:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service version incorrect"));
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %s: %d\n", cmdName,
+ gettext("unknown error"), ret);
+ break;
+ }
+ return (ret);
+}
+
+/*
+ * listStateFunc
+ *
+ * List the operational and config state of the stmf service
+ *
+ */
+/*ARGSUSED*/
+static int
+listStateFunc(int operandLen, char *operands[], cmdOptions_t *options,
+ void *args)
+{
+ int ret;
+ stmfState state;
+ boolean_t aluaEnabled;
+ uint32_t node;
+
+ if ((ret = getStmfState(&state)) != STMF_STATUS_SUCCESS)
+ return (ret);
+
+ (void) printf("%-18s: ", "Operational Status");
+ switch (state.operationalState) {
+ case STMF_SERVICE_STATE_ONLINE:
+ (void) printf("online");
+ break;
+ case STMF_SERVICE_STATE_OFFLINE:
+ (void) printf("offline");
+ break;
+ case STMF_SERVICE_STATE_ONLINING:
+ (void) printf("onlining");
+ break;
+ case STMF_SERVICE_STATE_OFFLINING:
+ (void) printf("offlining");
+ break;
+ default:
+ (void) printf("unknown");
+ break;
+ }
+ (void) printf("\n");
+ (void) printf("%-18s: ", "Config Status");
+ switch (state.configState) {
+ case STMF_CONFIG_STATE_NONE:
+ (void) printf("uninitialized");
+ break;
+ case STMF_CONFIG_STATE_INIT:
+ (void) printf("initializing");
+ break;
+ case STMF_CONFIG_STATE_INIT_DONE:
+ (void) printf("initialized");
+ break;
+ default:
+ (void) printf("unknown");
+ break;
+ }
+ (void) printf("\n");
+ ret = stmfGetAluaState(&aluaEnabled, &node);
+ switch (ret) {
+ case STMF_STATUS_SUCCESS:
+ break;
+ case STMF_ERROR_PERM:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("permission denied"));
+ break;
+ case STMF_ERROR_BUSY:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("resource busy"));
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %s: %d\n", cmdName,
+ gettext("unknown error"), ret);
+ break;
+ }
+ (void) printf("%-18s: ", "ALUA Status");
+ if (ret == STMF_STATUS_SUCCESS) {
+ if (aluaEnabled == B_TRUE) {
+ (void) printf("enabled");
+ } else {
+ (void) printf("disabled");
+ }
+ } else {
+ (void) printf("unknown");
+ }
+
+ (void) printf("\n");
+ (void) printf("%-18s: ", "ALUA Node");
+ if (ret == STMF_STATUS_SUCCESS) {
+ (void) printf("%d", node);
+ } else {
+ (void) printf("unknown");
+ }
+ (void) printf("\n");
+ return (ret);
+}
+
+/*
+ * listTargetFunc
+ *
+ * list the targets and optionally their properties
+ *
+ */
+/*ARGSUSED*/
+static int
+listTargetFunc(int operandLen, char *operands[], cmdOptions_t *options,
+ void *args)
+{
+ cmdOptions_t *optionList = options;
+ int ret = 0;
+ int stmfRet;
+ int i, j;
+ int outerLoop;
+ stmfSessionList *sessionList;
+ stmfDevid devid;
+ boolean_t operandEntered, found, verbose = B_FALSE;
+ stmfDevidList *targetList;
+ wchar_t targetIdent[STMF_IDENT_LENGTH + 1];
+ stmfTargetProperties targetProps;
+
+ if ((stmfRet = stmfGetTargetList(&targetList)) != STMF_STATUS_SUCCESS) {
+ switch (stmfRet) {
+ case STMF_ERROR_NOT_FOUND:
+ ret = 0;
+ break;
+ case STMF_ERROR_SERVICE_OFFLINE:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service offline"));
+ break;
+ case STMF_ERROR_BUSY:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("resource busy"));
+ break;
+ case STMF_ERROR_SERVICE_DATA_VERSION:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service version incorrect"));
+ break;
+ case STMF_ERROR_PERM:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("permission denied"));
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("unknown error"));
+ break;
+ }
+ return (1);
+ }
+
+ for (; optionList->optval; optionList++) {
+ switch (optionList->optval) {
+ case 'v':
+ verbose = B_TRUE;
+ break;
+ }
+ }
+
+ if (operandLen > 0) {
+ outerLoop = operandLen;
+ operandEntered = B_TRUE;
+ } else {
+ outerLoop = 1;
+ operandEntered = B_FALSE;
+ }
+
+ for (i = 0; i < outerLoop; i++) {
+ if (operandEntered) {
+ bzero(&devid, sizeof (devid));
+ (void) parseDevid(operands[i], &devid);
+ }
+ for (found = B_FALSE, j = 0; j < targetList->cnt; j++) {
+ if (operandEntered) {
+ if (bcmp(&devid, &(targetList->devid[j]),
+ sizeof (devid)) == 0) {
+ found = B_TRUE;
+ }
+ }
+ if ((found && operandEntered) || !operandEntered) {
+ (void) mbstowcs(targetIdent,
+ (char *)targetList->devid[j].ident,
+ STMF_IDENT_LENGTH);
+ targetIdent[STMF_IDENT_LENGTH] = 0;
+ (void) printf("Target: %ws\n", targetIdent);
+ if (verbose) {
+ stmfRet = stmfGetTargetProperties(
+ &(targetList->devid[j]),
+ &targetProps);
+ if (stmfRet == STMF_STATUS_SUCCESS) {
+ printTargetProps(&targetProps);
+ } else {
+ (void) fprintf(stderr, "%s:",
+ cmdName);
+ (void) fprintf(stderr, "%s\n",
+ gettext(" get properties"
+ " failed"));
+ }
+ stmfRet = stmfGetSessionList(
+ &(targetList->devid[j]),
+ &sessionList);
+ if (stmfRet == STMF_STATUS_SUCCESS) {
+ printSessionProps(sessionList);
+ } else {
+ (void) fprintf(stderr, "%s:",
+ cmdName);
+ (void) fprintf(stderr, "%s\n",
+ gettext(" get session info"
+ " failed"));
+ }
+ }
+ if (found && operandEntered) {
+ break;
+ }
+ }
+
+ }
+ if (operandEntered && !found) {
+ (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
+ operands[i], "not found");
+ ret = 1;
+ }
+ }
+ return (ret);
+}
+
+/*
+ * listViewFunc
+ *
+ * list the view entries for the specified logical unit
+ *
+ */
+/*ARGSUSED*/
+static int
+listViewFunc(int operandLen, char *operands[], cmdOptions_t *options,
+ void *args)
+{
+ stmfViewEntryList *viewEntryList;
+ stmfGuid inGuid;
+ unsigned int guid[sizeof (stmfGuid)];
+ int ret = 0;
+ int stmfRet;
+ int i, j, outerLoop;
+ boolean_t found = B_TRUE;
+ boolean_t operandEntered;
+ uint16_t outputLuNbr;
+ wchar_t groupName[sizeof (stmfGroupName)];
+ char sGuid[GUID_INPUT + 1];
+
+
+ for (; options->optval; options++) {
+ switch (options->optval) {
+ case 'l':
+ if (strlen(options->optarg) != GUID_INPUT) {
+ (void) fprintf(stderr,
+ "%s: %s: %s%d%s\n",
+ cmdName, options->optarg,
+ gettext("must be "), GUID_INPUT,
+ gettext(" hexadecimal digits"
+ " long"));
+ return (1);
+ }
+ bcopy(options->optarg, sGuid, GUID_INPUT);
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %c: %s\n",
+ cmdName, options->optval,
+ gettext("unknown option"));
+ return (1);
+ }
+ }
+
+ if (operandLen > 0) {
+ outerLoop = operandLen;
+ operandEntered = B_TRUE;
+ } else {
+ outerLoop = 1;
+ operandEntered = B_FALSE;
+ }
+
+ for (i = 0; i < 32; i++)
+ sGuid[i] = tolower(sGuid[i]);
+ sGuid[i] = 0;
+
+ (void) sscanf(sGuid, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
+ &guid[0], &guid[1], &guid[2], &guid[3], &guid[4], &guid[5],
+ &guid[6], &guid[7], &guid[8], &guid[9], &guid[10], &guid[11],
+ &guid[12], &guid[13], &guid[14], &guid[15]);
+
+ for (i = 0; i < sizeof (stmfGuid); i++) {
+ inGuid.guid[i] = guid[i];
+ }
+
+ if ((stmfRet = stmfGetViewEntryList(&inGuid, &viewEntryList))
+ != STMF_STATUS_SUCCESS) {
+
+ switch (stmfRet) {
+ case STMF_ERROR_BUSY:
+ (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
+ sGuid, gettext("resource busy"));
+ break;
+ case STMF_ERROR_SERVICE_NOT_FOUND:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service not found"));
+ break;
+ case STMF_ERROR_SERVICE_DATA_VERSION:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service version incorrect"));
+ break;
+ case STMF_ERROR_PERM:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("permission denied"));
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
+ sGuid, gettext("unknown error"));
+ break;
+ }
+ return (1);
+ }
+
+ if (viewEntryList->cnt == 0) {
+ (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
+ sGuid, gettext("no views found"));
+ return (1);
+ }
+
+ for (i = 0; i < outerLoop; i++) {
+ for (found = B_FALSE, j = 0; j < viewEntryList->cnt; j++) {
+ if (operandEntered) {
+ if (atoi(operands[i]) ==
+ viewEntryList->ve[j].veIndex) {
+ found = B_TRUE;
+ }
+ }
+ if ((found && operandEntered) || !operandEntered) {
+ (void) printf("View Entry: %d\n",
+ viewEntryList->ve[j].veIndex);
+ (void) printf(VIEW_FORMAT, "Host group");
+ if (viewEntryList->ve[j].allHosts) {
+ (void) printf("All\n");
+ } else {
+ (void) mbstowcs(groupName,
+ viewEntryList->ve[j].hostGroup,
+ sizeof (stmfGroupName) - 1);
+ groupName[sizeof (stmfGroupName) - 1]
+ = 0;
+ (void) printf("%ws\n", groupName);
+ }
+ (void) printf(VIEW_FORMAT, "Target group");
+ if (viewEntryList->ve[j].allTargets) {
+ (void) printf("All\n");
+ } else {
+ (void) mbstowcs(groupName,
+ viewEntryList->ve[j].targetGroup,
+ sizeof (stmfGroupName) - 1);
+ groupName[sizeof (stmfGroupName) - 1]
+ = 0;
+ (void) printf("%ws\n", groupName);
+ }
+ outputLuNbr = ((viewEntryList->ve[j].luNbr[0] &
+ 0x3F) << 8) | viewEntryList->ve[j].luNbr[1];
+ (void) printf(VIEW_FORMAT, "LUN");
+ (void) printf("%d\n", outputLuNbr);
+ if (found && operandEntered) {
+ break;
+ }
+ }
+ }
+ if (operandEntered && !found) {
+ (void) fprintf(stderr, "%s: %s, %s: %s\n", cmdName,
+ sGuid, operands[i], gettext("not found"));
+ ret = 1;
+ }
+ }
+
+ return (ret);
+}
+
+
+/*
+ * onlineOfflineLu
+ *
+ * Purpose: Online or offline a logical unit
+ *
+ * lu - logical unit to online or offline
+ *
+ * state - ONLINE_LU
+ * OFFLINE_LU
+ */
+static int
+onlineOfflineLu(char *lu, int state)
+{
+ char sGuid[GUID_INPUT + 1];
+ stmfGuid inGuid;
+ unsigned int guid[sizeof (stmfGuid)];
+ int i;
+ int ret = 0, stmfRet;
+ stmfLogicalUnitProperties luProps;
+
+ if (strlen(lu) != GUID_INPUT) {
+ (void) fprintf(stderr, "%s: %s: %s %d %s\n", cmdName, lu,
+ gettext("must be"), GUID_INPUT,
+ gettext("hexadecimal digits long"));
+ return (1);
+ }
+
+ bcopy(lu, sGuid, GUID_INPUT);
+
+ for (i = 0; i < 32; i++)
+ sGuid[i] = tolower(sGuid[i]);
+ sGuid[i] = 0;
+
+ (void) sscanf(sGuid, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
+ &guid[0], &guid[1], &guid[2], &guid[3], &guid[4], &guid[5],
+ &guid[6], &guid[7], &guid[8], &guid[9], &guid[10], &guid[11],
+ &guid[12], &guid[13], &guid[14], &guid[15]);
+
+ for (i = 0; i < sizeof (stmfGuid); i++) {
+ inGuid.guid[i] = guid[i];
+ }
+
+ if (state == ONLINE_LU) {
+ ret = stmfOnlineLogicalUnit(&inGuid);
+ } else if (state == OFFLINE_LU) {
+ ret = stmfOfflineLogicalUnit(&inGuid);
+ } else {
+ return (STMFADM_FAILURE);
+ }
+ if (ret != STMF_STATUS_SUCCESS) {
+ switch (ret) {
+ case STMF_ERROR_PERM:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("permission denied"));
+ break;
+ case STMF_ERROR_SERVICE_NOT_FOUND:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service not found"));
+ break;
+ case STMF_ERROR_BUSY:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("resource busy"));
+ break;
+ case STMF_ERROR_NOT_FOUND:
+ (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
+ lu, gettext("not found"));
+ break;
+ case STMF_ERROR_SERVICE_DATA_VERSION:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service version incorrect"));
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("unknown error"));
+ break;
+ }
+ } else {
+ struct timespec ts = {0};
+ unsigned int count = 0;
+ uint32_t ret_state;
+
+ ret_state = (state == ONLINE_LU) ?
+ STMF_LOGICAL_UNIT_ONLINING : STMF_LOGICAL_UNIT_OFFLINING;
+ ts.tv_nsec = DELAYED_EXEC_WAIT_INTERVAL;
+
+ /* CONSTCOND */
+ while (1) {
+ stmfRet = stmfGetLogicalUnitProperties(&inGuid,
+ &luProps);
+ if (stmfRet == STMF_STATUS_SUCCESS)
+ ret_state = luProps.status;
+
+ if ((state == ONLINE_LU &&
+ ret_state == STMF_LOGICAL_UNIT_ONLINE) ||
+ (state == OFFLINE_LU &&
+ ret_state == STMF_LOGICAL_UNIT_OFFLINE))
+ return (STMFADM_SUCCESS);
+
+ if ((state == ONLINE_LU &&
+ ret_state == STMF_LOGICAL_UNIT_OFFLINE) ||
+ (state == OFFLINE_LU &&
+ ret_state == STMF_LOGICAL_UNIT_ONLINE))
+ return (STMFADM_FAILURE);
+
+ if (++count == DELAYED_EXEC_WAIT_MAX) {
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("Logical Unit state change request "
+ "submitted. Waiting for completion "
+ "timed out"));
+ return (STMFADM_FAILURE);
+ }
+ (void) nanosleep(&ts, NULL);
+ }
+ }
+ return (STMFADM_FAILURE);
+}
+
+/*
+ * onlineLuFunc
+ *
+ * Purpose: Online a logical unit
+ *
+ */
+/*ARGSUSED*/
+static int
+onlineLuFunc(int operandLen, char *operands[], cmdOptions_t *options,
+ void *args)
+{
+ int ret;
+ stmfState state;
+
+ ret = getStmfState(&state);
+ if (ret != STMF_STATUS_SUCCESS)
+ return (ret);
+ if (state.operationalState == STMF_SERVICE_STATE_OFFLINE ||
+ state.operationalState == STMF_SERVICE_STATE_OFFLINING) {
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service is offline"));
+ return (1);
+ }
+ return (onlineOfflineLu(operands[0], ONLINE_LU));
+}
+
+/*
+ * offlineLuFunc
+ *
+ * Purpose: Offline a logical unit
+ *
+ */
+/*ARGSUSED*/
+static int
+offlineLuFunc(int operandLen, char *operands[], cmdOptions_t *options,
+ void *args)
+{
+ return (onlineOfflineLu(operands[0], OFFLINE_LU));
+}
+
+/*
+ * onlineOfflineTarget
+ *
+ * Purpose: Online or offline a target
+ *
+ * target - target to online or offline
+ *
+ * state - ONLINE_TARGET
+ * OFFLINE_TARGET
+ */
+static int
+onlineOfflineTarget(char *target, int state)
+{
+ int ret = 0, stmfRet = 0;
+ stmfDevid devid;
+ stmfTargetProperties targetProps;
+
+ if (parseDevid(target, &devid) != 0) {
+ (void) fprintf(stderr, "%s: %s: %s\n",
+ cmdName, target, gettext("unrecognized device id"));
+ return (1);
+ }
+ if (state == ONLINE_TARGET) {
+ ret = stmfOnlineTarget(&devid);
+ } else if (state == OFFLINE_TARGET) {
+ ret = stmfOfflineTarget(&devid);
+ } else {
+ return (STMFADM_FAILURE);
+ }
+ if (ret != STMF_STATUS_SUCCESS) {
+ switch (ret) {
+ case STMF_ERROR_PERM:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("permission denied"));
+ break;
+ case STMF_ERROR_SERVICE_NOT_FOUND:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service not found"));
+ break;
+ case STMF_ERROR_BUSY:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("resource busy"));
+ break;
+ case STMF_ERROR_NOT_FOUND:
+ (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
+ target, gettext("not found"));
+ break;
+ case STMF_ERROR_SERVICE_DATA_VERSION:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service version incorrect"));
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("unknown error"));
+ break;
+ }
+ } else {
+ struct timespec ts = {0};
+ unsigned int count = 0;
+ uint32_t ret_state;
+
+ ret_state = (state == ONLINE_TARGET) ?
+ STMF_TARGET_PORT_ONLINING : STMF_TARGET_PORT_OFFLINING;
+ ts.tv_nsec = DELAYED_EXEC_WAIT_INTERVAL;
+
+ /* CONSTCOND */
+ while (1) {
+ stmfRet = stmfGetTargetProperties(&devid, &targetProps);
+ if (stmfRet == STMF_STATUS_SUCCESS)
+ ret_state = targetProps.status;
+
+ if ((state == ONLINE_TARGET &&
+ ret_state == STMF_TARGET_PORT_ONLINE) ||
+ (state == OFFLINE_TARGET &&
+ ret_state == STMF_TARGET_PORT_OFFLINE)) {
+ return (STMFADM_SUCCESS);
+ }
+
+ if ((state == ONLINE_TARGET &&
+ ret_state == STMF_TARGET_PORT_OFFLINE) ||
+ (state == OFFLINE_TARGET &&
+ ret_state == STMF_TARGET_PORT_ONLINE)) {
+ return (STMFADM_FAILURE);
+ }
+
+ if (++count == DELAYED_EXEC_WAIT_MAX) {
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("Target state change request "
+ "submitted. Waiting for completion "
+ "timed out."));
+ return (STMFADM_FAILURE);
+ }
+ (void) nanosleep(&ts, NULL);
+ }
+ }
+ return (STMFADM_FAILURE);
+}
+
+/*
+ * onlineTargetFunc
+ *
+ * Purpose: Online a target
+ *
+ */
+/*ARGSUSED*/
+static int
+onlineTargetFunc(int operandLen, char *operands[], cmdOptions_t *options,
+ void *args)
+{
+ int ret;
+ stmfState state;
+
+ ret = getStmfState(&state);
+ if (ret != STMF_STATUS_SUCCESS)
+ return (ret);
+ if (state.operationalState == STMF_SERVICE_STATE_OFFLINE ||
+ state.operationalState == STMF_SERVICE_STATE_OFFLINING) {
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service is offline"));
+ return (1);
+ }
+ return (onlineOfflineTarget(operands[0], ONLINE_TARGET));
+}
+
+/*
+ * offlineTargetFunc
+ *
+ * Purpose: Offline a target
+ *
+ */
+/*ARGSUSED*/
+static int
+offlineTargetFunc(int operandLen, char *operands[], cmdOptions_t *options,
+ void *args)
+{
+ return (onlineOfflineTarget(operands[0], OFFLINE_TARGET));
+}
+
+
+/*ARGSUSED*/
+static int
+removeHostGroupMemberFunc(int operandLen, char *operands[],
+ cmdOptions_t *options, void *args)
+{
+ int i;
+ int ret = 0;
+ int stmfRet;
+ stmfGroupName groupName = {0};
+ stmfDevid devid;
+ wchar_t groupNamePrint[sizeof (stmfGroupName)] = {0};
+
+ for (; options->optval; options++) {
+ switch (options->optval) {
+ case 'g':
+ (void) mbstowcs(groupNamePrint, options->optarg,
+ sizeof (stmfGroupName) - 1);
+ bcopy(options->optarg, groupName,
+ strlen(options->optarg));
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %c: %s\n",
+ cmdName, options->optval,
+ gettext("unknown option"));
+ return (1);
+ }
+ }
+
+ for (i = 0; i < operandLen; i++) {
+ if (parseDevid(operands[i], &devid) != 0) {
+ (void) fprintf(stderr, "%s: %s: %s\n",
+ cmdName, operands[i],
+ gettext("unrecognized device id"));
+ ret++;
+ continue;
+ }
+ stmfRet = stmfRemoveFromHostGroup(&groupName, &devid);
+ switch (stmfRet) {
+ case STMF_STATUS_SUCCESS:
+ break;
+ case STMF_ERROR_MEMBER_NOT_FOUND:
+ (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
+ operands[i], gettext("not found"));
+ ret++;
+ break;
+ case STMF_ERROR_GROUP_NOT_FOUND:
+ (void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
+ groupNamePrint, gettext("not found"));
+ ret++;
+ break;
+ case STMF_ERROR_BUSY:
+ (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
+ operands[i], "resource busy");
+ ret++;
+ break;
+ case STMF_ERROR_SERVICE_NOT_FOUND:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service not found"));
+ ret++;
+ break;
+ case STMF_ERROR_SERVICE_DATA_VERSION:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service version incorrect"));
+ ret++;
+ break;
+ case STMF_ERROR_PERM:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("permission denied"));
+ ret++;
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
+ operands[i], gettext("unknown error"));
+ ret++;
+ break;
+ }
+ }
+
+ return (ret);
+}
+
+/*
+ * removeTargetGroupMemberFunc
+ *
+ * Removes one or more members from a target group
+ *
+ */
+/*ARGSUSED*/
+static int
+removeTargetGroupMemberFunc(int operandLen, char *operands[],
+ cmdOptions_t *options, void *args)
+{
+ int i;
+ int ret = 0;
+ int stmfRet;
+ stmfGroupName groupName = {0};
+ stmfDevid devid;
+ wchar_t groupNamePrint[sizeof (stmfGroupName)] = {0};
+
+ for (; options->optval; options++) {
+ switch (options->optval) {
+ case 'g':
+ (void) mbstowcs(groupNamePrint, options->optarg,
+ sizeof (stmfGroupName) - 1);
+ bcopy(options->optarg, groupName,
+ strlen(options->optarg));
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %c: %s\n",
+ cmdName, options->optval,
+ gettext("unknown option"));
+ return (1);
+ }
+ }
+
+ for (i = 0; i < operandLen; i++) {
+ if (parseDevid(operands[i], &devid) != 0) {
+ (void) fprintf(stderr, "%s: %s: %s\n",
+ cmdName, operands[i],
+ gettext("unrecognized device id"));
+ ret++;
+ continue;
+ }
+ stmfRet = stmfRemoveFromTargetGroup(&groupName, &devid);
+ switch (stmfRet) {
+ case STMF_STATUS_SUCCESS:
+ break;
+ case STMF_ERROR_MEMBER_NOT_FOUND:
+ (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
+ operands[i], gettext("not found"));
+ ret++;
+ break;
+ case STMF_ERROR_GROUP_NOT_FOUND:
+ (void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
+ groupNamePrint, gettext("not found"));
+ ret++;
+ break;
+ case STMF_ERROR_BUSY:
+ (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
+ operands[i], gettext("resource busy"));
+ ret++;
+ break;
+ case STMF_ERROR_SERVICE_NOT_FOUND:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service not found"));
+ ret++;
+ break;
+ case STMF_ERROR_PERM:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("permission denied"));
+ ret++;
+ break;
+ case STMF_ERROR_SERVICE_DATA_VERSION:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service version incorrect"));
+ ret++;
+ break;
+ case STMF_ERROR_TG_ONLINE:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF target must be offline"));
+ ret++;
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
+ operands[i], gettext("unknown error"));
+ ret++;
+ break;
+ }
+ }
+
+ return (ret);
+}
+
+/*
+ * removeViewFunc
+ *
+ * Removes one or more view entries from a logical unit
+ *
+ */
+/*ARGSUSED*/
+static int
+removeViewFunc(int operandLen, char *operands[], cmdOptions_t *options,
+ void *args)
+{
+ char sGuid[GUID_INPUT + 1];
+ stmfViewEntryList *viewEntryList;
+ stmfGuid inGuid;
+ uint32_t count;
+ unsigned int guid[sizeof (stmfGuid)];
+ char *endPtr;
+ uint32_t veNbr;
+ int i;
+ boolean_t all = B_FALSE;
+ boolean_t luInput = B_FALSE;
+ int ret = 0;
+ int stmfRet;
+
+ /* Note: 'l' is required */
+ for (; options->optval; options++) {
+ switch (options->optval) {
+ case 'l':
+ if (strlen(options->optarg) != GUID_INPUT) {
+ (void) fprintf(stderr,
+ "%s: %s: %s %d %s\n",
+ cmdName, options->optarg,
+ gettext("must be"), GUID_INPUT,
+ gettext("hexadecimal digits long"));
+ return (1);
+ }
+ bcopy(options->optarg, sGuid, GUID_INPUT);
+ luInput = B_TRUE;
+ break;
+ case 'a':
+ /* removing all view entries for this GUID */
+ all = B_TRUE;
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %c: %s\n",
+ cmdName, options->optval,
+ "unknown option");
+ return (1);
+ }
+ }
+
+ if (!all && operandLen == 0) {
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("no view entries specified"));
+ return (1);
+ }
+
+ if (!luInput) {
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("logical unit (-l) not specified"));
+ return (1);
+ }
+
+ for (i = 0; i < 32; i++)
+ sGuid[i] = tolower(sGuid[i]);
+ sGuid[i] = 0;
+
+ (void) sscanf(sGuid, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
+ &guid[0], &guid[1], &guid[2], &guid[3], &guid[4], &guid[5],
+ &guid[6], &guid[7], &guid[8], &guid[9], &guid[10], &guid[11],
+ &guid[12], &guid[13], &guid[14], &guid[15]);
+
+ for (i = 0; i < sizeof (stmfGuid); i++) {
+ inGuid.guid[i] = guid[i];
+ }
+
+ if ((stmfRet = stmfGetViewEntryList(&inGuid, &viewEntryList))
+ != STMF_STATUS_SUCCESS) {
+
+ switch (stmfRet) {
+ case STMF_ERROR_BUSY:
+ (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
+ sGuid, gettext("resource busy"));
+ break;
+ case STMF_ERROR_SERVICE_NOT_FOUND:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service not found"));
+ break;
+ case STMF_ERROR_SERVICE_DATA_VERSION:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service version incorrect"));
+ break;
+ case STMF_ERROR_PERM:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("permission denied"));
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
+ sGuid, gettext("unknown error"));
+ break;
+ }
+ return (1);
+ }
+
+ if (viewEntryList->cnt == 0) {
+ (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
+ sGuid, gettext("no views found"));
+ return (1);
+ }
+
+ if (all) {
+ count = viewEntryList->cnt;
+ } else {
+ count = operandLen;
+ }
+
+ for (i = 0; i < count; i++) {
+ if (all) {
+ veNbr = viewEntryList->ve[i].veIndex;
+ } else {
+ endPtr = NULL;
+ veNbr = strtol(operands[i], &endPtr, 10);
+ if (endPtr && *endPtr != 0) {
+ (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
+ operands[i], gettext("invalid input"));
+ continue;
+ }
+ }
+ stmfRet = stmfRemoveViewEntry(&inGuid, veNbr);
+ switch (stmfRet) {
+ case STMF_STATUS_SUCCESS:
+ break;
+ case STMF_ERROR_NOT_FOUND:
+ (void) fprintf(stderr, "%s: %s: %d: %s\n",
+ cmdName, sGuid, veNbr,
+ gettext("not found"));
+ ret++;
+ break;
+ case STMF_ERROR_BUSY:
+ (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
+ sGuid, gettext("resource busy"));
+ ret++;
+ break;
+ case STMF_ERROR_SERVICE_NOT_FOUND:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service not found"));
+ ret++;
+ break;
+ case STMF_ERROR_CONFIG_NONE:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service is not initialized"));
+ ret++;
+ break;
+ case STMF_ERROR_SERVICE_DATA_VERSION:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service version incorrect"));
+ ret++;
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %s, %d: %s",
+ cmdName, sGuid, veNbr,
+ gettext("unknown error"));
+ ret++;
+ break;
+ }
+ }
+
+ return (ret);
+}
+
+/*
+ * input:
+ * execFullName - exec name of program (argv[0])
+ *
+ * copied from usr/src/cmd/zoneadm/zoneadm.c in OS/Net
+ * (changed name to lowerCamelCase to keep consistent with this file)
+ *
+ * Returns:
+ * command name portion of execFullName
+ */
+static char *
+getExecBasename(char *execFullname)
+{
+ char *lastSlash, *execBasename;
+
+ /* guard against '/' at end of command invocation */
+ for (;;) {
+ lastSlash = strrchr(execFullname, '/');
+ if (lastSlash == NULL) {
+ execBasename = execFullname;
+ break;
+ } else {
+ execBasename = lastSlash + 1;
+ if (*execBasename == '\0') {
+ *lastSlash = '\0';
+ continue;
+ }
+ break;
+ }
+ }
+ return (execBasename);
+}
+
+int
+main(int argc, char *argv[])
+{
+ synTables_t synTables;
+ char versionString[VERSION_STRING_MAX_LEN];
+ int ret;
+ int funcRet;
+ void *subcommandArgs = NULL;
+
+ (void) setlocale(LC_ALL, "");
+ (void) textdomain(TEXT_DOMAIN);
+ /* set global command name */
+ cmdName = getExecBasename(argv[0]);
+
+ (void) snprintf(versionString, VERSION_STRING_MAX_LEN, "%s.%s",
+ VERSION_STRING_MAJOR, VERSION_STRING_MINOR);
+ synTables.versionString = versionString;
+ synTables.longOptionTbl = &longOptions[0];
+ synTables.subCommandPropsTbl = &subcommands[0];
+
+ ret = cmdParse(argc, argv, synTables, subcommandArgs, &funcRet);
+ if (ret != 0) {
+ return (ret);
+ }
+
+ return (funcRet);
+} /* end main */
diff --git a/usr/src/cmd/stmfadm/stmfadm.h b/usr/src/cmd/stmfadm/stmfadm.h
new file mode 100644
index 0000000..2224db9
--- /dev/null
+++ b/usr/src/cmd/stmfadm/stmfadm.h
@@ -0,0 +1,73 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _STMFADM_H
+#define _STMFADM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libintl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <inttypes.h>
+#include <cmdparse.h>
+
+/* DEFINES */
+
+/* subcommands */
+#define ADD_MEMBER SUBCOMMAND(0)
+#define ADD_VIEW SUBCOMMAND(1)
+#define CREATE_I_GROUP SUBCOMMAND(2)
+#define CREATE_T_GROUP SUBCOMMAND(3)
+#define DELETE_GROUP SUBCOMMAND(4)
+#define LIST_INIT SUBCOMMAND(5)
+#define LIST_INIT_GROUP SUBCOMMAND(6)
+#define LIST_TARGET_GROUP SUBCOMMAND(7)
+#define LIST_VIEW SUBCOMMAND(8)
+#define REMOVE_MEMBER SUBCOMMAND(9)
+#define REMOVE_VIEW SUBCOMMAND(10)
+
+
+#define OPERANDSTRING_INITIATOR "initiator-name"
+#define OPERANDSTRING_LU "LU-name"
+#define OPERANDSTRING_GROUP_MEMBER "group-member"
+#define OPERANDSTRING_GROUP_NAME "group-name"
+#define OPERANDSTRING_TARGET "target-name"
+#define OPERANDSTRING_VIEW_ENTRY "ve-number"
+
+#define VERSION_STRING_MAX_LEN 10
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _STMFADM_H */
diff --git a/usr/src/cmd/stmfsvc/stmf.xml b/usr/src/cmd/stmfsvc/stmf.xml
new file mode 100644
index 0000000..b3119da
--- /dev/null
+++ b/usr/src/cmd/stmfsvc/stmf.xml
@@ -0,0 +1,119 @@
+<?xml version='1.0'?>
+<!DOCTYPE service_bundle SYSTEM '/usr/share/lib/xml/dtd/service_bundle.dtd.1'>
+
+<!--
+
+CDDL HEADER START
+
+The contents of this file are subject to the terms of the
+Common Development and Distribution License (the "License").
+You may not use this file except in compliance with the License.
+
+You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+or http://www.opensolaris.org/os/licensing.
+See the License for the specific language governing permissions
+and limitations under the License.
+
+When distributing Covered Code, include this CDDL HEADER in each
+file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+If applicable, add the following below this CDDL HEADER, with the
+fields enclosed by brackets "[]" replaced with your own identifying
+information: Portions Copyright [yyyy] [name of copyright owner]
+
+CDDL HEADER END
+
+Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+Use is subject to license terms.
+
+
+Service manifests for SCSI Target Mode Framework
+-->
+
+<!--
+
+-->
+
+<service_bundle type='manifest' name='stmf'>
+
+<service
+ name='system/stmf'
+ type='service'
+ version='1'>
+
+ <create_default_instance enabled='false' />
+
+ <single_instance/>
+
+ <dependency name = 'filesystem_local'
+ grouping='require_all'
+ restart_on='none'
+ type='service'>
+ <service_fmri
+ value='svc:/system/filesystem/local:default'/>
+ </dependency>
+
+ <exec_method
+ type='method'
+ name='start'
+ exec='/lib/svc/method/svc-stmf start'
+ timeout_seconds='600'>
+ <method_context>
+ <method_credential
+ user='root'
+ group='root'
+ privileges='basic,sys_devices'
+ />
+ </method_context>
+ </exec_method>
+
+ <exec_method
+ type='method'
+ name='stop'
+ exec='/lib/svc/method/svc-stmf stop'
+ timeout_seconds='600'>
+ <method_context>
+ <method_credential
+ user='root'
+ group='root'
+ privileges='basic,sys_devices'
+ />
+ </method_context>
+ </exec_method>
+
+ <property_group name='startd' type='framework'>
+ <propval name='duration' type='astring'
+ value='transient' />
+ </property_group>
+
+ <property_group name='general' type='framework'>
+ <!-- to start stop stmf -->
+ <propval name='action_authorization' type='astring'
+ value='solaris.smf.manage.stmf' />
+ </property_group>
+
+ <property_group name='host_groups' type='application'>
+ </property_group>
+
+ <property_group name='target_groups' type='application'>
+ </property_group>
+
+
+ <stability value='Evolving' />
+
+ <template>
+ <common_name>
+ <loctext xml:lang='C'>
+ STMF
+ </loctext>
+ </common_name>
+ <documentation>
+ <manpage title='stmf' section='7D'
+ manpath='/usr/share/man' />
+ <manpage title='stmfadm' section='1M'
+ manpath='/usr/share /man' />
+ </documentation>
+ </template>
+
+</service>
+
+</service_bundle>
diff --git a/usr/src/cmd/stmfsvc/stmfsvc.c b/usr/src/cmd/stmfsvc/stmfsvc.c
new file mode 100644
index 0000000..814ebc2
--- /dev/null
+++ b/usr/src/cmd/stmfsvc/stmfsvc.c
@@ -0,0 +1,307 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <strings.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <libintl.h>
+#include <errno.h>
+#include <time.h>
+#include <string.h>
+#include <assert.h>
+#include <getopt.h>
+#include <cmdparse.h>
+#include <libstmf.h>
+#include <signal.h>
+#include <pthread.h>
+#include <locale.h>
+
+static int svcStart(int, char **, cmdOptions_t *, void *);
+static int svcStop(int, char **, cmdOptions_t *, void *);
+static int online();
+
+/*
+ * MAJOR - This should only change when there is an incompatible change made
+ * to the interfaces or the output.
+ *
+ * MINOR - This should change whenever there is a new command or new feature
+ * with no incompatible change.
+ */
+#define VERSION_STRING_MAJOR "1"
+#define VERSION_STRING_MINOR "0"
+#define VERSION_STRING_MAX_LEN 10
+
+/* 10 ms sleep in nanoseconds */
+#define TEN_MS_NANOSLEEP 10000000
+
+/* tables set up based on cmdparse instructions */
+
+/* add new options here */
+optionTbl_t longOptions[] = {
+ {NULL, 0, 0, 0}
+};
+
+/*
+ * Add new subcommands here
+ */
+subCommandProps_t subcommands[] = {
+ {"start", svcStart, NULL, NULL, NULL, OPERAND_NONE, NULL},
+ {"stop", svcStop, NULL, NULL, NULL, OPERAND_NONE, NULL},
+ {NULL, 0, NULL, NULL, 0, NULL, 0, NULL}
+};
+
+/* globals */
+char *cmdName;
+
+/*
+ * svcStop
+ *
+ * Offlines the stmf service
+ *
+ */
+/*ARGSUSED*/
+static int
+svcStop(int operandLen, char *operands[], cmdOptions_t *options,
+ void *args)
+{
+ int stmfRet;
+ int ret = 0;
+ stmfState state;
+ boolean_t serviceOffline = B_FALSE;
+ struct timespec rqtp;
+
+ bzero(&rqtp, sizeof (rqtp));
+
+ rqtp.tv_nsec = TEN_MS_NANOSLEEP;
+
+ if ((stmfRet = stmfOffline()) != STMF_STATUS_SUCCESS) {
+ switch (stmfRet) {
+ case STMF_ERROR_PERM:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("permission denied"));
+ break;
+ case STMF_ERROR_SERVICE_NOT_FOUND:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service not found"));
+ break;
+ case STMF_ERROR_SERVICE_OFFLINE:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service already offline"));
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("unable to offline service"));
+ break;
+ }
+ return (1);
+ }
+
+ /* wait for service offline */
+ while (!serviceOffline) {
+ stmfRet = stmfGetState(&state);
+ if (stmfRet != STMF_STATUS_SUCCESS) {
+ ret = 1;
+ break;
+ }
+ if (state.operationalState == STMF_SERVICE_STATE_OFFLINE) {
+ serviceOffline = B_TRUE;
+ } else {
+ (void) nanosleep(&rqtp, NULL);
+ }
+ }
+
+ return (ret);
+}
+
+/*
+ * loadConfig
+ *
+ * Loads the stmf config from the SMF repository
+ *
+ */
+/*ARGSUSED*/
+static int
+svcStart(int operandLen, char *operands[], cmdOptions_t *options,
+ void *args)
+{
+ int stmfRet;
+ int ret = 0;
+ (void) stmfLoadStmfProps();
+ if ((stmfRet = stmfLoadConfig()) != STMF_STATUS_SUCCESS) {
+ switch (stmfRet) {
+ case STMF_ERROR_PERM:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("permission denied"));
+ break;
+ case STMF_ERROR_SERVICE_NOT_FOUND:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service not found"));
+ break;
+ case STMF_ERROR_SERVICE_ONLINE:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service must be offline"));
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("Unable to load the configuration. "
+ "See /var/adm/messages for details"));
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("For information on reverting the "
+ "stmf:default instance to a previously "
+ "running configuration see the man page "
+ "for svccfg(1M)"));
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("After reverting the instance "
+ "you must clear the service maintenance "
+ "state. See the man page for svcadm(1M)"));
+ break;
+ }
+ return (1);
+ }
+ ret = online();
+ return (ret);
+
+}
+
+/*
+ * online
+ *
+ * Onlines the stmf service
+ *
+ */
+/*ARGSUSED*/
+static int
+online()
+{
+ int stmfRet;
+ int ret = 0;
+ stmfState state;
+ boolean_t serviceOnline = B_FALSE;
+ struct timespec rqtp;
+
+ bzero(&rqtp, sizeof (rqtp));
+
+ rqtp.tv_nsec = TEN_MS_NANOSLEEP;
+
+ if ((stmfRet = stmfOnline()) != STMF_STATUS_SUCCESS) {
+ switch (stmfRet) {
+ case STMF_ERROR_PERM:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("permission denied"));
+ break;
+ case STMF_ERROR_SERVICE_NOT_FOUND:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service not found"));
+ break;
+ case STMF_ERROR_SERVICE_ONLINE:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("STMF service already online"));
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("unable to online service"));
+ break;
+ }
+ return (1);
+ }
+
+ /* wait for service online */
+ while (!serviceOnline) {
+ stmfRet = stmfGetState(&state);
+ if (stmfRet != STMF_STATUS_SUCCESS) {
+ ret = 1;
+ break;
+ }
+ if (state.operationalState == STMF_SERVICE_STATE_ONLINE) {
+ serviceOnline = B_TRUE;
+ } else {
+ (void) nanosleep(&rqtp, NULL);
+ }
+ }
+
+ return (ret);
+}
+
+
+/*
+ * input:
+ * execFullName - exec name of program (argv[0])
+ *
+ * copied from usr/src/cmd/zoneadm/zoneadm.c in OS/Net
+ * (changed name to lowerCamelCase to keep consistent with this file)
+ *
+ * Returns:
+ * command name portion of execFullName
+ */
+static char *
+getExecBasename(char *execFullname)
+{
+ char *lastSlash, *execBasename;
+
+ /* guard against '/' at end of command invocation */
+ for (;;) {
+ lastSlash = strrchr(execFullname, '/');
+ if (lastSlash == NULL) {
+ execBasename = execFullname;
+ break;
+ } else {
+ execBasename = lastSlash + 1;
+ if (*execBasename == '\0') {
+ *lastSlash = '\0';
+ continue;
+ }
+ break;
+ }
+ }
+ return (execBasename);
+}
+
+int
+main(int argc, char *argv[])
+{
+ synTables_t synTables;
+ char versionString[VERSION_STRING_MAX_LEN];
+ int ret;
+ int funcRet;
+ void *subcommandArgs = NULL;
+
+ (void) setlocale(LC_ALL, "");
+ /* set global command name */
+ cmdName = getExecBasename(argv[0]);
+
+ (void) snprintf(versionString, VERSION_STRING_MAX_LEN, "%s.%s",
+ VERSION_STRING_MAJOR, VERSION_STRING_MINOR);
+ synTables.versionString = versionString;
+ synTables.longOptionTbl = &longOptions[0];
+ synTables.subCommandPropsTbl = &subcommands[0];
+
+ ret = cmdParse(argc, argv, synTables, subcommandArgs, &funcRet);
+ if (ret != 0) {
+ return (ret);
+ }
+
+ return (funcRet);
+} /* end main */