1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2014 Zbigniew Jędrzejewski-Szmek
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.
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.
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/>.
29 #include "analyze-verify.h"
31 static int generate_path(char **var, char **filenames) {
34 _cleanup_strv_free_ char **ans = NULL;
37 STRV_FOREACH(filename, filenames) {
40 t = dirname_malloc(*filename);
44 r = strv_consume(&ans, t);
49 assert_se(strv_uniq(ans));
51 r = strv_extend(&ans, "");
55 *var = strv_join(ans, ":");
62 static int verify_socket(Unit *u) {
67 if (u->type != UNIT_SOCKET)
70 /* Cannot run this without the service being around */
72 /* This makes sure instance is created if necessary. */
73 r = socket_instantiate_service(SOCKET(u));
75 log_unit_error(u->id, "Socket %s cannot be started, failed to create instance.",
80 /* This checks both type of sockets */
81 if (UNIT_ISSET(SOCKET(u)->service)) {
84 service = SERVICE(UNIT_DEREF(SOCKET(u)->service));
85 log_unit_debug(u->id, "%s uses %s", u->id, UNIT(service)->id);
87 if (UNIT(service)->load_state != UNIT_LOADED) {
88 log_unit_error(u->id, "Service %s not loaded, %s cannot be started.",
89 UNIT(service)->id, u->id);
97 static int verify_executable(Unit *u, ExecCommand *exec) {
101 if (access(exec->path, X_OK) < 0) {
102 log_unit_error(u->id, "%s: command %s is not executable: %m",
110 static int verify_executables(Unit *u) {
117 exec = u->type == UNIT_SOCKET ? SOCKET(u)->control_command :
118 u->type == UNIT_MOUNT ? MOUNT(u)->control_command :
119 u->type == UNIT_SWAP ? SWAP(u)->control_command : NULL;
120 k = verify_executable(u, exec);
124 if (u->type == UNIT_SERVICE)
125 for (i = 0; i < ELEMENTSOF(SERVICE(u)->exec_command); i++) {
126 k = verify_executable(u, SERVICE(u)->exec_command[i]);
131 if (u->type == UNIT_SOCKET)
132 for (i = 0; i < ELEMENTSOF(SOCKET(u)->exec_command); i++) {
133 k = verify_executable(u, SOCKET(u)->exec_command[i]);
141 static int verify_documentation(Unit *u, bool check_man) {
145 STRV_FOREACH(p, u->documentation) {
146 log_unit_debug(u->id, "%s: found documentation item %s.", u->id, *p);
147 if (check_man && startswith(*p, "man:")) {
148 k = show_man_page(*p + 4, true);
151 log_unit_error(u->id, "%s: can't show %s: %s",
152 u->id, *p, strerror(-r));
154 log_unit_error(u->id, "%s: man %s command failed with code %d",
164 /* Check remote URLs? */
169 static int verify_unit(Unit *u, bool check_man) {
170 _cleanup_bus_error_free_ sd_bus_error err = SD_BUS_ERROR_NULL;
176 if (log_get_max_level() >= LOG_DEBUG)
177 unit_dump(u, stdout, "\t");
179 log_unit_debug(u->id, "Creating %s/start job", u->id);
180 r = manager_add_job(u->manager, JOB_START, u, JOB_REPLACE, false, &err, &j);
181 if (sd_bus_error_is_set(&err))
182 log_unit_error(u->id, "Error: %s: %s",
183 err.name, err.message);
185 log_unit_error(u->id, "Failed to create %s/start: %s",
186 u->id, strerror(-r));
188 k = verify_socket(u);
192 k = verify_executables(u);
196 k = verify_documentation(u, check_man);
203 int verify_units(char **filenames, SystemdRunningAs running_as, bool check_man) {
204 _cleanup_bus_error_free_ sd_bus_error err = SD_BUS_ERROR_NULL;
209 _cleanup_free_ char *var = NULL;
214 Unit *units[strv_length(filenames)];
217 if (strv_isempty(filenames))
221 r = generate_path(&var, filenames);
223 return log_error_errno(r, "Failed to generate unit load path: %m");
225 assert_se(set_unit_path(var) >= 0);
227 r = manager_new(running_as, true, &m);
229 return log_error_errno(r, "Failed to initalize manager: %m");
231 log_debug("Starting manager...");
233 r = manager_startup(m, serial, fdset);
235 log_error_errno(r, "Failed to start manager: %m");
239 manager_clear_jobs(m);
241 log_debug("Loading remaining units from the command line...");
243 STRV_FOREACH(filename, filenames) {
244 char fname[UNIT_NAME_MAX + 2 + 1] = "./";
246 log_debug("Handling %s...", *filename);
248 /* manager_load_unit does not like pure basenames, so prepend
249 * the local directory, but only for valid names. manager_load_unit
250 * will print the error for other ones. */
251 if (!strchr(*filename, '/') && strlen(*filename) <= UNIT_NAME_MAX) {
252 strncat(fname + 2, *filename, UNIT_NAME_MAX);
253 k = manager_load_unit(m, NULL, fname, &err, &units[count]);
255 k = manager_load_unit(m, NULL, *filename, &err, &units[count]);
257 log_error_errno(k, "Failed to load %s: %m", *filename);
264 for (i = 0; i < count; i++) {
265 k = verify_unit(units[i], check_man);