9621 Make createtxg and guid properties public
[unleashed.git] / usr / src / cmd / raidctl / raidctl.c
blobc17df409326390e8070f4864e6ab97aedf05cff3
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 *yesstr = NULL;
120 static char *nostr = NULL;
121 static char *yesexpr = NULL;
123 static char *default_yesexpr = "^[yY]";
124 static char *default_yesstr = "yes";
125 static char *default_nostr = "no";
127 static regex_t re;
129 #define SET_DEFAULT_STRS \
130 regfree(&re); \
131 free(yesexpr); \
132 free(yesstr); \
133 free(nostr); \
134 yesexpr = default_yesexpr; \
135 yesstr = default_yesstr; \
136 nostr = default_nostr;
138 #define FREE_STRS \
139 if (yesexpr != default_yesexpr) \
140 free(yesexpr); \
141 if (yesstr != default_yesstr) \
142 free(yesstr); \
143 if (nostr != default_nostr) \
144 free(nostr);
146 /* program name */
147 static char *prog_namep;
151 * Functions declaration
153 static void helpinfo(char *prog_namep);
154 static int do_create_cidl(char *raid_levelp, char *capacityp, char *disk_argp,
155 char *stripe_sizep, uint32_t f_flag, char **argv, uint32_t optind);
156 static int do_create_ctd(char *raid_levelp, char **disks_argpp,
157 uint32_t disks_num, uint32_t argindex, uint32_t f_flag);
158 static int do_list(char *disk_argp, char **argv, uint32_t optind,
159 uint8_t is_snapshot);
160 static int do_delete(uint32_t f_flag, char **argv, uint32_t optind);
161 static int do_flash(uint8_t f_flag, char *filep, char **ctls_argpp,
162 uint32_t index, uint32_t ctl_num);
163 static int do_set_hsp(char *a_argp, char *disk_argp, char **argv,
164 uint32_t optind);
165 static int do_set_array_attr(uint32_t f_flag, char *p_argp, char **argv,
166 uint32_t optind);
167 static int snapshot_raidsystem(uint8_t recursive, uint8_t indent,
168 uint8_t is_snapshot);
169 static int snapshot_ctl(raid_obj_handle_t ctl_handle, uint8_t recursive,
170 uint8_t indent, uint8_t is_snapshot);
171 static int snapshot_array(raid_obj_handle_t array_handle,
172 uint8_t indent, uint8_t is_sub, uint8_t is_snapshot);
173 static int snapshot_disk(uint32_t ctl_tag, raid_obj_handle_t disk_handle,
174 uint8_t indent, uint8_t is_snapshot);
175 static int print_ctl_table(raid_obj_handle_t ctl_handle);
176 static int print_array_table(raid_obj_handle_t ctl_handle,
177 raid_obj_handle_t array_handle);
178 static int print_disk_table(raid_obj_handle_t ctl_handle,
179 raid_obj_handle_t disk_handle);
180 static int print_ctl_attr(raidcfg_controller_t *attrp);
181 static int print_array_attr(raidcfg_array_t *attrp);
182 static int print_arraypart_attr(raidcfg_arraypart_t *attrp);
183 static int print_disk_attr(raid_obj_handle_t ctl_handle,
184 raid_obj_handle_t disk_handle, raidcfg_disk_t *attrp);
185 static void print_indent(uint8_t indent);
186 static int get_disk_handle_cidl(uint32_t ctl_tag, char *disks_argp,
187 int *comps_nump, raid_obj_handle_t **handlespp);
188 static int get_disk_handle_ctd(int disks_num, char **disks_argpp,
189 uint32_t *ctl_tagp, raid_obj_handle_t *disks_handlep);
190 static int get_ctl_tag(char *argp, uint32_t *ctl_tagp);
191 static int get_array_tag(char *argp, uint32_t *ctl_tagp,
192 array_tag_t *array_tagp);
193 static int get_disk_tag_ctd(char *argp, disk_tag_t *disk_tagp,
194 uint32_t *controller_id);
195 static int get_disk_tag_cidl(char *argp, disk_tag_t *disk_tagp);
196 static int calc_size(char *sizep, uint64_t *valp);
197 static int is_fully_numeric(char *strp);
198 static int size_to_string(uint64_t size, char *string, int len);
199 static int enter_raidctl_lock(int *fd);
200 static void exit_raidctl_lock(int fd);
203 * Entry function of raidctl command
206 main(int argc, char **argv)
208 /* operation index */
209 int8_t findex = DO_HW_RAID_NOP;
211 /* argument pointers */
212 char *r_argp = NULL;
213 char *z_argp = NULL;
214 char *g_argp = NULL;
215 char *a_argp = NULL;
216 char *s_argp = NULL;
217 char *p_argp = NULL;
218 char *F_argp = NULL;
219 char *C_argp = NULL;
222 * operation flags.
224 uint8_t r_flag = FALSE;
225 uint8_t f_flag = FALSE;
226 uint8_t action = FALSE;
227 uint64_t options = 0;
229 /* index and temporary variables */
230 int ret;
231 int status;
232 char c = '\0';
234 /* fd for the filelock */
235 int fd;
237 if (enter_raidctl_lock(&fd) != SUCCESS) {
238 return (FAILURE);
241 (void) setlocale(LC_ALL, "");
242 (void) textdomain(TEXT_DOMAIN);
244 /* parse command line, and get program name */
245 if ((prog_namep = strrchr(argv[0], '/')) == NULL) {
246 prog_namep = argv[0];
247 } else {
248 prog_namep++;
251 /* close error option messages from getopt */
252 opterr = 0;
254 /* get yes expression according to current locale */
255 yesexpr = strdup(nl_langinfo(YESEXPR));
256 yesstr = strdup(nl_langinfo(YESSTR));
257 nostr = strdup(nl_langinfo(NOSTR));
258 if (yesexpr == NULL || yesstr == NULL || nostr == NULL) {
259 return (FAILURE);
263 * If the was no expression or if there is a compile error
264 * use default yes expression.
266 status = regcomp(&re, yesexpr, REG_EXTENDED | REG_NOSUB);
267 if ((*yesexpr == (char)NULL) ||
268 (*yesstr == (char)NULL) ||
269 (*nostr == (char)NULL) ||
270 (status != 0)) {
271 SET_DEFAULT_STRS;
272 if (regcomp(&re, default_yesexpr,
273 REG_EXTENDED | REG_NOSUB) != 0) {
274 return (FALSE);
278 while ((c = getopt(argc, argv,
279 "?hC:cdlF:r:z:g:a:s:p:fS")) != EOF) {
280 switch (c) {
281 case 'h':
282 case '?':
283 if (action == FALSE) {
284 findex = DO_HW_RAID_HELP;
285 action = TRUE;
286 options |= LOWER_H;
287 } else {
288 findex = DO_HW_RAID_NOP;
290 break;
291 case 'C':
292 if (action == FALSE) {
293 findex = DO_HW_RAID_CREATEN;
294 C_argp = optarg;
295 action = TRUE;
296 options |= UPPER_C;
297 } else {
298 findex = DO_HW_RAID_NOP;
300 break;
301 case 'c':
302 if (action == FALSE) {
303 findex = DO_HW_RAID_CREATEO;
304 action = TRUE;
305 options |= LOWER_C;
306 } else {
307 findex = DO_HW_RAID_NOP;
309 break;
310 case 'd':
311 if (action == FALSE) {
312 findex = DO_HW_RAID_DELETE;
313 action = TRUE;
314 options |= LOWER_D;
315 } else {
316 findex = DO_HW_RAID_NOP;
318 break;
319 case 'l':
320 if (action == FALSE) {
321 findex = DO_HW_RAID_LIST;
322 action = TRUE;
323 options |= LOWER_L;
324 } else {
325 findex = DO_HW_RAID_NOP;
327 break;
328 case 'F':
329 if (action == FALSE) {
330 findex = DO_HW_RAID_FLASH;
331 F_argp = optarg;
332 action = TRUE;
333 options |= UPPER_F;
334 } else {
335 findex = DO_HW_RAID_NOP;
337 break;
338 case 'a':
339 if (action == FALSE) {
340 findex = DO_HW_RAID_HSP;
341 a_argp = optarg;
342 action = TRUE;
343 options |= LOWER_A;
344 } else {
345 findex = DO_HW_RAID_NOP;
347 break;
348 case 'p':
349 if (action == FALSE) {
350 findex = DO_HW_RAID_SET_ATTR;
351 p_argp = optarg;
352 action = TRUE;
353 options |= LOWER_P;
354 } else {
355 findex = DO_HW_RAID_NOP;
357 break;
358 case 'r':
359 r_argp = optarg;
360 r_flag = TRUE;
361 options |= LOWER_R;
362 break;
363 case 'z':
364 z_argp = optarg;
365 options |= LOWER_Z;
366 break;
367 case 'g':
368 g_argp = optarg;
369 options |= LOWER_G;
370 break;
371 case 's':
372 s_argp = optarg;
373 options |= LOWER_S;
374 break;
375 case 'f':
376 f_flag = TRUE;
377 options |= LOWER_F;
378 break;
379 case 'S':
380 if (action == FALSE) {
381 findex = DO_HW_RAID_SNAPSHOT;
382 action = TRUE;
383 options |= UPPER_S;
384 } else {
385 findex = DO_HW_RAID_NOP;
387 break;
388 default:
389 (void) fprintf(stderr,
390 gettext("Invalid argument(s).\n"));
391 exit_raidctl_lock(fd);
392 FREE_STRS;
393 regfree(&re);
394 return (INVALID_ARG);
398 /* parse options */
399 switch (findex) {
400 case DO_HW_RAID_HELP:
401 if ((options & ~(LOWER_H)) != 0) {
402 ret = INVALID_ARG;
403 } else {
404 helpinfo(prog_namep);
405 ret = SUCCESS;
407 break;
408 case DO_HW_RAID_CREATEO:
409 if ((options & ~(LOWER_F | LOWER_C | LOWER_R)) != 0) {
410 ret = INVALID_ARG;
411 } else {
412 if (r_flag != FALSE && f_flag == FALSE) {
413 ret = do_create_ctd(r_argp, argv, argc - 4,
414 optind, f_flag);
415 } else if (r_flag == FALSE && f_flag == FALSE) {
416 ret = do_create_ctd(NULL, argv, argc - 2,
417 optind, f_flag);
418 } else if (r_flag != FALSE && f_flag != FALSE) {
419 ret = do_create_ctd(r_argp, argv, argc - 5,
420 optind, f_flag);
421 } else {
422 ret = do_create_ctd(NULL, argv, argc - 3,
423 optind, f_flag);
426 break;
427 case DO_HW_RAID_CREATEN:
428 if ((options & ~(LOWER_F | UPPER_C | LOWER_R | LOWER_Z |
429 LOWER_S)) != 0) {
430 ret = INVALID_ARG;
431 } else {
432 ret = do_create_cidl(r_argp, z_argp, C_argp, s_argp,
433 f_flag, argv, optind);
435 break;
436 case DO_HW_RAID_DELETE:
437 if ((options & ~(LOWER_F | LOWER_D)) != 0) {
438 ret = INVALID_ARG;
439 } else {
440 ret = do_delete(f_flag, argv, optind);
442 break;
443 case DO_HW_RAID_LIST:
444 if ((options & ~(LOWER_L | LOWER_G)) != 0) {
445 ret = INVALID_ARG;
446 } else {
447 ret = do_list(g_argp, argv, optind, FALSE);
449 break;
450 case DO_HW_RAID_SNAPSHOT:
451 if ((options & ~(UPPER_S | LOWER_G)) != 0) {
452 ret = INVALID_ARG;
453 } else {
454 ret = do_list(g_argp, argv, optind, TRUE);
456 break;
457 case DO_HW_RAID_FLASH:
458 if ((options & ~(LOWER_F | UPPER_F)) != 0) {
459 ret = INVALID_ARG;
460 } else {
461 if (f_flag == FALSE) {
462 ret = do_flash(f_flag, F_argp, argv, optind,
463 argc - 3);
464 } else {
465 ret = do_flash(f_flag, F_argp, argv, optind,
466 argc - 4);
469 break;
470 case DO_HW_RAID_HSP:
471 if ((options & ~(LOWER_A | LOWER_G)) != 0) {
472 ret = INVALID_ARG;
473 } else {
474 ret = do_set_hsp(a_argp, g_argp, argv, optind);
476 break;
477 case DO_HW_RAID_SET_ATTR:
478 if ((options & ~(LOWER_F | LOWER_P)) != 0) {
479 ret = INVALID_ARG;
480 } else {
481 ret = do_set_array_attr(f_flag, p_argp, argv, optind);
483 break;
484 case DO_HW_RAID_NOP:
485 if (argc == 1) {
486 ret = do_list(g_argp, argv, optind, FALSE);
487 } else {
488 ret = INVALID_ARG;
490 break;
491 default:
492 ret = INVALID_ARG;
493 break;
496 if (ret == INVALID_ARG) {
497 (void) fprintf(stderr,
498 gettext("Invalid argument(s).\n"));
500 exit_raidctl_lock(fd);
502 FREE_STRS;
503 regfree(&re);
504 return (ret);
508 * helpinfo(prog_namep)
509 * This function prints help informations for usrs.
511 static void
512 helpinfo(char *prog_namep)
514 char quote = '"';
516 (void) printf(gettext("%s [-f] -C %c<disks>%c [-r <raid_level>] "
517 "[-z <capacity>] [-s <stripe_size>] <controller>\n"), prog_namep,
518 quote, quote);
520 (void) printf(gettext("%s [-f] -d <volume>\n"), prog_namep);
522 (void) printf(gettext("%s [-f] -F <filename> <controller1> "
523 "[<controller2> ...]\n"), prog_namep);
525 (void) printf(gettext("%s [-f] -p %c<param>=<value>%c <volume>\n"),
526 prog_namep, quote, quote);
528 (void) printf(gettext("%s [-f] -c [-r <raid_level>] <disk1> <disk2> "
529 "[<disk3> ...]\n"), prog_namep);
531 (void) printf(gettext("%s [-l]\n"), prog_namep);
533 (void) printf(gettext("%s -l -g <disk> <controller>\n"), prog_namep);
535 (void) printf(gettext("%s -l <volume>\n"), prog_namep);
537 (void) printf(gettext("%s -l <controller1> [<controller2> ...]\n"),
538 prog_namep);
540 (void) printf(gettext("%s -a {set | unset} -g <disk> "
541 "{<volume> | <controller>}\n"), prog_namep);
543 (void) printf(gettext("%s -S [<volume> | <controller>]\n"), prog_namep);
545 (void) printf(gettext("%s -S -g <disk> <controller>\n"), prog_namep);
547 (void) printf(gettext("%s -h\n"), prog_namep);
551 * do_create_cidl(raid_levelp, capacityp, disks_argp, stripe_sizep,
552 * f_flag, argv, optind)
553 * This function creates a new RAID volume with specified arguments,
554 * and returns result as SUCCESS, INVALID_ARG or FAILURE.
555 * The "c.id.l" is used to express single physical disk. 'c' expresses
556 * bus number, 'id' expresses target number, and 'l' expresses lun.
557 * The physical disks represented by c.id.l may be invisible to OS, which
558 * means physical disks attached to controllers are not accessible by
559 * OS directly. The disks should be organized as a logical volume, and
560 * the logical volume is exported to OS as a single unit. Some hardware
561 * RAID controllers also support physical disks accessed by OS directly,
562 * for example LSI1068. In this case, it's both OK to express physical
563 * disk by c.id.l format or canonical ctd format.
565 static int
566 do_create_cidl(char *raid_levelp, char *capacityp, char *disks_argp,
567 char *stripe_sizep, uint32_t f_flag, char **argv, uint32_t optind)
569 uint32_t ctl_tag = MAX32BIT;
570 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE;
571 uint32_t raid_level = RAID_LEVEL_1;
572 uint64_t capacity = 0;
573 uint64_t stripe_size = (uint64_t)OBJ_ATTR_NONE;
574 raid_obj_handle_t *disk_handlesp = NULL;
575 raid_obj_handle_t array_handle = INIT_HANDLE_VALUE;
576 raidcfg_controller_t ctl_attr;
577 int comps_num = 0;
578 int ret = 0;
580 raidcfg_array_t array_attr;
582 if (argv[optind] == NULL || argv[optind + 1] != NULL) {
583 return (INVALID_ARG);
586 if (disks_argp == NULL) {
587 return (INVALID_ARG);
590 /* Check controller tag */
591 if (get_ctl_tag(argv[optind], &ctl_tag) != SUCCESS) {
592 return (INVALID_ARG);
595 ctl_handle = raidcfg_get_controller(ctl_tag);
596 if (ctl_handle <= 0) {
597 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ctl_handle));
598 return (FAILURE);
601 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
602 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
603 return (FAILURE);
606 /* Get raid level */
607 if (raid_levelp != NULL) {
608 if (*raid_levelp == '1' &&
609 (*(raid_levelp + 1) == 'E' || *(raid_levelp + 1) == 'e')) {
610 raid_level = RAID_LEVEL_1E;
611 } else {
612 if (is_fully_numeric(raid_levelp) == FALSE) {
613 return (INVALID_ARG);
616 switch (atoi(raid_levelp)) {
617 case 0:
618 raid_level = RAID_LEVEL_0;
619 break;
620 case 1:
621 raid_level = RAID_LEVEL_1;
622 break;
623 case 5:
624 raid_level = RAID_LEVEL_5;
625 break;
626 case 10:
627 raid_level = RAID_LEVEL_10;
628 break;
629 case 50:
630 raid_level = RAID_LEVEL_50;
631 break;
632 default:
633 return (INVALID_ARG);
639 * The rang check of capacity and stripe size is performed in library,
640 * and it relates to hardware feature.
643 /* Capacity in bytes. Capacity 0 means max available space. */
644 if (capacityp != NULL) {
645 if (*capacityp == '-' ||
646 calc_size(capacityp, &capacity) != SUCCESS) {
647 return (INVALID_ARG);
651 /* Stripe size in bytes */
652 if (stripe_sizep != NULL) {
653 if (calc_size(stripe_sizep, &stripe_size) != SUCCESS ||
654 *stripe_sizep == '-') {
655 return (INVALID_ARG);
659 /* Open controller before accessing its object */
660 if ((ret = raidcfg_open_controller(ctl_handle, NULL)) < 0) {
661 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
662 return (FAILURE);
665 /* Get disks' handles */
666 if ((ret = get_disk_handle_cidl(ctl_tag, disks_argp, &comps_num,
667 &disk_handlesp)) != SUCCESS) {
668 (void) raidcfg_close_controller(ctl_handle, NULL);
669 return (ret);
672 if (f_flag == FALSE) {
673 (void) fprintf(stdout, gettext("Creating RAID volume "
674 "will destroy all data on spare space of member disks, "
675 "proceed (%s/%s)? "), yesstr, nostr);
676 if (!yes()) {
677 (void) fprintf(stdout, gettext("RAID volume "
678 "not created.\n\n"));
679 (void) raidcfg_close_controller(ctl_handle, NULL);
680 free(disk_handlesp);
681 return (SUCCESS);
685 /* Create array */
686 array_handle = raidcfg_create_array(comps_num,
687 disk_handlesp, raid_level, capacity, stripe_size, NULL);
689 if (array_handle <= 0) {
690 (void) fprintf(stderr, "%s\n", raidcfg_errstr(array_handle));
691 free(disk_handlesp);
692 (void) raidcfg_close_controller(ctl_handle, NULL);
693 return (FAILURE);
696 /* Get attribute of the new created array */
697 if ((ret = raidcfg_get_attr(array_handle, &array_attr)) < 0) {
698 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
699 free(disk_handlesp);
700 (void) raidcfg_close_controller(ctl_handle, NULL);
701 return (FAILURE);
704 (void) fprintf(stdout, gettext("Volume c%ut%llud%llu is created "
705 "successfully!\n"), ctl_tag, array_attr.tag.idl.target_id,
706 array_attr.tag.idl.lun);
708 /* Print attribute of array */
709 (void) print_array_table(ctl_handle, array_handle);
711 /* Close controller */
712 (void) raidcfg_close_controller(ctl_handle, NULL);
714 free(disk_handlesp);
715 return (SUCCESS);
719 * do_create_ctd(raid_levelp, disks_argpp, disks_num, argindex, f_flag)
720 * This function creates array with specified arguments, and return result
721 * as SUCCESS, FAILURE, or INVALID_ARG. It only supports LSI MPT controller
722 * to be compatible with old raidctl. The capacity and stripe size can't
723 * be specified for LSI MPT controller, and they use zero and default value.
724 * The "ctd" is the canonical expression of physical disks which are
725 * accessible by OS.
727 static int
728 do_create_ctd(char *raid_levelp, char **disks_argpp, uint32_t disks_num,
729 uint32_t argindex, uint32_t f_flag)
731 uint32_t ctl_tag = MAX32BIT;
732 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE;
733 uint32_t raid_level = RAID_LEVEL_1;
734 uint64_t capacity = 0;
735 uint32_t stripe_size = (uint32_t)OBJ_ATTR_NONE;
736 raid_obj_handle_t *disk_handlesp = NULL;
737 raid_obj_handle_t array_handle = INIT_HANDLE_VALUE;
738 raidcfg_controller_t ctl_attr;
739 int ret;
741 raidcfg_array_t array_attr;
742 int i, j;
744 /* Check disks parameter */
745 if (disks_argpp == NULL || disks_num < 2) {
746 return (INVALID_ARG);
749 for (i = 0, j = argindex; i < disks_num; i++, j++) {
750 if (disks_argpp[j] == NULL) {
751 return (INVALID_ARG);
756 * We need check if the raid_level string is fully numeric. If user
757 * input string with unsupported letters, such as "s10", atoi() will
758 * return zero because it is an illegal string, but it doesn't mean
759 * RAID_LEVEL_0.
761 if (raid_levelp != NULL) {
762 if (*raid_levelp == '1' &&
763 (*(raid_levelp + 1) == 'E' || *(raid_levelp + 1) == 'e')) {
764 raid_level = RAID_LEVEL_1E;
765 } else {
766 if (is_fully_numeric(raid_levelp) == FALSE) {
767 return (INVALID_ARG);
770 switch (atoi(raid_levelp)) {
771 case 0:
772 raid_level = RAID_LEVEL_0;
773 break;
774 case 1:
775 raid_level = RAID_LEVEL_1;
776 break;
777 case 5:
778 raid_level = RAID_LEVEL_5;
779 break;
780 default:
781 return (INVALID_ARG);
786 /* Get disks tag and controller tag */
787 disk_handlesp = (raid_obj_handle_t *)calloc(disks_num + 2,
788 sizeof (raid_obj_handle_t));
789 if (disk_handlesp == NULL) {
790 return (FAILURE);
793 disk_handlesp[0] = OBJ_SEPARATOR_BEGIN;
794 disk_handlesp[disks_num + 1] = OBJ_SEPARATOR_END;
796 if ((ret = get_disk_handle_ctd(disks_num, &disks_argpp[argindex],
797 &ctl_tag, &disk_handlesp[1])) != SUCCESS) {
798 free(disk_handlesp);
799 return (ret);
802 /* LIB API should check whether all disks here belong to one ctl. */
803 /* get_disk_handle_ctd has opened controller. */
804 ctl_handle = raidcfg_get_controller(ctl_tag);
806 if (ctl_handle <= 0) {
807 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ctl_handle));
808 (void) raidcfg_close_controller(ctl_handle, NULL);
809 free(disk_handlesp);
810 return (FAILURE);
813 /* Check if the controller is host raid type */
814 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
815 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
816 (void) raidcfg_close_controller(ctl_handle, NULL);
817 free(disk_handlesp);
818 return (FAILURE);
821 if ((ctl_attr.capability & RAID_CAP_DISK_TRANS) == 0) {
822 /* -c only support host raid controller, return failure here */
823 (void) fprintf(stderr,
824 gettext("Option -c only supports host raid controller.\n"));
825 (void) raidcfg_close_controller(ctl_handle, NULL);
826 free(disk_handlesp);
827 return (FAILURE);
830 if (f_flag == FALSE) {
831 (void) fprintf(stdout, gettext("Creating RAID volume "
832 "will destroy all data on spare space of member disks, "
833 "proceed (%s/%s)? "), yesstr, nostr);
834 if (!yes()) {
835 (void) fprintf(stdout, gettext("RAID volume "
836 "not created.\n\n"));
837 free(disk_handlesp);
838 (void) raidcfg_close_controller(ctl_handle, NULL);
839 return (SUCCESS);
844 * For old raidctl, capacity is 0, which means to creates
845 * max possible capacity of array.
848 array_handle = raidcfg_create_array(disks_num + 2,
849 disk_handlesp, raid_level, capacity, stripe_size, NULL);
851 if (array_handle <= 0) {
852 (void) fprintf(stderr, "%s\n", raidcfg_errstr(array_handle));
853 free(disk_handlesp);
854 (void) raidcfg_close_controller(ctl_handle, NULL);
855 return (FAILURE);
858 /* Get attribute of array */
859 if ((ret = raidcfg_get_attr(array_handle, &array_attr)) < 0) {
860 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
861 free(disk_handlesp);
862 (void) raidcfg_close_controller(ctl_handle, NULL);
863 return (FAILURE);
866 /* Close controller */
867 (void) raidcfg_close_controller(ctl_handle, NULL);
869 /* Print feedback for user */
870 (void) fprintf(stdout,
871 gettext("Volume c%ut%llud%llu is created successfully!\n"),
872 ctl_tag, array_attr.tag.idl.target_id,
873 array_attr.tag.idl.lun);
874 free(disk_handlesp);
875 return (SUCCESS);
879 * do_list(disk_arg, argv, optind, is_snapshot)
880 * This function lists RAID's system configuration. It supports various RAID
881 * controller. The return value can be SUCCESS, FAILURE, or INVALID_ARG.
883 static int
884 do_list(char *disk_argp, char **argv, uint32_t optind, uint8_t is_snapshot)
886 uint32_t ctl_tag = MAX32BIT;
887 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE;
888 raid_obj_handle_t disk_handle = INIT_HANDLE_VALUE;
889 raid_obj_handle_t array_handle = INIT_HANDLE_VALUE;
890 disk_tag_t disk_tag;
891 array_tag_t array_tag;
893 int ret;
895 /* print RAID system */
896 if (disk_argp == NULL) {
897 if (argv[optind] == NULL) {
898 ret = snapshot_raidsystem(TRUE, 0, is_snapshot);
899 return (ret);
900 } else {
901 if (is_fully_numeric(argv[optind]) == TRUE) {
902 while (argv[optind] != NULL) {
903 if (get_ctl_tag(argv[optind], &ctl_tag)
904 != SUCCESS) {
905 ret = INVALID_ARG;
906 optind++;
907 continue;
909 ctl_handle =
910 raidcfg_get_controller(ctl_tag);
911 if (ctl_handle <= 0) {
912 (void) fprintf(stderr, "%s\n",
913 raidcfg_errstr(ctl_handle));
914 ret = FAILURE;
915 optind++;
916 continue;
918 ret =
919 raidcfg_open_controller(ctl_handle,
920 NULL);
921 if (ret < 0) {
922 (void) fprintf(stderr, "%s\n",
923 raidcfg_errstr(ret));
924 ret = FAILURE;
925 optind++;
926 continue;
928 if (is_snapshot == FALSE) {
929 ret =
930 print_ctl_table(ctl_handle);
931 } else {
932 ret =
933 snapshot_ctl(ctl_handle,
934 FALSE, 0, is_snapshot);
936 (void) raidcfg_close_controller(
937 ctl_handle, NULL);
938 optind++;
940 } else {
941 if (get_array_tag(argv[optind],
942 &ctl_tag, &array_tag) != SUCCESS) {
943 return (INVALID_ARG);
945 ctl_handle = raidcfg_get_controller(ctl_tag);
946 if (ctl_handle <= 0) {
947 (void) fprintf(stderr, "%s\n",
948 raidcfg_errstr(ctl_handle));
949 return (FAILURE);
952 ret = raidcfg_open_controller(ctl_handle, NULL);
953 if (ret < 0) {
954 (void) fprintf(stderr, "%s\n",
955 raidcfg_errstr(ret));
956 return (FAILURE);
959 array_handle = raidcfg_get_array(ctl_handle,
960 array_tag.idl.target_id, array_tag.idl.lun);
961 if (array_handle <= 0) {
962 (void) fprintf(stderr, "%s\n",
963 raidcfg_errstr(array_handle));
964 (void) raidcfg_close_controller(
965 ctl_handle, NULL);
966 return (FAILURE);
968 if (is_snapshot == FALSE) {
969 ret = print_array_table(ctl_handle,
970 array_handle);
971 } else {
972 ret = snapshot_array(array_handle, 0,
973 FALSE, is_snapshot);
975 (void) raidcfg_close_controller(
976 ctl_handle, NULL);
979 } else {
980 if (argv[optind + 1] != NULL) {
981 return (INVALID_ARG);
984 if (get_ctl_tag(argv[optind], &ctl_tag) != SUCCESS) {
985 return (INVALID_ARG);
988 ctl_handle = raidcfg_get_controller(ctl_tag);
989 if (ctl_handle <= 0) {
990 (void) fprintf(stderr, "%s\n",
991 raidcfg_errstr(ctl_handle));
992 return (FAILURE);
995 if (get_disk_tag_cidl(disk_argp, &disk_tag) != SUCCESS) {
996 return (INVALID_ARG);
999 ret = raidcfg_open_controller(ctl_handle, NULL);
1000 if (ret < 0) {
1001 (void) fprintf(stderr, "%s\n",
1002 raidcfg_errstr(ret));
1003 return (FAILURE);
1006 disk_handle = raidcfg_get_disk(ctl_handle, disk_tag);
1007 if (disk_handle <= 0) {
1008 (void) fprintf(stderr, "%s\n",
1009 raidcfg_errstr(disk_handle));
1010 (void) raidcfg_close_controller(ctl_handle, NULL);
1011 return (FAILURE);
1014 if (is_snapshot == FALSE) {
1015 ret = print_disk_table(ctl_handle, disk_handle);
1016 } else {
1017 ret = snapshot_disk(ctl_tag, disk_handle, 0,
1018 is_snapshot);
1020 (void) raidcfg_close_controller(ctl_handle, NULL);
1022 return (ret);
1026 * do_delete(f_flag, argv, optind)
1027 * This function deletes a specified array, and return result as SUCCESS,
1028 * FAILURE or INVALID_ARG.
1030 static int
1031 do_delete(uint32_t f_flag, char **argv, uint32_t optind)
1033 uint32_t ctl_tag;
1034 char *array_argp;
1035 array_tag_t array_tag;
1036 raid_obj_handle_t ctl_handle;
1037 raid_obj_handle_t array_handle;
1038 int ret;
1040 array_argp = argv[optind];
1041 if (array_argp == NULL || argv[optind + 1] != NULL) {
1042 return (INVALID_ARG);
1045 if (get_array_tag(array_argp, &ctl_tag, &array_tag) != SUCCESS) {
1046 return (INVALID_ARG);
1049 ctl_handle = raidcfg_get_controller(ctl_tag);
1050 if (ctl_handle <= 0) {
1051 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ctl_handle));
1052 return (INVALID_ARG);
1055 ret = raidcfg_open_controller(ctl_handle, NULL);
1056 if (ret < 0) {
1057 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1058 return (FAILURE);
1061 array_handle = raidcfg_get_array(ctl_handle, array_tag.idl.target_id,
1062 array_tag.idl.lun);
1063 if (array_handle <= 0) {
1064 (void) fprintf(stderr, "%s\n", raidcfg_errstr(array_handle));
1065 (void) raidcfg_close_controller(ctl_handle, NULL);
1066 return (FAILURE);
1069 if (f_flag == FALSE) {
1070 (void) fprintf(stdout, gettext("Deleting RAID volume "
1071 "%s will destroy all data it contains, "
1072 "proceed (%s/%s)? "), array_argp, yesstr, nostr);
1073 if (!yes()) {
1074 (void) fprintf(stdout, gettext("RAID Volume "
1075 "%s not deleted.\n\n"), array_argp);
1076 (void) raidcfg_close_controller(ctl_handle, NULL);
1077 return (SUCCESS);
1082 if ((ret = raidcfg_delete_array(array_handle, NULL)) < 0) {
1083 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1084 (void) raidcfg_close_controller(ctl_handle, NULL);
1085 return (FAILURE);
1088 (void) fprintf(stdout, gettext("Volume %s is deleted successfully!\n"),
1089 array_argp);
1090 (void) raidcfg_close_controller(ctl_handle, NULL);
1092 return (SUCCESS);
1096 * do_flash(f_flag, filep, ctls_argpp, index, ctl_num)
1097 * This function downloads and updates firmware for specified controller, and
1098 * return result as SUCCESS, FAILURE or INVALID_ARG.
1100 static int
1101 do_flash(uint8_t f_flag, char *filep, char **ctls_argpp,
1102 uint32_t index, uint32_t ctl_num)
1104 uint32_t ctl_tag = MAX32BIT;
1105 char *ctl_argp = NULL;
1106 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE;
1107 int ret;
1108 int i, j;
1110 if (ctl_num == 0)
1111 return (INVALID_ARG);
1113 for (i = 0, j = index; i < ctl_num; i++, j++) {
1114 ctl_argp = ctls_argpp[j];
1115 if (get_ctl_tag(ctl_argp, &ctl_tag) != SUCCESS) {
1116 return (INVALID_ARG);
1119 /* Ask user to confirm operation. */
1120 if (f_flag == FALSE) {
1121 (void) fprintf(stdout, gettext("Update flash image on "
1122 "controller %d (%s/%s)? "), ctl_tag, yesstr, nostr);
1123 if (!yes()) {
1124 (void) fprintf(stdout,
1125 gettext("Controller %d not "
1126 "flashed.\n\n"), ctl_tag);
1127 return (SUCCESS);
1131 if ((ctl_handle = raidcfg_get_controller(ctl_tag)) < 0) {
1132 (void) fprintf(stderr, "%s\n",
1133 raidcfg_errstr(ctl_handle));
1134 return (FAILURE);
1137 ret = raidcfg_open_controller(ctl_handle, NULL);
1138 if (ret < 0) {
1139 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1140 return (FAILURE);
1143 (void) fprintf(stdout, gettext("Start updating controller "
1144 "c%u firmware....\n"), ctl_tag);
1146 if ((ret = raidcfg_update_fw(ctl_handle, filep, NULL)) < 0) {
1147 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1148 (void) raidcfg_close_controller(ctl_handle, NULL);
1149 return (FAILURE);
1152 (void) fprintf(stdout, gettext("Update controller "
1153 "c%u firmware successfully.\n"), ctl_tag);
1155 (void) raidcfg_close_controller(ctl_handle, NULL);
1158 return (SUCCESS);
1162 * do_set_hsp(a_argp, disk_argp, argv, optind)
1163 * This function set or unset HSP relationship between disk and controller/
1164 * array, and return result as SUCCESS, FAILURE or INVALID_ARG.
1166 static int
1167 do_set_hsp(char *a_argp, char *disk_argp, char **argv, uint32_t optind)
1169 uint32_t flag = MAX32BIT;
1170 uint32_t ctl_tag = MAX32BIT;
1171 array_tag_t array_tag;
1172 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE;
1173 raid_obj_handle_t disk_handle = INIT_HANDLE_VALUE;
1174 raid_obj_handle_t array_handle = INIT_HANDLE_VALUE;
1175 raidcfg_controller_t ctl_attr;
1176 disk_tag_t disk_tag;
1178 int ret;
1179 int hsp_type;
1180 raidcfg_hsp_relation_t hsp_relation;
1182 (void) memset(&hsp_relation, 0, sizeof (raidcfg_hsp_relation_t));
1184 if (a_argp == NULL) {
1185 return (INVALID_ARG);
1188 if (strcmp(a_argp, "set") == 0) {
1189 flag = HSP_SET;
1190 } else if (strcmp(a_argp, "unset") == 0) {
1191 flag = HSP_UNSET;
1192 } else {
1193 return (INVALID_ARG);
1196 if (disk_argp == NULL) {
1197 return (INVALID_ARG);
1200 if (argv[optind] == NULL || argv[optind + 1] != NULL) {
1201 return (INVALID_ARG);
1202 } else if (is_fully_numeric(argv[optind]) == TRUE) {
1203 /* Global HSP */
1204 hsp_type = 0;
1205 if (get_disk_tag_cidl(disk_argp, &disk_tag) != SUCCESS) {
1206 return (INVALID_ARG);
1209 if (get_ctl_tag(argv[optind], &ctl_tag) != SUCCESS) {
1210 return (INVALID_ARG);
1213 ctl_handle = raidcfg_get_controller(ctl_tag);
1214 if (ctl_handle <= 0) {
1215 (void) fprintf(stderr, "%s\n",
1216 raidcfg_errstr(ctl_handle));
1217 return (FAILURE);
1220 ret = raidcfg_open_controller(ctl_handle, NULL);
1221 if (ret < 0) {
1222 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1223 return (FAILURE);
1226 disk_handle = raidcfg_get_disk(ctl_handle, disk_tag);
1227 if (disk_handle <= 0) {
1228 (void) fprintf(stderr, "%s\n",
1229 raidcfg_errstr(disk_handle));
1230 (void) raidcfg_close_controller(ctl_handle, NULL);
1231 return (FAILURE);
1233 } else {
1234 /* Local HSP */
1235 hsp_type = 1;
1236 if (get_array_tag(argv[optind], &ctl_tag, &array_tag) !=
1237 SUCCESS) {
1238 return (INVALID_ARG);
1241 /* Open controller */
1242 ctl_handle = raidcfg_get_controller(ctl_tag);
1243 if (ctl_handle <= 0) {
1244 (void) fprintf(stderr, "%s\n",
1245 raidcfg_errstr(ctl_handle));
1246 return (FAILURE);
1249 ret = raidcfg_open_controller(ctl_handle, NULL);
1250 if (ret < 0) {
1251 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1252 return (FAILURE);
1255 /* Get controller's attribute */
1256 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
1257 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1258 (void) raidcfg_close_controller(ctl_handle, NULL);
1259 return (FAILURE);
1262 if (get_disk_tag_cidl(disk_argp, &disk_tag) != SUCCESS) {
1263 (void) raidcfg_close_controller(ctl_handle, NULL);
1264 return (INVALID_ARG);
1267 /* Get disk handle */
1268 disk_handle = raidcfg_get_disk(ctl_handle, disk_tag);
1269 if (disk_handle <= 0) {
1270 (void) fprintf(stderr, "%s\n",
1271 raidcfg_errstr(disk_handle));
1272 (void) raidcfg_close_controller(ctl_handle, NULL);
1273 return (FAILURE);
1276 /* Get array handle */
1277 array_handle = raidcfg_get_array(ctl_handle,
1278 array_tag.idl.target_id, array_tag.idl.lun);
1279 if (array_handle <= 0) {
1280 (void) fprintf(stderr, "%s\n",
1281 raidcfg_errstr(array_handle));
1282 (void) raidcfg_close_controller(ctl_handle, NULL);
1283 return (FAILURE);
1287 hsp_relation.disk_handle = disk_handle;
1288 if (hsp_type) {
1289 /* Set or unset local HSP */
1290 hsp_relation.array_handle = array_handle;
1291 } else {
1292 /* Set or unset global HSP */
1293 hsp_relation.array_handle = OBJ_ATTR_NONE;
1296 /* Perform operation of set or unset */
1297 if (flag == HSP_SET) {
1298 if ((ret = raidcfg_set_hsp(&hsp_relation, NULL)) < 0) {
1299 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1300 (void) raidcfg_close_controller(ctl_handle, NULL);
1301 return (FAILURE);
1304 if (hsp_type) {
1305 (void) printf(gettext("Set local HSP between disk %s "
1306 "and RAID volume %s successfully.\n"),
1307 disk_argp, argv[optind]);
1308 } else {
1309 (void) printf(gettext("Set global HSP between disk %s "
1310 "and controller %s successfully.\n"),
1311 disk_argp, argv[optind]);
1313 } else {
1314 if ((ret = raidcfg_unset_hsp(&hsp_relation, NULL)) < 0) {
1315 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1316 (void) raidcfg_close_controller(ctl_handle, NULL);
1317 return (FAILURE);
1320 if (hsp_type) {
1321 (void) printf(gettext("Unset local HSP between "
1322 "disk %s and RAID volume %s successfully.\n"),
1323 disk_argp, argv[optind]);
1324 } else {
1325 (void) printf(gettext("Unset global HSP between "
1326 "disk %s and controller %s successfully.\n"),
1327 disk_argp, argv[optind]);
1330 (void) raidcfg_close_controller(ctl_handle, NULL);
1331 return (SUCCESS);
1335 * do_set_array_attr(f_flag, p_argp, argv, optind)
1336 * This function changes array's attribute when array is running.
1337 * The changeable attribute is up to controller's feature.
1338 * The return value can be SUCCESS, FAILURE or INVALID_ARG.
1340 static int
1341 do_set_array_attr(uint32_t f_flag, char *p_argp, char **argv, uint32_t optind)
1343 uint32_t ctl_tag = MAX32BIT;
1344 array_tag_t array_tag;
1345 uint32_t type = MAX32BIT;
1346 uint32_t value = MAX32BIT;
1347 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE;
1348 raid_obj_handle_t array_handle = INIT_HANDLE_VALUE;
1350 char *param, *op = "=";
1352 int ret;
1354 if (argv[optind] == NULL || argv[optind + 1] != NULL) {
1355 return (INVALID_ARG);
1358 if (p_argp != NULL) {
1359 param = strtok(p_argp, op);
1360 if (strcmp(param, "wp") == 0) {
1361 type = SET_CACHE_WR_PLY;
1362 param = strtok(NULL, op);
1363 if (strcmp(param, "on") == 0) {
1364 value = CACHE_WR_ON;
1365 } else if (strcmp(param, "off") == 0) {
1366 value = CACHE_WR_OFF;
1367 } else {
1368 return (INVALID_ARG);
1370 } else if (strcmp(param, "state") == 0) {
1371 type = SET_ACTIVATION_PLY;
1372 param = strtok(NULL, op);
1373 if (strcmp(param, "activate") == 0) {
1374 value = ARRAY_ACT_ACTIVATE;
1375 } else {
1376 return (INVALID_ARG);
1378 } else {
1379 return (INVALID_ARG);
1381 } else {
1382 return (INVALID_ARG);
1385 if (get_array_tag(argv[optind], &ctl_tag, &array_tag) != SUCCESS) {
1386 return (INVALID_ARG);
1389 ctl_handle = raidcfg_get_controller(ctl_tag);
1390 if (ctl_handle <= 0) {
1391 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ctl_handle));
1392 return (FAILURE);
1395 ret = raidcfg_open_controller(ctl_handle, NULL);
1396 if (ret < 0) {
1397 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1398 return (FAILURE);
1401 array_handle = raidcfg_get_array(ctl_handle, array_tag.idl.target_id,
1402 array_tag.idl.lun);
1403 if (array_handle <= 0) {
1404 (void) fprintf(stderr, "%s\n", raidcfg_errstr(array_handle));
1405 return (FAILURE);
1408 /* Ask user to confirm operation. */
1409 if (f_flag == FALSE) {
1410 (void) fprintf(stdout, gettext("Update attribute of "
1411 "array %s (%s/%s)? "), argv[optind], yesstr, nostr);
1412 if (!yes()) {
1413 (void) fprintf(stdout,
1414 gettext("Array %s not "
1415 "changed.\n\n"), argv[optind]);
1416 (void) raidcfg_close_controller(ctl_handle, NULL);
1417 return (SUCCESS);
1421 if ((ret = raidcfg_set_attr(array_handle, type, &value, NULL)) < 0) {
1422 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1423 (void) raidcfg_close_controller(ctl_handle, NULL);
1424 return (FAILURE);
1427 (void) printf(gettext("Set attribute of RAID volume %s "
1428 "successfully.\n"), argv[optind]);
1429 (void) raidcfg_close_controller(ctl_handle, NULL);
1431 return (SUCCESS);
1435 * snapshot_raidsystem(recursive, indent, is_snapshot)
1436 * This function prints the snapshot of whole RAID's system configuration,
1437 * and return result as SUCCESS or FAILURE.
1439 static int
1440 snapshot_raidsystem(uint8_t recursive, uint8_t indent, uint8_t is_snapshot)
1442 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE;
1443 int ret;
1445 ctl_handle = raidcfg_list_head(OBJ_SYSTEM, OBJ_TYPE_CONTROLLER);
1446 while (ctl_handle > 0) {
1447 ret = raidcfg_open_controller(ctl_handle, NULL);
1448 if (ret == 0) {
1449 if (snapshot_ctl(ctl_handle, recursive, indent,
1450 is_snapshot) == FAILURE) {
1451 (void) raidcfg_close_controller(ctl_handle,
1452 NULL);
1455 ctl_handle = raidcfg_list_next(ctl_handle);
1457 return (SUCCESS);
1461 * snapshot_ctl(ctl_handle, recursive, indent, is_snapshot)
1462 * This function prints snapshot of specified controller's configuration,
1463 * and return result as SUCCESS or FAILURE.
1465 static int
1466 snapshot_ctl(raid_obj_handle_t ctl_handle, uint8_t recursive, uint8_t indent,
1467 uint8_t is_snapshot)
1469 raid_obj_handle_t array_handle = INIT_HANDLE_VALUE;
1470 raid_obj_handle_t disk_handle = INIT_HANDLE_VALUE;
1471 raidcfg_controller_t ctl_attr;
1472 uint32_t ctl_tag;
1473 char ctlbuf[256];
1474 int ret;
1476 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
1477 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1478 return (FAILURE);
1481 ctl_tag = ctl_attr.controller_id;
1482 if (is_snapshot == FALSE) {
1483 print_indent(indent);
1484 (void) fprintf(stdout, gettext("Controller: %u\n"), ctl_tag);
1485 } else {
1486 (void) snprintf(ctlbuf, sizeof (ctlbuf), "%u \"%s\"",
1487 ctl_tag, ctl_attr.controller_type);
1488 (void) fprintf(stdout, "%s", ctlbuf);
1490 (void) fprintf(stdout, "\n");
1493 if (recursive == TRUE) {
1494 array_handle = raidcfg_list_head(ctl_handle, OBJ_TYPE_ARRAY);
1495 while (array_handle > 0) {
1496 if (snapshot_array(array_handle,
1497 indent + 1, FALSE, is_snapshot) == FAILURE) {
1498 return (FAILURE);
1501 array_handle = raidcfg_list_next(array_handle);
1504 disk_handle = raidcfg_list_head(ctl_handle, OBJ_TYPE_DISK);
1505 while (disk_handle > 0) {
1506 if (snapshot_disk(ctl_tag, disk_handle,
1507 indent + 1, is_snapshot) == FAILURE) {
1508 return (FAILURE);
1511 disk_handle = raidcfg_list_next(disk_handle);
1514 return (SUCCESS);
1519 * snapshot_array(array_handle, indent, is_sub, is_snapshot)
1520 * This function prints snapshot of specified array's configuration,
1521 * and return result as SUCCESS or FAILURE.
1523 static int
1524 snapshot_array(raid_obj_handle_t array_handle, uint8_t indent, uint8_t is_sub,
1525 uint8_t is_snapshot)
1527 raid_obj_handle_t ctl_handle;
1528 raid_obj_handle_t subarray_handle;
1529 raid_obj_handle_t arraypart_handle;
1530 raid_obj_handle_t task_handle;
1532 raidcfg_controller_t ctl_attr;
1533 raidcfg_array_t array_attr;
1534 raidcfg_arraypart_t arraypart_attr;
1535 raidcfg_task_t task_attr;
1537 char arraybuf[256] = "\0";
1538 char diskbuf[256] = "\0";
1539 char tempbuf[256] = "\0";
1540 int disknum = 0;
1542 uint32_t ctl_tag;
1543 int ret;
1545 ctl_handle = raidcfg_get_container(array_handle);
1546 ret = raidcfg_get_attr(ctl_handle, &ctl_attr);
1547 if (ret < 0) {
1548 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1549 return (FAILURE);
1551 ctl_tag = ctl_attr.controller_id;
1553 /* Print array attribute */
1554 if ((ret = raidcfg_get_attr(array_handle, &array_attr)) < 0) {
1555 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1556 return (FAILURE);
1559 if (is_snapshot == FALSE) {
1560 print_indent(indent);
1561 if (is_sub == FALSE) {
1562 (void) fprintf(stdout, gettext("Volume:"
1563 "c%ut%llud%llu\n"),
1564 ctl_tag, array_attr.tag.idl.target_id,
1565 array_attr.tag.idl.lun);
1566 } else {
1567 (void) fprintf(stdout, gettext("Sub-Volume\n"));
1569 } else {
1570 (void) snprintf(arraybuf, sizeof (arraybuf), "c%ut%llud%llu ",
1571 ctl_tag, array_attr.tag.idl.target_id,
1572 array_attr.tag.idl.lun);
1574 /* Check if array is in sync state */
1575 task_handle = raidcfg_list_head(array_handle, OBJ_TYPE_TASK);
1576 if (task_handle > 0) {
1577 (void) raidcfg_get_attr(task_handle, &task_attr);
1578 if (task_attr.task_func == TASK_FUNC_BUILD) {
1579 array_attr.state = ARRAY_STATE_SYNC;
1581 } else {
1582 subarray_handle = raidcfg_list_head(array_handle,
1583 OBJ_TYPE_ARRAY);
1584 while (subarray_handle > 0) {
1585 task_handle = raidcfg_list_head(subarray_handle,
1586 OBJ_TYPE_TASK);
1587 if (task_handle > 0) {
1588 (void) raidcfg_get_attr(task_handle,
1589 &task_attr);
1590 if (task_attr.task_func ==
1591 TASK_FUNC_BUILD) {
1592 array_attr.state =
1593 ARRAY_STATE_SYNC;
1595 break;
1597 subarray_handle =
1598 raidcfg_list_next(subarray_handle);
1602 /* Print sub array */
1603 subarray_handle = raidcfg_list_head(array_handle,
1604 OBJ_TYPE_ARRAY);
1605 while (subarray_handle > 0) {
1606 /* print subarraypart */
1607 arraypart_handle = raidcfg_list_head(subarray_handle,
1608 OBJ_TYPE_ARRAY_PART);
1609 while (arraypart_handle > 0) {
1610 if ((ret = raidcfg_get_attr(arraypart_handle,
1611 &arraypart_attr)) < 0) {
1612 (void) fprintf(stderr, "%s\n",
1613 raidcfg_errstr(ret));
1614 return (FAILURE);
1617 if (arraypart_attr.tag.cidl.bus == MAX64BIT) {
1618 (void) snprintf(tempbuf,
1619 sizeof (tempbuf),
1620 gettext("N/A"));
1621 } else {
1622 (void) snprintf(tempbuf,
1623 sizeof (tempbuf),
1624 "%llu.%llu.%llu",
1625 arraypart_attr.tag.cidl.bus,
1626 arraypart_attr.tag.cidl.target_id,
1627 arraypart_attr.tag.cidl.lun);
1629 (void) strlcat(diskbuf, tempbuf,
1630 sizeof (diskbuf));
1631 (void) strcat(diskbuf, " ");
1632 disknum++;
1633 arraypart_handle =
1634 raidcfg_list_next(arraypart_handle);
1636 subarray_handle = raidcfg_list_next(subarray_handle);
1639 /* Print arraypart */
1640 arraypart_handle = raidcfg_list_head(array_handle,
1641 OBJ_TYPE_ARRAY_PART);
1642 while (arraypart_handle > 0) {
1643 if ((ret = raidcfg_get_attr(arraypart_handle,
1644 &arraypart_attr)) < 0) {
1645 (void) fprintf(stderr, "%s\n",
1646 raidcfg_errstr(ret));
1647 return (FAILURE);
1650 if (arraypart_attr.tag.cidl.bus == MAX64BIT) {
1651 (void) snprintf(tempbuf, sizeof (tempbuf),
1652 gettext("N/A"));
1653 } else {
1654 (void) snprintf(tempbuf, sizeof (tempbuf),
1655 "%llu.%llu.%llu",
1656 arraypart_attr.tag.cidl.bus,
1657 arraypart_attr.tag.cidl.target_id,
1658 arraypart_attr.tag.cidl.lun);
1660 (void) strlcat(diskbuf, tempbuf, sizeof (diskbuf));
1661 (void) strcat(diskbuf, " ");
1662 disknum++;
1663 arraypart_handle = raidcfg_list_next(arraypart_handle);
1665 (void) snprintf(tempbuf, sizeof (tempbuf), "%u ", disknum);
1666 (void) strlcat(arraybuf, tempbuf, sizeof (arraybuf));
1667 (void) strlcat(arraybuf, diskbuf, sizeof (arraybuf));
1669 switch (array_attr.raid_level) {
1670 case RAID_LEVEL_0:
1671 (void) sprintf(tempbuf, "0");
1672 break;
1673 case RAID_LEVEL_1:
1674 (void) sprintf(tempbuf, "1");
1675 break;
1676 case RAID_LEVEL_1E:
1677 (void) sprintf(tempbuf, "1E");
1678 break;
1679 case RAID_LEVEL_5:
1680 (void) sprintf(tempbuf, "5");
1681 break;
1682 case RAID_LEVEL_10:
1683 (void) sprintf(tempbuf, "10");
1684 break;
1685 case RAID_LEVEL_50:
1686 (void) sprintf(tempbuf, "50");
1687 break;
1688 default:
1689 (void) snprintf(tempbuf, sizeof (tempbuf),
1690 gettext("N/A"));
1691 break;
1693 (void) strlcat(arraybuf, tempbuf, sizeof (arraybuf));
1694 (void) fprintf(stdout, "%s ", arraybuf);
1696 switch (array_attr.state) {
1697 case ARRAY_STATE_OPTIMAL:
1698 (void) fprintf(stdout, gettext("OPTIMAL"));
1699 break;
1700 case ARRAY_STATE_DEGRADED:
1701 (void) fprintf(stdout, gettext("DEGRADED"));
1702 break;
1703 case ARRAY_STATE_FAILED:
1704 (void) fprintf(stdout, gettext("FAILED"));
1705 break;
1706 case ARRAY_STATE_SYNC:
1707 (void) fprintf(stdout, gettext("SYNC"));
1708 break;
1709 case ARRAY_STATE_MISSING:
1710 (void) fprintf(stdout, gettext("MISSING"));
1711 break;
1712 default:
1713 (void) fprintf(stdout, gettext("N/A"));
1714 break;
1716 (void) fprintf(stdout, "\n");
1719 return (SUCCESS);
1723 * snapshot_disk(ctl_tag, disk_handle, indent, is_snapshot)
1724 * This function prints snapshot of specified disk's configuration, and return
1725 * result as SUCCESS or FAILURE.
1727 static int
1728 snapshot_disk(uint32_t ctl_tag, raid_obj_handle_t disk_handle, uint8_t indent,
1729 uint8_t is_snapshot)
1731 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE;
1732 raid_obj_handle_t hsp_handle;
1734 raidcfg_controller_t ctl_attr;
1735 raidcfg_disk_t disk_attr;
1736 char diskbuf[256] = "";
1737 char tempbuf[256] = "";
1739 int ret;
1741 ctl_handle = raidcfg_get_controller(ctl_tag);
1742 ret = raidcfg_get_attr(ctl_handle, &ctl_attr);
1743 if (ret < 0) {
1744 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1745 return (FAILURE);
1748 /* Print attribute of disk */
1749 if ((ret = raidcfg_get_attr(disk_handle, &disk_attr)) < 0) {
1750 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1751 return (FAILURE);
1754 if (is_snapshot == FALSE) {
1755 print_indent(indent);
1757 hsp_handle = raidcfg_list_head(disk_handle, OBJ_TYPE_HSP);
1759 if (disk_attr.tag.cidl.bus == MAX64BIT) {
1760 (void) fprintf(stdout, gettext("Disk: N/A"));
1761 } else {
1762 (void) fprintf(stdout, gettext("Disk: %llu.%llu.%llu"),
1763 disk_attr.tag.cidl.bus,
1764 disk_attr.tag.cidl.target_id,
1765 disk_attr.tag.cidl.lun);
1767 if (hsp_handle > 0) {
1768 (void) fprintf(stdout, "(HSP)");
1770 (void) fprintf(stdout, "\n");
1771 } else {
1772 if (disk_attr.tag.cidl.bus == MAX64BIT) {
1773 (void) fprintf(stdout, gettext("N/A"));
1774 } else {
1775 (void) snprintf(diskbuf, sizeof (diskbuf),
1776 "%llu.%llu.%llu ",
1777 disk_attr.tag.cidl.bus,
1778 disk_attr.tag.cidl.target_id,
1779 disk_attr.tag.cidl.lun);
1781 hsp_handle = raidcfg_list_head(disk_handle, OBJ_TYPE_HSP);
1782 if (hsp_handle > 0) {
1783 (void) snprintf(tempbuf, sizeof (tempbuf),
1784 gettext("HSP"));
1785 } else if (disk_attr.state == DISK_STATE_GOOD) {
1786 (void) snprintf(tempbuf, sizeof (tempbuf),
1787 gettext("GOOD"));
1788 } else if (disk_attr.state == DISK_STATE_FAILED) {
1789 (void) snprintf(tempbuf, sizeof (tempbuf),
1790 gettext("FAILED"));
1791 } else {
1792 (void) snprintf(tempbuf, sizeof (tempbuf),
1793 gettext("N/A"));
1796 (void) strlcat(diskbuf, tempbuf, sizeof (diskbuf));
1797 (void) fprintf(stdout, "%s\n", diskbuf);
1800 return (SUCCESS);
1803 static int
1804 print_ctl_table(raid_obj_handle_t ctl_handle)
1806 raidcfg_controller_t ctl_attr;
1807 char controller[8];
1808 int ret;
1810 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
1811 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1812 return (FAILURE);
1815 (void) fprintf(stdout, gettext("Controller\tType\t\tVersion"));
1816 (void) fprintf(stdout, "\n");
1817 (void) fprintf(stdout, "--------------------------------");
1818 (void) fprintf(stdout, "--------------------------------");
1819 (void) fprintf(stdout, "\n");
1821 (void) snprintf(controller, sizeof (controller), "%u",
1822 ctl_attr.controller_id);
1823 (void) printf("c%s\t\t", controller);
1825 (void) print_ctl_attr(&ctl_attr);
1826 (void) fprintf(stdout, "\n");
1828 return (SUCCESS);
1831 static int
1832 print_array_table(raid_obj_handle_t ctl_handle, raid_obj_handle_t array_handle)
1834 raidcfg_controller_t ctl_attr;
1835 raidcfg_array_t array_attr;
1836 raidcfg_array_t subarray_attr;
1837 raidcfg_arraypart_t arraypart_attr;
1838 raidcfg_task_t task_attr;
1840 raid_obj_handle_t subarray_handle;
1841 raid_obj_handle_t arraypart_handle;
1842 raid_obj_handle_t task_handle;
1844 char array[16];
1845 char arraypart[8];
1846 int ret;
1847 int i;
1849 /* Controller attribute */
1850 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
1851 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1852 return (FAILURE);
1855 /* Array attribute */
1856 if ((ret = raidcfg_get_attr(array_handle, &array_attr)) < 0) {
1857 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1858 return (FAILURE);
1861 /* print header */
1862 (void) fprintf(stdout, gettext("Volume\t\t\tSize\tStripe\tStatus\t"
1863 " Cache\tRAID"));
1864 (void) fprintf(stdout, "\n");
1865 (void) fprintf(stdout, gettext("\tSub\t\t\tSize\t\t\tLevel"));
1866 (void) fprintf(stdout, "\n");
1867 (void) fprintf(stdout, gettext("\t\tDisk\t\t\t\t\t"));
1868 (void) fprintf(stdout, "\n");
1869 (void) fprintf(stdout, "--------------------------------");
1870 (void) fprintf(stdout, "--------------------------------");
1871 (void) fprintf(stdout, "\n");
1873 /* print array */
1874 (void) snprintf(array, sizeof (array), "c%ut%llud%llu",
1875 ctl_attr.controller_id, array_attr.tag.idl.target_id,
1876 array_attr.tag.idl.lun);
1877 (void) fprintf(stdout, "%s\t\t", array);
1878 if (strlen(array) < 8)
1879 (void) fprintf(stdout, "\t");
1882 /* check if array is in sync state */
1883 task_handle = raidcfg_list_head(array_handle, OBJ_TYPE_TASK);
1884 if (task_handle > 0) {
1885 (void) raidcfg_get_attr(task_handle, &task_attr);
1886 if (task_attr.task_func == TASK_FUNC_BUILD) {
1887 array_attr.state = ARRAY_STATE_SYNC;
1889 } else {
1890 subarray_handle = raidcfg_list_head(array_handle,
1891 OBJ_TYPE_ARRAY);
1892 while (subarray_handle > 0) {
1893 task_handle = raidcfg_list_head(subarray_handle,
1894 OBJ_TYPE_TASK);
1895 if (task_handle > 0) {
1896 (void) raidcfg_get_attr(task_handle,
1897 &task_attr);
1898 if (task_attr.task_func == TASK_FUNC_BUILD) {
1899 array_attr.state = ARRAY_STATE_SYNC;
1901 break;
1903 subarray_handle = raidcfg_list_next(subarray_handle);
1907 (void) print_array_attr(&array_attr);
1908 (void) fprintf(stdout, "\n");
1910 /* Print sub array */
1911 i = 0; /* Count sub array number */
1912 subarray_handle = raidcfg_list_head(array_handle, OBJ_TYPE_ARRAY);
1913 while (subarray_handle > 0) {
1914 if ((ret = raidcfg_get_attr(subarray_handle,
1915 &subarray_attr)) < 0) {
1916 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1917 return (FAILURE);
1920 /* Use sub0/sub1 here, not cxtxd0 for subarray */
1921 (void) snprintf(array, sizeof (array), "sub%u", i++);
1922 (void) fprintf(stdout, "\t%s\t\t", array);
1924 /* Check if array is in sync */
1925 task_handle = raidcfg_list_head(subarray_handle, OBJ_TYPE_TASK);
1926 if (task_handle > 0) {
1927 (void) raidcfg_get_attr(task_handle, &task_attr);
1928 if (task_attr.task_func == TASK_FUNC_BUILD) {
1929 subarray_attr.state = ARRAY_STATE_SYNC;
1933 (void) print_array_attr(&subarray_attr);
1934 (void) fprintf(stdout, "\n");
1936 /* Print subarraypart */
1937 arraypart_handle = raidcfg_list_head(subarray_handle,
1938 OBJ_TYPE_ARRAY_PART);
1939 while (arraypart_handle > 0) {
1940 if ((ret = raidcfg_get_attr(arraypart_handle,
1941 &arraypart_attr)) < 0) {
1942 (void) fprintf(stderr, "%s\n",
1943 raidcfg_errstr(ret));
1944 return (FAILURE);
1947 if (arraypart_attr.tag.cidl.bus == MAX64BIT) {
1948 (void) snprintf(arraypart, sizeof (arraypart),
1949 gettext("N/A"));
1950 } else {
1951 (void) snprintf(arraypart, sizeof (arraypart),
1952 "%llu.%llu.%llu",
1953 arraypart_attr.tag.cidl.bus,
1954 arraypart_attr.tag.cidl.target_id,
1955 arraypart_attr.tag.cidl.lun);
1958 (void) fprintf(stdout, "\t\t%s\t", arraypart);
1959 (void) print_arraypart_attr(&arraypart_attr);
1960 (void) fprintf(stdout, "\n");
1961 arraypart_handle = raidcfg_list_next(arraypart_handle);
1963 subarray_handle = raidcfg_list_next(subarray_handle);
1966 /* Print arraypart */
1967 arraypart_handle = raidcfg_list_head(array_handle,
1968 OBJ_TYPE_ARRAY_PART);
1969 while (arraypart_handle > 0) {
1970 if ((ret = raidcfg_get_attr(arraypart_handle,
1971 &arraypart_attr)) < 0) {
1972 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1973 return (FAILURE);
1976 if (arraypart_attr.tag.cidl.bus == MAX64BIT) {
1977 (void) snprintf(arraypart, sizeof (arraypart),
1978 gettext("N/A"));
1979 } else {
1980 (void) snprintf(arraypart, sizeof (arraypart),
1981 "%llu.%llu.%llu",
1982 arraypart_attr.tag.cidl.bus,
1983 arraypart_attr.tag.cidl.target_id,
1984 arraypart_attr.tag.cidl.lun);
1987 (void) fprintf(stdout, "\t\t%s\t", arraypart);
1988 (void) print_arraypart_attr(&arraypart_attr);
1989 (void) fprintf(stdout, "\n");
1990 arraypart_handle = raidcfg_list_next(arraypart_handle);
1993 return (SUCCESS);
1996 static int
1997 print_disk_table(raid_obj_handle_t ctl_handle, raid_obj_handle_t disk_handle)
1999 raidcfg_controller_t ctl_attr;
2000 raidcfg_disk_t disk_attr;
2001 raidcfg_prop_t *prop_attr, *prop_attr2;
2002 raid_obj_handle_t prop_handle;
2003 char disk[8];
2004 int ret;
2006 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
2007 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
2008 return (FAILURE);
2011 if ((ret = raidcfg_get_attr(disk_handle, &disk_attr)) < 0) {
2012 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
2013 return (FAILURE);
2016 /* Print header */
2017 (void) fprintf(stdout, gettext("Disk\tVendor Product "
2018 "Firmware\tCapacity\tStatus\tHSP"));
2019 (void) fprintf(stdout, "\n");
2020 (void) fprintf(stdout, "--------------------------------------");
2021 (void) fprintf(stdout, "--------------------------------------");
2022 (void) fprintf(stdout, "\n");
2025 (void) snprintf(disk, sizeof (disk), "%llu.%llu.%llu",
2026 disk_attr.tag.cidl.bus,
2027 disk_attr.tag.cidl.target_id,
2028 disk_attr.tag.cidl.lun);
2030 (void) fprintf(stdout, "%s\t", disk);
2032 (void) print_disk_attr(ctl_handle, disk_handle, &disk_attr);
2034 prop_attr = calloc(1, sizeof (raidcfg_prop_t));
2035 if (prop_attr == NULL) {
2036 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ERR_NOMEM));
2037 return (FAILURE);
2040 prop_handle = raidcfg_list_head(disk_handle, OBJ_TYPE_PROP);
2041 if (prop_handle == 0) {
2042 free(prop_attr);
2043 return (SUCCESS);
2046 do {
2047 prop_attr->prop_size = 0;
2048 if ((ret = raidcfg_get_attr(prop_handle, prop_attr)) < 0) {
2049 free(prop_attr);
2050 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
2051 return (FAILURE);
2053 if (prop_attr->prop_type == PROP_GUID)
2054 break;
2055 } while (prop_handle != 0);
2057 prop_attr2 = realloc(prop_attr,
2058 sizeof (raidcfg_prop_t) + prop_attr->prop_size);
2059 free(prop_attr);
2060 if (prop_attr2 == NULL) {
2061 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ERR_NOMEM));
2062 return (FAILURE);
2065 if ((ret = raidcfg_get_attr(prop_handle, prop_attr2)) < 0) {
2066 free(prop_attr2);
2067 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
2068 return (FAILURE);
2071 (void) fprintf(stdout, "GUID:%s\n", prop_attr2->prop);
2073 free(prop_attr2);
2074 return (SUCCESS);
2078 * print_ctl_attr(attrp)
2079 * This function prints attribute of specified controller, and return
2080 * result as SUCCESS or FAILURE.
2082 static int
2083 print_ctl_attr(raidcfg_controller_t *attrp)
2085 char type[CONTROLLER_TYPE_LEN];
2086 char version[CONTROLLER_FW_LEN];
2088 if (attrp == NULL) {
2089 return (FAILURE);
2092 (void) snprintf(type, sizeof (type), "%s", attrp->controller_type);
2093 (void) fprintf(stdout, "%-16s", type);
2095 (void) snprintf(version, sizeof (version), "%s", attrp->fw_version);
2096 (void) fprintf(stdout, "%s", version);
2098 return (SUCCESS);
2102 * print_array_attr(attrp)
2103 * This function prints attribute of specified array, and return
2104 * result as SUCCESS or FAILURE.
2106 static int
2107 print_array_attr(raidcfg_array_t *attrp)
2109 char capacity[8];
2110 char stripe_size[8];
2111 char raid_level[8];
2113 if (attrp == NULL) {
2114 return (FAILURE);
2117 if (attrp->capacity != MAX64BIT) {
2118 if (size_to_string(attrp->capacity, capacity, 8) != SUCCESS) {
2119 return (FAILURE);
2121 (void) printf("%s\t", capacity);
2122 } else {
2123 (void) printf(gettext("N/A\t"));
2126 if (attrp->stripe_size != MAX32BIT) {
2127 (void) snprintf(stripe_size, sizeof (stripe_size), "%uK",
2128 attrp->stripe_size / 1024);
2129 (void) printf("%s\t", stripe_size);
2130 } else {
2131 (void) printf(gettext("N/A\t"));
2134 if (attrp->state & ARRAY_STATE_INACTIVATE)
2135 (void) printf("%-8s", gettext("INACTIVE"));
2136 else {
2137 switch (attrp->state) {
2138 case ARRAY_STATE_OPTIMAL:
2139 (void) printf("%-8s", gettext("OPTIMAL"));
2140 break;
2141 case ARRAY_STATE_DEGRADED:
2142 (void) printf("%-8s", gettext("DEGRADED"));
2143 break;
2144 case ARRAY_STATE_FAILED:
2145 (void) printf("%-8s", gettext("FAILED"));
2146 break;
2147 case ARRAY_STATE_SYNC:
2148 (void) printf("%-8s", gettext("SYNC"));
2149 break;
2150 case ARRAY_STATE_MISSING:
2151 (void) printf("%-8s", gettext("MISSING"));
2152 break;
2153 default:
2154 (void) printf("%-8s", gettext("N/A"));
2155 break;
2158 (void) printf(" ");
2160 if (attrp->write_policy == CACHE_WR_OFF) {
2161 (void) printf(gettext("OFF"));
2162 } else if (attrp->write_policy == CACHE_WR_ON) {
2163 (void) printf(gettext("ON"));
2164 } else {
2165 (void) printf(gettext("N/A"));
2167 (void) printf("\t");
2169 switch (attrp->raid_level) {
2170 case RAID_LEVEL_0:
2171 (void) sprintf(raid_level, "RAID0");
2172 break;
2173 case RAID_LEVEL_1:
2174 (void) sprintf(raid_level, "RAID1");
2175 break;
2176 case RAID_LEVEL_1E:
2177 (void) sprintf(raid_level, "RAID1E");
2178 break;
2179 case RAID_LEVEL_5:
2180 (void) sprintf(raid_level, "RAID5");
2181 break;
2182 case RAID_LEVEL_10:
2183 (void) sprintf(raid_level, "RAID10");
2184 break;
2185 case RAID_LEVEL_50:
2186 (void) sprintf(raid_level, "RAID50");
2187 break;
2188 default:
2189 (void) snprintf(raid_level, sizeof (raid_level),
2190 gettext("N/A"));
2191 break;
2193 (void) printf("%s", raid_level);
2195 return (SUCCESS);
2199 * print_arraypart_attr(attrp)
2200 * This function print attribute of specified arraypart, and return
2201 * result as SUCCESS or FAILURE.
2203 static int
2204 print_arraypart_attr(raidcfg_arraypart_t *attrp)
2206 char size[8];
2208 if (attrp == NULL) {
2209 return (FAILURE);
2212 if (attrp->size != MAX64BIT) {
2213 if (size_to_string(attrp->size, size, 8) != SUCCESS) {
2214 return (FAILURE);
2216 (void) printf("%s\t", size);
2217 } else {
2218 (void) printf(gettext("N/A\t"));
2221 (void) printf("\t");
2223 if (attrp->state == DISK_STATE_GOOD) {
2224 (void) printf(gettext("GOOD"));
2225 } else if (attrp->state == DISK_STATE_FAILED) {
2226 (void) printf(gettext("FAILED"));
2227 } else {
2228 (void) printf(gettext("N/A"));
2230 (void) printf("\t");
2232 return (SUCCESS);
2236 * print_disk_attr(ctl_handle, disk_handle, attrp)
2237 * This function prints attribute of specified disk, and return
2238 * result as SUCCESS or FAILURE.
2240 static int
2241 print_disk_attr(raid_obj_handle_t ctl_handle, raid_obj_handle_t disk_handle,
2242 raidcfg_disk_t *attrp)
2244 char vendor[DISK_VENDER_LEN + 1];
2245 char product[DISK_PRODUCT_LEN + 1];
2246 char revision[DISK_REV_LEN + 1];
2247 char capacity[16];
2248 char hsp[16];
2250 raid_obj_handle_t hsp_handle;
2251 raidcfg_hsp_t hsp_attr;
2252 raidcfg_controller_t ctl_attr;
2253 int ret;
2254 char is_indent;
2256 if (attrp == NULL) {
2257 return (FAILURE);
2260 (void) memccpy(vendor, attrp->vendorid, '\0', DISK_VENDER_LEN);
2261 vendor[DISK_VENDER_LEN] = '\0';
2262 (void) printf("%-9s", vendor);
2264 (void) memccpy(product, attrp->productid, '\0', DISK_PRODUCT_LEN);
2265 product[DISK_PRODUCT_LEN] = '\0';
2266 (void) printf("%-17s", product);
2268 (void) memccpy(revision, attrp->revision, '\0', DISK_REV_LEN);
2269 revision[DISK_REV_LEN] = '\0';
2270 (void) printf("%s\t\t", revision);
2272 if (attrp->capacity != MAX64BIT) {
2273 if (size_to_string(attrp->capacity, capacity, 16) != SUCCESS) {
2274 return (FAILURE);
2276 (void) printf("%s\t\t", capacity);
2277 } else {
2278 (void) printf(gettext("N/A"));
2281 if (attrp->state == DISK_STATE_GOOD) {
2282 (void) printf(gettext("GOOD"));
2283 } else if (attrp->state == DISK_STATE_FAILED) {
2284 (void) printf(gettext("FAILED"));
2285 } else {
2286 (void) printf(gettext("N/A"));
2288 (void) printf("\t");
2290 /* Controller attribute */
2291 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
2292 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
2293 return (FAILURE);
2296 hsp_handle = raidcfg_list_head(disk_handle, OBJ_TYPE_HSP);
2297 if (hsp_handle == 0) {
2298 (void) printf(gettext("N/A\n"));
2299 } else {
2300 is_indent = FALSE;
2301 while (hsp_handle > 0) {
2302 if ((ret = raidcfg_get_attr(hsp_handle,
2303 &hsp_attr)) < 0) {
2304 (void) fprintf(stderr, "%s\n",
2305 raidcfg_errstr(ret));
2306 return (FAILURE);
2309 if (is_indent == TRUE) {
2310 (void) printf("\t\t\t\t\t\t\t");
2311 } else {
2312 is_indent = TRUE;
2315 if (hsp_attr.type == HSP_TYPE_LOCAL) {
2316 (void) snprintf(hsp, sizeof (hsp),
2317 "c%ut%llud%llu",
2318 ctl_attr.controller_id,
2319 hsp_attr.tag.idl.target_id,
2320 hsp_attr.tag.idl.lun);
2321 (void) printf("%s\n", hsp);
2322 } else if (hsp_attr.type == HSP_TYPE_GLOBAL) {
2323 (void) printf(gettext("Global\n"));
2324 } else {
2325 return (FAILURE);
2328 hsp_handle = raidcfg_list_next(hsp_handle);
2331 return (SUCCESS);
2336 * print_indent(indent)
2337 * This function prints specified number of tab characters. It's used to
2338 * format layout.
2340 static void
2341 print_indent(uint8_t indent)
2343 uint32_t i;
2344 for (i = 0; i < indent; i++) {
2345 (void) fprintf(stdout, "\t");
2350 * get_disk_handle_cidl(ctl_tag, disks_argp, comps_num, handlespp)
2351 * This function parses the string of disk argument, and gets the disks tag
2352 * and separators from the string. Then it translates the tag to handle, and
2353 * stores handles and separators to new buffer pointed by parameter handlespp.
2354 * The format of disk_arg must be C:ID:L, for example, it is 0.1.0. The first
2355 * "0" is channel number, and the second "1" is target number, and the third
2356 * "0" is LUN number. The disk tags are separated by comma and parenthesis.
2357 * Function returns SUCCESS or FAILURE.
2359 static int
2360 get_disk_handle_cidl(uint32_t ctl_tag, char *disks_argp, int *comps_nump,
2361 raid_obj_handle_t **handlespp)
2363 int len = 0;
2364 int i = 0, j = 0;
2365 char *p, *t;
2366 char *delimit = " ";
2367 char *disks_str;
2368 disk_tag_t disk_tag;
2370 if (disks_argp == NULL || comps_nump == NULL) {
2371 return (FAILURE);
2374 p = disks_argp;
2375 len = strlen(disks_argp);
2377 if ((disks_str = (char *)malloc(3 * len + 4)) == NULL) {
2378 return (FAILURE);
2381 /* Insert whitespace between disk tags, '(' , and ')' */
2382 disks_str[j ++] = '(';
2383 disks_str[j ++] = ' ';
2385 while (p[i] != '\0') {
2386 if (p[i] == ')' || p[i] == '(') {
2387 disks_str[j ++] = ' ';
2388 disks_str[j ++] = p[i];
2389 disks_str[j ++] = ' ';
2390 } else
2391 disks_str[j ++] = p[i];
2392 i ++;
2394 disks_str[j ++] = ' ';
2395 disks_str[j ++] = ')';
2396 disks_str[j] = '\0';
2398 len = strlen(disks_str) + 1;
2400 if ((t = (char *)malloc(len)) == NULL) {
2401 return (FAILURE);
2403 (void) memcpy(t, disks_str, len);
2404 p = strtok(t, delimit);
2405 while (p != NULL) {
2406 (*comps_nump)++;
2407 p = strtok(NULL, delimit);
2409 free(t);
2411 *handlespp = calloc(*comps_nump, sizeof (raid_obj_handle_t));
2412 if (*handlespp == NULL) {
2413 return (FAILURE);
2416 for (i = 0; i < *comps_nump; i++)
2417 (*handlespp)[i] = INIT_HANDLE_VALUE;
2419 i = 0;
2420 p = strtok(disks_str, delimit);
2421 while (p != NULL) {
2422 if (*p == '(') {
2423 (*handlespp)[i] = OBJ_SEPARATOR_BEGIN;
2424 } else if (*p == ')') {
2425 (*handlespp)[i] = OBJ_SEPARATOR_END;
2426 } else {
2427 if (get_disk_tag_cidl(p, &disk_tag) != SUCCESS) {
2428 free(*handlespp);
2429 free(disks_str);
2430 return (INVALID_ARG);
2432 (*handlespp)[i] =
2433 raidcfg_get_disk(raidcfg_get_controller(ctl_tag),
2434 disk_tag);
2435 if ((*handlespp)[i] <= 0) {
2436 (void) fprintf(stderr, "%s\n",
2437 raidcfg_errstr((*handlespp)[i]));
2438 free(*handlespp);
2439 free(disks_str);
2440 return (FAILURE);
2443 p = strtok(NULL, delimit);
2444 i++;
2447 free(disks_str);
2448 return (SUCCESS);
2452 * get_disk_handle_ctd(disks_num, disks_argpp, ctl_tagp, disks_handlep)
2453 * This function parses string of single disk with "ctd" format, for example,
2454 * c0t0d0, and translates it to controller tag and disk tag.
2455 * Then it calls lib api and get disk handle. The controller tag and disk
2456 * handle are both returned by out parameters.
2457 * The return value is SUCCESS or FAILURE.
2459 static int
2460 get_disk_handle_ctd(int disks_num, char **disks_argpp, uint32_t *ctl_tagp,
2461 raid_obj_handle_t *disks_handlep)
2463 raid_obj_handle_t ctl_handle;
2464 disk_tag_t disk_tag;
2465 uint32_t ctl_id;
2466 int i;
2467 int ret;
2469 if (disks_handlep == NULL) {
2470 return (FAILURE);
2473 for (i = 0; i < disks_num; i++) {
2474 if (get_disk_tag_ctd(disks_argpp[i], &disk_tag, &ctl_id) !=
2475 SUCCESS) {
2476 return (INVALID_ARG);
2479 *ctl_tagp = ctl_id;
2481 if (i == 0) {
2482 ctl_handle = raidcfg_get_controller(*ctl_tagp);
2483 if (ctl_handle <= 0) {
2484 (void) fprintf(stderr, "%s\n",
2485 raidcfg_errstr(ctl_handle));
2486 return (FAILURE);
2488 ret = raidcfg_open_controller(ctl_handle, NULL);
2489 if (ret < 0) {
2490 (void) fprintf(stderr, "%s\n",
2491 raidcfg_errstr(ret));
2492 return (FAILURE);
2496 if ((disks_handlep[i] =
2497 raidcfg_get_disk(ctl_handle, disk_tag)) < 0) {
2498 (void) fprintf(stderr, "%s\n",
2499 raidcfg_errstr(disks_handlep[i]));
2500 (void) raidcfg_close_controller(ctl_handle, NULL);
2501 return (FAILURE);
2505 return (SUCCESS);
2509 * get_ctl_tag(argp)
2510 * This function translates controller string to tag. The return value is
2511 * SUCCESS if the string has legal format and is parsed successfully,
2512 * or FAILURE if it fails.
2514 static int
2515 get_ctl_tag(char *argp, uint32_t *ctl_tagp)
2517 if (argp == NULL || is_fully_numeric(argp) == FALSE ||
2518 ctl_tagp == NULL) {
2519 return (FAILURE);
2521 *ctl_tagp = (atoi(argp));
2522 return (SUCCESS);
2526 * get_array_tag(argp, ctl_tagp, array_tagp)
2527 * This function parses array string to get array tag and controller tag.
2528 * The return value is SUCCESS if the string has legal format, or
2529 * FAILURE if it fails.
2531 static int
2532 get_array_tag(char *argp, uint32_t *ctl_tagp, array_tag_t *array_tagp)
2534 char *t = NULL;
2535 char *cp = NULL;
2536 char *tp = NULL;
2537 char *dp = NULL;
2539 uint32_t value_c = MAX32BIT;
2540 uint32_t value_t = MAX32BIT;
2541 uint32_t value_d = MAX32BIT;
2543 int len = 0;
2545 if (argp == NULL || (len = strlen(argp)) == 0 ||
2546 array_tagp == NULL) {
2547 return (FAILURE);
2550 t = (char *)malloc(len + 1);
2551 if (t == NULL) {
2552 return (FAILURE);
2555 (void) memcpy(t, argp, len + 1);
2557 /* Now remmber to release t memory if exception occurs */
2558 if (((dp = strchr(t, 'd')) == NULL) ||
2559 ((tp = strchr(t, 't')) == NULL) ||
2560 ((cp = strchr(t, 'c')) == NULL)) {
2561 free(t);
2562 return (FAILURE);
2564 cp = t;
2566 *dp = '\0';
2567 dp++;
2568 *tp = '\0';
2569 tp++;
2570 cp++;
2572 if (is_fully_numeric(dp) == FALSE ||
2573 is_fully_numeric(tp) == FALSE ||
2574 is_fully_numeric(cp) == FALSE) {
2575 free(t);
2576 return (FAILURE);
2579 value_c = atoi(cp);
2580 value_t = atoi(tp);
2581 value_d = atoi(dp);
2583 array_tagp->idl.target_id = value_t;
2584 array_tagp->idl.lun = value_d;
2586 if (ctl_tagp != NULL) {
2587 *ctl_tagp = value_c;
2590 free(t);
2591 return (SUCCESS);
2595 * get_disk_tag_ctd(argp, disk_tagp)
2596 * This function parses disk string of ctd format, and translates it to
2597 * disk tag and controller tag. The tags is returned by out parameters.
2598 * The return value is SUCCESS if the string has legal format, or FAILURE
2599 * if it fails.
2601 static int
2602 get_disk_tag_ctd(char *argp, disk_tag_t *disk_tagp, uint32_t *ctl_tag)
2604 char *t = NULL;
2605 char *cp = NULL;
2606 char *tp = NULL;
2607 char *dp = NULL;
2609 uint32_t value_c = MAX32BIT;
2610 uint32_t value_t = MAX32BIT;
2611 uint32_t value_d = MAX32BIT;
2613 int len = 0;
2615 if (argp == NULL || (len = strlen(argp)) == 0 ||
2616 disk_tagp == NULL) {
2617 return (FAILURE);
2620 t = (char *)malloc(len + 1);
2621 if (t == NULL) {
2622 return (FAILURE);
2625 (void) memcpy(t, argp, len + 1);
2627 /* Now remmber to release t memory if exception occurs */
2628 if (((dp = strchr(t, 'd')) == NULL) ||
2629 ((tp = strchr(t, 't')) == NULL) ||
2630 ((cp = strchr(t, 'c')) == NULL)) {
2631 free(t);
2632 return (FAILURE);
2634 cp = t;
2636 *dp = '\0';
2637 dp++;
2638 *tp = '\0';
2639 tp++;
2640 cp++;
2642 if (is_fully_numeric(dp) == FALSE ||
2643 is_fully_numeric(tp) == FALSE ||
2644 is_fully_numeric(cp) == FALSE) {
2645 free(t);
2646 return (FAILURE);
2649 value_c = atoi(cp);
2650 value_t = atoi(tp);
2651 value_d = atoi(dp);
2653 disk_tagp->cidl.bus = 0;
2654 disk_tagp->cidl.target_id = value_t;
2655 disk_tagp->cidl.lun = value_d;
2656 *ctl_tag = value_c;
2658 free(t);
2659 return (SUCCESS);
2663 * get_disk_tag_cidl(argp, disk_tagp)
2664 * This function parses disk string of cidl format and translates it to tag.
2665 * The return value is disk tag if the string has legal format, or FAILURE
2666 * if it fails.
2668 static int
2669 get_disk_tag_cidl(char *argp, disk_tag_t *disk_tagp)
2671 int len = 0;
2672 char *p = NULL;
2673 char *t = NULL;
2674 char *dot1p = NULL;
2675 char *dot2p = NULL;
2677 if (argp == NULL || (len = strlen(argp)) == 0) {
2678 return (FAILURE);
2681 if (disk_tagp == NULL) {
2682 return (FAILURE);
2685 t = (char *)malloc(len + 1);
2686 if (t == NULL) {
2687 return (FAILURE);
2690 (void) memcpy(t, argp, len + 1);
2691 p = t;
2693 dot2p = strrchr(p, '.');
2694 if (dot2p == NULL) {
2695 free(t);
2696 return (FAILURE);
2698 *dot2p = '\0';
2699 dot2p++;
2701 dot1p = strrchr(p, '.');
2702 if (dot1p == NULL) {
2703 free(t);
2704 return (FAILURE);
2706 *dot1p = '\0';
2707 dot1p++;
2709 /* Assert only 2 dots in this string */
2710 if (strrchr(p, '.') != NULL) {
2711 free(t);
2712 return (FAILURE);
2715 while (*p == ' ')
2716 p++;
2718 if (is_fully_numeric(p) == FALSE ||
2719 is_fully_numeric(dot1p) == FALSE ||
2720 is_fully_numeric(dot2p) == FALSE) {
2721 free(t);
2722 return (FAILURE);
2725 disk_tagp->cidl.bus = atoi(p);
2726 disk_tagp->cidl.target_id = atoi(dot1p);
2727 disk_tagp->cidl.lun = atoi(dot2p);
2729 free(t);
2730 return (SUCCESS);
2734 * calc_size(sizep, valp)
2735 * This function calculates the value represented by string sizep.
2736 * The string sizep can be decomposed into three parts: an initial,
2737 * possibly empty, sequence of white-space characters; a subject digital
2738 * sequence interpreted as an integer with unit k/K/m/M/g/G/t/T; and a
2739 * final string of one or more unrecognized characters or white-sapce
2740 * characters, including the terminating null. If unrecognized character
2741 * exists or overflow happens, the conversion must fail and return
2742 * INVALID_ARG. If the conversion is performed successfully, result will
2743 * be saved into valp and function returns SUCCESS. It returns FAILURE
2744 * when memory allocation fails.
2746 static int
2747 calc_size(char *sizep, uint64_t *valp)
2749 int len;
2750 uint64_t size;
2751 uint64_t unit;
2752 char *t = NULL;
2753 char *tailp = NULL;
2755 if (sizep == NULL || valp == NULL) {
2756 return (INVALID_ARG);
2759 if (is_fully_numeric(sizep) == TRUE) {
2760 *valp = atoi(sizep);
2761 return (SUCCESS);
2764 len = strlen(sizep);
2765 if (len == 0) {
2766 return (INVALID_ARG);
2769 t = (char *)malloc(len + 1);
2770 if (t == NULL) {
2771 return (FAILURE);
2774 (void) memcpy(t, sizep, len + 1);
2776 switch (*(t + len - 1)) {
2777 case 'k':
2778 case 'K':
2779 unit = 1024ull;
2780 errno = 0;
2781 size = strtoll(t, &tailp, 0);
2782 break;
2783 case 'm':
2784 case 'M':
2785 unit = 1024ull * 1024ull;
2786 errno = 0;
2787 size = strtoll(t, &tailp, 0);
2788 break;
2789 case 'g':
2790 case 'G':
2791 unit = 1024ull * 1024ull * 1024ull;
2792 errno = 0;
2793 size = strtoll(t, &tailp, 0);
2794 break;
2795 case 't':
2796 case 'T':
2797 unit = 1024ull * 1024ull * 1024ull * 1024ull;
2798 errno = 0;
2799 size = strtoll(t, &tailp, 0);
2800 break;
2801 default:
2802 /* The unit must be kilobyte at least. */
2803 free(t);
2804 return (INVALID_ARG);
2807 *(t + len - 1) = '\0';
2808 if (is_fully_numeric(t) != TRUE) {
2809 free(t);
2810 return (INVALID_ARG);
2813 errno = 0;
2814 size = strtoll(t, &tailp, 0);
2816 /* Check overflow condition */
2817 if (errno == ERANGE || (size > (MAX64BIT / unit))) {
2818 free(t);
2819 return (INVALID_ARG);
2822 *valp = size * unit;
2823 free(t);
2824 return (SUCCESS);
2828 * is_fully_numeric(str)
2829 * This function checks if the string are legal numeric string. The beginning
2830 * or ending characters can be white spaces.
2831 * Return value is TRUE if the string are legal numeric string, or FALSE
2832 * otherwise.
2834 static int
2835 is_fully_numeric(char *strp)
2837 uint32_t len;
2838 uint32_t i;
2840 if (strp == NULL) {
2841 return (FALSE);
2844 len = strlen(strp);
2845 if (len == 0) {
2846 return (FALSE);
2849 /* Skip whitespace characters */
2850 for (i = 0; i < len; i++) {
2851 if (strp[i] != ' ') {
2852 break;
2856 /* if strp points all space characters */
2857 if (i == len) {
2858 return (FALSE);
2861 /* Check the digitals in string */
2862 for (; i < len; i++) {
2863 if (!isdigit(strp[i])) {
2864 break;
2868 /* Check the ending string */
2869 for (; i < len; i++) {
2870 if (strp[i] != ' ') {
2871 return (FALSE);
2875 return (TRUE);
2878 static int
2879 yes(void)
2881 int i, b;
2882 char ans[SCHAR_MAX + 1];
2884 for (i = 0; ; i++) {
2885 b = getchar();
2886 if (b == '\n' || b == '\0' || b == EOF) {
2887 ans[i] = 0;
2888 break;
2890 if (i < SCHAR_MAX) {
2891 ans[i] = b;
2894 if (i >= SCHAR_MAX) {
2895 i = SCHAR_MAX;
2896 ans[SCHAR_MAX] = 0;
2899 return (rpmatch(ans));
2903 * Function: int rpmatch(char *)
2905 * Description:
2907 * Internationalized get yes / no answer.
2909 * Inputs:
2910 * s -> Pointer to answer to compare against.
2912 * Returns:
2913 * TRUE -> Answer was affirmative
2914 * FALSE -> Answer was negative
2917 static int
2918 rpmatch(char *s)
2920 int status;
2922 /* match yesexpr */
2923 status = regexec(&re, s, (size_t)0, NULL, 0);
2924 if (status != 0) {
2925 return (FALSE);
2927 return (TRUE);
2930 static int
2931 size_to_string(uint64_t size, char *string, int len)
2933 int i = 0;
2934 uint32_t remainder;
2935 char unit[][2] = {" ", "K", "M", "G", "T"};
2937 if (string == NULL) {
2938 return (FAILURE);
2940 while (size > 1023) {
2941 remainder = size % 1024;
2942 size /= 1024;
2943 i++;
2946 if (i > 4) {
2947 return (FAILURE);
2950 remainder /= 103;
2951 if (remainder == 0) {
2952 (void) snprintf(string, len, "%llu", size);
2953 } else {
2954 (void) snprintf(string, len, "%llu.%1u", size,
2955 remainder);
2958 /* make sure there is one byte for unit */
2959 if ((strlen(string) + 1) >= len) {
2960 return (FAILURE);
2962 (void) strlcat(string, unit[i], len);
2964 return (SUCCESS);
2968 * Only one raidctl is running at one time.
2970 static int
2971 enter_raidctl_lock(int *fd)
2973 int fd0 = -1;
2974 struct flock lock;
2976 fd0 = open(RAIDCTL_LOCKF, O_CREAT|O_WRONLY, 0600);
2977 if (fd0 < 0) {
2978 if (errno == EACCES) {
2979 (void) fprintf(stderr,
2980 gettext("raidctl:must be root to run raidctl"
2981 ": %s\n"), strerror(errno));
2982 } else {
2983 (void) fprintf(stderr,
2984 gettext("raidctl:failed to open lockfile"
2985 " '"RAIDCTL_LOCKF"': %s\n"), strerror(errno));
2987 return (FAILURE);
2990 *fd = fd0;
2991 lock.l_type = F_WRLCK;
2992 lock.l_whence = SEEK_SET;
2993 lock.l_start = 0;
2994 lock.l_len = 0;
2996 if ((fcntl(fd0, F_SETLK, &lock) == -1) &&
2997 (errno == EAGAIN || errno == EDEADLK)) {
2998 if (fcntl(fd0, F_GETLK, &lock) == -1) {
2999 (void) fprintf(stderr,
3000 gettext("raidctl:enter_filelock error\n"));
3001 return (FAILURE);
3003 (void) fprintf(stderr, gettext("raidctl:"
3004 "enter_filelock:filelock is owned "
3005 "by 'process %d'\n"), lock.l_pid);
3006 return (FAILURE);
3009 return (SUCCESS);
3012 static void
3013 exit_raidctl_lock(int fd)
3015 struct flock lock;
3017 lock.l_type = F_UNLCK;
3018 lock.l_whence = SEEK_SET;
3019 lock.l_start = 0;
3020 lock.l_len = 0;
3021 if (fcntl(fd, F_SETLK, &lock) == -1) {
3022 (void) fprintf(stderr, gettext("raidctl: failed to"
3023 " exit_filelock: %s\n"),
3024 strerror(errno));
3026 (void) close(fd);