├── .github └── workflows │ └── ci.yml ├── .gitignore ├── LICENSE.GPL2 ├── LICENSE.LGPL2.1 ├── Makefile.am ├── README ├── TODO ├── autogen.sh ├── configure.ac ├── m4 ├── .gitignore ├── arch.m4 ├── attributes.m4 └── ax_normalize_path.m4 ├── man ├── .gitignore ├── bootchart.conf.xml ├── custom-man.xsl ├── standard-conf.xml ├── standard-options.xml └── systemd-bootchart.xml ├── po └── .gitignore ├── src ├── Makefile ├── _sd-common.h ├── alloc-util.c ├── alloc-util.h ├── architecture.h ├── attributes.h ├── bootchart.c ├── bootchart.conf ├── bootchart.h ├── build.h ├── cgroup-util.c ├── cgroup-util.h ├── conf-files.c ├── conf-files.h ├── conf-parser.c ├── conf-parser.h ├── def.h ├── dirent-util.c ├── dirent-util.h ├── fd-util.c ├── fd-util.h ├── fileio.c ├── fileio.h ├── formats-util.h ├── fs-util.c ├── fs-util.h ├── hash-funcs.c ├── hash-funcs.h ├── hashmap.c ├── hashmap.h ├── io-util.c ├── io-util.h ├── list.h ├── log.c ├── log.h ├── macro.h ├── mempool.c ├── mempool.h ├── missing.h ├── parse-util.c ├── parse-util.h ├── path-util.c ├── path-util.h ├── process-util.c ├── process-util.h ├── random-util.c ├── random-util.h ├── sd-messages.h ├── set.h ├── siphash24.c ├── siphash24.h ├── stdio-util.h ├── store.c ├── store.h ├── string-util.c ├── string-util.h ├── strv.c ├── strv.h ├── strxcpyx.c ├── strxcpyx.h ├── svg.c ├── svg.h ├── terminal-util.c ├── terminal-util.h ├── time-util.c ├── time-util.h ├── unaligned.h ├── utf8.c ├── utf8.h ├── util.c └── util.h ├── tests └── run └── units ├── .gitignore └── systemd-bootchart.service.in /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | branches: 9 | - main 10 | 11 | jobs: 12 | unit-test: 13 | runs-on: ubuntu-22.04 14 | concurrency: 15 | group: ${{ github.workflow }}-${{ toJSON(matrix.env) }}-${{ github.ref }} 16 | cancel-in-progress: true 17 | strategy: 18 | fail-fast: false 19 | matrix: 20 | env: 21 | - { CC: "gcc", CFLAGS: "-fno-omit-frame-pointer -fsanitize=undefined,address -ggdb3 -Og -fvar-tracking-assignments" } 22 | - { CC: "clang", CFLAGS: "-fno-omit-frame-pointer -fsanitize=undefined,address -ggdb3 -Og" } 23 | env: ${{ matrix.env }} 24 | steps: 25 | - uses: actions/checkout@v3 26 | 27 | - name: Install dependencies 28 | run: | 29 | sudo apt-get update 30 | sudo apt-get install intltool gcc llvm clang 31 | 32 | - name: ${{ format('Build check ({0})', env.CC) }} 33 | run: | 34 | ./autogen.sh 35 | ./configure --without-libsystemd --disable-man || cat config.log 36 | make -j 37 | make -j -k check 38 | 39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.a 2 | *.cache 3 | *.html 4 | *.la 5 | *.lo 6 | *.log 7 | *.o 8 | *.plist 9 | *.pyc 10 | *.stamp 11 | *.swp 12 | *.trs 13 | *~ 14 | .config.args 15 | .deps/ 16 | .dirstamp 17 | .libs/ 18 | /*.gcda 19 | /*.gcno 20 | /*.tar.bz2 21 | /*.tar.gz 22 | /*.tar.xz 23 | /build-aux 24 | /libtool 25 | /Makefile 26 | /TAGS 27 | /GPATH 28 | /GRTAGS 29 | /GSYMS 30 | /GTAGS 31 | /systemd-bootchart 32 | Makefile.in 33 | aclocal.m4 34 | config.h 35 | config.h.in 36 | config.log 37 | config.status 38 | configure 39 | stamp-* 40 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | # -*- Mode: makefile; indent-tabs-mode: t -*- 2 | # 3 | # This file is part of systemd-bootchart 4 | # 5 | # systemd is free software; you can redistribute it and/or modify it 6 | # under the terms of the GNU Lesser General Public License as published by 7 | # the Free Software Foundation; either version 2.1 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # systemd is distributed in the hope that it will be useful, but 11 | # WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | # Lesser General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU Lesser General Public License 16 | # along with systemd; If not, see . 17 | 18 | ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} 19 | AM_MAKEFLAGS = --no-print-directory 20 | AUTOMAKE_OPTIONS = color-tests parallel-tests 21 | 22 | GCC_COLORS ?= 'ooh, shiny!' 23 | export GCC_COLORS 24 | 25 | SUBDIRS = . 26 | 27 | # remove targets if the command fails 28 | .DELETE_ON_ERROR: 29 | 30 | # keep intermediate files 31 | .SECONDARY: 32 | 33 | # Keep the test-suite.log 34 | .PRECIOUS: $(TEST_SUITE_LOG) Makefile 35 | 36 | # Dirs of external packages 37 | systemdir=@systemdir@ 38 | 39 | # And these are the special ones for / 40 | rootprefix=@rootprefix@ 41 | rootbindir=$(rootprefix)/bin 42 | rootlibexecdir=$(rootprefix)/lib/systemd 43 | pkgsysconfdir=$(sysconfdir)/systemd 44 | systemunitdir=$(rootprefix)/lib/systemd/system 45 | 46 | AM_CFLAGS = $(OUR_CFLAGS) 47 | AM_LDFLAGS = $(OUR_LDFLAGS) 48 | AM_CPPFLAGS = \ 49 | -include $(top_builddir)/config.h \ 50 | -DPKGSYSCONFDIR=\"$(pkgsysconfdir)\" \ 51 | -DSYSTEM_CONFIG_UNIT_PATH=\"$(pkgsysconfdir)/system\" \ 52 | -DSYSTEM_DATA_UNIT_PATH=\"$(systemunitdir)\" \ 53 | -DSYSTEMD_BINARY_PATH=\"$(rootlibexecdir)/systemd\" \ 54 | -DROOTPREFIX=\"$(rootprefix)\" \ 55 | -DLIBDIR=\"$(libdir)\" \ 56 | -DROOTLIBDIR=\"$(rootlibdir)\" \ 57 | -DROOTLIBEXECDIR=\"$(rootlibexecdir)\" \ 58 | -I $(top_srcdir)/src 59 | 60 | ##################################################### 61 | 62 | dist_noinst_DATA = \ 63 | LICENSE.LGPL2.1 \ 64 | LICENSE.GPL2 65 | 66 | EXTRA_DIST = \ 67 | man/bootchart.conf.xml \ 68 | man/systemd-bootchart.xml \ 69 | man/custom-man.xsl \ 70 | man/standard-conf.xml \ 71 | man/standard-options.xml \ 72 | units/systemd-bootchart.service.in \ 73 | tests/run 74 | 75 | MANPAGES = man/bootchart.conf.5 man/systemd-bootchart.1 76 | MANPAGES_ALIAS = man/bootchart.conf.d.5 77 | 78 | if COND_man 79 | MAYBE_MANPAGES = $(MANPAGES) $(MANPAGES_ALIAS) 80 | endif 81 | man_MANS = $(MAYBE_MANPAGES) 82 | 83 | man/bootchart.conf.d.5: man/bootchart.conf.5 84 | 85 | XSLTPROC_FLAGS = \ 86 | --nonet \ 87 | --xinclude \ 88 | --stringparam man.output.quietly 1 \ 89 | --stringparam funcsynopsis.style ansi \ 90 | --stringparam man.authors.section.enabled 0 \ 91 | --stringparam man.copyright.section.enabled 0 \ 92 | --stringparam systemd.version $(VERSION) \ 93 | --path '$(builddir)/man:$(srcdir)/man' 94 | 95 | XSLT = $(if $(XSLTPROC), $(XSLTPROC), xsltproc) 96 | XSLTPROC_PROCESS_MAN = \ 97 | $(AM_V_XSLT)$(XSLT) -o $@ $(XSLTPROC_FLAGS) $(srcdir)/man/custom-man.xsl $< 98 | 99 | man/%.1: man/%.xml man/custom-man.xsl 100 | $(XSLTPROC_PROCESS_MAN) 101 | 102 | man/%.5: man/%.xml man/custom-man.xsl 103 | $(XSLTPROC_PROCESS_MAN) 104 | 105 | ##################################################### 106 | 107 | libutils_la_SOURCES = \ 108 | src/alloc-util.c \ 109 | src/alloc-util.h \ 110 | src/architecture.h \ 111 | src/attributes.h \ 112 | src/build.h \ 113 | src/cgroup-util.c \ 114 | src/cgroup-util.h \ 115 | src/conf-files.c \ 116 | src/conf-files.h \ 117 | src/conf-parser.c \ 118 | src/conf-parser.h \ 119 | src/def.h \ 120 | src/dirent-util.c \ 121 | src/dirent-util.h \ 122 | src/fd-util.c \ 123 | src/fd-util.h \ 124 | src/fileio.c \ 125 | src/fileio.h \ 126 | src/formats-util.h \ 127 | src/fs-util.c \ 128 | src/fs-util.h \ 129 | src/hash-funcs.c \ 130 | src/hash-funcs.h \ 131 | src/hashmap.c \ 132 | src/hashmap.h \ 133 | src/io-util.c \ 134 | src/io-util.h \ 135 | src/list.h \ 136 | src/log.c \ 137 | src/log.h \ 138 | src/macro.h \ 139 | src/mempool.c \ 140 | src/mempool.h \ 141 | src/missing.h \ 142 | src/parse-util.c \ 143 | src/parse-util.h \ 144 | src/path-util.c \ 145 | src/path-util.h \ 146 | src/process-util.c \ 147 | src/process-util.h \ 148 | src/random-util.c \ 149 | src/random-util.h \ 150 | src/_sd-common.h \ 151 | src/sd-messages.h \ 152 | src/set.h \ 153 | src/siphash24.c \ 154 | src/siphash24.h \ 155 | src/stdio-util.h \ 156 | src/string-util.c \ 157 | src/string-util.h \ 158 | src/strv.c \ 159 | src/strv.h \ 160 | src/strxcpyx.c \ 161 | src/strxcpyx.h \ 162 | src/terminal-util.c \ 163 | src/terminal-util.h \ 164 | src/time-util.c \ 165 | src/time-util.h \ 166 | src/unaligned.h \ 167 | src/utf8.c \ 168 | src/utf8.h \ 169 | src/util.c \ 170 | src/util.h 171 | 172 | libutils_la_CFLAGS = \ 173 | $(AM_CFLAGS) \ 174 | $(LIBSYSTEMD_CFLAGS) 175 | 176 | libutils_la_LIBADD = \ 177 | $(LIBSYSTEMD_LIBS) 178 | 179 | noinst_LTLIBRARIES = libutils.la 180 | 181 | ##################################################### 182 | 183 | systemd_bootchart_SOURCES = \ 184 | src/bootchart.c \ 185 | src/bootchart.h \ 186 | src/store.c \ 187 | src/store.h \ 188 | src/svg.c \ 189 | src/svg.h 190 | 191 | systemd_bootchart_LDADD = \ 192 | libutils.la 193 | 194 | ##################################################### 195 | 196 | TESTS = tests/run 197 | 198 | substitutions = \ 199 | '|rootlibexecdir=$(rootlibexecdir)|' 200 | 201 | SED_PROCESS = \ 202 | $(AM_V_GEN)$(MKDIR_P) $(dir $@) && \ 203 | $(SED) $(subst '|,-e 's|@,$(subst =,\@|,$(subst |',|g',$(substitutions)))) \ 204 | < $< > $@ 205 | 206 | units/%: units/%.in 207 | $(SED_PROCESS) 208 | 209 | man/%: man/%.in 210 | $(SED_PROCESS) 211 | 212 | rootlibexec_PROGRAMS = systemd-bootchart 213 | dist_pkgsysconf_DATA = src/bootchart.conf 214 | nodist_systemunit_DATA = units/systemd-bootchart.service 215 | 216 | in_files = $(filter %.in,$(EXTRA_DIST)) 217 | 218 | CLEANFILES = \ 219 | $(MANPAGES) $(MANPAGES_ALIAS) \ 220 | $(pkgconfigdata_DATA) \ 221 | $(pkgconfiglib_DATA) \ 222 | $(in_files:.in=) 223 | 224 | install-exec-hook: $(INSTALL_EXEC_HOOKS) 225 | 226 | uninstall-hook: $(UNINSTALL_DATA_HOOKS) $(UNINSTALL_EXEC_HOOKS) 227 | 228 | install-data-hook: $(INSTALL_DATA_HOOKS) 229 | 230 | .PHONY: git-tag 231 | git-tag: 232 | git tag -s "v$(VERSION)" -m "systemd $(VERSION)" 233 | 234 | .PHONY: git-tar 235 | git-tar: 236 | git archive --format=tar --prefix=systemd-$(VERSION)/ HEAD | xz > systemd-$(VERSION).tar.xz 237 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | For systemd-bootchart, several proc debug interfaces are required in the kernel config: 2 | CONFIG_SCHEDSTATS 3 | below is optional, for additional info: 4 | CONFIG_SCHED_DEBUG 5 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | - plot per-process IO utilization 2 | - group processes based on service association (cgroups) 3 | - document initcall_debug 4 | - kernel cmdline "bootchart" option for simplicity? 5 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # This file is part of systemd-journal-remote. 4 | # 5 | # systemd is free software; you can redistribute it and/or modify it 6 | # under the terms of the GNU Lesser General Public License as published by 7 | # the Free Software Foundation; either version 2.1 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # systemd is distributed in the hope that it will be useful, but 11 | # WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | # Lesser General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU Lesser General Public License 16 | # along with systemd; If not, see . 17 | 18 | set -e 19 | 20 | oldpwd=$(pwd) 21 | topdir=$(dirname $0) 22 | cd $topdir 23 | 24 | if [ -f .git/hooks/pre-commit.sample ] && [ ! -f .git/hooks/pre-commit ]; then 25 | # This part is allowed to fail 26 | cp -p .git/hooks/pre-commit.sample .git/hooks/pre-commit && \ 27 | chmod +x .git/hooks/pre-commit && \ 28 | echo "Activated pre-commit hook." || : 29 | fi 30 | 31 | intltoolize --force --automake 32 | autoreconf --force --install --symlink 33 | 34 | libdir() { 35 | echo $(cd "$1/$(gcc -print-multi-os-directory)"; pwd) 36 | } 37 | 38 | args="\ 39 | --sysconfdir=/etc \ 40 | --localstatedir=/var \ 41 | --libdir=$(libdir /usr/lib) \ 42 | " 43 | 44 | if [ -f "$topdir/.config.args" ]; then 45 | args="$args $(cat $topdir/.config.args)" 46 | fi 47 | 48 | if [ ! -L /bin ]; then 49 | args="$args \ 50 | --with-rootprefix=/ \ 51 | --with-rootlibdir=$(libdir /lib) \ 52 | " 53 | fi 54 | 55 | cd $oldpwd 56 | 57 | if [ "x$1" = "xc" ]; then 58 | $topdir/configure CFLAGS='-g -O0 -ftrapv' $args 59 | make clean 60 | else 61 | echo 62 | echo "----------------------------------------------------------------" 63 | echo "Initialized build system. For a common configuration please run:" 64 | echo "----------------------------------------------------------------" 65 | echo 66 | echo "$topdir/configure CFLAGS='-g -O0 -ftrapv' $args" 67 | echo 68 | fi 69 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # 2 | # This file is part of systemd-bootchart. 3 | # 4 | # systemd is free software; you can redistribute it and/or modify it 5 | # under the terms of the GNU Lesser General Public License as published by 6 | # the Free Software Foundation; either version 2.1 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # systemd is distributed in the hope that it will be useful, but 10 | # WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public License 15 | # along with systemd; If not, see . 16 | 17 | AC_PREREQ([2.64]) 18 | 19 | AC_INIT([systemd-bootchart], 20 | [235], 21 | [https://github.com/systemd/systemd-bootchart/issues], 22 | [systemd-bootchart], 23 | [https://github.com/systemd/systemd-bootchart/]) 24 | 25 | AC_CONFIG_SRCDIR([src/bootchart.c]) 26 | AC_CONFIG_MACRO_DIR([m4]) 27 | AC_CONFIG_HEADERS([config.h]) 28 | AC_CONFIG_AUX_DIR([build-aux]) 29 | 30 | AC_USE_SYSTEM_EXTENSIONS 31 | AC_SYS_LARGEFILE 32 | AC_PREFIX_DEFAULT([/usr]) 33 | AM_MAINTAINER_MODE([enable]) 34 | AM_INIT_AUTOMAKE([foreign 1.11 -Wall -Wno-portability silent-rules tar-pax no-dist-gzip dist-xz subdir-objects parallel-tests]) 35 | AM_SILENT_RULES([yes]) 36 | AC_CANONICAL_HOST 37 | AC_DEFINE_UNQUOTED([CANONICAL_HOST], "$host", [Canonical host string.]) 38 | LT_PREREQ(2.2) 39 | LT_INIT([disable-static]) 40 | 41 | AC_PROG_CC_C99 42 | 43 | SET_ARCH(X86_64, x86_64*) 44 | SET_ARCH(IA32, i*86*) 45 | SET_ARCH(MIPS, mips*) 46 | SET_ARCH(AARCH64, aarch64*) 47 | SET_ARCH(RISCV64, riscv64*) 48 | SET_ARCH(RISCV32, riscv32*) 49 | 50 | AC_CHECK_SIZEOF(pid_t) 51 | AC_CHECK_SIZEOF(uid_t) 52 | AC_CHECK_SIZEOF(gid_t) 53 | AC_CHECK_SIZEOF(time_t) 54 | AC_CHECK_SIZEOF(dev_t) 55 | AC_CHECK_SIZEOF(rlim_t,,[ 56 | #include 57 | #include 58 | ]) 59 | 60 | AC_CHECK_DECLS([gettid, getrandom], [], [], [[ 61 | #include 62 | #include 63 | #include 64 | #include 65 | ]]) 66 | 67 | AC_ARG_WITH(libsystemd, 68 | AS_HELP_STRING([--without-libsystemd], [Disable use of libsystemd for journal output]), 69 | [], [with_libsystemd=yes]) 70 | 71 | AS_IF([test "x$with_libsystemd" != xno], 72 | [PKG_CHECK_MODULES(LIBSYSTEMD, [libsystemd >= 221], 73 | [AC_DEFINE([HAVE_LIBSYSTEMD],[1],[Define if you have libsystemd])], 74 | [AC_MSG_ERROR([*** libsystemd library not found])] 75 | )] 76 | ) 77 | 78 | CC_CHECK_FLAGS_APPEND([with_cflags], [CFLAGS], [\ 79 | -pipe \ 80 | -Wall \ 81 | -Wextra \ 82 | -Wundef \ 83 | "-Wformat=2 -Wformat-security -Wformat-nonliteral" \ 84 | -Wlogical-op \ 85 | -Wmissing-include-dirs \ 86 | -Wold-style-definition \ 87 | -Wpointer-arith \ 88 | -Winit-self \ 89 | -Wdeclaration-after-statement \ 90 | -Wfloat-equal \ 91 | -Wsuggest-attribute=noreturn \ 92 | -Werror=missing-prototypes \ 93 | -Werror=implicit-function-declaration \ 94 | -Werror=missing-declarations \ 95 | -Werror=return-type \ 96 | -Werror=shadow \ 97 | -Wstrict-prototypes \ 98 | -Wredundant-decls \ 99 | -Wmissing-noreturn \ 100 | -Wshadow \ 101 | -Wendif-labels \ 102 | -Wstrict-aliasing=2 \ 103 | -Wwrite-strings \ 104 | -Wno-unused-parameter \ 105 | -Wno-missing-field-initializers \ 106 | -Wno-unused-result \ 107 | -Wno-format-signedness \ 108 | -Werror=overflow \ 109 | -Wdate-time \ 110 | -Wnested-externs \ 111 | -ffast-math \ 112 | -fno-common \ 113 | -fdiagnostics-show-option \ 114 | -fno-strict-aliasing \ 115 | -fvisibility=hidden \ 116 | -fstack-protector \ 117 | -fstack-protector-strong \ 118 | -fPIE \ 119 | --param=ssp-buffer-size=4]) 120 | 121 | AS_CASE([$CC], [*clang*], 122 | [CC_CHECK_FLAGS_APPEND([with_cppflags], [CPPFLAGS], [\ 123 | -Wno-typedef-redefinition \ 124 | -Wno-gnu-variable-sized-type-not-at-end \ 125 | ])]) 126 | 127 | AS_CASE([$CFLAGS], [*-O[[12345sz\ ]]*], 128 | [CC_CHECK_FLAGS_APPEND([with_cflags], [CFLAGS], [\ 129 | -flto -ffat-lto-objects])], 130 | [AC_MSG_RESULT([skipping -flto, optimization not enabled])]) 131 | AC_SUBST([OUR_CFLAGS], "$with_cflags $sanitizer_cflags") 132 | 133 | AS_CASE([$CFLAGS], [*-O[[12345sz\ ]]*], 134 | [CC_CHECK_FLAGS_APPEND([with_cppflags], [CPPFLAGS], [\ 135 | -Wp,-D_FORTIFY_SOURCE=2])], 136 | [AC_MSG_RESULT([skipping -D_FORTIFY_SOURCE, optimization not enabled])]) 137 | AC_SUBST([OUR_CPPFLAGS], "$with_cppflags $sanitizer_cppflags") 138 | 139 | AS_CASE([$CFLAGS], [*-O[[12345sz\ ]]*], 140 | [CC_CHECK_FLAGS_APPEND([with_ldflags], [LDFLAGS], [\ 141 | -Wl,--gc-sections])], 142 | [AC_MSG_RESULT([skipping --gc-sections, optimization not enabled])]) 143 | AC_SUBST([OUR_CFLAGS], "$with_ldflags $sanitizer_cflags") 144 | 145 | AS_CASE([$CFLAGS], [*-O[[12345sz\ ]]*], 146 | [CC_CHECK_FLAGS_APPEND([with_cflags], [CFLAGS], [\ 147 | -ffunction-sections -fdata-sections])], 148 | [AC_MSG_RESULT([skipping -ffunction/data-section, optimization not enabled])]) 149 | AC_SUBST([OUR_CFLAGS], "$with_cflags $sanitizer_cflags") 150 | 151 | CC_CHECK_FLAGS_APPEND([with_ldflags], [LDFLAGS], [\ 152 | -Wl,--as-needed \ 153 | -Wl,--no-undefined \ 154 | -Wl,-z,relro \ 155 | -Wl,-z,now \ 156 | -pie]) 157 | AC_SUBST([OUR_LDFLAGS], "$with_ldflags $sanitizer_ldflags") 158 | 159 | AC_ARG_WITH([rootprefix], 160 | AS_HELP_STRING([--with-rootprefix=DIR], [rootfs directory prefix for config files and binaries necessary for boot]), 161 | [], [with_rootprefix=${ac_default_prefix}]) 162 | # --with-rootprefix= (empty) should default to "/" but AX_NORMALIZE_PATH 163 | # defaults those to ".", solve that here for now until we can find a suitable 164 | # fix for AX_NORMALIZE_PATH upstream at autoconf-archive. 165 | # See: https://github.com/systemd/systemd/issues/54 166 | if test "x${with_rootprefix}" = "x"; then 167 | with_rootprefix="/" 168 | fi 169 | AX_NORMALIZE_PATH([with_rootprefix]) 170 | 171 | AC_ARG_WITH([rootlibdir], 172 | AS_HELP_STRING([--with-rootlibdir=DIR], [Root directory for libraries necessary for boot]), 173 | [], 174 | [with_rootlibdir=${libdir}]) 175 | 176 | AC_SUBST([rootprefix], [$with_rootprefix]) 177 | AC_SUBST([rootlibdir], [$with_rootlibdir]) 178 | 179 | AC_ARG_ENABLE([man], 180 | AS_HELP_STRING([--disable-man],[Build the man pages (default: yes)]), 181 | [build_man=$enableval], 182 | [build_man=yes]) 183 | 184 | AC_PATH_PROG([XSLTPROC], [xsltproc]) 185 | AS_IF([test -z "$XSLTPROC" -a "$build_man" = "yes"], 186 | [AC_MSG_ERROR([*** xsltproc is required for man pages])]) 187 | 188 | AM_CONDITIONAL([COND_man],[test "$build_man" = "yes"]) 189 | 190 | AC_CONFIG_FILES([ 191 | Makefile 192 | ]) 193 | 194 | AC_OUTPUT 195 | AC_MSG_RESULT([ 196 | $PACKAGE_NAME $VERSION 197 | 198 | prefix: ${prefix} 199 | sysconf dir: ${sysconfdir} 200 | datarootdir: ${datarootdir} 201 | includedir: ${includedir} 202 | lib dir: ${libdir} 203 | rootlib dir: ${with_rootlibdir} 204 | 205 | CFLAGS: ${OUR_CFLAGS} ${CFLAGS} 206 | CPPFLAGS: ${OUR_CPPFLAGS} ${CPPFLAGS} 207 | LDFLAGS: ${OUR_LDFLAGS} ${LDFLAGS} 208 | ]) 209 | -------------------------------------------------------------------------------- /m4/.gitignore: -------------------------------------------------------------------------------- 1 | intltool.m4 2 | libtool.m4 3 | ltoptions.m4 4 | ltsugar.m4 5 | ltversion.m4 6 | lt~obsolete.m4 7 | -------------------------------------------------------------------------------- /m4/arch.m4: -------------------------------------------------------------------------------- 1 | 2 | dnl SET_ARCH(ARCHNAME, PATTERN) 3 | dnl 4 | dnl Define ARCH_ condition if the pattern match with the current 5 | dnl architecture 6 | dnl 7 | AC_DEFUN([SET_ARCH], [ 8 | cpu_$1=false 9 | case "$host" in 10 | $2) cpu_$1=true ;; 11 | esac 12 | AM_CONDITIONAL(AS_TR_CPP(ARCH_$1), [test "x$cpu_$1" = xtrue]) 13 | ]) 14 | -------------------------------------------------------------------------------- /m4/ax_normalize_path.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_normalize_path.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_NORMALIZE_PATH(VARNAME, [REFERENCE_STRING]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Perform some cleanups on the value of $VARNAME (interpreted as a path): 12 | # 13 | # - empty paths are changed to '.' 14 | # - trailing slashes are removed 15 | # - repeated slashes are squeezed except a leading doubled slash '//' 16 | # (which might indicate a networked disk on some OS). 17 | # 18 | # REFERENCE_STRING is used to turn '/' into '\' and vice-versa: if 19 | # REFERENCE_STRING contains some backslashes, all slashes and backslashes 20 | # are turned into backslashes, otherwise they are all turned into slashes. 21 | # 22 | # This makes processing of DOS filenames quite easier, because you can 23 | # turn a filename to the Unix notation, make your processing, and turn it 24 | # back to original notation. 25 | # 26 | # filename='A:\FOO\\BAR\' 27 | # old_filename="$filename" 28 | # # Switch to the unix notation 29 | # AX_NORMALIZE_PATH([filename], ["/"]) 30 | # # now we have $filename = 'A:/FOO/BAR' and we can process it as if 31 | # # it was a Unix path. For instance let's say that you want 32 | # # to append '/subpath': 33 | # filename="$filename/subpath" 34 | # # finally switch back to the original notation 35 | # AX_NORMALIZE_PATH([filename], ["$old_filename"]) 36 | # # now $filename equals to 'A:\FOO\BAR\subpath' 37 | # 38 | # One good reason to make all path processing with the unix convention is 39 | # that backslashes have a special meaning in many cases. For instance 40 | # 41 | # expr 'A:\FOO' : 'A:\Foo' 42 | # 43 | # will return 0 because the second argument is a regex in which 44 | # backslashes have to be backslashed. In other words, to have the two 45 | # strings to match you should write this instead: 46 | # 47 | # expr 'A:\Foo' : 'A:\\Foo' 48 | # 49 | # Such behavior makes DOS filenames extremely unpleasant to work with. So 50 | # temporary turn your paths to the Unix notation, and revert them to the 51 | # original notation after the processing. See the macro 52 | # AX_COMPUTE_RELATIVE_PATHS for a concrete example of this. 53 | # 54 | # REFERENCE_STRING defaults to $VARIABLE, this means that slashes will be 55 | # converted to backslashes if $VARIABLE already contains some backslashes 56 | # (see $thirddir below). 57 | # 58 | # firstdir='/usr/local//share' 59 | # seconddir='C:\Program Files\\' 60 | # thirddir='C:\home/usr/' 61 | # AX_NORMALIZE_PATH([firstdir]) 62 | # AX_NORMALIZE_PATH([seconddir]) 63 | # AX_NORMALIZE_PATH([thirddir]) 64 | # # $firstdir = '/usr/local/share' 65 | # # $seconddir = 'C:\Program Files' 66 | # # $thirddir = 'C:\home\usr' 67 | # 68 | # LICENSE 69 | # 70 | # Copyright (c) 2008 Alexandre Duret-Lutz 71 | # 72 | # This program is free software; you can redistribute it and/or modify it 73 | # under the terms of the GNU General Public License as published by the 74 | # Free Software Foundation; either version 2 of the License, or (at your 75 | # option) any later version. 76 | # 77 | # This program is distributed in the hope that it will be useful, but 78 | # WITHOUT ANY WARRANTY; without even the implied warranty of 79 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 80 | # Public License for more details. 81 | # 82 | # You should have received a copy of the GNU General Public License along 83 | # with this program. If not, see . 84 | # 85 | # As a special exception, the respective Autoconf Macro's copyright owner 86 | # gives unlimited permission to copy, distribute and modify the configure 87 | # scripts that are the output of Autoconf when processing the Macro. You 88 | # need not follow the terms of the GNU General Public License when using 89 | # or distributing such scripts, even though portions of the text of the 90 | # Macro appear in them. The GNU General Public License (GPL) does govern 91 | # all other use of the material that constitutes the Autoconf Macro. 92 | # 93 | # This special exception to the GPL applies to versions of the Autoconf 94 | # Macro released by the Autoconf Archive. When you make and distribute a 95 | # modified version of the Autoconf Macro, you may extend this special 96 | # exception to the GPL to apply to your modified version as well. 97 | 98 | #serial 5 99 | 100 | AU_ALIAS([ADL_NORMALIZE_PATH], [AX_NORMALIZE_PATH]) 101 | AC_DEFUN([AX_NORMALIZE_PATH], 102 | [case ":[$]$1:" in 103 | # change empty paths to '.' 104 | ::) $1='.' ;; 105 | # strip trailing slashes 106 | :*[[\\/]]:) $1=`echo "[$]$1" | sed 's,[[\\/]]*[$],,'` ;; 107 | :*:) ;; 108 | esac 109 | # squeze repeated slashes 110 | case ifelse($2,,"[$]$1",$2) in 111 | # if the path contains any backslashes, turn slashes into backslashes 112 | *\\*) $1=`echo "[$]$1" | sed 's,\(.\)[[\\/]][[\\/]]*,\1\\\\,g'` ;; 113 | # if the path contains slashes, also turn backslashes into slashes 114 | *) $1=`echo "[$]$1" | sed 's,\(.\)[[\\/]][[\\/]]*,\1/,g'` ;; 115 | esac]) 116 | -------------------------------------------------------------------------------- /man/.gitignore: -------------------------------------------------------------------------------- 1 | /systemd.directives.xml 2 | /systemd.index.xml 3 | /*.[13578] 4 | /*.html 5 | /custom-entities.ent 6 | -------------------------------------------------------------------------------- /man/bootchart.conf.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 26 | 27 | 29 | 30 | bootchart.conf 31 | systemd 32 | 33 | 34 | 35 | Developer 36 | Auke 37 | Kok 38 | auke-jan.h.kok@intel.com 39 | 40 | 41 | 42 | 43 | 44 | bootchart.conf 45 | 5 46 | 47 | 48 | 49 | bootchart.conf 50 | bootchart.conf.d 51 | Boot performance analysis graphing tool configuration files 52 | 53 | 54 | 55 | /etc/systemd/bootchart.conf 56 | /etc/systemd/bootchart.conf.d/*.conf 57 | /run/systemd/bootchart.conf.d/*.conf 58 | /usr/lib/systemd/bootchart.conf.d/*.conf 59 | 60 | 61 | 62 | Description 63 | 64 | When starting, systemd-bootchart will read the configuration 65 | file /etc/systemd/bootchart.conf, followed by 66 | the files in the bootchart.conf.d 67 | directories. These configuration files determine logging 68 | parameters and graph output. 69 | 70 | 71 | 72 | 73 | 74 | Options 75 | 76 | 77 | 78 | 79 | Samples=500 80 | Configure the amount of samples to record in 81 | total before bootchart exits. Each sample will record at 82 | intervals defined by Frequency=. 83 | 84 | 85 | 86 | Frequency=25 87 | Configure the sample log frequency. This can 88 | be a fractional number, but must be larger than 0.0. Most 89 | systems can cope with values under 25-50 without impacting 90 | boot time severely. 91 | 92 | 93 | 94 | Relative=no 95 | Configures whether the left axis of the output 96 | graph equals time=0.0 (CLOCK_MONOTONIC 97 | start). This is useful for using bootchart at post-boot time 98 | to profile an already booted system, otherwise the graph would 99 | become extremely large. If set to yes, the horizontal axis 100 | starts at the first recorded sample instead of time=0.0. 101 | 102 | 103 | 104 | 105 | Filter=no 106 | Configures whether the resulting graph should 107 | omit tasks that did not contribute significantly to the boot. 108 | Processes that are too short-lived (only seen in one sample) 109 | or that do not consume any significant CPU time (less than 110 | 0.001sec) will not be displayed in the output 111 | graph. 112 | 113 | 114 | 115 | Output=[path] 116 | Configures the output directory for writing 117 | the graphs. By default, bootchart writes the graphs to 118 | /run/log. 119 | 120 | 121 | 122 | Init=[path] 123 | Configures bootchart to run a non-standard 124 | binary instead of 125 | /usr/lib/systemd/systemd. This option is 126 | only relevant if bootchart was invoked from the kernel command 127 | line with 128 | init=/usr/lib/systemd/systemd-bootchart. 129 | 130 | 131 | 132 | PlotMemoryUsage=no 133 | If set to yes, enables logging and graphing of 134 | processes' PSS memory consumption. 135 | 136 | 137 | 138 | PlotEntropyGraph=no 139 | If set to yes, enables logging and graphing of 140 | the kernel random entropy pool size. 141 | 142 | 143 | 144 | ScaleX=100 145 | Horizontal scaling factor for all variable 146 | graph components. 147 | 148 | 149 | 150 | ScaleY=20 151 | Vertical scaling factor for all variable graph 152 | components. 153 | 154 | 155 | 156 | ControlGroup=no 157 | Display process control group. 158 | 159 | 160 | 161 | 162 | Cmdline=no 163 | Display the full command line of each process. 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | See Also 172 | 173 | systemd-bootchart1, 174 | systemd.directives7 175 | 176 | 177 | 178 | 179 | -------------------------------------------------------------------------------- /man/custom-man.xsl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 21 | 22 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | .TH " 40 | 41 | 42 | 43 | 44 | 45 | " " 46 | 47 | " "" "systemd 48 | 49 | " " 50 | 51 | " 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | " 60 | 61 | " 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /man/standard-conf.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | Configuration Directories and Precedence 8 | 9 | Configuration files are read from directories in 10 | /etc/, /run/, and 11 | /usr/lib/, in order of precedence. 12 | Each configuration file in these configuration directories shall be named in 13 | the style of filename.conf. 14 | Files in /etc/ override files with the same name in 15 | /run/ and /usr/lib/. Files in 16 | /run/ override files with the same name in 17 | /usr/lib/. 18 | 19 | Packages should install their configuration files in 20 | /usr/lib/. Files in /etc/ are 21 | reserved for the local administrator, who may use this logic to override the 22 | configuration files installed by vendor packages. All configuration files 23 | are sorted by their filename in lexicographic order, regardless of which of 24 | the directories they reside in. If multiple files specify the same option, 25 | the entry in the file with the lexicographically latest name will take 26 | precedence. It is recommended to prefix all filenames with a two-digit number 27 | and a dash, to simplify the ordering of the files. 28 | 29 | If the administrator wants to disable a configuration file supplied by 30 | the vendor, the recommended way is to place a symlink to 31 | /dev/null in the configuration directory in 32 | /etc/, with the same filename as the vendor 33 | configuration file. If the vendor configuration file is included in 34 | the initrd image, the image has to be regenerated. 35 | 36 | 37 | 38 | 39 | Configuration Directories and Precedence 40 | 41 | The default configuration is defined during compilation, so a 42 | configuration file is only needed when it is necessary to deviate 43 | from those defaults. By default, the configuration file in 44 | /etc/systemd/ contains commented out entries 45 | showing the defaults as a guide to the administrator. This file 46 | can be edited to create local overrides. 47 | 48 | 49 | When packages need to customize the configuration, they can 50 | install configuration snippets in 51 | /usr/lib/systemd/*.conf.d/. Files in 52 | /etc/ are reserved for the local 53 | administrator, who may use this logic to override the 54 | configuration files installed by vendor packages. The main 55 | configuration file is read before any of the configuration 56 | directories, and has the lowest precedence; entries in a file in 57 | any configuration directory override entries in the single 58 | configuration file. Files in the 59 | *.conf.d/ configuration subdirectories 60 | are sorted by their filename in lexicographic order, regardless of 61 | which of the subdirectories they reside in. If multiple files 62 | specify the same option, the entry in the file with the 63 | lexicographically latest name takes precedence. It is recommended 64 | to prefix all filenames in those subdirectories with a two-digit 65 | number and a dash, to simplify the ordering of the files. 66 | 67 | To disable a configuration file supplied by the vendor, the 68 | recommended way is to place a symlink to 69 | /dev/null in the configuration directory in 70 | /etc/, with the same filename as the vendor 71 | configuration file. 72 | 73 | 74 | -------------------------------------------------------------------------------- /man/standard-options.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Print a short help text and exit. 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | Print a short version string and exit. 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | Do not pipe output into a pager. 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | Do not print the legend, i.e. column headers and the 36 | footer with hints. 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /po/.gitignore: -------------------------------------------------------------------------------- 1 | POTFILES 2 | Makefile.in.in 3 | .intltool-merge-cache 4 | Makefile 5 | systemd.pot 6 | /*.gmo 7 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | # This file is part of systemd. 2 | # 3 | # Copyright 2010 Lennart Poettering 4 | # 5 | # systemd is free software; you can redistribute it and/or modify it 6 | # under the terms of the GNU Lesser General Public License as published by 7 | # the Free Software Foundation; either version 2.1 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # systemd is distributed in the hope that it will be useful, but 11 | # WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | # Lesser General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU Lesser General Public License 16 | # along with systemd; If not, see . 17 | 18 | # This file is a dirty trick to simplify compilation from within 19 | # emacs. This file is not intended to be distributed. So, don't touch 20 | # it, even better ignore it! 21 | 22 | all: 23 | $(MAKE) -C .. 24 | 25 | clean: 26 | $(MAKE) -C .. clean 27 | 28 | .PHONY: all clean 29 | -------------------------------------------------------------------------------- /src/_sd-common.h: -------------------------------------------------------------------------------- 1 | #ifndef foosdcommonhfoo 2 | #define foosdcommonhfoo 3 | 4 | /*** 5 | This file is part of systemd. 6 | 7 | Copyright 2013 Lennart Poettering 8 | 9 | systemd is free software; you can redistribute it and/or modify it 10 | under the terms of the GNU Lesser General Public License as published by 11 | the Free Software Foundation; either version 2.1 of the License, or 12 | (at your option) any later version. 13 | 14 | systemd is distributed in the hope that it will be useful, but 15 | WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | Lesser General Public License for more details. 18 | 19 | You should have received a copy of the GNU Lesser General Public License 20 | along with systemd; If not, see . 21 | ***/ 22 | 23 | /* This is a private header; never even think of including this directly! */ 24 | 25 | #if __INCLUDE_LEVEL__ <= 1 26 | #error "Do not include _sd-common.h directly; it is a private header." 27 | #endif 28 | 29 | #ifndef _sd_printf_ 30 | # if __GNUC__ >= 4 31 | # define _sd_printf_(a,b) __attribute__ ((format (printf, a, b))) 32 | # else 33 | # define _sd_printf_(a,b) 34 | # endif 35 | #endif 36 | 37 | #ifndef _sd_sentinel_ 38 | # define _sd_sentinel_ __attribute__((sentinel)) 39 | #endif 40 | 41 | #ifndef _sd_packed_ 42 | # define _sd_packed_ __attribute__((packed)) 43 | #endif 44 | 45 | #ifndef _sd_pure_ 46 | # define _sd_pure_ __attribute__((pure)) 47 | #endif 48 | 49 | #ifndef _SD_STRINGIFY 50 | # define _SD_XSTRINGIFY(x) #x 51 | # define _SD_STRINGIFY(x) _SD_XSTRINGIFY(x) 52 | #endif 53 | 54 | #ifndef _SD_BEGIN_DECLARATIONS 55 | # ifdef __cplusplus 56 | # define _SD_BEGIN_DECLARATIONS \ 57 | extern "C" { \ 58 | struct _sd_useless_struct_to_allow_trailing_semicolon_ 59 | # else 60 | # define _SD_BEGIN_DECLARATIONS \ 61 | struct _sd_useless_struct_to_allow_trailing_semicolon_ 62 | # endif 63 | #endif 64 | 65 | #ifndef _SD_END_DECLARATIONS 66 | # ifdef __cplusplus 67 | # define _SD_END_DECLARATIONS \ 68 | } \ 69 | struct _sd_useless_cpp_struct_to_allow_trailing_semicolon_ 70 | # else 71 | # define _SD_END_DECLARATIONS \ 72 | struct _sd_useless_struct_to_allow_trailing_semicolon_ 73 | # endif 74 | #endif 75 | 76 | #define _SD_DEFINE_POINTER_CLEANUP_FUNC(type, func) \ 77 | static inline void func##p(type **p) { \ 78 | if (*p) \ 79 | func(*p); \ 80 | } \ 81 | struct _sd_useless_struct_to_allow_trailing_semicolon_ 82 | 83 | #endif 84 | -------------------------------------------------------------------------------- /src/alloc-util.c: -------------------------------------------------------------------------------- 1 | /*** 2 | This file is part of systemd. 3 | 4 | Copyright 2010 Lennart Poettering 5 | 6 | systemd is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation; either version 2.1 of the License, or 9 | (at your option) any later version. 10 | 11 | systemd is distributed in the hope that it will be useful, but 12 | WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with systemd; If not, see . 18 | ***/ 19 | 20 | #include 21 | 22 | #include "alloc-util.h" 23 | #include "macro.h" 24 | 25 | void* memdup(const void *p, size_t l) { 26 | void *r; 27 | 28 | assert(p); 29 | 30 | r = malloc(l); 31 | if (!r) 32 | return NULL; 33 | 34 | memcpy(r, p, l); 35 | return r; 36 | } 37 | 38 | void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) { 39 | size_t a, newalloc; 40 | void *q; 41 | 42 | assert(p); 43 | assert(allocated); 44 | 45 | if (*allocated >= need) 46 | return *p; 47 | 48 | newalloc = MAX(need * 2, 64u / size); 49 | a = newalloc * size; 50 | 51 | /* check for overflows */ 52 | if (a < size * need) 53 | return NULL; 54 | 55 | q = realloc(*p, a); 56 | if (!q) 57 | return NULL; 58 | 59 | *p = q; 60 | *allocated = newalloc; 61 | return q; 62 | } 63 | -------------------------------------------------------------------------------- /src/alloc-util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /*** 4 | This file is part of systemd. 5 | 6 | Copyright 2010 Lennart Poettering 7 | 8 | systemd is free software; you can redistribute it and/or modify it 9 | under the terms of the GNU Lesser General Public License as published by 10 | the Free Software Foundation; either version 2.1 of the License, or 11 | (at your option) any later version. 12 | 13 | systemd is distributed in the hope that it will be useful, but 14 | WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public License 19 | along with systemd; If not, see . 20 | ***/ 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include "attributes.h" 27 | 28 | #define new(t, n) ((t*) malloc_multiply(sizeof(t), (n))) 29 | 30 | #define new0(t, n) ((t*) calloc((n), sizeof(t))) 31 | 32 | #define newa(t, n) ((t*) alloca(sizeof(t)*(n))) 33 | 34 | #define newa0(t, n) ((t*) alloca0(sizeof(t)*(n))) 35 | 36 | #define newdup(t, p, n) ((t*) memdup_multiply(p, sizeof(t), (n))) 37 | 38 | #define malloc0(n) (calloc(1, (n))) 39 | 40 | static inline void *mfree(void *memory) { 41 | free(memory); 42 | return NULL; 43 | } 44 | 45 | void* memdup(const void *p, size_t l) _alloc_(2); 46 | 47 | static inline void freep(void *p) { 48 | free(*(void**) p); 49 | } 50 | 51 | #define _cleanup_free_ _cleanup_(freep) 52 | 53 | _malloc_ _alloc_(1, 2) static inline void *malloc_multiply(size_t a, size_t b) { 54 | if (_unlikely_(b != 0 && a > ((size_t) -1) / b)) 55 | return NULL; 56 | 57 | return malloc(a * b); 58 | } 59 | 60 | _alloc_(2, 3) static inline void *realloc_multiply(void *p, size_t a, size_t b) { 61 | if (_unlikely_(b != 0 && a > ((size_t) -1) / b)) 62 | return NULL; 63 | 64 | return realloc(p, a * b); 65 | } 66 | 67 | _alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t a, size_t b) { 68 | if (_unlikely_(b != 0 && a > ((size_t) -1) / b)) 69 | return NULL; 70 | 71 | return memdup(p, a * b); 72 | } 73 | 74 | void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size); 75 | 76 | #define GREEDY_REALLOC(array, allocated, need) \ 77 | greedy_realloc((void**) &(array), &(allocated), (need), sizeof((array)[0])) 78 | 79 | #define alloca0(n) \ 80 | ({ \ 81 | char *_new_; \ 82 | size_t _len_ = n; \ 83 | _new_ = alloca(_len_); \ 84 | (void *) memset(_new_, 0, _len_); \ 85 | }) 86 | 87 | /* It's not clear what alignment glibc/gcc alloca() guarantee, hence provide a guaranteed safe version */ 88 | #define alloca_align(size, align) \ 89 | ({ \ 90 | void *_ptr_; \ 91 | size_t _mask_ = (align) - 1; \ 92 | _ptr_ = alloca((size) + _mask_); \ 93 | (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_); \ 94 | }) 95 | 96 | #define alloca0_align(size, align) \ 97 | ({ \ 98 | void *_new_; \ 99 | size_t _size_ = (size); \ 100 | _new_ = alloca_align(_size_, (align)); \ 101 | (void*)memset(_new_, 0, _size_); \ 102 | }) 103 | -------------------------------------------------------------------------------- /src/architecture.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /*** 4 | This file is part of systemd. 5 | 6 | Copyright 2014 Lennart Poettering 7 | 8 | systemd is free software; you can redistribute it and/or modify it 9 | under the terms of the GNU Lesser General Public License as published by 10 | the Free Software Foundation; either version 2.1 of the License, or 11 | (at your option) any later version. 12 | 13 | systemd is distributed in the hope that it will be useful, but 14 | WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public License 19 | along with systemd; If not, see . 20 | ***/ 21 | 22 | #include 23 | 24 | #include "macro.h" 25 | #include "util.h" 26 | 27 | /* A cleaned up architecture definition. We don't want to get lost in 28 | * processor features, models, generations or even ABIs. Hence we 29 | * focus on general family, and distinguish word width and 30 | * endianness. */ 31 | 32 | enum { 33 | ARCHITECTURE_X86 = 0, 34 | ARCHITECTURE_X86_64, 35 | ARCHITECTURE_PPC, 36 | ARCHITECTURE_PPC_LE, 37 | ARCHITECTURE_PPC64, 38 | ARCHITECTURE_PPC64_LE, 39 | ARCHITECTURE_IA64, 40 | ARCHITECTURE_PARISC, 41 | ARCHITECTURE_PARISC64, 42 | ARCHITECTURE_S390, 43 | ARCHITECTURE_S390X, 44 | ARCHITECTURE_SPARC, 45 | ARCHITECTURE_SPARC64, 46 | ARCHITECTURE_MIPS, 47 | ARCHITECTURE_MIPS_LE, 48 | ARCHITECTURE_MIPS64, 49 | ARCHITECTURE_MIPS64_LE, 50 | ARCHITECTURE_ALPHA, 51 | ARCHITECTURE_ARM, 52 | ARCHITECTURE_ARM_BE, 53 | ARCHITECTURE_ARM64, 54 | ARCHITECTURE_ARM64_BE, 55 | ARCHITECTURE_SH, 56 | ARCHITECTURE_SH64, 57 | ARCHITECTURE_M68K, 58 | ARCHITECTURE_TILEGX, 59 | ARCHITECTURE_CRIS, 60 | ARCHITECTURE_RISCV64, 61 | ARCHITECTURE_RISCV32, 62 | ARCHITECTURE_LOONGARCH, 63 | _ARCHITECTURE_MAX, 64 | _ARCHITECTURE_INVALID = -1 65 | }; 66 | 67 | int uname_architecture(void); 68 | 69 | /* 70 | * LIB_ARCH_TUPLE should resolve to the local library path 71 | * architecture tuple systemd is built for, according to the Debian 72 | * tuple list: 73 | * 74 | * https://wiki.debian.org/Multiarch/Tuples 75 | * 76 | * This is used in library search paths that should understand 77 | * Debian's paths on all distributions. 78 | */ 79 | 80 | #if defined(__x86_64__) 81 | # define native_architecture() ARCHITECTURE_X86_64 82 | # define LIB_ARCH_TUPLE "x86_64-linux-gnu" 83 | # define PROC_CPUINFO_MODEL "model name" 84 | #elif defined(__i386__) 85 | # define native_architecture() ARCHITECTURE_X86 86 | # define LIB_ARCH_TUPLE "i386-linux-gnu" 87 | # define PROC_CPUINFO_MODEL "model name" 88 | #elif defined(__powerpc64__) 89 | # if __BYTE_ORDER == __BIG_ENDIAN 90 | # define native_architecture() ARCHITECTURE_PPC64 91 | # define LIB_ARCH_TUPLE "ppc64-linux-gnu" 92 | # else 93 | # define native_architecture() ARCHITECTURE_PPC64_LE 94 | # define LIB_ARCH_TUPLE "powerpc64le-linux-gnu" 95 | # endif 96 | # define PROC_CPUINFO_MODEL "cpu" 97 | #elif defined(__powerpc__) 98 | # if __BYTE_ORDER == __BIG_ENDIAN 99 | # define native_architecture() ARCHITECTURE_PPC 100 | # define LIB_ARCH_TUPLE "powerpc-linux-gnu" 101 | # else 102 | # define native_architecture() ARCHITECTURE_PPC_LE 103 | # error "Missing LIB_ARCH_TUPLE for PPCLE" 104 | # endif 105 | # define PROC_CPUINFO_MODEL "cpu" 106 | #elif defined(__ia64__) 107 | # define native_architecture() ARCHITECTURE_IA64 108 | # define LIB_ARCH_TUPLE "ia64-linux-gnu" 109 | #elif defined(__hppa64__) 110 | # define native_architecture() ARCHITECTURE_PARISC64 111 | # error "Missing LIB_ARCH_TUPLE for HPPA64" 112 | # define PROC_CPUINFO_MODEL "cpu" 113 | #elif defined(__hppa__) 114 | # define native_architecture() ARCHITECTURE_PARISC 115 | # define LIB_ARCH_TUPLE "hppa‑linux‑gnu" 116 | # define PROC_CPUINFO_MODEL "cpu" 117 | #elif defined(__s390x__) 118 | # define native_architecture() ARCHITECTURE_S390X 119 | # define LIB_ARCH_TUPLE "s390x-linux-gnu" 120 | #elif defined(__s390__) 121 | # define native_architecture() ARCHITECTURE_S390 122 | # define LIB_ARCH_TUPLE "s390-linux-gnu" 123 | #elif defined(__sparc64__) 124 | # define native_architecture() ARCHITECTURE_SPARC64 125 | # define LIB_ARCH_TUPLE "sparc64-linux-gnu" 126 | # define PROC_CPUINFO_MODEL "cpu" 127 | #elif defined(__sparc__) 128 | # define native_architecture() ARCHITECTURE_SPARC 129 | # define LIB_ARCH_TUPLE "sparc-linux-gnu" 130 | # define PROC_CPUINFO_MODEL "cpu" 131 | #elif defined(__mips64__) 132 | # if __BYTE_ORDER == __BIG_ENDIAN 133 | # define native_architecture() ARCHITECTURE_MIPS64 134 | # error "Missing LIB_ARCH_TUPLE for MIPS64" 135 | # else 136 | # define native_architecture() ARCHITECTURE_MIPS64_LE 137 | # error "Missing LIB_ARCH_TUPLE for MIPS64_LE" 138 | # endif 139 | # define PROC_CPUINFO_MODEL "cpu model" 140 | #elif defined(__mips__) 141 | # if __BYTE_ORDER == __BIG_ENDIAN 142 | # define native_architecture() ARCHITECTURE_MIPS 143 | # define LIB_ARCH_TUPLE "mips-linux-gnu" 144 | # else 145 | # define native_architecture() ARCHITECTURE_MIPS_LE 146 | # define LIB_ARCH_TUPLE "mipsel-linux-gnu" 147 | # endif 148 | # define PROC_CPUINFO_MODEL "cpu model" 149 | #elif defined(__alpha__) 150 | # define native_architecture() ARCHITECTURE_ALPHA 151 | # define LIB_ARCH_TUPLE "alpha-linux-gnu" 152 | #elif defined(__riscv) && __riscv_xlen == 64 153 | # define native_architecture() ARCHITECTURE_RISCV64 154 | # define define LIB_ARCH_TUPLE "riscv64-linux-gnu" 155 | #elif defined(__riscv) && __riscv_xlen == 32 156 | # define native_architecture() ARCHITECTURE_RISCV32 157 | # define define LIB_ARCH_TUPLE "riscv32-linux-gnu" 158 | #elif defined(__loongarch__) && __loongarch_grlen == 64 159 | # define native_architecture() ARCHITECTURE_LOONGARCH 160 | # define define LIB_ARCH_TUPLE "loongarch64-linux-gnu" 161 | #elif defined(__aarch64__) 162 | # if __BYTE_ORDER == __BIG_ENDIAN 163 | # define native_architecture() ARCHITECTURE_ARM64_BE 164 | # define LIB_ARCH_TUPLE "aarch64_be-linux-gnu" 165 | # else 166 | # define native_architecture() ARCHITECTURE_ARM64 167 | # define LIB_ARCH_TUPLE "aarch64-linux-gnu" 168 | # endif 169 | #elif defined(__arm__) 170 | # if __BYTE_ORDER == __BIG_ENDIAN 171 | # define native_architecture() ARCHITECTURE_ARM_BE 172 | # if defined(__ARM_EABI__) 173 | # if defined(__ARM_PCS_VFP) 174 | # define LIB_ARCH_TUPLE "armeb-linux-gnueabihf" 175 | # else 176 | # define LIB_ARCH_TUPLE "armeb-linux-gnueabi" 177 | # endif 178 | # else 179 | # define LIB_ARCH_TUPLE "armeb-linux-gnu" 180 | # endif 181 | # else 182 | # define native_architecture() ARCHITECTURE_ARM 183 | # if defined(__ARM_EABI__) 184 | # if defined(__ARM_PCS_VFP) 185 | # define LIB_ARCH_TUPLE "arm-linux-gnueabihf" 186 | # else 187 | # define LIB_ARCH_TUPLE "arm-linux-gnueabi" 188 | # endif 189 | # else 190 | # define LIB_ARCH_TUPLE "arm-linux-gnu" 191 | # endif 192 | # endif 193 | # define PROC_CPUINFO_MODEL "model name" 194 | #elif defined(__sh64__) 195 | # define native_architecture() ARCHITECTURE_SH64 196 | # error "Missing LIB_ARCH_TUPLE for SH64" 197 | #elif defined(__sh__) 198 | # define native_architecture() ARCHITECTURE_SH 199 | # define LIB_ARCH_TUPLE "sh4-linux-gnu" 200 | #elif defined(__m68k__) 201 | # define native_architecture() ARCHITECTURE_M68K 202 | # define LIB_ARCH_TUPLE "m68k-linux-gnu" 203 | #elif defined(__tilegx__) 204 | # define native_architecture() ARCHITECTURE_TILEGX 205 | # error "Missing LIB_ARCH_TUPLE for TILEGX" 206 | #elif defined(__cris__) 207 | # define native_architecture() ARCHITECTURE_CRIS 208 | # error "Missing LIB_ARCH_TUPLE for CRIS" 209 | #else 210 | # error "Please register your architecture here!" 211 | #endif 212 | 213 | #ifndef PROC_CPUINFO_MODEL 214 | #warning "PROC_CPUINFO_MODEL not defined for your architecture" 215 | #define PROC_CPUINFO_MODEL "model name" 216 | #endif 217 | 218 | const char *architecture_to_string(int a) _const_; 219 | int architecture_from_string(const char *s) _pure_; 220 | -------------------------------------------------------------------------------- /src/attributes.h: -------------------------------------------------------------------------------- 1 | #define _printf_(a,b) __attribute__ ((format (printf, a, b))) 2 | #define _alloc_(...) __attribute__ ((alloc_size(__VA_ARGS__))) 3 | #define _sentinel_ __attribute__ ((sentinel)) 4 | #define _unused_ __attribute__ ((unused)) 5 | #define _destructor_ __attribute__ ((destructor)) 6 | #define _pure_ __attribute__ ((pure)) 7 | #define _const_ __attribute__ ((const)) 8 | #define _deprecated_ __attribute__ ((deprecated)) 9 | #define _packed_ __attribute__ ((packed)) 10 | #define _malloc_ __attribute__ ((malloc)) 11 | #define _weak_ __attribute__ ((weak)) 12 | #define _likely_(x) (__builtin_expect(!!(x),1)) 13 | #define _unlikely_(x) (__builtin_expect(!!(x),0)) 14 | #define _public_ __attribute__ ((visibility("default"))) 15 | #define _hidden_ __attribute__ ((visibility("hidden"))) 16 | #define _weakref_(x) __attribute__((weakref(#x))) 17 | #define _alignas_(x) __attribute__((aligned(__alignof(x)))) 18 | #define _cleanup_(x) __attribute__((cleanup(x))) 19 | 20 | /* Define C11 thread_local attribute even on older gcc compiler 21 | * version */ 22 | #ifndef thread_local 23 | /* 24 | * Don't break on glibc < 2.16 that doesn't define __STDC_NO_THREADS__ 25 | * see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53769 26 | */ 27 | #if __STDC_VERSION__ >= 201112L && !(defined(__STDC_NO_THREADS__) || (defined(__GNU_LIBRARY__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 16)) 28 | #define thread_local _Thread_local 29 | #else 30 | #define thread_local __thread 31 | #endif 32 | #endif 33 | 34 | /* Define C11 noreturn without and even on older gcc 35 | * compiler versions */ 36 | #ifndef noreturn 37 | #if __STDC_VERSION__ >= 201112L 38 | #define noreturn _Noreturn 39 | #else 40 | #define noreturn __attribute__((noreturn)) 41 | #endif 42 | #endif 43 | -------------------------------------------------------------------------------- /src/bootchart.conf: -------------------------------------------------------------------------------- 1 | # This file is part of systemd. 2 | # 3 | # systemd is free software; you can redistribute it and/or modify it 4 | # under the terms of the GNU Lesser General Public License as published by 5 | # the Free Software Foundation; either version 2.1 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # Entries in this file show the compile time defaults. 9 | # You can change settings by editing this file. 10 | # Defaults can be restored by simply deleting this file. 11 | # 12 | # See bootchart.conf(5) for details. 13 | 14 | [Bootchart] 15 | #Samples=500 16 | #Frequency=25.0 17 | #Relative=no 18 | #Filter=yes 19 | #Output= 20 | #Init= 21 | #PlotMemoryUsage=no 22 | #PlotEntropyGraph=no 23 | #ScaleX=100.0 24 | #ScaleY=20.0 25 | #ControlGroup=no 26 | #PerCPU=no 27 | #Cmdline=no 28 | -------------------------------------------------------------------------------- /src/bootchart.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /*** 4 | This file is part of systemd. 5 | 6 | Copyright (C) 2009-2013 Intel Corporation 7 | 8 | Authors: 9 | Auke Kok 10 | 11 | systemd is free software; you can redistribute it and/or modify it 12 | under the terms of the GNU Lesser General Public License as published by 13 | the Free Software Foundation; either version 2.1 of the License, or 14 | (at your option) any later version. 15 | 16 | systemd is distributed in the hope that it will be useful, but 17 | WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | Lesser General Public License for more details. 20 | 21 | You should have received a copy of the GNU Lesser General Public License 22 | along with systemd; If not, see . 23 | ***/ 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | #include "list.h" 30 | 31 | #define MAXCPUS 512 32 | #define MAXPIDS 4194304 33 | 34 | struct block_stat_struct { 35 | /* /proc/vmstat pgpgin & pgpgout */ 36 | int bi; 37 | int bo; 38 | }; 39 | 40 | /* per process, per sample data we will log */ 41 | struct ps_sched_struct { 42 | /* /proc//schedstat fields 1 & 2 */ 43 | double runtime; 44 | double waittime; 45 | int pss; 46 | struct list_sample_data *sampledata; 47 | struct ps_sched_struct *next; 48 | struct ps_sched_struct *prev; 49 | struct ps_sched_struct *cross; /* cross pointer */ 50 | struct ps_struct *ps_new; 51 | }; 52 | 53 | struct list_sample_data { 54 | double runtime[MAXCPUS]; 55 | double waittime[MAXCPUS]; 56 | double sampletime; 57 | int entropy_avail; 58 | struct block_stat_struct blockstat; 59 | LIST_FIELDS(struct list_sample_data, link); /* DLL */ 60 | int counter; 61 | }; 62 | 63 | /* process info */ 64 | struct ps_struct { 65 | struct ps_struct *next_ps; /* SLL pointer */ 66 | struct ps_struct *next_running; /* currently running */ 67 | struct ps_struct *parent; /* ppid ref */ 68 | struct ps_struct *children; /* children */ 69 | struct ps_struct *next; /* siblings */ 70 | 71 | /* must match - otherwise it's a new process with same PID */ 72 | char name[256]; 73 | int pid; 74 | int ppid; 75 | char *cgroup; 76 | 77 | /* cache fd's */ 78 | int sched; 79 | int schedstat; 80 | FILE *smaps; 81 | 82 | /* used to garbage collect running process list*/ 83 | bool still_running; 84 | 85 | /* pointers to first/last seen timestamps */ 86 | struct ps_sched_struct *first; 87 | struct ps_sched_struct *last; 88 | 89 | /* records actual start time, may be way before bootchart runs */ 90 | double starttime; 91 | 92 | /* record human readable total cpu time */ 93 | double total; 94 | 95 | /* largest PSS size found */ 96 | int pss_max; 97 | 98 | /* for drawing connection lines later */ 99 | double pos_x; 100 | double pos_y; 101 | 102 | struct ps_sched_struct *sample; 103 | }; 104 | 105 | extern bool arg_relative; 106 | extern bool arg_filter; 107 | extern bool arg_show_cmdline; 108 | extern bool arg_show_cgroup; 109 | extern bool arg_pss; 110 | extern bool arg_entropy; 111 | extern bool arg_percpu; 112 | extern bool arg_initcall; 113 | extern int arg_samples_len; 114 | extern double arg_hz; 115 | extern double arg_scale_x; 116 | extern double arg_scale_y; 117 | 118 | extern char arg_output_path[PATH_MAX]; 119 | extern char arg_init_path[PATH_MAX]; 120 | -------------------------------------------------------------------------------- /src/build.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /*** 4 | This file is part of systemd. 5 | 6 | Copyright 2010 Lennart Poettering 7 | 8 | systemd is free software; you can redistribute it and/or modify it 9 | under the terms of the GNU Lesser General Public License as published by 10 | the Free Software Foundation; either version 2.1 of the License, or 11 | (at your option) any later version. 12 | 13 | systemd is distributed in the hope that it will be useful, but 14 | WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public License 19 | along with systemd; If not, see . 20 | ***/ 21 | 22 | #ifdef HAVE_PAM 23 | #define _PAM_FEATURE_ "+PAM" 24 | #else 25 | #define _PAM_FEATURE_ "-PAM" 26 | #endif 27 | 28 | #ifdef HAVE_AUDIT 29 | #define _AUDIT_FEATURE_ "+AUDIT" 30 | #else 31 | #define _AUDIT_FEATURE_ "-AUDIT" 32 | #endif 33 | 34 | #ifdef HAVE_SELINUX 35 | #define _SELINUX_FEATURE_ "+SELINUX" 36 | #else 37 | #define _SELINUX_FEATURE_ "-SELINUX" 38 | #endif 39 | 40 | #ifdef HAVE_APPARMOR 41 | #define _APPARMOR_FEATURE_ "+APPARMOR" 42 | #else 43 | #define _APPARMOR_FEATURE_ "-APPARMOR" 44 | #endif 45 | 46 | #ifdef HAVE_IMA 47 | #define _IMA_FEATURE_ "+IMA" 48 | #else 49 | #define _IMA_FEATURE_ "-IMA" 50 | #endif 51 | 52 | #ifdef HAVE_SMACK 53 | #define _SMACK_FEATURE_ "+SMACK" 54 | #else 55 | #define _SMACK_FEATURE_ "-SMACK" 56 | #endif 57 | 58 | #ifdef HAVE_SYSV_COMPAT 59 | #define _SYSVINIT_FEATURE_ "+SYSVINIT" 60 | #else 61 | #define _SYSVINIT_FEATURE_ "-SYSVINIT" 62 | #endif 63 | 64 | #ifdef HAVE_UTMP 65 | #define _UTMP_FEATURE_ "+UTMP" 66 | #else 67 | #define _UTMP_FEATURE_ "-UTMP" 68 | #endif 69 | 70 | #ifdef HAVE_LIBCRYPTSETUP 71 | #define _LIBCRYPTSETUP_FEATURE_ "+LIBCRYPTSETUP" 72 | #else 73 | #define _LIBCRYPTSETUP_FEATURE_ "-LIBCRYPTSETUP" 74 | #endif 75 | 76 | #ifdef HAVE_GCRYPT 77 | #define _GCRYPT_FEATURE_ "+GCRYPT" 78 | #else 79 | #define _GCRYPT_FEATURE_ "-GCRYPT" 80 | #endif 81 | 82 | #ifdef HAVE_GNUTLS 83 | #define _GNUTLS_FEATURE_ "+GNUTLS" 84 | #else 85 | #define _GNUTLS_FEATURE_ "-GNUTLS" 86 | #endif 87 | 88 | #ifdef HAVE_ACL 89 | #define _ACL_FEATURE_ "+ACL" 90 | #else 91 | #define _ACL_FEATURE_ "-ACL" 92 | #endif 93 | 94 | #ifdef HAVE_XZ 95 | #define _XZ_FEATURE_ "+XZ" 96 | #else 97 | #define _XZ_FEATURE_ "-XZ" 98 | #endif 99 | 100 | #ifdef HAVE_LZ4 101 | #define _LZ4_FEATURE_ "+LZ4" 102 | #else 103 | #define _LZ4_FEATURE_ "-LZ4" 104 | #endif 105 | 106 | #ifdef HAVE_SECCOMP 107 | #define _SECCOMP_FEATURE_ "+SECCOMP" 108 | #else 109 | #define _SECCOMP_FEATURE_ "-SECCOMP" 110 | #endif 111 | 112 | #ifdef HAVE_BLKID 113 | #define _BLKID_FEATURE_ "+BLKID" 114 | #else 115 | #define _BLKID_FEATURE_ "-BLKID" 116 | #endif 117 | 118 | #ifdef HAVE_ELFUTILS 119 | #define _ELFUTILS_FEATURE_ "+ELFUTILS" 120 | #else 121 | #define _ELFUTILS_FEATURE_ "-ELFUTILS" 122 | #endif 123 | 124 | #ifdef HAVE_KMOD 125 | #define _KMOD_FEATURE_ "+KMOD" 126 | #else 127 | #define _KMOD_FEATURE_ "-KMOD" 128 | #endif 129 | 130 | #ifdef HAVE_LIBIDN 131 | #define _IDN_FEATURE_ "+IDN" 132 | #else 133 | #define _IDN_FEATURE_ "-IDN" 134 | #endif 135 | 136 | #define SYSTEMD_FEATURES \ 137 | _PAM_FEATURE_ " " \ 138 | _AUDIT_FEATURE_ " " \ 139 | _SELINUX_FEATURE_ " " \ 140 | _IMA_FEATURE_ " " \ 141 | _APPARMOR_FEATURE_ " " \ 142 | _SMACK_FEATURE_ " " \ 143 | _SYSVINIT_FEATURE_ " " \ 144 | _UTMP_FEATURE_ " " \ 145 | _LIBCRYPTSETUP_FEATURE_ " " \ 146 | _GCRYPT_FEATURE_ " " \ 147 | _GNUTLS_FEATURE_ " " \ 148 | _ACL_FEATURE_ " " \ 149 | _XZ_FEATURE_ " " \ 150 | _LZ4_FEATURE_ " " \ 151 | _SECCOMP_FEATURE_ " " \ 152 | _BLKID_FEATURE_ " " \ 153 | _ELFUTILS_FEATURE_ " " \ 154 | _KMOD_FEATURE_ " " \ 155 | _IDN_FEATURE_ 156 | -------------------------------------------------------------------------------- /src/cgroup-util.c: -------------------------------------------------------------------------------- 1 | /*** 2 | This file is part of systemd. 3 | 4 | Copyright 2010 Lennart Poettering 5 | 6 | systemd is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation; either version 2.1 of the License, or 9 | (at your option) any later version. 10 | 11 | systemd is distributed in the hope that it will be useful, but 12 | WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with systemd; If not, see . 18 | ***/ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "attributes.h" 28 | #include "cgroup-util.h" 29 | #include "def.h" 30 | #include "fd-util.h" 31 | #include "fileio.h" 32 | #include "macro.h" 33 | #include "missing.h" 34 | #include "parse-util.h" 35 | #include "process-util.h" 36 | #include "string-util.h" 37 | 38 | #define F_TYPE_EQUAL(a, b) (a == (typeof(a)) b) 39 | 40 | int cg_pid_get_path(const char *controller, pid_t pid, char **path) { 41 | _cleanup_fclose_ FILE *f = NULL; 42 | char line[LINE_MAX]; 43 | const char *fs; 44 | size_t cs = 0; 45 | int unified; 46 | 47 | assert(path); 48 | assert(pid >= 0); 49 | 50 | unified = cg_unified(); 51 | if (unified < 0) 52 | return unified; 53 | if (unified == 0) { 54 | if (controller) { 55 | if (!cg_controller_is_valid(controller)) 56 | return -EINVAL; 57 | } else 58 | controller = SYSTEMD_CGROUP_CONTROLLER; 59 | 60 | cs = strlen(controller); 61 | } 62 | 63 | fs = procfs_file_alloca(pid, "cgroup"); 64 | f = fopen(fs, "re"); 65 | if (!f) 66 | return errno == ENOENT ? -ESRCH : -errno; 67 | 68 | FOREACH_LINE(line, f, return -errno) { 69 | char *e, *p; 70 | 71 | truncate_nl(line); 72 | 73 | if (unified) { 74 | e = startswith(line, "0:"); 75 | if (!e) 76 | continue; 77 | 78 | e = strchr(e, ':'); 79 | if (!e) 80 | continue; 81 | } else { 82 | char *l; 83 | size_t k; 84 | const char *word, *state; 85 | bool found = false; 86 | 87 | l = strchr(line, ':'); 88 | if (!l) 89 | continue; 90 | 91 | l++; 92 | e = strchr(l, ':'); 93 | if (!e) 94 | continue; 95 | 96 | *e = 0; 97 | FOREACH_WORD_SEPARATOR(word, k, l, ",", state) { 98 | if (k == cs && memcmp(word, controller, cs) == 0) { 99 | found = true; 100 | break; 101 | } 102 | } 103 | 104 | if (!found) 105 | continue; 106 | } 107 | 108 | p = strdup(e + 1); 109 | if (!p) 110 | return -ENOMEM; 111 | 112 | *path = p; 113 | return 0; 114 | } 115 | 116 | return -ENODATA; 117 | } 118 | 119 | #define CONTROLLER_VALID \ 120 | DIGITS LETTERS \ 121 | "_" 122 | 123 | bool cg_controller_is_valid(const char *p) { 124 | const char *t, *s; 125 | 126 | if (!p) 127 | return false; 128 | 129 | s = startswith(p, "name="); 130 | if (s) 131 | p = s; 132 | 133 | if (*p == 0 || *p == '_') 134 | return false; 135 | 136 | for (t = p; *t; t++) 137 | if (!strchr(CONTROLLER_VALID, *t)) 138 | return false; 139 | 140 | if (t - p > FILENAME_MAX) 141 | return false; 142 | 143 | return true; 144 | } 145 | 146 | static thread_local int unified_cache = -1; 147 | 148 | int cg_unified(void) { 149 | struct statfs fs; 150 | 151 | /* Checks if we support the unified hierarchy. Returns an 152 | * error when the cgroup hierarchies aren't mounted yet or we 153 | * have any other trouble determining if the unified hierarchy 154 | * is supported. */ 155 | 156 | if (unified_cache >= 0) 157 | return unified_cache; 158 | 159 | if (statfs("/sys/fs/cgroup/", &fs) < 0) 160 | return -errno; 161 | 162 | if (F_TYPE_EQUAL(fs.f_type, CGROUP_SUPER_MAGIC)) 163 | unified_cache = true; 164 | else if (F_TYPE_EQUAL(fs.f_type, TMPFS_MAGIC)) 165 | unified_cache = false; 166 | else 167 | return -ENOMEDIUM; 168 | 169 | return unified_cache; 170 | } 171 | 172 | int cg_blkio_weight_parse(const char *s, uint64_t *ret) { 173 | uint64_t u; 174 | int r; 175 | 176 | if (isempty(s)) { 177 | *ret = CGROUP_BLKIO_WEIGHT_INVALID; 178 | return 0; 179 | } 180 | 181 | r = safe_atou64(s, &u); 182 | if (r < 0) 183 | return r; 184 | 185 | if (u < CGROUP_BLKIO_WEIGHT_MIN || u > CGROUP_BLKIO_WEIGHT_MAX) 186 | return -ERANGE; 187 | 188 | *ret = u; 189 | return 0; 190 | } 191 | -------------------------------------------------------------------------------- /src/cgroup-util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /*** 4 | This file is part of systemd. 5 | 6 | Copyright 2010 Lennart Poettering 7 | 8 | systemd is free software; you can redistribute it and/or modify it 9 | under the terms of the GNU Lesser General Public License as published by 10 | the Free Software Foundation; either version 2.1 of the License, or 11 | (at your option) any later version. 12 | 13 | systemd is distributed in the hope that it will be useful, but 14 | WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public License 19 | along with systemd; If not, see . 20 | ***/ 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | /* Special values for the cpu.shares attribute */ 27 | #define CGROUP_CPU_SHARES_INVALID ((uint64_t) -1) 28 | #define CGROUP_CPU_SHARES_MIN UINT64_C(2) 29 | #define CGROUP_CPU_SHARES_MAX UINT64_C(262144) 30 | #define CGROUP_CPU_SHARES_DEFAULT UINT64_C(1024) 31 | 32 | static inline bool CGROUP_CPU_SHARES_IS_OK(uint64_t x) { 33 | return 34 | x == CGROUP_CPU_SHARES_INVALID || 35 | (x >= CGROUP_CPU_SHARES_MIN && x <= CGROUP_CPU_SHARES_MAX); 36 | } 37 | 38 | /* Special values for the blkio.weight attribute */ 39 | #define CGROUP_BLKIO_WEIGHT_INVALID ((uint64_t) -1) 40 | #define CGROUP_BLKIO_WEIGHT_MIN UINT64_C(10) 41 | #define CGROUP_BLKIO_WEIGHT_MAX UINT64_C(1000) 42 | #define CGROUP_BLKIO_WEIGHT_DEFAULT UINT64_C(500) 43 | 44 | static inline bool CGROUP_BLKIO_WEIGHT_IS_OK(uint64_t x) { 45 | return 46 | x == CGROUP_BLKIO_WEIGHT_INVALID || 47 | (x >= CGROUP_BLKIO_WEIGHT_MIN && x <= CGROUP_BLKIO_WEIGHT_MAX); 48 | } 49 | 50 | /* 51 | * General rules: 52 | * 53 | * We accept named hierarchies in the syntax "foo" and "name=foo". 54 | * 55 | * We expect that named hierarchies do not conflict in name with a 56 | * kernel hierarchy, modulo the "name=" prefix. 57 | * 58 | * We always generate "normalized" controller names, i.e. without the 59 | * "name=" prefix. 60 | * 61 | * We require absolute cgroup paths. When returning, we will always 62 | * generate paths with multiple adjacent / removed. 63 | */ 64 | 65 | int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self); 66 | int cg_migrate_recursive(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self, bool remove); 67 | int cg_migrate_recursive_fallback(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self, bool rem); 68 | 69 | int cg_pid_get_path(const char *controller, pid_t pid, char **path); 70 | 71 | int cg_pid_get_unit(pid_t pid, char **unit); 72 | int cg_pid_get_machine_name(pid_t pid, char **machine); 73 | 74 | bool cg_controller_is_valid(const char *p); 75 | 76 | int cg_slice_to_path(const char *unit, char **ret); 77 | 78 | int cg_unified(void); 79 | 80 | int cg_blkio_weight_parse(const char *s, uint64_t *ret); 81 | -------------------------------------------------------------------------------- /src/conf-files.c: -------------------------------------------------------------------------------- 1 | /*** 2 | This file is part of systemd. 3 | 4 | Copyright 2010 Lennart Poettering 5 | 6 | systemd is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation; either version 2.1 of the License, or 9 | (at your option) any later version. 10 | 11 | systemd is distributed in the hope that it will be useful, but 12 | WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with systemd; If not, see . 18 | ***/ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "conf-files.h" 27 | #include "dirent-util.h" 28 | #include "fd-util.h" 29 | #include "hash-funcs.h" 30 | #include "hashmap.h" 31 | #include "log.h" 32 | #include "macro.h" 33 | #include "path-util.h" 34 | #include "string-util.h" 35 | #include "strv.h" 36 | #include "util.h" 37 | 38 | static int files_add(Hashmap *h, const char *root, const char *path, const char *suffix) { 39 | _cleanup_closedir_ DIR *dir = NULL; 40 | const char *dirpath; 41 | struct dirent *de; 42 | int r; 43 | 44 | assert(path); 45 | assert(suffix); 46 | 47 | dirpath = prefix_roota(root, path); 48 | 49 | dir = opendir(dirpath); 50 | if (!dir) { 51 | if (errno == ENOENT) 52 | return 0; 53 | return -errno; 54 | } 55 | 56 | FOREACH_DIRENT(de, dir, return -errno) { 57 | char *p; 58 | 59 | if (!dirent_is_file_with_suffix(de, suffix)) 60 | continue; 61 | 62 | p = strjoin(dirpath, "/", de->d_name, NULL); 63 | if (!p) 64 | return -ENOMEM; 65 | 66 | r = hashmap_put(h, basename(p), p); 67 | if (r == -EEXIST) { 68 | log_debug("Skipping overridden file: %s.", p); 69 | free(p); 70 | } else if (r < 0) { 71 | free(p); 72 | return r; 73 | } else if (r == 0) { 74 | log_debug("Duplicate file %s", p); 75 | free(p); 76 | } 77 | } 78 | 79 | return 0; 80 | } 81 | 82 | static int base_cmp(const void *a, const void *b) { 83 | const char *s1, *s2; 84 | 85 | s1 = *(char * const *)a; 86 | s2 = *(char * const *)b; 87 | return strcmp(basename(s1), basename(s2)); 88 | } 89 | 90 | static int conf_files_list_strv_internal(char ***strv, const char *suffix, const char *root, char **dirs) { 91 | _cleanup_hashmap_free_ Hashmap *fh = NULL; 92 | char **files, **p; 93 | int r; 94 | 95 | assert(strv); 96 | assert(suffix); 97 | 98 | /* This alters the dirs string array */ 99 | if (!path_strv_resolve_uniq(dirs, root)) 100 | return -ENOMEM; 101 | 102 | fh = hashmap_new(&string_hash_ops); 103 | if (!fh) 104 | return -ENOMEM; 105 | 106 | STRV_FOREACH(p, dirs) { 107 | r = files_add(fh, root, *p, suffix); 108 | if (r == -ENOMEM) 109 | return r; 110 | if (r < 0) 111 | log_debug_errno(r, "Failed to search for files in %s, ignoring: %m", *p); 112 | } 113 | 114 | files = hashmap_get_strv(fh); 115 | if (!files) 116 | return -ENOMEM; 117 | 118 | qsort_safe(files, hashmap_size(fh), sizeof(char *), base_cmp); 119 | *strv = files; 120 | 121 | return 0; 122 | } 123 | 124 | int conf_files_list_nulstr(char ***strv, const char *suffix, const char *root, const char *d) { 125 | _cleanup_strv_free_ char **dirs = NULL; 126 | 127 | assert(strv); 128 | assert(suffix); 129 | 130 | dirs = strv_split_nulstr(d); 131 | if (!dirs) 132 | return -ENOMEM; 133 | 134 | return conf_files_list_strv_internal(strv, suffix, root, dirs); 135 | } 136 | -------------------------------------------------------------------------------- /src/conf-files.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /*** 4 | This file is part of systemd. 5 | 6 | Copyright 2010-2012 Lennart Poettering 7 | Copyright 2010-2012 Kay Sievers 8 | 9 | systemd is free software; you can redistribute it and/or modify it 10 | under the terms of the GNU Lesser General Public License as published by 11 | the Free Software Foundation; either version 2.1 of the License, or 12 | (at your option) any later version. 13 | 14 | systemd is distributed in the hope that it will be useful, but 15 | WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | Lesser General Public License for more details. 18 | 19 | You should have received a copy of the GNU Lesser General Public License 20 | along with systemd; If not, see . 21 | ***/ 22 | 23 | int conf_files_list_nulstr(char ***ret, const char *suffix, const char *root, const char *dirs); 24 | -------------------------------------------------------------------------------- /src/def.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /*** 4 | This file is part of systemd. 5 | 6 | Copyright 2010 Lennart Poettering 7 | 8 | systemd is free software; you can redistribute it and/or modify it 9 | under the terms of the GNU Lesser General Public License as published by 10 | the Free Software Foundation; either version 2.1 of the License, or 11 | (at your option) any later version. 12 | 13 | systemd is distributed in the hope that it will be useful, but 14 | WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public License 19 | along with systemd; If not, see . 20 | ***/ 21 | 22 | #include "util.h" 23 | 24 | #define DEFAULT_TIMEOUT_USEC (90*USEC_PER_SEC) 25 | #define DEFAULT_RESTART_USEC (100*USEC_PER_MSEC) 26 | #define DEFAULT_CONFIRM_USEC (30*USEC_PER_SEC) 27 | 28 | #define DEFAULT_START_LIMIT_INTERVAL (10*USEC_PER_SEC) 29 | #define DEFAULT_START_LIMIT_BURST 5 30 | 31 | /* The default time after which exit-on-idle services exit. This 32 | * should be kept lower than the watchdog timeout, because otherwise 33 | * the watchdog pings will keep the loop busy. */ 34 | #define DEFAULT_EXIT_USEC (30*USEC_PER_SEC) 35 | 36 | /* The default value for the net.unix.max_dgram_qlen sysctl */ 37 | #define DEFAULT_UNIX_MAX_DGRAM_QLEN 512UL 38 | 39 | #define SYSTEMD_CGROUP_CONTROLLER "name=systemd" 40 | 41 | #define SIGNALS_CRASH_HANDLER SIGSEGV,SIGILL,SIGFPE,SIGBUS,SIGQUIT,SIGABRT 42 | #define SIGNALS_IGNORE SIGPIPE 43 | 44 | #define REBOOT_PARAM_FILE "/run/systemd/reboot-param" 45 | 46 | #ifdef HAVE_SPLIT_USR 47 | #define KBD_KEYMAP_DIRS \ 48 | "/usr/share/keymaps/\0" \ 49 | "/usr/share/kbd/keymaps/\0" \ 50 | "/usr/lib/kbd/keymaps/\0" \ 51 | "/lib/kbd/keymaps/\0" 52 | #else 53 | #define KBD_KEYMAP_DIRS \ 54 | "/usr/share/keymaps/\0" \ 55 | "/usr/share/kbd/keymaps/\0" \ 56 | "/usr/lib/kbd/keymaps/\0" 57 | #endif 58 | 59 | #define UNIX_SYSTEM_BUS_ADDRESS "unix:path=/var/run/dbus/system_bus_socket" 60 | #define KERNEL_SYSTEM_BUS_ADDRESS "kernel:path=/sys/fs/kdbus/0-system/bus" 61 | #define DEFAULT_SYSTEM_BUS_ADDRESS KERNEL_SYSTEM_BUS_ADDRESS ";" UNIX_SYSTEM_BUS_ADDRESS 62 | #define UNIX_USER_BUS_ADDRESS_FMT "unix:path=%s/bus" 63 | #define KERNEL_USER_BUS_ADDRESS_FMT "kernel:path=/sys/fs/kdbus/"UID_FMT"-user/bus" 64 | 65 | #ifndef TTY_GID 66 | #define TTY_GID 5 67 | #endif 68 | 69 | #define NOTIFY_FD_MAX 768 70 | #define NOTIFY_BUFFER_MAX PIPE_BUF 71 | 72 | #ifdef HAVE_SPLIT_USR 73 | #define _CONF_PATHS_SPLIT_USR(n) "/lib/" n "\0" 74 | #else 75 | #define _CONF_PATHS_SPLIT_USR(n) 76 | #endif 77 | 78 | /* Return a nulstr for a standard cascade of configuration paths, 79 | * suitable to pass to conf_files_list_nulstr() or config_parse_many() 80 | * to implement drop-in directories for extending configuration 81 | * files. */ 82 | #define CONF_PATHS_NULSTR(n) \ 83 | "/etc/" n "\0" \ 84 | "/run/" n "\0" \ 85 | "/usr/local/lib/" n "\0" \ 86 | "/usr/lib/" n "\0" \ 87 | _CONF_PATHS_SPLIT_USR(n) 88 | -------------------------------------------------------------------------------- /src/dirent-util.c: -------------------------------------------------------------------------------- 1 | /*** 2 | This file is part of systemd. 3 | 4 | Copyright 2010-2012 Lennart Poettering 5 | 6 | systemd is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation; either version 2.1 of the License, or 9 | (at your option) any later version. 10 | 11 | systemd is distributed in the hope that it will be useful, but 12 | WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with systemd; If not, see . 18 | ***/ 19 | 20 | #include "dirent-util.h" 21 | #include "macro.h" 22 | #include "string-util.h" 23 | 24 | bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) { 25 | assert(de); 26 | 27 | if (de->d_type != DT_REG && 28 | de->d_type != DT_LNK && 29 | de->d_type != DT_UNKNOWN) 30 | return false; 31 | 32 | return endswith(de->d_name, suffix); 33 | } 34 | -------------------------------------------------------------------------------- /src/dirent-util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /*** 4 | This file is part of systemd. 5 | 6 | Copyright 2010 Lennart Poettering 7 | 8 | systemd is free software; you can redistribute it and/or modify it 9 | under the terms of the GNU Lesser General Public License as published by 10 | the Free Software Foundation; either version 2.1 of the License, or 11 | (at your option) any later version. 12 | 13 | systemd is distributed in the hope that it will be useful, but 14 | WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public License 19 | along with systemd; If not, see . 20 | ***/ 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include "attributes.h" 27 | 28 | bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) _pure_; 29 | 30 | #define FOREACH_DIRENT(de, d, on_error) \ 31 | for (errno = 0, de = readdir(d);; errno = 0, de = readdir(d)) \ 32 | if (!de) { \ 33 | if (errno > 0) { \ 34 | on_error; \ 35 | } \ 36 | break; \ 37 | } else 38 | -------------------------------------------------------------------------------- /src/fd-util.c: -------------------------------------------------------------------------------- 1 | /*** 2 | This file is part of systemd. 3 | 4 | Copyright 2010 Lennart Poettering 5 | 6 | systemd is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation; either version 2.1 of the License, or 9 | (at your option) any later version. 10 | 11 | systemd is distributed in the hope that it will be useful, but 12 | WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with systemd; If not, see . 18 | ***/ 19 | 20 | #include 21 | #include 22 | 23 | #include "fd-util.h" 24 | #include "macro.h" 25 | #include "util.h" 26 | 27 | int close_nointr(int fd) { 28 | assert(fd >= 0); 29 | 30 | if (close(fd) >= 0) 31 | return 0; 32 | 33 | /* 34 | * Just ignore EINTR; a retry loop is the wrong thing to do on 35 | * Linux. 36 | * 37 | * http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html 38 | * https://bugzilla.gnome.org/show_bug.cgi?id=682819 39 | * http://utcc.utoronto.ca/~cks/space/blog/unix/CloseEINTR 40 | * https://sites.google.com/site/michaelsafyan/software-engineering/checkforeintrwheninvokingclosethinkagain 41 | */ 42 | if (errno == EINTR) 43 | return 0; 44 | 45 | return -errno; 46 | } 47 | 48 | int safe_close(int fd) { 49 | 50 | /* 51 | * Like close_nointr() but cannot fail. Guarantees errno is 52 | * unchanged. Is a NOP with negative fds passed, and returns 53 | * -1, so that it can be used in this syntax: 54 | * 55 | * fd = safe_close(fd); 56 | */ 57 | 58 | if (fd >= 0) { 59 | PROTECT_ERRNO; 60 | 61 | /* The kernel might return pretty much any error code 62 | * via close(), but the fd will be closed anyway. The 63 | * only condition we want to check for here is whether 64 | * the fd was invalid at all... */ 65 | 66 | assert_se(close_nointr(fd) != -EBADF); 67 | } 68 | 69 | return -1; 70 | } 71 | 72 | int fclose_nointr(FILE *f) { 73 | assert(f); 74 | 75 | /* Same as close_nointr(), but for fclose() */ 76 | 77 | if (fclose(f) == 0) 78 | return 0; 79 | 80 | if (errno == EINTR) 81 | return 0; 82 | 83 | return -errno; 84 | } 85 | 86 | FILE* safe_fclose(FILE *f) { 87 | 88 | /* Same as safe_close(), but for fclose() */ 89 | 90 | if (f) { 91 | PROTECT_ERRNO; 92 | 93 | assert_se(fclose_nointr(f) != EBADF); 94 | } 95 | 96 | return NULL; 97 | } 98 | 99 | DIR* safe_closedir(DIR *d) { 100 | 101 | if (d) { 102 | PROTECT_ERRNO; 103 | 104 | assert_se(closedir(d) >= 0 || errno != EBADF); 105 | } 106 | 107 | return NULL; 108 | } 109 | -------------------------------------------------------------------------------- /src/fd-util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /*** 4 | This file is part of systemd. 5 | 6 | Copyright 2010 Lennart Poettering 7 | 8 | systemd is free software; you can redistribute it and/or modify it 9 | under the terms of the GNU Lesser General Public License as published by 10 | the Free Software Foundation; either version 2.1 of the License, or 11 | (at your option) any later version. 12 | 13 | systemd is distributed in the hope that it will be useful, but 14 | WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public License 19 | along with systemd; If not, see . 20 | ***/ 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include "attributes.h" 27 | #include "macro.h" 28 | 29 | /* Make sure we can distinguish fd 0 and NULL */ 30 | #define FD_TO_PTR(fd) INT_TO_PTR((fd)+1) 31 | #define PTR_TO_FD(p) (PTR_TO_INT(p)-1) 32 | 33 | int close_nointr(int fd); 34 | int safe_close(int fd); 35 | 36 | int fclose_nointr(FILE *f); 37 | FILE* safe_fclose(FILE *f); 38 | DIR* safe_closedir(DIR *f); 39 | 40 | static inline void closep(int *fd) { 41 | safe_close(*fd); 42 | } 43 | 44 | static inline void fclosep(FILE **f) { 45 | safe_fclose(*f); 46 | } 47 | 48 | DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, pclose); 49 | DEFINE_TRIVIAL_CLEANUP_FUNC(DIR*, closedir); 50 | 51 | #define _cleanup_close_ _cleanup_(closep) 52 | #define _cleanup_fclose_ _cleanup_(fclosep) 53 | #define _cleanup_pclose_ _cleanup_(pclosep) 54 | #define _cleanup_closedir_ _cleanup_(closedirp) 55 | 56 | /* Hint: ENETUNREACH happens if we try to connect to "non-existing" special IP addresses, such as ::5 */ 57 | #define ERRNO_IS_DISCONNECT(r) \ 58 | IN_SET(r, ENOTCONN, ECONNRESET, ECONNREFUSED, ECONNABORTED, EPIPE, ENETUNREACH) 59 | -------------------------------------------------------------------------------- /src/fileio.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /*** 4 | This file is part of systemd. 5 | 6 | Copyright 2010 Lennart Poettering 7 | 8 | systemd is free software; you can redistribute it and/or modify it 9 | under the terms of the GNU Lesser General Public License as published by 10 | the Free Software Foundation; either version 2.1 of the License, or 11 | (at your option) any later version. 12 | 13 | systemd is distributed in the hope that it will be useful, but 14 | WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public License 19 | along with systemd; If not, see . 20 | ***/ 21 | 22 | #include 23 | #include 24 | 25 | #include "attributes.h" 26 | 27 | typedef enum { 28 | WRITE_STRING_FILE_CREATE = 1, 29 | WRITE_STRING_FILE_ATOMIC = 2, 30 | WRITE_STRING_FILE_AVOID_NEWLINE = 4, 31 | WRITE_STRING_FILE_VERIFY_ON_FAILURE = 8, 32 | } WriteStringFileFlags; 33 | 34 | int read_one_line_file(const char *fn, char **line); 35 | int read_full_file(const char *fn, char **contents, size_t *size); 36 | int read_full_stream(FILE *f, char **contents, size_t *size); 37 | 38 | int parse_env_file(const char *fname, const char *separator, ...) _sentinel_; 39 | 40 | int get_proc_field(const char *filename, const char *pattern, const char *terminator, char **field); 41 | 42 | #define FOREACH_LINE(line, f, on_error) \ 43 | for (;;) \ 44 | if (!fgets(line, sizeof(line), f)) { \ 45 | if (ferror(f)) { \ 46 | on_error; \ 47 | } \ 48 | break; \ 49 | } else 50 | -------------------------------------------------------------------------------- /src/formats-util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /*** 4 | This file is part of systemd. 5 | 6 | Copyright 2015 Ronny Chevalier 7 | 8 | systemd is free software; you can redistribute it and/or modify it 9 | under the terms of the GNU Lesser General Public License as published by 10 | the Free Software Foundation; either version 2.1 of the License, or 11 | (at your option) any later version. 12 | 13 | systemd is distributed in the hope that it will be useful, but 14 | WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public License 19 | along with systemd; If not, see . 20 | ***/ 21 | 22 | #include 23 | 24 | #if SIZEOF_PID_T == 4 25 | # define PID_PRI PRIi32 26 | #elif SIZEOF_PID_T == 2 27 | # define PID_PRI PRIi16 28 | #else 29 | # error Unknown pid_t size 30 | #endif 31 | #define PID_FMT "%" PID_PRI 32 | 33 | #if SIZEOF_UID_T == 4 34 | # define UID_FMT "%" PRIu32 35 | #elif SIZEOF_UID_T == 2 36 | # define UID_FMT "%" PRIu16 37 | #else 38 | # error Unknown uid_t size 39 | #endif 40 | 41 | #if SIZEOF_GID_T == 4 42 | # define GID_FMT "%" PRIu32 43 | #elif SIZEOF_GID_T == 2 44 | # define GID_FMT "%" PRIu16 45 | #else 46 | # error Unknown gid_t size 47 | #endif 48 | 49 | #if SIZEOF_TIME_T == 8 50 | # define PRI_TIME PRIi64 51 | #elif SIZEOF_TIME_T == 4 52 | # define PRI_TIME PRIu32 53 | #else 54 | # error Unknown time_t size 55 | #endif 56 | 57 | #if SIZEOF_RLIM_T == 8 58 | # define RLIM_FMT "%" PRIu64 59 | #elif SIZEOF_RLIM_T == 4 60 | # define RLIM_FMT "%" PRIu32 61 | #else 62 | # error Unknown rlim_t size 63 | #endif 64 | -------------------------------------------------------------------------------- /src/fs-util.c: -------------------------------------------------------------------------------- 1 | /*** 2 | This file is part of systemd. 3 | 4 | Copyright 2010 Lennart Poettering 5 | 6 | systemd is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation; either version 2.1 of the License, or 9 | (at your option) any later version. 10 | 11 | systemd is distributed in the hope that it will be useful, but 12 | WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with systemd; If not, see . 18 | ***/ 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include "fs-util.h" 25 | #include "log.h" 26 | 27 | int fd_warn_permissions(const char *path, int fd) { 28 | struct stat st; 29 | 30 | if (fstat(fd, &st) < 0) 31 | return -errno; 32 | 33 | if (st.st_mode & 0111) 34 | log_warning("Configuration file %s is marked executable. Please remove executable permission bits. Proceeding anyway.", path); 35 | 36 | if (st.st_mode & 0002) 37 | log_warning("Configuration file %s is marked world-writable. Please remove world writability permission bits. Proceeding anyway.", path); 38 | 39 | if (getpid() == 1 && (st.st_mode & 0044) != 0044) 40 | log_warning("Configuration file %s is marked world-inaccessible. This has no effect as configuration data is accessible via APIs without restrictions. Proceeding anyway.", path); 41 | 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /src/fs-util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /*** 4 | This file is part of systemd. 5 | 6 | Copyright 2010 Lennart Poettering 7 | 8 | systemd is free software; you can redistribute it and/or modify it 9 | under the terms of the GNU Lesser General Public License as published by 10 | the Free Software Foundation; either version 2.1 of the License, or 11 | (at your option) any later version. 12 | 13 | systemd is distributed in the hope that it will be useful, but 14 | WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public License 19 | along with systemd; If not, see . 20 | ***/ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | int fd_warn_permissions(const char *path, int fd); 28 | 29 | #define laccess(path, mode) faccessat(AT_FDCWD, (path), (mode), AT_SYMLINK_NOFOLLOW) 30 | 31 | #define INOTIFY_EVENT_MAX (sizeof(struct inotify_event) + NAME_MAX + 1) 32 | 33 | #define FOREACH_INOTIFY_EVENT(e, buffer, sz) \ 34 | for ((e) = &buffer.ev; \ 35 | (uint8_t*) (e) < (uint8_t*) (buffer.raw) + (sz); \ 36 | (e) = (struct inotify_event*) ((uint8_t*) (e) + sizeof(struct inotify_event) + (e)->len)) 37 | 38 | union inotify_event_buffer { 39 | struct inotify_event ev; 40 | uint8_t raw[INOTIFY_EVENT_MAX]; 41 | }; 42 | -------------------------------------------------------------------------------- /src/hash-funcs.c: -------------------------------------------------------------------------------- 1 | /*** 2 | This file is part of systemd. 3 | 4 | Copyright 2010 Lennart Poettering 5 | Copyright 2014 Michal Schmidt 6 | 7 | systemd is free software; you can redistribute it and/or modify it 8 | under the terms of the GNU Lesser General Public License as published by 9 | the Free Software Foundation; either version 2.1 of the License, or 10 | (at your option) any later version. 11 | 12 | systemd is distributed in the hope that it will be useful, but 13 | WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public License 18 | along with systemd; If not, see . 19 | ***/ 20 | 21 | #include 22 | #include 23 | 24 | #include "hash-funcs.h" 25 | 26 | void string_hash_func(const void *p, struct siphash *state) { 27 | siphash24_compress(p, strlen(p) + 1, state); 28 | } 29 | 30 | int string_compare_func(const void *a, const void *b) { 31 | return strcmp(a, b); 32 | } 33 | 34 | const struct hash_ops string_hash_ops = { 35 | .hash = string_hash_func, 36 | .compare = string_compare_func 37 | }; 38 | 39 | void trivial_hash_func(const void *p, struct siphash *state) { 40 | siphash24_compress(&p, sizeof(p), state); 41 | } 42 | 43 | int trivial_compare_func(const void *a, const void *b) { 44 | return a < b ? -1 : (a > b ? 1 : 0); 45 | } 46 | 47 | const struct hash_ops trivial_hash_ops = { 48 | .hash = trivial_hash_func, 49 | .compare = trivial_compare_func 50 | }; 51 | 52 | void uint64_hash_func(const void *p, struct siphash *state) { 53 | siphash24_compress(p, sizeof(uint64_t), state); 54 | } 55 | 56 | int uint64_compare_func(const void *_a, const void *_b) { 57 | uint64_t a, b; 58 | a = *(const uint64_t*) _a; 59 | b = *(const uint64_t*) _b; 60 | return a < b ? -1 : (a > b ? 1 : 0); 61 | } 62 | 63 | const struct hash_ops uint64_hash_ops = { 64 | .hash = uint64_hash_func, 65 | .compare = uint64_compare_func 66 | }; 67 | 68 | #if SIZEOF_DEV_T != 8 69 | void devt_hash_func(const void *p, struct siphash *state) { 70 | siphash24_compress(p, sizeof(dev_t), state); 71 | } 72 | 73 | int devt_compare_func(const void *_a, const void *_b) { 74 | dev_t a, b; 75 | a = *(const dev_t*) _a; 76 | b = *(const dev_t*) _b; 77 | return a < b ? -1 : (a > b ? 1 : 0); 78 | } 79 | 80 | const struct hash_ops devt_hash_ops = { 81 | .hash = devt_hash_func, 82 | .compare = devt_compare_func 83 | }; 84 | #endif 85 | -------------------------------------------------------------------------------- /src/hash-funcs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /*** 4 | This file is part of systemd. 5 | 6 | Copyright 2010 Lennart Poettering 7 | Copyright 2014 Michal Schmidt 8 | 9 | systemd is free software; you can redistribute it and/or modify it 10 | under the terms of the GNU Lesser General Public License as published by 11 | the Free Software Foundation; either version 2.1 of the License, or 12 | (at your option) any later version. 13 | 14 | systemd is distributed in the hope that it will be useful, but 15 | WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | Lesser General Public License for more details. 18 | 19 | You should have received a copy of the GNU Lesser General Public License 20 | along with systemd; If not, see . 21 | ***/ 22 | 23 | #include "attributes.h" 24 | #include "siphash24.h" 25 | 26 | typedef void (*hash_func_t)(const void *p, struct siphash *state); 27 | typedef int (*compare_func_t)(const void *a, const void *b); 28 | 29 | struct hash_ops { 30 | hash_func_t hash; 31 | compare_func_t compare; 32 | }; 33 | 34 | void string_hash_func(const void *p, struct siphash *state); 35 | int string_compare_func(const void *a, const void *b) _pure_; 36 | extern const struct hash_ops string_hash_ops; 37 | 38 | /* This will compare the passed pointers directly, and will not 39 | * dereference them. This is hence not useful for strings or 40 | * suchlike. */ 41 | void trivial_hash_func(const void *p, struct siphash *state); 42 | int trivial_compare_func(const void *a, const void *b) _const_; 43 | extern const struct hash_ops trivial_hash_ops; 44 | 45 | /* 32bit values we can always just embed in the pointer itself, but 46 | * in order to support 32bit archs we need store 64bit values 47 | * indirectly, since they don't fit in a pointer. */ 48 | void uint64_hash_func(const void *p, struct siphash *state); 49 | int uint64_compare_func(const void *a, const void *b) _pure_; 50 | extern const struct hash_ops uint64_hash_ops; 51 | 52 | /* On some archs dev_t is 32bit, and on others 64bit. And sometimes 53 | * it's 64bit on 32bit archs, and sometimes 32bit on 64bit archs. Yuck! */ 54 | #if SIZEOF_DEV_T != 8 55 | void devt_hash_func(const void *p, struct siphash *state) _pure_; 56 | int devt_compare_func(const void *a, const void *b) _pure_; 57 | extern const struct hash_ops devt_hash_ops = { 58 | .hash = devt_hash_func, 59 | .compare = devt_compare_func 60 | }; 61 | #else 62 | #define devt_hash_func uint64_hash_func 63 | #define devt_compare_func uint64_compare_func 64 | #define devt_hash_ops uint64_hash_ops 65 | #endif 66 | -------------------------------------------------------------------------------- /src/io-util.c: -------------------------------------------------------------------------------- 1 | /*** 2 | This file is part of systemd. 3 | 4 | Copyright 2010 Lennart Poettering 5 | 6 | systemd is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation; either version 2.1 of the License, or 9 | (at your option) any later version. 10 | 11 | systemd is distributed in the hope that it will be useful, but 12 | WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with systemd; If not, see . 18 | ***/ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "io-util.h" 27 | #include "time-util.h" 28 | 29 | ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll) { 30 | uint8_t *p = buf; 31 | ssize_t n = 0; 32 | 33 | assert(fd >= 0); 34 | assert(buf); 35 | 36 | /* If called with nbytes == 0, let's call read() at least 37 | * once, to validate the operation */ 38 | 39 | if (nbytes > (size_t) SSIZE_MAX) 40 | return -EINVAL; 41 | 42 | do { 43 | ssize_t k; 44 | 45 | k = read(fd, p, nbytes); 46 | if (k < 0) { 47 | if (errno == EINTR) 48 | continue; 49 | 50 | if (errno == EAGAIN && do_poll) { 51 | 52 | /* We knowingly ignore any return value here, 53 | * and expect that any error/EOF is reported 54 | * via read() */ 55 | 56 | (void) fd_wait_for_event(fd, POLLIN, USEC_INFINITY); 57 | continue; 58 | } 59 | 60 | return n > 0 ? n : -errno; 61 | } 62 | 63 | if (k == 0) 64 | return n; 65 | 66 | assert((size_t) k <= nbytes); 67 | 68 | p += k; 69 | nbytes -= k; 70 | n += k; 71 | } while (nbytes > 0); 72 | 73 | return n; 74 | } 75 | 76 | int loop_read_exact(int fd, void *buf, size_t nbytes, bool do_poll) { 77 | ssize_t n; 78 | 79 | n = loop_read(fd, buf, nbytes, do_poll); 80 | if (n < 0) 81 | return (int) n; 82 | if ((size_t) n != nbytes) 83 | return -EIO; 84 | 85 | return 0; 86 | } 87 | 88 | int fd_wait_for_event(int fd, int event, usec_t t) { 89 | 90 | struct pollfd pollfd = { 91 | .fd = fd, 92 | .events = event, 93 | }; 94 | 95 | struct timespec ts; 96 | int r; 97 | 98 | r = ppoll(&pollfd, 1, t == USEC_INFINITY ? NULL : timespec_store(&ts, t), NULL); 99 | if (r < 0) 100 | return -errno; 101 | 102 | if (r == 0) 103 | return 0; 104 | 105 | return pollfd.revents; 106 | } 107 | -------------------------------------------------------------------------------- /src/io-util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /*** 4 | This file is part of systemd. 5 | 6 | Copyright 2010 Lennart Poettering 7 | 8 | systemd is free software; you can redistribute it and/or modify it 9 | under the terms of the GNU Lesser General Public License as published by 10 | the Free Software Foundation; either version 2.1 of the License, or 11 | (at your option) any later version. 12 | 13 | systemd is distributed in the hope that it will be useful, but 14 | WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public License 19 | along with systemd; If not, see . 20 | ***/ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "attributes.h" 29 | #include "macro.h" 30 | #include "time-util.h" 31 | 32 | ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll); 33 | int loop_read_exact(int fd, void *buf, size_t nbytes, bool do_poll); 34 | 35 | int fd_wait_for_event(int fd, int event, usec_t timeout); 36 | 37 | #define IOVEC_SET_STRING(i, s) \ 38 | do { \ 39 | struct iovec *_i = &(i); \ 40 | char *_s = (char *)(s); \ 41 | _i->iov_base = _s; \ 42 | _i->iov_len = strlen(_s); \ 43 | } while(false) 44 | 45 | static inline size_t IOVEC_TOTAL_SIZE(const struct iovec *i, unsigned n) { 46 | unsigned j; 47 | size_t r = 0; 48 | 49 | for (j = 0; j < n; j++) 50 | r += i[j].iov_len; 51 | 52 | return r; 53 | } 54 | 55 | static inline size_t IOVEC_INCREMENT(struct iovec *i, unsigned n, size_t k) { 56 | unsigned j; 57 | 58 | for (j = 0; j < n; j++) { 59 | size_t sub; 60 | 61 | if (_unlikely_(k <= 0)) 62 | break; 63 | 64 | sub = MIN(i[j].iov_len, k); 65 | i[j].iov_len -= sub; 66 | i[j].iov_base = (uint8_t*) i[j].iov_base + sub; 67 | k -= sub; 68 | } 69 | 70 | return k; 71 | } 72 | 73 | static inline bool FILE_SIZE_VALID(uint64_t l) { 74 | /* ftruncate() and friends take an unsigned file size, but actually cannot deal with file sizes larger than 75 | * 2^63 since the kernel internally handles it as signed value. This call allows checking for this early. */ 76 | 77 | return (l >> 63) == 0; 78 | } 79 | 80 | static inline bool FILE_SIZE_VALID_OR_INFINITY(uint64_t l) { 81 | 82 | /* Same as above, but allows one extra value: -1 as indication for infinity. */ 83 | 84 | if (l == (uint64_t) -1) 85 | return true; 86 | 87 | return FILE_SIZE_VALID(l); 88 | 89 | } 90 | -------------------------------------------------------------------------------- /src/log.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /*** 4 | This file is part of systemd. 5 | 6 | Copyright 2010 Lennart Poettering 7 | 8 | systemd is free software; you can redistribute it and/or modify it 9 | under the terms of the GNU Lesser General Public License as published by 10 | the Free Software Foundation; either version 2.1 of the License, or 11 | (at your option) any later version. 12 | 13 | systemd is distributed in the hope that it will be useful, but 14 | WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public License 19 | along with systemd; If not, see . 20 | ***/ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "alloc-util.h" 28 | #include "attributes.h" 29 | 30 | int log_get_max_level(void) _pure_; 31 | 32 | int log_internal( 33 | int level, 34 | int error, 35 | const char *file, 36 | int line, 37 | const char *func, 38 | const char *format, ...) _printf_(6,7); 39 | 40 | int log_internalv( 41 | int level, 42 | int error, 43 | const char *file, 44 | int line, 45 | const char *func, 46 | const char *format, 47 | va_list ap) _printf_(6,0); 48 | 49 | int log_struct_internal( 50 | int level, 51 | int error, 52 | const char *file, 53 | int line, 54 | const char *func, 55 | const char *format, ...) _printf_(6,0) _sentinel_; 56 | 57 | int log_oom_internal( 58 | const char *file, 59 | int line, 60 | const char *func); 61 | 62 | /* Logging for various assertions */ 63 | noreturn void log_assert_failed( 64 | const char *text, 65 | const char *file, 66 | int line, 67 | const char *func); 68 | 69 | noreturn void log_assert_failed_unreachable( 70 | const char *text, 71 | const char *file, 72 | int line, 73 | const char *func); 74 | 75 | void log_assert_failed_return( 76 | const char *text, 77 | const char *file, 78 | int line, 79 | const char *func); 80 | 81 | /* Logging with level */ 82 | #define log_full_errno(level, error, ...) \ 83 | ({ \ 84 | int _level = (level), _e = (error); \ 85 | (log_get_max_level() >= LOG_PRI(_level)) \ 86 | ? log_internal(_level, _e, __FILE__, __LINE__, __func__, __VA_ARGS__) \ 87 | : -abs(_e); \ 88 | }) 89 | 90 | #define log_full(level, ...) log_full_errno(level, 0, __VA_ARGS__) 91 | 92 | /* Normal logging */ 93 | #define log_debug(...) log_full(LOG_DEBUG, __VA_ARGS__) 94 | #define log_info(...) log_full(LOG_INFO, __VA_ARGS__) 95 | #define log_notice(...) log_full(LOG_NOTICE, __VA_ARGS__) 96 | #define log_warning(...) log_full(LOG_WARNING, __VA_ARGS__) 97 | #define log_error(...) log_full(LOG_ERR, __VA_ARGS__) 98 | #define log_emergency(...) log_full(getpid() == 1 ? LOG_EMERG : LOG_ERR, __VA_ARGS__) 99 | 100 | /* Logging triggered by an errno-like error */ 101 | #define log_debug_errno(error, ...) log_full_errno(LOG_DEBUG, error, __VA_ARGS__) 102 | #define log_info_errno(error, ...) log_full_errno(LOG_INFO, error, __VA_ARGS__) 103 | #define log_notice_errno(error, ...) log_full_errno(LOG_NOTICE, error, __VA_ARGS__) 104 | #define log_warning_errno(error, ...) log_full_errno(LOG_WARNING, error, __VA_ARGS__) 105 | #define log_error_errno(error, ...) log_full_errno(LOG_ERR, error, __VA_ARGS__) 106 | #define log_emergency_errno(error, ...) log_full_errno(getpid() == 1 ? LOG_EMERG : LOG_ERR, error, __VA_ARGS__) 107 | 108 | #ifdef LOG_TRACE 109 | # define log_trace(...) log_debug(__VA_ARGS__) 110 | #else 111 | # define log_trace(...) do {} while(0) 112 | #endif 113 | 114 | #define log_oom() log_oom_internal(__FILE__, __LINE__, __func__) 115 | 116 | /* Helpers to prepare various fields for structured logging */ 117 | #define LOG_MESSAGE(fmt, ...) "MESSAGE=" fmt, ##__VA_ARGS__ 118 | #define LOG_MESSAGE_ID(x) "MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(x) 119 | 120 | int log_syntax_internal( 121 | const char *unit, 122 | int level, 123 | const char *config_file, 124 | unsigned config_line, 125 | int error, 126 | const char *file, 127 | int line, 128 | const char *func, 129 | const char *format, ...) _printf_(9, 10); 130 | 131 | #define log_syntax(unit, level, config_file, config_line, error, ...) \ 132 | ({ \ 133 | int _level = (level), _e = (error); \ 134 | (log_get_max_level() >= LOG_PRI(_level)) \ 135 | ? log_syntax_internal(unit, _level, config_file, config_line, _e, __FILE__, __LINE__, __func__, __VA_ARGS__) \ 136 | : -abs(_e); \ 137 | }) 138 | 139 | #define log_syntax_invalid_utf8(unit, level, config_file, config_line, rvalue) \ 140 | ({ \ 141 | int _level = (level); \ 142 | if (log_get_max_level() >= LOG_PRI(_level)) { \ 143 | _cleanup_free_ char *_p = NULL; \ 144 | _p = utf8_escape_invalid(rvalue); \ 145 | log_syntax_internal(unit, _level, config_file, config_line, 0, __FILE__, __LINE__, __func__, \ 146 | "String is not UTF-8 clean, ignoring assignment: %s", strna(_p)); \ 147 | } \ 148 | -EINVAL; \ 149 | }) 150 | -------------------------------------------------------------------------------- /src/mempool.c: -------------------------------------------------------------------------------- 1 | /*** 2 | This file is part of systemd. 3 | 4 | Copyright 2010-2014 Lennart Poettering 5 | Copyright 2014 Michal Schmidt 6 | 7 | systemd is free software; you can redistribute it and/or modify it 8 | under the terms of the GNU Lesser General Public License as published by 9 | the Free Software Foundation; either version 2.1 of the License, or 10 | (at your option) any later version. 11 | 12 | systemd is distributed in the hope that it will be useful, but 13 | WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public License 18 | along with systemd; If not, see . 19 | ***/ 20 | 21 | #include 22 | #include 23 | 24 | #include "attributes.h" 25 | #include "macro.h" 26 | #include "mempool.h" 27 | #include "util.h" 28 | 29 | struct pool { 30 | struct pool *next; 31 | unsigned n_tiles; 32 | unsigned n_used; 33 | }; 34 | 35 | void* mempool_alloc_tile(struct mempool *mp) { 36 | unsigned i; 37 | 38 | /* When a tile is released we add it to the list and simply 39 | * place the next pointer at its offset 0. */ 40 | 41 | assert(mp->tile_size >= sizeof(void*)); 42 | assert(mp->at_least > 0); 43 | 44 | if (mp->freelist) { 45 | void *r; 46 | 47 | r = mp->freelist; 48 | mp->freelist = * (void**) mp->freelist; 49 | return r; 50 | } 51 | 52 | if (_unlikely_(!mp->first_pool) || 53 | _unlikely_(mp->first_pool->n_used >= mp->first_pool->n_tiles)) { 54 | unsigned n; 55 | size_t size; 56 | struct pool *p; 57 | 58 | n = mp->first_pool ? mp->first_pool->n_tiles : 0; 59 | n = MAX(mp->at_least, n * 2); 60 | size = PAGE_ALIGN(ALIGN(sizeof(struct pool)) + n*mp->tile_size); 61 | n = (size - ALIGN(sizeof(struct pool))) / mp->tile_size; 62 | 63 | p = malloc(size); 64 | if (!p) 65 | return NULL; 66 | 67 | p->next = mp->first_pool; 68 | p->n_tiles = n; 69 | p->n_used = 0; 70 | 71 | mp->first_pool = p; 72 | } 73 | 74 | i = mp->first_pool->n_used++; 75 | 76 | return ((uint8_t*) mp->first_pool) + ALIGN(sizeof(struct pool)) + i*mp->tile_size; 77 | } 78 | 79 | void* mempool_alloc0_tile(struct mempool *mp) { 80 | void *p; 81 | 82 | p = mempool_alloc_tile(mp); 83 | if (p) 84 | memzero(p, mp->tile_size); 85 | return p; 86 | } 87 | 88 | void mempool_free_tile(struct mempool *mp, void *p) { 89 | * (void**) p = mp->freelist; 90 | mp->freelist = p; 91 | } 92 | 93 | #ifdef VALGRIND 94 | 95 | void mempool_drop(struct mempool *mp) { 96 | struct pool *p = mp->first_pool; 97 | while (p) { 98 | struct pool *n; 99 | n = p->next; 100 | free(p); 101 | p = n; 102 | } 103 | } 104 | 105 | #endif 106 | -------------------------------------------------------------------------------- /src/mempool.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /*** 4 | This file is part of systemd. 5 | 6 | Copyright 2011-2014 Lennart Poettering 7 | Copyright 2014 Michal Schmidt 8 | 9 | systemd is free software; you can redistribute it and/or modify it 10 | under the terms of the GNU Lesser General Public License as published by 11 | the Free Software Foundation; either version 2.1 of the License, or 12 | (at your option) any later version. 13 | 14 | systemd is distributed in the hope that it will be useful, but 15 | WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | Lesser General Public License for more details. 18 | 19 | You should have received a copy of the GNU Lesser General Public License 20 | along with systemd; If not, see . 21 | ***/ 22 | 23 | #include 24 | 25 | struct pool; 26 | 27 | struct mempool { 28 | struct pool *first_pool; 29 | void *freelist; 30 | size_t tile_size; 31 | unsigned at_least; 32 | }; 33 | 34 | void* mempool_alloc_tile(struct mempool *mp); 35 | void* mempool_alloc0_tile(struct mempool *mp); 36 | void mempool_free_tile(struct mempool *mp, void *p); 37 | 38 | #define DEFINE_MEMPOOL(pool_name, tile_type, alloc_at_least) \ 39 | static struct mempool pool_name = { \ 40 | .tile_size = sizeof(tile_type), \ 41 | .at_least = alloc_at_least, \ 42 | } 43 | 44 | 45 | #ifdef VALGRIND 46 | void mempool_drop(struct mempool *mp); 47 | #endif 48 | -------------------------------------------------------------------------------- /src/missing.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #ifndef CGROUP_SUPER_MAGIC 7 | #define CGROUP_SUPER_MAGIC 0x27e0eb 8 | #endif 9 | 10 | #ifndef TMPFS_MAGIC 11 | #define TMPFS_MAGIC 0x01021994 12 | #endif 13 | 14 | #if !HAVE_DECL_GETTID 15 | static inline pid_t gettid(void) { 16 | return (pid_t) syscall(SYS_gettid); 17 | } 18 | #endif 19 | 20 | #ifndef __NR_getrandom 21 | # if defined __x86_64__ 22 | # define __NR_getrandom 318 23 | # elif defined(__i386__) 24 | # define __NR_getrandom 355 25 | # elif defined(__arm__) 26 | # define __NR_getrandom 384 27 | # elif defined(__aarch64__) 28 | # define __NR_getrandom 278 29 | # elif defined(__riscv) 30 | # define __NR_getrandom 278 31 | # elif defined(__ia64__) 32 | # define __NR_getrandom 1339 33 | # elif defined(__m68k__) 34 | # define __NR_getrandom 352 35 | # elif defined(__s390x__) 36 | # define __NR_getrandom 349 37 | # elif defined(__powerpc__) 38 | # define __NR_getrandom 359 39 | # elif defined _MIPS_SIM 40 | # if _MIPS_SIM == _MIPS_SIM_ABI32 41 | # define __NR_getrandom 4353 42 | # endif 43 | # if _MIPS_SIM == _MIPS_SIM_NABI32 44 | # define __NR_getrandom 6317 45 | # endif 46 | # if _MIPS_SIM == _MIPS_SIM_ABI64 47 | # define __NR_getrandom 5313 48 | # endif 49 | # else 50 | # warning "__NR_getrandom unknown for your architecture" 51 | # define __NR_getrandom 0xffffffff 52 | # endif 53 | #endif 54 | 55 | #if !HAVE_DECL_GETRANDOM 56 | static inline int getrandom(void *buffer, size_t count, unsigned flags) { 57 | return syscall(__NR_getrandom, buffer, count, flags); 58 | } 59 | #endif 60 | 61 | #ifndef GRND_NONBLOCK 62 | #define GRND_NONBLOCK 0x0001 63 | #endif 64 | -------------------------------------------------------------------------------- /src/parse-util.c: -------------------------------------------------------------------------------- 1 | /*** 2 | This file is part of systemd. 3 | 4 | Copyright 2010 Lennart Poettering 5 | 6 | systemd is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation; either version 2.1 of the License, or 9 | (at your option) any later version. 10 | 11 | systemd is distributed in the hope that it will be useful, but 12 | WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with systemd; If not, see . 18 | ***/ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "macro.h" 26 | #include "parse-util.h" 27 | #include "string-util.h" 28 | 29 | int parse_boolean(const char *v) { 30 | assert(v); 31 | 32 | if (streq(v, "1") || strcaseeq(v, "yes") || strcaseeq(v, "y") || strcaseeq(v, "true") || strcaseeq(v, "t") || strcaseeq(v, "on")) 33 | return 1; 34 | else if (streq(v, "0") || strcaseeq(v, "no") || strcaseeq(v, "n") || strcaseeq(v, "false") || strcaseeq(v, "f") || strcaseeq(v, "off")) 35 | return 0; 36 | 37 | return -EINVAL; 38 | } 39 | 40 | int safe_atou(const char *s, unsigned *ret_u) { 41 | char *x = NULL; 42 | unsigned long l; 43 | 44 | assert(s); 45 | assert(ret_u); 46 | 47 | /* strtoul() is happy to parse negative values, and silently 48 | * converts them to unsigned values without generating an 49 | * error. We want a clean error, hence let's look for the "-" 50 | * prefix on our own, and generate an error. But let's do so 51 | * only after strtoul() validated that the string is clean 52 | * otherwise, so that we return EINVAL preferably over 53 | * ERANGE. */ 54 | 55 | s += strspn(s, WHITESPACE); 56 | 57 | errno = 0; 58 | l = strtoul(s, &x, 0); 59 | if (errno > 0) 60 | return -errno; 61 | if (!x || x == s || *x) 62 | return -EINVAL; 63 | if (s[0] == '-') 64 | return -ERANGE; 65 | if ((unsigned long) (unsigned) l != l) 66 | return -ERANGE; 67 | 68 | *ret_u = (unsigned) l; 69 | return 0; 70 | } 71 | 72 | int safe_atoi(const char *s, int *ret_i) { 73 | char *x = NULL; 74 | long l; 75 | 76 | assert(s); 77 | assert(ret_i); 78 | 79 | errno = 0; 80 | l = strtol(s, &x, 0); 81 | if (errno > 0) 82 | return -errno; 83 | if (!x || x == s || *x) 84 | return -EINVAL; 85 | if ((long) (int) l != l) 86 | return -ERANGE; 87 | 88 | *ret_i = (int) l; 89 | return 0; 90 | } 91 | 92 | int safe_atollu(const char *s, long long unsigned *ret_llu) { 93 | char *x = NULL; 94 | unsigned long long l; 95 | 96 | assert(s); 97 | assert(ret_llu); 98 | 99 | s += strspn(s, WHITESPACE); 100 | 101 | errno = 0; 102 | l = strtoull(s, &x, 0); 103 | if (errno > 0) 104 | return -errno; 105 | if (!x || x == s || *x) 106 | return -EINVAL; 107 | if (*s == '-') 108 | return -ERANGE; 109 | 110 | *ret_llu = l; 111 | return 0; 112 | } 113 | 114 | int safe_atolli(const char *s, long long int *ret_lli) { 115 | char *x = NULL; 116 | long long l; 117 | 118 | assert(s); 119 | assert(ret_lli); 120 | 121 | errno = 0; 122 | l = strtoll(s, &x, 0); 123 | if (errno > 0) 124 | return -errno; 125 | if (!x || x == s || *x) 126 | return -EINVAL; 127 | 128 | *ret_lli = l; 129 | return 0; 130 | } 131 | 132 | int safe_atou8(const char *s, uint8_t *ret) { 133 | char *x = NULL; 134 | unsigned long l; 135 | 136 | assert(s); 137 | assert(ret); 138 | 139 | s += strspn(s, WHITESPACE); 140 | 141 | errno = 0; 142 | l = strtoul(s, &x, 0); 143 | if (errno > 0) 144 | return -errno; 145 | if (!x || x == s || *x) 146 | return -EINVAL; 147 | if (s[0] == '-') 148 | return -ERANGE; 149 | if ((unsigned long) (uint8_t) l != l) 150 | return -ERANGE; 151 | 152 | *ret = (uint8_t) l; 153 | return 0; 154 | } 155 | 156 | int safe_atou16(const char *s, uint16_t *ret) { 157 | char *x = NULL; 158 | unsigned long l; 159 | 160 | assert(s); 161 | assert(ret); 162 | 163 | s += strspn(s, WHITESPACE); 164 | 165 | errno = 0; 166 | l = strtoul(s, &x, 0); 167 | if (errno > 0) 168 | return -errno; 169 | if (!x || x == s || *x) 170 | return -EINVAL; 171 | if (s[0] == '-') 172 | return -ERANGE; 173 | if ((unsigned long) (uint16_t) l != l) 174 | return -ERANGE; 175 | 176 | *ret = (uint16_t) l; 177 | return 0; 178 | } 179 | 180 | int safe_atoi16(const char *s, int16_t *ret) { 181 | char *x = NULL; 182 | long l; 183 | 184 | assert(s); 185 | assert(ret); 186 | 187 | errno = 0; 188 | l = strtol(s, &x, 0); 189 | if (errno > 0) 190 | return -errno; 191 | if (!x || x == s || *x) 192 | return -EINVAL; 193 | if ((long) (int16_t) l != l) 194 | return -ERANGE; 195 | 196 | *ret = (int16_t) l; 197 | return 0; 198 | } 199 | 200 | int safe_atod(const char *s, double *ret_d) { 201 | char *x = NULL; 202 | double d = 0; 203 | locale_t loc; 204 | 205 | assert(s); 206 | assert(ret_d); 207 | 208 | loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0); 209 | if (loc == (locale_t) 0) 210 | return -errno; 211 | 212 | errno = 0; 213 | d = strtod_l(s, &x, loc); 214 | if (errno > 0) { 215 | freelocale(loc); 216 | return -errno; 217 | } 218 | if (!x || x == s || *x) { 219 | freelocale(loc); 220 | return -EINVAL; 221 | } 222 | 223 | freelocale(loc); 224 | *ret_d = (double) d; 225 | return 0; 226 | } 227 | -------------------------------------------------------------------------------- /src/parse-util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /*** 4 | This file is part of systemd. 5 | 6 | Copyright 2010 Lennart Poettering 7 | 8 | systemd is free software; you can redistribute it and/or modify it 9 | under the terms of the GNU Lesser General Public License as published by 10 | the Free Software Foundation; either version 2.1 of the License, or 11 | (at your option) any later version. 12 | 13 | systemd is distributed in the hope that it will be useful, but 14 | WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public License 19 | along with systemd; If not, see . 20 | ***/ 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include "attributes.h" 27 | #include "macro.h" 28 | 29 | #define MODE_INVALID ((mode_t) -1) 30 | 31 | int parse_boolean(const char *v) _pure_; 32 | 33 | int safe_atou(const char *s, unsigned *ret_u); 34 | int safe_atoi(const char *s, int *ret_i); 35 | int safe_atollu(const char *s, unsigned long long *ret_u); 36 | int safe_atolli(const char *s, long long int *ret_i); 37 | 38 | int safe_atou8(const char *s, uint8_t *ret); 39 | 40 | int safe_atou16(const char *s, uint16_t *ret); 41 | int safe_atoi16(const char *s, int16_t *ret); 42 | 43 | static inline int safe_atou32(const char *s, uint32_t *ret_u) { 44 | assert_cc(sizeof(uint32_t) == sizeof(unsigned)); 45 | return safe_atou(s, (unsigned*) ret_u); 46 | } 47 | 48 | static inline int safe_atoi32(const char *s, int32_t *ret_i) { 49 | assert_cc(sizeof(int32_t) == sizeof(int)); 50 | return safe_atoi(s, (int*) ret_i); 51 | } 52 | 53 | static inline int safe_atou64(const char *s, uint64_t *ret_u) { 54 | assert_cc(sizeof(uint64_t) == sizeof(unsigned long long)); 55 | return safe_atollu(s, (unsigned long long*) ret_u); 56 | } 57 | 58 | static inline int safe_atoi64(const char *s, int64_t *ret_i) { 59 | assert_cc(sizeof(int64_t) == sizeof(long long int)); 60 | return safe_atolli(s, (long long int*) ret_i); 61 | } 62 | 63 | #if LONG_MAX == INT_MAX 64 | static inline int safe_atolu(const char *s, unsigned long *ret_u) { 65 | assert_cc(sizeof(unsigned long) == sizeof(unsigned)); 66 | return safe_atou(s, (unsigned*) ret_u); 67 | } 68 | static inline int safe_atoli(const char *s, long int *ret_u) { 69 | assert_cc(sizeof(long int) == sizeof(int)); 70 | return safe_atoi(s, (int*) ret_u); 71 | } 72 | #else 73 | static inline int safe_atolu(const char *s, unsigned long *ret_u) { 74 | assert_cc(sizeof(unsigned long) == sizeof(unsigned long long)); 75 | return safe_atollu(s, (unsigned long long*) ret_u); 76 | } 77 | static inline int safe_atoli(const char *s, long int *ret_u) { 78 | assert_cc(sizeof(long int) == sizeof(long long int)); 79 | return safe_atolli(s, (long long int*) ret_u); 80 | } 81 | #endif 82 | 83 | int safe_atod(const char *s, double *ret_d); 84 | -------------------------------------------------------------------------------- /src/path-util.c: -------------------------------------------------------------------------------- 1 | /*** 2 | This file is part of systemd. 3 | 4 | Copyright 2010-2012 Lennart Poettering 5 | 6 | systemd is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation; either version 2.1 of the License, or 9 | (at your option) any later version. 10 | 11 | systemd is distributed in the hope that it will be useful, but 12 | WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with systemd; If not, see . 18 | ***/ 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include "alloc-util.h" 25 | #include "macro.h" 26 | #include "path-util.h" 27 | #include "string-util.h" 28 | #include "strv.h" 29 | 30 | bool path_is_absolute(const char *p) { 31 | return p[0] == '/'; 32 | } 33 | 34 | char **path_strv_resolve(char **l, const char *prefix) { 35 | char **s; 36 | unsigned k = 0; 37 | bool enomem = false; 38 | 39 | if (strv_isempty(l)) 40 | return l; 41 | 42 | /* Goes through every item in the string list and canonicalize 43 | * the path. This works in place and won't rollback any 44 | * changes on failure. */ 45 | 46 | STRV_FOREACH(s, l) { 47 | char *t, *u; 48 | _cleanup_free_ char *orig = NULL; 49 | 50 | if (!path_is_absolute(*s)) { 51 | free(*s); 52 | continue; 53 | } 54 | 55 | if (prefix) { 56 | orig = *s; 57 | t = strappend(prefix, orig); 58 | if (!t) { 59 | enomem = true; 60 | continue; 61 | } 62 | } else 63 | t = *s; 64 | 65 | errno = 0; 66 | u = canonicalize_file_name(t); 67 | if (!u) { 68 | if (errno == ENOENT) { 69 | if (prefix) { 70 | u = orig; 71 | orig = NULL; 72 | free(t); 73 | } else 74 | u = t; 75 | } else { 76 | free(t); 77 | if (errno == ENOMEM || errno == 0) 78 | enomem = true; 79 | 80 | continue; 81 | } 82 | } else if (prefix) { 83 | char *x; 84 | 85 | free(t); 86 | x = path_startswith(u, prefix); 87 | if (x) { 88 | /* restore the slash if it was lost */ 89 | if (!startswith(x, "/")) 90 | *(--x) = '/'; 91 | 92 | t = strdup(x); 93 | free(u); 94 | if (!t) { 95 | enomem = true; 96 | continue; 97 | } 98 | u = t; 99 | } else { 100 | /* canonicalized path goes outside of 101 | * prefix, keep the original path instead */ 102 | free(u); 103 | u = orig; 104 | orig = NULL; 105 | } 106 | } else 107 | free(t); 108 | 109 | l[k++] = u; 110 | } 111 | 112 | l[k] = NULL; 113 | 114 | if (enomem) 115 | return NULL; 116 | 117 | return l; 118 | } 119 | 120 | char **path_strv_resolve_uniq(char **l, const char *prefix) { 121 | 122 | if (strv_isempty(l)) 123 | return l; 124 | 125 | if (!path_strv_resolve(l, prefix)) 126 | return NULL; 127 | 128 | return strv_uniq(l); 129 | } 130 | 131 | char *path_kill_slashes(char *path) { 132 | char *f, *t; 133 | bool slash = false; 134 | 135 | /* Removes redundant inner and trailing slashes. Modifies the 136 | * passed string in-place. 137 | * 138 | * ///foo///bar/ becomes /foo/bar 139 | */ 140 | 141 | for (f = path, t = path; *f; f++) { 142 | 143 | if (*f == '/') { 144 | slash = true; 145 | continue; 146 | } 147 | 148 | if (slash) { 149 | slash = false; 150 | *(t++) = '/'; 151 | } 152 | 153 | *(t++) = *f; 154 | } 155 | 156 | /* Special rule, if we are talking of the root directory, a 157 | trailing slash is good */ 158 | 159 | if (t == path && slash) 160 | *(t++) = '/'; 161 | 162 | *t = 0; 163 | return path; 164 | } 165 | 166 | char* path_startswith(const char *path, const char *prefix) { 167 | assert(path); 168 | assert(prefix); 169 | 170 | if ((path[0] == '/') != (prefix[0] == '/')) 171 | return NULL; 172 | 173 | for (;;) { 174 | size_t a, b; 175 | 176 | path += strspn(path, "/"); 177 | prefix += strspn(prefix, "/"); 178 | 179 | if (*prefix == 0) 180 | return (char*) path; 181 | 182 | if (*path == 0) 183 | return NULL; 184 | 185 | a = strcspn(path, "/"); 186 | b = strcspn(prefix, "/"); 187 | 188 | if (a != b) 189 | return NULL; 190 | 191 | if (memcmp(path, prefix, a) != 0) 192 | return NULL; 193 | 194 | path += a; 195 | prefix += b; 196 | } 197 | } 198 | 199 | int path_compare(const char *a, const char *b) { 200 | int d; 201 | 202 | assert(a); 203 | assert(b); 204 | 205 | /* A relative path and an abolute path must not compare as equal. 206 | * Which one is sorted before the other does not really matter. 207 | * Here a relative path is ordered before an absolute path. */ 208 | d = (a[0] == '/') - (b[0] == '/'); 209 | if (d != 0) 210 | return d; 211 | 212 | for (;;) { 213 | size_t j, k; 214 | 215 | a += strspn(a, "/"); 216 | b += strspn(b, "/"); 217 | 218 | if (*a == 0 && *b == 0) 219 | return 0; 220 | 221 | /* Order prefixes first: "/foo" before "/foo/bar" */ 222 | if (*a == 0) 223 | return -1; 224 | if (*b == 0) 225 | return 1; 226 | 227 | j = strcspn(a, "/"); 228 | k = strcspn(b, "/"); 229 | 230 | /* Alphabetical sort: "/foo/aaa" before "/foo/b" */ 231 | d = memcmp(a, b, MIN(j, k)); 232 | if (d != 0) 233 | return (d > 0) - (d < 0); /* sign of d */ 234 | 235 | /* Sort "/foo/a" before "/foo/aaa" */ 236 | d = (j > k) - (j < k); /* sign of (j - k) */ 237 | if (d != 0) 238 | return d; 239 | 240 | a += j; 241 | b += k; 242 | } 243 | } 244 | 245 | bool path_equal(const char *a, const char *b) { 246 | return path_compare(a, b) == 0; 247 | } 248 | 249 | char *file_in_same_dir(const char *path, const char *filename) { 250 | char *e, *ret; 251 | size_t k; 252 | 253 | assert(path); 254 | assert(filename); 255 | 256 | /* This removes the last component of path and appends 257 | * filename, unless the latter is absolute anyway or the 258 | * former isn't */ 259 | 260 | if (path_is_absolute(filename)) 261 | return strdup(filename); 262 | 263 | e = strrchr(path, '/'); 264 | if (!e) 265 | return strdup(filename); 266 | 267 | k = strlen(filename); 268 | ret = new(char, (e + 1 - path) + k + 1); 269 | if (!ret) 270 | return NULL; 271 | 272 | memcpy(mempcpy(ret, path, e + 1 - path), filename, k + 1); 273 | return ret; 274 | } 275 | -------------------------------------------------------------------------------- /src/path-util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /*** 4 | This file is part of systemd. 5 | 6 | Copyright 2010-2012 Lennart Poettering 7 | 8 | systemd is free software; you can redistribute it and/or modify it 9 | under the terms of the GNU Lesser General Public License as published by 10 | the Free Software Foundation; either version 2.1 of the License, or 11 | (at your option) any later version. 12 | 13 | systemd is distributed in the hope that it will be useful, but 14 | WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public License 19 | along with systemd; If not, see . 20 | ***/ 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include "attributes.h" 27 | 28 | #define DEFAULT_PATH_NORMAL "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin" 29 | #define DEFAULT_PATH_SPLIT_USR DEFAULT_PATH_NORMAL ":/sbin:/bin" 30 | 31 | #ifdef HAVE_SPLIT_USR 32 | # define DEFAULT_PATH DEFAULT_PATH_SPLIT_USR 33 | #else 34 | # define DEFAULT_PATH DEFAULT_PATH_NORMAL 35 | #endif 36 | 37 | bool is_path(const char *p) _pure_; 38 | bool path_is_absolute(const char *p) _pure_; 39 | char* path_kill_slashes(char *path); 40 | char* path_startswith(const char *path, const char *prefix) _pure_; 41 | int path_compare(const char *a, const char *b) _pure_; 42 | bool path_equal(const char *a, const char *b) _pure_; 43 | 44 | char** path_strv_resolve(char **l, const char *prefix); 45 | char** path_strv_resolve_uniq(char **l, const char *prefix); 46 | 47 | /* Iterates through the path prefixes of the specified path, going up 48 | * the tree, to root. Also returns "" (and not "/"!) for the root 49 | * directory. Excludes the specified directory itself */ 50 | #define PATH_FOREACH_PREFIX(prefix, path) \ 51 | for (char *_slash = ({ path_kill_slashes(strcpy(prefix, path)); streq(prefix, "/") ? NULL : strrchr(prefix, '/'); }); _slash && ((*_slash = 0), true); _slash = strrchr((prefix), '/')) 52 | 53 | /* Same as PATH_FOREACH_PREFIX but also includes the specified path itself */ 54 | #define PATH_FOREACH_PREFIX_MORE(prefix, path) \ 55 | for (char *_slash = ({ path_kill_slashes(strcpy(prefix, path)); if (streq(prefix, "/")) prefix[0] = 0; strrchr(prefix, 0); }); _slash && ((*_slash = 0), true); _slash = strrchr((prefix), '/')) 56 | 57 | /* Similar to prefix_root(), but returns an alloca() buffer, or 58 | * possibly a const pointer into the path parameter */ 59 | #define prefix_roota(root, path) \ 60 | ({ \ 61 | const char* _path = (path), *_root = (root), *_ret; \ 62 | char *_p, *_n; \ 63 | size_t _l; \ 64 | while (_path[0] == '/' && _path[1] == '/') \ 65 | _path ++; \ 66 | if (isempty(_root) || path_equal(_root, "/")) \ 67 | _ret = _path; \ 68 | else { \ 69 | _l = strlen(_root) + 1 + strlen(_path) + 1; \ 70 | _n = alloca(_l); \ 71 | _p = stpcpy(_n, _root); \ 72 | while (_p > _n && _p[-1] == '/') \ 73 | _p--; \ 74 | if (_path[0] != '/') \ 75 | *(_p++) = '/'; \ 76 | strcpy(_p, _path); \ 77 | _ret = _n; \ 78 | } \ 79 | _ret; \ 80 | }) 81 | 82 | char *file_in_same_dir(const char *path, const char *filename); 83 | -------------------------------------------------------------------------------- /src/process-util.c: -------------------------------------------------------------------------------- 1 | /*** 2 | This file is part of systemd. 3 | 4 | Copyright 2010 Lennart Poettering 5 | 6 | systemd is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation; either version 2.1 of the License, or 9 | (at your option) any later version. 10 | 11 | systemd is distributed in the hope that it will be useful, but 12 | WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with systemd; If not, see . 18 | ***/ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #ifdef HAVE_VALGRIND_VALGRIND_H 29 | #include 30 | #endif 31 | 32 | #include "fd-util.h" 33 | #include "macro.h" 34 | #include "missing.h" 35 | #include "process-util.h" 36 | 37 | int getenv_for_pid(pid_t pid, const char *field, char **_value) { 38 | _cleanup_fclose_ FILE *f = NULL; 39 | char *value = NULL; 40 | int r; 41 | bool done = false; 42 | size_t l; 43 | const char *path; 44 | 45 | assert(pid >= 0); 46 | assert(field); 47 | assert(_value); 48 | 49 | path = procfs_file_alloca(pid, "environ"); 50 | 51 | f = fopen(path, "re"); 52 | if (!f) { 53 | if (errno == ENOENT) 54 | return -ESRCH; 55 | return -errno; 56 | } 57 | 58 | l = strlen(field); 59 | r = 0; 60 | 61 | do { 62 | char line[LINE_MAX]; 63 | unsigned i; 64 | 65 | for (i = 0; i < sizeof(line)-1; i++) { 66 | int c; 67 | 68 | c = getc(f); 69 | if (_unlikely_(c == EOF)) { 70 | done = true; 71 | break; 72 | } else if (c == 0) 73 | break; 74 | 75 | line[i] = c; 76 | } 77 | line[i] = 0; 78 | 79 | if (memcmp(line, field, l) == 0 && line[l] == '=') { 80 | value = strdup(line + l + 1); 81 | if (!value) 82 | return -ENOMEM; 83 | 84 | r = 1; 85 | break; 86 | } 87 | 88 | } while (!done); 89 | 90 | *_value = value; 91 | return r; 92 | } 93 | 94 | bool is_main_thread(void) { 95 | static thread_local int cached = 0; 96 | 97 | if (_unlikely_(cached == 0)) 98 | cached = getpid() == gettid() ? 1 : -1; 99 | 100 | return cached > 0; 101 | } 102 | -------------------------------------------------------------------------------- /src/process-util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /*** 4 | This file is part of systemd. 5 | 6 | Copyright 2010 Lennart Poettering 7 | 8 | systemd is free software; you can redistribute it and/or modify it 9 | under the terms of the GNU Lesser General Public License as published by 10 | the Free Software Foundation; either version 2.1 of the License, or 11 | (at your option) any later version. 12 | 13 | systemd is distributed in the hope that it will be useful, but 14 | WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public License 19 | along with systemd; If not, see . 20 | ***/ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "attributes.h" 28 | #include "formats-util.h" 29 | #include "macro.h" 30 | 31 | #define procfs_file_alloca(pid, field) \ 32 | ({ \ 33 | pid_t _pid_ = (pid); \ 34 | const char *_r_; \ 35 | if (_pid_ == 0) { \ 36 | _r_ = ("/proc/self/" field); \ 37 | } else { \ 38 | _r_ = alloca(strlen("/proc/") + DECIMAL_STR_MAX(pid_t) + 1 + sizeof(field)); \ 39 | sprintf((char*) _r_, "/proc/"PID_FMT"/" field, _pid_); \ 40 | } \ 41 | _r_; \ 42 | }) 43 | 44 | int getenv_for_pid(pid_t pid, const char *field, char **_value); 45 | 46 | bool pid_is_alive(pid_t pid); 47 | 48 | bool is_main_thread(void); 49 | 50 | #ifndef PERSONALITY_INVALID 51 | /* personality(7) documents that 0xffffffffUL is used for querying the 52 | * current personality, hence let's use that here as error 53 | * indicator. */ 54 | #define PERSONALITY_INVALID 0xffffffffLU 55 | #endif 56 | 57 | int ioprio_class_to_string_alloc(int i, char **s); 58 | int ioprio_class_from_string(const char *s); 59 | 60 | const char *sigchld_code_to_string(int i) _const_; 61 | int sigchld_code_from_string(const char *s) _pure_; 62 | 63 | #define PTR_TO_PID(p) ((pid_t) ((uintptr_t) p)) 64 | #define PID_TO_PTR(p) ((void*) ((uintptr_t) p)) 65 | -------------------------------------------------------------------------------- /src/random-util.c: -------------------------------------------------------------------------------- 1 | /*** 2 | This file is part of systemd. 3 | 4 | Copyright 2010 Lennart Poettering 5 | 6 | systemd is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation; either version 2.1 of the License, or 9 | (at your option) any later version. 10 | 11 | systemd is distributed in the hope that it will be useful, but 12 | WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with systemd; If not, see . 18 | ***/ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #ifdef HAVE_SYS_AUXV_H 29 | #include 30 | #endif 31 | 32 | #include "fd-util.h" 33 | #include "io-util.h" 34 | #include "missing.h" 35 | #include "random-util.h" 36 | #include "time-util.h" 37 | 38 | int dev_urandom(void *p, size_t n) { 39 | static int have_syscall = -1; 40 | 41 | _cleanup_close_ int fd = -1; 42 | int r; 43 | 44 | /* Gathers some randomness from the kernel. This call will 45 | * never block, and will always return some data from the 46 | * kernel, regardless if the random pool is fully initialized 47 | * or not. It thus makes no guarantee for the quality of the 48 | * returned entropy, but is good enough for or usual usecases 49 | * of seeding the hash functions for hashtable */ 50 | 51 | /* Use the getrandom() syscall unless we know we don't have 52 | * it, or when the requested size is too large for it. */ 53 | if (have_syscall != 0 || (size_t) (int) n != n) { 54 | r = getrandom(p, n, GRND_NONBLOCK); 55 | if (r == (int) n) { 56 | have_syscall = true; 57 | return 0; 58 | } 59 | 60 | if (r < 0) { 61 | if (errno == ENOSYS) 62 | /* we lack the syscall, continue with 63 | * reading from /dev/urandom */ 64 | have_syscall = false; 65 | else if (errno == EAGAIN) 66 | /* not enough entropy for now. Let's 67 | * remember to use the syscall the 68 | * next time, again, but also read 69 | * from /dev/urandom for now, which 70 | * doesn't care about the current 71 | * amount of entropy. */ 72 | have_syscall = true; 73 | else 74 | return -errno; 75 | } else 76 | /* too short read? */ 77 | return -ENODATA; 78 | } 79 | 80 | fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY); 81 | if (fd < 0) 82 | return errno == ENOENT ? -ENOSYS : -errno; 83 | 84 | return loop_read_exact(fd, p, n, true); 85 | } 86 | 87 | void initialize_srand(void) { 88 | static bool srand_called = false; 89 | unsigned x; 90 | #ifdef HAVE_SYS_AUXV_H 91 | void *auxv; 92 | #endif 93 | 94 | if (srand_called) 95 | return; 96 | 97 | #ifdef HAVE_SYS_AUXV_H 98 | /* The kernel provides us with 16 bytes of entropy in auxv, so let's try to make use of that to seed the 99 | * pseudo-random generator. It's better than nothing... */ 100 | 101 | auxv = (void*) getauxval(AT_RANDOM); 102 | if (auxv) { 103 | assert_cc(sizeof(x) < 16); 104 | memcpy(&x, auxv, sizeof(x)); 105 | } else 106 | #endif 107 | x = 0; 108 | 109 | 110 | x ^= (unsigned) now(CLOCK_REALTIME); 111 | x ^= (unsigned) gettid(); 112 | 113 | srand(x); 114 | srand_called = true; 115 | } 116 | 117 | void random_bytes(void *p, size_t n) { 118 | uint8_t *q; 119 | int r; 120 | 121 | r = dev_urandom(p, n); 122 | if (r >= 0) 123 | return; 124 | 125 | /* If some idiot made /dev/urandom unavailable to us, he'll 126 | * get a PRNG instead. */ 127 | 128 | initialize_srand(); 129 | 130 | for (q = p; q < (uint8_t*) p + n; q ++) 131 | *q = rand(); 132 | } 133 | -------------------------------------------------------------------------------- /src/random-util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /*** 4 | This file is part of systemd. 5 | 6 | Copyright 2010 Lennart Poettering 7 | 8 | systemd is free software; you can redistribute it and/or modify it 9 | under the terms of the GNU Lesser General Public License as published by 10 | the Free Software Foundation; either version 2.1 of the License, or 11 | (at your option) any later version. 12 | 13 | systemd is distributed in the hope that it will be useful, but 14 | WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public License 19 | along with systemd; If not, see . 20 | ***/ 21 | 22 | #include 23 | #include 24 | 25 | int dev_urandom(void *p, size_t n); 26 | void random_bytes(void *p, size_t n); 27 | void initialize_srand(void); 28 | 29 | static inline uint64_t random_u64(void) { 30 | uint64_t u; 31 | random_bytes(&u, sizeof(u)); 32 | return u; 33 | } 34 | 35 | static inline uint32_t random_u32(void) { 36 | uint32_t u; 37 | random_bytes(&u, sizeof(u)); 38 | return u; 39 | } 40 | -------------------------------------------------------------------------------- /src/sd-messages.h: -------------------------------------------------------------------------------- 1 | #ifndef foosdmessageshfoo 2 | #define foosdmessageshfoo 3 | 4 | /*** 5 | This file is part of systemd. 6 | 7 | Copyright 2012 Lennart Poettering 8 | 9 | systemd is free software; you can redistribute it and/or modify it 10 | under the terms of the GNU Lesser General Public License as published by 11 | the Free Software Foundation; either version 2.1 of the License, or 12 | (at your option) any later version. 13 | 14 | systemd is distributed in the hope that it will be useful, but 15 | WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | Lesser General Public License for more details. 18 | 19 | You should have received a copy of the GNU Lesser General Public License 20 | along with systemd; If not, see . 21 | ***/ 22 | 23 | #ifdef HAVE_LIBSYSTEMD 24 | #include 25 | 26 | #include "_sd-common.h" 27 | 28 | _SD_BEGIN_DECLARATIONS; 29 | 30 | #define SD_MESSAGE_INVALID_CONFIGURATION SD_ID128_MAKE(c7,72,d2,4e,9a,88,4c,be,b9,ea,12,62,5c,30,6c,01) 31 | #define SD_MESSAGE_BOOTCHART SD_ID128_MAKE(9f,26,aa,56,2c,f4,40,c2,b1,6c,77,3d,04,79,b5,18) 32 | 33 | _SD_END_DECLARATIONS; 34 | #endif 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /src/set.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /*** 4 | This file is part of systemd. 5 | 6 | Copyright 2010 Lennart Poettering 7 | 8 | systemd is free software; you can redistribute it and/or modify it 9 | under the terms of the GNU Lesser General Public License as published by 10 | the Free Software Foundation; either version 2.1 of the License, or 11 | (at your option) any later version. 12 | 13 | systemd is distributed in the hope that it will be useful, but 14 | WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public License 19 | along with systemd; If not, see . 20 | ***/ 21 | 22 | #include "hashmap.h" 23 | #include "macro.h" 24 | 25 | Set *internal_set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); 26 | #define set_new(ops) internal_set_new(ops HASHMAP_DEBUG_SRC_ARGS) 27 | 28 | static inline Set *set_free(Set *s) { 29 | internal_hashmap_free(HASHMAP_BASE(s)); 30 | return NULL; 31 | } 32 | 33 | static inline Set *set_free_free(Set *s) { 34 | internal_hashmap_free_free(HASHMAP_BASE(s)); 35 | return NULL; 36 | } 37 | 38 | /* no set_free_free_free */ 39 | 40 | static inline Set *set_copy(Set *s) { 41 | return (Set*) internal_hashmap_copy(HASHMAP_BASE(s)); 42 | } 43 | 44 | int internal_set_ensure_allocated(Set **s, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); 45 | #define set_ensure_allocated(h, ops) internal_set_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS) 46 | 47 | int set_put(Set *s, const void *key); 48 | /* no set_update */ 49 | /* no set_replace */ 50 | static inline void *set_get(Set *s, void *key) { 51 | return internal_hashmap_get(HASHMAP_BASE(s), key); 52 | } 53 | /* no set_get2 */ 54 | 55 | static inline bool set_contains(Set *s, const void *key) { 56 | return internal_hashmap_contains(HASHMAP_BASE(s), key); 57 | } 58 | 59 | static inline void *set_remove(Set *s, const void *key) { 60 | return internal_hashmap_remove(HASHMAP_BASE(s), key); 61 | } 62 | 63 | /* no set_remove2 */ 64 | /* no set_remove_value */ 65 | int set_remove_and_put(Set *s, const void *old_key, const void *new_key); 66 | /* no set_remove_and_replace */ 67 | int set_merge(Set *s, Set *other); 68 | 69 | static inline int set_reserve(Set *h, unsigned entries_add) { 70 | return internal_hashmap_reserve(HASHMAP_BASE(h), entries_add); 71 | } 72 | 73 | static inline int set_move(Set *s, Set *other) { 74 | return internal_hashmap_move(HASHMAP_BASE(s), HASHMAP_BASE(other)); 75 | } 76 | 77 | static inline int set_move_one(Set *s, Set *other, const void *key) { 78 | return internal_hashmap_move_one(HASHMAP_BASE(s), HASHMAP_BASE(other), key); 79 | } 80 | 81 | static inline unsigned set_size(Set *s) { 82 | return internal_hashmap_size(HASHMAP_BASE(s)); 83 | } 84 | 85 | static inline bool set_isempty(Set *s) { 86 | return set_size(s) == 0; 87 | } 88 | 89 | static inline unsigned set_buckets(Set *s) { 90 | return internal_hashmap_buckets(HASHMAP_BASE(s)); 91 | } 92 | 93 | bool set_iterate(Set *s, Iterator *i, void **value); 94 | 95 | static inline void set_clear(Set *s) { 96 | internal_hashmap_clear(HASHMAP_BASE(s)); 97 | } 98 | 99 | static inline void set_clear_free(Set *s) { 100 | internal_hashmap_clear_free(HASHMAP_BASE(s)); 101 | } 102 | 103 | /* no set_clear_free_free */ 104 | 105 | static inline void *set_steal_first(Set *s) { 106 | return internal_hashmap_steal_first(HASHMAP_BASE(s)); 107 | } 108 | 109 | /* no set_steal_first_key */ 110 | /* no set_first_key */ 111 | /* no set_next */ 112 | 113 | static inline char **set_get_strv(Set *s) { 114 | return internal_hashmap_get_strv(HASHMAP_BASE(s)); 115 | } 116 | 117 | int set_consume(Set *s, void *value); 118 | int set_put_strdup(Set *s, const char *p); 119 | int set_put_strdupv(Set *s, char **l); 120 | 121 | #define SET_FOREACH(e, s, i) \ 122 | for ((i) = ITERATOR_FIRST; set_iterate((s), &(i), (void**)&(e)); ) 123 | 124 | DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, set_free); 125 | DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, set_free_free); 126 | 127 | #define _cleanup_set_free_ _cleanup_(set_freep) 128 | #define _cleanup_set_free_free_ _cleanup_(set_free_freep) 129 | -------------------------------------------------------------------------------- /src/siphash24.c: -------------------------------------------------------------------------------- 1 | /* 2 | SipHash reference C implementation 3 | 4 | Written in 2012 by 5 | Jean-Philippe Aumasson 6 | Daniel J. Bernstein 7 | 8 | To the extent possible under law, the author(s) have dedicated all copyright 9 | and related and neighboring rights to this software to the public domain 10 | worldwide. This software is distributed without any warranty. 11 | 12 | You should have received a copy of the CC0 Public Domain Dedication along with 13 | this software. If not, see . 14 | 15 | (Minimal changes made by Lennart Poettering, to make clean for inclusion in systemd) 16 | (Refactored by Tom Gundersen to split up in several functions and follow systemd 17 | coding style) 18 | */ 19 | 20 | #include "macro.h" 21 | #include "siphash24.h" 22 | #include "unaligned.h" 23 | 24 | static inline uint64_t rotate_left(uint64_t x, uint8_t b) { 25 | assert(b < 64); 26 | 27 | return (x << b) | (x >> (64 - b)); 28 | } 29 | 30 | static inline void sipround(struct siphash *state) { 31 | assert(state); 32 | 33 | state->v0 += state->v1; 34 | state->v1 = rotate_left(state->v1, 13); 35 | state->v1 ^= state->v0; 36 | state->v0 = rotate_left(state->v0, 32); 37 | state->v2 += state->v3; 38 | state->v3 = rotate_left(state->v3, 16); 39 | state->v3 ^= state->v2; 40 | state->v0 += state->v3; 41 | state->v3 = rotate_left(state->v3, 21); 42 | state->v3 ^= state->v0; 43 | state->v2 += state->v1; 44 | state->v1 = rotate_left(state->v1, 17); 45 | state->v1 ^= state->v2; 46 | state->v2 = rotate_left(state->v2, 32); 47 | } 48 | 49 | void siphash24_init(struct siphash *state, const uint8_t k[16]) { 50 | uint64_t k0, k1; 51 | 52 | assert(state); 53 | assert(k); 54 | 55 | k0 = unaligned_read_le64(k); 56 | k1 = unaligned_read_le64(k + 8); 57 | 58 | *state = (struct siphash) { 59 | /* "somepseudorandomlygeneratedbytes" */ 60 | .v0 = 0x736f6d6570736575ULL ^ k0, 61 | .v1 = 0x646f72616e646f6dULL ^ k1, 62 | .v2 = 0x6c7967656e657261ULL ^ k0, 63 | .v3 = 0x7465646279746573ULL ^ k1, 64 | .padding = 0, 65 | .inlen = 0, 66 | }; 67 | } 68 | 69 | void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) { 70 | 71 | const uint8_t *in = _in; 72 | const uint8_t *end = in + inlen; 73 | size_t left = state->inlen & 7; 74 | uint64_t m; 75 | 76 | assert(in); 77 | assert(state); 78 | 79 | /* Update total length */ 80 | state->inlen += inlen; 81 | 82 | /* If padding exists, fill it out */ 83 | if (left > 0) { 84 | for ( ; in < end && left < 8; in ++, left ++) 85 | state->padding |= ((uint64_t) *in) << (left * 8); 86 | 87 | if (in == end && left < 8) 88 | /* We did not have enough input to fill out the padding completely */ 89 | return; 90 | 91 | #ifdef DEBUG 92 | printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0); 93 | printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1); 94 | printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2); 95 | printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3); 96 | printf("(%3zu) compress padding %08x %08x\n", state->inlen, (uint32_t) (state->padding >> 32), (uint32_t)state->padding); 97 | #endif 98 | 99 | state->v3 ^= state->padding; 100 | sipround(state); 101 | sipround(state); 102 | state->v0 ^= state->padding; 103 | 104 | state->padding = 0; 105 | } 106 | 107 | end -= (state->inlen % sizeof(uint64_t)); 108 | 109 | for ( ; in < end; in += 8) { 110 | m = unaligned_read_le64(in); 111 | #ifdef DEBUG 112 | printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0); 113 | printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1); 114 | printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2); 115 | printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3); 116 | printf("(%3zu) compress %08x %08x\n", state->inlen, (uint32_t) (m >> 32), (uint32_t) m); 117 | #endif 118 | state->v3 ^= m; 119 | sipround(state); 120 | sipround(state); 121 | state->v0 ^= m; 122 | } 123 | 124 | left = state->inlen & 7; 125 | switch (left) { 126 | case 7: 127 | state->padding |= ((uint64_t) in[6]) << 48; 128 | case 6: 129 | state->padding |= ((uint64_t) in[5]) << 40; 130 | case 5: 131 | state->padding |= ((uint64_t) in[4]) << 32; 132 | case 4: 133 | state->padding |= ((uint64_t) in[3]) << 24; 134 | case 3: 135 | state->padding |= ((uint64_t) in[2]) << 16; 136 | case 2: 137 | state->padding |= ((uint64_t) in[1]) << 8; 138 | case 1: 139 | state->padding |= ((uint64_t) in[0]); 140 | case 0: 141 | break; 142 | } 143 | } 144 | 145 | uint64_t siphash24_finalize(struct siphash *state) { 146 | uint64_t b; 147 | 148 | assert(state); 149 | 150 | b = state->padding | (((uint64_t) state->inlen) << 56); 151 | 152 | #ifdef DEBUG 153 | printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0); 154 | printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1); 155 | printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2); 156 | printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3); 157 | printf("(%3zu) padding %08x %08x\n", state->inlen, (uint32_t) (state->padding >> 32), (uint32_t) state->padding); 158 | #endif 159 | 160 | state->v3 ^= b; 161 | sipround(state); 162 | sipround(state); 163 | state->v0 ^= b; 164 | 165 | #ifdef DEBUG 166 | printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0); 167 | printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1); 168 | printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2); 169 | printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3); 170 | #endif 171 | state->v2 ^= 0xff; 172 | 173 | sipround(state); 174 | sipround(state); 175 | sipround(state); 176 | sipround(state); 177 | 178 | return state->v0 ^ state->v1 ^ state->v2 ^ state->v3; 179 | } 180 | 181 | uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[16]) { 182 | struct siphash state; 183 | 184 | assert(in); 185 | assert(k); 186 | 187 | siphash24_init(&state, k); 188 | siphash24_compress(in, inlen, &state); 189 | 190 | return siphash24_finalize(&state); 191 | } 192 | -------------------------------------------------------------------------------- /src/siphash24.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | struct siphash { 7 | uint64_t v0; 8 | uint64_t v1; 9 | uint64_t v2; 10 | uint64_t v3; 11 | uint64_t padding; 12 | size_t inlen; 13 | }; 14 | 15 | void siphash24_init(struct siphash *state, const uint8_t k[16]); 16 | void siphash24_compress(const void *in, size_t inlen, struct siphash *state); 17 | #define siphash24_compress_byte(byte, state) siphash24_compress((const uint8_t[]) { (byte) }, 1, (state)) 18 | 19 | uint64_t siphash24_finalize(struct siphash *state); 20 | 21 | uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[16]); 22 | -------------------------------------------------------------------------------- /src/stdio-util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /*** 4 | This file is part of systemd. 5 | 6 | Copyright 2010 Lennart Poettering 7 | 8 | systemd is free software; you can redistribute it and/or modify it 9 | under the terms of the GNU Lesser General Public License as published by 10 | the Free Software Foundation; either version 2.1 of the License, or 11 | (at your option) any later version. 12 | 13 | systemd is distributed in the hope that it will be useful, but 14 | WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public License 19 | along with systemd; If not, see . 20 | ***/ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "macro.h" 28 | 29 | #define xsprintf(buf, fmt, ...) \ 30 | assert_message_se((size_t) snprintf(buf, ELEMENTSOF(buf), fmt, __VA_ARGS__) < ELEMENTSOF(buf), "xsprintf: " #buf "[] must be big enough") 31 | 32 | 33 | #define VA_FORMAT_ADVANCE(format, ap) \ 34 | do { \ 35 | int _argtypes[128]; \ 36 | size_t _i, _k; \ 37 | _k = parse_printf_format((format), ELEMENTSOF(_argtypes), _argtypes); \ 38 | assert(_k < ELEMENTSOF(_argtypes)); \ 39 | for (_i = 0; _i < _k; _i++) { \ 40 | if (_argtypes[_i] & PA_FLAG_PTR) { \ 41 | (void) va_arg(ap, void*); \ 42 | continue; \ 43 | } \ 44 | \ 45 | switch (_argtypes[_i]) { \ 46 | case PA_INT: \ 47 | case PA_INT|PA_FLAG_SHORT: \ 48 | case PA_CHAR: \ 49 | (void) va_arg(ap, int); \ 50 | break; \ 51 | case PA_INT|PA_FLAG_LONG: \ 52 | (void) va_arg(ap, long int); \ 53 | break; \ 54 | case PA_INT|PA_FLAG_LONG_LONG: \ 55 | (void) va_arg(ap, long long int); \ 56 | break; \ 57 | case PA_WCHAR: \ 58 | (void) va_arg(ap, wchar_t); \ 59 | break; \ 60 | case PA_WSTRING: \ 61 | case PA_STRING: \ 62 | case PA_POINTER: \ 63 | (void) va_arg(ap, void*); \ 64 | break; \ 65 | case PA_FLOAT: \ 66 | case PA_DOUBLE: \ 67 | (void) va_arg(ap, double); \ 68 | break; \ 69 | case PA_DOUBLE|PA_FLAG_LONG_DOUBLE: \ 70 | (void) va_arg(ap, long double); \ 71 | break; \ 72 | default: \ 73 | assert_not_reached("Unknown format string argument."); \ 74 | } \ 75 | } \ 76 | } while(false) 77 | -------------------------------------------------------------------------------- /src/store.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /*** 4 | This file is part of systemd. 5 | 6 | Copyright (C) 2009-2013 Intel Corporation 7 | 8 | Authors: 9 | Auke Kok 10 | 11 | systemd is free software; you can redistribute it and/or modify it 12 | under the terms of the GNU Lesser General Public License as published by 13 | the Free Software Foundation; either version 2.1 of the License, or 14 | (at your option) any later version. 15 | 16 | systemd is distributed in the hope that it will be useful, but 17 | WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | Lesser General Public License for more details. 20 | 21 | You should have received a copy of the GNU Lesser General Public License 22 | along with systemd; If not, see . 23 | ***/ 24 | 25 | #include 26 | 27 | #include "bootchart.h" 28 | 29 | double gettime_ns(void); 30 | void log_uptime(void); 31 | int log_sample(DIR *proc, 32 | int sample, 33 | struct ps_struct *ps_first, 34 | struct list_sample_data **ptr, 35 | int *pscount, 36 | int *cpus); 37 | -------------------------------------------------------------------------------- /src/string-util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /*** 4 | This file is part of systemd. 5 | 6 | Copyright 2010 Lennart Poettering 7 | 8 | systemd is free software; you can redistribute it and/or modify it 9 | under the terms of the GNU Lesser General Public License as published by 10 | the Free Software Foundation; either version 2.1 of the License, or 11 | (at your option) any later version. 12 | 13 | systemd is distributed in the hope that it will be useful, but 14 | WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public License 19 | along with systemd; If not, see . 20 | ***/ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "attributes.h" 28 | #include "macro.h" 29 | 30 | /* What is interpreted as whitespace? */ 31 | #define WHITESPACE " \t\n\r" 32 | #define NEWLINE "\n\r" 33 | #define QUOTES "\"\'" 34 | #define COMMENTS "#;" 35 | #define GLOB_CHARS "*?[" 36 | #define DIGITS "0123456789" 37 | #define LOWERCASE_LETTERS "abcdefghijklmnopqrstuvwxyz" 38 | #define UPPERCASE_LETTERS "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 39 | #define LETTERS LOWERCASE_LETTERS UPPERCASE_LETTERS 40 | #define ALPHANUMERICAL LETTERS DIGITS 41 | 42 | #define streq(a,b) (strcmp((a),(b)) == 0) 43 | #define strneq(a, b, n) (strncmp((a), (b), (n)) == 0) 44 | #define strcaseeq(a,b) (strcasecmp((a),(b)) == 0) 45 | #define strncaseeq(a, b, n) (strncasecmp((a), (b), (n)) == 0) 46 | 47 | int strcmp_ptr(const char *a, const char *b) _pure_; 48 | 49 | static inline bool streq_ptr(const char *a, const char *b) { 50 | return strcmp_ptr(a, b) == 0; 51 | } 52 | 53 | static inline const char* strempty(const char *s) { 54 | return s ? s : ""; 55 | } 56 | 57 | static inline const char* strnull(const char *s) { 58 | return s ? s : "(null)"; 59 | } 60 | 61 | static inline const char *strna(const char *s) { 62 | return s ? s : "n/a"; 63 | } 64 | 65 | static inline bool isempty(const char *p) { 66 | return !p || !p[0]; 67 | } 68 | 69 | static inline char *startswith(const char *s, const char *prefix) { 70 | size_t l; 71 | 72 | l = strlen(prefix); 73 | if (strncmp(s, prefix, l) == 0) 74 | return (char*) s + l; 75 | 76 | return NULL; 77 | } 78 | 79 | static inline char *startswith_no_case(const char *s, const char *prefix) { 80 | size_t l; 81 | 82 | l = strlen(prefix); 83 | if (strncasecmp(s, prefix, l) == 0) 84 | return (char*) s + l; 85 | 86 | return NULL; 87 | } 88 | 89 | char *endswith(const char *s, const char *postfix) _pure_; 90 | 91 | const char* split(const char **state, size_t *l, const char *separator, bool quoted); 92 | 93 | #define FOREACH_WORD(word, length, s, state) \ 94 | _FOREACH_WORD(word, length, s, WHITESPACE, false, state) 95 | 96 | #define FOREACH_WORD_SEPARATOR(word, length, s, separator, state) \ 97 | _FOREACH_WORD(word, length, s, separator, false, state) 98 | 99 | #define FOREACH_WORD_QUOTED(word, length, s, state) \ 100 | _FOREACH_WORD(word, length, s, WHITESPACE, true, state) 101 | 102 | #define _FOREACH_WORD(word, length, s, separator, quoted, state) \ 103 | for ((state) = (s), (word) = split(&(state), &(length), (separator), (quoted)); (word); (word) = split(&(state), &(length), (separator), (quoted))) 104 | 105 | char *strappend(const char *s, const char *suffix); 106 | char *strnappend(const char *s, const char *suffix, size_t length); 107 | 108 | char *strjoin(const char *x, ...) _sentinel_; 109 | 110 | #define strjoina(a, ...) \ 111 | ({ \ 112 | const char *_appendees_[] = { a, __VA_ARGS__ }; \ 113 | char *_d_, *_p_; \ 114 | int _len_ = 0; \ 115 | unsigned _i_; \ 116 | for (_i_ = 0; _i_ < ELEMENTSOF(_appendees_) && _appendees_[_i_]; _i_++) \ 117 | _len_ += strlen(_appendees_[_i_]); \ 118 | _p_ = _d_ = alloca(_len_ + 1); \ 119 | for (_i_ = 0; _i_ < ELEMENTSOF(_appendees_) && _appendees_[_i_]; _i_++) \ 120 | _p_ = stpcpy(_p_, _appendees_[_i_]); \ 121 | *_p_ = 0; \ 122 | _d_; \ 123 | }) 124 | 125 | char *strstrip(char *s); 126 | char *truncate_nl(char *s); 127 | 128 | static inline bool _pure_ in_charset(const char *s, const char* charset) { 129 | assert(s); 130 | assert(charset); 131 | return s[strspn(s, charset)] == '\0'; 132 | } 133 | 134 | char *ellipsize_mem(const char *s, size_t old_length_bytes, size_t new_length_columns, unsigned percent); 135 | char *ellipsize(const char *s, size_t length, unsigned percent); 136 | 137 | bool nulstr_contains(const char*nulstr, const char *needle); 138 | 139 | char* strshorten(char *s, size_t l); 140 | 141 | char *strip_tab_ansi(char **p, size_t *l); 142 | 143 | char *strextend(char **x, ...) _sentinel_; 144 | 145 | char *strrep(const char *s, unsigned n); 146 | 147 | /* Normal memmem() requires haystack to be nonnull, which is annoying for zero-length buffers */ 148 | static inline void *memmem_safe(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen) { 149 | 150 | if (needlelen <= 0) 151 | return (void*) haystack; 152 | 153 | if (haystacklen < needlelen) 154 | return NULL; 155 | 156 | assert(haystack); 157 | assert(needle); 158 | 159 | return memmem(haystack, haystacklen, needle, needlelen); 160 | } 161 | -------------------------------------------------------------------------------- /src/strv.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /*** 4 | This file is part of systemd. 5 | 6 | Copyright 2010 Lennart Poettering 7 | 8 | systemd is free software; you can redistribute it and/or modify it 9 | under the terms of the GNU Lesser General Public License as published by 10 | the Free Software Foundation; either version 2.1 of the License, or 11 | (at your option) any later version. 12 | 13 | systemd is distributed in the hope that it will be useful, but 14 | WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public License 19 | along with systemd; If not, see . 20 | ***/ 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include "alloc-util.h" 27 | #include "attributes.h" 28 | #include "macro.h" 29 | 30 | char *strv_find(char **l, const char *name) _pure_; 31 | char *strv_find_prefix(char **l, const char *name) _pure_; 32 | char *strv_find_startswith(char **l, const char *name) _pure_; 33 | 34 | char **strv_free(char **l); 35 | DEFINE_TRIVIAL_CLEANUP_FUNC(char**, strv_free); 36 | #define _cleanup_strv_free_ _cleanup_(strv_freep) 37 | 38 | void strv_clear(char **l); 39 | 40 | char **strv_copy(char * const *l); 41 | unsigned strv_length(char * const *l) _pure_; 42 | 43 | int strv_extend_strv(char ***a, char **b, bool filter_duplicates); 44 | int strv_extend_strv_concat(char ***a, char **b, const char *suffix); 45 | int strv_extend(char ***l, const char *value); 46 | int strv_extendf(char ***l, const char *format, ...) _printf_(2,0); 47 | int strv_push(char ***l, char *value); 48 | int strv_push_pair(char ***l, char *a, char *b); 49 | int strv_push_prepend(char ***l, char *value); 50 | int strv_consume(char ***l, char *value); 51 | int strv_consume_prepend(char ***l, char *value); 52 | 53 | char **strv_remove(char **l, const char *s); 54 | char **strv_uniq(char **l); 55 | bool strv_is_uniq(char **l); 56 | 57 | bool strv_equal(char **a, char **b); 58 | 59 | #define strv_contains(l, s) (!!strv_find((l), (s))) 60 | 61 | char **strv_new(const char *x, ...) _sentinel_; 62 | char **strv_new_ap(const char *x, va_list ap); 63 | 64 | static inline const char* STRV_IFNOTNULL(const char *x) { 65 | return x ? x : (const char *) -1; 66 | } 67 | 68 | static inline bool strv_isempty(char * const *l) { 69 | return !l || !*l; 70 | } 71 | 72 | char **strv_split(const char *s, const char *separator); 73 | 74 | char *strv_join(char **l, const char *separator); 75 | 76 | char **strv_parse_nulstr(const char *s, size_t l); 77 | char **strv_split_nulstr(const char *s); 78 | 79 | bool strv_overlap(char **a, char **b) _pure_; 80 | 81 | #define STRV_FOREACH(s, l) \ 82 | for ((s) = (l); (s) && *(s); (s)++) 83 | 84 | #define STRV_FOREACH_BACKWARDS(s, l) \ 85 | STRV_FOREACH(s, l) \ 86 | ; \ 87 | for ((s)--; (l) && ((s) >= (l)); (s)--) 88 | 89 | #define STRV_FOREACH_PAIR(x, y, l) \ 90 | for ((x) = (l), (y) = (x+1); (x) && *(x) && *(y); (x) += 2, (y) = (x + 1)) 91 | 92 | char **strv_sort(char **l); 93 | void strv_print(char **l); 94 | 95 | #define STRV_MAKE(...) ((char**) ((const char*[]) { __VA_ARGS__, NULL })) 96 | 97 | #define STRV_MAKE_EMPTY ((char*[1]) { NULL }) 98 | 99 | #define strv_from_stdarg_alloca(first) \ 100 | ({ \ 101 | char **_l; \ 102 | \ 103 | if (!first) \ 104 | _l = (char**) &first; \ 105 | else { \ 106 | unsigned _n; \ 107 | va_list _ap; \ 108 | \ 109 | _n = 1; \ 110 | va_start(_ap, first); \ 111 | while (va_arg(_ap, char*)) \ 112 | _n++; \ 113 | va_end(_ap); \ 114 | \ 115 | _l = newa(char*, _n+1); \ 116 | _l[_n = 0] = (char*) first; \ 117 | va_start(_ap, first); \ 118 | for (;;) { \ 119 | _l[++_n] = va_arg(_ap, char*); \ 120 | if (!_l[_n]) \ 121 | break; \ 122 | } \ 123 | va_end(_ap); \ 124 | } \ 125 | _l; \ 126 | }) 127 | 128 | #define STR_IN_SET(x, ...) strv_contains(STRV_MAKE(__VA_ARGS__), x) 129 | 130 | #define FOREACH_STRING(x, ...) \ 131 | for (char **_l = ({ \ 132 | char **_ll = STRV_MAKE(__VA_ARGS__); \ 133 | x = _ll ? _ll[0] : NULL; \ 134 | _ll; \ 135 | }); \ 136 | _l && *_l; \ 137 | x = ({ \ 138 | _l ++; \ 139 | _l[0]; \ 140 | })) 141 | 142 | char **strv_reverse(char **l); 143 | 144 | bool strv_fnmatch(char* const* patterns, const char *s, int flags); 145 | 146 | static inline bool strv_fnmatch_or_empty(char* const* patterns, const char *s, int flags) { 147 | assert(s); 148 | return strv_isempty(patterns) || 149 | strv_fnmatch(patterns, s, flags); 150 | } 151 | 152 | char ***strv_free_free(char ***l); 153 | 154 | char **strv_skip(char **l, size_t n); 155 | 156 | int strv_extend_n(char ***l, const char *value, size_t n); 157 | -------------------------------------------------------------------------------- /src/strxcpyx.c: -------------------------------------------------------------------------------- 1 | /*** 2 | This file is part of systemd. 3 | 4 | Copyright 2013 Kay Sievers 5 | 6 | systemd is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation; either version 2.1 of the License, or 9 | (at your option) any later version. 10 | 11 | systemd is distributed in the hope that it will be useful, but 12 | WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with systemd; If not, see . 18 | ***/ 19 | 20 | /* 21 | * Concatenates/copies strings. In any case, terminates in all cases 22 | * with '\0' * and moves the @dest pointer forward to the added '\0'. 23 | * Returns the * remaining size, and 0 if the string was truncated. 24 | */ 25 | 26 | #include 27 | 28 | #include "strxcpyx.h" 29 | 30 | size_t strpcpy(char **dest, size_t size, const char *src) { 31 | size_t len; 32 | 33 | len = strlen(src); 34 | if (len >= size) { 35 | if (size > 1) 36 | *dest = mempcpy(*dest, src, size-1); 37 | size = 0; 38 | } else { 39 | if (len > 0) { 40 | *dest = mempcpy(*dest, src, len); 41 | size -= len; 42 | } 43 | } 44 | *dest[0] = '\0'; 45 | return size; 46 | } 47 | 48 | size_t strscpy(char *dest, size_t size, const char *src) { 49 | char *s; 50 | 51 | s = dest; 52 | return strpcpy(&s, size, src); 53 | } 54 | -------------------------------------------------------------------------------- /src/strxcpyx.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /*** 4 | This file is part of systemd. 5 | 6 | Copyright 2013 Kay Sievers 7 | 8 | systemd is free software; you can redistribute it and/or modify it 9 | under the terms of the GNU Lesser General Public License as published by 10 | the Free Software Foundation; either version 2.1 of the License, or 11 | (at your option) any later version. 12 | 13 | systemd is distributed in the hope that it will be useful, but 14 | WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public License 19 | along with systemd; If not, see . 20 | ***/ 21 | 22 | 23 | #include 24 | 25 | size_t strpcpy(char **dest, size_t size, const char *src); 26 | size_t strscpy(char *dest, size_t size, const char *src); 27 | -------------------------------------------------------------------------------- /src/svg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /*** 4 | This file is part of systemd. 5 | 6 | Copyright (C) 2009-2013 Intel Corporation 7 | 8 | Authors: 9 | Auke Kok 10 | 11 | systemd is free software; you can redistribute it and/or modify it 12 | under the terms of the GNU Lesser General Public License as published by 13 | the Free Software Foundation; either version 2.1 of the License, or 14 | (at your option) any later version. 15 | 16 | systemd is distributed in the hope that it will be useful, but 17 | WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | Lesser General Public License for more details. 20 | 21 | You should have received a copy of the GNU Lesser General Public License 22 | along with systemd; If not, see . 23 | ***/ 24 | 25 | #include 26 | #include 27 | 28 | int svg_do(FILE *of, 29 | const char *build, 30 | struct list_sample_data *head, 31 | struct ps_struct *ps_first, 32 | int n_samples, 33 | int pscount, 34 | int n_cpus, 35 | double graph_start, 36 | double log_start, 37 | double interval, 38 | int overrun); 39 | -------------------------------------------------------------------------------- /src/terminal-util.c: -------------------------------------------------------------------------------- 1 | /*** 2 | This file is part of systemd. 3 | 4 | Copyright 2010 Lennart Poettering 5 | 6 | systemd is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation; either version 2.1 of the License, or 9 | (at your option) any later version. 10 | 11 | systemd is distributed in the hope that it will be useful, but 12 | WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with systemd; If not, see . 18 | ***/ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "fd-util.h" 28 | #include "macro.h" 29 | #include "terminal-util.h" 30 | #include "time-util.h" 31 | 32 | static volatile unsigned cached_columns = 0; 33 | static volatile unsigned cached_lines = 0; 34 | 35 | int open_terminal(const char *name, int mode) { 36 | int fd, r; 37 | unsigned c = 0; 38 | 39 | /* 40 | * If a TTY is in the process of being closed opening it might 41 | * cause EIO. This is horribly awful, but unlikely to be 42 | * changed in the kernel. Hence we work around this problem by 43 | * retrying a couple of times. 44 | * 45 | * https://bugs.launchpad.net/ubuntu/+source/linux/+bug/554172/comments/245 46 | */ 47 | 48 | if (mode & O_CREAT) 49 | return -EINVAL; 50 | 51 | for (;;) { 52 | fd = open(name, mode, 0); 53 | if (fd >= 0) 54 | break; 55 | 56 | if (errno != EIO) 57 | return -errno; 58 | 59 | /* Max 1s in total */ 60 | if (c >= 20) 61 | return -errno; 62 | 63 | usleep(50 * USEC_PER_MSEC); 64 | c++; 65 | } 66 | 67 | r = isatty(fd); 68 | if (r < 0) { 69 | safe_close(fd); 70 | return -errno; 71 | } 72 | 73 | if (!r) { 74 | safe_close(fd); 75 | return -ENOTTY; 76 | } 77 | 78 | return fd; 79 | } 80 | 81 | int release_terminal(void) { 82 | static const struct sigaction sa_new = { 83 | .sa_handler = SIG_IGN, 84 | .sa_flags = SA_RESTART, 85 | }; 86 | 87 | _cleanup_close_ int fd = -1; 88 | struct sigaction sa_old; 89 | int r = 0; 90 | 91 | fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK); 92 | if (fd < 0) 93 | return -errno; 94 | 95 | /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed 96 | * by our own TIOCNOTTY */ 97 | assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0); 98 | 99 | if (ioctl(fd, TIOCNOTTY) < 0) 100 | r = -errno; 101 | 102 | assert_se(sigaction(SIGHUP, &sa_old, NULL) == 0); 103 | 104 | return r; 105 | } 106 | -------------------------------------------------------------------------------- /src/terminal-util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /*** 4 | This file is part of systemd. 5 | 6 | Copyright 2010 Lennart Poettering 7 | 8 | systemd is free software; you can redistribute it and/or modify it 9 | under the terms of the GNU Lesser General Public License as published by 10 | the Free Software Foundation; either version 2.1 of the License, or 11 | (at your option) any later version. 12 | 13 | systemd is distributed in the hope that it will be useful, but 14 | WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public License 19 | along with systemd; If not, see . 20 | ***/ 21 | 22 | #define ANSI_RED "\x1B[0;31m" 23 | #define ANSI_GREEN "\x1B[0;32m" 24 | #define ANSI_UNDERLINE "\x1B[0;4m" 25 | #define ANSI_HIGHLIGHT "\x1B[0;1;39m" 26 | #define ANSI_HIGHLIGHT_RED "\x1B[0;1;31m" 27 | #define ANSI_HIGHLIGHT_GREEN "\x1B[0;1;32m" 28 | #define ANSI_HIGHLIGHT_YELLOW "\x1B[0;1;33m" 29 | #define ANSI_HIGHLIGHT_BLUE "\x1B[0;1;34m" 30 | #define ANSI_HIGHLIGHT_UNDERLINE "\x1B[0;1;4m" 31 | #define ANSI_NORMAL "\x1B[0m" 32 | 33 | #define ANSI_ERASE_TO_END_OF_LINE "\x1B[K" 34 | 35 | /* Set cursor to top left corner and clear screen */ 36 | #define ANSI_HOME_CLEAR "\x1B[H\x1B[2J" 37 | 38 | int open_terminal(const char *name, int mode); 39 | int release_terminal(void); 40 | 41 | int make_null_stdio(void); 42 | -------------------------------------------------------------------------------- /src/time-util.c: -------------------------------------------------------------------------------- 1 | /*** 2 | This file is part of systemd. 3 | 4 | Copyright 2010 Lennart Poettering 5 | 6 | systemd is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation; either version 2.1 of the License, or 9 | (at your option) any later version. 10 | 11 | systemd is distributed in the hope that it will be useful, but 12 | WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with systemd; If not, see . 18 | ***/ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "fd-util.h" 27 | #include "macro.h" 28 | #include "time-util.h" 29 | 30 | static clockid_t map_clock_id(clockid_t c) { 31 | 32 | /* Some more exotic archs (s390, ppc, …) lack the "ALARM" flavour of the clocks. Thus, clock_gettime() will 33 | * fail for them. Since they are essentially the same as their non-ALARM pendants (their only difference is 34 | * when timers are set on them), let's just map them accordingly. This way, we can get the correct time even on 35 | * those archs. */ 36 | 37 | switch (c) { 38 | 39 | case CLOCK_BOOTTIME_ALARM: 40 | return CLOCK_BOOTTIME; 41 | 42 | case CLOCK_REALTIME_ALARM: 43 | return CLOCK_REALTIME; 44 | 45 | default: 46 | return c; 47 | } 48 | } 49 | 50 | usec_t now(clockid_t clock_id) { 51 | struct timespec ts; 52 | 53 | assert_se(clock_gettime(map_clock_id(clock_id), &ts) == 0); 54 | 55 | return timespec_load(&ts); 56 | } 57 | 58 | usec_t timespec_load(const struct timespec *ts) { 59 | assert(ts); 60 | 61 | if (ts->tv_sec == (time_t) -1 && 62 | ts->tv_nsec == (long) -1) 63 | return USEC_INFINITY; 64 | 65 | if ((usec_t) ts->tv_sec > (UINT64_MAX - (ts->tv_nsec / NSEC_PER_USEC)) / USEC_PER_SEC) 66 | return USEC_INFINITY; 67 | 68 | return 69 | (usec_t) ts->tv_sec * USEC_PER_SEC + 70 | (usec_t) ts->tv_nsec / NSEC_PER_USEC; 71 | } 72 | 73 | struct timespec *timespec_store(struct timespec *ts, usec_t u) { 74 | assert(ts); 75 | 76 | if (u == USEC_INFINITY) { 77 | ts->tv_sec = (time_t) -1; 78 | ts->tv_nsec = (long) -1; 79 | return ts; 80 | } 81 | 82 | ts->tv_sec = (time_t) (u / USEC_PER_SEC); 83 | ts->tv_nsec = (long int) ((u % USEC_PER_SEC) * NSEC_PER_USEC); 84 | 85 | return ts; 86 | } 87 | 88 | clockid_t clock_boottime_or_monotonic(void) { 89 | static clockid_t clock = -1; 90 | int fd; 91 | 92 | if (clock != -1) 93 | return clock; 94 | 95 | fd = timerfd_create(CLOCK_BOOTTIME, TFD_NONBLOCK|TFD_CLOEXEC); 96 | if (fd < 0) 97 | clock = CLOCK_MONOTONIC; 98 | else { 99 | safe_close(fd); 100 | clock = CLOCK_BOOTTIME; 101 | } 102 | 103 | return clock; 104 | } 105 | -------------------------------------------------------------------------------- /src/time-util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /*** 4 | This file is part of systemd. 5 | 6 | Copyright 2010 Lennart Poettering 7 | 8 | systemd is free software; you can redistribute it and/or modify it 9 | under the terms of the GNU Lesser General Public License as published by 10 | the Free Software Foundation; either version 2.1 of the License, or 11 | (at your option) any later version. 12 | 13 | systemd is distributed in the hope that it will be useful, but 14 | WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public License 19 | along with systemd; If not, see . 20 | ***/ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include "attributes.h" 30 | 31 | typedef uint64_t usec_t; 32 | typedef uint64_t nsec_t; 33 | 34 | #define NSEC_FMT "%" PRIu64 35 | #define USEC_FMT "%" PRIu64 36 | 37 | #include "macro.h" 38 | 39 | typedef struct dual_timestamp { 40 | usec_t realtime; 41 | usec_t monotonic; 42 | } dual_timestamp; 43 | 44 | #define USEC_INFINITY ((usec_t) -1) 45 | #define NSEC_INFINITY ((nsec_t) -1) 46 | 47 | #define MSEC_PER_SEC 1000ULL 48 | #define USEC_PER_SEC ((usec_t) 1000000ULL) 49 | #define USEC_PER_MSEC ((usec_t) 1000ULL) 50 | #define NSEC_PER_SEC ((nsec_t) 1000000000ULL) 51 | #define NSEC_PER_MSEC ((nsec_t) 1000000ULL) 52 | #define NSEC_PER_USEC ((nsec_t) 1000ULL) 53 | 54 | #define USEC_PER_MINUTE ((usec_t) (60ULL*USEC_PER_SEC)) 55 | #define NSEC_PER_MINUTE ((nsec_t) (60ULL*NSEC_PER_SEC)) 56 | #define USEC_PER_HOUR ((usec_t) (60ULL*USEC_PER_MINUTE)) 57 | #define NSEC_PER_HOUR ((nsec_t) (60ULL*NSEC_PER_MINUTE)) 58 | #define USEC_PER_DAY ((usec_t) (24ULL*USEC_PER_HOUR)) 59 | #define NSEC_PER_DAY ((nsec_t) (24ULL*NSEC_PER_HOUR)) 60 | #define USEC_PER_WEEK ((usec_t) (7ULL*USEC_PER_DAY)) 61 | #define NSEC_PER_WEEK ((nsec_t) (7ULL*NSEC_PER_DAY)) 62 | #define USEC_PER_MONTH ((usec_t) (2629800ULL*USEC_PER_SEC)) 63 | #define NSEC_PER_MONTH ((nsec_t) (2629800ULL*NSEC_PER_SEC)) 64 | #define USEC_PER_YEAR ((usec_t) (31557600ULL*USEC_PER_SEC)) 65 | #define NSEC_PER_YEAR ((nsec_t) (31557600ULL*NSEC_PER_SEC)) 66 | 67 | #define TIME_T_MAX (time_t)((UINTMAX_C(1) << ((sizeof(time_t) << 3) - 1)) - 1) 68 | 69 | #define DUAL_TIMESTAMP_NULL ((struct dual_timestamp) { 0ULL, 0ULL }) 70 | 71 | usec_t now(clockid_t clock); 72 | 73 | static inline bool dual_timestamp_is_set(dual_timestamp *ts) { 74 | return ((ts->realtime > 0 && ts->realtime != USEC_INFINITY) || 75 | (ts->monotonic > 0 && ts->monotonic != USEC_INFINITY)); 76 | } 77 | 78 | usec_t timespec_load(const struct timespec *ts) _pure_; 79 | struct timespec *timespec_store(struct timespec *ts, usec_t u); 80 | 81 | clockid_t clock_boottime_or_monotonic(void); 82 | 83 | #define xstrftime(buf, fmt, tm) \ 84 | assert_message_se(strftime(buf, ELEMENTSOF(buf), fmt, tm) > 0, \ 85 | "xstrftime: " #buf "[] must be big enough") 86 | 87 | static inline usec_t usec_add(usec_t a, usec_t b) { 88 | usec_t c; 89 | 90 | /* Adds two time values, and makes sure USEC_INFINITY as input results as USEC_INFINITY in output, and doesn't 91 | * overflow. */ 92 | 93 | c = a + b; 94 | if (c < a || c < b) /* overflow check */ 95 | return USEC_INFINITY; 96 | 97 | return c; 98 | } 99 | 100 | static inline usec_t usec_sub(usec_t timestamp, int64_t delta) { 101 | if (delta < 0) 102 | return usec_add(timestamp, (usec_t) (-delta)); 103 | 104 | if (timestamp == USEC_INFINITY) /* Make sure infinity doesn't degrade */ 105 | return USEC_INFINITY; 106 | 107 | if (timestamp < (usec_t) delta) 108 | return 0; 109 | 110 | return timestamp - delta; 111 | } 112 | -------------------------------------------------------------------------------- /src/unaligned.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /*** 4 | This file is part of systemd. 5 | 6 | Copyright 2014 Tom Gundersen 7 | 8 | systemd is free software; you can redistribute it and/or modify it 9 | under the terms of the GNU Lesser General Public License as published by 10 | the Free Software Foundation; either version 2.1 of the License, or 11 | (at your option) any later version. 12 | 13 | systemd is distributed in the hope that it will be useful, but 14 | WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public License 19 | along with systemd; If not, see . 20 | ***/ 21 | 22 | #include 23 | #include 24 | 25 | /* BE */ 26 | 27 | static inline uint16_t unaligned_read_be16(const void *_u) { 28 | const uint8_t *u = _u; 29 | 30 | return (((uint16_t) u[0]) << 8) | 31 | ((uint16_t) u[1]); 32 | } 33 | 34 | static inline uint32_t unaligned_read_be32(const void *_u) { 35 | const uint8_t *u = _u; 36 | 37 | return (((uint32_t) unaligned_read_be16(u)) << 16) | 38 | ((uint32_t) unaligned_read_be16(u + 2)); 39 | } 40 | 41 | static inline uint64_t unaligned_read_be64(const void *_u) { 42 | const uint8_t *u = _u; 43 | 44 | return (((uint64_t) unaligned_read_be32(u)) << 32) | 45 | ((uint64_t) unaligned_read_be32(u + 4)); 46 | } 47 | 48 | static inline void unaligned_write_be16(void *_u, uint16_t a) { 49 | uint8_t *u = _u; 50 | 51 | u[0] = (uint8_t) (a >> 8); 52 | u[1] = (uint8_t) a; 53 | } 54 | 55 | static inline void unaligned_write_be32(void *_u, uint32_t a) { 56 | uint8_t *u = _u; 57 | 58 | unaligned_write_be16(u, (uint16_t) (a >> 16)); 59 | unaligned_write_be16(u + 2, (uint16_t) a); 60 | } 61 | 62 | static inline void unaligned_write_be64(void *_u, uint64_t a) { 63 | uint8_t *u = _u; 64 | 65 | unaligned_write_be32(u, (uint32_t) (a >> 32)); 66 | unaligned_write_be32(u + 4, (uint32_t) a); 67 | } 68 | 69 | /* LE */ 70 | 71 | static inline uint16_t unaligned_read_le16(const void *_u) { 72 | const uint8_t *u = _u; 73 | 74 | return (((uint16_t) u[1]) << 8) | 75 | ((uint16_t) u[0]); 76 | } 77 | 78 | static inline uint32_t unaligned_read_le32(const void *_u) { 79 | const uint8_t *u = _u; 80 | 81 | return (((uint32_t) unaligned_read_le16(u + 2)) << 16) | 82 | ((uint32_t) unaligned_read_le16(u)); 83 | } 84 | 85 | static inline uint64_t unaligned_read_le64(const void *_u) { 86 | const uint8_t *u = _u; 87 | 88 | return (((uint64_t) unaligned_read_le32(u + 4)) << 32) | 89 | ((uint64_t) unaligned_read_le32(u)); 90 | } 91 | 92 | static inline void unaligned_write_le16(void *_u, uint16_t a) { 93 | uint8_t *u = _u; 94 | 95 | u[0] = (uint8_t) a; 96 | u[1] = (uint8_t) (a >> 8); 97 | } 98 | 99 | static inline void unaligned_write_le32(void *_u, uint32_t a) { 100 | uint8_t *u = _u; 101 | 102 | unaligned_write_le16(u, (uint16_t) a); 103 | unaligned_write_le16(u + 2, (uint16_t) (a >> 16)); 104 | } 105 | 106 | static inline void unaligned_write_le64(void *_u, uint64_t a) { 107 | uint8_t *u = _u; 108 | 109 | unaligned_write_le32(u, (uint32_t) a); 110 | unaligned_write_le32(u + 4, (uint32_t) (a >> 32)); 111 | } 112 | -------------------------------------------------------------------------------- /src/utf8.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /*** 4 | This file is part of systemd. 5 | 6 | Copyright 2012 Lennart Poettering 7 | 8 | systemd is free software; you can redistribute it and/or modify it 9 | under the terms of the GNU Lesser General Public License as published by 10 | the Free Software Foundation; either version 2.1 of the License, or 11 | (at your option) any later version. 12 | 13 | systemd is distributed in the hope that it will be useful, but 14 | WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public License 19 | along with systemd; If not, see . 20 | ***/ 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include "attributes.h" 27 | 28 | #define UTF8_REPLACEMENT_CHARACTER "\xef\xbf\xbd" 29 | 30 | bool unichar_is_valid(char32_t c); 31 | 32 | const char *utf8_is_valid(const char *s) _pure_; 33 | 34 | bool utf8_is_printable_newline(const char* str, size_t length, bool newline) _pure_; 35 | #define utf8_is_printable(str, length) utf8_is_printable_newline(str, length, true) 36 | 37 | char *utf8_escape_invalid(const char *s); 38 | char *utf8_escape_non_printable(const char *str); 39 | 40 | int utf8_encoded_valid_unichar(const char *str); 41 | int utf8_encoded_to_unichar(const char *str, char32_t *ret_unichar); 42 | 43 | static inline bool utf16_is_surrogate(char16_t c) { 44 | return (0xd800 <= c && c <= 0xdfff); 45 | } 46 | 47 | static inline bool utf16_is_trailing_surrogate(char16_t c) { 48 | return (0xdc00 <= c && c <= 0xdfff); 49 | } 50 | 51 | static inline char32_t utf16_surrogate_pair_to_unichar(char16_t lead, char16_t trail) { 52 | return ((lead - 0xd800) << 10) + (trail - 0xdc00) + 0x10000; 53 | } 54 | -------------------------------------------------------------------------------- /src/util.c: -------------------------------------------------------------------------------- 1 | /*** 2 | This file is part of systemd. 3 | 4 | Copyright 2010 Lennart Poettering 5 | 6 | systemd is free software; you can redistribute it and/or modify it 7 | under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation; either version 2.1 of the License, or 9 | (at your option) any later version. 10 | 11 | systemd is distributed in the hope that it will be useful, but 12 | WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with systemd; If not, see . 18 | ***/ 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include "build.h" 25 | #include "macro.h" 26 | #include "util.h" 27 | 28 | /* Put this test here for a lack of better place */ 29 | assert_cc(EAGAIN == EWOULDBLOCK); 30 | 31 | int saved_argc = 0; 32 | char **saved_argv = NULL; 33 | 34 | size_t page_size(void) { 35 | static thread_local size_t pgsz = 0; 36 | long r; 37 | 38 | if (_likely_(pgsz > 0)) 39 | return pgsz; 40 | 41 | r = sysconf(_SC_PAGESIZE); 42 | assert(r > 0); 43 | 44 | pgsz = (size_t) r; 45 | return pgsz; 46 | } 47 | 48 | int version(void) { 49 | puts(PACKAGE_STRING "\n" 50 | SYSTEMD_FEATURES); 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /src/util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /*** 4 | This file is part of systemd. 5 | 6 | Copyright 2010 Lennart Poettering 7 | 8 | systemd is free software; you can redistribute it and/or modify it 9 | under the terms of the GNU Lesser General Public License as published by 10 | the Free Software Foundation; either version 2.1 of the License, or 11 | (at your option) any later version. 12 | 13 | systemd is distributed in the hope that it will be useful, but 14 | WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public License 19 | along with systemd; If not, see . 20 | ***/ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include "attributes.h" 30 | #include "macro.h" 31 | 32 | size_t page_size(void) _pure_; 33 | #define PAGE_ALIGN(l) ALIGN_TO((l), page_size()) 34 | 35 | static inline const char* yes_no(bool b) { 36 | return b ? "yes" : "no"; 37 | } 38 | 39 | static inline const char* true_false(bool b) { 40 | return b ? "true" : "false"; 41 | } 42 | 43 | static inline const char* one_zero(bool b) { 44 | return b ? "1" : "0"; 45 | } 46 | 47 | #define NULSTR_FOREACH(i, l) \ 48 | for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1) 49 | 50 | #define NULSTR_FOREACH_PAIR(i, j, l) \ 51 | for ((i) = (l), (j) = strchr((i), 0)+1; (i) && *(i); (i) = strchr((j), 0)+1, (j) = *(i) ? strchr((i), 0)+1 : (i)) 52 | 53 | extern int saved_argc; 54 | extern char **saved_argv; 55 | 56 | /** 57 | * Normal qsort requires base to be nonnull. Here were require 58 | * that only if nmemb > 0. 59 | */ 60 | static inline void qsort_safe(void *base, size_t nmemb, size_t size, comparison_fn_t compar) { 61 | if (nmemb <= 1) 62 | return; 63 | 64 | assert(base); 65 | qsort(base, nmemb, size, compar); 66 | } 67 | 68 | /** 69 | * Normal memcpy requires src to be nonnull. We do nothing if n is 0. 70 | */ 71 | static inline void memcpy_safe(void *dst, const void *src, size_t n) { 72 | if (n == 0) 73 | return; 74 | assert(src); 75 | memcpy(dst, src, n); 76 | } 77 | 78 | #define memzero(x,l) (memset((x), 0, (l))) 79 | #define zero(x) (memzero(&(x), sizeof(x))) 80 | 81 | static inline void *mempset(void *s, int c, size_t n) { 82 | memset(s, c, n); 83 | return (uint8_t*)s + n; 84 | } 85 | 86 | static inline void _reset_errno_(int *saved_errno) { 87 | errno = *saved_errno; 88 | } 89 | 90 | #define PROTECT_ERRNO _cleanup_(_reset_errno_) __attribute__((unused)) int _saved_errno_ = errno 91 | 92 | static inline int negative_errno(void) { 93 | /* This helper should be used to shut up gcc if you know 'errno' is 94 | * negative. Instead of "return -errno;", use "return negative_errno();" 95 | * It will suppress bogus gcc warnings in case it assumes 'errno' might 96 | * be 0 and thus the caller's error-handling might not be triggered. */ 97 | assert_return(errno > 0, -EINVAL); 98 | return -errno; 99 | } 100 | 101 | static inline unsigned u64log2(uint64_t n) { 102 | #if __SIZEOF_LONG_LONG__ == 8 103 | return (n > 1) ? (unsigned) __builtin_clzll(n) ^ 63U : 0; 104 | #else 105 | #error "Wut?" 106 | #endif 107 | } 108 | 109 | static inline unsigned u32ctz(uint32_t n) { 110 | #if __SIZEOF_INT__ == 4 111 | return __builtin_ctz(n); 112 | #else 113 | #error "Wut?" 114 | #endif 115 | } 116 | 117 | static inline unsigned log2i(int x) { 118 | assert(x > 0); 119 | 120 | return __SIZEOF_INT__ * 8 - __builtin_clz(x) - 1; 121 | } 122 | 123 | static inline unsigned log2u(unsigned x) { 124 | assert(x > 0); 125 | 126 | return sizeof(unsigned) * 8 - __builtin_clz(x) - 1; 127 | } 128 | 129 | static inline unsigned log2u_round_up(unsigned x) { 130 | assert(x > 0); 131 | 132 | if (x == 1) 133 | return 0; 134 | 135 | return log2u(x - 1) + 1; 136 | } 137 | 138 | int version(void); 139 | -------------------------------------------------------------------------------- /tests/run: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | d= 3 | cleanup() { 4 | if [ -n "$d" ]; then 5 | d= 6 | rm -rf "$d" 7 | fi 8 | } 9 | trap cleanup EXIT 10 | d=`mktemp -d` 11 | 12 | test_runs=0 13 | test_failures=0 14 | 15 | t() { 16 | "$@" 17 | local r=$? 18 | : $((test_runs=test_runs+1)) 19 | if [ $r -ne 0 ]; then 20 | : $((test_failures=test_failures+1)) 21 | echo "not ok $test_runs - $*" 22 | fi 23 | } 24 | 25 | echo 1..3 26 | t ./systemd-bootchart -o "$d" -n 2 -r 27 | t ./systemd-bootchart -o "$d" -n 10 -r 28 | t ./systemd-bootchart -o "$d" -n 10 -r -p 29 | 30 | if [ $test_failures -ne 0 ]; then 31 | echo "# Failed $test_failures out of $test_runs tests" 32 | exit 1 33 | fi 34 | -------------------------------------------------------------------------------- /units/.gitignore: -------------------------------------------------------------------------------- 1 | /systemd-bootchart.service 2 | -------------------------------------------------------------------------------- /units/systemd-bootchart.service.in: -------------------------------------------------------------------------------- 1 | # This file is part of systemd. 2 | # 3 | # systemd is free software; you can redistribute it and/or modify it 4 | # under the terms of the GNU Lesser General Public License as published by 5 | # the Free Software Foundation; either version 2.1 of the License, or 6 | # (at your option) any later version. 7 | 8 | # Note: it's usually a better idea to run systemd-bootchart via the 9 | # init= kernel command line switch. See the man page for details. 10 | 11 | [Unit] 12 | Description=Boot Process Profiler 13 | Documentation=man:systemd-bootchart(1) man:bootchart.conf(5) 14 | DefaultDependencies=no 15 | 16 | [Service] 17 | ExecStart=@rootlibexecdir@/systemd-bootchart -r 18 | 19 | [Install] 20 | WantedBy=sysinit.target 21 | --------------------------------------------------------------------------------