diff options
-rw-r--r-- | Makefile-man.am | 5 | ||||
-rw-r--r-- | Makefile.am | 9 | ||||
-rw-r--r-- | catalog/systemd.ru.catalog.in | 27 | ||||
-rw-r--r-- | man/systemd-mount.xml | 20 | ||||
-rw-r--r-- | man/systemd-suspend.service.xml | 6 | ||||
-rw-r--r-- | src/core/timer.c | 2 | ||||
-rw-r--r-- | src/libsystemd/sd-event/sd-event.c | 7 | ||||
-rw-r--r-- | src/mount/mount-tool.c | 100 | ||||
-rw-r--r-- | src/run/run.c | 77 | ||||
-rw-r--r-- | src/shared/ptyfwd.c | 30 | ||||
-rw-r--r-- | src/shared/ptyfwd.h | 2 | ||||
-rw-r--r-- | src/shared/seccomp-util.c | 4 | ||||
-rw-r--r-- | src/test/test-af-list.c | 1 | ||||
-rw-r--r-- | src/test/test-arphrd-list.c | 1 |
14 files changed, 255 insertions, 36 deletions
diff --git a/Makefile-man.am b/Makefile-man.am index c47bedd0df..6f59658445 100644 --- a/Makefile-man.am +++ b/Makefile-man.am @@ -481,6 +481,7 @@ MANPAGES_ALIAS += \ man/systemd-udevd-control.socket.8 \ man/systemd-udevd-kernel.socket.8 \ man/systemd-udevd.8 \ + man/systemd-umount.1 \ man/systemd-update-done.8 \ man/systemd-user.conf.5 \ man/systemd-volatile-root.8 \ @@ -837,6 +838,7 @@ man/systemd-tmpfiles-setup.service.8: man/systemd-tmpfiles.8 man/systemd-udevd-control.socket.8: man/systemd-udevd.service.8 man/systemd-udevd-kernel.socket.8: man/systemd-udevd.service.8 man/systemd-udevd.8: man/systemd-udevd.service.8 +man/systemd-umount.1: man/systemd-mount.1 man/systemd-update-done.8: man/systemd-update-done.service.8 man/systemd-user.conf.5: man/systemd-system.conf.5 man/systemd-volatile-root.8: man/systemd-volatile-root.service.8 @@ -1787,6 +1789,9 @@ man/systemd-udevd-kernel.socket.html: man/systemd-udevd.service.html man/systemd-udevd.html: man/systemd-udevd.service.html $(html-alias) +man/systemd-umount.html: man/systemd-mount.html + $(html-alias) + man/systemd-update-done.html: man/systemd-update-done.service.html $(html-alias) diff --git a/Makefile.am b/Makefile.am index c87c547e05..9a435e3a66 100644 --- a/Makefile.am +++ b/Makefile.am @@ -673,6 +673,15 @@ EXTRA_DIST += \ @INTLTOOL_POLICY_RULE@ +systemd-mount-install-hook: + -$(LN_S) systemd-mount $(DESTDIR)$(bindir)/systemd-umount + +systemd-mount-uninstall-hook: + -rm $(DESTDIR)$(bindir)/systemd-umount + +INSTALL_EXEC_HOOKS += systemd-mount-install-hook +UNINSTALL_EXEC_HOOKS += systemd-mount-uninstall-hook + # ------------------------------------------------------------------------------ MANPAGES = diff --git a/catalog/systemd.ru.catalog.in b/catalog/systemd.ru.catalog.in index df55478592..3ee1ed63c0 100644 --- a/catalog/systemd.ru.catalog.in +++ b/catalog/systemd.ru.catalog.in @@ -1,7 +1,7 @@ # This file is part of systemd. # # Copyright 2012 Lennart Poettering -# Copyright 2013-2016 Sergey Ptashnick +# Copyright 2013-2017 Sergey Ptashnick # # 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 @@ -102,6 +102,18 @@ Documentation: man:core(5) Вероятно, это произошло из-за ошибки, допущенной в коде программы. Рекомендуется сообщить её разработчикам о возникшей проблеме. +# Subject: Core file was truncated to @SIZE_LIMIT@ bytes +-- 5aadd8e954dc4b1a8c954d63fd9e1137 +Subject: Файл с дампом памяти был урезан до @SIZE_LIMIT@ байт +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:coredump.conf(5) + +Объем памяти процесса превысил ограничения на размер дампа, установленные +для systemd-coredump(8). Записаны только первые @SIZE_LIMIT@ байт. Не исключено, +что этот дамп еще пригоден для анализа, хотя инструменты для анализа +дампов (например, gdb(1)) могут выдать предупреждение, что файл был урезан. + # Subject: A new session @SESSION_ID@ has been created for user @USER_ID@ -- 8d45620c1a4348dbb17410da57c60c66 Subject: Для пользователя @USER_ID@ создан новый сеанс @SESSION_ID@ @@ -175,6 +187,19 @@ Support: %SUPPORT_URL% Запуск системных служб занял @USERSPACE_USEC@ микросекунд. +# Subject: User manager start-up is now complete +-- eed00a68ffd84e31882105fd973abdd1 +Subject: Завершен запуск менеджера пользовательского сеанса +Defined-By: systemd +Support: %SUPPORT_URL% + +Менеджер пользовательского сеанса для пользователя с идентификатором @_UID@ +был запущен. Все службы, стоявшие в очереди на запуск, также были запущены. Тем +не менее, прочие службы могут все еще находиться в процессе запуска, либо могут +быть запущены позднее. + +Запуск менеджера занял @USERSPACE_USEC@ микросекунд. + # Subject: System sleep state @SLEEP@ entered -- 6bbd95ee977941e497c48be27c254128 Subject: Система перешла в состояние сна (@SLEEP@) diff --git a/man/systemd-mount.xml b/man/systemd-mount.xml index 06b7c85bd8..ab85dc5640 100644 --- a/man/systemd-mount.xml +++ b/man/systemd-mount.xml @@ -45,7 +45,8 @@ <refnamediv> <refname>systemd-mount</refname> - <refpurpose>Establish a mount or auto-mount point transiently</refpurpose> + <refname>systemd-umount</refname> + <refpurpose>Establish and destroy transient mount or auto-mount points</refpurpose> </refnamediv> <refsynopsisdiv> @@ -60,6 +61,11 @@ <arg choice="opt" rep="repeat"><replaceable>OPTIONS</replaceable></arg> <arg choice="plain"><option>--list</option></arg> </cmdsynopsis> + <cmdsynopsis> + <command>systemd-umount</command> + <arg choice="opt" rep="repeat"><replaceable>OPTIONS</replaceable></arg> + <arg choice="plain" rep="repeat"><replaceable>WHERE</replaceable></arg> + </cmdsynopsis> </refsynopsisdiv> <refsect1> @@ -91,6 +97,9 @@ <para>Use the <option>--list</option> command to show a terse table of all local, known block devices with file systems that may be mounted with this command.</para> + + <para><command>systemd-umount</command> can be used to unmount a mount or automount point. It is the same + as <command>systemd-mount</command> <option>--unmount</option>.</para> </refsect1> <refsect1> @@ -239,6 +248,15 @@ such as labels, etc.</para></listitem> </varlistentry> + <varlistentry> + <term><option>-u</option></term> + <term><option>--unmount</option></term> + + <listitem><para>Stop the mount and automount units corresponding to the specified mount points + <replaceable>WHERE</replaceable>.</para> + </listitem> + </varlistentry> + <xi:include href="user-system-options.xml" xpointer="user" /> <xi:include href="user-system-options.xml" xpointer="system" /> <xi:include href="user-system-options.xml" xpointer="host" /> diff --git a/man/systemd-suspend.service.xml b/man/systemd-suspend.service.xml index a8beb86f4d..c7733f2885 100644 --- a/man/systemd-suspend.service.xml +++ b/man/systemd-suspend.service.xml @@ -89,8 +89,10 @@ <para>Note that scripts or binaries dropped in <filename>/usr/lib/systemd/system-sleep/</filename> are intended for local use only and should be considered hacks. If applications - want to be notified of system suspend/hibernation and resume, - there are much nicer interfaces available.</para> + want to react to system suspend/hibernation and resume, + they should rather use the <ulink + url="http://www.freedesktop.org/wiki/Software/systemd/inhibit">Inhibitor + interface</ulink>.</para> <para>Note that <filename>systemd-suspend.service</filename>, diff --git a/src/core/timer.c b/src/core/timer.c index d7441d638f..af67b7591a 100644 --- a/src/core/timer.c +++ b/src/core/timer.c @@ -350,7 +350,7 @@ static void add_random(Timer *t, usec_t *v) { else *v += add; - log_unit_info(UNIT(t), "Adding %s random time.", format_timespan(s, sizeof(s), add, 0)); + log_unit_debug(UNIT(t), "Adding %s random time.", format_timespan(s, sizeof(s), add, 0)); } static void timer_enter_waiting(Timer *t, bool initial) { diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c index f94959adac..4816bd1f67 100644 --- a/src/libsystemd/sd-event/sd-event.c +++ b/src/libsystemd/sd-event/sd-event.c @@ -2226,11 +2226,16 @@ static int process_signal(sd_event *e, struct signal_data *d, uint32_t events) { } static int source_dispatch(sd_event_source *s) { + EventSourceType saved_type; int r = 0; assert(s); assert(s->pending || s->type == SOURCE_EXIT); + /* Save the event source type, here, so that we still know it after the event callback which might invalidate + * the event. */ + saved_type = s->type; + if (s->type != SOURCE_DEFER && s->type != SOURCE_EXIT) { r = source_set_pending(s, false); if (r < 0) @@ -2318,7 +2323,7 @@ static int source_dispatch(sd_event_source *s) { if (r < 0) log_debug_errno(r, "Event source %s (type %s) returned error, disabling: %m", - strna(s->description), event_source_type_to_string(s->type)); + strna(s->description), event_source_type_to_string(saved_type)); if (s->n_ref == 0) source_free(s); diff --git a/src/mount/mount-tool.c b/src/mount/mount-tool.c index 9d79e81918..a277724029 100644 --- a/src/mount/mount-tool.c +++ b/src/mount/mount-tool.c @@ -40,6 +40,7 @@ enum { ACTION_DEFAULT, ACTION_MOUNT, ACTION_AUTOMOUNT, + ACTION_UMOUNT, ACTION_LIST, } arg_action = ACTION_DEFAULT; @@ -99,6 +100,7 @@ static void help(void) { " Set automount unit property\n" " --bind-device Bind automount unit to device\n" " --list List mountable block devices\n" + " -u --umount Unmount mount points\n" , program_invocation_short_name); } @@ -144,6 +146,8 @@ static int parse_argv(int argc, char *argv[]) { { "automount-property", required_argument, NULL, ARG_AUTOMOUNT_PROPERTY }, { "bind-device", no_argument, NULL, ARG_BIND_DEVICE }, { "list", no_argument, NULL, ARG_LIST }, + { "umount", no_argument, NULL, 'u' }, + { "unmount", no_argument, NULL, 'u' }, {}, }; @@ -152,7 +156,10 @@ static int parse_argv(int argc, char *argv[]) { assert(argc >= 0); assert(argv); - while ((c = getopt_long(argc, argv, "hqH:M:t:o:p:A", options, NULL)) >= 0) + if (strstr(program_invocation_short_name, "systemd-umount")) + arg_action = ACTION_UMOUNT; + + while ((c = getopt_long(argc, argv, "hqH:M:t:o:p:Au", options, NULL)) >= 0) switch (c) { @@ -263,6 +270,10 @@ static int parse_argv(int argc, char *argv[]) { arg_action = ACTION_LIST; break; + case 'u': + arg_action = ACTION_UMOUNT; + break; + case '?': return -EINVAL; @@ -607,6 +618,89 @@ static int start_transient_automount( return 0; } +static int stop_mount( + sd_bus *bus, + char **argv, + const char *suffix) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL; + _cleanup_free_ char *mount_unit = NULL; + int r; + + if (!arg_no_block) { + r = bus_wait_for_jobs_new(bus, &w); + if (r < 0) + return log_error_errno(r, "Could not watch jobs: %m"); + } + + r = unit_name_from_path(arg_mount_where, suffix, &mount_unit); + if (r < 0) + return log_error_errno(r, "Failed to make mount unit name: %m"); + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "StopUnit"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password); + if (r < 0) + return bus_log_create_error(r); + + /* Name and mode */ + r = sd_bus_message_append(m, "ss", mount_unit, "fail"); + if (r < 0) + return bus_log_create_error(r); + + polkit_agent_open_if_enabled(); + + r = sd_bus_call(bus, m, 0, &error, &reply); + if (r < 0) + return log_error_errno(r, "Failed to stop mount unit: %s", bus_error_message(&error, r)); + + if (w) { + const char *object; + + r = sd_bus_message_read(reply, "o", &object); + if (r < 0) + return bus_log_parse_error(r); + + r = bus_wait_for_jobs_one(w, object, arg_quiet); + if (r < 0) + return r; + } + + if (!arg_quiet) + log_info("Stopped unit %s%s%s for mount point: %s%s%s", + ansi_highlight(), mount_unit, ansi_normal(), + ansi_highlight(), arg_mount_where, ansi_normal()); + + return 0; +} + +static int stop_mounts( + sd_bus *bus, + char **argv) { + + int r; + + r = stop_mount(bus, argv + optind, ".mount"); + if (r < 0) + return r; + + r = stop_mount(bus, argv + optind, ".automount"); + if (r < 0) + return r; + + return 0; +} + static int acquire_mount_type(struct udev_device *d) { const char *v; @@ -1093,6 +1187,10 @@ int main(int argc, char* argv[]) { r = start_transient_automount(bus, argv + optind); break; + case ACTION_UMOUNT: + r = stop_mounts(bus, argv + optind); + break; + default: assert_not_reached("Unexpected action."); } diff --git a/src/run/run.c b/src/run/run.c index 99f03465b0..08f7e12336 100644 --- a/src/run/run.c +++ b/src/run/run.c @@ -403,6 +403,11 @@ static int parse_argv(int argc, char *argv[]) { return -EINVAL; } + if (arg_pty && arg_no_block) { + log_error("--pty is not compatible with --no-block."); + return -EINVAL; + } + if (arg_scope && with_timer()) { log_error("Timer options are not supported in --scope mode."); return -EINVAL; @@ -784,21 +789,23 @@ static void run_context_free(RunContext *c) { } static void run_context_check_done(RunContext *c) { - bool done = true; + bool done; assert(c); if (c->match) - done = done && (c->active_state && STR_IN_SET(c->active_state, "inactive", "failed")); + done = STRPTR_IN_SET(c->active_state, "inactive", "failed"); + else + done = true; - if (c->forward) - done = done && pty_forward_is_done(c->forward); + if (c->forward && done) /* If the service is gone, it's time to drain the output */ + done = pty_forward_drain(c->forward); if (done) sd_event_exit(c->event, EXIT_SUCCESS); } -static int on_properties_changed(sd_bus_message *m, void *userdata, sd_bus_error *error) { +static int run_context_update(RunContext *c, const char *path) { static const struct bus_properties_map map[] = { { "ActiveState", "s", NULL, offsetof(RunContext, active_state) }, @@ -811,12 +818,11 @@ static int on_properties_changed(sd_bus_message *m, void *userdata, sd_bus_error {} }; - RunContext *c = userdata; int r; r = bus_map_all_properties(c->bus, "org.freedesktop.systemd1", - sd_bus_message_get_path(m), + path, map, c); if (r < 0) { @@ -828,6 +834,15 @@ static int on_properties_changed(sd_bus_message *m, void *userdata, sd_bus_error return 0; } +static int on_properties_changed(sd_bus_message *m, void *userdata, sd_bus_error *error) { + RunContext *c = userdata; + + assert(m); + assert(c); + + return run_context_update(c, sd_bus_message_get_path(m)); +} + static int pty_forward_handler(PTYForward *f, int rcode, void *userdata) { RunContext *c = userdata; @@ -985,6 +1000,8 @@ static int start_transient_service( if (arg_wait || master >= 0) { _cleanup_(run_context_free) RunContext c = {}; + _cleanup_free_ char *path = NULL; + const char *mt; c.bus = sd_bus_ref(bus); @@ -1007,27 +1024,27 @@ static int start_transient_service( pty_forward_set_handler(c.forward, pty_forward_handler, &c); } - if (arg_wait) { - _cleanup_free_ char *path = NULL; - const char *mt; - path = unit_dbus_path_from_name(service); - if (!path) - return log_oom(); + path = unit_dbus_path_from_name(service); + if (!path) + return log_oom(); - mt = strjoina("type='signal'," - "sender='org.freedesktop.systemd1'," - "path='", path, "'," - "interface='org.freedesktop.DBus.Properties'," - "member='PropertiesChanged'"); - r = sd_bus_add_match(bus, &c.match, mt, on_properties_changed, &c); - if (r < 0) - return log_error_errno(r, "Failed to add properties changed signal."); + mt = strjoina("type='signal'," + "sender='org.freedesktop.systemd1'," + "path='", path, "'," + "interface='org.freedesktop.DBus.Properties'," + "member='PropertiesChanged'"); + r = sd_bus_add_match(bus, &c.match, mt, on_properties_changed, &c); + if (r < 0) + return log_error_errno(r, "Failed to add properties changed signal."); - r = sd_bus_attach_event(bus, c.event, 0); - if (r < 0) - return log_error_errno(r, "Failed to attach bus to event loop."); - } + r = sd_bus_attach_event(bus, c.event, 0); + if (r < 0) + return log_error_errno(r, "Failed to attach bus to event loop."); + + r = run_context_update(&c, path); + if (r < 0) + return r; r = sd_event_loop(c.event); if (r < 0) @@ -1041,7 +1058,13 @@ static int start_transient_service( fputc('\n', stdout); } - if (!arg_quiet) { + if (arg_wait && !arg_quiet) { + + /* Explicitly destroy the PTY forwarder, so that the PTY device is usable again, in its + * original settings (i.e. proper line breaks), so that we can show the summary in a pretty + * way. */ + c.forward = pty_forward_free(c.forward); + if (!isempty(c.result)) log_info("Finished with result: %s", strna(c.result)); @@ -1416,7 +1439,7 @@ int main(int argc, char* argv[]) { /* If --wait is used connect via the bus, unconditionally, as ref/unref is not supported via the limited direct * connection */ - if (arg_wait) + if (arg_wait || arg_pty) r = bus_connect_transport(arg_transport, arg_host, arg_user, &bus); else r = bus_connect_transport_systemd(arg_transport, arg_host, arg_user, &bus); diff --git a/src/shared/ptyfwd.c b/src/shared/ptyfwd.c index 293c6673fc..59b541d519 100644 --- a/src/shared/ptyfwd.c +++ b/src/shared/ptyfwd.c @@ -69,6 +69,7 @@ struct PTYForward { bool read_from_master:1; bool done:1; + bool drain:1; bool last_char_set:1; char last_char; @@ -302,6 +303,11 @@ static int shovel(PTYForward *f) { return pty_forward_done(f, 0); } + /* If we were asked to drain, and there's nothing more to handle from the master, then call the callback + * too. */ + if (f->drain && f->out_buffer_full == 0 && !f->master_readable) + return pty_forward_done(f, 0); + return 0; } @@ -438,6 +444,9 @@ int pty_forward_new( r = sd_event_add_io(f->event, &f->stdin_event_source, STDIN_FILENO, EPOLLIN|EPOLLET, on_stdin_event, f); if (r < 0 && r != -EPERM) return r; + + if (r >= 0) + (void) sd_event_source_set_description(f->stdin_event_source, "ptyfwd-stdin"); } r = sd_event_add_io(f->event, &f->stdout_event_source, STDOUT_FILENO, EPOLLOUT|EPOLLET, on_stdout_event, f); @@ -446,15 +455,21 @@ int pty_forward_new( f->stdout_writable = true; else if (r < 0) return r; + else + (void) sd_event_source_set_description(f->stdout_event_source, "ptyfwd-stdout"); r = sd_event_add_io(f->event, &f->master_event_source, master, EPOLLIN|EPOLLOUT|EPOLLET, on_master_event, f); if (r < 0) return r; + (void) sd_event_source_set_description(f->master_event_source, "ptyfwd-master"); + r = sd_event_add_signal(f->event, &f->sigwinch_event_source, SIGWINCH, on_sigwinch_event, f); if (r < 0) return r; + (void) sd_event_source_set_description(f->sigwinch_event_source, "ptyfwd-sigwinch"); + *ret = f; f = NULL; @@ -519,3 +534,18 @@ void pty_forward_set_handler(PTYForward *f, PTYForwardHandler cb, void *userdata f->handler = cb; f->userdata = userdata; } + +bool pty_forward_drain(PTYForward *f) { + assert(f); + + /* Starts draining the forwarder. Specifically: + * + * - Returns true if there are no unprocessed bytes from the pty, false otherwise + * + * - Makes sure the handler function is called the next time the number of unprocessed bytes hits zero + */ + + f->drain = true; + + return f->out_buffer_full == 0 && !f->master_readable; +} diff --git a/src/shared/ptyfwd.h b/src/shared/ptyfwd.h index bd5d5fec0d..3fad1d3b26 100644 --- a/src/shared/ptyfwd.h +++ b/src/shared/ptyfwd.h @@ -51,4 +51,6 @@ bool pty_forward_is_done(PTYForward *f); void pty_forward_set_handler(PTYForward *f, PTYForwardHandler handler, void *userdata); +bool pty_forward_drain(PTYForward *f); + DEFINE_TRIVIAL_CLEANUP_FUNC(PTYForward*, pty_forward_free); diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c index 2c73cb8fa4..bd9c0aac60 100644 --- a/src/shared/seccomp-util.c +++ b/src/shared/seccomp-util.c @@ -171,11 +171,11 @@ int seccomp_init_for_arch(scmp_filter_ctx *ret, uint32_t arch, uint32_t default_ if (arch != SCMP_ARCH_NATIVE && arch != seccomp_arch_native()) { - r = seccomp_arch_add(seccomp, arch); + r = seccomp_arch_remove(seccomp, seccomp_arch_native()); if (r < 0) goto finish; - r = seccomp_arch_remove(seccomp, seccomp_arch_native()); + r = seccomp_arch_add(seccomp, arch); if (r < 0) goto finish; diff --git a/src/test/test-af-list.c b/src/test/test-af-list.c index e2479133de..e5ca54c8e7 100644 --- a/src/test/test-af-list.c +++ b/src/test/test-af-list.c @@ -24,6 +24,7 @@ #include "string-util.h" #include "util.h" +_unused_ \ static const struct af_name* lookup_af(register const char *str, register GPERF_LEN_TYPE len); #include "af-from-name.h" diff --git a/src/test/test-arphrd-list.c b/src/test/test-arphrd-list.c index 8f4f342faa..bb51518c9c 100644 --- a/src/test/test-arphrd-list.c +++ b/src/test/test-arphrd-list.c @@ -24,6 +24,7 @@ #include "string-util.h" #include "util.h" +_unused_ \ static const struct arphrd_name* lookup_arphrd(register const char *str, register GPERF_LEN_TYPE len); #include "arphrd-from-name.h" |