]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/conf-files.c
getty-generator: properly escape instance names
[thirdparty/systemd.git] / src / shared / 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
22#include <assert.h>
23#include <string.h>
24#include <unistd.h>
25#include <errno.h>
26#include <stdlib.h>
27#include <stdio.h>
28#include <sys/stat.h>
29#include <dirent.h>
30
31#include "macro.h"
32#include "util.h"
33#include "missing.h"
34#include "log.h"
35#include "strv.h"
9eb977db 36#include "path-util.h"
2c21044f
KS
37#include "hashmap.h"
38#include "conf-files.h"
39
cebed500 40static int files_add(Hashmap *h, const char *dirpath, const char *suffix, const char *root) {
fabe5c0e 41 _cleanup_closedir_ DIR *dir = NULL;
e02caf30 42
cebed500
LP
43 assert(dirpath);
44 assert(suffix);
45
46 if (isempty(root))
47 dir = opendir(dirpath);
48 else {
49 const char *p;
50
51 p = strappenda3(root, "/", dirpath);
52 dir = opendir(p);
53 }
2c21044f
KS
54 if (!dir) {
55 if (errno == ENOENT)
56 return 0;
57 return -errno;
58 }
59
60 for (;;) {
7d5e9c0f 61 struct dirent *de;
2c21044f 62 char *p;
fabe5c0e 63 int r;
2c21044f 64
a2be63f9
FW
65 errno = 0;
66 de = readdir(dir);
67 if (!de && errno != 0)
68 return -errno;
2c21044f
KS
69
70 if (!de)
71 break;
72
73 if (!dirent_is_file_with_suffix(de, suffix))
74 continue;
75
fabe5c0e
LP
76 p = strjoin(dirpath, "/", de->d_name, NULL);
77 if (!p)
e02caf30 78 return -ENOMEM;
2c21044f 79
2b6bf07d 80 r = hashmap_put(h, basename(p), p);
fabe5c0e
LP
81 if (r == -EEXIST) {
82 log_debug("Skipping overridden file: %s.", p);
83 free(p);
84 } else if (r < 0) {
85 free(p);
86 return r;
87 } else if (r == 0) {
88 log_debug("Duplicate file %s", p);
2c21044f
KS
89 free(p);
90 }
91 }
92
e02caf30 93 return 0;
2c21044f
KS
94}
95
96static int base_cmp(const void *a, const void *b) {
97 const char *s1, *s2;
98
99 s1 = *(char * const *)a;
100 s2 = *(char * const *)b;
2b6bf07d 101 return strcmp(basename(s1), basename(s2));
2c21044f
KS
102}
103
fabe5c0e
LP
104static int conf_files_list_strv_internal(char ***strv, const char *suffix, const char *root, char **dirs) {
105 Hashmap *fh;
106 char **files, **p;
578ac060 107 int r;
2c21044f 108
fabe5c0e
LP
109 assert(strv);
110 assert(suffix);
111
112 /* This alters the dirs string array */
112cfb18 113 if (!path_strv_canonicalize_absolute_uniq(dirs, root))
fabe5c0e 114 return -ENOMEM;
2c21044f
KS
115
116 fh = hashmap_new(string_hash_func, string_compare_func);
fabe5c0e
LP
117 if (!fh)
118 return -ENOMEM;
2c21044f
KS
119
120 STRV_FOREACH(p, dirs) {
cebed500 121 r = files_add(fh, *p, suffix, root);
fabe5c0e
LP
122 if (r == -ENOMEM) {
123 hashmap_free_free(fh);
124 return r;
125 } else if (r < 0)
126 log_debug("Failed to search for files in %s: %s",
127 *p, strerror(-r));
2c21044f
KS
128 }
129
130 files = hashmap_get_strv(fh);
131 if (files == NULL) {
fabe5c0e
LP
132 hashmap_free_free(fh);
133 return -ENOMEM;
2c21044f 134 }
fabe5c0e 135
7ff7394d 136 qsort_safe(files, hashmap_size(fh), sizeof(char *), base_cmp);
fabe5c0e 137 *strv = files;
2c21044f 138
2c21044f 139 hashmap_free(fh);
fabe5c0e
LP
140 return 0;
141}
142
844ec79b 143int conf_files_list_strv(char ***strv, const char *suffix, const char *root, const char* const* dirs) {
fabe5c0e
LP
144 _cleanup_strv_free_ char **copy = NULL;
145
146 assert(strv);
147 assert(suffix);
148
149 copy = strv_copy((char**) dirs);
150 if (!copy)
151 return -ENOMEM;
152
153 return conf_files_list_strv_internal(strv, suffix, root, copy);
2c21044f
KS
154}
155
7850b3b8 156int conf_files_list(char ***strv, const char *suffix, const char *root, const char *dir, ...) {
8201ad81
LP
157 _cleanup_strv_free_ char **dirs = NULL;
158 va_list ap;
fabe5c0e
LP
159
160 assert(strv);
161 assert(suffix);
2c21044f 162
8201ad81
LP
163 va_start(ap, dir);
164 dirs = strv_new_ap(dir, ap);
165 va_end(ap);
166
167 if (!dirs)
168 return -ENOMEM;
fabe5c0e
LP
169
170 return conf_files_list_strv_internal(strv, suffix, root, dirs);
171}
2c21044f 172
fabe5c0e
LP
173int conf_files_list_nulstr(char ***strv, const char *suffix, const char *root, const char *d) {
174 _cleanup_strv_free_ char **dirs = NULL;
175
176 assert(strv);
177 assert(suffix);
178
179 dirs = strv_split_nulstr(d);
180 if (!dirs)
181 return -ENOMEM;
2c21044f 182
fabe5c0e 183 return conf_files_list_strv_internal(strv, suffix, root, dirs);
2c21044f 184}