raidctl.c revision 317fb4ac3931ab67c3f66b6fd0e0f7f8a1727bc9
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* raidctl.c is the entry file of RAID configuration utility.
*/
#include <ctype.h>
#include <fcntl.h>
#include <langinfo.h>
#include <regex.h>
#include <locale.h>
#include <libintl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <errno.h>
#include <libgen.h>
#include <raidcfg.h>
#define TRUE 1
#define FALSE 0
#ifndef TEXT_DOMAIN
#define TEXT_DOMAIN "SYS_TEST"
#endif
/*
* Return value of command
*/
#define SUCCESS 0
#define INVALID_ARG 1
#define FAILURE 2
/*
* Initial value of variables
*/
#define INIT_HANDLE_VALUE -3
#define MAX64BIT 0xffffffffffffffffull
#define MAX32BIT 0xfffffffful
/*
* Flag of set or unset HSP
*/
#define HSP_SET 1
#define HSP_UNSET 0
/*
* Operate codes of command
*/
#define DO_HW_RAID_NOP -1
#define DO_HW_RAID_HELP 0
#define DO_HW_RAID_CREATEO 1
#define DO_HW_RAID_CREATEN 2
#define DO_HW_RAID_DELETE 3
#define DO_HW_RAID_LIST 4
#define DO_HW_RAID_FLASH 5
#define DO_HW_RAID_HSP 6
#define DO_HW_RAID_SET_ATTR 7
#define DO_HW_RAID_SNAPSHOT 8
#define LOWER_H (1 << 0)
/* Add a ARRAY state (temporary) */
#define ARRAY_STATE_SYNC 100
/*
* Function and strings to properly localize our prompt.
* english.
*/
#ifndef SCHAR_MAX
#define SCHAR_MAX 10
#endif
#define RAIDCTL_LOCKF "/var/run/lockf_raidctl"
/* Locale setting */
static int yes(void);
static int rpmatch(char *s);
static char *default_yesexpr = "^[yY]";
static char *default_yesstr = "yes";
static char *default_nostr = "no";
#define SET_DEFAULT_STRS \
yesexpr = default_yesexpr; \
yesstr = default_yesstr; \
#define FREE_STRS \
if (yesexpr != default_yesexpr) \
if (yesstr != default_yesstr) \
if (nostr != default_nostr) \
/* program name */
static char *prog_namep;
/*
* Functions declaration
*/
static void helpinfo(char *prog_namep);
static int is_fully_numeric(char *strp);
static int enter_raidctl_lock(int *fd);
static void exit_raidctl_lock(int fd);
/*
* Entry function of raidctl command
*/
int
{
/* operation index */
/* argument pointers */
/*
* operation flags.
*/
/* index and temporary variables */
int ret;
int status;
char c = '\0';
/* fd for the filelock */
int fd;
return (FAILURE);
}
(void) textdomain(TEXT_DOMAIN);
/* parse command line, and get program name */
prog_namep = argv[0];
} else {
prog_namep++;
}
/* close error option messages from getopt */
opterr = 0;
/* get yes expression according to current locale */
return (FAILURE);
}
/*
* If the was no expression or if there is a compile error
* use default yes expression.
*/
(status != 0)) {
REG_EXTENDED | REG_NOSUB) != 0) {
return (FALSE);
}
}
"?hC:cdlF:r:z:g:a:s:p:fS")) != EOF) {
switch (c) {
case 'h':
case '?':
} else {
}
break;
case 'C':
} else {
}
break;
case 'c':
} else {
}
break;
case 'd':
} else {
}
break;
case 'l':
} else {
}
break;
case 'F':
} else {
}
break;
case 'a':
} else {
}
break;
case 'p':
} else {
}
break;
case 'r':
break;
case 'z':
break;
case 'g':
break;
case 's':
break;
case 'f':
break;
case 'S':
} else {
}
break;
default:
gettext("Invalid argument(s).\n"));
return (INVALID_ARG);
}
}
/* parse options */
switch (findex) {
case DO_HW_RAID_HELP:
ret = INVALID_ARG;
} else {
}
break;
case DO_HW_RAID_CREATEO:
ret = INVALID_ARG;
} else {
} else {
}
}
break;
case DO_HW_RAID_CREATEN:
LOWER_S)) != 0) {
ret = INVALID_ARG;
} else {
}
break;
case DO_HW_RAID_DELETE:
ret = INVALID_ARG;
} else {
}
break;
case DO_HW_RAID_LIST:
ret = INVALID_ARG;
} else {
}
break;
case DO_HW_RAID_SNAPSHOT:
ret = INVALID_ARG;
} else {
}
break;
case DO_HW_RAID_FLASH:
ret = INVALID_ARG;
} else {
argc - 3);
} else {
argc - 4);
}
}
break;
case DO_HW_RAID_HSP:
ret = INVALID_ARG;
} else {
}
break;
case DO_HW_RAID_SET_ATTR:
ret = INVALID_ARG;
} else {
}
break;
case DO_HW_RAID_NOP:
if (argc == 1) {
} else {
ret = INVALID_ARG;
}
break;
default:
ret = INVALID_ARG;
break;
}
if (ret == INVALID_ARG) {
gettext("Invalid argument(s).\n"));
}
return (ret);
}
/*
* helpinfo(prog_namep)
* This function prints help informations for usrs.
*/
static void
helpinfo(char *prog_namep)
{
char quote = '"';
"[-z <capacity>] [-s <stripe_size>] <controller>\n"), prog_namep,
"[<controller2> ...]\n"), prog_namep);
"[<disk3> ...]\n"), prog_namep);
"{<volume> | <controller>}\n"), prog_namep);
}
/*
* do_create_cidl(raid_levelp, capacityp, disks_argp, stripe_sizep,
* f_flag, argv, optind)
* This function creates a new RAID volume with specified arguments,
* and returns result as SUCCESS, INVALID_ARG or FAILURE.
* The "c.id.l" is used to express single physical disk. 'c' expresses
* bus number, 'id' expresses target number, and 'l' expresses lun.
* The physical disks represented by c.id.l may be invisible to OS, which
* means physical disks attached to controllers are not accessible by
* OS directly. The disks should be organized as a logical volume, and
* the logical volume is exported to OS as a single unit. Some hardware
* RAID controllers also support physical disks accessed by OS directly,
* for example LSI1068. In this case, it's both OK to express physical
* disk by c.id.l format or canonical ctd format.
*/
static int
{
int comps_num = 0;
int ret = 0;
return (INVALID_ARG);
}
if (disks_argp == NULL) {
return (INVALID_ARG);
}
/* Check controller tag */
return (INVALID_ARG);
}
if (ctl_handle <= 0) {
return (FAILURE);
}
return (FAILURE);
}
/* Get raid level */
if (raid_levelp != NULL) {
if (*raid_levelp == '1' &&
} else {
return (INVALID_ARG);
}
switch (atoi(raid_levelp)) {
case 0:
break;
case 1:
break;
case 5:
break;
case 10:
break;
case 50:
break;
default:
return (INVALID_ARG);
}
}
}
/*
* The rang check of capacity and stripe size is performed in library,
* and it relates to hardware feature.
*/
/* Capacity in bytes. Capacity 0 means max available space. */
if (*capacityp == '-' ||
return (INVALID_ARG);
}
}
/* Stripe size in bytes */
if (stripe_sizep != NULL) {
*stripe_sizep == '-') {
return (INVALID_ARG);
}
}
/* Open controller before accessing its object */
return (FAILURE);
}
/* Get disks' handles */
&disk_handlesp)) != SUCCESS) {
return (ret);
}
"will destroy all data on spare space of member disks, "
if (!yes()) {
"not created.\n\n"));
return (SUCCESS);
}
}
/* Create array */
if (array_handle <= 0) {
return (FAILURE);
}
/* Get attribute of the new created array */
return (FAILURE);
}
/* Print attribute of array */
/* Close controller */
return (SUCCESS);
}
/*
* do_create_ctd(raid_levelp, disks_argpp, disks_num, argindex, f_flag)
* This function creates array with specified arguments, and return result
* as SUCCESS, FAILURE, or INVALID_ARG. It only supports LSI MPT controller
* to be compatible with old raidctl. The capacity and stripe size can't
* be specified for LSI MPT controller, and they use zero and default value.
* The "ctd" is the canonical expression of physical disks which are
* accessible by OS.
*/
static int
{
int ret;
int i, j;
/* Check disks parameter */
return (INVALID_ARG);
}
if (disks_argpp[j] == NULL) {
return (INVALID_ARG);
}
}
/*
* We need check if the raid_level string is fully numeric. If user
* input string with unsupported letters, such as "s10", atoi() will
* return zero because it is an illegal string, but it doesn't mean
* RAID_LEVEL_0.
*/
if (raid_levelp != NULL) {
if (*raid_levelp == '1' &&
} else {
return (INVALID_ARG);
}
switch (atoi(raid_levelp)) {
case 0:
break;
case 1:
break;
case 5:
break;
default:
return (INVALID_ARG);
}
}
}
/* Get disks tag and controller tag */
sizeof (raid_obj_handle_t));
if (disk_handlesp == NULL) {
return (FAILURE);
}
return (ret);
}
/* LIB API should check whether all disks here belong to one ctl. */
/* get_disk_handle_ctd has opened controller. */
if (ctl_handle <= 0) {
return (FAILURE);
}
/* Check if the controller is host raid type */
return (FAILURE);
}
/* -c only support host raid controller, return failure here */
gettext("Option -c only supports host raid controller.\n"));
return (FAILURE);
}
"will destroy all data on spare space of member disks, "
if (!yes()) {
"not created.\n\n"));
return (SUCCESS);
}
}
/*
* For old raidctl, capacity is 0, which means to creates
* max possible capacity of array.
*/
if (array_handle <= 0) {
return (FAILURE);
}
/* Get attribute of array */
return (FAILURE);
}
/* Close controller */
/* Print feedback for user */
gettext("Volume c%ut%llud%llu is created successfully!\n"),
return (SUCCESS);
}
/*
* do_list(disk_arg, argv, optind, is_snapshot)
* This function lists RAID's system configuration. It supports various RAID
* controller. The return value can be SUCCESS, FAILURE, or INVALID_ARG.
*/
static int
{
int ret;
/* print RAID system */
return (ret);
} else {
!= SUCCESS) {
ret = INVALID_ARG;
optind++;
continue;
}
if (ctl_handle <= 0) {
optind++;
continue;
}
ret =
NULL);
if (ret < 0) {
optind++;
continue;
}
if (is_snapshot == FALSE) {
ret =
} else {
ret =
FALSE, 0, is_snapshot);
}
(void) raidcfg_close_controller(
ctl_handle, NULL);
optind++;
}
} else {
return (INVALID_ARG);
}
if (ctl_handle <= 0) {
return (FAILURE);
}
if (ret < 0) {
return (FAILURE);
}
if (array_handle <= 0) {
(void) raidcfg_close_controller(
ctl_handle, NULL);
return (FAILURE);
}
if (is_snapshot == FALSE) {
} else {
FALSE, is_snapshot);
}
(void) raidcfg_close_controller(
ctl_handle, NULL);
}
}
} else {
return (INVALID_ARG);
}
return (INVALID_ARG);
}
if (ctl_handle <= 0) {
return (FAILURE);
}
return (INVALID_ARG);
}
if (ret < 0) {
return (FAILURE);
}
if (disk_handle <= 0) {
return (FAILURE);
}
if (is_snapshot == FALSE) {
} else {
}
}
return (ret);
}
/*
* do_delete(f_flag, argv, optind)
* This function deletes a specified array, and return result as SUCCESS,
* FAILURE or INVALID_ARG.
*/
static int
{
char *array_argp;
int ret;
return (INVALID_ARG);
}
return (INVALID_ARG);
}
if (ctl_handle <= 0) {
return (INVALID_ARG);
}
if (ret < 0) {
return (FAILURE);
}
if (array_handle <= 0) {
return (FAILURE);
}
"%s will destroy all data it contains, "
if (!yes()) {
"%s not deleted.\n\n"), array_argp);
return (SUCCESS);
}
}
return (FAILURE);
}
return (SUCCESS);
}
/*
* do_flash(f_flag, filep, ctls_argpp, index, ctl_num)
* This function downloads and updates firmware for specified controller, and
* return result as SUCCESS, FAILURE or INVALID_ARG.
*/
static int
{
int ret;
int i, j;
if (ctl_num == 0)
return (INVALID_ARG);
ctl_argp = ctls_argpp[j];
return (INVALID_ARG);
}
/* Ask user to confirm operation. */
if (!yes()) {
gettext("Controller %d not "
"flashed.\n\n"), ctl_tag);
return (SUCCESS);
}
}
return (FAILURE);
}
if (ret < 0) {
return (FAILURE);
}
"c%u firmware....\n"), ctl_tag);
return (FAILURE);
}
"c%u firmware successfully.\n"), ctl_tag);
}
return (SUCCESS);
}
/*
* do_set_hsp(a_argp, disk_argp, argv, optind)
* This function set or unset HSP relationship between disk and controller/
* array, and return result as SUCCESS, FAILURE or INVALID_ARG.
*/
static int
{
int ret;
int hsp_type;
return (INVALID_ARG);
}
} else {
return (INVALID_ARG);
}
return (INVALID_ARG);
}
return (INVALID_ARG);
/* Global HSP */
hsp_type = 0;
return (INVALID_ARG);
}
return (INVALID_ARG);
}
if (ctl_handle <= 0) {
return (FAILURE);
}
if (ret < 0) {
return (FAILURE);
}
if (disk_handle <= 0) {
return (FAILURE);
}
} else {
/* Local HSP */
hsp_type = 1;
SUCCESS) {
return (INVALID_ARG);
}
/* Open controller */
if (ctl_handle <= 0) {
return (FAILURE);
}
if (ret < 0) {
return (FAILURE);
}
/* Get controller's attribute */
return (FAILURE);
}
return (INVALID_ARG);
}
/* Get disk handle */
if (disk_handle <= 0) {
return (FAILURE);
}
/* Get array handle */
if (array_handle <= 0) {
return (FAILURE);
}
}
if (hsp_type) {
/* Set or unset local HSP */
} else {
/* Set or unset global HSP */
}
/* Perform operation of set or unset */
return (FAILURE);
}
if (hsp_type) {
"and RAID volume %s successfully.\n"),
} else {
"and controller %s successfully.\n"),
}
} else {
return (FAILURE);
}
if (hsp_type) {
"disk %s and RAID volume %s successfully.\n"),
} else {
"disk %s and controller %s successfully.\n"),
}
}
return (SUCCESS);
}
/*
* do_set_array_attr(f_flag, p_argp, argv, optind)
* This function changes array's attribute when array is running.
* The changeable attribute is up to controller's feature.
* The return value can be SUCCESS, FAILURE or INVALID_ARG.
*/
static int
{
int ret;
return (INVALID_ARG);
}
value = CACHE_WR_ON;
} else {
return (INVALID_ARG);
}
} else {
return (INVALID_ARG);
}
} else {
return (INVALID_ARG);
}
} else {
return (INVALID_ARG);
}
return (INVALID_ARG);
}
if (ctl_handle <= 0) {
return (FAILURE);
}
if (ret < 0) {
return (FAILURE);
}
if (array_handle <= 0) {
return (FAILURE);
}
/* Ask user to confirm operation. */
if (!yes()) {
gettext("Array %s not "
return (SUCCESS);
}
}
return (FAILURE);
}
return (SUCCESS);
}
/*
* snapshot_raidsystem(recursive, indent, is_snapshot)
* This function prints the snapshot of whole RAID's system configuration,
* and return result as SUCCESS or FAILURE.
*/
static int
{
int ret;
while (ctl_handle > 0) {
if (ret == 0) {
is_snapshot) == FAILURE) {
(void) raidcfg_close_controller(ctl_handle,
NULL);
}
}
}
return (SUCCESS);
}
/*
* snapshot_ctl(ctl_handle, recursive, indent, is_snapshot)
* This function prints snapshot of specified controller's configuration,
* and return result as SUCCESS or FAILURE.
*/
static int
{
char ctlbuf[256];
int ret;
return (FAILURE);
}
if (is_snapshot == FALSE) {
} else {
}
while (array_handle > 0) {
return (FAILURE);
}
}
while (disk_handle > 0) {
return (FAILURE);
}
}
}
return (SUCCESS);
}
/*
* snapshot_array(array_handle, indent, is_sub, is_snapshot)
* This function prints snapshot of specified array's configuration,
* and return result as SUCCESS or FAILURE.
*/
static int
{
int disknum = 0;
int ret;
if (ret < 0) {
return (FAILURE);
}
/* Print array attribute */
return (FAILURE);
}
if (is_snapshot == FALSE) {
"c%ut%llud%llu\n"),
} else {
}
} else {
/* Check if array is in sync state */
if (task_handle > 0) {
}
} else {
while (subarray_handle > 0) {
if (task_handle > 0) {
(void) raidcfg_get_attr(task_handle,
&task_attr);
}
break;
}
}
}
/* Print sub array */
while (subarray_handle > 0) {
/* print subarraypart */
while (arraypart_handle > 0) {
&arraypart_attr)) < 0) {
return (FAILURE);
}
sizeof (tempbuf),
gettext("N/A"));
} else {
sizeof (tempbuf),
"%llu.%llu.%llu",
}
sizeof (diskbuf));
disknum++;
}
}
/* Print arraypart */
while (arraypart_handle > 0) {
&arraypart_attr)) < 0) {
return (FAILURE);
}
gettext("N/A"));
} else {
"%llu.%llu.%llu",
}
disknum++;
}
switch (array_attr.raid_level) {
case RAID_LEVEL_0:
break;
case RAID_LEVEL_1:
break;
case RAID_LEVEL_1E:
break;
case RAID_LEVEL_5:
break;
case RAID_LEVEL_10:
break;
case RAID_LEVEL_50:
break;
default:
gettext("N/A"));
break;
}
switch (array_attr.state) {
case ARRAY_STATE_OPTIMAL:
break;
case ARRAY_STATE_DEGRADED:
break;
case ARRAY_STATE_FAILED:
break;
case ARRAY_STATE_SYNC:
break;
case ARRAY_STATE_MISSING:
break;
default:
break;
}
}
return (SUCCESS);
}
/*
* snapshot_disk(ctl_tag, disk_handle, indent, is_snapshot)
* This function prints snapshot of specified disk's configuration, and return
* result as SUCCESS or FAILURE.
*/
static int
{
int ret;
if (ret < 0) {
return (FAILURE);
}
/* Print attribute of disk */
return (FAILURE);
}
if (is_snapshot == FALSE) {
} else {
}
if (hsp_handle > 0) {
}
} else {
} else {
"%llu.%llu.%llu ",
}
if (hsp_handle > 0) {
gettext("HSP"));
gettext("GOOD"));
gettext("FAILED"));
} else {
gettext("N/A"));
}
}
return (SUCCESS);
}
static int
{
char controller[8];
int ret;
return (FAILURE);
}
(void) print_ctl_attr(&ctl_attr);
return (SUCCESS);
}
static int
{
char array[16];
char arraypart[8];
int ret;
int i;
/* Controller attribute */
return (FAILURE);
}
/* Array attribute */
return (FAILURE);
}
/* print header */
" Cache\tRAID"));
/* print array */
/* check if array is in sync state */
if (task_handle > 0) {
}
} else {
while (subarray_handle > 0) {
if (task_handle > 0) {
(void) raidcfg_get_attr(task_handle,
&task_attr);
}
break;
}
}
}
(void) print_array_attr(&array_attr);
/* Print sub array */
i = 0; /* Count sub array number */
while (subarray_handle > 0) {
&subarray_attr)) < 0) {
return (FAILURE);
}
/* Check if array is in sync */
if (task_handle > 0) {
}
}
(void) print_array_attr(&subarray_attr);
/* Print subarraypart */
while (arraypart_handle > 0) {
&arraypart_attr)) < 0) {
return (FAILURE);
}
gettext("N/A"));
} else {
"%llu.%llu.%llu",
}
(void) print_arraypart_attr(&arraypart_attr);
}
}
/* Print arraypart */
while (arraypart_handle > 0) {
&arraypart_attr)) < 0) {
return (FAILURE);
}
gettext("N/A"));
} else {
"%llu.%llu.%llu",
}
(void) print_arraypart_attr(&arraypart_attr);
}
return (SUCCESS);
}
static int
{
char disk[8];
int ret;
return (FAILURE);
}
return (FAILURE);
}
/* Print header */
"Capacity\tStatus\tHSP"));
return (FAILURE);
}
if (prop_handle == 0) {
return (SUCCESS);
}
do {
return (FAILURE);
}
break;
} while (prop_handle != 0);
if (prop_attr2 == NULL) {
return (FAILURE);
}
return (FAILURE);
}
return (SUCCESS);
}
/*
* print_ctl_attr(attrp)
* This function prints attribute of specified controller, and return
* result as SUCCESS or FAILURE.
*/
static int
{
char type[CONTROLLER_TYPE_LEN];
char version[CONTROLLER_FW_LEN];
return (FAILURE);
}
return (SUCCESS);
}
/*
* print_array_attr(attrp)
* This function prints attribute of specified array, and return
* result as SUCCESS or FAILURE.
*/
static int
{
char capacity[8];
char stripe_size[8];
char raid_level[8];
return (FAILURE);
}
return (FAILURE);
}
} else {
}
} else {
}
else {
case ARRAY_STATE_OPTIMAL:
break;
case ARRAY_STATE_DEGRADED:
break;
case ARRAY_STATE_FAILED:
break;
case ARRAY_STATE_SYNC:
break;
case ARRAY_STATE_MISSING:
break;
default:
break;
}
}
(void) printf(" ");
} else {
}
(void) printf("\t");
switch (attrp->raid_level) {
case RAID_LEVEL_0:
break;
case RAID_LEVEL_1:
break;
case RAID_LEVEL_1E:
break;
case RAID_LEVEL_5:
break;
case RAID_LEVEL_10:
break;
case RAID_LEVEL_50:
break;
default:
gettext("N/A"));
break;
}
return (SUCCESS);
}
/*
* print_arraypart_attr(attrp)
* This function print attribute of specified arraypart, and return
* result as SUCCESS or FAILURE.
*/
static int
{
char size[8];
return (FAILURE);
}
return (FAILURE);
}
} else {
}
(void) printf("\t");
} else {
}
(void) printf("\t");
return (SUCCESS);
}
/*
* print_disk_attr(ctl_handle, disk_handle, attrp)
* This function prints attribute of specified disk, and return
* result as SUCCESS or FAILURE.
*/
static int
{
char vendor[DISK_VENDER_LEN];
char product[DISK_PRODUCT_LEN];
char capacity[16];
char hsp[16];
int ret;
char is_indent;
return (FAILURE);
}
return (FAILURE);
}
} else {
}
} else {
}
(void) printf("\t");
/* Controller attribute */
return (FAILURE);
}
if (hsp_handle == 0) {
} else {
while (hsp_handle > 0) {
&hsp_attr)) < 0) {
return (FAILURE);
}
(void) printf("\t\t\t\t\t\t\t");
} else {
}
"c%ut%llud%llu",
} else {
return (FAILURE);
}
}
}
return (SUCCESS);
}
/*
* print_indent(indent)
* This function prints specified number of tab characters. It's used to
* format layout.
*/
static void
{
uint32_t i;
for (i = 0; i < indent; i++) {
}
}
/*
* get_disk_handle_cidl(ctl_tag, disks_argp, comps_num, handlespp)
* This function parses the string of disk argument, and gets the disks tag
* and separators from the string. Then it translates the tag to handle, and
* stores handles and separators to new buffer pointed by parameter handlespp.
* The format of disk_arg must be C:ID:L, for example, it is 0.1.0. The first
* "0" is channel number, and the second "1" is target number, and the third
* "0" is LUN number. The disk tags are separated by comma and parenthesis.
* Function returns SUCCESS or FAILURE.
*/
static int
{
int len = 0;
int i = 0, j = 0;
char *p, *t;
char *delimit = " ";
char *disks_str;
return (FAILURE);
}
p = disks_argp;
return (FAILURE);
}
/* Insert whitespace between disk tags, '(' , and ')' */
disks_str[j ++] = '(';
disks_str[j ++] = ' ';
while (p[i] != '\0') {
if (p[i] == ')' || p[i] == '(') {
disks_str[j ++] = ' ';
disks_str[j ++] = p[i];
disks_str[j ++] = ' ';
} else
disks_str[j ++] = p[i];
i ++;
}
disks_str[j ++] = ' ';
disks_str[j ++] = ')';
disks_str[j] = '\0';
return (FAILURE);
}
while (p != NULL) {
(*comps_nump)++;
}
free(t);
return (FAILURE);
}
for (i = 0; i < *comps_nump; i++)
(*handlespp)[i] = INIT_HANDLE_VALUE;
i = 0;
while (p != NULL) {
if (*p == '(') {
(*handlespp)[i] = OBJ_SEPARATOR_BEGIN;
} else if (*p == ')') {
(*handlespp)[i] = OBJ_SEPARATOR_END;
} else {
return (INVALID_ARG);
}
(*handlespp)[i] =
disk_tag);
if ((*handlespp)[i] <= 0) {
raidcfg_errstr((*handlespp)[i]));
return (FAILURE);
}
}
i++;
}
return (SUCCESS);
}
/*
* get_disk_handle_ctd(disks_num, disks_argpp, ctl_tagp, disks_handlep)
* This function parses string of single disk with "ctd" format, for example,
* c0t0d0, and translates it to controller tag and disk tag.
* Then it calls lib api and get disk handle. The controller tag and disk
* handle are both returned by out parameters.
* The return value is SUCCESS or FAILURE.
*/
static int
{
int i;
int ret;
if (disks_handlep == NULL) {
return (FAILURE);
}
for (i = 0; i < disks_num; i++) {
SUCCESS) {
return (INVALID_ARG);
}
if (i == 0) {
if (ctl_handle <= 0) {
return (FAILURE);
}
if (ret < 0) {
return (FAILURE);
}
}
if ((disks_handlep[i] =
raidcfg_errstr(disks_handlep[i]));
return (FAILURE);
}
}
return (SUCCESS);
}
/*
* get_ctl_tag(argp)
* This function translates controller string to tag. The return value is
* SUCCESS if the string has legal format and is parsed successfully,
* or FAILURE if it fails.
*/
static int
{
return (FAILURE);
}
return (SUCCESS);
}
/*
* get_array_tag(argp, ctl_tagp, array_tagp)
* This function parses array string to get array tag and controller tag.
* The return value is SUCCESS if the string has legal format, or
* FAILURE if it fails.
*/
static int
{
char *t = NULL;
int len = 0;
array_tagp == NULL) {
return (FAILURE);
}
if (t == NULL) {
return (FAILURE);
}
/* Now remmber to release t memory if exception occurs */
free(t);
return (FAILURE);
}
cp = t;
*dp = '\0';
dp++;
*tp = '\0';
tp++;
cp++;
free(t);
return (FAILURE);
}
}
free(t);
return (SUCCESS);
}
/*
* get_disk_tag_ctd(argp, disk_tagp)
* This function parses disk string of ctd format, and translates it to
* disk tag and controller tag. The tags is returned by out parameters.
* The return value is SUCCESS if the string has legal format, or FAILURE
* if it fails.
*/
static int
{
char *t = NULL;
int len = 0;
return (FAILURE);
}
if (t == NULL) {
return (FAILURE);
}
/* Now remmber to release t memory if exception occurs */
free(t);
return (FAILURE);
}
cp = t;
*dp = '\0';
dp++;
*tp = '\0';
tp++;
cp++;
free(t);
return (FAILURE);
}
free(t);
return (SUCCESS);
}
/*
* get_disk_tag_cidl(argp, disk_tagp)
* This function parses disk string of cidl format and translates it to tag.
* The return value is disk tag if the string has legal format, or FAILURE
* if it fails.
*/
static int
{
int len = 0;
char *p = NULL;
char *t = NULL;
return (FAILURE);
}
return (FAILURE);
}
if (t == NULL) {
return (FAILURE);
}
p = t;
free(t);
return (FAILURE);
}
*dot2p = '\0';
dot2p++;
free(t);
return (FAILURE);
}
*dot1p = '\0';
dot1p++;
/* Assert only 2 dots in this string */
free(t);
return (FAILURE);
}
while (*p == ' ')
p++;
if (is_fully_numeric(p) == FALSE ||
free(t);
return (FAILURE);
}
free(t);
return (SUCCESS);
}
/*
* calc_size(sizep, valp)
* This function calculates the value represented by string sizep.
* The string sizep can be decomposed into three parts: an initial,
* possibly empty, sequence of white-space characters; a subject digital
* sequence interpreted as an integer with unit k/K/m/M/g/G/t/T; and a
* final string of one or more unrecognized characters or white-sapce
* characters, including the terminating null. If unrecognized character
* exists or overflow happens, the conversion must fail and return
* INVALID_ARG. If the conversion is performed successfully, result will
* be saved into valp and function returns SUCCESS. It returns FAILURE
* when memory allocation fails.
*/
static int
{
int len;
char *t = NULL;
return (INVALID_ARG);
}
return (SUCCESS);
}
if (len == 0) {
return (INVALID_ARG);
}
if (t == NULL) {
return (FAILURE);
}
switch (*(t + len - 1)) {
case 'k':
case 'K':
unit = 1024ull;
errno = 0;
break;
case 'm':
case 'M':
errno = 0;
break;
case 'g':
case 'G':
errno = 0;
break;
case 't':
case 'T':
errno = 0;
break;
default:
/* The unit must be kilobyte at least. */
free(t);
return (INVALID_ARG);
}
if (is_fully_numeric(t) != TRUE) {
free(t);
return (INVALID_ARG);
}
errno = 0;
/* Check overflow condition */
free(t);
return (INVALID_ARG);
}
free(t);
return (SUCCESS);
}
/*
* is_fully_numeric(str)
* This function checks if the string are legal numeric string. The beginning
* or ending characters can be white spaces.
* Return value is TRUE if the string are legal numeric string, or FALSE
* otherwise.
*/
static int
is_fully_numeric(char *strp)
{
uint32_t i;
return (FALSE);
}
if (len == 0) {
return (FALSE);
}
/* Skip whitespace characters */
for (i = 0; i < len; i++) {
if (strp[i] != ' ') {
break;
}
}
/* if strp points all space characters */
if (i == len) {
return (FALSE);
}
/* Check the digitals in string */
for (; i < len; i++) {
break;
}
}
/* Check the ending string */
for (; i < len; i++) {
if (strp[i] != ' ') {
return (FALSE);
}
}
return (TRUE);
}
static int
yes(void)
{
int i, b;
for (i = 0; ; i++) {
b = getchar();
ans[i] = 0;
break;
}
if (i < SCHAR_MAX) {
ans[i] = b;
}
}
if (i >= SCHAR_MAX) {
i = SCHAR_MAX;
}
}
/*
* Function: int rpmatch(char *)
*
* Description:
*
* Internationalized get yes / no answer.
*
* Inputs:
* s -> Pointer to answer to compare against.
*
* Returns:
* TRUE -> Answer was affirmative
* FALSE -> Answer was negative
*/
static int
rpmatch(char *s)
{
int status;
/* match yesexpr */
if (status != 0) {
return (FALSE);
}
return (TRUE);
}
static int
{
int i = 0;
return (FAILURE);
}
while (size > 1023) {
size /= 1024;
i++;
}
if (i > 4) {
return (FAILURE);
}
remainder /= 103;
if (remainder == 0) {
} else {
}
/* make sure there is one byte for unit */
return (FAILURE);
}
return (SUCCESS);
}
/*
* Only one raidctl is running at one time.
*/
static int
enter_raidctl_lock(int *fd)
{
int fd0 = -1;
if (fd0 < 0) {
gettext("raidctl:must be root to run raidctl"
} else {
gettext("raidctl:failed to open lockfile"
}
return (FAILURE);
}
gettext("raidctl:enter_filelock error\n"));
return (FAILURE);
}
"enter_filelock:filelock is owned "
return (FAILURE);
}
return (SUCCESS);
}
static void
exit_raidctl_lock(int fd)
{
" exit_filelock: %s\n"),
}
}