helper.c revision f3861e1a2ceec23a5b699c24d814b7775a9e0b52
/*
* 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 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdlib.h>
#include <stdio.h>
#include <wchar.h>
#include <widec.h>
#include <netdb.h>
#include <unistd.h>
#include <libintl.h>
#include <limits.h>
#include <string.h>
#include <strings.h>
#include <syslog.h>
#include <errno.h>
#include <sys/iscsi_protocol.h>
#include <door.h>
#include <libxml/xmlreader.h>
#include <libscf.h>
#include <fcntl.h>
#include <iscsitgt_impl.h>
#include "cmdparse.h"
#include "utility.h"
#include "helper.h"
extern char *cmdName;
static stat_delta_t *stat_head;
/*
* []----
* | buffer_xml -- buffer incoming XML response until complete
* |
* | Incoming data from target may not be a complete XML message. So,
* | we need to wait until we've got everything otherwise the XML routines
* | will generate a parsing error for a short buffer.
* []----
*/
{
char *p,
*e,
*end_tag,
p = *storage;
if (s != NULL) {
if (p == NULL) {
p = strdup(s);
} else {
(void) strcat(p, s);
}
}
if (p == NULL) {
return (False);
}
if (*p != '<') {
return (False);
}
return (False);
}
/*
* The +3 is for the slash, closing tag character and null
* For example if p is pointing at a string which starts with
* "<foo>...."
* p will point at '<' and e will point at '>'. e - p is 4, yet
* the tag length is really 5 characters. We will need to create
* the end tag which also has a slash and NULL byte.
*/
return (False);
}
end_tag[0] = '<';
/*
* Copy in the tag value and the closing tag character '>'.
*/
/*
* Add the null byte
*/
/*
* Do we have the closing string yet? If not, just return
*/
*storage = p;
return (False);
}
/*
* Move past the closing tag and free the end_tag memory
*/
/*
* NULL terminate the string and remember to save that character
* so that we can restore it later.
*/
hold_ch = *e;
*e = '\0';
return (False);
while (xmlTextReaderRead(r) == 1) {
break;
}
*e = hold_ch;
for (; isspace(*e); e++)
;
if (*e != '\0') {
} else
free(p);
return (True);
}
/*
* Retrieve CHAP secret from input
*/
int
{
char *chapSecret;
/* XXX Should we prompt for hex or ascii printable input? */
/* get password */
gettext("secret too long"));
return (1);
}
gettext("secret too short"));
return (1);
}
gettext("secret not changed"));
return (1);
}
return (0);
}
void
{
switch (status) {
case iSCSINameLenZero:
break;
case iSCSINameLenExceededMax:
gettext("iSCSI name exceeded maximum length."));
break;
case iSCSINameUnknownType:
gettext("unknown iSCSI name type."));
break;
case iSCSINameIqnFormatError:
gettext("iqn formatting error."));
break;
case iSCSINameEUIFormatError:
gettext("eui formatting error."));
break;
}
}
/*
* This helper function could go into a utility module for general use.
*/
int
parseAddress(char *address_port_str,
char *address_str,
{
char port_str[64];
int tmp_port;
if (address_port_str[0] == '[') {
/* IPv6 address */
char *close_bracket_pos;
if (!close_bracket_pos) {
"IP address format error: %s\n", address_str);
return (PARSE_ADDR_MISSING_CLOSING_BRACKET);
}
/* Extract the port number */
if (*close_bracket_pos == ':') {
if (*close_bracket_pos != NULL) {
64);
if (((tmp_port > 0) &&
(tmp_port < 0)) {
/* Port number out of range */
"Specified port out of range: %d",
tmp_port);
return (PARSE_ADDR_PORT_OUT_OF_RANGE);
} else {
}
} else {
*port = defaultPort;
}
} else {
*port = defaultPort;
}
} else {
/* IPv4 address */
char *colon_pos;
if (!colon_pos) {
/* No port number specified. */
*port = defaultPort;
} else {
/* Extract the port number */
colon_pos++;
if (((tmp_port > 0) &&
(tmp_port < 0)) {
/* Port number out of range */
"Specified port out of range: %d",
tmp_port);
return (PARSE_ADDR_PORT_OUT_OF_RANGE);
} else {
}
} else {
*port = defaultPort;
}
}
}
return (PARSE_ADDR_OK);
}
/*
* []----
* | Following routine (number_to_scaled_string) is lifted
* []----
*/
/*
* Convert an unsigned long long to a string representation and place the
* result in the caller-supplied buffer.
* The given number is in units of "unit_from" size,
* this will first be converted to a number in 1024 or 1000 byte size,
* depending on the scaling factor.
* Then the number is scaled down until it is small enough to be in a good
* human readable format i.e. in the range 0 thru scale-1.
* If it's smaller than 10 there's room enough to provide one decimal place.
* The value "(unsigned long long)-1" is a special case and is always
* converted to "-1".
* Returns a pointer to the caller-supplied buffer.
*/
char *
char *buf, /* put the result here */
unsigned long long number, /* convert this number */
int unit_from,
int scale)
{
unsigned long long save = 0;
char *M = "KMGTPE"; /* Measurement: kilo, mega, giga, tera, peta, exa */
char *uom = M; /* unit of measurement, initially 'K' (=M[0]) */
if ((long long)number == (long long)-1) {
return (buf);
}
return (buf);
}
/*
* Convert number from unit_from to given scale (1024 or 1000).
* This means multiply number by unit_from and divide by scale.
*
* Would like to multiply by unit_from and then divide by scale,
* but if the first multiplication would overflow, then need to
* divide by scale and then multiply by unit_from.
*/
(unsigned long long)unit_from;
} else {
(unsigned long long)scale;
}
/*
* Now we have number as a count of scale units.
* Stop scaling when we reached exa bytes, then something is
* probably wrong with our number.
*/
uom++; /* next unit of measurement */
}
/* check if we should output a decimal place after the point */
/* sprintf() will round for us */
} else {
}
return (buf);
}
void
{
*lun;
char *val;
bzero(d, sizeof (*d));
}
}
}
}
}
}
}
{
stat_delta_t *n;
return (n);
}
return (NULL);
stat_head = n;
else {
stat_head = n;
}
return (n);
}
void
{
}
void
{
stat_delta_t *n;
/* CSTYLED */
for (;stat_head;) {
stat_head = n;
}
}
static char spaces[128];
/*
* []----
* | dospace -- generate a string which has the appropriate number of spaces
* |
* | NOTE: Since this function modifies a static buffer usage of this
* | function may not be what's expected. For example:
* | printf("%sfoo%sbar\n", dospace(1), dospace(2)); would produce
* | ' foo bar'
* | instead of
* | ' foo bar'
* []----
*/
char *
dospace(int n)
{
if (n < sizeof (spaces))
return (spaces);
}