1 /* Test glob compat symbol which avoid call GLOB_ALTDIRFUNC/gl_lstat.
2 Copyright (C) 2017-2018 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 <http://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 compat_symbol_reference (libc
, glob
, glob
, GLIBC_2_0
);
40 /* Compat glob should not call gl_lstat since for some old binaries it
41 might be unitialized (for instance GNUmake). Check if it is indeed
43 static bool stat_called
;
44 static bool lstat_called
;
55 { "dir1lev1", 1, DT_UNKNOWN
},
58 { "file1lev2", 2, DT_REG
},
59 { "file2lev2", 2, DT_REG
},
61 static const size_t nfiles
= sizeof (filesystem
) / sizeof (filesystem
[0]);
68 char room_for_dirent
[NAME_MAX
];
72 find_file (const char *s
)
87 if (strcmp (s
, ".") == 0)
90 if (s
[0] == '.' && s
[1] == '/')
95 char *endp
= strchrnul (s
, '/');
97 while (idx
< nfiles
&& filesystem
[idx
].level
>= level
)
99 if (filesystem
[idx
].level
== level
100 && memcmp (s
, filesystem
[idx
].name
, endp
- s
) == 0
101 && filesystem
[idx
].name
[endp
- s
] == '\0')
106 if (idx
== nfiles
|| filesystem
[idx
].level
< level
)
115 if (filesystem
[idx
].type
!= DT_DIR
116 && (idx
+ 1 >= nfiles
117 || filesystem
[idx
].level
>= filesystem
[idx
+ 1].level
))
134 my_opendir (const char *s
)
136 long int idx
= find_file (s
);
137 if (idx
== -1 || filesystem
[idx
].type
!= DT_DIR
)
140 my_DIR
*dir
= malloc (sizeof (my_DIR
));
142 FAIL_EXIT1 ("cannot allocate directory handle");
144 dir
->level
= filesystem
[idx
].level
;
150 static struct dirent
*
151 my_readdir (void *gdir
)
158 while (dir
->idx
< nfiles
&& filesystem
[dir
->idx
].level
> dir
->level
)
161 if (dir
->idx
== nfiles
|| filesystem
[dir
->idx
].level
< dir
->level
)
167 dir
->d
.d_ino
= 1; /* glob should not skip this entry. */
169 dir
->d
.d_type
= filesystem
[dir
->idx
].type
;
171 strcpy (dir
->d
.d_name
, filesystem
[dir
->idx
].name
);
179 my_closedir (void *dir
)
185 my_stat (const char *name
, struct stat
*st
)
189 long int idx
= find_file (name
);
193 memset (st
, '\0', sizeof (*st
));
195 if (filesystem
[idx
].type
== DT_UNKNOWN
)
196 st
->st_mode
= DTTOIF (idx
+ 1 < nfiles
197 && filesystem
[idx
].level
< filesystem
[idx
+ 1].level
198 ? DT_DIR
: DT_REG
) | 0777;
200 st
->st_mode
= DTTOIF (filesystem
[idx
].type
) | 0777;
205 my_lstat (const char *name
, struct stat
*st
)
209 long int idx
= find_file (name
);
213 memset (st
, '\0', sizeof (*st
));
215 if (filesystem
[idx
].type
== DT_UNKNOWN
)
216 st
->st_mode
= DTTOIF (idx
+ 1 < nfiles
217 && filesystem
[idx
].level
< filesystem
[idx
+ 1].level
218 ? DT_DIR
: DT_REG
) | 0777;
220 st
->st_mode
= DTTOIF (filesystem
[idx
].type
) | 0777;
229 memset (&gl
, '\0', sizeof (gl
));
231 gl
.gl_closedir
= my_closedir
;
232 gl
.gl_readdir
= my_readdir
;
233 gl
.gl_opendir
= my_opendir
;
234 gl
.gl_lstat
= my_lstat
;
235 gl
.gl_stat
= my_stat
;
237 int flags
= GLOB_ALTDIRFUNC
;
240 lstat_called
= false;
242 TEST_VERIFY_EXIT (glob ("*/file1lev2", flags
, NULL
, &gl
) == 0);
243 TEST_VERIFY_EXIT (gl
.gl_pathc
== 1);
244 TEST_VERIFY_EXIT (strcmp (gl
.gl_pathv
[0], "dir1lev1/file1lev2") == 0);
246 TEST_VERIFY_EXIT (stat_called
== true);
247 TEST_VERIFY_EXIT (lstat_called
== false);
252 #else /* TEST_COMPAT (libc, GLIBC_2_0, GLIBC_2_27) */
261 #include <support/test-driver.c>