"Unit %s is transient or generated.", changes[i].path);
goto found;
+ case -ETXTBSY:
+ r = sd_bus_error_setf(error, BUS_ERROR_UNIT_BAD_PATH,
+ "File %s is under the systemd unit hierarchy already.", changes[i].path);
+ goto found;
+
case -EUCLEAN:
r = sd_bus_error_setf(error, BUS_ERROR_BAD_UNIT_SETTING,
"\"%s\" is not a valid unit name.",
#define BUS_ERROR_UNIT_MASKED "org.freedesktop.systemd1.UnitMasked"
#define BUS_ERROR_UNIT_GENERATED "org.freedesktop.systemd1.UnitGenerated"
#define BUS_ERROR_UNIT_LINKED "org.freedesktop.systemd1.UnitLinked"
+#define BUS_ERROR_UNIT_BAD_PATH "org.freedesktop.systemd1.UnitBadPath"
#define BUS_ERROR_JOB_TYPE_NOT_APPLICABLE "org.freedesktop.systemd1.JobTypeNotApplicable"
#define BUS_ERROR_NO_ISOLATION "org.freedesktop.systemd1.NoIsolation"
#define BUS_ERROR_SHUTTING_DOWN "org.freedesktop.systemd1.ShuttingDown"
_cleanup_free_ char *parent = NULL;
int r;
- assert(path);
+ /* Check if 'path' is in lp->search_path. */
- r = path_extract_directory(path, &parent);
+ r = path_extract_directory(ASSERT_PTR(path), &parent);
if (r < 0)
return r;
- return path_strv_contains(lp->search_path, parent);
+ return path_strv_contains(ASSERT_PTR(lp)->search_path, parent);
+}
+
+static int underneath_search_path(const LookupPaths *lp, const char *path) {
+ /* Check if 'path' is underneath lp->search_path. */
+
+ return !!path_startswith_strv(ASSERT_PTR(path), ASSERT_PTR(lp)->search_path);
}
static const char* skip_root(const char *root_dir, const char *path) {
err = log_error_errno(changes[i].type, "Failed to %s unit, unit %s is transient or generated.",
verb, changes[i].path);
break;
+ case -ETXTBSY:
+ err = log_error_errno(changes[i].type, "Failed to %s unit, file %s is under the systemd unit hierarchy already.",
+ verb, changes[i].path);
+ break;
case -EBADSLT:
err = log_error_errno(changes[i].type, "Failed to %s unit, invalid specifier in \"%s\".",
verb, changes[i].path);
if (r < 0)
return install_changes_add(changes, n_changes, r, *file, NULL);
if (r > 0)
+ /* A silent noop if the file is already in the search path. */
continue;
+ r = underneath_search_path(&lp, *file);
+ if (r > 0)
+ r = -ETXTBSY;
+ if (r < 0)
+ return install_changes_add(changes, n_changes, r, *file, NULL);
+
if (!GREEDY_REALLOC0(todo, n_todo + 2))
return -ENOMEM;