Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
at release-16.03 216 lines 7.4 kB view raw
1commit 68302147ee061c69eb447e243ad9a18ef4cfbc4c 2Author: Florian Weimer <fweimer@redhat.com> 3Date: Fri Apr 29 09:33:07 2016 +0200 4 5 glob: Simplify the interface for the GLOB_ALTDIRFUNC callback gl_readdir 6 7 Previously, application code had to set up the d_namlen member if 8 the target supported it, involving conditional compilation. After 9 this change, glob will use the length of the string in d_name instead 10 of d_namlen to determine the file name length. All glibc targets 11 provide the d_type and d_ino members, and setting them as needed for 12 gl_readdir is straightforward. 13 14 Changing the behavior with regards to d_ino is left to a future 15 cleanup. 16 17 (cherry picked from commit 137fe72eca6923a00381a3ca9f0e7672c1f85e3f) 18 19diff --git a/manual/examples/mkdirent.c b/manual/examples/mkdirent.c 20new file mode 100644 21index 0000000..f8400f4 22--- /dev/null 23+++ b/manual/examples/mkdirent.c 24@@ -0,0 +1,42 @@ 25+/* Example for creating a struct dirent object for use with glob. 26+ Copyright (C) 2016 Free Software Foundation, Inc. 27+ 28+ This program is free software; you can redistribute it and/or 29+ modify it under the terms of the GNU General Public License 30+ as published by the Free Software Foundation; either version 2 31+ of the License, or (at your option) any later version. 32+ 33+ This program is distributed in the hope that it will be useful, 34+ but WITHOUT ANY WARRANTY; without even the implied warranty of 35+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 36+ GNU General Public License for more details. 37+ 38+ You should have received a copy of the GNU General Public License 39+ along with this program; if not, if not, see <http://www.gnu.org/licenses/>. 40+*/ 41+ 42+#include <dirent.h> 43+#include <errno.h> 44+#include <stddef.h> 45+#include <stdlib.h> 46+#include <string.h> 47+ 48+struct dirent * 49+mkdirent (const char *name) 50+{ 51+ size_t dirent_size = offsetof (struct dirent, d_name) + 1; 52+ size_t name_length = strlen (name); 53+ size_t total_size = dirent_size + name_length; 54+ if (total_size < dirent_size) 55+ { 56+ errno = ENOMEM; 57+ return NULL; 58+ } 59+ struct dirent *result = malloc (total_size); 60+ if (result == NULL) 61+ return NULL; 62+ result->d_type = DT_UNKNOWN; 63+ result->d_ino = 1; /* Do not skip this entry. */ 64+ memcpy (result->d_name, name, name_length + 1); 65+ return result; 66+} 67diff --git a/manual/pattern.texi b/manual/pattern.texi 68index d1b9275..565e7eb 100644 69--- a/manual/pattern.texi 70+++ b/manual/pattern.texi 71@@ -237,7 +237,44 @@ function used to read the contents of a directory. It is used if the 72 @code{GLOB_ALTDIRFUNC} bit is set in the flag parameter. The type of 73 this field is @w{@code{struct dirent *(*) (void *)}}. 74 75-This is a GNU extension. 76+An implementation of @code{gl_readdir} needs to initialize the following 77+members of the @code{struct dirent} object: 78+ 79+@table @code 80+@item d_type 81+This member should be set to the file type of the entry if it is known. 82+Otherwise, the value @code{DT_UNKNOWN} can be used. The @code{glob} 83+function may use the specified file type to avoid callbacks in cases 84+where the file type indicates that the data is not required. 85+ 86+@item d_ino 87+This member needs to be non-zero, otherwise @code{glob} may skip the 88+current entry and call the @code{gl_readdir} callback function again to 89+retrieve another entry. 90+ 91+@item d_name 92+This member must be set to the name of the entry. It must be 93+null-terminated. 94+@end table 95+ 96+The example below shows how to allocate a @code{struct dirent} object 97+containing a given name. 98+ 99+@smallexample 100+@include mkdirent.c.texi 101+@end smallexample 102+ 103+The @code{glob} function reads the @code{struct dirent} members listed 104+above and makes a copy of the file name in the @code{d_name} member 105+immediately after the @code{gl_readdir} callback function returns. 106+Future invocations of any of the callback functions may dealloacte or 107+reuse the buffer. It is the responsibility of the caller of the 108+@code{glob} function to allocate and deallocate the buffer, around the 109+call to @code{glob} or using the callback functions. For example, an 110+application could allocate the buffer in the @code{gl_readdir} callback 111+function, and deallocate it in the @code{gl_closedir} callback function. 112+ 113+The @code{gl_readdir} member is a GNU extension. 114 115 @item gl_opendir 116 The address of an alternative implementation of the @code{opendir} 117diff --git a/posix/bug-glob2.c b/posix/bug-glob2.c 118index ddf5ec9..0fdc5d0 100644 119--- a/posix/bug-glob2.c 120+++ b/posix/bug-glob2.c 121@@ -193,7 +193,7 @@ my_readdir (void *gdir) 122 return NULL; 123 } 124 125- dir->d.d_ino = dir->idx; 126+ dir->d.d_ino = 1; /* glob should not skip this entry. */ 127 128 #ifdef _DIRENT_HAVE_D_TYPE 129 dir->d.d_type = filesystem[dir->idx].type; 130diff --git a/posix/glob.c b/posix/glob.c 131index 0c04c3c..9ae76ac 100644 132--- a/posix/glob.c 133+++ b/posix/glob.c 134@@ -57,10 +57,8 @@ 135 136 #if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__ 137 # include <dirent.h> 138-# define NAMLEN(dirent) strlen((dirent)->d_name) 139 #else 140 # define dirent direct 141-# define NAMLEN(dirent) (dirent)->d_namlen 142 # ifdef HAVE_SYS_NDIR_H 143 # include <sys/ndir.h> 144 # endif 145@@ -76,12 +74,6 @@ 146 #endif 147 148 149-/* In GNU systems, <dirent.h> defines this macro for us. */ 150-#ifdef _D_NAMLEN 151-# undef NAMLEN 152-# define NAMLEN(d) _D_NAMLEN(d) 153-#endif 154- 155 /* When used in the GNU libc the symbol _DIRENT_HAVE_D_TYPE is available 156 if the `d_type' member for `struct dirent' is available. 157 HAVE_STRUCT_DIRENT_D_TYPE plays the same role in GNULIB. */ 158@@ -105,12 +97,6 @@ 159 160 /* If the system has the `struct dirent64' type we use it internally. */ 161 #if defined _LIBC && !defined COMPILE_GLOB64 162-# if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__ 163-# define CONVERT_D_NAMLEN(d64, d32) 164-# else 165-# define CONVERT_D_NAMLEN(d64, d32) \ 166- (d64)->d_namlen = (d32)->d_namlen; 167-# endif 168 169 # if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__ 170 # define CONVERT_D_INO(d64, d32) 171@@ -127,8 +113,7 @@ 172 # endif 173 174 # define CONVERT_DIRENT_DIRENT64(d64, d32) \ 175- memcpy ((d64)->d_name, (d32)->d_name, NAMLEN (d32) + 1); \ 176- CONVERT_D_NAMLEN (d64, d32) \ 177+ strcpy ((d64)->d_name, (d32)->d_name); \ 178 CONVERT_D_INO (d64, d32) \ 179 CONVERT_D_TYPE (d64, d32) 180 #endif 181@@ -1554,7 +1539,6 @@ glob_in_dir (const char *pattern, const char *directory, int flags, 182 while (1) 183 { 184 const char *name; 185- size_t len; 186 #if defined _LIBC && !defined COMPILE_GLOB64 187 struct dirent64 *d; 188 union 189@@ -1622,12 +1606,10 @@ glob_in_dir (const char *pattern, const char *directory, int flags, 190 names = newnames; 191 cur = 0; 192 } 193- len = NAMLEN (d); 194- names->name[cur] = (char *) malloc (len + 1); 195+ names->name[cur] = strdup (d->d_name); 196 if (names->name[cur] == NULL) 197 goto memory_error; 198- *((char *) mempcpy (names->name[cur++], name, len)) 199- = '\0'; 200+ ++cur; 201 ++nfound; 202 } 203 } 204diff --git a/posix/tst-gnuglob.c b/posix/tst-gnuglob.c 205index 992b997..b7b859b 100644 206--- a/posix/tst-gnuglob.c 207+++ b/posix/tst-gnuglob.c 208@@ -211,7 +211,7 @@ my_readdir (void *gdir) 209 return NULL; 210 } 211 212- dir->d.d_ino = dir->idx; 213+ dir->d.d_ino = 1; /* glob should not skip this entry. */ 214 215 #ifdef _DIRENT_HAVE_D_TYPE 216 dir->d.d_type = filesystem[dir->idx].type;