summaryrefslogtreecommitdiffstats
path: root/coccinelle
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:49:52 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:49:52 +0000
commit55944e5e40b1be2afc4855d8d2baf4b73d1876b5 (patch)
tree33f869f55a1b149e9b7c2b7e201867ca5dd52992 /coccinelle
parentInitial commit. (diff)
downloadsystemd-55944e5e40b1be2afc4855d8d2baf4b73d1876b5.tar.xz
systemd-55944e5e40b1be2afc4855d8d2baf4b73d1876b5.zip
Adding upstream version 255.4.upstream/255.4
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--coccinelle/bool-cast.cocci13
-rw-r--r--coccinelle/close-above-stdio.cocci37
-rw-r--r--coccinelle/cmp.cocci29
-rw-r--r--coccinelle/cond-omit-middle.cocci7
-rw-r--r--coccinelle/const-strlen.disabled15
-rw-r--r--coccinelle/debug-logging.cocci17
-rw-r--r--coccinelle/div-round-up.cocci21
-rw-r--r--coccinelle/dup-fcntl.cocci8
-rw-r--r--coccinelle/empty-or-dash.cocci6
-rw-r--r--coccinelle/empty-or-root.cocci11
-rw-r--r--coccinelle/empty-to-null.cocci13
-rw-r--r--coccinelle/empty-to-root.cocci17
-rw-r--r--coccinelle/enotsup.cocci5
-rw-r--r--coccinelle/equals-null.cocci30
-rw-r--r--coccinelle/errno-check.cocci11
-rw-r--r--coccinelle/errno-wrapper.cocci46
-rw-r--r--coccinelle/errno.cocci103
-rw-r--r--coccinelle/exit-0.cocci17
-rw-r--r--coccinelle/flags-set.cocci24
-rw-r--r--coccinelle/fopen-unlocked.cocci72
-rw-r--r--coccinelle/free_and_replace.cocci16
-rw-r--r--coccinelle/hashmap_free.cocci55
-rw-r--r--coccinelle/htonl.cocci21
-rw-r--r--coccinelle/in_set.cocci38
-rw-r--r--coccinelle/iovec-make.cocci34
-rw-r--r--coccinelle/isempty.cocci43
-rw-r--r--coccinelle/log-json.cocci9
-rw-r--r--coccinelle/macros.h231
-rw-r--r--coccinelle/malloc_multiply.cocci21
-rw-r--r--coccinelle/mempcpy.cocci13
-rw-r--r--coccinelle/memzero.cocci39
-rw-r--r--coccinelle/mfree.cocci7
-rw-r--r--coccinelle/mfree_return.cocci9
-rw-r--r--coccinelle/no-if-assignments.cocci21
-rw-r--r--coccinelle/not_in_set.cocci24
-rw-r--r--coccinelle/o-ndelay.cocci5
-rw-r--r--coccinelle/reallocarray.cocci21
-rw-r--r--coccinelle/redundant-if.cocci55
-rwxr-xr-xcoccinelle/run-coccinelle.sh48
-rw-r--r--coccinelle/safe_close-no-if.cocci8
-rw-r--r--coccinelle/safe_close.cocci19
-rw-r--r--coccinelle/safe_closedir.cocci28
-rw-r--r--coccinelle/safe_fclose.cocci28
-rw-r--r--coccinelle/sd_event_source_disable_unref.cocci37
-rw-r--r--coccinelle/set_ensure_put.cocci19
-rw-r--r--coccinelle/strdupa.cocci11
-rw-r--r--coccinelle/strempty.cocci73
-rw-r--r--coccinelle/strjoin.cocci16
-rw-r--r--coccinelle/strjoina.cocci8
-rw-r--r--coccinelle/strv_free.cocci28
-rw-r--r--coccinelle/swap-two.cocci8
-rw-r--r--coccinelle/synthetic-errno.cocci263
-rw-r--r--coccinelle/take-fd.cocci22
-rw-r--r--coccinelle/take-ptr.cocci15
-rw-r--r--coccinelle/timestamp-is-set.cocci73
-rw-r--r--coccinelle/while-true.cocci13
-rw-r--r--coccinelle/xsprintf.cocci8
-rw-r--r--coccinelle/zz-drop-braces.cocci28
58 files changed, 1917 insertions, 0 deletions
diff --git a/coccinelle/bool-cast.cocci b/coccinelle/bool-cast.cocci
new file mode 100644
index 0000000..a3311f0
--- /dev/null
+++ b/coccinelle/bool-cast.cocci
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+bool b;
+expression y;
+@@
+- b = !!(y);
++ b = y;
+@@
+bool b;
+expression y;
+@@
+- b = !!y;
++ b = y;
diff --git a/coccinelle/close-above-stdio.cocci b/coccinelle/close-above-stdio.cocci
new file mode 100644
index 0000000..93a0a85
--- /dev/null
+++ b/coccinelle/close-above-stdio.cocci
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+expression fd;
+@@
+- if (fd > 2)
+- safe_close(fd);
++ safe_close_above_stdio(fd);
+@@
+expression fd;
+@@
+- if (fd > 2)
+- fd = safe_close(fd);
++ fd = safe_close_above_stdio(fd);
+@@
+expression fd;
+@@
+- if (fd >= 3)
+- safe_close(fd);
++ safe_close_above_stdio(fd);
+@@
+expression fd;
+@@
+- if (fd >= 3)
+- fd = safe_close(fd);
++ fd = safe_close_above_stdio(fd);
+@@
+expression fd;
+@@
+- if (fd > STDERR_FILENO)
+- safe_close(fd);
++ safe_close_above_stdio(fd);
+@@
+expression fd;
+@@
+- if (fd > STDERR_FILENO)
+- fd = safe_close(fd);
++ fd = safe_close_above_stdio(fd);
diff --git a/coccinelle/cmp.cocci b/coccinelle/cmp.cocci
new file mode 100644
index 0000000..d5ab0f2
--- /dev/null
+++ b/coccinelle/cmp.cocci
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+expression x, y;
+@@
+- if (x < y)
+- return -1;
+- if (x > y)
+- return 1;
+- return 0;
++ return CMP(x, y);
+@@
+expression x, y;
+@@
+- if (x < y)
+- return -1;
+- else if (x > y)
+- return 1;
+- return 0;
++ return CMP(x, y);
+@@
+expression x, y;
+@@
+- if (x < y)
+- return -1;
+- else if (x > y)
+- return 1;
+- else
+- return 0;
++ return CMP(x, y);
diff --git a/coccinelle/cond-omit-middle.cocci b/coccinelle/cond-omit-middle.cocci
new file mode 100644
index 0000000..f1587b8
--- /dev/null
+++ b/coccinelle/cond-omit-middle.cocci
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/* See: https://gcc.gnu.org/onlinedocs/gcc/Conditionals.html#Conditionals */
+@@
+expression e, x;
+@@
+- e ? e : x
++ e ?: x
diff --git a/coccinelle/const-strlen.disabled b/coccinelle/const-strlen.disabled
new file mode 100644
index 0000000..8b1a635
--- /dev/null
+++ b/coccinelle/const-strlen.disabled
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+constant s;
+@@
+(
+#define STRLEN
+&
+- sizeof(s)-1
++ STRLEN(s)
+)
+@@
+constant s;
+@@
+- strlen(s)
++ STRLEN(s)
diff --git a/coccinelle/debug-logging.cocci b/coccinelle/debug-logging.cocci
new file mode 100644
index 0000000..2885350
--- /dev/null
+++ b/coccinelle/debug-logging.cocci
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+@@
+(
+#define DEBUG_LOGGING
+&
+- _unlikely_(log_get_max_level() >= LOG_DEBUG)
++ DEBUG_LOGGING
+)
+@@
+@@
+(
+#define DEBUG_LOGGING
+&
+- log_get_max_level() >= LOG_DEBUG
++ DEBUG_LOGGING
+)
diff --git a/coccinelle/div-round-up.cocci b/coccinelle/div-round-up.cocci
new file mode 100644
index 0000000..609ec87
--- /dev/null
+++ b/coccinelle/div-round-up.cocci
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+expression x, y;
+@@
+- ((x + y - 1) / y)
++ DIV_ROUND_UP(x, y)
+@@
+expression x, y;
+@@
+- ((x + (y - 1)) / y)
++ DIV_ROUND_UP(x, y)
+@@
+expression x, y;
+@@
+- (x + y - 1) / y
++ DIV_ROUND_UP(x, y)
+@@
+expression x, y;
+@@
+- (x + (y - 1)) / y
++ DIV_ROUND_UP(x, y)
diff --git a/coccinelle/dup-fcntl.cocci b/coccinelle/dup-fcntl.cocci
new file mode 100644
index 0000000..2c87f70
--- /dev/null
+++ b/coccinelle/dup-fcntl.cocci
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+/* We want to stick with dup() in test-fd-util.c */
+position p : script:python() { p[0].file != "src/test/test-fd-util.c" };
+expression fd;
+@@
+- dup@p(fd)
++ fcntl(fd, F_DUPFD, 3)
diff --git a/coccinelle/empty-or-dash.cocci b/coccinelle/empty-or-dash.cocci
new file mode 100644
index 0000000..56246af
--- /dev/null
+++ b/coccinelle/empty-or-dash.cocci
@@ -0,0 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+expression s;
+@@
+- (isempty(s) || streq(s, "-"))
++ empty_or_dash(s)
diff --git a/coccinelle/empty-or-root.cocci b/coccinelle/empty-or-root.cocci
new file mode 100644
index 0000000..d36f0c8
--- /dev/null
+++ b/coccinelle/empty-or-root.cocci
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+expression s;
+@@
+- (isempty(s) || path_equal(s, "/"))
++ empty_or_root(s)
+@@
+expression s;
+@@
+- (!isempty(s) && !path_equal(s, "/"))
++ !empty_or_root(s)
diff --git a/coccinelle/empty-to-null.cocci b/coccinelle/empty-to-null.cocci
new file mode 100644
index 0000000..82819e9
--- /dev/null
+++ b/coccinelle/empty-to-null.cocci
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+/* Avoid running this transformation on the empty_to_null macro itself.
+ * See the note in strempty.cocci to understand the weird magic below.
+*/
+position p : script:python() {
+ not (p[0].file == "src/basic/string-util.h" and p[0].current_element == "something_else")
+};
+expression s;
+@@
+
+- isempty@p(s) ? NULL : s
++ empty_to_null(s)
diff --git a/coccinelle/empty-to-root.cocci b/coccinelle/empty-to-root.cocci
new file mode 100644
index 0000000..9a65a69
--- /dev/null
+++ b/coccinelle/empty-to-root.cocci
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+expression s;
+@@
+- if (empty_or_root(s))
+- s = "/";
++ s = empty_to_root(s);
+@@
+expression s;
+@@
+- (empty_or_root(s) ? "/" : s)
++ empty_to_root(s)
+@@
+expression s;
+@@
+- (s ? s : "/")
++ empty_to_root(s)
diff --git a/coccinelle/enotsup.cocci b/coccinelle/enotsup.cocci
new file mode 100644
index 0000000..47ac4b7
--- /dev/null
+++ b/coccinelle/enotsup.cocci
@@ -0,0 +1,5 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+@@
+- ENOTSUP
++ EOPNOTSUPP
diff --git a/coccinelle/equals-null.cocci b/coccinelle/equals-null.cocci
new file mode 100644
index 0000000..92c7054
--- /dev/null
+++ b/coccinelle/equals-null.cocci
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+expression e;
+statement s;
+@@
+if (
+(
+!e
+|
+- e == NULL
++ !e
+)
+ )
+ {...}
+else s
+
+@@
+expression e;
+statement s;
+@@
+if (
+(
+e
+|
+- e != NULL
++ e
+)
+ )
+ {...}
+else s
diff --git a/coccinelle/errno-check.cocci b/coccinelle/errno-check.cocci
new file mode 100644
index 0000000..f6f0071
--- /dev/null
+++ b/coccinelle/errno-check.cocci
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+constant c;
+@@
+(
+- errno == -c
++ errno == c
+|
+- errno != -c
++ errno != c
+)
diff --git a/coccinelle/errno-wrapper.cocci b/coccinelle/errno-wrapper.cocci
new file mode 100644
index 0000000..61c8782
--- /dev/null
+++ b/coccinelle/errno-wrapper.cocci
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+expression r;
+@@
+- (r < 0 && ERRNO_IS_TRANSIENT(r))
++ ERRNO_IS_NEG_TRANSIENT(r)
+@@
+expression r;
+@@
+- (r < 0 && ERRNO_IS_DISCONNECT(r))
++ ERRNO_IS_NEG_DISCONNECT(r)
+@@
+expression r;
+@@
+- (r < 0 && ERRNO_IS_ACCEPT_AGAIN(r))
++ ERRNO_IS_NEG_ACCEPT_AGAIN(r)
+@@
+expression r;
+@@
+- (r < 0 && ERRNO_IS_RESOURCE(r))
++ ERRNO_IS_NEG_RESOURCE(r)
+@@
+expression r;
+@@
+- (r < 0 && ERRNO_IS_NOT_SUPPORTED(r))
++ ERRNO_IS_NEG_NOT_SUPPORTED(r)
+@@
+expression r;
+@@
+- (r < 0 && ERRNO_IS_PRIVILEGE(r))
++ ERRNO_IS_NEG_PRIVILEGE(r)
+@@
+expression r;
+@@
+- (r < 0 && ERRNO_IS_DISK_SPACE(r))
++ ERRNO_IS_NEG_DISK_SPACE(r)
+@@
+expression r;
+@@
+- (r < 0 && ERRNO_IS_DEVICE_ABSENT(r))
++ ERRNO_IS_NEG_DEVICE_ABSENT(r)
+@@
+expression r;
+@@
+- (r < 0 && ERRNO_IS_XATTR_ABSENT(r))
++ ERRNO_IS_NEG_XATTR_ABSENT(r)
diff --git a/coccinelle/errno.cocci b/coccinelle/errno.cocci
new file mode 100644
index 0000000..dd886ea
--- /dev/null
+++ b/coccinelle/errno.cocci
@@ -0,0 +1,103 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+identifier log_LEVEL_errno =~ "^log_(debug|info|notice|warning|error|emergency)_errno$";
+local idexpression r;
+expression e;
+@@
+- r = -e;
++ r =
+ log_LEVEL_errno(e, ...);
+@@
+identifier log_LEVEL_errno =~ "^log_(debug|info|notice|warning|error|emergency)_errno$";
+local idexpression r;
+expression e;
+@@
++ r =
+ log_LEVEL_errno(e, ...);
+- r = -e;
+@@
+identifier log_LEVEL_errno =~ "^log_(debug|info|notice|warning|error|emergency)_errno$";
+local idexpression r;
+expression e;
+@@
+- r =
++ return
+ log_LEVEL_errno(e, ...);
+- return r;
+@@
+identifier log_LEVEL_errno =~ "^log_(debug|info|notice|warning|error|emergency)_errno$";
+local idexpression r;
+@@
++ return
+ log_LEVEL_errno(r, ...);
+- return r;
+@@
+identifier log_LEVEL_errno =~ "^log_(debug|info|notice|warning|error|emergency)_errno$";
+expression e;
+@@
++ return
+ log_LEVEL_errno(e, ...);
+- return -e;
+@@
+identifier log_LEVEL_errno =~ "^log_(debug|info|notice|warning|error|emergency)_errno$";
+expression list args;
+expression e;
+local idexpression r;
+@@
+- log_LEVEL_errno(e, args);
+- r = e;
++ r = log_LEVEL_errno(e, args);
+@@
+identifier log_UNIT_LEVEL_errno =~ "^log_(unit|link|netdev|device|token)_(debug|info|notice|warning|error|emergency)_errno$";
+local idexpression r;
+expression e;
+expression u;
+@@
+- r = -e;
++ r =
+ log_UNIT_LEVEL_errno(u, e, ...);
+@@
+identifier log_UNIT_LEVEL_errno =~ "^log_(unit|link|netdev|device|token)_(debug|info|notice|warning|error|emergency)_errno$";
+local idexpression r;
+expression e;
+expression u;
+@@
++ r =
+ log_UNIT_LEVEL_errno(u, e, ...);
+- r = -e;
+@@
+identifier log_UNIT_LEVEL_errno =~ "^log_(unit|link|netdev|device|token)_(debug|info|notice|warning|error|emergency)_errno$";
+local idexpression r;
+expression e;
+expression u;
+@@
+- r =
++ return
+ log_UNIT_LEVEL_errno(u, e, ...);
+- return r;
+@@
+identifier log_UNIT_LEVEL_errno =~ "^log_(unit|link|netdev|device|token)_(debug|info|notice|warning|error|emergency)_errno$";
+local idexpression r;
+expression u;
+@@
++ return
+ log_UNIT_LEVEL_errno(u, r, ...);
+- return r;
+@@
+identifier log_UNIT_LEVEL_errno =~ "^log_(unit|link|netdev|device|token)_(debug|info|notice|warning|error|emergency)_errno$";
+expression e;
+expression u;
+@@
++ return
+ log_UNIT_LEVEL_errno(u, e, ...);
+- return -e;
+@@
+identifier log_UNIT_LEVEL_errno =~ "^log_(unit|link|netdev|device|token)_(debug|info|notice|warning|error|emergency)_errno$";
+expression list args;
+expression e;
+expression u;
+local idexpression r;
+@@
+- log_UNIT_LEVEL_errno(u, e, args);
+- r = e;
++ r = log_UNIT_LEVEL_errno(u, e, args);
diff --git a/coccinelle/exit-0.cocci b/coccinelle/exit-0.cocci
new file mode 100644
index 0000000..ff3d965
--- /dev/null
+++ b/coccinelle/exit-0.cocci
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+@@
+- exit(0);
++ exit(EXIT_SUCCESS);
+@@
+@@
+- _exit(0);
++ _exit(EXIT_SUCCESS);
+@@
+@@
+- exit(1);
++ exit(EXIT_FAILURE);
+@@
+@@
+- _exit(1);
++ _exit(EXIT_FAILURE);
diff --git a/coccinelle/flags-set.cocci b/coccinelle/flags-set.cocci
new file mode 100644
index 0000000..bcf08db
--- /dev/null
+++ b/coccinelle/flags-set.cocci
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+/* Disable this transformation in cases where it doesn't make sense or
+ * where it makes the resulting expression more confusing
+ */
+position p : script:python() {
+ not (p[0].file == "src/shared/securebits-util.h" or
+ p[0].file == "src/core/manager.h" or
+ p[0].current_element == "log_set_max_level_realm" or
+ p[0].current_element == "unichar_is_valid")
+ };
+expression x;
+constant y;
+@@
+(
+- ((x@p) & (y)) == (y)
++ FLAGS_SET(x, y)
+|
+- (x@p & (y)) == (y)
++ FLAGS_SET(x, y)
+|
+- ((x@p) & y) == y
++ FLAGS_SET(x, y)
+)
diff --git a/coccinelle/fopen-unlocked.cocci b/coccinelle/fopen-unlocked.cocci
new file mode 100644
index 0000000..1caa698
--- /dev/null
+++ b/coccinelle/fopen-unlocked.cocci
@@ -0,0 +1,72 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+expression f, path, options;
+@@
+- f = fopen(path, options);
+- if (!f)
+- return -errno;
+- (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
++ r = fopen_unlocked(path, options, &f);
++ if (r < 0)
++ return r;
+@@
+expression f, path, options;
+@@
+- f = fopen(path, options);
+- if (!f) {
+- if (errno == ENOENT)
+- return -ESRCH;
+- return -errno;
+- }
+- (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
++ r = fopen_unlocked(path, options, &f);
++ if (r == -ENOENT)
++ return -ESRCH;
++ if (r < 0)
++ return r;
+@@
+expression f, path, options;
+@@
+- f = fopen(path, options);
+- if (!f)
+- return errno == ENOENT ? -ESRCH : -errno;
+- (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
++ r = fopen_unlocked(path, options, &f);
++ if (r == -ENOENT)
++ return -ESRCH;
++ if (r < 0)
++ return r;
+@@
+expression f, path, p;
+@@
+ r = fopen_temporary(path, &f, &p);
+ if (r < 0)
+ return ...;
+- (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+@@
+expression f, g, path, p;
+@@
+ r = fopen_temporary_label(path, g, &f, &p);
+ if (r < 0)
+ return ...;
+- (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+@@
+expression f, fd, options;
+@@
+- f = fdopen(fd, options);
++ r = fdopen_unlocked(fd, options, &f);
++ if (r < 0) {
+- if (!f) {
+ ...
+- return -errno;
++ return r;
+ }
+- (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+@@
+expression f, buf, sz;
+@@
+- f = open_memstream(&buf, &sz);
++ f = open_memstream_unlocked(&buf, &sz);
+ if (!f)
+ return ...;
+- (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
diff --git a/coccinelle/free_and_replace.cocci b/coccinelle/free_and_replace.cocci
new file mode 100644
index 0000000..7d8b6a7
--- /dev/null
+++ b/coccinelle/free_and_replace.cocci
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+expression p, q;
+@@
+- free(p);
+- p = q;
+- q = NULL;
+- return 0;
++ return free_and_replace(p, q);
+@@
+expression p, q;
+@@
+- free(p);
+- p = q;
+- q = NULL;
++ free_and_replace(p, q);
diff --git a/coccinelle/hashmap_free.cocci b/coccinelle/hashmap_free.cocci
new file mode 100644
index 0000000..31e1279
--- /dev/null
+++ b/coccinelle/hashmap_free.cocci
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+expression p;
+@@
+- set_free(p);
+- p = NULL;
++ p = set_free(p);
+@@
+expression p;
+@@
+- if (p)
+- set_free(p);
+- p = NULL;
++ p = set_free(p);
+@@
+expression p;
+@@
+- if (p) {
+- set_free(p);
+- p = NULL;
+- }
++ p = set_free(p);
+@@
+expression p;
+@@
+- if (p)
+- set_free(p);
++ set_free(p);
+@@
+expression p;
+@@
+- hashmap_free(p);
+- p = NULL;
++ p = hashmap_free(p);
+@@
+expression p;
+@@
+- if (p)
+- hashmap_free(p);
+- p = NULL;
++ p = hashmap_free(p);
+@@
+expression p;
+@@
+- if (p) {
+- hashmap_free(p);
+- p = NULL;
+- }
++ p = hashmap_free(p);
+@@
+expression p;
+@@
+- if (p)
+- hashmap_free(p);
++ hashmap_free(p);
diff --git a/coccinelle/htonl.cocci b/coccinelle/htonl.cocci
new file mode 100644
index 0000000..c247d24
--- /dev/null
+++ b/coccinelle/htonl.cocci
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+expression s;
+@@
+- htonl(s)
++ htobe32(s)
+@@
+expression s;
+@@
+- htons(s)
++ htobe16(s)
+@@
+expression s;
+@@
+- ntohl(s)
++ be32toh(s)
+@@
+expression s;
+@@
+- ntohs(s)
++ be16toh(s)
diff --git a/coccinelle/in_set.cocci b/coccinelle/in_set.cocci
new file mode 100644
index 0000000..a3b02f9
--- /dev/null
+++ b/coccinelle/in_set.cocci
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/* Limit the number of expressions to 6 for performance reasons */
+
+@ is_in_assert_cc @
+identifier id = assert_cc;
+position p1;
+expression e;
+constant n0;
+@@
+
+ id(e@p1 == n0 || ...);
+
+@@
+expression e;
+position p2 != is_in_assert_cc.p1;
+/* Exclude JsonVariant * from the transformation, as it can't work with the
+ * current version of the IN_SET macro */
+typedef JsonVariant;
+type T != JsonVariant*;
+constant T n0, n1, n2, n3, n4, n5;
+@@
+
+(
+- e@p2 == n0 || e == n1 || e == n2 || e == n3 || e == n4 || e == n5
++ IN_SET(e, n0, n1, n2, n3, n4, n5)
+|
+- e@p2 == n0 || e == n1 || e == n2 || e == n3 || e == n4
++ IN_SET(e, n0, n1, n2, n3, n4)
+|
+- e@p2 == n0 || e == n1 || e == n2 || e == n3
++ IN_SET(e, n0, n1, n2, n3)
+|
+- e@p2 == n0 || e == n1 || e == n2
++ IN_SET(e, n0, n1, n2)
+|
+- e@p2 == n0 || e == n1
++ IN_SET(e, n0, n1)
+)
diff --git a/coccinelle/iovec-make.cocci b/coccinelle/iovec-make.cocci
new file mode 100644
index 0000000..bbbf4a2
--- /dev/null
+++ b/coccinelle/iovec-make.cocci
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+expression x, y, p, l;
+@@
+- x[y].iov_base = p;
+- x[y].iov_len = l;
+- y++;
++ x[y++] = IOVEC_MAKE(p, l);
+@@
+expression x, p, l;
+@@
+- x.iov_base = p;
+- x.iov_len = l;
++ x = IOVEC_MAKE(p, l);
+@@
+/* Don't run this transformation on iovec_done() and iovec_done_erase(),
+ * since the result, albeit correct, is a bit funky. */
+ position pos : script:python() { pos[0].current_element != "iovec_done" and
+ pos[0].current_element != "iovec_done_erase" };
+expression x, p, l;
+@@
+- x->iov_base@pos = p;
+- x->iov_len = l;
++ *x = IOVEC_MAKE(p, l);
+@@
+expression s;
+@@
+- IOVEC_MAKE(s, strlen(s));
++ IOVEC_MAKE_STRING(s);
+@@
+expression x, y, z;
+@@
+- x = (struct iovec) { .iov_base = y, .iov_len = z };
++ x = IOVEC_MAKE(y, z);
diff --git a/coccinelle/isempty.cocci b/coccinelle/isempty.cocci
new file mode 100644
index 0000000..b1b9277
--- /dev/null
+++ b/coccinelle/isempty.cocci
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+/* Disable this transformation for the test-string-util.c */
+position p : script:python() { p[0].file != "src/test/test-string-util.c" };
+expression s;
+@@
+(
+- strv_length@p(s) == 0
++ strv_isempty(s)
+|
+- strv_length@p(s) <= 0
++ strv_isempty(s)
+|
+- strv_length@p(s) > 0
++ !strv_isempty(s)
+|
+- strv_length@p(s) != 0
++ !strv_isempty(s)
+|
+- strlen@p(s) == 0
++ isempty(s)
+|
+- strlen@p(s) <= 0
++ isempty(s)
+|
+- strlen@p(s) > 0
++ !isempty(s)
+|
+- strlen@p(s) != 0
++ !isempty(s)
+|
+- strlen_ptr@p(s) == 0
++ isempty(s)
+|
+- strlen_ptr@p(s) <= 0
++ isempty(s)
+|
+- strlen_ptr@p(s) > 0
++ !isempty(s)
+|
+- strlen_ptr@p(s) != 0
++ !isempty(s)
+)
diff --git a/coccinelle/log-json.cocci b/coccinelle/log-json.cocci
new file mode 100644
index 0000000..d184e56
--- /dev/null
+++ b/coccinelle/log-json.cocci
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+expression e, v, flags;
+expression list args;
+@@
++ return
+- json_log(v, flags, 0, args);
++ json_log(v, flags, SYNTHETIC_ERRNO(e), args);
+- return -e;
diff --git a/coccinelle/macros.h b/coccinelle/macros.h
new file mode 100644
index 0000000..adfea5f
--- /dev/null
+++ b/coccinelle/macros.h
@@ -0,0 +1,231 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Collected macros from our systemd codebase to make the cocci semantic
+ * parser happy. Inspired by the original cocci macros file
+ * /usr/lib64/coccinelle/standard.h (including the YACFE_* symbols)
+ */
+
+// General
+#define PTR_TO_PID(x)
+
+// src/basic/macro.h
+#define _printf_(a, b) __attribute__((__format__(printf, a, b)))
+#define _alloc_(...) __attribute__((__alloc_size__(__VA_ARGS__)))
+#define _sentinel_ __attribute__((__sentinel__))
+#define _section_(x) __attribute__((__section__(x)))
+#define _used_ __attribute__((__used__))
+#define _unused_ __attribute__((__unused__))
+#define _destructor_ __attribute__((__destructor__))
+#define _pure_ __attribute__((__pure__))
+#define _const_ __attribute__((__const__))
+#define _deprecated_ __attribute__((__deprecated__))
+#define _packed_ __attribute__((__packed__))
+#define _malloc_ __attribute__((__malloc__))
+#define _weak_ __attribute__((__weak__))
+#define _likely_(x) (__builtin_expect(!!(x), 1))
+#define _unlikely_(x) (__builtin_expect(!!(x), 0))
+#define _public_ __attribute__((__visibility__("default")))
+#define _hidden_ __attribute__((__visibility__("hidden")))
+#define _weakref_(x) __attribute__((__weakref__(#x)))
+#define _align_(x) __attribute__((__aligned__(x)))
+#define _alignas_(x) __attribute__((__aligned__(__alignof(x))))
+#define _alignptr_ __attribute__((__aligned__(sizeof(void*))))
+#define _cleanup_(x) __attribute__((__cleanup__(x)))
+#define _fallthrough_
+#define _noreturn_ __attribute__((__noreturn__))
+#define thread_local __thread
+
+#define ELEMENTSOF(x) \
+ (__builtin_choose_expr( \
+ !__builtin_types_compatible_p(typeof(x), typeof(&*(x))), \
+ sizeof(x)/sizeof((x)[0]), \
+ VOID_0))
+
+// src/basic/umask-util.h
+#define _cleanup_umask_
+#define WITH_UMASK(mask) \
+ for (_cleanup_umask_ mode_t _saved_umask_ = umask(mask) | S_IFMT; \
+ FLAGS_SET(_saved_umask_, S_IFMT); \
+ _saved_umask_ &= 0777)
+
+// src/basic/hashmap.h
+#define _IDX_ITERATOR_FIRST (UINT_MAX - 1)
+#define HASHMAP_FOREACH(e, h) YACFE_ITERATOR
+#define ORDERED_HASHMAP_FOREACH(e, h) YACFE_ITERATOR
+#define HASHMAP_FOREACH_KEY(e, k, h) YACFE_ITERATOR
+#define ORDERED_HASHMAP_FOREACH_KEY(e, k, h) YACFE_ITERATOR
+
+// src/basic/list.h
+#define LIST_HEAD(t,name) \
+ t *name
+#define LIST_FIELDS(t,name) \
+ t *name##_next, *name##_prev
+#define LIST_HEAD_INIT(head) \
+ do { \
+ (head) = NULL; \
+ } while (false)
+#define LIST_INIT(name,item) \
+ do { \
+ typeof(*(item)) *_item = (item); \
+ assert(_item); \
+ _item->name##_prev = _item->name##_next = NULL; \
+ } while (false)
+#define LIST_PREPEND(name,head,item) \
+ do { \
+ typeof(*(head)) **_head = &(head), *_item = (item); \
+ assert(_item); \
+ if ((_item->name##_next = *_head)) \
+ _item->name##_next->name##_prev = _item; \
+ _item->name##_prev = NULL; \
+ *_head = _item; \
+ } while (false)
+#define LIST_APPEND(name,head,item) \
+ do { \
+ typeof(*(head)) **_hhead = &(head), *_tail; \
+ LIST_FIND_TAIL(name, *_hhead, _tail); \
+ LIST_INSERT_AFTER(name, *_hhead, _tail, item); \
+ } while (false)
+#define LIST_REMOVE(name,head,item) \
+ do { \
+ typeof(*(head)) **_head = &(head), *_item = (item); \
+ assert(_item); \
+ if (_item->name##_next) \
+ _item->name##_next->name##_prev = _item->name##_prev; \
+ if (_item->name##_prev) \
+ _item->name##_prev->name##_next = _item->name##_next; \
+ else { \
+ assert(*_head == _item); \
+ *_head = _item->name##_next; \
+ } \
+ _item->name##_next = _item->name##_prev = NULL; \
+ } while (false)
+#define LIST_FIND_HEAD(name,item,head) \
+ do { \
+ typeof(*(item)) *_item = (item); \
+ if (!_item) \
+ (head) = NULL; \
+ else { \
+ while (_item->name##_prev) \
+ _item = _item->name##_prev; \
+ (head) = _item; \
+ } \
+ } while (false)
+#define LIST_FIND_TAIL(name,item,tail) \
+ do { \
+ typeof(*(item)) *_item = (item); \
+ if (!_item) \
+ (tail) = NULL; \
+ else { \
+ while (_item->name##_next) \
+ _item = _item->name##_next; \
+ (tail) = _item; \
+ } \
+ } while (false)
+#define LIST_INSERT_AFTER(name,head,a,b) \
+ do { \
+ typeof(*(head)) **_head = &(head), *_a = (a), *_b = (b); \
+ assert(_b); \
+ if (!_a) { \
+ if ((_b->name##_next = *_head)) \
+ _b->name##_next->name##_prev = _b; \
+ _b->name##_prev = NULL; \
+ *_head = _b; \
+ } else { \
+ if ((_b->name##_next = _a->name##_next)) \
+ _b->name##_next->name##_prev = _b; \
+ _b->name##_prev = _a; \
+ _a->name##_next = _b; \
+ } \
+ } while (false)
+#define LIST_INSERT_BEFORE(name,head,a,b) \
+ do { \
+ typeof(*(head)) **_head = &(head), *_a = (a), *_b = (b); \
+ assert(_b); \
+ if (!_a) { \
+ if (!*_head) { \
+ _b->name##_next = NULL; \
+ _b->name##_prev = NULL; \
+ *_head = _b; \
+ } else { \
+ typeof(*(head)) *_tail = (head); \
+ while (_tail->name##_next) \
+ _tail = _tail->name##_next; \
+ _b->name##_next = NULL; \
+ _b->name##_prev = _tail; \
+ _tail->name##_next = _b; \
+ } \
+ } else { \
+ if ((_b->name##_prev = _a->name##_prev)) \
+ _b->name##_prev->name##_next = _b; \
+ else \
+ *_head = _b; \
+ _b->name##_next = _a; \
+ _a->name##_prev = _b; \
+ } \
+ } while (false)
+
+#define LIST_JUST_US(name,item) \
+ (!(item)->name##_prev && !(item)->name##_next)
+#define LIST_FOREACH(name,i,head) \
+ for ((i) = (head); (i); (i) = (i)->name##_next)
+#define LIST_FOREACH_SAFE(name,i,n,head) \
+ for ((i) = (head); (i) && (((n) = (i)->name##_next), 1); (i) = (n))
+#define LIST_FOREACH_BEFORE(name,i,p) \
+ for ((i) = (p)->name##_prev; (i); (i) = (i)->name##_prev)
+#define LIST_FOREACH_AFTER(name,i,p) \
+ for ((i) = (p)->name##_next; (i); (i) = (i)->name##_next)
+#define LIST_FOREACH_OTHERS(name,i,p) \
+ for (({ \
+ (i) = (p); \
+ while ((i) && (i)->name##_prev) \
+ (i) = (i)->name##_prev; \
+ if ((i) == (p)) \
+ (i) = (p)->name##_next; \
+ }); \
+ (i); \
+ (i) = (i)->name##_next == (p) ? (p)->name##_next : (i)->name##_next)
+#define LIST_LOOP_BUT_ONE(name,i,head,p) \
+ for ((i) = (p)->name##_next ? (p)->name##_next : (head); \
+ (i) != (p); \
+ (i) = (i)->name##_next ? (i)->name##_next : (head))
+
+#define LIST_JOIN(name,a,b) \
+ do { \
+ assert(b); \
+ if (!(a)) \
+ (a) = (b); \
+ else { \
+ typeof(*(a)) *_head = (b), *_tail; \
+ LIST_FIND_TAIL(name, (a), _tail); \
+ _tail->name##_next = _head; \
+ _head->name##_prev = _tail; \
+ } \
+ (b) = NULL; \
+ } while (false)
+
+// src/basic/strv.h
+#define STRV_FOREACH(s, l) YACFE_ITERATOR
+#define STRV_FOREACH_BACKWARDS(s, l) YACFE_ITERATOR
+#define STRV_FOREACH_PAIR(x, y, l) YACFE_ITERATOR
+
+// src/basic/socket-util.h
+#define CMSG_BUFFER_TYPE(size) \
+ union { \
+ struct cmsghdr cmsghdr; \
+ uint8_t buf[size]; \
+ uint8_t align_check[(size) >= CMSG_SPACE(0) && \
+ (size) == CMSG_ALIGN(size) ? 1 : -1]; \
+ }
+
+// src/libsystemd/sd-device/device-util.h
+#define FOREACH_DEVICE_PROPERTY(device, key, value) YACFE_ITERATOR
+#define FOREACH_DEVICE_TAG(device, tag) YACFE_ITERATOR
+#define FOREACH_DEVICE_CURRENT_TAG(device, tag) YACFE_ITERATOR
+#define FOREACH_DEVICE_SYSATTR(device, attr) YACFE_ITERATOR
+#define FOREACH_DEVICE_DEVLINK(device, devlink) YACFE_ITERATOR
+#define FOREACH_DEVICE(enumerator, device) YACFE_ITERATOR
+#define FOREACH_SUBSYSTEM(enumerator, device) YACFE_ITERATOR
+
+// src/basic/dirent-util.h
+#define FOREACH_DIRENT(de, d, on_error) YACFE_ITERATOR
+#define FOREACH_DIRENT_ALL(de, d, on_error) YACFE_ITERATOR
diff --git a/coccinelle/malloc_multiply.cocci b/coccinelle/malloc_multiply.cocci
new file mode 100644
index 0000000..320d257
--- /dev/null
+++ b/coccinelle/malloc_multiply.cocci
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+expression q, n, m;
+@@
+- q = malloc((n)*(m))
++ q = malloc_multiply(n, m)
+@@
+expression q, n, m;
+@@
+- q = malloc(n*(m))
++ q = malloc_multiply(n, m)
+@@
+expression q, n, m;
+@@
+- q = malloc((n)*m)
++ q = malloc_multiply(n, m)
+@@
+expression q, n, m;
+@@
+- q = malloc(n*m)
++ q = malloc_multiply(n, m)
diff --git a/coccinelle/mempcpy.cocci b/coccinelle/mempcpy.cocci
new file mode 100644
index 0000000..efb657a
--- /dev/null
+++ b/coccinelle/mempcpy.cocci
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+expression x, y, z;
+@@
+- memcpy(x, y, z);
+- x += z;
++ x = mempcpy(x, y, z);
+@@
+expression x, y, z;
+@@
+- memcpy_safe(x, y, z);
+- x += z;
++ x = mempcpy_safe(x, y, z);
diff --git a/coccinelle/memzero.cocci b/coccinelle/memzero.cocci
new file mode 100644
index 0000000..90fa0dd
--- /dev/null
+++ b/coccinelle/memzero.cocci
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+expression s;
+@@
+- memset(&s, 0, sizeof(s))
++ zero(s)
+@@
+expression s;
+@@
+- memset(s, 0, sizeof(*s))
++ zero(*s)
+@@
+expression s;
+@@
+- bzero(&s, sizeof(s))
++ zero(s)
+@@
+expression s;
+@@
+- bzero(s, sizeof(*s))
++ zero(*s)
+@@
+expression a, b;
+@@
+(
+#define memzero
+&
+- memset(a, 0, b)
++ memzero(a, b)
+)
+@@
+expression a, b;
+@@
+(
+#define memzero
+&
+- bzero(a, b)
++ memzero(a, b)
+)
diff --git a/coccinelle/mfree.cocci b/coccinelle/mfree.cocci
new file mode 100644
index 0000000..191cd62
--- /dev/null
+++ b/coccinelle/mfree.cocci
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+expression p;
+@@
+- free(p);
+- p = NULL;
++ p = mfree(p);
diff --git a/coccinelle/mfree_return.cocci b/coccinelle/mfree_return.cocci
new file mode 100644
index 0000000..c2c4cb3
--- /dev/null
+++ b/coccinelle/mfree_return.cocci
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+/* Avoid running this transformation on the mfree function itself */
+position p : script:python() { p[0].current_element != "mfree" };
+expression e;
+@@
+- free@p(e);
+- return NULL;
++ return mfree(e);
diff --git a/coccinelle/no-if-assignments.cocci b/coccinelle/no-if-assignments.cocci
new file mode 100644
index 0000000..9fbc018
--- /dev/null
+++ b/coccinelle/no-if-assignments.cocci
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+expression p, q;
+identifier r;
+statement s;
+@@
+- if ((r = q) < p)
+- s
++ r = q;
++ if (r < p)
++ s
+@@
+expression p, q;
+identifier r;
+statement s;
+@@
+- if ((r = q) >= p)
+- s
++ r = q;
++ if (r >= p)
++ s
diff --git a/coccinelle/not_in_set.cocci b/coccinelle/not_in_set.cocci
new file mode 100644
index 0000000..0840109
--- /dev/null
+++ b/coccinelle/not_in_set.cocci
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/* Limit the number of expressions to 6 for performance reasons */
+@@
+expression e;
+typedef JsonVariant;
+type T != JsonVariant*;
+constant T n0, n1, n2, n3, n4, n5;
+@@
+(
+- e != n0 && e != n1 && e != n2 && e != n3 && e != n4 && e != n5
++ !IN_SET(e, n0, n1, n2, n3, n4, n5)
+|
+- e != n0 && e != n1 && e != n2 && e != n3 && e != n4
++ !IN_SET(e, n0, n1, n2, n3, n4)
+|
+- e != n0 && e != n1 && e != n2 && e != n3
++ !IN_SET(e, n0, n1, n2, n3)
+|
+- e != n0 && e != n1 && e != n2
++ !IN_SET(e, n0, n1, n2)
+|
+- e != n0 && e != n1
++ !IN_SET(e, n0, n1)
+)
diff --git a/coccinelle/o-ndelay.cocci b/coccinelle/o-ndelay.cocci
new file mode 100644
index 0000000..8b7a150
--- /dev/null
+++ b/coccinelle/o-ndelay.cocci
@@ -0,0 +1,5 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+@@
+- O_NDELAY
++ O_NONBLOCK
diff --git a/coccinelle/reallocarray.cocci b/coccinelle/reallocarray.cocci
new file mode 100644
index 0000000..85a8b3b
--- /dev/null
+++ b/coccinelle/reallocarray.cocci
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+expression q, p, n, m;
+@@
+- q = realloc(p, (n)*(m))
++ q = reallocarray(p, n, m)
+@@
+expression q, p, n, m;
+@@
+- q = realloc(p, n*(m))
++ q = reallocarray(p, n, m)
+@@
+expression q, p, n, m;
+@@
+- q = realloc(p, (n)*m)
++ q = reallocarray(p, n, m)
+@@
+expression q, p, n, m;
+@@
+- q = realloc(p, n*m)
++ q = reallocarray(p, n, m)
diff --git a/coccinelle/redundant-if.cocci b/coccinelle/redundant-if.cocci
new file mode 100644
index 0000000..6582d63
--- /dev/null
+++ b/coccinelle/redundant-if.cocci
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+expression r;
+@@
+- if (r < 0)
+- return r;
+- if (r == 0)
+- return 0;
++ if (r <= 0)
++ return r;
+@@
+expression r;
+@@
+- if (r == 0)
+- return 0;
+- if (r < 0)
+- return r;
++ if (r <= 0)
++ return r;
+@@
+expression r;
+@@
+- if (r < 0)
+- return r;
+- if (r == 0)
+- return r;
++ if (r <= 0)
++ return r;
+@@
+expression r;
+@@
+- if (r == 0)
+- return r;
+- if (r < 0)
+- return r;
++ if (r <= 0)
++ return r;
+@@
+expression r;
+@@
+- if (r < 0)
+- return r;
+- if (r > 0)
+- return r;
++ if (r != 0)
++ return r;
+@@
+expression r;
+@@
+- if (r > 0)
+- return r;
+- if (r < 0)
+- return r;
++ if (r != 0)
++ return r;
diff --git a/coccinelle/run-coccinelle.sh b/coccinelle/run-coccinelle.sh
new file mode 100755
index 0000000..cd95179
--- /dev/null
+++ b/coccinelle/run-coccinelle.sh
@@ -0,0 +1,48 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+set -e
+
+# Exclude following paths from the Coccinelle transformations
+EXCLUDED_PATHS=(
+ "src/boot/efi/*"
+ "src/shared/linux/*"
+ "src/basic/linux/*"
+ # Symlinked to test-bus-vtable-cc.cc, which causes issues with the IN_SET macro
+ "src/libsystemd/sd-bus/test-bus-vtable.c"
+ "src/libsystemd/sd-journal/lookup3.c"
+)
+
+TOP_DIR="$(git rev-parse --show-toplevel)"
+ARGS=()
+
+# Create an array from files tracked by git...
+mapfile -t FILES < <(git ls-files ':/*.[ch]')
+# ...and filter everything that matches patterns from EXCLUDED_PATHS
+for excl in "${EXCLUDED_PATHS[@]}"; do
+ # shellcheck disable=SC2206
+ FILES=(${FILES[@]//$excl})
+done
+
+case "$1" in
+ -i)
+ ARGS+=(--in-place)
+ shift
+ ;;
+esac
+
+if ! parallel -h >/dev/null; then
+ echo 'Please install GNU parallel (package "parallel")'
+ exit 1
+fi
+
+[[ ${#@} -ne 0 ]] && SCRIPTS=("$@") || SCRIPTS=("$TOP_DIR"/coccinelle/*.cocci)
+
+for script in "${SCRIPTS[@]}"; do
+ echo "--x-- Processing $script --x--"
+ TMPFILE="$(mktemp)"
+ echo "+ spatch --sp-file $script ${ARGS[*]} ..."
+ parallel --halt now,fail=1 --keep-order --noswap --max-args=20 \
+ spatch --macro-file="$TOP_DIR/coccinelle/macros.h" --smpl-spacing --sp-file "$script" "${ARGS[@]}" ::: "${FILES[@]}" \
+ 2>"$TMPFILE" || cat "$TMPFILE"
+ echo -e "--x-- Processed $script --x--\n"
+done
diff --git a/coccinelle/safe_close-no-if.cocci b/coccinelle/safe_close-no-if.cocci
new file mode 100644
index 0000000..881ce1f
--- /dev/null
+++ b/coccinelle/safe_close-no-if.cocci
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+expression fd;
+@@
+- if (fd >= 0) {
+- fd = safe_close(fd);
+- }
++ fd = safe_close(fd);
diff --git a/coccinelle/safe_close.cocci b/coccinelle/safe_close.cocci
new file mode 100644
index 0000000..49254b6
--- /dev/null
+++ b/coccinelle/safe_close.cocci
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+expression fd;
+@@
+- close(fd);
+- fd = -EBADF;
++ fd = safe_close(fd);
+@@
+expression fd;
+@@
+- close_nointr(fd);
+- fd = -EBADF;
++ fd = safe_close(fd);
+@@
+expression fd;
+@@
+- safe_close(fd);
+- fd = -EBADF;
++ fd = safe_close(fd);
diff --git a/coccinelle/safe_closedir.cocci b/coccinelle/safe_closedir.cocci
new file mode 100644
index 0000000..8981825
--- /dev/null
+++ b/coccinelle/safe_closedir.cocci
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+expression p;
+@@
+- if (p) {
+- closedir(p);
+- p = NULL;
+- }
++ p = safe_closedir(p);
+@@
+expression p;
+@@
+- if (p)
+- closedir(p);
+- p = NULL;
++ p = safe_closedir(p);
+@@
+expression p;
+@@
+- closedir(p);
+- p = NULL;
++ p = safe_closedir(p);
+@@
+expression p;
+@@
+- if (p)
+- closedir(p);
++ safe_closedir(p);
diff --git a/coccinelle/safe_fclose.cocci b/coccinelle/safe_fclose.cocci
new file mode 100644
index 0000000..fc1b584
--- /dev/null
+++ b/coccinelle/safe_fclose.cocci
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+expression p;
+@@
+- if (p) {
+- fclose(p);
+- p = NULL;
+- }
++ p = safe_fclose(p);
+@@
+expression p;
+@@
+- if (p)
+- fclose(p);
+- p = NULL;
++ p = safe_fclose(p);
+@@
+expression p;
+@@
+- fclose(p);
+- p = NULL;
++ p = safe_fclose(p);
+@@
+expression p;
+@@
+- if (p)
+- fclose(p);
++ safe_fclose(p);
diff --git a/coccinelle/sd_event_source_disable_unref.cocci b/coccinelle/sd_event_source_disable_unref.cocci
new file mode 100644
index 0000000..659aa00
--- /dev/null
+++ b/coccinelle/sd_event_source_disable_unref.cocci
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+expression p;
+@@
+- if (p) {
+- (void) sd_event_source_set_enabled(p, SD_EVENT_OFF);
+- p = sd_event_source_unref(p);
+- }
++ p = sd_event_source_disable_unref(p);
+@@
+expression p;
+@@
+- if (p) {
+- sd_event_source_set_enabled(p, SD_EVENT_OFF);
+- sd_event_source_unref(p);
+- }
++ sd_event_source_disable_unref(p);
+@@
+expression p;
+@@
+- if (p) {
+- (void) sd_event_source_set_enabled(p, SD_EVENT_OFF);
+- sd_event_source_unref(p);
+- }
++ sd_event_source_disable_unref(p);
+@@
+expression p;
+@@
+- (void) sd_event_source_set_enabled(p, SD_EVENT_OFF);
+- sd_event_source_unref(p);
++ sd_event_source_disable_unref(p);
+@@
+expression p;
+@@
+- sd_event_source_set_enabled(p, SD_EVENT_OFF);
+- sd_event_source_unref(p);
++ sd_event_source_disable_unref(p);
diff --git a/coccinelle/set_ensure_put.cocci b/coccinelle/set_ensure_put.cocci
new file mode 100644
index 0000000..cfcd77b
--- /dev/null
+++ b/coccinelle/set_ensure_put.cocci
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+local idexpression r;
+expression p, k, x;
+@@
+- r = set_ensure_allocated(&p, k);
+- if (r < 0)
+- return ...;
+- r = set_put(p, x);
++ r = set_ensure_put(&p, k, x);
+@@
+local idexpression r;
+expression p, k, x;
+@@
+- r = set_ensure_allocated(p, k);
+- if (r < 0)
+- return ...;
+- r = set_put(*p, x);
++ r = set_ensure_put(p, k, x);
diff --git a/coccinelle/strdupa.cocci b/coccinelle/strdupa.cocci
new file mode 100644
index 0000000..665736e
--- /dev/null
+++ b/coccinelle/strdupa.cocci
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+expression x;
+@@
+- strdupa(x)
++ strdupa_safe(x)
+@@
+expression x, n;
+@@
+- strndupa(x, n)
++ strndupa_safe(x, n)
diff --git a/coccinelle/strempty.cocci b/coccinelle/strempty.cocci
new file mode 100644
index 0000000..d36f092
--- /dev/null
+++ b/coccinelle/strempty.cocci
@@ -0,0 +1,73 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+/* Avoid running this transformation on the strempty function itself and
+ * on the "make_expression" macro in src/libsystemd/sd-bus/bus-convenience.c.
+ * As Coccinelle's Location object doesn't support macro "detection", use
+ * a pretty horrifying combo of specifying a file and a special "something_else"
+ * position element, which is, apparently, the default value of
+ * "current_element" before it's set (according to the source code), thus
+ * matching any "top level" position, including macros. Let's hope we never
+ * introduce a function called "something_else"...
+ */
+position p : script:python() {
+ not (p[0].current_element == "strempty" or
+ (p[0].file == "src/libsystemd/sd-bus/bus-convenience.c" and
+ p[0].current_element == "something_else"))
+};
+expression s;
+@@
+(
+- s@p ?: ""
++ strempty(s)
+|
+- s@p ? s : ""
++ strempty(s)
+)
+
+@@
+position p : script:python() { p[0].current_element != "strempty" };
+expression s;
+@@
+- if (!s@p)
+- s = "";
++ s = strempty(s);
+
+@@
+position p : script:python() { p[0].current_element != "strnull" };
+expression s;
+@@
+(
+- s@p ?: "(null)"
++ strnull(s)
+|
+- s@p ? s : "(null)"
++ strnull(s)
+)
+
+@@
+position p : script:python() { p[0].current_element != "strnull" };
+expression s;
+@@
+- if (!s@p)
+- s = "(null)";
++ s = strnull(s);
+
+@@
+position p : script:python() { p[0].current_element != "strna" };
+expression s;
+@@
+(
+- s@p ?: "n/a"
++ strna(s)
+|
+- s@p ? s : "n/a"
++ strna(s)
+)
+
+@@
+position p : script:python() { p[0].current_element != "strna" };
+expression s;
+@@
+- if (!s@p)
+- s = "n/a";
++ s = strna(s);
diff --git a/coccinelle/strjoin.cocci b/coccinelle/strjoin.cocci
new file mode 100644
index 0000000..1efff70
--- /dev/null
+++ b/coccinelle/strjoin.cocci
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+position p : script:python() { p[0].current_element != "test_strjoin" };
+expression t;
+expression list args;
+@@
+(
+- strjoin@p(args, NULL);
++ strjoin(args);
+|
+- t = strjoin@p(args, NULL);
++ t = strjoin(args);
+|
+- return strjoin@p(args, NULL);
++ return strjoin(args);
+)
diff --git a/coccinelle/strjoina.cocci b/coccinelle/strjoina.cocci
new file mode 100644
index 0000000..891b22a
--- /dev/null
+++ b/coccinelle/strjoina.cocci
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+position p : script:python() { p[0].current_element != "test_strjoina" };
+expression n, m;
+expression list s;
+@@
+- n = strjoina@p(m, s, NULL);
++ n = strjoina(m, s);
diff --git a/coccinelle/strv_free.cocci b/coccinelle/strv_free.cocci
new file mode 100644
index 0000000..8eddfc5
--- /dev/null
+++ b/coccinelle/strv_free.cocci
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+expression p;
+@@
+- strv_free(p);
+- p = NULL;
++ p = strv_free(p);
+@@
+expression p;
+@@
+- if (p)
+- strv_free(p);
+- p = NULL;
++ p = strv_free(p);
+@@
+expression p;
+@@
+- if (p) {
+- strv_free(p);
+- p = NULL;
+- }
++ p = strv_free(p);
+@@
+expression p;
+@@
+- if (p)
+- strv_free(p);
++ strv_free(p);
diff --git a/coccinelle/swap-two.cocci b/coccinelle/swap-two.cocci
new file mode 100644
index 0000000..d80c4e0
--- /dev/null
+++ b/coccinelle/swap-two.cocci
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+expression x, y, z;
+@@
+- z = x;
+- x = y;
+- y = z;
++ SWAP_TWO(x, y);
diff --git a/coccinelle/synthetic-errno.cocci b/coccinelle/synthetic-errno.cocci
new file mode 100644
index 0000000..6826ea4
--- /dev/null
+++ b/coccinelle/synthetic-errno.cocci
@@ -0,0 +1,263 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+expression e;
+expression list args;
+@@
+(
+/* Ignore one specific case in src/shared/bootspec.c where we want to stick
+ * with the log_debug() + return pattern */
+log_debug("Found no default boot entry :(");
+|
+- log_debug(args);
+- return -e;
++ return log_debug_errno(SYNTHETIC_ERRNO(e), args);
+)
+@@
+expression e;
+expression list args;
+@@
+(
+/* Ignore specific cases in src/import/{export,import,pull}.c where we want to return positive value on success. */
+log_info("Exiting.");
+return -r;
+|
+- log_info(args);
+- return -e;
++ return log_info_errno(SYNTHETIC_ERRNO(e), args);
+)
+@@
+expression e;
+expression list args;
+@@
+- log_notice(args);
+- return -e;
++ return log_notice_errno(SYNTHETIC_ERRNO(e), args);
+@@
+expression e;
+expression list args;
+@@
+- log_error(args);
+- return -e;
++ return log_error_errno(SYNTHETIC_ERRNO(e), args);
+@@
+expression e;
+expression list args;
+@@
+- log_emergency(args);
+- return -e;
++ return log_emergency_errno(SYNTHETIC_ERRNO(e), args);
+@@
+identifier log_LEVEL_errno =~ "^log_(debug|info|notice|warning|error|emergency)_errno$";
+identifier ERRNO =~ "^E[A-Z]+$";
+expression list args;
+@@
+- log_LEVEL_errno(ERRNO, args);
++ log_LEVEL_errno(SYNTHETIC_ERRNO(ERRNO), args);
+@@
+identifier log_UNIT_LEVEL_errno =~ "^log_(unit|link|device|token)_(debug|info|notice|warning|error|emergency)_errno$";
+identifier ERRNO =~ "^E[A-Z]+$";
+expression u;
+expression list args;
+@@
+- log_UNIT_LEVEL_errno(u, ERRNO, args);
++ log_UNIT_LEVEL_errno(u, SYNTHETIC_ERRNO(ERRNO), args);
+@@
+expression e;
+expression u;
+expression list args;
+@@
+- log_unit_debug(u, args);
+- return -e;
++ return log_unit_debug_errno(u, SYNTHETIC_ERRNO(e), args);
+@@
+expression e;
+expression u;
+expression list args;
+@@
+- log_unit_info(u, args);
+- return -e;
++ return log_unit_info_errno(u, SYNTHETIC_ERRNO(e), args);
+@@
+expression e;
+expression u;
+expression list args;
+@@
+- log_unit_notice(u, args);
+- return -e;
++ return log_unit_notice_errno(u, SYNTHETIC_ERRNO(e), args);
+@@
+expression e;
+expression u;
+expression list args;
+@@
+- log_unit_error(u, args);
+- return -e;
++ return log_unit_error_errno(u, SYNTHETIC_ERRNO(e), args);
+@@
+expression e;
+expression u;
+expression list args;
+@@
+- log_unit_emergency(u, args);
+- return -e;
++ return log_unit_emergency_errno(u, SYNTHETIC_ERRNO(e), args);
+@@
+expression e;
+expression u;
+expression list args;
+@@
+- log_link_debug(u, args);
+- return -e;
++ return log_link_debug_errno(u, SYNTHETIC_ERRNO(e), args);
+@@
+expression e;
+expression u;
+expression list args;
+@@
+- log_link_info(u, args);
+- return -e;
++ return log_link_info_errno(u, SYNTHETIC_ERRNO(e), args);
+@@
+expression e;
+expression u;
+expression list args;
+@@
+- log_link_notice(u, args);
+- return -e;
++ return log_link_notice_errno(u, SYNTHETIC_ERRNO(e), args);
+@@
+expression e;
+expression u;
+expression list args;
+@@
+- log_link_error(u, args);
+- return -e;
++ return log_link_error_errno(u, SYNTHETIC_ERRNO(e), args);
+@@
+expression e;
+expression u;
+expression list args;
+@@
+- log_link_emergency(u, args);
+- return -e;
++ return log_link_emergency_errno(u, SYNTHETIC_ERRNO(e), args);
+@@
+expression e;
+expression u;
+expression list args;
+@@
+- log_netdev_debug(u, args);
+- return -e;
++ return log_netdev_debug_errno(u, SYNTHETIC_ERRNO(e), args);
+@@
+expression e;
+expression u;
+expression list args;
+@@
+- log_netdev_info(u, args);
+- return -e;
++ return log_netdev_info_errno(u, SYNTHETIC_ERRNO(e), args);
+@@
+expression e;
+expression u;
+expression list args;
+@@
+- log_netdev_notice(u, args);
+- return -e;
++ return log_netdev_notice_errno(u, SYNTHETIC_ERRNO(e), args);
+@@
+expression e;
+expression u;
+expression list args;
+@@
+- log_netdev_error(u, args);
+- return -e;
++ return log_netdev_error_errno(u, SYNTHETIC_ERRNO(e), args);
+@@
+expression e;
+expression u;
+expression list args;
+@@
+- log_netdev_emergency(u, args);
+- return -e;
++ return log_netdev_emergency_errno(u, SYNTHETIC_ERRNO(e), args);
+@@
+expression e;
+expression u;
+expression list args;
+@@
+- log_device_debug(u, args);
+- return -e;
++ return log_device_debug_errno(u, SYNTHETIC_ERRNO(e), args);
+@@
+expression e;
+expression u;
+expression list args;
+@@
+- log_device_info(u, args);
+- return -e;
++ return log_device_info_errno(u, SYNTHETIC_ERRNO(e), args);
+@@
+expression e;
+expression u;
+expression list args;
+@@
+- log_device_notice(u, args);
+- return -e;
++ return log_device_notice_errno(u, SYNTHETIC_ERRNO(e), args);
+@@
+expression e;
+expression u;
+expression list args;
+@@
+- log_device_error(u, args);
+- return -e;
++ return log_device_error_errno(u, SYNTHETIC_ERRNO(e), args);
+@@
+expression e;
+expression u;
+expression list args;
+@@
+- log_device_emergency(u, args);
+- return -e;
++ return log_device_emergency_errno(u, SYNTHETIC_ERRNO(e), args);
+@@
+expression e;
+expression u;
+expression list args;
+@@
+- log_token_debug(u, args);
+- return -e;
++ return log_token_debug_errno(u, SYNTHETIC_ERRNO(e), args);
+@@
+expression e;
+expression u;
+expression list args;
+@@
+- log_token_info(u, args);
+- return -e;
++ return log_token_info_errno(u, SYNTHETIC_ERRNO(e), args);
+@@
+expression e;
+expression u;
+expression list args;
+@@
+- log_token_notice(u, args);
+- return -e;
++ return log_token_notice_errno(u, SYNTHETIC_ERRNO(e), args);
+@@
+expression e;
+expression u;
+expression list args;
+@@
+- log_token_error(u, args);
+- return -e;
++ return log_token_error_errno(u, SYNTHETIC_ERRNO(e), args);
+@@
+expression e;
+expression u;
+expression list args;
+@@
+- log_token_emergency(u, args);
+- return -e;
++ return log_token_emergency_errno(u, SYNTHETIC_ERRNO(e), args);
diff --git a/coccinelle/take-fd.cocci b/coccinelle/take-fd.cocci
new file mode 100644
index 0000000..15f1e7c
--- /dev/null
+++ b/coccinelle/take-fd.cocci
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+local idexpression p;
+expression q;
+@@
+- p = q;
+- q = -EBADF;
+- return p;
++ return TAKE_FD(q);
+
+/* The ideal solution would use 'local idexpression' to avoid matching errno,
+ * which is a global variable. However, 'idexpression' nor 'identifier'
+ * would match, for example, "x->fd", which is considered 'expression' in
+ * the SmPL grammar
+ */
+@@
+expression p != errno;
+expression q;
+@@
+- p = q;
+- q = -EBADF;
++ p = TAKE_FD(q);
diff --git a/coccinelle/take-ptr.cocci b/coccinelle/take-ptr.cocci
new file mode 100644
index 0000000..3251d3e
--- /dev/null
+++ b/coccinelle/take-ptr.cocci
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+local idexpression p;
+expression q;
+@@
+- p = q;
+- q = NULL;
+- return p;
++ return TAKE_PTR(q);
+@@
+expression p, q;
+@@
+- p = q;
+- q = NULL;
++ p = TAKE_PTR(q);
diff --git a/coccinelle/timestamp-is-set.cocci b/coccinelle/timestamp-is-set.cocci
new file mode 100644
index 0000000..2d251fa
--- /dev/null
+++ b/coccinelle/timestamp-is-set.cocci
@@ -0,0 +1,73 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+expression x;
+constant USEC_INFINITY = USEC_INFINITY;
+/* We want to stick with the literal expression in the implementation of timestamp_is_set(), i.e. in time-util.c */
+position p : script:python() { p[0].file != "src/basic/time-util.h" };
+@@
+(
+- x > 0 && x < USEC_INFINITY
++ timestamp_is_set(x)
+|
+- x < USEC_INFINITY && x > 0
++ timestamp_is_set(x)
+|
+- x@p > 0 && x != USEC_INFINITY
++ timestamp_is_set(x)
+|
+- x != USEC_INFINITY && x > 0
++ timestamp_is_set(x)
+|
+- x != 0 && x < USEC_INFINITY
++ timestamp_is_set(x)
+|
+- x < USEC_INFINITY && x != 0
++ timestamp_is_set(x)
+|
+- x != 0 && x != USEC_INFINITY
++ timestamp_is_set(x)
+|
+- x != USEC_INFINITY && x != 0
++ timestamp_is_set(x)
+|
+- !IN_SET(x, 0, USEC_INFINITY)
++ timestamp_is_set(x)
+|
+- !IN_SET(x, USEC_INFINITY, 0)
++ timestamp_is_set(x)
+)
+@@
+expression x;
+constant USEC_INFINITY = USEC_INFINITY;
+@@
+(
+- x <= 0 || x >= USEC_INFINITY
++ !timestamp_is_set(x)
+|
+- x >= USEC_INFINITY || x <= 0
++ !timestamp_is_set(x)
+|
+- x <= 0 || x == USEC_INFINITY
++ !timestamp_is_set(x)
+|
+- x == USEC_INFINITY || x <= 0
++ !timestamp_is_set(x)
+|
+- x == 0 || x >= USEC_INFINITY
++ !timestamp_is_set(x)
+|
+- x >= USEC_INFINITY || x == 0
++ !timestamp_is_set(x)
+|
+- x == 0 || x == USEC_INFINITY
++ !timestamp_is_set(x)
+|
+- x == USEC_INFINITY || x == 0
++ !timestamp_is_set(x)
+|
+- IN_SET(x, 0, USEC_INFINITY)
++ !timestamp_is_set(x)
+|
+- IN_SET(x, USEC_INFINITY, 0)
++ !timestamp_is_set(x)
+)
diff --git a/coccinelle/while-true.cocci b/coccinelle/while-true.cocci
new file mode 100644
index 0000000..3ea70bc
--- /dev/null
+++ b/coccinelle/while-true.cocci
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+statement s;
+@@
+- while (true)
++ for (;;)
+s
+@@
+statement s;
+@@
+- while (1)
++ for (;;)
+s
diff --git a/coccinelle/xsprintf.cocci b/coccinelle/xsprintf.cocci
new file mode 100644
index 0000000..3b38090
--- /dev/null
+++ b/coccinelle/xsprintf.cocci
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+position p : script:python() { not p[0].file.startswith("man/") };
+expression e, fmt;
+expression list vaargs;
+@@
+- snprintf@p(e, sizeof(e), fmt, vaargs);
++ xsprintf(e, fmt, vaargs);
diff --git a/coccinelle/zz-drop-braces.cocci b/coccinelle/zz-drop-braces.cocci
new file mode 100644
index 0000000..8c3be01
--- /dev/null
+++ b/coccinelle/zz-drop-braces.cocci
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+@@
+position p : script:python() { p[0].file != "src/journal/lookup3.c" };
+identifier id;
+expression e;
+@@
+if (...)
+- {
+(
+ id@p(...);
+|
+ e@p;
+)
+- }
+
+@@
+position p : script:python() { p[0].file != "src/journal/lookup3.c" };
+identifier id;
+expression e;
+@@
+if (...)
+- {
+(
+ return id@p(...);
+|
+ return e@p;
+)
+- }