diff --git a/0001-handle-disable_caplock-and-compose_table-and-kbd_rat.patch b/0001-handle-disable_caplock-and-compose_table-and-kbd_rat.patch index 7b91b90f..9d981f20 100644 --- a/0001-handle-disable_caplock-and-compose_table-and-kbd_rat.patch +++ b/0001-handle-disable_caplock-and-compose_table-and-kbd_rat.patch @@ -7,10 +7,10 @@ Subject: [PATCH] handle disable_caplock and compose_table and kbd_rate src/vconsole-setup.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 121 insertions(+), 3 deletions(-) -diff --git a/src/vconsole-setup.c b/src/vconsole-setup.c -index c5f3628..6603a75 100644 ---- a/src/vconsole-setup.c -+++ b/src/vconsole-setup.c +Index: systemd-37/src/vconsole-setup.c +=================================================================== +--- systemd-37.orig/src/vconsole-setup.c ++++ systemd-37/src/vconsole-setup.c @@ -40,6 +40,7 @@ #include "log.h" #include "macro.h" @@ -30,7 +30,7 @@ index c5f3628..6603a75 100644 int i = 0; pid_t pid; -@@ -99,6 +100,8 @@ static int load_keymap(const char *vc, const char *map, const char *map_toggle, +@@ -99,6 +100,8 @@ static int load_keymap(const char *vc, c args[i++] = map; if (map_toggle) args[i++] = map_toggle; @@ -39,16 +39,17 @@ index c5f3628..6603a75 100644 args[i++] = NULL; if ((pid = fork()) < 0) { -@@ -150,6 +153,96 @@ static int load_font(const char *vc, const char *font, const char *map, const ch +@@ -150,6 +153,101 @@ static int load_font(const char *vc, con return 0; } +#ifdef TARGET_SUSE +static int load_compose_table(const char *vc, const char *compose_table, pid_t *_pid) { + const char *args[1024]; -+ int i = 0; ++ int i = 0, j = 0; + pid_t pid; + char **strv_compose_table = NULL; ++ char *to_free[1024]; + + if (isempty(compose_table)) { + /* An empty map means no compose table*/ @@ -79,7 +80,7 @@ index c5f3628..6603a75 100644 + } + asprintf(&arg, "compose.%s",*name); + compose_loaded = true; -+ args[i++] = arg; ++ args[i++] = to_free[j++] = arg; + + } + strv_free(strv_compose_table); @@ -95,6 +96,10 @@ index c5f3628..6603a75 100644 + } + + *_pid = pid; ++ ++ for (i=0 ; i < j ; i++) ++ free (to_free[i]); ++ + return 0; +} + @@ -136,7 +141,7 @@ index c5f3628..6603a75 100644 int main(int argc, char **argv) { const char *vc; char *vc_keymap = NULL; -@@ -163,8 +256,16 @@ int main(int argc, char **argv) { +@@ -163,8 +261,16 @@ int main(int argc, char **argv) { #ifdef TARGET_MANDRIVA char *vc_keytable = NULL; #endif @@ -153,7 +158,7 @@ index c5f3628..6603a75 100644 int r = EXIT_FAILURE; pid_t font_pid = 0, keymap_pid = 0; -@@ -265,6 +366,10 @@ int main(int argc, char **argv) { +@@ -265,6 +371,10 @@ int main(int argc, char **argv) { #elif defined(TARGET_SUSE) if ((r = parse_env_file("/etc/sysconfig/keyboard", NEWLINE, "KEYTABLE", &vc_keymap, @@ -164,15 +169,15 @@ index c5f3628..6603a75 100644 NULL)) < 0) { if (r != -ENOENT) -@@ -280,6 +385,7 @@ int main(int argc, char **argv) { +@@ -280,6 +390,7 @@ int main(int argc, char **argv) { if (r != -ENOENT) log_warning("Failed to read /etc/sysconfig/console: %s", strerror(-r)); } -+ disable_capslock = strcasecmp(vc_kbd_disable_caps_lock, "YES") == 0; ++ disable_capslock = vc_kbd_disable_caps_lock && strcasecmp(vc_kbd_disable_caps_lock, "YES") == 0; #elif defined(TARGET_ARCH) if ((r = parse_env_file("/etc/rc.conf", NEWLINE, -@@ -436,7 +542,11 @@ int main(int argc, char **argv) { +@@ -436,7 +547,11 @@ int main(int argc, char **argv) { if (!utf8) disable_utf8(fd); @@ -185,7 +190,7 @@ index c5f3628..6603a75 100644 load_font(vc, vc_font, vc_font_map, vc_font_unimap, &font_pid) >= 0) r = EXIT_SUCCESS; -@@ -444,6 +554,14 @@ finish: +@@ -444,6 +559,14 @@ finish: if (keymap_pid > 0) wait_for_terminate_and_warn(KBD_LOADKEYS, keymap_pid); @@ -200,6 +205,16 @@ index c5f3628..6603a75 100644 if (font_pid > 0) wait_for_terminate_and_warn(KBD_SETFONT, font_pid); --- -1.7.3.4 - +@@ -451,6 +574,12 @@ finish: + free(vc_font); + free(vc_font_map); + free(vc_font_unimap); ++#ifdef TARGET_SUSE ++ free(vc_kbd_delay); ++ free(vc_kbd_rate); ++ free(vc_kbd_disable_caps_lock); ++ free(vc_compose_table); ++#endif + + if (fd >= 0) + close_nointr_nofail(fd); diff --git a/bootsplash-quit.service b/bootsplash-quit.service index 6e20630d..272deb89 100644 --- a/bootsplash-quit.service +++ b/bootsplash-quit.service @@ -3,7 +3,9 @@ Description=Terminate bootsplash After=xdm.service rc-local.service bootsplash-startup.service Before=getty@tty1.service DefaultDependencies=no -Names=plymout-quit-wait.service +Names=plymouth-quit-wait.service +ConditionKernelCommandLine=splash=silent +ConditionKernelCommandLine=vga [Service] ExecStart=/lib/systemd/systemd-bootsplash 5 diff --git a/bootsplash-startup.service b/bootsplash-startup.service index a10976c6..9f70d06b 100644 --- a/bootsplash-startup.service +++ b/bootsplash-startup.service @@ -2,6 +2,7 @@ Description=Start bootsplash DefaultDependencies=no ConditionKernelCommandLine=splash=silent +ConditionKernelCommandLine=vga [Service] ExecStart=/lib/systemd/systemd-bootsplash 0 diff --git a/color-on-boot.patch b/color-on-boot.patch new file mode 100644 index 00000000..8be6e081 --- /dev/null +++ b/color-on-boot.patch @@ -0,0 +1,131 @@ +From 5831e9b726ab6e76b28a94861a014d3bc2aa3015 Mon Sep 17 00:00:00 2001 +From: Michal Schmidt +Date: Thu, 10 Nov 2011 12:53:39 +0100 +Subject: [PATCH] job: colored status messages on boot + +The lack or green/red status marks on boot has been described by some +users as "critical", "dramatic", "dealbreaker", "showstopper". Seriously. +--- + src/job.c | 13 +++++++------ + src/unit.c | 24 ++++++++++++++++++++---- + src/unit.h | 2 +- + 3 files changed, 28 insertions(+), 11 deletions(-) + +diff --git a/src/job.c b/src/job.c +index 20971da..1520d81 100644 +--- a/src/job.c ++++ b/src/job.c +@@ -484,19 +484,20 @@ static void job_print_status_message(Unit *u, JobType t, JobResult result) { + switch (result) { + + case JOB_DONE: +- unit_status_printf(u, "Started %s.\n", unit_description(u)); ++ unit_status_printf(u, ANSI_HIGHLIGHT_GREEN_ON " OK " ANSI_HIGHLIGHT_OFF, "Started %s", unit_description(u)); + break; + + case JOB_FAILED: +- unit_status_printf(u, "Starting %s " ANSI_HIGHLIGHT_ON "failed" ANSI_HIGHLIGHT_OFF ", see 'systemctl status %s' for details.\n", unit_description(u), u->meta.id); ++ unit_status_printf(u, ANSI_HIGHLIGHT_ON "FAILED" ANSI_HIGHLIGHT_OFF, "Failed to start %s", unit_description(u)); ++ unit_status_printf(u, NULL, "See 'systemctl status %s' for details.", u->meta.id); + break; + + case JOB_DEPENDENCY: +- unit_status_printf(u, "Starting %s " ANSI_HIGHLIGHT_ON "aborted" ANSI_HIGHLIGHT_OFF " because a dependency failed.\n", unit_description(u)); ++ unit_status_printf(u, ANSI_HIGHLIGHT_ON " ABORT" ANSI_HIGHLIGHT_OFF, "Dependency failed. Aborted start of %s", unit_description(u)); + break; + + case JOB_TIMEOUT: +- unit_status_printf(u, "Starting %s " ANSI_HIGHLIGHT_ON "timed out" ANSI_HIGHLIGHT_OFF ".\n", unit_description(u), u->meta.id); ++ unit_status_printf(u, ANSI_HIGHLIGHT_ON " TIME " ANSI_HIGHLIGHT_OFF, "Timed out starting %s", unit_description(u)); + break; + + default: +@@ -508,12 +509,12 @@ static void job_print_status_message(Unit *u, JobType t, JobResult result) { + switch (result) { + + case JOB_TIMEOUT: +- unit_status_printf(u, "Stopping %s " ANSI_HIGHLIGHT_ON "timed out" ANSI_HIGHLIGHT_OFF ".\n", unit_description(u), u->meta.id); ++ unit_status_printf(u, ANSI_HIGHLIGHT_ON " TIME " ANSI_HIGHLIGHT_OFF, "Timed out stopping %s", unit_description(u)); + break; + + case JOB_DONE: + case JOB_FAILED: +- unit_status_printf(u, "Stopped %s.\n", unit_description(u)); ++ unit_status_printf(u, ANSI_HIGHLIGHT_GREEN_ON " OK " ANSI_HIGHLIGHT_OFF, "Stopped %s", unit_description(u)); + break; + + default: +diff --git a/src/unit.c b/src/unit.c +index 903a8e4..ad4063b 100644 +--- a/src/unit.c ++++ b/src/unit.c +@@ -924,7 +924,7 @@ int unit_start(Unit *u) { + + unit_add_to_dbus_queue(u); + +- unit_status_printf(u, "Starting %s...\n", unit_description(u)); ++ unit_status_printf(u, NULL, "Starting %s...", unit_description(u)); + return UNIT_VTABLE(u)->start(u); + } + +@@ -966,7 +966,7 @@ int unit_stop(Unit *u) { + + unit_add_to_dbus_queue(u); + +- unit_status_printf(u, "Stopping %s...\n", unit_description(u)); ++ unit_status_printf(u, NULL, "Stopping %s...", unit_description(u)); + return UNIT_VTABLE(u)->stop(u); + } + +@@ -2426,8 +2426,11 @@ int unit_coldplug(Unit *u) { + return 0; + } + +-void unit_status_printf(Unit *u, const char *format, ...) { ++void unit_status_printf(Unit *u, const char *status, const char *format, ...) { + va_list ap; ++ char *s, *e; ++ int err; ++ const unsigned emax = status ? 80 - (sizeof("[ OK ]")-1) : 80; + + assert(u); + assert(format); +@@ -2442,8 +2445,21 @@ void unit_status_printf(Unit *u, const char *format, ...) { + return; + + va_start(ap, format); +- status_vprintf(format, ap); ++ err = vasprintf(&s, format, ap); + va_end(ap); ++ if (err < 0) ++ return; ++ ++ e = ellipsize(s, emax, 100); ++ free(s); ++ if (!e) ++ return; ++ ++ if (status) ++ status_printf("%s%*s[%s]\n", e, emax - strlen(e), "", status); ++ else ++ status_printf("%s\n", e); ++ free(e); + } + + bool unit_need_daemon_reload(Unit *u) { +diff --git a/src/unit.h b/src/unit.h +index 7da5723..b32c1a7 100644 +--- a/src/unit.h ++++ b/src/unit.h +@@ -512,7 +512,7 @@ int unit_add_node_link(Unit *u, const char *what, bool wants); + + int unit_coldplug(Unit *u); + +-void unit_status_printf(Unit *u, const char *format, ...); ++void unit_status_printf(Unit *u, const char *status, const char *format, ...); + + bool unit_need_daemon_reload(Unit *u); + +-- +1.7.7 + diff --git a/cron-tty-pam.patch b/cron-tty-pam.patch new file mode 100644 index 00000000..ecacaf35 --- /dev/null +++ b/cron-tty-pam.patch @@ -0,0 +1,81 @@ +From 1dc995370987660ff045ff4d7cf512da0390cf96 Mon Sep 17 00:00:00 2001 +From: Michal Schmidt +Date: Sat, 19 Nov 2011 01:14:11 +0100 +Subject: [PATCH 1/2] pam-module: use the correct session type "unspecified" + +logind does not understand "other". +--- + src/pam-module.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/src/pam-module.c b/src/pam-module.c +index dd05f93..e650886 100644 +--- a/src/pam-module.c ++++ b/src/pam-module.c +@@ -472,7 +472,7 @@ _public_ PAM_EXTERN int pam_sm_open_session( + get_seat_from_display(display, &seat, &vtnr); + + type = !isempty(display) ? "x11" : +- !isempty(tty) ? "tty" : "other"; ++ !isempty(tty) ? "tty" : "unspecified"; + + remote = !isempty(remote_host) && !streq(remote_host, "localhost") && !streq(remote_host, "localhost.localdomain"); + +-- +1.7.7 + + +From 1a4459d63323cdfdb8751077e555ddbbf80564b1 Mon Sep 17 00:00:00 2001 +From: Michal Schmidt +Date: Sat, 19 Nov 2011 01:17:46 +0100 +Subject: [PATCH 2/2] pam-module: treat "cron" in PAM_TTY as empty tty + +cron sets PAM_TTY to "cron" and it has been doing it for a long time. +It cannot be changed because user configurations may depend on it. + +https://bugzilla.redhat.com/show_bug.cgi?id=727315 +--- + src/logind-session.c | 4 ++-- + src/pam-module.c | 4 ++++ + 2 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/src/logind-session.c b/src/logind-session.c +index b0a09e3..63ee758 100644 +--- a/src/logind-session.c ++++ b/src/logind-session.c +@@ -536,7 +536,7 @@ int session_start(Session *s) { + if (r < 0) + return r; + +- log_full(s->display || s->tty ? LOG_INFO : LOG_DEBUG, ++ log_full(s->type == SESSION_TTY || s->type == SESSION_X11 ? LOG_INFO : LOG_DEBUG, + "New session %s of user %s.", s->id, s->user->name); + + /* Create cgroup */ +@@ -659,7 +659,7 @@ int session_stop(Session *s) { + assert(s); + + if (s->started) +- log_full(s->display || s->tty ? LOG_INFO : LOG_DEBUG, ++ log_full(s->type == SESSION_TTY || s->type == SESSION_X11 ? LOG_INFO : LOG_DEBUG, + "Removed session %s.", s->id); + + /* Kill cgroup */ +diff --git a/src/pam-module.c b/src/pam-module.c +index e650886..46b7bec 100644 +--- a/src/pam-module.c ++++ b/src/pam-module.c +@@ -463,6 +463,10 @@ _public_ PAM_EXTERN int pam_sm_open_session( + if (isempty(display)) + display = tty; + tty = ""; ++ } else if (streq(tty, "cron")) { ++ /* cron has been setting PAM_TTY to "cron" for a very long time ++ * and it cannot stop doing that for compatibility reasons. */ ++ tty = ""; + } + + if (!isempty(cvtnr)) +-- +1.7.7 + diff --git a/crypt-loop-file.patch b/crypt-loop-file.patch new file mode 100644 index 00000000..7869601b --- /dev/null +++ b/crypt-loop-file.patch @@ -0,0 +1,76 @@ +Index: systemd-37/src/cryptsetup-generator.c +=================================================================== +--- systemd-37.orig/src/cryptsetup-generator.c ++++ systemd-37/src/cryptsetup-generator.c +@@ -138,7 +138,7 @@ static int create_disk( + const char *password, + const char *options) { + +- char *p = NULL, *n = NULL, *d = NULL, *u = NULL, *from = NULL, *to = NULL, *e = NULL; ++ char *p = NULL, *n = NULL, *d = NULL, *u = NULL, *from = NULL, *to = NULL, *e = NULL, *path_file = NULL; + int r; + FILE *f = NULL; + bool noauto, nofail; +@@ -167,10 +167,50 @@ static int create_disk( + goto fail; + } + +- if (!(d = unit_name_from_path(u, ".device"))) { +- r = -ENOMEM; +- log_error("Failed to allocate device name."); +- goto fail; ++ if (!startswith(device,"/dev/")) { ++ ++ if (!(d = unit_name_build_escape("cryptsetup", name, ".path"))) { ++ r = -ENOMEM; ++ log_error("Failed to allocate path name."); ++ goto fail; ++ } ++ ++ if (asprintf(&path_file, "%s/%s", arg_dest, d) < 0) { ++ r = -ENOMEM; ++ log_error("Failed to allocate unit file name."); ++ goto fail; ++ } ++ ++ if (!(f = fopen(path_file, "wxe"))) { ++ r = -errno; ++ log_error("Failed to create unit file: %m"); ++ goto fail; ++ } ++ ++ fprintf(f, ++ "[Unit]\n" ++ "Description=Cryptography Setup for %s\n" ++ "DefaultDependencies=no\n" ++ "[Path]\n" ++ "PathExists=%s\n", ++ device, device); ++ ++ fflush(f); ++ ++ if (ferror(f)) { ++ r = -errno; ++ log_error("Failed to write file: %m"); ++ goto fail; ++ } ++ ++ f = NULL; ++ } else { ++ ++ if (!(d = unit_name_from_path(u, ".device"))) { ++ r = -ENOMEM; ++ log_error("Failed to allocate device name."); ++ goto fail; ++ } + } + + if (!(f = fopen(p, "wxe"))) { +@@ -300,6 +340,7 @@ fail: + free(n); + free(d); + free(e); ++ free(path_file); + + free(from); + free(to); diff --git a/delay-fsck-cryptsetup-after-md-lvm-dmraid.patch b/delay-fsck-cryptsetup-after-md-lvm-dmraid.patch new file mode 100644 index 00000000..403c9ed0 --- /dev/null +++ b/delay-fsck-cryptsetup-after-md-lvm-dmraid.patch @@ -0,0 +1,38 @@ +From c6170719e7afbcecc04e8939e93e9678529e6391 Mon Sep 17 00:00:00 2001 +From: Frederic Crozat +Date: Wed, 9 Nov 2011 11:10:49 +0100 +Subject: [PATCH] delay fsck / cryptsetup after md / dmraid / lvm are started + +--- + src/cryptsetup-generator.c | 1 + + units/fsck@.service.in | 2 +- + 2 files changed, 2 insertions(+), 1 deletions(-) + +diff --git a/src/cryptsetup-generator.c b/src/cryptsetup-generator.c +index 14fcce8..e62f0e0 100644 +--- a/src/cryptsetup-generator.c ++++ b/src/cryptsetup-generator.c +@@ -186,6 +186,7 @@ static int create_disk( + "DefaultDependencies=no\n" + "BindTo=%s dev-mapper-%%i.device\n" + "After=systemd-readahead-collect.service systemd-readahead-replay.service %s\n" ++ "After=md.service dmraid.service lvm.service\n" + "Before=umount.target\n", + d, d); + +diff --git a/units/fsck@.service.in b/units/fsck@.service.in +index e1f7736..c1870ce 100644 +--- a/units/fsck@.service.in ++++ b/units/fsck@.service.in +@@ -9,7 +9,7 @@ + Description=File System Check on %f + DefaultDependencies=no + BindTo=%i.device +-After=systemd-readahead-collect.service systemd-readahead-replay.service %i.device ++After=systemd-readahead-collect.service systemd-readahead-replay.service %i.device lvm.service md.service dmraid.service + Before=shutdown.target + + [Service] +-- +1.7.7 + diff --git a/do_not_warn_pidfile.patch b/do_not_warn_pidfile.patch new file mode 100644 index 00000000..83002c89 --- /dev/null +++ b/do_not_warn_pidfile.patch @@ -0,0 +1,60 @@ +From c5419d4239ceb4c3bd0263a0a810cf24a072b3c0 Mon Sep 17 00:00:00 2001 +From: Michal Schmidt +Date: Thu, 10 Nov 2011 09:55:47 +0100 +Subject: [PATCH] service: don't warn if the pidfile still exists after + SIGCHLD + +A service that drops its privileges may not be able to remove it when it +exits. The stale pidfile is not a problem as long as the service +carefully recognizes it on its next start. + +systemd would produce a warning after the service exits: + PID ... read from file ... does not exist. Your service or init + script might be broken. + +Silence the warning in this case. Still warn if this error is detected +when loading the pidfile after service start. + +Noticed by Miroslav Lichvar in + https://bugzilla.redhat.com/show_bug.cgi?id=752396 +--- + src/service.c | 9 +++++---- + 1 files changed, 5 insertions(+), 4 deletions(-) + +diff --git a/src/service.c b/src/service.c +index eb475d9..6fc2484 100644 +--- a/src/service.c ++++ b/src/service.c +@@ -1290,7 +1290,7 @@ static void service_dump(Unit *u, FILE *f, const char *prefix) { + free(p2); + } + +-static int service_load_pid_file(Service *s, bool warn_if_missing) { ++static int service_load_pid_file(Service *s, bool may_warn) { + char *k; + int r; + pid_t pid; +@@ -1301,7 +1301,7 @@ static int service_load_pid_file(Service *s, bool warn_if_missing) { + return -ENOENT; + + if ((r = read_one_line_file(s->pid_file, &k)) < 0) { +- if (warn_if_missing) ++ if (may_warn) + log_warning("Failed to read PID file %s after %s. The service might be broken.", + s->pid_file, service_state_to_string(s->state)); + return r; +@@ -1314,8 +1314,9 @@ static int service_load_pid_file(Service *s, bool warn_if_missing) { + return r; + + if (kill(pid, 0) < 0 && errno != EPERM) { +- log_warning("PID %lu read from file %s does not exist. Your service or init script might be broken.", +- (unsigned long) pid, s->pid_file); ++ if (may_warn) ++ log_warning("PID %lu read from file %s does not exist. Your service or init script might be broken.", ++ (unsigned long) pid, s->pid_file); + return -ESRCH; + } + +-- +1.7.7 + diff --git a/garbage_collect_units.patch b/garbage_collect_units.patch new file mode 100644 index 00000000..3ea2bd2e --- /dev/null +++ b/garbage_collect_units.patch @@ -0,0 +1,29 @@ +From 9a46fc3b9014de1bf0ed1f3004a536b08a19ebb3 Mon Sep 17 00:00:00 2001 +From: Michal Schmidt +Date: Tue, 6 Dec 2011 00:47:28 +0100 +Subject: [PATCH] unit: garbage collect units with load error + +Units that failed to load were never cleaned up. It was possible to +reach the 128K limit of units by attempting to load a bunch of nonsense. + +Bug observed by Reartes Guillermo in +https://bugzilla.redhat.com/show_bug.cgi?id=680122 +--- + src/unit.c | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/src/unit.c b/src/unit.c +index 2a549e2..018e986 100644 +--- a/src/unit.c ++++ b/src/unit.c +@@ -858,6 +858,7 @@ fail: + u->meta.load_state = UNIT_ERROR; + u->meta.load_error = r; + unit_add_to_dbus_queue(u); ++ unit_add_to_gc_queue(u); + + log_debug("Failed to load configuration for %s: %s", u->meta.id, strerror(-r)); + +-- +1.7.7 + diff --git a/handle-racy-daemon.patch b/handle-racy-daemon.patch new file mode 100644 index 00000000..4a8a07f1 --- /dev/null +++ b/handle-racy-daemon.patch @@ -0,0 +1,1066 @@ +From 35d50f55f346c71fd5e957d35ebcae1c50b1f9ce Mon Sep 17 00:00:00 2001 +From: Michal Schmidt +Date: Sat, 3 Dec 2011 00:41:34 +0100 +Subject: [PATCH 1/5] util: fix error checking after fgets() + +fgets() does not set errno on EOF. +--- + src/util.c | 8 ++++---- + 1 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/util.c b/src/util.c +index e93e6f6..da71e4d 100644 +--- a/src/util.c ++++ b/src/util.c +@@ -516,7 +516,7 @@ int get_parent_of_pid(pid_t pid, pid_t *_ppid) { + return -errno; + + if (!(fgets(line, sizeof(line), f))) { +- r = -errno; ++ r = feof(f) ? -EIO : -errno; + fclose(f); + return r; + } +@@ -561,7 +561,7 @@ int get_starttime_of_pid(pid_t pid, unsigned long long *st) { + return -errno; + + if (!(fgets(line, sizeof(line), f))) { +- r = -errno; ++ r = feof(f) ? -EIO : -errno; + fclose(f); + return r; + } +@@ -708,7 +708,7 @@ int read_one_line_file(const char *fn, char **line) { + return -errno; + + if (!(fgets(t, sizeof(t), f))) { +- r = -errno; ++ r = feof(f) ? -EIO : -errno; + goto finish; + } + +@@ -3266,7 +3266,7 @@ int get_ctty_devnr(pid_t pid, dev_t *d) { + return -errno; + + if (!fgets(line, sizeof(line), f)) { +- k = -errno; ++ k = feof(f) ? -EIO : -errno; + fclose(f); + return k; + } +-- +1.7.7 + + +From 768147d13d0877a4c3e5f6f986c3064de62ff4f1 Mon Sep 17 00:00:00 2001 +From: Michal Schmidt +Date: Sat, 3 Dec 2011 01:36:05 +0100 +Subject: [PATCH 2/5] path: use %m instead of strerror(errno) + +and strerror(-errno) was just wrong. +--- + src/path.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/path.c b/src/path.c +index f15c921..142fd2d 100644 +--- a/src/path.c ++++ b/src/path.c +@@ -556,7 +556,7 @@ static void path_fd_event(Unit *u, int fd, uint32_t events, Watch *w) { + } + + if (ioctl(fd, FIONREAD, &l) < 0) { +- log_error("FIONREAD failed: %s", strerror(errno)); ++ log_error("FIONREAD failed: %m"); + goto fail; + } + +@@ -568,7 +568,7 @@ static void path_fd_event(Unit *u, int fd, uint32_t events, Watch *w) { + } + + if ((k = read(fd, buf, l)) < 0) { +- log_error("Failed to read inotify event: %s", strerror(-errno)); ++ log_error("Failed to read inotify event: %m"); + goto fail; + } + +-- +1.7.7 + + +From 4b562198c79e4ebfc3d84b69a1dae374bc6cf9f5 Mon Sep 17 00:00:00 2001 +From: Michal Schmidt +Date: Sat, 3 Dec 2011 01:38:30 +0100 +Subject: [PATCH 3/5] path: refactor PathSpec usage + +path_*() functions operate on "Path *p" and they do not touch PathSpec +internals directly. + +pathspec_*() functions operate on "PathSpec *s". The PathSpec class will +be useful outside of path.c. +--- + src/path.c | 356 +++++++++++++++++++++++++++++++++--------------------------- + src/path.h | 8 ++ + 2 files changed, 203 insertions(+), 161 deletions(-) + +diff --git a/src/path.c b/src/path.c +index 142fd2d..db6f873 100644 +--- a/src/path.c ++++ b/src/path.c +@@ -39,26 +39,202 @@ static const UnitActiveState state_translation_table[_PATH_STATE_MAX] = { + [PATH_FAILED] = UNIT_FAILED + }; + +-static void path_init(Unit *u) { +- Path *p = PATH(u); ++int pathspec_watch(PathSpec *s, Unit *u) { ++ static const int flags_table[_PATH_TYPE_MAX] = { ++ [PATH_EXISTS] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB, ++ [PATH_EXISTS_GLOB] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB, ++ [PATH_CHANGED] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB|IN_CLOSE_WRITE|IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO, ++ [PATH_DIRECTORY_NOT_EMPTY] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB|IN_CREATE|IN_MOVED_TO ++ }; ++ ++ bool exists = false; ++ char *k, *slash; ++ int r; + + assert(u); +- assert(u->meta.load_state == UNIT_STUB); ++ assert(s); + +- p->directory_mode = 0755; ++ pathspec_unwatch(s, u); ++ ++ if (!(k = strdup(s->path))) ++ return -ENOMEM; ++ ++ if ((s->inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC)) < 0) { ++ r = -errno; ++ goto fail; ++ } ++ ++ if (unit_watch_fd(u, s->inotify_fd, EPOLLIN, &s->watch) < 0) { ++ r = -errno; ++ goto fail; ++ } ++ ++ if ((s->primary_wd = inotify_add_watch(s->inotify_fd, k, flags_table[s->type])) >= 0) ++ exists = true; ++ ++ do { ++ int flags; ++ ++ /* This assumes the path was passed through path_kill_slashes()! */ ++ if (!(slash = strrchr(k, '/'))) ++ break; ++ ++ /* Trim the path at the last slash. Keep the slash if it's the root dir. */ ++ slash[slash == k] = 0; ++ ++ flags = IN_MOVE_SELF; ++ if (!exists) ++ flags |= IN_DELETE_SELF | IN_ATTRIB | IN_CREATE | IN_MOVED_TO; ++ ++ if (inotify_add_watch(s->inotify_fd, k, flags) >= 0) ++ exists = true; ++ } while (slash != k); ++ ++ return 0; ++ ++fail: ++ free(k); ++ ++ pathspec_unwatch(s, u); ++ return r; + } + +-static void path_unwatch_one(Path *p, PathSpec *s) { ++void pathspec_unwatch(PathSpec *s, Unit *u) { + + if (s->inotify_fd < 0) + return; + +- unit_unwatch_fd(UNIT(p), &s->watch); ++ unit_unwatch_fd(u, &s->watch); + + close_nointr_nofail(s->inotify_fd); + s->inotify_fd = -1; + } + ++int pathspec_fd_event(PathSpec *s, uint32_t events) { ++ uint8_t *buf = NULL; ++ struct inotify_event *e; ++ ssize_t k; ++ int l; ++ int r = 0; ++ ++ if (events != EPOLLIN) { ++ log_error("Got Invalid poll event on inotify."); ++ r = -EINVAL; ++ goto out; ++ } ++ ++ if (ioctl(s->inotify_fd, FIONREAD, &l) < 0) { ++ log_error("FIONREAD failed: %m"); ++ r = -errno; ++ goto out; ++ } ++ ++ assert(l > 0); ++ ++ if (!(buf = malloc(l))) { ++ log_error("Failed to allocate buffer: %m"); ++ r = -errno; ++ goto out; ++ } ++ ++ if ((k = read(s->inotify_fd, buf, l)) < 0) { ++ log_error("Failed to read inotify event: %m"); ++ r = -errno; ++ goto out; ++ } ++ ++ e = (struct inotify_event*) buf; ++ ++ while (k > 0) { ++ size_t step; ++ ++ if (s->type == PATH_CHANGED && s->primary_wd == e->wd) ++ r = 1; ++ ++ step = sizeof(struct inotify_event) + e->len; ++ assert(step <= (size_t) k); ++ ++ e = (struct inotify_event*) ((uint8_t*) e + step); ++ k -= step; ++ } ++out: ++ free(buf); ++ return r; ++} ++ ++static bool pathspec_check_good(PathSpec *s, bool initial) { ++ bool good = false; ++ ++ switch (s->type) { ++ ++ case PATH_EXISTS: ++ good = access(s->path, F_OK) >= 0; ++ break; ++ ++ case PATH_EXISTS_GLOB: ++ good = glob_exists(s->path) > 0; ++ break; ++ ++ case PATH_DIRECTORY_NOT_EMPTY: { ++ int k; ++ ++ k = dir_is_empty(s->path); ++ good = !(k == -ENOENT || k > 0); ++ break; ++ } ++ ++ case PATH_CHANGED: { ++ bool b; ++ ++ b = access(s->path, F_OK) >= 0; ++ good = !initial && b != s->previous_exists; ++ s->previous_exists = b; ++ break; ++ } ++ ++ default: ++ ; ++ } ++ ++ return good; ++} ++ ++static bool pathspec_startswith(PathSpec *s, const char *what) { ++ return path_startswith(s->path, what); ++} ++ ++static void pathspec_mkdir(PathSpec *s, mode_t mode) { ++ int r; ++ ++ if (s->type == PATH_EXISTS || s->type == PATH_EXISTS_GLOB) ++ return; ++ ++ if ((r = mkdir_p(s->path, mode)) < 0) ++ log_warning("mkdir(%s) failed: %s", s->path, strerror(-r)); ++} ++ ++static void pathspec_dump(PathSpec *s, FILE *f, const char *prefix) { ++ fprintf(f, ++ "%s%s: %s\n", ++ prefix, ++ path_type_to_string(s->type), ++ s->path); ++} ++ ++void pathspec_done(PathSpec *s) { ++ assert(s->inotify_fd == -1); ++ free(s->path); ++} ++ ++static void path_init(Unit *u) { ++ Path *p = PATH(u); ++ ++ assert(u); ++ assert(u->meta.load_state == UNIT_STUB); ++ ++ p->directory_mode = 0755; ++} ++ + static void path_done(Unit *u) { + Path *p = PATH(u); + PathSpec *s; +@@ -66,9 +242,9 @@ static void path_done(Unit *u) { + assert(p); + + while ((s = p->specs)) { +- path_unwatch_one(p, s); ++ pathspec_unwatch(s, u); + LIST_REMOVE(PathSpec, spec, p->specs, s); +- free(s->path); ++ pathspec_done(s); + free(s); + } + } +@@ -86,7 +262,7 @@ int path_add_one_mount_link(Path *p, Mount *m) { + + LIST_FOREACH(spec, s, p->specs) { + +- if (!path_startswith(s->path, m->where)) ++ if (!pathspec_startswith(s, m->where)) + continue; + + if ((r = unit_add_two_dependencies(UNIT(p), UNIT_AFTER, UNIT_REQUIRES, UNIT(m), true)) < 0) +@@ -187,71 +363,7 @@ static void path_dump(Unit *u, FILE *f, const char *prefix) { + prefix, p->directory_mode); + + LIST_FOREACH(spec, s, p->specs) +- fprintf(f, +- "%s%s: %s\n", +- prefix, +- path_type_to_string(s->type), +- s->path); +-} +- +-static int path_watch_one(Path *p, PathSpec *s) { +- static const int flags_table[_PATH_TYPE_MAX] = { +- [PATH_EXISTS] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB, +- [PATH_EXISTS_GLOB] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB, +- [PATH_CHANGED] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB|IN_CLOSE_WRITE|IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO, +- [PATH_DIRECTORY_NOT_EMPTY] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB|IN_CREATE|IN_MOVED_TO +- }; +- +- bool exists = false; +- char *k, *slash; +- int r; +- +- assert(p); +- assert(s); +- +- path_unwatch_one(p, s); +- +- if (!(k = strdup(s->path))) +- return -ENOMEM; +- +- if ((s->inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC)) < 0) { +- r = -errno; +- goto fail; +- } +- +- if (unit_watch_fd(UNIT(p), s->inotify_fd, EPOLLIN, &s->watch) < 0) { +- r = -errno; +- goto fail; +- } +- +- if ((s->primary_wd = inotify_add_watch(s->inotify_fd, k, flags_table[s->type])) >= 0) +- exists = true; +- +- do { +- int flags; +- +- /* This assumes the path was passed through path_kill_slashes()! */ +- if (!(slash = strrchr(k, '/'))) +- break; +- +- /* Trim the path at the last slash. Keep the slash if it's the root dir. */ +- slash[slash == k] = 0; +- +- flags = IN_MOVE_SELF; +- if (!exists) +- flags |= IN_DELETE_SELF | IN_ATTRIB | IN_CREATE | IN_MOVED_TO; +- +- if (inotify_add_watch(s->inotify_fd, k, flags) >= 0) +- exists = true; +- } while (slash != k); +- +- return 0; +- +-fail: +- free(k); +- +- path_unwatch_one(p, s); +- return r; ++ pathspec_dump(s, f, prefix); + } + + static void path_unwatch(Path *p) { +@@ -260,7 +372,7 @@ static void path_unwatch(Path *p) { + assert(p); + + LIST_FOREACH(spec, s, p->specs) +- path_unwatch_one(p, s); ++ pathspec_unwatch(s, UNIT(p)); + } + + static int path_watch(Path *p) { +@@ -270,7 +382,7 @@ static int path_watch(Path *p) { + assert(p); + + LIST_FOREACH(spec, s, p->specs) +- if ((r = path_watch_one(p, s)) < 0) ++ if ((r = pathspec_watch(s, UNIT(p))) < 0) + return r; + + return 0; +@@ -361,37 +473,7 @@ static bool path_check_good(Path *p, bool initial) { + assert(p); + + LIST_FOREACH(spec, s, p->specs) { +- +- switch (s->type) { +- +- case PATH_EXISTS: +- good = access(s->path, F_OK) >= 0; +- break; +- +- case PATH_EXISTS_GLOB: +- good = glob_exists(s->path) > 0; +- break; +- +- case PATH_DIRECTORY_NOT_EMPTY: { +- int k; +- +- k = dir_is_empty(s->path); +- good = !(k == -ENOENT || k > 0); +- break; +- } +- +- case PATH_CHANGED: { +- bool b; +- +- b = access(s->path, F_OK) >= 0; +- good = !initial && b != s->previous_exists; +- s->previous_exists = b; +- break; +- } +- +- default: +- ; +- } ++ good = pathspec_check_good(s, initial); + + if (good) + break; +@@ -440,15 +522,8 @@ static void path_mkdir(Path *p) { + if (!p->make_directory) + return; + +- LIST_FOREACH(spec, s, p->specs) { +- int r; +- +- if (s->type == PATH_EXISTS || s->type == PATH_EXISTS_GLOB) +- continue; +- +- if ((r = mkdir_p(s->path, p->directory_mode)) < 0) +- log_warning("mkdir(%s) failed: %s", s->path, strerror(-r)); +- } ++ LIST_FOREACH(spec, s, p->specs) ++ pathspec_mkdir(s, p->directory_mode); + } + + static int path_start(Unit *u) { +@@ -525,12 +600,8 @@ static const char *path_sub_state_to_string(Unit *u) { + + static void path_fd_event(Unit *u, int fd, uint32_t events, Watch *w) { + Path *p = PATH(u); +- int l; +- ssize_t k; +- uint8_t *buf = NULL; +- struct inotify_event *e; + PathSpec *s; +- bool changed; ++ int changed; + + assert(p); + assert(fd >= 0); +@@ -541,13 +612,8 @@ static void path_fd_event(Unit *u, int fd, uint32_t events, Watch *w) { + + /* log_debug("inotify wakeup on %s.", u->meta.id); */ + +- if (events != EPOLLIN) { +- log_error("Got Invalid poll event on inotify."); +- goto fail; +- } +- + LIST_FOREACH(spec, s, p->specs) +- if (s->inotify_fd == fd) ++ if (pathspec_owns_inotify_fd(s, fd)) + break; + + if (!s) { +@@ -555,55 +621,23 @@ static void path_fd_event(Unit *u, int fd, uint32_t events, Watch *w) { + goto fail; + } + +- if (ioctl(fd, FIONREAD, &l) < 0) { +- log_error("FIONREAD failed: %m"); +- goto fail; +- } +- +- assert(l > 0); +- +- if (!(buf = malloc(l))) { +- log_error("Failed to allocate buffer: %s", strerror(ENOMEM)); +- goto fail; +- } +- +- if ((k = read(fd, buf, l)) < 0) { +- log_error("Failed to read inotify event: %m"); ++ changed = pathspec_fd_event(s, events); ++ if (changed < 0) + goto fail; +- } + + /* If we are already running, then remember that one event was + * dispatched so that we restart the service only if something + * actually changed on disk */ + p->inotify_triggered = true; + +- e = (struct inotify_event*) buf; +- +- changed = false; +- while (k > 0) { +- size_t step; +- +- if (s->type == PATH_CHANGED && s->primary_wd == e->wd) +- changed = true; +- +- step = sizeof(struct inotify_event) + e->len; +- assert(step <= (size_t) k); +- +- e = (struct inotify_event*) ((uint8_t*) e + step); +- k -= step; +- } +- + if (changed) + path_enter_running(p); + else + path_enter_waiting(p, false, true); + +- free(buf); +- + return; + + fail: +- free(buf); + path_enter_dead(p, false); + } + +diff --git a/src/path.h b/src/path.h +index 116fc63..4e6ccf5 100644 +--- a/src/path.h ++++ b/src/path.h +@@ -60,6 +60,14 @@ typedef struct PathSpec { + + } PathSpec; + ++int pathspec_watch(PathSpec *s, Unit *u); ++void pathspec_unwatch(PathSpec *s, Unit *u); ++int pathspec_fd_event(PathSpec *s, uint32_t events); ++void pathspec_done(PathSpec *s); ++static inline bool pathspec_owns_inotify_fd(PathSpec *s, int fd) { ++ return s->inotify_fd == fd; ++} ++ + struct Path { + Meta meta; + +-- +1.7.7 + + +From e92238567b9fc83ef77e359588d7b005ecae3d70 Mon Sep 17 00:00:00 2001 +From: Michal Schmidt +Date: Sat, 3 Dec 2011 10:22:26 +0100 +Subject: [PATCH 4/5] path: add PathModified (= PathChanged + IN_MODIFY) + +--- + man/systemd.path.xml | 17 ++++++++++------- + src/path.c | 2 ++ + src/path.h | 1 + + 3 files changed, 13 insertions(+), 7 deletions(-) + +diff --git a/man/systemd.path.xml b/man/systemd.path.xml +index 10d8f73..5b1ff75 100644 +--- a/man/systemd.path.xml ++++ b/man/systemd.path.xml +@@ -113,6 +113,7 @@ + PathExists= + PathExistsGlob= + PathChanged= ++ PathModified= + DirectoryNotEmpty= + + Defines paths to +@@ -129,8 +130,14 @@ + specified. PathChanged= + may be used to watch a file or + directory and activate the configured +- unit whenever it changes or is +- modified. DirectoryNotEmpty= ++ unit whenever it changes. It is not activated ++ on every write to the watched file but it is ++ activated if the file which was open for writing ++ gets closed. PathModified= ++ is similar, but additionally it is activated ++ also on simple writes to the watched file. ++ ++ DirectoryNotEmpty= + may be used to watch a directory and + activate the configured unit whenever + it contains at least one file. +@@ -154,11 +161,7 @@ + activated, then the configured unit is + immediately activated as + well. Something similar does not apply +- to +- PathChanged=. The +- latter is not activated on simple +- writes but only if files with were +- opened for writing are closed. ++ to PathChanged=. + + + +diff --git a/src/path.c b/src/path.c +index db6f873..1e5d825 100644 +--- a/src/path.c ++++ b/src/path.c +@@ -44,6 +44,7 @@ int pathspec_watch(PathSpec *s, Unit *u) { + [PATH_EXISTS] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB, + [PATH_EXISTS_GLOB] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB, + [PATH_CHANGED] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB|IN_CLOSE_WRITE|IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO, ++ [PATH_MODIFIED] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB|IN_CLOSE_WRITE|IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO|IN_MODIFY, + [PATH_DIRECTORY_NOT_EMPTY] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB|IN_CREATE|IN_MOVED_TO + }; + +@@ -713,6 +714,7 @@ static const char* const path_type_table[_PATH_TYPE_MAX] = { + [PATH_EXISTS] = "PathExists", + [PATH_EXISTS_GLOB] = "PathExistsGlob", + [PATH_CHANGED] = "PathChanged", ++ [PATH_MODIFIED] = "PathModified", + [PATH_DIRECTORY_NOT_EMPTY] = "DirectoryNotEmpty" + }; + +diff --git a/src/path.h b/src/path.h +index 4e6ccf5..1d78fe4 100644 +--- a/src/path.h ++++ b/src/path.h +@@ -41,6 +41,7 @@ typedef enum PathType { + PATH_EXISTS_GLOB, + PATH_DIRECTORY_NOT_EMPTY, + PATH_CHANGED, ++ PATH_MODIFIED, + _PATH_TYPE_MAX, + _PATH_TYPE_INVALID = -1 + } PathType; +-- +1.7.7 + + +From 3a11183858af30bc9b4e9dac430dd7541deec19b Mon Sep 17 00:00:00 2001 +From: Michal Schmidt +Date: Sat, 3 Dec 2011 02:13:30 +0100 +Subject: [PATCH 5/5] service: handle services with racy daemonization + gracefully + +There are a lot of forking daemons that do not exactly follow the +initialization steps as described in daemon(7). It is common that they +do not bother waiting in the parent process for the child to write the +PID file before exiting. The daemons' developers often do not perceive +this as a bug and they're unwilling to change. + +Currently systemd warns about the missing PID file and falls back to +guessing the main PID. Being not quite deterministic, the guess can be +wrong with bad consequences. If the guessing is disabled, determinism is +achieved at the cost of losing the ability of noticing when the main +process of the service dies. + +As long as it does not negatively affect properly written services, +systemd should strive for compatibility even with services with racy +daemonization. It is possible to provide determinism _and_ main process +supervision to them. + +If the PID file is not there, rather than guessing and considering the +service running immediately after getting the SIGCHLD from the ExecStart +(or ExecStartPost) process, we can keep the service in the activating +state for a bit longer. We can use inotify to wait for the PID file to +appear. Only when it finally does appear and we read a valid PID from +it, we'll move the service to the running state. If the PID file never +appears, the usual timeout kicks in and the service fails. +--- + src/service.c | 175 ++++++++++++++++++++++++++++++++++++++++++++++++++------- + src/service.h | 3 + + 2 files changed, 157 insertions(+), 21 deletions(-) + +diff --git a/src/service.c b/src/service.c +index 6fc2484..07137d2 100644 +--- a/src/service.c ++++ b/src/service.c +@@ -1302,8 +1302,8 @@ static int service_load_pid_file(Service *s, bool may_warn) { + + if ((r = read_one_line_file(s->pid_file, &k)) < 0) { + if (may_warn) +- log_warning("Failed to read PID file %s after %s. The service might be broken.", +- s->pid_file, service_state_to_string(s->state)); ++ log_info("PID file %s not readable (yet?) after %s.", ++ s->pid_file, service_state_to_string(s->state)); + return r; + } + +@@ -1315,8 +1315,8 @@ static int service_load_pid_file(Service *s, bool may_warn) { + + if (kill(pid, 0) < 0 && errno != EPERM) { + if (may_warn) +- log_warning("PID %lu read from file %s does not exist. Your service or init script might be broken.", +- (unsigned long) pid, s->pid_file); ++ log_info("PID %lu read from file %s does not exist.", ++ (unsigned long) pid, s->pid_file); + return -ESRCH; + } + +@@ -1328,7 +1328,8 @@ static int service_load_pid_file(Service *s, bool may_warn) { + (unsigned long) s->main_pid, (unsigned long) pid); + service_unwatch_main_pid(s); + s->main_pid_known = false; +- } ++ } else ++ log_debug("Main PID loaded: %lu", (unsigned long) pid); + + if ((r = service_set_main_pid(s, pid)) < 0) + return r; +@@ -1359,6 +1360,7 @@ static int service_search_main_pid(Service *s) { + if ((pid = cgroup_bonding_search_main_pid_list(s->meta.cgroup_bondings)) <= 0) + return -ENOENT; + ++ log_debug("Main PID guessed: %lu", (unsigned long) pid); + if ((r = service_set_main_pid(s, pid)) < 0) + return r; + +@@ -1451,6 +1453,17 @@ static int service_notify_sockets_dead(Service *s) { + return 0; + } + ++static void service_unwatch_pid_file(Service *s) { ++ if (!s->pid_file_pathspec) ++ return; ++ ++ log_debug("Stopping watch for %s's PID file %s", s->meta.id, s->pid_file_pathspec->path); ++ pathspec_unwatch(s->pid_file_pathspec, UNIT(s)); ++ pathspec_done(s->pid_file_pathspec); ++ free(s->pid_file_pathspec); ++ s->pid_file_pathspec = NULL; ++} ++ + static void service_set_state(Service *s, ServiceState state) { + ServiceState old_state; + assert(s); +@@ -1458,6 +1471,8 @@ static void service_set_state(Service *s, ServiceState state) { + old_state = s->state; + s->state = state; + ++ service_unwatch_pid_file(s); ++ + if (state != SERVICE_START_PRE && + state != SERVICE_START && + state != SERVICE_START_POST && +@@ -2602,6 +2617,95 @@ static bool service_check_snapshot(Unit *u) { + return !s->got_socket_fd; + } + ++static int service_retry_pid_file(Service *s) { ++ int r; ++ ++ assert(s->pid_file); ++ assert(s->state == SERVICE_START || s->state == SERVICE_START_POST); ++ ++ r = service_load_pid_file(s, false); ++ if (r < 0) ++ return r; ++ ++ service_unwatch_pid_file(s); ++ ++ service_enter_running(s, true); ++ return 0; ++} ++ ++static int service_watch_pid_file(Service *s) { ++ int r; ++ ++ log_debug("Setting watch for %s's PID file %s", s->meta.id, s->pid_file_pathspec->path); ++ r = pathspec_watch(s->pid_file_pathspec, UNIT(s)); ++ if (r < 0) ++ goto fail; ++ ++ /* the pidfile might have appeared just before we set the watch */ ++ service_retry_pid_file(s); ++ ++ return 0; ++fail: ++ log_error("Failed to set a watch for %s's PID file %s: %s", ++ s->meta.id, s->pid_file_pathspec->path, strerror(-r)); ++ service_unwatch_pid_file(s); ++ return r; ++} ++ ++static int service_demand_pid_file(Service *s) { ++ PathSpec *ps; ++ ++ assert(s->pid_file); ++ assert(!s->pid_file_pathspec); ++ ++ ps = new0(PathSpec, 1); ++ if (!ps) ++ return -ENOMEM; ++ ++ ps->path = strdup(s->pid_file); ++ if (!ps->path) { ++ free(ps); ++ return -ENOMEM; ++ } ++ ++ path_kill_slashes(ps->path); ++ ++ /* PATH_CHANGED would not be enough. There are daemons (sendmail) that ++ * keep their PID file open all the time. */ ++ ps->type = PATH_MODIFIED; ++ ps->inotify_fd = -1; ++ ++ s->pid_file_pathspec = ps; ++ ++ return service_watch_pid_file(s); ++} ++ ++static void service_fd_event(Unit *u, int fd, uint32_t events, Watch *w) { ++ Service *s = SERVICE(u); ++ ++ assert(s); ++ assert(fd >= 0); ++ assert(s->state == SERVICE_START || s->state == SERVICE_START_POST); ++ assert(s->pid_file_pathspec); ++ assert(pathspec_owns_inotify_fd(s->pid_file_pathspec, fd)); ++ ++ log_debug("inotify event for %s", u->meta.id); ++ ++ if (pathspec_fd_event(s->pid_file_pathspec, events) < 0) ++ goto fail; ++ ++ if (service_retry_pid_file(s) == 0) ++ return; ++ ++ if (service_watch_pid_file(s) < 0) ++ goto fail; ++ ++ return; ++fail: ++ service_unwatch_pid_file(s); ++ service_enter_signal(s, SERVICE_STOP_SIGTERM, false); ++} ++ + static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { + Service *s = SERVICE(u); + bool success; +@@ -2707,7 +2811,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { + success = true; + } + +- log_full(success ? LOG_DEBUG : LOG_NOTICE, ++ log_full(success ? LOG_DEBUG : LOG_NOTICE, + "%s: control process exited, code=%s status=%i", u->meta.id, sigchld_code_to_string(code), status); + s->failure = s->failure || !success; + +@@ -2742,27 +2846,41 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { + case SERVICE_START: + assert(s->type == SERVICE_FORKING); + +- /* Let's try to load the pid +- * file here if we can. We +- * ignore the return value, +- * since the PID file might +- * actually be created by a +- * START_POST script */ +- +- if (success) { +- service_load_pid_file(s, !s->exec_command[SERVICE_EXEC_START_POST]); +- service_search_main_pid(s); ++ if (!success) { ++ service_enter_signal(s, SERVICE_FINAL_SIGTERM, false); ++ break; ++ } + +- service_enter_start_post(s); ++ if (s->pid_file) { ++ /* Let's try to load the pid file here if we can. ++ * The PID file might actually be created by a START_POST ++ * script. In that case don't worry if the loading fails. */ ++ bool has_start_post = !!s->exec_command[SERVICE_EXEC_START_POST]; ++ int r = service_load_pid_file(s, !has_start_post); ++ if (!has_start_post && r < 0) { ++ r = service_demand_pid_file(s); ++ if (r < 0 || !cgroup_good(s)) ++ service_enter_signal(s, SERVICE_FINAL_SIGTERM, false); ++ break; ++ } + } else +- service_enter_signal(s, SERVICE_FINAL_SIGTERM, false); ++ service_search_main_pid(s); + ++ service_enter_start_post(s); + break; + + case SERVICE_START_POST: + if (success) { +- service_load_pid_file(s, true); +- service_search_main_pid(s); ++ if (s->pid_file) { ++ int r = service_load_pid_file(s, true); ++ if (r < 0) { ++ r = service_demand_pid_file(s); ++ if (r < 0 || !cgroup_good(s)) ++ service_enter_stop(s, false); ++ break; ++ } ++ } else ++ service_search_main_pid(s); + } + + s->reload_failure = !success; +@@ -2907,6 +3025,20 @@ static void service_cgroup_notify_event(Unit *u) { + * except when we don't know pid which to expect the + * SIGCHLD for. */ + ++ case SERVICE_START: ++ case SERVICE_START_POST: ++ /* If we were hoping for the daemon to write its PID file, ++ * we can give up now. */ ++ if (s->pid_file_pathspec) { ++ log_warning("%s never wrote its PID file. Failing.", s->meta.id); ++ service_unwatch_pid_file(s); ++ if (s->state == SERVICE_START) ++ service_enter_signal(s, SERVICE_FINAL_SIGTERM, false); ++ else ++ service_enter_stop(s, false); ++ } ++ break; ++ + case SERVICE_RUNNING: + service_enter_running(s, true); + break; +@@ -3216,7 +3348,7 @@ static int service_enumerate(Manager *m) { + r = 0; + + #ifdef TARGET_SUSE +- sysv_facility_in_insserv_conf (m); ++ sysv_facility_in_insserv_conf (m); + #endif + + finish: +@@ -3511,6 +3643,7 @@ const UnitVTable service_vtable = { + + .sigchld_event = service_sigchld_event, + .timer_event = service_timer_event, ++ .fd_event = service_fd_event, + + .reset_failed = service_reset_failed, + +diff --git a/src/service.h b/src/service.h +index e28f74b..15d58cc 100644 +--- a/src/service.h ++++ b/src/service.h +@@ -86,6 +86,8 @@ typedef enum NotifyAccess { + _NOTIFY_ACCESS_INVALID = -1 + } NotifyAccess; + ++typedef struct PathSpec PathSpec; ++ + struct Service { + Meta meta; + +@@ -157,6 +159,7 @@ struct Service { + Set *configured_sockets; + + Watch timer_watch; ++ PathSpec *pid_file_pathspec; + + NotifyAccess notify_access; + }; +-- +1.7.7 + +From 714d943f72417f53bcb98ed45d002aa270e793c4 Mon Sep 17 00:00:00 2001 +From: Michal Schmidt +Date: Thu, 8 Dec 2011 12:09:10 +0100 +Subject: [PATCH] path: add missing pieces for PathModified + +PATH_MODIFIED worked internally for PID files detection, but was unusable +in units. +--- + src/load-fragment-gperf.gperf.m4 | 1 + + src/path.c | 6 ++++-- + 2 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/src/load-fragment-gperf.gperf.m4 b/src/load-fragment-gperf.gperf.m4 +index 84ae28c..35ec005 100644 +--- a/src/load-fragment-gperf.gperf.m4 ++++ b/src/load-fragment-gperf.gperf.m4 +@@ -210,6 +210,7 @@ m4_dnl + Path.PathExists, config_parse_path_spec, 0, 0 + Path.PathExistsGlob, config_parse_path_spec, 0, 0 + Path.PathChanged, config_parse_path_spec, 0, 0 ++Path.PathModified, config_parse_path_spec, 0, 0 + Path.DirectoryNotEmpty, config_parse_path_spec, 0, 0 + Path.Unit, config_parse_path_unit, 0, 0 + Path.MakeDirectory, config_parse_bool, 0, offsetof(Path, make_directory) +diff --git a/src/path.c b/src/path.c +index 1e5d825..3fee247 100644 +--- a/src/path.c ++++ b/src/path.c +@@ -149,7 +149,8 @@ int pathspec_fd_event(PathSpec *s, uint32_t events) { + while (k > 0) { + size_t step; + +- if (s->type == PATH_CHANGED && s->primary_wd == e->wd) ++ if ((s->type == PATH_CHANGED || s->type == PATH_MODIFIED) && ++ s->primary_wd == e->wd) + r = 1; + + step = sizeof(struct inotify_event) + e->len; +@@ -184,7 +185,8 @@ static bool pathspec_check_good(PathSpec *s, bool initial) { + break; + } + +- case PATH_CHANGED: { ++ case PATH_CHANGED: ++ case PATH_MODIFIED: { + bool b; + + b = access(s->path, F_OK) >= 0; +-- +1.7.7 + diff --git a/lock-opensuse.patch b/lock-opensuse.patch new file mode 100644 index 00000000..0fa59df5 --- /dev/null +++ b/lock-opensuse.patch @@ -0,0 +1,16 @@ +Index: systemd-37/tmpfiles.d/legacy.conf +=================================================================== +--- systemd-37.orig/tmpfiles.d/legacy.conf ++++ systemd-37/tmpfiles.d/legacy.conf +@@ -17,6 +17,8 @@ + # On modern systems a BSD file lock is a better choice if + # serialization is needed on those devices. + +-d /run/lock 0755 root root - +-d /run/lock/subsys 0755 root root - +-d /run/lock/lockdev 0775 root lock - ++# changed for openSUSE : only /run/lock should be available ++ ++d /run/lock 0775 root lock - ++#d /run/lock/subsys 0755 root root - ++#d /run/lock/lockdev 0775 root lock - diff --git a/log_on_close.patch b/log_on_close.patch new file mode 100644 index 00000000..eee0eda3 --- /dev/null +++ b/log_on_close.patch @@ -0,0 +1,586 @@ +From 4d8a7798e7f12c6400495cbc4d0ad57ed20ce90a Mon Sep 17 00:00:00 2001 +From: Michal Schmidt +Date: Wed, 16 Nov 2011 23:45:01 +0100 +Subject: [PATCH 1/3] execute: avoid logging to closed fds + +Several functions called from the "sd(EXEC)" process try to log messages +when all the file descriptors are already closed, including the logging +ones. The logging functions do not expect their fds to be closed and +they hit an assertion failure. The failure wants to be logged too, +so there is an infinite recursion, ended by a SIGSEGV. + +When we close all fds, we must let log.c know about it. +--- + src/execute.c | 1 + + src/log.c | 4 ++++ + src/log.h | 1 + + 3 files changed, 6 insertions(+), 0 deletions(-) + +diff --git a/src/execute.c b/src/execute.c +index 250d53a..0651014 100644 +--- a/src/execute.c ++++ b/src/execute.c +@@ -1016,6 +1016,7 @@ int exec_spawn(ExecCommand *command, + /* Close sockets very early to make sure we don't + * block init reexecution because it cannot bind its + * sockets */ ++ log_forget_fds(); + if (close_all_fds(socket_fd >= 0 ? &socket_fd : fds, + socket_fd >= 0 ? 1 : n_fds) < 0) { + r = EXIT_FDS; +diff --git a/src/log.c b/src/log.c +index b8ce122..5c5b734 100644 +--- a/src/log.c ++++ b/src/log.c +@@ -237,6 +237,10 @@ void log_close(void) { + log_close_syslog(); + } + ++void log_forget_fds(void) { ++ console_fd = kmsg_fd = syslog_fd = -1; ++} ++ + void log_set_max_level(int level) { + assert((level & LOG_PRIMASK) == level); + +diff --git a/src/log.h b/src/log.h +index c402afb..9942e3e 100644 +--- a/src/log.h ++++ b/src/log.h +@@ -57,6 +57,7 @@ int log_get_max_level(void); + + int log_open(void); + void log_close(void); ++void log_forget_fds(void); + + void log_close_syslog(void); + void log_close_kmsg(void); +-- +1.7.7 + + +From 9ba353983adc026b75a503c1381f6e5c8062f3e0 Mon Sep 17 00:00:00 2001 +From: Michal Schmidt +Date: Thu, 17 Nov 2011 00:16:22 +0100 +Subject: [PATCH 2/3] execute: make setup_pam() return -errno when possible + +The only caller currently checks if the result is non-zero, +so nothing changes there. +--- + src/execute.c | 8 +++++++- + 1 files changed, 7 insertions(+), 1 deletions(-) + +diff --git a/src/execute.c b/src/execute.c +index 0651014..2039861 100644 +--- a/src/execute.c ++++ b/src/execute.c +@@ -716,6 +716,7 @@ static int setup_pam( + pam_handle_t *handle = NULL; + sigset_t ss, old_ss; + int pam_code = PAM_SUCCESS; ++ int err; + char **e = NULL; + bool close_session = false; + pid_t pam_pid = 0, parent_pid; +@@ -835,6 +836,11 @@ static int setup_pam( + return 0; + + fail: ++ if (pam_code != PAM_SUCCESS) ++ err = -EPERM; /* PAM errors do not map to errno */ ++ else ++ err = -errno; ++ + if (handle) { + if (close_session) + pam_code = pam_close_session(handle, PAM_DATA_SILENT); +@@ -851,7 +857,7 @@ fail: + kill(pam_pid, SIGCONT); + } + +- return EXIT_PAM; ++ return err; + } + #endif + +-- +1.7.7 + + +From 4c2630ebf23b6348174f0bdf1110e90efe45259c Mon Sep 17 00:00:00 2001 +From: Michal Schmidt +Date: Thu, 17 Nov 2011 00:21:16 +0100 +Subject: [PATCH 3/3] execute: log errors from "sd(EXEC)" + +To give the administrator more hints about failures occuring in spawning +of commands than just the exit code, log the strerror. +All fds are closed, so reopen the log. + +Related-to: https://bugzilla.redhat.com/show_bug.cgi?id=752901 +--- + src/execute.c | 138 +++++++++++++++++++++++++++++++++++++++-------------- + src/exit-status.c | 3 + + src/exit-status.h | 3 +- + 3 files changed, 107 insertions(+), 37 deletions(-) + +diff --git a/src/execute.c b/src/execute.c +index 2039861..481725d 100644 +--- a/src/execute.c ++++ b/src/execute.c +@@ -989,7 +989,7 @@ int exec_spawn(ExecCommand *command, + } + + if (pid == 0) { +- int i; ++ int i, err; + sigset_t ss; + const char *username = NULL, *home = NULL; + uid_t uid = (uid_t) -1; +@@ -1015,6 +1015,7 @@ int exec_spawn(ExecCommand *command, + + if (sigemptyset(&ss) < 0 || + sigprocmask(SIG_SETMASK, &ss, NULL) < 0) { ++ err = -errno; + r = EXIT_SIGNAL_MASK; + goto fail_child; + } +@@ -1023,14 +1024,16 @@ int exec_spawn(ExecCommand *command, + * block init reexecution because it cannot bind its + * sockets */ + log_forget_fds(); +- if (close_all_fds(socket_fd >= 0 ? &socket_fd : fds, +- socket_fd >= 0 ? 1 : n_fds) < 0) { ++ err = close_all_fds(socket_fd >= 0 ? &socket_fd : fds, ++ socket_fd >= 0 ? 1 : n_fds); ++ if (err < 0) { + r = EXIT_FDS; + goto fail_child; + } + + if (!context->same_pgrp) + if (setsid() < 0) { ++ err = -errno; + r = EXIT_SETSID; + goto fail_child; + } +@@ -1038,12 +1041,14 @@ int exec_spawn(ExecCommand *command, + if (context->tcpwrap_name) { + if (socket_fd >= 0) + if (!socket_tcpwrap(socket_fd, context->tcpwrap_name)) { ++ err = -EACCES; + r = EXIT_TCPWRAP; + goto fail_child; + } + + for (i = 0; i < (int) n_fds; i++) { + if (!socket_tcpwrap(fds[i], context->tcpwrap_name)) { ++ err = -EACCES; + r = EXIT_TCPWRAP; + goto fail_child; + } +@@ -1059,11 +1064,14 @@ int exec_spawn(ExecCommand *command, + + /* Set up terminal for the question */ + if ((r = setup_confirm_stdio(context, +- &saved_stdin, &saved_stdout))) ++ &saved_stdin, &saved_stdout))) { ++ err = -errno; + goto fail_child; ++ } + + /* Now ask the question. */ + if (!(line = exec_command_line(argv))) { ++ err = -ENOMEM; + r = EXIT_MEMORY; + goto fail_child; + } +@@ -1072,18 +1080,21 @@ int exec_spawn(ExecCommand *command, + free(line); + + if (r < 0 || response == 'n') { ++ err = -ECANCELED; + r = EXIT_CONFIRM; + goto fail_child; + } else if (response == 's') { +- r = 0; ++ err = r = 0; + goto fail_child; + } + + /* Release terminal for the question */ + if ((r = restore_confirm_stdio(context, + &saved_stdin, &saved_stdout, +- &keep_stdin, &keep_stdout))) ++ &keep_stdin, &keep_stdout))) { ++ err = -errno; + goto fail_child; ++ } + } + + /* If a socket is connected to STDIN/STDOUT/STDERR, we +@@ -1091,28 +1102,35 @@ int exec_spawn(ExecCommand *command, + if (socket_fd >= 0) + fd_nonblock(socket_fd, false); + +- if (!keep_stdin) +- if (setup_input(context, socket_fd, apply_tty_stdin) < 0) { ++ if (!keep_stdin) { ++ err = setup_input(context, socket_fd, apply_tty_stdin); ++ if (err < 0) { + r = EXIT_STDIN; + goto fail_child; + } ++ } + +- if (!keep_stdout) +- if (setup_output(context, socket_fd, file_name_from_path(command->path), apply_tty_stdin) < 0) { ++ if (!keep_stdout) { ++ err = setup_output(context, socket_fd, file_name_from_path(command->path), apply_tty_stdin); ++ if (err < 0) { + r = EXIT_STDOUT; + goto fail_child; + } ++ } + +- if (setup_error(context, socket_fd, file_name_from_path(command->path), apply_tty_stdin) < 0) { ++ err = setup_error(context, socket_fd, file_name_from_path(command->path), apply_tty_stdin); ++ if (err < 0) { + r = EXIT_STDERR; + goto fail_child; + } + +- if (cgroup_bondings) +- if (cgroup_bonding_install_list(cgroup_bondings, 0) < 0) { ++ if (cgroup_bondings) { ++ err = cgroup_bonding_install_list(cgroup_bondings, 0); ++ if (err < 0) { + r = EXIT_CGROUP; + goto fail_child; + } ++ } + + if (context->oom_score_adjust_set) { + char t[16]; +@@ -1133,6 +1151,7 @@ int exec_spawn(ExecCommand *command, + + if (write_one_line_file("/proc/self/oom_adj", t) < 0 + && errno != EACCES) { ++ err = -errno; + r = EXIT_OOM_ADJUST; + goto fail_child; + } +@@ -1141,6 +1160,7 @@ int exec_spawn(ExecCommand *command, + + if (context->nice_set) + if (setpriority(PRIO_PROCESS, 0, context->nice) < 0) { ++ err = -errno; + r = EXIT_NICE; + goto fail_child; + } +@@ -1153,6 +1173,7 @@ int exec_spawn(ExecCommand *command, + + if (sched_setscheduler(0, context->cpu_sched_policy | + (context->cpu_sched_reset_on_fork ? SCHED_RESET_ON_FORK : 0), ¶m) < 0) { ++ err = -errno; + r = EXIT_SETSCHEDULER; + goto fail_child; + } +@@ -1160,18 +1181,21 @@ int exec_spawn(ExecCommand *command, + + if (context->cpuset) + if (sched_setaffinity(0, CPU_ALLOC_SIZE(context->cpuset_ncpus), context->cpuset) < 0) { ++ err = -errno; + r = EXIT_CPUAFFINITY; + goto fail_child; + } + + if (context->ioprio_set) + if (ioprio_set(IOPRIO_WHO_PROCESS, 0, context->ioprio) < 0) { ++ err = -errno; + r = EXIT_IOPRIO; + goto fail_child; + } + + if (context->timer_slack_nsec_set) + if (prctl(PR_SET_TIMERSLACK, context->timer_slack_nsec) < 0) { ++ err = -errno; + r = EXIT_TIMERSLACK; + goto fail_child; + } +@@ -1181,36 +1205,45 @@ int exec_spawn(ExecCommand *command, + + if (context->user) { + username = context->user; +- if (get_user_creds(&username, &uid, &gid, &home) < 0) { ++ err = get_user_creds(&username, &uid, &gid, &home); ++ if (err < 0) { + r = EXIT_USER; + goto fail_child; + } + +- if (is_terminal_input(context->std_input)) +- if (chown_terminal(STDIN_FILENO, uid) < 0) { ++ if (is_terminal_input(context->std_input)) { ++ err = chown_terminal(STDIN_FILENO, uid); ++ if (err < 0) { + r = EXIT_STDIN; + goto fail_child; + } ++ } + +- if (cgroup_bondings && context->control_group_modify) +- if (cgroup_bonding_set_group_access_list(cgroup_bondings, 0755, uid, gid) < 0 || +- cgroup_bonding_set_task_access_list(cgroup_bondings, 0644, uid, gid) < 0) { ++ if (cgroup_bondings && context->control_group_modify) { ++ err = cgroup_bonding_set_group_access_list(cgroup_bondings, 0755, uid, gid); ++ if (err >= 0) ++ err = cgroup_bonding_set_task_access_list(cgroup_bondings, 0644, uid, gid); ++ if (err < 0) { + r = EXIT_CGROUP; + goto fail_child; + } ++ } + } + +- if (apply_permissions) +- if (enforce_groups(context, username, gid) < 0) { ++ if (apply_permissions) { ++ err = enforce_groups(context, username, gid); ++ if (err < 0) { + r = EXIT_GROUP; + goto fail_child; + } ++ } + + umask(context->umask); + + #ifdef HAVE_PAM + if (context->pam_name && username) { +- if (setup_pam(context->pam_name, username, context->tty_path, &pam_env, fds, n_fds) != 0) { ++ err = setup_pam(context->pam_name, username, context->tty_path, &pam_env, fds, n_fds); ++ if (err < 0) { + r = EXIT_PAM; + goto fail_child; + } +@@ -1218,6 +1251,7 @@ int exec_spawn(ExecCommand *command, + #endif + if (context->private_network) { + if (unshare(CLONE_NEWNET) < 0) { ++ err = -errno; + r = EXIT_NETWORK; + goto fail_child; + } +@@ -1229,23 +1263,28 @@ int exec_spawn(ExecCommand *command, + strv_length(context->read_only_dirs) > 0 || + strv_length(context->inaccessible_dirs) > 0 || + context->mount_flags != MS_SHARED || +- context->private_tmp) +- if ((r = setup_namespace( +- context->read_write_dirs, +- context->read_only_dirs, +- context->inaccessible_dirs, +- context->private_tmp, +- context->mount_flags)) < 0) ++ context->private_tmp) { ++ err = setup_namespace(context->read_write_dirs, ++ context->read_only_dirs, ++ context->inaccessible_dirs, ++ context->private_tmp, ++ context->mount_flags); ++ if (err < 0) { ++ r = EXIT_NAMESPACE; + goto fail_child; ++ } ++ } + + if (apply_chroot) { + if (context->root_directory) + if (chroot(context->root_directory) < 0) { ++ err = -errno; + r = EXIT_CHROOT; + goto fail_child; + } + + if (chdir(context->working_directory ? context->working_directory : "/") < 0) { ++ err = -errno; + r = EXIT_CHDIR; + goto fail_child; + } +@@ -1256,11 +1295,13 @@ int exec_spawn(ExecCommand *command, + if (asprintf(&d, "%s/%s", + context->root_directory ? context->root_directory : "", + context->working_directory ? context->working_directory : "") < 0) { ++ err = -ENOMEM; + r = EXIT_MEMORY; + goto fail_child; + } + + if (chdir(d) < 0) { ++ err = -errno; + free(d); + r = EXIT_CHDIR; + goto fail_child; +@@ -1271,9 +1312,12 @@ int exec_spawn(ExecCommand *command, + + /* We repeat the fd closing here, to make sure that + * nothing is leaked from the PAM modules */ +- if (close_all_fds(fds, n_fds) < 0 || +- shift_fds(fds, n_fds) < 0 || +- flags_fds(fds, n_fds, context->non_blocking) < 0) { ++ err = close_all_fds(fds, n_fds); ++ if (err >= 0) ++ err = shift_fds(fds, n_fds); ++ if (err >= 0) ++ err = flags_fds(fds, n_fds, context->non_blocking); ++ if (err < 0) { + r = EXIT_FDS; + goto fail_child; + } +@@ -1285,22 +1329,27 @@ int exec_spawn(ExecCommand *command, + continue; + + if (setrlimit(i, context->rlimit[i]) < 0) { ++ err = -errno; + r = EXIT_LIMITS; + goto fail_child; + } + } + +- if (context->capability_bounding_set_drop) +- if (do_capability_bounding_set_drop(context->capability_bounding_set_drop) < 0) { ++ if (context->capability_bounding_set_drop) { ++ err = do_capability_bounding_set_drop(context->capability_bounding_set_drop); ++ if (err < 0) { + r = EXIT_CAPABILITIES; + goto fail_child; + } ++ } + +- if (context->user) +- if (enforce_user(context, uid) < 0) { ++ if (context->user) { ++ err = enforce_user(context, uid); ++ if (err < 0) { + r = EXIT_USER; + goto fail_child; + } ++ } + + /* PR_GET_SECUREBITS is not privileged, while + * PR_SET_SECUREBITS is. So to suppress +@@ -1308,18 +1357,21 @@ int exec_spawn(ExecCommand *command, + * PR_SET_SECUREBITS unless necessary. */ + if (prctl(PR_GET_SECUREBITS) != context->secure_bits) + if (prctl(PR_SET_SECUREBITS, context->secure_bits) < 0) { ++ err = -errno; + r = EXIT_SECUREBITS; + goto fail_child; + } + + if (context->capabilities) + if (cap_set_proc(context->capabilities) < 0) { ++ err = -errno; + r = EXIT_CAPABILITIES; + goto fail_child; + } + } + + if (!(our_env = new0(char*, 7))) { ++ err = -ENOMEM; + r = EXIT_MEMORY; + goto fail_child; + } +@@ -1327,12 +1379,14 @@ int exec_spawn(ExecCommand *command, + if (n_fds > 0) + if (asprintf(our_env + n_env++, "LISTEN_PID=%lu", (unsigned long) getpid()) < 0 || + asprintf(our_env + n_env++, "LISTEN_FDS=%u", n_fds) < 0) { ++ err = -ENOMEM; + r = EXIT_MEMORY; + goto fail_child; + } + + if (home) + if (asprintf(our_env + n_env++, "HOME=%s", home) < 0) { ++ err = -ENOMEM; + r = EXIT_MEMORY; + goto fail_child; + } +@@ -1340,6 +1394,7 @@ int exec_spawn(ExecCommand *command, + if (username) + if (asprintf(our_env + n_env++, "LOGNAME=%s", username) < 0 || + asprintf(our_env + n_env++, "USER=%s", username) < 0) { ++ err = -ENOMEM; + r = EXIT_MEMORY; + goto fail_child; + } +@@ -1348,6 +1403,7 @@ int exec_spawn(ExecCommand *command, + context->std_output == EXEC_OUTPUT_TTY || + context->std_error == EXEC_OUTPUT_TTY) + if (!(our_env[n_env++] = strdup(default_term_for_tty(tty_path(context))))) { ++ err = -ENOMEM; + r = EXIT_MEMORY; + goto fail_child; + } +@@ -1362,11 +1418,13 @@ int exec_spawn(ExecCommand *command, + files_env, + pam_env, + NULL))) { ++ err = -ENOMEM; + r = EXIT_MEMORY; + goto fail_child; + } + + if (!(final_argv = replace_env_argv(argv, final_env))) { ++ err = -ENOMEM; + r = EXIT_MEMORY; + goto fail_child; + } +@@ -1374,9 +1432,17 @@ int exec_spawn(ExecCommand *command, + final_env = strv_env_clean(final_env); + + execve(command->path, final_argv, final_env); ++ err = -errno; + r = EXIT_EXEC; + + fail_child: ++ if (r != 0) { ++ log_open(); ++ log_warning("Failed at step %s spawning %s: %s", ++ exit_status_to_string(r, EXIT_STATUS_SYSTEMD), ++ command->path, strerror(-err)); ++ } ++ + strv_free(our_env); + strv_free(final_env); + strv_free(pam_env); +diff --git a/src/exit-status.c b/src/exit-status.c +index 8ed1a0e..ab8907d 100644 +--- a/src/exit-status.c ++++ b/src/exit-status.c +@@ -119,6 +119,9 @@ const char* exit_status_to_string(ExitStatus status, ExitStatusLevel level) { + + case EXIT_NETWORK: + return "NETWORK"; ++ ++ case EXIT_NAMESPACE: ++ return "NAMESPACE"; + } + } + +diff --git a/src/exit-status.h b/src/exit-status.h +index 3e977b1..44ef879 100644 +--- a/src/exit-status.h ++++ b/src/exit-status.h +@@ -65,7 +65,8 @@ typedef enum ExitStatus { + EXIT_STDERR, + EXIT_TCPWRAP, + EXIT_PAM, +- EXIT_NETWORK ++ EXIT_NETWORK, ++ EXIT_NAMESPACE + + } ExitStatus; + +-- +1.7.7 + diff --git a/modules_on_boot.patch b/modules_on_boot.patch index 929a2caa..5158a716 100644 --- a/modules_on_boot.patch +++ b/modules_on_boot.patch @@ -7,10 +7,10 @@ Subject: [PATCH] module-load: handle SUSE /etc/sysconfig/kernel module list src/modules-load.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 42 insertions(+), 0 deletions(-) -diff --git a/src/modules-load.c b/src/modules-load.c -index 8dd98f7..73ef5f5 100644 ---- a/src/modules-load.c -+++ b/src/modules-load.c +Index: systemd-37/src/modules-load.c +=================================================================== +--- systemd-37.orig/src/modules-load.c ++++ systemd-37/src/modules-load.c @@ -36,6 +36,9 @@ int main(int argc, char *argv[]) { char **arguments = NULL; unsigned n_arguments = 0, n_allocated = 0; @@ -74,6 +74,15 @@ index 8dd98f7..73ef5f5 100644 return r; } --- -1.7.3.4 - +Index: systemd-37/units/systemd-modules-load.service.in +=================================================================== +--- systemd-37.orig/units/systemd-modules-load.service.in ++++ systemd-37/units/systemd-modules-load.service.in +@@ -11,6 +11,7 @@ DefaultDependencies=no + Conflicts=shutdown.target + After=systemd-readahead-collect.service systemd-readahead-replay.service + Before=sysinit.target shutdown.target ++ConditionPathExists=|/etc/sysconfig/kernel + ConditionDirectoryNotEmpty=|/lib/modules-load.d + ConditionDirectoryNotEmpty=|/usr/lib/modules-load.d + ConditionDirectoryNotEmpty=|/usr/local/lib/modules-load.d diff --git a/mount-swap-log.patch b/mount-swap-log.patch new file mode 100644 index 00000000..9117adfe --- /dev/null +++ b/mount-swap-log.patch @@ -0,0 +1,54 @@ +From f6cebb3bd5a00d79c8131637c0f6796a75e6af99 Mon Sep 17 00:00:00 2001 +From: Michal Schmidt +Date: Sat, 19 Nov 2011 02:47:09 +0100 +Subject: [PATCH] let mount and swap units log to the configured defaults + +Related-to: https://bugzilla.redhat.com/show_bug.cgi?id=750032 +--- + src/mount.c | 6 ++++-- + src/swap.c | 5 +++-- + 2 files changed, 7 insertions(+), 4 deletions(-) + +diff --git a/src/mount.c b/src/mount.c +index f9cfe91..47422cc 100644 +--- a/src/mount.c ++++ b/src/mount.c +@@ -68,8 +68,10 @@ static void mount_init(Unit *u) { + + /* The stdio/kmsg bridge socket is on /, in order to avoid a + * dep loop, don't use kmsg logging for -.mount */ +- if (!unit_has_name(u, "-.mount")) +- m->exec_context.std_output = EXEC_OUTPUT_KMSG; ++ if (!unit_has_name(u, "-.mount")) { ++ m->exec_context.std_output = u->meta.manager->default_std_output; ++ m->exec_context.std_error = u->meta.manager->default_std_error; ++ } + + /* We need to make sure that /bin/mount is always called in + * the same process group as us, so that the autofs kernel +diff --git a/src/swap.c b/src/swap.c +index 54a8640..4fa30a3 100644 +--- a/src/swap.c ++++ b/src/swap.c +@@ -74,7 +74,7 @@ static void swap_unset_proc_swaps(Swap *s) { + s->parameters_proc_swaps.what = NULL; + } + +- static void swap_init(Unit *u) { ++static void swap_init(Unit *u) { + Swap *s = SWAP(u); + + assert(s); +@@ -83,7 +83,8 @@ static void swap_unset_proc_swaps(Swap *s) { + s->timeout_usec = DEFAULT_TIMEOUT_USEC; + + exec_context_init(&s->exec_context); +- s->exec_context.std_output = EXEC_OUTPUT_KMSG; ++ s->exec_context.std_output = u->meta.manager->default_std_output; ++ s->exec_context.std_error = u->meta.manager->default_std_error; + + s->parameters_etc_fstab.priority = s->parameters_proc_swaps.priority = s->parameters_fragment.priority = -1; + +-- +1.7.7 + diff --git a/new-lsb-headers.patch b/new-lsb-headers.patch new file mode 100644 index 00000000..7565c00f --- /dev/null +++ b/new-lsb-headers.patch @@ -0,0 +1,65 @@ +Index: systemd-37/src/service.c +=================================================================== +--- systemd-37.orig/src/service.c ++++ systemd-37/src/service.c +@@ -116,6 +116,7 @@ static void service_init(Unit *u) { + #ifdef HAVE_SYSV_COMPAT + s->sysv_start_priority = -1; + s->sysv_start_priority_from_rcnd = -1; ++ s->sysv_remain_after_exit_heuristic = true; + #endif + s->socket_fd = -1; + s->guess_main_pid = true; +@@ -805,6 +806,31 @@ static int service_load_sysv_path(Servic + + } else + state = LSB; ++ } else if (startswith_no_case(t, "PIDFile:")) { ++ char *fn; ++ ++ state = LSB; ++ ++ fn = strstrip(t+8); ++ if (!path_is_absolute(fn)) { ++ log_warning("[%s:%u] PID file not absolute. Ignoring.", path, line); ++ continue; ++ } ++ ++ if (!(fn = strdup(fn))) { ++ r = -ENOMEM; ++ goto finish; ++ } ++ ++ free(s->pid_file); ++ s->pid_file = fn; ++ s->sysv_remain_after_exit_heuristic = false; ++ } else if (startswith_no_case(t, "X-Systemd-RemainAfterExit:")) { ++ char *j; ++ ++ state = LSB; ++ if ((j = strstrip(t+26)) && *j) ++ s->sysv_remain_after_exit_heuristic = !parse_boolean(j); + } + } + } +@@ -2017,7 +2043,7 @@ static void service_enter_running(Servic + if ((main_pid_ok > 0 || (main_pid_ok < 0 && cgroup_ok != 0)) && + (s->bus_name_good || s->type != SERVICE_DBUS)) { + #ifdef HAVE_SYSV_COMPAT +- if (s->sysv_enabled && !s->pid_file) ++ if (s->sysv_enabled && !s->pid_file && s->sysv_remain_after_exit_heuristic) + s->remain_after_exit = false; + #endif + service_set_state(s, SERVICE_RUNNING); +Index: systemd-37/src/service.h +=================================================================== +--- systemd-37.orig/src/service.h ++++ systemd-37/src/service.h +@@ -139,6 +139,7 @@ struct Service { + #ifdef HAVE_SYSV_COMPAT + bool sysv_has_lsb:1; + bool sysv_enabled:1; ++ bool sysv_remain_after_exit_heuristic:1; + int sysv_start_priority_from_rcnd; + int sysv_start_priority; + diff --git a/private_tmp_crash.patch b/private_tmp_crash.patch deleted file mode 100644 index c7bb783b..00000000 --- a/private_tmp_crash.patch +++ /dev/null @@ -1,12 +0,0 @@ -Index: systemd-37/src/namespace.c -=================================================================== ---- systemd-37.orig/src/namespace.c -+++ systemd-37/src/namespace.c -@@ -157,7 +157,6 @@ static int apply_mount(Path *p, const ch - } - - if ((r = mount(what, where, NULL, MS_BIND|MS_REC, NULL)) >= 0) { -- log_debug("Successfully mounted %s to %s", what, where); - - /* The bind mount will always inherit the original - * flags. If we want to set any flag we need diff --git a/raid.patch b/raid.patch new file mode 100644 index 00000000..d2942787 --- /dev/null +++ b/raid.patch @@ -0,0 +1,13 @@ +Index: systemd-37/units/fsck@.service.in +=================================================================== +--- systemd-37.orig/units/fsck@.service.in ++++ systemd-37/units/fsck@.service.in +@@ -9,7 +9,7 @@ + Description=File System Check on %f + DefaultDependencies=no + BindTo=%i.device +-After=systemd-readahead-collect.service systemd-readahead-replay.service %i.device ++After=systemd-readahead-collect.service systemd-readahead-replay.service %i.device md.service dmraid.service lvm.service + Before=shutdown.target + + [Service] diff --git a/storage-after-cryptsetup.patch b/storage-after-cryptsetup.patch new file mode 100644 index 00000000..a317015e --- /dev/null +++ b/storage-after-cryptsetup.patch @@ -0,0 +1,132 @@ +From b9841589cf16950af7d123ecd128b84464d15a1d Mon Sep 17 00:00:00 2001 +From: Frederic Crozat +Date: Mon, 7 Nov 2011 18:04:20 +0100 +Subject: [PATCH] force lvm restart after cryptsetup target is reached + +--- + src/cryptsetup-generator.c | 80 ++++++++++++++++++++++++++++++++++++++++++++ + 1 files changed, 80 insertions(+), 0 deletions(-) + +diff --git a/src/cryptsetup-generator.c b/src/cryptsetup-generator.c +index a48b7a4..14fcce8 100644 +--- a/src/cryptsetup-generator.c ++++ b/src/cryptsetup-generator.c +@@ -22,12 +22,14 @@ + #include + #include + #include ++#include + + #include "log.h" + #include "util.h" + #include "unit-name.h" + + const char *arg_dest = "/tmp"; ++bool random_seed = false; + + static bool has_option(const char *haystack, const char *needle) { + const char *f = haystack; +@@ -58,6 +60,78 @@ static bool has_option(const char *haystack, const char *needle) { + return false; + } + ++static int create_storage_after_cryptsetup (void) { ++ int r; ++ char *to = NULL, *p = NULL; ++ FILE *f = NULL; ++ ++ if (asprintf(&p, "%s/storage-after-cryptsetup.service", arg_dest) < 0) { ++ r = -ENOMEM; ++ log_error("Failed to allocate unit file name."); ++ goto fail; ++ } ++ ++ if (!(f = fopen(p, "wxe"))) { ++ r = -errno; ++ log_error("Failed to create unit file: %m"); ++ goto fail; ++ } ++ ++ fprintf(f, ++ "[Unit]\n" ++ "Description=Restart storage after cryptsetup\n" ++ "DefaultDependencies=no\n" ++ "After=cryptsetup.target\n" ++ "Wants=cryptsetup.target\n" ++ "Before=shutdown.target\n"); ++ if (!random_seed) { ++ fprintf(f, "After=local-fs.target\n"); ++ } ++ ++ fprintf(f, ++ "\n[Service]\n" ++ "RemainAfterExit=true\n" ++ "Type=oneshot\n" ++ "TimeoutSec=0\n" ++ "ExecStart=/bin/systemctl restart lvm.service\n"); ++ ++ fflush(f); ++ ++ if (ferror(f)) { ++ r = -errno; ++ log_error("Failed to write file: %m"); ++ goto fail; ++ } ++ ++ if (asprintf(&to, "%s/local-fs.target.wants/storage-after-cryptsetup.service", arg_dest) < 0) { ++ r = -ENOMEM; ++ goto fail; ++ } ++ ++ mkdir_parents(to, 0755); ++ ++ if (symlink("../storage-after-cryptsetup.service", to) < 0) { ++ log_error("Failed to create symlink ../storage-after-cryptsetup.service to '%s': %m", to); ++ r = -errno; ++ goto fail; ++ } ++ ++ free(to); ++ to = NULL; ++ ++ r = 0; ++ system ("TMPDIR=/run /usr/bin/sed -e 's/\\(After=.*\\) local-fs.target\\(.*\\)/\\1\\2/g' /lib/systemd/system/systemd-random-seed-load.service > /etc/systemd/system/systemd-random-seed-load.service "); ++fail: ++ ++ free(p); ++ free(to); ++ ++ if (f) ++ fclose(f); ++ ++ return r; ++} ++ + static int create_disk( + const char *name, + const char *device, +@@ -122,8 +196,11 @@ static int create_disk( + if (password && (streq(password, "/dev/urandom") || + streq(password, "/dev/random") || + streq(password, "/dev/hw_random"))) ++ { + fprintf(f, + "After=systemd-random-seed-load.service\n"); ++ random_seed = true; ++ } + else + fprintf(f, + "Before=local-fs.target\n"); +@@ -293,6 +370,9 @@ int main(int argc, char *argv[]) { + free(options); + } + ++ if (create_storage_after_cryptsetup () < 0) ++ r = EXIT_FAILURE; ++ + finish: + return r; + } +-- +1.7.7 + diff --git a/storage-after-cryptsetup.service b/storage-after-cryptsetup.service deleted file mode 100644 index d47acc63..00000000 --- a/storage-after-cryptsetup.service +++ /dev/null @@ -1,12 +0,0 @@ -[Unit] -Description=Restart storage after crypsetup -DefaultDependencies=no -Before=local-fs.target shutdown.target -After=cryptsetup.target -Wants=cryptsetup.target - -[Service] -RemainAfterExit=true -Type=oneshot -TimeoutSec=0 -ExecStart=/bin/systemctl restart lvm.service diff --git a/systemd-gtk.changes b/systemd-gtk.changes index cf784743..6127a51d 100644 --- a/systemd-gtk.changes +++ b/systemd-gtk.changes @@ -1,3 +1,36 @@ +------------------------------------------------------------------- +Wed Dec 7 15:15:07 UTC 2011 - fcrozat@suse.com + +- Remove storage-after-cryptsetup.service, add + storage-after-cryptsetup.patch instead to prevent dependency + cycle (bnc#722539). +- Add delay-fsck-cryptsetup-after-md-lvm-dmraid.patch: ensure + fsck/cryptsetup is run after lvm/md/dmraid have landed + (bnc#724912). +- Add cron-tty-pam.patch: Fix cron filling logs (bnc#731358). +- Add do_not_warn_pidfile.patch: Fix PID warning in logs + (bnc#732912). +- Add mount-swap-log.patch: Ensure swap and mount output is + redirected to default log target (rhb#750032). +- Add color-on-boot.patch: ensure colored status are displayed at + boot time. +- Update modules_on_boot.patch to fix bnc#732041. +- Replace private_tmp_crash.patch with log_on_close.patch, better + upstream fix for bnc#699829 and fix bnc#731719. +- Update vconsole patch to fix memleaks and crash (bnc#734527). +- Add handle-racy-daemon.patch: fix warnings with sendmail + (bnc#732912). +- Add new-lsb-headers.patch: support PIDFile: and + X-Systemd-RemainAfterExit: header in initscript (bnc#727771). +- Update bootsplash services to not start if vga= is missing from + cmdline (bnc#727771) +- Add lock-opensuse.patch: disable /var/lock/{subsys,lockdev} and + change default permissions on /var/lock (bnc#733523). +- Add garbage_collect_units: ensure error units are correctly + garbage collected (rhb#680122). +- Add crypt-loop-file.patch: add support for crypt file loop + (bnc#730496). + ------------------------------------------------------------------- Sat Nov 19 15:40:38 UTC 2011 - coolo@suse.com diff --git a/systemd.changes b/systemd.changes index cf784743..6127a51d 100644 --- a/systemd.changes +++ b/systemd.changes @@ -1,3 +1,36 @@ +------------------------------------------------------------------- +Wed Dec 7 15:15:07 UTC 2011 - fcrozat@suse.com + +- Remove storage-after-cryptsetup.service, add + storage-after-cryptsetup.patch instead to prevent dependency + cycle (bnc#722539). +- Add delay-fsck-cryptsetup-after-md-lvm-dmraid.patch: ensure + fsck/cryptsetup is run after lvm/md/dmraid have landed + (bnc#724912). +- Add cron-tty-pam.patch: Fix cron filling logs (bnc#731358). +- Add do_not_warn_pidfile.patch: Fix PID warning in logs + (bnc#732912). +- Add mount-swap-log.patch: Ensure swap and mount output is + redirected to default log target (rhb#750032). +- Add color-on-boot.patch: ensure colored status are displayed at + boot time. +- Update modules_on_boot.patch to fix bnc#732041. +- Replace private_tmp_crash.patch with log_on_close.patch, better + upstream fix for bnc#699829 and fix bnc#731719. +- Update vconsole patch to fix memleaks and crash (bnc#734527). +- Add handle-racy-daemon.patch: fix warnings with sendmail + (bnc#732912). +- Add new-lsb-headers.patch: support PIDFile: and + X-Systemd-RemainAfterExit: header in initscript (bnc#727771). +- Update bootsplash services to not start if vga= is missing from + cmdline (bnc#727771) +- Add lock-opensuse.patch: disable /var/lock/{subsys,lockdev} and + change default permissions on /var/lock (bnc#733523). +- Add garbage_collect_units: ensure error units are correctly + garbage collected (rhb#680122). +- Add crypt-loop-file.patch: add support for crypt file loop + (bnc#730496). + ------------------------------------------------------------------- Sat Nov 19 15:40:38 UTC 2011 - coolo@suse.com diff --git a/systemd.spec b/systemd.spec index 94c5cb89..733be9ee 100644 --- a/systemd.spec +++ b/systemd.spec @@ -62,7 +62,6 @@ Source7: systemd-bootsplash Source8: bootsplash-startup.service Source9: bootsplash-quit.service Source10: bootsplash-shutdown.service -Source11: storage-after-cryptsetup.service Patch1: 0001-Add-bootsplash-handling-for-password-dialogs.patch # handle SUSE specific kbd settings Patch6: 0001-handle-disable_caplock-and-compose_table-and-kbd_rat.patch @@ -72,9 +71,13 @@ Patch10: 0001-service-Fix-dependencies-added-when-parsing-insserv..patch Patch13: 0001-service-flags-sysv-service-with-detected-pid-as-Rema.patch Patch15: support-sysvinit.patch Patch16: modules_on_boot.patch -Patch17: private_tmp_crash.patch Patch18: systemctl-completion-fix.patch Patch19: avoid-random-seed-cycle.patch +Patch22: new-lsb-headers.patch +Patch23: storage-after-cryptsetup.patch +Patch24: delay-fsck-cryptsetup-after-md-lvm-dmraid.patch +Patch31: lock-opensuse.patch +Patch33: crypt-loop-file.patch # Upstream First - Policy: # Never add any patches to this package without the upstream commit id @@ -82,6 +85,13 @@ Patch19: avoid-random-seed-cycle.patch # an exception will be silently removed with the next version update. Patch20: crash-isolating.patch Patch21: no-tmpfs-fsck.patch +Patch25: cron-tty-pam.patch +Patch26: do_not_warn_pidfile.patch +Patch27: mount-swap-log.patch +Patch28: color-on-boot.patch +Patch29: log_on_close.patch +Patch30: handle-racy-daemon.patch +Patch32: garbage_collect_units.patch %description Systemd is a system and service manager, compatible with SysV and LSB @@ -132,11 +142,22 @@ Plymouth integration for systemd %patch13 -p1 %patch15 -p1 %patch16 -p1 -%patch17 -p1 %patch18 -p1 %patch19 -p1 %patch20 -p1 %patch21 -p1 +%patch22 -p1 +%patch23 -p1 +%patch24 -p1 +%patch25 -p1 +%patch26 -p1 +%patch27 -p1 +%patch28 -p1 +%patch29 -p1 +%patch30 -p1 +%patch31 -p1 +%patch32 -p1 +%patch33 -p1 %build autoreconf -fiv @@ -168,12 +189,11 @@ install -m755 %{S:3} -D %{buildroot}%{_sbindir}/systemd-sysv-convert # do not install, code has been fixed, might be useful in the future #install -m755 %{S:5} %{buildroot}/lib/systemd/system-generators install -m755 %{S:7} %{buildroot}/lib/systemd/ -install -m644 %{S:8} %{S:9} %{S:10} %{S:11} %{buildroot}/lib/systemd/system/ +install -m644 %{S:8} %{S:9} %{S:10} %{buildroot}/lib/systemd/system/ ln -s ../bootsplash-startup.service %{buildroot}/lib/systemd/system/basic.target.wants/ ln -s ../bootsplash-quit.service %{buildroot}/lib/systemd/system/multi-user.target.wants/ ln -s ../bootsplash-shutdown.service %{buildroot}/lib/systemd/system/shutdown.target.wants/ ln -s ../bootsplash-shutdown.service %{buildroot}/lib/systemd/system/reboot.target.wants/ -ln -s ../storage-after-cryptsetup.service %{buildroot}/lib/systemd/system/local-fs.target.wants/ ln -s ../bin/systemd %{buildroot}/sbin/init ln -s ../bin/systemctl %{buildroot}/sbin/reboot ln -s ../bin/systemctl %{buildroot}/sbin/halt