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