1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) International Business Machines Corp., 2001
4 * Ported to LTP: Wayne Boyer
5 * Copyright (c) 2018 Cyril Hrubis <chrubis@suse.cz>
6 */
7
8 /*
9 * Check if many children can read what is written to a pipe by the parent.
10 *
11 * ALGORITHM
12 * For a different nchilds number:
13 * 1. Open a pipe and write nchilds * (PIPE_BUF/nchilds) bytes into it
14 * 2. Fork nchilds children
15 * 3. Each child reads PIPE_BUF/nchilds characters and checks that the
16 * bytes read are correct
17 */
18 #include <stdlib.h>
19 #include "tst_test.h"
20
21 static int fds[2];
22 static unsigned char buf[PIPE_BUF];
23 static size_t read_per_child;
24
do_child(void)25 void do_child(void)
26 {
27 size_t nread;
28 unsigned char rbuf[read_per_child];
29 unsigned int i;
30
31 SAFE_CLOSE(fds[1]);
32
33 nread = SAFE_READ(0, fds[0], rbuf, sizeof(rbuf));
34
35 if (nread != read_per_child) {
36 tst_res(TFAIL, "Invalid read size child %i size %zu",
37 getpid(), nread);
38 return;
39 }
40
41 for (i = 0; i < read_per_child; i++) {
42 if (rbuf[i] != (i % 256)) {
43 tst_res(TFAIL,
44 "Invalid byte read child %i byte %i have %i expected %i",
45 getpid(), i, rbuf[i], i % 256);
46 return;
47 }
48 }
49
50 tst_res(TPASS, "Child %i read pipe buffer correctly", getpid());
51 }
52
53 static unsigned int childs[] = {
54 1,
55 2,
56 3,
57 4,
58 10,
59 50
60 };
61
run(unsigned int tcase)62 static void run(unsigned int tcase)
63 {
64 pid_t pid;
65 unsigned int nchilds = childs[tcase];
66 read_per_child = PIPE_BUF/nchilds;
67 unsigned int i, j;
68
69 tst_res(TINFO, "Reading %zu per each of %u children",
70 read_per_child, nchilds);
71
72 for (i = 0; i < nchilds; i++) {
73 for (j = 0; j < read_per_child; j++) {
74 buf[i * read_per_child + j] = j % 256;
75 }
76 }
77
78 SAFE_PIPE(fds);
79
80 SAFE_WRITE(1, fds[1], buf, read_per_child * nchilds);
81
82 for (i = 0; i < nchilds; i++) {
83 pid = SAFE_FORK();
84
85 if (!pid) {
86 do_child();
87 exit(0);
88 }
89 }
90
91 tst_reap_children();
92
93 SAFE_CLOSE(fds[0]);
94 SAFE_CLOSE(fds[1]);
95 }
96
97 static struct tst_test test = {
98 .forks_child = 1,
99 .test = run,
100 .tcnt = ARRAY_SIZE(childs),
101 };
102