diff options
-rw-r--r-- | Makefile.am | 113 | ||||
-rw-r--r-- | m4/attributes.m4 | 2 | ||||
-rw-r--r-- | man/hostname.xml | 4 | ||||
-rw-r--r-- | man/hostnamectl.xml | 8 | ||||
-rw-r--r-- | man/systemd.generator.xml | 15 | ||||
-rw-r--r-- | shell-completion/bash/journalctl | 13 | ||||
-rw-r--r-- | shell-completion/zsh/_busctl | 2 | ||||
-rw-r--r-- | src/basic/time-util.c | 3 | ||||
-rw-r--r-- | src/core/unit.c | 2 | ||||
-rw-r--r-- | src/journal-remote/journal-remote.c | 2 | ||||
-rw-r--r-- | src/journal/catalog.c | 146 | ||||
-rw-r--r-- | src/journal/catalog.h | 2 | ||||
-rw-r--r-- | src/journal/journal-file.c | 32 | ||||
-rw-r--r-- | src/journal/journald-server.c | 13 | ||||
-rw-r--r-- | src/journal/mmap-cache.c | 66 | ||||
-rw-r--r-- | src/journal/sd-journal.c | 2 | ||||
-rw-r--r-- | src/journal/test-catalog.c | 130 | ||||
-rw-r--r-- | src/resolve/resolved-dns-dnssec.c | 2 | ||||
-rw-r--r-- | src/resolve/resolved-dns-packet.c | 2 | ||||
-rw-r--r-- | src/resolve/resolved-dns-rr.c | 2 | ||||
-rw-r--r-- | test/sys.tar.xz | bin | 165116 -> 261380 bytes | |||
-rwxr-xr-x | test/udev-test.pl | 4 | ||||
-rw-r--r-- | units/rescue.service.in | 2 |
23 files changed, 373 insertions, 194 deletions
diff --git a/Makefile.am b/Makefile.am index f1f8315f30..a3a473097b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -155,6 +155,14 @@ else noinst_PROGRAMS = TESTS = endif +if ENABLE_BASH_COMPLETION +dist_bashcompletion_DATA = $(dist_bashcompletion_data) +nodist_bashcompletion_DATA = $(nodist_bashcompletion_data) +endif +if ENABLE_ZSH_COMPLETION +dist_zshcompletion_DATA = $(dist_zshcompletion_data) +nodist_zshcompletion_DATA = $(nodist_zshcompletion_data) +endif udevlibexec_PROGRAMS = gperf_gperf_sources = @@ -165,6 +173,8 @@ m4_files = $(filter %.m4,$(EXTRA_DIST) $(in_files:.m4.in=.m4)) CLEANFILES = $(BUILT_SOURCES) \ $(pkgconfigdata_DATA) \ $(pkgconfiglib_DATA) \ + $(nodist_bashcompletion_data) \ + $(nodist_zshcompletion_data) \ $(in_files:.in=) $(in_in_files:.in.in=) \ $(m4_files:.m4=) @@ -416,8 +426,7 @@ systemgenerator_PROGRAMS = \ systemd-system-update-generator \ systemd-debug-generator -if ENABLE_BASH_COMPLETION -dist_bashcompletion_DATA = \ +dist_bashcompletion_data = \ shell-completion/bash/busctl \ shell-completion/bash/journalctl \ shell-completion/bash/systemd-analyze \ @@ -432,12 +441,10 @@ dist_bashcompletion_DATA = \ shell-completion/bash/udevadm \ shell-completion/bash/kernel-install -nodist_bashcompletion_DATA = \ +nodist_bashcompletion_data = \ shell-completion/bash/systemctl -endif -if ENABLE_ZSH_COMPLETION -dist_zshcompletion_DATA = \ +dist_zshcompletion_data = \ shell-completion/zsh/_busctl \ shell-completion/zsh/_journalctl \ shell-completion/zsh/_udevadm \ @@ -451,18 +458,13 @@ dist_zshcompletion_DATA = \ shell-completion/zsh/_systemd-delta \ shell-completion/zsh/_systemd -nodist_zshcompletion_DATA = \ +nodist_zshcompletion_data = \ shell-completion/zsh/_systemctl -endif EXTRA_DIST += \ shell-completion/bash/systemctl.in \ shell-completion/zsh/_systemctl.in -CLEANFILES += \ - $(nodist_bashcompletion_DATA) \ - $(nodist_zshcompletion_DATA) - dist_sysctl_DATA = \ sysctl.d/50-default.conf @@ -2396,10 +2398,8 @@ SYSINIT_TARGET_WANTS += \ systemd-tmpfiles-setup-dev.service \ systemd-tmpfiles-setup.service -if ENABLE_ZSH_COMPLETION -dist_zshcompletion_DATA += \ +dist_zshcompletion_data += \ shell-completion/zsh/_systemd-tmpfiles -endif TIMERS_TARGET_WANTS += \ systemd-tmpfiles-clean.timer @@ -2627,16 +2627,12 @@ bootctl_LDADD = \ bin_PROGRAMS += \ bootctl -if ENABLE_BASH_COMPLETION -dist_bashcompletion_DATA += \ +dist_bashcompletion_data += \ shell-completion/bash/bootctl -endif -if ENABLE_ZSH_COMPLETION -dist_zshcompletion_DATA += \ +dist_zshcompletion_data += \ shell-completion/zsh/_bootctl endif -endif # ------------------------------------------------------------------------------ if HAVE_GNUEFI @@ -2717,14 +2713,13 @@ systemd_boot_sources = \ EXTRA_DIST += $(systemd_boot_sources) $(systemd_boot_headers) -if ENABLE_EFI -if HAVE_GNUEFI systemd_boot_objects = $(addprefix $(top_builddir)/,$(systemd_boot_sources:.c=.o)) systemd_boot_solib = $(top_builddir)/src/boot/efi/systemd_boot.so systemd_boot = systemd-boot$(EFI_MACHINE_TYPE_NAME).efi +if ENABLE_EFI +if HAVE_GNUEFI bootlib_DATA = $(systemd_boot) -CLEANFILES += $(systemd_boot_objects) $(systemd_boot_solib) $(systemd_boot) $(top_builddir)/src/boot/efi/%.o: $(top_srcdir)/src/boot/efi/%.c $(addprefix $(top_srcdir)/,$(systemd_boot_headers)) @$(MKDIR_P) $(top_builddir)/src/boot/efi/ @@ -2741,6 +2736,8 @@ $(systemd_boot): $(systemd_boot_solib) endif endif +CLEANFILES += $(systemd_boot_objects) $(systemd_boot_solib) $(systemd_boot) + # ------------------------------------------------------------------------------ stub_headers = \ src/boot/efi/util.h \ @@ -2764,14 +2761,13 @@ EXTRA_DIST += \ $(stub_headers) \ test/splash.bmp -if ENABLE_EFI -if HAVE_GNUEFI stub_objects = $(addprefix $(top_builddir)/,$(stub_sources:.c=.o)) stub_solib = $(top_builddir)/src/boot/efi/stub.so stub = linux$(EFI_MACHINE_TYPE_NAME).efi.stub +if ENABLE_EFI +if HAVE_GNUEFI bootlib_DATA += $(stub) -CLEANFILES += $(stub_objects) $(stub_solib) $(stub) $(top_builddir)/src/boot/efi/%.o: $(top_srcdir)/src/boot/efi/%.c $(addprefix $(top_srcdir)/,$(stub_headers)) @$(MKDIR_P) $(top_builddir)/src/boot/efi/ @@ -2785,6 +2781,11 @@ $(stub_solib): $(stub_objects) $(stub): $(stub_solib) $(AM_V_GEN)$(OBJCOPY) -j .text -j .sdata -j .data -j .dynamic \ -j .dynsym -j .rel -j .rela -j .reloc $(EFI_FORMAT) $< $@ +endif +endif + +CLEANFILES += $(stub_objects) $(stub_solib) $(stub) + # ------------------------------------------------------------------------------ CLEANFILES += test-efi-disk.img @@ -2794,8 +2795,6 @@ test-efi-disk.img: $(systemd_boot) $(stub) test/test-efi-create-disk.sh test-efi: test-efi-disk.img $(QEMU) -machine accel=kvm -m 1024 -bios $(QEMU_BIOS) -snapshot test-efi-disk.img -endif -endif EXTRA_DIST += test/test-efi-create-disk.sh @@ -4440,15 +4439,11 @@ test_coredump_vacuum_SOURCES = \ test_coredump_vacuum_LDADD = \ libshared.la -if ENABLE_BASH_COMPLETION -dist_bashcompletion_DATA += \ +dist_bashcompletion_data += \ shell-completion/bash/coredumpctl -endif -if ENABLE_ZSH_COMPLETION -dist_zshcompletion_DATA += \ +dist_zshcompletion_data += \ shell-completion/zsh/_coredumpctl -endif nodist_sysctl_DATA = \ sysctl.d/50-coredump.conf @@ -4699,16 +4694,12 @@ hostnamectl_LDADD = \ bin_PROGRAMS += \ hostnamectl -if ENABLE_BASH_COMPLETION -dist_bashcompletion_DATA += \ +dist_bashcompletion_data += \ shell-completion/bash/hostnamectl -endif -if ENABLE_ZSH_COMPLETION -dist_zshcompletion_DATA += \ +dist_zshcompletion_data += \ shell-completion/zsh/_hostnamectl endif -endif polkitpolicy_in_files += \ src/hostname/org.freedesktop.hostname1.policy.in @@ -4773,16 +4764,12 @@ localectl_LDADD = \ bin_PROGRAMS += \ localectl -if ENABLE_BASH_COMPLETION -dist_bashcompletion_DATA += \ +dist_bashcompletion_data += \ shell-completion/bash/localectl -endif -if ENABLE_ZSH_COMPLETION -dist_zshcompletion_DATA += \ +dist_zshcompletion_data += \ shell-completion/zsh/_localectl endif -endif .PHONY: update-kbd-model-map @@ -4833,16 +4820,12 @@ timedatectl_LDADD = \ bin_PROGRAMS += \ timedatectl -if ENABLE_BASH_COMPLETION -dist_bashcompletion_DATA += \ +dist_bashcompletion_data += \ shell-completion/bash/timedatectl -endif -if ENABLE_ZSH_COMPLETION -dist_zshcompletion_DATA += \ +dist_zshcompletion_data += \ shell-completion/zsh/_timedatectl endif -endif polkitpolicy_in_files += \ src/timedate/org.freedesktop.timedate1.policy.in @@ -4948,11 +4931,6 @@ machinectl_LDADD = \ rootbin_PROGRAMS += \ machinectl -if ENABLE_BASH_COMPLETION -dist_bashcompletion_DATA += \ - shell-completion/bash/machinectl -endif - test_machine_tables_SOURCES = \ src/machine/test-machine-tables.c @@ -4980,11 +4958,12 @@ dist_dbuspolicy_DATA += \ polkitpolicy_files += \ src/machine/org.freedesktop.machine1.policy -if ENABLE_ZSH_COMPLETION -dist_zshcompletion_DATA += \ +dist_bashcompletion_data += \ + shell-completion/bash/machinectl + +dist_zshcompletion_data += \ shell-completion/zsh/_machinectl \ shell-completion/zsh/_sd_machines -endif SYSTEM_UNIT_ALIASES += \ systemd-machined.service dbus-org.freedesktop.machine1.service @@ -5474,10 +5453,8 @@ networkctl_LDADD = \ libshared.la \ libsystemd-network.la -if ENABLE_BASH_COMPLETION -dist_bashcompletion_DATA += \ +dist_bashcompletion_data += \ shell-completion/bash/networkctl -endif test_network_SOURCES = \ src/network/test-network.c @@ -5607,16 +5584,12 @@ loginctl_LDADD = \ rootbin_PROGRAMS += \ loginctl -if ENABLE_BASH_COMPLETION -dist_bashcompletion_DATA += \ +dist_bashcompletion_data += \ shell-completion/bash/loginctl -endif -if ENABLE_ZSH_COMPLETION -dist_zshcompletion_DATA += \ +dist_zshcompletion_data += \ shell-completion/zsh/_loginctl \ shell-completion/zsh/_systemd-inhibit -endif systemd_inhibit_SOURCES = \ src/login/inhibit.c diff --git a/m4/attributes.m4 b/m4/attributes.m4 index db5df250f4..51ac88be61 100644 --- a/m4/attributes.m4 +++ b/m4/attributes.m4 @@ -43,7 +43,7 @@ AC_DEFUN([CC_CHECK_FLAG_APPEND], [ AC_CACHE_CHECK([if $CC supports flag $3 in envvar $2], AS_TR_SH([cc_cv_$2_$3]), [eval "AS_TR_SH([cc_save_$2])='${$2}'" - eval "AS_TR_SH([$2])='-Werror `echo "$3" | sed 's/^-Wno-/-W/'`'" + eval "AS_TR_SH([$2])='${cc_save_$2} -Werror `echo "$3" | sed 's/^-Wno-/-W/'`'" AC_LINK_IFELSE([AC_LANG_SOURCE(ifelse([$4], [], [int main(void) { return 0; } ], [$4]))], diff --git a/man/hostname.xml b/man/hostname.xml index 9688450e1c..8a4c0d5ac0 100644 --- a/man/hostname.xml +++ b/man/hostname.xml @@ -64,10 +64,6 @@ for DNS domain name labels, even though this is not a strict requirement.</para> - <para>Depending on the operating system, other configuration files - might be checked for configuration of the hostname as well, - however only as fallback.</para> - <para>You may use <citerefentry><refentrytitle>hostnamectl</refentrytitle><manvolnum>1</manvolnum></citerefentry> to change the value of this file during runtime from the command diff --git a/man/hostnamectl.xml b/man/hostnamectl.xml index b1f038156d..60004e9d04 100644 --- a/man/hostnamectl.xml +++ b/man/hostnamectl.xml @@ -66,10 +66,10 @@ high-level "pretty" hostname which might include all kinds of special characters (e.g. "Lennart's Laptop"), the static hostname which is used to initialize the kernel hostname at boot (e.g. - "lennarts-laptop"), and the transient hostname which is a default - received from network configuration. If a static hostname is set, - and is valid (something other than localhost), then the transient - hostname is not used.</para> + "lennarts-laptop"), and the transient hostname which is a fallback + value received from network configuration. If a static hostname is + set, and is valid (something other than localhost), then the + transient hostname is not used.</para> <para>Note that the pretty hostname has little restrictions on the characters used, while the static and transient hostnames are diff --git a/man/systemd.generator.xml b/man/systemd.generator.xml index 62658fb115..4b80dab108 100644 --- a/man/systemd.generator.xml +++ b/man/systemd.generator.xml @@ -164,13 +164,16 @@ Generators are run very early at boot and cannot rely on any external services. They may not talk to any other process. That includes simple things such as logging to - <citerefentry - project='man-pages'><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry>, + <citerefentry project='man-pages'><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry>, or <command>systemd</command> itself (this means: no - <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>!). They - can however rely on the most basic kernel functionality to - be available, including a mounted <filename>/sys</filename>, - <filename>/proc</filename>, <filename>/dev</filename>. + <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>)!. + Non-essential file systems like + <filename>/var</filename> and <filename>/home</filename> + are mounted after generators have run. Generators + can however rely on the most basic kernel functionality to be + available, including a mounted <filename>/sys</filename>, + <filename>/proc</filename>, <filename>/dev</filename>, + <filename>/usr</filename>. </para> </listitem> diff --git a/shell-completion/bash/journalctl b/shell-completion/bash/journalctl index 321d439f0c..7c8a9ce361 100644 --- a/shell-completion/bash/journalctl +++ b/shell-completion/bash/journalctl @@ -24,6 +24,12 @@ __contains_word () { done } +__get_machines() { + local a b + (machinectl list-images --no-legend --no-pager; machinectl list --no-legend --no-pager; echo ".host") | \ + { while read a b; do echo " $a"; done; } | sort -u; +} + __journal_fields=(MESSAGE{,_ID} PRIORITY CODE_{FILE,LINE,FUNC} ERRNO SYSLOG_{FACILITY,IDENTIFIER,PID} COREDUMP_EXE _{P,U,G}ID _COMM _EXE _CMDLINE @@ -49,11 +55,11 @@ _journalctl() { --utc -x --catalog --no-full --force --dump-catalog --flush --rotate --sync' [ARG]='-b --boot --this-boot -D --directory --file -F --field - -o --output -u --unit --user-unit -p --priority + -M --machine -o --output -u --unit --user-unit -p --priority --vacuum-size --vacuum-time' [ARGUNKNOWN]='-c --cursor --interval -n --lines -S --since -U --until --after-cursor --verify-key -t --identifier - --root -M --machine' + --root' ) if __contains_word "$prev" ${OPTS[ARG]} ${OPTS[ARGUNKNOWN]}; then @@ -74,6 +80,9 @@ _journalctl() { ;; --field|-F) comps=${__journal_fields[*]} + ;; + --machine|-M) + comps=$( __get_machines ) ;; --priority|-p) comps=${__syslog_priorities[*]} diff --git a/shell-completion/zsh/_busctl b/shell-completion/zsh/_busctl index ef790e558f..a425b8c700 100644 --- a/shell-completion/zsh/_busctl +++ b/shell-completion/zsh/_busctl @@ -1,6 +1,6 @@ #compdef busctl -# hostnamectl(1) completion -*- shell-script -*- +# busctl(1) completion -*- shell-script -*- # # This file is part of systemd. # diff --git a/src/basic/time-util.c b/src/basic/time-util.c index bfc7cf870c..293442cf0e 100644 --- a/src/basic/time-util.c +++ b/src/basic/time-util.c @@ -117,9 +117,8 @@ dual_timestamp* dual_timestamp_from_boottime_or_monotonic(dual_timestamp *ts, us ts->realtime = ts->monotonic = USEC_INFINITY; return ts; } - ts->realtime = now(CLOCK_REALTIME); - ts->monotonic = now(CLOCK_MONOTONIC); + dual_timestamp_get(ts); delta = (int64_t) now(clock_boottime_or_monotonic()) - (int64_t) u; if ((int64_t) ts->realtime > delta) diff --git a/src/core/unit.c b/src/core/unit.c index 0c1efc0e16..be4dac8fea 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -2852,7 +2852,7 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) { /* Versions before 228 did not carry a state change timestamp. In this case, take the current time. This is * useful, so that timeouts based on this timestamp don't trigger too early, and is in-line with the logic from - * before 228 where the base for timeouts was not peristet across reboots. */ + * before 228 where the base for timeouts was not persistent across reboots. */ if (!dual_timestamp_is_set(&u->state_change_timestamp)) dual_timestamp_get(&u->state_change_timestamp); diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c index cfe111fd91..fa4a4ff931 100644 --- a/src/journal-remote/journal-remote.c +++ b/src/journal-remote/journal-remote.c @@ -645,7 +645,7 @@ static int setup_microhttpd_server(RemoteServer *s, { MHD_OPTION_NOTIFY_COMPLETED, (intptr_t) request_meta_free}, { MHD_OPTION_EXTERNAL_LOGGER, (intptr_t) microhttpd_logger}, { MHD_OPTION_LISTEN_SOCKET, fd}, - { MHD_OPTION_CONNECTION_MEMORY_LIMIT, DATA_SIZE_MAX}, + { MHD_OPTION_CONNECTION_MEMORY_LIMIT, 128*1024}, { MHD_OPTION_END}, { MHD_OPTION_END}, { MHD_OPTION_END}, diff --git a/src/journal/catalog.c b/src/journal/catalog.c index fcaa54aa0c..ddec6bd503 100644 --- a/src/journal/catalog.c +++ b/src/journal/catalog.c @@ -94,25 +94,87 @@ const struct hash_ops catalog_hash_ops = { .compare = catalog_compare_func }; +static bool next_header(const char **s) { + const char *e; + + e = strchr(*s, '\n'); + + /* Unexpected end */ + if (!e) + return false; + + /* End of headers */ + if (e == *s) + return false; + + *s = e + 1; + return true; +} + +static const char *skip_header(const char *s) { + while (next_header(&s)) + ; + return s; +} + +static char *combine_entries(const char *one, const char *two) { + const char *b1, *b2; + size_t l1, l2, n; + char *dest, *p; + + /* Find split point of headers to body */ + b1 = skip_header(one); + b2 = skip_header(two); + + l1 = strlen(one); + l2 = strlen(two); + dest = new(char, l1 + l2 + 1); + if (!dest) { + log_oom(); + return NULL; + } + + p = dest; + + /* Headers from @one */ + n = b1 - one; + p = mempcpy(p, one, n); + + /* Headers from @two, these will only be found if not present above */ + n = b2 - two; + p = mempcpy(p, two, n); + + /* Body from @one */ + n = l1 - (b1 - one); + if (n > 0) { + memcpy(p, b1, n); + p += n; + + /* Body from @two */ + } else { + n = l2 - (b2 - two); + memcpy(p, b2, n); + p += n; + } + + assert(p - dest <= (ptrdiff_t)(l1 + l2)); + p[0] = '\0'; + return dest; +} + static int finish_item( Hashmap *h, - struct strbuf *sb, sd_id128_t id, const char *language, - const char *payload) { + char *payload) { - ssize_t offset; _cleanup_free_ CatalogItem *i = NULL; + _cleanup_free_ char *combined = NULL, *prev = NULL; int r; assert(h); - assert(sb); assert(payload); - offset = strbuf_add_string(sb, payload, strlen(payload)); - if (offset < 0) - return log_oom(); - i = new0(CatalogItem, 1); if (!i) return log_oom(); @@ -122,17 +184,27 @@ static int finish_item( assert(strlen(language) > 1 && strlen(language) < 32); strcpy(i->language, language); } - i->offset = htole64((uint64_t) offset); - r = hashmap_put(h, i, i); - if (r == -EEXIST) { - log_warning("Duplicate entry for " SD_ID128_FORMAT_STR ".%s, ignoring.", - SD_ID128_FORMAT_VAL(id), language ? language : "C"); - return 0; - } else if (r < 0) - return r; + prev = hashmap_get(h, i); + + /* Already have such an item, combine them */ + if (prev) { + combined = combine_entries(payload, prev); + if (!combined) + return log_oom(); + r = hashmap_update(h, i, combined); + if (r < 0) + return r; + combined = NULL; + + /* A new item */ + } else { + r = hashmap_put(h, i, payload); + if (r < 0) + return r; + i = NULL; + } - i = NULL; return 0; } @@ -189,7 +261,7 @@ static int catalog_entry_lang(const char* filename, int line, return 0; } -int catalog_import_file(Hashmap *h, struct strbuf *sb, const char *path) { +int catalog_import_file(Hashmap *h, const char *path) { _cleanup_fclose_ FILE *f = NULL; _cleanup_free_ char *payload = NULL; unsigned n = 0; @@ -199,7 +271,6 @@ int catalog_import_file(Hashmap *h, struct strbuf *sb, const char *path) { int r; assert(h); - assert(sb); assert(path); f = fopen(path, "re"); @@ -254,10 +325,11 @@ int catalog_import_file(Hashmap *h, struct strbuf *sb, const char *path) { if (sd_id128_from_string(line + 2 + 1, &jd) >= 0) { if (got_id) { - r = finish_item(h, sb, id, lang ?: deflang, payload); + r = finish_item(h, id, lang ?: deflang, payload); if (r < 0) return r; + payload = NULL; lang = mfree(lang); } @@ -310,9 +382,10 @@ int catalog_import_file(Hashmap *h, struct strbuf *sb, const char *path) { } if (got_id) { - r = finish_item(h, sb, id, lang ?: deflang, payload); + r = finish_item(h, id, lang ?: deflang, payload); if (r < 0) return r; + payload = NULL; } return 0; @@ -389,8 +462,10 @@ int catalog_update(const char* database, const char* root, const char* const* di _cleanup_strv_free_ char **files = NULL; char **f; struct strbuf *sb = NULL; - _cleanup_hashmap_free_free_ Hashmap *h = NULL; + _cleanup_hashmap_free_free_free_ Hashmap *h = NULL; _cleanup_free_ CatalogItem *items = NULL; + ssize_t offset; + char *payload; CatalogItem *i; Iterator j; unsigned n; @@ -413,7 +488,7 @@ int catalog_update(const char* database, const char* root, const char* const* di STRV_FOREACH(f, files) { log_debug("Reading file '%s'", *f); - r = catalog_import_file(h, sb, *f); + r = catalog_import_file(h, *f); if (r < 0) { log_error_errno(r, "Failed to import file '%s': %m", *f); goto finish; @@ -426,8 +501,6 @@ int catalog_update(const char* database, const char* root, const char* const* di } else log_debug("Found %u items in catalog.", hashmap_size(h)); - strbuf_complete(sb); - items = new(CatalogItem, hashmap_size(h)); if (!items) { r = log_oom(); @@ -435,16 +508,25 @@ int catalog_update(const char* database, const char* root, const char* const* di } n = 0; - HASHMAP_FOREACH(i, h, j) { + HASHMAP_FOREACH_KEY(payload, i, h, j) { log_debug("Found " SD_ID128_FORMAT_STR ", language %s", SD_ID128_FORMAT_VAL(i->id), isempty(i->language) ? "C" : i->language); + + offset = strbuf_add_string(sb, payload, strlen(payload)); + if (offset < 0) { + r = log_oom(); + goto finish; + } + i->offset = htole64((uint64_t) offset); items[n++] = *i; } assert(n == hashmap_size(h)); qsort_safe(items, n, sizeof(CatalogItem), catalog_compare_func); + strbuf_complete(sb); + sz = write_catalog(database, sb, items, n); if (sz < 0) r = log_error_errno(sz, "Failed to write %s: %m", database); @@ -587,7 +669,7 @@ finish: static char *find_header(const char *s, const char *header) { for (;;) { - const char *v, *e; + const char *v; v = startswith(s, header); if (v) { @@ -595,16 +677,8 @@ static char *find_header(const char *s, const char *header) { return strndup(v, strcspn(v, NEWLINE)); } - /* End of text */ - e = strchr(s, '\n'); - if (!e) + if (!next_header(&s)) return NULL; - - /* End of header */ - if (e == s) - return NULL; - - s = e + 1; } } diff --git a/src/journal/catalog.h b/src/journal/catalog.h index bcc73c2631..b3856d2de0 100644 --- a/src/journal/catalog.h +++ b/src/journal/catalog.h @@ -28,7 +28,7 @@ #include "hashmap.h" #include "strbuf.h" -int catalog_import_file(Hashmap *h, struct strbuf *sb, const char *path); +int catalog_import_file(Hashmap *h, const char *path); int catalog_update(const char* database, const char* root, const char* const* dirs); int catalog_get(const char* database, sd_id128_t id, char **data); int catalog_list(FILE *f, const char* database, bool oneline); diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 2973176c8d..3d87e25724 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -100,7 +100,7 @@ static int journal_file_set_online(JournalFile *f) { if (mmap_cache_got_sigbus(f->mmap, f->fd)) return -EIO; - switch(f->header->state) { + switch (f->header->state) { case STATE_ONLINE: return 0; @@ -247,6 +247,7 @@ static int journal_file_refresh_header(JournalFile *f) { int r; assert(f); + assert(f->header); r = sd_id128_get_machine(&f->header->machine_id); if (r < 0) @@ -273,6 +274,7 @@ static int journal_file_verify_header(JournalFile *f) { uint32_t flags; assert(f); + assert(f->header); if (memcmp(f->header->signature, HEADER_SIGNATURE, 8)) return -EBADMSG; @@ -381,6 +383,7 @@ static int journal_file_allocate(JournalFile *f, uint64_t offset, uint64_t size) int r; assert(f); + assert(f->header); /* We assume that this file is not sparse, and we know that * for sure, since we always call posix_fallocate() @@ -544,6 +547,7 @@ static uint64_t journal_file_entry_seqnum(JournalFile *f, uint64_t *seqnum) { uint64_t r; assert(f); + assert(f->header); r = le64toh(f->header->tail_entry_seqnum) + 1; @@ -573,6 +577,7 @@ int journal_file_append_object(JournalFile *f, ObjectType type, uint64_t size, O void *t; assert(f); + assert(f->header); assert(type > OBJECT_UNUSED && type < _OBJECT_TYPE_MAX); assert(size >= sizeof(ObjectHeader)); assert(offset); @@ -622,6 +627,7 @@ static int journal_file_setup_data_hash_table(JournalFile *f) { int r; assert(f); + assert(f->header); /* We estimate that we need 1 hash table entry per 768 bytes of journal file and we want to make sure we never get @@ -655,6 +661,7 @@ static int journal_file_setup_field_hash_table(JournalFile *f) { int r; assert(f); + assert(f->header); /* We use a fixed size hash table for the fields as this * number should grow very slowly only */ @@ -681,6 +688,7 @@ int journal_file_map_data_hash_table(JournalFile *f) { int r; assert(f); + assert(f->header); if (f->data_hash_table) return 0; @@ -706,6 +714,7 @@ int journal_file_map_field_hash_table(JournalFile *f) { int r; assert(f); + assert(f->header); if (f->field_hash_table) return 0; @@ -735,6 +744,8 @@ static int journal_file_link_field( int r; assert(f); + assert(f->header); + assert(f->field_hash_table); assert(o); assert(offset > 0); @@ -778,6 +789,8 @@ static int journal_file_link_data( int r; assert(f); + assert(f->header); + assert(f->data_hash_table); assert(o); assert(offset > 0); @@ -826,6 +839,7 @@ int journal_file_find_field_object_with_hash( int r; assert(f); + assert(f->header); assert(field && size > 0); /* If the field hash table is empty, we can't find anything */ @@ -897,6 +911,7 @@ int journal_file_find_data_object_with_hash( int r; assert(f); + assert(f->header); assert(data || size == 0); /* If there's no data hash table, then there's no entry. */ @@ -1193,6 +1208,7 @@ static int link_entry_into_array(JournalFile *f, Object *o; assert(f); + assert(f->header); assert(first); assert(idx); assert(p > 0); @@ -1313,6 +1329,7 @@ static int journal_file_link_entry(JournalFile *f, Object *o, uint64_t offset) { int r; assert(f); + assert(f->header); assert(o); assert(offset > 0); @@ -1363,6 +1380,7 @@ static int journal_file_append_entry_internal( int r; assert(f); + assert(f->header); assert(items || n_items == 0); assert(ts); @@ -1507,6 +1525,7 @@ int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const st struct dual_timestamp _ts; assert(f); + assert(f->header); assert(iovec || n_iovec == 0); if (!ts) { @@ -2022,6 +2041,8 @@ int journal_file_move_to_entry_by_seqnum( direction_t direction, Object **ret, uint64_t *offset) { + assert(f); + assert(f->header); return generic_array_bisect(f, le64toh(f->header->entry_array_offset), @@ -2057,6 +2078,8 @@ int journal_file_move_to_entry_by_realtime( direction_t direction, Object **ret, uint64_t *offset) { + assert(f); + assert(f->header); return generic_array_bisect(f, le64toh(f->header->entry_array_offset), @@ -2149,7 +2172,9 @@ void journal_file_save_location(JournalFile *f, Object *o, uint64_t offset) { int journal_file_compare_locations(JournalFile *af, JournalFile *bf) { assert(af); + assert(af->header); assert(bf); + assert(bf->header); assert(af->location_type == LOCATION_SEEK); assert(bf->location_type == LOCATION_SEEK); @@ -2209,6 +2234,7 @@ int journal_file_next_entry( int r; assert(f); + assert(f->header); n = le64toh(f->header->n_entries); if (n <= 0) @@ -2491,6 +2517,7 @@ void journal_file_dump(JournalFile *f) { uint64_t p; assert(f); + assert(f->header); journal_file_print_header(f); @@ -2575,6 +2602,7 @@ void journal_file_print_header(JournalFile *f) { char bytes[FORMAT_BYTES_MAX]; assert(f); + assert(f->header); printf("File Path: %s\n" "File ID: %s\n" @@ -3180,6 +3208,7 @@ void journal_default_metrics(JournalMetrics *m, int fd) { int journal_file_get_cutoff_realtime_usec(JournalFile *f, usec_t *from, usec_t *to) { assert(f); + assert(f->header); assert(from || to); if (from) { @@ -3243,6 +3272,7 @@ int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot_id, u bool journal_file_rotate_suggested(JournalFile *f, usec_t max_file_usec) { assert(f); + assert(f->header); /* If we gained new header fields we gained new features, * hence suggest a rotation */ diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 8ff7ef943b..6a4e3bf249 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -244,7 +244,6 @@ static int open_journal( int flags, bool seal, JournalMetrics *metrics, - JournalFile *template, JournalFile **ret) { int r; JournalFile *f; @@ -254,9 +253,9 @@ static int open_journal( assert(ret); if (reliably) - r = journal_file_open_reliably(fname, flags, 0640, s->compress, seal, metrics, s->mmap, template, &f); + r = journal_file_open_reliably(fname, flags, 0640, s->compress, seal, metrics, s->mmap, NULL, &f); else - r = journal_file_open(fname, flags, 0640, s->compress, seal, metrics, s->mmap, template, &f); + r = journal_file_open(fname, flags, 0640, s->compress, seal, metrics, s->mmap, NULL, &f); if (r < 0) return r; @@ -308,7 +307,7 @@ static JournalFile* find_journal(Server *s, uid_t uid) { journal_file_close(f); } - r = open_journal(s, true, p, O_RDWR|O_CREAT, s->seal, &s->system_metrics, NULL, &f); + r = open_journal(s, true, p, O_RDWR|O_CREAT, s->seal, &s->system_metrics, &f); if (r < 0) return s->system_journal; @@ -1000,7 +999,7 @@ static int system_journal_open(Server *s, bool flush_requested) { (void) mkdir(fn, 0755); fn = strjoina(fn, "/system.journal"); - r = open_journal(s, true, fn, O_RDWR|O_CREAT, s->seal, &s->system_metrics, NULL, &s->system_journal); + r = open_journal(s, true, fn, O_RDWR|O_CREAT, s->seal, &s->system_metrics, &s->system_journal); if (r >= 0) { server_add_acls(s->system_journal, 0); (void) determine_space_for(s, &s->system_metrics, "/var/log/journal/", "System journal", true, true, NULL, NULL); @@ -1023,7 +1022,7 @@ static int system_journal_open(Server *s, bool flush_requested) { * if it already exists, so that we can flush * it into the system journal */ - r = open_journal(s, false, fn, O_RDWR, false, &s->runtime_metrics, NULL, &s->runtime_journal); + r = open_journal(s, false, fn, O_RDWR, false, &s->runtime_metrics, &s->runtime_journal); if (r < 0) { if (r != -ENOENT) log_warning_errno(r, "Failed to open runtime journal: %m"); @@ -1040,7 +1039,7 @@ static int system_journal_open(Server *s, bool flush_requested) { (void) mkdir("/run/log/journal", 0755); (void) mkdir_parents(fn, 0750); - r = open_journal(s, true, fn, O_RDWR|O_CREAT, false, &s->runtime_metrics, NULL, &s->runtime_journal); + r = open_journal(s, true, fn, O_RDWR|O_CREAT, false, &s->runtime_metrics, &s->runtime_journal); if (r < 0) return log_error_errno(r, "Failed to open runtime journal: %m"); } diff --git a/src/journal/mmap-cache.c b/src/journal/mmap-cache.c index a69672ce21..4636e4b395 100644 --- a/src/journal/mmap-cache.c +++ b/src/journal/mmap-cache.c @@ -173,10 +173,11 @@ _pure_ static bool window_matches(Window *w, int fd, int prot, uint64_t offset, offset + size <= w->offset + w->size; } -static Window *window_add(MMapCache *m) { +static Window *window_add(MMapCache *m, FileDescriptor *fd, int prot, bool keep_always, uint64_t offset, size_t size, void *ptr) { Window *w; assert(m); + assert(fd); if (!m->last_unused || m->n_windows <= WINDOWS_MIN) { @@ -194,6 +195,15 @@ static Window *window_add(MMapCache *m) { } w->cache = m; + w->fd = fd; + w->prot = prot; + w->keep_always = keep_always; + w->offset = offset; + w->size = size; + w->ptr = ptr; + + LIST_PREPEND(by_fd, fd->windows, w); + return w; } @@ -459,6 +469,33 @@ static int find_mmap( return 1; } +static int mmap_try_harder(MMapCache *m, void *addr, int fd, int prot, int flags, uint64_t offset, size_t size, void **res) { + void *ptr; + + assert(m); + assert(fd >= 0); + assert(res); + + for (;;) { + int r; + + ptr = mmap(addr, size, prot, flags, fd, offset); + if (ptr != MAP_FAILED) + break; + if (errno != ENOMEM) + return -errno; + + r = make_room(m); + if (r < 0) + return r; + if (r == 0) + return -ENOMEM; + } + + *res = ptr; + return 0; +} + static int add_mmap( MMapCache *m, int fd, @@ -512,19 +549,9 @@ static int add_mmap( wsize = PAGE_ALIGN(st->st_size - woffset); } - for (;;) { - d = mmap(NULL, wsize, prot, MAP_SHARED, fd, woffset); - if (d != MAP_FAILED) - break; - if (errno != ENOMEM) - return -errno; - - r = make_room(m); - if (r < 0) - return r; - if (r == 0) - return -ENOMEM; - } + r = mmap_try_harder(m, NULL, fd, prot, MAP_SHARED, woffset, wsize, &d); + if (r < 0) + return r; c = context_add(m, context); if (!c) @@ -534,19 +561,10 @@ static int add_mmap( if (!f) goto outofmem; - w = window_add(m); + w = window_add(m, f, prot, keep_always, woffset, wsize, d); if (!w) goto outofmem; - w->keep_always = keep_always; - w->ptr = d; - w->offset = woffset; - w->prot = prot; - w->size = wsize; - w->fd = f; - - LIST_PREPEND(by_fd, f->windows, w); - context_detach_window(c); c->window = w; LIST_PREPEND(by_window, w->contexts, c); diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index 7a3aaf0cab..5ff2335efe 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -2638,7 +2638,7 @@ _public_ int sd_journal_enumerate_fields(sd_journal *j, const char **field) { } } - /* We use OBJECT_UNUSED here, so that the iteator below doesn't remove our mmap window */ + /* We use OBJECT_UNUSED here, so that the iterator below doesn't remove our mmap window */ r = journal_file_move_to_object(f, OBJECT_UNUSED, j->fields_offset, &o); if (r < 0) return r; diff --git a/src/journal/test-catalog.c b/src/journal/test-catalog.c index 25980b7744..ae936f6419 100644 --- a/src/journal/test-catalog.c +++ b/src/journal/test-catalog.c @@ -46,61 +46,135 @@ static const char *no_catalog_dirs[] = { NULL }; -static void test_import(Hashmap *h, struct strbuf *sb, - const char* contents, ssize_t size, int code) { +static Hashmap * test_import(const char* contents, ssize_t size, int code) { int r; char name[] = "/tmp/test-catalog.XXXXXX"; _cleanup_close_ int fd; + Hashmap *h; + + if (size < 0) + size = strlen(contents); + + assert_se(h = hashmap_new(&catalog_hash_ops)); fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); assert_se(write(fd, contents, size) == size); - r = catalog_import_file(h, sb, name); + r = catalog_import_file(h, name); assert_se(r == code); unlink(name); -} -static void test_catalog_importing(void) { - Hashmap *h; - struct strbuf *sb; + return h; +} - assert_se(h = hashmap_new(&catalog_hash_ops)); - assert_se(sb = strbuf_new()); +static void test_catalog_import_invalid(void) { + _cleanup_hashmap_free_free_free_ Hashmap *h = NULL; -#define BUF "xxx" - test_import(h, sb, BUF, sizeof(BUF), -EINVAL); -#undef BUF + h = test_import("xxx", -1, -EINVAL); assert_se(hashmap_isempty(h)); - log_debug("----------------------------------------"); +} -#define BUF \ +static void test_catalog_import_badid(void) { + _cleanup_hashmap_free_free_free_ Hashmap *h = NULL; + const char *input = "-- 0027229ca0644181a76c4e92458afaff dededededededededededededededede\n" \ "Subject: message\n" \ "\n" \ -"payload\n" - test_import(h, sb, BUF, sizeof(BUF), -EINVAL); -#undef BUF +"payload\n"; + h = test_import(input, -1, -EINVAL); +} - log_debug("----------------------------------------"); +static void test_catalog_import_one(void) { + _cleanup_hashmap_free_free_free_ Hashmap *h = NULL; + char *payload; + Iterator j; -#define BUF \ + const char *input = "-- 0027229ca0644181a76c4e92458afaff dededededededededededededededed\n" \ "Subject: message\n" \ "\n" \ -"payload\n" - test_import(h, sb, BUF, sizeof(BUF), 0); -#undef BUF +"payload\n"; + const char *expect = +"Subject: message\n" \ +"\n" \ +"payload\n"; + h = test_import(input, -1, 0); assert_se(hashmap_size(h) == 1); - log_debug("----------------------------------------"); + HASHMAP_FOREACH(payload, h, j) { + assert_se(streq(expect, payload)); + } +} - hashmap_free_free(h); - strbuf_cleanup(sb); +static void test_catalog_import_merge(void) { + _cleanup_hashmap_free_free_free_ Hashmap *h = NULL; + char *payload; + Iterator j; + + const char *input = +"-- 0027229ca0644181a76c4e92458afaff dededededededededededededededed\n" \ +"Subject: message\n" \ +"Defined-By: me\n" \ +"\n" \ +"payload\n" \ +"\n" \ +"-- 0027229ca0644181a76c4e92458afaff dededededededededededededededed\n" \ +"Subject: override subject\n" \ +"X-Header: hello\n" \ +"\n" \ +"override payload\n"; + + const char *combined = +"Subject: override subject\n" \ +"X-Header: hello\n" \ +"Subject: message\n" \ +"Defined-By: me\n" \ +"\n" \ +"override payload\n"; + + h = test_import(input, -1, 0); + assert_se(hashmap_size(h) == 1); + + HASHMAP_FOREACH(payload, h, j) { + assert_se(streq(combined, payload)); + } } +static void test_catalog_import_merge_no_body(void) { + _cleanup_hashmap_free_free_free_ Hashmap *h = NULL; + char *payload; + Iterator j; + + const char *input = +"-- 0027229ca0644181a76c4e92458afaff dededededededededededededededed\n" \ +"Subject: message\n" \ +"Defined-By: me\n" \ +"\n" \ +"payload\n" \ +"\n" \ +"-- 0027229ca0644181a76c4e92458afaff dededededededededededededededed\n" \ +"Subject: override subject\n" \ +"X-Header: hello\n" \ +"\n"; + + const char *combined = +"Subject: override subject\n" \ +"X-Header: hello\n" \ +"Subject: message\n" \ +"Defined-By: me\n" \ +"\n" \ +"payload\n"; + + h = test_import(input, -1, 0); + assert_se(hashmap_size(h) == 1); + + HASHMAP_FOREACH(payload, h, j) { + assert_se(streq(combined, payload)); + } +} static const char* database = NULL; @@ -166,7 +240,11 @@ int main(int argc, char *argv[]) { test_catalog_file_lang(); - test_catalog_importing(); + test_catalog_import_invalid(); + test_catalog_import_badid(); + test_catalog_import_one(); + test_catalog_import_merge(); + test_catalog_import_merge_no_body(); test_catalog_update(); diff --git a/src/resolve/resolved-dns-dnssec.c b/src/resolve/resolved-dns-dnssec.c index 21cf161494..701b735a5d 100644 --- a/src/resolve/resolved-dns-dnssec.c +++ b/src/resolve/resolved-dns-dnssec.c @@ -1248,7 +1248,7 @@ static int nsec3_is_good(DnsResourceRecord *rr, DnsResourceRecord *nsec3) { if (rr->key->type != DNS_TYPE_NSEC3) return 0; - /* RFC 5155, Section 8.2 says we MUST ignore NSEC3 RRs with flags != 0 or 1 */ + /* RFC 5155, Section 8.2 says we MUST ignore NSEC3 RRs with flags != 0 or 1 */ if (!IN_SET(rr->nsec3.flags, 0, 1)) return 0; diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c index 5cbe20832f..0bf268398c 100644 --- a/src/resolve/resolved-dns-packet.c +++ b/src/resolve/resolved-dns-packet.c @@ -2170,7 +2170,7 @@ int dns_packet_extract(DnsPacket *p) { } if (!dns_name_is_root(DNS_RESOURCE_KEY_NAME(rr->key))) { - /* If the OPT RR qis not owned by the root domain, then it is bad, let's ignore + /* If the OPT RR is not owned by the root domain, then it is bad, let's ignore * it. */ log_debug("OPT RR is not owned by root domain, ignoring."); bad_opt = true; diff --git a/src/resolve/resolved-dns-rr.c b/src/resolve/resolved-dns-rr.c index 783ec7516c..33e6f0014b 100644 --- a/src/resolve/resolved-dns-rr.c +++ b/src/resolve/resolved-dns-rr.c @@ -1450,7 +1450,7 @@ static int dns_resource_record_compare_func(const void *a, const void *b) { if (dns_resource_record_equal(x, y)) return 0; - /* This is a bit dirty, we don't implement proper odering, but + /* This is a bit dirty, we don't implement proper ordering, but * the hashtable doesn't need ordering anyway, hence we don't * care. */ return x < y ? -1 : 1; diff --git a/test/sys.tar.xz b/test/sys.tar.xz Binary files differindex 49ee8027b2..052c77d182 100644 --- a/test/sys.tar.xz +++ b/test/sys.tar.xz diff --git a/test/udev-test.pl b/test/udev-test.pl index 0a89303570..638c3e8f4e 100755 --- a/test/udev-test.pl +++ b/test/udev-test.pl @@ -700,7 +700,7 @@ EOF desc => "big major number test", devpath => "/devices/virtual/misc/misc-fake1", exp_name => "node", - exp_majorminor => "4095:1", + exp_majorminor => "511:1", rules => <<EOF KERNEL=="misc-fake1", SYMLINK+="node" EOF @@ -709,7 +709,7 @@ EOF desc => "big major and big minor number test", devpath => "/devices/virtual/misc/misc-fake89999", exp_name => "node", - exp_majorminor => "4095:89999", + exp_majorminor => "511:89999", rules => <<EOF KERNEL=="misc-fake89999", SYMLINK+="node" EOF diff --git a/units/rescue.service.in b/units/rescue.service.in index 6c202174d3..92553f61dd 100644 --- a/units/rescue.service.in +++ b/units/rescue.service.in @@ -17,7 +17,7 @@ Before=shutdown.target Environment=HOME=/root WorkingDirectory=-/root ExecStartPre=-/bin/plymouth quit -ExecStartPre=-/bin/echo -e 'Welcome to emergency mode! After logging in, type "journalctl -xb" to view\\nsystem logs, "systemctl reboot" to reboot, "systemctl default" or ^D to\\nboot into default mode.' +ExecStartPre=-/bin/echo -e 'Welcome to rescue mode! After logging in, type "journalctl -xb" to view\\nsystem logs, "systemctl reboot" to reboot, "systemctl default" or ^D to\\nboot into default mode.' ExecStart=-/bin/sh -c "@SULOGIN@; @SYSTEMCTL@ --job-mode=fail --no-block default" Type=idle StandardInput=tty-force |