16ba597c5SAnurag S. Maskey /*
26ba597c5SAnurag S. Maskey * CDDL HEADER START
36ba597c5SAnurag S. Maskey *
46ba597c5SAnurag S. Maskey * The contents of this file are subject to the terms of the
56ba597c5SAnurag S. Maskey * Common Development and Distribution License (the "License").
66ba597c5SAnurag S. Maskey * You may not use this file except in compliance with the License.
76ba597c5SAnurag S. Maskey *
86ba597c5SAnurag S. Maskey * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96ba597c5SAnurag S. Maskey * or http://www.opensolaris.org/os/licensing.
106ba597c5SAnurag S. Maskey * See the License for the specific language governing permissions
116ba597c5SAnurag S. Maskey * and limitations under the License.
126ba597c5SAnurag S. Maskey *
136ba597c5SAnurag S. Maskey * When distributing Covered Code, include this CDDL HEADER in each
146ba597c5SAnurag S. Maskey * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156ba597c5SAnurag S. Maskey * If applicable, add the following below this CDDL HEADER, with the
166ba597c5SAnurag S. Maskey * fields enclosed by brackets "[]" replaced with your own identifying
176ba597c5SAnurag S. Maskey * information: Portions Copyright [yyyy] [name of copyright owner]
186ba597c5SAnurag S. Maskey *
196ba597c5SAnurag S. Maskey * CDDL HEADER END
206ba597c5SAnurag S. Maskey */
216ba597c5SAnurag S. Maskey
226ba597c5SAnurag S. Maskey /*
236ba597c5SAnurag S. Maskey * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
246ba597c5SAnurag S. Maskey * Use is subject to license terms.
256ba597c5SAnurag S. Maskey */
266ba597c5SAnurag S. Maskey
276ba597c5SAnurag S. Maskey #include <assert.h>
286ba597c5SAnurag S. Maskey #include <dirent.h>
296ba597c5SAnurag S. Maskey #include <ctype.h>
306ba597c5SAnurag S. Maskey #include <libgen.h>
316ba597c5SAnurag S. Maskey #include <errno.h>
326ba597c5SAnurag S. Maskey #include <fcntl.h>
336ba597c5SAnurag S. Maskey #include <sys/param.h>
346ba597c5SAnurag S. Maskey #include <sys/types.h>
356ba597c5SAnurag S. Maskey #include <sys/stat.h>
366ba597c5SAnurag S. Maskey #include <stdio.h>
376ba597c5SAnurag S. Maskey #include <stdlib.h>
386ba597c5SAnurag S. Maskey #include <strings.h>
396ba597c5SAnurag S. Maskey #include <unistd.h>
406ba597c5SAnurag S. Maskey
416ba597c5SAnurag S. Maskey #include "libnwam_impl.h"
426ba597c5SAnurag S. Maskey #include <libnwam_priv.h>
436ba597c5SAnurag S. Maskey #include <libnwam.h>
446ba597c5SAnurag S. Maskey
456ba597c5SAnurag S. Maskey /*
466ba597c5SAnurag S. Maskey * Implementation of files backend for libnwam configuration objects.
476ba597c5SAnurag S. Maskey * /etc/dladm/datalink.conf-like format is used.
486ba597c5SAnurag S. Maskey */
496ba597c5SAnurag S. Maskey #define NWAM_FILE_LINE_MAX 2048
506ba597c5SAnurag S. Maskey #define NWAM_FILE_PROP_ESCAPE '\\'
516ba597c5SAnurag S. Maskey #define NWAM_FILE_PROP_DELIMITER ';'
526ba597c5SAnurag S. Maskey #define NWAM_FILE_PROP_ASSIGN '='
536ba597c5SAnurag S. Maskey #define NWAM_FILE_VALUE_DELIMITER ','
546ba597c5SAnurag S. Maskey #define NWAM_FILE_BOOLEAN_TRUE "true"
556ba597c5SAnurag S. Maskey #define NWAM_FILE_BOOLEAN_FALSE "false"
566ba597c5SAnurag S. Maskey
576ba597c5SAnurag S. Maskey /*
586ba597c5SAnurag S. Maskey * strtok_r-like function that takes a string, finds the next unescaped
596ba597c5SAnurag S. Maskey * delimiter char after in, nullifies it and sets nextp to point to the
606ba597c5SAnurag S. Maskey * remaining string (if any). Returns in, setting nextp to NULL if no such
616ba597c5SAnurag S. Maskey * delimiter is found.
626ba597c5SAnurag S. Maskey */
636ba597c5SAnurag S. Maskey char *
nwam_tokenize_by_unescaped_delim(char * in,char delim,char ** nextp)646ba597c5SAnurag S. Maskey nwam_tokenize_by_unescaped_delim(char *in, char delim, char **nextp)
656ba597c5SAnurag S. Maskey {
666ba597c5SAnurag S. Maskey boolean_t escaped = B_FALSE;
676ba597c5SAnurag S. Maskey size_t totlen;
686ba597c5SAnurag S. Maskey
696ba597c5SAnurag S. Maskey if (in == NULL)
706ba597c5SAnurag S. Maskey return (NULL);
716ba597c5SAnurag S. Maskey
726ba597c5SAnurag S. Maskey totlen = strlen(in);
736ba597c5SAnurag S. Maskey
746ba597c5SAnurag S. Maskey for (*nextp = in; (*nextp - in) < strlen(in); (*nextp)++) {
756ba597c5SAnurag S. Maskey if ((*nextp)[0] == NWAM_FILE_PROP_ESCAPE) {
766ba597c5SAnurag S. Maskey escaped = !escaped;
776ba597c5SAnurag S. Maskey } else if (!escaped && (*nextp)[0] == delim) {
786ba597c5SAnurag S. Maskey /* Nullify delimiter */
796ba597c5SAnurag S. Maskey (*nextp)[0] = '\0';
806ba597c5SAnurag S. Maskey /*
816ba597c5SAnurag S. Maskey * If more string left to go, nextp points to string
826ba597c5SAnurag S. Maskey * after delimiter, otherwise NULL.
836ba597c5SAnurag S. Maskey */
846ba597c5SAnurag S. Maskey (*nextp)++;
856ba597c5SAnurag S. Maskey *nextp = ((*nextp - in) < totlen) ? (*nextp) : NULL;
866ba597c5SAnurag S. Maskey return (in);
876ba597c5SAnurag S. Maskey } else {
886ba597c5SAnurag S. Maskey escaped = B_FALSE;
896ba597c5SAnurag S. Maskey }
906ba597c5SAnurag S. Maskey }
916ba597c5SAnurag S. Maskey *nextp = NULL;
926ba597c5SAnurag S. Maskey return (in);
936ba597c5SAnurag S. Maskey }
946ba597c5SAnurag S. Maskey
956ba597c5SAnurag S. Maskey /* Add escape chars to value string */
966ba597c5SAnurag S. Maskey static void
value_add_escapes(char * in,char * out)976ba597c5SAnurag S. Maskey value_add_escapes(char *in, char *out)
986ba597c5SAnurag S. Maskey {
996ba597c5SAnurag S. Maskey int i, j = 0;
1006ba597c5SAnurag S. Maskey
1016ba597c5SAnurag S. Maskey /*
1026ba597c5SAnurag S. Maskey * It is safe to use strlen() as we sanitycheck string length on value
1036ba597c5SAnurag S. Maskey * creation, so no string longer than NWAM_MAX_VALUE_LEN is accepted.
1046ba597c5SAnurag S. Maskey */
1056ba597c5SAnurag S. Maskey for (i = 0; i < strlen(in); i++) {
1066ba597c5SAnurag S. Maskey switch (in[i]) {
1076ba597c5SAnurag S. Maskey case NWAM_FILE_VALUE_DELIMITER:
1086ba597c5SAnurag S. Maskey case NWAM_FILE_PROP_DELIMITER:
1096ba597c5SAnurag S. Maskey case NWAM_FILE_PROP_ESCAPE:
1106ba597c5SAnurag S. Maskey out[j++] = NWAM_FILE_PROP_ESCAPE;
1116ba597c5SAnurag S. Maskey out[j++] = in[i];
1126ba597c5SAnurag S. Maskey break;
1136ba597c5SAnurag S. Maskey default:
1146ba597c5SAnurag S. Maskey out[j++] = in[i];
1156ba597c5SAnurag S. Maskey break;
1166ba597c5SAnurag S. Maskey }
1176ba597c5SAnurag S. Maskey }
1186ba597c5SAnurag S. Maskey out[j] = '\0';
1196ba597c5SAnurag S. Maskey }
1206ba597c5SAnurag S. Maskey
1216ba597c5SAnurag S. Maskey static char *
value_remove_escapes(char * in)1226ba597c5SAnurag S. Maskey value_remove_escapes(char *in)
1236ba597c5SAnurag S. Maskey {
1246ba597c5SAnurag S. Maskey char *out;
1256ba597c5SAnurag S. Maskey int i, j = 0;
1266ba597c5SAnurag S. Maskey
1276ba597c5SAnurag S. Maskey if ((out = strdup(in)) == NULL)
1286ba597c5SAnurag S. Maskey return (NULL);
1296ba597c5SAnurag S. Maskey
1306ba597c5SAnurag S. Maskey /*
1316ba597c5SAnurag S. Maskey * It is safe to use strlen() as we sanitycheck string length on value
1326ba597c5SAnurag S. Maskey * creation (i.e. before they are written to the file), so no string
1336ba597c5SAnurag S. Maskey * longer than NWAM_MAX_VALUE_LEN is accepted.
1346ba597c5SAnurag S. Maskey */
1356ba597c5SAnurag S. Maskey for (i = 0; i < strlen(in); i++) {
1366ba597c5SAnurag S. Maskey if (in[i] == NWAM_FILE_PROP_ESCAPE)
1376ba597c5SAnurag S. Maskey out[j++] = in[++i];
1386ba597c5SAnurag S. Maskey else
1396ba597c5SAnurag S. Maskey out[j++] = in[i];
1406ba597c5SAnurag S. Maskey }
1416ba597c5SAnurag S. Maskey out[j] = '\0';
1426ba597c5SAnurag S. Maskey return (out);
1436ba597c5SAnurag S. Maskey }
1446ba597c5SAnurag S. Maskey
1456ba597c5SAnurag S. Maskey
1466ba597c5SAnurag S. Maskey /*
1476ba597c5SAnurag S. Maskey * Parse line into name and object list of properties.
1486ba597c5SAnurag S. Maskey * Each line has the format:
1496ba597c5SAnurag S. Maskey *
1506ba597c5SAnurag S. Maskey * objname [prop=type:val1[,val2..];..]
1516ba597c5SAnurag S. Maskey */
1526ba597c5SAnurag S. Maskey nwam_error_t
nwam_line_to_object(char * line,char ** objname,void * proplist)1536ba597c5SAnurag S. Maskey nwam_line_to_object(char *line, char **objname, void *proplist)
1546ba597c5SAnurag S. Maskey {
1556ba597c5SAnurag S. Maskey char *next = line, *prop, *nextprop, *propname, *proptypestr, *nextval;
1566ba597c5SAnurag S. Maskey char **valstr, **newvalstr;
1576ba597c5SAnurag S. Maskey boolean_t *valbool, *newvalbool;
1586ba597c5SAnurag S. Maskey int64_t *valint, *newvalint;
1596ba597c5SAnurag S. Maskey uint64_t *valuint, *newvaluint;
1606ba597c5SAnurag S. Maskey uint_t nelem, i;
1616ba597c5SAnurag S. Maskey nwam_value_type_t proptype;
1626ba597c5SAnurag S. Maskey nwam_value_t val = NULL;
1636ba597c5SAnurag S. Maskey nwam_error_t err;
1646ba597c5SAnurag S. Maskey
1656ba597c5SAnurag S. Maskey if ((err = nwam_alloc_object_list(proplist)) != NWAM_SUCCESS)
1666ba597c5SAnurag S. Maskey return (err);
1676ba597c5SAnurag S. Maskey
1686ba597c5SAnurag S. Maskey *objname = line;
1696ba597c5SAnurag S. Maskey
1706ba597c5SAnurag S. Maskey if ((*objname = nwam_tokenize_by_unescaped_delim(line, '\t', &prop))
1716ba597c5SAnurag S. Maskey == NULL) {
1726ba597c5SAnurag S. Maskey nwam_free_object_list(*((char **)proplist));
1736ba597c5SAnurag S. Maskey return (NWAM_ENTITY_INVALID);
1746ba597c5SAnurag S. Maskey }
1756ba597c5SAnurag S. Maskey
1766ba597c5SAnurag S. Maskey while ((prop = nwam_tokenize_by_unescaped_delim(prop,
1776ba597c5SAnurag S. Maskey NWAM_FILE_PROP_DELIMITER, &nextprop)) != NULL) {
1786ba597c5SAnurag S. Maskey /*
1796ba597c5SAnurag S. Maskey * Parse property into name=type,val[,val]
1806ba597c5SAnurag S. Maskey */
1816ba597c5SAnurag S. Maskey if ((propname = nwam_tokenize_by_unescaped_delim(prop,
1826ba597c5SAnurag S. Maskey NWAM_FILE_PROP_ASSIGN, &next)) == NULL ||
1836ba597c5SAnurag S. Maskey (proptypestr = nwam_tokenize_by_unescaped_delim(next,
1846ba597c5SAnurag S. Maskey NWAM_FILE_VALUE_DELIMITER, &next)) == NULL) {
1856ba597c5SAnurag S. Maskey nwam_free_object_list(*((char **)proplist));
1866ba597c5SAnurag S. Maskey return (NWAM_ENTITY_INVALID);
1876ba597c5SAnurag S. Maskey }
1886ba597c5SAnurag S. Maskey if ((proptype = nwam_string_to_value_type(proptypestr)) ==
1896ba597c5SAnurag S. Maskey NWAM_VALUE_TYPE_UNKNOWN) {
1906ba597c5SAnurag S. Maskey nwam_free_object_list(*((char **)proplist));
1916ba597c5SAnurag S. Maskey return (NWAM_ENTITY_INVALID);
1926ba597c5SAnurag S. Maskey }
1936ba597c5SAnurag S. Maskey valbool = NULL;
1946ba597c5SAnurag S. Maskey valint = NULL;
1956ba597c5SAnurag S. Maskey valstr = NULL;
1966ba597c5SAnurag S. Maskey switch (proptype) {
1976ba597c5SAnurag S. Maskey case NWAM_VALUE_TYPE_BOOLEAN:
1986ba597c5SAnurag S. Maskey valbool = calloc(NWAM_MAX_NUM_VALUES,
1996ba597c5SAnurag S. Maskey sizeof (boolean_t));
2006ba597c5SAnurag S. Maskey break;
2016ba597c5SAnurag S. Maskey case NWAM_VALUE_TYPE_INT64:
2026ba597c5SAnurag S. Maskey valint = calloc(NWAM_MAX_NUM_VALUES,
2036ba597c5SAnurag S. Maskey sizeof (int64_t));
2046ba597c5SAnurag S. Maskey break;
2056ba597c5SAnurag S. Maskey case NWAM_VALUE_TYPE_UINT64:
2066ba597c5SAnurag S. Maskey valuint = calloc(NWAM_MAX_NUM_VALUES,
2076ba597c5SAnurag S. Maskey sizeof (uint64_t));
2086ba597c5SAnurag S. Maskey break;
2096ba597c5SAnurag S. Maskey case NWAM_VALUE_TYPE_STRING:
2106ba597c5SAnurag S. Maskey valstr = calloc(NWAM_MAX_NUM_VALUES,
2116ba597c5SAnurag S. Maskey sizeof (char *));
2126ba597c5SAnurag S. Maskey break;
2136ba597c5SAnurag S. Maskey default:
2146ba597c5SAnurag S. Maskey nwam_free_object_list(*((char **)proplist));
2156ba597c5SAnurag S. Maskey return (NWAM_ENTITY_INVALID_VALUE);
2166ba597c5SAnurag S. Maskey }
2176ba597c5SAnurag S. Maskey if (valbool == NULL && valint == NULL && valuint == NULL &&
2186ba597c5SAnurag S. Maskey valstr == NULL) {
2196ba597c5SAnurag S. Maskey /* Memory allocation failed */
2206ba597c5SAnurag S. Maskey nwam_free_object_list(*((char **)proplist));
2216ba597c5SAnurag S. Maskey return (NWAM_NO_MEMORY);
2226ba597c5SAnurag S. Maskey }
2236ba597c5SAnurag S. Maskey nelem = 0;
2246ba597c5SAnurag S. Maskey while ((nextval = nwam_tokenize_by_unescaped_delim(next,
2256ba597c5SAnurag S. Maskey NWAM_FILE_VALUE_DELIMITER, &next)) != NULL) {
2266ba597c5SAnurag S. Maskey nelem++;
2276ba597c5SAnurag S. Maskey switch (proptype) {
2286ba597c5SAnurag S. Maskey case NWAM_VALUE_TYPE_BOOLEAN:
2296ba597c5SAnurag S. Maskey if (strncmp(nextval, NWAM_FILE_BOOLEAN_TRUE,
2306ba597c5SAnurag S. Maskey strlen(nextval)) == 0) {
2316ba597c5SAnurag S. Maskey valbool[nelem - 1] = B_TRUE;
2326ba597c5SAnurag S. Maskey } else if (strncmp(nextval,
2336ba597c5SAnurag S. Maskey NWAM_FILE_BOOLEAN_FALSE, strlen(nextval))
2346ba597c5SAnurag S. Maskey == 0) {
2356ba597c5SAnurag S. Maskey valbool[nelem - 1] = B_FALSE;
2366ba597c5SAnurag S. Maskey } else {
2376ba597c5SAnurag S. Maskey nwam_free_object_list
2386ba597c5SAnurag S. Maskey (*((char **)proplist));
2396ba597c5SAnurag S. Maskey return (NWAM_ENTITY_INVALID_VALUE);
2406ba597c5SAnurag S. Maskey }
2416ba597c5SAnurag S. Maskey break;
2426ba597c5SAnurag S. Maskey case NWAM_VALUE_TYPE_INT64:
2436ba597c5SAnurag S. Maskey valint[nelem - 1] = (int64_t)atoll(nextval);
2446ba597c5SAnurag S. Maskey break;
2456ba597c5SAnurag S. Maskey case NWAM_VALUE_TYPE_UINT64:
2466ba597c5SAnurag S. Maskey valuint[nelem - 1] = (uint64_t)atoll(nextval);
2476ba597c5SAnurag S. Maskey break;
2486ba597c5SAnurag S. Maskey case NWAM_VALUE_TYPE_STRING:
2496ba597c5SAnurag S. Maskey valstr[nelem - 1] =
2506ba597c5SAnurag S. Maskey value_remove_escapes(nextval);
2516ba597c5SAnurag S. Maskey break;
2526ba597c5SAnurag S. Maskey default:
2536ba597c5SAnurag S. Maskey nwam_free_object_list(*((char **)proplist));
2546ba597c5SAnurag S. Maskey return (NWAM_ENTITY_INVALID_VALUE);
2556ba597c5SAnurag S. Maskey }
2566ba597c5SAnurag S. Maskey }
2576ba597c5SAnurag S. Maskey switch (proptype) {
2586ba597c5SAnurag S. Maskey case NWAM_VALUE_TYPE_BOOLEAN:
2596ba597c5SAnurag S. Maskey if ((newvalbool = realloc(valbool,
2606ba597c5SAnurag S. Maskey nelem * sizeof (boolean_t))) == NULL) {
2616ba597c5SAnurag S. Maskey nwam_free_object_list(*((char **)proplist));
2626ba597c5SAnurag S. Maskey return (NWAM_NO_MEMORY);
2636ba597c5SAnurag S. Maskey }
2646ba597c5SAnurag S. Maskey if ((err = nwam_value_create_boolean_array(newvalbool,
2656ba597c5SAnurag S. Maskey nelem, &val)) != NWAM_SUCCESS ||
2666ba597c5SAnurag S. Maskey (err = nwam_set_prop_value(*((char **)proplist),
2676ba597c5SAnurag S. Maskey propname, val)) != NWAM_SUCCESS) {
2686ba597c5SAnurag S. Maskey free(newvalbool);
2696ba597c5SAnurag S. Maskey nwam_value_free(val);
2706ba597c5SAnurag S. Maskey nwam_free_object_list(*((char **)proplist));
2716ba597c5SAnurag S. Maskey return (err);
2726ba597c5SAnurag S. Maskey }
2736ba597c5SAnurag S. Maskey free(newvalbool);
2746ba597c5SAnurag S. Maskey nwam_value_free(val);
2756ba597c5SAnurag S. Maskey break;
2766ba597c5SAnurag S. Maskey case NWAM_VALUE_TYPE_INT64:
2776ba597c5SAnurag S. Maskey if ((newvalint = realloc(valint,
2786ba597c5SAnurag S. Maskey nelem * sizeof (int64_t))) == NULL) {
2796ba597c5SAnurag S. Maskey nwam_free_object_list(*((char **)proplist));
2806ba597c5SAnurag S. Maskey return (NWAM_NO_MEMORY);
2816ba597c5SAnurag S. Maskey }
2826ba597c5SAnurag S. Maskey if ((err = nwam_value_create_int64_array(newvalint,
2836ba597c5SAnurag S. Maskey nelem, &val)) != NWAM_SUCCESS ||
2846ba597c5SAnurag S. Maskey (err = nwam_set_prop_value(*((char **)proplist),
2856ba597c5SAnurag S. Maskey propname, val)) != NWAM_SUCCESS) {
2866ba597c5SAnurag S. Maskey free(newvalint);
2876ba597c5SAnurag S. Maskey nwam_value_free(val);
2886ba597c5SAnurag S. Maskey nwam_free_object_list(*((char **)proplist));
2896ba597c5SAnurag S. Maskey return (err);
2906ba597c5SAnurag S. Maskey }
2916ba597c5SAnurag S. Maskey free(newvalint);
2926ba597c5SAnurag S. Maskey nwam_value_free(val);
2936ba597c5SAnurag S. Maskey break;
2946ba597c5SAnurag S. Maskey case NWAM_VALUE_TYPE_UINT64:
2956ba597c5SAnurag S. Maskey if ((newvaluint = realloc(valuint,
2966ba597c5SAnurag S. Maskey nelem * sizeof (uint64_t))) == NULL) {
2976ba597c5SAnurag S. Maskey nwam_free_object_list(*((char **)proplist));
2986ba597c5SAnurag S. Maskey return (NWAM_NO_MEMORY);
2996ba597c5SAnurag S. Maskey }
3006ba597c5SAnurag S. Maskey if ((err = nwam_value_create_uint64_array(newvaluint,
3016ba597c5SAnurag S. Maskey nelem, &val)) != NWAM_SUCCESS ||
3026ba597c5SAnurag S. Maskey (err = nwam_set_prop_value(*((char **)proplist),
3036ba597c5SAnurag S. Maskey propname, val)) != NWAM_SUCCESS) {
3046ba597c5SAnurag S. Maskey free(newvaluint);
3056ba597c5SAnurag S. Maskey nwam_value_free(val);
3066ba597c5SAnurag S. Maskey nwam_free_object_list(*((char **)proplist));
3076ba597c5SAnurag S. Maskey return (err);
3086ba597c5SAnurag S. Maskey }
3096ba597c5SAnurag S. Maskey free(newvaluint);
3106ba597c5SAnurag S. Maskey nwam_value_free(val);
3116ba597c5SAnurag S. Maskey break;
3126ba597c5SAnurag S. Maskey case NWAM_VALUE_TYPE_STRING:
3136ba597c5SAnurag S. Maskey if ((newvalstr = realloc(valstr,
3146ba597c5SAnurag S. Maskey nelem * sizeof (char *))) == NULL) {
3156ba597c5SAnurag S. Maskey nwam_free_object_list(*((char **)proplist));
3166ba597c5SAnurag S. Maskey return (NWAM_NO_MEMORY);
3176ba597c5SAnurag S. Maskey }
3186ba597c5SAnurag S. Maskey if ((err = nwam_value_create_string_array(newvalstr,
3196ba597c5SAnurag S. Maskey nelem, &val)) != NWAM_SUCCESS ||
3206ba597c5SAnurag S. Maskey (err = nwam_set_prop_value(*((char **)proplist),
3216ba597c5SAnurag S. Maskey propname, val)) != NWAM_SUCCESS) {
3226ba597c5SAnurag S. Maskey for (i = 0; i < nelem; i++)
3236ba597c5SAnurag S. Maskey free(newvalstr[i]);
3246ba597c5SAnurag S. Maskey free(newvalstr);
3256ba597c5SAnurag S. Maskey nwam_value_free(val);
3266ba597c5SAnurag S. Maskey nwam_free_object_list(*((char **)proplist));
3276ba597c5SAnurag S. Maskey return (err);
3286ba597c5SAnurag S. Maskey }
3296ba597c5SAnurag S. Maskey for (i = 0; i < nelem; i++)
3306ba597c5SAnurag S. Maskey free(newvalstr[i]);
3316ba597c5SAnurag S. Maskey free(newvalstr);
3326ba597c5SAnurag S. Maskey nwam_value_free(val);
3336ba597c5SAnurag S. Maskey break;
3346ba597c5SAnurag S. Maskey }
3356ba597c5SAnurag S. Maskey prop = nextprop;
3366ba597c5SAnurag S. Maskey }
3376ba597c5SAnurag S. Maskey
3386ba597c5SAnurag S. Maskey return (NWAM_SUCCESS);
3396ba597c5SAnurag S. Maskey }
3406ba597c5SAnurag S. Maskey
3416ba597c5SAnurag S. Maskey /*
3426ba597c5SAnurag S. Maskey * Create list of NCP files used for walk of NCPs and for case-insensitive
3436ba597c5SAnurag S. Maskey * matching of NCP name to file.
3446ba597c5SAnurag S. Maskey */
3456ba597c5SAnurag S. Maskey static nwam_error_t
create_ncp_file_list(char *** ncpfilesp,uint_t * num_filesp)3466ba597c5SAnurag S. Maskey create_ncp_file_list(char ***ncpfilesp, uint_t *num_filesp)
3476ba597c5SAnurag S. Maskey {
3486ba597c5SAnurag S. Maskey DIR *dirp = NULL;
3496ba597c5SAnurag S. Maskey struct dirent *dp;
3506ba597c5SAnurag S. Maskey char *ncpname, **ncpfiles = NULL;
3516ba597c5SAnurag S. Maskey nwam_error_t err = NWAM_SUCCESS;
3526ba597c5SAnurag S. Maskey uint_t i;
3536ba597c5SAnurag S. Maskey
3546ba597c5SAnurag S. Maskey ncpfiles = calloc(NWAM_MAX_NUM_OBJECTS, sizeof (char *));
3556ba597c5SAnurag S. Maskey if (ncpfiles == NULL)
3566ba597c5SAnurag S. Maskey return (NWAM_NO_MEMORY);
3576ba597c5SAnurag S. Maskey *num_filesp = 0;
3586ba597c5SAnurag S. Maskey
3596ba597c5SAnurag S. Maskey /*
3606ba597c5SAnurag S. Maskey * Construct NCP list by finding all files in NWAM directory
3616ba597c5SAnurag S. Maskey * that match the NCP filename format.
3626ba597c5SAnurag S. Maskey */
3636ba597c5SAnurag S. Maskey if ((dirp = opendir(NWAM_CONF_DIR)) == NULL) {
3646ba597c5SAnurag S. Maskey err = nwam_errno_to_nwam_error(errno);
3656ba597c5SAnurag S. Maskey goto done;
3666ba597c5SAnurag S. Maskey }
3676ba597c5SAnurag S. Maskey
3686ba597c5SAnurag S. Maskey while ((dp = readdir(dirp)) != NULL) {
3696ba597c5SAnurag S. Maskey uint_t filenamelen;
3706ba597c5SAnurag S. Maskey
3716ba597c5SAnurag S. Maskey /* Ensure filename is valid */
3726ba597c5SAnurag S. Maskey if (nwam_ncp_file_to_name(dp->d_name, &ncpname) != NWAM_SUCCESS)
3736ba597c5SAnurag S. Maskey continue;
3746ba597c5SAnurag S. Maskey free(ncpname);
3756ba597c5SAnurag S. Maskey filenamelen = strlen(NWAM_CONF_DIR) + strlen(dp->d_name) + 1;
3766ba597c5SAnurag S. Maskey if ((ncpfiles[*num_filesp] = malloc(filenamelen)) == NULL) {
3776ba597c5SAnurag S. Maskey err = NWAM_NO_MEMORY;
3786ba597c5SAnurag S. Maskey goto done;
3796ba597c5SAnurag S. Maskey }
3806ba597c5SAnurag S. Maskey (void) strlcpy(ncpfiles[*num_filesp], NWAM_CONF_DIR,
3816ba597c5SAnurag S. Maskey strlen(NWAM_CONF_DIR) + 1);
3826ba597c5SAnurag S. Maskey (void) strlcpy(ncpfiles[*num_filesp] + strlen(NWAM_CONF_DIR),
3836ba597c5SAnurag S. Maskey dp->d_name, filenamelen - strlen(NWAM_CONF_DIR));
3846ba597c5SAnurag S. Maskey (*num_filesp)++;
3856ba597c5SAnurag S. Maskey }
3866ba597c5SAnurag S. Maskey done:
3876ba597c5SAnurag S. Maskey if (dirp != NULL)
3886ba597c5SAnurag S. Maskey (void) closedir(dirp);
3896ba597c5SAnurag S. Maskey
3906ba597c5SAnurag S. Maskey if (err != NWAM_SUCCESS) {
3916ba597c5SAnurag S. Maskey for (i = 0; i < *num_filesp; i++)
3926ba597c5SAnurag S. Maskey free(ncpfiles[i]);
3936ba597c5SAnurag S. Maskey free(ncpfiles);
3946ba597c5SAnurag S. Maskey } else {
3956ba597c5SAnurag S. Maskey *ncpfilesp = realloc(ncpfiles, sizeof (char *) * (*num_filesp));
396*69b43529SMichael Hunter if (*num_filesp != 0 && *ncpfilesp == NULL)
3976ba597c5SAnurag S. Maskey err = NWAM_NO_MEMORY;
3986ba597c5SAnurag S. Maskey }
3996ba597c5SAnurag S. Maskey return (err);
4006ba597c5SAnurag S. Maskey }
4016ba597c5SAnurag S. Maskey
4026ba597c5SAnurag S. Maskey /*
4036ba597c5SAnurag S. Maskey * Read object specified by objname from file, converting it to
4046ba597c5SAnurag S. Maskey * an object list. If filename is NULL, a list of configuration object
4056ba597c5SAnurag S. Maskey * containers is returned, represented as an object lists with elements "enms"
4066ba597c5SAnurag S. Maskey * "locs" and "ncps". Each of these is a list of configuration files for each
4076ba597c5SAnurag S. Maskey * object. This corresponds to the enm.conf file, loc.conf file and list of
4086ba597c5SAnurag S. Maskey * ncp conf files. If objname is NULL, read all objects, and create
4096ba597c5SAnurag S. Maskey * an nvlist with one element - "object-list" - which has as its values
4106ba597c5SAnurag S. Maskey * the names of the objects found. Otherwise obj points to an object list
4116ba597c5SAnurag S. Maskey * of properties for the first object in the file that case-insensitively
4126ba597c5SAnurag S. Maskey * matches objname. We write the found name into objname so that it can be
4136ba597c5SAnurag S. Maskey * returned to the caller (and set in the object handle).
4146ba597c5SAnurag S. Maskey */
4156ba597c5SAnurag S. Maskey /* ARGSUSED2 */
4166ba597c5SAnurag S. Maskey nwam_error_t
nwam_read_object_from_files_backend(char * filename,char * objname,uint64_t flags,void * obj)4176ba597c5SAnurag S. Maskey nwam_read_object_from_files_backend(char *filename, char *objname,
4186ba597c5SAnurag S. Maskey uint64_t flags, void *obj)
4196ba597c5SAnurag S. Maskey {
4206ba597c5SAnurag S. Maskey char line[NWAM_FILE_LINE_MAX];
4216ba597c5SAnurag S. Maskey char *cp, *foundobjname, **objnames = NULL, **ncpfiles = NULL;
4226ba597c5SAnurag S. Maskey uint_t num_files = 0;
4236ba597c5SAnurag S. Maskey FILE *fp = NULL;
4246ba597c5SAnurag S. Maskey nwam_error_t err;
4256ba597c5SAnurag S. Maskey void *objlist = NULL, *proplist = NULL;
4266ba597c5SAnurag S. Maskey uint_t i = 0, j = 0;
4276ba597c5SAnurag S. Maskey nwam_value_t objnamesval = NULL;
4286ba597c5SAnurag S. Maskey
4296ba597c5SAnurag S. Maskey assert(obj != NULL);
4306ba597c5SAnurag S. Maskey
4316ba597c5SAnurag S. Maskey *((char **)obj) = NULL;
4326ba597c5SAnurag S. Maskey
4336ba597c5SAnurag S. Maskey if (filename == NULL) {
4346ba597c5SAnurag S. Maskey nwam_value_t enmval = NULL, locval = NULL, ncpval = NULL;
4356ba597c5SAnurag S. Maskey
4366ba597c5SAnurag S. Maskey /*
4376ba597c5SAnurag S. Maskey * When the filename is not specified, it signifies a
4386ba597c5SAnurag S. Maskey * request for the list of configuration object containers -
4396ba597c5SAnurag S. Maskey * in this case files.
4406ba597c5SAnurag S. Maskey *
4416ba597c5SAnurag S. Maskey * A list of all object files is returned. For ENMs
4426ba597c5SAnurag S. Maskey * and locations, only the default loc.conf and enm.conf
4436ba597c5SAnurag S. Maskey * files are used, but for NCPs we need to walk the
4446ba597c5SAnurag S. Maskey * files in the NWAM directory retrieving each one that
4456ba597c5SAnurag S. Maskey * matches the NCP pattern.
4466ba597c5SAnurag S. Maskey */
4476ba597c5SAnurag S. Maskey if ((err = nwam_alloc_object_list(&objlist)) != NWAM_SUCCESS)
4486ba597c5SAnurag S. Maskey return (err);
4496ba597c5SAnurag S. Maskey
4506ba597c5SAnurag S. Maskey if ((err = nwam_value_create_string(NWAM_ENM_CONF_FILE,
4516ba597c5SAnurag S. Maskey &enmval)) != NWAM_SUCCESS ||
4526ba597c5SAnurag S. Maskey (err = nwam_value_create_string(NWAM_LOC_CONF_FILE,
4536ba597c5SAnurag S. Maskey &locval)) != NWAM_SUCCESS ||
4546ba597c5SAnurag S. Maskey (err = nwam_set_prop_value(objlist, NWAM_ENM_OBJECT_STRING,
4556ba597c5SAnurag S. Maskey enmval)) != NWAM_SUCCESS ||
4566ba597c5SAnurag S. Maskey (err = nwam_set_prop_value(objlist, NWAM_LOC_OBJECT_STRING,
4576ba597c5SAnurag S. Maskey locval)) != NWAM_SUCCESS)
4586ba597c5SAnurag S. Maskey goto done_with_containers;
4596ba597c5SAnurag S. Maskey
4606ba597c5SAnurag S. Maskey /*
4616ba597c5SAnurag S. Maskey * Construct NCP list by finding all files in NWAM directory
4626ba597c5SAnurag S. Maskey * that match the NCP filename format.
4636ba597c5SAnurag S. Maskey */
4646ba597c5SAnurag S. Maskey if ((err = create_ncp_file_list(&ncpfiles, &num_files))
4656ba597c5SAnurag S. Maskey != NWAM_SUCCESS)
4666ba597c5SAnurag S. Maskey goto done_with_containers;
4676ba597c5SAnurag S. Maskey
4686ba597c5SAnurag S. Maskey if ((err = nwam_value_create_string_array(ncpfiles, num_files,
4696ba597c5SAnurag S. Maskey &ncpval)) == NWAM_SUCCESS) {
4706ba597c5SAnurag S. Maskey err = nwam_set_prop_value(objlist,
4716ba597c5SAnurag S. Maskey NWAM_NCP_OBJECT_STRING, ncpval);
4726ba597c5SAnurag S. Maskey }
4736ba597c5SAnurag S. Maskey
4746ba597c5SAnurag S. Maskey done_with_containers:
4756ba597c5SAnurag S. Maskey nwam_value_free(enmval);
4766ba597c5SAnurag S. Maskey nwam_value_free(locval);
4776ba597c5SAnurag S. Maskey nwam_value_free(ncpval);
4786ba597c5SAnurag S. Maskey if (ncpfiles != NULL) {
4796ba597c5SAnurag S. Maskey for (j = 0; j < num_files; j++)
4806ba597c5SAnurag S. Maskey free(ncpfiles[j]);
4816ba597c5SAnurag S. Maskey free(ncpfiles);
4826ba597c5SAnurag S. Maskey }
4836ba597c5SAnurag S. Maskey if (err != NWAM_SUCCESS)
4846ba597c5SAnurag S. Maskey nwam_free_object_list(objlist);
4856ba597c5SAnurag S. Maskey else
4866ba597c5SAnurag S. Maskey *((char **)obj) = objlist;
4876ba597c5SAnurag S. Maskey return (err);
4886ba597c5SAnurag S. Maskey }
4896ba597c5SAnurag S. Maskey
4906ba597c5SAnurag S. Maskey if (objname == NULL) {
4916ba597c5SAnurag S. Maskey /* Allocate string array to store object names */
4926ba597c5SAnurag S. Maskey if ((objnames = calloc(NWAM_MAX_NUM_OBJECTS, sizeof (char *)))
4936ba597c5SAnurag S. Maskey == NULL)
4946ba597c5SAnurag S. Maskey return (NWAM_NO_MEMORY);
4956ba597c5SAnurag S. Maskey }
4966ba597c5SAnurag S. Maskey
4976ba597c5SAnurag S. Maskey fp = fopen(filename, "r");
4986ba597c5SAnurag S. Maskey if (fp == NULL) {
4996ba597c5SAnurag S. Maskey if (errno != ENOENT) {
5006ba597c5SAnurag S. Maskey if (objname == NULL)
5016ba597c5SAnurag S. Maskey free(objnames);
5026ba597c5SAnurag S. Maskey return (NWAM_ERROR_INTERNAL);
5036ba597c5SAnurag S. Maskey }
5046ba597c5SAnurag S. Maskey
5056ba597c5SAnurag S. Maskey /*
5066ba597c5SAnurag S. Maskey * Check NCP file list in case filename passed in was derived
5076ba597c5SAnurag S. Maskey * from a case-insensitive NCP name.
5086ba597c5SAnurag S. Maskey */
5096ba597c5SAnurag S. Maskey if ((err = create_ncp_file_list(&ncpfiles, &num_files))
5106ba597c5SAnurag S. Maskey == NWAM_SUCCESS) {
5116ba597c5SAnurag S. Maskey for (j = 0; j < num_files; j++) {
5126ba597c5SAnurag S. Maskey if (strcasecmp(ncpfiles[j], filename) == 0) {
5136ba597c5SAnurag S. Maskey fp = fopen(ncpfiles[j], "r");
5146ba597c5SAnurag S. Maskey if (fp != NULL) {
5156ba597c5SAnurag S. Maskey /* Copy real filename back */
5166ba597c5SAnurag S. Maskey (void) strlcpy(filename,
5176ba597c5SAnurag S. Maskey ncpfiles[j],
5186ba597c5SAnurag S. Maskey strlen(filename) + 1);
5196ba597c5SAnurag S. Maskey break;
5206ba597c5SAnurag S. Maskey }
5216ba597c5SAnurag S. Maskey }
5226ba597c5SAnurag S. Maskey }
5236ba597c5SAnurag S. Maskey for (j = 0; j < num_files; j++)
5246ba597c5SAnurag S. Maskey free(ncpfiles[j]);
5256ba597c5SAnurag S. Maskey free(ncpfiles);
5266ba597c5SAnurag S. Maskey }
5276ba597c5SAnurag S. Maskey /* Return NOT_FOUND if file not found */
5286ba597c5SAnurag S. Maskey if (fp == NULL) {
5296ba597c5SAnurag S. Maskey if (objname == NULL)
5306ba597c5SAnurag S. Maskey free(objnames);
5316ba597c5SAnurag S. Maskey return (NWAM_ENTITY_NOT_FOUND);
5326ba597c5SAnurag S. Maskey }
5336ba597c5SAnurag S. Maskey }
5346ba597c5SAnurag S. Maskey
5356ba597c5SAnurag S. Maskey while (fgets(line, sizeof (line), fp) != NULL) {
5366ba597c5SAnurag S. Maskey if (line[strlen(line) - 1] == '\n')
5376ba597c5SAnurag S. Maskey line[strlen(line) - 1] = '\0';
5386ba597c5SAnurag S. Maskey
5396ba597c5SAnurag S. Maskey cp = line;
5406ba597c5SAnurag S. Maskey
5416ba597c5SAnurag S. Maskey while (isspace(*cp))
5426ba597c5SAnurag S. Maskey cp++;
5436ba597c5SAnurag S. Maskey
5446ba597c5SAnurag S. Maskey if (*cp == '#' || *cp == '\0')
5456ba597c5SAnurag S. Maskey continue;
5466ba597c5SAnurag S. Maskey
5476ba597c5SAnurag S. Maskey if ((err = nwam_line_to_object(cp, &foundobjname, &proplist))
5486ba597c5SAnurag S. Maskey != NWAM_SUCCESS)
5496ba597c5SAnurag S. Maskey goto done;
5506ba597c5SAnurag S. Maskey
5516ba597c5SAnurag S. Maskey if (objname != NULL) {
5526ba597c5SAnurag S. Maskey /*
5536ba597c5SAnurag S. Maskey * Is this the specified object? If so set objname and
5546ba597c5SAnurag S. Maskey * obj and bail.
5556ba597c5SAnurag S. Maskey */
5566ba597c5SAnurag S. Maskey if (strcasecmp(objname, foundobjname) == 0) {
5576ba597c5SAnurag S. Maskey *((char **)obj) = proplist;
5586ba597c5SAnurag S. Maskey (void) strlcpy(objname, foundobjname,
5596ba597c5SAnurag S. Maskey NWAM_MAX_NAME_LEN);
5606ba597c5SAnurag S. Maskey break;
5616ba597c5SAnurag S. Maskey } else {
5626ba597c5SAnurag S. Maskey nwam_free_object_list(proplist);
5636ba597c5SAnurag S. Maskey }
5646ba597c5SAnurag S. Maskey } else {
5656ba597c5SAnurag S. Maskey objnames[i] = strdup(foundobjname);
5666ba597c5SAnurag S. Maskey nwam_free_object_list(proplist);
5676ba597c5SAnurag S. Maskey if (objnames[i] == NULL) {
5686ba597c5SAnurag S. Maskey err = NWAM_NO_MEMORY;
5696ba597c5SAnurag S. Maskey goto done;
5706ba597c5SAnurag S. Maskey }
5716ba597c5SAnurag S. Maskey i++;
5726ba597c5SAnurag S. Maskey }
5736ba597c5SAnurag S. Maskey
5746ba597c5SAnurag S. Maskey }
5756ba597c5SAnurag S. Maskey if (objname == NULL) {
5766ba597c5SAnurag S. Maskey /*
5776ba597c5SAnurag S. Maskey * Allocate object list with one value named
5786ba597c5SAnurag S. Maskey * NWAM_OBJECT_NAMES_STRING - it's values are the names of
5796ba597c5SAnurag S. Maskey * the objects found.
5806ba597c5SAnurag S. Maskey */
5816ba597c5SAnurag S. Maskey if ((err = nwam_alloc_object_list(&objlist)) == NWAM_SUCCESS &&
5826ba597c5SAnurag S. Maskey (err = nwam_value_create_string_array(objnames, i,
5836ba597c5SAnurag S. Maskey &objnamesval)) == NWAM_SUCCESS) {
5846ba597c5SAnurag S. Maskey err = nwam_set_prop_value(objlist,
5856ba597c5SAnurag S. Maskey NWAM_OBJECT_NAMES_STRING, objnamesval);
5866ba597c5SAnurag S. Maskey }
5876ba597c5SAnurag S. Maskey }
5886ba597c5SAnurag S. Maskey
5896ba597c5SAnurag S. Maskey done:
5906ba597c5SAnurag S. Maskey if (fp != NULL)
5916ba597c5SAnurag S. Maskey (void) fclose(fp);
5926ba597c5SAnurag S. Maskey
5936ba597c5SAnurag S. Maskey /*
5946ba597c5SAnurag S. Maskey * We're done, either we have success, and return our object list
5956ba597c5SAnurag S. Maskey * containing object names, or we have failure and we need to free
5966ba597c5SAnurag S. Maskey * the object list.
5976ba597c5SAnurag S. Maskey */
5986ba597c5SAnurag S. Maskey if (objname == NULL) {
5996ba597c5SAnurag S. Maskey for (j = 0; j < i; j++)
6006ba597c5SAnurag S. Maskey free(objnames[j]);
6016ba597c5SAnurag S. Maskey free(objnames);
6026ba597c5SAnurag S. Maskey nwam_value_free(objnamesval);
6036ba597c5SAnurag S. Maskey if (err == NWAM_SUCCESS) {
6046ba597c5SAnurag S. Maskey *((char **)obj) = objlist;
6056ba597c5SAnurag S. Maskey } else {
6066ba597c5SAnurag S. Maskey *((char **)obj) = NULL;
6076ba597c5SAnurag S. Maskey nwam_free_object_list(objlist);
6086ba597c5SAnurag S. Maskey }
6096ba597c5SAnurag S. Maskey } else {
6106ba597c5SAnurag S. Maskey /* Check if to-be-read object was not found */
6116ba597c5SAnurag S. Maskey if (*((char **)obj) == NULL && err == NWAM_SUCCESS)
6126ba597c5SAnurag S. Maskey return (NWAM_ENTITY_NOT_FOUND);
6136ba597c5SAnurag S. Maskey }
6146ba597c5SAnurag S. Maskey
6156ba597c5SAnurag S. Maskey return (err);
6166ba597c5SAnurag S. Maskey }
6176ba597c5SAnurag S. Maskey
6186ba597c5SAnurag S. Maskey nwam_error_t
nwam_object_to_line(FILE * fp,const char * objname,void * proplist)6196ba597c5SAnurag S. Maskey nwam_object_to_line(FILE *fp, const char *objname, void *proplist)
6206ba597c5SAnurag S. Maskey {
6216ba597c5SAnurag S. Maskey char *propname, *lastpropname = NULL;
6226ba597c5SAnurag S. Maskey boolean_t *valbool;
6236ba597c5SAnurag S. Maskey int64_t *valint;
6246ba597c5SAnurag S. Maskey uint64_t *valuint;
6256ba597c5SAnurag S. Maskey char **valstr;
6266ba597c5SAnurag S. Maskey uint_t nelem, i;
6276ba597c5SAnurag S. Maskey nwam_value_t val;
6286ba597c5SAnurag S. Maskey nwam_value_type_t type;
6296ba597c5SAnurag S. Maskey
6306ba597c5SAnurag S. Maskey (void) fprintf(fp, "%s\t", objname);
6316ba597c5SAnurag S. Maskey
6326ba597c5SAnurag S. Maskey while (nwam_next_object_prop(proplist, lastpropname, &propname, &val)
6336ba597c5SAnurag S. Maskey == NWAM_SUCCESS) {
6346ba597c5SAnurag S. Maskey
6356ba597c5SAnurag S. Maskey (void) fprintf(fp, "%s%c", propname, NWAM_FILE_PROP_ASSIGN);
6366ba597c5SAnurag S. Maskey
6376ba597c5SAnurag S. Maskey if (nwam_value_get_type(val, &type) != NWAM_SUCCESS)
6386ba597c5SAnurag S. Maskey return (NWAM_INVALID_ARG);
6396ba597c5SAnurag S. Maskey
6406ba597c5SAnurag S. Maskey switch (type) {
6416ba597c5SAnurag S. Maskey case NWAM_VALUE_TYPE_BOOLEAN:
6426ba597c5SAnurag S. Maskey (void) fprintf(fp, "%s",
6436ba597c5SAnurag S. Maskey nwam_value_type_to_string(NWAM_VALUE_TYPE_BOOLEAN));
6446ba597c5SAnurag S. Maskey if (nwam_value_get_boolean_array(val, &valbool, &nelem)
6456ba597c5SAnurag S. Maskey != NWAM_SUCCESS) {
6466ba597c5SAnurag S. Maskey nwam_value_free(val);
6476ba597c5SAnurag S. Maskey return (NWAM_INVALID_ARG);
6486ba597c5SAnurag S. Maskey }
6496ba597c5SAnurag S. Maskey for (i = 0; i < nelem; i++) {
6506ba597c5SAnurag S. Maskey (void) fprintf(fp, "%c",
6516ba597c5SAnurag S. Maskey NWAM_FILE_VALUE_DELIMITER);
6526ba597c5SAnurag S. Maskey if (valbool[i]) {
6536ba597c5SAnurag S. Maskey (void) fprintf(fp,
6546ba597c5SAnurag S. Maskey NWAM_FILE_BOOLEAN_TRUE);
6556ba597c5SAnurag S. Maskey } else {
6566ba597c5SAnurag S. Maskey (void) fprintf(fp,
6576ba597c5SAnurag S. Maskey NWAM_FILE_BOOLEAN_FALSE);
6586ba597c5SAnurag S. Maskey }
6596ba597c5SAnurag S. Maskey }
6606ba597c5SAnurag S. Maskey break;
6616ba597c5SAnurag S. Maskey
6626ba597c5SAnurag S. Maskey case NWAM_VALUE_TYPE_INT64:
6636ba597c5SAnurag S. Maskey (void) fprintf(fp, "%s",
6646ba597c5SAnurag S. Maskey nwam_value_type_to_string(NWAM_VALUE_TYPE_INT64));
6656ba597c5SAnurag S. Maskey if (nwam_value_get_int64_array(val, &valint, &nelem)
6666ba597c5SAnurag S. Maskey != NWAM_SUCCESS) {
6676ba597c5SAnurag S. Maskey nwam_value_free(val);
6686ba597c5SAnurag S. Maskey return (NWAM_INVALID_ARG);
6696ba597c5SAnurag S. Maskey }
6706ba597c5SAnurag S. Maskey for (i = 0; i < nelem; i++) {
6716ba597c5SAnurag S. Maskey (void) fprintf(fp, "%c%lld",
6726ba597c5SAnurag S. Maskey NWAM_FILE_VALUE_DELIMITER, valint[i]);
6736ba597c5SAnurag S. Maskey }
6746ba597c5SAnurag S. Maskey break;
6756ba597c5SAnurag S. Maskey
6766ba597c5SAnurag S. Maskey case NWAM_VALUE_TYPE_UINT64:
6776ba597c5SAnurag S. Maskey (void) fprintf(fp, "%s",
6786ba597c5SAnurag S. Maskey nwam_value_type_to_string(NWAM_VALUE_TYPE_UINT64));
6796ba597c5SAnurag S. Maskey if (nwam_value_get_uint64_array(val, &valuint, &nelem)
6806ba597c5SAnurag S. Maskey != NWAM_SUCCESS) {
6816ba597c5SAnurag S. Maskey nwam_value_free(val);
6826ba597c5SAnurag S. Maskey return (NWAM_INVALID_ARG);
6836ba597c5SAnurag S. Maskey }
6846ba597c5SAnurag S. Maskey for (i = 0; i < nelem; i++) {
6856ba597c5SAnurag S. Maskey (void) fprintf(fp, "%c%lld",
6866ba597c5SAnurag S. Maskey NWAM_FILE_VALUE_DELIMITER, valuint[i]);
6876ba597c5SAnurag S. Maskey }
6886ba597c5SAnurag S. Maskey break;
6896ba597c5SAnurag S. Maskey
6906ba597c5SAnurag S. Maskey case NWAM_VALUE_TYPE_STRING:
6916ba597c5SAnurag S. Maskey (void) fprintf(fp, "%s",
6926ba597c5SAnurag S. Maskey nwam_value_type_to_string(NWAM_VALUE_TYPE_STRING));
6936ba597c5SAnurag S. Maskey if (nwam_value_get_string_array(val, &valstr, &nelem)
6946ba597c5SAnurag S. Maskey != NWAM_SUCCESS) {
6956ba597c5SAnurag S. Maskey nwam_value_free(val);
6966ba597c5SAnurag S. Maskey return (NWAM_INVALID_ARG);
6976ba597c5SAnurag S. Maskey }
6986ba597c5SAnurag S. Maskey for (i = 0; i < nelem; i++) {
6996ba597c5SAnurag S. Maskey char evalstr[NWAM_MAX_VALUE_LEN];
7006ba597c5SAnurag S. Maskey /* Add escape chars as necessary */
7016ba597c5SAnurag S. Maskey value_add_escapes(valstr[i], evalstr);
7026ba597c5SAnurag S. Maskey (void) fprintf(fp, "%c%s",
7036ba597c5SAnurag S. Maskey NWAM_FILE_VALUE_DELIMITER, evalstr);
7046ba597c5SAnurag S. Maskey }
7056ba597c5SAnurag S. Maskey break;
7066ba597c5SAnurag S. Maskey default:
7076ba597c5SAnurag S. Maskey nwam_value_free(val);
7086ba597c5SAnurag S. Maskey return (NWAM_INVALID_ARG);
7096ba597c5SAnurag S. Maskey }
7106ba597c5SAnurag S. Maskey nwam_value_free(val);
7116ba597c5SAnurag S. Maskey (void) fprintf(fp, "%c", NWAM_FILE_PROP_DELIMITER);
7126ba597c5SAnurag S. Maskey
7136ba597c5SAnurag S. Maskey lastpropname = propname;
7146ba597c5SAnurag S. Maskey
7156ba597c5SAnurag S. Maskey }
7166ba597c5SAnurag S. Maskey (void) fprintf(fp, "\n");
7176ba597c5SAnurag S. Maskey return (NWAM_SUCCESS);
7186ba597c5SAnurag S. Maskey }
7196ba597c5SAnurag S. Maskey
7206ba597c5SAnurag S. Maskey /*
7216ba597c5SAnurag S. Maskey * Write object specified by objname to file. If objname is NULL, objlist
7226ba597c5SAnurag S. Maskey * must be a list of lists, where each list corresponds to an
7236ba597c5SAnurag S. Maskey * object to write to the file. Otherwise objlist should point to a list of
7246ba597c5SAnurag S. Maskey * properties for the object specified by objname. The write operation is
7256ba597c5SAnurag S. Maskey * first done to filename.new, and if this succeeds, the file is renamed to
7266ba597c5SAnurag S. Maskey * filename. Since rename(2) is atomic, this approach guarantees a complete
7276ba597c5SAnurag S. Maskey * configuration will end up in filename as a result of an aborted operation.
7286ba597c5SAnurag S. Maskey */
7296ba597c5SAnurag S. Maskey nwam_error_t
nwam_write_object_to_files_backend(const char * filename,const char * objname,uint64_t flags,void * objlist)7306ba597c5SAnurag S. Maskey nwam_write_object_to_files_backend(const char *filename, const char *objname,
7316ba597c5SAnurag S. Maskey uint64_t flags, void *objlist)
7326ba597c5SAnurag S. Maskey {
7336ba597c5SAnurag S. Maskey void *proplist;
7346ba597c5SAnurag S. Maskey char *currobjname, *lastobjname = NULL;
7356ba597c5SAnurag S. Maskey int fd, cmd;
7366ba597c5SAnurag S. Maskey nwam_error_t err = NWAM_SUCCESS;
7376ba597c5SAnurag S. Maskey char *dir;
7386ba597c5SAnurag S. Maskey char tmpfilename[MAXPATHLEN], filename_copy[MAXPATHLEN];
7396ba597c5SAnurag S. Maskey FILE *fp;
7406ba597c5SAnurag S. Maskey mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
7416ba597c5SAnurag S. Maskey mode_t dirmode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
7426ba597c5SAnurag S. Maskey struct flock fl = { F_WRLCK, SEEK_SET, 0, 0, 0};
7436ba597c5SAnurag S. Maskey struct flock fu = { F_UNLCK, SEEK_SET, 0, 0, 0};
7446ba597c5SAnurag S. Maskey
7456ba597c5SAnurag S. Maskey assert(filename != NULL);
7466ba597c5SAnurag S. Maskey
7476ba597c5SAnurag S. Maskey /* Create the directory in case it does not exist. */
7486ba597c5SAnurag S. Maskey (void) strlcpy(filename_copy, filename, MAXPATHLEN);
7496ba597c5SAnurag S. Maskey if ((dir = dirname(filename_copy)) == NULL)
7506ba597c5SAnurag S. Maskey return (nwam_errno_to_nwam_error(errno));
7516ba597c5SAnurag S. Maskey if (mkdir(dir, dirmode) != 0) {
7526ba597c5SAnurag S. Maskey if (errno != EEXIST)
7536ba597c5SAnurag S. Maskey return (nwam_errno_to_nwam_error(errno));
7546ba597c5SAnurag S. Maskey }
7556ba597c5SAnurag S. Maskey
7566ba597c5SAnurag S. Maskey (void) snprintf(tmpfilename, MAXPATHLEN, "%s.new", filename);
7576ba597c5SAnurag S. Maskey
7586ba597c5SAnurag S. Maskey if ((fd = open(tmpfilename, O_RDWR | O_CREAT | O_TRUNC, mode)) < 0)
7596ba597c5SAnurag S. Maskey return (nwam_errno_to_nwam_error(errno));
7606ba597c5SAnurag S. Maskey
7616ba597c5SAnurag S. Maskey if ((fp = fdopen(fd, "w")) == NULL) {
7626ba597c5SAnurag S. Maskey err = nwam_errno_to_nwam_error(errno);
7636ba597c5SAnurag S. Maskey goto done;
7646ba597c5SAnurag S. Maskey }
7656ba597c5SAnurag S. Maskey /*
7666ba597c5SAnurag S. Maskey * Need to lock filename.new to prevent multiple commits colliding
7676ba597c5SAnurag S. Maskey * at this point.
7686ba597c5SAnurag S. Maskey */
7696ba597c5SAnurag S. Maskey if (flags & NWAM_FLAG_BLOCKING)
7706ba597c5SAnurag S. Maskey cmd = F_SETLKW;
7716ba597c5SAnurag S. Maskey else
7726ba597c5SAnurag S. Maskey cmd = F_SETLK;
7736ba597c5SAnurag S. Maskey if (fcntl(fd, cmd, &fl) != 0) {
7746ba597c5SAnurag S. Maskey if (errno == EAGAIN)
7756ba597c5SAnurag S. Maskey return (NWAM_ENTITY_IN_USE);
7766ba597c5SAnurag S. Maskey else
7776ba597c5SAnurag S. Maskey return (NWAM_ERROR_INTERNAL);
7786ba597c5SAnurag S. Maskey }
7796ba597c5SAnurag S. Maskey
7806ba597c5SAnurag S. Maskey if (objname != NULL) {
7816ba597c5SAnurag S. Maskey /* Only one object to write */
7826ba597c5SAnurag S. Maskey err = nwam_object_to_line(fp, objname, objlist);
7836ba597c5SAnurag S. Maskey } else {
7846ba597c5SAnurag S. Maskey if (objlist == NULL) {
7856ba597c5SAnurag S. Maskey err = NWAM_SUCCESS;
7866ba597c5SAnurag S. Maskey goto done;
7876ba597c5SAnurag S. Maskey }
7886ba597c5SAnurag S. Maskey /* Otherwise, write each object in turn. */
7896ba597c5SAnurag S. Maskey while ((err = nwam_next_object_list(objlist, lastobjname,
7906ba597c5SAnurag S. Maskey &currobjname, &proplist)) == NWAM_SUCCESS) {
7916ba597c5SAnurag S. Maskey if ((err = nwam_object_to_line(fp, currobjname,
7926ba597c5SAnurag S. Maskey proplist)) != NWAM_SUCCESS)
7936ba597c5SAnurag S. Maskey break;
7946ba597c5SAnurag S. Maskey lastobjname = currobjname;
7956ba597c5SAnurag S. Maskey }
7966ba597c5SAnurag S. Maskey if (err == NWAM_LIST_END)
7976ba597c5SAnurag S. Maskey err = NWAM_SUCCESS;
7986ba597c5SAnurag S. Maskey }
7996ba597c5SAnurag S. Maskey done:
8006ba597c5SAnurag S. Maskey if (err == NWAM_SUCCESS) {
8016ba597c5SAnurag S. Maskey if (rename(tmpfilename, filename) == 0) {
8026ba597c5SAnurag S. Maskey (void) fcntl(fd, F_SETLKW, &fu);
8036ba597c5SAnurag S. Maskey (void) fclose(fp);
8046ba597c5SAnurag S. Maskey return (NWAM_SUCCESS);
8056ba597c5SAnurag S. Maskey } else {
8066ba597c5SAnurag S. Maskey err = nwam_errno_to_nwam_error(errno);
8076ba597c5SAnurag S. Maskey }
8086ba597c5SAnurag S. Maskey }
8096ba597c5SAnurag S. Maskey (void) fcntl(fd, F_SETLKW, &fu);
8106ba597c5SAnurag S. Maskey (void) fclose(fp);
8116ba597c5SAnurag S. Maskey (void) unlink(tmpfilename);
8126ba597c5SAnurag S. Maskey
8136ba597c5SAnurag S. Maskey return (err);
8146ba597c5SAnurag S. Maskey }
8156ba597c5SAnurag S. Maskey
8166ba597c5SAnurag S. Maskey /*
8176ba597c5SAnurag S. Maskey * Read in all objects from file and update object corresponding to objname
8186ba597c5SAnurag S. Maskey * with properties recorded in proplist, and then write results to filename.
8196ba597c5SAnurag S. Maskey * If objname is empty, no object needs to be updated. If proplist is NULL,
8206ba597c5SAnurag S. Maskey * object is to be removed (this is done by simply not adding it to the list
8216ba597c5SAnurag S. Maskey * of objects).
8226ba597c5SAnurag S. Maskey */
8236ba597c5SAnurag S. Maskey nwam_error_t
nwam_update_object_in_files_backend(char * filename,char * objname,uint64_t flags,void * proplist)8246ba597c5SAnurag S. Maskey nwam_update_object_in_files_backend(char *filename, char *objname,
8256ba597c5SAnurag S. Maskey uint64_t flags, void *proplist)
8266ba597c5SAnurag S. Maskey {
8276ba597c5SAnurag S. Maskey nwam_error_t err;
8286ba597c5SAnurag S. Maskey void *objlist, *objnamelist;
8296ba597c5SAnurag S. Maskey char **object_names;
8306ba597c5SAnurag S. Maskey nwam_value_t value = NULL;
8316ba597c5SAnurag S. Maskey uint_t i, num_objects;
8326ba597c5SAnurag S. Maskey
8336ba597c5SAnurag S. Maskey assert(filename != NULL);
8346ba597c5SAnurag S. Maskey
8356ba597c5SAnurag S. Maskey /* If we find existing object, fail if creation was specified */
8366ba597c5SAnurag S. Maskey if (flags & NWAM_FLAG_CREATE) {
8376ba597c5SAnurag S. Maskey char discard_objname[NWAM_MAX_NAME_LEN];
8386ba597c5SAnurag S. Maskey void *discard_objlist;
8396ba597c5SAnurag S. Maskey
8406ba597c5SAnurag S. Maskey (void) strlcpy(discard_objname, objname,
8416ba597c5SAnurag S. Maskey sizeof (discard_objname));
8426ba597c5SAnurag S. Maskey if ((err = nwam_read_object_from_files_backend(filename,
8436ba597c5SAnurag S. Maskey discard_objname, 0, &discard_objlist)) == NWAM_SUCCESS) {
8446ba597c5SAnurag S. Maskey nwam_free_object_list(discard_objlist);
8456ba597c5SAnurag S. Maskey return (NWAM_ENTITY_EXISTS);
8466ba597c5SAnurag S. Maskey }
8476ba597c5SAnurag S. Maskey }
8486ba597c5SAnurag S. Maskey
8496ba597c5SAnurag S. Maskey /* Get existing list of object names (if any) */
8506ba597c5SAnurag S. Maskey err = nwam_read_object_from_files_backend(filename, NULL, flags,
8516ba597c5SAnurag S. Maskey &objnamelist);
8526ba597c5SAnurag S. Maskey switch (err) {
8536ba597c5SAnurag S. Maskey case NWAM_SUCCESS:
8546ba597c5SAnurag S. Maskey /*
8556ba597c5SAnurag S. Maskey * For each object name on list other than the one to be
8566ba597c5SAnurag S. Maskey * updated, add an object list consisting of its properties.
8576ba597c5SAnurag S. Maskey * The object to be updated (if any) will be added below.
8586ba597c5SAnurag S. Maskey */
8596ba597c5SAnurag S. Maskey if ((err = nwam_alloc_object_list(&objlist)) != NWAM_SUCCESS) {
8606ba597c5SAnurag S. Maskey nwam_free_object_list(objnamelist);
8616ba597c5SAnurag S. Maskey return (err);
8626ba597c5SAnurag S. Maskey }
8636ba597c5SAnurag S. Maskey if ((err = nwam_get_prop_value(objnamelist,
8646ba597c5SAnurag S. Maskey NWAM_OBJECT_NAMES_STRING, &value)) != NWAM_SUCCESS ||
8656ba597c5SAnurag S. Maskey (err = nwam_value_get_string_array(value, &object_names,
8666ba597c5SAnurag S. Maskey &num_objects)) != NWAM_SUCCESS) {
8676ba597c5SAnurag S. Maskey nwam_value_free(value);
8686ba597c5SAnurag S. Maskey nwam_free_object_list(objnamelist);
8696ba597c5SAnurag S. Maskey nwam_free_object_list(objlist);
8706ba597c5SAnurag S. Maskey return (err);
8716ba597c5SAnurag S. Maskey }
8726ba597c5SAnurag S. Maskey nwam_free_object_list(objnamelist);
8736ba597c5SAnurag S. Maskey
8746ba597c5SAnurag S. Maskey for (i = 0; i < num_objects; i++) {
8756ba597c5SAnurag S. Maskey void *oproplist = NULL;
8766ba597c5SAnurag S. Maskey
8776ba597c5SAnurag S. Maskey if (objname != NULL &&
8786ba597c5SAnurag S. Maskey strcmp(objname, object_names[i]) == 0)
8796ba597c5SAnurag S. Maskey continue;
8806ba597c5SAnurag S. Maskey
8816ba597c5SAnurag S. Maskey if ((err = nwam_read_object_from_files_backend(filename,
8826ba597c5SAnurag S. Maskey object_names[i], flags, &oproplist))
8836ba597c5SAnurag S. Maskey != NWAM_SUCCESS ||
8846ba597c5SAnurag S. Maskey (err = nwam_object_list_add_object_list(objlist,
8856ba597c5SAnurag S. Maskey object_names[i], oproplist)) != NWAM_SUCCESS) {
8866ba597c5SAnurag S. Maskey nwam_free_object_list(oproplist);
8876ba597c5SAnurag S. Maskey nwam_free_object_list(objlist);
8886ba597c5SAnurag S. Maskey nwam_value_free(value);
8896ba597c5SAnurag S. Maskey return (err);
8906ba597c5SAnurag S. Maskey }
8916ba597c5SAnurag S. Maskey nwam_free_object_list(oproplist);
8926ba597c5SAnurag S. Maskey }
8936ba597c5SAnurag S. Maskey nwam_value_free(value);
8946ba597c5SAnurag S. Maskey break;
8956ba597c5SAnurag S. Maskey
8966ba597c5SAnurag S. Maskey case NWAM_ENTITY_NOT_FOUND:
8976ba597c5SAnurag S. Maskey /*
8986ba597c5SAnurag S. Maskey * Just need to write/remove this single object.
8996ba597c5SAnurag S. Maskey */
9006ba597c5SAnurag S. Maskey return (nwam_write_object_to_files_backend(filename, objname,
9016ba597c5SAnurag S. Maskey flags, proplist));
9026ba597c5SAnurag S. Maskey
9036ba597c5SAnurag S. Maskey default:
9046ba597c5SAnurag S. Maskey return (err);
9056ba597c5SAnurag S. Maskey }
9066ba597c5SAnurag S. Maskey
9076ba597c5SAnurag S. Maskey /*
9086ba597c5SAnurag S. Maskey * Add the object to be updated to our list of objects if the
9096ba597c5SAnurag S. Maskey * property list is non-NULL (NULL signifies remove the object).
9106ba597c5SAnurag S. Maskey */
9116ba597c5SAnurag S. Maskey if (objname != NULL && proplist != NULL) {
9126ba597c5SAnurag S. Maskey if ((err = nwam_object_list_add_object_list(objlist,
9136ba597c5SAnurag S. Maskey (char *)objname, proplist)) != NWAM_SUCCESS) {
9146ba597c5SAnurag S. Maskey nwam_free_object_list(objlist);
9156ba597c5SAnurag S. Maskey return (err);
9166ba597c5SAnurag S. Maskey }
9176ba597c5SAnurag S. Maskey }
9186ba597c5SAnurag S. Maskey
9196ba597c5SAnurag S. Maskey err = nwam_write_object_to_files_backend(filename, NULL, flags,
9206ba597c5SAnurag S. Maskey objlist);
9216ba597c5SAnurag S. Maskey
9226ba597c5SAnurag S. Maskey nwam_free_object_list(objlist);
9236ba597c5SAnurag S. Maskey
9246ba597c5SAnurag S. Maskey return (err);
9256ba597c5SAnurag S. Maskey }
9266ba597c5SAnurag S. Maskey
9276ba597c5SAnurag S. Maskey /*
9286ba597c5SAnurag S. Maskey * Remove specified object from file by reading in the list of objects,
9296ba597c5SAnurag S. Maskey * removing objname and writing the remainder.
9306ba597c5SAnurag S. Maskey */
9316ba597c5SAnurag S. Maskey nwam_error_t
nwam_remove_object_from_files_backend(char * filename,char * objname,uint64_t flags)9326ba597c5SAnurag S. Maskey nwam_remove_object_from_files_backend(char *filename, char *objname,
9336ba597c5SAnurag S. Maskey uint64_t flags)
9346ba597c5SAnurag S. Maskey {
9356ba597c5SAnurag S. Maskey int uerr;
9366ba597c5SAnurag S. Maskey
9376ba597c5SAnurag S. Maskey assert(filename != NULL);
9386ba597c5SAnurag S. Maskey
9396ba597c5SAnurag S. Maskey if (objname == NULL) {
9406ba597c5SAnurag S. Maskey /*
9416ba597c5SAnurag S. Maskey * NULL objname signifies remove file.
9426ba597c5SAnurag S. Maskey */
9436ba597c5SAnurag S. Maskey uerr = unlink(filename);
9446ba597c5SAnurag S. Maskey if (uerr != 0)
9456ba597c5SAnurag S. Maskey return (nwam_errno_to_nwam_error(errno));
9466ba597c5SAnurag S. Maskey return (NWAM_SUCCESS);
9476ba597c5SAnurag S. Maskey }
9486ba597c5SAnurag S. Maskey
9496ba597c5SAnurag S. Maskey return (nwam_update_object_in_files_backend(filename, objname, flags,
9506ba597c5SAnurag S. Maskey NULL));
9516ba597c5SAnurag S. Maskey }
952