1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (C) 2017-2019 Petr Vorel pvorel@suse.cz
4 * Copyright (C) 2022 Andrea Cervesato andrea.cervesato@suse.com
5 */
6
7#ifndef TST_SAFE_POSIX_IPC_H__
8#define TST_SAFE_POSIX_IPC_H__
9
10#include <mqueue.h>
11#include <stdarg.h>
12
13#define SAFE_MQ_OPEN(pathname, oflags, ...) \
14	safe_mq_open(__FILE__, __LINE__, (pathname), (oflags), ##__VA_ARGS__)
15
16#define SAFE_MQ_CLOSE(mqdes) \
17	safe_mq_close(__FILE__, __LINE__, (mqdes))
18
19#define SAFE_MQ_NOTIFY(mqdes, sevp)				\
20	safe_mq_notify(__FILE__, __LINE__, (mqdes), (sevp))
21
22#define SAFE_MQ_SEND(mqdes, msg_ptr, msg_len, msg_prio) \
23	safe_mq_send(__FILE__, __LINE__, (mqdes), (msg_ptr), (msg_len), (msg_prio))
24
25#define SAFE_MQ_UNLINK(name) \
26	safe_mq_unlink(__FILE__, __LINE__, (name))
27
28static inline int safe_mq_open(const char *file, const int lineno,
29			       const char *pathname, int oflags, ...)
30{
31	va_list ap;
32	int rval;
33	mode_t mode;
34	struct mq_attr *attr;
35
36	va_start(ap, oflags);
37
38	/* Android's NDK's mode_t is smaller than an int, which results in
39	 * SIGILL here when passing the mode_t type.
40	 */
41#ifndef __ANDROID__
42	mode = va_arg(ap, mode_t);
43#else
44	mode = va_arg(ap, int);
45#endif
46
47	attr = va_arg(ap, struct mq_attr *);
48
49	va_end(ap);
50
51	rval = mq_open(pathname, oflags, mode, attr);
52
53	if (rval == -1) {
54		tst_brk_(file, lineno, TBROK | TERRNO,
55			"mq_open(%s,%d,%04o,%p) failed", pathname, oflags,
56			mode, attr);
57	} else if (rval < 0) {
58		tst_brk_(file, lineno, TBROK | TERRNO,
59			"Invalid mq_open(%s) return value %d", pathname, rval);
60	}
61
62	return rval;
63}
64
65static inline int safe_mq_close(const char *file, const int lineno,
66				mqd_t __mqdes)
67{
68	int rval;
69
70	rval = mq_close(__mqdes);
71
72	if (rval == -1) {
73		tst_brk_(file, lineno, TBROK | TERRNO,
74			"mq_close(%d) failed", __mqdes);
75	} else if (rval < 0) {
76		tst_brk_(file, lineno, TBROK | TERRNO,
77			"Invalid mq_close(%d) return value %d", __mqdes, rval);
78	}
79
80	return rval;
81}
82
83static inline int safe_mq_unlink(const char *file, const int lineno,
84				const char* name)
85{
86	int rval;
87
88	rval = mq_unlink(name);
89
90	if (rval == -1) {
91		tst_brk_(file, lineno, TBROK | TERRNO,
92			"mq_unlink(%s) failed", name);
93	} else if (rval < 0) {
94		tst_brk_(file, lineno, TBROK | TERRNO,
95			"Invalid mq_unlink(%s) return value %d", name, rval);
96	}
97
98	return rval;
99}
100
101static inline int safe_mq_notify(const char *file, const int lineno,
102			  mqd_t mqdes, const struct sigevent *sevp)
103{
104	int rval;
105
106	rval = mq_notify(mqdes, sevp);
107
108	if (rval == -1)
109		tst_brk_(file, lineno, TBROK | TERRNO, "mq_notify() failed");
110
111	return rval;
112}
113
114static inline int safe_mq_send(const char *file, const int lineno,
115			mqd_t mqdes, const char *msg_ptr,
116			size_t msg_len, unsigned int msg_prio)
117{
118	int rval;
119
120	rval = mq_send(mqdes, msg_ptr, msg_len, msg_prio);
121
122	if (rval == -1) {
123		tst_brk_(file, lineno, TBROK | TERRNO,
124			"mq_send(%d,%s,%zu,%d) failed", mqdes, msg_ptr,
125			msg_len, msg_prio);
126	}
127
128	return rval;
129}
130
131#endif /* TST_SAFE_POSIX_IPC_H__ */
132