if (u)
r = unit_env_printf(u, word, &resolved);
else
- r = specifier_printf(word, sc_arg_max(), system_and_tmp_specifier_table, NULL, &resolved);
+ r = specifier_printf(word, sc_arg_max(), system_and_tmp_specifier_table, NULL, NULL, &resolved);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to resolve specifiers in %s, ignoring: %m", word);
#include "unit.h"
#include "user-util.h"
-static int specifier_prefix_and_instance(char specifier, const void *data, const void *userdata, char **ret) {
+static int specifier_prefix_and_instance(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
const Unit *u = userdata;
assert(u);
return unit_name_to_prefix_and_instance(u->id, ret);
}
-static int specifier_prefix(char specifier, const void *data, const void *userdata, char **ret) {
+static int specifier_prefix(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
const Unit *u = userdata;
assert(u);
return unit_name_to_prefix(u->id, ret);
}
-static int specifier_prefix_unescaped(char specifier, const void *data, const void *userdata, char **ret) {
+static int specifier_prefix_unescaped(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
_cleanup_free_ char *p = NULL;
const Unit *u = userdata;
int r;
return unit_name_unescape(p, ret);
}
-static int specifier_instance_unescaped(char specifier, const void *data, const void *userdata, char **ret) {
+static int specifier_instance_unescaped(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
const Unit *u = userdata;
assert(u);
return unit_name_unescape(strempty(u->instance), ret);
}
-static int specifier_last_component(char specifier, const void *data, const void *userdata, char **ret) {
+static int specifier_last_component(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
const Unit *u = userdata;
_cleanup_free_ char *prefix = NULL;
char *dash;
dash = strrchr(prefix, '-');
if (dash)
- return specifier_string(specifier, dash + 1, userdata, ret);
+ return specifier_string(specifier, dash + 1, root, userdata, ret);
*ret = TAKE_PTR(prefix);
return 0;
}
-static int specifier_last_component_unescaped(char specifier, const void *data, const void *userdata, char **ret) {
+static int specifier_last_component_unescaped(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
_cleanup_free_ char *p = NULL;
int r;
- r = specifier_last_component(specifier, data, userdata, &p);
+ r = specifier_last_component(specifier, data, root, userdata, &p);
if (r < 0)
return r;
return unit_name_unescape(p, ret);
}
-static int specifier_filename(char specifier, const void *data, const void *userdata, char **ret) {
+static int specifier_filename(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
const Unit *u = userdata;
assert(u);
log_unit_warning(u, "Specifier '%%%c' used in unit configuration, which is deprecated. Please update your unit file, as it does not work as intended.", specifier);
}
-static int specifier_cgroup(char specifier, const void *data, const void *userdata, char **ret) {
+static int specifier_cgroup(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
const Unit *u = userdata;
char *n;
return 0;
}
-static int specifier_cgroup_root(char specifier, const void *data, const void *userdata, char **ret) {
+static int specifier_cgroup_root(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
const Unit *u = userdata;
char *n;
return 0;
}
-static int specifier_cgroup_slice(char specifier, const void *data, const void *userdata, char **ret) {
+static int specifier_cgroup_slice(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
const Unit *u = userdata, *slice;
char *n;
return 0;
}
-static int specifier_special_directory(char specifier, const void *data, const void *userdata, char **ret) {
+static int specifier_special_directory(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
const Unit *u = userdata;
char *n = NULL;
assert(format);
assert(ret);
- return specifier_printf(format, UNIT_NAME_MAX, table, u, ret);
+ return specifier_printf(format, UNIT_NAME_MAX, table, NULL, u, ret);
}
int unit_full_printf_full(const Unit *u, const char *format, size_t max_length, char **ret) {
{}
};
- return specifier_printf(format, max_length, table, u, ret);
+ return specifier_printf(format, max_length, table, NULL, u, ret);
}
/* Nota bene: the empty label is a totally valid one. Let's hence not follow our usual rule of
* assigning the empty string to reset to default here, but really accept it as label to set. */
- r = specifier_printf(rvalue, GPT_LABEL_MAX, system_and_tmp_specifier_table, NULL, &resolved);
+ r = specifier_printf(rvalue, GPT_LABEL_MAX, system_and_tmp_specifier_table, arg_root, NULL, &resolved);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to expand specifiers in Label=, ignoring: %s", rvalue);
if (!isempty(p))
return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL), "Too many arguments: %s", rvalue);
- r = specifier_printf(source, PATH_MAX-1, system_and_tmp_specifier_table, NULL, &resolved_source);
+ r = specifier_printf(source, PATH_MAX-1, system_and_tmp_specifier_table, arg_root, NULL, &resolved_source);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to expand specifiers in CopyFiles= source, ignoring: %s", rvalue);
if (r < 0)
return 0;
- r = specifier_printf(target, PATH_MAX-1, system_and_tmp_specifier_table, NULL, &resolved_target);
+ r = specifier_printf(target, PATH_MAX-1, system_and_tmp_specifier_table, arg_root, NULL, &resolved_target);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to expand specifiers in CopyFiles= target, ignoring: %s", resolved_target);
return 0;
}
- r = specifier_printf(rvalue, PATH_MAX-1, system_and_tmp_specifier_table, NULL, &d);
+ r = specifier_printf(rvalue, PATH_MAX-1, system_and_tmp_specifier_table, arg_root, NULL, &d);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to expand specifiers in CopyBlocks= source path, ignoring: %s", rvalue);
if (r == 0)
return 0;
- r = specifier_printf(word, PATH_MAX-1, system_and_tmp_specifier_table, NULL, &d);
+ r = specifier_printf(word, PATH_MAX-1, system_and_tmp_specifier_table, arg_root, NULL, &d);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to expand specifiers in MakeDirectories= parameter, ignoring: %s", word);
return 0;
}
- r = specifier_printf(rvalue, DNS_LABEL_MAX, specifier_table, NULL, &name);
+ r = specifier_printf(rvalue, DNS_LABEL_MAX, specifier_table, NULL, NULL, &name);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Invalid service instance name template '%s', ignoring assignment: %m", rvalue);
return 0;
}
-static int specifier_dnssd_host_name(char specifier, const void *data, const void *userdata, char **ret) {
+static int specifier_dnssd_host_name(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
DnssdService *s = (DnssdService *) userdata;
char *n;
assert(s);
assert(s->name_template);
- r = specifier_printf(s->name_template, DNS_LABEL_MAX, specifier_table, s, &name);
+ r = specifier_printf(s->name_template, DNS_LABEL_MAX, specifier_table, NULL, s, &name);
if (r < 0)
return log_debug_errno(r, "Failed to replace specifiers: %m");
#include "unit-name.h"
#include "user-util.h"
-static int specifier_prefix_and_instance(char specifier, const void *data, const void *userdata, char **ret) {
+static int specifier_prefix_and_instance(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
const UnitFileInstallInfo *i = userdata;
_cleanup_free_ char *prefix = NULL;
int r;
return 0;
}
-static int specifier_name(char specifier, const void *data, const void *userdata, char **ret) {
+static int specifier_name(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
const UnitFileInstallInfo *i = userdata;
char *ans;
return 0;
}
-static int specifier_prefix(char specifier, const void *data, const void *userdata, char **ret) {
+static int specifier_prefix(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
const UnitFileInstallInfo *i = userdata;
assert(i);
return unit_name_to_prefix(i->name, ret);
}
-static int specifier_instance(char specifier, const void *data, const void *userdata, char **ret) {
+static int specifier_instance(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
const UnitFileInstallInfo *i = userdata;
char *instance;
int r;
return 0;
}
-static int specifier_last_component(char specifier, const void *data, const void *userdata, char **ret) {
+static int specifier_last_component(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
_cleanup_free_ char *prefix = NULL;
char *dash;
int r;
- r = specifier_prefix(specifier, data, userdata, &prefix);
+ r = specifier_prefix(specifier, data, root, userdata, &prefix);
if (r < 0)
return r;
return 0;
}
-int install_full_printf_internal(const UnitFileInstallInfo *i, const char *format, size_t max_length, char **ret) {
+int install_full_printf_internal(const UnitFileInstallInfo *i, const char *format, size_t max_length, const char *root, char **ret) {
/* This is similar to unit_name_printf() */
const Specifier table[] = {
assert(format);
assert(ret);
- return specifier_printf(format, max_length, table, i, ret);
+ return specifier_printf(format, max_length, table, root, i, ret);
}
#include "install.h"
#include "unit-name.h"
-int install_full_printf_internal(const UnitFileInstallInfo *i, const char *format, size_t max_length, char **ret);
-static inline int install_name_printf(const UnitFileInstallInfo *i, const char *format, char **ret) {
- return install_full_printf_internal(i, format, UNIT_NAME_MAX, ret);
+int install_full_printf_internal(const UnitFileInstallInfo *i, const char *format, size_t max_length, const char *root, char **ret);
+
+static inline int install_name_printf(const UnitFileInstallInfo *i, const char *format, const char *root, char **ret) {
+ return install_full_printf_internal(i, format, UNIT_NAME_MAX, root, ret);
}
-static inline int install_path_printf(const UnitFileInstallInfo *i, const char *format, char **ret) {
- return install_full_printf_internal(i, format, PATH_MAX-1, ret);
+static inline int install_path_printf(const UnitFileInstallInfo *i, const char *format, const char *root, char **ret) {
+ return install_full_printf_internal(i, format, PATH_MAX-1, root, ret);
}
free(i->name);
free(i->path);
+ free(i->root);
strv_free(i->aliases);
strv_free(i->wanted_by);
strv_free(i->required_by);
InstallContext *c,
const char *name,
const char *path,
+ const char *root,
bool auxiliary,
UnitFileInstallInfo **ret) {
goto fail;
}
+ if (root) {
+ i->root = strdup(root);
+ if (!i->root) {
+ r = -ENOMEM;
+ goto fail;
+ }
+ }
+
if (path) {
i->path = strdup(path);
if (!i->path) {
if (r == 0)
break;
- r = install_name_printf(info, word, &printed);
+ r = install_name_printf(info, word, info->root, &printed);
if (r < 0)
return r;
- r = install_info_add(c, printed, NULL, true, NULL);
+ r = install_info_add(c, printed, NULL, info->root, /* auxiliary= */ true, NULL);
if (r < 0)
return r;
return log_syntax(unit, LOG_WARNING, filename, line, 0,
"DefaultInstance= only makes sense for template units, ignoring.");
- r = install_name_printf(i, rvalue, &printed);
+ r = install_name_printf(i, rvalue, i->root, &printed);
if (r < 0)
return r;
bn = buffer;
}
- r = install_info_add(c, bn, NULL, false, &i);
+ r = install_info_add(c, bn, NULL, paths->root_dir, /* auxiliary= */ false, &i);
if (r < 0)
return r;
pp = prefix_roota(paths->root_dir, name_or_path);
- return install_info_add(c, NULL, pp, false, ret);
+ return install_info_add(c, NULL, pp, paths->root_dir, /* auxiliary= */ false, ret);
} else
- return install_info_add(c, name_or_path, NULL, false, ret);
+ return install_info_add(c, name_or_path, NULL, paths->root_dir, /* auxiliary= */ false, ret);
}
static int install_info_discover(
STRV_FOREACH(s, i->aliases) {
_cleanup_free_ char *alias_path = NULL, *dst = NULL, *dst_updated = NULL;
- q = install_path_printf(i, *s, &dst);
+ q = install_path_printf(i, *s, i->root, &dst);
if (q < 0)
return q;
STRV_FOREACH(s, list) {
_cleanup_free_ char *path = NULL, *dst = NULL;
- q = install_name_printf(i, *s, &dst);
+ q = install_name_printf(i, *s, i->root, &dst);
if (q < 0)
return q;
if (!unit_name_is_valid(*i, UNIT_NAME_ANY))
return -EINVAL;
- r = install_info_add(&c, *i, NULL, false, NULL);
+ r = install_info_add(&c, *i, NULL, paths.root_dir, /* auxiliary= */ false, NULL);
if (r < 0)
return r;
}
struct UnitFileInstallInfo {
char *name;
char *path;
+ char *root;
char **aliases;
char **wanted_by;
#include "alloc-util.h"
#include "architecture.h"
+#include "fd-util.h"
#include "format-util.h"
#include "fs-util.h"
#include "hostname-util.h"
+#include "id128-util.h"
#include "macro.h"
#include "os-util.h"
#include "specifier.h"
* and "%" used for escaping. */
#define POSSIBLE_SPECIFIERS ALPHANUMERICAL "%"
-int specifier_printf(const char *text, size_t max_length, const Specifier table[], const void *userdata, char **ret) {
+int specifier_printf(const char *text, size_t max_length, const Specifier table[], const char *root, const void *userdata, char **ret) {
_cleanup_free_ char *result = NULL;
bool percent = false;
const char *f;
_cleanup_free_ char *w = NULL;
size_t k, j;
- r = i->lookup(i->specifier, i->data, userdata, &w);
+ r = i->lookup(i->specifier, i->data, root, userdata, &w);
if (r < 0)
return r;
/* Generic handler for simple string replacements */
-int specifier_string(char specifier, const void *data, const void *userdata, char **ret) {
+int specifier_string(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
char *n;
n = strdup(strempty(data));
return 0;
}
-int specifier_machine_id(char specifier, const void *data, const void *userdata, char **ret) {
+int specifier_machine_id(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
sd_id128_t id;
char *n;
int r;
- r = sd_id128_get_machine(&id);
+ if (root) {
+ _cleanup_close_ int fd = -1;
+
+ fd = chase_symlinks_and_open("/etc/machine-id", root, CHASE_PREFIX_ROOT, O_RDONLY|O_CLOEXEC|O_NOCTTY, NULL);
+ if (fd < 0)
+ return fd;
+
+ r = id128_read_fd(fd, ID128_PLAIN, &id);
+ } else
+ r = sd_id128_get_machine(&id);
if (r < 0)
return r;
return 0;
}
-int specifier_boot_id(char specifier, const void *data, const void *userdata, char **ret) {
+int specifier_boot_id(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
sd_id128_t id;
char *n;
int r;
return 0;
}
-int specifier_host_name(char specifier, const void *data, const void *userdata, char **ret) {
+int specifier_host_name(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
char *n;
n = gethostname_malloc();
return 0;
}
-int specifier_short_host_name(char specifier, const void *data, const void *userdata, char **ret) {
+int specifier_short_host_name(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
char *n;
n = gethostname_short_malloc();
return 0;
}
-int specifier_kernel_release(char specifier, const void *data, const void *userdata, char **ret) {
+int specifier_kernel_release(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
struct utsname uts;
char *n;
int r;
return 0;
}
-int specifier_architecture(char specifier, const void *data, const void *userdata, char **ret) {
+int specifier_architecture(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
char *t;
t = strdup(architecture_to_string(uname_architecture()));
return 0;
}
-static int specifier_os_release_common(const char *field, char **ret) {
+static int specifier_os_release_common(const char *field, const char *root, char **ret) {
char *t = NULL;
int r;
- r = parse_os_release(NULL, field, &t);
+ r = parse_os_release(root, field, &t);
if (r < 0)
return r;
if (!t) {
return 0;
}
-int specifier_os_id(char specifier, const void *data, const void *userdata, char **ret) {
- return specifier_os_release_common("ID", ret);
+int specifier_os_id(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
+ return specifier_os_release_common("ID", root, ret);
}
-int specifier_os_version_id(char specifier, const void *data, const void *userdata, char **ret) {
- return specifier_os_release_common("VERSION_ID", ret);
+int specifier_os_version_id(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
+ return specifier_os_release_common("VERSION_ID", root, ret);
}
-int specifier_os_build_id(char specifier, const void *data, const void *userdata, char **ret) {
- return specifier_os_release_common("BUILD_ID", ret);
+int specifier_os_build_id(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
+ return specifier_os_release_common("BUILD_ID", root, ret);
}
-int specifier_os_variant_id(char specifier, const void *data, const void *userdata, char **ret) {
- return specifier_os_release_common("VARIANT_ID", ret);
+int specifier_os_variant_id(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
+ return specifier_os_release_common("VARIANT_ID", root, ret);
}
-int specifier_os_image_id(char specifier, const void *data, const void *userdata, char **ret) {
- return specifier_os_release_common("IMAGE_ID", ret);
+int specifier_os_image_id(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
+ return specifier_os_release_common("IMAGE_ID", root, ret);
}
-int specifier_os_image_version(char specifier, const void *data, const void *userdata, char **ret) {
- return specifier_os_release_common("IMAGE_VERSION", ret);
+int specifier_os_image_version(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
+ return specifier_os_release_common("IMAGE_VERSION", root, ret);
}
-int specifier_group_name(char specifier, const void *data, const void *userdata, char **ret) {
+int specifier_group_name(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
char *t;
t = gid_to_name(getgid());
return 0;
}
-int specifier_group_id(char specifier, const void *data, const void *userdata, char **ret) {
+int specifier_group_id(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
if (asprintf(ret, UID_FMT, getgid()) < 0)
return -ENOMEM;
return 0;
}
-int specifier_user_name(char specifier, const void *data, const void *userdata, char **ret) {
+int specifier_user_name(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
char *t;
/* If we are UID 0 (root), this will not result in NSS, otherwise it might. This is good, as we want to be able
return 0;
}
-int specifier_user_id(char specifier, const void *data, const void *userdata, char **ret) {
+int specifier_user_id(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
if (asprintf(ret, UID_FMT, getuid()) < 0)
return -ENOMEM;
return 0;
}
-int specifier_user_home(char specifier, const void *data, const void *userdata, char **ret) {
+int specifier_user_home(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
/* On PID 1 (which runs as root) this will not result in NSS,
* which is good. See above */
return get_home_dir(ret);
}
-int specifier_user_shell(char specifier, const void *data, const void *userdata, char **ret) {
+int specifier_user_shell(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
/* On PID 1 (which runs as root) this will not result in NSS,
* which is good. See above */
return get_shell(ret);
}
-int specifier_tmp_dir(char specifier, const void *data, const void *userdata, char **ret) {
+int specifier_tmp_dir(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
const char *p;
char *copy;
int r;
- r = tmp_dir(&p);
- if (r < 0)
- return r;
-
+ if (root) /* If root dir is set, don't honour $TMP or similar */
+ p = "/tmp";
+ else {
+ r = tmp_dir(&p);
+ if (r < 0)
+ return r;
+ }
copy = strdup(p);
if (!copy)
return -ENOMEM;
return 0;
}
-int specifier_var_tmp_dir(char specifier, const void *data, const void *userdata, char **ret) {
+int specifier_var_tmp_dir(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
const char *p;
char *copy;
int r;
- r = var_tmp_dir(&p);
- if (r < 0)
- return r;
-
+ if (root)
+ p = "/var/tmp";
+ else {
+ r = var_tmp_dir(&p);
+ if (r < 0)
+ return r;
+ }
copy = strdup(p);
if (!copy)
return -ENOMEM;
#include "string-util.h"
-typedef int (*SpecifierCallback)(char specifier, const void *data, const void *userdata, char **ret);
+typedef int (*SpecifierCallback)(char specifier, const void *data, const char *root, const void *userdata, char **ret);
typedef struct Specifier {
const char specifier;
const void *data;
} Specifier;
-int specifier_printf(const char *text, size_t max_length, const Specifier table[], const void *userdata, char **ret);
+int specifier_printf(const char *text, size_t max_length, const Specifier table[], const char *root, const void *userdata, char **ret);
-int specifier_string(char specifier, const void *data, const void *userdata, char **ret);
+int specifier_string(char specifier, const void *data, const char *root, const void *userdata, char **ret);
-int specifier_machine_id(char specifier, const void *data, const void *userdata, char **ret);
-int specifier_boot_id(char specifier, const void *data, const void *userdata, char **ret);
-int specifier_host_name(char specifier, const void *data, const void *userdata, char **ret);
-int specifier_short_host_name(char specifier, const void *data, const void *userdata, char **ret);
-int specifier_kernel_release(char specifier, const void *data, const void *userdata, char **ret);
-int specifier_architecture(char specifier, const void *data, const void *userdata, char **ret);
-int specifier_os_id(char specifier, const void *data, const void *userdata, char **ret);
-int specifier_os_version_id(char specifier, const void *data, const void *userdata, char **ret);
-int specifier_os_build_id(char specifier, const void *data, const void *userdata, char **ret);
-int specifier_os_variant_id(char specifier, const void *data, const void *userdata, char **ret);
-int specifier_os_image_id(char specifier, const void *data, const void *userdata, char **ret);
-int specifier_os_image_version(char specifier, const void *data, const void *userdata, char **ret);
+int specifier_machine_id(char specifier, const void *data, const char *root, const void *userdata, char **ret);
+int specifier_boot_id(char specifier, const void *data, const char *root, const void *userdata, char **ret);
+int specifier_host_name(char specifier, const void *data, const char *root, const void *userdata, char **ret);
+int specifier_short_host_name(char specifier, const void *data, const char *root, const void *userdata, char **ret);
+int specifier_kernel_release(char specifier, const void *data, const char *root, const void *userdata, char **ret);
+int specifier_architecture(char specifier, const void *data, const char *root, const void *userdata, char **ret);
+int specifier_os_id(char specifier, const void *data, const char *root, const void *userdata, char **ret);
+int specifier_os_version_id(char specifier, const void *data, const char *root, const void *userdata, char **ret);
+int specifier_os_build_id(char specifier, const void *data, const char *root, const void *userdata, char **ret);
+int specifier_os_variant_id(char specifier, const void *data, const char *root, const void *userdata, char **ret);
+int specifier_os_image_id(char specifier, const void *data, const char *root, const void *userdata, char **ret);
+int specifier_os_image_version(char specifier, const void *data, const char *root, const void *userdata, char **ret);
-int specifier_group_name(char specifier, const void *data, const void *userdata, char **ret);
-int specifier_group_id(char specifier, const void *data, const void *userdata, char **ret);
-int specifier_user_name(char specifier, const void *data, const void *userdata, char **ret);
-int specifier_user_id(char specifier, const void *data, const void *userdata, char **ret);
-int specifier_user_home(char specifier, const void *data, const void *userdata, char **ret);
-int specifier_user_shell(char specifier, const void *data, const void *userdata, char **ret);
+int specifier_group_name(char specifier, const void *data, const char *root, const void *userdata, char **ret);
+int specifier_group_id(char specifier, const void *data, const char *root, const void *userdata, char **ret);
+int specifier_user_name(char specifier, const void *data, const char *root, const void *userdata, char **ret);
+int specifier_user_id(char specifier, const void *data, const char *root, const void *userdata, char **ret);
+int specifier_user_home(char specifier, const void *data, const char *root, const void *userdata, char **ret);
+int specifier_user_shell(char specifier, const void *data, const char *root, const void *userdata, char **ret);
-int specifier_tmp_dir(char specifier, const void *data, const void *userdata, char **ret);
-int specifier_var_tmp_dir(char specifier, const void *data, const void *userdata, char **ret);
+int specifier_tmp_dir(char specifier, const void *data, const char *root, const void *userdata, char **ret);
+int specifier_var_tmp_dir(char specifier, const void *data, const char *root, const void *userdata, char **ret);
/* Typically, in places where one of the above specifier is to be resolved the other similar ones are to be
* resolved, too. Hence let's define common macros for the relevant array entries.
name = mfree(name);
if (name) {
- r = specifier_printf(name, NAME_MAX, system_and_tmp_specifier_table, NULL, &resolved_name);
+ r = specifier_printf(name, NAME_MAX, system_and_tmp_specifier_table, arg_root, NULL, &resolved_name);
if (r < 0)
return log_error_errno(r, "[%s:%u] Failed to replace specifiers in '%s': %m", fname, line, name);
id = mfree(id);
if (id) {
- r = specifier_printf(id, PATH_MAX-1, system_and_tmp_specifier_table, NULL, &resolved_id);
+ r = specifier_printf(id, PATH_MAX-1, system_and_tmp_specifier_table, arg_root, NULL, &resolved_id);
if (r < 0)
return log_error_errno(r, "[%s:%u] Failed to replace specifiers in '%s': %m",
fname, line, name);
description = mfree(description);
if (description) {
- r = specifier_printf(description, LONG_LINE_MAX, system_and_tmp_specifier_table, NULL, &resolved_description);
+ r = specifier_printf(description, LONG_LINE_MAX, system_and_tmp_specifier_table, arg_root, NULL, &resolved_description);
if (r < 0)
return log_error_errno(r, "[%s:%u] Failed to replace specifiers in '%s': %m",
fname, line, description);
home = mfree(home);
if (home) {
- r = specifier_printf(home, PATH_MAX-1, system_and_tmp_specifier_table, NULL, &resolved_home);
+ r = specifier_printf(home, PATH_MAX-1, system_and_tmp_specifier_table, arg_root, NULL, &resolved_home);
if (r < 0)
return log_error_errno(r, "[%s:%u] Failed to replace specifiers in '%s': %m",
fname, line, home);
shell = mfree(shell);
if (shell) {
- r = specifier_printf(shell, PATH_MAX-1, system_and_tmp_specifier_table, NULL, &resolved_shell);
+ r = specifier_printf(shell, PATH_MAX-1, system_and_tmp_specifier_table, arg_root, NULL, &resolved_shell);
if (r < 0)
return log_error_errno(r, "[%s:%u] Failed to replace specifiers in '%s': %m",
fname, line, shell);
_cleanup_free_ char *mid = NULL, *bid = NULL, *host = NULL, *gid = NULL, *group = NULL, *uid = NULL, *user = NULL;
- assert_se(specifier_machine_id('m', NULL, NULL, &mid) >= 0 && mid);
- assert_se(specifier_boot_id('b', NULL, NULL, &bid) >= 0 && bid);
+ assert_se(specifier_machine_id('m', NULL, NULL, NULL, &mid) >= 0 && mid);
+ assert_se(specifier_boot_id('b', NULL, NULL, NULL, &bid) >= 0 && bid);
assert_se(host = gethostname_malloc());
assert_se(group = gid_to_name(getgid()));
assert_se(asprintf(&gid, UID_FMT, getgid()) >= 0);
_cleanup_free_ char \
*d1 = strdup(i.name), \
*d2 = strdup(i.path); \
- assert_se(install_name_printf(&src, pattern, &t) >= 0 || !result); \
+ assert_se(install_name_printf(&src, pattern, NULL, &t) >= 0 || !result); \
memzero(i.name, strlen(i.name)); \
memzero(i.path, strlen(i.path)); \
assert_se(d1 && d2); \
log_info("/* %s */", __func__);
- r = specifier_printf("xxx a=%X b=%Y yyy", SIZE_MAX, table, NULL, &w);
+ r = specifier_printf("xxx a=%X b=%Y yyy", SIZE_MAX, table, NULL, NULL, &w);
assert_se(r >= 0);
assert_se(w);
assert_se(streq(w, "xxx a=AAAA b=BBBB yyy"));
free(w);
- r = specifier_printf("machine=%m, boot=%b, host=%H, version=%v, arch=%a", SIZE_MAX, table, NULL, &w);
+ r = specifier_printf("machine=%m, boot=%b, host=%H, version=%v, arch=%a", SIZE_MAX, table, NULL, NULL, &w);
assert_se(r >= 0);
assert_se(w);
puts(w);
w = mfree(w);
- specifier_printf("os=%o, os-version=%w, build=%B, variant=%W", SIZE_MAX, table, NULL, &w);
+ specifier_printf("os=%o, os-version=%w, build=%B, variant=%W", SIZE_MAX, table, NULL, NULL, &w);
if (w)
puts(w);
}
xsprintf(spec, "%%%c", s->specifier);
- assert_se(specifier_printf(spec, SIZE_MAX, specifier_table, NULL, &resolved) >= 0);
+ assert_se(specifier_printf(spec, SIZE_MAX, specifier_table, NULL, NULL, &resolved) >= 0);
log_info("%%%c → %s", s->specifier, resolved);
}
log_info("/* %s */", __func__);
- assert_se(specifier_machine_id('m', NULL, NULL, &mid) >= 0 && mid);
- assert_se(specifier_boot_id('b', NULL, NULL, &bid) >= 0 && bid);
+ assert_se(specifier_machine_id('m', NULL, NULL, NULL, &mid) >= 0 && mid);
+ assert_se(specifier_boot_id('b', NULL, NULL, NULL, &bid) >= 0 && bid);
assert_se(host = gethostname_malloc());
assert_se(user = uid_to_name(getuid()));
assert_se(group = gid_to_name(getgid()));
STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
-static int specifier_machine_id_safe(char specifier, const void *data, const void *userdata, char **ret);
-static int specifier_directory(char specifier, const void *data, const void *userdata, char **ret);
+static int specifier_machine_id_safe(char specifier, const void *data, const char *root, const void *userdata, char **ret);
+static int specifier_directory(char specifier, const void *data, const char *root, const void *userdata, char **ret);
static const Specifier specifier_table[] = {
{ 'a', specifier_architecture, NULL },
{}
};
-static int specifier_machine_id_safe(char specifier, const void *data, const void *userdata, char **ret) {
+static int specifier_machine_id_safe(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
int r;
- /* If /etc/machine_id is missing or empty (e.g. in a chroot environment)
- * return a recognizable error so that the caller can skip the rule
- * gracefully. */
+ /* If /etc/machine_id is missing or empty (e.g. in a chroot environment) return a recognizable error
+ * so that the caller can skip the rule gracefully. */
- r = specifier_machine_id(specifier, data, userdata, ret);
+ r = specifier_machine_id(specifier, data, root, userdata, ret);
if (IN_SET(r, -ENOENT, -ENOMEDIUM))
return -ENXIO;
return r;
}
-static int specifier_directory(char specifier, const void *data, const void *userdata, char **ret) {
+static int specifier_directory(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
struct table_entry {
uint64_t type;
const char *suffix;
[DIRECTORY_LOGS] = { SD_PATH_USER_CONFIGURATION, "log" },
};
- unsigned i;
const struct table_entry *paths;
+ _cleanup_free_ char *p = NULL;
+ unsigned i;
+ int r;
assert_cc(ELEMENTSOF(paths_system) == ELEMENTSOF(paths_user));
paths = arg_user ? paths_user : paths_system;
i = PTR_TO_UINT(data);
assert(i < ELEMENTSOF(paths_system));
- return sd_path_lookup(paths[i].type, paths[i].suffix, ret);
+ r = sd_path_lookup(paths[i].type, paths[i].suffix, &p);
+ if (r < 0)
+ return r;
+
+ if (arg_root) {
+ _cleanup_free_ char *j = NULL;
+
+ j = path_join(arg_root, p);
+ if (!j)
+ return -ENOMEM;
+
+ *ret = TAKE_PTR(j);
+ } else
+ *ret = TAKE_PTR(p);
+
+ return 0;
}
static int log_unresolvable_specifier(const char *filename, unsigned line) {
if (r < 0)
return log_error_errno(r, "Failed to unescape parameter to write: %s", i->argument);
- r = specifier_printf(unescaped, PATH_MAX-1, specifier_table, NULL, &resolved);
+ r = specifier_printf(unescaped, PATH_MAX-1, specifier_table, arg_root, NULL, &resolved);
if (r < 0)
return r;
case SET_XATTR:
case RECURSIVE_SET_XATTR:
STRV_FOREACH(xattr, i->xattrs) {
- r = specifier_printf(*xattr, SIZE_MAX, specifier_table, NULL, &resolved);
+ r = specifier_printf(*xattr, SIZE_MAX, specifier_table, arg_root, NULL, &resolved);
if (r < 0)
return r;
i.allow_failure = allow_failure;
i.try_replace = try_replace;
- r = specifier_printf(path, PATH_MAX-1, specifier_table, NULL, &i.path);
+ r = specifier_printf(path, PATH_MAX-1, specifier_table, arg_root, NULL, &i.path);
if (r == -ENXIO)
return log_unresolvable_specifier(fname, line);
if (r < 0) {