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
= reallocarray(valbool
, nelem
,
260 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
= reallocarray(valint
, nelem
,
278 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
= reallocarray(valuint
, nelem
,
296 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
= reallocarray(valstr
, nelem
,
314 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
= reallocarray(ncpfiles
, *num_filesp
,
397 if (*num_filesp
!= 0 && *ncpfilesp
== NULL
)
398 err
= NWAM_NO_MEMORY
;
404 * Read object specified by objname from file, converting it to
405 * an object list. If filename is NULL, a list of configuration object
406 * containers is returned, represented as an object lists with elements "enms"
407 * "locs" and "ncps". Each of these is a list of configuration files for each
408 * object. This corresponds to the enm.conf file, loc.conf file and list of
409 * ncp conf files. If objname is NULL, read all objects, and create
410 * an nvlist with one element - "object-list" - which has as its values
411 * the names of the objects found. Otherwise obj points to an object list
412 * of properties for the first object in the file that case-insensitively
413 * matches objname. We write the found name into objname so that it can be
414 * returned to the caller (and set in the object handle).
418 nwam_read_object_from_files_backend(char *filename
, char *objname
,
419 uint64_t flags
, void *obj
)
421 char line
[NWAM_FILE_LINE_MAX
];
422 char *cp
, *foundobjname
, **objnames
= NULL
, **ncpfiles
= NULL
;
423 uint_t num_files
= 0;
426 void *objlist
= NULL
, *proplist
= NULL
;
428 nwam_value_t objnamesval
= NULL
;
432 *((char **)obj
) = NULL
;
434 if (filename
== NULL
) {
435 nwam_value_t enmval
= NULL
, locval
= NULL
, ncpval
= NULL
;
438 * When the filename is not specified, it signifies a
439 * request for the list of configuration object containers -
440 * in this case files.
442 * A list of all object files is returned. For ENMs
443 * and locations, only the default loc.conf and enm.conf
444 * files are used, but for NCPs we need to walk the
445 * files in the NWAM directory retrieving each one that
446 * matches the NCP pattern.
448 if ((err
= nwam_alloc_object_list(&objlist
)) != NWAM_SUCCESS
)
451 if ((err
= nwam_value_create_string(NWAM_ENM_CONF_FILE
,
452 &enmval
)) != NWAM_SUCCESS
||
453 (err
= nwam_value_create_string(NWAM_LOC_CONF_FILE
,
454 &locval
)) != NWAM_SUCCESS
||
455 (err
= nwam_set_prop_value(objlist
, NWAM_ENM_OBJECT_STRING
,
456 enmval
)) != NWAM_SUCCESS
||
457 (err
= nwam_set_prop_value(objlist
, NWAM_LOC_OBJECT_STRING
,
458 locval
)) != NWAM_SUCCESS
)
459 goto done_with_containers
;
462 * Construct NCP list by finding all files in NWAM directory
463 * that match the NCP filename format.
465 if ((err
= create_ncp_file_list(&ncpfiles
, &num_files
))
467 goto done_with_containers
;
469 if ((err
= nwam_value_create_string_array(ncpfiles
, num_files
,
470 &ncpval
)) == NWAM_SUCCESS
) {
471 err
= nwam_set_prop_value(objlist
,
472 NWAM_NCP_OBJECT_STRING
, ncpval
);
475 done_with_containers
:
476 nwam_value_free(enmval
);
477 nwam_value_free(locval
);
478 nwam_value_free(ncpval
);
479 if (ncpfiles
!= NULL
) {
480 for (j
= 0; j
< num_files
; j
++)
484 if (err
!= NWAM_SUCCESS
)
485 nwam_free_object_list(objlist
);
487 *((char **)obj
) = objlist
;
491 if (objname
== NULL
) {
492 /* Allocate string array to store object names */
493 if ((objnames
= calloc(NWAM_MAX_NUM_OBJECTS
, sizeof (char *)))
495 return (NWAM_NO_MEMORY
);
498 fp
= fopen(filename
, "r");
500 if (errno
!= ENOENT
) {
503 return (NWAM_ERROR_INTERNAL
);
507 * Check NCP file list in case filename passed in was derived
508 * from a case-insensitive NCP name.
510 if ((err
= create_ncp_file_list(&ncpfiles
, &num_files
))
512 for (j
= 0; j
< num_files
; j
++) {
513 if (strcasecmp(ncpfiles
[j
], filename
) == 0) {
514 fp
= fopen(ncpfiles
[j
], "r");
516 /* Copy real filename back */
517 (void) strlcpy(filename
,
519 strlen(filename
) + 1);
524 for (j
= 0; j
< num_files
; j
++)
528 /* Return NOT_FOUND if file not found */
532 return (NWAM_ENTITY_NOT_FOUND
);
536 while (fgets(line
, sizeof (line
), fp
) != NULL
) {
537 if (line
[strlen(line
) - 1] == '\n')
538 line
[strlen(line
) - 1] = '\0';
545 if (*cp
== '#' || *cp
== '\0')
548 if ((err
= nwam_line_to_object(cp
, &foundobjname
, &proplist
))
552 if (objname
!= NULL
) {
554 * Is this the specified object? If so set objname and
557 if (strcasecmp(objname
, foundobjname
) == 0) {
558 *((char **)obj
) = proplist
;
559 (void) strlcpy(objname
, foundobjname
,
563 nwam_free_object_list(proplist
);
566 objnames
[i
] = strdup(foundobjname
);
567 nwam_free_object_list(proplist
);
568 if (objnames
[i
] == NULL
) {
569 err
= NWAM_NO_MEMORY
;
576 if (objname
== NULL
) {
578 * Allocate object list with one value named
579 * NWAM_OBJECT_NAMES_STRING - it's values are the names of
582 if ((err
= nwam_alloc_object_list(&objlist
)) == NWAM_SUCCESS
&&
583 (err
= nwam_value_create_string_array(objnames
, i
,
584 &objnamesval
)) == NWAM_SUCCESS
) {
585 err
= nwam_set_prop_value(objlist
,
586 NWAM_OBJECT_NAMES_STRING
, objnamesval
);
595 * We're done, either we have success, and return our object list
596 * containing object names, or we have failure and we need to free
599 if (objname
== NULL
) {
600 for (j
= 0; j
< i
; j
++)
603 nwam_value_free(objnamesval
);
604 if (err
== NWAM_SUCCESS
) {
605 *((char **)obj
) = objlist
;
607 *((char **)obj
) = NULL
;
608 nwam_free_object_list(objlist
);
611 /* Check if to-be-read object was not found */
612 if (*((char **)obj
) == NULL
&& err
== NWAM_SUCCESS
)
613 return (NWAM_ENTITY_NOT_FOUND
);
620 nwam_object_to_line(FILE *fp
, const char *objname
, void *proplist
)
622 char *propname
, *lastpropname
= NULL
;
629 nwam_value_type_t type
;
631 (void) fprintf(fp
, "%s\t", objname
);
633 while (nwam_next_object_prop(proplist
, lastpropname
, &propname
, &val
)
636 (void) fprintf(fp
, "%s%c", propname
, NWAM_FILE_PROP_ASSIGN
);
638 if (nwam_value_get_type(val
, &type
) != NWAM_SUCCESS
)
639 return (NWAM_INVALID_ARG
);
642 case NWAM_VALUE_TYPE_BOOLEAN
:
643 (void) fprintf(fp
, "%s",
644 nwam_value_type_to_string(NWAM_VALUE_TYPE_BOOLEAN
));
645 if (nwam_value_get_boolean_array(val
, &valbool
, &nelem
)
647 nwam_value_free(val
);
648 return (NWAM_INVALID_ARG
);
650 for (i
= 0; i
< nelem
; i
++) {
651 (void) fprintf(fp
, "%c",
652 NWAM_FILE_VALUE_DELIMITER
);
655 NWAM_FILE_BOOLEAN_TRUE
);
658 NWAM_FILE_BOOLEAN_FALSE
);
663 case NWAM_VALUE_TYPE_INT64
:
664 (void) fprintf(fp
, "%s",
665 nwam_value_type_to_string(NWAM_VALUE_TYPE_INT64
));
666 if (nwam_value_get_int64_array(val
, &valint
, &nelem
)
668 nwam_value_free(val
);
669 return (NWAM_INVALID_ARG
);
671 for (i
= 0; i
< nelem
; i
++) {
672 (void) fprintf(fp
, "%c%lld",
673 NWAM_FILE_VALUE_DELIMITER
, valint
[i
]);
677 case NWAM_VALUE_TYPE_UINT64
:
678 (void) fprintf(fp
, "%s",
679 nwam_value_type_to_string(NWAM_VALUE_TYPE_UINT64
));
680 if (nwam_value_get_uint64_array(val
, &valuint
, &nelem
)
682 nwam_value_free(val
);
683 return (NWAM_INVALID_ARG
);
685 for (i
= 0; i
< nelem
; i
++) {
686 (void) fprintf(fp
, "%c%lld",
687 NWAM_FILE_VALUE_DELIMITER
, valuint
[i
]);
691 case NWAM_VALUE_TYPE_STRING
:
692 (void) fprintf(fp
, "%s",
693 nwam_value_type_to_string(NWAM_VALUE_TYPE_STRING
));
694 if (nwam_value_get_string_array(val
, &valstr
, &nelem
)
696 nwam_value_free(val
);
697 return (NWAM_INVALID_ARG
);
699 for (i
= 0; i
< nelem
; i
++) {
700 char evalstr
[NWAM_MAX_VALUE_LEN
];
701 /* Add escape chars as necessary */
702 value_add_escapes(valstr
[i
], evalstr
);
703 (void) fprintf(fp
, "%c%s",
704 NWAM_FILE_VALUE_DELIMITER
, evalstr
);
708 nwam_value_free(val
);
709 return (NWAM_INVALID_ARG
);
711 nwam_value_free(val
);
712 (void) fprintf(fp
, "%c", NWAM_FILE_PROP_DELIMITER
);
714 lastpropname
= propname
;
717 (void) fprintf(fp
, "\n");
718 return (NWAM_SUCCESS
);
722 * Write object specified by objname to file. If objname is NULL, objlist
723 * must be a list of lists, where each list corresponds to an
724 * object to write to the file. Otherwise objlist should point to a list of
725 * properties for the object specified by objname. The write operation is
726 * first done to filename.new, and if this succeeds, the file is renamed to
727 * filename. Since rename(2) is atomic, this approach guarantees a complete
728 * configuration will end up in filename as a result of an aborted operation.
731 nwam_write_object_to_files_backend(const char *filename
, const char *objname
,
732 uint64_t flags
, void *objlist
)
735 char *currobjname
, *lastobjname
= NULL
;
737 nwam_error_t err
= NWAM_SUCCESS
;
739 char tmpfilename
[MAXPATHLEN
], filename_copy
[MAXPATHLEN
];
741 mode_t mode
= S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
;
742 mode_t dirmode
= S_IRWXU
| S_IRGRP
| S_IXGRP
| S_IROTH
| S_IXOTH
;
743 struct flock fl
= { F_WRLCK
, SEEK_SET
, 0, 0, 0};
744 struct flock fu
= { F_UNLCK
, SEEK_SET
, 0, 0, 0};
746 assert(filename
!= NULL
);
748 /* Create the directory in case it does not exist. */
749 (void) strlcpy(filename_copy
, filename
, MAXPATHLEN
);
750 if ((dir
= dirname(filename_copy
)) == NULL
)
751 return (nwam_errno_to_nwam_error(errno
));
752 if (mkdir(dir
, dirmode
) != 0) {
754 return (nwam_errno_to_nwam_error(errno
));
757 (void) snprintf(tmpfilename
, MAXPATHLEN
, "%s.new", filename
);
759 if ((fd
= open(tmpfilename
, O_RDWR
| O_CREAT
| O_TRUNC
, mode
)) < 0)
760 return (nwam_errno_to_nwam_error(errno
));
762 if ((fp
= fdopen(fd
, "w")) == NULL
) {
763 err
= nwam_errno_to_nwam_error(errno
);
767 * Need to lock filename.new to prevent multiple commits colliding
770 if (flags
& NWAM_FLAG_BLOCKING
)
774 if (fcntl(fd
, cmd
, &fl
) != 0) {
776 return (NWAM_ENTITY_IN_USE
);
778 return (NWAM_ERROR_INTERNAL
);
781 if (objname
!= NULL
) {
782 /* Only one object to write */
783 err
= nwam_object_to_line(fp
, objname
, objlist
);
785 if (objlist
== NULL
) {
789 /* Otherwise, write each object in turn. */
790 while ((err
= nwam_next_object_list(objlist
, lastobjname
,
791 &currobjname
, &proplist
)) == NWAM_SUCCESS
) {
792 if ((err
= nwam_object_to_line(fp
, currobjname
,
793 proplist
)) != NWAM_SUCCESS
)
795 lastobjname
= currobjname
;
797 if (err
== NWAM_LIST_END
)
801 if (err
== NWAM_SUCCESS
) {
802 if (rename(tmpfilename
, filename
) == 0) {
803 (void) fcntl(fd
, F_SETLKW
, &fu
);
805 return (NWAM_SUCCESS
);
807 err
= nwam_errno_to_nwam_error(errno
);
810 (void) fcntl(fd
, F_SETLKW
, &fu
);
812 (void) unlink(tmpfilename
);
818 * Read in all objects from file and update object corresponding to objname
819 * with properties recorded in proplist, and then write results to filename.
820 * If objname is empty, no object needs to be updated. If proplist is NULL,
821 * object is to be removed (this is done by simply not adding it to the list
825 nwam_update_object_in_files_backend(char *filename
, char *objname
,
826 uint64_t flags
, void *proplist
)
829 void *objlist
, *objnamelist
;
831 nwam_value_t value
= NULL
;
832 uint_t i
, num_objects
;
834 assert(filename
!= NULL
);
836 /* If we find existing object, fail if creation was specified */
837 if (flags
& NWAM_FLAG_CREATE
) {
838 char discard_objname
[NWAM_MAX_NAME_LEN
];
839 void *discard_objlist
;
841 (void) strlcpy(discard_objname
, objname
,
842 sizeof (discard_objname
));
843 if ((err
= nwam_read_object_from_files_backend(filename
,
844 discard_objname
, 0, &discard_objlist
)) == NWAM_SUCCESS
) {
845 nwam_free_object_list(discard_objlist
);
846 return (NWAM_ENTITY_EXISTS
);
850 /* Get existing list of object names (if any) */
851 err
= nwam_read_object_from_files_backend(filename
, NULL
, flags
,
856 * For each object name on list other than the one to be
857 * updated, add an object list consisting of its properties.
858 * The object to be updated (if any) will be added below.
860 if ((err
= nwam_alloc_object_list(&objlist
)) != NWAM_SUCCESS
) {
861 nwam_free_object_list(objnamelist
);
864 if ((err
= nwam_get_prop_value(objnamelist
,
865 NWAM_OBJECT_NAMES_STRING
, &value
)) != NWAM_SUCCESS
||
866 (err
= nwam_value_get_string_array(value
, &object_names
,
867 &num_objects
)) != NWAM_SUCCESS
) {
868 nwam_value_free(value
);
869 nwam_free_object_list(objnamelist
);
870 nwam_free_object_list(objlist
);
873 nwam_free_object_list(objnamelist
);
875 for (i
= 0; i
< num_objects
; i
++) {
876 void *oproplist
= NULL
;
878 if (objname
!= NULL
&&
879 strcmp(objname
, object_names
[i
]) == 0)
882 if ((err
= nwam_read_object_from_files_backend(filename
,
883 object_names
[i
], flags
, &oproplist
))
885 (err
= nwam_object_list_add_object_list(objlist
,
886 object_names
[i
], oproplist
)) != NWAM_SUCCESS
) {
887 nwam_free_object_list(oproplist
);
888 nwam_free_object_list(objlist
);
889 nwam_value_free(value
);
892 nwam_free_object_list(oproplist
);
894 nwam_value_free(value
);
897 case NWAM_ENTITY_NOT_FOUND
:
899 * Just need to write/remove this single object.
901 return (nwam_write_object_to_files_backend(filename
, objname
,
909 * Add the object to be updated to our list of objects if the
910 * property list is non-NULL (NULL signifies remove the object).
912 if (objname
!= NULL
&& proplist
!= NULL
) {
913 if ((err
= nwam_object_list_add_object_list(objlist
,
914 (char *)objname
, proplist
)) != NWAM_SUCCESS
) {
915 nwam_free_object_list(objlist
);
920 err
= nwam_write_object_to_files_backend(filename
, NULL
, flags
,
923 nwam_free_object_list(objlist
);
929 * Remove specified object from file by reading in the list of objects,
930 * removing objname and writing the remainder.
933 nwam_remove_object_from_files_backend(char *filename
, char *objname
,
938 assert(filename
!= NULL
);
940 if (objname
== NULL
) {
942 * NULL objname signifies remove file.
944 uerr
= unlink(filename
);
946 return (nwam_errno_to_nwam_error(errno
));
947 return (NWAM_SUCCESS
);
950 return (nwam_update_object_in_files_backend(filename
, objname
, flags
,