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