4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
33 #include <sys/param.h>
34 #include <sys/types.h>
41 #include "libnwam_impl.h"
42 #include <libnwam_priv.h>
46 * Implementation of files backend for libnwam configuration objects.
47 * /etc/dladm/datalink.conf-like format is used.
49 #define NWAM_FILE_LINE_MAX 2048
50 #define NWAM_FILE_PROP_ESCAPE '\\'
51 #define NWAM_FILE_PROP_DELIMITER ';'
52 #define NWAM_FILE_PROP_ASSIGN '='
53 #define NWAM_FILE_VALUE_DELIMITER ','
54 #define NWAM_FILE_BOOLEAN_TRUE "true"
55 #define NWAM_FILE_BOOLEAN_FALSE "false"
58 * strtok_r-like function that takes a string, finds the next unescaped
59 * delimiter char after in, nullifies it and sets nextp to point to the
60 * remaining string (if any). Returns in, setting nextp to NULL if no such
64 nwam_tokenize_by_unescaped_delim(char *in
, char delim
, char **nextp
)
66 boolean_t escaped
= B_FALSE
;
74 for (*nextp
= in
; (*nextp
- in
) < strlen(in
); (*nextp
)++) {
75 if ((*nextp
)[0] == NWAM_FILE_PROP_ESCAPE
) {
77 } else if (!escaped
&& (*nextp
)[0] == delim
) {
78 /* Nullify delimiter */
81 * If more string left to go, nextp points to string
82 * after delimiter, otherwise NULL.
85 *nextp
= ((*nextp
- in
) < totlen
) ? (*nextp
) : NULL
;
95 /* Add escape chars to value string */
97 value_add_escapes(char *in
, char *out
)
102 * It is safe to use strlen() as we sanitycheck string length on value
103 * creation, so no string longer than NWAM_MAX_VALUE_LEN is accepted.
105 for (i
= 0; i
< strlen(in
); i
++) {
107 case NWAM_FILE_VALUE_DELIMITER
:
108 case NWAM_FILE_PROP_DELIMITER
:
109 case NWAM_FILE_PROP_ESCAPE
:
110 out
[j
++] = NWAM_FILE_PROP_ESCAPE
;
122 value_remove_escapes(char *in
)
127 if ((out
= strdup(in
)) == NULL
)
131 * It is safe to use strlen() as we sanitycheck string length on value
132 * creation (i.e. before they are written to the file), so no string
133 * longer than NWAM_MAX_VALUE_LEN is accepted.
135 for (i
= 0; i
< strlen(in
); i
++) {
136 if (in
[i
] == NWAM_FILE_PROP_ESCAPE
)
147 * Parse line into name and object list of properties.
148 * Each line has the format:
150 * objname [prop=type:val1[,val2..];..]
153 nwam_line_to_object(char *line
, char **objname
, void *proplist
)
155 char *next
= line
, *prop
, *nextprop
, *propname
, *proptypestr
, *nextval
;
156 char **valstr
, **newvalstr
;
157 boolean_t
*valbool
, *newvalbool
;
158 int64_t *valint
, *newvalint
;
159 uint64_t *valuint
, *newvaluint
;
161 nwam_value_type_t proptype
;
162 nwam_value_t val
= NULL
;
165 if ((err
= nwam_alloc_object_list(proplist
)) != NWAM_SUCCESS
)
170 if ((*objname
= nwam_tokenize_by_unescaped_delim(line
, '\t', &prop
))
172 nwam_free_object_list(*((char **)proplist
));
173 return (NWAM_ENTITY_INVALID
);
176 while ((prop
= nwam_tokenize_by_unescaped_delim(prop
,
177 NWAM_FILE_PROP_DELIMITER
, &nextprop
)) != NULL
) {
179 * Parse property into name=type,val[,val]
181 if ((propname
= nwam_tokenize_by_unescaped_delim(prop
,
182 NWAM_FILE_PROP_ASSIGN
, &next
)) == NULL
||
183 (proptypestr
= nwam_tokenize_by_unescaped_delim(next
,
184 NWAM_FILE_VALUE_DELIMITER
, &next
)) == NULL
) {
185 nwam_free_object_list(*((char **)proplist
));
186 return (NWAM_ENTITY_INVALID
);
188 if ((proptype
= nwam_string_to_value_type(proptypestr
)) ==
189 NWAM_VALUE_TYPE_UNKNOWN
) {
190 nwam_free_object_list(*((char **)proplist
));
191 return (NWAM_ENTITY_INVALID
);
197 case NWAM_VALUE_TYPE_BOOLEAN
:
198 valbool
= calloc(NWAM_MAX_NUM_VALUES
,
201 case NWAM_VALUE_TYPE_INT64
:
202 valint
= calloc(NWAM_MAX_NUM_VALUES
,
205 case NWAM_VALUE_TYPE_UINT64
:
206 valuint
= calloc(NWAM_MAX_NUM_VALUES
,
209 case NWAM_VALUE_TYPE_STRING
:
210 valstr
= calloc(NWAM_MAX_NUM_VALUES
,
214 nwam_free_object_list(*((char **)proplist
));
215 return (NWAM_ENTITY_INVALID_VALUE
);
217 if (valbool
== NULL
&& valint
== NULL
&& valuint
== NULL
&&
219 /* Memory allocation failed */
220 nwam_free_object_list(*((char **)proplist
));
221 return (NWAM_NO_MEMORY
);
224 while ((nextval
= nwam_tokenize_by_unescaped_delim(next
,
225 NWAM_FILE_VALUE_DELIMITER
, &next
)) != NULL
) {
228 case NWAM_VALUE_TYPE_BOOLEAN
:
229 if (strncmp(nextval
, NWAM_FILE_BOOLEAN_TRUE
,
230 strlen(nextval
)) == 0) {
231 valbool
[nelem
- 1] = B_TRUE
;
232 } else if (strncmp(nextval
,
233 NWAM_FILE_BOOLEAN_FALSE
, strlen(nextval
))
235 valbool
[nelem
- 1] = B_FALSE
;
237 nwam_free_object_list
238 (*((char **)proplist
));
239 return (NWAM_ENTITY_INVALID_VALUE
);
242 case NWAM_VALUE_TYPE_INT64
:
243 valint
[nelem
- 1] = (int64_t)atoll(nextval
);
245 case NWAM_VALUE_TYPE_UINT64
:
246 valuint
[nelem
- 1] = (uint64_t)atoll(nextval
);
248 case NWAM_VALUE_TYPE_STRING
:
250 value_remove_escapes(nextval
);
253 nwam_free_object_list(*((char **)proplist
));
254 return (NWAM_ENTITY_INVALID_VALUE
);
258 case NWAM_VALUE_TYPE_BOOLEAN
:
259 if ((newvalbool
= realloc(valbool
,
260 nelem
* sizeof (boolean_t
))) == NULL
) {
261 nwam_free_object_list(*((char **)proplist
));
262 return (NWAM_NO_MEMORY
);
264 if ((err
= nwam_value_create_boolean_array(newvalbool
,
265 nelem
, &val
)) != NWAM_SUCCESS
||
266 (err
= nwam_set_prop_value(*((char **)proplist
),
267 propname
, val
)) != NWAM_SUCCESS
) {
269 nwam_value_free(val
);
270 nwam_free_object_list(*((char **)proplist
));
274 nwam_value_free(val
);
276 case NWAM_VALUE_TYPE_INT64
:
277 if ((newvalint
= realloc(valint
,
278 nelem
* sizeof (int64_t))) == NULL
) {
279 nwam_free_object_list(*((char **)proplist
));
280 return (NWAM_NO_MEMORY
);
282 if ((err
= nwam_value_create_int64_array(newvalint
,
283 nelem
, &val
)) != NWAM_SUCCESS
||
284 (err
= nwam_set_prop_value(*((char **)proplist
),
285 propname
, val
)) != NWAM_SUCCESS
) {
287 nwam_value_free(val
);
288 nwam_free_object_list(*((char **)proplist
));
292 nwam_value_free(val
);
294 case NWAM_VALUE_TYPE_UINT64
:
295 if ((newvaluint
= realloc(valuint
,
296 nelem
* sizeof (uint64_t))) == NULL
) {
297 nwam_free_object_list(*((char **)proplist
));
298 return (NWAM_NO_MEMORY
);
300 if ((err
= nwam_value_create_uint64_array(newvaluint
,
301 nelem
, &val
)) != NWAM_SUCCESS
||
302 (err
= nwam_set_prop_value(*((char **)proplist
),
303 propname
, val
)) != NWAM_SUCCESS
) {
305 nwam_value_free(val
);
306 nwam_free_object_list(*((char **)proplist
));
310 nwam_value_free(val
);
312 case NWAM_VALUE_TYPE_STRING
:
313 if ((newvalstr
= realloc(valstr
,
314 nelem
* sizeof (char *))) == NULL
) {
315 nwam_free_object_list(*((char **)proplist
));
316 return (NWAM_NO_MEMORY
);
318 if ((err
= nwam_value_create_string_array(newvalstr
,
319 nelem
, &val
)) != NWAM_SUCCESS
||
320 (err
= nwam_set_prop_value(*((char **)proplist
),
321 propname
, val
)) != NWAM_SUCCESS
) {
322 for (i
= 0; i
< nelem
; i
++)
325 nwam_value_free(val
);
326 nwam_free_object_list(*((char **)proplist
));
329 for (i
= 0; i
< nelem
; i
++)
332 nwam_value_free(val
);
338 return (NWAM_SUCCESS
);
342 * Create list of NCP files used for walk of NCPs and for case-insensitive
343 * matching of NCP name to file.
346 create_ncp_file_list(char ***ncpfilesp
, uint_t
*num_filesp
)
350 char *ncpname
, **ncpfiles
= NULL
;
351 nwam_error_t err
= NWAM_SUCCESS
;
354 ncpfiles
= calloc(NWAM_MAX_NUM_OBJECTS
, sizeof (char *));
355 if (ncpfiles
== NULL
)
356 return (NWAM_NO_MEMORY
);
360 * Construct NCP list by finding all files in NWAM directory
361 * that match the NCP filename format.
363 if ((dirp
= opendir(NWAM_CONF_DIR
)) == NULL
) {
364 err
= nwam_errno_to_nwam_error(errno
);
368 while ((dp
= readdir(dirp
)) != NULL
) {
371 /* Ensure filename is valid */
372 if (nwam_ncp_file_to_name(dp
->d_name
, &ncpname
) != NWAM_SUCCESS
)
375 filenamelen
= strlen(NWAM_CONF_DIR
) + strlen(dp
->d_name
) + 1;
376 if ((ncpfiles
[*num_filesp
] = malloc(filenamelen
)) == NULL
) {
377 err
= NWAM_NO_MEMORY
;
380 (void) strlcpy(ncpfiles
[*num_filesp
], NWAM_CONF_DIR
,
381 strlen(NWAM_CONF_DIR
) + 1);
382 (void) strlcpy(ncpfiles
[*num_filesp
] + strlen(NWAM_CONF_DIR
),
383 dp
->d_name
, filenamelen
- strlen(NWAM_CONF_DIR
));
388 (void) closedir(dirp
);
390 if (err
!= NWAM_SUCCESS
) {
391 for (i
= 0; i
< *num_filesp
; i
++)
395 *ncpfilesp
= realloc(ncpfiles
, sizeof (char *) * (*num_filesp
));
396 if (*num_filesp
!= 0 && *ncpfilesp
== NULL
)
397 err
= NWAM_NO_MEMORY
;
403 * Read object specified by objname from file, converting it to
404 * an object list. If filename is NULL, a list of configuration object
405 * containers is returned, represented as an object lists with elements "enms"
406 * "locs" and "ncps". Each of these is a list of configuration files for each
407 * object. This corresponds to the enm.conf file, loc.conf file and list of
408 * ncp conf files. If objname is NULL, read all objects, and create
409 * an nvlist with one element - "object-list" - which has as its values
410 * the names of the objects found. Otherwise obj points to an object list
411 * of properties for the first object in the file that case-insensitively
412 * matches objname. We write the found name into objname so that it can be
413 * returned to the caller (and set in the object handle).
417 nwam_read_object_from_files_backend(char *filename
, char *objname
,
418 uint64_t flags
, void *obj
)
420 char line
[NWAM_FILE_LINE_MAX
];
421 char *cp
, *foundobjname
, **objnames
= NULL
, **ncpfiles
= NULL
;
422 uint_t num_files
= 0;
425 void *objlist
= NULL
, *proplist
= NULL
;
427 nwam_value_t objnamesval
= NULL
;
431 *((char **)obj
) = NULL
;
433 if (filename
== NULL
) {
434 nwam_value_t enmval
= NULL
, locval
= NULL
, ncpval
= NULL
;
437 * When the filename is not specified, it signifies a
438 * request for the list of configuration object containers -
439 * in this case files.
441 * A list of all object files is returned. For ENMs
442 * and locations, only the default loc.conf and enm.conf
443 * files are used, but for NCPs we need to walk the
444 * files in the NWAM directory retrieving each one that
445 * matches the NCP pattern.
447 if ((err
= nwam_alloc_object_list(&objlist
)) != NWAM_SUCCESS
)
450 if ((err
= nwam_value_create_string(NWAM_ENM_CONF_FILE
,
451 &enmval
)) != NWAM_SUCCESS
||
452 (err
= nwam_value_create_string(NWAM_LOC_CONF_FILE
,
453 &locval
)) != NWAM_SUCCESS
||
454 (err
= nwam_set_prop_value(objlist
, NWAM_ENM_OBJECT_STRING
,
455 enmval
)) != NWAM_SUCCESS
||
456 (err
= nwam_set_prop_value(objlist
, NWAM_LOC_OBJECT_STRING
,
457 locval
)) != NWAM_SUCCESS
)
458 goto done_with_containers
;
461 * Construct NCP list by finding all files in NWAM directory
462 * that match the NCP filename format.
464 if ((err
= create_ncp_file_list(&ncpfiles
, &num_files
))
466 goto done_with_containers
;
468 if ((err
= nwam_value_create_string_array(ncpfiles
, num_files
,
469 &ncpval
)) == NWAM_SUCCESS
) {
470 err
= nwam_set_prop_value(objlist
,
471 NWAM_NCP_OBJECT_STRING
, ncpval
);
474 done_with_containers
:
475 nwam_value_free(enmval
);
476 nwam_value_free(locval
);
477 nwam_value_free(ncpval
);
478 if (ncpfiles
!= NULL
) {
479 for (j
= 0; j
< num_files
; j
++)
483 if (err
!= NWAM_SUCCESS
)
484 nwam_free_object_list(objlist
);
486 *((char **)obj
) = objlist
;
490 if (objname
== NULL
) {
491 /* Allocate string array to store object names */
492 if ((objnames
= calloc(NWAM_MAX_NUM_OBJECTS
, sizeof (char *)))
494 return (NWAM_NO_MEMORY
);
497 fp
= fopen(filename
, "r");
499 if (errno
!= ENOENT
) {
502 return (NWAM_ERROR_INTERNAL
);
506 * Check NCP file list in case filename passed in was derived
507 * from a case-insensitive NCP name.
509 if ((err
= create_ncp_file_list(&ncpfiles
, &num_files
))
511 for (j
= 0; j
< num_files
; j
++) {
512 if (strcasecmp(ncpfiles
[j
], filename
) == 0) {
513 fp
= fopen(ncpfiles
[j
], "r");
515 /* Copy real filename back */
516 (void) strlcpy(filename
,
518 strlen(filename
) + 1);
523 for (j
= 0; j
< num_files
; j
++)
527 /* Return NOT_FOUND if file not found */
531 return (NWAM_ENTITY_NOT_FOUND
);
535 while (fgets(line
, sizeof (line
), fp
) != NULL
) {
536 if (line
[strlen(line
) - 1] == '\n')
537 line
[strlen(line
) - 1] = '\0';
544 if (*cp
== '#' || *cp
== '\0')
547 if ((err
= nwam_line_to_object(cp
, &foundobjname
, &proplist
))
551 if (objname
!= NULL
) {
553 * Is this the specified object? If so set objname and
556 if (strcasecmp(objname
, foundobjname
) == 0) {
557 *((char **)obj
) = proplist
;
558 (void) strlcpy(objname
, foundobjname
,
562 nwam_free_object_list(proplist
);
565 objnames
[i
] = strdup(foundobjname
);
566 nwam_free_object_list(proplist
);
567 if (objnames
[i
] == NULL
) {
568 err
= NWAM_NO_MEMORY
;
575 if (objname
== NULL
) {
577 * Allocate object list with one value named
578 * NWAM_OBJECT_NAMES_STRING - it's values are the names of
581 if ((err
= nwam_alloc_object_list(&objlist
)) == NWAM_SUCCESS
&&
582 (err
= nwam_value_create_string_array(objnames
, i
,
583 &objnamesval
)) == NWAM_SUCCESS
) {
584 err
= nwam_set_prop_value(objlist
,
585 NWAM_OBJECT_NAMES_STRING
, objnamesval
);
594 * We're done, either we have success, and return our object list
595 * containing object names, or we have failure and we need to free
598 if (objname
== NULL
) {
599 for (j
= 0; j
< i
; j
++)
602 nwam_value_free(objnamesval
);
603 if (err
== NWAM_SUCCESS
) {
604 *((char **)obj
) = objlist
;
606 *((char **)obj
) = NULL
;
607 nwam_free_object_list(objlist
);
610 /* Check if to-be-read object was not found */
611 if (*((char **)obj
) == NULL
&& err
== NWAM_SUCCESS
)
612 return (NWAM_ENTITY_NOT_FOUND
);
619 nwam_object_to_line(FILE *fp
, const char *objname
, void *proplist
)
621 char *propname
, *lastpropname
= NULL
;
628 nwam_value_type_t type
;
630 (void) fprintf(fp
, "%s\t", objname
);
632 while (nwam_next_object_prop(proplist
, lastpropname
, &propname
, &val
)
635 (void) fprintf(fp
, "%s%c", propname
, NWAM_FILE_PROP_ASSIGN
);
637 if (nwam_value_get_type(val
, &type
) != NWAM_SUCCESS
)
638 return (NWAM_INVALID_ARG
);
641 case NWAM_VALUE_TYPE_BOOLEAN
:
642 (void) fprintf(fp
, "%s",
643 nwam_value_type_to_string(NWAM_VALUE_TYPE_BOOLEAN
));
644 if (nwam_value_get_boolean_array(val
, &valbool
, &nelem
)
646 nwam_value_free(val
);
647 return (NWAM_INVALID_ARG
);
649 for (i
= 0; i
< nelem
; i
++) {
650 (void) fprintf(fp
, "%c",
651 NWAM_FILE_VALUE_DELIMITER
);
654 NWAM_FILE_BOOLEAN_TRUE
);
657 NWAM_FILE_BOOLEAN_FALSE
);
662 case NWAM_VALUE_TYPE_INT64
:
663 (void) fprintf(fp
, "%s",
664 nwam_value_type_to_string(NWAM_VALUE_TYPE_INT64
));
665 if (nwam_value_get_int64_array(val
, &valint
, &nelem
)
667 nwam_value_free(val
);
668 return (NWAM_INVALID_ARG
);
670 for (i
= 0; i
< nelem
; i
++) {
671 (void) fprintf(fp
, "%c%lld",
672 NWAM_FILE_VALUE_DELIMITER
, valint
[i
]);
676 case NWAM_VALUE_TYPE_UINT64
:
677 (void) fprintf(fp
, "%s",
678 nwam_value_type_to_string(NWAM_VALUE_TYPE_UINT64
));
679 if (nwam_value_get_uint64_array(val
, &valuint
, &nelem
)
681 nwam_value_free(val
);
682 return (NWAM_INVALID_ARG
);
684 for (i
= 0; i
< nelem
; i
++) {
685 (void) fprintf(fp
, "%c%lld",
686 NWAM_FILE_VALUE_DELIMITER
, valuint
[i
]);
690 case NWAM_VALUE_TYPE_STRING
:
691 (void) fprintf(fp
, "%s",
692 nwam_value_type_to_string(NWAM_VALUE_TYPE_STRING
));
693 if (nwam_value_get_string_array(val
, &valstr
, &nelem
)
695 nwam_value_free(val
);
696 return (NWAM_INVALID_ARG
);
698 for (i
= 0; i
< nelem
; i
++) {
699 char evalstr
[NWAM_MAX_VALUE_LEN
];
700 /* Add escape chars as necessary */
701 value_add_escapes(valstr
[i
], evalstr
);
702 (void) fprintf(fp
, "%c%s",
703 NWAM_FILE_VALUE_DELIMITER
, evalstr
);
707 nwam_value_free(val
);
708 return (NWAM_INVALID_ARG
);
710 nwam_value_free(val
);
711 (void) fprintf(fp
, "%c", NWAM_FILE_PROP_DELIMITER
);
713 lastpropname
= propname
;
716 (void) fprintf(fp
, "\n");
717 return (NWAM_SUCCESS
);
721 * Write object specified by objname to file. If objname is NULL, objlist
722 * must be a list of lists, where each list corresponds to an
723 * object to write to the file. Otherwise objlist should point to a list of
724 * properties for the object specified by objname. The write operation is
725 * first done to filename.new, and if this succeeds, the file is renamed to
726 * filename. Since rename(2) is atomic, this approach guarantees a complete
727 * configuration will end up in filename as a result of an aborted operation.
730 nwam_write_object_to_files_backend(const char *filename
, const char *objname
,
731 uint64_t flags
, void *objlist
)
734 char *currobjname
, *lastobjname
= NULL
;
736 nwam_error_t err
= NWAM_SUCCESS
;
738 char tmpfilename
[MAXPATHLEN
], filename_copy
[MAXPATHLEN
];
740 mode_t mode
= S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
;
741 mode_t dirmode
= S_IRWXU
| S_IRGRP
| S_IXGRP
| S_IROTH
| S_IXOTH
;
742 struct flock fl
= { F_WRLCK
, SEEK_SET
, 0, 0, 0};
743 struct flock fu
= { F_UNLCK
, SEEK_SET
, 0, 0, 0};
745 assert(filename
!= NULL
);
747 /* Create the directory in case it does not exist. */
748 (void) strlcpy(filename_copy
, filename
, MAXPATHLEN
);
749 if ((dir
= dirname(filename_copy
)) == NULL
)
750 return (nwam_errno_to_nwam_error(errno
));
751 if (mkdir(dir
, dirmode
) != 0) {
753 return (nwam_errno_to_nwam_error(errno
));
756 (void) snprintf(tmpfilename
, MAXPATHLEN
, "%s.new", filename
);
758 if ((fd
= open(tmpfilename
, O_RDWR
| O_CREAT
| O_TRUNC
, mode
)) < 0)
759 return (nwam_errno_to_nwam_error(errno
));
761 if ((fp
= fdopen(fd
, "w")) == NULL
) {
762 err
= nwam_errno_to_nwam_error(errno
);
766 * Need to lock filename.new to prevent multiple commits colliding
769 if (flags
& NWAM_FLAG_BLOCKING
)
773 if (fcntl(fd
, cmd
, &fl
) != 0) {
775 return (NWAM_ENTITY_IN_USE
);
777 return (NWAM_ERROR_INTERNAL
);
780 if (objname
!= NULL
) {
781 /* Only one object to write */
782 err
= nwam_object_to_line(fp
, objname
, objlist
);
784 if (objlist
== NULL
) {
788 /* Otherwise, write each object in turn. */
789 while ((err
= nwam_next_object_list(objlist
, lastobjname
,
790 &currobjname
, &proplist
)) == NWAM_SUCCESS
) {
791 if ((err
= nwam_object_to_line(fp
, currobjname
,
792 proplist
)) != NWAM_SUCCESS
)
794 lastobjname
= currobjname
;
796 if (err
== NWAM_LIST_END
)
800 if (err
== NWAM_SUCCESS
) {
801 if (rename(tmpfilename
, filename
) == 0) {
802 (void) fcntl(fd
, F_SETLKW
, &fu
);
804 return (NWAM_SUCCESS
);
806 err
= nwam_errno_to_nwam_error(errno
);
809 (void) fcntl(fd
, F_SETLKW
, &fu
);
811 (void) unlink(tmpfilename
);
817 * Read in all objects from file and update object corresponding to objname
818 * with properties recorded in proplist, and then write results to filename.
819 * If objname is empty, no object needs to be updated. If proplist is NULL,
820 * object is to be removed (this is done by simply not adding it to the list
824 nwam_update_object_in_files_backend(char *filename
, char *objname
,
825 uint64_t flags
, void *proplist
)
828 void *objlist
, *objnamelist
;
830 nwam_value_t value
= NULL
;
831 uint_t i
, num_objects
;
833 assert(filename
!= NULL
);
835 /* If we find existing object, fail if creation was specified */
836 if (flags
& NWAM_FLAG_CREATE
) {
837 char discard_objname
[NWAM_MAX_NAME_LEN
];
838 void *discard_objlist
;
840 (void) strlcpy(discard_objname
, objname
,
841 sizeof (discard_objname
));
842 if ((err
= nwam_read_object_from_files_backend(filename
,
843 discard_objname
, 0, &discard_objlist
)) == NWAM_SUCCESS
) {
844 nwam_free_object_list(discard_objlist
);
845 return (NWAM_ENTITY_EXISTS
);
849 /* Get existing list of object names (if any) */
850 err
= nwam_read_object_from_files_backend(filename
, NULL
, flags
,
855 * For each object name on list other than the one to be
856 * updated, add an object list consisting of its properties.
857 * The object to be updated (if any) will be added below.
859 if ((err
= nwam_alloc_object_list(&objlist
)) != NWAM_SUCCESS
) {
860 nwam_free_object_list(objnamelist
);
863 if ((err
= nwam_get_prop_value(objnamelist
,
864 NWAM_OBJECT_NAMES_STRING
, &value
)) != NWAM_SUCCESS
||
865 (err
= nwam_value_get_string_array(value
, &object_names
,
866 &num_objects
)) != NWAM_SUCCESS
) {
867 nwam_value_free(value
);
868 nwam_free_object_list(objnamelist
);
869 nwam_free_object_list(objlist
);
872 nwam_free_object_list(objnamelist
);
874 for (i
= 0; i
< num_objects
; i
++) {
875 void *oproplist
= NULL
;
877 if (objname
!= NULL
&&
878 strcmp(objname
, object_names
[i
]) == 0)
881 if ((err
= nwam_read_object_from_files_backend(filename
,
882 object_names
[i
], flags
, &oproplist
))
884 (err
= nwam_object_list_add_object_list(objlist
,
885 object_names
[i
], oproplist
)) != NWAM_SUCCESS
) {
886 nwam_free_object_list(oproplist
);
887 nwam_free_object_list(objlist
);
888 nwam_value_free(value
);
891 nwam_free_object_list(oproplist
);
893 nwam_value_free(value
);
896 case NWAM_ENTITY_NOT_FOUND
:
898 * Just need to write/remove this single object.
900 return (nwam_write_object_to_files_backend(filename
, objname
,
908 * Add the object to be updated to our list of objects if the
909 * property list is non-NULL (NULL signifies remove the object).
911 if (objname
!= NULL
&& proplist
!= NULL
) {
912 if ((err
= nwam_object_list_add_object_list(objlist
,
913 (char *)objname
, proplist
)) != NWAM_SUCCESS
) {
914 nwam_free_object_list(objlist
);
919 err
= nwam_write_object_to_files_backend(filename
, NULL
, flags
,
922 nwam_free_object_list(objlist
);
928 * Remove specified object from file by reading in the list of objects,
929 * removing objname and writing the remainder.
932 nwam_remove_object_from_files_backend(char *filename
, char *objname
,
937 assert(filename
!= NULL
);
939 if (objname
== NULL
) {
941 * NULL objname signifies remove file.
943 uerr
= unlink(filename
);
945 return (nwam_errno_to_nwam_error(errno
));
946 return (NWAM_SUCCESS
);
949 return (nwam_update_object_in_files_backend(filename
, objname
, flags
,