1 /* 2 * Copyright (c) International Business Machines Corp., 2001 3 * 07/2001 Ported by Wayne Boyer 4 * Copyright (c) 2018 Cyril Hrubis <chrubis (at) suse.cz> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 14 * the GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21 /* 22 * Check if many children can read what is written to a pipe by the parent. 23 * 24 * ALGORITHM 25 * For a different nchilds number: 26 * 1. Open a pipe and write nchilds * (PIPE_BUF/nchilds) bytes into it 27 * 2. Fork nchilds children 28 * 3. Each child reads PIPE_BUF/nchilds characters and checks that the 29 * bytes read are correct 30 */ 31 #include <stdlib.h> 32 #include "tst_test.h" 33 34 static int fds[2]; 35 static unsigned char buf[PIPE_BUF]; 36 static size_t read_per_child; 37 38 void do_child(void) 39 { 40 size_t nread; 41 unsigned char rbuf[read_per_child]; 42 unsigned int i; 43 44 SAFE_CLOSE(fds[1]); 45 46 nread = SAFE_READ(0, fds[0], rbuf, sizeof(rbuf)); 47 48 if (nread != read_per_child) { 49 tst_res(TFAIL, "Invalid read size child %i size %zu", 50 getpid(), nread); 51 return; 52 } 53 54 for (i = 0; i < read_per_child; i++) { 55 if (rbuf[i] != (i % 256)) { 56 tst_res(TFAIL, 57 "Invalid byte read child %i byte %i have %i expected %i", 58 getpid(), i, rbuf[i], i % 256); 59 return; 60 } 61 } 62 63 tst_res(TPASS, "Child %i read pipe buffer correctly", getpid()); 64 } 65 66 static unsigned int childs[] = { 67 1, 68 2, 69 3, 70 4, 71 10, 72 50 73 }; 74 75 static void run(unsigned int tcase) 76 { 77 pid_t pid; 78 unsigned int nchilds = childs[tcase]; 79 read_per_child = PIPE_BUF/nchilds; 80 unsigned int i, j; 81 82 tst_res(TINFO, "Reading %zu per each of %u children", 83 read_per_child, nchilds); 84 85 for (i = 0; i < nchilds; i++) { 86 for (j = 0; j < read_per_child; j++) { 87 buf[i * read_per_child + j] = j % 256; 88 } 89 } 90 91 SAFE_PIPE(fds); 92 93 SAFE_WRITE(1, fds[1], buf, read_per_child * nchilds); 94 95 for (i = 0; i < nchilds; i++) { 96 pid = SAFE_FORK(); 97 98 if (!pid) { 99 do_child(); 100 exit(0); 101 } 102 } 103 104 tst_reap_children(); 105 106 SAFE_CLOSE(fds[0]); 107 SAFE_CLOSE(fds[1]); 108 } 109 110 static struct tst_test test = { 111 .forks_child = 1, 112 .test = run, 113 .tcnt = ARRAY_SIZE(childs), 114 }; 115