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