chiark / gitweb /
replace more dup() by F_DUPFD_CLOEXEC
[elogind.git] / src / shared / install.c
index 116106824f9e91de3b4bbc82493aec873abd16db..9ce94035b92096e316a051e5c66dae32827427cd 100644 (file)
 #include "conf-files.h"
 #include "specifier.h"
 #include "install-printf.h"
+#include "special.h"
 
 typedef struct {
         Hashmap *will_install;
         Hashmap *have_installed;
 } InstallContext;
 
-#define _cleanup_lookup_paths_free_ \
-        __attribute__((cleanup(lookup_paths_free)))
-#define _cleanup_install_context_done_ \
-        __attribute__((cleanup(install_context_done)))
+#define _cleanup_install_context_done_ _cleanup_(install_context_done)
 
 static int lookup_paths_init_from_scope(LookupPaths *paths, UnitFileScope scope) {
         assert(paths);
@@ -206,7 +204,7 @@ static int remove_marked_symlinks_fd(
 
         d = fdopendir(fd);
         if (!d) {
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 return -errno;
         }
 
@@ -214,11 +212,10 @@ static int remove_marked_symlinks_fd(
 
         for (;;) {
                 struct dirent *de;
-                union dirent_storage buf;
-                int k;
 
-                k = readdir_r(d, &buf.de, &de);
-                if (k != 0) {
+                errno = 0;
+                de = readdir(d);
+                if (!de && errno != 0) {
                         r = -errno;
                         break;
                 }
@@ -247,7 +244,7 @@ static int remove_marked_symlinks_fd(
 
                         p = path_make_absolute(de->d_name, path);
                         if (!p) {
-                                close_nointr_nofail(nfd);
+                                safe_close(nfd);
                                 return -ENOMEM;
                         }
 
@@ -278,10 +275,10 @@ static int remove_marked_symlinks_fd(
 
                         found =
                                 set_get(remove_symlinks_to, dest) ||
-                                set_get(remove_symlinks_to, path_get_file_name(dest));
+                                set_get(remove_symlinks_to, basename(dest));
 
                         if (unit_name_is_instance(p))
-                                found = found && strv_contains(files, path_get_file_name(p));
+                                found = found && strv_contains(files, basename(p));
 
                         if (found) {
 
@@ -335,7 +332,7 @@ static int remove_marked_symlinks(
                 int q, cfd;
                 deleted = false;
 
-                cfd = dup(fd);
+                cfd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
                 if (cfd < 0) {
                         r = -errno;
                         break;
@@ -347,7 +344,7 @@ static int remove_marked_symlinks(
                         r = q;
         } while (deleted);
 
-        close_nointr_nofail(fd);
+        safe_close(fd);
 
         return r;
 }
@@ -370,17 +367,16 @@ static int find_symlinks_fd(
 
         d = fdopendir(fd);
         if (!d) {
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 return -errno;
         }
 
         for (;;) {
-                int k;
                 struct dirent *de;
-                union dirent_storage buf;
 
-                k = readdir_r(d, &buf.de, &de);
-                if (k != 0)
+                errno = 0;
+                de = readdir(d);
+                if (!de && errno != 0)
                         return -errno;
 
                 if (!de)
@@ -407,7 +403,7 @@ static int find_symlinks_fd(
 
                         p = path_make_absolute(de->d_name, path);
                         if (!p) {
-                                close_nointr_nofail(nfd);
+                                safe_close(nfd);
                                 return -ENOMEM;
                         }
 
@@ -453,7 +449,7 @@ static int find_symlinks_fd(
                         if (path_is_absolute(name))
                                 found_dest = path_equal(dest, name);
                         else
-                                found_dest = streq(path_get_file_name(dest), name);
+                                found_dest = streq(basename(dest), name);
 
                         if (found_path && found_dest) {
                                 _cleanup_free_ char *t = NULL;
@@ -473,8 +469,6 @@ static int find_symlinks_fd(
                                 return 1;
                 }
         }
-
-        return r;
 }
 
 static int find_symlinks(
@@ -560,7 +554,7 @@ int unit_file_mask(
                 UnitFileScope scope,
                 bool runtime,
                 const char *root_dir,
-                char *files[],
+                char **files,
                 bool force,
                 UnitFileChange **changes,
                 unsigned *n_changes) {
@@ -579,7 +573,7 @@ int unit_file_mask(
         STRV_FOREACH(i, files) {
                 _cleanup_free_ char *path = NULL;
 
-                if (!unit_name_is_valid(*i, true)) {
+                if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
                         if (r == 0)
                                 r = -EINVAL;
                         continue;
@@ -629,7 +623,7 @@ int unit_file_unmask(
                 UnitFileScope scope,
                 bool runtime,
                 const char *root_dir,
-                char *files[],
+                char **files,
                 UnitFileChange **changes,
                 unsigned *n_changes) {
 
@@ -647,7 +641,7 @@ int unit_file_unmask(
         STRV_FOREACH(i, files) {
                 char *path;
 
-                if (!unit_name_is_valid(*i, true)) {
+                if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
                         if (r == 0)
                                 r = -EINVAL;
                         continue;
@@ -694,7 +688,7 @@ int unit_file_link(
                 UnitFileScope scope,
                 bool runtime,
                 const char *root_dir,
-                char *files[],
+                char **files,
                 bool force,
                 UnitFileChange **changes,
                 unsigned *n_changes) {
@@ -720,10 +714,10 @@ int unit_file_link(
                 char *fn;
                 struct stat st;
 
-                fn = path_get_file_name(*i);
+                fn = basename(*i);
 
                 if (!path_is_absolute(*i) ||
-                    !unit_name_is_valid(fn, true)) {
+                    !unit_name_is_valid(fn, TEMPLATE_VALID)) {
                         if (r == 0)
                                 r = -EINVAL;
                         continue;
@@ -863,9 +857,9 @@ static int install_info_add(
         assert(name || path);
 
         if (!name)
-                name = path_get_file_name(path);
+                name = basename(path);
 
-        if (!unit_name_is_valid(name, true))
+        if (!unit_name_is_valid(name, TEMPLATE_VALID))
                 return -EINVAL;
 
         if (hashmap_get(c->have_installed, name) ||
@@ -924,6 +918,7 @@ 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,
@@ -959,6 +954,7 @@ 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,
@@ -967,14 +963,15 @@ static int config_parse_user(const char *unit,
 
         InstallInfo *i = data;
         char* printed;
+        int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
 
-        printed = install_full_printf(i, rvalue);
-        if (!printed)
-                return -ENOMEM;
+        r = install_full_printf(i, rvalue, &printed);
+        if (r < 0)
+                return r;
 
         free(i->user);
         i->user = printed;
@@ -1011,7 +1008,7 @@ static int unit_file_load(
 
         f = fdopen(fd, "re");
         if (!f) {
-                close_nointr_nofail(fd);
+                safe_close(fd);
                 return -ENOMEM;
         }
 
@@ -1021,9 +1018,9 @@ static int unit_file_load(
                 return r;
 
         return
-                strv_length(info->aliases) +
-                strv_length(info->wanted_by) +
-                strv_length(info->required_by);
+                (int) strv_length(info->aliases) +
+                (int) strv_length(info->wanted_by) +
+                (int) strv_length(info->required_by);
 }
 
 static int unit_file_search(
@@ -1062,8 +1059,8 @@ static int unit_file_search(
                         info->path = path;
                 else {
                         if (r == -ENOENT && unit_name_is_instance(info->name)) {
-                                /* unit file doesn't exist, however instance enablement was request */
-                                /* we will check if it is possible to load template unit file */
+                                /* Unit file doesn't exist, however instance enablement was requested.
+                                 * We will check if it is possible to load template unit file. */
                                 char *template = NULL,
                                      *template_path = NULL,
                                      *template_dir = NULL;
@@ -1074,7 +1071,7 @@ static int unit_file_search(
                                         return -ENOMEM;
                                 }
 
-                                /* we will reuse path variable since we don't need it anymore */
+                                /* We will reuse path variable since we don't need it anymore. */
                                 template_dir = path;
                                 *(strrchr(path, '/') + 1) = '\0';
 
@@ -1085,7 +1082,7 @@ static int unit_file_search(
                                         return -ENOMEM;
                                 }
 
-                                /* let's try to load template unit */
+                                /* Let's try to load template unit. */
                                 r = unit_file_load(c, info, template_path, allow_symlink);
                                 if (r >= 0) {
                                         info->path = strdup(template_path);
@@ -1133,9 +1130,9 @@ static int unit_file_can_install(
 
         if (r >= 0)
                 r =
-                        strv_length(i->aliases) +
-                        strv_length(i->wanted_by) +
-                        strv_length(i->required_by);
+                        (int) strv_length(i->aliases) +
+                        (int) strv_length(i->wanted_by) +
+                        (int) strv_length(i->required_by);
 
         return r;
 }
@@ -1173,7 +1170,9 @@ static int create_symlink(
         if (!force)
                 return -EEXIST;
 
-        unlink(new_path);
+        r = unlink(new_path);
+        if (r < 0 && errno != ENOENT)
+                return -errno;
 
         if (symlink(old_path, new_path) >= 0) {
                 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
@@ -1200,9 +1199,9 @@ static int install_info_symlink_alias(
         STRV_FOREACH(s, i->aliases) {
                 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
 
-                dst = install_full_printf(i, *s);
-                if (!dst)
-                        return -ENOMEM;
+                q = install_full_printf(i, *s, &dst);
+                if (q < 0)
+                        return q;
 
                 alias_path = path_make_absolute(dst, config_path);
                 if (!alias_path)
@@ -1232,11 +1231,11 @@ static int install_info_symlink_wants(
         STRV_FOREACH(s, i->wanted_by) {
                 _cleanup_free_ char *path = NULL, *dst = NULL;
 
-                dst = install_full_printf(i, *s);
-                if (!dst)
-                        return -ENOMEM;
+                q = install_full_printf(i, *s, &dst);
+                if (q < 0)
+                        return q;
 
-                if (!unit_name_is_valid(dst, true)) {
+                if (!unit_name_is_valid(dst, TEMPLATE_VALID)) {
                         r = -EINVAL;
                         continue;
                 }
@@ -1269,11 +1268,11 @@ static int install_info_symlink_requires(
         STRV_FOREACH(s, i->required_by) {
                 _cleanup_free_ char *path = NULL, *dst = NULL;
 
-                dst = install_full_printf(i, *s);
-                if (!dst)
-                        return -ENOMEM;
+                q = install_full_printf(i, *s, &dst);
+                if (q < 0)
+                        return q;
 
-                if (!unit_name_is_valid(dst, true)) {
+                if (!unit_name_is_valid(dst, TEMPLATE_VALID)) {
                         r = -EINVAL;
                         continue;
                 }
@@ -1425,16 +1424,30 @@ static int install_context_mark_for_removal(
                         r += q;
 
                 if (unit_name_is_instance(i->name)) {
-                        char *unit_file = NULL;
+                        char *unit_file;
+
+                        if (i->path) {
+                                unit_file = basename(i->path);
+
+                                if (unit_name_is_instance(unit_file))
+                                        /* unit file named as instance exists, thus all symlinks
+                                         * pointing to it will be removed */
+                                        q = mark_symlink_for_removal(remove_symlinks_to, i->name);
+                                else
+                                        /* does not exist, thus we will mark for removal symlinks
+                                         * to template unit file */
+                                        q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
+                        } else {
+                                /* If i->path is not set, it means that we didn't actually find
+                                 * the unit file. But we can still remove symlinks to the
+                                 * nonexistent template. */
+                                unit_file = unit_name_template(i->name);
+                                if (!unit_file)
+                                        return log_oom();
 
-                        unit_file = path_get_file_name(i->path);
-
-                        if (unit_name_is_instance(unit_file))
-                                /* unit file named as instance exists, thus all symlinks pointing to it, will be removed */
-                                q = mark_symlink_for_removal(remove_symlinks_to, i->name);
-                        else
-                                /* does not exist, thus we will mark for removal symlinks to template unit file */
                                 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
+                                free(unit_file);
+                        }
                 } else
                         q = mark_symlink_for_removal(remove_symlinks_to, i->name);
 
@@ -1449,7 +1462,7 @@ int unit_file_enable(
                 UnitFileScope scope,
                 bool runtime,
                 const char *root_dir,
-                char *files[],
+                char **files,
                 bool force,
                 UnitFileChange **changes,
                 unsigned *n_changes) {
@@ -1481,15 +1494,15 @@ int unit_file_enable(
         supposed to be created, not the ones actually created. This is
         useful to determine whether the passed files had any
         installation data at all. */
-        r = install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
-        return r;
+
+        return install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
 }
 
 int unit_file_disable(
                 UnitFileScope scope,
                 bool runtime,
                 const char *root_dir,
-                char *files[],
+                char **files,
                 UnitFileChange **changes,
                 unsigned *n_changes) {
 
@@ -1530,7 +1543,7 @@ int unit_file_reenable(
                 UnitFileScope scope,
                 bool runtime,
                 const char *root_dir,
-                char *files[],
+                char **files,
                 bool force,
                 UnitFileChange **changes,
                 unsigned *n_changes) {
@@ -1548,7 +1561,8 @@ int unit_file_reenable(
 int unit_file_set_default(
                 UnitFileScope scope,
                 const char *root_dir,
-                char *file,
+                const char *file,
+                bool force,
                 UnitFileChange **changes,
                 unsigned *n_changes) {
 
@@ -1561,6 +1575,7 @@ int unit_file_set_default(
 
         assert(scope >= 0);
         assert(scope < _UNIT_FILE_SCOPE_MAX);
+        assert(file);
 
         if (unit_name_to_type(file) != UNIT_TARGET)
                 return -EINVAL;
@@ -1577,14 +1592,15 @@ int unit_file_set_default(
         if (r < 0)
                 return r;
 
-        i = (InstallInfo*)hashmap_first(c.will_install);
+        assert_se(i = hashmap_first(c.will_install));
 
         r = unit_file_search(&c, i, &paths, root_dir, false);
         if (r < 0)
                 return r;
 
-        path = strappenda(config_path, "/default.target");
-        r = create_symlink(i->path, path, true, changes, n_changes);
+        path = strappenda(config_path, "/" SPECIAL_DEFAULT_TARGET);
+
+        r = create_symlink(i->path, path, force, changes, n_changes);
         if (r < 0)
                 return r;
 
@@ -1600,17 +1616,22 @@ int unit_file_get_default(
         char **p;
         int r;
 
+        assert(scope >= 0);
+        assert(scope < _UNIT_FILE_SCOPE_MAX);
+        assert(name);
+
         r = lookup_paths_init_from_scope(&paths, scope);
         if (r < 0)
                 return r;
 
         STRV_FOREACH(p, paths.unit_path) {
                 _cleanup_free_ char *path = NULL, *tmp = NULL;
+                char *n;
 
                 if (isempty(root_dir))
-                        path = strappend(*p, "/default.target");
+                        path = strappend(*p, "/" SPECIAL_DEFAULT_TARGET);
                 else
-                        path = strjoin(root_dir, "/", *p, "/default.target", NULL);
+                        path = strjoin(root_dir, "/", *p, "/" SPECIAL_DEFAULT_TARGET, NULL);
 
                 if (!path)
                         return -ENOMEM;
@@ -1618,13 +1639,18 @@ int unit_file_get_default(
                 r = readlink_malloc(path, &tmp);
                 if (r == -ENOENT)
                         continue;
+                else if (r == -EINVAL)
+                        /* not a symlink */
+                        n = strdup(SPECIAL_DEFAULT_TARGET);
                 else if (r < 0)
                         return r;
+                else
+                        n = strdup(basename(tmp));
 
-                *name = strdup(path_get_file_name(tmp));
-                if (!*name)
+                if (!n)
                         return -ENOMEM;
 
+                *name = n;
                 return 0;
         }
 
@@ -1649,7 +1675,7 @@ UnitFileState unit_file_get_state(
         if (root_dir && scope != UNIT_FILE_SYSTEM)
                 return -EINVAL;
 
-        if (!unit_name_is_valid(name, true))
+        if (!unit_name_is_valid(name, TEMPLATE_VALID))
                 return -EINVAL;
 
         r = lookup_paths_init_from_scope(&paths, scope);
@@ -1794,7 +1820,7 @@ int unit_file_preset(
                 UnitFileScope scope,
                 bool runtime,
                 const char *root_dir,
-                char *files[],
+                char **files,
                 bool force,
                 UnitFileChange **changes,
                 unsigned *n_changes) {
@@ -1819,7 +1845,7 @@ int unit_file_preset(
 
         STRV_FOREACH(i, files) {
 
-                if (!unit_name_is_valid(*i, true))
+                if (!unit_name_is_valid(*i, TEMPLATE_VALID))
                         return -EINVAL;
 
                 r = unit_file_query_preset(scope, *i);
@@ -1859,6 +1885,7 @@ static void unitfilelist_free(UnitFileList **f) {
         free((*f)->path);
         free(*f);
 }
+#define _cleanup_unitfilelist_free_ _cleanup_(unitfilelist_free)
 
 int unit_file_get_list(
                 UnitFileScope scope,
@@ -1909,13 +1936,12 @@ int unit_file_get_list(
 
                 for (;;) {
                         struct dirent *de;
-                        union dirent_storage buffer;
-                        UnitFileList __attribute__((cleanup(unitfilelist_free)))
-                                *f = NULL;
+                        _cleanup_unitfilelist_free_ UnitFileList *f = NULL;
 
-                        r = readdir_r(d, &buffer.de, &de);
-                        if (r != 0)
-                                return -r;
+                        errno = 0;
+                        de = readdir(d);
+                        if (!de && errno != 0)
+                                return -errno;
 
                         if (!de)
                                 break;
@@ -1923,7 +1949,7 @@ int unit_file_get_list(
                         if (ignore_file(de->d_name))
                                 continue;
 
-                        if (!unit_name_is_valid(de->d_name, true))
+                        if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
                                 continue;
 
                         if (hashmap_get(h, de->d_name))
@@ -1979,7 +2005,7 @@ int unit_file_get_list(
                                 f->state = UNIT_FILE_STATIC;
 
                 found:
-                        r = hashmap_put(h, path_get_file_name(f->path), f);
+                        r = hashmap_put(h, basename(f->path), f);
                         if (r < 0)
                                 return r;
                         f = NULL; /* prevent cleanup */