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