mktemp: fix template diagnostic with --suffix
[coreutils.git] / tests / rm / rm-readdir-fail.sh
blob8224f740f5cf4ea49fa1e88eb76da07dd8e9c5bc
1 #!/bin/sh
2 # Test rm's behavior when the directory cannot be read.
3 # This test is skipped on systems that lack LD_PRELOAD support.
5 # Copyright (C) 2016-2024 Free Software Foundation, Inc.
7 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program. If not, see <https://www.gnu.org/licenses/>.
20 . "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
21 print_ver_ rm
22 require_gcc_shared_
24 mkdir -p dir/notempty || framework_failure_
26 # Simulate "readdir" failure.
27 cat > k.c <<\EOF || framework_failure_
28 #define _GNU_SOURCE
30 /* Setup so we don't have to worry about readdir64. */
31 #ifndef __LP64__
32 # define _FILE_OFFSET_BITS 64
33 #endif
35 #include <dlfcn.h>
36 #include <dirent.h>
37 #include <errno.h>
38 #include <stdio.h>
39 #include <stdlib.h>
41 struct dirent *readdir (DIR *dirp)
43 static int count = 1;
45 #ifndef __LP64__
46 if (count == 1)
47 fclose (fopen ("32bit", "w"));
48 errno = ENOSYS;
49 return NULL;
50 #endif
52 static struct dirent *(*real_readdir)(DIR *dirp);
53 if (! real_readdir && ! (real_readdir = dlsym (RTLD_NEXT, "readdir")))
55 fprintf (stderr, "Failed to find readdir()\n");
56 errno = ESRCH;
57 return NULL;
59 struct dirent* d;
60 if (! (d = real_readdir (dirp)))
62 fprintf (stderr, "Failed to get dirent\n");
63 errno = ENOENT;
64 return NULL;
67 /* Flag that LD_PRELOAD and above functions work. */
68 if (count == 1)
69 fclose (fopen ("preloaded", "w"));
71 /* Return some entries to trigger partial read failure,
72 ensuring we don't return ignored '.' or '..' */
73 char const *readdir_partial = getenv ("READDIR_PARTIAL");
74 if (readdir_partial && *readdir_partial && count <= 3)
76 count++;
77 d->d_name[0]='0'+count; d->d_name[1]='\0';
78 #ifdef _DIRENT_HAVE_D_NAMLEN
79 d->d_namlen = 1;
80 #endif
81 errno = 0;
82 return d;
85 /* Fail. */
86 errno = ENOENT;
87 return NULL;
89 EOF
91 # Then compile/link it:
92 gcc_shared_ k.c k.so \
93 || framework_failure_ 'failed to build shared library'
95 # Test if LD_PRELOAD works:
96 export READDIR_PARTIAL
97 for READDIR_PARTIAL in '' '1'; do
98 rm -f preloaded
99 (export LD_PRELOAD=$LD_PRELOAD:./k.so
100 returns_ 1 rm -Rf dir 2>>errt) || fail=1
101 if test -f 32bit; then
102 skip_ 'This test only supports 64 bit systems'
103 elif ! test -f preloaded; then
104 cat errt
105 skip_ "internal test failure: maybe LD_PRELOAD doesn't work?"
107 done
109 # First case is failure to read any items from dir, then assume empty.
110 # Generally that will be diagnosed when rm tries to rmdir().
111 # Second case is more general error where we fail immediately
112 # (with ENOENT in this case but it could be anything).
113 cat <<EOF > exp
114 rm: cannot remove 'dir'
115 Failed to get dirent
116 rm: traversal failed: dir
118 sed 's/\(rm:.*\):.*/\1/' errt > err || framework_failure_
119 compare exp err || fail=1
121 Exit $fail