diff options
578 files changed, 9882 insertions, 6159 deletions
diff --git a/.gitignore b/.gitignore index 0a32bae7a8..7abe8e7dae 100644 --- a/.gitignore +++ b/.gitignore @@ -20,12 +20,12 @@ /*.tar.bz2 /*.tar.gz /*.tar.xz -/Makefile -/TAGS /GPATH /GRTAGS /GSYMS /GTAGS +/Makefile +/TAGS /ata_id /bootctl /build-aux @@ -42,14 +42,12 @@ /journalctl /libsystemd-*.c /libtool +/linuxx64.efi.stub /localectl /loginctl /machinectl /mtd_probe /networkctl -/linuxx64.efi.stub -/systemd-bootx64.efi -/test-efi-disk.img /scsi_id /systemadm /systemctl @@ -61,6 +59,7 @@ /systemd-backlight /systemd-binfmt /systemd-bootchart +/systemd-bootx64.efi /systemd-bus-proxyd /systemd-cat /systemd-cgls @@ -135,11 +134,11 @@ /systemd-vconsole-setup /tags /test-acd -/test-architecture -/test-audit-type /test-af-list +/test-architecture /test-arphrd-list /test-async +/test-audit-type /test-barrier /test-bitmap /test-boot-timestamp @@ -183,19 +182,20 @@ /test-dhcp-server /test-dhcp6-client /test-dns-domain +/test-efi-disk.img /test-ellipsize /test-engine /test-env-replace /test-event /test-execute +/test-extract-word /test-fdset /test-fileio -/test-fstab-util /test-firewall-util +/test-fstab-util /test-hashmap /test-hostname /test-hostname-util -/test-ndisc-rs /test-id128 /test-inhibit /test-install @@ -229,9 +229,13 @@ /test-machine-tables /test-mmap-cache /test-namespace +/test-ndisc-rs +/test-netlink +/test-netlink-manual /test-network /test-network-tables /test-ns +/test-parse-util /test-path /test-path-lookup /test-path-util @@ -244,8 +248,6 @@ /test-replace-var /test-resolve /test-ring -/test-netlink -/test-netlink-manual /test-sched-prio /test-set /test-sigbus diff --git a/Makefile.am b/Makefile.am index 2e960623a5..be001bd09e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -762,10 +762,11 @@ noinst_LTLIBRARIES += \ libbasic_la_SOURCES = \ src/basic/missing.h \ - src/basic/capability.c \ - src/basic/capability.h \ + src/basic/capability-util.c \ + src/basic/capability-util.h \ src/basic/conf-files.c \ src/basic/conf-files.h \ + src/basic/stdio-util.h \ src/basic/hostname-util.h \ src/basic/hostname-util.c \ src/basic/unit-name.c \ @@ -787,8 +788,32 @@ libbasic_la_SOURCES = \ src/basic/string-util.h \ src/basic/fd-util.c \ src/basic/fd-util.h \ + src/basic/parse-util.c \ + src/basic/parse-util.h \ src/basic/user-util.c \ src/basic/user-util.h \ + src/basic/rlimit-util.c \ + src/basic/rlimit-util.h \ + src/basic/dirent-util.c \ + src/basic/dirent-util.h \ + src/basic/xattr-util.c \ + src/basic/xattr-util.h \ + src/basic/chattr-util.c \ + src/basic/chattr-util.h \ + src/basic/proc-cmdline.c \ + src/basic/proc-cmdline.h \ + src/basic/fs-util.c \ + src/basic/fs-util.h \ + src/basic/syslog-util.c \ + src/basic/syslog-util.h \ + src/basic/stat-util.c \ + src/basic/stat-util.h \ + src/basic/mount-util.c \ + src/basic/mount-util.h \ + src/basic/hexdecoct.c \ + src/basic/hexdecoct.h \ + src/basic/glob-util.h \ + src/basic/glob-util.c \ src/basic/extract-word.c \ src/basic/extract-word.h \ src/basic/escape.c \ @@ -803,8 +828,11 @@ libbasic_la_SOURCES = \ src/basic/time-util.h \ src/basic/locale-util.c \ src/basic/locale-util.h \ + src/basic/umask-util.h \ src/basic/signal-util.c \ src/basic/signal-util.h \ + src/basic/string-table.c \ + src/basic/string-table.h \ src/basic/mempool.c \ src/basic/mempool.h \ src/basic/hashmap.c \ @@ -819,6 +847,8 @@ libbasic_la_SOURCES = \ src/basic/fdset.h \ src/basic/prioq.c \ src/basic/prioq.h \ + src/basic/web-util.c \ + src/basic/web-util.h \ src/basic/strv.c \ src/basic/strv.h \ src/basic/env-util.c \ @@ -877,8 +907,8 @@ libbasic_la_SOURCES = \ src/basic/login-util.c \ src/basic/cap-list.c \ src/basic/cap-list.h \ - src/basic/audit.c \ - src/basic/audit.h \ + src/basic/audit-util.c \ + src/basic/audit-util.h \ src/basic/xml.c \ src/basic/xml.h \ src/basic/json.c \ @@ -913,6 +943,8 @@ libbasic_la_SOURCES = \ src/basic/rm-rf.h \ src/basic/copy.c \ src/basic/copy.h \ + src/basic/alloc-util.h \ + src/basic/alloc-util.c \ src/basic/formats-util.h nodist_libbasic_la_SOURCES = \ @@ -1415,6 +1447,8 @@ tests += \ test-utf8 \ test-ellipsize \ test-util \ + test-extract-word \ + test-parse-util \ test-user-util \ test-hostname-util \ test-process-util \ @@ -1481,7 +1515,6 @@ EXTRA_DIST += \ test/h.service \ test/parent-deep.slice \ test/parent.slice \ - test/paths.target \ test/sched_idle_bad.service \ test/sched_idle_ok.service \ test/sched_rr_bad.service \ @@ -1495,43 +1528,58 @@ EXTRA_DIST += \ test/testsuite.target \ test/timers.target \ test/unstoppable.service \ - test/path-changed.service \ - test/path-directorynotempty.service \ - test/path-existsglob.service \ - test/path-exists.service \ - test/path-makedirectory.service \ - test/path-modified.service \ - test/path-mycustomunit.service \ - test/path-service.service \ - test/path-changed.path \ - test/path-directorynotempty.path \ - test/path-existsglob.path \ - test/path-exists.path \ - test/path-makedirectory.path \ - test/path-modified.path \ - test/path-unit.path \ - test/exec-environment-empty.service \ - test/exec-environment-multiple.service \ - test/exec-environment.service \ - test/exec-group.service \ - test/exec-ignoresigpipe-no.service \ - test/exec-ignoresigpipe-yes.service \ - test/exec-personality-x86-64.service \ - test/exec-personality-x86.service \ - test/exec-personality-s390.service \ - test/exec-privatedevices-no.service \ - test/exec-privatedevices-yes.service \ - test/exec-privatetmp-no.service \ - test/exec-privatetmp-yes.service \ - test/exec-systemcallerrornumber.service \ - test/exec-systemcallfilter-failing2.service \ - test/exec-systemcallfilter-failing.service \ - test/exec-systemcallfilter-not-failing2.service \ - test/exec-systemcallfilter-not-failing.service \ - test/exec-user.service \ - test/exec-workingdirectory.service \ - test/exec-umask-0177.service \ - test/exec-umask-default.service \ + test/test-path/paths.target \ + test/test-path/basic.target \ + test/test-path/sysinit.target \ + test/test-path/path-changed.service \ + test/test-path/path-directorynotempty.service \ + test/test-path/path-existsglob.service \ + test/test-path/path-exists.service \ + test/test-path/path-makedirectory.service \ + test/test-path/path-modified.service \ + test/test-path/path-mycustomunit.service \ + test/test-path/path-service.service \ + test/test-path/path-changed.path \ + test/test-path/path-directorynotempty.path \ + test/test-path/path-existsglob.path \ + test/test-path/path-exists.path \ + test/test-path/path-makedirectory.path \ + test/test-path/path-modified.path \ + test/test-path/path-unit.path \ + test/test-execute/exec-environment-empty.service \ + test/test-execute/exec-environment-multiple.service \ + test/test-execute/exec-environment.service \ + test/test-execute/exec-group.service \ + test/test-execute/exec-ignoresigpipe-no.service \ + test/test-execute/exec-ignoresigpipe-yes.service \ + test/test-execute/exec-personality-x86-64.service \ + test/test-execute/exec-personality-x86.service \ + test/test-execute/exec-personality-s390.service \ + test/test-execute/exec-privatedevices-no.service \ + test/test-execute/exec-privatedevices-yes.service \ + test/test-execute/exec-privatetmp-no.service \ + test/test-execute/exec-privatetmp-yes.service \ + test/test-execute/exec-systemcallerrornumber.service \ + test/test-execute/exec-systemcallfilter-failing2.service \ + test/test-execute/exec-systemcallfilter-failing.service \ + test/test-execute/exec-systemcallfilter-not-failing2.service \ + test/test-execute/exec-systemcallfilter-not-failing.service \ + test/test-execute/exec-user.service \ + test/test-execute/exec-workingdirectory.service \ + test/test-execute/exec-umask-0177.service \ + test/test-execute/exec-umask-default.service \ + test/test-execute/exec-privatenetwork-yes.service \ + test/test-execute/exec-environmentfile.service \ + test/test-execute/exec-oomscoreadjust-positive.service \ + test/test-execute/exec-oomscoreadjust-negative.service \ + test/test-execute/exec-ioschedulingclass-best-effort.service \ + test/test-execute/exec-ioschedulingclass-idle.service \ + test/test-execute/exec-ioschedulingclass-none.service \ + test/test-execute/exec-ioschedulingclass-realtime.service \ + test/test-execute/exec-capabilityboundingset-invert.service \ + test/test-execute/exec-capabilityboundingset-merge.service \ + test/test-execute/exec-capabilityboundingset-reset.service \ + test/test-execute/exec-capabilityboundingset-simple.service \ test/bus-policy/hello.conf \ test/bus-policy/methods.conf \ test/bus-policy/ownerships.conf \ @@ -1700,6 +1748,18 @@ test_util_SOURCES = \ test_util_LDADD = \ libshared.la +test_extract_word_SOURCES = \ + src/test/test-extract-word.c + +test_extract_word_LDADD = \ + libshared.la + +test_parse_util_SOURCES = \ + src/test/test-parse-util.c + +test_parse_util_LDADD = \ + libshared.la + test_user_util_SOURCES = \ src/test/test-user-util.c @@ -4202,6 +4262,7 @@ dist_catalog_DATA = \ catalog/systemd.pl.catalog \ catalog/systemd.pt_BR.catalog \ catalog/systemd.ru.catalog \ + catalog/systemd.zh_CN.catalog \ catalog/systemd.zh_TW.catalog \ catalog/systemd.catalog @@ -24,6 +24,16 @@ External: * When lz4 gets an API for lz4 command output, make use of it to compress coredumps in a way compatible with /usr/bin/lz4. +Janitorial Clean-ups: + +* code cleanup: retire FOREACH_WORD_QUOTED, port to extract_first_word() loops instead + +* replace manual readdir() loops with FOREACH_DIRENT or FOREACH_DIRENT_ALL + +* Get rid of the last strerror() invocations in favour of %m and strerror_r() + +* Rearrange tests so that the various test-xyz.c match a specific src/basic/xyz.c again + Features: * do something about "/control" subcgroups in the unified cgroup hierarchy @@ -221,8 +231,6 @@ Features: * Find a solution for SMACK capabilities stuff: http://lists.freedesktop.org/archives/systemd-devel/2014-December/026188.html -* port libmount hookup to use API's own inotify interface, as soon as that is table in libmount - * "systemctl preset-all" should probably order the unit files it operates on lexicographically before starting to work, in order to ensure deterministic behaviour if two unit files conflict (like DMs @@ -264,8 +272,6 @@ Features: * maybe add support for specifier expansion in user.conf, specifically DefaultEnvironment= -* code cleanup: retire FOREACH_WORD_QUOTED, port to extract_first_word() loops instead - * introduce systemd-timesync-wait.service or so to sync on an NTP fix? * systemd --user should issue sd_notify() upon reaching basic.target, not on becoming idle @@ -553,9 +559,6 @@ Features: * maybe do not install getty@tty1.service symlink in /etc but in /usr? -* fstab: add new mount option x-systemd-after=/foobar/waldo to allow manual dependencies to other mount points - https://bugzilla.redhat.com/show_bug.cgi?id=812826 - * print a nicer explanation if people use variable/specifier expansion in ExecStart= for the first word * mount: turn dependency information from /proc/self/mountinfo into dependency information between systemd units. diff --git a/catalog/systemd.zh_CN.catalog b/catalog/systemd.zh_CN.catalog new file mode 100644 index 0000000000..38639109e4 --- /dev/null +++ b/catalog/systemd.zh_CN.catalog @@ -0,0 +1,253 @@ +# This file is part of systemd. +# +# Copyright 2012 Lennart Poettering +# Copyright 2015 Boyuan Yang +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see <http://www.gnu.org/licenses/>. + +# Message catalog for systemd's own messages +# Simplified Chinese translation + +# 本 catalog 文档格式被记载在 +# http://www.freedesktop.org/wiki/Software/systemd/catalog + +# 如需了解我们为什么做这些工作,请见 https://xkcd.com/1024/ + +-- f77379a8490b408bbe5f6940505a777b +Subject: 日志已开始 +Defined-By: systemd +Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel + +系统日志进程已启动,已打开供写入的日志文件并准备好处理请求。 + +-- d93fb3c9c24d451a97cea615ce59c00b +Subject: 日志已停止 +Defined-By: systemd +Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel + +系统日志进程已终止,并已关闭所有当前活动的日志文件。 + +-- a596d6fe7bfa4994828e72309e95d61e +Subject: 由某个服务而来的消息已被抑制 +Defined-By: systemd +Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel +Documentation: man:journald.conf(5) + +某个服务在一个时间周期内记录了太多消息。 +从该服务而来的消息已被丢弃。 + +请注意只有由有问题的服务传来的消息被丢弃, +其它服务的消息不受影响。 + +可以在 /etc/systemd/journald.conf 中设定 RateLimitInterval= +以及 RateLimitBurst = 的值以控制丢弃信息的限制。 +请参见 journald.conf(5) 以了解详情。 + +-- e9bf28e6e834481bb6f48f548ad13606 +Subject: 日志消息已遗失 +Defined-By: systemd +Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel + +因日志系统对内核消息的处理速度不够快, +部分信息已经遗失。 + +-- fc2e22bc6ee647b6b90729ab34a250b1 +Subject: 进程 @COREDUMP_PID@ (@COREDUMP_COMM@) 核心已转储 +Defined-By: systemd +Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel +Documentation: man:core(5) + +进程 @COREDUMP_PID@ (@COREDUMP_COMM@) 已崩溃并进行核心转储。 + +这通常意味着崩溃程序中存在编程错误,并应当将此错误向其开发者报告。 + +-- 8d45620c1a4348dbb17410da57c60c66 +Subject: 一个新会话 @SESSION_ID@ 已为用户 @USER_ID@ 建立 +Defined-By: systemd +Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel +Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat + +一个 ID 为 @SESSION_ID@ 的新会话已为用户 @USER_ID@ 建立。 + +该会话的首进程为 @LEADER@。 + +-- 3354939424b4456d9802ca8333ed424a +Subject: 会话 @SESSION_ID@ 已终止 +Defined-By: systemd +Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel +Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat + +一个 ID 为 @SESSION_ID@ 的会话已终止。 + +-- fcbefc5da23d428093f97c82a9290f7b +Subject: 一个新的座位 @SEAT_ID@ 可用 +Defined-By: systemd +Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel +Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat + +一个新的座位 @SEAT_ID@ 已被配置并已可用。 + +-- e7852bfe46784ed0accde04bc864c2d5 +Subject: 座位 @SEAT_ID@ 已被移除 +Defined-By: systemd +Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel +Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat + +座位 @SEAT_ID@ 已被移除并不再可用。 + +-- c7a787079b354eaaa9e77b371893cd27 +Subject: 时间已变更 +Defined-By: systemd +Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel + +系统时钟已变更为1970年1月1日后 @REALTIME@ 微秒。 + +-- 45f82f4aef7a4bbf942ce861d1f20990 +Subject: 时区变更为 @TIMEZONE@ +Defined-By: systemd +Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel + +系统时区已变更为 @TIMEZONE@。 + +-- b07a249cd024414a82dd00cd181378ff +Subject: 系统启动已完成 +Defined-By: systemd +Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel + +所有系统启动时需要的系统服务均已成功启动。 +请注意这并不代表现在机器已经空闲,因为某些服务可能仍处于完成启动的过程中。 + +内核启动使用了 @KERNEL_USEC@ 毫秒。 + +初始内存盘启动使用了 @INITRD_USEC@ 毫秒。 + +用户空间启动使用了 @USERSPACE_USEC@ 毫秒。 + +-- 6bbd95ee977941e497c48be27c254128 +Subject: 系统已进入 @SLEEP@ 睡眠状态 +Defined-By: systemd +Support: http://lists.freedesktop.org/mailman/listinfo/systemd-deve + +系统现已进入 @SLEEP@ 睡眠状态。 + +-- 8811e6df2a8e40f58a94cea26f8ebf14 +Subject: 系统已离开 @SLEEP@ 睡眠状态 +Defined-By: systemd +Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel + +系统现已离开 @SLEEP@ 睡眠状态。 + +-- 98268866d1d54a499c4e98921d93bc40 +Subject: 系统关机已开始 +Defined-By: systemd +Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel + +系统关机操作已初始化。 +关机已开始,所有系统服务均已结束,所有文件系统已卸载。 + +-- 7d4958e842da4a758f6c1cdc7b36dcc5 +Subject: @UNIT@ 单元已开始启动 +Defined-By: systemd +Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel + +@UNIT@ 单元已开始启动。 + +-- 39f53479d3a045ac8e11786248231fbf +Subject: @UNIT@ 单元已结束启动 +Defined-By: systemd +Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel + +@UNIT@ 单元已结束启动。 + +启动结果为“@RESULT@”。 + +-- de5b426a63be47a7b6ac3eaac82e2f6f +Subject: @UNIT@ 单元已开始停止操作 +Defined-By: systemd +Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel + +@UNIT@ 单元已开始停止操作。 + +-- 9d1aaa27d60140bd96365438aad20286 +Subject: @UNIT@ 单元已结束停止操作 +Defined-By: systemd +Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel + +@UNIT@ 单元已结束停止操作。 + +-- be02cf6855d2428ba40df7e9d022f03d +Subject: @UNIT@ 单元已失败 +Defined-By: systemd +Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel + +@UNIT@ 单元已失败。 + +结果为“@RESULT@”。 + +-- d34d037fff1847e6ae669a370e694725 +Subject: @UNIT@ 单元已开始重新载入其配置 +Defined-By: systemd +Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel + +@UNIT@ 单元已开始重新载入其配置。 + +-- 7b05ebc668384222baa8881179cfda54 +Subject: @UNIT@ 单元已结束配置重载入 +Defined-By: systemd +Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel + +@UNIT@ 单元已结束配置重载入操作。 + +结果为“@RESULT@”。 + +-- 641257651c1b4ec9a8624d7a40a9e1e7 +Subject: 进程 @EXECUTABLE@ 无法执行 +Defined-By: systemd +Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel + +进程 @EXECUTABLE@ 无法被执行并已失败。 + +该进程返回的错误代码为 @ERRNO@。 + +-- 0027229ca0644181a76c4e92458afa2e +Subject: 一个或更多消息无法被转发至 syslog +Defined-By: systemd +Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel + +有一条或更多的消息无法被转发至与 journald 同时运行的 syslog 服务。 +这通常意味着 syslog 实现无法跟上队列中消息进入的速度。 + +-- 1dee0369c7fc4736b7099b38ecb46ee7 +Subject: 挂载点不为空 +Defined-By: systemd +Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel + +目录 @WHERE@ 被指定为挂载点(即 /etc/fstab 文件的第二栏,或 systemd 单元 +文件的 Where= 字段),且该目录非空。 +这并不会影响挂载行为,但该目录中先前已存在的文件将无法被访问。 +如需查看这些文件,请手动将其下的文件系统挂载到另一个位置。 + +-- 24d8d4452573402496068381a6312df2 +Subject: 一个虚拟机或容器已启动 +Defined-By: systemd +Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel + +虚拟机 @NAME@,以及其首进程 PID @LEADER@,已被启动并可被使用。 + +-- 58432bd3bace477cb514b56381b8a758 +Subject: 一个虚拟机或容器已被终止 +Defined-By: systemd +Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel + +虚拟机 @NAME@,以及其首进程 PID @LEADER@,已被关闭并停止。 diff --git a/hwdb/20-bluetooth-vendor-product.hwdb b/hwdb/20-bluetooth-vendor-product.hwdb index 1dd642678d..a825e744e1 100644 --- a/hwdb/20-bluetooth-vendor-product.hwdb +++ b/hwdb/20-bluetooth-vendor-product.hwdb @@ -1982,3 +1982,87 @@ bluetooth:v0291* bluetooth:v0292* ID_VENDOR_FROM_DATABASE=SwiftSensors + +bluetooth:v0293* + ID_VENDOR_FROM_DATABASE=Blue Bite + +bluetooth:v0294* + ID_VENDOR_FROM_DATABASE=ELIAS GmbH + +bluetooth:v0295* + ID_VENDOR_FROM_DATABASE=Sivantos GmbH + +bluetooth:v0296* + ID_VENDOR_FROM_DATABASE=Petzl + +bluetooth:v0297* + ID_VENDOR_FROM_DATABASE=storm power ltd + +bluetooth:v0298* + ID_VENDOR_FROM_DATABASE=EISST Ltd + +bluetooth:v0299* + ID_VENDOR_FROM_DATABASE=Inexess Technology Simma KG + +bluetooth:v029A* + ID_VENDOR_FROM_DATABASE=Currant, Inc. + +bluetooth:v029B* + ID_VENDOR_FROM_DATABASE=C2 Development, Inc. + +bluetooth:v029C* + ID_VENDOR_FROM_DATABASE=Blue Sky Scientific, LLC + +bluetooth:v029D* + ID_VENDOR_FROM_DATABASE=ALOTTAZS LABS, LLC + +bluetooth:v029E* + ID_VENDOR_FROM_DATABASE=Kupson spol. s r.o. + +bluetooth:v029F* + ID_VENDOR_FROM_DATABASE=Areus Engineering GmbH + +bluetooth:v02A0* + ID_VENDOR_FROM_DATABASE=Impossible Camera GmbH + +bluetooth:v02A1* + ID_VENDOR_FROM_DATABASE=InventureTrack Systems + +bluetooth:v02A2* + ID_VENDOR_FROM_DATABASE=LockedUp + +bluetooth:v02A3* + ID_VENDOR_FROM_DATABASE=Itude + +bluetooth:v02A4* + ID_VENDOR_FROM_DATABASE=Pacific Lock Company + +bluetooth:v02A5* + ID_VENDOR_FROM_DATABASE=Tendyron Corporation ( 天地融科技股份有限公司 ) + +bluetooth:v02A6* + ID_VENDOR_FROM_DATABASE=Robert Bosch GmbH + +bluetooth:v02A7* + ID_VENDOR_FROM_DATABASE=Illuxtron international B.V. + +bluetooth:v02A8* + ID_VENDOR_FROM_DATABASE=miSport Ltd. + +bluetooth:v02A9* + ID_VENDOR_FROM_DATABASE=Chargelib + +bluetooth:v02AA* + ID_VENDOR_FROM_DATABASE=Doppler Lab + +bluetooth:v02AB* + ID_VENDOR_FROM_DATABASE=BBPOS Limited + +bluetooth:v02AC* + ID_VENDOR_FROM_DATABASE=RTB Elektronik GmbH & Co. KG + +bluetooth:v02AD* + ID_VENDOR_FROM_DATABASE=Rx Networks, Inc. + +bluetooth:v02AE* + ID_VENDOR_FROM_DATABASE=WeatherFlow, Inc. diff --git a/man/systemd-detect-virt.xml b/man/systemd-detect-virt.xml index 9ea9141d4d..190ab19152 100644 --- a/man/systemd-detect-virt.xml +++ b/man/systemd-detect-virt.xml @@ -139,7 +139,7 @@ </row> <row> - <entry morerows="5">container</entry> + <entry morerows="5">Container</entry> <entry><varname>openvz</varname></entry> <entry>OpenVZ/Virtuozzo</entry> </row> @@ -197,6 +197,18 @@ </varlistentry> <varlistentry> + <term><option>-r</option></term> + <term><option>--chroot</option></term> + + <listitem><para>Detect whether invoked in a + <citerefentry><refentrytitle>chroot</refentrytitle><manvolnum>2</manvolnum></citerefentry> + environment. In this mode no output is written, but the return + value indicates whether the process was invoked in a + <function>chroot()</function> + environment or not.</para></listitem> + </varlistentry> + + <varlistentry> <term><option>-q</option></term> <term><option>--quiet</option></term> @@ -221,7 +233,8 @@ <title>See Also</title> <para> <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>, - <citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry> + <citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry>, + <citerefentry><refentrytitle>chroot</refentrytitle><manvolnum>2</manvolnum></citerefentry> </para> </refsect1> diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml index 56db9ff17e..8dad0e0f59 100644 --- a/man/systemd-system.conf.xml +++ b/man/systemd-system.conf.xml @@ -109,8 +109,10 @@ <term><varname>CPUAffinity=</varname></term> <listitem><para>Configures the initial CPU affinity for the - init process. Takes a space-separated list of CPU - indices.</para></listitem> + init process. Takes a list of CPU indices or ranges separated + by either whitespace or commas. CPU ranges are specified by + the lower and upper CPU indices separated by a + dash.</para></listitem> </varlistentry> <varlistentry> diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index d3f56fee40..5f99fa875e 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -217,8 +217,10 @@ <term><varname>CPUAffinity=</varname></term> <listitem><para>Controls the CPU affinity of the executed - processes. Takes a space-separated list of CPU indices. This - option may be specified more than once in which case the + processes. Takes a list of CPU indices or ranges separated by + either whitespace or commas. CPU ranges are specified by the + lower and upper CPU indices separated by a dash. + This option may be specified more than once in which case the specified CPU affinity masks are merged. If the empty string is assigned, the mask is reset, all assignments prior to this will have no effect. See diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml index 33f1309268..a4eeccaed4 100644 --- a/man/systemd.unit.xml +++ b/man/systemd.unit.xml @@ -263,10 +263,8 @@ in directories listed earlier override files with the same name in directories lower in the list.</para> - <para>When systemd is running in user mode - (<option>--user</option>) and the variable - <varname>$SYSTEMD_UNIT_PATH</varname> is set, the contents of this - variable overrides the unit load path. If + <para>When the variable <varname>$SYSTEMD_UNIT_PATH</varname> is set, + the contents of this variable overrides the unit load path. If <varname>$SYSTEMD_UNIT_PATH</varname> ends with an empty component (<literal>:</literal>), the usual unit load path will be appended to the contents of the variable.</para> diff --git a/po/LINGUAS b/po/LINGUAS index db05932efd..2774a3228f 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -12,6 +12,7 @@ uk sv sr es +zh_CN zh_TW be be@latin diff --git a/po/zh_CN.po b/po/zh_CN.po new file mode 100644 index 0000000000..67639620fb --- /dev/null +++ b/po/zh_CN.po @@ -0,0 +1,527 @@ +# Simplified Chinese translation for systemd. +# Copyright (C) 2015 systemd's COPYRIGHT HOLDER +# This file is distributed under the same license as the systemd package. +# +# Frank Hill <hxf.prc@gmail.com>, 2014. +# Boyuan Yang <073plan@gmail.com>, 2015. +msgid "" +msgstr "" +"Project-Id-Version: systemd\n" +"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" +"POT-Creation-Date: 2015-10-27 02:24+0000\n" +"PO-Revision-Date: 2015-10-28 15:00+0800\n" +"Last-Translator: Boyuan Yang <073plan@gmail.com>\n" +"Language-Team: Chinese <i18n-zh@googlegroups.com>\n" +"Language: zh_CN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Lokalize 2.0\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 +msgid "Send passphrase back to system" +msgstr "将密码发回系统" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 +msgid "" +"Authentication is required to send the entered passphrase back to the system." +msgstr "将输入的密码发回系统需要验证。" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 +msgid "Manage system services or other units" +msgstr "管理系统服务或其它单元" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 +msgid "Authentication is required to manage system services or other units." +msgstr "管理系统服务或其它单元需要验证。" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 +msgid "Manage system service or unit files" +msgstr "管理系统服务或单元文件" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 +msgid "Authentication is required to manage system service or unit files." +msgstr "管理系统服务或单元文件需要验证。" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 +msgid "Set or unset system and service manager environment variables" +msgstr "设置或清除系统及服务管理器的环境变量" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 +msgid "" +"Authentication is required to set or unset system and service manager " +"environment variables." +msgstr "设置或清除系统及服务管理器的环境变量需要验证。" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 +msgid "Reload the systemd state" +msgstr "重新载入 systemd 状态" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 +msgid "Authentication is required to reload the systemd state." +msgstr "重新载入 systemd 状态需要验证。" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 +msgid "Set host name" +msgstr "设置主机名" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 +msgid "Authentication is required to set the local host name." +msgstr "设置本地主机名需要验证。" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 +msgid "Set static host name" +msgstr "设置静态主机名" + +# For pretty hostname, the zh_CN/zh_TW translation should be discussed again. +# +# There were some discussions, like https://lists.fedoraprojects.org/pipermail/trans-zh_cn/2012-December/001347.html +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 +#, fuzzy +msgid "" +"Authentication is required to set the statically configured local host name, " +"as well as the pretty host name." +msgstr "设置静态本地主机名或漂亮的主机名需要验证。" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 +msgid "Set machine information" +msgstr "设置机器信息" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 +msgid "Authentication is required to set local machine information." +msgstr "设置本地机器信息需要验证。" + +#: ../src/import/org.freedesktop.import1.policy.in.h:1 +msgid "Import a VM or container image" +msgstr "导入虚拟机或容器镜像" + +#: ../src/import/org.freedesktop.import1.policy.in.h:2 +msgid "Authentication is required to import a VM or container image" +msgstr "导入虚拟机或容器镜像需要验证" + +#: ../src/import/org.freedesktop.import1.policy.in.h:3 +msgid "Export a VM or container image" +msgstr "导出虚拟机或容器镜像" + +#: ../src/import/org.freedesktop.import1.policy.in.h:4 +msgid "Authentication is required to export a VM or container image" +msgstr "导出虚拟机或容器镜像需要验证" + +#: ../src/import/org.freedesktop.import1.policy.in.h:5 +msgid "Download a VM or container image" +msgstr "下载虚拟机或容器镜像" + +#: ../src/import/org.freedesktop.import1.policy.in.h:6 +msgid "Authentication is required to download a VM or container image" +msgstr "下载虚拟机或容器镜像需要验证。" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:1 +msgid "Set system locale" +msgstr "设置系统区域和语言" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:2 +msgid "Authentication is required to set the system locale." +msgstr "设置系统区域和语言需要验证。" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:3 +msgid "Set system keyboard settings" +msgstr "设置系统键盘" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:4 +msgid "Authentication is required to set the system keyboard settings." +msgstr "设置系统键盘需要验证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:1 +msgid "Allow applications to inhibit system shutdown" +msgstr "允许应用程序阻止系统关机" + +#: ../src/login/org.freedesktop.login1.policy.in.h:2 +msgid "" +"Authentication is required for an application to inhibit system shutdown." +msgstr "要允许应用程序阻止系统关机需要验证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:3 +msgid "Allow applications to delay system shutdown" +msgstr "允许应用程序延迟系统关机" + +#: ../src/login/org.freedesktop.login1.policy.in.h:4 +msgid "Authentication is required for an application to delay system shutdown." +msgstr "要允许应用程序延迟系统关机需要验证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:5 +msgid "Allow applications to inhibit system sleep" +msgstr "允许应用程序阻止系统睡眠" + +#: ../src/login/org.freedesktop.login1.policy.in.h:6 +msgid "Authentication is required for an application to inhibit system sleep." +msgstr "要允许应用程序阻止系统睡眠需要验证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:7 +msgid "Allow applications to delay system sleep" +msgstr "允许应用程序延迟系统睡眠" + +#: ../src/login/org.freedesktop.login1.policy.in.h:8 +msgid "Authentication is required for an application to delay system sleep." +msgstr "要允许应用程序延迟系统睡眠需要验证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:9 +msgid "Allow applications to inhibit automatic system suspend" +msgstr "允许应用程序阻止系统自动挂起" + +#: ../src/login/org.freedesktop.login1.policy.in.h:10 +msgid "" +"Authentication is required for an application to inhibit automatic system " +"suspend." +msgstr "要允许应用程序阻止系统自动挂起需要验证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:11 +msgid "Allow applications to inhibit system handling of the power key" +msgstr "允许应用程序阻止系统响应电源键" + +#: ../src/login/org.freedesktop.login1.policy.in.h:12 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the power key." +msgstr "要允许应用程序阻止系统响应电源键需要验证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:13 +msgid "Allow applications to inhibit system handling of the suspend key" +msgstr "允许应用程序阻止系统响应挂起键" + +#: ../src/login/org.freedesktop.login1.policy.in.h:14 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the suspend key." +msgstr "要允许应用程序阻止系统响应挂起键需要验证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:15 +msgid "Allow applications to inhibit system handling of the hibernate key" +msgstr "允许应用程序阻止系统响应挂起键" + +#: ../src/login/org.freedesktop.login1.policy.in.h:16 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the hibernate key." +msgstr "要允许应用程序阻止系统响应挂起键需要验证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:17 +#, fuzzy +msgid "Allow applications to inhibit system handling of the lid switch" +msgstr "允许应用程序阻止系统响应笔记本上盖开关事件" + +#: ../src/login/org.freedesktop.login1.policy.in.h:18 +#, fuzzy +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the lid switch." +msgstr "要允许应用程序阻止系统响应笔记本上盖开关事件需要验证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:19 +msgid "Allow non-logged-in users to run programs" +msgstr "允许未登录用户运行程序" + +#: ../src/login/org.freedesktop.login1.policy.in.h:20 +msgid "Authentication is required to run programs as a non-logged-in user." +msgstr "要允许未登录用户运行程序需要验证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:21 +msgid "Allow attaching devices to seats" +msgstr "允许将设备附加至会话座位" + +# Pay attention to the concept of "seat". +# +# To fully understand the meaning, please refer to session management in old ConsoleKit and new systemd-logind. +#: ../src/login/org.freedesktop.login1.policy.in.h:22 +msgid "Authentication is required for attaching a device to a seat." +msgstr "要允许将设备附加至某个会话座位需要验证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:23 +msgid "Flush device to seat attachments" +msgstr "刷新设备至会话座位间的连接" + +#: ../src/login/org.freedesktop.login1.policy.in.h:24 +msgid "" +"Authentication is required for resetting how devices are attached to seats." +msgstr "重新设定设备的会话座位接入方式时需要验证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:25 +msgid "Power off the system" +msgstr "关闭系统" + +#: ../src/login/org.freedesktop.login1.policy.in.h:26 +msgid "Authentication is required for powering off the system." +msgstr "关闭系统需要验证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:27 +msgid "Power off the system while other users are logged in" +msgstr "存在其他已登录用户时仍然关机" + +#: ../src/login/org.freedesktop.login1.policy.in.h:28 +msgid "" +"Authentication is required for powering off the system while other users are " +"logged in." +msgstr "存在其他已登录用户时关闭系统需要验证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:29 +msgid "Power off the system while an application asked to inhibit it" +msgstr "有其它应用程序阻止时仍然关机" + +#: ../src/login/org.freedesktop.login1.policy.in.h:30 +msgid "" +"Authentication is required for powering off the system while an application " +"asked to inhibit it." +msgstr "要在其它应用程序阻止关机时关闭系统需要验证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:31 +msgid "Reboot the system" +msgstr "重启系统" + +#: ../src/login/org.freedesktop.login1.policy.in.h:32 +msgid "Authentication is required for rebooting the system." +msgstr "重启系统需要验证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:33 +msgid "Reboot the system while other users are logged in" +msgstr "存在其他已登录用户时仍然重启" + +#: ../src/login/org.freedesktop.login1.policy.in.h:34 +msgid "" +"Authentication is required for rebooting the system while other users are " +"logged in." +msgstr "存在其他已登录用户时重启系统需要验证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:35 +msgid "Reboot the system while an application asked to inhibit it" +msgstr "有其它应用程序阻止时仍然重启" + +#: ../src/login/org.freedesktop.login1.policy.in.h:36 +msgid "" +"Authentication is required for rebooting the system while an application " +"asked to inhibit it." +msgstr "要在其它应用程序阻止重启时重启系统需要验证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:37 +msgid "Suspend the system" +msgstr "挂起系统" + +#: ../src/login/org.freedesktop.login1.policy.in.h:38 +msgid "Authentication is required for suspending the system." +msgstr "挂起系统需要验证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:39 +msgid "Suspend the system while other users are logged in" +msgstr "存在其他已登录用户时仍然挂起系统" + +#: ../src/login/org.freedesktop.login1.policy.in.h:40 +msgid "" +"Authentication is required for suspending the system while other users are " +"logged in." +msgstr "存在其他已登录用户时挂起系统需要验证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:41 +msgid "Suspend the system while an application asked to inhibit it" +msgstr "有其它应用程序阻止时仍然挂起系统" + +#: ../src/login/org.freedesktop.login1.policy.in.h:42 +msgid "" +"Authentication is required for suspending the system while an application " +"asked to inhibit it." +msgstr "要在其它应用程序阻止挂起时挂起系统需要验证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:43 +msgid "Hibernate the system" +msgstr "休眠" + +#: ../src/login/org.freedesktop.login1.policy.in.h:44 +msgid "Authentication is required for hibernating the system." +msgstr "休眠需要验证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:45 +msgid "Hibernate the system while other users are logged in" +msgstr "存在其他已登录用户时仍然休眠" + +#: ../src/login/org.freedesktop.login1.policy.in.h:46 +msgid "" +"Authentication is required for hibernating the system while other users are " +"logged in." +msgstr "存在其他已登录用户时进行休眠需要验证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:47 +msgid "Hibernate the system while an application asked to inhibit it" +msgstr "有其它应用程序阻止时仍然休眠" + +#: ../src/login/org.freedesktop.login1.policy.in.h:48 +msgid "" +"Authentication is required for hibernating the system while an application " +"asked to inhibit it." +msgstr "要在其它应用程序阻止休眠时进行休眠需要验证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:49 +msgid "Manage active sessions, users and seats" +msgstr "管理活动会话、用户与会话座位" + +#: ../src/login/org.freedesktop.login1.policy.in.h:50 +msgid "" +"Authentication is required for managing active sessions, users and seats." +msgstr "要管理活动会话、用户与会话座位需要验证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:51 +msgid "Lock or unlock active sessions" +msgstr "活动会话锁定与解锁" + +#: ../src/login/org.freedesktop.login1.policy.in.h:52 +msgid "Authentication is required to lock or unlock active sessions." +msgstr "要对活动会话进行锁定或解锁需要验证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:53 +msgid "Allow indication to the firmware to boot to setup interface" +msgstr "允许向固件发出指示以启动至固件设置界面" + +#: ../src/login/org.freedesktop.login1.policy.in.h:54 +msgid "" +"Authentication is required to indicate to the firmware to boot to setup " +"interface." +msgstr "要允许向固件发出启动时进入设置界面的指令需要验证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:55 +msgid "Set a wall message" +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:56 +#, fuzzy +msgid "Authentication is required to set a wall message" +msgstr "" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:1 +msgid "Log into a local container" +msgstr "登入一个本地容器" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:2 +msgid "Authentication is required to log into a local container." +msgstr "要登入一个本地容器需要验证。" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:3 +msgid "Log into the local host" +msgstr "登入本地主机" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:4 +msgid "Authentication is required to log into the local host." +msgstr "要登入本地主机需要验证。" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:5 +msgid "Acquire a shell in a local container" +msgstr "在本地容器中获取一个 shell" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:6 +msgid "Authentication is required to acquire a shell in a local container." +msgstr "要在本地容器中获取 shell 需要验证。" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:7 +msgid "Acquire a shell on the local host" +msgstr "在本地主机中获取一个 shell" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:8 +msgid "Authentication is required to acquire a shell on the local host." +msgstr "要在本地主机中获取 shell 需要验证。" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:9 +msgid "Acquire a pseudo TTY in a local container" +msgstr "在本地容器中获取一个假 TTY" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:10 +msgid "" +"Authentication is required to acquire a pseudo TTY in a local container." +msgstr "要在本地容器中获取假 TTY 需要验证。" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:11 +msgid "Acquire a pseudo TTY on the local host" +msgstr "在本地主机中获取一个假 TTY" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:12 +msgid "Authentication is required to acquire a pseudo TTY on the local host." +msgstr "要在本地主机中获取假 TTY 需要验证。" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:13 +msgid "Manage local virtual machines and containers" +msgstr "管理本地虚拟机和容器" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:14 +msgid "" +"Authentication is required to manage local virtual machines and containers." +msgstr "要管理本地虚拟机和容器需要验证。" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:15 +msgid "Manage local virtual machine and container images" +msgstr "管理本地虚拟机和容器的镜像" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:16 +msgid "" +"Authentication is required to manage local virtual machine and container " +"images." +msgstr "要管理本地的虚拟机和容器镜像需要验证。" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 +msgid "Set system time" +msgstr "设置系统时间" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 +msgid "Authentication is required to set the system time." +msgstr "设置系统时间需要验证。" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 +msgid "Set system timezone" +msgstr "设置系统时区" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 +msgid "Authentication is required to set the system timezone." +msgstr "设置系统时区需要验证。" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 +msgid "Set RTC to local timezone or UTC" +msgstr "设置硬件时钟使用本地时间或 UTC" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 +msgid "" +"Authentication is required to control whether the RTC stores the local or " +"UTC time." +msgstr "设置硬件时钟使用本地时间或 UTC 需要验证。" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 +msgid "Turn network time synchronization on or off" +msgstr "打开或关闭网络时间同步" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 +msgid "" +"Authentication is required to control whether network time synchronization " +"shall be enabled." +msgstr "设置是否启用网络时间同步需要验证。" + +#: ../src/core/dbus-unit.c:430 +msgid "Authentication is required to start '$(unit)'." +msgstr "启动“$(unit)”需要验证。" + +#: ../src/core/dbus-unit.c:431 +msgid "Authentication is required to stop '$(unit)'." +msgstr "停止“$(unit)”需要验证。" + +#: ../src/core/dbus-unit.c:432 +msgid "Authentication is required to reload '$(unit)'." +msgstr "重新载入“$(unit)”需要验证。" + +#: ../src/core/dbus-unit.c:433 ../src/core/dbus-unit.c:434 +msgid "Authentication is required to restart '$(unit)'." +msgstr "重新启动“$(unit)”需要验证。" + +#: ../src/core/dbus-unit.c:537 +msgid "Authentication is required to kill '$(unit)'." +msgstr "杀死“$(unit)”需要验证。" + +#: ../src/core/dbus-unit.c:567 +msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." +msgstr "重置“$(unit)”的失败(\"failed\")状态需要验证。" + +#: ../src/core/dbus-unit.c:599 +msgid "Authentication is required to set properties on '$(unit)'." +msgstr "设置“$(unit)”的属性需要验证。" + diff --git a/shell-completion/bash/hostnamectl b/shell-completion/bash/hostnamectl index 9ad52e03b4..6a252188ea 100644 --- a/shell-completion/bash/hostnamectl +++ b/shell-completion/bash/hostnamectl @@ -38,7 +38,7 @@ _hostnamectl() { local -A VERBS=( [STANDALONE]='status' [ICONS]='set-icon-name' - [NAME]='set-hostname set-deployment' + [NAME]='set-hostname set-deployment set-location' [CHASSIS]='set-chassis' ) diff --git a/shell-completion/bash/systemctl.in b/shell-completion/bash/systemctl.in index 29bb41c436..cfe003544d 100644 --- a/shell-completion/bash/systemctl.in +++ b/shell-completion/bash/systemctl.in @@ -106,6 +106,8 @@ _systemctl () { if __contains_word "--user" ${COMP_WORDS[*]}; then mode=--user + elif __contains_word "--global" ${COMP_WORDS[*]}; then + mode=--user else mode=--system fi diff --git a/src/activate/activate.c b/src/activate/activate.c index 0e6ead310e..b7e6255f49 100644 --- a/src/activate/activate.c +++ b/src/activate/activate.c @@ -28,13 +28,14 @@ #include "sd-daemon.h" +#include "alloc-util.h" +#include "fd-util.h" #include "log.h" #include "macro.h" #include "signal-util.h" #include "socket-util.h" #include "string-util.h" #include "strv.h" -#include "fd-util.h" static char** arg_listen = NULL; static bool arg_accept = false; diff --git a/src/analyze/analyze-verify.c b/src/analyze/analyze-verify.c index f4255f979e..a377996a37 100644 --- a/src/analyze/analyze-verify.c +++ b/src/analyze/analyze-verify.c @@ -21,12 +21,14 @@ #include <stdlib.h> -#include "manager.h" +#include "alloc-util.h" +#include "analyze-verify.h" #include "bus-util.h" #include "log.h" -#include "strv.h" +#include "manager.h" #include "pager.h" -#include "analyze-verify.h" +#include "path-util.h" +#include "strv.h" static int generate_path(char **var, char **filenames) { char **filename; diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c index 4bf83eb329..27ead903e9 100644 --- a/src/analyze/analyze.c +++ b/src/analyze/analyze.c @@ -27,12 +27,16 @@ #include "sd-bus.h" +#include "alloc-util.h" #include "analyze-verify.h" #include "bus-error.h" #include "bus-util.h" +#include "glob-util.h" #include "hashmap.h" +#include "locale-util.h" #include "log.h" #include "pager.h" +#include "parse-util.h" #include "special.h" #include "strv.h" #include "strxcpyx.h" diff --git a/src/backlight/backlight.c b/src/backlight/backlight.c index fc96eee6a9..08980fba82 100644 --- a/src/backlight/backlight.c +++ b/src/backlight/backlight.c @@ -21,10 +21,13 @@ #include "libudev.h" +#include "alloc-util.h" #include "def.h" #include "escape.h" #include "fileio.h" #include "mkdir.h" +#include "parse-util.h" +#include "proc-cmdline.h" #include "string-util.h" #include "udev-util.h" #include "util.h" diff --git a/src/basic/alloc-util.c b/src/basic/alloc-util.c new file mode 100644 index 0000000000..48183e381f --- /dev/null +++ b/src/basic/alloc-util.c @@ -0,0 +1,81 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include "alloc-util.h" +#include "util.h" + +void* memdup(const void *p, size_t l) { + void *r; + + assert(p); + + r = malloc(l); + if (!r) + return NULL; + + memcpy(r, p, l); + return r; +} + +void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) { + size_t a, newalloc; + void *q; + + assert(p); + assert(allocated); + + if (*allocated >= need) + return *p; + + newalloc = MAX(need * 2, 64u / size); + a = newalloc * size; + + /* check for overflows */ + if (a < size * need) + return NULL; + + q = realloc(*p, a); + if (!q) + return NULL; + + *p = q; + *allocated = newalloc; + return q; +} + +void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size) { + size_t prev; + uint8_t *q; + + assert(p); + assert(allocated); + + prev = *allocated; + + q = greedy_realloc(p, allocated, need, size); + if (!q) + return NULL; + + if (*allocated > prev) + memzero(q + prev * size, (*allocated - prev) * size); + + return q; +} diff --git a/src/basic/alloc-util.h b/src/basic/alloc-util.h new file mode 100644 index 0000000000..12b602e185 --- /dev/null +++ b/src/basic/alloc-util.h @@ -0,0 +1,108 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <alloca.h> +#include <stdlib.h> +#include <string.h> + +#include "macro.h" + +#define new(t, n) ((t*) malloc_multiply(sizeof(t), (n))) + +#define new0(t, n) ((t*) calloc((n), sizeof(t))) + +#define newa(t, n) ((t*) alloca(sizeof(t)*(n))) + +#define newa0(t, n) ((t*) alloca0(sizeof(t)*(n))) + +#define newdup(t, p, n) ((t*) memdup_multiply(p, sizeof(t), (n))) + +#define malloc0(n) (calloc(1, (n))) + +static inline void *mfree(void *memory) { + free(memory); + return NULL; +} + +void* memdup(const void *p, size_t l) _alloc_(2); + +static inline void freep(void *p) { + free(*(void**) p); +} + +#define _cleanup_free_ _cleanup_(freep) + +_malloc_ _alloc_(1, 2) static inline void *malloc_multiply(size_t a, size_t b) { + if (_unlikely_(b != 0 && a > ((size_t) -1) / b)) + return NULL; + + return malloc(a * b); +} + +_alloc_(2, 3) static inline void *realloc_multiply(void *p, size_t a, size_t b) { + if (_unlikely_(b != 0 && a > ((size_t) -1) / b)) + return NULL; + + return realloc(p, a * b); +} + +_alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t a, size_t b) { + if (_unlikely_(b != 0 && a > ((size_t) -1) / b)) + return NULL; + + return memdup(p, a * b); +} + +void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size); +void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size); + +#define GREEDY_REALLOC(array, allocated, need) \ + greedy_realloc((void**) &(array), &(allocated), (need), sizeof((array)[0])) + +#define GREEDY_REALLOC0(array, allocated, need) \ + greedy_realloc0((void**) &(array), &(allocated), (need), sizeof((array)[0])) + +#define alloca0(n) \ + ({ \ + char *_new_; \ + size_t _len_ = n; \ + _new_ = alloca(_len_); \ + (void *) memset(_new_, 0, _len_); \ + }) + +/* It's not clear what alignment glibc/gcc alloca() guarantee, hence provide a guaranteed safe version */ +#define alloca_align(size, align) \ + ({ \ + void *_ptr_; \ + size_t _mask_ = (align) - 1; \ + _ptr_ = alloca((size) + _mask_); \ + (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_); \ + }) + +#define alloca0_align(size, align) \ + ({ \ + void *_new_; \ + size_t _size_ = (size); \ + _new_ = alloca_align(_size_, (align)); \ + (void*)memset(_new_, 0, _size_); \ + }) diff --git a/src/basic/audit.c b/src/basic/audit-util.c index c9b762151a..4612297334 100644 --- a/src/basic/audit.c +++ b/src/basic/audit-util.c @@ -22,10 +22,12 @@ #include <errno.h> #include <stdio.h> -#include "audit.h" +#include "alloc-util.h" +#include "audit-util.h" #include "fd-util.h" #include "fileio.h" #include "macro.h" +#include "parse-util.h" #include "process-util.h" #include "user-util.h" #include "util.h" diff --git a/src/basic/audit.h b/src/basic/audit-util.h index 6de331c73e..6de331c73e 100644 --- a/src/basic/audit.h +++ b/src/basic/audit-util.h diff --git a/src/basic/bitmap.c b/src/basic/bitmap.c index 2eabf3e1c1..1449e2ea85 100644 --- a/src/basic/bitmap.c +++ b/src/basic/bitmap.c @@ -19,9 +19,9 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include "util.h" - +#include "alloc-util.h" #include "bitmap.h" +#include "util.h" struct Bitmap { uint64_t *bitmaps; diff --git a/src/basic/btrfs-util.c b/src/basic/btrfs-util.c index f799f8dcc2..4c90bc0c80 100644 --- a/src/basic/btrfs-util.c +++ b/src/basic/btrfs-util.c @@ -26,6 +26,7 @@ #include <linux/btrfs.h> #endif +#include "alloc-util.h" #include "btrfs-ctree.h" #include "btrfs-util.h" #include "copy.h" @@ -36,6 +37,7 @@ #include "path-util.h" #include "selinux-util.h" #include "smack-util.h" +#include "stat-util.h" #include "string-util.h" #include "util.h" @@ -60,13 +62,13 @@ static int validate_subvolume_name(const char *name) { static int open_parent(const char *path, int flags) { _cleanup_free_ char *parent = NULL; - int r, fd; + int fd; assert(path); - r = path_get_parent(path, &parent); - if (r < 0) - return r; + parent = dirname_malloc(path); + if (!parent) + return -ENOMEM; fd = open(parent, flags); if (fd < 0) diff --git a/src/basic/bus-label.c b/src/basic/bus-label.c index ccc9f2bf8e..c1534657ac 100644 --- a/src/basic/bus-label.c +++ b/src/basic/bus-label.c @@ -21,10 +21,11 @@ #include <stdlib.h> -#include "util.h" -#include "macro.h" - +#include "alloc-util.h" #include "bus-label.h" +#include "hexdecoct.h" +#include "macro.h" +#include "util.h" char *bus_label_escape(const char *s) { char *r, *t; diff --git a/src/basic/calendarspec.c b/src/basic/calendarspec.c index 50328e4187..a6a906f453 100644 --- a/src/basic/calendarspec.c +++ b/src/basic/calendarspec.c @@ -22,8 +22,10 @@ #include <stdlib.h> #include <string.h> +#include "alloc-util.h" #include "string-util.h" #include "calendarspec.h" +#include "fileio.h" #define BITS_WEEKDAYS 127 diff --git a/src/basic/cap-list.c b/src/basic/cap-list.c index bd5bffbfa5..4d391510bc 100644 --- a/src/basic/cap-list.c +++ b/src/basic/cap-list.c @@ -21,9 +21,10 @@ #include <string.h> -#include "util.h" #include "cap-list.h" #include "missing.h" +#include "parse-util.h" +#include "util.h" static const struct capability_name* lookup_capability(register const char *str, register unsigned int len); diff --git a/src/basic/capability.c b/src/basic/capability-util.c index 6f25b5dee9..4479200306 100644 --- a/src/basic/capability.c +++ b/src/basic/capability-util.c @@ -26,10 +26,12 @@ #include <sys/prctl.h> #include <unistd.h> -#include "capability.h" +#include "alloc-util.h" +#include "capability-util.h" #include "fileio.h" #include "log.h" #include "macro.h" +#include "parse-util.h" #include "util.h" int have_effective_cap(int value) { diff --git a/src/basic/capability.h b/src/basic/capability-util.h index 4eb5c2a835..4eb5c2a835 100644 --- a/src/basic/capability.h +++ b/src/basic/capability-util.h diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 4af991200c..f7fc2c2c97 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -29,18 +29,25 @@ #include <sys/types.h> #include <unistd.h> +#include "alloc-util.h" #include "cgroup-util.h" +#include "dirent-util.h" #include "extract-word.h" #include "fd-util.h" #include "fileio.h" #include "formats-util.h" +#include "fs-util.h" #include "login-util.h" #include "macro.h" #include "mkdir.h" +#include "parse-util.h" #include "path-util.h" +#include "proc-cmdline.h" #include "process-util.h" #include "set.h" #include "special.h" +#include "stat-util.h" +#include "string-table.h" #include "string-util.h" #include "unit-name.h" #include "user-util.h" diff --git a/src/basic/chattr-util.c b/src/basic/chattr-util.c new file mode 100644 index 0000000000..d49ca0537a --- /dev/null +++ b/src/basic/chattr-util.c @@ -0,0 +1,107 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <linux/fs.h> + +#include "chattr-util.h" +#include "fd-util.h" +#include "util.h" + +int chattr_fd(int fd, unsigned value, unsigned mask) { + unsigned old_attr, new_attr; + struct stat st; + + assert(fd >= 0); + + if (fstat(fd, &st) < 0) + return -errno; + + /* Explicitly check whether this is a regular file or + * directory. If it is anything else (such as a device node or + * fifo), then the ioctl will not hit the file systems but + * possibly drivers, where the ioctl might have different + * effects. Notably, DRM is using the same ioctl() number. */ + + if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode)) + return -ENOTTY; + + if (mask == 0) + return 0; + + if (ioctl(fd, FS_IOC_GETFLAGS, &old_attr) < 0) + return -errno; + + new_attr = (old_attr & ~mask) | (value & mask); + if (new_attr == old_attr) + return 0; + + if (ioctl(fd, FS_IOC_SETFLAGS, &new_attr) < 0) + return -errno; + + return 1; +} + +int chattr_path(const char *p, unsigned value, unsigned mask) { + _cleanup_close_ int fd = -1; + + assert(p); + + if (mask == 0) + return 0; + + fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); + if (fd < 0) + return -errno; + + return chattr_fd(fd, value, mask); +} + +int read_attr_fd(int fd, unsigned *ret) { + struct stat st; + + assert(fd >= 0); + + if (fstat(fd, &st) < 0) + return -errno; + + if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode)) + return -ENOTTY; + + if (ioctl(fd, FS_IOC_GETFLAGS, ret) < 0) + return -errno; + + return 0; +} + +int read_attr_path(const char *p, unsigned *ret) { + _cleanup_close_ int fd = -1; + + assert(p); + assert(ret); + + fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); + if (fd < 0) + return -errno; + + return read_attr_fd(fd, ret); +} diff --git a/src/basic/chattr-util.h b/src/basic/chattr-util.h new file mode 100644 index 0000000000..ba6b8eb5c1 --- /dev/null +++ b/src/basic/chattr-util.h @@ -0,0 +1,28 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +int chattr_fd(int fd, unsigned value, unsigned mask); +int chattr_path(const char *p, unsigned value, unsigned mask); + +int read_attr_fd(int fd, unsigned *ret); +int read_attr_path(const char *p, unsigned *ret); diff --git a/src/basic/conf-files.c b/src/basic/conf-files.c index 3af3fe392c..be9972ffff 100644 --- a/src/basic/conf-files.c +++ b/src/basic/conf-files.c @@ -26,6 +26,7 @@ #include <string.h> #include "conf-files.h" +#include "dirent-util.h" #include "fd-util.h" #include "hashmap.h" #include "log.h" diff --git a/src/basic/copy.c b/src/basic/copy.c index 9f274c4d51..a187ae08fe 100644 --- a/src/basic/copy.c +++ b/src/basic/copy.c @@ -22,13 +22,20 @@ #include <sys/sendfile.h> #include <sys/xattr.h> +#include "alloc-util.h" #include "btrfs-util.h" +#include "chattr-util.h" #include "copy.h" +#include "dirent-util.h" #include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" #include "io-util.h" #include "string-util.h" #include "strv.h" +#include "umask-util.h" #include "util.h" +#include "xattr-util.h" #define COPY_BUFFER_SIZE (16*1024) diff --git a/src/basic/cpu-set-util.c b/src/basic/cpu-set-util.c index 5e064d854f..4950c66767 100644 --- a/src/basic/cpu-set-util.c +++ b/src/basic/cpu-set-util.c @@ -20,9 +20,11 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" +#include "cpu-set-util.h" #include "extract-word.h" +#include "parse-util.h" #include "util.h" -#include "cpu-set-util.h" cpu_set_t* cpu_set_malloc(unsigned *ncpus) { cpu_set_t *c; @@ -70,14 +72,12 @@ int parse_cpu_set_and_warn( for (;;) { _cleanup_free_ char *word = NULL; - unsigned cpu; + unsigned cpu, cpu_lower, cpu_upper; int r; - r = extract_first_word(&rvalue, &word, WHITESPACE, EXTRACT_QUOTES); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Invalid value for %s: %s", lvalue, whole_rvalue); - return r; - } + r = extract_first_word(&rvalue, &word, WHITESPACE ",", EXTRACT_QUOTES); + if (r < 0) + return log_syntax(unit, LOG_ERR, filename, line, r, "Invalid value for %s: %s", lvalue, whole_rvalue); if (r == 0) break; @@ -87,13 +87,17 @@ int parse_cpu_set_and_warn( return log_oom(); } - r = safe_atou(word, &cpu); - if (r < 0 || cpu >= ncpus) { - log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse CPU affinity '%s'", rvalue); - return -EINVAL; - } - - CPU_SET_S(cpu, CPU_ALLOC_SIZE(ncpus), c); + r = parse_range(word, &cpu_lower, &cpu_upper); + if (r < 0) + return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse CPU affinity '%s'", word); + if (cpu_lower >= ncpus || cpu_upper >= ncpus) + return log_syntax(unit, LOG_ERR, filename, line, EINVAL, "CPU out of range '%s' ncpus is %u", word, ncpus); + + if (cpu_lower > cpu_upper) + log_syntax(unit, LOG_WARNING, filename, line, 0, "Range '%s' is invalid, %u > %u", word, cpu_lower, cpu_upper); + else + for (cpu = cpu_lower; cpu <= cpu_upper; cpu++) + CPU_SET_S(cpu, CPU_ALLOC_SIZE(ncpus), c); } /* On success, sets *cpu_set and returns ncpus for the system. */ diff --git a/src/basic/device-nodes.h b/src/basic/device-nodes.h index 04ba4897e5..7db81f3d52 100644 --- a/src/basic/device-nodes.h +++ b/src/basic/device-nodes.h @@ -21,5 +21,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include <sys/types.h> + int encode_devnode_name(const char *str, char *str_enc, size_t len); int whitelisted_char_for_devnode(char c, const char *additional); diff --git a/src/basic/dirent-util.c b/src/basic/dirent-util.c new file mode 100644 index 0000000000..c433d5844a --- /dev/null +++ b/src/basic/dirent-util.c @@ -0,0 +1,81 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2010-2012 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <fcntl.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +#include "dirent-util.h" +#include "string-util.h" + +int dirent_ensure_type(DIR *d, struct dirent *de) { + struct stat st; + + assert(d); + assert(de); + + if (de->d_type != DT_UNKNOWN) + return 0; + + if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) + return -errno; + + de->d_type = + S_ISREG(st.st_mode) ? DT_REG : + S_ISDIR(st.st_mode) ? DT_DIR : + S_ISLNK(st.st_mode) ? DT_LNK : + S_ISFIFO(st.st_mode) ? DT_FIFO : + S_ISSOCK(st.st_mode) ? DT_SOCK : + S_ISCHR(st.st_mode) ? DT_CHR : + S_ISBLK(st.st_mode) ? DT_BLK : + DT_UNKNOWN; + + return 0; +} + +bool dirent_is_file(const struct dirent *de) { + assert(de); + + if (hidden_file(de->d_name)) + return false; + + if (de->d_type != DT_REG && + de->d_type != DT_LNK && + de->d_type != DT_UNKNOWN) + return false; + + return true; +} + +bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) { + assert(de); + + if (de->d_type != DT_REG && + de->d_type != DT_LNK && + de->d_type != DT_UNKNOWN) + return false; + + if (hidden_file_allow_backup(de->d_name)) + return false; + + return endswith(de->d_name, suffix); +} diff --git a/src/basic/dirent-util.h b/src/basic/dirent-util.h new file mode 100644 index 0000000000..5866a755f4 --- /dev/null +++ b/src/basic/dirent-util.h @@ -0,0 +1,51 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <dirent.h> + +#include "path-util.h" + +int dirent_ensure_type(DIR *d, struct dirent *de); + +bool dirent_is_file(const struct dirent *de) _pure_; +bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) _pure_; + +#define FOREACH_DIRENT(de, d, on_error) \ + for (errno = 0, de = readdir(d);; errno = 0, de = readdir(d)) \ + if (!de) { \ + if (errno > 0) { \ + on_error; \ + } \ + break; \ + } else if (hidden_file((de)->d_name)) \ + continue; \ + else + +#define FOREACH_DIRENT_ALL(de, d, on_error) \ + for (errno = 0, de = readdir(d);; errno = 0, de = readdir(d)) \ + if (!de) { \ + if (errno > 0) { \ + on_error; \ + } \ + break; \ + } else diff --git a/src/basic/env-util.c b/src/basic/env-util.c index a392af737c..9ddac5d6a1 100644 --- a/src/basic/env-util.c +++ b/src/basic/env-util.c @@ -22,12 +22,14 @@ #include <limits.h> #include <unistd.h> +#include "alloc-util.h" #include "def.h" +#include "env-util.h" +#include "parse-util.h" #include "string-util.h" #include "strv.h" #include "utf8.h" #include "util.h" -#include "env-util.h" #define VALID_CHARS_ENV_NAME \ DIGITS LETTERS \ @@ -593,3 +595,13 @@ char **replace_env_argv(char **argv, char **env) { ret[k] = NULL; return ret; } + +int getenv_bool(const char *p) { + const char *e; + + e = getenv(p); + if (!e) + return -ENXIO; + + return parse_boolean(e); +} diff --git a/src/basic/env-util.h b/src/basic/env-util.h index 803aa61cad..6485dade18 100644 --- a/src/basic/env-util.h +++ b/src/basic/env-util.h @@ -47,3 +47,5 @@ char **strv_env_unset_many(char **l, ...) _sentinel_; char *strv_env_get_n(char **l, const char *name, size_t k) _pure_; char *strv_env_get(char **x, const char *n) _pure_; + +int getenv_bool(const char *p); diff --git a/src/basic/escape.c b/src/basic/escape.c index cf05ce10ef..add0d7795b 100644 --- a/src/basic/escape.c +++ b/src/basic/escape.c @@ -19,11 +19,12 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" +#include "escape.h" +#include "hexdecoct.h" #include "utf8.h" #include "util.h" -#include "escape.h" - size_t cescape_char(char c, char *buf) { char * buf_old = buf; diff --git a/src/basic/extract-word.c b/src/basic/extract-word.c index f2b74802fa..c0f9394fad 100644 --- a/src/basic/extract-word.c +++ b/src/basic/extract-word.c @@ -19,6 +19,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "escape.h" #include "utf8.h" #include "util.h" diff --git a/src/basic/fd-util.c b/src/basic/fd-util.c index e54c104597..d1b1db3a4d 100644 --- a/src/basic/fd-util.c +++ b/src/basic/fd-util.c @@ -19,7 +19,10 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "dirent-util.h" #include "fd-util.h" +#include "parse-util.h" +#include "socket-util.h" #include "util.h" int close_nointr(int fd) { @@ -319,3 +322,30 @@ void cmsg_close_all(struct msghdr *mh) { if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) close_many((int*) CMSG_DATA(cmsg), (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int)); } + +bool fdname_is_valid(const char *s) { + const char *p; + + /* Validates a name for $LISTEN_FDNAMES. We basically allow + * everything ASCII that's not a control character. Also, as + * special exception the ":" character is not allowed, as we + * use that as field separator in $LISTEN_FDNAMES. + * + * Note that the empty string is explicitly allowed + * here. However, we limit the length of the names to 255 + * characters. */ + + if (!s) + return false; + + for (p = s; *p; p++) { + if (*p < ' ') + return false; + if (*p >= 127) + return false; + if (*p == ':') + return false; + } + + return p - s < 256; +} diff --git a/src/basic/fd-util.h b/src/basic/fd-util.h index be00d881c3..1ca10f0383 100644 --- a/src/basic/fd-util.h +++ b/src/basic/fd-util.h @@ -67,3 +67,5 @@ int close_all_fds(const int except[], unsigned n_except); int same_fd(int a, int b); void cmsg_close_all(struct msghdr *mh); + +bool fdname_is_valid(const char *s); diff --git a/src/basic/fdset.c b/src/basic/fdset.c index 9669110828..42b0b2b98f 100644 --- a/src/basic/fdset.c +++ b/src/basic/fdset.c @@ -25,9 +25,11 @@ #include "sd-daemon.h" +#include "dirent-util.h" #include "fd-util.h" #include "fdset.h" #include "macro.h" +#include "parse-util.h" #include "set.h" #include "util.h" @@ -42,7 +44,7 @@ FDSet *fdset_new(void) { return MAKE_FDSET(set_new(NULL)); } -int fdset_new_array(FDSet **ret, int *fds, unsigned n_fds) { +int fdset_new_array(FDSet **ret, const int *fds, unsigned n_fds) { unsigned i; FDSet *s; int r; diff --git a/src/basic/fdset.h b/src/basic/fdset.h index 340438d7c4..70d8acbcff 100644 --- a/src/basic/fdset.h +++ b/src/basic/fdset.h @@ -35,7 +35,7 @@ int fdset_consume(FDSet *s, int fd); bool fdset_contains(FDSet *s, int fd); int fdset_remove(FDSet *s, int fd); -int fdset_new_array(FDSet **ret, int *fds, unsigned n_fds); +int fdset_new_array(FDSet **ret, const int *fds, unsigned n_fds); int fdset_new_fill(FDSet **ret); int fdset_new_listen_fds(FDSet **ret, bool unset); diff --git a/src/basic/fileio.c b/src/basic/fileio.c index 5d33309ab2..619dafb517 100644 --- a/src/basic/fileio.c +++ b/src/basic/fileio.c @@ -21,12 +21,18 @@ #include <unistd.h> +#include "alloc-util.h" #include "ctype.h" #include "escape.h" #include "fd-util.h" #include "fileio.h" +#include "fs-util.h" +#include "hexdecoct.h" +#include "path-util.h" +#include "random-util.h" #include "string-util.h" #include "strv.h" +#include "umask-util.h" #include "utf8.h" #include "util.h" @@ -54,7 +60,7 @@ static int write_string_file_atomic(const char *fn, const char *line, bool enfor if (r < 0) return r; - fchmod_umask(fileno(f), 0644); + (void) fchmod_umask(fileno(f), 0644); r = write_string_stream(f, line, enforce_newline); if (r >= 0) { @@ -63,7 +69,7 @@ static int write_string_file_atomic(const char *fn, const char *line, bool enfor } if (r < 0) - unlink(p); + (void) unlink(p); return r; } @@ -848,3 +854,298 @@ int get_proc_field(const char *filename, const char *pattern, const char *termin *field = f; return 0; } + +DIR *xopendirat(int fd, const char *name, int flags) { + int nfd; + DIR *d; + + assert(!(flags & O_CREAT)); + + nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags, 0); + if (nfd < 0) + return NULL; + + d = fdopendir(nfd); + if (!d) { + safe_close(nfd); + return NULL; + } + + return d; +} + +static int search_and_fopen_internal(const char *path, const char *mode, const char *root, char **search, FILE **_f) { + char **i; + + assert(path); + assert(mode); + assert(_f); + + if (!path_strv_resolve_uniq(search, root)) + return -ENOMEM; + + STRV_FOREACH(i, search) { + _cleanup_free_ char *p = NULL; + FILE *f; + + if (root) + p = strjoin(root, *i, "/", path, NULL); + else + p = strjoin(*i, "/", path, NULL); + if (!p) + return -ENOMEM; + + f = fopen(p, mode); + if (f) { + *_f = f; + return 0; + } + + if (errno != ENOENT) + return -errno; + } + + return -ENOENT; +} + +int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f) { + _cleanup_strv_free_ char **copy = NULL; + + assert(path); + assert(mode); + assert(_f); + + if (path_is_absolute(path)) { + FILE *f; + + f = fopen(path, mode); + if (f) { + *_f = f; + return 0; + } + + return -errno; + } + + copy = strv_copy((char**) search); + if (!copy) + return -ENOMEM; + + return search_and_fopen_internal(path, mode, root, copy, _f); +} + +int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f) { + _cleanup_strv_free_ char **s = NULL; + + if (path_is_absolute(path)) { + FILE *f; + + f = fopen(path, mode); + if (f) { + *_f = f; + return 0; + } + + return -errno; + } + + s = strv_split_nulstr(search); + if (!s) + return -ENOMEM; + + return search_and_fopen_internal(path, mode, root, s, _f); +} + +int fopen_temporary(const char *path, FILE **_f, char **_temp_path) { + FILE *f; + char *t; + int r, fd; + + assert(path); + assert(_f); + assert(_temp_path); + + r = tempfn_xxxxxx(path, NULL, &t); + if (r < 0) + return r; + + fd = mkostemp_safe(t, O_WRONLY|O_CLOEXEC); + if (fd < 0) { + free(t); + return -errno; + } + + f = fdopen(fd, "we"); + if (!f) { + unlink_noerrno(t); + free(t); + safe_close(fd); + return -errno; + } + + *_f = f; + *_temp_path = t; + + return 0; +} + +int fflush_and_check(FILE *f) { + assert(f); + + errno = 0; + fflush(f); + + if (ferror(f)) + return errno ? -errno : -EIO; + + return 0; +} + +/* This is much like like mkostemp() but is subject to umask(). */ +int mkostemp_safe(char *pattern, int flags) { + _cleanup_umask_ mode_t u; + int fd; + + assert(pattern); + + u = umask(077); + + fd = mkostemp(pattern, flags); + if (fd < 0) + return -errno; + + return fd; +} + +int open_tmpfile(const char *path, int flags) { + char *p; + int fd; + + assert(path); + +#ifdef O_TMPFILE + /* Try O_TMPFILE first, if it is supported */ + fd = open(path, flags|O_TMPFILE|O_EXCL, S_IRUSR|S_IWUSR); + if (fd >= 0) + return fd; +#endif + + /* Fall back to unguessable name + unlinking */ + p = strjoina(path, "/systemd-tmp-XXXXXX"); + + fd = mkostemp_safe(p, flags); + if (fd < 0) + return fd; + + unlink(p); + return fd; +} + +int tempfn_xxxxxx(const char *p, const char *extra, char **ret) { + const char *fn; + char *t; + + assert(p); + assert(ret); + + /* + * Turns this: + * /foo/bar/waldo + * + * Into this: + * /foo/bar/.#<extra>waldoXXXXXX + */ + + fn = basename(p); + if (!filename_is_valid(fn)) + return -EINVAL; + + if (extra == NULL) + extra = ""; + + t = new(char, strlen(p) + 2 + strlen(extra) + 6 + 1); + if (!t) + return -ENOMEM; + + strcpy(stpcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), ".#"), extra), fn), "XXXXXX"); + + *ret = path_kill_slashes(t); + return 0; +} + +int tempfn_random(const char *p, const char *extra, char **ret) { + const char *fn; + char *t, *x; + uint64_t u; + unsigned i; + + assert(p); + assert(ret); + + /* + * Turns this: + * /foo/bar/waldo + * + * Into this: + * /foo/bar/.#<extra>waldobaa2a261115984a9 + */ + + fn = basename(p); + if (!filename_is_valid(fn)) + return -EINVAL; + + if (!extra) + extra = ""; + + t = new(char, strlen(p) + 2 + strlen(extra) + 16 + 1); + if (!t) + return -ENOMEM; + + x = stpcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), ".#"), extra), fn); + + u = random_u64(); + for (i = 0; i < 16; i++) { + *(x++) = hexchar(u & 0xF); + u >>= 4; + } + + *x = 0; + + *ret = path_kill_slashes(t); + return 0; +} + +int tempfn_random_child(const char *p, const char *extra, char **ret) { + char *t, *x; + uint64_t u; + unsigned i; + + assert(p); + assert(ret); + + /* Turns this: + * /foo/bar/waldo + * Into this: + * /foo/bar/waldo/.#<extra>3c2b6219aa75d7d0 + */ + + if (!extra) + extra = ""; + + t = new(char, strlen(p) + 3 + strlen(extra) + 16 + 1); + if (!t) + return -ENOMEM; + + x = stpcpy(stpcpy(stpcpy(t, p), "/.#"), extra); + + u = random_u64(); + for (i = 0; i < 16; i++) { + *(x++) = hexchar(u & 0xF); + u >>= 4; + } + + *x = 0; + + *ret = path_kill_slashes(t); + return 0; +} diff --git a/src/basic/fileio.h b/src/basic/fileio.h index 4998d4d042..fa7f192331 100644 --- a/src/basic/fileio.h +++ b/src/basic/fileio.h @@ -20,8 +20,12 @@ You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ + +#include <dirent.h> +#include <stdbool.h> #include <stddef.h> #include <stdio.h> +#include <sys/types.h> #include "macro.h" @@ -49,3 +53,27 @@ int write_env_file(const char *fname, char **l); int executable_is_script(const char *path, char **interpreter); int get_proc_field(const char *filename, const char *pattern, const char *terminator, char **field); + +DIR *xopendirat(int dirfd, const char *name, int flags); + +int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f); +int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f); + +#define FOREACH_LINE(line, f, on_error) \ + for (;;) \ + if (!fgets(line, sizeof(line), f)) { \ + if (ferror(f)) { \ + on_error; \ + } \ + break; \ + } else + +int fflush_and_check(FILE *f); + +int fopen_temporary(const char *path, FILE **_f, char **_temp_path); +int mkostemp_safe(char *pattern, int flags); +int open_tmpfile(const char *path, int flags); + +int tempfn_xxxxxx(const char *p, const char *extra, char **ret); +int tempfn_random(const char *p, const char *extra, char **ret); +int tempfn_random_child(const char *p, const char *extra, char **ret); diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c new file mode 100644 index 0000000000..7aee404bfc --- /dev/null +++ b/src/basic/fs-util.c @@ -0,0 +1,480 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include "alloc-util.h" +#include "dirent-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "mkdir.h" +#include "parse-util.h" +#include "path-util.h" +#include "string-util.h" +#include "strv.h" +#include "user-util.h" +#include "util.h" + +int unlink_noerrno(const char *path) { + PROTECT_ERRNO; + int r; + + r = unlink(path); + if (r < 0) + return -errno; + + return 0; +} + +int rmdir_parents(const char *path, const char *stop) { + size_t l; + int r = 0; + + assert(path); + assert(stop); + + l = strlen(path); + + /* Skip trailing slashes */ + while (l > 0 && path[l-1] == '/') + l--; + + while (l > 0) { + char *t; + + /* Skip last component */ + while (l > 0 && path[l-1] != '/') + l--; + + /* Skip trailing slashes */ + while (l > 0 && path[l-1] == '/') + l--; + + if (l <= 0) + break; + + t = strndup(path, l); + if (!t) + return -ENOMEM; + + if (path_startswith(stop, t)) { + free(t); + return 0; + } + + r = rmdir(t); + free(t); + + if (r < 0) + if (errno != ENOENT) + return -errno; + } + + return 0; +} + + +int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) { + struct stat buf; + int ret; + + ret = renameat2(olddirfd, oldpath, newdirfd, newpath, RENAME_NOREPLACE); + if (ret >= 0) + return 0; + + /* renameat2() exists since Linux 3.15, btrfs added support for it later. + * If it is not implemented, fallback to another method. */ + if (!IN_SET(errno, EINVAL, ENOSYS)) + return -errno; + + /* The link()/unlink() fallback does not work on directories. But + * renameat() without RENAME_NOREPLACE gives the same semantics on + * directories, except when newpath is an *empty* directory. This is + * good enough. */ + ret = fstatat(olddirfd, oldpath, &buf, AT_SYMLINK_NOFOLLOW); + if (ret >= 0 && S_ISDIR(buf.st_mode)) { + ret = renameat(olddirfd, oldpath, newdirfd, newpath); + return ret >= 0 ? 0 : -errno; + } + + /* If it is not a directory, use the link()/unlink() fallback. */ + ret = linkat(olddirfd, oldpath, newdirfd, newpath, 0); + if (ret < 0) + return -errno; + + ret = unlinkat(olddirfd, oldpath, 0); + if (ret < 0) { + /* backup errno before the following unlinkat() alters it */ + ret = errno; + (void) unlinkat(newdirfd, newpath, 0); + errno = ret; + return -errno; + } + + return 0; +} + +int readlinkat_malloc(int fd, const char *p, char **ret) { + size_t l = 100; + int r; + + assert(p); + assert(ret); + + for (;;) { + char *c; + ssize_t n; + + c = new(char, l); + if (!c) + return -ENOMEM; + + n = readlinkat(fd, p, c, l-1); + if (n < 0) { + r = -errno; + free(c); + return r; + } + + if ((size_t) n < l-1) { + c[n] = 0; + *ret = c; + return 0; + } + + free(c); + l *= 2; + } +} + +int readlink_malloc(const char *p, char **ret) { + return readlinkat_malloc(AT_FDCWD, p, ret); +} + +int readlink_value(const char *p, char **ret) { + _cleanup_free_ char *link = NULL; + char *value; + int r; + + r = readlink_malloc(p, &link); + if (r < 0) + return r; + + value = basename(link); + if (!value) + return -ENOENT; + + value = strdup(value); + if (!value) + return -ENOMEM; + + *ret = value; + + return 0; +} + +int readlink_and_make_absolute(const char *p, char **r) { + _cleanup_free_ char *target = NULL; + char *k; + int j; + + assert(p); + assert(r); + + j = readlink_malloc(p, &target); + if (j < 0) + return j; + + k = file_in_same_dir(p, target); + if (!k) + return -ENOMEM; + + *r = k; + return 0; +} + +int readlink_and_canonicalize(const char *p, char **r) { + char *t, *s; + int j; + + assert(p); + assert(r); + + j = readlink_and_make_absolute(p, &t); + if (j < 0) + return j; + + s = canonicalize_file_name(t); + if (s) { + free(t); + *r = s; + } else + *r = t; + + path_kill_slashes(*r); + + return 0; +} + +int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) { + assert(path); + + /* Under the assumption that we are running privileged we + * first change the access mode and only then hand out + * ownership to avoid a window where access is too open. */ + + if (mode != MODE_INVALID) + if (chmod(path, mode) < 0) + return -errno; + + if (uid != UID_INVALID || gid != GID_INVALID) + if (chown(path, uid, gid) < 0) + return -errno; + + return 0; +} + +int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid) { + assert(fd >= 0); + + /* Under the assumption that we are running privileged we + * first change the access mode and only then hand out + * ownership to avoid a window where access is too open. */ + + if (mode != MODE_INVALID) + if (fchmod(fd, mode) < 0) + return -errno; + + if (uid != UID_INVALID || gid != GID_INVALID) + if (fchown(fd, uid, gid) < 0) + return -errno; + + return 0; +} + +int fchmod_umask(int fd, mode_t m) { + mode_t u; + int r; + + u = umask(0777); + r = fchmod(fd, m & (~u)) < 0 ? -errno : 0; + umask(u); + + return r; +} + +int fd_warn_permissions(const char *path, int fd) { + struct stat st; + + if (fstat(fd, &st) < 0) + return -errno; + + if (st.st_mode & 0111) + log_warning("Configuration file %s is marked executable. Please remove executable permission bits. Proceeding anyway.", path); + + if (st.st_mode & 0002) + log_warning("Configuration file %s is marked world-writable. Please remove world writability permission bits. Proceeding anyway.", path); + + if (getpid() == 1 && (st.st_mode & 0044) != 0044) + 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); + + return 0; +} + +int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode) { + _cleanup_close_ int fd; + int r; + + assert(path); + + if (parents) + mkdir_parents(path, 0755); + + fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, mode > 0 ? mode : 0644); + if (fd < 0) + return -errno; + + if (mode > 0) { + r = fchmod(fd, mode); + if (r < 0) + return -errno; + } + + if (uid != UID_INVALID || gid != GID_INVALID) { + r = fchown(fd, uid, gid); + if (r < 0) + return -errno; + } + + if (stamp != USEC_INFINITY) { + struct timespec ts[2]; + + timespec_store(&ts[0], stamp); + ts[1] = ts[0]; + r = futimens(fd, ts); + } else + r = futimens(fd, NULL); + if (r < 0) + return -errno; + + return 0; +} + +int touch(const char *path) { + return touch_file(path, false, USEC_INFINITY, UID_INVALID, GID_INVALID, 0); +} + +int symlink_idempotent(const char *from, const char *to) { + _cleanup_free_ char *p = NULL; + int r; + + assert(from); + assert(to); + + if (symlink(from, to) < 0) { + if (errno != EEXIST) + return -errno; + + r = readlink_malloc(to, &p); + if (r < 0) + return r; + + if (!streq(p, from)) + return -EINVAL; + } + + return 0; +} + +int symlink_atomic(const char *from, const char *to) { + _cleanup_free_ char *t = NULL; + int r; + + assert(from); + assert(to); + + r = tempfn_random(to, NULL, &t); + if (r < 0) + return r; + + if (symlink(from, t) < 0) + return -errno; + + if (rename(t, to) < 0) { + unlink_noerrno(t); + return -errno; + } + + return 0; +} + +int mknod_atomic(const char *path, mode_t mode, dev_t dev) { + _cleanup_free_ char *t = NULL; + int r; + + assert(path); + + r = tempfn_random(path, NULL, &t); + if (r < 0) + return r; + + if (mknod(t, mode, dev) < 0) + return -errno; + + if (rename(t, path) < 0) { + unlink_noerrno(t); + return -errno; + } + + return 0; +} + +int mkfifo_atomic(const char *path, mode_t mode) { + _cleanup_free_ char *t = NULL; + int r; + + assert(path); + + r = tempfn_random(path, NULL, &t); + if (r < 0) + return r; + + if (mkfifo(t, mode) < 0) + return -errno; + + if (rename(t, path) < 0) { + unlink_noerrno(t); + return -errno; + } + + return 0; +} + +int get_files_in_directory(const char *path, char ***list) { + _cleanup_closedir_ DIR *d = NULL; + size_t bufsize = 0, n = 0; + _cleanup_strv_free_ char **l = NULL; + + assert(path); + + /* Returns all files in a directory in *list, and the number + * of files as return value. If list is NULL returns only the + * number. */ + + d = opendir(path); + if (!d) + return -errno; + + for (;;) { + struct dirent *de; + + errno = 0; + de = readdir(d); + if (!de && errno != 0) + return -errno; + if (!de) + break; + + dirent_ensure_type(d, de); + + if (!dirent_is_file(de)) + continue; + + if (list) { + /* one extra slot is needed for the terminating NULL */ + if (!GREEDY_REALLOC(l, bufsize, n + 2)) + return -ENOMEM; + + l[n] = strdup(de->d_name); + if (!l[n]) + return -ENOMEM; + + l[++n] = NULL; + } else + n++; + } + + if (list) { + *list = l; + l = NULL; /* avoid freeing */ + } + + return n; +} diff --git a/src/basic/fs-util.h b/src/basic/fs-util.h new file mode 100644 index 0000000000..b94873e65b --- /dev/null +++ b/src/basic/fs-util.h @@ -0,0 +1,74 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <fcntl.h> +#include <sys/inotify.h> +#include <sys/types.h> +#include <unistd.h> +#include <limits.h> + +#include "time-util.h" + +int unlink_noerrno(const char *path); + +int rmdir_parents(const char *path, const char *stop); + +int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath); + +int readlinkat_malloc(int fd, const char *p, char **ret); +int readlink_malloc(const char *p, char **r); +int readlink_value(const char *p, char **ret); +int readlink_and_make_absolute(const char *p, char **r); +int readlink_and_canonicalize(const char *p, char **r); + +int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid); +int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid); + +int fchmod_umask(int fd, mode_t mode); + +int fd_warn_permissions(const char *path, int fd); + +#define laccess(path, mode) faccessat(AT_FDCWD, (path), (mode), AT_SYMLINK_NOFOLLOW) + +int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode); +int touch(const char *path); + +int symlink_idempotent(const char *from, const char *to); + +int symlink_atomic(const char *from, const char *to); +int mknod_atomic(const char *path, mode_t mode, dev_t dev); +int mkfifo_atomic(const char *path, mode_t mode); + +int get_files_in_directory(const char *path, char ***list); + +#define INOTIFY_EVENT_MAX (sizeof(struct inotify_event) + NAME_MAX + 1) + +#define FOREACH_INOTIFY_EVENT(e, buffer, sz) \ + for ((e) = &buffer.ev; \ + (uint8_t*) (e) < (uint8_t*) (buffer.raw) + (sz); \ + (e) = (struct inotify_event*) ((uint8_t*) (e) + sizeof(struct inotify_event) + (e)->len)) + +union inotify_event_buffer { + struct inotify_event ev; + uint8_t raw[INOTIFY_EVENT_MAX]; +}; diff --git a/src/basic/glob-util.c b/src/basic/glob-util.c new file mode 100644 index 0000000000..112c6392e5 --- /dev/null +++ b/src/basic/glob-util.c @@ -0,0 +1,71 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <glob.h> + +#include "glob-util.h" +#include "strv.h" +#include "util.h" + +int glob_exists(const char *path) { + _cleanup_globfree_ glob_t g = {}; + int k; + + assert(path); + + errno = 0; + k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g); + + if (k == GLOB_NOMATCH) + return 0; + if (k == GLOB_NOSPACE) + return -ENOMEM; + if (k != 0) + return errno ? -errno : -EIO; + + return !strv_isempty(g.gl_pathv); +} + +int glob_extend(char ***strv, const char *path) { + _cleanup_globfree_ glob_t g = {}; + int k; + char **p; + + errno = 0; + k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g); + + if (k == GLOB_NOMATCH) + return -ENOENT; + if (k == GLOB_NOSPACE) + return -ENOMEM; + if (k != 0) + return errno ? -errno : -EIO; + if (strv_isempty(g.gl_pathv)) + return -ENOENT; + + STRV_FOREACH(p, g.gl_pathv) { + k = strv_extend(strv, *p); + if (k < 0) + return k; + } + + return 0; +} diff --git a/src/basic/glob-util.h b/src/basic/glob-util.h new file mode 100644 index 0000000000..8817df14b4 --- /dev/null +++ b/src/basic/glob-util.h @@ -0,0 +1,37 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <string.h> + +#include "macro.h" +#include "util.h" + +int glob_exists(const char *path); +int glob_extend(char ***strv, const char *path); + +#define _cleanup_globfree_ _cleanup_(globfree) + +_pure_ static inline bool string_is_glob(const char *p) { + /* Check if a string contains any glob patterns. */ + return !!strpbrk(p, GLOB_CHARS); +} diff --git a/src/basic/hashmap.c b/src/basic/hashmap.c index 20e7e51d9e..4109a08c6c 100644 --- a/src/basic/hashmap.c +++ b/src/basic/hashmap.c @@ -20,18 +20,20 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <stdlib.h> #include <errno.h> #include <pthread.h> +#include <stdlib.h> -#include "util.h" +#include "alloc-util.h" #include "hashmap.h" -#include "set.h" #include "macro.h" -#include "siphash24.h" -#include "strv.h" #include "mempool.h" +#include "process-util.h" #include "random-util.h" +#include "set.h" +#include "siphash24.h" +#include "strv.h" +#include "util.h" #ifdef ENABLE_DEBUG_HASHMAP #include "list.h" diff --git a/src/basic/hexdecoct.c b/src/basic/hexdecoct.c new file mode 100644 index 0000000000..4eb566b15a --- /dev/null +++ b/src/basic/hexdecoct.c @@ -0,0 +1,698 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <ctype.h> +#include <inttypes.h> + +#include "alloc-util.h" +#include "hexdecoct.h" +#include "util.h" + +char octchar(int x) { + return '0' + (x & 7); +} + +int unoctchar(char c) { + + if (c >= '0' && c <= '7') + return c - '0'; + + return -EINVAL; +} + +char decchar(int x) { + return '0' + (x % 10); +} + +int undecchar(char c) { + + if (c >= '0' && c <= '9') + return c - '0'; + + return -EINVAL; +} + +char hexchar(int x) { + static const char table[16] = "0123456789abcdef"; + + return table[x & 15]; +} + +int unhexchar(char c) { + + if (c >= '0' && c <= '9') + return c - '0'; + + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + + return -EINVAL; +} + +char *hexmem(const void *p, size_t l) { + char *r, *z; + const uint8_t *x; + + z = r = malloc(l * 2 + 1); + if (!r) + return NULL; + + for (x = p; x < (const uint8_t*) p + l; x++) { + *(z++) = hexchar(*x >> 4); + *(z++) = hexchar(*x & 15); + } + + *z = 0; + return r; +} + +int unhexmem(const char *p, size_t l, void **mem, size_t *len) { + _cleanup_free_ uint8_t *r = NULL; + uint8_t *z; + const char *x; + + assert(mem); + assert(len); + assert(p); + + z = r = malloc((l + 1) / 2 + 1); + if (!r) + return -ENOMEM; + + for (x = p; x < p + l; x += 2) { + int a, b; + + a = unhexchar(x[0]); + if (a < 0) + return a; + else if (x+1 < p + l) { + b = unhexchar(x[1]); + if (b < 0) + return b; + } else + b = 0; + + *(z++) = (uint8_t) a << 4 | (uint8_t) b; + } + + *z = 0; + + *mem = r; + r = NULL; + *len = (l + 1) / 2; + + return 0; +} + +/* https://tools.ietf.org/html/rfc4648#section-6 + * Notice that base32hex differs from base32 in the alphabet it uses. + * The distinction is that the base32hex representation preserves the + * order of the underlying data when compared as bytestrings, this is + * useful when representing NSEC3 hashes, as one can then verify the + * order of hashes directly from their representation. */ +char base32hexchar(int x) { + static const char table[32] = "0123456789" + "ABCDEFGHIJKLMNOPQRSTUV"; + + return table[x & 31]; +} + +int unbase32hexchar(char c) { + unsigned offset; + + if (c >= '0' && c <= '9') + return c - '0'; + + offset = '9' - '0' + 1; + + if (c >= 'A' && c <= 'V') + return c - 'A' + offset; + + return -EINVAL; +} + +char *base32hexmem(const void *p, size_t l, bool padding) { + char *r, *z; + const uint8_t *x; + size_t len; + + if (padding) + /* five input bytes makes eight output bytes, padding is added so we must round up */ + len = 8 * (l + 4) / 5; + else { + /* same, but round down as there is no padding */ + len = 8 * l / 5; + + switch (l % 5) { + case 4: + len += 7; + break; + case 3: + len += 5; + break; + case 2: + len += 4; + break; + case 1: + len += 2; + break; + } + } + + z = r = malloc(len + 1); + if (!r) + return NULL; + + for (x = p; x < (const uint8_t*) p + (l / 5) * 5; x += 5) { + /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ + x[3] == QQQQQQQQ; x[4] == WWWWWWWW */ + *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */ + *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */ + *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */ + *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */ + *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */ + *(z++) = base32hexchar((x[3] & 127) >> 2); /* 000QQQQQ */ + *(z++) = base32hexchar((x[3] & 3) << 3 | x[4] >> 5); /* 000QQWWW */ + *(z++) = base32hexchar((x[4] & 31)); /* 000WWWWW */ + } + + switch (l % 5) { + case 4: + *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */ + *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */ + *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */ + *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */ + *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */ + *(z++) = base32hexchar((x[3] & 127) >> 2); /* 000QQQQQ */ + *(z++) = base32hexchar((x[3] & 3) << 3); /* 000QQ000 */ + if (padding) + *(z++) = '='; + + break; + + case 3: + *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */ + *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */ + *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */ + *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */ + *(z++) = base32hexchar((x[2] & 15) << 1); /* 000ZZZZ0 */ + if (padding) { + *(z++) = '='; + *(z++) = '='; + *(z++) = '='; + } + + break; + + case 2: + *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */ + *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */ + *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */ + *(z++) = base32hexchar((x[1] & 1) << 4); /* 000Y0000 */ + if (padding) { + *(z++) = '='; + *(z++) = '='; + *(z++) = '='; + *(z++) = '='; + } + + break; + + case 1: + *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */ + *(z++) = base32hexchar((x[0] & 7) << 2); /* 000XXX00 */ + if (padding) { + *(z++) = '='; + *(z++) = '='; + *(z++) = '='; + *(z++) = '='; + *(z++) = '='; + *(z++) = '='; + } + + break; + } + + *z = 0; + return r; +} + +int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *_len) { + _cleanup_free_ uint8_t *r = NULL; + int a, b, c, d, e, f, g, h; + uint8_t *z; + const char *x; + size_t len; + unsigned pad = 0; + + assert(p); + + /* padding ensures any base32hex input has input divisible by 8 */ + if (padding && l % 8 != 0) + return -EINVAL; + + if (padding) { + /* strip the padding */ + while (l > 0 && p[l - 1] == '=' && pad < 7) { + pad ++; + l --; + } + } + + /* a group of eight input bytes needs five output bytes, in case of + padding we need to add some extra bytes */ + len = (l / 8) * 5; + + switch (l % 8) { + case 7: + len += 4; + break; + case 5: + len += 3; + break; + case 4: + len += 2; + break; + case 2: + len += 1; + break; + case 0: + break; + default: + return -EINVAL; + } + + z = r = malloc(len + 1); + if (!r) + return -ENOMEM; + + for (x = p; x < p + (l / 8) * 8; x += 8) { + /* a == 000XXXXX; b == 000YYYYY; c == 000ZZZZZ; d == 000WWWWW + e == 000SSSSS; f == 000QQQQQ; g == 000VVVVV; h == 000RRRRR */ + a = unbase32hexchar(x[0]); + if (a < 0) + return -EINVAL; + + b = unbase32hexchar(x[1]); + if (b < 0) + return -EINVAL; + + c = unbase32hexchar(x[2]); + if (c < 0) + return -EINVAL; + + d = unbase32hexchar(x[3]); + if (d < 0) + return -EINVAL; + + e = unbase32hexchar(x[4]); + if (e < 0) + return -EINVAL; + + f = unbase32hexchar(x[5]); + if (f < 0) + return -EINVAL; + + g = unbase32hexchar(x[6]); + if (g < 0) + return -EINVAL; + + h = unbase32hexchar(x[7]); + if (h < 0) + return -EINVAL; + + *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */ + *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */ + *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */ + *(z++) = (uint8_t) e << 7 | (uint8_t) f << 2 | (uint8_t) g >> 3; /* SQQQQQVV */ + *(z++) = (uint8_t) g << 5 | (uint8_t) h; /* VVVRRRRR */ + } + + switch (l % 8) { + case 7: + a = unbase32hexchar(x[0]); + if (a < 0) + return -EINVAL; + + b = unbase32hexchar(x[1]); + if (b < 0) + return -EINVAL; + + c = unbase32hexchar(x[2]); + if (c < 0) + return -EINVAL; + + d = unbase32hexchar(x[3]); + if (d < 0) + return -EINVAL; + + e = unbase32hexchar(x[4]); + if (e < 0) + return -EINVAL; + + f = unbase32hexchar(x[5]); + if (f < 0) + return -EINVAL; + + g = unbase32hexchar(x[6]); + if (g < 0) + return -EINVAL; + + /* g == 000VV000 */ + if (g & 7) + return -EINVAL; + + *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */ + *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */ + *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */ + *(z++) = (uint8_t) e << 7 | (uint8_t) f << 2 | (uint8_t) g >> 3; /* SQQQQQVV */ + + break; + case 5: + a = unbase32hexchar(x[0]); + if (a < 0) + return -EINVAL; + + b = unbase32hexchar(x[1]); + if (b < 0) + return -EINVAL; + + c = unbase32hexchar(x[2]); + if (c < 0) + return -EINVAL; + + d = unbase32hexchar(x[3]); + if (d < 0) + return -EINVAL; + + e = unbase32hexchar(x[4]); + if (e < 0) + return -EINVAL; + + /* e == 000SSSS0 */ + if (e & 1) + return -EINVAL; + + *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */ + *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */ + *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */ + + break; + case 4: + a = unbase32hexchar(x[0]); + if (a < 0) + return -EINVAL; + + b = unbase32hexchar(x[1]); + if (b < 0) + return -EINVAL; + + c = unbase32hexchar(x[2]); + if (c < 0) + return -EINVAL; + + d = unbase32hexchar(x[3]); + if (d < 0) + return -EINVAL; + + /* d == 000W0000 */ + if (d & 15) + return -EINVAL; + + *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */ + *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */ + + break; + case 2: + a = unbase32hexchar(x[0]); + if (a < 0) + return -EINVAL; + + b = unbase32hexchar(x[1]); + if (b < 0) + return -EINVAL; + + /* b == 000YYY00 */ + if (b & 3) + return -EINVAL; + + *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */ + + break; + case 0: + break; + default: + return -EINVAL; + } + + *z = 0; + + *mem = r; + r = NULL; + *_len = len; + + return 0; +} + +/* https://tools.ietf.org/html/rfc4648#section-4 */ +char base64char(int x) { + static const char table[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + return table[x & 63]; +} + +int unbase64char(char c) { + unsigned offset; + + if (c >= 'A' && c <= 'Z') + return c - 'A'; + + offset = 'Z' - 'A' + 1; + + if (c >= 'a' && c <= 'z') + return c - 'a' + offset; + + offset += 'z' - 'a' + 1; + + if (c >= '0' && c <= '9') + return c - '0' + offset; + + offset += '9' - '0' + 1; + + if (c == '+') + return offset; + + offset ++; + + if (c == '/') + return offset; + + return -EINVAL; +} + +char *base64mem(const void *p, size_t l) { + char *r, *z; + const uint8_t *x; + + /* three input bytes makes four output bytes, padding is added so we must round up */ + z = r = malloc(4 * (l + 2) / 3 + 1); + if (!r) + return NULL; + + for (x = p; x < (const uint8_t*) p + (l / 3) * 3; x += 3) { + /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ */ + *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */ + *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4); /* 00XXYYYY */ + *(z++) = base64char((x[1] & 15) << 2 | x[2] >> 6); /* 00YYYYZZ */ + *(z++) = base64char(x[2] & 63); /* 00ZZZZZZ */ + } + + switch (l % 3) { + case 2: + *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */ + *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4); /* 00XXYYYY */ + *(z++) = base64char((x[1] & 15) << 2); /* 00YYYY00 */ + *(z++) = '='; + + break; + case 1: + *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */ + *(z++) = base64char((x[0] & 3) << 4); /* 00XX0000 */ + *(z++) = '='; + *(z++) = '='; + + break; + } + + *z = 0; + return r; +} + +int unbase64mem(const char *p, size_t l, void **mem, size_t *_len) { + _cleanup_free_ uint8_t *r = NULL; + int a, b, c, d; + uint8_t *z; + const char *x; + size_t len; + + assert(p); + + /* padding ensures any base63 input has input divisible by 4 */ + if (l % 4 != 0) + return -EINVAL; + + /* strip the padding */ + if (l > 0 && p[l - 1] == '=') + l --; + if (l > 0 && p[l - 1] == '=') + l --; + + /* a group of four input bytes needs three output bytes, in case of + padding we need to add two or three extra bytes */ + len = (l / 4) * 3 + (l % 4 ? (l % 4) - 1 : 0); + + z = r = malloc(len + 1); + if (!r) + return -ENOMEM; + + for (x = p; x < p + (l / 4) * 4; x += 4) { + /* a == 00XXXXXX; b == 00YYYYYY; c == 00ZZZZZZ; d == 00WWWWWW */ + a = unbase64char(x[0]); + if (a < 0) + return -EINVAL; + + b = unbase64char(x[1]); + if (b < 0) + return -EINVAL; + + c = unbase64char(x[2]); + if (c < 0) + return -EINVAL; + + d = unbase64char(x[3]); + if (d < 0) + return -EINVAL; + + *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */ + *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */ + *(z++) = (uint8_t) c << 6 | (uint8_t) d; /* ZZWWWWWW */ + } + + switch (l % 4) { + case 3: + a = unbase64char(x[0]); + if (a < 0) + return -EINVAL; + + b = unbase64char(x[1]); + if (b < 0) + return -EINVAL; + + c = unbase64char(x[2]); + if (c < 0) + return -EINVAL; + + /* c == 00ZZZZ00 */ + if (c & 3) + return -EINVAL; + + *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */ + *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */ + + break; + case 2: + a = unbase64char(x[0]); + if (a < 0) + return -EINVAL; + + b = unbase64char(x[1]); + if (b < 0) + return -EINVAL; + + /* b == 00YY0000 */ + if (b & 15) + return -EINVAL; + + *(z++) = (uint8_t) a << 2 | (uint8_t) (b >> 4); /* XXXXXXYY */ + + break; + case 0: + + break; + default: + return -EINVAL; + } + + *z = 0; + + *mem = r; + r = NULL; + *_len = len; + + return 0; +} + +void hexdump(FILE *f, const void *p, size_t s) { + const uint8_t *b = p; + unsigned n = 0; + + assert(s == 0 || b); + + while (s > 0) { + size_t i; + + fprintf(f, "%04x ", n); + + for (i = 0; i < 16; i++) { + + if (i >= s) + fputs(" ", f); + else + fprintf(f, "%02x ", b[i]); + + if (i == 7) + fputc(' ', f); + } + + fputc(' ', f); + + for (i = 0; i < 16; i++) { + + if (i >= s) + fputc(' ', f); + else + fputc(isprint(b[i]) ? (char) b[i] : '.', f); + } + + fputc('\n', f); + + if (s < 16) + break; + + n += 16; + b += 16; + s -= 16; + } +} diff --git a/src/basic/hexdecoct.h b/src/basic/hexdecoct.h new file mode 100644 index 0000000000..4aeb4c3bdc --- /dev/null +++ b/src/basic/hexdecoct.h @@ -0,0 +1,54 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <stdbool.h> +#include <stdio.h> +#include <sys/types.h> + +#include "macro.h" + +char octchar(int x) _const_; +int unoctchar(char c) _const_; + +char decchar(int x) _const_; +int undecchar(char c) _const_; + +char hexchar(int x) _const_; +int unhexchar(char c) _const_; + +char *hexmem(const void *p, size_t l); +int unhexmem(const char *p, size_t l, void **mem, size_t *len); + +char base32hexchar(int x) _const_; +int unbase32hexchar(char c) _const_; + +char base64char(int x) _const_; +int unbase64char(char c) _const_; + +char *base32hexmem(const void *p, size_t l, bool padding); +int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *len); + +char *base64mem(const void *p, size_t l); +int unbase64mem(const char *p, size_t l, void **mem, size_t *len); + +void hexdump(FILE *f, const void *p, size_t s); diff --git a/src/basic/hostname-util.c b/src/basic/hostname-util.c index 7d058416e5..ea0528c6fc 100644 --- a/src/basic/hostname-util.c +++ b/src/basic/hostname-util.c @@ -23,6 +23,7 @@ #include <sys/utsname.h> #include "fd-util.h" +#include "fileio.h" #include "hostname-util.h" #include "string-util.h" #include "util.h" diff --git a/src/basic/in-addr-util.c b/src/basic/in-addr-util.c index d88864b598..f4e24121e7 100644 --- a/src/basic/in-addr-util.c +++ b/src/basic/in-addr-util.c @@ -21,6 +21,7 @@ #include <arpa/inet.h> +#include "alloc-util.h" #include "in-addr-util.h" int in_addr_is_null(int family, const union in_addr_union *u) { diff --git a/src/basic/io-util.h b/src/basic/io-util.h index ff7c2a9ac4..cd2aa75ad2 100644 --- a/src/basic/io-util.h +++ b/src/basic/io-util.h @@ -21,8 +21,9 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <sys/types.h> #include <stdbool.h> +#include <sys/types.h> +#include <sys/uio.h> #include "time-util.h" @@ -37,3 +38,39 @@ int pipe_eof(int fd); int fd_wait_for_event(int fd, int event, usec_t timeout); ssize_t sparse_write(int fd, const void *p, size_t sz, size_t run_length); + +#define IOVEC_SET_STRING(i, s) \ + do { \ + struct iovec *_i = &(i); \ + char *_s = (char *)(s); \ + _i->iov_base = _s; \ + _i->iov_len = strlen(_s); \ + } while(false) + +static inline size_t IOVEC_TOTAL_SIZE(const struct iovec *i, unsigned n) { + unsigned j; + size_t r = 0; + + for (j = 0; j < n; j++) + r += i[j].iov_len; + + return r; +} + +static inline size_t IOVEC_INCREMENT(struct iovec *i, unsigned n, size_t k) { + unsigned j; + + for (j = 0; j < n; j++) { + size_t sub; + + if (_unlikely_(k <= 0)) + break; + + sub = MIN(i[j].iov_len, k); + i[j].iov_len -= sub; + i[j].iov_base = (uint8_t*) i[j].iov_base + sub; + k -= sub; + } + + return k; +} diff --git a/src/basic/json.c b/src/basic/json.c index 2b634aa7f8..716705e5ff 100644 --- a/src/basic/json.c +++ b/src/basic/json.c @@ -22,10 +22,12 @@ #include <math.h> #include <sys/types.h> +#include "alloc-util.h" +#include "json.h" #include "macro.h" +#include "hexdecoct.h" #include "string-util.h" #include "utf8.h" -#include "json.h" int json_variant_new(JsonVariant **ret, JsonVariantType type) { JsonVariant *v; diff --git a/src/basic/locale-util.c b/src/basic/locale-util.c index 44e1628664..b87fd7670b 100644 --- a/src/basic/locale-util.c +++ b/src/basic/locale-util.c @@ -19,11 +19,16 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include <langinfo.h> +#include <locale.h> #include <sys/mman.h> +#include "dirent-util.h" #include "fd-util.h" #include "locale-util.h" +#include "path-util.h" #include "set.h" +#include "string-table.h" #include "string-util.h" #include "strv.h" #include "utf8.h" @@ -205,6 +210,88 @@ bool locale_is_valid(const char *name) { return true; } +void init_gettext(void) { + setlocale(LC_ALL, ""); + textdomain(GETTEXT_PACKAGE); +} + +bool is_locale_utf8(void) { + const char *set; + static int cached_answer = -1; + + /* Note that we default to 'true' here, since today UTF8 is + * pretty much supported everywhere. */ + + if (cached_answer >= 0) + goto out; + + if (!setlocale(LC_ALL, "")) { + cached_answer = true; + goto out; + } + + set = nl_langinfo(CODESET); + if (!set) { + cached_answer = true; + goto out; + } + + if (streq(set, "UTF-8")) { + cached_answer = true; + goto out; + } + + /* For LC_CTYPE=="C" return true, because CTYPE is effectly + * unset and everything can do to UTF-8 nowadays. */ + set = setlocale(LC_CTYPE, NULL); + if (!set) { + cached_answer = true; + goto out; + } + + /* Check result, but ignore the result if C was set + * explicitly. */ + cached_answer = + STR_IN_SET(set, "C", "POSIX") && + !getenv("LC_ALL") && + !getenv("LC_CTYPE") && + !getenv("LANG"); + +out: + return (bool) cached_answer; +} + + +const char *draw_special_char(DrawSpecialChar ch) { + + static const char *draw_table[2][_DRAW_SPECIAL_CHAR_MAX] = { + + /* UTF-8 */ { + [DRAW_TREE_VERTICAL] = "\342\224\202 ", /* │ */ + [DRAW_TREE_BRANCH] = "\342\224\234\342\224\200", /* ├─ */ + [DRAW_TREE_RIGHT] = "\342\224\224\342\224\200", /* └─ */ + [DRAW_TREE_SPACE] = " ", /* */ + [DRAW_TRIANGULAR_BULLET] = "\342\200\243", /* ‣ */ + [DRAW_BLACK_CIRCLE] = "\342\227\217", /* ● */ + [DRAW_ARROW] = "\342\206\222", /* → */ + [DRAW_DASH] = "\342\200\223", /* – */ + }, + + /* ASCII fallback */ { + [DRAW_TREE_VERTICAL] = "| ", + [DRAW_TREE_BRANCH] = "|-", + [DRAW_TREE_RIGHT] = "`-", + [DRAW_TREE_SPACE] = " ", + [DRAW_TRIANGULAR_BULLET] = ">", + [DRAW_BLACK_CIRCLE] = "*", + [DRAW_ARROW] = "->", + [DRAW_DASH] = "-", + } + }; + + return draw_table[!is_locale_utf8()][ch]; +} + static const char * const locale_variable_table[_VARIABLE_LC_MAX] = { [VARIABLE_LANG] = "LANG", [VARIABLE_LANGUAGE] = "LANGUAGE", diff --git a/src/basic/locale-util.h b/src/basic/locale-util.h index e48aa3d9af..c71d145139 100644 --- a/src/basic/locale-util.h +++ b/src/basic/locale-util.h @@ -21,6 +21,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include <libintl.h> #include <stdbool.h> #include "macro.h" @@ -50,5 +51,25 @@ typedef enum LocaleVariable { int get_locales(char ***l); bool locale_is_valid(const char *name); +#define _(String) gettext(String) +#define N_(String) String +void init_gettext(void); + +bool is_locale_utf8(void); + +typedef enum DrawSpecialChar { + DRAW_TREE_VERTICAL, + DRAW_TREE_BRANCH, + DRAW_TREE_RIGHT, + DRAW_TREE_SPACE, + DRAW_TRIANGULAR_BULLET, + DRAW_BLACK_CIRCLE, + DRAW_ARROW, + DRAW_DASH, + _DRAW_SPECIAL_CHAR_MAX +} DrawSpecialChar; + +const char *draw_special_char(DrawSpecialChar ch); + const char* locale_variable_to_string(LocaleVariable i) _const_; LocaleVariable locale_variable_from_string(const char *s) _pure_; diff --git a/src/basic/lockfile-util.c b/src/basic/lockfile-util.c index e573dcb56f..87c3aef7af 100644 --- a/src/basic/lockfile-util.c +++ b/src/basic/lockfile-util.c @@ -27,9 +27,12 @@ #include <limits.h> #include <sys/file.h> +#include "alloc-util.h" #include "fd-util.h" #include "fileio.h" +#include "fs-util.h" #include "lockfile-util.h" +#include "path-util.h" #include "util.h" int make_lock_file(const char *p, int operation, LockFile *ret) { diff --git a/src/basic/log.c b/src/basic/log.c index 99dccb1f10..1582fce61c 100644 --- a/src/basic/log.c +++ b/src/basic/log.c @@ -31,15 +31,22 @@ #include "sd-messages.h" +#include "alloc-util.h" #include "fd-util.h" #include "formats-util.h" +#include "io-util.h" #include "log.h" #include "macro.h" #include "missing.h" +#include "parse-util.h" +#include "proc-cmdline.h" #include "process-util.h" #include "signal-util.h" #include "socket-util.h" +#include "stdio-util.h" +#include "string-table.h" #include "string-util.h" +#include "syslog-util.h" #include "terminal-util.h" #include "util.h" diff --git a/src/basic/macro.h b/src/basic/macro.h index f55d65e2f1..daa7c416f7 100644 --- a/src/basic/macro.h +++ b/src/basic/macro.h @@ -22,11 +22,10 @@ ***/ #include <assert.h> -#include <sys/param.h> -#include <sys/types.h> -#include <sys/uio.h> #include <inttypes.h> #include <stdbool.h> +#include <sys/param.h> +#include <sys/types.h> #define _printf_(a,b) __attribute__ ((format (printf, a, b))) #define _alloc_(...) __attribute__ ((alloc_size(__VA_ARGS__))) @@ -295,111 +294,10 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) { #define PTR_TO_SIZE(p) ((size_t) ((uintptr_t) (p))) #define SIZE_TO_PTR(u) ((void *) ((uintptr_t) (u))) -/* The following macros add 1 when converting things, since UID 0 is a - * valid UID, while the pointer NULL is special */ -#define PTR_TO_UID(p) ((uid_t) (((uintptr_t) (p))-1)) -#define UID_TO_PTR(u) ((void*) (((uintptr_t) (u))+1)) - -#define PTR_TO_GID(p) ((gid_t) (((uintptr_t) (p))-1)) -#define GID_TO_PTR(u) ((void*) (((uintptr_t) (u))+1)) - -#define PTR_TO_PID(p) ((pid_t) ((uintptr_t) p)) -#define PID_TO_PTR(p) ((void*) ((uintptr_t) p)) - -#define memzero(x,l) (memset((x), 0, (l))) -#define zero(x) (memzero(&(x), sizeof(x))) - #define CHAR_TO_STR(x) ((char[2]) { x, 0 }) #define char_array_0(x) x[sizeof(x)-1] = 0; -#define IOVEC_SET_STRING(i, s) \ - do { \ - struct iovec *_i = &(i); \ - char *_s = (char *)(s); \ - _i->iov_base = _s; \ - _i->iov_len = strlen(_s); \ - } while(false) - -static inline size_t IOVEC_TOTAL_SIZE(const struct iovec *i, unsigned n) { - unsigned j; - size_t r = 0; - - for (j = 0; j < n; j++) - r += i[j].iov_len; - - return r; -} - -static inline size_t IOVEC_INCREMENT(struct iovec *i, unsigned n, size_t k) { - unsigned j; - - for (j = 0; j < n; j++) { - size_t sub; - - if (_unlikely_(k <= 0)) - break; - - sub = MIN(i[j].iov_len, k); - i[j].iov_len -= sub; - i[j].iov_base = (uint8_t*) i[j].iov_base + sub; - k -= sub; - } - - return k; -} - -#define VA_FORMAT_ADVANCE(format, ap) \ -do { \ - int _argtypes[128]; \ - size_t _i, _k; \ - _k = parse_printf_format((format), ELEMENTSOF(_argtypes), _argtypes); \ - assert(_k < ELEMENTSOF(_argtypes)); \ - for (_i = 0; _i < _k; _i++) { \ - if (_argtypes[_i] & PA_FLAG_PTR) { \ - (void) va_arg(ap, void*); \ - continue; \ - } \ - \ - switch (_argtypes[_i]) { \ - case PA_INT: \ - case PA_INT|PA_FLAG_SHORT: \ - case PA_CHAR: \ - (void) va_arg(ap, int); \ - break; \ - case PA_INT|PA_FLAG_LONG: \ - (void) va_arg(ap, long int); \ - break; \ - case PA_INT|PA_FLAG_LONG_LONG: \ - (void) va_arg(ap, long long int); \ - break; \ - case PA_WCHAR: \ - (void) va_arg(ap, wchar_t); \ - break; \ - case PA_WSTRING: \ - case PA_STRING: \ - case PA_POINTER: \ - (void) va_arg(ap, void*); \ - break; \ - case PA_FLOAT: \ - case PA_DOUBLE: \ - (void) va_arg(ap, double); \ - break; \ - case PA_DOUBLE|PA_FLAG_LONG_DOUBLE: \ - (void) va_arg(ap, long double); \ - break; \ - default: \ - assert_not_reached("Unknown format string argument."); \ - } \ - } \ -} while(false) - - /* Because statfs.t_type can be int on some architectures, we have to cast - * the const magic to the type, otherwise the compiler warns about - * signed/unsigned comparison, because the magic can be 32 bit unsigned. - */ -#define F_TYPE_EQUAL(a, b) (a == (typeof(a)) b) - /* Returns the number of chars needed to format variables of the * specified type as a decimal string. Adds in extra space for a * negative '-' prefix (hence works correctly on signed @@ -410,6 +308,15 @@ do { \ sizeof(type) <= 4 ? 10 : \ sizeof(type) <= 8 ? 20 : sizeof(int[-2*(sizeof(type) > 8)]))) +#define DECIMAL_STR_WIDTH(x) \ + ({ \ + typeof(x) _x_ = (x); \ + unsigned ans = 1; \ + while (_x_ /= 10) \ + ans++; \ + ans; \ + }) + #define SET_FLAG(v, flag, b) \ (v) = (b) ? ((v) | (flag)) : ((v) & ~(flag)) @@ -466,10 +373,6 @@ do { \ #endif #endif -#define UID_INVALID ((uid_t) -1) -#define GID_INVALID ((gid_t) -1) -#define MODE_INVALID ((mode_t) -1) - #define DEFINE_TRIVIAL_CLEANUP_FUNC(type, func) \ static inline void func##p(type *p) { \ if (*p) \ @@ -477,7 +380,4 @@ do { \ } \ struct __useless_struct_to_allow_trailing_semicolon__ -#define CMSG_FOREACH(cmsg, mh) \ - for ((cmsg) = CMSG_FIRSTHDR(mh); (cmsg); (cmsg) = CMSG_NXTHDR((mh), (cmsg))) - #include "log.h" diff --git a/src/basic/memfd-util.c b/src/basic/memfd-util.c index 9d638b27f0..92630f6b25 100644 --- a/src/basic/memfd-util.c +++ b/src/basic/memfd-util.c @@ -27,6 +27,7 @@ #include <sys/mman.h> #include <sys/prctl.h> +#include "alloc-util.h" #include "fd-util.h" #include "memfd-util.h" #include "missing.h" diff --git a/src/basic/mkdir.c b/src/basic/mkdir.c index 7ee4546988..0214c4627e 100644 --- a/src/basic/mkdir.c +++ b/src/basic/mkdir.c @@ -22,9 +22,12 @@ #include <string.h> #include <errno.h> -#include "util.h" -#include "path-util.h" +#include "fs-util.h" #include "mkdir.h" +#include "path-util.h" +#include "stat-util.h" +#include "user-util.h" +#include "util.h" int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, mkdir_func_t _mkdir) { struct stat st; diff --git a/src/basic/mount-util.c b/src/basic/mount-util.c new file mode 100644 index 0000000000..29997b1ce7 --- /dev/null +++ b/src/basic/mount-util.c @@ -0,0 +1,529 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <string.h> +#include <sys/mount.h> +#include <sys/statvfs.h> + +#include "alloc-util.h" +#include "escape.h" +#include "fd-util.h" +#include "fileio.h" +#include "mount-util.h" +#include "parse-util.h" +#include "path-util.h" +#include "set.h" +#include "stdio-util.h" +#include "string-util.h" +#include "util.h" + +static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *mnt_id) { + char path[strlen("/proc/self/fdinfo/") + DECIMAL_STR_MAX(int)]; + _cleanup_free_ char *fdinfo = NULL; + _cleanup_close_ int subfd = -1; + char *p; + int r; + + if ((flags & AT_EMPTY_PATH) && isempty(filename)) + xsprintf(path, "/proc/self/fdinfo/%i", fd); + else { + subfd = openat(fd, filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH); + if (subfd < 0) + return -errno; + + xsprintf(path, "/proc/self/fdinfo/%i", subfd); + } + + r = read_full_file(path, &fdinfo, NULL); + if (r == -ENOENT) /* The fdinfo directory is a relatively new addition */ + return -EOPNOTSUPP; + if (r < 0) + return -errno; + + p = startswith(fdinfo, "mnt_id:"); + if (!p) { + p = strstr(fdinfo, "\nmnt_id:"); + if (!p) /* The mnt_id field is a relatively new addition */ + return -EOPNOTSUPP; + + p += 8; + } + + p += strspn(p, WHITESPACE); + p[strcspn(p, WHITESPACE)] = 0; + + return safe_atoi(p, mnt_id); +} + + +int fd_is_mount_point(int fd, const char *filename, int flags) { + union file_handle_union h = FILE_HANDLE_INIT, h_parent = FILE_HANDLE_INIT; + int mount_id = -1, mount_id_parent = -1; + bool nosupp = false, check_st_dev = true; + struct stat a, b; + int r; + + assert(fd >= 0); + assert(filename); + + /* First we will try the name_to_handle_at() syscall, which + * tells us the mount id and an opaque file "handle". It is + * not supported everywhere though (kernel compile-time + * option, not all file systems are hooked up). If it works + * the mount id is usually good enough to tell us whether + * something is a mount point. + * + * If that didn't work we will try to read the mount id from + * /proc/self/fdinfo/<fd>. This is almost as good as + * name_to_handle_at(), however, does not return the + * opaque file handle. The opaque file handle is pretty useful + * to detect the root directory, which we should always + * consider a mount point. Hence we use this only as + * fallback. Exporting the mnt_id in fdinfo is a pretty recent + * kernel addition. + * + * As last fallback we do traditional fstat() based st_dev + * comparisons. This is how things were traditionally done, + * but unionfs breaks breaks this since it exposes file + * systems with a variety of st_dev reported. Also, btrfs + * subvolumes have different st_dev, even though they aren't + * real mounts of their own. */ + + r = name_to_handle_at(fd, filename, &h.handle, &mount_id, flags); + if (r < 0) { + if (errno == ENOSYS) + /* This kernel does not support name_to_handle_at() + * fall back to simpler logic. */ + goto fallback_fdinfo; + else if (errno == EOPNOTSUPP) + /* This kernel or file system does not support + * name_to_handle_at(), hence let's see if the + * upper fs supports it (in which case it is a + * mount point), otherwise fallback to the + * traditional stat() logic */ + nosupp = true; + else + return -errno; + } + + r = name_to_handle_at(fd, "", &h_parent.handle, &mount_id_parent, AT_EMPTY_PATH); + if (r < 0) { + if (errno == EOPNOTSUPP) { + if (nosupp) + /* Neither parent nor child do name_to_handle_at()? + We have no choice but to fall back. */ + goto fallback_fdinfo; + else + /* The parent can't do name_to_handle_at() but the + * directory we are interested in can? + * If so, it must be a mount point. */ + return 1; + } else + return -errno; + } + + /* The parent can do name_to_handle_at() but the + * directory we are interested in can't? If so, it + * must be a mount point. */ + if (nosupp) + return 1; + + /* If the file handle for the directory we are + * interested in and its parent are identical, we + * assume this is the root directory, which is a mount + * point. */ + + if (h.handle.handle_bytes == h_parent.handle.handle_bytes && + h.handle.handle_type == h_parent.handle.handle_type && + memcmp(h.handle.f_handle, h_parent.handle.f_handle, h.handle.handle_bytes) == 0) + return 1; + + return mount_id != mount_id_parent; + +fallback_fdinfo: + r = fd_fdinfo_mnt_id(fd, filename, flags, &mount_id); + if (r == -EOPNOTSUPP) + goto fallback_fstat; + if (r < 0) + return r; + + r = fd_fdinfo_mnt_id(fd, "", AT_EMPTY_PATH, &mount_id_parent); + if (r < 0) + return r; + + if (mount_id != mount_id_parent) + return 1; + + /* Hmm, so, the mount ids are the same. This leaves one + * special case though for the root file system. For that, + * let's see if the parent directory has the same inode as we + * are interested in. Hence, let's also do fstat() checks now, + * too, but avoid the st_dev comparisons, since they aren't + * that useful on unionfs mounts. */ + check_st_dev = false; + +fallback_fstat: + /* yay for fstatat() taking a different set of flags than the other + * _at() above */ + if (flags & AT_SYMLINK_FOLLOW) + flags &= ~AT_SYMLINK_FOLLOW; + else + flags |= AT_SYMLINK_NOFOLLOW; + if (fstatat(fd, filename, &a, flags) < 0) + return -errno; + + if (fstatat(fd, "", &b, AT_EMPTY_PATH) < 0) + return -errno; + + /* A directory with same device and inode as its parent? Must + * be the root directory */ + if (a.st_dev == b.st_dev && + a.st_ino == b.st_ino) + return 1; + + return check_st_dev && (a.st_dev != b.st_dev); +} + +/* flags can be AT_SYMLINK_FOLLOW or 0 */ +int path_is_mount_point(const char *t, int flags) { + _cleanup_close_ int fd = -1; + _cleanup_free_ char *canonical = NULL, *parent = NULL; + + assert(t); + + if (path_equal(t, "/")) + return 1; + + /* we need to resolve symlinks manually, we can't just rely on + * fd_is_mount_point() to do that for us; if we have a structure like + * /bin -> /usr/bin/ and /usr is a mount point, then the parent that we + * look at needs to be /usr, not /. */ + if (flags & AT_SYMLINK_FOLLOW) { + canonical = canonicalize_file_name(t); + if (!canonical) + return -errno; + + t = canonical; + } + + parent = dirname_malloc(t); + if (!parent) + return -ENOMEM; + + fd = openat(AT_FDCWD, parent, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_PATH); + if (fd < 0) + return -errno; + + return fd_is_mount_point(fd, basename(t), flags); +} + +int umount_recursive(const char *prefix, int flags) { + bool again; + int n = 0, r; + + /* Try to umount everything recursively below a + * directory. Also, take care of stacked mounts, and keep + * unmounting them until they are gone. */ + + do { + _cleanup_fclose_ FILE *proc_self_mountinfo = NULL; + + again = false; + r = 0; + + proc_self_mountinfo = fopen("/proc/self/mountinfo", "re"); + if (!proc_self_mountinfo) + return -errno; + + for (;;) { + _cleanup_free_ char *path = NULL, *p = NULL; + int k; + + k = fscanf(proc_self_mountinfo, + "%*s " /* (1) mount id */ + "%*s " /* (2) parent id */ + "%*s " /* (3) major:minor */ + "%*s " /* (4) root */ + "%ms " /* (5) mount point */ + "%*s" /* (6) mount options */ + "%*[^-]" /* (7) optional fields */ + "- " /* (8) separator */ + "%*s " /* (9) file system type */ + "%*s" /* (10) mount source */ + "%*s" /* (11) mount options 2 */ + "%*[^\n]", /* some rubbish at the end */ + &path); + if (k != 1) { + if (k == EOF) + break; + + continue; + } + + r = cunescape(path, UNESCAPE_RELAX, &p); + if (r < 0) + return r; + + if (!path_startswith(p, prefix)) + continue; + + if (umount2(p, flags) < 0) { + r = -errno; + continue; + } + + again = true; + n++; + + break; + } + + } while (again); + + return r ? r : n; +} + +static int get_mount_flags(const char *path, unsigned long *flags) { + struct statvfs buf; + + if (statvfs(path, &buf) < 0) + return -errno; + *flags = buf.f_flag; + return 0; +} + +int bind_remount_recursive(const char *prefix, bool ro) { + _cleanup_set_free_free_ Set *done = NULL; + _cleanup_free_ char *cleaned = NULL; + int r; + + /* Recursively remount a directory (and all its submounts) + * read-only or read-write. If the directory is already + * mounted, we reuse the mount and simply mark it + * MS_BIND|MS_RDONLY (or remove the MS_RDONLY for read-write + * operation). If it isn't we first make it one. Afterwards we + * apply MS_BIND|MS_RDONLY (or remove MS_RDONLY) to all + * submounts we can access, too. When mounts are stacked on + * the same mount point we only care for each individual + * "top-level" mount on each point, as we cannot + * influence/access the underlying mounts anyway. We do not + * have any effect on future submounts that might get + * propagated, they migt be writable. This includes future + * submounts that have been triggered via autofs. */ + + cleaned = strdup(prefix); + if (!cleaned) + return -ENOMEM; + + path_kill_slashes(cleaned); + + done = set_new(&string_hash_ops); + if (!done) + return -ENOMEM; + + for (;;) { + _cleanup_fclose_ FILE *proc_self_mountinfo = NULL; + _cleanup_set_free_free_ Set *todo = NULL; + bool top_autofs = false; + char *x; + unsigned long orig_flags; + + todo = set_new(&string_hash_ops); + if (!todo) + return -ENOMEM; + + proc_self_mountinfo = fopen("/proc/self/mountinfo", "re"); + if (!proc_self_mountinfo) + return -errno; + + for (;;) { + _cleanup_free_ char *path = NULL, *p = NULL, *type = NULL; + int k; + + k = fscanf(proc_self_mountinfo, + "%*s " /* (1) mount id */ + "%*s " /* (2) parent id */ + "%*s " /* (3) major:minor */ + "%*s " /* (4) root */ + "%ms " /* (5) mount point */ + "%*s" /* (6) mount options (superblock) */ + "%*[^-]" /* (7) optional fields */ + "- " /* (8) separator */ + "%ms " /* (9) file system type */ + "%*s" /* (10) mount source */ + "%*s" /* (11) mount options (bind mount) */ + "%*[^\n]", /* some rubbish at the end */ + &path, + &type); + if (k != 2) { + if (k == EOF) + break; + + continue; + } + + r = cunescape(path, UNESCAPE_RELAX, &p); + if (r < 0) + return r; + + /* Let's ignore autofs mounts. If they aren't + * triggered yet, we want to avoid triggering + * them, as we don't make any guarantees for + * future submounts anyway. If they are + * already triggered, then we will find + * another entry for this. */ + if (streq(type, "autofs")) { + top_autofs = top_autofs || path_equal(cleaned, p); + continue; + } + + if (path_startswith(p, cleaned) && + !set_contains(done, p)) { + + r = set_consume(todo, p); + p = NULL; + + if (r == -EEXIST) + continue; + if (r < 0) + return r; + } + } + + /* If we have no submounts to process anymore and if + * the root is either already done, or an autofs, we + * are done */ + if (set_isempty(todo) && + (top_autofs || set_contains(done, cleaned))) + return 0; + + if (!set_contains(done, cleaned) && + !set_contains(todo, cleaned)) { + /* The prefix directory itself is not yet a + * mount, make it one. */ + if (mount(cleaned, cleaned, NULL, MS_BIND|MS_REC, NULL) < 0) + return -errno; + + orig_flags = 0; + (void) get_mount_flags(cleaned, &orig_flags); + orig_flags &= ~MS_RDONLY; + + if (mount(NULL, prefix, NULL, orig_flags|MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0) + return -errno; + + x = strdup(cleaned); + if (!x) + return -ENOMEM; + + r = set_consume(done, x); + if (r < 0) + return r; + } + + while ((x = set_steal_first(todo))) { + + r = set_consume(done, x); + if (r == -EEXIST || r == 0) + continue; + if (r < 0) + return r; + + /* Try to reuse the original flag set, but + * don't care for errors, in case of + * obstructed mounts */ + orig_flags = 0; + (void) get_mount_flags(x, &orig_flags); + orig_flags &= ~MS_RDONLY; + + if (mount(NULL, x, NULL, orig_flags|MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0) { + + /* Deal with mount points that are + * obstructed by a later mount */ + + if (errno != ENOENT) + return -errno; + } + + } + } +} + +int mount_move_root(const char *path) { + assert(path); + + if (chdir(path) < 0) + return -errno; + + if (mount(path, "/", NULL, MS_MOVE, NULL) < 0) + return -errno; + + if (chroot(".") < 0) + return -errno; + + if (chdir("/") < 0) + return -errno; + + return 0; +} + +bool fstype_is_network(const char *fstype) { + static const char table[] = + "afs\0" + "cifs\0" + "smbfs\0" + "sshfs\0" + "ncpfs\0" + "ncp\0" + "nfs\0" + "nfs4\0" + "gfs\0" + "gfs2\0" + "glusterfs\0"; + + const char *x; + + x = startswith(fstype, "fuse."); + if (x) + fstype = x; + + return nulstr_contains(table, fstype); +} + +int repeat_unmount(const char *path, int flags) { + bool done = false; + + assert(path); + + /* If there are multiple mounts on a mount point, this + * removes them all */ + + for (;;) { + if (umount2(path, flags) < 0) { + + if (errno == EINVAL) + return done; + + return -errno; + } + + done = true; + } +} diff --git a/src/basic/mount-util.h b/src/basic/mount-util.h new file mode 100644 index 0000000000..48954c2d67 --- /dev/null +++ b/src/basic/mount-util.h @@ -0,0 +1,52 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <fcntl.h> +#include <mntent.h> +#include <stdbool.h> +#include <sys/stat.h> +#include <sys/types.h> + +#include "missing.h" + +int fd_is_mount_point(int fd, const char *filename, int flags); +int path_is_mount_point(const char *path, int flags); + +int repeat_unmount(const char *path, int flags); + +int umount_recursive(const char *target, int flags); +int bind_remount_recursive(const char *prefix, bool ro); + +int mount_move_root(const char *path); + +DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, endmntent); +#define _cleanup_endmntent_ _cleanup_(endmntentp) + +bool fstype_is_network(const char *fstype); + +union file_handle_union { + struct file_handle handle; + char padding[sizeof(struct file_handle) + MAX_HANDLE_SZ]; +}; + +#define FILE_HANDLE_INIT { .handle.handle_bytes = MAX_HANDLE_SZ } diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c new file mode 100644 index 0000000000..1ee5783680 --- /dev/null +++ b/src/basic/parse-util.c @@ -0,0 +1,447 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include "alloc-util.h" +#include "extract-word.h" +#include "parse-util.h" +#include "string-util.h" +#include "util.h" + +int parse_boolean(const char *v) { + assert(v); + + if (streq(v, "1") || strcaseeq(v, "yes") || strcaseeq(v, "y") || strcaseeq(v, "true") || strcaseeq(v, "t") || strcaseeq(v, "on")) + return 1; + else if (streq(v, "0") || strcaseeq(v, "no") || strcaseeq(v, "n") || strcaseeq(v, "false") || strcaseeq(v, "f") || strcaseeq(v, "off")) + return 0; + + return -EINVAL; +} + +int parse_pid(const char *s, pid_t* ret_pid) { + unsigned long ul = 0; + pid_t pid; + int r; + + assert(s); + assert(ret_pid); + + r = safe_atolu(s, &ul); + if (r < 0) + return r; + + pid = (pid_t) ul; + + if ((unsigned long) pid != ul) + return -ERANGE; + + if (pid <= 0) + return -ERANGE; + + *ret_pid = pid; + return 0; +} + +int parse_mode(const char *s, mode_t *ret) { + char *x; + long l; + + assert(s); + assert(ret); + + errno = 0; + l = strtol(s, &x, 8); + if (errno != 0) + return -errno; + + if (!x || x == s || *x) + return -EINVAL; + if (l < 0 || l > 07777) + return -ERANGE; + + *ret = (mode_t) l; + return 0; +} + +int parse_size(const char *t, uint64_t base, uint64_t *size) { + + /* Soo, sometimes we want to parse IEC binary suffixes, and + * sometimes SI decimal suffixes. This function can parse + * both. Which one is the right way depends on the + * context. Wikipedia suggests that SI is customary for + * hardware metrics and network speeds, while IEC is + * customary for most data sizes used by software and volatile + * (RAM) memory. Hence be careful which one you pick! + * + * In either case we use just K, M, G as suffix, and not Ki, + * Mi, Gi or so (as IEC would suggest). That's because that's + * frickin' ugly. But this means you really need to make sure + * to document which base you are parsing when you use this + * call. */ + + struct table { + const char *suffix; + unsigned long long factor; + }; + + static const struct table iec[] = { + { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL }, + { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL }, + { "T", 1024ULL*1024ULL*1024ULL*1024ULL }, + { "G", 1024ULL*1024ULL*1024ULL }, + { "M", 1024ULL*1024ULL }, + { "K", 1024ULL }, + { "B", 1ULL }, + { "", 1ULL }, + }; + + static const struct table si[] = { + { "E", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL*1000ULL }, + { "P", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL }, + { "T", 1000ULL*1000ULL*1000ULL*1000ULL }, + { "G", 1000ULL*1000ULL*1000ULL }, + { "M", 1000ULL*1000ULL }, + { "K", 1000ULL }, + { "B", 1ULL }, + { "", 1ULL }, + }; + + const struct table *table; + const char *p; + unsigned long long r = 0; + unsigned n_entries, start_pos = 0; + + assert(t); + assert(base == 1000 || base == 1024); + assert(size); + + if (base == 1000) { + table = si; + n_entries = ELEMENTSOF(si); + } else { + table = iec; + n_entries = ELEMENTSOF(iec); + } + + p = t; + do { + unsigned long long l, tmp; + double frac = 0; + char *e; + unsigned i; + + p += strspn(p, WHITESPACE); + if (*p == '-') + return -ERANGE; + + errno = 0; + l = strtoull(p, &e, 10); + if (errno > 0) + return -errno; + if (e == p) + return -EINVAL; + + if (*e == '.') { + e++; + + /* strtoull() itself would accept space/+/- */ + if (*e >= '0' && *e <= '9') { + unsigned long long l2; + char *e2; + + l2 = strtoull(e, &e2, 10); + if (errno > 0) + return -errno; + + /* Ignore failure. E.g. 10.M is valid */ + frac = l2; + for (; e < e2; e++) + frac /= 10; + } + } + + e += strspn(e, WHITESPACE); + + for (i = start_pos; i < n_entries; i++) + if (startswith(e, table[i].suffix)) + break; + + if (i >= n_entries) + return -EINVAL; + + if (l + (frac > 0) > ULLONG_MAX / table[i].factor) + return -ERANGE; + + tmp = l * table[i].factor + (unsigned long long) (frac * table[i].factor); + if (tmp > ULLONG_MAX - r) + return -ERANGE; + + r += tmp; + if ((unsigned long long) (uint64_t) r != r) + return -ERANGE; + + p = e + strlen(table[i].suffix); + + start_pos = i + 1; + + } while (*p); + + *size = r; + + return 0; +} + +int parse_range(const char *t, unsigned *lower, unsigned *upper) { + _cleanup_free_ char *word = NULL; + unsigned l, u; + int r; + + assert(lower); + assert(upper); + + /* Extract the lower bound. */ + r = extract_first_word(&t, &word, "-", EXTRACT_DONT_COALESCE_SEPARATORS); + if (r < 0) + return r; + if (r == 0) + return -EINVAL; + + r = safe_atou(word, &l); + if (r < 0) + return r; + + /* Check for the upper bound and extract it if needed */ + if (!t) + /* Single number with no dashes. */ + u = l; + else if (!*t) + /* Trailing dash is an error. */ + return -EINVAL; + else { + r = safe_atou(t, &u); + if (r < 0) + return r; + } + + *lower = l; + *upper = u; + return 0; +} + +char *format_bytes(char *buf, size_t l, uint64_t t) { + unsigned i; + + /* This only does IEC units so far */ + + static const struct { + const char *suffix; + uint64_t factor; + } table[] = { + { "E", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) }, + { "P", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) }, + { "T", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) }, + { "G", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) }, + { "M", UINT64_C(1024)*UINT64_C(1024) }, + { "K", UINT64_C(1024) }, + }; + + if (t == (uint64_t) -1) + return NULL; + + for (i = 0; i < ELEMENTSOF(table); i++) { + + if (t >= table[i].factor) { + snprintf(buf, l, + "%" PRIu64 ".%" PRIu64 "%s", + t / table[i].factor, + ((t*UINT64_C(10)) / table[i].factor) % UINT64_C(10), + table[i].suffix); + + goto finish; + } + } + + snprintf(buf, l, "%" PRIu64 "B", t); + +finish: + buf[l-1] = 0; + return buf; + +} + +int safe_atou(const char *s, unsigned *ret_u) { + char *x = NULL; + unsigned long l; + + assert(s); + assert(ret_u); + + errno = 0; + l = strtoul(s, &x, 0); + + if (!x || x == s || *x || errno) + return errno > 0 ? -errno : -EINVAL; + + if ((unsigned long) (unsigned) l != l) + return -ERANGE; + + *ret_u = (unsigned) l; + return 0; +} + +int safe_atoi(const char *s, int *ret_i) { + char *x = NULL; + long l; + + assert(s); + assert(ret_i); + + errno = 0; + l = strtol(s, &x, 0); + + if (!x || x == s || *x || errno) + return errno > 0 ? -errno : -EINVAL; + + if ((long) (int) l != l) + return -ERANGE; + + *ret_i = (int) l; + return 0; +} + +int safe_atollu(const char *s, long long unsigned *ret_llu) { + char *x = NULL; + unsigned long long l; + + assert(s); + assert(ret_llu); + + errno = 0; + l = strtoull(s, &x, 0); + + if (!x || x == s || *x || errno) + return errno ? -errno : -EINVAL; + + *ret_llu = l; + return 0; +} + +int safe_atolli(const char *s, long long int *ret_lli) { + char *x = NULL; + long long l; + + assert(s); + assert(ret_lli); + + errno = 0; + l = strtoll(s, &x, 0); + + if (!x || x == s || *x || errno) + return errno ? -errno : -EINVAL; + + *ret_lli = l; + return 0; +} + +int safe_atou8(const char *s, uint8_t *ret) { + char *x = NULL; + unsigned long l; + + assert(s); + assert(ret); + + errno = 0; + l = strtoul(s, &x, 0); + + if (!x || x == s || *x || errno) + return errno > 0 ? -errno : -EINVAL; + + if ((unsigned long) (uint8_t) l != l) + return -ERANGE; + + *ret = (uint8_t) l; + return 0; +} + +int safe_atou16(const char *s, uint16_t *ret) { + char *x = NULL; + unsigned long l; + + assert(s); + assert(ret); + + errno = 0; + l = strtoul(s, &x, 0); + + if (!x || x == s || *x || errno) + return errno > 0 ? -errno : -EINVAL; + + if ((unsigned long) (uint16_t) l != l) + return -ERANGE; + + *ret = (uint16_t) l; + return 0; +} + +int safe_atoi16(const char *s, int16_t *ret) { + char *x = NULL; + long l; + + assert(s); + assert(ret); + + errno = 0; + l = strtol(s, &x, 0); + + if (!x || x == s || *x || errno) + return errno > 0 ? -errno : -EINVAL; + + if ((long) (int16_t) l != l) + return -ERANGE; + + *ret = (int16_t) l; + return 0; +} + +int safe_atod(const char *s, double *ret_d) { + char *x = NULL; + double d = 0; + locale_t loc; + + assert(s); + assert(ret_d); + + loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0); + if (loc == (locale_t) 0) + return -errno; + + errno = 0; + d = strtod_l(s, &x, loc); + + if (!x || x == s || *x || errno) { + freelocale(loc); + return errno ? -errno : -EINVAL; + } + + freelocale(loc); + *ret_d = (double) d; + return 0; +} diff --git a/src/basic/parse-util.h b/src/basic/parse-util.h new file mode 100644 index 0000000000..0e56848e26 --- /dev/null +++ b/src/basic/parse-util.h @@ -0,0 +1,91 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <inttypes.h> +#include <sys/types.h> + +#include "macro.h" + +#define MODE_INVALID ((mode_t) -1) + +int parse_boolean(const char *v) _pure_; +int parse_pid(const char *s, pid_t* ret_pid); +int parse_mode(const char *s, mode_t *ret); + +int parse_size(const char *t, uint64_t base, uint64_t *size); +int parse_range(const char *t, unsigned *lower, unsigned *upper); + +#define FORMAT_BYTES_MAX 8 +char *format_bytes(char *buf, size_t l, uint64_t t); + +int safe_atou(const char *s, unsigned *ret_u); +int safe_atoi(const char *s, int *ret_i); +int safe_atollu(const char *s, unsigned long long *ret_u); +int safe_atolli(const char *s, long long int *ret_i); + +int safe_atou8(const char *s, uint8_t *ret); + +int safe_atou16(const char *s, uint16_t *ret); +int safe_atoi16(const char *s, int16_t *ret); + +static inline int safe_atou32(const char *s, uint32_t *ret_u) { + assert_cc(sizeof(uint32_t) == sizeof(unsigned)); + return safe_atou(s, (unsigned*) ret_u); +} + +static inline int safe_atoi32(const char *s, int32_t *ret_i) { + assert_cc(sizeof(int32_t) == sizeof(int)); + return safe_atoi(s, (int*) ret_i); +} + +static inline int safe_atou64(const char *s, uint64_t *ret_u) { + assert_cc(sizeof(uint64_t) == sizeof(unsigned long long)); + return safe_atollu(s, (unsigned long long*) ret_u); +} + +static inline int safe_atoi64(const char *s, int64_t *ret_i) { + assert_cc(sizeof(int64_t) == sizeof(long long int)); + return safe_atolli(s, (long long int*) ret_i); +} + +#if LONG_MAX == INT_MAX +static inline int safe_atolu(const char *s, unsigned long *ret_u) { + assert_cc(sizeof(unsigned long) == sizeof(unsigned)); + return safe_atou(s, (unsigned*) ret_u); +} +static inline int safe_atoli(const char *s, long int *ret_u) { + assert_cc(sizeof(long int) == sizeof(int)); + return safe_atoi(s, (int*) ret_u); +} +#else +static inline int safe_atolu(const char *s, unsigned long *ret_u) { + assert_cc(sizeof(unsigned long) == sizeof(unsigned long long)); + return safe_atollu(s, (unsigned long long*) ret_u); +} +static inline int safe_atoli(const char *s, long int *ret_u) { + assert_cc(sizeof(long int) == sizeof(long long int)); + return safe_atolli(s, (long long int*) ret_u); +} +#endif + +int safe_atod(const char *s, double *ret_d); diff --git a/src/basic/path-util.c b/src/basic/path-util.c index 0b8cac8f3e..ec90c432a4 100644 --- a/src/basic/path-util.c +++ b/src/basic/path-util.c @@ -27,12 +27,22 @@ #include <sys/statvfs.h> #include <unistd.h> +/* When we include libgen.h because we need dirname() we immediately + * undefine basename() since libgen.h defines it as a macro to the + * POSIX version which is really broken. We prefer GNU basename(). */ +#include <libgen.h> +#undef basename + +#include "alloc-util.h" #include "fd-util.h" #include "fileio.h" +#include "fs-util.h" #include "log.h" #include "macro.h" #include "missing.h" +#include "parse-util.h" #include "path-util.h" +#include "stat-util.h" #include "string-util.h" #include "strv.h" #include "util.h" @@ -45,47 +55,6 @@ bool is_path(const char *p) { return !!strchr(p, '/'); } -int path_get_parent(const char *path, char **_r) { - const char *e, *a = NULL, *b = NULL, *p; - char *r; - bool slash = false; - - assert(path); - assert(_r); - - if (!*path) - return -EINVAL; - - for (e = path; *e; e++) { - - if (!slash && *e == '/') { - a = b; - b = e; - slash = true; - } else if (slash && *e != '/') - slash = false; - } - - if (*(e-1) == '/') - p = a; - else - p = b; - - if (!p) - return -EINVAL; - - if (p == path) - r = strdup("/"); - else - r = strndup(path, p-path); - - if (!r) - return -ENOMEM; - - *_r = r; - return 0; -} - int path_split_and_make_absolute(const char *p, char ***ret) { char **l; int r; @@ -95,7 +64,7 @@ int path_split_and_make_absolute(const char *p, char ***ret) { l = strv_split(p, ":"); if (!l) - return NULL; + return -ENOMEM; r = path_strv_make_absolute_cwd(l); if (r < 0) { @@ -488,243 +457,6 @@ char* path_join(const char *root, const char *path, const char *rest) { NULL); } -static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *mnt_id) { - char path[strlen("/proc/self/fdinfo/") + DECIMAL_STR_MAX(int)]; - _cleanup_free_ char *fdinfo = NULL; - _cleanup_close_ int subfd = -1; - char *p; - int r; - - if ((flags & AT_EMPTY_PATH) && isempty(filename)) - xsprintf(path, "/proc/self/fdinfo/%i", fd); - else { - subfd = openat(fd, filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH); - if (subfd < 0) - return -errno; - - xsprintf(path, "/proc/self/fdinfo/%i", subfd); - } - - r = read_full_file(path, &fdinfo, NULL); - if (r == -ENOENT) /* The fdinfo directory is a relatively new addition */ - return -EOPNOTSUPP; - if (r < 0) - return -errno; - - p = startswith(fdinfo, "mnt_id:"); - if (!p) { - p = strstr(fdinfo, "\nmnt_id:"); - if (!p) /* The mnt_id field is a relatively new addition */ - return -EOPNOTSUPP; - - p += 8; - } - - p += strspn(p, WHITESPACE); - p[strcspn(p, WHITESPACE)] = 0; - - return safe_atoi(p, mnt_id); -} - -int fd_is_mount_point(int fd, const char *filename, int flags) { - union file_handle_union h = FILE_HANDLE_INIT, h_parent = FILE_HANDLE_INIT; - int mount_id = -1, mount_id_parent = -1; - bool nosupp = false, check_st_dev = true; - struct stat a, b; - int r; - - assert(fd >= 0); - assert(filename); - - /* First we will try the name_to_handle_at() syscall, which - * tells us the mount id and an opaque file "handle". It is - * not supported everywhere though (kernel compile-time - * option, not all file systems are hooked up). If it works - * the mount id is usually good enough to tell us whether - * something is a mount point. - * - * If that didn't work we will try to read the mount id from - * /proc/self/fdinfo/<fd>. This is almost as good as - * name_to_handle_at(), however, does not return the - * opaque file handle. The opaque file handle is pretty useful - * to detect the root directory, which we should always - * consider a mount point. Hence we use this only as - * fallback. Exporting the mnt_id in fdinfo is a pretty recent - * kernel addition. - * - * As last fallback we do traditional fstat() based st_dev - * comparisons. This is how things were traditionally done, - * but unionfs breaks breaks this since it exposes file - * systems with a variety of st_dev reported. Also, btrfs - * subvolumes have different st_dev, even though they aren't - * real mounts of their own. */ - - r = name_to_handle_at(fd, filename, &h.handle, &mount_id, flags); - if (r < 0) { - if (errno == ENOSYS) - /* This kernel does not support name_to_handle_at() - * fall back to simpler logic. */ - goto fallback_fdinfo; - else if (errno == EOPNOTSUPP) - /* This kernel or file system does not support - * name_to_handle_at(), hence let's see if the - * upper fs supports it (in which case it is a - * mount point), otherwise fallback to the - * traditional stat() logic */ - nosupp = true; - else - return -errno; - } - - r = name_to_handle_at(fd, "", &h_parent.handle, &mount_id_parent, AT_EMPTY_PATH); - if (r < 0) { - if (errno == EOPNOTSUPP) { - if (nosupp) - /* Neither parent nor child do name_to_handle_at()? - We have no choice but to fall back. */ - goto fallback_fdinfo; - else - /* The parent can't do name_to_handle_at() but the - * directory we are interested in can? - * If so, it must be a mount point. */ - return 1; - } else - return -errno; - } - - /* The parent can do name_to_handle_at() but the - * directory we are interested in can't? If so, it - * must be a mount point. */ - if (nosupp) - return 1; - - /* If the file handle for the directory we are - * interested in and its parent are identical, we - * assume this is the root directory, which is a mount - * point. */ - - if (h.handle.handle_bytes == h_parent.handle.handle_bytes && - h.handle.handle_type == h_parent.handle.handle_type && - memcmp(h.handle.f_handle, h_parent.handle.f_handle, h.handle.handle_bytes) == 0) - return 1; - - return mount_id != mount_id_parent; - -fallback_fdinfo: - r = fd_fdinfo_mnt_id(fd, filename, flags, &mount_id); - if (r == -EOPNOTSUPP) - goto fallback_fstat; - if (r < 0) - return r; - - r = fd_fdinfo_mnt_id(fd, "", AT_EMPTY_PATH, &mount_id_parent); - if (r < 0) - return r; - - if (mount_id != mount_id_parent) - return 1; - - /* Hmm, so, the mount ids are the same. This leaves one - * special case though for the root file system. For that, - * let's see if the parent directory has the same inode as we - * are interested in. Hence, let's also do fstat() checks now, - * too, but avoid the st_dev comparisons, since they aren't - * that useful on unionfs mounts. */ - check_st_dev = false; - -fallback_fstat: - /* yay for fstatat() taking a different set of flags than the other - * _at() above */ - if (flags & AT_SYMLINK_FOLLOW) - flags &= ~AT_SYMLINK_FOLLOW; - else - flags |= AT_SYMLINK_NOFOLLOW; - if (fstatat(fd, filename, &a, flags) < 0) - return -errno; - - if (fstatat(fd, "", &b, AT_EMPTY_PATH) < 0) - return -errno; - - /* A directory with same device and inode as its parent? Must - * be the root directory */ - if (a.st_dev == b.st_dev && - a.st_ino == b.st_ino) - return 1; - - return check_st_dev && (a.st_dev != b.st_dev); -} - -/* flags can be AT_SYMLINK_FOLLOW or 0 */ -int path_is_mount_point(const char *t, int flags) { - _cleanup_close_ int fd = -1; - _cleanup_free_ char *canonical = NULL, *parent = NULL; - int r; - - assert(t); - - if (path_equal(t, "/")) - return 1; - - /* we need to resolve symlinks manually, we can't just rely on - * fd_is_mount_point() to do that for us; if we have a structure like - * /bin -> /usr/bin/ and /usr is a mount point, then the parent that we - * look at needs to be /usr, not /. */ - if (flags & AT_SYMLINK_FOLLOW) { - canonical = canonicalize_file_name(t); - if (!canonical) - return -errno; - - t = canonical; - } - - r = path_get_parent(t, &parent); - if (r < 0) - return r; - - fd = openat(AT_FDCWD, parent, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_PATH); - if (fd < 0) - return -errno; - - return fd_is_mount_point(fd, basename(t), flags); -} - -int path_is_read_only_fs(const char *path) { - struct statvfs st; - - assert(path); - - if (statvfs(path, &st) < 0) - return -errno; - - if (st.f_flag & ST_RDONLY) - return true; - - /* On NFS, statvfs() might not reflect whether we can actually - * write to the remote share. Let's try again with - * access(W_OK) which is more reliable, at least sometimes. */ - if (access(path, W_OK) < 0 && errno == EROFS) - return true; - - return false; -} - -int path_is_os_tree(const char *path) { - char *p; - int r; - - /* We use /usr/lib/os-release as flag file if something is an OS */ - p = strjoina(path, "/usr/lib/os-release"); - r = access(p, F_OK); - if (r >= 0) - return 1; - - /* Also check for the old location in /etc, just in case. */ - p = strjoina(path, "/etc/os-release"); - r = access(p, F_OK); - - return r >= 0; -} - int find_binary(const char *name, char **ret) { int last_error, r; const char *p; @@ -936,3 +668,134 @@ int parse_path_argument_and_warn(const char *path, bool suppress_root, char **ar *arg = p; return 0; } + +char* dirname_malloc(const char *path) { + char *d, *dir, *dir2; + + assert(path); + + d = strdup(path); + if (!d) + return NULL; + + dir = dirname(d); + assert(dir); + + if (dir == d) + return d; + + dir2 = strdup(dir); + free(d); + + return dir2; +} + +bool filename_is_valid(const char *p) { + const char *e; + + if (isempty(p)) + return false; + + if (streq(p, ".")) + return false; + + if (streq(p, "..")) + return false; + + e = strchrnul(p, '/'); + if (*e != 0) + return false; + + if (e - p > FILENAME_MAX) + return false; + + return true; +} + +bool path_is_safe(const char *p) { + + if (isempty(p)) + return false; + + if (streq(p, "..") || startswith(p, "../") || endswith(p, "/..") || strstr(p, "/../")) + return false; + + if (strlen(p)+1 > PATH_MAX) + return false; + + /* The following two checks are not really dangerous, but hey, they still are confusing */ + if (streq(p, ".") || startswith(p, "./") || endswith(p, "/.") || strstr(p, "/./")) + return false; + + if (strstr(p, "//")) + return false; + + return true; +} + +char *file_in_same_dir(const char *path, const char *filename) { + char *e, *ret; + size_t k; + + assert(path); + assert(filename); + + /* This removes the last component of path and appends + * filename, unless the latter is absolute anyway or the + * former isn't */ + + if (path_is_absolute(filename)) + return strdup(filename); + + e = strrchr(path, '/'); + if (!e) + return strdup(filename); + + k = strlen(filename); + ret = new(char, (e + 1 - path) + k + 1); + if (!ret) + return NULL; + + memcpy(mempcpy(ret, path, e + 1 - path), filename, k + 1); + return ret; +} + +bool hidden_file_allow_backup(const char *filename) { + assert(filename); + + return + filename[0] == '.' || + streq(filename, "lost+found") || + streq(filename, "aquota.user") || + streq(filename, "aquota.group") || + endswith(filename, ".rpmnew") || + endswith(filename, ".rpmsave") || + endswith(filename, ".rpmorig") || + endswith(filename, ".dpkg-old") || + endswith(filename, ".dpkg-new") || + endswith(filename, ".dpkg-tmp") || + endswith(filename, ".dpkg-dist") || + endswith(filename, ".dpkg-bak") || + endswith(filename, ".dpkg-backup") || + endswith(filename, ".dpkg-remove") || + endswith(filename, ".swp"); +} + +bool hidden_file(const char *filename) { + assert(filename); + + if (endswith(filename, "~")) + return true; + + return hidden_file_allow_backup(filename); +} + +bool is_device_path(const char *path) { + + /* Returns true on paths that refer to a device, either in + * sysfs or in /dev */ + + return + path_startswith(path, "/dev/") || + path_startswith(path, "/sys/"); +} diff --git a/src/basic/path-util.h b/src/basic/path-util.h index 9d4522c8eb..989e0f9004 100644 --- a/src/basic/path-util.h +++ b/src/basic/path-util.h @@ -37,7 +37,6 @@ bool is_path(const char *p) _pure_; int path_split_and_make_absolute(const char *p, char ***ret); -int path_get_parent(const char *path, char **parent); bool path_is_absolute(const char *p) _pure_; char* path_make_absolute(const char *p, const char *prefix); int path_make_absolute_cwd(const char *p, char **ret); @@ -53,11 +52,6 @@ int path_strv_make_absolute_cwd(char **l); char** path_strv_resolve(char **l, const char *prefix); char** path_strv_resolve_uniq(char **l, const char *prefix); -int fd_is_mount_point(int fd, const char *filename, int flags); -int path_is_mount_point(const char *path, int flags); -int path_is_read_only_fs(const char *path); -int path_is_os_tree(const char *path); - int find_binary(const char *name, char **filename); bool paths_check_timestamp(const char* const* paths, usec_t *paths_ts_usec, bool update); @@ -103,3 +97,15 @@ char *prefix_root(const char *root, const char *path); }) int parse_path_argument_and_warn(const char *path, bool suppress_root, char **arg); + +char* dirname_malloc(const char *path); + +bool filename_is_valid(const char *p) _pure_; +bool path_is_safe(const char *p) _pure_; + +char *file_in_same_dir(const char *path, const char *filename); + +bool hidden_file_allow_backup(const char *filename); +bool hidden_file(const char *filename) _pure_; + +bool is_device_path(const char *path); diff --git a/src/basic/prioq.c b/src/basic/prioq.c index d55b348c22..7590698911 100644 --- a/src/basic/prioq.c +++ b/src/basic/prioq.c @@ -29,8 +29,9 @@ * The underlying algorithm used in this implementation is a Heap. */ -#include "util.h" +#include "alloc-util.h" #include "prioq.h" +#include "util.h" struct prioq_item { void *data; diff --git a/src/basic/proc-cmdline.c b/src/basic/proc-cmdline.c new file mode 100644 index 0000000000..dd91ce7dbc --- /dev/null +++ b/src/basic/proc-cmdline.c @@ -0,0 +1,145 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include "alloc-util.h" +#include "extract-word.h" +#include "fileio.h" +#include "macro.h" +#include "parse-util.h" +#include "proc-cmdline.h" +#include "process-util.h" +#include "string-util.h" +#include "util.h" +#include "virt.h" + +int proc_cmdline(char **ret) { + assert(ret); + + if (detect_container() > 0) + return get_process_cmdline(1, 0, false, ret); + else + return read_one_line_file("/proc/cmdline", ret); +} + +int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value)) { + _cleanup_free_ char *line = NULL; + const char *p; + int r; + + assert(parse_item); + + r = proc_cmdline(&line); + if (r < 0) + return r; + + p = line; + for (;;) { + _cleanup_free_ char *word = NULL; + char *value = NULL; + + r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX); + if (r < 0) + return r; + if (r == 0) + break; + + /* Filter out arguments that are intended only for the + * initrd */ + if (!in_initrd() && startswith(word, "rd.")) + continue; + + value = strchr(word, '='); + if (value) + *(value++) = 0; + + r = parse_item(word, value); + if (r < 0) + return r; + } + + return 0; +} + +int get_proc_cmdline_key(const char *key, char **value) { + _cleanup_free_ char *line = NULL, *ret = NULL; + bool found = false; + const char *p; + int r; + + assert(key); + + r = proc_cmdline(&line); + if (r < 0) + return r; + + p = line; + for (;;) { + _cleanup_free_ char *word = NULL; + const char *e; + + r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX); + if (r < 0) + return r; + if (r == 0) + break; + + /* Filter out arguments that are intended only for the + * initrd */ + if (!in_initrd() && startswith(word, "rd.")) + continue; + + if (value) { + e = startswith(word, key); + if (!e) + continue; + + r = free_and_strdup(&ret, e); + if (r < 0) + return r; + + found = true; + } else { + if (streq(word, key)) + found = true; + } + } + + if (value) { + *value = ret; + ret = NULL; + } + + return found; + +} + +int shall_restore_state(void) { + _cleanup_free_ char *value = NULL; + int r; + + r = get_proc_cmdline_key("systemd.restore_state=", &value); + if (r < 0) + return r; + if (r == 0) + return true; + + return parse_boolean(value) != 0; +} diff --git a/src/basic/proc-cmdline.h b/src/basic/proc-cmdline.h new file mode 100644 index 0000000000..ea8277b053 --- /dev/null +++ b/src/basic/proc-cmdline.h @@ -0,0 +1,28 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +int proc_cmdline(char **ret); +int parse_proc_cmdline(int (*parse_word)(const char *key, const char *value)); +int get_proc_cmdline_key(const char *parameter, char **value); + +int shall_restore_state(void); diff --git a/src/basic/process-util.c b/src/basic/process-util.c index 72fc82e7cb..7631928d5f 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -20,20 +20,27 @@ #include <assert.h> #include <ctype.h> #include <errno.h> +#include <sched.h> #include <signal.h> #include <stdbool.h> #include <stdio.h> #include <string.h> +#include <sys/personality.h> +#include <sys/prctl.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> +#include "alloc-util.h" #include "escape.h" #include "fd-util.h" #include "fileio.h" +#include "fs-util.h" +#include "ioprio.h" #include "log.h" #include "process-util.h" #include "signal-util.h" +#include "string-table.h" #include "string-util.h" #include "user-util.h" #include "util.h" @@ -178,6 +185,37 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char * return 0; } +void rename_process(const char name[8]) { + assert(name); + + /* This is a like a poor man's setproctitle(). It changes the + * comm field, argv[0], and also the glibc's internally used + * name of the process. For the first one a limit of 16 chars + * applies, to the second one usually one of 10 (i.e. length + * of "/sbin/init"), to the third one one of 7 (i.e. length of + * "systemd"). If you pass a longer string it will be + * truncated */ + + prctl(PR_SET_NAME, name); + + if (program_invocation_name) + strncpy(program_invocation_name, name, strlen(program_invocation_name)); + + if (saved_argc > 0) { + int i; + + if (saved_argv[0]) + strncpy(saved_argv[0], name, strlen(saved_argv[0])); + + for (i = 1; i < saved_argc; i++) { + if (!saved_argv[i]) + break; + + memzero(saved_argv[i], strlen(saved_argv[i])); + } + } +} + int is_kernel_thread(pid_t pid) { const char *p; size_t count; @@ -368,7 +406,7 @@ int get_process_environ(pid_t pid, char **env) { return 0; } -int get_parent_of_pid(pid_t pid, pid_t *_ppid) { +int get_process_ppid(pid_t pid, pid_t *_ppid) { int r; _cleanup_free_ char *line = NULL; long unsigned ppid; @@ -561,9 +599,12 @@ int getenv_for_pid(pid_t pid, const char *field, char **_value) { bool pid_is_unwaited(pid_t pid) { /* Checks whether a PID is still valid at all, including a zombie */ - if (pid <= 0) + if (pid < 0) return false; + if (pid <= 1) /* If we or PID 1 would be dead and have been waited for, this code would not be running */ + return true; + if (kill(pid, 0) >= 0) return true; @@ -575,12 +616,141 @@ bool pid_is_alive(pid_t pid) { /* Checks whether a PID is still valid and not a zombie */ - if (pid <= 0) + if (pid < 0) return false; + if (pid <= 1) /* If we or PID 1 would be a zombie, this code would not be running */ + return true; + r = get_process_state(pid); if (r == -ESRCH || r == 'Z') return false; return true; } + +bool is_main_thread(void) { + static thread_local int cached = 0; + + if (_unlikely_(cached == 0)) + cached = getpid() == gettid() ? 1 : -1; + + return cached > 0; +} + +noreturn void freeze(void) { + + /* Make sure nobody waits for us on a socket anymore */ + close_all_fds(NULL, 0); + + sync(); + + for (;;) + pause(); +} + +bool oom_score_adjust_is_valid(int oa) { + return oa >= OOM_SCORE_ADJ_MIN && oa <= OOM_SCORE_ADJ_MAX; +} + +unsigned long personality_from_string(const char *p) { + + /* Parse a personality specifier. We introduce our own + * identifiers that indicate specific ABIs, rather than just + * hints regarding the register size, since we want to keep + * things open for multiple locally supported ABIs for the + * same register size. We try to reuse the ABI identifiers + * used by libseccomp. */ + +#if defined(__x86_64__) + + if (streq(p, "x86")) + return PER_LINUX32; + + if (streq(p, "x86-64")) + return PER_LINUX; + +#elif defined(__i386__) + + if (streq(p, "x86")) + return PER_LINUX; + +#elif defined(__s390x__) + + if (streq(p, "s390")) + return PER_LINUX32; + + if (streq(p, "s390x")) + return PER_LINUX; + +#elif defined(__s390__) + + if (streq(p, "s390")) + return PER_LINUX; +#endif + + return PERSONALITY_INVALID; +} + +const char* personality_to_string(unsigned long p) { + +#if defined(__x86_64__) + + if (p == PER_LINUX32) + return "x86"; + + if (p == PER_LINUX) + return "x86-64"; + +#elif defined(__i386__) + + if (p == PER_LINUX) + return "x86"; + +#elif defined(__s390x__) + + if (p == PER_LINUX) + return "s390x"; + + if (p == PER_LINUX32) + return "s390"; + +#elif defined(__s390__) + + if (p == PER_LINUX) + return "s390"; + +#endif + + return NULL; +} + +static const char *const ioprio_class_table[] = { + [IOPRIO_CLASS_NONE] = "none", + [IOPRIO_CLASS_RT] = "realtime", + [IOPRIO_CLASS_BE] = "best-effort", + [IOPRIO_CLASS_IDLE] = "idle" +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, INT_MAX); + +static const char *const sigchld_code_table[] = { + [CLD_EXITED] = "exited", + [CLD_KILLED] = "killed", + [CLD_DUMPED] = "dumped", + [CLD_TRAPPED] = "trapped", + [CLD_STOPPED] = "stopped", + [CLD_CONTINUED] = "continued", +}; + +DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int); + +static const char* const sched_policy_table[] = { + [SCHED_OTHER] = "other", + [SCHED_BATCH] = "batch", + [SCHED_IDLE] = "idle", + [SCHED_FIFO] = "fifo", + [SCHED_RR] = "rr" +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX); diff --git a/src/basic/process-util.h b/src/basic/process-util.h index 2c0d1af000..72633ebf70 100644 --- a/src/basic/process-util.h +++ b/src/basic/process-util.h @@ -27,6 +27,7 @@ #include <signal.h> #include "formats-util.h" +#include "macro.h" #define procfs_file_alloca(pid, field) \ ({ \ @@ -51,6 +52,7 @@ int get_process_capeff(pid_t pid, char **capeff); int get_process_cwd(pid_t pid, char **cwd); int get_process_root(pid_t pid, char **root); int get_process_environ(pid_t pid, char **environ); +int get_process_ppid(pid_t pid, pid_t *ppid); int wait_for_terminate(pid_t pid, siginfo_t *status); int wait_for_terminate_and_warn(const char *name, pid_t pid, bool check_exit_code); @@ -59,10 +61,39 @@ void sigkill_wait(pid_t *pid); #define _cleanup_sigkill_wait_ _cleanup_(sigkill_wait) int kill_and_sigcont(pid_t pid, int sig); -pid_t get_parent_of_pid(pid_t pid, pid_t *ppid); + void rename_process(const char name[8]); int is_kernel_thread(pid_t pid); + int getenv_for_pid(pid_t pid, const char *field, char **_value); bool pid_is_alive(pid_t pid); bool pid_is_unwaited(pid_t pid); + +bool is_main_thread(void); + +noreturn void freeze(void); + +bool oom_score_adjust_is_valid(int oa); + +#ifndef PERSONALITY_INVALID +/* personality(7) documents that 0xffffffffUL is used for querying the + * current personality, hence let's use that here as error + * indicator. */ +#define PERSONALITY_INVALID 0xffffffffLU +#endif + +unsigned long personality_from_string(const char *p); +const char *personality_to_string(unsigned long); + +int ioprio_class_to_string_alloc(int i, char **s); +int ioprio_class_from_string(const char *s); + +const char *sigchld_code_to_string(int i) _const_; +int sigchld_code_from_string(const char *s) _pure_; + +int sched_policy_to_string_alloc(int i, char **s); +int sched_policy_from_string(const char *s); + +#define PTR_TO_PID(p) ((pid_t) ((uintptr_t) p)) +#define PID_TO_PTR(p) ((void*) ((uintptr_t) p)) diff --git a/src/basic/replace-var.c b/src/basic/replace-var.c index 478fc43a38..18b49a9227 100644 --- a/src/basic/replace-var.c +++ b/src/basic/replace-var.c @@ -21,6 +21,7 @@ #include <string.h> +#include "alloc-util.h" #include "macro.h" #include "util.h" #include "replace-var.h" diff --git a/src/basic/rlimit-util.c b/src/basic/rlimit-util.c new file mode 100644 index 0000000000..2627c813fc --- /dev/null +++ b/src/basic/rlimit-util.c @@ -0,0 +1,70 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include "missing.h" +#include "rlimit-util.h" +#include "string-table.h" +#include "util.h" + +int setrlimit_closest(int resource, const struct rlimit *rlim) { + struct rlimit highest, fixed; + + assert(rlim); + + if (setrlimit(resource, rlim) >= 0) + return 0; + + if (errno != EPERM) + return -errno; + + /* So we failed to set the desired setrlimit, then let's try + * to get as close as we can */ + assert_se(getrlimit(resource, &highest) == 0); + + fixed.rlim_cur = MIN(rlim->rlim_cur, highest.rlim_max); + fixed.rlim_max = MIN(rlim->rlim_max, highest.rlim_max); + + if (setrlimit(resource, &fixed) < 0) + return -errno; + + return 0; +} + +static const char* const rlimit_table[_RLIMIT_MAX] = { + [RLIMIT_CPU] = "LimitCPU", + [RLIMIT_FSIZE] = "LimitFSIZE", + [RLIMIT_DATA] = "LimitDATA", + [RLIMIT_STACK] = "LimitSTACK", + [RLIMIT_CORE] = "LimitCORE", + [RLIMIT_RSS] = "LimitRSS", + [RLIMIT_NOFILE] = "LimitNOFILE", + [RLIMIT_AS] = "LimitAS", + [RLIMIT_NPROC] = "LimitNPROC", + [RLIMIT_MEMLOCK] = "LimitMEMLOCK", + [RLIMIT_LOCKS] = "LimitLOCKS", + [RLIMIT_SIGPENDING] = "LimitSIGPENDING", + [RLIMIT_MSGQUEUE] = "LimitMSGQUEUE", + [RLIMIT_NICE] = "LimitNICE", + [RLIMIT_RTPRIO] = "LimitRTPRIO", + [RLIMIT_RTTIME] = "LimitRTTIME" +}; + +DEFINE_STRING_TABLE_LOOKUP(rlimit, int); diff --git a/src/basic/rlimit-util.h b/src/basic/rlimit-util.h new file mode 100644 index 0000000000..262f86dd04 --- /dev/null +++ b/src/basic/rlimit-util.h @@ -0,0 +1,33 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <sys/resource.h> + +#include "macro.h" + +const char *rlimit_to_string(int i) _const_; +int rlimit_from_string(const char *s) _pure_; + +int setrlimit_closest(int resource, const struct rlimit *rlim); + +#define RLIMIT_MAKE_CONST(lim) ((struct rlimit) { lim, lim }) diff --git a/src/basic/rm-rf.c b/src/basic/rm-rf.c index a5daa23f86..8ec7dd75ee 100644 --- a/src/basic/rm-rf.c +++ b/src/basic/rm-rf.c @@ -21,8 +21,10 @@ #include "btrfs-util.h" #include "fd-util.h" +#include "mount-util.h" #include "path-util.h" #include "rm-rf.h" +#include "stat-util.h" #include "string-util.h" #include "util.h" diff --git a/src/basic/selinux-util.c b/src/basic/selinux-util.c index 7a7dc90e3c..a821a3d5bb 100644 --- a/src/basic/selinux-util.c +++ b/src/basic/selinux-util.c @@ -29,6 +29,7 @@ #include <selinux/context.h> #endif +#include "alloc-util.h" #include "strv.h" #include "path-util.h" #include "selinux-util.h" diff --git a/src/basic/signal-util.c b/src/basic/signal-util.c index 730f99e0af..8038bc891d 100644 --- a/src/basic/signal-util.c +++ b/src/basic/signal-util.c @@ -19,11 +19,12 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "parse-util.h" +#include "signal-util.h" +#include "string-table.h" #include "string-util.h" #include "util.h" -#include "signal-util.h" - int reset_all_signal_handlers(void) { static const struct sigaction sa = { .sa_handler = SIG_DFL, @@ -268,3 +269,7 @@ int signal_from_string_try_harder(const char *s) { return signo; } + +void nop_signal_handler(int sig) { + /* nothing here */ +} diff --git a/src/basic/signal-util.h b/src/basic/signal-util.h index 5e6eb50b07..e7393e2dac 100644 --- a/src/basic/signal-util.h +++ b/src/basic/signal-util.h @@ -39,3 +39,5 @@ const char *signal_to_string(int i) _const_; int signal_from_string(const char *s) _pure_; int signal_from_string_try_harder(const char *s); + +void nop_signal_handler(int sig); diff --git a/src/basic/smack-util.c b/src/basic/smack-util.c index 5f570ff02a..fcc046098d 100644 --- a/src/basic/smack-util.c +++ b/src/basic/smack-util.c @@ -23,11 +23,14 @@ #include <sys/xattr.h> -#include "util.h" -#include "process-util.h" -#include "path-util.h" +#include "alloc-util.h" #include "fileio.h" +#include "path-util.h" +#include "process-util.h" #include "smack-util.h" +#include "string-table.h" +#include "util.h" +#include "xattr-util.h" #ifdef HAVE_SMACK bool mac_smack_use(void) { diff --git a/src/basic/socket-label.c b/src/basic/socket-label.c index 4099ea6f9f..e5d4efc719 100644 --- a/src/basic/socket-label.c +++ b/src/basic/socket-label.c @@ -25,6 +25,7 @@ #include <sys/stat.h> #include <unistd.h> +#include "alloc-util.h" #include "fd-util.h" #include "macro.h" #include "missing.h" diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c index 684ac765f5..1acab1ef95 100644 --- a/src/basic/socket-util.c +++ b/src/basic/socket-util.c @@ -30,14 +30,18 @@ #include <sys/types.h> #include <unistd.h> +#include "alloc-util.h" #include "fd-util.h" #include "fileio.h" #include "formats-util.h" #include "macro.h" #include "missing.h" +#include "parse-util.h" #include "path-util.h" #include "socket-util.h" +#include "string-table.h" #include "string-util.h" +#include "user-util.h" #include "util.h" int socket_address_parse(SocketAddress *a, const char *s) { diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h index 8b5410b391..c60f2556af 100644 --- a/src/basic/socket-util.h +++ b/src/basic/socket-util.h @@ -127,3 +127,6 @@ int getpeersec(int fd, char **ret); int send_one_fd(int transport_fd, int fd, int flags); int receive_one_fd(int transport_fd, int flags); + +#define CMSG_FOREACH(cmsg, mh) \ + for ((cmsg) = CMSG_FIRSTHDR(mh); (cmsg); (cmsg) = CMSG_NXTHDR((mh), (cmsg))) diff --git a/src/basic/stat-util.c b/src/basic/stat-util.c new file mode 100644 index 0000000000..3bc66b3be7 --- /dev/null +++ b/src/basic/stat-util.c @@ -0,0 +1,216 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2010-2012 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <fcntl.h> +#include <linux/magic.h> +#include <sys/statvfs.h> +#include <unistd.h> + +#include "dirent-util.h" +#include "fd-util.h" +#include "macro.h" +#include "missing.h" +#include "stat-util.h" +#include "string-util.h" + +int is_symlink(const char *path) { + struct stat info; + + assert(path); + + if (lstat(path, &info) < 0) + return -errno; + + return !!S_ISLNK(info.st_mode); +} + +int is_dir(const char* path, bool follow) { + struct stat st; + int r; + + assert(path); + + if (follow) + r = stat(path, &st); + else + r = lstat(path, &st); + if (r < 0) + return -errno; + + return !!S_ISDIR(st.st_mode); +} + +int is_device_node(const char *path) { + struct stat info; + + assert(path); + + if (lstat(path, &info) < 0) + return -errno; + + return !!(S_ISBLK(info.st_mode) || S_ISCHR(info.st_mode)); +} + +int dir_is_empty(const char *path) { + _cleanup_closedir_ DIR *d; + struct dirent *de; + + d = opendir(path); + if (!d) + return -errno; + + FOREACH_DIRENT(de, d, return -errno) + return 0; + + return 1; +} + +bool null_or_empty(struct stat *st) { + assert(st); + + if (S_ISREG(st->st_mode) && st->st_size <= 0) + return true; + + /* We don't want to hardcode the major/minor of /dev/null, + * hence we do a simpler "is this a device node?" check. */ + + if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) + return true; + + return false; +} + +int null_or_empty_path(const char *fn) { + struct stat st; + + assert(fn); + + if (stat(fn, &st) < 0) + return -errno; + + return null_or_empty(&st); +} + +int null_or_empty_fd(int fd) { + struct stat st; + + assert(fd >= 0); + + if (fstat(fd, &st) < 0) + return -errno; + + return null_or_empty(&st); +} + +int path_is_read_only_fs(const char *path) { + struct statvfs st; + + assert(path); + + if (statvfs(path, &st) < 0) + return -errno; + + if (st.f_flag & ST_RDONLY) + return true; + + /* On NFS, statvfs() might not reflect whether we can actually + * write to the remote share. Let's try again with + * access(W_OK) which is more reliable, at least sometimes. */ + if (access(path, W_OK) < 0 && errno == EROFS) + return true; + + return false; +} + +int path_is_os_tree(const char *path) { + char *p; + int r; + + assert(path); + + /* We use /usr/lib/os-release as flag file if something is an OS */ + p = strjoina(path, "/usr/lib/os-release"); + r = access(p, F_OK); + if (r >= 0) + return 1; + + /* Also check for the old location in /etc, just in case. */ + p = strjoina(path, "/etc/os-release"); + r = access(p, F_OK); + + return r >= 0; +} + +int files_same(const char *filea, const char *fileb) { + struct stat a, b; + + assert(filea); + assert(fileb); + + if (stat(filea, &a) < 0) + return -errno; + + if (stat(fileb, &b) < 0) + return -errno; + + return a.st_dev == b.st_dev && + a.st_ino == b.st_ino; +} + +bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) { + assert(s); + assert_cc(sizeof(statfs_f_type_t) >= sizeof(s->f_type)); + + return F_TYPE_EQUAL(s->f_type, magic_value); +} + +int fd_check_fstype(int fd, statfs_f_type_t magic_value) { + struct statfs s; + + if (fstatfs(fd, &s) < 0) + return -errno; + + return is_fs_type(&s, magic_value); +} + +int path_check_fstype(const char *path, statfs_f_type_t magic_value) { + _cleanup_close_ int fd = -1; + + fd = open(path, O_RDONLY); + if (fd < 0) + return -errno; + + return fd_check_fstype(fd, magic_value); +} + +bool is_temporary_fs(const struct statfs *s) { + return is_fs_type(s, TMPFS_MAGIC) || + is_fs_type(s, RAMFS_MAGIC); +} + +int fd_is_temporary_fs(int fd) { + struct statfs s; + + if (fstatfs(fd, &s) < 0) + return -errno; + + return is_temporary_fs(&s); +} diff --git a/src/basic/stat-util.h b/src/basic/stat-util.h new file mode 100644 index 0000000000..909b220a24 --- /dev/null +++ b/src/basic/stat-util.h @@ -0,0 +1,70 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + This file is part of systemd. + + Copyright 2010-2012 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <stdbool.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/vfs.h> + +#include "macro.h" + +int is_symlink(const char *path); +int is_dir(const char *path, bool follow); +int is_device_node(const char *path); + +int dir_is_empty(const char *path); + +static inline int dir_is_populated(const char *path) { + int r; + r = dir_is_empty(path); + if (r < 0) + return r; + return !r; +} + +bool null_or_empty(struct stat *st) _pure_; +int null_or_empty_path(const char *fn); +int null_or_empty_fd(int fd); + +int path_is_read_only_fs(const char *path); +int path_is_os_tree(const char *path); + +int files_same(const char *filea, const char *fileb); + +/* The .f_type field of struct statfs is really weird defined on + * different archs. Let's use our own type we know is sufficiently + * larger to store the possible values. */ +typedef long statfs_f_type_t; + +bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) _pure_; +int fd_check_fstype(int fd, statfs_f_type_t magic_value); +int path_check_fstype(const char *path, statfs_f_type_t magic_value); + +bool is_temporary_fs(const struct statfs *s) _pure_; +int fd_is_temporary_fs(int fd); + +/* Because statfs.t_type can be int on some architectures, we have to cast + * the const magic to the type, otherwise the compiler warns about + * signed/unsigned comparison, because the magic can be 32 bit unsigned. + */ +#define F_TYPE_EQUAL(a, b) (a == (typeof(a)) b) diff --git a/src/basic/stdio-util.h b/src/basic/stdio-util.h new file mode 100644 index 0000000000..b36e8a947e --- /dev/null +++ b/src/basic/stdio-util.h @@ -0,0 +1,78 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <printf.h> +#include <stdarg.h> +#include <stdio.h> +#include <sys/types.h> + +#include "macro.h" + +#define xsprintf(buf, fmt, ...) \ + assert_message_se((size_t) snprintf(buf, ELEMENTSOF(buf), fmt, __VA_ARGS__) < ELEMENTSOF(buf), "xsprintf: " #buf "[] must be big enough") + + +#define VA_FORMAT_ADVANCE(format, ap) \ +do { \ + int _argtypes[128]; \ + size_t _i, _k; \ + _k = parse_printf_format((format), ELEMENTSOF(_argtypes), _argtypes); \ + assert(_k < ELEMENTSOF(_argtypes)); \ + for (_i = 0; _i < _k; _i++) { \ + if (_argtypes[_i] & PA_FLAG_PTR) { \ + (void) va_arg(ap, void*); \ + continue; \ + } \ + \ + switch (_argtypes[_i]) { \ + case PA_INT: \ + case PA_INT|PA_FLAG_SHORT: \ + case PA_CHAR: \ + (void) va_arg(ap, int); \ + break; \ + case PA_INT|PA_FLAG_LONG: \ + (void) va_arg(ap, long int); \ + break; \ + case PA_INT|PA_FLAG_LONG_LONG: \ + (void) va_arg(ap, long long int); \ + break; \ + case PA_WCHAR: \ + (void) va_arg(ap, wchar_t); \ + break; \ + case PA_WSTRING: \ + case PA_STRING: \ + case PA_POINTER: \ + (void) va_arg(ap, void*); \ + break; \ + case PA_FLOAT: \ + case PA_DOUBLE: \ + (void) va_arg(ap, double); \ + break; \ + case PA_DOUBLE|PA_FLAG_LONG_DOUBLE: \ + (void) va_arg(ap, long double); \ + break; \ + default: \ + assert_not_reached("Unknown format string argument."); \ + } \ + } \ +} while(false) diff --git a/src/basic/strbuf.c b/src/basic/strbuf.c index 01a076c2ba..f4f702a05a 100644 --- a/src/basic/strbuf.c +++ b/src/basic/strbuf.c @@ -22,8 +22,9 @@ #include <stdlib.h> #include <string.h> -#include "util.h" +#include "alloc-util.h" #include "strbuf.h" +#include "util.h" /* * Strbuf stores given strings in a single continuous allocated memory diff --git a/src/basic/string-table.c b/src/basic/string-table.c new file mode 100644 index 0000000000..a860324fc9 --- /dev/null +++ b/src/basic/string-table.c @@ -0,0 +1,35 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include "string-table.h" + +ssize_t string_table_lookup(const char * const *table, size_t len, const char *key) { + size_t i; + + if (!key) + return -1; + + for (i = 0; i < len; ++i) + if (streq_ptr(table[i], key)) + return (ssize_t) i; + + return -1; +} diff --git a/src/basic/string-table.h b/src/basic/string-table.h new file mode 100644 index 0000000000..51b6007214 --- /dev/null +++ b/src/basic/string-table.h @@ -0,0 +1,88 @@ + +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <stddef.h> +#include <stdio.h> +#include <string.h> +#include <sys/types.h> + +#include "macro.h" +#include "parse-util.h" +#include "string-util.h" + +ssize_t string_table_lookup(const char * const *table, size_t len, const char *key); + +/* For basic lookup tables with strictly enumerated entries */ +#define _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \ + scope const char *name##_to_string(type i) { \ + if (i < 0 || i >= (type) ELEMENTSOF(name##_table)) \ + return NULL; \ + return name##_table[i]; \ + } + +#define _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope) \ + scope type name##_from_string(const char *s) { \ + return (type) string_table_lookup(name##_table, ELEMENTSOF(name##_table), s); \ + } + +#define _DEFINE_STRING_TABLE_LOOKUP(name,type,scope) \ + _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \ + _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope) \ + struct __useless_struct_to_allow_trailing_semicolon__ + +#define DEFINE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,) +#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,static) +#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,static) +#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,static) + +/* For string conversions where numbers are also acceptable */ +#define DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(name,type,max) \ + int name##_to_string_alloc(type i, char **str) { \ + char *s; \ + if (i < 0 || i > max) \ + return -ERANGE; \ + if (i < (type) ELEMENTSOF(name##_table)) { \ + s = strdup(name##_table[i]); \ + if (!s) \ + return -ENOMEM; \ + } else { \ + if (asprintf(&s, "%i", i) < 0) \ + return -ENOMEM; \ + } \ + *str = s; \ + return 0; \ + } \ + type name##_from_string(const char *s) { \ + type i; \ + unsigned u = 0; \ + if (!s) \ + return (type) -1; \ + for (i = 0; i < (type) ELEMENTSOF(name##_table); i++) \ + if (streq_ptr(name##_table[i], s)) \ + return i; \ + if (safe_atou(s, &u) >= 0 && u <= max) \ + return (type) u; \ + return (type) -1; \ + } \ + struct __useless_struct_to_allow_trailing_semicolon__ diff --git a/src/basic/string-util.c b/src/basic/string-util.c index a7cf4e8520..63b9b79df9 100644 --- a/src/basic/string-util.c +++ b/src/basic/string-util.c @@ -19,6 +19,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "gunicode.h" #include "utf8.h" #include "util.h" @@ -765,3 +766,20 @@ char *string_free_erase(char *s) { string_erase(s); return mfree(s); } + +bool string_is_safe(const char *p) { + const char *t; + + if (!p) + return false; + + for (t = p; *t; t++) { + if (*t > 0 && *t < ' ') /* no control characters */ + return false; + + if (strchr(QUOTES "\\\x7f", *t)) + return false; + } + + return true; +} diff --git a/src/basic/string-util.h b/src/basic/string-util.h index 7b7c0e5f32..297b8f8232 100644 --- a/src/basic/string-util.h +++ b/src/basic/string-util.h @@ -168,3 +168,5 @@ void string_erase(char *x); char *string_free_erase(char *s); DEFINE_TRIVIAL_CLEANUP_FUNC(char *, string_free_erase); #define _cleanup_string_free_erase_ _cleanup_(string_free_erasep) + +bool string_is_safe(const char *p) _pure_; diff --git a/src/basic/strv.c b/src/basic/strv.c index f5df269006..ba6df716a7 100644 --- a/src/basic/strv.c +++ b/src/basic/strv.c @@ -24,6 +24,7 @@ #include <stdlib.h> #include <string.h> +#include "alloc-util.h" #include "escape.h" #include "string-util.h" #include "util.h" diff --git a/src/basic/syslog-util.c b/src/basic/syslog-util.c new file mode 100644 index 0000000000..01577941a0 --- /dev/null +++ b/src/basic/syslog-util.c @@ -0,0 +1,115 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <syslog.h> + +#include "assert.h" +#include "hexdecoct.h" +#include "string-table.h" +#include "syslog-util.h" + +int syslog_parse_priority(const char **p, int *priority, bool with_facility) { + int a = 0, b = 0, c = 0; + int k; + + assert(p); + assert(*p); + assert(priority); + + if ((*p)[0] != '<') + return 0; + + if (!strchr(*p, '>')) + return 0; + + if ((*p)[2] == '>') { + c = undecchar((*p)[1]); + k = 3; + } else if ((*p)[3] == '>') { + b = undecchar((*p)[1]); + c = undecchar((*p)[2]); + k = 4; + } else if ((*p)[4] == '>') { + a = undecchar((*p)[1]); + b = undecchar((*p)[2]); + c = undecchar((*p)[3]); + k = 5; + } else + return 0; + + if (a < 0 || b < 0 || c < 0 || + (!with_facility && (a || b || c > 7))) + return 0; + + if (with_facility) + *priority = a*100 + b*10 + c; + else + *priority = (*priority & LOG_FACMASK) | c; + + *p += k; + return 1; +} + +static const char *const log_facility_unshifted_table[LOG_NFACILITIES] = { + [LOG_FAC(LOG_KERN)] = "kern", + [LOG_FAC(LOG_USER)] = "user", + [LOG_FAC(LOG_MAIL)] = "mail", + [LOG_FAC(LOG_DAEMON)] = "daemon", + [LOG_FAC(LOG_AUTH)] = "auth", + [LOG_FAC(LOG_SYSLOG)] = "syslog", + [LOG_FAC(LOG_LPR)] = "lpr", + [LOG_FAC(LOG_NEWS)] = "news", + [LOG_FAC(LOG_UUCP)] = "uucp", + [LOG_FAC(LOG_CRON)] = "cron", + [LOG_FAC(LOG_AUTHPRIV)] = "authpriv", + [LOG_FAC(LOG_FTP)] = "ftp", + [LOG_FAC(LOG_LOCAL0)] = "local0", + [LOG_FAC(LOG_LOCAL1)] = "local1", + [LOG_FAC(LOG_LOCAL2)] = "local2", + [LOG_FAC(LOG_LOCAL3)] = "local3", + [LOG_FAC(LOG_LOCAL4)] = "local4", + [LOG_FAC(LOG_LOCAL5)] = "local5", + [LOG_FAC(LOG_LOCAL6)] = "local6", + [LOG_FAC(LOG_LOCAL7)] = "local7" +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_facility_unshifted, int, LOG_FAC(~0)); + +bool log_facility_unshifted_is_valid(int facility) { + return facility >= 0 && facility <= LOG_FAC(~0); +} + +static const char *const log_level_table[] = { + [LOG_EMERG] = "emerg", + [LOG_ALERT] = "alert", + [LOG_CRIT] = "crit", + [LOG_ERR] = "err", + [LOG_WARNING] = "warning", + [LOG_NOTICE] = "notice", + [LOG_INFO] = "info", + [LOG_DEBUG] = "debug" +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_level, int, LOG_DEBUG); + +bool log_level_is_valid(int level) { + return level >= 0 && level <= LOG_DEBUG; +} diff --git a/src/basic/syslog-util.h b/src/basic/syslog-util.h new file mode 100644 index 0000000000..eb79c6dbd8 --- /dev/null +++ b/src/basic/syslog-util.h @@ -0,0 +1,34 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <stdbool.h> + +int log_facility_unshifted_to_string_alloc(int i, char **s); +int log_facility_unshifted_from_string(const char *s); +bool log_facility_unshifted_is_valid(int faciliy); + +int log_level_to_string_alloc(int i, char **s); +int log_level_from_string(const char *s); +bool log_level_is_valid(int level); + +int syslog_parse_priority(const char **p, int *priority, bool with_facility); diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c index 7dfab0af62..b96bfcb8ef 100644 --- a/src/basic/terminal-util.c +++ b/src/basic/terminal-util.c @@ -31,12 +31,16 @@ #include <time.h> #include <unistd.h> +#include "alloc-util.h" #include "fd-util.h" #include "fileio.h" +#include "fs-util.h" #include "io-util.h" +#include "parse-util.h" #include "path-util.h" #include "process-util.h" #include "socket-util.h" +#include "stat-util.h" #include "string-util.h" #include "terminal-util.h" #include "time-util.h" @@ -624,84 +628,6 @@ int make_console_stdio(void) { return 0; } -int status_vprintf(const char *status, bool ellipse, bool ephemeral, const char *format, va_list ap) { - static const char status_indent[] = " "; /* "[" STATUS "] " */ - _cleanup_free_ char *s = NULL; - _cleanup_close_ int fd = -1; - struct iovec iovec[6] = {}; - int n = 0; - static bool prev_ephemeral; - - assert(format); - - /* This is independent of logging, as status messages are - * optional and go exclusively to the console. */ - - if (vasprintf(&s, format, ap) < 0) - return log_oom(); - - fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC); - if (fd < 0) - return fd; - - if (ellipse) { - char *e; - size_t emax, sl; - int c; - - c = fd_columns(fd); - if (c <= 0) - c = 80; - - sl = status ? sizeof(status_indent)-1 : 0; - - emax = c - sl - 1; - if (emax < 3) - emax = 3; - - e = ellipsize(s, emax, 50); - if (e) { - free(s); - s = e; - } - } - - if (prev_ephemeral) - IOVEC_SET_STRING(iovec[n++], "\r" ANSI_ERASE_TO_END_OF_LINE); - prev_ephemeral = ephemeral; - - if (status) { - if (!isempty(status)) { - IOVEC_SET_STRING(iovec[n++], "["); - IOVEC_SET_STRING(iovec[n++], status); - IOVEC_SET_STRING(iovec[n++], "] "); - } else - IOVEC_SET_STRING(iovec[n++], status_indent); - } - - IOVEC_SET_STRING(iovec[n++], s); - if (!ephemeral) - IOVEC_SET_STRING(iovec[n++], "\n"); - - if (writev(fd, iovec, n) < 0) - return -errno; - - return 0; -} - -int status_printf(const char *status, bool ellipse, bool ephemeral, const char *format, ...) { - va_list ap; - int r; - - assert(format); - - va_start(ap, format); - r = status_vprintf(status, ellipse, ephemeral, format, ap); - va_end(ap); - - return r; -} - bool tty_is_vc(const char *tty) { assert(tty); diff --git a/src/basic/terminal-util.h b/src/basic/terminal-util.h index ee0b68b433..f2185c1c11 100644 --- a/src/basic/terminal-util.h +++ b/src/basic/terminal-util.h @@ -71,9 +71,6 @@ int make_stdio(int fd); int make_null_stdio(void); int make_console_stdio(void); -int status_vprintf(const char *status, bool ellipse, bool ephemeral, const char *format, va_list ap) _printf_(4,0); -int status_printf(const char *status, bool ellipse, bool ephemeral, const char *format, ...) _printf_(4,5); - int fd_columns(int fd); unsigned columns(void); int fd_lines(int fd); diff --git a/src/basic/time-util.c b/src/basic/time-util.c index b348ed4204..9dc280efc6 100644 --- a/src/basic/time-util.c +++ b/src/basic/time-util.c @@ -23,7 +23,10 @@ #include <sys/timerfd.h> #include <sys/timex.h> +#include "alloc-util.h" #include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" #include "path-util.h" #include "string-util.h" #include "strv.h" diff --git a/src/basic/umask-util.h b/src/basic/umask-util.h new file mode 100644 index 0000000000..8ed34658b4 --- /dev/null +++ b/src/basic/umask-util.h @@ -0,0 +1,48 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <stdbool.h> +#include <sys/stat.h> +#include <sys/types.h> + +#include "macro.h" + +static inline void umaskp(mode_t *u) { + umask(*u); +} + +#define _cleanup_umask_ _cleanup_(umaskp) + +struct _umask_struct_ { + mode_t mask; + bool quit; +}; + +static inline void _reset_umask_(struct _umask_struct_ *s) { + umask(s->mask); +}; + +#define RUN_WITH_UMASK(mask) \ + for (_cleanup_(_reset_umask_) struct _umask_struct_ _saved_umask_ = { umask(mask), false }; \ + !_saved_umask_.quit ; \ + _saved_umask_.quit = true) diff --git a/src/basic/unit-name.c b/src/basic/unit-name.c index 383c4ab871..0775ae7c14 100644 --- a/src/basic/unit-name.c +++ b/src/basic/unit-name.c @@ -22,13 +22,16 @@ #include <errno.h> #include <string.h> +#include "alloc-util.h" #include "bus-label.h" #include "def.h" +#include "hexdecoct.h" #include "path-util.h" +#include "string-table.h" #include "string-util.h" #include "strv.h" -#include "util.h" #include "unit-name.h" +#include "util.h" #define VALID_CHARS \ DIGITS LETTERS \ diff --git a/src/basic/user-util.c b/src/basic/user-util.c index 7e6c4c645d..d6c936db37 100644 --- a/src/basic/user-util.c +++ b/src/basic/user-util.c @@ -22,11 +22,14 @@ #include <pwd.h> #include <grp.h> -#include "user-util.h" +#include "alloc-util.h" +#include "fd-util.h" #include "macro.h" -#include "util.h" -#include "string-util.h" +#include "parse-util.h" #include "path-util.h" +#include "string-util.h" +#include "user-util.h" +#include "util.h" bool uid_is_valid(uid_t uid) { @@ -427,3 +430,43 @@ int reset_uid_gid(void) { return 0; } + +int take_etc_passwd_lock(const char *root) { + + struct flock flock = { + .l_type = F_WRLCK, + .l_whence = SEEK_SET, + .l_start = 0, + .l_len = 0, + }; + + const char *path; + int fd, r; + + /* This is roughly the same as lckpwdf(), but not as awful. We + * don't want to use alarm() and signals, hence we implement + * our own trivial version of this. + * + * Note that shadow-utils also takes per-database locks in + * addition to lckpwdf(). However, we don't given that they + * are redundant as they they invoke lckpwdf() first and keep + * it during everything they do. The per-database locks are + * awfully racy, and thus we just won't do them. */ + + if (root) + path = prefix_roota(root, "/etc/.pwd.lock"); + else + path = "/etc/.pwd.lock"; + + fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0600); + if (fd < 0) + return -errno; + + r = fcntl(fd, F_SETLKW, &flock); + if (r < 0) { + safe_close(fd); + return -errno; + } + + return fd; +} diff --git a/src/basic/user-util.h b/src/basic/user-util.h index 7995698f27..11ff6674cf 100644 --- a/src/basic/user-util.h +++ b/src/basic/user-util.h @@ -52,3 +52,16 @@ int get_home_dir(char **ret); int get_shell(char **_ret); int reset_uid_gid(void); + +int take_etc_passwd_lock(const char *root); + +#define UID_INVALID ((uid_t) -1) +#define GID_INVALID ((gid_t) -1) + +/* The following macros add 1 when converting things, since UID 0 is a + * valid UID, while the pointer NULL is special */ +#define PTR_TO_UID(p) ((uid_t) (((uintptr_t) (p))-1)) +#define UID_TO_PTR(u) ((void*) (((uintptr_t) (u))+1)) + +#define PTR_TO_GID(p) ((gid_t) (((uintptr_t) (p))-1)) +#define GID_TO_PTR(u) ((void*) (((uintptr_t) (u))+1)) diff --git a/src/basic/utf8.c b/src/basic/utf8.c index 800884ffee..7600d99903 100644 --- a/src/basic/utf8.c +++ b/src/basic/utf8.c @@ -49,6 +49,8 @@ #include <string.h> #include <stdbool.h> +#include "alloc-util.h" +#include "hexdecoct.h" #include "utf8.h" #include "util.h" diff --git a/src/basic/util.c b/src/basic/util.c index d5227aa6d0..08bdcd28f2 100644 --- a/src/basic/util.c +++ b/src/basic/util.c @@ -23,7 +23,6 @@ #include <dirent.h> #include <errno.h> #include <fcntl.h> -#include <glob.h> #include <grp.h> #include <langinfo.h> #include <libintl.h> @@ -46,7 +45,6 @@ #include <sys/mount.h> #include <sys/personality.h> #include <sys/prctl.h> -#include <sys/resource.h> #include <sys/stat.h> #include <sys/statvfs.h> #include <sys/time.h> @@ -54,7 +52,6 @@ #include <sys/utsname.h> #include <sys/vfs.h> #include <sys/wait.h> -#include <sys/xattr.h> #include <syslog.h> #include <unistd.h> @@ -72,6 +69,7 @@ * otherwise conflicts with sys/mount.h. Yay, Linux is great! */ #include <linux/fs.h> +#include "alloc-util.h" #include "build.h" #include "def.h" #include "device-nodes.h" @@ -89,11 +87,14 @@ #include "macro.h" #include "missing.h" #include "mkdir.h" +#include "hexdecoct.h" +#include "parse-util.h" #include "path-util.h" #include "process-util.h" #include "random-util.h" #include "signal-util.h" #include "sparse-endian.h" +#include "string-table.h" #include "string-util.h" #include "strv.h" #include "terminal-util.h" @@ -101,6 +102,8 @@ #include "utf8.h" #include "util.h" #include "virt.h" +#include "dirent-util.h" +#include "stat-util.h" /* Put this test here for a lack of better place */ assert_cc(EAGAIN == EWOULDBLOCK); @@ -122,1571 +125,6 @@ size_t page_size(void) { return pgsz; } -int unlink_noerrno(const char *path) { - PROTECT_ERRNO; - int r; - - r = unlink(path); - if (r < 0) - return -errno; - - return 0; -} - -int parse_boolean(const char *v) { - assert(v); - - if (streq(v, "1") || strcaseeq(v, "yes") || strcaseeq(v, "y") || strcaseeq(v, "true") || strcaseeq(v, "t") || strcaseeq(v, "on")) - return 1; - else if (streq(v, "0") || strcaseeq(v, "no") || strcaseeq(v, "n") || strcaseeq(v, "false") || strcaseeq(v, "f") || strcaseeq(v, "off")) - return 0; - - return -EINVAL; -} - -int parse_pid(const char *s, pid_t* ret_pid) { - unsigned long ul = 0; - pid_t pid; - int r; - - assert(s); - assert(ret_pid); - - r = safe_atolu(s, &ul); - if (r < 0) - return r; - - pid = (pid_t) ul; - - if ((unsigned long) pid != ul) - return -ERANGE; - - if (pid <= 0) - return -ERANGE; - - *ret_pid = pid; - return 0; -} - -int safe_atou(const char *s, unsigned *ret_u) { - char *x = NULL; - unsigned long l; - - assert(s); - assert(ret_u); - - errno = 0; - l = strtoul(s, &x, 0); - - if (!x || x == s || *x || errno) - return errno > 0 ? -errno : -EINVAL; - - if ((unsigned long) (unsigned) l != l) - return -ERANGE; - - *ret_u = (unsigned) l; - return 0; -} - -int safe_atoi(const char *s, int *ret_i) { - char *x = NULL; - long l; - - assert(s); - assert(ret_i); - - errno = 0; - l = strtol(s, &x, 0); - - if (!x || x == s || *x || errno) - return errno > 0 ? -errno : -EINVAL; - - if ((long) (int) l != l) - return -ERANGE; - - *ret_i = (int) l; - return 0; -} - -int safe_atou8(const char *s, uint8_t *ret) { - char *x = NULL; - unsigned long l; - - assert(s); - assert(ret); - - errno = 0; - l = strtoul(s, &x, 0); - - if (!x || x == s || *x || errno) - return errno > 0 ? -errno : -EINVAL; - - if ((unsigned long) (uint8_t) l != l) - return -ERANGE; - - *ret = (uint8_t) l; - return 0; -} - -int safe_atou16(const char *s, uint16_t *ret) { - char *x = NULL; - unsigned long l; - - assert(s); - assert(ret); - - errno = 0; - l = strtoul(s, &x, 0); - - if (!x || x == s || *x || errno) - return errno > 0 ? -errno : -EINVAL; - - if ((unsigned long) (uint16_t) l != l) - return -ERANGE; - - *ret = (uint16_t) l; - return 0; -} - -int safe_atoi16(const char *s, int16_t *ret) { - char *x = NULL; - long l; - - assert(s); - assert(ret); - - errno = 0; - l = strtol(s, &x, 0); - - if (!x || x == s || *x || errno) - return errno > 0 ? -errno : -EINVAL; - - if ((long) (int16_t) l != l) - return -ERANGE; - - *ret = (int16_t) l; - return 0; -} - -int safe_atollu(const char *s, long long unsigned *ret_llu) { - char *x = NULL; - unsigned long long l; - - assert(s); - assert(ret_llu); - - errno = 0; - l = strtoull(s, &x, 0); - - if (!x || x == s || *x || errno) - return errno ? -errno : -EINVAL; - - *ret_llu = l; - return 0; -} - -int safe_atolli(const char *s, long long int *ret_lli) { - char *x = NULL; - long long l; - - assert(s); - assert(ret_lli); - - errno = 0; - l = strtoll(s, &x, 0); - - if (!x || x == s || *x || errno) - return errno ? -errno : -EINVAL; - - *ret_lli = l; - return 0; -} - -int safe_atod(const char *s, double *ret_d) { - char *x = NULL; - double d = 0; - locale_t loc; - - assert(s); - assert(ret_d); - - loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0); - if (loc == (locale_t) 0) - return -errno; - - errno = 0; - d = strtod_l(s, &x, loc); - - if (!x || x == s || *x || errno) { - freelocale(loc); - return errno ? -errno : -EINVAL; - } - - freelocale(loc); - *ret_d = (double) d; - return 0; -} - - -int fchmod_umask(int fd, mode_t m) { - mode_t u; - int r; - - u = umask(0777); - r = fchmod(fd, m & (~u)) < 0 ? -errno : 0; - umask(u); - - return r; -} - -int readlinkat_malloc(int fd, const char *p, char **ret) { - size_t l = 100; - int r; - - assert(p); - assert(ret); - - for (;;) { - char *c; - ssize_t n; - - c = new(char, l); - if (!c) - return -ENOMEM; - - n = readlinkat(fd, p, c, l-1); - if (n < 0) { - r = -errno; - free(c); - return r; - } - - if ((size_t) n < l-1) { - c[n] = 0; - *ret = c; - return 0; - } - - free(c); - l *= 2; - } -} - -int readlink_malloc(const char *p, char **ret) { - return readlinkat_malloc(AT_FDCWD, p, ret); -} - -int readlink_value(const char *p, char **ret) { - _cleanup_free_ char *link = NULL; - char *value; - int r; - - r = readlink_malloc(p, &link); - if (r < 0) - return r; - - value = basename(link); - if (!value) - return -ENOENT; - - value = strdup(value); - if (!value) - return -ENOMEM; - - *ret = value; - - return 0; -} - -int readlink_and_make_absolute(const char *p, char **r) { - _cleanup_free_ char *target = NULL; - char *k; - int j; - - assert(p); - assert(r); - - j = readlink_malloc(p, &target); - if (j < 0) - return j; - - k = file_in_same_dir(p, target); - if (!k) - return -ENOMEM; - - *r = k; - return 0; -} - -int readlink_and_canonicalize(const char *p, char **r) { - char *t, *s; - int j; - - assert(p); - assert(r); - - j = readlink_and_make_absolute(p, &t); - if (j < 0) - return j; - - s = canonicalize_file_name(t); - if (s) { - free(t); - *r = s; - } else - *r = t; - - path_kill_slashes(*r); - - return 0; -} - -char *file_in_same_dir(const char *path, const char *filename) { - char *e, *ret; - size_t k; - - assert(path); - assert(filename); - - /* This removes the last component of path and appends - * filename, unless the latter is absolute anyway or the - * former isn't */ - - if (path_is_absolute(filename)) - return strdup(filename); - - e = strrchr(path, '/'); - if (!e) - return strdup(filename); - - k = strlen(filename); - ret = new(char, (e + 1 - path) + k + 1); - if (!ret) - return NULL; - - memcpy(mempcpy(ret, path, e + 1 - path), filename, k + 1); - return ret; -} - -int rmdir_parents(const char *path, const char *stop) { - size_t l; - int r = 0; - - assert(path); - assert(stop); - - l = strlen(path); - - /* Skip trailing slashes */ - while (l > 0 && path[l-1] == '/') - l--; - - while (l > 0) { - char *t; - - /* Skip last component */ - while (l > 0 && path[l-1] != '/') - l--; - - /* Skip trailing slashes */ - while (l > 0 && path[l-1] == '/') - l--; - - if (l <= 0) - break; - - if (!(t = strndup(path, l))) - return -ENOMEM; - - if (path_startswith(stop, t)) { - free(t); - return 0; - } - - r = rmdir(t); - free(t); - - if (r < 0) - if (errno != ENOENT) - return -errno; - } - - return 0; -} - -char hexchar(int x) { - static const char table[16] = "0123456789abcdef"; - - return table[x & 15]; -} - -int unhexchar(char c) { - - if (c >= '0' && c <= '9') - return c - '0'; - - if (c >= 'a' && c <= 'f') - return c - 'a' + 10; - - if (c >= 'A' && c <= 'F') - return c - 'A' + 10; - - return -EINVAL; -} - -char *hexmem(const void *p, size_t l) { - char *r, *z; - const uint8_t *x; - - z = r = malloc(l * 2 + 1); - if (!r) - return NULL; - - for (x = p; x < (const uint8_t*) p + l; x++) { - *(z++) = hexchar(*x >> 4); - *(z++) = hexchar(*x & 15); - } - - *z = 0; - return r; -} - -int unhexmem(const char *p, size_t l, void **mem, size_t *len) { - _cleanup_free_ uint8_t *r = NULL; - uint8_t *z; - const char *x; - - assert(mem); - assert(len); - assert(p); - - z = r = malloc((l + 1) / 2 + 1); - if (!r) - return -ENOMEM; - - for (x = p; x < p + l; x += 2) { - int a, b; - - a = unhexchar(x[0]); - if (a < 0) - return a; - else if (x+1 < p + l) { - b = unhexchar(x[1]); - if (b < 0) - return b; - } else - b = 0; - - *(z++) = (uint8_t) a << 4 | (uint8_t) b; - } - - *z = 0; - - *mem = r; - r = NULL; - *len = (l + 1) / 2; - - return 0; -} - -/* https://tools.ietf.org/html/rfc4648#section-6 - * Notice that base32hex differs from base32 in the alphabet it uses. - * The distinction is that the base32hex representation preserves the - * order of the underlying data when compared as bytestrings, this is - * useful when representing NSEC3 hashes, as one can then verify the - * order of hashes directly from their representation. */ -char base32hexchar(int x) { - static const char table[32] = "0123456789" - "ABCDEFGHIJKLMNOPQRSTUV"; - - return table[x & 31]; -} - -int unbase32hexchar(char c) { - unsigned offset; - - if (c >= '0' && c <= '9') - return c - '0'; - - offset = '9' - '0' + 1; - - if (c >= 'A' && c <= 'V') - return c - 'A' + offset; - - return -EINVAL; -} - -char *base32hexmem(const void *p, size_t l, bool padding) { - char *r, *z; - const uint8_t *x; - size_t len; - - if (padding) - /* five input bytes makes eight output bytes, padding is added so we must round up */ - len = 8 * (l + 4) / 5; - else { - /* same, but round down as there is no padding */ - len = 8 * l / 5; - - switch (l % 5) { - case 4: - len += 7; - break; - case 3: - len += 5; - break; - case 2: - len += 4; - break; - case 1: - len += 2; - break; - } - } - - z = r = malloc(len + 1); - if (!r) - return NULL; - - for (x = p; x < (const uint8_t*) p + (l / 5) * 5; x += 5) { - /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ - x[3] == QQQQQQQQ; x[4] == WWWWWWWW */ - *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */ - *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */ - *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */ - *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */ - *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */ - *(z++) = base32hexchar((x[3] & 127) >> 2); /* 000QQQQQ */ - *(z++) = base32hexchar((x[3] & 3) << 3 | x[4] >> 5); /* 000QQWWW */ - *(z++) = base32hexchar((x[4] & 31)); /* 000WWWWW */ - } - - switch (l % 5) { - case 4: - *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */ - *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */ - *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */ - *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */ - *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */ - *(z++) = base32hexchar((x[3] & 127) >> 2); /* 000QQQQQ */ - *(z++) = base32hexchar((x[3] & 3) << 3); /* 000QQ000 */ - if (padding) - *(z++) = '='; - - break; - - case 3: - *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */ - *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */ - *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */ - *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */ - *(z++) = base32hexchar((x[2] & 15) << 1); /* 000ZZZZ0 */ - if (padding) { - *(z++) = '='; - *(z++) = '='; - *(z++) = '='; - } - - break; - - case 2: - *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */ - *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */ - *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */ - *(z++) = base32hexchar((x[1] & 1) << 4); /* 000Y0000 */ - if (padding) { - *(z++) = '='; - *(z++) = '='; - *(z++) = '='; - *(z++) = '='; - } - - break; - - case 1: - *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */ - *(z++) = base32hexchar((x[0] & 7) << 2); /* 000XXX00 */ - if (padding) { - *(z++) = '='; - *(z++) = '='; - *(z++) = '='; - *(z++) = '='; - *(z++) = '='; - *(z++) = '='; - } - - break; - } - - *z = 0; - return r; -} - -int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *_len) { - _cleanup_free_ uint8_t *r = NULL; - int a, b, c, d, e, f, g, h; - uint8_t *z; - const char *x; - size_t len; - unsigned pad = 0; - - assert(p); - - /* padding ensures any base32hex input has input divisible by 8 */ - if (padding && l % 8 != 0) - return -EINVAL; - - if (padding) { - /* strip the padding */ - while (l > 0 && p[l - 1] == '=' && pad < 7) { - pad ++; - l --; - } - } - - /* a group of eight input bytes needs five output bytes, in case of - padding we need to add some extra bytes */ - len = (l / 8) * 5; - - switch (l % 8) { - case 7: - len += 4; - break; - case 5: - len += 3; - break; - case 4: - len += 2; - break; - case 2: - len += 1; - break; - case 0: - break; - default: - return -EINVAL; - } - - z = r = malloc(len + 1); - if (!r) - return -ENOMEM; - - for (x = p; x < p + (l / 8) * 8; x += 8) { - /* a == 000XXXXX; b == 000YYYYY; c == 000ZZZZZ; d == 000WWWWW - e == 000SSSSS; f == 000QQQQQ; g == 000VVVVV; h == 000RRRRR */ - a = unbase32hexchar(x[0]); - if (a < 0) - return -EINVAL; - - b = unbase32hexchar(x[1]); - if (b < 0) - return -EINVAL; - - c = unbase32hexchar(x[2]); - if (c < 0) - return -EINVAL; - - d = unbase32hexchar(x[3]); - if (d < 0) - return -EINVAL; - - e = unbase32hexchar(x[4]); - if (e < 0) - return -EINVAL; - - f = unbase32hexchar(x[5]); - if (f < 0) - return -EINVAL; - - g = unbase32hexchar(x[6]); - if (g < 0) - return -EINVAL; - - h = unbase32hexchar(x[7]); - if (h < 0) - return -EINVAL; - - *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */ - *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */ - *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */ - *(z++) = (uint8_t) e << 7 | (uint8_t) f << 2 | (uint8_t) g >> 3; /* SQQQQQVV */ - *(z++) = (uint8_t) g << 5 | (uint8_t) h; /* VVVRRRRR */ - } - - switch (l % 8) { - case 7: - a = unbase32hexchar(x[0]); - if (a < 0) - return -EINVAL; - - b = unbase32hexchar(x[1]); - if (b < 0) - return -EINVAL; - - c = unbase32hexchar(x[2]); - if (c < 0) - return -EINVAL; - - d = unbase32hexchar(x[3]); - if (d < 0) - return -EINVAL; - - e = unbase32hexchar(x[4]); - if (e < 0) - return -EINVAL; - - f = unbase32hexchar(x[5]); - if (f < 0) - return -EINVAL; - - g = unbase32hexchar(x[6]); - if (g < 0) - return -EINVAL; - - /* g == 000VV000 */ - if (g & 7) - return -EINVAL; - - *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */ - *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */ - *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */ - *(z++) = (uint8_t) e << 7 | (uint8_t) f << 2 | (uint8_t) g >> 3; /* SQQQQQVV */ - - break; - case 5: - a = unbase32hexchar(x[0]); - if (a < 0) - return -EINVAL; - - b = unbase32hexchar(x[1]); - if (b < 0) - return -EINVAL; - - c = unbase32hexchar(x[2]); - if (c < 0) - return -EINVAL; - - d = unbase32hexchar(x[3]); - if (d < 0) - return -EINVAL; - - e = unbase32hexchar(x[4]); - if (e < 0) - return -EINVAL; - - /* e == 000SSSS0 */ - if (e & 1) - return -EINVAL; - - *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */ - *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */ - *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */ - - break; - case 4: - a = unbase32hexchar(x[0]); - if (a < 0) - return -EINVAL; - - b = unbase32hexchar(x[1]); - if (b < 0) - return -EINVAL; - - c = unbase32hexchar(x[2]); - if (c < 0) - return -EINVAL; - - d = unbase32hexchar(x[3]); - if (d < 0) - return -EINVAL; - - /* d == 000W0000 */ - if (d & 15) - return -EINVAL; - - *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */ - *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */ - - break; - case 2: - a = unbase32hexchar(x[0]); - if (a < 0) - return -EINVAL; - - b = unbase32hexchar(x[1]); - if (b < 0) - return -EINVAL; - - /* b == 000YYY00 */ - if (b & 3) - return -EINVAL; - - *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */ - - break; - case 0: - break; - default: - return -EINVAL; - } - - *z = 0; - - *mem = r; - r = NULL; - *_len = len; - - return 0; -} - -/* https://tools.ietf.org/html/rfc4648#section-4 */ -char base64char(int x) { - static const char table[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789+/"; - return table[x & 63]; -} - -int unbase64char(char c) { - unsigned offset; - - if (c >= 'A' && c <= 'Z') - return c - 'A'; - - offset = 'Z' - 'A' + 1; - - if (c >= 'a' && c <= 'z') - return c - 'a' + offset; - - offset += 'z' - 'a' + 1; - - if (c >= '0' && c <= '9') - return c - '0' + offset; - - offset += '9' - '0' + 1; - - if (c == '+') - return offset; - - offset ++; - - if (c == '/') - return offset; - - return -EINVAL; -} - -char *base64mem(const void *p, size_t l) { - char *r, *z; - const uint8_t *x; - - /* three input bytes makes four output bytes, padding is added so we must round up */ - z = r = malloc(4 * (l + 2) / 3 + 1); - if (!r) - return NULL; - - for (x = p; x < (const uint8_t*) p + (l / 3) * 3; x += 3) { - /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ */ - *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */ - *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4); /* 00XXYYYY */ - *(z++) = base64char((x[1] & 15) << 2 | x[2] >> 6); /* 00YYYYZZ */ - *(z++) = base64char(x[2] & 63); /* 00ZZZZZZ */ - } - - switch (l % 3) { - case 2: - *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */ - *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4); /* 00XXYYYY */ - *(z++) = base64char((x[1] & 15) << 2); /* 00YYYY00 */ - *(z++) = '='; - - break; - case 1: - *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */ - *(z++) = base64char((x[0] & 3) << 4); /* 00XX0000 */ - *(z++) = '='; - *(z++) = '='; - - break; - } - - *z = 0; - return r; -} - -int unbase64mem(const char *p, size_t l, void **mem, size_t *_len) { - _cleanup_free_ uint8_t *r = NULL; - int a, b, c, d; - uint8_t *z; - const char *x; - size_t len; - - assert(p); - - /* padding ensures any base63 input has input divisible by 4 */ - if (l % 4 != 0) - return -EINVAL; - - /* strip the padding */ - if (l > 0 && p[l - 1] == '=') - l --; - if (l > 0 && p[l - 1] == '=') - l --; - - /* a group of four input bytes needs three output bytes, in case of - padding we need to add two or three extra bytes */ - len = (l / 4) * 3 + (l % 4 ? (l % 4) - 1 : 0); - - z = r = malloc(len + 1); - if (!r) - return -ENOMEM; - - for (x = p; x < p + (l / 4) * 4; x += 4) { - /* a == 00XXXXXX; b == 00YYYYYY; c == 00ZZZZZZ; d == 00WWWWWW */ - a = unbase64char(x[0]); - if (a < 0) - return -EINVAL; - - b = unbase64char(x[1]); - if (b < 0) - return -EINVAL; - - c = unbase64char(x[2]); - if (c < 0) - return -EINVAL; - - d = unbase64char(x[3]); - if (d < 0) - return -EINVAL; - - *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */ - *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */ - *(z++) = (uint8_t) c << 6 | (uint8_t) d; /* ZZWWWWWW */ - } - - switch (l % 4) { - case 3: - a = unbase64char(x[0]); - if (a < 0) - return -EINVAL; - - b = unbase64char(x[1]); - if (b < 0) - return -EINVAL; - - c = unbase64char(x[2]); - if (c < 0) - return -EINVAL; - - /* c == 00ZZZZ00 */ - if (c & 3) - return -EINVAL; - - *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */ - *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */ - - break; - case 2: - a = unbase64char(x[0]); - if (a < 0) - return -EINVAL; - - b = unbase64char(x[1]); - if (b < 0) - return -EINVAL; - - /* b == 00YY0000 */ - if (b & 15) - return -EINVAL; - - *(z++) = (uint8_t) a << 2 | (uint8_t) (b >> 4); /* XXXXXXYY */ - - break; - case 0: - - break; - default: - return -EINVAL; - } - - *z = 0; - - *mem = r; - r = NULL; - *_len = len; - - return 0; -} - -char octchar(int x) { - return '0' + (x & 7); -} - -int unoctchar(char c) { - - if (c >= '0' && c <= '7') - return c - '0'; - - return -EINVAL; -} - -char decchar(int x) { - return '0' + (x % 10); -} - -int undecchar(char c) { - - if (c >= '0' && c <= '9') - return c - '0'; - - return -EINVAL; -} - -_pure_ static bool hidden_file_allow_backup(const char *filename) { - assert(filename); - - return - filename[0] == '.' || - streq(filename, "lost+found") || - streq(filename, "aquota.user") || - streq(filename, "aquota.group") || - endswith(filename, ".rpmnew") || - endswith(filename, ".rpmsave") || - endswith(filename, ".rpmorig") || - endswith(filename, ".dpkg-old") || - endswith(filename, ".dpkg-new") || - endswith(filename, ".dpkg-tmp") || - endswith(filename, ".dpkg-dist") || - endswith(filename, ".dpkg-bak") || - endswith(filename, ".dpkg-backup") || - endswith(filename, ".dpkg-remove") || - endswith(filename, ".swp"); -} - -bool hidden_file(const char *filename) { - assert(filename); - - if (endswith(filename, "~")) - return true; - - return hidden_file_allow_backup(filename); -} - -bool fstype_is_network(const char *fstype) { - static const char table[] = - "afs\0" - "cifs\0" - "smbfs\0" - "sshfs\0" - "ncpfs\0" - "ncp\0" - "nfs\0" - "nfs4\0" - "gfs\0" - "gfs2\0" - "glusterfs\0"; - - const char *x; - - x = startswith(fstype, "fuse."); - if (x) - fstype = x; - - return nulstr_contains(table, fstype); -} - -int parse_size(const char *t, uint64_t base, uint64_t *size) { - - /* Soo, sometimes we want to parse IEC binary suffixes, and - * sometimes SI decimal suffixes. This function can parse - * both. Which one is the right way depends on the - * context. Wikipedia suggests that SI is customary for - * hardware metrics and network speeds, while IEC is - * customary for most data sizes used by software and volatile - * (RAM) memory. Hence be careful which one you pick! - * - * In either case we use just K, M, G as suffix, and not Ki, - * Mi, Gi or so (as IEC would suggest). That's because that's - * frickin' ugly. But this means you really need to make sure - * to document which base you are parsing when you use this - * call. */ - - struct table { - const char *suffix; - unsigned long long factor; - }; - - static const struct table iec[] = { - { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL }, - { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL }, - { "T", 1024ULL*1024ULL*1024ULL*1024ULL }, - { "G", 1024ULL*1024ULL*1024ULL }, - { "M", 1024ULL*1024ULL }, - { "K", 1024ULL }, - { "B", 1ULL }, - { "", 1ULL }, - }; - - static const struct table si[] = { - { "E", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL*1000ULL }, - { "P", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL }, - { "T", 1000ULL*1000ULL*1000ULL*1000ULL }, - { "G", 1000ULL*1000ULL*1000ULL }, - { "M", 1000ULL*1000ULL }, - { "K", 1000ULL }, - { "B", 1ULL }, - { "", 1ULL }, - }; - - const struct table *table; - const char *p; - unsigned long long r = 0; - unsigned n_entries, start_pos = 0; - - assert(t); - assert(base == 1000 || base == 1024); - assert(size); - - if (base == 1000) { - table = si; - n_entries = ELEMENTSOF(si); - } else { - table = iec; - n_entries = ELEMENTSOF(iec); - } - - p = t; - do { - unsigned long long l, tmp; - double frac = 0; - char *e; - unsigned i; - - p += strspn(p, WHITESPACE); - if (*p == '-') - return -ERANGE; - - errno = 0; - l = strtoull(p, &e, 10); - if (errno > 0) - return -errno; - if (e == p) - return -EINVAL; - - if (*e == '.') { - e++; - - /* strtoull() itself would accept space/+/- */ - if (*e >= '0' && *e <= '9') { - unsigned long long l2; - char *e2; - - l2 = strtoull(e, &e2, 10); - if (errno > 0) - return -errno; - - /* Ignore failure. E.g. 10.M is valid */ - frac = l2; - for (; e < e2; e++) - frac /= 10; - } - } - - e += strspn(e, WHITESPACE); - - for (i = start_pos; i < n_entries; i++) - if (startswith(e, table[i].suffix)) - break; - - if (i >= n_entries) - return -EINVAL; - - if (l + (frac > 0) > ULLONG_MAX / table[i].factor) - return -ERANGE; - - tmp = l * table[i].factor + (unsigned long long) (frac * table[i].factor); - if (tmp > ULLONG_MAX - r) - return -ERANGE; - - r += tmp; - if ((unsigned long long) (uint64_t) r != r) - return -ERANGE; - - p = e + strlen(table[i].suffix); - - start_pos = i + 1; - - } while (*p); - - *size = r; - - return 0; -} - -bool is_device_path(const char *path) { - - /* Returns true on paths that refer to a device, either in - * sysfs or in /dev */ - - return - path_startswith(path, "/dev/") || - path_startswith(path, "/sys/"); -} - -int dir_is_empty(const char *path) { - _cleanup_closedir_ DIR *d; - struct dirent *de; - - d = opendir(path); - if (!d) - return -errno; - - FOREACH_DIRENT(de, d, return -errno) - return 0; - - return 1; -} - -char* dirname_malloc(const char *path) { - char *d, *dir, *dir2; - - d = strdup(path); - if (!d) - return NULL; - dir = dirname(d); - assert(dir); - - if (dir != d) { - dir2 = strdup(dir); - free(d); - return dir2; - } - - return dir; -} - -void rename_process(const char name[8]) { - assert(name); - - /* This is a like a poor man's setproctitle(). It changes the - * comm field, argv[0], and also the glibc's internally used - * name of the process. For the first one a limit of 16 chars - * applies, to the second one usually one of 10 (i.e. length - * of "/sbin/init"), to the third one one of 7 (i.e. length of - * "systemd"). If you pass a longer string it will be - * truncated */ - - prctl(PR_SET_NAME, name); - - if (program_invocation_name) - strncpy(program_invocation_name, name, strlen(program_invocation_name)); - - if (saved_argc > 0) { - int i; - - if (saved_argv[0]) - strncpy(saved_argv[0], name, strlen(saved_argv[0])); - - for (i = 1; i < saved_argc; i++) { - if (!saved_argv[i]) - break; - - memzero(saved_argv[i], strlen(saved_argv[i])); - } - } -} - -bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) { - assert(s); - assert_cc(sizeof(statfs_f_type_t) >= sizeof(s->f_type)); - - return F_TYPE_EQUAL(s->f_type, magic_value); -} - -int fd_check_fstype(int fd, statfs_f_type_t magic_value) { - struct statfs s; - - if (fstatfs(fd, &s) < 0) - return -errno; - - return is_fs_type(&s, magic_value); -} - -int path_check_fstype(const char *path, statfs_f_type_t magic_value) { - _cleanup_close_ int fd = -1; - - fd = open(path, O_RDONLY); - if (fd < 0) - return -errno; - - return fd_check_fstype(fd, magic_value); -} - -bool is_temporary_fs(const struct statfs *s) { - return is_fs_type(s, TMPFS_MAGIC) || - is_fs_type(s, RAMFS_MAGIC); -} - -int fd_is_temporary_fs(int fd) { - struct statfs s; - - if (fstatfs(fd, &s) < 0) - return -errno; - - return is_temporary_fs(&s); -} - -int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) { - assert(path); - - /* Under the assumption that we are running privileged we - * first change the access mode and only then hand out - * ownership to avoid a window where access is too open. */ - - if (mode != MODE_INVALID) - if (chmod(path, mode) < 0) - return -errno; - - if (uid != UID_INVALID || gid != GID_INVALID) - if (chown(path, uid, gid) < 0) - return -errno; - - return 0; -} - -int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid) { - assert(fd >= 0); - - /* Under the assumption that we are running privileged we - * first change the access mode and only then hand out - * ownership to avoid a window where access is too open. */ - - if (mode != MODE_INVALID) - if (fchmod(fd, mode) < 0) - return -errno; - - if (uid != UID_INVALID || gid != GID_INVALID) - if (fchown(fd, uid, gid) < 0) - return -errno; - - return 0; -} - -int files_same(const char *filea, const char *fileb) { - struct stat a, b; - - if (stat(filea, &a) < 0) - return -errno; - - if (stat(fileb, &b) < 0) - return -errno; - - return a.st_dev == b.st_dev && - a.st_ino == b.st_ino; -} - -int running_in_chroot(void) { - int ret; - - ret = files_same("/proc/1/root", "/"); - if (ret < 0) - return ret; - - return ret == 0; -} - -int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode) { - _cleanup_close_ int fd; - int r; - - assert(path); - - if (parents) - mkdir_parents(path, 0755); - - fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, mode > 0 ? mode : 0644); - if (fd < 0) - return -errno; - - if (mode > 0) { - r = fchmod(fd, mode); - if (r < 0) - return -errno; - } - - if (uid != UID_INVALID || gid != GID_INVALID) { - r = fchown(fd, uid, gid); - if (r < 0) - return -errno; - } - - if (stamp != USEC_INFINITY) { - struct timespec ts[2]; - - timespec_store(&ts[0], stamp); - ts[1] = ts[0]; - r = futimens(fd, ts); - } else - r = futimens(fd, NULL); - if (r < 0) - return -errno; - - return 0; -} - -int touch(const char *path) { - return touch_file(path, false, USEC_INFINITY, UID_INVALID, GID_INVALID, 0); -} - -static char *unquote(const char *s, const char* quotes) { - size_t l; - assert(s); - - /* This is rather stupid, simply removes the heading and - * trailing quotes if there is one. Doesn't care about - * escaping or anything. - * - * DON'T USE THIS FOR NEW CODE ANYMORE!*/ - - l = strlen(s); - if (l < 2) - return strdup(s); - - if (strchr(quotes, s[0]) && s[l-1] == s[0]) - return strndup(s+1, l-2); - - return strdup(s); -} - -noreturn void freeze(void) { - - /* Make sure nobody waits for us on a socket anymore */ - close_all_fds(NULL, 0); - - sync(); - - for (;;) - pause(); -} - -bool null_or_empty(struct stat *st) { - assert(st); - - if (S_ISREG(st->st_mode) && st->st_size <= 0) - return true; - - if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) - return true; - - return false; -} - -int null_or_empty_path(const char *fn) { - struct stat st; - - assert(fn); - - if (stat(fn, &st) < 0) - return -errno; - - return null_or_empty(&st); -} - -int null_or_empty_fd(int fd) { - struct stat st; - - assert(fd >= 0); - - if (fstat(fd, &st) < 0) - return -errno; - - return null_or_empty(&st); -} - -DIR *xopendirat(int fd, const char *name, int flags) { - int nfd; - DIR *d; - - assert(!(flags & O_CREAT)); - - nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags, 0); - if (nfd < 0) - return NULL; - - d = fdopendir(nfd); - if (!d) { - safe_close(nfd); - return NULL; - } - - return d; -} - -static char *tag_to_udev_node(const char *tagvalue, const char *by) { - _cleanup_free_ char *t = NULL, *u = NULL; - size_t enc_len; - - u = unquote(tagvalue, QUOTES); - if (!u) - return NULL; - - enc_len = strlen(u) * 4 + 1; - t = new(char, enc_len); - if (!t) - return NULL; - - if (encode_devnode_name(u, t, enc_len) < 0) - return NULL; - - return strjoin("/dev/disk/by-", by, "/", t, NULL); -} - -char *fstab_node_to_udev_node(const char *p) { - assert(p); - - if (startswith(p, "LABEL=")) - return tag_to_udev_node(p+6, "label"); - - if (startswith(p, "UUID=")) - return tag_to_udev_node(p+5, "uuid"); - - if (startswith(p, "PARTUUID=")) - return tag_to_udev_node(p+9, "partuuid"); - - if (startswith(p, "PARTLABEL=")) - return tag_to_udev_node(p+10, "partlabel"); - - return strdup(p); -} - -bool dirent_is_file(const struct dirent *de) { - assert(de); - - if (hidden_file(de->d_name)) - return false; - - if (de->d_type != DT_REG && - de->d_type != DT_LNK && - de->d_type != DT_UNKNOWN) - return false; - - return true; -} - -bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) { - assert(de); - - if (de->d_type != DT_REG && - de->d_type != DT_LNK && - de->d_type != DT_UNKNOWN) - return false; - - if (hidden_file_allow_backup(de->d_name)) - return false; - - return endswith(de->d_name, suffix); -} - static int do_execute(char **directories, usec_t timeout, char *argv[]) { _cleanup_hashmap_free_free_ Hashmap *pids = NULL; _cleanup_set_free_free_ Set *seen = NULL; @@ -1831,125 +269,6 @@ bool plymouth_running(void) { return access("/run/plymouth/pid", F_OK) >= 0; } -int fopen_temporary(const char *path, FILE **_f, char **_temp_path) { - FILE *f; - char *t; - int r, fd; - - assert(path); - assert(_f); - assert(_temp_path); - - r = tempfn_xxxxxx(path, NULL, &t); - if (r < 0) - return r; - - fd = mkostemp_safe(t, O_WRONLY|O_CLOEXEC); - if (fd < 0) { - free(t); - return -errno; - } - - f = fdopen(fd, "we"); - if (!f) { - unlink_noerrno(t); - free(t); - safe_close(fd); - return -errno; - } - - *_f = f; - *_temp_path = t; - - return 0; -} - -int symlink_atomic(const char *from, const char *to) { - _cleanup_free_ char *t = NULL; - int r; - - assert(from); - assert(to); - - r = tempfn_random(to, NULL, &t); - if (r < 0) - return r; - - if (symlink(from, t) < 0) - return -errno; - - if (rename(t, to) < 0) { - unlink_noerrno(t); - return -errno; - } - - return 0; -} - -int symlink_idempotent(const char *from, const char *to) { - _cleanup_free_ char *p = NULL; - int r; - - assert(from); - assert(to); - - if (symlink(from, to) < 0) { - if (errno != EEXIST) - return -errno; - - r = readlink_malloc(to, &p); - if (r < 0) - return r; - - if (!streq(p, from)) - return -EINVAL; - } - - return 0; -} - -int mknod_atomic(const char *path, mode_t mode, dev_t dev) { - _cleanup_free_ char *t = NULL; - int r; - - assert(path); - - r = tempfn_random(path, NULL, &t); - if (r < 0) - return r; - - if (mknod(t, mode, dev) < 0) - return -errno; - - if (rename(t, path) < 0) { - unlink_noerrno(t); - return -errno; - } - - return 0; -} - -int mkfifo_atomic(const char *path, mode_t mode) { - _cleanup_free_ char *t = NULL; - int r; - - assert(path); - - r = tempfn_random(path, NULL, &t); - if (r < 0) - return r; - - if (mkfifo(t, mode) < 0) - return -errno; - - if (rename(t, path) < 0) { - unlink_noerrno(t); - return -errno; - } - - return 0; -} - bool display_is_local(const char *display) { assert(display); @@ -1984,135 +303,6 @@ int socket_from_display(const char *display, char **path) { return 0; } -int glob_exists(const char *path) { - _cleanup_globfree_ glob_t g = {}; - int k; - - assert(path); - - errno = 0; - k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g); - - if (k == GLOB_NOMATCH) - return 0; - else if (k == GLOB_NOSPACE) - return -ENOMEM; - else if (k == 0) - return !strv_isempty(g.gl_pathv); - else - return errno ? -errno : -EIO; -} - -int glob_extend(char ***strv, const char *path) { - _cleanup_globfree_ glob_t g = {}; - int k; - char **p; - - errno = 0; - k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g); - - if (k == GLOB_NOMATCH) - return -ENOENT; - else if (k == GLOB_NOSPACE) - return -ENOMEM; - else if (k != 0 || strv_isempty(g.gl_pathv)) - return errno ? -errno : -EIO; - - STRV_FOREACH(p, g.gl_pathv) { - k = strv_extend(strv, *p); - if (k < 0) - break; - } - - return k; -} - -int dirent_ensure_type(DIR *d, struct dirent *de) { - struct stat st; - - assert(d); - assert(de); - - if (de->d_type != DT_UNKNOWN) - return 0; - - if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) - return -errno; - - de->d_type = - S_ISREG(st.st_mode) ? DT_REG : - S_ISDIR(st.st_mode) ? DT_DIR : - S_ISLNK(st.st_mode) ? DT_LNK : - S_ISFIFO(st.st_mode) ? DT_FIFO : - S_ISSOCK(st.st_mode) ? DT_SOCK : - S_ISCHR(st.st_mode) ? DT_CHR : - S_ISBLK(st.st_mode) ? DT_BLK : - DT_UNKNOWN; - - return 0; -} - -int get_files_in_directory(const char *path, char ***list) { - _cleanup_closedir_ DIR *d = NULL; - size_t bufsize = 0, n = 0; - _cleanup_strv_free_ char **l = NULL; - - assert(path); - - /* Returns all files in a directory in *list, and the number - * of files as return value. If list is NULL returns only the - * number. */ - - d = opendir(path); - if (!d) - return -errno; - - for (;;) { - struct dirent *de; - - errno = 0; - de = readdir(d); - if (!de && errno != 0) - return -errno; - if (!de) - break; - - dirent_ensure_type(d, de); - - if (!dirent_is_file(de)) - continue; - - if (list) { - /* one extra slot is needed for the terminating NULL */ - if (!GREEDY_REALLOC(l, bufsize, n + 2)) - return -ENOMEM; - - l[n] = strdup(de->d_name); - if (!l[n]) - return -ENOMEM; - - l[++n] = NULL; - } else - n++; - } - - if (list) { - *list = l; - l = NULL; /* avoid freeing */ - } - - return n; -} - -bool is_main_thread(void) { - static thread_local int cached = 0; - - if (_unlikely_(cached == 0)) - cached = getpid() == gettid() ? 1 : -1; - - return cached > 0; -} - int block_get_whole_disk(dev_t d, dev_t *ret) { char *p, *s; int r; @@ -2173,103 +363,6 @@ int block_get_whole_disk(dev_t d, dev_t *ret) { return -ENOENT; } -static const char *const ioprio_class_table[] = { - [IOPRIO_CLASS_NONE] = "none", - [IOPRIO_CLASS_RT] = "realtime", - [IOPRIO_CLASS_BE] = "best-effort", - [IOPRIO_CLASS_IDLE] = "idle" -}; - -DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, INT_MAX); - -static const char *const sigchld_code_table[] = { - [CLD_EXITED] = "exited", - [CLD_KILLED] = "killed", - [CLD_DUMPED] = "dumped", - [CLD_TRAPPED] = "trapped", - [CLD_STOPPED] = "stopped", - [CLD_CONTINUED] = "continued", -}; - -DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int); - -static const char *const log_facility_unshifted_table[LOG_NFACILITIES] = { - [LOG_FAC(LOG_KERN)] = "kern", - [LOG_FAC(LOG_USER)] = "user", - [LOG_FAC(LOG_MAIL)] = "mail", - [LOG_FAC(LOG_DAEMON)] = "daemon", - [LOG_FAC(LOG_AUTH)] = "auth", - [LOG_FAC(LOG_SYSLOG)] = "syslog", - [LOG_FAC(LOG_LPR)] = "lpr", - [LOG_FAC(LOG_NEWS)] = "news", - [LOG_FAC(LOG_UUCP)] = "uucp", - [LOG_FAC(LOG_CRON)] = "cron", - [LOG_FAC(LOG_AUTHPRIV)] = "authpriv", - [LOG_FAC(LOG_FTP)] = "ftp", - [LOG_FAC(LOG_LOCAL0)] = "local0", - [LOG_FAC(LOG_LOCAL1)] = "local1", - [LOG_FAC(LOG_LOCAL2)] = "local2", - [LOG_FAC(LOG_LOCAL3)] = "local3", - [LOG_FAC(LOG_LOCAL4)] = "local4", - [LOG_FAC(LOG_LOCAL5)] = "local5", - [LOG_FAC(LOG_LOCAL6)] = "local6", - [LOG_FAC(LOG_LOCAL7)] = "local7" -}; - -DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_facility_unshifted, int, LOG_FAC(~0)); - -bool log_facility_unshifted_is_valid(int facility) { - return facility >= 0 && facility <= LOG_FAC(~0); -} - -static const char *const log_level_table[] = { - [LOG_EMERG] = "emerg", - [LOG_ALERT] = "alert", - [LOG_CRIT] = "crit", - [LOG_ERR] = "err", - [LOG_WARNING] = "warning", - [LOG_NOTICE] = "notice", - [LOG_INFO] = "info", - [LOG_DEBUG] = "debug" -}; - -DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_level, int, LOG_DEBUG); - -bool log_level_is_valid(int level) { - return level >= 0 && level <= LOG_DEBUG; -} - -static const char* const sched_policy_table[] = { - [SCHED_OTHER] = "other", - [SCHED_BATCH] = "batch", - [SCHED_IDLE] = "idle", - [SCHED_FIFO] = "fifo", - [SCHED_RR] = "rr" -}; - -DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX); - -static const char* const rlimit_table[_RLIMIT_MAX] = { - [RLIMIT_CPU] = "LimitCPU", - [RLIMIT_FSIZE] = "LimitFSIZE", - [RLIMIT_DATA] = "LimitDATA", - [RLIMIT_STACK] = "LimitSTACK", - [RLIMIT_CORE] = "LimitCORE", - [RLIMIT_RSS] = "LimitRSS", - [RLIMIT_NOFILE] = "LimitNOFILE", - [RLIMIT_AS] = "LimitAS", - [RLIMIT_NPROC] = "LimitNPROC", - [RLIMIT_MEMLOCK] = "LimitMEMLOCK", - [RLIMIT_LOCKS] = "LimitLOCKS", - [RLIMIT_SIGPENDING] = "LimitSIGPENDING", - [RLIMIT_MSGQUEUE] = "LimitMSGQUEUE", - [RLIMIT_NICE] = "LimitNICE", - [RLIMIT_RTPRIO] = "LimitRTPRIO", - [RLIMIT_RTTIME] = "LimitRTTIME" -}; - -DEFINE_STRING_TABLE_LOOKUP(rlimit, int); - bool kexec_loaded(void) { bool loaded = false; char *s; @@ -2300,58 +393,6 @@ int prot_from_flags(int flags) { } } -char *format_bytes(char *buf, size_t l, uint64_t t) { - unsigned i; - - static const struct { - const char *suffix; - uint64_t factor; - } table[] = { - { "E", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) }, - { "P", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) }, - { "T", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) }, - { "G", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) }, - { "M", UINT64_C(1024)*UINT64_C(1024) }, - { "K", UINT64_C(1024) }, - }; - - if (t == (uint64_t) -1) - return NULL; - - for (i = 0; i < ELEMENTSOF(table); i++) { - - if (t >= table[i].factor) { - snprintf(buf, l, - "%" PRIu64 ".%" PRIu64 "%s", - t / table[i].factor, - ((t*UINT64_C(10)) / table[i].factor) % UINT64_C(10), - table[i].suffix); - - goto finish; - } - } - - snprintf(buf, l, "%" PRIu64 "B", t); - -finish: - buf[l-1] = 0; - return buf; - -} - -void* memdup(const void *p, size_t l) { - void *r; - - assert(p); - - r = malloc(l); - if (!r) - return NULL; - - memcpy(r, p, l); - return r; -} - int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) { bool stdout_is_tty, stderr_is_tty; pid_t parent_pid, agent_pid; @@ -2454,82 +495,6 @@ int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *pa _exit(EXIT_FAILURE); } -int setrlimit_closest(int resource, const struct rlimit *rlim) { - struct rlimit highest, fixed; - - assert(rlim); - - if (setrlimit(resource, rlim) >= 0) - return 0; - - if (errno != EPERM) - return -errno; - - /* So we failed to set the desired setrlimit, then let's try - * to get as close as we can */ - assert_se(getrlimit(resource, &highest) == 0); - - fixed.rlim_cur = MIN(rlim->rlim_cur, highest.rlim_max); - fixed.rlim_max = MIN(rlim->rlim_max, highest.rlim_max); - - if (setrlimit(resource, &fixed) < 0) - return -errno; - - return 0; -} - -bool http_etag_is_valid(const char *etag) { - if (isempty(etag)) - return false; - - if (!endswith(etag, "\"")) - return false; - - if (!startswith(etag, "\"") && !startswith(etag, "W/\"")) - return false; - - return true; -} - -bool http_url_is_valid(const char *url) { - const char *p; - - if (isempty(url)) - return false; - - p = startswith(url, "http://"); - if (!p) - p = startswith(url, "https://"); - if (!p) - return false; - - if (isempty(p)) - return false; - - return ascii_is_valid(p); -} - -bool documentation_url_is_valid(const char *url) { - const char *p; - - if (isempty(url)) - return false; - - if (http_url_is_valid(url)) - return true; - - p = startswith(url, "file:/"); - if (!p) - p = startswith(url, "info:"); - if (!p) - p = startswith(url, "man:"); - - if (isempty(p)) - return false; - - return ascii_is_valid(p); -} - bool in_initrd(void) { static int saved = -1; struct statfs s; @@ -2554,64 +519,6 @@ bool in_initrd(void) { return saved; } -bool filename_is_valid(const char *p) { - - if (isempty(p)) - return false; - - if (strchr(p, '/')) - return false; - - if (streq(p, ".")) - return false; - - if (streq(p, "..")) - return false; - - if (strlen(p) > FILENAME_MAX) - return false; - - return true; -} - -bool string_is_safe(const char *p) { - const char *t; - - if (!p) - return false; - - for (t = p; *t; t++) { - if (*t > 0 && *t < ' ') - return false; - - if (strchr("\\\"\'\x7f", *t)) - return false; - } - - return true; -} - -bool path_is_safe(const char *p) { - - if (isempty(p)) - return false; - - if (streq(p, "..") || startswith(p, "../") || endswith(p, "/..") || strstr(p, "/../")) - return false; - - if (strlen(p)+1 > PATH_MAX) - return false; - - /* The following two checks are not really dangerous, but hey, they still are confusing */ - if (streq(p, ".") || startswith(p, "./") || endswith(p, "/.") || strstr(p, "/./")) - return false; - - if (strstr(p, "//")) - return false; - - return true; -} - /* hey glibc, APIs with callbacks without a user pointer are so useless */ void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size, int (*compar) (const void *, const void *, void *), void *arg) { @@ -2635,83 +542,6 @@ void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size, return NULL; } -void init_gettext(void) { - setlocale(LC_ALL, ""); - textdomain(GETTEXT_PACKAGE); -} - -bool is_locale_utf8(void) { - const char *set; - static int cached_answer = -1; - - if (cached_answer >= 0) - goto out; - - if (!setlocale(LC_ALL, "")) { - cached_answer = true; - goto out; - } - - set = nl_langinfo(CODESET); - if (!set) { - cached_answer = true; - goto out; - } - - if (streq(set, "UTF-8")) { - cached_answer = true; - goto out; - } - - /* For LC_CTYPE=="C" return true, because CTYPE is effectly - * unset and everything can do to UTF-8 nowadays. */ - set = setlocale(LC_CTYPE, NULL); - if (!set) { - cached_answer = true; - goto out; - } - - /* Check result, but ignore the result if C was set - * explicitly. */ - cached_answer = - STR_IN_SET(set, "C", "POSIX") && - !getenv("LC_ALL") && - !getenv("LC_CTYPE") && - !getenv("LANG"); - -out: - return (bool) cached_answer; -} - -const char *draw_special_char(DrawSpecialChar ch) { - static const char *draw_table[2][_DRAW_SPECIAL_CHAR_MAX] = { - - /* UTF-8 */ { - [DRAW_TREE_VERTICAL] = "\342\224\202 ", /* │ */ - [DRAW_TREE_BRANCH] = "\342\224\234\342\224\200", /* ├─ */ - [DRAW_TREE_RIGHT] = "\342\224\224\342\224\200", /* └─ */ - [DRAW_TREE_SPACE] = " ", /* */ - [DRAW_TRIANGULAR_BULLET] = "\342\200\243", /* ‣ */ - [DRAW_BLACK_CIRCLE] = "\342\227\217", /* ● */ - [DRAW_ARROW] = "\342\206\222", /* → */ - [DRAW_DASH] = "\342\200\223", /* – */ - }, - - /* ASCII fallback */ { - [DRAW_TREE_VERTICAL] = "| ", - [DRAW_TREE_BRANCH] = "|-", - [DRAW_TREE_RIGHT] = "`-", - [DRAW_TREE_SPACE] = " ", - [DRAW_TRIANGULAR_BULLET] = ">", - [DRAW_BLACK_CIRCLE] = "*", - [DRAW_ARROW] = "->", - [DRAW_DASH] = "-", - } - }; - - return draw_table[!is_locale_utf8()][ch]; -} - int on_ac_power(void) { bool found_offline = false, found_online = false; _cleanup_closedir_ DIR *d = NULL; @@ -2788,133 +618,6 @@ int on_ac_power(void) { return found_online || !found_offline; } -static int search_and_fopen_internal(const char *path, const char *mode, const char *root, char **search, FILE **_f) { - char **i; - - assert(path); - assert(mode); - assert(_f); - - if (!path_strv_resolve_uniq(search, root)) - return -ENOMEM; - - STRV_FOREACH(i, search) { - _cleanup_free_ char *p = NULL; - FILE *f; - - if (root) - p = strjoin(root, *i, "/", path, NULL); - else - p = strjoin(*i, "/", path, NULL); - if (!p) - return -ENOMEM; - - f = fopen(p, mode); - if (f) { - *_f = f; - return 0; - } - - if (errno != ENOENT) - return -errno; - } - - return -ENOENT; -} - -int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f) { - _cleanup_strv_free_ char **copy = NULL; - - assert(path); - assert(mode); - assert(_f); - - if (path_is_absolute(path)) { - FILE *f; - - f = fopen(path, mode); - if (f) { - *_f = f; - return 0; - } - - return -errno; - } - - copy = strv_copy((char**) search); - if (!copy) - return -ENOMEM; - - return search_and_fopen_internal(path, mode, root, copy, _f); -} - -int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f) { - _cleanup_strv_free_ char **s = NULL; - - if (path_is_absolute(path)) { - FILE *f; - - f = fopen(path, mode); - if (f) { - *_f = f; - return 0; - } - - return -errno; - } - - s = strv_split_nulstr(search); - if (!s) - return -ENOMEM; - - return search_and_fopen_internal(path, mode, root, s, _f); -} - -void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) { - size_t a, newalloc; - void *q; - - assert(p); - assert(allocated); - - if (*allocated >= need) - return *p; - - newalloc = MAX(need * 2, 64u / size); - a = newalloc * size; - - /* check for overflows */ - if (a < size * need) - return NULL; - - q = realloc(*p, a); - if (!q) - return NULL; - - *p = q; - *allocated = newalloc; - return q; -} - -void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size) { - size_t prev; - uint8_t *q; - - assert(p); - assert(allocated); - - prev = *allocated; - - q = greedy_realloc(p, allocated, need, size); - if (!q) - return NULL; - - if (*allocated > prev) - memzero(q + prev * size, (*allocated - prev) * size); - - return q; -} - bool id128_is_valid(const char *s) { size_t i, l; @@ -2956,120 +659,6 @@ bool id128_is_valid(const char *s) { return true; } -int shall_restore_state(void) { - _cleanup_free_ char *value = NULL; - int r; - - r = get_proc_cmdline_key("systemd.restore_state=", &value); - if (r < 0) - return r; - if (r == 0) - return true; - - return parse_boolean(value) != 0; -} - -int proc_cmdline(char **ret) { - assert(ret); - - if (detect_container() > 0) - return get_process_cmdline(1, 0, false, ret); - else - return read_one_line_file("/proc/cmdline", ret); -} - -int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value)) { - _cleanup_free_ char *line = NULL; - const char *p; - int r; - - assert(parse_item); - - r = proc_cmdline(&line); - if (r < 0) - return r; - - p = line; - for (;;) { - _cleanup_free_ char *word = NULL; - char *value = NULL; - - r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX); - if (r < 0) - return r; - if (r == 0) - break; - - /* Filter out arguments that are intended only for the - * initrd */ - if (!in_initrd() && startswith(word, "rd.")) - continue; - - value = strchr(word, '='); - if (value) - *(value++) = 0; - - r = parse_item(word, value); - if (r < 0) - return r; - } - - return 0; -} - -int get_proc_cmdline_key(const char *key, char **value) { - _cleanup_free_ char *line = NULL, *ret = NULL; - bool found = false; - const char *p; - int r; - - assert(key); - - r = proc_cmdline(&line); - if (r < 0) - return r; - - p = line; - for (;;) { - _cleanup_free_ char *word = NULL; - const char *e; - - r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX); - if (r < 0) - return r; - if (r == 0) - break; - - /* Filter out arguments that are intended only for the - * initrd */ - if (!in_initrd() && startswith(word, "rd.")) - continue; - - if (value) { - e = startswith(word, key); - if (!e) - continue; - - r = free_and_strdup(&ret, e); - if (r < 0) - return r; - - found = true; - } else { - if (streq(word, key)) - found = true; - } - } - - if (value) { - *value = ret; - ret = NULL; - } - - return found; - -} - int container_get_leader(const char *machine, pid_t *pid) { _cleanup_free_ char *s = NULL, *class = NULL; const char *p; @@ -3219,136 +808,6 @@ int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int return reset_uid_gid(); } -/* This is much like like mkostemp() but is subject to umask(). */ -int mkostemp_safe(char *pattern, int flags) { - _cleanup_umask_ mode_t u; - int fd; - - assert(pattern); - - u = umask(077); - - fd = mkostemp(pattern, flags); - if (fd < 0) - return -errno; - - return fd; -} - -int open_tmpfile(const char *path, int flags) { - char *p; - int fd; - - assert(path); - -#ifdef O_TMPFILE - /* Try O_TMPFILE first, if it is supported */ - fd = open(path, flags|O_TMPFILE|O_EXCL, S_IRUSR|S_IWUSR); - if (fd >= 0) - return fd; -#endif - - /* Fall back to unguessable name + unlinking */ - p = strjoina(path, "/systemd-tmp-XXXXXX"); - - fd = mkostemp_safe(p, flags); - if (fd < 0) - return fd; - - unlink(p); - return fd; -} - -int fd_warn_permissions(const char *path, int fd) { - struct stat st; - - if (fstat(fd, &st) < 0) - return -errno; - - if (st.st_mode & 0111) - log_warning("Configuration file %s is marked executable. Please remove executable permission bits. Proceeding anyway.", path); - - if (st.st_mode & 0002) - log_warning("Configuration file %s is marked world-writable. Please remove world writability permission bits. Proceeding anyway.", path); - - if (getpid() == 1 && (st.st_mode & 0044) != 0044) - 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); - - return 0; -} - -unsigned long personality_from_string(const char *p) { - - /* Parse a personality specifier. We introduce our own - * identifiers that indicate specific ABIs, rather than just - * hints regarding the register size, since we want to keep - * things open for multiple locally supported ABIs for the - * same register size. We try to reuse the ABI identifiers - * used by libseccomp. */ - -#if defined(__x86_64__) - - if (streq(p, "x86")) - return PER_LINUX32; - - if (streq(p, "x86-64")) - return PER_LINUX; - -#elif defined(__i386__) - - if (streq(p, "x86")) - return PER_LINUX; - -#elif defined(__s390x__) - - if (streq(p, "s390")) - return PER_LINUX32; - - if (streq(p, "s390x")) - return PER_LINUX; - -#elif defined(__s390__) - - if (streq(p, "s390")) - return PER_LINUX; -#endif - - return PERSONALITY_INVALID; -} - -const char* personality_to_string(unsigned long p) { - -#if defined(__x86_64__) - - if (p == PER_LINUX32) - return "x86"; - - if (p == PER_LINUX) - return "x86-64"; - -#elif defined(__i386__) - - if (p == PER_LINUX) - return "x86"; - -#elif defined(__s390x__) - - if (p == PER_LINUX) - return "s390x"; - - if (p == PER_LINUX32) - return "s390"; - -#elif defined(__s390__) - - if (p == PER_LINUX) - return "s390"; - -#endif - - return NULL; -} - uint64_t physical_memory(void) { long mem; @@ -3361,49 +820,6 @@ uint64_t physical_memory(void) { return (uint64_t) mem * (uint64_t) page_size(); } -void hexdump(FILE *f, const void *p, size_t s) { - const uint8_t *b = p; - unsigned n = 0; - - assert(s == 0 || b); - - while (s > 0) { - size_t i; - - fprintf(f, "%04x ", n); - - for (i = 0; i < 16; i++) { - - if (i >= s) - fputs(" ", f); - else - fprintf(f, "%02x ", b[i]); - - if (i == 7) - fputc(' ', f); - } - - fputc(' ', f); - - for (i = 0; i < 16; i++) { - - if (i >= s) - fputc(' ', f); - else - fputc(isprint(b[i]) ? (char) b[i] : '.', f); - } - - fputc('\n', f); - - if (s < 16) - break; - - n += 16; - b += 16; - s -= 16; - } -} - int update_reboot_param_file(const char *param) { int r = 0; @@ -3417,846 +833,8 @@ int update_reboot_param_file(const char *param) { return 0; } -int umount_recursive(const char *prefix, int flags) { - bool again; - int n = 0, r; - - /* Try to umount everything recursively below a - * directory. Also, take care of stacked mounts, and keep - * unmounting them until they are gone. */ - - do { - _cleanup_fclose_ FILE *proc_self_mountinfo = NULL; - - again = false; - r = 0; - - proc_self_mountinfo = fopen("/proc/self/mountinfo", "re"); - if (!proc_self_mountinfo) - return -errno; - - for (;;) { - _cleanup_free_ char *path = NULL, *p = NULL; - int k; - - k = fscanf(proc_self_mountinfo, - "%*s " /* (1) mount id */ - "%*s " /* (2) parent id */ - "%*s " /* (3) major:minor */ - "%*s " /* (4) root */ - "%ms " /* (5) mount point */ - "%*s" /* (6) mount options */ - "%*[^-]" /* (7) optional fields */ - "- " /* (8) separator */ - "%*s " /* (9) file system type */ - "%*s" /* (10) mount source */ - "%*s" /* (11) mount options 2 */ - "%*[^\n]", /* some rubbish at the end */ - &path); - if (k != 1) { - if (k == EOF) - break; - - continue; - } - - r = cunescape(path, UNESCAPE_RELAX, &p); - if (r < 0) - return r; - - if (!path_startswith(p, prefix)) - continue; - - if (umount2(p, flags) < 0) { - r = -errno; - continue; - } - - again = true; - n++; - - break; - } - - } while (again); - - return r ? r : n; -} - -static int get_mount_flags(const char *path, unsigned long *flags) { - struct statvfs buf; - - if (statvfs(path, &buf) < 0) - return -errno; - *flags = buf.f_flag; - return 0; -} - -int bind_remount_recursive(const char *prefix, bool ro) { - _cleanup_set_free_free_ Set *done = NULL; - _cleanup_free_ char *cleaned = NULL; - int r; - - /* Recursively remount a directory (and all its submounts) - * read-only or read-write. If the directory is already - * mounted, we reuse the mount and simply mark it - * MS_BIND|MS_RDONLY (or remove the MS_RDONLY for read-write - * operation). If it isn't we first make it one. Afterwards we - * apply MS_BIND|MS_RDONLY (or remove MS_RDONLY) to all - * submounts we can access, too. When mounts are stacked on - * the same mount point we only care for each individual - * "top-level" mount on each point, as we cannot - * influence/access the underlying mounts anyway. We do not - * have any effect on future submounts that might get - * propagated, they migt be writable. This includes future - * submounts that have been triggered via autofs. */ - - cleaned = strdup(prefix); - if (!cleaned) - return -ENOMEM; - - path_kill_slashes(cleaned); - - done = set_new(&string_hash_ops); - if (!done) - return -ENOMEM; - - for (;;) { - _cleanup_fclose_ FILE *proc_self_mountinfo = NULL; - _cleanup_set_free_free_ Set *todo = NULL; - bool top_autofs = false; - char *x; - unsigned long orig_flags; - - todo = set_new(&string_hash_ops); - if (!todo) - return -ENOMEM; - - proc_self_mountinfo = fopen("/proc/self/mountinfo", "re"); - if (!proc_self_mountinfo) - return -errno; - - for (;;) { - _cleanup_free_ char *path = NULL, *p = NULL, *type = NULL; - int k; - - k = fscanf(proc_self_mountinfo, - "%*s " /* (1) mount id */ - "%*s " /* (2) parent id */ - "%*s " /* (3) major:minor */ - "%*s " /* (4) root */ - "%ms " /* (5) mount point */ - "%*s" /* (6) mount options (superblock) */ - "%*[^-]" /* (7) optional fields */ - "- " /* (8) separator */ - "%ms " /* (9) file system type */ - "%*s" /* (10) mount source */ - "%*s" /* (11) mount options (bind mount) */ - "%*[^\n]", /* some rubbish at the end */ - &path, - &type); - if (k != 2) { - if (k == EOF) - break; - - continue; - } - - r = cunescape(path, UNESCAPE_RELAX, &p); - if (r < 0) - return r; - - /* Let's ignore autofs mounts. If they aren't - * triggered yet, we want to avoid triggering - * them, as we don't make any guarantees for - * future submounts anyway. If they are - * already triggered, then we will find - * another entry for this. */ - if (streq(type, "autofs")) { - top_autofs = top_autofs || path_equal(cleaned, p); - continue; - } - - if (path_startswith(p, cleaned) && - !set_contains(done, p)) { - - r = set_consume(todo, p); - p = NULL; - - if (r == -EEXIST) - continue; - if (r < 0) - return r; - } - } - - /* If we have no submounts to process anymore and if - * the root is either already done, or an autofs, we - * are done */ - if (set_isempty(todo) && - (top_autofs || set_contains(done, cleaned))) - return 0; - - if (!set_contains(done, cleaned) && - !set_contains(todo, cleaned)) { - /* The prefix directory itself is not yet a - * mount, make it one. */ - if (mount(cleaned, cleaned, NULL, MS_BIND|MS_REC, NULL) < 0) - return -errno; - - orig_flags = 0; - (void) get_mount_flags(cleaned, &orig_flags); - orig_flags &= ~MS_RDONLY; - - if (mount(NULL, prefix, NULL, orig_flags|MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0) - return -errno; - - x = strdup(cleaned); - if (!x) - return -ENOMEM; - - r = set_consume(done, x); - if (r < 0) - return r; - } - - while ((x = set_steal_first(todo))) { - - r = set_consume(done, x); - if (r == -EEXIST || r == 0) - continue; - if (r < 0) - return r; - - /* Try to reuse the original flag set, but - * don't care for errors, in case of - * obstructed mounts */ - orig_flags = 0; - (void) get_mount_flags(x, &orig_flags); - orig_flags &= ~MS_RDONLY; - - if (mount(NULL, x, NULL, orig_flags|MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0) { - - /* Deal with mount points that are - * obstructed by a later mount */ - - if (errno != ENOENT) - return -errno; - } - - } - } -} - -int fflush_and_check(FILE *f) { - assert(f); - - errno = 0; - fflush(f); - - if (ferror(f)) - return errno ? -errno : -EIO; - - return 0; -} - -int tempfn_xxxxxx(const char *p, const char *extra, char **ret) { - const char *fn; - char *t; - - assert(p); - assert(ret); - - /* - * Turns this: - * /foo/bar/waldo - * - * Into this: - * /foo/bar/.#<extra>waldoXXXXXX - */ - - fn = basename(p); - if (!filename_is_valid(fn)) - return -EINVAL; - - if (extra == NULL) - extra = ""; - - t = new(char, strlen(p) + 2 + strlen(extra) + 6 + 1); - if (!t) - return -ENOMEM; - - strcpy(stpcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), ".#"), extra), fn), "XXXXXX"); - - *ret = path_kill_slashes(t); - return 0; -} - -int tempfn_random(const char *p, const char *extra, char **ret) { - const char *fn; - char *t, *x; - uint64_t u; - unsigned i; - - assert(p); - assert(ret); - - /* - * Turns this: - * /foo/bar/waldo - * - * Into this: - * /foo/bar/.#<extra>waldobaa2a261115984a9 - */ - - fn = basename(p); - if (!filename_is_valid(fn)) - return -EINVAL; - - if (!extra) - extra = ""; - - t = new(char, strlen(p) + 2 + strlen(extra) + 16 + 1); - if (!t) - return -ENOMEM; - - x = stpcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), ".#"), extra), fn); - - u = random_u64(); - for (i = 0; i < 16; i++) { - *(x++) = hexchar(u & 0xF); - u >>= 4; - } - - *x = 0; - - *ret = path_kill_slashes(t); - return 0; -} - -int tempfn_random_child(const char *p, const char *extra, char **ret) { - char *t, *x; - uint64_t u; - unsigned i; - - assert(p); - assert(ret); - - /* Turns this: - * /foo/bar/waldo - * Into this: - * /foo/bar/waldo/.#<extra>3c2b6219aa75d7d0 - */ - - if (!extra) - extra = ""; - - t = new(char, strlen(p) + 3 + strlen(extra) + 16 + 1); - if (!t) - return -ENOMEM; - - x = stpcpy(stpcpy(stpcpy(t, p), "/.#"), extra); - - u = random_u64(); - for (i = 0; i < 16; i++) { - *(x++) = hexchar(u & 0xF); - u >>= 4; - } - - *x = 0; - - *ret = path_kill_slashes(t); - return 0; -} - -int take_password_lock(const char *root) { - - struct flock flock = { - .l_type = F_WRLCK, - .l_whence = SEEK_SET, - .l_start = 0, - .l_len = 0, - }; - - const char *path; - int fd, r; - - /* This is roughly the same as lckpwdf(), but not as awful. We - * don't want to use alarm() and signals, hence we implement - * our own trivial version of this. - * - * Note that shadow-utils also takes per-database locks in - * addition to lckpwdf(). However, we don't given that they - * are redundant as they they invoke lckpwdf() first and keep - * it during everything they do. The per-database locks are - * awfully racy, and thus we just won't do them. */ - - if (root) - path = strjoina(root, "/etc/.pwd.lock"); - else - path = "/etc/.pwd.lock"; - - fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0600); - if (fd < 0) - return -errno; - - r = fcntl(fd, F_SETLKW, &flock); - if (r < 0) { - safe_close(fd); - return -errno; - } - - return fd; -} - -int is_symlink(const char *path) { - struct stat info; - - if (lstat(path, &info) < 0) - return -errno; - - return !!S_ISLNK(info.st_mode); -} - -int is_dir(const char* path, bool follow) { - struct stat st; - int r; - - if (follow) - r = stat(path, &st); - else - r = lstat(path, &st); - if (r < 0) - return -errno; - - return !!S_ISDIR(st.st_mode); -} - -int is_device_node(const char *path) { - struct stat info; - - if (lstat(path, &info) < 0) - return -errno; - - return !!(S_ISBLK(info.st_mode) || S_ISCHR(info.st_mode)); -} - -ssize_t fgetxattrat_fake(int dirfd, const char *filename, const char *attribute, void *value, size_t size, int flags) { - char fn[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1]; - _cleanup_close_ int fd = -1; - ssize_t l; - - /* The kernel doesn't have a fgetxattrat() command, hence let's emulate one */ - - fd = openat(dirfd, filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH|(flags & AT_SYMLINK_NOFOLLOW ? O_NOFOLLOW : 0)); - if (fd < 0) - return -errno; - - xsprintf(fn, "/proc/self/fd/%i", fd); - - l = getxattr(fn, attribute, value, size); - if (l < 0) - return -errno; - - return l; -} - -static int parse_crtime(le64_t le, usec_t *usec) { - uint64_t u; - - assert(usec); - - u = le64toh(le); - if (u == 0 || u == (uint64_t) -1) - return -EIO; - - *usec = (usec_t) u; - return 0; -} - -int fd_getcrtime(int fd, usec_t *usec) { - le64_t le; - ssize_t n; - - assert(fd >= 0); - assert(usec); - - /* Until Linux gets a real concept of birthtime/creation time, - * let's fake one with xattrs */ - - n = fgetxattr(fd, "user.crtime_usec", &le, sizeof(le)); - if (n < 0) - return -errno; - if (n != sizeof(le)) - return -EIO; - - return parse_crtime(le, usec); -} - -int fd_getcrtime_at(int dirfd, const char *name, usec_t *usec, int flags) { - le64_t le; - ssize_t n; - - n = fgetxattrat_fake(dirfd, name, "user.crtime_usec", &le, sizeof(le), flags); - if (n < 0) - return -errno; - if (n != sizeof(le)) - return -EIO; - - return parse_crtime(le, usec); -} - -int path_getcrtime(const char *p, usec_t *usec) { - le64_t le; - ssize_t n; - - assert(p); - assert(usec); - - n = getxattr(p, "user.crtime_usec", &le, sizeof(le)); - if (n < 0) - return -errno; - if (n != sizeof(le)) - return -EIO; - - return parse_crtime(le, usec); -} - -int fd_setcrtime(int fd, usec_t usec) { - le64_t le; - - assert(fd >= 0); - - if (usec <= 0) - usec = now(CLOCK_REALTIME); - - le = htole64((uint64_t) usec); - if (fsetxattr(fd, "user.crtime_usec", &le, sizeof(le), 0) < 0) - return -errno; - - return 0; -} - -int chattr_fd(int fd, unsigned value, unsigned mask) { - unsigned old_attr, new_attr; - struct stat st; - - assert(fd >= 0); - - if (fstat(fd, &st) < 0) - return -errno; - - /* Explicitly check whether this is a regular file or - * directory. If it is anything else (such as a device node or - * fifo), then the ioctl will not hit the file systems but - * possibly drivers, where the ioctl might have different - * effects. Notably, DRM is using the same ioctl() number. */ - - if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode)) - return -ENOTTY; - - if (mask == 0) - return 0; - - if (ioctl(fd, FS_IOC_GETFLAGS, &old_attr) < 0) - return -errno; - - new_attr = (old_attr & ~mask) | (value & mask); - if (new_attr == old_attr) - return 0; - - if (ioctl(fd, FS_IOC_SETFLAGS, &new_attr) < 0) - return -errno; - - return 1; -} - -int chattr_path(const char *p, unsigned value, unsigned mask) { - _cleanup_close_ int fd = -1; - - assert(p); - - if (mask == 0) - return 0; - - fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); - if (fd < 0) - return -errno; - - return chattr_fd(fd, value, mask); -} - -int read_attr_fd(int fd, unsigned *ret) { - struct stat st; - - assert(fd >= 0); - - if (fstat(fd, &st) < 0) - return -errno; - - if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode)) - return -ENOTTY; - - if (ioctl(fd, FS_IOC_GETFLAGS, ret) < 0) - return -errno; - - return 0; -} - -int read_attr_path(const char *p, unsigned *ret) { - _cleanup_close_ int fd = -1; - - assert(p); - assert(ret); - - fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); - if (fd < 0) - return -errno; - - return read_attr_fd(fd, ret); -} - -int syslog_parse_priority(const char **p, int *priority, bool with_facility) { - int a = 0, b = 0, c = 0; - int k; - - assert(p); - assert(*p); - assert(priority); - - if ((*p)[0] != '<') - return 0; - - if (!strchr(*p, '>')) - return 0; - - if ((*p)[2] == '>') { - c = undecchar((*p)[1]); - k = 3; - } else if ((*p)[3] == '>') { - b = undecchar((*p)[1]); - c = undecchar((*p)[2]); - k = 4; - } else if ((*p)[4] == '>') { - a = undecchar((*p)[1]); - b = undecchar((*p)[2]); - c = undecchar((*p)[3]); - k = 5; - } else - return 0; - - if (a < 0 || b < 0 || c < 0 || - (!with_facility && (a || b || c > 7))) - return 0; - - if (with_facility) - *priority = a*100 + b*10 + c; - else - *priority = (*priority & LOG_FACMASK) | c; - - *p += k; - return 1; -} - -ssize_t string_table_lookup(const char * const *table, size_t len, const char *key) { - size_t i; - - if (!key) - return -1; - - for (i = 0; i < len; ++i) - if (streq_ptr(table[i], key)) - return (ssize_t) i; - - return -1; -} - -int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) { - struct stat buf; - int ret; - - ret = renameat2(olddirfd, oldpath, newdirfd, newpath, RENAME_NOREPLACE); - if (ret >= 0) - return 0; - - /* renameat2() exists since Linux 3.15, btrfs added support for it later. - * If it is not implemented, fallback to another method. */ - if (!IN_SET(errno, EINVAL, ENOSYS)) - return -errno; - - /* The link()/unlink() fallback does not work on directories. But - * renameat() without RENAME_NOREPLACE gives the same semantics on - * directories, except when newpath is an *empty* directory. This is - * good enough. */ - ret = fstatat(olddirfd, oldpath, &buf, AT_SYMLINK_NOFOLLOW); - if (ret >= 0 && S_ISDIR(buf.st_mode)) { - ret = renameat(olddirfd, oldpath, newdirfd, newpath); - return ret >= 0 ? 0 : -errno; - } - - /* If it is not a directory, use the link()/unlink() fallback. */ - ret = linkat(olddirfd, oldpath, newdirfd, newpath, 0); - if (ret < 0) - return -errno; - - ret = unlinkat(olddirfd, oldpath, 0); - if (ret < 0) { - /* backup errno before the following unlinkat() alters it */ - ret = errno; - (void) unlinkat(newdirfd, newpath, 0); - errno = ret; - return -errno; - } - - return 0; -} - -int parse_mode(const char *s, mode_t *ret) { - char *x; - long l; - - assert(s); - assert(ret); - - errno = 0; - l = strtol(s, &x, 8); - if (errno != 0) - return -errno; - - if (!x || x == s || *x) - return -EINVAL; - if (l < 0 || l > 07777) - return -ERANGE; - - *ret = (mode_t) l; - return 0; -} - -int mount_move_root(const char *path) { - assert(path); - - if (chdir(path) < 0) - return -errno; - - if (mount(path, "/", NULL, MS_MOVE, NULL) < 0) - return -errno; - - if (chroot(".") < 0) - return -errno; - - if (chdir("/") < 0) - return -errno; - - return 0; -} - -int getxattr_malloc(const char *path, const char *name, char **value, bool allow_symlink) { - char *v; - size_t l; - ssize_t n; - - assert(path); - assert(name); - assert(value); - - for (l = 100; ; l = (size_t) n + 1) { - v = new0(char, l); - if (!v) - return -ENOMEM; - - if (allow_symlink) - n = lgetxattr(path, name, v, l); - else - n = getxattr(path, name, v, l); - - if (n >= 0 && (size_t) n < l) { - *value = v; - return n; - } - - free(v); - - if (n < 0 && errno != ERANGE) - return -errno; - - if (allow_symlink) - n = lgetxattr(path, name, NULL, 0); - else - n = getxattr(path, name, NULL, 0); - if (n < 0) - return -errno; - } -} - -int fgetxattr_malloc(int fd, const char *name, char **value) { - char *v; - size_t l; - ssize_t n; - - assert(fd >= 0); - assert(name); - assert(value); - - for (l = 100; ; l = (size_t) n + 1) { - v = new0(char, l); - if (!v) - return -ENOMEM; - - n = fgetxattr(fd, name, v, l); - - if (n >= 0 && (size_t) n < l) { - *value = v; - return n; - } - - free(v); - - if (n < 0 && errno != ERANGE) - return -errno; - - n = fgetxattr(fd, name, NULL, 0); - if (n < 0) - return -errno; - } -} - -void nop_signal_handler(int sig) { - /* nothing here */ -} - int version(void) { puts(PACKAGE_STRING "\n" SYSTEMD_FEATURES); return 0; } - -bool fdname_is_valid(const char *s) { - const char *p; - - /* Validates a name for $LISTEN_FDNAMES. We basically allow - * everything ASCII that's not a control character. Also, as - * special exception the ":" character is not allowed, as we - * use that as field separator in $LISTEN_FDNAMES. - * - * Note that the empty string is explicitly allowed - * here. However, we limit the length of the names to 255 - * characters. */ - - if (!s) - return false; - - for (p = s; *p; p++) { - if (*p < ' ') - return false; - if (*p >= 127) - return false; - if (*p == ':') - return false; - } - - return p - s < 256; -} - -bool oom_score_adjust_is_valid(int oa) { - return oa >= OOM_SCORE_ADJ_MIN && oa <= OOM_SCORE_ADJ_MAX; -} diff --git a/src/basic/util.h b/src/basic/util.h index f32033767a..a8fba372d1 100644 --- a/src/basic/util.h +++ b/src/basic/util.h @@ -22,12 +22,10 @@ ***/ #include <alloca.h> -#include <dirent.h> #include <fcntl.h> #include <inttypes.h> #include <limits.h> #include <locale.h> -#include <mntent.h> #include <stdarg.h> #include <stdbool.h> #include <stddef.h> @@ -53,28 +51,9 @@ #define COMMENTS "#;" #define GLOB_CHARS "*?[" -#define FORMAT_BYTES_MAX 8 - size_t page_size(void) _pure_; #define PAGE_ALIGN(l) ALIGN_TO((l), page_size()) -#define new(t, n) ((t*) malloc_multiply(sizeof(t), (n))) - -#define new0(t, n) ((t*) calloc((n), sizeof(t))) - -#define newa(t, n) ((t*) alloca(sizeof(t)*(n))) - -#define newa0(t, n) ((t*) alloca0(sizeof(t)*(n))) - -#define newdup(t, p, n) ((t*) memdup_multiply(p, sizeof(t), (n))) - -#define malloc0(n) (calloc(1, (n))) - -static inline void *mfree(void *memory) { - free(memory); - return NULL; -} - static inline const char* yes_no(bool b) { return b ? "yes" : "no"; } @@ -87,220 +66,13 @@ static inline const char* one_zero(bool b) { return b ? "1" : "0"; } -int parse_size(const char *t, uint64_t base, uint64_t *size); - -int parse_boolean(const char *v) _pure_; -int parse_pid(const char *s, pid_t* ret_pid); - -int safe_atou(const char *s, unsigned *ret_u); -int safe_atoi(const char *s, int *ret_i); - -int safe_atollu(const char *s, unsigned long long *ret_u); -int safe_atolli(const char *s, long long int *ret_i); - -int safe_atod(const char *s, double *ret_d); - -int safe_atou8(const char *s, uint8_t *ret); - -#if LONG_MAX == INT_MAX -static inline int safe_atolu(const char *s, unsigned long *ret_u) { - assert_cc(sizeof(unsigned long) == sizeof(unsigned)); - return safe_atou(s, (unsigned*) ret_u); -} -static inline int safe_atoli(const char *s, long int *ret_u) { - assert_cc(sizeof(long int) == sizeof(int)); - return safe_atoi(s, (int*) ret_u); -} -#else -static inline int safe_atolu(const char *s, unsigned long *ret_u) { - assert_cc(sizeof(unsigned long) == sizeof(unsigned long long)); - return safe_atollu(s, (unsigned long long*) ret_u); -} -static inline int safe_atoli(const char *s, long int *ret_u) { - assert_cc(sizeof(long int) == sizeof(long long int)); - return safe_atolli(s, (long long int*) ret_u); -} -#endif - -static inline int safe_atou32(const char *s, uint32_t *ret_u) { - assert_cc(sizeof(uint32_t) == sizeof(unsigned)); - return safe_atou(s, (unsigned*) ret_u); -} - -static inline int safe_atoi32(const char *s, int32_t *ret_i) { - assert_cc(sizeof(int32_t) == sizeof(int)); - return safe_atoi(s, (int*) ret_i); -} - -static inline int safe_atou64(const char *s, uint64_t *ret_u) { - assert_cc(sizeof(uint64_t) == sizeof(unsigned long long)); - return safe_atollu(s, (unsigned long long*) ret_u); -} - -static inline int safe_atoi64(const char *s, int64_t *ret_i) { - assert_cc(sizeof(int64_t) == sizeof(long long int)); - return safe_atolli(s, (long long int*) ret_i); -} - -int safe_atou16(const char *s, uint16_t *ret); -int safe_atoi16(const char *s, int16_t *ret); - -int readlinkat_malloc(int fd, const char *p, char **ret); -int readlink_malloc(const char *p, char **r); -int readlink_value(const char *p, char **ret); -int readlink_and_make_absolute(const char *p, char **r); -int readlink_and_canonicalize(const char *p, char **r); - -char *file_in_same_dir(const char *path, const char *filename); - -int rmdir_parents(const char *path, const char *stop); - -char hexchar(int x) _const_; -int unhexchar(char c) _const_; -char octchar(int x) _const_; -int unoctchar(char c) _const_; -char decchar(int x) _const_; -int undecchar(char c) _const_; -char base32hexchar(int x) _const_; -int unbase32hexchar(char c) _const_; -char base64char(int x) _const_; -int unbase64char(char c) _const_; - -bool dirent_is_file(const struct dirent *de) _pure_; -bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) _pure_; - -bool hidden_file(const char *filename) _pure_; - -/* For basic lookup tables with strictly enumerated entries */ -#define _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \ - scope const char *name##_to_string(type i) { \ - if (i < 0 || i >= (type) ELEMENTSOF(name##_table)) \ - return NULL; \ - return name##_table[i]; \ - } - -ssize_t string_table_lookup(const char * const *table, size_t len, const char *key); - -#define _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope) \ - scope type name##_from_string(const char *s) { \ - return (type) string_table_lookup(name##_table, ELEMENTSOF(name##_table), s); \ - } - -#define _DEFINE_STRING_TABLE_LOOKUP(name,type,scope) \ - _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \ - _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope) \ - struct __useless_struct_to_allow_trailing_semicolon__ - -#define DEFINE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,) -#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,static) -#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,static) -#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,static) - -/* For string conversions where numbers are also acceptable */ -#define DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(name,type,max) \ - int name##_to_string_alloc(type i, char **str) { \ - char *s; \ - if (i < 0 || i > max) \ - return -ERANGE; \ - if (i < (type) ELEMENTSOF(name##_table)) { \ - s = strdup(name##_table[i]); \ - if (!s) \ - return -ENOMEM; \ - } else { \ - if (asprintf(&s, "%i", i) < 0) \ - return -ENOMEM; \ - } \ - *str = s; \ - return 0; \ - } \ - type name##_from_string(const char *s) { \ - type i; \ - unsigned u = 0; \ - if (!s) \ - return (type) -1; \ - for (i = 0; i < (type) ELEMENTSOF(name##_table); i++) \ - if (streq_ptr(name##_table[i], s)) \ - return i; \ - if (safe_atou(s, &u) >= 0 && u <= max) \ - return (type) u; \ - return (type) -1; \ - } \ - struct __useless_struct_to_allow_trailing_semicolon__ - -bool fstype_is_network(const char *fstype); - -int fopen_temporary(const char *path, FILE **_f, char **_temp_path); - -bool is_device_path(const char *path); - -int dir_is_empty(const char *path); -char* dirname_malloc(const char *path); - -static inline int dir_is_populated(const char *path) { - int r; - r = dir_is_empty(path); - if (r < 0) - return r; - return !r; -} - -int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid); -int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid); - -typedef long statfs_f_type_t; - -bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) _pure_; -int fd_check_fstype(int fd, statfs_f_type_t magic_value); -int path_check_fstype(const char *path, statfs_f_type_t magic_value); - -bool is_temporary_fs(const struct statfs *s) _pure_; -int fd_is_temporary_fs(int fd); - -#define xsprintf(buf, fmt, ...) \ - assert_message_se((size_t) snprintf(buf, ELEMENTSOF(buf), fmt, __VA_ARGS__) < ELEMENTSOF(buf), \ - "xsprintf: " #buf "[] must be big enough") - -int files_same(const char *filea, const char *fileb); - -int running_in_chroot(void); - -int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode); -int touch(const char *path); - -noreturn void freeze(void); - -bool null_or_empty(struct stat *st) _pure_; -int null_or_empty_path(const char *fn); -int null_or_empty_fd(int fd); - -DIR *xopendirat(int dirfd, const char *name, int flags); - -char *fstab_node_to_udev_node(const char *p); - void execute_directories(const char* const* directories, usec_t timeout, char *argv[]); bool plymouth_running(void); -int symlink_idempotent(const char *from, const char *to); - -int symlink_atomic(const char *from, const char *to); -int mknod_atomic(const char *path, mode_t mode, dev_t dev); -int mkfifo_atomic(const char *path, mode_t mode); - -int fchmod_umask(int fd, mode_t mode); - bool display_is_local(const char *display) _pure_; int socket_from_display(const char *display, char **path); -int glob_exists(const char *path); -int glob_extend(char ***strv, const char *path); - -int dirent_ensure_type(DIR *d, struct dirent *de); - -int get_files_in_directory(const char *path, char ***list); - -bool is_main_thread(void); - int block_get_whole_disk(dev_t d, dev_t *ret); #define NULSTR_FOREACH(i, l) \ @@ -309,26 +81,6 @@ int block_get_whole_disk(dev_t d, dev_t *ret); #define NULSTR_FOREACH_PAIR(i, j, l) \ for ((i) = (l), (j) = strchr((i), 0)+1; (i) && *(i); (i) = strchr((j), 0)+1, (j) = *(i) ? strchr((i), 0)+1 : (i)) -int ioprio_class_to_string_alloc(int i, char **s); -int ioprio_class_from_string(const char *s); - -const char *sigchld_code_to_string(int i) _const_; -int sigchld_code_from_string(const char *s) _pure_; - -int log_facility_unshifted_to_string_alloc(int i, char **s); -int log_facility_unshifted_from_string(const char *s); -bool log_facility_unshifted_is_valid(int faciliy); - -int log_level_to_string_alloc(int i, char **s); -int log_level_from_string(const char *s); -bool log_level_is_valid(int level); - -int sched_policy_to_string_alloc(int i, char **s); -int sched_policy_from_string(const char *s); - -const char *rlimit_to_string(int i) _const_; -int rlimit_from_string(const char *s) _pure_; - extern int saved_argc; extern char **saved_argv; @@ -336,147 +88,36 @@ bool kexec_loaded(void); int prot_from_flags(int flags) _const_; -char *format_bytes(char *buf, size_t l, uint64_t t); - -void* memdup(const void *p, size_t l) _alloc_(2); - int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...); -int setrlimit_closest(int resource, const struct rlimit *rlim); - -bool http_url_is_valid(const char *url) _pure_; -bool documentation_url_is_valid(const char *url) _pure_; - -bool http_etag_is_valid(const char *etag); - bool in_initrd(void); -static inline void freep(void *p) { - free(*(void**) p); -} - -static inline void umaskp(mode_t *u) { - umask(*u); -} - -DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, endmntent); - -#define _cleanup_free_ _cleanup_(freep) -#define _cleanup_umask_ _cleanup_(umaskp) -#define _cleanup_globfree_ _cleanup_(globfree) -#define _cleanup_endmntent_ _cleanup_(endmntentp) - -_malloc_ _alloc_(1, 2) static inline void *malloc_multiply(size_t a, size_t b) { - if (_unlikely_(b != 0 && a > ((size_t) -1) / b)) - return NULL; - - return malloc(a * b); -} - -_alloc_(2, 3) static inline void *realloc_multiply(void *p, size_t a, size_t b) { - if (_unlikely_(b != 0 && a > ((size_t) -1) / b)) - return NULL; - - return realloc(p, a * b); -} - -_alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t a, size_t b) { - if (_unlikely_(b != 0 && a > ((size_t) -1) / b)) - return NULL; - - return memdup(p, a * b); -} - -bool filename_is_valid(const char *p) _pure_; -bool path_is_safe(const char *p) _pure_; -bool string_is_safe(const char *p) _pure_; - -/** - * Check if a string contains any glob patterns. - */ -_pure_ static inline bool string_is_glob(const char *p) { - return !!strpbrk(p, GLOB_CHARS); -} - void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size, int (*compar) (const void *, const void *, void *), void *arg); -#define _(String) gettext (String) -#define N_(String) String -void init_gettext(void); -bool is_locale_utf8(void); - -typedef enum DrawSpecialChar { - DRAW_TREE_VERTICAL, - DRAW_TREE_BRANCH, - DRAW_TREE_RIGHT, - DRAW_TREE_SPACE, - DRAW_TRIANGULAR_BULLET, - DRAW_BLACK_CIRCLE, - DRAW_ARROW, - DRAW_DASH, - _DRAW_SPECIAL_CHAR_MAX -} DrawSpecialChar; - -const char *draw_special_char(DrawSpecialChar ch); +/** + * Normal qsort requires base to be nonnull. Here were require + * that only if nmemb > 0. + */ +static inline void qsort_safe(void *base, size_t nmemb, size_t size, comparison_fn_t compar) { + if (nmemb <= 1) + return; + + assert(base); + qsort(base, nmemb, size, compar); +} int on_ac_power(void); -int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f); -int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f); - -#define FOREACH_LINE(line, f, on_error) \ - for (;;) \ - if (!fgets(line, sizeof(line), f)) { \ - if (ferror(f)) { \ - on_error; \ - } \ - break; \ - } else - -#define FOREACH_DIRENT(de, d, on_error) \ - for (errno = 0, de = readdir(d);; errno = 0, de = readdir(d)) \ - if (!de) { \ - if (errno > 0) { \ - on_error; \ - } \ - break; \ - } else if (hidden_file((de)->d_name)) \ - continue; \ - else - -#define FOREACH_DIRENT_ALL(de, d, on_error) \ - for (errno = 0, de = readdir(d);; errno = 0, de = readdir(d)) \ - if (!de) { \ - if (errno > 0) { \ - on_error; \ - } \ - break; \ - } else +#define memzero(x,l) (memset((x), 0, (l))) +#define zero(x) (memzero(&(x), sizeof(x))) static inline void *mempset(void *s, int c, size_t n) { memset(s, c, n); return (uint8_t*)s + n; } -char *hexmem(const void *p, size_t l); -int unhexmem(const char *p, size_t l, void **mem, size_t *len); - -char *base32hexmem(const void *p, size_t l, bool padding); -int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *len); - -char *base64mem(const void *p, size_t l); -int unbase64mem(const char *p, size_t l, void **mem, size_t *len); - -void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size); -void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size); -#define GREEDY_REALLOC(array, allocated, need) \ - greedy_realloc((void**) &(array), &(allocated), (need), sizeof((array)[0])) - -#define GREEDY_REALLOC0(array, allocated, need) \ - greedy_realloc0((void**) &(array), &(allocated), (need), sizeof((array)[0])) - static inline void _reset_errno_(int *saved_errno) { errno = *saved_errno; } @@ -492,20 +133,6 @@ static inline int negative_errno(void) { return -errno; } -struct _umask_struct_ { - mode_t mask; - bool quit; -}; - -static inline void _reset_umask_(struct _umask_struct_ *s) { - umask(s->mask); -}; - -#define RUN_WITH_UMASK(mask) \ - for (_cleanup_(_reset_umask_) struct _umask_struct_ _saved_umask_ = { umask(mask), false }; \ - !_saved_umask_.quit ; \ - _saved_umask_.quit = true) - static inline unsigned u64log2(uint64_t n) { #if __SIZEOF_LONG_LONG__ == 8 return (n > 1) ? (unsigned) __builtin_clzll(n) ^ 63U : 0; @@ -543,154 +170,15 @@ static inline unsigned log2u_round_up(unsigned x) { return log2u(x - 1) + 1; } -#define DECIMAL_STR_WIDTH(x) \ - ({ \ - typeof(x) _x_ = (x); \ - unsigned ans = 1; \ - while (_x_ /= 10) \ - ans++; \ - ans; \ - }) - -int unlink_noerrno(const char *path); - -#define alloca0(n) \ - ({ \ - char *_new_; \ - size_t _len_ = n; \ - _new_ = alloca(_len_); \ - (void *) memset(_new_, 0, _len_); \ - }) - -/* It's not clear what alignment glibc/gcc alloca() guarantee, hence provide a guaranteed safe version */ -#define alloca_align(size, align) \ - ({ \ - void *_ptr_; \ - size_t _mask_ = (align) - 1; \ - _ptr_ = alloca((size) + _mask_); \ - (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_); \ - }) - -#define alloca0_align(size, align) \ - ({ \ - void *_new_; \ - size_t _size_ = (size); \ - _new_ = alloca_align(_size_, (align)); \ - (void*)memset(_new_, 0, _size_); \ - }) - bool id128_is_valid(const char *s) _pure_; -int shall_restore_state(void); - -/** - * Normal qsort requires base to be nonnull. Here were require - * that only if nmemb > 0. - */ -static inline void qsort_safe(void *base, size_t nmemb, size_t size, comparison_fn_t compar) { - if (nmemb <= 1) - return; - - assert(base); - qsort(base, nmemb, size, compar); -} - -int proc_cmdline(char **ret); -int parse_proc_cmdline(int (*parse_word)(const char *key, const char *value)); -int get_proc_cmdline_key(const char *parameter, char **value); - int container_get_leader(const char *machine, pid_t *pid); int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd); int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd); -int mkostemp_safe(char *pattern, int flags); -int open_tmpfile(const char *path, int flags); - -int fd_warn_permissions(const char *path, int fd); - -#ifndef PERSONALITY_INVALID -/* personality(7) documents that 0xffffffffUL is used for querying the - * current personality, hence let's use that here as error - * indicator. */ -#define PERSONALITY_INVALID 0xffffffffLU -#endif - -unsigned long personality_from_string(const char *p); -const char *personality_to_string(unsigned long); - uint64_t physical_memory(void); -void hexdump(FILE *f, const void *p, size_t s); - -union file_handle_union { - struct file_handle handle; - char padding[sizeof(struct file_handle) + MAX_HANDLE_SZ]; -}; -#define FILE_HANDLE_INIT { .handle.handle_bytes = MAX_HANDLE_SZ } - int update_reboot_param_file(const char *param); -int umount_recursive(const char *target, int flags); - -int bind_remount_recursive(const char *prefix, bool ro); - -int fflush_and_check(FILE *f); - -int tempfn_xxxxxx(const char *p, const char *extra, char **ret); -int tempfn_random(const char *p, const char *extra, char **ret); -int tempfn_random_child(const char *p, const char *extra, char **ret); - -int take_password_lock(const char *root); - -int is_symlink(const char *path); -int is_dir(const char *path, bool follow); -int is_device_node(const char *path); - -#define INOTIFY_EVENT_MAX (sizeof(struct inotify_event) + NAME_MAX + 1) - -#define FOREACH_INOTIFY_EVENT(e, buffer, sz) \ - for ((e) = &buffer.ev; \ - (uint8_t*) (e) < (uint8_t*) (buffer.raw) + (sz); \ - (e) = (struct inotify_event*) ((uint8_t*) (e) + sizeof(struct inotify_event) + (e)->len)) - -union inotify_event_buffer { - struct inotify_event ev; - uint8_t raw[INOTIFY_EVENT_MAX]; -}; - -#define laccess(path, mode) faccessat(AT_FDCWD, (path), (mode), AT_SYMLINK_NOFOLLOW) - -ssize_t fgetxattrat_fake(int dirfd, const char *filename, const char *attribute, void *value, size_t size, int flags); - -int fd_setcrtime(int fd, usec_t usec); -int fd_getcrtime(int fd, usec_t *usec); -int path_getcrtime(const char *p, usec_t *usec); -int fd_getcrtime_at(int dirfd, const char *name, usec_t *usec, int flags); - -int chattr_fd(int fd, unsigned value, unsigned mask); -int chattr_path(const char *p, unsigned value, unsigned mask); - -int read_attr_fd(int fd, unsigned *ret); -int read_attr_path(const char *p, unsigned *ret); - -#define RLIMIT_MAKE_CONST(lim) ((struct rlimit) { lim, lim }) - -int syslog_parse_priority(const char **p, int *priority, bool with_facility); - -int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath); - -int parse_mode(const char *s, mode_t *ret); - -int mount_move_root(const char *path); - -int getxattr_malloc(const char *path, const char *name, char **value, bool allow_symlink); -int fgetxattr_malloc(int fd, const char *name, char **value); - -void nop_signal_handler(int sig); - int version(void); - -bool fdname_is_valid(const char *s); - -bool oom_score_adjust_is_valid(int oa); diff --git a/src/basic/virt.c b/src/basic/virt.c index 9267a2730b..fb181e5b55 100644 --- a/src/basic/virt.c +++ b/src/basic/virt.c @@ -23,8 +23,11 @@ #include <string.h> #include <unistd.h> +#include "alloc-util.h" #include "fileio.h" #include "process-util.h" +#include "stat-util.h" +#include "string-table.h" #include "string-util.h" #include "util.h" #include "virt.h" @@ -411,6 +414,16 @@ int detect_virtualization(void) { return detect_vm(); } +int running_in_chroot(void) { + int ret; + + ret = files_same("/proc/1/root", "/"); + if (ret < 0) + return ret; + + return ret == 0; +} + static const char *const virtualization_table[_VIRTUALIZATION_MAX] = { [VIRTUALIZATION_NONE] = "none", [VIRTUALIZATION_KVM] = "kvm", diff --git a/src/basic/virt.h b/src/basic/virt.h index 449e069901..ed83608019 100644 --- a/src/basic/virt.h +++ b/src/basic/virt.h @@ -67,5 +67,7 @@ int detect_vm(void); int detect_container(void); int detect_virtualization(void); +int running_in_chroot(void); + const char *virtualization_to_string(int v) _const_; int virtualization_from_string(const char *s) _pure_; diff --git a/src/basic/web-util.c b/src/basic/web-util.c new file mode 100644 index 0000000000..68ec04021b --- /dev/null +++ b/src/basic/web-util.c @@ -0,0 +1,78 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <stdbool.h> + +#include "string-util.h" +#include "utf8.h" +#include "web-util.h" + +bool http_etag_is_valid(const char *etag) { + if (isempty(etag)) + return false; + + if (!endswith(etag, "\"")) + return false; + + if (!startswith(etag, "\"") && !startswith(etag, "W/\"")) + return false; + + return true; +} + +bool http_url_is_valid(const char *url) { + const char *p; + + if (isempty(url)) + return false; + + p = startswith(url, "http://"); + if (!p) + p = startswith(url, "https://"); + if (!p) + return false; + + if (isempty(p)) + return false; + + return ascii_is_valid(p); +} + +bool documentation_url_is_valid(const char *url) { + const char *p; + + if (isempty(url)) + return false; + + if (http_url_is_valid(url)) + return true; + + p = startswith(url, "file:/"); + if (!p) + p = startswith(url, "info:"); + if (!p) + p = startswith(url, "man:"); + + if (isempty(p)) + return false; + + return ascii_is_valid(p); +} diff --git a/src/basic/web-util.h b/src/basic/web-util.h new file mode 100644 index 0000000000..40c1509eb8 --- /dev/null +++ b/src/basic/web-util.h @@ -0,0 +1,32 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <stdbool.h> + +#include "macro.h" + +bool http_url_is_valid(const char *url) _pure_; + +bool documentation_url_is_valid(const char *url) _pure_; + +bool http_etag_is_valid(const char *etag); diff --git a/src/basic/xattr-util.c b/src/basic/xattr-util.c new file mode 100644 index 0000000000..6abdaedc3e --- /dev/null +++ b/src/basic/xattr-util.c @@ -0,0 +1,195 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <sys/xattr.h> + +#include "alloc-util.h" +#include "fd-util.h" +#include "sparse-endian.h" +#include "stdio-util.h" +#include "util.h" +#include "xattr-util.h" + +int getxattr_malloc(const char *path, const char *name, char **value, bool allow_symlink) { + char *v; + size_t l; + ssize_t n; + + assert(path); + assert(name); + assert(value); + + for (l = 100; ; l = (size_t) n + 1) { + v = new0(char, l); + if (!v) + return -ENOMEM; + + if (allow_symlink) + n = lgetxattr(path, name, v, l); + else + n = getxattr(path, name, v, l); + + if (n >= 0 && (size_t) n < l) { + *value = v; + return n; + } + + free(v); + + if (n < 0 && errno != ERANGE) + return -errno; + + if (allow_symlink) + n = lgetxattr(path, name, NULL, 0); + else + n = getxattr(path, name, NULL, 0); + if (n < 0) + return -errno; + } +} + +int fgetxattr_malloc(int fd, const char *name, char **value) { + char *v; + size_t l; + ssize_t n; + + assert(fd >= 0); + assert(name); + assert(value); + + for (l = 100; ; l = (size_t) n + 1) { + v = new0(char, l); + if (!v) + return -ENOMEM; + + n = fgetxattr(fd, name, v, l); + + if (n >= 0 && (size_t) n < l) { + *value = v; + return n; + } + + free(v); + + if (n < 0 && errno != ERANGE) + return -errno; + + n = fgetxattr(fd, name, NULL, 0); + if (n < 0) + return -errno; + } +} + +ssize_t fgetxattrat_fake(int dirfd, const char *filename, const char *attribute, void *value, size_t size, int flags) { + char fn[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1]; + _cleanup_close_ int fd = -1; + ssize_t l; + + /* The kernel doesn't have a fgetxattrat() command, hence let's emulate one */ + + fd = openat(dirfd, filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH|(flags & AT_SYMLINK_NOFOLLOW ? O_NOFOLLOW : 0)); + if (fd < 0) + return -errno; + + xsprintf(fn, "/proc/self/fd/%i", fd); + + l = getxattr(fn, attribute, value, size); + if (l < 0) + return -errno; + + return l; +} + +static int parse_crtime(le64_t le, usec_t *usec) { + uint64_t u; + + assert(usec); + + u = le64toh(le); + if (u == 0 || u == (uint64_t) -1) + return -EIO; + + *usec = (usec_t) u; + return 0; +} + +int fd_getcrtime(int fd, usec_t *usec) { + le64_t le; + ssize_t n; + + assert(fd >= 0); + assert(usec); + + /* Until Linux gets a real concept of birthtime/creation time, + * let's fake one with xattrs */ + + n = fgetxattr(fd, "user.crtime_usec", &le, sizeof(le)); + if (n < 0) + return -errno; + if (n != sizeof(le)) + return -EIO; + + return parse_crtime(le, usec); +} + +int fd_getcrtime_at(int dirfd, const char *name, usec_t *usec, int flags) { + le64_t le; + ssize_t n; + + n = fgetxattrat_fake(dirfd, name, "user.crtime_usec", &le, sizeof(le), flags); + if (n < 0) + return -errno; + if (n != sizeof(le)) + return -EIO; + + return parse_crtime(le, usec); +} + +int path_getcrtime(const char *p, usec_t *usec) { + le64_t le; + ssize_t n; + + assert(p); + assert(usec); + + n = getxattr(p, "user.crtime_usec", &le, sizeof(le)); + if (n < 0) + return -errno; + if (n != sizeof(le)) + return -EIO; + + return parse_crtime(le, usec); +} + +int fd_setcrtime(int fd, usec_t usec) { + le64_t le; + + assert(fd >= 0); + + if (usec <= 0) + usec = now(CLOCK_REALTIME); + + le = htole64((uint64_t) usec); + if (fsetxattr(fd, "user.crtime_usec", &le, sizeof(le), 0) < 0) + return -errno; + + return 0; +} diff --git a/src/basic/xattr-util.h b/src/basic/xattr-util.h new file mode 100644 index 0000000000..cf4cb12a25 --- /dev/null +++ b/src/basic/xattr-util.h @@ -0,0 +1,38 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <stdbool.h> +#include <sys/types.h> + +#include "time-util.h" + +int getxattr_malloc(const char *path, const char *name, char **value, bool allow_symlink); +int fgetxattr_malloc(int fd, const char *name, char **value); + +ssize_t fgetxattrat_fake(int dirfd, const char *filename, const char *attribute, void *value, size_t size, int flags); + +int fd_setcrtime(int fd, usec_t usec); + +int fd_getcrtime(int fd, usec_t *usec); +int path_getcrtime(const char *p, usec_t *usec); +int fd_getcrtime_at(int dirfd, const char *name, usec_t *usec, int flags); diff --git a/src/binfmt/binfmt.c b/src/binfmt/binfmt.c index b96695c353..8e63153c92 100644 --- a/src/binfmt/binfmt.c +++ b/src/binfmt/binfmt.c @@ -27,6 +27,7 @@ #include <stdlib.h> #include <string.h> +#include "alloc-util.h" #include "conf-files.h" #include "fd-util.h" #include "fileio.h" diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c index a167f8086c..4cf42d17f3 100644 --- a/src/boot/bootctl.c +++ b/src/boot/bootctl.c @@ -37,9 +37,12 @@ #include <sys/statfs.h> #include <unistd.h> +#include "alloc-util.h" #include "blkid-util.h" #include "efivars.h" #include "fd-util.h" +#include "fileio.h" +#include "locale-util.h" #include "rm-rf.h" #include "string-util.h" #include "util.h" diff --git a/src/bootchart/bootchart.c b/src/bootchart/bootchart.c index ef113ed40c..6723fa5098 100644 --- a/src/bootchart/bootchart.c +++ b/src/bootchart/bootchart.c @@ -48,6 +48,7 @@ #include "sd-journal.h" +#include "alloc-util.h" #include "bootchart.h" #include "conf-parser.h" #include "fd-util.h" @@ -55,6 +56,7 @@ #include "io-util.h" #include "list.h" #include "macro.h" +#include "parse-util.h" #include "path-util.h" #include "store.h" #include "string-util.h" diff --git a/src/bootchart/store.c b/src/bootchart/store.c index 6066e14288..c1b1e77e44 100644 --- a/src/bootchart/store.c +++ b/src/bootchart/store.c @@ -31,10 +31,13 @@ #include <time.h> #include <unistd.h> +#include "alloc-util.h" #include "bootchart.h" #include "cgroup-util.h" +#include "dirent-util.h" #include "fd-util.h" #include "fileio.h" +#include "parse-util.h" #include "store.h" #include "string-util.h" #include "strxcpyx.h" diff --git a/src/bootchart/svg.c b/src/bootchart/svg.c index 43eca90618..05330c0577 100644 --- a/src/bootchart/svg.c +++ b/src/bootchart/svg.c @@ -30,6 +30,7 @@ #include <sys/utsname.h> #include <fcntl.h> +#include "alloc-util.h" #include "architecture.h" #include "util.h" #include "fileio.h" diff --git a/src/bus-proxyd/bus-proxyd.c b/src/bus-proxyd/bus-proxyd.c index 7e7574568c..6a7134644f 100644 --- a/src/bus-proxyd/bus-proxyd.c +++ b/src/bus-proxyd/bus-proxyd.c @@ -33,9 +33,10 @@ #include "sd-daemon.h" +#include "alloc-util.h" #include "bus-internal.h" #include "bus-xml-policy.h" -#include "capability.h" +#include "capability-util.h" #include "def.h" #include "fd-util.h" #include "formats-util.h" diff --git a/src/bus-proxyd/bus-xml-policy.c b/src/bus-proxyd/bus-xml-policy.c index 56dcfeab62..f0834e9525 100644 --- a/src/bus-proxyd/bus-xml-policy.c +++ b/src/bus-proxyd/bus-xml-policy.c @@ -21,12 +21,15 @@ #include "sd-login.h" +#include "alloc-util.h" #include "bus-internal.h" #include "bus-xml-policy.h" #include "conf-files.h" #include "fileio.h" #include "formats-util.h" +#include "locale-util.h" #include "set.h" +#include "string-table.h" #include "string-util.h" #include "strv.h" #include "user-util.h" diff --git a/src/bus-proxyd/driver.c b/src/bus-proxyd/driver.c index 4e859412f8..2e8bd83efd 100644 --- a/src/bus-proxyd/driver.c +++ b/src/bus-proxyd/driver.c @@ -27,6 +27,7 @@ #include "sd-bus.h" +#include "alloc-util.h" #include "bus-internal.h" #include "bus-message.h" #include "bus-util.h" diff --git a/src/bus-proxyd/proxy.c b/src/bus-proxyd/proxy.c index ea2a01fdae..db399b24f2 100644 --- a/src/bus-proxyd/proxy.c +++ b/src/bus-proxyd/proxy.c @@ -31,6 +31,7 @@ #include "sd-bus.h" #include "sd-daemon.h" +#include "alloc-util.h" #include "bus-control.h" #include "bus-internal.h" #include "bus-message.h" @@ -44,6 +45,7 @@ #include "set.h" #include "strv.h" #include "synthesize.h" +#include "user-util.h" #include "util.h" static int proxy_create_destination(Proxy *p, const char *destination, const char *local_sec, bool negotiate_fds) { diff --git a/src/bus-proxyd/stdio-bridge.c b/src/bus-proxyd/stdio-bridge.c index a009ea76c4..6e47884209 100644 --- a/src/bus-proxyd/stdio-bridge.c +++ b/src/bus-proxyd/stdio-bridge.c @@ -30,6 +30,7 @@ #include "sd-daemon.h" #include "sd-bus.h" +#include "alloc-util.h" #include "bus-internal.h" #include "bus-util.h" #include "def.h" diff --git a/src/bus-proxyd/test-bus-xml-policy.c b/src/bus-proxyd/test-bus-xml-policy.c index cb7ff6b970..1f465edd91 100644 --- a/src/bus-proxyd/test-bus-xml-policy.c +++ b/src/bus-proxyd/test-bus-xml-policy.c @@ -25,6 +25,7 @@ #include "sd-bus.h" +#include "alloc-util.h" #include "bus-xml-policy.h" #include "log.h" #include "string-util.h" diff --git a/src/cgls/cgls.c b/src/cgls/cgls.c index 41c539a1bc..4e9a76a100 100644 --- a/src/cgls/cgls.c +++ b/src/cgls/cgls.c @@ -27,6 +27,7 @@ #include "sd-bus.h" +#include "alloc-util.h" #include "bus-error.h" #include "bus-util.h" #include "cgroup-show.h" diff --git a/src/cgtop/cgtop.c b/src/cgtop/cgtop.c index 3786dae2d9..eea8aea76b 100644 --- a/src/cgtop/cgtop.c +++ b/src/cgtop/cgtop.c @@ -30,12 +30,14 @@ #include "sd-bus.h" +#include "alloc-util.h" #include "bus-error.h" #include "bus-util.h" #include "cgroup-util.h" #include "fd-util.h" #include "fileio.h" #include "hashmap.h" +#include "parse-util.h" #include "path-util.h" #include "process-util.h" #include "terminal-util.h" diff --git a/src/core/automount.c b/src/core/automount.c index d362d6579d..4c229247c5 100644 --- a/src/core/automount.c +++ b/src/core/automount.c @@ -29,6 +29,7 @@ #include <sys/stat.h> #include <unistd.h> +#include "alloc-util.h" #include "async.h" #include "automount.h" #include "bus-error.h" @@ -39,10 +40,14 @@ #include "io-util.h" #include "label.h" #include "mkdir.h" +#include "mount-util.h" #include "mount.h" +#include "parse-util.h" #include "path-util.h" #include "process-util.h" #include "special.h" +#include "stdio-util.h" +#include "string-table.h" #include "string-util.h" #include "unit-name.h" #include "unit.h" @@ -84,26 +89,11 @@ static void automount_init(Unit *u) { UNIT(a)->ignore_on_isolate = true; } -static void repeat_unmount(const char *path) { - assert(path); - - for (;;) { - /* If there are multiple mounts on a mount point, this - * removes them all */ - - if (umount2(path, MNT_DETACH) >= 0) - continue; - - if (errno != EINVAL) - log_error_errno(errno, "Failed to unmount: %m"); - - break; - } -} - static int automount_send_ready(Automount *a, Set *tokens, int status); static void unmount_autofs(Automount *a) { + int r; + assert(a); if (a->pipe_fd < 0) @@ -119,8 +109,11 @@ static void unmount_autofs(Automount *a) { * around */ if (a->where && (UNIT(a)->manager->exit_code != MANAGER_RELOAD && - UNIT(a)->manager->exit_code != MANAGER_REEXECUTE)) - repeat_unmount(a->where); + UNIT(a)->manager->exit_code != MANAGER_REEXECUTE)) { + r = repeat_unmount(a->where, MNT_DETACH); + if (r < 0) + log_error_errno(r, "Failed to unmount: %m"); + } } static void automount_done(Unit *u) { @@ -140,13 +133,12 @@ static void automount_done(Unit *u) { static int automount_add_mount_links(Automount *a) { _cleanup_free_ char *parent = NULL; - int r; assert(a); - r = path_get_parent(a->where, &parent); - if (r < 0) - return r; + parent = dirname_malloc(a->where); + if (!parent) + return -ENOMEM; return unit_require_mounts_for(UNIT(a), parent); } @@ -611,12 +603,16 @@ static void automount_enter_waiting(Automount *a) { return; fail: + log_unit_error_errno(UNIT(a), r, "Failed to initialize automounter: %m"); + safe_close_pair(p); - if (mounted) - repeat_unmount(a->where); + if (mounted) { + r = repeat_unmount(a->where, MNT_DETACH); + if (r < 0) + log_error_errno(r, "Failed to unmount, ignoring: %m"); + } - log_unit_error_errno(UNIT(a), r, "Failed to initialize automounter: %m"); automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES); } diff --git a/src/core/bus-endpoint.c b/src/core/bus-endpoint.c index 0c4b3e7c8b..d22a80c91f 100644 --- a/src/core/bus-endpoint.c +++ b/src/core/bus-endpoint.c @@ -19,10 +19,11 @@ #include <stdlib.h> -#include "kdbus.h" +#include "alloc-util.h" +#include "bus-endpoint.h" #include "bus-kernel.h" #include "bus-policy.h" -#include "bus-endpoint.h" +#include "kdbus.h" int bus_kernel_set_endpoint_policy(int fd, uid_t uid, BusEndpoint *ep) { diff --git a/src/core/bus-policy.c b/src/core/bus-policy.c index 2490903a8c..4907c268e8 100644 --- a/src/core/bus-policy.c +++ b/src/core/bus-policy.c @@ -19,9 +19,11 @@ #include <stdlib.h> +#include "alloc-util.h" #include "bus-kernel.h" #include "bus-policy.h" #include "kdbus.h" +#include "string-table.h" #include "user-util.h" #include "util.h" diff --git a/src/core/busname.c b/src/core/busname.c index 335a1fdc4c..68508e20d2 100644 --- a/src/core/busname.c +++ b/src/core/busname.c @@ -21,6 +21,7 @@ #include <sys/mman.h> +#include "alloc-util.h" #include "bus-internal.h" #include "bus-kernel.h" #include "bus-policy.h" @@ -30,9 +31,12 @@ #include "fd-util.h" #include "formats-util.h" #include "kdbus.h" +#include "parse-util.h" +#include "process-util.h" #include "service.h" #include "signal-util.h" #include "special.h" +#include "string-table.h" #include "string-util.h" static const UnitActiveState state_translation_table[_BUSNAME_STATE_MAX] = { @@ -360,10 +364,9 @@ static int busname_coldplug(Unit *u) { if (n->deserialized_state == n->state) return 0; - if (IN_SET(n->deserialized_state, BUSNAME_MAKING, BUSNAME_SIGTERM, BUSNAME_SIGKILL)) { - - if (n->control_pid <= 0) - return -EBADMSG; + if (n->control_pid > 0 && + pid_is_unwaited(n->control_pid) && + IN_SET(n->deserialized_state, BUSNAME_MAKING, BUSNAME_SIGTERM, BUSNAME_SIGKILL)) { r = unit_watch_pid(UNIT(n), n->control_pid); if (r < 0) diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 2a2cf02774..bed01fde21 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -22,12 +22,17 @@ #include <fcntl.h> #include <fnmatch.h> +#include "alloc-util.h" #include "cgroup-util.h" #include "cgroup.h" #include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "parse-util.h" #include "path-util.h" #include "process-util.h" #include "special.h" +#include "string-table.h" #include "string-util.h" #define CGROUP_CPU_QUOTA_PERIOD_USEC ((usec_t) 100 * USEC_PER_MSEC) @@ -1204,7 +1209,7 @@ int unit_search_main_pid(Unit *u, pid_t *ret) { continue; /* Ignore processes that aren't our kids */ - if (get_parent_of_pid(npid, &ppid) >= 0 && ppid != mypid) + if (get_process_ppid(npid, &ppid) >= 0 && ppid != mypid) continue; if (pid != 0) diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c index 6a43be873a..3fd295baa9 100644 --- a/src/core/dbus-cgroup.c +++ b/src/core/dbus-cgroup.c @@ -19,11 +19,13 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "bus-util.h" #include "cgroup-util.h" #include "cgroup.h" #include "dbus-cgroup.h" #include "fd-util.h" +#include "fileio.h" #include "path-util.h" static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy, cgroup_device_policy, CGroupDevicePolicy); diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c index 12aeda6f2f..db4206a523 100644 --- a/src/core/dbus-execute.c +++ b/src/core/dbus-execute.c @@ -26,8 +26,9 @@ #endif #include "af-list.h" +#include "alloc-util.h" #include "bus-util.h" -#include "capability.h" +#include "capability-util.h" #include "dbus-execute.h" #include "env-util.h" #include "execute.h" @@ -36,13 +37,16 @@ #include "ioprio.h" #include "missing.h" #include "namespace.h" +#include "parse-util.h" #include "path-util.h" -#include "strv.h" -#include "utf8.h" - +#include "process-util.h" +#include "rlimit-util.h" #ifdef HAVE_SECCOMP #include "seccomp-util.h" #endif +#include "strv.h" +#include "syslog-util.h" +#include "utf8.h" BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output, exec_output, ExecOutput); @@ -109,7 +113,7 @@ static int property_get_oom_score_adjust( n = 0; if (read_one_line_file("/proc/self/oom_score_adj", &t) >= 0) - safe_atoi(t, &n); + safe_atoi32(t, &n); } return sd_bus_message_append(reply, "i", n); diff --git a/src/core/dbus-job.c b/src/core/dbus-job.c index e95ec5c0cb..8c30d66250 100644 --- a/src/core/dbus-job.c +++ b/src/core/dbus-job.c @@ -21,12 +21,13 @@ #include "sd-bus.h" +#include "alloc-util.h" +#include "dbus-job.h" #include "dbus.h" #include "job.h" #include "log.h" #include "selinux-access.h" #include "string-util.h" -#include "dbus-job.h" static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, job_type, JobType); static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_state, job_state, JobState); diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index 1ef259ec7a..1f9f25093d 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -23,6 +23,7 @@ #include <sys/prctl.h> #include <unistd.h> +#include "alloc-util.h" #include "architecture.h" #include "build.h" #include "bus-common-errors.h" @@ -35,13 +36,16 @@ #include "dbus.h" #include "env-util.h" #include "fd-util.h" +#include "fileio.h" #include "formats-util.h" #include "install.h" #include "log.h" #include "path-util.h" #include "selinux-access.h" +#include "stat-util.h" #include "string-util.h" #include "strv.h" +#include "syslog-util.h" #include "virt.h" #include "watchdog.h" diff --git a/src/core/dbus-scope.c b/src/core/dbus-scope.c index f8fb373bf0..16375b2311 100644 --- a/src/core/dbus-scope.c +++ b/src/core/dbus-scope.c @@ -19,17 +19,18 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include "selinux-access.h" -#include "unit.h" -#include "scope.h" -#include "dbus.h" -#include "bus-util.h" -#include "bus-internal.h" +#include "alloc-util.h" #include "bus-common-errors.h" -#include "dbus-unit.h" +#include "bus-internal.h" +#include "bus-util.h" #include "dbus-cgroup.h" #include "dbus-kill.h" #include "dbus-scope.h" +#include "dbus-unit.h" +#include "dbus.h" +#include "scope.h" +#include "selinux-access.h" +#include "unit.h" static int bus_scope_abandon(sd_bus_message *message, void *userdata, sd_bus_error *error) { Scope *s = userdata; diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c index 22b8690c54..c41b3e1723 100644 --- a/src/core/dbus-service.c +++ b/src/core/dbus-service.c @@ -19,6 +19,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "async.h" #include "bus-util.h" #include "dbus-cgroup.h" @@ -26,6 +27,7 @@ #include "dbus-kill.h" #include "dbus-service.h" #include "fd-util.h" +#include "fileio.h" #include "path-util.h" #include "service.h" #include "string-util.h" diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c index 5941b72bc0..be5ef261a6 100644 --- a/src/core/dbus-socket.c +++ b/src/core/dbus-socket.c @@ -19,13 +19,14 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "bus-util.h" #include "dbus-cgroup.h" #include "dbus-execute.h" +#include "dbus-socket.h" #include "socket.h" #include "string-util.h" #include "unit.h" -#include "dbus-socket.h" static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, socket_result, SocketResult); static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_bind_ipv6_only, socket_address_bind_ipv6_only, SocketAddressBindIPv6Only); diff --git a/src/core/dbus-timer.c b/src/core/dbus-timer.c index 8ea2cf84a4..a8a280d961 100644 --- a/src/core/dbus-timer.c +++ b/src/core/dbus-timer.c @@ -19,11 +19,12 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include "unit.h" -#include "timer.h" -#include "dbus-timer.h" +#include "alloc-util.h" #include "bus-util.h" +#include "dbus-timer.h" #include "strv.h" +#include "timer.h" +#include "unit.h" static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, timer_result, TimerResult); diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index 7220fe688f..6320cd1aa9 100644 --- a/src/core/dbus-unit.c +++ b/src/core/dbus-unit.c @@ -21,15 +21,18 @@ #include "sd-bus.h" +#include "alloc-util.h" #include "bus-common-errors.h" #include "cgroup-util.h" +#include "dbus-unit.h" #include "dbus.h" +#include "locale-util.h" #include "log.h" #include "selinux-access.h" #include "special.h" #include "string-util.h" #include "strv.h" -#include "dbus-unit.h" +#include "user-util.h" static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_load_state, unit_load_state, UnitLoadState); static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_job_mode, job_mode, JobMode); diff --git a/src/core/dbus.c b/src/core/dbus.c index 37410a9870..6c44b28adf 100644 --- a/src/core/dbus.c +++ b/src/core/dbus.c @@ -25,6 +25,7 @@ #include "sd-bus.h" +#include "alloc-util.h" #include "bus-common-errors.h" #include "bus-error.h" #include "bus-internal.h" @@ -45,6 +46,7 @@ #include "string-util.h" #include "strv.h" #include "strxcpyx.h" +#include "user-util.h" #define CONNECTIONS_MAX 4096 @@ -782,7 +784,7 @@ static int bus_setup_api(Manager *m, sd_bus *bus) { HASHMAP_FOREACH_KEY(u, name, m->watch_bus, i) { r = unit_install_bus_match(u, bus, name); if (r < 0) - log_error_errno(r, "Failed to subscribe to NameOwnerChanged signal: %m"); + log_error_errno(r, "Failed to subscribe to NameOwnerChanged signal for '%s': %m", name); } r = sd_bus_add_match( diff --git a/src/core/device.c b/src/core/device.c index 9127d2d225..23ee7aee7e 100644 --- a/src/core/device.c +++ b/src/core/device.c @@ -24,15 +24,18 @@ #include "libudev.h" +#include "alloc-util.h" #include "dbus-device.h" +#include "device.h" #include "log.h" +#include "parse-util.h" #include "path-util.h" +#include "stat-util.h" #include "string-util.h" #include "swap.h" #include "udev-util.h" #include "unit-name.h" #include "unit.h" -#include "device.h" static const UnitActiveState state_translation_table[_DEVICE_STATE_MAX] = { [DEVICE_DEAD] = UNIT_INACTIVE, diff --git a/src/core/execute.c b/src/core/execute.c index 3f2607ff1a..d751065af0 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -53,6 +53,7 @@ #include "sd-messages.h" #include "af-list.h" +#include "alloc-util.h" #ifdef HAVE_APPARMOR #include "apparmor-util.h" #endif @@ -60,7 +61,7 @@ #include "barrier.h" #include "bus-endpoint.h" #include "cap-list.h" -#include "capability.h" +#include "capability-util.h" #include "def.h" #include "env-util.h" #include "errno-list.h" @@ -69,6 +70,8 @@ #include "fd-util.h" #include "fileio.h" #include "formats-util.h" +#include "fs-util.h" +#include "glob-util.h" #include "io-util.h" #include "ioprio.h" #include "log.h" @@ -76,8 +79,10 @@ #include "missing.h" #include "mkdir.h" #include "namespace.h" +#include "parse-util.h" #include "path-util.h" #include "process-util.h" +#include "rlimit-util.h" #include "rm-rf.h" #ifdef HAVE_SECCOMP #include "seccomp-util.h" @@ -86,8 +91,10 @@ #include "selinux-util.h" #include "signal-util.h" #include "smack-util.h" +#include "string-table.h" #include "string-util.h" #include "strv.h" +#include "syslog-util.h" #include "terminal-util.h" #include "unit.h" #include "user-util.h" diff --git a/src/core/failure-action.c b/src/core/failure-action.c index 3412accf3e..c7c95984b7 100644 --- a/src/core/failure-action.c +++ b/src/core/failure-action.c @@ -23,10 +23,11 @@ #include <sys/reboot.h> #include <linux/reboot.h> -#include "bus-util.h" #include "bus-error.h" -#include "special.h" +#include "bus-util.h" #include "failure-action.h" +#include "special.h" +#include "string-table.h" #include "terminal-util.h" static void log_and_status(Manager *m, const char *message) { diff --git a/src/core/hostname-setup.c b/src/core/hostname-setup.c index f1563afff9..cc7515905d 100644 --- a/src/core/hostname-setup.c +++ b/src/core/hostname-setup.c @@ -23,6 +23,7 @@ #include <stdio.h> #include <stdlib.h> +#include "alloc-util.h" #include "fileio.h" #include "hostname-util.h" #include "log.h" diff --git a/src/core/ima-setup.c b/src/core/ima-setup.c index 0c0982b0b4..9572fa17d9 100644 --- a/src/core/ima-setup.c +++ b/src/core/ima-setup.c @@ -25,6 +25,7 @@ #include <errno.h> #include "fd-util.h" +#include "fileio.h" #include "ima-setup.h" #include "log.h" #include "util.h" diff --git a/src/core/job.c b/src/core/job.c index 8a0e0a0ea4..120381fc3b 100644 --- a/src/core/job.c +++ b/src/core/job.c @@ -24,20 +24,23 @@ #include "sd-id128.h" #include "sd-messages.h" +#include "alloc-util.h" #include "async.h" #include "dbus-job.h" #include "dbus.h" #include "escape.h" +#include "job.h" #include "log.h" #include "macro.h" +#include "parse-util.h" #include "set.h" #include "special.h" +#include "string-table.h" #include "string-util.h" #include "strv.h" #include "terminal-util.h" #include "unit.h" #include "virt.h" -#include "job.h" Job* job_new_raw(Unit *unit) { Job *j; diff --git a/src/core/kill.c b/src/core/kill.c index bddfa4460f..1466d5ce64 100644 --- a/src/core/kill.c +++ b/src/core/kill.c @@ -19,9 +19,10 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include "util.h" -#include "signal-util.h" #include "kill.h" +#include "signal-util.h" +#include "string-table.h" +#include "util.h" void kill_context_init(KillContext *c) { assert(c); diff --git a/src/core/killall.c b/src/core/killall.c index cb11987166..77f145b4d1 100644 --- a/src/core/killall.c +++ b/src/core/killall.c @@ -24,9 +24,11 @@ #include <sys/wait.h> #include <unistd.h> +#include "alloc-util.h" #include "fd-util.h" #include "formats-util.h" #include "killall.h" +#include "parse-util.h" #include "process-util.h" #include "set.h" #include "string-util.h" diff --git a/src/core/kmod-setup.c b/src/core/kmod-setup.c index 2068ffd69b..651f79a1fe 100644 --- a/src/core/kmod-setup.c +++ b/src/core/kmod-setup.c @@ -27,7 +27,7 @@ #endif #include "macro.h" -#include "capability.h" +#include "capability-util.h" #include "bus-util.h" #include "kmod-setup.h" diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index 31fdc48823..a30cd0967d 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -32,6 +32,7 @@ #include <sys/resource.h> #include <sys/stat.h> +#include "alloc-util.h" #include "af-list.h" #include "bus-error.h" #include "bus-internal.h" @@ -44,22 +45,27 @@ #include "errno-list.h" #include "escape.h" #include "fd-util.h" +#include "fs-util.h" #include "ioprio.h" #include "load-fragment.h" #include "log.h" #include "missing.h" +#include "parse-util.h" #include "path-util.h" +#include "process-util.h" #ifdef HAVE_SECCOMP #include "seccomp-util.h" #endif #include "securebits.h" #include "signal-util.h" +#include "stat-util.h" #include "string-util.h" #include "strv.h" #include "unit-name.h" #include "unit-printf.h" #include "unit.h" #include "utf8.h" +#include "web-util.h" int config_parse_warn_compat( const char *unit, @@ -976,10 +982,11 @@ int config_parse_bounding_set(const char *unit, void *userdata) { uint64_t *capability_bounding_set_drop = data; - const char *word, *state; - size_t l; + uint64_t capability_bounding_set; bool invert = false; uint64_t sum = 0; + const char *prev; + const char *cur; assert(filename); assert(lvalue); @@ -996,29 +1003,38 @@ int config_parse_bounding_set(const char *unit, * non-inverted everywhere to have a fully normalized * interface. */ - FOREACH_WORD_QUOTED(word, l, rvalue, state) { - _cleanup_free_ char *t = NULL; + prev = cur = rvalue; + for (;;) { + _cleanup_free_ char *word = NULL; int cap; + int r; - t = strndup(word, l); - if (!t) + r = extract_first_word(&cur, &word, NULL, EXTRACT_QUOTES); + if (r == 0) + break; + if (r == -ENOMEM) return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Trailing garbage in bounding set, ignoring: %s", prev); + break; + } - cap = capability_from_name(t); + cap = capability_from_name(word); if (cap < 0) { - log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse capability in bounding set, ignoring: %s", t); + log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse capability in bounding set, ignoring: %s", word); + prev = cur; continue; } sum |= ((uint64_t) 1ULL) << (uint64_t) cap; + prev = cur; } - if (!isempty(state)) - log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring."); - if (invert) - *capability_bounding_set_drop |= sum; + capability_bounding_set = invert ? ~sum : sum; + if (*capability_bounding_set_drop && capability_bounding_set) + *capability_bounding_set_drop = ~(~*capability_bounding_set_drop | capability_bounding_set); else - *capability_bounding_set_drop |= ~sum; + *capability_bounding_set_drop = ~capability_bounding_set; return 0; } diff --git a/src/core/machine-id-setup.c b/src/core/machine-id-setup.c index c72892b343..145ba2a28d 100644 --- a/src/core/machine-id-setup.c +++ b/src/core/machine-id-setup.c @@ -29,16 +29,22 @@ #include "sd-id128.h" +#include "alloc-util.h" #include "fd-util.h" #include "fileio.h" +#include "fs-util.h" +#include "hexdecoct.h" #include "io-util.h" #include "log.h" #include "machine-id-setup.h" #include "macro.h" #include "mkdir.h" +#include "mount-util.h" #include "path-util.h" #include "process-util.h" +#include "stat-util.h" #include "string-util.h" +#include "umask-util.h" #include "util.h" #include "virt.h" diff --git a/src/core/main.c b/src/core/main.c index b0ca6fa10e..593b974566 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -40,11 +40,12 @@ #include "sd-daemon.h" #include "sd-bus.h" +#include "alloc-util.h" #include "architecture.h" #include "build.h" #include "bus-error.h" #include "bus-util.h" -#include "capability.h" +#include "capability-util.h" #include "clock-util.h" #include "conf-parser.h" #include "cpu-set-util.h" @@ -55,6 +56,7 @@ #include "fdset.h" #include "fileio.h" #include "formats-util.h" +#include "fs-util.h" #include "hostname-setup.h" #include "ima-setup.h" #include "killall.h" @@ -67,12 +69,17 @@ #include "missing.h" #include "mount-setup.h" #include "pager.h" +#include "parse-util.h" +#include "proc-cmdline.h" #include "process-util.h" +#include "rlimit-util.h" #include "selinux-setup.h" #include "selinux-util.h" #include "signal-util.h" #include "smack-setup.h" #include "special.h" +#include "stat-util.h" +#include "stdio-util.h" #include "strv.h" #include "switch-root.h" #include "terminal-util.h" diff --git a/src/core/manager.c b/src/core/manager.c index 287676ff27..b13663e702 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -40,6 +40,7 @@ #include "sd-daemon.h" #include "sd-messages.h" +#include "alloc-util.h" #include "audit-fd.h" #include "boot-timestamps.h" #include "bus-common-errors.h" @@ -54,6 +55,8 @@ #include "escape.h" #include "exit-status.h" #include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" #include "hashmap.h" #include "io-util.h" #include "locale-setup.h" @@ -62,6 +65,7 @@ #include "manager.h" #include "missing.h" #include "mkdir.h" +#include "parse-util.h" #include "path-lookup.h" #include "path-util.h" #include "process-util.h" @@ -69,16 +73,21 @@ #include "rm-rf.h" #include "signal-util.h" #include "special.h" +#include "stat-util.h" +#include "string-table.h" #include "string-util.h" #include "strv.h" #include "terminal-util.h" #include "time-util.h" #include "transaction.h" +#include "umask-util.h" #include "unit-name.h" #include "util.h" #include "virt.h" #include "watchdog.h" +#define NOTIFY_RCVBUF_SIZE (8*1024*1024) + /* Initial delay and the interval for printing status messages about running jobs */ #define JOBS_IN_PROGRESS_WAIT_USEC (5*USEC_PER_SEC) #define JOBS_IN_PROGRESS_PERIOD_USEC (USEC_PER_SEC / 3) @@ -682,6 +691,8 @@ static int manager_setup_notify(Manager *m) { if (fd < 0) return log_error_errno(errno, "Failed to allocate notification socket: %m"); + fd_inc_rcvbuf(fd, NOTIFY_RCVBUF_SIZE); + if (m->running_as == MANAGER_SYSTEM) m->notify_socket = strdup("/run/systemd/notify"); else { @@ -1481,7 +1492,7 @@ static unsigned manager_dispatch_dbus_queue(Manager *m) { return n; } -static void manager_invoke_notify_message(Manager *m, Unit *u, pid_t pid, char *buf, size_t n, FDSet *fds) { +static void manager_invoke_notify_message(Manager *m, Unit *u, pid_t pid, const char *buf, size_t n, FDSet *fds) { _cleanup_strv_free_ char **tags = NULL; assert(m); @@ -1502,9 +1513,33 @@ static void manager_invoke_notify_message(Manager *m, Unit *u, pid_t pid, char * } static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) { + _cleanup_fdset_free_ FDSet *fds = NULL; Manager *m = userdata; + + char buf[NOTIFY_BUFFER_MAX+1]; + struct iovec iovec = { + .iov_base = buf, + .iov_len = sizeof(buf)-1, + }; + union { + struct cmsghdr cmsghdr; + uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) + + CMSG_SPACE(sizeof(int) * NOTIFY_FD_MAX)]; + } control = {}; + struct msghdr msghdr = { + .msg_iov = &iovec, + .msg_iovlen = 1, + .msg_control = &control, + .msg_controllen = sizeof(control), + }; + + struct cmsghdr *cmsg; + struct ucred *ucred = NULL; + bool found = false; + Unit *u1, *u2, *u3; + int r, *fd_array = NULL; + unsigned n_fds = 0; ssize_t n; - int r; assert(m); assert(m->notify_fd == fd); @@ -1514,106 +1549,80 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t return 0; } - for (;;) { - _cleanup_fdset_free_ FDSet *fds = NULL; - char buf[NOTIFY_BUFFER_MAX+1]; - struct iovec iovec = { - .iov_base = buf, - .iov_len = sizeof(buf)-1, - }; - union { - struct cmsghdr cmsghdr; - uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) + - CMSG_SPACE(sizeof(int) * NOTIFY_FD_MAX)]; - } control = {}; - struct msghdr msghdr = { - .msg_iov = &iovec, - .msg_iovlen = 1, - .msg_control = &control, - .msg_controllen = sizeof(control), - }; - struct cmsghdr *cmsg; - struct ucred *ucred = NULL; - bool found = false; - Unit *u1, *u2, *u3; - int *fd_array = NULL; - unsigned n_fds = 0; - - n = recvmsg(m->notify_fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); - if (n < 0) { - if (errno == EAGAIN || errno == EINTR) - break; + n = recvmsg(m->notify_fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); + if (n < 0) { + if (errno == EAGAIN || errno == EINTR) + return 0; - return -errno; - } + return -errno; + } - CMSG_FOREACH(cmsg, &msghdr) { - if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { + CMSG_FOREACH(cmsg, &msghdr) { + if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { - fd_array = (int*) CMSG_DATA(cmsg); - n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int); + fd_array = (int*) CMSG_DATA(cmsg); + n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int); - } else if (cmsg->cmsg_level == SOL_SOCKET && - cmsg->cmsg_type == SCM_CREDENTIALS && - cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) { + } else if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_CREDENTIALS && + cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) { - ucred = (struct ucred*) CMSG_DATA(cmsg); - } + ucred = (struct ucred*) CMSG_DATA(cmsg); } + } - if (n_fds > 0) { - assert(fd_array); + if (n_fds > 0) { + assert(fd_array); - r = fdset_new_array(&fds, fd_array, n_fds); - if (r < 0) { - close_many(fd_array, n_fds); - return log_oom(); - } + r = fdset_new_array(&fds, fd_array, n_fds); + if (r < 0) { + close_many(fd_array, n_fds); + return log_oom(); } + } - if (!ucred || ucred->pid <= 0) { - log_warning("Received notify message without valid credentials. Ignoring."); - continue; - } + if (!ucred || ucred->pid <= 0) { + log_warning("Received notify message without valid credentials. Ignoring."); + return 0; + } - if ((size_t) n >= sizeof(buf)) { - log_warning("Received notify message exceeded maximum size. Ignoring."); - continue; - } + if ((size_t) n >= sizeof(buf)) { + log_warning("Received notify message exceeded maximum size. Ignoring."); + return 0; + } - buf[n] = 0; + buf[n] = 0; - /* Notify every unit that might be interested, but try - * to avoid notifying the same one multiple times. */ - u1 = manager_get_unit_by_pid_cgroup(m, ucred->pid); - if (u1) { - manager_invoke_notify_message(m, u1, ucred->pid, buf, n, fds); - found = true; - } + /* Notify every unit that might be interested, but try + * to avoid notifying the same one multiple times. */ + u1 = manager_get_unit_by_pid_cgroup(m, ucred->pid); + if (u1) { + manager_invoke_notify_message(m, u1, ucred->pid, buf, n, fds); + found = true; + } - u2 = hashmap_get(m->watch_pids1, PID_TO_PTR(ucred->pid)); - if (u2 && u2 != u1) { - manager_invoke_notify_message(m, u2, ucred->pid, buf, n, fds); - found = true; - } + u2 = hashmap_get(m->watch_pids1, PID_TO_PTR(ucred->pid)); + if (u2 && u2 != u1) { + manager_invoke_notify_message(m, u2, ucred->pid, buf, n, fds); + found = true; + } - u3 = hashmap_get(m->watch_pids2, PID_TO_PTR(ucred->pid)); - if (u3 && u3 != u2 && u3 != u1) { - manager_invoke_notify_message(m, u3, ucred->pid, buf, n, fds); - found = true; - } + u3 = hashmap_get(m->watch_pids2, PID_TO_PTR(ucred->pid)); + if (u3 && u3 != u2 && u3 != u1) { + manager_invoke_notify_message(m, u3, ucred->pid, buf, n, fds); + found = true; + } - if (!found) - log_warning("Cannot find unit for notify message of PID "PID_FMT".", ucred->pid); + if (!found) + log_warning("Cannot find unit for notify message of PID "PID_FMT".", ucred->pid); - if (fdset_size(fds) > 0) - log_warning("Got auxiliary fds with notification message, closing all."); - } + if (fdset_size(fds) > 0) + log_warning("Got auxiliary fds with notification message, closing all."); return 0; } -static void invoke_sigchld_event(Manager *m, Unit *u, siginfo_t *si) { +static void invoke_sigchld_event(Manager *m, Unit *u, const siginfo_t *si) { assert(m); assert(u); assert(si); @@ -1995,8 +2004,7 @@ int manager_loop(Manager *m) { m->exit_code = MANAGER_OK; /* Release the path cache */ - set_free_free(m->unit_path_cache); - m->unit_path_cache = NULL; + m->unit_path_cache = set_free_free(m->unit_path_cache); manager_check_finished(m); @@ -2106,6 +2114,9 @@ void manager_send_unit_audit(Manager *m, Unit *u, int type, bool success) { const char *msg; int audit_fd, r; + if (m->running_as != MANAGER_SYSTEM) + return; + audit_fd = get_audit_fd(); if (audit_fd < 0) return; @@ -2115,9 +2126,6 @@ void manager_send_unit_audit(Manager *m, Unit *u, int type, bool success) { if (m->n_reloading > 0) return; - if (m->running_as != MANAGER_SYSTEM) - return; - if (u->type != UNIT_SERVICE) return; @@ -2766,8 +2774,7 @@ static int create_generator_dir(Manager *m, char **generator, const char *name) return log_oom(); if (!mkdtemp(p)) { - log_error_errno(errno, "Failed to create generator directory %s: %m", - p); + log_error_errno(errno, "Failed to create generator directory %s: %m", p); free(p); return -errno; } diff --git a/src/core/mount-setup.c b/src/core/mount-setup.c index 9b16eaa0e2..b2596d1cd1 100644 --- a/src/core/mount-setup.c +++ b/src/core/mount-setup.c @@ -25,22 +25,25 @@ #include <unistd.h> #include <ftw.h> -#include "mount-setup.h" -#include "dev-setup.h" +#include "alloc-util.h" #include "bus-util.h" +#include "cgroup-util.h" +#include "dev-setup.h" +#include "efivars.h" +#include "label.h" #include "log.h" #include "macro.h" -#include "util.h" -#include "label.h" -#include "set.h" -#include "strv.h" +#include "missing.h" #include "mkdir.h" +#include "mount-setup.h" +#include "mount-util.h" #include "path-util.h" -#include "missing.h" -#include "virt.h" -#include "efivars.h" +#include "set.h" #include "smack-util.h" -#include "cgroup-util.h" +#include "strv.h" +#include "user-util.h" +#include "util.h" +#include "virt.h" typedef enum MountMode { MNT_NONE = 0, diff --git a/src/core/mount.c b/src/core/mount.c index ebdb3503e9..950d5d76d5 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -26,6 +26,7 @@ #include "sd-messages.h" +#include "alloc-util.h" #include "dbus-mount.h" #include "escape.h" #include "exit-status.h" @@ -35,10 +36,14 @@ #include "manager.h" #include "mkdir.h" #include "mount-setup.h" +#include "mount-util.h" #include "mount.h" +#include "parse-util.h" #include "path-util.h" +#include "process-util.h" #include "smack-util.h" #include "special.h" +#include "string-table.h" #include "string-util.h" #include "strv.h" #include "unit-name.h" @@ -251,9 +256,10 @@ static int mount_add_mount_links(Mount *m) { if (!path_equal(m->where, "/")) { /* Adds in links to other mount points that might lie further * up in the hierarchy */ - r = path_get_parent(m->where, &parent); - if (r < 0) - return r; + + parent = dirname_malloc(m->where); + if (!parent) + return -ENOMEM; r = unit_require_mounts_for(UNIT(m), parent); if (r < 0) @@ -626,19 +632,19 @@ static int mount_coldplug(Unit *u) { if (new_state == m->state) return 0; - if (new_state == MOUNT_MOUNTING || - new_state == MOUNT_MOUNTING_DONE || - new_state == MOUNT_REMOUNTING || - new_state == MOUNT_UNMOUNTING || - new_state == MOUNT_MOUNTING_SIGTERM || - new_state == MOUNT_MOUNTING_SIGKILL || - new_state == MOUNT_UNMOUNTING_SIGTERM || - new_state == MOUNT_UNMOUNTING_SIGKILL || - new_state == MOUNT_REMOUNTING_SIGTERM || - new_state == MOUNT_REMOUNTING_SIGKILL) { - - if (m->control_pid <= 0) - return -EBADMSG; + if (m->control_pid > 0 && + pid_is_unwaited(m->control_pid) && + IN_SET(new_state, + MOUNT_MOUNTING, + MOUNT_MOUNTING_DONE, + MOUNT_REMOUNTING, + MOUNT_UNMOUNTING, + MOUNT_MOUNTING_SIGTERM, + MOUNT_MOUNTING_SIGKILL, + MOUNT_UNMOUNTING_SIGTERM, + MOUNT_UNMOUNTING_SIGKILL, + MOUNT_REMOUNTING_SIGTERM, + MOUNT_REMOUNTING_SIGKILL)) { r = unit_watch_pid(UNIT(m), m->control_pid); if (r < 0) diff --git a/src/core/namespace.c b/src/core/namespace.c index 4d11d54bfe..81ba09ea5d 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -28,17 +28,22 @@ #include <unistd.h> #include <linux/fs.h> +#include "alloc-util.h" #include "dev-setup.h" #include "fd-util.h" #include "loopback-setup.h" #include "missing.h" #include "mkdir.h" +#include "mount-util.h" #include "namespace.h" #include "path-util.h" #include "selinux-util.h" #include "socket-util.h" +#include "string-table.h" #include "string-util.h" #include "strv.h" +#include "umask-util.h" +#include "user-util.h" #include "util.h" typedef enum MountMode { diff --git a/src/core/path.c b/src/core/path.c index 11054d8c78..35e1753583 100644 --- a/src/core/path.c +++ b/src/core/path.c @@ -28,10 +28,14 @@ #include "bus-util.h" #include "dbus-path.h" #include "fd-util.h" +#include "fs-util.h" +#include "glob-util.h" #include "macro.h" #include "mkdir.h" #include "path.h" #include "special.h" +#include "stat-util.h" +#include "string-table.h" #include "string-util.h" #include "unit-name.h" #include "unit.h" diff --git a/src/core/scope.c b/src/core/scope.c index 9f72851382..6bacb226e8 100644 --- a/src/core/scope.c +++ b/src/core/scope.c @@ -22,15 +22,17 @@ #include <errno.h> #include <unistd.h> +#include "alloc-util.h" #include "dbus-scope.h" #include "load-dropin.h" #include "log.h" +#include "scope.h" #include "special.h" +#include "string-table.h" #include "string-util.h" #include "strv.h" #include "unit-name.h" #include "unit.h" -#include "scope.h" static const UnitActiveState state_translation_table[_SCOPE_STATE_MAX] = { [SCOPE_DEAD] = UNIT_INACTIVE, diff --git a/src/core/selinux-access.c b/src/core/selinux-access.c index cf38fa0ebe..4bcdd27389 100644 --- a/src/core/selinux-access.c +++ b/src/core/selinux-access.c @@ -32,13 +32,16 @@ #endif #include "sd-bus.h" + +#include "alloc-util.h" +#include "audit-fd.h" #include "bus-util.h" -#include "util.h" #include "log.h" +#include "path-util.h" #include "selinux-util.h" -#include "audit-fd.h" +#include "stdio-util.h" #include "strv.h" -#include "path-util.h" +#include "util.h" static bool initialized = false; diff --git a/src/core/service.c b/src/core/service.c index abcbd4954f..586eddd99a 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -23,6 +23,7 @@ #include <signal.h> #include <unistd.h> +#include "alloc-util.h" #include "async.h" #include "bus-error.h" #include "bus-kernel.h" @@ -35,15 +36,18 @@ #include "fd-util.h" #include "fileio.h" #include "formats-util.h" +#include "fs-util.h" #include "load-dropin.h" #include "load-fragment.h" #include "log.h" #include "manager.h" +#include "parse-util.h" #include "path-util.h" #include "process-util.h" #include "service.h" #include "signal-util.h" #include "special.h" +#include "string-table.h" #include "string-util.h" #include "strv.h" #include "unit-name.h" @@ -171,7 +175,7 @@ static int service_set_main_pid(Service *s, pid_t pid) { s->main_pid = pid; s->main_pid_known = true; - if (get_parent_of_pid(pid, &ppid) >= 0 && ppid != getpid()) { + if (get_process_ppid(pid, &ppid) >= 0 && ppid != getpid()) { log_unit_warning(UNIT(s), "Supervising process "PID_FMT" which is not our child. We'll most likely not notice when it exits.", pid); s->main_pid_alien = true; } else @@ -416,7 +420,7 @@ static int service_add_fd_store_set(Service *s, FDSet *fds, const char *name) { } if (fdset_size(fds) > 0) - log_unit_warning(UNIT(s), "Tried to store more fds than FDStoreMax=%u allows, closing remaining.", s->n_fd_store_max); + log_unit_warning(UNIT(s), "Tried to store more fds than FileDescriptorStoreMax=%u allows, closing remaining.", s->n_fd_store_max); return 0; } @@ -908,66 +912,67 @@ static int service_coldplug(Unit *u) { assert(s); assert(s->state == SERVICE_DEAD); - if (s->deserialized_state != s->state) { - - if (IN_SET(s->deserialized_state, - SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, - SERVICE_RELOAD, - SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, - SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL)) { - - usec_t k; + if (s->deserialized_state == s->state) + return 0; - k = IN_SET(s->deserialized_state, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, SERVICE_RELOAD) ? s->timeout_start_usec : s->timeout_stop_usec; + if (IN_SET(s->deserialized_state, + SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, + SERVICE_RELOAD, + SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, + SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL)) { - /* For the start/stop timeouts 0 means off */ - if (k > 0) { - r = service_arm_timer(s, k); - if (r < 0) - return r; - } - } + usec_t k; - if (s->deserialized_state == SERVICE_AUTO_RESTART) { + k = IN_SET(s->deserialized_state, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, SERVICE_RELOAD) ? s->timeout_start_usec : s->timeout_stop_usec; - /* The restart timeouts 0 means immediately */ - r = service_arm_timer(s, s->restart_usec); - if (r < 0) - return r; - } - - if (pid_is_unwaited(s->main_pid) && - ((s->deserialized_state == SERVICE_START && IN_SET(s->type, SERVICE_FORKING, SERVICE_DBUS, SERVICE_ONESHOT, SERVICE_NOTIFY)) || - IN_SET(s->deserialized_state, - SERVICE_START, SERVICE_START_POST, - SERVICE_RUNNING, SERVICE_RELOAD, - SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, - SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL))) { - r = unit_watch_pid(UNIT(s), s->main_pid); + /* For the start/stop timeouts 0 means off */ + if (k > 0) { + r = service_arm_timer(s, k); if (r < 0) return r; } + } - if (pid_is_unwaited(s->control_pid) && - IN_SET(s->deserialized_state, - SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, - SERVICE_RELOAD, - SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, - SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL)) { - r = unit_watch_pid(UNIT(s), s->control_pid); - if (r < 0) - return r; - } + if (s->deserialized_state == SERVICE_AUTO_RESTART) { - if (!IN_SET(s->deserialized_state, SERVICE_DEAD, SERVICE_FAILED, SERVICE_AUTO_RESTART)) - unit_watch_all_pids(UNIT(s)); + /* The restart timeouts 0 means immediately */ + r = service_arm_timer(s, s->restart_usec); + if (r < 0) + return r; + } - if (IN_SET(s->deserialized_state, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD)) - service_start_watchdog(s); + if (s->main_pid > 0 && + pid_is_unwaited(s->main_pid) && + ((s->deserialized_state == SERVICE_START && IN_SET(s->type, SERVICE_FORKING, SERVICE_DBUS, SERVICE_ONESHOT, SERVICE_NOTIFY)) || + IN_SET(s->deserialized_state, + SERVICE_START, SERVICE_START_POST, + SERVICE_RUNNING, SERVICE_RELOAD, + SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, + SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL))) { + r = unit_watch_pid(UNIT(s), s->main_pid); + if (r < 0) + return r; + } - service_set_state(s, s->deserialized_state); + if (s->control_pid > 0 && + pid_is_unwaited(s->control_pid) && + IN_SET(s->deserialized_state, + SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, + SERVICE_RELOAD, + SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, + SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL)) { + r = unit_watch_pid(UNIT(s), s->control_pid); + if (r < 0) + return r; } + if (!IN_SET(s->deserialized_state, SERVICE_DEAD, SERVICE_FAILED, SERVICE_AUTO_RESTART)) + unit_watch_all_pids(UNIT(s)); + + if (IN_SET(s->deserialized_state, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD)) + service_start_watchdog(s); + + service_set_state(s, s->deserialized_state); return 0; } diff --git a/src/core/show-status.c b/src/core/show-status.c index 7951ea7303..e4e12a3365 100644 --- a/src/core/show-status.c +++ b/src/core/show-status.c @@ -19,9 +19,14 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" +#include "fd-util.h" +#include "io-util.h" +#include "parse-util.h" +#include "show-status.h" #include "string-util.h" +#include "terminal-util.h" #include "util.h" -#include "show-status.h" int parse_show_status(const char *v, ShowStatus *ret) { int r; @@ -41,3 +46,81 @@ int parse_show_status(const char *v, ShowStatus *ret) { *ret = r ? SHOW_STATUS_YES : SHOW_STATUS_NO; return 0; } + +int status_vprintf(const char *status, bool ellipse, bool ephemeral, const char *format, va_list ap) { + static const char status_indent[] = " "; /* "[" STATUS "] " */ + _cleanup_free_ char *s = NULL; + _cleanup_close_ int fd = -1; + struct iovec iovec[6] = {}; + int n = 0; + static bool prev_ephemeral; + + assert(format); + + /* This is independent of logging, as status messages are + * optional and go exclusively to the console. */ + + if (vasprintf(&s, format, ap) < 0) + return log_oom(); + + fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC); + if (fd < 0) + return fd; + + if (ellipse) { + char *e; + size_t emax, sl; + int c; + + c = fd_columns(fd); + if (c <= 0) + c = 80; + + sl = status ? sizeof(status_indent)-1 : 0; + + emax = c - sl - 1; + if (emax < 3) + emax = 3; + + e = ellipsize(s, emax, 50); + if (e) { + free(s); + s = e; + } + } + + if (prev_ephemeral) + IOVEC_SET_STRING(iovec[n++], "\r" ANSI_ERASE_TO_END_OF_LINE); + prev_ephemeral = ephemeral; + + if (status) { + if (!isempty(status)) { + IOVEC_SET_STRING(iovec[n++], "["); + IOVEC_SET_STRING(iovec[n++], status); + IOVEC_SET_STRING(iovec[n++], "] "); + } else + IOVEC_SET_STRING(iovec[n++], status_indent); + } + + IOVEC_SET_STRING(iovec[n++], s); + if (!ephemeral) + IOVEC_SET_STRING(iovec[n++], "\n"); + + if (writev(fd, iovec, n) < 0) + return -errno; + + return 0; +} + +int status_printf(const char *status, bool ellipse, bool ephemeral, const char *format, ...) { + va_list ap; + int r; + + assert(format); + + va_start(ap, format); + r = status_vprintf(status, ellipse, ephemeral, format, ap); + va_end(ap); + + return r; +} diff --git a/src/core/show-status.h b/src/core/show-status.h index a2b2153746..c79d4acb66 100644 --- a/src/core/show-status.h +++ b/src/core/show-status.h @@ -21,6 +21,10 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include <stdbool.h> + +#include "macro.h" + /* Manager status */ typedef enum ShowStatus { @@ -32,3 +36,6 @@ typedef enum ShowStatus { } ShowStatus; int parse_show_status(const char *v, ShowStatus *ret); + +int status_vprintf(const char *status, bool ellipse, bool ephemeral, const char *format, va_list ap) _printf_(4,0); +int status_printf(const char *status, bool ellipse, bool ephemeral, const char *format, ...) _printf_(4,5); diff --git a/src/core/shutdown.c b/src/core/shutdown.c index 33383a4b0b..3a95b5fd72 100644 --- a/src/core/shutdown.c +++ b/src/core/shutdown.c @@ -31,12 +31,14 @@ #include <sys/stat.h> #include <unistd.h> +#include "alloc-util.h" #include "cgroup-util.h" #include "def.h" #include "fileio.h" #include "killall.h" #include "log.h" #include "missing.h" +#include "parse-util.h" #include "process-util.h" #include "string-util.h" #include "switch-root.h" diff --git a/src/core/slice.c b/src/core/slice.c index 8fb6d28a3c..4602144150 100644 --- a/src/core/slice.c +++ b/src/core/slice.c @@ -21,6 +21,7 @@ #include <errno.h> +#include "alloc-util.h" #include "dbus-slice.h" #include "log.h" #include "special.h" diff --git a/src/core/smack-setup.c b/src/core/smack-setup.c index 34df392184..0661ff9ecd 100644 --- a/src/core/smack-setup.c +++ b/src/core/smack-setup.c @@ -28,6 +28,8 @@ #include <stdlib.h> #include <string.h> +#include "alloc-util.h" +#include "dirent-util.h" #include "fd-util.h" #include "fileio.h" #include "log.h" diff --git a/src/core/snapshot.c b/src/core/snapshot.c index 15726c344e..ba3135f401 100644 --- a/src/core/snapshot.c +++ b/src/core/snapshot.c @@ -21,12 +21,15 @@ #include <errno.h> +#include "alloc-util.h" #include "bus-common-errors.h" #include "dbus-snapshot.h" +#include "parse-util.h" +#include "parse-util.h" +#include "snapshot.h" #include "string-util.h" #include "unit-name.h" #include "unit.h" -#include "snapshot.h" static const UnitActiveState state_translation_table[_SNAPSHOT_STATE_MAX] = { [SNAPSHOT_DEAD] = UNIT_INACTIVE, diff --git a/src/core/snapshot.h b/src/core/snapshot.h index 97747e18bd..bd52dea408 100644 --- a/src/core/snapshot.h +++ b/src/core/snapshot.h @@ -23,6 +23,8 @@ typedef struct Snapshot Snapshot; +#include "unit.h" + struct Snapshot { Unit meta; diff --git a/src/core/socket.c b/src/core/socket.c index 7f401025ed..3c7f972fbc 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -31,6 +31,7 @@ #include "sd-event.h" +#include "alloc-util.h" #include "bus-error.h" #include "bus-util.h" #include "copy.h" @@ -43,12 +44,15 @@ #include "log.h" #include "missing.h" #include "mkdir.h" +#include "parse-util.h" #include "path-util.h" +#include "process-util.h" #include "selinux-util.h" #include "signal-util.h" #include "smack-util.h" #include "socket.h" #include "special.h" +#include "string-table.h" #include "string-util.h" #include "strv.h" #include "unit-name.h" @@ -1168,9 +1172,9 @@ static int usbffs_dispatch_eps(SocketPort *p) { _cleanup_free_ char *path = NULL; int r, i, n, k; - r = path_get_parent(p->path, &path); - if (r < 0) - return r; + path = dirname_malloc(p->path); + if (!path) + return -ENOMEM; r = scandir(path, &ent, usbffs_select_ep, alphasort); if (r < 0) @@ -1451,7 +1455,9 @@ static int socket_coldplug(Unit *u) { if (s->deserialized_state == s->state) return 0; - if (IN_SET(s->deserialized_state, + if (s->control_pid > 0 && + pid_is_unwaited(s->control_pid) && + IN_SET(s->deserialized_state, SOCKET_START_PRE, SOCKET_START_CHOWN, SOCKET_START_POST, @@ -1462,9 +1468,6 @@ static int socket_coldplug(Unit *u) { SOCKET_FINAL_SIGTERM, SOCKET_FINAL_SIGKILL)) { - if (s->control_pid <= 0) - return -EBADMSG; - r = unit_watch_pid(UNIT(s), s->control_pid); if (r < 0) return r; diff --git a/src/core/swap.c b/src/core/swap.c index d864c7b304..f626ea4d87 100644 --- a/src/core/swap.c +++ b/src/core/swap.c @@ -26,14 +26,18 @@ #include "libudev.h" +#include "alloc-util.h" #include "dbus-swap.h" #include "escape.h" #include "exit-status.h" #include "fd-util.h" #include "formats-util.h" #include "fstab-util.h" +#include "parse-util.h" #include "path-util.h" +#include "process-util.h" #include "special.h" +#include "string-table.h" #include "string-util.h" #include "swap.h" #include "udev-util.h" @@ -524,16 +528,16 @@ static int swap_coldplug(Unit *u) { if (new_state == s->state) return 0; - if (new_state == SWAP_ACTIVATING || - new_state == SWAP_ACTIVATING_SIGTERM || - new_state == SWAP_ACTIVATING_SIGKILL || - new_state == SWAP_ACTIVATING_DONE || - new_state == SWAP_DEACTIVATING || - new_state == SWAP_DEACTIVATING_SIGTERM || - new_state == SWAP_DEACTIVATING_SIGKILL) { - - if (s->control_pid <= 0) - return -EBADMSG; + if (s->control_pid > 0 && + pid_is_unwaited(s->control_pid) && + IN_SET(new_state, + SWAP_ACTIVATING, + SWAP_ACTIVATING_SIGTERM, + SWAP_ACTIVATING_SIGKILL, + SWAP_ACTIVATING_DONE, + SWAP_DEACTIVATING, + SWAP_DEACTIVATING_SIGTERM, + SWAP_DEACTIVATING_SIGKILL)) { r = unit_watch_pid(UNIT(s), s->control_pid); if (r < 0) diff --git a/src/core/timer.c b/src/core/timer.c index 908d45ac73..cc2afedabf 100644 --- a/src/core/timer.c +++ b/src/core/timer.c @@ -21,10 +21,14 @@ #include <errno.h> +#include "alloc-util.h" #include "bus-error.h" #include "bus-util.h" #include "dbus-timer.h" +#include "fs-util.h" +#include "parse-util.h" #include "special.h" +#include "string-table.h" #include "string-util.h" #include "timer.h" #include "unit-name.h" diff --git a/src/core/transaction.c b/src/core/transaction.c index d1c1b9a3cd..69f28c902f 100644 --- a/src/core/transaction.c +++ b/src/core/transaction.c @@ -22,10 +22,11 @@ #include <unistd.h> #include <fcntl.h> +#include "alloc-util.h" #include "bus-common-errors.h" #include "bus-error.h" -#include "transaction.h" #include "terminal-util.h" +#include "transaction.h" static void transaction_unlink_job(Transaction *tr, Job *j, bool delete_dependencies); diff --git a/src/core/umount.c b/src/core/umount.c index 8735bed7b1..9d1f7660db 100644 --- a/src/core/umount.c +++ b/src/core/umount.c @@ -29,6 +29,7 @@ #include "libudev.h" +#include "alloc-util.h" #include "escape.h" #include "fd-util.h" #include "fstab-util.h" diff --git a/src/core/unit-printf.c b/src/core/unit-printf.c index 4a5c7efdb0..721c8ccce9 100644 --- a/src/core/unit-printf.c +++ b/src/core/unit-printf.c @@ -19,6 +19,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "cgroup-util.h" #include "formats-util.h" #include "macro.h" diff --git a/src/core/unit.c b/src/core/unit.c index 572b1c1b78..6c130d4cd1 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -28,6 +28,7 @@ #include "sd-id128.h" #include "sd-messages.h" +#include "alloc-util.h" #include "bus-common-errors.h" #include "bus-util.h" #include "cgroup-util.h" @@ -44,10 +45,12 @@ #include "macro.h" #include "missing.h" #include "mkdir.h" +#include "parse-util.h" #include "path-util.h" #include "process-util.h" #include "set.h" #include "special.h" +#include "stat-util.h" #include "string-util.h" #include "strv.h" #include "unit-name.h" @@ -416,12 +419,11 @@ static void unit_remove_transient(Unit *u) { STRV_FOREACH(i, u->dropin_paths) { _cleanup_free_ char *p = NULL; - int r; (void) unlink(*i); - r = path_get_parent(*i, &p); - if (r >= 0) + p = dirname_malloc(*i); + if (p) (void) rmdir(p); } } @@ -2326,7 +2328,7 @@ int unit_add_two_dependencies_by_name(Unit *u, UnitDependency d, UnitDependency int set_unit_path(const char *p) { /* This is mostly for debug purposes */ - if (setenv("SYSTEMD_UNIT_PATH", p, 0) < 0) + if (setenv("SYSTEMD_UNIT_PATH", p, 1) < 0) return -errno; return 0; @@ -2509,7 +2511,7 @@ int unit_watch_bus_name(Unit *u, const char *name) { * Otherwise, just put the name in the list. bus_setup_api() will take care later. */ r = unit_install_bus_match(u, u->manager->api_bus, name); if (r < 0) - return log_warning_errno(r, "Failed to subscribe to NameOwnerChanged signal: %m"); + return log_warning_errno(r, "Failed to subscribe to NameOwnerChanged signal for '%s': %m", name); } r = hashmap_put(u->manager->watch_bus, name, u); diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c index 78adcf18d6..ae53bac600 100644 --- a/src/cryptsetup/cryptsetup-generator.c +++ b/src/cryptsetup/cryptsetup-generator.c @@ -21,14 +21,18 @@ #include <errno.h> +#include "alloc-util.h" #include "dropin.h" #include "fd-util.h" +#include "fileio.h" #include "fstab-util.h" #include "generator.h" #include "hashmap.h" #include "log.h" #include "mkdir.h" +#include "parse-util.h" #include "path-util.h" +#include "proc-cmdline.h" #include "string-util.h" #include "strv.h" #include "unit-name.h" diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c index f5fb6a09fe..98fe52a81b 100644 --- a/src/cryptsetup/cryptsetup.c +++ b/src/cryptsetup/cryptsetup.c @@ -27,11 +27,14 @@ #include "sd-device.h" +#include "alloc-util.h" #include "ask-password-api.h" #include "device-util.h" #include "escape.h" #include "fileio.h" #include "log.h" +#include "mount-util.h" +#include "parse-util.h" #include "path-util.h" #include "string-util.h" #include "strv.h" diff --git a/src/dbus1-generator/dbus1-generator.c b/src/dbus1-generator/dbus1-generator.c index 8dd75f3324..b57bf9a57d 100644 --- a/src/dbus1-generator/dbus1-generator.c +++ b/src/dbus1-generator/dbus1-generator.c @@ -19,11 +19,14 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "bus-internal.h" #include "bus-util.h" #include "cgroup-util.h" #include "conf-parser.h" +#include "dirent-util.h" #include "fd-util.h" +#include "fileio.h" #include "mkdir.h" #include "special.h" #include "unit-name.h" diff --git a/src/debug-generator/debug-generator.c b/src/debug-generator/debug-generator.c index 7f26108e9c..e16c3b9453 100644 --- a/src/debug-generator/debug-generator.c +++ b/src/debug-generator/debug-generator.c @@ -19,11 +19,14 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include "util.h" -#include "strv.h" -#include "unit-name.h" +#include "alloc-util.h" #include "mkdir.h" +#include "parse-util.h" +#include "proc-cmdline.h" #include "string-util.h" +#include "strv.h" +#include "unit-name.h" +#include "util.h" static const char *arg_dest = "/tmp"; static char **arg_mask = NULL; diff --git a/src/delta/delta.c b/src/delta/delta.c index 5dbd526b9b..6c25b185ed 100644 --- a/src/delta/delta.c +++ b/src/delta/delta.c @@ -26,13 +26,19 @@ #include <sys/prctl.h> #include <unistd.h> +#include "alloc-util.h" +#include "dirent-util.h" #include "fd-util.h" +#include "fs-util.h" #include "hashmap.h" +#include "locale-util.h" #include "log.h" #include "pager.h" +#include "parse-util.h" #include "path-util.h" #include "process-util.h" #include "signal-util.h" +#include "stat-util.h" #include "string-util.h" #include "strv.h" #include "terminal-util.h" diff --git a/src/detect-virt/detect-virt.c b/src/detect-virt/detect-virt.c index dcf4e9749e..0a256c29be 100644 --- a/src/detect-virt/detect-virt.c +++ b/src/detect-virt/detect-virt.c @@ -31,7 +31,8 @@ static bool arg_quiet = false; static enum { ANY_VIRTUALIZATION, ONLY_VM, - ONLY_CONTAINER + ONLY_CONTAINER, + ONLY_CHROOT, } arg_mode = ANY_VIRTUALIZATION; static void help(void) { @@ -41,6 +42,7 @@ static void help(void) { " --version Show package version\n" " -c --container Only detect whether we are run in a container\n" " -v --vm Only detect whether we are run in a VM\n" + " -r --chroot Detect whether we are run in a chroot() environment\n" " -q --quiet Don't output anything, just set return value\n" , program_invocation_short_name); } @@ -55,7 +57,8 @@ static int parse_argv(int argc, char *argv[]) { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "container", no_argument, NULL, 'c' }, - { "vm", optional_argument, NULL, 'v' }, + { "vm", no_argument, NULL, 'v' }, + { "chroot", no_argument, NULL, 'r' }, { "quiet", no_argument, NULL, 'q' }, {} }; @@ -65,7 +68,7 @@ static int parse_argv(int argc, char *argv[]) { assert(argc >= 0); assert(argv); - while ((c = getopt_long(argc, argv, "hqcv", options, NULL)) >= 0) + while ((c = getopt_long(argc, argv, "hqcvr", options, NULL)) >= 0) switch (c) { @@ -88,6 +91,10 @@ static int parse_argv(int argc, char *argv[]) { arg_mode = ONLY_VM; break; + case 'r': + arg_mode = ONLY_CHROOT; + break; + case '?': return -EINVAL; @@ -137,6 +144,15 @@ int main(int argc, char *argv[]) { break; + case ONLY_CHROOT: + r = running_in_chroot(); + if (r < 0) { + log_error_errno(r, "Failed to check for chroot() environment: %m"); + return EXIT_FAILURE; + } + + return r ? EXIT_SUCCESS : EXIT_FAILURE; + case ANY_VIRTUALIZATION: default: r = detect_virtualization(); diff --git a/src/escape/escape.c b/src/escape/escape.c index 9390558554..e857affbc4 100644 --- a/src/escape/escape.c +++ b/src/escape/escape.c @@ -23,6 +23,7 @@ #include <stdio.h> #include <stdlib.h> +#include "alloc-util.h" #include "log.h" #include "string-util.h" #include "strv.h" diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c index 5aa247b2ae..46cfe9f851 100644 --- a/src/firstboot/firstboot.c +++ b/src/firstboot/firstboot.c @@ -24,19 +24,24 @@ #include <shadow.h> #include <unistd.h> +#include "alloc-util.h" #include "ask-password-api.h" #include "copy.h" +#include "fd-util.h" #include "fileio.h" +#include "fs-util.h" #include "hostname-util.h" #include "locale-util.h" #include "mkdir.h" +#include "parse-util.h" #include "path-util.h" #include "random-util.h" +#include "string-util.h" #include "strv.h" #include "terminal-util.h" #include "time-util.h" -#include "string-util.h" -#include "fd-util.h" +#include "umask-util.h" +#include "user-util.h" static char *arg_root = NULL; static char *arg_locale = NULL; /* $LANG */ @@ -535,7 +540,7 @@ static int process_root_password(void) { mkdir_parents(etc_shadow, 0755); - lock = take_password_lock(arg_root); + lock = take_etc_passwd_lock(arg_root); if (lock < 0) return lock; diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c index 9c49557787..5b806a1e69 100644 --- a/src/fsck/fsck.c +++ b/src/fsck/fsck.c @@ -32,16 +32,21 @@ #include "sd-bus.h" #include "sd-device.h" +#include "alloc-util.h" #include "bus-common-errors.h" #include "bus-error.h" #include "bus-util.h" #include "device-util.h" #include "fd-util.h" +#include "fs-util.h" +#include "parse-util.h" #include "path-util.h" +#include "proc-cmdline.h" #include "process-util.h" #include "signal-util.h" #include "socket-util.h" #include "special.h" +#include "stdio-util.h" #include "util.h" /* exit codes as defined in fsck(8) */ diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c index 0a3917b7ba..f7c8d11ace 100644 --- a/src/fstab-generator/fstab-generator.c +++ b/src/fstab-generator/fstab-generator.c @@ -25,14 +25,20 @@ #include <string.h> #include <unistd.h> +#include "alloc-util.h" #include "fd-util.h" +#include "fileio.h" #include "fstab-util.h" #include "generator.h" #include "log.h" #include "mkdir.h" #include "mount-setup.h" +#include "mount-util.h" +#include "parse-util.h" #include "path-util.h" +#include "proc-cmdline.h" #include "special.h" +#include "stat-util.h" #include "string-util.h" #include "strv.h" #include "unit-name.h" diff --git a/src/getty-generator/getty-generator.c b/src/getty-generator/getty-generator.c index 0997cc5fae..03df7365b5 100644 --- a/src/getty-generator/getty-generator.c +++ b/src/getty-generator/getty-generator.c @@ -24,6 +24,7 @@ #include <string.h> #include <unistd.h> +#include "alloc-util.h" #include "fd-util.h" #include "fileio.h" #include "log.h" diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c index ba97c98d6f..5ea6c86898 100644 --- a/src/gpt-auto-generator/gpt-auto-generator.c +++ b/src/gpt-auto-generator/gpt-auto-generator.c @@ -27,8 +27,10 @@ #include "libudev.h" #include "sd-id128.h" +#include "alloc-util.h" #include "blkid-util.h" #include "btrfs-util.h" +#include "dirent-util.h" #include "efivars.h" #include "fd-util.h" #include "fileio.h" @@ -37,8 +39,12 @@ #include "gpt.h" #include "missing.h" #include "mkdir.h" +#include "mount-util.h" +#include "parse-util.h" #include "path-util.h" +#include "proc-cmdline.h" #include "special.h" +#include "stat-util.h" #include "string-util.h" #include "udev-util.h" #include "unit-name.h" diff --git a/src/hibernate-resume/hibernate-resume-generator.c b/src/hibernate-resume/hibernate-resume-generator.c index dff2ada384..da719f2a30 100644 --- a/src/hibernate-resume/hibernate-resume-generator.c +++ b/src/hibernate-resume/hibernate-resume-generator.c @@ -22,8 +22,11 @@ #include <errno.h> #include <stdio.h> +#include "alloc-util.h" +#include "fstab-util.h" #include "log.h" #include "mkdir.h" +#include "proc-cmdline.h" #include "special.h" #include "string-util.h" #include "unit-name.h" diff --git a/src/hibernate-resume/hibernate-resume.c b/src/hibernate-resume/hibernate-resume.c index 1f3b169905..316a2803d3 100644 --- a/src/hibernate-resume/hibernate-resume.c +++ b/src/hibernate-resume/hibernate-resume.c @@ -23,9 +23,10 @@ #include <errno.h> #include <sys/stat.h> +#include "alloc-util.h" +#include "fileio.h" #include "log.h" #include "util.h" -#include "fileio.h" int main(int argc, char *argv[]) { struct stat st; diff --git a/src/hostname/hostnamectl.c b/src/hostname/hostnamectl.c index 0724fcc16d..bf09fb8fbb 100644 --- a/src/hostname/hostnamectl.c +++ b/src/hostname/hostnamectl.c @@ -28,6 +28,7 @@ #include "sd-bus.h" #include "sd-id128.h" +#include "alloc-util.h" #include "architecture.h" #include "bus-error.h" #include "bus-util.h" diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c index dd508aefb5..92061532b8 100644 --- a/src/hostname/hostnamed.c +++ b/src/hostname/hostnamed.c @@ -24,16 +24,20 @@ #include <unistd.h> #include <sys/utsname.h> -#include "util.h" -#include "strv.h" +#include "alloc-util.h" +#include "bus-util.h" #include "def.h" -#include "virt.h" #include "env-util.h" -#include "fileio-label.h" -#include "bus-util.h" #include "event-util.h" -#include "selinux-util.h" +#include "fileio-label.h" #include "hostname-util.h" +#include "parse-util.h" +#include "path-util.h" +#include "selinux-util.h" +#include "strv.h" +#include "user-util.h" +#include "util.h" +#include "virt.h" #define VALID_DEPLOYMENT_CHARS (DIGITS LETTERS "-.:") diff --git a/src/hwdb/hwdb.c b/src/hwdb/hwdb.c index 3b800e99d3..de59b797a6 100644 --- a/src/hwdb/hwdb.c +++ b/src/hwdb/hwdb.c @@ -22,7 +22,11 @@ #include <stdlib.h> #include <string.h> +#include "alloc-util.h" #include "conf-files.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" #include "hwdb-internal.h" #include "hwdb-util.h" #include "mkdir.h" @@ -31,7 +35,6 @@ #include "strv.h" #include "util.h" #include "verbs.h" -#include "fd-util.h" /* * Generic udev properties, key/value database based on modalias strings. diff --git a/src/import/curl-util.c b/src/import/curl-util.c index 455fa1e07d..4278466df1 100644 --- a/src/import/curl-util.c +++ b/src/import/curl-util.c @@ -19,6 +19,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "curl-util.h" #include "fd-util.h" #include "string-util.h" diff --git a/src/import/export-raw.c b/src/import/export-raw.c index 24c0ec9309..103d45bf21 100644 --- a/src/import/export-raw.c +++ b/src/import/export-raw.c @@ -25,10 +25,12 @@ #include "sd-daemon.h" +#include "alloc-util.h" #include "btrfs-util.h" #include "copy.h" #include "export-raw.h" #include "fd-util.h" +#include "fileio.h" #include "import-common.h" #include "ratelimit.h" #include "string-util.h" diff --git a/src/import/export-tar.c b/src/import/export-tar.c index aa9b7f1a91..2bbec661e6 100644 --- a/src/import/export-tar.c +++ b/src/import/export-tar.c @@ -21,9 +21,11 @@ #include "sd-daemon.h" +#include "alloc-util.h" #include "btrfs-util.h" #include "export-tar.h" #include "fd-util.h" +#include "fileio.h" #include "import-common.h" #include "process-util.h" #include "ratelimit.h" diff --git a/src/import/export.c b/src/import/export.c index 1ecd1e4e10..2b33d778d3 100644 --- a/src/import/export.c +++ b/src/import/export.c @@ -23,10 +23,12 @@ #include "sd-event.h" +#include "alloc-util.h" #include "event-util.h" #include "export-raw.h" #include "export-tar.h" #include "fd-util.h" +#include "fs-util.h" #include "hostname-util.h" #include "import-util.h" #include "machine-image.h" diff --git a/src/import/import-common.c b/src/import/import-common.c index d96a000f81..a8551ca9e8 100644 --- a/src/import/import-common.c +++ b/src/import/import-common.c @@ -25,7 +25,7 @@ #include <unistd.h> #include "btrfs-util.h" -#include "capability.h" +#include "capability-util.h" #include "fd-util.h" #include "import-common.h" #include "signal-util.h" diff --git a/src/import/import-compress.c b/src/import/import-compress.c index d6b8133036..d4ff178f60 100644 --- a/src/import/import-compress.c +++ b/src/import/import-compress.c @@ -19,8 +19,9 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include "util.h" #include "import-compress.h" +#include "string-table.h" +#include "util.h" void import_compress_free(ImportCompress *c) { assert(c); diff --git a/src/import/import-raw.c b/src/import/import-raw.c index a34f30abfc..2193d1d7f1 100644 --- a/src/import/import-raw.c +++ b/src/import/import-raw.c @@ -24,9 +24,13 @@ #include "sd-daemon.h" #include "sd-event.h" +#include "alloc-util.h" #include "btrfs-util.h" +#include "chattr-util.h" #include "copy.h" #include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" #include "hostname-util.h" #include "import-common.h" #include "import-compress.h" diff --git a/src/import/import-tar.c b/src/import/import-tar.c index 9aade0f430..2ae1d88168 100644 --- a/src/import/import-tar.c +++ b/src/import/import-tar.c @@ -24,9 +24,12 @@ #include "sd-daemon.h" #include "sd-event.h" +#include "alloc-util.h" #include "btrfs-util.h" #include "copy.h" #include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" #include "hostname-util.h" #include "import-common.h" #include "import-compress.h" diff --git a/src/import/import.c b/src/import/import.c index e50ded9219..018b94d4c4 100644 --- a/src/import/import.c +++ b/src/import/import.c @@ -23,8 +23,10 @@ #include "sd-event.h" +#include "alloc-util.h" #include "event-util.h" #include "fd-util.h" +#include "fs-util.h" #include "hostname-util.h" #include "import-raw.h" #include "import-tar.h" diff --git a/src/import/importd.c b/src/import/importd.c index b712cedcc6..4228681cea 100644 --- a/src/import/importd.c +++ b/src/import/importd.c @@ -23,6 +23,7 @@ #include "sd-bus.h" +#include "alloc-util.h" #include "bus-common-errors.h" #include "bus-util.h" #include "def.h" @@ -32,12 +33,17 @@ #include "machine-pool.h" #include "missing.h" #include "mkdir.h" +#include "parse-util.h" #include "path-util.h" #include "process-util.h" #include "signal-util.h" #include "socket-util.h" +#include "string-table.h" #include "strv.h" +#include "syslog-util.h" +#include "user-util.h" #include "util.h" +#include "web-util.h" typedef struct Transfer Transfer; typedef struct Manager Manager; diff --git a/src/import/pull-common.c b/src/import/pull-common.c index f465154b1d..d6567ba7ee 100644 --- a/src/import/pull-common.c +++ b/src/import/pull-common.c @@ -21,12 +21,15 @@ #include <sys/prctl.h> +#include "alloc-util.h" #include "btrfs-util.h" -#include "capability.h" +#include "capability-util.h" #include "copy.h" +#include "dirent-util.h" #include "escape.h" #include "fd-util.h" #include "io-util.h" +#include "path-util.h" #include "process-util.h" #include "pull-common.h" #include "pull-job.h" @@ -36,6 +39,7 @@ #include "string-util.h" #include "strv.h" #include "util.h" +#include "web-util.h" #define FILENAME_ESCAPE "/.#\"\'" #define HASH_URL_THRESHOLD_LENGTH (_POSIX_PATH_MAX - 16) diff --git a/src/import/pull-dkr.c b/src/import/pull-dkr.c index 1cd9e7b0bd..831470ff13 100644 --- a/src/import/pull-dkr.c +++ b/src/import/pull-dkr.c @@ -24,10 +24,13 @@ #include "sd-daemon.h" +#include "alloc-util.h" #include "aufs-util.h" #include "btrfs-util.h" #include "curl-util.h" #include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" #include "hostname-util.h" #include "import-common.h" #include "import-util.h" @@ -42,6 +45,7 @@ #include "string-util.h" #include "strv.h" #include "utf8.h" +#include "web-util.h" typedef enum DkrProgress { DKR_SEARCHING, @@ -479,13 +483,13 @@ static int dkr_pull_make_local_copy(DkrPull *i, DkrPullVersion version) { if (!i->final_path) { i->final_path = strjoin(i->image_root, "/.dkr-", i->id, NULL); if (!i->final_path) - return log_oom(); + return -ENOMEM; } if (version == DKR_PULL_V2) { - r = path_get_parent(i->image_root, &p); - if (r < 0) - return r; + p = dirname_malloc(i->image_root); + if (!p) + return -ENOMEM; } r = pull_make_local_copy(i->final_path, p ?: i->image_root, i->local, i->force_local); diff --git a/src/import/pull-job.c b/src/import/pull-job.c index 4736306de2..824fa246ec 100644 --- a/src/import/pull-job.c +++ b/src/import/pull-job.c @@ -21,12 +21,16 @@ #include <sys/xattr.h> +#include "alloc-util.h" #include "fd-util.h" +#include "hexdecoct.h" #include "io-util.h" #include "machine-pool.h" +#include "parse-util.h" #include "pull-job.h" #include "string-util.h" #include "strv.h" +#include "xattr-util.h" PullJob* pull_job_unref(PullJob *j) { if (!j) diff --git a/src/import/pull-raw.c b/src/import/pull-raw.c index 848a4fcd44..394131680d 100644 --- a/src/import/pull-raw.c +++ b/src/import/pull-raw.c @@ -25,10 +25,14 @@ #include "sd-daemon.h" +#include "alloc-util.h" #include "btrfs-util.h" +#include "chattr-util.h" #include "copy.h" #include "curl-util.h" #include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" #include "hostname-util.h" #include "import-common.h" #include "import-util.h" @@ -44,6 +48,7 @@ #include "strv.h" #include "utf8.h" #include "util.h" +#include "web-util.h" typedef enum RawProgress { RAW_DOWNLOADING, diff --git a/src/import/pull-tar.c b/src/import/pull-tar.c index 3540bbff41..26c0bc5866 100644 --- a/src/import/pull-tar.c +++ b/src/import/pull-tar.c @@ -24,10 +24,13 @@ #include "sd-daemon.h" +#include "alloc-util.h" #include "btrfs-util.h" #include "copy.h" #include "curl-util.h" #include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" #include "hostname-util.h" #include "import-common.h" #include "import-util.h" @@ -43,6 +46,7 @@ #include "strv.h" #include "utf8.h" #include "util.h" +#include "web-util.h" typedef enum TarProgress { TAR_DOWNLOADING, diff --git a/src/import/pull.c b/src/import/pull.c index 73d5f391c2..39f5b2d8e4 100644 --- a/src/import/pull.c +++ b/src/import/pull.c @@ -23,16 +23,19 @@ #include "sd-event.h" +#include "alloc-util.h" #include "event-util.h" #include "hostname-util.h" #include "import-util.h" #include "machine-image.h" +#include "parse-util.h" #include "pull-dkr.h" #include "pull-raw.h" #include "pull-tar.h" #include "signal-util.h" #include "string-util.h" #include "verbs.h" +#include "web-util.h" static bool arg_force = false; static const char *arg_image_root = "/var/lib/machines"; diff --git a/src/import/qcow2-util.c b/src/import/qcow2-util.c index fd3cf1b0e3..47dabaa86e 100644 --- a/src/import/qcow2-util.c +++ b/src/import/qcow2-util.c @@ -21,10 +21,11 @@ #include <zlib.h> -#include "util.h" -#include "sparse-endian.h" -#include "qcow2-util.h" +#include "alloc-util.h" #include "btrfs-util.h" +#include "qcow2-util.h" +#include "sparse-endian.h" +#include "util.h" #define QCOW2_MAGIC 0x514649fb diff --git a/src/initctl/initctl.c b/src/initctl/initctl.c index 2b374c0288..f1cf31a4a8 100644 --- a/src/initctl/initctl.c +++ b/src/initctl/initctl.c @@ -28,6 +28,7 @@ #include "sd-bus.h" #include "sd-daemon.h" +#include "alloc-util.h" #include "bus-error.h" #include "bus-util.h" #include "def.h" diff --git a/src/journal-remote/journal-gatewayd.c b/src/journal-remote/journal-gatewayd.c index 92ef723aff..6b93a758f6 100644 --- a/src/journal-remote/journal-gatewayd.c +++ b/src/journal-remote/journal-gatewayd.c @@ -33,6 +33,7 @@ #include "sd-daemon.h" #include "sd-journal.h" +#include "alloc-util.h" #include "bus-util.h" #include "fd-util.h" #include "fileio.h" @@ -40,6 +41,7 @@ #include "log.h" #include "logs-show.h" #include "microhttpd-util.h" +#include "parse-util.h" #include "sigbus.h" #include "util.h" diff --git a/src/journal-remote/journal-remote-parse.c b/src/journal-remote/journal-remote-parse.c index bb299e378c..3ff40228a0 100644 --- a/src/journal-remote/journal-remote-parse.c +++ b/src/journal-remote/journal-remote-parse.c @@ -19,9 +19,11 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "fd-util.h" #include "journal-remote-parse.h" #include "journald-native.h" +#include "parse-util.h" #include "string-util.h" #define LINE_CHUNK 8*1024u diff --git a/src/journal-remote/journal-remote-write.c b/src/journal-remote/journal-remote-write.c index 40f4ff8e58..d8250378b0 100644 --- a/src/journal-remote/journal-remote-write.c +++ b/src/journal-remote/journal-remote-write.c @@ -19,6 +19,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "journal-remote.h" int iovw_put(struct iovec_wrapper *iovw, void* data, size_t len) { diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c index de207f8d24..dc69bb8679 100644 --- a/src/journal-remote/journal-remote.c +++ b/src/journal-remote/journal-remote.c @@ -35,6 +35,7 @@ #include "sd-daemon.h" +#include "alloc-util.h" #include "conf-parser.h" #include "escape.h" #include "fd-util.h" @@ -44,8 +45,12 @@ #include "journal-remote.h" #include "journald-native.h" #include "macro.h" +#include "parse-util.h" #include "signal-util.h" #include "socket-util.h" +#include "stat-util.h" +#include "stdio-util.h" +#include "string-table.h" #include "string-util.h" #include "strv.h" @@ -643,11 +648,12 @@ static int setup_microhttpd_server(RemoteServer *s, { MHD_OPTION_NOTIFY_COMPLETED, (intptr_t) request_meta_free}, { MHD_OPTION_EXTERNAL_LOGGER, (intptr_t) microhttpd_logger}, { MHD_OPTION_LISTEN_SOCKET, fd}, + { MHD_OPTION_CONNECTION_MEMORY_LIMIT, DATA_SIZE_MAX}, { MHD_OPTION_END}, { MHD_OPTION_END}, { MHD_OPTION_END}, { MHD_OPTION_END}}; - int opts_pos = 3; + int opts_pos = 4; int flags = MHD_USE_DEBUG | MHD_USE_DUAL_STACK | @@ -1410,18 +1416,21 @@ static int parse_argv(int argc, char *argv[]) { case ARG_GNUTLS_LOG: { #ifdef HAVE_GNUTLS - const char *word, *state; - size_t size; + const char* p = optarg; + for (;;) { + _cleanup_free_ char *word = NULL; - FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) { - char *cat; + r = extract_first_word(&p, &word, ",", 0); + if (r < 0) + return log_error_errno(r, "Failed to parse --gnutls-log= argument: %m"); - cat = strndup(word, size); - if (!cat) - return log_oom(); + if (r == 0) + break; - if (strv_consume(&arg_gnutls_log, cat) < 0) + if (strv_push(&arg_gnutls_log, word) < 0) return log_oom(); + + word = NULL; } break; #else diff --git a/src/journal-remote/journal-upload-journal.c b/src/journal-remote/journal-upload-journal.c index 6b3ad924a7..3ee6d32bf7 100644 --- a/src/journal-remote/journal-upload-journal.c +++ b/src/journal-remote/journal-upload-journal.c @@ -1,11 +1,33 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2014 Zbigniew Jędrzejewski-Szmek + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + #include <stdbool.h> #include <curl/curl.h> -#include "util.h" +#include "alloc-util.h" +#include "journal-upload.h" #include "log.h" #include "utf8.h" -#include "journal-upload.h" +#include "util.h" /** * Write up to size bytes to buf. Return negative on error, and number of diff --git a/src/journal-remote/journal-upload.c b/src/journal-remote/journal-upload.c index a945a9971a..7d274d2fc9 100644 --- a/src/journal-remote/journal-upload.c +++ b/src/journal-remote/journal-upload.c @@ -27,13 +27,16 @@ #include "sd-daemon.h" +#include "alloc-util.h" #include "conf-parser.h" #include "fd-util.h" #include "fileio.h" #include "formats-util.h" +#include "glob-util.h" #include "journal-upload.h" #include "log.h" #include "mkdir.h" +#include "parse-util.h" #include "sigbus.h" #include "signal-util.h" #include "string-util.h" diff --git a/src/journal-remote/microhttpd-util.c b/src/journal-remote/microhttpd-util.c index df068a089c..b2c398a845 100644 --- a/src/journal-remote/microhttpd-util.c +++ b/src/journal-remote/microhttpd-util.c @@ -29,6 +29,7 @@ #include <gnutls/x509.h> #endif +#include "alloc-util.h" #include "log.h" #include "macro.h" #include "string-util.h" diff --git a/src/journal/cat.c b/src/journal/cat.c index ff1887604a..7fd4198df8 100644 --- a/src/journal/cat.c +++ b/src/journal/cat.c @@ -29,7 +29,9 @@ #include "sd-journal.h" #include "fd-util.h" +#include "parse-util.h" #include "string-util.h" +#include "syslog-util.h" #include "util.h" static char *arg_identifier = NULL; diff --git a/src/journal/catalog.c b/src/journal/catalog.c index d5bc17b4b6..95a6857472 100644 --- a/src/journal/catalog.c +++ b/src/journal/catalog.c @@ -29,12 +29,15 @@ #include "sd-id128.h" +#include "alloc-util.h" #include "catalog.h" #include "conf-files.h" #include "fd-util.h" +#include "fileio.h" #include "hashmap.h" #include "log.h" #include "mkdir.h" +#include "path-util.h" #include "siphash24.h" #include "sparse-endian.h" #include "strbuf.h" diff --git a/src/journal/compress.c b/src/journal/compress.c index 9308e8b789..e1ca0a8818 100644 --- a/src/journal/compress.c +++ b/src/journal/compress.c @@ -33,12 +33,14 @@ #include <lz4frame.h> #endif +#include "alloc-util.h" #include "compress.h" #include "fd-util.h" #include "io-util.h" #include "journal-def.h" #include "macro.h" #include "sparse-endian.h" +#include "string-table.h" #include "string-util.h" #include "util.h" diff --git a/src/journal/coredump-vacuum.c b/src/journal/coredump-vacuum.c index bad6ea4242..39bc2e4270 100644 --- a/src/journal/coredump-vacuum.c +++ b/src/journal/coredump-vacuum.c @@ -21,7 +21,9 @@ #include <sys/statvfs.h> +#include "alloc-util.h" #include "coredump-vacuum.h" +#include "dirent-util.h" #include "fd-util.h" #include "hashmap.h" #include "macro.h" diff --git a/src/journal/coredump.c b/src/journal/coredump.c index 7336db219b..2e543537f6 100644 --- a/src/journal/coredump.c +++ b/src/journal/coredump.c @@ -34,22 +34,28 @@ #include "sd-login.h" #include "acl-util.h" -#include "capability.h" +#include "alloc-util.h" +#include "capability-util.h" #include "cgroup-util.h" #include "compress.h" #include "conf-parser.h" #include "copy.h" #include "coredump-vacuum.h" +#include "dirent-util.h" #include "escape.h" #include "fd-util.h" #include "fileio.h" +#include "fs-util.h" +#include "io-util.h" #include "journald-native.h" #include "log.h" #include "macro.h" #include "mkdir.h" +#include "parse-util.h" #include "process-util.h" #include "special.h" #include "stacktrace.h" +#include "string-table.h" #include "string-util.h" #include "strv.h" #include "user-util.h" diff --git a/src/journal/coredumpctl.c b/src/journal/coredumpctl.c index f891ddffc6..af4d051138 100644 --- a/src/journal/coredumpctl.c +++ b/src/journal/coredumpctl.c @@ -28,12 +28,15 @@ #include "sd-journal.h" +#include "alloc-util.h" #include "compress.h" #include "fd-util.h" +#include "fileio.h" #include "journal-internal.h" #include "log.h" #include "macro.h" #include "pager.h" +#include "parse-util.h" #include "path-util.h" #include "process-util.h" #include "set.h" @@ -41,8 +44,8 @@ #include "signal-util.h" #include "string-util.h" #include "terminal-util.h" -#include "util.h" #include "user-util.h" +#include "util.h" static enum { ACTION_NONE, diff --git a/src/journal/fsprg.h b/src/journal/fsprg.h index 150d034828..5959b1fed2 100644 --- a/src/journal/fsprg.h +++ b/src/journal/fsprg.h @@ -29,6 +29,7 @@ #include <inttypes.h> #include "macro.h" +#include "util.h" #ifdef __cplusplus extern "C" { diff --git a/src/journal/journal-authenticate.c b/src/journal/journal-authenticate.c index dc51a5ab2f..0c4ac5cdc3 100644 --- a/src/journal/journal-authenticate.c +++ b/src/journal/journal-authenticate.c @@ -27,6 +27,7 @@ #include "journal-authenticate.h" #include "journal-def.h" #include "journal-file.h" +#include "hexdecoct.h" static uint64_t journal_file_tag_seqnum(JournalFile *f) { uint64_t r; diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index f193cb90ce..12b39dbb27 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -28,15 +28,19 @@ #include <sys/uio.h> #include <unistd.h> +#include "alloc-util.h" #include "btrfs-util.h" +#include "chattr-util.h" #include "compress.h" #include "fd-util.h" #include "journal-authenticate.h" #include "journal-def.h" #include "journal-file.h" #include "lookup3.h" +#include "parse-util.h" #include "random-util.h" #include "string-util.h" +#include "xattr-util.h" #define DEFAULT_DATA_HASH_TABLE_SIZE (2047ULL*sizeof(HashItem)) #define DEFAULT_FIELD_HASH_TABLE_SIZE (333ULL*sizeof(HashItem)) diff --git a/src/journal/journal-send.c b/src/journal/journal-send.c index f388c30d2e..fa5dee73c3 100644 --- a/src/journal/journal-send.c +++ b/src/journal/journal-send.c @@ -31,10 +31,13 @@ #include "sd-journal.h" +#include "alloc-util.h" #include "fd-util.h" +#include "fileio.h" #include "io-util.h" #include "memfd-util.h" #include "socket-util.h" +#include "stdio-util.h" #include "string-util.h" #include "util.h" diff --git a/src/journal/journal-vacuum.c b/src/journal/journal-vacuum.c index dca5bf5000..4b5fc76eb1 100644 --- a/src/journal/journal-vacuum.c +++ b/src/journal/journal-vacuum.c @@ -25,12 +25,16 @@ #include "sd-id128.h" +#include "alloc-util.h" +#include "dirent-util.h" #include "fd-util.h" #include "journal-def.h" #include "journal-file.h" #include "journal-vacuum.h" +#include "parse-util.h" #include "string-util.h" #include "util.h" +#include "xattr-util.h" struct vacuum_info { uint64_t usage; diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c index de4f73a471..b78ce98b17 100644 --- a/src/journal/journal-verify.c +++ b/src/journal/journal-verify.c @@ -24,8 +24,10 @@ #include <fcntl.h> #include <stddef.h> +#include "alloc-util.h" #include "compress.h" #include "fd-util.h" +#include "fileio.h" #include "journal-authenticate.h" #include "journal-def.h" #include "journal-file.h" diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 6e452a4d51..a35783e3ff 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -39,12 +39,16 @@ #include "sd-journal.h" #include "acl-util.h" +#include "alloc-util.h" #include "bus-error.h" #include "bus-util.h" #include "catalog.h" +#include "chattr-util.h" #include "fd-util.h" #include "fileio.h" +#include "fs-util.h" #include "fsprg.h" +#include "glob-util.h" #include "hostname-util.h" #include "io-util.h" #include "journal-def.h" @@ -52,14 +56,18 @@ #include "journal-qrcode.h" #include "journal-vacuum.h" #include "journal-verify.h" +#include "locale-util.h" #include "log.h" #include "logs-show.h" #include "mkdir.h" #include "pager.h" +#include "parse-util.h" #include "path-util.h" +#include "rlimit-util.h" #include "set.h" #include "sigbus.h" #include "strv.h" +#include "syslog-util.h" #include "terminal-util.h" #include "unit-name.h" #include "user-util.h" diff --git a/src/journal/journald-audit.c b/src/journal/journald-audit.c index 4c102fd530..3c13fe0d67 100644 --- a/src/journal/journald-audit.c +++ b/src/journal/journald-audit.c @@ -19,8 +19,11 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "audit-type.h" #include "fd-util.h" +#include "hexdecoct.h" +#include "io-util.h" #include "journald-audit.h" #include "missing.h" #include "string-util.h" diff --git a/src/journal/journald-console.c b/src/journal/journald-console.c index 5f3eb05275..860832cfc8 100644 --- a/src/journal/journald-console.c +++ b/src/journal/journald-console.c @@ -23,13 +23,17 @@ #include <fcntl.h> #include <sys/socket.h> +#include "alloc-util.h" +#include "fd-util.h" #include "fileio.h" -#include "journald-server.h" -#include "journald-console.h" #include "formats-util.h" +#include "io-util.h" +#include "journald-console.h" +#include "journald-server.h" +#include "parse-util.h" #include "process-util.h" +#include "stdio-util.h" #include "terminal-util.h" -#include "fd-util.h" static bool prefix_timestamp(void) { diff --git a/src/journal/journald-kmsg.c b/src/journal/journald-kmsg.c index 5a05632e56..489f6f689c 100644 --- a/src/journal/journald-kmsg.c +++ b/src/journal/journald-kmsg.c @@ -31,10 +31,13 @@ #include "escape.h" #include "fd-util.h" #include "formats-util.h" +#include "io-util.h" #include "journald-kmsg.h" #include "journald-server.h" #include "journald-syslog.h" +#include "parse-util.h" #include "process-util.h" +#include "stdio-util.h" #include "string-util.h" void server_forward_kmsg( diff --git a/src/journal/journald-native.c b/src/journal/journald-native.c index 7d4aac687e..6fff4fe473 100644 --- a/src/journal/journald-native.c +++ b/src/journal/journald-native.c @@ -24,7 +24,10 @@ #include <sys/mman.h> #include <unistd.h> +#include "alloc-util.h" #include "fd-util.h" +#include "fs-util.h" +#include "io-util.h" #include "journald-console.h" #include "journald-kmsg.h" #include "journald-native.h" @@ -32,6 +35,7 @@ #include "journald-syslog.h" #include "journald-wall.h" #include "memfd-util.h" +#include "parse-util.h" #include "path-util.h" #include "selinux-util.h" #include "socket-util.h" diff --git a/src/journal/journald-rate-limit.c b/src/journal/journald-rate-limit.c index 6e9557c06e..434ddc8ac9 100644 --- a/src/journal/journald-rate-limit.c +++ b/src/journal/journald-rate-limit.c @@ -22,6 +22,7 @@ #include <errno.h> #include <string.h> +#include "alloc-util.h" #include "hashmap.h" #include "list.h" #include "random-util.h" diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 7cefea323e..299b0a848f 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -34,13 +34,18 @@ #include "sd-messages.h" #include "acl-util.h" +#include "alloc-util.h" +#include "audit-util.h" #include "cgroup-util.h" #include "conf-parser.h" +#include "dirent-util.h" #include "extract-word.h" #include "fd-util.h" #include "formats-util.h" +#include "fs-util.h" #include "hashmap.h" #include "hostname-util.h" +#include "io-util.h" #include "journal-authenticate.h" #include "journal-file.h" #include "journal-internal.h" @@ -54,11 +59,14 @@ #include "journald-syslog.h" #include "missing.h" #include "mkdir.h" +#include "parse-util.h" +#include "proc-cmdline.h" #include "process-util.h" #include "rm-rf.h" #include "selinux-util.h" #include "signal-util.h" #include "socket-util.h" +#include "string-table.h" #include "string-util.h" #define USER_JOURNALS_MAX 1024 @@ -70,6 +78,8 @@ #define RECHECK_SPACE_USEC (30*USEC_PER_SEC) +#define NOTIFY_SNDBUF_SIZE (8*1024*1024) + static int determine_space_for( Server *s, JournalMetrics *metrics, @@ -1449,6 +1459,126 @@ static int server_open_hostname(Server *s) { return 0; } +static int dispatch_notify_event(sd_event_source *es, int fd, uint32_t revents, void *userdata) { + Server *s = userdata; + int r; + + assert(s); + assert(s->notify_event_source == es); + assert(s->notify_fd == fd); + + if (revents != EPOLLOUT) { + log_error("Invalid events on notify file descriptor."); + return -EINVAL; + } + + /* The $NOTIFY_SOCKET is writable again, now send exactly one + * message on it. Either it's the initial READY=1 event or an + * stdout stream event. If there's nothing to write anymore, + * turn our event source off. The next time there's something + * to send it will be turned on again. */ + + if (!s->sent_notify_ready) { + static const char p[] = + "READY=1\n" + "STATUS=Processing requests..."; + ssize_t l; + + l = send(s->notify_fd, p, strlen(p), MSG_DONTWAIT); + if (l < 0) { + if (errno == EAGAIN) + return 0; + + return log_error_errno(errno, "Failed to send READY=1 notification message: %m"); + } + + s->sent_notify_ready = true; + log_debug("Sent READY=1 notification."); + + } else if (s->stdout_streams_notify_queue) + /* Dispatch one stream notification event */ + stdout_stream_send_notify(s->stdout_streams_notify_queue); + + /* Leave us enabled if there's still more to to do. */ + if (s->stdout_streams_notify_queue) + return 0; + + /* There was nothing to do anymore, let's turn ourselves off. */ + r = sd_event_source_set_enabled(es, SD_EVENT_OFF); + if (r < 0) + return log_error_errno(r, "Failed to turn off notify event source: %m"); + + return 0; +} + +static int server_connect_notify(Server *s) { + union sockaddr_union sa = { + .un.sun_family = AF_UNIX, + }; + const char *e; + int r; + + assert(s); + assert(s->notify_fd < 0); + assert(!s->notify_event_source); + + /* + So here's the problem: we'd like to send notification + messages to PID 1, but we cannot do that via sd_notify(), + since that's synchronous, and we might end up blocking on + it. Specifically: given that PID 1 might block on + dbus-daemon during IPC, and dbus-daemon is logging to us, + and might hence block on us, we might end up in a deadlock + if we block on sending PID 1 notification messages -- by + generating a full blocking circle. To avoid this, let's + create a non-blocking socket, and connect it to the + notification socket, and then wait for POLLOUT before we + send anything. This should efficiently avoid any deadlocks, + as we'll never block on PID 1, hence PID 1 can safely block + on dbus-daemon which can safely block on us again. + + Don't think that this issue is real? It is, see: + https://github.com/systemd/systemd/issues/1505 + */ + + e = getenv("NOTIFY_SOCKET"); + if (!e) + return 0; + + if ((e[0] != '@' && e[0] != '/') || e[1] == 0) { + log_error("NOTIFY_SOCKET set to an invalid value: %s", e); + return -EINVAL; + } + + if (strlen(e) > sizeof(sa.un.sun_path)) { + log_error("NOTIFY_SOCKET path too long: %s", e); + return -EINVAL; + } + + s->notify_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (s->notify_fd < 0) + return log_error_errno(errno, "Failed to create notify socket: %m"); + + (void) fd_inc_sndbuf(s->notify_fd, NOTIFY_SNDBUF_SIZE); + + strncpy(sa.un.sun_path, e, sizeof(sa.un.sun_path)); + if (sa.un.sun_path[0] == '@') + sa.un.sun_path[0] = 0; + + r = connect(s->notify_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(e)); + if (r < 0) + return log_error_errno(errno, "Failed to connect to notify socket: %m"); + + r = sd_event_add_io(s->event, &s->notify_event_source, s->notify_fd, EPOLLOUT, dispatch_notify_event, s); + if (r < 0) + return log_error_errno(r, "Failed to watch notification socket: %m"); + + /* This should fire pretty soon, which we'll use to send the + * READY=1 event. */ + + return 0; +} + int server_init(Server *s) { _cleanup_fdset_free_ FDSet *fds = NULL; int n, r, fd; @@ -1457,7 +1587,7 @@ int server_init(Server *s) { assert(s); zero(*s); - s->syslog_fd = s->native_fd = s->stdout_fd = s->dev_kmsg_fd = s->audit_fd = s->hostname_fd = -1; + s->syslog_fd = s->native_fd = s->stdout_fd = s->dev_kmsg_fd = s->audit_fd = s->hostname_fd = s->notify_fd = -1; s->compress = true; s->seal = true; @@ -1503,8 +1633,6 @@ int server_init(Server *s) { if (r < 0) return log_error_errno(r, "Failed to create event loop: %m"); - sd_event_set_watchdog(s->event, true); - n = sd_listen_fds(true); if (n < 0) return log_error_errno(n, "Failed to read listening file descriptors from environment: %m"); @@ -1629,6 +1757,8 @@ int server_init(Server *s) { server_cache_boot_id(s); server_cache_machine_id(s); + (void) server_connect_notify(s); + return system_journal_open(s, false); } @@ -1677,6 +1807,7 @@ void server_done(Server *s) { sd_event_source_unref(s->sigterm_event_source); sd_event_source_unref(s->sigint_event_source); sd_event_source_unref(s->hostname_event_source); + sd_event_source_unref(s->notify_event_source); sd_event_unref(s->event); safe_close(s->syslog_fd); @@ -1685,6 +1816,7 @@ void server_done(Server *s) { safe_close(s->dev_kmsg_fd); safe_close(s->audit_fd); safe_close(s->hostname_fd); + safe_close(s->notify_fd); if (s->rate_limit) journal_rate_limit_free(s->rate_limit); diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h index 535c0ab9ab..170602ea16 100644 --- a/src/journal/journald-server.h +++ b/src/journal/journald-server.h @@ -25,10 +25,13 @@ #include <sys/types.h> #include "sd-event.h" -#include "journal-file.h" + +typedef struct Server Server; + #include "hashmap.h" -#include "audit.h" +#include "journal-file.h" #include "journald-rate-limit.h" +#include "journald-stream.h" #include "list.h" typedef enum Storage { @@ -48,15 +51,14 @@ typedef enum SplitMode { _SPLIT_INVALID = -1 } SplitMode; -typedef struct StdoutStream StdoutStream; - -typedef struct Server { +struct Server { int syslog_fd; int native_fd; int stdout_fd; int dev_kmsg_fd; int audit_fd; int hostname_fd; + int notify_fd; sd_event *event; @@ -71,6 +73,7 @@ typedef struct Server { sd_event_source *sigterm_event_source; sd_event_source *sigint_event_source; sd_event_source *hostname_event_source; + sd_event_source *notify_event_source; JournalFile *runtime_journal; JournalFile *system_journal; @@ -111,6 +114,7 @@ typedef struct Server { usec_t oldest_file_usec; LIST_HEAD(StdoutStream, stdout_streams); + LIST_HEAD(StdoutStream, stdout_streams_notify_queue); unsigned n_stdout_streams; char *tty_path; @@ -132,6 +136,7 @@ typedef struct Server { struct udev *udev; + bool sent_notify_ready; bool sync_scheduled; char machine_id_field[sizeof("_MACHINE_ID=") + 32]; @@ -140,7 +145,7 @@ typedef struct Server { /* Cached cgroup root, so that we don't have to query that all the time */ char *cgroup_root; -} Server; +}; #define SERVER_MACHINE_ID(s) ((s)->machine_id_field + strlen("_MACHINE_ID=")) diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c index 0dd511519c..fb6afee171 100644 --- a/src/journal/journald-stream.c +++ b/src/journal/journald-stream.c @@ -29,9 +29,12 @@ #include "sd-daemon.h" #include "sd-event.h" +#include "alloc-util.h" +#include "dirent-util.h" #include "escape.h" #include "fd-util.h" #include "fileio.h" +#include "io-util.h" #include "journald-console.h" #include "journald-kmsg.h" #include "journald-server.h" @@ -39,9 +42,12 @@ #include "journald-syslog.h" #include "journald-wall.h" #include "mkdir.h" +#include "parse-util.h" #include "selinux-util.h" #include "socket-util.h" +#include "stdio-util.h" #include "string-util.h" +#include "syslog-util.h" #define STDOUT_STREAMS_MAX 4096 @@ -73,6 +79,7 @@ struct StdoutStream { bool forward_to_console:1; bool fdstore:1; + bool in_notify_queue:1; char buffer[LINE_MAX+1]; size_t length; @@ -82,6 +89,7 @@ struct StdoutStream { char *state_file; LIST_FIELDS(StdoutStream, stdout_stream); + LIST_FIELDS(StdoutStream, stdout_stream_notify_queue); }; void stdout_stream_free(StdoutStream *s) { @@ -92,6 +100,9 @@ void stdout_stream_free(StdoutStream *s) { assert(s->server->n_stdout_streams > 0); s->server->n_stdout_streams --; LIST_REMOVE(stdout_stream, s->server->stdout_streams, s); + + if (s->in_notify_queue) + LIST_REMOVE(stdout_stream_notify_queue, s->server->stdout_streams_notify_queue, s); } if (s->event_source) { @@ -115,7 +126,7 @@ static void stdout_stream_destroy(StdoutStream *s) { return; if (s->state_file) - unlink(s->state_file); + (void) unlink(s->state_file); stdout_stream_free(s); } @@ -194,11 +205,15 @@ static int stdout_stream_save(StdoutStream *s) { goto fail; } - /* Store the connection fd in PID 1, so that we get it passed - * in again on next start */ - if (!s->fdstore) { - sd_pid_notify_with_fds(0, false, "FDSTORE=1", &s->fd, 1); - s->fdstore = true; + if (!s->fdstore && !s->in_notify_queue) { + LIST_PREPEND(stdout_stream_notify_queue, s->server->stdout_streams_notify_queue, s); + s->in_notify_queue = true; + + if (s->server->notify_event_source) { + r = sd_event_source_set_enabled(s->server->notify_event_source, SD_EVENT_ON); + if (r < 0) + log_warning_errno(r, "Failed to enable notify event source: %m"); + } } return 0; @@ -723,3 +738,50 @@ int server_open_stdout_socket(Server *s) { return 0; } + +void stdout_stream_send_notify(StdoutStream *s) { + struct iovec iovec = { + .iov_base = (char*) "FDSTORE=1", + .iov_len = strlen("FDSTORE=1"), + }; + struct msghdr msghdr = { + .msg_iov = &iovec, + .msg_iovlen = 1, + }; + struct cmsghdr *cmsg; + ssize_t l; + + assert(s); + assert(!s->fdstore); + assert(s->in_notify_queue); + assert(s->server); + assert(s->server->notify_fd >= 0); + + /* Store the connection fd in PID 1, so that we get it passed + * in again on next start */ + + msghdr.msg_controllen = CMSG_SPACE(sizeof(int)); + msghdr.msg_control = alloca0(msghdr.msg_controllen); + + cmsg = CMSG_FIRSTHDR(&msghdr); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(int)); + + memcpy(CMSG_DATA(cmsg), &s->fd, sizeof(int)); + + l = sendmsg(s->server->notify_fd, &msghdr, MSG_DONTWAIT|MSG_NOSIGNAL); + if (l < 0) { + if (errno == EAGAIN) + return; + + log_error_errno(errno, "Failed to send stream file descriptor to service manager: %m"); + } else { + log_debug("Successfully sent stream file descriptor to service manager."); + s->fdstore = 1; + } + + LIST_REMOVE(stdout_stream_notify_queue, s->server->stdout_streams_notify_queue, s); + s->in_notify_queue = false; + +} diff --git a/src/journal/journald-stream.h b/src/journal/journald-stream.h index 257dce45df..e3497f0ded 100644 --- a/src/journal/journald-stream.h +++ b/src/journal/journald-stream.h @@ -21,9 +21,13 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +typedef struct StdoutStream StdoutStream; + #include "fdset.h" #include "journald-server.h" int server_open_stdout_socket(Server *s); int server_restore_streams(Server *s, FDSet *fds); + void stdout_stream_free(StdoutStream *s); +void stdout_stream_send_notify(StdoutStream *s); diff --git a/src/journal/journald-syslog.c b/src/journal/journald-syslog.c index 7e9ba12560..f3ac1a7ae0 100644 --- a/src/journal/journald-syslog.c +++ b/src/journal/journald-syslog.c @@ -25,8 +25,10 @@ #include "sd-messages.h" +#include "alloc-util.h" #include "fd-util.h" #include "formats-util.h" +#include "io-util.h" #include "journald-console.h" #include "journald-kmsg.h" #include "journald-server.h" @@ -35,7 +37,9 @@ #include "process-util.h" #include "selinux-util.h" #include "socket-util.h" +#include "stdio-util.h" #include "string-util.h" +#include "syslog-util.h" /* Warn once every 30s if we missed syslog message */ #define WARN_FORWARD_SYSLOG_MISSED_USEC (30 * USEC_PER_SEC) diff --git a/src/journal/journald-wall.c b/src/journal/journald-wall.c index 5284914941..69540f1141 100644 --- a/src/journal/journald-wall.c +++ b/src/journal/journald-wall.c @@ -19,6 +19,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "formats-util.h" #include "journald-server.h" #include "process-util.h" diff --git a/src/journal/journald.c b/src/journal/journald.c index 83236ceba9..b137e3c7be 100644 --- a/src/journal/journald.c +++ b/src/journal/journald.c @@ -61,10 +61,6 @@ int main(int argc, char *argv[]) { log_debug("systemd-journald running as pid "PID_FMT, getpid()); server_driver_message(&server, SD_MESSAGE_JOURNAL_START, "Journal started"); - sd_notify(false, - "READY=1\n" - "STATUS=Processing requests..."); - for (;;) { usec_t t = USEC_INFINITY, n; @@ -117,10 +113,6 @@ int main(int argc, char *argv[]) { server_driver_message(&server, SD_MESSAGE_JOURNAL_STOP, "Journal stopped"); finish: - sd_notify(false, - "STOPPING=1\n" - "STATUS=Shutting down..."); - server_done(&server); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; diff --git a/src/journal/mmap-cache.c b/src/journal/mmap-cache.c index 22f75540b8..3cb1dfa986 100644 --- a/src/journal/mmap-cache.c +++ b/src/journal/mmap-cache.c @@ -23,6 +23,7 @@ #include <stdlib.h> #include <sys/mman.h> +#include "alloc-util.h" #include "hashmap.h" #include "list.h" #include "log.h" diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index 9dcfc726ea..218df8cebe 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -30,11 +30,14 @@ #include "sd-journal.h" +#include "alloc-util.h" #include "catalog.h" #include "compress.h" +#include "dirent-util.h" #include "fd-util.h" #include "fileio.h" #include "formats-util.h" +#include "fs-util.h" #include "hashmap.h" #include "hostname-util.h" #include "io-util.h" @@ -46,6 +49,8 @@ #include "missing.h" #include "path-util.h" #include "replace-var.h" +#include "stat-util.h" +#include "stdio-util.h" #include "string-util.h" #include "strv.h" @@ -1020,8 +1025,6 @@ _public_ int sd_journal_seek_cursor(sd_journal *j, const char *cursor) { _public_ int sd_journal_test_cursor(sd_journal *j, const char *cursor) { int r; - const char *word, *state; - size_t l; Object *o; assert_return(j, -EINVAL); @@ -1035,20 +1038,23 @@ _public_ int sd_journal_test_cursor(sd_journal *j, const char *cursor) { if (r < 0) return r; - FOREACH_WORD_SEPARATOR(word, l, cursor, ";", state) { + for(;;) { _cleanup_free_ char *item = NULL; - sd_id128_t id; unsigned long long ll; + sd_id128_t id; int k = 0; - if (l < 2 || word[1] != '=') - return -EINVAL; + r = extract_first_word(&cursor, &item, ";", EXTRACT_DONT_COALESCE_SEPARATORS); + if (r < 0) + return r; - item = strndup(word, l); - if (!item) - return -ENOMEM; + if (r == 0) + break; - switch (word[0]) { + if (strlen(item) < 2 || item[1] != '=') + return -EINVAL; + + switch (item[0]) { case 's': k = sd_id128_from_string(item+2, &id); diff --git a/src/journal/stacktrace.c b/src/journal/stacktrace.c index e32550d644..4305462f80 100644 --- a/src/journal/stacktrace.c +++ b/src/journal/stacktrace.c @@ -22,6 +22,7 @@ #include <dwarf.h> #include <elfutils/libdwfl.h> +#include "alloc-util.h" #include "fd-util.h" #include "formats-util.h" #include "macro.h" diff --git a/src/journal/test-catalog.c b/src/journal/test-catalog.c index 72c1f60f02..aea8fd15e6 100644 --- a/src/journal/test-catalog.c +++ b/src/journal/test-catalog.c @@ -27,8 +27,10 @@ #include "sd-messages.h" +#include "alloc-util.h" #include "catalog.h" #include "fd-util.h" +#include "fileio.h" #include "log.h" #include "macro.h" #include "string-util.h" diff --git a/src/journal/test-compress-benchmark.c b/src/journal/test-compress-benchmark.c index 0a9ab7f52c..93ea9c6318 100644 --- a/src/journal/test-compress-benchmark.c +++ b/src/journal/test-compress-benchmark.c @@ -19,8 +19,10 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "compress.h" #include "macro.h" +#include "parse-util.h" #include "random-util.h" #include "string-util.h" #include "util.h" diff --git a/src/journal/test-compress.c b/src/journal/test-compress.c index e562fa1948..b9d90a8988 100644 --- a/src/journal/test-compress.c +++ b/src/journal/test-compress.c @@ -17,8 +17,10 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "compress.h" #include "fd-util.h" +#include "fileio.h" #include "macro.h" #include "random-util.h" #include "util.h" diff --git a/src/journal/test-journal-flush.c b/src/journal/test-journal-flush.c index 6061623ae7..03d1522e23 100644 --- a/src/journal/test-journal-flush.c +++ b/src/journal/test-journal-flush.c @@ -23,6 +23,7 @@ #include "sd-journal.h" +#include "alloc-util.h" #include "journal-file.h" #include "journal-internal.h" #include "macro.h" diff --git a/src/journal/test-journal-init.c b/src/journal/test-journal-init.c index 717b703d19..142da85041 100644 --- a/src/journal/test-journal-init.c +++ b/src/journal/test-journal-init.c @@ -22,6 +22,7 @@ #include "sd-journal.h" #include "log.h" +#include "parse-util.h" #include "rm-rf.h" #include "util.h" diff --git a/src/journal/test-journal-interleaving.c b/src/journal/test-journal-interleaving.c index 8069339c1f..4ad89fe4b6 100644 --- a/src/journal/test-journal-interleaving.c +++ b/src/journal/test-journal-interleaving.c @@ -24,11 +24,14 @@ #include <fcntl.h> #include "sd-journal.h" + +#include "alloc-util.h" #include "journal-file.h" #include "journal-vacuum.h" -#include "util.h" #include "log.h" +#include "parse-util.h" #include "rm-rf.h" +#include "util.h" /* This program tests skipping around in a multi-file journal. */ diff --git a/src/journal/test-journal-match.c b/src/journal/test-journal-match.c index 476477055a..abefedb992 100644 --- a/src/journal/test-journal-match.c +++ b/src/journal/test-journal-match.c @@ -23,6 +23,7 @@ #include "sd-journal.h" +#include "alloc-util.h" #include "journal-internal.h" #include "log.h" #include "string-util.h" diff --git a/src/journal/test-journal-stream.c b/src/journal/test-journal-stream.c index b5ecf2f375..0cbef4b8c5 100644 --- a/src/journal/test-journal-stream.c +++ b/src/journal/test-journal-stream.c @@ -19,16 +19,19 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <unistd.h> #include <fcntl.h> +#include <unistd.h> #include "sd-journal.h" -#include "util.h" + +#include "alloc-util.h" +#include "journal-file.h" +#include "journal-internal.h" #include "log.h" #include "macro.h" +#include "parse-util.h" #include "rm-rf.h" -#include "journal-file.h" -#include "journal-internal.h" +#include "util.h" #define N_ENTRIES 200 diff --git a/src/journal/test-journal-syslog.c b/src/journal/test-journal-syslog.c index de942c50cc..1784187fe9 100644 --- a/src/journal/test-journal-syslog.c +++ b/src/journal/test-journal-syslog.c @@ -19,6 +19,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "journald-syslog.h" #include "macro.h" #include "string-util.h" diff --git a/src/journal/test-mmap-cache.c b/src/journal/test-mmap-cache.c index ac1239acc4..fdd48e531c 100644 --- a/src/journal/test-mmap-cache.c +++ b/src/journal/test-mmap-cache.c @@ -19,12 +19,13 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include <fcntl.h> #include <stdlib.h> #include <sys/mman.h> #include <unistd.h> -#include <fcntl.h> #include "fd-util.h" +#include "fileio.h" #include "macro.h" #include "mmap-cache.h" #include "util.h" diff --git a/src/libsystemd-network/dhcp6-option.c b/src/libsystemd-network/dhcp6-option.c index f41bebced0..076bb2dac0 100644 --- a/src/libsystemd-network/dhcp6-option.c +++ b/src/libsystemd-network/dhcp6-option.c @@ -23,14 +23,14 @@ #include <errno.h> #include <string.h> -#include "sparse-endian.h" -#include "unaligned.h" -#include "util.h" -#include "strv.h" - +#include "alloc-util.h" #include "dhcp6-internal.h" #include "dhcp6-protocol.h" #include "dns-domain.h" +#include "sparse-endian.h" +#include "strv.h" +#include "unaligned.h" +#include "util.h" #define DHCP6_OPTION_IA_NA_LEN 12 #define DHCP6_OPTION_IA_TA_LEN 4 diff --git a/src/libsystemd-network/lldp-internal.c b/src/libsystemd-network/lldp-internal.c index 70061e914f..583be2f55d 100644 --- a/src/libsystemd-network/lldp-internal.c +++ b/src/libsystemd-network/lldp-internal.c @@ -22,6 +22,7 @@ #include "sd-lldp.h" +#include "alloc-util.h" #include "lldp-internal.h" /* We store maximum 1K chassis entries */ diff --git a/src/libsystemd-network/lldp-port.c b/src/libsystemd-network/lldp-port.c index 7486b4c38f..97b6b485d2 100644 --- a/src/libsystemd-network/lldp-port.c +++ b/src/libsystemd-network/lldp-port.c @@ -20,6 +20,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "async.h" #include "lldp-port.h" #include "lldp-network.h" diff --git a/src/libsystemd-network/lldp-tlv.c b/src/libsystemd-network/lldp-tlv.c index 66af22e37d..0851957ab4 100644 --- a/src/libsystemd-network/lldp-tlv.c +++ b/src/libsystemd-network/lldp-tlv.c @@ -23,8 +23,9 @@ #include <net/ethernet.h> #include <arpa/inet.h> -#include "macro.h" +#include "alloc-util.h" #include "lldp-tlv.h" +#include "macro.h" int tlv_section_new(tlv_section **ret) { tlv_section *s; diff --git a/src/libsystemd-network/network-internal.c b/src/libsystemd-network/network-internal.c index 39551b5761..52d76e443e 100644 --- a/src/libsystemd-network/network-internal.c +++ b/src/libsystemd-network/network-internal.c @@ -25,16 +25,19 @@ #include "sd-ndisc.h" +#include "alloc-util.h" #include "condition.h" #include "conf-parser.h" #include "dhcp-lease-internal.h" #include "log.h" +#include "network-internal.h" +#include "hexdecoct.h" +#include "parse-util.h" #include "siphash24.h" #include "string-util.h" #include "strv.h" #include "utf8.h" #include "util.h" -#include "network-internal.h" const char *net_get_name(struct udev_device *device) { const char *name, *field; diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c index a6d6a176e4..57fc8216c3 100644 --- a/src/libsystemd-network/sd-dhcp-client.c +++ b/src/libsystemd-network/sd-dhcp-client.c @@ -28,6 +28,7 @@ #include "sd-dhcp-client.h" +#include "alloc-util.h" #include "async.h" #include "dhcp-identifier.h" #include "dhcp-internal.h" diff --git a/src/libsystemd-network/sd-dhcp-lease.c b/src/libsystemd-network/sd-dhcp-lease.c index d982936a28..c850538d74 100644 --- a/src/libsystemd-network/sd-dhcp-lease.c +++ b/src/libsystemd-network/sd-dhcp-lease.c @@ -26,6 +26,7 @@ #include "sd-dhcp-lease.h" +#include "alloc-util.h" #include "dhcp-lease-internal.h" #include "dhcp-protocol.h" #include "dns-domain.h" @@ -34,6 +35,8 @@ #include "hostname-util.h" #include "in-addr-util.h" #include "network-internal.h" +#include "hexdecoct.h" +#include "parse-util.h" #include "unaligned.h" int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr) { diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index a2a8c16fc8..8d0d9955c3 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -24,6 +24,7 @@ #include "sd-dhcp-server.h" +#include "alloc-util.h" #include "dhcp-internal.h" #include "dhcp-server-internal.h" #include "fd-util.h" diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c index ade1b470d4..e29de60d24 100644 --- a/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/libsystemd-network/sd-dhcp6-client.c @@ -26,6 +26,7 @@ #include "sd-dhcp6-client.h" +#include "alloc-util.h" #include "dhcp-identifier.h" #include "dhcp6-internal.h" #include "dhcp6-lease-internal.h" @@ -33,6 +34,7 @@ #include "fd-util.h" #include "network-internal.h" #include "random-util.h" +#include "string-table.h" #include "util.h" #define MAX_MAC_ADDR_LEN INFINIBAND_ALEN diff --git a/src/libsystemd-network/sd-dhcp6-lease.c b/src/libsystemd-network/sd-dhcp6-lease.c index f34af6eaba..3f32ba35e7 100644 --- a/src/libsystemd-network/sd-dhcp6-lease.c +++ b/src/libsystemd-network/sd-dhcp6-lease.c @@ -22,11 +22,11 @@ #include <errno.h> -#include "strv.h" -#include "util.h" - +#include "alloc-util.h" #include "dhcp6-lease-internal.h" #include "dhcp6-protocol.h" +#include "strv.h" +#include "util.h" int dhcp6_lease_clear_timers(DHCP6IA *ia) { assert_return(ia, -EINVAL); diff --git a/src/libsystemd-network/sd-ipv4acd.c b/src/libsystemd-network/sd-ipv4acd.c index 3053724ea2..5340fdc0c1 100644 --- a/src/libsystemd-network/sd-ipv4acd.c +++ b/src/libsystemd-network/sd-ipv4acd.c @@ -26,6 +26,7 @@ #include "sd-ipv4acd.h" +#include "alloc-util.h" #include "arp-util.h" #include "event-util.h" #include "fd-util.h" diff --git a/src/libsystemd-network/sd-ipv4ll.c b/src/libsystemd-network/sd-ipv4ll.c index 68ec58da90..0d915e20e7 100644 --- a/src/libsystemd-network/sd-ipv4ll.c +++ b/src/libsystemd-network/sd-ipv4ll.c @@ -27,6 +27,7 @@ #include "sd-ipv4acd.h" #include "sd-ipv4ll.h" +#include "alloc-util.h" #include "event-util.h" #include "in-addr-util.h" #include "list.h" diff --git a/src/libsystemd-network/sd-lldp.c b/src/libsystemd-network/sd-lldp.c index b2b85e56e8..4ebe8053fa 100644 --- a/src/libsystemd-network/sd-lldp.c +++ b/src/libsystemd-network/sd-lldp.c @@ -24,7 +24,9 @@ #include "sd-lldp.h" +#include "alloc-util.h" #include "fd-util.h" +#include "fileio.h" #include "hashmap.h" #include "lldp-internal.h" #include "lldp-port.h" diff --git a/src/libsystemd-network/sd-ndisc.c b/src/libsystemd-network/sd-ndisc.c index ca4bb6325b..c494b9d6d8 100644 --- a/src/libsystemd-network/sd-ndisc.c +++ b/src/libsystemd-network/sd-ndisc.c @@ -26,6 +26,7 @@ #include "sd-ndisc.h" +#include "alloc-util.h" #include "async.h" #include "icmp6-util.h" #include "list.h" diff --git a/src/libsystemd-network/sd-pppoe.c b/src/libsystemd-network/sd-pppoe.c index 03a88973bf..045decc46c 100644 --- a/src/libsystemd-network/sd-pppoe.c +++ b/src/libsystemd-network/sd-pppoe.c @@ -30,6 +30,7 @@ #include "sd-pppoe.h" +#include "alloc-util.h" #include "async.h" #include "event-util.h" #include "fd-util.h" diff --git a/src/libsystemd-network/test-dhcp-client.c b/src/libsystemd-network/test-dhcp-client.c index 40a85eb25e..5b52c1cbb9 100644 --- a/src/libsystemd-network/test-dhcp-client.c +++ b/src/libsystemd-network/test-dhcp-client.c @@ -27,6 +27,7 @@ #include "sd-dhcp-client.h" #include "sd-event.h" +#include "alloc-util.h" #include "dhcp-identifier.h" #include "dhcp-internal.h" #include "dhcp-protocol.h" diff --git a/src/libsystemd-network/test-dhcp-option.c b/src/libsystemd-network/test-dhcp-option.c index b1ef174849..2d29e28f16 100644 --- a/src/libsystemd-network/test-dhcp-option.c +++ b/src/libsystemd-network/test-dhcp-option.c @@ -5,11 +5,11 @@ #include <errno.h> #include <string.h> -#include "util.h" -#include "macro.h" - -#include "dhcp-protocol.h" +#include "alloc-util.h" #include "dhcp-internal.h" +#include "dhcp-protocol.h" +#include "macro.h" +#include "util.h" struct option_desc { uint8_t sname[64]; diff --git a/src/libsystemd-network/test-ipv4ll-manual.c b/src/libsystemd-network/test-ipv4ll-manual.c index 08421c3575..913a929069 100644 --- a/src/libsystemd-network/test-ipv4ll-manual.c +++ b/src/libsystemd-network/test-ipv4ll-manual.c @@ -29,9 +29,11 @@ #include "sd-ipv4ll.h" #include "sd-netlink.h" +#include "alloc-util.h" #include "event-util.h" #include "in-addr-util.h" #include "netlink-util.h" +#include "parse-util.h" #include "string-util.h" #include "util.h" diff --git a/src/libsystemd-network/test-lldp.c b/src/libsystemd-network/test-lldp.c index 109462662f..931df7c170 100644 --- a/src/libsystemd-network/test-lldp.c +++ b/src/libsystemd-network/test-lldp.c @@ -28,6 +28,7 @@ #include "sd-event.h" #include "sd-lldp.h" +#include "alloc-util.h" #include "event-util.h" #include "fd-util.h" #include "lldp-network.h" diff --git a/src/libsystemd/sd-bus/bus-control.c b/src/libsystemd/sd-bus/bus-control.c index e68207ae07..d5bc32e757 100644 --- a/src/libsystemd/sd-bus/bus-control.c +++ b/src/libsystemd/sd-bus/bus-control.c @@ -28,14 +28,17 @@ #include "sd-bus.h" +#include "alloc-util.h" #include "bus-bloom.h" +#include "bus-control.h" #include "bus-internal.h" #include "bus-message.h" #include "bus-util.h" -#include "capability.h" +#include "capability-util.h" +#include "stdio-util.h" #include "string-util.h" #include "strv.h" -#include "bus-control.h" +#include "user-util.h" _public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) { int r; diff --git a/src/libsystemd/sd-bus/bus-creds.c b/src/libsystemd/sd-bus/bus-creds.c index d7bff784b8..2922da3763 100644 --- a/src/libsystemd/sd-bus/bus-creds.c +++ b/src/libsystemd/sd-bus/bus-creds.c @@ -22,20 +22,24 @@ #include <linux/capability.h> #include <stdlib.h> -#include "audit.h" +#include "alloc-util.h" +#include "audit-util.h" #include "bus-creds.h" #include "bus-label.h" #include "bus-message.h" #include "bus-util.h" -#include "capability.h" +#include "capability-util.h" #include "cgroup-util.h" #include "fd-util.h" #include "fileio.h" #include "formats-util.h" +#include "hexdecoct.h" +#include "parse-util.h" #include "process-util.h" #include "string-util.h" #include "strv.h" #include "terminal-util.h" +#include "user-util.h" #include "util.h" enum { diff --git a/src/libsystemd/sd-bus/bus-dump.c b/src/libsystemd/sd-bus/bus-dump.c index cd7fcc7c80..43a7e67a6d 100644 --- a/src/libsystemd/sd-bus/bus-dump.c +++ b/src/libsystemd/sd-bus/bus-dump.c @@ -19,18 +19,21 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" +#include "bus-dump.h" #include "bus-internal.h" #include "bus-message.h" #include "bus-type.h" #include "cap-list.h" -#include "capability.h" +#include "capability-util.h" +#include "fileio.h" #include "formats-util.h" +#include "locale-util.h" #include "macro.h" #include "string-util.h" #include "strv.h" #include "terminal-util.h" #include "util.h" -#include "bus-dump.h" static char *indent(unsigned level, unsigned flags) { char *p; diff --git a/src/libsystemd/sd-bus/bus-error.c b/src/libsystemd/sd-bus/bus-error.c index 831ceb86b9..84229c2964 100644 --- a/src/libsystemd/sd-bus/bus-error.c +++ b/src/libsystemd/sd-bus/bus-error.c @@ -28,6 +28,7 @@ #include "sd-bus.h" +#include "alloc-util.h" #include "errno-list.h" #include "string-util.h" #include "util.h" diff --git a/src/libsystemd/sd-bus/bus-internal.c b/src/libsystemd/sd-bus/bus-internal.c index 486a8cf8de..d9f9cd1c5e 100644 --- a/src/libsystemd/sd-bus/bus-internal.c +++ b/src/libsystemd/sd-bus/bus-internal.c @@ -19,8 +19,10 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "bus-internal.h" #include "bus-message.h" +#include "hexdecoct.h" #include "string-util.h" bool object_path_is_valid(const char *p) { diff --git a/src/libsystemd/sd-bus/bus-introspect.c b/src/libsystemd/sd-bus/bus-introspect.c index f5a8885332..a90536bac9 100644 --- a/src/libsystemd/sd-bus/bus-introspect.c +++ b/src/libsystemd/sd-bus/bus-introspect.c @@ -24,6 +24,7 @@ #include "bus-protocol.h" #include "bus-signature.h" #include "fd-util.h" +#include "fileio.h" #include "string-util.h" #include "util.h" diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c index f311e86d44..6716f6daca 100644 --- a/src/libsystemd/sd-bus/bus-kernel.c +++ b/src/libsystemd/sd-bus/bus-kernel.c @@ -34,19 +34,22 @@ #include <libgen.h> #undef basename +#include "alloc-util.h" #include "bus-bloom.h" #include "bus-internal.h" #include "bus-kernel.h" #include "bus-label.h" #include "bus-message.h" #include "bus-util.h" -#include "capability.h" +#include "capability-util.h" #include "fd-util.h" #include "fileio.h" #include "formats-util.h" #include "memfd-util.h" +#include "parse-util.h" #include "string-util.h" #include "strv.h" +#include "user-util.h" #include "util.h" #define UNIQUE_NAME_MAX (3+DECIMAL_STR_MAX(uint64_t)) diff --git a/src/libsystemd/sd-bus/bus-match.c b/src/libsystemd/sd-bus/bus-match.c index 58b19fbdc7..55dc7caa53 100644 --- a/src/libsystemd/sd-bus/bus-match.c +++ b/src/libsystemd/sd-bus/bus-match.c @@ -19,11 +19,14 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "bus-internal.h" #include "bus-match.h" #include "bus-message.h" #include "bus-util.h" #include "fd-util.h" +#include "fileio.h" +#include "hexdecoct.h" #include "string-util.h" #include "strv.h" diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c index 447e25db8a..5c80095bf0 100644 --- a/src/libsystemd/sd-bus/bus-message.c +++ b/src/libsystemd/sd-bus/bus-message.c @@ -25,6 +25,7 @@ #include "sd-bus.h" +#include "alloc-util.h" #include "bus-gvariant.h" #include "bus-internal.h" #include "bus-message.h" @@ -32,6 +33,7 @@ #include "bus-type.h" #include "bus-util.h" #include "fd-util.h" +#include "io-util.h" #include "memfd-util.h" #include "string-util.h" #include "strv.h" diff --git a/src/libsystemd/sd-bus/bus-objects.c b/src/libsystemd/sd-bus/bus-objects.c index d3679800b5..8c472626a8 100644 --- a/src/libsystemd/sd-bus/bus-objects.c +++ b/src/libsystemd/sd-bus/bus-objects.c @@ -19,6 +19,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "bus-internal.h" #include "bus-introspect.h" #include "bus-message.h" diff --git a/src/libsystemd/sd-bus/bus-slot.c b/src/libsystemd/sd-bus/bus-slot.c index 63f10eba2c..550bad27ba 100644 --- a/src/libsystemd/sd-bus/bus-slot.c +++ b/src/libsystemd/sd-bus/bus-slot.c @@ -21,6 +21,7 @@ #include "sd-bus.h" +#include "alloc-util.h" #include "bus-control.h" #include "bus-objects.h" #include "string-util.h" diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c index 42d7f80461..a5cb667630 100644 --- a/src/libsystemd/sd-bus/bus-socket.c +++ b/src/libsystemd/sd-bus/bus-socket.c @@ -27,14 +27,17 @@ #include "sd-bus.h" #include "sd-daemon.h" +#include "alloc-util.h" #include "bus-internal.h" #include "bus-message.h" #include "bus-socket.h" #include "fd-util.h" #include "formats-util.h" +#include "hexdecoct.h" #include "macro.h" #include "missing.h" #include "signal-util.h" +#include "stdio-util.h" #include "string-util.h" #include "user-util.h" #include "utf8.h" diff --git a/src/libsystemd/sd-bus/bus-track.c b/src/libsystemd/sd-bus/bus-track.c index 0911156e19..fd7e58fcfa 100644 --- a/src/libsystemd/sd-bus/bus-track.c +++ b/src/libsystemd/sd-bus/bus-track.c @@ -21,6 +21,7 @@ #include "sd-bus.h" +#include "alloc-util.h" #include "bus-internal.h" #include "bus-track.h" #include "bus-util.h" diff --git a/src/libsystemd/sd-bus/busctl-introspect.c b/src/libsystemd/sd-bus/busctl-introspect.c index 5604db9716..71f962b00c 100644 --- a/src/libsystemd/sd-bus/busctl-introspect.c +++ b/src/libsystemd/sd-bus/busctl-introspect.c @@ -21,10 +21,11 @@ #include "sd-bus.h" +#include "alloc-util.h" +#include "busctl-introspect.h" #include "string-util.h" #include "util.h" #include "xml.h" -#include "busctl-introspect.h" #define NODE_DEPTH_MAX 16 diff --git a/src/libsystemd/sd-bus/busctl.c b/src/libsystemd/sd-bus/busctl.c index d3e846db84..452ac7c407 100644 --- a/src/libsystemd/sd-bus/busctl.c +++ b/src/libsystemd/sd-bus/busctl.c @@ -23,6 +23,7 @@ #include "sd-bus.h" +#include "alloc-util.h" #include "bus-dump.h" #include "bus-internal.h" #include "bus-signature.h" @@ -31,8 +32,10 @@ #include "busctl-introspect.h" #include "escape.h" #include "fd-util.h" +#include "locale-util.h" #include "log.h" #include "pager.h" +#include "parse-util.h" #include "path-util.h" #include "set.h" #include "strv.h" diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c index 7b91c2583d..a8d79b01b0 100644 --- a/src/libsystemd/sd-bus/sd-bus.c +++ b/src/libsystemd/sd-bus/sd-bus.c @@ -29,6 +29,7 @@ #include "sd-bus.h" +#include "alloc-util.h" #include "bus-container.h" #include "bus-control.h" #include "bus-internal.h" @@ -48,6 +49,8 @@ #include "hostname-util.h" #include "macro.h" #include "missing.h" +#include "hexdecoct.h" +#include "parse-util.h" #include "string-util.h" #include "strv.h" #include "util.h" diff --git a/src/libsystemd/sd-bus/test-bus-benchmark.c b/src/libsystemd/sd-bus/test-bus-benchmark.c index 549c88cd2d..96a0929a14 100644 --- a/src/libsystemd/sd-bus/test-bus-benchmark.c +++ b/src/libsystemd/sd-bus/test-bus-benchmark.c @@ -23,6 +23,7 @@ #include "sd-bus.h" +#include "alloc-util.h" #include "bus-internal.h" #include "bus-kernel.h" #include "bus-util.h" diff --git a/src/libsystemd/sd-bus/test-bus-chat.c b/src/libsystemd/sd-bus/test-bus-chat.c index e9e5e4a8e3..767aef63ff 100644 --- a/src/libsystemd/sd-bus/test-bus-chat.c +++ b/src/libsystemd/sd-bus/test-bus-chat.c @@ -26,6 +26,7 @@ #include "sd-bus.h" +#include "alloc-util.h" #include "bus-error.h" #include "bus-internal.h" #include "bus-match.h" diff --git a/src/libsystemd/sd-bus/test-bus-gvariant.c b/src/libsystemd/sd-bus/test-bus-gvariant.c index f94da4cccd..931c001788 100644 --- a/src/libsystemd/sd-bus/test-bus-gvariant.c +++ b/src/libsystemd/sd-bus/test-bus-gvariant.c @@ -25,6 +25,7 @@ #include "sd-bus.h" +#include "alloc-util.h" #include "bus-dump.h" #include "bus-gvariant.h" #include "bus-internal.h" diff --git a/src/libsystemd/sd-bus/test-bus-kernel-bloom.c b/src/libsystemd/sd-bus/test-bus-kernel-bloom.c index ff7f9cdafa..dbdaa69fbe 100644 --- a/src/libsystemd/sd-bus/test-bus-kernel-bloom.c +++ b/src/libsystemd/sd-bus/test-bus-kernel-bloom.c @@ -21,6 +21,7 @@ #include "sd-bus.h" +#include "alloc-util.h" #include "bus-kernel.h" #include "bus-util.h" #include "fd-util.h" diff --git a/src/libsystemd/sd-bus/test-bus-kernel.c b/src/libsystemd/sd-bus/test-bus-kernel.c index 7d05953cd0..0080f71d3b 100644 --- a/src/libsystemd/sd-bus/test-bus-kernel.c +++ b/src/libsystemd/sd-bus/test-bus-kernel.c @@ -23,6 +23,7 @@ #include "sd-bus.h" +#include "alloc-util.h" #include "bus-dump.h" #include "bus-kernel.h" #include "bus-util.h" diff --git a/src/libsystemd/sd-bus/test-bus-marshal.c b/src/libsystemd/sd-bus/test-bus-marshal.c index c0daa451ec..0747d6a37c 100644 --- a/src/libsystemd/sd-bus/test-bus-marshal.c +++ b/src/libsystemd/sd-bus/test-bus-marshal.c @@ -32,12 +32,14 @@ #include "sd-bus.h" +#include "alloc-util.h" #include "bus-dump.h" #include "bus-label.h" #include "bus-message.h" #include "bus-util.h" #include "fd-util.h" #include "log.h" +#include "hexdecoct.h" #include "util.h" static void test_bus_path_encode_unique(void) { diff --git a/src/libsystemd/sd-bus/test-bus-objects.c b/src/libsystemd/sd-bus/test-bus-objects.c index 138db910ea..5bc72e2355 100644 --- a/src/libsystemd/sd-bus/test-bus-objects.c +++ b/src/libsystemd/sd-bus/test-bus-objects.c @@ -24,6 +24,7 @@ #include "sd-bus.h" +#include "alloc-util.h" #include "bus-dump.h" #include "bus-internal.h" #include "bus-message.h" diff --git a/src/libsystemd/sd-bus/test-bus-proxy.c b/src/libsystemd/sd-bus/test-bus-proxy.c index ae04ff5b0d..428e185769 100644 --- a/src/libsystemd/sd-bus/test-bus-proxy.c +++ b/src/libsystemd/sd-bus/test-bus-proxy.c @@ -25,6 +25,7 @@ #include "sd-bus.h" +#include "alloc-util.h" #include "bus-dump.h" #include "bus-kernel.h" #include "bus-util.h" diff --git a/src/libsystemd/sd-bus/test-bus-zero-copy.c b/src/libsystemd/sd-bus/test-bus-zero-copy.c index 1be0dbcd82..ff8df61a9e 100644 --- a/src/libsystemd/sd-bus/test-bus-zero-copy.c +++ b/src/libsystemd/sd-bus/test-bus-zero-copy.c @@ -23,6 +23,7 @@ #include "sd-bus.h" +#include "alloc-util.h" #include "bus-dump.h" #include "bus-kernel.h" #include "bus-message.h" diff --git a/src/libsystemd/sd-daemon/sd-daemon.c b/src/libsystemd/sd-daemon/sd-daemon.c index 85c73722df..27045e25d0 100644 --- a/src/libsystemd/sd-daemon/sd-daemon.c +++ b/src/libsystemd/sd-daemon/sd-daemon.c @@ -35,12 +35,17 @@ #include "sd-daemon.h" +#include "alloc-util.h" #include "fd-util.h" +#include "fs-util.h" +#include "parse-util.h" #include "path-util.h" #include "socket-util.h" #include "strv.h" #include "util.h" +#define SNDBUF_SIZE (8*1024*1024) + static void unsetenv_all(bool unset_environment) { if (!unset_environment) @@ -431,12 +436,19 @@ _public_ int sd_pid_notify_with_fds(pid_t pid, int unset_environment, const char goto finish; } + if (strlen(e) > sizeof(sockaddr.un.sun_path)) { + r = -EINVAL; + goto finish; + } + fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0); if (fd < 0) { r = -errno; goto finish; } + fd_inc_sndbuf(fd, SNDBUF_SIZE); + iovec.iov_len = strlen(state); strncpy(sockaddr.un.sun_path, e, sizeof(sockaddr.un.sun_path)); diff --git a/src/libsystemd/sd-device/device-enumerator.c b/src/libsystemd/sd-device/device-enumerator.c index c98053220c..ae3157ee5e 100644 --- a/src/libsystemd/sd-device/device-enumerator.c +++ b/src/libsystemd/sd-device/device-enumerator.c @@ -20,8 +20,10 @@ #include "sd-device.h" +#include "alloc-util.h" #include "device-enumerator-private.h" #include "device-util.h" +#include "dirent-util.h" #include "fd-util.h" #include "prioq.h" #include "set.h" diff --git a/src/libsystemd/sd-device/device-private.c b/src/libsystemd/sd-device/device-private.c index bcabf9468d..a13477e753 100644 --- a/src/libsystemd/sd-device/device-private.c +++ b/src/libsystemd/sd-device/device-private.c @@ -24,20 +24,25 @@ #include "sd-device.h" +#include "alloc-util.h" #include "device-internal.h" #include "device-private.h" #include "device-util.h" #include "fd-util.h" #include "fileio.h" +#include "fs-util.h" #include "hashmap.h" #include "macro.h" #include "mkdir.h" +#include "parse-util.h" #include "path-util.h" #include "refcnt.h" #include "set.h" +#include "string-table.h" #include "string-util.h" #include "strv.h" #include "strxcpyx.h" +#include "user-util.h" #include "util.h" int device_add_property(sd_device *device, const char *key, const char *value) { diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c index 593dda52f2..0d40bc5c00 100644 --- a/src/libsystemd/sd-device/sd-device.c +++ b/src/libsystemd/sd-device/sd-device.c @@ -24,15 +24,19 @@ #include "sd-device.h" +#include "alloc-util.h" #include "device-internal.h" #include "device-private.h" #include "device-util.h" #include "fd-util.h" #include "fileio.h" +#include "fs-util.h" #include "hashmap.h" #include "macro.h" +#include "parse-util.h" #include "path-util.h" #include "set.h" +#include "stat-util.h" #include "string-util.h" #include "strv.h" #include "strxcpyx.h" diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c index b3f8881714..ee4886700e 100644 --- a/src/libsystemd/sd-event/sd-event.c +++ b/src/libsystemd/sd-event/sd-event.c @@ -27,6 +27,7 @@ #include "sd-event.h" #include "sd-id128.h" +#include "alloc-util.h" #include "fd-util.h" #include "hashmap.h" #include "list.h" diff --git a/src/libsystemd/sd-hwdb/sd-hwdb.c b/src/libsystemd/sd-hwdb/sd-hwdb.c index 9304fd376e..0e034863d6 100644 --- a/src/libsystemd/sd-hwdb/sd-hwdb.c +++ b/src/libsystemd/sd-hwdb/sd-hwdb.c @@ -29,6 +29,7 @@ #include "sd-hwdb.h" +#include "alloc-util.h" #include "fd-util.h" #include "hashmap.h" #include "hwdb-internal.h" diff --git a/src/libsystemd/sd-id128/sd-id128.c b/src/libsystemd/sd-id128/sd-id128.c index 335ad3b1b4..1e17ea6a06 100644 --- a/src/libsystemd/sd-id128/sd-id128.c +++ b/src/libsystemd/sd-id128/sd-id128.c @@ -28,6 +28,7 @@ #include "fd-util.h" #include "io-util.h" #include "macro.h" +#include "hexdecoct.h" #include "random-util.h" #include "util.h" diff --git a/src/libsystemd/sd-login/sd-login.c b/src/libsystemd/sd-login/sd-login.c index f564d43e06..cd766c3f91 100644 --- a/src/libsystemd/sd-login/sd-login.c +++ b/src/libsystemd/sd-login/sd-login.c @@ -27,15 +27,20 @@ #include "sd-login.h" +#include "alloc-util.h" #include "cgroup-util.h" +#include "dirent-util.h" #include "escape.h" #include "fd-util.h" #include "fileio.h" #include "formats-util.h" +#include "fs-util.h" #include "hostname-util.h" #include "io-util.h" #include "login-util.h" #include "macro.h" +#include "parse-util.h" +#include "path-util.h" #include "socket-util.h" #include "string-util.h" #include "strv.h" diff --git a/src/libsystemd/sd-login/test-login.c b/src/libsystemd/sd-login/test-login.c index 46aa73b38a..b0f94c9522 100644 --- a/src/libsystemd/sd-login/test-login.c +++ b/src/libsystemd/sd-login/test-login.c @@ -24,6 +24,7 @@ #include "sd-login.h" +#include "alloc-util.h" #include "fd-util.h" #include "formats-util.h" #include "string-util.h" diff --git a/src/libsystemd/sd-netlink/local-addresses.c b/src/libsystemd/sd-netlink/local-addresses.c index e2f637f7f9..a00865b56b 100644 --- a/src/libsystemd/sd-netlink/local-addresses.c +++ b/src/libsystemd/sd-netlink/local-addresses.c @@ -21,6 +21,8 @@ ***/ #include "sd-netlink.h" + +#include "alloc-util.h" #include "netlink-util.h" #include "macro.h" #include "local-addresses.h" diff --git a/src/libsystemd/sd-netlink/netlink-message.c b/src/libsystemd/sd-netlink/netlink-message.c index 80ad70cfee..03971b3596 100644 --- a/src/libsystemd/sd-netlink/netlink-message.c +++ b/src/libsystemd/sd-netlink/netlink-message.c @@ -25,6 +25,7 @@ #include "sd-netlink.h" +#include "alloc-util.h" #include "formats-util.h" #include "missing.h" #include "netlink-internal.h" diff --git a/src/libsystemd/sd-netlink/netlink-socket.c b/src/libsystemd/sd-netlink/netlink-socket.c index 68a4d3c0d1..13945202e4 100644 --- a/src/libsystemd/sd-netlink/netlink-socket.c +++ b/src/libsystemd/sd-netlink/netlink-socket.c @@ -25,6 +25,7 @@ #include "sd-netlink.h" +#include "alloc-util.h" #include "formats-util.h" #include "missing.h" #include "netlink-internal.h" diff --git a/src/libsystemd/sd-netlink/netlink-types.c b/src/libsystemd/sd-netlink/netlink-types.c index 4a5340e659..cf0a6248d6 100644 --- a/src/libsystemd/sd-netlink/netlink-types.c +++ b/src/libsystemd/sd-netlink/netlink-types.c @@ -28,16 +28,15 @@ #include <linux/if_bridge.h> #include <linux/if_addr.h> #include <linux/if.h> - #include <linux/ip.h> #include <linux/if_link.h> #include <linux/if_tunnel.h> #include "macro.h" -#include "util.h" - -#include "netlink-types.h" #include "missing.h" +#include "netlink-types.h" +#include "string-table.h" +#include "util.h" /* Maximum ARP IP target defined in kernel */ #define BOND_MAX_ARP_TARGETS 16 diff --git a/src/libsystemd/sd-netlink/sd-netlink.c b/src/libsystemd/sd-netlink/sd-netlink.c index ba1f2a5a42..7c24e053cf 100644 --- a/src/libsystemd/sd-netlink/sd-netlink.c +++ b/src/libsystemd/sd-netlink/sd-netlink.c @@ -24,6 +24,7 @@ #include "sd-netlink.h" +#include "alloc-util.h" #include "fd-util.h" #include "hashmap.h" #include "macro.h" diff --git a/src/libsystemd/sd-netlink/test-local-addresses.c b/src/libsystemd/sd-netlink/test-local-addresses.c index 9867eec065..7180175970 100644 --- a/src/libsystemd/sd-netlink/test-local-addresses.c +++ b/src/libsystemd/sd-netlink/test-local-addresses.c @@ -19,6 +19,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "in-addr-util.h" #include "local-addresses.h" #include "af-list.h" diff --git a/src/libsystemd/sd-network/network-util.c b/src/libsystemd/sd-network/network-util.c index 8070ff07c4..a2d6c59314 100644 --- a/src/libsystemd/sd-network/network-util.c +++ b/src/libsystemd/sd-network/network-util.c @@ -19,6 +19,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "fd-util.h" #include "network-util.h" #include "strv.h" diff --git a/src/libsystemd/sd-network/sd-network.c b/src/libsystemd/sd-network/sd-network.c index ad1227264c..efbceba83d 100644 --- a/src/libsystemd/sd-network/sd-network.c +++ b/src/libsystemd/sd-network/sd-network.c @@ -27,12 +27,15 @@ #include "sd-network.h" +#include "alloc-util.h" +#include "fd-util.h" #include "fileio.h" +#include "fs-util.h" #include "macro.h" +#include "parse-util.h" #include "string-util.h" #include "strv.h" #include "util.h" -#include "fd-util.h" _public_ int sd_network_get_operational_state(char **state) { _cleanup_free_ char *s = NULL; diff --git a/src/libsystemd/sd-path/sd-path.c b/src/libsystemd/sd-path/sd-path.c index 8e3eeb15d8..480f1ad065 100644 --- a/src/libsystemd/sd-path/sd-path.c +++ b/src/libsystemd/sd-path/sd-path.c @@ -19,8 +19,10 @@ #include "sd-path.h" +#include "alloc-util.h" #include "architecture.h" #include "fd-util.h" +#include "fileio.h" #include "missing.h" #include "path-util.h" #include "string-util.h" diff --git a/src/libsystemd/sd-resolve/sd-resolve.c b/src/libsystemd/sd-resolve/sd-resolve.c index 724405d534..48767600c9 100644 --- a/src/libsystemd/sd-resolve/sd-resolve.c +++ b/src/libsystemd/sd-resolve/sd-resolve.c @@ -33,6 +33,7 @@ #include "sd-resolve.h" +#include "alloc-util.h" #include "fd-util.h" #include "io-util.h" #include "list.h" diff --git a/src/libsystemd/sd-resolve/test-resolve.c b/src/libsystemd/sd-resolve/test-resolve.c index 87e6e47041..05544a584c 100644 --- a/src/libsystemd/sd-resolve/test-resolve.c +++ b/src/libsystemd/sd-resolve/test-resolve.c @@ -30,6 +30,7 @@ #include "sd-resolve.h" +#include "alloc-util.h" #include "macro.h" #include "resolve-util.h" #include "socket-util.h" diff --git a/src/libudev/libudev-device.c b/src/libudev/libudev-device.c index 1e513f3ff7..814e016800 100644 --- a/src/libudev/libudev-device.c +++ b/src/libudev/libudev-device.c @@ -37,10 +37,12 @@ #include "libudev.h" #include "sd-device.h" +#include "alloc-util.h" #include "device-private.h" #include "device-util.h" #include "libudev-device-internal.h" #include "libudev-private.h" +#include "parse-util.h" /** * SECTION:libudev-device diff --git a/src/libudev/libudev-enumerate.c b/src/libudev/libudev-enumerate.c index 56436772b0..442f9615f2 100644 --- a/src/libudev/libudev-enumerate.c +++ b/src/libudev/libudev-enumerate.c @@ -31,6 +31,7 @@ #include "libudev.h" #include "sd-device.h" +#include "alloc-util.h" #include "device-enumerator-private.h" #include "device-util.h" #include "libudev-device-internal.h" diff --git a/src/libudev/libudev-hwdb.c b/src/libudev/libudev-hwdb.c index 6dc2b0533e..eba698d163 100644 --- a/src/libudev/libudev-hwdb.c +++ b/src/libudev/libudev-hwdb.c @@ -19,6 +19,7 @@ #include "sd-hwdb.h" +#include "alloc-util.h" #include "hwdb-util.h" #include "libudev-private.h" diff --git a/src/libudev/libudev-list.c b/src/libudev/libudev-list.c index 19e9130be0..da496ed456 100644 --- a/src/libudev/libudev-list.c +++ b/src/libudev/libudev-list.c @@ -17,11 +17,12 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <stdlib.h> -#include <stddef.h> #include <errno.h> +#include <stddef.h> +#include <stdlib.h> #include <string.h> +#include "alloc-util.h" #include "libudev-private.h" /** diff --git a/src/libudev/libudev-monitor.c b/src/libudev/libudev-monitor.c index 5590aec2b7..c3883e485b 100644 --- a/src/libudev/libudev-monitor.c +++ b/src/libudev/libudev-monitor.c @@ -30,10 +30,13 @@ #include "libudev.h" +#include "alloc-util.h" #include "fd-util.h" +#include "fileio.h" #include "formats-util.h" #include "libudev-private.h" #include "missing.h" +#include "mount-util.h" #include "socket-util.h" #include "string-util.h" diff --git a/src/libudev/libudev-queue.c b/src/libudev/libudev-queue.c index a22994c8a2..58410b1b8f 100644 --- a/src/libudev/libudev-queue.c +++ b/src/libudev/libudev-queue.c @@ -24,6 +24,7 @@ #include <errno.h> #include <sys/inotify.h> +#include "alloc-util.h" #include "fd-util.h" #include "io-util.h" #include "libudev-private.h" diff --git a/src/libudev/libudev-util.c b/src/libudev/libudev-util.c index a614230df4..574cfeac85 100644 --- a/src/libudev/libudev-util.c +++ b/src/libudev/libudev-util.c @@ -29,6 +29,7 @@ #include "MurmurHash2.h" #include "device-nodes.h" #include "libudev-private.h" +#include "syslog-util.h" #include "utf8.h" /** diff --git a/src/libudev/libudev.c b/src/libudev/libudev.c index afadfe6993..63fb05547d 100644 --- a/src/libudev/libudev.c +++ b/src/libudev/libudev.c @@ -26,6 +26,7 @@ #include "libudev.h" +#include "alloc-util.h" #include "fd-util.h" #include "libudev-private.h" #include "missing.h" diff --git a/src/locale/localed.c b/src/locale/localed.c index 73e25f0642..720cbbaaba 100644 --- a/src/locale/localed.c +++ b/src/locale/localed.c @@ -30,20 +30,23 @@ #include "sd-bus.h" -#include "util.h" -#include "mkdir.h" -#include "strv.h" -#include "def.h" -#include "env-util.h" -#include "fileio.h" -#include "fileio-label.h" -#include "bus-util.h" +#include "alloc-util.h" #include "bus-error.h" #include "bus-message.h" +#include "bus-util.h" +#include "def.h" +#include "env-util.h" #include "event-util.h" +#include "fd-util.h" +#include "fileio-label.h" +#include "fileio.h" #include "locale-util.h" +#include "mkdir.h" +#include "path-util.h" #include "selinux-util.h" -#include "fd-util.h" +#include "strv.h" +#include "user-util.h" +#include "util.h" enum { /* We don't list LC_ALL here on purpose. People should be diff --git a/src/login/inhibit.c b/src/login/inhibit.c index f79f89af7e..70fef332f7 100644 --- a/src/login/inhibit.c +++ b/src/login/inhibit.c @@ -27,6 +27,7 @@ #include "sd-bus.h" +#include "alloc-util.h" #include "bus-error.h" #include "bus-util.h" #include "fd-util.h" diff --git a/src/login/loginctl.c b/src/login/loginctl.c index 1cd186dec3..aff68a49fe 100644 --- a/src/login/loginctl.c +++ b/src/login/loginctl.c @@ -27,6 +27,7 @@ #include "sd-bus.h" +#include "alloc-util.h" #include "bus-error.h" #include "bus-util.h" #include "cgroup-show.h" @@ -35,6 +36,7 @@ #include "logs-show.h" #include "macro.h" #include "pager.h" +#include "parse-util.h" #include "process-util.h" #include "signal-util.h" #include "spawn-polkit-agent.h" diff --git a/src/login/logind-acl.c b/src/login/logind-acl.c index 4d7bda3ee0..d0dd569a03 100644 --- a/src/login/logind-acl.c +++ b/src/login/logind-acl.c @@ -23,6 +23,8 @@ #include <string.h> #include "acl-util.h" +#include "alloc-util.h" +#include "dirent-util.h" #include "escape.h" #include "fd-util.h" #include "formats-util.h" diff --git a/src/login/logind-action.c b/src/login/logind-action.c index f06f8edc07..185108f8f1 100644 --- a/src/login/logind-action.c +++ b/src/login/logind-action.c @@ -21,14 +21,16 @@ #include <unistd.h> -#include "conf-parser.h" -#include "special.h" -#include "sleep-config.h" -#include "bus-util.h" +#include "alloc-util.h" #include "bus-error.h" -#include "logind-action.h" +#include "bus-util.h" +#include "conf-parser.h" #include "formats-util.h" +#include "logind-action.h" #include "process-util.h" +#include "sleep-config.h" +#include "special.h" +#include "string-table.h" #include "terminal-util.h" #include "user-util.h" diff --git a/src/login/logind-button.c b/src/login/logind-button.c index b98035be21..b08b69dbfc 100644 --- a/src/login/logind-button.c +++ b/src/login/logind-button.c @@ -28,6 +28,7 @@ #include "sd-messages.h" +#include "alloc-util.h" #include "fd-util.h" #include "logind-button.h" #include "string-util.h" diff --git a/src/login/logind-core.c b/src/login/logind-core.c index c2541e490b..b3f30c8dc9 100644 --- a/src/login/logind-core.c +++ b/src/login/logind-core.c @@ -25,6 +25,7 @@ #include <pwd.h> #include <linux/vt.h> +#include "alloc-util.h" #include "bus-error.h" #include "bus-util.h" #include "cgroup-util.h" diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 61c2c9ba40..7890d68aa0 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -26,15 +26,18 @@ #include "sd-messages.h" -#include "audit.h" +#include "alloc-util.h" +#include "audit-util.h" #include "bus-common-errors.h" #include "bus-error.h" #include "bus-util.h" +#include "dirent-util.h" #include "efivars.h" #include "escape.h" #include "fd-util.h" #include "fileio-label.h" #include "formats-util.h" +#include "fs-util.h" #include "logind.h" #include "mkdir.h" #include "path-util.h" diff --git a/src/login/logind-device.c b/src/login/logind-device.c index ee4c45fb8d..ffb9162e56 100644 --- a/src/login/logind-device.c +++ b/src/login/logind-device.c @@ -21,8 +21,9 @@ #include <string.h> -#include "util.h" +#include "alloc-util.h" #include "logind-device.h" +#include "util.h" Device* device_new(Manager *m, const char *sysfs, bool master) { Device *d; diff --git a/src/login/logind-inhibit.c b/src/login/logind-inhibit.c index c4b74eb734..33fbdde557 100644 --- a/src/login/logind-inhibit.c +++ b/src/login/logind-inhibit.c @@ -24,12 +24,15 @@ #include <string.h> #include <unistd.h> +#include "alloc-util.h" #include "escape.h" #include "fd-util.h" #include "fileio.h" #include "formats-util.h" #include "logind-inhibit.h" #include "mkdir.h" +#include "parse-util.h" +#include "string-table.h" #include "string-util.h" #include "user-util.h" #include "util.h" diff --git a/src/login/logind-seat-dbus.c b/src/login/logind-seat-dbus.c index 346e1d2cec..43b578f364 100644 --- a/src/login/logind-seat-dbus.c +++ b/src/login/logind-seat-dbus.c @@ -22,13 +22,15 @@ #include <errno.h> #include <string.h> -#include "util.h" -#include "bus-util.h" -#include "strv.h" +#include "alloc-util.h" #include "bus-common-errors.h" #include "bus-label.h" -#include "logind.h" +#include "bus-util.h" #include "logind-seat.h" +#include "logind.h" +#include "strv.h" +#include "user-util.h" +#include "util.h" static int property_get_active_session( sd_bus *bus, diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c index dad552d5f2..1f4936cebe 100644 --- a/src/login/logind-seat.c +++ b/src/login/logind-seat.c @@ -26,11 +26,14 @@ #include "sd-messages.h" +#include "alloc-util.h" #include "fd-util.h" +#include "fileio.h" #include "formats-util.h" #include "logind-acl.h" #include "logind-seat.h" #include "mkdir.h" +#include "parse-util.h" #include "string-util.h" #include "terminal-util.h" #include "util.h" diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c index fe398a5eb6..7810199a54 100644 --- a/src/login/logind-session-dbus.c +++ b/src/login/logind-session-dbus.c @@ -22,6 +22,7 @@ #include <errno.h> #include <string.h> +#include "alloc-util.h" #include "bus-common-errors.h" #include "bus-label.h" #include "bus-util.h" diff --git a/src/login/logind-session-device.c b/src/login/logind-session-device.c index 3a0bb720f9..9bf3ca0995 100644 --- a/src/login/logind-session-device.c +++ b/src/login/logind-session-device.c @@ -27,6 +27,7 @@ #include "libudev.h" +#include "alloc-util.h" #include "bus-util.h" #include "fd-util.h" #include "logind-session-device.h" diff --git a/src/login/logind-session.c b/src/login/logind-session.c index 714b1cb299..a53dcb9960 100644 --- a/src/login/logind-session.c +++ b/src/login/logind-session.c @@ -30,7 +30,8 @@ #include "sd-messages.h" -#include "audit.h" +#include "alloc-util.h" +#include "audit-util.h" #include "bus-error.h" #include "bus-util.h" #include "escape.h" @@ -41,7 +42,9 @@ #include "io-util.h" #include "logind-session.h" #include "mkdir.h" +#include "parse-util.h" #include "path-util.h" +#include "string-table.h" #include "terminal-util.h" #include "user-util.h" #include "util.h" diff --git a/src/login/logind-user-dbus.c b/src/login/logind-user-dbus.c index 5975b579e9..df901f6558 100644 --- a/src/login/logind-user-dbus.c +++ b/src/login/logind-user-dbus.c @@ -22,6 +22,7 @@ #include <errno.h> #include <string.h> +#include "alloc-util.h" #include "bus-util.h" #include "formats-util.h" #include "logind-user.h" diff --git a/src/login/logind-user.c b/src/login/logind-user.c index 80328068cd..56bc5a010c 100644 --- a/src/login/logind-user.c +++ b/src/login/logind-user.c @@ -24,6 +24,7 @@ #include <sys/mount.h> #include <unistd.h> +#include "alloc-util.h" #include "bus-error.h" #include "bus-util.h" #include "clean-ipc.h" @@ -32,15 +33,20 @@ #include "fd-util.h" #include "fileio.h" #include "formats-util.h" +#include "fs-util.h" #include "hashmap.h" #include "label.h" #include "logind-user.h" #include "mkdir.h" +#include "mount-util.h" +#include "parse-util.h" #include "path-util.h" #include "rm-rf.h" #include "smack-util.h" #include "special.h" +#include "string-table.h" #include "unit-name.h" +#include "user-util.h" #include "util.h" User* user_new(Manager *m, uid_t uid, gid_t gid, const char *name) { diff --git a/src/login/logind-utmp.c b/src/login/logind-utmp.c index 9c766bcb25..3e7a935a34 100644 --- a/src/login/logind-utmp.c +++ b/src/login/logind-utmp.c @@ -26,7 +26,8 @@ #include "sd-messages.h" -#include "audit.h" +#include "alloc-util.h" +#include "audit-util.h" #include "bus-common-errors.h" #include "bus-error.h" #include "bus-util.h" diff --git a/src/login/logind.c b/src/login/logind.c index 02c87ca58e..4b8c834269 100644 --- a/src/login/logind.c +++ b/src/login/logind.c @@ -27,9 +27,11 @@ #include "libudev.h" #include "sd-daemon.h" +#include "alloc-util.h" #include "bus-error.h" #include "bus-util.h" #include "conf-parser.h" +#include "dirent-util.h" #include "fd-util.h" #include "formats-util.h" #include "logind.h" diff --git a/src/login/pam_systemd.c b/src/login/pam_systemd.c index dbd055a79a..0d61f528db 100644 --- a/src/login/pam_systemd.c +++ b/src/login/pam_systemd.c @@ -30,7 +30,8 @@ #include <security/pam_modutil.h> #include <sys/file.h> -#include "audit.h" +#include "alloc-util.h" +#include "audit-util.h" #include "bus-common-errors.h" #include "bus-error.h" #include "bus-util.h" @@ -41,6 +42,7 @@ #include "hostname-util.h" #include "login-util.h" #include "macro.h" +#include "parse-util.h" #include "socket-util.h" #include "strv.h" #include "terminal-util.h" diff --git a/src/login/sysfs-show.c b/src/login/sysfs-show.c index 32e53c0a11..e9ca4bb03d 100644 --- a/src/login/sysfs-show.c +++ b/src/login/sysfs-show.c @@ -24,6 +24,8 @@ #include "libudev.h" +#include "alloc-util.h" +#include "locale-util.h" #include "path-util.h" #include "string-util.h" #include "sysfs-show.h" diff --git a/src/machine/image-dbus.c b/src/machine/image-dbus.c index 2453a9ff04..4ec1766033 100644 --- a/src/machine/image-dbus.c +++ b/src/machine/image-dbus.c @@ -19,11 +19,13 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "bus-label.h" -#include "strv.h" #include "bus-util.h" -#include "machine-image.h" #include "image-dbus.h" +#include "machine-image.h" +#include "strv.h" +#include "user-util.h" static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, image_type, ImageType); diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c index c17a98e90f..452130a29c 100644 --- a/src/machine/machine-dbus.c +++ b/src/machine/machine-dbus.c @@ -29,6 +29,7 @@ #include <libgen.h> #undef basename +#include "alloc-util.h" #include "bus-common-errors.h" #include "bus-internal.h" #include "bus-label.h" @@ -38,6 +39,7 @@ #include "fd-util.h" #include "fileio.h" #include "formats-util.h" +#include "fs-util.h" #include "in-addr-util.h" #include "local-addresses.h" #include "machine-dbus.h" @@ -47,6 +49,7 @@ #include "process-util.h" #include "strv.h" #include "terminal-util.h" +#include "user-util.h" static int property_get_id( sd_bus *bus, diff --git a/src/machine/machine.c b/src/machine/machine.c index e41f8add98..ef5c8551b5 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -25,6 +25,7 @@ #include "sd-messages.h" +#include "alloc-util.h" #include "bus-error.h" #include "bus-util.h" #include "escape.h" @@ -35,10 +36,13 @@ #include "machine-dbus.h" #include "machine.h" #include "mkdir.h" +#include "parse-util.h" #include "special.h" +#include "string-table.h" #include "terminal-util.h" #include "unit-name.h" #include "util.h" +#include "extract-word.h" Machine* machine_new(Manager *manager, MachineClass class, const char *name) { Machine *m; @@ -309,17 +313,26 @@ int machine_load(Machine *m) { } if (netif) { - size_t l, allocated = 0, nr = 0; - const char *word, *state; + size_t allocated = 0, nr = 0; + const char *p; int *ni = NULL; - FOREACH_WORD(word, l, netif, state) { - char buf[l+1]; + p = netif; + for(;;) { + _cleanup_free_ char *word = NULL; int ifi; - *(char*) (mempcpy(buf, word, l)) = 0; + r = extract_first_word(&p, &word, NULL, 0); + if (r == 0) + break; + else if (r == -ENOMEM) + return log_oom(); + else if (r < 0) { + log_warning_errno(r, "Failed to parse NETIF: %s", netif); + continue; + } - if (safe_atoi(buf, &ifi) < 0) + if (safe_atoi(word, &ifi) < 0) continue; if (ifi <= 0) continue; diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index 23cc74ab54..7e17c7a41c 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -33,6 +33,7 @@ #include "sd-bus.h" +#include "alloc-util.h" #include "bus-error.h" #include "bus-util.h" #include "cgroup-show.h" @@ -48,6 +49,7 @@ #include "macro.h" #include "mkdir.h" #include "pager.h" +#include "parse-util.h" #include "path-util.h" #include "process-util.h" #include "ptyfwd.h" @@ -58,6 +60,7 @@ #include "unit-name.h" #include "util.h" #include "verbs.h" +#include "web-util.h" static char **arg_property = NULL; static bool arg_all = false; diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c index 3c91fa8644..7827f063c1 100644 --- a/src/machine/machined-dbus.c +++ b/src/machine/machined-dbus.c @@ -25,6 +25,7 @@ #include "sd-id128.h" +#include "alloc-util.h" #include "btrfs-util.h" #include "bus-common-errors.h" #include "bus-util.h" @@ -39,6 +40,7 @@ #include "machined.h" #include "path-util.h" #include "process-util.h" +#include "stdio-util.h" #include "strv.h" #include "unit-name.h" #include "user-util.h" diff --git a/src/machine/machined.c b/src/machine/machined.c index fe229c88a8..d6e7ce67fc 100644 --- a/src/machine/machined.c +++ b/src/machine/machined.c @@ -25,9 +25,11 @@ #include "sd-daemon.h" +#include "alloc-util.h" #include "bus-error.h" #include "bus-util.h" #include "cgroup-util.h" +#include "dirent-util.h" #include "fd-util.h" #include "formats-util.h" #include "hostname-util.h" diff --git a/src/modules-load/modules-load.c b/src/modules-load/modules-load.c index 34bd65cb11..830ca7b89d 100644 --- a/src/modules-load/modules-load.c +++ b/src/modules-load/modules-load.c @@ -28,7 +28,9 @@ #include "conf-files.h" #include "fd-util.h" +#include "fileio.h" #include "log.h" +#include "proc-cmdline.h" #include "string-util.h" #include "strv.h" #include "util.h" diff --git a/src/network/networkctl.c b/src/network/networkctl.c index acb6b7ce24..97c1fe6560 100644 --- a/src/network/networkctl.c +++ b/src/network/networkctl.c @@ -28,15 +28,20 @@ #include "sd-netlink.h" #include "sd-network.h" +#include "alloc-util.h" #include "arphrd-list.h" #include "device-util.h" #include "ether-addr-util.h" #include "hwdb-util.h" #include "lldp.h" #include "local-addresses.h" +#include "locale-util.h" +#include "locale-util.h" #include "netlink-util.h" #include "pager.h" +#include "parse-util.h" #include "socket-util.h" +#include "string-table.h" #include "string-util.h" #include "strv.h" #include "terminal-util.h" diff --git a/src/network/networkd-address-pool.c b/src/network/networkd-address-pool.c index 08e0b9a64b..889fe1e30d 100644 --- a/src/network/networkd-address-pool.c +++ b/src/network/networkd-address-pool.c @@ -19,6 +19,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "networkd-address-pool.h" #include "networkd.h" #include "set.h" diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index dcd7b482d3..e550ee5701 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -21,15 +21,17 @@ #include <net/if.h> +#include "alloc-util.h" #include "conf-parser.h" #include "firewall-util.h" #include "netlink-util.h" +#include "networkd-address.h" #include "networkd.h" +#include "parse-util.h" #include "set.h" #include "string-util.h" #include "utf8.h" #include "util.h" -#include "networkd-address.h" int address_new(Address **ret) { _cleanup_address_free_ Address *address = NULL; diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index 22594a9415..c412a2cc31 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -22,10 +22,11 @@ #include <netinet/ether.h> #include <linux/if.h> +#include "alloc-util.h" +#include "dhcp-lease-internal.h" #include "hostname-util.h" -#include "networkd-link.h" #include "network-internal.h" -#include "dhcp-lease-internal.h" +#include "networkd-link.h" static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { diff --git a/src/network/networkd-fdb.c b/src/network/networkd-fdb.c index 9cb63cb79f..c9222b8cb8 100644 --- a/src/network/networkd-fdb.c +++ b/src/network/networkd-fdb.c @@ -22,12 +22,12 @@ #include <net/if.h> #include <net/ethernet.h> +#include "alloc-util.h" #include "conf-parser.h" -#include "util.h" #include "netlink-util.h" - -#include "networkd.h" #include "networkd-fdb.h" +#include "networkd.h" +#include "util.h" /* create a new FDB entry or get an existing one. */ int fdb_entry_new_static(Network *const network, diff --git a/src/network/networkd-link-bus.c b/src/network/networkd-link-bus.c index 1a1524dfb4..7fc4510ac9 100644 --- a/src/network/networkd-link-bus.c +++ b/src/network/networkd-link-bus.c @@ -22,8 +22,10 @@ #include "bus-util.h" #include "strv.h" -#include "networkd.h" +#include "alloc-util.h" #include "networkd-link.h" +#include "networkd.h" +#include "parse-util.h" static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_operational_state, link_operstate, LinkOperationalState); static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_administrative_state, link_state, LinkState); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 1144c82c17..12ca02868d 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -23,6 +23,7 @@ #include <linux/if.h> #include <unistd.h> +#include "alloc-util.h" #include "bus-util.h" #include "dhcp-lease-internal.h" #include "fd-util.h" @@ -33,6 +34,8 @@ #include "networkd-netdev.h" #include "set.h" #include "socket-util.h" +#include "stdio-util.h" +#include "string-table.h" #include "udev-util.h" #include "util.h" #include "virt.h" @@ -346,12 +349,12 @@ static void link_free(Link *link) { while (!set_isempty(link->addresses)) address_free(set_first(link->addresses)); - set_free(link->addresses); - while (!set_isempty(link->addresses_foreign)) address_free(set_first(link->addresses_foreign)); - set_free(link->addresses_foreign); + link->addresses = set_free(link->addresses); + + link->addresses_foreign = set_free(link->addresses_foreign); while ((address = link->pool_addresses)) { LIST_REMOVE(addresses, link->pool_addresses, address); diff --git a/src/network/networkd-manager-bus.c b/src/network/networkd-manager-bus.c index b281f4fdb6..dafaf2daea 100644 --- a/src/network/networkd-manager-bus.c +++ b/src/network/networkd-manager-bus.c @@ -19,8 +19,8 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "bus-util.h" - #include "networkd.h" static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_operational_state, link_operstate, LinkOperationalState); diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index febfe2ff81..6b2a661ca7 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -25,10 +25,12 @@ #include "sd-daemon.h" #include "sd-netlink.h" +#include "alloc-util.h" #include "bus-util.h" #include "conf-parser.h" #include "def.h" #include "fd-util.h" +#include "fileio.h" #include "libudev-private.h" #include "local-addresses.h" #include "netlink-util.h" diff --git a/src/network/networkd-netdev-bond.c b/src/network/networkd-netdev-bond.c index afc1efdcf7..70105b8aa0 100644 --- a/src/network/networkd-netdev-bond.c +++ b/src/network/networkd-netdev-bond.c @@ -25,10 +25,12 @@ #include "sd-netlink.h" +#include "alloc-util.h" #include "conf-parser.h" #include "missing.h" -#include "string-util.h" #include "networkd-netdev-bond.h" +#include "string-util.h" +#include "string-table.h" /* * Number of seconds between instances where the bonding diff --git a/src/network/networkd-netdev-ipvlan.c b/src/network/networkd-netdev-ipvlan.c index fb0aed0dcb..27cb7d1bf0 100644 --- a/src/network/networkd-netdev-ipvlan.c +++ b/src/network/networkd-netdev-ipvlan.c @@ -21,8 +21,9 @@ #include <net/if.h> -#include "networkd-netdev-ipvlan.h" #include "conf-parser.h" +#include "networkd-netdev-ipvlan.h" +#include "string-table.h" static const char* const ipvlan_mode_table[_NETDEV_IPVLAN_MODE_MAX] = { [NETDEV_IPVLAN_MODE_L2] = "L2", diff --git a/src/network/networkd-netdev-macvlan.c b/src/network/networkd-netdev-macvlan.c index e17de793ce..7144823b2d 100644 --- a/src/network/networkd-netdev-macvlan.c +++ b/src/network/networkd-netdev-macvlan.c @@ -21,8 +21,9 @@ #include <net/if.h> -#include "networkd-netdev-macvlan.h" #include "conf-parser.h" +#include "networkd-netdev-macvlan.h" +#include "string-table.h" static const char* const macvlan_mode_table[_NETDEV_MACVLAN_MODE_MAX] = { [NETDEV_MACVLAN_MODE_PRIVATE] = "private", diff --git a/src/network/networkd-netdev-tunnel.c b/src/network/networkd-netdev-tunnel.c index bbc4606258..385338849f 100644 --- a/src/network/networkd-netdev-tunnel.c +++ b/src/network/networkd-netdev-tunnel.c @@ -30,9 +30,11 @@ #include "conf-parser.h" #include "missing.h" #include "networkd-link.h" +#include "networkd-netdev-tunnel.h" +#include "parse-util.h" +#include "string-table.h" #include "string-util.h" #include "util.h" -#include "networkd-netdev-tunnel.h" #define DEFAULT_TNL_HOP_LIMIT 64 #define IP6_FLOWINFO_FLOWLABEL htonl(0x000FFFFF) diff --git a/src/network/networkd-netdev-tuntap.c b/src/network/networkd-netdev-tuntap.c index d04bb9bd9f..851e83537e 100644 --- a/src/network/networkd-netdev-tuntap.c +++ b/src/network/networkd-netdev-tuntap.c @@ -23,6 +23,7 @@ #include <net/if.h> #include <linux/if_tun.h> +#include "alloc-util.h" #include "fd-util.h" #include "networkd-netdev-tuntap.h" #include "user-util.h" diff --git a/src/network/networkd-netdev.c b/src/network/networkd-netdev.c index bd1129a09b..dd0b400c6a 100644 --- a/src/network/networkd-netdev.c +++ b/src/network/networkd-netdev.c @@ -21,6 +21,7 @@ #include <net/if.h> +#include "alloc-util.h" #include "conf-files.h" #include "conf-parser.h" #include "fd-util.h" @@ -30,6 +31,8 @@ #include "networkd-netdev.h" #include "networkd.h" #include "siphash24.h" +#include "stat-util.h" +#include "string-table.h" #include "string-util.h" const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = { diff --git a/src/network/networkd-network-bus.c b/src/network/networkd-network-bus.c index 2199b93baa..120760a986 100644 --- a/src/network/networkd-network-bus.c +++ b/src/network/networkd-network-bus.c @@ -19,6 +19,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "networkd.h" #include "string-util.h" #include "strv.h" diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 150fd052c2..cc8d019017 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -22,6 +22,7 @@ #include <ctype.h> #include <net/if.h> +#include "alloc-util.h" #include "conf-files.h" #include "conf-parser.h" #include "dns-domain.h" @@ -30,6 +31,9 @@ #include "network-internal.h" #include "networkd-network.h" #include "networkd.h" +#include "parse-util.h" +#include "stat-util.h" +#include "string-table.h" #include "string-util.h" #include "util.h" diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index fcca679093..4a74bc69f3 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -19,13 +19,15 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "conf-parser.h" #include "in-addr-util.h" #include "netlink-util.h" +#include "networkd-route.h" #include "networkd.h" +#include "parse-util.h" #include "string-util.h" #include "util.h" -#include "networkd-route.h" int route_new(Route **ret) { _cleanup_route_free_ Route *route = NULL; diff --git a/src/network/networkd-util.c b/src/network/networkd-util.c index 4e4a4bbd58..17165266ef 100644 --- a/src/network/networkd-util.c +++ b/src/network/networkd-util.c @@ -21,6 +21,8 @@ #include "conf-parser.h" #include "networkd-util.h" +#include "parse-util.h" +#include "string-table.h" #include "string-util.h" #include "util.h" diff --git a/src/network/networkd-wait-online-link.c b/src/network/networkd-wait-online-link.c index cc4b46d5b0..c2779ff773 100644 --- a/src/network/networkd-wait-online-link.c +++ b/src/network/networkd-wait-online-link.c @@ -22,6 +22,7 @@ #include "sd-network.h" +#include "alloc-util.h" #include "networkd-wait-online-link.h" #include "string-util.h" diff --git a/src/network/networkd-wait-online-manager.c b/src/network/networkd-wait-online-manager.c index 112d92a568..0c40ab2bb8 100644 --- a/src/network/networkd-wait-online-manager.c +++ b/src/network/networkd-wait-online-manager.c @@ -23,14 +23,13 @@ #include <linux/if.h> #include <fnmatch.h> +#include "alloc-util.h" #include "netlink-util.h" - #include "network-internal.h" #include "networkd-wait-online-link.h" #include "networkd-wait-online.h" - -#include "util.h" #include "time-util.h" +#include "util.h" bool manager_ignore_link(Manager *m, Link *link) { char **ignore; diff --git a/src/network/networkd.c b/src/network/networkd.c index 1a17847715..c03ac69e27 100644 --- a/src/network/networkd.c +++ b/src/network/networkd.c @@ -21,7 +21,7 @@ #include "sd-daemon.h" -#include "capability.h" +#include "capability-util.h" #include "networkd.h" #include "signal-util.h" #include "user-util.h" diff --git a/src/network/test-network.c b/src/network/test-network.c index bac1d6781d..dbed3795e3 100644 --- a/src/network/test-network.c +++ b/src/network/test-network.c @@ -19,6 +19,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "networkd.h" #include "network-internal.h" #include "dhcp-lease-internal.h" diff --git a/src/notify/notify.c b/src/notify/notify.c index 288e0a4316..b144554702 100644 --- a/src/notify/notify.c +++ b/src/notify/notify.c @@ -27,9 +27,11 @@ #include "sd-daemon.h" +#include "alloc-util.h" #include "env-util.h" #include "formats-util.h" #include "log.h" +#include "parse-util.h" #include "string-util.h" #include "strv.h" #include "util.h" diff --git a/src/nspawn/nspawn-cgroup.c b/src/nspawn/nspawn-cgroup.c index 4e86ed13cb..270bcf010f 100644 --- a/src/nspawn/nspawn-cgroup.c +++ b/src/nspawn/nspawn-cgroup.c @@ -21,6 +21,7 @@ #include <sys/mount.h> +#include "alloc-util.h" #include "cgroup-util.h" #include "fd-util.h" #include "fileio.h" diff --git a/src/nspawn/nspawn-expose-ports.c b/src/nspawn/nspawn-expose-ports.c index 98e4a7682f..38245434da 100644 --- a/src/nspawn/nspawn-expose-ports.c +++ b/src/nspawn/nspawn-expose-ports.c @@ -21,12 +21,14 @@ #include "sd-netlink.h" +#include "alloc-util.h" #include "fd-util.h" #include "firewall-util.h" #include "in-addr-util.h" #include "local-addresses.h" #include "netlink-util.h" #include "nspawn-expose-ports.h" +#include "parse-util.h" #include "socket-util.h" #include "string-util.h" #include "util.h" diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c index 25457fd62d..ee61306aa5 100644 --- a/src/nspawn/nspawn-mount.c +++ b/src/nspawn/nspawn-mount.c @@ -22,17 +22,23 @@ #include <sys/mount.h> #include <linux/magic.h> +#include "alloc-util.h" #include "cgroup-util.h" #include "escape.h" +#include "fs-util.h" #include "label.h" #include "mkdir.h" +#include "mount-util.h" +#include "nspawn-mount.h" +#include "parse-util.h" #include "path-util.h" #include "rm-rf.h" #include "set.h" +#include "stat-util.h" #include "string-util.h" #include "strv.h" +#include "user-util.h" #include "util.h" -#include "nspawn-mount.h" CustomMount* custom_mount_add(CustomMount **l, unsigned *n, CustomMountType t) { CustomMount *c, *ret; diff --git a/src/nspawn/nspawn-network.c b/src/nspawn/nspawn-network.c index 4af18a4e94..29384b60b2 100644 --- a/src/nspawn/nspawn-network.c +++ b/src/nspawn/nspawn-network.c @@ -26,6 +26,7 @@ #include "sd-id128.h" #include "sd-netlink.h" +#include "alloc-util.h" #include "ether-addr-util.h" #include "netlink-util.h" #include "siphash24.h" diff --git a/src/nspawn/nspawn-register.c b/src/nspawn/nspawn-register.c index b2776a61c2..7139ad9958 100644 --- a/src/nspawn/nspawn-register.c +++ b/src/nspawn/nspawn-register.c @@ -21,12 +21,12 @@ #include "sd-bus.h" -#include "util.h" -#include "strv.h" -#include "bus-util.h" #include "bus-error.h" - +#include "bus-util.h" #include "nspawn-register.h" +#include "stat-util.h" +#include "strv.h" +#include "util.h" int register_machine( const char *machine_name, diff --git a/src/nspawn/nspawn-settings.c b/src/nspawn/nspawn-settings.c index f088884776..6885d0641e 100644 --- a/src/nspawn/nspawn-settings.c +++ b/src/nspawn/nspawn-settings.c @@ -19,12 +19,13 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include "util.h" -#include "conf-parser.h" -#include "strv.h" +#include "alloc-util.h" #include "cap-list.h" - +#include "conf-parser.h" #include "nspawn-settings.h" +#include "process-util.h" +#include "strv.h" +#include "util.h" int settings_load(FILE *f, const char *path, Settings **ret) { _cleanup_(settings_freep) Settings *s = NULL; diff --git a/src/nspawn/nspawn-setuid.c b/src/nspawn/nspawn-setuid.c index 6b4ca5a3f3..aa6a16309c 100644 --- a/src/nspawn/nspawn-setuid.c +++ b/src/nspawn/nspawn-setuid.c @@ -23,6 +23,7 @@ #include <sys/types.h> #include <unistd.h> +#include "alloc-util.h" #include "fd-util.h" #include "mkdir.h" #include "nspawn-setuid.h" diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 6502fe1943..ff12ca6498 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -46,12 +46,13 @@ #include "sd-daemon.h" #include "sd-id128.h" +#include "alloc-util.h" #include "barrier.h" #include "base-filesystem.h" #include "blkid-util.h" #include "btrfs-util.h" #include "cap-list.h" -#include "capability.h" +#include "capability-util.h" #include "cgroup-util.h" #include "copy.h" #include "dev-setup.h" @@ -61,6 +62,7 @@ #include "fdset.h" #include "fileio.h" #include "formats-util.h" +#include "fs-util.h" #include "gpt.h" #include "hostname-util.h" #include "log.h" @@ -69,6 +71,7 @@ #include "macro.h" #include "missing.h" #include "mkdir.h" +#include "mount-util.h" #include "netlink-util.h" #include "nspawn-cgroup.h" #include "nspawn-expose-ports.h" @@ -77,6 +80,7 @@ #include "nspawn-register.h" #include "nspawn-settings.h" #include "nspawn-setuid.h" +#include "parse-util.h" #include "path-util.h" #include "process-util.h" #include "ptyfwd.h" @@ -87,10 +91,13 @@ #endif #include "signal-util.h" #include "socket-util.h" +#include "stat-util.h" +#include "stdio-util.h" #include "string-util.h" #include "strv.h" #include "terminal-util.h" #include "udev-util.h" +#include "umask-util.h" #include "user-util.h" #include "util.h" @@ -380,6 +387,7 @@ static int parse_argv(int argc, char *argv[]) { }; int c, r; + const char *p; uint64_t plus = 0, minus = 0; bool mask_all_settings = false, mask_no_settings = false; @@ -517,15 +525,16 @@ static int parse_argv(int argc, char *argv[]) { case ARG_CAPABILITY: case ARG_DROP_CAPABILITY: { - const char *state, *word; - size_t length; + p = optarg; + for(;;) { + _cleanup_free_ char *t = NULL; - FOREACH_WORD_SEPARATOR(word, length, optarg, ",", state) { - _cleanup_free_ char *t; + r = extract_first_word(&p, &t, ",", 0); + if (r < 0) + return log_error_errno(r, "Failed to parse capability %s.", t); - t = strndup(word, length); - if (!t) - return log_oom(); + if (r == 0) + break; if (streq(t, "all")) { if (c == ARG_CAPABILITY) @@ -3218,8 +3227,7 @@ int main(int argc, char *argv[]) { } for (;;) { - _cleanup_close_pair_ int kmsg_socket_pair[2] = { -1, -1 }, rtnl_socket_pair[2] = { -1, -1 }, pid_socket_pair[2] = { -1, -1 }, - uid_shift_socket_pair[2] = { -1, -1 }; + _cleanup_close_pair_ int kmsg_socket_pair[2] = { -1, -1 }, rtnl_socket_pair[2] = { -1, -1 }, pid_socket_pair[2] = { -1, -1 }, uid_shift_socket_pair[2] = { -1, -1 }; ContainerStatus container_status; _cleanup_(barrier_destroy) Barrier barrier = BARRIER_NULL; static const struct sigaction sa = { diff --git a/src/nss-myhostname/nss-myhostname.c b/src/nss-myhostname/nss-myhostname.c index 009a9ad886..ee10b105ea 100644 --- a/src/nss-myhostname/nss-myhostname.c +++ b/src/nss-myhostname/nss-myhostname.c @@ -26,6 +26,7 @@ #include <stdlib.h> #include <string.h> +#include "alloc-util.h" #include "hostname-util.h" #include "local-addresses.h" #include "macro.h" diff --git a/src/nss-mymachines/nss-mymachines.c b/src/nss-mymachines/nss-mymachines.c index b98bde676b..969fa9619e 100644 --- a/src/nss-mymachines/nss-mymachines.c +++ b/src/nss-mymachines/nss-mymachines.c @@ -25,6 +25,7 @@ #include "sd-bus.h" #include "sd-login.h" +#include "alloc-util.h" #include "bus-common-errors.h" #include "bus-util.h" #include "hostname-util.h" diff --git a/src/path/path.c b/src/path/path.c index 97e8323de1..0ece72f6fe 100644 --- a/src/path/path.c +++ b/src/path/path.c @@ -26,6 +26,7 @@ #include "sd-path.h" +#include "alloc-util.h" #include "log.h" #include "macro.h" #include "string-util.h" diff --git a/src/quotacheck/quotacheck.c b/src/quotacheck/quotacheck.c index a2a035f4f1..dc2911e4e8 100644 --- a/src/quotacheck/quotacheck.c +++ b/src/quotacheck/quotacheck.c @@ -29,6 +29,7 @@ #include "signal-util.h" #include "string-util.h" #include "util.h" +#include "proc-cmdline.h" static bool arg_skip = false; static bool arg_force = false; diff --git a/src/random-seed/random-seed.c b/src/random-seed/random-seed.c index fbfd3a3eba..d857ade36a 100644 --- a/src/random-seed/random-seed.c +++ b/src/random-seed/random-seed.c @@ -25,6 +25,7 @@ #include <sys/stat.h> #include <unistd.h> +#include "alloc-util.h" #include "fd-util.h" #include "io-util.h" #include "log.h" diff --git a/src/rc-local-generator/rc-local-generator.c b/src/rc-local-generator/rc-local-generator.c index 1007de3959..8e5cf0908c 100644 --- a/src/rc-local-generator/rc-local-generator.c +++ b/src/rc-local-generator/rc-local-generator.c @@ -24,6 +24,7 @@ #include <stdio.h> #include <unistd.h> +#include "alloc-util.h" #include "log.h" #include "mkdir.h" #include "string-util.h" diff --git a/src/remount-fs/remount-fs.c b/src/remount-fs/remount-fs.c index f904e48e75..57f99c9ef0 100644 --- a/src/remount-fs/remount-fs.c +++ b/src/remount-fs/remount-fs.c @@ -26,12 +26,13 @@ #include <sys/wait.h> #include <mntent.h> +#include "exit-status.h" #include "log.h" -#include "util.h" +#include "mount-setup.h" +#include "mount-util.h" #include "path-util.h" #include "signal-util.h" -#include "mount-setup.h" -#include "exit-status.h" +#include "util.h" /* Goes through /etc/fstab and remounts all API file systems, applying * options that are in /etc/fstab that systemd might not have diff --git a/src/resolve-host/resolve-host.c b/src/resolve-host/resolve-host.c index 97516a87a8..57739d1f3e 100644 --- a/src/resolve-host/resolve-host.c +++ b/src/resolve-host/resolve-host.c @@ -25,9 +25,11 @@ #include "sd-bus.h" #include "af-list.h" +#include "alloc-util.h" #include "bus-error.h" #include "bus-util.h" #include "in-addr-util.h" +#include "parse-util.h" #include "resolved-def.h" #include "resolved-dns-packet.h" diff --git a/src/resolve/resolved-bus.c b/src/resolve/resolved-bus.c index bf1b7c8ab4..f0a3b607d4 100644 --- a/src/resolve/resolved-bus.c +++ b/src/resolve/resolved-bus.c @@ -19,9 +19,9 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "bus-common-errors.h" #include "bus-util.h" - #include "dns-domain.h" #include "resolved-bus.h" #include "resolved-def.h" diff --git a/src/resolve/resolved-conf.c b/src/resolve/resolved-conf.c index aca0d891c6..c9919ced67 100644 --- a/src/resolve/resolved-conf.c +++ b/src/resolve/resolved-conf.c @@ -19,13 +19,14 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "conf-parser.h" -#include "string-util.h" +#include "extract-word.h" +#include "parse-util.h" #include "resolved-conf.h" +#include "string-util.h" int manager_parse_dns_server(Manager *m, DnsServerType type, const char *string) { - const char *word, *state; - size_t length; DnsServer *first; int r; @@ -34,19 +35,22 @@ int manager_parse_dns_server(Manager *m, DnsServerType type, const char *string) first = type == DNS_SERVER_FALLBACK ? m->fallback_dns_servers : m->dns_servers; - FOREACH_WORD_QUOTED(word, length, string, state) { - char buffer[length+1]; - int family; + for(;;) { + _cleanup_free_ char *word = NULL; union in_addr_union addr; bool found = false; DnsServer *s; + int family; - memcpy(buffer, word, length); - buffer[length] = 0; + r = extract_first_word(&string, &word, NULL, 0); + if (r < 0) + return log_error_errno(r, "Failed to parse resolved dns server syntax \"%s\": %m", string); + if (r == 0) + break; - r = in_addr_from_string_auto(buffer, &family, &addr); + r = in_addr_from_string_auto(word, &family, &addr); if (r < 0) { - log_warning("Ignoring invalid DNS address '%s'", buffer); + log_warning("Ignoring invalid DNS address '%s'", word); continue; } diff --git a/src/resolve/resolved-dns-answer.c b/src/resolve/resolved-dns-answer.c index e1a2865007..3cf9c68074 100644 --- a/src/resolve/resolved-dns-answer.c +++ b/src/resolve/resolved-dns-answer.c @@ -19,6 +19,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "dns-domain.h" #include "resolved-dns-answer.h" #include "string-util.h" diff --git a/src/resolve/resolved-dns-cache.c b/src/resolve/resolved-dns-cache.c index ab13636bc1..04f64022e0 100644 --- a/src/resolve/resolved-dns-cache.c +++ b/src/resolve/resolved-dns-cache.c @@ -19,6 +19,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "resolved-dns-cache.h" #include "resolved-dns-packet.h" diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c index bebd1ee4a6..f23b3cf893 100644 --- a/src/resolve/resolved-dns-packet.c +++ b/src/resolve/resolved-dns-packet.c @@ -19,12 +19,14 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include "utf8.h" -#include "util.h" -#include "strv.h" -#include "unaligned.h" +#include "alloc-util.h" #include "dns-domain.h" #include "resolved-dns-packet.h" +#include "string-table.h" +#include "strv.h" +#include "unaligned.h" +#include "utf8.h" +#include "util.h" int dns_packet_new(DnsPacket **ret, DnsProtocol protocol, size_t mtu) { DnsPacket *p; diff --git a/src/resolve/resolved-dns-query.c b/src/resolve/resolved-dns-query.c index 4b1d18b2ef..f7cb84e2a6 100644 --- a/src/resolve/resolved-dns-query.c +++ b/src/resolve/resolved-dns-query.c @@ -19,10 +19,10 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include "hostname-util.h" +#include "alloc-util.h" #include "dns-domain.h" +#include "hostname-util.h" #include "local-addresses.h" - #include "resolved-dns-query.h" /* How long to wait for the query in total */ diff --git a/src/resolve/resolved-dns-question.c b/src/resolve/resolved-dns-question.c index 1507f22da0..48951221dc 100644 --- a/src/resolve/resolved-dns-question.c +++ b/src/resolve/resolved-dns-question.c @@ -19,8 +19,9 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include "resolved-dns-question.h" +#include "alloc-util.h" #include "dns-domain.h" +#include "resolved-dns-question.h" DnsQuestion *dns_question_new(unsigned n) { DnsQuestion *q; diff --git a/src/resolve/resolved-dns-rr.c b/src/resolve/resolved-dns-rr.c index c8f591d005..ba2ea686f3 100644 --- a/src/resolve/resolved-dns-rr.c +++ b/src/resolve/resolved-dns-rr.c @@ -21,12 +21,14 @@ #include <math.h> +#include "alloc-util.h" #include "dns-domain.h" #include "dns-type.h" +#include "hexdecoct.h" #include "resolved-dns-packet.h" +#include "resolved-dns-rr.h" #include "string-util.h" #include "strv.h" -#include "resolved-dns-rr.h" DnsResourceKey* dns_resource_key_new(uint16_t class, uint16_t type, const char *name) { DnsResourceKey *k; diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index 7c63c63b63..b15370b017 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -22,6 +22,7 @@ #include <netinet/tcp.h> #include "af-list.h" +#include "alloc-util.h" #include "dns-domain.h" #include "fd-util.h" #include "hostname-util.h" diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c index 8693911e65..e803f635ab 100644 --- a/src/resolve/resolved-dns-server.c +++ b/src/resolve/resolved-dns-server.c @@ -19,9 +19,9 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include "siphash24.h" - +#include "alloc-util.h" #include "resolved-dns-server.h" +#include "siphash24.h" /* After how much time to repeat classic DNS requests */ #define DNS_TIMEOUT_MIN_USEC (500 * USEC_PER_MSEC) diff --git a/src/resolve/resolved-dns-stream.c b/src/resolve/resolved-dns-stream.c index b2eebe09a2..1c501182fb 100644 --- a/src/resolve/resolved-dns-stream.c +++ b/src/resolve/resolved-dns-stream.c @@ -21,7 +21,9 @@ #include <netinet/tcp.h> +#include "alloc-util.h" #include "fd-util.h" +#include "io-util.h" #include "missing.h" #include "resolved-dns-stream.h" diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c index 84472ca1bc..6545f6cd8a 100644 --- a/src/resolve/resolved-dns-transaction.c +++ b/src/resolve/resolved-dns-transaction.c @@ -20,12 +20,13 @@ ***/ #include "af-list.h" - +#include "alloc-util.h" #include "dns-domain.h" #include "fd-util.h" #include "random-util.h" #include "resolved-dns-transaction.h" #include "resolved-llmnr.h" +#include "string-table.h" DnsTransaction* dns_transaction_free(DnsTransaction *t) { DnsQuery *q; diff --git a/src/resolve/resolved-dns-zone.c b/src/resolve/resolved-dns-zone.c index 8a6086a4de..48dcf76daa 100644 --- a/src/resolve/resolved-dns-zone.c +++ b/src/resolve/resolved-dns-zone.c @@ -19,6 +19,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "dns-domain.h" #include "list.h" #include "resolved-dns-packet.h" diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c index 43a3b61b08..2892641075 100644 --- a/src/resolve/resolved-link.c +++ b/src/resolve/resolved-link.c @@ -23,7 +23,9 @@ #include "sd-network.h" +#include "alloc-util.h" #include "missing.h" +#include "parse-util.h" #include "resolved-link.h" #include "string-util.h" #include "strv.h" diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index 6144eedfeb..a588538b52 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -25,6 +25,7 @@ #include <sys/ioctl.h> #include "af-list.h" +#include "alloc-util.h" #include "dns-domain.h" #include "fd-util.h" #include "fileio-label.h" @@ -33,12 +34,14 @@ #include "netlink-util.h" #include "network-internal.h" #include "ordered-set.h" +#include "parse-util.h" #include "random-util.h" #include "resolved-bus.h" #include "resolved-conf.h" #include "resolved-llmnr.h" #include "resolved-manager.h" #include "socket-util.h" +#include "string-table.h" #include "string-util.h" #include "utf8.h" diff --git a/src/resolve/resolved.c b/src/resolve/resolved.c index df4eb6f63e..7ba0546f4a 100644 --- a/src/resolve/resolved.c +++ b/src/resolve/resolved.c @@ -22,7 +22,7 @@ #include "sd-daemon.h" #include "sd-event.h" -#include "capability.h" +#include "capability-util.h" #include "mkdir.h" #include "resolved-conf.h" #include "resolved-manager.h" diff --git a/src/rfkill/rfkill.c b/src/rfkill/rfkill.c index 311343e454..bb00f99ecf 100644 --- a/src/rfkill/rfkill.c +++ b/src/rfkill/rfkill.c @@ -25,11 +25,15 @@ #include "libudev.h" #include "sd-daemon.h" +#include "alloc-util.h" #include "escape.h" #include "fd-util.h" #include "fileio.h" #include "io-util.h" #include "mkdir.h" +#include "parse-util.h" +#include "proc-cmdline.h" +#include "string-table.h" #include "string-util.h" #include "udev-util.h" #include "util.h" diff --git a/src/run/run.c b/src/run/run.c index 3646305961..38a482bb11 100644 --- a/src/run/run.c +++ b/src/run/run.c @@ -25,6 +25,7 @@ #include "sd-bus.h" #include "sd-event.h" +#include "alloc-util.h" #include "bus-error.h" #include "bus-util.h" #include "calendarspec.h" @@ -40,6 +41,7 @@ #include "terminal-util.h" #include "unit-name.h" #include "user-util.h" +#include "parse-util.h" static bool arg_ask_password = true; static bool arg_scope = false; diff --git a/src/shared/acl-util.c b/src/shared/acl-util.c index e8931daee2..79f5a60579 100644 --- a/src/shared/acl-util.c +++ b/src/shared/acl-util.c @@ -22,6 +22,7 @@ #include <errno.h> #include <stdbool.h> +#include "alloc-util.h" #include "acl-util.h" #include "string-util.h" #include "strv.h" diff --git a/src/shared/acpi-fpdt.c b/src/shared/acpi-fpdt.c index b3d2f96885..8e36067f74 100644 --- a/src/shared/acpi-fpdt.c +++ b/src/shared/acpi-fpdt.c @@ -25,6 +25,7 @@ #include <string.h> #include <unistd.h> +#include "alloc-util.h" #include "acpi-fpdt.h" #include "fd-util.h" #include "fileio.h" diff --git a/src/shared/apparmor-util.c b/src/shared/apparmor-util.c index c2bbd330bd..f6ac43adfe 100644 --- a/src/shared/apparmor-util.c +++ b/src/shared/apparmor-util.c @@ -19,10 +19,11 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ - -#include "util.h" -#include "fileio.h" +#include "alloc-util.h" #include "apparmor-util.h" +#include "fileio.h" +#include "parse-util.h" +#include "util.h" bool mac_apparmor_use(void) { static int cached_use = -1; diff --git a/src/shared/architecture.c b/src/shared/architecture.c index e5efcd77b6..e2efa4272b 100644 --- a/src/shared/architecture.c +++ b/src/shared/architecture.c @@ -21,6 +21,7 @@ #include <sys/utsname.h> +#include "string-table.h" #include "string-util.h" #include "architecture.h" diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c index 15203d21ea..c96dbf877a 100644 --- a/src/shared/ask-password-api.c +++ b/src/shared/ask-password-api.c @@ -32,8 +32,10 @@ #include <termios.h> #include <unistd.h> +#include "alloc-util.h" #include "ask-password-api.h" #include "fd-util.h" +#include "fileio.h" #include "formats-util.h" #include "io-util.h" #include "missing.h" @@ -44,6 +46,7 @@ #include "string-util.h" #include "strv.h" #include "terminal-util.h" +#include "umask-util.h" #include "util.h" #define KEYRING_TIMEOUT_USEC ((5 * USEC_PER_MINUTE) / 2) diff --git a/src/shared/base-filesystem.c b/src/shared/base-filesystem.c index 751dfdec45..e605490c32 100644 --- a/src/shared/base-filesystem.c +++ b/src/shared/base-filesystem.c @@ -24,12 +24,15 @@ #include <sys/stat.h> #include <unistd.h> +#include "alloc-util.h" +#include "base-filesystem.h" +#include "fd-util.h" #include "log.h" #include "macro.h" #include "string-util.h" +#include "umask-util.h" +#include "user-util.h" #include "util.h" -#include "base-filesystem.h" -#include "fd-util.h" typedef struct BaseFilesystem { const char *dir; diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index e6c5875766..a13991a960 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -25,6 +25,7 @@ #include "sd-daemon.h" #include "sd-event.h" +#include "alloc-util.h" #include "bus-error.h" #include "bus-internal.h" #include "bus-label.h" @@ -37,12 +38,19 @@ #include "fd-util.h" #include "macro.h" #include "missing.h" +#include "parse-util.h" #include "path-util.h" +#include "proc-cmdline.h" +#include "process-util.h" +#include "rlimit-util.h" #include "set.h" #include "signal-util.h" +#include "stdio-util.h" #include "string-util.h" #include "strv.h" +#include "syslog-util.h" #include "unit-name.h" +#include "user-util.h" #include "utf8.h" #include "util.h" @@ -1442,7 +1450,7 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen "SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies", "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "RemainAfterExit", "PrivateTmp", "PrivateDevices", "PrivateNetwork", "NoNewPrivileges", - "SyslogLevelPrefix")) { + "SyslogLevelPrefix", "Delegate")) { r = parse_boolean(eq); if (r < 0) { diff --git a/src/shared/cgroup-show.c b/src/shared/cgroup-show.c index 395e41930c..129ffc7056 100644 --- a/src/shared/cgroup-show.c +++ b/src/shared/cgroup-show.c @@ -24,10 +24,12 @@ #include <stdio.h> #include <string.h> +#include "alloc-util.h" #include "cgroup-show.h" #include "cgroup-util.h" #include "fd-util.h" #include "formats-util.h" +#include "locale-util.h" #include "macro.h" #include "path-util.h" #include "process-util.h" diff --git a/src/shared/clean-ipc.c b/src/shared/clean-ipc.c index fe3187384f..c60f605997 100644 --- a/src/shared/clean-ipc.c +++ b/src/shared/clean-ipc.c @@ -30,10 +30,12 @@ #include "clean-ipc.h" #include "fd-util.h" +#include "fileio.h" #include "formats-util.h" #include "string-util.h" #include "strv.h" #include "util.h" +#include "dirent-util.h" static int clean_sysvipc_shm(uid_t delete_uid) { _cleanup_fclose_ FILE *f = NULL; diff --git a/src/shared/condition.c b/src/shared/condition.c index b8915dab8a..a69719116c 100644 --- a/src/shared/condition.c +++ b/src/shared/condition.c @@ -27,18 +27,25 @@ #include "sd-id128.h" +#include "alloc-util.h" #include "apparmor-util.h" #include "architecture.h" -#include "audit.h" +#include "audit-util.h" #include "cap-list.h" #include "condition.h" #include "extract-word.h" #include "fd-util.h" +#include "glob-util.h" #include "hostname-util.h" #include "ima-util.h" +#include "mount-util.h" +#include "parse-util.h" #include "path-util.h" +#include "proc-cmdline.h" #include "selinux-util.h" #include "smack-util.h" +#include "stat-util.h" +#include "string-table.h" #include "string-util.h" #include "util.h" #include "virt.h" diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c index 1b47c0ab52..3f8eaf7d9a 100644 --- a/src/shared/conf-parser.c +++ b/src/shared/conf-parser.c @@ -26,17 +26,22 @@ #include "sd-messages.h" +#include "alloc-util.h" #include "conf-files.h" +#include "conf-parser.h" +#include "fd-util.h" +#include "fs-util.h" #include "log.h" #include "macro.h" +#include "parse-util.h" #include "path-util.h" +#include "process-util.h" #include "signal-util.h" #include "string-util.h" #include "strv.h" +#include "syslog-util.h" #include "utf8.h" #include "util.h" -#include "conf-parser.h" -#include "fd-util.h" int config_item_table_lookup( const void *table, diff --git a/src/shared/dev-setup.c b/src/shared/dev-setup.c index 25ad918b85..ad3c17d5bd 100644 --- a/src/shared/dev-setup.c +++ b/src/shared/dev-setup.c @@ -23,10 +23,12 @@ #include <stdlib.h> #include <unistd.h> -#include "util.h" +#include "alloc-util.h" +#include "dev-setup.h" #include "label.h" #include "path-util.h" -#include "dev-setup.h" +#include "user-util.h" +#include "util.h" int dev_setup(const char *prefix, uid_t uid, gid_t gid) { static const char symlinks[] = diff --git a/src/shared/dns-domain.c b/src/shared/dns-domain.c index d4df9d2acb..7af15e0098 100644 --- a/src/shared/dns-domain.c +++ b/src/shared/dns-domain.c @@ -24,8 +24,11 @@ #include <stringprep.h> #endif -#include "string-util.h" +#include "alloc-util.h" #include "dns-domain.h" +#include "hexdecoct.h" +#include "parse-util.h" +#include "string-util.h" int dns_label_unescape(const char **name, char *dest, size_t sz) { const char *n; diff --git a/src/shared/dropin.c b/src/shared/dropin.c index 1836e91acd..0d44401cc2 100644 --- a/src/shared/dropin.c +++ b/src/shared/dropin.c @@ -19,12 +19,14 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "conf-files.h" #include "dropin.h" #include "escape.h" #include "fd-util.h" #include "fileio-label.h" #include "mkdir.h" +#include "path-util.h" #include "string-util.h" #include "strv.h" #include "util.h" diff --git a/src/shared/efivars.c b/src/shared/efivars.c index 4808ede60c..86bb0b57c3 100644 --- a/src/shared/efivars.c +++ b/src/shared/efivars.c @@ -23,9 +23,13 @@ #include <string.h> #include <fcntl.h> +#include "alloc-util.h" +#include "dirent-util.h" #include "efivars.h" #include "fd-util.h" #include "io-util.h" +#include "parse-util.h" +#include "stdio-util.h" #include "utf8.h" #include "util.h" #include "virt.h" diff --git a/src/shared/firewall-util.c b/src/shared/firewall-util.c index effc6e8e70..e178287872 100644 --- a/src/shared/firewall-util.c +++ b/src/shared/firewall-util.c @@ -27,8 +27,9 @@ #include <linux/netfilter/xt_addrtype.h> #include <libiptc/libiptc.h> -#include "util.h" +#include "alloc-util.h" #include "firewall-util.h" +#include "util.h" DEFINE_TRIVIAL_CLEANUP_FUNC(struct xtc_handle*, iptc_free); diff --git a/src/shared/fstab-util.c b/src/shared/fstab-util.c index bdfc13e3cd..eb2845cddf 100644 --- a/src/shared/fstab-util.c +++ b/src/shared/fstab-util.c @@ -19,11 +19,15 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" +#include "device-nodes.h" +#include "fstab-util.h" +#include "mount-util.h" +#include "parse-util.h" #include "path-util.h" #include "string-util.h" #include "strv.h" #include "util.h" -#include "fstab-util.h" bool fstab_is_mount_point(const char *mount) { _cleanup_endmntent_ FILE *f = NULL; @@ -195,3 +199,60 @@ int fstab_find_pri(const char *options, int *ret) { *ret = (int) pri; return 1; } + +static char *unquote(const char *s, const char* quotes) { + size_t l; + assert(s); + + /* This is rather stupid, simply removes the heading and + * trailing quotes if there is one. Doesn't care about + * escaping or anything. + * + * DON'T USE THIS FOR NEW CODE ANYMORE!*/ + + l = strlen(s); + if (l < 2) + return strdup(s); + + if (strchr(quotes, s[0]) && s[l-1] == s[0]) + return strndup(s+1, l-2); + + return strdup(s); +} + +static char *tag_to_udev_node(const char *tagvalue, const char *by) { + _cleanup_free_ char *t = NULL, *u = NULL; + size_t enc_len; + + u = unquote(tagvalue, QUOTES); + if (!u) + return NULL; + + enc_len = strlen(u) * 4 + 1; + t = new(char, enc_len); + if (!t) + return NULL; + + if (encode_devnode_name(u, t, enc_len) < 0) + return NULL; + + return strjoin("/dev/disk/by-", by, "/", t, NULL); +} + +char *fstab_node_to_udev_node(const char *p) { + assert(p); + + if (startswith(p, "LABEL=")) + return tag_to_udev_node(p+6, "label"); + + if (startswith(p, "UUID=")) + return tag_to_udev_node(p+5, "uuid"); + + if (startswith(p, "PARTUUID=")) + return tag_to_udev_node(p+9, "partuuid"); + + if (startswith(p, "PARTLABEL=")) + return tag_to_udev_node(p+10, "partlabel"); + + return strdup(p); +} diff --git a/src/shared/fstab-util.h b/src/shared/fstab-util.h index 872b2363cd..5ebea44019 100644 --- a/src/shared/fstab-util.h +++ b/src/shared/fstab-util.h @@ -23,11 +23,12 @@ #include <stdbool.h> #include <stddef.h> + #include "macro.h" bool fstab_is_mount_point(const char *mount); -int fstab_filter_options(const char *opts, const char *names, - const char **namefound, char **value, char **filtered); + +int fstab_filter_options(const char *opts, const char *names, const char **namefound, char **value, char **filtered); int fstab_extract_values(const char *opts, const char *name, char ***values); @@ -49,3 +50,5 @@ static inline bool fstab_test_yes_no_option(const char *opts, const char *yes_no return opt == yes_no; } + +char *fstab_node_to_udev_node(const char *p); diff --git a/src/shared/generator.c b/src/shared/generator.c index 0a8e282949..cb4ebc606e 100644 --- a/src/shared/generator.c +++ b/src/shared/generator.c @@ -21,6 +21,7 @@ #include <unistd.h> +#include "alloc-util.h" #include "dropin.h" #include "escape.h" #include "fd-util.h" @@ -28,6 +29,7 @@ #include "fstab-util.h" #include "generator.h" #include "mkdir.h" +#include "mount-util.h" #include "path-util.h" #include "special.h" #include "string-util.h" diff --git a/src/shared/import-util.c b/src/shared/import-util.c index c4c66c847d..ddc8c00a2d 100644 --- a/src/shared/import-util.c +++ b/src/shared/import-util.c @@ -19,10 +19,13 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "btrfs-util.h" +#include "import-util.h" +#include "path-util.h" +#include "string-table.h" #include "string-util.h" #include "util.h" -#include "import-util.h" int import_url_last_component(const char *url, char **ret) { const char *e, *p; diff --git a/src/shared/install-printf.c b/src/shared/install-printf.c index 224874f65c..e1cb5d27ff 100644 --- a/src/shared/install-printf.c +++ b/src/shared/install-printf.c @@ -21,6 +21,7 @@ #include <stdlib.h> +#include "alloc-util.h" #include "formats-util.h" #include "install-printf.h" #include "specifier.h" diff --git a/src/shared/install.c b/src/shared/install.c index 9b72f76662..b7d1d22505 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -25,21 +25,26 @@ #include <string.h> #include <unistd.h> +#include "alloc-util.h" #include "conf-files.h" #include "conf-parser.h" +#include "dirent-util.h" +#include "fd-util.h" +#include "fs-util.h" #include "hashmap.h" #include "install-printf.h" +#include "install.h" #include "mkdir.h" #include "path-lookup.h" #include "path-util.h" #include "set.h" #include "special.h" +#include "stat-util.h" +#include "string-table.h" #include "string-util.h" #include "strv.h" #include "unit-name.h" #include "util.h" -#include "install.h" -#include "fd-util.h" typedef struct { OrderedHashmap *will_install; @@ -48,13 +53,12 @@ typedef struct { static int in_search_path(const char *path, char **search) { _cleanup_free_ char *parent = NULL; - int r; assert(path); - r = path_get_parent(path, &parent); - if (r < 0) - return r; + parent = dirname_malloc(path); + if (!parent) + return -ENOMEM; return strv_contains(search, parent); } @@ -925,8 +929,6 @@ static int config_parse_also( void *data, void *userdata) { - size_t l; - const char *word, *state; InstallContext *c = data; UnitFileInstallInfo *i = userdata; @@ -934,13 +936,18 @@ static int config_parse_also( assert(lvalue); assert(rvalue); - FOREACH_WORD_QUOTED(word, l, rvalue, state) { - _cleanup_free_ char *n; + for(;;) { + _cleanup_free_ char *n = NULL; int r; - n = strndup(word, l); - if (!n) - return -ENOMEM; + r = extract_first_word(&rvalue, &n, NULL, 0); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse config %s, ignoring.", rvalue); + return 0; + } + + if (r == 0) + break; r = install_info_add(c, n, NULL); if (r < 0) @@ -950,8 +957,6 @@ static int config_parse_also( if (r < 0) return r; } - if (!isempty(state)) - log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring."); return 0; } diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c index d8ea4c9f92..0313b0946f 100644 --- a/src/shared/logs-show.c +++ b/src/shared/logs-show.c @@ -25,6 +25,7 @@ #include <sys/socket.h> #include <time.h> +#include "alloc-util.h" #include "fd-util.h" #include "formats-util.h" #include "hashmap.h" @@ -33,7 +34,9 @@ #include "journal-internal.h" #include "log.h" #include "logs-show.h" +#include "parse-util.h" #include "process-util.h" +#include "string-table.h" #include "string-util.h" #include "terminal-util.h" #include "utf8.h" diff --git a/src/shared/machine-image.c b/src/shared/machine-image.c index 415d939fc6..2c1da0a40d 100644 --- a/src/shared/machine-image.c +++ b/src/shared/machine-image.c @@ -23,16 +23,22 @@ #include <linux/fs.h> #include <sys/statfs.h> +#include "alloc-util.h" #include "btrfs-util.h" +#include "chattr-util.h" #include "copy.h" +#include "dirent-util.h" #include "fd-util.h" +#include "fs-util.h" #include "machine-image.h" #include "mkdir.h" #include "path-util.h" #include "rm-rf.h" +#include "string-table.h" #include "string-util.h" #include "strv.h" #include "utf8.h" +#include "xattr-util.h" static const char image_search_path[] = "/var/lib/machines\0" diff --git a/src/shared/machine-pool.c b/src/shared/machine-pool.c index a2cb5fc5a0..60b1b3092d 100644 --- a/src/shared/machine-pool.c +++ b/src/shared/machine-pool.c @@ -24,14 +24,20 @@ #include <sys/statvfs.h> #include <sys/vfs.h> +#include "alloc-util.h" #include "btrfs-util.h" #include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" #include "lockfile-util.h" #include "machine-pool.h" #include "mkdir.h" +#include "mount-util.h" +#include "parse-util.h" #include "path-util.h" #include "process-util.h" #include "signal-util.h" +#include "stat-util.h" #include "string-util.h" #include "util.h" diff --git a/src/shared/pager.c b/src/shared/pager.c index 7029d6b2e2..d149bc1722 100644 --- a/src/shared/pager.c +++ b/src/shared/pager.c @@ -27,6 +27,7 @@ #include "copy.h" #include "fd-util.h" +#include "locale-util.h" #include "macro.h" #include "pager.h" #include "process-util.h" diff --git a/src/shared/path-lookup.c b/src/shared/path-lookup.c index 1e63c72047..d71f379e76 100644 --- a/src/shared/path-lookup.c +++ b/src/shared/path-lookup.c @@ -24,6 +24,7 @@ #include <string.h> #include <errno.h> +#include "alloc-util.h" #include "util.h" #include "strv.h" #include "path-util.h" diff --git a/src/shared/ptyfwd.c b/src/shared/ptyfwd.c index e5e0f37adf..63e81f4894 100644 --- a/src/shared/ptyfwd.c +++ b/src/shared/ptyfwd.c @@ -24,6 +24,7 @@ #include <limits.h> #include <termios.h> +#include "alloc-util.h" #include "fd-util.h" #include "ptyfwd.h" #include "util.h" @@ -412,6 +413,7 @@ PTYForward *pty_forward_free(PTYForward *f) { sd_event_source_unref(f->stdin_event_source); sd_event_source_unref(f->stdout_event_source); sd_event_source_unref(f->master_event_source); + sd_event_source_unref(f->sigwinch_event_source); sd_event_unref(f->event); if (f->saved_stdout) diff --git a/src/shared/sleep-config.c b/src/shared/sleep-config.c index b5cb9508bf..bbbb3460d4 100644 --- a/src/shared/sleep-config.c +++ b/src/shared/sleep-config.c @@ -21,6 +21,7 @@ #include <stdio.h> +#include "alloc-util.h" #include "conf-parser.h" #include "fd-util.h" #include "fileio.h" @@ -29,6 +30,7 @@ #include "string-util.h" #include "strv.h" #include "util.h" +#include "parse-util.h" #define USE(x, y) do{ (x) = (y); (y) = NULL; } while(0) diff --git a/src/shared/spawn-polkit-agent.c b/src/shared/spawn-polkit-agent.c index 7cc9e7ccc1..ec6e5a8312 100644 --- a/src/shared/spawn-polkit-agent.c +++ b/src/shared/spawn-polkit-agent.c @@ -30,6 +30,7 @@ #include "log.h" #include "process-util.h" #include "spawn-polkit-agent.h" +#include "stdio-util.h" #include "util.h" #ifdef ENABLE_POLKIT @@ -78,8 +79,9 @@ void polkit_agent_close(void) { return; /* Inform agent that we are done */ - kill(agent_pid, SIGTERM); - kill(agent_pid, SIGCONT); + (void) kill(agent_pid, SIGTERM); + (void) kill(agent_pid, SIGCONT); + (void) wait_for_terminate(agent_pid, NULL); agent_pid = 0; } diff --git a/src/shared/specifier.c b/src/shared/specifier.c index 610aec0df5..c5c4a4d7d7 100644 --- a/src/shared/specifier.c +++ b/src/shared/specifier.c @@ -22,11 +22,12 @@ #include <string.h> #include <sys/utsname.h> +#include "alloc-util.h" #include "hostname-util.h" #include "macro.h" +#include "specifier.h" #include "string-util.h" #include "util.h" -#include "specifier.h" /* * Generic infrastructure for replacing %x style specifiers in diff --git a/src/shared/switch-root.c b/src/shared/switch-root.c index 60d7043fda..fc885f6cb8 100644 --- a/src/shared/switch-root.c +++ b/src/shared/switch-root.c @@ -35,6 +35,7 @@ #include "rm-rf.h" #include "string-util.h" #include "switch-root.h" +#include "user-util.h" #include "util.h" int switch_root(const char *new_root, const char *oldroot, bool detach_oldroot, unsigned long mountflags) { diff --git a/src/shared/utmp-wtmp.c b/src/shared/utmp-wtmp.c index 1e6ac2f27d..13b32a0509 100644 --- a/src/shared/utmp-wtmp.c +++ b/src/shared/utmp-wtmp.c @@ -27,6 +27,7 @@ #include <unistd.h> #include <utmpx.h> +#include "alloc-util.h" #include "fd-util.h" #include "hostname-util.h" #include "macro.h" diff --git a/src/socket-proxy/socket-proxyd.c b/src/socket-proxy/socket-proxyd.c index e82fb06417..ba82adadb4 100644 --- a/src/socket-proxy/socket-proxyd.c +++ b/src/socket-proxy/socket-proxyd.c @@ -34,6 +34,7 @@ #include "sd-event.h" #include "sd-resolve.h" +#include "alloc-util.h" #include "fd-util.h" #include "log.h" #include "path-util.h" diff --git a/src/system-update-generator/system-update-generator.c b/src/system-update-generator/system-update-generator.c index 794aa1a0c7..6c2f53774d 100644 --- a/src/system-update-generator/system-update-generator.c +++ b/src/system-update-generator/system-update-generator.c @@ -22,6 +22,7 @@ #include <errno.h> #include <unistd.h> +#include "fs-util.h" #include "log.h" #include "string-util.h" #include "util.h" diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index fe4213c085..70871cf3e6 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -37,6 +37,7 @@ #include "sd-daemon.h" #include "sd-login.h" +#include "alloc-util.h" #include "bus-common-errors.h" #include "bus-error.h" #include "bus-message.h" @@ -51,25 +52,31 @@ #include "fd-util.h" #include "fileio.h" #include "formats-util.h" +#include "fs-util.h" +#include "glob-util.h" #include "hostname-util.h" #include "initreq.h" #include "install.h" #include "io-util.h" #include "list.h" +#include "locale-util.h" #include "log.h" #include "logs-show.h" #include "macro.h" #include "mkdir.h" #include "pager.h" +#include "parse-util.h" #include "path-lookup.h" #include "path-util.h" #include "process-util.h" +#include "rlimit-util.h" #include "set.h" #include "signal-util.h" #include "socket-util.h" #include "spawn-ask-password-agent.h" #include "spawn-polkit-agent.h" #include "special.h" +#include "stat-util.h" #include "strv.h" #include "terminal-util.h" #include "unit-name.h" @@ -77,6 +84,7 @@ #include "util.h" #include "utmp-wtmp.h" #include "verbs.h" +#include "virt.h" static char **arg_types = NULL; static char **arg_states = NULL; @@ -288,6 +296,10 @@ static bool install_client_side(void) { if (arg_scope == UNIT_FILE_GLOBAL) return true; + /* Unsupported environment variable, mostly for debugging purposes */ + if (getenv_bool("SYSTEMCTL_INSTALL_CLIENT_SIDE") > 0) + return true; + return false; } @@ -3478,7 +3490,8 @@ static void print_status_info( dir = mfree(dir); - if (path_get_parent(*dropin, &dir) < 0) { + dir = dirname_malloc(*dropin); + if (!dir) { log_oom(); return; } @@ -5308,6 +5321,9 @@ static int enable_sysv_units(const char *verb, char **args) { if (arg_scope != UNIT_FILE_SYSTEM) return 0; + if (getenv_bool("SYSTEMCTL_SKIP_SYSV") > 0) + return 0; + if (!STR_IN_SET(verb, "enable", "disable", @@ -6615,6 +6631,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) { {} }; + const char *p; int c, r; assert(argc >= 0); @@ -6635,15 +6652,19 @@ static int systemctl_parse_argv(int argc, char *argv[]) { return version(); case 't': { - const char *word, *state; - size_t size; + if (isempty(optarg)) + return log_error_errno(r, "--type requires arguments."); - FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) { - _cleanup_free_ char *type; + p = optarg; + for(;;) { + _cleanup_free_ char *type = NULL; - type = strndup(word, size); - if (!type) - return -ENOMEM; + r = extract_first_word(&p, &type, ",", 0); + if (r < 0) + return log_error_errno(r, "Failed to parse type: %s", optarg); + + if (r == 0) + break; if (streq(type, "help")) { help_types(); @@ -6684,18 +6705,21 @@ static int systemctl_parse_argv(int argc, char *argv[]) { if (!arg_properties) return log_oom(); } else { - const char *word, *state; - size_t size; + p = optarg; + for(;;) { + _cleanup_free_ char *prop = NULL; - FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) { - char *prop; + r = extract_first_word(&p, &prop, ",", 0); + if (r < 0) + return log_error_errno(r, "Failed to parse property: %s", optarg); - prop = strndup(word, size); - if (!prop) - return log_oom(); + if (r == 0) + break; - if (strv_consume(&arg_properties, prop) < 0) + if (strv_push(&arg_properties, prop) < 0) return log_oom(); + + prop = NULL; } } @@ -6861,15 +6885,19 @@ static int systemctl_parse_argv(int argc, char *argv[]) { break; case ARG_STATE: { - const char *word, *state; - size_t size; + if (isempty(optarg)) + return log_error_errno(r, "--signal requires arguments."); - FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) { + p = optarg; + for(;;) { _cleanup_free_ char *s = NULL; - s = strndup(word, size); - if (!s) - return log_oom(); + r = extract_first_word(&p, &s, ",", 0); + if (r < 0) + return log_error_errno(r, "Failed to parse signal: %s", optarg); + + if (r == 0) + break; if (streq(s, "help")) { help_states(); diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c index 177432bf9f..36d310b4c4 100644 --- a/src/sysusers/sysusers.c +++ b/src/sysusers/sysusers.c @@ -26,6 +26,7 @@ #include <shadow.h> #include <utmp.h> +#include "alloc-util.h" #include "conf-files.h" #include "copy.h" #include "fileio-label.h" @@ -1859,7 +1860,7 @@ int main(int argc, char *argv[]) { if (r < 0) goto finish; - lock = take_password_lock(arg_root); + lock = take_etc_passwd_lock(arg_root); if (lock < 0) { log_error_errno(lock, "Failed to take lock: %m"); goto finish; diff --git a/src/sysv-generator/sysv-generator.c b/src/sysv-generator/sysv-generator.c index 3374456973..b2d53d3b4f 100644 --- a/src/sysv-generator/sysv-generator.c +++ b/src/sysv-generator/sysv-generator.c @@ -25,8 +25,12 @@ #include <stdio.h> #include <unistd.h> +#include "alloc-util.h" +#include "dirent-util.h" #include "fd-util.h" +#include "fileio.h" #include "hashmap.h" +#include "hexdecoct.h" #include "install.h" #include "log.h" #include "mkdir.h" @@ -34,6 +38,7 @@ #include "path-util.h" #include "set.h" #include "special.h" +#include "stat-util.h" #include "string-util.h" #include "strv.h" #include "unit-name.h" @@ -82,9 +87,13 @@ typedef struct SysvStub { char **conflicts; bool has_lsb; bool reload; + bool loaded; } SysvStub; static void free_sysvstub(SysvStub *s) { + if (!s) + return; + free(s->name); free(s->path); free(s->description); @@ -109,19 +118,14 @@ static void free_sysvstub_hashmapp(Hashmap **h) { } static int add_symlink(const char *service, const char *where) { - _cleanup_free_ char *from = NULL, *to = NULL; + const char *from, *to; int r; assert(service); assert(where); - from = strjoin(arg_dest, "/", service, NULL); - if (!from) - return log_oom(); - - to = strjoin(arg_dest, "/", where, ".wants/", service, NULL); - if (!to) - return log_oom(); + from = strjoina(arg_dest, "/", service); + to = strjoina(arg_dest, "/", where, ".wants/", service); mkdir_parents_label(to, 0755); @@ -129,6 +133,7 @@ static int add_symlink(const char *service, const char *where) { if (r < 0) { if (errno == EEXIST) return 0; + return -errno; } @@ -136,20 +141,19 @@ static int add_symlink(const char *service, const char *where) { } static int add_alias(const char *service, const char *alias) { - _cleanup_free_ char *link = NULL; + const char *link; int r; assert(service); assert(alias); - link = strjoin(arg_dest, "/", alias, NULL); - if (!link) - return log_oom(); + link = strjoina(arg_dest, "/", alias); r = symlink(service, link); if (r < 0) { if (errno == EEXIST) return 0; + return -errno; } @@ -157,26 +161,32 @@ static int add_alias(const char *service, const char *alias) { } static int generate_unit_file(SysvStub *s) { - char **p; + _cleanup_free_ char *before = NULL, *after = NULL, *wants = NULL, *conflicts = NULL; _cleanup_fclose_ FILE *f = NULL; - _cleanup_free_ char *unit = NULL, - *before = NULL, *after = NULL, - *wants = NULL, *conflicts = NULL; + const char *unit; + char **p; int r; + assert(s); + + if (!s->loaded) + return 0; + + unit = strjoina(arg_dest, "/", s->name); + before = strv_join(s->before, " "); after = strv_join(s->after, " "); wants = strv_join(s->wants, " "); conflicts = strv_join(s->conflicts, " "); - unit = strjoin(arg_dest, "/", s->name, NULL); - if (!before || !after || !wants || !conflicts || !unit) + + if (!before || !after || !wants || !conflicts) return log_oom(); /* We might already have a symlink with the same name from a Provides:, * or from backup files like /etc/init.d/foo.bak. Real scripts always win, * so remove an existing link */ if (is_symlink(unit) > 0) { - log_warning("Overwriting existing symlink %s with real service", unit); + log_warning("Overwriting existing symlink %s with real service.", unit); (void) unlink(unit); } @@ -188,9 +198,11 @@ static int generate_unit_file(SysvStub *s) { "# Automatically generated by systemd-sysv-generator\n\n" "[Unit]\n" "Documentation=man:systemd-sysv-generator(8)\n" - "SourcePath=%s\n" - "Description=%s\n", - s->path, s->description); + "SourcePath=%s\n", + s->path); + + if (s->description) + fprintf(f, "Description=%s\n", s->description); if (!isempty(before)) fprintf(f, "Before=%s\n", before); @@ -223,13 +235,17 @@ static int generate_unit_file(SysvStub *s) { if (s->reload) fprintf(f, "ExecReload=%s reload\n", s->path); + r = fflush_and_check(f); + if (r < 0) + return log_error_errno(r, "Failed to write unit %s: %m", unit); + STRV_FOREACH(p, s->wanted_by) { r = add_symlink(s->name, *p); if (r < 0) - log_error_errno(r, "Failed to create 'Wants' symlink to %s: %m", *p); + log_warning_errno(r, "Failed to create 'Wants' symlink to %s, ignoring: %m", *p); } - return 0; + return 1; } static bool usage_contains_reload(const char *line) { @@ -259,7 +275,7 @@ static char *sysv_translate_name(const char *name) { return res; } -static int sysv_translate_facility(const char *name, const char *filename, char **_r) { +static int sysv_translate_facility(const char *name, const char *filename, char **ret) { /* We silently ignore the $ prefix here. According to the LSB * spec it simply indicates whether something is a @@ -278,31 +294,45 @@ static int sysv_translate_facility(const char *name, const char *filename, char "time", SPECIAL_TIME_SYNC_TARGET, }; - char *filename_no_sh, *e, *r; + char *filename_no_sh, *e, *m; const char *n; unsigned i; + int r; assert(name); - assert(_r); + assert(filename); + assert(ret); n = *name == '$' ? name + 1 : name; for (i = 0; i < ELEMENTSOF(table); i += 2) { - if (!streq(table[i], n)) continue; if (!table[i+1]) return 0; - r = strdup(table[i+1]); - if (!r) + m = strdup(table[i+1]); + if (!m) return log_oom(); - goto finish; + *ret = m; + return 1; + } + + /* If we don't know this name, fallback heuristics to figure + * out whether something is a target or a service alias. */ + + /* Facilities starting with $ are most likely targets */ + if (*name == '$') { + r = unit_name_build(n, NULL, ".target", ret); + if (r < 0) + return log_error_errno(r, "Failed to build name: %m"); + + return r; } - /* strip ".sh" suffix from file name for comparison */ + /* Strip ".sh" suffix from file name for comparison */ filename_no_sh = strdupa(filename); e = endswith(filename_no_sh, ".sh"); if (e) { @@ -310,103 +340,103 @@ static int sysv_translate_facility(const char *name, const char *filename, char filename = filename_no_sh; } - /* If we don't know this name, fallback heuristics to figure - * out whether something is a target or a service alias. */ - - if (*name == '$') { - int k; - - /* Facilities starting with $ are most likely targets */ - k = unit_name_build(n, NULL, ".target", &r); - if (k < 0) - return k; - - } else if (streq_ptr(n, filename)) - /* Names equaling the file name of the services are redundant */ + /* Names equaling the file name of the services are redundant */ + if (streq_ptr(n, filename)) return 0; - else - /* Everything else we assume to be normal service names */ - r = sysv_translate_name(n); - if (!r) - return -ENOMEM; -finish: - *_r = r; + /* Everything else we assume to be normal service names */ + m = sysv_translate_name(n); + if (!m) + return log_oom(); + *ret = m; return 1; } static int handle_provides(SysvStub *s, unsigned line, const char *full_text, const char *text) { - const char *word, *state_; - size_t z; int r; - FOREACH_WORD_QUOTED(word, z, text, state_) { - _cleanup_free_ char *n = NULL, *m = NULL; - UnitType t; + assert(s); + assert(full_text); + assert(text); - n = strndup(word, z); - if (!n) - return log_oom(); + for (;;) { + _cleanup_free_ char *word = NULL, *m = NULL; - r = sysv_translate_facility(n, basename(s->path), &m); + r = extract_first_word(&text, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX); if (r < 0) - return r; + return log_error_errno(r, "Failed to parse word from provides string: %m"); if (r == 0) + break; + + r = sysv_translate_facility(word, basename(s->path), &m); + if (r <= 0) /* continue on error */ continue; - t = unit_name_to_type(m); - if (t == UNIT_SERVICE) { + switch (unit_name_to_type(m)) { + + case UNIT_SERVICE: log_debug("Adding Provides: alias '%s' for '%s'", m, s->name); r = add_alias(s->name, m); if (r < 0) log_warning_errno(r, "[%s:%u] Failed to add LSB Provides name %s, ignoring: %m", s->path, line, m); - } else if (t == UNIT_TARGET) { + break; + + case UNIT_TARGET: + /* NB: SysV targets which are provided by a * service are pulled in by the services, as * an indication that the generic service is * now available. This is strictly one-way. * The targets do NOT pull in SysV services! */ + r = strv_extend(&s->before, m); if (r < 0) return log_oom(); + r = strv_extend(&s->wants, m); if (r < 0) return log_oom(); + if (streq(m, SPECIAL_NETWORK_ONLINE_TARGET)) { r = strv_extend(&s->before, SPECIAL_NETWORK_TARGET); if (r < 0) return log_oom(); } - } else if (t == _UNIT_TYPE_INVALID) + + break; + + case _UNIT_TYPE_INVALID: log_warning("Unit name '%s' is invalid", m); - else + break; + + default: log_warning("Unknown unit type for unit '%s'", m); + } } - if (!isempty(state_)) - log_error("[%s:%u] Trailing garbage in Provides, ignoring.", s->path, line); + return 0; } static int handle_dependencies(SysvStub *s, unsigned line, const char *full_text, const char *text) { - const char *word, *state_; - size_t z; int r; - FOREACH_WORD_QUOTED(word, z, text, state_) { - _cleanup_free_ char *n = NULL, *m = NULL; - bool is_before; + assert(s); + assert(full_text); + assert(text); - n = strndup(word, z); - if (!n) - return log_oom(); + for (;;) { + _cleanup_free_ char *word = NULL, *m = NULL; + bool is_before; - r = sysv_translate_facility(n, basename(s->path), &m); - if (r < 0) { - log_warning_errno(r, "[%s:%u] Failed to translate LSB dependency %s, ignoring: %m", s->path, line, n); - continue; - } + r = extract_first_word(&text, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX); + if (r < 0) + return log_error_errno(r, "Failed to parse word from provides string: %m"); if (r == 0) + break; + + r = sysv_translate_facility(word, basename(s->path), &m); + if (r <= 0) /* continue on error */ continue; is_before = startswith_no_case(full_text, "X-Start-Before:"); @@ -416,15 +446,14 @@ static int handle_dependencies(SysvStub *s, unsigned line, const char *full_text r = strv_extend(&s->after, m); if (r < 0) return log_oom(); + r = strv_extend(&s->wants, m); } else r = strv_extend(is_before ? &s->before : &s->after, m); - if (r < 0) return log_oom(); } - if (!isempty(state_)) - log_warning("[%s:%u] Trailing garbage in %*s, ignoring.", s->path, line, (int)(strchr(full_text, ':') - full_text), full_text); + return 0; } @@ -442,24 +471,22 @@ static int load_sysv(SysvStub *s) { _cleanup_free_ char *short_description = NULL, *long_description = NULL, *chkconfig_description = NULL; char *description; bool supports_reload = false; + char l[LINE_MAX]; assert(s); f = fopen(s->path, "re"); - if (!f) - return errno == ENOENT ? 0 : -errno; + if (!f) { + if (errno == ENOENT) + return 0; - log_debug("Loading SysV script %s", s->path); + return log_error_errno(errno, "Failed to open %s: %m", s->path); + } - while (!feof(f)) { - char l[LINE_MAX], *t; + log_debug("Loading SysV script %s", s->path); - if (!fgets(l, sizeof(l), f)) { - if (feof(f)) - break; - - return log_error_errno(errno, "Failed to read configuration file '%s': %m", s->path); - } + FOREACH_LINE(l, f, goto fail) { + char *t; line++; @@ -502,29 +529,25 @@ static int load_sysv(SysvStub *s) { if (startswith_no_case(t, "description:")) { - size_t k = strlen(t); - char *d; - const char *j; + size_t k; + const const char *j; - if (t[k-1] == '\\') { + k = strlen(t); + if (k > 0 && t[k-1] == '\\') { state = DESCRIPTION; t[k-1] = 0; } j = strstrip(t+12); - if (j && *j) { - d = strdup(j); - if (!d) - return -ENOMEM; - } else - d = NULL; + if (isempty(j)) + j = NULL; - free(chkconfig_description); - chkconfig_description = d; + r = free_and_strdup(&chkconfig_description, j); + if (r < 0) + return log_oom(); } else if (startswith_no_case(t, "pidfile:")) { - - char *fn; + const char *fn; state = NORMAL; @@ -534,12 +557,9 @@ static int load_sysv(SysvStub *s) { continue; } - fn = strdup(fn); - if (!fn) - return -ENOMEM; - - free(s->pid_file); - s->pid_file = fn; + r = free_and_strdup(&s->pid_file, fn); + if (r < 0) + return log_oom(); } } else if (state == DESCRIPTION) { @@ -547,25 +567,25 @@ static int load_sysv(SysvStub *s) { /* Try to parse Red Hat style description * continuation */ - size_t k = strlen(t); + size_t k; char *j; - if (t[k-1] == '\\') + k = strlen(t); + if (k > 0 && t[k-1] == '\\') t[k-1] = 0; else state = NORMAL; j = strstrip(t); - if (j && *j) { + if (!isempty(j)) { char *d = NULL; if (chkconfig_description) d = strjoin(chkconfig_description, " ", j, NULL); else d = strdup(j); - if (!d) - return -ENOMEM; + return log_oom(); free(chkconfig_description); chkconfig_description = d; @@ -579,6 +599,7 @@ static int load_sysv(SysvStub *s) { r = handle_provides(s, line, t, t + 9); if (r < 0) return r; + } else if (startswith_no_case(t, "Required-Start:") || startswith_no_case(t, "Should-Start:") || startswith_no_case(t, "X-Start-Before:") || @@ -590,55 +611,47 @@ static int load_sysv(SysvStub *s) { if (r < 0) return r; - } else if (startswith_no_case(t, "Description:")) { - char *d, *j; + const char *j; state = LSB_DESCRIPTION; j = strstrip(t+12); - if (j && *j) { - d = strdup(j); - if (!d) - return -ENOMEM; - } else - d = NULL; + if (isempty(j)) + j = NULL; - free(long_description); - long_description = d; + r = free_and_strdup(&long_description, j); + if (r < 0) + return log_oom(); } else if (startswith_no_case(t, "Short-Description:")) { - char *d, *j; + const char *j; state = LSB; j = strstrip(t+18); - if (j && *j) { - d = strdup(j); - if (!d) - return -ENOMEM; - } else - d = NULL; + if (isempty(j)) + j = NULL; - free(short_description); - short_description = d; + r = free_and_strdup(&short_description, j); + if (r < 0) + return log_oom(); } else if (state == LSB_DESCRIPTION) { if (startswith(l, "#\t") || startswith(l, "# ")) { - char *j; + const char *j; j = strstrip(t); - if (j && *j) { + if (!isempty(j)) { char *d = NULL; if (long_description) d = strjoin(long_description, " ", t, NULL); else d = strdup(j); - if (!d) - return -ENOMEM; + return log_oom(); free(long_description); long_description = d; @@ -669,12 +682,16 @@ static int load_sysv(SysvStub *s) { d = strappend(s->has_lsb ? "LSB: " : "SYSV: ", description); if (!d) - return -ENOMEM; + return log_oom(); s->description = d; } + s->loaded = true; return 0; + +fail: + return log_error_errno(errno, "Failed to read configuration file '%s': %m", s->path); } static int fix_order(SysvStub *s, Hashmap *all_services) { @@ -684,6 +701,9 @@ static int fix_order(SysvStub *s, Hashmap *all_services) { assert(s); + if (!s->loaded) + return 0; + if (s->sysv_start_priority < 0) return 0; @@ -691,6 +711,9 @@ static int fix_order(SysvStub *s, Hashmap *all_services) { if (s == other) continue; + if (!other->loaded) + continue; + if (other->sysv_start_priority < 0) continue; @@ -703,13 +726,12 @@ static int fix_order(SysvStub *s, Hashmap *all_services) { r = strv_extend(&s->after, other->name); if (r < 0) return log_oom(); - } - else if (other->sysv_start_priority > s->sysv_start_priority) { + + } else if (other->sysv_start_priority > s->sysv_start_priority) { r = strv_extend(&s->before, other->name); if (r < 0) return log_oom(); - } - else + } else continue; /* FIXME: Maybe we should compare the name here lexicographically? */ @@ -721,6 +743,9 @@ static int fix_order(SysvStub *s, Hashmap *all_services) { static int enumerate_sysv(const LookupPaths *lp, Hashmap *all_services) { char **path; + assert(lp); + assert(all_services); + STRV_FOREACH(path, lp->sysvinit_path) { _cleanup_closedir_ DIR *d = NULL; struct dirent *de; @@ -728,21 +753,18 @@ static int enumerate_sysv(const LookupPaths *lp, Hashmap *all_services) { d = opendir(*path); if (!d) { if (errno != ENOENT) - log_warning_errno(errno, "opendir(%s) failed: %m", *path); + log_warning_errno(errno, "Opening %s failed, ignoring: %m", *path); continue; } - while ((de = readdir(d))) { + FOREACH_DIRENT(de, d, log_error_errno(errno, "Failed to enumerate directory %s, ignoring: %m", *path)) { _cleanup_free_ char *fpath = NULL, *name = NULL; _cleanup_(free_sysvstubp) SysvStub *service = NULL; struct stat st; int r; - if (hidden_file(de->d_name)) - continue; - if (fstatat(dirfd(d), de->d_name, &st, 0) < 0) { - log_warning_errno(errno, "stat() failed on %s/%s: %m", *path, de->d_name); + log_warning_errno(errno, "stat() failed on %s/%s, ignoring: %m", *path, de->d_name); continue; } @@ -759,15 +781,15 @@ static int enumerate_sysv(const LookupPaths *lp, Hashmap *all_services) { if (hashmap_contains(all_services, name)) continue; - fpath = strjoin(*path, "/", de->d_name, NULL); - if (!fpath) - return log_oom(); - if (unit_file_lookup_state(UNIT_FILE_SYSTEM, NULL, lp, name) >= 0) { log_debug("Native unit for %s already exists, skipping", name); continue; } + fpath = strjoin(*path, "/", de->d_name, NULL); + if (!fpath) + return log_oom(); + service = new0(SysvStub, 1); if (!service) return log_oom(); @@ -775,12 +797,12 @@ static int enumerate_sysv(const LookupPaths *lp, Hashmap *all_services) { service->sysv_start_priority = -1; service->name = name; service->path = fpath; + name = fpath = NULL; r = hashmap_put(all_services, service->name, service); if (r < 0) return log_oom(); - name = fpath = NULL; service = NULL; } } @@ -789,43 +811,41 @@ static int enumerate_sysv(const LookupPaths *lp, Hashmap *all_services) { } static int set_dependencies_from_rcnd(const LookupPaths *lp, Hashmap *all_services) { - char **p; - unsigned i; - _cleanup_closedir_ DIR *d = NULL; - _cleanup_free_ char *path = NULL, *fpath = NULL; - SysvStub *service; - Iterator j; Set *runlevel_services[ELEMENTSOF(rcnd_table)] = {}; _cleanup_set_free_ Set *shutdown_services = NULL; - int r = 0; + SysvStub *service; + unsigned i; + Iterator j; + char **p; + int r; - STRV_FOREACH(p, lp->sysvrcnd_path) + assert(lp); + + STRV_FOREACH(p, lp->sysvrcnd_path) { for (i = 0; i < ELEMENTSOF(rcnd_table); i ++) { + + _cleanup_closedir_ DIR *d = NULL; + _cleanup_free_ char *path = NULL; struct dirent *de; - free(path); path = strjoin(*p, "/", rcnd_table[i].path, NULL); - if (!path) - return -ENOMEM; - - safe_closedir(d); + if (!path) { + r = log_oom(); + goto finish; + } d = opendir(path); if (!d) { if (errno != ENOENT) - log_warning_errno(errno, "opendir(%s) failed: %m", path); + log_warning_errno(errno, "Opening %s failed, ignoring: %m", path); continue; } - while ((de = readdir(d))) { - _cleanup_free_ char *name = NULL; - + FOREACH_DIRENT(de, d, log_error_errno(errno, "Failed to enumerate directory %s, ignoring: %m", path)) { + _cleanup_free_ char *name = NULL, *fpath = NULL; int a, b; - if (hidden_file(de->d_name)) - continue; - if (de->d_name[0] != 'S' && de->d_name[0] != 'K') continue; @@ -838,10 +858,9 @@ static int set_dependencies_from_rcnd(const LookupPaths *lp, Hashmap *all_servic if (a < 0 || b < 0) continue; - free(fpath); fpath = strjoin(*p, "/", de->d_name, NULL); if (!fpath) { - r = -ENOMEM; + r = log_oom(); goto finish; } @@ -853,64 +872,77 @@ static int set_dependencies_from_rcnd(const LookupPaths *lp, Hashmap *all_servic service = hashmap_get(all_services, name); if (!service){ - log_debug("Ignoring %s symlink in %s, not generating %s.", - de->d_name, rcnd_table[i].path, name); + log_debug("Ignoring %s symlink in %s, not generating %s.", de->d_name, rcnd_table[i].path, name); continue; } if (de->d_name[0] == 'S') { - if (rcnd_table[i].type == RUNLEVEL_UP) { - service->sysv_start_priority = - MAX(a*10 + b, service->sysv_start_priority); - } + if (rcnd_table[i].type == RUNLEVEL_UP) + service->sysv_start_priority = MAX(a*10 + b, service->sysv_start_priority); r = set_ensure_allocated(&runlevel_services[i], NULL); - if (r < 0) + if (r < 0) { + log_oom(); goto finish; + } r = set_put(runlevel_services[i], service); - if (r < 0) + if (r < 0) { + log_oom(); goto finish; + } } else if (de->d_name[0] == 'K' && (rcnd_table[i].type == RUNLEVEL_DOWN)) { r = set_ensure_allocated(&shutdown_services, NULL); - if (r < 0) + if (r < 0) { + log_oom(); goto finish; + } r = set_put(shutdown_services, service); - if (r < 0) + if (r < 0) { + log_oom(); goto finish; + } } } } + } for (i = 0; i < ELEMENTSOF(rcnd_table); i ++) SET_FOREACH(service, runlevel_services[i], j) { r = strv_extend(&service->before, rcnd_table[i].target); - if (r < 0) - return log_oom(); + if (r < 0) { + log_oom(); + goto finish; + } r = strv_extend(&service->wanted_by, rcnd_table[i].target); - if (r < 0) - return log_oom(); + if (r < 0) { + log_oom(); + goto finish; + } } SET_FOREACH(service, shutdown_services, j) { r = strv_extend(&service->before, SPECIAL_SHUTDOWN_TARGET); - if (r < 0) - return log_oom(); + if (r < 0) { + log_oom(); + goto finish; + } r = strv_extend(&service->conflicts, SPECIAL_SHUTDOWN_TARGET); - if (r < 0) - return log_oom(); + if (r < 0) { + log_oom(); + goto finish; + } } r = 0; finish: - for (i = 0; i < ELEMENTSOF(rcnd_table); i++) set_free(runlevel_services[i]); @@ -918,11 +950,11 @@ finish: } int main(int argc, char *argv[]) { - int r, q; - _cleanup_lookup_paths_free_ LookupPaths lp = {}; _cleanup_(free_sysvstub_hashmapp) Hashmap *all_services = NULL; + _cleanup_lookup_paths_free_ LookupPaths lp = {}; SysvStub *service; Iterator j; + int r; if (argc > 1 && argc != 4) { log_error("This program takes three or no arguments."); @@ -940,43 +972,34 @@ int main(int argc, char *argv[]) { r = lookup_paths_init(&lp, MANAGER_SYSTEM, true, NULL, NULL, NULL, NULL); if (r < 0) { - log_error("Failed to find lookup paths."); - return EXIT_FAILURE; + log_error_errno(r, "Failed to find lookup paths: %m"); + goto finish; } all_services = hashmap_new(&string_hash_ops); if (!all_services) { - log_oom(); - return EXIT_FAILURE; + r = log_oom(); + goto finish; } r = enumerate_sysv(&lp, all_services); - if (r < 0) { - log_error("Failed to generate units for all init scripts."); - return EXIT_FAILURE; - } + if (r < 0) + goto finish; r = set_dependencies_from_rcnd(&lp, all_services); - if (r < 0) { - log_error("Failed to read runlevels from rcnd links."); - return EXIT_FAILURE; - } + if (r < 0) + goto finish; - HASHMAP_FOREACH(service, all_services, j) { - q = load_sysv(service); - if (q < 0) - continue; - } + HASHMAP_FOREACH(service, all_services, j) + (void) load_sysv(service); HASHMAP_FOREACH(service, all_services, j) { - q = fix_order(service, all_services); - if (q < 0) - continue; - - q = generate_unit_file(service); - if (q < 0) - continue; + (void) fix_order(service, all_services); + (void) generate_unit_file(service); } - return EXIT_SUCCESS; + r = 0; + +finish: + return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } diff --git a/src/test/test-async.c b/src/test/test-async.c index abd36d693c..ada6d67c42 100644 --- a/src/test/test-async.c +++ b/src/test/test-async.c @@ -20,8 +20,9 @@ #include <unistd.h> #include "async.h" -#include "util.h" +#include "fileio.h" #include "macro.h" +#include "util.h" static bool test_async = false; diff --git a/src/test/test-btrfs.c b/src/test/test-btrfs.c index afe3ff8fc2..33356f8387 100644 --- a/src/test/test-btrfs.c +++ b/src/test/test-btrfs.c @@ -25,6 +25,7 @@ #include "fd-util.h" #include "fileio.h" #include "log.h" +#include "parse-util.h" #include "string-util.h" #include "util.h" diff --git a/src/test/test-calendarspec.c b/src/test/test-calendarspec.c index 12f366a34c..70819b0371 100644 --- a/src/test/test-calendarspec.c +++ b/src/test/test-calendarspec.c @@ -21,6 +21,7 @@ #include <string.h> +#include "alloc-util.h" #include "calendarspec.h" #include "string-util.h" #include "util.h" diff --git a/src/test/test-cap-list.c b/src/test/test-cap-list.c index 43a2d35b80..4418bafda6 100644 --- a/src/test/test-cap-list.c +++ b/src/test/test-cap-list.c @@ -19,12 +19,15 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include "util.h" -#include "fileio.h" -#include "cap-list.h" -#include "capability.h" #include <sys/prctl.h> +#include "alloc-util.h" +#include "cap-list.h" +#include "capability-util.h" +#include "fileio.h" +#include "parse-util.h" +#include "util.h" + /* verify the capability parser */ static void test_cap_list(void) { int i; diff --git a/src/test/test-capability.c b/src/test/test-capability.c index 09d7e61e92..fc8d3ffe0d 100644 --- a/src/test/test-capability.c +++ b/src/test/test-capability.c @@ -24,7 +24,7 @@ #include <sys/wait.h> #include <unistd.h> -#include "capability.h" +#include "capability-util.h" #include "fd-util.h" #include "macro.h" #include "util.h" diff --git a/src/test/test-cgroup-util.c b/src/test/test-cgroup-util.c index 7bf59a0aa2..a48b324e26 100644 --- a/src/test/test-cgroup-util.c +++ b/src/test/test-cgroup-util.c @@ -19,12 +19,16 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "cgroup-util.h" +#include "dirent-util.h" #include "fd-util.h" #include "formats-util.h" +#include "parse-util.h" #include "process-util.h" #include "string-util.h" #include "test-helper.h" +#include "user-util.h" #include "util.h" static void check_p_d_u(const char *path, int code, const char *result) { diff --git a/src/test/test-condition.c b/src/test/test-condition.c index 91a27138eb..f224c6cdd8 100644 --- a/src/test/test-condition.c +++ b/src/test/test-condition.c @@ -19,9 +19,10 @@ #include "sd-id128.h" +#include "alloc-util.h" #include "apparmor-util.h" #include "architecture.h" -#include "audit.h" +#include "audit-util.h" #include "condition.h" #include "hostname-util.h" #include "ima-util.h" diff --git a/src/test/test-conf-files.c b/src/test/test-conf-files.c index 30ba5364c4..a69698d4ea 100644 --- a/src/test/test-conf-files.c +++ b/src/test/test-conf-files.c @@ -22,11 +22,14 @@ #include <stdarg.h> #include <stdio.h> +#include "alloc-util.h" #include "conf-files.h" +#include "fs-util.h" #include "macro.h" #include "rm-rf.h" #include "string-util.h" #include "strv.h" +#include "user-util.h" #include "util.h" static void setup_test_dir(char *tmp_dir, const char *files, ...) { diff --git a/src/test/test-copy.c b/src/test/test-copy.c index 1bd50edca2..ad57cb0202 100644 --- a/src/test/test-copy.c +++ b/src/test/test-copy.c @@ -19,9 +19,11 @@ #include <unistd.h> +#include "alloc-util.h" #include "copy.h" #include "fd-util.h" #include "fileio.h" +#include "fs-util.h" #include "macro.h" #include "mkdir.h" #include "path-util.h" diff --git a/src/test/test-date.c b/src/test/test-date.c index e1c6ecb2ef..c6d8bf82ea 100644 --- a/src/test/test-date.c +++ b/src/test/test-date.c @@ -21,8 +21,9 @@ #include <string.h> -#include "util.h" +#include "alloc-util.h" #include "string-util.h" +#include "util.h" static void test_should_pass(const char *p) { usec_t t, q; diff --git a/src/test/test-device-nodes.c b/src/test/test-device-nodes.c index 1c745d6e5b..646b168cc0 100644 --- a/src/test/test-device-nodes.c +++ b/src/test/test-device-nodes.c @@ -21,6 +21,7 @@ #include <sys/types.h> +#include "alloc-util.h" #include "device-nodes.h" #include "string-util.h" #include "util.h" diff --git a/src/test/test-dns-domain.c b/src/test/test-dns-domain.c index 1a8541e1cc..d5778748a0 100644 --- a/src/test/test-dns-domain.c +++ b/src/test/test-dns-domain.c @@ -19,6 +19,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "dns-domain.h" #include "macro.h" #include "string-util.h" diff --git a/src/test/test-ellipsize.c b/src/test/test-ellipsize.c index 033d5af719..c597d5aecd 100644 --- a/src/test/test-ellipsize.c +++ b/src/test/test-ellipsize.c @@ -21,6 +21,7 @@ #include <stdio.h> +#include "alloc-util.h" #include "def.h" #include "string-util.h" #include "terminal-util.h" diff --git a/src/test/test-execute.c b/src/test/test-execute.c index fa6336f1fb..e2ec53ee51 100644 --- a/src/test/test-execute.c +++ b/src/test/test-execute.c @@ -17,14 +17,20 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include <grp.h> +#include <pwd.h> #include <stdio.h> +#include <sys/types.h> -#include "unit.h" -#include "manager.h" -#include "util.h" +#include "fileio.h" +#include "fs-util.h" #include "macro.h" +#include "manager.h" #include "mkdir.h" +#include "path-util.h" #include "rm-rf.h" +#include "unit.h" +#include "util.h" typedef void (*test_function_t)(Manager *m); @@ -123,11 +129,17 @@ static void test_exec_systemcallerrornumber(Manager *m) { } static void test_exec_user(Manager *m) { - test(m, "exec-user.service", 0, CLD_EXITED); + if (getpwnam("nobody")) + test(m, "exec-user.service", 0, CLD_EXITED); + else + log_error_errno(errno, "Skipping test_exec_user, could not find nobody user: %m"); } static void test_exec_group(Manager *m) { - test(m, "exec-group.service", 0, CLD_EXITED); + if (getgrnam("nobody")) + test(m, "exec-group.service", 0, CLD_EXITED); + else + log_error_errno(errno, "Skipping test_exec_group, could not find nobody group: %m"); } static void test_exec_environment(Manager *m) { @@ -136,6 +148,26 @@ static void test_exec_environment(Manager *m) { test(m, "exec-environment-empty.service", 0, CLD_EXITED); } +static void test_exec_environmentfile(Manager *m) { + static const char e[] = + "VAR1='word1 word2'\n" + "VAR2=word3 \n" + "# comment1\n" + "\n" + "; comment2\n" + " ; # comment3\n" + "line without an equal\n" + "VAR3='$word 5 6'\n"; + int r; + + r = write_string_file("/tmp/test-exec_environmentfile.conf", e, WRITE_STRING_FILE_CREATE); + assert_se(r == 0); + + test(m, "exec-environmentfile.service", 0, CLD_EXITED); + + unlink("/tmp/test-exec_environmentfile.conf"); +} + static void test_exec_umask(Manager *m) { test(m, "exec-umask-default.service", 0, CLD_EXITED); test(m, "exec-umask-0177.service", 0, CLD_EXITED); @@ -144,7 +176,51 @@ static void test_exec_umask(Manager *m) { static void test_exec_runtimedirectory(Manager *m) { test(m, "exec-runtimedirectory.service", 0, CLD_EXITED); test(m, "exec-runtimedirectory-mode.service", 0, CLD_EXITED); - test(m, "exec-runtimedirectory-owner.service", 0, CLD_EXITED); + if (getgrnam("nobody")) + test(m, "exec-runtimedirectory-owner.service", 0, CLD_EXITED); + else + log_error_errno(errno, "Skipping test_exec_runtimedirectory-owner, could not find nobody group: %m"); +} + +static void test_exec_capabilityboundingset(Manager *m) { + int r; + + /* We use capsh to test if the capabilities are + * properly set, so be sure that it exists */ + r = find_binary("capsh", NULL); + if (r < 0) { + log_error_errno(r, "Skipping test_exec_capabilityboundingset, could not find capsh binary: %m"); + return; + } + + test(m, "exec-capabilityboundingset-simple.service", 0, CLD_EXITED); + test(m, "exec-capabilityboundingset-reset.service", 0, CLD_EXITED); + test(m, "exec-capabilityboundingset-merge.service", 0, CLD_EXITED); + test(m, "exec-capabilityboundingset-invert.service", 0, CLD_EXITED); +} + +static void test_exec_privatenetwork(Manager *m) { + int r; + + r = find_binary("ip", NULL); + if (r < 0) { + log_error_errno(r, "Skipping test_exec_privatenetwork, could not find ip binary: %m"); + return; + } + + test(m, "exec-privatenetwork-yes.service", 0, CLD_EXITED); +} + +static void test_exec_oomscoreadjust(Manager *m) { + test(m, "exec-oomscoreadjust-positive.service", 0, CLD_EXITED); + test(m, "exec-oomscoreadjust-negative.service", 0, CLD_EXITED); +} + +static void test_exec_ioschedulingclass(Manager *m) { + test(m, "exec-ioschedulingclass-none.service", 0, CLD_EXITED); + test(m, "exec-ioschedulingclass-idle.service", 0, CLD_EXITED); + test(m, "exec-ioschedulingclass-realtime.service", 0, CLD_EXITED); + test(m, "exec-ioschedulingclass-best-effort.service", 0, CLD_EXITED); } int main(int argc, char *argv[]) { @@ -154,13 +230,18 @@ int main(int argc, char *argv[]) { test_exec_ignoresigpipe, test_exec_privatetmp, test_exec_privatedevices, + test_exec_privatenetwork, test_exec_systemcallfilter, test_exec_systemcallerrornumber, test_exec_user, test_exec_group, test_exec_environment, + test_exec_environmentfile, test_exec_umask, test_exec_runtimedirectory, + test_exec_capabilityboundingset, + test_exec_oomscoreadjust, + test_exec_ioschedulingclass, NULL, }; test_function_t *test = NULL; @@ -177,7 +258,7 @@ int main(int argc, char *argv[]) { } assert_se(setenv("XDG_RUNTIME_DIR", "/tmp/", 1) == 0); - assert_se(set_unit_path(TEST_DIR) >= 0); + assert_se(set_unit_path(TEST_DIR "/test-execute/") >= 0); r = manager_new(MANAGER_USER, true, &m); if (IN_SET(r, -EPERM, -EACCES, -EADDRINUSE, -EHOSTDOWN, -ENOENT)) { diff --git a/src/test/test-extract-word.c b/src/test/test-extract-word.c new file mode 100644 index 0000000000..09698c07c7 --- /dev/null +++ b/src/test/test-extract-word.c @@ -0,0 +1,546 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + Copyright 2013 Thomas H.P. Andersen + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <stdlib.h> +#include <string.h> + +#include "extract-word.h" +#include "log.h" +#include "string-util.h" + +static void test_extract_first_word(void) { + const char *p, *original; + char *t; + + p = original = "foobar waldo"; + assert_se(extract_first_word(&p, &t, NULL, 0) > 0); + assert_se(streq(t, "foobar")); + free(t); + assert_se(p == original + 7); + + assert_se(extract_first_word(&p, &t, NULL, 0) > 0); + assert_se(streq(t, "waldo")); + free(t); + assert_se(isempty(p)); + + assert_se(extract_first_word(&p, &t, NULL, 0) == 0); + assert_se(!t); + assert_se(isempty(p)); + + p = original = "\"foobar\" \'waldo\'"; + assert_se(extract_first_word(&p, &t, NULL, 0) > 0); + assert_se(streq(t, "\"foobar\"")); + free(t); + assert_se(p == original + 9); + + assert_se(extract_first_word(&p, &t, NULL, 0) > 0); + assert_se(streq(t, "\'waldo\'")); + free(t); + assert_se(isempty(p)); + + assert_se(extract_first_word(&p, &t, NULL, 0) == 0); + assert_se(!t); + assert_se(isempty(p)); + + p = original = "\"foobar\" \'waldo\'"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0); + assert_se(streq(t, "foobar")); + free(t); + assert_se(p == original + 9); + + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0); + assert_se(streq(t, "waldo")); + free(t); + assert_se(isempty(p)); + + assert_se(extract_first_word(&p, &t, NULL, 0) == 0); + assert_se(!t); + assert_se(isempty(p)); + + p = original = "\""; + assert_se(extract_first_word(&p, &t, NULL, 0) == 1); + assert_se(streq(t, "\"")); + free(t); + assert_se(isempty(p)); + + p = original = "\""; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) == -EINVAL); + assert_se(p == original + 1); + + p = original = "\'"; + assert_se(extract_first_word(&p, &t, NULL, 0) == 1); + assert_se(streq(t, "\'")); + free(t); + assert_se(isempty(p)); + + p = original = "\'"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) == -EINVAL); + assert_se(p == original + 1); + + p = original = "\'fooo"; + assert_se(extract_first_word(&p, &t, NULL, 0) == 1); + assert_se(streq(t, "\'fooo")); + free(t); + assert_se(isempty(p)); + + p = original = "\'fooo"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) == -EINVAL); + assert_se(p == original + 5); + + p = original = "\'fooo"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX) > 0); + assert_se(streq(t, "fooo")); + free(t); + assert_se(isempty(p)); + + p = original = "\"fooo"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX) > 0); + assert_se(streq(t, "fooo")); + free(t); + assert_se(isempty(p)); + + p = original = "yay\'foo\'bar"; + assert_se(extract_first_word(&p, &t, NULL, 0) > 0); + assert_se(streq(t, "yay\'foo\'bar")); + free(t); + assert_se(isempty(p)); + + p = original = "yay\'foo\'bar"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0); + assert_se(streq(t, "yayfoobar")); + free(t); + assert_se(isempty(p)); + + p = original = " foobar "; + assert_se(extract_first_word(&p, &t, NULL, 0) > 0); + assert_se(streq(t, "foobar")); + free(t); + assert_se(isempty(p)); + + p = original = " foo\\ba\\x6ar "; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE) > 0); + assert_se(streq(t, "foo\ba\x6ar")); + free(t); + assert_se(isempty(p)); + + p = original = " foo\\ba\\x6ar "; + assert_se(extract_first_word(&p, &t, NULL, 0) > 0); + assert_se(streq(t, "foobax6ar")); + free(t); + assert_se(isempty(p)); + + p = original = " f\\u00f6o \"pi\\U0001F4A9le\" "; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE) > 0); + assert_se(streq(t, "föo")); + free(t); + assert_se(p == original + 13); + + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE) > 0); + assert_se(streq(t, "pi\360\237\222\251le")); + free(t); + assert_se(isempty(p)); + + p = original = "fooo\\"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_RELAX) > 0); + assert_se(streq(t, "fooo")); + free(t); + assert_se(isempty(p)); + + p = original = "fooo\\"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE_RELAX) > 0); + assert_se(streq(t, "fooo\\")); + free(t); + assert_se(isempty(p)); + + p = original = "fooo\\"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0); + assert_se(streq(t, "fooo\\")); + free(t); + assert_se(isempty(p)); + + p = original = "fooo\\"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX) > 0); + assert_se(streq(t, "fooo\\")); + free(t); + assert_se(isempty(p)); + + p = original = "\"foo\\"; + assert_se(extract_first_word(&p, &t, NULL, 0) == -EINVAL); + assert_se(p == original + 5); + + p = original = "\"foo\\"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX) > 0); + assert_se(streq(t, "foo")); + free(t); + assert_se(isempty(p)); + + p = original = "foo::bar"; + assert_se(extract_first_word(&p, &t, ":", 0) == 1); + assert_se(streq(t, "foo")); + free(t); + assert_se(p == original + 5); + + assert_se(extract_first_word(&p, &t, ":", 0) == 1); + assert_se(streq(t, "bar")); + free(t); + assert_se(isempty(p)); + + assert_se(extract_first_word(&p, &t, ":", 0) == 0); + assert_se(!t); + assert_se(isempty(p)); + + p = original = "foo\\:bar::waldo"; + assert_se(extract_first_word(&p, &t, ":", 0) == 1); + assert_se(streq(t, "foo:bar")); + free(t); + assert_se(p == original + 10); + + assert_se(extract_first_word(&p, &t, ":", 0) == 1); + assert_se(streq(t, "waldo")); + free(t); + assert_se(isempty(p)); + + assert_se(extract_first_word(&p, &t, ":", 0) == 0); + assert_se(!t); + assert_se(isempty(p)); + + p = original = "\"foo\\"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE_RELAX) == -EINVAL); + assert_se(p == original + 5); + + p = original = "\"foo\\"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0); + assert_se(streq(t, "foo\\")); + free(t); + assert_se(isempty(p)); + + p = original = "\"foo\\"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0); + assert_se(streq(t, "foo\\")); + free(t); + assert_se(isempty(p)); + + p = original = "fooo\\ bar quux"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_RELAX) > 0); + assert_se(streq(t, "fooo bar")); + free(t); + assert_se(p == original + 10); + + p = original = "fooo\\ bar quux"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE_RELAX) > 0); + assert_se(streq(t, "fooo bar")); + free(t); + assert_se(p == original + 10); + + p = original = "fooo\\ bar quux"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0); + assert_se(streq(t, "fooo bar")); + free(t); + assert_se(p == original + 10); + + p = original = "fooo\\ bar quux"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE) == -EINVAL); + assert_se(p == original + 5); + + p = original = "fooo\\ bar quux"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX) > 0); + assert_se(streq(t, "fooo\\ bar")); + free(t); + assert_se(p == original + 10); + + p = original = "\\w+@\\K[\\d.]+"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE) == -EINVAL); + assert_se(p == original + 1); + + p = original = "\\w+@\\K[\\d.]+"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX) > 0); + assert_se(streq(t, "\\w+@\\K[\\d.]+")); + free(t); + assert_se(isempty(p)); + + p = original = "\\w+\\b"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX) > 0); + assert_se(streq(t, "\\w+\b")); + free(t); + assert_se(isempty(p)); + + p = original = "-N ''"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0); + assert_se(streq(t, "-N")); + free(t); + assert_se(p == original + 3); + + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0); + assert_se(streq(t, "")); + free(t); + assert_se(isempty(p)); + + p = original = ":foo\\:bar::waldo:"; + assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1); + assert_se(t); + assert_se(streq(t, "")); + free(t); + assert_se(p == original + 1); + + assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1); + assert_se(streq(t, "foo:bar")); + free(t); + assert_se(p == original + 10); + + assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1); + assert_se(t); + assert_se(streq(t, "")); + free(t); + assert_se(p == original + 11); + + assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1); + assert_se(streq(t, "waldo")); + free(t); + assert_se(p == original + 17); + + assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1); + assert_se(streq(t, "")); + free(t); + assert_se(p == NULL); + + assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 0); + assert_se(!t); + assert_se(!p); +} + +static void test_extract_first_word_and_warn(void) { + const char *p, *original; + char *t; + + p = original = "foobar waldo"; + assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "foobar")); + free(t); + assert_se(p == original + 7); + + assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "waldo")); + free(t); + assert_se(isempty(p)); + + assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) == 0); + assert_se(!t); + assert_se(isempty(p)); + + p = original = "\"foobar\" \'waldo\'"; + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "foobar")); + free(t); + assert_se(p == original + 9); + + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "waldo")); + free(t); + assert_se(isempty(p)); + + assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) == 0); + assert_se(!t); + assert_se(isempty(p)); + + p = original = "\""; + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) == -EINVAL); + assert_se(p == original + 1); + + p = original = "\'"; + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) == -EINVAL); + assert_se(p == original + 1); + + p = original = "\'fooo"; + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) == -EINVAL); + assert_se(p == original + 5); + + p = original = "\'fooo"; + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "fooo")); + free(t); + assert_se(isempty(p)); + + p = original = " foo\\ba\\x6ar "; + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "foo\ba\x6ar")); + free(t); + assert_se(isempty(p)); + + p = original = " foo\\ba\\x6ar "; + assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "foobax6ar")); + free(t); + assert_se(isempty(p)); + + p = original = " f\\u00f6o \"pi\\U0001F4A9le\" "; + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "föo")); + free(t); + assert_se(p == original + 13); + + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "pi\360\237\222\251le")); + free(t); + assert_se(isempty(p)); + + p = original = "fooo\\"; + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_RELAX, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "fooo")); + free(t); + assert_se(isempty(p)); + + p = original = "fooo\\"; + assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "fooo\\")); + free(t); + assert_se(isempty(p)); + + p = original = "fooo\\"; + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "fooo\\")); + free(t); + assert_se(isempty(p)); + + p = original = "\"foo\\"; + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) == -EINVAL); + assert_se(p == original + 5); + + p = original = "\"foo\\"; + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "foo")); + free(t); + assert_se(isempty(p)); + + p = original = "\"foo\\"; + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE, NULL, "fake", 1, original) == -EINVAL); + assert_se(p == original + 5); + + p = original = "\"foo\\"; + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE|EXTRACT_RELAX, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "foo")); + free(t); + assert_se(isempty(p)); + + p = original = "fooo\\ bar quux"; + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_RELAX, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "fooo bar")); + free(t); + assert_se(p == original + 10); + + p = original = "fooo\\ bar quux"; + assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "fooo bar")); + free(t); + assert_se(p == original + 10); + + p = original = "fooo\\ bar quux"; + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "fooo\\ bar")); + free(t); + assert_se(p == original + 10); + + p = original = "\\w+@\\K[\\d.]+"; + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "\\w+@\\K[\\d.]+")); + free(t); + assert_se(isempty(p)); + + p = original = "\\w+\\b"; + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "\\w+\b")); + free(t); + assert_se(isempty(p)); +} + +static void test_extract_many_words(void) { + const char *p, *original; + char *a, *b, *c; + + p = original = "foobar waldi piep"; + assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 3); + assert_se(isempty(p)); + assert_se(streq_ptr(a, "foobar")); + assert_se(streq_ptr(b, "waldi")); + assert_se(streq_ptr(c, "piep")); + free(a); + free(b); + free(c); + + p = original = "'foobar' wa\"ld\"i "; + assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 2); + assert_se(isempty(p)); + assert_se(streq_ptr(a, "'foobar'")); + assert_se(streq_ptr(b, "wa\"ld\"i")); + assert_se(streq_ptr(c, NULL)); + free(a); + free(b); + + p = original = "'foobar' wa\"ld\"i "; + assert_se(extract_many_words(&p, NULL, EXTRACT_QUOTES, &a, &b, &c, NULL) == 2); + assert_se(isempty(p)); + assert_se(streq_ptr(a, "foobar")); + assert_se(streq_ptr(b, "waldi")); + assert_se(streq_ptr(c, NULL)); + free(a); + free(b); + + p = original = ""; + assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 0); + assert_se(isempty(p)); + assert_se(streq_ptr(a, NULL)); + assert_se(streq_ptr(b, NULL)); + assert_se(streq_ptr(c, NULL)); + + p = original = " "; + assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 0); + assert_se(isempty(p)); + assert_se(streq_ptr(a, NULL)); + assert_se(streq_ptr(b, NULL)); + assert_se(streq_ptr(c, NULL)); + + p = original = "foobar"; + assert_se(extract_many_words(&p, NULL, 0, NULL) == 0); + assert_se(p == original); + + p = original = "foobar waldi"; + assert_se(extract_many_words(&p, NULL, 0, &a, NULL) == 1); + assert_se(p == original+7); + assert_se(streq_ptr(a, "foobar")); + free(a); + + p = original = " foobar "; + assert_se(extract_many_words(&p, NULL, 0, &a, NULL) == 1); + assert_se(isempty(p)); + assert_se(streq_ptr(a, "foobar")); + free(a); +} + +int main(int argc, char *argv[]) { + log_parse_environment(); + log_open(); + + test_extract_first_word(); + test_extract_first_word_and_warn(); + test_extract_many_words(); + + return 0; +} diff --git a/src/test/test-fdset.c b/src/test/test-fdset.c index 96d5e38177..282aab1246 100644 --- a/src/test/test-fdset.c +++ b/src/test/test-fdset.c @@ -22,6 +22,7 @@ #include "fd-util.h" #include "fdset.h" +#include "fileio.h" #include "macro.h" #include "util.h" diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c index a40f013491..e588681b86 100644 --- a/src/test/test-fileio.c +++ b/src/test/test-fileio.c @@ -23,11 +23,13 @@ #include <fcntl.h> #include <unistd.h> +#include "alloc-util.h" #include "ctype.h" #include "def.h" #include "env-util.h" #include "fd-util.h" #include "fileio.h" +#include "parse-util.h" #include "process-util.h" #include "string-util.h" #include "strv.h" diff --git a/src/test/test-fstab-util.c b/src/test/test-fstab-util.c index b02f3a6e7c..27816ac779 100644 --- a/src/test/test-fstab-util.c +++ b/src/test/test-fstab-util.c @@ -19,6 +19,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "fstab-util.h" #include "log.h" #include "string-util.h" diff --git a/src/test/test-hashmap-plain.c b/src/test/test-hashmap-plain.c index 2da6446961..6bf33306a9 100644 --- a/src/test/test-hashmap-plain.c +++ b/src/test/test-hashmap-plain.c @@ -17,6 +17,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "hashmap.h" #include "string-util.h" #include "strv.h" diff --git a/src/test/test-hostname-util.c b/src/test/test-hostname-util.c index ac8f4ecc68..590175433c 100644 --- a/src/test/test-hostname-util.c +++ b/src/test/test-hostname-util.c @@ -21,10 +21,11 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include "util.h" +#include "alloc-util.h" #include "fileio.h" #include "hostname-util.h" #include "string-util.h" +#include "util.h" static void test_hostname_is_valid(void) { assert_se(hostname_is_valid("foobar", false)); diff --git a/src/test/test-id128.c b/src/test/test-id128.c index 2c8ba70ffb..32cf3f80ca 100644 --- a/src/test/test-id128.c +++ b/src/test/test-id128.c @@ -24,6 +24,7 @@ #include "sd-daemon.h" #include "sd-id128.h" +#include "alloc-util.h" #include "macro.h" #include "string-util.h" #include "util.h" diff --git a/src/test/test-json.c b/src/test/test-json.c index ba4d75c0c8..3995224eea 100644 --- a/src/test/test-json.c +++ b/src/test/test-json.c @@ -21,6 +21,7 @@ #include <math.h> +#include "alloc-util.h" #include "json.h" #include "string-util.h" #include "util.h" diff --git a/src/test/test-namespace.c b/src/test/test-namespace.c index a060a7ba6f..5a12e959d4 100644 --- a/src/test/test-namespace.c +++ b/src/test/test-namespace.c @@ -21,6 +21,7 @@ #include <sys/socket.h> +#include "alloc-util.h" #include "fd-util.h" #include "namespace.h" #include "process-util.h" diff --git a/src/test/test-parse-util.c b/src/test/test-parse-util.c new file mode 100644 index 0000000000..d3ae0599ab --- /dev/null +++ b/src/test/test-parse-util.c @@ -0,0 +1,452 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + Copyright 2013 Thomas H.P. Andersen + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <locale.h> +#include <math.h> + +#include "log.h" +#include "parse-util.h" + +static void test_parse_boolean(void) { + assert_se(parse_boolean("1") == 1); + assert_se(parse_boolean("y") == 1); + assert_se(parse_boolean("Y") == 1); + assert_se(parse_boolean("yes") == 1); + assert_se(parse_boolean("YES") == 1); + assert_se(parse_boolean("true") == 1); + assert_se(parse_boolean("TRUE") == 1); + assert_se(parse_boolean("on") == 1); + assert_se(parse_boolean("ON") == 1); + + assert_se(parse_boolean("0") == 0); + assert_se(parse_boolean("n") == 0); + assert_se(parse_boolean("N") == 0); + assert_se(parse_boolean("no") == 0); + assert_se(parse_boolean("NO") == 0); + assert_se(parse_boolean("false") == 0); + assert_se(parse_boolean("FALSE") == 0); + assert_se(parse_boolean("off") == 0); + assert_se(parse_boolean("OFF") == 0); + + assert_se(parse_boolean("garbage") < 0); + assert_se(parse_boolean("") < 0); + assert_se(parse_boolean("full") < 0); +} + +static void test_parse_pid(void) { + int r; + pid_t pid; + + r = parse_pid("100", &pid); + assert_se(r == 0); + assert_se(pid == 100); + + r = parse_pid("0x7FFFFFFF", &pid); + assert_se(r == 0); + assert_se(pid == 2147483647); + + pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */ + r = parse_pid("0", &pid); + assert_se(r == -ERANGE); + assert_se(pid == 65); + + pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */ + r = parse_pid("-100", &pid); + assert_se(r == -ERANGE); + assert_se(pid == 65); + + pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */ + r = parse_pid("0xFFFFFFFFFFFFFFFFF", &pid); + assert_se(r == -ERANGE); + assert_se(pid == 65); + + r = parse_pid("junk", &pid); + assert_se(r == -EINVAL); +} + +static void test_parse_mode(void) { + mode_t m; + + assert_se(parse_mode("-1", &m) < 0); + assert_se(parse_mode("", &m) < 0); + assert_se(parse_mode("888", &m) < 0); + assert_se(parse_mode("77777", &m) < 0); + + assert_se(parse_mode("544", &m) >= 0 && m == 0544); + assert_se(parse_mode("777", &m) >= 0 && m == 0777); + assert_se(parse_mode("7777", &m) >= 0 && m == 07777); + assert_se(parse_mode("0", &m) >= 0 && m == 0); +} + +static void test_parse_size(void) { + uint64_t bytes; + + assert_se(parse_size("111", 1024, &bytes) == 0); + assert_se(bytes == 111); + + assert_se(parse_size("111.4", 1024, &bytes) == 0); + assert_se(bytes == 111); + + assert_se(parse_size(" 112 B", 1024, &bytes) == 0); + assert_se(bytes == 112); + + assert_se(parse_size(" 112.6 B", 1024, &bytes) == 0); + assert_se(bytes == 112); + + assert_se(parse_size("3.5 K", 1024, &bytes) == 0); + assert_se(bytes == 3*1024 + 512); + + assert_se(parse_size("3. K", 1024, &bytes) == 0); + assert_se(bytes == 3*1024); + + assert_se(parse_size("3.0 K", 1024, &bytes) == 0); + assert_se(bytes == 3*1024); + + assert_se(parse_size("3. 0 K", 1024, &bytes) == -EINVAL); + + assert_se(parse_size(" 4 M 11.5K", 1024, &bytes) == 0); + assert_se(bytes == 4*1024*1024 + 11 * 1024 + 512); + + assert_se(parse_size("3B3.5G", 1024, &bytes) == -EINVAL); + + assert_se(parse_size("3.5G3B", 1024, &bytes) == 0); + assert_se(bytes == 3ULL*1024*1024*1024 + 512*1024*1024 + 3); + + assert_se(parse_size("3.5G 4B", 1024, &bytes) == 0); + assert_se(bytes == 3ULL*1024*1024*1024 + 512*1024*1024 + 4); + + assert_se(parse_size("3B3G4T", 1024, &bytes) == -EINVAL); + + assert_se(parse_size("4T3G3B", 1024, &bytes) == 0); + assert_se(bytes == (4ULL*1024 + 3)*1024*1024*1024 + 3); + + assert_se(parse_size(" 4 T 3 G 3 B", 1024, &bytes) == 0); + assert_se(bytes == (4ULL*1024 + 3)*1024*1024*1024 + 3); + + assert_se(parse_size("12P", 1024, &bytes) == 0); + assert_se(bytes == 12ULL * 1024*1024*1024*1024*1024); + + assert_se(parse_size("12P12P", 1024, &bytes) == -EINVAL); + + assert_se(parse_size("3E 2P", 1024, &bytes) == 0); + assert_se(bytes == (3 * 1024 + 2ULL) * 1024*1024*1024*1024*1024); + + assert_se(parse_size("12X", 1024, &bytes) == -EINVAL); + + assert_se(parse_size("12.5X", 1024, &bytes) == -EINVAL); + + assert_se(parse_size("12.5e3", 1024, &bytes) == -EINVAL); + + assert_se(parse_size("1024E", 1024, &bytes) == -ERANGE); + assert_se(parse_size("-1", 1024, &bytes) == -ERANGE); + assert_se(parse_size("-1024E", 1024, &bytes) == -ERANGE); + + assert_se(parse_size("-1024P", 1024, &bytes) == -ERANGE); + + assert_se(parse_size("-10B 20K", 1024, &bytes) == -ERANGE); +} + +static void test_parse_range(void) { + unsigned lower, upper; + + /* Successful cases */ + assert_se(parse_range("111", &lower, &upper) == 0); + assert_se(lower == 111); + assert_se(upper == 111); + + assert_se(parse_range("111-123", &lower, &upper) == 0); + assert_se(lower == 111); + assert_se(upper == 123); + + assert_se(parse_range("123-111", &lower, &upper) == 0); + assert_se(lower == 123); + assert_se(upper == 111); + + assert_se(parse_range("123-123", &lower, &upper) == 0); + assert_se(lower == 123); + assert_se(upper == 123); + + assert_se(parse_range("0", &lower, &upper) == 0); + assert_se(lower == 0); + assert_se(upper == 0); + + assert_se(parse_range("0-15", &lower, &upper) == 0); + assert_se(lower == 0); + assert_se(upper == 15); + + assert_se(parse_range("15-0", &lower, &upper) == 0); + assert_se(lower == 15); + assert_se(upper == 0); + + assert_se(parse_range("128-65535", &lower, &upper) == 0); + assert_se(lower == 128); + assert_se(upper == 65535); + + assert_se(parse_range("1024-4294967295", &lower, &upper) == 0); + assert_se(lower == 1024); + assert_se(upper == 4294967295); + + /* Leading whitespace is acceptable */ + assert_se(parse_range(" 111", &lower, &upper) == 0); + assert_se(lower == 111); + assert_se(upper == 111); + + assert_se(parse_range(" 111-123", &lower, &upper) == 0); + assert_se(lower == 111); + assert_se(upper == 123); + + assert_se(parse_range("111- 123", &lower, &upper) == 0); + assert_se(lower == 111); + assert_se(upper == 123); + + assert_se(parse_range("\t111-\t123", &lower, &upper) == 0); + assert_se(lower == 111); + assert_se(upper == 123); + + assert_se(parse_range(" \t 111- \t 123", &lower, &upper) == 0); + assert_se(lower == 111); + assert_se(upper == 123); + + /* Error cases, make sure they fail as expected */ + lower = upper = 9999; + assert_se(parse_range("111garbage", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("garbage111", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("garbage", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("111-123garbage", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("111garbage-123", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + /* Empty string */ + lower = upper = 9999; + assert_se(parse_range("", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + /* 111--123 will pass -123 to safe_atou which returns -ERANGE for negative */ + assert_se(parse_range("111--123", &lower, &upper) == -ERANGE); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("-111-123", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("111-123-", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("111.4-123", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("111-123.4", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("111,4-123", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("111-123,4", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + /* Error on trailing dash */ + assert_se(parse_range("111-", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("111-123-", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("111--", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("111- ", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + /* Whitespace is not a separator */ + assert_se(parse_range("111 123", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("111\t123", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("111 \t 123", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + /* Trailing whitespace is invalid (from safe_atou) */ + assert_se(parse_range("111 ", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("111-123 ", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("111 -123", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("111 -123 ", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("111\t-123\t", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("111 \t -123 \t ", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + /* Out of the "unsigned" range, this is 1<<64 */ + assert_se(parse_range("0-18446744073709551616", &lower, &upper) == -ERANGE); + assert_se(lower == 9999); + assert_se(upper == 9999); +} + +static void test_safe_atolli(void) { + int r; + long long l; + + r = safe_atolli("12345", &l); + assert_se(r == 0); + assert_se(l == 12345); + + r = safe_atolli("junk", &l); + assert_se(r == -EINVAL); +} + +static void test_safe_atou16(void) { + int r; + uint16_t l; + + r = safe_atou16("12345", &l); + assert_se(r == 0); + assert_se(l == 12345); + + r = safe_atou16("123456", &l); + assert_se(r == -ERANGE); + + r = safe_atou16("junk", &l); + assert_se(r == -EINVAL); +} + +static void test_safe_atoi16(void) { + int r; + int16_t l; + + r = safe_atoi16("-12345", &l); + assert_se(r == 0); + assert_se(l == -12345); + + r = safe_atoi16("36536", &l); + assert_se(r == -ERANGE); + + r = safe_atoi16("junk", &l); + assert_se(r == -EINVAL); +} + +static void test_safe_atod(void) { + int r; + double d; + char *e; + + r = safe_atod("junk", &d); + assert_se(r == -EINVAL); + + r = safe_atod("0.2244", &d); + assert_se(r == 0); + assert_se(fabs(d - 0.2244) < 0.000001); + + r = safe_atod("0,5", &d); + assert_se(r == -EINVAL); + + errno = 0; + strtod("0,5", &e); + assert_se(*e == ','); + + /* Check if this really is locale independent */ + if (setlocale(LC_NUMERIC, "de_DE.utf8")) { + + r = safe_atod("0.2244", &d); + assert_se(r == 0); + assert_se(fabs(d - 0.2244) < 0.000001); + + r = safe_atod("0,5", &d); + assert_se(r == -EINVAL); + + errno = 0; + assert_se(fabs(strtod("0,5", &e) - 0.5) < 0.00001); + } + + /* And check again, reset */ + assert_se(setlocale(LC_NUMERIC, "C")); + + r = safe_atod("0.2244", &d); + assert_se(r == 0); + assert_se(fabs(d - 0.2244) < 0.000001); + + r = safe_atod("0,5", &d); + assert_se(r == -EINVAL); + + errno = 0; + strtod("0,5", &e); + assert_se(*e == ','); +} + +int main(int argc, char *argv[]) { + log_parse_environment(); + log_open(); + + test_parse_boolean(); + test_parse_pid(); + test_parse_mode(); + test_parse_size(); + test_parse_range(); + test_safe_atolli(); + test_safe_atou16(); + test_safe_atoi16(); + test_safe_atod(); + + return 0; +} diff --git a/src/test/test-path-lookup.c b/src/test/test-path-lookup.c index 92ffa65925..65cb894ff7 100644 --- a/src/test/test-path-lookup.c +++ b/src/test/test-path-lookup.c @@ -19,6 +19,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include <stdlib.h> #include <sys/stat.h> #include "log.h" @@ -30,19 +31,27 @@ static void test_paths(ManagerRunningAs running_as, bool personal) { char template[] = "/tmp/test-path-lookup.XXXXXXX"; - _cleanup_lookup_paths_free_ LookupPaths lp = {}; - char *exists, *not; + _cleanup_lookup_paths_free_ LookupPaths lp_without_env = {}; + _cleanup_lookup_paths_free_ LookupPaths lp_with_env = {}; + char *exists, *not, *systemd_unit_path; assert_se(mkdtemp(template)); exists = strjoina(template, "/exists"); assert_se(mkdir(exists, 0755) == 0); not = strjoina(template, "/not"); - assert_se(lookup_paths_init(&lp, running_as, personal, NULL, exists, not, not) == 0); + assert_se(unsetenv("SYSTEMD_UNIT_PATH") == 0); + assert_se(lookup_paths_init(&lp_without_env, running_as, personal, NULL, exists, not, not) == 0); - assert_se(!strv_isempty(lp.unit_path)); - assert_se(strv_contains(lp.unit_path, exists)); - assert_se(strv_contains(lp.unit_path, not)); + assert_se(!strv_isempty(lp_without_env.unit_path)); + assert_se(strv_contains(lp_without_env.unit_path, exists)); + assert_se(strv_contains(lp_without_env.unit_path, not)); + + systemd_unit_path = strjoina(template, "/systemd-unit-path"); + assert_se(setenv("SYSTEMD_UNIT_PATH", systemd_unit_path, 1) == 0); + assert_se(lookup_paths_init(&lp_with_env, running_as, personal, NULL, exists, not, not) == 0); + assert_se(strv_length(lp_with_env.unit_path) == 1); + assert_se(streq(lp_with_env.unit_path[0], systemd_unit_path)); assert_se(rm_rf(template, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0); } diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c index 89129c9894..3f0f0264ab 100644 --- a/src/test/test-path-util.c +++ b/src/test/test-path-util.c @@ -23,8 +23,10 @@ #include <sys/mount.h> #include <unistd.h> +#include "alloc-util.h" #include "fd-util.h" #include "macro.h" +#include "mount-util.h" #include "path-util.h" #include "rm-rf.h" #include "string-util.h" @@ -77,20 +79,6 @@ static void test_path(void) { assert_se(streq(basename("/aa///file..."), "file...")); assert_se(streq(basename("file.../"), "")); -#define test_parent(x, y) { \ - _cleanup_free_ char *z = NULL; \ - int r = path_get_parent(x, &z); \ - printf("expected: %s\n", y ? y : "error"); \ - printf("actual: %s\n", r<0 ? "error" : z); \ - assert_se((y==NULL) ^ (r==0)); \ - assert_se(y==NULL || path_equal(z, y)); \ - } - - test_parent("./aa/bb/../file.da.", "./aa/bb/.."); - test_parent("/aa///.file", "/aa///"); - test_parent("/aa///file...", "/aa///"); - test_parent("file.../", NULL); - fd = open("/", O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOCTTY); assert_se(fd >= 0); assert_se(fd_is_mount_point(fd, "/", 0) > 0); diff --git a/src/test/test-path.c b/src/test/test-path.c index e9e0bfd41d..8302bdd283 100644 --- a/src/test/test-path.c +++ b/src/test/test-path.c @@ -20,6 +20,9 @@ #include <stdbool.h> #include <stdio.h> +#include "alloc-util.h" +#include "fd-util.h" +#include "fs-util.h" #include "macro.h" #include "manager.h" #include "mkdir.h" @@ -28,7 +31,6 @@ #include "strv.h" #include "unit.h" #include "util.h" -#include "fd-util.h" typedef void (*test_function_t)(Manager *m); @@ -256,7 +258,7 @@ int main(int argc, char *argv[]) { log_parse_environment(); log_open(); - assert_se(set_unit_path(TEST_DIR) >= 0); + assert_se(set_unit_path(TEST_DIR "/test-path/") >= 0); for (test = tests; test && *test; test++) { int r; diff --git a/src/test/test-prioq.c b/src/test/test-prioq.c index 1e2e42cbca..07273ffe79 100644 --- a/src/test/test-prioq.c +++ b/src/test/test-prioq.c @@ -21,10 +21,11 @@ #include <stdlib.h> -#include "util.h" -#include "set.h" +#include "alloc-util.h" #include "prioq.h" +#include "set.h" #include "siphash24.h" +#include "util.h" #define SET_SIZE 1024*4 diff --git a/src/test/test-process-util.c b/src/test/test-process-util.c index 16a7148b19..48be5a3a87 100644 --- a/src/test/test-process-util.c +++ b/src/test/test-process-util.c @@ -23,6 +23,7 @@ #include <sys/wait.h> #include <unistd.h> +#include "alloc-util.h" #include "log.h" #include "macro.h" #include "process-util.h" @@ -54,7 +55,7 @@ static void test_get_process_comm(void) { assert_se(get_process_cmdline(1, 8, false, &d) >= 0); log_info("pid1 cmdline truncated: '%s'", d); - assert_se(get_parent_of_pid(1, &e) >= 0); + assert_se(get_process_ppid(1, &e) >= 0); log_info("pid1 ppid: "PID_FMT, e); assert_se(e == 0); diff --git a/src/test/test-socket-util.c b/src/test/test-socket-util.c index 4a2d952c86..b9699b2028 100644 --- a/src/test/test-socket-util.c +++ b/src/test/test-socket-util.c @@ -17,6 +17,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "async.h" #include "fd-util.h" #include "in-addr-util.h" diff --git a/src/test/test-strv.c b/src/test/test-strv.c index c676893719..c27f15283e 100644 --- a/src/test/test-strv.c +++ b/src/test/test-strv.c @@ -22,6 +22,7 @@ #include <string.h> +#include "alloc-util.h" #include "specifier.h" #include "string-util.h" #include "strv.h" diff --git a/src/test/test-tables.c b/src/test/test-tables.c index 0e5ab1645f..ed4abdbf12 100644 --- a/src/test/test-tables.c +++ b/src/test/test-tables.c @@ -17,7 +17,10 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "architecture.h" #include "automount.h" +#include "bus-xml-policy.h" +#include "busname.h" #include "cgroup.h" #include "compress.h" #include "condition.h" @@ -25,7 +28,10 @@ #include "execute.h" #include "install.h" #include "job.h" +#include "journald-server.h" #include "kill.h" +#include "link-config.h" +#include "locale-util.h" #include "log.h" #include "logs-show.h" #include "mount.h" @@ -42,12 +48,7 @@ #include "unit-name.h" #include "unit.h" #include "util.h" -#include "architecture.h" -#include "link-config.h" -#include "bus-xml-policy.h" -#include "busname.h" -#include "journald-server.h" -#include "locale-util.h" +#include "rlimit-util.h" #include "test-tables.h" diff --git a/src/test/test-terminal-util.c b/src/test/test-terminal-util.c index a41de59719..e940b5a204 100644 --- a/src/test/test-terminal-util.c +++ b/src/test/test-terminal-util.c @@ -21,11 +21,12 @@ #include <stdio.h> #include <stdbool.h> -#include "terminal-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "log.h" #include "macro.h" +#include "terminal-util.h" #include "util.h" -#include "log.h" -#include "fd-util.h" static void test_default_term_for_tty(void) { puts(default_term_for_tty("/dev/tty23")); diff --git a/src/test/test-tmpfiles.c b/src/test/test-tmpfiles.c index 6aa9cc8473..a8bd722e44 100644 --- a/src/test/test-tmpfiles.c +++ b/src/test/test-tmpfiles.c @@ -24,7 +24,9 @@ #include <stdlib.h> #include <unistd.h> +#include "alloc-util.h" #include "fd-util.h" +#include "fileio.h" #include "formats-util.h" #include "string-util.h" #include "util.h" diff --git a/src/test/test-udev.c b/src/test/test-udev.c index 3b9f71e3a2..219d659b41 100644 --- a/src/test/test-udev.c +++ b/src/test/test-udev.c @@ -26,6 +26,7 @@ #include <sys/signalfd.h> #include <unistd.h> +#include "fs-util.h" #include "missing.h" #include "selinux-util.h" #include "signal-util.h" diff --git a/src/test/test-uid-range.c b/src/test/test-uid-range.c index bc5baa2fcb..4dcf10e26d 100644 --- a/src/test/test-uid-range.c +++ b/src/test/test-uid-range.c @@ -21,8 +21,10 @@ #include <stddef.h> -#include "util.h" +#include "alloc-util.h" #include "uid-range.h" +#include "user-util.h" +#include "util.h" int main(int argc, char *argv[]) { _cleanup_free_ UidRange *p = NULL; diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c index 226453d06e..f9107e0d0d 100644 --- a/src/test/test-unit-file.c +++ b/src/test/test-unit-file.c @@ -24,8 +24,10 @@ #include <stddef.h> #include <stdio.h> #include <string.h> +#include <sys/capability.h> #include <unistd.h> +#include "alloc-util.h" #include "fd-util.h" #include "fileio.h" #include "hashmap.h" @@ -628,6 +630,57 @@ static void test_install_printf(void) { expect(i4, "%U", "0"); } +static uint64_t make_cap(int cap) { + return ((uint64_t) 1ULL << (uint64_t) cap); +} + +static void test_config_parse_bounding_set(void) { + /* int config_parse_bounding_set( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) */ + int r; + uint64_t capability_bounding_set_drop = 0; + + r = config_parse_bounding_set(NULL, "fake", 1, "section", 1, + "CapabilityBoundingSet", 0, "CAP_NET_RAW", + &capability_bounding_set_drop, NULL); + assert_se(r >= 0); + assert_se(capability_bounding_set_drop == ~make_cap(CAP_NET_RAW)); + + r = config_parse_bounding_set(NULL, "fake", 1, "section", 1, + "CapabilityBoundingSet", 0, "CAP_NET_ADMIN", + &capability_bounding_set_drop, NULL); + assert_se(r >= 0); + assert_se(capability_bounding_set_drop == ~(make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN))); + + r = config_parse_bounding_set(NULL, "fake", 1, "section", 1, + "CapabilityBoundingSet", 0, "", + &capability_bounding_set_drop, NULL); + assert_se(r >= 0); + assert_se(capability_bounding_set_drop == ~((uint64_t) 0ULL)); + + r = config_parse_bounding_set(NULL, "fake", 1, "section", 1, + "CapabilityBoundingSet", 0, "~", + &capability_bounding_set_drop, NULL); + assert_se(r >= 0); + assert_se(capability_bounding_set_drop == (uint64_t) 0ULL); + + capability_bounding_set_drop = 0; + r = config_parse_bounding_set(NULL, "fake", 1, "section", 1, + "CapabilityBoundingSet", 0, " 'CAP_NET_RAW' WAT_CAP??? CAP_NET_ADMIN CAP'_trailing_garbage", + &capability_bounding_set_drop, NULL); + assert_se(r >= 0); + assert_se(capability_bounding_set_drop == ~(make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN))); +} + int main(int argc, char *argv[]) { int r; @@ -636,6 +689,7 @@ int main(int argc, char *argv[]) { r = test_unit_file_get_set(); test_config_parse_exec(); + test_config_parse_bounding_set(); test_load_env_file_1(); test_load_env_file_2(); test_load_env_file_3(); diff --git a/src/test/test-unit-name.c b/src/test/test-unit-name.c index 5aff771af5..9db7853dd4 100644 --- a/src/test/test-unit-name.c +++ b/src/test/test-unit-name.c @@ -26,6 +26,7 @@ #include <stdlib.h> #include <string.h> +#include "alloc-util.h" #include "hostname-util.h" #include "macro.h" #include "manager.h" diff --git a/src/test/test-user-util.c b/src/test/test-user-util.c index dfd2031998..09d37087e5 100644 --- a/src/test/test-user-util.c +++ b/src/test/test-user-util.c @@ -19,6 +19,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "macro.h" #include "string-util.h" #include "user-util.h" diff --git a/src/test/test-utf8.c b/src/test/test-utf8.c index a8e15b7cf1..0af8349732 100644 --- a/src/test/test-utf8.c +++ b/src/test/test-utf8.c @@ -19,6 +19,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "utf8.h" #include "util.h" #include "string-util.h" diff --git a/src/test/test-util.c b/src/test/test-util.c index c1f8a866af..647df4f5c3 100644 --- a/src/test/test-util.c +++ b/src/test/test-util.c @@ -22,8 +22,6 @@ #include <errno.h> #include <fcntl.h> -#include <locale.h> -#include <math.h> #include <signal.h> #include <string.h> #include <sys/types.h> @@ -31,22 +29,33 @@ #include <sys/xattr.h> #include <unistd.h> +#include "alloc-util.h" #include "conf-parser.h" #include "cpu-set-util.h" #include "def.h" #include "escape.h" #include "fd-util.h" #include "fileio.h" +#include "fs-util.h" +#include "fstab-util.h" +#include "glob-util.h" +#include "hexdecoct.h" #include "io-util.h" #include "mkdir.h" +#include "parse-util.h" +#include "path-util.h" +#include "proc-cmdline.h" #include "process-util.h" #include "rm-rf.h" #include "signal-util.h" +#include "stat-util.h" #include "string-util.h" #include "strv.h" +#include "user-util.h" #include "util.h" #include "virt.h" -#include "user-util.h" +#include "web-util.h" +#include "xattr-util.h" static void test_streq_ptr(void) { assert_se(streq_ptr(NULL, NULL)); @@ -226,63 +235,6 @@ static void test_close_many(void) { unlink(name2); } -static void test_parse_boolean(void) { - assert_se(parse_boolean("1") == 1); - assert_se(parse_boolean("y") == 1); - assert_se(parse_boolean("Y") == 1); - assert_se(parse_boolean("yes") == 1); - assert_se(parse_boolean("YES") == 1); - assert_se(parse_boolean("true") == 1); - assert_se(parse_boolean("TRUE") == 1); - assert_se(parse_boolean("on") == 1); - assert_se(parse_boolean("ON") == 1); - - assert_se(parse_boolean("0") == 0); - assert_se(parse_boolean("n") == 0); - assert_se(parse_boolean("N") == 0); - assert_se(parse_boolean("no") == 0); - assert_se(parse_boolean("NO") == 0); - assert_se(parse_boolean("false") == 0); - assert_se(parse_boolean("FALSE") == 0); - assert_se(parse_boolean("off") == 0); - assert_se(parse_boolean("OFF") == 0); - - assert_se(parse_boolean("garbage") < 0); - assert_se(parse_boolean("") < 0); - assert_se(parse_boolean("full") < 0); -} - -static void test_parse_pid(void) { - int r; - pid_t pid; - - r = parse_pid("100", &pid); - assert_se(r == 0); - assert_se(pid == 100); - - r = parse_pid("0x7FFFFFFF", &pid); - assert_se(r == 0); - assert_se(pid == 2147483647); - - pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */ - r = parse_pid("0", &pid); - assert_se(r == -ERANGE); - assert_se(pid == 65); - - pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */ - r = parse_pid("-100", &pid); - assert_se(r == -ERANGE); - assert_se(pid == 65); - - pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */ - r = parse_pid("0xFFFFFFFFFFFFFFFFF", &pid); - assert_se(r == -ERANGE); - assert_se(pid == 65); - - r = parse_pid("junk", &pid); - assert_se(r == -EINVAL); -} - static void test_parse_uid(void) { int r; uid_t uid; @@ -298,96 +250,6 @@ static void test_parse_uid(void) { assert_se(r == -EINVAL); } -static void test_safe_atou16(void) { - int r; - uint16_t l; - - r = safe_atou16("12345", &l); - assert_se(r == 0); - assert_se(l == 12345); - - r = safe_atou16("123456", &l); - assert_se(r == -ERANGE); - - r = safe_atou16("junk", &l); - assert_se(r == -EINVAL); -} - -static void test_safe_atoi16(void) { - int r; - int16_t l; - - r = safe_atoi16("-12345", &l); - assert_se(r == 0); - assert_se(l == -12345); - - r = safe_atoi16("36536", &l); - assert_se(r == -ERANGE); - - r = safe_atoi16("junk", &l); - assert_se(r == -EINVAL); -} - -static void test_safe_atolli(void) { - int r; - long long l; - - r = safe_atolli("12345", &l); - assert_se(r == 0); - assert_se(l == 12345); - - r = safe_atolli("junk", &l); - assert_se(r == -EINVAL); -} - -static void test_safe_atod(void) { - int r; - double d; - char *e; - - r = safe_atod("junk", &d); - assert_se(r == -EINVAL); - - r = safe_atod("0.2244", &d); - assert_se(r == 0); - assert_se(fabs(d - 0.2244) < 0.000001); - - r = safe_atod("0,5", &d); - assert_se(r == -EINVAL); - - errno = 0; - strtod("0,5", &e); - assert_se(*e == ','); - - /* Check if this really is locale independent */ - if (setlocale(LC_NUMERIC, "de_DE.utf8")) { - - r = safe_atod("0.2244", &d); - assert_se(r == 0); - assert_se(fabs(d - 0.2244) < 0.000001); - - r = safe_atod("0,5", &d); - assert_se(r == -EINVAL); - - errno = 0; - assert_se(fabs(strtod("0,5", &e) - 0.5) < 0.00001); - } - - /* And check again, reset */ - assert_se(setlocale(LC_NUMERIC, "C")); - - r = safe_atod("0.2244", &d); - assert_se(r == 0); - assert_se(fabs(d - 0.2244) < 0.000001); - - r = safe_atod("0,5", &d); - assert_se(r == -EINVAL); - - errno = 0; - strtod("0,5", &e); - assert_se(*e == ','); -} - static void test_strappend(void) { _cleanup_free_ char *t1, *t2, *t3, *t4; @@ -900,74 +762,6 @@ static void test_protect_errno(void) { assert_se(errno == 12); } -static void test_parse_size(void) { - uint64_t bytes; - - assert_se(parse_size("111", 1024, &bytes) == 0); - assert_se(bytes == 111); - - assert_se(parse_size("111.4", 1024, &bytes) == 0); - assert_se(bytes == 111); - - assert_se(parse_size(" 112 B", 1024, &bytes) == 0); - assert_se(bytes == 112); - - assert_se(parse_size(" 112.6 B", 1024, &bytes) == 0); - assert_se(bytes == 112); - - assert_se(parse_size("3.5 K", 1024, &bytes) == 0); - assert_se(bytes == 3*1024 + 512); - - assert_se(parse_size("3. K", 1024, &bytes) == 0); - assert_se(bytes == 3*1024); - - assert_se(parse_size("3.0 K", 1024, &bytes) == 0); - assert_se(bytes == 3*1024); - - assert_se(parse_size("3. 0 K", 1024, &bytes) == -EINVAL); - - assert_se(parse_size(" 4 M 11.5K", 1024, &bytes) == 0); - assert_se(bytes == 4*1024*1024 + 11 * 1024 + 512); - - assert_se(parse_size("3B3.5G", 1024, &bytes) == -EINVAL); - - assert_se(parse_size("3.5G3B", 1024, &bytes) == 0); - assert_se(bytes == 3ULL*1024*1024*1024 + 512*1024*1024 + 3); - - assert_se(parse_size("3.5G 4B", 1024, &bytes) == 0); - assert_se(bytes == 3ULL*1024*1024*1024 + 512*1024*1024 + 4); - - assert_se(parse_size("3B3G4T", 1024, &bytes) == -EINVAL); - - assert_se(parse_size("4T3G3B", 1024, &bytes) == 0); - assert_se(bytes == (4ULL*1024 + 3)*1024*1024*1024 + 3); - - assert_se(parse_size(" 4 T 3 G 3 B", 1024, &bytes) == 0); - assert_se(bytes == (4ULL*1024 + 3)*1024*1024*1024 + 3); - - assert_se(parse_size("12P", 1024, &bytes) == 0); - assert_se(bytes == 12ULL * 1024*1024*1024*1024*1024); - - assert_se(parse_size("12P12P", 1024, &bytes) == -EINVAL); - - assert_se(parse_size("3E 2P", 1024, &bytes) == 0); - assert_se(bytes == (3 * 1024 + 2ULL) * 1024*1024*1024*1024*1024); - - assert_se(parse_size("12X", 1024, &bytes) == -EINVAL); - - assert_se(parse_size("12.5X", 1024, &bytes) == -EINVAL); - - assert_se(parse_size("12.5e3", 1024, &bytes) == -EINVAL); - - assert_se(parse_size("1024E", 1024, &bytes) == -ERANGE); - assert_se(parse_size("-1", 1024, &bytes) == -ERANGE); - assert_se(parse_size("-1024E", 1024, &bytes) == -ERANGE); - - assert_se(parse_size("-1024P", 1024, &bytes) == -ERANGE); - - assert_se(parse_size("-10B 20K", 1024, &bytes) == -ERANGE); -} - static void test_parse_cpu_set(void) { cpu_set_t *c = NULL; int ncpus; @@ -1001,19 +795,76 @@ static void test_parse_cpu_set(void) { /* Use commas as separators */ ncpus = parse_cpu_set_and_warn("0,1,2,3 8,9,10,11", &c, NULL, "fake", 1, "CPUAffinity"); - assert_se(ncpus < 0); - assert_se(!c); + assert_se(ncpus >= 1024); + assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8); + for (cpu = 0; cpu < 4; cpu++) + assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); + for (cpu = 8; cpu < 12; cpu++) + assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); + c = mfree(c); + + /* Commas with spaces (and trailing comma, space) */ + ncpus = parse_cpu_set_and_warn("0, 1, 2, 3, 4, 5, 6, 7, ", &c, NULL, "fake", 1, "CPUAffinity"); + assert_se(ncpus >= 1024); + assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8); + for (cpu = 0; cpu < 8; cpu++) + assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); + c = mfree(c); /* Ranges */ ncpus = parse_cpu_set_and_warn("0-3,8-11", &c, NULL, "fake", 1, "CPUAffinity"); - assert_se(ncpus < 0); - assert_se(!c); + assert_se(ncpus >= 1024); + assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8); + for (cpu = 0; cpu < 4; cpu++) + assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); + for (cpu = 8; cpu < 12; cpu++) + assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); + c = mfree(c); + + /* Ranges with trailing comma, space */ + ncpus = parse_cpu_set_and_warn("0-3 8-11, ", &c, NULL, "fake", 1, "CPUAffinity"); + assert_se(ncpus >= 1024); + assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8); + for (cpu = 0; cpu < 4; cpu++) + assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); + for (cpu = 8; cpu < 12; cpu++) + assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); + c = mfree(c); + + /* Negative range (returns empty cpu_set) */ + ncpus = parse_cpu_set_and_warn("3-0", &c, NULL, "fake", 1, "CPUAffinity"); + assert_se(ncpus >= 1024); + assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 0); + c = mfree(c); + + /* Overlapping ranges */ + ncpus = parse_cpu_set_and_warn("0-7 4-11", &c, NULL, "fake", 1, "CPUAffinity"); + assert_se(ncpus >= 1024); + assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 12); + for (cpu = 0; cpu < 12; cpu++) + assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); + c = mfree(c); + + /* Mix ranges and individual CPUs */ + ncpus = parse_cpu_set_and_warn("0,1 4-11", &c, NULL, "fake", 1, "CPUAffinity"); + assert_se(ncpus >= 1024); + assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 10); + assert_se(CPU_ISSET_S(0, CPU_ALLOC_SIZE(ncpus), c)); + assert_se(CPU_ISSET_S(1, CPU_ALLOC_SIZE(ncpus), c)); + for (cpu = 4; cpu < 12; cpu++) + assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); + c = mfree(c); /* Garbage */ ncpus = parse_cpu_set_and_warn("0 1 2 3 garbage", &c, NULL, "fake", 1, "CPUAffinity"); assert_se(ncpus < 0); assert_se(!c); + /* Range with garbage */ + ncpus = parse_cpu_set_and_warn("0-3 8-garbage", &c, NULL, "fake", 1, "CPUAffinity"); + assert_se(ncpus < 0); + assert_se(!c); + /* Empty string */ c = NULL; ncpus = parse_cpu_set_and_warn("", &c, NULL, "fake", 1, "CPUAffinity"); @@ -1559,513 +1410,6 @@ static void test_execute_directory(void) { (void) rm_rf(template_hi, REMOVE_ROOT|REMOVE_PHYSICAL); } -static void test_extract_first_word(void) { - const char *p, *original; - char *t; - - p = original = "foobar waldo"; - assert_se(extract_first_word(&p, &t, NULL, 0) > 0); - assert_se(streq(t, "foobar")); - free(t); - assert_se(p == original + 7); - - assert_se(extract_first_word(&p, &t, NULL, 0) > 0); - assert_se(streq(t, "waldo")); - free(t); - assert_se(isempty(p)); - - assert_se(extract_first_word(&p, &t, NULL, 0) == 0); - assert_se(!t); - assert_se(isempty(p)); - - p = original = "\"foobar\" \'waldo\'"; - assert_se(extract_first_word(&p, &t, NULL, 0) > 0); - assert_se(streq(t, "\"foobar\"")); - free(t); - assert_se(p == original + 9); - - assert_se(extract_first_word(&p, &t, NULL, 0) > 0); - assert_se(streq(t, "\'waldo\'")); - free(t); - assert_se(isempty(p)); - - assert_se(extract_first_word(&p, &t, NULL, 0) == 0); - assert_se(!t); - assert_se(isempty(p)); - - p = original = "\"foobar\" \'waldo\'"; - assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0); - assert_se(streq(t, "foobar")); - free(t); - assert_se(p == original + 9); - - assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0); - assert_se(streq(t, "waldo")); - free(t); - assert_se(isempty(p)); - - assert_se(extract_first_word(&p, &t, NULL, 0) == 0); - assert_se(!t); - assert_se(isempty(p)); - - p = original = "\""; - assert_se(extract_first_word(&p, &t, NULL, 0) == 1); - assert_se(streq(t, "\"")); - free(t); - assert_se(isempty(p)); - - p = original = "\""; - assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) == -EINVAL); - assert_se(p == original + 1); - - p = original = "\'"; - assert_se(extract_first_word(&p, &t, NULL, 0) == 1); - assert_se(streq(t, "\'")); - free(t); - assert_se(isempty(p)); - - p = original = "\'"; - assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) == -EINVAL); - assert_se(p == original + 1); - - p = original = "\'fooo"; - assert_se(extract_first_word(&p, &t, NULL, 0) == 1); - assert_se(streq(t, "\'fooo")); - free(t); - assert_se(isempty(p)); - - p = original = "\'fooo"; - assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) == -EINVAL); - assert_se(p == original + 5); - - p = original = "\'fooo"; - assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX) > 0); - assert_se(streq(t, "fooo")); - free(t); - assert_se(isempty(p)); - - p = original = "\"fooo"; - assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX) > 0); - assert_se(streq(t, "fooo")); - free(t); - assert_se(isempty(p)); - - p = original = "yay\'foo\'bar"; - assert_se(extract_first_word(&p, &t, NULL, 0) > 0); - assert_se(streq(t, "yay\'foo\'bar")); - free(t); - assert_se(isempty(p)); - - p = original = "yay\'foo\'bar"; - assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0); - assert_se(streq(t, "yayfoobar")); - free(t); - assert_se(isempty(p)); - - p = original = " foobar "; - assert_se(extract_first_word(&p, &t, NULL, 0) > 0); - assert_se(streq(t, "foobar")); - free(t); - assert_se(isempty(p)); - - p = original = " foo\\ba\\x6ar "; - assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE) > 0); - assert_se(streq(t, "foo\ba\x6ar")); - free(t); - assert_se(isempty(p)); - - p = original = " foo\\ba\\x6ar "; - assert_se(extract_first_word(&p, &t, NULL, 0) > 0); - assert_se(streq(t, "foobax6ar")); - free(t); - assert_se(isempty(p)); - - p = original = " f\\u00f6o \"pi\\U0001F4A9le\" "; - assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE) > 0); - assert_se(streq(t, "föo")); - free(t); - assert_se(p == original + 13); - - assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE) > 0); - assert_se(streq(t, "pi\360\237\222\251le")); - free(t); - assert_se(isempty(p)); - - p = original = "fooo\\"; - assert_se(extract_first_word(&p, &t, NULL, EXTRACT_RELAX) > 0); - assert_se(streq(t, "fooo")); - free(t); - assert_se(isempty(p)); - - p = original = "fooo\\"; - assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE_RELAX) > 0); - assert_se(streq(t, "fooo\\")); - free(t); - assert_se(isempty(p)); - - p = original = "fooo\\"; - assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0); - assert_se(streq(t, "fooo\\")); - free(t); - assert_se(isempty(p)); - - p = original = "fooo\\"; - assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX) > 0); - assert_se(streq(t, "fooo\\")); - free(t); - assert_se(isempty(p)); - - p = original = "\"foo\\"; - assert_se(extract_first_word(&p, &t, NULL, 0) == -EINVAL); - assert_se(p == original + 5); - - p = original = "\"foo\\"; - assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX) > 0); - assert_se(streq(t, "foo")); - free(t); - assert_se(isempty(p)); - - p = original = "foo::bar"; - assert_se(extract_first_word(&p, &t, ":", 0) == 1); - assert_se(streq(t, "foo")); - free(t); - assert_se(p == original + 5); - - assert_se(extract_first_word(&p, &t, ":", 0) == 1); - assert_se(streq(t, "bar")); - free(t); - assert_se(isempty(p)); - - assert_se(extract_first_word(&p, &t, ":", 0) == 0); - assert_se(!t); - assert_se(isempty(p)); - - p = original = "foo\\:bar::waldo"; - assert_se(extract_first_word(&p, &t, ":", 0) == 1); - assert_se(streq(t, "foo:bar")); - free(t); - assert_se(p == original + 10); - - assert_se(extract_first_word(&p, &t, ":", 0) == 1); - assert_se(streq(t, "waldo")); - free(t); - assert_se(isempty(p)); - - assert_se(extract_first_word(&p, &t, ":", 0) == 0); - assert_se(!t); - assert_se(isempty(p)); - - p = original = "\"foo\\"; - assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE_RELAX) == -EINVAL); - assert_se(p == original + 5); - - p = original = "\"foo\\"; - assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0); - assert_se(streq(t, "foo\\")); - free(t); - assert_se(isempty(p)); - - p = original = "\"foo\\"; - assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0); - assert_se(streq(t, "foo\\")); - free(t); - assert_se(isempty(p)); - - p = original = "fooo\\ bar quux"; - assert_se(extract_first_word(&p, &t, NULL, EXTRACT_RELAX) > 0); - assert_se(streq(t, "fooo bar")); - free(t); - assert_se(p == original + 10); - - p = original = "fooo\\ bar quux"; - assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE_RELAX) > 0); - assert_se(streq(t, "fooo bar")); - free(t); - assert_se(p == original + 10); - - p = original = "fooo\\ bar quux"; - assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0); - assert_se(streq(t, "fooo bar")); - free(t); - assert_se(p == original + 10); - - p = original = "fooo\\ bar quux"; - assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE) == -EINVAL); - assert_se(p == original + 5); - - p = original = "fooo\\ bar quux"; - assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX) > 0); - assert_se(streq(t, "fooo\\ bar")); - free(t); - assert_se(p == original + 10); - - p = original = "\\w+@\\K[\\d.]+"; - assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE) == -EINVAL); - assert_se(p == original + 1); - - p = original = "\\w+@\\K[\\d.]+"; - assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX) > 0); - assert_se(streq(t, "\\w+@\\K[\\d.]+")); - free(t); - assert_se(isempty(p)); - - p = original = "\\w+\\b"; - assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX) > 0); - assert_se(streq(t, "\\w+\b")); - free(t); - assert_se(isempty(p)); - - p = original = "-N ''"; - assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0); - assert_se(streq(t, "-N")); - free(t); - assert_se(p == original + 3); - - assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0); - assert_se(streq(t, "")); - free(t); - assert_se(isempty(p)); - - p = original = ":foo\\:bar::waldo:"; - assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1); - assert_se(t); - assert_se(streq(t, "")); - free(t); - assert_se(p == original + 1); - - assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1); - assert_se(streq(t, "foo:bar")); - free(t); - assert_se(p == original + 10); - - assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1); - assert_se(t); - assert_se(streq(t, "")); - free(t); - assert_se(p == original + 11); - - assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1); - assert_se(streq(t, "waldo")); - free(t); - assert_se(p == original + 17); - - assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1); - assert_se(streq(t, "")); - free(t); - assert_se(p == NULL); - - assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 0); - assert_se(!t); - assert_se(!p); -} - -static void test_extract_first_word_and_warn(void) { - const char *p, *original; - char *t; - - p = original = "foobar waldo"; - assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0); - assert_se(streq(t, "foobar")); - free(t); - assert_se(p == original + 7); - - assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0); - assert_se(streq(t, "waldo")); - free(t); - assert_se(isempty(p)); - - assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) == 0); - assert_se(!t); - assert_se(isempty(p)); - - p = original = "\"foobar\" \'waldo\'"; - assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) > 0); - assert_se(streq(t, "foobar")); - free(t); - assert_se(p == original + 9); - - assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) > 0); - assert_se(streq(t, "waldo")); - free(t); - assert_se(isempty(p)); - - assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) == 0); - assert_se(!t); - assert_se(isempty(p)); - - p = original = "\""; - assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) == -EINVAL); - assert_se(p == original + 1); - - p = original = "\'"; - assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) == -EINVAL); - assert_se(p == original + 1); - - p = original = "\'fooo"; - assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) == -EINVAL); - assert_se(p == original + 5); - - p = original = "\'fooo"; - assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX, NULL, "fake", 1, original) > 0); - assert_se(streq(t, "fooo")); - free(t); - assert_se(isempty(p)); - - p = original = " foo\\ba\\x6ar "; - assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0); - assert_se(streq(t, "foo\ba\x6ar")); - free(t); - assert_se(isempty(p)); - - p = original = " foo\\ba\\x6ar "; - assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0); - assert_se(streq(t, "foobax6ar")); - free(t); - assert_se(isempty(p)); - - p = original = " f\\u00f6o \"pi\\U0001F4A9le\" "; - assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0); - assert_se(streq(t, "föo")); - free(t); - assert_se(p == original + 13); - - assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0); - assert_se(streq(t, "pi\360\237\222\251le")); - free(t); - assert_se(isempty(p)); - - p = original = "fooo\\"; - assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_RELAX, NULL, "fake", 1, original) > 0); - assert_se(streq(t, "fooo")); - free(t); - assert_se(isempty(p)); - - p = original = "fooo\\"; - assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0); - assert_se(streq(t, "fooo\\")); - free(t); - assert_se(isempty(p)); - - p = original = "fooo\\"; - assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0); - assert_se(streq(t, "fooo\\")); - free(t); - assert_se(isempty(p)); - - p = original = "\"foo\\"; - assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) == -EINVAL); - assert_se(p == original + 5); - - p = original = "\"foo\\"; - assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX, NULL, "fake", 1, original) > 0); - assert_se(streq(t, "foo")); - free(t); - assert_se(isempty(p)); - - p = original = "\"foo\\"; - assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE, NULL, "fake", 1, original) == -EINVAL); - assert_se(p == original + 5); - - p = original = "\"foo\\"; - assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE|EXTRACT_RELAX, NULL, "fake", 1, original) > 0); - assert_se(streq(t, "foo")); - free(t); - assert_se(isempty(p)); - - p = original = "fooo\\ bar quux"; - assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_RELAX, NULL, "fake", 1, original) > 0); - assert_se(streq(t, "fooo bar")); - free(t); - assert_se(p == original + 10); - - p = original = "fooo\\ bar quux"; - assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0); - assert_se(streq(t, "fooo bar")); - free(t); - assert_se(p == original + 10); - - p = original = "fooo\\ bar quux"; - assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0); - assert_se(streq(t, "fooo\\ bar")); - free(t); - assert_se(p == original + 10); - - p = original = "\\w+@\\K[\\d.]+"; - assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0); - assert_se(streq(t, "\\w+@\\K[\\d.]+")); - free(t); - assert_se(isempty(p)); - - p = original = "\\w+\\b"; - assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0); - assert_se(streq(t, "\\w+\b")); - free(t); - assert_se(isempty(p)); -} - -static void test_extract_many_words(void) { - const char *p, *original; - char *a, *b, *c; - - p = original = "foobar waldi piep"; - assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 3); - assert_se(isempty(p)); - assert_se(streq_ptr(a, "foobar")); - assert_se(streq_ptr(b, "waldi")); - assert_se(streq_ptr(c, "piep")); - free(a); - free(b); - free(c); - - p = original = "'foobar' wa\"ld\"i "; - assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 2); - assert_se(isempty(p)); - assert_se(streq_ptr(a, "'foobar'")); - assert_se(streq_ptr(b, "wa\"ld\"i")); - assert_se(streq_ptr(c, NULL)); - free(a); - free(b); - - p = original = "'foobar' wa\"ld\"i "; - assert_se(extract_many_words(&p, NULL, EXTRACT_QUOTES, &a, &b, &c, NULL) == 2); - assert_se(isempty(p)); - assert_se(streq_ptr(a, "foobar")); - assert_se(streq_ptr(b, "waldi")); - assert_se(streq_ptr(c, NULL)); - free(a); - free(b); - - p = original = ""; - assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 0); - assert_se(isempty(p)); - assert_se(streq_ptr(a, NULL)); - assert_se(streq_ptr(b, NULL)); - assert_se(streq_ptr(c, NULL)); - - p = original = " "; - assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 0); - assert_se(isempty(p)); - assert_se(streq_ptr(a, NULL)); - assert_se(streq_ptr(b, NULL)); - assert_se(streq_ptr(c, NULL)); - - p = original = "foobar"; - assert_se(extract_many_words(&p, NULL, 0, NULL) == 0); - assert_se(p == original); - - p = original = "foobar waldi"; - assert_se(extract_many_words(&p, NULL, 0, &a, NULL) == 1); - assert_se(p == original+7); - assert_se(streq_ptr(a, "foobar")); - free(a); - - p = original = " foobar "; - assert_se(extract_many_words(&p, NULL, 0, &a, NULL) == 1); - assert_se(isempty(p)); - assert_se(streq_ptr(a, "foobar")); - free(a); -} - static int parse_item(const char *key, const char *value) { assert_se(key); @@ -2214,20 +1558,6 @@ static void test_shell_maybe_quote(void) { test_shell_maybe_quote_one("foo$bar", "\"foo\\$bar\""); } -static void test_parse_mode(void) { - mode_t m; - - assert_se(parse_mode("-1", &m) < 0); - assert_se(parse_mode("", &m) < 0); - assert_se(parse_mode("888", &m) < 0); - assert_se(parse_mode("77777", &m) < 0); - - assert_se(parse_mode("544", &m) >= 0 && m == 0544); - assert_se(parse_mode("777", &m) >= 0 && m == 0777); - assert_se(parse_mode("7777", &m) >= 0 && m == 07777); - assert_se(parse_mode("0", &m) >= 0 && m == 0); -} - static void test_tempfn(void) { char *ret = NULL, *p; @@ -2320,13 +1650,7 @@ int main(int argc, char *argv[]) { test_div_round_up(); test_first_word(); test_close_many(); - test_parse_boolean(); - test_parse_pid(); test_parse_uid(); - test_safe_atou16(); - test_safe_atoi16(); - test_safe_atolli(); - test_safe_atod(); test_strappend(); test_strstrip(); test_delete_chars(); @@ -2353,7 +1677,6 @@ int main(int argc, char *argv[]) { test_memdup_multiply(); test_u64log2(); test_protect_errno(); - test_parse_size(); test_parse_cpu_set(); test_config_parse_iec_uint64(); test_strextend(); @@ -2385,9 +1708,6 @@ int main(int argc, char *argv[]) { test_search_and_fopen_nulstr(); test_glob_exists(); test_execute_directory(); - test_extract_first_word(); - test_extract_first_word_and_warn(); - test_extract_many_words(); test_parse_proc_cmdline(); test_raw_clone(); test_same_fd(); @@ -2395,7 +1715,6 @@ int main(int argc, char *argv[]) { test_sparse_write(); test_shell_escape(); test_shell_maybe_quote(); - test_parse_mode(); test_tempfn(); test_strcmp_ptr(); test_fgetxattrat_fake(); diff --git a/src/test/test-xml.c b/src/test/test-xml.c index 93b0e7c3fb..548d75a3c3 100644 --- a/src/test/test-xml.c +++ b/src/test/test-xml.c @@ -21,6 +21,7 @@ #include <stdarg.h> +#include "alloc-util.h" #include "string-util.h" #include "util.h" #include "xml.h" diff --git a/src/timedate/timedatectl.c b/src/timedate/timedatectl.c index 68fbe3f5b8..564d72773a 100644 --- a/src/timedate/timedatectl.c +++ b/src/timedate/timedatectl.c @@ -30,6 +30,7 @@ #include "bus-error.h" #include "bus-util.h" #include "pager.h" +#include "parse-util.h" #include "spawn-polkit-agent.h" #include "strv.h" #include "terminal-util.h" diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c index 6de9e246f6..968ef8a788 100644 --- a/src/timedate/timedated.c +++ b/src/timedate/timedated.c @@ -23,21 +23,24 @@ #include <string.h> #include <unistd.h> -#include "sd-messages.h" -#include "sd-event.h" #include "sd-bus.h" +#include "sd-event.h" +#include "sd-messages.h" -#include "util.h" -#include "strv.h" -#include "def.h" -#include "clock-util.h" -#include "path-util.h" -#include "fileio-label.h" -#include "bus-util.h" -#include "bus-error.h" +#include "alloc-util.h" #include "bus-common-errors.h" +#include "bus-error.h" +#include "bus-util.h" +#include "clock-util.h" +#include "def.h" #include "event-util.h" +#include "fileio-label.h" +#include "fs-util.h" +#include "path-util.h" #include "selinux-util.h" +#include "strv.h" +#include "user-util.h" +#include "util.h" #define NULL_ADJTIME_UTC "0.0 0 0\n0\nUTC\n" #define NULL_ADJTIME_LOCAL "0.0 0 0\n0\nLOCAL\n" diff --git a/src/timesync/timesyncd-conf.c b/src/timesync/timesyncd-conf.c index 28e0636604..be651fc636 100644 --- a/src/timesync/timesyncd-conf.c +++ b/src/timesync/timesyncd-conf.c @@ -19,14 +19,14 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "string-util.h" #include "timesyncd-manager.h" #include "timesyncd-server.h" #include "timesyncd-conf.h" +#include "extract-word.h" int manager_parse_server_string(Manager *m, ServerType type, const char *string) { - const char *word, *state; - size_t length; ServerName *first; int r; @@ -35,17 +35,20 @@ int manager_parse_server_string(Manager *m, ServerType type, const char *string) first = type == SERVER_FALLBACK ? m->fallback_servers : m->system_servers; - FOREACH_WORD_QUOTED(word, length, string, state) { - char buffer[length+1]; + for (;;) { + _cleanup_free_ char *word = NULL; bool found = false; ServerName *n; - memcpy(buffer, word, length); - buffer[length] = 0; + r = extract_first_word(&string, &word, NULL, 0); + if (r < 0) + return log_error_errno(r, "Failed to parse timesyncd server syntax \"%s\": %m", string); + if (r == 0) + break; /* Filter out duplicates */ LIST_FOREACH(names, n, first) - if (streq_ptr(n->string, buffer)) { + if (streq_ptr(n->string, word)) { found = true; break; } @@ -53,7 +56,7 @@ int manager_parse_server_string(Manager *m, ServerType type, const char *string) if (found) continue; - r = server_name_new(m, NULL, type, buffer); + r = server_name_new(m, NULL, type, word); if (r < 0) return r; } diff --git a/src/timesync/timesyncd-manager.c b/src/timesync/timesyncd-manager.c index d44cf0a80b..b4995c3064 100644 --- a/src/timesync/timesyncd-manager.c +++ b/src/timesync/timesyncd-manager.c @@ -33,7 +33,9 @@ #include "sd-daemon.h" +#include "alloc-util.h" #include "fd-util.h" +#include "fs-util.h" #include "list.h" #include "log.h" #include "missing.h" diff --git a/src/timesync/timesyncd-server.c b/src/timesync/timesyncd-server.c index ec3fe1fc4e..f98e6b4cf0 100644 --- a/src/timesync/timesyncd-server.c +++ b/src/timesync/timesyncd-server.c @@ -19,6 +19,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "timesyncd-server.h" int server_address_new( diff --git a/src/timesync/timesyncd.c b/src/timesync/timesyncd.c index 7a0ab18ca0..7f70eaaea0 100644 --- a/src/timesync/timesyncd.c +++ b/src/timesync/timesyncd.c @@ -22,9 +22,10 @@ #include "sd-daemon.h" #include "sd-event.h" -#include "capability.h" +#include "capability-util.h" #include "clock-util.h" #include "fd-util.h" +#include "fs-util.h" #include "network-util.h" #include "signal-util.h" #include "timesyncd-conf.h" diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index 05c4661a2c..45335425ce 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -39,26 +39,37 @@ #include <unistd.h> #include "acl-util.h" +#include "alloc-util.h" #include "btrfs-util.h" -#include "capability.h" +#include "capability-util.h" +#include "chattr-util.h" #include "conf-files.h" #include "copy.h" #include "escape.h" #include "fd-util.h" +#include "fileio.h" #include "formats-util.h" +#include "fs-util.h" +#include "glob-util.h" #include "io-util.h" #include "label.h" #include "log.h" #include "macro.h" #include "missing.h" #include "mkdir.h" +#include "mount-util.h" +#include "parse-util.h" #include "path-util.h" #include "rm-rf.h" #include "selinux-util.h" #include "set.h" #include "specifier.h" +#include "stat-util.h" +#include "stdio-util.h" +#include "string-table.h" #include "string-util.h" #include "strv.h" +#include "umask-util.h" #include "user-util.h" #include "util.h" diff --git a/src/tty-ask-password-agent/tty-ask-password-agent.c b/src/tty-ask-password-agent/tty-ask-password-agent.c index 33419f6962..d2938f0872 100644 --- a/src/tty-ask-password-agent/tty-ask-password-agent.c +++ b/src/tty-ask-password-agent/tty-ask-password-agent.c @@ -32,9 +32,11 @@ #include <sys/un.h> #include <unistd.h> +#include "alloc-util.h" #include "ask-password-api.h" #include "conf-parser.h" #include "def.h" +#include "dirent-util.h" #include "fd-util.h" #include "io-util.h" #include "mkdir.h" diff --git a/src/udev/collect/collect.c b/src/udev/collect/collect.c index b234792e23..b6c95cd452 100644 --- a/src/udev/collect/collect.c +++ b/src/udev/collect/collect.c @@ -24,6 +24,7 @@ #include <stddef.h> #include <stdio.h> +#include "alloc-util.h" #include "libudev-private.h" #include "macro.h" #include "string-util.h" diff --git a/src/udev/net/ethtool-util.c b/src/udev/net/ethtool-util.c index a4b05d1bec..0647008d90 100644 --- a/src/udev/net/ethtool-util.c +++ b/src/udev/net/ethtool-util.c @@ -19,17 +19,17 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <sys/ioctl.h> #include <net/if.h> +#include <sys/ioctl.h> #include <linux/ethtool.h> #include <linux/sockios.h> +#include "conf-parser.h" #include "ethtool-util.h" - +#include "log.h" +#include "string-table.h" #include "strxcpyx.h" #include "util.h" -#include "log.h" -#include "conf-parser.h" static const char* const duplex_table[_DUP_MAX] = { [DUP_FULL] = "full", diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c index e9577930e3..776674e994 100644 --- a/src/udev/net/link-config.c +++ b/src/udev/net/link-config.c @@ -24,6 +24,7 @@ #include "sd-netlink.h" +#include "alloc-util.h" #include "conf-files.h" #include "conf-parser.h" #include "ethtool-util.h" @@ -34,8 +35,12 @@ #include "missing.h" #include "netlink-util.h" #include "network-internal.h" +#include "parse-util.h" #include "path-util.h" +#include "proc-cmdline.h" #include "random-util.h" +#include "stat-util.h" +#include "string-table.h" #include "string-util.h" #include "strv.h" #include "util.h" diff --git a/src/udev/udev-builtin-blkid.c b/src/udev/udev-builtin-blkid.c index 0976525eb3..d0e47ec6d8 100644 --- a/src/udev/udev-builtin-blkid.c +++ b/src/udev/udev-builtin-blkid.c @@ -29,6 +29,7 @@ #include "sd-id128.h" +#include "alloc-util.h" #include "efivars.h" #include "fd-util.h" #include "gpt.h" diff --git a/src/udev/udev-builtin-hwdb.c b/src/udev/udev-builtin-hwdb.c index 97a5a9c77f..f4a065a97d 100644 --- a/src/udev/udev-builtin-hwdb.c +++ b/src/udev/udev-builtin-hwdb.c @@ -24,6 +24,7 @@ #include "sd-hwdb.h" +#include "alloc-util.h" #include "hwdb-util.h" #include "string-util.h" #include "udev-util.h" diff --git a/src/udev/udev-builtin-keyboard.c b/src/udev/udev-builtin-keyboard.c index 5e97bdd614..aa10beafb0 100644 --- a/src/udev/udev-builtin-keyboard.c +++ b/src/udev/udev-builtin-keyboard.c @@ -24,6 +24,8 @@ #include <linux/input.h> #include "fd-util.h" +#include "parse-util.h" +#include "stdio-util.h" #include "string-util.h" #include "udev.h" diff --git a/src/udev/udev-builtin-net_setup_link.c b/src/udev/udev-builtin-net_setup_link.c index d4589470fb..f72894b5c5 100644 --- a/src/udev/udev-builtin-net_setup_link.c +++ b/src/udev/udev-builtin-net_setup_link.c @@ -19,9 +19,10 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include "alloc-util.h" #include "link-config.h" -#include "udev.h" #include "log.h" +#include "udev.h" static link_config_ctx *ctx = NULL; diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c index 2c40988c7a..1e190140b2 100644 --- a/src/udev/udev-builtin-path_id.c +++ b/src/udev/udev-builtin-path_id.c @@ -30,6 +30,7 @@ #include <string.h> #include <unistd.h> +#include "alloc-util.h" #include "string-util.h" #include "udev.h" diff --git a/src/udev/udev-builtin-usb_id.c b/src/udev/udev-builtin-usb_id.c index cb531bd168..587649eff0 100644 --- a/src/udev/udev-builtin-usb_id.c +++ b/src/udev/udev-builtin-usb_id.c @@ -29,6 +29,7 @@ #include <string.h> #include <unistd.h> +#include "alloc-util.h" #include "fd-util.h" #include "string-util.h" #include "udev.h" diff --git a/src/udev/udev-ctrl.c b/src/udev/udev-ctrl.c index 937fc4ecd8..1e05be51a5 100644 --- a/src/udev/udev-ctrl.c +++ b/src/udev/udev-ctrl.c @@ -18,6 +18,7 @@ #include <sys/socket.h> #include <sys/un.h> +#include "alloc-util.h" #include "fd-util.h" #include "formats-util.h" #include "socket-util.h" diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c index bf122f85c7..6b4bd31281 100644 --- a/src/udev/udev-event.c +++ b/src/udev/udev-event.c @@ -30,6 +30,7 @@ #include <sys/wait.h> #include <unistd.h> +#include "alloc-util.h" #include "event-util.h" #include "fd-util.h" #include "formats-util.h" diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c index 4ed6416ecd..afdeb0a21b 100644 --- a/src/udev/udev-node.c +++ b/src/udev/udev-node.c @@ -26,6 +26,7 @@ #include <unistd.h> #include "formats-util.h" +#include "fs-util.h" #include "selinux-util.h" #include "smack-util.h" #include "string-util.h" diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c index 311d515645..c06ace09cf 100644 --- a/src/udev/udev-rules.c +++ b/src/udev/udev-rules.c @@ -29,10 +29,13 @@ #include <time.h> #include <unistd.h> +#include "alloc-util.h" #include "conf-files.h" #include "escape.h" #include "fd-util.h" +#include "glob-util.h" #include "path-util.h" +#include "stat-util.h" #include "strbuf.h" #include "string-util.h" #include "strv.h" diff --git a/src/udev/udevadm-hwdb.c b/src/udev/udevadm-hwdb.c index f9509ad640..031a099d77 100644 --- a/src/udev/udevadm-hwdb.c +++ b/src/udev/udevadm-hwdb.c @@ -22,7 +22,10 @@ #include <stdlib.h> #include <string.h> +#include "alloc-util.h" #include "conf-files.h" +#include "fileio.h" +#include "fs-util.h" #include "hwdb-internal.h" #include "hwdb-util.h" #include "strbuf.h" diff --git a/src/udev/udevadm-settle.c b/src/udev/udevadm-settle.c index 3d6ca7a985..c25071b0fe 100644 --- a/src/udev/udevadm-settle.c +++ b/src/udev/udevadm-settle.c @@ -26,6 +26,7 @@ #include <getopt.h> #include <poll.h> +#include "parse-util.h" #include "udev.h" #include "util.h" diff --git a/src/udev/udevd.c b/src/udev/udevd.c index df5fd88bff..2c152129cc 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -43,6 +43,7 @@ #include "sd-daemon.h" #include "sd-event.h" +#include "alloc-util.h" #include "cgroup-util.h" #include "cpu-set-util.h" #include "dev-setup.h" @@ -50,16 +51,21 @@ #include "fd-util.h" #include "fileio.h" #include "formats-util.h" +#include "fs-util.h" #include "hashmap.h" #include "io-util.h" #include "netlink-util.h" +#include "parse-util.h" +#include "proc-cmdline.h" #include "process-util.h" #include "selinux-util.h" #include "signal-util.h" +#include "socket-util.h" #include "string-util.h" #include "terminal-util.h" #include "udev-util.h" #include "udev.h" +#include "user-util.h" static bool arg_debug = false; static int arg_daemonize = false; diff --git a/src/update-utmp/update-utmp.c b/src/update-utmp/update-utmp.c index bcabf65a36..d50063cbcd 100644 --- a/src/update-utmp/update-utmp.c +++ b/src/update-utmp/update-utmp.c @@ -29,15 +29,16 @@ #include "sd-bus.h" +#include "alloc-util.h" +#include "bus-error.h" +#include "bus-util.h" +#include "formats-util.h" #include "log.h" #include "macro.h" -#include "util.h" #include "special.h" -#include "utmp-wtmp.h" -#include "bus-util.h" -#include "bus-error.h" #include "unit-name.h" -#include "formats-util.h" +#include "util.h" +#include "utmp-wtmp.h" typedef struct Context { sd_bus *bus; diff --git a/src/vconsole/vconsole-setup.c b/src/vconsole/vconsole-setup.c index 49523a0a67..2298f1c2a9 100644 --- a/src/vconsole/vconsole-setup.c +++ b/src/vconsole/vconsole-setup.c @@ -31,9 +31,11 @@ #include <sys/ioctl.h> #include <unistd.h> +#include "alloc-util.h" #include "fd-util.h" #include "fileio.h" #include "io-util.h" +#include "locale-util.h" #include "log.h" #include "process-util.h" #include "signal-util.h" diff --git a/sysctl.d/50-default.conf b/sysctl.d/50-default.conf index def151bb84..2097551c33 100644 --- a/sysctl.d/50-default.conf +++ b/sysctl.d/50-default.conf @@ -35,6 +35,9 @@ net.ipv4.conf.all.promote_secondaries = 1 # Fair Queue CoDel packet scheduler to fight bufferbloat net.core.default_qdisc = fq_codel +# Make sure we can queue more than just a few datagrams in AF_UNIX sockets. +net.unix.max_dgram_qlen = 512 + # Enable hard and soft link protection fs.protected_hardlinks = 1 fs.protected_symlinks = 1 diff --git a/test/paths.target b/test/paths.target deleted file mode 120000 index e9939c9801..0000000000 --- a/test/paths.target +++ /dev/null @@ -1 +0,0 @@ -../units/paths.target
\ No newline at end of file diff --git a/test/test-execute/exec-capabilityboundingset-invert.service b/test/test-execute/exec-capabilityboundingset-invert.service new file mode 100644 index 0000000000..e2b09e1550 --- /dev/null +++ b/test/test-execute/exec-capabilityboundingset-invert.service @@ -0,0 +1,6 @@ +[Unit] +Description=Test for CapabilityBoundingSet + +[Service] +ExecStart=/bin/sh -c 'c=$(capsh --print | grep "Bounding set " | grep "cap_chown"); echo $c; exit $(test -z $c)' +CapabilityBoundingSet=~CAP_CHOWN diff --git a/test/test-execute/exec-capabilityboundingset-merge.service b/test/test-execute/exec-capabilityboundingset-merge.service new file mode 100644 index 0000000000..b0f4732529 --- /dev/null +++ b/test/test-execute/exec-capabilityboundingset-merge.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for CapabilityBoundingSet + +[Service] +ExecStart=/bin/sh -c 'c=$(capsh --print | grep "Bounding set " | cut -f 2 -d "="); echo $c; exit $(test $c = "cap_chown,cap_fowner,cap_kill")' +CapabilityBoundingSet=CAP_FOWNER +CapabilityBoundingSet=CAP_KILL CAP_CHOWN diff --git a/test/test-execute/exec-capabilityboundingset-reset.service b/test/test-execute/exec-capabilityboundingset-reset.service new file mode 100644 index 0000000000..51092ab0d5 --- /dev/null +++ b/test/test-execute/exec-capabilityboundingset-reset.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for CapabilityBoundingSet + +[Service] +ExecStart=/bin/sh -c 'c=$(capsh --print | grep "Bounding set " | cut -f 2 -d "="); echo $c; exit $(test -z $c)' +CapabilityBoundingSet=CAP_FOWNER CAP_KILL +CapabilityBoundingSet= diff --git a/test/test-execute/exec-capabilityboundingset-simple.service b/test/test-execute/exec-capabilityboundingset-simple.service new file mode 100644 index 0000000000..b9037a0ddf --- /dev/null +++ b/test/test-execute/exec-capabilityboundingset-simple.service @@ -0,0 +1,6 @@ +[Unit] +Description=Test for CapabilityBoundingSet + +[Service] +ExecStart=/bin/sh -c 'c=$(capsh --print | grep "Bounding set " | cut -f 2 -d "="); echo $c; exit $(test $c = "cap_fowner,cap_kill")' +CapabilityBoundingSet=CAP_FOWNER CAP_KILL diff --git a/test/exec-environment-empty.service b/test/test-execute/exec-environment-empty.service index 0219ca4fd7..0219ca4fd7 100644 --- a/test/exec-environment-empty.service +++ b/test/test-execute/exec-environment-empty.service diff --git a/test/exec-environment-multiple.service b/test/test-execute/exec-environment-multiple.service index 479005a5d8..479005a5d8 100644 --- a/test/exec-environment-multiple.service +++ b/test/test-execute/exec-environment-multiple.service diff --git a/test/exec-environment.service b/test/test-execute/exec-environment.service index 4586b4c4a9..4586b4c4a9 100644 --- a/test/exec-environment.service +++ b/test/test-execute/exec-environment.service diff --git a/test/test-execute/exec-environmentfile.service b/test/test-execute/exec-environmentfile.service new file mode 100644 index 0000000000..848f2a120c --- /dev/null +++ b/test/test-execute/exec-environmentfile.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for EnvironmentFile + +[Service] +ExecStart=/bin/sh -c 'exit $(test "$VAR1" = "word1 word2") && $(test "$VAR2" = word3) && $(test "$VAR3" = \'$word 5 6\')' +Type=oneshot +EnvironmentFile=/tmp/test-exec_environmentfile.conf diff --git a/test/exec-group.service b/test/test-execute/exec-group.service index 1aa04b5bd2..1aa04b5bd2 100644 --- a/test/exec-group.service +++ b/test/test-execute/exec-group.service diff --git a/test/exec-ignoresigpipe-no.service b/test/test-execute/exec-ignoresigpipe-no.service index 69b2e9d8a8..69b2e9d8a8 100644 --- a/test/exec-ignoresigpipe-no.service +++ b/test/test-execute/exec-ignoresigpipe-no.service diff --git a/test/exec-ignoresigpipe-yes.service b/test/test-execute/exec-ignoresigpipe-yes.service index 877ec8aed0..877ec8aed0 100644 --- a/test/exec-ignoresigpipe-yes.service +++ b/test/test-execute/exec-ignoresigpipe-yes.service diff --git a/test/test-execute/exec-ioschedulingclass-best-effort.service b/test/test-execute/exec-ioschedulingclass-best-effort.service new file mode 100644 index 0000000000..56e2718505 --- /dev/null +++ b/test/test-execute/exec-ioschedulingclass-best-effort.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for IOSchedulingClass=best-effort + +[Service] +ExecStart=/bin/bash -c 'c=$(ionice); echo $c; [[ "$c" == best-effort* ]]' +Type=oneshot +IOSchedulingClass=best-effort diff --git a/test/test-execute/exec-ioschedulingclass-idle.service b/test/test-execute/exec-ioschedulingclass-idle.service new file mode 100644 index 0000000000..b45795cab7 --- /dev/null +++ b/test/test-execute/exec-ioschedulingclass-idle.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for IOSchedulingClass=idle + +[Service] +ExecStart=/bin/bash -c 'c=$(ionice); echo $c; [[ "$c" == idle* ]]' +Type=oneshot +IOSchedulingClass=idle diff --git a/test/test-execute/exec-ioschedulingclass-none.service b/test/test-execute/exec-ioschedulingclass-none.service new file mode 100644 index 0000000000..36b546ca01 --- /dev/null +++ b/test/test-execute/exec-ioschedulingclass-none.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for IOSchedulingClass=none + +[Service] +ExecStart=/bin/bash -c 'c=$(ionice); echo $c; [[ "$c" == none* ]]' +Type=oneshot +IOSchedulingClass=none diff --git a/test/test-execute/exec-ioschedulingclass-realtime.service b/test/test-execute/exec-ioschedulingclass-realtime.service new file mode 100644 index 0000000000..74936d8079 --- /dev/null +++ b/test/test-execute/exec-ioschedulingclass-realtime.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for IOSchedulingClass=realtime + +[Service] +ExecStart=/bin/bash -c 'c=$(ionice); echo $c; [[ "$c" == realtime* ]]' +Type=oneshot +IOSchedulingClass=realtime diff --git a/test/test-execute/exec-oomscoreadjust-negative.service b/test/test-execute/exec-oomscoreadjust-negative.service new file mode 100644 index 0000000000..63ab501c63 --- /dev/null +++ b/test/test-execute/exec-oomscoreadjust-negative.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for OOMScoreAdjust + +[Service] +ExecStart=/bin/bash -c 'c=$(cat /proc/self/oom_score_adj); echo $c; exit $(test $c -eq -100)' +OOMScoreAdjust=-100 +Type=oneshot diff --git a/test/test-execute/exec-oomscoreadjust-positive.service b/test/test-execute/exec-oomscoreadjust-positive.service new file mode 100644 index 0000000000..e47a4f1392 --- /dev/null +++ b/test/test-execute/exec-oomscoreadjust-positive.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for OOMScoreAdjust + +[Service] +ExecStart=/bin/bash -c 'c=$(cat /proc/self/oom_score_adj); echo $c; exit $(test $c -eq 100)' +OOMScoreAdjust=100 +Type=oneshot diff --git a/test/exec-personality-s390.service b/test/test-execute/exec-personality-s390.service index f3c3b03e3d..f3c3b03e3d 100644 --- a/test/exec-personality-s390.service +++ b/test/test-execute/exec-personality-s390.service diff --git a/test/exec-personality-x86-64.service b/test/test-execute/exec-personality-x86-64.service index 5bb5d910d0..5bb5d910d0 100644 --- a/test/exec-personality-x86-64.service +++ b/test/test-execute/exec-personality-x86-64.service diff --git a/test/exec-personality-x86.service b/test/test-execute/exec-personality-x86.service index 0b370a6480..0b370a6480 100644 --- a/test/exec-personality-x86.service +++ b/test/test-execute/exec-personality-x86.service diff --git a/test/exec-privatedevices-no.service b/test/test-execute/exec-privatedevices-no.service index cf4f275fb6..cf4f275fb6 100644 --- a/test/exec-privatedevices-no.service +++ b/test/test-execute/exec-privatedevices-no.service diff --git a/test/exec-privatedevices-yes.service b/test/test-execute/exec-privatedevices-yes.service index 85b3f4f981..85b3f4f981 100644 --- a/test/exec-privatedevices-yes.service +++ b/test/test-execute/exec-privatedevices-yes.service diff --git a/test/test-execute/exec-privatenetwork-yes.service b/test/test-execute/exec-privatenetwork-yes.service new file mode 100644 index 0000000000..494712e6a7 --- /dev/null +++ b/test/test-execute/exec-privatenetwork-yes.service @@ -0,0 +1,6 @@ +[Unit] +Description=Test for PrivateNetwork + +[Service] +ExecStart=/bin/sh -c 'i=$(ip link | grep ": " | grep -v lo); echo $i; exit $(test -z $i)' +PrivateNetwork=yes diff --git a/test/exec-privatetmp-no.service b/test/test-execute/exec-privatetmp-no.service index d69e552a63..d69e552a63 100644 --- a/test/exec-privatetmp-no.service +++ b/test/test-execute/exec-privatetmp-no.service diff --git a/test/exec-privatetmp-yes.service b/test/test-execute/exec-privatetmp-yes.service index 881a040b87..881a040b87 100644 --- a/test/exec-privatetmp-yes.service +++ b/test/test-execute/exec-privatetmp-yes.service diff --git a/test/exec-runtimedirectory-mode.service b/test/test-execute/exec-runtimedirectory-mode.service index ba6d7ee39f..ba6d7ee39f 100644 --- a/test/exec-runtimedirectory-mode.service +++ b/test/test-execute/exec-runtimedirectory-mode.service diff --git a/test/exec-runtimedirectory-owner.service b/test/test-execute/exec-runtimedirectory-owner.service index 077e08d1c5..077e08d1c5 100644 --- a/test/exec-runtimedirectory-owner.service +++ b/test/test-execute/exec-runtimedirectory-owner.service diff --git a/test/exec-runtimedirectory.service b/test/test-execute/exec-runtimedirectory.service index c12a6c63d6..c12a6c63d6 100644 --- a/test/exec-runtimedirectory.service +++ b/test/test-execute/exec-runtimedirectory.service diff --git a/test/exec-systemcallerrornumber.service b/test/test-execute/exec-systemcallerrornumber.service index 255a8b231a..255a8b231a 100644 --- a/test/exec-systemcallerrornumber.service +++ b/test/test-execute/exec-systemcallerrornumber.service diff --git a/test/exec-systemcallfilter-failing.service b/test/test-execute/exec-systemcallfilter-failing.service index c6ce9368c9..c6ce9368c9 100644 --- a/test/exec-systemcallfilter-failing.service +++ b/test/test-execute/exec-systemcallfilter-failing.service diff --git a/test/exec-systemcallfilter-failing2.service b/test/test-execute/exec-systemcallfilter-failing2.service index b7f7c2aff9..b7f7c2aff9 100644 --- a/test/exec-systemcallfilter-failing2.service +++ b/test/test-execute/exec-systemcallfilter-failing2.service diff --git a/test/exec-systemcallfilter-not-failing.service b/test/test-execute/exec-systemcallfilter-not-failing.service index feb206ab6d..feb206ab6d 100644 --- a/test/exec-systemcallfilter-not-failing.service +++ b/test/test-execute/exec-systemcallfilter-not-failing.service diff --git a/test/exec-systemcallfilter-not-failing2.service b/test/test-execute/exec-systemcallfilter-not-failing2.service index cca469aa3d..cca469aa3d 100644 --- a/test/exec-systemcallfilter-not-failing2.service +++ b/test/test-execute/exec-systemcallfilter-not-failing2.service diff --git a/test/exec-umask-0177.service b/test/test-execute/exec-umask-0177.service index af9295888e..af9295888e 100644 --- a/test/exec-umask-0177.service +++ b/test/test-execute/exec-umask-0177.service diff --git a/test/exec-umask-default.service b/test/test-execute/exec-umask-default.service index 41e20a60a1..41e20a60a1 100644 --- a/test/exec-umask-default.service +++ b/test/test-execute/exec-umask-default.service diff --git a/test/exec-user.service b/test/test-execute/exec-user.service index 2ca08ebb42..2ca08ebb42 100644 --- a/test/exec-user.service +++ b/test/test-execute/exec-user.service diff --git a/test/exec-workingdirectory.service b/test/test-execute/exec-workingdirectory.service index 10855d682a..10855d682a 100644 --- a/test/exec-workingdirectory.service +++ b/test/test-execute/exec-workingdirectory.service diff --git a/test/test-path/basic.target b/test/test-path/basic.target new file mode 120000 index 0000000000..a882b72cc9 --- /dev/null +++ b/test/test-path/basic.target @@ -0,0 +1 @@ +../../units/basic.target
\ No newline at end of file diff --git a/test/path-changed.path b/test/test-path/path-changed.path index e58bdd925f..e58bdd925f 100644 --- a/test/path-changed.path +++ b/test/test-path/path-changed.path diff --git a/test/path-changed.service b/test/test-path/path-changed.service index 8bdf178830..8bdf178830 120000 --- a/test/path-changed.service +++ b/test/test-path/path-changed.service diff --git a/test/path-directorynotempty.path b/test/test-path/path-directorynotempty.path index 17e599fc0e..17e599fc0e 100644 --- a/test/path-directorynotempty.path +++ b/test/test-path/path-directorynotempty.path diff --git a/test/path-directorynotempty.service b/test/test-path/path-directorynotempty.service index 8bdf178830..8bdf178830 120000 --- a/test/path-directorynotempty.service +++ b/test/test-path/path-directorynotempty.service diff --git a/test/path-exists.path b/test/test-path/path-exists.path index c4c9105af4..c4c9105af4 100644 --- a/test/path-exists.path +++ b/test/test-path/path-exists.path diff --git a/test/path-exists.service b/test/test-path/path-exists.service index 8bdf178830..8bdf178830 120000 --- a/test/path-exists.service +++ b/test/test-path/path-exists.service diff --git a/test/path-existsglob.path b/test/test-path/path-existsglob.path index a058599605..a058599605 100644 --- a/test/path-existsglob.path +++ b/test/test-path/path-existsglob.path diff --git a/test/path-existsglob.service b/test/test-path/path-existsglob.service index 8bdf178830..8bdf178830 120000 --- a/test/path-existsglob.service +++ b/test/test-path/path-existsglob.service diff --git a/test/path-makedirectory.path b/test/test-path/path-makedirectory.path index 9408479c0f..9408479c0f 100644 --- a/test/path-makedirectory.path +++ b/test/test-path/path-makedirectory.path diff --git a/test/path-makedirectory.service b/test/test-path/path-makedirectory.service index 8bdf178830..8bdf178830 120000 --- a/test/path-makedirectory.service +++ b/test/test-path/path-makedirectory.service diff --git a/test/path-modified.path b/test/test-path/path-modified.path index 18363227ba..18363227ba 100644 --- a/test/path-modified.path +++ b/test/test-path/path-modified.path diff --git a/test/path-modified.service b/test/test-path/path-modified.service index 8bdf178830..8bdf178830 120000 --- a/test/path-modified.service +++ b/test/test-path/path-modified.service diff --git a/test/path-mycustomunit.service b/test/test-path/path-mycustomunit.service index 172ac0d0d5..172ac0d0d5 100644 --- a/test/path-mycustomunit.service +++ b/test/test-path/path-mycustomunit.service diff --git a/test/path-service.service b/test/test-path/path-service.service index f8499ec619..f8499ec619 100644 --- a/test/path-service.service +++ b/test/test-path/path-service.service diff --git a/test/path-unit.path b/test/test-path/path-unit.path index 95e572d6d5..95e572d6d5 100644 --- a/test/path-unit.path +++ b/test/test-path/path-unit.path diff --git a/test/test-path/paths.target b/test/test-path/paths.target new file mode 120000 index 0000000000..b402796cb9 --- /dev/null +++ b/test/test-path/paths.target @@ -0,0 +1 @@ +../../units/paths.target
\ No newline at end of file diff --git a/test/test-path/sysinit.target b/test/test-path/sysinit.target new file mode 120000 index 0000000000..9d10e5b2e2 --- /dev/null +++ b/test/test-path/sysinit.target @@ -0,0 +1 @@ +../../units/sysinit.target
\ No newline at end of file diff --git a/units/systemd-journald.service.in b/units/systemd-journald.service.in index 41bfde5be3..2552102bfc 100644 --- a/units/systemd-journald.service.in +++ b/units/systemd-journald.service.in @@ -22,7 +22,6 @@ RestartSec=0 NotifyAccess=all StandardOutput=null CapabilityBoundingSet=CAP_SYS_ADMIN CAP_DAC_OVERRIDE CAP_SYS_PTRACE CAP_SYSLOG CAP_AUDIT_CONTROL CAP_AUDIT_READ CAP_CHOWN CAP_DAC_READ_SEARCH CAP_FOWNER CAP_SETUID CAP_SETGID CAP_MAC_OVERRIDE -WatchdogSec=3min FileDescriptorStoreMax=1024 # Increase the default a bit in order to allow many simultaneous |