]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/conf-files.c
util: split out escaping code into escape.[ch]
[thirdparty/systemd.git] / src / basic / conf-files.c
CommitLineData
2c21044f
KS
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
2c21044f 22#include <string.h>
2c21044f
KS
23#include <errno.h>
24#include <stdlib.h>
25#include <stdio.h>
2c21044f
KS
26#include <dirent.h>
27
28#include "macro.h"
29#include "util.h"
30#include "missing.h"
31#include "log.h"
32#include "strv.h"
9eb977db 33#include "path-util.h"
2c21044f
KS
34#include "hashmap.h"
35#include "conf-files.h"
36
cba2ef02 37static int files_add(Hashmap *h, const char *root, const char *path, const char *suffix) {
fabe5c0e 38 _cleanup_closedir_ DIR *dir = NULL;
1d13f648
LP
39 const char *dirpath;
40 int r;
e02caf30 41
cba2ef02 42 assert(path);
cebed500
LP
43 assert(suffix);
44
1d13f648 45 dirpath = prefix_roota(root, path);
cebed500 46
cba2ef02 47 dir = opendir(dirpath);
2c21044f
KS
48 if (!dir) {
49 if (errno == ENOENT)
50 return 0;
51 return -errno;
52 }
53
54 for (;;) {
7d5e9c0f 55 struct dirent *de;
2c21044f
KS
56 char *p;
57
a2be63f9
FW
58 errno = 0;
59 de = readdir(dir);
60 if (!de && errno != 0)
61 return -errno;
2c21044f
KS
62
63 if (!de)
64 break;
65
66 if (!dirent_is_file_with_suffix(de, suffix))
67 continue;
68
fabe5c0e
LP
69 p = strjoin(dirpath, "/", de->d_name, NULL);
70 if (!p)
e02caf30 71 return -ENOMEM;
2c21044f 72
2b6bf07d 73 r = hashmap_put(h, basename(p), p);
fabe5c0e
LP
74 if (r == -EEXIST) {
75 log_debug("Skipping overridden file: %s.", p);
76 free(p);
77 } else if (r < 0) {
78 free(p);
79 return r;
80 } else if (r == 0) {
81 log_debug("Duplicate file %s", p);
2c21044f
KS
82 free(p);
83 }
84 }
85
e02caf30 86 return 0;
2c21044f
KS
87}
88
89static int base_cmp(const void *a, const void *b) {
90 const char *s1, *s2;
91
92 s1 = *(char * const *)a;
93 s2 = *(char * const *)b;
2b6bf07d 94 return strcmp(basename(s1), basename(s2));
2c21044f
KS
95}
96
fabe5c0e 97static int conf_files_list_strv_internal(char ***strv, const char *suffix, const char *root, char **dirs) {
e1d75803 98 _cleanup_hashmap_free_ Hashmap *fh = NULL;
fabe5c0e 99 char **files, **p;
578ac060 100 int r;
2c21044f 101
fabe5c0e
LP
102 assert(strv);
103 assert(suffix);
104
105 /* This alters the dirs string array */
7d8da2c9 106 if (!path_strv_resolve_uniq(dirs, root))
fabe5c0e 107 return -ENOMEM;
2c21044f 108
d5099efc 109 fh = hashmap_new(&string_hash_ops);
fabe5c0e
LP
110 if (!fh)
111 return -ENOMEM;
2c21044f
KS
112
113 STRV_FOREACH(p, dirs) {
cba2ef02 114 r = files_add(fh, root, *p, suffix);
fabe5c0e 115 if (r == -ENOMEM) {
fabe5c0e
LP
116 return r;
117 } else if (r < 0)
c33b3297
MS
118 log_debug_errno(r, "Failed to search for files in %s: %m",
119 *p);
2c21044f
KS
120 }
121
122 files = hashmap_get_strv(fh);
123 if (files == NULL) {
fabe5c0e 124 return -ENOMEM;
2c21044f 125 }
fabe5c0e 126
7ff7394d 127 qsort_safe(files, hashmap_size(fh), sizeof(char *), base_cmp);
fabe5c0e 128 *strv = files;
2c21044f 129
fabe5c0e
LP
130 return 0;
131}
132
844ec79b 133int conf_files_list_strv(char ***strv, const char *suffix, const char *root, const char* const* dirs) {
fabe5c0e
LP
134 _cleanup_strv_free_ char **copy = NULL;
135
136 assert(strv);
137 assert(suffix);
138
139 copy = strv_copy((char**) dirs);
140 if (!copy)
141 return -ENOMEM;
142
143 return conf_files_list_strv_internal(strv, suffix, root, copy);
2c21044f
KS
144}
145
7850b3b8 146int conf_files_list(char ***strv, const char *suffix, const char *root, const char *dir, ...) {
8201ad81
LP
147 _cleanup_strv_free_ char **dirs = NULL;
148 va_list ap;
fabe5c0e
LP
149
150 assert(strv);
151 assert(suffix);
2c21044f 152
8201ad81
LP
153 va_start(ap, dir);
154 dirs = strv_new_ap(dir, ap);
155 va_end(ap);
156
157 if (!dirs)
158 return -ENOMEM;
fabe5c0e
LP
159
160 return conf_files_list_strv_internal(strv, suffix, root, dirs);
161}
2c21044f 162
fabe5c0e
LP
163int conf_files_list_nulstr(char ***strv, const char *suffix, const char *root, const char *d) {
164 _cleanup_strv_free_ char **dirs = NULL;
165
166 assert(strv);
167 assert(suffix);
168
169 dirs = strv_split_nulstr(d);
170 if (!dirs)
171 return -ENOMEM;
2c21044f 172
fabe5c0e 173 return conf_files_list_strv_internal(strv, suffix, root, dirs);
2c21044f 174}