[systemd-commits] 11 commits - Makefile.am man/systemd.unit.xml src/core src/shared src/test test/README.testsuite test/TEST-01-BASIC test/TEST-03-JOBS TODO
Zbigniew JÄdrzejewski-Szmek
zbyszek at kemper.freedesktop.org
Tue Jan 29 16:28:57 PST 2013
Makefile.am | 12 -
TODO | 3
man/systemd.unit.xml | 4
src/core/unit-printf.c | 51 ----
src/shared/install-printf.c | 132 +++++++++++
src/shared/install-printf.h | 25 ++
src/shared/install.c | 511 +++++++++++++++++---------------------------
src/shared/install.h | 10
src/shared/macro.h | 1
src/shared/set.c | 8
src/shared/set.h | 1
src/shared/specifier.c | 36 +++
src/shared/specifier.h | 6
src/test/test-unit-file.c | 71 ++++++
src/test/test-unit-name.c | 302 +++++++++++++-------------
test/README.testsuite | 4
test/TEST-01-BASIC/test.sh | 6
test/TEST-03-JOBS/test.sh | 2
18 files changed, 677 insertions(+), 508 deletions(-)
New commits:
commit 7bcd865d386d96caac83cb1c589fdb8f9ce3b081
Author: Zbigniew JÄdrzejewski-Szmek <zbyszek at in.waw.pl>
Date: Tue Jan 29 16:14:07 2013 -0500
test: some trivial fixes to test scripts
- fix typo
- use compiled systemd-nspawn
- drop --capability=... from systemd-nspawn invocation, is is the default now
- simplify sudo make invocations
diff --git a/TODO b/TODO
index 3e2ff8b..26e4c5a 100644
--- a/TODO
+++ b/TODO
@@ -13,6 +13,9 @@ Bugfixes:
* properly handle .mount unit state tracking when two mount points are stacked one on top of another on the exact same mount point.
+* add 'set -e' to scripts in test/
+* make test in test/ work with separate output dir
+
Fedora 19:
* drop no longer needed modprobe.d udlfb file (it does not belong in /etc anyway)
diff --git a/test/README.testsuite b/test/README.testsuite
index 0f96b98..54d0eaa 100644
--- a/test/README.testsuite
+++ b/test/README.testsuite
@@ -28,8 +28,8 @@ $ sudo make clean setup run
If you want to log in the testsuite virtual machine, you can specify
additional kernel command line parameter with $DEBUGFAIL.
-$ sudo sh -c 'DEBUGFAIL="systemd.unit=multi-user.target" make clean setup run'
+$ sudo make DEBUGFAIL="systemd.unit=multi-user.target" clean setup run
you can even skip the "clean" and "setup" if you want to run the machine again.
-$ sudo sh -c 'DEBUGFAIL="systemd.unit=multi-user.target" make run'
+$ sudo make DEBUGFAIL="systemd.unit=multi-user.target" run
diff --git a/test/TEST-01-BASIC/test.sh b/test/TEST-01-BASIC/test.sh
index 7d2e3d4..9049207 100755
--- a/test/TEST-01-BASIC/test.sh
+++ b/test/TEST-01-BASIC/test.sh
@@ -33,7 +33,7 @@ run_qemu() {
run_nspawn() {
- systemd-nspawn -b -D $TESTDIR/nspawn-root --capability=CAP_AUDIT_CONTROL,CAP_AUDIT_WRITE /usr/lib/systemd/systemd
+ ../../systemd-nspawn -b -D $TESTDIR/nspawn-root /usr/lib/systemd/systemd
ret=1
[[ -e $TESTDIR/nspawn-root/testok ]] && ret=0
cp -a $TESTDIR/nspawn-root/failed $TESTDIR
@@ -213,7 +213,7 @@ EOF
# install ld.so.conf* and run ldconfig
cp -a /etc/ld.so.conf* $initdir/etc
ldconfig -r "$initdir"
- ddebug "Strip binaeries"
+ ddebug "Strip binaries"
find "$initdir" -perm +111 -type f | xargs strip --strip-unneeded | ddebug
# copy depmod files
@@ -230,7 +230,7 @@ EOF
ddebug "cp -ar $TESTDIR/root $TESTDIR/nspawn-root"
cp -ar $TESTDIR/root $TESTDIR/nspawn-root
# we don't mount in the nspawn root
- rm -fr $TESTDIR/nspawn-root/etc/fstab
+ rm -f $TESTDIR/nspawn-root/etc/fstab
ddebug "umount $TESTDIR/root"
umount $TESTDIR/root
diff --git a/test/TEST-03-JOBS/test.sh b/test/TEST-03-JOBS/test.sh
index 4cfb2a5..bd211f3 100755
--- a/test/TEST-03-JOBS/test.sh
+++ b/test/TEST-03-JOBS/test.sh
@@ -33,7 +33,7 @@ run_qemu() {
run_nspawn() {
- systemd-nspawn -b -D $TESTDIR/nspawn-root --capability=CAP_AUDIT_CONTROL,CAP_AUDIT_WRITE /usr/lib/systemd/systemd
+ ../../systemd-nspawn -b -D $TESTDIR/nspawn-root /usr/lib/systemd/systemd
ret=1
[[ -e $TESTDIR/nspawn-root/testok ]] && ret=0
cp -a $TESTDIR/nspawn-root/failed $TESTDIR
commit 1682ff60114b7a57972a03aa99f9864064593f72
Author: Zbigniew JÄdrzejewski-Szmek <zbyszek at in.waw.pl>
Date: Tue Jan 29 15:25:36 2013 -0500
tests: add test for unit name printing
diff --git a/Makefile.am b/Makefile.am
index c44ca0b..f014931 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1325,6 +1325,10 @@ test_efivars_LDADD = \
test_unit_name_SOURCES = \
src/test/test-unit-name.c
+test_unit_name_CFLAGS = \
+ $(AM_CFLAGS) \
+ $(DBUS_CFLAGS)
+
test_unit_name_LDADD = \
libsystemd-core.la
diff --git a/src/test/test-unit-name.c b/src/test/test-unit-name.c
index 5207781..b1a4134 100644
--- a/src/test/test-unit-name.c
+++ b/src/test/test-unit-name.c
@@ -4,6 +4,7 @@
This file is part of systemd.
Copyright 2012 Lennart Poettering
+ Copyright 2013 Zbigniew JÄdrzejewski-Szmek
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
@@ -22,12 +23,19 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include "manager.h"
+#include "unit.h"
#include "unit-name.h"
+#include "unit-printf.h"
+#include "install.h"
+#include "specifier.h"
#include "util.h"
+#include "macro.h"
-int main(int argc, char* argv[]) {
-
+static void test_replacements(void) {
#define expect(pattern, repl, expected) \
{ \
char _cleanup_free_ *t = \
@@ -97,5 +105,85 @@ int main(int argc, char* argv[]) {
expect("_____##@;;;,,,##----.....service");
expect("xxx@@@@/////\\\\\\\\\\yyy.service");
+#undef expect
+}
+
+static void test_unit_printf(void) {
+ Manager *m;
+ Unit *u, *u2;
+
+ char _cleanup_free_ *mid, *bid, *host, *root_uid;
+ struct passwd *root;
+
+ assert_se((mid = specifier_machine_id('m', NULL, NULL)));
+ assert_se((bid = specifier_boot_id('b', NULL, NULL)));
+ assert_se((host = gethostname_malloc()));
+
+ assert_se((root = getpwnam("root")));
+ assert_se(asprintf(&root_uid, "%d", (int) root->pw_uid) > 0);
+
+ assert_se(manager_new(SYSTEMD_SYSTEM, &m) == 0);
+
+#define expect(unit, pattern, expected) \
+ { \
+ char _cleanup_free_ *t = \
+ unit_full_printf(unit, pattern); \
+ printf("result: %s\n", t); \
+ assert(streq(t, expected)); \
+ }
+
+ assert_se(setenv("USER", "root", 1) == 0);
+ assert_se(setenv("HOME", "/root", 1) == 0);
+
+ assert_se(u = unit_new(m, sizeof(Service)));
+ assert_se(unit_add_name(u, "blah.service") == 0);
+ assert_se(unit_add_name(u, "blah.service") == 0);
+
+ /* general tests */
+ expect(u, "%%", "%");
+ expect(u, "%%s", "%s");
+ expect(u, "%", ""); // REALLY?
+
+ /* normal unit */
+ expect(u, "%n", "blah.service");
+ expect(u, "%N", "blah");
+ expect(u, "%p", "blah");
+ expect(u, "%P", "blah");
+ expect(u, "%i", "");
+ expect(u, "%I", "");
+ expect(u, "%u", root->pw_name);
+ expect(u, "%U", root_uid);
+ expect(u, "%h", root->pw_dir);
+ expect(u, "%s", root->pw_shell);
+ expect(u, "%m", mid);
+ expect(u, "%b", bid);
+ expect(u, "%H", host);
+ expect(u, "%t", "/run");
+
+ /* templated */
+ assert_se(u2 = unit_new(m, sizeof(Service)));
+ assert_se(unit_add_name(u2, "blah at foo-foo.service") == 0);
+ assert_se(unit_add_name(u2, "blah at foo-foo.service") == 0);
+
+ expect(u2, "%n", "blah at foo-foo.service");
+ expect(u2, "%N", "blah at foo-foo");
+ expect(u2, "%p", "blah");
+ expect(u2, "%P", "blah");
+ expect(u2, "%i", "foo-foo");
+ expect(u2, "%I", "foo/foo");
+ expect(u2, "%u", root->pw_name);
+ expect(u2, "%U", root_uid);
+ expect(u2, "%h", root->pw_dir);
+ expect(u2, "%s", root->pw_shell);
+ expect(u2, "%m", mid);
+ expect(u2, "%b", bid);
+ expect(u2, "%H", host);
+ expect(u2, "%t", "/run");
+}
+
+int main(int argc, char* argv[]) {
+ test_replacements();
+ test_unit_printf();
+
return 0;
}
commit 3251c0d2392062b2b8354793a2037d1161f824ee
Author: Zbigniew JÄdrzejewski-Szmek <zbyszek at in.waw.pl>
Date: Tue Jan 29 14:39:32 2013 -0500
tests: compress unit name tests and add more asserts
diff --git a/src/test/test-unit-name.c b/src/test/test-unit-name.c
index 50187e1..5207781 100644
--- a/src/test/test-unit-name.c
+++ b/src/test/test-unit-name.c
@@ -27,151 +27,75 @@
#include "util.h"
int main(int argc, char* argv[]) {
- char *t, *k;
-
- t = unit_name_replace_instance("foo at .service", "waldo");
- puts(t);
- free(t);
-
- t = unit_name_replace_instance("foo at xyz.service", "waldo");
- puts(t);
- free(t);
-
- t = unit_name_replace_instance("xyz", "waldo");
- puts(t);
- free(t);
-
- t = unit_name_replace_instance("", "waldo");
- puts(t);
- free(t);
-
- t = unit_name_replace_instance("", "");
- puts(t);
- free(t);
-
- t = unit_name_replace_instance("foo.service", "waldo");
- puts(t);
- free(t);
-
- t = unit_name_replace_instance(".service", "waldo");
- puts(t);
- free(t);
-
- t = unit_name_replace_instance("foo at bar", "waldo");
- puts(t);
- free(t);
-
- t = unit_name_replace_instance("foo@", "waldo");
- puts(t);
- free(t);
-
- t = unit_name_replace_instance("@", "waldo");
- puts(t);
- free(t);
-
- t = unit_name_replace_instance("@bar", "waldo");
- puts(t);
- free(t);
-
- t = unit_name_from_path("/waldo", ".mount");
- puts(t);
- k = unit_name_to_path(t);
- puts(k);
- free(k);
- free(t);
-
- t = unit_name_from_path("/waldo/quuix", ".mount");
- puts(t);
- k = unit_name_to_path(t);
- puts(k);
- free(k);
- free(t);
-
- t = unit_name_from_path("/waldo/quuix/", ".mount");
- puts(t);
- k = unit_name_to_path(t);
- puts(k);
- free(k);
- free(t);
-
- t = unit_name_from_path("/", ".mount");
- puts(t);
- k = unit_name_to_path(t);
- puts(k);
- free(k);
- free(t);
-
- t = unit_name_from_path("///", ".mount");
- puts(t);
- k = unit_name_to_path(t);
- puts(k);
- free(k);
- free(t);
-
- t = unit_name_from_path_instance("waldo", "/waldo", ".mount");
- puts(t);
- free(t);
-
- t = unit_name_from_path_instance("waldo", "/waldo////quuix////", ".mount");
- puts(t);
- free(t);
-
- t = unit_name_from_path_instance("waldo", "/", ".mount");
- puts(t);
- free(t);
-
- t = unit_name_from_path_instance("wa--ldo", "/--", ".mount");
- puts(t);
- free(t);
-
- assert_se(t = unit_name_mangle("/home"));
- assert_se(k = unit_name_mangle(t));
- puts(t);
- assert_se(streq(t, k));
- free(t);
- free(k);
-
- assert_se(t = unit_name_mangle("/dev/sda"));
- assert_se(k = unit_name_mangle(t));
- puts(t);
- assert_se(streq(t, k));
- free(t);
- free(k);
-
- assert_se(t = unit_name_mangle("üxknürz.service"));
- assert_se(k = unit_name_mangle(t));
- puts(t);
- assert_se(streq(t, k));
- free(t);
- free(k);
-
- assert_se(t = unit_name_mangle("foobar-meh...waldi.service"));
- assert_se(k = unit_name_mangle(t));
- puts(t);
- assert_se(streq(t, k));
- free(t);
- free(k);
-
- assert_se(t = unit_name_mangle("_____####----.....service"));
- assert_se(k = unit_name_mangle(t));
- puts(t);
- assert_se(streq(t, k));
- free(t);
- free(k);
-
- assert_se(t = unit_name_mangle("_____##@;;;,,,##----.....service"));
- assert_se(k = unit_name_mangle(t));
- puts(t);
- assert_se(streq(t, k));
- free(t);
- free(k);
-
- assert_se(t = unit_name_mangle("xxx@@@@/////\\\\\\\\\\yyy.service"));
- assert_se(k = unit_name_mangle(t));
- puts(t);
- assert_se(streq(t, k));
- free(t);
- free(k);
+
+#define expect(pattern, repl, expected) \
+ { \
+ char _cleanup_free_ *t = \
+ unit_name_replace_instance(pattern, repl); \
+ puts(t); \
+ assert(streq(t, expected)); \
+ }
+
+ expect("foo at .service", "waldo", "foo at waldo.service");
+ expect("foo at xyz.service", "waldo", "foo at waldo.service");
+ expect("xyz", "waldo", "xyz");
+ expect("", "waldo", "");
+ expect("foo.service", "waldo", "foo.service");
+ expect(".service", "waldo", ".service");
+ expect("foo@", "waldo", "foo at waldo");
+ expect("@bar", "waldo", "@waldo");
+
+ puts("-------------------------------------------------");
+#undef expect
+#define expect(path, suffix, expected) \
+ { \
+ char _cleanup_free_ *k, *t = \
+ unit_name_from_path(path, suffix); \
+ puts(t); \
+ k = unit_name_to_path(t); \
+ puts(k); \
+ assert(streq(k, expected ? expected : path)); \
+ }
+
+ expect("/waldo", ".mount", NULL);
+ expect("/waldo/quuix", ".mount", NULL);
+ expect("/waldo/quuix/", ".mount", "/waldo/quuix");
+ expect("/", ".mount", NULL);
+ expect("///", ".mount", "/");
+
+ puts("-------------------------------------------------");
+#undef expect
+#define expect(pattern, path, suffix, expected) \
+ { \
+ char _cleanup_free_ *t = \
+ unit_name_from_path_instance(pattern, path, suffix); \
+ puts(t); \
+ assert(streq(t, expected)); \
+ }
+
+ expect("waldo", "/waldo", ".mount", "waldo at waldo.mount");
+ expect("waldo", "/waldo////quuix////", ".mount", "waldo at waldo-quuix.mount");
+ expect("waldo", "/", ".mount", "waldo at -.mount");
+ expect("wa--ldo", "/--", ".mount", "wa--ldo@\\x2d\\x2d.mount");
+
+ puts("-------------------------------------------------");
+#undef expect
+#define expect(pattern) \
+ { \
+ char _cleanup_free_ *k, *t; \
+ assert_se(t = unit_name_mangle(pattern)); \
+ assert_se(k = unit_name_mangle(t)); \
+ puts(t); \
+ assert_se(streq(t, k)); \
+ }
+
+ expect("/home");
+ expect("/dev/sda");
+ expect("üxknürz.service");
+ expect("foobar-meh...waldi.service");
+ expect("_____####----.....service");
+ expect("_____##@;;;,,,##----.....service");
+ expect("xxx@@@@/////\\\\\\\\\\yyy.service");
return 0;
}
commit 7742f7e999d58062b9784be83553eda109fff366
Author: Zbigniew JÄdrzejewski-Szmek <zbyszek at in.waw.pl>
Date: Tue Jan 29 14:39:06 2013 -0500
tests: add test for install_full_printf()
diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c
index de8be32..8519131 100644
--- a/src/test/test-unit-file.c
+++ b/src/test/test-unit-file.c
@@ -27,6 +27,8 @@
#include <unistd.h>
#include "install.h"
+#include "install-printf.h"
+#include "specifier.h"
#include "util.h"
#include "macro.h"
#include "hashmap.h"
@@ -228,6 +230,74 @@ static void test_load_env_file_2(void) {
unlink(name);
}
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wnonnull"
+
+static void test_install_printf(void) {
+ char name[] = "name.service",
+ path[] = "/run/systemd/systemd/name.service",
+ user[] = "xxxx-no-such-user";
+ InstallInfo i = {name, path, user};
+ InstallInfo i2 = {name, path, NULL};
+ char name3[] = "name at inst.service",
+ path3[] = "/run/systemd/systemd/name.service";
+ InstallInfo i3 = {name3, path3, user};
+ InstallInfo i4 = {name3, path3, NULL};
+
+ char _cleanup_free_ *mid, *bid, *host;
+
+ assert_se((mid = specifier_machine_id('m', NULL, NULL)));
+ assert_se((bid = specifier_boot_id('b', NULL, NULL)));
+ assert_se((host = gethostname_malloc()));
+
+#define expect(src, pattern, result) \
+ { \
+ char _cleanup_free_ *t = install_full_printf(&src, pattern); \
+ char _cleanup_free_ \
+ *d1 = strdup(i.name), \
+ *d2 = strdup(i.path), \
+ *d3 = strdup(i.user); \
+ memzero(i.name, strlen(i.name)); \
+ memzero(i.path, strlen(i.path)); \
+ memzero(i.user, strlen(i.user)); \
+ assert(d1 && d2 && d3); \
+ if (result) { \
+ printf("%s\n", t); \
+ assert(streq(t, result)); \
+ } else assert(t == NULL); \
+ strcpy(i.name, d1); \
+ strcpy(i.path, d2); \
+ strcpy(i.user, d3); \
+ }
+
+ assert_se(setenv("USER", "root", 1) == 0);
+
+ expect(i, "%n", "name.service");
+ expect(i, "%N", "name");
+ expect(i, "%p", "name");
+ expect(i, "%i", "");
+ expect(i, "%u", "xxxx-no-such-user");
+ expect(i, "%U", NULL);
+ expect(i, "%m", mid);
+ expect(i, "%b", bid);
+ expect(i, "%H", host);
+
+ expect(i2, "%u", "root");
+ expect(i2, "%U", "0");
+
+ expect(i3, "%n", "name at inst.service");
+ expect(i3, "%N", "name at inst");
+ expect(i3, "%p", "name");
+ expect(i3, "%u", "xxxx-no-such-user");
+ expect(i3, "%U", NULL);
+ expect(i3, "%m", mid);
+ expect(i3, "%b", bid);
+ expect(i3, "%H", host);
+
+ expect(i4, "%u", "root");
+ expect(i4, "%U", "0");
+}
+#pragma GCC diagnostic pop
int main(int argc, char *argv[]) {
@@ -235,6 +305,7 @@ int main(int argc, char *argv[]) {
test_config_parse_exec();
test_load_env_file_1();
test_load_env_file_2();
+ test_install_printf();
return 0;
}
commit 3f0b2f0f452e94444e4fb7b62030ea05738bb1b6
Author: Zbigniew JÄdrzejewski-Szmek <zbyszek at in.waw.pl>
Date: Mon Jan 28 22:34:38 2013 -0500
install: allow %u an and %U specifiers in WantedBy/RequiredBy/Alias
diff --git a/src/shared/install-printf.c b/src/shared/install-printf.c
index 85aebc4..10b0cf3 100644
--- a/src/shared/install-printf.c
+++ b/src/shared/install-printf.c
@@ -24,6 +24,7 @@
#include "specifier.h"
#include "unit-name.h"
+#include "util.h"
#include "install-printf.h"
static char *specifier_prefix_and_instance(char specifier, void *data, void *userdata) {
@@ -56,6 +57,42 @@ static char *specifier_instance(char specifier, void *data, void *userdata) {
return strdup("");
}
+static char *specifier_user_name(char specifier, void *data, void *userdata) {
+ InstallInfo *i = userdata;
+ const char *username;
+ char _cleanup_free_ *tmp = NULL;
+ char *printed = NULL;
+
+ assert(i);
+
+ if (i->user)
+ username = i->user;
+ else
+ /* get USER env from env or our own uid */
+ username = tmp = getusername_malloc();
+
+ switch (specifier) {
+ case 'u':
+ printed = strdup(username);
+ break;
+ case 'U': {
+ /* fish username from passwd */
+ uid_t uid;
+ int r;
+
+ r = get_user_creds(&username, &uid, NULL, NULL, NULL);
+ if (r < 0)
+ return NULL;
+
+ if (asprintf(&printed, "%d", uid) < 0)
+ return NULL;
+ break;
+ }}
+
+ return printed;
+}
+
+
char *install_full_printf(InstallInfo *i, const char *format) {
/* This is similar to unit_full_printf() but does not support
@@ -79,8 +116,8 @@ char *install_full_printf(InstallInfo *i, const char *format) {
{ 'p', specifier_prefix, NULL },
{ 'i', specifier_instance, NULL },
-// { 'U', specifier_user_name, NULL },
-// { 'u', specifier_user_name, NULL },
+ { 'U', specifier_user_name, NULL },
+ { 'u', specifier_user_name, NULL },
{ 'm', specifier_machine_id, NULL },
{ 'H', specifier_host_name, NULL },
diff --git a/src/shared/install.c b/src/shared/install.c
index 7fb352c..b82d189 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -956,6 +956,33 @@ static int config_parse_also(
return 0;
}
+static int config_parse_user(
+ const char *filename,
+ unsigned line,
+ const char *section,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ InstallInfo *i = data;
+ char* printed;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+
+ printed = install_full_printf(i, rvalue);
+ if (!printed)
+ return -ENOMEM;
+
+ free(i->user);
+ i->user = printed;
+
+ return 0;
+}
+
static int unit_file_load(
InstallContext *c,
InstallInfo *info,
@@ -967,6 +994,7 @@ static int unit_file_load(
{ "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
{ "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
{ "Install", "Also", config_parse_also, 0, c },
+ { "Exec", "User", config_parse_user, 0, info },
{ NULL, NULL, NULL, 0, NULL }
};
diff --git a/src/shared/install.h b/src/shared/install.h
index 5a35125..755ddde 100644
--- a/src/shared/install.h
+++ b/src/shared/install.h
@@ -66,6 +66,7 @@ typedef struct UnitFileList {
typedef struct {
char *name;
char *path;
+ char *user;
char **aliases;
char **wanted_by;
commit 7584d236eac91f9b7128b1eb08bddf18be2bce9f
Author: Zbigniew JÄdrzejewski-Szmek <zbyszek at in.waw.pl>
Date: Sun Jan 27 23:11:31 2013 -0500
install: allow specifiers in WantedBy/RequiredBy/Alias
This allows one templated unit to refer to another templated unit
at installation time.
Examples:
> grep WantedBy ~/.config/systemd/user/mpop at .timer
WantedBy=services@%i.target
> srv disable mpop at iit.timer
rm '/home/alxchk/.config/systemd/user/services at iit.target.wants/mpop at iit.timer'
> srv enable mpop at iit.timer
ln -s '/home/alxchk/.config/systemd/user/mpop at .timer' '/home/alxchk/.config/systemd/user/services at iit.target.wants/mpop at iit.timer'
Based-on-patch-by: Oleksii Shevchuk <alxchk at gmail.com>
diff --git a/Makefile.am b/Makefile.am
index 8d10144..c44ca0b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -901,6 +901,8 @@ noinst_LTLIBRARIES += \
libsystemd_units_la_SOURCES = \
src/shared/install.c \
src/shared/install.h \
+ src/shared/install-printf.c \
+ src/shared/install-printf.h \
src/shared/path-lookup.c \
src/shared/path-lookup.h
@@ -1403,7 +1405,8 @@ test_strv_SOURCES = \
src/test/test-strv.c
test_strv_LDADD = \
- libsystemd-shared.la
+ libsystemd-shared.la \
+ libsystemd-id128-internal.la
test_install_SOURCES = \
src/test/test-install.c
@@ -1415,7 +1418,8 @@ test_install_CFLAGS = \
test_install_LDADD = \
libsystemd-units.la \
libsystemd-label.la \
- libsystemd-shared.la
+ libsystemd-shared.la \
+ libsystemd-id128-internal.la
test_watchdog_SOURCES = \
src/test/test-watchdog.c
diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml
index c09b8aa..7c3a6c7 100644
--- a/man/systemd.unit.xml
+++ b/man/systemd.unit.xml
@@ -994,6 +994,10 @@
</varlistentry>
</variablelist>
+ <para>The following specifiers are interpreted in the
+ Install section: %n, %N, %p, %i, %U, %u, %m, %H, %b.
+ For their meaning see the next section.
+ </para>
</refsect1>
<refsect1>
diff --git a/src/core/unit-printf.c b/src/core/unit-printf.c
index 7430beb..7415824 100644
--- a/src/core/unit-printf.c
+++ b/src/core/unit-printf.c
@@ -250,12 +250,13 @@ char *unit_full_printf(Unit *u, const char *format) {
* %r root cgroup path of this systemd instance (e.g. "/user/lennart/shared/systemd-4711")
* %R parent of root cgroup path (e.g. "/usr/lennart/shared")
* %t the runtime directory to place sockets in (e.g. "/run" or $XDG_RUNTIME_DIR)
+ * %U the UID of the configured user or running user
* %u the username of the configured user or running user
* %h the homedir of the configured user or running user
* %s the shell of the configured user or running user
* %m the machine ID of the running system
- * %b the boot ID of the running system
* %H the host name of the running system
+ * %b the boot ID of the running system
*/
const Specifier table[] = {
@@ -282,7 +283,6 @@ char *unit_full_printf(Unit *u, const char *format) {
{ 0, NULL, NULL }
};
- assert(u);
assert(format);
return specifier_printf(format, table, u);
diff --git a/src/shared/install-printf.c b/src/shared/install-printf.c
new file mode 100644
index 0000000..85aebc4
--- /dev/null
+++ b/src/shared/install-printf.c
@@ -0,0 +1,95 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2013 Zbigniew JÄdrzejewski-Szmek
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include "specifier.h"
+#include "unit-name.h"
+#include "install-printf.h"
+
+static char *specifier_prefix_and_instance(char specifier, void *data, void *userdata) {
+ InstallInfo *i = userdata;
+ assert(i);
+
+ return unit_name_to_prefix_and_instance(i->name);
+}
+
+static char *specifier_prefix(char specifier, void *data, void *userdata) {
+ InstallInfo *i = userdata;
+ assert(i);
+
+ return unit_name_to_prefix(i->name);
+}
+
+static char *specifier_instance(char specifier, void *data, void *userdata) {
+ InstallInfo *i = userdata;
+ char *instance;
+ int r;
+
+ assert(i);
+
+ r = unit_name_to_instance(i->name, &instance);
+ if (r < 0)
+ return NULL;
+ if (instance != NULL)
+ return instance;
+ else
+ return strdup("");
+}
+
+char *install_full_printf(InstallInfo *i, const char *format) {
+
+ /* This is similar to unit_full_printf() but does not support
+ * anything path-related.
+ *
+ * %n: the full id of the unit (foo at bar.waldo)
+ * %N: the id of the unit without the suffix (foo at bar)
+ * %p: the prefix (foo)
+ * %i: the instance (bar)
+
+ * %U the UID of the configured user or running user
+ * %u the username of the configured user or running user
+ * %m the machine ID of the running system
+ * %H the host name of the running system
+ * %b the boot ID of the running system
+ */
+
+ const Specifier table[] = {
+ { 'n', specifier_string, i->name },
+ { 'N', specifier_prefix_and_instance, NULL },
+ { 'p', specifier_prefix, NULL },
+ { 'i', specifier_instance, NULL },
+
+// { 'U', specifier_user_name, NULL },
+// { 'u', specifier_user_name, NULL },
+
+ { 'm', specifier_machine_id, NULL },
+ { 'H', specifier_host_name, NULL },
+ { 'b', specifier_boot_id, NULL },
+ { 0, NULL, NULL }
+ };
+
+ assert(i);
+ assert(format);
+
+ return specifier_printf(format, table, i);
+}
diff --git a/src/shared/install-printf.h b/src/shared/install-printf.h
new file mode 100644
index 0000000..46f5294
--- /dev/null
+++ b/src/shared/install-printf.h
@@ -0,0 +1,25 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2013 Zbigniew JÄdrzejewski-Szmek
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#pragma once
+
+#include "install.h"
+char *install_full_printf(InstallInfo *i, const char *format);
diff --git a/src/shared/install.c b/src/shared/install.c
index 24905e1..7fb352c 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -36,15 +36,8 @@
#include "install.h"
#include "conf-parser.h"
#include "conf-files.h"
-
-typedef struct {
- char *name;
- char *path;
-
- char **aliases;
- char **wanted_by;
- char **required_by;
-} InstallInfo;
+#include "specifier.h"
+#include "install-printf.h"
typedef struct {
Hashmap *will_install;
@@ -1177,16 +1170,17 @@ static int install_info_symlink_alias(
assert(config_path);
STRV_FOREACH(s, i->aliases) {
- char *alias_path;
+ char _cleanup_free_ *alias_path = NULL, *dst = NULL;
- alias_path = path_make_absolute(*s, config_path);
+ dst = install_full_printf(i, *s);
+ if (!dst)
+ return -ENOMEM;
+ alias_path = path_make_absolute(dst, config_path);
if (!alias_path)
return -ENOMEM;
q = create_symlink(i->path, alias_path, force, changes, n_changes);
- free(alias_path);
-
if (r == 0)
r = q;
}
@@ -1208,18 +1202,21 @@ static int install_info_symlink_wants(
assert(config_path);
STRV_FOREACH(s, i->wanted_by) {
- char *path;
+ char _cleanup_free_ *path = NULL, *dst = NULL;
- if (!unit_name_is_valid(*s, true)) {
+ dst = install_full_printf(i, *s);
+ if (!dst)
+ return -ENOMEM;
+
+ if (!unit_name_is_valid(dst, true)) {
r = -EINVAL;
continue;
}
- if (asprintf(&path, "%s/%s.wants/%s", config_path, *s, i->name) < 0)
+ if (asprintf(&path, "%s/%s.wants/%s", config_path, dst, i->name) < 0)
return -ENOMEM;
q = create_symlink(i->path, path, force, changes, n_changes);
- free(path);
if (r == 0)
r = q;
@@ -1242,18 +1239,21 @@ static int install_info_symlink_requires(
assert(config_path);
STRV_FOREACH(s, i->required_by) {
- char *path;
+ char _cleanup_free_ *path = NULL, *dst = NULL;
- if (!unit_name_is_valid(*s, true)) {
+ dst = install_full_printf(i, *s);
+ if (!dst)
+ return -ENOMEM;
+
+ if (!unit_name_is_valid(dst, true)) {
r = -EINVAL;
continue;
}
- if (asprintf(&path, "%s/%s.requires/%s", config_path, *s, i->name) < 0)
+ if (asprintf(&path, "%s/%s.requires/%s", config_path, dst, i->name) < 0)
return -ENOMEM;
q = create_symlink(i->path, path, force, changes, n_changes);
- free(path);
if (r == 0)
r = q;
diff --git a/src/shared/install.h b/src/shared/install.h
index 5524991..5a35125 100644
--- a/src/shared/install.h
+++ b/src/shared/install.h
@@ -63,6 +63,15 @@ typedef struct UnitFileList {
UnitFileState state;
} UnitFileList;
+typedef struct {
+ char *name;
+ char *path;
+
+ char **aliases;
+ char **wanted_by;
+ char **required_by;
+} InstallInfo;
+
int unit_file_enable(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes);
int unit_file_disable(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], UnitFileChange **changes, unsigned *n_changes);
int unit_file_reenable(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes);
commit 0591220f339c313761f9a208e88fb719db566993
Author: Zbigniew JÄdrzejewski-Szmek <zbyszek at in.waw.pl>
Date: Tue Jan 29 10:32:39 2013 -0500
core: fix %U when no User= used
When the username was not explicitly specified, both %U and %u would
print the username. Make %U always print UID.
diff --git a/src/core/unit-printf.c b/src/core/unit-printf.c
index 3aa735e..7430beb 100644
--- a/src/core/unit-printf.c
+++ b/src/core/unit-printf.c
@@ -26,6 +26,7 @@
#include "strv.h"
#include "unit-name.h"
#include "unit-printf.h"
+#include "macro.h"
static char *specifier_prefix_and_instance(char specifier, void *data, void *userdata) {
Unit *u = userdata;
@@ -123,6 +124,7 @@ static char *specifier_user_name(char specifier, void *data, void *userdata) {
ExecContext *c;
int r;
const char *username;
+ char _cleanup_free_ *tmp = NULL;
uid_t uid;
char *printed = NULL;
@@ -130,12 +132,13 @@ static char *specifier_user_name(char specifier, void *data, void *userdata) {
c = unit_get_exec_context(u);
- /* get USER env from our own env if set */
- if (!c || !c->user)
- return getusername_malloc();
+ if (c && c->user)
+ username = c->user;
+ else
+ /* get USER env from env or our own uid */
+ username = tmp = getusername_malloc();
/* fish username from passwd */
- username = c->user;
r = get_user_creds(&username, &uid, NULL, NULL, NULL);
if (r < 0)
return NULL;
commit d848b9cbfa0ba72381363accce481600169df2eb
Author: Zbigniew JÄdrzejewski-Szmek <zbyszek at in.waw.pl>
Date: Sun Jan 27 19:44:52 2013 -0500
Move generic specifier functions to shared
No functional change. This makes it possible to use them in install.c.
diff --git a/src/core/unit-printf.c b/src/core/unit-printf.c
index a58c96c..3aa735e 100644
--- a/src/core/unit-printf.c
+++ b/src/core/unit-printf.c
@@ -211,42 +211,6 @@ static char *specifier_user_shell(char specifier, void *data, void *userdata) {
return strdup(shell);
}
-static char *specifier_machine_id(char specifier, void *data, void *userdata) {
- sd_id128_t id;
- char *buf;
- int r;
-
- r = sd_id128_get_machine(&id);
- if (r < 0)
- return NULL;
-
- buf = new(char, 33);
- if (!buf)
- return NULL;
-
- return sd_id128_to_string(id, buf);
-}
-
-static char *specifier_boot_id(char specifier, void *data, void *userdata) {
- sd_id128_t id;
- char *buf;
- int r;
-
- r = sd_id128_get_boot(&id);
- if (r < 0)
- return NULL;
-
- buf = new(char, 33);
- if (!buf)
- return NULL;
-
- return sd_id128_to_string(id, buf);
-}
-
-static char *specifier_host_name(char specifier, void *data, void *userdata) {
- return gethostname_malloc();
-}
-
char *unit_name_printf(Unit *u, const char* format) {
/*
diff --git a/src/shared/specifier.c b/src/shared/specifier.c
index 599027c..7577c91 100644
--- a/src/shared/specifier.c
+++ b/src/shared/specifier.c
@@ -109,3 +109,39 @@ char *specifier_printf(const char *text, const Specifier table[], void *userdata
char* specifier_string(char specifier, void *data, void *userdata) {
return strdup(strempty(data));
}
+
+char *specifier_machine_id(char specifier, void *data, void *userdata) {
+ sd_id128_t id;
+ char *buf;
+ int r;
+
+ r = sd_id128_get_machine(&id);
+ if (r < 0)
+ return NULL;
+
+ buf = new(char, 33);
+ if (!buf)
+ return NULL;
+
+ return sd_id128_to_string(id, buf);
+}
+
+char *specifier_boot_id(char specifier, void *data, void *userdata) {
+ sd_id128_t id;
+ char *buf;
+ int r;
+
+ r = sd_id128_get_boot(&id);
+ if (r < 0)
+ return NULL;
+
+ buf = new(char, 33);
+ if (!buf)
+ return NULL;
+
+ return sd_id128_to_string(id, buf);
+}
+
+char *specifier_host_name(char specifier, void *data, void *userdata) {
+ return gethostname_malloc();
+}
diff --git a/src/shared/specifier.h b/src/shared/specifier.h
index 25a27a4..0440dca 100644
--- a/src/shared/specifier.h
+++ b/src/shared/specifier.h
@@ -31,4 +31,8 @@ typedef struct Specifier {
char *specifier_printf(const char *text, const Specifier table[], void *userdata);
-char* specifier_string(char specifier, void *data, void *userdata);
+char *specifier_string(char specifier, void *data, void *userdata);
+
+char *specifier_machine_id(char specifier, void *data, void *userdata);
+char *specifier_boot_id(char specifier, void *data, void *userdata);
+char *specifier_host_name(char specifier, void *data, void *userdata);
commit d9e5e694ea7841045975426163c96fc9f71e6f7d
Author: Zbigniew JÄdrzejewski-Szmek <zbyszek at in.waw.pl>
Date: Mon Jan 28 20:33:10 2013 -0500
install: automatic cleanup using local cleanup functions
diff --git a/src/shared/install.c b/src/shared/install.c
index d2da0d8..24905e1 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -51,6 +51,11 @@ typedef struct {
Hashmap *have_installed;
} InstallContext;
+#define _cleanup_lookup_paths_free_ \
+ __attribute__((cleanup(lookup_paths_free)))
+#define _cleanup_install_context_done_ \
+ __attribute__((cleanup(install_context_done)))
+
static int lookup_paths_init_from_scope(LookupPaths *paths, UnitFileScope scope) {
assert(paths);
assert(scope >= 0);
@@ -200,7 +205,7 @@ static int remove_marked_symlinks_fd(
char** files) {
int r = 0;
- DIR *d;
+ DIR _cleanup_closedir_ *d = NULL;
assert(remove_symlinks_to);
assert(fd >= 0);
@@ -237,7 +242,7 @@ static int remove_marked_symlinks_fd(
if (de->d_type == DT_DIR) {
int nfd, q;
- char *p;
+ char _cleanup_free_ *p = NULL;
nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
if (nfd < 0) {
@@ -252,32 +257,26 @@ static int remove_marked_symlinks_fd(
p = path_make_absolute(de->d_name, path);
if (!p) {
close_nointr_nofail(nfd);
- r = -ENOMEM;
- break;
+ return -ENOMEM;
}
/* This will close nfd, regardless whether it succeeds or not */
q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, deleted, changes, n_changes, files);
- free(p);
if (r == 0)
r = q;
} else if (de->d_type == DT_LNK) {
- char *p, *dest;
+ char _cleanup_free_ *p = NULL, *dest = NULL;
int q;
bool found;
p = path_make_absolute(de->d_name, path);
- if (!p) {
- r = -ENOMEM;
- break;
- }
+ if (!p)
+ return -ENOMEM;
q = readlink_and_canonicalize(p, &dest);
if (q < 0) {
- free(p);
-
if (q == -ENOENT)
continue;
@@ -316,14 +315,9 @@ static int remove_marked_symlinks_fd(
}
}
}
-
- free(p);
- free(dest);
}
}
- closedir(d);
-
return r;
}
@@ -713,25 +707,25 @@ int unit_file_link(
UnitFileChange **changes,
unsigned *n_changes) {
- LookupPaths paths;
- char **i, *config_path = NULL;
+ LookupPaths _cleanup_lookup_paths_free_ paths = {NULL};
+ char **i;
+ char _cleanup_free_ *config_path = NULL;
int r, q;
assert(scope >= 0);
assert(scope < _UNIT_FILE_SCOPE_MAX);
- zero(paths);
-
r = lookup_paths_init_from_scope(&paths, scope);
if (r < 0)
return r;
r = get_config_path(scope, runtime, root_dir, &config_path);
if (r < 0)
- goto finish;
+ return r;
STRV_FOREACH(i, files) {
- char *path, *fn;
+ char _cleanup_free_ *path = NULL;
+ char *fn;
struct stat st;
fn = path_get_file_name(*i);
@@ -755,48 +749,34 @@ int unit_file_link(
}
q = in_search_path(*i, paths.unit_path);
- if (q < 0) {
- r = q;
- break;
- }
+ if (q < 0)
+ return q;
if (q > 0)
continue;
path = path_make_absolute(fn, config_path);
- if (!path) {
- r = -ENOMEM;
- break;
- }
+ if (!path)
+ return -ENOMEM;
if (symlink(*i, path) >= 0) {
add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
-
- free(path);
continue;
}
if (errno == EEXIST) {
- char *dest = NULL;
+ char _cleanup_free_ *dest = NULL;
q = readlink_and_make_absolute(path, &dest);
if (q < 0 && errno != ENOENT) {
- free(path);
-
if (r == 0)
r = q;
-
continue;
}
- if (q >= 0 && path_equal(dest, *i)) {
- free(dest);
- free(path);
+ if (q >= 0 && path_equal(dest, *i))
continue;
- }
-
- free(dest);
if (force) {
unlink(path);
@@ -806,7 +786,6 @@ int unit_file_link(
add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
- free(path);
continue;
}
}
@@ -817,14 +796,8 @@ int unit_file_link(
if (r == 0)
r = -errno;
}
-
- free(path);
}
- finish:
- lookup_paths_free(&paths);
- free(config_path);
-
return r;
}
@@ -975,7 +948,7 @@ static int config_parse_also(
assert(rvalue);
FOREACH_WORD_QUOTED(w, l, rvalue, state) {
- char *n;
+ char _cleanup_free_ *n;
int r;
n = strndup(w, l);
@@ -983,12 +956,8 @@ static int config_parse_also(
return -ENOMEM;
r = install_info_add(c, n, NULL);
- if (r < 0) {
- free(n);
+ if (r < 0)
return r;
- }
-
- free(n);
}
return 0;
@@ -1009,7 +978,7 @@ static int unit_file_load(
};
int fd;
- FILE *f;
+ FILE _cleanup_fclose_ *f = NULL;
int r;
assert(c);
@@ -1027,7 +996,6 @@ static int unit_file_load(
}
r = config_parse(path, f, NULL, config_item_table_lookup, (void*) items, true, info);
- fclose(f);
if (r < 0)
return r;
@@ -1127,15 +1095,13 @@ static int unit_file_can_install(
const char *name,
bool allow_symlink) {
- InstallContext c;
+ InstallContext _cleanup_install_context_done_ c = {NULL};
InstallInfo *i;
int r;
assert(paths);
assert(name);
- zero(c);
-
r = install_info_add_auto(&c, name);
if (r < 0)
return r;
@@ -1150,8 +1116,6 @@ static int unit_file_can_install(
strv_length(i->wanted_by) +
strv_length(i->required_by);
- install_context_done(&c);
-
return r;
}
@@ -1162,7 +1126,7 @@ static int create_symlink(
UnitFileChange **changes,
unsigned *n_changes) {
- char *dest;
+ char _cleanup_free_ *dest = NULL;
int r;
assert(old_path);
@@ -1182,12 +1146,8 @@ static int create_symlink(
if (r < 0)
return r;
- if (path_equal(dest, old_path)) {
- free(dest);
+ if (path_equal(dest, old_path))
return 0;
- }
-
- free(dest);
if (!force)
return -EEXIST;
@@ -1311,7 +1271,7 @@ static int install_info_symlink_link(
unsigned *n_changes) {
int r;
- char *path;
+ char _cleanup_free_ *path = NULL;
assert(i);
assert(paths);
@@ -1326,8 +1286,6 @@ static int install_info_symlink_link(
return -ENOMEM;
r = create_symlink(i->path, path, force, changes, n_changes);
- free(path);
-
return r;
}
@@ -1466,29 +1424,27 @@ int unit_file_enable(
UnitFileChange **changes,
unsigned *n_changes) {
- LookupPaths paths;
- InstallContext c;
- char **i, *config_path = NULL;
+ LookupPaths _cleanup_lookup_paths_free_ paths = {NULL};
+ InstallContext _cleanup_install_context_done_ c = {NULL};
+ char **i;
+ char _cleanup_free_ *config_path = NULL;
int r;
assert(scope >= 0);
assert(scope < _UNIT_FILE_SCOPE_MAX);
- zero(paths);
- zero(c);
-
r = lookup_paths_init_from_scope(&paths, scope);
if (r < 0)
return r;
r = get_config_path(scope, runtime, root_dir, &config_path);
if (r < 0)
- goto finish;
+ return r;
STRV_FOREACH(i, files) {
r = install_info_add_auto(&c, *i);
if (r < 0)
- goto finish;
+ return r;
}
/* This will return the number of symlink rules that were
@@ -1496,12 +1452,6 @@ int unit_file_enable(
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);
-
-finish:
- install_context_done(&c);
- lookup_paths_free(&paths);
- free(config_path);
-
return r;
}
@@ -1513,30 +1463,28 @@ int unit_file_disable(
UnitFileChange **changes,
unsigned *n_changes) {
- LookupPaths paths;
- InstallContext c;
- char **i, *config_path = NULL;
- Set *remove_symlinks_to = NULL;
+ LookupPaths _cleanup_lookup_paths_free_ paths = {NULL};
+ InstallContext _cleanup_install_context_done_ c = {NULL};
+ char **i;
+ char _cleanup_free_ *config_path = NULL;
+ Set _cleanup_set_free_free_ *remove_symlinks_to = NULL;
int r, q;
assert(scope >= 0);
assert(scope < _UNIT_FILE_SCOPE_MAX);
- zero(paths);
- zero(c);
-
r = lookup_paths_init_from_scope(&paths, scope);
if (r < 0)
return r;
r = get_config_path(scope, runtime, root_dir, &config_path);
if (r < 0)
- goto finish;
+ return r;
STRV_FOREACH(i, files) {
r = install_info_add_auto(&c, *i);
if (r < 0)
- goto finish;
+ return r;
}
r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
@@ -1545,12 +1493,6 @@ int unit_file_disable(
if (r == 0)
r = q;
-finish:
- install_context_done(&c);
- lookup_paths_free(&paths);
- set_free_free(remove_symlinks_to);
- free(config_path);
-
return r;
}
@@ -1563,34 +1505,32 @@ int unit_file_reenable(
UnitFileChange **changes,
unsigned *n_changes) {
- LookupPaths paths;
- InstallContext c;
- char **i, *config_path = NULL;
- Set *remove_symlinks_to = NULL;
+ LookupPaths _cleanup_lookup_paths_free_ paths = {NULL};
+ InstallContext _cleanup_install_context_done_ c = {NULL};
+ char **i;
+ char _cleanup_free_ *config_path = NULL;
+ Set _cleanup_set_free_free_ *remove_symlinks_to = NULL;
int r, q;
assert(scope >= 0);
assert(scope < _UNIT_FILE_SCOPE_MAX);
- zero(paths);
- zero(c);
-
r = lookup_paths_init_from_scope(&paths, scope);
if (r < 0)
return r;
r = get_config_path(scope, runtime, root_dir, &config_path);
if (r < 0)
- goto finish;
+ return r;
STRV_FOREACH(i, files) {
r = mark_symlink_for_removal(&remove_symlinks_to, *i);
if (r < 0)
- goto finish;
+ return r;
r = install_info_add_auto(&c, *i);
if (r < 0)
- goto finish;
+ return r;
}
r = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
@@ -1600,12 +1540,6 @@ int unit_file_reenable(
if (r == 0)
r = q;
-finish:
- lookup_paths_free(&paths);
- install_context_done(&c);
- set_free_free(remove_symlinks_to);
- free(config_path);
-
return r;
}
@@ -1614,17 +1548,16 @@ UnitFileState unit_file_get_state(
const char *root_dir,
const char *name) {
- LookupPaths paths;
+ LookupPaths _cleanup_lookup_paths_free_ paths = {NULL};
UnitFileState state = _UNIT_FILE_STATE_INVALID;
- char **i, *path = NULL;
+ char **i;
+ char _cleanup_free_ *path = NULL;
int r;
assert(scope >= 0);
assert(scope < _UNIT_FILE_SCOPE_MAX);
assert(name);
- zero(paths);
-
if (root_dir && scope != UNIT_FILE_SYSTEM)
return -EINVAL;
@@ -1646,65 +1579,50 @@ UnitFileState unit_file_get_state(
else
asprintf(&path, "%s/%s", *i, name);
- if (!path) {
- r = -ENOMEM;
- goto finish;
- }
+ if (!path)
+ return -ENOMEM;
if (lstat(path, &st) < 0) {
r = -errno;
if (errno == ENOENT)
continue;
- goto finish;
+ return -errno;
}
- if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode)) {
- r = -ENOENT;
- goto finish;
- }
+ if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
+ return -ENOENT;
r = null_or_empty_path(path);
if (r < 0 && r != -ENOENT)
- goto finish;
+ return r;
else if (r > 0) {
state = path_startswith(*i, "/run") ?
UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
- r = 0;
- goto finish;
+ return state;
}
r = find_symlinks_in_scope(scope, root_dir, name, &state);
- if (r < 0) {
- goto finish;
- } else if (r > 0) {
- r = 0;
- goto finish;
- }
+ if (r < 0)
+ return r;
+ else if (r > 0)
+ return state;
r = unit_file_can_install(&paths, root_dir, path, true);
if (r < 0 && errno != -ENOENT)
- goto finish;
- else if (r > 0) {
- state = UNIT_FILE_DISABLED;
- r = 0;
- goto finish;
- } else if (r == 0) {
- state = UNIT_FILE_STATIC;
- r = 0;
- goto finish;
- }
+ return r;
+ else if (r > 0)
+ return UNIT_FILE_DISABLED;
+ else if (r == 0)
+ return UNIT_FILE_STATIC;
}
-finish:
- lookup_paths_free(&paths);
- free(path);
-
return r < 0 ? r : state;
}
int unit_file_query_preset(UnitFileScope scope, const char *name) {
- char **files, **i;
+ char _cleanup_strv_free_ **files = NULL;
+ char **i;
int r;
assert(scope >= 0);
@@ -1733,15 +1651,14 @@ int unit_file_query_preset(UnitFileScope scope, const char *name) {
return r;
STRV_FOREACH(i, files) {
- FILE *f;
+ FILE _cleanup_fclose_ *f;
f = fopen(*i, "re");
if (!f) {
if (errno == ENOENT)
continue;
- r = -errno;
- goto finish;
+ return -errno;
}
for (;;) {
@@ -1761,34 +1678,23 @@ int unit_file_query_preset(UnitFileScope scope, const char *name) {
l += 6;
l += strspn(l, WHITESPACE);
- if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
- r = 1;
- fclose(f);
- goto finish;
- }
+ if (fnmatch(l, name, FNM_NOESCAPE) == 0)
+ return 1;
+
} else if (first_word(l, "disable")) {
l += 7;
l += strspn(l, WHITESPACE);
- if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
- r = 0;
- fclose(f);
- goto finish;
- }
+ if (fnmatch(l, name, FNM_NOESCAPE) == 0)
+ return 0;
+
} else
log_debug("Couldn't parse line '%s'", l);
}
-
- fclose(f);
}
/* Default is "enable" */
- r = 1;
-
-finish:
- strv_free(files);
-
- return r;
+ return 1;
}
int unit_file_preset(
@@ -1800,37 +1706,32 @@ int unit_file_preset(
UnitFileChange **changes,
unsigned *n_changes) {
- LookupPaths paths;
- InstallContext plus, minus;
- char **i, *config_path = NULL;
- Set *remove_symlinks_to = NULL;
+ LookupPaths _cleanup_lookup_paths_free_ paths = {NULL};
+ InstallContext _cleanup_install_context_done_ plus = {NULL}, minus = {NULL};
+ char **i;
+ char _cleanup_free_ *config_path = NULL;
+ Set _cleanup_set_free_free_ *remove_symlinks_to = NULL;
int r, q;
assert(scope >= 0);
assert(scope < _UNIT_FILE_SCOPE_MAX);
- zero(paths);
- zero(plus);
- zero(minus);
-
r = lookup_paths_init_from_scope(&paths, scope);
if (r < 0)
return r;
r = get_config_path(scope, runtime, root_dir, &config_path);
if (r < 0)
- goto finish;
+ return r;
STRV_FOREACH(i, files) {
- if (!unit_name_is_valid(*i, true)) {
- r = -EINVAL;
- goto finish;
- }
+ if (!unit_name_is_valid(*i, true))
+ return -EINVAL;
r = unit_file_query_preset(scope, *i);
if (r < 0)
- goto finish;
+ return r;
if (r)
r = install_info_add_auto(&plus, *i);
@@ -1838,46 +1739,49 @@ int unit_file_preset(
r = install_info_add_auto(&minus, *i);
if (r < 0)
- goto finish;
+ return r;
}
- r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
+ r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to,
+ config_path, root_dir);
- q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
+ q = remove_marked_symlinks(remove_symlinks_to, config_path,
+ changes, n_changes, files);
if (r == 0)
r = q;
/* Returns number of symlinks that where supposed to be installed. */
- q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
+ q = install_context_apply(&plus, &paths, config_path, root_dir, force,
+ changes, n_changes);
if (r == 0)
r = q;
-finish:
- lookup_paths_free(&paths);
- install_context_done(&plus);
- install_context_done(&minus);
- set_free_free(remove_symlinks_to);
- free(config_path);
-
return r;
}
+static void unitfilelist_free(UnitFileList **f) {
+ if (!*f)
+ return;
+
+ free((*f)->path);
+ free(*f);
+}
+
int unit_file_get_list(
UnitFileScope scope,
const char *root_dir,
Hashmap *h) {
- LookupPaths paths;
- char **i, *buf = NULL;
- DIR *d = NULL;
+ LookupPaths _cleanup_lookup_paths_free_ paths = {NULL};
+ char **i;
+ char _cleanup_free_ *buf = NULL;
+ DIR _cleanup_closedir_ *d = NULL;
int r;
assert(scope >= 0);
assert(scope < _UNIT_FILE_SCOPE_MAX);
assert(h);
- zero(paths);
-
if (root_dir && scope != UNIT_FILE_SYSTEM)
return -EINVAL;
@@ -1892,10 +1796,9 @@ int unit_file_get_list(
buf = NULL;
if (root_dir) {
- if (asprintf(&buf, "%s/%s", root_dir, *i) < 0) {
- r = -ENOMEM;
- goto finish;
- }
+ if (asprintf(&buf, "%s/%s", root_dir, *i) < 0)
+ return -ENOMEM;
+
units_dir = buf;
} else
units_dir = *i;
@@ -1908,20 +1811,18 @@ int unit_file_get_list(
if (errno == ENOENT)
continue;
- r = -errno;
- goto finish;
+ return -errno;
}
for (;;) {
struct dirent *de;
union dirent_storage buffer;
- UnitFileList *f;
+ UnitFileList __attribute__((cleanup(unitfilelist_free)))
+ *f = NULL;
r = readdir_r(d, &buffer.de, &de);
- if (r != 0) {
- r = -r;
- goto finish;
- }
+ if (r != 0)
+ return -r;
if (!de)
break;
@@ -1940,31 +1841,24 @@ int unit_file_get_list(
if (r == -ENOENT)
continue;
- goto finish;
+ return r;
}
if (de->d_type != DT_LNK && de->d_type != DT_REG)
continue;
f = new0(UnitFileList, 1);
- if (!f) {
- r = -ENOMEM;
- goto finish;
- }
+ if (!f)
+ return -ENOMEM;
f->path = path_make_absolute(de->d_name, units_dir);
- if (!f->path) {
- free(f);
- r = -ENOMEM;
- goto finish;
- }
+ if (!f->path)
+ return -ENOMEM;
r = null_or_empty_path(f->path);
- if (r < 0 && r != -ENOENT) {
- free(f->path);
- free(f);
- goto finish;
- } else if (r > 0) {
+ if (r < 0 && r != -ENOENT)
+ return r;
+ else if (r > 0) {
f->state =
path_startswith(*i, "/run") ?
UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
@@ -1972,11 +1866,9 @@ int unit_file_get_list(
}
r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
- if (r < 0) {
- free(f->path);
- free(f);
- goto finish;
- } else if (r > 0) {
+ if (r < 0)
+ return r;
+ else if (r > 0) {
f->state = UNIT_FILE_ENABLED;
goto found;
}
@@ -1986,32 +1878,21 @@ int unit_file_get_list(
r == -EBADMSG || /* Invalid format? */
r == -ENOENT /* Included file not found? */)
f->state = UNIT_FILE_INVALID;
- else if (r < 0) {
- free(f->path);
- free(f);
- goto finish;
- } else if (r > 0)
+ else if (r < 0)
+ return r;
+ else if (r > 0)
f->state = UNIT_FILE_DISABLED;
else
f->state = UNIT_FILE_STATIC;
found:
r = hashmap_put(h, path_get_file_name(f->path), f);
- if (r < 0) {
- free(f->path);
- free(f);
- goto finish;
- }
+ if (r < 0)
+ return r;
+ f = NULL; /* prevent cleanup */
}
}
-finish:
- lookup_paths_free(&paths);
- free(buf);
-
- if (d)
- closedir(d);
-
return r;
}
commit ea55addcb7cd31ab46f7be610cd3dc60c3abb52a
Author: Zbigniew JÄdrzejewski-Szmek <zbyszek at in.waw.pl>
Date: Sun Jan 27 15:54:00 2013 -0500
install: use automatic cleanup in find_symlinks_fd()
diff --git a/src/shared/install.c b/src/shared/install.c
index a9d75f3..d2da0d8 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -375,7 +375,7 @@ static int find_symlinks_fd(
bool *same_name_link) {
int r = 0;
- DIR *d;
+ DIR _cleanup_closedir_ *d = NULL;
assert(name);
assert(fd >= 0);
@@ -395,13 +395,11 @@ static int find_symlinks_fd(
union dirent_storage buf;
k = readdir_r(d, &buf.de, &de);
- if (k != 0) {
- r = -errno;
- break;
- }
+ if (k != 0)
+ return -errno;
if (!de)
- break;
+ return r;
if (ignore_file(de->d_name))
continue;
@@ -410,7 +408,7 @@ static int find_symlinks_fd(
if (de->d_type == DT_DIR) {
int nfd, q;
- char *p;
+ char _cleanup_free_ *p = NULL;
nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
if (nfd < 0) {
@@ -425,39 +423,31 @@ static int find_symlinks_fd(
p = path_make_absolute(de->d_name, path);
if (!p) {
close_nointr_nofail(nfd);
- r = -ENOMEM;
- break;
+ return -ENOMEM;
}
/* This will close nfd, regardless whether it succeeds or not */
q = find_symlinks_fd(name, nfd, p, config_path, same_name_link);
- free(p);
- if (q > 0) {
- r = 1;
- break;
- }
+ if (q > 0)
+ return 1;
if (r == 0)
r = q;
} else if (de->d_type == DT_LNK) {
- char *p, *dest;
+ char _cleanup_free_ *p = NULL, *dest = NULL;
bool found_path, found_dest, b = false;
int q;
/* Acquire symlink name */
p = path_make_absolute(de->d_name, path);
- if (!p) {
- r = -ENOMEM;
- break;
- }
+ if (!p)
+ return -ENOMEM;
/* Acquire symlink destination */
q = readlink_and_canonicalize(p, &dest);
if (q < 0) {
- free(p);
-
if (q == -ENOENT)
continue;
@@ -480,37 +470,25 @@ static int find_symlinks_fd(
else
found_dest = streq(path_get_file_name(dest), name);
- free(dest);
-
if (found_path && found_dest) {
- char *t;
+ char _cleanup_free_ *t = NULL;
/* Filter out same name links in the main
* config path */
t = path_make_absolute(name, config_path);
- if (!t) {
- free(p);
- r = -ENOMEM;
- break;
- }
+ if (!t)
+ return -ENOMEM;
b = path_equal(t, p);
- free(t);
}
- free(p);
-
if (b)
*same_name_link = true;
- else if (found_path || found_dest) {
- r = 1;
- break;
- }
+ else if (found_path || found_dest)
+ return 1;
}
}
- closedir(d);
-
return r;
}
commit e3ded78be7df143ba780dd55ca8897fdddd67460
Author: Zbigniew JÄdrzejewski-Szmek <zbyszek at in.waw.pl>
Date: Mon Jan 28 19:36:48 2013 -0500
shared: introduce _cleanup_set_free_free_
diff --git a/src/shared/macro.h b/src/shared/macro.h
index b307ded..0559190 100644
--- a/src/shared/macro.h
+++ b/src/shared/macro.h
@@ -201,6 +201,7 @@ static inline size_t IOVEC_INCREMENT(struct iovec *i, unsigned n, size_t k) {
#define _cleanup_closedir_ __attribute__((cleanup(closedirp)))
#define _cleanup_umask_ __attribute__((cleanup(umaskp)))
#define _cleanup_set_free_ __attribute__((cleanup(set_freep)))
+#define _cleanup_set_free_free_ __attribute__((cleanup(set_free_freep)))
#define _cleanup_strv_free_ __attribute__((cleanup(strv_freep)))
#define VA_FORMAT_ADVANCE(format, ap) \
diff --git a/src/shared/set.c b/src/shared/set.c
index 53399b6..cd910d7 100644
--- a/src/shared/set.c
+++ b/src/shared/set.c
@@ -49,6 +49,14 @@ void set_free_free(Set *s) {
hashmap_free_free(MAKE_HASHMAP(s));
}
+void set_free_freep(Set **s) {
+ if (!*s)
+ return;
+
+ set_free_free(*s);
+ *s = NULL;
+}
+
int set_ensure_allocated(Set **s, hash_func_t hash_func, compare_func_t compare_func) {
return hashmap_ensure_allocated((Hashmap**) s, hash_func, compare_func);
}
diff --git a/src/shared/set.h b/src/shared/set.h
index ed5b5a4..2f79258 100644
--- a/src/shared/set.h
+++ b/src/shared/set.h
@@ -35,6 +35,7 @@ Set *set_new(hash_func_t hash_func, compare_func_t compare_func);
void set_free(Set* s);
void set_freep(Set **s);
void set_free_free(Set *s);
+void set_free_freep(Set **s);
Set* set_copy(Set *s);
int set_ensure_allocated(Set **s, hash_func_t hash_func, compare_func_t compare_func);
More information about the systemd-commits
mailing list