mirror of
https://github.com/systemd/systemd.git
synced 2024-12-22 17:35:35 +03:00
Merge pull request #22195 from keszybz/more-specifiers
Add unit specifiers for fragment path and directory
This commit is contained in:
commit
071be9701a
@ -2098,6 +2098,16 @@ Note that this setting is <emphasis>not</emphasis> influenced by the <varname>Us
|
|||||||
<xi:include href="standard-specifiers.xml" xpointer="V"/>
|
<xi:include href="standard-specifiers.xml" xpointer="V"/>
|
||||||
<xi:include href="standard-specifiers.xml" xpointer="w"/>
|
<xi:include href="standard-specifiers.xml" xpointer="w"/>
|
||||||
<xi:include href="standard-specifiers.xml" xpointer="W"/>
|
<xi:include href="standard-specifiers.xml" xpointer="W"/>
|
||||||
|
<row>
|
||||||
|
<entry><literal>%y</literal></entry>
|
||||||
|
<entry>The path to the fragment</entry>
|
||||||
|
<entry>This is the path where the main part of the unit file is located. For linked unit files, the real path outside of the unit search directories is used. For units that don't have a fragment file, this specifier will raise an error.</entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry><literal>%Y</literal></entry>
|
||||||
|
<entry>The directory of the fragment</entry>
|
||||||
|
<entry>This is the directory part of <literal>%y</literal>.</entry>
|
||||||
|
</row>
|
||||||
<xi:include href="standard-specifiers.xml" xpointer="percent"/>
|
<xi:include href="standard-specifiers.xml" xpointer="percent"/>
|
||||||
</tbody>
|
</tbody>
|
||||||
</tgroup>
|
</tgroup>
|
||||||
|
@ -13,28 +13,22 @@
|
|||||||
#include "user-util.h"
|
#include "user-util.h"
|
||||||
|
|
||||||
static int specifier_prefix_and_instance(char specifier, const void *data, const char *root, 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;
|
const Unit *u = ASSERT_PTR(userdata);
|
||||||
|
|
||||||
assert(u);
|
|
||||||
|
|
||||||
return unit_name_to_prefix_and_instance(u->id, ret);
|
return unit_name_to_prefix_and_instance(u->id, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int specifier_prefix(char specifier, const void *data, const char *root, 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;
|
const Unit *u = ASSERT_PTR(userdata);
|
||||||
|
|
||||||
assert(u);
|
|
||||||
|
|
||||||
return unit_name_to_prefix(u->id, ret);
|
return unit_name_to_prefix(u->id, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int specifier_prefix_unescaped(char specifier, const void *data, const char *root, 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;
|
_cleanup_free_ char *p = NULL;
|
||||||
const Unit *u = userdata;
|
const Unit *u = ASSERT_PTR(userdata);
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(u);
|
|
||||||
|
|
||||||
r = unit_name_to_prefix(u->id, &p);
|
r = unit_name_to_prefix(u->id, &p);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
@ -43,21 +37,17 @@ static int specifier_prefix_unescaped(char specifier, const void *data, const ch
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int specifier_instance_unescaped(char specifier, const void *data, const char *root, 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;
|
const Unit *u = ASSERT_PTR(userdata);
|
||||||
|
|
||||||
assert(u);
|
|
||||||
|
|
||||||
return unit_name_unescape(strempty(u->instance), ret);
|
return unit_name_unescape(strempty(u->instance), ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int specifier_last_component(char specifier, const void *data, const char *root, 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;
|
const Unit *u = ASSERT_PTR(userdata);
|
||||||
_cleanup_free_ char *prefix = NULL;
|
_cleanup_free_ char *prefix = NULL;
|
||||||
char *dash;
|
char *dash;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(u);
|
|
||||||
|
|
||||||
r = unit_name_to_prefix(u->id, &prefix);
|
r = unit_name_to_prefix(u->id, &prefix);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
@ -82,9 +72,7 @@ static int specifier_last_component_unescaped(char specifier, const void *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int specifier_filename(char specifier, const void *data, const char *root, 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;
|
const Unit *u = ASSERT_PTR(userdata);
|
||||||
|
|
||||||
assert(u);
|
|
||||||
|
|
||||||
if (u->instance)
|
if (u->instance)
|
||||||
return unit_name_path_unescape(u->instance, ret);
|
return unit_name_path_unescape(u->instance, ret);
|
||||||
@ -97,11 +85,9 @@ static void bad_specifier(const Unit *u, char specifier) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int specifier_cgroup(char specifier, const void *data, const char *root, 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;
|
const Unit *u = ASSERT_PTR(userdata);
|
||||||
char *n;
|
char *n;
|
||||||
|
|
||||||
assert(u);
|
|
||||||
|
|
||||||
bad_specifier(u, specifier);
|
bad_specifier(u, specifier);
|
||||||
|
|
||||||
if (u->cgroup_path)
|
if (u->cgroup_path)
|
||||||
@ -116,11 +102,9 @@ static int specifier_cgroup(char specifier, const void *data, const char *root,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int specifier_cgroup_root(char specifier, const void *data, const char *root, 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;
|
const Unit *u = ASSERT_PTR(userdata);
|
||||||
char *n;
|
char *n;
|
||||||
|
|
||||||
assert(u);
|
|
||||||
|
|
||||||
bad_specifier(u, specifier);
|
bad_specifier(u, specifier);
|
||||||
|
|
||||||
n = strdup(u->manager->cgroup_root);
|
n = strdup(u->manager->cgroup_root);
|
||||||
@ -132,11 +116,9 @@ static int specifier_cgroup_root(char specifier, const void *data, const char *r
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int specifier_cgroup_slice(char specifier, const void *data, const char *root, 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;
|
const Unit *u = ASSERT_PTR(userdata), *slice;
|
||||||
char *n;
|
char *n;
|
||||||
|
|
||||||
assert(u);
|
|
||||||
|
|
||||||
bad_specifier(u, specifier);
|
bad_specifier(u, specifier);
|
||||||
|
|
||||||
slice = UNIT_GET_SLICE(u);
|
slice = UNIT_GET_SLICE(u);
|
||||||
@ -155,11 +137,9 @@ static int specifier_cgroup_slice(char specifier, const void *data, const char *
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int specifier_special_directory(char specifier, const void *data, const char *root, 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;
|
const Unit *u = ASSERT_PTR(userdata);
|
||||||
char *n = NULL;
|
char *n = NULL;
|
||||||
|
|
||||||
assert(u);
|
|
||||||
|
|
||||||
n = strdup(u->manager->prefix[PTR_TO_UINT(data)]);
|
n = strdup(u->manager->prefix[PTR_TO_UINT(data)]);
|
||||||
if (!n)
|
if (!n)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@ -169,7 +149,6 @@ static int specifier_special_directory(char specifier, const void *data, const c
|
|||||||
}
|
}
|
||||||
|
|
||||||
int unit_name_printf(const Unit *u, const char* format, char **ret) {
|
int unit_name_printf(const Unit *u, const char* format, char **ret) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This will use the passed string as format string and replace the following specifiers (which should all be
|
* This will use the passed string as format string and replace the following specifiers (which should all be
|
||||||
* safe for inclusion in unit names):
|
* safe for inclusion in unit names):
|
||||||
@ -240,6 +219,8 @@ int unit_full_printf_full(const Unit *u, const char *format, size_t max_length,
|
|||||||
{ 'P', specifier_prefix_unescaped, NULL },
|
{ 'P', specifier_prefix_unescaped, NULL },
|
||||||
|
|
||||||
{ 'f', specifier_filename, NULL },
|
{ 'f', specifier_filename, NULL },
|
||||||
|
{ 'y', specifier_real_path, u->fragment_path },
|
||||||
|
{ 'Y', specifier_real_directory, u->fragment_path },
|
||||||
|
|
||||||
{ 'c', specifier_cgroup, NULL },
|
{ 'c', specifier_cgroup, NULL },
|
||||||
{ 'r', specifier_cgroup_slice, NULL },
|
{ 'r', specifier_cgroup_slice, NULL },
|
||||||
|
@ -14,12 +14,10 @@
|
|||||||
#include "user-util.h"
|
#include "user-util.h"
|
||||||
|
|
||||||
static int specifier_prefix_and_instance(char specifier, const void *data, const char *root, 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;
|
const UnitFileInstallInfo *i = ASSERT_PTR(userdata);
|
||||||
_cleanup_free_ char *prefix = NULL;
|
_cleanup_free_ char *prefix = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(i);
|
|
||||||
|
|
||||||
r = unit_name_to_prefix_and_instance(i->name, &prefix);
|
r = unit_name_to_prefix_and_instance(i->name, &prefix);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
@ -38,11 +36,9 @@ static int specifier_prefix_and_instance(char specifier, const void *data, const
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int specifier_name(char specifier, const void *data, const char *root, 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;
|
const UnitFileInstallInfo *i = ASSERT_PTR(userdata);
|
||||||
char *ans;
|
char *ans;
|
||||||
|
|
||||||
assert(i);
|
|
||||||
|
|
||||||
if (unit_name_is_valid(i->name, UNIT_NAME_TEMPLATE) && i->default_instance)
|
if (unit_name_is_valid(i->name, UNIT_NAME_TEMPLATE) && i->default_instance)
|
||||||
return unit_name_replace_instance(i->name, i->default_instance, ret);
|
return unit_name_replace_instance(i->name, i->default_instance, ret);
|
||||||
|
|
||||||
@ -54,20 +50,16 @@ static int specifier_name(char specifier, const void *data, const char *root, co
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int specifier_prefix(char specifier, const void *data, const char *root, 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;
|
const UnitFileInstallInfo *i = ASSERT_PTR(userdata);
|
||||||
|
|
||||||
assert(i);
|
|
||||||
|
|
||||||
return unit_name_to_prefix(i->name, ret);
|
return unit_name_to_prefix(i->name, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int specifier_instance(char specifier, const void *data, const char *root, 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;
|
const UnitFileInstallInfo *i = ASSERT_PTR(userdata);
|
||||||
char *instance;
|
char *instance;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(i);
|
|
||||||
|
|
||||||
r = unit_name_to_instance(i->name, &instance);
|
r = unit_name_to_instance(i->name, &instance);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
@ -87,6 +79,8 @@ static int specifier_last_component(char specifier, const void *data, const char
|
|||||||
char *dash;
|
char *dash;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
assert(ret);
|
||||||
|
|
||||||
r = specifier_prefix(specifier, data, root, userdata, &prefix);
|
r = specifier_prefix(specifier, data, root, userdata, &prefix);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "id128-util.h"
|
#include "id128-util.h"
|
||||||
#include "macro.h"
|
#include "macro.h"
|
||||||
#include "os-util.h"
|
#include "os-util.h"
|
||||||
|
#include "path-util.h"
|
||||||
#include "specifier.h"
|
#include "specifier.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
@ -35,7 +36,6 @@
|
|||||||
int specifier_printf(const char *text, size_t max_length, const Specifier table[], const char *root, 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;
|
_cleanup_free_ char *result = NULL;
|
||||||
bool percent = false;
|
bool percent = false;
|
||||||
const char *f;
|
|
||||||
size_t l;
|
size_t l;
|
||||||
char *t;
|
char *t;
|
||||||
int r;
|
int r;
|
||||||
@ -48,8 +48,10 @@ int specifier_printf(const char *text, size_t max_length, const Specifier table[
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
t = result;
|
t = result;
|
||||||
|
|
||||||
for (f = text; *f != '\0'; f++, l--) {
|
for (const char *f = text; *f != '\0'; f++, l--) {
|
||||||
if (percent) {
|
if (percent) {
|
||||||
|
percent = false;
|
||||||
|
|
||||||
if (*f == '%')
|
if (*f == '%')
|
||||||
*(t++) = '%';
|
*(t++) = '%';
|
||||||
else {
|
else {
|
||||||
@ -66,6 +68,8 @@ int specifier_printf(const char *text, size_t max_length, const Specifier table[
|
|||||||
r = i->lookup(i->specifier, i->data, root, userdata, &w);
|
r = i->lookup(i->specifier, i->data, root, userdata, &w);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
if (isempty(w))
|
||||||
|
continue;
|
||||||
|
|
||||||
j = t - result;
|
j = t - result;
|
||||||
k = strlen(w);
|
k = strlen(w);
|
||||||
@ -82,8 +86,6 @@ int specifier_printf(const char *text, size_t max_length, const Specifier table[
|
|||||||
*(t++) = *f;
|
*(t++) = *f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
percent = false;
|
|
||||||
} else if (*f == '%')
|
} else if (*f == '%')
|
||||||
percent = true;
|
percent = true;
|
||||||
else
|
else
|
||||||
@ -108,16 +110,39 @@ int specifier_printf(const char *text, size_t max_length, const Specifier table[
|
|||||||
/* Generic handler for simple string replacements */
|
/* Generic handler for simple string replacements */
|
||||||
|
|
||||||
int specifier_string(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
|
int specifier_string(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
|
||||||
char *n;
|
char *n = NULL;
|
||||||
|
|
||||||
n = strdup(strempty(data));
|
if (!isempty(data)) {
|
||||||
|
n = strdup(data);
|
||||||
if (!n)
|
if (!n)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
*ret = n;
|
*ret = n;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int specifier_real_path(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
|
||||||
|
const char *path = data;
|
||||||
|
|
||||||
|
if (!path)
|
||||||
|
return -ENOENT;
|
||||||
|
|
||||||
|
return chase_symlinks(path, root, 0, ret, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int specifier_real_directory(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
|
||||||
|
_cleanup_free_ char *path = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = specifier_real_path(specifier, data, root, userdata, &path);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
assert(path);
|
||||||
|
return path_extract_directory(path, ret);
|
||||||
|
}
|
||||||
|
|
||||||
int specifier_machine_id(char specifier, const void *data, const char *root, 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;
|
sd_id128_t id;
|
||||||
char *n;
|
char *n;
|
||||||
@ -186,10 +211,8 @@ int specifier_short_host_name(char specifier, const void *data, const char *root
|
|||||||
int specifier_kernel_release(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) {
|
||||||
struct utsname uts;
|
struct utsname uts;
|
||||||
char *n;
|
char *n;
|
||||||
int r;
|
|
||||||
|
|
||||||
r = uname(&uts);
|
if (uname(&uts) < 0)
|
||||||
if (r < 0)
|
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
n = strdup(uts.release);
|
n = strdup(uts.release);
|
||||||
@ -211,47 +234,31 @@ int specifier_architecture(char specifier, const void *data, const char *root, c
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int specifier_os_release_common(const char *field, const char *root, char **ret) {
|
/* Note: fields in /etc/os-release might quite possibly be missing, even if everything is entirely valid
|
||||||
char *t = NULL;
|
* otherwise. We'll return an empty value or NULL in that case from the functions below. */
|
||||||
int r;
|
|
||||||
|
|
||||||
r = parse_os_release(root, field, &t);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
if (!t) {
|
|
||||||
/* fields in /etc/os-release might quite possibly be missing, even if everything is entirely
|
|
||||||
* valid otherwise. Let's hence return "" in that case. */
|
|
||||||
t = strdup("");
|
|
||||||
if (!t)
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
*ret = t;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int specifier_os_id(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) {
|
||||||
return specifier_os_release_common("ID", root, ret);
|
return parse_os_release(root, "ID", ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
int specifier_os_version_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) {
|
||||||
return specifier_os_release_common("VERSION_ID", root, ret);
|
return parse_os_release(root, "VERSION_ID", ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
int specifier_os_build_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) {
|
||||||
return specifier_os_release_common("BUILD_ID", root, ret);
|
return parse_os_release(root, "BUILD_ID", ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
int specifier_os_variant_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) {
|
||||||
return specifier_os_release_common("VARIANT_ID", root, ret);
|
return parse_os_release(root, "VARIANT_ID", ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
int specifier_os_image_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) {
|
||||||
return specifier_os_release_common("IMAGE_ID", root, ret);
|
return parse_os_release(root, "IMAGE_ID", ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
int specifier_os_image_version(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) {
|
||||||
return specifier_os_release_common("IMAGE_VERSION", root, ret);
|
return parse_os_release(root, "IMAGE_VERSION", ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
int specifier_group_name(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
|
int specifier_group_name(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
|
||||||
@ -291,7 +298,6 @@ int specifier_user_name(char specifier, const void *data, const char *root, cons
|
|||||||
}
|
}
|
||||||
|
|
||||||
int specifier_user_id(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) {
|
||||||
|
|
||||||
if (asprintf(ret, UID_FMT, getuid()) < 0)
|
if (asprintf(ret, UID_FMT, getuid()) < 0)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -14,6 +14,8 @@ typedef struct Specifier {
|
|||||||
int specifier_printf(const char *text, size_t max_length, const Specifier table[], const char *root, 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 char *root, const void *userdata, char **ret);
|
int specifier_string(char specifier, const void *data, const char *root, const void *userdata, char **ret);
|
||||||
|
int specifier_real_path(char specifier, const void *data, const char *root, const void *userdata, char **ret);
|
||||||
|
int specifier_real_directory(char specifier, const void *data, const char *root, const void *userdata, char **ret);
|
||||||
|
|
||||||
int specifier_machine_id(char specifier, const void *data, const char *root, 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_boot_id(char specifier, const void *data, const char *root, const void *userdata, char **ret);
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "specifier.h"
|
#include "specifier.h"
|
||||||
|
#include "stat-util.h"
|
||||||
#include "stdio-util.h"
|
#include "stdio-util.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
@ -56,6 +57,7 @@ TEST(specifier_printf) {
|
|||||||
static const Specifier table[] = {
|
static const Specifier table[] = {
|
||||||
{ 'X', specifier_string, (char*) "AAAA" },
|
{ 'X', specifier_string, (char*) "AAAA" },
|
||||||
{ 'Y', specifier_string, (char*) "BBBB" },
|
{ 'Y', specifier_string, (char*) "BBBB" },
|
||||||
|
{ 'e', specifier_string, NULL },
|
||||||
COMMON_SYSTEM_SPECIFIERS,
|
COMMON_SYSTEM_SPECIFIERS,
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
@ -63,25 +65,66 @@ TEST(specifier_printf) {
|
|||||||
_cleanup_free_ char *w = NULL;
|
_cleanup_free_ char *w = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = specifier_printf("xxx a=%X b=%Y yyy", SIZE_MAX, table, NULL, NULL, &w);
|
r = specifier_printf("xxx a=%X b=%Y e=%e yyy", SIZE_MAX, table, NULL, NULL, &w);
|
||||||
assert_se(r >= 0);
|
assert_se(r >= 0);
|
||||||
assert_se(w);
|
assert_se(w);
|
||||||
|
|
||||||
puts(w);
|
puts(w);
|
||||||
assert_se(streq(w, "xxx a=AAAA b=BBBB yyy"));
|
assert_se(streq(w, "xxx a=AAAA b=BBBB e= yyy"));
|
||||||
|
|
||||||
free(w);
|
free(w);
|
||||||
r = specifier_printf("machine=%m, boot=%b, host=%H, version=%v, arch=%a", SIZE_MAX, table, NULL, NULL, &w);
|
r = specifier_printf("machine=%m, boot=%b, host=%H, version=%v, arch=%a, empty=%e", SIZE_MAX, table, NULL, NULL, &w);
|
||||||
assert_se(r >= 0);
|
assert_se(r >= 0);
|
||||||
assert_se(w);
|
assert_se(w);
|
||||||
puts(w);
|
puts(w);
|
||||||
|
|
||||||
w = mfree(w);
|
w = mfree(w);
|
||||||
specifier_printf("os=%o, os-version=%w, build=%B, variant=%W", SIZE_MAX, table, NULL, NULL, &w);
|
specifier_printf("os=%o, os-version=%w, build=%B, variant=%W, empty=%e%e%e", SIZE_MAX, table, NULL, NULL, &w);
|
||||||
if (w)
|
if (w)
|
||||||
puts(w);
|
puts(w);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(specifier_real_path) {
|
||||||
|
static const Specifier table[] = {
|
||||||
|
{ 'p', specifier_string, "/dev/initctl" },
|
||||||
|
{ 'y', specifier_real_path, "/dev/initctl" },
|
||||||
|
{ 'Y', specifier_real_directory, "/dev/initctl" },
|
||||||
|
{ 'w', specifier_real_path, "/dev/tty" },
|
||||||
|
{ 'W', specifier_real_directory, "/dev/tty" },
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
_cleanup_free_ char *w = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = specifier_printf("p=%p y=%y Y=%Y w=%w W=%W", SIZE_MAX, table, NULL, NULL, &w);
|
||||||
|
assert_se(r >= 0 || r == -ENOENT);
|
||||||
|
assert_se(w || r == -ENOENT);
|
||||||
|
puts(strnull(w));
|
||||||
|
|
||||||
|
/* /dev/initctl should normally be a symlink to /run/initctl */
|
||||||
|
if (files_same("/dev/initctl", "/run/initctl", 0) > 0)
|
||||||
|
assert_se(streq(w, "p=/dev/initctl y=/run/initctl Y=/run w=/dev/tty W=/dev"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(specifier_real_path_missing_file) {
|
||||||
|
static const Specifier table[] = {
|
||||||
|
{ 'p', specifier_string, "/dev/-no-such-file--" },
|
||||||
|
{ 'y', specifier_real_path, "/dev/-no-such-file--" },
|
||||||
|
{ 'Y', specifier_real_directory, "/dev/-no-such-file--" },
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
_cleanup_free_ char *w = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = specifier_printf("p=%p y=%y", SIZE_MAX, table, NULL, NULL, &w);
|
||||||
|
assert_se(r == -ENOENT);
|
||||||
|
|
||||||
|
r = specifier_printf("p=%p Y=%Y", SIZE_MAX, table, NULL, NULL, &w);
|
||||||
|
assert_se(r == -ENOENT);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(specifiers) {
|
TEST(specifiers) {
|
||||||
for (const Specifier *s = specifier_table; s->specifier; s++) {
|
for (const Specifier *s = specifier_table; s->specifier; s++) {
|
||||||
char spec[3];
|
char spec[3];
|
||||||
|
Loading…
Reference in New Issue
Block a user