summaryrefslogtreecommitdiff
path: root/src/shared/install.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/shared/install.c')
-rw-r--r--src/shared/install.c134
1 files changed, 109 insertions, 25 deletions
diff --git a/src/shared/install.c b/src/shared/install.c
index 10c724edbd..71012eafb4 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -276,6 +276,70 @@ void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
free(changes);
}
+void unit_file_dump_changes(int r, const char *verb, const UnitFileChange *changes, unsigned n_changes, bool quiet) {
+ unsigned i;
+ bool logged = false;
+
+ assert(changes || n_changes == 0);
+ /* If verb is not specified, errors are not allowed! */
+ assert(verb || r >= 0);
+
+ for (i = 0; i < n_changes; i++) {
+ assert(verb || changes[i].type >= 0);
+
+ switch(changes[i].type) {
+ case UNIT_FILE_SYMLINK:
+ if (!quiet)
+ log_info("Created symlink %s, pointing to %s.", changes[i].path, changes[i].source);
+ break;
+ case UNIT_FILE_UNLINK:
+ if (!quiet)
+ log_info("Removed %s.", changes[i].path);
+ break;
+ case UNIT_FILE_IS_MASKED:
+ if (!quiet)
+ log_info("Unit %s is masked, ignoring.", changes[i].path);
+ break;
+ case -EEXIST:
+ if (changes[i].source)
+ log_error_errno(changes[i].type,
+ "Failed to %s unit, file %s already exists and is a symlink to %s.",
+ verb, changes[i].path, changes[i].source);
+ else
+ log_error_errno(changes[i].type,
+ "Failed to %s unit, file %s already exists.",
+ verb, changes[i].path);
+ logged = true;
+ break;
+ case -ERFKILL:
+ log_error_errno(changes[i].type, "Failed to %s unit, unit %s is masked.",
+ verb, changes[i].path);
+ logged = true;
+ break;
+ case -EADDRNOTAVAIL:
+ log_error_errno(changes[i].type, "Failed to %s unit, unit %s is transient or generated.",
+ verb, changes[i].path);
+ logged = true;
+ break;
+ case -ELOOP:
+ log_error_errno(changes[i].type, "Failed to %s unit, refusing to operate on linked unit file %s",
+ verb, changes[i].path);
+ logged = true;
+ break;
+ default:
+ assert(changes[i].type < 0);
+ log_error_errno(changes[i].type, "Failed to %s unit, file %s: %m.",
+ verb, changes[i].path);
+ logged = true;
+ }
+ }
+
+ if (r < 0 && !logged)
+ log_error_errno(r, "Failed to %s: %m.", verb);
+}
+
+
+
static int create_symlink(
const char *old_path,
const char *new_path,
@@ -300,8 +364,10 @@ static int create_symlink(
return 1;
}
- if (errno != EEXIST)
+ if (errno != EEXIST) {
+ unit_file_changes_add(changes, n_changes, -errno, new_path, NULL);
return -errno;
+ }
r = readlink_malloc(new_path, &dest);
if (r < 0)
@@ -310,8 +376,10 @@ static int create_symlink(
if (path_equal(dest, old_path))
return 0;
- if (!force)
+ if (!force) {
+ unit_file_changes_add(changes, n_changes, -EEXIST, new_path, dest);
return -EEXIST;
+ }
r = symlink_atomic(old_path, new_path);
if (r < 0)
@@ -421,6 +489,7 @@ static int remove_marked_symlinks_fd(
p = path_make_absolute(de->d_name, path);
if (!p)
return -ENOMEM;
+ path_kill_slashes(p);
q = readlink_malloc(p, &dest);
if (q == -ENOENT)
@@ -434,8 +503,7 @@ static int remove_marked_symlinks_fd(
/* We remove all links pointing to a file or path that is marked, as well as all files sharing
* the same name as a file that is marked. */
- found =
- set_contains(remove_symlinks_to, dest) ||
+ found = set_contains(remove_symlinks_to, dest) ||
set_contains(remove_symlinks_to, basename(dest)) ||
set_contains(remove_symlinks_to, de->d_name);
@@ -445,10 +513,10 @@ static int remove_marked_symlinks_fd(
if (unlinkat(fd, de->d_name, 0) < 0 && errno != ENOENT) {
if (r == 0)
r = -errno;
+ unit_file_changes_add(changes, n_changes, -errno, p, NULL);
continue;
}
- path_kill_slashes(p);
(void) rmdir_parents(p, config_path);
unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, p, NULL);
@@ -746,19 +814,26 @@ static UnitFileInstallInfo *install_info_find(InstallContext *c, const char *nam
return ordered_hashmap_get(c->will_process, name);
}
-static int install_info_may_process(UnitFileInstallInfo *i, const LookupPaths *paths) {
+static int install_info_may_process(
+ UnitFileInstallInfo *i,
+ const LookupPaths *paths,
+ UnitFileChange **changes,
+ unsigned *n_changes) {
assert(i);
assert(paths);
/* Checks whether the loaded unit file is one we should process, or is masked, transient or generated and thus
* not subject to enable/disable operations. */
- if (i->type == UNIT_FILE_TYPE_MASKED)
+ if (i->type == UNIT_FILE_TYPE_MASKED) {
+ unit_file_changes_add(changes, n_changes, -ERFKILL, i->path, NULL);
return -ERFKILL;
- if (path_is_generator(paths, i->path))
- return -EADDRNOTAVAIL;
- if (path_is_transient(paths, i->path))
+ }
+ if (path_is_generator(paths, i->path) ||
+ path_is_transient(paths, i->path)) {
+ unit_file_changes_add(changes, n_changes, -EADDRNOTAVAIL, i->path, NULL);
return -EADDRNOTAVAIL;
+ }
return 0;
}
@@ -1391,8 +1466,10 @@ static int install_info_symlink_link(
assert(i->path);
r = in_search_path(paths, i->path);
- if (r != 0)
+ if (r < 0)
return r;
+ if (r > 0)
+ return 0;
path = strjoin(config_path, "/", i->name, NULL);
if (!path)
@@ -1431,7 +1508,8 @@ static int install_info_apply(
r = q;
q = install_info_symlink_link(i, paths, config_path, force, changes, n_changes);
- if (r == 0)
+ /* Do not count links to the unit file towards the "carries_install_info" count */
+ if (r == 0 && q < 0)
r = q;
return r;
@@ -1481,7 +1559,7 @@ static int install_context_apply(
if (q < 0)
r = q;
else
- r+= q;
+ r += q;
}
}
@@ -1638,8 +1716,11 @@ int unit_file_unmask(
return -ENOMEM;
if (unlink(path) < 0) {
- if (errno != ENOENT && r >= 0)
- r = -errno;
+ if (errno != ENOENT) {
+ if (r >= 0)
+ r = -errno;
+ unit_file_changes_add(changes, n_changes, -errno, path, NULL);
+ }
continue;
}
@@ -1954,7 +2035,7 @@ int unit_file_add_dependency(
r = install_info_discover(scope, &c, &paths, target, SEARCH_FOLLOW_CONFIG_SYMLINKS, &target_info);
if (r < 0)
return r;
- r = install_info_may_process(target_info, &paths);
+ r = install_info_may_process(target_info, &paths, changes, n_changes);
if (r < 0)
return r;
@@ -1966,7 +2047,7 @@ int unit_file_add_dependency(
r = install_info_discover(scope, &c, &paths, *f, SEARCH_FOLLOW_CONFIG_SYMLINKS, &i);
if (r < 0)
return r;
- r = install_info_may_process(i, &paths);
+ r = install_info_may_process(i, &paths, changes, n_changes);
if (r < 0)
return r;
@@ -2019,7 +2100,7 @@ int unit_file_enable(
r = install_info_discover(scope, &c, &paths, *f, SEARCH_LOAD, &i);
if (r < 0)
return r;
- r = install_info_may_process(i, &paths);
+ r = install_info_may_process(i, &paths, changes, n_changes);
if (r < 0)
return r;
@@ -2132,7 +2213,7 @@ int unit_file_set_default(
r = install_info_discover(scope, &c, &paths, name, 0, &i);
if (r < 0)
return r;
- r = install_info_may_process(i, &paths);
+ r = install_info_may_process(i, &paths, changes, n_changes);
if (r < 0)
return r;
@@ -2164,7 +2245,7 @@ int unit_file_get_default(
r = install_info_discover(scope, &c, &paths, SPECIAL_DEFAULT_TARGET, SEARCH_FOLLOW_CONFIG_SYMLINKS, &i);
if (r < 0)
return r;
- r = install_info_may_process(i, &paths);
+ r = install_info_may_process(i, &paths, NULL, 0);
if (r < 0)
return r;
@@ -2413,7 +2494,7 @@ static int execute_preset(
if (q < 0)
r = q;
else
- r+= q;
+ r += q;
}
}
@@ -2426,7 +2507,9 @@ static int preset_prepare_one(
InstallContext *minus,
LookupPaths *paths,
UnitFilePresetMode mode,
- const char *name) {
+ const char *name,
+ UnitFileChange **changes,
+ unsigned *n_changes) {
UnitFileInstallInfo *i;
int r;
@@ -2444,7 +2527,7 @@ static int preset_prepare_one(
if (r < 0)
return r;
- r = install_info_may_process(i, paths);
+ r = install_info_may_process(i, paths, changes, n_changes);
if (r < 0)
return r;
} else
@@ -2483,7 +2566,7 @@ int unit_file_preset(
if (!unit_name_is_valid(*i, UNIT_NAME_ANY))
return -EINVAL;
- r = preset_prepare_one(scope, &plus, &minus, &paths, mode, *i);
+ r = preset_prepare_one(scope, &plus, &minus, &paths, mode, *i, changes, n_changes);
if (r < 0)
return r;
}
@@ -2538,7 +2621,8 @@ int unit_file_preset_all(
if (!IN_SET(de->d_type, DT_LNK, DT_REG))
continue;
- r = preset_prepare_one(scope, &plus, &minus, &paths, mode, de->d_name);
+ /* we don't pass changes[] in, because we want to handle errors on our own */
+ r = preset_prepare_one(scope, &plus, &minus, &paths, mode, de->d_name, NULL, 0);
if (r == -ERFKILL)
r = unit_file_changes_add(changes, n_changes,
UNIT_FILE_IS_MASKED, de->d_name, NULL);