1#!/bin/sh 2 3# 4# Copyright (c) 2017 Dell EMC Isilon 5# All rights reserved. 6# 7# Redistribution and use in source and binary forms, with or without 8# modification, are permitted provided that the following conditions 9# are met: 10# 1. Redistributions of source code must retain the above copyright 11# notice, this list of conditions and the following disclaimer. 12# 2. Redistributions in binary form must reproduce the above copyright 13# notice, this list of conditions and the following disclaimer in the 14# documentation and/or other materials provided with the distribution. 15# 16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26# SUCH DAMAGE. 27# 28 29# mkfifo(2), select(2) with tmpfs(4) scenario. 30 31. ../default.cfg 32[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 33 34dir=/tmp 35odir=`pwd` 36cd $dir 37sed '1,/^EOF/d' < $odir/$0 > $dir/mkfifo5.c 38mycc -o mkfifo5 -Wall -Wextra -O0 -g mkfifo5.c || exit 1 39rm -f mkfifo5.c 40cd $odir 41 42mount | grep -q "on $mntpoint " && umount -f $mntpoint 43mount -o size=1g -t tmpfs tmpfs $mntpoint 44 45fifo=$mntpoint/fifo.file 46cd $mntpoint 47/tmp/mkfifo5 $fifo 48s=$? 49cd $odir 50 51while mount | grep "on $mntpoint " | grep -q tmpfs; do 52 umount $mntpoint || sleep 1 53done 54rm -rf /tmp/mkfifo5 55exit $s 56 57EOF 58#include <sys/param.h> 59#include <sys/mman.h> 60#include <sys/stat.h> 61#include <sys/wait.h> 62 63#include <err.h> 64#include <errno.h> 65#include <fcntl.h> 66#include <signal.h> 67#include <stdio.h> 68#include <stdlib.h> 69#include <time.h> 70#include <unistd.h> 71 72static char *path; 73 74#define PARALLEL 1 75 76static void 77reader(void) 78{ 79 fd_set rset; 80 struct timeval timeout; 81 int fd, n, r; 82 char ch; 83 84 do { 85 if((fd = open(path, O_RDONLY)) == -1) 86 if (errno != EINTR) 87 err(1, "open(%s, O_RDONLY)", 88 path); 89 if (fd == -1) 90 warn("open(%s) ro", path); 91 } while (fd == -1); 92 93 /* Read one character */ 94 FD_ZERO(&rset); 95 FD_SET(fd, &rset); 96 if ((n = select(fd + 1, &rset, NULL, NULL, NULL)) < 0) 97 if (errno != EINTR) 98 err(1, "select()"); 99 if (n == 1 && FD_ISSET(fd, &rset)) { 100 r = read(fd, &ch, 1); 101 if (r == -1) 102 err(1, "read"); 103 if (r == 0) 104 fprintf(stderr, "read(1): EOF\n"); 105 } 106 107 /* timeout */ 108 ch = 'z'; 109 FD_ZERO(&rset); 110 FD_SET(fd, &rset); 111 timeout.tv_sec = 1; 112 timeout.tv_usec = 0; 113 if ((n = select(fd + 1, &rset, NULL, NULL, &timeout)) < 0) 114 if (errno != EINTR) 115 err(1, "select()"); 116 if (n != 1) 117 fprintf(stderr, "FAIL Expected n == 0, got %d\n", n); 118 if (n == 1 && FD_ISSET(fd, &rset)) { 119 r = read(fd, &ch, 1); 120 if (r == -1) 121 err(1, "read"); 122 if (r == 0) 123 fprintf(stderr, "read(2): EOF\n"); 124 } 125 126 /* timeout */ 127 ch = 'z'; 128 FD_ZERO(&rset); 129 FD_SET(fd, &rset); 130 timeout.tv_sec = 1; 131 timeout.tv_usec = 0; 132 if ((n = select(fd + 1, &rset, NULL, NULL, &timeout)) < 0) 133 if (errno != EINTR) 134 err(1, "select()"); 135 if (n != 1) 136 fprintf(stderr, "FAIL Expected n == 0, got %d\n", n); 137 if (n == 1 && FD_ISSET(fd, &rset)) { 138 r = read(fd, &ch, 1); 139 if (r == -1) 140 err(1, "read"); 141 if (r != 0) 142 fprintf(stderr, "read(3): %c\n", ch); 143 } 144 145 if (close(fd) == -1) 146 err(1, "close() in child"); 147 _exit(n == 1 ? 0 : 1); 148} 149 150static void 151writer(void) 152{ 153 int fd; 154 155 do { 156 if ((fd = open(path, O_WRONLY)) == -1) 157 if (errno != EINTR) 158 err(1, "open(%s, O_WRONLY)", 159 path); 160 if (fd == -1) 161 warn("open(%s) wr", path); 162 } while (fd == -1); 163 if (write(fd, "a", 1) != 1) 164 err(1, "write one"); 165 if (write(fd, "b", 1) != 1) 166 err(1, "write one"); 167 if (close(fd) == -1) 168 warn("close() in parent"); 169} 170 171static void 172test(void) 173{ 174 pid_t pid; 175 int status; 176 177 if ((pid = fork()) == 0) 178 reader(); 179 writer(); 180 181 if (waitpid(pid, &status, 0) != pid) 182 err(1, "waitpid(%d)", pid); 183 184 _exit(status != 0); 185} 186 187int 188main(int argc __unused, char *argv[]) 189{ 190 int e, i, pids[PARALLEL], status; 191 192 if (argc != 2) { 193 fprintf(stderr, "Usage: %s <fifo file>\n", argv[0]); 194 exit(1); 195 } 196 path = argv[1]; 197 e = 0; 198 199 unlink(path); 200 if (mkfifo(path, 0640) == -1) 201 err(1, "mkfifo(%s)", path); 202 203 for (i = 0; i < PARALLEL; i++) { 204 if ((pids[i] = fork()) == 0) 205 test(); 206 } 207 for (i = 0; i < PARALLEL; i++) { 208 if (waitpid(pids[i], &status, 0) == -1) 209 err(1, "waitpid(%d)", pids[i]); 210 e += status == 0 ? 0 : 1; 211 } 212 213 return (e); 214} 215