Blame export.c

Packit 1c819f
/*
Packit 1c819f
 * Helper functions to represent iSNS objects as text,
Packit 1c819f
 * and/or to parse objects represented in textual form.
Packit 1c819f
 * These functions can be used by command line utilities
Packit 1c819f
 * such as isnsadm, as well as applications like iscsid
Packit 1c819f
 * or stgtd when talking to the iSNS discovery daemon.
Packit 1c819f
 *
Packit 1c819f
 * Copyright (C) 2007 Olaf Kirch <olaf.kirch@oracle.com>
Packit 1c819f
 */
Packit 1c819f
Packit 1c819f
#include <stdlib.h>
Packit 1c819f
#include <stdio.h>
Packit 1c819f
#include <string.h>
Packit 1c819f
#include <unistd.h>
Packit 1c819f
#include <ctype.h>
Packit 1c819f
Packit 1c819f
#include "config.h"
Packit 1c819f
#include <libisns/isns.h>
Packit 1c819f
#include <libisns/util.h>
Packit 1c819f
#include "vendor.h"
Packit 1c819f
#include <libisns/attrs.h>
Packit 1c819f
#include "security.h"
Packit 1c819f
#include "objects.h"
Packit 1c819f
#include <libisns/paths.h>
Packit 1c819f
Packit 1c819f
#define MAX_ALIASES		4
Packit 1c819f
Packit 1c819f
struct isns_tag_prefix {
Packit 1c819f
	const char *		name;
Packit 1c819f
	unsigned int		name_len;
Packit 1c819f
	isns_object_template_t *context;
Packit 1c819f
};
Packit 1c819f
Packit 1c819f
struct tag_name {
Packit 1c819f
	const char *		name;
Packit 1c819f
	uint32_t		tag;
Packit 1c819f
	struct isns_tag_prefix *prefix;
Packit 1c819f
	const char *		alias[MAX_ALIASES];
Packit 1c819f
};
Packit 1c819f
Packit 1c819f
static struct isns_tag_prefix all_prefixes[__ISNS_OBJECT_TYPE_MAX] = {
Packit 1c819f
[ISNS_OBJECT_TYPE_ENTITY] = { "entity-", 7, &isns_entity_template	},
Packit 1c819f
[ISNS_OBJECT_TYPE_NODE]   = { "iscsi-",	 6, &isns_iscsi_node_template	},
Packit 1c819f
[ISNS_OBJECT_TYPE_PORTAL] = { "portal-", 7, &isns_portal_template	},
Packit 1c819f
[ISNS_OBJECT_TYPE_PG]     = { "pg-",	 3, &isns_iscsi_pg_template	},
Packit 1c819f
[ISNS_OBJECT_TYPE_DD]     = { "dd-",	 3, &isns_dd_template		},
Packit 1c819f
[ISNS_OBJECT_TYPE_POLICY] = { "policy-", 7, &isns_policy_template	},
Packit 1c819f
};
Packit 1c819f
Packit 1c819f
static struct tag_name	all_attrs[] = {
Packit 1c819f
{ "id",			ISNS_TAG_ENTITY_IDENTIFIER,
Packit 1c819f
			.alias = { "eid", },
Packit 1c819f
},
Packit 1c819f
{ "prot",		ISNS_TAG_ENTITY_PROTOCOL },
Packit 1c819f
{ "idx",		ISNS_TAG_ENTITY_INDEX },
Packit 1c819f
Packit 1c819f
{ "name",		ISNS_TAG_ISCSI_NAME },
Packit 1c819f
{ "node-type",		ISNS_TAG_ISCSI_NODE_TYPE },
Packit 1c819f
{ "alias",		ISNS_TAG_ISCSI_ALIAS },
Packit 1c819f
{ "authmethod",		ISNS_TAG_ISCSI_AUTHMETHOD },
Packit 1c819f
{ "idx",		ISNS_TAG_ISCSI_NODE_INDEX },
Packit 1c819f
Packit 1c819f
{ "addr",		ISNS_TAG_PORTAL_IP_ADDRESS },
Packit 1c819f
{ "port",		ISNS_TAG_PORTAL_TCP_UDP_PORT },
Packit 1c819f
{ "name",		ISNS_TAG_PORTAL_SYMBOLIC_NAME },
Packit 1c819f
{ "esi-port",		ISNS_TAG_ESI_PORT },
Packit 1c819f
{ "esi-interval",	ISNS_TAG_ESI_INTERVAL },
Packit 1c819f
{ "scn-port",		ISNS_TAG_SCN_PORT },
Packit 1c819f
{ "idx",		ISNS_TAG_PORTAL_INDEX },
Packit 1c819f
Packit 1c819f
{ "name",		ISNS_TAG_PG_ISCSI_NAME },
Packit 1c819f
{ "addr",		ISNS_TAG_PG_PORTAL_IP_ADDR },
Packit 1c819f
{ "port",		ISNS_TAG_PG_PORTAL_TCP_UDP_PORT },
Packit 1c819f
{ "tag",		ISNS_TAG_PG_TAG },
Packit 1c819f
{ "pgt",		ISNS_TAG_PG_TAG },
Packit 1c819f
{ "idx",		ISNS_TAG_PG_INDEX },
Packit 1c819f
Packit 1c819f
{ "id",			ISNS_TAG_DD_ID },
Packit 1c819f
{ "name",		ISNS_TAG_DD_SYMBOLIC_NAME },
Packit 1c819f
{ "member-name",	ISNS_TAG_DD_MEMBER_ISCSI_NAME },
Packit 1c819f
{ "member-iscsi-idx",	ISNS_TAG_DD_MEMBER_ISCSI_INDEX },
Packit 1c819f
{ "member-fc-name",	ISNS_TAG_DD_MEMBER_FC_PORT_NAME },
Packit 1c819f
{ "member-portal-idx",	ISNS_TAG_DD_MEMBER_PORTAL_INDEX },
Packit 1c819f
{ "member-addr",	ISNS_TAG_DD_MEMBER_PORTAL_IP_ADDR  },
Packit 1c819f
{ "member-port",	ISNS_TAG_DD_MEMBER_PORTAL_TCP_UDP_PORT  },
Packit 1c819f
{ "features",		ISNS_TAG_DD_FEATURES },
Packit 1c819f
Packit 1c819f
{ "name",		OPENISNS_TAG_POLICY_SPI,
Packit 1c819f
			.alias = { "spi" },
Packit 1c819f
},
Packit 1c819f
{ "key",		OPENISNS_TAG_POLICY_KEY },
Packit 1c819f
{ "entity",		OPENISNS_TAG_POLICY_ENTITY },
Packit 1c819f
{ "object-type",	OPENISNS_TAG_POLICY_OBJECT_TYPE },
Packit 1c819f
{ "node-type",		OPENISNS_TAG_POLICY_NODE_TYPE },
Packit 1c819f
{ "node-name",		OPENISNS_TAG_POLICY_NODE_NAME },
Packit 1c819f
{ "functions",		OPENISNS_TAG_POLICY_FUNCTIONS },
Packit 1c819f
Packit 1c819f
{ NULL }
Packit 1c819f
};
Packit 1c819f
Packit 1c819f
/*
Packit 1c819f
 * Initialize tag array
Packit 1c819f
 */
Packit 1c819f
static void
Packit 1c819f
init_tags(void)
Packit 1c819f
{
Packit 1c819f
	struct tag_name	*t;
Packit 1c819f
Packit 1c819f
	for (t = all_attrs; t->name; ++t) {
Packit 1c819f
		isns_object_template_t *tmpl;
Packit 1c819f
Packit 1c819f
		tmpl = isns_object_template_for_tag(t->tag);
Packit 1c819f
		if (tmpl == NULL)
Packit 1c819f
			isns_fatal("Bug: cannot find object type for tag %s\n",
Packit 1c819f
					t->name);
Packit 1c819f
		t->prefix = &all_prefixes[tmpl->iot_handle];
Packit 1c819f
	}
Packit 1c819f
}
Packit 1c819f
Packit 1c819f
/*
Packit 1c819f
 * Match prefix
Packit 1c819f
 */
Packit 1c819f
static struct isns_tag_prefix *
Packit 1c819f
find_prefix(const char *name)
Packit 1c819f
{
Packit 1c819f
	struct isns_tag_prefix *p;
Packit 1c819f
	unsigned int	i;
Packit 1c819f
Packit 1c819f
	for (i = 0, p = all_prefixes; i < __ISNS_OBJECT_TYPE_MAX; ++i, ++p) {
Packit 1c819f
		if (p->name && !strncmp(name, p->name, p->name_len))
Packit 1c819f
			return p;
Packit 1c819f
	}
Packit 1c819f
	return NULL;
Packit 1c819f
}
Packit 1c819f
Packit 1c819f
/*
Packit 1c819f
 * Look up the tag for a given attribute name.
Packit 1c819f
 * By default, attr names come with a disambiguating
Packit 1c819f
 * prefix that defines the object type the attribute applies
Packit 1c819f
 * to, such as "entity-" or "portal-". Once a context has
Packit 1c819f
 * been established (ie we know the object type subsequent
Packit 1c819f
 * attributes apply to), specifying the prefix is optional.
Packit 1c819f
 *
Packit 1c819f
 * For instance, in a portal context, "addr=10.1.1.1 port=616 name=foo"
Packit 1c819f
 * specifies three portal related attributes. Whereas in a portal
Packit 1c819f
 * group context, the same string would specify three portal group
Packit 1c819f
 * related attributes. To disambiguate, the first attribute in
Packit 1c819f
 * this list should be prefixed by "portal-" or "pg-", respectively.
Packit 1c819f
 */
Packit 1c819f
static uint32_t
Packit 1c819f
tag_by_name(const char *name, struct isns_attr_list_parser *st)
Packit 1c819f
{
Packit 1c819f
	const char	*orig_name = name;
Packit 1c819f
	unsigned int	nmatch = 0, i;
Packit 1c819f
	struct tag_name	*t, *match[8];
Packit 1c819f
	struct isns_tag_prefix *specific = NULL;
Packit 1c819f
Packit 1c819f
	if (all_attrs[0].prefix == NULL)
Packit 1c819f
		init_tags();
Packit 1c819f
Packit 1c819f
	specific = find_prefix(name);
Packit 1c819f
	if (specific != NULL) {
Packit 1c819f
		if (st->prefix
Packit 1c819f
		 && st->prefix != specific
Packit 1c819f
		 && !st->multi_type_permitted) {
Packit 1c819f
			isns_error("Cannot mix attributes of different types\n");
Packit 1c819f
			return 0;
Packit 1c819f
		}
Packit 1c819f
		name += specific->name_len;
Packit 1c819f
		st->prefix = specific;
Packit 1c819f
	}
Packit 1c819f
Packit 1c819f
	for (t = all_attrs; t->name; ++t) {
Packit 1c819f
		if (specific && t->prefix != specific)
Packit 1c819f
			continue;
Packit 1c819f
		if (!st->multi_type_permitted
Packit 1c819f
		 && st->prefix && t->prefix != st->prefix)
Packit 1c819f
			continue;
Packit 1c819f
		if (!strcmp(name, t->name))
Packit 1c819f
			goto match;
Packit 1c819f
		for (i = 0; i < MAX_ALIASES && t->alias[i]; ++i) {
Packit 1c819f
			if (!strcmp(name, t->alias[i]))
Packit 1c819f
				goto match;
Packit 1c819f
		}
Packit 1c819f
		continue;
Packit 1c819f
Packit 1c819f
match:
Packit 1c819f
		if (nmatch < 8)
Packit 1c819f
			match[nmatch++] = t;
Packit 1c819f
	}
Packit 1c819f
Packit 1c819f
	if (nmatch > 1) {
Packit 1c819f
		char		conflict[128];
Packit 1c819f
		unsigned int	i;
Packit 1c819f
Packit 1c819f
		conflict[0] = '\0';
Packit 1c819f
		for (i = 0; i < nmatch; ++i) {
Packit 1c819f
			if (i)
Packit 1c819f
				strcat(conflict, ", ");
Packit 1c819f
			t = match[i];
Packit 1c819f
			strcat(conflict, t->prefix->name);
Packit 1c819f
			strcat(conflict, t->name);
Packit 1c819f
		}
Packit 1c819f
		isns_error("tag name \"%s\" not unique in this context "
Packit 1c819f
				"(could be one of %s)\n",
Packit 1c819f
				orig_name, conflict);
Packit 1c819f
		return 0;
Packit 1c819f
	}
Packit 1c819f
Packit 1c819f
	if (nmatch == 0) {
Packit 1c819f
		isns_error("tag name \"%s\" not known in this context\n",
Packit 1c819f
				orig_name);
Packit 1c819f
		return 0;
Packit 1c819f
	}
Packit 1c819f
Packit 1c819f
	st->prefix = match[0]->prefix;
Packit 1c819f
	return match[0]->tag;
Packit 1c819f
}
Packit 1c819f
Packit 1c819f
static const char *
Packit 1c819f
name_by_tag(uint32_t tag, struct isns_attr_list_parser *st)
Packit 1c819f
{
Packit 1c819f
	struct tag_name *t;
Packit 1c819f
Packit 1c819f
	for (t = all_attrs; t->name; ++t) {
Packit 1c819f
		if (st->prefix && t->prefix != st->prefix)
Packit 1c819f
			continue;
Packit 1c819f
		if (t->tag == tag)
Packit 1c819f
			return t->name;
Packit 1c819f
	}
Packit 1c819f
	return NULL;
Packit 1c819f
}
Packit 1c819f
Packit 1c819f
static int
Packit 1c819f
parse_one_attr(const char *name, const char *value,
Packit 1c819f
		isns_attr_list_t *attrs,
Packit 1c819f
		struct isns_attr_list_parser *st)
Packit 1c819f
{
Packit 1c819f
	isns_attr_t	*attr;
Packit 1c819f
	uint32_t	tag;
Packit 1c819f
Packit 1c819f
	/* Special case: "portal=<address:port>" is translated to
Packit 1c819f
	 * addr=<address> port=<port>
Packit 1c819f
	 * If no context has been set, assume portal context.
Packit 1c819f
	 */
Packit 1c819f
	if (!strcasecmp(name, "portal")) {
Packit 1c819f
		isns_portal_info_t portal_info;
Packit 1c819f
		uint32_t	addr_tag, port_tag;
Packit 1c819f
Packit 1c819f
		if (st->prefix == NULL) {
Packit 1c819f
			addr_tag = tag_by_name("portal-addr", st);
Packit 1c819f
			port_tag = tag_by_name("portal-port", st);
Packit 1c819f
		} else {
Packit 1c819f
			addr_tag = tag_by_name("addr", st);
Packit 1c819f
			port_tag = tag_by_name("port", st);
Packit 1c819f
		}
Packit 1c819f
Packit 1c819f
		if (!addr_tag || !port_tag) {
Packit 1c819f
			isns_error("portal=... not supported in this context\n");
Packit 1c819f
			return 0;
Packit 1c819f
		}
Packit 1c819f
		if (value == NULL) {
Packit 1c819f
			isns_attr_list_append_nil(attrs, addr_tag);
Packit 1c819f
			isns_attr_list_append_nil(attrs, port_tag);
Packit 1c819f
			return 1;
Packit 1c819f
		}
Packit 1c819f
		if (!isns_portal_parse(&portal_info, value, st->default_port))
Packit 1c819f
			return 0;
Packit 1c819f
		isns_portal_to_attr_list(&portal_info, addr_tag, port_tag, attrs);
Packit 1c819f
		return 1;
Packit 1c819f
	}
Packit 1c819f
Packit 1c819f
	if (!(tag = tag_by_name(name, st)))
Packit 1c819f
		return 0;
Packit 1c819f
Packit 1c819f
	/* Special handling for key objects */
Packit 1c819f
	if (tag == OPENISNS_TAG_POLICY_KEY) {
Packit 1c819f
		if (!value || !strcasecmp(value, "gen")) {
Packit 1c819f
			if (st->generate_key == NULL) {
Packit 1c819f
				isns_error("Key generation not supported in this context\n");
Packit 1c819f
				return 0;
Packit 1c819f
			}
Packit 1c819f
			attr = st->generate_key();
Packit 1c819f
		} else {
Packit 1c819f
			if (st->load_key == NULL) {
Packit 1c819f
				isns_error("Policy-key attribute not supported in this context\n");
Packit 1c819f
				return 0;
Packit 1c819f
			}
Packit 1c819f
			attr = st->load_key(value);
Packit 1c819f
		}
Packit 1c819f
		goto append_attr;
Packit 1c819f
	}
Packit 1c819f
Packit 1c819f
	if (value == NULL) {
Packit 1c819f
		isns_attr_list_append_nil(attrs, tag);
Packit 1c819f
		return 1;
Packit 1c819f
	}
Packit 1c819f
Packit 1c819f
	attr = isns_attr_from_string(tag, value);
Packit 1c819f
	if (!attr)
Packit 1c819f
		return 0;
Packit 1c819f
Packit 1c819f
append_attr:
Packit 1c819f
	isns_attr_list_append_attr(attrs, attr);
Packit 1c819f
	return 1;
Packit 1c819f
}
Packit 1c819f
Packit 1c819f
void
Packit 1c819f
isns_attr_list_parser_init(struct isns_attr_list_parser *st,
Packit 1c819f
				isns_object_template_t *tmpl)
Packit 1c819f
{
Packit 1c819f
	if (all_attrs[0].prefix == NULL)
Packit 1c819f
		init_tags();
Packit 1c819f
Packit 1c819f
	memset(st, 0, sizeof(*st));
Packit 1c819f
	if (tmpl)
Packit 1c819f
		st->prefix = &all_prefixes[tmpl->iot_handle];
Packit 1c819f
}
Packit 1c819f
Packit 1c819f
int
Packit 1c819f
isns_attr_list_split(char *line, char **argv, unsigned int argc_max)
Packit 1c819f
{
Packit 1c819f
	char		*src = line;
Packit 1c819f
	unsigned int	argc = 0, quoted = 0;
Packit 1c819f
Packit 1c819f
	if (!line)
Packit 1c819f
		return 0;
Packit 1c819f
Packit 1c819f
	while (1) {
Packit 1c819f
		char	*dst;
Packit 1c819f
Packit 1c819f
		while (isspace(*src))
Packit 1c819f
			++src;
Packit 1c819f
		if (!*src)
Packit 1c819f
			break;
Packit 1c819f
Packit 1c819f
		argv[argc] = dst = src;
Packit 1c819f
		while (*src) {
Packit 1c819f
			char cc = *src++;
Packit 1c819f
Packit 1c819f
			if (cc == '"') {
Packit 1c819f
				quoted = !quoted;
Packit 1c819f
				continue;
Packit 1c819f
			}
Packit 1c819f
			if (!quoted && isspace(cc)) {
Packit 1c819f
				*dst = '\0';
Packit 1c819f
				break;
Packit 1c819f
			}
Packit 1c819f
			*dst++ = cc;
Packit 1c819f
		}
Packit 1c819f
Packit 1c819f
		if (quoted) {
Packit 1c819f
			isns_error("%s: Unterminated quoted string: \"%s\"\n",
Packit 1c819f
					__FUNCTION__, argv[argc]);
Packit 1c819f
			return -1;
Packit 1c819f
		}
Packit 1c819f
		argc++;
Packit 1c819f
	}
Packit 1c819f
Packit 1c819f
	return argc;
Packit 1c819f
}
Packit 1c819f
Packit 1c819f
int
Packit 1c819f
isns_parse_attrs(unsigned int argc, char **argv,
Packit 1c819f
		isns_attr_list_t *attrs,
Packit 1c819f
		struct isns_attr_list_parser *st)
Packit 1c819f
{
Packit 1c819f
	unsigned int	i;
Packit 1c819f
Packit 1c819f
	for (i = 0; i < argc; ++i) {
Packit 1c819f
		char		*name, *value;
Packit 1c819f
Packit 1c819f
		name = argv[i];
Packit 1c819f
		if ((value = strchr(name, '=')) != NULL)
Packit 1c819f
			*value++ = '\0';
Packit 1c819f
Packit 1c819f
		if (!value && !st->nil_permitted) {
Packit 1c819f
			isns_error("Missing value for atribute %s\n", name);
Packit 1c819f
			return 0;
Packit 1c819f
		}
Packit 1c819f
Packit 1c819f
		if (!parse_one_attr(name, value, attrs, st)) {
Packit 1c819f
			isns_error("Unable to parse %s=%s\n", name, value);
Packit 1c819f
			return 0;
Packit 1c819f
		}
Packit 1c819f
	}
Packit 1c819f
Packit 1c819f
	return 1;
Packit 1c819f
}
Packit 1c819f
Packit 1c819f
/*
Packit 1c819f
 * Query strings may contain a mix of query keys (foo=bar),
Packit 1c819f
 * and requested attributes (?foo). The former are used by
Packit 1c819f
 * the server in its object search, whereas the latter instruct
Packit 1c819f
 * it which attributes to return.
Packit 1c819f
 */
Packit 1c819f
int
Packit 1c819f
isns_parse_query_attrs(unsigned int argc, char **argv,
Packit 1c819f
		isns_attr_list_t *keys,
Packit 1c819f
		isns_attr_list_t *requested_attrs,
Packit 1c819f
		struct isns_attr_list_parser *st)
Packit 1c819f
{
Packit 1c819f
	struct isns_attr_list_parser query_state;
Packit 1c819f
	unsigned int	i;
Packit 1c819f
Packit 1c819f
	query_state = *st;
Packit 1c819f
	query_state.multi_type_permitted = 1;
Packit 1c819f
Packit 1c819f
	for (i = 0; i < argc; ++i) {
Packit 1c819f
		char		*name, *value;
Packit 1c819f
Packit 1c819f
		name = argv[i];
Packit 1c819f
		if ((value = strchr(name, '=')) != NULL)
Packit 1c819f
			*value++ = '\0';
Packit 1c819f
Packit 1c819f
		if (name[0] == '?') {
Packit 1c819f
			uint32_t tag;
Packit 1c819f
Packit 1c819f
			if (value) {
Packit 1c819f
				isns_error("No value allowed for query attribute %s\n",
Packit 1c819f
						name);
Packit 1c819f
				return 0;
Packit 1c819f
			}
Packit 1c819f
Packit 1c819f
			if ((tag = tag_by_name(name + 1, &query_state)) != 0) {
Packit 1c819f
				isns_attr_list_append_nil(requested_attrs, tag);
Packit 1c819f
				continue;
Packit 1c819f
			}
Packit 1c819f
		} else {
Packit 1c819f
			if (!value && !st->nil_permitted) {
Packit 1c819f
				isns_error("Missing value for atribute %s\n", name);
Packit 1c819f
				return 0;
Packit 1c819f
			}
Packit 1c819f
Packit 1c819f
			if (parse_one_attr(name, value, keys, st))
Packit 1c819f
				continue;
Packit 1c819f
		}
Packit 1c819f
Packit 1c819f
		isns_error("Unable to parse %s=%s\n", name, value);
Packit 1c819f
		return 0;
Packit 1c819f
	}
Packit 1c819f
Packit 1c819f
	return 1;
Packit 1c819f
}
Packit 1c819f
Packit 1c819f
void
Packit 1c819f
isns_attr_list_parser_help(struct isns_attr_list_parser *st)
Packit 1c819f
{
Packit 1c819f
	isns_object_template_t *tmpl, *current = NULL;
Packit 1c819f
	struct tag_name	*t;
Packit 1c819f
Packit 1c819f
	if (all_attrs[0].prefix == NULL)
Packit 1c819f
		init_tags();
Packit 1c819f
Packit 1c819f
	for (t = all_attrs; t->name; ++t) {
Packit 1c819f
		const isns_tag_type_t *tag_type;
Packit 1c819f
		char		namebuf[64];
Packit 1c819f
		const char	*help;
Packit 1c819f
		unsigned int	i;
Packit 1c819f
Packit 1c819f
		if (st && !st->multi_type_permitted
Packit 1c819f
		 && st->prefix && t->prefix != st->prefix)
Packit 1c819f
			continue;
Packit 1c819f
Packit 1c819f
		tmpl = t->prefix->context;
Packit 1c819f
		if (tmpl != current) {
Packit 1c819f
			printf("\nAttributes for object type %s; using prefix %s\n",
Packit 1c819f
				tmpl->iot_name, t->prefix->name);
Packit 1c819f
			current = tmpl;
Packit 1c819f
		}
Packit 1c819f
Packit 1c819f
		snprintf(namebuf, sizeof(namebuf), "%s%s", t->prefix->name, t->name);
Packit 1c819f
		printf("  %-20s   ", namebuf);
Packit 1c819f
Packit 1c819f
		tag_type = isns_tag_type_by_id(t->tag);
Packit 1c819f
		if (tag_type == NULL) {
Packit 1c819f
			printf("Unknown\n");
Packit 1c819f
			continue;
Packit 1c819f
		}
Packit 1c819f
		printf("%s (%s", tag_type->it_name,
Packit 1c819f
				tag_type->it_type->it_name);
Packit 1c819f
Packit 1c819f
		if (tag_type->it_readonly)
Packit 1c819f
			printf("; readonly");
Packit 1c819f
		if (tag_type->it_multiple)
Packit 1c819f
			printf("; multiple instances");
Packit 1c819f
		printf(")");
Packit 1c819f
Packit 1c819f
		help = NULL;
Packit 1c819f
		if (t->tag == OPENISNS_TAG_POLICY_KEY) {
Packit 1c819f
			help = "name of key file, or \"gen\" for key generation";
Packit 1c819f
		} else
Packit 1c819f
		if (tag_type->it_help)
Packit 1c819f
			help = tag_type->it_help();
Packit 1c819f
Packit 1c819f
		if (help) {
Packit 1c819f
			if (strlen(help) < 20)
Packit 1c819f
				printf(" [%s]", help);
Packit 1c819f
			else
Packit 1c819f
				printf("\n%25s[%s]", "", help);
Packit 1c819f
		}
Packit 1c819f
		printf("\n");
Packit 1c819f
Packit 1c819f
		if (t->alias[0]) {
Packit 1c819f
			printf("%25sAliases:", "");
Packit 1c819f
			for (i = 0; i < MAX_ALIASES && t->alias[i]; ++i)
Packit 1c819f
				printf(" %s", t->alias[i]);
Packit 1c819f
			printf("\n");
Packit 1c819f
		}
Packit 1c819f
	}
Packit 1c819f
}
Packit 1c819f
Packit 1c819f
isns_object_template_t *
Packit 1c819f
isns_attr_list_parser_context(const struct isns_attr_list_parser *st)
Packit 1c819f
{
Packit 1c819f
	if (st->prefix)
Packit 1c819f
		return st->prefix->context;
Packit 1c819f
	return NULL;
Packit 1c819f
}
Packit 1c819f
Packit 1c819f
int
Packit 1c819f
isns_print_attrs(isns_object_t *obj, char **argv, unsigned int argsmax)
Packit 1c819f
{
Packit 1c819f
	struct isns_attr_list_parser st;
Packit 1c819f
	unsigned int	i, argc = 0;
Packit 1c819f
Packit 1c819f
	isns_attr_list_parser_init(&st, obj->ie_template);
Packit 1c819f
Packit 1c819f
	for (i = 0; i < obj->ie_attrs.ial_count; ++i) {
Packit 1c819f
		isns_attr_t *attr = obj->ie_attrs.ial_data[i];
Packit 1c819f
		char		argbuf[512], value[512];
Packit 1c819f
		const char	*name;
Packit 1c819f
Packit 1c819f
		name = name_by_tag(attr->ia_tag_id, &st);
Packit 1c819f
		if (name == NULL)
Packit 1c819f
			continue;
Packit 1c819f
		if (argc + 1 >= argsmax)
Packit 1c819f
			break;
Packit 1c819f
Packit 1c819f
		snprintf(argbuf, sizeof(argbuf), "%s%s=%s",
Packit 1c819f
				st.prefix->name, name,
Packit 1c819f
				isns_attr_print_value(attr, value, sizeof(value)));
Packit 1c819f
		argv[argc++] = isns_strdup(argbuf);
Packit 1c819f
	}
Packit 1c819f
Packit 1c819f
	argv[argc] = NULL;
Packit 1c819f
	return argc;
Packit 1c819f
}