Home | History | Annotate | Download | only in stmfadm
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #include <stdlib.h>
     27 #include <stdio.h>
     28 #include <strings.h>
     29 #include <sys/types.h>
     30 #include <unistd.h>
     31 #include <wchar.h>
     32 #include <libintl.h>
     33 #include <errno.h>
     34 #include <time.h>
     35 #include <string.h>
     36 #include <assert.h>
     37 #include <getopt.h>
     38 #include <cmdparse.h>
     39 #include <stmfadm.h>
     40 #include <libstmf.h>
     41 #include <signal.h>
     42 #include <pthread.h>
     43 #include <locale.h>
     44 
     45 static int addHostGroupMemberFunc(int, char **, cmdOptions_t *, void *);
     46 static int addTargetGroupMemberFunc(int, char **, cmdOptions_t *, void *);
     47 static int addViewFunc(int, char **, cmdOptions_t *, void *);
     48 static int createHostGroupFunc(int, char **, cmdOptions_t *, void *);
     49 static int createLuFunc(int, char **, cmdOptions_t *, void *);
     50 static int modifyLuFunc(int, char **, cmdOptions_t *, void *);
     51 static int importLuFunc(int, char **, cmdOptions_t *, void *);
     52 static int deleteLuFunc(int, char **, cmdOptions_t *, void *);
     53 static int createTargetGroupFunc(int, char **, cmdOptions_t *, void *);
     54 static int deleteHostGroupFunc(int, char **, cmdOptions_t *, void *);
     55 static int deleteTargetGroupFunc(int, char **, cmdOptions_t *, void *);
     56 static int listLuFunc(int, char **, cmdOptions_t *, void *);
     57 static int listTargetFunc(int, char **, cmdOptions_t *, void *);
     58 static int listViewFunc(int, char **, cmdOptions_t *, void *);
     59 static int listHostGroupFunc(int, char **, cmdOptions_t *, void *);
     60 static int listStateFunc(int, char **, cmdOptions_t *, void *);
     61 static int listTargetGroupFunc(int, char **, cmdOptions_t *, void *);
     62 static int offlineTargetFunc(int, char **, cmdOptions_t *, void *);
     63 static int offlineLuFunc(int, char **, cmdOptions_t *, void *);
     64 static int onlineTargetFunc(int, char **, cmdOptions_t *, void *);
     65 static int onlineLuFunc(int, char **, cmdOptions_t *, void *);
     66 static int onlineOfflineTarget(char *, int);
     67 static int onlineOfflineLu(char *, int);
     68 static int removeHostGroupMemberFunc(int, char **, cmdOptions_t *, void *);
     69 static int removeTargetGroupMemberFunc(int, char **, cmdOptions_t *, void *);
     70 static int callModify(char *, stmfGuid *, uint32_t, const char *, const char *);
     71 static int removeViewFunc(int, char **, cmdOptions_t *, void *);
     72 static char *getExecBasename(char *);
     73 static int parseDevid(char *input, stmfDevid *devid);
     74 static void printGroupProps(stmfGroupProperties *groupProps);
     75 static int checkScsiNameString(wchar_t *, stmfDevid *);
     76 static int checkHexUpper(char *);
     77 static int checkIscsiName(wchar_t *);
     78 static void printLuProps(stmfLogicalUnitProperties *luProps);
     79 static int printExtLuProps(stmfGuid *guid);
     80 static void printGuid(stmfGuid *guid, FILE *printWhere);
     81 static void printTargetProps(stmfTargetProperties *);
     82 static void printSessionProps(stmfSessionList *);
     83 static int setLuPropFromInput(luResource, char *);
     84 static int convertCharToPropId(char *, uint32_t *);
     85 
     86 
     87 
     88 /*
     89  *  MAJOR - This should only change when there is an incompatible change made
     90  *  to the interfaces or the output.
     91  *
     92  *  MINOR - This should change whenever there is a new command or new feature
     93  *  with no incompatible change.
     94  */
     95 #define	VERSION_STRING_MAJOR	    "1"
     96 #define	VERSION_STRING_MINOR	    "0"
     97 #define	MAX_DEVID_INPUT		    256
     98 #define	GUID_INPUT		    32
     99 #define	MAX_LU_NBR		    16383
    100 #define	ONLINE_LU		    0
    101 #define	OFFLINE_LU		    1
    102 #define	ONLINE_TARGET		    2
    103 #define	OFFLINE_TARGET		    3
    104 #define	PROPS_FORMAT		    "    %-18s: "
    105 #define	VIEW_FORMAT		    "    %-13s: "
    106 #define	LVL3_FORMAT		    "        %s"
    107 #define	LVL4_FORMAT		    "            %s"
    108 
    109 /* SCSI Name String length definitions */
    110 #define	SNS_EUI_16		    16
    111 #define	SNS_EUI_24		    24
    112 #define	SNS_EUI_32		    32
    113 #define	SNS_NAA_16		    16
    114 #define	SNS_NAA_32		    32
    115 #define	SNS_WWN_16		    16
    116 #define	SNS_IQN_223		    223
    117 
    118 /* LU Property strings */
    119 #define	GUID			    "GUID"
    120 #define	ALIAS			    "ALIAS"
    121 #define	VID			    "VID"
    122 #define	PID			    "PID"
    123 #define	META_FILE		    "META"
    124 #define	WRITE_PROTECT		    "WP"
    125 #define	WRITEBACK_CACHE_DISABLE	    "WCD"
    126 #define	COMPANY_ID		    "OUI"
    127 #define	BLOCK_SIZE		    "BLK"
    128 #define	SERIAL_NUMBER		    "SERIAL"
    129 #define	MGMT_URL		    "MGMT-URL"
    130 #define	HOST_ID			    "HOST-ID"
    131 
    132 #define	MODIFY_HELP "\n"\
    133 "Description: Modify properties of a logical unit. \n" \
    134 "Valid properties for -p, --lu-prop are: \n" \
    135 "     alias    - alias for logical unit (up to 255 chars)\n" \
    136 "     mgmt-url - Management URL address\n" \
    137 "     wcd      - write cache disabled (true, false)\n" \
    138 "     wp       - write protect (true, false)\n\n" \
    139 "-f alters the meaning of the operand to be a file name\n" \
    140 "rather than a LU name. This allows for modification\n" \
    141 "of a logical unit that is not yet imported into stmf\n"
    142 
    143 #define	CREATE_HELP "\n"\
    144 "Description: Create a logical unit. \n" \
    145 "Valid properties for -p, --lu-prop are: \n" \
    146 "     alias    - alias for logical unit (up to 255 chars)\n" \
    147 "     blk      - block size in bytes in 2^n\n" \
    148 "     guid     - 32 ascii hex characters in NAA format \n" \
    149 "     host-id  - host identifier to be used for GUID generation \n" \
    150 "                8 ascii hex characters\n" \
    151 "     meta     - separate meta data file name\n" \
    152 "     mgmt-url - Management URL address\n" \
    153 "     oui      - organizational unique identifier\n" \
    154 "                6 ascii hex characters of valid format\n" \
    155 "     pid      - product identifier (up to 16 chars)\n" \
    156 "     serial   - serial number (up to 252 chars)\n" \
    157 "     vid      - vendor identifier (up to 8 chars)\n" \
    158 "     wcd      - write cache disabled (true, false)\n" \
    159 "     wp       - write protect (true, false)\n"
    160 #define	ADD_VIEW_HELP "\n"\
    161 "Description: Add a view entry to a logical unit. \n" \
    162 "A view entry is comprised of three elements; the \n" \
    163 "logical unit number, the target group name and the\n" \
    164 "host group name. These three elements combine together\n" \
    165 "to form a view for a given COMSTAR logical unit.\n" \
    166 "This view is realized by a client, a SCSI initiator,\n" \
    167 "via a REPORT LUNS command. \n"
    168 
    169 
    170 
    171 /* tables set up based on cmdparse instructions */
    172 
    173 /* add new options here */
    174 optionTbl_t longOptions[] = {
    175 	{"all", no_arg, 'a', NULL},
    176 	{"group-name", required_arg, 'g', "group-name"},
    177 	{"keep-views", no_arg, 'k', NULL},
    178 	{"lu-name", required_arg, 'l', "LU-Name"},
    179 	{"lun", required_arg, 'n', "logical-unit-number"},
    180 	{"lu-prop", required_arg, 'p', "logical-unit-property=value"},
    181 	{"file", no_arg, 'f', "filename"},
    182 	{"size", required_arg, 's', "size K/M/G/T/P"},
    183 	{"target-group", required_arg, 't', "group-name"},
    184 	{"host-group", required_arg, 'h', "group-name"},
    185 	{"verbose", no_arg, 'v', NULL},
    186 	{NULL, 0, 0, 0}
    187 };
    188 
    189 /*
    190  * Add new subcommands here
    191  */
    192 subCommandProps_t subcommands[] = {
    193 	{"add-hg-member", addHostGroupMemberFunc, "g", "g", NULL,
    194 		OPERAND_MANDATORY_MULTIPLE, OPERANDSTRING_GROUP_MEMBER, NULL},
    195 	{"add-tg-member", addTargetGroupMemberFunc, "g", "g", NULL,
    196 		OPERAND_MANDATORY_MULTIPLE, OPERANDSTRING_GROUP_MEMBER, NULL},
    197 	{"add-view", addViewFunc, "nth", NULL, NULL,
    198 		OPERAND_MANDATORY_SINGLE, OPERANDSTRING_LU, ADD_VIEW_HELP},
    199 	{"create-hg", createHostGroupFunc, NULL, NULL, NULL,
    200 		OPERAND_MANDATORY_SINGLE, OPERANDSTRING_GROUP_NAME, NULL},
    201 	{"create-tg", createTargetGroupFunc, NULL, NULL, NULL,
    202 		OPERAND_MANDATORY_SINGLE, OPERANDSTRING_GROUP_NAME, NULL},
    203 	{"create-lu", createLuFunc, "ps", NULL, NULL, OPERAND_MANDATORY_SINGLE,
    204 		"lu file", CREATE_HELP},
    205 	{"delete-hg", deleteHostGroupFunc, NULL, NULL, NULL,
    206 		OPERAND_MANDATORY_SINGLE, OPERANDSTRING_GROUP_NAME, NULL},
    207 	{"modify-lu", modifyLuFunc, "psf", NULL, NULL, OPERAND_MANDATORY_SINGLE,
    208 		OPERANDSTRING_LU, MODIFY_HELP},
    209 	{"delete-lu", deleteLuFunc, "k", NULL, NULL,
    210 		OPERAND_MANDATORY_MULTIPLE, OPERANDSTRING_LU, NULL},
    211 	{"delete-tg", deleteTargetGroupFunc, NULL, NULL, NULL,
    212 		OPERAND_MANDATORY_SINGLE, OPERANDSTRING_GROUP_NAME, NULL},
    213 	{"import-lu", importLuFunc, NULL, NULL, NULL,
    214 		OPERAND_MANDATORY_SINGLE, "file name", NULL},
    215 	{"list-hg", listHostGroupFunc, "v", NULL, NULL,
    216 		OPERAND_OPTIONAL_MULTIPLE, OPERANDSTRING_GROUP_NAME, NULL},
    217 	{"list-lu", listLuFunc, "v", NULL, NULL, OPERAND_OPTIONAL_MULTIPLE,
    218 		OPERANDSTRING_LU, NULL},
    219 	{"list-state", listStateFunc, NULL, NULL, NULL, OPERAND_NONE, NULL},
    220 	{"list-target", listTargetFunc, "v", NULL, NULL,
    221 		OPERAND_OPTIONAL_MULTIPLE, OPERANDSTRING_TARGET, NULL},
    222 	{"list-tg", listTargetGroupFunc, "v", NULL, NULL,
    223 		OPERAND_OPTIONAL_MULTIPLE, OPERANDSTRING_GROUP_NAME, NULL},
    224 	{"list-view", listViewFunc, "l", "l", NULL,
    225 		OPERAND_OPTIONAL_MULTIPLE, OPERANDSTRING_VIEW_ENTRY, NULL},
    226 	{"online-lu", onlineLuFunc, NULL, NULL, NULL,
    227 		OPERAND_MANDATORY_SINGLE, OPERANDSTRING_LU, NULL},
    228 	{"offline-lu", offlineLuFunc, NULL, NULL, NULL,
    229 		OPERAND_MANDATORY_SINGLE, OPERANDSTRING_LU, NULL},
    230 	{"online-target", onlineTargetFunc, NULL, NULL, NULL,
    231 		OPERAND_MANDATORY_SINGLE, OPERANDSTRING_TARGET, NULL},
    232 	{"offline-target", offlineTargetFunc, NULL, NULL, NULL,
    233 		OPERAND_MANDATORY_SINGLE, OPERANDSTRING_TARGET, NULL},
    234 	{"remove-hg-member", removeHostGroupMemberFunc, "g", "g", NULL,
    235 		OPERAND_MANDATORY_MULTIPLE, OPERANDSTRING_GROUP_MEMBER, NULL},
    236 	{"remove-tg-member", removeTargetGroupMemberFunc, "g", "g", NULL,
    237 		OPERAND_MANDATORY_MULTIPLE, OPERANDSTRING_GROUP_MEMBER, NULL},
    238 	{"remove-view", removeViewFunc, "la", "l", NULL,
    239 		OPERAND_OPTIONAL_MULTIPLE, OPERANDSTRING_VIEW_ENTRY, NULL},
    240 	{NULL, 0, NULL, NULL, 0, NULL, 0, NULL, NULL}
    241 };
    242 
    243 /* globals */
    244 char *cmdName;
    245 
    246 /*
    247  * addHostGroupMemberFunc
    248  *
    249  * Add members to a host group
    250  *
    251  */
    252 /*ARGSUSED*/
    253 static int
    254 addHostGroupMemberFunc(int operandLen, char *operands[], cmdOptions_t *options,
    255     void *args)
    256 {
    257 	int i;
    258 	int ret = 0;
    259 	int stmfRet;
    260 	stmfGroupName groupName = {0};
    261 	wchar_t groupNamePrint[sizeof (stmfGroupName)] = {0};
    262 	stmfDevid devid;
    263 
    264 	for (; options->optval; options++) {
    265 		switch (options->optval) {
    266 			/* host group name */
    267 			case 'g':
    268 				(void) mbstowcs(groupNamePrint, options->optarg,
    269 				    sizeof (stmfGroupName) - 1);
    270 				bcopy(options->optarg, groupName,
    271 				    strlen(options->optarg));
    272 				break;
    273 			default:
    274 				(void) fprintf(stderr, "%s: %c: %s\n",
    275 				    cmdName, options->optval,
    276 				    gettext("unknown option"));
    277 				return (1);
    278 		}
    279 	}
    280 
    281 	for (i = 0; i < operandLen; i++) {
    282 		if (parseDevid(operands[i], &devid) != 0) {
    283 			(void) fprintf(stderr, "%s: %s: %s\n",
    284 			    cmdName, operands[i],
    285 			    gettext("unrecognized device id"));
    286 			ret++;
    287 			continue;
    288 		}
    289 		stmfRet = stmfAddToHostGroup(&groupName, &devid);
    290 		switch (stmfRet) {
    291 			case STMF_STATUS_SUCCESS:
    292 				break;
    293 			case STMF_ERROR_EXISTS:
    294 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
    295 				    operands[i], gettext("already exists"));
    296 				ret++;
    297 				break;
    298 			case STMF_ERROR_GROUP_NOT_FOUND:
    299 				(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
    300 				    groupNamePrint, gettext("not found"));
    301 				ret++;
    302 				break;
    303 			case STMF_ERROR_PERM:
    304 				(void) fprintf(stderr, "%s: %s\n", cmdName,
    305 				    gettext("permission denied"));
    306 				break;
    307 			case STMF_ERROR_BUSY:
    308 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
    309 				    operands[i], gettext("resource busy"));
    310 				ret++;
    311 				break;
    312 			case STMF_ERROR_SERVICE_NOT_FOUND:
    313 				(void) fprintf(stderr, "%s: %s\n", cmdName,
    314 				    gettext("STMF service not found"));
    315 				ret++;
    316 				break;
    317 			case STMF_ERROR_SERVICE_DATA_VERSION:
    318 				(void) fprintf(stderr, "%s: %s\n", cmdName,
    319 				    gettext("STMF service version incorrect"));
    320 				ret++;
    321 				break;
    322 			default:
    323 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
    324 				    operands[i], gettext("unknown error"));
    325 				ret++;
    326 				break;
    327 		}
    328 	}
    329 
    330 	return (ret);
    331 }
    332 
    333 /*
    334  * addTargetGroupMemberFunc
    335  *
    336  * Add members to a target group
    337  *
    338  */
    339 /*ARGSUSED*/
    340 static int
    341 addTargetGroupMemberFunc(int operandLen, char *operands[],
    342     cmdOptions_t *options, void *args)
    343 {
    344 	int i;
    345 	int ret = 0;
    346 	int stmfRet;
    347 	stmfGroupName groupName = {0};
    348 	wchar_t groupNamePrint[sizeof (stmfGroupName)] = {0};
    349 	stmfDevid devid;
    350 
    351 	for (; options->optval; options++) {
    352 		switch (options->optval) {
    353 			/* target group name */
    354 			case 'g':
    355 				(void) mbstowcs(groupNamePrint, options->optarg,
    356 				    sizeof (stmfGroupName) - 1);
    357 				bcopy(options->optarg, groupName,
    358 				    strlen(options->optarg));
    359 				break;
    360 			default:
    361 				(void) fprintf(stderr, "%s: %c: %s\n",
    362 				    cmdName, options->optval,
    363 				    gettext("unknown option"));
    364 				return (1);
    365 		}
    366 	}
    367 
    368 	for (i = 0; i < operandLen; i++) {
    369 		if (parseDevid(operands[i], &devid) != 0) {
    370 			(void) fprintf(stderr, "%s: %s: %s\n",
    371 			    cmdName, operands[i],
    372 			    gettext("unrecognized device id"));
    373 			ret++;
    374 			continue;
    375 		}
    376 		stmfRet = stmfAddToTargetGroup(&groupName, &devid);
    377 		switch (stmfRet) {
    378 			case STMF_STATUS_SUCCESS:
    379 				break;
    380 			case STMF_ERROR_EXISTS:
    381 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
    382 				    operands[i], gettext("already exists"));
    383 				ret++;
    384 				break;
    385 			case STMF_ERROR_GROUP_NOT_FOUND:
    386 				(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
    387 				    groupNamePrint, gettext("not found"));
    388 				ret++;
    389 				break;
    390 			case STMF_ERROR_PERM:
    391 				(void) fprintf(stderr, "%s: %s\n", cmdName,
    392 				    gettext("permission denied"));
    393 				break;
    394 			case STMF_ERROR_BUSY:
    395 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
    396 				    operands[i], gettext("resource busy"));
    397 				ret++;
    398 				break;
    399 			case STMF_ERROR_SERVICE_NOT_FOUND:
    400 				(void) fprintf(stderr, "%s: %s\n", cmdName,
    401 				    gettext("STMF service not found"));
    402 				ret++;
    403 				break;
    404 			case STMF_ERROR_SERVICE_ONLINE:
    405 				(void) fprintf(stderr, "%s: %s\n", cmdName,
    406 				    gettext("STMF service must be offline"));
    407 				ret++;
    408 				break;
    409 			case STMF_ERROR_SERVICE_DATA_VERSION:
    410 				(void) fprintf(stderr, "%s: %s\n", cmdName,
    411 				    gettext("STMF service version incorrect"));
    412 				ret++;
    413 				break;
    414 			case STMF_ERROR_TG_ONLINE:
    415 				(void) fprintf(stderr, "%s: %s\n", cmdName,
    416 				    gettext("STMF target must be offline"));
    417 				ret++;
    418 				break;
    419 			default:
    420 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
    421 				    operands[i], gettext("unknown error"));
    422 				ret++;
    423 				break;
    424 		}
    425 	}
    426 
    427 	return (ret);
    428 }
    429 
    430 /*
    431  * parseDevid
    432  *
    433  * Converts char * input to a stmfDevid
    434  *
    435  * input - this should be in the following format with either a
    436  * wwn. iqn. or eui. representation.
    437  * A name string of the format:
    438  *	wwn.<WWN> (FC/SAS address)
    439  *	iqn.<iSCSI name> (iSCSI iqn)
    440  *	eui.<WWN> (iSCSI eui name)
    441  *
    442  * devid - pointer to stmfDevid structure allocated by the caller.
    443  *
    444  * Returns:
    445  *  0 on success
    446  *  non-zero on failure
    447  */
    448 static int
    449 parseDevid(char *input, stmfDevid *devid)
    450 {
    451 	wchar_t inputWc[MAX_DEVID_INPUT + 1] = {0};
    452 
    453 	/* convert to wcs */
    454 	(void) mbstowcs(inputWc, input, MAX_DEVID_INPUT);
    455 
    456 	/*
    457 	 * Check for known scsi name string formats
    458 	 * If one is found, we're done
    459 	 * If not, then it's a failure to parse
    460 	 */
    461 	if (checkScsiNameString(inputWc, devid) == 0) {
    462 		return (0);
    463 	}
    464 
    465 	return (-1);
    466 }
    467 
    468 /*
    469  * checkScsiNameString
    470  *
    471  * Validates known SCSI name string formats and converts to stmfDevid
    472  * format
    473  *
    474  * input - input SCSI name string
    475  * devid - pointer to stmfDevid structure allocated by the caller
    476  *         on successful return, contains the devid based on input
    477  *
    478  * returns:
    479  *         0 on success
    480  *         -1 on failure
    481  */
    482 static int
    483 checkScsiNameString(wchar_t *input, stmfDevid *devid)
    484 {
    485 	char *mbString = NULL;
    486 	int mbStringLen;
    487 	int len;
    488 	int i;
    489 
    490 	/*
    491 	 * Convert to multi-byte string
    492 	 *
    493 	 * This is used for either eui or naa formats
    494 	 */
    495 	mbString = calloc(1, (mbStringLen = wcstombs(mbString, input, 0)) + 1);
    496 	if (mbString == NULL) {
    497 		(void) fprintf(stderr, "%s: %s\n",
    498 		    cmdName, "Insufficient memory\n");
    499 		return (-1);
    500 	}
    501 	if (wcstombs(mbString, input, mbStringLen) == (size_t)-1) {
    502 		return (-1);
    503 	}
    504 
    505 	/*
    506 	 * check for iqn format
    507 	 */
    508 	if (strncmp(mbString, "iqn.", 4) == 0) {
    509 		if ((len = strlen(mbString)) > (SNS_IQN_223)) {
    510 			return (-1);
    511 		}
    512 		for (i = 0; i < len; i++) {
    513 			mbString[i] = tolower(mbString[i]);
    514 		}
    515 		if (checkIscsiName(input + 4) != 0) {
    516 			return (-1);
    517 		}
    518 	} else if (strncmp(mbString, "wwn.", 4) == 0) {
    519 		if ((len = strlen(mbString + 4)) != SNS_WWN_16) {
    520 			return (-1);
    521 		} else if (checkHexUpper(mbString + 4) != 0) {
    522 			return (-1);
    523 		}
    524 	} else if (strncmp(mbString, "eui.", 4) == 0) {
    525 		if ((len = strlen(mbString + 4)) != SNS_EUI_16) {
    526 			return (-1);
    527 		} else if (checkHexUpper(mbString + 4) != 0) {
    528 			return (-1);
    529 		}
    530 	} else {
    531 		return (-1);
    532 	}
    533 
    534 	/*
    535 	 * We have a validated name string.
    536 	 * Go ahead and set the length and copy it.
    537 	 */
    538 	devid->identLength = strlen(mbString);
    539 	bzero(devid->ident, STMF_IDENT_LENGTH);
    540 	bcopy(mbString, devid->ident, devid->identLength);
    541 
    542 	return (0);
    543 }
    544 
    545 
    546 /*
    547  * Checks whether the entire string is in hex and converts to upper
    548  */
    549 static int
    550 checkHexUpper(char *input)
    551 {
    552 	int i;
    553 
    554 	for (i = 0; i < strlen(input); i++) {
    555 		if (isxdigit(input[i])) {
    556 			input[i] = toupper(input[i]);
    557 			continue;
    558 		}
    559 		return (-1);
    560 	}
    561 
    562 	return (0);
    563 }
    564 
    565 /*
    566  * checkIscsiName
    567  *
    568  * Purpose: Basic string checking on name
    569  */
    570 static int
    571 checkIscsiName(wchar_t *input)
    572 {
    573 	int i;
    574 
    575 	for (i = 0; input[i] != 0; i++) {
    576 		if (!iswalnum(input[i]) && input[i] != '-' &&
    577 		    input[i] != '.' && input[i] != ':') {
    578 			return (-1);
    579 		}
    580 	}
    581 
    582 	return (0);
    583 }
    584 
    585 
    586 /*
    587  * addViewFunc
    588  *
    589  * Adds a view entry to a logical unit
    590  *
    591  */
    592 /*ARGSUSED*/
    593 static int
    594 addViewFunc(int operandLen, char *operands[], cmdOptions_t *options,
    595     void *args)
    596 {
    597 	stmfViewEntry viewEntry;
    598 	stmfGuid inGuid;
    599 	unsigned int guid[sizeof (stmfGuid)];
    600 	uint16_t inputLuNbr;
    601 	int ret = 0;
    602 	int stmfRet;
    603 	int i;
    604 	char sGuid[GUID_INPUT + 1];
    605 
    606 	bzero(&viewEntry, sizeof (viewEntry));
    607 	/* init view entry structure */
    608 	viewEntry.allHosts = B_TRUE;
    609 	viewEntry.allTargets = B_TRUE;
    610 	viewEntry.luNbrValid = B_FALSE;
    611 
    612 	/* check input length */
    613 	if (strlen(operands[0]) != GUID_INPUT) {
    614 		(void) fprintf(stderr, "%s: %s: %s%d%s\n", cmdName, operands[0],
    615 		    gettext("must be "), GUID_INPUT,
    616 		    gettext(" hexadecimal digits"));
    617 		return (1);
    618 	}
    619 
    620 	for (; options->optval; options++) {
    621 		switch (options->optval) {
    622 			/* logical unit number */
    623 			case 'n':
    624 				viewEntry.luNbrValid = B_TRUE;
    625 				inputLuNbr = atoi(options->optarg);
    626 				if (inputLuNbr > MAX_LU_NBR) {
    627 					(void) fprintf(stderr, "%s: %d: %s\n",
    628 					    cmdName, inputLuNbr,
    629 					    gettext("Logical unit number"
    630 					    " must be less than 16384"));
    631 					return (1);
    632 				}
    633 				viewEntry.luNbr[0] = inputLuNbr >> 8;
    634 				viewEntry.luNbr[1] = inputLuNbr & 0xff;
    635 				break;
    636 			/* host group */
    637 			case 'h':
    638 				viewEntry.allHosts = B_FALSE;
    639 				bcopy(options->optarg, viewEntry.hostGroup,
    640 				    strlen(options->optarg));
    641 				break;
    642 			/* target group */
    643 			case 't':
    644 				viewEntry.allTargets = B_FALSE;
    645 				bcopy(options->optarg, viewEntry.targetGroup,
    646 				    strlen(options->optarg));
    647 				break;
    648 			default:
    649 				(void) fprintf(stderr, "%s: %c: %s\n",
    650 				    cmdName, options->optval,
    651 				    gettext("unknown option"));
    652 				return (1);
    653 		}
    654 	}
    655 
    656 	/* convert to lower case for scan */
    657 	for (i = 0; i < 32; i++)
    658 		sGuid[i] = tolower(operands[0][i]);
    659 	sGuid[i] = 0;
    660 
    661 	(void) sscanf(sGuid, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
    662 	    &guid[0], &guid[1], &guid[2], &guid[3], &guid[4], &guid[5],
    663 	    &guid[6], &guid[7], &guid[8], &guid[9], &guid[10], &guid[11],
    664 	    &guid[12], &guid[13], &guid[14], &guid[15]);
    665 
    666 	for (i = 0; i < sizeof (stmfGuid); i++) {
    667 		inGuid.guid[i] = guid[i];
    668 	}
    669 
    670 	/* add the view entry */
    671 	stmfRet = stmfAddViewEntry(&inGuid, &viewEntry);
    672 	switch (stmfRet) {
    673 		case STMF_STATUS_SUCCESS:
    674 			break;
    675 		case STMF_ERROR_EXISTS:
    676 			(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
    677 			    operands[0], gettext("already exists"));
    678 			ret++;
    679 			break;
    680 		case STMF_ERROR_BUSY:
    681 			(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
    682 			    operands[0], gettext("resource busy"));
    683 			ret++;
    684 			break;
    685 		case STMF_ERROR_SERVICE_NOT_FOUND:
    686 			(void) fprintf(stderr, "%s: %s\n", cmdName,
    687 			    gettext("STMF service not found"));
    688 			ret++;
    689 			break;
    690 		case STMF_ERROR_PERM:
    691 			(void) fprintf(stderr, "%s: %s\n", cmdName,
    692 			    gettext("permission denied"));
    693 			ret++;
    694 			break;
    695 		case STMF_ERROR_LUN_IN_USE:
    696 			(void) fprintf(stderr, "%s: %s\n", cmdName,
    697 			    gettext("LUN already in use"));
    698 			ret++;
    699 			break;
    700 		case STMF_ERROR_VE_CONFLICT:
    701 			(void) fprintf(stderr, "%s: %s\n", cmdName,
    702 			    gettext("view entry exists"));
    703 			ret++;
    704 			break;
    705 		case STMF_ERROR_CONFIG_NONE:
    706 			(void) fprintf(stderr, "%s: %s\n", cmdName,
    707 			    gettext("STMF service is not initialized"));
    708 			ret++;
    709 			break;
    710 		case STMF_ERROR_SERVICE_DATA_VERSION:
    711 			(void) fprintf(stderr, "%s: %s\n", cmdName,
    712 			    gettext("STMF service version incorrect"));
    713 			ret++;
    714 			break;
    715 		case STMF_ERROR_INVALID_HG:
    716 			(void) fprintf(stderr, "%s: %s\n", cmdName,
    717 			    gettext("invalid host group"));
    718 			ret++;
    719 			break;
    720 		case STMF_ERROR_INVALID_TG:
    721 			(void) fprintf(stderr, "%s: %s\n", cmdName,
    722 			    gettext("invalid target group"));
    723 			ret++;
    724 			break;
    725 		default:
    726 			(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
    727 			    operands[0], gettext("unknown error"));
    728 			ret++;
    729 			break;
    730 	}
    731 
    732 	return (ret);
    733 }
    734 
    735 /*
    736  * createHostGroupFunc
    737  *
    738  * Create a host group
    739  *
    740  */
    741 /*ARGSUSED*/
    742 static int
    743 createHostGroupFunc(int operandLen, char *operands[],
    744     cmdOptions_t *options, void *args)
    745 {
    746 	int ret = 0;
    747 	int stmfRet;
    748 	wchar_t groupNamePrint[sizeof (stmfGroupName)] = {0};
    749 	stmfGroupName groupName = {0};
    750 
    751 	(void) strlcpy(groupName, operands[0], sizeof (groupName));
    752 	(void) mbstowcs(groupNamePrint, (char *)groupName,
    753 	    sizeof (stmfGroupName) - 1);
    754 	/* call create group */
    755 	stmfRet = stmfCreateHostGroup(&groupName);
    756 	switch (stmfRet) {
    757 		case STMF_STATUS_SUCCESS:
    758 			break;
    759 		case STMF_ERROR_EXISTS:
    760 			(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
    761 			    operands[0], gettext("already exists"));
    762 			ret++;
    763 			break;
    764 		case STMF_ERROR_BUSY:
    765 			(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
    766 			    operands[0], gettext("resource busy"));
    767 			ret++;
    768 			break;
    769 		case STMF_ERROR_SERVICE_NOT_FOUND:
    770 			(void) fprintf(stderr, "%s: %s\n", cmdName,
    771 			    gettext("STMF service not found"));
    772 			ret++;
    773 			break;
    774 		case STMF_ERROR_PERM:
    775 			(void) fprintf(stderr, "%s: %s\n", cmdName,
    776 			    gettext("permission denied"));
    777 			ret++;
    778 			break;
    779 		case STMF_ERROR_SERVICE_DATA_VERSION:
    780 			(void) fprintf(stderr, "%s: %s\n", cmdName,
    781 			    gettext("STMF service version incorrect"));
    782 			ret++;
    783 			break;
    784 		default:
    785 			(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
    786 			    operands[0], gettext("unknown error"));
    787 			ret++;
    788 			break;
    789 	}
    790 
    791 	return (ret);
    792 }
    793 
    794 /*
    795  * createLuFunc
    796  *
    797  * Create a logical unit
    798  *
    799  */
    800 /*ARGSUSED*/
    801 static int
    802 createLuFunc(int operandLen, char *operands[], cmdOptions_t *options,
    803     void *args)
    804 {
    805 	luResource hdl = NULL;
    806 	int ret = 0;
    807 	int stmfRet = 0;
    808 	char guidAsciiBuf[33];
    809 	stmfGuid createdGuid;
    810 
    811 	stmfRet = stmfCreateLuResource(STMF_DISK, &hdl);
    812 
    813 	if (stmfRet != STMF_STATUS_SUCCESS) {
    814 		(void) fprintf(stderr, "%s: %s\n",
    815 		    cmdName, gettext("Failure to create lu resource\n"));
    816 		return (1);
    817 	}
    818 
    819 	for (; options->optval; options++) {
    820 		switch (options->optval) {
    821 			case 'p':
    822 				ret = setLuPropFromInput(hdl, options->optarg);
    823 				if (ret != 0) {
    824 					(void) stmfFreeLuResource(hdl);
    825 					return (1);
    826 				}
    827 				break;
    828 			case 's':
    829 				stmfRet = stmfSetLuProp(hdl, STMF_LU_PROP_SIZE,
    830 				    options->optarg);
    831 				if (stmfRet != STMF_STATUS_SUCCESS) {
    832 					(void) fprintf(stderr, "%s: %c: %s\n",
    833 					    cmdName, options->optval,
    834 					    gettext("size param invalid"));
    835 					(void) stmfFreeLuResource(hdl);
    836 					return (1);
    837 				}
    838 				break;
    839 			default:
    840 				(void) fprintf(stderr, "%s: %c: %s\n",
    841 				    cmdName, options->optval,
    842 				    gettext("unknown option"));
    843 				return (1);
    844 		}
    845 	}
    846 
    847 	stmfRet = stmfSetLuProp(hdl, STMF_LU_PROP_FILENAME, operands[0]);
    848 
    849 	if (stmfRet != STMF_STATUS_SUCCESS) {
    850 		(void) fprintf(stderr, "%s: %s\n",
    851 		    cmdName, gettext("could not set filename"));
    852 		return (1);
    853 	}
    854 
    855 	stmfRet = stmfCreateLu(hdl, &createdGuid);
    856 	switch (stmfRet) {
    857 		case STMF_STATUS_SUCCESS:
    858 			break;
    859 		case STMF_ERROR_BUSY:
    860 		case STMF_ERROR_LU_BUSY:
    861 			(void) fprintf(stderr, "%s: %s\n", cmdName,
    862 			    gettext("resource busy"));
    863 			ret++;
    864 			break;
    865 		case STMF_ERROR_PERM:
    866 			(void) fprintf(stderr, "%s: %s\n", cmdName,
    867 			    gettext("permission denied"));
    868 			ret++;
    869 			break;
    870 		case STMF_ERROR_FILE_IN_USE:
    871 			(void) fprintf(stderr, "%s: filename %s: %s\n", cmdName,
    872 			    operands[0], gettext("in use"));
    873 			ret++;
    874 			break;
    875 		case STMF_ERROR_INVALID_BLKSIZE:
    876 			(void) fprintf(stderr, "%s: %s\n", cmdName,
    877 			    gettext("invalid block size"));
    878 			ret++;
    879 			break;
    880 		case STMF_ERROR_GUID_IN_USE:
    881 			(void) fprintf(stderr, "%s: %s\n", cmdName,
    882 			    gettext("guid in use"));
    883 			ret++;
    884 			break;
    885 		case STMF_ERROR_META_FILE_NAME:
    886 			(void) fprintf(stderr, "%s: %s\n", cmdName,
    887 			    gettext("meta file error"));
    888 			ret++;
    889 			break;
    890 		case STMF_ERROR_DATA_FILE_NAME:
    891 			(void) fprintf(stderr, "%s: %s\n", cmdName,
    892 			    gettext("data file error"));
    893 			ret++;
    894 			break;
    895 		case STMF_ERROR_FILE_SIZE_INVALID:
    896 			(void) fprintf(stderr, "%s: %s\n", cmdName,
    897 			    gettext("file size invalid"));
    898 			ret++;
    899 			break;
    900 		case STMF_ERROR_SIZE_OUT_OF_RANGE:
    901 			(void) fprintf(stderr, "%s: %s\n", cmdName,
    902 			    gettext("invalid size"));
    903 			ret++;
    904 			break;
    905 		case STMF_ERROR_META_CREATION:
    906 			(void) fprintf(stderr, "%s: %s\n", cmdName,
    907 			    gettext("could not create meta file"));
    908 			ret++;
    909 			break;
    910 		case STMF_ERROR_WRITE_CACHE_SET:
    911 			(void) fprintf(stderr, "%s: %s\n", cmdName,
    912 			    gettext("could not set write cache"));
    913 			ret++;
    914 			break;
    915 		default:
    916 			(void) fprintf(stderr, "%s: %s\n", cmdName,
    917 			    gettext("unknown error"));
    918 			ret++;
    919 			break;
    920 	}
    921 
    922 	if (ret != 0) {
    923 		goto done;
    924 	}
    925 
    926 	(void) snprintf(guidAsciiBuf, sizeof (guidAsciiBuf),
    927 	    "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X"
    928 	    "%02X%02X%02X%02X%02X%02X",
    929 	    createdGuid.guid[0], createdGuid.guid[1], createdGuid.guid[2],
    930 	    createdGuid.guid[3], createdGuid.guid[4], createdGuid.guid[5],
    931 	    createdGuid.guid[6], createdGuid.guid[7], createdGuid.guid[8],
    932 	    createdGuid.guid[9], createdGuid.guid[10], createdGuid.guid[11],
    933 	    createdGuid.guid[12], createdGuid.guid[13], createdGuid.guid[14],
    934 	    createdGuid.guid[15]);
    935 	(void) printf("Logical unit created: %s\n", guidAsciiBuf);
    936 
    937 done:
    938 	(void) stmfFreeLuResource(hdl);
    939 	return (ret);
    940 }
    941 
    942 /*
    943  * createLuFunc
    944  *
    945  * Create a logical unit
    946  *
    947  */
    948 /*ARGSUSED*/
    949 static int
    950 modifyLuFunc(int operandLen, char *operands[], cmdOptions_t *options,
    951     void *args)
    952 {
    953 	stmfGuid inGuid;
    954 	unsigned int guid[sizeof (stmfGuid)];
    955 	int ret = 0;
    956 	int i;
    957 	char *fname = NULL;
    958 	char *lasts = NULL;
    959 	char sGuid[GUID_INPUT + 1];
    960 	char *prop = NULL;
    961 	char *propVal = NULL;
    962 	boolean_t fnameUsed = B_FALSE;
    963 	uint32_t propId;
    964 	cmdOptions_t *optionStart = options;
    965 
    966 
    967 	for (; options->optval; options++) {
    968 		switch (options->optval) {
    969 			case 'f':
    970 				fnameUsed = B_TRUE;
    971 				fname = operands[0];
    972 				break;
    973 		}
    974 	}
    975 	options = optionStart;
    976 
    977 	/* check input length */
    978 	if (!fnameUsed && strlen(operands[0]) != GUID_INPUT) {
    979 		(void) fprintf(stderr, "%s: %s: %s%d%s\n", cmdName, operands[0],
    980 		    gettext("must be "), GUID_INPUT,
    981 		    gettext(" hexadecimal digits"));
    982 		return (1);
    983 	}
    984 
    985 	if (!fnameUsed) {
    986 		/* convert to lower case for scan */
    987 		for (i = 0; i < 32; i++)
    988 			sGuid[i] = tolower(operands[0][i]);
    989 		sGuid[i] = 0;
    990 		(void) sscanf(sGuid,
    991 		    "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
    992 		    &guid[0], &guid[1], &guid[2], &guid[3], &guid[4], &guid[5],
    993 		    &guid[6], &guid[7], &guid[8], &guid[9], &guid[10],
    994 		    &guid[11], &guid[12], &guid[13], &guid[14], &guid[15]);
    995 
    996 		for (i = 0; i < sizeof (stmfGuid); i++) {
    997 			inGuid.guid[i] = guid[i];
    998 		}
    999 	}
   1000 
   1001 	for (; options->optval; options++) {
   1002 		switch (options->optval) {
   1003 			case 'p':
   1004 				prop = strtok_r(options->optarg, "=", &lasts);
   1005 				propVal = strtok_r(NULL, "=", &lasts);
   1006 				ret = convertCharToPropId(prop, &propId);
   1007 				if (ret != 0) {
   1008 					(void) fprintf(stderr, "%s: %s: %s\n",
   1009 					    cmdName,
   1010 					gettext("invalid property specified"),
   1011 					    prop);
   1012 					return (1);
   1013 				}
   1014 				if (propVal ==  NULL &&
   1015 				    propId != STMF_LU_PROP_MGMT_URL) {
   1016 					(void) fprintf(stderr, "%s: %s: %s\n",
   1017 					    cmdName, options->optarg,
   1018 					    gettext("invalid property specifier"
   1019 					    "- prop=val\n"));
   1020 					return (1);
   1021 				}
   1022 				if (propVal ==  NULL) {
   1023 					ret = callModify(fname, &inGuid, propId,
   1024 					    "", prop);
   1025 				} else {
   1026 					ret = callModify(fname, &inGuid, propId,
   1027 					    propVal, prop);
   1028 				}
   1029 				if (ret != 0) {
   1030 					return (1);
   1031 				}
   1032 				break;
   1033 			case 's':
   1034 				if (callModify(fname, &inGuid,
   1035 				    STMF_LU_PROP_SIZE, options->optarg,
   1036 				    "size") != 0) {
   1037 					return (1);
   1038 				}
   1039 				break;
   1040 			case 'f':
   1041 				break;
   1042 			default:
   1043 				(void) fprintf(stderr, "%s: %c: %s\n",
   1044 				    cmdName, options->optval,
   1045 				    gettext("unknown option"));
   1046 				return (1);
   1047 		}
   1048 	}
   1049 	return (ret);
   1050 }
   1051 
   1052 static int
   1053 callModify(char *fname, stmfGuid *luGuid, uint32_t prop, const char *propVal,
   1054     const char *propString)
   1055 {
   1056 	int ret = 0;
   1057 	int stmfRet = 0;
   1058 
   1059 	if (!fname) {
   1060 		stmfRet = stmfModifyLu(luGuid, prop, propVal);
   1061 	} else {
   1062 		stmfRet = stmfModifyLuByFname(STMF_DISK, fname, prop,
   1063 		    propVal);
   1064 	}
   1065 	switch (stmfRet) {
   1066 		case STMF_STATUS_SUCCESS:
   1067 			break;
   1068 		case STMF_ERROR_BUSY:
   1069 		case STMF_ERROR_LU_BUSY:
   1070 			(void) fprintf(stderr, "%s: %s\n", cmdName,
   1071 			    gettext("resource busy"));
   1072 			ret++;
   1073 			break;
   1074 		case STMF_ERROR_PERM:
   1075 			(void) fprintf(stderr, "%s: %s\n", cmdName,
   1076 			    gettext("permission denied"));
   1077 			ret++;
   1078 			break;
   1079 		case STMF_ERROR_INVALID_BLKSIZE:
   1080 			(void) fprintf(stderr, "%s: %s\n", cmdName,
   1081 			    gettext("invalid block size"));
   1082 			ret++;
   1083 			break;
   1084 		case STMF_ERROR_GUID_IN_USE:
   1085 			(void) fprintf(stderr, "%s: %s\n", cmdName,
   1086 			    gettext("guid in use"));
   1087 			ret++;
   1088 			break;
   1089 		case STMF_ERROR_META_FILE_NAME:
   1090 			(void) fprintf(stderr, "%s: %s\n", cmdName,
   1091 			    gettext("meta file error"));
   1092 			ret++;
   1093 			break;
   1094 		case STMF_ERROR_DATA_FILE_NAME:
   1095 			(void) fprintf(stderr, "%s: %s\n", cmdName,
   1096 			    gettext("data file error"));
   1097 			ret++;
   1098 			break;
   1099 		case STMF_ERROR_FILE_SIZE_INVALID:
   1100 			(void) fprintf(stderr, "%s: %s\n", cmdName,
   1101 			    gettext("file size invalid"));
   1102 			ret++;
   1103 			break;
   1104 		case STMF_ERROR_SIZE_OUT_OF_RANGE:
   1105 			(void) fprintf(stderr, "%s: %s\n", cmdName,
   1106 			    gettext("invalid size"));
   1107 			ret++;
   1108 			break;
   1109 		case STMF_ERROR_META_CREATION:
   1110 			(void) fprintf(stderr, "%s: %s\n", cmdName,
   1111 			    gettext("could not create meta file"));
   1112 			ret++;
   1113 			break;
   1114 		case STMF_ERROR_INVALID_PROP:
   1115 			(void) fprintf(stderr, "%s: %s\n", cmdName,
   1116 			    gettext("invalid property for modify"));
   1117 			ret++;
   1118 			break;
   1119 		case STMF_ERROR_WRITE_CACHE_SET:
   1120 			(void) fprintf(stderr, "%s: %s\n", cmdName,
   1121 			    gettext("could not set write cache"));
   1122 			ret++;
   1123 			break;
   1124 		case STMF_ERROR_ACCESS_STATE_SET:
   1125 			(void) fprintf(stderr, "%s: %s\n", cmdName,
   1126 			    gettext("cannot modify while in standby mode"));
   1127 			ret++;
   1128 			break;
   1129 		default:
   1130 			(void) fprintf(stderr, "%s: %s: %s: %d\n", cmdName,
   1131 			    gettext("could not set property"), propString,
   1132 			    stmfRet);
   1133 			ret++;
   1134 			break;
   1135 	}
   1136 
   1137 	return (ret);
   1138 }
   1139 
   1140 
   1141 /*
   1142  * importLuFunc
   1143  *
   1144  * Create a logical unit
   1145  *
   1146  */
   1147 /*ARGSUSED*/
   1148 static int
   1149 importLuFunc(int operandLen, char *operands[], cmdOptions_t *options,
   1150     void *args)
   1151 {
   1152 	int stmfRet = 0;
   1153 	int ret = 0;
   1154 	char guidAsciiBuf[33];
   1155 	stmfGuid createdGuid;
   1156 
   1157 	stmfRet = stmfImportLu(STMF_DISK, operands[0], &createdGuid);
   1158 	switch (stmfRet) {
   1159 		case STMF_STATUS_SUCCESS:
   1160 			break;
   1161 		case STMF_ERROR_BUSY:
   1162 		case STMF_ERROR_LU_BUSY:
   1163 			(void) fprintf(stderr, "%s: %s\n", cmdName,
   1164 			    gettext("resource busy"));
   1165 			ret++;
   1166 			break;
   1167 		case STMF_ERROR_PERM:
   1168 			(void) fprintf(stderr, "%s: %s\n", cmdName,
   1169 			    gettext("permission denied"));
   1170 			ret++;
   1171 			break;
   1172 		case STMF_ERROR_FILE_IN_USE:
   1173 			(void) fprintf(stderr, "%s: filename %s: %s\n", cmdName,
   1174 			    operands[0], gettext("in use"));
   1175 			ret++;
   1176 			break;
   1177 		case STMF_ERROR_GUID_IN_USE:
   1178 			(void) fprintf(stderr, "%s: %s\n", cmdName,
   1179 			    gettext("guid in use"));
   1180 			ret++;
   1181 			break;
   1182 		case STMF_ERROR_META_FILE_NAME:
   1183 			(void) fprintf(stderr, "%s: %s\n", cmdName,
   1184 			    gettext("meta file error"));
   1185 			ret++;
   1186 			break;
   1187 		case STMF_ERROR_DATA_FILE_NAME:
   1188 			(void) fprintf(stderr, "%s: %s\n", cmdName,
   1189 			    gettext("data file error"));
   1190 			ret++;
   1191 			break;
   1192 		case STMF_ERROR_META_CREATION:
   1193 			(void) fprintf(stderr, "%s: %s\n", cmdName,
   1194 			    gettext("could not create meta file"));
   1195 			ret++;
   1196 			break;
   1197 		case STMF_ERROR_WRITE_CACHE_SET:
   1198 			(void) fprintf(stderr, "%s: %s\n", cmdName,
   1199 			    gettext("could not set write cache"));
   1200 			ret++;
   1201 			break;
   1202 		default:
   1203 			(void) fprintf(stderr, "%s: %s\n", cmdName,
   1204 			    gettext("unknown error"));
   1205 			ret++;
   1206 			break;
   1207 	}
   1208 
   1209 	if (ret != STMF_STATUS_SUCCESS) {
   1210 		goto done;
   1211 	}
   1212 
   1213 	(void) snprintf(guidAsciiBuf, sizeof (guidAsciiBuf),
   1214 	    "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X"
   1215 	    "%02X%02X%02X%02X%02X%02X",
   1216 	    createdGuid.guid[0], createdGuid.guid[1], createdGuid.guid[2],
   1217 	    createdGuid.guid[3], createdGuid.guid[4], createdGuid.guid[5],
   1218 	    createdGuid.guid[6], createdGuid.guid[7], createdGuid.guid[8],
   1219 	    createdGuid.guid[9], createdGuid.guid[10], createdGuid.guid[11],
   1220 	    createdGuid.guid[12], createdGuid.guid[13], createdGuid.guid[14],
   1221 	    createdGuid.guid[15]);
   1222 	(void) printf("Logical unit imported: %s\n", guidAsciiBuf);
   1223 
   1224 done:
   1225 	return (ret);
   1226 }
   1227 
   1228 static int
   1229 setLuPropFromInput(luResource hdl, char *optarg)
   1230 {
   1231 	char *prop = NULL;
   1232 	char *propVal = NULL;
   1233 	char *lasts = NULL;
   1234 	uint32_t propId;
   1235 	int ret = 0;
   1236 
   1237 	prop = strtok_r(optarg, "=", &lasts);
   1238 	if ((propVal = strtok_r(NULL, "=", &lasts)) == NULL) {
   1239 		(void) fprintf(stderr, "%s: %s: %s\n",
   1240 		    cmdName, optarg,
   1241 		    gettext("invalid property specifier - prop=val\n"));
   1242 		return (1);
   1243 	}
   1244 
   1245 	ret = convertCharToPropId(prop, &propId);
   1246 	if (ret != 0) {
   1247 		(void) fprintf(stderr, "%s: %s: %s\n",
   1248 		    cmdName, gettext("invalid property specified"), prop);
   1249 		return (1);
   1250 	}
   1251 
   1252 	ret = stmfSetLuProp(hdl, propId, propVal);
   1253 	if (ret != STMF_STATUS_SUCCESS) {
   1254 		(void) fprintf(stderr, "%s: %s %s: ",
   1255 		    cmdName, gettext("unable to set"), prop);
   1256 		switch (ret) {
   1257 			case STMF_ERROR_INVALID_PROPSIZE:
   1258 				(void) fprintf(stderr, "invalid length\n");
   1259 				break;
   1260 			case STMF_ERROR_INVALID_ARG:
   1261 				(void) fprintf(stderr, "bad format\n");
   1262 				break;
   1263 			default:
   1264 				(void) fprintf(stderr, "\n");
   1265 				break;
   1266 		}
   1267 		return (1);
   1268 	}
   1269 
   1270 	return (0);
   1271 }
   1272 
   1273 static int
   1274 convertCharToPropId(char *prop, uint32_t *propId)
   1275 {
   1276 	if (strcasecmp(prop, GUID) == 0) {
   1277 		*propId = STMF_LU_PROP_GUID;
   1278 	} else if (strcasecmp(prop, ALIAS) == 0) {
   1279 		*propId = STMF_LU_PROP_ALIAS;
   1280 	} else if (strcasecmp(prop, VID) == 0) {
   1281 		*propId = STMF_LU_PROP_VID;
   1282 	} else if (strcasecmp(prop, PID) == 0) {
   1283 		*propId = STMF_LU_PROP_PID;
   1284 	} else if (strcasecmp(prop, WRITE_PROTECT) == 0) {
   1285 		*propId = STMF_LU_PROP_WRITE_PROTECT;
   1286 	} else if (strcasecmp(prop, WRITEBACK_CACHE_DISABLE) == 0) {
   1287 		*propId = STMF_LU_PROP_WRITE_CACHE_DISABLE;
   1288 	} else if (strcasecmp(prop, BLOCK_SIZE) == 0) {
   1289 		*propId = STMF_LU_PROP_BLOCK_SIZE;
   1290 	} else if (strcasecmp(prop, SERIAL_NUMBER) == 0) {
   1291 		*propId = STMF_LU_PROP_SERIAL_NUM;
   1292 	} else if (strcasecmp(prop, COMPANY_ID) == 0) {
   1293 		*propId = STMF_LU_PROP_COMPANY_ID;
   1294 	} else if (strcasecmp(prop, META_FILE) == 0) {
   1295 		*propId = STMF_LU_PROP_META_FILENAME;
   1296 	} else if (strcasecmp(prop, MGMT_URL) == 0) {
   1297 		*propId = STMF_LU_PROP_MGMT_URL;
   1298 	} else if (strcasecmp(prop, HOST_ID) == 0) {
   1299 		*propId = STMF_LU_PROP_HOST_ID;
   1300 	} else {
   1301 		return (1);
   1302 	}
   1303 	return (0);
   1304 }
   1305 
   1306 /*
   1307  * deleteLuFunc
   1308  *
   1309  * Delete a logical unit
   1310  *
   1311  */
   1312 /*ARGSUSED*/
   1313 static int
   1314 deleteLuFunc(int operandLen, char *operands[], cmdOptions_t *options,
   1315     void *args)
   1316 {
   1317 	int i, j;
   1318 	int ret = 0;
   1319 	int stmfRet;
   1320 	unsigned int inGuid[sizeof (stmfGuid)];
   1321 	stmfGuid delGuid;
   1322 	boolean_t keepViews = B_FALSE;
   1323 	boolean_t viewEntriesRemoved = B_FALSE;
   1324 	boolean_t noLunFound = B_FALSE;
   1325 	boolean_t views = B_FALSE;
   1326 	char sGuid[GUID_INPUT + 1];
   1327 	stmfViewEntryList *viewEntryList = NULL;
   1328 
   1329 	for (; options->optval; options++) {
   1330 		switch (options->optval) {
   1331 			/* Keep views for logical unit */
   1332 			case 'k':
   1333 				keepViews = B_TRUE;
   1334 				break;
   1335 			default:
   1336 				(void) fprintf(stderr, "%s: %c: %s\n",
   1337 				    cmdName, options->optval,
   1338 				    gettext("unknown option"));
   1339 				return (1);
   1340 		}
   1341 	}
   1342 
   1343 
   1344 	for (i = 0; i < operandLen; i++) {
   1345 		for (j = 0; j < GUID_INPUT; j++) {
   1346 			if (!isxdigit(operands[i][j])) {
   1347 				break;
   1348 			}
   1349 			sGuid[j] = tolower(operands[i][j]);
   1350 		}
   1351 		if (j != GUID_INPUT) {
   1352 			(void) fprintf(stderr, "%s: %s: %s%d%s\n",
   1353 			    cmdName, operands[i], gettext("must be "),
   1354 			    GUID_INPUT,
   1355 			    gettext(" hexadecimal digits long"));
   1356 			continue;
   1357 		}
   1358 
   1359 		sGuid[j] = 0;
   1360 
   1361 		(void) sscanf(sGuid,
   1362 		    "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
   1363 		    &inGuid[0], &inGuid[1], &inGuid[2], &inGuid[3],
   1364 		    &inGuid[4], &inGuid[5], &inGuid[6], &inGuid[7],
   1365 		    &inGuid[8], &inGuid[9], &inGuid[10], &inGuid[11],
   1366 		    &inGuid[12], &inGuid[13], &inGuid[14], &inGuid[15]);
   1367 
   1368 		for (j = 0; j < sizeof (stmfGuid); j++) {
   1369 			delGuid.guid[j] = inGuid[j];
   1370 		}
   1371 
   1372 		stmfRet = stmfDeleteLu(&delGuid);
   1373 		switch (stmfRet) {
   1374 			case STMF_STATUS_SUCCESS:
   1375 				break;
   1376 			case STMF_ERROR_NOT_FOUND:
   1377 				noLunFound = B_TRUE;
   1378 				break;
   1379 			case STMF_ERROR_BUSY:
   1380 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   1381 				    gettext("resource busy"));
   1382 				ret++;
   1383 				break;
   1384 			case STMF_ERROR_PERM:
   1385 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   1386 				    gettext("permission denied"));
   1387 				ret++;
   1388 				break;
   1389 			default:
   1390 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   1391 				    gettext("unknown error"));
   1392 				ret++;
   1393 				break;
   1394 		}
   1395 
   1396 		if (!keepViews) {
   1397 			stmfRet = stmfGetViewEntryList(&delGuid,
   1398 			    &viewEntryList);
   1399 			if (stmfRet == STMF_STATUS_SUCCESS) {
   1400 				for (j = 0; j < viewEntryList->cnt; j++) {
   1401 					(void) stmfRemoveViewEntry(&delGuid,
   1402 					    viewEntryList->ve[j].veIndex);
   1403 				}
   1404 				viewEntriesRemoved = B_TRUE;
   1405 				stmfFreeMemory(viewEntryList);
   1406 			} else if (stmfRet != STMF_ERROR_NOT_FOUND) {
   1407 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   1408 				    gettext("unable to remove view entries\n"));
   1409 				ret++;
   1410 			} /* No view entries to remove */
   1411 		}
   1412 		if (keepViews) {
   1413 			stmfRet = stmfGetViewEntryList(&delGuid,
   1414 			    &viewEntryList);
   1415 			if (stmfRet == STMF_STATUS_SUCCESS) {
   1416 				views = B_TRUE;
   1417 				stmfFreeMemory(viewEntryList);
   1418 			}
   1419 		}
   1420 
   1421 		if ((!viewEntriesRemoved && noLunFound && !views) ||
   1422 		    (!views && keepViews && noLunFound)) {
   1423 			(void) fprintf(stderr, "%s: %s: %s\n",
   1424 			    cmdName, sGuid,
   1425 			    gettext("not found"));
   1426 			ret++;
   1427 		}
   1428 		noLunFound = viewEntriesRemoved = views = B_FALSE;
   1429 	}
   1430 	return (ret);
   1431 }
   1432 
   1433 
   1434 /*
   1435  * createTargetGroupFunc
   1436  *
   1437  * Create a target group
   1438  *
   1439  */
   1440 /*ARGSUSED*/
   1441 static int
   1442 createTargetGroupFunc(int operandLen, char *operands[], cmdOptions_t *options,
   1443     void *args)
   1444 {
   1445 	int ret = 0;
   1446 	int stmfRet;
   1447 	wchar_t groupNamePrint[sizeof (stmfGroupName)] = {0};
   1448 	stmfGroupName groupName = {0};
   1449 
   1450 	(void) strlcpy(groupName, operands[0], sizeof (groupName));
   1451 	(void) mbstowcs(groupNamePrint, (char *)groupName,
   1452 	    sizeof (stmfGroupName) - 1);
   1453 	/* call create group */
   1454 	stmfRet = stmfCreateTargetGroup(&groupName);
   1455 	switch (stmfRet) {
   1456 		case STMF_STATUS_SUCCESS:
   1457 			break;
   1458 		case STMF_ERROR_EXISTS:
   1459 			(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
   1460 			    groupNamePrint, gettext("already exists"));
   1461 			ret++;
   1462 			break;
   1463 		case STMF_ERROR_BUSY:
   1464 			(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
   1465 			    groupNamePrint, gettext("resource busy"));
   1466 			ret++;
   1467 			break;
   1468 		case STMF_ERROR_PERM:
   1469 			(void) fprintf(stderr, "%s: %s\n", cmdName,
   1470 			    gettext("permission denied"));
   1471 			ret++;
   1472 			break;
   1473 		case STMF_ERROR_SERVICE_NOT_FOUND:
   1474 			(void) fprintf(stderr, "%s: %s\n", cmdName,
   1475 			    gettext("STMF service not found"));
   1476 			ret++;
   1477 			break;
   1478 		case STMF_ERROR_SERVICE_DATA_VERSION:
   1479 			(void) fprintf(stderr, "%s: %s\n", cmdName,
   1480 			    gettext("STMF service version incorrect"));
   1481 			ret++;
   1482 			break;
   1483 		default:
   1484 			(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
   1485 			    groupNamePrint, gettext("unknown error"));
   1486 			ret++;
   1487 			break;
   1488 	}
   1489 
   1490 	return (ret);
   1491 }
   1492 
   1493 /*
   1494  * deleteHostGroupFunc
   1495  *
   1496  * Delete a host group
   1497  *
   1498  */
   1499 /*ARGSUSED*/
   1500 static int
   1501 deleteHostGroupFunc(int operandLen, char *operands[],
   1502     cmdOptions_t *options, void *args)
   1503 {
   1504 	int ret = 0;
   1505 	int stmfRet;
   1506 	wchar_t groupNamePrint[sizeof (stmfGroupName)] = {0};
   1507 	stmfGroupName groupName = {0};
   1508 
   1509 	(void) strlcpy(groupName, operands[0], sizeof (groupName));
   1510 	(void) mbstowcs(groupNamePrint, (char *)groupName,
   1511 	    sizeof (stmfGroupName) - 1);
   1512 	/* call delete group */
   1513 	stmfRet = stmfDeleteHostGroup(&groupName);
   1514 	switch (stmfRet) {
   1515 		case STMF_STATUS_SUCCESS:
   1516 			break;
   1517 		case STMF_ERROR_NOT_FOUND:
   1518 			(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
   1519 			    groupNamePrint, gettext("not found"));
   1520 			ret++;
   1521 			break;
   1522 		case STMF_ERROR_BUSY:
   1523 			(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
   1524 			    groupNamePrint, gettext("resource busy"));
   1525 			ret++;
   1526 			break;
   1527 		case STMF_ERROR_SERVICE_NOT_FOUND:
   1528 			(void) fprintf(stderr, "%s: %s\n", cmdName,
   1529 			    gettext("STMF service not found"));
   1530 			ret++;
   1531 			break;
   1532 		case STMF_ERROR_PERM:
   1533 			(void) fprintf(stderr, "%s: %s\n", cmdName,
   1534 			    gettext("permission denied"));
   1535 			ret++;
   1536 			break;
   1537 		case STMF_ERROR_GROUP_IN_USE:
   1538 			(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
   1539 			    groupNamePrint,
   1540 			    gettext("group is in use by existing view entry"));
   1541 			ret++;
   1542 			break;
   1543 		case STMF_ERROR_SERVICE_DATA_VERSION:
   1544 			(void) fprintf(stderr, "%s: %s\n", cmdName,
   1545 			    gettext("STMF service version incorrect"));
   1546 			ret++;
   1547 			break;
   1548 		default:
   1549 			(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
   1550 			    groupNamePrint, gettext("unknown error"));
   1551 			ret++;
   1552 			break;
   1553 	}
   1554 
   1555 	return (ret);
   1556 }
   1557 
   1558 /*
   1559  * deleteTargetGroupFunc
   1560  *
   1561  * Delete a target group
   1562  *
   1563  */
   1564 /*ARGSUSED*/
   1565 static int
   1566 deleteTargetGroupFunc(int operandLen, char *operands[], cmdOptions_t *options,
   1567     void *args)
   1568 {
   1569 	int ret = 0;
   1570 	int stmfRet;
   1571 	wchar_t groupNamePrint[sizeof (stmfGroupName)] = {0};
   1572 	stmfGroupName groupName = {0};
   1573 
   1574 	(void) strlcpy(groupName, operands[0], sizeof (groupName));
   1575 	(void) mbstowcs(groupNamePrint, (char *)groupName,
   1576 	    sizeof (stmfGroupName) - 1);
   1577 	/* call delete group */
   1578 	stmfRet = stmfDeleteTargetGroup(&groupName);
   1579 	switch (stmfRet) {
   1580 		case STMF_STATUS_SUCCESS:
   1581 			break;
   1582 		case STMF_ERROR_NOT_FOUND:
   1583 			(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
   1584 			    groupNamePrint, gettext("not found"));
   1585 			ret++;
   1586 			break;
   1587 		case STMF_ERROR_BUSY:
   1588 			(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
   1589 			    groupNamePrint, gettext("resource busy"));
   1590 			ret++;
   1591 			break;
   1592 		case STMF_ERROR_SERVICE_NOT_FOUND:
   1593 			(void) fprintf(stderr, "%s: %s\n", cmdName,
   1594 			    gettext("STMF service not found"));
   1595 			ret++;
   1596 			break;
   1597 		case STMF_ERROR_PERM:
   1598 			(void) fprintf(stderr, "%s: %s\n", cmdName,
   1599 			    gettext("permission denied"));
   1600 			ret++;
   1601 			break;
   1602 		case STMF_ERROR_GROUP_IN_USE:
   1603 			(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
   1604 			    groupNamePrint,
   1605 			    gettext("group is in use by existing view entry"));
   1606 			ret++;
   1607 			break;
   1608 		case STMF_ERROR_SERVICE_DATA_VERSION:
   1609 			(void) fprintf(stderr, "%s: %s\n", cmdName,
   1610 			    gettext("STMF service version incorrect"));
   1611 			ret++;
   1612 			break;
   1613 		default:
   1614 			(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
   1615 			    groupNamePrint, gettext("unknown error"));
   1616 			ret++;
   1617 			break;
   1618 	}
   1619 
   1620 	return (ret);
   1621 }
   1622 
   1623 /*
   1624  * listHostGroupFunc
   1625  *
   1626  * Lists the specified host groups or all if none are specified
   1627  *
   1628  */
   1629 /*ARGSUSED*/
   1630 static int
   1631 listHostGroupFunc(int operandLen, char *operands[], cmdOptions_t *options,
   1632     void *args)
   1633 {
   1634 	int ret = 0;
   1635 	int stmfRet;
   1636 	int i, j, outerLoop;
   1637 	boolean_t verbose = B_FALSE;
   1638 	boolean_t found = B_TRUE;
   1639 	boolean_t operandEntered;
   1640 	stmfGroupList *groupList;
   1641 	stmfGroupProperties *groupProps;
   1642 	wchar_t operandName[sizeof (stmfGroupName)];
   1643 	wchar_t groupNamePrint[sizeof (stmfGroupName)];
   1644 
   1645 	for (; options->optval; options++) {
   1646 		switch (options->optval) {
   1647 			case 'v':
   1648 				verbose = B_TRUE;
   1649 				break;
   1650 			default:
   1651 				(void) fprintf(stderr, "%s: %c: %s\n",
   1652 				    cmdName, options->optval,
   1653 				    gettext("unknown option"));
   1654 				return (1);
   1655 		}
   1656 	}
   1657 
   1658 	if (operandLen > 0) {
   1659 		outerLoop = operandLen;
   1660 		operandEntered = B_TRUE;
   1661 	} else {
   1662 		outerLoop = 1;
   1663 		operandEntered = B_FALSE;
   1664 	}
   1665 
   1666 	stmfRet = stmfGetHostGroupList(&groupList);
   1667 	if (stmfRet != STMF_STATUS_SUCCESS) {
   1668 		switch (stmfRet) {
   1669 			case STMF_ERROR_BUSY:
   1670 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   1671 				    gettext("resource busy"));
   1672 				break;
   1673 			case STMF_ERROR_SERVICE_NOT_FOUND:
   1674 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   1675 				    gettext("STMF service not found"));
   1676 				break;
   1677 			case STMF_ERROR_PERM:
   1678 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   1679 				    gettext("permission denied"));
   1680 				break;
   1681 			case STMF_ERROR_SERVICE_DATA_VERSION:
   1682 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   1683 				    gettext("STMF service version incorrect"));
   1684 				break;
   1685 			default:
   1686 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   1687 				    gettext("unknown error"));
   1688 				break;
   1689 		}
   1690 		return (1);
   1691 	}
   1692 
   1693 	for (i = 0; i < outerLoop; i++) {
   1694 		for (found = B_FALSE, j = 0; j < groupList->cnt; j++) {
   1695 			(void) mbstowcs(groupNamePrint,
   1696 			    (char *)groupList->name[j],
   1697 			    sizeof (stmfGroupName) - 1);
   1698 			groupNamePrint[sizeof (stmfGroupName) - 1] = 0;
   1699 			if (operandEntered) {
   1700 				(void) mbstowcs(operandName, operands[i],
   1701 				    sizeof (stmfGroupName) - 1);
   1702 				operandName[sizeof (stmfGroupName) - 1] = 0;
   1703 				if (wcscmp(operandName, groupNamePrint)
   1704 				    == 0) {
   1705 					found = B_TRUE;
   1706 				}
   1707 			}
   1708 			if ((found && operandEntered) || !operandEntered) {
   1709 				(void) printf("Host Group: %ws\n",
   1710 				    groupNamePrint);
   1711 				if (verbose) {
   1712 					stmfRet = stmfGetHostGroupMembers(
   1713 					    &(groupList->name[j]), &groupProps);
   1714 					if (stmfRet != STMF_STATUS_SUCCESS) {
   1715 						return (1);
   1716 					}
   1717 					printGroupProps(groupProps);
   1718 				}
   1719 				if (found && operandEntered) {
   1720 					break;
   1721 				}
   1722 			}
   1723 
   1724 		}
   1725 		if (operandEntered && !found) {
   1726 			(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
   1727 			    operands[i], gettext("not found"));
   1728 			ret = 1;
   1729 		}
   1730 	}
   1731 	return (ret);
   1732 }
   1733 
   1734 /*
   1735  * printGroupProps
   1736  *
   1737  * Prints group members for target or host groups
   1738  *
   1739  */
   1740 static void
   1741 printGroupProps(stmfGroupProperties *groupProps)
   1742 {
   1743 	int i;
   1744 	wchar_t memberIdent[sizeof (groupProps->name[0].ident) + 1] = {0};
   1745 
   1746 
   1747 	for (i = 0; i < groupProps->cnt; i++) {
   1748 		(void) mbstowcs(memberIdent, (char *)groupProps->name[i].ident,
   1749 		    sizeof (groupProps->name[0].ident));
   1750 		(void) printf("\tMember: %ws\n", memberIdent);
   1751 	}
   1752 }
   1753 
   1754 /*
   1755  * listTargetGroupFunc
   1756  *
   1757  * Lists the specified target groups or all if none are specified
   1758  *
   1759  */
   1760 /*ARGSUSED*/
   1761 static int
   1762 listTargetGroupFunc(int operandLen, char *operands[], cmdOptions_t *options,
   1763     void *args)
   1764 {
   1765 	int ret = 0;
   1766 	int stmfRet;
   1767 	int i, j, outerLoop;
   1768 	boolean_t verbose = B_FALSE;
   1769 	boolean_t found = B_TRUE;
   1770 	boolean_t operandEntered;
   1771 	stmfGroupList *groupList;
   1772 	stmfGroupProperties *groupProps;
   1773 	wchar_t operandName[sizeof (stmfGroupName)];
   1774 	wchar_t groupNamePrint[sizeof (stmfGroupName)];
   1775 
   1776 	for (; options->optval; options++) {
   1777 		switch (options->optval) {
   1778 			case 'v':
   1779 				verbose = B_TRUE;
   1780 				break;
   1781 			default:
   1782 				(void) fprintf(stderr, "%s: %c: %s\n",
   1783 				    cmdName, options->optval,
   1784 				    gettext("unknown option"));
   1785 				return (1);
   1786 		}
   1787 	}
   1788 
   1789 	if (operandLen > 0) {
   1790 		outerLoop = operandLen;
   1791 		operandEntered = B_TRUE;
   1792 	} else {
   1793 		outerLoop = 1;
   1794 		operandEntered = B_FALSE;
   1795 	}
   1796 
   1797 	stmfRet = stmfGetTargetGroupList(&groupList);
   1798 	if (stmfRet != STMF_STATUS_SUCCESS) {
   1799 		switch (stmfRet) {
   1800 			case STMF_ERROR_BUSY:
   1801 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   1802 				    gettext("resource busy"));
   1803 				break;
   1804 			case STMF_ERROR_SERVICE_NOT_FOUND:
   1805 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   1806 				    gettext("STMF service not found"));
   1807 				break;
   1808 			case STMF_ERROR_SERVICE_DATA_VERSION:
   1809 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   1810 				    gettext("STMF service version incorrect"));
   1811 				break;
   1812 			case STMF_ERROR_PERM:
   1813 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   1814 				    gettext("permission denied"));
   1815 				break;
   1816 			default:
   1817 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   1818 				    gettext("unknown error"));
   1819 				break;
   1820 		}
   1821 		return (1);
   1822 	}
   1823 
   1824 	for (i = 0; i < outerLoop; i++) {
   1825 		for (found = B_FALSE, j = 0; j < groupList->cnt; j++) {
   1826 			(void) mbstowcs(groupNamePrint,
   1827 			    (char *)groupList->name[j],
   1828 			    sizeof (stmfGroupName) - 1);
   1829 			groupNamePrint[sizeof (stmfGroupName) - 1] = 0;
   1830 			if (operandEntered) {
   1831 				(void) mbstowcs(operandName, operands[i],
   1832 				    sizeof (stmfGroupName) - 1);
   1833 				operandName[sizeof (stmfGroupName) - 1] = 0;
   1834 				if (wcscmp(operandName, groupNamePrint)
   1835 				    == 0) {
   1836 					found = B_TRUE;
   1837 				}
   1838 			}
   1839 			if ((found && operandEntered) || !operandEntered) {
   1840 				(void) printf("Target Group: %ws\n",
   1841 				    groupNamePrint);
   1842 				if (verbose) {
   1843 					stmfRet = stmfGetTargetGroupMembers(
   1844 					    &(groupList->name[j]), &groupProps);
   1845 					if (stmfRet != STMF_STATUS_SUCCESS) {
   1846 						return (1);
   1847 					}
   1848 					printGroupProps(groupProps);
   1849 				}
   1850 				if (found && operandEntered) {
   1851 					break;
   1852 				}
   1853 			}
   1854 
   1855 		}
   1856 		if (operandEntered && !found) {
   1857 			(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
   1858 			    operands[i], gettext("not found"));
   1859 			ret = 1;
   1860 		}
   1861 	}
   1862 	return (ret);
   1863 }
   1864 
   1865 /*
   1866  * listLuFunc
   1867  *
   1868  * List the logical units and optionally the properties
   1869  *
   1870  */
   1871 /*ARGSUSED*/
   1872 static int
   1873 listLuFunc(int operandLen, char *operands[], cmdOptions_t *options, void *args)
   1874 {
   1875 	cmdOptions_t *optionList = options;
   1876 	boolean_t operandEntered;
   1877 	int i, j;
   1878 	int ret = 0;
   1879 	int stmfRet;
   1880 	int outerLoop;
   1881 	unsigned int inGuid[sizeof (stmfGuid)];
   1882 	stmfGuid cmpGuid;
   1883 	boolean_t verbose = B_FALSE;
   1884 	boolean_t found;
   1885 	char sGuid[GUID_INPUT + 1];
   1886 	stmfGuidList *luList;
   1887 	stmfLogicalUnitProperties luProps;
   1888 	boolean_t invalidInput = B_FALSE;
   1889 	stmfViewEntryList *viewEntryList;
   1890 
   1891 	for (; optionList->optval; optionList++) {
   1892 		switch (optionList->optval) {
   1893 			case 'v':
   1894 				verbose = B_TRUE;
   1895 				break;
   1896 		}
   1897 	}
   1898 
   1899 	if ((stmfRet = stmfGetLogicalUnitList(&luList))
   1900 	    != STMF_STATUS_SUCCESS) {
   1901 		switch (stmfRet) {
   1902 			case STMF_ERROR_SERVICE_NOT_FOUND:
   1903 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   1904 				    gettext("STMF service not found"));
   1905 				break;
   1906 			case STMF_ERROR_BUSY:
   1907 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   1908 				    gettext("resource busy"));
   1909 				break;
   1910 			case STMF_ERROR_PERM:
   1911 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   1912 				    gettext("permission denied"));
   1913 				break;
   1914 			case STMF_ERROR_SERVICE_DATA_VERSION:
   1915 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   1916 				    gettext("STMF service version incorrect"));
   1917 				break;
   1918 			default:
   1919 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   1920 				    gettext("list failed"));
   1921 				break;
   1922 		}
   1923 		return (1);
   1924 	}
   1925 
   1926 	if (operandLen > 0) {
   1927 		operandEntered = B_TRUE;
   1928 		outerLoop = operandLen;
   1929 	} else {
   1930 		operandEntered = B_FALSE;
   1931 		outerLoop = 1;
   1932 	}
   1933 
   1934 
   1935 	for (invalidInput = B_FALSE, i = 0; i < outerLoop; i++) {
   1936 		if (operandEntered) {
   1937 			if (strlen(operands[i]) != GUID_INPUT) {
   1938 				invalidInput = B_TRUE;
   1939 			} else {
   1940 				for (j = 0; j < GUID_INPUT; j++) {
   1941 					if (!isxdigit(operands[i][j])) {
   1942 						invalidInput = B_TRUE;
   1943 						break;
   1944 					}
   1945 				}
   1946 			}
   1947 			if (invalidInput) {
   1948 				(void) fprintf(stderr, "%s: %s: %s%d%s\n",
   1949 				    cmdName, operands[i], gettext("must be "),
   1950 				    GUID_INPUT,
   1951 				    gettext(" hexadecimal digits long"));
   1952 				invalidInput = B_FALSE;
   1953 				continue;
   1954 			}
   1955 
   1956 			for (j = 0; j < GUID_INPUT; j++) {
   1957 				sGuid[j] = tolower(operands[i][j]);
   1958 			}
   1959 			sGuid[j] = 0;
   1960 
   1961 			(void) sscanf(sGuid,
   1962 			    "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
   1963 			    &inGuid[0], &inGuid[1], &inGuid[2], &inGuid[3],
   1964 			    &inGuid[4], &inGuid[5], &inGuid[6], &inGuid[7],
   1965 			    &inGuid[8], &inGuid[9], &inGuid[10], &inGuid[11],
   1966 			    &inGuid[12], &inGuid[13], &inGuid[14], &inGuid[15]);
   1967 
   1968 			for (j = 0; j < sizeof (stmfGuid); j++) {
   1969 				cmpGuid.guid[j] = inGuid[j];
   1970 			}
   1971 		}
   1972 
   1973 		for (found = B_FALSE, j = 0; j < luList->cnt; j++) {
   1974 			if (operandEntered) {
   1975 				if (bcmp(luList->guid[j].guid, cmpGuid.guid,
   1976 				    sizeof (stmfGuid)) == 0) {
   1977 					found = B_TRUE;
   1978 				}
   1979 			}
   1980 			if ((found && operandEntered) || !operandEntered) {
   1981 				(void) printf("LU Name: ");
   1982 				printGuid(&luList->guid[j], stdout);
   1983 				(void) printf("\n");
   1984 
   1985 				if (verbose) {
   1986 					stmfRet = stmfGetLogicalUnitProperties(
   1987 					    &(luList->guid[j]), &luProps);
   1988 					if (stmfRet == STMF_STATUS_SUCCESS) {
   1989 						printLuProps(&luProps);
   1990 					} else {
   1991 						(void) fprintf(stderr, "%s:",
   1992 						    cmdName);
   1993 						printGuid(&luList->guid[j],
   1994 						    stderr);
   1995 						(void) fprintf(stderr, "%s\n",
   1996 						    gettext(" get properties "
   1997 						    "failed"));
   1998 					}
   1999 					stmfRet = stmfGetViewEntryList(
   2000 					    &(luList->guid[j]),
   2001 					    &viewEntryList);
   2002 					(void) printf(PROPS_FORMAT,
   2003 					    "View Entry Count");
   2004 					if (stmfRet == STMF_STATUS_SUCCESS) {
   2005 						(void) printf("%d",
   2006 						    viewEntryList->cnt);
   2007 					} else if (stmfRet ==
   2008 					    STMF_ERROR_NOT_FOUND) {
   2009 						(void) printf("0");
   2010 					} else {
   2011 						(void) printf("unknown");
   2012 					}
   2013 					(void) printf("\n");
   2014 					ret = printExtLuProps(
   2015 					    &(luList->guid[j]));
   2016 				}
   2017 				if (found && operandEntered) {
   2018 					break;
   2019 				}
   2020 			}
   2021 
   2022 		}
   2023 		if (operandEntered && !found) {
   2024 			(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
   2025 			    operands[i], gettext("not found"));
   2026 			ret = 1;
   2027 		}
   2028 	}
   2029 
   2030 	return (ret);
   2031 }
   2032 
   2033 static void
   2034 printGuid(stmfGuid *guid, FILE *stream)
   2035 {
   2036 	int i;
   2037 	for (i = 0; i < 16; i++) {
   2038 		(void) fprintf(stream, "%02X", guid->guid[i]);
   2039 	}
   2040 }
   2041 
   2042 static int
   2043 printExtLuProps(stmfGuid *guid)
   2044 {
   2045 	int stmfRet;
   2046 	luResource hdl = NULL;
   2047 	int ret = 0;
   2048 	char propVal[MAXNAMELEN];
   2049 	size_t propValSize = sizeof (propVal);
   2050 
   2051 	if ((stmfRet = stmfGetLuResource(guid, &hdl))
   2052 	    != STMF_STATUS_SUCCESS) {
   2053 		switch (stmfRet) {
   2054 			case STMF_ERROR_BUSY:
   2055 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   2056 				    gettext("resource busy"));
   2057 				break;
   2058 			case STMF_ERROR_PERM:
   2059 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   2060 				    gettext("permission denied"));
   2061 				break;
   2062 			case STMF_ERROR_NOT_FOUND:
   2063 				/* No error here */
   2064 				return (0);
   2065 				break;
   2066 			default:
   2067 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   2068 				    gettext("get extended properties failed"));
   2069 				break;
   2070 		}
   2071 		return (1);
   2072 	}
   2073 
   2074 	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_FILENAME, propVal,
   2075 	    &propValSize);
   2076 	(void) printf(PROPS_FORMAT, "Data File");
   2077 	if (stmfRet == STMF_STATUS_SUCCESS) {
   2078 		(void) printf("%s\n", propVal);
   2079 	} else if (stmfRet == STMF_ERROR_NO_PROP) {
   2080 		(void) printf("not set\n");
   2081 	} else if (stmfRet == STMF_ERROR_NO_PROP_STANDBY) {
   2082 		(void) printf("prop unavailable in standby\n");
   2083 	} else {
   2084 		(void) printf("<error retrieving property>\n");
   2085 		ret++;
   2086 	}
   2087 
   2088 	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_META_FILENAME, propVal,
   2089 	    &propValSize);
   2090 	(void) printf(PROPS_FORMAT, "Meta File");
   2091 	if (stmfRet == STMF_STATUS_SUCCESS) {
   2092 		(void) printf("%s\n", propVal);
   2093 	} else if (stmfRet == STMF_ERROR_NO_PROP) {
   2094 		(void) printf("not set\n");
   2095 	} else if (stmfRet == STMF_ERROR_NO_PROP_STANDBY) {
   2096 		(void) printf("prop unavailable in standby\n");
   2097 	} else {
   2098 		(void) printf("<error retrieving property>\n");
   2099 		ret++;
   2100 	}
   2101 
   2102 	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_SIZE, propVal,
   2103 	    &propValSize);
   2104 	(void) printf(PROPS_FORMAT, "Size");
   2105 	if (stmfRet == STMF_STATUS_SUCCESS) {
   2106 		(void) printf("%s\n", propVal);
   2107 	} else if (stmfRet == STMF_ERROR_NO_PROP) {
   2108 		(void) printf("not set\n");
   2109 	} else if (stmfRet == STMF_ERROR_NO_PROP_STANDBY) {
   2110 		(void) printf("prop unavailable in standby\n");
   2111 	} else {
   2112 		(void) printf("<error retrieving property>\n");
   2113 		ret++;
   2114 	}
   2115 
   2116 	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_BLOCK_SIZE, propVal,
   2117 	    &propValSize);
   2118 	(void) printf(PROPS_FORMAT, "Block Size");
   2119 	if (stmfRet == STMF_STATUS_SUCCESS) {
   2120 		(void) printf("%s\n", propVal);
   2121 	} else if (stmfRet == STMF_ERROR_NO_PROP) {
   2122 		(void) printf("not set\n");
   2123 	} else if (stmfRet == STMF_ERROR_NO_PROP_STANDBY) {
   2124 		(void) printf("prop unavailable in standby\n");
   2125 	} else {
   2126 		(void) printf("<error retrieving property>\n");
   2127 		ret++;
   2128 	}
   2129 
   2130 	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_MGMT_URL, propVal,
   2131 	    &propValSize);
   2132 	(void) printf(PROPS_FORMAT, "Management URL");
   2133 	if (stmfRet == STMF_STATUS_SUCCESS) {
   2134 		(void) printf("%s\n", propVal);
   2135 	} else if (stmfRet == STMF_ERROR_NO_PROP) {
   2136 		(void) printf("not set\n");
   2137 	} else if (stmfRet == STMF_ERROR_NO_PROP_STANDBY) {
   2138 		(void) printf("prop unavailable in standby\n");
   2139 	} else {
   2140 		(void) printf("<error retrieving property>\n");
   2141 		ret++;
   2142 	}
   2143 
   2144 	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_VID, propVal,
   2145 	    &propValSize);
   2146 	(void) printf(PROPS_FORMAT, "Vendor ID");
   2147 	if (stmfRet == STMF_STATUS_SUCCESS) {
   2148 		(void) printf("%s\n", propVal);
   2149 	} else if (stmfRet == STMF_ERROR_NO_PROP) {
   2150 		(void) printf("not set\n");
   2151 	} else if (stmfRet == STMF_ERROR_NO_PROP_STANDBY) {
   2152 		(void) printf("prop unavailable in standby\n");
   2153 	} else {
   2154 		(void) printf("<error retrieving property>\n");
   2155 		ret++;
   2156 	}
   2157 
   2158 	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_PID, propVal,
   2159 	    &propValSize);
   2160 	(void) printf(PROPS_FORMAT, "Product ID");
   2161 	if (stmfRet == STMF_STATUS_SUCCESS) {
   2162 		(void) printf("%s\n", propVal);
   2163 	} else if (stmfRet == STMF_ERROR_NO_PROP) {
   2164 		(void) printf("not set\n");
   2165 	} else if (stmfRet == STMF_ERROR_NO_PROP_STANDBY) {
   2166 		(void) printf("prop unavailable in standby\n");
   2167 	} else {
   2168 		(void) printf("<error retrieving property>\n");
   2169 		ret++;
   2170 	}
   2171 
   2172 	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_SERIAL_NUM, propVal,
   2173 	    &propValSize);
   2174 	(void) printf(PROPS_FORMAT, "Serial Num");
   2175 	if (stmfRet == STMF_STATUS_SUCCESS) {
   2176 		(void) printf("%s\n", propVal);
   2177 	} else if (stmfRet == STMF_ERROR_NO_PROP) {
   2178 		(void) printf("not set\n");
   2179 	} else if (stmfRet == STMF_ERROR_NO_PROP_STANDBY) {
   2180 		(void) printf("prop unavailable in standby\n");
   2181 	} else {
   2182 		(void) printf("<error retrieving property>\n");
   2183 		ret++;
   2184 	}
   2185 
   2186 	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_WRITE_PROTECT, propVal,
   2187 	    &propValSize);
   2188 	(void) printf(PROPS_FORMAT, "Write Protect");
   2189 	if (stmfRet == STMF_STATUS_SUCCESS) {
   2190 		(void) printf("%s\n",
   2191 		    strcasecmp(propVal, "true") ? "Disabled" : "Enabled");
   2192 	} else if (stmfRet == STMF_ERROR_NO_PROP) {
   2193 		(void) printf("not set\n");
   2194 	} else if (stmfRet == STMF_ERROR_NO_PROP_STANDBY) {
   2195 		(void) printf("prop unavailable in standby\n");
   2196 	} else {
   2197 		(void) printf("<error retrieving property>\n");
   2198 		ret++;
   2199 	}
   2200 
   2201 	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_WRITE_CACHE_DISABLE, propVal,
   2202 	    &propValSize);
   2203 	(void) printf(PROPS_FORMAT, "Writeback Cache");
   2204 	if (stmfRet == STMF_STATUS_SUCCESS) {
   2205 		(void) printf("%s\n",
   2206 		    strcasecmp(propVal, "true") ? "Enabled" : "Disabled");
   2207 	} else if (stmfRet == STMF_ERROR_NO_PROP) {
   2208 		(void) printf("not set\n");
   2209 	} else if (stmfRet == STMF_ERROR_NO_PROP_STANDBY) {
   2210 		(void) printf("prop unavailable in standby\n");
   2211 	} else {
   2212 		(void) printf("<error retrieving property>\n");
   2213 		ret++;
   2214 	}
   2215 
   2216 	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_ACCESS_STATE, propVal,
   2217 	    &propValSize);
   2218 	(void) printf(PROPS_FORMAT, "Access State");
   2219 	if (stmfRet == STMF_STATUS_SUCCESS) {
   2220 		if (strcmp(propVal, STMF_ACCESS_ACTIVE) == 0) {
   2221 			(void) printf("%s\n", "Active");
   2222 		} else if (strcmp(propVal,
   2223 		    STMF_ACCESS_ACTIVE_TO_STANDBY) == 0) {
   2224 			(void) printf("%s\n", "Active->Standby");
   2225 		} else if (strcmp(propVal, STMF_ACCESS_STANDBY) == 0) {
   2226 			(void) printf("%s\n", "Standby");
   2227 		} else if (strcmp(propVal,
   2228 		    STMF_ACCESS_STANDBY_TO_ACTIVE) == 0) {
   2229 			(void) printf("%s\n", "Standby->Active");
   2230 		} else {
   2231 			(void) printf("%s\n", "Unknown");
   2232 		}
   2233 	} else if (stmfRet == STMF_ERROR_NO_PROP) {
   2234 		(void) printf("not set\n");
   2235 	} else {
   2236 		(void) printf("<error retrieving property>\n");
   2237 		ret++;
   2238 	}
   2239 
   2240 done:
   2241 	(void) stmfFreeLuResource(hdl);
   2242 	return (ret);
   2243 
   2244 }
   2245 
   2246 
   2247 /*
   2248  * printLuProps
   2249  *
   2250  * Prints the properties for a logical unit
   2251  *
   2252  */
   2253 static void
   2254 printLuProps(stmfLogicalUnitProperties *luProps)
   2255 {
   2256 	(void) printf(PROPS_FORMAT, "Operational Status");
   2257 	switch (luProps->status) {
   2258 		case STMF_LOGICAL_UNIT_ONLINE:
   2259 			(void) printf("Online");
   2260 			break;
   2261 		case STMF_LOGICAL_UNIT_OFFLINE:
   2262 			(void) printf("Offline");
   2263 			break;
   2264 		case STMF_LOGICAL_UNIT_ONLINING:
   2265 			(void) printf("Onlining");
   2266 			break;
   2267 		case STMF_LOGICAL_UNIT_OFFLINING:
   2268 			(void) printf("Offlining");
   2269 			break;
   2270 		case STMF_LOGICAL_UNIT_UNREGISTERED:
   2271 			(void) printf("unregistered");
   2272 			(void) strncpy(luProps->providerName, "unregistered",
   2273 			    sizeof (luProps->providerName));
   2274 			break;
   2275 		default:
   2276 			(void) printf("unknown");
   2277 			break;
   2278 	}
   2279 	(void) printf("\n");
   2280 	(void) printf(PROPS_FORMAT, "Provider Name");
   2281 	if (luProps->providerName[0] != 0) {
   2282 		(void) printf("%s", luProps->providerName);
   2283 	} else {
   2284 		(void) printf("unknown");
   2285 	}
   2286 	(void) printf("\n");
   2287 	(void) printf(PROPS_FORMAT, "Alias");
   2288 	if (luProps->alias[0] != 0) {
   2289 		(void) printf("%s", luProps->alias);
   2290 	} else {
   2291 		(void) printf("-");
   2292 	}
   2293 	(void) printf("\n");
   2294 }
   2295 
   2296 /*
   2297  * printTargetProps
   2298  *
   2299  * Prints the properties for a target
   2300  *
   2301  */
   2302 static void
   2303 printTargetProps(stmfTargetProperties *targetProps)
   2304 {
   2305 	(void) printf(PROPS_FORMAT, "Operational Status");
   2306 	switch (targetProps->status) {
   2307 		case STMF_TARGET_PORT_ONLINE:
   2308 			(void) printf("Online");
   2309 			break;
   2310 		case STMF_TARGET_PORT_OFFLINE:
   2311 			(void) printf("Offline");
   2312 			break;
   2313 		case STMF_TARGET_PORT_ONLINING:
   2314 			(void) printf("Onlining");
   2315 			break;
   2316 		case STMF_TARGET_PORT_OFFLINING:
   2317 			(void) printf("Offlining");
   2318 			break;
   2319 		default:
   2320 			(void) printf("unknown");
   2321 			break;
   2322 	}
   2323 	(void) printf("\n");
   2324 	(void) printf(PROPS_FORMAT, "Provider Name");
   2325 	if (targetProps->providerName[0] != 0) {
   2326 		(void) printf("%s", targetProps->providerName);
   2327 	}
   2328 	(void) printf("\n");
   2329 	(void) printf(PROPS_FORMAT, "Alias");
   2330 	if (targetProps->alias[0] != 0) {
   2331 		(void) printf("%s", targetProps->alias);
   2332 	} else {
   2333 		(void) printf("-");
   2334 	}
   2335 	(void) printf("\n");
   2336 	(void) printf(PROPS_FORMAT, "Protocol");
   2337 	switch (targetProps->protocol) {
   2338 		case STMF_PROTOCOL_FIBRE_CHANNEL:
   2339 			(void) printf("%s", "Fibre Channel");
   2340 			break;
   2341 		case STMF_PROTOCOL_ISCSI:
   2342 			(void) printf("%s", "iSCSI");
   2343 			break;
   2344 		case STMF_PROTOCOL_SRP:
   2345 			(void) printf("%s", "SRP");
   2346 			break;
   2347 		case STMF_PROTOCOL_SAS:
   2348 			(void) printf("%s", "SAS");
   2349 			break;
   2350 		default:
   2351 			(void) printf("%s", "unknown");
   2352 			break;
   2353 	}
   2354 
   2355 	(void) printf("\n");
   2356 }
   2357 
   2358 /*
   2359  * printSessionProps
   2360  *
   2361  * Prints the session data
   2362  *
   2363  */
   2364 static void
   2365 printSessionProps(stmfSessionList *sessionList)
   2366 {
   2367 	int i;
   2368 	char *cTime;
   2369 	wchar_t initiator[STMF_IDENT_LENGTH + 1];
   2370 
   2371 	(void) printf(PROPS_FORMAT, "Sessions");
   2372 	(void) printf("%d\n", sessionList->cnt);
   2373 	for (i = 0; i < sessionList->cnt; i++) {
   2374 		(void) mbstowcs(initiator,
   2375 		    (char *)sessionList->session[i].initiator.ident,
   2376 		    STMF_IDENT_LENGTH);
   2377 		initiator[STMF_IDENT_LENGTH] = 0;
   2378 		(void) printf(LVL3_FORMAT, "Initiator: ");
   2379 		(void) printf("%ws\n", initiator);
   2380 		(void) printf(LVL4_FORMAT, "Alias: ");
   2381 		if (sessionList->session[i].alias[0] != 0) {
   2382 			(void) printf("%s", sessionList->session[i].alias);
   2383 		} else {
   2384 			(void) printf("-");
   2385 		}
   2386 		(void) printf("\n");
   2387 		(void) printf(LVL4_FORMAT, "Logged in since: ");
   2388 		cTime = ctime(&(sessionList->session[i].creationTime));
   2389 		if (cTime != NULL) {
   2390 			(void) printf("%s", cTime);
   2391 		} else {
   2392 			(void) printf("unknown\n");
   2393 		}
   2394 	}
   2395 }
   2396 
   2397 static int
   2398 getStmfState(stmfState *state)
   2399 {
   2400 	int ret;
   2401 
   2402 	ret = stmfGetState(state);
   2403 	switch (ret) {
   2404 		case STMF_STATUS_SUCCESS:
   2405 			break;
   2406 		case STMF_ERROR_PERM:
   2407 			(void) fprintf(stderr, "%s: %s\n", cmdName,
   2408 			    gettext("permission denied"));
   2409 			break;
   2410 		case STMF_ERROR_SERVICE_NOT_FOUND:
   2411 			(void) fprintf(stderr, "%s: %s\n", cmdName,
   2412 			    gettext("STMF service not found"));
   2413 			break;
   2414 		case STMF_ERROR_BUSY:
   2415 			(void) fprintf(stderr, "%s: %s\n", cmdName,
   2416 			    gettext("resource busy"));
   2417 			break;
   2418 		case STMF_ERROR_SERVICE_DATA_VERSION:
   2419 			(void) fprintf(stderr, "%s: %s\n", cmdName,
   2420 			    gettext("STMF service version incorrect"));
   2421 			break;
   2422 		default:
   2423 			(void) fprintf(stderr, "%s: %s: %d\n", cmdName,
   2424 			    gettext("unknown error"), ret);
   2425 			break;
   2426 	}
   2427 	return (ret);
   2428 }
   2429 
   2430 /*
   2431  * listStateFunc
   2432  *
   2433  * List the operational and config state of the stmf service
   2434  *
   2435  */
   2436 /*ARGSUSED*/
   2437 static int
   2438 listStateFunc(int operandLen, char *operands[], cmdOptions_t *options,
   2439     void *args)
   2440 {
   2441 	int ret;
   2442 	stmfState state;
   2443 	boolean_t aluaEnabled;
   2444 	uint32_t node;
   2445 
   2446 	if ((ret = getStmfState(&state)) != STMF_STATUS_SUCCESS)
   2447 		return (ret);
   2448 
   2449 	(void) printf("%-18s: ", "Operational Status");
   2450 	switch (state.operationalState) {
   2451 		case STMF_SERVICE_STATE_ONLINE:
   2452 			(void) printf("online");
   2453 			break;
   2454 		case STMF_SERVICE_STATE_OFFLINE:
   2455 			(void) printf("offline");
   2456 			break;
   2457 		case STMF_SERVICE_STATE_ONLINING:
   2458 			(void) printf("onlining");
   2459 			break;
   2460 		case STMF_SERVICE_STATE_OFFLINING:
   2461 			(void) printf("offlining");
   2462 			break;
   2463 		default:
   2464 			(void) printf("unknown");
   2465 			break;
   2466 	}
   2467 	(void) printf("\n");
   2468 	(void) printf("%-18s: ", "Config Status");
   2469 	switch (state.configState) {
   2470 		case STMF_CONFIG_STATE_NONE:
   2471 			(void) printf("uninitialized");
   2472 			break;
   2473 		case STMF_CONFIG_STATE_INIT:
   2474 			(void) printf("initializing");
   2475 			break;
   2476 		case STMF_CONFIG_STATE_INIT_DONE:
   2477 			(void) printf("initialized");
   2478 			break;
   2479 		default:
   2480 			(void) printf("unknown");
   2481 			break;
   2482 	}
   2483 	(void) printf("\n");
   2484 	ret = stmfGetAluaState(&aluaEnabled, &node);
   2485 	switch (ret) {
   2486 		case STMF_STATUS_SUCCESS:
   2487 			break;
   2488 		case STMF_ERROR_PERM:
   2489 			(void) fprintf(stderr, "%s: %s\n", cmdName,
   2490 			    gettext("permission denied"));
   2491 			break;
   2492 		case STMF_ERROR_BUSY:
   2493 			(void) fprintf(stderr, "%s: %s\n", cmdName,
   2494 			    gettext("resource busy"));
   2495 			break;
   2496 		default:
   2497 			(void) fprintf(stderr, "%s: %s: %d\n", cmdName,
   2498 			    gettext("unknown error"), ret);
   2499 			break;
   2500 	}
   2501 	(void) printf("%-18s: ", "ALUA Status");
   2502 	if (ret == STMF_STATUS_SUCCESS) {
   2503 		if (aluaEnabled == B_TRUE) {
   2504 			(void) printf("enabled");
   2505 		} else {
   2506 			(void) printf("disabled");
   2507 		}
   2508 	} else {
   2509 		(void) printf("unknown");
   2510 	}
   2511 
   2512 	(void) printf("\n");
   2513 	(void) printf("%-18s: ", "ALUA Node");
   2514 	if (ret == STMF_STATUS_SUCCESS) {
   2515 		(void) printf("%d", node);
   2516 	} else {
   2517 		(void) printf("unknown");
   2518 	}
   2519 	(void) printf("\n");
   2520 	return (ret);
   2521 }
   2522 
   2523 /*
   2524  * listTargetFunc
   2525  *
   2526  * list the targets and optionally their properties
   2527  *
   2528  */
   2529 /*ARGSUSED*/
   2530 static int
   2531 listTargetFunc(int operandLen, char *operands[], cmdOptions_t *options,
   2532     void *args)
   2533 {
   2534 	cmdOptions_t *optionList = options;
   2535 	int ret = 0;
   2536 	int stmfRet;
   2537 	int i, j;
   2538 	int outerLoop;
   2539 	stmfSessionList *sessionList;
   2540 	stmfDevid devid;
   2541 	boolean_t operandEntered, found, verbose = B_FALSE;
   2542 	stmfDevidList *targetList;
   2543 	wchar_t targetIdent[STMF_IDENT_LENGTH + 1];
   2544 	stmfTargetProperties targetProps;
   2545 
   2546 	if ((stmfRet = stmfGetTargetList(&targetList)) != STMF_STATUS_SUCCESS) {
   2547 		switch (stmfRet) {
   2548 			case STMF_ERROR_NOT_FOUND:
   2549 				ret = 0;
   2550 				break;
   2551 			case STMF_ERROR_SERVICE_OFFLINE:
   2552 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   2553 				    gettext("STMF service offline"));
   2554 				break;
   2555 			case STMF_ERROR_BUSY:
   2556 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   2557 				    gettext("resource busy"));
   2558 				break;
   2559 			case STMF_ERROR_SERVICE_DATA_VERSION:
   2560 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   2561 				    gettext("STMF service version incorrect"));
   2562 				break;
   2563 			case STMF_ERROR_PERM:
   2564 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   2565 				    gettext("permission denied"));
   2566 				break;
   2567 			default:
   2568 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   2569 				    gettext("unknown error"));
   2570 				break;
   2571 		}
   2572 		return (1);
   2573 	}
   2574 
   2575 	for (; optionList->optval; optionList++) {
   2576 		switch (optionList->optval) {
   2577 			case 'v':
   2578 				verbose = B_TRUE;
   2579 				break;
   2580 		}
   2581 	}
   2582 
   2583 	if (operandLen > 0) {
   2584 		outerLoop = operandLen;
   2585 		operandEntered = B_TRUE;
   2586 	} else {
   2587 		outerLoop = 1;
   2588 		operandEntered = B_FALSE;
   2589 	}
   2590 
   2591 	for (i = 0; i < outerLoop; i++) {
   2592 		if (operandEntered) {
   2593 			bzero(&devid, sizeof (devid));
   2594 			(void) parseDevid(operands[i], &devid);
   2595 		}
   2596 		for (found = B_FALSE, j = 0; j < targetList->cnt; j++) {
   2597 			if (operandEntered) {
   2598 				if (bcmp(&devid, &(targetList->devid[j]),
   2599 				    sizeof (devid)) == 0) {
   2600 					found = B_TRUE;
   2601 				}
   2602 			}
   2603 			if ((found && operandEntered) || !operandEntered) {
   2604 				(void) mbstowcs(targetIdent,
   2605 				    (char *)targetList->devid[j].ident,
   2606 				    STMF_IDENT_LENGTH);
   2607 				targetIdent[STMF_IDENT_LENGTH] = 0;
   2608 				(void) printf("Target: %ws\n", targetIdent);
   2609 				if (verbose) {
   2610 					stmfRet = stmfGetTargetProperties(
   2611 					    &(targetList->devid[j]),
   2612 					    &targetProps);
   2613 					if (stmfRet == STMF_STATUS_SUCCESS) {
   2614 						printTargetProps(&targetProps);
   2615 					} else {
   2616 						(void) fprintf(stderr, "%s:",
   2617 						    cmdName);
   2618 						(void) fprintf(stderr, "%s\n",
   2619 						    gettext(" get properties"
   2620 						    " failed"));
   2621 					}
   2622 					stmfRet = stmfGetSessionList(
   2623 					    &(targetList->devid[j]),
   2624 					    &sessionList);
   2625 					if (stmfRet == STMF_STATUS_SUCCESS) {
   2626 						printSessionProps(sessionList);
   2627 					} else {
   2628 						(void) fprintf(stderr, "%s:",
   2629 						    cmdName);
   2630 						(void) fprintf(stderr, "%s\n",
   2631 						    gettext(" get session info"
   2632 						    " failed"));
   2633 					}
   2634 				}
   2635 				if (found && operandEntered) {
   2636 					break;
   2637 				}
   2638 			}
   2639 
   2640 		}
   2641 		if (operandEntered && !found) {
   2642 			(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
   2643 			    operands[i], "not found");
   2644 			ret = 1;
   2645 		}
   2646 	}
   2647 	return (ret);
   2648 }
   2649 
   2650 /*
   2651  * listViewFunc
   2652  *
   2653  * list the view entries for the specified logical unit
   2654  *
   2655  */
   2656 /*ARGSUSED*/
   2657 static int
   2658 listViewFunc(int operandLen, char *operands[], cmdOptions_t *options,
   2659     void *args)
   2660 {
   2661 	stmfViewEntryList *viewEntryList;
   2662 	stmfGuid inGuid;
   2663 	unsigned int guid[sizeof (stmfGuid)];
   2664 	int ret = 0;
   2665 	int stmfRet;
   2666 	int i, j, outerLoop;
   2667 	boolean_t found = B_TRUE;
   2668 	boolean_t operandEntered;
   2669 	uint16_t outputLuNbr;
   2670 	wchar_t groupName[sizeof (stmfGroupName)];
   2671 	char sGuid[GUID_INPUT + 1];
   2672 
   2673 
   2674 	for (; options->optval; options++) {
   2675 		switch (options->optval) {
   2676 			case 'l':
   2677 				if (strlen(options->optarg) != GUID_INPUT) {
   2678 					(void) fprintf(stderr,
   2679 					    "%s: %s: %s%d%s\n",
   2680 					    cmdName, options->optarg,
   2681 					    gettext("must be "), GUID_INPUT,
   2682 					    gettext(" hexadecimal digits"
   2683 					    " long"));
   2684 					return (1);
   2685 				}
   2686 				bcopy(options->optarg, sGuid, GUID_INPUT);
   2687 				break;
   2688 			default:
   2689 				(void) fprintf(stderr, "%s: %c: %s\n",
   2690 				    cmdName, options->optval,
   2691 				    gettext("unknown option"));
   2692 				return (1);
   2693 		}
   2694 	}
   2695 
   2696 	if (operandLen > 0) {
   2697 		outerLoop = operandLen;
   2698 		operandEntered = B_TRUE;
   2699 	} else {
   2700 		outerLoop = 1;
   2701 		operandEntered = B_FALSE;
   2702 	}
   2703 
   2704 	for (i = 0; i < 32; i++)
   2705 		sGuid[i] = tolower(sGuid[i]);
   2706 	sGuid[i] = 0;
   2707 
   2708 	(void) sscanf(sGuid, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
   2709 	    &guid[0], &guid[1], &guid[2], &guid[3], &guid[4], &guid[5],
   2710 	    &guid[6], &guid[7], &guid[8], &guid[9], &guid[10], &guid[11],
   2711 	    &guid[12], &guid[13], &guid[14], &guid[15]);
   2712 
   2713 	for (i = 0; i < sizeof (stmfGuid); i++) {
   2714 		inGuid.guid[i] = guid[i];
   2715 	}
   2716 
   2717 	if ((stmfRet = stmfGetViewEntryList(&inGuid, &viewEntryList))
   2718 	    != STMF_STATUS_SUCCESS) {
   2719 
   2720 		switch (stmfRet) {
   2721 			case STMF_ERROR_BUSY:
   2722 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
   2723 				    sGuid, gettext("resource busy"));
   2724 				break;
   2725 			case STMF_ERROR_NOT_FOUND:
   2726 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
   2727 				    sGuid, gettext("no views found"));
   2728 				break;
   2729 			case STMF_ERROR_SERVICE_NOT_FOUND:
   2730 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   2731 				    gettext("STMF service not found"));
   2732 				break;
   2733 			case STMF_ERROR_SERVICE_DATA_VERSION:
   2734 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   2735 				    gettext("STMF service version incorrect"));
   2736 				break;
   2737 			case STMF_ERROR_PERM:
   2738 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   2739 				    gettext("permission denied"));
   2740 				break;
   2741 			default:
   2742 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
   2743 				    sGuid, gettext("unknown error"));
   2744 				break;
   2745 		}
   2746 		return (1);
   2747 	}
   2748 
   2749 	for (i = 0; i < outerLoop; i++) {
   2750 		for (found = B_FALSE, j = 0; j < viewEntryList->cnt; j++) {
   2751 			if (operandEntered) {
   2752 				if (atoi(operands[i]) ==
   2753 				    viewEntryList->ve[j].veIndex) {
   2754 					found = B_TRUE;
   2755 				}
   2756 			}
   2757 			if ((found && operandEntered) || !operandEntered) {
   2758 				(void) printf("View Entry: %d\n",
   2759 				    viewEntryList->ve[j].veIndex);
   2760 				(void) printf(VIEW_FORMAT, "Host group");
   2761 				if (viewEntryList->ve[j].allHosts) {
   2762 					(void) printf("All\n");
   2763 				} else {
   2764 					(void) mbstowcs(groupName,
   2765 					    viewEntryList->ve[j].hostGroup,
   2766 					    sizeof (stmfGroupName) - 1);
   2767 					groupName[sizeof (stmfGroupName) - 1]
   2768 					    = 0;
   2769 					(void) printf("%ws\n", groupName);
   2770 				}
   2771 				(void) printf(VIEW_FORMAT, "Target group");
   2772 				if (viewEntryList->ve[j].allTargets) {
   2773 					(void) printf("All\n");
   2774 				} else {
   2775 					(void) mbstowcs(groupName,
   2776 					    viewEntryList->ve[j].targetGroup,
   2777 					    sizeof (stmfGroupName) - 1);
   2778 					groupName[sizeof (stmfGroupName) - 1]
   2779 					    = 0;
   2780 					(void) printf("%ws\n", groupName);
   2781 				}
   2782 				outputLuNbr = ((viewEntryList->ve[j].luNbr[0] &
   2783 				    0x3F) << 8) | viewEntryList->ve[j].luNbr[1];
   2784 				(void) printf(VIEW_FORMAT, "LUN");
   2785 				(void) printf("%d\n", outputLuNbr);
   2786 				if (found && operandEntered) {
   2787 					break;
   2788 				}
   2789 			}
   2790 		}
   2791 		if (operandEntered && !found) {
   2792 			(void) fprintf(stderr, "%s: %s, %s: %s\n", cmdName,
   2793 			    sGuid, operands[i], gettext("not found"));
   2794 			ret = 1;
   2795 		}
   2796 	}
   2797 
   2798 	return (ret);
   2799 }
   2800 
   2801 
   2802 /*
   2803  * onlineOfflineLu
   2804  *
   2805  * Purpose: Online or offline a logical unit
   2806  *
   2807  * lu - logical unit to online or offline
   2808  *
   2809  * state - ONLINE_LU
   2810  *         OFFLINE_LU
   2811  */
   2812 static int
   2813 onlineOfflineLu(char *lu, int state)
   2814 {
   2815 	char sGuid[GUID_INPUT + 1];
   2816 	stmfGuid inGuid;
   2817 	unsigned int guid[sizeof (stmfGuid)];
   2818 	int i;
   2819 	int ret = 0;
   2820 
   2821 	if (strlen(lu) != GUID_INPUT) {
   2822 		(void) fprintf(stderr, "%s: %s: %s %d %s\n", cmdName, lu,
   2823 		    gettext("must be"), GUID_INPUT,
   2824 		    gettext("hexadecimal digits long"));
   2825 		return (1);
   2826 	}
   2827 
   2828 	bcopy(lu, sGuid, GUID_INPUT);
   2829 
   2830 	for (i = 0; i < 32; i++)
   2831 		sGuid[i] = tolower(sGuid[i]);
   2832 	sGuid[i] = 0;
   2833 
   2834 	(void) sscanf(sGuid, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
   2835 	    &guid[0], &guid[1], &guid[2], &guid[3], &guid[4], &guid[5],
   2836 	    &guid[6], &guid[7], &guid[8], &guid[9], &guid[10], &guid[11],
   2837 	    &guid[12], &guid[13], &guid[14], &guid[15]);
   2838 
   2839 	for (i = 0; i < sizeof (stmfGuid); i++) {
   2840 		inGuid.guid[i] = guid[i];
   2841 	}
   2842 
   2843 	if (state == ONLINE_LU) {
   2844 		ret = stmfOnlineLogicalUnit(&inGuid);
   2845 	} else if (state == OFFLINE_LU) {
   2846 		ret = stmfOfflineLogicalUnit(&inGuid);
   2847 	}
   2848 	if (ret != STMF_STATUS_SUCCESS) {
   2849 		switch (ret) {
   2850 			case STMF_ERROR_PERM:
   2851 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   2852 				    gettext("permission denied"));
   2853 				break;
   2854 			case STMF_ERROR_SERVICE_NOT_FOUND:
   2855 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   2856 				    gettext("STMF service not found"));
   2857 				break;
   2858 			case STMF_ERROR_NOT_FOUND:
   2859 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
   2860 				    lu, gettext("not found"));
   2861 				break;
   2862 			case STMF_ERROR_SERVICE_DATA_VERSION:
   2863 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   2864 				    gettext("STMF service version incorrect"));
   2865 				break;
   2866 			default:
   2867 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   2868 				    gettext("unknown error"));
   2869 				break;
   2870 		}
   2871 	}
   2872 	return (ret);
   2873 }
   2874 
   2875 /*
   2876  * onlineLuFunc
   2877  *
   2878  * Purpose: Online a logical unit
   2879  *
   2880  */
   2881 /*ARGSUSED*/
   2882 static int
   2883 onlineLuFunc(int operandLen, char *operands[], cmdOptions_t *options,
   2884     void *args)
   2885 {
   2886 	int ret;
   2887 	stmfState state;
   2888 
   2889 	ret = getStmfState(&state);
   2890 	if (ret != STMF_STATUS_SUCCESS)
   2891 		return (ret);
   2892 	if (state.operationalState == STMF_SERVICE_STATE_OFFLINE ||
   2893 	    state.operationalState == STMF_SERVICE_STATE_OFFLINING) {
   2894 		(void) fprintf(stderr, "%s: %s\n", cmdName,
   2895 		    gettext("STMF service is offline"));
   2896 		return (1);
   2897 	}
   2898 	return (onlineOfflineLu(operands[0], ONLINE_LU));
   2899 }
   2900 
   2901 /*
   2902  * offlineLuFunc
   2903  *
   2904  * Purpose: Offline a logical unit
   2905  *
   2906  */
   2907 /*ARGSUSED*/
   2908 static int
   2909 offlineLuFunc(int operandLen, char *operands[], cmdOptions_t *options,
   2910     void *args)
   2911 {
   2912 	return (onlineOfflineLu(operands[0], OFFLINE_LU));
   2913 }
   2914 
   2915 /*
   2916  * onlineOfflineTarget
   2917  *
   2918  * Purpose: Online or offline a target
   2919  *
   2920  * target - target to online or offline
   2921  *
   2922  * state - ONLINE_TARGET
   2923  *         OFFLINE_TARGET
   2924  */
   2925 static int
   2926 onlineOfflineTarget(char *target, int state)
   2927 {
   2928 	int ret = 0;
   2929 	stmfDevid devid;
   2930 
   2931 	if (parseDevid(target, &devid) != 0) {
   2932 		(void) fprintf(stderr, "%s: %s: %s\n",
   2933 		    cmdName, target, gettext("unrecognized device id"));
   2934 		return (1);
   2935 	}
   2936 	if (state == ONLINE_TARGET) {
   2937 		ret = stmfOnlineTarget(&devid);
   2938 	} else if (state == OFFLINE_TARGET) {
   2939 		ret = stmfOfflineTarget(&devid);
   2940 	}
   2941 	if (ret != STMF_STATUS_SUCCESS) {
   2942 		switch (ret) {
   2943 			case STMF_ERROR_PERM:
   2944 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   2945 				    gettext("permission denied"));
   2946 				break;
   2947 			case STMF_ERROR_SERVICE_NOT_FOUND:
   2948 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   2949 				    gettext("STMF service not found"));
   2950 				break;
   2951 			case STMF_ERROR_NOT_FOUND:
   2952 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
   2953 				    target, gettext("not found"));
   2954 				break;
   2955 			case STMF_ERROR_SERVICE_DATA_VERSION:
   2956 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   2957 				    gettext("STMF service version incorrect"));
   2958 				break;
   2959 			default:
   2960 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   2961 				    gettext("unknown error"));
   2962 				break;
   2963 		}
   2964 	}
   2965 	return (ret);
   2966 }
   2967 
   2968 /*
   2969  * onlineTargetFunc
   2970  *
   2971  * Purpose: Online a target
   2972  *
   2973  */
   2974 /*ARGSUSED*/
   2975 static int
   2976 onlineTargetFunc(int operandLen, char *operands[], cmdOptions_t *options,
   2977     void *args)
   2978 {
   2979 	int ret;
   2980 	stmfState state;
   2981 
   2982 	ret = getStmfState(&state);
   2983 	if (ret != STMF_STATUS_SUCCESS)
   2984 		return (ret);
   2985 	if (state.operationalState == STMF_SERVICE_STATE_OFFLINE ||
   2986 	    state.operationalState == STMF_SERVICE_STATE_OFFLINING) {
   2987 		(void) fprintf(stderr, "%s: %s\n", cmdName,
   2988 		    gettext("STMF service is offline"));
   2989 		return (1);
   2990 	}
   2991 	return (onlineOfflineTarget(operands[0], ONLINE_TARGET));
   2992 }
   2993 
   2994 /*
   2995  * offlineTargetFunc
   2996  *
   2997  * Purpose: Offline a target
   2998  *
   2999  */
   3000 /*ARGSUSED*/
   3001 static int
   3002 offlineTargetFunc(int operandLen, char *operands[], cmdOptions_t *options,
   3003     void *args)
   3004 {
   3005 	return (onlineOfflineTarget(operands[0], OFFLINE_TARGET));
   3006 }
   3007 
   3008 
   3009 /*ARGSUSED*/
   3010 static int
   3011 removeHostGroupMemberFunc(int operandLen, char *operands[],
   3012     cmdOptions_t *options, void *args)
   3013 {
   3014 	int i;
   3015 	int ret = 0;
   3016 	int stmfRet;
   3017 	stmfGroupName groupName = {0};
   3018 	stmfDevid devid;
   3019 	wchar_t groupNamePrint[sizeof (stmfGroupName)] = {0};
   3020 
   3021 	for (; options->optval; options++) {
   3022 		switch (options->optval) {
   3023 			case 'g':
   3024 				(void) mbstowcs(groupNamePrint, options->optarg,
   3025 				    sizeof (stmfGroupName) - 1);
   3026 				bcopy(options->optarg, groupName,
   3027 				    strlen(options->optarg));
   3028 				break;
   3029 			default:
   3030 				(void) fprintf(stderr, "%s: %c: %s\n",
   3031 				    cmdName, options->optval,
   3032 				    gettext("unknown option"));
   3033 				return (1);
   3034 		}
   3035 	}
   3036 
   3037 	for (i = 0; i < operandLen; i++) {
   3038 		if (parseDevid(operands[i], &devid) != 0) {
   3039 			(void) fprintf(stderr, "%s: %s: %s\n",
   3040 			    cmdName, operands[i],
   3041 			    gettext("unrecognized device id"));
   3042 			ret++;
   3043 			continue;
   3044 		}
   3045 		stmfRet = stmfRemoveFromHostGroup(&groupName, &devid);
   3046 		switch (stmfRet) {
   3047 			case STMF_STATUS_SUCCESS:
   3048 				break;
   3049 			case STMF_ERROR_MEMBER_NOT_FOUND:
   3050 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
   3051 				    operands[i], gettext("not found"));
   3052 				ret++;
   3053 				break;
   3054 			case STMF_ERROR_GROUP_NOT_FOUND:
   3055 				(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
   3056 				    groupNamePrint, gettext("not found"));
   3057 				ret++;
   3058 				break;
   3059 			case STMF_ERROR_BUSY:
   3060 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
   3061 				    operands[i], "resource busy");
   3062 				ret++;
   3063 				break;
   3064 			case STMF_ERROR_SERVICE_NOT_FOUND:
   3065 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   3066 				    gettext("STMF service not found"));
   3067 				ret++;
   3068 				break;
   3069 			case STMF_ERROR_SERVICE_DATA_VERSION:
   3070 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   3071 				    gettext("STMF service version incorrect"));
   3072 				ret++;
   3073 				break;
   3074 			case STMF_ERROR_PERM:
   3075 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   3076 				    gettext("permission denied"));
   3077 				ret++;
   3078 				break;
   3079 			default:
   3080 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
   3081 				    operands[i], gettext("unknown error"));
   3082 				ret++;
   3083 				break;
   3084 		}
   3085 	}
   3086 
   3087 	return (ret);
   3088 }
   3089 
   3090 /*
   3091  * removeTargetGroupMemberFunc
   3092  *
   3093  * Removes one or more members from a target group
   3094  *
   3095  */
   3096 /*ARGSUSED*/
   3097 static int
   3098 removeTargetGroupMemberFunc(int operandLen, char *operands[],
   3099     cmdOptions_t *options, void *args)
   3100 {
   3101 	int i;
   3102 	int ret = 0;
   3103 	int stmfRet;
   3104 	stmfGroupName groupName = {0};
   3105 	stmfDevid devid;
   3106 	wchar_t groupNamePrint[sizeof (stmfGroupName)] = {0};
   3107 
   3108 	for (; options->optval; options++) {
   3109 		switch (options->optval) {
   3110 			case 'g':
   3111 				(void) mbstowcs(groupNamePrint, options->optarg,
   3112 				    sizeof (stmfGroupName) - 1);
   3113 				bcopy(options->optarg, groupName,
   3114 				    strlen(options->optarg));
   3115 				break;
   3116 			default:
   3117 				(void) fprintf(stderr, "%s: %c: %s\n",
   3118 				    cmdName, options->optval,
   3119 				    gettext("unknown option"));
   3120 				return (1);
   3121 		}
   3122 	}
   3123 
   3124 	for (i = 0; i < operandLen; i++) {
   3125 		if (parseDevid(operands[i], &devid) != 0) {
   3126 			(void) fprintf(stderr, "%s: %s: %s\n",
   3127 			    cmdName, operands[i],
   3128 			    gettext("unrecognized device id"));
   3129 			ret++;
   3130 			continue;
   3131 		}
   3132 		stmfRet = stmfRemoveFromTargetGroup(&groupName, &devid);
   3133 		switch (stmfRet) {
   3134 			case STMF_STATUS_SUCCESS:
   3135 				break;
   3136 			case STMF_ERROR_MEMBER_NOT_FOUND:
   3137 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
   3138 				    operands[i], gettext("not found"));
   3139 				ret++;
   3140 				break;
   3141 			case STMF_ERROR_GROUP_NOT_FOUND:
   3142 				(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
   3143 				    groupNamePrint, gettext("not found"));
   3144 				ret++;
   3145 				break;
   3146 			case STMF_ERROR_BUSY:
   3147 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
   3148 				    operands[i], gettext("resource busy"));
   3149 				ret++;
   3150 				break;
   3151 			case STMF_ERROR_SERVICE_NOT_FOUND:
   3152 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   3153 				    gettext("STMF service not found"));
   3154 				ret++;
   3155 				break;
   3156 			case STMF_ERROR_PERM:
   3157 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   3158 				    gettext("permission denied"));
   3159 				ret++;
   3160 				break;
   3161 			case STMF_ERROR_SERVICE_DATA_VERSION:
   3162 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   3163 				    gettext("STMF service version incorrect"));
   3164 				ret++;
   3165 				break;
   3166 			case STMF_ERROR_TG_ONLINE:
   3167 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   3168 				    gettext("STMF target must be offline"));
   3169 				ret++;
   3170 				break;
   3171 			default:
   3172 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
   3173 				    operands[i], gettext("unknown error"));
   3174 				ret++;
   3175 				break;
   3176 		}
   3177 	}
   3178 
   3179 	return (ret);
   3180 }
   3181 
   3182 /*
   3183  * removeViewFunc
   3184  *
   3185  * Removes one or more view entries from a logical unit
   3186  *
   3187  */
   3188 /*ARGSUSED*/
   3189 static int
   3190 removeViewFunc(int operandLen, char *operands[], cmdOptions_t *options,
   3191     void *args)
   3192 {
   3193 	char sGuid[GUID_INPUT + 1];
   3194 	stmfViewEntryList *viewEntryList;
   3195 	stmfGuid inGuid;
   3196 	uint32_t count;
   3197 	unsigned int guid[sizeof (stmfGuid)];
   3198 	char *endPtr;
   3199 	uint32_t veNbr;
   3200 	int i;
   3201 	boolean_t all = B_FALSE;
   3202 	boolean_t luInput = B_FALSE;
   3203 	int ret = 0;
   3204 	int stmfRet;
   3205 
   3206 	/* Note: 'l' is required */
   3207 	for (; options->optval; options++) {
   3208 		switch (options->optval) {
   3209 			case 'l':
   3210 				if (strlen(options->optarg) != GUID_INPUT) {
   3211 					(void) fprintf(stderr,
   3212 					    "%s: %s: %s %d %s\n",
   3213 					    cmdName, options->optarg,
   3214 					    gettext("must be"), GUID_INPUT,
   3215 					    gettext("hexadecimal digits long"));
   3216 					return (1);
   3217 				}
   3218 				bcopy(options->optarg, sGuid, GUID_INPUT);
   3219 				luInput = B_TRUE;
   3220 				break;
   3221 			case 'a':
   3222 				/* removing all view entries for this GUID */
   3223 				all = B_TRUE;
   3224 				break;
   3225 			default:
   3226 				(void) fprintf(stderr, "%s: %c: %s\n",
   3227 				    cmdName, options->optval,
   3228 				    "unknown option");
   3229 				return (1);
   3230 		}
   3231 	}
   3232 
   3233 	if (!all && operandLen == 0) {
   3234 		(void) fprintf(stderr, "%s: %s\n", cmdName,
   3235 		    gettext("no view entries specified"));
   3236 		return (1);
   3237 	}
   3238 
   3239 	if (!luInput) {
   3240 		(void) fprintf(stderr, "%s: %s\n", cmdName,
   3241 		    gettext("logical unit (-l) not specified"));
   3242 		return (1);
   3243 	}
   3244 
   3245 	for (i = 0; i < 32; i++)
   3246 		sGuid[i] = tolower(sGuid[i]);
   3247 	sGuid[i] = 0;
   3248 
   3249 	(void) sscanf(sGuid, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
   3250 	    &guid[0], &guid[1], &guid[2], &guid[3], &guid[4], &guid[5],
   3251 	    &guid[6], &guid[7], &guid[8], &guid[9], &guid[10], &guid[11],
   3252 	    &guid[12], &guid[13], &guid[14], &guid[15]);
   3253 
   3254 	for (i = 0; i < sizeof (stmfGuid); i++) {
   3255 		inGuid.guid[i] = guid[i];
   3256 	}
   3257 
   3258 	if ((stmfRet = stmfGetViewEntryList(&inGuid, &viewEntryList))
   3259 	    != STMF_STATUS_SUCCESS) {
   3260 
   3261 		switch (stmfRet) {
   3262 			case STMF_ERROR_BUSY:
   3263 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
   3264 				    sGuid, gettext("resource busy"));
   3265 				break;
   3266 			case STMF_ERROR_NOT_FOUND:
   3267 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
   3268 				    sGuid, gettext("no views found"));
   3269 				break;
   3270 			case STMF_ERROR_SERVICE_NOT_FOUND:
   3271 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   3272 				    gettext("STMF service not found"));
   3273 				break;
   3274 			case STMF_ERROR_SERVICE_DATA_VERSION:
   3275 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   3276 				    gettext("STMF service version incorrect"));
   3277 				break;
   3278 			case STMF_ERROR_PERM:
   3279 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   3280 				    gettext("permission denied"));
   3281 				break;
   3282 			default:
   3283 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
   3284 				    sGuid, gettext("unknown error"));
   3285 				break;
   3286 		}
   3287 		return (1);
   3288 	}
   3289 
   3290 	if (all) {
   3291 		count = viewEntryList->cnt;
   3292 	} else {
   3293 		count = operandLen;
   3294 	}
   3295 
   3296 	for (i = 0; i < count; i++) {
   3297 		if (all) {
   3298 			veNbr = viewEntryList->ve[i].veIndex;
   3299 		} else {
   3300 			endPtr = NULL;
   3301 			veNbr = strtol(operands[i], &endPtr, 10);
   3302 			if (endPtr && *endPtr != 0) {
   3303 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
   3304 				    operands[i], gettext("invalid input"));
   3305 				continue;
   3306 			}
   3307 		}
   3308 		stmfRet = stmfRemoveViewEntry(&inGuid, veNbr);
   3309 		switch (stmfRet) {
   3310 			case STMF_STATUS_SUCCESS:
   3311 				break;
   3312 			case STMF_ERROR_NOT_FOUND:
   3313 				(void) fprintf(stderr, "%s: %s: %d: %s\n",
   3314 				    cmdName, sGuid, veNbr,
   3315 				    gettext("not found"));
   3316 				ret++;
   3317 				break;
   3318 			case STMF_ERROR_BUSY:
   3319 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
   3320 				    sGuid, gettext("resource busy"));
   3321 				ret++;
   3322 				break;
   3323 			case STMF_ERROR_SERVICE_NOT_FOUND:
   3324 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   3325 				    gettext("STMF service not found"));
   3326 				ret++;
   3327 				break;
   3328 			case STMF_ERROR_CONFIG_NONE:
   3329 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   3330 				    gettext("STMF service is not initialized"));
   3331 				ret++;
   3332 				break;
   3333 			case STMF_ERROR_SERVICE_DATA_VERSION:
   3334 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   3335 				    gettext("STMF service version incorrect"));
   3336 				ret++;
   3337 				break;
   3338 			default:
   3339 				(void) fprintf(stderr, "%s: %s, %d: %s",
   3340 				    cmdName, sGuid, veNbr,
   3341 				    gettext("unknown error"));
   3342 				ret++;
   3343 				break;
   3344 		}
   3345 	}
   3346 
   3347 	return (ret);
   3348 }
   3349 
   3350 /*
   3351  * input:
   3352  *  execFullName - exec name of program (argv[0])
   3353  *
   3354  *  copied from usr/src/cmd/zoneadm/zoneadm.c in OS/Net
   3355  *  (changed name to lowerCamelCase to keep consistent with this file)
   3356  *
   3357  * Returns:
   3358  *  command name portion of execFullName
   3359  */
   3360 static char *
   3361 getExecBasename(char *execFullname)
   3362 {
   3363 	char *lastSlash, *execBasename;
   3364 
   3365 	/* guard against '/' at end of command invocation */
   3366 	for (;;) {
   3367 		lastSlash = strrchr(execFullname, '/');
   3368 		if (lastSlash == NULL) {
   3369 			execBasename = execFullname;
   3370 			break;
   3371 		} else {
   3372 			execBasename = lastSlash + 1;
   3373 			if (*execBasename == '\0') {
   3374 				*lastSlash = '\0';
   3375 				continue;
   3376 			}
   3377 			break;
   3378 		}
   3379 	}
   3380 	return (execBasename);
   3381 }
   3382 
   3383 int
   3384 main(int argc, char *argv[])
   3385 {
   3386 	synTables_t synTables;
   3387 	char versionString[VERSION_STRING_MAX_LEN];
   3388 	int ret;
   3389 	int funcRet;
   3390 	void *subcommandArgs = NULL;
   3391 
   3392 	(void) setlocale(LC_ALL, "");
   3393 	(void) textdomain(TEXT_DOMAIN);
   3394 	/* set global command name */
   3395 	cmdName = getExecBasename(argv[0]);
   3396 
   3397 	(void) snprintf(versionString, VERSION_STRING_MAX_LEN, "%s.%s",
   3398 	    VERSION_STRING_MAJOR, VERSION_STRING_MINOR);
   3399 	synTables.versionString = versionString;
   3400 	synTables.longOptionTbl = &longOptions[0];
   3401 	synTables.subCommandPropsTbl = &subcommands[0];
   3402 
   3403 	ret = cmdParse(argc, argv, synTables, subcommandArgs, &funcRet);
   3404 	if (ret != 0) {
   3405 		return (ret);
   3406 	}
   3407 
   3408 	return (funcRet);
   3409 } /* end main */
   3410