1 /* Test glob compat symbol which avoid call GLOB_ALTDIRFUNC/gl_lstat.
2 Copyright (C) 2017-2020 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>
35 #if TEST_COMPAT (libc, GLIBC_2_0, GLIBC_2_27)
38 /* On alpha glob exists in version GLIBC_2_0, GLIBC_2_1, and GLIBC_2_27.
39 This test needs to access the version prior to GLIBC_2_27, which is
40 GLIBC_2_1 on alpha, GLIBC_2_0 elsewhere. */
42 compat_symbol_reference (libc
, glob
, glob
, GLIBC_2_1
);
44 compat_symbol_reference (libc
, glob
, glob
, GLIBC_2_0
);
47 /* Compat glob should not call gl_lstat since for some old binaries it
48 might be unitialized (for instance GNUmake). Check if it is indeed
50 static bool stat_called
;
51 static bool lstat_called
;
62 { "dir1lev1", 1, DT_UNKNOWN
},
65 { "file1lev2", 2, DT_REG
},
66 { "file2lev2", 2, DT_REG
},
68 static const size_t nfiles
= sizeof (filesystem
) / sizeof (filesystem
[0]);
75 char room_for_dirent
[NAME_MAX
];
79 find_file (const char *s
)
94 if (strcmp (s
, ".") == 0)
97 if (s
[0] == '.' && s
[1] == '/')
102 char *endp
= strchrnul (s
, '/');
104 while (idx
< nfiles
&& filesystem
[idx
].level
>= level
)
106 if (filesystem
[idx
].level
== level
107 && memcmp (s
, filesystem
[idx
].name
, endp
- s
) == 0
108 && filesystem
[idx
].name
[endp
- s
] == '\0')
113 if (idx
== nfiles
|| filesystem
[idx
].level
< level
)
122 if (filesystem
[idx
].type
!= DT_DIR
123 && (idx
+ 1 >= nfiles
124 || filesystem
[idx
].level
>= filesystem
[idx
+ 1].level
))
141 my_opendir (const char *s
)
143 long int idx
= find_file (s
);
144 if (idx
== -1 || filesystem
[idx
].type
!= DT_DIR
)
147 my_DIR
*dir
= malloc (sizeof (my_DIR
));
149 FAIL_EXIT1 ("cannot allocate directory handle");
151 dir
->level
= filesystem
[idx
].level
;
157 static struct dirent
*
158 my_readdir (void *gdir
)
165 while (dir
->idx
< nfiles
&& filesystem
[dir
->idx
].level
> dir
->level
)
168 if (dir
->idx
== nfiles
|| filesystem
[dir
->idx
].level
< dir
->level
)
174 dir
->d
.d_ino
= 1; /* glob should not skip this entry. */
176 dir
->d
.d_type
= filesystem
[dir
->idx
].type
;
178 strcpy (dir
->d
.d_name
, filesystem
[dir
->idx
].name
);
186 my_closedir (void *dir
)
192 my_stat (const char *name
, struct stat
*st
)
196 long int idx
= find_file (name
);
200 memset (st
, '\0', sizeof (*st
));
202 if (filesystem
[idx
].type
== DT_UNKNOWN
)
203 st
->st_mode
= DTTOIF (idx
+ 1 < nfiles
204 && filesystem
[idx
].level
< filesystem
[idx
+ 1].level
205 ? DT_DIR
: DT_REG
) | 0777;
207 st
->st_mode
= DTTOIF (filesystem
[idx
].type
) | 0777;
212 my_lstat (const char *name
, struct stat
*st
)
216 long int idx
= find_file (name
);
220 memset (st
, '\0', sizeof (*st
));
222 if (filesystem
[idx
].type
== DT_UNKNOWN
)
223 st
->st_mode
= DTTOIF (idx
+ 1 < nfiles
224 && filesystem
[idx
].level
< filesystem
[idx
+ 1].level
225 ? DT_DIR
: DT_REG
) | 0777;
227 st
->st_mode
= DTTOIF (filesystem
[idx
].type
) | 0777;
236 memset (&gl
, '\0', sizeof (gl
));
238 gl
.gl_closedir
= my_closedir
;
239 gl
.gl_readdir
= my_readdir
;
240 gl
.gl_opendir
= my_opendir
;
241 gl
.gl_lstat
= my_lstat
;
242 gl
.gl_stat
= my_stat
;
244 int flags
= GLOB_ALTDIRFUNC
;
247 lstat_called
= false;
249 TEST_VERIFY_EXIT (glob ("*/file1lev2", flags
, NULL
, &gl
) == 0);
250 TEST_VERIFY_EXIT (gl
.gl_pathc
== 1);
251 TEST_VERIFY_EXIT (strcmp (gl
.gl_pathv
[0], "dir1lev1/file1lev2") == 0);
253 TEST_VERIFY_EXIT (stat_called
== true);
254 TEST_VERIFY_EXIT (lstat_called
== false);
259 #else /* TEST_COMPAT (libc, GLIBC_2_0, GLIBC_2_27) */
268 #include <support/test-driver.c>