mirror of git://sourceware.org/git/glibc.git
glob: Simplify the interface for the GLOB_ALTDIRFUNC callback gl_readdir
Previously, application code had to set up the d_namlen member if the target supported it, involving conditional compilation. After this change, glob will use the length of the string in d_name instead of d_namlen to determine the file name length. All glibc targets provide the d_type and d_ino members, and setting them as needed for gl_readdir is straightforward. Changing the behavior with regards to d_ino is left to a future cleanup.
This commit is contained in:
parent
a7657f3012
commit
137fe72eca
15
ChangeLog
15
ChangeLog
|
|
@ -1,3 +1,18 @@
|
|||
2016-04-29 Florian Weimer <fweimer@redhat.com>
|
||||
|
||||
glob: Simplify and document the interface for the GLOB_ALTDIRFUNC
|
||||
callback function gl_readdir.
|
||||
* posix/glob.c (NAMELEN, CONVERT_D_NAMLEN): Remove.
|
||||
(CONVERT_DIRENT_DIRENT64): Use strcpy instead of memcpy.
|
||||
(glob_in_dir): Remove len. Use strdup instead of malloc and
|
||||
memcpy to copy the name.
|
||||
* manual/pattern.texi (Calling Glob): Document requirements for
|
||||
implementations of the gl_readdir callback function.
|
||||
* manual/examples/mkdirent.c: New example.
|
||||
* posix/bug-glob2.c (my_readdir): Set d_ino to 1 unconditionally,
|
||||
per the manual guidance.
|
||||
* posix/tst-gnuglob.c (my_readdir): Likewise.
|
||||
|
||||
2016-04-28 Joseph Myers <joseph@codesourcery.com>
|
||||
|
||||
[BZ #20014]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
/* Example for creating a struct dirent object for use with glob.
|
||||
Copyright (C) 2016 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct dirent *
|
||||
mkdirent (const char *name)
|
||||
{
|
||||
size_t dirent_size = offsetof (struct dirent, d_name) + 1;
|
||||
size_t name_length = strlen (name);
|
||||
size_t total_size = dirent_size + name_length;
|
||||
if (total_size < dirent_size)
|
||||
{
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
struct dirent *result = malloc (total_size);
|
||||
if (result == NULL)
|
||||
return NULL;
|
||||
result->d_type = DT_UNKNOWN;
|
||||
result->d_ino = 1; /* Do not skip this entry. */
|
||||
memcpy (result->d_name, name, name_length + 1);
|
||||
return result;
|
||||
}
|
||||
|
|
@ -237,7 +237,44 @@ function used to read the contents of a directory. It is used if the
|
|||
@code{GLOB_ALTDIRFUNC} bit is set in the flag parameter. The type of
|
||||
this field is @w{@code{struct dirent *(*) (void *)}}.
|
||||
|
||||
This is a GNU extension.
|
||||
An implementation of @code{gl_readdir} needs to initialize the following
|
||||
members of the @code{struct dirent} object:
|
||||
|
||||
@table @code
|
||||
@item d_type
|
||||
This member should be set to the file type of the entry if it is known.
|
||||
Otherwise, the value @code{DT_UNKNOWN} can be used. The @code{glob}
|
||||
function may use the specified file type to avoid callbacks in cases
|
||||
where the file type indicates that the data is not required.
|
||||
|
||||
@item d_ino
|
||||
This member needs to be non-zero, otherwise @code{glob} may skip the
|
||||
current entry and call the @code{gl_readdir} callback function again to
|
||||
retrieve another entry.
|
||||
|
||||
@item d_name
|
||||
This member must be set to the name of the entry. It must be
|
||||
null-terminated.
|
||||
@end table
|
||||
|
||||
The example below shows how to allocate a @code{struct dirent} object
|
||||
containing a given name.
|
||||
|
||||
@smallexample
|
||||
@include mkdirent.c.texi
|
||||
@end smallexample
|
||||
|
||||
The @code{glob} function reads the @code{struct dirent} members listed
|
||||
above and makes a copy of the file name in the @code{d_name} member
|
||||
immediately after the @code{gl_readdir} callback function returns.
|
||||
Future invocations of any of the callback functions may dealloacte or
|
||||
reuse the buffer. It is the responsibility of the caller of the
|
||||
@code{glob} function to allocate and deallocate the buffer, around the
|
||||
call to @code{glob} or using the callback functions. For example, an
|
||||
application could allocate the buffer in the @code{gl_readdir} callback
|
||||
function, and deallocate it in the @code{gl_closedir} callback function.
|
||||
|
||||
The @code{gl_readdir} member is a GNU extension.
|
||||
|
||||
@item gl_opendir
|
||||
The address of an alternative implementation of the @code{opendir}
|
||||
|
|
|
|||
|
|
@ -193,7 +193,7 @@ my_readdir (void *gdir)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
dir->d.d_ino = dir->idx;
|
||||
dir->d.d_ino = 1; /* glob should not skip this entry. */
|
||||
|
||||
#ifdef _DIRENT_HAVE_D_TYPE
|
||||
dir->d.d_type = filesystem[dir->idx].type;
|
||||
|
|
|
|||
24
posix/glob.c
24
posix/glob.c
|
|
@ -57,10 +57,8 @@
|
|||
|
||||
#if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__
|
||||
# include <dirent.h>
|
||||
# define NAMLEN(dirent) strlen((dirent)->d_name)
|
||||
#else
|
||||
# define dirent direct
|
||||
# define NAMLEN(dirent) (dirent)->d_namlen
|
||||
# ifdef HAVE_SYS_NDIR_H
|
||||
# include <sys/ndir.h>
|
||||
# endif
|
||||
|
|
@ -76,12 +74,6 @@
|
|||
#endif
|
||||
|
||||
|
||||
/* In GNU systems, <dirent.h> defines this macro for us. */
|
||||
#ifdef _D_NAMLEN
|
||||
# undef NAMLEN
|
||||
# define NAMLEN(d) _D_NAMLEN(d)
|
||||
#endif
|
||||
|
||||
/* When used in the GNU libc the symbol _DIRENT_HAVE_D_TYPE is available
|
||||
if the `d_type' member for `struct dirent' is available.
|
||||
HAVE_STRUCT_DIRENT_D_TYPE plays the same role in GNULIB. */
|
||||
|
|
@ -105,12 +97,6 @@
|
|||
|
||||
/* If the system has the `struct dirent64' type we use it internally. */
|
||||
#if defined _LIBC && !defined COMPILE_GLOB64
|
||||
# if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__
|
||||
# define CONVERT_D_NAMLEN(d64, d32)
|
||||
# else
|
||||
# define CONVERT_D_NAMLEN(d64, d32) \
|
||||
(d64)->d_namlen = (d32)->d_namlen;
|
||||
# endif
|
||||
|
||||
# if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
|
||||
# define CONVERT_D_INO(d64, d32)
|
||||
|
|
@ -127,8 +113,7 @@
|
|||
# endif
|
||||
|
||||
# define CONVERT_DIRENT_DIRENT64(d64, d32) \
|
||||
memcpy ((d64)->d_name, (d32)->d_name, NAMLEN (d32) + 1); \
|
||||
CONVERT_D_NAMLEN (d64, d32) \
|
||||
strcpy ((d64)->d_name, (d32)->d_name); \
|
||||
CONVERT_D_INO (d64, d32) \
|
||||
CONVERT_D_TYPE (d64, d32)
|
||||
#endif
|
||||
|
|
@ -1554,7 +1539,6 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
|
|||
while (1)
|
||||
{
|
||||
const char *name;
|
||||
size_t len;
|
||||
#if defined _LIBC && !defined COMPILE_GLOB64
|
||||
struct dirent64 *d;
|
||||
union
|
||||
|
|
@ -1622,12 +1606,10 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
|
|||
names = newnames;
|
||||
cur = 0;
|
||||
}
|
||||
len = NAMLEN (d);
|
||||
names->name[cur] = (char *) malloc (len + 1);
|
||||
names->name[cur] = strdup (d->d_name);
|
||||
if (names->name[cur] == NULL)
|
||||
goto memory_error;
|
||||
*((char *) mempcpy (names->name[cur++], name, len))
|
||||
= '\0';
|
||||
++cur;
|
||||
++nfound;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -211,7 +211,7 @@ my_readdir (void *gdir)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
dir->d.d_ino = dir->idx;
|
||||
dir->d.d_ino = 1; /* glob should not skip this entry. */
|
||||
|
||||
#ifdef _DIRENT_HAVE_D_TYPE
|
||||
dir->d.d_type = filesystem[dir->idx].type;
|
||||
|
|
|
|||
Loading…
Reference in New Issue