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 * 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 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 * 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 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 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 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 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 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 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 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