2001-08-21 12:56:08 +00:00
/*
2007-07-08 22:51:20 +00:00
* Copyright ( C ) 2001 - 2004 Sistina Software , Inc . All rights reserved .
2011-05-24 13:53:26 +00:00
* Copyright ( C ) 2004 - 2011 Red Hat , Inc . All rights reserved .
2001-08-21 12:56:08 +00:00
*
2004-03-30 19:35:44 +00:00
* This file is part of LVM2 .
*
* This copyrighted material is made available to anyone wishing to use ,
* modify , copy , or redistribute it subject to the terms and conditions
2007-08-20 20:55:30 +00:00
* of the GNU Lesser General Public License v .2 .1 .
2004-03-30 19:35:44 +00:00
*
2007-08-20 20:55:30 +00:00
* You should have received a copy of the GNU Lesser General Public License
2004-03-30 19:35:44 +00:00
* along with this program ; if not , write to the Free Software Foundation ,
* Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
2001-08-21 12:56:08 +00:00
*/
2011-08-30 14:55:15 +00:00
2002-11-18 14:01:16 +00:00
# include "lib.h"
2011-08-30 14:55:15 +00:00
2002-11-18 14:01:16 +00:00
# include "config.h"
# include "crc.h"
# include "device.h"
2004-05-04 18:28:15 +00:00
# include "str_list.h"
# include "toolcontext.h"
2007-07-24 17:48:08 +00:00
# include "lvm-file.h"
2013-06-25 12:27:04 +02:00
# include "memlock.h"
2002-11-18 14:01:16 +00:00
2001-08-21 12:56:08 +00:00
# include <sys/stat.h>
# include <sys/mman.h>
# include <unistd.h>
# include <fcntl.h>
2011-12-18 21:56:03 +00:00
# include <assert.h>
2013-03-05 17:36:10 +01:00
# include <ctype.h>
2014-03-21 10:43:44 +01:00
# include <math.h>
# include <float.h>
2001-09-13 12:38:31 +00:00
2013-06-25 12:25:43 +02:00
static const char * _config_source_names [ ] = {
[ CONFIG_UNDEFINED ] = " undefined " ,
[ CONFIG_FILE ] = " file " ,
[ CONFIG_MERGED_FILES ] = " merged files " ,
[ CONFIG_STRING ] = " string " ,
2014-05-19 10:58:28 +02:00
[ CONFIG_PROFILE ] = " profile " ,
[ CONFIG_FILE_SPECIAL ] = " special purpose "
2013-06-25 12:25:43 +02:00
} ;
2011-12-18 21:56:03 +00:00
struct config_file {
off_t st_size ;
char * filename ;
int exists ;
int keep_open ;
struct device * dev ;
} ;
2013-06-25 12:25:43 +02:00
struct config_source {
config_source_t type ;
time_t timestamp ;
union {
struct config_file * file ;
struct config_file * profile ;
} source ;
} ;
2013-03-05 16:49:42 +01:00
/*
* Map each ID to respective definition of the configuration item .
*/
static struct cfg_def_item _cfg_def_items [ CFG_COUNT + 1 ] = {
# define cfg_section(id, name, parent, flags, since_version, comment) {id, parent, name, CFG_TYPE_SECTION, {0}, flags, since_version, comment},
# define cfg(id, name, parent, flags, type, default_value, since_version, comment) {id, parent, name, type, {.v_##type = default_value}, flags, since_version, comment},
config: add CFG_DEFAULT_RUN_TIME for config options with runtime defaults
Previously, we declared a default value as undefined ("NULL") for
settings which require runtime context to be set first (e.g. settings
for paths that rely on SYSTEM_DIR environment variable or they depend
on any other setting in some way).
If we want to output default values as they are really used in runtime,
we should make it possible to define a default value as function which
is evaluated, not just providing a firm constant value as it was before.
This patch defines simple prototypes for such functions. Also, there's
new helper macros "cfg_runtime" and "cfg_array_runtime" - they provide
exactly the same functionality as the original "cfg" and "cfg_array"
macros when defining the configuration settings in config_settings.h,
but they don't set the constant default value. Instead, they automatically
link the configuration setting definition with one of these functions:
typedef int (*t_fn_CFG_TYPE_BOOL) (struct cmd_context *cmd, struct profile *profile);
typedef int (*t_fn_CFG_TYPE_INT) (struct cmd_context *cmd, struct profile *profile);
typedef float (*t_fn_CFG_TYPE_FLOAT) (struct cmd_context *cmd, struct profile *profile);
typedef const char* (*t_fn_CFG_TYPE_STRING) (struct cmd_context *cmd, struct profile *profile);
typedef const char* (*t_fn_CFG_TYPE_ARRAY) (struct cmd_context *cmd, struct profile *profile);
(The new macros actually set the CFG_DEFAULT_RUNTIME flag properly and
set the default value link to the function accordingly).
Then such configuration setting requires a function of selected type to
be defined. This function has a predefined name:
get_default_<id>
...where the <id> is the id of the setting as defined in
config_settings.h. For example "backup_archive_dir_CFG" if defined
as a setting with default value evaluated in runtime with "cfg_runtime"
will automatically have "get_default_backup_archive_dir_CFG" function
linked to this setting to get the default value.
2014-03-03 12:34:11 +01:00
# define cfg_runtime(id, name, parent, flags, type, since_version, comment) {id, parent, name, type, {.fn_##type = get_default_##id}, flags | CFG_DEFAULT_RUN_TIME, since_version, comment},
2013-03-05 16:49:42 +01:00
# define cfg_array(id, name, parent, flags, types, default_value, since_version, comment) {id, parent, name, CFG_TYPE_ARRAY | types, {.v_CFG_TYPE_STRING = default_value}, flags, since_version, comment},
config: add CFG_DEFAULT_RUN_TIME for config options with runtime defaults
Previously, we declared a default value as undefined ("NULL") for
settings which require runtime context to be set first (e.g. settings
for paths that rely on SYSTEM_DIR environment variable or they depend
on any other setting in some way).
If we want to output default values as they are really used in runtime,
we should make it possible to define a default value as function which
is evaluated, not just providing a firm constant value as it was before.
This patch defines simple prototypes for such functions. Also, there's
new helper macros "cfg_runtime" and "cfg_array_runtime" - they provide
exactly the same functionality as the original "cfg" and "cfg_array"
macros when defining the configuration settings in config_settings.h,
but they don't set the constant default value. Instead, they automatically
link the configuration setting definition with one of these functions:
typedef int (*t_fn_CFG_TYPE_BOOL) (struct cmd_context *cmd, struct profile *profile);
typedef int (*t_fn_CFG_TYPE_INT) (struct cmd_context *cmd, struct profile *profile);
typedef float (*t_fn_CFG_TYPE_FLOAT) (struct cmd_context *cmd, struct profile *profile);
typedef const char* (*t_fn_CFG_TYPE_STRING) (struct cmd_context *cmd, struct profile *profile);
typedef const char* (*t_fn_CFG_TYPE_ARRAY) (struct cmd_context *cmd, struct profile *profile);
(The new macros actually set the CFG_DEFAULT_RUNTIME flag properly and
set the default value link to the function accordingly).
Then such configuration setting requires a function of selected type to
be defined. This function has a predefined name:
get_default_<id>
...where the <id> is the id of the setting as defined in
config_settings.h. For example "backup_archive_dir_CFG" if defined
as a setting with default value evaluated in runtime with "cfg_runtime"
will automatically have "get_default_backup_archive_dir_CFG" function
linked to this setting to get the default value.
2014-03-03 12:34:11 +01:00
# define cfg_array_runtime(id, name, parent, flags, types, since_version, comment) {id, parent, name, CFG_TYPE_ARRAY | types, {.fn_CFG_TYPE_STRING = get_default_##id}, flags | CFG_DEFAULT_RUN_TIME, since_version, comment},
2013-03-05 16:49:42 +01:00
# include "config_settings.h"
# undef cfg_section
# undef cfg
config: add CFG_DEFAULT_RUN_TIME for config options with runtime defaults
Previously, we declared a default value as undefined ("NULL") for
settings which require runtime context to be set first (e.g. settings
for paths that rely on SYSTEM_DIR environment variable or they depend
on any other setting in some way).
If we want to output default values as they are really used in runtime,
we should make it possible to define a default value as function which
is evaluated, not just providing a firm constant value as it was before.
This patch defines simple prototypes for such functions. Also, there's
new helper macros "cfg_runtime" and "cfg_array_runtime" - they provide
exactly the same functionality as the original "cfg" and "cfg_array"
macros when defining the configuration settings in config_settings.h,
but they don't set the constant default value. Instead, they automatically
link the configuration setting definition with one of these functions:
typedef int (*t_fn_CFG_TYPE_BOOL) (struct cmd_context *cmd, struct profile *profile);
typedef int (*t_fn_CFG_TYPE_INT) (struct cmd_context *cmd, struct profile *profile);
typedef float (*t_fn_CFG_TYPE_FLOAT) (struct cmd_context *cmd, struct profile *profile);
typedef const char* (*t_fn_CFG_TYPE_STRING) (struct cmd_context *cmd, struct profile *profile);
typedef const char* (*t_fn_CFG_TYPE_ARRAY) (struct cmd_context *cmd, struct profile *profile);
(The new macros actually set the CFG_DEFAULT_RUNTIME flag properly and
set the default value link to the function accordingly).
Then such configuration setting requires a function of selected type to
be defined. This function has a predefined name:
get_default_<id>
...where the <id> is the id of the setting as defined in
config_settings.h. For example "backup_archive_dir_CFG" if defined
as a setting with default value evaluated in runtime with "cfg_runtime"
will automatically have "get_default_backup_archive_dir_CFG" function
linked to this setting to get the default value.
2014-03-03 12:34:11 +01:00
# undef cfg_runtime
2013-03-05 16:49:42 +01:00
# undef cfg_array
config: add CFG_DEFAULT_RUN_TIME for config options with runtime defaults
Previously, we declared a default value as undefined ("NULL") for
settings which require runtime context to be set first (e.g. settings
for paths that rely on SYSTEM_DIR environment variable or they depend
on any other setting in some way).
If we want to output default values as they are really used in runtime,
we should make it possible to define a default value as function which
is evaluated, not just providing a firm constant value as it was before.
This patch defines simple prototypes for such functions. Also, there's
new helper macros "cfg_runtime" and "cfg_array_runtime" - they provide
exactly the same functionality as the original "cfg" and "cfg_array"
macros when defining the configuration settings in config_settings.h,
but they don't set the constant default value. Instead, they automatically
link the configuration setting definition with one of these functions:
typedef int (*t_fn_CFG_TYPE_BOOL) (struct cmd_context *cmd, struct profile *profile);
typedef int (*t_fn_CFG_TYPE_INT) (struct cmd_context *cmd, struct profile *profile);
typedef float (*t_fn_CFG_TYPE_FLOAT) (struct cmd_context *cmd, struct profile *profile);
typedef const char* (*t_fn_CFG_TYPE_STRING) (struct cmd_context *cmd, struct profile *profile);
typedef const char* (*t_fn_CFG_TYPE_ARRAY) (struct cmd_context *cmd, struct profile *profile);
(The new macros actually set the CFG_DEFAULT_RUNTIME flag properly and
set the default value link to the function accordingly).
Then such configuration setting requires a function of selected type to
be defined. This function has a predefined name:
get_default_<id>
...where the <id> is the id of the setting as defined in
config_settings.h. For example "backup_archive_dir_CFG" if defined
as a setting with default value evaluated in runtime with "cfg_runtime"
will automatically have "get_default_backup_archive_dir_CFG" function
linked to this setting to get the default value.
2014-03-03 12:34:11 +01:00
# undef cfg_array_runtime
2013-03-05 16:49:42 +01:00
} ;
2013-06-25 12:25:43 +02:00
config_source_t config_get_source_type ( struct dm_config_tree * cft )
{
struct config_source * cs = dm_config_get_custom ( cft ) ;
return cs ? cs - > type : CONFIG_UNDEFINED ;
}
2011-12-18 21:56:03 +00:00
/*
* public interface
*/
2013-06-25 12:25:43 +02:00
struct dm_config_tree * config_open ( config_source_t source ,
const char * filename ,
int keep_open )
2002-01-07 10:23:52 +00:00
{
2011-12-18 21:56:03 +00:00
struct dm_config_tree * cft = dm_config_create ( ) ;
2013-06-25 12:25:43 +02:00
struct config_source * cs ;
2011-12-18 21:56:03 +00:00
struct config_file * cf ;
2013-06-25 12:25:43 +02:00
2011-12-18 21:56:03 +00:00
if ( ! cft )
return NULL ;
2013-06-25 12:25:43 +02:00
if ( ! ( cs = dm_pool_zalloc ( cft - > mem , sizeof ( struct config_source ) ) ) ) {
log_error ( " Failed to allocate config source. " ) ;
2013-04-23 11:58:50 +02:00
goto fail ;
}
2002-01-07 10:23:52 +00:00
2014-05-19 10:58:28 +02:00
if ( ( source = = CONFIG_FILE ) | |
( source = = CONFIG_FILE_SPECIAL ) | |
( source = = CONFIG_PROFILE ) ) {
2013-06-25 12:25:43 +02:00
if ( ! ( cf = dm_pool_zalloc ( cft - > mem , sizeof ( struct config_file ) ) ) ) {
log_error ( " Failed to allocate config file. " ) ;
goto fail ;
}
2011-12-18 21:56:03 +00:00
2013-06-25 12:25:43 +02:00
cf - > keep_open = keep_open ;
if ( filename & &
! ( cf - > filename = dm_pool_strdup ( cft - > mem , filename ) ) ) {
log_error ( " Failed to duplicate filename. " ) ;
goto fail ;
}
cs - > source . file = cf ;
2011-12-18 21:56:03 +00:00
}
2013-06-25 12:25:43 +02:00
cs - > type = source ;
dm_config_set_custom ( cft , cs ) ;
2011-12-18 21:56:03 +00:00
return cft ;
fail :
dm_config_destroy ( cft ) ;
return NULL ;
}
/*
* Doesn ' t populate filename if the file is empty .
*/
int config_file_check ( struct dm_config_tree * cft , const char * * filename , struct stat * info )
{
2013-06-25 12:25:43 +02:00
struct config_source * cs = dm_config_get_custom ( cft ) ;
struct config_file * cf ;
2011-12-18 21:56:03 +00:00
struct stat _info ;
2014-05-19 10:58:28 +02:00
if ( ( cs - > type ! = CONFIG_FILE ) & &
( cs - > type ! = CONFIG_PROFILE ) & &
( cs - > type ! = CONFIG_FILE_SPECIAL ) ) {
log_error ( INTERNAL_ERROR " config_file_check: expected file, special file or "
" profile config source, found %s config source. " ,
_config_source_names [ cs - > type ] ) ;
2013-06-25 12:25:43 +02:00
return 0 ;
}
2011-12-18 21:56:03 +00:00
if ( ! info )
info = & _info ;
2013-06-25 12:25:43 +02:00
cf = cs - > source . file ;
2011-12-18 21:56:03 +00:00
if ( stat ( cf - > filename , info ) ) {
log_sys_error ( " stat " , cf - > filename ) ;
cf - > exists = 0 ;
return 0 ;
}
if ( ! S_ISREG ( info - > st_mode ) ) {
log_error ( " %s is not a regular file " , cf - > filename ) ;
cf - > exists = 0 ;
return 0 ;
}
2013-06-25 12:25:43 +02:00
cs - > timestamp = info - > st_ctime ;
2011-12-18 21:56:03 +00:00
cf - > exists = 1 ;
cf - > st_size = info - > st_size ;
if ( info - > st_size = = 0 )
log_verbose ( " %s is empty " , cf - > filename ) ;
else if ( filename )
* filename = cf - > filename ;
return 1 ;
}
/*
* Return 1 if config files ought to be reloaded
*/
int config_file_changed ( struct dm_config_tree * cft )
{
2013-06-25 12:25:43 +02:00
struct config_source * cs = dm_config_get_custom ( cft ) ;
struct config_file * cf ;
2011-12-18 21:56:03 +00:00
struct stat info ;
2013-06-25 12:25:43 +02:00
if ( cs - > type ! = CONFIG_FILE ) {
log_error ( INTERNAL_ERROR " config_file_changed: expected file config source, "
" found %s config source. " , _config_source_names [ cs - > type ] ) ;
return 0 ;
}
cf = cs - > source . file ;
2011-12-18 21:56:03 +00:00
if ( ! cf - > filename )
return 0 ;
if ( stat ( cf - > filename , & info ) = = - 1 ) {
/* Ignore a deleted config file: still use original data */
if ( errno = = ENOENT ) {
if ( ! cf - > exists )
return 0 ;
log_very_verbose ( " Config file %s has disappeared! " ,
cf - > filename ) ;
goto reload ;
}
log_sys_error ( " stat " , cf - > filename ) ;
log_error ( " Failed to reload configuration files " ) ;
return 0 ;
}
if ( ! S_ISREG ( info . st_mode ) ) {
log_error ( " Configuration file %s is not a regular file " ,
cf - > filename ) ;
goto reload ;
}
/* Unchanged? */
2013-06-25 12:25:43 +02:00
if ( cs - > timestamp = = info . st_ctime & & cf - > st_size = = info . st_size )
2011-12-18 21:56:03 +00:00
return 0 ;
reload :
log_verbose ( " Detected config file change to %s " , cf - > filename ) ;
return 1 ;
}
2013-06-25 12:25:43 +02:00
void config_destroy ( struct dm_config_tree * cft )
2011-12-18 21:56:03 +00:00
{
2013-06-25 12:25:43 +02:00
struct config_source * cs ;
struct config_file * cf ;
2011-12-18 21:56:03 +00:00
2013-06-25 12:25:43 +02:00
if ( ! cft )
return ;
cs = dm_config_get_custom ( cft ) ;
2014-05-19 10:58:28 +02:00
if ( ( cs - > type = = CONFIG_FILE ) | |
( cs - > type = = CONFIG_PROFILE ) | |
( cs - > type = = CONFIG_FILE_SPECIAL ) ) {
2013-06-25 12:25:43 +02:00
cf = cs - > source . file ;
if ( cf & & cf - > dev )
if ( ! dev_close ( cf - > dev ) )
stack ;
}
2002-01-07 10:23:52 +00:00
2011-08-30 14:55:15 +00:00
dm_config_destroy ( cft ) ;
2006-05-16 16:48:31 +00:00
}
2013-06-25 12:25:43 +02:00
struct dm_config_tree * config_file_open_and_read ( const char * config_file ,
config_source_t source )
2013-06-25 12:25:23 +02:00
{
struct dm_config_tree * cft ;
struct stat info ;
2013-06-25 12:25:43 +02:00
if ( ! ( cft = config_open ( source , config_file , 0 ) ) ) {
2013-06-25 12:25:23 +02:00
log_error ( " config_tree allocation failed " ) ;
return NULL ;
}
/* Is there a config file? */
if ( stat ( config_file , & info ) = = - 1 ) {
2013-06-25 12:25:43 +02:00
/* Profile file must be present! */
if ( errno = = ENOENT & & ( source ! = CONFIG_PROFILE ) )
2013-06-25 12:25:23 +02:00
return cft ;
log_sys_error ( " stat " , config_file ) ;
goto bad ;
}
log_very_verbose ( " Loading config file: %s " , config_file ) ;
if ( ! config_file_read ( cft ) ) {
log_error ( " Failed to load config file %s " , config_file ) ;
goto bad ;
}
return cft ;
bad :
2013-06-25 12:25:43 +02:00
config_destroy ( cft ) ;
2013-06-25 12:25:23 +02:00
return NULL ;
}
2011-09-02 01:32:08 +00:00
/*
* Returns config tree if it was removed .
*/
2013-06-25 12:25:43 +02:00
struct dm_config_tree * remove_config_tree_by_source ( struct cmd_context * cmd ,
config_source_t source )
2011-09-02 01:32:08 +00:00
{
2013-06-25 12:25:43 +02:00
struct dm_config_tree * previous_cft = NULL ;
struct dm_config_tree * cft = cmd - > cft ;
struct config_source * cs ;
while ( cft ) {
cs = dm_config_get_custom ( cft ) ;
if ( cs & & ( cs - > type = = source ) ) {
if ( previous_cft ) {
previous_cft - > cascade = cft - > cascade ;
cmd - > cft = previous_cft ;
} else
cmd - > cft = cft - > cascade ;
cft - > cascade = NULL ;
break ;
}
previous_cft = cft ;
cft = cft - > cascade ;
}
2011-09-02 01:32:08 +00:00
2013-06-25 12:25:43 +02:00
return cft ;
2011-09-02 01:32:08 +00:00
}
2009-07-27 21:01:56 +00:00
int override_config_tree_from_string ( struct cmd_context * cmd ,
const char * config_settings )
{
2011-09-02 01:32:08 +00:00
struct dm_config_tree * cft_new ;
2013-06-25 12:25:43 +02:00
struct config_source * cs = dm_config_get_custom ( cmd - > cft ) ;
/*
* Follow this sequence :
2013-06-25 12:27:37 +02:00
* CONFIG_STRING - > CONFIG_PROFILE - > CONFIG_FILE / CONFIG_MERGED_FILES
2013-06-25 12:25:43 +02:00
*/
if ( cs - > type = = CONFIG_STRING ) {
log_error ( INTERNAL_ERROR " override_config_tree_from_string: "
" config cascade already contains a string config. " ) ;
return 0 ;
}
2011-09-02 01:32:08 +00:00
if ( ! ( cft_new = dm_config_from_string ( config_settings ) ) ) {
2009-07-27 21:01:56 +00:00
log_error ( " Failed to set overridden configuration entries. " ) ;
2012-10-16 10:07:27 +02:00
return 0 ;
2009-07-27 21:01:56 +00:00
}
2013-06-25 12:25:43 +02:00
if ( ! ( cs = dm_pool_zalloc ( cft_new - > mem , sizeof ( struct config_source ) ) ) ) {
log_error ( " Failed to allocate config source. " ) ;
dm_config_destroy ( cft_new ) ;
return 0 ;
}
cs - > type = CONFIG_STRING ;
dm_config_set_custom ( cft_new , cs ) ;
2011-09-02 01:32:08 +00:00
cmd - > cft = dm_config_insert_cascaded_tree ( cft_new , cmd - > cft ) ;
2012-10-16 10:07:27 +02:00
return 1 ;
2009-07-27 21:01:56 +00:00
}
2013-06-25 12:27:37 +02:00
int override_config_tree_from_profile ( struct cmd_context * cmd ,
struct profile * profile )
{
struct dm_config_tree * cft = cmd - > cft , * cft_string = NULL ;
struct config_source * cs = dm_config_get_custom ( cft ) ;
/*
* Follow this sequence :
* CONFIG_STRING - > CONFIG_PROFILE - > CONFIG_FILE / CONFIG_MERGED_FILES
*/
if ( ! profile - > cft & & ! load_profile ( cmd , profile ) )
return_0 ;
if ( cs - > type = = CONFIG_STRING ) {
cft_string = cft ;
cft = cft - > cascade ;
cs = dm_config_get_custom ( cft ) ;
if ( cs - > type = = CONFIG_PROFILE ) {
log_error ( INTERNAL_ERROR " override_config_tree_from_profile: "
" config cascade already contains a profile config. " ) ;
return 0 ;
}
dm_config_insert_cascaded_tree ( cft_string , profile - > cft ) ;
}
cmd - > cft = dm_config_insert_cascaded_tree ( profile - > cft , cft ) ;
cmd - > cft = cft_string ? : profile - > cft ;
return 1 ;
}
2011-12-18 21:56:03 +00:00
int config_file_read_fd ( struct dm_config_tree * cft , struct device * dev ,
off_t offset , size_t size , off_t offset2 , size_t size2 ,
checksum_fn_t checksum_fn , uint32_t checksum )
2001-08-21 12:56:08 +00:00
{
2012-02-23 22:36:21 +00:00
char * fb , * fe ;
2002-11-18 14:01:16 +00:00
int r = 0 ;
2003-07-04 22:34:56 +00:00
int use_mmap = 1 ;
off_t mmap_offset = 0 ;
2007-06-13 15:11:19 +00:00
char * buf = NULL ;
2013-06-25 12:25:43 +02:00
struct config_source * cs = dm_config_get_custom ( cft ) ;
2014-05-19 10:58:28 +02:00
if ( ( cs - > type ! = CONFIG_FILE ) & &
( cs - > type ! = CONFIG_PROFILE ) & &
( cs - > type ! = CONFIG_FILE_SPECIAL ) ) {
log_error ( INTERNAL_ERROR " config_file_read_fd: expected file, special file "
" or profile config source, found %s config source. " ,
_config_source_names [ cs - > type ] ) ;
2013-06-25 12:25:43 +02:00
return 0 ;
}
2002-04-24 18:20:51 +00:00
2003-07-04 22:34:56 +00:00
/* Only use mmap with regular files */
if ( ! ( dev - > flags & DEV_REGULAR ) | | size2 )
use_mmap = 0 ;
if ( use_mmap ) {
2006-08-17 18:23:44 +00:00
mmap_offset = offset % lvm_getpagesize ( ) ;
2002-11-18 14:01:16 +00:00
/* memory map the file */
2011-08-30 14:55:15 +00:00
fb = mmap ( ( caddr_t ) 0 , size + mmap_offset , PROT_READ ,
MAP_PRIVATE , dev_fd ( dev ) , offset - mmap_offset ) ;
if ( fb = = ( caddr_t ) ( - 1 ) ) {
2003-07-04 22:34:56 +00:00
log_sys_error ( " mmap " , dev_name ( dev ) ) ;
2002-11-18 14:01:16 +00:00
goto out ;
}
2011-08-30 14:55:15 +00:00
fb = fb + mmap_offset ;
2003-07-04 22:34:56 +00:00
} else {
2011-10-11 09:06:09 +00:00
if ( ! ( buf = dm_malloc ( size + size2 ) ) ) {
log_error ( " Failed to allocate circular buffer. " ) ;
return 0 ;
}
2007-04-19 02:10:42 +00:00
if ( ! dev_read_circular ( dev , ( uint64_t ) offset , size ,
( uint64_t ) offset2 , size2 , buf ) ) {
2003-07-04 22:34:56 +00:00
goto out ;
}
2011-08-30 14:55:15 +00:00
fb = buf ;
2002-11-18 14:01:16 +00:00
}
if ( checksum_fn & & checksum ! =
2011-08-30 14:55:15 +00:00
( checksum_fn ( checksum_fn ( INITIAL_CRC , ( const uint8_t * ) fb , size ) ,
( const uint8_t * ) ( fb + size ) , size2 ) ) ) {
2003-07-04 22:34:56 +00:00
log_error ( " %s: Checksum error " , dev_name ( dev ) ) ;
2002-11-18 14:01:16 +00:00
goto out ;
}
2011-08-30 14:55:15 +00:00
fe = fb + size + size2 ;
if ( ! dm_config_parse ( cft , fb , fe ) )
2008-01-30 13:19:47 +00:00
goto_out ;
2002-11-18 14:01:16 +00:00
r = 1 ;
out :
2003-07-04 22:34:56 +00:00
if ( ! use_mmap )
2006-05-16 16:48:31 +00:00
dm_free ( buf ) ;
2002-11-18 14:01:16 +00:00
else {
/* unmap the file */
2012-02-23 22:36:21 +00:00
if ( munmap ( fb - mmap_offset , size + mmap_offset ) ) {
2003-07-04 22:34:56 +00:00
log_sys_error ( " munmap " , dev_name ( dev ) ) ;
2002-11-18 14:01:16 +00:00
r = 0 ;
}
}
return r ;
}
2011-12-18 21:56:03 +00:00
int config_file_read ( struct dm_config_tree * cft )
2002-11-18 14:01:16 +00:00
{
2011-09-02 01:32:08 +00:00
const char * filename = NULL ;
2013-06-25 12:25:43 +02:00
struct config_source * cs = dm_config_get_custom ( cft ) ;
struct config_file * cf ;
2002-11-18 14:01:16 +00:00
struct stat info ;
2011-08-30 14:55:15 +00:00
int r ;
2002-04-24 18:20:51 +00:00
2011-12-18 21:56:03 +00:00
if ( ! config_file_check ( cft , & filename , & info ) )
2011-09-01 21:04:14 +00:00
return_0 ;
2004-05-04 18:28:15 +00:00
2011-09-02 01:32:08 +00:00
/* Nothing to do. E.g. empty file. */
if ( ! filename )
return 1 ;
2013-06-25 12:25:43 +02:00
cf = cs - > source . file ;
2011-12-18 21:56:03 +00:00
if ( ! cf - > dev ) {
if ( ! ( cf - > dev = dev_create_file ( filename , NULL , NULL , 1 ) ) )
2006-11-04 03:34:10 +00:00
return_0 ;
2003-07-04 22:34:56 +00:00
2011-12-18 21:56:03 +00:00
if ( ! dev_open_readonly_buffered ( cf - > dev ) )
2006-11-04 03:34:10 +00:00
return_0 ;
2002-04-24 18:20:51 +00:00
}
2011-12-18 21:56:03 +00:00
r = config_file_read_fd ( cft , cf - > dev , 0 , ( size_t ) info . st_size , 0 , 0 ,
( checksum_fn_t ) NULL , 0 ) ;
2002-11-18 14:01:16 +00:00
2011-12-18 21:56:03 +00:00
if ( ! cf - > keep_open ) {
2012-03-01 21:12:37 +00:00
if ( ! dev_close ( cf - > dev ) )
stack ;
2011-12-18 21:56:03 +00:00
cf - > dev = NULL ;
2006-11-04 03:34:10 +00:00
}
2002-11-18 14:01:16 +00:00
return r ;
}
2011-12-18 21:56:03 +00:00
time_t config_file_timestamp ( struct dm_config_tree * cft )
{
2013-06-25 12:25:43 +02:00
struct config_source * cs = dm_config_get_custom ( cft ) ;
return cs - > timestamp ;
2011-12-18 21:56:03 +00:00
}
2013-03-05 16:49:42 +01:00
# define cfg_def_get_item_p(id) (&_cfg_def_items[id])
2014-03-04 10:29:08 +01:00
# define cfg_def_get_default_value_hint(cmd,item,type,profile) ((item->flags & CFG_DEFAULT_RUN_TIME) ? item->default_value.fn_##type(cmd,profile) : item->default_value.v_##type)
# define cfg_def_get_default_value(cmd,item,type,profile) (item->flags & CFG_DEFAULT_UNDEFINED ? 0 : cfg_def_get_default_value_hint(cmd,item,type,profile))
2013-03-05 16:49:42 +01:00
2014-02-25 11:08:00 +01:00
static int _cfg_def_make_path ( char * buf , size_t buf_size , int id , cfg_def_item_t * item , int xlate )
2013-03-05 16:49:42 +01:00
{
2014-02-25 11:08:00 +01:00
int variable = item - > flags & CFG_NAME_VARIABLE ;
2013-03-05 16:49:42 +01:00
int parent_id = item - > parent ;
int count , n ;
if ( id = = parent_id )
return 0 ;
2014-02-25 11:08:00 +01:00
count = _cfg_def_make_path ( buf , buf_size , parent_id , cfg_def_get_item_p ( parent_id ) , xlate ) ;
if ( ( n = dm_snprintf ( buf + count , buf_size - count , " %s%s%s%s " ,
2013-03-05 16:49:42 +01:00
count ? " / " : " " ,
2014-02-25 11:08:00 +01:00
xlate & & variable ? " < " : " " ,
! xlate & & variable ? " # " : item - > name ,
xlate & & variable ? " > " : " " ) ) < 0 ) {
2013-03-05 16:49:42 +01:00
log_error ( INTERNAL_ERROR " _cfg_def_make_path: supplied buffer too small for %s/%s " ,
cfg_def_get_item_p ( parent_id ) - > name , item - > name ) ;
buf [ 0 ] = ' \0 ' ;
return 0 ;
}
return count + n ;
}
int config_def_get_path ( char * buf , size_t buf_size , int id )
{
2014-02-25 11:08:00 +01:00
return _cfg_def_make_path ( buf , buf_size , id , cfg_def_get_item_p ( id ) , 0 ) ;
2013-03-05 16:49:42 +01:00
}
2013-03-05 17:14:18 +01:00
static void _get_type_name ( char * buf , size_t buf_size , cfg_def_type_t type )
{
2013-04-19 21:24:51 +02:00
( void ) dm_snprintf ( buf , buf_size , " %s%s%s%s%s%s " ,
( type & CFG_TYPE_ARRAY ) ?
( ( type & ~ CFG_TYPE_ARRAY ) ?
" array with values of type: " : " array " ) : " " ,
( type & CFG_TYPE_SECTION ) ? " section " : " " ,
( type & CFG_TYPE_BOOL ) ? " boolean " : " " ,
( type & CFG_TYPE_INT ) ? " integer " : " " ,
( type & CFG_TYPE_FLOAT ) ? " float " : " " ,
( type & CFG_TYPE_STRING ) ? " string " : " " ) ;
2013-03-05 17:14:18 +01:00
}
static void _log_type_error ( const char * path , cfg_def_type_t actual ,
cfg_def_type_t expected , int suppress_messages )
{
2013-04-19 21:24:51 +02:00
static char actual_type_name [ 128 ] ;
static char expected_type_name [ 128 ] ;
2013-03-05 17:14:18 +01:00
_get_type_name ( actual_type_name , sizeof ( actual_type_name ) , actual ) ;
_get_type_name ( expected_type_name , sizeof ( expected_type_name ) , expected ) ;
log_warn_suppress ( suppress_messages , " Configuration setting \" %s \" has invalid type. "
" Found%s, expected%s. " , path ,
actual_type_name , expected_type_name ) ;
}
2014-03-24 13:21:41 +01:00
static struct dm_config_value * _get_def_array_values ( struct dm_config_tree * cft ,
const cfg_def_item_t * def )
{
char * enc_value , * token , * p , * r ;
struct dm_config_value * array = NULL , * v = NULL , * oldv = NULL ;
if ( ! def - > default_value . v_CFG_TYPE_STRING ) {
if ( ! ( array = dm_config_create_value ( cft ) ) ) {
log_error ( " Failed to create default empty array for %s. " , def - > name ) ;
return NULL ;
}
array - > type = DM_CFG_EMPTY_ARRAY ;
return array ;
}
if ( ! ( p = token = enc_value = dm_strdup ( def - > default_value . v_CFG_TYPE_STRING ) ) ) {
log_error ( " _get_def_array_values: dm_strdup failed " ) ;
return NULL ;
}
/* Proper value always starts with '#'. */
if ( token [ 0 ] ! = ' # ' )
goto bad ;
while ( token ) {
/* Move to type identifier. Error on no char. */
token + + ;
if ( ! token [ 0 ] )
goto bad ;
/* Move to the actual value and decode any "##" into "#". */
p = token + 1 ;
while ( ( p = strchr ( p , ' # ' ) ) & & p [ 1 ] = = ' # ' ) {
memmove ( p , p + 1 , strlen ( p ) ) ;
p + + ;
}
/* Separate the value out of the whole string. */
if ( p )
p [ 0 ] = ' \0 ' ;
if ( ! ( v = dm_config_create_value ( cft ) ) ) {
log_error ( " Failed to create default config array value for %s. " , def - > name ) ;
dm_free ( enc_value ) ;
return NULL ;
}
if ( oldv )
oldv - > next = v ;
if ( ! array )
array = v ;
switch ( toupper ( token [ 0 ] ) ) {
case ' I ' :
case ' B ' :
v - > v . i = strtoll ( token + 1 , & r , 10 ) ;
if ( * r )
goto bad ;
v - > type = DM_CFG_INT ;
break ;
case ' F ' :
v - > v . f = strtod ( token + 1 , & r ) ;
if ( * r )
goto bad ;
v - > type = DM_CFG_FLOAT ;
break ;
case ' S ' :
if ( ! ( r = dm_pool_strdup ( cft - > mem , token + 1 ) ) ) {
dm_free ( enc_value ) ;
log_error ( " Failed to duplicate token for default "
" array value of %s. " , def - > name ) ;
return NULL ;
}
v - > v . str = r ;
v - > type = DM_CFG_STRING ;
break ;
default :
goto bad ;
}
oldv = v ;
token = p ;
}
dm_free ( enc_value ) ;
return array ;
bad :
log_error ( INTERNAL_ERROR " Default array value malformed for \" %s \" , "
" value: \" %s \" , token: \" %s \" . " , def - > name ,
def - > default_value . v_CFG_TYPE_STRING , token ) ;
dm_free ( enc_value ) ;
return NULL ;
}
2014-03-19 08:45:05 +01:00
static int _config_def_check_node_single_value ( struct cft_check_handle * handle ,
const char * rp , const struct dm_config_value * v ,
const cfg_def_item_t * def )