xref: /titanic_51/usr/src/cmd/datadm/datadm.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <unistd.h>
30*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
31*7c478bd9Sstevel@tonic-gate #include <sys/socket.h>
32*7c478bd9Sstevel@tonic-gate #include <sys/sockio.h>
33*7c478bd9Sstevel@tonic-gate #include <netinet/in.h>
34*7c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
35*7c478bd9Sstevel@tonic-gate #include <net/if.h>
36*7c478bd9Sstevel@tonic-gate #include <stdio.h>
37*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
38*7c478bd9Sstevel@tonic-gate #include <strings.h>
39*7c478bd9Sstevel@tonic-gate #include <ctype.h>
40*7c478bd9Sstevel@tonic-gate #include <errno.h>
41*7c478bd9Sstevel@tonic-gate #include <libintl.h>
42*7c478bd9Sstevel@tonic-gate #include <locale.h>
43*7c478bd9Sstevel@tonic-gate #include <libdevinfo.h>
44*7c478bd9Sstevel@tonic-gate 
45*7c478bd9Sstevel@tonic-gate #define	DATADM_OP_VIEW		0x0000
46*7c478bd9Sstevel@tonic-gate #define	DATADM_OP_UPDATE	0x0001
47*7c478bd9Sstevel@tonic-gate #define	DATADM_OP_ADD		0x0002
48*7c478bd9Sstevel@tonic-gate #define	DATADM_OP_REMOVE	0x0003
49*7c478bd9Sstevel@tonic-gate #define	DATADM_NUM_OPS		0x0004
50*7c478bd9Sstevel@tonic-gate #define	DATADM_DAT_CONF		"/etc/dat/dat.conf"
51*7c478bd9Sstevel@tonic-gate #define	DATADM_LINESZ		1024
52*7c478bd9Sstevel@tonic-gate #define	DATADM_NUM_SP_TOKENS	7
53*7c478bd9Sstevel@tonic-gate #define	DATADM_NUM_DAT_TOKENS	8
54*7c478bd9Sstevel@tonic-gate #define	DATADM_IA_NAME		"ibd"
55*7c478bd9Sstevel@tonic-gate #define	DATADM_DRV_NAME		"driver_name"
56*7c478bd9Sstevel@tonic-gate #define	DATADM_MAX_TOKENS	16
57*7c478bd9Sstevel@tonic-gate 
58*7c478bd9Sstevel@tonic-gate /*
59*7c478bd9Sstevel@tonic-gate  * generic entry
60*7c478bd9Sstevel@tonic-gate  * placed at the top of all entry types
61*7c478bd9Sstevel@tonic-gate  */
62*7c478bd9Sstevel@tonic-gate typedef struct datadm_entry {
63*7c478bd9Sstevel@tonic-gate 	struct datadm_entry	*de_next;
64*7c478bd9Sstevel@tonic-gate } datadm_entry_t;
65*7c478bd9Sstevel@tonic-gate 
66*7c478bd9Sstevel@tonic-gate /*
67*7c478bd9Sstevel@tonic-gate  * list structure
68*7c478bd9Sstevel@tonic-gate  * can be manipulated using datadm_walk_list or
69*7c478bd9Sstevel@tonic-gate  * datadm_enqueue_entry
70*7c478bd9Sstevel@tonic-gate  */
71*7c478bd9Sstevel@tonic-gate typedef struct datadm_list {
72*7c478bd9Sstevel@tonic-gate 	datadm_entry_t		*dl_head;
73*7c478bd9Sstevel@tonic-gate 	datadm_entry_t		*dl_tail;
74*7c478bd9Sstevel@tonic-gate 	uint_t			dl_count;
75*7c478bd9Sstevel@tonic-gate } datadm_list_t;
76*7c478bd9Sstevel@tonic-gate 
77*7c478bd9Sstevel@tonic-gate /*
78*7c478bd9Sstevel@tonic-gate  * internal representation of the version string in
79*7c478bd9Sstevel@tonic-gate  * dat.conf or service_provider.conf. the format is
80*7c478bd9Sstevel@tonic-gate  * <dv_name><dv_major>.<dv_minor>
81*7c478bd9Sstevel@tonic-gate  */
82*7c478bd9Sstevel@tonic-gate typedef struct datadm_version {
83*7c478bd9Sstevel@tonic-gate 	char	*dv_name;
84*7c478bd9Sstevel@tonic-gate 	uint_t	dv_major;
85*7c478bd9Sstevel@tonic-gate 	uint_t	dv_minor;
86*7c478bd9Sstevel@tonic-gate } datadm_version_t;
87*7c478bd9Sstevel@tonic-gate 
88*7c478bd9Sstevel@tonic-gate /*
89*7c478bd9Sstevel@tonic-gate  * each sp_entry corresponds to an entry in dat.conf or
90*7c478bd9Sstevel@tonic-gate  * service_provider.conf. an sp_entry is processed by the
91*7c478bd9Sstevel@tonic-gate  * function datadm_process_sp_entry.
92*7c478bd9Sstevel@tonic-gate  */
93*7c478bd9Sstevel@tonic-gate typedef struct datadm_sp_entry {
94*7c478bd9Sstevel@tonic-gate 	datadm_entry_t		spe_header;
95*7c478bd9Sstevel@tonic-gate 	char			*spe_devname;
96*7c478bd9Sstevel@tonic-gate 	datadm_version_t	spe_api_version;
97*7c478bd9Sstevel@tonic-gate 	int			spe_threadsafe;
98*7c478bd9Sstevel@tonic-gate 	int			spe_default;
99*7c478bd9Sstevel@tonic-gate 	char			*spe_libpath;
100*7c478bd9Sstevel@tonic-gate 	datadm_version_t	spe_sp_version;
101*7c478bd9Sstevel@tonic-gate 	char			*spe_sp_data;
102*7c478bd9Sstevel@tonic-gate 	int			spe_invalid;
103*7c478bd9Sstevel@tonic-gate } datadm_sp_entry_t;
104*7c478bd9Sstevel@tonic-gate 
105*7c478bd9Sstevel@tonic-gate /*
106*7c478bd9Sstevel@tonic-gate  * an hca_entry is created whenever a new hca device is
107*7c478bd9Sstevel@tonic-gate  * encountered during sp_entry processing. this structure
108*7c478bd9Sstevel@tonic-gate  * contains two lists. the sp_list holds sp entries that
109*7c478bd9Sstevel@tonic-gate  * are added when sp entry processing occurs. duplicate
110*7c478bd9Sstevel@tonic-gate  * sp entries are not added to this list. the ia_list may
111*7c478bd9Sstevel@tonic-gate  * be built statically using the information in dat.conf or
112*7c478bd9Sstevel@tonic-gate  * dynamically using libdevinfo. similar to the sp_list,
113*7c478bd9Sstevel@tonic-gate  * the ia_list contains only unique entries.
114*7c478bd9Sstevel@tonic-gate  */
115*7c478bd9Sstevel@tonic-gate typedef struct datadm_hca_entry {
116*7c478bd9Sstevel@tonic-gate 	datadm_entry_t		he_header;
117*7c478bd9Sstevel@tonic-gate 	char			*he_name;
118*7c478bd9Sstevel@tonic-gate 	datadm_list_t		he_sp_list;
119*7c478bd9Sstevel@tonic-gate 	datadm_list_t		he_ia_list;
120*7c478bd9Sstevel@tonic-gate } datadm_hca_entry_t;
121*7c478bd9Sstevel@tonic-gate 
122*7c478bd9Sstevel@tonic-gate /*
123*7c478bd9Sstevel@tonic-gate  * an ia_entry is created when a new ia name is encountered
124*7c478bd9Sstevel@tonic-gate  * during sp_entry processing or when a new ia name is
125*7c478bd9Sstevel@tonic-gate  * discovered by datadm_fill_ia_list. ia_entry holds the ia
126*7c478bd9Sstevel@tonic-gate  * device's instance number.
127*7c478bd9Sstevel@tonic-gate  */
128*7c478bd9Sstevel@tonic-gate typedef struct datadm_ia_entry {
129*7c478bd9Sstevel@tonic-gate 	datadm_entry_t		iae_header;
130*7c478bd9Sstevel@tonic-gate 	int			iae_devnum;
131*7c478bd9Sstevel@tonic-gate } datadm_ia_entry_t;
132*7c478bd9Sstevel@tonic-gate 
133*7c478bd9Sstevel@tonic-gate /*
134*7c478bd9Sstevel@tonic-gate  * a comment entry represents one of the comment lines at the
135*7c478bd9Sstevel@tonic-gate  * top of dat.conf. a list of these lines are saved during the
136*7c478bd9Sstevel@tonic-gate  * parsing of dat.conf. these lines are written back to dat.conf
137*7c478bd9Sstevel@tonic-gate  * when dat.conf gets regenerated.
138*7c478bd9Sstevel@tonic-gate  */
139*7c478bd9Sstevel@tonic-gate typedef struct datadm_cmnt_entry {
140*7c478bd9Sstevel@tonic-gate 	datadm_entry_t		cmnt_header;
141*7c478bd9Sstevel@tonic-gate 	char			*cmnt_line;
142*7c478bd9Sstevel@tonic-gate } datadm_cmnt_entry_t;
143*7c478bd9Sstevel@tonic-gate 
144*7c478bd9Sstevel@tonic-gate /*
145*7c478bd9Sstevel@tonic-gate  * 2nd argument to datadm_hca_entry_find.
146*7c478bd9Sstevel@tonic-gate  * hf_hca_entry is filled in if an hca_entry with
147*7c478bd9Sstevel@tonic-gate  * a matching he_name is found.
148*7c478bd9Sstevel@tonic-gate  */
149*7c478bd9Sstevel@tonic-gate typedef struct datadm_hca_find {
150*7c478bd9Sstevel@tonic-gate 	datadm_sp_entry_t	*hf_sp_entry;
151*7c478bd9Sstevel@tonic-gate 	datadm_hca_entry_t	*hf_hca_entry;
152*7c478bd9Sstevel@tonic-gate } datadm_hca_find_t;
153*7c478bd9Sstevel@tonic-gate 
154*7c478bd9Sstevel@tonic-gate /*
155*7c478bd9Sstevel@tonic-gate  * 2nd argument to datadm_ia_entry_find.
156*7c478bd9Sstevel@tonic-gate  * if_ia_entry is filled in if an ia_entry with
157*7c478bd9Sstevel@tonic-gate  * a matching ia_devnum is found.
158*7c478bd9Sstevel@tonic-gate  */
159*7c478bd9Sstevel@tonic-gate typedef struct datadm_ia_find {
160*7c478bd9Sstevel@tonic-gate 	int			if_ia_devnum;
161*7c478bd9Sstevel@tonic-gate 	datadm_ia_entry_t	*if_ia_entry;
162*7c478bd9Sstevel@tonic-gate } datadm_ia_find_t;
163*7c478bd9Sstevel@tonic-gate 
164*7c478bd9Sstevel@tonic-gate /*
165*7c478bd9Sstevel@tonic-gate  * this gets passed to datadm_fill_ia_list.
166*7c478bd9Sstevel@tonic-gate  * we do this to avoid regenerating the device
167*7c478bd9Sstevel@tonic-gate  * tree for each hca_entry we process.
168*7c478bd9Sstevel@tonic-gate  */
169*7c478bd9Sstevel@tonic-gate typedef struct datadm_fill_ia_list {
170*7c478bd9Sstevel@tonic-gate 	di_node_t		ia_root_node;
171*7c478bd9Sstevel@tonic-gate 	int			ia_sock_fd_v4;
172*7c478bd9Sstevel@tonic-gate 	int			ia_sock_fd_v6;
173*7c478bd9Sstevel@tonic-gate } datadm_fill_ia_list_t;
174*7c478bd9Sstevel@tonic-gate 
175*7c478bd9Sstevel@tonic-gate /*
176*7c478bd9Sstevel@tonic-gate  * this defines the commandline parameters specified
177*7c478bd9Sstevel@tonic-gate  * by the user.
178*7c478bd9Sstevel@tonic-gate  */
179*7c478bd9Sstevel@tonic-gate typedef struct datadm_args {
180*7c478bd9Sstevel@tonic-gate 	char			*da_sp_conf;
181*7c478bd9Sstevel@tonic-gate 	char			*da_dat_conf;
182*7c478bd9Sstevel@tonic-gate 	int			da_op_type;
183*7c478bd9Sstevel@tonic-gate } datadm_args_t;
184*7c478bd9Sstevel@tonic-gate 
185*7c478bd9Sstevel@tonic-gate static datadm_args_t		datadm_args;
186*7c478bd9Sstevel@tonic-gate static datadm_list_t		datadm_conf_header;
187*7c478bd9Sstevel@tonic-gate static char			*datadm_conf_header_default =
188*7c478bd9Sstevel@tonic-gate 	"#\n"
189*7c478bd9Sstevel@tonic-gate 	"# Copyright 2004 Sun Microsystems, Inc.  All rights reserved.\n"
190*7c478bd9Sstevel@tonic-gate 	"# Use is subject to license terms.\n"
191*7c478bd9Sstevel@tonic-gate 	"#\n"
192*7c478bd9Sstevel@tonic-gate 	"# ident \"@(#)dat.conf   1.1     03/08/26 SMI\"\n"
193*7c478bd9Sstevel@tonic-gate 	"#\n"
194*7c478bd9Sstevel@tonic-gate 	"# DAT configuration file.\n"
195*7c478bd9Sstevel@tonic-gate 	"#\n"
196*7c478bd9Sstevel@tonic-gate 	"# This file is updated using the datadm(1) command.\n"
197*7c478bd9Sstevel@tonic-gate 	"# Do not hand edit this file.\n"
198*7c478bd9Sstevel@tonic-gate 	"# See datadm(1) man page for more details.\n"
199*7c478bd9Sstevel@tonic-gate 	"#\n"
200*7c478bd9Sstevel@tonic-gate 	"# The fields in this file are -\n"
201*7c478bd9Sstevel@tonic-gate 	"#\n"
202*7c478bd9Sstevel@tonic-gate 	"# IAname version threadsafe default library-path provider-version \\\n"
203*7c478bd9Sstevel@tonic-gate 	"# instance-data platform-information\n"
204*7c478bd9Sstevel@tonic-gate 	"#\n";
205*7c478bd9Sstevel@tonic-gate 
206*7c478bd9Sstevel@tonic-gate /*
207*7c478bd9Sstevel@tonic-gate  * common parsing functions.
208*7c478bd9Sstevel@tonic-gate  */
209*7c478bd9Sstevel@tonic-gate typedef int (*datadm_parse_func_t)(char *, void *);
210*7c478bd9Sstevel@tonic-gate static int datadm_parse_line(char *, char *[], int *);
211*7c478bd9Sstevel@tonic-gate static int datadm_parse_generic_str(char *, char **);
212*7c478bd9Sstevel@tonic-gate static int datadm_parse_nonnull_str(char *, char **);
213*7c478bd9Sstevel@tonic-gate static int datadm_parse_version(char *, datadm_version_t *);
214*7c478bd9Sstevel@tonic-gate static int datadm_parse_devname(char *, datadm_sp_entry_t *);
215*7c478bd9Sstevel@tonic-gate static int datadm_parse_api_version(char *, datadm_sp_entry_t *);
216*7c478bd9Sstevel@tonic-gate static int datadm_parse_threadsafe(char *, datadm_sp_entry_t *);
217*7c478bd9Sstevel@tonic-gate static int datadm_parse_default(char *, datadm_sp_entry_t *);
218*7c478bd9Sstevel@tonic-gate static int datadm_parse_libpath(char *, datadm_sp_entry_t *);
219*7c478bd9Sstevel@tonic-gate static int datadm_parse_sp_version(char *, datadm_sp_entry_t *);
220*7c478bd9Sstevel@tonic-gate static int datadm_parse_sp_data(char *, datadm_sp_entry_t *);
221*7c478bd9Sstevel@tonic-gate static int datadm_parse_ia_name(char *, int *);
222*7c478bd9Sstevel@tonic-gate 
223*7c478bd9Sstevel@tonic-gate /*
224*7c478bd9Sstevel@tonic-gate  * utility functions
225*7c478bd9Sstevel@tonic-gate  */
226*7c478bd9Sstevel@tonic-gate static void datadm_enqueue_entry(datadm_list_t *, datadm_entry_t *);
227*7c478bd9Sstevel@tonic-gate static int datadm_walk_list(datadm_list_t *,
228*7c478bd9Sstevel@tonic-gate     int (*)(datadm_entry_t *, void *), void *);
229*7c478bd9Sstevel@tonic-gate static int datadm_str_match(char *, char *);
230*7c478bd9Sstevel@tonic-gate static int datadm_version_match(datadm_version_t *, datadm_version_t *);
231*7c478bd9Sstevel@tonic-gate static int datadm_sp_entry_match(datadm_sp_entry_t *, datadm_sp_entry_t *);
232*7c478bd9Sstevel@tonic-gate 
233*7c478bd9Sstevel@tonic-gate /*
234*7c478bd9Sstevel@tonic-gate  * entry allocation/deallocation
235*7c478bd9Sstevel@tonic-gate  */
236*7c478bd9Sstevel@tonic-gate static datadm_sp_entry_t *datadm_alloc_sp_entry(void);
237*7c478bd9Sstevel@tonic-gate static datadm_ia_entry_t *datadm_alloc_ia_entry(void);
238*7c478bd9Sstevel@tonic-gate static datadm_hca_entry_t *datadm_alloc_hca_entry(void);
239*7c478bd9Sstevel@tonic-gate static datadm_cmnt_entry_t *datadm_alloc_cmnt_entry(void);
240*7c478bd9Sstevel@tonic-gate static void datadm_free_sp_entry(datadm_sp_entry_t *);
241*7c478bd9Sstevel@tonic-gate static void datadm_free_ia_entry(datadm_ia_entry_t *);
242*7c478bd9Sstevel@tonic-gate static void datadm_free_hca_entry(datadm_hca_entry_t *);
243*7c478bd9Sstevel@tonic-gate static void datadm_free_cmnt_entry(datadm_cmnt_entry_t *);
244*7c478bd9Sstevel@tonic-gate 
245*7c478bd9Sstevel@tonic-gate 
246*7c478bd9Sstevel@tonic-gate /*
247*7c478bd9Sstevel@tonic-gate  * high level parsing functions
248*7c478bd9Sstevel@tonic-gate  */
249*7c478bd9Sstevel@tonic-gate static int datadm_parse_sp_conf(datadm_list_t *);
250*7c478bd9Sstevel@tonic-gate static int datadm_parse_dat_conf(datadm_list_t *);
251*7c478bd9Sstevel@tonic-gate static int datadm_process_sp_entry(datadm_list_t *, datadm_sp_entry_t *, int);
252*7c478bd9Sstevel@tonic-gate 
253*7c478bd9Sstevel@tonic-gate /*
254*7c478bd9Sstevel@tonic-gate  * ia devices discovery
255*7c478bd9Sstevel@tonic-gate  */
256*7c478bd9Sstevel@tonic-gate static int datadm_build_ia_lists(datadm_list_t *);
257*7c478bd9Sstevel@tonic-gate static int datadm_fill_ia_list(datadm_hca_entry_t *, datadm_fill_ia_list_t *);
258*7c478bd9Sstevel@tonic-gate 
259*7c478bd9Sstevel@tonic-gate /*
260*7c478bd9Sstevel@tonic-gate  * helper function for OP_REMOVE
261*7c478bd9Sstevel@tonic-gate  */
262*7c478bd9Sstevel@tonic-gate static void datadm_invalidate_common_sp_entries(datadm_list_t *,
263*7c478bd9Sstevel@tonic-gate     datadm_list_t *);
264*7c478bd9Sstevel@tonic-gate 
265*7c478bd9Sstevel@tonic-gate /*
266*7c478bd9Sstevel@tonic-gate  * output generation
267*7c478bd9Sstevel@tonic-gate  */
268*7c478bd9Sstevel@tonic-gate static int datadm_generate_dat_conf(datadm_list_t *);
269*7c478bd9Sstevel@tonic-gate static int datadm_generate_conf_header(FILE *);
270*7c478bd9Sstevel@tonic-gate static int datadm_generate_conf_entry(FILE *, datadm_ia_entry_t *,
271*7c478bd9Sstevel@tonic-gate     datadm_sp_entry_t *);
272*7c478bd9Sstevel@tonic-gate 
273*7c478bd9Sstevel@tonic-gate /*
274*7c478bd9Sstevel@tonic-gate  * datadm operations
275*7c478bd9Sstevel@tonic-gate  */
276*7c478bd9Sstevel@tonic-gate static int datadm_view(void);
277*7c478bd9Sstevel@tonic-gate static int datadm_update(void);
278*7c478bd9Sstevel@tonic-gate static int datadm_add(void);
279*7c478bd9Sstevel@tonic-gate static int datadm_remove(void);
280*7c478bd9Sstevel@tonic-gate 
281*7c478bd9Sstevel@tonic-gate /*
282*7c478bd9Sstevel@tonic-gate  * usage
283*7c478bd9Sstevel@tonic-gate  */
284*7c478bd9Sstevel@tonic-gate static void datadm_usage(void);
285*7c478bd9Sstevel@tonic-gate 
286*7c478bd9Sstevel@tonic-gate 
287*7c478bd9Sstevel@tonic-gate /*
288*7c478bd9Sstevel@tonic-gate  * parse function tables
289*7c478bd9Sstevel@tonic-gate  */
290*7c478bd9Sstevel@tonic-gate static datadm_parse_func_t datadm_sp_parse_funcs[DATADM_NUM_SP_TOKENS] = {
291*7c478bd9Sstevel@tonic-gate 	(datadm_parse_func_t)datadm_parse_devname,
292*7c478bd9Sstevel@tonic-gate 	(datadm_parse_func_t)datadm_parse_api_version,
293*7c478bd9Sstevel@tonic-gate 	(datadm_parse_func_t)datadm_parse_threadsafe,
294*7c478bd9Sstevel@tonic-gate 	(datadm_parse_func_t)datadm_parse_default,
295*7c478bd9Sstevel@tonic-gate 	(datadm_parse_func_t)datadm_parse_libpath,
296*7c478bd9Sstevel@tonic-gate 	(datadm_parse_func_t)datadm_parse_sp_version,
297*7c478bd9Sstevel@tonic-gate 	(datadm_parse_func_t)datadm_parse_sp_data
298*7c478bd9Sstevel@tonic-gate };
299*7c478bd9Sstevel@tonic-gate 
300*7c478bd9Sstevel@tonic-gate static datadm_parse_func_t datadm_dat_parse_funcs[DATADM_NUM_DAT_TOKENS] = {
301*7c478bd9Sstevel@tonic-gate 	(datadm_parse_func_t)datadm_parse_ia_name,
302*7c478bd9Sstevel@tonic-gate 	(datadm_parse_func_t)datadm_parse_api_version,
303*7c478bd9Sstevel@tonic-gate 	(datadm_parse_func_t)datadm_parse_threadsafe,
304*7c478bd9Sstevel@tonic-gate 	(datadm_parse_func_t)datadm_parse_default,
305*7c478bd9Sstevel@tonic-gate 	(datadm_parse_func_t)datadm_parse_libpath,
306*7c478bd9Sstevel@tonic-gate 	(datadm_parse_func_t)datadm_parse_sp_version,
307*7c478bd9Sstevel@tonic-gate 	(datadm_parse_func_t)datadm_parse_sp_data,
308*7c478bd9Sstevel@tonic-gate 	(datadm_parse_func_t)datadm_parse_devname
309*7c478bd9Sstevel@tonic-gate };
310*7c478bd9Sstevel@tonic-gate 
311*7c478bd9Sstevel@tonic-gate /*
312*7c478bd9Sstevel@tonic-gate  * operation table
313*7c478bd9Sstevel@tonic-gate  */
314*7c478bd9Sstevel@tonic-gate static int (*datadm_ops[DATADM_NUM_OPS])(void) = {
315*7c478bd9Sstevel@tonic-gate 	datadm_view,
316*7c478bd9Sstevel@tonic-gate 	datadm_update,
317*7c478bd9Sstevel@tonic-gate 	datadm_add,
318*7c478bd9Sstevel@tonic-gate 	datadm_remove
319*7c478bd9Sstevel@tonic-gate };
320*7c478bd9Sstevel@tonic-gate 
321*7c478bd9Sstevel@tonic-gate static void
322*7c478bd9Sstevel@tonic-gate datadm_usage(void)
323*7c478bd9Sstevel@tonic-gate {
324*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext(
325*7c478bd9Sstevel@tonic-gate 	    "usage: datadm -v\n"
326*7c478bd9Sstevel@tonic-gate 	    "              -u\n"
327*7c478bd9Sstevel@tonic-gate 	    "              -a <service_provider.conf>\n"
328*7c478bd9Sstevel@tonic-gate 	    "              -r <service_provider.conf>\n"));
329*7c478bd9Sstevel@tonic-gate }
330*7c478bd9Sstevel@tonic-gate 
331*7c478bd9Sstevel@tonic-gate static int
332*7c478bd9Sstevel@tonic-gate datadm_parse_generic_str(char *str, char **strptr)
333*7c478bd9Sstevel@tonic-gate {
334*7c478bd9Sstevel@tonic-gate 	int	len;
335*7c478bd9Sstevel@tonic-gate 
336*7c478bd9Sstevel@tonic-gate 	len = strlen(str);
337*7c478bd9Sstevel@tonic-gate 	*strptr = (char *)malloc(len + 1);
338*7c478bd9Sstevel@tonic-gate 	if (*strptr == NULL) {
339*7c478bd9Sstevel@tonic-gate 		return (-1);
340*7c478bd9Sstevel@tonic-gate 	}
341*7c478bd9Sstevel@tonic-gate 	(void) strcpy(*strptr, str);
342*7c478bd9Sstevel@tonic-gate 	return (0);
343*7c478bd9Sstevel@tonic-gate }
344*7c478bd9Sstevel@tonic-gate 
345*7c478bd9Sstevel@tonic-gate /*
346*7c478bd9Sstevel@tonic-gate  * this function strips off leading and trailing
347*7c478bd9Sstevel@tonic-gate  * whitespaces and returns an error for null or
348*7c478bd9Sstevel@tonic-gate  * empty strings.
349*7c478bd9Sstevel@tonic-gate  */
350*7c478bd9Sstevel@tonic-gate static int
351*7c478bd9Sstevel@tonic-gate datadm_parse_nonnull_str(char *str, char **strptr)
352*7c478bd9Sstevel@tonic-gate {
353*7c478bd9Sstevel@tonic-gate 	int	len, i;
354*7c478bd9Sstevel@tonic-gate 	char	*start;
355*7c478bd9Sstevel@tonic-gate 
356*7c478bd9Sstevel@tonic-gate 	if (str[0] == '\0') {
357*7c478bd9Sstevel@tonic-gate 		return (-1);
358*7c478bd9Sstevel@tonic-gate 	}
359*7c478bd9Sstevel@tonic-gate 	start = str;
360*7c478bd9Sstevel@tonic-gate 	for (i = 0; str[i] != '\0'; i++) {
361*7c478bd9Sstevel@tonic-gate 		if (!isspace(str[i])) {
362*7c478bd9Sstevel@tonic-gate 			start = &str[i];
363*7c478bd9Sstevel@tonic-gate 			break;
364*7c478bd9Sstevel@tonic-gate 		}
365*7c478bd9Sstevel@tonic-gate 	}
366*7c478bd9Sstevel@tonic-gate 	for (; str[i] != '\0'; i++) {
367*7c478bd9Sstevel@tonic-gate 		if (isspace(str[i])) {
368*7c478bd9Sstevel@tonic-gate 			str[i] = '\0';
369*7c478bd9Sstevel@tonic-gate 		}
370*7c478bd9Sstevel@tonic-gate 	}
371*7c478bd9Sstevel@tonic-gate 	len = strlen(start);
372*7c478bd9Sstevel@tonic-gate 	*strptr = (char *)malloc(len + 1);
373*7c478bd9Sstevel@tonic-gate 	if (*strptr == NULL) {
374*7c478bd9Sstevel@tonic-gate 		return (-1);
375*7c478bd9Sstevel@tonic-gate 	}
376*7c478bd9Sstevel@tonic-gate 	(void) strcpy(*strptr, start);
377*7c478bd9Sstevel@tonic-gate 	return (0);
378*7c478bd9Sstevel@tonic-gate }
379*7c478bd9Sstevel@tonic-gate 
380*7c478bd9Sstevel@tonic-gate /*
381*7c478bd9Sstevel@tonic-gate  * parses the api_version and sp_version fields in
382*7c478bd9Sstevel@tonic-gate  * dat.conf and service_provider.conf
383*7c478bd9Sstevel@tonic-gate  */
384*7c478bd9Sstevel@tonic-gate static int
385*7c478bd9Sstevel@tonic-gate datadm_parse_version(char *str, datadm_version_t *version)
386*7c478bd9Sstevel@tonic-gate {
387*7c478bd9Sstevel@tonic-gate 	int	i = 0, len;
388*7c478bd9Sstevel@tonic-gate 	int	major_idx, minor_idx;
389*7c478bd9Sstevel@tonic-gate 
390*7c478bd9Sstevel@tonic-gate 	len = strlen(str);
391*7c478bd9Sstevel@tonic-gate 
392*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < len; i++) {
393*7c478bd9Sstevel@tonic-gate 		if (isdigit(str[i])) break;
394*7c478bd9Sstevel@tonic-gate 	}
395*7c478bd9Sstevel@tonic-gate 	if (i == len) {
396*7c478bd9Sstevel@tonic-gate 		return (-1);
397*7c478bd9Sstevel@tonic-gate 	}
398*7c478bd9Sstevel@tonic-gate 	if (i > 0) {
399*7c478bd9Sstevel@tonic-gate 		version->dv_name = (char *)malloc(i + 1);
400*7c478bd9Sstevel@tonic-gate 		bcopy(str, version->dv_name, i);
401*7c478bd9Sstevel@tonic-gate 		version->dv_name[i] = '\0';
402*7c478bd9Sstevel@tonic-gate 	} else {
403*7c478bd9Sstevel@tonic-gate 		version->dv_name = NULL;
404*7c478bd9Sstevel@tonic-gate 	}
405*7c478bd9Sstevel@tonic-gate 	major_idx = i;
406*7c478bd9Sstevel@tonic-gate 
407*7c478bd9Sstevel@tonic-gate 	for (; i < len; i++) {
408*7c478bd9Sstevel@tonic-gate 		if (!isdigit(str[i])) break;
409*7c478bd9Sstevel@tonic-gate 	}
410*7c478bd9Sstevel@tonic-gate 	if (i == len) {
411*7c478bd9Sstevel@tonic-gate 		return (-1);
412*7c478bd9Sstevel@tonic-gate 	}
413*7c478bd9Sstevel@tonic-gate 	if (str[i] != '.') {
414*7c478bd9Sstevel@tonic-gate 		return (-1);
415*7c478bd9Sstevel@tonic-gate 	}
416*7c478bd9Sstevel@tonic-gate 	minor_idx = ++i;
417*7c478bd9Sstevel@tonic-gate 	if (i == len) {
418*7c478bd9Sstevel@tonic-gate 		return (-1);
419*7c478bd9Sstevel@tonic-gate 	}
420*7c478bd9Sstevel@tonic-gate 	for (; i < len; i++) {
421*7c478bd9Sstevel@tonic-gate 		if (!isdigit(str[i])) break;
422*7c478bd9Sstevel@tonic-gate 	}
423*7c478bd9Sstevel@tonic-gate 	if (i != len) {
424*7c478bd9Sstevel@tonic-gate 		return (-1);
425*7c478bd9Sstevel@tonic-gate 	}
426*7c478bd9Sstevel@tonic-gate 	version->dv_major = atoi(str + major_idx);
427*7c478bd9Sstevel@tonic-gate 	version->dv_minor = atoi(str + minor_idx);
428*7c478bd9Sstevel@tonic-gate 	return (0);
429*7c478bd9Sstevel@tonic-gate }
430*7c478bd9Sstevel@tonic-gate 
431*7c478bd9Sstevel@tonic-gate /*
432*7c478bd9Sstevel@tonic-gate  * parses the ia_name field in dat.conf
433*7c478bd9Sstevel@tonic-gate  */
434*7c478bd9Sstevel@tonic-gate static int
435*7c478bd9Sstevel@tonic-gate datadm_parse_ia_name(char *str, int *ia_devnum)
436*7c478bd9Sstevel@tonic-gate {
437*7c478bd9Sstevel@tonic-gate 	int	len;
438*7c478bd9Sstevel@tonic-gate 	int	i, start;
439*7c478bd9Sstevel@tonic-gate 
440*7c478bd9Sstevel@tonic-gate 	len = strlen(DATADM_IA_NAME);
441*7c478bd9Sstevel@tonic-gate 	if (strncmp(str, DATADM_IA_NAME, len) != 0) {
442*7c478bd9Sstevel@tonic-gate 		return (-1);
443*7c478bd9Sstevel@tonic-gate 	}
444*7c478bd9Sstevel@tonic-gate 	start = i = len;
445*7c478bd9Sstevel@tonic-gate 	len = strlen(str);
446*7c478bd9Sstevel@tonic-gate 	if (str[i] == '\0') {
447*7c478bd9Sstevel@tonic-gate 		return (-1);
448*7c478bd9Sstevel@tonic-gate 	}
449*7c478bd9Sstevel@tonic-gate 	for (; i < len; i++) {
450*7c478bd9Sstevel@tonic-gate 		if (!isdigit(str[i])) break;
451*7c478bd9Sstevel@tonic-gate 	}
452*7c478bd9Sstevel@tonic-gate 	if (i != len) {
453*7c478bd9Sstevel@tonic-gate 		return (-1);
454*7c478bd9Sstevel@tonic-gate 	}
455*7c478bd9Sstevel@tonic-gate 	*ia_devnum = atoi(str + start);
456*7c478bd9Sstevel@tonic-gate 	return (0);
457*7c478bd9Sstevel@tonic-gate }
458*7c478bd9Sstevel@tonic-gate 
459*7c478bd9Sstevel@tonic-gate /*
460*7c478bd9Sstevel@tonic-gate  * parses the device name, strips leading and trailing spaces.
461*7c478bd9Sstevel@tonic-gate  * the format should be "driver_name=<dev_name>"
462*7c478bd9Sstevel@tonic-gate  */
463*7c478bd9Sstevel@tonic-gate static int
464*7c478bd9Sstevel@tonic-gate datadm_parse_devname(char *str, datadm_sp_entry_t *sp_entry)
465*7c478bd9Sstevel@tonic-gate {
466*7c478bd9Sstevel@tonic-gate 	int	len, dlen, i, j = 0;
467*7c478bd9Sstevel@tonic-gate 	char	*drv_name = DATADM_DRV_NAME;
468*7c478bd9Sstevel@tonic-gate 
469*7c478bd9Sstevel@tonic-gate 	len = strlen(str);
470*7c478bd9Sstevel@tonic-gate 	dlen = strlen(drv_name);
471*7c478bd9Sstevel@tonic-gate 
472*7c478bd9Sstevel@tonic-gate 	/*
473*7c478bd9Sstevel@tonic-gate 	 * strip out leading spaces and try to match
474*7c478bd9Sstevel@tonic-gate 	 * the expected string
475*7c478bd9Sstevel@tonic-gate 	 */
476*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < len; i++) {
477*7c478bd9Sstevel@tonic-gate 		if (isspace(str[i]) && j == 0) {
478*7c478bd9Sstevel@tonic-gate 			continue;
479*7c478bd9Sstevel@tonic-gate 		} else {
480*7c478bd9Sstevel@tonic-gate 			if (str[i] == drv_name[j]) {
481*7c478bd9Sstevel@tonic-gate 				j++;
482*7c478bd9Sstevel@tonic-gate 				if (j == dlen) {
483*7c478bd9Sstevel@tonic-gate 					break;
484*7c478bd9Sstevel@tonic-gate 				} else {
485*7c478bd9Sstevel@tonic-gate 					continue;
486*7c478bd9Sstevel@tonic-gate 				}
487*7c478bd9Sstevel@tonic-gate 			} else {
488*7c478bd9Sstevel@tonic-gate 				break;
489*7c478bd9Sstevel@tonic-gate 			}
490*7c478bd9Sstevel@tonic-gate 		}
491*7c478bd9Sstevel@tonic-gate 	}
492*7c478bd9Sstevel@tonic-gate 
493*7c478bd9Sstevel@tonic-gate 	/*
494*7c478bd9Sstevel@tonic-gate 	 * j must be dlen if the matching string is found
495*7c478bd9Sstevel@tonic-gate 	 */
496*7c478bd9Sstevel@tonic-gate 	if (j != dlen) {
497*7c478bd9Sstevel@tonic-gate 		return (-1);
498*7c478bd9Sstevel@tonic-gate 	}
499*7c478bd9Sstevel@tonic-gate 
500*7c478bd9Sstevel@tonic-gate 	/*
501*7c478bd9Sstevel@tonic-gate 	 * skip past the last char of drv_name
502*7c478bd9Sstevel@tonic-gate 	 */
503*7c478bd9Sstevel@tonic-gate 	i++;
504*7c478bd9Sstevel@tonic-gate 
505*7c478bd9Sstevel@tonic-gate 	/*
506*7c478bd9Sstevel@tonic-gate 	 * strip the spaces before the '='
507*7c478bd9Sstevel@tonic-gate 	 */
508*7c478bd9Sstevel@tonic-gate 	for (; i < len; i++) {
509*7c478bd9Sstevel@tonic-gate 		if (!isspace(str[i])) {
510*7c478bd9Sstevel@tonic-gate 			break;
511*7c478bd9Sstevel@tonic-gate 		}
512*7c478bd9Sstevel@tonic-gate 	}
513*7c478bd9Sstevel@tonic-gate 
514*7c478bd9Sstevel@tonic-gate 	/*
515*7c478bd9Sstevel@tonic-gate 	 * return if the string is too long or if
516*7c478bd9Sstevel@tonic-gate 	 * the '=' isn't found
517*7c478bd9Sstevel@tonic-gate 	 */
518*7c478bd9Sstevel@tonic-gate 	if (i >= len || str[i] != '=') {
519*7c478bd9Sstevel@tonic-gate 		return (-1);
520*7c478bd9Sstevel@tonic-gate 	}
521*7c478bd9Sstevel@tonic-gate 	i++;
522*7c478bd9Sstevel@tonic-gate 	if (i >= len) {
523*7c478bd9Sstevel@tonic-gate 		/*
524*7c478bd9Sstevel@tonic-gate 		 * no string after the equal
525*7c478bd9Sstevel@tonic-gate 		 */
526*7c478bd9Sstevel@tonic-gate 		return (-1);
527*7c478bd9Sstevel@tonic-gate 	}
528*7c478bd9Sstevel@tonic-gate 	return (datadm_parse_nonnull_str(str + i, &sp_entry->spe_devname));
529*7c478bd9Sstevel@tonic-gate }
530*7c478bd9Sstevel@tonic-gate 
531*7c478bd9Sstevel@tonic-gate static int
532*7c478bd9Sstevel@tonic-gate datadm_parse_api_version(char *str, datadm_sp_entry_t *sp_entry)
533*7c478bd9Sstevel@tonic-gate {
534*7c478bd9Sstevel@tonic-gate 	return (datadm_parse_version(str, &sp_entry->spe_api_version));
535*7c478bd9Sstevel@tonic-gate }
536*7c478bd9Sstevel@tonic-gate 
537*7c478bd9Sstevel@tonic-gate static int
538*7c478bd9Sstevel@tonic-gate datadm_parse_threadsafe(char *str, datadm_sp_entry_t *sp_entry)
539*7c478bd9Sstevel@tonic-gate {
540*7c478bd9Sstevel@tonic-gate 	int retval = 0;
541*7c478bd9Sstevel@tonic-gate 
542*7c478bd9Sstevel@tonic-gate 	if (strcmp(str, "threadsafe") == 0) {
543*7c478bd9Sstevel@tonic-gate 		sp_entry->spe_threadsafe = 1;
544*7c478bd9Sstevel@tonic-gate 	} else if (strcmp(str, "nonthreadsafe") == 0) {
545*7c478bd9Sstevel@tonic-gate 		sp_entry->spe_threadsafe = 0;
546*7c478bd9Sstevel@tonic-gate 	} else {
547*7c478bd9Sstevel@tonic-gate 		retval = -1;
548*7c478bd9Sstevel@tonic-gate 	}
549*7c478bd9Sstevel@tonic-gate 	return (retval);
550*7c478bd9Sstevel@tonic-gate }
551*7c478bd9Sstevel@tonic-gate 
552*7c478bd9Sstevel@tonic-gate static int
553*7c478bd9Sstevel@tonic-gate datadm_parse_default(char *str, datadm_sp_entry_t *sp_entry)
554*7c478bd9Sstevel@tonic-gate {
555*7c478bd9Sstevel@tonic-gate 	int retval = 0;
556*7c478bd9Sstevel@tonic-gate 
557*7c478bd9Sstevel@tonic-gate 	if (strcmp(str, "default") == 0) {
558*7c478bd9Sstevel@tonic-gate 		sp_entry->spe_default = 1;
559*7c478bd9Sstevel@tonic-gate 	} else if (strcmp(str, "nondefault") == 0) {
560*7c478bd9Sstevel@tonic-gate 		sp_entry->spe_default = 0;
561*7c478bd9Sstevel@tonic-gate 	} else {
562*7c478bd9Sstevel@tonic-gate 		retval = -1;
563*7c478bd9Sstevel@tonic-gate 	}
564*7c478bd9Sstevel@tonic-gate 	return (retval);
565*7c478bd9Sstevel@tonic-gate }
566*7c478bd9Sstevel@tonic-gate 
567*7c478bd9Sstevel@tonic-gate static int
568*7c478bd9Sstevel@tonic-gate datadm_parse_libpath(char *str, datadm_sp_entry_t *sp_entry)
569*7c478bd9Sstevel@tonic-gate {
570*7c478bd9Sstevel@tonic-gate 	return (datadm_parse_nonnull_str(str, &sp_entry->spe_libpath));
571*7c478bd9Sstevel@tonic-gate }
572*7c478bd9Sstevel@tonic-gate 
573*7c478bd9Sstevel@tonic-gate static int
574*7c478bd9Sstevel@tonic-gate datadm_parse_sp_version(char *str, datadm_sp_entry_t *sp_entry)
575*7c478bd9Sstevel@tonic-gate {
576*7c478bd9Sstevel@tonic-gate 	return (datadm_parse_version(str, &sp_entry->spe_sp_version));
577*7c478bd9Sstevel@tonic-gate }
578*7c478bd9Sstevel@tonic-gate 
579*7c478bd9Sstevel@tonic-gate static int
580*7c478bd9Sstevel@tonic-gate datadm_parse_sp_data(char *str, datadm_sp_entry_t *sp_entry)
581*7c478bd9Sstevel@tonic-gate {
582*7c478bd9Sstevel@tonic-gate 	return (datadm_parse_generic_str(str, &sp_entry->spe_sp_data));
583*7c478bd9Sstevel@tonic-gate }
584*7c478bd9Sstevel@tonic-gate 
585*7c478bd9Sstevel@tonic-gate static void
586*7c478bd9Sstevel@tonic-gate datadm_enqueue_entry(datadm_list_t *list, datadm_entry_t *entry)
587*7c478bd9Sstevel@tonic-gate {
588*7c478bd9Sstevel@tonic-gate 	if (list->dl_head == NULL) {
589*7c478bd9Sstevel@tonic-gate 		list->dl_head = entry;
590*7c478bd9Sstevel@tonic-gate 		list->dl_tail = entry;
591*7c478bd9Sstevel@tonic-gate 		list->dl_count = 1;
592*7c478bd9Sstevel@tonic-gate 	} else {
593*7c478bd9Sstevel@tonic-gate 		list->dl_tail->de_next = entry;
594*7c478bd9Sstevel@tonic-gate 		list->dl_tail = entry;
595*7c478bd9Sstevel@tonic-gate 		list->dl_count++;
596*7c478bd9Sstevel@tonic-gate 	}
597*7c478bd9Sstevel@tonic-gate }
598*7c478bd9Sstevel@tonic-gate 
599*7c478bd9Sstevel@tonic-gate /*
600*7c478bd9Sstevel@tonic-gate  * iterates through the list applying func on each element.
601*7c478bd9Sstevel@tonic-gate  * break and return if func returns non-zero.
602*7c478bd9Sstevel@tonic-gate  */
603*7c478bd9Sstevel@tonic-gate static int
604*7c478bd9Sstevel@tonic-gate datadm_walk_list(datadm_list_t *list, int (*func)(datadm_entry_t *, void *),
605*7c478bd9Sstevel@tonic-gate 	void *arg)
606*7c478bd9Sstevel@tonic-gate {
607*7c478bd9Sstevel@tonic-gate 	datadm_entry_t	*entry;
608*7c478bd9Sstevel@tonic-gate 	int		retval = 0;
609*7c478bd9Sstevel@tonic-gate 
610*7c478bd9Sstevel@tonic-gate 	entry = list->dl_head;
611*7c478bd9Sstevel@tonic-gate 	while (entry != NULL) {
612*7c478bd9Sstevel@tonic-gate 		retval = (*func)(entry, arg);
613*7c478bd9Sstevel@tonic-gate 		if (retval != 0) break;
614*7c478bd9Sstevel@tonic-gate 		entry = entry->de_next;
615*7c478bd9Sstevel@tonic-gate 	}
616*7c478bd9Sstevel@tonic-gate 	return (retval);
617*7c478bd9Sstevel@tonic-gate }
618*7c478bd9Sstevel@tonic-gate 
619*7c478bd9Sstevel@tonic-gate /*
620*7c478bd9Sstevel@tonic-gate  * iterates through the list applying free_func to each element.
621*7c478bd9Sstevel@tonic-gate  * list becomes empty when the function returns.
622*7c478bd9Sstevel@tonic-gate  */
623*7c478bd9Sstevel@tonic-gate static void
624*7c478bd9Sstevel@tonic-gate datadm_free_list(datadm_list_t *list, void (*free_func)(datadm_entry_t *))
625*7c478bd9Sstevel@tonic-gate {
626*7c478bd9Sstevel@tonic-gate 	while (list->dl_head != NULL) {
627*7c478bd9Sstevel@tonic-gate 		datadm_entry_t	*entry;
628*7c478bd9Sstevel@tonic-gate 
629*7c478bd9Sstevel@tonic-gate 		entry = list->dl_head;
630*7c478bd9Sstevel@tonic-gate 		list->dl_head = entry->de_next;
631*7c478bd9Sstevel@tonic-gate 		(*free_func)(entry);
632*7c478bd9Sstevel@tonic-gate 	}
633*7c478bd9Sstevel@tonic-gate 	list->dl_count = 0;
634*7c478bd9Sstevel@tonic-gate 	list->dl_tail = NULL;
635*7c478bd9Sstevel@tonic-gate }
636*7c478bd9Sstevel@tonic-gate 
637*7c478bd9Sstevel@tonic-gate static datadm_sp_entry_t *
638*7c478bd9Sstevel@tonic-gate datadm_alloc_sp_entry(void)
639*7c478bd9Sstevel@tonic-gate {
640*7c478bd9Sstevel@tonic-gate 	datadm_sp_entry_t	*sp_entry;
641*7c478bd9Sstevel@tonic-gate 
642*7c478bd9Sstevel@tonic-gate 	sp_entry = (datadm_sp_entry_t *)malloc(sizeof (*sp_entry));
643*7c478bd9Sstevel@tonic-gate 	if (sp_entry == NULL) {
644*7c478bd9Sstevel@tonic-gate 		return (NULL);
645*7c478bd9Sstevel@tonic-gate 	}
646*7c478bd9Sstevel@tonic-gate 	bzero(sp_entry, sizeof (*sp_entry));
647*7c478bd9Sstevel@tonic-gate 	return (sp_entry);
648*7c478bd9Sstevel@tonic-gate }
649*7c478bd9Sstevel@tonic-gate 
650*7c478bd9Sstevel@tonic-gate static void
651*7c478bd9Sstevel@tonic-gate datadm_free_sp_entry(datadm_sp_entry_t *sp_entry)
652*7c478bd9Sstevel@tonic-gate {
653*7c478bd9Sstevel@tonic-gate 	if (sp_entry->spe_devname != NULL) {
654*7c478bd9Sstevel@tonic-gate 		free(sp_entry->spe_devname);
655*7c478bd9Sstevel@tonic-gate 		sp_entry->spe_devname = NULL;
656*7c478bd9Sstevel@tonic-gate 	}
657*7c478bd9Sstevel@tonic-gate 	if (sp_entry->spe_api_version.dv_name != NULL) {
658*7c478bd9Sstevel@tonic-gate 		free(sp_entry->spe_api_version.dv_name);
659*7c478bd9Sstevel@tonic-gate 		sp_entry->spe_api_version.dv_name = NULL;
660*7c478bd9Sstevel@tonic-gate 	}
661*7c478bd9Sstevel@tonic-gate 	sp_entry->spe_api_version.dv_major = 0;
662*7c478bd9Sstevel@tonic-gate 	sp_entry->spe_api_version.dv_minor = 0;
663*7c478bd9Sstevel@tonic-gate 	sp_entry->spe_threadsafe = 0;
664*7c478bd9Sstevel@tonic-gate 	sp_entry->spe_default = 0;
665*7c478bd9Sstevel@tonic-gate 	if (sp_entry->spe_libpath != NULL) {
666*7c478bd9Sstevel@tonic-gate 		free(sp_entry->spe_libpath);
667*7c478bd9Sstevel@tonic-gate 		sp_entry->spe_libpath = NULL;
668*7c478bd9Sstevel@tonic-gate 	}
669*7c478bd9Sstevel@tonic-gate 	if (sp_entry->spe_sp_version.dv_name != NULL) {
670*7c478bd9Sstevel@tonic-gate 		free(sp_entry->spe_sp_version.dv_name);
671*7c478bd9Sstevel@tonic-gate 		sp_entry->spe_sp_version.dv_name = NULL;
672*7c478bd9Sstevel@tonic-gate 	}
673*7c478bd9Sstevel@tonic-gate 	sp_entry->spe_sp_version.dv_major = 0;
674*7c478bd9Sstevel@tonic-gate 	sp_entry->spe_sp_version.dv_minor = 0;
675*7c478bd9Sstevel@tonic-gate 	if (sp_entry->spe_sp_data != NULL) {
676*7c478bd9Sstevel@tonic-gate 		free(sp_entry->spe_sp_data);
677*7c478bd9Sstevel@tonic-gate 		sp_entry->spe_sp_data = NULL;
678*7c478bd9Sstevel@tonic-gate 	}
679*7c478bd9Sstevel@tonic-gate 	free(sp_entry);
680*7c478bd9Sstevel@tonic-gate }
681*7c478bd9Sstevel@tonic-gate 
682*7c478bd9Sstevel@tonic-gate static int
683*7c478bd9Sstevel@tonic-gate datadm_str_match(char *s1, char *s2)
684*7c478bd9Sstevel@tonic-gate {
685*7c478bd9Sstevel@tonic-gate 	if (s1 == NULL || s2 == NULL) {
686*7c478bd9Sstevel@tonic-gate 		if (s1 != s2) {
687*7c478bd9Sstevel@tonic-gate 			return (0);
688*7c478bd9Sstevel@tonic-gate 		}
689*7c478bd9Sstevel@tonic-gate 	} else {
690*7c478bd9Sstevel@tonic-gate 		if (strcmp(s1, s2) != 0) {
691*7c478bd9Sstevel@tonic-gate 			return (0);
692*7c478bd9Sstevel@tonic-gate 		}
693*7c478bd9Sstevel@tonic-gate 	}
694*7c478bd9Sstevel@tonic-gate 	return (1);
695*7c478bd9Sstevel@tonic-gate }
696*7c478bd9Sstevel@tonic-gate 
697*7c478bd9Sstevel@tonic-gate static int
698*7c478bd9Sstevel@tonic-gate datadm_version_match(datadm_version_t *v1, datadm_version_t *v2)
699*7c478bd9Sstevel@tonic-gate {
700*7c478bd9Sstevel@tonic-gate 	if (!datadm_str_match(v1->dv_name, v2->dv_name)) {
701*7c478bd9Sstevel@tonic-gate 		return (0);
702*7c478bd9Sstevel@tonic-gate 	}
703*7c478bd9Sstevel@tonic-gate 	if (v1->dv_major != v2->dv_major) {
704*7c478bd9Sstevel@tonic-gate 		return (0);
705*7c478bd9Sstevel@tonic-gate 	}
706*7c478bd9Sstevel@tonic-gate 	if (v1->dv_minor != v2->dv_minor) {
707*7c478bd9Sstevel@tonic-gate 		return (0);
708*7c478bd9Sstevel@tonic-gate 	}
709*7c478bd9Sstevel@tonic-gate 	return (1);
710*7c478bd9Sstevel@tonic-gate }
711*7c478bd9Sstevel@tonic-gate 
712*7c478bd9Sstevel@tonic-gate static int
713*7c478bd9Sstevel@tonic-gate datadm_sp_entry_match(datadm_sp_entry_t *sp1, datadm_sp_entry_t *sp2)
714*7c478bd9Sstevel@tonic-gate {
715*7c478bd9Sstevel@tonic-gate 	if (!datadm_str_match(sp1->spe_devname, sp2->spe_devname)) {
716*7c478bd9Sstevel@tonic-gate 		return (0);
717*7c478bd9Sstevel@tonic-gate 	}
718*7c478bd9Sstevel@tonic-gate 	if (!datadm_version_match(&sp1->spe_api_version,
719*7c478bd9Sstevel@tonic-gate 	    &sp2->spe_api_version)) {
720*7c478bd9Sstevel@tonic-gate 		return (0);
721*7c478bd9Sstevel@tonic-gate 	}
722*7c478bd9Sstevel@tonic-gate 	if (sp1->spe_threadsafe != sp2->spe_threadsafe) {
723*7c478bd9Sstevel@tonic-gate 		return (0);
724*7c478bd9Sstevel@tonic-gate 	}
725*7c478bd9Sstevel@tonic-gate 	if (sp2->spe_default != sp2->spe_default) {
726*7c478bd9Sstevel@tonic-gate 		return (0);
727*7c478bd9Sstevel@tonic-gate 	}
728*7c478bd9Sstevel@tonic-gate 	if (!datadm_str_match(sp1->spe_libpath, sp2->spe_libpath)) {
729*7c478bd9Sstevel@tonic-gate 		return (0);
730*7c478bd9Sstevel@tonic-gate 	}
731*7c478bd9Sstevel@tonic-gate 	if (!datadm_version_match(&sp1->spe_sp_version,
732*7c478bd9Sstevel@tonic-gate 	    &sp2->spe_sp_version)) {
733*7c478bd9Sstevel@tonic-gate 		return (0);
734*7c478bd9Sstevel@tonic-gate 	}
735*7c478bd9Sstevel@tonic-gate 	if (!datadm_str_match(sp1->spe_sp_data, sp2->spe_sp_data)) {
736*7c478bd9Sstevel@tonic-gate 		return (0);
737*7c478bd9Sstevel@tonic-gate 	}
738*7c478bd9Sstevel@tonic-gate 	return (1);
739*7c478bd9Sstevel@tonic-gate }
740*7c478bd9Sstevel@tonic-gate 
741*7c478bd9Sstevel@tonic-gate static datadm_ia_entry_t *
742*7c478bd9Sstevel@tonic-gate datadm_alloc_ia_entry(void)
743*7c478bd9Sstevel@tonic-gate {
744*7c478bd9Sstevel@tonic-gate 	datadm_ia_entry_t	*ia_entry;
745*7c478bd9Sstevel@tonic-gate 
746*7c478bd9Sstevel@tonic-gate 	ia_entry = (datadm_ia_entry_t *)malloc(sizeof (*ia_entry));
747*7c478bd9Sstevel@tonic-gate 	if (ia_entry == NULL) {
748*7c478bd9Sstevel@tonic-gate 		return (NULL);
749*7c478bd9Sstevel@tonic-gate 	}
750*7c478bd9Sstevel@tonic-gate 	bzero(ia_entry, sizeof (*ia_entry));
751*7c478bd9Sstevel@tonic-gate 	return (ia_entry);
752*7c478bd9Sstevel@tonic-gate }
753*7c478bd9Sstevel@tonic-gate 
754*7c478bd9Sstevel@tonic-gate static void
755*7c478bd9Sstevel@tonic-gate datadm_free_ia_entry(datadm_ia_entry_t *ia_entry)
756*7c478bd9Sstevel@tonic-gate {
757*7c478bd9Sstevel@tonic-gate 	free(ia_entry);
758*7c478bd9Sstevel@tonic-gate }
759*7c478bd9Sstevel@tonic-gate 
760*7c478bd9Sstevel@tonic-gate static datadm_hca_entry_t *
761*7c478bd9Sstevel@tonic-gate datadm_alloc_hca_entry(void)
762*7c478bd9Sstevel@tonic-gate {
763*7c478bd9Sstevel@tonic-gate 	datadm_hca_entry_t	*hca_entry;
764*7c478bd9Sstevel@tonic-gate 
765*7c478bd9Sstevel@tonic-gate 	hca_entry = (datadm_hca_entry_t *)malloc(sizeof (*hca_entry));
766*7c478bd9Sstevel@tonic-gate 	if (hca_entry == NULL) {
767*7c478bd9Sstevel@tonic-gate 		return (NULL);
768*7c478bd9Sstevel@tonic-gate 	}
769*7c478bd9Sstevel@tonic-gate 	bzero(hca_entry, sizeof (*hca_entry));
770*7c478bd9Sstevel@tonic-gate 	return (hca_entry);
771*7c478bd9Sstevel@tonic-gate }
772*7c478bd9Sstevel@tonic-gate 
773*7c478bd9Sstevel@tonic-gate static void
774*7c478bd9Sstevel@tonic-gate datadm_free_hca_entry(datadm_hca_entry_t *hca_entry)
775*7c478bd9Sstevel@tonic-gate {
776*7c478bd9Sstevel@tonic-gate 	if (hca_entry->he_name != NULL) {
777*7c478bd9Sstevel@tonic-gate 		free(hca_entry->he_name);
778*7c478bd9Sstevel@tonic-gate 		hca_entry->he_name = NULL;
779*7c478bd9Sstevel@tonic-gate 	}
780*7c478bd9Sstevel@tonic-gate 	datadm_free_list(&hca_entry->he_sp_list,
781*7c478bd9Sstevel@tonic-gate 	    (void (*)(datadm_entry_t *))datadm_free_sp_entry);
782*7c478bd9Sstevel@tonic-gate 	datadm_free_list(&hca_entry->he_ia_list,
783*7c478bd9Sstevel@tonic-gate 	    (void (*)(datadm_entry_t *))datadm_free_ia_entry);
784*7c478bd9Sstevel@tonic-gate 	free(hca_entry);
785*7c478bd9Sstevel@tonic-gate }
786*7c478bd9Sstevel@tonic-gate 
787*7c478bd9Sstevel@tonic-gate static int
788*7c478bd9Sstevel@tonic-gate datadm_hca_entry_match(datadm_hca_entry_t *h1, datadm_hca_entry_t *h2)
789*7c478bd9Sstevel@tonic-gate {
790*7c478bd9Sstevel@tonic-gate 	if (!datadm_str_match(h1->he_name, h2->he_name)) {
791*7c478bd9Sstevel@tonic-gate 		return (0);
792*7c478bd9Sstevel@tonic-gate 	}
793*7c478bd9Sstevel@tonic-gate 	return (1);
794*7c478bd9Sstevel@tonic-gate }
795*7c478bd9Sstevel@tonic-gate 
796*7c478bd9Sstevel@tonic-gate static int
797*7c478bd9Sstevel@tonic-gate datadm_hca_entry_find(datadm_hca_entry_t *h1, datadm_hca_find_t *hf)
798*7c478bd9Sstevel@tonic-gate {
799*7c478bd9Sstevel@tonic-gate 	if (datadm_str_match(h1->he_name, hf->hf_sp_entry->spe_devname)) {
800*7c478bd9Sstevel@tonic-gate 		hf->hf_hca_entry = h1;
801*7c478bd9Sstevel@tonic-gate 		return (1);
802*7c478bd9Sstevel@tonic-gate 	}
803*7c478bd9Sstevel@tonic-gate 	return (0);
804*7c478bd9Sstevel@tonic-gate }
805*7c478bd9Sstevel@tonic-gate 
806*7c478bd9Sstevel@tonic-gate static int
807*7c478bd9Sstevel@tonic-gate datadm_ia_entry_find(datadm_ia_entry_t *i1, datadm_ia_find_t *iaf)
808*7c478bd9Sstevel@tonic-gate {
809*7c478bd9Sstevel@tonic-gate 	if (i1->iae_devnum == iaf->if_ia_devnum) {
810*7c478bd9Sstevel@tonic-gate 		iaf->if_ia_entry = i1;
811*7c478bd9Sstevel@tonic-gate 		return (1);
812*7c478bd9Sstevel@tonic-gate 	}
813*7c478bd9Sstevel@tonic-gate 	return (0);
814*7c478bd9Sstevel@tonic-gate }
815*7c478bd9Sstevel@tonic-gate 
816*7c478bd9Sstevel@tonic-gate static datadm_cmnt_entry_t *
817*7c478bd9Sstevel@tonic-gate datadm_alloc_cmnt_entry(void)
818*7c478bd9Sstevel@tonic-gate {
819*7c478bd9Sstevel@tonic-gate 	datadm_cmnt_entry_t	*cmnt_entry;
820*7c478bd9Sstevel@tonic-gate 
821*7c478bd9Sstevel@tonic-gate 	cmnt_entry = (datadm_cmnt_entry_t *)malloc(sizeof (*cmnt_entry));
822*7c478bd9Sstevel@tonic-gate 	if (cmnt_entry == NULL) {
823*7c478bd9Sstevel@tonic-gate 		return (NULL);
824*7c478bd9Sstevel@tonic-gate 	}
825*7c478bd9Sstevel@tonic-gate 	bzero(cmnt_entry, sizeof (*cmnt_entry));
826*7c478bd9Sstevel@tonic-gate 	return (cmnt_entry);
827*7c478bd9Sstevel@tonic-gate }
828*7c478bd9Sstevel@tonic-gate 
829*7c478bd9Sstevel@tonic-gate static void
830*7c478bd9Sstevel@tonic-gate datadm_free_cmnt_entry(datadm_cmnt_entry_t *cmnt_entry)
831*7c478bd9Sstevel@tonic-gate {
832*7c478bd9Sstevel@tonic-gate 	if (cmnt_entry->cmnt_line != NULL) {
833*7c478bd9Sstevel@tonic-gate 		free(cmnt_entry->cmnt_line);
834*7c478bd9Sstevel@tonic-gate 		cmnt_entry->cmnt_line = NULL;
835*7c478bd9Sstevel@tonic-gate 	}
836*7c478bd9Sstevel@tonic-gate 	free(cmnt_entry);
837*7c478bd9Sstevel@tonic-gate }
838*7c478bd9Sstevel@tonic-gate 
839*7c478bd9Sstevel@tonic-gate /*
840*7c478bd9Sstevel@tonic-gate  * tokenizes a line and strips off the quotes from quoted strings
841*7c478bd9Sstevel@tonic-gate  */
842*7c478bd9Sstevel@tonic-gate static int
843*7c478bd9Sstevel@tonic-gate datadm_parse_line(char *line_buf, char *tokens[], int *token_count)
844*7c478bd9Sstevel@tonic-gate {
845*7c478bd9Sstevel@tonic-gate 	int			len, i;
846*7c478bd9Sstevel@tonic-gate 	int			count = 0;
847*7c478bd9Sstevel@tonic-gate 	char			*start = NULL;
848*7c478bd9Sstevel@tonic-gate 
849*7c478bd9Sstevel@tonic-gate 	/* the line must not be longer than DATADM_LINESZ */
850*7c478bd9Sstevel@tonic-gate 	len = strlen(line_buf);
851*7c478bd9Sstevel@tonic-gate 	if (line_buf[len - 1] != '\n') {
852*7c478bd9Sstevel@tonic-gate 		return (-1);
853*7c478bd9Sstevel@tonic-gate 	}
854*7c478bd9Sstevel@tonic-gate 	/* discard blank lines and comments */
855*7c478bd9Sstevel@tonic-gate 	if (len == 1) {
856*7c478bd9Sstevel@tonic-gate 		*token_count = 0;
857*7c478bd9Sstevel@tonic-gate 		return (0);
858*7c478bd9Sstevel@tonic-gate 	}
859*7c478bd9Sstevel@tonic-gate 	if (len >= 2 && line_buf[0] == '#') {
860*7c478bd9Sstevel@tonic-gate 		*token_count = 0;
861*7c478bd9Sstevel@tonic-gate 		return (0);
862*7c478bd9Sstevel@tonic-gate 	}
863*7c478bd9Sstevel@tonic-gate 	/* removes the new line */
864*7c478bd9Sstevel@tonic-gate 	line_buf[len - 1] = '\0';
865*7c478bd9Sstevel@tonic-gate 	len--;
866*7c478bd9Sstevel@tonic-gate 
867*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < len; i++) {
868*7c478bd9Sstevel@tonic-gate 		if (start != NULL) {
869*7c478bd9Sstevel@tonic-gate 			/*
870*7c478bd9Sstevel@tonic-gate 			 * start points to the start of
871*7c478bd9Sstevel@tonic-gate 			 * a new token. if start is '"',
872*7c478bd9Sstevel@tonic-gate 			 * we should expect a quoted
873*7c478bd9Sstevel@tonic-gate 			 * string.
874*7c478bd9Sstevel@tonic-gate 			 */
875*7c478bd9Sstevel@tonic-gate 			if (*start == '\"') {
876*7c478bd9Sstevel@tonic-gate 				/*
877*7c478bd9Sstevel@tonic-gate 				 * keep scanning until we
878*7c478bd9Sstevel@tonic-gate 				 * hit the end quote.
879*7c478bd9Sstevel@tonic-gate 				 */
880*7c478bd9Sstevel@tonic-gate 				if (line_buf[i] != '\"') {
881*7c478bd9Sstevel@tonic-gate 					continue;
882*7c478bd9Sstevel@tonic-gate 				}
883*7c478bd9Sstevel@tonic-gate 				/*
884*7c478bd9Sstevel@tonic-gate 				 * skip past the start quote
885*7c478bd9Sstevel@tonic-gate 				 */
886*7c478bd9Sstevel@tonic-gate 				start++;
887*7c478bd9Sstevel@tonic-gate 			} else {
888*7c478bd9Sstevel@tonic-gate 				/*
889*7c478bd9Sstevel@tonic-gate 				 * our token is not a quoted
890*7c478bd9Sstevel@tonic-gate 				 * string. our token ends only
891*7c478bd9Sstevel@tonic-gate 				 * when we hit a whitespace.
892*7c478bd9Sstevel@tonic-gate 				 */
893*7c478bd9Sstevel@tonic-gate 				if (!isspace(line_buf[i])) {
894*7c478bd9Sstevel@tonic-gate 					continue;
895*7c478bd9Sstevel@tonic-gate 				}
896*7c478bd9Sstevel@tonic-gate 			}
897*7c478bd9Sstevel@tonic-gate 			/*
898*7c478bd9Sstevel@tonic-gate 			 * nullify the end quote (if any)
899*7c478bd9Sstevel@tonic-gate 			 * and update the tokens array.
900*7c478bd9Sstevel@tonic-gate 			 */
901*7c478bd9Sstevel@tonic-gate 			line_buf[i] = '\0';
902*7c478bd9Sstevel@tonic-gate 			tokens[count] = start;
903*7c478bd9Sstevel@tonic-gate 			start = NULL;
904*7c478bd9Sstevel@tonic-gate 			count++;
905*7c478bd9Sstevel@tonic-gate 		} else {
906*7c478bd9Sstevel@tonic-gate 			/*
907*7c478bd9Sstevel@tonic-gate 			 * skip whitespaces
908*7c478bd9Sstevel@tonic-gate 			 */
909*7c478bd9Sstevel@tonic-gate 			if (isspace(line_buf[i])) {
910*7c478bd9Sstevel@tonic-gate 				continue;
911*7c478bd9Sstevel@tonic-gate 			} else {
912*7c478bd9Sstevel@tonic-gate 				start = &line_buf[i];
913*7c478bd9Sstevel@tonic-gate 			}
914*7c478bd9Sstevel@tonic-gate 		}
915*7c478bd9Sstevel@tonic-gate 		if (count == DATADM_MAX_TOKENS) {
916*7c478bd9Sstevel@tonic-gate 			start = NULL;
917*7c478bd9Sstevel@tonic-gate 			break;
918*7c478bd9Sstevel@tonic-gate 		}
919*7c478bd9Sstevel@tonic-gate 	}
920*7c478bd9Sstevel@tonic-gate 	if (start != NULL) {
921*7c478bd9Sstevel@tonic-gate 		tokens[count] = start;
922*7c478bd9Sstevel@tonic-gate 		start = NULL;
923*7c478bd9Sstevel@tonic-gate 		count++;
924*7c478bd9Sstevel@tonic-gate 	}
925*7c478bd9Sstevel@tonic-gate 	*token_count = count;
926*7c478bd9Sstevel@tonic-gate 	return (0);
927*7c478bd9Sstevel@tonic-gate }
928*7c478bd9Sstevel@tonic-gate 
929*7c478bd9Sstevel@tonic-gate /*
930*7c478bd9Sstevel@tonic-gate  * attempts to save sp_entry into hca_list.
931*7c478bd9Sstevel@tonic-gate  * becomes no-op if sp entry already exists.
932*7c478bd9Sstevel@tonic-gate  * new hca entries and ia entries are created as needed.
933*7c478bd9Sstevel@tonic-gate  */
934*7c478bd9Sstevel@tonic-gate static int
935*7c478bd9Sstevel@tonic-gate datadm_process_sp_entry(datadm_list_t *hca_list, datadm_sp_entry_t *sp_entry,
936*7c478bd9Sstevel@tonic-gate 	int ia_devnum)
937*7c478bd9Sstevel@tonic-gate {
938*7c478bd9Sstevel@tonic-gate 	datadm_hca_find_t	hca_find;
939*7c478bd9Sstevel@tonic-gate 	datadm_ia_find_t	ia_find;
940*7c478bd9Sstevel@tonic-gate 	datadm_hca_entry_t	*hca_entry;
941*7c478bd9Sstevel@tonic-gate 
942*7c478bd9Sstevel@tonic-gate 	hca_find.hf_sp_entry = sp_entry;
943*7c478bd9Sstevel@tonic-gate 	hca_find.hf_hca_entry = NULL;
944*7c478bd9Sstevel@tonic-gate 	(void) datadm_walk_list(hca_list, (int (*)(datadm_entry_t *, void *))
945*7c478bd9Sstevel@tonic-gate 	    datadm_hca_entry_find, (void *)&hca_find);
946*7c478bd9Sstevel@tonic-gate 
947*7c478bd9Sstevel@tonic-gate 	if (hca_find.hf_hca_entry == NULL) {
948*7c478bd9Sstevel@tonic-gate 		int	dlen;
949*7c478bd9Sstevel@tonic-gate 
950*7c478bd9Sstevel@tonic-gate 		/*
951*7c478bd9Sstevel@tonic-gate 		 * hca_entry not found, need to create
952*7c478bd9Sstevel@tonic-gate 		 * and insert one.
953*7c478bd9Sstevel@tonic-gate 		 */
954*7c478bd9Sstevel@tonic-gate 		hca_entry = datadm_alloc_hca_entry();
955*7c478bd9Sstevel@tonic-gate 		if (hca_entry == NULL) {
956*7c478bd9Sstevel@tonic-gate 			return (-1);
957*7c478bd9Sstevel@tonic-gate 		}
958*7c478bd9Sstevel@tonic-gate 		dlen = strlen(sp_entry->spe_devname);
959*7c478bd9Sstevel@tonic-gate 		hca_entry->he_name = (char *)malloc(dlen + 1);
960*7c478bd9Sstevel@tonic-gate 		if (hca_entry->he_name == NULL) {
961*7c478bd9Sstevel@tonic-gate 			datadm_free_hca_entry(hca_entry);
962*7c478bd9Sstevel@tonic-gate 			return (-1);
963*7c478bd9Sstevel@tonic-gate 		}
964*7c478bd9Sstevel@tonic-gate 		(void) strcpy(hca_entry->he_name, sp_entry->spe_devname);
965*7c478bd9Sstevel@tonic-gate 		datadm_enqueue_entry(hca_list, (datadm_entry_t *)hca_entry);
966*7c478bd9Sstevel@tonic-gate 	} else {
967*7c478bd9Sstevel@tonic-gate 		hca_entry = hca_find.hf_hca_entry;
968*7c478bd9Sstevel@tonic-gate 	}
969*7c478bd9Sstevel@tonic-gate 	if (ia_devnum == -1) {
970*7c478bd9Sstevel@tonic-gate 		goto put_sp_entry;
971*7c478bd9Sstevel@tonic-gate 	}
972*7c478bd9Sstevel@tonic-gate 	ia_find.if_ia_devnum = ia_devnum;
973*7c478bd9Sstevel@tonic-gate 	ia_find.if_ia_entry = NULL;
974*7c478bd9Sstevel@tonic-gate 	(void) datadm_walk_list(&hca_entry->he_ia_list,
975*7c478bd9Sstevel@tonic-gate 	    (int (*)(datadm_entry_t *, void *))datadm_ia_entry_find, &ia_find);
976*7c478bd9Sstevel@tonic-gate 
977*7c478bd9Sstevel@tonic-gate 	if (ia_find.if_ia_entry == NULL) {
978*7c478bd9Sstevel@tonic-gate 		datadm_ia_entry_t	*ia_entry;
979*7c478bd9Sstevel@tonic-gate 
980*7c478bd9Sstevel@tonic-gate 		/*
981*7c478bd9Sstevel@tonic-gate 		 * ia_entry not found, need to create
982*7c478bd9Sstevel@tonic-gate 		 * and insert one.
983*7c478bd9Sstevel@tonic-gate 		 */
984*7c478bd9Sstevel@tonic-gate 		ia_entry = datadm_alloc_ia_entry();
985*7c478bd9Sstevel@tonic-gate 		if (ia_entry == NULL) {
986*7c478bd9Sstevel@tonic-gate 			return (-1);
987*7c478bd9Sstevel@tonic-gate 		}
988*7c478bd9Sstevel@tonic-gate 		ia_entry->iae_devnum = ia_devnum;
989*7c478bd9Sstevel@tonic-gate 		datadm_enqueue_entry(&hca_entry->he_ia_list,
990*7c478bd9Sstevel@tonic-gate 		    (datadm_entry_t *)ia_entry);
991*7c478bd9Sstevel@tonic-gate 	}
992*7c478bd9Sstevel@tonic-gate 
993*7c478bd9Sstevel@tonic-gate put_sp_entry:;
994*7c478bd9Sstevel@tonic-gate 
995*7c478bd9Sstevel@tonic-gate 	if (datadm_walk_list(&hca_entry->he_sp_list,
996*7c478bd9Sstevel@tonic-gate 	    (int (*)(datadm_entry_t *, void *))datadm_sp_entry_match,
997*7c478bd9Sstevel@tonic-gate 	    (void *)sp_entry)) {
998*7c478bd9Sstevel@tonic-gate 		return (1);
999*7c478bd9Sstevel@tonic-gate 	} else {
1000*7c478bd9Sstevel@tonic-gate 		/*
1001*7c478bd9Sstevel@tonic-gate 		 * only insert sp_entry if it is not found.
1002*7c478bd9Sstevel@tonic-gate 		 */
1003*7c478bd9Sstevel@tonic-gate 		datadm_enqueue_entry(&hca_entry->he_sp_list,
1004*7c478bd9Sstevel@tonic-gate 		    (datadm_entry_t *)sp_entry);
1005*7c478bd9Sstevel@tonic-gate 	}
1006*7c478bd9Sstevel@tonic-gate 	return (0);
1007*7c478bd9Sstevel@tonic-gate }
1008*7c478bd9Sstevel@tonic-gate 
1009*7c478bd9Sstevel@tonic-gate /*
1010*7c478bd9Sstevel@tonic-gate  * parses service_provider.conf
1011*7c478bd9Sstevel@tonic-gate  */
1012*7c478bd9Sstevel@tonic-gate static int
1013*7c478bd9Sstevel@tonic-gate datadm_parse_sp_conf(datadm_list_t *hca_list)
1014*7c478bd9Sstevel@tonic-gate {
1015*7c478bd9Sstevel@tonic-gate 	datadm_sp_entry_t	*sp_entry;
1016*7c478bd9Sstevel@tonic-gate 	FILE			*sp_file;
1017*7c478bd9Sstevel@tonic-gate 	char			*sp_conf = datadm_args.da_sp_conf;
1018*7c478bd9Sstevel@tonic-gate 	char			*tokens[DATADM_MAX_TOKENS];
1019*7c478bd9Sstevel@tonic-gate 	char			line_buf[DATADM_LINESZ];
1020*7c478bd9Sstevel@tonic-gate 	int			retval = 0;
1021*7c478bd9Sstevel@tonic-gate 	int			token_count = 0;
1022*7c478bd9Sstevel@tonic-gate 	int			line_count = 0;
1023*7c478bd9Sstevel@tonic-gate 
1024*7c478bd9Sstevel@tonic-gate 	sp_file = fopen(sp_conf, "r");
1025*7c478bd9Sstevel@tonic-gate 	if (sp_file == NULL) {
1026*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
1027*7c478bd9Sstevel@tonic-gate 		    gettext("datadm: cannot open %s\n"), sp_conf);
1028*7c478bd9Sstevel@tonic-gate 		return (-1);
1029*7c478bd9Sstevel@tonic-gate 	}
1030*7c478bd9Sstevel@tonic-gate 
1031*7c478bd9Sstevel@tonic-gate 	for (;;) {
1032*7c478bd9Sstevel@tonic-gate 		bzero(line_buf, DATADM_LINESZ);
1033*7c478bd9Sstevel@tonic-gate 		if (fgets(line_buf, DATADM_LINESZ, sp_file) == NULL) {
1034*7c478bd9Sstevel@tonic-gate 			break;
1035*7c478bd9Sstevel@tonic-gate 		}
1036*7c478bd9Sstevel@tonic-gate 		token_count = 0;
1037*7c478bd9Sstevel@tonic-gate 		line_count++;
1038*7c478bd9Sstevel@tonic-gate 		retval = datadm_parse_line(line_buf, tokens, &token_count);
1039*7c478bd9Sstevel@tonic-gate 		if (retval != 0) {
1040*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
1041*7c478bd9Sstevel@tonic-gate 			    "datadm: %s: line %d exceeded max length %d\n"),
1042*7c478bd9Sstevel@tonic-gate 			    sp_conf, line_count, DATADM_LINESZ);
1043*7c478bd9Sstevel@tonic-gate 			break;
1044*7c478bd9Sstevel@tonic-gate 		}
1045*7c478bd9Sstevel@tonic-gate 		if (token_count == 0) continue;
1046*7c478bd9Sstevel@tonic-gate 		if (token_count == DATADM_NUM_SP_TOKENS) {
1047*7c478bd9Sstevel@tonic-gate 			int i = 0;
1048*7c478bd9Sstevel@tonic-gate 
1049*7c478bd9Sstevel@tonic-gate 			sp_entry = datadm_alloc_sp_entry();
1050*7c478bd9Sstevel@tonic-gate 			if (sp_entry == NULL) {
1051*7c478bd9Sstevel@tonic-gate 				retval = -1;
1052*7c478bd9Sstevel@tonic-gate 				break;
1053*7c478bd9Sstevel@tonic-gate 			}
1054*7c478bd9Sstevel@tonic-gate 
1055*7c478bd9Sstevel@tonic-gate 			/*
1056*7c478bd9Sstevel@tonic-gate 			 * sp_entry gets filled incrementally by
1057*7c478bd9Sstevel@tonic-gate 			 * each parsing function
1058*7c478bd9Sstevel@tonic-gate 			 */
1059*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < DATADM_NUM_SP_TOKENS &&
1060*7c478bd9Sstevel@tonic-gate 			    retval == 0; i++) {
1061*7c478bd9Sstevel@tonic-gate 				retval = (*datadm_sp_parse_funcs[i])
1062*7c478bd9Sstevel@tonic-gate 				    (tokens[i], (void *)sp_entry);
1063*7c478bd9Sstevel@tonic-gate 			}
1064*7c478bd9Sstevel@tonic-gate 			if (retval != 0) {
1065*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(
1066*7c478bd9Sstevel@tonic-gate 				    "datadm: parse error: %s, "
1067*7c478bd9Sstevel@tonic-gate 				    "line %d, token: %s\n"),
1068*7c478bd9Sstevel@tonic-gate 				    sp_conf, line_count, tokens[i - 1]);
1069*7c478bd9Sstevel@tonic-gate 				datadm_free_sp_entry(sp_entry);
1070*7c478bd9Sstevel@tonic-gate 				sp_entry = NULL;
1071*7c478bd9Sstevel@tonic-gate 				break;
1072*7c478bd9Sstevel@tonic-gate 			}
1073*7c478bd9Sstevel@tonic-gate 
1074*7c478bd9Sstevel@tonic-gate 			retval = datadm_process_sp_entry(hca_list,
1075*7c478bd9Sstevel@tonic-gate 			    sp_entry, -1);
1076*7c478bd9Sstevel@tonic-gate 			if (retval != 0) {
1077*7c478bd9Sstevel@tonic-gate 				datadm_free_sp_entry(sp_entry);
1078*7c478bd9Sstevel@tonic-gate 				if (retval == 1) {
1079*7c478bd9Sstevel@tonic-gate 					retval = 0;
1080*7c478bd9Sstevel@tonic-gate 				} else {
1081*7c478bd9Sstevel@tonic-gate 					break;
1082*7c478bd9Sstevel@tonic-gate 				}
1083*7c478bd9Sstevel@tonic-gate 			}
1084*7c478bd9Sstevel@tonic-gate 		} else {
1085*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
1086*7c478bd9Sstevel@tonic-gate 			    "datadm: parse error: %s, line %d, "
1087*7c478bd9Sstevel@tonic-gate 			    "# of tokens: %d, expected %d\n"), sp_conf,
1088*7c478bd9Sstevel@tonic-gate 			    line_count, token_count, DATADM_NUM_SP_TOKENS);
1089*7c478bd9Sstevel@tonic-gate 			retval = -1;
1090*7c478bd9Sstevel@tonic-gate 			break;
1091*7c478bd9Sstevel@tonic-gate 		}
1092*7c478bd9Sstevel@tonic-gate 	}
1093*7c478bd9Sstevel@tonic-gate 	if (retval != 0) {
1094*7c478bd9Sstevel@tonic-gate 		datadm_free_list(hca_list,
1095*7c478bd9Sstevel@tonic-gate 		    (void (*)(datadm_entry_t *))datadm_free_hca_entry);
1096*7c478bd9Sstevel@tonic-gate 	}
1097*7c478bd9Sstevel@tonic-gate 	(void) fclose(sp_file);
1098*7c478bd9Sstevel@tonic-gate 	return (retval);
1099*7c478bd9Sstevel@tonic-gate }
1100*7c478bd9Sstevel@tonic-gate 
1101*7c478bd9Sstevel@tonic-gate /*
1102*7c478bd9Sstevel@tonic-gate  * parses dat.conf
1103*7c478bd9Sstevel@tonic-gate  */
1104*7c478bd9Sstevel@tonic-gate static int
1105*7c478bd9Sstevel@tonic-gate datadm_parse_dat_conf(datadm_list_t *hca_list)
1106*7c478bd9Sstevel@tonic-gate {
1107*7c478bd9Sstevel@tonic-gate 	boolean_t		save_header = B_TRUE;
1108*7c478bd9Sstevel@tonic-gate 	datadm_sp_entry_t	*sp_entry;
1109*7c478bd9Sstevel@tonic-gate 	FILE			*dat_file;
1110*7c478bd9Sstevel@tonic-gate 	char			*dat_conf = datadm_args.da_dat_conf;
1111*7c478bd9Sstevel@tonic-gate 	char			*tokens[DATADM_MAX_TOKENS];
1112*7c478bd9Sstevel@tonic-gate 	char			line_buf[DATADM_LINESZ];
1113*7c478bd9Sstevel@tonic-gate 	int			retval = 0;
1114*7c478bd9Sstevel@tonic-gate 	int			token_count = 0;
1115*7c478bd9Sstevel@tonic-gate 	int			line_count = 0;
1116*7c478bd9Sstevel@tonic-gate 
1117*7c478bd9Sstevel@tonic-gate 	dat_file = fopen(dat_conf, "r");
1118*7c478bd9Sstevel@tonic-gate 	if (dat_file == NULL) {
1119*7c478bd9Sstevel@tonic-gate 		/* dat.conf not existing is not an error for OP_ADD */
1120*7c478bd9Sstevel@tonic-gate 		if (datadm_args.da_op_type == DATADM_OP_ADD) {
1121*7c478bd9Sstevel@tonic-gate 			return (0);
1122*7c478bd9Sstevel@tonic-gate 		}
1123*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("datadm: cannot open %s\n"),
1124*7c478bd9Sstevel@tonic-gate 		    dat_conf);
1125*7c478bd9Sstevel@tonic-gate 		return (-1);
1126*7c478bd9Sstevel@tonic-gate 	}
1127*7c478bd9Sstevel@tonic-gate 
1128*7c478bd9Sstevel@tonic-gate 	for (;;) {
1129*7c478bd9Sstevel@tonic-gate 		bzero(line_buf, DATADM_LINESZ);
1130*7c478bd9Sstevel@tonic-gate 		if (fgets(line_buf, DATADM_LINESZ, dat_file) == NULL) {
1131*7c478bd9Sstevel@tonic-gate 			break;
1132*7c478bd9Sstevel@tonic-gate 		}
1133*7c478bd9Sstevel@tonic-gate 		token_count = 0;
1134*7c478bd9Sstevel@tonic-gate 		line_count++;
1135*7c478bd9Sstevel@tonic-gate 		retval = datadm_parse_line(line_buf, tokens, &token_count);
1136*7c478bd9Sstevel@tonic-gate 		if (retval != 0) {
1137*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
1138*7c478bd9Sstevel@tonic-gate 			    "datadm: %s: line %d exceeded max length %d\n"),
1139*7c478bd9Sstevel@tonic-gate 			    dat_conf, line_count, DATADM_LINESZ);
1140*7c478bd9Sstevel@tonic-gate 			break;
1141*7c478bd9Sstevel@tonic-gate 		}
1142*7c478bd9Sstevel@tonic-gate 		if (token_count == 0) {
1143*7c478bd9Sstevel@tonic-gate 			datadm_cmnt_entry_t	*cmnt_entry;
1144*7c478bd9Sstevel@tonic-gate 			int			cmnt_len;
1145*7c478bd9Sstevel@tonic-gate 
1146*7c478bd9Sstevel@tonic-gate 			/*
1147*7c478bd9Sstevel@tonic-gate 			 * comments are saved only if they are
1148*7c478bd9Sstevel@tonic-gate 			 * at the top of dat.conf.
1149*7c478bd9Sstevel@tonic-gate 			 */
1150*7c478bd9Sstevel@tonic-gate 			if (!save_header) continue;
1151*7c478bd9Sstevel@tonic-gate 			cmnt_entry = datadm_alloc_cmnt_entry();
1152*7c478bd9Sstevel@tonic-gate 			if (cmnt_entry == NULL) {
1153*7c478bd9Sstevel@tonic-gate 				perror("datadm: malloc");
1154*7c478bd9Sstevel@tonic-gate 				retval = -1;
1155*7c478bd9Sstevel@tonic-gate 				break;
1156*7c478bd9Sstevel@tonic-gate 			}
1157*7c478bd9Sstevel@tonic-gate 			cmnt_len = strlen(line_buf);
1158*7c478bd9Sstevel@tonic-gate 			cmnt_entry->cmnt_line = (char *)malloc(cmnt_len + 1);
1159*7c478bd9Sstevel@tonic-gate 			if (cmnt_entry->cmnt_line == NULL) {
1160*7c478bd9Sstevel@tonic-gate 				perror("datadm: malloc");
1161*7c478bd9Sstevel@tonic-gate 				datadm_free_cmnt_entry(cmnt_entry);
1162*7c478bd9Sstevel@tonic-gate 				retval = -1;
1163*7c478bd9Sstevel@tonic-gate 				break;
1164*7c478bd9Sstevel@tonic-gate 			}
1165*7c478bd9Sstevel@tonic-gate 			(void) strncpy(cmnt_entry->cmnt_line,
1166*7c478bd9Sstevel@tonic-gate 			    line_buf, cmnt_len);
1167*7c478bd9Sstevel@tonic-gate 			cmnt_entry->cmnt_line[cmnt_len] = '\0';
1168*7c478bd9Sstevel@tonic-gate 			datadm_enqueue_entry(&datadm_conf_header,
1169*7c478bd9Sstevel@tonic-gate 			    (datadm_entry_t *)cmnt_entry);
1170*7c478bd9Sstevel@tonic-gate 			continue;
1171*7c478bd9Sstevel@tonic-gate 		}
1172*7c478bd9Sstevel@tonic-gate 		if (token_count == DATADM_NUM_DAT_TOKENS) {
1173*7c478bd9Sstevel@tonic-gate 			int i = 0;
1174*7c478bd9Sstevel@tonic-gate 			int ia_devnum = -1;
1175*7c478bd9Sstevel@tonic-gate 
1176*7c478bd9Sstevel@tonic-gate 			/*
1177*7c478bd9Sstevel@tonic-gate 			 * we stop saving comment lines once
1178*7c478bd9Sstevel@tonic-gate 			 * we see the first valid line.
1179*7c478bd9Sstevel@tonic-gate 			 */
1180*7c478bd9Sstevel@tonic-gate 			save_header = B_FALSE;
1181*7c478bd9Sstevel@tonic-gate 			sp_entry = datadm_alloc_sp_entry();
1182*7c478bd9Sstevel@tonic-gate 			if (sp_entry == NULL) {
1183*7c478bd9Sstevel@tonic-gate 				retval = -1;
1184*7c478bd9Sstevel@tonic-gate 				break;
1185*7c478bd9Sstevel@tonic-gate 			}
1186*7c478bd9Sstevel@tonic-gate 
1187*7c478bd9Sstevel@tonic-gate 			/*
1188*7c478bd9Sstevel@tonic-gate 			 * sp_entry gets filled incrementally by
1189*7c478bd9Sstevel@tonic-gate 			 * each parsing function
1190*7c478bd9Sstevel@tonic-gate 			 */
1191*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < DATADM_NUM_DAT_TOKENS &&
1192*7c478bd9Sstevel@tonic-gate 			    retval == 0; i++) {
1193*7c478bd9Sstevel@tonic-gate 				void	*arg;
1194*7c478bd9Sstevel@tonic-gate 
1195*7c478bd9Sstevel@tonic-gate 				if (i == 0) {
1196*7c478bd9Sstevel@tonic-gate 					/*
1197*7c478bd9Sstevel@tonic-gate 					 * the first token (ia name)
1198*7c478bd9Sstevel@tonic-gate 					 * does not belong to an
1199*7c478bd9Sstevel@tonic-gate 					 * sp_entry
1200*7c478bd9Sstevel@tonic-gate 					 */
1201*7c478bd9Sstevel@tonic-gate 					arg = (void *)&ia_devnum;
1202*7c478bd9Sstevel@tonic-gate 				} else {
1203*7c478bd9Sstevel@tonic-gate 					arg = (void *)sp_entry;
1204*7c478bd9Sstevel@tonic-gate 				}
1205*7c478bd9Sstevel@tonic-gate 				retval = (*datadm_dat_parse_funcs[i])
1206*7c478bd9Sstevel@tonic-gate 				    (tokens[i], arg);
1207*7c478bd9Sstevel@tonic-gate 			}
1208*7c478bd9Sstevel@tonic-gate 			if (retval != 0) {
1209*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(
1210*7c478bd9Sstevel@tonic-gate 				    "datadm: parse error: %s, "
1211*7c478bd9Sstevel@tonic-gate 				    "line %d, token: %s\n"), dat_conf,
1212*7c478bd9Sstevel@tonic-gate 				    line_count, tokens[i - 1]);
1213*7c478bd9Sstevel@tonic-gate 				datadm_free_sp_entry(sp_entry);
1214*7c478bd9Sstevel@tonic-gate 				sp_entry = NULL;
1215*7c478bd9Sstevel@tonic-gate 				break;
1216*7c478bd9Sstevel@tonic-gate 			}
1217*7c478bd9Sstevel@tonic-gate 
1218*7c478bd9Sstevel@tonic-gate 			/*
1219*7c478bd9Sstevel@tonic-gate 			 * we ignore the ibds in dat.conf if we are
1220*7c478bd9Sstevel@tonic-gate 			 * doing update
1221*7c478bd9Sstevel@tonic-gate 			 */
1222*7c478bd9Sstevel@tonic-gate 			if (datadm_args.da_op_type == DATADM_OP_UPDATE) {
1223*7c478bd9Sstevel@tonic-gate 				ia_devnum = -1;
1224*7c478bd9Sstevel@tonic-gate 			}
1225*7c478bd9Sstevel@tonic-gate 			retval = datadm_process_sp_entry(hca_list, sp_entry,
1226*7c478bd9Sstevel@tonic-gate 			    ia_devnum);
1227*7c478bd9Sstevel@tonic-gate 			if (retval != 0) {
1228*7c478bd9Sstevel@tonic-gate 				datadm_free_sp_entry(sp_entry);
1229*7c478bd9Sstevel@tonic-gate 				if (retval == 1) {
1230*7c478bd9Sstevel@tonic-gate 					retval = 0;
1231*7c478bd9Sstevel@tonic-gate 				} else {
1232*7c478bd9Sstevel@tonic-gate 					break;
1233*7c478bd9Sstevel@tonic-gate 				}
1234*7c478bd9Sstevel@tonic-gate 			}
1235*7c478bd9Sstevel@tonic-gate 		} else {
1236*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
1237*7c478bd9Sstevel@tonic-gate 			    "datadm: parse error: %s, line %d, "
1238*7c478bd9Sstevel@tonic-gate 			    "# of tokens: %d, expected %d\n"), dat_conf,
1239*7c478bd9Sstevel@tonic-gate 			    line_count, token_count, DATADM_NUM_DAT_TOKENS);
1240*7c478bd9Sstevel@tonic-gate 			retval = -1;
1241*7c478bd9Sstevel@tonic-gate 			break;
1242*7c478bd9Sstevel@tonic-gate 		}
1243*7c478bd9Sstevel@tonic-gate 	}
1244*7c478bd9Sstevel@tonic-gate 	if (retval != 0) {
1245*7c478bd9Sstevel@tonic-gate 		datadm_free_list(&datadm_conf_header,
1246*7c478bd9Sstevel@tonic-gate 		    (void (*)(datadm_entry_t *))datadm_free_cmnt_entry);
1247*7c478bd9Sstevel@tonic-gate 		datadm_free_list(hca_list,
1248*7c478bd9Sstevel@tonic-gate 		    (void (*)(datadm_entry_t *))datadm_free_hca_entry);
1249*7c478bd9Sstevel@tonic-gate 	}
1250*7c478bd9Sstevel@tonic-gate 	(void) fclose(dat_file);
1251*7c478bd9Sstevel@tonic-gate 	return (retval);
1252*7c478bd9Sstevel@tonic-gate }
1253*7c478bd9Sstevel@tonic-gate 
1254*7c478bd9Sstevel@tonic-gate /*
1255*7c478bd9Sstevel@tonic-gate  * discovers all ibd devices under a particular hca
1256*7c478bd9Sstevel@tonic-gate  */
1257*7c478bd9Sstevel@tonic-gate static int
1258*7c478bd9Sstevel@tonic-gate datadm_fill_ia_list(datadm_hca_entry_t *hca, datadm_fill_ia_list_t *args)
1259*7c478bd9Sstevel@tonic-gate {
1260*7c478bd9Sstevel@tonic-gate 	di_node_t	root_node;
1261*7c478bd9Sstevel@tonic-gate 	di_node_t	hca_node;
1262*7c478bd9Sstevel@tonic-gate 	int		retval = 0;
1263*7c478bd9Sstevel@tonic-gate 	int		sv4, sv6;
1264*7c478bd9Sstevel@tonic-gate 
1265*7c478bd9Sstevel@tonic-gate 	root_node = args->ia_root_node;
1266*7c478bd9Sstevel@tonic-gate 	sv4 = args->ia_sock_fd_v4;
1267*7c478bd9Sstevel@tonic-gate 	sv6 = args->ia_sock_fd_v6;
1268*7c478bd9Sstevel@tonic-gate 
1269*7c478bd9Sstevel@tonic-gate 	hca_node = di_drv_first_node(hca->he_name, root_node);
1270*7c478bd9Sstevel@tonic-gate 	if (hca_node == DI_NODE_NIL) {
1271*7c478bd9Sstevel@tonic-gate 		return (0);
1272*7c478bd9Sstevel@tonic-gate 	}
1273*7c478bd9Sstevel@tonic-gate 	while (hca_node != DI_NODE_NIL) {
1274*7c478bd9Sstevel@tonic-gate 		di_node_t	ibd_node;
1275*7c478bd9Sstevel@tonic-gate 
1276*7c478bd9Sstevel@tonic-gate 		ibd_node = di_drv_first_node(DATADM_IA_NAME, hca_node);
1277*7c478bd9Sstevel@tonic-gate 		while (ibd_node != DI_NODE_NIL) {
1278*7c478bd9Sstevel@tonic-gate 			datadm_ia_find_t	ia_find;
1279*7c478bd9Sstevel@tonic-gate 			datadm_ia_entry_t	*ia_entry;
1280*7c478bd9Sstevel@tonic-gate 			struct lifreq		req;
1281*7c478bd9Sstevel@tonic-gate 			int			devnum, rval;
1282*7c478bd9Sstevel@tonic-gate 
1283*7c478bd9Sstevel@tonic-gate 			devnum = di_instance(ibd_node);
1284*7c478bd9Sstevel@tonic-gate 			if (devnum == -1) {
1285*7c478bd9Sstevel@tonic-gate 				ibd_node = di_drv_next_node(ibd_node);
1286*7c478bd9Sstevel@tonic-gate 				continue;
1287*7c478bd9Sstevel@tonic-gate 			}
1288*7c478bd9Sstevel@tonic-gate 
1289*7c478bd9Sstevel@tonic-gate 			(void) snprintf(req.lifr_name, sizeof (req.lifr_name),
1290*7c478bd9Sstevel@tonic-gate 			    "%s%d", DATADM_IA_NAME, devnum);
1291*7c478bd9Sstevel@tonic-gate 			/*
1292*7c478bd9Sstevel@tonic-gate 			 * we don't really need to know the ip address.
1293*7c478bd9Sstevel@tonic-gate 			 * we just want to check if the device is plumbed
1294*7c478bd9Sstevel@tonic-gate 			 * or not.
1295*7c478bd9Sstevel@tonic-gate 			 */
1296*7c478bd9Sstevel@tonic-gate 			rval = ioctl(sv4, SIOCGLIFADDR, (caddr_t)&req);
1297*7c478bd9Sstevel@tonic-gate 			if (rval != 0) {
1298*7c478bd9Sstevel@tonic-gate 				/*
1299*7c478bd9Sstevel@tonic-gate 				 * we try v6 if the v4 address isn't found.
1300*7c478bd9Sstevel@tonic-gate 				 */
1301*7c478bd9Sstevel@tonic-gate 				rval = ioctl(sv6, SIOCGLIFADDR, (caddr_t)&req);
1302*7c478bd9Sstevel@tonic-gate 				if (rval != 0) {
1303*7c478bd9Sstevel@tonic-gate 					ibd_node = di_drv_next_node(ibd_node);
1304*7c478bd9Sstevel@tonic-gate 					continue;
1305*7c478bd9Sstevel@tonic-gate 				}
1306*7c478bd9Sstevel@tonic-gate 			}
1307*7c478bd9Sstevel@tonic-gate 			ia_find.if_ia_devnum = devnum;
1308*7c478bd9Sstevel@tonic-gate 			ia_find.if_ia_entry = NULL;
1309*7c478bd9Sstevel@tonic-gate 			(void) datadm_walk_list(&hca->he_ia_list,
1310*7c478bd9Sstevel@tonic-gate 			    (int (*)(datadm_entry_t *, void *))
1311*7c478bd9Sstevel@tonic-gate 			    datadm_ia_entry_find, &ia_find);
1312*7c478bd9Sstevel@tonic-gate 
1313*7c478bd9Sstevel@tonic-gate 			if (ia_find.if_ia_entry == NULL) {
1314*7c478bd9Sstevel@tonic-gate 				/*
1315*7c478bd9Sstevel@tonic-gate 				 * we insert an ia entry only if
1316*7c478bd9Sstevel@tonic-gate 				 * it is unique.
1317*7c478bd9Sstevel@tonic-gate 				 */
1318*7c478bd9Sstevel@tonic-gate 				ia_entry = datadm_alloc_ia_entry();
1319*7c478bd9Sstevel@tonic-gate 				if (ia_entry == NULL) {
1320*7c478bd9Sstevel@tonic-gate 					retval = -1;
1321*7c478bd9Sstevel@tonic-gate 					break;
1322*7c478bd9Sstevel@tonic-gate 				}
1323*7c478bd9Sstevel@tonic-gate 				ia_entry->iae_devnum = devnum;
1324*7c478bd9Sstevel@tonic-gate 				datadm_enqueue_entry(&hca->he_ia_list,
1325*7c478bd9Sstevel@tonic-gate 				    (datadm_entry_t *)ia_entry);
1326*7c478bd9Sstevel@tonic-gate 			} else {
1327*7c478bd9Sstevel@tonic-gate 				ia_entry = ia_find.if_ia_entry;
1328*7c478bd9Sstevel@tonic-gate 			}
1329*7c478bd9Sstevel@tonic-gate 			ibd_node = di_drv_next_node(ibd_node);
1330*7c478bd9Sstevel@tonic-gate 		}
1331*7c478bd9Sstevel@tonic-gate 		hca_node = di_drv_next_node(hca_node);
1332*7c478bd9Sstevel@tonic-gate 	}
1333*7c478bd9Sstevel@tonic-gate 	if (retval != 0) {
1334*7c478bd9Sstevel@tonic-gate 		datadm_free_list(&hca->he_ia_list,
1335*7c478bd9Sstevel@tonic-gate 		    (void (*)(datadm_entry_t *))datadm_free_ia_entry);
1336*7c478bd9Sstevel@tonic-gate 	}
1337*7c478bd9Sstevel@tonic-gate 	return (0);
1338*7c478bd9Sstevel@tonic-gate }
1339*7c478bd9Sstevel@tonic-gate 
1340*7c478bd9Sstevel@tonic-gate /*
1341*7c478bd9Sstevel@tonic-gate  * used by OP_REMOVE to invalidate common sp entries between hl1 and hl2.
1342*7c478bd9Sstevel@tonic-gate  * invalid sp entries will be ignored by datadm_generate_dat_conf.
1343*7c478bd9Sstevel@tonic-gate  */
1344*7c478bd9Sstevel@tonic-gate static void
1345*7c478bd9Sstevel@tonic-gate datadm_invalidate_common_sp_entries(datadm_list_t *hl1, datadm_list_t *hl2)
1346*7c478bd9Sstevel@tonic-gate {
1347*7c478bd9Sstevel@tonic-gate 	datadm_entry_t	*he1, *he2;
1348*7c478bd9Sstevel@tonic-gate 
1349*7c478bd9Sstevel@tonic-gate 	he1 = hl1->dl_head;
1350*7c478bd9Sstevel@tonic-gate 	while (he1 != NULL) {
1351*7c478bd9Sstevel@tonic-gate 		he2 = hl2->dl_head;
1352*7c478bd9Sstevel@tonic-gate 		while (he2 != NULL) {
1353*7c478bd9Sstevel@tonic-gate 			datadm_entry_t	*se1, *se2;
1354*7c478bd9Sstevel@tonic-gate 
1355*7c478bd9Sstevel@tonic-gate 			if (!datadm_hca_entry_match(
1356*7c478bd9Sstevel@tonic-gate 			    (datadm_hca_entry_t *)he1,
1357*7c478bd9Sstevel@tonic-gate 			    (datadm_hca_entry_t *)he2)) {
1358*7c478bd9Sstevel@tonic-gate 				he2 = he2->de_next;
1359*7c478bd9Sstevel@tonic-gate 				continue;
1360*7c478bd9Sstevel@tonic-gate 			}
1361*7c478bd9Sstevel@tonic-gate 			se1 = ((datadm_hca_entry_t *)he1)->he_sp_list.dl_head;
1362*7c478bd9Sstevel@tonic-gate 			while (se1 != NULL) {
1363*7c478bd9Sstevel@tonic-gate 				se2 = ((datadm_hca_entry_t *)he2)->
1364*7c478bd9Sstevel@tonic-gate 				    he_sp_list.dl_head;
1365*7c478bd9Sstevel@tonic-gate 				while (se2 != NULL) {
1366*7c478bd9Sstevel@tonic-gate 					if (!datadm_sp_entry_match(
1367*7c478bd9Sstevel@tonic-gate 					    (datadm_sp_entry_t *)se1,
1368*7c478bd9Sstevel@tonic-gate 					    (datadm_sp_entry_t *)se2)) {
1369*7c478bd9Sstevel@tonic-gate 						se2 = se2->de_next;
1370*7c478bd9Sstevel@tonic-gate 						continue;
1371*7c478bd9Sstevel@tonic-gate 					}
1372*7c478bd9Sstevel@tonic-gate 					((datadm_sp_entry_t *)se1)->
1373*7c478bd9Sstevel@tonic-gate 					    spe_invalid = 1;
1374*7c478bd9Sstevel@tonic-gate 					break;
1375*7c478bd9Sstevel@tonic-gate 				}
1376*7c478bd9Sstevel@tonic-gate 				se1 = se1->de_next;
1377*7c478bd9Sstevel@tonic-gate 			}
1378*7c478bd9Sstevel@tonic-gate 			break;
1379*7c478bd9Sstevel@tonic-gate 		}
1380*7c478bd9Sstevel@tonic-gate 		he1 = he1->de_next;
1381*7c478bd9Sstevel@tonic-gate 	}
1382*7c478bd9Sstevel@tonic-gate }
1383*7c478bd9Sstevel@tonic-gate 
1384*7c478bd9Sstevel@tonic-gate /*
1385*7c478bd9Sstevel@tonic-gate  * applies datadm_fill_ia_list on each hca_list element
1386*7c478bd9Sstevel@tonic-gate  */
1387*7c478bd9Sstevel@tonic-gate static int
1388*7c478bd9Sstevel@tonic-gate datadm_build_ia_lists(datadm_list_t *hca_list)
1389*7c478bd9Sstevel@tonic-gate {
1390*7c478bd9Sstevel@tonic-gate 	datadm_fill_ia_list_t	ia_args;
1391*7c478bd9Sstevel@tonic-gate 	di_node_t		root_node;
1392*7c478bd9Sstevel@tonic-gate 	int			retval = 0;
1393*7c478bd9Sstevel@tonic-gate 	int			sv4, sv6;
1394*7c478bd9Sstevel@tonic-gate 
1395*7c478bd9Sstevel@tonic-gate 	root_node = di_init("/", DINFOCPYALL);
1396*7c478bd9Sstevel@tonic-gate 	if (root_node == DI_NODE_NIL) {
1397*7c478bd9Sstevel@tonic-gate 		perror("datadm: di_init");
1398*7c478bd9Sstevel@tonic-gate 		return (-1);
1399*7c478bd9Sstevel@tonic-gate 	}
1400*7c478bd9Sstevel@tonic-gate 	sv4 = socket(AF_INET, SOCK_DGRAM, 0);
1401*7c478bd9Sstevel@tonic-gate 	if (sv4 < 0) {
1402*7c478bd9Sstevel@tonic-gate 		perror("datadm: socket");
1403*7c478bd9Sstevel@tonic-gate 		di_fini(root_node);
1404*7c478bd9Sstevel@tonic-gate 		return (-1);
1405*7c478bd9Sstevel@tonic-gate 	}
1406*7c478bd9Sstevel@tonic-gate 	sv6 = socket(AF_INET6, SOCK_DGRAM, 0);
1407*7c478bd9Sstevel@tonic-gate 	if (sv6 < 0) {
1408*7c478bd9Sstevel@tonic-gate 		perror("datadm: socket");
1409*7c478bd9Sstevel@tonic-gate 		di_fini(root_node);
1410*7c478bd9Sstevel@tonic-gate 		return (-1);
1411*7c478bd9Sstevel@tonic-gate 	}
1412*7c478bd9Sstevel@tonic-gate 	ia_args.ia_root_node = root_node;
1413*7c478bd9Sstevel@tonic-gate 	ia_args.ia_sock_fd_v4 = sv4;
1414*7c478bd9Sstevel@tonic-gate 	ia_args.ia_sock_fd_v6 = sv6;
1415*7c478bd9Sstevel@tonic-gate 
1416*7c478bd9Sstevel@tonic-gate 	retval = datadm_walk_list(hca_list,
1417*7c478bd9Sstevel@tonic-gate 	    (int (*)(datadm_entry_t *, void *))datadm_fill_ia_list, &ia_args);
1418*7c478bd9Sstevel@tonic-gate 
1419*7c478bd9Sstevel@tonic-gate 	(void) close(sv4);
1420*7c478bd9Sstevel@tonic-gate 	(void) close(sv6);
1421*7c478bd9Sstevel@tonic-gate 	di_fini(root_node);
1422*7c478bd9Sstevel@tonic-gate 	return (retval);
1423*7c478bd9Sstevel@tonic-gate }
1424*7c478bd9Sstevel@tonic-gate 
1425*7c478bd9Sstevel@tonic-gate static int
1426*7c478bd9Sstevel@tonic-gate datadm_generate_conf_entry(FILE *outfile, datadm_ia_entry_t *ia_entry,
1427*7c478bd9Sstevel@tonic-gate 	datadm_sp_entry_t *sp_entry)
1428*7c478bd9Sstevel@tonic-gate {
1429*7c478bd9Sstevel@tonic-gate 	int	retval;
1430*7c478bd9Sstevel@tonic-gate 
1431*7c478bd9Sstevel@tonic-gate 	retval = fprintf(outfile,
1432*7c478bd9Sstevel@tonic-gate 	    "%s%d  %s%d.%d  %s  %s  %s  %s%d.%d  \"%s\"  \"%s%s%s\"\n",
1433*7c478bd9Sstevel@tonic-gate 	    DATADM_IA_NAME, ia_entry->iae_devnum,
1434*7c478bd9Sstevel@tonic-gate 	    (sp_entry->spe_api_version.dv_name ?
1435*7c478bd9Sstevel@tonic-gate 	    sp_entry->spe_api_version.dv_name : ""),
1436*7c478bd9Sstevel@tonic-gate 	    sp_entry->spe_api_version.dv_major,
1437*7c478bd9Sstevel@tonic-gate 	    sp_entry->spe_api_version.dv_minor,
1438*7c478bd9Sstevel@tonic-gate 	    (sp_entry->spe_threadsafe ? "threadsafe" : "nonthreadsafe"),
1439*7c478bd9Sstevel@tonic-gate 	    (sp_entry->spe_default ? "default" : "nondefault"),
1440*7c478bd9Sstevel@tonic-gate 	    sp_entry->spe_libpath,
1441*7c478bd9Sstevel@tonic-gate 	    (sp_entry->spe_sp_version.dv_name ?
1442*7c478bd9Sstevel@tonic-gate 	    sp_entry->spe_sp_version.dv_name : ""),
1443*7c478bd9Sstevel@tonic-gate 	    sp_entry->spe_sp_version.dv_major,
1444*7c478bd9Sstevel@tonic-gate 	    sp_entry->spe_sp_version.dv_minor,
1445*7c478bd9Sstevel@tonic-gate 	    sp_entry->spe_sp_data,
1446*7c478bd9Sstevel@tonic-gate 	    DATADM_DRV_NAME, "=", sp_entry->spe_devname);
1447*7c478bd9Sstevel@tonic-gate 
1448*7c478bd9Sstevel@tonic-gate 	if (retval < 0) {
1449*7c478bd9Sstevel@tonic-gate 		return (-1);
1450*7c478bd9Sstevel@tonic-gate 	}
1451*7c478bd9Sstevel@tonic-gate 	return (0);
1452*7c478bd9Sstevel@tonic-gate }
1453*7c478bd9Sstevel@tonic-gate 
1454*7c478bd9Sstevel@tonic-gate /*
1455*7c478bd9Sstevel@tonic-gate  * generate dat.conf header
1456*7c478bd9Sstevel@tonic-gate  */
1457*7c478bd9Sstevel@tonic-gate static int
1458*7c478bd9Sstevel@tonic-gate datadm_generate_conf_header(FILE *outfile)
1459*7c478bd9Sstevel@tonic-gate {
1460*7c478bd9Sstevel@tonic-gate 	datadm_entry_t		*cep;
1461*7c478bd9Sstevel@tonic-gate 	datadm_cmnt_entry_t	*cmnt;
1462*7c478bd9Sstevel@tonic-gate 	int			retval = 0;
1463*7c478bd9Sstevel@tonic-gate 
1464*7c478bd9Sstevel@tonic-gate 	cep = datadm_conf_header.dl_head;
1465*7c478bd9Sstevel@tonic-gate 	if (cep == NULL) {
1466*7c478bd9Sstevel@tonic-gate 		/*
1467*7c478bd9Sstevel@tonic-gate 		 * if dat.conf doesn't have a header, we prepend a
1468*7c478bd9Sstevel@tonic-gate 		 * default one.
1469*7c478bd9Sstevel@tonic-gate 		 */
1470*7c478bd9Sstevel@tonic-gate 		retval = fprintf(outfile, "%s", datadm_conf_header_default);
1471*7c478bd9Sstevel@tonic-gate 		goto done;
1472*7c478bd9Sstevel@tonic-gate 	}
1473*7c478bd9Sstevel@tonic-gate 	while (cep != NULL) {
1474*7c478bd9Sstevel@tonic-gate 		cmnt = (datadm_cmnt_entry_t *)cep;
1475*7c478bd9Sstevel@tonic-gate 		if (cmnt->cmnt_line != NULL) {
1476*7c478bd9Sstevel@tonic-gate 			int		len;
1477*7c478bd9Sstevel@tonic-gate 
1478*7c478bd9Sstevel@tonic-gate 			retval = fprintf(outfile, "%s", cmnt->cmnt_line);
1479*7c478bd9Sstevel@tonic-gate 			if (retval < 0) {
1480*7c478bd9Sstevel@tonic-gate 				break;
1481*7c478bd9Sstevel@tonic-gate 			}
1482*7c478bd9Sstevel@tonic-gate 
1483*7c478bd9Sstevel@tonic-gate 			/*
1484*7c478bd9Sstevel@tonic-gate 			 * append a newline if the comment line doesn't
1485*7c478bd9Sstevel@tonic-gate 			 * have one.
1486*7c478bd9Sstevel@tonic-gate 			 */
1487*7c478bd9Sstevel@tonic-gate 			len = strlen(cmnt->cmnt_line);
1488*7c478bd9Sstevel@tonic-gate 			if (cmnt->cmnt_line[len - 1] != '\n') {
1489*7c478bd9Sstevel@tonic-gate 				retval = fprintf(outfile, "\n");
1490*7c478bd9Sstevel@tonic-gate 				if (retval < 0) {
1491*7c478bd9Sstevel@tonic-gate 					break;
1492*7c478bd9Sstevel@tonic-gate 				}
1493*7c478bd9Sstevel@tonic-gate 			}
1494*7c478bd9Sstevel@tonic-gate 		}
1495*7c478bd9Sstevel@tonic-gate 		cep = cep->de_next;
1496*7c478bd9Sstevel@tonic-gate 	}
1497*7c478bd9Sstevel@tonic-gate done:;
1498*7c478bd9Sstevel@tonic-gate 	if (retval < 0) {
1499*7c478bd9Sstevel@tonic-gate 		return (-1);
1500*7c478bd9Sstevel@tonic-gate 	}
1501*7c478bd9Sstevel@tonic-gate 	return (0);
1502*7c478bd9Sstevel@tonic-gate }
1503*7c478bd9Sstevel@tonic-gate 
1504*7c478bd9Sstevel@tonic-gate /*
1505*7c478bd9Sstevel@tonic-gate  * outputs dat.conf to stdout or to basedir/etc/dat/dat.conf
1506*7c478bd9Sstevel@tonic-gate  */
1507*7c478bd9Sstevel@tonic-gate static int
1508*7c478bd9Sstevel@tonic-gate datadm_generate_dat_conf(datadm_list_t *hca_list)
1509*7c478bd9Sstevel@tonic-gate {
1510*7c478bd9Sstevel@tonic-gate 	FILE			*outfile = NULL;
1511*7c478bd9Sstevel@tonic-gate 	char			*dat_conf = datadm_args.da_dat_conf;
1512*7c478bd9Sstevel@tonic-gate 	datadm_entry_t		*hep;
1513*7c478bd9Sstevel@tonic-gate 	int			retval = 0;
1514*7c478bd9Sstevel@tonic-gate 
1515*7c478bd9Sstevel@tonic-gate 	if (datadm_args.da_op_type == DATADM_OP_VIEW) {
1516*7c478bd9Sstevel@tonic-gate 		outfile = stdout;
1517*7c478bd9Sstevel@tonic-gate 	} else {
1518*7c478bd9Sstevel@tonic-gate 		outfile = fopen(dat_conf, "w+");
1519*7c478bd9Sstevel@tonic-gate 		if (outfile == NULL) {
1520*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
1521*7c478bd9Sstevel@tonic-gate 			    "datadm: cannot open %s: %s\n"),
1522*7c478bd9Sstevel@tonic-gate 			    dat_conf, strerror(errno));
1523*7c478bd9Sstevel@tonic-gate 			return (-1);
1524*7c478bd9Sstevel@tonic-gate 		}
1525*7c478bd9Sstevel@tonic-gate 	}
1526*7c478bd9Sstevel@tonic-gate 	if (outfile != stdout) {
1527*7c478bd9Sstevel@tonic-gate 		/*
1528*7c478bd9Sstevel@tonic-gate 		 * do not generate the header if we are
1529*7c478bd9Sstevel@tonic-gate 		 * printing to the screen
1530*7c478bd9Sstevel@tonic-gate 		 */
1531*7c478bd9Sstevel@tonic-gate 		retval = datadm_generate_conf_header(outfile);
1532*7c478bd9Sstevel@tonic-gate 		if (retval != 0) {
1533*7c478bd9Sstevel@tonic-gate 			goto done;
1534*7c478bd9Sstevel@tonic-gate 		}
1535*7c478bd9Sstevel@tonic-gate 	}
1536*7c478bd9Sstevel@tonic-gate 	hep = hca_list->dl_head;
1537*7c478bd9Sstevel@tonic-gate 	while (hep != NULL) {
1538*7c478bd9Sstevel@tonic-gate 		datadm_entry_t	*iep;
1539*7c478bd9Sstevel@tonic-gate 
1540*7c478bd9Sstevel@tonic-gate 		iep = ((datadm_hca_entry_t *)hep)->he_ia_list.dl_head;
1541*7c478bd9Sstevel@tonic-gate 		while (iep != NULL) {
1542*7c478bd9Sstevel@tonic-gate 			datadm_entry_t	*sep;
1543*7c478bd9Sstevel@tonic-gate 
1544*7c478bd9Sstevel@tonic-gate 			sep = ((datadm_hca_entry_t *)hep)->he_sp_list.dl_head;
1545*7c478bd9Sstevel@tonic-gate 			while (sep != NULL) {
1546*7c478bd9Sstevel@tonic-gate 				if (((datadm_sp_entry_t *)sep)->spe_invalid) {
1547*7c478bd9Sstevel@tonic-gate 					sep = sep->de_next;
1548*7c478bd9Sstevel@tonic-gate 					continue;
1549*7c478bd9Sstevel@tonic-gate 				}
1550*7c478bd9Sstevel@tonic-gate 				retval = datadm_generate_conf_entry(outfile,
1551*7c478bd9Sstevel@tonic-gate 				    (datadm_ia_entry_t *)iep,
1552*7c478bd9Sstevel@tonic-gate 				    (datadm_sp_entry_t *)sep);
1553*7c478bd9Sstevel@tonic-gate 				if (retval != 0) {
1554*7c478bd9Sstevel@tonic-gate 					goto done;
1555*7c478bd9Sstevel@tonic-gate 				}
1556*7c478bd9Sstevel@tonic-gate 				sep = sep->de_next;
1557*7c478bd9Sstevel@tonic-gate 			}
1558*7c478bd9Sstevel@tonic-gate 			iep = iep->de_next;
1559*7c478bd9Sstevel@tonic-gate 		}
1560*7c478bd9Sstevel@tonic-gate 		hep = hep->de_next;
1561*7c478bd9Sstevel@tonic-gate 	}
1562*7c478bd9Sstevel@tonic-gate 	retval = fflush(outfile);
1563*7c478bd9Sstevel@tonic-gate done:;
1564*7c478bd9Sstevel@tonic-gate 	if (outfile != stdout) {
1565*7c478bd9Sstevel@tonic-gate 		(void) fclose(outfile);
1566*7c478bd9Sstevel@tonic-gate 	}
1567*7c478bd9Sstevel@tonic-gate 	if (retval < 0) {
1568*7c478bd9Sstevel@tonic-gate 		perror("datadm: fprintf");
1569*7c478bd9Sstevel@tonic-gate 	}
1570*7c478bd9Sstevel@tonic-gate 	return (retval);
1571*7c478bd9Sstevel@tonic-gate }
1572*7c478bd9Sstevel@tonic-gate 
1573*7c478bd9Sstevel@tonic-gate static int
1574*7c478bd9Sstevel@tonic-gate datadm_view(void)
1575*7c478bd9Sstevel@tonic-gate {
1576*7c478bd9Sstevel@tonic-gate 	int			retval = 0;
1577*7c478bd9Sstevel@tonic-gate 	datadm_list_t		hca_list;
1578*7c478bd9Sstevel@tonic-gate 
1579*7c478bd9Sstevel@tonic-gate 	bzero(&hca_list, sizeof (hca_list));
1580*7c478bd9Sstevel@tonic-gate 
1581*7c478bd9Sstevel@tonic-gate 	retval = datadm_parse_dat_conf(&hca_list);
1582*7c478bd9Sstevel@tonic-gate 	if (retval != 0) {
1583*7c478bd9Sstevel@tonic-gate 		goto cleanup;
1584*7c478bd9Sstevel@tonic-gate 	}
1585*7c478bd9Sstevel@tonic-gate 	retval = datadm_generate_dat_conf(&hca_list);
1586*7c478bd9Sstevel@tonic-gate 	if (retval != 0) {
1587*7c478bd9Sstevel@tonic-gate 		goto cleanup;
1588*7c478bd9Sstevel@tonic-gate 	}
1589*7c478bd9Sstevel@tonic-gate 
1590*7c478bd9Sstevel@tonic-gate cleanup:;
1591*7c478bd9Sstevel@tonic-gate 	datadm_free_list(&datadm_conf_header,
1592*7c478bd9Sstevel@tonic-gate 	    (void (*)(datadm_entry_t *))datadm_free_cmnt_entry);
1593*7c478bd9Sstevel@tonic-gate 	datadm_free_list(&hca_list,
1594*7c478bd9Sstevel@tonic-gate 	    (void (*)(datadm_entry_t *))datadm_free_hca_entry);
1595*7c478bd9Sstevel@tonic-gate 	return (retval);
1596*7c478bd9Sstevel@tonic-gate }
1597*7c478bd9Sstevel@tonic-gate 
1598*7c478bd9Sstevel@tonic-gate static int
1599*7c478bd9Sstevel@tonic-gate datadm_update(void)
1600*7c478bd9Sstevel@tonic-gate {
1601*7c478bd9Sstevel@tonic-gate 	int			retval = 0;
1602*7c478bd9Sstevel@tonic-gate 	datadm_list_t		hca_list;
1603*7c478bd9Sstevel@tonic-gate 
1604*7c478bd9Sstevel@tonic-gate 	bzero(&hca_list, sizeof (hca_list));
1605*7c478bd9Sstevel@tonic-gate 
1606*7c478bd9Sstevel@tonic-gate 	retval = datadm_parse_dat_conf(&hca_list);
1607*7c478bd9Sstevel@tonic-gate 	if (retval != 0) {
1608*7c478bd9Sstevel@tonic-gate 		goto cleanup;
1609*7c478bd9Sstevel@tonic-gate 	}
1610*7c478bd9Sstevel@tonic-gate 	retval = datadm_build_ia_lists(&hca_list);
1611*7c478bd9Sstevel@tonic-gate 	if (retval != 0) {
1612*7c478bd9Sstevel@tonic-gate 		goto cleanup;
1613*7c478bd9Sstevel@tonic-gate 	}
1614*7c478bd9Sstevel@tonic-gate 	retval = datadm_generate_dat_conf(&hca_list);
1615*7c478bd9Sstevel@tonic-gate 	if (retval != 0) {
1616*7c478bd9Sstevel@tonic-gate 		goto cleanup;
1617*7c478bd9Sstevel@tonic-gate 	}
1618*7c478bd9Sstevel@tonic-gate 
1619*7c478bd9Sstevel@tonic-gate cleanup:;
1620*7c478bd9Sstevel@tonic-gate 	datadm_free_list(&datadm_conf_header,
1621*7c478bd9Sstevel@tonic-gate 	    (void (*)(datadm_entry_t *))datadm_free_cmnt_entry);
1622*7c478bd9Sstevel@tonic-gate 	datadm_free_list(&hca_list,
1623*7c478bd9Sstevel@tonic-gate 	    (void (*)(datadm_entry_t *))datadm_free_hca_entry);
1624*7c478bd9Sstevel@tonic-gate 	return (retval);
1625*7c478bd9Sstevel@tonic-gate }
1626*7c478bd9Sstevel@tonic-gate 
1627*7c478bd9Sstevel@tonic-gate static int
1628*7c478bd9Sstevel@tonic-gate datadm_add(void)
1629*7c478bd9Sstevel@tonic-gate {
1630*7c478bd9Sstevel@tonic-gate 	int			retval = 0;
1631*7c478bd9Sstevel@tonic-gate 	datadm_list_t		hca_list;
1632*7c478bd9Sstevel@tonic-gate 
1633*7c478bd9Sstevel@tonic-gate 	bzero(&hca_list, sizeof (hca_list));
1634*7c478bd9Sstevel@tonic-gate 
1635*7c478bd9Sstevel@tonic-gate 	retval = datadm_parse_dat_conf(&hca_list);
1636*7c478bd9Sstevel@tonic-gate 	if (retval != 0) {
1637*7c478bd9Sstevel@tonic-gate 		goto cleanup;
1638*7c478bd9Sstevel@tonic-gate 	}
1639*7c478bd9Sstevel@tonic-gate 	retval = datadm_parse_sp_conf(&hca_list);
1640*7c478bd9Sstevel@tonic-gate 	if (retval != 0) {
1641*7c478bd9Sstevel@tonic-gate 		goto cleanup;
1642*7c478bd9Sstevel@tonic-gate 	}
1643*7c478bd9Sstevel@tonic-gate 	retval = datadm_build_ia_lists(&hca_list);
1644*7c478bd9Sstevel@tonic-gate 	if (retval != 0) {
1645*7c478bd9Sstevel@tonic-gate 		goto cleanup;
1646*7c478bd9Sstevel@tonic-gate 	}
1647*7c478bd9Sstevel@tonic-gate 	retval = datadm_generate_dat_conf(&hca_list);
1648*7c478bd9Sstevel@tonic-gate 	if (retval != 0) {
1649*7c478bd9Sstevel@tonic-gate 		goto cleanup;
1650*7c478bd9Sstevel@tonic-gate 	}
1651*7c478bd9Sstevel@tonic-gate 
1652*7c478bd9Sstevel@tonic-gate cleanup:;
1653*7c478bd9Sstevel@tonic-gate 	datadm_free_list(&datadm_conf_header,
1654*7c478bd9Sstevel@tonic-gate 	    (void (*)(datadm_entry_t *))datadm_free_cmnt_entry);
1655*7c478bd9Sstevel@tonic-gate 	datadm_free_list(&hca_list,
1656*7c478bd9Sstevel@tonic-gate 	    (void (*)(datadm_entry_t *))datadm_free_hca_entry);
1657*7c478bd9Sstevel@tonic-gate 	return (retval);
1658*7c478bd9Sstevel@tonic-gate }
1659*7c478bd9Sstevel@tonic-gate 
1660*7c478bd9Sstevel@tonic-gate static int
1661*7c478bd9Sstevel@tonic-gate datadm_remove(void)
1662*7c478bd9Sstevel@tonic-gate {
1663*7c478bd9Sstevel@tonic-gate 	int			retval = 0;
1664*7c478bd9Sstevel@tonic-gate 	datadm_list_t		hca_list;
1665*7c478bd9Sstevel@tonic-gate 	datadm_list_t		hca_list2;
1666*7c478bd9Sstevel@tonic-gate 
1667*7c478bd9Sstevel@tonic-gate 	bzero(&hca_list, sizeof (hca_list));
1668*7c478bd9Sstevel@tonic-gate 	bzero(&hca_list2, sizeof (hca_list2));
1669*7c478bd9Sstevel@tonic-gate 
1670*7c478bd9Sstevel@tonic-gate 	retval = datadm_parse_dat_conf(&hca_list);
1671*7c478bd9Sstevel@tonic-gate 	if (retval != 0) {
1672*7c478bd9Sstevel@tonic-gate 		goto cleanup;
1673*7c478bd9Sstevel@tonic-gate 	}
1674*7c478bd9Sstevel@tonic-gate 	retval = datadm_parse_sp_conf(&hca_list2);
1675*7c478bd9Sstevel@tonic-gate 	if (retval != 0) {
1676*7c478bd9Sstevel@tonic-gate 		goto cleanup;
1677*7c478bd9Sstevel@tonic-gate 	}
1678*7c478bd9Sstevel@tonic-gate 	datadm_invalidate_common_sp_entries(&hca_list, &hca_list2);
1679*7c478bd9Sstevel@tonic-gate 
1680*7c478bd9Sstevel@tonic-gate 	retval = datadm_generate_dat_conf(&hca_list);
1681*7c478bd9Sstevel@tonic-gate 	if (retval != 0) {
1682*7c478bd9Sstevel@tonic-gate 		goto cleanup;
1683*7c478bd9Sstevel@tonic-gate 	}
1684*7c478bd9Sstevel@tonic-gate 
1685*7c478bd9Sstevel@tonic-gate cleanup:;
1686*7c478bd9Sstevel@tonic-gate 	datadm_free_list(&datadm_conf_header,
1687*7c478bd9Sstevel@tonic-gate 	    (void (*)(datadm_entry_t *))datadm_free_cmnt_entry);
1688*7c478bd9Sstevel@tonic-gate 	datadm_free_list(&hca_list,
1689*7c478bd9Sstevel@tonic-gate 	    (void (*)(datadm_entry_t *))datadm_free_hca_entry);
1690*7c478bd9Sstevel@tonic-gate 	datadm_free_list(&hca_list2,
1691*7c478bd9Sstevel@tonic-gate 	    (void (*)(datadm_entry_t *))datadm_free_hca_entry);
1692*7c478bd9Sstevel@tonic-gate 	return (retval);
1693*7c478bd9Sstevel@tonic-gate }
1694*7c478bd9Sstevel@tonic-gate 
1695*7c478bd9Sstevel@tonic-gate static int
1696*7c478bd9Sstevel@tonic-gate datadm_locate_dat_conf(char *basedir)
1697*7c478bd9Sstevel@tonic-gate {
1698*7c478bd9Sstevel@tonic-gate 	char		*dat_conf;
1699*7c478bd9Sstevel@tonic-gate 
1700*7c478bd9Sstevel@tonic-gate 	if (basedir == NULL) {
1701*7c478bd9Sstevel@tonic-gate 		datadm_args.da_dat_conf = DATADM_DAT_CONF;
1702*7c478bd9Sstevel@tonic-gate 		return (0);
1703*7c478bd9Sstevel@tonic-gate 	}
1704*7c478bd9Sstevel@tonic-gate 	dat_conf = (char *)malloc(strlen(basedir) +
1705*7c478bd9Sstevel@tonic-gate 	    strlen(DATADM_DAT_CONF) + 1);
1706*7c478bd9Sstevel@tonic-gate 	if (dat_conf == NULL) {
1707*7c478bd9Sstevel@tonic-gate 		return (-1);
1708*7c478bd9Sstevel@tonic-gate 	}
1709*7c478bd9Sstevel@tonic-gate 	dat_conf[0] = '\0';
1710*7c478bd9Sstevel@tonic-gate 	(void) strcat(dat_conf, basedir);
1711*7c478bd9Sstevel@tonic-gate 	(void) strcat(dat_conf, DATADM_DAT_CONF);
1712*7c478bd9Sstevel@tonic-gate 	datadm_args.da_dat_conf = dat_conf;
1713*7c478bd9Sstevel@tonic-gate 	return (0);
1714*7c478bd9Sstevel@tonic-gate }
1715*7c478bd9Sstevel@tonic-gate 
1716*7c478bd9Sstevel@tonic-gate int
1717*7c478bd9Sstevel@tonic-gate main(int argc, char **argv)
1718*7c478bd9Sstevel@tonic-gate {
1719*7c478bd9Sstevel@tonic-gate 	extern char	*optarg;
1720*7c478bd9Sstevel@tonic-gate 	extern int	optind;
1721*7c478bd9Sstevel@tonic-gate 	char		*basedir = NULL;
1722*7c478bd9Sstevel@tonic-gate 	int		c, retval;
1723*7c478bd9Sstevel@tonic-gate 	int		op_type = -1, errflg = 0;
1724*7c478bd9Sstevel@tonic-gate 
1725*7c478bd9Sstevel@tonic-gate 	bzero(&datadm_args, sizeof (datadm_args));
1726*7c478bd9Sstevel@tonic-gate 	bzero(&datadm_conf_header, sizeof (datadm_conf_header));
1727*7c478bd9Sstevel@tonic-gate 
1728*7c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
1729*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
1730*7c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"	/* Use this only if it weren't */
1731*7c478bd9Sstevel@tonic-gate #endif
1732*7c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
1733*7c478bd9Sstevel@tonic-gate 
1734*7c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "vua:r:b:")) != EOF) {
1735*7c478bd9Sstevel@tonic-gate 		switch (c) {
1736*7c478bd9Sstevel@tonic-gate 		case 'v':
1737*7c478bd9Sstevel@tonic-gate 			if (op_type != -1) errflg = 1;
1738*7c478bd9Sstevel@tonic-gate 			op_type = DATADM_OP_VIEW;
1739*7c478bd9Sstevel@tonic-gate 			break;
1740*7c478bd9Sstevel@tonic-gate 		case 'u':
1741*7c478bd9Sstevel@tonic-gate 			if (op_type != -1) errflg = 1;
1742*7c478bd9Sstevel@tonic-gate 			op_type = DATADM_OP_UPDATE;
1743*7c478bd9Sstevel@tonic-gate 			break;
1744*7c478bd9Sstevel@tonic-gate 		case 'a':
1745*7c478bd9Sstevel@tonic-gate 			if (op_type != -1) errflg = 1;
1746*7c478bd9Sstevel@tonic-gate 			op_type = DATADM_OP_ADD;
1747*7c478bd9Sstevel@tonic-gate 			datadm_args.da_sp_conf = optarg;
1748*7c478bd9Sstevel@tonic-gate 			break;
1749*7c478bd9Sstevel@tonic-gate 		case 'r':
1750*7c478bd9Sstevel@tonic-gate 			if (op_type != -1) errflg = 1;
1751*7c478bd9Sstevel@tonic-gate 			op_type = DATADM_OP_REMOVE;
1752*7c478bd9Sstevel@tonic-gate 			datadm_args.da_sp_conf = optarg;
1753*7c478bd9Sstevel@tonic-gate 			break;
1754*7c478bd9Sstevel@tonic-gate 		case 'b':
1755*7c478bd9Sstevel@tonic-gate 			basedir = optarg;
1756*7c478bd9Sstevel@tonic-gate 			break;
1757*7c478bd9Sstevel@tonic-gate 		default:
1758*7c478bd9Sstevel@tonic-gate 			errflg = 1;
1759*7c478bd9Sstevel@tonic-gate 			break;
1760*7c478bd9Sstevel@tonic-gate 		}
1761*7c478bd9Sstevel@tonic-gate 		if (errflg != 0) {
1762*7c478bd9Sstevel@tonic-gate 			break;
1763*7c478bd9Sstevel@tonic-gate 		}
1764*7c478bd9Sstevel@tonic-gate 	}
1765*7c478bd9Sstevel@tonic-gate 	if (errflg != 0 || op_type == -1 || optind < argc) {
1766*7c478bd9Sstevel@tonic-gate 		datadm_usage();
1767*7c478bd9Sstevel@tonic-gate 		return (1);
1768*7c478bd9Sstevel@tonic-gate 	}
1769*7c478bd9Sstevel@tonic-gate 	datadm_args.da_op_type = op_type;
1770*7c478bd9Sstevel@tonic-gate 	if (datadm_locate_dat_conf(basedir)) {
1771*7c478bd9Sstevel@tonic-gate 		return (1);
1772*7c478bd9Sstevel@tonic-gate 	}
1773*7c478bd9Sstevel@tonic-gate 
1774*7c478bd9Sstevel@tonic-gate 	retval = (*datadm_ops[op_type])();
1775*7c478bd9Sstevel@tonic-gate 	return (retval);
1776*7c478bd9Sstevel@tonic-gate }
1777