2012-05-07 20:55:45 +04:00
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
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 Lesser General Public License as published by
the Free Software Foundation ; either version 2.1 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
Lesser General Public License for more details .
You should have received a copy of the GNU Lesser General Public License
along with systemd ; If not , see < http : //www.gnu.org/licenses/>.
* * */
# include <assert.h>
# include <string.h>
# include <unistd.h>
# include <errno.h>
# include <stdlib.h>
# include <stdio.h>
# include <sys/stat.h>
# include <dirent.h>
# include "macro.h"
# include "util.h"
# include "missing.h"
# include "log.h"
# include "strv.h"
2012-05-07 23:36:12 +04:00
# include "path-util.h"
2012-05-07 20:55:45 +04:00
# include "hashmap.h"
# include "conf-files.h"
2014-06-20 06:07:04 +04:00
static int files_add ( Hashmap * h , const char * root , const char * path , const char * suffix ) {
2013-02-12 02:48:36 +04:00
_cleanup_closedir_ DIR * dir = NULL ;
2014-06-20 06:07:04 +04:00
char * dirpath ;
2013-02-08 13:45:30 +04:00
2014-06-20 06:07:04 +04:00
assert ( path ) ;
2014-06-17 03:56:44 +04:00
assert ( suffix ) ;
2014-06-20 06:07:04 +04:00
dirpath = strappenda ( root ? root : " " , path ) ;
2014-06-17 03:56:44 +04:00
2014-06-20 06:07:04 +04:00
dir = opendir ( dirpath ) ;
2012-05-07 20:55:45 +04:00
if ( ! dir ) {
if ( errno = = ENOENT )
return 0 ;
return - errno ;
}
for ( ; ; ) {
2012-09-20 00:21:09 +04:00
struct dirent * de ;
2012-05-07 20:55:45 +04:00
char * p ;
2013-02-12 02:48:36 +04:00
int r ;
2012-05-07 20:55:45 +04:00
2013-12-19 14:33:09 +04:00
errno = 0 ;
de = readdir ( dir ) ;
if ( ! de & & errno ! = 0 )
return - errno ;
2012-05-07 20:55:45 +04:00
if ( ! de )
break ;
if ( ! dirent_is_file_with_suffix ( de , suffix ) )
continue ;
2013-02-12 02:48:36 +04:00
p = strjoin ( dirpath , " / " , de - > d_name , NULL ) ;
if ( ! p )
2013-02-08 13:45:30 +04:00
return - ENOMEM ;
2012-05-07 20:55:45 +04:00
2013-12-07 06:29:55 +04:00
r = hashmap_put ( h , basename ( p ) , p ) ;
2013-02-12 02:48:36 +04:00
if ( r = = - EEXIST ) {
log_debug ( " Skipping overridden file: %s. " , p ) ;
free ( p ) ;
} else if ( r < 0 ) {
free ( p ) ;
return r ;
} else if ( r = = 0 ) {
log_debug ( " Duplicate file %s " , p ) ;
2012-05-07 20:55:45 +04:00
free ( p ) ;
}
}
2013-02-08 13:45:30 +04:00
return 0 ;
2012-05-07 20:55:45 +04:00
}
static int base_cmp ( const void * a , const void * b ) {
const char * s1 , * s2 ;
s1 = * ( char * const * ) a ;
s2 = * ( char * const * ) b ;
2013-12-07 06:29:55 +04:00
return strcmp ( basename ( s1 ) , basename ( s2 ) ) ;
2012-05-07 20:55:45 +04:00
}
2013-02-12 02:48:36 +04:00
static int conf_files_list_strv_internal ( char * * * strv , const char * suffix , const char * root , char * * dirs ) {
2014-06-24 21:00:32 +04:00
_cleanup_hashmap_free_ Hashmap * fh = NULL ;
2013-02-12 02:48:36 +04:00
char * * files , * * p ;
2012-07-25 01:18:25 +04:00
int r ;
2012-05-07 20:55:45 +04:00
2013-02-12 02:48:36 +04:00
assert ( strv ) ;
assert ( suffix ) ;
/* This alters the dirs string array */
2014-06-20 06:07:02 +04:00
if ( ! path_strv_resolve_uniq ( dirs , root ) )
2013-02-12 02:48:36 +04:00
return - ENOMEM ;
2012-05-07 20:55:45 +04:00
2014-08-13 03:00:18 +04:00
fh = hashmap_new ( & string_hash_ops ) ;
2013-02-12 02:48:36 +04:00
if ( ! fh )
return - ENOMEM ;
2012-05-07 20:55:45 +04:00
STRV_FOREACH ( p , dirs ) {
2014-06-20 06:07:04 +04:00
r = files_add ( fh , root , * p , suffix ) ;
2013-02-12 02:48:36 +04:00
if ( r = = - ENOMEM ) {
return r ;
} else if ( r < 0 )
2014-11-28 19:09:20 +03:00
log_debug_errno ( r , " Failed to search for files in %s: %m " ,
* p ) ;
2012-05-07 20:55:45 +04:00
}
files = hashmap_get_strv ( fh ) ;
if ( files = = NULL ) {
2013-02-12 02:48:36 +04:00
return - ENOMEM ;
2012-05-07 20:55:45 +04:00
}
2013-02-12 02:48:36 +04:00
2013-10-12 03:33:13 +04:00
qsort_safe ( files , hashmap_size ( fh ) , sizeof ( char * ) , base_cmp ) ;
2013-02-12 02:48:36 +04:00
* strv = files ;
2012-05-07 20:55:45 +04:00
2013-02-12 02:48:36 +04:00
return 0 ;
}
2013-03-29 04:17:24 +04:00
int conf_files_list_strv ( char * * * strv , const char * suffix , const char * root , const char * const * dirs ) {
2013-02-12 02:48:36 +04:00
_cleanup_strv_free_ char * * copy = NULL ;
assert ( strv ) ;
assert ( suffix ) ;
copy = strv_copy ( ( char * * ) dirs ) ;
if ( ! copy )
return - ENOMEM ;
return conf_files_list_strv_internal ( strv , suffix , root , copy ) ;
2012-05-07 20:55:45 +04:00
}
2013-02-08 13:22:02 +04:00
int conf_files_list ( char * * * strv , const char * suffix , const char * root , const char * dir , . . . ) {
2013-10-30 21:15:38 +04:00
_cleanup_strv_free_ char * * dirs = NULL ;
va_list ap ;
2013-02-12 02:48:36 +04:00
assert ( strv ) ;
assert ( suffix ) ;
2012-05-07 20:55:45 +04:00
2013-10-30 21:15:38 +04:00
va_start ( ap , dir ) ;
dirs = strv_new_ap ( dir , ap ) ;
va_end ( ap ) ;
if ( ! dirs )
return - ENOMEM ;
2013-02-12 02:48:36 +04:00
return conf_files_list_strv_internal ( strv , suffix , root , dirs ) ;
}
2012-05-07 20:55:45 +04:00
2013-02-12 02:48:36 +04:00
int conf_files_list_nulstr ( char * * * strv , const char * suffix , const char * root , const char * d ) {
_cleanup_strv_free_ char * * dirs = NULL ;
assert ( strv ) ;
assert ( suffix ) ;
dirs = strv_split_nulstr ( d ) ;
if ( ! dirs )
return - ENOMEM ;
2012-05-07 20:55:45 +04:00
2013-02-12 02:48:36 +04:00
return conf_files_list_strv_internal ( strv , suffix , root , dirs ) ;
2012-05-07 20:55:45 +04:00
}