2010-08-14 21:59:25 +04:00
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2009-11-19 02:48:48 +03:00
2010-02-03 15:03:47 +03:00
/***
This file is part of systemd .
Copyright 2010 Lennart Poettering
systemd is free software ; you can redistribute it and / or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
systemd is distributed in the hope that it will be useful , but
WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
General Public License for more details .
You should have received a copy of the GNU General Public License
along with systemd ; If not , see < http : //www.gnu.org/licenses/>.
* * */
2009-11-19 02:48:48 +03:00
# include <string.h>
# include <stdio.h>
# include <errno.h>
# include <assert.h>
# include <stdlib.h>
# include "conf-parser.h"
# include "util.h"
# include "macro.h"
2009-11-19 04:51:44 +03:00
# include "strv.h"
2010-01-20 21:19:53 +03:00
# include "log.h"
2012-03-13 01:22:16 +04:00
# include "utf8.h"
2009-11-19 02:48:48 +03:00
2011-08-01 02:43:05 +04:00
int config_item_table_lookup (
void * table ,
2009-11-19 02:48:48 +03:00
const char * section ,
const char * lvalue ,
2011-08-01 02:43:05 +04:00
ConfigParserCallback * func ,
int * ltype ,
void * * data ,
2009-11-19 02:48:48 +03:00
void * userdata ) {
2011-08-01 02:43:05 +04:00
ConfigTableItem * t ;
assert ( table ) ;
2009-11-19 02:48:48 +03:00
assert ( lvalue ) ;
2011-08-01 02:43:05 +04:00
assert ( func ) ;
assert ( ltype ) ;
assert ( data ) ;
2009-11-19 02:48:48 +03:00
2011-08-01 02:43:05 +04:00
for ( t = table ; t - > lvalue ; t + + ) {
2009-11-19 02:48:48 +03:00
2011-08-01 02:43:05 +04:00
if ( ! streq ( lvalue , t - > lvalue ) )
2009-11-19 02:48:48 +03:00
continue ;
2011-08-01 02:43:05 +04:00
if ( ! streq_ptr ( section , t - > section ) )
2009-11-19 02:48:48 +03:00
continue ;
2011-08-01 02:43:05 +04:00
* func = t - > parse ;
* ltype = t - > ltype ;
* data = t - > data ;
return 1 ;
}
2009-11-19 02:48:48 +03:00
2011-08-01 02:43:05 +04:00
return 0 ;
}
2010-06-16 03:58:50 +04:00
2011-08-01 02:43:05 +04:00
int config_item_perf_lookup (
void * table ,
const char * section ,
const char * lvalue ,
ConfigParserCallback * func ,
int * ltype ,
void * * data ,
void * userdata ) {
ConfigPerfItemLookup lookup = ( ConfigPerfItemLookup ) table ;
const ConfigPerfItem * p ;
assert ( table ) ;
assert ( lvalue ) ;
assert ( func ) ;
assert ( ltype ) ;
assert ( data ) ;
if ( ! section )
p = lookup ( lvalue , strlen ( lvalue ) ) ;
else {
char * key ;
2011-08-01 04:39:22 +04:00
key = join ( section , " . " , lvalue , NULL ) ;
if ( ! key )
2011-08-01 02:43:05 +04:00
return - ENOMEM ;
p = lookup ( key , strlen ( key ) ) ;
free ( key ) ;
2009-11-19 02:48:48 +03:00
}
2011-08-01 02:43:05 +04:00
if ( ! p )
return 0 ;
* func = p - > parse ;
* ltype = p - > ltype ;
* data = ( uint8_t * ) userdata + p - > offset ;
return 1 ;
}
/* Run the user supplied parser for an assignment */
static int next_assignment (
const char * filename ,
unsigned line ,
ConfigItemLookup lookup ,
void * table ,
const char * section ,
const char * lvalue ,
const char * rvalue ,
bool relaxed ,
void * userdata ) {
ConfigParserCallback func = NULL ;
int ltype = 0 ;
void * data = NULL ;
int r ;
assert ( filename ) ;
assert ( line > 0 ) ;
assert ( lookup ) ;
assert ( lvalue ) ;
assert ( rvalue ) ;
r = lookup ( table , section , lvalue , & func , & ltype , & data , userdata ) ;
if ( r < 0 )
return r ;
2011-08-01 03:18:14 +04:00
if ( r > 0 ) {
if ( func )
return func ( filename , line , section , lvalue , ltype , rvalue , data , userdata ) ;
return 0 ;
}
2011-08-01 02:43:05 +04:00
2010-04-13 21:26:04 +04:00
/* Warn about unknown non-extension fields. */
2010-06-16 03:58:50 +04:00
if ( ! relaxed & & ! startswith ( lvalue , " X- " ) )
2011-08-01 02:43:05 +04:00
log_info ( " [%s:%u] Unknown lvalue '%s' in section '%s'. Ignoring. " , filename , line , lvalue , section ) ;
2010-04-13 21:26:04 +04:00
2010-01-27 02:19:06 +03:00
return 0 ;
2009-11-19 02:48:48 +03:00
}
/* Parse a variable assignment line */
2011-08-01 02:43:05 +04:00
static int parse_line (
const char * filename ,
unsigned line ,
const char * sections ,
ConfigItemLookup lookup ,
void * table ,
bool relaxed ,
char * * section ,
char * l ,
void * userdata ) {
2010-01-28 00:38:48 +03:00
char * e ;
2009-11-19 02:48:48 +03:00
2011-08-01 02:43:05 +04:00
assert ( filename ) ;
assert ( line > 0 ) ;
assert ( lookup ) ;
assert ( l ) ;
2010-01-28 00:38:48 +03:00
l = strstrip ( l ) ;
2009-11-19 02:48:48 +03:00
2010-01-28 00:38:48 +03:00
if ( ! * l )
2009-11-19 02:48:48 +03:00
return 0 ;
2010-01-27 07:30:38 +03:00
2010-01-28 00:38:48 +03:00
if ( strchr ( COMMENTS , * l ) )
2010-01-27 07:30:38 +03:00
return 0 ;
2009-11-19 02:48:48 +03:00
2010-01-28 00:38:48 +03:00
if ( startswith ( l , " .include " ) ) {
char * fn ;
2009-11-19 02:48:48 +03:00
int r ;
2011-08-01 02:43:05 +04:00
fn = file_in_same_dir ( filename , strstrip ( l + 9 ) ) ;
if ( ! fn )
2010-01-28 00:38:48 +03:00
return - ENOMEM ;
2009-11-19 02:48:48 +03:00
2011-08-01 02:43:05 +04:00
r = config_parse ( fn , NULL , sections , lookup , table , relaxed , userdata ) ;
2010-01-28 00:38:48 +03:00
free ( fn ) ;
2009-11-19 02:48:48 +03:00
return r ;
}
2010-01-28 00:38:48 +03:00
if ( * l = = ' [ ' ) {
2009-11-19 02:48:48 +03:00
size_t k ;
char * n ;
2010-01-28 00:38:48 +03:00
k = strlen ( l ) ;
2009-11-19 02:48:48 +03:00
assert ( k > 0 ) ;
2010-01-28 00:38:48 +03:00
if ( l [ k - 1 ] ! = ' ] ' ) {
2010-01-20 21:19:53 +03:00
log_error ( " [%s:%u] Invalid section header. " , filename , line ) ;
2009-11-19 02:48:48 +03:00
return - EBADMSG ;
}
2011-08-01 02:43:05 +04:00
n = strndup ( l + 1 , k - 2 ) ;
if ( ! n )
2009-11-19 02:48:48 +03:00
return - ENOMEM ;
2011-08-01 02:43:05 +04:00
if ( sections & & ! nulstr_contains ( sections , n ) ) {
2010-01-19 04:56:37 +03:00
2011-08-01 02:43:05 +04:00
if ( ! relaxed )
log_info ( " [%s:%u] Unknown section '%s'. Ignoring. " , filename , line , n ) ;
free ( n ) ;
* section = NULL ;
} else {
free ( * section ) ;
* section = n ;
}
2009-11-19 02:48:48 +03:00
return 0 ;
}
2011-08-01 02:43:05 +04:00
if ( sections & & ! * section )
2010-06-16 03:58:50 +04:00
return 0 ;
2011-08-01 02:43:05 +04:00
e = strchr ( l , ' = ' ) ;
if ( ! e ) {
2010-01-20 21:19:53 +03:00
log_error ( " [%s:%u] Missing '='. " , filename , line ) ;
2009-11-19 02:48:48 +03:00
return - EBADMSG ;
}
* e = 0 ;
e + + ;
2011-08-01 02:43:05 +04:00
return next_assignment (
filename ,
line ,
lookup ,
table ,
* section ,
strstrip ( l ) ,
strstrip ( e ) ,
relaxed ,
userdata ) ;
2009-11-19 02:48:48 +03:00
}
/* Go through the file and parse each line */
2011-08-01 02:43:05 +04:00
int config_parse (
const char * filename ,
FILE * f ,
const char * sections ,
ConfigItemLookup lookup ,
void * table ,
bool relaxed ,
void * userdata ) {
2009-11-19 02:48:48 +03:00
unsigned line = 0 ;
char * section = NULL ;
int r ;
2010-04-06 04:36:41 +04:00
bool ours = false ;
2010-07-07 20:20:42 +04:00
char * continuation = NULL ;
2009-11-19 02:48:48 +03:00
assert ( filename ) ;
2011-08-01 02:43:05 +04:00
assert ( lookup ) ;
2009-11-19 02:48:48 +03:00
2010-01-26 23:39:06 +03:00
if ( ! f ) {
2011-08-01 02:43:05 +04:00
f = fopen ( filename , " re " ) ;
if ( ! f ) {
2010-01-26 23:39:06 +03:00
r = - errno ;
log_error ( " Failed to open configuration file '%s': %s " , filename , strerror ( - r ) ) ;
goto finish ;
}
2010-04-06 04:36:41 +04:00
ours = true ;
2009-11-19 02:48:48 +03:00
}
while ( ! feof ( f ) ) {
2010-07-07 20:20:42 +04:00
char l [ LINE_MAX ] , * p , * c = NULL , * e ;
bool escaped = false ;
2009-11-19 02:48:48 +03:00
if ( ! fgets ( l , sizeof ( l ) , f ) ) {
if ( feof ( f ) )
break ;
r = - errno ;
2010-01-20 21:19:53 +03:00
log_error ( " Failed to read configuration file '%s': %s " , filename , strerror ( - r ) ) ;
2009-11-19 02:48:48 +03:00
goto finish ;
}
2010-07-07 20:20:42 +04:00
truncate_nl ( l ) ;
if ( continuation ) {
2011-08-01 02:43:05 +04:00
c = strappend ( continuation , l ) ;
if ( ! c ) {
2010-07-07 20:20:42 +04:00
r = - ENOMEM ;
goto finish ;
}
free ( continuation ) ;
continuation = NULL ;
p = c ;
} else
p = l ;
for ( e = p ; * e ; e + + ) {
if ( escaped )
escaped = false ;
else if ( * e = = ' \\ ' )
escaped = true ;
}
if ( escaped ) {
* ( e - 1 ) = ' ' ;
if ( c )
continuation = c ;
2011-08-01 02:43:05 +04:00
else {
continuation = strdup ( l ) ;
2011-09-23 03:43:28 +04:00
if ( ! continuation ) {
2011-08-01 02:43:05 +04:00
r = - ENOMEM ;
goto finish ;
}
2010-07-07 20:20:42 +04:00
}
continue ;
}
2011-08-01 02:43:05 +04:00
r = parse_line ( filename ,
+ + line ,
sections ,
lookup ,
table ,
relaxed ,
& section ,
p ,
userdata ) ;
2010-07-07 20:20:42 +04:00
free ( c ) ;
if ( r < 0 )
2009-11-19 02:48:48 +03:00
goto finish ;
}
r = 0 ;
finish :
free ( section ) ;
2010-07-07 20:20:42 +04:00
free ( continuation ) ;
2009-11-19 02:48:48 +03:00
2010-04-06 04:36:41 +04:00
if ( f & & ours )
2009-11-19 02:48:48 +03:00
fclose ( f ) ;
return r ;
}
int config_parse_int (
const char * filename ,
unsigned line ,
const char * section ,
const char * lvalue ,
2011-03-25 07:07:20 +03:00
int ltype ,
2009-11-19 02:48:48 +03:00
const char * rvalue ,
void * data ,
void * userdata ) {
int * i = data ;
int r ;
assert ( filename ) ;
assert ( lvalue ) ;
assert ( rvalue ) ;
assert ( data ) ;
if ( ( r = safe_atoi ( rvalue , i ) ) < 0 ) {
2011-08-01 02:43:05 +04:00
log_error ( " [%s:%u] Failed to parse numeric value, ingoring: %s " , filename , line , rvalue ) ;
return 0 ;
2009-11-19 02:48:48 +03:00
}
return 0 ;
}
2011-05-17 21:37:03 +04:00
int config_parse_long (
const char * filename ,
unsigned line ,
const char * section ,
const char * lvalue ,
int ltype ,
const char * rvalue ,
void * data ,
void * userdata ) {
long * i = data ;
int r ;
assert ( filename ) ;
assert ( lvalue ) ;
assert ( rvalue ) ;
assert ( data ) ;
if ( ( r = safe_atoli ( rvalue , i ) ) < 0 ) {
2011-08-01 02:43:05 +04:00
log_error ( " [%s:%u] Failed to parse numeric value, ignoring: %s " , filename , line , rvalue ) ;
return 0 ;
2011-05-17 21:37:03 +04:00
}
return 0 ;
}
2010-10-25 22:35:17 +04:00
int config_parse_uint64 (
const char * filename ,
unsigned line ,
const char * section ,
const char * lvalue ,
2011-03-25 07:07:20 +03:00
int ltype ,
2010-10-25 22:35:17 +04:00
const char * rvalue ,
void * data ,
void * userdata ) {
uint64_t * u = data ;
int r ;
assert ( filename ) ;
assert ( lvalue ) ;
assert ( rvalue ) ;
assert ( data ) ;
if ( ( r = safe_atou64 ( rvalue , u ) ) < 0 ) {
2011-08-01 02:43:05 +04:00
log_error ( " [%s:%u] Failed to parse numeric value, ignoring: %s " , filename , line , rvalue ) ;
return 0 ;
2010-10-25 22:35:17 +04:00
}
return 0 ;
}
2009-11-19 02:48:48 +03:00
int config_parse_unsigned (
const char * filename ,
unsigned line ,
const char * section ,
const char * lvalue ,
2011-03-25 07:07:20 +03:00
int ltype ,
2009-11-19 02:48:48 +03:00
const char * rvalue ,
void * data ,
void * userdata ) {
unsigned * u = data ;
int r ;
assert ( filename ) ;
assert ( lvalue ) ;
assert ( rvalue ) ;
assert ( data ) ;
if ( ( r = safe_atou ( rvalue , u ) ) < 0 ) {
2010-01-20 21:19:53 +03:00
log_error ( " [%s:%u] Failed to parse numeric value: %s " , filename , line , rvalue ) ;
2009-11-19 02:48:48 +03:00
return r ;
}
return 0 ;
}
2012-01-31 23:53:34 +04:00
int config_parse_bytes_size (
2009-11-19 02:48:48 +03:00
const char * filename ,
unsigned line ,
const char * section ,
const char * lvalue ,
2011-03-25 07:07:20 +03:00
int ltype ,
2009-11-19 02:48:48 +03:00
const char * rvalue ,
void * data ,
void * userdata ) {
size_t * sz = data ;
2012-01-31 23:53:34 +04:00
off_t o ;
2009-11-19 02:48:48 +03:00
assert ( filename ) ;
assert ( lvalue ) ;
assert ( rvalue ) ;
assert ( data ) ;
2012-01-31 23:53:34 +04:00
if ( parse_bytes ( rvalue , & o ) < 0 | | ( off_t ) ( size_t ) o ! = o ) {
log_error ( " [%s:%u] Failed to parse byte value, ignoring: %s " , filename , line , rvalue ) ;
return 0 ;
}
* sz = ( size_t ) o ;
return 0 ;
}
int config_parse_bytes_off (
const char * filename ,
unsigned line ,
const char * section ,
const char * lvalue ,
int ltype ,
const char * rvalue ,
void * data ,
void * userdata ) {
off_t * bytes = data ;
assert ( filename ) ;
assert ( lvalue ) ;
assert ( rvalue ) ;
assert ( data ) ;
assert_cc ( sizeof ( off_t ) = = sizeof ( uint64_t ) ) ;
if ( parse_bytes ( rvalue , bytes ) < 0 ) {
log_error ( " [%s:%u] Failed to parse bytes value, ignoring: %s " , filename , line , rvalue ) ;
2011-08-01 02:43:05 +04:00
return 0 ;
2009-11-19 02:48:48 +03:00
}
return 0 ;
}
int config_parse_bool (
const char * filename ,
unsigned line ,
const char * section ,
const char * lvalue ,
2011-03-25 07:07:20 +03:00
int ltype ,
2009-11-19 02:48:48 +03:00
const char * rvalue ,
void * data ,
void * userdata ) {
int k ;
bool * b = data ;
assert ( filename ) ;
assert ( lvalue ) ;
assert ( rvalue ) ;
assert ( data ) ;
if ( ( k = parse_boolean ( rvalue ) ) < 0 ) {
2011-08-01 02:43:05 +04:00
log_error ( " [%s:%u] Failed to parse boolean value, ignoring: %s " , filename , line , rvalue ) ;
return 0 ;
2009-11-19 02:48:48 +03:00
}
* b = ! ! k ;
return 0 ;
}
2012-01-18 18:40:21 +04:00
int config_parse_tristate (
const char * filename ,
unsigned line ,
const char * section ,
const char * lvalue ,
int ltype ,
const char * rvalue ,
void * data ,
void * userdata ) {
int k ;
int * b = data ;
assert ( filename ) ;
assert ( lvalue ) ;
assert ( rvalue ) ;
assert ( data ) ;
/* Tristates are like booleans, but can also take the 'default' value, i.e. "-1" */
k = parse_boolean ( rvalue ) ;
if ( k < 0 ) {
log_error ( " [%s:%u] Failed to parse boolean value, ignoring: %s " , filename , line , rvalue ) ;
return 0 ;
}
* b = ! ! k ;
return 0 ;
}
2009-11-19 02:48:48 +03:00
int config_parse_string (
const char * filename ,
unsigned line ,
const char * section ,
const char * lvalue ,
2011-03-25 07:07:20 +03:00
int ltype ,
2009-11-19 02:48:48 +03:00
const char * rvalue ,
void * data ,
void * userdata ) {
char * * s = data ;
char * n ;
assert ( filename ) ;
assert ( lvalue ) ;
assert ( rvalue ) ;
assert ( data ) ;
2012-03-13 01:22:16 +04:00
n = cunescape ( rvalue ) ;
if ( ! n )
return - ENOMEM ;
if ( ! utf8_is_valid ( n ) ) {
log_error ( " [%s:%u] String is not UTF-8 clean, ignoring assignment: %s " , filename , line , rvalue ) ;
free ( n ) ;
return 0 ;
}
2009-11-19 02:48:48 +03:00
free ( * s ) ;
2012-03-13 01:22:16 +04:00
if ( * n )
* s = n ;
else {
free ( n ) ;
* s = NULL ;
}
2009-11-19 02:48:48 +03:00
return 0 ;
}
2009-11-19 04:51:44 +03:00
2010-01-26 06:18:44 +03:00
int config_parse_path (
const char * filename ,
unsigned line ,
const char * section ,
const char * lvalue ,
2011-03-25 07:07:20 +03:00
int ltype ,
2010-01-26 06:18:44 +03:00
const char * rvalue ,
void * data ,
void * userdata ) {
char * * s = data ;
char * n ;
assert ( filename ) ;
assert ( lvalue ) ;
assert ( rvalue ) ;
assert ( data ) ;
2012-03-13 01:22:16 +04:00
if ( ! utf8_is_valid ( rvalue ) ) {
log_error ( " [%s:%u] Path is not UTF-8 clean, ignoring assignment: %s " , filename , line , rvalue ) ;
return 0 ;
}
2010-04-22 00:15:06 +04:00
if ( ! path_is_absolute ( rvalue ) ) {
2011-08-01 02:43:05 +04:00
log_error ( " [%s:%u] Not an absolute path, ignoring: %s " , filename , line , rvalue ) ;
return 0 ;
2010-01-26 06:18:44 +03:00
}
2012-03-13 01:22:16 +04:00
n = strdup ( rvalue ) ;
if ( ! n )
2010-01-26 06:18:44 +03:00
return - ENOMEM ;
2010-05-24 07:25:33 +04:00
path_kill_slashes ( n ) ;
2010-01-26 06:18:44 +03:00
free ( * s ) ;
* s = n ;
return 0 ;
}
2009-11-19 04:51:44 +03:00
int config_parse_strv (
const char * filename ,
unsigned line ,
const char * section ,
const char * lvalue ,
2011-03-25 07:07:20 +03:00
int ltype ,
2009-11-19 04:51:44 +03:00
const char * rvalue ,
void * data ,
void * userdata ) {
char * * * sv = data ;
char * * n ;
char * w ;
unsigned k ;
size_t l ;
char * state ;
2012-03-13 01:22:16 +04:00
int r ;
2009-11-19 04:51:44 +03:00
assert ( filename ) ;
assert ( lvalue ) ;
assert ( rvalue ) ;
assert ( data ) ;
k = strv_length ( * sv ) ;
2010-01-26 06:18:44 +03:00
FOREACH_WORD_QUOTED ( w , l , rvalue , state )
2009-11-19 04:51:44 +03:00
k + + ;
2012-03-13 01:22:16 +04:00
n = new ( char * , k + 1 ) ;
if ( ! n )
2009-11-19 04:51:44 +03:00
return - ENOMEM ;
2010-04-06 04:37:47 +04:00
if ( * sv )
for ( k = 0 ; ( * sv ) [ k ] ; k + + )
n [ k ] = ( * sv ) [ k ] ;
2010-04-06 23:52:35 +04:00
else
k = 0 ;
2010-04-06 04:37:47 +04:00
2012-03-13 01:22:16 +04:00
FOREACH_WORD_QUOTED ( w , l , rvalue , state ) {
n [ k ] = cunescape_length ( w , l ) ;
if ( ! n [ k ] ) {
r = - ENOMEM ;
2009-11-19 04:51:44 +03:00
goto fail ;
2012-03-13 01:22:16 +04:00
}
if ( ! utf8_is_valid ( n [ k ] ) ) {
log_error ( " [%s:%u] String is not UTF-8 clean, ignoring assignment: %s " , filename , line , rvalue ) ;
free ( n [ k ] ) ;
continue ;
}
k + + ;
}
2009-11-19 04:51:44 +03:00
n [ k ] = NULL ;
free ( * sv ) ;
* sv = n ;
return 0 ;
fail :
for ( ; k > 0 ; k - - )
free ( n [ k - 1 ] ) ;
2010-01-26 06:18:44 +03:00
free ( n ) ;
2009-11-19 04:51:44 +03:00
2012-03-13 01:22:16 +04:00
return r ;
2009-11-19 04:51:44 +03:00
}
2010-04-22 00:15:06 +04:00
int config_parse_path_strv (
const char * filename ,
unsigned line ,
const char * section ,
const char * lvalue ,
2011-03-25 07:07:20 +03:00
int ltype ,
2010-04-22 00:15:06 +04:00
const char * rvalue ,
void * data ,
void * userdata ) {
char * * * sv = data ;
char * * n ;
char * w ;
unsigned k ;
size_t l ;
char * state ;
int r ;
assert ( filename ) ;
assert ( lvalue ) ;
assert ( rvalue ) ;
assert ( data ) ;
k = strv_length ( * sv ) ;
FOREACH_WORD_QUOTED ( w , l , rvalue , state )
k + + ;
2012-03-13 01:22:16 +04:00
n = new ( char * , k + 1 ) ;
if ( ! n )
2010-04-22 00:15:06 +04:00
return - ENOMEM ;
k = 0 ;
if ( * sv )
for ( ; ( * sv ) [ k ] ; k + + )
n [ k ] = ( * sv ) [ k ] ;
FOREACH_WORD_QUOTED ( w , l , rvalue , state ) {
2012-03-13 01:22:16 +04:00
n [ k ] = strndup ( w , l ) ;
if ( ! n [ k ] ) {
2010-04-22 00:15:06 +04:00
r = - ENOMEM ;
goto fail ;
}
2012-03-13 01:22:16 +04:00
if ( ! utf8_is_valid ( n [ k ] ) ) {
log_error ( " [%s:%u] Path is not UTF-8 clean, ignoring assignment: %s " , filename , line , rvalue ) ;
free ( n [ k ] ) ;
continue ;
}
2010-04-22 00:15:06 +04:00
if ( ! path_is_absolute ( n [ k ] ) ) {
2011-08-01 02:43:05 +04:00
log_error ( " [%s:%u] Not an absolute path, ignoring: %s " , filename , line , rvalue ) ;
free ( n [ k ] ) ;
continue ;
2010-04-22 00:15:06 +04:00
}
2010-05-24 07:25:33 +04:00
path_kill_slashes ( n [ k ] ) ;
2010-04-22 00:15:06 +04:00
k + + ;
}
n [ k ] = NULL ;
free ( * sv ) ;
* sv = n ;
return 0 ;
fail :
for ( ; k > 0 ; k - - )
free ( n [ k - 1 ] ) ;
free ( n ) ;
return r ;
}
2011-08-01 02:43:05 +04:00
int config_parse_usec (
const char * filename ,
unsigned line ,
const char * section ,
const char * lvalue ,
int ltype ,
const char * rvalue ,
void * data ,
void * userdata ) {
usec_t * usec = data ;
assert ( filename ) ;
assert ( lvalue ) ;
assert ( rvalue ) ;
assert ( data ) ;
if ( parse_usec ( rvalue , usec ) < 0 ) {
log_error ( " [%s:%u] Failed to parse time value, ignoring: %s " , filename , line , rvalue ) ;
return 0 ;
}
return 0 ;
}
int config_parse_mode (
const char * filename ,
unsigned line ,
const char * section ,
const char * lvalue ,
int ltype ,
const char * rvalue ,
void * data ,
void * userdata ) {
mode_t * m = data ;
long l ;
char * x = NULL ;
assert ( filename ) ;
assert ( lvalue ) ;
assert ( rvalue ) ;
assert ( data ) ;
errno = 0 ;
l = strtol ( rvalue , & x , 8 ) ;
if ( ! x | | * x | | errno ) {
log_error ( " [%s:%u] Failed to parse mode value, ignoring: %s " , filename , line , rvalue ) ;
return 0 ;
}
if ( l < 0000 | | l > 07777 ) {
log_error ( " [%s:%u] mode value out of range, ignoring: %s " , filename , line , rvalue ) ;
return 0 ;
}
* m = ( mode_t ) l ;
return 0 ;
}