From a4b143cb65ba5767d993a3b041001c1172e2396d Mon Sep 17 00:00:00 2001 From: CentOS Buildsys Date: Nov 19 2013 20:52:42 +0000 Subject: import systemd-207-8.el7.src.rpm --- diff --git a/.systemd.metadata b/.systemd.metadata new file mode 100644 index 0000000..b58f4e8 --- /dev/null +++ b/.systemd.metadata @@ -0,0 +1 @@ +ea1a538bc3d29f7c6f7f0a0aa5c070b9018c5527 SOURCES/systemd-207.tar.xz diff --git a/README.md b/README.md deleted file mode 100644 index 0e7897f..0000000 --- a/README.md +++ /dev/null @@ -1,5 +0,0 @@ -The master branch has no content - -Look at the c7 branch if you are working with CentOS-7, or the c4/c5/c6 branch for CentOS-4, 5 or 6 - -If you find this file in a distro specific branch, it means that no content has been checked in yet diff --git a/SOURCES/0001-RHEL-units-add-Install-section-to-tmp.mount.patch b/SOURCES/0001-RHEL-units-add-Install-section-to-tmp.mount.patch new file mode 100644 index 0000000..d70f7a5 --- /dev/null +++ b/SOURCES/0001-RHEL-units-add-Install-section-to-tmp.mount.patch @@ -0,0 +1,24 @@ +From 2e987a0ac284a1cd1ab4f8e335abcae91c976f15 Mon Sep 17 00:00:00 2001 +From: Michal Schmidt +Date: Fri, 15 Feb 2013 09:07:57 +0100 +Subject: [PATCH] RHEL: units: add [Install] section to tmp.mount + +Related: #908253 +--- + units/tmp.mount | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/units/tmp.mount b/units/tmp.mount +index 99a3ba3..79e1c76 100644 +--- a/units/tmp.mount ++++ b/units/tmp.mount +@@ -18,3 +18,9 @@ What=tmpfs + Where=/tmp + Type=tmpfs + Options=mode=1777,strictatime ++ ++# tmp.mount is statically enabled in upstream. In RHEL tmp-on-tmpfs is not used ++# by default, but there are cases where it is necessary (anaconda, live images, ++# read-only root). Make 'systemctl enable tmp.mount' work: ++[Install] ++WantedBy=local-fs.target diff --git a/SOURCES/0002-kernel-install-add-fedora-specific-callouts-to-new-k.patch b/SOURCES/0002-kernel-install-add-fedora-specific-callouts-to-new-k.patch new file mode 100644 index 0000000..ef90378 --- /dev/null +++ b/SOURCES/0002-kernel-install-add-fedora-specific-callouts-to-new-k.patch @@ -0,0 +1,42 @@ +From b81d902a8ec4e81c6ddda0208307ee77d4e0858b Mon Sep 17 00:00:00 2001 +From: Harald Hoyer +Date: Wed, 13 Mar 2013 07:57:53 +0100 +Subject: [PATCH] kernel-install: add fedora specific callouts to + new-kernel-pkg + +--- + src/kernel-install/kernel-install | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +diff --git a/src/kernel-install/kernel-install b/src/kernel-install/kernel-install +index fb2ee57..f491947 100644 +--- a/src/kernel-install/kernel-install ++++ b/src/kernel-install/kernel-install +@@ -19,6 +19,27 @@ + # You should have received a copy of the GNU Lesser General Public License + # along with systemd; If not, see . + ++if [[ -x /sbin/new-kernel-pkg ]]; then ++ [[ "$2" == *\+* ]] && flavor=-"${2##*+}" ++ case "$1" in ++ add) ++ /sbin/new-kernel-pkg --package "kernel${flavor}" --install "$2" || exit $? ++ /sbin/new-kernel-pkg --package "kernel${flavor}" --mkinitrd --dracut --depmod --update "$2" || exit $? ++ /sbin/new-kernel-pkg --package "kernel${flavor}" --rpmposttrans "$2" || exit $? ++ ;; ++ remove) ++ /sbin/new-kernel-pkg --package "kernel${flavor+-$flavor}" --rminitrd --rmmoddep --remove "$2" || exit $? ++ ;; ++ *) ++ ;; ++ esac ++ ++ # exit, if we can't find a boot loader spec conforming setup ++ if ! [[ -d /boot/loader/entries || -L /boot/loader/entries ]]; then ++ exit 0 ++ fi ++fi ++ + usage() + { + echo "Usage:" >&2 diff --git a/SOURCES/0003-core-cgroup-first-print-then-free.patch b/SOURCES/0003-core-cgroup-first-print-then-free.patch new file mode 100644 index 0000000..dc4eecf --- /dev/null +++ b/SOURCES/0003-core-cgroup-first-print-then-free.patch @@ -0,0 +1,23 @@ +From 89ad78921a404dc82f22862f2354707199ea1616 Mon Sep 17 00:00:00 2001 +From: Lukas Nykryn +Date: Fri, 13 Sep 2013 14:31:17 +0200 +Subject: [PATCH] core/cgroup: first print then free + +--- + src/core/cgroup.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/core/cgroup.c b/src/core/cgroup.c +index 3eeb475..513450a 100644 +--- a/src/core/cgroup.c ++++ b/src/core/cgroup.c +@@ -395,8 +395,8 @@ static int unit_create_cgroups(Unit *u, CGroupControllerMask mask) { + is_in_hash = true; + + if (r < 0) { +- free(path); + log_error("cgroup %s exists already: %s", path, strerror(-r)); ++ free(path); + return r; + } + diff --git a/SOURCES/0004-swap-fix-reverse-dependencies.patch b/SOURCES/0004-swap-fix-reverse-dependencies.patch new file mode 100644 index 0000000..63674d1 --- /dev/null +++ b/SOURCES/0004-swap-fix-reverse-dependencies.patch @@ -0,0 +1,27 @@ +From 0f84fab56d31f53b2970bdee64e254c4518618a7 Mon Sep 17 00:00:00 2001 +From: Tom Gundersen +Date: Fri, 13 Sep 2013 14:46:18 +0200 +Subject: [PATCH] swap: fix reverse dependencies + +Make sure swap.target correctly requires/wants the swap units. + +This fixes https://bugs.freedesktop.org/show_bug.cgi?id=69291. + +Reported-by: Hussam Al-Tayeb +--- + src/core/swap.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/core/swap.c b/src/core/swap.c +index 57d15eb..3950860 100644 +--- a/src/core/swap.c ++++ b/src/core/swap.c +@@ -220,7 +220,7 @@ static int swap_add_default_dependencies(Swap *s) { + } + + if (!noauto) { +- r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, (nofail ? UNIT_WANTED_BY : UNIT_REQUIRED_BY), ++ r = unit_add_two_dependencies_by_name_inverse(UNIT(s), UNIT_AFTER, (nofail ? UNIT_WANTS : UNIT_REQUIRES), + SPECIAL_SWAP_TARGET, NULL, true); + if (r < 0) + return r; diff --git a/SOURCES/0005-update-TODO.patch b/SOURCES/0005-update-TODO.patch new file mode 100644 index 0000000..911db49 --- /dev/null +++ b/SOURCES/0005-update-TODO.patch @@ -0,0 +1,22 @@ +From d0746c1d17407a17c18f26876d9ca0f6f20b29b0 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Fri, 13 Sep 2013 04:13:47 +0200 +Subject: [PATCH] update TODO + +--- + TODO | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/TODO b/TODO +index 08d4914..5354692 100644 +--- a/TODO ++++ b/TODO +@@ -58,6 +58,8 @@ CGroup Rework Completion: + + Features: + ++* Move backlight and random-seed into /var/lib/systemd ++ + * When a Type=forking service fails and needed another service that + service is not cleaned up again when it has StopWhenUnneeded=yes + http://lists.freedesktop.org/archives/systemd-devel/2013-July/012141.html diff --git a/SOURCES/0006-cryptsetup-generator-don-t-create-tmp-swap-units.patch b/SOURCES/0006-cryptsetup-generator-don-t-create-tmp-swap-units.patch new file mode 100644 index 0000000..2d242c5 --- /dev/null +++ b/SOURCES/0006-cryptsetup-generator-don-t-create-tmp-swap-units.patch @@ -0,0 +1,50 @@ +From d12ed80037b482f7da136abbd7abce9c9219ef8e Mon Sep 17 00:00:00 2001 +From: Tom Gundersen +Date: Thu, 15 Aug 2013 08:47:59 +0800 +Subject: [PATCH] cryptsetup-generator: don't create tmp+swap units + +--- + src/cryptsetup/cryptsetup-generator.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c +index 81b7708..967c5e6 100644 +--- a/src/cryptsetup/cryptsetup-generator.c ++++ b/src/cryptsetup/cryptsetup-generator.c +@@ -72,13 +72,20 @@ static int create_disk( + + _cleanup_free_ char *p = NULL, *n = NULL, *d = NULL, *u = NULL, *from = NULL, *to = NULL, *e = NULL; + _cleanup_fclose_ FILE *f = NULL; +- bool noauto, nofail; ++ bool noauto, nofail, tmp, swap; + + assert(name); + assert(device); + + noauto = has_option(options, "noauto"); + nofail = has_option(options, "nofail"); ++ tmp = has_option(options, "tmp"); ++ swap = has_option(options, "swap"); ++ ++ if (tmp && swap) { ++ log_error("Device '%s' cannot be both 'tmp' and 'swap'. Ignoring.", name); ++ return -EINVAL; ++ } + + n = unit_name_from_path_instance("systemd-cryptsetup", name, ".service"); + if (!n) +@@ -151,12 +158,12 @@ static int create_disk( + name, u, strempty(password), strempty(options), + name); + +- if (has_option(options, "tmp")) ++ if (tmp) + fprintf(f, + "ExecStartPost=/sbin/mke2fs '/dev/mapper/%s'\n", + name); + +- if (has_option(options, "swap")) ++ if (swap) + fprintf(f, + "ExecStartPost=/sbin/mkswap '/dev/mapper/%s'\n", + name); diff --git a/SOURCES/0007-cryptsetup-generator-allow-specifying-options-in-pro.patch b/SOURCES/0007-cryptsetup-generator-allow-specifying-options-in-pro.patch new file mode 100644 index 0000000..98f140e --- /dev/null +++ b/SOURCES/0007-cryptsetup-generator-allow-specifying-options-in-pro.patch @@ -0,0 +1,185 @@ +From 61ca2800f3a1666478bdc01fc796d36c917a5032 Mon Sep 17 00:00:00 2001 +From: Tom Gundersen +Date: Sun, 18 Aug 2013 14:59:00 +0800 +Subject: [PATCH] cryptsetup-generator: allow specifying options in + /proc/cmdline +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The main usecase for this is to make it possible to use cryptsetup in +the initrd without it having to include a host-specific /etc/crypttab. + +Tested-by: Thomas Bächler +--- + man/systemd-cryptsetup-generator.xml | 23 ++++++++++ + src/cryptsetup/cryptsetup-generator.c | 79 +++++++++++++++++++++++++++++++++-- + 2 files changed, 98 insertions(+), 4 deletions(-) + +diff --git a/man/systemd-cryptsetup-generator.xml b/man/systemd-cryptsetup-generator.xml +index 215ac2d..d6b7e49 100644 +--- a/man/systemd-cryptsetup-generator.xml ++++ b/man/systemd-cryptsetup-generator.xml +@@ -137,6 +137,29 @@ + will be activated in the initrd or the real root. + + ++ ++ ++ luks.options= ++ rd.luks.options= ++ ++ Takes a LUKS super ++ block UUID followed by an '=' and a string ++ of options separated by commas as argument. ++ This will override the options for the given ++ UUID. ++ If only a list of options, without an ++ UUID, is specified, they apply to any UUIDs not ++ specified elsewhere, and without an entry in ++ /etc/crypttab. ++ rd.luks.options= ++ is honored only by initial RAM disk ++ (initrd) while ++ luks.options= is ++ honored by both the main system and ++ the initrd. ++ ++ ++ + + luks.key= + rd.luks.key= +diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c +index 967c5e6..ba6efa6 100644 +--- a/src/cryptsetup/cryptsetup-generator.c ++++ b/src/cryptsetup/cryptsetup-generator.c +@@ -240,7 +240,7 @@ static int create_disk( + return 0; + } + +-static int parse_proc_cmdline(char ***arg_proc_cmdline_disks, char **arg_proc_cmdline_keyfile) { ++static int parse_proc_cmdline(char ***arg_proc_cmdline_disks, char ***arg_proc_cmdline_options, char **arg_proc_cmdline_keyfile) { + _cleanup_free_ char *line = NULL; + char *w = NULL, *state = NULL; + int r; +@@ -307,7 +307,20 @@ static int parse_proc_cmdline(char ***arg_proc_cmdline_disks, char **arg_proc_cm + return log_oom(); + } + ++ } else if (startswith(word, "luks.options=")) { ++ if (strv_extend(arg_proc_cmdline_options, word + 13) < 0) ++ return log_oom(); ++ ++ } else if (startswith(word, "rd.luks.options=")) { ++ ++ if (in_initrd()) { ++ if (strv_extend(arg_proc_cmdline_options, word + 16) < 0) ++ return log_oom(); ++ } ++ + } else if (startswith(word, "luks.key=")) { ++ if (*arg_proc_cmdline_keyfile) ++ free(*arg_proc_cmdline_keyfile); + *arg_proc_cmdline_keyfile = strdup(word + 9); + if (!*arg_proc_cmdline_keyfile) + return log_oom(); +@@ -337,6 +350,7 @@ static int parse_proc_cmdline(char ***arg_proc_cmdline_disks, char **arg_proc_cm + int main(int argc, char *argv[]) { + _cleanup_strv_free_ char **arg_proc_cmdline_disks_done = NULL; + _cleanup_strv_free_ char **arg_proc_cmdline_disks = NULL; ++ _cleanup_strv_free_ char **arg_proc_cmdline_options = NULL; + _cleanup_free_ char *arg_proc_cmdline_keyfile = NULL; + _cleanup_fclose_ FILE *f = NULL; + unsigned n = 0; +@@ -357,7 +371,7 @@ int main(int argc, char *argv[]) { + + umask(0022); + +- if (parse_proc_cmdline(&arg_proc_cmdline_disks, &arg_proc_cmdline_keyfile) < 0) ++ if (parse_proc_cmdline(&arg_proc_cmdline_disks, &arg_proc_cmdline_options, &arg_proc_cmdline_keyfile) < 0) + return EXIT_FAILURE; + + if (!arg_enabled) +@@ -412,6 +426,26 @@ int main(int argc, char *argv[]) { + continue; + } + ++ if (arg_proc_cmdline_options) { ++ /* ++ If options are specified on the kernel commandline, let them override ++ the ones from crypttab. ++ */ ++ STRV_FOREACH(i, arg_proc_cmdline_options) { ++ _cleanup_free_ char *proc_uuid = NULL, *proc_options = NULL; ++ const char *p = *i; ++ ++ k = sscanf(p, "%m[0-9a-fA-F-]=%ms", &proc_uuid, &proc_options); ++ if (k == 2 && streq(proc_uuid, device + 5)) { ++ if (options) ++ free(options); ++ options = strdup(p); ++ if (!proc_options) ++ return log_oom(); ++ } ++ } ++ } ++ + if (arg_proc_cmdline_disks) { + /* + If luks UUIDs are specified on the kernel command line, use them as a filter +@@ -452,7 +486,7 @@ next: + on the kernel command line and not yet written. + */ + +- _cleanup_free_ char *name = NULL, *device = NULL; ++ _cleanup_free_ char *name = NULL, *device = NULL, *options = NULL; + const char *p = *i; + + if (startswith(p, "luks-")) +@@ -467,7 +501,44 @@ next: + if (!name || !device) + return log_oom(); + +- if (create_disk(name, device, arg_proc_cmdline_keyfile, "timeout=0") < 0) ++ if (arg_proc_cmdline_options) { ++ /* ++ If options are specified on the kernel commandline, use them. ++ */ ++ char **j; ++ ++ STRV_FOREACH(j, arg_proc_cmdline_options) { ++ _cleanup_free_ char *proc_uuid = NULL, *proc_options = NULL; ++ const char *s = *j; ++ int k; ++ ++ k = sscanf(s, "%m[0-9a-fA-F-]=%ms", &proc_uuid, &proc_options); ++ if (k == 2) { ++ if (streq(proc_uuid, device + 5)) { ++ if (options) ++ free(options); ++ options = strdup(proc_options); ++ if (!options) ++ return log_oom(); ++ } ++ } else if (!options) { ++ /* ++ Fall back to options without a specified UUID ++ */ ++ options = strdup(s); ++ if (!options) ++ return log_oom(); ++ } ++ } ++ } ++ ++ if (!options) { ++ options = strdup("timeout=0"); ++ if (!options) ++ return log_oom(); ++ } ++ ++ if (create_disk(name, device, arg_proc_cmdline_keyfile, options) < 0) + r = EXIT_FAILURE; + } + diff --git a/SOURCES/0008-automount-rename-repeat_unmont-to-repeat_unmount.patch b/SOURCES/0008-automount-rename-repeat_unmont-to-repeat_unmount.patch new file mode 100644 index 0000000..7541077 --- /dev/null +++ b/SOURCES/0008-automount-rename-repeat_unmont-to-repeat_unmount.patch @@ -0,0 +1,41 @@ +From 091169fa11a366ab42fb6f71c22e8ed95868f804 Mon Sep 17 00:00:00 2001 +From: David Mackey +Date: Thu, 12 Sep 2013 19:45:49 -0700 +Subject: [PATCH] automount: rename repeat_unmont to repeat_unmount + +Trivial cleanup of repeat_unmount() spelling. +--- + src/core/automount.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/core/automount.c b/src/core/automount.c +index a20d534..6762392 100644 +--- a/src/core/automount.c ++++ b/src/core/automount.c +@@ -66,7 +66,7 @@ static void automount_init(Unit *u) { + UNIT(a)->ignore_on_isolate = true; + } + +-static void repeat_unmout(const char *path) { ++static void repeat_unmount(const char *path) { + assert(path); + + for (;;) { +@@ -100,7 +100,7 @@ static void unmount_autofs(Automount *a) { + if (a->where && + (UNIT(a)->manager->exit_code != MANAGER_RELOAD && + UNIT(a)->manager->exit_code != MANAGER_REEXECUTE)) +- repeat_unmout(a->where); ++ repeat_unmount(a->where); + } + + static void automount_done(Unit *u) { +@@ -575,7 +575,7 @@ fail: + close_nointr_nofail(ioctl_fd); + + if (mounted) +- repeat_unmout(a->where); ++ repeat_unmount(a->where); + + log_error_unit(UNIT(a)->id, + "Failed to initialize automounter: %s", strerror(-r)); diff --git a/SOURCES/0009-cgroup-add-the-missing-setting-of-variable-s-value.patch b/SOURCES/0009-cgroup-add-the-missing-setting-of-variable-s-value.patch new file mode 100644 index 0000000..2b0aafe --- /dev/null +++ b/SOURCES/0009-cgroup-add-the-missing-setting-of-variable-s-value.patch @@ -0,0 +1,24 @@ +From 8799f0a37ef24fe2709b6e7fdb4ca2c1c9586718 Mon Sep 17 00:00:00 2001 +From: Gao feng +Date: Fri, 13 Sep 2013 11:17:05 +0800 +Subject: [PATCH] cgroup: add the missing setting of variable's value + +set the value of variable "r" to the return value +of cg_set_attribute. +--- + src/core/cgroup.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/core/cgroup.c b/src/core/cgroup.c +index 513450a..9804227 100644 +--- a/src/core/cgroup.c ++++ b/src/core/cgroup.c +@@ -264,7 +264,7 @@ void cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const cha + log_error("Failed to set memory.limit_in_bytes on %s: %s", path, strerror(-r)); + + sprintf(buf, "%" PRIu64 "\n", c->memory_soft_limit); +- cg_set_attribute("memory", path, "memory.soft_limit_in_bytes", buf); ++ r = cg_set_attribute("memory", path, "memory.soft_limit_in_bytes", buf); + if (r < 0) + log_error("Failed to set memory.limit_in_bytes on %s: %s", path, strerror(-r)); + } diff --git a/SOURCES/0010-cgroup-correct-the-log-information.patch b/SOURCES/0010-cgroup-correct-the-log-information.patch new file mode 100644 index 0000000..2b7839b --- /dev/null +++ b/SOURCES/0010-cgroup-correct-the-log-information.patch @@ -0,0 +1,23 @@ +From 9b69c0d07b0db38c181e35e52bcea0eb0dd21818 Mon Sep 17 00:00:00 2001 +From: Gao feng +Date: Fri, 13 Sep 2013 11:17:06 +0800 +Subject: [PATCH] cgroup: correct the log information + +it should be memory.soft_limit_in_bytes. +--- + src/core/cgroup.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/core/cgroup.c b/src/core/cgroup.c +index 9804227..08cb64b 100644 +--- a/src/core/cgroup.c ++++ b/src/core/cgroup.c +@@ -266,7 +266,7 @@ void cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const cha + sprintf(buf, "%" PRIu64 "\n", c->memory_soft_limit); + r = cg_set_attribute("memory", path, "memory.soft_limit_in_bytes", buf); + if (r < 0) +- log_error("Failed to set memory.limit_in_bytes on %s: %s", path, strerror(-r)); ++ log_error("Failed to set memory.soft_limit_in_bytes on %s: %s", path, strerror(-r)); + } + + if (mask & CGROUP_DEVICE) { diff --git a/SOURCES/0011-cgroup-fix-incorrectly-setting-memory-cgroup.patch b/SOURCES/0011-cgroup-fix-incorrectly-setting-memory-cgroup.patch new file mode 100644 index 0000000..3f8b175 --- /dev/null +++ b/SOURCES/0011-cgroup-fix-incorrectly-setting-memory-cgroup.patch @@ -0,0 +1,43 @@ +From c7e5130d5b3983986bfe95918c75e083fa90dd47 Mon Sep 17 00:00:00 2001 +From: Gao feng +Date: Fri, 13 Sep 2013 14:43:04 +0800 +Subject: [PATCH] cgroup: fix incorrectly setting memory cgroup + +If the memory_limit of unit is -1, we should write "-1" +to the file memory.limit_in_bytes. not the (unit64_t) -1. + +otherwise the memory.limit_in_bytes will be set to zero. +--- + src/core/cgroup.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +diff --git a/src/core/cgroup.c b/src/core/cgroup.c +index 08cb64b..1f41efc 100644 +--- a/src/core/cgroup.c ++++ b/src/core/cgroup.c +@@ -257,14 +257,21 @@ void cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const cha + + if (mask & CGROUP_MEMORY) { + char buf[DECIMAL_STR_MAX(uint64_t) + 1]; ++ if (c->memory_limit != (uint64_t) -1) { ++ sprintf(buf, "%" PRIu64 "\n", c->memory_limit); ++ r = cg_set_attribute("memory", path, "memory.limit_in_bytes", buf); ++ } else ++ r = cg_set_attribute("memory", path, "memory.limit_in_bytes", "-1"); + +- sprintf(buf, "%" PRIu64 "\n", c->memory_limit); +- r = cg_set_attribute("memory", path, "memory.limit_in_bytes", buf); + if (r < 0) + log_error("Failed to set memory.limit_in_bytes on %s: %s", path, strerror(-r)); + +- sprintf(buf, "%" PRIu64 "\n", c->memory_soft_limit); +- r = cg_set_attribute("memory", path, "memory.soft_limit_in_bytes", buf); ++ if (c->memory_soft_limit != (uint64_t) -1) { ++ sprintf(buf, "%" PRIu64 "\n", c->memory_soft_limit); ++ r = cg_set_attribute("memory", path, "memory.soft_limit_in_bytes", buf); ++ } else ++ r = cg_set_attribute("memory", path, "memory.soft_limit_in_bytes", "-1"); ++ + if (r < 0) + log_error("Failed to set memory.soft_limit_in_bytes on %s: %s", path, strerror(-r)); + } diff --git a/SOURCES/0012-random-seed-we-should-return-errno-of-failed-loop_wr.patch b/SOURCES/0012-random-seed-we-should-return-errno-of-failed-loop_wr.patch new file mode 100644 index 0000000..31317ef --- /dev/null +++ b/SOURCES/0012-random-seed-we-should-return-errno-of-failed-loop_wr.patch @@ -0,0 +1,22 @@ +From 198884f22dc432a98e3d4423434b9e97d67f2da8 Mon Sep 17 00:00:00 2001 +From: Lukas Nykryn +Date: Fri, 13 Sep 2013 14:12:55 +0200 +Subject: [PATCH] random-seed: we should return errno of failed loop_write + +--- + src/random-seed/random-seed.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/random-seed/random-seed.c b/src/random-seed/random-seed.c +index 4776c07..afbd500 100644 +--- a/src/random-seed/random-seed.c ++++ b/src/random-seed/random-seed.c +@@ -157,7 +157,7 @@ int main(int argc, char *argv[]) { + r = loop_write(seed_fd, buf, (size_t) k, false); + if (r <= 0) { + log_error("Failed to write new random seed file: %s", r < 0 ? strerror(-r) : "short write"); +- r = k == 0 ? -EIO : (int) k; ++ r = r == 0 ? -EIO : r; + } + } + diff --git a/SOURCES/0013-update-TODO.patch b/SOURCES/0013-update-TODO.patch new file mode 100644 index 0000000..53c15ec --- /dev/null +++ b/SOURCES/0013-update-TODO.patch @@ -0,0 +1,24 @@ +From f11f72532fd9a05149714229cb7559b8e3fa802a Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Fri, 13 Sep 2013 14:28:17 +0200 +Subject: [PATCH] update TODO + +--- + TODO | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/TODO b/TODO +index 5354692..9943b3e 100644 +--- a/TODO ++++ b/TODO +@@ -60,6 +60,10 @@ Features: + + * Move backlight and random-seed into /var/lib/systemd + ++* If we try to find a unit via a danglign symlink generate a clean ++ error. Currently we just ignore it and read the unit from the search ++ path anyway. ++ + * When a Type=forking service fails and needed another service that + service is not cleaned up again when it has StopWhenUnneeded=yes + http://lists.freedesktop.org/archives/systemd-devel/2013-July/012141.html diff --git a/SOURCES/0014-libudev-fix-move_later-comparison.patch b/SOURCES/0014-libudev-fix-move_later-comparison.patch new file mode 100644 index 0000000..4301b0c --- /dev/null +++ b/SOURCES/0014-libudev-fix-move_later-comparison.patch @@ -0,0 +1,24 @@ +From 3b93bf5a35b0bb7111754fbae75e7654b775506d Mon Sep 17 00:00:00 2001 +From: Lukas Nykryn +Date: Fri, 13 Sep 2013 14:12:54 +0200 +Subject: [PATCH] libudev: fix move_later comparison + +At the beginning move_later is set to -1, but it is set to different +value only if expression !move_later is true. +--- + src/libudev/libudev-enumerate.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/libudev/libudev-enumerate.c b/src/libudev/libudev-enumerate.c +index bc1e37d..8146f27 100644 +--- a/src/libudev/libudev-enumerate.c ++++ b/src/libudev/libudev-enumerate.c +@@ -300,7 +300,7 @@ _public_ struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enume + /* skip to be delayed devices, and move the to + * the point where the prefix changes. We can + * only move one item at a time. */ +- if (!move_later) { ++ if (move_later == -1) { + move_later_prefix = devices_delay_later(udev_enumerate->udev, entry->syspath); + + if (move_later_prefix > 0) { diff --git a/SOURCES/0015-man-document-luks.options-kernel-commandline.patch b/SOURCES/0015-man-document-luks.options-kernel-commandline.patch new file mode 100644 index 0000000..542a589 --- /dev/null +++ b/SOURCES/0015-man-document-luks.options-kernel-commandline.patch @@ -0,0 +1,23 @@ +From 583f4eb5d443bc09502d6973f08755173db43fd8 Mon Sep 17 00:00:00 2001 +From: Tom Gundersen +Date: Fri, 13 Sep 2013 21:03:55 +0200 +Subject: [PATCH] man: document luks.options kernel commandline + +This should have been part of commit 7ab064a6d +--- + man/kernel-command-line.xml | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/man/kernel-command-line.xml b/man/kernel-command-line.xml +index a4b7d13..cc267a3 100644 +--- a/man/kernel-command-line.xml ++++ b/man/kernel-command-line.xml +@@ -250,6 +250,8 @@ + rd.luks.crypttab= + luks.uuid= + rd.luks.uuid= ++ luks.options= ++ rd.luks.options= + luks.key= + rd.luks.key= + diff --git a/SOURCES/0016-keymap-remove-some-commented-out-lines.patch b/SOURCES/0016-keymap-remove-some-commented-out-lines.patch new file mode 100644 index 0000000..0a5896d --- /dev/null +++ b/SOURCES/0016-keymap-remove-some-commented-out-lines.patch @@ -0,0 +1,33 @@ +From f559cb147ae336f62a9020fa909b70ea90e43886 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Wed, 28 Aug 2013 17:23:59 -0400 +Subject: [PATCH] keymap: remove some commented out lines + +--- + hwdb/60-keyboard.hwdb | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/hwdb/60-keyboard.hwdb b/hwdb/60-keyboard.hwdb +index eca3f55..53e83ad 100644 +--- a/hwdb/60-keyboard.hwdb ++++ b/hwdb/60-keyboard.hwdb +@@ -894,11 +894,6 @@ keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*200E[45]*:pvr* + # Series 5 + keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*700Z*:pvr* + KEYBOARD_KEY_ce=!prog1 # Fn+F1 launch settings +-#KEYBOARD_KEY_89=!brightnessdown # Fn+F2 +-#KEYBOARD_KEY_88=!brightnessup # Fn+F3 +-#KEYBOARD_KEY_82=!switchvideomode # Fn+F4 video output +-#KEYBOARD_KEY_f9=!f23 # Fn+F5 touchpad turn OFF +-#KEYBOARD_KEY_f7=!f22 # Fn+F5 touchpad turn ON + KEYBOARD_KEY_a0=!mute # Fn+F6 mute + KEYBOARD_KEY_ae=!volumedown # Fn+F7 + KEYBOARD_KEY_b0=!volumeup # Fn+F8 +@@ -906,7 +901,6 @@ keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*700Z*:pvr* + KEYBOARD_KEY_96=!kbdillumup # Fn+F10 keyboard backlight up + KEYBOARD_KEY_b3=!prog3 # Fn+F11 fan/cooling mode changer + KEYBOARD_KEY_d5=!wlan # Fn+F12 wlan/airplane switch +-# KEYBOARD_KEY_ba=!ejectcd # Fn+DEL eject cd + + # Series 9 + keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*90X3A*:pvr* diff --git a/SOURCES/0017-Advertise-hibernation-only-if-there-s-enough-free-sw.patch b/SOURCES/0017-Advertise-hibernation-only-if-there-s-enough-free-sw.patch new file mode 100644 index 0000000..3ce4abf --- /dev/null +++ b/SOURCES/0017-Advertise-hibernation-only-if-there-s-enough-free-sw.patch @@ -0,0 +1,259 @@ +From 3559039a97e1d3e28dd9b38202d3499652a58036 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Fri, 13 Sep 2013 19:41:52 -0400 +Subject: [PATCH] Advertise hibernation only if there's enough free swap + +Condition that is checked is taken from upower: + active(anon) < free swap * 0.98 + +This is really stupid, because the kernel knows the situation better, +e.g. there could be two swap files, and then hibernation would be +impossible despite passing this check, or the kernel could start +supporting compressed swap and/or compressed hibernation images, and +then this this check would be too stringent. Nevertheless, until +we have something better, this should at least return a true negative +if there's no swap. + +Logging of capabilities in the journal is changed to not strip leading +zeros. I consider this more readable anyway. + +http://cgit.freedesktop.org/upower/tree/src/up-daemon.c#n613 +https://bugzilla.redhat.com/show_bug.cgi?id=1007059 +--- + src/shared/fileio.c | 34 ++++++++++++++++++++++++++++++++++ + src/shared/fileio.h | 2 ++ + src/shared/logs-show.c | 2 +- + src/shared/sleep-config.c | 45 ++++++++++++++++++++++++++++++++++++++++++++- + src/shared/util.c | 23 +---------------------- + src/test/test-fileio.c | 20 ++++++++++++++++++++ + src/test/test-sleep.c | 16 ++++++++-------- + 7 files changed, 110 insertions(+), 32 deletions(-) + +diff --git a/src/shared/fileio.c b/src/shared/fileio.c +index 77fd059..4e2b444 100644 +--- a/src/shared/fileio.c ++++ b/src/shared/fileio.c +@@ -648,3 +648,37 @@ int executable_is_script(const char *path, char **interpreter) { + *interpreter = ans; + return 1; + } ++ ++/** ++ * Retrieve one field from a file like /proc/self/status. ++ * pattern should start with '\n' and end with ':'. Whitespace ++ * after ':' will be skipped. field must be freed afterwards. ++ */ ++int get_status_field(const char *filename, const char *pattern, char **field) { ++ _cleanup_free_ char *status = NULL; ++ char *t; ++ size_t len; ++ int r; ++ ++ assert(filename); ++ assert(field); ++ ++ r = read_full_file(filename, &status, NULL); ++ if (r < 0) ++ return r; ++ ++ t = strstr(status, pattern); ++ if (!t) ++ return -ENOENT; ++ ++ t += strlen(pattern); ++ t += strspn(t, WHITESPACE); ++ ++ len = strcspn(t, WHITESPACE); ++ ++ *field = strndup(t, len); ++ if (!*field) ++ return -ENOMEM; ++ ++ return 0; ++} +diff --git a/src/shared/fileio.h b/src/shared/fileio.h +index a0aae28..59e4150 100644 +--- a/src/shared/fileio.h ++++ b/src/shared/fileio.h +@@ -37,3 +37,5 @@ int load_env_file(const char *fname, const char *separator, char ***l); + int write_env_file(const char *fname, char **l); + + int executable_is_script(const char *path, char **interpreter); ++ ++int get_status_field(const char *filename, const char *pattern, char **field); +diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c +index 87633e7..f50777c 100644 +--- a/src/shared/logs-show.c ++++ b/src/shared/logs-show.c +@@ -201,7 +201,7 @@ static int output_short( + assert(j); + + /* Set the threshold to one bigger than the actual print +- * treshold, so that if the line is actually longer than what ++ * threshold, so that if the line is actually longer than what + * we're willing to print, ellipsization will occur. This way + * we won't output a misleading line without any indication of + * truncation. +diff --git a/src/shared/sleep-config.c b/src/shared/sleep-config.c +index cd3238b..5ec7cce 100644 +--- a/src/shared/sleep-config.c ++++ b/src/shared/sleep-config.c +@@ -163,6 +163,46 @@ int can_sleep_disk(char **types) { + return false; + } + ++#define HIBERNATION_SWAP_THRESHOLD 0.98 ++ ++static bool enough_memory_for_hibernation(void) { ++ _cleanup_free_ char *active = NULL, *swapfree = NULL; ++ unsigned long long act, swap; ++ int r; ++ ++ r = get_status_field("/proc/meminfo", "\nSwapFree:", &swapfree); ++ if (r < 0) { ++ log_error("Failed to retrieve SwapFree from /proc/meminfo: %s", strerror(-r)); ++ return false; ++ } ++ ++ r = safe_atollu(swapfree, &swap); ++ if (r < 0) { ++ log_error("Failed to parse SwapFree from /proc/meminfo: %s: %s", ++ swapfree, strerror(-r)); ++ return false; ++ } ++ ++ r = get_status_field("/proc/meminfo", "\nActive(anon):", &active); ++ if (r < 0) { ++ log_error("Failed to retrieve Active(anon) from /proc/meminfo: %s", strerror(-r)); ++ return false; ++ } ++ ++ r = safe_atollu(active, &act); ++ if (r < 0) { ++ log_error("Failed to parse Active(anon) from /proc/meminfo: %s: %s", ++ active, strerror(-r)); ++ return false; ++ } ++ ++ r = act <= swap * HIBERNATION_SWAP_THRESHOLD; ++ log_debug("Hibernation is %spossible, Active(anon)=%llu kB, SwapFree=%llu kB, threshold=%.2g%%", ++ r ? "" : "im", act, swap, 100*HIBERNATION_SWAP_THRESHOLD); ++ ++ return r; ++} ++ + int can_sleep(const char *verb) { + _cleanup_strv_free_ char **modes = NULL, **states = NULL; + int r; +@@ -175,5 +215,8 @@ int can_sleep(const char *verb) { + if (r < 0) + return false; + +- return can_sleep_state(states) && can_sleep_disk(modes); ++ if (!can_sleep_state(states) || !can_sleep_disk(modes)) ++ return false; ++ ++ return streq(verb, "suspend") || enough_memory_for_hibernation(); + } +diff --git a/src/shared/util.c b/src/shared/util.c +index 9a075fa..f6f3b18 100644 +--- a/src/shared/util.c ++++ b/src/shared/util.c +@@ -694,9 +694,6 @@ int is_kernel_thread(pid_t pid) { + + int get_process_capeff(pid_t pid, char **capeff) { + const char *p; +- _cleanup_free_ char *status = NULL; +- char *t = NULL; +- int r; + + assert(capeff); + assert(pid >= 0); +@@ -706,25 +703,7 @@ int get_process_capeff(pid_t pid, char **capeff) { + else + p = procfs_file_alloca(pid, "status"); + +- r = read_full_file(p, &status, NULL); +- if (r < 0) +- return r; +- +- t = strstr(status, "\nCapEff:\t"); +- if (!t) +- return -ENOENT; +- +- for (t += strlen("\nCapEff:\t"); t[0] == '0'; t++) +- continue; +- +- if (t[0] == '\n') +- t--; +- +- *capeff = strndup(t, strchr(t, '\n') - t); +- if (!*capeff) +- return -ENOMEM; +- +- return 0; ++ return get_status_field(p, "\nCapEff:", capeff); + } + + int get_process_exe(pid_t pid, char **name) { +diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c +index 1184e7e..4a4ed79 100644 +--- a/src/test/test-fileio.c ++++ b/src/test/test-fileio.c +@@ -229,9 +229,29 @@ static void test_executable_is_script(void) { + unlink(t); + } + ++static void test_status_field(void) { ++ _cleanup_free_ char *t = NULL, *p = NULL, *s = NULL; ++ unsigned long long total, buffers; ++ ++ assert_se(get_status_field("/proc/self/status", "\nThreads:", &t) == 0); ++ puts(t); ++ assert_se(streq(t, "1")); ++ ++ assert_se(get_status_field("/proc/meminfo", "MemTotal:", &p) == 0); ++ puts(p); ++ assert_se(safe_atollu(p, &total) == 0); ++ ++ assert_se(get_status_field("/proc/meminfo", "\nBuffers:", &s) == 0); ++ puts(s); ++ assert_se(safe_atollu(s, &buffers) == 0); ++ ++ assert(buffers < total); ++} ++ + int main(int argc, char *argv[]) { + test_parse_env_file(); + test_parse_multiline_env_file(); + test_executable_is_script(); ++ test_status_field(); + return 0; + } +diff --git a/src/test/test-sleep.c b/src/test/test-sleep.c +index c3cb9c5..545dfab 100644 +--- a/src/test/test-sleep.c ++++ b/src/test/test-sleep.c +@@ -40,14 +40,14 @@ int main(int argc, char* argv[]) { + **shutdown = strv_new("shutdown", NULL), + **freez = strv_new("freeze", NULL); + +- log_info("Can Standby: %s", yes_no(can_sleep_state(standby) > 0)); +- log_info("Can Suspend: %s", yes_no(can_sleep_state(mem) > 0)); +- log_info("Can Hibernate: %s", yes_no(can_sleep_state(disk) > 0)); +- log_info("Can Hibernate+Suspend (Hybrid-Sleep): %s", yes_no(can_sleep_disk(suspend) > 0)); +- log_info("Can Hibernate+Reboot: %s", yes_no(can_sleep_disk(reboot) > 0)); +- log_info("Can Hibernate+Platform: %s", yes_no(can_sleep_disk(platform) > 0)); +- log_info("Can Hibernate+Shutdown: %s", yes_no(can_sleep_disk(shutdown) > 0)); +- log_info("Can Freeze: %s", yes_no(can_sleep_disk(freez) > 0)); ++ log_info("Standby configured: %s", yes_no(can_sleep_state(standby) > 0)); ++ log_info("Suspend configured: %s", yes_no(can_sleep_state(mem) > 0)); ++ log_info("Hibernate configured: %s", yes_no(can_sleep_state(disk) > 0)); ++ log_info("Hibernate+Suspend (Hybrid-Sleep) configured: %s", yes_no(can_sleep_disk(suspend) > 0)); ++ log_info("Hibernate+Reboot configured: %s", yes_no(can_sleep_disk(reboot) > 0)); ++ log_info("Hibernate+Platform configured: %s", yes_no(can_sleep_disk(platform) > 0)); ++ log_info("Hibernate+Shutdown configured: %s", yes_no(can_sleep_disk(shutdown) > 0)); ++ log_info("Freeze configured: %s", yes_no(can_sleep_state(freez) > 0)); + + log_info("Suspend configured and possible: %s", yes_no(can_sleep("suspend") > 0)); + log_info("Hibernation configured and possible: %s", yes_no(can_sleep("hibernate") > 0)); diff --git a/SOURCES/0018-README-add-SCSI-BSG-option.patch b/SOURCES/0018-README-add-SCSI-BSG-option.patch new file mode 100644 index 0000000..0653ac8 --- /dev/null +++ b/SOURCES/0018-README-add-SCSI-BSG-option.patch @@ -0,0 +1,24 @@ +From 64a94f1e45890eaeb5880dbd2044265e17023067 Mon Sep 17 00:00:00 2001 +From: Kay Sievers +Date: Sun, 15 Sep 2013 07:29:25 +0200 +Subject: [PATCH] README: add SCSI BSG option + +--- + README | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/README b/README +index a16f342..b39cd37 100644 +--- a/README ++++ b/README +@@ -64,6 +64,10 @@ REQUIREMENTS: + Mount and bind mount handling might require it: + CONFIG_FHANDLE + ++ Support for some SCSI devices serial number retrieval, to ++ create additional symlinks in /dev/disk/ and /dev/tape: ++ CONFIG_BLK_DEV_BSG ++ + Optional but strongly recommended: + CONFIG_IPV6 + CONFIG_AUTOFS4_FS diff --git a/SOURCES/0019-swap-create-.wants-symlink-to-auto-swap-devices.patch b/SOURCES/0019-swap-create-.wants-symlink-to-auto-swap-devices.patch new file mode 100644 index 0000000..0c3dd14 --- /dev/null +++ b/SOURCES/0019-swap-create-.wants-symlink-to-auto-swap-devices.patch @@ -0,0 +1,87 @@ +From c1f9c15f319f7dfb96bcbf2c3cf879f2b4457350 Mon Sep 17 00:00:00 2001 +From: Tom Gundersen +Date: Mon, 16 Sep 2013 01:08:32 +0200 +Subject: [PATCH] swap: create .wants symlink to 'auto' swap devices + +As we load unit files lazily, we need to make sure something pulls in swap +units that should be started automatically, otherwise the default dependencies +will never be applied. + +This partially reinstates code removed in +commit 64347fc2b983f33e7efb0fd2bb44e133fb9f30f4. + +Also don't order swap devices after swap.target when they are 'nofail'. +--- + src/core/swap.c | 8 ++++++-- + src/fstab-generator/fstab-generator.c | 18 ++++++++++++++++-- + 2 files changed, 22 insertions(+), 4 deletions(-) + +diff --git a/src/core/swap.c b/src/core/swap.c +index 3950860..76c7d45 100644 +--- a/src/core/swap.c ++++ b/src/core/swap.c +@@ -220,8 +220,12 @@ static int swap_add_default_dependencies(Swap *s) { + } + + if (!noauto) { +- r = unit_add_two_dependencies_by_name_inverse(UNIT(s), UNIT_AFTER, (nofail ? UNIT_WANTS : UNIT_REQUIRES), +- SPECIAL_SWAP_TARGET, NULL, true); ++ if (nofail) ++ r = unit_add_dependency_by_name_inverse(UNIT(s), ++ UNIT_WANTS, SPECIAL_SWAP_TARGET, NULL, true); ++ else ++ r = unit_add_two_dependencies_by_name_inverse(UNIT(s), ++ UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SWAP_TARGET, NULL, true); + if (r < 0) + return r; + } +diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c +index 6ebe8aa..b73dfa4 100644 +--- a/src/fstab-generator/fstab-generator.c ++++ b/src/fstab-generator/fstab-generator.c +@@ -66,6 +66,7 @@ static int mount_find_pri(struct mntent *me, int *ret) { + static int add_swap(const char *what, struct mntent *me) { + _cleanup_free_ char *name = NULL, *unit = NULL, *lnk = NULL, *device = NULL; + _cleanup_fclose_ FILE *f = NULL; ++ bool noauto; + int r, pri = -1; + + assert(what); +@@ -77,6 +78,8 @@ static int add_swap(const char *what, struct mntent *me) { + return pri; + } + ++ noauto = !!hasmntopt(me, "noauto"); ++ + name = unit_name_from_path(what, ".swap"); + if (!name) + return log_oom(); +@@ -97,8 +100,7 @@ static int add_swap(const char *what, struct mntent *me) { + fprintf(f, + "# Automatically generated by systemd-fstab-generator\n\n" + "[Unit]\n" +- "SourcePath=/etc/fstab\n" +- "\n" ++ "SourcePath=/etc/fstab\n\n" + "[Swap]\n" + "What=%s\n", + what); +@@ -114,6 +116,18 @@ static int add_swap(const char *what, struct mntent *me) { + return -errno; + } + ++ if (!noauto) { ++ lnk = strjoin(arg_dest, "/" SPECIAL_SWAP_TARGET ".wants/", name, NULL); ++ if (!lnk) ++ return log_oom(); ++ ++ mkdir_parents_label(lnk, 0755); ++ if (symlink(unit, lnk) < 0) { ++ log_error("Failed to create symlink %s: %m", lnk); ++ return -errno; ++ } ++ } ++ + return 0; + } + diff --git a/SOURCES/0020-cgroup-add-missing-equals-for-BlockIOWeight.patch b/SOURCES/0020-cgroup-add-missing-equals-for-BlockIOWeight.patch new file mode 100644 index 0000000..b8d63a7 --- /dev/null +++ b/SOURCES/0020-cgroup-add-missing-equals-for-BlockIOWeight.patch @@ -0,0 +1,22 @@ +From f93999bbdbc9e16322d77bda2a4e44c20040808d Mon Sep 17 00:00:00 2001 +From: Gao feng +Date: Mon, 16 Sep 2013 09:57:33 +0800 +Subject: [PATCH] cgroup: add missing equals for BlockIOWeight + +--- + src/core/cgroup.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/core/cgroup.c b/src/core/cgroup.c +index 1f41efc..9277dd6 100644 +--- a/src/core/cgroup.c ++++ b/src/core/cgroup.c +@@ -92,7 +92,7 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) { + "%sBlockIOAccounting=%s\n" + "%sMemoryAccounting=%s\n" + "%sCPUShares=%lu\n" +- "%sBlockIOWeight%lu\n" ++ "%sBlockIOWeight=%lu\n" + "%sMemoryLimit=%" PRIu64 "\n" + "%sMemorySoftLimit=%" PRIu64 "\n" + "%sDevicePolicy=%s\n", diff --git a/SOURCES/0021-Assume-that-proc-meminfo-can-be-missing.patch b/SOURCES/0021-Assume-that-proc-meminfo-can-be-missing.patch new file mode 100644 index 0000000..e834c09 --- /dev/null +++ b/SOURCES/0021-Assume-that-proc-meminfo-can-be-missing.patch @@ -0,0 +1,50 @@ +From 0fdb6640bb9de89ca739676bbbb43d3a05a42f50 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Sun, 15 Sep 2013 08:40:16 -0400 +Subject: [PATCH] Assume that /proc/meminfo can be missing + +Travis tests are failing, probably because /proc/meminfo is not available +in the test environment. The same might be true in some virtualized systems, +so just treat missing /proc/meminfo as a sign that hibernation is not +possible. +--- + src/shared/sleep-config.c | 3 ++- + src/test/test-fileio.c | 6 +++++- + 2 files changed, 7 insertions(+), 2 deletions(-) + +diff --git a/src/shared/sleep-config.c b/src/shared/sleep-config.c +index 5ec7cce..148c4dc 100644 +--- a/src/shared/sleep-config.c ++++ b/src/shared/sleep-config.c +@@ -172,7 +172,8 @@ static bool enough_memory_for_hibernation(void) { + + r = get_status_field("/proc/meminfo", "\nSwapFree:", &swapfree); + if (r < 0) { +- log_error("Failed to retrieve SwapFree from /proc/meminfo: %s", strerror(-r)); ++ log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, ++ "Failed to retrieve SwapFree from /proc/meminfo: %s", strerror(-r)); + return false; + } + +diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c +index 4a4ed79..3511f3a 100644 +--- a/src/test/test-fileio.c ++++ b/src/test/test-fileio.c +@@ -232,12 +232,16 @@ static void test_executable_is_script(void) { + static void test_status_field(void) { + _cleanup_free_ char *t = NULL, *p = NULL, *s = NULL; + unsigned long long total, buffers; ++ int r; + + assert_se(get_status_field("/proc/self/status", "\nThreads:", &t) == 0); + puts(t); + assert_se(streq(t, "1")); + +- assert_se(get_status_field("/proc/meminfo", "MemTotal:", &p) == 0); ++ r = get_status_field("/proc/meminfo", "MemTotal:", &p); ++ if (r == -ENOENT) ++ return; ++ assert(r == 0); + puts(p); + assert_se(safe_atollu(p, &total) == 0); + diff --git a/SOURCES/0022-transaction.c-do-not-point-users-to-logs-when-unit-n.patch b/SOURCES/0022-transaction.c-do-not-point-users-to-logs-when-unit-n.patch new file mode 100644 index 0000000..e3555ef --- /dev/null +++ b/SOURCES/0022-transaction.c-do-not-point-users-to-logs-when-unit-n.patch @@ -0,0 +1,63 @@ +From a38c3d5d4e94c7e11db1ca22126bb11c6b029886 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Sun, 15 Sep 2013 12:15:38 -0400 +Subject: [PATCH] transaction.c: do not point users to logs when unit not found + +The logs are unlikely to contain any useful information in this case. + +Also, change "walked on cycle path" to "found dependency on", which +is less technical and indicates the direction. With the old message, +I was never sure if prior units depended on later ones, or vice versa. + +https://bugzilla.redhat.com/show_bug.cgi?id=996133 +https://bugzilla.redhat.com/show_bug.cgi?id=997082 +--- + src/core/transaction.c | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +diff --git a/src/core/transaction.c b/src/core/transaction.c +index 27efef7..203070f 100644 +--- a/src/core/transaction.c ++++ b/src/core/transaction.c +@@ -344,7 +344,7 @@ static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsi + assert(!j->transaction_prev); + + /* Does a recursive sweep through the ordering graph, looking +- * for a cycle. If we find cycle we try to break it. */ ++ * for a cycle. If we find a cycle we try to break it. */ + + /* Have we seen this before? */ + if (j->generation == generation) { +@@ -371,7 +371,7 @@ static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsi + + /* logging for j not k here here to provide consistent narrative */ + log_info_unit(j->unit->id, +- "Walked on cycle path to %s/%s", ++ "Found dependency on %s/%s", + k->unit->id, job_type_to_string(k->type)); + + if (!delete && +@@ -860,7 +860,7 @@ int transaction_add_job_and_dependencies( + return -EINVAL; + } + +- if (type != JOB_STOP && (unit->load_state == UNIT_ERROR || unit->load_state == UNIT_NOT_FOUND)) { ++ if (type != JOB_STOP && unit->load_state == UNIT_ERROR) { + dbus_set_error(e, BUS_ERROR_LOAD_FAILED, + "Unit %s failed to load: %s. " + "See system logs and 'systemctl status %s' for details.", +@@ -870,6 +870,14 @@ int transaction_add_job_and_dependencies( + return -EINVAL; + } + ++ if (type != JOB_STOP && unit->load_state == UNIT_NOT_FOUND) { ++ dbus_set_error(e, BUS_ERROR_LOAD_FAILED, ++ "Unit %s failed to load: %s.", ++ unit->id, ++ strerror(-unit->load_error)); ++ return -EINVAL; ++ } ++ + if (type != JOB_STOP && unit->load_state == UNIT_MASKED) { + dbus_set_error(e, BUS_ERROR_MASKED, "Unit %s is masked.", unit->id); + return -EADDRNOTAVAIL; diff --git a/SOURCES/0023-Verify-validity-of-session-name-when-received-from-o.patch b/SOURCES/0023-Verify-validity-of-session-name-when-received-from-o.patch new file mode 100644 index 0000000..d13a554 --- /dev/null +++ b/SOURCES/0023-Verify-validity-of-session-name-when-received-from-o.patch @@ -0,0 +1,283 @@ +From 45f0d8e103c57e9e5e9d92bba1dc2d50b49806de Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Sun, 15 Sep 2013 22:26:56 -0400 +Subject: [PATCH] Verify validity of session name when received from outside + +Only ASCII letters and digits are allowed. +--- + Makefile.am | 14 +++++++++++--- + TODO | 3 --- + src/login/login-shared.c | 8 ++++++++ + src/login/login-shared.h | 3 +++ + src/login/logind-dbus.c | 1 + + src/login/logind-session.c | 1 + + src/login/logind-session.h | 1 + + src/login/logind.c | 6 ++++++ + src/login/sd-login.c | 12 +++++++----- + src/shared/cgroup-util.c | 4 +--- + src/shared/def.h | 5 +++++ + src/shared/env-util.c | 5 ++--- + src/shared/replace-var.c | 3 ++- + src/shared/unit-name.c | 5 ++--- + 14 files changed, 50 insertions(+), 21 deletions(-) + create mode 100644 src/login/login-shared.c + create mode 100644 src/login/login-shared.h + +diff --git a/Makefile.am b/Makefile.am +index 7b7539a..6014521 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -2324,7 +2324,10 @@ if HAVE_ACL + libudev_core_la_SOURCES += \ + src/udev/udev-builtin-uaccess.c \ + src/login/logind-acl.c \ +- src/login/sd-login.c ++ src/login/sd-login.c \ ++ src/systemd/sd-login.h \ ++ src/login/login-shared.c \ ++ src/login/login-shared.h + + libudev_core_la_LIBADD += \ + libsystemd-acl.la +@@ -3759,7 +3762,9 @@ libsystemd_logind_core_la_SOURCES = \ + src/login/logind-session-dbus.c \ + src/login/logind-seat-dbus.c \ + src/login/logind-user-dbus.c \ +- src/login/logind-acl.h ++ src/login/logind-acl.h \ ++ src/login/login-shared.c \ ++ src/login/login-shared.h + + libsystemd_logind_core_la_CFLAGS = \ + $(AM_CFLAGS) \ +@@ -3860,7 +3865,10 @@ tests += \ + test-login-tables + + libsystemd_login_la_SOURCES = \ +- src/login/sd-login.c ++ src/login/sd-login.c \ ++ src/systemd/sd-login.h \ ++ src/login/login-shared.c \ ++ src/login/login-shared.h + + libsystemd_login_la_CFLAGS = \ + $(AM_CFLAGS) \ +diff --git a/TODO b/TODO +index 9943b3e..bfeaa81 100644 +--- a/TODO ++++ b/TODO +@@ -142,9 +142,6 @@ Features: + + * journald: make sure ratelimit is actually really per-service with the new cgroup changes + +-* libsystemd-logind: sd_session_is_active() and friends: verify +- validity of session name before appending it to a path +- + * gparted needs to disable auto-activation of mount units somehow, or + maybe we should stop doing auto-activation of this after boot + entirely. https://bugzilla.gnome.org/show_bug.cgi?id=701676 +diff --git a/src/login/login-shared.c b/src/login/login-shared.c +new file mode 100644 +index 0000000..ff13c28 +--- /dev/null ++++ b/src/login/login-shared.c +@@ -0,0 +1,8 @@ ++#include "login-shared.h" ++#include "def.h" ++ ++bool session_id_valid(const char *id) { ++ assert(id); ++ ++ return id + strspn(id, LETTERS DIGITS) == '\0'; ++} +diff --git a/src/login/login-shared.h b/src/login/login-shared.h +new file mode 100644 +index 0000000..728ef00 +--- /dev/null ++++ b/src/login/login-shared.h +@@ -0,0 +1,3 @@ ++#include ++ ++bool session_id_valid(const char *id); +diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c +index 345df9f..d052e74 100644 +--- a/src/login/logind-dbus.c ++++ b/src/login/logind-dbus.c +@@ -554,6 +554,7 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message) { + * the audit data and let's better register a new + * ID */ + if (hashmap_get(m->sessions, id)) { ++ log_warning("Existing logind session ID %s used by new audit session, ignoring", id); + audit_id = 0; + + free(id); +diff --git a/src/login/logind-session.c b/src/login/logind-session.c +index a726fb1..2d22a68 100644 +--- a/src/login/logind-session.c ++++ b/src/login/logind-session.c +@@ -41,6 +41,7 @@ Session* session_new(Manager *m, const char *id) { + + assert(m); + assert(id); ++ assert(session_id_valid(id)); + + s = new0(Session, 1); + if (!s) +diff --git a/src/login/logind-session.h b/src/login/logind-session.h +index edaae8d..9cf6485 100644 +--- a/src/login/logind-session.h ++++ b/src/login/logind-session.h +@@ -29,6 +29,7 @@ typedef enum KillWho KillWho; + #include "logind.h" + #include "logind-seat.h" + #include "logind-user.h" ++#include "login-shared.h" + + typedef enum SessionState { + SESSION_OPENING, /* Session scope is being created */ +diff --git a/src/login/logind.c b/src/login/logind.c +index 9094567..4ef92b8 100644 +--- a/src/login/logind.c ++++ b/src/login/logind.c +@@ -684,6 +684,12 @@ int manager_enumerate_sessions(Manager *m) { + if (!dirent_is_file(de)) + continue; + ++ if (!session_id_valid(de->d_name)) { ++ log_warning("Invalid session file name '%s', ignoring.", de->d_name); ++ r = -EINVAL; ++ continue; ++ } ++ + k = manager_add_session(m, de->d_name, &s); + if (k < 0) { + log_error("Failed to add session by file name %s: %s", de->d_name, strerror(-k)); +diff --git a/src/login/sd-login.c b/src/login/sd-login.c +index 8a7838d..71d8c29 100644 +--- a/src/login/sd-login.c ++++ b/src/login/sd-login.c +@@ -31,6 +31,7 @@ + #include "sd-login.h" + #include "strv.h" + #include "fileio.h" ++#include "login-shared.h" + + _public_ int sd_pid_get_session(pid_t pid, char **session) { + if (pid < 0) +@@ -226,17 +227,19 @@ static int file_of_session(const char *session, char **_p) { + + assert(_p); + +- if (session) ++ if (session) { ++ if (!session_id_valid(session)) ++ return -EINVAL; ++ + p = strappend("/run/systemd/sessions/", session); +- else { +- char *buf; ++ } else { ++ _cleanup_free_ char *buf = NULL; + + r = sd_pid_get_session(0, &buf); + if (r < 0) + return r; + + p = strappend("/run/systemd/sessions/", buf); +- free(buf); + } + + if (!p) +@@ -255,7 +258,6 @@ _public_ int sd_session_is_active(const char *session) { + return r; + + r = parse_env_file(p, NEWLINE, "ACTIVE", &s, NULL); +- + if (r < 0) + return r; + +diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c +index 1d545e0..0bffebd 100644 +--- a/src/shared/cgroup-util.c ++++ b/src/shared/cgroup-util.c +@@ -1511,9 +1511,7 @@ char *cg_unescape(const char *p) { + } + + #define CONTROLLER_VALID \ +- "0123456789" \ +- "abcdefghijklmnopqrstuvwxyz" \ +- "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ ++ DIGITS LETTERS \ + "_" + + bool cg_controller_is_valid(const char *p, bool allow_named) { +diff --git a/src/shared/def.h b/src/shared/def.h +index 5abb544..edd0bcf 100644 +--- a/src/shared/def.h ++++ b/src/shared/def.h +@@ -33,3 +33,8 @@ + + #define SIGNALS_CRASH_HANDLER SIGSEGV,SIGILL,SIGFPE,SIGBUS,SIGQUIT,SIGABRT + #define SIGNALS_IGNORE SIGPIPE ++ ++#define DIGITS "0123456789" ++#define LOWERCASE_LETTERS "abcdefghijklmnopqrstuvwxyz" ++#define UPPERCASE_LETTERS "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ++#define LETTERS LOWERCASE_LETTERS UPPERCASE_LETTERS +diff --git a/src/shared/env-util.c b/src/shared/env-util.c +index 6a52fb9..5e29629 100644 +--- a/src/shared/env-util.c ++++ b/src/shared/env-util.c +@@ -27,11 +27,10 @@ + #include "utf8.h" + #include "util.h" + #include "env-util.h" ++#include "def.h" + + #define VALID_CHARS_ENV_NAME \ +- "0123456789" \ +- "abcdefghijklmnopqrstuvwxyz" \ +- "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ ++ DIGITS LETTERS \ + "_" + + #ifndef ARG_MAX +diff --git a/src/shared/replace-var.c b/src/shared/replace-var.c +index e11c57a..478fc43 100644 +--- a/src/shared/replace-var.c ++++ b/src/shared/replace-var.c +@@ -24,6 +24,7 @@ + #include "macro.h" + #include "util.h" + #include "replace-var.h" ++#include "def.h" + + /* + * Generic infrastructure for replacing @FOO@ style variables in +@@ -40,7 +41,7 @@ static int get_variable(const char *b, char **r) { + if (*b != '@') + return 0; + +- k = strspn(b + 1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ_"); ++ k = strspn(b + 1, UPPERCASE_LETTERS "_"); + if (k <= 0 || b[k+1] != '@') + return 0; + +diff --git a/src/shared/unit-name.c b/src/shared/unit-name.c +index 1baa6eb..8f6c28e 100644 +--- a/src/shared/unit-name.c ++++ b/src/shared/unit-name.c +@@ -26,11 +26,10 @@ + #include "path-util.h" + #include "util.h" + #include "unit-name.h" ++#include "def.h" + + #define VALID_CHARS \ +- "0123456789" \ +- "abcdefghijklmnopqrstuvwxyz" \ +- "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ ++ DIGITS LETTERS \ + ":-_.\\" + + static const char* const unit_type_table[_UNIT_TYPE_MAX] = { diff --git a/SOURCES/0024-udev-rules-avoid-erroring-on-trailing-whitespace.patch b/SOURCES/0024-udev-rules-avoid-erroring-on-trailing-whitespace.patch new file mode 100644 index 0000000..a1145df --- /dev/null +++ b/SOURCES/0024-udev-rules-avoid-erroring-on-trailing-whitespace.patch @@ -0,0 +1,27 @@ +From c4f1b97f45f1685c0a4bcba8c6724ce17bb6af19 Mon Sep 17 00:00:00 2001 +From: Dave Reisner +Date: Mon, 16 Sep 2013 11:22:35 -0400 +Subject: [PATCH] udev-rules: avoid erroring on trailing whitespace + +https://bugs.archlinux.org/task/36950 +--- + src/udev/udev-rules.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c +index f14158b..6f8b127 100644 +--- a/src/udev/udev-rules.c ++++ b/src/udev/udev-rules.c +@@ -1068,6 +1068,12 @@ static int add_rule(struct udev_rules *rules, char *line, + enum operation_type op; + + if (get_key(rules->udev, &linepos, &key, &op, &value) != 0) { ++ /* Avoid erroring on trailing whitespace. This is probably rare ++ * so save the work for the error case instead of always trying ++ * to strip the trailing whitespace with strstrip(). */ ++ while (isblank(*linepos)) ++ linepos++; ++ + /* If we aren't at the end of the line, this is a parsing error. + * Make a best effort to describe where the problem is. */ + if (*linepos != '\n') { diff --git a/SOURCES/0025-keymap-Add-Samsung-Series-5-Ultra.patch b/SOURCES/0025-keymap-Add-Samsung-Series-5-Ultra.patch new file mode 100644 index 0000000..7004c85 --- /dev/null +++ b/SOURCES/0025-keymap-Add-Samsung-Series-5-Ultra.patch @@ -0,0 +1,65 @@ +From 3d2b4b62bfc73a38dce90be5cebdc924db42f63c Mon Sep 17 00:00:00 2001 +From: Martin Pitt +Date: Mon, 16 Sep 2013 14:25:44 -0500 +Subject: [PATCH] keymap: Add Samsung Series 5 [Ultra] + +Also consolidate the wlan key into the "all Samsung" rule to avoid repetition. + +Thanks to Mauro Carvalho Chehab! + +https://bugzilla.redhat.com/show_bug.cgi?id=989103 +--- + hwdb/60-keyboard.hwdb | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +diff --git a/hwdb/60-keyboard.hwdb b/hwdb/60-keyboard.hwdb +index 53e83ad..3862b4c 100644 +--- a/hwdb/60-keyboard.hwdb ++++ b/hwdb/60-keyboard.hwdb +@@ -882,6 +882,8 @@ keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn* + KEYBOARD_KEY_b1=!prog2 # Fn+F7 run Samsung Magic Doctor (keypressed event is generated twice) + KEYBOARD_KEY_b3=!prog3 # Fn+F8 switch power mode (battery/dynamic/performance) + KEYBOARD_KEY_b4=!wlan # Fn+F9 (X60P) ++ KEYBOARD_KEY_c5=!prog3 # Fn+F8 switch power mode (battery/dynamic/performance) ++ KEYBOARD_KEY_d5=!wlan # Fn+F12 wlan/airplane switch + KEYBOARD_KEY_f7=!f22 # Fn+F10 Touchpad on + KEYBOARD_KEY_f9=!f23 # Fn+F10 Touchpad off + +@@ -889,9 +891,18 @@ keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn* + keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*300E[457]*:pvr* + keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*200E[45]*:pvr* + KEYBOARD_KEY_ce=! # Fn+F1 launch control setting +- KEYBOARD_KEY_d5=! # Fn+F12 Wi-Fi toggle + + # Series 5 ++keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*530U*:pvr* ++ KEYBOARD_KEY_ce=!prog1 # Fn+F1 launch settings ++ KEYBOARD_KEY_a8=! # Fn Lock - Function lock on ++ KEYBOARD_KEY_a9=! # Fn Lock - Function lock off ++ ++keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*550P*:pvr* ++ KEYBOARD_KEY_ce=!prog1 # Fn+F1 launch settings ++ KEYBOARD_KEY_a8=! # Fn Lock - Function lock on ++ KEYBOARD_KEY_a9=! # Fn Lock - Function lock off ++ + keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*700Z*:pvr* + KEYBOARD_KEY_ce=!prog1 # Fn+F1 launch settings + KEYBOARD_KEY_a0=!mute # Fn+F6 mute +@@ -900,7 +911,6 @@ keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*700Z*:pvr* + KEYBOARD_KEY_97=!kbdillumdown # Fn+F9 keyboard backlight down + KEYBOARD_KEY_96=!kbdillumup # Fn+F10 keyboard backlight up + KEYBOARD_KEY_b3=!prog3 # Fn+F11 fan/cooling mode changer +- KEYBOARD_KEY_d5=!wlan # Fn+F12 wlan/airplane switch + + # Series 9 + keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*90X3A*:pvr* +@@ -936,9 +946,6 @@ keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*700Z*:pvr* + keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*700T*:pvr* + KEYBOARD_KEY_ad=leftmeta + +-keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn535U*:pvr* +- KEYBOARD_KEY_d5=!wlan +- + ########################################################### + # SONY + ########################################################### diff --git a/SOURCES/0026-login-fix-login_is_valid-test.patch b/SOURCES/0026-login-fix-login_is_valid-test.patch new file mode 100644 index 0000000..2d2a8eb --- /dev/null +++ b/SOURCES/0026-login-fix-login_is_valid-test.patch @@ -0,0 +1,149 @@ +From 87e08d21857b2b2e59f3480e6d0538b535a5897c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Mon, 16 Sep 2013 11:04:20 -0500 +Subject: [PATCH] login: fix login_is_valid test + +--- + Makefile.am | 10 +++++++++- + src/login/login-shared.c | 23 ++++++++++++++++++++++- + src/login/login-shared.h | 21 +++++++++++++++++++++ + src/login/test-login-shared.c | 38 ++++++++++++++++++++++++++++++++++++++ + 4 files changed, 90 insertions(+), 2 deletions(-) + create mode 100644 src/login/test-login-shared.c + +diff --git a/Makefile.am b/Makefile.am +index 6014521..eae001b 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -3836,6 +3836,13 @@ test_login_LDADD = \ + libsystemd-login-internal.la \ + libsystemd-shared.la + ++test_login_shared_SOURCES = \ ++ src/login/test-login-shared.c ++ ++test_login_shared_LDADD = \ ++ libsystemd-login-internal.la \ ++ libsystemd-shared.la ++ + test_inhibit_SOURCES = \ + src/login/test-inhibit.c + +@@ -3862,7 +3869,8 @@ manual_tests += \ + test-inhibit + + tests += \ +- test-login-tables ++ test-login-tables \ ++ test-login-shared + + libsystemd_login_la_SOURCES = \ + src/login/sd-login.c \ +diff --git a/src/login/login-shared.c b/src/login/login-shared.c +index ff13c28..054c775 100644 +--- a/src/login/login-shared.c ++++ b/src/login/login-shared.c +@@ -1,8 +1,29 @@ ++/*-*- 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 . ++***/ ++ + #include "login-shared.h" + #include "def.h" + + bool session_id_valid(const char *id) { + assert(id); + +- return id + strspn(id, LETTERS DIGITS) == '\0'; ++ return id[0] && id[strspn(id, LETTERS DIGITS)] == '\0'; + } +diff --git a/src/login/login-shared.h b/src/login/login-shared.h +index 728ef00..b2787c9 100644 +--- a/src/login/login-shared.h ++++ b/src/login/login-shared.h +@@ -1,3 +1,24 @@ ++/*-*- 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 . ++***/ ++ + #include + + bool session_id_valid(const char *id); +diff --git a/src/login/test-login-shared.c b/src/login/test-login-shared.c +new file mode 100644 +index 0000000..2df6029 +--- /dev/null ++++ b/src/login/test-login-shared.c +@@ -0,0 +1,38 @@ ++/*-*- 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 . ++***/ ++ ++#include "macro.h" ++#include "login-shared.h" ++ ++static void test_session_id_valid(void) { ++ assert_se(session_id_valid("c1")); ++ assert_se(session_id_valid("1234")); ++ ++ assert_se(!session_id_valid("1-2")); ++ assert_se(!session_id_valid("")); ++ assert_se(!session_id_valid("\tid")); ++} ++ ++int main(int argc, char* argv[]) { ++ test_session_id_valid(); ++ ++ return 0; ++} diff --git a/SOURCES/0027-polkit-Avoid-race-condition-in-scraping-proc.patch b/SOURCES/0027-polkit-Avoid-race-condition-in-scraping-proc.patch new file mode 100644 index 0000000..b1b1cc3 --- /dev/null +++ b/SOURCES/0027-polkit-Avoid-race-condition-in-scraping-proc.patch @@ -0,0 +1,74 @@ +From 88e8824997b26b821530384bb944e15a63e81301 Mon Sep 17 00:00:00 2001 +From: Colin Walters +Date: Thu, 22 Aug 2013 13:55:21 -0400 +Subject: [PATCH] polkit: Avoid race condition in scraping /proc + +If a calling process execve()s a setuid program, it can appear to be +uid 0. Since we're receiving requests over DBus, avoid this by simply +passing system-bus-name as a subject. + +https://bugzilla.redhat.com/show_bug.cgi?id=1005142 +--- + src/shared/polkit.c | 31 +++++-------------------------- + 1 file changed, 5 insertions(+), 26 deletions(-) + +diff --git a/src/shared/polkit.c b/src/shared/polkit.c +index cea7074..1c5e9e3 100644 +--- a/src/shared/polkit.c ++++ b/src/shared/polkit.c +@@ -38,12 +38,8 @@ int verify_polkit( + + #ifdef ENABLE_POLKIT + DBusMessage *m = NULL, *reply = NULL; +- const char *unix_process = "unix-process", *pid = "pid", *starttime = "start-time", *cancel_id = ""; ++ const char *system_bus_name = "system-bus-name", *name = "name", *cancel_id = ""; + uint32_t flags = interactive ? 1 : 0; +- pid_t pid_raw; +- uint32_t pid_u32; +- unsigned long long starttime_raw; +- uint64_t starttime_u64; + DBusMessageIter iter_msg, iter_struct, iter_array, iter_dict, iter_variant; + int r; + dbus_bool_t authorized = FALSE, challenge = FALSE; +@@ -68,14 +64,6 @@ int verify_polkit( + + #ifdef ENABLE_POLKIT + +- pid_raw = bus_get_unix_process_id(c, sender, error); +- if (pid_raw == 0) +- return -EINVAL; +- +- r = get_starttime_of_pid(pid_raw, &starttime_raw); +- if (r < 0) +- return r; +- + m = dbus_message_new_method_call( + "org.freedesktop.PolicyKit1", + "/org/freedesktop/PolicyKit1/Authority", +@@ -86,22 +74,13 @@ int verify_polkit( + + dbus_message_iter_init_append(m, &iter_msg); + +- pid_u32 = (uint32_t) pid_raw; +- starttime_u64 = (uint64_t) starttime_raw; +- + if (!dbus_message_iter_open_container(&iter_msg, DBUS_TYPE_STRUCT, NULL, &iter_struct) || +- !dbus_message_iter_append_basic(&iter_struct, DBUS_TYPE_STRING, &unix_process) || ++ !dbus_message_iter_append_basic(&iter_struct, DBUS_TYPE_STRING, &system_bus_name) || + !dbus_message_iter_open_container(&iter_struct, DBUS_TYPE_ARRAY, "{sv}", &iter_array) || + !dbus_message_iter_open_container(&iter_array, DBUS_TYPE_DICT_ENTRY, NULL, &iter_dict) || +- !dbus_message_iter_append_basic(&iter_dict, DBUS_TYPE_STRING, &pid) || +- !dbus_message_iter_open_container(&iter_dict, DBUS_TYPE_VARIANT, "u", &iter_variant) || +- !dbus_message_iter_append_basic(&iter_variant, DBUS_TYPE_UINT32, &pid_u32) || +- !dbus_message_iter_close_container(&iter_dict, &iter_variant) || +- !dbus_message_iter_close_container(&iter_array, &iter_dict) || +- !dbus_message_iter_open_container(&iter_array, DBUS_TYPE_DICT_ENTRY, NULL, &iter_dict) || +- !dbus_message_iter_append_basic(&iter_dict, DBUS_TYPE_STRING, &starttime) || +- !dbus_message_iter_open_container(&iter_dict, DBUS_TYPE_VARIANT, "t", &iter_variant) || +- !dbus_message_iter_append_basic(&iter_variant, DBUS_TYPE_UINT64, &starttime_u64) || ++ !dbus_message_iter_append_basic(&iter_dict, DBUS_TYPE_STRING, &name) || ++ !dbus_message_iter_open_container(&iter_dict, DBUS_TYPE_VARIANT, "s", &iter_variant) || ++ !dbus_message_iter_append_basic(&iter_variant, DBUS_TYPE_STRING, &sender) || + !dbus_message_iter_close_container(&iter_dict, &iter_variant) || + !dbus_message_iter_close_container(&iter_array, &iter_dict) || + !dbus_message_iter_close_container(&iter_struct, &iter_array) || diff --git a/SOURCES/0028-core-whenever-a-new-PID-is-passed-to-us-make-sure-we.patch b/SOURCES/0028-core-whenever-a-new-PID-is-passed-to-us-make-sure-we.patch new file mode 100644 index 0000000..0323c04 --- /dev/null +++ b/SOURCES/0028-core-whenever-a-new-PID-is-passed-to-us-make-sure-we.patch @@ -0,0 +1,71 @@ +From f47d0b042f6d0a1661dff9816410162693d1daa2 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 1 Oct 2013 05:06:56 +0200 +Subject: [PATCH] core: whenever a new PID is passed to us, make sure we watch + it + +--- + src/core/service.c | 21 +++++++++++++++------ + 1 file changed, 15 insertions(+), 6 deletions(-) + +diff --git a/src/core/service.c b/src/core/service.c +index 246a86e..5953f45 100644 +--- a/src/core/service.c ++++ b/src/core/service.c +@@ -191,7 +191,13 @@ static int service_set_main_pid(Service *s, pid_t pid) { + if (pid == getpid()) + return -EINVAL; + +- service_unwatch_main_pid(s); ++ if (s->main_pid == pid && s->main_pid_known) ++ return 0; ++ ++ if (s->main_pid != pid) { ++ service_unwatch_main_pid(s); ++ exec_status_start(&s->main_exec_status, pid); ++ } + + s->main_pid = pid; + s->main_pid_known = true; +@@ -205,8 +211,6 @@ static int service_set_main_pid(Service *s, pid_t pid) { + } else + s->main_pid_alien = false; + +- exec_status_start(&s->main_exec_status, pid); +- + return 0; + } + +@@ -2698,8 +2702,10 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value, + + if (parse_pid(value, &pid) < 0) + log_debug_unit(u->id, "Failed to parse main-pid value %s", value); +- else +- service_set_main_pid(s, (pid_t) pid); ++ else { ++ service_set_main_pid(s, pid); ++ unit_watch_pid(UNIT(s), pid); ++ } + } else if (streq(key, "main-pid-known")) { + int b; + +@@ -3391,6 +3397,7 @@ static void service_notify_message(Unit *u, pid_t pid, char **tags) { + log_debug_unit(u->id, + "%s: got %s", u->id, e); + service_set_main_pid(s, pid); ++ unit_watch_pid(UNIT(s), pid); + } + } + +@@ -3687,8 +3694,10 @@ static void service_bus_query_pid_done( + (s->state == SERVICE_START || + s->state == SERVICE_START_POST || + s->state == SERVICE_RUNNING || +- s->state == SERVICE_RELOAD)) ++ s->state == SERVICE_RELOAD)){ + service_set_main_pid(s, pid); ++ unit_watch_pid(UNIT(s), pid); ++ } + } + + int service_set_socket_fd(Service *s, int fd, Socket *sock) { diff --git a/SOURCES/0029-remove-user-.service.patch b/SOURCES/0029-remove-user-.service.patch new file mode 100644 index 0000000..e61dcff --- /dev/null +++ b/SOURCES/0029-remove-user-.service.patch @@ -0,0 +1,91 @@ +From 40810e62f4df958b2465dcc1923b8b827fb778e8 Mon Sep 17 00:00:00 2001 +From: Harald Hoyer +Date: Wed, 30 Oct 2013 18:22:49 +0100 +Subject: [PATCH] remove user@.service + +fixes rhbz#1019738 +--- + Makefile.am | 2 -- + src/login/logind-user.c | 42 ------------------------------------------ + 2 files changed, 44 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index eae001b..25bfd91 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -435,7 +435,6 @@ nodist_systemunit_DATA = \ + units/systemd-sysctl.service \ + units/emergency.service \ + units/rescue.service \ +- units/user@.service \ + units/systemd-hibernate.service \ + units/systemd-hybrid-sleep.service \ + units/systemd-suspend.service \ +@@ -484,7 +483,6 @@ EXTRA_DIST += \ + units/user/systemd-exit.service.in \ + units/systemd-fsck@.service.in \ + units/systemd-fsck-root.service.in \ +- units/user@.service.in \ + units/systemd-udevd.service \ + units/systemd-udev-trigger.service \ + units/systemd-udev-settle.service \ +diff --git a/src/login/logind-user.c b/src/login/logind-user.c +index adbe638..9cc186b 100644 +--- a/src/login/logind-user.c ++++ b/src/login/logind-user.c +@@ -365,43 +365,6 @@ static int user_start_slice(User *u) { + return 0; + } + +-static int user_start_service(User *u) { +- DBusError error; +- char *job; +- int r; +- +- assert(u); +- +- dbus_error_init(&error); +- +- if (!u->service) { +- char lu[DECIMAL_STR_MAX(unsigned long) + 1], *service; +- sprintf(lu, "%lu", (unsigned long) u->uid); +- +- service = unit_name_build("user", lu, ".service"); +- if (!service) +- return log_oom(); +- +- r = manager_start_unit(u->manager, service, &error, &job); +- if (r < 0) { +- log_error("Failed to start user service: %s", bus_error(&error, r)); +- dbus_error_free(&error); +- +- free(service); +- } else { +- u->service = service; +- +- free(u->service_job); +- u->service_job = job; +- } +- } +- +- if (u->service) +- hashmap_put(u->manager->user_units, u->service, u); +- +- return 0; +-} +- + int user_start(User *u) { + int r; + +@@ -422,11 +385,6 @@ int user_start(User *u) { + if (r < 0) + return r; + +- /* Spawn user systemd */ +- r = user_start_service(u); +- if (r < 0) +- return r; +- + if (!dual_timestamp_is_set(&u->timestamp)) + dual_timestamp_get(&u->timestamp); + diff --git a/SOURCES/0030-cgroup-always-enable-memory.use_hierarchy-for-all-cg.patch b/SOURCES/0030-cgroup-always-enable-memory.use_hierarchy-for-all-cg.patch new file mode 100644 index 0000000..266f504 --- /dev/null +++ b/SOURCES/0030-cgroup-always-enable-memory.use_hierarchy-for-all-cg.patch @@ -0,0 +1,27 @@ +From 8986b8ccd7ea39d75246b72f497a4131a278f3bb Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 23 Sep 2013 16:02:31 -0500 +Subject: [PATCH] cgroup: always enable memory.use_hierarchy= for all cgroups + in the memory hierarchy + +The non-hierarchial mode contradicts the whole idea of a cgroup tree so +let's not support this. In the future the kernel will only support the +hierarchial logic anyway. +--- + src/core/cgroup.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/core/cgroup.c b/src/core/cgroup.c +index 9277dd6..7f29afb 100644 +--- a/src/core/cgroup.c ++++ b/src/core/cgroup.c +@@ -678,6 +678,9 @@ int manager_setup_cgroup(Manager *m) { + /* 6. Figure out which controllers are supported */ + m->cgroup_supported = cg_mask_supported(); + ++ /* 7. Always enable hierarchial support if it exists... */ ++ cg_set_attribute("memory", "/", "memory.use_hierarchy", "1"); ++ + return 0; + } + diff --git a/SOURCES/0031-logind-return-EINVAL-when-PID-is-wrong.patch b/SOURCES/0031-logind-return-EINVAL-when-PID-is-wrong.patch new file mode 100644 index 0000000..4a7f024 --- /dev/null +++ b/SOURCES/0031-logind-return-EINVAL-when-PID-is-wrong.patch @@ -0,0 +1,45 @@ +From 07c3b93b709a601398ce5e06d48f215d097ed959 Mon Sep 17 00:00:00 2001 +From: Lukas Nykryn +Date: Tue, 24 Sep 2013 16:27:20 +0200 +Subject: [PATCH] logind: return -EINVAL when PID is wrong + +dbus-send --print-reply --system --dest=org.freedesktop.login1 +/org/freedesktop/login1 org.freedesktop.login1.Manager.GetUserByPID +uint32:0 +causes +systemd-logind[29843]: Assertion 'pid >= 1' failed at +src/login/logind.c:938, function manager_get_user_by_pid(). Aborting. +--- + src/login/logind.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/src/login/logind.c b/src/login/logind.c +index 4ef92b8..afc737c 100644 +--- a/src/login/logind.c ++++ b/src/login/logind.c +@@ -914,9 +914,11 @@ int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) { + int r; + + assert(m); +- assert(pid >= 1); + assert(session); + ++ if (pid < 1) ++ return -EINVAL; ++ + r = cg_pid_get_unit(pid, &unit); + if (r < 0) + return r; +@@ -935,9 +937,11 @@ int manager_get_user_by_pid(Manager *m, pid_t pid, User **user) { + int r; + + assert(m); +- assert(pid >= 1); + assert(user); + ++ if (pid < 1) ++ return -EINVAL; ++ + r = cg_pid_get_slice(pid, &unit); + if (r < 0) + return r; diff --git a/SOURCES/0032-core-drop-some-out-of-date-references-to-cgroup-sett.patch b/SOURCES/0032-core-drop-some-out-of-date-references-to-cgroup-sett.patch new file mode 100644 index 0000000..84e5fa1 --- /dev/null +++ b/SOURCES/0032-core-drop-some-out-of-date-references-to-cgroup-sett.patch @@ -0,0 +1,197 @@ +From 873b06ca6f97f7288c98647fa5e761847122a382 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 26 Sep 2013 22:49:44 +0200 +Subject: [PATCH] core: drop some out-of-date references to cgroup settings + +--- + man/systemd-cgtop.xml | 36 +++++++++++++++--------------------- + man/systemd-system.conf.xml | 27 +-------------------------- + man/systemd.unit.xml | 5 ++++- + src/core/dbus-manager.c | 27 --------------------------- + src/core/system.conf | 3 +-- + src/core/user.conf | 1 - + 6 files changed, 21 insertions(+), 78 deletions(-) + +diff --git a/man/systemd-cgtop.xml b/man/systemd-cgtop.xml +index 0e9e5e6..51549c4 100644 +--- a/man/systemd-cgtop.xml ++++ b/man/systemd-cgtop.xml +@@ -73,30 +73,23 @@ + only accounted for control groups in the + cpuacct hierarchy, memory usage + only for those in memory and disk +- I/O usage for those in +- blkio. systemd1 +- by default places all services in their own control +- group in the cpuacct hierarchy, but +- not in memory nor +- blkio. If resource monitoring for +- these resources is required, it is recommended to add +- blkio and memory +- to the DefaultControllers= setting +- in /etc/systemd/system.conf (see +- systemd-system.conf5 +- for details). Alternatively, it is possible to enable +- resource accounting individually for services, by +- making use of the ControlGroup= +- option in the unit files (See +- systemd.exec5 ++ I/O usage for those in blkio. If ++ resource monitoring for these resources is required, ++ it is recommended to add the ++ CPUAccounting=1, ++ MemoryAccounting=1 and ++ BlockIOAccounting=1 settings in the ++ unit files in question (See ++ systemd.cgroup5 + for details). + + To emphasize this: unless +- blkio and memory +- are enabled for the services in question with either +- of the options suggested above no resource accounting +- will be available for system services and the data shown +- by systemd-cgtop will be ++ CPUAccounting=1, ++ MemoryAccounting=1 and ++ BlockIOAccounting=1 are enabled for ++ the services in question no resource accounting will ++ be available for system services and the data shown by ++ systemd-cgtop will be + incomplete. + + +@@ -281,6 +274,7 @@ + systemd1, + systemctl1, + systemd-cgls1, ++ systemd.cgroup5, + top1 + + +diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml +index c52e590..e8cf8a9 100644 +--- a/man/systemd-system.conf.xml ++++ b/man/systemd-system.conf.xml +@@ -104,32 +104,7 @@ + + + +- DefaultControllers=cpu +- +- Configures in which +- control group hierarchies to create +- per-service cgroups automatically, in +- addition to the +- name=systemd named +- hierarchy. Defaults to +- cpu. Takes a +- space-separated list of controller +- names. Pass the empty string to ensure +- that systemd does not touch any +- hierarchies but its own. +- +- Note that the default value of +- 'cpu' will make realtime scheduling +- unavailable to system services. See +- My +- Service Can't Get Realtime! +- for more +- information. +- +- +- +- JoinControllers=cpu,cpuacct,cpuset net_cls,netprio ++ JoinControllers=cpu,cpuacct net_cls,netprio + + Configures controllers + that shall be mounted in a single +diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml +index d61426a..5c8b8e8 100644 +--- a/man/systemd.unit.xml ++++ b/man/systemd.unit.xml +@@ -1241,7 +1241,10 @@ + + %R + Parent directory of the control group path where units are placed. +- For system instances this usually resolves to /, except in containers, where this resolves to the container's root directory. This specifier is particularly useful in the ControlGroup= setting (see systemd.exec5). ++ For system instances this usually ++ resolves to /, except in ++ containers, where this resolves to the ++ container's root directory. + + + %t +diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c +index 75e2e45..676a07f 100644 +--- a/src/core/dbus-manager.c ++++ b/src/core/dbus-manager.c +@@ -103,32 +103,6 @@ + " \n" \ + " \n" \ + " \n" \ +- " \n" \ +- " \n" \ +- " \n" \ +- " \n" \ +- " \n" \ +- " \n" \ +- " \n" \ +- " \n" \ +- " " \ +- " \n" \ +- " \n" \ +- " \n" \ +- " \n" \ +- " \n" \ +- " \n" \ +- " \n" \ +- " \n" \ +- " \n" \ +- " \n" \ +- " " \ +- " \n" \ +- " \n" \ +- " \n" \ +- " \n" \ +- " \n" \ +- " \n" \ + " \n" \ + " \n" \ + " \n" \ +@@ -316,7 +290,6 @@ + " \n" \ + " \n" \ + " \n" \ +- " \n" \ + " \n" \ + " \n" \ + " \n" \ +diff --git a/src/core/system.conf b/src/core/system.conf +index f2817bc..7b03c87 100644 +--- a/src/core/system.conf ++++ b/src/core/system.conf +@@ -17,10 +17,9 @@ + #ShowStatus=yes + #CrashChVT=1 + #CPUAffinity=1 2 +-#DefaultControllers=cpu + #DefaultStandardOutput=journal + #DefaultStandardError=inherit +-#JoinControllers=cpu,cpuacct,cpuset net_cls,net_prio ++#JoinControllers=cpu,cpuacct net_cls,net_prio + #RuntimeWatchdogSec=0 + #ShutdownWatchdogSec=10min + #CapabilityBoundingSet= +diff --git a/src/core/user.conf b/src/core/user.conf +index 4252451..4a0129a 100644 +--- a/src/core/user.conf ++++ b/src/core/user.conf +@@ -12,6 +12,5 @@ + #LogTarget=console + #LogColor=yes + #LogLocation=no +-#DefaultControllers=cpu + #DefaultStandardOutput=inherit + #DefaultStandardError=inherit diff --git a/SOURCES/0033-man-explain-NAME-in-systemctl-man-page.patch b/SOURCES/0033-man-explain-NAME-in-systemctl-man-page.patch new file mode 100644 index 0000000..931639e --- /dev/null +++ b/SOURCES/0033-man-explain-NAME-in-systemctl-man-page.patch @@ -0,0 +1,33 @@ +From 29acf51b6a3ea9305752c9c4dacf1289a1edacb5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?V=C3=A1clav=20Pavl=C3=ADn?= +Date: Thu, 31 Oct 2013 14:36:41 +0100 +Subject: [PATCH] man: explain NAME in systemctl man page + +--- + man/systemctl.xml | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/man/systemctl.xml b/man/systemctl.xml +index b043581..51c34b7 100644 +--- a/man/systemctl.xml ++++ b/man/systemctl.xml +@@ -63,6 +63,19 @@ along with systemd; If not, see . + introspect and control the state of the + systemd1 + system and service manager. ++ ++ For Unit Commands the NAME represents full name of unit. ++ ++systemctl start foo.service ++ ++ For Unit File Commands the NAME represents full name of the unit file, or absolute path to the unit file. ++ ++systemctl start /path/to/foo.service ++ ++ While working with services/service files, systemctl is able to append .service suffix when it is missing. ++ ++systemctl start foo ++ + + + diff --git a/SOURCES/0034-journald-accept-EPOLLERR-from-dev-kmsg.patch b/SOURCES/0034-journald-accept-EPOLLERR-from-dev-kmsg.patch new file mode 100644 index 0000000..decdec9 --- /dev/null +++ b/SOURCES/0034-journald-accept-EPOLLERR-from-dev-kmsg.patch @@ -0,0 +1,69 @@ +From 21deaace3a2ce9531443279a7c36a0fc068bdea7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Thu, 19 Sep 2013 16:57:57 -0500 +Subject: [PATCH] journald: accept EPOLLERR from /dev/kmsg + +Also print out unexpected epoll events explictly. +--- + src/journal/journald-server.c | 20 +++++++++++++++----- + 1 file changed, 15 insertions(+), 5 deletions(-) + +diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c +index ba211b3..c252710 100644 +--- a/src/journal/journald-server.c ++++ b/src/journal/journald-server.c +@@ -1075,7 +1075,8 @@ int process_event(Server *s, struct epoll_event *ev) { + ssize_t n; + + if (ev->events != EPOLLIN) { +- log_error("Got invalid event from epoll."); ++ log_error("Got invalid event from epoll for %s: %"PRIx32, ++ "signal fd", ev->events); + return -EIO; + } + +@@ -1128,8 +1129,12 @@ int process_event(Server *s, struct epoll_event *ev) { + } else if (ev->data.fd == s->dev_kmsg_fd) { + int r; + +- if (ev->events != EPOLLIN) { +- log_error("Got invalid event from epoll."); ++ if (ev->events & EPOLLERR) ++ log_warning("/dev/kmsg buffer overrun, some messages lost."); ++ ++ if (!(ev->events & EPOLLIN)) { ++ log_error("Got invalid event from epoll for %s: %"PRIx32, ++ "/dev/kmsg", ev->events); + return -EIO; + } + +@@ -1143,7 +1148,9 @@ int process_event(Server *s, struct epoll_event *ev) { + ev->data.fd == s->syslog_fd) { + + if (ev->events != EPOLLIN) { +- log_error("Got invalid event from epoll."); ++ log_error("Got invalid event from epoll for %s: %"PRIx32, ++ ev->data.fd == s->native_fd ? "native fd" : "syslog fd", ++ ev->events); + return -EIO; + } + +@@ -1264,7 +1271,8 @@ int process_event(Server *s, struct epoll_event *ev) { + } else if (ev->data.fd == s->stdout_fd) { + + if (ev->events != EPOLLIN) { +- log_error("Got invalid event from epoll."); ++ log_error("Got invalid event from epoll for %s: %"PRIx32, ++ "stdout fd", ev->events); + return -EIO; + } + +@@ -1275,6 +1283,8 @@ int process_event(Server *s, struct epoll_event *ev) { + StdoutStream *stream; + + if ((ev->events|EPOLLIN|EPOLLHUP) != (EPOLLIN|EPOLLHUP)) { ++ log_error("Got invalid event from epoll for %s: %"PRIx32, ++ "stdout stream", ev->events); + log_error("Got invalid event from epoll."); + return -EIO; + } diff --git a/SOURCES/0035-journald-avoid-NSS-in-journald.patch b/SOURCES/0035-journald-avoid-NSS-in-journald.patch new file mode 100644 index 0000000..fb5de56 --- /dev/null +++ b/SOURCES/0035-journald-avoid-NSS-in-journald.patch @@ -0,0 +1,89 @@ +From 6359b8041144a0571853b1dcad55ad60922af55d Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 17 Sep 2013 16:42:36 -0500 +Subject: [PATCH] journald: avoid NSS in journald + +In order to avoid a deadlock between journald looking up the +"systemd-journal" group name, and nscd (or anyother NSS backing daemon) +logging something back to the journal avoid all NSS in journald the same +way as we avoid it from PID 1. + +With this change we rely on the kernel file system logic to adjust the +group of created journal files via the SETGID bit on the journal +directory. To ensure that it is always set, even after the user created +it with a simply "mkdir" on the shell we fix it up via tmpfiles on boot. +--- + src/journal/journald-server.c | 25 ++----------------------- + src/journal/journald-server.h | 3 --- + tmpfiles.d/systemd.conf | 3 +++ + 3 files changed, 5 insertions(+), 26 deletions(-) + +diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c +index c252710..8007b05 100644 +--- a/src/journal/journald-server.c ++++ b/src/journal/journald-server.c +@@ -180,25 +180,6 @@ static uint64_t available_space(Server *s, bool verbose) { + return s->cached_available_space; + } + +-static void server_read_file_gid(Server *s) { +- const char *g = "systemd-journal"; +- int r; +- +- assert(s); +- +- if (s->file_gid_valid) +- return; +- +- r = get_group_creds(&g, &s->file_gid); +- if (r < 0) +- log_warning("Failed to resolve '%s' group: %s", g, strerror(-r)); +- +- /* if we couldn't read the gid, then it will be 0, but that's +- * fine and we shouldn't try to resolve the group again, so +- * let's just pretend it worked right-away. */ +- s->file_gid_valid = true; +-} +- + void server_fix_perms(Server *s, JournalFile *f, uid_t uid) { + int r; + #ifdef HAVE_ACL +@@ -209,11 +190,9 @@ void server_fix_perms(Server *s, JournalFile *f, uid_t uid) { + + assert(f); + +- server_read_file_gid(s); +- +- r = fchmod_and_fchown(f->fd, 0640, 0, s->file_gid); ++ r = fchmod(f->fd, 0640); + if (r < 0) +- log_warning("Failed to fix access mode/rights on %s, ignoring: %s", f->path, strerror(-r)); ++ log_warning("Failed to fix access mode on %s, ignoring: %s", f->path, strerror(-r)); + + #ifdef HAVE_ACL + if (uid <= 0) +diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h +index e856ef2..0393e38 100644 +--- a/src/journal/journald-server.h ++++ b/src/journal/journald-server.h +@@ -97,9 +97,6 @@ typedef struct Server { + usec_t max_file_usec; + usec_t oldest_file_usec; + +- gid_t file_gid; +- bool file_gid_valid; +- + LIST_HEAD(StdoutStream, stdout_streams); + unsigned n_stdout_streams; + +diff --git a/tmpfiles.d/systemd.conf b/tmpfiles.d/systemd.conf +index 4924b4e..c397c71 100644 +--- a/tmpfiles.d/systemd.conf ++++ b/tmpfiles.d/systemd.conf +@@ -23,3 +23,6 @@ d /run/systemd/machines 0755 root root - + d /run/systemd/shutdown 0755 root root - + + F /run/nologin 0644 - - - "System is booting up." ++ ++m /var/log/journal 2755 root systemd-journal - - ++m /var/log/journal/%m 2755 root systemd-journal - - diff --git a/SOURCES/0036-libudev-add-missing-global-to-symbol-export.patch b/SOURCES/0036-libudev-add-missing-global-to-symbol-export.patch new file mode 100644 index 0000000..0afb8f6 --- /dev/null +++ b/SOURCES/0036-libudev-add-missing-global-to-symbol-export.patch @@ -0,0 +1,20 @@ +From 23e9bb8dc174e2418c852361ee4ca7dc0474b879 Mon Sep 17 00:00:00 2001 +From: Kay Sievers +Date: Tue, 17 Sep 2013 16:37:42 -0500 +Subject: [PATCH] libudev: add missing 'global' to symbol export + +--- + src/libudev/libudev.sym | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/libudev/libudev.sym b/src/libudev/libudev.sym +index 8e09430..1e6f885 100644 +--- a/src/libudev/libudev.sym ++++ b/src/libudev/libudev.sym +@@ -109,5 +109,6 @@ global: + } LIBUDEV_189; + + LIBUDEV_199 { ++global: + udev_device_set_sysattr_value; + } LIBUDEV_196; diff --git a/SOURCES/0037-gpt-auto-generator-do-not-assume-that-dev-block-u-u-.patch b/SOURCES/0037-gpt-auto-generator-do-not-assume-that-dev-block-u-u-.patch new file mode 100644 index 0000000..262b269 --- /dev/null +++ b/SOURCES/0037-gpt-auto-generator-do-not-assume-that-dev-block-u-u-.patch @@ -0,0 +1,206 @@ +From cb6800ec93c7d49f5f43355fef44f6797759cc0a Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 17 Sep 2013 18:04:40 -0500 +Subject: [PATCH] gpt-auto-generator: do not assume that /dev/block/%u:%u is + useable + +The generator might run before udev, and udev sets up the /dev/block/ +symlinks, hence we cannot use them from the gpt generator. Instead, +manually translate a major/minor to a device node. +--- + src/gpt-auto-generator/gpt-auto-generator.c | 109 +++++++++++++++++++--------- + 1 file changed, 74 insertions(+), 35 deletions(-) + +diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c +index 880661e..ca54925 100644 +--- a/src/gpt-auto-generator/gpt-auto-generator.c ++++ b/src/gpt-auto-generator/gpt-auto-generator.c +@@ -55,18 +55,13 @@ static inline void blkid_free_probep(blkid_probe *b) { + } + #define _cleanup_blkid_freep_probe_ _cleanup_(blkid_free_probep) + +-static int verify_gpt_partition(dev_t dev, sd_id128_t *type, unsigned *nr, char **fstype) { +- _cleanup_free_ char *t = NULL; ++static int verify_gpt_partition(const char *node, sd_id128_t *type, unsigned *nr, char **fstype) { + _cleanup_blkid_freep_probe_ blkid_probe b = NULL; + const char *v; + int r; + +- r = asprintf(&t, "/dev/block/%u:%u", major(dev), minor(dev)); +- if (r < 0) +- return -ENOMEM; +- + errno = 0; +- b = blkid_new_probe_from_filename(t); ++ b = blkid_new_probe_from_filename(node); + if (!b) + return errno != 0 ? -errno : -ENOMEM; + +@@ -237,8 +232,7 @@ static int add_home(const char *path, const char *fstype) { + return 0; + } + +-static int enumerate_partitions(dev_t dev) { +- struct udev *udev; ++static int enumerate_partitions(struct udev *udev, dev_t dev) { + struct udev_enumerate *e = NULL; + struct udev_device *parent = NULL, *d = NULL; + struct udev_list_entry *first, *item; +@@ -246,10 +240,6 @@ static int enumerate_partitions(dev_t dev) { + _cleanup_free_ char *home = NULL, *home_fstype = NULL; + int r; + +- udev = udev_new(); +- if (!udev) +- return log_oom(); +- + e = udev_enumerate_new(udev); + if (!e) { + r = log_oom(); +@@ -294,7 +284,6 @@ static int enumerate_partitions(dev_t dev) { + struct udev_device *q; + sd_id128_t type_id; + unsigned nr; +- dev_t sub; + + q = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item)); + if (!q) { +@@ -314,12 +303,10 @@ static int enumerate_partitions(dev_t dev) { + goto finish; + } + +- sub = udev_device_get_devnum(q); +- +- r = verify_gpt_partition(sub, &type_id, &nr, &fstype); ++ r = verify_gpt_partition(node, &type_id, &nr, &fstype); + if (r < 0) { +- log_error("Failed to verify GPT partition /dev/block/%u:%u: %s", +- major(sub), minor(sub), strerror(-r)); ++ log_error("Failed to verify GPT partition %s: %s", ++ node, strerror(-r)); + udev_device_unref(q); + goto finish; + } +@@ -360,8 +347,6 @@ finish: + if (e) + udev_enumerate_unref(e); + +- if (udev) +- udev_unref(udev); + + return r; + } +@@ -440,13 +425,50 @@ static int get_block_device(const char *path, dev_t *dev) { + return 0; + } + ++static int devno_to_devnode(struct udev *udev, dev_t devno, char **ret) { ++ struct udev_device *d = NULL; ++ const char *t; ++ char *n; ++ int r; ++ ++ d = udev_device_new_from_devnum(udev, 'b', devno); ++ if (!d) { ++ r = log_oom(); ++ goto finish; ++ } ++ ++ t = udev_device_get_devnode(d); ++ if (!t) { ++ r = -ENODEV; ++ goto finish; ++ } ++ ++ n = strdup(t); ++ if (!n) { ++ r = -ENOMEM; ++ goto finish; ++ } ++ ++ *ret = n; ++ r = 0; ++ ++finish: ++ if (d) ++ udev_device_unref(d); ++ ++ return r; ++} ++ + int main(int argc, char *argv[]) { +- dev_t dev; ++ _cleanup_free_ char *node = NULL; ++ struct udev *udev = NULL; ++ dev_t devno; + int r; + + if (argc > 1 && argc != 4) { + log_error("This program takes three or no arguments."); +- return EXIT_FAILURE; ++ r = -EINVAL; ++ goto finish; + } + + if (argc > 1) +@@ -458,31 +480,48 @@ int main(int argc, char *argv[]) { + + umask(0022); + +- if (in_initrd()) +- return EXIT_SUCCESS; ++ if (in_initrd()) { ++ r = 0; ++ goto finish; ++ } + +- r = get_block_device("/", &dev); ++ r = get_block_device("/", &devno); + if (r < 0) { + log_error("Failed to determine block device of root file system: %s", strerror(-r)); +- return EXIT_FAILURE; ++ goto finish; + } + if (r == 0) { + log_debug("Root file system not on a (single) block device."); +- return EXIT_SUCCESS; ++ goto finish; ++ } ++ ++ udev = udev_new(); ++ if (!udev) { ++ r = log_oom(); ++ goto finish; ++ } ++ ++ r = devno_to_devnode(udev, devno, &node); ++ if (r < 0) { ++ log_error("Failed to determine block device node from major/minor: %s", strerror(-r)); ++ goto finish; + } + +- log_debug("Root device /dev/block/%u:%u.", major(dev), minor(dev)); ++ log_debug("Root device %s.", node); + +- r = verify_gpt_partition(dev, NULL, NULL, NULL); ++ r = verify_gpt_partition(node, NULL, NULL, NULL); + if (r < 0) { +- log_error("Failed to verify GPT partition /dev/block/%u:%u: %s", +- major(dev), minor(dev), strerror(-r)); +- return EXIT_FAILURE; ++ log_error("Failed to verify GPT partition %s: %s", node, strerror(-r)); ++ goto finish; + } + if (r == 0) +- return EXIT_SUCCESS; ++ goto finish; ++ ++ r = enumerate_partitions(udev, devno); + +- r = enumerate_partitions(dev); ++finish: ++ if (udev) ++ udev_unref(udev); + + return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; + } diff --git a/SOURCES/0038-logind-put-correct-user-object-paths-in-introspectio.patch b/SOURCES/0038-logind-put-correct-user-object-paths-in-introspectio.patch new file mode 100644 index 0000000..1ff1c8b --- /dev/null +++ b/SOURCES/0038-logind-put-correct-user-object-paths-in-introspectio.patch @@ -0,0 +1,23 @@ +From 31ad5f9f7291e5f97e62402f3198c9a5161548c1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Mantas=20Mikul=C4=97nas?= +Date: Fri, 20 Sep 2013 18:14:02 +0300 +Subject: [PATCH] logind: put correct user object paths in introspection data + +Sync with user_bus_path() in logind-user-dbus.c +--- + src/login/logind-dbus.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c +index d052e74..77dda10 100644 +--- a/src/login/logind-dbus.c ++++ b/src/login/logind-dbus.c +@@ -2256,7 +2256,7 @@ static DBusHandlerResult manager_message_handler( + } + + HASHMAP_FOREACH(user, m->users, i) +- fprintf(f, "", (unsigned long long) user->uid); ++ fprintf(f, "", (unsigned long long) user->uid); + + HASHMAP_FOREACH(session, m->sessions, i) { + p = bus_path_escape(session->id); diff --git a/SOURCES/0039-Fix-obsolete-references-to-systemd-random-seed-load..patch b/SOURCES/0039-Fix-obsolete-references-to-systemd-random-seed-load..patch new file mode 100644 index 0000000..fba35b4 --- /dev/null +++ b/SOURCES/0039-Fix-obsolete-references-to-systemd-random-seed-load..patch @@ -0,0 +1,38 @@ +From fc8c5e4ff8248fa5548de63a5b96d1d9cf2be425 Mon Sep 17 00:00:00 2001 +From: Eelco Dolstra +Date: Sun, 22 Sep 2013 20:38:24 +0200 +Subject: [PATCH] Fix obsolete references to systemd-random-seed-load.service + +This service was merged with systemd-random-seed-save.service in +c35b956d34bbb8bb208e49e45de2c103ca11911c. +--- + src/cryptsetup/cryptsetup-generator.c | 2 +- + units/systemd-random-seed.service.in | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c +index ba6efa6..8792e6b 100644 +--- a/src/cryptsetup/cryptsetup-generator.c ++++ b/src/cryptsetup/cryptsetup-generator.c +@@ -129,7 +129,7 @@ static int create_disk( + if (streq(password, "/dev/urandom") || + streq(password, "/dev/random") || + streq(password, "/dev/hw_random")) +- fputs("After=systemd-random-seed-load.service\n", f); ++ fputs("After=systemd-random-seed.service\n", f); + else if (!streq(password, "-") && + !streq(password, "none")) + fprintf(f, +diff --git a/units/systemd-random-seed.service.in b/units/systemd-random-seed.service.in +index 0c21a04..1879b2f 100644 +--- a/units/systemd-random-seed.service.in ++++ b/units/systemd-random-seed.service.in +@@ -7,7 +7,7 @@ + + [Unit] + Description=Load/Save Random Seed +-Documentation=man:systemd-random-seed-load.service(8) man:random(4) ++Documentation=man:systemd-random-seed.service(8) man:random(4) + DefaultDependencies=no + RequiresMountsFor=@RANDOM_SEED@ + Conflicts=shutdown.target diff --git a/SOURCES/0040-cgroup-always-enable-memory.use_hierarchy-for-all-cg.patch b/SOURCES/0040-cgroup-always-enable-memory.use_hierarchy-for-all-cg.patch new file mode 100644 index 0000000..eaa35ea --- /dev/null +++ b/SOURCES/0040-cgroup-always-enable-memory.use_hierarchy-for-all-cg.patch @@ -0,0 +1,28 @@ +From 91d2bf71864a1cb9f1228b65b126f5d74d8e09b9 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 23 Sep 2013 16:02:31 -0500 +Subject: [PATCH] cgroup: always enable memory.use_hierarchy= for all cgroups + in the memory hierarchy + +The non-hierarchial mode contradicts the whole idea of a cgroup tree so +let's not support this. In the future the kernel will only support the +hierarchial logic anyway. +--- + src/core/cgroup.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/core/cgroup.c b/src/core/cgroup.c +index 7f29afb..24a2306 100644 +--- a/src/core/cgroup.c ++++ b/src/core/cgroup.c +@@ -256,8 +256,9 @@ void cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const cha + } + + if (mask & CGROUP_MEMORY) { +- char buf[DECIMAL_STR_MAX(uint64_t) + 1]; + if (c->memory_limit != (uint64_t) -1) { ++ char buf[DECIMAL_STR_MAX(uint64_t) + 1]; ++ + sprintf(buf, "%" PRIu64 "\n", c->memory_limit); + r = cg_set_attribute("memory", path, "memory.limit_in_bytes", buf); + } else diff --git a/SOURCES/0041-journalctl-1-s-adm-systemd-journal.patch b/SOURCES/0041-journalctl-1-s-adm-systemd-journal.patch new file mode 100644 index 0000000..f82532f --- /dev/null +++ b/SOURCES/0041-journalctl-1-s-adm-systemd-journal.patch @@ -0,0 +1,22 @@ +From 07da21cf4de7428cc2016333f8ae774fcab6e9fd Mon Sep 17 00:00:00 2001 +From: Dave Reisner +Date: Tue, 24 Sep 2013 14:39:40 -0400 +Subject: [PATCH] journalctl(1): s/adm/systemd-journal/ + +--- + man/journalctl.xml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/man/journalctl.xml b/man/journalctl.xml +index a5778bf..b5a0c53 100644 +--- a/man/journalctl.xml ++++ b/man/journalctl.xml +@@ -104,7 +104,7 @@ + + All users are granted access to their private + per-user journals. However, by default, only root and +- users who are members of the adm ++ users who are members of the systemd-journal + group get access to the system journal and the + journals of other users. + diff --git a/SOURCES/0042-cgroup-if-we-do-a-cgroup-operation-then-do-something.patch b/SOURCES/0042-cgroup-if-we-do-a-cgroup-operation-then-do-something.patch new file mode 100644 index 0000000..627c665 --- /dev/null +++ b/SOURCES/0042-cgroup-if-we-do-a-cgroup-operation-then-do-something.patch @@ -0,0 +1,422 @@ +From 9c9e7b8fffbb21009d39a90076542e553a5c2190 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 23 Sep 2013 21:56:05 -0500 +Subject: [PATCH] cgroup: if we do a cgroup operation then do something on all + supported controllers + +Previously we did operations like attach, trim or migrate only on the +controllers that were enabled for a specific unit. With this changes we +will now do them for all supproted controllers, and fall back to all +possible prefix paths if the specified paths do not exist. + +This fixes issues if a controller is being disabled for a unit where it +was previously enabled, and makes sure that all processes stay as "far +down" the tree as groups exist. +--- + src/core/cgroup.c | 8 +-- + src/core/execute.c | 4 +- + src/core/mount.c | 2 +- + src/core/scope.c | 2 +- + src/core/service.c | 2 +- + src/core/socket.c | 2 +- + src/core/swap.c | 2 +- + src/shared/cgroup-util.c | 154 ++++++++++++++++++++++++++++++----------------- + src/shared/cgroup-util.h | 12 ++-- + 9 files changed, 118 insertions(+), 70 deletions(-) + +diff --git a/src/core/cgroup.c b/src/core/cgroup.c +index 24a2306..2f1e4a3 100644 +--- a/src/core/cgroup.c ++++ b/src/core/cgroup.c +@@ -409,13 +409,13 @@ static int unit_create_cgroups(Unit *u, CGroupControllerMask mask) { + } + + /* First, create our own group */ +- r = cg_create_with_mask(mask, path); ++ r = cg_create_everywhere(u->manager->cgroup_supported, mask, path); + if (r < 0) + log_error("Failed to create cgroup %s: %s", path, strerror(-r)); + + /* Then, possibly move things over */ +- if (u->cgroup_path && !streq(path, u->cgroup_path)) { +- r = cg_migrate_with_mask(mask, u->cgroup_path, path); ++ if (u->cgroup_path) { ++ r = cg_migrate_everywhere(u->manager->cgroup_supported, u->cgroup_path, path); + if (r < 0) + log_error("Failed to migrate cgroup %s: %s", path, strerror(-r)); + } +@@ -549,7 +549,7 @@ void unit_destroy_cgroup(Unit *u) { + if (!u->cgroup_path) + return; + +- r = cg_trim_with_mask(u->cgroup_mask, u->cgroup_path, !unit_has_name(u, SPECIAL_ROOT_SLICE)); ++ r = cg_trim_everywhere(u->manager->cgroup_supported, u->cgroup_path, !unit_has_name(u, SPECIAL_ROOT_SLICE)); + if (r < 0) + log_debug("Failed to destroy cgroup %s: %s", u->cgroup_path, strerror(-r)); + +diff --git a/src/core/execute.c b/src/core/execute.c +index 43b571e..789122e 100644 +--- a/src/core/execute.c ++++ b/src/core/execute.c +@@ -1016,7 +1016,7 @@ int exec_spawn(ExecCommand *command, + bool apply_chroot, + bool apply_tty_stdin, + bool confirm_spawn, +- CGroupControllerMask cgroup_mask, ++ CGroupControllerMask cgroup_supported, + const char *cgroup_path, + const char *unit_id, + int idle_pipe[4], +@@ -1197,7 +1197,7 @@ int exec_spawn(ExecCommand *command, + } + + if (cgroup_path) { +- err = cg_attach_with_mask(cgroup_mask, cgroup_path, 0); ++ err = cg_attach_everywhere(cgroup_supported, cgroup_path, 0); + if (err < 0) { + r = EXIT_CGROUP; + goto fail_child; +diff --git a/src/core/mount.c b/src/core/mount.c +index 5c18d4e..78c5c1e 100644 +--- a/src/core/mount.c ++++ b/src/core/mount.c +@@ -888,7 +888,7 @@ static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) { + true, + true, + UNIT(m)->manager->confirm_spawn, +- UNIT(m)->cgroup_mask, ++ UNIT(m)->manager->cgroup_supported, + UNIT(m)->cgroup_path, + UNIT(m)->id, + NULL, +diff --git a/src/core/scope.c b/src/core/scope.c +index b94f3ff..50e5dba 100644 +--- a/src/core/scope.c ++++ b/src/core/scope.c +@@ -257,7 +257,7 @@ static int scope_start(Unit *u) { + return r; + } + +- r = cg_attach_many_with_mask(u->cgroup_mask, u->cgroup_path, s->pids); ++ r = cg_attach_many_everywhere(u->manager->cgroup_supported, u->cgroup_path, s->pids); + if (r < 0) + return r; + +diff --git a/src/core/service.c b/src/core/service.c +index 5953f45..fc04196 100644 +--- a/src/core/service.c ++++ b/src/core/service.c +@@ -1826,7 +1826,7 @@ static int service_spawn( + apply_chroot, + apply_tty_stdin, + UNIT(s)->manager->confirm_spawn, +- UNIT(s)->cgroup_mask, ++ UNIT(s)->manager->cgroup_supported, + path, + UNIT(s)->id, + s->type == SERVICE_IDLE ? UNIT(s)->manager->idle_pipe : NULL, +diff --git a/src/core/socket.c b/src/core/socket.c +index 2130e48..25c2a51 100644 +--- a/src/core/socket.c ++++ b/src/core/socket.c +@@ -1241,7 +1241,7 @@ static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) { + true, + true, + UNIT(s)->manager->confirm_spawn, +- UNIT(s)->cgroup_mask, ++ UNIT(s)->manager->cgroup_supported, + UNIT(s)->cgroup_path, + UNIT(s)->id, + NULL, +diff --git a/src/core/swap.c b/src/core/swap.c +index 76c7d45..d225485 100644 +--- a/src/core/swap.c ++++ b/src/core/swap.c +@@ -625,7 +625,7 @@ static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) { + true, + true, + UNIT(s)->manager->confirm_spawn, +- UNIT(s)->cgroup_mask, ++ UNIT(s)->manager->cgroup_supported, + UNIT(s)->cgroup_path, + UNIT(s)->id, + NULL, +diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c +index 0bffebd..2e630d4 100644 +--- a/src/shared/cgroup-util.c ++++ b/src/shared/cgroup-util.c +@@ -435,6 +435,46 @@ int cg_migrate_recursive( + return ret; + } + ++int cg_migrate_recursive_fallback( ++ const char *cfrom, ++ const char *pfrom, ++ const char *cto, ++ const char *pto, ++ bool ignore_self, ++ bool rem) { ++ ++ int r; ++ ++ assert(cfrom); ++ assert(pfrom); ++ assert(cto); ++ assert(pto); ++ ++ r = cg_migrate_recursive(cfrom, pfrom, cto, pto, ignore_self, rem); ++ if (r < 0) { ++ char prefix[strlen(pto) + 1]; ++ ++ /* This didn't work? Then let's try all prefixes of the destination */ ++ ++ strcpy(prefix, pto); ++ for (;;) { ++ char *slash; ++ ++ slash = strrchr(prefix, '/'); ++ if (!slash) ++ break; ++ ++ *slash = 0; ++ ++ r = cg_migrate_recursive(cfrom, pfrom, cto, prefix, ignore_self, rem); ++ if (r >= 0) ++ break; ++ } ++ } ++ ++ return r; ++} ++ + static const char *normalize_controller(const char *controller) { + + assert(controller); +@@ -607,6 +647,39 @@ int cg_attach(const char *controller, const char *path, pid_t pid) { + return write_string_file(fs, c); + } + ++int cg_attach_fallback(const char *controller, const char *path, pid_t pid) { ++ int r; ++ ++ assert(controller); ++ assert(path); ++ assert(pid >= 0); ++ ++ r = cg_attach(controller, path, pid); ++ if (r < 0) { ++ char prefix[strlen(path) + 1]; ++ ++ /* This didn't work? Then let's try all prefixes of ++ * the destination */ ++ ++ strcpy(prefix, path); ++ for (;;) { ++ char *slash; ++ ++ slash = strrchr(prefix, '/'); ++ if (!slash) ++ break; ++ ++ *slash = 0; ++ ++ r = cg_attach(controller, prefix, pid); ++ if (r >= 0) ++ break; ++ } ++ } ++ ++ return r; ++} ++ + int cg_set_group_access( + const char *controller, + const char *path, +@@ -1607,7 +1680,7 @@ static const char mask_names[] = + "memory\0" + "devices\0"; + +-int cg_create_with_mask(CGroupControllerMask mask, const char *path) { ++int cg_create_everywhere(CGroupControllerMask supported, CGroupControllerMask mask, const char *path) { + CGroupControllerMask bit = 1; + const char *n; + int r; +@@ -1623,102 +1696,75 @@ int cg_create_with_mask(CGroupControllerMask mask, const char *path) { + + /* Then, do the same in the other hierarchies */ + NULSTR_FOREACH(n, mask_names) { +- if (bit & mask) ++ if (mask & bit) + cg_create(n, path); +- else ++ else if (supported & bit) + cg_trim(n, path, true); + + bit <<= 1; + } + +- return r; ++ return 0; + } + +-int cg_attach_with_mask(CGroupControllerMask mask, const char *path, pid_t pid) { ++int cg_attach_everywhere(CGroupControllerMask supported, const char *path, pid_t pid) { + CGroupControllerMask bit = 1; + const char *n; + int r; + + r = cg_attach(SYSTEMD_CGROUP_CONTROLLER, path, pid); ++ if (r < 0) ++ return r; + + NULSTR_FOREACH(n, mask_names) { +- if (bit & mask) +- cg_attach(n, path, pid); +- else { +- char prefix[strlen(path) + 1], *slash; +- +- /* OK, this one is a bit harder... Now we need +- * to add to the closest parent cgroup we +- * can find */ +- strcpy(prefix, path); +- while ((slash = strrchr(prefix, '/'))) { +- int q; +- *slash = 0; +- +- q = cg_attach(n, prefix, pid); +- if (q >= 0) +- break; +- } +- } ++ if (supported & bit) ++ cg_attach_fallback(n, path, pid); + + bit <<= 1; + } + +- return r; ++ return 0; + } + +-int cg_attach_many_with_mask(CGroupControllerMask mask, const char *path, Set* pids) { ++int cg_attach_many_everywhere(CGroupControllerMask supported, const char *path, Set* pids) { + Iterator i; + void *pidp; + int r = 0; + + SET_FOREACH(pidp, pids, i) { + pid_t pid = PTR_TO_LONG(pidp); +- int k; ++ int q; + +- k = cg_attach_with_mask(mask, path, pid); +- if (k < 0) +- r = k; ++ q = cg_attach_everywhere(supported, path, pid); ++ if (q < 0) ++ r = q; + } + + return r; + } + +-int cg_migrate_with_mask(CGroupControllerMask mask, const char *from, const char *to) { ++int cg_migrate_everywhere(CGroupControllerMask supported, const char *from, const char *to) { + CGroupControllerMask bit = 1; + const char *n; + int r; + +- if (path_equal(from, to)) +- return 0; +- +- r = cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, from, SYSTEMD_CGROUP_CONTROLLER, to, false, true); ++ if (!path_equal(from, to)) { ++ r = cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, from, SYSTEMD_CGROUP_CONTROLLER, to, false, true); ++ if (r < 0) ++ return r; ++ } + + NULSTR_FOREACH(n, mask_names) { +- if (bit & mask) +- cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, to, n, to, false, false); +- else { +- char prefix[strlen(to) + 1], *slash; +- +- strcpy(prefix, to); +- while ((slash = strrchr(prefix, '/'))) { +- int q; +- +- *slash = 0; +- +- q = cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, to, n, prefix, false, false); +- if (q >= 0) +- break; +- } +- } ++ if (supported & bit) ++ cg_migrate_recursive_fallback(SYSTEMD_CGROUP_CONTROLLER, to, n, to, false, false); + + bit <<= 1; + } + +- return r; ++ return 0; + } + +-int cg_trim_with_mask(CGroupControllerMask mask, const char *path, bool delete_root) { ++int cg_trim_everywhere(CGroupControllerMask supported, const char *path, bool delete_root) { + CGroupControllerMask bit = 1; + const char *n; + int r; +@@ -1728,13 +1774,13 @@ int cg_trim_with_mask(CGroupControllerMask mask, const char *path, bool delete_r + return r; + + NULSTR_FOREACH(n, mask_names) { +- if (bit & mask) ++ if (supported & bit) + cg_trim(n, path, delete_root); + + bit <<= 1; + } + +- return r; ++ return 0; + } + + CGroupControllerMask cg_mask_supported(void) { +diff --git a/src/shared/cgroup-util.h b/src/shared/cgroup-util.h +index 0fc93c1..0963450 100644 +--- a/src/shared/cgroup-util.h ++++ b/src/shared/cgroup-util.h +@@ -64,6 +64,7 @@ int cg_kill_recursive_and_wait(const char *controller, const char *path, bool re + + int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self); + int cg_migrate_recursive(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self, bool remove); ++int cg_migrate_recursive_fallback(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self, bool rem); + + int cg_split_spec(const char *spec, char **controller, char **path); + int cg_join_spec(const char *controller, const char *path, char **spec); +@@ -81,6 +82,7 @@ int cg_delete(const char *controller, const char *path); + + int cg_create(const char *controller, const char *path); + int cg_attach(const char *controller, const char *path, pid_t pid); ++int cg_attach_fallback(const char *controller, const char *path, pid_t pid); + int cg_create_and_attach(const char *controller, const char *path, pid_t pid); + + int cg_set_attribute(const char *controller, const char *path, const char *attribute, const char *value); +@@ -126,10 +128,10 @@ bool cg_controller_is_valid(const char *p, bool allow_named); + + int cg_slice_to_path(const char *unit, char **ret); + +-int cg_create_with_mask(CGroupControllerMask mask, const char *path); +-int cg_attach_with_mask(CGroupControllerMask mask, const char *path, pid_t pid); +-int cg_attach_many_with_mask(CGroupControllerMask mask, const char *path, Set* pids); +-int cg_migrate_with_mask(CGroupControllerMask mask, const char *from, const char *to); +-int cg_trim_with_mask(CGroupControllerMask mask, const char *path, bool delete_root); ++int cg_create_everywhere(CGroupControllerMask supported, CGroupControllerMask mask, const char *path); ++int cg_attach_everywhere(CGroupControllerMask supported, const char *path, pid_t pid); ++int cg_attach_many_everywhere(CGroupControllerMask supported, const char *path, Set* pids); ++int cg_migrate_everywhere(CGroupControllerMask supported, const char *from, const char *to); ++int cg_trim_everywhere(CGroupControllerMask supported, const char *path, bool delete_root); + + CGroupControllerMask cg_mask_supported(void); diff --git a/SOURCES/0043-core-rework-how-we-match-mount-units-against-each-ot.patch b/SOURCES/0043-core-rework-how-we-match-mount-units-against-each-ot.patch new file mode 100644 index 0000000..6376705 --- /dev/null +++ b/SOURCES/0043-core-rework-how-we-match-mount-units-against-each-ot.patch @@ -0,0 +1,1156 @@ +From f0af1f20acc04b744f4ce1ed4b028e84576541d7 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 26 Sep 2013 20:14:24 +0200 +Subject: [PATCH] core: rework how we match mount units against each other + +Previously to automatically create dependencies between mount units we +matched every mount unit agains all others resulting in O(n^2) +complexity. On setups with large amounts of mount units this might make +things slow. + +This change replaces the matching code to use a hashtable that is keyed +by a path prefix, and points to a set of units that require that path to +be around. When a new mount unit is installed it is hence sufficient to +simply look up this set of units via its own file system paths to know +which units to order after itself. + +This patch also changes all unit types to only create automatic mount +dependencies via the RequiresMountsFor= logic, and this is exposed to +the outside to make things more transparent. + +With this change we still have some O(n) complexities in place when +handling mounts, but that's currently unavoidable due to kernel APIs, +and still substantially better than O(n^2) as before. + +https://bugs.freedesktop.org/show_bug.cgi?id=69740 +--- + src/core/automount.c | 33 +---- + src/core/automount.h | 2 - + src/core/load-fragment-gperf.gperf.m4 | 2 +- + src/core/load-fragment.c | 47 ++++--- + src/core/manager.c | 44 +++++- + src/core/manager.h | 12 +- + src/core/mount.c | 255 +++++++++------------------------- + src/core/path.c | 32 +---- + src/core/path.h | 4 - + src/core/socket.c | 49 ++----- + src/core/socket.h | 4 - + src/core/swap.c | 40 +----- + src/core/swap.h | 2 - + src/core/unit.c | 162 +++++++++++++++++---- + src/core/unit.h | 6 +- + src/shared/socket-util.c | 8 +- + src/shared/socket-util.h | 2 +- + 17 files changed, 309 insertions(+), 395 deletions(-) + +diff --git a/src/core/automount.c b/src/core/automount.c +index 6762392..d1379e0 100644 +--- a/src/core/automount.c ++++ b/src/core/automount.c +@@ -117,42 +117,17 @@ static void automount_done(Unit *u) { + a->tokens = NULL; + } + +-int automount_add_one_mount_link(Automount *a, Mount *m) { ++static int automount_add_mount_links(Automount *a) { ++ _cleanup_free_ char *parent = NULL; + int r; + + assert(a); +- assert(m); +- +- if (UNIT(a)->load_state != UNIT_LOADED || +- UNIT(m)->load_state != UNIT_LOADED) +- return 0; +- +- if (!path_startswith(a->where, m->where)) +- return 0; + +- if (path_equal(a->where, m->where)) +- return 0; +- +- r = unit_add_two_dependencies(UNIT(a), UNIT_AFTER, UNIT_REQUIRES, UNIT(m), true); ++ r = path_get_parent(a->where, &parent); + if (r < 0) + return r; + +- return 0; +-} +- +-static int automount_add_mount_links(Automount *a) { +- Unit *other; +- int r; +- +- assert(a); +- +- LIST_FOREACH(units_by_type, other, UNIT(a)->manager->units_by_type[UNIT_MOUNT]) { +- r = automount_add_one_mount_link(a, MOUNT(other)); +- if (r < 0) +- return r; +- } +- +- return 0; ++ return unit_require_mounts_for(UNIT(a), parent); + } + + static int automount_add_default_dependencies(Automount *a) { +diff --git a/src/core/automount.h b/src/core/automount.h +index 0c6b8a7..a7a25d3 100644 +--- a/src/core/automount.h ++++ b/src/core/automount.h +@@ -62,8 +62,6 @@ extern const UnitVTable automount_vtable; + + int automount_send_ready(Automount *a, int status); + +-int automount_add_one_mount_link(Automount *a, Mount *m); +- + const char* automount_state_to_string(AutomountState i) _const_; + AutomountState automount_state_from_string(const char *s) _pure_; + +diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 +index 33c6880..3f064a9 100644 +--- a/src/core/load-fragment-gperf.gperf.m4 ++++ b/src/core/load-fragment-gperf.gperf.m4 +@@ -117,7 +117,7 @@ Unit.PropagateReloadTo, config_parse_unit_deps, UNIT_PROPAG + Unit.ReloadPropagatedFrom, config_parse_unit_deps, UNIT_RELOAD_PROPAGATED_FROM, 0 + Unit.PropagateReloadFrom, config_parse_unit_deps, UNIT_RELOAD_PROPAGATED_FROM, 0 + Unit.PartOf, config_parse_unit_deps, UNIT_PART_OF, 0 +-Unit.RequiresMountsFor, config_parse_unit_requires_mounts_for, 0, offsetof(Unit, requires_mounts_for) ++Unit.RequiresMountsFor, config_parse_unit_requires_mounts_for, 0, 0 + Unit.StopWhenUnneeded, config_parse_bool, 0, offsetof(Unit, stop_when_unneeded) + Unit.RefuseManualStart, config_parse_bool, 0, offsetof(Unit, refuse_manual_start) + Unit.RefuseManualStop, config_parse_bool, 0, offsetof(Unit, refuse_manual_stop) +diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c +index f4a268c..ed8602f 100644 +--- a/src/core/load-fragment.c ++++ b/src/core/load-fragment.c +@@ -1742,33 +1742,48 @@ int config_parse_unit_condition_null(const char *unit, + DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier"); + DEFINE_CONFIG_PARSE_ENUM(config_parse_start_limit_action, start_limit_action, StartLimitAction, "Failed to parse start limit action specifier"); + +-int config_parse_unit_requires_mounts_for(const char *unit, +- const char *filename, +- unsigned line, +- const char *section, +- const char *lvalue, +- int ltype, +- const char *rvalue, +- void *data, +- void *userdata) { ++int config_parse_unit_requires_mounts_for( ++ const char *unit, ++ const char *filename, ++ unsigned line, ++ const char *section, ++ const char *lvalue, ++ int ltype, ++ const char *rvalue, ++ void *data, ++ void *userdata) { + + Unit *u = userdata; ++ char *state; ++ size_t l; ++ char *w; + int r; +- bool empty_before; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + +- empty_before = !u->requires_mounts_for; ++ FOREACH_WORD_QUOTED(w, l, rvalue, state) { ++ _cleanup_free_ char *n; ++ ++ n = strndup(w, l); ++ if (!n) ++ return log_oom(); + +- r = config_parse_path_strv(unit, filename, line, section, lvalue, ltype, +- rvalue, data, userdata); ++ if (!utf8_is_valid(n)) { ++ log_syntax(unit, LOG_ERR, filename, line, EINVAL, ++ "Path is not UTF-8 clean, ignoring assignment: %s", rvalue); ++ continue; ++ } + +- /* Make it easy to find units with requires_mounts set */ +- if (empty_before && u->requires_mounts_for) +- LIST_PREPEND(Unit, has_requires_mounts_for, u->manager->has_requires_mounts_for, u); ++ r = unit_require_mounts_for(u, n); ++ if (r < 0) { ++ log_syntax(unit, LOG_ERR, filename, line, r, ++ "Failed to add required mount for, ignoring: %s", rvalue); ++ continue; ++ } ++ } + + return r; + } +diff --git a/src/core/manager.c b/src/core/manager.c +index 669af15..dadbedd 100644 +--- a/src/core/manager.c ++++ b/src/core/manager.c +@@ -771,6 +771,9 @@ void manager_free(Manager *m) { + for (i = 0; i < RLIMIT_NLIMITS; i++) + free(m->rlimit[i]); + ++ assert(hashmap_isempty(m->units_requiring_mounts_for)); ++ hashmap_free(m->units_requiring_mounts_for); ++ + free(m); + } + +@@ -783,9 +786,11 @@ int manager_enumerate(Manager *m) { + /* Let's ask every type to load all units from disk/kernel + * that it might know */ + for (c = 0; c < _UNIT_TYPE_MAX; c++) +- if (unit_vtable[c]->enumerate) +- if ((q = unit_vtable[c]->enumerate(m)) < 0) ++ if (unit_vtable[c]->enumerate) { ++ q = unit_vtable[c]->enumerate(m); ++ if (q < 0) + r = q; ++ } + + manager_dispatch_load_queue(m); + return r; +@@ -2765,6 +2770,41 @@ void manager_status_printf(Manager *m, bool ephemeral, const char *status, const + va_end(ap); + } + ++int manager_get_unit_by_path(Manager *m, const char *path, const char *suffix, Unit **_found) { ++ _cleanup_free_ char *p = NULL; ++ Unit *found; ++ ++ assert(m); ++ assert(path); ++ assert(suffix); ++ assert(_found); ++ ++ p = unit_name_from_path(path, suffix); ++ if (!p) ++ return -ENOMEM; ++ ++ found = manager_get_unit(m, p); ++ if (!found) { ++ *_found = NULL; ++ return 0; ++ } ++ ++ *_found = found; ++ return 1; ++} ++ ++Set *manager_get_units_requiring_mounts_for(Manager *m, const char *path) { ++ char p[strlen(path)+1]; ++ ++ assert(m); ++ assert(path); ++ ++ strcpy(p, path); ++ path_kill_slashes(p); ++ ++ return hashmap_get(m->units_requiring_mounts_for, streq(p, "/") ? "" : p); ++} ++ + void watch_init(Watch *w) { + assert(w); + +diff --git a/src/core/manager.h b/src/core/manager.h +index 3969553..a3049b5 100644 +--- a/src/core/manager.h ++++ b/src/core/manager.h +@@ -103,9 +103,6 @@ struct Manager { + * type we maintain a per type linked list */ + LIST_HEAD(Unit, units_by_type[_UNIT_TYPE_MAX]); + +- /* To optimize iteration of units that have requires_mounts_for set */ +- LIST_HEAD(Unit, has_requires_mounts_for); +- + /* Units that need to be loaded */ + LIST_HEAD(Unit, load_queue); /* this is actually more a stack than a queue, but uh. */ + +@@ -251,6 +248,11 @@ struct Manager { + + char *switch_root; + char *switch_root_init; ++ ++ /* This maps all possible path prefixes to the units needing ++ * them. It's a hashmap with a path string as key and a Set as ++ * value where Unit objects are contained. */ ++ Hashmap *units_requiring_mounts_for; + }; + + int manager_new(SystemdRunningAs running_as, bool reexecuting, Manager **m); +@@ -263,6 +265,8 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds); + Job *manager_get_job(Manager *m, uint32_t id); + Unit *manager_get_unit(Manager *m, const char *name); + ++int manager_get_unit_by_path(Manager *m, const char *path, const char *suffix, Unit **_found); ++ + int manager_get_job_from_dbus_path(Manager *m, const char *s, Job **_j); + + int manager_load_unit_prepare(Manager *m, const char *name, const char *path, DBusError *e, Unit **_ret); +@@ -316,4 +320,6 @@ void manager_recheck_journal(Manager *m); + void manager_set_show_status(Manager *m, bool b); + void manager_status_printf(Manager *m, bool ephemeral, const char *status, const char *format, ...) _printf_attr_(4,5); + ++Set *manager_get_units_requiring_mounts_for(Manager *m, const char *path); ++ + void watch_init(Watch *w); +diff --git a/src/core/mount.c b/src/core/mount.c +index 78c5c1e..3d46557 100644 +--- a/src/core/mount.c ++++ b/src/core/mount.c +@@ -157,138 +157,58 @@ _pure_ static MountParameters* get_mount_parameters(Mount *m) { + } + + static int mount_add_mount_links(Mount *m) { +- Unit *other; +- int r; ++ _cleanup_free_ char *parent = NULL; + MountParameters *pm; +- +- assert(m); +- +- pm = get_mount_parameters_fragment(m); +- +- /* Adds in links to other mount points that might lie below or +- * above us in the hierarchy */ +- +- LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_MOUNT]) { +- Mount *n = MOUNT(other); +- MountParameters *pn; +- +- if (n == m) +- continue; +- +- if (UNIT(n)->load_state != UNIT_LOADED) +- continue; +- +- pn = get_mount_parameters_fragment(n); +- +- if (path_startswith(m->where, n->where)) { +- +- if ((r = unit_add_dependency(UNIT(m), UNIT_AFTER, UNIT(n), true)) < 0) +- return r; +- +- if (pn) +- if ((r = unit_add_dependency(UNIT(m), UNIT_REQUIRES, UNIT(n), true)) < 0) +- return r; +- +- } else if (path_startswith(n->where, m->where)) { +- +- if ((r = unit_add_dependency(UNIT(n), UNIT_AFTER, UNIT(m), true)) < 0) +- return r; +- +- if (pm) +- if ((r = unit_add_dependency(UNIT(n), UNIT_REQUIRES, UNIT(m), true)) < 0) +- return r; +- +- } else if (pm && pm->what && path_startswith(pm->what, n->where)) { +- +- if ((r = unit_add_dependency(UNIT(m), UNIT_AFTER, UNIT(n), true)) < 0) +- return r; +- +- if ((r = unit_add_dependency(UNIT(m), UNIT_REQUIRES, UNIT(n), true)) < 0) +- return r; +- +- } else if (pn && pn->what && path_startswith(pn->what, m->where)) { +- +- if ((r = unit_add_dependency(UNIT(n), UNIT_AFTER, UNIT(m), true)) < 0) +- return r; +- +- if ((r = unit_add_dependency(UNIT(n), UNIT_REQUIRES, UNIT(m), true)) < 0) +- return r; +- } +- } +- +- return 0; +-} +- +-static int mount_add_swap_links(Mount *m) { + Unit *other; ++ Iterator i; ++ Set *s; + int r; + + assert(m); + +- LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_SWAP]) { +- r = swap_add_one_mount_link(SWAP(other), m); ++ if (!path_equal(m->where, "/")) { ++ /* Adds in links to other mount points that might lie further ++ * up in the hierarchy */ ++ r = path_get_parent(m->where, &parent); + if (r < 0) + return r; +- } + +- return 0; +-} +- +-static int mount_add_path_links(Mount *m) { +- Unit *other; +- int r; +- +- assert(m); +- +- LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_PATH]) { +- r = path_add_one_mount_link(PATH(other), m); ++ r = unit_require_mounts_for(UNIT(m), parent); + if (r < 0) + return r; + } + +- return 0; +-} +- +-static int mount_add_automount_links(Mount *m) { +- Unit *other; +- int r; +- +- assert(m); +- +- LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_AUTOMOUNT]) { +- r = automount_add_one_mount_link(AUTOMOUNT(other), m); ++ /* Adds in links to other mount points that might be needed ++ * for the source path (if this is a bind mount) to be ++ * available. */ ++ pm = get_mount_parameters_fragment(m); ++ if (pm && path_is_absolute(pm->what)) { ++ r = unit_require_mounts_for(UNIT(m), pm->what); + if (r < 0) + return r; + } + +- return 0; +-} ++ /* Adds in links to other units that use this path or paths ++ * further down in the hierarchy */ ++ s = manager_get_units_requiring_mounts_for(UNIT(m)->manager, m->where); ++ SET_FOREACH(other, s, i) { + +-static int mount_add_socket_links(Mount *m) { +- Unit *other; +- int r; ++ if (other->load_state != UNIT_LOADED) ++ continue; + +- assert(m); ++ if (other == UNIT(m)) ++ continue; + +- LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_SOCKET]) { +- r = socket_add_one_mount_link(SOCKET(other), m); ++ r = unit_add_dependency(other, UNIT_AFTER, UNIT(m), true); + if (r < 0) + return r; +- } + +- return 0; +-} +- +-static int mount_add_requires_mounts_links(Mount *m) { +- Unit *other; +- int r; +- +- assert(m); +- +- LIST_FOREACH(has_requires_mounts_for, other, UNIT(m)->manager->has_requires_mounts_for) { +- r = unit_add_one_mount_link(other, m); +- if (r < 0) +- return r; ++ if (UNIT(m)->fragment_path) { ++ /* If we have fragment configuration, then make this dependency required */ ++ r = unit_add_dependency(other, UNIT_REQUIRES, UNIT(m), true); ++ if (r < 0) ++ return r; ++ } + } + + return 0; +@@ -567,8 +487,9 @@ static int mount_fix_timeouts(Mount *m) { + } + + static int mount_verify(Mount *m) { ++ _cleanup_free_ char *e = NULL; + bool b; +- char *e; ++ + assert(m); + + if (UNIT(m)->load_state != UNIT_LOADED) +@@ -577,12 +498,11 @@ static int mount_verify(Mount *m) { + if (!m->from_fragment && !m->from_proc_self_mountinfo) + return -ENOENT; + +- if (!(e = unit_name_from_path(m->where, ".mount"))) ++ e = unit_name_from_path(m->where, ".mount"); ++ if (!e) + return -ENOMEM; + + b = unit_has_name(UNIT(m), e); +- free(e); +- + if (!b) { + log_error_unit(UNIT(m)->id, + "%s's Where setting doesn't match unit name. Refusing.", +@@ -646,26 +566,6 @@ static int mount_add_extras(Mount *m) { + if (r < 0) + return r; + +- r = mount_add_socket_links(m); +- if (r < 0) +- return r; +- +- r = mount_add_swap_links(m); +- if (r < 0) +- return r; +- +- r = mount_add_path_links(m); +- if (r < 0) +- return r; +- +- r = mount_add_requires_mounts_links(m); +- if (r < 0) +- return r; +- +- r = mount_add_automount_links(m); +- if (r < 0) +- return r; +- + r = mount_add_quota_links(m); + if (r < 0) + return r; +@@ -1650,79 +1550,56 @@ fail: + static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) { + int r = 0; + unsigned i; +- char *device, *path, *options, *options2, *fstype, *d, *p, *o; + + assert(m); + + rewind(m->proc_self_mountinfo); + + for (i = 1;; i++) { ++ _cleanup_free_ char *device = NULL, *path = NULL, *options = NULL, *options2 = NULL, *fstype = NULL, *d = NULL, *p = NULL, *o = NULL; + int k; + +- device = path = options = options2 = fstype = d = p = o = NULL; +- +- if ((k = fscanf(m->proc_self_mountinfo, +- "%*s " /* (1) mount id */ +- "%*s " /* (2) parent id */ +- "%*s " /* (3) major:minor */ +- "%*s " /* (4) root */ +- "%ms " /* (5) mount point */ +- "%ms" /* (6) mount options */ +- "%*[^-]" /* (7) optional fields */ +- "- " /* (8) separator */ +- "%ms " /* (9) file system type */ +- "%ms" /* (10) mount source */ +- "%ms" /* (11) mount options 2 */ +- "%*[^\n]", /* some rubbish at the end */ +- &path, +- &options, +- &fstype, +- &device, +- &options2)) != 5) { +- +- if (k == EOF) +- break; +- ++ k = fscanf(m->proc_self_mountinfo, ++ "%*s " /* (1) mount id */ ++ "%*s " /* (2) parent id */ ++ "%*s " /* (3) major:minor */ ++ "%*s " /* (4) root */ ++ "%ms " /* (5) mount point */ ++ "%ms" /* (6) mount options */ ++ "%*[^-]" /* (7) optional fields */ ++ "- " /* (8) separator */ ++ "%ms " /* (9) file system type */ ++ "%ms" /* (10) mount source */ ++ "%ms" /* (11) mount options 2 */ ++ "%*[^\n]", /* some rubbish at the end */ ++ &path, ++ &options, ++ &fstype, ++ &device, ++ &options2); ++ ++ if (k == EOF) ++ break; ++ ++ if (k != 5) { + log_warning("Failed to parse /proc/self/mountinfo:%u.", i); +- goto clean_up; ++ continue; + } + + o = strjoin(options, ",", options2, NULL); +- if (!o) { +- r = -ENOMEM; +- goto finish; +- } ++ if (!o) ++ return log_oom(); + +- if (!(d = cunescape(device)) || +- !(p = cunescape(path))) { +- r = -ENOMEM; +- goto finish; +- } ++ d = cunescape(device); ++ p = cunescape(path); ++ if (!d || !p) ++ return log_oom(); + +- if ((k = mount_add_one(m, d, p, o, fstype, 0, set_flags)) < 0) ++ k = mount_add_one(m, d, p, o, fstype, 0, set_flags); ++ if (k < 0) + r = k; +- +-clean_up: +- free(device); +- free(path); +- free(options); +- free(options2); +- free(fstype); +- free(d); +- free(p); +- free(o); + } + +-finish: +- free(device); +- free(path); +- free(options); +- free(options2); +- free(fstype); +- free(d); +- free(p); +- free(o); +- + return r; + } + +diff --git a/src/core/path.c b/src/core/path.c +index 8a09deb..99e2fed 100644 +--- a/src/core/path.c ++++ b/src/core/path.c +@@ -241,10 +241,6 @@ static bool path_spec_check_good(PathSpec *s, bool initial) { + return good; + } + +-static bool path_spec_startswith(PathSpec *s, const char *what) { +- return path_startswith(s->path, what); +-} +- + static void path_spec_mkdir(PathSpec *s, mode_t mode) { + int r; + +@@ -301,38 +297,14 @@ static void path_done(Unit *u) { + path_free_specs(p); + } + +-int path_add_one_mount_link(Path *p, Mount *m) { ++static int path_add_mount_links(Path *p) { + PathSpec *s; + int r; + + assert(p); +- assert(m); +- +- if (UNIT(p)->load_state != UNIT_LOADED || +- UNIT(m)->load_state != UNIT_LOADED) +- return 0; + + LIST_FOREACH(spec, s, p->specs) { +- if (!path_spec_startswith(s, m->where)) +- continue; +- +- r = unit_add_two_dependencies(UNIT(p), UNIT_AFTER, UNIT_REQUIRES, +- UNIT(m), true); +- if (r < 0) +- return r; +- } +- +- return 0; +-} +- +-static int path_add_mount_links(Path *p) { +- Unit *other; +- int r; +- +- assert(p); +- +- LIST_FOREACH(units_by_type, other, UNIT(p)->manager->units_by_type[UNIT_MOUNT]) { +- r = path_add_one_mount_link(p, MOUNT(other)); ++ r = unit_require_mounts_for(UNIT(p), s->path); + if (r < 0) + return r; + } +diff --git a/src/core/path.h b/src/core/path.h +index 6adab58..dec3df7 100644 +--- a/src/core/path.h ++++ b/src/core/path.h +@@ -90,10 +90,6 @@ struct Path { + PathResult result; + }; + +-/* Called from the mount code figure out if a mount is a dependency of +- * any of the paths of this path object */ +-int path_add_one_mount_link(Path *p, Mount *m); +- + void path_free_specs(Path *p); + + extern const UnitVTable path_vtable; +diff --git a/src/core/socket.c b/src/core/socket.c +index 25c2a51..778f8c8 100644 +--- a/src/core/socket.c ++++ b/src/core/socket.c +@@ -258,53 +258,24 @@ static int socket_verify(Socket *s) { + return 0; + } + +-static bool socket_needs_mount(Socket *s, const char *prefix) { ++static int socket_add_mount_links(Socket *s) { + SocketPort *p; +- +- assert(s); +- +- LIST_FOREACH(port, p, s->ports) { +- +- if (p->type == SOCKET_SOCKET) { +- if (socket_address_needs_mount(&p->address, prefix)) +- return true; +- } else if (p->type == SOCKET_FIFO || p->type == SOCKET_SPECIAL) { +- if (path_startswith(p->path, prefix)) +- return true; +- } +- } +- +- return false; +-} +- +-int socket_add_one_mount_link(Socket *s, Mount *m) { + int r; + + assert(s); +- assert(m); + +- if (UNIT(s)->load_state != UNIT_LOADED || +- UNIT(m)->load_state != UNIT_LOADED) +- return 0; +- +- if (!socket_needs_mount(s, m->where)) +- return 0; +- +- r = unit_add_two_dependencies(UNIT(s), UNIT_AFTER, UNIT_REQUIRES, UNIT(m), true); +- if (r < 0) +- return r; +- +- return 0; +-} ++ LIST_FOREACH(port, p, s->ports) { ++ const char *path = NULL; + +-static int socket_add_mount_links(Socket *s) { +- Unit *other; +- int r; ++ if (p->type == SOCKET_SOCKET) ++ path = socket_address_get_path(&p->address); ++ else if (p->type == SOCKET_FIFO || p->type == SOCKET_SPECIAL) ++ path = p->path; + +- assert(s); ++ if (!path) ++ continue; + +- LIST_FOREACH(units_by_type, other, UNIT(s)->manager->units_by_type[UNIT_MOUNT]) { +- r = socket_add_one_mount_link(s, MOUNT(other)); ++ r = unit_require_mounts_for(UNIT(s), path); + if (r < 0) + return r; + } +diff --git a/src/core/socket.h b/src/core/socket.h +index 5733322..3d7eadc 100644 +--- a/src/core/socket.h ++++ b/src/core/socket.h +@@ -156,10 +156,6 @@ struct Socket { + /* Called from the service code when collecting fds */ + int socket_collect_fds(Socket *s, int **fds, unsigned *n_fds); + +-/* Called from the mount code figure out if a mount is a dependency of +- * any of the sockets of this socket */ +-int socket_add_one_mount_link(Socket *s, Mount *m); +- + /* Called from the service code when a per-connection service ended */ + void socket_connection_unref(Socket *s); + +diff --git a/src/core/swap.c b/src/core/swap.c +index d225485..6f86a86 100644 +--- a/src/core/swap.c ++++ b/src/core/swap.c +@@ -137,42 +137,6 @@ static void swap_done(Unit *u) { + unit_unwatch_timer(u, &s->timer_watch); + } + +-int swap_add_one_mount_link(Swap *s, Mount *m) { +- int r; +- +- assert(s); +- assert(m); +- +- if (UNIT(s)->load_state != UNIT_LOADED || +- UNIT(m)->load_state != UNIT_LOADED) +- return 0; +- +- if (is_device_path(s->what)) +- return 0; +- +- if (!path_startswith(s->what, m->where)) +- return 0; +- +- r = unit_add_two_dependencies(UNIT(s), UNIT_AFTER, UNIT_REQUIRES, UNIT(m), true); +- if (r < 0) +- return r; +- +- return 0; +-} +- +-static int swap_add_mount_links(Swap *s) { +- Unit *other; +- int r; +- +- assert(s); +- +- LIST_FOREACH(units_by_type, other, UNIT(s)->manager->units_by_type[UNIT_MOUNT]) +- if ((r = swap_add_one_mount_link(s, MOUNT(other))) < 0) +- return r; +- +- return 0; +-} +- + static int swap_add_device_links(Swap *s) { + SwapParameters *p; + +@@ -300,11 +264,11 @@ static int swap_load(Unit *u) { + if ((r = unit_set_description(u, s->what)) < 0) + return r; + +- r = swap_add_device_links(s); ++ r = unit_require_mounts_for(UNIT(s), s->what); + if (r < 0) + return r; + +- r = swap_add_mount_links(s); ++ r = swap_add_device_links(s); + if (r < 0) + return r; + +diff --git a/src/core/swap.h b/src/core/swap.h +index 7e48c0e..dd89535 100644 +--- a/src/core/swap.h ++++ b/src/core/swap.h +@@ -107,8 +107,6 @@ struct Swap { + + extern const UnitVTable swap_vtable; + +-int swap_add_one_mount_link(Swap *s, Mount *m); +- + int swap_dispatch_reload(Manager *m); + int swap_fd_event(Manager *m, int events); + +diff --git a/src/core/unit.c b/src/core/unit.c +index ab313b9..4b97710 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -374,6 +374,34 @@ static void unit_remove_transient(Unit *u) { + } + } + ++static void unit_free_requires_mounts_for(Unit *u) { ++ char **j; ++ ++ STRV_FOREACH(j, u->requires_mounts_for) { ++ char s[strlen(*j) + 1]; ++ ++ PATH_FOREACH_PREFIX_MORE(s, *j) { ++ char *y; ++ Set *x; ++ ++ x = hashmap_get2(u->manager->units_requiring_mounts_for, s, (void**) &y); ++ if (!x) ++ continue; ++ ++ set_remove(x, u); ++ ++ if (set_isempty(x)) { ++ hashmap_remove(u->manager->units_requiring_mounts_for, y); ++ free(y); ++ set_free(x); ++ } ++ } ++ } ++ ++ strv_free(u->requires_mounts_for); ++ u->requires_mounts_for = NULL; ++} ++ + void unit_free(Unit *u) { + UnitDependency d; + Iterator i; +@@ -390,6 +418,8 @@ void unit_free(Unit *u) { + if (UNIT_VTABLE(u)->done) + UNIT_VTABLE(u)->done(u); + ++ unit_free_requires_mounts_for(u); ++ + SET_FOREACH(t, u->names, i) + hashmap_remove_value(u->manager->units, t, u); + +@@ -408,11 +438,6 @@ void unit_free(Unit *u) { + for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) + bidi_set_free(u, u->dependencies[d]); + +- if (u->requires_mounts_for) { +- LIST_REMOVE(Unit, has_requires_mounts_for, u->manager->has_requires_mounts_for, u); +- strv_free(u->requires_mounts_for); +- } +- + if (u->type != _UNIT_TYPE_INVALID) + LIST_REMOVE(Unit, units_by_type, u->manager->units_by_type[u->type], u); + +@@ -2659,40 +2684,39 @@ void unit_ref_unset(UnitRef *ref) { + ref->unit = NULL; + } + +-int unit_add_one_mount_link(Unit *u, Mount *m) { ++int unit_add_mount_links(Unit *u) { + char **i; ++ int r; + + assert(u); +- assert(m); +- +- if (u->load_state != UNIT_LOADED || +- UNIT(m)->load_state != UNIT_LOADED) +- return 0; + + STRV_FOREACH(i, u->requires_mounts_for) { ++ char prefix[strlen(*i) + 1]; + +- if (UNIT(m) == u) +- continue; ++ PATH_FOREACH_PREFIX_MORE(prefix, *i) { ++ Unit *m; + +- if (!path_startswith(*i, m->where)) +- continue; +- +- return unit_add_two_dependencies(u, UNIT_AFTER, UNIT_REQUIRES, UNIT(m), true); +- } +- +- return 0; +-} ++ r = manager_get_unit_by_path(u->manager, prefix, ".mount", &m); ++ if (r < 0) ++ return r; ++ if (r == 0) ++ continue; ++ if (m == u) ++ continue; + +-int unit_add_mount_links(Unit *u) { +- Unit *other; +- int r; ++ if (m->load_state != UNIT_LOADED) ++ continue; + +- assert(u); ++ r = unit_add_dependency(u, UNIT_AFTER, m, true); ++ if (r < 0) ++ return r; + +- LIST_FOREACH(units_by_type, other, u->manager->units_by_type[UNIT_MOUNT]) { +- r = unit_add_one_mount_link(u, MOUNT(other)); +- if (r < 0) +- return r; ++ if (m->fragment_path) { ++ r = unit_add_dependency(u, UNIT_REQUIRES, m, true); ++ if (r < 0) ++ return r; ++ } ++ } + } + + return 0; +@@ -3012,6 +3036,86 @@ int unit_kill_context( + return wait_for_exit; + } + ++int unit_require_mounts_for(Unit *u, const char *path) { ++ char prefix[strlen(path) + 1], *p; ++ int r; ++ ++ assert(u); ++ assert(path); ++ ++ /* Registers a unit for requiring a certain path and all its ++ * prefixes. We keep a simple array of these paths in the ++ * unit, since its usually short. However, we build a prefix ++ * table for all possible prefixes so that new appearing mount ++ * units can easily determine which units to make themselves a ++ * dependency of. */ ++ ++ p = strdup(path); ++ if (!p) ++ return -ENOMEM; ++ ++ path_kill_slashes(p); ++ ++ if (!path_is_absolute(p)) { ++ free(p); ++ return -EINVAL; ++ } ++ ++ if (!path_is_safe(p)) { ++ free(p); ++ return -EPERM; ++ } ++ ++ if (strv_contains(u->requires_mounts_for, p)) { ++ free(p); ++ return 0; ++ } ++ ++ r = strv_push(&u->requires_mounts_for, p); ++ if (r < 0) { ++ free(p); ++ return r; ++ } ++ ++ PATH_FOREACH_PREFIX_MORE(prefix, p) { ++ Set *x; ++ ++ x = hashmap_get(u->manager->units_requiring_mounts_for, prefix); ++ if (!x) { ++ char *q; ++ ++ if (!u->manager->units_requiring_mounts_for) { ++ u->manager->units_requiring_mounts_for = hashmap_new(string_hash_func, string_compare_func); ++ if (!u->manager->units_requiring_mounts_for) ++ return -ENOMEM; ++ } ++ ++ q = strdup(prefix); ++ if (!q) ++ return -ENOMEM; ++ ++ x = set_new(NULL, NULL); ++ if (!x) { ++ free(q); ++ return -ENOMEM; ++ } ++ ++ r = hashmap_put(u->manager->units_requiring_mounts_for, q, x); ++ if (r < 0) { ++ free(q); ++ set_free(x); ++ return r; ++ } ++ } ++ ++ r = set_put(x, u); ++ if (r < 0) ++ return r; ++ } ++ ++ return 0; ++} ++ + static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = { + [UNIT_ACTIVE] = "active", + [UNIT_RELOADING] = "reloading", +diff --git a/src/core/unit.h b/src/core/unit.h +index 0caea18..6dd750f 100644 +--- a/src/core/unit.h ++++ b/src/core/unit.h +@@ -173,7 +173,6 @@ struct Unit { + + /* Counterparts in the cgroup filesystem */ + char *cgroup_path; +- bool cgroup_realized; + CGroupControllerMask cgroup_mask; + + UnitRef slice; +@@ -255,6 +254,8 @@ struct Unit { + bool no_gc:1; + + bool in_audit:1; ++ ++ bool cgroup_realized:1; + }; + + struct UnitStatusMessageFormats { +@@ -589,7 +590,6 @@ void unit_ref_unset(UnitRef *ref); + #define UNIT_DEREF(ref) ((ref).unit) + #define UNIT_ISSET(ref) (!!(ref).unit) + +-int unit_add_one_mount_link(Unit *u, Mount *m); + int unit_add_mount_links(Unit *u); + + int unit_exec_context_defaults(Unit *u, ExecContext *c); +@@ -609,6 +609,8 @@ int unit_kill_context(Unit *u, KillContext *c, bool sigkill, pid_t main_pid, pid + + int unit_make_transient(Unit *u); + ++int unit_require_mounts_for(Unit *u, const char *path); ++ + const char *unit_active_state_to_string(UnitActiveState i) _const_; + UnitActiveState unit_active_state_from_string(const char *s) _pure_; + +diff --git a/src/shared/socket-util.c b/src/shared/socket-util.c +index c583d3d..9224208 100644 +--- a/src/shared/socket-util.c ++++ b/src/shared/socket-util.c +@@ -486,16 +486,16 @@ bool socket_address_is_netlink(const SocketAddress *a, const char *s) { + return socket_address_equal(a, &b); + } + +-bool socket_address_needs_mount(const SocketAddress *a, const char *prefix) { ++const char* socket_address_get_path(const SocketAddress *a) { + assert(a); + + if (socket_address_family(a) != AF_UNIX) +- return false; ++ return NULL; + + if (a->sockaddr.un.sun_path[0] == 0) +- return false; ++ return NULL; + +- return path_startswith(a->sockaddr.un.sun_path, prefix); ++ return a->sockaddr.un.sun_path; + } + + bool socket_ipv6_is_supported(void) { +diff --git a/src/shared/socket-util.h b/src/shared/socket-util.h +index 7829a33..e0b85ad 100644 +--- a/src/shared/socket-util.h ++++ b/src/shared/socket-util.h +@@ -92,7 +92,7 @@ int make_socket_fd(const char* address, int flags); + + bool socket_address_equal(const SocketAddress *a, const SocketAddress *b) _pure_; + +-bool socket_address_needs_mount(const SocketAddress *a, const char *prefix); ++const char* socket_address_get_path(const SocketAddress *a); + + const char* socket_address_bind_ipv6_only_to_string(SocketAddressBindIPv6Only b) _const_; + SocketAddressBindIPv6Only socket_address_bind_ipv6_only_from_string(const char *s) _pure_; diff --git a/SOURCES/0044-logind-never-consider-a-closing-session-relevant-for.patch b/SOURCES/0044-logind-never-consider-a-closing-session-relevant-for.patch new file mode 100644 index 0000000..86aea72 --- /dev/null +++ b/SOURCES/0044-logind-never-consider-a-closing-session-relevant-for.patch @@ -0,0 +1,23 @@ +From 48797bdc98bb45dbd1aa7150bac5eff0acd31d58 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 26 Sep 2013 21:32:47 +0200 +Subject: [PATCH] logind: never consider a closing session relevant for PK + checks + +https://bugzilla.redhat.com/show_bug.cgi?id=1010215 +--- + src/login/logind-dbus.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c +index 77dda10..9f4c120 100644 +--- a/src/login/logind-dbus.c ++++ b/src/login/logind-dbus.c +@@ -957,6 +957,7 @@ static int have_multiple_sessions( + * count, and non-login sessions do not count either. */ + HASHMAP_FOREACH(session, m->sessions, i) + if (session->class == SESSION_USER && ++ !session->closing && + session->user->uid != uid) + return true; + diff --git a/SOURCES/0045-man-drop-references-to-cgroup-wher-appropriate.patch b/SOURCES/0045-man-drop-references-to-cgroup-wher-appropriate.patch new file mode 100644 index 0000000..c2a207f --- /dev/null +++ b/SOURCES/0045-man-drop-references-to-cgroup-wher-appropriate.patch @@ -0,0 +1,436 @@ +From a8c3f5121fac2cc4f8e3221a5a06b63d2e9c6f02 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Fri, 27 Sep 2013 00:05:07 +0200 +Subject: [PATCH] man: drop references to "cgroup" wher appropriate + +Since cgroups are mostly now an implementation detail of systemd lets +deemphasize it a bit in the man pages. This renames systemd.cgroup(5) to +systemd.resource-control(5) and uses the term "resource control" rather +than "cgroup" where appropriate. + +This leaves the word "cgroup" in at a couple of places though, like for +example systemd-cgtop and systemd-cgls where cgroup stuff is at the core +of what is happening. + +Conflicts: + man/systemd.exec.xml +--- + Makefile-man.am | 2 +- + man/loginctl.xml | 4 ++-- + man/machinectl.xml | 4 ++-- + man/pam_systemd.xml | 2 +- + man/systemctl.xml | 14 ++++++------- + man/systemd-cgls.xml | 6 +++--- + man/systemd-cgtop.xml | 4 ++-- + man/systemd.exec.xml | 5 +++-- + man/systemd.mount.xml | 6 +++--- + ...emd.cgroup.xml => systemd.resource-control.xml} | 24 ++++++++++------------ + man/systemd.scope.xml | 2 +- + man/systemd.service.xml | 6 +++--- + man/systemd.slice.xml | 22 ++++++++++---------- + man/systemd.socket.xml | 12 +++++------ + man/systemd.swap.xml | 6 +++--- + 15 files changed, 59 insertions(+), 60 deletions(-) + rename man/{systemd.cgroup.xml => systemd.resource-control.xml} (96%) + +diff --git a/Makefile-man.am b/Makefile-man.am +index 1f63595..c8a4342 100644 +--- a/Makefile-man.am ++++ b/Makefile-man.am +@@ -78,7 +78,6 @@ MANPAGES += \ + man/systemd-update-utmp.service.8 \ + man/systemd.1 \ + man/systemd.automount.5 \ +- man/systemd.cgroup.5 \ + man/systemd.device.5 \ + man/systemd.exec.5 \ + man/systemd.journal-fields.7 \ +@@ -86,6 +85,7 @@ MANPAGES += \ + man/systemd.mount.5 \ + man/systemd.path.5 \ + man/systemd.preset.5 \ ++ man/systemd.resource-control.5 \ + man/systemd.scope.5 \ + man/systemd.service.5 \ + man/systemd.slice.5 \ +diff --git a/man/loginctl.xml b/man/loginctl.xml +index ef0dfc0..1b54ff7 100644 +--- a/man/loginctl.xml ++++ b/man/loginctl.xml +@@ -117,8 +117,8 @@ + + + +- Do not ellipsize cgroup +- members. ++ Do not ellipsize ++ process tree entries. + + + +diff --git a/man/machinectl.xml b/man/machinectl.xml +index 5efa3a5..2ed9f2e 100644 +--- a/man/machinectl.xml ++++ b/man/machinectl.xml +@@ -117,8 +117,8 @@ + + + +- Do not ellipsize cgroup +- members. ++ Do not ellipsize ++ process tree entries. + + + +diff --git a/man/pam_systemd.xml b/man/pam_systemd.xml +index 951ae20..0e25a4a 100644 +--- a/man/pam_systemd.xml ++++ b/man/pam_systemd.xml +@@ -55,7 +55,7 @@ + Description + + pam_systemd registers user +- sessions in the systemd login manager ++ sessions with the systemd login manager + systemd-logind.service8, + and hence the systemd control group hierarchy. + +diff --git a/man/systemctl.xml b/man/systemctl.xml +index 51c34b7..a70c964 100644 +--- a/man/systemctl.xml ++++ b/man/systemctl.xml +@@ -187,7 +187,7 @@ systemctl start foo + + + +- Do not ellipsize unit names, cgroup members, and ++ Do not ellipsize unit names, process tree entries, and + truncate unit descriptions in the output of + list-units and + list-jobs. +@@ -724,14 +724,14 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service + + Set the specified unit properties at runtime where + this is supported. This allows changing configuration +- parameter properties such as resource management controls at ++ parameter properties such as resource control settings at + runtime. Not all properties may be changed at runtime, but +- many resource management settings (primarily those in +- systemd.cgroup5) ++ many resource control settings (primarily those in ++ systemd.resource-control5) + may. The changes are applied instantly, and stored on disk + for future boots, unless is +- passed, in which case the settings only apply until the next +- reboot. The syntax of the property assignment follows ++ passed, in which case the settings only apply until the ++ next reboot. The syntax of the property assignment follows + closely the syntax of assignments in unit files. + + Example: systemctl set-property foobar.service CPUShares=777 +@@ -1299,7 +1299,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service + journalctl1, + loginctl1, + systemd.unit5, +- systemd.cgroup5, ++ systemd.resource-management5, + systemd.special7, + wall1, + systemd.preset5 +diff --git a/man/systemd-cgls.xml b/man/systemd-cgls.xml +index fcaf894..432706b 100644 +--- a/man/systemd-cgls.xml ++++ b/man/systemd-cgls.xml +@@ -116,8 +116,8 @@ + + + +- Do not ellipsize cgroup +- members. ++ Do not ellipsize ++ process tree members. + + + +@@ -132,7 +132,7 @@ + + + +- Limit cgroups shown to ++ Limit control groups shown to + the part corresponding to the + container MACHINE. + +diff --git a/man/systemd-cgtop.xml b/man/systemd-cgtop.xml +index 51549c4..7faedfb 100644 +--- a/man/systemd-cgtop.xml ++++ b/man/systemd-cgtop.xml +@@ -80,7 +80,7 @@ + MemoryAccounting=1 and + BlockIOAccounting=1 settings in the + unit files in question (See +- systemd.cgroup5 ++ systemd.resource-control5 + for details). + + To emphasize this: unless +@@ -274,7 +274,7 @@ + systemd1, + systemctl1, + systemd-cgls1, +- systemd.cgroup5, ++ systemd.resource-control5, + top1 + + +diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml +index 5721dc1..28d7fd4 100644 +--- a/man/systemd.exec.xml ++++ b/man/systemd.exec.xml +@@ -1017,8 +1017,9 @@ + systemd.swap5, + systemd.mount5, + systemd.kill5, +- systemd.cgroup5, +- systemd.directives7 ++ systemd.resource-control5, ++ systemd.directives7, ++ exec3 + + + +diff --git a/man/systemd.mount.xml b/man/systemd.mount.xml +index e5b5c3c..48af1ca 100644 +--- a/man/systemd.mount.xml ++++ b/man/systemd.mount.xml +@@ -76,8 +76,8 @@ + systemd.kill5, + which define the way the processes are terminated, and + in +- systemd.cgroup5, +- which configure control group settings for the ++ systemd.resource-control5, ++ which configure resource control settings for the + processes of the service. Note that the User= and + Group= options are not particularly useful for mount + units specifying a Type= option or +@@ -302,7 +302,7 @@ + systemd.unit5, + systemd.exec5, + systemd.kill5, +- systemd.cgroup5, ++ systemd.resource-control5, + systemd.service5, + systemd.device5, + proc5, +diff --git a/man/systemd.cgroup.xml b/man/systemd.resource-control.xml +similarity index 96% +rename from man/systemd.cgroup.xml +rename to man/systemd.resource-control.xml +index cc0eb15..2427f208 100644 +--- a/man/systemd.cgroup.xml ++++ b/man/systemd.resource-control.xml +@@ -22,9 +22,9 @@ You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . + --> + +- ++ + +- systemd.cgroup ++ systemd.resource-control + systemd + + +@@ -38,13 +38,13 @@ along with systemd; If not, see . + + + +- systemd.cgroup ++ systemd.resource-control + 5 + + + +- systemd.cgroup +- Control Group configuration unit settings ++ systemd.resource-control ++ Resource control unit settings + + + +@@ -63,12 +63,10 @@ along with systemd; If not, see . + + Unit configuration files for services, slices, scopes, + sockets, mount points, and swap devices share a subset of +- configuration options which configure the control group settings +- for spawned processes. +- +- Control Groups is a concept for organizing processes in a +- hierarch tree of named groups for the purpose of resource +- management. ++ configuration options for resource control of spawned ++ processes. Internally, this relies on the the Control Groups ++ kernel concept for organizing processes in a hierarchial tree of ++ named groups for the purpose of resource management. + + This man page lists the configuration options shared by + those six unit types. See +@@ -82,7 +80,7 @@ along with systemd; If not, see . + and + systemd.swap5 + for more information on the specific unit configuration files. The +- execution-specific configuration options are configured in the ++ resource control configuration options are configured in the + [Slice], [Scope], [Service], [Socket], [Mount], or [Swap] + sections, depending on the unit type. + +@@ -91,7 +89,7 @@ along with systemd; If not, see . + Options + + Units of the types listed above can have settings +- for cgroup configuration: ++ for resource control configuration: + + + +diff --git a/man/systemd.scope.xml b/man/systemd.scope.xml +index e8fa1ae..9813e0a 100644 +--- a/man/systemd.scope.xml ++++ b/man/systemd.scope.xml +@@ -86,7 +86,7 @@ along with systemd; If not, see . + systemd1, + systemd-run1, + systemd.unit5, +- systemd.cgroup5, ++ systemd.resource-control5, + systemd.service5, + systemd.directives7. + +diff --git a/man/systemd.service.xml b/man/systemd.service.xml +index 8eda85f..45f96fa 100644 +--- a/man/systemd.service.xml ++++ b/man/systemd.service.xml +@@ -76,8 +76,8 @@ + systemd.kill5, + which define the way the processes of the service are + terminated, and in +- systemd.cgroup5, +- which configure control group settings for the ++ systemd.resource-control5, ++ which configure resource control settings for the + processes of the service. + + Unless DefaultDependencies= +@@ -1006,7 +1006,7 @@ + systemctl8, + systemd.unit5, + systemd.exec5, +- systemd.cgroup5, ++ systemd.resource-control5, + systemd.kill5, + systemd.directives7 + +diff --git a/man/systemd.slice.xml b/man/systemd.slice.xml +index b7b0622..4d27ddf 100644 +--- a/man/systemd.slice.xml ++++ b/man/systemd.slice.xml +@@ -58,14 +58,14 @@ along with systemd; If not, see . + .slice encodes information about a slice which + is a concept for hierarchially managing resources of a group of + processes. This management is performed by creating a node in the +- control group tree. Units that manage processes (primarilly scope +- and service units) may be assigned to a specific slice. For each +- slice, certain resource limits may the be set that apply to all +- processes of all units contained in that slice. Slices are +- organized hierarchially in a tree. The name of the slice encodes +- the location in the tree. The name consists of a dash-separated +- series of names, which describes the path to the slice from the +- root slice. The root slice is named, ++ Linux Control Group (cgroup) tree. Units that manage processes ++ (primarilly scope and service units) may be assigned to a specific ++ slice. For each slice, certain resource limits may the be set that ++ apply to all processes of all units contained in that ++ slice. Slices are organized hierarchially in a tree. The name of ++ the slice encodes the location in the tree. The name consists of a ++ dash-separated series of names, which describes the path to the ++ slice from the root slice. The root slice is named, + -.slice. Example: + foo-bar.slice is a slice that is located + within foo.slice, which in turn is located in +@@ -89,9 +89,9 @@ along with systemd; If not, see . + files. The common configuration items are configured + in the generic [Unit] and [Install] sections. The + slice specific configuration options are configured in +- the [Slice] section. Currently, only generic cgroup settings ++ the [Slice] section. Currently, only generic resource control settings + as described in +- systemd.cgroup7 are allowed. ++ systemd.resource-control7 are allowed. + + + Unless DefaultDependencies=false +@@ -110,7 +110,7 @@ along with systemd; If not, see . + + systemd1, + systemd.unit5, +- systemd.cgroup5, ++ systemd.resource-control5, + systemd.service5, + systemd.scope5, + systemd.special7, +diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml +index 419a38c..8c88d9f 100644 +--- a/man/systemd.socket.xml ++++ b/man/systemd.socket.xml +@@ -78,11 +78,11 @@ + commands are executed + in, and in + systemd.kill5, +- which define the way the processes are +- terminated, and in +- systemd.cgroup5, +- which configure control group settings for the +- processes of the service. ++ which define the way the processes are terminated, and ++ in ++ systemd.resource-control5, ++ which configure resource control settings for the ++ processes of the socket. + + For each socket file a matching service file + (see +@@ -712,7 +712,7 @@ + systemd.unit5, + systemd.exec5, + systemd.kill5, +- systemd.cgroup5, ++ systemd.resource-control5, + systemd.service5, + systemd.directives7 + +diff --git a/man/systemd.swap.xml b/man/systemd.swap.xml +index 18ef5b0..813ae6c 100644 +--- a/man/systemd.swap.xml ++++ b/man/systemd.swap.xml +@@ -76,8 +76,8 @@ + systemd.kill5, + which define the way the processes are + terminated, and in +- systemd.cgroup5, +- which configure control group settings for the ++ systemd.resource-control5, ++ which configure resource control settings for the + processes of the service. + + Swap units must be named after the devices +@@ -206,7 +206,7 @@ + systemd.unit5, + systemd.exec5, + systemd.kill5, +- systemd.cgroup5, ++ systemd.resource-control5, + systemd.device5, + systemd.mount5, + swapon8, diff --git a/SOURCES/0046-systemctl-make-sure-set-property-mangles-unit-names.patch b/SOURCES/0046-systemctl-make-sure-set-property-mangles-unit-names.patch new file mode 100644 index 0000000..1c5dc03 --- /dev/null +++ b/SOURCES/0046-systemctl-make-sure-set-property-mangles-unit-names.patch @@ -0,0 +1,36 @@ +From 86ccda12838942a4df2c974bad9386a60835ba67 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Fri, 27 Sep 2013 00:11:54 +0200 +Subject: [PATCH] systemctl: make sure set-property mangles unit names + +--- + src/systemctl/systemctl.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c +index 57e5bb9..16da293 100644 +--- a/src/systemctl/systemctl.c ++++ b/src/systemctl/systemctl.c +@@ -3828,7 +3828,8 @@ static int append_assignment(DBusMessageIter *iter, const char *assignment) { + + static int set_property(DBusConnection *bus, char **args) { + +- _cleanup_free_ DBusMessage *m = NULL, *reply = NULL; ++ _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL; ++ _cleanup_free_ char *n = NULL; + DBusMessageIter iter, sub; + dbus_bool_t runtime; + DBusError error; +@@ -3849,7 +3850,11 @@ static int set_property(DBusConnection *bus, char **args) { + + runtime = arg_runtime; + +- if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &args[1]) || ++ n = unit_name_mangle(args[1]); ++ if (!n) ++ return log_oom(); ++ ++ if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n) || + !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &runtime) || + !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sv)", &sub)) + return log_oom(); diff --git a/SOURCES/0047-dbus-fix-introspection-for-TimerSlackNSec.patch b/SOURCES/0047-dbus-fix-introspection-for-TimerSlackNSec.patch new file mode 100644 index 0000000..b6f2a1f --- /dev/null +++ b/SOURCES/0047-dbus-fix-introspection-for-TimerSlackNSec.patch @@ -0,0 +1,22 @@ +From 21062f680e6aff80a41ebb3d90543c310f6c22e6 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Fri, 27 Sep 2013 00:35:36 +0200 +Subject: [PATCH] dbus: fix introspection for TimerSlackNSec + +--- + src/core/dbus-execute.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/core/dbus-execute.h b/src/core/dbus-execute.h +index 5a6a559..79bf308 100644 +--- a/src/core/dbus-execute.h ++++ b/src/core/dbus-execute.h +@@ -63,7 +63,7 @@ + " \n" \ + " \n" \ + " \n" \ +- " \n" \ ++ " \n" \ + " \n" \ + " \n" \ + " \n" \ diff --git a/SOURCES/0048-swap-properly-expose-timeout-property-on-the-bus.patch b/SOURCES/0048-swap-properly-expose-timeout-property-on-the-bus.patch new file mode 100644 index 0000000..93150d9 --- /dev/null +++ b/SOURCES/0048-swap-properly-expose-timeout-property-on-the-bus.patch @@ -0,0 +1,21 @@ +From 83ee5d7f274a3a365fd0f4855ec14e444bc56321 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Fri, 27 Sep 2013 02:02:21 +0200 +Subject: [PATCH] swap: properly expose timeout property on the bus + +--- + src/core/dbus-swap.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/core/dbus-swap.c b/src/core/dbus-swap.c +index 86fcf16..06edfdc 100644 +--- a/src/core/dbus-swap.c ++++ b/src/core/dbus-swap.c +@@ -95,6 +95,7 @@ static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_swap_append_swap_result, swap_result, + static const BusProperty bus_swap_properties[] = { + { "What", bus_property_append_string, "s", offsetof(Swap, what), true }, + { "Priority", bus_swap_append_priority, "i", 0 }, ++ { "TimeoutUSec",bus_property_append_usec, "t", offsetof(Swap, timeout_usec)}, + BUS_EXEC_COMMAND_PROPERTY("ExecActivate", offsetof(Swap, exec_command[SWAP_EXEC_ACTIVATE]), false), + BUS_EXEC_COMMAND_PROPERTY("ExecDeactivate", offsetof(Swap, exec_command[SWAP_EXEC_DEACTIVATE]), false), + { "ControlPID", bus_property_append_pid, "u", offsetof(Swap, control_pid) }, diff --git a/SOURCES/0049-build-sys-restore-detection-of-sphinx.patch b/SOURCES/0049-build-sys-restore-detection-of-sphinx.patch new file mode 100644 index 0000000..41ee8fe --- /dev/null +++ b/SOURCES/0049-build-sys-restore-detection-of-sphinx.patch @@ -0,0 +1,29 @@ +From 2127292995c93c4324cc15a8034e009fb78eb5a5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Fri, 27 Sep 2013 08:24:00 +0200 +Subject: [PATCH] build-sys: restore detection of sphinx + +--- + configure.ac | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/configure.ac b/configure.ac +index d3f853f..c7f4f1b 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -185,6 +185,7 @@ AS_IF([test "x$enable_python_devel" != "xno"], [ + [have_python_devel=no])]) + AS_IF([test "x$have_python_devel" = xno -a "x$enable_python_devel" = xyes], + [AC_MSG_ERROR([*** python-devel support requested but libraries not found])]) ++ AC_PATH_PROGS(SPHINX_BUILD, sphinx-build-${PYTHON_VERSION} sphinx-build) + ]) + AM_CONDITIONAL([HAVE_PYTHON_DEVEL], [test "$have_python_devel" = "yes"]) + +@@ -1051,6 +1052,7 @@ AC_MSG_RESULT([ + SysV rc?.d directories: ${SYSTEM_SYSVRCND_PATH} + Build Python: ${PYTHON} + Installation Python: ${PYTHON_BINARY} ++ sphinx binary: ${SPHINX_BUILD} + firmware path: ${FIRMWARE_PATH} + PAM modules dir: ${with_pamlibdir} + PAM configuration dir: ${with_pamconfdir} diff --git a/SOURCES/0050-util-add-macro-for-iterating-through-all-prefixes-of.patch b/SOURCES/0050-util-add-macro-for-iterating-through-all-prefixes-of.patch new file mode 100644 index 0000000..5846c39 --- /dev/null +++ b/SOURCES/0050-util-add-macro-for-iterating-through-all-prefixes-of.patch @@ -0,0 +1,119 @@ +From c9f59a78c0016b37730cec831e1eec139ca4a561 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 25 Sep 2013 20:58:23 +0200 +Subject: [PATCH] util: add macro for iterating through all prefixes of a path + +Syntactic sugar in a macro PATH_FOREACH_PREFIX. +--- + src/shared/cgroup-util.c | 26 ++++---------------------- + src/shared/path-util.h | 3 +++ + src/test/test-path-util.c | 27 +++++++++++++++++++++++++++ + 3 files changed, 34 insertions(+), 22 deletions(-) + +diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c +index 2e630d4..dc0fe85 100644 +--- a/src/shared/cgroup-util.c ++++ b/src/shared/cgroup-util.c +@@ -456,23 +456,14 @@ int cg_migrate_recursive_fallback( + + /* This didn't work? Then let's try all prefixes of the destination */ + +- strcpy(prefix, pto); +- for (;;) { +- char *slash; +- +- slash = strrchr(prefix, '/'); +- if (!slash) +- break; +- +- *slash = 0; +- ++ PATH_FOREACH_PREFIX(prefix, pto) { + r = cg_migrate_recursive(cfrom, pfrom, cto, prefix, ignore_self, rem); + if (r >= 0) + break; + } + } + +- return r; ++ return 0; + } + + static const char *normalize_controller(const char *controller) { +@@ -661,23 +652,14 @@ int cg_attach_fallback(const char *controller, const char *path, pid_t pid) { + /* This didn't work? Then let's try all prefixes of + * the destination */ + +- strcpy(prefix, path); +- for (;;) { +- char *slash; +- +- slash = strrchr(prefix, '/'); +- if (!slash) +- break; +- +- *slash = 0; +- ++ PATH_FOREACH_PREFIX(prefix, path) { + r = cg_attach(controller, prefix, pid); + if (r >= 0) + break; + } + } + +- return r; ++ return 0; + } + + int cg_set_group_access( +diff --git a/src/shared/path-util.h b/src/shared/path-util.h +index 9452931..03f2cf2 100644 +--- a/src/shared/path-util.h ++++ b/src/shared/path-util.h +@@ -51,3 +51,6 @@ int path_is_read_only_fs(const char *path); + int path_is_os_tree(const char *path); + + int find_binary(const char *name, char **filename); ++ ++#define PATH_FOREACH_PREFIX(prefix, path) \ ++ for (char *_slash = strrchr(path_kill_slashes(strcpy(prefix, path)), '/'); _slash && !(*_slash = 0); _slash = strrchr((prefix), '/')) +diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c +index b0aeb11..e303e48 100644 +--- a/src/test/test-path-util.c ++++ b/src/test/test-path-util.c +@@ -106,8 +106,35 @@ static void test_find_binary(void) { + assert(find_binary("xxxx-xxxx", &p) == -ENOENT); + } + ++static void test_prefixes(void) { ++ static const char* values[] = { "/a/b/c", "/a/b", "/a", "", NULL}; ++ unsigned i = 0; ++ char s[PATH_MAX]; ++ ++ PATH_FOREACH_PREFIX(s, "/a/b/c/d") { ++ log_error("---%s---", s); ++ assert_se(streq(s, values[i++])); ++ } ++ ++ assert_se(values[i] == NULL); ++ ++ i = 0; ++ PATH_FOREACH_PREFIX(s, "////a////b////c///d///////") ++ assert_se(streq(s, values[i++])); ++ ++ assert_se(values[i] == NULL); ++ ++ PATH_FOREACH_PREFIX(s, "////") ++ assert_se(streq(s, "")); ++ ++ PATH_FOREACH_PREFIX(s, "") ++ assert_not_reached("wut?"); ++ ++} ++ + int main(void) { + test_path(); + test_find_binary(); ++ test_prefixes(); + return 0; + } diff --git a/SOURCES/0051-util-properly-handle-the-root-dir-in-PATH_FOREACH_PR.patch b/SOURCES/0051-util-properly-handle-the-root-dir-in-PATH_FOREACH_PR.patch new file mode 100644 index 0000000..a3deb42 --- /dev/null +++ b/SOURCES/0051-util-properly-handle-the-root-dir-in-PATH_FOREACH_PR.patch @@ -0,0 +1,94 @@ +From dc5e623cbd6c4250d514ec1c9d67c338cd71934c Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 26 Sep 2013 19:58:33 +0200 +Subject: [PATCH] util: properly handle the root dir in PATH_FOREACH_PREFIX + +Also add PATH_FOREACH_PREFIX_MORE which includes the specified dir +itself in the iteration +--- + src/shared/path-util.h | 9 ++++++++- + src/test/test-path-util.c | 34 ++++++++++++++++++++++++++++++---- + 2 files changed, 38 insertions(+), 5 deletions(-) + +diff --git a/src/shared/path-util.h b/src/shared/path-util.h +index 03f2cf2..0a42de7 100644 +--- a/src/shared/path-util.h ++++ b/src/shared/path-util.h +@@ -52,5 +52,12 @@ int path_is_os_tree(const char *path); + + int find_binary(const char *name, char **filename); + ++/* Iterates through the path prefixes of the specified path, going up ++ * the tree, to root. Also returns "" (and not "/"!) for the root ++ * directory. Excludes the specified directory itself */ + #define PATH_FOREACH_PREFIX(prefix, path) \ +- for (char *_slash = strrchr(path_kill_slashes(strcpy(prefix, path)), '/'); _slash && !(*_slash = 0); _slash = strrchr((prefix), '/')) ++ for (char *_slash = ({ path_kill_slashes(strcpy(prefix, path)); streq(prefix, "/") ? NULL : strrchr(prefix, '/'); }); _slash && !(*_slash = 0); _slash = strrchr((prefix), '/')) ++ ++/* Same as PATH_FOREACH_PREFIX but also includes the specified path itself */ ++#define PATH_FOREACH_PREFIX_MORE(prefix, path) \ ++ for (char *_slash = ({ path_kill_slashes(strcpy(prefix, path)); if (streq(prefix, "/")) prefix[0] = 0; strrchr(prefix, 0); }); _slash && !(*_slash = 0); _slash = strrchr((prefix), '/')) +diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c +index e303e48..ed3b315 100644 +--- a/src/test/test-path-util.c ++++ b/src/test/test-path-util.c +@@ -107,29 +107,55 @@ static void test_find_binary(void) { + } + + static void test_prefixes(void) { +- static const char* values[] = { "/a/b/c", "/a/b", "/a", "", NULL}; +- unsigned i = 0; ++ static const char* values[] = { "/a/b/c/d", "/a/b/c", "/a/b", "/a", "", NULL}; ++ unsigned i; + char s[PATH_MAX]; ++ bool b; + +- PATH_FOREACH_PREFIX(s, "/a/b/c/d") { ++ i = 0; ++ PATH_FOREACH_PREFIX_MORE(s, "/a/b/c/d") { + log_error("---%s---", s); + assert_se(streq(s, values[i++])); + } ++ assert_se(values[i] == NULL); + ++ i = 1; ++ PATH_FOREACH_PREFIX(s, "/a/b/c/d") { ++ log_error("---%s---", s); ++ assert_se(streq(s, values[i++])); ++ } + assert_se(values[i] == NULL); + + i = 0; +- PATH_FOREACH_PREFIX(s, "////a////b////c///d///////") ++ PATH_FOREACH_PREFIX_MORE(s, "////a////b////c///d///////") + assert_se(streq(s, values[i++])); ++ assert_se(values[i] == NULL); + ++ i = 1; ++ PATH_FOREACH_PREFIX(s, "////a////b////c///d///////") ++ assert_se(streq(s, values[i++])); + assert_se(values[i] == NULL); + + PATH_FOREACH_PREFIX(s, "////") ++ assert_not_reached("Wut?"); ++ ++ b = false; ++ PATH_FOREACH_PREFIX_MORE(s, "////") { ++ assert_se(!b); + assert_se(streq(s, "")); ++ b = true; ++ } ++ assert_se(b); + + PATH_FOREACH_PREFIX(s, "") + assert_not_reached("wut?"); + ++ b = false; ++ PATH_FOREACH_PREFIX_MORE(s, "") { ++ assert(!b); ++ assert(streq(s, "")); ++ b = true; ++ } + } + + int main(void) { diff --git a/SOURCES/0052-cgroup-get-rid-of-MemorySoftLimit.patch b/SOURCES/0052-cgroup-get-rid-of-MemorySoftLimit.patch new file mode 100644 index 0000000..025b012 --- /dev/null +++ b/SOURCES/0052-cgroup-get-rid-of-MemorySoftLimit.patch @@ -0,0 +1,245 @@ +From 5ba4f4d42db066c3a9255768d5c38d841127bd07 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 17 Sep 2013 14:58:00 -0500 +Subject: [PATCH] cgroup: get rid of MemorySoftLimit= + +The cgroup attribute memory.soft_limit_in_bytes is unlikely to stay +around in the kernel for good, so let's not expose it for now. We can +readd something like it later when the kernel guys decided on a final +API for this. + +Conflicts: + TODO +--- + TODO | 9 +++++++++ + man/systemd.resource-control.xml | 15 +++++---------- + src/core/cgroup.c | 16 ++-------------- + src/core/cgroup.h | 1 - + src/core/dbus-cgroup.c | 10 ++-------- + src/core/dbus-cgroup.h | 1 - + src/core/load-fragment-gperf.gperf.m4 | 1 - + src/core/load-fragment.c | 7 ++----- + src/systemctl/systemctl.c | 2 +- + 9 files changed, 21 insertions(+), 41 deletions(-) + +diff --git a/TODO b/TODO +index bfeaa81..4c3e14f 100644 +--- a/TODO ++++ b/TODO +@@ -58,6 +58,15 @@ CGroup Rework Completion: + + Features: + ++* always set memory.user_hierarchy for all cgroups we create ++ ++* After coming back from hibernation reset hibernation swap partition ++ ++* mounts: do not test each mount unit against each other mount unit to ++ determine prefixes. Instead generated list of all prefixes and ++ interate through that to bring down complexity from O(n^2) to O(n) ++ when loading units ++ + * Move backlight and random-seed into /var/lib/systemd + + * If we try to find a unit via a danglign symlink generate a clean +diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml +index 2427f208..de017a7 100644 +--- a/man/systemd.resource-control.xml ++++ b/man/systemd.resource-control.xml +@@ -134,22 +134,17 @@ along with systemd; If not, see . + + + MemoryLimit=bytes +- MemorySoftLimit=bytes + + +- Specify the hard and soft limits on maximum memory +- usage of the executed processes. The "hard" limit specifies +- how much process and kernel memory can be used by tasks in +- this unit, when there is no memory contention. If the kernel +- detects memory contention, memory reclaim will be performed +- until the memory usage is within the "soft" limit. Takes a ++ Specify the limit on maximum memory usage of the ++ executed processes. The limit specifies how much process and ++ kernel memory can be used by tasks in this unit. Takes a + memory size in bytes. If the value is suffixed with K, M, G + or T, the specified memory size is parsed as Kilobytes, + Megabytes, Gigabytes, or Terabytes (with the base 1024), + respectively. This controls the +- memory.limit_in_bytes and +- memory.soft_limit_in_bytes control group +- attributes. For details about these control group attributes, ++ memory.limit_in_bytes control group ++ attribute. For details about this control group attribute, + see memory.txt. + +diff --git a/src/core/cgroup.c b/src/core/cgroup.c +index 2f1e4a3..8bf4d89 100644 +--- a/src/core/cgroup.c ++++ b/src/core/cgroup.c +@@ -33,7 +33,7 @@ void cgroup_context_init(CGroupContext *c) { + * structure is preinitialized to 0 */ + + c->cpu_shares = 1024; +- c->memory_limit = c->memory_soft_limit = (uint64_t) -1; ++ c->memory_limit = (uint64_t) -1; + c->blockio_weight = 1000; + } + +@@ -94,7 +94,6 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) { + "%sCPUShares=%lu\n" + "%sBlockIOWeight=%lu\n" + "%sMemoryLimit=%" PRIu64 "\n" +- "%sMemorySoftLimit=%" PRIu64 "\n" + "%sDevicePolicy=%s\n", + prefix, yes_no(c->cpu_accounting), + prefix, yes_no(c->blockio_accounting), +@@ -102,7 +101,6 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) { + prefix, c->cpu_shares, + prefix, c->blockio_weight, + prefix, c->memory_limit, +- prefix, c->memory_soft_limit, + prefix, cgroup_device_policy_to_string(c->device_policy)); + + LIST_FOREACH(device_allow, a, c->device_allow) +@@ -266,15 +264,6 @@ void cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const cha + + if (r < 0) + log_error("Failed to set memory.limit_in_bytes on %s: %s", path, strerror(-r)); +- +- if (c->memory_soft_limit != (uint64_t) -1) { +- sprintf(buf, "%" PRIu64 "\n", c->memory_soft_limit); +- r = cg_set_attribute("memory", path, "memory.soft_limit_in_bytes", buf); +- } else +- r = cg_set_attribute("memory", path, "memory.soft_limit_in_bytes", "-1"); +- +- if (r < 0) +- log_error("Failed to set memory.soft_limit_in_bytes on %s: %s", path, strerror(-r)); + } + + if (mask & CGROUP_DEVICE) { +@@ -337,8 +326,7 @@ CGroupControllerMask cgroup_context_get_mask(CGroupContext *c) { + mask |= CGROUP_BLKIO; + + if (c->memory_accounting || +- c->memory_limit != (uint64_t) -1 || +- c->memory_soft_limit != (uint64_t) -1) ++ c->memory_limit != (uint64_t) -1) + mask |= CGROUP_MEMORY; + + if (c->device_allow || c->device_policy != CGROUP_AUTO) +diff --git a/src/core/cgroup.h b/src/core/cgroup.h +index 786bd71..0a079e9 100644 +--- a/src/core/cgroup.h ++++ b/src/core/cgroup.h +@@ -77,7 +77,6 @@ struct CGroupContext { + LIST_HEAD(CGroupBlockIODeviceBandwidth, blockio_device_bandwidths); + + uint64_t memory_limit; +- uint64_t memory_soft_limit; + + CGroupDevicePolicy device_policy; + LIST_HEAD(CGroupDeviceAllow, device_allow); +diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c +index 1f2a396..9ebcad9 100644 +--- a/src/core/dbus-cgroup.c ++++ b/src/core/dbus-cgroup.c +@@ -133,7 +133,6 @@ const BusProperty bus_cgroup_context_properties[] = { + { "BlockIOWriteBandwidth", bus_cgroup_append_device_bandwidths, "a(st)", 0 }, + { "MemoryAccounting", bus_property_append_bool, "b", offsetof(CGroupContext, memory_accounting) }, + { "MemoryLimit", bus_property_append_uint64, "t", offsetof(CGroupContext, memory_limit) }, +- { "MemorySoftLimit", bus_property_append_uint64, "t", offsetof(CGroupContext, memory_soft_limit) }, + { "DevicePolicy", bus_cgroup_append_device_policy, "s", offsetof(CGroupContext, device_policy) }, + { "DeviceAllow", bus_cgroup_append_device_allow, "a(ss)", 0 }, + {} +@@ -418,21 +417,16 @@ int bus_cgroup_set_property( + + return 1; + +- } else if (streq(name, "MemoryLimit") || streq(name, "MemorySoftLimit")) { ++ } else if (streq(name, "MemoryLimit")) { + + if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_UINT64) + return -EINVAL; + + if (mode != UNIT_CHECK) { + uint64_t limit; +- + dbus_message_iter_get_basic(i, &limit); + +- if (streq(name, "MemoryLimit")) +- c->memory_limit = limit; +- else +- c->memory_soft_limit = limit; +- ++ c->memory_limit = limit; + unit_write_drop_in_private_format(u, mode, name, "%s=%" PRIu64, name, limit); + } + +diff --git a/src/core/dbus-cgroup.h b/src/core/dbus-cgroup.h +index 4ce1e7e..e5ac4c3 100644 +--- a/src/core/dbus-cgroup.h ++++ b/src/core/dbus-cgroup.h +@@ -37,7 +37,6 @@ + " \n" \ + " \n" \ + " \n" \ +- " \n" \ + " \n" \ + " \n" + +diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 +index 3f064a9..31fb7bc 100644 +--- a/src/core/load-fragment-gperf.gperf.m4 ++++ b/src/core/load-fragment-gperf.gperf.m4 +@@ -89,7 +89,6 @@ $1.CPUAccounting, config_parse_bool, 0, + $1.CPUShares, config_parse_cpu_shares, 0, offsetof($1, cgroup_context) + $1.MemoryAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.memory_accounting) + $1.MemoryLimit, config_parse_memory_limit, 0, offsetof($1, cgroup_context) +-$1.MemorySoftLimit, config_parse_memory_limit, 0, offsetof($1, cgroup_context) + $1.DeviceAllow, config_parse_device_allow, 0, offsetof($1, cgroup_context) + $1.DevicePolicy, config_parse_device_policy, 0, offsetof($1, cgroup_context.device_policy) + $1.BlockIOAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.blockio_accounting) +diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c +index ed8602f..6e0a180 100644 +--- a/src/core/load-fragment.c ++++ b/src/core/load-fragment.c +@@ -2015,14 +2015,11 @@ int config_parse_memory_limit( + void *userdata) { + + CGroupContext *c = data; +- uint64_t *limit; + off_t bytes; + int r; + +- limit = streq(lvalue, "MemoryLimit") ? &c->memory_limit : &c->memory_soft_limit; +- + if (isempty(rvalue)) { +- *limit = (uint64_t) -1; ++ c->memory_limit = (uint64_t) -1; + return 0; + } + +@@ -2035,7 +2032,7 @@ int config_parse_memory_limit( + return 0; + } + +- *limit = (uint64_t) bytes; ++ c->memory_limit = (uint64_t) bytes; + return 0; + } + +diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c +index 16da293..1080065 100644 +--- a/src/systemctl/systemctl.c ++++ b/src/systemctl/systemctl.c +@@ -3657,7 +3657,7 @@ static int append_assignment(DBusMessageIter *iter, const char *assignment) { + !dbus_message_iter_append_basic(&sub, DBUS_TYPE_BOOLEAN, &b)) + return log_oom(); + +- } else if (streq(field, "MemoryLimit") || streq(field, "MemorySoftLimit")) { ++ } else if (streq(field, "MemoryLimit")) { + off_t bytes; + uint64_t u; + diff --git a/SOURCES/0053-set-IgnoreOnIsolate-true-for-systemd-cryptsetup-.ser.patch b/SOURCES/0053-set-IgnoreOnIsolate-true-for-systemd-cryptsetup-.ser.patch new file mode 100644 index 0000000..28c3c71 --- /dev/null +++ b/SOURCES/0053-set-IgnoreOnIsolate-true-for-systemd-cryptsetup-.ser.patch @@ -0,0 +1,27 @@ +From 0ac89decd89110fa64fe1f9ff7ff5a271026a272 Mon Sep 17 00:00:00 2001 +From: Andrey Borzenkov +Date: Sun, 29 Sep 2013 15:37:30 +0400 +Subject: [PATCH] set IgnoreOnIsolate=true for systemd-cryptsetup@.service + +When crypttab contains noauto, cryptsetup service does not have any +explicit dependencies. If service is started later manually (directly or via +mount dependency) it will be stopped on isolate. + +mount units already have IgnoreOnIsolate set by default. Set it by +default for cryptsetup units as well. +--- + src/cryptsetup/cryptsetup-generator.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c +index 8792e6b..e1798a3 100644 +--- a/src/cryptsetup/cryptsetup-generator.c ++++ b/src/cryptsetup/cryptsetup-generator.c +@@ -118,6 +118,7 @@ static int create_disk( + "Conflicts=umount.target\n" + "DefaultDependencies=no\n" + "BindsTo=dev-mapper-%i.device\n" ++ "IgnoreOnIsolate=true\n" + "After=systemd-readahead-collect.service systemd-readahead-replay.service\n", + f); + diff --git a/SOURCES/0054-main-don-t-free-fds-array-twice.patch b/SOURCES/0054-main-don-t-free-fds-array-twice.patch new file mode 100644 index 0000000..d9fdedc --- /dev/null +++ b/SOURCES/0054-main-don-t-free-fds-array-twice.patch @@ -0,0 +1,21 @@ +From 32eda9ada3dade4c9f6a8a176ee326ccdd61fda8 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 1 Oct 2013 00:06:48 +0200 +Subject: [PATCH] main: don't free fds array twice + +--- + src/core/main.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/core/main.c b/src/core/main.c +index 72bd542..662d16d 100644 +--- a/src/core/main.c ++++ b/src/core/main.c +@@ -1567,6 +1567,7 @@ int main(int argc, char *argv[]) { + /* This will close all file descriptors that were opened, but + * not claimed by any unit. */ + fdset_free(fds); ++ fds = NULL; + + if (serialization) { + fclose(serialization); diff --git a/SOURCES/0055-local-fix-memory-leak-when-putting-together-locale-s.patch b/SOURCES/0055-local-fix-memory-leak-when-putting-together-locale-s.patch new file mode 100644 index 0000000..e17e503 --- /dev/null +++ b/SOURCES/0055-local-fix-memory-leak-when-putting-together-locale-s.patch @@ -0,0 +1,147 @@ +From 64d6d09b47d22db8a82373229c828e7cf1373955 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 1 Oct 2013 00:08:30 +0200 +Subject: [PATCH] local: fix memory leak when putting together locale settings + +Also, we need to use proper strv_env_xyz() calls when putting together +the environment array, since otherwise settings won't be properly +overriden. + +And let's get rid of strv_appendf(), is overkill and there was only one +user. +--- + src/core/locale-setup.c | 31 +++++++++++++++++++++++++++---- + src/core/manager.c | 4 +++- + src/shared/strv.c | 15 --------------- + src/shared/strv.h | 1 - + 4 files changed, 30 insertions(+), 21 deletions(-) + +diff --git a/src/core/locale-setup.c b/src/core/locale-setup.c +index 31374ac..276deb9 100644 +--- a/src/core/locale-setup.c ++++ b/src/core/locale-setup.c +@@ -29,6 +29,7 @@ + #include "virt.h" + #include "fileio.h" + #include "strv.h" ++#include "env-util.h" + + enum { + /* We don't list LC_ALL here on purpose. People should be +@@ -69,7 +70,7 @@ static const char * const variable_names[_VARIABLE_MAX] = { + }; + + int locale_setup(char ***environment) { +- char **env; ++ char **add; + char *variables[_VARIABLE_MAX] = {}; + int r = 0, i; + +@@ -119,22 +120,44 @@ int locale_setup(char ***environment) { + log_warning("Failed to read /etc/locale.conf: %s", strerror(-r)); + } + ++ add = NULL; + for (i = 0; i < _VARIABLE_MAX; i++) { ++ char *s; ++ + if (!variables[i]) + continue; + +- env = strv_appendf(*environment, "%s=%s", variable_names[i], variables[i]); +- if (!env) { ++ s = strjoin(variable_names[i], "=", variables[i], NULL); ++ if (!s) { ++ r = -ENOMEM; ++ goto finish; ++ } ++ ++ if (strv_push(&add, s) < 0) { ++ free(s); ++ r = -ENOMEM; ++ goto finish; ++ } ++ } ++ ++ if (!strv_isempty(add)) { ++ char **e; ++ ++ e = strv_env_merge(2, *environment, add); ++ if (!e) { + r = -ENOMEM; + goto finish; + } + +- *environment = env; ++ strv_free(*environment); ++ *environment = e; + } + + r = 0; + + finish: ++ strv_free(add); ++ + for (i = 0; i < _VARIABLE_MAX; i++) + free(variables[i]); + +diff --git a/src/core/manager.c b/src/core/manager.c +index dadbedd..30b49ff 100644 +--- a/src/core/manager.c ++++ b/src/core/manager.c +@@ -2666,14 +2666,16 @@ void manager_undo_generators(Manager *m) { + } + + int manager_environment_add(Manager *m, char **environment) { +- + char **e = NULL; + assert(m); ++ + e = strv_env_merge(2, m->environment, environment); + if (!e) + return -ENOMEM; ++ + strv_free(m->environment); + m->environment = e; ++ + return 0; + } + +diff --git a/src/shared/strv.c b/src/shared/strv.c +index 2df478f..adeee28 100644 +--- a/src/shared/strv.c ++++ b/src/shared/strv.c +@@ -424,21 +424,6 @@ fail: + return NULL; + } + +-char **strv_appendf(char **l, const char *format, ...) { +- va_list ap; +- _cleanup_free_ char *s = NULL; +- int r; +- +- va_start(ap, format); +- r = vasprintf(&s, format, ap); +- va_end(ap); +- +- if (r < 0) +- return NULL; +- +- return strv_append(l, s); +-} +- + int strv_push(char ***l, char *value) { + char **c; + unsigned n; +diff --git a/src/shared/strv.h b/src/shared/strv.h +index 4e80ea6..d1f2a0e 100644 +--- a/src/shared/strv.h ++++ b/src/shared/strv.h +@@ -42,7 +42,6 @@ unsigned strv_length(char * const *l) _pure_; + char **strv_merge(char **a, char **b); + char **strv_merge_concat(char **a, char **b, const char *suffix); + char **strv_append(char **l, const char *s); +-char **strv_appendf(char **l, const char *format, ...) _printf_attr_(2, 3); + int strv_extend(char ***l, const char *value); + int strv_push(char ***l, char *value); + diff --git a/SOURCES/0056-hashmap-size-hashmap-bucket-array-dynamically.patch b/SOURCES/0056-hashmap-size-hashmap-bucket-array-dynamically.patch new file mode 100644 index 0000000..2d3c916 --- /dev/null +++ b/SOURCES/0056-hashmap-size-hashmap-bucket-array-dynamically.patch @@ -0,0 +1,470 @@ +From 6b28d81fea017382e098c24514ae229fcb0a4a7d Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 1 Oct 2013 00:13:18 +0200 +Subject: [PATCH] hashmap: size hashmap bucket array dynamically + +Instead of fixing the hashmap bucket array to 127 entries dynamically +size it, starting with a smaller one of 31. As soon as a fill level of +75% is reached, quadruple the size, and so on. + +This should siginficantly optimize the lookup time in large tables +(from O(n) back to O(1)), and save memory on smaller tables (which most +are). +--- + src/shared/hashmap.c | 152 ++++++++++++++++++++++++++++++++++++------------ + src/shared/hashmap.h | 1 + + src/test/test-hashmap.c | 28 ++++++++- + 3 files changed, 143 insertions(+), 38 deletions(-) + +diff --git a/src/shared/hashmap.c b/src/shared/hashmap.c +index 4ea1a0f..6330792 100644 +--- a/src/shared/hashmap.c ++++ b/src/shared/hashmap.c +@@ -28,7 +28,7 @@ + #include "hashmap.h" + #include "macro.h" + +-#define NBUCKETS 127 ++#define INITIAL_N_BUCKETS 31 + + struct hashmap_entry { + const void *key; +@@ -42,13 +42,13 @@ struct Hashmap { + compare_func_t compare_func; + + struct hashmap_entry *iterate_list_head, *iterate_list_tail; +- unsigned n_entries; ++ ++ struct hashmap_entry ** buckets; ++ unsigned n_buckets, n_entries; + + bool from_pool; + }; + +-#define BY_HASH(h) ((struct hashmap_entry**) ((uint8_t*) (h) + ALIGN(sizeof(Hashmap)))) +- + struct pool { + struct pool *next; + unsigned n_tiles; +@@ -64,6 +64,11 @@ static void *first_entry_tile = NULL; + static void* allocate_tile(struct pool **first_pool, void **first_tile, size_t tile_size) { + unsigned i; + ++ /* When a tile is released we add it to the list and simply ++ * place the next pointer at its offset 0. */ ++ ++ assert(tile_size >= sizeof(void*)); ++ + if (*first_tile) { + void *r; + +@@ -173,7 +178,7 @@ Hashmap *hashmap_new(hash_func_t hash_func, compare_func_t compare_func) { + + b = is_main_thread(); + +- size = ALIGN(sizeof(Hashmap)) + NBUCKETS * sizeof(struct hashmap_entry*); ++ size = ALIGN(sizeof(Hashmap)) + INITIAL_N_BUCKETS * sizeof(struct hashmap_entry*); + + if (b) { + h = allocate_tile(&first_hashmap_pool, &first_hashmap_tile, size); +@@ -191,23 +196,30 @@ Hashmap *hashmap_new(hash_func_t hash_func, compare_func_t compare_func) { + h->hash_func = hash_func ? hash_func : trivial_hash_func; + h->compare_func = compare_func ? compare_func : trivial_compare_func; + ++ h->n_buckets = INITIAL_N_BUCKETS; + h->n_entries = 0; + h->iterate_list_head = h->iterate_list_tail = NULL; + ++ h->buckets = (struct hashmap_entry**) ((uint8_t*) h + ALIGN(sizeof(Hashmap))); ++ + h->from_pool = b; + + return h; + } + + int hashmap_ensure_allocated(Hashmap **h, hash_func_t hash_func, compare_func_t compare_func) { ++ Hashmap *q; ++ + assert(h); + + if (*h) + return 0; + +- if (!(*h = hashmap_new(hash_func, compare_func))) ++ q = hashmap_new(hash_func, compare_func); ++ if (!q) + return -ENOMEM; + ++ *h = q; + return 0; + } + +@@ -216,11 +228,11 @@ static void link_entry(Hashmap *h, struct hashmap_entry *e, unsigned hash) { + assert(e); + + /* Insert into hash table */ +- e->bucket_next = BY_HASH(h)[hash]; ++ e->bucket_next = h->buckets[hash]; + e->bucket_previous = NULL; +- if (BY_HASH(h)[hash]) +- BY_HASH(h)[hash]->bucket_previous = e; +- BY_HASH(h)[hash] = e; ++ if (h->buckets[hash]) ++ h->buckets[hash]->bucket_previous = e; ++ h->buckets[hash] = e; + + /* Insert into iteration list */ + e->iterate_previous = h->iterate_list_tail; +@@ -260,7 +272,7 @@ static void unlink_entry(Hashmap *h, struct hashmap_entry *e, unsigned hash) { + if (e->bucket_previous) + e->bucket_previous->bucket_next = e->bucket_next; + else +- BY_HASH(h)[hash] = e->bucket_next; ++ h->buckets[hash] = e->bucket_next; + + assert(h->n_entries >= 1); + h->n_entries--; +@@ -272,7 +284,7 @@ static void remove_entry(Hashmap *h, struct hashmap_entry *e) { + assert(h); + assert(e); + +- hash = h->hash_func(e->key) % NBUCKETS; ++ hash = h->hash_func(e->key) % h->n_buckets; + + unlink_entry(h, e, hash); + +@@ -291,6 +303,9 @@ void hashmap_free(Hashmap*h) { + + hashmap_clear(h); + ++ if (h->buckets != (struct hashmap_entry**) ((uint8_t*) h + ALIGN(sizeof(Hashmap)))) ++ free(h->buckets); ++ + if (h->from_pool) + deallocate_tile(&first_hashmap_tile, h); + else +@@ -357,22 +372,72 @@ void hashmap_clear_free_free(Hashmap *h) { + static struct hashmap_entry *hash_scan(Hashmap *h, unsigned hash, const void *key) { + struct hashmap_entry *e; + assert(h); +- assert(hash < NBUCKETS); ++ assert(hash < h->n_buckets); + +- for (e = BY_HASH(h)[hash]; e; e = e->bucket_next) ++ for (e = h->buckets[hash]; e; e = e->bucket_next) + if (h->compare_func(e->key, key) == 0) + return e; + + return NULL; + } + ++static bool resize_buckets(Hashmap *h) { ++ unsigned m; ++ struct hashmap_entry **n, *i; ++ ++ assert(h); ++ ++ if (_likely_(h->n_entries*4 < h->n_buckets*3)) ++ return false; ++ ++ /* Increase by four */ ++ m = (h->n_entries+1)*4-1; ++ ++ /* If we hit OOM we simply risk packed hashmaps... */ ++ n = new0(struct hashmap_entry*, m); ++ if (!n) ++ return false; ++ ++ for (i = h->iterate_list_head; i; i = i->iterate_next) { ++ unsigned hash, x; ++ ++ hash = h->hash_func(i->key); ++ ++ /* First, drop from old bucket table */ ++ if (i->bucket_next) ++ i->bucket_next->bucket_previous = i->bucket_previous; ++ ++ if (i->bucket_previous) ++ i->bucket_previous->bucket_next = i->bucket_next; ++ else ++ h->buckets[hash % h->n_buckets] = i->bucket_next; ++ ++ /* Then, add to new backet table */ ++ x = hash % m; ++ ++ i->bucket_next = n[x]; ++ i->bucket_previous = NULL; ++ if (n[x]) ++ n[x]->bucket_previous = i; ++ n[x] = i; ++ } ++ ++ if (h->buckets != (struct hashmap_entry**) ((uint8_t*) h + ALIGN(sizeof(Hashmap)))) ++ free(h->buckets); ++ ++ h->buckets = n; ++ h->n_buckets = m; ++ ++ return true; ++} ++ + int hashmap_put(Hashmap *h, const void *key, void *value) { + struct hashmap_entry *e; + unsigned hash; + + assert(h); + +- hash = h->hash_func(key) % NBUCKETS; ++ hash = h->hash_func(key) % h->n_buckets; + e = hash_scan(h, hash, key); + if (e) { + if (e->value == value) +@@ -380,6 +445,9 @@ int hashmap_put(Hashmap *h, const void *key, void *value) { + return -EEXIST; + } + ++ if (resize_buckets(h)) ++ hash = h->hash_func(key) % h->n_buckets; ++ + if (h->from_pool) + e = allocate_tile(&first_entry_pool, &first_entry_tile, sizeof(struct hashmap_entry)); + else +@@ -402,7 +470,7 @@ int hashmap_replace(Hashmap *h, const void *key, void *value) { + + assert(h); + +- hash = h->hash_func(key) % NBUCKETS; ++ hash = h->hash_func(key) % h->n_buckets; + e = hash_scan(h, hash, key); + if (e) { + e->key = key; +@@ -419,7 +487,7 @@ int hashmap_update(Hashmap *h, const void *key, void *value) { + + assert(h); + +- hash = h->hash_func(key) % NBUCKETS; ++ hash = h->hash_func(key) % h->n_buckets; + e = hash_scan(h, hash, key); + if (!e) + return -ENOENT; +@@ -435,7 +503,7 @@ void* hashmap_get(Hashmap *h, const void *key) { + if (!h) + return NULL; + +- hash = h->hash_func(key) % NBUCKETS; ++ hash = h->hash_func(key) % h->n_buckets; + e = hash_scan(h, hash, key); + if (!e) + return NULL; +@@ -450,7 +518,7 @@ void* hashmap_get2(Hashmap *h, const void *key, void **key2) { + if (!h) + return NULL; + +- hash = h->hash_func(key) % NBUCKETS; ++ hash = h->hash_func(key) % h->n_buckets; + e = hash_scan(h, hash, key); + if (!e) + return NULL; +@@ -467,7 +535,7 @@ bool hashmap_contains(Hashmap *h, const void *key) { + if (!h) + return false; + +- hash = h->hash_func(key) % NBUCKETS; ++ hash = h->hash_func(key) % h->n_buckets; + + if (!hash_scan(h, hash, key)) + return false; +@@ -483,7 +551,7 @@ void* hashmap_remove(Hashmap *h, const void *key) { + if (!h) + return NULL; + +- hash = h->hash_func(key) % NBUCKETS; ++ hash = h->hash_func(key) % h->n_buckets; + + if (!(e = hash_scan(h, hash, key))) + return NULL; +@@ -501,11 +569,11 @@ int hashmap_remove_and_put(Hashmap *h, const void *old_key, const void *new_key, + if (!h) + return -ENOENT; + +- old_hash = h->hash_func(old_key) % NBUCKETS; ++ old_hash = h->hash_func(old_key) % h->n_buckets; + if (!(e = hash_scan(h, old_hash, old_key))) + return -ENOENT; + +- new_hash = h->hash_func(new_key) % NBUCKETS; ++ new_hash = h->hash_func(new_key) % h->n_buckets; + if (hash_scan(h, new_hash, new_key)) + return -EEXIST; + +@@ -526,11 +594,11 @@ int hashmap_remove_and_replace(Hashmap *h, const void *old_key, const void *new_ + if (!h) + return -ENOENT; + +- old_hash = h->hash_func(old_key) % NBUCKETS; ++ old_hash = h->hash_func(old_key) % h->n_buckets; + if (!(e = hash_scan(h, old_hash, old_key))) + return -ENOENT; + +- new_hash = h->hash_func(new_key) % NBUCKETS; ++ new_hash = h->hash_func(new_key) % h->n_buckets; + if ((k = hash_scan(h, new_hash, new_key))) + if (e != k) + remove_entry(h, k); +@@ -552,9 +620,10 @@ void* hashmap_remove_value(Hashmap *h, const void *key, void *value) { + if (!h) + return NULL; + +- hash = h->hash_func(key) % NBUCKETS; ++ hash = h->hash_func(key) % h->n_buckets; + +- if (!(e = hash_scan(h, hash, key))) ++ e = hash_scan(h, hash, key); ++ if (!e) + return NULL; + + if (e->value != value) +@@ -642,9 +711,10 @@ void *hashmap_iterate_skip(Hashmap *h, const void *key, Iterator *i) { + if (!h) + return NULL; + +- hash = h->hash_func(key) % NBUCKETS; ++ hash = h->hash_func(key) % h->n_buckets; + +- if (!(e = hash_scan(h, hash, key))) ++ e = hash_scan(h, hash, key); ++ if (!e) + return NULL; + + *i = (Iterator) e; +@@ -723,6 +793,14 @@ unsigned hashmap_size(Hashmap *h) { + return h->n_entries; + } + ++unsigned hashmap_buckets(Hashmap *h) { ++ ++ if (!h) ++ return 0; ++ ++ return h->n_buckets; ++} ++ + bool hashmap_isempty(Hashmap *h) { + + if (!h) +@@ -766,12 +844,12 @@ void hashmap_move(Hashmap *h, Hashmap *other) { + + n = e->iterate_next; + +- h_hash = h->hash_func(e->key) % NBUCKETS; ++ h_hash = h->hash_func(e->key) % h->n_buckets; + + if (hash_scan(h, h_hash, e->key)) + continue; + +- other_hash = other->hash_func(e->key) % NBUCKETS; ++ other_hash = other->hash_func(e->key) % other->n_buckets; + + unlink_entry(other, e, other_hash); + link_entry(h, e, h_hash); +@@ -787,12 +865,13 @@ int hashmap_move_one(Hashmap *h, Hashmap *other, const void *key) { + + assert(h); + +- h_hash = h->hash_func(key) % NBUCKETS; ++ h_hash = h->hash_func(key) % h->n_buckets; + if (hash_scan(h, h_hash, key)) + return -EEXIST; + +- other_hash = other->hash_func(key) % NBUCKETS; +- if (!(e = hash_scan(other, other_hash, key))) ++ other_hash = other->hash_func(key) % other->n_buckets; ++ e = hash_scan(other, other_hash, key); ++ if (!e) + return -ENOENT; + + unlink_entry(other, e, other_hash); +@@ -806,7 +885,8 @@ Hashmap *hashmap_copy(Hashmap *h) { + + assert(h); + +- if (!(copy = hashmap_new(h->hash_func, h->compare_func))) ++ copy = hashmap_new(h->hash_func, h->compare_func); ++ if (!copy) + return NULL; + + if (hashmap_merge(copy, h) < 0) { +@@ -845,7 +925,7 @@ void *hashmap_next(Hashmap *h, const void *key) { + if (!h) + return NULL; + +- hash = h->hash_func(key) % NBUCKETS; ++ hash = h->hash_func(key) % h->n_buckets; + e = hash_scan(h, hash, key); + if (!e) + return NULL; +diff --git a/src/shared/hashmap.h b/src/shared/hashmap.h +index 15b7e27..3d4f672 100644 +--- a/src/shared/hashmap.h ++++ b/src/shared/hashmap.h +@@ -76,6 +76,7 @@ int hashmap_move_one(Hashmap *h, Hashmap *other, const void *key); + + unsigned hashmap_size(Hashmap *h) _pure_; + bool hashmap_isempty(Hashmap *h) _pure_; ++unsigned hashmap_buckets(Hashmap *h) _pure_; + + void *hashmap_iterate(Hashmap *h, Iterator *i, const void **key); + void *hashmap_iterate_backwards(Hashmap *h, Iterator *i, const void **key); +diff --git a/src/test/test-hashmap.c b/src/test/test-hashmap.c +index 2aead79..349e8e5 100644 +--- a/src/test/test-hashmap.c ++++ b/src/test/test-hashmap.c +@@ -467,6 +467,30 @@ static void test_hashmap_get(void) { + hashmap_free_free(m); + } + ++static void test_hashmap_many(void) { ++ Hashmap *h; ++ unsigned i; ++ ++#define N_ENTRIES 100000 ++ ++ assert_se(h = hashmap_new(NULL, NULL)); ++ ++ for (i = 1; i < N_ENTRIES*3; i+=3) { ++ assert_se(hashmap_put(h, UINT_TO_PTR(i), UINT_TO_PTR(i)) >= 0); ++ assert_se(PTR_TO_UINT(hashmap_get(h, UINT_TO_PTR(i))) == i); ++ } ++ ++ for (i = 1; i < N_ENTRIES*3; i++) ++ assert_se(hashmap_contains(h, UINT_TO_PTR(i)) == (i % 3 == 1)); ++ ++ log_info("%u <= %u * 0.75 = %g", hashmap_size(h), hashmap_buckets(h), hashmap_buckets(h) * 0.75); ++ ++ assert_se(hashmap_size(h) <= hashmap_buckets(h) * 0.75); ++ assert_se(hashmap_size(h) == N_ENTRIES); ++ ++ hashmap_free(h); ++} ++ + static void test_uint64_compare_func(void) { + assert_se(uint64_compare_func("a", "a") == 0); + assert_se(uint64_compare_func("a", "b") == -1); +@@ -484,8 +508,7 @@ static void test_string_compare_func(void) { + assert_se(string_compare_func("fred", "fred") == 0); + } + +-int main(int argc, const char *argv[]) +-{ ++int main(int argc, const char *argv[]) { + test_hashmap_copy(); + test_hashmap_get_strv(); + test_hashmap_move_one(); +@@ -502,6 +525,7 @@ int main(int argc, const char *argv[]) + test_hashmap_isempty(); + test_hashmap_get(); + test_hashmap_size(); ++ test_hashmap_many(); + test_uint64_compare_func(); + test_trivial_compare_func(); + test_string_compare_func(); diff --git a/SOURCES/0057-smack-setup-fix-path-to-Smack-CIPSO-mappings.patch b/SOURCES/0057-smack-setup-fix-path-to-Smack-CIPSO-mappings.patch new file mode 100644 index 0000000..701d29c --- /dev/null +++ b/SOURCES/0057-smack-setup-fix-path-to-Smack-CIPSO-mappings.patch @@ -0,0 +1,25 @@ +From d235f3854b80b7e3bedd96391bd9ea8db5b8ff93 Mon Sep 17 00:00:00 2001 +From: Patrick McCarty +Date: Mon, 30 Sep 2013 17:43:38 -0700 +Subject: [PATCH] smack-setup: fix path to Smack/CIPSO mappings + +The correct path to the dir with CIPSO mappings is /etc/smack/cipso.d/; +/etc/smack/cipso is a file that can include these mappings as well, +though it is no longer supported in upstream libsmack. +--- + src/core/smack-setup.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/core/smack-setup.c b/src/core/smack-setup.c +index d67a84a..1434dea 100644 +--- a/src/core/smack-setup.c ++++ b/src/core/smack-setup.c +@@ -40,7 +40,7 @@ + #include "label.h" + + #define SMACK_CONFIG "/etc/smack/accesses.d/" +-#define CIPSO_CONFIG "/etc/smack/cipso/" ++#define CIPSO_CONFIG "/etc/smack/cipso.d/" + + #ifdef HAVE_SMACK + diff --git a/SOURCES/0058-fix-lingering-references-to-var-lib-backlight-random.patch b/SOURCES/0058-fix-lingering-references-to-var-lib-backlight-random.patch new file mode 100644 index 0000000..498eca3 --- /dev/null +++ b/SOURCES/0058-fix-lingering-references-to-var-lib-backlight-random.patch @@ -0,0 +1,51 @@ +From 43c6d0a4d2fec97929de9aef0a36815d82ad22ac Mon Sep 17 00:00:00 2001 +From: Dave Reisner +Date: Wed, 2 Oct 2013 07:46:24 -0400 +Subject: [PATCH] fix lingering references to /var/lib/{backlight,random-seed} + +This should have been part of ef5bfcf668e6029faa78534dfe. +--- + man/systemd-backlight@.service.xml | 2 +- + man/systemd-random-seed.service.xml | 2 +- + units/systemd-backlight@.service.in | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/man/systemd-backlight@.service.xml b/man/systemd-backlight@.service.xml +index 2b73625..4318964 100644 +--- a/man/systemd-backlight@.service.xml ++++ b/man/systemd-backlight@.service.xml +@@ -58,7 +58,7 @@ + is a service that restores the display backlight + brightness at early-boot and saves it at shutdown. On + disk, the backlight brightness is stored in +- /var/lib/backlight/. Note that by ++ /var/lib/systemd/backlight/. Note that by + default, only firmware backlight devices are + saved/restored. + +diff --git a/man/systemd-random-seed.service.xml b/man/systemd-random-seed.service.xml +index 8cd14b7..e5cd037 100644 +--- a/man/systemd-random-seed.service.xml ++++ b/man/systemd-random-seed.service.xml +@@ -61,7 +61,7 @@ + for details. Saving/restoring the random seed across + boots increases the amount of available entropy early + at boot. On disk the random seed is stored in +- /var/lib/random-seed. ++ /var/lib/systemd/random-seed. + + + +diff --git a/units/systemd-backlight@.service.in b/units/systemd-backlight@.service.in +index b0e75db..5caa5d5 100644 +--- a/units/systemd-backlight@.service.in ++++ b/units/systemd-backlight@.service.in +@@ -9,7 +9,7 @@ + Description=Load/Save Screen Backlight Brightness of %I + Documentation=man:systemd-backlight@.service(8) + DefaultDependencies=no +-RequiresMountsFor=/var/lib/backlight ++RequiresMountsFor=/var/lib/systemd/backlight + Conflicts=shutdown.target + After=systemd-readahead-collect.service systemd-readahead-replay.service systemd-remount-fs.service + Before=sysinit.target shutdown.target diff --git a/SOURCES/0059-cryptsetup-fix-OOM-handling-when-parsing-mount-optio.patch b/SOURCES/0059-cryptsetup-fix-OOM-handling-when-parsing-mount-optio.patch new file mode 100644 index 0000000..dbcb754 --- /dev/null +++ b/SOURCES/0059-cryptsetup-fix-OOM-handling-when-parsing-mount-optio.patch @@ -0,0 +1,45 @@ +From c201b69ff022a9527323d2445b11861ccbf3cfad Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 2 Oct 2013 19:36:28 +0200 +Subject: [PATCH] cryptsetup: fix OOM handling when parsing mount options + +--- + src/cryptsetup/cryptsetup.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c +index 22b5eea..769c3e4 100644 +--- a/src/cryptsetup/cryptsetup.c ++++ b/src/cryptsetup/cryptsetup.c +@@ -74,7 +74,7 @@ static int parse_one_option(const char *option) { + + t = strdup(option+7); + if (!t) +- return -ENOMEM; ++ return log_oom(); + + free(opt_cipher); + opt_cipher = t; +@@ -89,9 +89,10 @@ static int parse_one_option(const char *option) { + } else if (startswith(option, "tcrypt-keyfile=")) { + + opt_type = CRYPT_TCRYPT; +- if (path_is_absolute(option+15)) +- opt_tcrypt_keyfiles = strv_append(opt_tcrypt_keyfiles, strdup(option+15)); +- else ++ if (path_is_absolute(option+15)) { ++ if (strv_extend(&opt_tcrypt_keyfiles, option + 15) < 0) ++ return log_oom(); ++ } else + log_error("Key file path '%s' is not absolute. Ignoring.", option+15); + + } else if (startswith(option, "keyfile-size=")) { +@@ -113,7 +114,7 @@ static int parse_one_option(const char *option) { + + t = strdup(option+5); + if (!t) +- return -ENOMEM; ++ return log_oom(); + + free(opt_hash); + opt_hash = t; diff --git a/SOURCES/0060-journald-add-missing-error-check.patch b/SOURCES/0060-journald-add-missing-error-check.patch new file mode 100644 index 0000000..8dff9a2 --- /dev/null +++ b/SOURCES/0060-journald-add-missing-error-check.patch @@ -0,0 +1,22 @@ +From 69538099422c80bfef9c8761645c0a3fc64cc803 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 2 Oct 2013 19:36:43 +0200 +Subject: [PATCH] journald: add missing error check + +--- + src/journal/journal-file.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c +index 1236403..81c344f 100644 +--- a/src/journal/journal-file.c ++++ b/src/journal/journal-file.c +@@ -907,6 +907,8 @@ static int journal_file_append_field( + + osize = offsetof(Object, field.payload) + size; + r = journal_file_append_object(f, OBJECT_FIELD, osize, &o, &p); ++ if (r < 0) ++ return r; + + o->field.hash = htole64(hash); + memcpy(o->field.payload, field, size); diff --git a/SOURCES/0061-bus-fix-potentially-uninitialized-memory-access.patch b/SOURCES/0061-bus-fix-potentially-uninitialized-memory-access.patch new file mode 100644 index 0000000..ac10649 --- /dev/null +++ b/SOURCES/0061-bus-fix-potentially-uninitialized-memory-access.patch @@ -0,0 +1,31 @@ +From 6ea4084c96dd151eca88b3277148e249e3eebe38 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 2 Oct 2013 19:37:11 +0200 +Subject: [PATCH] bus: fix potentially uninitialized memory access + +--- + src/libsystemd-bus/bus-internal.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/libsystemd-bus/bus-internal.c b/src/libsystemd-bus/bus-internal.c +index 0e66f3d..cac948e 100644 +--- a/src/libsystemd-bus/bus-internal.c ++++ b/src/libsystemd-bus/bus-internal.c +@@ -63,7 +63,7 @@ bool object_path_is_valid(const char *p) { + + bool interface_name_is_valid(const char *p) { + const char *q; +- bool dot, found_dot; ++ bool dot, found_dot = false; + + if (isempty(p)) + return false; +@@ -103,7 +103,7 @@ bool interface_name_is_valid(const char *p) { + + bool service_name_is_valid(const char *p) { + const char *q; +- bool dot, found_dot, unique; ++ bool dot, found_dot = false, unique; + + if (isempty(p)) + return false; diff --git a/SOURCES/0062-dbus-fix-return-value-of-dispatch_rqueue.patch b/SOURCES/0062-dbus-fix-return-value-of-dispatch_rqueue.patch new file mode 100644 index 0000000..010cdd1 --- /dev/null +++ b/SOURCES/0062-dbus-fix-return-value-of-dispatch_rqueue.patch @@ -0,0 +1,27 @@ +From 26a238ce83143c6bac8afa4639ba4dcfd9d48ca7 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 2 Oct 2013 19:37:30 +0200 +Subject: [PATCH] dbus: fix return value of dispatch_rqueue() + +--- + src/libsystemd-bus/sd-bus.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/libsystemd-bus/sd-bus.c b/src/libsystemd-bus/sd-bus.c +index 3f766fb..db0880f 100644 +--- a/src/libsystemd-bus/sd-bus.c ++++ b/src/libsystemd-bus/sd-bus.c +@@ -1215,11 +1215,11 @@ static int dispatch_rqueue(sd_bus *bus, sd_bus_message **m) { + if (r == 0) + return ret; + +- r = 1; ++ ret = 1; + } while (!z); + + *m = z; +- return 1; ++ return ret; + } + + int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *serial) { diff --git a/SOURCES/0063-modules-load-fix-error-handling.patch b/SOURCES/0063-modules-load-fix-error-handling.patch new file mode 100644 index 0000000..8859cae --- /dev/null +++ b/SOURCES/0063-modules-load-fix-error-handling.patch @@ -0,0 +1,24 @@ +From caf4ebe6cde955a39445b7a94f1173fef3d40d95 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 2 Oct 2013 19:37:44 +0200 +Subject: [PATCH] modules-load: fix error handling + +--- + src/modules-load/modules-load.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/modules-load/modules-load.c b/src/modules-load/modules-load.c +index 7b19ee0..49ee420 100644 +--- a/src/modules-load/modules-load.c ++++ b/src/modules-load/modules-load.c +@@ -302,8 +302,8 @@ int main(int argc, char *argv[]) { + + STRV_FOREACH(i, arg_proc_cmdline_modules) { + k = load_module(ctx, *i); +- if (k < 0) +- r = EXIT_FAILURE; ++ if (k < 0 && r == 0) ++ r = k; + } + + r = conf_files_list_nulstr(&files, ".conf", NULL, conf_file_dirs); diff --git a/SOURCES/0064-efi-never-call-qsort-on-potentially-NULL-arrays.patch b/SOURCES/0064-efi-never-call-qsort-on-potentially-NULL-arrays.patch new file mode 100644 index 0000000..d4518da --- /dev/null +++ b/SOURCES/0064-efi-never-call-qsort-on-potentially-NULL-arrays.patch @@ -0,0 +1,23 @@ +From 8744e02186cd7253aebc84043de7455ef0044e2d Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 2 Oct 2013 19:38:09 +0200 +Subject: [PATCH] efi: never call qsort on potentially NULL arrays + +--- + src/shared/efivars.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/shared/efivars.c b/src/shared/efivars.c +index 8d004ba..99340c9 100644 +--- a/src/shared/efivars.c ++++ b/src/shared/efivars.c +@@ -383,7 +383,8 @@ int efi_get_boot_options(uint16_t **options) { + list[count ++] = id; + } + +- qsort(list, count, sizeof(uint16_t), cmp_uint16); ++ if (list) ++ qsort(list, count, sizeof(uint16_t), cmp_uint16); + + *options = list; + return count; diff --git a/SOURCES/0065-strv-don-t-access-potentially-NULL-string-arrays.patch b/SOURCES/0065-strv-don-t-access-potentially-NULL-string-arrays.patch new file mode 100644 index 0000000..450fb66 --- /dev/null +++ b/SOURCES/0065-strv-don-t-access-potentially-NULL-string-arrays.patch @@ -0,0 +1,24 @@ +From fb197fc897370c0ea840099e1c8da6353ea12514 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 2 Oct 2013 19:38:28 +0200 +Subject: [PATCH] strv: don't access potentially NULL string arrays + +--- + src/shared/env-util.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/shared/env-util.c b/src/shared/env-util.c +index 5e29629..7976881 100644 +--- a/src/shared/env-util.c ++++ b/src/shared/env-util.c +@@ -405,7 +405,9 @@ char **strv_env_clean_log(char **e, const char *message) { + e[k++] = *p; + } + +- e[k] = NULL; ++ if (e) ++ e[k] = NULL; ++ + return e; + } + diff --git a/SOURCES/0066-mkdir-pass-a-proper-function-pointer-to-mkdir_safe_i.patch b/SOURCES/0066-mkdir-pass-a-proper-function-pointer-to-mkdir_safe_i.patch new file mode 100644 index 0000000..6f6f40a --- /dev/null +++ b/SOURCES/0066-mkdir-pass-a-proper-function-pointer-to-mkdir_safe_i.patch @@ -0,0 +1,22 @@ +From 56c6d3913e4cd7160b14f9f8a9c7b232444a5235 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 2 Oct 2013 19:38:52 +0200 +Subject: [PATCH] mkdir: pass a proper function pointer to mkdir_safe_internal + +--- + src/shared/mkdir.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/shared/mkdir.c b/src/shared/mkdir.c +index b7e5c6e..43c6ea6 100644 +--- a/src/shared/mkdir.c ++++ b/src/shared/mkdir.c +@@ -53,7 +53,7 @@ int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, mkd + } + + int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid) { +- return mkdir_safe_internal(path, mode, uid, gid, false); ++ return mkdir_safe_internal(path, mode, uid, gid, mkdir); + } + + static int is_dir(const char* path) { diff --git a/SOURCES/0067-tmpfiles.d-include-setgid-perms-for-run-log-journal.patch b/SOURCES/0067-tmpfiles.d-include-setgid-perms-for-run-log-journal.patch new file mode 100644 index 0000000..68c461f --- /dev/null +++ b/SOURCES/0067-tmpfiles.d-include-setgid-perms-for-run-log-journal.patch @@ -0,0 +1,23 @@ +From 6a89a85811f364d1df7c5a6f992132bec693273d Mon Sep 17 00:00:00 2001 +From: Dave Reisner +Date: Wed, 2 Oct 2013 15:35:16 -0400 +Subject: [PATCH] tmpfiles.d: include setgid perms for /run/log/journal + +4608af4333d0f7f5 set permissions for journal storage on persistent disk +but not the volatile storage. + +ref: https://bugs.archlinux.org/task/37170 +--- + tmpfiles.d/systemd.conf | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/tmpfiles.d/systemd.conf b/tmpfiles.d/systemd.conf +index c397c71..ae292a0 100644 +--- a/tmpfiles.d/systemd.conf ++++ b/tmpfiles.d/systemd.conf +@@ -26,3 +26,5 @@ F /run/nologin 0644 - - - "System is booting up." + + m /var/log/journal 2755 root systemd-journal - - + m /var/log/journal/%m 2755 root systemd-journal - - ++m /run/log/journal 2755 root systemd-journal - - ++m /run/log/journal/%m 2755 root systemd-journal - - diff --git a/SOURCES/0068-gpt-auto-generator-exit-immediately-if-in-container.patch b/SOURCES/0068-gpt-auto-generator-exit-immediately-if-in-container.patch new file mode 100644 index 0000000..461eb0b --- /dev/null +++ b/SOURCES/0068-gpt-auto-generator-exit-immediately-if-in-container.patch @@ -0,0 +1,37 @@ +From b5515ebda086ada98da101c72455668a91841749 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Thu, 3 Oct 2013 22:13:01 -0400 +Subject: [PATCH] gpt-auto-generator: exit immediately if in container + +Otherwise we get an ugly warning when running systemd in +a container. +--- + src/gpt-auto-generator/gpt-auto-generator.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c +index ca54925..d2b4213 100644 +--- a/src/gpt-auto-generator/gpt-auto-generator.c ++++ b/src/gpt-auto-generator/gpt-auto-generator.c +@@ -38,6 +38,7 @@ + #include "libudev.h" + #include "special.h" + #include "unit-name.h" ++#include "virt.h" + + /* TODO: + * +@@ -481,6 +482,13 @@ int main(int argc, char *argv[]) { + umask(0022); + + if (in_initrd()) { ++ log_debug("In initrd, exiting."); ++ r = 0; ++ goto finish; ++ } ++ ++ if (detect_container(NULL) > 0) { ++ log_debug("In a container, exiting."); + r = 0; + goto finish; + } diff --git a/SOURCES/0069-systemd-order-remote-mounts-from-mountinfo-before-re.patch b/SOURCES/0069-systemd-order-remote-mounts-from-mountinfo-before-re.patch new file mode 100644 index 0000000..11bc34e --- /dev/null +++ b/SOURCES/0069-systemd-order-remote-mounts-from-mountinfo-before-re.patch @@ -0,0 +1,38 @@ +From e6d71d64929cff5bbcfe56dc185062f86fd2a202 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Thu, 3 Oct 2013 22:15:08 -0400 +Subject: [PATCH] systemd: order remote mounts from mountinfo before + remote-fs.target + +Usually the network is stopped before filesystems are umounted. +Ordering network filesystems before remote-fs.target means that their +unmounting will be performed earlier, and can terminate sucessfully. + +https://bugs.freedesktop.org/show_bug.cgi?id=70002 +--- + src/core/mount.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/src/core/mount.c b/src/core/mount.c +index 3d46557..93bfa99 100644 +--- a/src/core/mount.c ++++ b/src/core/mount.c +@@ -1440,6 +1440,9 @@ static int mount_add_one( + + u = manager_get_unit(m, e); + if (!u) { ++ const char* const target = ++ fstype_is_network(fstype) ? SPECIAL_REMOTE_FS_TARGET : SPECIAL_LOCAL_FS_TARGET; ++ + delete = true; + + u = unit_new(m, sizeof(Mount)); +@@ -1466,7 +1469,7 @@ static int mount_add_one( + goto fail; + } + +- r = unit_add_dependency_by_name(u, UNIT_BEFORE, SPECIAL_LOCAL_FS_TARGET, NULL, true); ++ r = unit_add_dependency_by_name(u, UNIT_BEFORE, target, NULL, true); + if (r < 0) + goto fail; + diff --git a/SOURCES/0070-manager-when-verifying-whether-clients-may-change-en.patch b/SOURCES/0070-manager-when-verifying-whether-clients-may-change-en.patch new file mode 100644 index 0000000..6a0ac45 --- /dev/null +++ b/SOURCES/0070-manager-when-verifying-whether-clients-may-change-en.patch @@ -0,0 +1,42 @@ +From d36d41d6a28ae21da6e6e032f9988049bad0cea3 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Fri, 4 Oct 2013 17:01:37 +0200 +Subject: [PATCH] manager: when verifying whether clients may change + environment using selinux check for "reload" rather "reboot" + +This appears to be a copy/paste error. +--- + src/core/dbus-manager.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c +index 676a07f..8f4d017 100644 +--- a/src/core/dbus-manager.c ++++ b/src/core/dbus-manager.c +@@ -1397,7 +1397,7 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, + _cleanup_strv_free_ char **l = NULL; + char **e = NULL; + +- SELINUX_ACCESS_CHECK(connection, message, "reboot"); ++ SELINUX_ACCESS_CHECK(connection, message, "reload"); + + r = bus_parse_strv(message, &l); + if (r == -ENOMEM) +@@ -1424,7 +1424,7 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, + _cleanup_strv_free_ char **l = NULL; + char **e = NULL; + +- SELINUX_ACCESS_CHECK(connection, message, "reboot"); ++ SELINUX_ACCESS_CHECK(connection, message, "reload"); + + r = bus_parse_strv(message, &l); + if (r == -ENOMEM) +@@ -1452,7 +1452,7 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, + char **f = NULL; + DBusMessageIter iter; + +- SELINUX_ACCESS_CHECK(connection, message, "reboot"); ++ SELINUX_ACCESS_CHECK(connection, message, "reload"); + + if (!dbus_message_iter_init(message, &iter)) + goto oom; diff --git a/SOURCES/0071-mount-check-for-NULL-before-reading-pm-what.patch b/SOURCES/0071-mount-check-for-NULL-before-reading-pm-what.patch new file mode 100644 index 0000000..ca14af6 --- /dev/null +++ b/SOURCES/0071-mount-check-for-NULL-before-reading-pm-what.patch @@ -0,0 +1,26 @@ +From 1f8cb5185ca41b891ebfa2e6aed093be49b958ce Mon Sep 17 00:00:00 2001 +From: Dave Reisner +Date: Fri, 4 Oct 2013 18:22:40 -0400 +Subject: [PATCH] mount: check for NULL before reading pm->what + +Since a57f7e2c828b85, a mount unit with garbage in it would cause +systemd to crash on loading it. + +ref: https://bugs.freedesktop.org/show_bug.cgi?id=70148 +--- + src/core/mount.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/core/mount.c b/src/core/mount.c +index 93bfa99..db055f0 100644 +--- a/src/core/mount.c ++++ b/src/core/mount.c +@@ -182,7 +182,7 @@ static int mount_add_mount_links(Mount *m) { + * for the source path (if this is a bind mount) to be + * available. */ + pm = get_mount_parameters_fragment(m); +- if (pm && path_is_absolute(pm->what)) { ++ if (pm && pm->what && path_is_absolute(pm->what)) { + r = unit_require_mounts_for(UNIT(m), pm->what); + if (r < 0) + return r; diff --git a/SOURCES/0072-core-do-not-add-what-to-RequiresMountsFor-for-networ.patch b/SOURCES/0072-core-do-not-add-what-to-RequiresMountsFor-for-networ.patch new file mode 100644 index 0000000..de392ad --- /dev/null +++ b/SOURCES/0072-core-do-not-add-what-to-RequiresMountsFor-for-networ.patch @@ -0,0 +1,178 @@ +From 37d5a05d8444e816937fb6736b35a9bc7de0865d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Sat, 5 Oct 2013 13:09:43 -0400 +Subject: [PATCH] core: do not add "what" to RequiresMountsFor for network + mounts + +For cifs mount like //server/share, we would get +RequiresMountsFor=/server/share, which probably isn't +harmful, but quite confusing. + +Unfortunately a bunch of static functions had to be moved +up, but patch is really one line. +--- + src/core/mount.c | 137 ++++++++++++++++++++++++++++--------------------------- + 1 file changed, 70 insertions(+), 67 deletions(-) + +diff --git a/src/core/mount.c b/src/core/mount.c +index db055f0..70cd372 100644 +--- a/src/core/mount.c ++++ b/src/core/mount.c +@@ -59,6 +59,72 @@ static const UnitActiveState state_translation_table[_MOUNT_STATE_MAX] = { + [MOUNT_FAILED] = UNIT_FAILED + }; + ++static char* mount_test_option(const char *haystack, const char *needle) { ++ struct mntent me = { .mnt_opts = (char*) haystack }; ++ ++ assert(needle); ++ ++ /* Like glibc's hasmntopt(), but works on a string, not a ++ * struct mntent */ ++ ++ if (!haystack) ++ return NULL; ++ ++ return hasmntopt(&me, needle); ++} ++ ++static bool mount_is_network(MountParameters *p) { ++ assert(p); ++ ++ if (mount_test_option(p->options, "_netdev")) ++ return true; ++ ++ if (p->fstype && fstype_is_network(p->fstype)) ++ return true; ++ ++ return false; ++} ++ ++static bool mount_is_bind(MountParameters *p) { ++ assert(p); ++ ++ if (mount_test_option(p->options, "bind")) ++ return true; ++ ++ if (p->fstype && streq(p->fstype, "bind")) ++ return true; ++ ++ if (mount_test_option(p->options, "rbind")) ++ return true; ++ ++ if (p->fstype && streq(p->fstype, "rbind")) ++ return true; ++ ++ return false; ++} ++ ++static bool mount_is_auto(MountParameters *p) { ++ assert(p); ++ ++ return !mount_test_option(p->options, "noauto"); ++} ++ ++static bool needs_quota(MountParameters *p) { ++ assert(p); ++ ++ if (mount_is_network(p)) ++ return false; ++ ++ if (mount_is_bind(p)) ++ return false; ++ ++ return mount_test_option(p->options, "usrquota") || ++ mount_test_option(p->options, "grpquota") || ++ mount_test_option(p->options, "quota") || ++ mount_test_option(p->options, "usrjquota") || ++ mount_test_option(p->options, "grpjquota"); ++} ++ + static void mount_init(Unit *u) { + Mount *m = MOUNT(u); + +@@ -182,7 +248,10 @@ static int mount_add_mount_links(Mount *m) { + * for the source path (if this is a bind mount) to be + * available. */ + pm = get_mount_parameters_fragment(m); +- if (pm && pm->what && path_is_absolute(pm->what)) { ++ if (pm && pm->what && ++ path_is_absolute(pm->what) && ++ !mount_is_network(pm)) { ++ + r = unit_require_mounts_for(UNIT(m), pm->what); + if (r < 0) + return r; +@@ -214,72 +283,6 @@ static int mount_add_mount_links(Mount *m) { + return 0; + } + +-static char* mount_test_option(const char *haystack, const char *needle) { +- struct mntent me = { .mnt_opts = (char*) haystack }; +- +- assert(needle); +- +- /* Like glibc's hasmntopt(), but works on a string, not a +- * struct mntent */ +- +- if (!haystack) +- return NULL; +- +- return hasmntopt(&me, needle); +-} +- +-static bool mount_is_network(MountParameters *p) { +- assert(p); +- +- if (mount_test_option(p->options, "_netdev")) +- return true; +- +- if (p->fstype && fstype_is_network(p->fstype)) +- return true; +- +- return false; +-} +- +-static bool mount_is_bind(MountParameters *p) { +- assert(p); +- +- if (mount_test_option(p->options, "bind")) +- return true; +- +- if (p->fstype && streq(p->fstype, "bind")) +- return true; +- +- if (mount_test_option(p->options, "rbind")) +- return true; +- +- if (p->fstype && streq(p->fstype, "rbind")) +- return true; +- +- return false; +-} +- +-static bool mount_is_auto(MountParameters *p) { +- assert(p); +- +- return !mount_test_option(p->options, "noauto"); +-} +- +-static bool needs_quota(MountParameters *p) { +- assert(p); +- +- if (mount_is_network(p)) +- return false; +- +- if (mount_is_bind(p)) +- return false; +- +- return mount_test_option(p->options, "usrquota") || +- mount_test_option(p->options, "grpquota") || +- mount_test_option(p->options, "quota") || +- mount_test_option(p->options, "usrjquota") || +- mount_test_option(p->options, "grpjquota"); +-} +- + static int mount_add_device_links(Mount *m) { + MountParameters *p; + bool device_wants_mount = false; diff --git a/SOURCES/0073-systemd-serialize-deserialize-forbid_restart-value.patch b/SOURCES/0073-systemd-serialize-deserialize-forbid_restart-value.patch new file mode 100644 index 0000000..adcc980 --- /dev/null +++ b/SOURCES/0073-systemd-serialize-deserialize-forbid_restart-value.patch @@ -0,0 +1,48 @@ +From 901779a7633bcb9831e14fd80eb6db0a22c39f22 Mon Sep 17 00:00:00 2001 +From: Sylvia Else +Date: Sun, 6 Oct 2013 23:06:35 -0400 +Subject: [PATCH] systemd: serialize/deserialize forbid_restart value + +The Service type's forbid_restart field was not preserved by +serialization/deserialization, so the fact that the service should not +be restarted after stopping was lost. + +If a systemctl stop foo command has been given, but the foo service +has not yet stopped, and then the systemctl --system daemon-reload was +given, then when the foo service eventually stopped, systemd would +restart it. + +https://bugs.freedesktop.org/show_bug.cgi?id=69800 +--- + src/core/service.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/src/core/service.c b/src/core/service.c +index fc04196..7a78060 100644 +--- a/src/core/service.c ++++ b/src/core/service.c +@@ -2653,6 +2653,9 @@ static int service_serialize(Unit *u, FILE *f, FDSet *fds) { + if (s->exec_context.var_tmp_dir) + unit_serialize_item(u, f, "var-tmp-dir", s->exec_context.var_tmp_dir); + ++ if (s->forbid_restart) ++ unit_serialize_item(u, f, "forbid_restart", yes_no(s->forbid_restart)); ++ + return 0; + } + +@@ -2789,6 +2792,14 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value, + return log_oom(); + + s->exec_context.var_tmp_dir = t; ++ } else if (streq(key, "forbid_restart")) { ++ int b; ++ ++ b = parse_boolean(value); ++ if (b < 0) ++ log_debug_unit(u->id, "Failed to parse forbid_restart value %s", value); ++ else ++ s->forbid_restart = b; + } else + log_debug_unit(u->id, "Unknown serialization key '%s'", key); + diff --git a/SOURCES/0074-core-unify-the-way-we-denote-serialization-attribute.patch b/SOURCES/0074-core-unify-the-way-we-denote-serialization-attribute.patch new file mode 100644 index 0000000..840ea8f --- /dev/null +++ b/SOURCES/0074-core-unify-the-way-we-denote-serialization-attribute.patch @@ -0,0 +1,37 @@ +From 5a09d8f3a0b610beaef3445abb57f45daae6f10f Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 9 Oct 2013 00:13:55 +0200 +Subject: [PATCH] core: unify the way we denote serialization attributes + +--- + src/core/service.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/core/service.c b/src/core/service.c +index 7a78060..cfc8ba6 100644 +--- a/src/core/service.c ++++ b/src/core/service.c +@@ -2654,7 +2654,7 @@ static int service_serialize(Unit *u, FILE *f, FDSet *fds) { + unit_serialize_item(u, f, "var-tmp-dir", s->exec_context.var_tmp_dir); + + if (s->forbid_restart) +- unit_serialize_item(u, f, "forbid_restart", yes_no(s->forbid_restart)); ++ unit_serialize_item(u, f, "forbid-restart", yes_no(s->forbid_restart)); + + return 0; + } +@@ -2792,12 +2792,12 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value, + return log_oom(); + + s->exec_context.var_tmp_dir = t; +- } else if (streq(key, "forbid_restart")) { ++ } else if (streq(key, "forbid-restart")) { + int b; + + b = parse_boolean(value); + if (b < 0) +- log_debug_unit(u->id, "Failed to parse forbid_restart value %s", value); ++ log_debug_unit(u->id, "Failed to parse forbid-restart value %s", value); + else + s->forbid_restart = b; + } else diff --git a/SOURCES/0075-journald-fix-minor-memory-leak.patch b/SOURCES/0075-journald-fix-minor-memory-leak.patch new file mode 100644 index 0000000..627a2e1 --- /dev/null +++ b/SOURCES/0075-journald-fix-minor-memory-leak.patch @@ -0,0 +1,22 @@ +From e5440ffff5a2dd4f46a7f19fd2e9af4abe3e0121 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 9 Oct 2013 04:03:45 +0200 +Subject: [PATCH] journald: fix minor memory leak + +--- + src/journal/journal-vacuum.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/journal/journal-vacuum.c b/src/journal/journal-vacuum.c +index c73ad8f..8d5effb 100644 +--- a/src/journal/journal-vacuum.c ++++ b/src/journal/journal-vacuum.c +@@ -278,6 +278,8 @@ int journal_directory_vacuum( + } else if (errno != ENOENT) + log_warning("Failed to delete %s/%s: %m", directory, p); + ++ free(p); ++ + continue; + } + diff --git a/SOURCES/0076-journald-remove-rotated-file-from-hashmap-when-rotat.patch b/SOURCES/0076-journald-remove-rotated-file-from-hashmap-when-rotat.patch new file mode 100644 index 0000000..bd20427 --- /dev/null +++ b/SOURCES/0076-journald-remove-rotated-file-from-hashmap-when-rotat.patch @@ -0,0 +1,36 @@ +From 42ca19f57176c4b89fc318b5612e644f66ff8d37 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Wed, 9 Oct 2013 22:13:13 -0400 +Subject: [PATCH] journald: remove rotated file from hashmap when rotation + fails + +Before, when the user journal file was rotated, journal_file_rotate +could close the old file and fail to open the new file. In that +case, we would leave the old (deallocated) file in the hashmap. +On subsequent accesses, we could retrieve this stale entry, leading +to a segfault. + +When journal_file_rotate fails with the file pointer set to 0, +old file is certainly gone, and cannot be used anymore. + +https://bugzilla.redhat.com/show_bug.cgi?id=890463 +--- + src/journal/journald-server.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c +index 8007b05..2ae0591 100644 +--- a/src/journal/journald-server.c ++++ b/src/journal/journald-server.c +@@ -321,8 +321,10 @@ void server_rotate(Server *s) { + if (r < 0) + if (f) + log_error("Failed to rotate %s: %s", f->path, strerror(-r)); +- else ++ else { + log_error("Failed to create user journal: %s", strerror(-r)); ++ hashmap_remove(s->user_journals, k); ++ } + else { + hashmap_replace(s->user_journals, k, f); + server_fix_perms(s, f, PTR_TO_UINT32(k)); diff --git a/SOURCES/0077-udevadm.xml-document-resolve-names-option-for-test.patch b/SOURCES/0077-udevadm.xml-document-resolve-names-option-for-test.patch new file mode 100644 index 0000000..3b9a3da --- /dev/null +++ b/SOURCES/0077-udevadm.xml-document-resolve-names-option-for-test.patch @@ -0,0 +1,31 @@ +From b83f0d2ac4845071541737428e9e7b15aa12c982 Mon Sep 17 00:00:00 2001 +From: Dave Reisner +Date: Sun, 13 Oct 2013 17:42:51 -0400 +Subject: [PATCH] udevadm.xml: document --resolve-names option for test + +And remove documentation of the --subsystem flag which doesn't actually +exist. +--- + man/udevadm.xml | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/man/udevadm.xml b/man/udevadm.xml +index d0b257d..b959216 100644 +--- a/man/udevadm.xml ++++ b/man/udevadm.xml +@@ -462,9 +462,13 @@ + + + +- ++ + +- The subsystem string. ++ Specify when udevadm should resolve names of users and groups. ++ When set to early (the default) names will be resolved when the ++ rules are parsed. When set to late names will be resolved for ++ every event. When set to never names will never be resolved and ++ all devices will be owned by root. + + + diff --git a/SOURCES/0078-dbus-common-avoid-leak-in-error-path.patch b/SOURCES/0078-dbus-common-avoid-leak-in-error-path.patch new file mode 100644 index 0000000..c49dbab --- /dev/null +++ b/SOURCES/0078-dbus-common-avoid-leak-in-error-path.patch @@ -0,0 +1,68 @@ +From 8ce4a7267b3e22e1633f2cfdc1898e52c54fb254 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Fri, 11 Oct 2013 19:33:20 -0400 +Subject: [PATCH] dbus-common: avoid leak in error path + +src/shared/dbus-common.c:968:33: warning: Potential leak of memory pointed to by 'l' + return -EINVAL; + ^~~~~~ +--- + src/shared/dbus-common.c | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) + +diff --git a/src/shared/dbus-common.c b/src/shared/dbus-common.c +index c727cae..3ba2d87 100644 +--- a/src/shared/dbus-common.c ++++ b/src/shared/dbus-common.c +@@ -934,7 +934,7 @@ int bus_parse_strv_iter(DBusMessageIter *iter, char ***_l) { + int bus_parse_strv_pairs_iter(DBusMessageIter *iter, char ***_l) { + DBusMessageIter sub, sub2; + unsigned n = 0, i = 0; +- char **l; ++ _cleanup_strv_free_ char **l = NULL; + + assert(iter); + assert(_l); +@@ -953,6 +953,7 @@ int bus_parse_strv_pairs_iter(DBusMessageIter *iter, char ***_l) { + l = new(char*, n*2+1); + if (!l) + return -ENOMEM; ++ l[0] = NULL; /* make sure that l is properly terminated at all times */ + + dbus_message_iter_recurse(iter, &sub); + +@@ -968,26 +969,25 @@ int bus_parse_strv_pairs_iter(DBusMessageIter *iter, char ***_l) { + return -EINVAL; + + l[i] = strdup(a); +- if (!l[i]) { +- strv_free(l); ++ if (!l[i]) + return -ENOMEM; +- } ++ i++; + +- l[++i] = strdup(b); +- if (!l[i]) { +- strv_free(l); ++ l[i] = strdup(b); ++ if (!l[i]) + return -ENOMEM; +- } +- + i++; ++ + dbus_message_iter_next(&sub); + } + + assert(i == n*2); + l[i] = NULL; + +- if (_l) ++ if (_l) { + *_l = l; ++ l = NULL; /* avoid freeing */ ++ } + + return 0; + } diff --git a/SOURCES/0079-drop-ins-check-return-value.patch b/SOURCES/0079-drop-ins-check-return-value.patch new file mode 100644 index 0000000..a7088f4 --- /dev/null +++ b/SOURCES/0079-drop-ins-check-return-value.patch @@ -0,0 +1,26 @@ +From 49a1b4948c3da7828c4b3765782e43f8a26c2929 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Fri, 11 Oct 2013 19:33:36 -0400 +Subject: [PATCH] drop-ins: check return value + +If the function failed, nothing serious would happen +because unlink would probably return EFAULT, but this +would obscure the real error and is a bit sloppy. +--- + src/core/unit.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/core/unit.c b/src/core/unit.c +index 4b97710..1db7d06 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -2908,6 +2908,9 @@ int unit_remove_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name) { + return 0; + + r = drop_in_file(u, mode, name, &p, &q); ++ if (r < 0) ++ return r; ++ + if (unlink(q) < 0) + r = errno == ENOENT ? 0 : -errno; + else diff --git a/SOURCES/0080-shared-util-Fix-glob_extend-argument.patch b/SOURCES/0080-shared-util-Fix-glob_extend-argument.patch new file mode 100644 index 0000000..e0a7153 --- /dev/null +++ b/SOURCES/0080-shared-util-Fix-glob_extend-argument.patch @@ -0,0 +1,25 @@ +From ebdc476db9419b36a046e8870ee6bb4bc6f57dc3 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Mon, 14 Oct 2013 08:15:51 +0200 +Subject: [PATCH] shared/util: Fix glob_extend() argument + +glob_extend() would completely fail to work, or return incorrect +data if it wasn't being passed the current getopt "optarg" variable +as it used the global variable, instead of the passed parameters. +--- + src/shared/util.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/shared/util.c b/src/shared/util.c +index f6f3b18..3d4ca7c 100644 +--- a/src/shared/util.c ++++ b/src/shared/util.c +@@ -4370,7 +4370,7 @@ int glob_extend(char ***strv, const char *path) { + char **p; + + errno = 0; +- k = glob(optarg, GLOB_NOSORT|GLOB_BRACE, NULL, &g); ++ k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g); + + if (k == GLOB_NOMATCH) + return -ENOENT; diff --git a/SOURCES/0081-Fix-for-SIGSEGV-in-systemd-bootchart-on-short-living.patch b/SOURCES/0081-Fix-for-SIGSEGV-in-systemd-bootchart-on-short-living.patch new file mode 100644 index 0000000..df97a46 --- /dev/null +++ b/SOURCES/0081-Fix-for-SIGSEGV-in-systemd-bootchart-on-short-living.patch @@ -0,0 +1,31 @@ +From 3a01553871713888812f234b62a40e892f9f2b8c Mon Sep 17 00:00:00 2001 +From: Igor Zhbanov +Date: Tue, 15 Oct 2013 14:35:13 +0400 +Subject: [PATCH] Fix for SIGSEGV in systemd-bootchart on short-living + processes + +The function svg_ps_bars() dereferencess NULL pointer in the line + endtime = ps->last->sampledata->sampletime; +because of partially initialized ps_struct (ps->last == NULL). + +If some process terminates between scaning /proc directory in the log_sample() +function and reading additional information from /proc/PID/... files, +the files couldn't be read, the loop will be continued and partially +initialized structure returned. +--- + src/bootchart/store.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/bootchart/store.c b/src/bootchart/store.c +index f8c97c2..7f86cfe 100644 +--- a/src/bootchart/store.c ++++ b/src/bootchart/store.c +@@ -275,7 +275,7 @@ schedstat_next: + pscount++; + + /* mark our first sample */ +- ps->first = ps->sample; ++ ps->first = ps->last = ps->sample; + ps->sample->runtime = atoll(rt); + ps->sample->waittime = atoll(wt); + diff --git a/SOURCES/0082-man-document-the-b-special-boot-option.patch b/SOURCES/0082-man-document-the-b-special-boot-option.patch new file mode 100644 index 0000000..70dc3b3 --- /dev/null +++ b/SOURCES/0082-man-document-the-b-special-boot-option.patch @@ -0,0 +1,34 @@ +From 051ee7b5173acc07875f6cf5b0c839302f9ce04d Mon Sep 17 00:00:00 2001 +From: Jan Engelhardt +Date: Tue, 15 Oct 2013 08:58:50 +0200 +Subject: [PATCH] man: document the -b special boot option + +--- + man/kernel-command-line.xml | 1 + + man/systemd.xml | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/man/kernel-command-line.xml b/man/kernel-command-line.xml +index cc267a3..abe68e5 100644 +--- a/man/kernel-command-line.xml ++++ b/man/kernel-command-line.xml +@@ -123,6 +123,7 @@ + + + ++ -b + emergency + single + s +diff --git a/man/systemd.xml b/man/systemd.xml +index 97ef768..89939f3 100644 +--- a/man/systemd.xml ++++ b/man/systemd.xml +@@ -1149,6 +1149,7 @@ + + + ++ -b + emergency + + Boot into emergency diff --git a/SOURCES/0083-tmpfiles-log-unaccessible-FUSE-mount-points-only-as-.patch b/SOURCES/0083-tmpfiles-log-unaccessible-FUSE-mount-points-only-as-.patch new file mode 100644 index 0000000..ab3c202 --- /dev/null +++ b/SOURCES/0083-tmpfiles-log-unaccessible-FUSE-mount-points-only-as-.patch @@ -0,0 +1,34 @@ +From 1d007bd94d09c955d548f4425a591f5a3bf032e4 Mon Sep 17 00:00:00 2001 +From: Kay Sievers +Date: Thu, 17 Oct 2013 03:20:46 +0200 +Subject: [PATCH] tmpfiles: log unaccessible FUSE mount points only as debug + message + +--- + src/tmpfiles/tmpfiles.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c +index 5eca82a..ea99920 100644 +--- a/src/tmpfiles/tmpfiles.c ++++ b/src/tmpfiles/tmpfiles.c +@@ -273,12 +273,15 @@ static int dir_cleanup( + continue; + + if (fstatat(dirfd(d), dent->d_name, &s, AT_SYMLINK_NOFOLLOW) < 0) { ++ if (errno == ENOENT) ++ continue; + +- if (errno != ENOENT) { ++ /* FUSE, NFS mounts, SELinux might return EACCES */ ++ if (errno == EACCES) ++ log_debug("stat(%s/%s) failed: %m", p, dent->d_name); ++ else + log_error("stat(%s/%s) failed: %m", p, dent->d_name); +- r = -errno; +- } +- ++ r = -errno; + continue; + } + diff --git a/SOURCES/0084-move-utf8-functions-from-libudev-private.h-to-utf8.h.patch b/SOURCES/0084-move-utf8-functions-from-libudev-private.h-to-utf8.h.patch new file mode 100644 index 0000000..1130387 --- /dev/null +++ b/SOURCES/0084-move-utf8-functions-from-libudev-private.h-to-utf8.h.patch @@ -0,0 +1,514 @@ +From 1bd14ab0b60de49c8546f22d90996b95423b9eeb Mon Sep 17 00:00:00 2001 +From: Dave Reisner +Date: Tue, 17 Sep 2013 15:39:09 -0400 +Subject: [PATCH] move utf8 functions from libudev-private.h to utf8.h + +There's now some more obvious overlap amongst the two utf8 validation +functions, but no more than there already was previously. + +This also adds some menial tests for anyone who wants to do more +merging of these two in the future. +--- + .gitignore | 2 + + Makefile.am | 10 +++ + src/libudev/libudev-util.c | 171 +-------------------------------------------- + src/shared/utf8.c | 151 +++++++++++++++++++++++++++++++++++++++ + src/shared/utf8.h | 4 ++ + src/test/test-utf8.c | 59 ++++++++++++++++ + 6 files changed, 229 insertions(+), 168 deletions(-) + create mode 100644 src/test/test-utf8.c + +diff --git a/.gitignore b/.gitignore +index 61bc2a3..deeee53 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -124,6 +124,7 @@ + /test-list + /test-log + /test-login ++/test-login-shared + /test-loopback + /test-mmap-cache + /test-ns +@@ -143,6 +144,7 @@ + /test-udev + /test-unit-file + /test-unit-name ++/test-utf8 + /test-util + /test-watchdog + /timedatectl +diff --git a/Makefile.am b/Makefile.am +index 25bfd91..6dd33ad 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -1121,6 +1121,7 @@ tests += \ + test-strxcpyx \ + test-unit-name \ + test-unit-file \ ++ test-utf8 \ + test-util \ + test-date \ + test-sleep \ +@@ -1223,6 +1224,15 @@ test_unit_file_CFLAGS = \ + test_unit_file_LDADD = \ + libsystemd-core.la + ++test_utf8_SOURCES = \ ++ src/test/test-utf8.c ++ ++test_utf8_CFLAGS = \ ++ $(AM_CFLAGS) ++ ++test_utf8_LDADD = \ ++ libsystemd-shared.la ++ + test_util_SOURCES = \ + src/test/test-util.c + +diff --git a/src/libudev/libudev-util.c b/src/libudev/libudev-util.c +index 714dc50..d54430c 100644 +--- a/src/libudev/libudev-util.c ++++ b/src/libudev/libudev-util.c +@@ -34,6 +34,7 @@ + + #include "libudev.h" + #include "libudev-private.h" ++#include "utf8.h" + + /** + * SECTION:libudev-util +@@ -306,129 +307,6 @@ void util_remove_trailing_chars(char *path, char c) + path[--len] = '\0'; + } + +-/* count of characters used to encode one unicode char */ +-static int utf8_encoded_expected_len(const char *str) +-{ +- unsigned char c = (unsigned char)str[0]; +- +- if (c < 0x80) +- return 1; +- if ((c & 0xe0) == 0xc0) +- return 2; +- if ((c & 0xf0) == 0xe0) +- return 3; +- if ((c & 0xf8) == 0xf0) +- return 4; +- if ((c & 0xfc) == 0xf8) +- return 5; +- if ((c & 0xfe) == 0xfc) +- return 6; +- return 0; +-} +- +-/* decode one unicode char */ +-static int utf8_encoded_to_unichar(const char *str) +-{ +- int unichar; +- int len; +- int i; +- +- len = utf8_encoded_expected_len(str); +- switch (len) { +- case 1: +- return (int)str[0]; +- case 2: +- unichar = str[0] & 0x1f; +- break; +- case 3: +- unichar = (int)str[0] & 0x0f; +- break; +- case 4: +- unichar = (int)str[0] & 0x07; +- break; +- case 5: +- unichar = (int)str[0] & 0x03; +- break; +- case 6: +- unichar = (int)str[0] & 0x01; +- break; +- default: +- return -1; +- } +- +- for (i = 1; i < len; i++) { +- if (((int)str[i] & 0xc0) != 0x80) +- return -1; +- unichar <<= 6; +- unichar |= (int)str[i] & 0x3f; +- } +- +- return unichar; +-} +- +-/* expected size used to encode one unicode char */ +-static int utf8_unichar_to_encoded_len(int unichar) +-{ +- if (unichar < 0x80) +- return 1; +- if (unichar < 0x800) +- return 2; +- if (unichar < 0x10000) +- return 3; +- if (unichar < 0x200000) +- return 4; +- if (unichar < 0x4000000) +- return 5; +- return 6; +-} +- +-/* check if unicode char has a valid numeric range */ +-static int utf8_unichar_valid_range(int unichar) +-{ +- if (unichar > 0x10ffff) +- return 0; +- if ((unichar & 0xfffff800) == 0xd800) +- return 0; +- if ((unichar > 0xfdcf) && (unichar < 0xfdf0)) +- return 0; +- if ((unichar & 0xffff) == 0xffff) +- return 0; +- return 1; +-} +- +-/* validate one encoded unicode char and return its length */ +-static int utf8_encoded_valid_unichar(const char *str) +-{ +- int len; +- int unichar; +- int i; +- +- len = utf8_encoded_expected_len(str); +- if (len == 0) +- return -1; +- +- /* ascii is valid */ +- if (len == 1) +- return 1; +- +- /* check if expected encoded chars are available */ +- for (i = 0; i < len; i++) +- if ((str[i] & 0x80) != 0x80) +- return -1; +- +- unichar = utf8_encoded_to_unichar(str); +- +- /* check if encoded length matches encoded value */ +- if (utf8_unichar_to_encoded_len(unichar) != len) +- return -1; +- +- /* check if value has valid range */ +- if (!utf8_unichar_valid_range(unichar)) +- return -1; +- +- return len; +-} +- + int util_replace_whitespace(const char *str, char *to, size_t len) + { + size_t i, j; +@@ -457,17 +335,6 @@ int util_replace_whitespace(const char *str, char *to, size_t len) + return 0; + } + +-static int is_whitelisted(char c, const char *white) +-{ +- if ((c >= '0' && c <= '9') || +- (c >= 'A' && c <= 'Z') || +- (c >= 'a' && c <= 'z') || +- strchr("#+-.:=@_", c) != NULL || +- (white != NULL && strchr(white, c) != NULL)) +- return 1; +- return 0; +-} +- + /* allow chars in whitelist, plain ascii, hex-escaping and valid utf8 */ + int util_replace_chars(char *str, const char *white) + { +@@ -477,7 +344,7 @@ int util_replace_chars(char *str, const char *white) + while (str[i] != '\0') { + int len; + +- if (is_whitelisted(str[i], white)) { ++ if (is_utf8_encoding_whitelisted(str[i], white)) { + i++; + continue; + } +@@ -525,39 +392,7 @@ int util_replace_chars(char *str, const char *white) + **/ + _public_ int udev_util_encode_string(const char *str, char *str_enc, size_t len) + { +- size_t i, j; +- +- if (str == NULL || str_enc == NULL) +- return -1; +- +- for (i = 0, j = 0; str[i] != '\0'; i++) { +- int seqlen; +- +- seqlen = utf8_encoded_valid_unichar(&str[i]); +- if (seqlen > 1) { +- if (len-j < (size_t)seqlen) +- goto err; +- memcpy(&str_enc[j], &str[i], seqlen); +- j += seqlen; +- i += (seqlen-1); +- } else if (str[i] == '\\' || !is_whitelisted(str[i], NULL)) { +- if (len-j < 4) +- goto err; +- sprintf(&str_enc[j], "\\x%02x", (unsigned char) str[i]); +- j += 4; +- } else { +- if (len-j < 1) +- goto err; +- str_enc[j] = str[i]; +- j++; +- } +- } +- if (len-j < 1) +- goto err; +- str_enc[j] = '\0'; +- return 0; +-err: +- return -1; ++ return udev_encode_string(str, str_enc, len); + } + + /* +diff --git a/src/shared/utf8.c b/src/shared/utf8.c +index 655cc77..1a68394 100644 +--- a/src/shared/utf8.c ++++ b/src/shared/utf8.c +@@ -317,3 +317,154 @@ char *utf16_to_utf8(const void *s, size_t length) { + + return r; + } ++ ++/* count of characters used to encode one unicode char */ ++static int utf8_encoded_expected_len(const char *str) { ++ unsigned char c = (unsigned char)str[0]; ++ ++ if (c < 0x80) ++ return 1; ++ if ((c & 0xe0) == 0xc0) ++ return 2; ++ if ((c & 0xf0) == 0xe0) ++ return 3; ++ if ((c & 0xf8) == 0xf0) ++ return 4; ++ if ((c & 0xfc) == 0xf8) ++ return 5; ++ if ((c & 0xfe) == 0xfc) ++ return 6; ++ return 0; ++} ++ ++/* decode one unicode char */ ++static int utf8_encoded_to_unichar(const char *str) { ++ int unichar; ++ int len; ++ int i; ++ ++ len = utf8_encoded_expected_len(str); ++ switch (len) { ++ case 1: ++ return (int)str[0]; ++ case 2: ++ unichar = str[0] & 0x1f; ++ break; ++ case 3: ++ unichar = (int)str[0] & 0x0f; ++ break; ++ case 4: ++ unichar = (int)str[0] & 0x07; ++ break; ++ case 5: ++ unichar = (int)str[0] & 0x03; ++ break; ++ case 6: ++ unichar = (int)str[0] & 0x01; ++ break; ++ default: ++ return -1; ++ } ++ ++ for (i = 1; i < len; i++) { ++ if (((int)str[i] & 0xc0) != 0x80) ++ return -1; ++ unichar <<= 6; ++ unichar |= (int)str[i] & 0x3f; ++ } ++ ++ return unichar; ++} ++ ++/* expected size used to encode one unicode char */ ++static int utf8_unichar_to_encoded_len(int unichar) { ++ if (unichar < 0x80) ++ return 1; ++ if (unichar < 0x800) ++ return 2; ++ if (unichar < 0x10000) ++ return 3; ++ if (unichar < 0x200000) ++ return 4; ++ if (unichar < 0x4000000) ++ return 5; ++ return 6; ++} ++ ++/* validate one encoded unicode char and return its length */ ++int utf8_encoded_valid_unichar(const char *str) { ++ int len; ++ int unichar; ++ int i; ++ ++ len = utf8_encoded_expected_len(str); ++ if (len == 0) ++ return -1; ++ ++ /* ascii is valid */ ++ if (len == 1) ++ return 1; ++ ++ /* check if expected encoded chars are available */ ++ for (i = 0; i < len; i++) ++ if ((str[i] & 0x80) != 0x80) ++ return -1; ++ ++ unichar = utf8_encoded_to_unichar(str); ++ ++ /* check if encoded length matches encoded value */ ++ if (utf8_unichar_to_encoded_len(unichar) != len) ++ return -1; ++ ++ /* check if value has valid range */ ++ if (!is_unicode_valid(unichar)) ++ return -1; ++ ++ return len; ++} ++ ++int is_utf8_encoding_whitelisted(char c, const char *white) { ++ if ((c >= '0' && c <= '9') || ++ (c >= 'A' && c <= 'Z') || ++ (c >= 'a' && c <= 'z') || ++ strchr("#+-.:=@_", c) != NULL || ++ (white != NULL && strchr(white, c) != NULL)) ++ return 1; ++ return 0; ++} ++ ++int udev_encode_string(const char *str, char *str_enc, size_t len) { ++ size_t i, j; ++ ++ if (str == NULL || str_enc == NULL) ++ return -1; ++ ++ for (i = 0, j = 0; str[i] != '\0'; i++) { ++ int seqlen; ++ ++ seqlen = utf8_encoded_valid_unichar(&str[i]); ++ if (seqlen > 1) { ++ if (len-j < (size_t)seqlen) ++ goto err; ++ memcpy(&str_enc[j], &str[i], seqlen); ++ j += seqlen; ++ i += (seqlen-1); ++ } else if (str[i] == '\\' || !is_utf8_encoding_whitelisted(str[i], NULL)) { ++ if (len-j < 4) ++ goto err; ++ sprintf(&str_enc[j], "\\x%02x", (unsigned char) str[i]); ++ j += 4; ++ } else { ++ if (len-j < 1) ++ goto err; ++ str_enc[j] = str[i]; ++ j++; ++ } ++ } ++ if (len-j < 1) ++ goto err; ++ str_enc[j] = '\0'; ++ return 0; ++err: ++ return -1; ++} +diff --git a/src/shared/utf8.h b/src/shared/utf8.h +index f805ea6..7a5608c 100644 +--- a/src/shared/utf8.h ++++ b/src/shared/utf8.h +@@ -34,3 +34,7 @@ char *utf8_filter(const char *s); + char *ascii_filter(const char *s); + + char *utf16_to_utf8(const void *s, size_t length); ++ ++int utf8_encoded_valid_unichar(const char *str); ++int is_utf8_encoding_whitelisted(char c, const char *white); ++int udev_encode_string(const char *str, char *str_enc, size_t len); +diff --git a/src/test/test-utf8.c b/src/test/test-utf8.c +new file mode 100644 +index 0000000..d2b9771 +--- /dev/null ++++ b/src/test/test-utf8.c +@@ -0,0 +1,59 @@ ++/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ ++ ++/*** ++ This file is part of systemd. ++ ++ Copyright 2013 Dave Reisner ++ ++ 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 . ++***/ ++ ++ ++#include "utf8.h" ++#include "util.h" ++ ++/* helpers for test_udev_encode_string */ ++static char *do_encode_string(const char *in) { ++ size_t out_len = strlen(in) * 4; ++ char *out = malloc(out_len); ++ ++ assert_se(out); ++ assert_se(udev_encode_string(in, out, out_len) >= 0); ++ puts(out); ++ ++ return out; ++} ++ ++static bool expect_encoded_as(const char *in, const char *expected) { ++ _cleanup_free_ char *encoded = do_encode_string(in); ++ return streq(encoded, expected); ++} ++ ++static void test_udev_encode_string(void) { ++ assert_se(expect_encoded_as("systemd sucks", "systemd\\x20sucks")); ++ assert_se(expect_encoded_as("pinkiepie", "pinkiepie")); ++ assert_se(expect_encoded_as("valíd\\ųtf8", "valíd\\x5cųtf8")); ++ assert_se(expect_encoded_as("s/ash/ng", "s\\x2fash\\x2fng")); ++} ++ ++static void test_utf8_is_valid(void) { ++ assert_se(utf8_is_valid("ascii is valid unicode")); ++ assert_se(utf8_is_valid("\341\204\242")); ++ assert_se(!utf8_is_valid("\341\204")); ++} ++ ++int main(int argc, char *argv[]) { ++ test_utf8_is_valid(); ++ test_udev_encode_string(); ++} diff --git a/SOURCES/0085-Use-udev_encode_string-in-fstab_node_to_udev_node.patch b/SOURCES/0085-Use-udev_encode_string-in-fstab_node_to_udev_node.patch new file mode 100644 index 0000000..fb9d269 --- /dev/null +++ b/SOURCES/0085-Use-udev_encode_string-in-fstab_node_to_udev_node.patch @@ -0,0 +1,113 @@ +From b6c9f1408abaebffc4b8151fa5615075767f4a92 Mon Sep 17 00:00:00 2001 +From: Dave Reisner +Date: Tue, 17 Sep 2013 15:47:08 -0400 +Subject: [PATCH] Use udev_encode_string in fstab_node_to_udev_node + +Resolves a longstanding bug which caused this function to wrongly +handle (escape) valid utf8 characters. +--- + src/shared/util.c | 20 +++++++++----------- + src/test/test-util.c | 36 ++++++++++++++++++++++++++++++++++++ + 2 files changed, 45 insertions(+), 11 deletions(-) + +diff --git a/src/shared/util.c b/src/shared/util.c +index 3d4ca7c..766957a 100644 +--- a/src/shared/util.c ++++ b/src/shared/util.c +@@ -73,6 +73,7 @@ + #include "hashmap.h" + #include "env-util.h" + #include "fileio.h" ++#include "utf8.h" + + int saved_argc = 0; + char **saved_argv = NULL; +@@ -3495,26 +3496,23 @@ int signal_from_string_try_harder(const char *s) { + } + + static char *tag_to_udev_node(const char *tagvalue, const char *by) { +- char *dn, *t, *u; +- int r; +- +- /* FIXME: to follow udev's logic 100% we need to leave valid +- * UTF8 chars unescaped */ ++ _cleanup_free_ char *t = NULL, *u = NULL; ++ char *dn; ++ size_t enc_len; + + u = unquote(tagvalue, "\"\'"); + if (u == NULL) + return NULL; + +- t = xescape(u, "/ "); +- free(u); +- ++ enc_len = strlen(u) * 4; ++ t = new(char, enc_len); + if (t == NULL) + return NULL; + +- r = asprintf(&dn, "/dev/disk/by-%s/%s", by, t); +- free(t); ++ if (udev_encode_string(u, t, enc_len) < 0) ++ return NULL; + +- if (r < 0) ++ if (asprintf(&dn, "/dev/disk/by-%s/%s", by, t) < 0) + return NULL; + + return dn; +diff --git a/src/test/test-util.c b/src/test/test-util.c +index dd7768d..ad13d53 100644 +--- a/src/test/test-util.c ++++ b/src/test/test-util.c +@@ -547,6 +547,41 @@ static void test_split_pair(void) { + assert_se(streq(b, "=")); + } + ++static void test_fstab_node_to_udev_node(void) { ++ char *n; ++ ++ n = fstab_node_to_udev_node("LABEL=applé/jack"); ++ puts(n); ++ assert_se(streq(n, "/dev/disk/by-label/applé\\x2fjack")); ++ free(n); ++ ++ n = fstab_node_to_udev_node("PARTLABEL=pinkié pie"); ++ puts(n); ++ assert_se(streq(n, "/dev/disk/by-partlabel/pinkié\\x20pie")); ++ free(n); ++ ++ n = fstab_node_to_udev_node("UUID=037b9d94-148e-4ee4-8d38-67bfe15bb535"); ++ puts(n); ++ assert_se(streq(n, "/dev/disk/by-uuid/037b9d94-148e-4ee4-8d38-67bfe15bb535")); ++ free(n); ++ ++ n = fstab_node_to_udev_node("PARTUUID=037b9d94-148e-4ee4-8d38-67bfe15bb535"); ++ puts(n); ++ assert_se(streq(n, "/dev/disk/by-partuuid/037b9d94-148e-4ee4-8d38-67bfe15bb535")); ++ free(n); ++ ++ ++ n = fstab_node_to_udev_node("PONIES=awesome"); ++ puts(n); ++ assert_se(streq(n, "PONIES=awesome")); ++ free(n); ++ ++ n = fstab_node_to_udev_node("/dev/xda1"); ++ puts(n); ++ assert_se(streq(n, "/dev/xda1")); ++ free(n); ++} ++ + int main(int argc, char *argv[]) { + test_streq_ptr(); + test_first_word(); +@@ -582,6 +617,7 @@ int main(int argc, char *argv[]) { + test_strrep(); + test_parse_user_at_host(); + test_split_pair(); ++ test_fstab_node_to_udev_node(); + + return 0; + } diff --git a/SOURCES/0086-Fix-buffer-overrun-when-enumerating-files.patch b/SOURCES/0086-Fix-buffer-overrun-when-enumerating-files.patch new file mode 100644 index 0000000..06024b3 --- /dev/null +++ b/SOURCES/0086-Fix-buffer-overrun-when-enumerating-files.patch @@ -0,0 +1,173 @@ +From 29328cbda5daea22f02e4ca94ca75783f22efc61 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Sun, 29 Sep 2013 14:40:58 +0200 +Subject: [PATCH] Fix buffer overrun when enumerating files + +https://bugs.freedesktop.org/show_bug.cgi?id=69887 + +Based-on-a-patch-by: Hans Petter Jansson +--- + src/shared/util.c | 79 +++++++++++++++++----------------------------------- + src/test/test-util.c | 10 +++++++ + 2 files changed, 36 insertions(+), 53 deletions(-) + +diff --git a/src/shared/util.c b/src/shared/util.c +index 766957a..4f80cc8 100644 +--- a/src/shared/util.c ++++ b/src/shared/util.c +@@ -4412,38 +4412,31 @@ int dirent_ensure_type(DIR *d, struct dirent *de) { + } + + int in_search_path(const char *path, char **search) { +- char **i, *parent; ++ char **i; ++ _cleanup_free_ char *parent = NULL; + int r; + + r = path_get_parent(path, &parent); + if (r < 0) + return r; + +- r = 0; +- +- STRV_FOREACH(i, search) { +- if (path_equal(parent, *i)) { +- r = 1; +- break; +- } +- } +- +- free(parent); ++ STRV_FOREACH(i, search) ++ if (path_equal(parent, *i)) ++ return 1; + +- return r; ++ return 0; + } + + int get_files_in_directory(const char *path, char ***list) { +- DIR *d; +- int r = 0; +- unsigned n = 0; +- char **l = NULL; ++ _cleanup_closedir_ DIR *d = NULL; ++ size_t bufsize = 0, n = 0; ++ _cleanup_strv_free_ char **l = NULL; + + assert(path); + + /* Returns all files in a directory in *list, and the number + * of files as return value. If list is NULL returns only the +- * number */ ++ * number. */ + + d = opendir(path); + if (!d) +@@ -4455,11 +4448,9 @@ int get_files_in_directory(const char *path, char ***list) { + int k; + + k = readdir_r(d, &buf.de, &de); +- if (k != 0) { +- r = -k; +- goto finish; +- } +- ++ assert(k >= 0); ++ if (k > 0) ++ return -k; + if (!de) + break; + +@@ -4469,43 +4460,25 @@ int get_files_in_directory(const char *path, char ***list) { + continue; + + if (list) { +- if ((unsigned) r >= n) { +- char **t; +- +- n = MAX(16, 2*r); +- t = realloc(l, sizeof(char*) * n); +- if (!t) { +- r = -ENOMEM; +- goto finish; +- } +- +- l = t; +- } +- +- assert((unsigned) r < n); ++ /* one extra slot is needed for the terminating NULL */ ++ if (!GREEDY_REALLOC(l, bufsize, n + 2)) ++ return -ENOMEM; + +- l[r] = strdup(de->d_name); +- if (!l[r]) { +- r = -ENOMEM; +- goto finish; +- } ++ l[n] = strdup(de->d_name); ++ if (!l[n]) ++ return -ENOMEM; + +- l[++r] = NULL; ++ l[++n] = NULL; + } else +- r++; ++ n++; + } + +-finish: +- if (d) +- closedir(d); +- +- if (r >= 0) { +- if (list) +- *list = l; +- } else +- strv_free(l); ++ if (list) { ++ *list = l; ++ l = NULL; /* avoid freeing */ ++ } + +- return r; ++ return n; + } + + char *strjoin(const char *x, ...) { +diff --git a/src/test/test-util.c b/src/test/test-util.c +index ad13d53..c5762ed 100644 +--- a/src/test/test-util.c ++++ b/src/test/test-util.c +@@ -27,6 +27,7 @@ + #include + + #include "util.h" ++#include "strv.h" + + static void test_streq_ptr(void) { + assert_se(streq_ptr(NULL, NULL)); +@@ -582,6 +583,14 @@ static void test_fstab_node_to_udev_node(void) { + free(n); + } + ++static void test_get_files_in_directory(void) { ++ _cleanup_strv_free_ char **l = NULL, **t = NULL; ++ ++ assert_se(get_files_in_directory("/tmp", &l) >= 0); ++ assert_se(get_files_in_directory(".", &l) >= 0); ++ assert_se(get_files_in_directory(".", NULL) >= 0); ++} ++ + int main(int argc, char *argv[]) { + test_streq_ptr(); + test_first_word(); +@@ -618,6 +627,7 @@ int main(int argc, char *argv[]) { + test_parse_user_at_host(); + test_split_pair(); + test_fstab_node_to_udev_node(); ++ test_get_files_in_directory(); + + return 0; + } diff --git a/SOURCES/0087-shared-utf8-merge-implementations-remove-cruft.patch b/SOURCES/0087-shared-utf8-merge-implementations-remove-cruft.patch new file mode 100644 index 0000000..685e5e7 --- /dev/null +++ b/SOURCES/0087-shared-utf8-merge-implementations-remove-cruft.patch @@ -0,0 +1,401 @@ +From 3fde78dba9ad834ab264ad6888672833874b9101 Mon Sep 17 00:00:00 2001 +From: Dave Reisner +Date: Wed, 18 Sep 2013 11:52:14 -0400 +Subject: [PATCH] shared/utf8: merge implementations, remove cruft + +This unifies the utf8 handling code which was previously duplicated in +udev and systemd. +--- + TODO | 1 - + src/shared/utf8.c | 279 +++++++++++++-------------------------------------- + src/shared/utf8.h | 3 +- + src/test/test-utf8.c | 9 ++ + 4 files changed, 81 insertions(+), 211 deletions(-) + +diff --git a/TODO b/TODO +index 4c3e14f..8b7325e 100644 +--- a/TODO ++++ b/TODO +@@ -599,7 +599,6 @@ Features: + * udev: + - remove src/udev/udev-builtin-firmware.c (CONFIG_FW_LOADER_USER_HELPER=n) + - move to LGPL +- - unify utf8 validator code with shared/ + - kill scsi_id + - add trigger --subsystem-match=usb/usb_device device + +diff --git a/src/shared/utf8.c b/src/shared/utf8.c +index 1a68394..732f0f0 100644 +--- a/src/shared/utf8.c ++++ b/src/shared/utf8.c +@@ -51,8 +51,6 @@ + #include "utf8.h" + #include "util.h" + +-#define FILTER_CHAR '_' +- + static inline bool is_unicode_valid(uint32_t ch) { + + if (ch >= 0x110000) /* End of unicode space */ +@@ -67,17 +65,6 @@ static inline bool is_unicode_valid(uint32_t ch) { + return true; + } + +-static inline bool is_continuation_char(uint8_t ch) { +- if ((ch & 0xc0) != 0x80) /* 10xxxxxx */ +- return false; +- return true; +-} +- +-static inline void merge_continuation_char(uint32_t *u_ch, uint8_t ch) { +- *u_ch <<= 6; +- *u_ch |= ch & 0x3f; +-} +- + static bool is_unicode_control(uint32_t ch) { + + /* +@@ -90,163 +77,97 @@ static bool is_unicode_control(uint32_t ch) { + (0x7F <= ch && ch <= 0x9F); + } + +-bool utf8_is_printable(const char* str, size_t length) { +- uint32_t val = 0; +- uint32_t min = 0; +- const uint8_t *p; ++/* count of characters used to encode one unicode char */ ++static int utf8_encoded_expected_len(const char *str) { ++ unsigned char c = (unsigned char)str[0]; + +- assert(str); ++ if (c < 0x80) ++ return 1; ++ if ((c & 0xe0) == 0xc0) ++ return 2; ++ if ((c & 0xf0) == 0xe0) ++ return 3; ++ if ((c & 0xf8) == 0xf0) ++ return 4; ++ if ((c & 0xfc) == 0xf8) ++ return 5; ++ if ((c & 0xfe) == 0xfc) ++ return 6; ++ return 0; ++} + +- for (p = (const uint8_t*) str; length; p++, length--) { +- if (*p < 128) { +- val = *p; +- } else { +- if ((*p & 0xe0) == 0xc0) { /* 110xxxxx two-char seq. */ +- min = 128; +- val = (uint32_t) (*p & 0x1e); +- goto ONE_REMAINING; +- } else if ((*p & 0xf0) == 0xe0) { /* 1110xxxx three-char seq.*/ +- min = (1 << 11); +- val = (uint32_t) (*p & 0x0f); +- goto TWO_REMAINING; +- } else if ((*p & 0xf8) == 0xf0) { /* 11110xxx four-char seq */ +- min = (1 << 16); +- val = (uint32_t) (*p & 0x07); +- } else +- return false; +- +- p++; +- length--; +- if (!length || !is_continuation_char(*p)) +- return false; +- merge_continuation_char(&val, *p); +- +- TWO_REMAINING: +- p++; +- length--; +- if (!is_continuation_char(*p)) +- return false; +- merge_continuation_char(&val, *p); +- +- ONE_REMAINING: +- p++; +- length--; +- if (!is_continuation_char(*p)) +- return false; +- merge_continuation_char(&val, *p); +- +- if (val < min) +- return false; +- } ++/* decode one unicode char */ ++static int utf8_encoded_to_unichar(const char *str) { ++ int unichar; ++ int len; ++ int i; + +- if (is_unicode_control(val)) +- return false; ++ len = utf8_encoded_expected_len(str); ++ switch (len) { ++ case 1: ++ return (int)str[0]; ++ case 2: ++ unichar = str[0] & 0x1f; ++ break; ++ case 3: ++ unichar = (int)str[0] & 0x0f; ++ break; ++ case 4: ++ unichar = (int)str[0] & 0x07; ++ break; ++ case 5: ++ unichar = (int)str[0] & 0x03; ++ break; ++ case 6: ++ unichar = (int)str[0] & 0x01; ++ break; ++ default: ++ return -1; + } + +- return true; ++ for (i = 1; i < len; i++) { ++ if (((int)str[i] & 0xc0) != 0x80) ++ return -1; ++ unichar <<= 6; ++ unichar |= (int)str[i] & 0x3f; ++ } ++ ++ return unichar; + } + +-static char* utf8_validate(const char *str, char *output) { +- uint32_t val = 0; +- uint32_t min = 0; +- const uint8_t *p, *last; +- int size; +- uint8_t *o; ++bool utf8_is_printable(const char* str, size_t length) { ++ const uint8_t *p; + + assert(str); + +- o = (uint8_t*) output; +- for (p = (const uint8_t*) str; *p; p++) { +- if (*p < 128) { +- if (o) +- *o = *p; +- } else { +- last = p; +- +- if ((*p & 0xe0) == 0xc0) { /* 110xxxxx two-char seq. */ +- size = 2; +- min = 128; +- val = (uint32_t) (*p & 0x1e); +- goto ONE_REMAINING; +- } else if ((*p & 0xf0) == 0xe0) { /* 1110xxxx three-char seq.*/ +- size = 3; +- min = (1 << 11); +- val = (uint32_t) (*p & 0x0f); +- goto TWO_REMAINING; +- } else if ((*p & 0xf8) == 0xf0) { /* 11110xxx four-char seq */ +- size = 4; +- min = (1 << 16); +- val = (uint32_t) (*p & 0x07); +- } else +- goto error; +- +- p++; +- if (!is_continuation_char(*p)) +- goto error; +- merge_continuation_char(&val, *p); +- +- TWO_REMAINING: +- p++; +- if (!is_continuation_char(*p)) +- goto error; +- merge_continuation_char(&val, *p); +- +- ONE_REMAINING: +- p++; +- if (!is_continuation_char(*p)) +- goto error; +- merge_continuation_char(&val, *p); +- +- if (val < min) +- goto error; +- +- if (!is_unicode_valid(val)) +- goto error; +- +- if (o) { +- memcpy(o, last, (size_t) size); +- o += size; +- } +- +- continue; +- +- error: +- if (o) { +- *o = FILTER_CHAR; +- p = last; /* We retry at the next character */ +- } else +- goto failure; +- } ++ for (p = (const uint8_t*) str; length; p++) { ++ int encoded_len = utf8_encoded_valid_unichar((const char *)p); ++ int32_t val = utf8_encoded_to_unichar((const char*)p); + +- if (o) +- o++; +- } ++ if (encoded_len < 0 || val < 0 || is_unicode_control(val)) ++ return false; + +- if (o) { +- *o = '\0'; +- return output; ++ length -= encoded_len; + } + +- return (char*) str; +- +-failure: +- return NULL; +-} +- +-char* utf8_is_valid (const char *str) { +- return utf8_validate(str, NULL); ++ return true; + } + +-char* utf8_filter (const char *str) { +- char *new_str; ++const char *utf8_is_valid(const char *str) { ++ const uint8_t *p; + + assert(str); + +- new_str = malloc(strlen(str) + 1); +- if (!new_str) +- return NULL; ++ for (p = (const uint8_t*) str; *p; ) { ++ int len = utf8_encoded_valid_unichar((const char *)p); ++ ++ if (len < 0) ++ return NULL; ++ ++ p += len; ++ } + +- return utf8_validate(str, new_str); ++ return str; + } + + char *ascii_is_valid(const char *str) { +@@ -318,64 +239,6 @@ char *utf16_to_utf8(const void *s, size_t length) { + return r; + } + +-/* count of characters used to encode one unicode char */ +-static int utf8_encoded_expected_len(const char *str) { +- unsigned char c = (unsigned char)str[0]; +- +- if (c < 0x80) +- return 1; +- if ((c & 0xe0) == 0xc0) +- return 2; +- if ((c & 0xf0) == 0xe0) +- return 3; +- if ((c & 0xf8) == 0xf0) +- return 4; +- if ((c & 0xfc) == 0xf8) +- return 5; +- if ((c & 0xfe) == 0xfc) +- return 6; +- return 0; +-} +- +-/* decode one unicode char */ +-static int utf8_encoded_to_unichar(const char *str) { +- int unichar; +- int len; +- int i; +- +- len = utf8_encoded_expected_len(str); +- switch (len) { +- case 1: +- return (int)str[0]; +- case 2: +- unichar = str[0] & 0x1f; +- break; +- case 3: +- unichar = (int)str[0] & 0x0f; +- break; +- case 4: +- unichar = (int)str[0] & 0x07; +- break; +- case 5: +- unichar = (int)str[0] & 0x03; +- break; +- case 6: +- unichar = (int)str[0] & 0x01; +- break; +- default: +- return -1; +- } +- +- for (i = 1; i < len; i++) { +- if (((int)str[i] & 0xc0) != 0x80) +- return -1; +- unichar <<= 6; +- unichar |= (int)str[i] & 0x3f; +- } +- +- return unichar; +-} +- + /* expected size used to encode one unicode char */ + static int utf8_unichar_to_encoded_len(int unichar) { + if (unichar < 0x80) +diff --git a/src/shared/utf8.h b/src/shared/utf8.h +index 7a5608c..22e1346 100644 +--- a/src/shared/utf8.h ++++ b/src/shared/utf8.h +@@ -25,12 +25,11 @@ + + #include "macro.h" + +-char *utf8_is_valid(const char *s) _pure_; ++const char *utf8_is_valid(const char *s) _pure_; + char *ascii_is_valid(const char *s) _pure_; + + bool utf8_is_printable(const char* str, size_t length) _pure_; + +-char *utf8_filter(const char *s); + char *ascii_filter(const char *s); + + char *utf16_to_utf8(const void *s, size_t length); +diff --git a/src/test/test-utf8.c b/src/test/test-utf8.c +index d2b9771..26cc37b 100644 +--- a/src/test/test-utf8.c ++++ b/src/test/test-utf8.c +@@ -47,6 +47,12 @@ static void test_udev_encode_string(void) { + assert_se(expect_encoded_as("s/ash/ng", "s\\x2fash\\x2fng")); + } + ++static void test_utf8_is_printable(void) { ++ assert_se(utf8_is_printable("ascii is valid\tunicode", 22)); ++ assert_se(utf8_is_printable("\342\204\242", 3)); ++ assert_se(!utf8_is_printable("\341\204", 2)); ++} ++ + static void test_utf8_is_valid(void) { + assert_se(utf8_is_valid("ascii is valid unicode")); + assert_se(utf8_is_valid("\341\204\242")); +@@ -55,5 +61,8 @@ static void test_utf8_is_valid(void) { + + int main(int argc, char *argv[]) { + test_utf8_is_valid(); ++ test_utf8_is_printable(); + test_udev_encode_string(); ++ ++ return 0; + } diff --git a/SOURCES/0088-device-nodes-move-device-node-specific-code-to-own-f.patch b/SOURCES/0088-device-nodes-move-device-node-specific-code-to-own-f.patch new file mode 100644 index 0000000..4aac24b --- /dev/null +++ b/SOURCES/0088-device-nodes-move-device-node-specific-code-to-own-f.patch @@ -0,0 +1,418 @@ +From a6b1359b406410ca48160deb442a62f73f3b7508 Mon Sep 17 00:00:00 2001 +From: Dave Reisner +Date: Wed, 18 Sep 2013 12:12:04 -0400 +Subject: [PATCH] device-nodes: move device node specific code to own file + +In the process, rename udev_encode_string which is poorly named for what +it does. It deals specifically with encoding names that udev creates and +has its own rules: utf8 is valid but some ascii is not (e.g. path +separators), and everything else is simply escaped. Rename it to +encode_devnode_name. +--- + .gitignore | 1 + + Makefile.am | 14 ++++++++- + src/libudev/libudev-util.c | 5 +-- + src/shared/device-nodes.c | 74 ++++++++++++++++++++++++++++++++++++++++++++ + src/shared/device-nodes.h | 23 ++++++++++++++ + src/shared/utf8.c | 46 --------------------------- + src/shared/utf8.h | 2 -- + src/shared/util.c | 4 +-- + src/test/test-device-nodes.c | 55 ++++++++++++++++++++++++++++++++ + src/test/test-utf8.c | 28 +---------------- + 10 files changed, 172 insertions(+), 80 deletions(-) + create mode 100644 src/shared/device-nodes.c + create mode 100644 src/shared/device-nodes.h + create mode 100644 src/test/test-device-nodes.c + +diff --git a/.gitignore b/.gitignore +index deeee53..8115d4d 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -101,6 +101,7 @@ + /test-cgroup-util + /test-daemon + /test-date ++/test-device-nodes + /test-efivars + /test-engine + /test-env-replace +diff --git a/Makefile.am b/Makefile.am +index 6dd33ad..aa16522 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -640,6 +640,8 @@ libsystemd_shared_la_SOURCES = \ + src/shared/list.h \ + src/shared/macro.h \ + src/shared/def.h \ ++ src/shared/device-nodes.c \ ++ src/shared/device-nodes.h \ + src/shared/sparse-endian.h \ + src/shared/util.c \ + src/shared/util.h \ +@@ -1135,7 +1137,8 @@ tests += \ + test-time \ + test-hashmap \ + test-list \ +- test-tables ++ test-tables \ ++ test-device-nodes + + EXTRA_DIST += \ + test/sched_idle_bad.service \ +@@ -1147,6 +1150,15 @@ EXTRA_DIST += \ + EXTRA_DIST += \ + src/test/test-helper.h + ++test_device_nodes_SOURCES = \ ++ src/test/test-device-nodes.c ++ ++test_device_nodes_CFLAGS = \ ++ $(AM_CFLAGS) ++ ++test_device_nodes_LDADD = \ ++ libsystemd-shared.la ++ + test_engine_SOURCES = \ + src/test/test-engine.c + +diff --git a/src/libudev/libudev-util.c b/src/libudev/libudev-util.c +index d54430c..b5b9db6 100644 +--- a/src/libudev/libudev-util.c ++++ b/src/libudev/libudev-util.c +@@ -32,6 +32,7 @@ + #include + #include + ++#include "device-nodes.h" + #include "libudev.h" + #include "libudev-private.h" + #include "utf8.h" +@@ -344,7 +345,7 @@ int util_replace_chars(char *str, const char *white) + while (str[i] != '\0') { + int len; + +- if (is_utf8_encoding_whitelisted(str[i], white)) { ++ if (whitelisted_char_for_devnode(str[i], white)) { + i++; + continue; + } +@@ -392,7 +393,7 @@ int util_replace_chars(char *str, const char *white) + **/ + _public_ int udev_util_encode_string(const char *str, char *str_enc, size_t len) + { +- return udev_encode_string(str, str_enc, len); ++ return encode_devnode_name(str, str_enc, len); + } + + /* +diff --git a/src/shared/device-nodes.c b/src/shared/device-nodes.c +new file mode 100644 +index 0000000..986553e +--- /dev/null ++++ b/src/shared/device-nodes.c +@@ -0,0 +1,74 @@ ++/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ ++ ++/*** ++ This file is part of systemd. ++ ++ Copyright 2012 Lennart Poettering ++ ++ 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 . ++***/ ++ ++#include ++#include ++#include ++#include ++ ++#include "device-nodes.h" ++#include "utf8.h" ++ ++int whitelisted_char_for_devnode(char c, const char *white) { ++ if ((c >= '0' && c <= '9') || ++ (c >= 'A' && c <= 'Z') || ++ (c >= 'a' && c <= 'z') || ++ strchr("#+-.:=@_", c) != NULL || ++ (white != NULL && strchr(white, c) != NULL)) ++ return 1; ++ return 0; ++} ++ ++int encode_devnode_name(const char *str, char *str_enc, size_t len) { ++ size_t i, j; ++ ++ if (str == NULL || str_enc == NULL) ++ return -1; ++ ++ for (i = 0, j = 0; str[i] != '\0'; i++) { ++ int seqlen; ++ ++ seqlen = utf8_encoded_valid_unichar(&str[i]); ++ if (seqlen > 1) { ++ if (len-j < (size_t)seqlen) ++ goto err; ++ memcpy(&str_enc[j], &str[i], seqlen); ++ j += seqlen; ++ i += (seqlen-1); ++ } else if (str[i] == '\\' || !whitelisted_char_for_devnode(str[i], NULL)) { ++ if (len-j < 4) ++ goto err; ++ sprintf(&str_enc[j], "\\x%02x", (unsigned char) str[i]); ++ j += 4; ++ } else { ++ if (len-j < 1) ++ goto err; ++ str_enc[j] = str[i]; ++ j++; ++ } ++ } ++ if (len-j < 1) ++ goto err; ++ str_enc[j] = '\0'; ++ return 0; ++err: ++ return -1; ++} +diff --git a/src/shared/device-nodes.h b/src/shared/device-nodes.h +new file mode 100644 +index 0000000..a98195a +--- /dev/null ++++ b/src/shared/device-nodes.h +@@ -0,0 +1,23 @@ ++/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ ++ ++/*** ++ This file is part of systemd. ++ ++ Copyright 2012 Lennart Poettering ++ ++ 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 . ++***/ ++ ++int encode_devnode_name(const char *str, char *str_enc, size_t len); ++int whitelisted_char_for_devnode(char c, const char *additional); +diff --git a/src/shared/utf8.c b/src/shared/utf8.c +index 732f0f0..c3d97cc 100644 +--- a/src/shared/utf8.c ++++ b/src/shared/utf8.c +@@ -285,49 +285,3 @@ int utf8_encoded_valid_unichar(const char *str) { + + return len; + } +- +-int is_utf8_encoding_whitelisted(char c, const char *white) { +- if ((c >= '0' && c <= '9') || +- (c >= 'A' && c <= 'Z') || +- (c >= 'a' && c <= 'z') || +- strchr("#+-.:=@_", c) != NULL || +- (white != NULL && strchr(white, c) != NULL)) +- return 1; +- return 0; +-} +- +-int udev_encode_string(const char *str, char *str_enc, size_t len) { +- size_t i, j; +- +- if (str == NULL || str_enc == NULL) +- return -1; +- +- for (i = 0, j = 0; str[i] != '\0'; i++) { +- int seqlen; +- +- seqlen = utf8_encoded_valid_unichar(&str[i]); +- if (seqlen > 1) { +- if (len-j < (size_t)seqlen) +- goto err; +- memcpy(&str_enc[j], &str[i], seqlen); +- j += seqlen; +- i += (seqlen-1); +- } else if (str[i] == '\\' || !is_utf8_encoding_whitelisted(str[i], NULL)) { +- if (len-j < 4) +- goto err; +- sprintf(&str_enc[j], "\\x%02x", (unsigned char) str[i]); +- j += 4; +- } else { +- if (len-j < 1) +- goto err; +- str_enc[j] = str[i]; +- j++; +- } +- } +- if (len-j < 1) +- goto err; +- str_enc[j] = '\0'; +- return 0; +-err: +- return -1; +-} +diff --git a/src/shared/utf8.h b/src/shared/utf8.h +index 22e1346..96a03ea 100644 +--- a/src/shared/utf8.h ++++ b/src/shared/utf8.h +@@ -35,5 +35,3 @@ char *ascii_filter(const char *s); + char *utf16_to_utf8(const void *s, size_t length); + + int utf8_encoded_valid_unichar(const char *str); +-int is_utf8_encoding_whitelisted(char c, const char *white); +-int udev_encode_string(const char *str, char *str_enc, size_t len); +diff --git a/src/shared/util.c b/src/shared/util.c +index 4f80cc8..4711d91 100644 +--- a/src/shared/util.c ++++ b/src/shared/util.c +@@ -73,7 +73,7 @@ + #include "hashmap.h" + #include "env-util.h" + #include "fileio.h" +-#include "utf8.h" ++#include "device-nodes.h" + + int saved_argc = 0; + char **saved_argv = NULL; +@@ -3509,7 +3509,7 @@ static char *tag_to_udev_node(const char *tagvalue, const char *by) { + if (t == NULL) + return NULL; + +- if (udev_encode_string(u, t, enc_len) < 0) ++ if (encode_devnode_name(u, t, enc_len) < 0) + return NULL; + + if (asprintf(&dn, "/dev/disk/by-%s/%s", by, t) < 0) +diff --git a/src/test/test-device-nodes.c b/src/test/test-device-nodes.c +new file mode 100644 +index 0000000..2f3dedb +--- /dev/null ++++ b/src/test/test-device-nodes.c +@@ -0,0 +1,55 @@ ++/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ ++ ++/*** ++ This file is part of systemd. ++ ++ Copyright 2013 Dave Reisner ++ ++ 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 . ++***/ ++ ++#include ++ ++#include "device-nodes.h" ++#include "util.h" ++ ++/* helpers for test_encode_devnode_name */ ++static char *do_encode_string(const char *in) { ++ size_t out_len = strlen(in) * 4; ++ char *out = malloc(out_len); ++ ++ assert_se(out); ++ assert_se(encode_devnode_name(in, out, out_len) >= 0); ++ puts(out); ++ ++ return out; ++} ++ ++static bool expect_encoded_as(const char *in, const char *expected) { ++ _cleanup_free_ char *encoded = do_encode_string(in); ++ return streq(encoded, expected); ++} ++ ++static void test_encode_devnode_name(void) { ++ assert_se(expect_encoded_as("systemd sucks", "systemd\\x20sucks")); ++ assert_se(expect_encoded_as("pinkiepie", "pinkiepie")); ++ assert_se(expect_encoded_as("valíd\\ųtf8", "valíd\\x5cųtf8")); ++ assert_se(expect_encoded_as("s/ash/ng", "s\\x2fash\\x2fng")); ++} ++ ++int main(int argc, char *argv[]) { ++ test_encode_devnode_name(); ++ ++ return 0; ++} +diff --git a/src/test/test-utf8.c b/src/test/test-utf8.c +index 26cc37b..b5a833e 100644 +--- a/src/test/test-utf8.c ++++ b/src/test/test-utf8.c +@@ -19,34 +19,9 @@ + along with systemd; If not, see . + ***/ + +- + #include "utf8.h" + #include "util.h" + +-/* helpers for test_udev_encode_string */ +-static char *do_encode_string(const char *in) { +- size_t out_len = strlen(in) * 4; +- char *out = malloc(out_len); +- +- assert_se(out); +- assert_se(udev_encode_string(in, out, out_len) >= 0); +- puts(out); +- +- return out; +-} +- +-static bool expect_encoded_as(const char *in, const char *expected) { +- _cleanup_free_ char *encoded = do_encode_string(in); +- return streq(encoded, expected); +-} +- +-static void test_udev_encode_string(void) { +- assert_se(expect_encoded_as("systemd sucks", "systemd\\x20sucks")); +- assert_se(expect_encoded_as("pinkiepie", "pinkiepie")); +- assert_se(expect_encoded_as("valíd\\ųtf8", "valíd\\x5cųtf8")); +- assert_se(expect_encoded_as("s/ash/ng", "s\\x2fash\\x2fng")); +-} +- + static void test_utf8_is_printable(void) { + assert_se(utf8_is_printable("ascii is valid\tunicode", 22)); + assert_se(utf8_is_printable("\342\204\242", 3)); +@@ -55,14 +30,13 @@ static void test_utf8_is_printable(void) { + + static void test_utf8_is_valid(void) { + assert_se(utf8_is_valid("ascii is valid unicode")); +- assert_se(utf8_is_valid("\341\204\242")); ++ assert_se(utf8_is_valid("\342\204\242")); + assert_se(!utf8_is_valid("\341\204")); + } + + int main(int argc, char *argv[]) { + test_utf8_is_valid(); + test_utf8_is_printable(); +- test_udev_encode_string(); + + return 0; + } diff --git a/SOURCES/0089-shared-util-fix-off-by-one-error-in-tag_to_udev_node.patch b/SOURCES/0089-shared-util-fix-off-by-one-error-in-tag_to_udev_node.patch new file mode 100644 index 0000000..b7146f4 --- /dev/null +++ b/SOURCES/0089-shared-util-fix-off-by-one-error-in-tag_to_udev_node.patch @@ -0,0 +1,47 @@ +From 665bb7f5ec052d5e78bb298f1f2fc181ba03c411 Mon Sep 17 00:00:00 2001 +From: Dave Reisner +Date: Sun, 6 Oct 2013 18:26:23 -0400 +Subject: [PATCH] shared/util: fix off-by-one error in tag_to_udev_node + +Triggered false negatives when encoding a string which needed every +character to be escaped, e.g. "LABEL=/". +--- + src/shared/util.c | 2 +- + src/test/test-device-nodes.c | 4 +++- + 2 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/src/shared/util.c b/src/shared/util.c +index 4711d91..e69d1ff 100644 +--- a/src/shared/util.c ++++ b/src/shared/util.c +@@ -3504,7 +3504,7 @@ static char *tag_to_udev_node(const char *tagvalue, const char *by) { + if (u == NULL) + return NULL; + +- enc_len = strlen(u) * 4; ++ enc_len = strlen(u) * 4 + 1; + t = new(char, enc_len); + if (t == NULL) + return NULL; +diff --git a/src/test/test-device-nodes.c b/src/test/test-device-nodes.c +index 2f3dedb..59ba4be 100644 +--- a/src/test/test-device-nodes.c ++++ b/src/test/test-device-nodes.c +@@ -26,7 +26,7 @@ + + /* helpers for test_encode_devnode_name */ + static char *do_encode_string(const char *in) { +- size_t out_len = strlen(in) * 4; ++ size_t out_len = strlen(in) * 4 + 1; + char *out = malloc(out_len); + + assert_se(out); +@@ -46,6 +46,8 @@ static void test_encode_devnode_name(void) { + assert_se(expect_encoded_as("pinkiepie", "pinkiepie")); + assert_se(expect_encoded_as("valíd\\ųtf8", "valíd\\x5cųtf8")); + assert_se(expect_encoded_as("s/ash/ng", "s\\x2fash\\x2fng")); ++ assert_se(expect_encoded_as("/", "\\x2f")); ++ assert_se(expect_encoded_as("!", "\\x21")); + } + + int main(int argc, char *argv[]) { diff --git a/SOURCES/0090-udev-path_id-fix-by-path-link-generation-for-scm-dev.patch b/SOURCES/0090-udev-path_id-fix-by-path-link-generation-for-scm-dev.patch new file mode 100644 index 0000000..81471cb --- /dev/null +++ b/SOURCES/0090-udev-path_id-fix-by-path-link-generation-for-scm-dev.patch @@ -0,0 +1,25 @@ +From dd6fb603d74e958f6a24b07f8792f07a576111ee Mon Sep 17 00:00:00 2001 +From: Sebastian Ott +Date: Tue, 17 Sep 2013 19:16:08 +0200 +Subject: [PATCH] udev: path_id - fix by-path link generation for scm devices + +Set some_transport = true to prevent scm devices from being ignored. + +Suggested-by: Harald Hoyer +Signed-off-by: Sebastian Ott +--- + src/udev/udev-builtin-path_id.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c +index da02731..0659967 100644 +--- a/src/udev/udev-builtin-path_id.c ++++ b/src/udev/udev-builtin-path_id.c +@@ -531,6 +531,7 @@ static int builtin_path_id(struct udev_device *dev, int argc, char *argv[], bool + } else if (streq(subsys, "scm")) { + path_prepend(&path, "scm-%s", udev_device_get_sysname(parent)); + parent = skip_subsystem(parent, "scm"); ++ some_transport = true; + } + + parent = udev_device_get_parent(parent); diff --git a/SOURCES/0091-hashmap-randomize-hash-functions-a-bit.patch b/SOURCES/0091-hashmap-randomize-hash-functions-a-bit.patch new file mode 100644 index 0000000..5c7b270 --- /dev/null +++ b/SOURCES/0091-hashmap-randomize-hash-functions-a-bit.patch @@ -0,0 +1,374 @@ +From 9bf25f9e532dad32d71e95a85c413996d4bd58ac Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 1 Oct 2013 23:11:23 +0200 +Subject: [PATCH] hashmap: randomize hash functions a bit + +--- + configure.ac | 2 +- + src/shared/hashmap.c | 104 +++++++++++++++++++++++++++++++-------------------- + src/shared/util.c | 19 ++++++++++ + src/shared/util.h | 1 + + 4 files changed, 85 insertions(+), 41 deletions(-) + +diff --git a/configure.ac b/configure.ac +index c7f4f1b..2ae0411 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -804,7 +804,7 @@ have_myhostname=no + AC_ARG_ENABLE(myhostname, AS_HELP_STRING([--disable-myhostname], [disable nss-myhostname support])) + if test "x$enable_myhostname" != "xno"; then + AC_HEADER_STDC +- AC_CHECK_HEADERS([arpa/inet.h fcntl.h inttypes.h netdb.h netinet/in.h stdlib.h string.h sys/socket.h sys/time.h unistd.h nss.h sys/ioctl.h]) ++ AC_CHECK_HEADERS([arpa/inet.h fcntl.h inttypes.h netdb.h netinet/in.h stdlib.h string.h sys/socket.h sys/time.h unistd.h nss.h sys/ioctl.h sys/auxv.h]) + + AC_C_CONST + AC_TYPE_SIZE_T +diff --git a/src/shared/hashmap.c b/src/shared/hashmap.c +index 6330792..f06fce6 100644 +--- a/src/shared/hashmap.c ++++ b/src/shared/hashmap.c +@@ -24,6 +24,10 @@ + #include + #include + ++#ifdef HAVE_SYS_AUXV_H ++#include ++#endif ++ + #include "util.h" + #include "hashmap.h" + #include "macro.h" +@@ -46,6 +50,7 @@ struct Hashmap { + struct hashmap_entry ** buckets; + unsigned n_buckets, n_entries; + ++ unsigned random_xor; + bool from_pool; + }; + +@@ -171,10 +176,15 @@ int uint64_compare_func(const void *_a, const void *_b) { + return a < b ? -1 : (a > b ? 1 : 0); + } + ++static unsigned bucket_hash(Hashmap *h, const void *p) { ++ return (h->hash_func(p) ^ h->random_xor) % h->n_buckets; ++} ++ + Hashmap *hashmap_new(hash_func_t hash_func, compare_func_t compare_func) { + bool b; + Hashmap *h; + size_t size; ++ void *auxv; + + b = is_main_thread(); + +@@ -204,6 +214,19 @@ Hashmap *hashmap_new(hash_func_t hash_func, compare_func_t compare_func) { + + h->from_pool = b; + ++ /* Let's randomize our hash functions a bit so that they are ++ * harder to guess for clients. For this, start out by cheaply ++ * using some bits the kernel passed into the process using ++ * the auxiliary vector. If the hashmap grows later on we will ++ * rehash everything using a new random XOR mask from ++ * /dev/random. */ ++#ifdef HAVE_SYS_AUXV_H ++ auxv = (void*) getauxval(AT_RANDOM); ++ h->random_xor = auxv ? *(unsigned*) auxv : random_u(); ++#else ++ h->random_xor = random_u(); ++#endif ++ + return h; + } + +@@ -284,8 +307,7 @@ static void remove_entry(Hashmap *h, struct hashmap_entry *e) { + assert(h); + assert(e); + +- hash = h->hash_func(e->key) % h->n_buckets; +- ++ hash = bucket_hash(h, e->key); + unlink_entry(h, e, hash); + + if (h->from_pool) +@@ -368,7 +390,6 @@ void hashmap_clear_free_free(Hashmap *h) { + } + } + +- + static struct hashmap_entry *hash_scan(Hashmap *h, unsigned hash, const void *key) { + struct hashmap_entry *e; + assert(h); +@@ -382,8 +403,8 @@ static struct hashmap_entry *hash_scan(Hashmap *h, unsigned hash, const void *ke + } + + static bool resize_buckets(Hashmap *h) { +- unsigned m; + struct hashmap_entry **n, *i; ++ unsigned m, nxor; + + assert(h); + +@@ -398,6 +419,11 @@ static bool resize_buckets(Hashmap *h) { + if (!n) + return false; + ++ /* Let's use a different randomized xor value for the ++ * extension, so that people cannot guess what we are using ++ * here forever */ ++ nxor = random_u(); ++ + for (i = h->iterate_list_head; i; i = i->iterate_next) { + unsigned hash, x; + +@@ -410,10 +436,10 @@ static bool resize_buckets(Hashmap *h) { + if (i->bucket_previous) + i->bucket_previous->bucket_next = i->bucket_next; + else +- h->buckets[hash % h->n_buckets] = i->bucket_next; ++ h->buckets[(hash ^ h->random_xor) % h->n_buckets] = i->bucket_next; + + /* Then, add to new backet table */ +- x = hash % m; ++ x = (hash ^ nxor) % m; + + i->bucket_next = n[x]; + i->bucket_previous = NULL; +@@ -427,6 +453,7 @@ static bool resize_buckets(Hashmap *h) { + + h->buckets = n; + h->n_buckets = m; ++ h->random_xor = nxor; + + return true; + } +@@ -437,7 +464,7 @@ int hashmap_put(Hashmap *h, const void *key, void *value) { + + assert(h); + +- hash = h->hash_func(key) % h->n_buckets; ++ hash = bucket_hash(h, key); + e = hash_scan(h, hash, key); + if (e) { + if (e->value == value) +@@ -446,7 +473,7 @@ int hashmap_put(Hashmap *h, const void *key, void *value) { + } + + if (resize_buckets(h)) +- hash = h->hash_func(key) % h->n_buckets; ++ hash = bucket_hash(h, key); + + if (h->from_pool) + e = allocate_tile(&first_entry_pool, &first_entry_tile, sizeof(struct hashmap_entry)); +@@ -470,7 +497,7 @@ int hashmap_replace(Hashmap *h, const void *key, void *value) { + + assert(h); + +- hash = h->hash_func(key) % h->n_buckets; ++ hash = bucket_hash(h, key); + e = hash_scan(h, hash, key); + if (e) { + e->key = key; +@@ -487,7 +514,7 @@ int hashmap_update(Hashmap *h, const void *key, void *value) { + + assert(h); + +- hash = h->hash_func(key) % h->n_buckets; ++ hash = bucket_hash(h, key); + e = hash_scan(h, hash, key); + if (!e) + return -ENOENT; +@@ -503,7 +530,7 @@ void* hashmap_get(Hashmap *h, const void *key) { + if (!h) + return NULL; + +- hash = h->hash_func(key) % h->n_buckets; ++ hash = bucket_hash(h, key); + e = hash_scan(h, hash, key); + if (!e) + return NULL; +@@ -518,7 +545,7 @@ void* hashmap_get2(Hashmap *h, const void *key, void **key2) { + if (!h) + return NULL; + +- hash = h->hash_func(key) % h->n_buckets; ++ hash = bucket_hash(h, key); + e = hash_scan(h, hash, key); + if (!e) + return NULL; +@@ -535,12 +562,8 @@ bool hashmap_contains(Hashmap *h, const void *key) { + if (!h) + return false; + +- hash = h->hash_func(key) % h->n_buckets; +- +- if (!hash_scan(h, hash, key)) +- return false; +- +- return true; ++ hash = bucket_hash(h, key); ++ return !!hash_scan(h, hash, key); + } + + void* hashmap_remove(Hashmap *h, const void *key) { +@@ -551,9 +574,9 @@ void* hashmap_remove(Hashmap *h, const void *key) { + if (!h) + return NULL; + +- hash = h->hash_func(key) % h->n_buckets; +- +- if (!(e = hash_scan(h, hash, key))) ++ hash = bucket_hash(h, key); ++ e = hash_scan(h, hash, key); ++ if (!e) + return NULL; + + data = e->value; +@@ -569,11 +592,12 @@ int hashmap_remove_and_put(Hashmap *h, const void *old_key, const void *new_key, + if (!h) + return -ENOENT; + +- old_hash = h->hash_func(old_key) % h->n_buckets; +- if (!(e = hash_scan(h, old_hash, old_key))) ++ old_hash = bucket_hash(h, old_key); ++ e = hash_scan(h, old_hash, old_key); ++ if (!e) + return -ENOENT; + +- new_hash = h->hash_func(new_key) % h->n_buckets; ++ new_hash = bucket_hash(h, new_key); + if (hash_scan(h, new_hash, new_key)) + return -EEXIST; + +@@ -594,12 +618,14 @@ int hashmap_remove_and_replace(Hashmap *h, const void *old_key, const void *new_ + if (!h) + return -ENOENT; + +- old_hash = h->hash_func(old_key) % h->n_buckets; +- if (!(e = hash_scan(h, old_hash, old_key))) ++ old_hash = bucket_hash(h, old_key); ++ e = hash_scan(h, old_hash, old_key); ++ if (!e) + return -ENOENT; + +- new_hash = h->hash_func(new_key) % h->n_buckets; +- if ((k = hash_scan(h, new_hash, new_key))) ++ new_hash = bucket_hash(h, new_key); ++ k = hash_scan(h, new_hash, new_key); ++ if (k) + if (e != k) + remove_entry(h, k); + +@@ -620,7 +646,7 @@ void* hashmap_remove_value(Hashmap *h, const void *key, void *value) { + if (!h) + return NULL; + +- hash = h->hash_func(key) % h->n_buckets; ++ hash = bucket_hash(h, key); + + e = hash_scan(h, hash, key); + if (!e) +@@ -711,7 +737,7 @@ void *hashmap_iterate_skip(Hashmap *h, const void *key, Iterator *i) { + if (!h) + return NULL; + +- hash = h->hash_func(key) % h->n_buckets; ++ hash = bucket_hash(h, key); + + e = hash_scan(h, hash, key); + if (!e) +@@ -820,9 +846,9 @@ int hashmap_merge(Hashmap *h, Hashmap *other) { + for (e = other->iterate_list_head; e; e = e->iterate_next) { + int r; + +- if ((r = hashmap_put(h, e->key, e->value)) < 0) +- if (r != -EEXIST) +- return r; ++ r = hashmap_put(h, e->key, e->value); ++ if (r < 0 && r != -EEXIST) ++ return r; + } + + return 0; +@@ -844,13 +870,11 @@ void hashmap_move(Hashmap *h, Hashmap *other) { + + n = e->iterate_next; + +- h_hash = h->hash_func(e->key) % h->n_buckets; +- ++ h_hash = bucket_hash(h, e->key); + if (hash_scan(h, h_hash, e->key)) + continue; + +- other_hash = other->hash_func(e->key) % other->n_buckets; +- ++ other_hash = bucket_hash(other, e->key); + unlink_entry(other, e, other_hash); + link_entry(h, e, h_hash); + } +@@ -865,11 +889,11 @@ int hashmap_move_one(Hashmap *h, Hashmap *other, const void *key) { + + assert(h); + +- h_hash = h->hash_func(key) % h->n_buckets; ++ h_hash = bucket_hash(h, key); + if (hash_scan(h, h_hash, key)) + return -EEXIST; + +- other_hash = other->hash_func(key) % other->n_buckets; ++ other_hash = bucket_hash(other, key); + e = hash_scan(other, other_hash, key); + if (!e) + return -ENOENT; +@@ -925,7 +949,7 @@ void *hashmap_next(Hashmap *h, const void *key) { + if (!h) + return NULL; + +- hash = h->hash_func(key) % h->n_buckets; ++ hash = bucket_hash(h, key); + e = hash_scan(h, hash, key); + if (!e) + return NULL; +diff --git a/src/shared/util.c b/src/shared/util.c +index e69d1ff..95fe35e 100644 +--- a/src/shared/util.c ++++ b/src/shared/util.c +@@ -2420,6 +2420,25 @@ fallback: + return random() * RAND_MAX + random(); + } + ++unsigned random_u(void) { ++ _cleanup_close_ int fd; ++ unsigned u; ++ ssize_t r; ++ ++ fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY); ++ if (fd < 0) ++ goto fallback; ++ ++ r = loop_read(fd, &u, sizeof(u), true); ++ if (r != sizeof(u)) ++ goto fallback; ++ ++ return u; ++ ++fallback: ++ return random() * RAND_MAX + random(); ++} ++ + void rename_process(const char name[8]) { + assert(name); + +diff --git a/src/shared/util.h b/src/shared/util.h +index 63f4e3d..1b845b3 100644 +--- a/src/shared/util.h ++++ b/src/shared/util.h +@@ -253,6 +253,7 @@ int make_null_stdio(void); + int make_console_stdio(void); + + unsigned long long random_ull(void); ++unsigned random_u(void); + + /* For basic lookup tables with strictly enumerated entries */ + #define __DEFINE_STRING_TABLE_LOOKUP(name,type,scope) \ diff --git a/SOURCES/0092-Configurable-Timeouts-Restarts-default-values.patch b/SOURCES/0092-Configurable-Timeouts-Restarts-default-values.patch new file mode 100644 index 0000000..6267d66 --- /dev/null +++ b/SOURCES/0092-Configurable-Timeouts-Restarts-default-values.patch @@ -0,0 +1,293 @@ +From b78b223c1f2cfb6bdeac4dc22748e7289c4537da Mon Sep 17 00:00:00 2001 +From: Oleksii Shevchuk +Date: Mon, 4 Nov 2013 18:47:43 +0200 +Subject: [PATCH] Configurable Timeouts/Restarts default values + +https://bugs.freedesktop.org/show_bug.cgi?id=71132 + +Patch adds DefaultTimeoutStartSec, DefaultTimeoutStopSec, DefaultRestartSec +configuration options to manager configuration file. +--- + man/systemd-system.conf.xml | 24 +++++++++++++++++++++++- + man/systemd.mount.xml | 4 ++-- + man/systemd.service.xml | 6 ++++-- + man/systemd.socket.xml | 4 ++-- + man/systemd.swap.xml | 4 ++-- + src/core/device.c | 2 +- + src/core/main.c | 9 +++++++++ + src/core/manager.h | 3 +++ + src/core/mount.c | 2 +- + src/core/scope.c | 2 +- + src/core/service.c | 6 +++--- + src/core/socket.c | 2 +- + src/core/swap.c | 2 +- + src/core/system.conf | 3 +++ + src/core/user.conf | 3 +++ + 15 files changed, 59 insertions(+), 17 deletions(-) + +diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml +index e8cf8a9..c1f2648 100644 +--- a/man/systemd-system.conf.xml ++++ b/man/systemd-system.conf.xml +@@ -61,7 +61,6 @@ + otherwise user.conf. These + configuration files contain a few settings controlling + basic manager operations. +- + + + +@@ -95,6 +94,29 @@ + + + ++ DefaultTimeoutStartSec= ++ DefaultTimeoutStopSec= ++ DefaultRestartSec= ++ ++ Configures the default ++ time-outs for starting and stopping of ++ units, as well as the default time to ++ sleep between automatic restarts of a ++ units, as configured per-unit in ++ TimeoutStartSec=, ++ TimeoutStopSec= and ++ RestartSec= (for ++ service units see ++ systemd.service5 ++ for details on the per-unit ++ settings). For non-service units ++ DefaultTimeoutStartSec= ++ sets the default ++ TimeoutSec= value. ++ ++ ++ ++ + CPUAffinity= + + Configures the initial +diff --git a/man/systemd.mount.xml b/man/systemd.mount.xml +index 48af1ca..71a5736 100644 +--- a/man/systemd.mount.xml ++++ b/man/systemd.mount.xml +@@ -260,8 +260,8 @@ + Takes a unit-less value in seconds, or + a time span value such as "5min + 20s". Pass 0 to disable the timeout +- logic. Defaults to +- 90s. ++ logic. Default value is setted up in manager configuration ++ file via DefaultTimeoutStart=. + + + +diff --git a/man/systemd.service.xml b/man/systemd.service.xml +index 45f96fa..1e94f82 100644 +--- a/man/systemd.service.xml ++++ b/man/systemd.service.xml +@@ -523,7 +523,8 @@ + Takes a unit-less value in seconds, or a + time span value such as "5min + 20s". Pass 0 to disable the timeout +- logic. Defaults to 90s, except when ++ logic. Defaults to TimeoutStartSec= in ++ manager configuration file, except when + Type=oneshot is + used in which case the timeout + is disabled by default. +@@ -544,7 +545,8 @@ + Takes a unit-less value in seconds, or a + time span value such as "5min + 20s". Pass 0 to disable the timeout +- logic. Defaults to 90s. ++ logic. Defaults to TimeoutStartSec= in ++ manager configuration file. + + + +diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml +index 8c88d9f..1c78562 100644 +--- a/man/systemd.socket.xml ++++ b/man/systemd.socket.xml +@@ -679,8 +679,8 @@ + Takes a unit-less value in seconds, or + a time span value such as "5min + 20s". Pass 0 to disable the timeout +- logic. Defaults to +- 90s. ++ logic. Defaults to TimeoutStartSec= in ++ manager configuration file. + + + +diff --git a/man/systemd.swap.xml b/man/systemd.swap.xml +index 813ae6c..13f6c84 100644 +--- a/man/systemd.swap.xml ++++ b/man/systemd.swap.xml +@@ -186,8 +186,8 @@ + Takes a unit-less value in seconds, or + a time span value such as "5min + 20s". Pass 0 to disable the timeout +- logic. Defaults to +- 90s. ++ logic. Defaults to TimeoutStartSec= in ++ manager configuration file. + + + +diff --git a/src/core/device.c b/src/core/device.c +index 9fca82a..5397bd6 100644 +--- a/src/core/device.c ++++ b/src/core/device.c +@@ -70,7 +70,7 @@ static void device_init(Unit *u) { + * indefinitely for plugged in devices, something which cannot + * happen for the other units since their operations time out + * anyway. */ +- UNIT(d)->job_timeout = DEFAULT_TIMEOUT_USEC; ++ UNIT(d)->job_timeout = u->manager->default_timeout_start_usec; + + UNIT(d)->ignore_on_isolate = true; + UNIT(d)->ignore_on_snapshot = true; +diff --git a/src/core/main.c b/src/core/main.c +index 662d16d..b72d7f4 100644 +--- a/src/core/main.c ++++ b/src/core/main.c +@@ -90,6 +90,9 @@ static bool arg_switched_root = false; + static char ***arg_join_controllers = NULL; + static ExecOutput arg_default_std_output = EXEC_OUTPUT_JOURNAL; + static ExecOutput arg_default_std_error = EXEC_OUTPUT_INHERIT; ++static usec_t arg_default_restart_usec = DEFAULT_RESTART_USEC; ++static usec_t arg_default_timeout_start_usec = DEFAULT_TIMEOUT_USEC; ++static usec_t arg_default_timeout_stop_usec = DEFAULT_TIMEOUT_USEC; + static usec_t arg_runtime_watchdog = 0; + static usec_t arg_shutdown_watchdog = 10 * USEC_PER_MINUTE; + static char **arg_default_environment = NULL; +@@ -636,6 +639,9 @@ static int parse_config_file(void) { + { "Manager", "CPUAffinity", config_parse_cpu_affinity2, 0, NULL }, + { "Manager", "DefaultStandardOutput", config_parse_output, 0, &arg_default_std_output }, + { "Manager", "DefaultStandardError", config_parse_output, 0, &arg_default_std_error }, ++ { "Manager", "DefaultTimeoutStartSec", config_parse_sec, 0, &arg_default_timeout_start_usec }, ++ { "Manager", "DefaultTimeoutStopSec", config_parse_sec, 0, &arg_default_timeout_stop_usec }, ++ { "Manager", "DefaultRestartSec", config_parse_sec, 0, &arg_default_restart_usec }, + { "Manager", "JoinControllers", config_parse_join_controllers, 0, &arg_join_controllers }, + { "Manager", "RuntimeWatchdogSec", config_parse_sec, 0, &arg_runtime_watchdog }, + { "Manager", "ShutdownWatchdogSec", config_parse_sec, 0, &arg_shutdown_watchdog }, +@@ -1542,6 +1548,9 @@ int main(int argc, char *argv[]) { + m->confirm_spawn = arg_confirm_spawn; + m->default_std_output = arg_default_std_output; + m->default_std_error = arg_default_std_error; ++ m->default_restart_usec = arg_default_restart_usec; ++ m->default_timeout_start_usec = arg_default_timeout_start_usec; ++ m->default_timeout_stop_usec = arg_default_timeout_stop_usec; + m->runtime_watchdog = arg_runtime_watchdog; + m->shutdown_watchdog = arg_shutdown_watchdog; + m->userspace_timestamp = userspace_timestamp; +diff --git a/src/core/manager.h b/src/core/manager.h +index a3049b5..e74c609 100644 +--- a/src/core/manager.h ++++ b/src/core/manager.h +@@ -230,6 +230,9 @@ struct Manager { + + ExecOutput default_std_output, default_std_error; + ++ usec_t default_restart_usec, default_timeout_start_usec, ++ default_timeout_stop_usec; ++ + struct rlimit *rlimit[RLIMIT_NLIMITS]; + + /* non-zero if we are reloading or reexecuting, */ +diff --git a/src/core/mount.c b/src/core/mount.c +index 70cd372..c0445a6 100644 +--- a/src/core/mount.c ++++ b/src/core/mount.c +@@ -131,7 +131,7 @@ static void mount_init(Unit *u) { + assert(u); + assert(u->load_state == UNIT_STUB); + +- m->timeout_usec = DEFAULT_TIMEOUT_USEC; ++ m->timeout_usec = u->manager->default_timeout_start_usec; + m->directory_mode = 0755; + + exec_context_init(&m->exec_context); +diff --git a/src/core/scope.c b/src/core/scope.c +index 50e5dba..41da3b9 100644 +--- a/src/core/scope.c ++++ b/src/core/scope.c +@@ -46,7 +46,7 @@ static void scope_init(Unit *u) { + assert(u); + assert(u->load_state == UNIT_STUB); + +- s->timeout_stop_usec = DEFAULT_TIMEOUT_USEC; ++ s->timeout_stop_usec = u->manager->default_timeout_stop_usec; + + watch_init(&s->timer_watch); + +diff --git a/src/core/service.c b/src/core/service.c +index cfc8ba6..ea47f8c 100644 +--- a/src/core/service.c ++++ b/src/core/service.c +@@ -124,9 +124,9 @@ static void service_init(Unit *u) { + assert(u); + assert(u->load_state == UNIT_STUB); + +- s->timeout_start_usec = DEFAULT_TIMEOUT_USEC; +- s->timeout_stop_usec = DEFAULT_TIMEOUT_USEC; +- s->restart_usec = DEFAULT_RESTART_USEC; ++ s->timeout_start_usec = u->manager->default_timeout_start_usec; ++ s->timeout_stop_usec = u->manager->default_timeout_stop_usec; ++ s->restart_usec = u->manager->default_restart_usec; + s->type = _SERVICE_TYPE_INVALID; + + watch_init(&s->watchdog_watch); +diff --git a/src/core/socket.c b/src/core/socket.c +index 778f8c8..247f2fb 100644 +--- a/src/core/socket.c ++++ b/src/core/socket.c +@@ -73,7 +73,7 @@ static void socket_init(Unit *u) { + assert(u->load_state == UNIT_STUB); + + s->backlog = SOMAXCONN; +- s->timeout_usec = DEFAULT_TIMEOUT_USEC; ++ s->timeout_usec = u->manager->default_timeout_start_usec; + s->directory_mode = 0755; + s->socket_mode = 0666; + +diff --git a/src/core/swap.c b/src/core/swap.c +index 6f86a86..392cb17 100644 +--- a/src/core/swap.c ++++ b/src/core/swap.c +@@ -86,7 +86,7 @@ static void swap_init(Unit *u) { + assert(s); + assert(UNIT(s)->load_state == UNIT_STUB); + +- s->timeout_usec = DEFAULT_TIMEOUT_USEC; ++ s->timeout_usec = u->manager->default_timeout_start_usec; + + exec_context_init(&s->exec_context); + s->exec_context.std_output = u->manager->default_std_output; +diff --git a/src/core/system.conf b/src/core/system.conf +index 7b03c87..3c6cc03 100644 +--- a/src/core/system.conf ++++ b/src/core/system.conf +@@ -24,6 +24,9 @@ + #ShutdownWatchdogSec=10min + #CapabilityBoundingSet= + #TimerSlackNSec= ++#DefaultTimeoutStartSec=90s ++#DefaultTimeoutStopSec=90s ++#DefaultRestartSec=100ms + #DefaultEnvironment= + #DefaultLimitCPU= + #DefaultLimitFSIZE= +diff --git a/src/core/user.conf b/src/core/user.conf +index 4a0129a..b030701 100644 +--- a/src/core/user.conf ++++ b/src/core/user.conf +@@ -14,3 +14,6 @@ + #LogLocation=no + #DefaultStandardOutput=inherit + #DefaultStandardError=inherit ++#DefaultTimeoutStartSec=90s ++#DefaultTimeoutStopSec=90s ++#DefaultRestartSec=100ms diff --git a/SOURCES/0093-manager-configurable-StartLimit-default-values.patch b/SOURCES/0093-manager-configurable-StartLimit-default-values.patch new file mode 100644 index 0000000..c564dda --- /dev/null +++ b/SOURCES/0093-manager-configurable-StartLimit-default-values.patch @@ -0,0 +1,161 @@ +From 4490d065a987d464fed86b2d48d607766c192bfe Mon Sep 17 00:00:00 2001 +From: Lukas Nykryn +Date: Fri, 8 Nov 2013 16:01:22 +0100 +Subject: [PATCH] manager: configurable StartLimit default values + +https://bugzilla.redhat.com/show_bug.cgi?id=821723 +--- + man/systemd-system.conf.xml | 13 +++++++++++++ + man/systemd.service.xml | 9 ++++++--- + src/core/main.c | 6 ++++++ + src/core/manager.h | 3 +++ + src/core/service.c | 4 +++- + src/core/system.conf | 2 ++ + src/core/user.conf | 2 ++ + src/shared/def.h | 3 +++ + 8 files changed, 38 insertions(+), 4 deletions(-) + +diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml +index c1f2648..9a1a99f 100644 +--- a/man/systemd-system.conf.xml ++++ b/man/systemd-system.conf.xml +@@ -115,6 +115,19 @@ + TimeoutSec= value. + + ++ ++ DefaultStartLimitInterval= ++ DefaultStartLimitBurst= ++ ++ Configure the default start rate ++ limiting, as configured per-service by ++ StartLimitInterval= and ++ StartLimitBurst=. See ++ systemd.service5 ++ for details on the per-service ++ settings). ++ ++ + + + CPUAffinity= +diff --git a/man/systemd.service.xml b/man/systemd.service.xml +index 1e94f82..7200fb9 100644 +--- a/man/systemd.service.xml ++++ b/man/systemd.service.xml +@@ -862,12 +862,15 @@ + these two options, this rate limiting + may be modified. Use + StartLimitInterval= +- to configure the checking interval +- (defaults to 10s, set to 0 to disable ++ to configure the checking interval (defaults to ++ DefaultStartLimitInterval= in ++ manager configuration file, set to 0 to disable + any kind of rate limiting). Use + StartLimitBurst= to + configure how many starts per interval +- are allowed (defaults to 5). These ++ are allowed (defaults to ++ DefaultStartLimitBurst= in ++ manager configuration file). These + configuration options are particularly + useful in conjunction with + Restart=, however +diff --git a/src/core/main.c b/src/core/main.c +index b72d7f4..4911768 100644 +--- a/src/core/main.c ++++ b/src/core/main.c +@@ -93,6 +93,8 @@ static ExecOutput arg_default_std_error = EXEC_OUTPUT_INHERIT; + static usec_t arg_default_restart_usec = DEFAULT_RESTART_USEC; + static usec_t arg_default_timeout_start_usec = DEFAULT_TIMEOUT_USEC; + static usec_t arg_default_timeout_stop_usec = DEFAULT_TIMEOUT_USEC; ++static usec_t arg_default_start_limit_interval = DEFAULT_START_LIMIT_INTERVAL; ++static unsigned arg_default_start_limit_burst = DEFAULT_START_LIMIT_BURST; + static usec_t arg_runtime_watchdog = 0; + static usec_t arg_shutdown_watchdog = 10 * USEC_PER_MINUTE; + static char **arg_default_environment = NULL; +@@ -642,6 +644,8 @@ static int parse_config_file(void) { + { "Manager", "DefaultTimeoutStartSec", config_parse_sec, 0, &arg_default_timeout_start_usec }, + { "Manager", "DefaultTimeoutStopSec", config_parse_sec, 0, &arg_default_timeout_stop_usec }, + { "Manager", "DefaultRestartSec", config_parse_sec, 0, &arg_default_restart_usec }, ++ { "Manager", "DefaultStartLimitInterval", config_parse_sec, 0, &arg_default_start_limit_interval }, ++ { "Manager", "DefaultStartLimitBurst", config_parse_unsigned, 0, &arg_default_start_limit_burst }, + { "Manager", "JoinControllers", config_parse_join_controllers, 0, &arg_join_controllers }, + { "Manager", "RuntimeWatchdogSec", config_parse_sec, 0, &arg_runtime_watchdog }, + { "Manager", "ShutdownWatchdogSec", config_parse_sec, 0, &arg_shutdown_watchdog }, +@@ -1551,6 +1555,8 @@ int main(int argc, char *argv[]) { + m->default_restart_usec = arg_default_restart_usec; + m->default_timeout_start_usec = arg_default_timeout_start_usec; + m->default_timeout_stop_usec = arg_default_timeout_stop_usec; ++ m->default_start_limit_interval = arg_default_start_limit_interval; ++ m->default_start_limit_burst = arg_default_start_limit_burst; + m->runtime_watchdog = arg_runtime_watchdog; + m->shutdown_watchdog = arg_shutdown_watchdog; + m->userspace_timestamp = userspace_timestamp; +diff --git a/src/core/manager.h b/src/core/manager.h +index e74c609..ee42c5e 100644 +--- a/src/core/manager.h ++++ b/src/core/manager.h +@@ -233,6 +233,9 @@ struct Manager { + usec_t default_restart_usec, default_timeout_start_usec, + default_timeout_stop_usec; + ++ usec_t default_start_limit_interval; ++ unsigned default_start_limit_burst; ++ + struct rlimit *rlimit[RLIMIT_NLIMITS]; + + /* non-zero if we are reloading or reexecuting, */ +diff --git a/src/core/service.c b/src/core/service.c +index ea47f8c..cefb253 100644 +--- a/src/core/service.c ++++ b/src/core/service.c +@@ -143,7 +143,9 @@ static void service_init(Unit *u) { + kill_context_init(&s->kill_context); + cgroup_context_init(&s->cgroup_context); + +- RATELIMIT_INIT(s->start_limit, 10*USEC_PER_SEC, 5); ++ RATELIMIT_INIT(s->start_limit, ++ u->manager->default_start_limit_interval, ++ u->manager->default_start_limit_burst); + + s->control_command_id = _SERVICE_EXEC_COMMAND_INVALID; + } +diff --git a/src/core/system.conf b/src/core/system.conf +index 3c6cc03..38bbca5 100644 +--- a/src/core/system.conf ++++ b/src/core/system.conf +@@ -27,6 +27,8 @@ + #DefaultTimeoutStartSec=90s + #DefaultTimeoutStopSec=90s + #DefaultRestartSec=100ms ++#DefaultStartLimitInterval=10s ++#DefaultStartLimitBurst=5 + #DefaultEnvironment= + #DefaultLimitCPU= + #DefaultLimitFSIZE= +diff --git a/src/core/user.conf b/src/core/user.conf +index b030701..923ca66 100644 +--- a/src/core/user.conf ++++ b/src/core/user.conf +@@ -17,3 +17,5 @@ + #DefaultTimeoutStartSec=90s + #DefaultTimeoutStopSec=90s + #DefaultRestartSec=100ms ++#DefaultStartLimitInterval=10s ++#DefaultStartLimitBurst=5 +diff --git a/src/shared/def.h b/src/shared/def.h +index edd0bcf..e4ef735 100644 +--- a/src/shared/def.h ++++ b/src/shared/def.h +@@ -27,6 +27,9 @@ + #define DEFAULT_RESTART_USEC (100*USEC_PER_MSEC) + #define DEFAULT_CONFIRM_USEC (30*USEC_PER_SEC) + ++#define DEFAULT_START_LIMIT_INTERVAL (10*USEC_PER_SEC) ++#define DEFAULT_START_LIMIT_BURST 5 ++ + #define DEFAULT_EXIT_USEC (5*USEC_PER_MINUTE) + + #define SYSTEMD_CGROUP_CONTROLLER "name=systemd" diff --git a/SOURCES/0094-sysctl-bring-back-etc-sysctl.conf.patch b/SOURCES/0094-sysctl-bring-back-etc-sysctl.conf.patch new file mode 100644 index 0000000..9b8e129 --- /dev/null +++ b/SOURCES/0094-sysctl-bring-back-etc-sysctl.conf.patch @@ -0,0 +1,25 @@ +From c5e66155b5d6bb57aa1c93bdab988e61c3e41bbe Mon Sep 17 00:00:00 2001 +From: Harald Hoyer +Date: Mon, 11 Nov 2013 11:17:57 +0100 +Subject: [PATCH] sysctl: bring back /etc/sysctl.conf + +Read /etc/sysctl.conf as the last file, overwriting everything. +--- + src/sysctl/sysctl.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/sysctl/sysctl.c b/src/sysctl/sysctl.c +index b5670db..878c923 100644 +--- a/src/sysctl/sysctl.c ++++ b/src/sysctl/sysctl.c +@@ -311,6 +311,10 @@ int main(int argc, char *argv[]) { + if (k < 0 && r == 0) + r = k; + } ++ ++ k = parse_file(sysctl_options, "/etc/sysctl.conf", true); ++ if (k < 0 && r == 0) ++ r = k; + } + + k = apply_all(sysctl_options); diff --git a/SOURCES/0095-tmpfiles-add-a-new-m-line-type-that-adjusts-user-gro.patch b/SOURCES/0095-tmpfiles-add-a-new-m-line-type-that-adjusts-user-gro.patch new file mode 100644 index 0000000..a65c0b5 --- /dev/null +++ b/SOURCES/0095-tmpfiles-add-a-new-m-line-type-that-adjusts-user-gro.patch @@ -0,0 +1,158 @@ +From cb869b77802b536aab1716714cdd5478d891d3f4 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 17 Sep 2013 16:33:30 -0500 +Subject: [PATCH] tmpfiles: add a new "m" line type that adjusts + user/group/mode of a file if it exists + +--- + man/systemd-tmpfiles.xml | 2 +- + man/tmpfiles.d.xml | 11 +++++++++++ + src/tmpfiles/tmpfiles.c | 39 +++++++++++++++++++++++++++++++-------- + 3 files changed, 43 insertions(+), 9 deletions(-) + +diff --git a/man/systemd-tmpfiles.xml b/man/systemd-tmpfiles.xml +index 281ab3c..ba727e1 100644 +--- a/man/systemd-tmpfiles.xml ++++ b/man/systemd-tmpfiles.xml +@@ -165,7 +165,7 @@ + See Also + + systemd1, +- tmpfiles.d5, ++ tmpfiles.d5 + + + +diff --git a/man/tmpfiles.d.xml b/man/tmpfiles.d.xml +index cdc87c9..98e3690 100644 +--- a/man/tmpfiles.d.xml ++++ b/man/tmpfiles.d.xml +@@ -152,6 +152,17 @@ L /tmp/foobar - - - - /dev/null + + + ++ m ++ If the ++ specified file path exists ++ adjust its access mode, group ++ and user to the specified ++ values and reset the SELinux ++ label. If it doesn't exist do ++ nothing. ++ ++ ++ + x + Ignore a path + during cleaning. Use this type +diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c +index ea99920..49e6529 100644 +--- a/src/tmpfiles/tmpfiles.c ++++ b/src/tmpfiles/tmpfiles.c +@@ -68,6 +68,7 @@ typedef enum ItemType { + CREATE_SYMLINK = 'L', + CREATE_CHAR_DEVICE = 'c', + CREATE_BLOCK_DEVICE = 'b', ++ ADJUST_MODE = 'm', + + /* These ones take globs */ + IGNORE_PATH = 'x', +@@ -256,8 +257,8 @@ static int dir_cleanup( + dev_t rootdev, + bool mountpoint, + int maxdepth, +- bool keep_this_level) +-{ ++ bool keep_this_level) { ++ + struct dirent *dent; + struct timespec times[2]; + bool deleted = false; +@@ -431,12 +432,16 @@ finish: + return r; + } + +-static int item_set_perms(Item *i, const char *path) { ++static int item_set_perms_full(Item *i, const char *path, bool ignore_enoent) { ++ int r; ++ + /* not using i->path directly because it may be a glob */ + if (i->mode_set) + if (chmod(path, i->mode) < 0) { +- log_error("chmod(%s) failed: %m", path); +- return -errno; ++ if (errno != ENOENT || !ignore_enoent) { ++ log_error("chmod(%s) failed: %m", path); ++ return -errno; ++ } + } + + if (i->uid_set || i->gid_set) +@@ -444,11 +449,18 @@ static int item_set_perms(Item *i, const char *path) { + i->uid_set ? i->uid : (uid_t) -1, + i->gid_set ? i->gid : (gid_t) -1) < 0) { + +- log_error("chown(%s) failed: %m", path); +- return -errno; ++ if (errno != ENOENT || !ignore_enoent) { ++ log_error("chown(%s) failed: %m", path); ++ return -errno; ++ } + } + +- return label_fix(path, false, false); ++ r = label_fix(path, false, false); ++ return r == -ENOENT && ignore_enoent ? 0 : r; ++} ++ ++static int item_set_perms(Item *i, const char *path) { ++ return item_set_perms_full(i, path, false); + } + + static int write_one_file(Item *i, const char *path) { +@@ -644,6 +656,7 @@ static int create_item(Item *i) { + if (r < 0) + return r; + break; ++ + case WRITE_FILE: + r = glob_item(i, write_one_file); + if (r < 0) +@@ -651,6 +664,13 @@ static int create_item(Item *i) { + + break; + ++ case ADJUST_MODE: ++ r = item_set_perms_full(i, i->path, true); ++ if (r < 0) ++ return r; ++ ++ break; ++ + case TRUNCATE_DIRECTORY: + case CREATE_DIRECTORY: + +@@ -821,6 +841,7 @@ static int remove_item_instance(Item *i, const char *instance) { + case RELABEL_PATH: + case RECURSIVE_RELABEL_PATH: + case WRITE_FILE: ++ case ADJUST_MODE: + break; + + case REMOVE_PATH: +@@ -866,6 +887,7 @@ static int remove_item(Item *i) { + case RELABEL_PATH: + case RECURSIVE_RELABEL_PATH: + case WRITE_FILE: ++ case ADJUST_MODE: + break; + + case REMOVE_PATH: +@@ -1093,6 +1115,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { + case RECURSIVE_REMOVE_PATH: + case RELABEL_PATH: + case RECURSIVE_RELABEL_PATH: ++ case ADJUST_MODE: + break; + + case CREATE_SYMLINK: diff --git a/SOURCES/85-display-manager.preset b/SOURCES/85-display-manager.preset new file mode 100644 index 0000000..c1d3069 --- /dev/null +++ b/SOURCES/85-display-manager.preset @@ -0,0 +1,10 @@ +# We enable all display managers by default. Since only one can +# actually be enabled at the same time the one which is installed +# first wins + +enable gdm.service +enable lightdm.service +enable slim.service +enable lxdm.service +enable kdm.service +enable xdm.service diff --git a/SOURCES/90-default.preset b/SOURCES/90-default.preset new file mode 100644 index 0000000..41ec976 --- /dev/null +++ b/SOURCES/90-default.preset @@ -0,0 +1,106 @@ +# Also see: +# https://fedoraproject.org/wiki/Starting_services_by_default + +# systemd +enable remote-fs.target +enable getty@tty1.service +enable systemd-readahead-replay.service +enable systemd-readahead-collect.service + +# System stuff +enable sshd.service +enable atd.* +enable crond.* +enable chronyd.service +enable rpcbind.* +enable NetworkManager.service +enable NetworkManager-dispatcher.service +enable ModemManager.service +enable auditd.service +enable restorecond.service +enable bluetooth.* +enable avahi-daemon.* +enable cups.* + +# The various syslog implementations +enable rsyslog.* +enable syslog-ng.* +enable sysklogd.* + +# Network facing +enable firewalld.service +enable libvirtd.service +enable xinetd.service +enable ladvd.service + +# Storage +enable multipathd.service +enable libstoragemgmt.service +enable lvm2-monitor.* +enable lvm2-lvmetad.* +enable dm-event.* +enable dmraid-activation.service + +# https://bugzilla.redhat.com/show_bug.cgi?id=855372 +enable mdmonitor.service +enable mdmonitor-takeover.service + +# https://bugzilla.redhat.com/show_bug.cgi?id=876237 +enable spice-vdagentd.service + +# https://bugzilla.redhat.com/show_bug.cgi?id=885406 +enable qemu-guest-agent.service + +# https://bugzilla.redhat.com/show_bug.cgi?id=928726 +enable dnf-makecache.timer + +# https://bugzilla.redhat.com/show_bug.cgi?id=929403 +enable initial-setup-graphical.service +enable initial-setup-text.service + +# https://bugzilla.redhat.com/show_bug.cgi?id=957135 +enable vmtoolsd.service + +#https://bugzilla.redhat.com/show_bug.cgi?id=995987 +enable kdump.service + +#https://bugzilla.redhat.com/show_bug.cgi?id=1009970 +enable tuned.service + +# Hardware +enable gpm.* +enable gpsd.* +enable irqbalance.service +enable lm_sensors.service +enable mcelog.* +enable acpid.* +enable smartd.service +enable pcscd.socket +enable rngd.service + +# Other stuff +enable abrtd.service +enable abrt-ccpp.service +enable abrt-oops.service +enable abrt-xorg.service +enable abrt-vmcore.service +enable lttng-sessiond.service +enable ksm.service +enable ksmtuned.service +enable rootfs-resize.service +enable sysstat.service +enable uuidd.service +enable xendomains.service +enable xenstored.service +enable xenconsoled.service +enable hypervkvpd.service +enable hypervvssd.service + +# Desktop stuff +enable accounts-daemon.service +enable rtkit-daemon.service +enable upower.service +enable udisks2.service +enable polkit.service +enable packagekit-offline-update.service +enable PackageKit.service diff --git a/SOURCES/99-default-disable.preset b/SOURCES/99-default-disable.preset new file mode 100644 index 0000000..1f29b50 --- /dev/null +++ b/SOURCES/99-default-disable.preset @@ -0,0 +1 @@ +disable * diff --git a/SOURCES/listen.conf b/SOURCES/listen.conf new file mode 100644 index 0000000..3d68da0 --- /dev/null +++ b/SOURCES/listen.conf @@ -0,0 +1 @@ +$SystemLogSocketName /run/systemd/journal/syslog diff --git a/SOURCES/rc.local b/SOURCES/rc.local new file mode 100644 index 0000000..87f017f --- /dev/null +++ b/SOURCES/rc.local @@ -0,0 +1,13 @@ +#!/bin/bash +# THIS FILE IS ADDED FOR COMPATIBILITY PURPOSES +# +# It is highly advisable to create own systemd services or udev rules +# to run scripts during boot instead of using this file. +# +# In constrast to previous versions due to parallel execution during boot +# this script will NOT be run after all other services. +# +# Please note that you must run 'chmod +x /etc/rc.d/rc.local' to ensure +# that this script will be executed during boot. + +exit 0 diff --git a/SOURCES/systemd-sysv-convert b/SOURCES/systemd-sysv-convert new file mode 100755 index 0000000..1c3f1a9 --- /dev/null +++ b/SOURCES/systemd-sysv-convert @@ -0,0 +1,148 @@ +#!/usr/bin/python +# -*- Mode: Python; python-indent: 8; indent-tabs-mode: t -*- + +import sys, os, argparse, errno + +def find_service(service, runlevel): + priority = -1 + + for l in os.listdir("/etc/rc%i.d" % runlevel): + if len(l) < 4: + continue + + if l[0] != 'S' or l[3:] != service: + continue + + p = int(l[1:3]) + + if p >= 0 and p <= 99 and p >= priority: + priority = p; + + return priority + +def lookup_database(services): + try: + database = open("/var/lib/systemd/sysv-convert/database", "r") + except IOError, e: + if e.errno != errno.ENOENT: + raise e + + return {} + + found = {} + k = 0 + + for line in database: + service, r, p = line.strip().split("\t", 3) + k += 1 + + try: + runlevel = int(r) + priority = int(p) + except ValueError, e: + sys.stderr.write("Failed to parse database line %i. Ignoring." % k) + continue + + if runlevel not in (2, 3, 4, 5): + sys.stderr.write("Runlevel out of bounds in database line %i. Ignoring." % k) + continue + + if priority < 0 or priority > 99: + sys.stderr.write("Priority out of bounds in database line %i. Ignoring." % k) + continue + + if service not in services: + continue + + if service not in found: + found[service] = {} + + if runlevel not in found[service] or found[service][runlevel] < priority: + found[service][runlevel] = priority + + return found + +def mkdir_p(path): + try: + os.makedirs(path, 0755) + except OSError, e: + if e.errno != errno.EEXIST: + raise e + +if os.geteuid() != 0: + sys.stderr.write("Need to be root.\n") + sys.exit(1) + +parser = argparse.ArgumentParser(description='Save and Restore SysV Service Runlevel Information') + +parser.add_argument('services', metavar='SERVICE', type=str, nargs='+', + help='Service names') + +parser.add_argument('--save', dest='save', action='store_const', + const=True, default=False, + help='Save SysV runlevel information for one or more services') + +parser.add_argument('--show', dest='show', action='store_const', + const=True, default=False, + help='Show saved SysV runlevel information for one or more services') + +parser.add_argument('--apply', dest='apply', action='store_const', + const=True, default=False, + help='Apply saved SysV runlevel information for one or more services to systemd counterparts') + +a = parser.parse_args() + +if a.save: + for service in a.services: + if not os.access("/etc/rc.d/init.d/%s" % service, os.F_OK): + sys.stderr.write("SysV service %s does not exist.\n" % service) + sys.exit(1) + + mkdir_p("/var/lib/systemd/sysv-convert") + database = open("/var/lib/systemd/sysv-convert/database", "a") + + for runlevel in (2, 3, 4, 5): + priority = find_service(service, runlevel) + + if priority >= 0: + database.write("%s\t%s\t%s\n" % (service, runlevel, priority)) + +elif a.show: + found = lookup_database(a.services) + + if len(found) <= 0: + sys.stderr.write("No information about passed services found.\n") + sys.exit(1) + + for service, data in found.iteritems(): + for runlevel, priority in data.iteritems(): + sys.stdout.write("SysV service %s enabled in runlevel %s at priority %s\n" % (service, runlevel, priority)) + +elif a.apply: + for service in a.services: + if not os.access("/lib/systemd/system/%s.service" % service, os.F_OK): + sys.stderr.write("systemd service %s.service does not exist.\n" % service) + sys.exit(1) + + found = lookup_database(a.services) + + if len(found) <= 0: + sys.stderr.write("No information about passed services found.\n") + sys.exit(1) + + for service, data in found.iteritems(): + for runlevel in data.iterkeys(): + + sys.stderr.write("ln -sf /lib/systemd/system/%s.service /etc/systemd/system/runlevel%i.target.wants/%s.service\n" % (service, runlevel, service)) + + mkdir_p("/etc/systemd/system/runlevel%i.target.wants" % runlevel) + + try: + os.symlink("/lib/systemd/system/%s.service" % service, + "/etc/systemd/system/runlevel%i.target.wants/%s.service" % (runlevel, service)) + except OSError, e: + if e.errno != errno.EEXIST: + raise e + +else: + parser.print_help() diff --git a/SOURCES/yum-protect-systemd.conf b/SOURCES/yum-protect-systemd.conf new file mode 100644 index 0000000..24ad079 --- /dev/null +++ b/SOURCES/yum-protect-systemd.conf @@ -0,0 +1 @@ +systemd diff --git a/SPECS/systemd.spec b/SPECS/systemd.spec new file mode 100644 index 0000000..b0f4033 --- /dev/null +++ b/SPECS/systemd.spec @@ -0,0 +1,1748 @@ +# PIE is broken on s390 (#868839, #872148) +%ifnarch s390 s390x +%global _hardened_build 1 +%endif + +# We ship a .pc file but don't want to have a dep on pkg-config. We +# strip the automatically generated dep here and instead co-own the +# directory. +%global __requires_exclude pkg-config + +Name: systemd +Url: http://www.freedesktop.org/wiki/Software/systemd +Version: 207 +Release: 8%{?dist} +# For a breakdown of the licensing, see README +License: LGPLv2+ and MIT and GPLv2+ +Summary: A System and Service Manager + +Source0: http://www.freedesktop.org/software/systemd/%{name}-%{version}.tar.xz + +# Fedora's default preset policy +Source1: 90-default.preset +Source7: 99-default-disable.preset +Source5: 85-display-manager.preset +# Feodora's SysV convert script. meh. +Source2: systemd-sysv-convert +# Stop-gap, just to ensure things work fine with rsyslog without having to change the package right-away +Source4: listen.conf +# Prevent accidental removal of the systemd package +Source6: yum-protect-systemd.conf +# ship /etc/rc.d/rc.local https://bugzilla.redhat.com/show_bug.cgi?id=968401 +Source8: rc.local + + +# RHEL-specific: +Patch0001: 0001-RHEL-units-add-Install-section-to-tmp.mount.patch +Patch0002: 0002-kernel-install-add-fedora-specific-callouts-to-new-k.patch +Patch0003: 0003-core-cgroup-first-print-then-free.patch +Patch0004: 0004-swap-fix-reverse-dependencies.patch +Patch0005: 0005-update-TODO.patch +Patch0006: 0006-cryptsetup-generator-don-t-create-tmp-swap-units.patch +Patch0007: 0007-cryptsetup-generator-allow-specifying-options-in-pro.patch +Patch0008: 0008-automount-rename-repeat_unmont-to-repeat_unmount.patch +Patch0009: 0009-cgroup-add-the-missing-setting-of-variable-s-value.patch +Patch0010: 0010-cgroup-correct-the-log-information.patch +Patch0011: 0011-cgroup-fix-incorrectly-setting-memory-cgroup.patch +Patch0012: 0012-random-seed-we-should-return-errno-of-failed-loop_wr.patch +Patch0013: 0013-update-TODO.patch +Patch0014: 0014-libudev-fix-move_later-comparison.patch +Patch0015: 0015-man-document-luks.options-kernel-commandline.patch +Patch0016: 0016-keymap-remove-some-commented-out-lines.patch +Patch0017: 0017-Advertise-hibernation-only-if-there-s-enough-free-sw.patch +Patch0018: 0018-README-add-SCSI-BSG-option.patch +Patch0019: 0019-swap-create-.wants-symlink-to-auto-swap-devices.patch +Patch0020: 0020-cgroup-add-missing-equals-for-BlockIOWeight.patch +Patch0021: 0021-Assume-that-proc-meminfo-can-be-missing.patch +Patch0022: 0022-transaction.c-do-not-point-users-to-logs-when-unit-n.patch +Patch0023: 0023-Verify-validity-of-session-name-when-received-from-o.patch +Patch0024: 0024-udev-rules-avoid-erroring-on-trailing-whitespace.patch +Patch0025: 0025-keymap-Add-Samsung-Series-5-Ultra.patch +Patch0026: 0026-login-fix-login_is_valid-test.patch +Patch0027: 0027-polkit-Avoid-race-condition-in-scraping-proc.patch +Patch0028: 0028-core-whenever-a-new-PID-is-passed-to-us-make-sure-we.patch +Patch0029: 0029-remove-user-.service.patch +Patch0030: 0030-cgroup-always-enable-memory.use_hierarchy-for-all-cg.patch +Patch0031: 0031-logind-return-EINVAL-when-PID-is-wrong.patch +Patch0032: 0032-core-drop-some-out-of-date-references-to-cgroup-sett.patch +Patch0033: 0033-man-explain-NAME-in-systemctl-man-page.patch +Patch0034: 0034-journald-accept-EPOLLERR-from-dev-kmsg.patch +Patch0035: 0035-journald-avoid-NSS-in-journald.patch +Patch0036: 0036-libudev-add-missing-global-to-symbol-export.patch +Patch0037: 0037-gpt-auto-generator-do-not-assume-that-dev-block-u-u-.patch +Patch0038: 0038-logind-put-correct-user-object-paths-in-introspectio.patch +Patch0039: 0039-Fix-obsolete-references-to-systemd-random-seed-load..patch +Patch0040: 0040-cgroup-always-enable-memory.use_hierarchy-for-all-cg.patch +Patch0041: 0041-journalctl-1-s-adm-systemd-journal.patch +Patch0042: 0042-cgroup-if-we-do-a-cgroup-operation-then-do-something.patch +Patch0043: 0043-core-rework-how-we-match-mount-units-against-each-ot.patch +Patch0044: 0044-logind-never-consider-a-closing-session-relevant-for.patch +Patch0045: 0045-man-drop-references-to-cgroup-wher-appropriate.patch +Patch0046: 0046-systemctl-make-sure-set-property-mangles-unit-names.patch +Patch0047: 0047-dbus-fix-introspection-for-TimerSlackNSec.patch +Patch0048: 0048-swap-properly-expose-timeout-property-on-the-bus.patch +Patch0049: 0049-build-sys-restore-detection-of-sphinx.patch +Patch0050: 0050-util-add-macro-for-iterating-through-all-prefixes-of.patch +Patch0051: 0051-util-properly-handle-the-root-dir-in-PATH_FOREACH_PR.patch +Patch0052: 0052-cgroup-get-rid-of-MemorySoftLimit.patch +Patch0053: 0053-set-IgnoreOnIsolate-true-for-systemd-cryptsetup-.ser.patch +Patch0054: 0054-main-don-t-free-fds-array-twice.patch +Patch0055: 0055-local-fix-memory-leak-when-putting-together-locale-s.patch +Patch0056: 0056-hashmap-size-hashmap-bucket-array-dynamically.patch +Patch0057: 0057-smack-setup-fix-path-to-Smack-CIPSO-mappings.patch +Patch0058: 0058-fix-lingering-references-to-var-lib-backlight-random.patch +Patch0059: 0059-cryptsetup-fix-OOM-handling-when-parsing-mount-optio.patch +Patch0060: 0060-journald-add-missing-error-check.patch +Patch0061: 0061-bus-fix-potentially-uninitialized-memory-access.patch +Patch0062: 0062-dbus-fix-return-value-of-dispatch_rqueue.patch +Patch0063: 0063-modules-load-fix-error-handling.patch +Patch0064: 0064-efi-never-call-qsort-on-potentially-NULL-arrays.patch +Patch0065: 0065-strv-don-t-access-potentially-NULL-string-arrays.patch +Patch0066: 0066-mkdir-pass-a-proper-function-pointer-to-mkdir_safe_i.patch +Patch0067: 0067-tmpfiles.d-include-setgid-perms-for-run-log-journal.patch +Patch0068: 0068-gpt-auto-generator-exit-immediately-if-in-container.patch +Patch0069: 0069-systemd-order-remote-mounts-from-mountinfo-before-re.patch +Patch0070: 0070-manager-when-verifying-whether-clients-may-change-en.patch +Patch0071: 0071-mount-check-for-NULL-before-reading-pm-what.patch +Patch0072: 0072-core-do-not-add-what-to-RequiresMountsFor-for-networ.patch +Patch0073: 0073-systemd-serialize-deserialize-forbid_restart-value.patch +Patch0074: 0074-core-unify-the-way-we-denote-serialization-attribute.patch +Patch0075: 0075-journald-fix-minor-memory-leak.patch +Patch0076: 0076-journald-remove-rotated-file-from-hashmap-when-rotat.patch +Patch0077: 0077-udevadm.xml-document-resolve-names-option-for-test.patch +Patch0078: 0078-dbus-common-avoid-leak-in-error-path.patch +Patch0079: 0079-drop-ins-check-return-value.patch +Patch0080: 0080-shared-util-Fix-glob_extend-argument.patch +Patch0081: 0081-Fix-for-SIGSEGV-in-systemd-bootchart-on-short-living.patch +Patch0082: 0082-man-document-the-b-special-boot-option.patch +Patch0083: 0083-tmpfiles-log-unaccessible-FUSE-mount-points-only-as-.patch +Patch0084: 0084-move-utf8-functions-from-libudev-private.h-to-utf8.h.patch +Patch0085: 0085-Use-udev_encode_string-in-fstab_node_to_udev_node.patch +Patch0086: 0086-Fix-buffer-overrun-when-enumerating-files.patch +Patch0087: 0087-shared-utf8-merge-implementations-remove-cruft.patch +Patch0088: 0088-device-nodes-move-device-node-specific-code-to-own-f.patch +Patch0089: 0089-shared-util-fix-off-by-one-error-in-tag_to_udev_node.patch +Patch0090: 0090-udev-path_id-fix-by-path-link-generation-for-scm-dev.patch +Patch0091: 0091-hashmap-randomize-hash-functions-a-bit.patch +Patch0092: 0092-Configurable-Timeouts-Restarts-default-values.patch +Patch0093: 0093-manager-configurable-StartLimit-default-values.patch +Patch0094: 0094-sysctl-bring-back-etc-sysctl.conf.patch +Patch0095: 0095-tmpfiles-add-a-new-m-line-type-that-adjusts-user-gro.patch + +%global num_patches %{lua: c=0; for i,p in ipairs(patches) do c=c+1; end; print(c);} + +BuildRequires: libcap-devel +BuildRequires: tcp_wrappers-devel +BuildRequires: pam-devel +BuildRequires: libselinux-devel +BuildRequires: audit-libs-devel +BuildRequires: cryptsetup-devel +BuildRequires: dbus-devel +BuildRequires: libacl-devel +BuildRequires: pciutils-devel +BuildRequires: glib2-devel +BuildRequires: gobject-introspection-devel +BuildRequires: libblkid-devel +BuildRequires: xz-devel +BuildRequires: kmod-devel +BuildRequires: libgcrypt-devel +BuildRequires: qrencode-devel +BuildRequires: libmicrohttpd-devel +BuildRequires: libxslt +BuildRequires: docbook-style-xsl +BuildRequires: pkgconfig +BuildRequires: intltool +BuildRequires: gperf +BuildRequires: gtk-doc +BuildRequires: python2-devel +%if %{num_patches} +BuildRequires: automake +BuildRequires: autoconf +BuildRequires: libtool +BuildRequires: git +%endif +Requires(post): coreutils +Requires(post): gawk +Requires(post): sed +Requires(post): acl +Requires(pre): coreutils +Requires(pre): /usr/bin/getent +Requires(pre): /usr/sbin/groupadd +Requires: dbus +Requires: nss-myhostname +Requires: %{name}-libs = %{version}-%{release} +Requires: kmod >= 14 + +Provides: /bin/systemctl +Provides: /sbin/shutdown +Provides: syslog +Provides: systemd-units = %{version}-%{release} +# part of system since f18, drop at f20 +Provides: udev = %{version} +Obsoletes: udev < 183 +Conflicts: dracut < 027 +# f18 version, drop at f20 +Conflicts: plymouth < 0.8.5.1 +# For the journal-gateway split in F20, drop at F22 +Obsoletes: systemd < 204-10 +# Ensures correct multilib updates added F18, drop at F20 +Conflicts: systemd < 185-4 +# added F18, drop at F20 +Obsoletes: system-setup-keyboard < 0.9 +Provides: system-setup-keyboard = 0.9 +# nss-myhostname got integrated in F19, drop at F21 +Obsoletes: nss-myhostname < 0.4 +Provides: nss-myhostname = 0.4 +# systemd-analyze got merged in F19, drop at F21 +Obsoletes: systemd-analyze < 198 +Provides: systemd-analyze = 198 +Obsoletes: upstart < 1.2-3 +Obsoletes: upstart-sysvinit < 1.2-3 +Conflicts: upstart-sysvinit +Obsoletes: hal + +%description +systemd is a system and service manager for Linux, compatible with +SysV and LSB init scripts. systemd provides aggressive parallelization +capabilities, uses socket and D-Bus activation for starting services, +offers on-demand starting of daemons, keeps track of processes using +Linux cgroups, supports snapshotting and restoring of the system +state, maintains mount and automount points and implements an +elaborate transactional dependency-based service control logic. It can +work as a drop-in replacement for sysvinit. + +%package libs +Summary: systemd libraries +License: LGPLv2+ and MIT +Obsoletes: libudev < 183 +Obsoletes: systemd < 185-4 +Conflicts: systemd < 185-4 + +%description libs +Libraries for systemd and udev, as well as the systemd PAM module. + +%package devel +Summary: Development headers for systemd +License: LGPLv2+ and MIT +Requires: %{name} = %{version}-%{release} +Provides: libudev-devel = %{version} +Obsoletes: libudev-devel < 183 + +%description devel +Development headers and auxiliary files for developing applications for systemd. + +%package sysv +Summary: SysV tools for systemd +License: LGPLv2+ +Requires: %{name} = %{version}-%{release} + +%description sysv +SysV compatibility tools for systemd + +%package python +Summary: Python Bindings for systemd +License: LGPLv2+ +Requires: %{name} = %{version}-%{release} + +%description python +This package contains python binds for systemd APIs + +%package -n libgudev1 +Summary: Libraries for adding libudev support to applications that use glib +Conflicts: filesystem < 3 +License: LGPLv2+ +Requires: %{name} = %{version}-%{release} + +%description -n libgudev1 +This package contains the libraries that make it easier to use libudev +functionality from applications that use glib. + +%package -n libgudev1-devel +Summary: Header files for adding libudev support to applications that use glib +Requires: libgudev1 = %{version}-%{release} +License: LGPLv2+ + +%description -n libgudev1-devel +This package contains the header and pkg-config files for developing +glib-based applications using libudev functionality. + +%package journal-gateway +Summary: Gateway for serving journal events over the network using HTTP +Requires: %{name} = %{version}-%{release} +License: LGPLv2+ +Requires(pre): /usr/bin/getent +Requires(post): systemd +Requires(preun): systemd +Requires(postun): systemd +# For the journal-gateway split in F20, drop at F22 +Obsoletes: systemd < 204-10 + +%description journal-gateway +systemd-journal-gatewayd serves journal events over the network using HTTP. + +%prep +%setup -q + +%if %{num_patches} + git init + git config user.email "systemd-maint@redhat.com" + git config user.name "Fedora systemd team" + git add . + git commit -a -q -m "%{version} baseline." + + # Apply all the patches. + git am \ + --exclude .gitignore \ + --exclude docs/.gitignore \ + --exclude docs/gudev/.gitignore \ + --exclude docs/libudev/.gitignore \ + --exclude docs/sysvinit/.gitignore \ + --exclude docs/var-log/.gitignore \ + --exclude hwdb/.gitignore \ + --exclude m4/.gitignore \ + --exclude man/.gitignore \ + --exclude po/.gitignore \ + --exclude rules/.gitignore \ + --exclude src/.gitignore \ + --exclude src/analyze/.gitignore \ + --exclude src/core/.gitignore \ + --exclude src/gudev/.gitignore \ + --exclude src/hostname/.gitignore \ + --exclude src/journal/.gitignore \ + --exclude src/libsystemd-daemon/.gitignore \ + --exclude src/libsystemd-id128/.gitignore \ + --exclude src/libudev/.gitignore \ + --exclude src/locale/.gitignore \ + --exclude src/login/.gitignore \ + --exclude src/python-systemd/.gitignore \ + --exclude src/python-systemd/docs/.gitignore \ + --exclude src/timedate/.gitignore \ + --exclude src/udev/.gitignore \ + --exclude src/udev/scsi_id/.gitignore \ + --exclude sysctl.d/.gitignore \ + --exclude test/.gitignore \ + --exclude units/.gitignore \ + --exclude units/user/.gitignore \ + %{patches} +%endif + +%build +%if %{num_patches} + autoreconf +%endif + +%configure \ + --libexecdir=%{_prefix}/lib \ + --enable-gtk-doc \ + --disable-static \ + --with-sysvinit-path=/etc/rc.d/init.d \ + --with-rc-local-script-path-start=/etc/rc.d/rc.local +make %{?_smp_mflags} V=1 + +%install +%make_install +find %{buildroot} \( -name '*.a' -o -name '*.la' \) -delete + +# udev links +mkdir -p %{buildroot}/%{_sbindir} +ln -sf ../bin/udevadm %{buildroot}%{_sbindir}/udevadm + +# Create SysV compatibility symlinks. systemctl/systemd are smart +# enough to detect in which way they are called. +ln -s ../lib/systemd/systemd %{buildroot}%{_sbindir}/init +ln -s ../bin/systemctl %{buildroot}%{_sbindir}/reboot +ln -s ../bin/systemctl %{buildroot}%{_sbindir}/halt +ln -s ../bin/systemctl %{buildroot}%{_sbindir}/poweroff +ln -s ../bin/systemctl %{buildroot}%{_sbindir}/shutdown +ln -s ../bin/systemctl %{buildroot}%{_sbindir}/telinit +ln -s ../bin/systemctl %{buildroot}%{_sbindir}/runlevel + +# legacy links +ln -s loginctl %{buildroot}%{_bindir}/systemd-loginctl + +# We create all wants links manually at installation time to make sure +# they are not owned and hence overriden by rpm after the used deleted +# them. +rm -r %{buildroot}%{_sysconfdir}/systemd/system/*.target.wants + +# Make sure the ghost-ing below works +touch %{buildroot}%{_sysconfdir}/systemd/system/runlevel2.target +touch %{buildroot}%{_sysconfdir}/systemd/system/runlevel3.target +touch %{buildroot}%{_sysconfdir}/systemd/system/runlevel4.target +touch %{buildroot}%{_sysconfdir}/systemd/system/runlevel5.target + +# Make sure these directories are properly owned +mkdir -p %{buildroot}%{_prefix}/lib/systemd/system/basic.target.wants +mkdir -p %{buildroot}%{_prefix}/lib/systemd/system/default.target.wants +mkdir -p %{buildroot}%{_prefix}/lib/systemd/system/dbus.target.wants +mkdir -p %{buildroot}%{_prefix}/lib/systemd/system/syslog.target.wants + +# Make sure the user generators dir exists too +mkdir -p %{buildroot}%{_prefix}/lib/systemd/system-generators +mkdir -p %{buildroot}%{_prefix}/lib/systemd/user-generators + +# Create new-style configuration files so that we can ghost-own them +touch %{buildroot}%{_sysconfdir}/hostname +touch %{buildroot}%{_sysconfdir}/vconsole.conf +touch %{buildroot}%{_sysconfdir}/locale.conf +touch %{buildroot}%{_sysconfdir}/machine-id +touch %{buildroot}%{_sysconfdir}/machine-info +touch %{buildroot}%{_sysconfdir}/localtime +mkdir -p %{buildroot}%{_sysconfdir}/X11/xorg.conf.d +touch %{buildroot}%{_sysconfdir}/X11/xorg.conf.d/00-keyboard.conf + +# Install Fedora default preset policy +mkdir -p %{buildroot}%{_prefix}/lib/systemd/system-preset/ +mkdir -p %{buildroot}%{_prefix}/lib/systemd/user-preset/ +install -m 0644 %{SOURCE1} %{buildroot}%{_prefix}/lib/systemd/system-preset/ +install -m 0644 %{SOURCE5} %{buildroot}%{_prefix}/lib/systemd/system-preset/ +install -m 0644 %{SOURCE7} %{buildroot}%{_prefix}/lib/systemd/system-preset/ + +# Make sure the shutdown/sleep drop-in dirs exist +mkdir -p %{buildroot}%{_prefix}/lib/systemd/system-shutdown/ +mkdir -p %{buildroot}%{_prefix}/lib/systemd/system-sleep/ + +# Make sure the NTP units dir exists +mkdir -p %{buildroot}%{_prefix}/lib/systemd/ntp-units.d/ + +# Make sure directories in /var exist +mkdir -p %{buildroot}%{_localstatedir}/lib/systemd/coredump +mkdir -p %{buildroot}%{_localstatedir}/lib/systemd/catalog +touch %{buildroot}%{_localstatedir}/lib/systemd/catalog/database +touch %{buildroot}%{_sysconfdir}/udev/hwdb.bin + +# Install SysV conversion tool for systemd +install -m 0755 %{SOURCE2} %{buildroot}%{_bindir}/ + +# Install rsyslog fragment +mkdir -p %{buildroot}%{_sysconfdir}/rsyslog.d/ +install -m 0644 %{SOURCE4} %{buildroot}%{_sysconfdir}/rsyslog.d/ + +# Install yum protection fragment +mkdir -p %{buildroot}%{_sysconfdir}/yum/protected.d/ +install -m 0644 %{SOURCE6} %{buildroot}%{_sysconfdir}/yum/protected.d/systemd.conf + +# Install rc.local +mkdir -p %{buildroot}%{_sysconfdir}/rc.d/ +install -m 0644 %{SOURCE8} %{buildroot}%{_sysconfdir}/rc.d/rc.local +ln -s rc.d/rc.local %{buildroot}%{_sysconfdir}/rc.local + +# To avoid making life hard for Rawhide-using developers, don't package the +# kernel.core_pattern setting until systemd-coredump is a part of an actual +# systemd release and it's made clear how to get the core dumps out of the +# journal. +rm -f %{buildroot}%{_prefix}/lib/sysctl.d/50-coredump.conf + +# For now remove /var/log/README since we are not enabling persistant +# logging yet. +rm -f %{buildroot}%{_localstatedir}/log/README + +# No tmp-on-tmpfs by default in RHEL7. bz#876122 +rm -f %{buildroot}%{_prefix}/lib/systemd/system/local-fs.target.wants/tmp.mount + +# No gpt-auto-generator in RHEL7 +rm -f %{buildroot}%{_prefix}/lib/systemd/system-generators/systemd-gpt-auto-generator + +%pre +getent group cdrom >/dev/null 2>&1 || groupadd -r -g 11 cdrom >/dev/null 2>&1 || : +getent group tape >/dev/null 2>&1 || groupadd -r -g 33 tape >/dev/null 2>&1 || : +getent group dialout >/dev/null 2>&1 || groupadd -r -g 18 dialout >/dev/null 2>&1 || : +getent group floppy >/dev/null 2>&1 || groupadd -r -g 19 floppy >/dev/null 2>&1 || : +getent group systemd-journal >/dev/null 2>&1 || groupadd -r -g 190 systemd-journal 2>&1 || : + +systemctl stop systemd-udevd-control.socket systemd-udevd-kernel.socket systemd-udevd.service >/dev/null 2>&1 || : + +# Rename configuration files that changed their names +mv -n %{_sysconfdir}/systemd/systemd-logind.conf %{_sysconfdir}/systemd/logind.conf >/dev/null 2>&1 || : +mv -n %{_sysconfdir}/systemd/systemd-journald.conf %{_sysconfdir}/systemd/journald.conf >/dev/null 2>&1 || : + +%pretrans -p +--# Migrate away from systemd-timedated-ntp.target. +--# Take note which ntp services, if any, were pulled in by it. +--# We'll enable them the usual way in %%post. +--# Remove this after upgrades from F17 are no longer supported. +function migrate_ntp() + --# Are we upgrading from a version that had systemd-timedated-ntp.target? + t = posix.stat("/usr/lib/systemd/system/systemd-timedated-ntp.target", "type") + if t ~= "regular" then return end + + --# Was the target enabled? + t = posix.stat("/etc/systemd/system/multi-user.target.wants/systemd-timedated-ntp.target", "type") + if t ~= "link" then return end + + --# filesystem provides /var/lib/rpm-state since F17 GA + r,msg,errno = posix.mkdir("/var/lib/rpm-state/systemd") + if r == nil and errno ~= 17 then return end --# EEXIST is fine. + + --# Save the list of ntp services pulled by the target. + f = io.open("/var/lib/rpm-state/systemd/ntp-units", "w") + if f == nil then return end + + files = posix.dir("/usr/lib/systemd/system/systemd-timedated-ntp.target.wants") + for i,name in ipairs(files) do + if name ~= "." and name ~= ".." then + s = string.format("%s\n", name) + f:write(s) + end + end + + f:close() +end + +migrate_ntp() +return 0 + +%post +systemd-machine-id-setup >/dev/null 2>&1 || : +/usr/lib/systemd/systemd-random-seed save >/dev/null 2>&1 || : +systemctl daemon-reexec >/dev/null 2>&1 || : +systemctl start systemd-udevd.service >/dev/null 2>&1 || : +udevadm hwdb --update >/dev/null 2>&1 || : +journalctl --update-catalog >/dev/null 2>&1 || : + +# Stop-gap until rsyslog.rpm does this on its own. (This is supposed +# to fail when the link already exists) +ln -s /usr/lib/systemd/system/rsyslog.service /etc/systemd/system/syslog.service >/dev/null 2>&1 || : + +if [ $1 -eq 1 ] ; then + # Try to read default runlevel from the old inittab if it exists + runlevel=$(awk -F ':' '$3 == "initdefault" && $1 !~ "^#" { print $2 }' /etc/inittab 2> /dev/null) + if [ -z "$runlevel" ] ; then + target="/usr/lib/systemd/system/graphical.target" + else + target="/usr/lib/systemd/system/runlevel$runlevel.target" + fi + + # And symlink what we found to the new-style default.target + ln -sf "$target" /etc/systemd/system/default.target >/dev/null 2>&1 || : + + # Services we install by default, and which are controlled by presets. + systemctl preset \ + getty@tty1.service \ + remote-fs.target \ + systemd-readahead-replay.service \ + systemd-readahead-collect.service >/dev/null 2>&1 || : +else + # This systemd service does not exist anymore, we now do it + # internally in PID 1 + rm -f /etc/systemd/system/sysinit.target.wants/hwclock-load.service >/dev/null 2>&1 || : + + # This systemd target does not exist anymore. It's been replaced + # by ntp-units.d. + rm -f /etc/systemd/system/multi-user.target.wants/systemd-timedated-ntp.target >/dev/null 2>&1 || : + + # Enable the units recorded by %%pretrans + if [ -e /var/lib/rpm-state/systemd/ntp-units ] ; then + while read service; do + systemctl enable "$service" >/dev/null 2>&1 || : + done < /var/lib/rpm-state/systemd/ntp-units + rm -r /var/lib/rpm-state/systemd/ntp-units >/dev/null 2>&1 || : + fi +fi + +# Migrate /etc/sysconfig/clock +if [ ! -L /etc/localtime -a -e /etc/sysconfig/clock ] ; then + . /etc/sysconfig/clock >/dev/null 2>&1 || : + if [ -n "$ZONE" -a -e "/usr/share/zoneinfo/$ZONE" ] ; then + ln -sf "../usr/share/zoneinfo/$ZONE" /etc/localtime >/dev/null 2>&1 || : + fi +fi +rm -f /etc/sysconfig/clock >/dev/null 2>&1 || : + +# Migrate /etc/sysconfig/i18n +if [ -e /etc/sysconfig/i18n -a ! -e /etc/locale.conf ]; then + unset LANG + unset LC_CTYPE + unset LC_NUMERIC + unset LC_TIME + unset LC_COLLATE + unset LC_MONETARY + unset LC_MESSAGES + unset LC_PAPER + unset LC_NAME + unset LC_ADDRESS + unset LC_TELEPHONE + unset LC_MEASUREMENT + unset LC_IDENTIFICATION + . /etc/sysconfig/i18n >/dev/null 2>&1 || : + [ -n "$LANG" ] && echo LANG=$LANG > /etc/locale.conf 2>&1 || : + [ -n "$LC_CTYPE" ] && echo LC_CTYPE=$LC_CTYPE >> /etc/locale.conf 2>&1 || : + [ -n "$LC_NUMERIC" ] && echo LC_NUMERIC=$LC_NUMERIC >> /etc/locale.conf 2>&1 || : + [ -n "$LC_TIME" ] && echo LC_TIME=$LC_TIME >> /etc/locale.conf 2>&1 || : + [ -n "$LC_COLLATE" ] && echo LC_COLLATE=$LC_COLLATE >> /etc/locale.conf 2>&1 || : + [ -n "$LC_MONETARY" ] && echo LC_MONETARY=$LC_MONETARY >> /etc/locale.conf 2>&1 || : + [ -n "$LC_MESSAGES" ] && echo LC_MESSAGES=$LC_MESSAGES >> /etc/locale.conf 2>&1 || : + [ -n "$LC_PAPER" ] && echo LC_PAPER=$LC_PAPER >> /etc/locale.conf 2>&1 || : + [ -n "$LC_NAME" ] && echo LC_NAME=$LC_NAME >> /etc/locale.conf 2>&1 || : + [ -n "$LC_ADDRESS" ] && echo LC_ADDRESS=$LC_ADDRESS >> /etc/locale.conf 2>&1 || : + [ -n "$LC_TELEPHONE" ] && echo LC_TELEPHONE=$LC_TELEPHONE >> /etc/locale.conf 2>&1 || : + [ -n "$LC_MEASUREMENT" ] && echo LC_MEASUREMENT=$LC_MEASUREMENT >> /etc/locale.conf 2>&1 || : + [ -n "$LC_IDENTIFICATION" ] && echo LC_IDENTIFICATION=$LC_IDENTIFICATION >> /etc/locale.conf 2>&1 || : +fi + +# Migrate /etc/sysconfig/keyboard +if [ -e /etc/sysconfig/keyboard -a ! -e /etc/vconsole.conf ]; then + unset SYSFONT + unset SYSFONTACM + unset UNIMAP + unset KEYMAP + [ -e /etc/sysconfig/i18n ] && . /etc/sysconfig/i18n >/dev/null 2>&1 || : + . /etc/sysconfig/keyboard >/dev/null 2>&1 || : + [ -n "$SYSFONT" ] && echo FONT=$SYSFONT > /etc/vconsole.conf 2>&1 || : + [ -n "$SYSFONTACM" ] && echo FONT_MAP=$SYSFONTACM >> /etc/vconsole.conf 2>&1 || : + [ -n "$UNIMAP" ] && echo FONT_UNIMAP=$UNIMAP >> /etc/vconsole.conf 2>&1 || : + [ -n "$KEYTABLE" ] && echo KEYMAP=$KEYTABLE >> /etc/vconsole.conf 2>&1 || : +fi +rm -f /etc/sysconfig/i18n >/dev/null 2>&1 || : +rm -f /etc/sysconfig/keyboard >/dev/null 2>&1 || : + +# Migrate HOSTNAME= from /etc/sysconfig/network +if [ -e /etc/sysconfig/network -a ! -e /etc/hostname ]; then + unset HOSTNAME + . /etc/sysconfig/network >/dev/null 2>&1 || : + [ -n "$HOSTNAME" ] && echo $HOSTNAME > /etc/hostname 2>&1 || : +fi +sed -i '/^HOSTNAME=/d' /etc/sysconfig/network >/dev/null 2>&1 || : + +# Migrate the old systemd-setup-keyboard X11 configuration fragment +if [ ! -e /etc/X11/xorg.conf.d/00-keyboard.conf ] ; then + mv /etc/X11/xorg.conf.d/00-system-setup-keyboard.conf /etc/X11/xorg.conf.d/00-keyboard.conf >/dev/null 2>&1 || : +else + rm -f /etc/X11/xorg.conf.d/00-system-setup-keyboard.conf >/dev/null 2>&1 || : +fi + +# sed-fu to add myhostname to the hosts line of /etc/nsswitch.conf +if [ -f /etc/nsswitch.conf ] ; then + sed -i.bak -e ' + /^hosts:/ !b + /\/ b + s/[[:blank:]]*$/ myhostname/ + ' /etc/nsswitch.conf >/dev/null 2>&1 || : +fi + +%posttrans +# Convert old /etc/sysconfig/desktop settings +preferred= +if [ -f /etc/sysconfig/desktop ]; then + . /etc/sysconfig/desktop + if [ "$DISPLAYMANAGER" = GNOME ]; then + preferred=gdm + elif [ "$DISPLAYMANAGER" = KDE ]; then + preferred=kdm + elif [ "$DISPLAYMANAGER" = WDM ]; then + preferred=wdm + elif [ "$DISPLAYMANAGER" = XDM ]; then + preferred=xdm + elif [ -n "$DISPLAYMANAGER" ]; then + preferred=${DISPLAYMANAGER##*/} + fi +fi +if [ -z "$preferred" ]; then + if [ -x /usr/sbin/gdm ]; then + preferred=gdm + elif [ -x /usr/bin/kdm ]; then + preferred=kdm + fi +fi +if [ -n "$preferred" -a -r "/usr/lib/systemd/system/$preferred.service" ]; then + # This is supposed to fail when the symlink already exists + ln -s "/usr/lib/systemd/system/$preferred.service" /etc/systemd/system/display-manager.service >/dev/null 2>&1 || : +fi + +%postun +if [ $1 -ge 1 ] ; then + systemctl daemon-reload > /dev/null 2>&1 || : + systemctl try-restart systemd-logind.service >/dev/null 2>&1 || : +fi + +%preun +if [ $1 -eq 0 ] ; then + systemctl disable \ + getty@.service \ + remote-fs.target \ + systemd-readahead-replay.service \ + systemd-readahead-collect.service >/dev/null 2>&1 || : + + rm -f /etc/systemd/system/default.target >/dev/null 2>&1 || : + + if [ -f /etc/nsswitch.conf ] ; then + sed -i.bak -e ' + /^hosts:/ !b + s/[[:blank:]]\+myhostname\>// + ' /etc/nsswitch.conf >/dev/null 2>&1 || : + fi +fi + +%post libs -p /sbin/ldconfig +%postun libs -p /sbin/ldconfig + +%post -n libgudev1 -p /sbin/ldconfig +%postun -n libgudev1 -p /sbin/ldconfig + +%pre journal-gateway +getent group systemd-journal-gateway >/dev/null 2>&1 || groupadd -r -g 191 systemd-journal-gateway 2>&1 || : +getent passwd systemd-journal-gateway >/dev/null 2>&1 || useradd -r -l -u 191 -g systemd-journal-gateway -d %{_prefix}/lib/systemd -s /sbin/nologin -c "Journal Gateway" systemd-journal-gateway >/dev/null 2>&1 || : + +%post journal-gateway +%systemd_post systemd-journal-gatewayd.socket systemd-journal-gatewayd.service + +%preun journal-gateway +%systemd_preun systemd-journal-gatewayd.socket systemd-journal-gatewayd.service + +%postun journal-gateway +%systemd_postun_with_restart systemd-journal-gatewayd.service + +%files +%doc %{_docdir}/systemd +%dir %{_sysconfdir}/systemd +%dir %{_sysconfdir}/systemd/system +%dir %{_sysconfdir}/systemd/user +%dir %{_sysconfdir}/tmpfiles.d +%dir %{_sysconfdir}/sysctl.d +%dir %{_sysconfdir}/modules-load.d +%dir %{_sysconfdir}/binfmt.d +%dir %{_sysconfdir}/udev +%dir %{_sysconfdir}/udev/rules.d +%dir %{_prefix}/lib/systemd +%dir %{_prefix}/lib/systemd/system-generators +%dir %{_prefix}/lib/systemd/user-generators +%dir %{_prefix}/lib/systemd/system-preset +%dir %{_prefix}/lib/systemd/user-preset +%dir %{_prefix}/lib/systemd/system-shutdown +%dir %{_prefix}/lib/systemd/system-sleep +%dir %{_prefix}/lib/systemd/catalog +%dir %{_prefix}/lib/systemd/ntp-units.d +%dir %{_prefix}/lib/tmpfiles.d +%dir %{_prefix}/lib/sysctl.d +%dir %{_prefix}/lib/modules-load.d +%dir %{_prefix}/lib/binfmt.d +%dir %{_datadir}/systemd +%dir %{_datadir}/pkgconfig +%dir %{_localstatedir}/lib/systemd +%dir %{_localstatedir}/lib/systemd/catalog +%dir %{_localstatedir}/lib/systemd/coredump +%config(noreplace) %{_sysconfdir}/dbus-1/system.d/org.freedesktop.systemd1.conf +%config(noreplace) %{_sysconfdir}/dbus-1/system.d/org.freedesktop.hostname1.conf +%config(noreplace) %{_sysconfdir}/dbus-1/system.d/org.freedesktop.login1.conf +%config(noreplace) %{_sysconfdir}/dbus-1/system.d/org.freedesktop.locale1.conf +%config(noreplace) %{_sysconfdir}/dbus-1/system.d/org.freedesktop.timedate1.conf +%config(noreplace) %{_sysconfdir}/dbus-1/system.d/org.freedesktop.machine1.conf +%config(noreplace) %{_sysconfdir}/systemd/system.conf +%config(noreplace) %{_sysconfdir}/systemd/user.conf +%config(noreplace) %{_sysconfdir}/systemd/logind.conf +%config(noreplace) %{_sysconfdir}/systemd/journald.conf +%config(noreplace) %{_sysconfdir}/systemd/bootchart.conf +%config(noreplace) %{_sysconfdir}/udev/udev.conf +%config(noreplace) %{_sysconfdir}/rsyslog.d/listen.conf +%config(noreplace) %{_sysconfdir}/yum/protected.d/systemd.conf +%config(noreplace) %{_sysconfdir}/pam.d/systemd-user +%ghost %{_sysconfdir}/udev/hwdb.bin +%{_rpmconfigdir}/macros.d/macros.systemd +%{_sysconfdir}/xdg/systemd +%{_sysconfdir}/rc.d/init.d/README +%ghost %config(noreplace) %{_sysconfdir}/hostname +%ghost %config(noreplace) %{_sysconfdir}/localtime +%ghost %config(noreplace) %{_sysconfdir}/vconsole.conf +%ghost %config(noreplace) %{_sysconfdir}/locale.conf +%ghost %config(noreplace) %{_sysconfdir}/machine-id +%ghost %config(noreplace) %{_sysconfdir}/machine-info +%ghost %config(noreplace) %{_sysconfdir}/X11/xorg.conf.d/00-keyboard.conf +%ghost %config(noreplace) %{_sysconfdir}/X11/xorg.conf.d/00-system-setup-keyboard.conf +%ghost %{_localstatedir}/lib/systemd/catalog/database +%{_bindir}/systemctl +%{_bindir}/systemd-notify +%{_bindir}/systemd-analyze +%{_bindir}/systemd-ask-password +%{_bindir}/systemd-tty-ask-password-agent +%{_bindir}/systemd-machine-id-setup +%{_bindir}/loginctl +%{_bindir}/systemd-loginctl +%{_bindir}/journalctl +%{_bindir}/machinectl +%{_bindir}/systemd-tmpfiles +%{_bindir}/systemd-nspawn +%{_bindir}/systemd-stdio-bridge +%{_bindir}/systemd-cat +%{_bindir}/systemd-cgls +%{_bindir}/systemd-cgtop +%{_bindir}/systemd-delta +%{_bindir}/systemd-run +%caps(cap_dac_override,cap_sys_ptrace=pe) %{_bindir}/systemd-detect-virt +%{_bindir}/systemd-inhibit +%{_bindir}/hostnamectl +%{_bindir}/localectl +%{_bindir}/timedatectl +%{_bindir}/bootctl +%{_bindir}/systemd-coredumpctl +%{_bindir}/udevadm +%{_bindir}/kernel-install +%{_prefix}/lib/systemd/systemd +%exclude %{_prefix}/lib/systemd/system/systemd-journal-gatewayd.* +%{_prefix}/lib/systemd/system +%{_prefix}/lib/systemd/user +%exclude %{_prefix}/lib/systemd/systemd-journal-gatewayd +%{_prefix}/lib/systemd/systemd-* +%{_prefix}/lib/udev +%{_prefix}/lib/systemd/system-generators/systemd-cryptsetup-generator +%{_prefix}/lib/systemd/system-generators/systemd-getty-generator +%{_prefix}/lib/systemd/system-generators/systemd-rc-local-generator +%{_prefix}/lib/systemd/system-generators/systemd-fstab-generator +%{_prefix}/lib/systemd/system-generators/systemd-system-update-generator +%{_prefix}/lib/systemd/system-generators/systemd-efi-boot-generator +%{_prefix}/lib/tmpfiles.d/systemd.conf +%{_prefix}/lib/tmpfiles.d/x11.conf +%{_prefix}/lib/tmpfiles.d/legacy.conf +%{_prefix}/lib/tmpfiles.d/tmp.conf +%{_prefix}/lib/sysctl.d/50-default.conf +%{_prefix}/lib/systemd/system-preset/85-display-manager.preset +%{_prefix}/lib/systemd/system-preset/90-default.preset +%{_prefix}/lib/systemd/system-preset/99-default-disable.preset +%{_prefix}/lib/systemd/catalog/systemd.catalog +%{_prefix}/lib/kernel/install.d/50-depmod.install +%{_prefix}/lib/kernel/install.d/90-loaderentry.install +%{_sbindir}/init +%{_sbindir}/reboot +%{_sbindir}/halt +%{_sbindir}/poweroff +%{_sbindir}/shutdown +%{_sbindir}/telinit +%{_sbindir}/runlevel +%{_sbindir}/udevadm +%{_mandir}/man1/* +%{_mandir}/man5/* +%{_mandir}/man7/* +%exclude %{_mandir}/man8/systemd-journal-gatewayd.* +%{_mandir}/man8/* +%{_datadir}/systemd/kbd-model-map +%{_datadir}/dbus-1/services/org.freedesktop.systemd1.service +%{_datadir}/dbus-1/system-services/org.freedesktop.systemd1.service +%{_datadir}/dbus-1/system-services/org.freedesktop.hostname1.service +%{_datadir}/dbus-1/system-services/org.freedesktop.login1.service +%{_datadir}/dbus-1/system-services/org.freedesktop.locale1.service +%{_datadir}/dbus-1/system-services/org.freedesktop.timedate1.service +%{_datadir}/dbus-1/system-services/org.freedesktop.machine1.service +%{_datadir}/dbus-1/interfaces/org.freedesktop.systemd1.*.xml +%{_datadir}/dbus-1/interfaces/org.freedesktop.hostname1.xml +%{_datadir}/dbus-1/interfaces/org.freedesktop.locale1.xml +%{_datadir}/dbus-1/interfaces/org.freedesktop.timedate1.xml +%{_datadir}/polkit-1/actions/org.freedesktop.systemd1.policy +%{_datadir}/polkit-1/actions/org.freedesktop.hostname1.policy +%{_datadir}/polkit-1/actions/org.freedesktop.login1.policy +%{_datadir}/polkit-1/actions/org.freedesktop.locale1.policy +%{_datadir}/polkit-1/actions/org.freedesktop.timedate1.policy +%{_datadir}/pkgconfig/systemd.pc +%{_datadir}/pkgconfig/udev.pc +%{_datadir}/bash-completion/completions/hostnamectl +%{_datadir}/bash-completion/completions/journalctl +%{_datadir}/bash-completion/completions/localectl +%{_datadir}/bash-completion/completions/loginctl +%{_datadir}/bash-completion/completions/systemctl +%{_datadir}/bash-completion/completions/systemd-coredumpctl +%{_datadir}/bash-completion/completions/timedatectl +%{_datadir}/bash-completion/completions/udevadm +%{_datadir}/bash-completion/completions/systemd-analyze +%{_datadir}/bash-completion/completions/kernel-install +%{_datadir}/bash-completion/completions/systemd-run +%{_datadir}/zsh/site-functions/* +%ghost %{_localstatedir}/lib/random-seed +%ghost %dir %{_localstatedir}/var/lib/systemd/ +%ghost %dir %{_localstatedir}/var/lib/systemd/coredump +%ghost %dir %{_localstatedir}/var/lib/systemd/catalog +%ghost %{_localstatedir}/var/lib/systemd/catalog/database +%ghost %dir %{_localstatedir}/var/lib/backlight/ +%config(noreplace) %{_sysconfdir}/rc.d/rc.local +%{_sysconfdir}/rc.local + +# Make sure we don't remove runlevel targets from F14 alpha installs, +# but make sure we don't create then anew. +%ghost %config(noreplace) %{_sysconfdir}/systemd/system/runlevel2.target +%ghost %config(noreplace) %{_sysconfdir}/systemd/system/runlevel3.target +%ghost %config(noreplace) %{_sysconfdir}/systemd/system/runlevel4.target +%ghost %config(noreplace) %{_sysconfdir}/systemd/system/runlevel5.target + +%files libs +%{_libdir}/security/pam_systemd.so +%{_libdir}/libnss_myhostname.so.2 +%{_libdir}/libsystemd-daemon.so.* +%{_libdir}/libsystemd-login.so.* +%{_libdir}/libsystemd-journal.so.* +%{_libdir}/libsystemd-id128.so.* +%{_libdir}/libudev.so.* + +%files devel +%dir %{_includedir}/systemd +%{_libdir}/libsystemd-daemon.so +%{_libdir}/libsystemd-login.so +%{_libdir}/libsystemd-journal.so +%{_libdir}/libsystemd-id128.so +%{_libdir}/libudev.so +%{_includedir}/systemd/sd-daemon.h +%{_includedir}/systemd/sd-login.h +%{_includedir}/systemd/sd-journal.h +%{_includedir}/systemd/sd-id128.h +%{_includedir}/systemd/sd-messages.h +%{_includedir}/systemd/sd-shutdown.h +%{_includedir}/libudev.h +%{_libdir}/pkgconfig/libsystemd-daemon.pc +%{_libdir}/pkgconfig/libsystemd-login.pc +%{_libdir}/pkgconfig/libsystemd-journal.pc +%{_libdir}/pkgconfig/libsystemd-id128.pc +%{_libdir}/pkgconfig/libudev.pc +%{_mandir}/man3/* +%dir %{_datadir}/gtk-doc/html/libudev +%{_datadir}/gtk-doc/html/libudev/* + +%files sysv +%{_bindir}/systemd-sysv-convert + +%files python +%{python_sitearch}/systemd/__init__.py +%{python_sitearch}/systemd/__init__.pyc +%{python_sitearch}/systemd/__init__.pyo +%{python_sitearch}/systemd/_journal.so +%{python_sitearch}/systemd/_reader.so +%{python_sitearch}/systemd/_daemon.so +%{python_sitearch}/systemd/id128.so +%{python_sitearch}/systemd/login.so +%{python_sitearch}/systemd/journal.py +%{python_sitearch}/systemd/journal.pyc +%{python_sitearch}/systemd/journal.pyo +%{python_sitearch}/systemd/daemon.py +%{python_sitearch}/systemd/daemon.pyc +%{python_sitearch}/systemd/daemon.pyo + +%files -n libgudev1 +%{_libdir}/libgudev-1.0.so.* +%{_libdir}/girepository-1.0/GUdev-1.0.typelib + +%files -n libgudev1-devel +%{_libdir}/libgudev-1.0.so +%dir %{_includedir}/gudev-1.0 +%dir %{_includedir}/gudev-1.0/gudev +%{_includedir}/gudev-1.0/gudev/*.h +%{_datadir}/gir-1.0/GUdev-1.0.gir +%dir %{_datadir}/gtk-doc/html/gudev +%{_datadir}/gtk-doc/html/gudev/* +%{_libdir}/pkgconfig/gudev-1.0* + +%files journal-gateway +%{_prefix}/lib/systemd/system/systemd-journal-gatewayd.* +%{_prefix}/lib/systemd/systemd-journal-gatewayd +%{_mandir}/man8/systemd-journal-gatewayd.* +%{_datadir}/systemd/gatewayd + +%changelog +* Tue Nov 19 2013 Lukas Nykryn - 207-8 +- tmpfiles: introduce m (#1030961) + +* Tue Nov 12 2013 Lukas Nykryn - 207-7 +- introduce DefaultStartLimit (#821723) + +* Mon Nov 11 2013 Harald Hoyer 207-6 +- changed systemd-journal-gateway login shell to /sbin/nologin +- backported a lot of bugfixes +- udev: path_id - fix by-path link generation for scm devices +Resolves: rhbz#888707 + +* Tue Nov 05 2013 Lukas Nykryn - 207-5 +- create /etc/rc.d/rc.local (#968401) +- cgroup: always enable memory.use_hierarchy= for all cgroups (#1011575) +- remove user@.service (#1019738) +- drop some out-of-date references to cgroup settings (#1000004) +- explain NAME in systemctl man page (#978954) + +* Tue Oct 15 2013 Lukas Nykryn - 207-4 +- core: whenever a new PID is passed to us, make sure we watch it + +* Tue Oct 01 2013 Lukas Nykryn - 207-3 +- presets: add tuned.service + +* Thu Sep 19 2013 Lukas Nykryn - 207-2 +- Advertise hibernation only if there's enough free swap +- swap: create .wants symlink to 'auto' swap devices +- Verify validity of session name when received from outside +- polkit: Avoid race condition in scraping /proc +Resolves: rhbz#1005142 + +* Fri Sep 13 2013 Harald Hoyer 207-1 +- version 207 + +* Fri Sep 06 2013 Harald Hoyer 206-8 +- support "debug" kernel command line parameter +- journald: fix fd leak in journal_file_empty +- journald: fix vacuuming of archived journals +- libudev: enumerate - do not try to match against an empty subsystem +- cgtop: fixup the online help +- libudev: fix memleak when enumerating childs + +* Wed Aug 28 2013 Harald Hoyer 206-7 +- fixed cgroup hashmap corruption +Resolves: rhbz#997742 rhbz#995197 + +* Fri Aug 23 2013 Harald Hoyer 206-6 +- cgroup.c: check return value of unit_realize_cgroup_now() +Resolves: rhbz#997742 rhbz#995197 + +* Thu Aug 22 2013 Harald Hoyer 206-5 +- obsolete upstart +Resolves: rhbz#978014 +- obsolete hal +Resolves: rhbz#975589 +- service: always unwatch PIDs before forgetting old ones +Resolves: rhbz#995197 +- units: disable kmod-static-nodes.service in containers +- use CAP_MKNOD ConditionCapability +- fstab-generator: read rd.fstab=on/off switch correctly +- backlight: add minimal tool to save/restore screen brightness +- backlight: instead of syspath use sysname for identifying +- sysctl: allow overwriting of values specified in "later" +- systemd-python: fix initialization of _Reader objects +- udevd: simplify sigterm check +- libudev: fix hwdb validation to look for the *new* file +- units: make fsck units remain after exit +- udev: replace CAP_MKNOD by writable /sys condition +- libudev-enumerate.c:udev_enumerate_get_list_entry() fixed +- journal: fix parsing of facility in syslog messages + +* Fri Aug 09 2013 Harald Hoyer 206-4 +- journal: handle multiline syslog messages +- man: Fix copy&paste error +- core: synchronously block when logging +- journal: immediately sync to disk as soon as we receieve an EMERG/ALERT/CRIT message +- initctl: use irreversible jobs when switching runlevels +- udev: log error if chmod/chown of static dev nodes fails +- udev: static_node - don't touch permissions uneccessarily +- tmpfiles: support passing --prefix multiple times +- tmpfiles: introduce --exclude-prefix +- tmpfiles-setup: exclude /dev prefixes files +- logind: update state file after generating the session fifo, not before +- journalctl: use _COMM= match for scripts +- man: systemd.unit: fix volatile path +- man: link up scope+slice units from systemd.unit(5) +- man: there is no session mode, only user mode +- journal: fix hashmap leak in mmap-cache +- systemd-delta: Only print colors when on a tty +- systemd: fix segv in snapshot creation +- udev: hwdb - try reading modalias for usb before falling back to the composed one +- udevd: respect the log-level set in /etc/udev/udev.conf +- fstab-generator: respect noauto/nofail when adding sysroot mount + +* Fri Aug 02 2013 Lukáš Nykrýn - 206-3 +- add dependency on kmod >= 14 +- remove /var/log/journal to make journal non-persistant (#989750) +- add hypervkvpd.service to presets (#924321) + +* Thu Aug 01 2013 Lukáš Nykrýn - 206-2 +- 80-net-name-slot.rules: only rename network interfaces on ACTION==add + +* Tue Jul 23 2013 Kay Sievers - 206-1 +- New upstream release + Resolves (#984152) + +* Wed Jul 3 2013 Lennart Poettering - 205-1 +- New upstream release + +* Wed Jun 26 2013 Michal Schmidt 204-10 +- Split systemd-journal-gateway subpackage (#908081). + +* Mon Jun 24 2013 Michal Schmidt 204-9 +- Rename nm_dispatcher to NetworkManager-dispatcher in default preset (#977433) + +* Fri Jun 14 2013 Harald Hoyer 204-8 +- fix, which helps to sucessfully browse journals with + duplicated seqnums + +* Fri Jun 14 2013 Harald Hoyer 204-7 +- fix duplicate message ID bug +Resolves: rhbz#974132 + +* Thu Jun 06 2013 Harald Hoyer 204-6 +- introduce 99-default-disable.preset + +* Thu Jun 6 2013 Lennart Poettering - 204-5 +- Rename 90-display-manager.preset to 85-display-manager.preset so that it actually takes precedence over 90-default.preset's "disable *" line (#903690) + +* Tue May 28 2013 Harald Hoyer 204-4 +- Fix kernel-install (#965897) + +* Wed May 22 2013 Kay Sievers - 204-3 +- Fix kernel-install (#965897) + +* Thu May 9 2013 Lennart Poettering - 204-2 +- New upstream release +- disable isdn by default (#959793) + +* Tue May 07 2013 Harald Hoyer 203-2 +- forward port kernel-install-grubby.patch + +* Tue May 7 2013 Lennart Poettering - 203-1 +- New upstream release + +* Wed Apr 24 2013 Harald Hoyer 202-3 +- fix ENOENT for getaddrinfo +- Resolves: rhbz#954012 rhbz#956035 +- crypt-setup-generator: correctly check return of strdup +- logind-dbus: initialize result variable +- prevent library underlinking + +* Fri Apr 19 2013 Harald Hoyer 202-2 +- nspawn create empty /etc/resolv.conf if necessary +- python wrapper: add sd_journal_add_conjunction() +- fix s390 booting +- Resolves: rhbz#953217 + +* Thu Apr 18 2013 Lennart Poettering - 202-1 +- New upstream release + +* Tue Apr 09 2013 Michal Schmidt - 201-2 +- Automatically discover whether to run autoreconf and add autotools and git + BuildRequires based on the presence of patches to be applied. +- Use find -delete. + +* Mon Apr 8 2013 Lennart Poettering - 201-1 +- New upstream release + +* Mon Apr 8 2013 Lennart Poettering - 200-4 +- Update preset file + +* Fri Mar 29 2013 Lennart Poettering - 200-3 +- Remove NetworkManager-wait-online.service from presets file again, it should default to off + +* Fri Mar 29 2013 Lennart Poettering - 200-2 +- New upstream release + +* Tue Mar 26 2013 Lennart Poettering - 199-2 +- Add NetworkManager-wait-online.service to the presets file + +* Tue Mar 26 2013 Lennart Poettering - 199-1 +- New upstream release + +* Mon Mar 18 2013 Michal Schmidt 198-7 +- Drop /usr/s?bin/ prefixes. + +* Fri Mar 15 2013 Harald Hoyer 198-6 +- run autogen to pickup all changes + +* Fri Mar 15 2013 Harald Hoyer 198-5 +- do not mount anything, when not running as pid 1 +- add initrd.target for systemd in the initrd + +* Wed Mar 13 2013 Harald Hoyer 198-4 +- fix switch-root and local-fs.target problem +- patch kernel-install to use grubby, if available + +* Fri Mar 08 2013 Harald Hoyer 198-3 +- add Conflict with dracut < 026 because of the new switch-root isolate + +* Thu Mar 7 2013 Lennart Poettering - 198-2 +- Create required users + +* Thu Mar 7 2013 Lennart Poettering - 198-1 +- New release +- Enable journal persistancy by default + +* Sun Feb 10 2013 Peter Robinson 197-3 +- Bump for ARM + +* Fri Jan 18 2013 Michal Schmidt - 197-2 +- Added qemu-guest-agent.service to presets (Lennart, #885406). +- Add missing pygobject3-base to systemd-analyze deps (Lennart). +- Do not require hwdata, it is all in the hwdb now (Kay). +- Drop dependency on dbus-python. + +* Tue Jan 8 2013 Lennart Poettering - 197-1 +- New upstream release + +* Mon Dec 10 2012 Michal Schmidt - 196-4 +- Enable rngd.service by default (#857765). + +* Mon Dec 10 2012 Michal Schmidt - 196-3 +- Disable hardening on s390(x) because PIE is broken there and produces + text relocations with __thread (#868839). + +* Wed Dec 05 2012 Michal Schmidt - 196-2 +- added spice-vdagentd.service to presets (Lennart, #876237) +- BR cryptsetup-devel instead of the legacy cryptsetup-luks-devel provide name + (requested by Milan Brož). +- verbose make to see the actual build flags + +* Wed Nov 21 2012 Lennart Poettering - 196-1 +- New upstream release + +* Tue Nov 20 2012 Lennart Poettering - 195-8 +- https://bugzilla.redhat.com/show_bug.cgi?id=873459 +- https://bugzilla.redhat.com/show_bug.cgi?id=878093 + +* Thu Nov 15 2012 Michal Schmidt - 195-7 +- Revert udev killing cgroup patch for F18 Beta. +- https://bugzilla.redhat.com/show_bug.cgi?id=873576 + +* Fri Nov 09 2012 Michal Schmidt - 195-6 +- Fix cyclical dep between systemd and systemd-libs. +- Avoid broken build of test-journal-syslog. +- https://bugzilla.redhat.com/show_bug.cgi?id=873387 +- https://bugzilla.redhat.com/show_bug.cgi?id=872638 + +* Thu Oct 25 2012 Kay Sievers - 195-5 +- require 'sed', limit HOSTNAME= match + +* Wed Oct 24 2012 Michal Schmidt - 195-4 +- add dmraid-activation.service to the default preset +- add yum protected.d fragment +- https://bugzilla.redhat.com/show_bug.cgi?id=869619 +- https://bugzilla.redhat.com/show_bug.cgi?id=869717 + +* Wed Oct 24 2012 Kay Sievers - 195-3 +- Migrate /etc/sysconfig/ i18n, keyboard, network files/variables to + systemd native files + +* Tue Oct 23 2012 Lennart Poettering - 195-2 +- Provide syslog because the journal is fine as a syslog implementation + +* Tue Oct 23 2012 Lennart Poettering - 195-1 +- New upstream release +- https://bugzilla.redhat.com/show_bug.cgi?id=831665 +- https://bugzilla.redhat.com/show_bug.cgi?id=847720 +- https://bugzilla.redhat.com/show_bug.cgi?id=858693 +- https://bugzilla.redhat.com/show_bug.cgi?id=863481 +- https://bugzilla.redhat.com/show_bug.cgi?id=864629 +- https://bugzilla.redhat.com/show_bug.cgi?id=864672 +- https://bugzilla.redhat.com/show_bug.cgi?id=864674 +- https://bugzilla.redhat.com/show_bug.cgi?id=865128 +- https://bugzilla.redhat.com/show_bug.cgi?id=866346 +- https://bugzilla.redhat.com/show_bug.cgi?id=867407 +- https://bugzilla.redhat.com/show_bug.cgi?id=868603 + +* Wed Oct 10 2012 Michal Schmidt - 194-2 +- Add scriptlets for migration away from systemd-timedated-ntp.target + +* Wed Oct 3 2012 Lennart Poettering - 194-1 +- New upstream release +- https://bugzilla.redhat.com/show_bug.cgi?id=859614 +- https://bugzilla.redhat.com/show_bug.cgi?id=859655 + +* Fri Sep 28 2012 Lennart Poettering - 193-1 +- New upstream release + +* Tue Sep 25 2012 Lennart Poettering - 192-1 +- New upstream release + +* Fri Sep 21 2012 Lennart Poettering - 191-2 +- Fix journal mmap header prototype definition to fix compilation on 32bit + +* Fri Sep 21 2012 Lennart Poettering - 191-1 +- New upstream release +- Enable all display managers by default, as discussed with Adam Williamson + +* Thu Sep 20 2012 Lennart Poettering - 190-1 +- New upstream release +- Take possession of /etc/localtime, and remove /etc/sysconfig/clock +- https://bugzilla.redhat.com/show_bug.cgi?id=858780 +- https://bugzilla.redhat.com/show_bug.cgi?id=858787 +- https://bugzilla.redhat.com/show_bug.cgi?id=858771 +- https://bugzilla.redhat.com/show_bug.cgi?id=858754 +- https://bugzilla.redhat.com/show_bug.cgi?id=858746 +- https://bugzilla.redhat.com/show_bug.cgi?id=858266 +- https://bugzilla.redhat.com/show_bug.cgi?id=858224 +- https://bugzilla.redhat.com/show_bug.cgi?id=857670 +- https://bugzilla.redhat.com/show_bug.cgi?id=856975 +- https://bugzilla.redhat.com/show_bug.cgi?id=855863 +- https://bugzilla.redhat.com/show_bug.cgi?id=851970 +- https://bugzilla.redhat.com/show_bug.cgi?id=851275 +- https://bugzilla.redhat.com/show_bug.cgi?id=851131 +- https://bugzilla.redhat.com/show_bug.cgi?id=847472 +- https://bugzilla.redhat.com/show_bug.cgi?id=847207 +- https://bugzilla.redhat.com/show_bug.cgi?id=846483 +- https://bugzilla.redhat.com/show_bug.cgi?id=846085 +- https://bugzilla.redhat.com/show_bug.cgi?id=845973 +- https://bugzilla.redhat.com/show_bug.cgi?id=845194 +- https://bugzilla.redhat.com/show_bug.cgi?id=845028 +- https://bugzilla.redhat.com/show_bug.cgi?id=844630 +- https://bugzilla.redhat.com/show_bug.cgi?id=839736 +- https://bugzilla.redhat.com/show_bug.cgi?id=835848 +- https://bugzilla.redhat.com/show_bug.cgi?id=831740 +- https://bugzilla.redhat.com/show_bug.cgi?id=823485 +- https://bugzilla.redhat.com/show_bug.cgi?id=821813 +- https://bugzilla.redhat.com/show_bug.cgi?id=807886 +- https://bugzilla.redhat.com/show_bug.cgi?id=802198 +- https://bugzilla.redhat.com/show_bug.cgi?id=767795 +- https://bugzilla.redhat.com/show_bug.cgi?id=767561 +- https://bugzilla.redhat.com/show_bug.cgi?id=752774 +- https://bugzilla.redhat.com/show_bug.cgi?id=732874 +- https://bugzilla.redhat.com/show_bug.cgi?id=858735 + +* Thu Sep 13 2012 Lennart Poettering - 189-4 +- Don't pull in pkg-config as dep +- https://bugzilla.redhat.com/show_bug.cgi?id=852828 + +* Wed Sep 12 2012 Lennart Poettering - 189-3 +- Update preset policy +- Rename preset policy file from 99-default.preset to 90-default.preset so that people can order their own stuff after the Fedora default policy if they wish + +* Thu Aug 23 2012 Lennart Poettering - 189-2 +- Update preset policy +- https://bugzilla.redhat.com/show_bug.cgi?id=850814 + +* Thu Aug 23 2012 Lennart Poettering - 189-1 +- New upstream release + +* Thu Aug 16 2012 Ray Strode 188-4 +- more scriptlet fixes + (move dm migration logic to %posttrans so the service + files it's looking for are available at the time + the logic is run) + +* Sat Aug 11 2012 Lennart Poettering - 188-3 +- Remount file systems MS_PRIVATE before switching roots +- https://bugzilla.redhat.com/show_bug.cgi?id=847418 + +* Wed Aug 08 2012 Rex Dieter - 188-2 +- fix scriptlets + +* Wed Aug 8 2012 Lennart Poettering - 188-1 +- New upstream release +- Enable gdm and avahi by default via the preset file +- Convert /etc/sysconfig/desktop to display-manager.service symlink +- Enable hardened build + +* Mon Jul 30 2012 Kay Sievers - 187-3 +- Obsolete: system-setup-keyboard + +* Wed Jul 25 2012 Kalev Lember - 187-2 +- Run ldconfig for the new -libs subpackage + +* Thu Jul 19 2012 Lennart Poettering - 187-1 +- New upstream release + +* Mon Jul 09 2012 Harald Hoyer 186-2 +- fixed dracut conflict version + +* Tue Jul 3 2012 Lennart Poettering - 186-1 +- New upstream release + +* Fri Jun 22 2012 Nils Philippsen - 185-7.gite7aee75 +- add obsoletes/conflicts so multilib systemd -> systemd-libs updates work + +* Thu Jun 14 2012 Michal Schmidt - 185-6.gite7aee75 +- Update to current git + +* Wed Jun 06 2012 Kay Sievers - 185-5.gita2368a3 +- disable plymouth in configure, to drop the .wants/ symlinks + +* Wed Jun 06 2012 Michal Schmidt - 185-4.gita2368a3 +- Update to current git snapshot + - Add systemd-readahead-analyze + - Drop upstream patch +- Split systemd-libs +- Drop duplicate doc files +- Fixed License headers of subpackages + +* Wed Jun 06 2012 Ray Strode - 185-3 +- Drop plymouth files +- Conflict with old plymouth + +* Tue Jun 05 2012 Kay Sievers - 185-2 +- selinux udev labeling fix +- conflict with older dracut versions for new udev file names + +* Mon Jun 04 2012 Kay Sievers - 185-1 +- New upstream release + - udev selinux labeling fixes + - new man pages + - systemctl help + +* Thu May 31 2012 Lennart Poettering - 184-1 +- New upstream release + +* Thu May 24 2012 Kay Sievers - 183-1 +- New upstream release including udev merge. + +* Wed Mar 28 2012 Michal Schmidt - 44-4 +- Add triggers from Bill Nottingham to correct the damage done by + the obsoleted systemd-units's preun scriptlet (#807457). + +* Mon Mar 26 2012 Dennis Gilmore - 44-3 +- apply patch from upstream so we can build systemd on arm and ppc +- and likely the rest of the secondary arches + +* Tue Mar 20 2012 Michal Schmidt - 44-2 +- Don't build the gtk parts anymore. They're moving into systemd-ui. +- Remove a dead patch file. + +* Fri Mar 16 2012 Lennart Poettering - 44-1 +- New upstream release +- Closes #798760, #784921, #783134, #768523, #781735 + +* Mon Feb 27 2012 Dennis Gilmore - 43-2 +- don't conflict with fedora-release systemd never actually provided +- /etc/os-release so there is no actual conflict + +* Wed Feb 15 2012 Lennart Poettering - 43-1 +- New upstream release +- Closes #789758, #790260, #790522 + +* Sat Feb 11 2012 Lennart Poettering - 42-1 +- New upstream release +- Save a bit of entropy during system installation (#789407) +- Don't own /etc/os-release anymore, leave that to fedora-release + +* Thu Feb 9 2012 Adam Williamson - 41-2 +- rebuild for fixed binutils + +* Thu Feb 9 2012 Lennart Poettering - 41-1 +- New upstream release + +* Tue Feb 7 2012 Lennart Poettering - 40-1 +- New upstream release + +* Thu Jan 26 2012 Kay Sievers - 39-3 +- provide /sbin/shutdown + +* Wed Jan 25 2012 Harald Hoyer 39-2 +- increment release + +* Wed Jan 25 2012 Kay Sievers - 39-1.1 +- install everything in /usr + https://fedoraproject.org/wiki/Features/UsrMove + +* Wed Jan 25 2012 Lennart Poettering - 39-1 +- New upstream release + +* Sun Jan 22 2012 Michal Schmidt - 38-6.git9fa2f41 +- Update to a current git snapshot. +- Resolves: #781657 + +* Sun Jan 22 2012 Michal Schmidt - 38-5 +- Build against libgee06. Reenable gtk tools. +- Delete unused patches. +- Add easy building of git snapshots. +- Remove legacy spec file elements. +- Don't mention implicit BuildRequires. +- Configure with --disable-static. +- Merge -units into the main package. +- Move section 3 manpages to -devel. +- Fix unowned directory. +- Run ldconfig in scriptlets. +- Split systemd-analyze to a subpackage. + +* Sat Jan 21 2012 Dan Horák - 38-4 +- fix build on big-endians + +* Wed Jan 11 2012 Lennart Poettering - 38-3 +- Disable building of gtk tools for now + +* Wed Jan 11 2012 Lennart Poettering - 38-2 +- Fix a few (build) dependencies + +* Wed Jan 11 2012 Lennart Poettering - 38-1 +- New upstream release + +* Tue Nov 15 2011 Michal Schmidt - 37-4 +- Run authconfig if /etc/pam.d/system-auth is not a symlink. +- Resolves: #753160 + +* Wed Nov 02 2011 Michal Schmidt - 37-3 +- Fix remote-fs-pre.target and its ordering. +- Resolves: #749940 + +* Wed Oct 19 2011 Michal Schmidt - 37-2 +- A couple of fixes from upstream: +- Fix a regression in bash-completion reported in Bodhi. +- Fix a crash in isolating. +- Resolves: #717325 + +* Tue Oct 11 2011 Lennart Poettering - 37-1 +- New upstream release +- Resolves: #744726, #718464, #713567, #713707, #736756 + +* Thu Sep 29 2011 Michal Schmidt - 36-5 +- Undo the workaround. Kay says it does not belong in systemd. +- Unresolves: #741655 + +* Thu Sep 29 2011 Michal Schmidt - 36-4 +- Workaround for the crypto-on-lvm-on-crypto disk layout +- Resolves: #741655 + +* Sun Sep 25 2011 Michal Schmidt - 36-3 +- Revert an upstream patch that caused ordering cycles +- Resolves: #741078 + +* Fri Sep 23 2011 Lennart Poettering - 36-2 +- Add /etc/timezone to ghosted files + +* Fri Sep 23 2011 Lennart Poettering - 36-1 +- New upstream release +- Resolves: #735013, #736360, #737047, #737509, #710487, #713384 + +* Thu Sep 1 2011 Lennart Poettering - 35-1 +- New upstream release +- Update post scripts +- Resolves: #726683, #713384, #698198, #722803, #727315, #729997, #733706, #734611 + +* Thu Aug 25 2011 Lennart Poettering - 34-1 +- New upstream release + +* Fri Aug 19 2011 Harald Hoyer 33-2 +- fix ABRT on service file reloading +- Resolves: rhbz#732020 + +* Wed Aug 3 2011 Lennart Poettering - 33-1 +- New upstream release + +* Fri Jul 29 2011 Lennart Poettering - 32-1 +- New upstream release + +* Wed Jul 27 2011 Lennart Poettering - 31-2 +- Fix access mode of modprobe file, restart logind after upgrade + +* Wed Jul 27 2011 Lennart Poettering - 31-1 +- New upstream release + +* Wed Jul 13 2011 Lennart Poettering - 30-1 +- New upstream release + +* Thu Jun 16 2011 Lennart Poettering - 29-1 +- New upstream release + +* Mon Jun 13 2011 Michal Schmidt - 28-4 +- Apply patches from current upstream. +- Fixes memory size detection on 32-bit with >4GB RAM (BZ712341) + +* Wed Jun 08 2011 Michal Schmidt - 28-3 +- Apply patches from current upstream +- https://bugzilla.redhat.com/show_bug.cgi?id=709909 +- https://bugzilla.redhat.com/show_bug.cgi?id=710839 +- https://bugzilla.redhat.com/show_bug.cgi?id=711015 + +* Sat May 28 2011 Lennart Poettering - 28-2 +- Pull in nss-myhostname + +* Thu May 26 2011 Lennart Poettering - 28-1 +- New upstream release + +* Wed May 25 2011 Lennart Poettering - 26-2 +- Bugfix release +- https://bugzilla.redhat.com/show_bug.cgi?id=707507 +- https://bugzilla.redhat.com/show_bug.cgi?id=707483 +- https://bugzilla.redhat.com/show_bug.cgi?id=705427 +- https://bugzilla.redhat.com/show_bug.cgi?id=707577 + +* Sat Apr 30 2011 Lennart Poettering - 26-1 +- New upstream release +- https://bugzilla.redhat.com/show_bug.cgi?id=699394 +- https://bugzilla.redhat.com/show_bug.cgi?id=698198 +- https://bugzilla.redhat.com/show_bug.cgi?id=698674 +- https://bugzilla.redhat.com/show_bug.cgi?id=699114 +- https://bugzilla.redhat.com/show_bug.cgi?id=699128 + +* Thu Apr 21 2011 Lennart Poettering - 25-1 +- New upstream release +- https://bugzilla.redhat.com/show_bug.cgi?id=694788 +- https://bugzilla.redhat.com/show_bug.cgi?id=694321 +- https://bugzilla.redhat.com/show_bug.cgi?id=690253 +- https://bugzilla.redhat.com/show_bug.cgi?id=688661 +- https://bugzilla.redhat.com/show_bug.cgi?id=682662 +- https://bugzilla.redhat.com/show_bug.cgi?id=678555 +- https://bugzilla.redhat.com/show_bug.cgi?id=628004 + +* Wed Apr 6 2011 Lennart Poettering - 24-1 +- New upstream release +- https://bugzilla.redhat.com/show_bug.cgi?id=694079 +- https://bugzilla.redhat.com/show_bug.cgi?id=693289 +- https://bugzilla.redhat.com/show_bug.cgi?id=693274 +- https://bugzilla.redhat.com/show_bug.cgi?id=693161 + +* Tue Apr 5 2011 Lennart Poettering - 23-1 +- New upstream release +- Include systemd-sysv-convert + +* Fri Apr 1 2011 Lennart Poettering - 22-1 +- New upstream release + +* Wed Mar 30 2011 Lennart Poettering - 21-2 +- The quota services are now pulled in by mount points, hence no need to enable them explicitly + +* Tue Mar 29 2011 Lennart Poettering - 21-1 +- New upstream release + +* Mon Mar 28 2011 Matthias Clasen - 20-2 +- Apply upstream patch to not send untranslated messages to plymouth + +* Tue Mar 8 2011 Lennart Poettering - 20-1 +- New upstream release + +* Tue Mar 1 2011 Lennart Poettering - 19-1 +- New upstream release + +* Wed Feb 16 2011 Lennart Poettering - 18-1 +- New upstream release + +* Mon Feb 14 2011 Bill Nottingham - 17-6 +- bump upstart obsoletes (#676815) + +* Wed Feb 9 2011 Tom Callaway - 17-5 +- add macros.systemd file for %%{_unitdir} + +* Wed Feb 09 2011 Fedora Release Engineering - 17-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Wed Feb 9 2011 Lennart Poettering - 17-3 +- Fix popen() of systemctl, #674916 + +* Mon Feb 7 2011 Bill Nottingham - 17-2 +- add epoch to readahead obsolete + +* Sat Jan 22 2011 Lennart Poettering - 17-1 +- New upstream release + +* Tue Jan 18 2011 Lennart Poettering - 16-2 +- Drop console.conf again, since it is not shipped in pamtmp.conf + +* Sat Jan 8 2011 Lennart Poettering - 16-1 +- New upstream release + +* Thu Nov 25 2010 Lennart Poettering - 15-1 +- New upstream release + +* Thu Nov 25 2010 Lennart Poettering - 14-1 +- Upstream update +- Enable hwclock-load by default +- Obsolete readahead +- Enable /var/run and /var/lock on tmpfs + +* Fri Nov 19 2010 Lennart Poettering - 13-1 +- new upstream release + +* Wed Nov 17 2010 Bill Nottingham 12-3 +- Fix clash + +* Wed Nov 17 2010 Lennart Poettering - 12-2 +- Don't clash with initscripts for now, so that we don't break the builders + +* Wed Nov 17 2010 Lennart Poettering - 12-1 +- New upstream release + +* Fri Nov 12 2010 Matthias Clasen - 11-2 +- Rebuild with newer vala, libnotify + +* Thu Oct 7 2010 Lennart Poettering - 11-1 +- New upstream release + +* Wed Sep 29 2010 Jesse Keating - 10-6 +- Rebuilt for gcc bug 634757 + +* Thu Sep 23 2010 Bill Nottingham - 10-5 +- merge -sysvinit into main package + +* Mon Sep 20 2010 Bill Nottingham - 10-4 +- obsolete upstart-sysvinit too + +* Fri Sep 17 2010 Bill Nottingham - 10-3 +- Drop upstart requires + +* Tue Sep 14 2010 Lennart Poettering - 10-2 +- Enable audit +- https://bugzilla.redhat.com/show_bug.cgi?id=633771 + +* Tue Sep 14 2010 Lennart Poettering - 10-1 +- New upstream release +- https://bugzilla.redhat.com/show_bug.cgi?id=630401 +- https://bugzilla.redhat.com/show_bug.cgi?id=630225 +- https://bugzilla.redhat.com/show_bug.cgi?id=626966 +- https://bugzilla.redhat.com/show_bug.cgi?id=623456 + +* Fri Sep 3 2010 Bill Nottingham - 9-3 +- move fedora-specific units to initscripts; require newer version thereof + +* Fri Sep 3 2010 Lennart Poettering - 9-2 +- Add missing tarball + +* Fri Sep 3 2010 Lennart Poettering - 9-1 +- New upstream version +- Closes 501720, 614619, 621290, 626443, 626477, 627014, 627785, 628913 + +* Fri Aug 27 2010 Lennart Poettering - 8-3 +- Reexecute after installation, take ownership of /var/run/user +- https://bugzilla.redhat.com/show_bug.cgi?id=627457 +- https://bugzilla.redhat.com/show_bug.cgi?id=627634 + +* Thu Aug 26 2010 Lennart Poettering - 8-2 +- Properly create default.target link + +* Wed Aug 25 2010 Lennart Poettering - 8-1 +- New upstream release + +* Thu Aug 12 2010 Lennart Poettering - 7-3 +- Fix https://bugzilla.redhat.com/show_bug.cgi?id=623561 + +* Thu Aug 12 2010 Lennart Poettering - 7-2 +- Fix https://bugzilla.redhat.com/show_bug.cgi?id=623430 + +* Tue Aug 10 2010 Lennart Poettering - 7-1 +- New upstream release + +* Fri Aug 6 2010 Lennart Poettering - 6-2 +- properly hide output on package installation +- pull in coreutils during package installtion + +* Fri Aug 6 2010 Lennart Poettering - 6-1 +- New upstream release +- Fixes #621200 + +* Wed Aug 4 2010 Lennart Poettering - 5-2 +- Add tarball + +* Wed Aug 4 2010 Lennart Poettering - 5-1 +- Prepare release 5 + +* Tue Jul 27 2010 Bill Nottingham - 4-4 +- Add 'sysvinit-userspace' provide to -sysvinit package to fix upgrade/install (#618537) + +* Sat Jul 24 2010 Lennart Poettering - 4-3 +- Add libselinux to build dependencies + +* Sat Jul 24 2010 Lennart Poettering - 4-2 +- Use the right tarball + +* Sat Jul 24 2010 Lennart Poettering - 4-1 +- New upstream release, and make default + +* Tue Jul 13 2010 Lennart Poettering - 3-3 +- Used wrong tarball + +* Tue Jul 13 2010 Lennart Poettering - 3-2 +- Own /cgroup jointly with libcgroup, since we don't dpend on it anymore + +* Tue Jul 13 2010 Lennart Poettering - 3-1 +- New upstream release + +* Fri Jul 9 2010 Lennart Poettering - 2-0 +- New upstream release + +* Wed Jul 7 2010 Lennart Poettering - 1-0 +- First upstream release + +* Tue Jun 29 2010 Lennart Poettering - 0-0.7.20100629git4176e5 +- New snapshot +- Split off -units package where other packages can depend on without pulling in the whole of systemd + +* Tue Jun 22 2010 Lennart Poettering - 0-0.6.20100622gita3723b +- Add missing libtool dependency. + +* Tue Jun 22 2010 Lennart Poettering - 0-0.5.20100622gita3723b +- Update snapshot + +* Mon Jun 14 2010 Rahul Sundaram - 0-0.4.20100614git393024 +- Pull the latest snapshot that fixes a segfault. Resolves rhbz#603231 + +* Fri Jun 11 2010 Rahul Sundaram - 0-0.3.20100610git2f198e +- More minor fixes as per review + +* Thu Jun 10 2010 Rahul Sundaram - 0-0.2.20100610git2f198e +- Spec improvements from David Hollis + +* Wed Jun 09 2010 Rahul Sundaram - 0-0.1.20090609git2f198e +- Address review comments + +* Tue Jun 01 2010 Rahul Sundaram - 0-0.0.git2010-06-02 +- Initial spec (adopted from Kay Sievers)