X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fshared%2Finstall.c;h=26dbbb6f07c155cbe7b5d092e9e85b2eb31df971;hb=8f294b45cbb627d31342f6a79444be59ce7e2274;hp=a6a9f19e75b38b773dd8b7b25f614399665e8243;hpb=1dacfd2ad643019f41fb979f5a8c144172911f85;p=elogind.git diff --git a/src/shared/install.c b/src/shared/install.c index a6a9f19e7..26dbbb6f0 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -47,6 +47,37 @@ typedef struct { #define _cleanup_install_context_done_ _cleanup_(install_context_done) +static int in_search_path(const char *path, char **search, const char *root_dir) { + _cleanup_free_ char *parent = NULL; + char **i; + int r; + + assert(path); + + r = path_get_parent(path, &parent); + if (r < 0) + return r; + + STRV_FOREACH(i, search) { + _cleanup_free_ char *buf = NULL; + const char *p; + + if (root_dir) { + buf = strjoin(root_dir, "/", *i, NULL); + if (!buf) + return -ENOMEM; + + p = buf; + } else + p = *i; + + if (path_equal(parent, p)) + return 1; + } + + return 0; +} + static int lookup_paths_init_from_scope(LookupPaths *paths, UnitFileScope scope, const char *root_dir) { @@ -266,8 +297,22 @@ static int remove_marked_symlinks_fd( if (unit_name_is_instance(de->d_name) && instance_whitelist && - !strv_contains(instance_whitelist, de->d_name)) - continue; + !strv_contains(instance_whitelist, de->d_name)) { + + _cleanup_free_ char *w; + + /* OK, the file is not listed directly + * in the whitelist, so let's check if + * the template of it might be + * listed. */ + + w = unit_name_template(de->d_name); + if (!w) + return -ENOMEM; + + if (!strv_contains(instance_whitelist, w)) + continue; + } p = path_make_absolute(de->d_name, path); if (!p) @@ -290,18 +335,14 @@ static int remove_marked_symlinks_fd( if (!found) continue; - if (unlink(p) < 0 && errno != ENOENT) { - if (r == 0) r = -errno; continue; } - rmdir_parents(p, config_path); - path_kill_slashes(p); - + rmdir_parents(p, config_path); add_file_change(changes, n_changes, UNIT_FILE_UNLINK, p, NULL); if (!set_get(remove_symlinks_to, p)) { @@ -603,13 +644,9 @@ int unit_file_mask( continue; if (force) { - unlink(path); - - if (symlink("/dev/null", path) >= 0) { - + if (symlink_atomic("/dev/null", path) >= 0) { add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL); add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null"); - continue; } } @@ -740,7 +777,7 @@ int unit_file_link( continue; } - q = in_search_path(*i, paths.unit_path); + q = in_search_path(*i, paths.unit_path, root_dir); if (q < 0) return q; @@ -770,13 +807,9 @@ int unit_file_link( continue; if (force) { - unlink(path); - - if (symlink(*i, path) >= 0) { - + if (symlink_atomic(*i, path) >= 0) { add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL); add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i); - continue; } } @@ -827,6 +860,7 @@ static void install_info_free(InstallInfo *i) { strv_free(i->aliases); strv_free(i->wanted_by); strv_free(i->required_by); + free(i->default_instance); free(i); } @@ -919,16 +953,17 @@ static int install_info_add_auto( return install_info_add(c, name_or_path, NULL); } -static int config_parse_also(const char *unit, - const char *filename, - unsigned line, - const char *section, - unsigned section_line, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +static int config_parse_also( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { char *w; size_t l; @@ -955,19 +990,20 @@ static int config_parse_also(const char *unit, return 0; } -static int config_parse_user(const char *unit, - const char *filename, - unsigned line, - const char *section, - unsigned section_line, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +static int config_parse_user( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { InstallInfo *i = data; - char* printed; + char *printed; int r; assert(filename); @@ -984,6 +1020,39 @@ static int config_parse_user(const char *unit, return 0; } +static int config_parse_default_instance( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + InstallInfo *i = data; + char *printed; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + r = install_full_printf(i, rvalue, &printed); + if (r < 0) + return r; + + if (!unit_instance_is_valid(printed)) + return -EINVAL; + + free(i->default_instance); + i->default_instance = printed; + + return 0; +} + static int unit_file_load( InstallContext *c, InstallInfo *info, @@ -991,12 +1060,13 @@ static int unit_file_load( bool allow_symlink) { const ConfigTableItem items[] = { - { "Install", "Alias", config_parse_strv, 0, &info->aliases }, - { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by }, - { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by }, - { "Install", "Also", config_parse_also, 0, c }, - { "Exec", "User", config_parse_user, 0, info }, - { NULL, NULL, NULL, 0, NULL } + { "Install", "Alias", config_parse_strv, 0, &info->aliases }, + { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by }, + { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by }, + { "Install", "DefaultInstance", config_parse_default_instance, 0, info }, + { "Install", "Also", config_parse_also, 0, c }, + { "Exec", "User", config_parse_user, 0, info }, + {} }; int fd; @@ -1017,8 +1087,7 @@ static int unit_file_load( return -ENOMEM; } - r = config_parse(NULL, path, f, NULL, - config_item_table_lookup, (void*) items, true, true, info); + r = config_parse(NULL, path, f, NULL, config_item_table_lookup, (void*) items, true, true, info); if (r < 0) return r; @@ -1043,67 +1112,69 @@ static int unit_file_search( assert(paths); if (info->path) { - char *full_path = NULL; + const char *path; - if (!isempty(root_dir)) - full_path = strappenda(root_dir, info->path); + if (isempty(root_dir)) + path = info->path; + else + path = strappenda(root_dir, info->path); - return unit_file_load(c, info, full_path ?: info->path, allow_symlink); + return unit_file_load(c, info, path, allow_symlink); } assert(info->name); STRV_FOREACH(p, paths->unit_path) { - _cleanup_free_ char *path = NULL, *full_path = NULL; + _cleanup_free_ char *path = NULL; - path = strjoin(*p, "/", info->name, NULL); + if (isempty(root_dir)) + path = strjoin(*p, "/", info->name, NULL); + else + path = strjoin(root_dir, "/", *p, "/", info->name, NULL); if (!path) return -ENOMEM; - if (!isempty(root_dir)) { - full_path = strappend(root_dir, path); - if (!full_path) - return -ENOMEM; - } - - r = unit_file_load(c, info, full_path ?: path, allow_symlink); + r = unit_file_load(c, info, path, allow_symlink); if (r >= 0) { info->path = path; path = NULL; - } else if (r == -ENOENT && unit_name_is_instance(info->name)) { - /* Unit file doesn't exist, however instance enablement was requested. - * We will check if it is possible to load template unit file. */ - _cleanup_free_ char *template = NULL, *template_dir = NULL; + return r; + } + if (r != -ENOENT && r != -ELOOP) + return r; + } - template = unit_name_template(info->name); - if (!template) - return -ENOMEM; + if (unit_name_is_instance(info->name)) { - /* We will reuse path variable since we don't need it anymore. */ - template_dir = path; - *(strrchr(template_dir, '/') + 1) = '\0'; + /* Unit file doesn't exist, however instance + * enablement was requested. We will check if it is + * possible to load template unit file. */ - path = strappend(template_dir, template); + _cleanup_free_ char *template = NULL, *template_dir = NULL; + + template = unit_name_template(info->name); + if (!template) + return -ENOMEM; + + STRV_FOREACH(p, paths->unit_path) { + _cleanup_free_ char *path = NULL; + + if (isempty(root_dir)) + path = strjoin(*p, "/", template, NULL); + else + path = strjoin(root_dir, "/", *p, "/", template, NULL); if (!path) return -ENOMEM; - if (!isempty(root_dir)) { - free(full_path); - full_path = strappend(root_dir, path); - if (!full_path) - return -ENOMEM; - } - - /* Let's try to load template unit. */ - r = unit_file_load(c, info, full_path ?: path, allow_symlink); + r = unit_file_load(c, info, path, allow_symlink); if (r >= 0) { info->path = path; path = NULL; + return r; } + if (r != -ENOENT && r != -ELOOP) + return r; } - - if (r != -ENOENT && r != -ELOOP) - return r; } return -ENOENT; @@ -1172,17 +1243,14 @@ static int create_symlink( if (!force) return -EEXIST; - r = unlink(new_path); - if (r < 0 && errno != ENOENT) - return -errno; + r = symlink_atomic(old_path, new_path); + if (r < 0) + return r; - if (symlink(old_path, new_path) >= 0) { - add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL); - add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path); - return 0; - } + add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL); + add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path); - return -errno; + return 0; } static int install_info_symlink_alias( @@ -1220,54 +1288,30 @@ static int install_info_symlink_alias( static int install_info_symlink_wants( InstallInfo *i, const char *config_path, + char **list, + const char *suffix, bool force, UnitFileChange **changes, unsigned *n_changes) { + _cleanup_free_ char *buf = NULL; + const char *n; char **s; int r = 0, q; assert(i); assert(config_path); - STRV_FOREACH(s, i->wanted_by) { - _cleanup_free_ char *path = NULL, *dst = NULL; - - q = install_full_printf(i, *s, &dst); - if (q < 0) - return q; - - if (!unit_name_is_valid(dst, TEMPLATE_VALID)) { - r = -EINVAL; - continue; - } - - if (asprintf(&path, "%s/%s.wants/%s", config_path, dst, i->name) < 0) + if (unit_name_is_template(i->name) && i->default_instance) { + buf = unit_name_replace_instance(i->name, i->default_instance); + if (!buf) return -ENOMEM; - q = create_symlink(i->path, path, force, changes, n_changes); - - if (r == 0) - r = q; - } - - return r; -} - -static int install_info_symlink_requires( - InstallInfo *i, - const char *config_path, - bool force, - UnitFileChange **changes, - unsigned *n_changes) { - - char **s; - int r = 0, q; - - assert(i); - assert(config_path); + n = buf; + } else + n = i->name; - STRV_FOREACH(s, i->required_by) { + STRV_FOREACH(s, list) { _cleanup_free_ char *path = NULL, *dst = NULL; q = install_full_printf(i, *s, &dst); @@ -1279,11 +1323,11 @@ static int install_info_symlink_requires( continue; } - if (asprintf(&path, "%s/%s.requires/%s", config_path, dst, i->name) < 0) + path = strjoin(config_path, "/", dst, suffix, n, NULL); + if (!path) return -ENOMEM; q = create_symlink(i->path, path, force, changes, n_changes); - if (r == 0) r = q; } @@ -1295,6 +1339,7 @@ static int install_info_symlink_link( InstallInfo *i, LookupPaths *paths, const char *config_path, + const char *root_dir, bool force, UnitFileChange **changes, unsigned *n_changes) { @@ -1307,7 +1352,7 @@ static int install_info_symlink_link( assert(config_path); assert(i->path); - r = in_search_path(i->path, paths->unit_path); + r = in_search_path(i->path, paths->unit_path, root_dir); if (r != 0) return r; @@ -1322,6 +1367,7 @@ static int install_info_apply( InstallInfo *i, LookupPaths *paths, const char *config_path, + const char *root_dir, bool force, UnitFileChange **changes, unsigned *n_changes) { @@ -1334,15 +1380,15 @@ static int install_info_apply( r = install_info_symlink_alias(i, config_path, force, changes, n_changes); - q = install_info_symlink_wants(i, config_path, force, changes, n_changes); + q = install_info_symlink_wants(i, config_path, i->wanted_by, ".wants/", force, changes, n_changes); if (r == 0) r = q; - q = install_info_symlink_requires(i, config_path, force, changes, n_changes); + q = install_info_symlink_wants(i, config_path, i->required_by, ".requires/", force, changes, n_changes); if (r == 0) r = q; - q = install_info_symlink_link(i, paths, config_path, force, changes, n_changes); + q = install_info_symlink_link(i, paths, config_path, root_dir, force, changes, n_changes); if (r == 0) r = q; @@ -1382,7 +1428,7 @@ static int install_context_apply( } else if (r >= 0) r += q; - q = install_info_apply(i, paths, config_path, force, changes, n_changes); + q = install_info_apply(i, paths, config_path, root_dir, force, changes, n_changes); if (r >= 0 && q < 0) r = q; }