dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / raidctl / raidctl.c
blob96ea876c1d1f99dcddc73e8c46ae5704e92b3db3
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 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
25 * raidctl.c is the entry file of RAID configuration utility.
28 #include <ctype.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32 #include <langinfo.h>
33 #include <regex.h>
34 #include <locale.h>
35 #include <libintl.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <strings.h>
40 #include <unistd.h>
41 #include <errno.h>
42 #include <libgen.h>
43 #include <raidcfg.h>
46 #define TRUE 1
47 #define FALSE 0
49 #ifndef TEXT_DOMAIN
50 #define TEXT_DOMAIN "SYS_TEST"
51 #endif
54 * Return value of command
56 #define SUCCESS 0
57 #define INVALID_ARG 1
58 #define FAILURE 2
61 * Initial value of variables
63 #define INIT_HANDLE_VALUE -3
64 #define MAX64BIT 0xffffffffffffffffull
65 #define MAX32BIT 0xfffffffful
68 * Flag of set or unset HSP
70 #define HSP_SET 1
71 #define HSP_UNSET 0
74 * Operate codes of command
76 #define DO_HW_RAID_NOP -1
77 #define DO_HW_RAID_HELP 0
78 #define DO_HW_RAID_CREATEO 1
79 #define DO_HW_RAID_CREATEN 2
80 #define DO_HW_RAID_DELETE 3
81 #define DO_HW_RAID_LIST 4
82 #define DO_HW_RAID_FLASH 5
83 #define DO_HW_RAID_HSP 6
84 #define DO_HW_RAID_SET_ATTR 7
85 #define DO_HW_RAID_SNAPSHOT 8
87 #define LOWER_H (1 << 0)
88 #define LOWER_C (1 << 1)
89 #define LOWER_D (1 << 2)
90 #define LOWER_L (1 << 3)
91 #define LOWER_R (1 << 4)
92 #define LOWER_Z (1 << 5)
93 #define LOWER_G (1 << 6)
94 #define LOWER_A (1 << 7)
95 #define LOWER_S (1 << 8)
96 #define LOWER_P (1 << 9)
97 #define LOWER_F (1 << 10)
98 #define UPPER_S (1 << 11)
99 #define UPPER_C (1 << 12)
100 #define UPPER_F (1 << 13)
102 /* Add a ARRAY state (temporary) */
103 #define ARRAY_STATE_SYNC 100
106 * Function and strings to properly localize our prompt.
107 * So for example in German it would ask (ja/nein) or (yes/no) in
108 * english.
110 #ifndef SCHAR_MAX
111 #define SCHAR_MAX 10
112 #endif
114 #define RAIDCTL_LOCKF "/var/run/lockf_raidctl"
116 /* Locale setting */
117 static int yes(void);
118 static int rpmatch(char *s);
119 static char *yesexpr = NULL;
121 static char *default_yesexpr = "^[yY]";
123 static regex_t re;
125 #define SET_DEFAULT_STRS \
126 regfree(&re); \
127 free(yesexpr); \
128 yesexpr = default_yesexpr;
130 #define FREE_STRS \
131 free(yesexpr);
133 /* program name */
134 static char *prog_namep;
138 * Functions declaration
140 static void helpinfo(char *prog_namep);
141 static int do_create_cidl(char *raid_levelp, char *capacityp, char *disk_argp,
142 char *stripe_sizep, uint32_t f_flag, char **argv, uint32_t optind);
143 static int do_create_ctd(char *raid_levelp, char **disks_argpp,
144 uint32_t disks_num, uint32_t argindex, uint32_t f_flag);
145 static int do_list(char *disk_argp, char **argv, uint32_t optind,
146 uint8_t is_snapshot);
147 static int do_delete(uint32_t f_flag, char **argv, uint32_t optind);
148 static int do_flash(uint8_t f_flag, char *filep, char **ctls_argpp,
149 uint32_t index, uint32_t ctl_num);
150 static int do_set_hsp(char *a_argp, char *disk_argp, char **argv,
151 uint32_t optind);
152 static int do_set_array_attr(uint32_t f_flag, char *p_argp, char **argv,
153 uint32_t optind);
154 static int snapshot_raidsystem(uint8_t recursive, uint8_t indent,
155 uint8_t is_snapshot);
156 static int snapshot_ctl(raid_obj_handle_t ctl_handle, uint8_t recursive,
157 uint8_t indent, uint8_t is_snapshot);
158 static int snapshot_array(raid_obj_handle_t array_handle,
159 uint8_t indent, uint8_t is_sub, uint8_t is_snapshot);
160 static int snapshot_disk(uint32_t ctl_tag, raid_obj_handle_t disk_handle,
161 uint8_t indent, uint8_t is_snapshot);
162 static int print_ctl_table(raid_obj_handle_t ctl_handle);
163 static int print_array_table(raid_obj_handle_t ctl_handle,
164 raid_obj_handle_t array_handle);
165 static int print_disk_table(raid_obj_handle_t ctl_handle,
166 raid_obj_handle_t disk_handle);
167 static int print_ctl_attr(raidcfg_controller_t *attrp);
168 static int print_array_attr(raidcfg_array_t *attrp);
169 static int print_arraypart_attr(raidcfg_arraypart_t *attrp);
170 static int print_disk_attr(raid_obj_handle_t ctl_handle,
171 raid_obj_handle_t disk_handle, raidcfg_disk_t *attrp);
172 static void print_indent(uint8_t indent);
173 static int get_disk_handle_cidl(uint32_t ctl_tag, char *disks_argp,
174 int *comps_nump, raid_obj_handle_t **handlespp);
175 static int get_disk_handle_ctd(int disks_num, char **disks_argpp,
176 uint32_t *ctl_tagp, raid_obj_handle_t *disks_handlep);
177 static int get_ctl_tag(char *argp, uint32_t *ctl_tagp);
178 static int get_array_tag(char *argp, uint32_t *ctl_tagp,
179 array_tag_t *array_tagp);
180 static int get_disk_tag_ctd(char *argp, disk_tag_t *disk_tagp,
181 uint32_t *controller_id);
182 static int get_disk_tag_cidl(char *argp, disk_tag_t *disk_tagp);
183 static int calc_size(char *sizep, uint64_t *valp);
184 static int is_fully_numeric(char *strp);
185 static int size_to_string(uint64_t size, char *string, int len);
186 static int enter_raidctl_lock(int *fd);
187 static void exit_raidctl_lock(int fd);
190 * Entry function of raidctl command
193 main(int argc, char **argv)
195 /* operation index */
196 int8_t findex = DO_HW_RAID_NOP;
198 /* argument pointers */
199 char *r_argp = NULL;
200 char *z_argp = NULL;
201 char *g_argp = NULL;
202 char *a_argp = NULL;
203 char *s_argp = NULL;
204 char *p_argp = NULL;
205 char *F_argp = NULL;
206 char *C_argp = NULL;
209 * operation flags.
211 uint8_t r_flag = FALSE;
212 uint8_t f_flag = FALSE;
213 uint8_t action = FALSE;
214 uint64_t options = 0;
216 /* index and temporary variables */
217 int ret;
218 int status;
219 char c = '\0';
221 /* fd for the filelock */
222 int fd;
224 if (enter_raidctl_lock(&fd) != SUCCESS) {
225 return (FAILURE);
228 (void) setlocale(LC_ALL, "");
229 (void) textdomain(TEXT_DOMAIN);
231 /* parse command line, and get program name */
232 if ((prog_namep = strrchr(argv[0], '/')) == NULL) {
233 prog_namep = argv[0];
234 } else {
235 prog_namep++;
238 /* close error option messages from getopt */
239 opterr = 0;
241 /* get yes expression according to current locale */
242 yesexpr = strdup(nl_langinfo(YESEXPR));
243 if (yesexpr == NULL)
244 return (FAILURE);
247 * If the was no expression or if there is a compile error
248 * use default yes expression.
250 status = regcomp(&re, yesexpr, REG_EXTENDED | REG_NOSUB);
251 if ((*yesexpr == '\0') || (status != 0)) {
252 SET_DEFAULT_STRS;
253 if (regcomp(&re, default_yesexpr,
254 REG_EXTENDED | REG_NOSUB) != 0) {
255 return (FALSE);
259 while ((c = getopt(argc, argv,
260 "?hC:cdlF:r:z:g:a:s:p:fS")) != EOF) {
261 switch (c) {
262 case 'h':
263 case '?':
264 if (action == FALSE) {
265 findex = DO_HW_RAID_HELP;
266 action = TRUE;
267 options |= LOWER_H;
268 } else {
269 findex = DO_HW_RAID_NOP;
271 break;
272 case 'C':
273 if (action == FALSE) {
274 findex = DO_HW_RAID_CREATEN;
275 C_argp = optarg;
276 action = TRUE;
277 options |= UPPER_C;
278 } else {
279 findex = DO_HW_RAID_NOP;
281 break;
282 case 'c':
283 if (action == FALSE) {
284 findex = DO_HW_RAID_CREATEO;
285 action = TRUE;
286 options |= LOWER_C;
287 } else {
288 findex = DO_HW_RAID_NOP;
290 break;
291 case 'd':
292 if (action == FALSE) {
293 findex = DO_HW_RAID_DELETE;
294 action = TRUE;
295 options |= LOWER_D;
296 } else {
297 findex = DO_HW_RAID_NOP;
299 break;
300 case 'l':
301 if (action == FALSE) {
302 findex = DO_HW_RAID_LIST;
303 action = TRUE;
304 options |= LOWER_L;
305 } else {
306 findex = DO_HW_RAID_NOP;
308 break;
309 case 'F':
310 if (action == FALSE) {
311 findex = DO_HW_RAID_FLASH;
312 F_argp = optarg;
313 action = TRUE;
314 options |= UPPER_F;
315 } else {
316 findex = DO_HW_RAID_NOP;
318 break;
319 case 'a':
320 if (action == FALSE) {
321 findex = DO_HW_RAID_HSP;
322 a_argp = optarg;
323 action = TRUE;
324 options |= LOWER_A;
325 } else {
326 findex = DO_HW_RAID_NOP;
328 break;
329 case 'p':
330 if (action == FALSE) {
331 findex = DO_HW_RAID_SET_ATTR;
332 p_argp = optarg;
333 action = TRUE;
334 options |= LOWER_P;
335 } else {
336 findex = DO_HW_RAID_NOP;
338 break;
339 case 'r':
340 r_argp = optarg;
341 r_flag = TRUE;
342 options |= LOWER_R;
343 break;
344 case 'z':
345 z_argp = optarg;
346 options |= LOWER_Z;
347 break;
348 case 'g':
349 g_argp = optarg;
350 options |= LOWER_G;
351 break;
352 case 's':
353 s_argp = optarg;
354 options |= LOWER_S;
355 break;
356 case 'f':
357 f_flag = TRUE;
358 options |= LOWER_F;
359 break;
360 case 'S':
361 if (action == FALSE) {
362 findex = DO_HW_RAID_SNAPSHOT;
363 action = TRUE;
364 options |= UPPER_S;
365 } else {
366 findex = DO_HW_RAID_NOP;
368 break;
369 default:
370 (void) fprintf(stderr,
371 gettext("Invalid argument(s).\n"));
372 exit_raidctl_lock(fd);
373 FREE_STRS;
374 regfree(&re);
375 return (INVALID_ARG);
379 /* parse options */
380 switch (findex) {
381 case DO_HW_RAID_HELP:
382 if ((options & ~(LOWER_H)) != 0) {
383 ret = INVALID_ARG;
384 } else {
385 helpinfo(prog_namep);
386 ret = SUCCESS;
388 break;
389 case DO_HW_RAID_CREATEO:
390 if ((options & ~(LOWER_F | LOWER_C | LOWER_R)) != 0) {
391 ret = INVALID_ARG;
392 } else {
393 if (r_flag != FALSE && f_flag == FALSE) {
394 ret = do_create_ctd(r_argp, argv, argc - 4,
395 optind, f_flag);
396 } else if (r_flag == FALSE && f_flag == FALSE) {
397 ret = do_create_ctd(NULL, argv, argc - 2,
398 optind, f_flag);
399 } else if (r_flag != FALSE && f_flag != FALSE) {
400 ret = do_create_ctd(r_argp, argv, argc - 5,
401 optind, f_flag);
402 } else {
403 ret = do_create_ctd(NULL, argv, argc - 3,
404 optind, f_flag);
407 break;
408 case DO_HW_RAID_CREATEN:
409 if ((options & ~(LOWER_F | UPPER_C | LOWER_R | LOWER_Z |
410 LOWER_S)) != 0) {
411 ret = INVALID_ARG;
412 } else {
413 ret = do_create_cidl(r_argp, z_argp, C_argp, s_argp,
414 f_flag, argv, optind);
416 break;
417 case DO_HW_RAID_DELETE:
418 if ((options & ~(LOWER_F | LOWER_D)) != 0) {
419 ret = INVALID_ARG;
420 } else {
421 ret = do_delete(f_flag, argv, optind);
423 break;
424 case DO_HW_RAID_LIST:
425 if ((options & ~(LOWER_L | LOWER_G)) != 0) {
426 ret = INVALID_ARG;
427 } else {
428 ret = do_list(g_argp, argv, optind, FALSE);
430 break;
431 case DO_HW_RAID_SNAPSHOT:
432 if ((options & ~(UPPER_S | LOWER_G)) != 0) {
433 ret = INVALID_ARG;
434 } else {
435 ret = do_list(g_argp, argv, optind, TRUE);
437 break;
438 case DO_HW_RAID_FLASH:
439 if ((options & ~(LOWER_F | UPPER_F)) != 0) {
440 ret = INVALID_ARG;
441 } else {
442 if (f_flag == FALSE) {
443 ret = do_flash(f_flag, F_argp, argv, optind,
444 argc - 3);
445 } else {
446 ret = do_flash(f_flag, F_argp, argv, optind,
447 argc - 4);
450 break;
451 case DO_HW_RAID_HSP:
452 if ((options & ~(LOWER_A | LOWER_G)) != 0) {
453 ret = INVALID_ARG;
454 } else {
455 ret = do_set_hsp(a_argp, g_argp, argv, optind);
457 break;
458 case DO_HW_RAID_SET_ATTR:
459 if ((options & ~(LOWER_F | LOWER_P)) != 0) {
460 ret = INVALID_ARG;
461 } else {
462 ret = do_set_array_attr(f_flag, p_argp, argv, optind);
464 break;
465 case DO_HW_RAID_NOP:
466 if (argc == 1) {
467 ret = do_list(g_argp, argv, optind, FALSE);
468 } else {
469 ret = INVALID_ARG;
471 break;
472 default:
473 ret = INVALID_ARG;
474 break;
477 if (ret == INVALID_ARG) {
478 (void) fprintf(stderr,
479 gettext("Invalid argument(s).\n"));
481 exit_raidctl_lock(fd);
483 FREE_STRS;
484 regfree(&re);
485 return (ret);
489 * helpinfo(prog_namep)
490 * This function prints help informations for usrs.
492 static void
493 helpinfo(char *prog_namep)
495 char quote = '"';
497 (void) printf(gettext("%s [-f] -C %c<disks>%c [-r <raid_level>] "
498 "[-z <capacity>] [-s <stripe_size>] <controller>\n"), prog_namep,
499 quote, quote);
501 (void) printf(gettext("%s [-f] -d <volume>\n"), prog_namep);
503 (void) printf(gettext("%s [-f] -F <filename> <controller1> "
504 "[<controller2> ...]\n"), prog_namep);
506 (void) printf(gettext("%s [-f] -p %c<param>=<value>%c <volume>\n"),
507 prog_namep, quote, quote);
509 (void) printf(gettext("%s [-f] -c [-r <raid_level>] <disk1> <disk2> "
510 "[<disk3> ...]\n"), prog_namep);
512 (void) printf(gettext("%s [-l]\n"), prog_namep);
514 (void) printf(gettext("%s -l -g <disk> <controller>\n"), prog_namep);
516 (void) printf(gettext("%s -l <volume>\n"), prog_namep);
518 (void) printf(gettext("%s -l <controller1> [<controller2> ...]\n"),
519 prog_namep);
521 (void) printf(gettext("%s -a {set | unset} -g <disk> "
522 "{<volume> | <controller>}\n"), prog_namep);
524 (void) printf(gettext("%s -S [<volume> | <controller>]\n"), prog_namep);
526 (void) printf(gettext("%s -S -g <disk> <controller>\n"), prog_namep);
528 (void) printf(gettext("%s -h\n"), prog_namep);
532 * do_create_cidl(raid_levelp, capacityp, disks_argp, stripe_sizep,
533 * f_flag, argv, optind)
534 * This function creates a new RAID volume with specified arguments,
535 * and returns result as SUCCESS, INVALID_ARG or FAILURE.
536 * The "c.id.l" is used to express single physical disk. 'c' expresses
537 * bus number, 'id' expresses target number, and 'l' expresses lun.
538 * The physical disks represented by c.id.l may be invisible to OS, which
539 * means physical disks attached to controllers are not accessible by
540 * OS directly. The disks should be organized as a logical volume, and
541 * the logical volume is exported to OS as a single unit. Some hardware
542 * RAID controllers also support physical disks accessed by OS directly,
543 * for example LSI1068. In this case, it's both OK to express physical
544 * disk by c.id.l format or canonical ctd format.
546 static int
547 do_create_cidl(char *raid_levelp, char *capacityp, char *disks_argp,
548 char *stripe_sizep, uint32_t f_flag, char **argv, uint32_t optind)
550 uint32_t ctl_tag = MAX32BIT;
551 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE;
552 uint32_t raid_level = RAID_LEVEL_1;
553 uint64_t capacity = 0;
554 uint64_t stripe_size = (uint64_t)OBJ_ATTR_NONE;
555 raid_obj_handle_t *disk_handlesp = NULL;
556 raid_obj_handle_t array_handle = INIT_HANDLE_VALUE;
557 raidcfg_controller_t ctl_attr;
558 int comps_num = 0;
559 int ret = 0;
561 raidcfg_array_t array_attr;
563 if (argv[optind] == NULL || argv[optind + 1] != NULL) {
564 return (INVALID_ARG);
567 if (disks_argp == NULL) {
568 return (INVALID_ARG);
571 /* Check controller tag */
572 if (get_ctl_tag(argv[optind], &ctl_tag) != SUCCESS) {
573 return (INVALID_ARG);
576 ctl_handle = raidcfg_get_controller(ctl_tag);
577 if (ctl_handle <= 0) {
578 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ctl_handle));
579 return (FAILURE);
582 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
583 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
584 return (FAILURE);
587 /* Get raid level */
588 if (raid_levelp != NULL) {
589 if (*raid_levelp == '1' &&
590 (*(raid_levelp + 1) == 'E' || *(raid_levelp + 1) == 'e')) {
591 raid_level = RAID_LEVEL_1E;
592 } else {
593 if (is_fully_numeric(raid_levelp) == FALSE) {
594 return (INVALID_ARG);
597 switch (atoi(raid_levelp)) {
598 case 0:
599 raid_level = RAID_LEVEL_0;
600 break;
601 case 1:
602 raid_level = RAID_LEVEL_1;
603 break;
604 case 5:
605 raid_level = RAID_LEVEL_5;
606 break;
607 case 10:
608 raid_level = RAID_LEVEL_10;
609 break;
610 case 50:
611 raid_level = RAID_LEVEL_50;
612 break;
613 default:
614 return (INVALID_ARG);
620 * The rang check of capacity and stripe size is performed in library,
621 * and it relates to hardware feature.
624 /* Capacity in bytes. Capacity 0 means max available space. */
625 if (capacityp != NULL) {
626 if (*capacityp == '-' ||
627 calc_size(capacityp, &capacity) != SUCCESS) {
628 return (INVALID_ARG);
632 /* Stripe size in bytes */
633 if (stripe_sizep != NULL) {
634 if (calc_size(stripe_sizep, &stripe_size) != SUCCESS ||
635 *stripe_sizep == '-') {
636 return (INVALID_ARG);
640 /* Open controller before accessing its object */
641 if ((ret = raidcfg_open_controller(ctl_handle, NULL)) < 0) {
642 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
643 return (FAILURE);
646 /* Get disks' handles */
647 if ((ret = get_disk_handle_cidl(ctl_tag, disks_argp, &comps_num,
648 &disk_handlesp)) != SUCCESS) {
649 (void) raidcfg_close_controller(ctl_handle, NULL);
650 return (ret);
653 if (f_flag == FALSE) {
654 (void) fprintf(stdout, gettext("Creating RAID volume "
655 "will destroy all data on spare space of member disks, "
656 "proceed? "));
657 if (!yes()) {
658 (void) fprintf(stdout, gettext("RAID volume "
659 "not created.\n\n"));
660 (void) raidcfg_close_controller(ctl_handle, NULL);
661 free(disk_handlesp);
662 return (SUCCESS);
666 /* Create array */
667 array_handle = raidcfg_create_array(comps_num,
668 disk_handlesp, raid_level, capacity, stripe_size, NULL);
670 if (array_handle <= 0) {
671 (void) fprintf(stderr, "%s\n", raidcfg_errstr(array_handle));
672 free(disk_handlesp);
673 (void) raidcfg_close_controller(ctl_handle, NULL);
674 return (FAILURE);
677 /* Get attribute of the new created array */
678 if ((ret = raidcfg_get_attr(array_handle, &array_attr)) < 0) {
679 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
680 free(disk_handlesp);
681 (void) raidcfg_close_controller(ctl_handle, NULL);
682 return (FAILURE);
685 (void) fprintf(stdout, gettext("Volume c%ut%llud%llu is created "
686 "successfully!\n"), ctl_tag, array_attr.tag.idl.target_id,
687 array_attr.tag.idl.lun);
689 /* Print attribute of array */
690 (void) print_array_table(ctl_handle, array_handle);
692 /* Close controller */
693 (void) raidcfg_close_controller(ctl_handle, NULL);
695 free(disk_handlesp);
696 return (SUCCESS);
700 * do_create_ctd(raid_levelp, disks_argpp, disks_num, argindex, f_flag)
701 * This function creates array with specified arguments, and return result
702 * as SUCCESS, FAILURE, or INVALID_ARG. It only supports LSI MPT controller
703 * to be compatible with old raidctl. The capacity and stripe size can't
704 * be specified for LSI MPT controller, and they use zero and default value.
705 * The "ctd" is the canonical expression of physical disks which are
706 * accessible by OS.
708 static int
709 do_create_ctd(char *raid_levelp, char **disks_argpp, uint32_t disks_num,
710 uint32_t argindex, uint32_t f_flag)
712 uint32_t ctl_tag = MAX32BIT;
713 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE;
714 uint32_t raid_level = RAID_LEVEL_1;
715 uint64_t capacity = 0;
716 uint32_t stripe_size = (uint32_t)OBJ_ATTR_NONE;
717 raid_obj_handle_t *disk_handlesp = NULL;
718 raid_obj_handle_t array_handle = INIT_HANDLE_VALUE;
719 raidcfg_controller_t ctl_attr;
720 int ret;
722 raidcfg_array_t array_attr;
723 int i, j;
725 /* Check disks parameter */
726 if (disks_argpp == NULL || disks_num < 2) {
727 return (INVALID_ARG);
730 for (i = 0, j = argindex; i < disks_num; i++, j++) {
731 if (disks_argpp[j] == NULL) {
732 return (INVALID_ARG);
737 * We need check if the raid_level string is fully numeric. If user
738 * input string with unsupported letters, such as "s10", atoi() will
739 * return zero because it is an illegal string, but it doesn't mean
740 * RAID_LEVEL_0.
742 if (raid_levelp != NULL) {
743 if (*raid_levelp == '1' &&
744 (*(raid_levelp + 1) == 'E' || *(raid_levelp + 1) == 'e')) {
745 raid_level = RAID_LEVEL_1E;
746 } else {
747 if (is_fully_numeric(raid_levelp) == FALSE) {
748 return (INVALID_ARG);
751 switch (atoi(raid_levelp)) {
752 case 0:
753 raid_level = RAID_LEVEL_0;
754 break;
755 case 1:
756 raid_level = RAID_LEVEL_1;
757 break;
758 case 5:
759 raid_level = RAID_LEVEL_5;
760 break;
761 default:
762 return (INVALID_ARG);
767 /* Get disks tag and controller tag */
768 disk_handlesp = (raid_obj_handle_t *)calloc(disks_num + 2,
769 sizeof (raid_obj_handle_t));
770 if (disk_handlesp == NULL) {
771 return (FAILURE);
774 disk_handlesp[0] = OBJ_SEPARATOR_BEGIN;
775 disk_handlesp[disks_num + 1] = OBJ_SEPARATOR_END;
777 if ((ret = get_disk_handle_ctd(disks_num, &disks_argpp[argindex],
778 &ctl_tag, &disk_handlesp[1])) != SUCCESS) {
779 free(disk_handlesp);
780 return (ret);
783 /* LIB API should check whether all disks here belong to one ctl. */
784 /* get_disk_handle_ctd has opened controller. */
785 ctl_handle = raidcfg_get_controller(ctl_tag);
787 if (ctl_handle <= 0) {
788 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ctl_handle));
789 (void) raidcfg_close_controller(ctl_handle, NULL);
790 free(disk_handlesp);
791 return (FAILURE);
794 /* Check if the controller is host raid type */
795 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
796 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
797 (void) raidcfg_close_controller(ctl_handle, NULL);
798 free(disk_handlesp);
799 return (FAILURE);
802 if ((ctl_attr.capability & RAID_CAP_DISK_TRANS) == 0) {
803 /* -c only support host raid controller, return failure here */
804 (void) fprintf(stderr,
805 gettext("Option -c only supports host raid controller.\n"));
806 (void) raidcfg_close_controller(ctl_handle, NULL);
807 free(disk_handlesp);
808 return (FAILURE);
811 if (f_flag == FALSE) {
812 (void) fprintf(stdout, gettext("Creating RAID volume "
813 "will destroy all data on spare space of member disks, "
814 "proceed? "));
815 if (!yes()) {
816 (void) fprintf(stdout, gettext("RAID volume "
817 "not created.\n\n"));
818 free(disk_handlesp);
819 (void) raidcfg_close_controller(ctl_handle, NULL);
820 return (SUCCESS);
825 * For old raidctl, capacity is 0, which means to creates
826 * max possible capacity of array.
829 array_handle = raidcfg_create_array(disks_num + 2,
830 disk_handlesp, raid_level, capacity, stripe_size, NULL);
832 if (array_handle <= 0) {
833 (void) fprintf(stderr, "%s\n", raidcfg_errstr(array_handle));
834 free(disk_handlesp);
835 (void) raidcfg_close_controller(ctl_handle, NULL);
836 return (FAILURE);
839 /* Get attribute of array */
840 if ((ret = raidcfg_get_attr(array_handle, &array_attr)) < 0) {
841 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
842 free(disk_handlesp);
843 (void) raidcfg_close_controller(ctl_handle, NULL);
844 return (FAILURE);
847 /* Close controller */
848 (void) raidcfg_close_controller(ctl_handle, NULL);
850 /* Print feedback for user */
851 (void) fprintf(stdout,
852 gettext("Volume c%ut%llud%llu is created successfully!\n"),
853 ctl_tag, array_attr.tag.idl.target_id,
854 array_attr.tag.idl.lun);
855 free(disk_handlesp);
856 return (SUCCESS);
860 * do_list(disk_arg, argv, optind, is_snapshot)
861 * This function lists RAID's system configuration. It supports various RAID
862 * controller. The return value can be SUCCESS, FAILURE, or INVALID_ARG.
864 static int
865 do_list(char *disk_argp, char **argv, uint32_t optind, uint8_t is_snapshot)
867 uint32_t ctl_tag = MAX32BIT;
868 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE;
869 raid_obj_handle_t disk_handle = INIT_HANDLE_VALUE;
870 raid_obj_handle_t array_handle = INIT_HANDLE_VALUE;
871 disk_tag_t disk_tag;
872 array_tag_t array_tag;
874 int ret;
876 /* print RAID system */
877 if (disk_argp == NULL) {
878 if (argv[optind] == NULL) {
879 ret = snapshot_raidsystem(TRUE, 0, is_snapshot);
880 return (ret);
881 } else {
882 if (is_fully_numeric(argv[optind]) == TRUE) {
883 while (argv[optind] != NULL) {
884 if (get_ctl_tag(argv[optind], &ctl_tag)
885 != SUCCESS) {
886 ret = INVALID_ARG;
887 optind++;
888 continue;
890 ctl_handle =
891 raidcfg_get_controller(ctl_tag);
892 if (ctl_handle <= 0) {
893 (void) fprintf(stderr, "%s\n",
894 raidcfg_errstr(ctl_handle));
895 ret = FAILURE;
896 optind++;
897 continue;
899 ret =
900 raidcfg_open_controller(ctl_handle,
901 NULL);
902 if (ret < 0) {
903 (void) fprintf(stderr, "%s\n",
904 raidcfg_errstr(ret));
905 ret = FAILURE;
906 optind++;
907 continue;
909 if (is_snapshot == FALSE) {
910 ret =
911 print_ctl_table(ctl_handle);
912 } else {
913 ret =
914 snapshot_ctl(ctl_handle,
915 FALSE, 0, is_snapshot);
917 (void) raidcfg_close_controller(
918 ctl_handle, NULL);
919 optind++;
921 } else {
922 if (get_array_tag(argv[optind],
923 &ctl_tag, &array_tag) != SUCCESS) {
924 return (INVALID_ARG);
926 ctl_handle = raidcfg_get_controller(ctl_tag);
927 if (ctl_handle <= 0) {
928 (void) fprintf(stderr, "%s\n",
929 raidcfg_errstr(ctl_handle));
930 return (FAILURE);
933 ret = raidcfg_open_controller(ctl_handle, NULL);
934 if (ret < 0) {
935 (void) fprintf(stderr, "%s\n",
936 raidcfg_errstr(ret));
937 return (FAILURE);
940 array_handle = raidcfg_get_array(ctl_handle,
941 array_tag.idl.target_id, array_tag.idl.lun);
942 if (array_handle <= 0) {
943 (void) fprintf(stderr, "%s\n",
944 raidcfg_errstr(array_handle));
945 (void) raidcfg_close_controller(
946 ctl_handle, NULL);
947 return (FAILURE);
949 if (is_snapshot == FALSE) {
950 ret = print_array_table(ctl_handle,
951 array_handle);
952 } else {
953 ret = snapshot_array(array_handle, 0,
954 FALSE, is_snapshot);
956 (void) raidcfg_close_controller(
957 ctl_handle, NULL);
960 } else {
961 if (argv[optind + 1] != NULL) {
962 return (INVALID_ARG);
965 if (get_ctl_tag(argv[optind], &ctl_tag) != SUCCESS) {
966 return (INVALID_ARG);
969 ctl_handle = raidcfg_get_controller(ctl_tag);
970 if (ctl_handle <= 0) {
971 (void) fprintf(stderr, "%s\n",
972 raidcfg_errstr(ctl_handle));
973 return (FAILURE);
976 if (get_disk_tag_cidl(disk_argp, &disk_tag) != SUCCESS) {
977 return (INVALID_ARG);
980 ret = raidcfg_open_controller(ctl_handle, NULL);
981 if (ret < 0) {
982 (void) fprintf(stderr, "%s\n",
983 raidcfg_errstr(ret));
984 return (FAILURE);
987 disk_handle = raidcfg_get_disk(ctl_handle, disk_tag);
988 if (disk_handle <= 0) {
989 (void) fprintf(stderr, "%s\n",
990 raidcfg_errstr(disk_handle));
991 (void) raidcfg_close_controller(ctl_handle, NULL);
992 return (FAILURE);
995 if (is_snapshot == FALSE) {
996 ret = print_disk_table(ctl_handle, disk_handle);
997 } else {
998 ret = snapshot_disk(ctl_tag, disk_handle, 0,
999 is_snapshot);
1001 (void) raidcfg_close_controller(ctl_handle, NULL);
1003 return (ret);
1007 * do_delete(f_flag, argv, optind)
1008 * This function deletes a specified array, and return result as SUCCESS,
1009 * FAILURE or INVALID_ARG.
1011 static int
1012 do_delete(uint32_t f_flag, char **argv, uint32_t optind)
1014 uint32_t ctl_tag;
1015 char *array_argp;
1016 array_tag_t array_tag;
1017 raid_obj_handle_t ctl_handle;
1018 raid_obj_handle_t array_handle;
1019 int ret;
1021 array_argp = argv[optind];
1022 if (array_argp == NULL || argv[optind + 1] != NULL) {
1023 return (INVALID_ARG);
1026 if (get_array_tag(array_argp, &ctl_tag, &array_tag) != SUCCESS) {
1027 return (INVALID_ARG);
1030 ctl_handle = raidcfg_get_controller(ctl_tag);
1031 if (ctl_handle <= 0) {
1032 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ctl_handle));
1033 return (INVALID_ARG);
1036 ret = raidcfg_open_controller(ctl_handle, NULL);
1037 if (ret < 0) {
1038 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1039 return (FAILURE);
1042 array_handle = raidcfg_get_array(ctl_handle, array_tag.idl.target_id,
1043 array_tag.idl.lun);
1044 if (array_handle <= 0) {
1045 (void) fprintf(stderr, "%s\n", raidcfg_errstr(array_handle));
1046 (void) raidcfg_close_controller(ctl_handle, NULL);
1047 return (FAILURE);
1050 if (f_flag == FALSE) {
1051 (void) fprintf(stdout, gettext("Deleting RAID volume "
1052 "%s will destroy all data it contains, "
1053 "proceed? "), array_argp);
1054 if (!yes()) {
1055 (void) fprintf(stdout, gettext("RAID Volume "
1056 "%s not deleted.\n\n"), array_argp);
1057 (void) raidcfg_close_controller(ctl_handle, NULL);
1058 return (SUCCESS);
1063 if ((ret = raidcfg_delete_array(array_handle, NULL)) < 0) {
1064 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1065 (void) raidcfg_close_controller(ctl_handle, NULL);
1066 return (FAILURE);
1069 (void) fprintf(stdout, gettext("Volume %s is deleted successfully!\n"),
1070 array_argp);
1071 (void) raidcfg_close_controller(ctl_handle, NULL);
1073 return (SUCCESS);
1077 * do_flash(f_flag, filep, ctls_argpp, index, ctl_num)
1078 * This function downloads and updates firmware for specified controller, and
1079 * return result as SUCCESS, FAILURE or INVALID_ARG.
1081 static int
1082 do_flash(uint8_t f_flag, char *filep, char **ctls_argpp,
1083 uint32_t index, uint32_t ctl_num)
1085 uint32_t ctl_tag = MAX32BIT;
1086 char *ctl_argp = NULL;
1087 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE;
1088 int ret;
1089 int i, j;
1091 if (ctl_num == 0)
1092 return (INVALID_ARG);
1094 for (i = 0, j = index; i < ctl_num; i++, j++) {
1095 ctl_argp = ctls_argpp[j];
1096 if (get_ctl_tag(ctl_argp, &ctl_tag) != SUCCESS) {
1097 return (INVALID_ARG);
1100 /* Ask user to confirm operation. */
1101 if (f_flag == FALSE) {
1102 (void) fprintf(stdout, gettext("Update flash image on "
1103 "controller %d? "), ctl_tag);
1104 if (!yes()) {
1105 (void) fprintf(stdout,
1106 gettext("Controller %d not "
1107 "flashed.\n\n"), ctl_tag);
1108 return (SUCCESS);
1112 if ((ctl_handle = raidcfg_get_controller(ctl_tag)) < 0) {
1113 (void) fprintf(stderr, "%s\n",
1114 raidcfg_errstr(ctl_handle));
1115 return (FAILURE);
1118 ret = raidcfg_open_controller(ctl_handle, NULL);
1119 if (ret < 0) {
1120 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1121 return (FAILURE);
1124 (void) fprintf(stdout, gettext("Start updating controller "
1125 "c%u firmware....\n"), ctl_tag);
1127 if ((ret = raidcfg_update_fw(ctl_handle, filep, NULL)) < 0) {
1128 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1129 (void) raidcfg_close_controller(ctl_handle, NULL);
1130 return (FAILURE);
1133 (void) fprintf(stdout, gettext("Update controller "
1134 "c%u firmware successfully.\n"), ctl_tag);
1136 (void) raidcfg_close_controller(ctl_handle, NULL);
1139 return (SUCCESS);
1143 * do_set_hsp(a_argp, disk_argp, argv, optind)
1144 * This function set or unset HSP relationship between disk and controller/
1145 * array, and return result as SUCCESS, FAILURE or INVALID_ARG.
1147 static int
1148 do_set_hsp(char *a_argp, char *disk_argp, char **argv, uint32_t optind)
1150 uint32_t flag = MAX32BIT;
1151 uint32_t ctl_tag = MAX32BIT;
1152 array_tag_t array_tag;
1153 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE;
1154 raid_obj_handle_t disk_handle = INIT_HANDLE_VALUE;
1155 raid_obj_handle_t array_handle = INIT_HANDLE_VALUE;
1156 raidcfg_controller_t ctl_attr;
1157 disk_tag_t disk_tag;
1159 int ret;
1160 int hsp_type;
1161 raidcfg_hsp_relation_t hsp_relation;
1163 (void) memset(&hsp_relation, 0, sizeof (raidcfg_hsp_relation_t));
1165 if (a_argp == NULL) {
1166 return (INVALID_ARG);
1169 if (strcmp(a_argp, "set") == 0) {
1170 flag = HSP_SET;
1171 } else if (strcmp(a_argp, "unset") == 0) {
1172 flag = HSP_UNSET;
1173 } else {
1174 return (INVALID_ARG);
1177 if (disk_argp == NULL) {
1178 return (INVALID_ARG);
1181 if (argv[optind] == NULL || argv[optind + 1] != NULL) {
1182 return (INVALID_ARG);
1183 } else if (is_fully_numeric(argv[optind]) == TRUE) {
1184 /* Global HSP */
1185 hsp_type = 0;
1186 if (get_disk_tag_cidl(disk_argp, &disk_tag) != SUCCESS) {
1187 return (INVALID_ARG);
1190 if (get_ctl_tag(argv[optind], &ctl_tag) != SUCCESS) {
1191 return (INVALID_ARG);
1194 ctl_handle = raidcfg_get_controller(ctl_tag);
1195 if (ctl_handle <= 0) {
1196 (void) fprintf(stderr, "%s\n",
1197 raidcfg_errstr(ctl_handle));
1198 return (FAILURE);
1201 ret = raidcfg_open_controller(ctl_handle, NULL);
1202 if (ret < 0) {
1203 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1204 return (FAILURE);
1207 disk_handle = raidcfg_get_disk(ctl_handle, disk_tag);
1208 if (disk_handle <= 0) {
1209 (void) fprintf(stderr, "%s\n",
1210 raidcfg_errstr(disk_handle));
1211 (void) raidcfg_close_controller(ctl_handle, NULL);
1212 return (FAILURE);
1214 } else {
1215 /* Local HSP */
1216 hsp_type = 1;
1217 if (get_array_tag(argv[optind], &ctl_tag, &array_tag) !=
1218 SUCCESS) {
1219 return (INVALID_ARG);
1222 /* Open controller */
1223 ctl_handle = raidcfg_get_controller(ctl_tag);
1224 if (ctl_handle <= 0) {
1225 (void) fprintf(stderr, "%s\n",
1226 raidcfg_errstr(ctl_handle));
1227 return (FAILURE);
1230 ret = raidcfg_open_controller(ctl_handle, NULL);
1231 if (ret < 0) {
1232 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1233 return (FAILURE);
1236 /* Get controller's attribute */
1237 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
1238 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1239 (void) raidcfg_close_controller(ctl_handle, NULL);
1240 return (FAILURE);
1243 if (get_disk_tag_cidl(disk_argp, &disk_tag) != SUCCESS) {
1244 (void) raidcfg_close_controller(ctl_handle, NULL);
1245 return (INVALID_ARG);
1248 /* Get disk handle */
1249 disk_handle = raidcfg_get_disk(ctl_handle, disk_tag);
1250 if (disk_handle <= 0) {
1251 (void) fprintf(stderr, "%s\n",
1252 raidcfg_errstr(disk_handle));
1253 (void) raidcfg_close_controller(ctl_handle, NULL);
1254 return (FAILURE);
1257 /* Get array handle */
1258 array_handle = raidcfg_get_array(ctl_handle,
1259 array_tag.idl.target_id, array_tag.idl.lun);
1260 if (array_handle <= 0) {
1261 (void) fprintf(stderr, "%s\n",
1262 raidcfg_errstr(array_handle));
1263 (void) raidcfg_close_controller(ctl_handle, NULL);
1264 return (FAILURE);
1268 hsp_relation.disk_handle = disk_handle;
1269 if (hsp_type) {
1270 /* Set or unset local HSP */
1271 hsp_relation.array_handle = array_handle;
1272 } else {
1273 /* Set or unset global HSP */
1274 hsp_relation.array_handle = OBJ_ATTR_NONE;
1277 /* Perform operation of set or unset */
1278 if (flag == HSP_SET) {
1279 if ((ret = raidcfg_set_hsp(&hsp_relation, NULL)) < 0) {
1280 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1281 (void) raidcfg_close_controller(ctl_handle, NULL);
1282 return (FAILURE);
1285 if (hsp_type) {
1286 (void) printf(gettext("Set local HSP between disk %s "
1287 "and RAID volume %s successfully.\n"),
1288 disk_argp, argv[optind]);
1289 } else {
1290 (void) printf(gettext("Set global HSP between disk %s "
1291 "and controller %s successfully.\n"),
1292 disk_argp, argv[optind]);
1294 } else {
1295 if ((ret = raidcfg_unset_hsp(&hsp_relation, NULL)) < 0) {
1296 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1297 (void) raidcfg_close_controller(ctl_handle, NULL);
1298 return (FAILURE);
1301 if (hsp_type) {
1302 (void) printf(gettext("Unset local HSP between "
1303 "disk %s and RAID volume %s successfully.\n"),
1304 disk_argp, argv[optind]);
1305 } else {
1306 (void) printf(gettext("Unset global HSP between "
1307 "disk %s and controller %s successfully.\n"),
1308 disk_argp, argv[optind]);
1311 (void) raidcfg_close_controller(ctl_handle, NULL);
1312 return (SUCCESS);
1316 * do_set_array_attr(f_flag, p_argp, argv, optind)
1317 * This function changes array's attribute when array is running.
1318 * The changeable attribute is up to controller's feature.
1319 * The return value can be SUCCESS, FAILURE or INVALID_ARG.
1321 static int
1322 do_set_array_attr(uint32_t f_flag, char *p_argp, char **argv, uint32_t optind)
1324 uint32_t ctl_tag = MAX32BIT;
1325 array_tag_t array_tag;
1326 uint32_t type = MAX32BIT;
1327 uint32_t value = MAX32BIT;
1328 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE;
1329 raid_obj_handle_t array_handle = INIT_HANDLE_VALUE;
1331 char *param, *op = "=";
1333 int ret;
1335 if (argv[optind] == NULL || argv[optind + 1] != NULL) {
1336 return (INVALID_ARG);
1339 if (p_argp != NULL) {
1340 param = strtok(p_argp, op);
1341 if (strcmp(param, "wp") == 0) {
1342 type = SET_CACHE_WR_PLY;
1343 param = strtok(NULL, op);
1344 if (strcmp(param, "on") == 0) {
1345 value = CACHE_WR_ON;
1346 } else if (strcmp(param, "off") == 0) {
1347 value = CACHE_WR_OFF;
1348 } else {
1349 return (INVALID_ARG);
1351 } else if (strcmp(param, "state") == 0) {
1352 type = SET_ACTIVATION_PLY;
1353 param = strtok(NULL, op);
1354 if (strcmp(param, "activate") == 0) {
1355 value = ARRAY_ACT_ACTIVATE;
1356 } else {
1357 return (INVALID_ARG);
1359 } else {
1360 return (INVALID_ARG);
1362 } else {
1363 return (INVALID_ARG);
1366 if (get_array_tag(argv[optind], &ctl_tag, &array_tag) != SUCCESS) {
1367 return (INVALID_ARG);
1370 ctl_handle = raidcfg_get_controller(ctl_tag);
1371 if (ctl_handle <= 0) {
1372 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ctl_handle));
1373 return (FAILURE);
1376 ret = raidcfg_open_controller(ctl_handle, NULL);
1377 if (ret < 0) {
1378 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1379 return (FAILURE);
1382 array_handle = raidcfg_get_array(ctl_handle, array_tag.idl.target_id,
1383 array_tag.idl.lun);
1384 if (array_handle <= 0) {
1385 (void) fprintf(stderr, "%s\n", raidcfg_errstr(array_handle));
1386 return (FAILURE);
1389 /* Ask user to confirm operation. */
1390 if (f_flag == FALSE) {
1391 (void) fprintf(stdout, gettext("Update attribute of "
1392 "array %s? "), argv[optind]);
1393 if (!yes()) {
1394 (void) fprintf(stdout,
1395 gettext("Array %s not "
1396 "changed.\n\n"), argv[optind]);
1397 (void) raidcfg_close_controller(ctl_handle, NULL);
1398 return (SUCCESS);
1402 if ((ret = raidcfg_set_attr(array_handle, type, &value, NULL)) < 0) {
1403 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1404 (void) raidcfg_close_controller(ctl_handle, NULL);
1405 return (FAILURE);
1408 (void) printf(gettext("Set attribute of RAID volume %s "
1409 "successfully.\n"), argv[optind]);
1410 (void) raidcfg_close_controller(ctl_handle, NULL);
1412 return (SUCCESS);
1416 * snapshot_raidsystem(recursive, indent, is_snapshot)
1417 * This function prints the snapshot of whole RAID's system configuration,
1418 * and return result as SUCCESS or FAILURE.
1420 static int
1421 snapshot_raidsystem(uint8_t recursive, uint8_t indent, uint8_t is_snapshot)
1423 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE;
1424 int ret;
1426 ctl_handle = raidcfg_list_head(OBJ_SYSTEM, OBJ_TYPE_CONTROLLER);
1427 while (ctl_handle > 0) {
1428 ret = raidcfg_open_controller(ctl_handle, NULL);
1429 if (ret == 0) {
1430 if (snapshot_ctl(ctl_handle, recursive, indent,
1431 is_snapshot) == FAILURE) {
1432 (void) raidcfg_close_controller(ctl_handle,
1433 NULL);
1436 ctl_handle = raidcfg_list_next(ctl_handle);
1438 return (SUCCESS);
1442 * snapshot_ctl(ctl_handle, recursive, indent, is_snapshot)
1443 * This function prints snapshot of specified controller's configuration,
1444 * and return result as SUCCESS or FAILURE.
1446 static int
1447 snapshot_ctl(raid_obj_handle_t ctl_handle, uint8_t recursive, uint8_t indent,
1448 uint8_t is_snapshot)
1450 raid_obj_handle_t array_handle = INIT_HANDLE_VALUE;
1451 raid_obj_handle_t disk_handle = INIT_HANDLE_VALUE;
1452 raidcfg_controller_t ctl_attr;
1453 uint32_t ctl_tag;
1454 char ctlbuf[256];
1455 int ret;
1457 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
1458 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1459 return (FAILURE);
1462 ctl_tag = ctl_attr.controller_id;
1463 if (is_snapshot == FALSE) {
1464 print_indent(indent);
1465 (void) fprintf(stdout, gettext("Controller: %u\n"), ctl_tag);
1466 } else {
1467 (void) snprintf(ctlbuf, sizeof (ctlbuf), "%u \"%s\"",
1468 ctl_tag, ctl_attr.controller_type);
1469 (void) fprintf(stdout, "%s", ctlbuf);
1471 (void) fprintf(stdout, "\n");
1474 if (recursive == TRUE) {
1475 array_handle = raidcfg_list_head(ctl_handle, OBJ_TYPE_ARRAY);
1476 while (array_handle > 0) {
1477 if (snapshot_array(array_handle,
1478 indent + 1, FALSE, is_snapshot) == FAILURE) {
1479 return (FAILURE);
1482 array_handle = raidcfg_list_next(array_handle);
1485 disk_handle = raidcfg_list_head(ctl_handle, OBJ_TYPE_DISK);
1486 while (disk_handle > 0) {
1487 if (snapshot_disk(ctl_tag, disk_handle,
1488 indent + 1, is_snapshot) == FAILURE) {
1489 return (FAILURE);
1492 disk_handle = raidcfg_list_next(disk_handle);
1495 return (SUCCESS);
1500 * snapshot_array(array_handle, indent, is_sub, is_snapshot)
1501 * This function prints snapshot of specified array's configuration,
1502 * and return result as SUCCESS or FAILURE.
1504 static int
1505 snapshot_array(raid_obj_handle_t array_handle, uint8_t indent, uint8_t is_sub,
1506 uint8_t is_snapshot)
1508 raid_obj_handle_t ctl_handle;
1509 raid_obj_handle_t subarray_handle;
1510 raid_obj_handle_t arraypart_handle;
1511 raid_obj_handle_t task_handle;
1513 raidcfg_controller_t ctl_attr;
1514 raidcfg_array_t array_attr;
1515 raidcfg_arraypart_t arraypart_attr;
1516 raidcfg_task_t task_attr;
1518 char arraybuf[256] = "\0";
1519 char diskbuf[256] = "\0";
1520 char tempbuf[256] = "\0";
1521 int disknum = 0;
1523 uint32_t ctl_tag;
1524 int ret;
1526 ctl_handle = raidcfg_get_container(array_handle);
1527 ret = raidcfg_get_attr(ctl_handle, &ctl_attr);
1528 if (ret < 0) {
1529 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1530 return (FAILURE);
1532 ctl_tag = ctl_attr.controller_id;
1534 /* Print array attribute */
1535 if ((ret = raidcfg_get_attr(array_handle, &array_attr)) < 0) {
1536 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1537 return (FAILURE);
1540 if (is_snapshot == FALSE) {
1541 print_indent(indent);
1542 if (is_sub == FALSE) {
1543 (void) fprintf(stdout, gettext("Volume:"
1544 "c%ut%llud%llu\n"),
1545 ctl_tag, array_attr.tag.idl.target_id,
1546 array_attr.tag.idl.lun);
1547 } else {
1548 (void) fprintf(stdout, gettext("Sub-Volume\n"));
1550 } else {
1551 (void) snprintf(arraybuf, sizeof (arraybuf), "c%ut%llud%llu ",
1552 ctl_tag, array_attr.tag.idl.target_id,
1553 array_attr.tag.idl.lun);
1555 /* Check if array is in sync state */
1556 task_handle = raidcfg_list_head(array_handle, OBJ_TYPE_TASK);
1557 if (task_handle > 0) {
1558 (void) raidcfg_get_attr(task_handle, &task_attr);
1559 if (task_attr.task_func == TASK_FUNC_BUILD) {
1560 array_attr.state = ARRAY_STATE_SYNC;
1562 } else {
1563 subarray_handle = raidcfg_list_head(array_handle,
1564 OBJ_TYPE_ARRAY);
1565 while (subarray_handle > 0) {
1566 task_handle = raidcfg_list_head(subarray_handle,
1567 OBJ_TYPE_TASK);
1568 if (task_handle > 0) {
1569 (void) raidcfg_get_attr(task_handle,
1570 &task_attr);
1571 if (task_attr.task_func ==
1572 TASK_FUNC_BUILD) {
1573 array_attr.state =
1574 ARRAY_STATE_SYNC;
1576 break;
1578 subarray_handle =
1579 raidcfg_list_next(subarray_handle);
1583 /* Print sub array */
1584 subarray_handle = raidcfg_list_head(array_handle,
1585 OBJ_TYPE_ARRAY);
1586 while (subarray_handle > 0) {
1587 /* print subarraypart */
1588 arraypart_handle = raidcfg_list_head(subarray_handle,
1589 OBJ_TYPE_ARRAY_PART);
1590 while (arraypart_handle > 0) {
1591 if ((ret = raidcfg_get_attr(arraypart_handle,
1592 &arraypart_attr)) < 0) {
1593 (void) fprintf(stderr, "%s\n",
1594 raidcfg_errstr(ret));
1595 return (FAILURE);
1598 if (arraypart_attr.tag.cidl.bus == MAX64BIT) {
1599 (void) snprintf(tempbuf,
1600 sizeof (tempbuf),
1601 gettext("N/A"));
1602 } else {
1603 (void) snprintf(tempbuf,
1604 sizeof (tempbuf),
1605 "%llu.%llu.%llu",
1606 arraypart_attr.tag.cidl.bus,
1607 arraypart_attr.tag.cidl.target_id,
1608 arraypart_attr.tag.cidl.lun);
1610 (void) strlcat(diskbuf, tempbuf,
1611 sizeof (diskbuf));
1612 (void) strcat(diskbuf, " ");
1613 disknum++;
1614 arraypart_handle =
1615 raidcfg_list_next(arraypart_handle);
1617 subarray_handle = raidcfg_list_next(subarray_handle);
1620 /* Print arraypart */
1621 arraypart_handle = raidcfg_list_head(array_handle,
1622 OBJ_TYPE_ARRAY_PART);
1623 while (arraypart_handle > 0) {
1624 if ((ret = raidcfg_get_attr(arraypart_handle,
1625 &arraypart_attr)) < 0) {
1626 (void) fprintf(stderr, "%s\n",
1627 raidcfg_errstr(ret));
1628 return (FAILURE);
1631 if (arraypart_attr.tag.cidl.bus == MAX64BIT) {
1632 (void) snprintf(tempbuf, sizeof (tempbuf),
1633 gettext("N/A"));
1634 } else {
1635 (void) snprintf(tempbuf, sizeof (tempbuf),
1636 "%llu.%llu.%llu",
1637 arraypart_attr.tag.cidl.bus,
1638 arraypart_attr.tag.cidl.target_id,
1639 arraypart_attr.tag.cidl.lun);
1641 (void) strlcat(diskbuf, tempbuf, sizeof (diskbuf));
1642 (void) strcat(diskbuf, " ");
1643 disknum++;
1644 arraypart_handle = raidcfg_list_next(arraypart_handle);
1646 (void) snprintf(tempbuf, sizeof (tempbuf), "%u ", disknum);
1647 (void) strlcat(arraybuf, tempbuf, sizeof (arraybuf));
1648 (void) strlcat(arraybuf, diskbuf, sizeof (arraybuf));
1650 switch (array_attr.raid_level) {
1651 case RAID_LEVEL_0:
1652 (void) sprintf(tempbuf, "0");
1653 break;
1654 case RAID_LEVEL_1:
1655 (void) sprintf(tempbuf, "1");
1656 break;
1657 case RAID_LEVEL_1E:
1658 (void) sprintf(tempbuf, "1E");
1659 break;
1660 case RAID_LEVEL_5:
1661 (void) sprintf(tempbuf, "5");
1662 break;
1663 case RAID_LEVEL_10:
1664 (void) sprintf(tempbuf, "10");
1665 break;
1666 case RAID_LEVEL_50:
1667 (void) sprintf(tempbuf, "50");
1668 break;
1669 default:
1670 (void) snprintf(tempbuf, sizeof (tempbuf),
1671 gettext("N/A"));
1672 break;
1674 (void) strlcat(arraybuf, tempbuf, sizeof (arraybuf));
1675 (void) fprintf(stdout, "%s ", arraybuf);
1677 switch (array_attr.state) {
1678 case ARRAY_STATE_OPTIMAL:
1679 (void) fprintf(stdout, gettext("OPTIMAL"));
1680 break;
1681 case ARRAY_STATE_DEGRADED:
1682 (void) fprintf(stdout, gettext("DEGRADED"));
1683 break;
1684 case ARRAY_STATE_FAILED:
1685 (void) fprintf(stdout, gettext("FAILED"));
1686 break;
1687 case ARRAY_STATE_SYNC:
1688 (void) fprintf(stdout, gettext("SYNC"));
1689 break;
1690 case ARRAY_STATE_MISSING:
1691 (void) fprintf(stdout, gettext("MISSING"));
1692 break;
1693 default:
1694 (void) fprintf(stdout, gettext("N/A"));
1695 break;
1697 (void) fprintf(stdout, "\n");
1700 return (SUCCESS);
1704 * snapshot_disk(ctl_tag, disk_handle, indent, is_snapshot)
1705 * This function prints snapshot of specified disk's configuration, and return
1706 * result as SUCCESS or FAILURE.
1708 static int
1709 snapshot_disk(uint32_t ctl_tag, raid_obj_handle_t disk_handle, uint8_t indent,
1710 uint8_t is_snapshot)
1712 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE;
1713 raid_obj_handle_t hsp_handle;
1715 raidcfg_controller_t ctl_attr;
1716 raidcfg_disk_t disk_attr;
1717 char diskbuf[256] = "";
1718 char tempbuf[256] = "";
1720 int ret;
1722 ctl_handle = raidcfg_get_controller(ctl_tag);
1723 ret = raidcfg_get_attr(ctl_handle, &ctl_attr);
1724 if (ret < 0) {
1725 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1726 return (FAILURE);
1729 /* Print attribute of disk */
1730 if ((ret = raidcfg_get_attr(disk_handle, &disk_attr)) < 0) {
1731 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1732 return (FAILURE);
1735 if (is_snapshot == FALSE) {
1736 print_indent(indent);
1738 hsp_handle = raidcfg_list_head(disk_handle, OBJ_TYPE_HSP);
1740 if (disk_attr.tag.cidl.bus == MAX64BIT) {
1741 (void) fprintf(stdout, gettext("Disk: N/A"));
1742 } else {
1743 (void) fprintf(stdout, gettext("Disk: %llu.%llu.%llu"),
1744 disk_attr.tag.cidl.bus,
1745 disk_attr.tag.cidl.target_id,
1746 disk_attr.tag.cidl.lun);
1748 if (hsp_handle > 0) {
1749 (void) fprintf(stdout, "(HSP)");
1751 (void) fprintf(stdout, "\n");
1752 } else {
1753 if (disk_attr.tag.cidl.bus == MAX64BIT) {
1754 (void) fprintf(stdout, gettext("N/A"));
1755 } else {
1756 (void) snprintf(diskbuf, sizeof (diskbuf),
1757 "%llu.%llu.%llu ",
1758 disk_attr.tag.cidl.bus,
1759 disk_attr.tag.cidl.target_id,
1760 disk_attr.tag.cidl.lun);
1762 hsp_handle = raidcfg_list_head(disk_handle, OBJ_TYPE_HSP);
1763 if (hsp_handle > 0) {
1764 (void) snprintf(tempbuf, sizeof (tempbuf),
1765 gettext("HSP"));
1766 } else if (disk_attr.state == DISK_STATE_GOOD) {
1767 (void) snprintf(tempbuf, sizeof (tempbuf),
1768 gettext("GOOD"));
1769 } else if (disk_attr.state == DISK_STATE_FAILED) {
1770 (void) snprintf(tempbuf, sizeof (tempbuf),
1771 gettext("FAILED"));
1772 } else {
1773 (void) snprintf(tempbuf, sizeof (tempbuf),
1774 gettext("N/A"));
1777 (void) strlcat(diskbuf, tempbuf, sizeof (diskbuf));
1778 (void) fprintf(stdout, "%s\n", diskbuf);
1781 return (SUCCESS);
1784 static int
1785 print_ctl_table(raid_obj_handle_t ctl_handle)
1787 raidcfg_controller_t ctl_attr;
1788 char controller[8];
1789 int ret;
1791 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
1792 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1793 return (FAILURE);
1796 (void) fprintf(stdout, gettext("Controller\tType\t\tVersion"));
1797 (void) fprintf(stdout, "\n");
1798 (void) fprintf(stdout, "--------------------------------");
1799 (void) fprintf(stdout, "--------------------------------");
1800 (void) fprintf(stdout, "\n");
1802 (void) snprintf(controller, sizeof (controller), "%u",
1803 ctl_attr.controller_id);
1804 (void) printf("c%s\t\t", controller);
1806 (void) print_ctl_attr(&ctl_attr);
1807 (void) fprintf(stdout, "\n");
1809 return (SUCCESS);
1812 static int
1813 print_array_table(raid_obj_handle_t ctl_handle, raid_obj_handle_t array_handle)
1815 raidcfg_controller_t ctl_attr;
1816 raidcfg_array_t array_attr;
1817 raidcfg_array_t subarray_attr;
1818 raidcfg_arraypart_t arraypart_attr;
1819 raidcfg_task_t task_attr;
1821 raid_obj_handle_t subarray_handle;
1822 raid_obj_handle_t arraypart_handle;
1823 raid_obj_handle_t task_handle;
1825 char array[16];
1826 char arraypart[8];
1827 int ret;
1828 int i;
1830 /* Controller attribute */
1831 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
1832 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1833 return (FAILURE);
1836 /* Array attribute */
1837 if ((ret = raidcfg_get_attr(array_handle, &array_attr)) < 0) {
1838 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1839 return (FAILURE);
1842 /* print header */
1843 (void) fprintf(stdout, gettext("Volume\t\t\tSize\tStripe\tStatus\t"
1844 " Cache\tRAID"));
1845 (void) fprintf(stdout, "\n");
1846 (void) fprintf(stdout, gettext("\tSub\t\t\tSize\t\t\tLevel"));
1847 (void) fprintf(stdout, "\n");
1848 (void) fprintf(stdout, gettext("\t\tDisk\t\t\t\t\t"));
1849 (void) fprintf(stdout, "\n");
1850 (void) fprintf(stdout, "--------------------------------");
1851 (void) fprintf(stdout, "--------------------------------");
1852 (void) fprintf(stdout, "\n");
1854 /* print array */
1855 (void) snprintf(array, sizeof (array), "c%ut%llud%llu",
1856 ctl_attr.controller_id, array_attr.tag.idl.target_id,
1857 array_attr.tag.idl.lun);
1858 (void) fprintf(stdout, "%s\t\t", array);
1859 if (strlen(array) < 8)
1860 (void) fprintf(stdout, "\t");
1863 /* check if array is in sync state */
1864 task_handle = raidcfg_list_head(array_handle, OBJ_TYPE_TASK);
1865 if (task_handle > 0) {
1866 (void) raidcfg_get_attr(task_handle, &task_attr);
1867 if (task_attr.task_func == TASK_FUNC_BUILD) {
1868 array_attr.state = ARRAY_STATE_SYNC;
1870 } else {
1871 subarray_handle = raidcfg_list_head(array_handle,
1872 OBJ_TYPE_ARRAY);
1873 while (subarray_handle > 0) {
1874 task_handle = raidcfg_list_head(subarray_handle,
1875 OBJ_TYPE_TASK);
1876 if (task_handle > 0) {
1877 (void) raidcfg_get_attr(task_handle,
1878 &task_attr);
1879 if (task_attr.task_func == TASK_FUNC_BUILD) {
1880 array_attr.state = ARRAY_STATE_SYNC;
1882 break;
1884 subarray_handle = raidcfg_list_next(subarray_handle);
1888 (void) print_array_attr(&array_attr);
1889 (void) fprintf(stdout, "\n");
1891 /* Print sub array */
1892 i = 0; /* Count sub array number */
1893 subarray_handle = raidcfg_list_head(array_handle, OBJ_TYPE_ARRAY);
1894 while (subarray_handle > 0) {
1895 if ((ret = raidcfg_get_attr(subarray_handle,
1896 &subarray_attr)) < 0) {
1897 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1898 return (FAILURE);
1901 /* Use sub0/sub1 here, not cxtxd0 for subarray */
1902 (void) snprintf(array, sizeof (array), "sub%u", i++);
1903 (void) fprintf(stdout, "\t%s\t\t", array);
1905 /* Check if array is in sync */
1906 task_handle = raidcfg_list_head(subarray_handle, OBJ_TYPE_TASK);
1907 if (task_handle > 0) {
1908 (void) raidcfg_get_attr(task_handle, &task_attr);
1909 if (task_attr.task_func == TASK_FUNC_BUILD) {
1910 subarray_attr.state = ARRAY_STATE_SYNC;
1914 (void) print_array_attr(&subarray_attr);
1915 (void) fprintf(stdout, "\n");
1917 /* Print subarraypart */
1918 arraypart_handle = raidcfg_list_head(subarray_handle,
1919 OBJ_TYPE_ARRAY_PART);
1920 while (arraypart_handle > 0) {
1921 if ((ret = raidcfg_get_attr(arraypart_handle,
1922 &arraypart_attr)) < 0) {
1923 (void) fprintf(stderr, "%s\n",
1924 raidcfg_errstr(ret));
1925 return (FAILURE);
1928 if (arraypart_attr.tag.cidl.bus == MAX64BIT) {
1929 (void) snprintf(arraypart, sizeof (arraypart),
1930 gettext("N/A"));
1931 } else {
1932 (void) snprintf(arraypart, sizeof (arraypart),
1933 "%llu.%llu.%llu",
1934 arraypart_attr.tag.cidl.bus,
1935 arraypart_attr.tag.cidl.target_id,
1936 arraypart_attr.tag.cidl.lun);
1939 (void) fprintf(stdout, "\t\t%s\t", arraypart);
1940 (void) print_arraypart_attr(&arraypart_attr);
1941 (void) fprintf(stdout, "\n");
1942 arraypart_handle = raidcfg_list_next(arraypart_handle);
1944 subarray_handle = raidcfg_list_next(subarray_handle);
1947 /* Print arraypart */
1948 arraypart_handle = raidcfg_list_head(array_handle,
1949 OBJ_TYPE_ARRAY_PART);
1950 while (arraypart_handle > 0) {
1951 if ((ret = raidcfg_get_attr(arraypart_handle,
1952 &arraypart_attr)) < 0) {
1953 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1954 return (FAILURE);
1957 if (arraypart_attr.tag.cidl.bus == MAX64BIT) {
1958 (void) snprintf(arraypart, sizeof (arraypart),
1959 gettext("N/A"));
1960 } else {
1961 (void) snprintf(arraypart, sizeof (arraypart),
1962 "%llu.%llu.%llu",
1963 arraypart_attr.tag.cidl.bus,
1964 arraypart_attr.tag.cidl.target_id,
1965 arraypart_attr.tag.cidl.lun);
1968 (void) fprintf(stdout, "\t\t%s\t", arraypart);
1969 (void) print_arraypart_attr(&arraypart_attr);
1970 (void) fprintf(stdout, "\n");
1971 arraypart_handle = raidcfg_list_next(arraypart_handle);
1974 return (SUCCESS);
1977 static int
1978 print_disk_table(raid_obj_handle_t ctl_handle, raid_obj_handle_t disk_handle)
1980 raidcfg_controller_t ctl_attr;
1981 raidcfg_disk_t disk_attr;
1982 raidcfg_prop_t *prop_attr, *prop_attr2;
1983 raid_obj_handle_t prop_handle;
1984 char disk[8];
1985 int ret;
1987 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
1988 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1989 return (FAILURE);
1992 if ((ret = raidcfg_get_attr(disk_handle, &disk_attr)) < 0) {
1993 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1994 return (FAILURE);
1997 /* Print header */
1998 (void) fprintf(stdout, gettext("Disk\tVendor Product "
1999 "Firmware\tCapacity\tStatus\tHSP"));
2000 (void) fprintf(stdout, "\n");
2001 (void) fprintf(stdout, "--------------------------------------");
2002 (void) fprintf(stdout, "--------------------------------------");
2003 (void) fprintf(stdout, "\n");
2006 (void) snprintf(disk, sizeof (disk), "%llu.%llu.%llu",
2007 disk_attr.tag.cidl.bus,
2008 disk_attr.tag.cidl.target_id,
2009 disk_attr.tag.cidl.lun);
2011 (void) fprintf(stdout, "%s\t", disk);
2013 (void) print_disk_attr(ctl_handle, disk_handle, &disk_attr);
2015 prop_attr = calloc(1, sizeof (raidcfg_prop_t));
2016 if (prop_attr == NULL) {
2017 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ERR_NOMEM));
2018 return (FAILURE);
2021 prop_handle = raidcfg_list_head(disk_handle, OBJ_TYPE_PROP);
2022 if (prop_handle == 0) {
2023 free(prop_attr);
2024 return (SUCCESS);
2027 do {
2028 prop_attr->prop_size = 0;
2029 if ((ret = raidcfg_get_attr(prop_handle, prop_attr)) < 0) {
2030 free(prop_attr);
2031 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
2032 return (FAILURE);
2034 if (prop_attr->prop_type == PROP_GUID)
2035 break;
2036 } while (prop_handle != 0);
2038 prop_attr2 = realloc(prop_attr,
2039 sizeof (raidcfg_prop_t) + prop_attr->prop_size);
2040 free(prop_attr);
2041 if (prop_attr2 == NULL) {
2042 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ERR_NOMEM));
2043 return (FAILURE);
2046 if ((ret = raidcfg_get_attr(prop_handle, prop_attr2)) < 0) {
2047 free(prop_attr2);
2048 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
2049 return (FAILURE);
2052 (void) fprintf(stdout, "GUID:%s\n", prop_attr2->prop);
2054 free(prop_attr2);
2055 return (SUCCESS);
2059 * print_ctl_attr(attrp)
2060 * This function prints attribute of specified controller, and return
2061 * result as SUCCESS or FAILURE.
2063 static int
2064 print_ctl_attr(raidcfg_controller_t *attrp)
2066 char type[CONTROLLER_TYPE_LEN];
2067 char version[CONTROLLER_FW_LEN];
2069 if (attrp == NULL) {
2070 return (FAILURE);
2073 (void) snprintf(type, sizeof (type), "%s", attrp->controller_type);
2074 (void) fprintf(stdout, "%-16s", type);
2076 (void) snprintf(version, sizeof (version), "%s", attrp->fw_version);
2077 (void) fprintf(stdout, "%s", version);
2079 return (SUCCESS);
2083 * print_array_attr(attrp)
2084 * This function prints attribute of specified array, and return
2085 * result as SUCCESS or FAILURE.
2087 static int
2088 print_array_attr(raidcfg_array_t *attrp)
2090 char capacity[8];
2091 char stripe_size[8];
2092 char raid_level[8];
2094 if (attrp == NULL) {
2095 return (FAILURE);
2098 if (attrp->capacity != MAX64BIT) {
2099 if (size_to_string(attrp->capacity, capacity, 8) != SUCCESS) {
2100 return (FAILURE);
2102 (void) printf("%s\t", capacity);
2103 } else {
2104 (void) printf(gettext("N/A\t"));
2107 if (attrp->stripe_size != MAX32BIT) {
2108 (void) snprintf(stripe_size, sizeof (stripe_size), "%uK",
2109 attrp->stripe_size / 1024);
2110 (void) printf("%s\t", stripe_size);
2111 } else {
2112 (void) printf(gettext("N/A\t"));
2115 if (attrp->state & ARRAY_STATE_INACTIVATE)
2116 (void) printf("%-8s", gettext("INACTIVE"));
2117 else {
2118 switch (attrp->state) {
2119 case ARRAY_STATE_OPTIMAL:
2120 (void) printf("%-8s", gettext("OPTIMAL"));
2121 break;
2122 case ARRAY_STATE_DEGRADED:
2123 (void) printf("%-8s", gettext("DEGRADED"));
2124 break;
2125 case ARRAY_STATE_FAILED:
2126 (void) printf("%-8s", gettext("FAILED"));
2127 break;
2128 case ARRAY_STATE_SYNC:
2129 (void) printf("%-8s", gettext("SYNC"));
2130 break;
2131 case ARRAY_STATE_MISSING:
2132 (void) printf("%-8s", gettext("MISSING"));
2133 break;
2134 default:
2135 (void) printf("%-8s", gettext("N/A"));
2136 break;
2139 (void) printf(" ");
2141 if (attrp->write_policy == CACHE_WR_OFF) {
2142 (void) printf(gettext("OFF"));
2143 } else if (attrp->write_policy == CACHE_WR_ON) {
2144 (void) printf(gettext("ON"));
2145 } else {
2146 (void) printf(gettext("N/A"));
2148 (void) printf("\t");
2150 switch (attrp->raid_level) {
2151 case RAID_LEVEL_0:
2152 (void) sprintf(raid_level, "RAID0");
2153 break;
2154 case RAID_LEVEL_1:
2155 (void) sprintf(raid_level, "RAID1");
2156 break;
2157 case RAID_LEVEL_1E:
2158 (void) sprintf(raid_level, "RAID1E");
2159 break;
2160 case RAID_LEVEL_5:
2161 (void) sprintf(raid_level, "RAID5");
2162 break;
2163 case RAID_LEVEL_10:
2164 (void) sprintf(raid_level, "RAID10");
2165 break;
2166 case RAID_LEVEL_50:
2167 (void) sprintf(raid_level, "RAID50");
2168 break;
2169 default:
2170 (void) snprintf(raid_level, sizeof (raid_level),
2171 gettext("N/A"));
2172 break;
2174 (void) printf("%s", raid_level);
2176 return (SUCCESS);
2180 * print_arraypart_attr(attrp)
2181 * This function print attribute of specified arraypart, and return
2182 * result as SUCCESS or FAILURE.
2184 static int
2185 print_arraypart_attr(raidcfg_arraypart_t *attrp)
2187 char size[8];
2189 if (attrp == NULL) {
2190 return (FAILURE);
2193 if (attrp->size != MAX64BIT) {
2194 if (size_to_string(attrp->size, size, 8) != SUCCESS) {
2195 return (FAILURE);
2197 (void) printf("%s\t", size);
2198 } else {
2199 (void) printf(gettext("N/A\t"));
2202 (void) printf("\t");
2204 if (attrp->state == DISK_STATE_GOOD) {
2205 (void) printf(gettext("GOOD"));
2206 } else if (attrp->state == DISK_STATE_FAILED) {
2207 (void) printf(gettext("FAILED"));
2208 } else {
2209 (void) printf(gettext("N/A"));
2211 (void) printf("\t");
2213 return (SUCCESS);
2217 * print_disk_attr(ctl_handle, disk_handle, attrp)
2218 * This function prints attribute of specified disk, and return
2219 * result as SUCCESS or FAILURE.
2221 static int
2222 print_disk_attr(raid_obj_handle_t ctl_handle, raid_obj_handle_t disk_handle,
2223 raidcfg_disk_t *attrp)
2225 char vendor[DISK_VENDER_LEN + 1];
2226 char product[DISK_PRODUCT_LEN + 1];
2227 char revision[DISK_REV_LEN + 1];
2228 char capacity[16];
2229 char hsp[16];
2231 raid_obj_handle_t hsp_handle;
2232 raidcfg_hsp_t hsp_attr;
2233 raidcfg_controller_t ctl_attr;
2234 int ret;
2235 char is_indent;
2237 if (attrp == NULL) {
2238 return (FAILURE);
2241 (void) memccpy(vendor, attrp->vendorid, '\0', DISK_VENDER_LEN);
2242 vendor[DISK_VENDER_LEN] = '\0';
2243 (void) printf("%-9s", vendor);
2245 (void) memccpy(product, attrp->productid, '\0', DISK_PRODUCT_LEN);
2246 product[DISK_PRODUCT_LEN] = '\0';
2247 (void) printf("%-17s", product);
2249 (void) memccpy(revision, attrp->revision, '\0', DISK_REV_LEN);
2250 revision[DISK_REV_LEN] = '\0';
2251 (void) printf("%s\t\t", revision);
2253 if (attrp->capacity != MAX64BIT) {
2254 if (size_to_string(attrp->capacity, capacity, 16) != SUCCESS) {
2255 return (FAILURE);
2257 (void) printf("%s\t\t", capacity);
2258 } else {
2259 (void) printf(gettext("N/A"));
2262 if (attrp->state == DISK_STATE_GOOD) {
2263 (void) printf(gettext("GOOD"));
2264 } else if (attrp->state == DISK_STATE_FAILED) {
2265 (void) printf(gettext("FAILED"));
2266 } else {
2267 (void) printf(gettext("N/A"));
2269 (void) printf("\t");
2271 /* Controller attribute */
2272 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
2273 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
2274 return (FAILURE);
2277 hsp_handle = raidcfg_list_head(disk_handle, OBJ_TYPE_HSP);
2278 if (hsp_handle == 0) {
2279 (void) printf(gettext("N/A\n"));
2280 } else {
2281 is_indent = FALSE;
2282 while (hsp_handle > 0) {
2283 if ((ret = raidcfg_get_attr(hsp_handle,
2284 &hsp_attr)) < 0) {
2285 (void) fprintf(stderr, "%s\n",
2286 raidcfg_errstr(ret));
2287 return (FAILURE);
2290 if (is_indent == TRUE) {
2291 (void) printf("\t\t\t\t\t\t\t");
2292 } else {
2293 is_indent = TRUE;
2296 if (hsp_attr.type == HSP_TYPE_LOCAL) {
2297 (void) snprintf(hsp, sizeof (hsp),
2298 "c%ut%llud%llu",
2299 ctl_attr.controller_id,
2300 hsp_attr.tag.idl.target_id,
2301 hsp_attr.tag.idl.lun);
2302 (void) printf("%s\n", hsp);
2303 } else if (hsp_attr.type == HSP_TYPE_GLOBAL) {
2304 (void) printf(gettext("Global\n"));
2305 } else {
2306 return (FAILURE);
2309 hsp_handle = raidcfg_list_next(hsp_handle);
2312 return (SUCCESS);
2317 * print_indent(indent)
2318 * This function prints specified number of tab characters. It's used to
2319 * format layout.
2321 static void
2322 print_indent(uint8_t indent)
2324 uint32_t i;
2325 for (i = 0; i < indent; i++) {
2326 (void) fprintf(stdout, "\t");
2331 * get_disk_handle_cidl(ctl_tag, disks_argp, comps_num, handlespp)
2332 * This function parses the string of disk argument, and gets the disks tag
2333 * and separators from the string. Then it translates the tag to handle, and
2334 * stores handles and separators to new buffer pointed by parameter handlespp.
2335 * The format of disk_arg must be C:ID:L, for example, it is 0.1.0. The first
2336 * "0" is channel number, and the second "1" is target number, and the third
2337 * "0" is LUN number. The disk tags are separated by comma and parenthesis.
2338 * Function returns SUCCESS or FAILURE.
2340 static int
2341 get_disk_handle_cidl(uint32_t ctl_tag, char *disks_argp, int *comps_nump,
2342 raid_obj_handle_t **handlespp)
2344 int len = 0;
2345 int i = 0, j = 0;
2346 char *p, *t;
2347 char *delimit = " ";
2348 char *disks_str;
2349 disk_tag_t disk_tag;
2351 if (disks_argp == NULL || comps_nump == NULL) {
2352 return (FAILURE);
2355 p = disks_argp;
2356 len = strlen(disks_argp);
2358 if ((disks_str = (char *)malloc(3 * len + 4)) == NULL) {
2359 return (FAILURE);
2362 /* Insert whitespace between disk tags, '(' , and ')' */
2363 disks_str[j ++] = '(';
2364 disks_str[j ++] = ' ';
2366 while (p[i] != '\0') {
2367 if (p[i] == ')' || p[i] == '(') {
2368 disks_str[j ++] = ' ';
2369 disks_str[j ++] = p[i];
2370 disks_str[j ++] = ' ';
2371 } else
2372 disks_str[j ++] = p[i];
2373 i ++;
2375 disks_str[j ++] = ' ';
2376 disks_str[j ++] = ')';
2377 disks_str[j] = '\0';
2379 len = strlen(disks_str) + 1;
2381 if ((t = (char *)malloc(len)) == NULL) {
2382 return (FAILURE);
2384 (void) memcpy(t, disks_str, len);
2385 p = strtok(t, delimit);
2386 while (p != NULL) {
2387 (*comps_nump)++;
2388 p = strtok(NULL, delimit);
2390 free(t);
2392 *handlespp = calloc(*comps_nump, sizeof (raid_obj_handle_t));
2393 if (*handlespp == NULL) {
2394 return (FAILURE);
2397 for (i = 0; i < *comps_nump; i++)
2398 (*handlespp)[i] = INIT_HANDLE_VALUE;
2400 i = 0;
2401 p = strtok(disks_str, delimit);
2402 while (p != NULL) {
2403 if (*p == '(') {
2404 (*handlespp)[i] = OBJ_SEPARATOR_BEGIN;
2405 } else if (*p == ')') {
2406 (*handlespp)[i] = OBJ_SEPARATOR_END;
2407 } else {
2408 if (get_disk_tag_cidl(p, &disk_tag) != SUCCESS) {
2409 free(*handlespp);
2410 free(disks_str);
2411 return (INVALID_ARG);
2413 (*handlespp)[i] =
2414 raidcfg_get_disk(raidcfg_get_controller(ctl_tag),
2415 disk_tag);
2416 if ((*handlespp)[i] <= 0) {
2417 (void) fprintf(stderr, "%s\n",
2418 raidcfg_errstr((*handlespp)[i]));
2419 free(*handlespp);
2420 free(disks_str);
2421 return (FAILURE);
2424 p = strtok(NULL, delimit);
2425 i++;
2428 free(disks_str);
2429 return (SUCCESS);
2433 * get_disk_handle_ctd(disks_num, disks_argpp, ctl_tagp, disks_handlep)
2434 * This function parses string of single disk with "ctd" format, for example,
2435 * c0t0d0, and translates it to controller tag and disk tag.
2436 * Then it calls lib api and get disk handle. The controller tag and disk
2437 * handle are both returned by out parameters.
2438 * The return value is SUCCESS or FAILURE.
2440 static int
2441 get_disk_handle_ctd(int disks_num, char **disks_argpp, uint32_t *ctl_tagp,
2442 raid_obj_handle_t *disks_handlep)
2444 raid_obj_handle_t ctl_handle;
2445 disk_tag_t disk_tag;
2446 uint32_t ctl_id;
2447 int i;
2448 int ret;
2450 if (disks_handlep == NULL) {
2451 return (FAILURE);
2454 for (i = 0; i < disks_num; i++) {
2455 if (get_disk_tag_ctd(disks_argpp[i], &disk_tag, &ctl_id) !=
2456 SUCCESS) {
2457 return (INVALID_ARG);
2460 *ctl_tagp = ctl_id;
2462 if (i == 0) {
2463 ctl_handle = raidcfg_get_controller(*ctl_tagp);
2464 if (ctl_handle <= 0) {
2465 (void) fprintf(stderr, "%s\n",
2466 raidcfg_errstr(ctl_handle));
2467 return (FAILURE);
2469 ret = raidcfg_open_controller(ctl_handle, NULL);
2470 if (ret < 0) {
2471 (void) fprintf(stderr, "%s\n",
2472 raidcfg_errstr(ret));
2473 return (FAILURE);
2477 if ((disks_handlep[i] =
2478 raidcfg_get_disk(ctl_handle, disk_tag)) < 0) {
2479 (void) fprintf(stderr, "%s\n",
2480 raidcfg_errstr(disks_handlep[i]));
2481 (void) raidcfg_close_controller(ctl_handle, NULL);
2482 return (FAILURE);
2486 return (SUCCESS);
2490 * get_ctl_tag(argp)
2491 * This function translates controller string to tag. The return value is
2492 * SUCCESS if the string has legal format and is parsed successfully,
2493 * or FAILURE if it fails.
2495 static int
2496 get_ctl_tag(char *argp, uint32_t *ctl_tagp)
2498 if (argp == NULL || is_fully_numeric(argp) == FALSE ||
2499 ctl_tagp == NULL) {
2500 return (FAILURE);
2502 *ctl_tagp = (atoi(argp));
2503 return (SUCCESS);
2507 * get_array_tag(argp, ctl_tagp, array_tagp)
2508 * This function parses array string to get array tag and controller tag.
2509 * The return value is SUCCESS if the string has legal format, or
2510 * FAILURE if it fails.
2512 static int
2513 get_array_tag(char *argp, uint32_t *ctl_tagp, array_tag_t *array_tagp)
2515 char *t = NULL;
2516 char *cp = NULL;
2517 char *tp = NULL;
2518 char *dp = NULL;
2520 uint32_t value_c = MAX32BIT;
2521 uint32_t value_t = MAX32BIT;
2522 uint32_t value_d = MAX32BIT;
2524 int len = 0;
2526 if (argp == NULL || (len = strlen(argp)) == 0 ||
2527 array_tagp == NULL) {
2528 return (FAILURE);
2531 t = (char *)malloc(len + 1);
2532 if (t == NULL) {
2533 return (FAILURE);
2536 (void) memcpy(t, argp, len + 1);
2538 /* Now remmber to release t memory if exception occurs */
2539 if (((dp = strchr(t, 'd')) == NULL) ||
2540 ((tp = strchr(t, 't')) == NULL) ||
2541 ((cp = strchr(t, 'c')) == NULL)) {
2542 free(t);
2543 return (FAILURE);
2545 cp = t;
2547 *dp = '\0';
2548 dp++;
2549 *tp = '\0';
2550 tp++;
2551 cp++;
2553 if (is_fully_numeric(dp) == FALSE ||
2554 is_fully_numeric(tp) == FALSE ||
2555 is_fully_numeric(cp) == FALSE) {
2556 free(t);
2557 return (FAILURE);
2560 value_c = atoi(cp);
2561 value_t = atoi(tp);
2562 value_d = atoi(dp);
2564 array_tagp->idl.target_id = value_t;
2565 array_tagp->idl.lun = value_d;
2567 if (ctl_tagp != NULL) {
2568 *ctl_tagp = value_c;
2571 free(t);
2572 return (SUCCESS);
2576 * get_disk_tag_ctd(argp, disk_tagp)
2577 * This function parses disk string of ctd format, and translates it to
2578 * disk tag and controller tag. The tags is returned by out parameters.
2579 * The return value is SUCCESS if the string has legal format, or FAILURE
2580 * if it fails.
2582 static int
2583 get_disk_tag_ctd(char *argp, disk_tag_t *disk_tagp, uint32_t *ctl_tag)
2585 char *t = NULL;
2586 char *cp = NULL;
2587 char *tp = NULL;
2588 char *dp = NULL;
2590 uint32_t value_c = MAX32BIT;
2591 uint32_t value_t = MAX32BIT;
2592 uint32_t value_d = MAX32BIT;
2594 int len = 0;
2596 if (argp == NULL || (len = strlen(argp)) == 0 ||
2597 disk_tagp == NULL) {
2598 return (FAILURE);
2601 t = (char *)malloc(len + 1);
2602 if (t == NULL) {
2603 return (FAILURE);
2606 (void) memcpy(t, argp, len + 1);
2608 /* Now remmber to release t memory if exception occurs */
2609 if (((dp = strchr(t, 'd')) == NULL) ||
2610 ((tp = strchr(t, 't')) == NULL) ||
2611 ((cp = strchr(t, 'c')) == NULL)) {
2612 free(t);
2613 return (FAILURE);
2615 cp = t;
2617 *dp = '\0';
2618 dp++;
2619 *tp = '\0';
2620 tp++;
2621 cp++;
2623 if (is_fully_numeric(dp) == FALSE ||
2624 is_fully_numeric(tp) == FALSE ||
2625 is_fully_numeric(cp) == FALSE) {
2626 free(t);
2627 return (FAILURE);
2630 value_c = atoi(cp);
2631 value_t = atoi(tp);
2632 value_d = atoi(dp);
2634 disk_tagp->cidl.bus = 0;
2635 disk_tagp->cidl.target_id = value_t;
2636 disk_tagp->cidl.lun = value_d;
2637 *ctl_tag = value_c;
2639 free(t);
2640 return (SUCCESS);
2644 * get_disk_tag_cidl(argp, disk_tagp)
2645 * This function parses disk string of cidl format and translates it to tag.
2646 * The return value is disk tag if the string has legal format, or FAILURE
2647 * if it fails.
2649 static int
2650 get_disk_tag_cidl(char *argp, disk_tag_t *disk_tagp)
2652 int len = 0;
2653 char *p = NULL;
2654 char *t = NULL;
2655 char *dot1p = NULL;
2656 char *dot2p = NULL;
2658 if (argp == NULL || (len = strlen(argp)) == 0) {
2659 return (FAILURE);
2662 if (disk_tagp == NULL) {
2663 return (FAILURE);
2666 t = (char *)malloc(len + 1);
2667 if (t == NULL) {
2668 return (FAILURE);
2671 (void) memcpy(t, argp, len + 1);
2672 p = t;
2674 dot2p = strrchr(p, '.');
2675 if (dot2p == NULL) {
2676 free(t);
2677 return (FAILURE);
2679 *dot2p = '\0';
2680 dot2p++;
2682 dot1p = strrchr(p, '.');
2683 if (dot1p == NULL) {
2684 free(t);
2685 return (FAILURE);
2687 *dot1p = '\0';
2688 dot1p++;
2690 /* Assert only 2 dots in this string */
2691 if (strrchr(p, '.') != NULL) {
2692 free(t);
2693 return (FAILURE);
2696 while (*p == ' ')
2697 p++;
2699 if (is_fully_numeric(p) == FALSE ||
2700 is_fully_numeric(dot1p) == FALSE ||
2701 is_fully_numeric(dot2p) == FALSE) {
2702 free(t);
2703 return (FAILURE);
2706 disk_tagp->cidl.bus = atoi(p);
2707 disk_tagp->cidl.target_id = atoi(dot1p);
2708 disk_tagp->cidl.lun = atoi(dot2p);
2710 free(t);
2711 return (SUCCESS);
2715 * calc_size(sizep, valp)
2716 * This function calculates the value represented by string sizep.
2717 * The string sizep can be decomposed into three parts: an initial,
2718 * possibly empty, sequence of white-space characters; a subject digital
2719 * sequence interpreted as an integer with unit k/K/m/M/g/G/t/T; and a
2720 * final string of one or more unrecognized characters or white-sapce
2721 * characters, including the terminating null. If unrecognized character
2722 * exists or overflow happens, the conversion must fail and return
2723 * INVALID_ARG. If the conversion is performed successfully, result will
2724 * be saved into valp and function returns SUCCESS. It returns FAILURE
2725 * when memory allocation fails.
2727 static int
2728 calc_size(char *sizep, uint64_t *valp)
2730 int len;
2731 uint64_t size;
2732 uint64_t unit;
2733 char *t = NULL;
2734 char *tailp = NULL;
2736 if (sizep == NULL || valp == NULL) {
2737 return (INVALID_ARG);
2740 if (is_fully_numeric(sizep) == TRUE) {
2741 *valp = atoi(sizep);
2742 return (SUCCESS);
2745 len = strlen(sizep);
2746 if (len == 0) {
2747 return (INVALID_ARG);
2750 t = (char *)malloc(len + 1);
2751 if (t == NULL) {
2752 return (FAILURE);
2755 (void) memcpy(t, sizep, len + 1);
2757 switch (*(t + len - 1)) {
2758 case 'k':
2759 case 'K':
2760 unit = 1024ull;
2761 errno = 0;
2762 size = strtoll(t, &tailp, 0);
2763 break;
2764 case 'm':
2765 case 'M':
2766 unit = 1024ull * 1024ull;
2767 errno = 0;
2768 size = strtoll(t, &tailp, 0);
2769 break;
2770 case 'g':
2771 case 'G':
2772 unit = 1024ull * 1024ull * 1024ull;
2773 errno = 0;
2774 size = strtoll(t, &tailp, 0);
2775 break;
2776 case 't':
2777 case 'T':
2778 unit = 1024ull * 1024ull * 1024ull * 1024ull;
2779 errno = 0;
2780 size = strtoll(t, &tailp, 0);
2781 break;
2782 default:
2783 /* The unit must be kilobyte at least. */
2784 free(t);
2785 return (INVALID_ARG);
2788 *(t + len - 1) = '\0';
2789 if (is_fully_numeric(t) != TRUE) {
2790 free(t);
2791 return (INVALID_ARG);
2794 errno = 0;
2795 size = strtoll(t, &tailp, 0);
2797 /* Check overflow condition */
2798 if (errno == ERANGE || (size > (MAX64BIT / unit))) {
2799 free(t);
2800 return (INVALID_ARG);
2803 *valp = size * unit;
2804 free(t);
2805 return (SUCCESS);
2809 * is_fully_numeric(str)
2810 * This function checks if the string are legal numeric string. The beginning
2811 * or ending characters can be white spaces.
2812 * Return value is TRUE if the string are legal numeric string, or FALSE
2813 * otherwise.
2815 static int
2816 is_fully_numeric(char *strp)
2818 uint32_t len;
2819 uint32_t i;
2821 if (strp == NULL) {
2822 return (FALSE);
2825 len = strlen(strp);
2826 if (len == 0) {
2827 return (FALSE);
2830 /* Skip whitespace characters */
2831 for (i = 0; i < len; i++) {
2832 if (strp[i] != ' ') {
2833 break;
2837 /* if strp points all space characters */
2838 if (i == len) {
2839 return (FALSE);
2842 /* Check the digitals in string */
2843 for (; i < len; i++) {
2844 if (!isdigit(strp[i])) {
2845 break;
2849 /* Check the ending string */
2850 for (; i < len; i++) {
2851 if (strp[i] != ' ') {
2852 return (FALSE);
2856 return (TRUE);
2859 static int
2860 yes(void)
2862 int i, b;
2863 char ans[SCHAR_MAX + 1];
2865 for (i = 0; ; i++) {
2866 b = getchar();
2867 if (b == '\n' || b == '\0' || b == EOF) {
2868 ans[i] = 0;
2869 break;
2871 if (i < SCHAR_MAX) {
2872 ans[i] = b;
2875 if (i >= SCHAR_MAX) {
2876 i = SCHAR_MAX;
2877 ans[SCHAR_MAX] = 0;
2880 return (rpmatch(ans));
2884 * Function: int rpmatch(char *)
2886 * Description:
2888 * Internationalized get yes / no answer.
2890 * Inputs:
2891 * s -> Pointer to answer to compare against.
2893 * Returns:
2894 * TRUE -> Answer was affirmative
2895 * FALSE -> Answer was negative
2898 static int
2899 rpmatch(char *s)
2901 int status;
2903 /* match yesexpr */
2904 status = regexec(&re, s, (size_t)0, NULL, 0);
2905 if (status != 0) {
2906 return (FALSE);
2908 return (TRUE);
2911 static int
2912 size_to_string(uint64_t size, char *string, int len)
2914 int i = 0;
2915 uint32_t remainder;
2916 char unit[][2] = {" ", "K", "M", "G", "T"};
2918 if (string == NULL) {
2919 return (FAILURE);
2921 while (size > 1023) {
2922 remainder = size % 1024;
2923 size /= 1024;
2924 i++;
2927 if (i > 4) {
2928 return (FAILURE);
2931 remainder /= 103;
2932 if (remainder == 0) {
2933 (void) snprintf(string, len, "%llu", size);
2934 } else {
2935 (void) snprintf(string, len, "%llu.%1u", size,
2936 remainder);
2939 /* make sure there is one byte for unit */
2940 if ((strlen(string) + 1) >= len) {
2941 return (FAILURE);
2943 (void) strlcat(string, unit[i], len);
2945 return (SUCCESS);
2949 * Only one raidctl is running at one time.
2951 static int
2952 enter_raidctl_lock(int *fd)
2954 int fd0 = -1;
2955 struct flock lock;
2957 fd0 = open(RAIDCTL_LOCKF, O_CREAT|O_WRONLY, 0600);
2958 if (fd0 < 0) {
2959 if (errno == EACCES) {
2960 (void) fprintf(stderr,
2961 gettext("raidctl:must be root to run raidctl"
2962 ": %s\n"), strerror(errno));
2963 } else {
2964 (void) fprintf(stderr,
2965 gettext("raidctl:failed to open lockfile"
2966 " '"RAIDCTL_LOCKF"': %s\n"), strerror(errno));
2968 return (FAILURE);
2971 *fd = fd0;
2972 lock.l_type = F_WRLCK;
2973 lock.l_whence = SEEK_SET;
2974 lock.l_start = 0;
2975 lock.l_len = 0;
2977 if ((fcntl(fd0, F_SETLK, &lock) == -1) &&
2978 (errno == EAGAIN || errno == EDEADLK)) {
2979 if (fcntl(fd0, F_GETLK, &lock) == -1) {
2980 (void) fprintf(stderr,
2981 gettext("raidctl:enter_filelock error\n"));
2982 return (FAILURE);
2984 (void) fprintf(stderr, gettext("raidctl:"
2985 "enter_filelock:filelock is owned "
2986 "by 'process %d'\n"), lock.l_pid);
2987 return (FAILURE);
2990 return (SUCCESS);
2993 static void
2994 exit_raidctl_lock(int fd)
2996 struct flock lock;
2998 lock.l_type = F_UNLCK;
2999 lock.l_whence = SEEK_SET;
3000 lock.l_start = 0;
3001 lock.l_len = 0;
3002 if (fcntl(fd, F_SETLK, &lock) == -1) {
3003 (void) fprintf(stderr, gettext("raidctl: failed to"
3004 " exit_filelock: %s\n"),
3005 strerror(errno));
3007 (void) close(fd);