1#!/bin/sh 2# Test for nftw(3). 3# Copyright (C) 1997-2022 Free Software Foundation, Inc. 4# This file is part of the GNU C Library. 5 6# The GNU C Library is free software; you can redistribute it and/or 7# modify it under the terms of the GNU Lesser General Public 8# License as published by the Free Software Foundation; either 9# version 2.1 of the License, or (at your option) any later version. 10 11# The GNU C Library 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 the GNU 14# Lesser General Public License for more details. 15 16# You should have received a copy of the GNU Lesser General Public 17# License along with the GNU C Library; if not, see 18# <https://www.gnu.org/licenses/>. 19 20set -e 21 22# The common objpfx, used to find libraries and the dynamic loader. 23objpfx=$1 24 25# We expect one parameter which is the test program. This must understand 26# a number options: 27# --phys use the FTW_PHYS flag 28# --chdir use the FTW_CHDIR and print the current directory 29# in the callback 30# --depth use the FTW_DEPTH flag 31# --early-exit print file@2 item only and return non-zero from the 32# callback when it is seen 33testprogram=$2 34 35# We cannot test this as root. 36if test `id | sed "s/uid=\([0-9]*\).*/\1/"` = 0; then 37 exit 0 38fi 39 40# Since we use `sort' we must make sure to use the same locale everywhere. 41LC_ALL=C 42export LC_ALL 43 44# First create our scenario: 45tmp=${objpfx}io 46tmpdir=$(mktemp -d $tmp/ftwtest.d.XXXXXX) 47ftwtest=$(basename $tmpdir) 48 49trap 'chmod -fR a+x $tmpdir; rm -fr $tmpdir $testout' 0 1 2 3 15 50 51mkdir $tmpdir/foo 52mkdir $tmpdir/bar 53echo > $tmpdir/baz 54mkdir $tmpdir/foo/lvl1 55echo > $tmpdir/foo/lvl1/file@1 56mkdir $tmpdir/foo/lvl1/lvl2 57echo > $tmpdir/foo/lvl1/lvl2/file@2 58mkdir $tmpdir/foo/lvl1/lvl2/lvl3 59echo > $tmpdir/foo/lvl1/lvl2/lvl3/file@3 60ln -s $tmpdir $tmpdir/foo/lvl1/lvl2/lvl3/link@3 61ln -s $tmpdir/foo/lvl1/lvl2 $tmpdir/foo/lvl1/lvl2/link@2 62ln -s $tmpdir/foo/lvl1/lvl2/lvl3/lvl4 $tmpdir/foo/lvl1/link@1 63echo > $tmpdir/bar/xo 64chmod a-x,a+r $tmpdir/bar 65 66testout=$(mktemp $tmp/ftwtest-tmp-XXXXXX.out) 67 68$testprogram $tmpdir | 69 sort > $testout 70 71cat <<EOF | cmp $testout - || exit 1 72base = "$tmp/", file = "$ftwtest", flag = FTW_D, level = 0 73base = "$tmp/$ftwtest/", file = "bar", flag = FTW_D, level = 1 74base = "$tmp/$ftwtest/", file = "baz", flag = FTW_F, level = 1 75base = "$tmp/$ftwtest/", file = "foo", flag = FTW_D, level = 1 76base = "$tmp/$ftwtest/bar/", file = "xo", flag = FTW_NS, level = 2 77base = "$tmp/$ftwtest/foo/", file = "lvl1", flag = FTW_D, level = 2 78base = "$tmp/$ftwtest/foo/lvl1/", file = "file@1", flag = FTW_F, level = 3 79base = "$tmp/$ftwtest/foo/lvl1/", file = "link@1", flag = FTW_SLN, level = 3 80base = "$tmp/$ftwtest/foo/lvl1/", file = "lvl2", flag = FTW_D, level = 3 81base = "$tmp/$ftwtest/foo/lvl1/lvl2/", file = "file@2", flag = FTW_F, level = 4 82base = "$tmp/$ftwtest/foo/lvl1/lvl2/", file = "lvl3", flag = FTW_D, level = 4 83base = "$tmp/$ftwtest/foo/lvl1/lvl2/lvl3/", file = "file@3", flag = FTW_F, level = 5 84EOF 85rm $testout 86 87$testprogram --depth $tmpdir | 88 sort > $testout 89 90cat <<EOF | cmp $testout - || exit 1 91base = "$tmp/", file = "$ftwtest", flag = FTW_DP, level = 0 92base = "$tmp/$ftwtest/", file = "bar", flag = FTW_DP, level = 1 93base = "$tmp/$ftwtest/", file = "baz", flag = FTW_F, level = 1 94base = "$tmp/$ftwtest/", file = "foo", flag = FTW_DP, level = 1 95base = "$tmp/$ftwtest/bar/", file = "xo", flag = FTW_NS, level = 2 96base = "$tmp/$ftwtest/foo/", file = "lvl1", flag = FTW_DP, level = 2 97base = "$tmp/$ftwtest/foo/lvl1/", file = "file@1", flag = FTW_F, level = 3 98base = "$tmp/$ftwtest/foo/lvl1/", file = "link@1", flag = FTW_SLN, level = 3 99base = "$tmp/$ftwtest/foo/lvl1/", file = "lvl2", flag = FTW_DP, level = 3 100base = "$tmp/$ftwtest/foo/lvl1/lvl2/", file = "file@2", flag = FTW_F, level = 4 101base = "$tmp/$ftwtest/foo/lvl1/lvl2/", file = "lvl3", flag = FTW_DP, level = 4 102base = "$tmp/$ftwtest/foo/lvl1/lvl2/lvl3/", file = "file@3", flag = FTW_F, level = 5 103EOF 104rm $testout 105 106$testprogram --phys $tmpdir | 107 sort > $testout 108 109cat <<EOF | cmp $testout - || exit 1 110base = "$tmp/", file = "$ftwtest", flag = FTW_D, level = 0 111base = "$tmp/$ftwtest/", file = "bar", flag = FTW_D, level = 1 112base = "$tmp/$ftwtest/", file = "baz", flag = FTW_F, level = 1 113base = "$tmp/$ftwtest/", file = "foo", flag = FTW_D, level = 1 114base = "$tmp/$ftwtest/bar/", file = "xo", flag = FTW_NS, level = 2 115base = "$tmp/$ftwtest/foo/", file = "lvl1", flag = FTW_D, level = 2 116base = "$tmp/$ftwtest/foo/lvl1/", file = "file@1", flag = FTW_F, level = 3 117base = "$tmp/$ftwtest/foo/lvl1/", file = "link@1", flag = FTW_SL, level = 3 118base = "$tmp/$ftwtest/foo/lvl1/", file = "lvl2", flag = FTW_D, level = 3 119base = "$tmp/$ftwtest/foo/lvl1/lvl2/", file = "file@2", flag = FTW_F, level = 4 120base = "$tmp/$ftwtest/foo/lvl1/lvl2/", file = "link@2", flag = FTW_SL, level = 4 121base = "$tmp/$ftwtest/foo/lvl1/lvl2/", file = "lvl3", flag = FTW_D, level = 4 122base = "$tmp/$ftwtest/foo/lvl1/lvl2/lvl3/", file = "file@3", flag = FTW_F, level = 5 123base = "$tmp/$ftwtest/foo/lvl1/lvl2/lvl3/", file = "link@3", flag = FTW_SL, level = 5 124EOF 125rm $testout 126 127# For the next test everything must be readable. 128chmod -fR a+x $tmpdir 129 130$testprogram --chdir $tmpdir | 131 sort > $testout 132 133# perhaps $tmp involves some symlinks... 134tmpreal=`cd $tmp; pwd -P 2>/dev/null` 135 136cat <<EOF | cmp $testout - || exit 1 137base = "$tmp/", file = "$ftwtest", flag = FTW_D, cwd = $tmpreal, level = 0 138base = "$tmp/$ftwtest/", file = "bar", flag = FTW_D, cwd = $tmpreal/$ftwtest, level = 1 139base = "$tmp/$ftwtest/", file = "baz", flag = FTW_F, cwd = $tmpreal/$ftwtest, level = 1 140base = "$tmp/$ftwtest/", file = "foo", flag = FTW_D, cwd = $tmpreal/$ftwtest, level = 1 141base = "$tmp/$ftwtest/bar/", file = "xo", flag = FTW_F, cwd = $tmpreal/$ftwtest/bar, level = 2 142base = "$tmp/$ftwtest/foo/", file = "lvl1", flag = FTW_D, cwd = $tmpreal/$ftwtest/foo, level = 2 143base = "$tmp/$ftwtest/foo/lvl1/", file = "file@1", flag = FTW_F, cwd = $tmpreal/$ftwtest/foo/lvl1, level = 3 144base = "$tmp/$ftwtest/foo/lvl1/", file = "link@1", flag = FTW_SLN, cwd = $tmpreal/$ftwtest/foo/lvl1, level = 3 145base = "$tmp/$ftwtest/foo/lvl1/", file = "lvl2", flag = FTW_D, cwd = $tmpreal/$ftwtest/foo/lvl1, level = 3 146base = "$tmp/$ftwtest/foo/lvl1/lvl2/", file = "file@2", flag = FTW_F, cwd = $tmpreal/$ftwtest/foo/lvl1/lvl2, level = 4 147base = "$tmp/$ftwtest/foo/lvl1/lvl2/", file = "lvl3", flag = FTW_D, cwd = $tmpreal/$ftwtest/foo/lvl1/lvl2, level = 4 148base = "$tmp/$ftwtest/foo/lvl1/lvl2/lvl3/", file = "file@3", flag = FTW_F, cwd = $tmpreal/$ftwtest/foo/lvl1/lvl2/lvl3, level = 5 149EOF 150rm $testout 151 152curwd=`pwd -P 2>/dev/null` 153cd "$tmp" 154$testprogram --chdir $ftwtest | 155 sort > $testout 156cd "$curwd" 157 158cat <<EOF | diff -u $testout - || exit 1 159base = "", file = "$ftwtest", flag = FTW_D, cwd = $tmpreal, level = 0 160base = "$ftwtest/", file = "bar", flag = FTW_D, cwd = $tmpreal/$ftwtest, level = 1 161base = "$ftwtest/", file = "baz", flag = FTW_F, cwd = $tmpreal/$ftwtest, level = 1 162base = "$ftwtest/", file = "foo", flag = FTW_D, cwd = $tmpreal/$ftwtest, level = 1 163base = "$ftwtest/bar/", file = "xo", flag = FTW_F, cwd = $tmpreal/$ftwtest/bar, level = 2 164base = "$ftwtest/foo/", file = "lvl1", flag = FTW_D, cwd = $tmpreal/$ftwtest/foo, level = 2 165base = "$ftwtest/foo/lvl1/", file = "file@1", flag = FTW_F, cwd = $tmpreal/$ftwtest/foo/lvl1, level = 3 166base = "$ftwtest/foo/lvl1/", file = "link@1", flag = FTW_SLN, cwd = $tmpreal/$ftwtest/foo/lvl1, level = 3 167base = "$ftwtest/foo/lvl1/", file = "lvl2", flag = FTW_D, cwd = $tmpreal/$ftwtest/foo/lvl1, level = 3 168base = "$ftwtest/foo/lvl1/lvl2/", file = "file@2", flag = FTW_F, cwd = $tmpreal/$ftwtest/foo/lvl1/lvl2, level = 4 169base = "$ftwtest/foo/lvl1/lvl2/", file = "lvl3", flag = FTW_D, cwd = $tmpreal/$ftwtest/foo/lvl1/lvl2, level = 4 170base = "$ftwtest/foo/lvl1/lvl2/lvl3/", file = "file@3", flag = FTW_F, cwd = $tmpreal/$ftwtest/foo/lvl1/lvl2/lvl3, level = 5 171EOF 172rm $testout 173 174curwd=`pwd -P` 175cd "$tmp" 176$testprogram --chdir $ftwtest/. | 177 sort > $testout 178cd "$curwd" 179 180cat <<EOF | diff -u $testout - || exit 1 181base = "$ftwtest/", file = ".", flag = FTW_D, cwd = $tmpreal/$ftwtest, level = 0 182base = "$ftwtest/./", file = "bar", flag = FTW_D, cwd = $tmpreal/$ftwtest, level = 1 183base = "$ftwtest/./", file = "baz", flag = FTW_F, cwd = $tmpreal/$ftwtest, level = 1 184base = "$ftwtest/./", file = "foo", flag = FTW_D, cwd = $tmpreal/$ftwtest, level = 1 185base = "$ftwtest/./bar/", file = "xo", flag = FTW_F, cwd = $tmpreal/$ftwtest/bar, level = 2 186base = "$ftwtest/./foo/", file = "lvl1", flag = FTW_D, cwd = $tmpreal/$ftwtest/foo, level = 2 187base = "$ftwtest/./foo/lvl1/", file = "file@1", flag = FTW_F, cwd = $tmpreal/$ftwtest/foo/lvl1, level = 3 188base = "$ftwtest/./foo/lvl1/", file = "link@1", flag = FTW_SLN, cwd = $tmpreal/$ftwtest/foo/lvl1, level = 3 189base = "$ftwtest/./foo/lvl1/", file = "lvl2", flag = FTW_D, cwd = $tmpreal/$ftwtest/foo/lvl1, level = 3 190base = "$ftwtest/./foo/lvl1/lvl2/", file = "file@2", flag = FTW_F, cwd = $tmpreal/$ftwtest/foo/lvl1/lvl2, level = 4 191base = "$ftwtest/./foo/lvl1/lvl2/", file = "lvl3", flag = FTW_D, cwd = $tmpreal/$ftwtest/foo/lvl1/lvl2, level = 4 192base = "$ftwtest/./foo/lvl1/lvl2/lvl3/", file = "file@3", flag = FTW_F, cwd = $tmpreal/$ftwtest/foo/lvl1/lvl2/lvl3, level = 5 193EOF 194rm $testout 195 196curwd=`pwd -P 2>/dev/null` 197cd "$tmp" 198$testprogram --chdir $ftwtest/foo/lvl1/link@1 | 199 sort > $testout 200cd "$curwd" 201 202cat <<EOF | diff -u $testout - || exit 1 203base = "$ftwtest/foo/lvl1/", file = "link@1", flag = FTW_SLN, cwd = $tmpreal/$ftwtest/foo/lvl1, level = 0 204EOF 205rm $testout 206 207$testprogram --early-exit $tmpdir | 208 sort > $testout 209 210cat <<EOF | cmp $testout - || exit 1 211base = "$tmp/$ftwtest/foo/lvl1/lvl2/", file = "file@2", flag = FTW_F, level = 4 212succeeded 213EOF 214rm $testout 215 216mkdir $tmpdir/foo/lvl1b 217echo > $tmpdir/foo/lvl1b/file@1b 218echo > $tmpdir/foo/lvl1b/file2@1b 219echo > $tmpdir/foo/lvl1b/file3@1b 220 221$testprogram --skip-subtree=lvl1 $tmpdir | 222 sort > $testout 223 224cat <<EOF | diff -u $testout - || exit 1 225base = "$tmp/", file = "$ftwtest", flag = FTW_D, level = 0 226base = "$tmp/$ftwtest/", file = "bar", flag = FTW_D, level = 1 227base = "$tmp/$ftwtest/", file = "baz", flag = FTW_F, level = 1 228base = "$tmp/$ftwtest/", file = "foo", flag = FTW_D, level = 1 229base = "$tmp/$ftwtest/bar/", file = "xo", flag = FTW_F, level = 2 230base = "$tmp/$ftwtest/foo/", file = "lvl1", flag = FTW_D, level = 2 231base = "$tmp/$ftwtest/foo/", file = "lvl1b", flag = FTW_D, level = 2 232base = "$tmp/$ftwtest/foo/lvl1b/", file = "file2@1b", flag = FTW_F, level = 3 233base = "$tmp/$ftwtest/foo/lvl1b/", file = "file3@1b", flag = FTW_F, level = 3 234base = "$tmp/$ftwtest/foo/lvl1b/", file = "file@1b", flag = FTW_F, level = 3 235EOF 236rm $testout 237 238$testprogram --skip-siblings=lvl1 $tmpdir | 239 sort > $testout 240 241# The filesystem is not required to put lvl1 before lvl1b. 242# If lvl1b comes after lvl1, it shouldn't be printed, while if it 243# comes before, it should. 244catcmd=cat 245[ -n "`ls -U $tmpdir/foo/ | sed -n '/lvl1$/,${/lvl1b$/p;}'`" ] \ 246 && catcmd="grep -v lvl1b" 247 248$catcmd <<EOF | diff -u $testout - || exit 1 249base = "$tmp/", file = "$ftwtest", flag = FTW_D, level = 0 250base = "$tmp/$ftwtest/", file = "bar", flag = FTW_D, level = 1 251base = "$tmp/$ftwtest/", file = "baz", flag = FTW_F, level = 1 252base = "$tmp/$ftwtest/", file = "foo", flag = FTW_D, level = 1 253base = "$tmp/$ftwtest/bar/", file = "xo", flag = FTW_F, level = 2 254base = "$tmp/$ftwtest/foo/", file = "lvl1", flag = FTW_D, level = 2 255base = "$tmp/$ftwtest/foo/", file = "lvl1b", flag = FTW_D, level = 2 256base = "$tmp/$ftwtest/foo/lvl1b/", file = "file2@1b", flag = FTW_F, level = 3 257base = "$tmp/$ftwtest/foo/lvl1b/", file = "file3@1b", flag = FTW_F, level = 3 258base = "$tmp/$ftwtest/foo/lvl1b/", file = "file@1b", flag = FTW_F, level = 3 259EOF 260rm $testout 261 262$testprogram --skip-siblings=file@1b $tmpdir | 263 sort > $testout 264 265# The filesystem is not required to put file2@1b and file3@1b after file@1b. 266# If file[23]@1b come after file@1b, it shouldn't be printed, while if they 267# come before, they should. 268regexp=`echo $(ls -U $tmp/$ftwtest/foo/lvl1b \ 269 | sed -n '/file@1b$/,${/file[23]@1b$/p;}') | sed 's, ,|,'` 270catcmd=cat 271[ -n "$regexp" ] && catcmd="grep -E -v $regexp" 272 273$catcmd <<EOF | diff -u $testout - || exit 1 274base = "$tmp/", file = "$ftwtest", flag = FTW_D, level = 0 275base = "$tmp/$ftwtest/", file = "bar", flag = FTW_D, level = 1 276base = "$tmp/$ftwtest/", file = "baz", flag = FTW_F, level = 1 277base = "$tmp/$ftwtest/", file = "foo", flag = FTW_D, level = 1 278base = "$tmp/$ftwtest/bar/", file = "xo", flag = FTW_F, level = 2 279base = "$tmp/$ftwtest/foo/", file = "lvl1", flag = FTW_D, level = 2 280base = "$tmp/$ftwtest/foo/", file = "lvl1b", flag = FTW_D, level = 2 281base = "$tmp/$ftwtest/foo/lvl1/", file = "file@1", flag = FTW_F, level = 3 282base = "$tmp/$ftwtest/foo/lvl1/", file = "link@1", flag = FTW_SLN, level = 3 283base = "$tmp/$ftwtest/foo/lvl1/", file = "lvl2", flag = FTW_D, level = 3 284base = "$tmp/$ftwtest/foo/lvl1/lvl2/", file = "file@2", flag = FTW_F, level = 4 285base = "$tmp/$ftwtest/foo/lvl1/lvl2/", file = "lvl3", flag = FTW_D, level = 4 286base = "$tmp/$ftwtest/foo/lvl1/lvl2/lvl3/", file = "file@3", flag = FTW_F, level = 5 287base = "$tmp/$ftwtest/foo/lvl1b/", file = "file2@1b", flag = FTW_F, level = 3 288base = "$tmp/$ftwtest/foo/lvl1b/", file = "file3@1b", flag = FTW_F, level = 3 289base = "$tmp/$ftwtest/foo/lvl1b/", file = "file@1b", flag = FTW_F, level = 3 290EOF 291rm $testout 292 293rm -fr $tmpdir 294 295trap '' 0 296 297exit 0 298