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/>.
31 #include "analyze-verify.h"
33 static int generate_path(char **var, char **filenames) {
36 _cleanup_strv_free_ char **ans = NULL;
39 STRV_FOREACH(filename, filenames) {
42 t = dirname_malloc(*filename);
46 r = strv_consume(&ans, t);
51 assert_se(strv_uniq(ans));
53 r = strv_extend(&ans, "");
57 *var = strv_join(ans, ":");
64 static int verify_socket(Unit *u) {
69 if (u->type != UNIT_SOCKET)
72 /* Cannot run this without the service being around */
74 /* This makes sure instance is created if necessary. */
75 r = socket_instantiate_service(SOCKET(u));
77 log_error_unit(u->id, "Socket %s cannot be started, failed to create instance.",
82 /* This checks both type of sockets */
83 if (UNIT_ISSET(SOCKET(u)->service)) {
86 service = SERVICE(UNIT_DEREF(SOCKET(u)->service));
87 log_debug_unit(u->id, "%s uses %s", u->id, UNIT(service)->id);
89 if (UNIT(service)->load_state != UNIT_LOADED) {
90 log_error_unit(u->id, "Service %s not loaded, %s cannot be started.",
91 UNIT(service)->id, u->id);
99 static int verify_executable(Unit *u, ExecCommand *exec) {
103 if (access(exec->path, X_OK) < 0) {
104 log_error_unit(u->id, "%s: command %s is not executable: %m",
112 static int verify_executables(Unit *u) {
119 exec = u->type == UNIT_SOCKET ? SOCKET(u)->control_command :
120 u->type == UNIT_MOUNT ? MOUNT(u)->control_command :
121 u->type == UNIT_SWAP ? SWAP(u)->control_command : NULL;
122 k = verify_executable(u, exec);
126 if (u->type == UNIT_SERVICE)
127 for (i = 0; i < ELEMENTSOF(SERVICE(u)->exec_command); i++) {
128 k = verify_executable(u, SERVICE(u)->exec_command[i]);
133 if (u->type == UNIT_SOCKET)
134 for (i = 0; i < ELEMENTSOF(SOCKET(u)->exec_command); i++) {
135 k = verify_executable(u, SOCKET(u)->exec_command[i]);
143 static int verify_documentation(Unit *u, bool check_man) {
147 STRV_FOREACH(p, u->documentation) {
148 log_debug_unit(u->id, "%s: found documentation item %s.", u->id, *p);
149 if (check_man && startswith(*p, "man:")) {
150 k = show_man_page(*p + 4, true);
153 log_error_unit(u->id, "%s: can't show %s: %s",
154 u->id, *p, strerror(-r));
156 log_error_unit(u->id, "%s: man %s command failed with code %d",
166 /* Check remote URLs? */
171 static int verify_unit(Unit *u, bool check_man) {
172 _cleanup_bus_error_free_ sd_bus_error err = SD_BUS_ERROR_NULL;
178 if (log_get_max_level() >= LOG_DEBUG)
179 unit_dump(u, stdout, "\t");
181 log_debug_unit(u->id, "Creating %s/start job", u->id);
182 r = manager_add_job(u->manager, JOB_START, u, JOB_REPLACE, false, &err, &j);
183 if (sd_bus_error_is_set(&err))
184 log_error_unit(u->id, "Error: %s: %s",
185 err.name, err.message);
187 log_error_unit(u->id, "Failed to create %s/start: %s",
188 u->id, strerror(-r));
190 k = verify_socket(u);
194 k = verify_executables(u);
198 k = verify_documentation(u, check_man);
205 int verify_units(char **filenames, SystemdRunningAs running_as, bool check_man) {
206 _cleanup_bus_error_free_ sd_bus_error err = SD_BUS_ERROR_NULL;
211 _cleanup_free_ char *var = NULL;
216 Unit *units[strv_length(filenames)];
219 if (strv_isempty(filenames))
223 r = generate_path(&var, filenames);
225 log_error("Failed to generate unit load path: %s", strerror(-r));
229 assert_se(set_unit_path(var) >= 0);
231 r = manager_new(running_as, true, &m);
233 log_error("Failed to initalize manager: %s", strerror(-r));
237 log_debug("Starting manager...");
239 r = manager_startup(m, serial, fdset);
241 log_error("Failed to start manager: %s", strerror(-r));
245 manager_clear_jobs(m);
247 log_debug("Loading remaining units from the command line...");
249 STRV_FOREACH(filename, filenames) {
250 char fname[UNIT_NAME_MAX + 2 + 1] = "./";
252 log_debug("Handling %s...", *filename);
254 /* manager_load_unit does not like pure basenames, so prepend
255 * the local directory, but only for valid names. manager_load_unit
256 * will print the error for other ones. */
257 if (!strchr(*filename, '/') && strlen(*filename) <= UNIT_NAME_MAX) {
258 strncat(fname + 2, *filename, UNIT_NAME_MAX);
259 k = manager_load_unit(m, NULL, fname, &err, &units[count]);
261 k = manager_load_unit(m, NULL, *filename, &err, &units[count]);
263 log_error("Failed to load %s: %s", *filename, strerror(-k));
270 for (i = 0; i < count; i++) {
271 k = verify_unit(units[i], check_man);