1 /* Test glob compat symbol which avoid call GLOB_ALTDIRFUNC/gl_lstat.
2 Copyright (C) 2017-2024 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
23 #include <sys/types.h>
25 #include <sys/types.h>
31 #include <shlib-compat.h>
32 #include <support/check.h>
33 #include <support/temp_file.h>
36 /* On alpha glob exists in version GLIBC_2_0, GLIBC_2_1, and GLIBC_2_27.
37 This test needs to access the version prior to GLIBC_2_27, which is
38 GLIBC_2_1 on alpha, GLIBC_2_0 elsewhere. */
40 compat_symbol_reference (libc
, glob
, glob
, GLIBC_2_1
);
42 compat_symbol_reference (libc
, glob
, glob
, GLIBC_2_0
);
45 /* Compat glob should not call gl_lstat since for some old binaries it
46 might be uninitialized (for instance GNUmake). Check if it is indeed
48 static bool stat_called
;
49 static bool lstat_called
;
60 { "dir1lev1", 1, DT_UNKNOWN
},
63 { "file1lev2", 2, DT_REG
},
64 { "file2lev2", 2, DT_REG
},
66 static const size_t nfiles
= sizeof (filesystem
) / sizeof (filesystem
[0]);
73 char room_for_dirent
[NAME_MAX
];
77 find_file (const char *s
)
92 if (strcmp (s
, ".") == 0)
95 if (s
[0] == '.' && s
[1] == '/')
100 char *endp
= strchrnul (s
, '/');
102 while (idx
< nfiles
&& filesystem
[idx
].level
>= level
)
104 if (filesystem
[idx
].level
== level
105 && memcmp (s
, filesystem
[idx
].name
, endp
- s
) == 0
106 && filesystem
[idx
].name
[endp
- s
] == '\0')
111 if (idx
== nfiles
|| filesystem
[idx
].level
< level
)
120 if (filesystem
[idx
].type
!= DT_DIR
121 && (idx
+ 1 >= nfiles
122 || filesystem
[idx
].level
>= filesystem
[idx
+ 1].level
))
139 my_opendir (const char *s
)
141 long int idx
= find_file (s
);
142 if (idx
== -1 || filesystem
[idx
].type
!= DT_DIR
)
145 my_DIR
*dir
= malloc (sizeof (my_DIR
));
147 FAIL_EXIT1 ("cannot allocate directory handle");
149 dir
->level
= filesystem
[idx
].level
;
155 static struct dirent
*
156 my_readdir (void *gdir
)
163 while (dir
->idx
< nfiles
&& filesystem
[dir
->idx
].level
> dir
->level
)
166 if (dir
->idx
== nfiles
|| filesystem
[dir
->idx
].level
< dir
->level
)
172 dir
->d
.d_ino
= 1; /* glob should not skip this entry. */
174 dir
->d
.d_type
= filesystem
[dir
->idx
].type
;
176 __strcpy_chk (dir
->d
.d_name
, filesystem
[dir
->idx
].name
, NAME_MAX
);
184 my_closedir (void *dir
)
190 my_stat (const char *name
, struct stat
*st
)
194 long int idx
= find_file (name
);
198 memset (st
, '\0', sizeof (*st
));
200 if (filesystem
[idx
].type
== DT_UNKNOWN
)
201 st
->st_mode
= DTTOIF (idx
+ 1 < nfiles
202 && filesystem
[idx
].level
< filesystem
[idx
+ 1].level
203 ? DT_DIR
: DT_REG
) | 0777;
205 st
->st_mode
= DTTOIF (filesystem
[idx
].type
) | 0777;
210 my_lstat (const char *name
, struct stat
*st
)
214 long int idx
= find_file (name
);
218 memset (st
, '\0', sizeof (*st
));
220 if (filesystem
[idx
].type
== DT_UNKNOWN
)
221 st
->st_mode
= DTTOIF (idx
+ 1 < nfiles
222 && filesystem
[idx
].level
< filesystem
[idx
+ 1].level
223 ? DT_DIR
: DT_REG
) | 0777;
225 st
->st_mode
= DTTOIF (filesystem
[idx
].type
) | 0777;
234 memset (&gl
, '\0', sizeof (gl
));
236 gl
.gl_closedir
= my_closedir
;
237 gl
.gl_readdir
= my_readdir
;
238 gl
.gl_opendir
= my_opendir
;
239 gl
.gl_lstat
= my_lstat
;
240 gl
.gl_stat
= my_stat
;
242 int flags
= GLOB_ALTDIRFUNC
;
245 lstat_called
= false;
247 TEST_VERIFY_EXIT (glob ("*/file1lev2", flags
, NULL
, &gl
) == 0);
248 TEST_VERIFY_EXIT (gl
.gl_pathc
== 1);
249 TEST_VERIFY_EXIT (strcmp (gl
.gl_pathv
[0], "dir1lev1/file1lev2") == 0);
251 TEST_VERIFY_EXIT (stat_called
== true);
252 TEST_VERIFY_EXIT (lstat_called
== false);
257 #include <support/test-driver.c>