]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/conf-files.c
run: add support for executing commands remotely via SSH or in a container
[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
7ff7394d 130 qsort_safe(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, ...) {
250a918d 151 char **dirs;
fabe5c0e
LP
152
153 assert(strv);
154 assert(suffix);
2c21044f 155
250a918d 156 dirs = strv_from_stdarg_alloca(dir);
fabe5c0e
LP
157
158 return conf_files_list_strv_internal(strv, suffix, root, dirs);
159}
2c21044f 160
fabe5c0e
LP
161int conf_files_list_nulstr(char ***strv, const char *suffix, const char *root, const char *d) {
162 _cleanup_strv_free_ char **dirs = NULL;
163
164 assert(strv);
165 assert(suffix);
166
167 dirs = strv_split_nulstr(d);
168 if (!dirs)
169 return -ENOMEM;
2c21044f 170
fabe5c0e 171 return conf_files_list_strv_internal(strv, suffix, root, dirs);
2c21044f 172}