]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/conf-files.c
core: add new "scope" unit type for making a unit of pre-existing processes
[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
7850b3b8 40static int files_add(Hashmap *h, const char *root, const char *path, const char *suffix) {
fabe5c0e 41 _cleanup_closedir_ DIR *dir = NULL;
e02caf30 42 _cleanup_free_ char *dirpath = NULL;
2c21044f 43
e02caf30
KS
44 if (asprintf(&dirpath, "%s%s", root ? root : "", path) < 0)
45 return -ENOMEM;
46
47 dir = opendir(dirpath);
2c21044f
KS
48 if (!dir) {
49 if (errno == ENOENT)
50 return 0;
51 return -errno;
52 }
53
54 for (;;) {
7d5e9c0f
LP
55 struct dirent *de;
56 union dirent_storage buf;
2c21044f 57 char *p;
fabe5c0e 58 int r;
2c21044f 59
fabe5c0e
LP
60 r = readdir_r(dir, &buf.de, &de);
61 if (r != 0)
62 return -r;
2c21044f
KS
63
64 if (!de)
65 break;
66
67 if (!dirent_is_file_with_suffix(de, suffix))
68 continue;
69
fabe5c0e
LP
70 p = strjoin(dirpath, "/", de->d_name, NULL);
71 if (!p)
e02caf30 72 return -ENOMEM;
2c21044f 73
fabe5c0e
LP
74 r = hashmap_put(h, path_get_file_name(p), p);
75 if (r == -EEXIST) {
76 log_debug("Skipping overridden file: %s.", p);
77 free(p);
78 } else if (r < 0) {
79 free(p);
80 return r;
81 } else if (r == 0) {
82 log_debug("Duplicate file %s", p);
2c21044f
KS
83 free(p);
84 }
85 }
86
e02caf30 87 return 0;
2c21044f
KS
88}
89
90static int base_cmp(const void *a, const void *b) {
91 const char *s1, *s2;
92
93 s1 = *(char * const *)a;
94 s2 = *(char * const *)b;
9eb977db 95 return strcmp(path_get_file_name(s1), path_get_file_name(s2));
2c21044f
KS
96}
97
fabe5c0e
LP
98static int conf_files_list_strv_internal(char ***strv, const char *suffix, const char *root, char **dirs) {
99 Hashmap *fh;
100 char **files, **p;
578ac060 101 int r;
2c21044f 102
fabe5c0e
LP
103 assert(strv);
104 assert(suffix);
105
106 /* This alters the dirs string array */
107 if (!path_strv_canonicalize_uniq(dirs))
108 return -ENOMEM;
2c21044f
KS
109
110 fh = hashmap_new(string_hash_func, string_compare_func);
fabe5c0e
LP
111 if (!fh)
112 return -ENOMEM;
2c21044f
KS
113
114 STRV_FOREACH(p, dirs) {
7850b3b8 115 r = files_add(fh, root, *p, suffix);
fabe5c0e
LP
116 if (r == -ENOMEM) {
117 hashmap_free_free(fh);
118 return r;
119 } else if (r < 0)
120 log_debug("Failed to search for files in %s: %s",
121 *p, strerror(-r));
2c21044f
KS
122 }
123
124 files = hashmap_get_strv(fh);
125 if (files == NULL) {
fabe5c0e
LP
126 hashmap_free_free(fh);
127 return -ENOMEM;
2c21044f 128 }
fabe5c0e 129
2c21044f 130 qsort(files, hashmap_size(fh), sizeof(char *), base_cmp);
fabe5c0e 131 *strv = files;
2c21044f 132
2c21044f 133 hashmap_free(fh);
fabe5c0e
LP
134 return 0;
135}
136
844ec79b 137int conf_files_list_strv(char ***strv, const char *suffix, const char *root, const char* const* dirs) {
fabe5c0e
LP
138 _cleanup_strv_free_ char **copy = NULL;
139
140 assert(strv);
141 assert(suffix);
142
143 copy = strv_copy((char**) dirs);
144 if (!copy)
145 return -ENOMEM;
146
147 return conf_files_list_strv_internal(strv, suffix, root, copy);
2c21044f
KS
148}
149
7850b3b8 150int conf_files_list(char ***strv, const char *suffix, const char *root, const char *dir, ...) {
fabe5c0e 151 _cleanup_strv_free_ char **dirs = NULL;
2c21044f 152 va_list ap;
fabe5c0e
LP
153
154 assert(strv);
155 assert(suffix);
2c21044f
KS
156
157 va_start(ap, dir);
158 dirs = strv_new_ap(dir, ap);
159 va_end(ap);
2c21044f 160
fabe5c0e
LP
161 if (!dirs)
162 return -ENOMEM;
163
164 return conf_files_list_strv_internal(strv, suffix, root, dirs);
165}
2c21044f 166
fabe5c0e
LP
167int conf_files_list_nulstr(char ***strv, const char *suffix, const char *root, const char *d) {
168 _cleanup_strv_free_ char **dirs = NULL;
169
170 assert(strv);
171 assert(suffix);
172
173 dirs = strv_split_nulstr(d);
174 if (!dirs)
175 return -ENOMEM;
2c21044f 176
fabe5c0e 177 return conf_files_list_strv_internal(strv, suffix, root, dirs);
2c21044f 178}