2010-08-14 21:59:25 +04:00
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2010-01-23 03:52:57 +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
2012-04-12 02:20:58 +04:00
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation ; either version 2.1 of the License , or
2010-02-03 15:03:47 +03:00
( 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
2012-04-12 02:20:58 +04:00
Lesser General Public License for more details .
2010-02-03 15:03:47 +03:00
2012-04-12 02:20:58 +04:00
You should have received a copy of the GNU Lesser General Public License
2010-02-03 15:03:47 +03:00
along with systemd ; If not , see < http : //www.gnu.org/licenses/>.
* * */
2010-01-27 02:15:56 +03:00
# include <dirent.h>
# include <errno.h>
# include "unit.h"
2010-01-23 03:52:57 +03:00
# include "load-dropin.h"
2010-01-27 06:55:19 +03:00
# include "log.h"
2010-02-13 03:07:02 +03:00
# include "strv.h"
2010-04-15 05:11:11 +04:00
# include "unit-name.h"
2013-01-11 03:21:06 +04:00
# include "conf-parser.h"
# include "load-fragment.h"
2013-01-11 04:04:11 +04:00
# include "conf-files.h"
2013-01-11 03:21:06 +04:00
2013-01-11 04:04:11 +04:00
static int iterate_dir ( Unit * u , const char * path , UnitDependency dependency , char * * * strv ) {
2013-01-11 03:21:06 +04:00
_cleanup_closedir_ DIR * d = NULL ;
2010-04-15 05:11:11 +04:00
int r ;
2010-11-15 06:24:04 +03:00
assert ( u ) ;
assert ( path ) ;
2013-01-11 04:04:11 +04:00
/* The config directories are special, since the order of the
* drop - ins matters */
if ( dependency < 0 ) {
r = strv_extend ( strv , path ) ;
if ( r < 0 )
return log_oom ( ) ;
return 0 ;
}
2011-08-31 05:55:38 +04:00
d = opendir ( path ) ;
if ( ! d ) {
2010-04-15 05:11:11 +04:00
if ( errno = = ENOENT )
return 0 ;
return - errno ;
}
2013-01-11 03:21:06 +04:00
for ( ; ; ) {
struct dirent * de ;
union dirent_storage buf ;
_cleanup_free_ char * f = NULL ;
int k ;
k = readdir_r ( d , & buf . de , & de ) ;
if ( k ! = 0 ) {
log_error ( " Failed to read directory %s: %s " , path , strerror ( k ) ) ;
return - k ;
}
if ( ! de )
break ;
2010-04-15 05:11:11 +04:00
if ( ignore_file ( de - > d_name ) )
continue ;
2012-07-13 15:41:01 +04:00
f = strjoin ( path , " / " , de - > d_name , NULL ) ;
2013-01-11 03:21:06 +04:00
if ( ! f )
return log_oom ( ) ;
2010-04-15 05:11:11 +04:00
2013-01-11 04:04:11 +04:00
r = unit_add_dependency_by_name ( u , dependency , de - > d_name , f , true ) ;
if ( r < 0 )
log_error ( " Cannot add dependency %s to %s, ignoring: %s " , de - > d_name , u - > id , strerror ( - r ) ) ;
2010-04-15 05:11:11 +04:00
}
2013-01-11 03:21:06 +04:00
return 0 ;
2010-04-15 05:11:11 +04:00
}
2010-01-23 03:52:57 +03:00
2013-01-11 04:04:11 +04:00
static int process_dir ( Unit * u , const char * unit_path , const char * name , const char * suffix , UnitDependency dependency , char * * * strv ) {
2010-01-27 02:15:56 +03:00
int r ;
2010-11-15 06:24:04 +03:00
char * path ;
2010-01-27 02:15:56 +03:00
2010-01-26 23:39:06 +03:00
assert ( u ) ;
2010-11-15 06:24:04 +03:00
assert ( unit_path ) ;
assert ( name ) ;
assert ( suffix ) ;
2010-01-23 03:52:57 +03:00
2012-07-13 15:41:01 +04:00
path = strjoin ( unit_path , " / " , name , suffix , NULL ) ;
2011-08-01 03:28:01 +04:00
if ( ! path )
2010-11-15 06:24:04 +03:00
return - ENOMEM ;
2010-01-23 03:52:57 +03:00
2012-01-15 15:04:08 +04:00
if ( u - > manager - > unit_path_cache & &
! set_get ( u - > manager - > unit_path_cache , path ) )
2010-11-15 06:24:04 +03:00
r = 0 ;
else
2013-01-11 04:04:11 +04:00
r = iterate_dir ( u , path , dependency , strv ) ;
2010-11-15 06:24:04 +03:00
free ( path ) ;
2010-01-27 02:15:56 +03:00
2010-11-15 06:24:04 +03:00
if ( r < 0 )
return r ;
2010-01-27 02:15:56 +03:00
2012-01-15 15:04:08 +04:00
if ( u - > instance ) {
2010-11-15 06:24:04 +03:00
char * template ;
/* Also try the template dir */
2010-01-27 02:15:56 +03:00
2011-08-31 05:55:38 +04:00
template = unit_name_template ( name ) ;
if ( ! template )
2010-11-15 06:24:04 +03:00
return - ENOMEM ;
2010-01-27 02:15:56 +03:00
2012-07-13 15:41:01 +04:00
path = strjoin ( unit_path , " / " , template , suffix , NULL ) ;
2010-11-15 06:24:04 +03:00
free ( template ) ;
2010-01-27 02:15:56 +03:00
2011-08-01 04:45:51 +04:00
if ( ! path )
2010-11-15 06:24:04 +03:00
return - ENOMEM ;
2010-01-27 02:15:56 +03:00
2012-01-15 15:04:08 +04:00
if ( u - > manager - > unit_path_cache & &
! set_get ( u - > manager - > unit_path_cache , path ) )
2010-11-15 06:24:04 +03:00
r = 0 ;
else
2013-01-11 04:04:11 +04:00
r = iterate_dir ( u , path , dependency , strv ) ;
2010-11-15 06:24:04 +03:00
free ( path ) ;
2010-01-27 02:15:56 +03:00
2010-11-15 06:24:04 +03:00
if ( r < 0 )
return r ;
}
2010-01-27 02:15:56 +03:00
2010-11-15 06:24:04 +03:00
return 0 ;
}
2010-01-27 02:15:56 +03:00
2010-11-15 06:24:04 +03:00
int unit_load_dropin ( Unit * u ) {
Iterator i ;
char * t ;
2013-01-11 04:04:11 +04:00
_cleanup_strv_free_ char * * strv = NULL ;
int r ;
2010-11-15 06:24:04 +03:00
assert ( u ) ;
/* Load dependencies from supplementary drop-in directories */
2010-02-13 03:07:02 +03:00
2012-01-15 15:04:08 +04:00
SET_FOREACH ( t , u - > names , i ) {
2010-11-15 06:24:04 +03:00
char * * p ;
2012-01-15 15:04:08 +04:00
STRV_FOREACH ( p , u - > manager - > lookup_paths . unit_path ) {
2013-01-11 04:04:11 +04:00
r = process_dir ( u , * p , t , " .wants " , UNIT_WANTS , NULL ) ;
2011-08-31 05:55:38 +04:00
if ( r < 0 )
2010-11-15 06:24:04 +03:00
return r ;
2013-01-11 04:04:11 +04:00
r = process_dir ( u , * p , t , " .requires " , UNIT_REQUIRES , NULL ) ;
2011-08-31 05:55:38 +04:00
if ( r < 0 )
2010-11-15 06:24:04 +03:00
return r ;
2013-01-11 03:21:06 +04:00
/* This loads the drop-in config snippets */
2013-01-11 04:04:11 +04:00
r = process_dir ( u , * p , t , " .d " , _UNIT_DEPENDENCY_INVALID , & strv ) ;
2013-01-11 03:21:06 +04:00
if ( r < 0 )
return r ;
2010-02-13 03:07:02 +03:00
}
2010-01-27 02:15:56 +03:00
}
2013-01-11 04:04:11 +04:00
if ( ! strv_isempty ( strv ) ) {
2013-01-12 02:39:23 +04:00
_cleanup_strv_free_ char * * files = NULL ;
char * * f ;
2013-01-11 04:04:11 +04:00
r = conf_files_list_strv ( & files , " .conf " , ( const char * * ) strv ) ;
if ( r < 0 ) {
log_error ( " Failed to get list of configuration files: %s " , strerror ( - r ) ) ;
return r ;
}
STRV_FOREACH ( f , files ) {
r = config_parse ( * f , NULL , UNIT_VTABLE ( u ) - > sections , config_item_perf_lookup , ( void * ) load_fragment_gperf_lookup , false , u ) ;
if ( r < 0 )
return r ;
}
}
2010-01-23 03:52:57 +03:00
return 0 ;
}