1*11767SAnurag.Maskey@Sun.COM /*
2*11767SAnurag.Maskey@Sun.COM  * CDDL HEADER START
3*11767SAnurag.Maskey@Sun.COM  *
4*11767SAnurag.Maskey@Sun.COM  * The contents of this file are subject to the terms of the
5*11767SAnurag.Maskey@Sun.COM  * Common Development and Distribution License (the "License").
6*11767SAnurag.Maskey@Sun.COM  * You may not use this file except in compliance with the License.
7*11767SAnurag.Maskey@Sun.COM  *
8*11767SAnurag.Maskey@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*11767SAnurag.Maskey@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*11767SAnurag.Maskey@Sun.COM  * See the License for the specific language governing permissions
11*11767SAnurag.Maskey@Sun.COM  * and limitations under the License.
12*11767SAnurag.Maskey@Sun.COM  *
13*11767SAnurag.Maskey@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*11767SAnurag.Maskey@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*11767SAnurag.Maskey@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*11767SAnurag.Maskey@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*11767SAnurag.Maskey@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*11767SAnurag.Maskey@Sun.COM  *
19*11767SAnurag.Maskey@Sun.COM  * CDDL HEADER END
20*11767SAnurag.Maskey@Sun.COM  */
21*11767SAnurag.Maskey@Sun.COM 
22*11767SAnurag.Maskey@Sun.COM /*
23*11767SAnurag.Maskey@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
24*11767SAnurag.Maskey@Sun.COM  * Use is subject to license terms.
25*11767SAnurag.Maskey@Sun.COM  */
26*11767SAnurag.Maskey@Sun.COM 
27*11767SAnurag.Maskey@Sun.COM #include <assert.h>
28*11767SAnurag.Maskey@Sun.COM #include <dirent.h>
29*11767SAnurag.Maskey@Sun.COM #include <ctype.h>
30*11767SAnurag.Maskey@Sun.COM #include <libgen.h>
31*11767SAnurag.Maskey@Sun.COM #include <errno.h>
32*11767SAnurag.Maskey@Sun.COM #include <fcntl.h>
33*11767SAnurag.Maskey@Sun.COM #include <sys/param.h>
34*11767SAnurag.Maskey@Sun.COM #include <sys/types.h>
35*11767SAnurag.Maskey@Sun.COM #include <sys/stat.h>
36*11767SAnurag.Maskey@Sun.COM #include <stdio.h>
37*11767SAnurag.Maskey@Sun.COM #include <stdlib.h>
38*11767SAnurag.Maskey@Sun.COM #include <strings.h>
39*11767SAnurag.Maskey@Sun.COM #include <unistd.h>
40*11767SAnurag.Maskey@Sun.COM 
41*11767SAnurag.Maskey@Sun.COM #include "libnwam_impl.h"
42*11767SAnurag.Maskey@Sun.COM #include <libnwam_priv.h>
43*11767SAnurag.Maskey@Sun.COM #include <libnwam.h>
44*11767SAnurag.Maskey@Sun.COM 
45*11767SAnurag.Maskey@Sun.COM /*
46*11767SAnurag.Maskey@Sun.COM  * Implementation of files backend for libnwam configuration objects.
47*11767SAnurag.Maskey@Sun.COM  * /etc/dladm/datalink.conf-like format is used.
48*11767SAnurag.Maskey@Sun.COM  */
49*11767SAnurag.Maskey@Sun.COM #define	NWAM_FILE_LINE_MAX		2048
50*11767SAnurag.Maskey@Sun.COM #define	NWAM_FILE_PROP_ESCAPE		'\\'
51*11767SAnurag.Maskey@Sun.COM #define	NWAM_FILE_PROP_DELIMITER	';'
52*11767SAnurag.Maskey@Sun.COM #define	NWAM_FILE_PROP_ASSIGN		'='
53*11767SAnurag.Maskey@Sun.COM #define	NWAM_FILE_VALUE_DELIMITER	','
54*11767SAnurag.Maskey@Sun.COM #define	NWAM_FILE_BOOLEAN_TRUE		"true"
55*11767SAnurag.Maskey@Sun.COM #define	NWAM_FILE_BOOLEAN_FALSE		"false"
56*11767SAnurag.Maskey@Sun.COM 
57*11767SAnurag.Maskey@Sun.COM /*
58*11767SAnurag.Maskey@Sun.COM  * strtok_r-like function that takes a string, finds the next unescaped
59*11767SAnurag.Maskey@Sun.COM  * delimiter char after in, nullifies it and sets nextp to point to the
60*11767SAnurag.Maskey@Sun.COM  * remaining string (if any). Returns in, setting nextp to NULL if no such
61*11767SAnurag.Maskey@Sun.COM  * delimiter is found.
62*11767SAnurag.Maskey@Sun.COM  */
63*11767SAnurag.Maskey@Sun.COM char *
64*11767SAnurag.Maskey@Sun.COM nwam_tokenize_by_unescaped_delim(char *in, char delim, char **nextp)
65*11767SAnurag.Maskey@Sun.COM {
66*11767SAnurag.Maskey@Sun.COM 	boolean_t escaped = B_FALSE;
67*11767SAnurag.Maskey@Sun.COM 	size_t totlen;
68*11767SAnurag.Maskey@Sun.COM 
69*11767SAnurag.Maskey@Sun.COM 	if (in == NULL)
70*11767SAnurag.Maskey@Sun.COM 		return (NULL);
71*11767SAnurag.Maskey@Sun.COM 
72*11767SAnurag.Maskey@Sun.COM 	totlen = strlen(in);
73*11767SAnurag.Maskey@Sun.COM 
74*11767SAnurag.Maskey@Sun.COM 	for (*nextp = in; (*nextp - in) < strlen(in); (*nextp)++) {
75*11767SAnurag.Maskey@Sun.COM 		if ((*nextp)[0] == NWAM_FILE_PROP_ESCAPE) {
76*11767SAnurag.Maskey@Sun.COM 			escaped = !escaped;
77*11767SAnurag.Maskey@Sun.COM 		} else if (!escaped && (*nextp)[0] == delim) {
78*11767SAnurag.Maskey@Sun.COM 			/* Nullify delimiter */
79*11767SAnurag.Maskey@Sun.COM 			(*nextp)[0] = '\0';
80*11767SAnurag.Maskey@Sun.COM 			/*
81*11767SAnurag.Maskey@Sun.COM 			 * If more string left to go, nextp points to string
82*11767SAnurag.Maskey@Sun.COM 			 * after delimiter, otherwise NULL.
83*11767SAnurag.Maskey@Sun.COM 			 */
84*11767SAnurag.Maskey@Sun.COM 			(*nextp)++;
85*11767SAnurag.Maskey@Sun.COM 			*nextp = ((*nextp - in) < totlen) ? (*nextp) : NULL;
86*11767SAnurag.Maskey@Sun.COM 			return (in);
87*11767SAnurag.Maskey@Sun.COM 		} else {
88*11767SAnurag.Maskey@Sun.COM 			escaped = B_FALSE;
89*11767SAnurag.Maskey@Sun.COM 		}
90*11767SAnurag.Maskey@Sun.COM 	}
91*11767SAnurag.Maskey@Sun.COM 	*nextp = NULL;
92*11767SAnurag.Maskey@Sun.COM 	return (in);
93*11767SAnurag.Maskey@Sun.COM }
94*11767SAnurag.Maskey@Sun.COM 
95*11767SAnurag.Maskey@Sun.COM /* Add escape chars to value string */
96*11767SAnurag.Maskey@Sun.COM static void
97*11767SAnurag.Maskey@Sun.COM value_add_escapes(char *in, char *out)
98*11767SAnurag.Maskey@Sun.COM {
99*11767SAnurag.Maskey@Sun.COM 	int i, j = 0;
100*11767SAnurag.Maskey@Sun.COM 
101*11767SAnurag.Maskey@Sun.COM 	/*
102*11767SAnurag.Maskey@Sun.COM 	 * It is safe to use strlen() as we sanitycheck string length on value
103*11767SAnurag.Maskey@Sun.COM 	 * creation, so no string longer than NWAM_MAX_VALUE_LEN is accepted.
104*11767SAnurag.Maskey@Sun.COM 	 */
105*11767SAnurag.Maskey@Sun.COM 	for (i = 0; i < strlen(in); i++) {
106*11767SAnurag.Maskey@Sun.COM 		switch (in[i]) {
107*11767SAnurag.Maskey@Sun.COM 		case NWAM_FILE_VALUE_DELIMITER:
108*11767SAnurag.Maskey@Sun.COM 		case NWAM_FILE_PROP_DELIMITER:
109*11767SAnurag.Maskey@Sun.COM 		case NWAM_FILE_PROP_ESCAPE:
110*11767SAnurag.Maskey@Sun.COM 			out[j++] = NWAM_FILE_PROP_ESCAPE;
111*11767SAnurag.Maskey@Sun.COM 			out[j++] = in[i];
112*11767SAnurag.Maskey@Sun.COM 			break;
113*11767SAnurag.Maskey@Sun.COM 		default:
114*11767SAnurag.Maskey@Sun.COM 			out[j++] = in[i];
115*11767SAnurag.Maskey@Sun.COM 			break;
116*11767SAnurag.Maskey@Sun.COM 		}
117*11767SAnurag.Maskey@Sun.COM 	}
118*11767SAnurag.Maskey@Sun.COM 	out[j] = '\0';
119*11767SAnurag.Maskey@Sun.COM }
120*11767SAnurag.Maskey@Sun.COM 
121*11767SAnurag.Maskey@Sun.COM static char *
122*11767SAnurag.Maskey@Sun.COM value_remove_escapes(char *in)
123*11767SAnurag.Maskey@Sun.COM {
124*11767SAnurag.Maskey@Sun.COM 	char *out;
125*11767SAnurag.Maskey@Sun.COM 	int i, j = 0;
126*11767SAnurag.Maskey@Sun.COM 
127*11767SAnurag.Maskey@Sun.COM 	if ((out = strdup(in)) == NULL)
128*11767SAnurag.Maskey@Sun.COM 		return (NULL);
129*11767SAnurag.Maskey@Sun.COM 
130*11767SAnurag.Maskey@Sun.COM 	/*
131*11767SAnurag.Maskey@Sun.COM 	 * It is safe to use strlen() as we sanitycheck string length on value
132*11767SAnurag.Maskey@Sun.COM 	 * creation (i.e. before they are written to the file), so no string
133*11767SAnurag.Maskey@Sun.COM 	 * longer than NWAM_MAX_VALUE_LEN is accepted.
134*11767SAnurag.Maskey@Sun.COM 	 */
135*11767SAnurag.Maskey@Sun.COM 	for (i = 0; i < strlen(in); i++) {
136*11767SAnurag.Maskey@Sun.COM 		if (in[i] == NWAM_FILE_PROP_ESCAPE)
137*11767SAnurag.Maskey@Sun.COM 			out[j++] = in[++i];
138*11767SAnurag.Maskey@Sun.COM 		else
139*11767SAnurag.Maskey@Sun.COM 			out[j++] = in[i];
140*11767SAnurag.Maskey@Sun.COM 	}
141*11767SAnurag.Maskey@Sun.COM 	out[j] = '\0';
142*11767SAnurag.Maskey@Sun.COM 	return (out);
143*11767SAnurag.Maskey@Sun.COM }
144*11767SAnurag.Maskey@Sun.COM 
145*11767SAnurag.Maskey@Sun.COM 
146*11767SAnurag.Maskey@Sun.COM /*
147*11767SAnurag.Maskey@Sun.COM  * Parse line into name and object list of properties.
148*11767SAnurag.Maskey@Sun.COM  * Each line has the format:
149*11767SAnurag.Maskey@Sun.COM  *
150*11767SAnurag.Maskey@Sun.COM  * objname	[prop=type:val1[,val2..];..]
151*11767SAnurag.Maskey@Sun.COM  */
152*11767SAnurag.Maskey@Sun.COM nwam_error_t
153*11767SAnurag.Maskey@Sun.COM nwam_line_to_object(char *line, char **objname, void *proplist)
154*11767SAnurag.Maskey@Sun.COM {
155*11767SAnurag.Maskey@Sun.COM 	char *next = line, *prop, *nextprop, *propname, *proptypestr, *nextval;
156*11767SAnurag.Maskey@Sun.COM 	char **valstr, **newvalstr;
157*11767SAnurag.Maskey@Sun.COM 	boolean_t *valbool, *newvalbool;
158*11767SAnurag.Maskey@Sun.COM 	int64_t *valint, *newvalint;
159*11767SAnurag.Maskey@Sun.COM 	uint64_t *valuint, *newvaluint;
160*11767SAnurag.Maskey@Sun.COM 	uint_t nelem, i;
161*11767SAnurag.Maskey@Sun.COM 	nwam_value_type_t proptype;
162*11767SAnurag.Maskey@Sun.COM 	nwam_value_t val = NULL;
163*11767SAnurag.Maskey@Sun.COM 	nwam_error_t err;
164*11767SAnurag.Maskey@Sun.COM 
165*11767SAnurag.Maskey@Sun.COM 	if ((err = nwam_alloc_object_list(proplist)) != NWAM_SUCCESS)
166*11767SAnurag.Maskey@Sun.COM 		return (err);
167*11767SAnurag.Maskey@Sun.COM 
168*11767SAnurag.Maskey@Sun.COM 	*objname = line;
169*11767SAnurag.Maskey@Sun.COM 
170*11767SAnurag.Maskey@Sun.COM 	if ((*objname = nwam_tokenize_by_unescaped_delim(line, '\t', &prop))
171*11767SAnurag.Maskey@Sun.COM 	    == NULL) {
172*11767SAnurag.Maskey@Sun.COM 		nwam_free_object_list(*((char **)proplist));
173*11767SAnurag.Maskey@Sun.COM 		return (NWAM_ENTITY_INVALID);
174*11767SAnurag.Maskey@Sun.COM 	}
175*11767SAnurag.Maskey@Sun.COM 
176*11767SAnurag.Maskey@Sun.COM 	while ((prop = nwam_tokenize_by_unescaped_delim(prop,
177*11767SAnurag.Maskey@Sun.COM 	    NWAM_FILE_PROP_DELIMITER, &nextprop)) != NULL) {
178*11767SAnurag.Maskey@Sun.COM 		/*
179*11767SAnurag.Maskey@Sun.COM 		 * Parse property into name=type,val[,val]
180*11767SAnurag.Maskey@Sun.COM 		 */
181*11767SAnurag.Maskey@Sun.COM 		if ((propname = nwam_tokenize_by_unescaped_delim(prop,
182*11767SAnurag.Maskey@Sun.COM 		    NWAM_FILE_PROP_ASSIGN, &next)) == NULL ||
183*11767SAnurag.Maskey@Sun.COM 		    (proptypestr = nwam_tokenize_by_unescaped_delim(next,
184*11767SAnurag.Maskey@Sun.COM 		    NWAM_FILE_VALUE_DELIMITER, &next)) == NULL) {
185*11767SAnurag.Maskey@Sun.COM 			nwam_free_object_list(*((char **)proplist));
186*11767SAnurag.Maskey@Sun.COM 			return (NWAM_ENTITY_INVALID);
187*11767SAnurag.Maskey@Sun.COM 		}
188*11767SAnurag.Maskey@Sun.COM 		if ((proptype = nwam_string_to_value_type(proptypestr)) ==
189*11767SAnurag.Maskey@Sun.COM 		    NWAM_VALUE_TYPE_UNKNOWN) {
190*11767SAnurag.Maskey@Sun.COM 			nwam_free_object_list(*((char **)proplist));
191*11767SAnurag.Maskey@Sun.COM 			return (NWAM_ENTITY_INVALID);
192*11767SAnurag.Maskey@Sun.COM 		}
193*11767SAnurag.Maskey@Sun.COM 		valbool = NULL;
194*11767SAnurag.Maskey@Sun.COM 		valint = NULL;
195*11767SAnurag.Maskey@Sun.COM 		valstr = NULL;
196*11767SAnurag.Maskey@Sun.COM 		switch (proptype) {
197*11767SAnurag.Maskey@Sun.COM 		case NWAM_VALUE_TYPE_BOOLEAN:
198*11767SAnurag.Maskey@Sun.COM 			valbool = calloc(NWAM_MAX_NUM_VALUES,
199*11767SAnurag.Maskey@Sun.COM 			    sizeof (boolean_t));
200*11767SAnurag.Maskey@Sun.COM 			break;
201*11767SAnurag.Maskey@Sun.COM 		case NWAM_VALUE_TYPE_INT64:
202*11767SAnurag.Maskey@Sun.COM 			valint = calloc(NWAM_MAX_NUM_VALUES,
203*11767SAnurag.Maskey@Sun.COM 			    sizeof (int64_t));
204*11767SAnurag.Maskey@Sun.COM 			break;
205*11767SAnurag.Maskey@Sun.COM 		case NWAM_VALUE_TYPE_UINT64:
206*11767SAnurag.Maskey@Sun.COM 			valuint = calloc(NWAM_MAX_NUM_VALUES,
207*11767SAnurag.Maskey@Sun.COM 			    sizeof (uint64_t));
208*11767SAnurag.Maskey@Sun.COM 			break;
209*11767SAnurag.Maskey@Sun.COM 		case NWAM_VALUE_TYPE_STRING:
210*11767SAnurag.Maskey@Sun.COM 			valstr = calloc(NWAM_MAX_NUM_VALUES,
211*11767SAnurag.Maskey@Sun.COM 			    sizeof (char *));
212*11767SAnurag.Maskey@Sun.COM 			break;
213*11767SAnurag.Maskey@Sun.COM 		default:
214*11767SAnurag.Maskey@Sun.COM 			nwam_free_object_list(*((char **)proplist));
215*11767SAnurag.Maskey@Sun.COM 			return (NWAM_ENTITY_INVALID_VALUE);
216*11767SAnurag.Maskey@Sun.COM 		}
217*11767SAnurag.Maskey@Sun.COM 		if (valbool == NULL && valint == NULL && valuint == NULL &&
218*11767SAnurag.Maskey@Sun.COM 		    valstr == NULL) {
219*11767SAnurag.Maskey@Sun.COM 			/* Memory allocation failed */
220*11767SAnurag.Maskey@Sun.COM 			nwam_free_object_list(*((char **)proplist));
221*11767SAnurag.Maskey@Sun.COM 			return (NWAM_NO_MEMORY);
222*11767SAnurag.Maskey@Sun.COM 		}
223*11767SAnurag.Maskey@Sun.COM 		nelem = 0;
224*11767SAnurag.Maskey@Sun.COM 		while ((nextval = nwam_tokenize_by_unescaped_delim(next,
225*11767SAnurag.Maskey@Sun.COM 		    NWAM_FILE_VALUE_DELIMITER, &next)) != NULL) {
226*11767SAnurag.Maskey@Sun.COM 			nelem++;
227*11767SAnurag.Maskey@Sun.COM 			switch (proptype) {
228*11767SAnurag.Maskey@Sun.COM 			case NWAM_VALUE_TYPE_BOOLEAN:
229*11767SAnurag.Maskey@Sun.COM 				if (strncmp(nextval, NWAM_FILE_BOOLEAN_TRUE,
230*11767SAnurag.Maskey@Sun.COM 				    strlen(nextval)) == 0) {
231*11767SAnurag.Maskey@Sun.COM 					valbool[nelem - 1] = B_TRUE;
232*11767SAnurag.Maskey@Sun.COM 				} else if (strncmp(nextval,
233*11767SAnurag.Maskey@Sun.COM 				    NWAM_FILE_BOOLEAN_FALSE, strlen(nextval))
234*11767SAnurag.Maskey@Sun.COM 				    == 0) {
235*11767SAnurag.Maskey@Sun.COM 					valbool[nelem - 1] = B_FALSE;
236*11767SAnurag.Maskey@Sun.COM 				} else {
237*11767SAnurag.Maskey@Sun.COM 					nwam_free_object_list
238*11767SAnurag.Maskey@Sun.COM 					    (*((char **)proplist));
239*11767SAnurag.Maskey@Sun.COM 					return (NWAM_ENTITY_INVALID_VALUE);
240*11767SAnurag.Maskey@Sun.COM 				}
241*11767SAnurag.Maskey@Sun.COM 				break;
242*11767SAnurag.Maskey@Sun.COM 			case NWAM_VALUE_TYPE_INT64:
243*11767SAnurag.Maskey@Sun.COM 				valint[nelem - 1] = (int64_t)atoll(nextval);
244*11767SAnurag.Maskey@Sun.COM 				break;
245*11767SAnurag.Maskey@Sun.COM 			case NWAM_VALUE_TYPE_UINT64:
246*11767SAnurag.Maskey@Sun.COM 				valuint[nelem - 1] = (uint64_t)atoll(nextval);
247*11767SAnurag.Maskey@Sun.COM 				break;
248*11767SAnurag.Maskey@Sun.COM 			case NWAM_VALUE_TYPE_STRING:
249*11767SAnurag.Maskey@Sun.COM 				valstr[nelem - 1] =
250*11767SAnurag.Maskey@Sun.COM 				    value_remove_escapes(nextval);
251*11767SAnurag.Maskey@Sun.COM 				break;
252*11767SAnurag.Maskey@Sun.COM 			default:
253*11767SAnurag.Maskey@Sun.COM 				nwam_free_object_list(*((char **)proplist));
254*11767SAnurag.Maskey@Sun.COM 				return (NWAM_ENTITY_INVALID_VALUE);
255*11767SAnurag.Maskey@Sun.COM 			}
256*11767SAnurag.Maskey@Sun.COM 		}
257*11767SAnurag.Maskey@Sun.COM 		switch (proptype) {
258*11767SAnurag.Maskey@Sun.COM 		case NWAM_VALUE_TYPE_BOOLEAN:
259*11767SAnurag.Maskey@Sun.COM 			if ((newvalbool = realloc(valbool,
260*11767SAnurag.Maskey@Sun.COM 			    nelem * sizeof (boolean_t))) == NULL) {
261*11767SAnurag.Maskey@Sun.COM 				nwam_free_object_list(*((char **)proplist));
262*11767SAnurag.Maskey@Sun.COM 				return (NWAM_NO_MEMORY);
263*11767SAnurag.Maskey@Sun.COM 			}
264*11767SAnurag.Maskey@Sun.COM 			if ((err = nwam_value_create_boolean_array(newvalbool,
265*11767SAnurag.Maskey@Sun.COM 			    nelem, &val)) != NWAM_SUCCESS ||
266*11767SAnurag.Maskey@Sun.COM 			    (err = nwam_set_prop_value(*((char **)proplist),
267*11767SAnurag.Maskey@Sun.COM 			    propname, val)) != NWAM_SUCCESS) {
268*11767SAnurag.Maskey@Sun.COM 				free(newvalbool);
269*11767SAnurag.Maskey@Sun.COM 				nwam_value_free(val);
270*11767SAnurag.Maskey@Sun.COM 				nwam_free_object_list(*((char **)proplist));
271*11767SAnurag.Maskey@Sun.COM 				return (err);
272*11767SAnurag.Maskey@Sun.COM 			}
273*11767SAnurag.Maskey@Sun.COM 			free(newvalbool);
274*11767SAnurag.Maskey@Sun.COM 			nwam_value_free(val);
275*11767SAnurag.Maskey@Sun.COM 			break;
276*11767SAnurag.Maskey@Sun.COM 		case NWAM_VALUE_TYPE_INT64:
277*11767SAnurag.Maskey@Sun.COM 			if ((newvalint = realloc(valint,
278*11767SAnurag.Maskey@Sun.COM 			    nelem * sizeof (int64_t))) == NULL) {
279*11767SAnurag.Maskey@Sun.COM 				nwam_free_object_list(*((char **)proplist));
280*11767SAnurag.Maskey@Sun.COM 				return (NWAM_NO_MEMORY);
281*11767SAnurag.Maskey@Sun.COM 			}
282*11767SAnurag.Maskey@Sun.COM 			if ((err = nwam_value_create_int64_array(newvalint,
283*11767SAnurag.Maskey@Sun.COM 			    nelem, &val)) != NWAM_SUCCESS ||
284*11767SAnurag.Maskey@Sun.COM 			    (err = nwam_set_prop_value(*((char **)proplist),
285*11767SAnurag.Maskey@Sun.COM 			    propname, val)) != NWAM_SUCCESS) {
286*11767SAnurag.Maskey@Sun.COM 				free(newvalint);
287*11767SAnurag.Maskey@Sun.COM 				nwam_value_free(val);
288*11767SAnurag.Maskey@Sun.COM 				nwam_free_object_list(*((char **)proplist));
289*11767SAnurag.Maskey@Sun.COM 				return (err);
290*11767SAnurag.Maskey@Sun.COM 			}
291*11767SAnurag.Maskey@Sun.COM 			free(newvalint);
292*11767SAnurag.Maskey@Sun.COM 			nwam_value_free(val);
293*11767SAnurag.Maskey@Sun.COM 			break;
294*11767SAnurag.Maskey@Sun.COM 		case NWAM_VALUE_TYPE_UINT64:
295*11767SAnurag.Maskey@Sun.COM 			if ((newvaluint = realloc(valuint,
296*11767SAnurag.Maskey@Sun.COM 			    nelem * sizeof (uint64_t))) == NULL) {
297*11767SAnurag.Maskey@Sun.COM 				nwam_free_object_list(*((char **)proplist));
298*11767SAnurag.Maskey@Sun.COM 				return (NWAM_NO_MEMORY);
299*11767SAnurag.Maskey@Sun.COM 			}
300*11767SAnurag.Maskey@Sun.COM 			if ((err = nwam_value_create_uint64_array(newvaluint,
301*11767SAnurag.Maskey@Sun.COM 			    nelem, &val)) != NWAM_SUCCESS ||
302*11767SAnurag.Maskey@Sun.COM 			    (err = nwam_set_prop_value(*((char **)proplist),
303*11767SAnurag.Maskey@Sun.COM 			    propname, val)) != NWAM_SUCCESS) {
304*11767SAnurag.Maskey@Sun.COM 				free(newvaluint);
305*11767SAnurag.Maskey@Sun.COM 				nwam_value_free(val);
306*11767SAnurag.Maskey@Sun.COM 				nwam_free_object_list(*((char **)proplist));
307*11767SAnurag.Maskey@Sun.COM 				return (err);
308*11767SAnurag.Maskey@Sun.COM 			}
309*11767SAnurag.Maskey@Sun.COM 			free(newvaluint);
310*11767SAnurag.Maskey@Sun.COM 			nwam_value_free(val);
311*11767SAnurag.Maskey@Sun.COM 			break;
312*11767SAnurag.Maskey@Sun.COM 		case NWAM_VALUE_TYPE_STRING:
313*11767SAnurag.Maskey@Sun.COM 			if ((newvalstr = realloc(valstr,
314*11767SAnurag.Maskey@Sun.COM 			    nelem * sizeof (char *))) == NULL) {
315*11767SAnurag.Maskey@Sun.COM 				nwam_free_object_list(*((char **)proplist));
316*11767SAnurag.Maskey@Sun.COM 				return (NWAM_NO_MEMORY);
317*11767SAnurag.Maskey@Sun.COM 			}
318*11767SAnurag.Maskey@Sun.COM 			if ((err = nwam_value_create_string_array(newvalstr,
319*11767SAnurag.Maskey@Sun.COM 			    nelem, &val)) != NWAM_SUCCESS ||
320*11767SAnurag.Maskey@Sun.COM 			    (err = nwam_set_prop_value(*((char **)proplist),
321*11767SAnurag.Maskey@Sun.COM 			    propname, val)) != NWAM_SUCCESS) {
322*11767SAnurag.Maskey@Sun.COM 				for (i = 0; i < nelem; i++)
323*11767SAnurag.Maskey@Sun.COM 					free(newvalstr[i]);
324*11767SAnurag.Maskey@Sun.COM 				free(newvalstr);
325*11767SAnurag.Maskey@Sun.COM 				nwam_value_free(val);
326*11767SAnurag.Maskey@Sun.COM 				nwam_free_object_list(*((char **)proplist));
327*11767SAnurag.Maskey@Sun.COM 				return (err);
328*11767SAnurag.Maskey@Sun.COM 			}
329*11767SAnurag.Maskey@Sun.COM 			for (i = 0; i < nelem; i++)
330*11767SAnurag.Maskey@Sun.COM 				free(newvalstr[i]);
331*11767SAnurag.Maskey@Sun.COM 			free(newvalstr);
332*11767SAnurag.Maskey@Sun.COM 			nwam_value_free(val);
333*11767SAnurag.Maskey@Sun.COM 			break;
334*11767SAnurag.Maskey@Sun.COM 		}
335*11767SAnurag.Maskey@Sun.COM 		prop = nextprop;
336*11767SAnurag.Maskey@Sun.COM 	}
337*11767SAnurag.Maskey@Sun.COM 
338*11767SAnurag.Maskey@Sun.COM 	return (NWAM_SUCCESS);
339*11767SAnurag.Maskey@Sun.COM }
340*11767SAnurag.Maskey@Sun.COM 
341*11767SAnurag.Maskey@Sun.COM /*
342*11767SAnurag.Maskey@Sun.COM  * Create list of NCP files used for walk of NCPs and for case-insensitive
343*11767SAnurag.Maskey@Sun.COM  * matching of NCP name to file.
344*11767SAnurag.Maskey@Sun.COM  */
345*11767SAnurag.Maskey@Sun.COM static nwam_error_t
346*11767SAnurag.Maskey@Sun.COM create_ncp_file_list(char ***ncpfilesp, uint_t *num_filesp)
347*11767SAnurag.Maskey@Sun.COM {
348*11767SAnurag.Maskey@Sun.COM 	DIR *dirp = NULL;
349*11767SAnurag.Maskey@Sun.COM 	struct dirent *dp;
350*11767SAnurag.Maskey@Sun.COM 	char *ncpname, **ncpfiles = NULL;
351*11767SAnurag.Maskey@Sun.COM 	nwam_error_t err = NWAM_SUCCESS;
352*11767SAnurag.Maskey@Sun.COM 	uint_t i;
353*11767SAnurag.Maskey@Sun.COM 
354*11767SAnurag.Maskey@Sun.COM 	ncpfiles = calloc(NWAM_MAX_NUM_OBJECTS, sizeof (char *));
355*11767SAnurag.Maskey@Sun.COM 	if (ncpfiles == NULL)
356*11767SAnurag.Maskey@Sun.COM 		return (NWAM_NO_MEMORY);
357*11767SAnurag.Maskey@Sun.COM 	*num_filesp = 0;
358*11767SAnurag.Maskey@Sun.COM 
359*11767SAnurag.Maskey@Sun.COM 	/*
360*11767SAnurag.Maskey@Sun.COM 	 * Construct NCP list by finding all files in NWAM directory
361*11767SAnurag.Maskey@Sun.COM 	 * that match the NCP filename format.
362*11767SAnurag.Maskey@Sun.COM 	 */
363*11767SAnurag.Maskey@Sun.COM 	if ((dirp = opendir(NWAM_CONF_DIR)) == NULL) {
364*11767SAnurag.Maskey@Sun.COM 		err = nwam_errno_to_nwam_error(errno);
365*11767SAnurag.Maskey@Sun.COM 		goto done;
366*11767SAnurag.Maskey@Sun.COM 	}
367*11767SAnurag.Maskey@Sun.COM 
368*11767SAnurag.Maskey@Sun.COM 	while ((dp = readdir(dirp)) != NULL) {
369*11767SAnurag.Maskey@Sun.COM 		uint_t filenamelen;
370*11767SAnurag.Maskey@Sun.COM 
371*11767SAnurag.Maskey@Sun.COM 		/* Ensure filename is valid */
372*11767SAnurag.Maskey@Sun.COM 		if (nwam_ncp_file_to_name(dp->d_name, &ncpname) != NWAM_SUCCESS)
373*11767SAnurag.Maskey@Sun.COM 			continue;
374*11767SAnurag.Maskey@Sun.COM 		free(ncpname);
375*11767SAnurag.Maskey@Sun.COM 		filenamelen = strlen(NWAM_CONF_DIR) + strlen(dp->d_name) + 1;
376*11767SAnurag.Maskey@Sun.COM 		if ((ncpfiles[*num_filesp] = malloc(filenamelen)) == NULL) {
377*11767SAnurag.Maskey@Sun.COM 			err = NWAM_NO_MEMORY;
378*11767SAnurag.Maskey@Sun.COM 			goto done;
379*11767SAnurag.Maskey@Sun.COM 		}
380*11767SAnurag.Maskey@Sun.COM 		(void) strlcpy(ncpfiles[*num_filesp], NWAM_CONF_DIR,
381*11767SAnurag.Maskey@Sun.COM 		    strlen(NWAM_CONF_DIR) + 1);
382*11767SAnurag.Maskey@Sun.COM 		(void) strlcpy(ncpfiles[*num_filesp] + strlen(NWAM_CONF_DIR),
383*11767SAnurag.Maskey@Sun.COM 		    dp->d_name, filenamelen - strlen(NWAM_CONF_DIR));
384*11767SAnurag.Maskey@Sun.COM 		(*num_filesp)++;
385*11767SAnurag.Maskey@Sun.COM 	}
386*11767SAnurag.Maskey@Sun.COM done:
387*11767SAnurag.Maskey@Sun.COM 	if (dirp != NULL)
388*11767SAnurag.Maskey@Sun.COM 		(void) closedir(dirp);
389*11767SAnurag.Maskey@Sun.COM 
390*11767SAnurag.Maskey@Sun.COM 	if (err != NWAM_SUCCESS) {
391*11767SAnurag.Maskey@Sun.COM 		for (i = 0; i < *num_filesp; i++)
392*11767SAnurag.Maskey@Sun.COM 			free(ncpfiles[i]);
393*11767SAnurag.Maskey@Sun.COM 		free(ncpfiles);
394*11767SAnurag.Maskey@Sun.COM 	} else {
395*11767SAnurag.Maskey@Sun.COM 		*ncpfilesp = realloc(ncpfiles, sizeof (char *) * (*num_filesp));
396*11767SAnurag.Maskey@Sun.COM 		if (*ncpfilesp == NULL)
397*11767SAnurag.Maskey@Sun.COM 			err = NWAM_NO_MEMORY;
398*11767SAnurag.Maskey@Sun.COM 	}
399*11767SAnurag.Maskey@Sun.COM 	return (err);
400*11767SAnurag.Maskey@Sun.COM }
401*11767SAnurag.Maskey@Sun.COM 
402*11767SAnurag.Maskey@Sun.COM /*
403*11767SAnurag.Maskey@Sun.COM  * Read object specified by objname from file, converting it to
404*11767SAnurag.Maskey@Sun.COM  * an object list.  If filename is NULL, a list of configuration object
405*11767SAnurag.Maskey@Sun.COM  * containers is returned, represented as an object lists with elements "enms"
406*11767SAnurag.Maskey@Sun.COM  * "locs" and "ncps". Each of these is a list of configuration files for each
407*11767SAnurag.Maskey@Sun.COM  * object. This corresponds to the enm.conf file, loc.conf file and list of
408*11767SAnurag.Maskey@Sun.COM  * ncp conf files. If objname is NULL, read all objects, and create
409*11767SAnurag.Maskey@Sun.COM  * an nvlist with one element - "object-list" - which has as its values
410*11767SAnurag.Maskey@Sun.COM  * the names of the objects found.  Otherwise obj points to an object list
411*11767SAnurag.Maskey@Sun.COM  * of properties for the first object in the file that case-insensitively
412*11767SAnurag.Maskey@Sun.COM  * matches objname.  We write the found name into objname so that it can be
413*11767SAnurag.Maskey@Sun.COM  * returned to the caller (and set in the object handle).
414*11767SAnurag.Maskey@Sun.COM  */
415*11767SAnurag.Maskey@Sun.COM /* ARGSUSED2 */
416*11767SAnurag.Maskey@Sun.COM nwam_error_t
417*11767SAnurag.Maskey@Sun.COM nwam_read_object_from_files_backend(char *filename, char *objname,
418*11767SAnurag.Maskey@Sun.COM     uint64_t flags, void *obj)
419*11767SAnurag.Maskey@Sun.COM {
420*11767SAnurag.Maskey@Sun.COM 	char line[NWAM_FILE_LINE_MAX];
421*11767SAnurag.Maskey@Sun.COM 	char *cp, *foundobjname, **objnames = NULL, **ncpfiles = NULL;
422*11767SAnurag.Maskey@Sun.COM 	uint_t num_files = 0;
423*11767SAnurag.Maskey@Sun.COM 	FILE *fp = NULL;
424*11767SAnurag.Maskey@Sun.COM 	nwam_error_t err;
425*11767SAnurag.Maskey@Sun.COM 	void *objlist = NULL, *proplist = NULL;
426*11767SAnurag.Maskey@Sun.COM 	uint_t i = 0, j = 0;
427*11767SAnurag.Maskey@Sun.COM 	nwam_value_t objnamesval = NULL;
428*11767SAnurag.Maskey@Sun.COM 
429*11767SAnurag.Maskey@Sun.COM 	assert(obj != NULL);
430*11767SAnurag.Maskey@Sun.COM 
431*11767SAnurag.Maskey@Sun.COM 	*((char **)obj) = NULL;
432*11767SAnurag.Maskey@Sun.COM 
433*11767SAnurag.Maskey@Sun.COM 	if (filename == NULL) {
434*11767SAnurag.Maskey@Sun.COM 		nwam_value_t enmval = NULL, locval = NULL, ncpval = NULL;
435*11767SAnurag.Maskey@Sun.COM 
436*11767SAnurag.Maskey@Sun.COM 		/*
437*11767SAnurag.Maskey@Sun.COM 		 * When the filename is not specified, it signifies a
438*11767SAnurag.Maskey@Sun.COM 		 * request for the list of configuration object containers -
439*11767SAnurag.Maskey@Sun.COM 		 * in this case files.
440*11767SAnurag.Maskey@Sun.COM 		 *
441*11767SAnurag.Maskey@Sun.COM 		 * A list of all object files is returned. For ENMs
442*11767SAnurag.Maskey@Sun.COM 		 * and locations, only the default loc.conf and enm.conf
443*11767SAnurag.Maskey@Sun.COM 		 * files are used, but for NCPs we need to walk the
444*11767SAnurag.Maskey@Sun.COM 		 * files in the NWAM directory retrieving each one that
445*11767SAnurag.Maskey@Sun.COM 		 * matches the NCP pattern.
446*11767SAnurag.Maskey@Sun.COM 		 */
447*11767SAnurag.Maskey@Sun.COM 		if ((err = nwam_alloc_object_list(&objlist)) != NWAM_SUCCESS)
448*11767SAnurag.Maskey@Sun.COM 			return (err);
449*11767SAnurag.Maskey@Sun.COM 
450*11767SAnurag.Maskey@Sun.COM 		if ((err = nwam_value_create_string(NWAM_ENM_CONF_FILE,
451*11767SAnurag.Maskey@Sun.COM 		    &enmval)) != NWAM_SUCCESS ||
452*11767SAnurag.Maskey@Sun.COM 		    (err = nwam_value_create_string(NWAM_LOC_CONF_FILE,
453*11767SAnurag.Maskey@Sun.COM 		    &locval)) != NWAM_SUCCESS ||
454*11767SAnurag.Maskey@Sun.COM 		    (err = nwam_set_prop_value(objlist, NWAM_ENM_OBJECT_STRING,
455*11767SAnurag.Maskey@Sun.COM 		    enmval)) != NWAM_SUCCESS ||
456*11767SAnurag.Maskey@Sun.COM 		    (err = nwam_set_prop_value(objlist, NWAM_LOC_OBJECT_STRING,
457*11767SAnurag.Maskey@Sun.COM 		    locval)) != NWAM_SUCCESS)
458*11767SAnurag.Maskey@Sun.COM 			goto done_with_containers;
459*11767SAnurag.Maskey@Sun.COM 
460*11767SAnurag.Maskey@Sun.COM 		/*
461*11767SAnurag.Maskey@Sun.COM 		 * Construct NCP list by finding all files in NWAM directory
462*11767SAnurag.Maskey@Sun.COM 		 * that match the NCP filename format.
463*11767SAnurag.Maskey@Sun.COM 		 */
464*11767SAnurag.Maskey@Sun.COM 		if ((err = create_ncp_file_list(&ncpfiles, &num_files))
465*11767SAnurag.Maskey@Sun.COM 		    != NWAM_SUCCESS)
466*11767SAnurag.Maskey@Sun.COM 			goto done_with_containers;
467*11767SAnurag.Maskey@Sun.COM 
468*11767SAnurag.Maskey@Sun.COM 		if ((err = nwam_value_create_string_array(ncpfiles, num_files,
469*11767SAnurag.Maskey@Sun.COM 		    &ncpval)) == NWAM_SUCCESS) {
470*11767SAnurag.Maskey@Sun.COM 			err = nwam_set_prop_value(objlist,
471*11767SAnurag.Maskey@Sun.COM 			    NWAM_NCP_OBJECT_STRING, ncpval);
472*11767SAnurag.Maskey@Sun.COM 		}
473*11767SAnurag.Maskey@Sun.COM 
474*11767SAnurag.Maskey@Sun.COM done_with_containers:
475*11767SAnurag.Maskey@Sun.COM 		nwam_value_free(enmval);
476*11767SAnurag.Maskey@Sun.COM 		nwam_value_free(locval);
477*11767SAnurag.Maskey@Sun.COM 		nwam_value_free(ncpval);
478*11767SAnurag.Maskey@Sun.COM 		if (ncpfiles != NULL) {
479*11767SAnurag.Maskey@Sun.COM 			for (j = 0; j < num_files; j++)
480*11767SAnurag.Maskey@Sun.COM 				free(ncpfiles[j]);
481*11767SAnurag.Maskey@Sun.COM 			free(ncpfiles);
482*11767SAnurag.Maskey@Sun.COM 		}
483*11767SAnurag.Maskey@Sun.COM 		if (err != NWAM_SUCCESS)
484*11767SAnurag.Maskey@Sun.COM 			nwam_free_object_list(objlist);
485*11767SAnurag.Maskey@Sun.COM 		else
486*11767SAnurag.Maskey@Sun.COM 			*((char **)obj) = objlist;
487*11767SAnurag.Maskey@Sun.COM 		return (err);
488*11767SAnurag.Maskey@Sun.COM 	}
489*11767SAnurag.Maskey@Sun.COM 
490*11767SAnurag.Maskey@Sun.COM 	if (objname == NULL) {
491*11767SAnurag.Maskey@Sun.COM 		/* Allocate string array to store object names */
492*11767SAnurag.Maskey@Sun.COM 		if ((objnames = calloc(NWAM_MAX_NUM_OBJECTS, sizeof (char *)))
493*11767SAnurag.Maskey@Sun.COM 		    == NULL)
494*11767SAnurag.Maskey@Sun.COM 			return (NWAM_NO_MEMORY);
495*11767SAnurag.Maskey@Sun.COM 	}
496*11767SAnurag.Maskey@Sun.COM 
497*11767SAnurag.Maskey@Sun.COM 	fp = fopen(filename, "r");
498*11767SAnurag.Maskey@Sun.COM 	if (fp == NULL) {
499*11767SAnurag.Maskey@Sun.COM 		if (errno != ENOENT) {
500*11767SAnurag.Maskey@Sun.COM 			if (objname == NULL)
501*11767SAnurag.Maskey@Sun.COM 				free(objnames);
502*11767SAnurag.Maskey@Sun.COM 			return (NWAM_ERROR_INTERNAL);
503*11767SAnurag.Maskey@Sun.COM 		}
504*11767SAnurag.Maskey@Sun.COM 
505*11767SAnurag.Maskey@Sun.COM 		/*
506*11767SAnurag.Maskey@Sun.COM 		 * Check NCP file list in case filename passed in was derived
507*11767SAnurag.Maskey@Sun.COM 		 * from a case-insensitive NCP name.
508*11767SAnurag.Maskey@Sun.COM 		 */
509*11767SAnurag.Maskey@Sun.COM 		if ((err = create_ncp_file_list(&ncpfiles, &num_files))
510*11767SAnurag.Maskey@Sun.COM 		    == NWAM_SUCCESS) {
511*11767SAnurag.Maskey@Sun.COM 			for (j = 0; j < num_files; j++) {
512*11767SAnurag.Maskey@Sun.COM 				if (strcasecmp(ncpfiles[j], filename) == 0) {
513*11767SAnurag.Maskey@Sun.COM 					fp = fopen(ncpfiles[j], "r");
514*11767SAnurag.Maskey@Sun.COM 					if (fp != NULL) {
515*11767SAnurag.Maskey@Sun.COM 						/* Copy real filename back */
516*11767SAnurag.Maskey@Sun.COM 						(void) strlcpy(filename,
517*11767SAnurag.Maskey@Sun.COM 						    ncpfiles[j],
518*11767SAnurag.Maskey@Sun.COM 						    strlen(filename) + 1);
519*11767SAnurag.Maskey@Sun.COM 						break;
520*11767SAnurag.Maskey@Sun.COM 					}
521*11767SAnurag.Maskey@Sun.COM 				}
522*11767SAnurag.Maskey@Sun.COM 			}
523*11767SAnurag.Maskey@Sun.COM 			for (j = 0; j < num_files; j++)
524*11767SAnurag.Maskey@Sun.COM 				free(ncpfiles[j]);
525*11767SAnurag.Maskey@Sun.COM 			free(ncpfiles);
526*11767SAnurag.Maskey@Sun.COM 		}
527*11767SAnurag.Maskey@Sun.COM 		/* Return NOT_FOUND if file not found */
528*11767SAnurag.Maskey@Sun.COM 		if (fp == NULL) {
529*11767SAnurag.Maskey@Sun.COM 			if (objname == NULL)
530*11767SAnurag.Maskey@Sun.COM 				free(objnames);
531*11767SAnurag.Maskey@Sun.COM 			return (NWAM_ENTITY_NOT_FOUND);
532*11767SAnurag.Maskey@Sun.COM 		}
533*11767SAnurag.Maskey@Sun.COM 	}
534*11767SAnurag.Maskey@Sun.COM 
535*11767SAnurag.Maskey@Sun.COM 	while (fgets(line, sizeof (line), fp) != NULL) {
536*11767SAnurag.Maskey@Sun.COM 		if (line[strlen(line) - 1] == '\n')
537*11767SAnurag.Maskey@Sun.COM 			line[strlen(line) - 1] = '\0';
538*11767SAnurag.Maskey@Sun.COM 
539*11767SAnurag.Maskey@Sun.COM 		cp = line;
540*11767SAnurag.Maskey@Sun.COM 
541*11767SAnurag.Maskey@Sun.COM 		while (isspace(*cp))
542*11767SAnurag.Maskey@Sun.COM 			cp++;
543*11767SAnurag.Maskey@Sun.COM 
544*11767SAnurag.Maskey@Sun.COM 		if (*cp == '#' || *cp == '\0')
545*11767SAnurag.Maskey@Sun.COM 			continue;
546*11767SAnurag.Maskey@Sun.COM 
547*11767SAnurag.Maskey@Sun.COM 		if ((err = nwam_line_to_object(cp, &foundobjname, &proplist))
548*11767SAnurag.Maskey@Sun.COM 		    != NWAM_SUCCESS)
549*11767SAnurag.Maskey@Sun.COM 			goto done;
550*11767SAnurag.Maskey@Sun.COM 
551*11767SAnurag.Maskey@Sun.COM 		if (objname != NULL) {
552*11767SAnurag.Maskey@Sun.COM 			/*
553*11767SAnurag.Maskey@Sun.COM 			 * Is this the specified object?  If so set objname and
554*11767SAnurag.Maskey@Sun.COM 			 * obj and bail.
555*11767SAnurag.Maskey@Sun.COM 			 */
556*11767SAnurag.Maskey@Sun.COM 			if (strcasecmp(objname, foundobjname) == 0) {
557*11767SAnurag.Maskey@Sun.COM 				*((char **)obj) = proplist;
558*11767SAnurag.Maskey@Sun.COM 				(void) strlcpy(objname, foundobjname,
559*11767SAnurag.Maskey@Sun.COM 				    NWAM_MAX_NAME_LEN);
560*11767SAnurag.Maskey@Sun.COM 				break;
561*11767SAnurag.Maskey@Sun.COM 			} else {
562*11767SAnurag.Maskey@Sun.COM 				nwam_free_object_list(proplist);
563*11767SAnurag.Maskey@Sun.COM 			}
564*11767SAnurag.Maskey@Sun.COM 		} else {
565*11767SAnurag.Maskey@Sun.COM 			objnames[i] = strdup(foundobjname);
566*11767SAnurag.Maskey@Sun.COM 			nwam_free_object_list(proplist);
567*11767SAnurag.Maskey@Sun.COM 			if (objnames[i] == NULL) {
568*11767SAnurag.Maskey@Sun.COM 				err = NWAM_NO_MEMORY;
569*11767SAnurag.Maskey@Sun.COM 				goto done;
570*11767SAnurag.Maskey@Sun.COM 			}
571*11767SAnurag.Maskey@Sun.COM 			i++;
572*11767SAnurag.Maskey@Sun.COM 		}
573*11767SAnurag.Maskey@Sun.COM 
574*11767SAnurag.Maskey@Sun.COM 	}
575*11767SAnurag.Maskey@Sun.COM 	if (objname == NULL) {
576*11767SAnurag.Maskey@Sun.COM 		/*
577*11767SAnurag.Maskey@Sun.COM 		 * Allocate object list with one value named
578*11767SAnurag.Maskey@Sun.COM 		 * NWAM_OBJECT_NAMES_STRING - it's values are the names of
579*11767SAnurag.Maskey@Sun.COM 		 * the objects found.
580*11767SAnurag.Maskey@Sun.COM 		 */
581*11767SAnurag.Maskey@Sun.COM 		if ((err = nwam_alloc_object_list(&objlist)) == NWAM_SUCCESS &&
582*11767SAnurag.Maskey@Sun.COM 		    (err = nwam_value_create_string_array(objnames, i,
583*11767SAnurag.Maskey@Sun.COM 		    &objnamesval)) == NWAM_SUCCESS) {
584*11767SAnurag.Maskey@Sun.COM 			err = nwam_set_prop_value(objlist,
585*11767SAnurag.Maskey@Sun.COM 			    NWAM_OBJECT_NAMES_STRING, objnamesval);
586*11767SAnurag.Maskey@Sun.COM 		}
587*11767SAnurag.Maskey@Sun.COM 	}
588*11767SAnurag.Maskey@Sun.COM 
589*11767SAnurag.Maskey@Sun.COM done:
590*11767SAnurag.Maskey@Sun.COM 	if (fp != NULL)
591*11767SAnurag.Maskey@Sun.COM 		(void) fclose(fp);
592*11767SAnurag.Maskey@Sun.COM 
593*11767SAnurag.Maskey@Sun.COM 	/*
594*11767SAnurag.Maskey@Sun.COM 	 * We're done, either we have success, and return our object list
595*11767SAnurag.Maskey@Sun.COM 	 * containing object names, or we have failure and we need to free
596*11767SAnurag.Maskey@Sun.COM 	 * the object list.
597*11767SAnurag.Maskey@Sun.COM 	 */
598*11767SAnurag.Maskey@Sun.COM 	if (objname == NULL) {
599*11767SAnurag.Maskey@Sun.COM 		for (j = 0; j < i; j++)
600*11767SAnurag.Maskey@Sun.COM 			free(objnames[j]);
601*11767SAnurag.Maskey@Sun.COM 		free(objnames);
602*11767SAnurag.Maskey@Sun.COM 		nwam_value_free(objnamesval);
603*11767SAnurag.Maskey@Sun.COM 		if (err == NWAM_SUCCESS) {
604*11767SAnurag.Maskey@Sun.COM 			*((char **)obj) = objlist;
605*11767SAnurag.Maskey@Sun.COM 		} else {
606*11767SAnurag.Maskey@Sun.COM 			*((char **)obj) = NULL;
607*11767SAnurag.Maskey@Sun.COM 			nwam_free_object_list(objlist);
608*11767SAnurag.Maskey@Sun.COM 		}
609*11767SAnurag.Maskey@Sun.COM 	} else {
610*11767SAnurag.Maskey@Sun.COM 		/* Check if to-be-read object was not found */
611*11767SAnurag.Maskey@Sun.COM 		if (*((char **)obj) == NULL && err == NWAM_SUCCESS)
612*11767SAnurag.Maskey@Sun.COM 			return (NWAM_ENTITY_NOT_FOUND);
613*11767SAnurag.Maskey@Sun.COM 	}
614*11767SAnurag.Maskey@Sun.COM 
615*11767SAnurag.Maskey@Sun.COM 	return (err);
616*11767SAnurag.Maskey@Sun.COM }
617*11767SAnurag.Maskey@Sun.COM 
618*11767SAnurag.Maskey@Sun.COM nwam_error_t
619*11767SAnurag.Maskey@Sun.COM nwam_object_to_line(FILE *fp, const char *objname, void *proplist)
620*11767SAnurag.Maskey@Sun.COM {
621*11767SAnurag.Maskey@Sun.COM 	char *propname, *lastpropname = NULL;
622*11767SAnurag.Maskey@Sun.COM 	boolean_t *valbool;
623*11767SAnurag.Maskey@Sun.COM 	int64_t *valint;
624*11767SAnurag.Maskey@Sun.COM 	uint64_t *valuint;
625*11767SAnurag.Maskey@Sun.COM 	char **valstr;
626*11767SAnurag.Maskey@Sun.COM 	uint_t nelem, i;
627*11767SAnurag.Maskey@Sun.COM 	nwam_value_t val;
628*11767SAnurag.Maskey@Sun.COM 	nwam_value_type_t type;
629*11767SAnurag.Maskey@Sun.COM 
630*11767SAnurag.Maskey@Sun.COM 	(void) fprintf(fp, "%s\t", objname);
631*11767SAnurag.Maskey@Sun.COM 
632*11767SAnurag.Maskey@Sun.COM 	while (nwam_next_object_prop(proplist, lastpropname, &propname, &val)
633*11767SAnurag.Maskey@Sun.COM 	    == NWAM_SUCCESS) {
634*11767SAnurag.Maskey@Sun.COM 
635*11767SAnurag.Maskey@Sun.COM 		(void) fprintf(fp, "%s%c", propname, NWAM_FILE_PROP_ASSIGN);
636*11767SAnurag.Maskey@Sun.COM 
637*11767SAnurag.Maskey@Sun.COM 		if (nwam_value_get_type(val, &type) != NWAM_SUCCESS)
638*11767SAnurag.Maskey@Sun.COM 			return (NWAM_INVALID_ARG);
639*11767SAnurag.Maskey@Sun.COM 
640*11767SAnurag.Maskey@Sun.COM 		switch (type) {
641*11767SAnurag.Maskey@Sun.COM 		case NWAM_VALUE_TYPE_BOOLEAN:
642*11767SAnurag.Maskey@Sun.COM 			(void) fprintf(fp, "%s",
643*11767SAnurag.Maskey@Sun.COM 			    nwam_value_type_to_string(NWAM_VALUE_TYPE_BOOLEAN));
644*11767SAnurag.Maskey@Sun.COM 			if (nwam_value_get_boolean_array(val, &valbool, &nelem)
645*11767SAnurag.Maskey@Sun.COM 			    != NWAM_SUCCESS) {
646*11767SAnurag.Maskey@Sun.COM 				nwam_value_free(val);
647*11767SAnurag.Maskey@Sun.COM 				return (NWAM_INVALID_ARG);
648*11767SAnurag.Maskey@Sun.COM 			}
649*11767SAnurag.Maskey@Sun.COM 			for (i = 0; i < nelem; i++) {
650*11767SAnurag.Maskey@Sun.COM 				(void) fprintf(fp, "%c",
651*11767SAnurag.Maskey@Sun.COM 				    NWAM_FILE_VALUE_DELIMITER);
652*11767SAnurag.Maskey@Sun.COM 				if (valbool[i]) {
653*11767SAnurag.Maskey@Sun.COM 					(void) fprintf(fp,
654*11767SAnurag.Maskey@Sun.COM 					    NWAM_FILE_BOOLEAN_TRUE);
655*11767SAnurag.Maskey@Sun.COM 				} else {
656*11767SAnurag.Maskey@Sun.COM 					(void) fprintf(fp,
657*11767SAnurag.Maskey@Sun.COM 					    NWAM_FILE_BOOLEAN_FALSE);
658*11767SAnurag.Maskey@Sun.COM 				}
659*11767SAnurag.Maskey@Sun.COM 			}
660*11767SAnurag.Maskey@Sun.COM 			break;
661*11767SAnurag.Maskey@Sun.COM 
662*11767SAnurag.Maskey@Sun.COM 		case NWAM_VALUE_TYPE_INT64:
663*11767SAnurag.Maskey@Sun.COM 			(void) fprintf(fp, "%s",
664*11767SAnurag.Maskey@Sun.COM 			    nwam_value_type_to_string(NWAM_VALUE_TYPE_INT64));
665*11767SAnurag.Maskey@Sun.COM 			if (nwam_value_get_int64_array(val, &valint, &nelem)
666*11767SAnurag.Maskey@Sun.COM 			    != NWAM_SUCCESS) {
667*11767SAnurag.Maskey@Sun.COM 				nwam_value_free(val);
668*11767SAnurag.Maskey@Sun.COM 				return (NWAM_INVALID_ARG);
669*11767SAnurag.Maskey@Sun.COM 			}
670*11767SAnurag.Maskey@Sun.COM 			for (i = 0; i < nelem; i++) {
671*11767SAnurag.Maskey@Sun.COM 				(void) fprintf(fp, "%c%lld",
672*11767SAnurag.Maskey@Sun.COM 				    NWAM_FILE_VALUE_DELIMITER, valint[i]);
673*11767SAnurag.Maskey@Sun.COM 			}
674*11767SAnurag.Maskey@Sun.COM 			break;
675*11767SAnurag.Maskey@Sun.COM 
676*11767SAnurag.Maskey@Sun.COM 		case NWAM_VALUE_TYPE_UINT64:
677*11767SAnurag.Maskey@Sun.COM 			(void) fprintf(fp, "%s",
678*11767SAnurag.Maskey@Sun.COM 			    nwam_value_type_to_string(NWAM_VALUE_TYPE_UINT64));
679*11767SAnurag.Maskey@Sun.COM 			if (nwam_value_get_uint64_array(val, &valuint, &nelem)
680*11767SAnurag.Maskey@Sun.COM 			    != NWAM_SUCCESS) {
681*11767SAnurag.Maskey@Sun.COM 				nwam_value_free(val);
682*11767SAnurag.Maskey@Sun.COM 				return (NWAM_INVALID_ARG);
683*11767SAnurag.Maskey@Sun.COM 			}
684*11767SAnurag.Maskey@Sun.COM 			for (i = 0; i < nelem; i++) {
685*11767SAnurag.Maskey@Sun.COM 				(void) fprintf(fp, "%c%lld",
686*11767SAnurag.Maskey@Sun.COM 				    NWAM_FILE_VALUE_DELIMITER, valuint[i]);
687*11767SAnurag.Maskey@Sun.COM 			}
688*11767SAnurag.Maskey@Sun.COM 			break;
689*11767SAnurag.Maskey@Sun.COM 
690*11767SAnurag.Maskey@Sun.COM 		case NWAM_VALUE_TYPE_STRING:
691*11767SAnurag.Maskey@Sun.COM 			(void) fprintf(fp, "%s",
692*11767SAnurag.Maskey@Sun.COM 			    nwam_value_type_to_string(NWAM_VALUE_TYPE_STRING));
693*11767SAnurag.Maskey@Sun.COM 			if (nwam_value_get_string_array(val, &valstr, &nelem)
694*11767SAnurag.Maskey@Sun.COM 			    != NWAM_SUCCESS) {
695*11767SAnurag.Maskey@Sun.COM 				nwam_value_free(val);
696*11767SAnurag.Maskey@Sun.COM 				return (NWAM_INVALID_ARG);
697*11767SAnurag.Maskey@Sun.COM 			}
698*11767SAnurag.Maskey@Sun.COM 			for (i = 0; i < nelem; i++) {
699*11767SAnurag.Maskey@Sun.COM 				char evalstr[NWAM_MAX_VALUE_LEN];
700*11767SAnurag.Maskey@Sun.COM 				/* Add escape chars as necessary */
701*11767SAnurag.Maskey@Sun.COM 				value_add_escapes(valstr[i], evalstr);
702*11767SAnurag.Maskey@Sun.COM 				(void) fprintf(fp, "%c%s",
703*11767SAnurag.Maskey@Sun.COM 				    NWAM_FILE_VALUE_DELIMITER, evalstr);
704*11767SAnurag.Maskey@Sun.COM 			}
705*11767SAnurag.Maskey@Sun.COM 			break;
706*11767SAnurag.Maskey@Sun.COM 		default:
707*11767SAnurag.Maskey@Sun.COM 			nwam_value_free(val);
708*11767SAnurag.Maskey@Sun.COM 			return (NWAM_INVALID_ARG);
709*11767SAnurag.Maskey@Sun.COM 		}
710*11767SAnurag.Maskey@Sun.COM 		nwam_value_free(val);
711*11767SAnurag.Maskey@Sun.COM 		(void) fprintf(fp, "%c", NWAM_FILE_PROP_DELIMITER);
712*11767SAnurag.Maskey@Sun.COM 
713*11767SAnurag.Maskey@Sun.COM 		lastpropname = propname;
714*11767SAnurag.Maskey@Sun.COM 
715*11767SAnurag.Maskey@Sun.COM 	}
716*11767SAnurag.Maskey@Sun.COM 	(void) fprintf(fp, "\n");
717*11767SAnurag.Maskey@Sun.COM 	return (NWAM_SUCCESS);
718*11767SAnurag.Maskey@Sun.COM }
719*11767SAnurag.Maskey@Sun.COM 
720*11767SAnurag.Maskey@Sun.COM /*
721*11767SAnurag.Maskey@Sun.COM  * Write object specified by objname to file.  If objname is NULL, objlist
722*11767SAnurag.Maskey@Sun.COM  * must be a list of lists, where each list corresponds to an
723*11767SAnurag.Maskey@Sun.COM  * object to write to the file.  Otherwise objlist should point to a list of
724*11767SAnurag.Maskey@Sun.COM  * properties for the object specified by objname.  The write operation is
725*11767SAnurag.Maskey@Sun.COM  * first done to filename.new, and if this succeeds, the file is renamed to
726*11767SAnurag.Maskey@Sun.COM  * filename.  Since rename(2) is atomic, this approach guarantees a complete
727*11767SAnurag.Maskey@Sun.COM  * configuration will end up in filename as a result of an aborted operation.
728*11767SAnurag.Maskey@Sun.COM  */
729*11767SAnurag.Maskey@Sun.COM nwam_error_t
730*11767SAnurag.Maskey@Sun.COM nwam_write_object_to_files_backend(const char *filename, const char *objname,
731*11767SAnurag.Maskey@Sun.COM     uint64_t flags, void *objlist)
732*11767SAnurag.Maskey@Sun.COM {
733*11767SAnurag.Maskey@Sun.COM 	void *proplist;
734*11767SAnurag.Maskey@Sun.COM 	char *currobjname, *lastobjname = NULL;
735*11767SAnurag.Maskey@Sun.COM 	int fd, cmd;
736*11767SAnurag.Maskey@Sun.COM 	nwam_error_t err = NWAM_SUCCESS;
737*11767SAnurag.Maskey@Sun.COM 	char *dir;
738*11767SAnurag.Maskey@Sun.COM 	char tmpfilename[MAXPATHLEN], filename_copy[MAXPATHLEN];
739*11767SAnurag.Maskey@Sun.COM 	FILE *fp;
740*11767SAnurag.Maskey@Sun.COM 	mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
741*11767SAnurag.Maskey@Sun.COM 	mode_t dirmode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
742*11767SAnurag.Maskey@Sun.COM 	struct flock fl = { F_WRLCK, SEEK_SET, 0, 0, 0};
743*11767SAnurag.Maskey@Sun.COM 	struct flock fu = { F_UNLCK, SEEK_SET, 0, 0, 0};
744*11767SAnurag.Maskey@Sun.COM 
745*11767SAnurag.Maskey@Sun.COM 	assert(filename != NULL);
746*11767SAnurag.Maskey@Sun.COM 
747*11767SAnurag.Maskey@Sun.COM 	/* Create the directory in case it does not exist. */
748*11767SAnurag.Maskey@Sun.COM 	(void) strlcpy(filename_copy, filename, MAXPATHLEN);
749*11767SAnurag.Maskey@Sun.COM 	if ((dir = dirname(filename_copy)) == NULL)
750*11767SAnurag.Maskey@Sun.COM 		return (nwam_errno_to_nwam_error(errno));
751*11767SAnurag.Maskey@Sun.COM 	if (mkdir(dir, dirmode) != 0) {
752*11767SAnurag.Maskey@Sun.COM 		if (errno != EEXIST)
753*11767SAnurag.Maskey@Sun.COM 			return (nwam_errno_to_nwam_error(errno));
754*11767SAnurag.Maskey@Sun.COM 	}
755*11767SAnurag.Maskey@Sun.COM 
756*11767SAnurag.Maskey@Sun.COM 	(void) snprintf(tmpfilename, MAXPATHLEN, "%s.new", filename);
757*11767SAnurag.Maskey@Sun.COM 
758*11767SAnurag.Maskey@Sun.COM 	if ((fd = open(tmpfilename, O_RDWR | O_CREAT | O_TRUNC, mode)) < 0)
759*11767SAnurag.Maskey@Sun.COM 			return (nwam_errno_to_nwam_error(errno));
760*11767SAnurag.Maskey@Sun.COM 
761*11767SAnurag.Maskey@Sun.COM 	if ((fp = fdopen(fd, "w")) == NULL) {
762*11767SAnurag.Maskey@Sun.COM 		err = nwam_errno_to_nwam_error(errno);
763*11767SAnurag.Maskey@Sun.COM 		goto done;
764*11767SAnurag.Maskey@Sun.COM 	}
765*11767SAnurag.Maskey@Sun.COM 	/*
766*11767SAnurag.Maskey@Sun.COM 	 * Need to lock filename.new to prevent multiple commits colliding
767*11767SAnurag.Maskey@Sun.COM 	 * at this point.
768*11767SAnurag.Maskey@Sun.COM 	 */
769*11767SAnurag.Maskey@Sun.COM 	if (flags & NWAM_FLAG_BLOCKING)
770*11767SAnurag.Maskey@Sun.COM 		cmd = F_SETLKW;
771*11767SAnurag.Maskey@Sun.COM 	else
772*11767SAnurag.Maskey@Sun.COM 		cmd = F_SETLK;
773*11767SAnurag.Maskey@Sun.COM 	if (fcntl(fd, cmd, &fl) != 0) {
774*11767SAnurag.Maskey@Sun.COM 		if (errno == EAGAIN)
775*11767SAnurag.Maskey@Sun.COM 			return (NWAM_ENTITY_IN_USE);
776*11767SAnurag.Maskey@Sun.COM 		else
777*11767SAnurag.Maskey@Sun.COM 			return (NWAM_ERROR_INTERNAL);
778*11767SAnurag.Maskey@Sun.COM 	}
779*11767SAnurag.Maskey@Sun.COM 
780*11767SAnurag.Maskey@Sun.COM 	if (objname != NULL) {
781*11767SAnurag.Maskey@Sun.COM 		/* Only one object to write */
782*11767SAnurag.Maskey@Sun.COM 		err = nwam_object_to_line(fp, objname, objlist);
783*11767SAnurag.Maskey@Sun.COM 	} else {
784*11767SAnurag.Maskey@Sun.COM 		if (objlist == NULL) {
785*11767SAnurag.Maskey@Sun.COM 			err = NWAM_SUCCESS;
786*11767SAnurag.Maskey@Sun.COM 			goto done;
787*11767SAnurag.Maskey@Sun.COM 		}
788*11767SAnurag.Maskey@Sun.COM 		/* Otherwise, write each object in turn. */
789*11767SAnurag.Maskey@Sun.COM 		while ((err = nwam_next_object_list(objlist, lastobjname,
790*11767SAnurag.Maskey@Sun.COM 		    &currobjname, &proplist)) == NWAM_SUCCESS) {
791*11767SAnurag.Maskey@Sun.COM 			if ((err = nwam_object_to_line(fp, currobjname,
792*11767SAnurag.Maskey@Sun.COM 			    proplist)) != NWAM_SUCCESS)
793*11767SAnurag.Maskey@Sun.COM 				break;
794*11767SAnurag.Maskey@Sun.COM 			lastobjname = currobjname;
795*11767SAnurag.Maskey@Sun.COM 		}
796*11767SAnurag.Maskey@Sun.COM 		if (err == NWAM_LIST_END)
797*11767SAnurag.Maskey@Sun.COM 			err = NWAM_SUCCESS;
798*11767SAnurag.Maskey@Sun.COM 	}
799*11767SAnurag.Maskey@Sun.COM done:
800*11767SAnurag.Maskey@Sun.COM 	if (err == NWAM_SUCCESS) {
801*11767SAnurag.Maskey@Sun.COM 		if (rename(tmpfilename, filename) == 0) {
802*11767SAnurag.Maskey@Sun.COM 			(void) fcntl(fd, F_SETLKW, &fu);
803*11767SAnurag.Maskey@Sun.COM 			(void) fclose(fp);
804*11767SAnurag.Maskey@Sun.COM 			return (NWAM_SUCCESS);
805*11767SAnurag.Maskey@Sun.COM 		} else {
806*11767SAnurag.Maskey@Sun.COM 			err = nwam_errno_to_nwam_error(errno);
807*11767SAnurag.Maskey@Sun.COM 		}
808*11767SAnurag.Maskey@Sun.COM 	}
809*11767SAnurag.Maskey@Sun.COM 	(void) fcntl(fd, F_SETLKW, &fu);
810*11767SAnurag.Maskey@Sun.COM 	(void) fclose(fp);
811*11767SAnurag.Maskey@Sun.COM 	(void) unlink(tmpfilename);
812*11767SAnurag.Maskey@Sun.COM 
813*11767SAnurag.Maskey@Sun.COM 	return (err);
814*11767SAnurag.Maskey@Sun.COM }
815*11767SAnurag.Maskey@Sun.COM 
816*11767SAnurag.Maskey@Sun.COM /*
817*11767SAnurag.Maskey@Sun.COM  * Read in all objects from file and update object corresponding to objname
818*11767SAnurag.Maskey@Sun.COM  * with properties recorded in proplist, and then write results to filename.
819*11767SAnurag.Maskey@Sun.COM  * If objname is empty, no object needs to be updated.  If proplist is NULL,
820*11767SAnurag.Maskey@Sun.COM  * object is to be removed (this is done by simply not adding it to the list
821*11767SAnurag.Maskey@Sun.COM  * of objects).
822*11767SAnurag.Maskey@Sun.COM  */
823*11767SAnurag.Maskey@Sun.COM nwam_error_t
824*11767SAnurag.Maskey@Sun.COM nwam_update_object_in_files_backend(char *filename, char *objname,
825*11767SAnurag.Maskey@Sun.COM     uint64_t flags, void *proplist)
826*11767SAnurag.Maskey@Sun.COM {
827*11767SAnurag.Maskey@Sun.COM 	nwam_error_t err;
828*11767SAnurag.Maskey@Sun.COM 	void *objlist, *objnamelist;
829*11767SAnurag.Maskey@Sun.COM 	char **object_names;
830*11767SAnurag.Maskey@Sun.COM 	nwam_value_t value = NULL;
831*11767SAnurag.Maskey@Sun.COM 	uint_t i, num_objects;
832*11767SAnurag.Maskey@Sun.COM 
833*11767SAnurag.Maskey@Sun.COM 	assert(filename != NULL);
834*11767SAnurag.Maskey@Sun.COM 
835*11767SAnurag.Maskey@Sun.COM 	/*  If we find existing object, fail if creation was specified */
836*11767SAnurag.Maskey@Sun.COM 	if (flags & NWAM_FLAG_CREATE) {
837*11767SAnurag.Maskey@Sun.COM 		char discard_objname[NWAM_MAX_NAME_LEN];
838*11767SAnurag.Maskey@Sun.COM 		void *discard_objlist;
839*11767SAnurag.Maskey@Sun.COM 
840*11767SAnurag.Maskey@Sun.COM 		(void) strlcpy(discard_objname, objname,
841*11767SAnurag.Maskey@Sun.COM 		    sizeof (discard_objname));
842*11767SAnurag.Maskey@Sun.COM 		if ((err = nwam_read_object_from_files_backend(filename,
843*11767SAnurag.Maskey@Sun.COM 		    discard_objname, 0, &discard_objlist)) == NWAM_SUCCESS) {
844*11767SAnurag.Maskey@Sun.COM 			nwam_free_object_list(discard_objlist);
845*11767SAnurag.Maskey@Sun.COM 			return (NWAM_ENTITY_EXISTS);
846*11767SAnurag.Maskey@Sun.COM 		}
847*11767SAnurag.Maskey@Sun.COM 	}
848*11767SAnurag.Maskey@Sun.COM 
849*11767SAnurag.Maskey@Sun.COM 	/* Get existing list of object names (if any) */
850*11767SAnurag.Maskey@Sun.COM 	err = nwam_read_object_from_files_backend(filename, NULL, flags,
851*11767SAnurag.Maskey@Sun.COM 	    &objnamelist);
852*11767SAnurag.Maskey@Sun.COM 	switch (err) {
853*11767SAnurag.Maskey@Sun.COM 	case NWAM_SUCCESS:
854*11767SAnurag.Maskey@Sun.COM 		/*
855*11767SAnurag.Maskey@Sun.COM 		 * For each object name on list other than the one to be
856*11767SAnurag.Maskey@Sun.COM 		 * updated,  add an object list consisting of its properties.
857*11767SAnurag.Maskey@Sun.COM 		 * The object to be updated (if any) will be added below.
858*11767SAnurag.Maskey@Sun.COM 		 */
859*11767SAnurag.Maskey@Sun.COM 		if ((err = nwam_alloc_object_list(&objlist)) != NWAM_SUCCESS) {
860*11767SAnurag.Maskey@Sun.COM 			nwam_free_object_list(objnamelist);
861*11767SAnurag.Maskey@Sun.COM 			return (err);
862*11767SAnurag.Maskey@Sun.COM 		}
863*11767SAnurag.Maskey@Sun.COM 		if ((err = nwam_get_prop_value(objnamelist,
864*11767SAnurag.Maskey@Sun.COM 		    NWAM_OBJECT_NAMES_STRING, &value)) != NWAM_SUCCESS ||
865*11767SAnurag.Maskey@Sun.COM 		    (err = nwam_value_get_string_array(value, &object_names,
866*11767SAnurag.Maskey@Sun.COM 		    &num_objects)) != NWAM_SUCCESS) {
867*11767SAnurag.Maskey@Sun.COM 			nwam_value_free(value);
868*11767SAnurag.Maskey@Sun.COM 			nwam_free_object_list(objnamelist);
869*11767SAnurag.Maskey@Sun.COM 			nwam_free_object_list(objlist);
870*11767SAnurag.Maskey@Sun.COM 			return (err);
871*11767SAnurag.Maskey@Sun.COM 		}
872*11767SAnurag.Maskey@Sun.COM 		nwam_free_object_list(objnamelist);
873*11767SAnurag.Maskey@Sun.COM 
874*11767SAnurag.Maskey@Sun.COM 		for (i = 0; i < num_objects; i++) {
875*11767SAnurag.Maskey@Sun.COM 			void *oproplist = NULL;
876*11767SAnurag.Maskey@Sun.COM 
877*11767SAnurag.Maskey@Sun.COM 			if (objname != NULL &&
878*11767SAnurag.Maskey@Sun.COM 			    strcmp(objname, object_names[i]) == 0)
879*11767SAnurag.Maskey@Sun.COM 					continue;
880*11767SAnurag.Maskey@Sun.COM 
881*11767SAnurag.Maskey@Sun.COM 			if ((err = nwam_read_object_from_files_backend(filename,
882*11767SAnurag.Maskey@Sun.COM 			    object_names[i], flags, &oproplist))
883*11767SAnurag.Maskey@Sun.COM 			    != NWAM_SUCCESS ||
884*11767SAnurag.Maskey@Sun.COM 			    (err = nwam_object_list_add_object_list(objlist,
885*11767SAnurag.Maskey@Sun.COM 			    object_names[i], oproplist)) != NWAM_SUCCESS) {
886*11767SAnurag.Maskey@Sun.COM 				nwam_free_object_list(oproplist);
887*11767SAnurag.Maskey@Sun.COM 				nwam_free_object_list(objlist);
888*11767SAnurag.Maskey@Sun.COM 				nwam_value_free(value);
889*11767SAnurag.Maskey@Sun.COM 				return (err);
890*11767SAnurag.Maskey@Sun.COM 			}
891*11767SAnurag.Maskey@Sun.COM 			nwam_free_object_list(oproplist);
892*11767SAnurag.Maskey@Sun.COM 		}
893*11767SAnurag.Maskey@Sun.COM 		nwam_value_free(value);
894*11767SAnurag.Maskey@Sun.COM 		break;
895*11767SAnurag.Maskey@Sun.COM 
896*11767SAnurag.Maskey@Sun.COM 	case NWAM_ENTITY_NOT_FOUND:
897*11767SAnurag.Maskey@Sun.COM 		/*
898*11767SAnurag.Maskey@Sun.COM 		 * Just need to write/remove this single object.
899*11767SAnurag.Maskey@Sun.COM 		 */
900*11767SAnurag.Maskey@Sun.COM 		return (nwam_write_object_to_files_backend(filename, objname,
901*11767SAnurag.Maskey@Sun.COM 		    flags, proplist));
902*11767SAnurag.Maskey@Sun.COM 
903*11767SAnurag.Maskey@Sun.COM 	default:
904*11767SAnurag.Maskey@Sun.COM 		return (err);
905*11767SAnurag.Maskey@Sun.COM 	}
906*11767SAnurag.Maskey@Sun.COM 
907*11767SAnurag.Maskey@Sun.COM 	/*
908*11767SAnurag.Maskey@Sun.COM 	 * Add the object to be updated to our list of objects if the
909*11767SAnurag.Maskey@Sun.COM 	 * property list is non-NULL (NULL signifies remove the object).
910*11767SAnurag.Maskey@Sun.COM 	 */
911*11767SAnurag.Maskey@Sun.COM 	if (objname != NULL && proplist != NULL) {
912*11767SAnurag.Maskey@Sun.COM 		if ((err = nwam_object_list_add_object_list(objlist,
913*11767SAnurag.Maskey@Sun.COM 		    (char *)objname, proplist)) != NWAM_SUCCESS) {
914*11767SAnurag.Maskey@Sun.COM 			nwam_free_object_list(objlist);
915*11767SAnurag.Maskey@Sun.COM 			return (err);
916*11767SAnurag.Maskey@Sun.COM 		}
917*11767SAnurag.Maskey@Sun.COM 	}
918*11767SAnurag.Maskey@Sun.COM 
919*11767SAnurag.Maskey@Sun.COM 	err = nwam_write_object_to_files_backend(filename, NULL, flags,
920*11767SAnurag.Maskey@Sun.COM 	    objlist);
921*11767SAnurag.Maskey@Sun.COM 
922*11767SAnurag.Maskey@Sun.COM 	nwam_free_object_list(objlist);
923*11767SAnurag.Maskey@Sun.COM 
924*11767SAnurag.Maskey@Sun.COM 	return (err);
925*11767SAnurag.Maskey@Sun.COM }
926*11767SAnurag.Maskey@Sun.COM 
927*11767SAnurag.Maskey@Sun.COM /*
928*11767SAnurag.Maskey@Sun.COM  * Remove specified object from file by reading in the list of objects,
929*11767SAnurag.Maskey@Sun.COM  * removing objname and writing the remainder.
930*11767SAnurag.Maskey@Sun.COM  */
931*11767SAnurag.Maskey@Sun.COM nwam_error_t
932*11767SAnurag.Maskey@Sun.COM nwam_remove_object_from_files_backend(char *filename, char *objname,
933*11767SAnurag.Maskey@Sun.COM     uint64_t flags)
934*11767SAnurag.Maskey@Sun.COM {
935*11767SAnurag.Maskey@Sun.COM 	int uerr;
936*11767SAnurag.Maskey@Sun.COM 
937*11767SAnurag.Maskey@Sun.COM 	assert(filename != NULL);
938*11767SAnurag.Maskey@Sun.COM 
939*11767SAnurag.Maskey@Sun.COM 	if (objname == NULL) {
940*11767SAnurag.Maskey@Sun.COM 		/*
941*11767SAnurag.Maskey@Sun.COM 		 * NULL objname signifies remove file.
942*11767SAnurag.Maskey@Sun.COM 		 */
943*11767SAnurag.Maskey@Sun.COM 		uerr = unlink(filename);
944*11767SAnurag.Maskey@Sun.COM 		if (uerr != 0)
945*11767SAnurag.Maskey@Sun.COM 			return (nwam_errno_to_nwam_error(errno));
946*11767SAnurag.Maskey@Sun.COM 		return (NWAM_SUCCESS);
947*11767SAnurag.Maskey@Sun.COM 	}
948*11767SAnurag.Maskey@Sun.COM 
949*11767SAnurag.Maskey@Sun.COM 	return (nwam_update_object_in_files_backend(filename, objname, flags,
950*11767SAnurag.Maskey@Sun.COM 	    NULL));
951*11767SAnurag.Maskey@Sun.COM }
952