1#!/bin/sh 2 3# 4# Copyright (c) 2014 EMC Corp. 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# Demonstrate that fts_read(3) will open a fifo for read. 30# Not seen on a pristine FreeBSD. 31 32# $ while ./fifo.sh; do date; done 33# Wed Oct 1 14:07:41 CEST 2014 34# Wed Oct 1 14:09:58 CEST 2014 35# FAIL 36# $ ps -l19547 37# UID PID PPID CPU PRI NI VSZ RSS MWCHAN STAT TT TIME COMMAND 38# 0 19547 19544 0 25 0 12176 3996 fifoor I 0 0:08.19 /tmp/fifo 39# $ gdb /tmp/fifo 19547 40# GNU gdb 6.1.1 [FreeBSD] 41# Copyright 2004 Free Software Foundation, Inc. 42# GDB is free software, covered by the GNU General Public License, and you are 43# welcome to change it and/or distribute copies of it under certain conditions. 44# Type "show copying" to see the conditions. 45# There is absolutely no warranty for GDB. Type "show warranty" for details. 46# This GDB was configured as "amd64-marcel-freebsd"... 47# Attaching to program: /tmp/fifo, process 19547 48# Reading symbols from /lib/libc.so.7...done. 49# Loaded symbols for /lib/libc.so.7 50# Reading symbols from /libexec/ld-elf.so.1...done. 51# Loaded symbols for /libexec/ld-elf.so.1 52# 0x00000008008a9ab8 in enc_openat () from /lib/libc.so.7 53# (gdb) bt 54# #0 0x00000008008a9ab8 in enc_openat () from /lib/libc.so.7 55# #1 0x00000008008a581b in fts_read () from /lib/libc.so.7 56# #2 0x00000008008a4f24 in fts_read () from /lib/libc.so.7 57# #3 0x0000000000400ee9 in test () at /tmp/fifo.c:86 58# #4 0x0000000000400fd8 in main () at /tmp/fifo.c:108 59# (gdb) f 3 60# #3 0x0000000000400ee9 in test () at /tmp/fifo.c:86 61# 86 while ((p = fts_read(fts)) != NULL) { 62# Current language: auto; currently minimal 63# (gdb) 64# 65 66[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 67. ../default.cfg 68 69cat > /tmp/fifo3.c <<EOF 70#include <sys/types.h> 71#include <sys/stat.h> 72#include <sys/wait.h> 73 74#include <err.h> 75#include <errno.h> 76#include <fts.h> 77#include <stdint.h> 78#include <stdio.h> 79#include <stdlib.h> 80#include <unistd.h> 81 82#define LOOPS 50 83#define PARALLEL 4 84 85void 86tmkfifo(void) 87{ 88 pid_t pid; 89 int i, j; 90 char name[80]; 91 92 setproctitle(__func__); 93 pid = getpid(); 94 for (j = 0; j < LOOPS; j++) { 95 for (i = 0; i < 1000; i++) { 96 snprintf(name, sizeof(name), "fifo.%d.%06d", pid, i); 97 if (mkfifo(name, 0644) == -1) 98 err(1, "mkfifo(%s)", name); 99 } 100 for (i = 0; i < 1000; i++) { 101 snprintf(name, sizeof(name), "fifo.%d.%06d", pid, i); 102 if (unlink(name) == -1) 103 err(1, "unlink(%s)", name); 104 } 105 } 106 _exit(0); 107} 108 109void 110tmkdir(void) 111{ 112 pid_t pid; 113 int i, j; 114 char name[80]; 115 116 setproctitle(__func__); 117 pid = getpid(); 118 for (j = 0; j < LOOPS; j++) { 119 for (i = 0; i < 1000; i++) { 120 snprintf(name, sizeof(name), "dir.%d.%06d", pid, i); 121 if (mkdir(name, 0644) == -1) 122 err(1, "mkdir(%s)", name); 123 } 124 for (i = 0; i < 1000; i++) { 125 snprintf(name, sizeof(name), "dir.%d.%06d", pid, i); 126 if (rmdir(name) == -1) 127 err(1, "unlink(%s)", name); 128 } 129 } 130 _exit(0); 131} 132 133void 134test(void) 135{ 136 FTS *fts; 137 FTSENT *p; 138 int ftsoptions, i; 139 char *args[2]; 140 141 if (fork() == 0) 142 tmkfifo(); 143 if (fork() == 0) 144 tmkdir(); 145 146 ftsoptions = FTS_PHYSICAL; 147 args[0] = "."; 148 args[1] = 0; 149 150 for (i = 0; i < LOOPS; i++) { 151 if ((fts = fts_open(args, ftsoptions, NULL)) == NULL) 152 err(1, "fts_open"); 153 154 while ((p = fts_read(fts)) != NULL) { 155#if defined(TEST) 156 fprintf(stdout, "%s\n", p->fts_path); 157#endif 158 } 159 160 if (errno != 0 && errno != ENOENT) 161 err(1, "fts_read"); 162 if (fts_close(fts) == -1) 163 err(1, "fts_close()"); 164 } 165 wait(NULL); 166 wait(NULL); 167 168 _exit(0); 169} 170 171int 172main(void) 173{ 174 int i; 175 176 for (i = 0; i < PARALLEL; i++) 177 if (fork() == 0) 178 test(); 179 for (i = 0; i < PARALLEL; i++) 180 wait(NULL); 181 182 return (0); 183} 184EOF 185mycc -o /tmp/fifo3 -Wall -Wextra -O0 -g /tmp/fifo3.c || exit 1 186 187mount | grep $mntpoint | grep -q /dev/md && umount -f $mntpoint 188[ -c /dev/md$mdstart ] && mdconfig -d -u $mdstart 189 190mdconfig -a -t swap -s 1g -u $mdstart || exit 1 191newfs md$mdstart > /dev/null 192mount /dev/md$mdstart $mntpoint 193 194(cd $mntpoint; /tmp/fifo3 ) & 195 196while pgrep -q fifo3; do 197 ps -lx | grep -v grep | grep -q fifoor && 198 { echo FAIL; exit 1; } 199 sleep 2 200done 201 202wait 203 204while mount | grep $mntpoint | grep -q /dev/md; do 205 umount $mntpoint || sleep 1 206done 207mdconfig -d -u $mdstart 208rm /tmp/fifo3 /tmp/fifo3.c 209