1#!/bin/sh 2# Makes sure, inotify will switch to polling mode if directory 3# of the watched file was removed and recreated. 4# (...instead of getting stuck forever) 5 6# Copyright (C) 2017-2023 Free Software Foundation, Inc. 7 8# This program is free software: you can redistribute it and/or modify 9# it under the terms of the GNU General Public License as published by 10# the Free Software Foundation, either version 3 of the License, or 11# (at your option) any later version. 12 13# This program is distributed in the hope that it will be useful, 14# but WITHOUT ANY WARRANTY; without even the implied warranty of 15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16# GNU General Public License for more details. 17 18# You should have received a copy of the GNU General Public License 19# along with this program. If not, see <https://www.gnu.org/licenses/>. 20 21. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src 22print_ver_ tail 23 24grep '^#define HAVE_INOTIFY 1' "$CONFIG_HEADER" >/dev/null && is_local_dir_ . \ 25 || skip_ 'inotify is not supported' 26 27# Terminate any background tail process 28cleanup_() { kill $pid 2>/dev/null && wait $pid; } 29 30cleanup_fail_ () 31{ 32 warn_ $1 33 cleanup_ 34 fail=1 35} 36 37# $check_re - string to be found 38# $check_f - file to be searched 39check_tail_output_ () 40{ 41 local delay="$1" 42 grep $check_re $check_f > /dev/null || 43 { sleep $delay ; return 1; } 44} 45 46grep_timeout_ () 47{ 48 check_re="$1" 49 check_f="$2" 50 retry_delay_ check_tail_output_ .1 5 51} 52 53# Prepare the file to be watched 54mkdir dir && echo 'inotify' > dir/file || framework_failure_ 55 56#tail must print content of the file to stdout, verify 57timeout 60 tail --pid=$$ -F dir/file >out 2>&1 & pid=$! 58grep_timeout_ 'inotify' 'out' || 59{ cleanup_fail_ 'file to be tailed does not exist'; } 60 61inotify_failed_re='inotify (resources exhausted|cannot be used)' 62grep -E "$inotify_failed_re" out && 63 skip_ "inotify can't be used" 64 65# Remove the directory, should get the message about the deletion 66rm -r dir || framework_failure_ 67grep_timeout_ 'polling' 'out' || 68{ cleanup_fail_ 'tail did not switch to polling mode'; } 69 70# Recreate the dir, must get a message about recreation 71mkdir dir && touch dir/file || framework_failure_ 72grep_timeout_ 'appeared' 'out' || 73{ cleanup_fail_ 'previously removed file did not appear'; } 74 75cleanup_ 76 77# Expected result for the whole process 78cat <<\EOF > exp || framework_failure_ 79inotify 80tail: 'dir/file' has become inaccessible: No such file or directory 81tail: directory containing watched file was removed 82tail: inotify cannot be used, reverting to polling 83tail: 'dir/file' has appeared; following new file 84EOF 85 86compare exp out || fail=1 87 88Exit $fail 89