Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/testing/selftests/ipc/msgque.c
26285 views
1
// SPDX-License-Identifier: GPL-2.0
2
#define _GNU_SOURCE
3
#include <stdlib.h>
4
#include <stdio.h>
5
#include <string.h>
6
#include <errno.h>
7
#include <sys/msg.h>
8
#include <fcntl.h>
9
10
#include "../kselftest.h"
11
12
#define MAX_MSG_SIZE 32
13
14
struct msg1 {
15
int msize;
16
long mtype;
17
char mtext[MAX_MSG_SIZE];
18
};
19
20
#define TEST_STRING "Test sysv5 msg"
21
#define MSG_TYPE 1
22
23
#define ANOTHER_TEST_STRING "Yet another test sysv5 msg"
24
#define ANOTHER_MSG_TYPE 26538
25
26
struct msgque_data {
27
key_t key;
28
int msq_id;
29
int qbytes;
30
int qnum;
31
int mode;
32
struct msg1 *messages;
33
};
34
35
int restore_queue(struct msgque_data *msgque)
36
{
37
int fd, ret, id, i;
38
char buf[32];
39
40
fd = open("/proc/sys/kernel/msg_next_id", O_WRONLY);
41
if (fd == -1) {
42
ksft_test_result_fail("Failed to open /proc/sys/kernel/msg_next_id\n");
43
return -errno;
44
}
45
sprintf(buf, "%d", msgque->msq_id);
46
47
ret = write(fd, buf, strlen(buf));
48
if (ret != strlen(buf)) {
49
ksft_test_result_fail("Failed to write to /proc/sys/kernel/msg_next_id\n");
50
return -errno;
51
}
52
53
id = msgget(msgque->key, msgque->mode | IPC_CREAT | IPC_EXCL);
54
if (id == -1) {
55
ksft_test_result_fail("Failed to create queue\n");
56
return -errno;
57
}
58
59
if (id != msgque->msq_id) {
60
ksft_test_result_fail("Restored queue has wrong id (%d instead of %d)\n"
61
, id, msgque->msq_id);
62
ret = -EFAULT;
63
goto destroy;
64
}
65
66
for (i = 0; i < msgque->qnum; i++) {
67
if (msgsnd(msgque->msq_id, &msgque->messages[i].mtype,
68
msgque->messages[i].msize, IPC_NOWAIT) != 0) {
69
ksft_test_result_fail("msgsnd failed (%m)\n");
70
ret = -errno;
71
goto destroy;
72
}
73
}
74
return 0;
75
76
destroy:
77
if (msgctl(id, IPC_RMID, NULL))
78
printf("Failed to destroy queue: %d\n", -errno);
79
return ret;
80
}
81
82
int check_and_destroy_queue(struct msgque_data *msgque)
83
{
84
struct msg1 message;
85
int cnt = 0, ret;
86
87
while (1) {
88
ret = msgrcv(msgque->msq_id, &message.mtype, MAX_MSG_SIZE,
89
0, IPC_NOWAIT);
90
if (ret < 0) {
91
if (errno == ENOMSG)
92
break;
93
ksft_test_result_fail("Failed to read IPC message: %m\n");
94
ret = -errno;
95
goto err;
96
}
97
if (ret != msgque->messages[cnt].msize) {
98
ksft_test_result_fail("Wrong message size: %d (expected %d)\n", ret, msgque->messages[cnt].msize);
99
ret = -EINVAL;
100
goto err;
101
}
102
if (message.mtype != msgque->messages[cnt].mtype) {
103
ksft_test_result_fail("Wrong message type\n");
104
ret = -EINVAL;
105
goto err;
106
}
107
if (memcmp(message.mtext, msgque->messages[cnt].mtext, ret)) {
108
ksft_test_result_fail("Wrong message content\n");
109
ret = -EINVAL;
110
goto err;
111
}
112
cnt++;
113
}
114
115
if (cnt != msgque->qnum) {
116
ksft_test_result_fail("Wrong message number\n");
117
ret = -EINVAL;
118
goto err;
119
}
120
121
ret = 0;
122
err:
123
if (msgctl(msgque->msq_id, IPC_RMID, NULL)) {
124
printf("Failed to destroy queue: %d\n", -errno);
125
return -errno;
126
}
127
return ret;
128
}
129
130
int dump_queue(struct msgque_data *msgque)
131
{
132
struct msqid_ds ds;
133
int kern_id;
134
int i, ret;
135
136
for (kern_id = 0; kern_id < 256; kern_id++) {
137
ret = msgctl(kern_id, MSG_STAT, &ds);
138
if (ret < 0) {
139
if (errno == EINVAL)
140
continue;
141
ksft_test_result_fail("Failed to get stats for IPC queue with id %d\n",
142
kern_id);
143
return -errno;
144
}
145
146
if (ret == msgque->msq_id)
147
break;
148
}
149
150
msgque->messages = malloc(sizeof(struct msg1) * ds.msg_qnum);
151
if (msgque->messages == NULL) {
152
ksft_test_result_fail("Failed to get stats for IPC queue\n");
153
return -ENOMEM;
154
}
155
156
msgque->qnum = ds.msg_qnum;
157
msgque->mode = ds.msg_perm.mode;
158
msgque->qbytes = ds.msg_qbytes;
159
160
for (i = 0; i < msgque->qnum; i++) {
161
ret = msgrcv(msgque->msq_id, &msgque->messages[i].mtype,
162
MAX_MSG_SIZE, i, IPC_NOWAIT | MSG_COPY);
163
if (ret < 0) {
164
ksft_test_result_fail("Failed to copy IPC message: %m (%d)\n", errno);
165
return -errno;
166
}
167
msgque->messages[i].msize = ret;
168
}
169
return 0;
170
}
171
172
int fill_msgque(struct msgque_data *msgque)
173
{
174
struct msg1 msgbuf;
175
176
msgbuf.mtype = MSG_TYPE;
177
memcpy(msgbuf.mtext, TEST_STRING, sizeof(TEST_STRING));
178
if (msgsnd(msgque->msq_id, &msgbuf.mtype, sizeof(TEST_STRING),
179
IPC_NOWAIT) != 0) {
180
ksft_test_result_fail("First message send failed (%m)\n");
181
return -errno;
182
}
183
184
msgbuf.mtype = ANOTHER_MSG_TYPE;
185
memcpy(msgbuf.mtext, ANOTHER_TEST_STRING, sizeof(ANOTHER_TEST_STRING));
186
if (msgsnd(msgque->msq_id, &msgbuf.mtype, sizeof(ANOTHER_TEST_STRING),
187
IPC_NOWAIT) != 0) {
188
ksft_test_result_fail("Second message send failed (%m)\n");
189
return -errno;
190
}
191
return 0;
192
}
193
194
int main(int argc, char **argv)
195
{
196
int err;
197
struct msgque_data msgque;
198
199
if (getuid() != 0)
200
ksft_exit_skip("Please run the test as root - Exiting.\n");
201
202
msgque.key = ftok(argv[0], 822155650);
203
if (msgque.key == -1) {
204
ksft_test_result_fail("Can't make key: %d\n", -errno);
205
ksft_exit_fail();
206
}
207
208
msgque.msq_id = msgget(msgque.key, IPC_CREAT | IPC_EXCL | 0666);
209
if (msgque.msq_id == -1) {
210
err = -errno;
211
ksft_test_result_fail("Can't create queue: %d\n", err);
212
goto err_out;
213
}
214
215
err = fill_msgque(&msgque);
216
if (err) {
217
ksft_test_result_fail("Failed to fill queue: %d\n", err);
218
goto err_destroy;
219
}
220
221
err = dump_queue(&msgque);
222
if (err) {
223
ksft_test_result_fail("Failed to dump queue: %d\n", err);
224
goto err_destroy;
225
}
226
227
err = check_and_destroy_queue(&msgque);
228
if (err) {
229
ksft_test_result_fail("Failed to check and destroy queue: %d\n", err);
230
goto err_out;
231
}
232
233
err = restore_queue(&msgque);
234
if (err) {
235
ksft_test_result_fail("Failed to restore queue: %d\n", err);
236
goto err_destroy;
237
}
238
239
err = check_and_destroy_queue(&msgque);
240
if (err) {
241
ksft_test_result_fail("Failed to test queue: %d\n", err);
242
goto err_out;
243
}
244
ksft_exit_pass();
245
246
err_destroy:
247
if (msgctl(msgque.msq_id, IPC_RMID, NULL)) {
248
printf("Failed to destroy queue: %d\n", -errno);
249
ksft_exit_fail();
250
}
251
err_out:
252
ksft_exit_fail();
253
}
254
255