X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fload-fragment.c;h=1a87a96194118a6284dde9ceb0421691e9469ffb;hp=6a71d422f4a25e3030be26dee95d900fc0fabff7;hb=0dcc78574905ca0e31694238662002bd36ca65d4;hpb=2e22afe909cd5fa003347aa91ad15f0516e5047f diff --git a/src/load-fragment.c b/src/load-fragment.c index 6a71d422f..1a87a9619 100644 --- a/src/load-fragment.c +++ b/src/load-fragment.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "unit.h" #include "strv.h" @@ -382,7 +383,7 @@ static int config_parse_exec( char *w; size_t l; char *state; - bool honour_argv0, write_to_path; + bool honour_argv0 = false, ignore = false; path = NULL; nce = NULL; @@ -393,9 +394,17 @@ static int config_parse_exec( if (rvalue[0] == 0) break; - honour_argv0 = rvalue[0] == '@'; + if (rvalue[0] == '-') { + ignore = true; + rvalue ++; + } + + if (rvalue[0] == '@') { + honour_argv0 = true; + rvalue ++; + } - if (rvalue[honour_argv0 ? 1 : 0] != '/') { + if (*rvalue != '/') { log_error("[%s:%u] Invalid executable path in command line: %s", filename, line, rvalue); return -EINVAL; } @@ -408,19 +417,18 @@ static int config_parse_exec( k++; } - if (!(n = new(char*, k + (honour_argv0 ? 0 : 1)))) + if (!(n = new(char*, k + !honour_argv0))) return -ENOMEM; k = 0; - write_to_path = honour_argv0; FOREACH_WORD_QUOTED(w, l, rvalue, state) { if (strncmp(w, ";", l) == 0) break; - if (write_to_path) { - if (!(path = cunescape_length(w+1, l-1))) + if (honour_argv0 && w == rvalue) { + assert(!path); + if (!(path = cunescape_length(w, l))) goto fail; - write_to_path = false; } else { if (!(n[k++] = cunescape_length(w, l))) goto fail; @@ -446,6 +454,7 @@ static int config_parse_exec( nce->argv = n; nce->path = path; + nce->ignore = ignore; path_kill_slashes(nce->path); @@ -1303,16 +1312,20 @@ static int open_follow(char **filename, FILE **_f, Set *names, char **_final) { path_kill_slashes(*filename); /* Add the file name we are currently looking at to - * the names of this unit */ + * the names of this unit, but only if it is a valid + * unit name. */ name = file_name_from_path(*filename); - if (!(id = set_get(names, name))) { - if (!(id = strdup(name))) - return -ENOMEM; + if (unit_name_is_valid(name)) { + if (!(id = set_get(names, name))) { - if ((r = set_put(names, id)) < 0) { - free(id); - return r; + if (!(id = strdup(name))) + return -ENOMEM; + + if ((r = set_put(names, id)) < 0) { + free(id); + return r; + } } } @@ -1331,7 +1344,7 @@ static int open_follow(char **filename, FILE **_f, Set *names, char **_final) { *filename = target; } - if (!(f = fdopen(fd, "r"))) { + if (!(f = fdopen(fd, "re"))) { r = -errno; close_nointr_nofail(fd); return r; @@ -1550,10 +1563,14 @@ static int load_from_path(Unit *u, const char *path) { { "Conflicts", config_parse_deps, UINT_TO_PTR(UNIT_CONFLICTS), "Unit" }, { "Before", config_parse_deps, UINT_TO_PTR(UNIT_BEFORE), "Unit" }, { "After", config_parse_deps, UINT_TO_PTR(UNIT_AFTER), "Unit" }, + { "OnFailure", config_parse_deps, UINT_TO_PTR(UNIT_ON_FAILURE), "Unit" }, { "RecursiveStop", config_parse_bool, &u->meta.recursive_stop, "Unit" }, { "StopWhenUnneeded", config_parse_bool, &u->meta.stop_when_unneeded, "Unit" }, - { "OnlyByDependency", config_parse_bool, &u->meta.only_by_dependency, "Unit" }, + { "RefuseManualStart", config_parse_bool, &u->meta.refuse_manual_start, "Unit" }, + { "RefuseManualStop", config_parse_bool, &u->meta.refuse_manual_stop, "Unit" }, { "DefaultDependencies", config_parse_bool, &u->meta.default_dependencies, "Unit" }, + { "IgnoreDependencyFailure",config_parse_bool, &u->meta.ignore_dependency_failure, "Unit" }, + { "JobTimeoutSec", config_parse_usec, &u->meta.job_timeout, "Unit" }, { "PIDFile", config_parse_path, &u->service.pid_file, "Service" }, { "ExecStartPre", config_parse_exec, u->service.exec_command+SERVICE_EXEC_START_PRE, "Service" }, @@ -1600,6 +1617,7 @@ static int load_from_path(Unit *u, const char *path) { { "Mark", config_parse_int, &u->socket.mark, "Socket" }, { "PipeSize", config_parse_size, &u->socket.pipe_size, "Socket" }, { "FreeBind", config_parse_bool, &u->socket.free_bind, "Socket" }, + { "TCPCongestion", config_parse_string, &u->socket.tcp_congestion, "Socket" }, EXEC_CONTEXT_CONFIG_ITEMS(u->socket.exec_context, "Socket"), { "What", config_parse_string, &u->mount.parameters_fragment.what, "Mount" }, @@ -1644,6 +1662,7 @@ static int load_from_path(Unit *u, const char *path) { FILE *f = NULL; char *filename = NULL, *id = NULL; Unit *merged; + struct stat st; if (!u) { /* Dirty dirty hack. */ @@ -1690,7 +1709,13 @@ static int load_from_path(Unit *u, const char *path) { goto finish; } - if ((r = open_follow(&filename, &f, symlink_names, &id)) < 0) { + if (u->meta.manager->unit_path_cache && + !set_get(u->meta.manager->unit_path_cache, filename)) + r = -ENOENT; + else + r = open_follow(&filename, &f, symlink_names, &id); + + if (r < 0) { char *sn; free(filename); @@ -1711,6 +1736,7 @@ static int load_from_path(Unit *u, const char *path) { } if (!filename) { + /* Hmm, no suitable file found? */ r = 0; goto finish; } @@ -1725,6 +1751,12 @@ static int load_from_path(Unit *u, const char *path) { goto finish; } + zero(st); + if (fstat(fileno(f), &st) < 0) { + r = -errno; + goto finish; + } + /* Now, parse the file contents */ if ((r = config_parse(filename, f, sections, items, false, u)) < 0) goto finish; @@ -1733,6 +1765,8 @@ static int load_from_path(Unit *u, const char *path) { u->meta.fragment_path = filename; filename = NULL; + u->meta.fragment_mtime = timespec_load(&st.st_mtim); + u->meta.load_state = UNIT_LOADED; r = 0; @@ -1748,68 +1782,69 @@ finish: int unit_load_fragment(Unit *u) { int r; + Iterator i; + const char *t; assert(u); + assert(u->meta.load_state == UNIT_STUB); + assert(u->meta.id); + + /* First, try to find the unit under its id. We always look + * for unit files in the default directories, to make it easy + * to override things by placing things in /etc/systemd/system */ + if ((r = load_from_path(u, u->meta.id)) < 0) + return r; + + /* Try to find an alias we can load this with */ + if (u->meta.load_state == UNIT_STUB) + SET_FOREACH(t, u->meta.names, i) { - if (u->meta.fragment_path) { + if (t == u->meta.id) + continue; + + if ((r = load_from_path(u, t)) < 0) + return r; + + if (u->meta.load_state != UNIT_STUB) + break; + } + /* And now, try looking for it under the suggested (originally linked) path */ + if (u->meta.load_state == UNIT_STUB && u->meta.fragment_path) if ((r = load_from_path(u, u->meta.fragment_path)) < 0) return r; - } else { - Iterator i; - const char *t; + /* Look for a template */ + if (u->meta.load_state == UNIT_STUB && u->meta.instance) { + char *k; + + if (!(k = unit_name_template(u->meta.id))) + return -ENOMEM; - /* Try to find the unit under its id */ - if ((r = load_from_path(u, u->meta.id)) < 0) + r = load_from_path(u, k); + free(k); + + if (r < 0) return r; - /* Try to find an alias we can load this with */ if (u->meta.load_state == UNIT_STUB) SET_FOREACH(t, u->meta.names, i) { if (t == u->meta.id) continue; - if ((r = load_from_path(u, t)) < 0) + if (!(k = unit_name_template(t))) + return -ENOMEM; + + r = load_from_path(u, k); + free(k); + + if (r < 0) return r; if (u->meta.load_state != UNIT_STUB) break; } - - /* Now, follow the same logic, but look for a template */ - if (u->meta.load_state == UNIT_STUB && u->meta.instance) { - char *k; - - if (!(k = unit_name_template(u->meta.id))) - return -ENOMEM; - - r = load_from_path(u, k); - free(k); - - if (r < 0) - return r; - - if (u->meta.load_state == UNIT_STUB) - SET_FOREACH(t, u->meta.names, i) { - - if (t == u->meta.id) - continue; - - if (!(k = unit_name_template(t))) - return -ENOMEM; - - r = load_from_path(u, k); - free(k); - - if (r < 0) - return r; - - if (u->meta.load_state != UNIT_STUB) - break; - } - } } return 0;