This is the mail archive of the
glibc-cvs@sourceware.org
mailing list for the glibc project.
GNU C Library master sources branch azanella/glob-fixes created. glibc-2.25-823-g80aed7e
- From: azanella at sourceware dot org
- To: glibc-cvs at sourceware dot org
- Date: 26 Jul 2017 20:17:06 -0000
- Subject: GNU C Library master sources branch azanella/glob-fixes created. glibc-2.25-823-g80aed7e
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".
The branch, azanella/glob-fixes has been created
at 80aed7ed5a919358c0bce9bfee97c4d8ac533d5e (commit)
- Log -----------------------------------------------------------------
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=80aed7ed5a919358c0bce9bfee97c4d8ac533d5e
commit 80aed7ed5a919358c0bce9bfee97c4d8ac533d5e
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Wed Jul 26 16:09:26 2017 -0300
posix: Fix glob with GLOB_NOCHECK returning modified patterns (BZ#10246)
Acconding to POSIX glob with GLOB_NOCHECK should return a list consisting
of only of the input pattern in case of no match. However GLIBC does not
honor in case of '//<something'. This is due internally this is handled
and special case and prefix_array (responsable to prepend the directory
name) does not know if the input already contains a slash or not since
either '/<something>' or '//<something>' will be handle in same way.
This patch fix it by using a empty directory name for the latter (since
prefix_array already adds a slash as default for each entry).
Checked on x86_64-linux-gnu.
[BZ #10246]
* posix/glob.c (glob): Handle pattern that do not match and
start with '/' correctly.
* posix/globtest.sh: New tests for NOCHECK.
diff --git a/posix/glob.c b/posix/glob.c
index e94d0f7..744bcce 100644
--- a/posix/glob.c
+++ b/posix/glob.c
@@ -357,6 +357,8 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
size_t oldcount;
int meta;
bool dirname_modified;
+ /* Indicate if the directory should be prepended on return values. */
+ bool dirname_prefix = true;
glob_t dirs;
int retval = 0;
struct char_array dirname;
@@ -590,6 +592,10 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
goto err_nospace;
dirlen = 1;
++filename;
+ /* prefix_array adds a separator for each result and DIRNAME is
+ already '/'. So we indicate later that we should not prepend
+ anything for this specific case. */
+ dirname_prefix = false;
}
else
{
@@ -1099,7 +1105,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
if (dirlen > 0)
{
/* Stick the directory on the front of each name. */
- if (prefix_array (char_array_str (&dirname),
+ if (prefix_array (dirname_prefix ? char_array_str (&dirname) : "",
&pglob->gl_pathv[old_pathc + pglob->gl_offs],
pglob->gl_pathc - old_pathc))
{
@@ -1196,12 +1202,8 @@ prefix_array (const char *dirname, char **array, size_t n)
# define DIRSEP_CHAR '/'
#endif
- if (dirlen == 1 && dirname[0] == '/')
- /* DIRNAME is just "/", so normal prepending would get us "//foo".
- We want "/foo" instead, so don't prepend any chars from DIRNAME. */
- dirlen = 0;
#if defined __MSDOS__ || defined WINDOWS32
- else if (dirlen > 1)
+ if (dirlen > 1)
{
if (dirname[dirlen - 1] == '/' && dirname[dirlen - 2] == ':')
/* DIRNAME is "d:/". Don't prepend the slash from DIRNAME. */
diff --git a/posix/globtest.sh b/posix/globtest.sh
index 73f7ae3..938bc47 100755
--- a/posix/globtest.sh
+++ b/posix/globtest.sh
@@ -242,6 +242,42 @@ if test $failed -ne 0; then
result=1
fi
+# Test NOCHECK for specific cases where the pattern used starts
+# with '/' (BZ#10246).
+failed=0
+${test_program_prefix} \
+${common_objpfx}posix/globtest -c "$testdir" "/%" |
+sort > $testout
+cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
+`/%'
+EOF
+if test $failed -ne 0; then
+ echo "No check test failed" >> $logfile
+ result=1
+fi
+
+${test_program_prefix} \
+${common_objpfx}posix/globtest -c "$testdir" "//%" |
+sort > $testout
+cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
+`//%'
+EOF
+if test $failed -ne 0; then
+ echo "No check test failed" >> $logfile
+ result=1
+fi
+
+${test_program_prefix} \
+${common_objpfx}posix/globtest -c "$testdir" "///%" |
+sort > $testout
+cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
+`///%'
+EOF
+if test $failed -ne 0; then
+ echo "No check test failed" >> $logfile
+ result=1
+fi
+
# Test NOMAGIC without magic characters
failed=0
${test_program_prefix} \
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=c50dfe79df1b3a3fe3ba3bc1eba3c354a5d122a6
commit c50dfe79df1b3a3fe3ba3bc1eba3c354a5d122a6
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Wed Jul 26 11:39:49 2017 -0300
posix: Use enum for __glob_pattern_type result
This patch replaces the internal integer constant from
__glob_pattern_type return with a proper enum.
Checked on x86_64-linux-gnu.
* posix/glob_internal.h (__glob_pat_types): New enumeration.
(__glob_pattern_type): Use __glob_pat_types.
* posix/glob_pattern_p.c (__glob_pattern_p): Likewise.
* posix/glob.c (glob): Likewise.
(glob_in_dir): Likewise.
diff --git a/posix/glob.c b/posix/glob.c
index 0ab2eaf..e94d0f7 100644
--- a/posix/glob.c
+++ b/posix/glob.c
@@ -905,7 +905,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
[ which we handle the same, using fnmatch. Broken unterminated
pattern bracket expressions ought to be rare enough that it is
not worth special casing them, fnmatch will do the right thing. */
- if (meta & 5)
+ if (meta & (__glob_special | __glob_bracket))
{
/* The directory name contains metacharacters, so we
have to glob for the directory, and then glob for
@@ -1057,7 +1057,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
size_t old_pathc = pglob->gl_pathc;
int orig_flags = flags;
- if (meta & 2)
+ if (meta & __glob_backslash)
{
char *p = strchr (char_array_str (&dirname), '\\'), *q;
/* We need to unescape the dirname string. It is certainly
@@ -1270,14 +1270,14 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
globnames_array_init (&globnames);
meta = __glob_pattern_type (pattern, !(flags & GLOB_NOESCAPE));
- if (meta == 0 && (flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
+ if (meta == __glob_none && (flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
{
/* We need not do any tests. The PATTERN contains no meta
characters and we must not return an error therefore the
result will always contain exactly one name. */
flags |= GLOB_NOCHECK;
}
- else if (meta == 0)
+ else if (meta == __glob_none)
{
/* Since we use the normal file functions we can also use stat()
to verify the file is there. */
diff --git a/posix/glob_internal.h b/posix/glob_internal.h
index d989a98..54143c2 100644
--- a/posix/glob_internal.h
+++ b/posix/glob_internal.h
@@ -19,35 +19,43 @@
#ifndef GLOB_INTERNAL_H
# define GLOB_INTERNAL_H
+enum __glob_pat_types
+{
+ __glob_none = 0x0,
+ __glob_special = 0x1,
+ __glob_backslash = 0x2,
+ __glob_bracket = 0x4
+};
+
static inline int
__glob_pattern_type (const char *pattern, int quote)
{
const char *p;
- int ret = 0;
+ int ret = __glob_none;
for (p = pattern; *p != '\0'; ++p)
switch (*p)
{
case '?':
case '*':
- return 1;
+ return __glob_special;
case '\\':
if (quote)
{
if (p[1] != '\0')
++p;
- ret |= 2;
+ ret |= __glob_backslash;
}
break;
case '[':
- ret |= 4;
+ ret |= __glob_bracket;
break;
case ']':
if (ret & 4)
- return 1;
+ return __glob_special;
break;
}
diff --git a/posix/glob_pattern_p.c b/posix/glob_pattern_p.c
index 6e451f2..61caf37 100644
--- a/posix/glob_pattern_p.c
+++ b/posix/glob_pattern_p.c
@@ -24,6 +24,6 @@
int
__glob_pattern_p (const char *pattern, int quote)
{
- return __glob_pattern_type (pattern, quote) == 1;
+ return __glob_pattern_type (pattern, quote) == __glob_special;
}
weak_alias (__glob_pattern_p, glob_pattern_p)
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=6e05025f557147feec2772f2e65a2f95baae0eee
commit 6e05025f557147feec2772f2e65a2f95baae0eee
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Wed Jun 7 09:33:19 2017 -0300
posix: More check for overflow allocation in glob
This patch adds and replace the allocation overflow based using
malloc internal functions check_add_wrapv_size_t and __libc_reallocarray.
Checked on x86_64-linux-gnu.
* posix/glob.c (glob_malloc_incr): New function.
(glob_malloc_incr2): Likewise.
(glob_realloc_incr): Likewise.
(glob): Use glob_{realloc,malloc}_incr{2}.
diff --git a/posix/glob.c b/posix/glob.c
index 5dc1fd5..0ab2eaf 100644
--- a/posix/glob.c
+++ b/posix/glob.c
@@ -302,6 +302,39 @@ get_home_directory (const char *user_name, struct char_array *home_dir)
return retval;
}
+/* Allocate '(size + incr) * typesize' bytes while for overflow on the
+ arithmetic operations. */
+static void *
+glob_malloc_incr (size_t size, size_t incr, size_t typesize)
+{
+ size_t newsize;
+ if (check_add_overflow_size_t (size, incr, &newsize))
+ return NULL;
+ return __libc_reallocarray (NULL, newsize, typesize);
+}
+
+/* Allocate '(size + incr1 + incr2) * typesize' bytes while for overflow on
+ the arithmetic operations. */
+static void *
+glob_malloc_incr2 (size_t size, size_t incr1, size_t incr2, size_t typesize)
+{
+ size_t newsize;
+ if (check_add_overflow_size_t (size, incr1, &newsize)
+ || check_add_overflow_size_t (newsize, incr2, &newsize))
+ return NULL;
+ return __libc_reallocarray (NULL, newsize, typesize);
+}
+
+/* Reallocate '(size + incr1) * typesize' bytes while for overflow on the
+ arithmetic operations. */
+static void *
+glob_realloc_incr (void *old, size_t size, size_t incr, size_t typesize)
+{
+ size_t newsize;
+ if (check_add_overflow_size_t (size, incr, &newsize))
+ return NULL;
+ return __libc_reallocarray (old, newsize, typesize);
+}
/* Do glob searching for PATTERN, placing results in PGLOB.
The bits defined above may be set in FLAGS.
@@ -356,11 +389,8 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
{
size_t i;
- if (pglob->gl_offs >= ~((size_t) 0) / sizeof (char *))
- goto err_nospace;
-
- pglob->gl_pathv = (char **) malloc ((pglob->gl_offs + 1)
- * sizeof (char *));
+ pglob->gl_pathv = glob_malloc_incr (pglob->gl_offs, 1,
+ sizeof (char *));
if (pglob->gl_pathv == NULL)
goto err_nospace;
@@ -816,10 +846,11 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
: (__lstat64 (char_array_str (&dirname), &st64) == 0
&& S_ISDIR (st64.st_mode)))))
{
- size_t newcount = pglob->gl_pathc + pglob->gl_offs;
char **new_gl_pathv;
+ size_t newcount;
- if (newcount > SIZE_MAX / sizeof (char *) - 2)
+ if (check_add_overflow_size_t (pglob->gl_pathc, pglob->gl_offs,
+ &newcount))
{
nospace:
free (pglob->gl_pathv);
@@ -828,8 +859,8 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
goto err_nospace;
}
- new_gl_pathv = realloc (pglob->gl_pathv,
- (newcount + 2) * sizeof (char *));
+ new_gl_pathv = glob_realloc_incr (pglob->gl_pathv, newcount, 2,
+ sizeof (char *));
if (new_gl_pathv == NULL)
goto nospace;
pglob->gl_pathv = new_gl_pathv;
@@ -837,9 +868,12 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
if (flags & GLOB_MARK)
{
char *p;
- pglob->gl_pathv[newcount] = malloc (dirlen + 2);
+
+ pglob->gl_pathv[newcount] = glob_malloc_incr (dirlen, 2,
+ sizeof (char));
if (pglob->gl_pathv[newcount] == NULL)
goto nospace;
+
p = mempcpy (pglob->gl_pathv[newcount],
char_array_str (&dirname), dirlen);
p[0] = '/';
@@ -976,18 +1010,19 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
/* No matches. */
if (flags & GLOB_NOCHECK)
{
- size_t newcount = pglob->gl_pathc + pglob->gl_offs;
+ size_t newcount;
char **new_gl_pathv;
- if (newcount > SIZE_MAX / sizeof (char *) - 2)
+ if (check_add_overflow_size_t (pglob->gl_pathc, pglob->gl_offs,
+ &newcount))
{
nospace2:
globfree (&dirs);
goto err_nospace;
}
- new_gl_pathv = realloc (pglob->gl_pathv,
- (newcount + 2) * sizeof (char *));
+ new_gl_pathv = glob_realloc_incr (pglob->gl_pathv, newcount, 2,
+ sizeof (char *));
if (new_gl_pathv == NULL)
goto nospace2;
pglob->gl_pathv = new_gl_pathv;
@@ -1089,15 +1124,16 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
: (__lstat64 (pglob->gl_pathv[i], &st64) == 0
&& (S_ISDIR (st64.st_mode) || S_ISLNK (st64.st_mode)))))
{
- size_t len = strlen (pglob->gl_pathv[i]) + 2;
- char *new = realloc (pglob->gl_pathv[i], len);
+ size_t len = strlen (pglob->gl_pathv[i]);
+ char *new = glob_realloc_incr (pglob->gl_pathv[i], len, 2,
+ sizeof (char));
if (new == NULL)
{
globfree (pglob);
pglob->gl_pathc = 0;
goto err_nospace;
}
- strcpy (&new[len - 2], "/");
+ strcpy (&new[len], "/");
pglob->gl_pathv[i] = new;
}
}
@@ -1182,7 +1218,7 @@ prefix_array (const char *dirname, char **array, size_t n)
for (i = 0; i < n; ++i)
{
size_t eltlen = strlen (array[i]) + 1;
- char *new = malloc (dirlen + 1 + eltlen);
+ char *new = glob_malloc_incr2 (dirlen, 1, eltlen, sizeof (char));
if (new == NULL)
{
while (i > 0)
@@ -1190,11 +1226,10 @@ prefix_array (const char *dirname, char **array, size_t n)
return 1;
}
- {
- char *endp = mempcpy (new, dirname, dirlen);
- *endp++ = DIRSEP_CHAR;
- mempcpy (endp, array[i], eltlen);
- }
+ char *endp = mempcpy (new, dirname, dirlen);
+ *endp++ = DIRSEP_CHAR;
+ mempcpy (endp, array[i], eltlen);
+
free (array[i]);
array[i] = new;
}
@@ -1345,16 +1380,15 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
if (nfound != 0)
{
char **new_gl_pathv;
+ size_t newlen;
result = 0;
- if (SIZE_MAX / sizeof (char *) - pglob->gl_pathc
- < pglob->gl_offs + nfound + 1)
+ if (check_add_overflow_size_t (pglob->gl_pathc, pglob->gl_offs, &newlen)
+ || check_add_overflow_size_t (newlen, nfound, &newlen)
+ || check_add_overflow_size_t (newlen, 1, &newlen))
goto memory_error;
- new_gl_pathv
- = realloc (pglob->gl_pathv,
- (pglob->gl_pathc + pglob->gl_offs + nfound + 1)
- * sizeof (char *));
+ new_gl_pathv = realloc (pglob->gl_pathv, newlen * sizeof (char *));
if (new_gl_pathv == NULL)
{
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=89e7c2b0d336e51968484d187aa67b250bfbc7a2
commit 89e7c2b0d336e51968484d187aa67b250bfbc7a2
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Tue Jun 6 11:38:29 2017 -0300
posix: Add common function to get home directory
This patch adds a common function to get the full home directory
from a user. No functional changes expected.
Checked on x86_64-linux-gnu.
* posix/glob.c (get_home_directory): New function.
(glob): Use get_home_directory.
diff --git a/posix/glob.c b/posix/glob.c
index e84989c..5dc1fd5 100644
--- a/posix/glob.c
+++ b/posix/glob.c
@@ -264,6 +264,44 @@ next_brace_sub (const char *cp, int flags)
return *cp != '\0' ? cp : NULL;
}
+/* Obtain the full home directory path from user 'user_name' and writes it
+ on char_array 'home_dir'. */
+static bool
+get_home_directory (const char *user_name, struct char_array *home_dir)
+{
+ struct passwd *p;
+#if defined HAVE_GETPWNAM_R || defined _LIBC
+ struct passwd pwbuf;
+ int save = errno;
+ struct scratch_buffer pwtmpbuf;
+ scratch_buffer_init (&pwtmpbuf);
+
+ while (getpwnam_r (user_name, &pwbuf, pwtmpbuf.data, pwtmpbuf.length, &p)
+ != 0)
+ {
+ if (errno != ERANGE)
+ {
+ p = NULL;
+ break;
+ }
+ if (!scratch_buffer_grow (&pwtmpbuf))
+ return false;
+ __set_errno (save);
+ }
+#else
+ p = getpwnam (pwtmpbuf.data);
+#endif
+
+ bool retval = false;
+ if (p != NULL)
+ {
+ if (char_array_set_str (home_dir, p->pw_dir))
+ retval = true;
+ }
+ scratch_buffer_free (&pwtmpbuf);
+ return retval;
+}
+
/* Do glob searching for PATTERN, placing results in PGLOB.
The bits defined above may be set in FLAGS.
@@ -649,38 +687,8 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
success = __getlogin_r (user_name, sizeof (user_name)) == 0;
if (success)
{
- struct passwd *p;
-# if defined HAVE_GETPWNAM_R || defined _LIBC
- struct passwd pwbuf;
- int save = errno;
- struct scratch_buffer pwtmpbuf;
- scratch_buffer_init (&pwtmpbuf);
-
- while (getpwnam_r (user_name, &pwbuf,
- pwtmpbuf.data, pwtmpbuf.length, &p)
- != 0)
- {
- if (errno != ERANGE)
- {
- p = NULL;
- break;
- }
- if (!scratch_buffer_grow (&pwtmpbuf))
- goto err_nospace;
- __set_errno (save);
- }
-# else
- p = getpwnam (pwtmpbuf.data);
-# endif
- if (p != NULL)
- {
- if (!char_array_set_str (&home_dir, p->pw_dir))
- {
- scratch_buffer_free (&pwtmpbuf);
- goto err_nospace;
- }
- }
- scratch_buffer_free (&pwtmpbuf);
+ if (!get_home_directory (user_name, &home_dir))
+ goto err_nospace;
}
}
if (char_array_is_empty (&home_dir))
@@ -693,10 +701,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
else
{
if (!char_array_set_str (&home_dir, "~"))
- {
- retval = GLOB_NOSPACE;
- goto out;
- }
+ goto err_nospace;
}
}
# endif /* WINDOWS32 */
@@ -777,59 +782,21 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
}
/* Look up specific user's home directory. */
- {
- struct passwd *p;
- struct scratch_buffer pwtmpbuf;
- scratch_buffer_init (&pwtmpbuf);
-
-# if defined HAVE_GETPWNAM_R || defined _LIBC
- struct passwd pwbuf;
- int save = errno;
-
- while (getpwnam_r (user_name, &pwbuf,
- pwtmpbuf.data, pwtmpbuf.length, &p) != 0)
- {
- if (errno != ERANGE)
- {
- p = NULL;
- break;
- }
- if (!scratch_buffer_grow (&pwtmpbuf))
- {
- retval = GLOB_NOSPACE;
- goto out;
- }
- __set_errno (save);
- }
-# else
- p = getpwnam (user_name);
-# endif
-
- /* If we found a home directory use this. */
- if (p != NULL)
- {
- if (!char_array_set_str (&dirname, p->pw_dir))
- {
- scratch_buffer_free (&pwtmpbuf);
- retval = GLOB_NOSPACE;
- goto out;
- }
-
- dirlen = strlen (p->pw_dir);
- dirname_modified = true;
- }
- else
- {
- if (flags & GLOB_TILDE_CHECK)
- /* We have to regard it as an error if we cannot find the
- home directory. */
- {
- retval = GLOB_NOMATCH;
- goto out;
- }
- }
- scratch_buffer_free (&pwtmpbuf);
- }
+ if (get_home_directory (user_name, &dirname))
+ {
+ dirlen = char_array_size (&dirname) - 1;
+ dirname_modified = true;
+ }
+ else
+ {
+ if (flags & GLOB_TILDE_CHECK)
+ /* We have to regard it as an error if we cannot find the
+ home directory. */
+ {
+ retval = GLOB_NOMATCH;
+ goto out;
+ }
+ }
}
# endif /* Not Amiga && not WINDOWS32. */
}
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=5f9db2076c77c55d6b81cf38ea2621e7f71f59c1
commit 5f9db2076c77c55d6b81cf38ea2621e7f71f59c1
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Tue Jun 6 10:57:33 2017 -0300
posix: Use char_array for home_dir in glob
This patch uses char_array for home directory discovery. It simplifies
the buffer management.
Checked on x86_64-linux-gnu.
* posix/glob.c (glob): Use char_array for home directory.
diff --git a/posix/glob.c b/posix/glob.c
index eaf3a20..e84989c 100644
--- a/posix/glob.c
+++ b/posix/glob.c
@@ -606,8 +606,15 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
|| char_array_pos (&dirname, 2) == '/')))
{
/* Look up home directory. */
- char *home_dir = getenv ("HOME");
- int malloc_home_dir = 0;
+ struct char_array home_dir;
+
+ const char *home_env = getenv ("HOME");
+ home_env = home_env == NULL ? "" : home_env;
+ if (!char_array_init_str (&home_dir, home_env))
+ {
+ retval = GLOB_NOSPACE;
+ goto out;
+ }
# ifdef _AMIGA
if (home_dir == NULL || home_dir[0] == '\0')
home_dir = "SYS:";
@@ -634,7 +641,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
home_dir = "c:/users/default"; /* poor default */
}
# else
- if (home_dir == NULL || home_dir[0] == '\0')
+ if (char_array_is_empty (&home_dir))
{
int success;
char user_name[LOGIN_NAME_MAX];
@@ -667,9 +674,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
# endif
if (p != NULL)
{
- home_dir = strdup (p->pw_dir);
- malloc_home_dir = 1;
- if (home_dir == NULL)
+ if (!char_array_set_str (&home_dir, p->pw_dir))
{
scratch_buffer_free (&pwtmpbuf);
goto err_nospace;
@@ -678,10 +683,8 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
scratch_buffer_free (&pwtmpbuf);
}
}
- if (home_dir == NULL || home_dir[0] == '\0')
+ if (char_array_is_empty (&home_dir))
{
- if (__glibc_unlikely (malloc_home_dir))
- free (home_dir);
if (flags & GLOB_TILDE_CHECK)
{
retval = GLOB_NOMATCH;
@@ -689,8 +692,11 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
}
else
{
- home_dir = (char *) "~"; /* No luck. */
- malloc_home_dir = 0;
+ if (!char_array_set_str (&home_dir, "~"))
+ {
+ retval = GLOB_NOSPACE;
+ goto out;
+ }
}
}
# endif /* WINDOWS32 */
@@ -698,7 +704,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
/* Now construct the full directory. */
if (char_array_pos (&dirname, 1) == '\0')
{
- if (!char_array_set_str (&dirname, home_dir))
+ if (!char_array_set_str (&dirname, char_array_str (&home_dir)))
goto err_nospace;
dirlen = char_array_size (&dirname) - 1;
}
@@ -706,9 +712,11 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
{
/* Replaces '~' by the obtained HOME dir. */
char_array_erase (&dirname, 0);
- if (!char_array_prepend_str (&dirname, home_dir))
+ if (!char_array_prepend_str (&dirname,
+ char_array_str (&home_dir)))
goto err_nospace;
}
+ char_array_free (&home_dir);
dirname_modified = true;
}
# if !defined _AMIGA && !defined WINDOWS32
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=44684cd21876bde13fc3bed741f887ebff173d69
commit 44684cd21876bde13fc3bed741f887ebff173d69
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Mon Jun 5 19:55:48 2017 -0300
posix: Remove all alloca usage in glob
With alloca usage removal from glob this patch wraps it up by removing
all the alloca defines and macros usage.
Checked on x86_64-linux-gnu.
posix/glob.c (glob_in_dir): Remove alloca_used argument.
(glob): Remove alloca_used.
diff --git a/posix/glob.c b/posix/glob.c
index e89864d..eaf3a20 100644
--- a/posix/glob.c
+++ b/posix/glob.c
@@ -58,7 +58,6 @@
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
-#include <alloca.h>
#ifdef _LIBC
# undef strdup
@@ -229,17 +228,11 @@ convert_dirent64 (const struct dirent64 *source)
# ifdef GNULIB_defined_closedir
# undef closedir
# endif
-
-/* Just use malloc. */
-# define __libc_use_alloca(n) false
-# define alloca_account(len, avar) ((void) (len), (void) (avar), (void *) 0)
-# define extend_alloca_account(buf, len, newlen, avar) \
- ((void) (buf), (void) (len), (void) (newlen), (void) (avar), (void *) 0)
#endif
static int glob_in_dir (const char *pattern, const char *directory,
int flags, int (*errfunc) (const char *, int),
- glob_t *pglob, size_t alloca_used);
+ glob_t *pglob);
extern int __glob_pattern_type (const char *pattern, int quote)
attribute_hidden;
@@ -295,7 +288,6 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
bool dirname_modified;
glob_t dirs;
int retval = 0;
- size_t alloca_used = 0;
struct char_array dirname;
if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0)
@@ -972,7 +964,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
status = glob_in_dir (filename, dirs.gl_pathv[i],
((flags | GLOB_APPEND)
& ~(GLOB_NOCHECK | GLOB_NOMAGIC)),
- errfunc, pglob, alloca_used);
+ errfunc, pglob);
if (status == GLOB_NOMATCH)
/* No matches in this directory. Try the next. */
continue;
@@ -1079,7 +1071,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
if (dirname_modified)
flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC);
status = glob_in_dir (filename, char_array_str (&dirname), flags,
- errfunc, pglob, alloca_used);
+ errfunc, pglob);
if (status != 0)
{
if (status == GLOB_NOMATCH && flags != orig_flags
@@ -1256,8 +1248,7 @@ struct globnames_result
The GLOB_APPEND flag is assumed to be set (always appends). */
static int
glob_in_dir (const char *pattern, const char *directory, int flags,
- int (*errfunc) (const char *, int),
- glob_t *pglob, size_t alloca_used)
+ int (*errfunc) (const char *, int), glob_t *pglob)
{
void *stream = NULL;
struct globnames_array globnames;
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=3a5cee0bfadd7f3b6b1a273570c25daecba731c9
commit 3a5cee0bfadd7f3b6b1a273570c25daecba731c9
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Mon Jun 5 19:41:58 2017 -0300
posix: Use dynarray for globname in glob
This patch uses dynarray at glob internal glob_in_dir function to manage
the various matched patterns. It simplify and removes all the boilerplate
buffer managements required. It also removes the glob_use_alloca, since
it is not used anymore.
Checked on x86_64-linux-gnu.
* posix/glob.c (glob_use_alloca): Remove.
(glob_in_dir): Use dynarray for globnames.
diff --git a/posix/glob.c b/posix/glob.c
index 2b16bf1..e89864d 100644
--- a/posix/glob.c
+++ b/posix/glob.c
@@ -237,33 +237,6 @@ convert_dirent64 (const struct dirent64 *source)
((void) (buf), (void) (len), (void) (newlen), (void) (avar), (void *) 0)
#endif
-/* Set *R = A + B. Return true if the answer is mathematically
- incorrect due to overflow; in this case, *R is the low order
- bits of the correct answer.. */
-
-static bool size_add_wrapv (size_t a, size_t b, size_t *r);
-static bool glob_use_alloca (size_t alloca_used, size_t len);
-
-/* We must not compile this function twice. */
-static bool
-size_add_wrapv (size_t a, size_t b, size_t *r)
-{
-#if 5 <= __GNUC__
- return __builtin_add_overflow (a, b, r);
-#else
- *r = a + b;
- return *r < a;
-#endif
-}
-
-static bool
-glob_use_alloca (size_t alloca_used, size_t len)
-{
- size_t size;
- return (!size_add_wrapv (alloca_used, len, &size)
- && __libc_use_alloca (size));
-}
-
static int glob_in_dir (const char *pattern, const char *directory,
int flags, int (*errfunc) (const char *, int),
glob_t *pglob, size_t alloca_used);
@@ -1262,6 +1235,20 @@ prefix_array (const char *dirname, char **array, size_t n)
return 0;
}
+struct globnames_result
+{
+ char **names;
+ size_t length;
+};
+
+/* Create a dynamic array for C string representing the glob name found. */
+#define DYNARRAY_STRUCT globnames_array
+#define DYNARRAY_ELEMENT_FREE(ptr) free (*ptr)
+#define DYNARRAY_ELEMENT char *
+#define DYNARRAY_PREFIX globnames_array_
+#define DYNARRAY_FINAL_TYPE struct globnames_result
+#define DYNARRAY_INITIAL_SIZE 64
+#include <malloc/dynarray-skeleton.c>
/* Like `glob', but PATTERN is a final pathname component,
and matches are searched for in DIRECTORY.
@@ -1273,26 +1260,13 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
glob_t *pglob, size_t alloca_used)
{
void *stream = NULL;
- struct globnames
- {
- struct globnames *next;
- size_t count;
- char *name[64];
- };
-#define INITIAL_COUNT sizeof (init_names.name) / sizeof (init_names.name[0])
- struct globnames init_names;
- struct globnames *names = &init_names;
- struct globnames *names_alloca = &init_names;
+ struct globnames_array globnames;
size_t nfound = 0;
- size_t cur = 0;
int meta;
int save;
int result;
- alloca_used += sizeof (init_names);
-
- init_names.next = NULL;
- init_names.count = INITIAL_COUNT;
+ globnames_array_init (&globnames);
meta = __glob_pattern_type (pattern, !(flags & GLOB_NOESCAPE));
if (meta == 0 && (flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
@@ -1379,30 +1353,10 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
if (fnmatch (pattern, d.name, fnm_flags) == 0)
{
- if (cur == names->count)
- {
- struct globnames *newnames;
- size_t count = names->count * 2;
- size_t size = (sizeof (struct globnames)
- + ((count - INITIAL_COUNT)
- * sizeof (char *)));
- if (glob_use_alloca (alloca_used, size))
- newnames = names_alloca
- = alloca_account (size, alloca_used);
- else if ((newnames = malloc (size)) == NULL)
- goto memory_error;
- newnames->count = count;
- newnames->next = names;
- names = newnames;
- cur = 0;
- }
- names->name[cur] = strdup (d.name);
- if (names->name[cur] == NULL)
- goto memory_error;
- ++cur;
- ++nfound;
- if (SIZE_MAX - pglob->gl_offs <= nfound)
- goto memory_error;
+ globnames_array_add (&globnames, strdup (d.name));
+ if (globnames_array_has_failed (&globnames))
+ goto memory_error;
+ nfound++;
}
}
}
@@ -1412,10 +1366,13 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
{
size_t len = strlen (pattern);
nfound = 1;
- names->name[cur] = malloc (len + 1);
- if (names->name[cur] == NULL)
+ char *newp = malloc (len + 1);
+ if (newp == NULL)
+ goto memory_error;
+ *((char *) mempcpy (newp, pattern, len)) = '\0';
+ globnames_array_add (&globnames, newp);
+ if (globnames_array_has_failed (&globnames))
goto memory_error;
- *((char *) mempcpy (names->name[cur++], pattern, len)) = '\0';
}
result = GLOB_NOMATCH;
@@ -1436,61 +1393,25 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
if (new_gl_pathv == NULL)
{
memory_error:
- while (1)
- {
- struct globnames *old = names;
- size_t i;
- for (i = 0; i < cur; ++i)
- free (names->name[i]);
- names = names->next;
- /* NB: we will not leak memory here if we exit without
- freeing the current block assigned to OLD. At least
- the very first block is always allocated on the stack
- and this is the block assigned to OLD here. */
- if (names == NULL)
- {
- assert (old == &init_names);
- break;
- }
- cur = names->count;
- if (old == names_alloca)
- names_alloca = names;
- else
- free (old);
- }
+ globnames_array_free (&globnames);
result = GLOB_NOSPACE;
}
else
{
- while (1)
+ struct globnames_result ret = { .names = 0, .length = -1 };
+ if (!globnames_array_finalize (&globnames, &ret))
+ result = GLOB_NOSPACE;
+ else
{
- struct globnames *old = names;
- size_t i;
- for (i = 0; i < cur; ++i)
+ for (size_t i = 0; i < ret.length; ++i)
new_gl_pathv[pglob->gl_offs + pglob->gl_pathc++]
- = names->name[i];
- names = names->next;
- /* NB: we will not leak memory here if we exit without
- freeing the current block assigned to OLD. At least
- the very first block is always allocated on the stack
- and this is the block assigned to OLD here. */
- if (names == NULL)
- {
- assert (old == &init_names);
- break;
- }
- cur = names->count;
- if (old == names_alloca)
- names_alloca = names;
- else
- free (old);
- }
-
- pglob->gl_pathv = new_gl_pathv;
+ = ret.names[i];
- pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
-
- pglob->gl_flags = flags;
+ pglob->gl_pathv = new_gl_pathv;
+ pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
+ pglob->gl_flags = flags;
+ }
+ free (ret.names);
}
}
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=923c67dea223b7d2f02cbd8ccf7c588aaf439ba6
commit 923c67dea223b7d2f02cbd8ccf7c588aaf439ba6
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Mon Jun 5 17:20:01 2017 -0300
posix: Remove alloca usage on glob dirname
This patch replaces the alloca/malloc usage for dirname creation
by the char_array struct.
Checked on x86_64-linux-gnu.
* posix/glob.c (glob_in_dir): Remove alloca usage for fullname.
* malloc/char_array-skeleton.c (char_array_init_str): Remove unused
attribute.
(char_array_append_str): Likewise.
diff --git a/posix/glob.c b/posix/glob.c
index 6a73e7a..2b16bf1 100644
--- a/posix/glob.c
+++ b/posix/glob.c
@@ -1272,7 +1272,6 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
int (*errfunc) (const char *, int),
glob_t *pglob, size_t alloca_used)
{
- size_t dirlen = strlen (directory);
void *stream = NULL;
struct globnames
{
@@ -1312,33 +1311,24 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
struct stat st;
struct_stat64 st64;
} ust;
- size_t patlen = strlen (pattern);
- size_t fullsize;
- bool alloca_fullname
- = (! size_add_wrapv (dirlen + 1, patlen + 1, &fullsize)
- && glob_use_alloca (alloca_used, fullsize));
- char *fullname;
- if (alloca_fullname)
- fullname = alloca_account (fullsize, alloca_used);
- else
+ struct char_array fullname;
+
+ if (!char_array_init_str (&fullname, directory)
+ || !char_array_append_str (&fullname, "/")
+ || !char_array_append_str (&fullname, pattern))
{
- fullname = malloc (fullsize);
- if (fullname == NULL)
- return GLOB_NOSPACE;
+ char_array_free (&fullname);
+ return GLOB_NOSPACE;
}
- mempcpy (mempcpy (mempcpy (fullname, directory, dirlen),
- "/", 1),
- pattern, patlen + 1);
if ((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
- ? (*pglob->gl_lstat) (fullname, &ust.st)
- : __lstat64 (fullname, &ust.st64)) == 0)
+ ? (*pglob->gl_lstat) (char_array_str (&fullname), &ust.st)
+ : __lstat64 (char_array_str (&fullname), &ust.st64)) == 0)
/* We found this file to be existing. Now tell the rest
of the function to copy this name into the result. */
flags |= GLOB_NOCHECK;
- if (__glibc_unlikely (!alloca_fullname))
- free (fullname);
+ char_array_free (&fullname);
}
else
{
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=34f6a6e813fbb9d15895008157a4c3fe9f6a19d8
commit 34f6a6e813fbb9d15895008157a4c3fe9f6a19d8
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Mon Jun 5 15:19:22 2017 -0300
posix: Remove alloca usage for GLOB_BRACE on glob
GNU GLOB_BRACE internal implementation constructs a new expression and
calls glob recursively. It then requires a possible large temporary
buffer place the new pattern.
This patch removes the alloca/malloc usage and replaces it with
char_array.
Checked on x86_64-linux-gnu.
* posix/glob.c (glob): Remove alloca usage for onealt.
diff --git a/posix/glob.c b/posix/glob.c
index 3d6c6dd..6a73e7a 100644
--- a/posix/glob.c
+++ b/posix/glob.c
@@ -397,44 +397,32 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
/* Allocate working buffer large enough for our work. Note that
we have at least an opening and closing brace. */
size_t firstc;
- char *alt_start;
const char *p;
const char *next;
const char *rest;
size_t rest_len;
- char *onealt;
- size_t pattern_len = strlen (pattern) - 1;
- int alloca_onealt = glob_use_alloca (alloca_used, pattern_len);
- if (alloca_onealt)
- onealt = alloca_account (pattern_len, alloca_used);
- else
+ struct char_array onealt;
+
+ /* We know the prefix for all sub-patterns. */
+ ptrdiff_t onealtlen = begin - pattern;
+ if (!char_array_init_str_size (&onealt, pattern, onealtlen))
{
- onealt = malloc (pattern_len);
- if (onealt == NULL)
+ if (!(flags & GLOB_APPEND))
{
- if (!(flags & GLOB_APPEND))
- {
- pglob->gl_pathc = 0;
- pglob->gl_pathv = NULL;
- }
- goto err_nospace;
+ pglob->gl_pathc = 0;
+ pglob->gl_pathv = NULL;
}
+ goto err_nospace;
}
- /* We know the prefix for all sub-patterns. */
- alt_start = mempcpy (onealt, pattern, begin - pattern);
-
/* Find the first sub-pattern and at the same time find the
rest after the closing brace. */
next = next_brace_sub (begin + 1, flags);
if (next == NULL)
{
/* It is an invalid expression. */
- illegal_brace:
- if (__glibc_unlikely (!alloca_onealt))
- free (onealt);
- char_array_free (&dirname);
- return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
+ char_array_free (&onealt);
+ goto illegal_brace;
}
/* Now find the end of the whole brace expression. */
@@ -443,8 +431,11 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
{
rest = next_brace_sub (rest + 1, flags);
if (rest == NULL)
- /* It is an illegal expression. */
- goto illegal_brace;
+ {
+ /* It is an illegal expression. */
+ char_array_free (&onealt);
+ goto illegal_brace;
+ }
}
/* Please note that we now can be sure the brace expression
is well-formed. */
@@ -463,17 +454,24 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
int result;
/* Construct the new glob expression. */
- mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len);
+ ptrdiff_t nextlen = next - p;
+ if (!char_array_replace_str_pos (&onealt, onealtlen, p, nextlen)
+ || !char_array_replace_str_pos (&onealt, onealtlen + nextlen,
+ rest, rest_len))
+ {
+ char_array_free (&onealt);
+ retval = GLOB_NOSPACE;
+ goto out;
+ }
- result = glob (onealt,
+ result = glob (char_array_str (&onealt),
((flags & ~(GLOB_NOCHECK | GLOB_NOMAGIC))
| GLOB_APPEND), errfunc, pglob);
/* If we got an error, return it. */
if (result && result != GLOB_NOMATCH)
{
- if (__glibc_unlikely (!alloca_onealt))
- free (onealt);
+ char_array_free (&onealt);
if (!(flags & GLOB_APPEND))
{
globfree (pglob);
@@ -492,8 +490,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
assert (next != NULL);
}
- if (__glibc_unlikely (!alloca_onealt))
- free (onealt);
+ char_array_free (&onealt);
if (pglob->gl_pathc != firstc)
/* We found some entries. */
@@ -1180,6 +1177,10 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
err_nospace:
char_array_free (&dirname);
return GLOB_NOSPACE;
+
+ illegal_brace:
+ char_array_free (&dirname);
+ return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
}
#if defined _LIBC && !defined glob
libc_hidden_def (glob)
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=5389d55d0488f71d7dbcda40c24b78d33fd960ec
commit 5389d55d0488f71d7dbcda40c24b78d33fd960ec
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Mon Jun 5 12:31:21 2017 -0300
posix: User LOGIN_NAME_MAX for all user name in glob
This patch limits all user name obtained for GLOB_TILDE to max of
LOGIN_NAME_MAX (256 on glibc) and remove all stack/malloc buffer
handling boilerplate.
Checked on x86_64-linux-gnu.
* posix/glob.c (glob): Remove alloca usage on user_name for
GLOB_TILDE.
diff --git a/posix/glob.c b/posix/glob.c
index 46150a8..3d6c6dd 100644
--- a/posix/glob.c
+++ b/posix/glob.c
@@ -754,8 +754,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
{
char *dirnamestr = char_array_at (&dirname, 0);
char *end_name = strchr (dirnamestr, '/');
- char *user_name;
- int malloc_user_name = 0;
+ char user_name[LOGIN_NAME_MAX];
char *unescape = NULL;
if (!(flags & GLOB_NOESCAPE))
@@ -770,26 +769,14 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
unescape = memchr (dirnamestr, '\\', end_name - dirnamestr);
}
if (end_name == NULL)
- user_name = dirnamestr + 1;
+ strncpy (user_name, dirnamestr + 1, LOGIN_NAME_MAX - 1);
else
{
- char *newp;
- if (glob_use_alloca (alloca_used, end_name - dirnamestr))
- newp = alloca_account (end_name - dirnamestr, alloca_used);
- else
- {
- newp = malloc (end_name - dirnamestr);
- if (newp == NULL)
- {
- retval = GLOB_NOSPACE;
- goto out;
- }
- malloc_user_name = 1;
- }
if (unescape != NULL)
{
- char *p = mempcpy (newp, dirnamestr + 1,
- unescape - dirnamestr - 1);
+ ptrdiff_t name_len = unescape - dirnamestr - 1;
+ name_len = MIN (name_len, LOGIN_NAME_MAX - 1);
+ char *p = mempcpy (user_name, dirnamestr + 1, name_len);
char *q = unescape;
while (*q != '\0')
{
@@ -811,9 +798,12 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
*p = '\0';
}
else
- *((char *) mempcpy (newp, dirnamestr + 1, end_name - dirnamestr))
- = '\0';
- user_name = newp;
+ {
+ ptrdiff_t name_len = end_name - dirnamestr;
+ name_len = MIN (name_len, LOGIN_NAME_MAX - 1);
+ *((char *) mempcpy (user_name, dirnamestr + 1, name_len))
+ = '\0';
+ }
}
/* Look up specific user's home directory. */
@@ -845,9 +835,6 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
p = getpwnam (user_name);
# endif
- if (__glibc_unlikely (malloc_user_name))
- free (user_name);
-
/* If we found a home directory use this. */
if (p != NULL)
{
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=08530e743120416c3efd23e61920afc16e3dc5d7
commit 08530e743120416c3efd23e61920afc16e3dc5d7
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Mon Jun 5 12:12:38 2017 -0300
posix: Remove glob GET_LOGIN_NAME_MAX usage
Current glob implementation allows non limited user name for home
directory construction on GLOB_TILDE case. To accomplish it glob
either construct a name on stack if size are small enough (based
on current alloca_used) value in heap otherwise.
There is no actual login to resize the buffer in case of the resizing
the buffer in case of ERANGE, so a static buffer using glibc default
LOGIN_NAME_MAX is suffice.
Checked on x86_64-linux-gnu.
* posix/glob.c (LOGIN_NAME_MAX): Define if not defined.
(glob): Use static buffer for user_name on getlogin_r.
diff --git a/posix/glob.c b/posix/glob.c
index a7e568d..46150a8 100644
--- a/posix/glob.c
+++ b/posix/glob.c
@@ -92,10 +92,8 @@
#include "glob_internal.h"
#include <malloc/char_array-skeleton.c>
-#ifdef _SC_LOGIN_NAME_MAX
-# define GET_LOGIN_NAME_MAX() sysconf (_SC_LOGIN_NAME_MAX)
-#else
-# define GET_LOGIN_NAME_MAX() (-1)
+#ifndef LOGIN_NAME_MAX
+# define LOGIN_NAME_MAX 256
#endif
static const char *next_brace_sub (const char *begin, int flags) __THROWNL;
@@ -677,25 +675,9 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
if (home_dir == NULL || home_dir[0] == '\0')
{
int success;
- char *name;
- int malloc_name = 0;
- size_t buflen = GET_LOGIN_NAME_MAX () + 1;
-
- if (buflen == 0)
- /* `sysconf' does not support _SC_LOGIN_NAME_MAX. Try
- a moderate value. */
- buflen = 20;
- if (glob_use_alloca (alloca_used, buflen))
- name = alloca_account (buflen, alloca_used);
- else
- {
- name = malloc (buflen);
- if (name == NULL)
- goto err_nospace;
- malloc_name = 1;
- }
+ char user_name[LOGIN_NAME_MAX];
- success = __getlogin_r (name, buflen) == 0;
+ success = __getlogin_r (user_name, sizeof (user_name)) == 0;
if (success)
{
struct passwd *p;
@@ -705,7 +687,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
struct scratch_buffer pwtmpbuf;
scratch_buffer_init (&pwtmpbuf);
- while (getpwnam_r (name, &pwbuf,
+ while (getpwnam_r (user_name, &pwbuf,
pwtmpbuf.data, pwtmpbuf.length, &p)
!= 0)
{
@@ -733,11 +715,6 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
}
scratch_buffer_free (&pwtmpbuf);
}
- else
- {
- if (__glibc_unlikely (malloc_name))
- free (name);
- }
}
if (home_dir == NULL || home_dir[0] == '\0')
{
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=a192083bb599321a0d16ca31978d6be3f8f857ff
commit a192083bb599321a0d16ca31978d6be3f8f857ff
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Sun Jun 4 16:53:20 2017 -0300
posix: Use char_array for internal glob dirname
This is the first patch of the set to remove alloca usage on glob
implementation. Internal path to search for file might expand to a
non static directory derived from pattern for some difference cases
(GLOB_NOESCAPE, GNU GLOB_TILDE) and to allow a non-static dirname
path glob uses a lot of boilerplate code to manage the buffer (which
is either allocated using alloca or malloc depending both to size
requested and the total alloca_used).
The patch changes to use the char_array struct with the default size
(256 bytes). It simplifies all the allocation code by using char_array
one and every internal buffer access is done using char_array provided
functions. No functional changes are expected.
Checked on x86_64-linux-gnu.
* posix/globc.c (glob): Use char_array for dirname.
diff --git a/posix/glob.c b/posix/glob.c
index 425d81b..a7e568d 100644
--- a/posix/glob.c
+++ b/posix/glob.c
@@ -90,6 +90,7 @@
#include <scratch_buffer.h>
#include "glob_internal.h"
+#include <malloc/char_array-skeleton.c>
#ifdef _SC_LOGIN_NAME_MAX
# define GET_LOGIN_NAME_MAX() sysconf (_SC_LOGIN_NAME_MAX)
@@ -316,16 +317,15 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
glob_t *pglob)
{
const char *filename;
- char *dirname = NULL;
size_t dirlen;
int status;
size_t oldcount;
int meta;
- int dirname_modified;
- int malloc_dirname = 0;
+ bool dirname_modified;
glob_t dirs;
int retval = 0;
size_t alloca_used = 0;
+ struct char_array dirname;
if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0)
{
@@ -333,6 +333,9 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
return -1;
}
+ if (!char_array_init_empty (&dirname))
+ return GLOB_NOSPACE;
+
/* POSIX requires all slashes to be matched. This means that with
a trailing slash we must match only directories. */
if (pattern[0] && pattern[strlen (pattern) - 1] == '/')
@@ -353,12 +356,12 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
size_t i;
if (pglob->gl_offs >= ~((size_t) 0) / sizeof (char *))
- return GLOB_NOSPACE;
+ goto err_nospace;
pglob->gl_pathv = (char **) malloc ((pglob->gl_offs + 1)
* sizeof (char *));
if (pglob->gl_pathv == NULL)
- return GLOB_NOSPACE;
+ goto err_nospace;
for (i = 0; i <= pglob->gl_offs; ++i)
pglob->gl_pathv[i] = NULL;
@@ -416,7 +419,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
pglob->gl_pathc = 0;
pglob->gl_pathv = NULL;
}
- return GLOB_NOSPACE;
+ goto err_nospace;
}
}
@@ -432,6 +435,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
illegal_brace:
if (__glibc_unlikely (!alloca_onealt))
free (onealt);
+ char_array_free (&dirname);
return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
}
@@ -477,7 +481,8 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
globfree (pglob);
pglob->gl_pathc = 0;
}
- return result;
+ retval = result;
+ goto out;
}
if (*next == '}')
@@ -494,9 +499,10 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
if (pglob->gl_pathc != firstc)
/* We found some entries. */
- return 0;
+ retval = 0;
else if (!(flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
- return GLOB_NOMATCH;
+ retval = GLOB_NOMATCH;
+ goto out;
}
}
@@ -512,14 +518,15 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
if (filename == NULL)
filename = strchr (pattern, ':');
#endif /* __MSDOS__ || WINDOWS32 */
- dirname_modified = 0;
+ dirname_modified = false;
if (filename == NULL)
{
/* This can mean two things: a simple name or "~name". The latter
case is nothing but a notation for a directory. */
if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~')
{
- dirname = (char *) pattern;
+ if (!char_array_set_str (&dirname, pattern))
+ goto err_nospace;
dirlen = strlen (pattern);
/* Set FILENAME to NULL as a special flag. This is ugly but
@@ -537,10 +544,12 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
filename = pattern;
#ifdef _AMIGA
- dirname = (char *) "";
+# define CURRENT_FILENAME ""
#else
- dirname = (char *) ".";
+# define CURRENT_FILENAME "."
#endif
+ if (!char_array_set_str (&dirname, CURRENT_FILENAME))
+ goto err_nospace;
dirlen = 0;
}
}
@@ -549,13 +558,13 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
&& (flags & GLOB_NOESCAPE) == 0))
{
/* "/pattern" or "\\/pattern". */
- dirname = (char *) "/";
+ if (!char_array_set_str (&dirname, "/"))
+ goto err_nospace;
dirlen = 1;
++filename;
}
else
{
- char *newp;
dirlen = filename - pattern;
#if defined __MSDOS__ || defined WINDOWS32
if (*filename == ':'
@@ -569,50 +578,48 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
/* For now, disallow wildcards in the drive spec, to
prevent infinite recursion in glob. */
if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE)))
- return GLOB_NOMATCH;
+ {
+ retval = GLOB_NOMATCH;
+ goto out;
+ }
/* If this is "d:pattern", we need to copy ':' to DIRNAME
as well. If it's "d:/pattern", don't remove the slash
from "d:/", since "d:" and "d:/" are not the same.*/
}
#endif
- if (glob_use_alloca (alloca_used, dirlen + 1))
- newp = alloca_account (dirlen + 1, alloca_used);
- else
- {
- newp = malloc (dirlen + 1);
- if (newp == NULL)
- return GLOB_NOSPACE;
- malloc_dirname = 1;
- }
- *((char *) mempcpy (newp, pattern, dirlen)) = '\0';
- dirname = newp;
+ if (!char_array_set_str_size (&dirname, pattern, dirlen))
+ goto err_nospace;
++filename;
if (filename[0] == '\0'
#if defined __MSDOS__ || defined WINDOWS32
- && dirname[dirlen - 1] != ':'
- && (dirlen < 3 || dirname[dirlen - 2] != ':'
- || dirname[dirlen - 1] != '/')
+ && char_array_pos (&dirname, dirlen - 1) != ':'
+ && (dirlen < 3 || char_array_pos (&dirname, dirlen - 2) != ':'
+ || char_array_pos (&dirname, dirlen - 1) != '/')
#endif
&& dirlen > 1)
/* "pattern/". Expand "pattern", appending slashes. */
{
int orig_flags = flags;
int val;
- if (!(flags & GLOB_NOESCAPE) && dirname[dirlen - 1] == '\\')
+ if (!(flags & GLOB_NOESCAPE)
+ && char_array_pos (&dirname, dirlen - 1) == '\\')
{
/* "pattern\\/". Remove the final backslash if it hasn't
been quoted. */
- char *p = (char *) &dirname[dirlen - 1];
-
- while (p > dirname && p[-1] == '\\') --p;
- if ((&dirname[dirlen] - p) & 1)
+ size_t p = dirlen - 1;
+ while (p > 0 && char_array_pos (&dirname, p - 1) == '\\') --p;
+ if ((dirlen - p) & 1)
{
- *(char *) &dirname[--dirlen] = '\0';
+ /* Since we are shrinking the array, there is no need to
+ check the function return. */
+ dirlen -= 1;
+ char_array_crop (&dirname, dirlen);
flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC);
}
}
- val = glob (dirname, flags | GLOB_MARK, errfunc, pglob);
+ val = glob (char_array_str (&dirname), flags | GLOB_MARK, errfunc,
+ pglob);
if (val == 0)
pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK)
| (flags & GLOB_MARK));
@@ -629,11 +636,14 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
}
}
- if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~')
+ if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK))
+ && char_array_pos (&dirname, 0) == '~')
{
- if (dirname[1] == '\0' || dirname[1] == '/'
- || (!(flags & GLOB_NOESCAPE) && dirname[1] == '\\'
- && (dirname[2] == '\0' || dirname[2] == '/')))
+ if (char_array_pos (&dirname, 1) == '\0'
+ || char_array_pos (&dirname, 1) == '/'
+ || (!(flags & GLOB_NOESCAPE) && char_array_pos (&dirname, 1) == '\\'
+ && (char_array_pos (&dirname, 2) == '\0'
+ || char_array_pos (&dirname, 2) == '/')))
{
/* Look up home directory. */
char *home_dir = getenv ("HOME");
@@ -681,10 +691,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
{
name = malloc (buflen);
if (name == NULL)
- {
- retval = GLOB_NOSPACE;
- goto out;
- }
+ goto err_nospace;
malloc_name = 1;
}
@@ -708,10 +715,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
break;
}
if (!scratch_buffer_grow (&pwtmpbuf))
- {
- retval = GLOB_NOSPACE;
- goto out;
- }
+ goto err_nospace;
__set_errno (save);
}
# else
@@ -724,8 +728,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
if (home_dir == NULL)
{
scratch_buffer_free (&pwtmpbuf);
- retval = GLOB_NOSPACE;
- goto out;
+ goto err_nospace;
}
}
scratch_buffer_free (&pwtmpbuf);
@@ -754,53 +757,26 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
# endif /* WINDOWS32 */
# endif
/* Now construct the full directory. */
- if (dirname[1] == '\0')
+ if (char_array_pos (&dirname, 1) == '\0')
{
- if (__glibc_unlikely (malloc_dirname))
- free (dirname);
-
- dirname = home_dir;
- dirlen = strlen (dirname);
- malloc_dirname = malloc_home_dir;
+ if (!char_array_set_str (&dirname, home_dir))
+ goto err_nospace;
+ dirlen = char_array_size (&dirname) - 1;
}
else
{
- char *newp;
- size_t home_len = strlen (home_dir);
- int use_alloca = glob_use_alloca (alloca_used, home_len + dirlen);
- if (use_alloca)
- newp = alloca_account (home_len + dirlen, alloca_used);
- else
- {
- newp = malloc (home_len + dirlen);
- if (newp == NULL)
- {
- if (__glibc_unlikely (malloc_home_dir))
- free (home_dir);
- retval = GLOB_NOSPACE;
- goto out;
- }
- }
-
- mempcpy (mempcpy (newp, home_dir, home_len),
- &dirname[1], dirlen);
-
- if (__glibc_unlikely (malloc_dirname))
- free (dirname);
-
- dirname = newp;
- dirlen += home_len - 1;
- malloc_dirname = !use_alloca;
-
- if (__glibc_unlikely (malloc_home_dir))
- free (home_dir);
+ /* Replaces '~' by the obtained HOME dir. */
+ char_array_erase (&dirname, 0);
+ if (!char_array_prepend_str (&dirname, home_dir))
+ goto err_nospace;
}
- dirname_modified = 1;
+ dirname_modified = true;
}
# if !defined _AMIGA && !defined WINDOWS32
else
{
- char *end_name = strchr (dirname, '/');
+ char *dirnamestr = char_array_at (&dirname, 0);
+ char *end_name = strchr (dirnamestr, '/');
char *user_name;
int malloc_user_name = 0;
char *unescape = NULL;
@@ -809,23 +785,23 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
{
if (end_name == NULL)
{
- unescape = strchr (dirname, '\\');
+ unescape = strchr (dirnamestr, '\\');
if (unescape)
end_name = strchr (unescape, '\0');
}
else
- unescape = memchr (dirname, '\\', end_name - dirname);
+ unescape = memchr (dirnamestr, '\\', end_name - dirnamestr);
}
if (end_name == NULL)
- user_name = dirname + 1;
+ user_name = dirnamestr + 1;
else
{
char *newp;
- if (glob_use_alloca (alloca_used, end_name - dirname))
- newp = alloca_account (end_name - dirname, alloca_used);
+ if (glob_use_alloca (alloca_used, end_name - dirnamestr))
+ newp = alloca_account (end_name - dirnamestr, alloca_used);
else
{
- newp = malloc (end_name - dirname);
+ newp = malloc (end_name - dirnamestr);
if (newp == NULL)
{
retval = GLOB_NOSPACE;
@@ -835,8 +811,8 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
}
if (unescape != NULL)
{
- char *p = mempcpy (newp, dirname + 1,
- unescape - dirname - 1);
+ char *p = mempcpy (newp, dirnamestr + 1,
+ unescape - dirnamestr - 1);
char *q = unescape;
while (*q != '\0')
{
@@ -858,7 +834,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
*p = '\0';
}
else
- *((char *) mempcpy (newp, dirname + 1, end_name - dirname))
+ *((char *) mempcpy (newp, dirnamestr + 1, end_name - dirnamestr))
= '\0';
user_name = newp;
}
@@ -898,39 +874,25 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
/* If we found a home directory use this. */
if (p != NULL)
{
- size_t home_len = strlen (p->pw_dir);
- size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
-
- if (__glibc_unlikely (malloc_dirname))
- free (dirname);
- malloc_dirname = 0;
-
- if (glob_use_alloca (alloca_used, home_len + rest_len + 1))
- dirname = alloca_account (home_len + rest_len + 1,
- alloca_used);
- else
+ if (!char_array_set_str (&dirname, p->pw_dir))
{
- dirname = malloc (home_len + rest_len + 1);
- if (dirname == NULL)
- {
- scratch_buffer_free (&pwtmpbuf);
- retval = GLOB_NOSPACE;
- goto out;
- }
- malloc_dirname = 1;
+ scratch_buffer_free (&pwtmpbuf);
+ retval = GLOB_NOSPACE;
+ goto out;
}
- *((char *) mempcpy (mempcpy (dirname, p->pw_dir, home_len),
- end_name, rest_len)) = '\0';
- dirlen = home_len + rest_len;
- dirname_modified = 1;
+ dirlen = strlen (p->pw_dir);
+ dirname_modified = true;
}
else
{
if (flags & GLOB_TILDE_CHECK)
/* We have to regard it as an error if we cannot find the
home directory. */
- return GLOB_NOMATCH;
+ {
+ retval = GLOB_NOMATCH;
+ goto out;
+ }
}
scratch_buffer_free (&pwtmpbuf);
}
@@ -948,9 +910,10 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
/* Return the directory if we don't check for error or if it exists. */
if ((flags & GLOB_NOCHECK)
|| (((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0))
- ? ((*pglob->gl_lstat) (dirname, &st) == 0
+ ? ((*pglob->gl_lstat) (char_array_str (&dirname), &st) == 0
&& S_ISDIR (st.st_mode))
- : (__lstat64 (dirname, &st64) == 0 && S_ISDIR (st64.st_mode)))))
+ : (__lstat64 (char_array_str (&dirname), &st64) == 0
+ && S_ISDIR (st64.st_mode)))))
{
size_t newcount = pglob->gl_pathc + pglob->gl_offs;
char **new_gl_pathv;
@@ -958,12 +921,10 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
if (newcount > SIZE_MAX / sizeof (char *) - 2)
{
nospace:
- if (__glibc_unlikely (malloc_dirname))
- free (dirname);
free (pglob->gl_pathv);
pglob->gl_pathv = NULL;
pglob->gl_pathc = 0;
- return GLOB_NOSPACE;
+ goto err_nospace;
}
new_gl_pathv = realloc (pglob->gl_pathv,
@@ -978,33 +939,32 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
pglob->gl_pathv[newcount] = malloc (dirlen + 2);
if (pglob->gl_pathv[newcount] == NULL)
goto nospace;
- p = mempcpy (pglob->gl_pathv[newcount], dirname, dirlen);
+ p = mempcpy (pglob->gl_pathv[newcount],
+ char_array_str (&dirname), dirlen);
p[0] = '/';
p[1] = '\0';
}
else
{
- if (__glibc_unlikely (malloc_dirname))
- pglob->gl_pathv[newcount] = dirname;
- else
- {
- pglob->gl_pathv[newcount] = strdup (dirname);
- if (pglob->gl_pathv[newcount] == NULL)
- goto nospace;
- }
+ pglob->gl_pathv[newcount] = strdup (char_array_str (&dirname));
+ if (pglob->gl_pathv[newcount] == NULL)
+ goto nospace;
}
pglob->gl_pathv[++newcount] = NULL;
++pglob->gl_pathc;
pglob->gl_flags = flags;
- return 0;
+ retval = 0;
+ goto out;
}
/* Not found. */
- return GLOB_NOMATCH;
+ retval = GLOB_NOMATCH;
+ goto out;
}
- meta = __glob_pattern_type (dirname, !(flags & GLOB_NOESCAPE));
+ meta = __glob_pattern_type (char_array_str (&dirname),
+ !(flags & GLOB_NOESCAPE));
/* meta is 1 if correct glob pattern containing metacharacters.
If meta has bit (1 << 2) set, it means there was an unterminated
[ which we handle the same, using fnmatch. Broken unterminated
@@ -1017,15 +977,15 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
the pattern in each directory found. */
size_t i;
- if (!(flags & GLOB_NOESCAPE) && dirlen > 0 && dirname[dirlen - 1] == '\\')
+ if (!(flags & GLOB_NOESCAPE) && dirlen > 0
+ && char_array_pos (&dirname, dirlen - 1) == '\\')
{
/* "foo\\/bar". Remove the final backslash from dirname
if it has not been quoted. */
- char *p = (char *) &dirname[dirlen - 1];
-
- while (p > dirname && p[-1] == '\\') --p;
- if ((&dirname[dirlen] - p) & 1)
- *(char *) &dirname[--dirlen] = '\0';
+ size_t p = dirlen - 1;
+ while (p > 0 && char_array_pos (&dirname, p - 1) == '\\') --p;
+ if ((dirlen - p) & 1)
+ char_array_crop (&dirname, --dirlen);
}
if (__glibc_unlikely ((flags & GLOB_ALTDIRFUNC) != 0))
@@ -1039,7 +999,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
dirs.gl_lstat = pglob->gl_lstat;
}
- status = glob (dirname,
+ status = glob (char_array_str (&dirname),
((flags & (GLOB_ERR | GLOB_NOESCAPE
| GLOB_ALTDIRFUNC))
| GLOB_NOSORT | GLOB_ONLYDIR),
@@ -1047,7 +1007,10 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
if (status != 0)
{
if ((flags & GLOB_NOCHECK) == 0 || status != GLOB_NOMATCH)
- return status;
+ {
+ retval = status;
+ goto out;
+ }
goto no_matches;
}
@@ -1085,7 +1048,8 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
globfree (&dirs);
globfree (pglob);
pglob->gl_pathc = 0;
- return status;
+ retval = status;
+ goto out;
}
/* Stick the directory on the front of each name. */
@@ -1096,7 +1060,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
globfree (&dirs);
globfree (pglob);
pglob->gl_pathc = 0;
- return GLOB_NOSPACE;
+ goto err_nospace;
}
}
@@ -1118,7 +1082,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
{
nospace2:
globfree (&dirs);
- return GLOB_NOSPACE;
+ goto err_nospace;
}
new_gl_pathv = realloc (pglob->gl_pathv,
@@ -1133,7 +1097,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
globfree (&dirs);
globfree (pglob);
pglob->gl_pathc = 0;
- return GLOB_NOSPACE;
+ goto err_nospace;
}
++pglob->gl_pathc;
@@ -1145,7 +1109,8 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
else
{
globfree (&dirs);
- return GLOB_NOMATCH;
+ retval = GLOB_NOMATCH;
+ goto out;
}
}
@@ -1158,7 +1123,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
if (meta & 2)
{
- char *p = strchr (dirname, '\\'), *q;
+ char *p = strchr (char_array_str (&dirname), '\\'), *q;
/* We need to unescape the dirname string. It is certainly
allocated by alloca, as otherwise filename would be NULL
or dirname wouldn't contain backslashes. */
@@ -1175,12 +1140,12 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
++q;
}
while (*p++ != '\0');
- dirname_modified = 1;
+ dirname_modified = true;
}
if (dirname_modified)
flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC);
- status = glob_in_dir (filename, dirname, flags, errfunc, pglob,
- alloca_used);
+ status = glob_in_dir (filename, char_array_str (&dirname), flags,
+ errfunc, pglob, alloca_used);
if (status != 0)
{
if (status == GLOB_NOMATCH && flags != orig_flags
@@ -1191,19 +1156,20 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
flags = orig_flags;
goto no_matches;
}
- return status;
+ retval = status;
+ goto out;
}
if (dirlen > 0)
{
/* Stick the directory on the front of each name. */
- if (prefix_array (dirname,
+ if (prefix_array (char_array_str (&dirname),
&pglob->gl_pathv[old_pathc + pglob->gl_offs],
pglob->gl_pathc - old_pathc))
{
globfree (pglob);
pglob->gl_pathc = 0;
- return GLOB_NOSPACE;
+ goto err_nospace;
}
}
}
@@ -1228,7 +1194,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
{
globfree (pglob);
pglob->gl_pathc = 0;
- return GLOB_NOSPACE;
+ goto err_nospace;
}
strcpy (&new[len - 2], "/");
pglob->gl_pathv[i] = new;
@@ -1244,10 +1210,12 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
}
out:
- if (__glibc_unlikely (malloc_dirname))
- free (dirname);
-
+ char_array_free (&dirname);
return retval;
+
+ err_nospace:
+ char_array_free (&dirname);
+ return GLOB_NOSPACE;
}
#if defined _LIBC && !defined glob
libc_hidden_def (glob)
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=7f028010854a13cecdbea14954ea97a94428bad7
commit 7f028010854a13cecdbea14954ea97a94428bad7
Author: Florian Weimer <fweimer@redhat.com>
Date: Sat Jun 3 20:22:24 2017 -0300
posix: Rewrite to use struct scratch_buffer instead of extend_alloca
This patch removes a lot of boilerplate code to manager buffers for
getpwnam_r.
Checked on x86_64-linux-gnu.
[BZ #18023]
* posix/glob.c (glob): Use struct scratch_buffer instead of
extend_alloca.
diff --git a/posix/glob.c b/posix/glob.c
index dc13e26..425d81b 100644
--- a/posix/glob.c
+++ b/posix/glob.c
@@ -88,13 +88,9 @@
#include <fnmatch.h>
+#include <scratch_buffer.h>
#include "glob_internal.h"
-#ifdef _SC_GETPW_R_SIZE_MAX
-# define GETPW_R_SIZE_MAX() sysconf (_SC_GETPW_R_SIZE_MAX)
-#else
-# define GETPW_R_SIZE_MAX() (-1)
-#endif
#ifdef _SC_LOGIN_NAME_MAX
# define GET_LOGIN_NAME_MAX() sysconf (_SC_LOGIN_NAME_MAX)
#else
@@ -696,97 +692,43 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
if (success)
{
struct passwd *p;
- char *malloc_pwtmpbuf = NULL;
- char *pwtmpbuf;
# if defined HAVE_GETPWNAM_R || defined _LIBC
- long int pwbuflenmax = GETPW_R_SIZE_MAX ();
- size_t pwbuflen = pwbuflenmax;
struct passwd pwbuf;
int save = errno;
+ struct scratch_buffer pwtmpbuf;
+ scratch_buffer_init (&pwtmpbuf);
-# ifndef _LIBC
- if (! (0 < pwbuflenmax && pwbuflenmax <= SIZE_MAX))
- /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX.
- Try a moderate value. */
- pwbuflen = 1024;
-# endif
- if (glob_use_alloca (alloca_used, pwbuflen))
- pwtmpbuf = alloca_account (pwbuflen, alloca_used);
- else
- {
- pwtmpbuf = malloc (pwbuflen);
- if (pwtmpbuf == NULL)
- {
- if (__glibc_unlikely (malloc_name))
- free (name);
- retval = GLOB_NOSPACE;
- goto out;
- }
- malloc_pwtmpbuf = pwtmpbuf;
- }
-
- while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p)
+ while (getpwnam_r (name, &pwbuf,
+ pwtmpbuf.data, pwtmpbuf.length, &p)
!= 0)
{
- size_t newlen;
- bool v;
if (errno != ERANGE)
{
p = NULL;
break;
}
- v = size_add_wrapv (pwbuflen, pwbuflen, &newlen);
- if (!v && malloc_pwtmpbuf == NULL
- && glob_use_alloca (alloca_used, newlen))
- pwtmpbuf = extend_alloca_account (pwtmpbuf, pwbuflen,
- newlen, alloca_used);
- else
+ if (!scratch_buffer_grow (&pwtmpbuf))
{
- char *newp = (v ? NULL
- : realloc (malloc_pwtmpbuf, newlen));
- if (newp == NULL)
- {
- free (malloc_pwtmpbuf);
- if (__glibc_unlikely (malloc_name))
- free (name);
- retval = GLOB_NOSPACE;
- goto out;
- }
- malloc_pwtmpbuf = pwtmpbuf = newp;
+ retval = GLOB_NOSPACE;
+ goto out;
}
- pwbuflen = newlen;
__set_errno (save);
}
# else
- p = getpwnam (name);
+ p = getpwnam (pwtmpbuf.data);
# endif
- if (__glibc_unlikely (malloc_name))
- free (name);
if (p != NULL)
{
- if (malloc_pwtmpbuf == NULL)
- home_dir = p->pw_dir;
- else
+ home_dir = strdup (p->pw_dir);
+ malloc_home_dir = 1;
+ if (home_dir == NULL)
{
- size_t home_dir_len = strlen (p->pw_dir) + 1;
- if (glob_use_alloca (alloca_used, home_dir_len))
- home_dir = alloca_account (home_dir_len,
- alloca_used);
- else
- {
- home_dir = malloc (home_dir_len);
- if (home_dir == NULL)
- {
- free (pwtmpbuf);
- retval = GLOB_NOSPACE;
- goto out;
- }
- malloc_home_dir = 1;
- }
- memcpy (home_dir, p->pw_dir, home_dir_len);
+ scratch_buffer_free (&pwtmpbuf);
+ retval = GLOB_NOSPACE;
+ goto out;
}
}
- free (malloc_pwtmpbuf);
+ scratch_buffer_free (&pwtmpbuf);
}
else
{
@@ -924,59 +866,25 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
/* Look up specific user's home directory. */
{
struct passwd *p;
- char *malloc_pwtmpbuf = NULL;
+ struct scratch_buffer pwtmpbuf;
+ scratch_buffer_init (&pwtmpbuf);
+
# if defined HAVE_GETPWNAM_R || defined _LIBC
- long int buflenmax = GETPW_R_SIZE_MAX ();
- size_t buflen = buflenmax;
- char *pwtmpbuf;
struct passwd pwbuf;
int save = errno;
-# ifndef _LIBC
- if (! (0 <= buflenmax && buflenmax <= SIZE_MAX))
- /* Perhaps 'sysconf' does not support _SC_GETPW_R_SIZE_MAX. Try a
- moderate value. */
- buflen = 1024;
-# endif
- if (glob_use_alloca (alloca_used, buflen))
- pwtmpbuf = alloca_account (buflen, alloca_used);
- else
- {
- pwtmpbuf = malloc (buflen);
- if (pwtmpbuf == NULL)
- {
- nomem_getpw:
- if (__glibc_unlikely (malloc_user_name))
- free (user_name);
- retval = GLOB_NOSPACE;
- goto out;
- }
- malloc_pwtmpbuf = pwtmpbuf;
- }
-
- while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0)
+ while (getpwnam_r (user_name, &pwbuf,
+ pwtmpbuf.data, pwtmpbuf.length, &p) != 0)
{
- size_t newlen;
- bool v;
if (errno != ERANGE)
{
p = NULL;
break;
}
- v = size_add_wrapv (buflen, buflen, &newlen);
- if (!v && malloc_pwtmpbuf == NULL
- && glob_use_alloca (alloca_used, newlen))
- pwtmpbuf = extend_alloca_account (pwtmpbuf, buflen,
- newlen, alloca_used);
- else
+ if (!scratch_buffer_grow (&pwtmpbuf))
{
- char *newp = v ? NULL : realloc (malloc_pwtmpbuf, newlen);
- if (newp == NULL)
- {
- free (malloc_pwtmpbuf);
- goto nomem_getpw;
- }
- malloc_pwtmpbuf = pwtmpbuf = newp;
+ retval = GLOB_NOSPACE;
+ goto out;
}
__set_errno (save);
}
@@ -1005,7 +913,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
dirname = malloc (home_len + rest_len + 1);
if (dirname == NULL)
{
- free (malloc_pwtmpbuf);
+ scratch_buffer_free (&pwtmpbuf);
retval = GLOB_NOSPACE;
goto out;
}
@@ -1016,18 +924,15 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
dirlen = home_len + rest_len;
dirname_modified = 1;
-
- free (malloc_pwtmpbuf);
}
else
{
- free (malloc_pwtmpbuf);
-
if (flags & GLOB_TILDE_CHECK)
/* We have to regard it as an error if we cannot find the
home directory. */
return GLOB_NOMATCH;
}
+ scratch_buffer_free (&pwtmpbuf);
}
}
# endif /* Not Amiga && not WINDOWS32. */
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=782c40918fa3d3a161e4fe3014ea23c2bd170872
commit 782c40918fa3d3a161e4fe3014ea23c2bd170872
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Fri Jun 2 15:38:04 2017 -0300
posix: Consolidate glob implementation
This patch consolidates the glob implementation. The main changes are:
* Remove specific defines required for multiple compilation in same
unit (GLOB_ONLY_P, NO_GLOB_PATTERN_P and GLOB_COMPAT_BUILD). To allow
using the same code to build compat version on Linux, extra units are
used instead (oldglob.c).
* Both globfree and GNU extension glob_pattern_p are now on their files.
This simplifies the creation of compat symbol when required.
* Also similar to glob/glob64, a new globfree64 is file is added with an
empty implementatio as default.
* On Linux all implementation now uses a default one with the exception
of alpha (which requires a specific versioning) and s390-32 (which
different than other 32 bits with support for v2.1 symbol does not
add a compat symbol).
* Move i386 olddirent.h header to Linux default directory, since it is
the only header with this name and it is shared among different
architectures (and used on compat glob symbol).
Checked on x86_64-linux-gnu and i686-linux-gnu.
* posix/Makefile (routines): Add globfree, globfree64, and
glob_pattern_p.
* posix/glob.c: Remove GLOB_ONLY_P, GLOB_COMPAT_BUILD, and
NO_GLOB_PATTERN_P define usage.
(globfree): Move to its own file.
(__glob_pattern_type): Likewise.
(__glob_pattern_p): Likewise.
* posix/glob_internal.h: New file.
* posix/glob_pattern_p.c: Likewise.
* posix/globfree.c: Likewise.
* posix/globfree64.c: Likewise.
* sysdeps/gnu/glob64.c: Remove file.
* sysdeps/unix/sysv/linux/Makefile (sysdep_routines): Add oldglob.
* sysdeps/unix/sysv/linux/alpha/Makefile [$(subdir) = posix]
(sysdep_routines): Remove rule.
* sysdeps/unix/sysv/linux/alpha/glob.c: Remove file.
* sysdeps/unix/sysv/linux/arm/glob64.c: Likewise.
* sysdeps/wordsize-64/glob.c: Likewise.
* sysdeps/unix/sysv/linux/m68k/glob64.c: Likewise.
* sysdeps/unix/sysv/linux/mips/mips64/n64/glob64.c: Likewise.
* sysdeps/unix/sysv/linux/powerpc/powerpc32/glob64.c: Likewise.
* sysdeps/unix/sysv/linux/sparc/sparc32/glob64.c: Likewise.
* sysdeps/unix/sysv/linux/wordsize-64/glob64.c: Likewise.
* sysdeps/unix/sysv/linux/x86_64/x32/glob.c: Likewise.
* sysdeps/wordsize-64/glob64.c: Likewise.
* sysdeps/unix/sysv/linux/alpha/glob64.c: New file.
* sysdeps/unix/sysv/linux/alpha/globfree.c: Likewise.
* sysdeps/unix/sysv/linux/glob.c: Likewise.
* sysdeps/unix/sysv/linux/glob64.c: Likewise.
* sysdeps/unix/sysv/linux/globfree.c: Likewise.
* sysdeps/unix/sysv/linux/globfree64.c: Likewise.
* sysdeps/unix/sysv/linux/i386/alphasort64.c: include olddirent.h
using relative path instead of absolute one.
* sysdeps/unix/sysv/linux/i386/getdents64.c: Likewise.
* sysdeps/unix/sysv/linux/i386/readdir64.c: Likewise.
* sysdeps/unix/sysv/linux/i386/readdir64_r.c: Likewise.
* sysdeps/unix/sysv/linux/i386/versionsort64.c: Likewise.
* sysdeps/unix/sysv/linux/i386/olddirent.h: Move to ...
* sysdeps/unix/sysv/linux/olddirent.h: ... here.
* sysdeps/unix/sysv/linux/i386/glob64.c: Move to ...
* sysdeps/unix/sysv/linux/oldglob.c: ... here.
* sysdeps/unix/sysv/linux/i386/glob64.c: Remove file.
* sysdeps/unix/sysv/linux/oldglob.c: New file.
* sysdeps/unix/sysv/linux/s390/s390-32/glob64.c: New file.
* sysdeps/unix/sysv/linux/s390/s390-32/oldglob.c: Likewise.
diff --git a/posix/Makefile b/posix/Makefile
index 4862cbe..d091d13 100644
--- a/posix/Makefile
+++ b/posix/Makefile
@@ -45,7 +45,7 @@ routines := \
getpgid setpgid getpgrp bsd-getpgrp setpgrp getsid setsid \
getresuid getresgid setresuid setresgid \
pathconf sysconf fpathconf \
- glob glob64 fnmatch regex \
+ glob glob64 globfree globfree64 glob_pattern_p fnmatch regex \
confstr \
getopt getopt1 \
sched_setp sched_getp sched_sets sched_gets sched_yield sched_primax \
diff --git a/posix/glob.c b/posix/glob.c
index 250bff1..dc13e26 100644
--- a/posix/glob.c
+++ b/posix/glob.c
@@ -37,8 +37,6 @@
#include <stdio.h> /* Needed on stupid SunOS for assert. */
-#ifndef GLOB_ONLY_P
-
#include <unistd.h>
#if !defined POSIX && defined _POSIX_VERSION
# define POSIX
@@ -90,6 +88,8 @@
#include <fnmatch.h>
+#include "glob_internal.h"
+
#ifdef _SC_GETPW_R_SIZE_MAX
# define GETPW_R_SIZE_MAX() sysconf (_SC_GETPW_R_SIZE_MAX)
#else
@@ -168,8 +168,6 @@ readdir_result_might_be_dir (struct readdir_result d)
D_INO_TO_RESULT (source) \
}
-#endif /* !defined GLOB_ONLY_P */
-
/* Call gl_readdir on STREAM. This macro can be overridden to reduce
type safety if an old interface version needs to be supported. */
#ifndef GL_READDIR
@@ -252,7 +250,6 @@ static bool size_add_wrapv (size_t a, size_t b, size_t *r);
static bool glob_use_alloca (size_t alloca_used, size_t len);
/* We must not compile this function twice. */
-#ifndef GLOB_COMPAT_BUILD
static bool
size_add_wrapv (size_t a, size_t b, size_t *r)
{
@@ -271,7 +268,6 @@ glob_use_alloca (size_t alloca_used, size_t len)
return (!size_add_wrapv (alloca_used, len, &size)
&& __libc_use_alloca (size));
}
-#endif
static int glob_in_dir (const char *pattern, const char *directory,
int flags, int (*errfunc) (const char *, int),
@@ -279,7 +275,6 @@ static int glob_in_dir (const char *pattern, const char *directory,
extern int __glob_pattern_type (const char *pattern, int quote)
attribute_hidden;
-#ifndef GLOB_ONLY_P
static int prefix_array (const char *prefix, char **array, size_t n) __THROWNL;
static int collated_compare (const void *, const void *) __THROWNL;
@@ -308,7 +303,6 @@ next_brace_sub (const char *cp, int flags)
return *cp != '\0' ? cp : NULL;
}
-#endif /* !defined GLOB_ONLY_P */
/* Do glob searching for PATTERN, placing results in PGLOB.
The bits defined above may be set in FLAGS.
@@ -1355,26 +1349,6 @@ libc_hidden_def (glob)
#endif
-#ifndef GLOB_ONLY_P
-
-/* Free storage allocated in PGLOB by a previous `glob' call. */
-void
-globfree (glob_t *pglob)
-{
- if (pglob->gl_pathv != NULL)
- {
- size_t i;
- for (i = 0; i < pglob->gl_pathc; ++i)
- free (pglob->gl_pathv[pglob->gl_offs + i]);
- free (pglob->gl_pathv);
- pglob->gl_pathv = NULL;
- }
-}
-#if defined _LIBC && !defined globfree
-libc_hidden_def (globfree)
-#endif
-
-
/* Do a collated comparison of A and B. */
static int
collated_compare (const void *a, const void *b)
@@ -1451,58 +1425,6 @@ prefix_array (const char *dirname, char **array, size_t n)
}
-/* We must not compile this function twice. */
-#ifndef NO_GLOB_PATTERN_P
-int
-__glob_pattern_type (const char *pattern, int quote)
-{
- const char *p;
- int ret = 0;
-
- for (p = pattern; *p != '\0'; ++p)
- switch (*p)
- {
- case '?':
- case '*':
- return 1;
-
- case '\\':
- if (quote)
- {
- if (p[1] != '\0')
- ++p;
- ret |= 2;
- }
- break;
-
- case '[':
- ret |= 4;
- break;
-
- case ']':
- if (ret & 4)
- return 1;
- break;
- }
-
- return ret;
-}
-
-/* Return nonzero if PATTERN contains any metacharacters.
- Metacharacters can be quoted with backslashes if QUOTE is nonzero. */
-int
-__glob_pattern_p (const char *pattern, int quote)
-{
- return __glob_pattern_type (pattern, quote) == 1;
-}
-# ifdef _LIBC
-weak_alias (__glob_pattern_p, glob_pattern_p)
-# endif
-#endif
-
-#endif /* !defined GLOB_ONLY_P */
-
-
/* Like `glob', but PATTERN is a final pathname component,
and matches are searched for in DIRECTORY.
The GLOB_NOSORT bit in FLAGS is ignored. No sorting is ever done.
diff --git a/sysdeps/unix/sysv/linux/i386/getdents64.c b/posix/glob_internal.h
similarity index 55%
copy from sysdeps/unix/sysv/linux/i386/getdents64.c
copy to posix/glob_internal.h
index e8b257f..d989a98 100644
--- a/sysdeps/unix/sysv/linux/i386/getdents64.c
+++ b/posix/glob_internal.h
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2017 Free Software Foundation, Inc.
+/* Shared definition for glob and glob_pattern_p.
+ Copyright (C) 2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -15,25 +16,42 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#define __GETDENTS __getdents64
-#define DIRENT_TYPE struct dirent64
-
-#include <sysdeps/unix/sysv/linux/getdents.c>
-
-#include <shlib-compat.h>
-
-#undef __READDIR
-#undef __GETDENTS
-#undef DIRENT_TYPE
-
-#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
-
-#include <sysdeps/unix/sysv/linux/i386/olddirent.h>
-
-#define __GETDENTS __old_getdents64
-#define DIRENT_TYPE struct __old_dirent64
-#define kernel_dirent old_kernel_dirent
-#define kernel_dirent64 old_kernel_dirent64
-
-#include <sysdeps/unix/sysv/linux/getdents.c>
-#endif
+#ifndef GLOB_INTERNAL_H
+# define GLOB_INTERNAL_H
+
+static inline int
+__glob_pattern_type (const char *pattern, int quote)
+{
+ const char *p;
+ int ret = 0;
+
+ for (p = pattern; *p != '\0'; ++p)
+ switch (*p)
+ {
+ case '?':
+ case '*':
+ return 1;
+
+ case '\\':
+ if (quote)
+ {
+ if (p[1] != '\0')
+ ++p;
+ ret |= 2;
+ }
+ break;
+
+ case '[':
+ ret |= 4;
+ break;
+
+ case ']':
+ if (ret & 4)
+ return 1;
+ break;
+ }
+
+ return ret;
+}
+
+#endif /* GLOB_INTERNAL_H */
diff --git a/sysdeps/unix/sysv/linux/i386/getdents64.c b/posix/glob_pattern_p.c
similarity index 56%
copy from sysdeps/unix/sysv/linux/i386/getdents64.c
copy to posix/glob_pattern_p.c
index e8b257f..6e451f2 100644
--- a/sysdeps/unix/sysv/linux/i386/getdents64.c
+++ b/posix/glob_pattern_p.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2017 Free Software Foundation, Inc.
+/* Return nonzero if PATTERN contains any metacharacters.
+ Copyright (C) 2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -15,25 +16,14 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#define __GETDENTS __getdents64
-#define DIRENT_TYPE struct dirent64
-
-#include <sysdeps/unix/sysv/linux/getdents.c>
-
-#include <shlib-compat.h>
-
-#undef __READDIR
-#undef __GETDENTS
-#undef DIRENT_TYPE
-
-#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
-
-#include <sysdeps/unix/sysv/linux/i386/olddirent.h>
-
-#define __GETDENTS __old_getdents64
-#define DIRENT_TYPE struct __old_dirent64
-#define kernel_dirent old_kernel_dirent
-#define kernel_dirent64 old_kernel_dirent64
-
-#include <sysdeps/unix/sysv/linux/getdents.c>
-#endif
+#include <glob.h>
+#include "glob_internal.h"
+
+/* Return nonzero if PATTERN contains any metacharacters.
+ Metacharacters can be quoted with backslashes if QUOTE is nonzero. */
+int
+__glob_pattern_p (const char *pattern, int quote)
+{
+ return __glob_pattern_type (pattern, quote) == 1;
+}
+weak_alias (__glob_pattern_p, glob_pattern_p)
diff --git a/sysdeps/unix/sysv/linux/i386/getdents64.c b/posix/globfree.c
similarity index 56%
copy from sysdeps/unix/sysv/linux/i386/getdents64.c
copy to posix/globfree.c
index e8b257f..4ebd142 100644
--- a/sysdeps/unix/sysv/linux/i386/getdents64.c
+++ b/posix/globfree.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2017 Free Software Foundation, Inc.
+/* Frees the dynamically allocated storage from an earlier call to glob.
+ Copyright (C) 2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -15,25 +16,22 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#define __GETDENTS __getdents64
-#define DIRENT_TYPE struct dirent64
-
-#include <sysdeps/unix/sysv/linux/getdents.c>
-
-#include <shlib-compat.h>
-
-#undef __READDIR
-#undef __GETDENTS
-#undef DIRENT_TYPE
-
-#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
-
-#include <sysdeps/unix/sysv/linux/i386/olddirent.h>
-
-#define __GETDENTS __old_getdents64
-#define DIRENT_TYPE struct __old_dirent64
-#define kernel_dirent old_kernel_dirent
-#define kernel_dirent64 old_kernel_dirent64
-
-#include <sysdeps/unix/sysv/linux/getdents.c>
+#include <glob.h>
+#include <stdlib.h>
+
+/* Free storage allocated in PGLOB by a previous `glob' call. */
+void
+globfree (glob_t *pglob)
+{
+ if (pglob->gl_pathv != NULL)
+ {
+ size_t i;
+ for (i = 0; i < pglob->gl_pathc; ++i)
+ free (pglob->gl_pathv[pglob->gl_offs + i]);
+ free (pglob->gl_pathv);
+ pglob->gl_pathv = NULL;
+ }
+}
+#ifndef globfree
+libc_hidden_def (globfree)
#endif
diff --git a/sysdeps/unix/sysv/linux/i386/getdents64.c b/posix/globfree64.c
similarity index 56%
copy from sysdeps/unix/sysv/linux/i386/getdents64.c
copy to posix/globfree64.c
index e8b257f..cce288e 100644
--- a/sysdeps/unix/sysv/linux/i386/getdents64.c
+++ b/posix/globfree64.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2017 Free Software Foundation, Inc.
+/* Frees the dynamically allocated storage from an earlier call to glob.
+ Copyright (C) 2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -15,25 +16,12 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#define __GETDENTS __getdents64
-#define DIRENT_TYPE struct dirent64
+#include <glob.h>
+#include <stdlib.h>
-#include <sysdeps/unix/sysv/linux/getdents.c>
-
-#include <shlib-compat.h>
-
-#undef __READDIR
-#undef __GETDENTS
-#undef DIRENT_TYPE
-
-#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
-
-#include <sysdeps/unix/sysv/linux/i386/olddirent.h>
-
-#define __GETDENTS __old_getdents64
-#define DIRENT_TYPE struct __old_dirent64
-#define kernel_dirent old_kernel_dirent
-#define kernel_dirent64 old_kernel_dirent64
-
-#include <sysdeps/unix/sysv/linux/getdents.c>
-#endif
+/* Free storage allocated in PGLOB by a previous `glob' call. */
+void
+globfree64 (glob64_t *pglob)
+{
+}
+libc_hidden_def (globfree64)
diff --git a/sysdeps/gnu/glob64.c b/sysdeps/gnu/glob64.c
deleted file mode 100644
index 250ff07..0000000
--- a/sysdeps/gnu/glob64.c
+++ /dev/null
@@ -1,25 +0,0 @@
-#include <dirent.h>
-#include <glob.h>
-#include <sys/stat.h>
-
-#define dirent dirent64
-#define __readdir(dirp) __readdir64 (dirp)
-
-#define glob_t glob64_t
-#define glob(pattern, flags, errfunc, pglob) \
- glob64 (pattern, flags, errfunc, pglob)
-#define globfree(pglob) globfree64 (pglob)
-
-#undef stat
-#define stat stat64
-#undef __lstat
-#define __lstat(file, buf) __lxstat64 (_STAT_VER, file, buf)
-
-#define NO_GLOB_PATTERN_P 1
-
-#define COMPILE_GLOB64 1
-
-#include <posix/glob.c>
-
-libc_hidden_def (glob64)
-libc_hidden_def (globfree64)
diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
index 9d6a2de..8847751 100644
--- a/sysdeps/unix/sysv/linux/Makefile
+++ b/sysdeps/unix/sysv/linux/Makefile
@@ -162,7 +162,7 @@ endif
ifeq ($(subdir),posix)
sysdep_headers += bits/initspin.h
-sysdep_routines += sched_getcpu
+sysdep_routines += sched_getcpu oldglob
tests += tst-affinity tst-affinity-pid
diff --git a/sysdeps/unix/sysv/linux/alpha/Makefile b/sysdeps/unix/sysv/linux/alpha/Makefile
index 47bd189..50f4fb1 100644
--- a/sysdeps/unix/sysv/linux/alpha/Makefile
+++ b/sysdeps/unix/sysv/linux/alpha/Makefile
@@ -1,7 +1,3 @@
-ifeq ($(subdir),posix)
-sysdep_routines += oldglob
-endif
-
ifeq ($(subdir),stdlib)
gen-as-const-headers += ucontext-offsets.sym
endif
diff --git a/sysdeps/unix/sysv/linux/alpha/glob.c b/sysdeps/unix/sysv/linux/alpha/glob64.c
similarity index 78%
copy from sysdeps/unix/sysv/linux/alpha/glob.c
copy to sysdeps/unix/sysv/linux/alpha/glob64.c
index 2d7d287..dd86d15 100644
--- a/sysdeps/unix/sysv/linux/alpha/glob.c
+++ b/sysdeps/unix/sysv/linux/alpha/glob64.c
@@ -16,36 +16,25 @@
<http://www.gnu.org/licenses/>. */
#define glob64 __no_glob64_decl
-#define globfree64 __no_globfree64_decl
-#include <sys/types.h>
#include <glob.h>
#include <shlib-compat.h>
/* For Linux/Alpha we have to make the glob symbols versioned. */
#define glob(pattern, flags, errfunc, pglob) \
__new_glob (pattern, flags, errfunc, pglob)
-#define globfree(pglob) \
- __new_globfree (pglob)
/* We need prototypes for these new names. */
extern int __new_glob (const char *__pattern, int __flags,
int (*__errfunc) (const char *, int),
glob_t *__pglob);
-extern void __new_globfree (glob_t *__pglob);
#include <posix/glob.c>
#undef glob
-#undef globfree
#undef glob64
-#undef globfree64
versioned_symbol (libc, __new_glob, glob, GLIBC_2_1);
-versioned_symbol (libc, __new_globfree, globfree, GLIBC_2_1);
libc_hidden_ver (__new_glob, glob)
-libc_hidden_ver (__new_globfree, globfree)
weak_alias (__new_glob, glob64)
-weak_alias (__new_globfree, globfree64)
-libc_hidden_ver (__new_globfree, globfree64)
diff --git a/sysdeps/unix/sysv/linux/alpha/glob.c b/sysdeps/unix/sysv/linux/alpha/globfree.c
similarity index 58%
rename from sysdeps/unix/sysv/linux/alpha/glob.c
rename to sysdeps/unix/sysv/linux/alpha/globfree.c
index 2d7d287..9d159f1 100644
--- a/sysdeps/unix/sysv/linux/alpha/glob.c
+++ b/sysdeps/unix/sysv/linux/alpha/globfree.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 1998-2017 Free Software Foundation, Inc.
+/* Frees the dynamically allocated storage from an earlier call to glob.
+ Copyright (C) 2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -12,40 +13,24 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library. If not, see
+ License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#define glob64 __no_glob64_decl
#define globfree64 __no_globfree64_decl
-#include <sys/types.h>
#include <glob.h>
#include <shlib-compat.h>
-/* For Linux/Alpha we have to make the glob symbols versioned. */
-#define glob(pattern, flags, errfunc, pglob) \
- __new_glob (pattern, flags, errfunc, pglob)
-#define globfree(pglob) \
- __new_globfree (pglob)
-
-/* We need prototypes for these new names. */
-extern int __new_glob (const char *__pattern, int __flags,
- int (*__errfunc) (const char *, int),
- glob_t *__pglob);
+#define globfree(pglob) __new_globfree (pglob)
extern void __new_globfree (glob_t *__pglob);
-#include <posix/glob.c>
+#include <posix/globfree.c>
-#undef glob
#undef globfree
-#undef glob64
#undef globfree64
-versioned_symbol (libc, __new_glob, glob, GLIBC_2_1);
versioned_symbol (libc, __new_globfree, globfree, GLIBC_2_1);
-libc_hidden_ver (__new_glob, glob)
libc_hidden_ver (__new_globfree, globfree)
-weak_alias (__new_glob, glob64)
weak_alias (__new_globfree, globfree64)
libc_hidden_ver (__new_globfree, globfree64)
diff --git a/sysdeps/unix/sysv/linux/arm/glob64.c b/sysdeps/unix/sysv/linux/arm/glob64.c
deleted file mode 100644
index 82a9a29..0000000
--- a/sysdeps/unix/sysv/linux/arm/glob64.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/i386/glob64.c>
diff --git a/sysdeps/unix/sysv/linux/i386/getdents64.c b/sysdeps/unix/sysv/linux/glob.c
similarity index 56%
copy from sysdeps/unix/sysv/linux/i386/getdents64.c
copy to sysdeps/unix/sysv/linux/glob.c
index e8b257f..153ba8c 100644
--- a/sysdeps/unix/sysv/linux/i386/getdents64.c
+++ b/sysdeps/unix/sysv/linux/glob.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2017 Free Software Foundation, Inc.
+/* Find pathnames matching a pattern.
+ Copyright (C) 2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -15,25 +16,8 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#define __GETDENTS __getdents64
-#define DIRENT_TYPE struct dirent64
+#include <sys/types.h>
-#include <sysdeps/unix/sysv/linux/getdents.c>
-
-#include <shlib-compat.h>
-
-#undef __READDIR
-#undef __GETDENTS
-#undef DIRENT_TYPE
-
-#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
-
-#include <sysdeps/unix/sysv/linux/i386/olddirent.h>
-
-#define __GETDENTS __old_getdents64
-#define DIRENT_TYPE struct __old_dirent64
-#define kernel_dirent old_kernel_dirent
-#define kernel_dirent64 old_kernel_dirent64
-
-#include <sysdeps/unix/sysv/linux/getdents.c>
+#ifndef __OFF_T_MATCHES_OFF64_T
+# include <posix/glob.c>
#endif
diff --git a/sysdeps/unix/sysv/linux/glob64.c b/sysdeps/unix/sysv/linux/glob64.c
new file mode 100644
index 0000000..6ff6611
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/glob64.c
@@ -0,0 +1,55 @@
+/* Find pathnames matching a pattern.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sys/types.h>
+
+#ifdef __OFF_T_MATCHES_OFF64_T
+# define glob64 __no_glob64_decl
+# include <posix/glob.c>
+# undef glob64
+weak_alias (glob, glob64)
+#else
+# include <glob.h>
+# include <dirent.h>
+# include <sys/stat.h>
+
+# define dirent dirent64
+# define __readdir(dirp) __readdir64 (dirp)
+
+# define glob_t glob64_t
+# define glob(pattern, flags, errfunc, pglob) \
+ __glob64 (pattern, flags, errfunc, pglob)
+# define globfree(pglob) globfree64 (pglob)
+
+# undef stat
+# define stat stat64
+
+# define COMPILE_GLOB64 1
+
+# include <posix/glob.c>
+
+# include "shlib-compat.h"
+
+# ifdef GLOB_NO_OLD_VERSION
+strong_alias (__glob64, glob64)
+libc_hidden_def (glob64)
+# else
+versioned_symbol (libc, __glob64, glob64, GLIBC_2_2);
+libc_hidden_ver (__glob64, glob64)
+# endif
+#endif
diff --git a/sysdeps/unix/sysv/linux/i386/getdents64.c b/sysdeps/unix/sysv/linux/globfree.c
similarity index 56%
copy from sysdeps/unix/sysv/linux/i386/getdents64.c
copy to sysdeps/unix/sysv/linux/globfree.c
index e8b257f..d615510 100644
--- a/sysdeps/unix/sysv/linux/i386/getdents64.c
+++ b/sysdeps/unix/sysv/linux/globfree.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2017 Free Software Foundation, Inc.
+/* Frees the dynamically allocated storage from an earlier call to glob.
+ Copyright (C) 2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -15,25 +16,8 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#define __GETDENTS __getdents64
-#define DIRENT_TYPE struct dirent64
-
-#include <sysdeps/unix/sysv/linux/getdents.c>
-
-#include <shlib-compat.h>
-
-#undef __READDIR
-#undef __GETDENTS
-#undef DIRENT_TYPE
-
-#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
-
-#include <sysdeps/unix/sysv/linux/i386/olddirent.h>
-
-#define __GETDENTS __old_getdents64
-#define DIRENT_TYPE struct __old_dirent64
-#define kernel_dirent old_kernel_dirent
-#define kernel_dirent64 old_kernel_dirent64
-
-#include <sysdeps/unix/sysv/linux/getdents.c>
-#endif
+#define globfree64 __no_globfree64_decl
+#include <posix/globfree.c>
+#undef globfree64
+weak_alias (globfree, globfree64)
+libc_hidden_ver (globfree, globfree64)
diff --git a/sysdeps/unix/sysv/linux/globfree64.c b/sysdeps/unix/sysv/linux/globfree64.c
new file mode 100644
index 0000000..e69de29
diff --git a/sysdeps/unix/sysv/linux/i386/alphasort64.c b/sysdeps/unix/sysv/linux/i386/alphasort64.c
index d5fd47a..04b29b6 100644
--- a/sysdeps/unix/sysv/linux/i386/alphasort64.c
+++ b/sysdeps/unix/sysv/linux/i386/alphasort64.c
@@ -30,7 +30,7 @@ versioned_symbol (libc, __alphasort64, alphasort64, GLIBC_2_2);
#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
-#include <sysdeps/unix/sysv/linux/i386/olddirent.h>
+#include <olddirent.h>
int
__old_alphasort64 (const struct __old_dirent64 **a,
diff --git a/sysdeps/unix/sysv/linux/i386/getdents64.c b/sysdeps/unix/sysv/linux/i386/getdents64.c
index e8b257f..2010bbf 100644
--- a/sysdeps/unix/sysv/linux/i386/getdents64.c
+++ b/sysdeps/unix/sysv/linux/i386/getdents64.c
@@ -28,7 +28,7 @@
#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
-#include <sysdeps/unix/sysv/linux/i386/olddirent.h>
+#include <olddirent.h>
#define __GETDENTS __old_getdents64
#define DIRENT_TYPE struct __old_dirent64
diff --git a/sysdeps/unix/sysv/linux/i386/readdir64.c b/sysdeps/unix/sysv/linux/i386/readdir64.c
index f80b6a7..bd2375f 100644
--- a/sysdeps/unix/sysv/linux/i386/readdir64.c
+++ b/sysdeps/unix/sysv/linux/i386/readdir64.c
@@ -31,7 +31,7 @@ versioned_symbol (libc, __readdir64, readdir64, GLIBC_2_2);
#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
-#include <sysdeps/unix/sysv/linux/i386/olddirent.h>
+#include <olddirent.h>
#define __READDIR attribute_compat_text_section __old_readdir64
#define __GETDENTS __old_getdents64
diff --git a/sysdeps/unix/sysv/linux/i386/readdir64_r.c b/sysdeps/unix/sysv/linux/i386/readdir64_r.c
index 344fd53..8c0262d 100644
--- a/sysdeps/unix/sysv/linux/i386/readdir64_r.c
+++ b/sysdeps/unix/sysv/linux/i386/readdir64_r.c
@@ -31,7 +31,7 @@ versioned_symbol (libc, __readdir64_r, readdir64_r, GLIBC_2_2);
#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
-#include <sysdeps/unix/sysv/linux/i386/olddirent.h>
+#include <olddirent.h>
#define __READDIR_R attribute_compat_text_section __old_readdir64_r
#define __GETDENTS __old_getdents64
diff --git a/sysdeps/unix/sysv/linux/i386/versionsort64.c b/sysdeps/unix/sysv/linux/i386/versionsort64.c
index 3e1c6ea..87f2f95 100644
--- a/sysdeps/unix/sysv/linux/i386/versionsort64.c
+++ b/sysdeps/unix/sysv/linux/i386/versionsort64.c
@@ -30,7 +30,7 @@ versioned_symbol (libc, __versionsort64, versionsort64, GLIBC_2_2);
#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
-#include <sysdeps/unix/sysv/linux/i386/olddirent.h>
+#include <olddirent.h>
int
__old_versionsort64 (const struct __old_dirent64 **a,
diff --git a/sysdeps/unix/sysv/linux/m68k/glob64.c b/sysdeps/unix/sysv/linux/m68k/glob64.c
deleted file mode 100644
index 82a9a29..0000000
--- a/sysdeps/unix/sysv/linux/m68k/glob64.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/i386/glob64.c>
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/glob64.c b/sysdeps/unix/sysv/linux/mips/mips64/n64/glob64.c
deleted file mode 100644
index 33918ea..0000000
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/glob64.c
+++ /dev/null
@@ -1 +0,0 @@
-/* glob64 is in glob.c */
diff --git a/sysdeps/unix/sysv/linux/i386/olddirent.h b/sysdeps/unix/sysv/linux/olddirent.h
similarity index 100%
rename from sysdeps/unix/sysv/linux/i386/olddirent.h
rename to sysdeps/unix/sysv/linux/olddirent.h
diff --git a/sysdeps/unix/sysv/linux/i386/glob64.c b/sysdeps/unix/sysv/linux/oldglob.c
similarity index 61%
rename from sysdeps/unix/sysv/linux/i386/glob64.c
rename to sysdeps/unix/sysv/linux/oldglob.c
index 2dcbe33..af934f9 100644
--- a/sysdeps/unix/sysv/linux/i386/glob64.c
+++ b/sysdeps/unix/sysv/linux/oldglob.c
@@ -1,5 +1,5 @@
-/* Two glob variants with 64-bit support, for dirent64 and __olddirent64.
- Copyright (C) 1998-2017 Free Software Foundation, Inc.
+/* Find pathnames matching a pattern. Compatibility version.
+ Copyright (C) 2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -16,61 +16,32 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#include <dirent.h>
#include <glob.h>
-#include <sys/stat.h>
-
-#define dirent dirent64
-#define __readdir(dirp) __readdir64 (dirp)
-
-#define glob_t glob64_t
-#define glob(pattern, flags, errfunc, pglob) \
- __glob64 (pattern, flags, errfunc, pglob)
-#define globfree(pglob) globfree64 (pglob)
-
-#undef stat
-#define stat stat64
-#undef __lstat
-#define __lstat(file, buf) __lxstat64 (_STAT_VER, file, buf)
-
-#define NO_GLOB_PATTERN_P 1
-
-#define COMPILE_GLOB64 1
-
-#include <posix/glob.c>
-
#include "shlib-compat.h"
-libc_hidden_def (globfree64)
-
-versioned_symbol (libc, __glob64, glob64, GLIBC_2_2);
-libc_hidden_ver (__glob64, glob64)
-
-#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
+#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2) \
+ && !defined(GLOB_NO_OLD_VERSION)
-#include <sysdeps/unix/sysv/linux/i386/olddirent.h>
+#include <olddirent.h>
int __old_glob64 (const char *__pattern, int __flags,
int (*__errfunc) (const char *, int),
glob64_t *__pglob);
-#undef dirent
+#define glob_t glob64_t
+#define globfree(pglob) globfree64 (pglob)
+#undef stat
+#define stat stat64
+
#define dirent __old_dirent64
-#undef GL_READDIR
-# define GL_READDIR(pglob, stream) \
+#define GL_READDIR(pglob, stream) \
((struct __old_dirent64 *) (pglob)->gl_readdir (stream))
-#undef __readdir
#define __readdir(dirp) __old_readdir64 (dirp)
-#undef glob
#define glob(pattern, flags, errfunc, pglob) \
__old_glob64 (pattern, flags, errfunc, pglob)
#define convert_dirent __old_convert_dirent
-#define glob_in_dir __old_glob_in_dir
-#define GLOB_ATTRIBUTE attribute_compat_text_section
-#define GLOB_ONLY_P 1
-
-#define GLOB_COMPAT_BUILD 1
+#define GLOB_ATTRIBUTE attribute_compat_text_section
#include <posix/glob.c>
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/glob64.c b/sysdeps/unix/sysv/linux/powerpc/powerpc32/glob64.c
deleted file mode 100644
index 82a9a29..0000000
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/glob64.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/i386/glob64.c>
diff --git a/sysdeps/unix/sysv/linux/i386/getdents64.c b/sysdeps/unix/sysv/linux/s390/s390-32/glob64.c
similarity index 56%
copy from sysdeps/unix/sysv/linux/i386/getdents64.c
copy to sysdeps/unix/sysv/linux/s390/s390-32/glob64.c
index e8b257f..b00dc54 100644
--- a/sysdeps/unix/sysv/linux/i386/getdents64.c
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/glob64.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2017 Free Software Foundation, Inc.
+/* Find pathnames matching a pattern. S390-32 Linux version.
+ Copyright (C) 2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -15,25 +16,5 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#define __GETDENTS __getdents64
-#define DIRENT_TYPE struct dirent64
-
-#include <sysdeps/unix/sysv/linux/getdents.c>
-
-#include <shlib-compat.h>
-
-#undef __READDIR
-#undef __GETDENTS
-#undef DIRENT_TYPE
-
-#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
-
-#include <sysdeps/unix/sysv/linux/i386/olddirent.h>
-
-#define __GETDENTS __old_getdents64
-#define DIRENT_TYPE struct __old_dirent64
-#define kernel_dirent old_kernel_dirent
-#define kernel_dirent64 old_kernel_dirent64
-
-#include <sysdeps/unix/sysv/linux/getdents.c>
-#endif
+#define GLOB_NO_OLD_VERSION
+#include <sysdeps/unix/sysv/linux/glob64.c>
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/oldglob.c b/sysdeps/unix/sysv/linux/s390/s390-32/oldglob.c
new file mode 100644
index 0000000..56d7d12
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/oldglob.c
@@ -0,0 +1,2 @@
+#define GLOB_NO_OLD_VERSION
+#include <sysdeps/unix/sysv/linux/oldglob.c>
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/glob64.c b/sysdeps/unix/sysv/linux/sparc/sparc32/glob64.c
deleted file mode 100644
index 82a9a29..0000000
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/glob64.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/i386/glob64.c>
diff --git a/sysdeps/unix/sysv/linux/wordsize-64/glob64.c b/sysdeps/unix/sysv/linux/wordsize-64/glob64.c
deleted file mode 100644
index eab7703..0000000
--- a/sysdeps/unix/sysv/linux/wordsize-64/glob64.c
+++ /dev/null
@@ -1,2 +0,0 @@
-/* This file is here so sysdeps/gnu/glob64.c doesn't take precedence. */
-#include <sysdeps/wordsize-64/glob64.c>
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/glob.c b/sysdeps/unix/sysv/linux/x86_64/x32/glob.c
deleted file mode 100644
index e542747..0000000
--- a/sysdeps/unix/sysv/linux/x86_64/x32/glob.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/wordsize-64/glob.c>
diff --git a/sysdeps/wordsize-64/glob.c b/sysdeps/wordsize-64/glob.c
deleted file mode 100644
index 082faf1..0000000
--- a/sysdeps/wordsize-64/glob.c
+++ /dev/null
@@ -1,8 +0,0 @@
-#define glob64 __no_glob64_decl
-#define globfree64 __no_globfree64_decl
-#include <posix/glob.c>
-#undef glob64
-#undef globfree64
-weak_alias (glob, glob64)
-weak_alias (globfree, globfree64)
-libc_hidden_ver (globfree, globfree64)
diff --git a/sysdeps/wordsize-64/glob64.c b/sysdeps/wordsize-64/glob64.c
deleted file mode 100644
index 33918ea..0000000
--- a/sysdeps/wordsize-64/glob64.c
+++ /dev/null
@@ -1 +0,0 @@
-/* glob64 is in glob.c */
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=e0906fb5e1e3dd4ce487b8dc76e72035c21b9768
commit e0906fb5e1e3dd4ce487b8dc76e72035c21b9768
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Wed May 24 09:41:15 2017 -0300
posix: Adjust glob tests to libsupport
This patch adjust glob tests to use libsupport. It also refactor some
tests to move to a more meaningful file name and to gather similar tests
in a common file:
* move bug-glob3.c tests to tst-glob_basic.c.
* move bug-glob2.c tests to tst-glob_memory.c
* move common definitions to tst-glob_common.c.
Checked on x86_64-linux-gnu.
* posix/Makefile (tests): Remove bug-glob2 and bug-glob3. Add
tst-glob_basic and tst-glob_memory.
* posix/bug-glob3.c: Move to ...
* posix/tst-glob_basic.c: ... here.
* posix/bug-glob2.c: Move to ...
* posix/tst-glob_memory.c: ... here.
* posix/globtest.c: Use libsupport.
* posix/tst-gnuglob.c: Likewise.
* posix/tst-glob_common.c: New file.
diff --git a/posix/Makefile b/posix/Makefile
index 1424703..4862cbe 100644
--- a/posix/Makefile
+++ b/posix/Makefile
@@ -79,7 +79,7 @@ tests := test-errno tstgetopt testfnm runtests runptests \
tst-nice tst-nanosleep tst-regex2 \
transbug tst-rxspencer tst-pcre tst-boost \
bug-ga1 tst-vfork1 tst-vfork2 tst-vfork3 tst-waitid \
- tst-getaddrinfo2 bug-glob2 bug-glob3 tst-sysconf \
+ tst-getaddrinfo2 tst-glob_memory tst-glob_basic tst-sysconf \
tst-execvp1 tst-execvp2 tst-execlp1 tst-execlp2 \
tst-execv1 tst-execv2 tst-execl1 tst-execl2 \
tst-execve1 tst-execve2 tst-execle1 tst-execle2 \
@@ -122,7 +122,7 @@ generated += $(addprefix wordexp-test-result, 1 2 3 4 5 6 7 8 9 10) \
tst-getconf.out \
tst-pcre-mem.out tst-pcre.mtrace tst-boost-mem.out \
tst-boost.mtrace bug-ga2.mtrace bug-ga2-mem.out \
- bug-glob2.mtrace bug-glob2-mem.out tst-vfork3-mem.out \
+ tst-glob_memory.mtrace tst-glob_memory-mem.out tst-vfork3-mem.out \
tst-vfork3.mtrace getconf.speclist tst-fnmatch-mem.out \
tst-fnmatch.mtrace bug-regex36.mtrace
@@ -140,7 +140,7 @@ tests-special += $(objpfx)bug-regex2-mem.out $(objpfx)bug-regex14-mem.out \
$(objpfx)bug-regex21-mem.out $(objpfx)bug-regex31-mem.out \
$(objpfx)tst-rxspencer-no-utf8-mem.out $(objpfx)tst-pcre-mem.out \
$(objpfx)tst-boost-mem.out $(objpfx)tst-getconf.out \
- $(objpfx)bug-glob2-mem.out $(objpfx)tst-vfork3-mem.out \
+ $(objpfx)tst-glob_memory-mem.out $(objpfx)tst-vfork3-mem.out \
$(objpfx)tst-fnmatch-mem.out $(objpfx)bug-regex36-mem.out
xtests-special += $(objpfx)bug-ga2-mem.out
endif
@@ -343,10 +343,10 @@ $(objpfx)bug-ga2-mem.out: $(objpfx)bug-ga2.out
bug-ga2-ENV = MALLOC_TRACE=$(objpfx)bug-ga2.mtrace
-bug-glob2-ENV = MALLOC_TRACE=$(objpfx)bug-glob2.mtrace
+tst-glob_memory-ENV = MALLOC_TRACE=$(objpfx)tst-glob_memory.mtrace
-$(objpfx)bug-glob2-mem.out: $(objpfx)bug-glob2.out
- $(common-objpfx)malloc/mtrace $(objpfx)bug-glob2.mtrace > $@; \
+$(objpfx)tst-glob_memory-mem.out: $(objpfx)tst-glob_memory.out
+ $(common-objpfx)malloc/mtrace $(objpfx)tst-glob_memory.mtrace > $@; \
$(evaluate-test)
$(inst_libexecdir)/getconf: $(inst_bindir)/getconf \
diff --git a/posix/bug-glob3.c b/posix/bug-glob3.c
deleted file mode 100644
index f2fbd70..0000000
--- a/posix/bug-glob3.c
+++ /dev/null
@@ -1,45 +0,0 @@
-#include <glob.h>
-#include <stdio.h>
-#include <string.h>
-
-static int
-do_test (void)
-{
- int result = 0;
- glob_t g;
- g.gl_pathc = 0;
-
- int r = glob ("", 0, NULL, &g);
- if (r != GLOB_NOMATCH)
- {
- puts ("glob (\"\", 0, NULL, &g) did not fail");
- result = 1;
- }
- else if (g.gl_pathc != 0)
- {
- puts ("gl_pathc after glob (\"\", 0, NULL, &g) not zero");
- result = 1;
- }
-
- r = glob ("", GLOB_NOCHECK, NULL, &g);
- if (r != 0)
- {
- puts ("glob (\"\", GLOB_NOCHECK, NULL, &g) did fail");
- result = 1;
- }
- else if (g.gl_pathc != 1)
- {
- puts ("gl_pathc after glob (\"\", GLOB_NOCHECK, NULL, &g) not 1");
- result = 1;
- }
- else if (strcmp (g.gl_pathv[0], "") != 0)
- {
- puts ("gl_pathv[0] after glob (\"\", GLOB_NOCHECK, NULL, &g) not \"\"");
- result = 1;
- }
-
- return result;
-}
-
-#define TEST_FUNCTION do_test ()
-#include "../test-skeleton.c"
diff --git a/posix/globtest.c b/posix/globtest.c
index 7ffcb91..e5b5891 100644
--- a/posix/globtest.c
+++ b/posix/globtest.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 1997-2017 Free Software Foundation, Inc.
+/* Basic glob tests. It uses an extenal driver script (tst-glob.sh).
+ Copyright (C) 1997-2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -21,77 +22,97 @@
#include <unistd.h>
#include <glob.h>
-int
-main (int argc, char *argv[])
+#include <support/check.h>
+
+#define OPT_BRACE 'b'
+#define OPT_NOCHECK 'c'
+#define OPT_ONLYDIR 'd'
+#define OPT_NOESCAPE 'e'
+#define OPT_ERR 'E'
+#define OPT_NOMAGIC 'g'
+#define OPT_MARK 'm'
+#define OPT_DOOFFS 'o'
+#define OPT_PERIOD 'p'
+#define OPT_QUOTES 'q'
+#define OPT_NOSORT 's'
+#define OPT_TILDE 't'
+#define OPT_TILDE_CHECK 'T'
+
+#define CMDLINE_OPTSTRING "bcdeEgmopqstT"
+
+static int glob_flags = 0;
+static int quotes = 1;
+
+static void
+cmdline_process_function (int c)
{
- int i, j;
- int glob_flags = 0;
- glob_t g;
- int quotes = 1;
+ switch (c)
+ {
+ case OPT_BRACE:
+ glob_flags |= GLOB_BRACE;
+ break;
+ case OPT_NOCHECK:
+ glob_flags |= GLOB_NOCHECK;
+ break;
+ case OPT_ONLYDIR:
+ glob_flags |= GLOB_ONLYDIR;
+ break;
+ case OPT_NOESCAPE:
+ glob_flags |= GLOB_NOESCAPE;
+ break;
+ case OPT_ERR:
+ glob_flags |= GLOB_ERR;
+ break;
+ case OPT_NOMAGIC:
+ glob_flags |= GLOB_NOMAGIC;
+ break;
+ case OPT_MARK:
+ glob_flags |= GLOB_MARK;
+ break;
+ case OPT_DOOFFS:
+ glob_flags |= GLOB_DOOFFS;
+ break;
+ case OPT_PERIOD:
+ glob_flags |= GLOB_PERIOD;
+ break;
+ case OPT_QUOTES:
+ quotes = 0;
+ break;
+ case OPT_NOSORT:
+ glob_flags |= GLOB_NOSORT;
+ break;
+ case OPT_TILDE:
+ glob_flags |= GLOB_TILDE;
+ break;
+ case OPT_TILDE_CHECK:
+ glob_flags |= GLOB_TILDE_CHECK;
+ break;
+ }
+}
- g.gl_offs = 0;
+#define CMDLINE_PROCESS cmdline_process_function
- while ((i = getopt (argc, argv, "bcdeEgmopqstT")) != -1)
- switch(i)
- {
- case 'b':
- glob_flags |= GLOB_BRACE;
- break;
- case 'c':
- glob_flags |= GLOB_NOCHECK;
- break;
- case 'd':
- glob_flags |= GLOB_ONLYDIR;
- break;
- case 'e':
- glob_flags |= GLOB_NOESCAPE;
- break;
- case 'E':
- glob_flags |= GLOB_ERR;
- break;
- case 'g':
- glob_flags |= GLOB_NOMAGIC;
- break;
- case 'm':
- glob_flags |= GLOB_MARK;
- break;
- case 'o':
- glob_flags |= GLOB_DOOFFS;
- g.gl_offs = 1;
- break;
- case 'p':
- glob_flags |= GLOB_PERIOD;
- break;
- case 'q':
- quotes = 0;
- break;
- case 's':
- glob_flags |= GLOB_NOSORT;
- break;
- case 't':
- glob_flags |= GLOB_TILDE;
- break;
- case 'T':
- glob_flags |= GLOB_TILDE_CHECK;
- break;
- default:
- exit (-1);
- }
+static int
+do_test_argv (int argc, char *argv[])
+{
+ int i, j;
+ glob_t g;
- if (optind >= argc || chdir (argv[optind]))
- exit(1);
+ g.gl_offs = glob_flags & GLOB_DOOFFS ? 1 : 0;
- j = optind + 1;
- if (optind + 1 >= argc)
- exit (1);
+ if (argc < 2)
+ FAIL_EXIT1 ("invalid arguments (expecting path for glob)");
+ if (chdir (argv[1]) != 0)
+ FAIL_EXIT1 ("chmod (%s): %m", argv[1]);
- /* Do a glob on each remaining argument. */
- for (j = optind + 1; j < argc; j++) {
- i = glob (argv[j], glob_flags, NULL, &g);
- if (i != 0)
- break;
- glob_flags |= GLOB_APPEND;
- }
+ /* Do a glob on each argument. */
+ for (j = 2; j < argc; j++)
+ {
+ i = glob (argv[j], glob_flags, NULL, &g);
+ if (i != 0)
+ break;
+ glob_flags |= GLOB_APPEND;
+ }
/* Was there an error? */
if (i == GLOB_NOSPACE)
@@ -106,16 +127,18 @@ main (int argc, char *argv[])
if ((glob_flags & GLOB_DOOFFS) && g.gl_pathv[0] == NULL)
g.gl_pathv[0] = (char *) "abc";
- /* Print out the names. Unless otherwise specified, qoute them. */
+ /* Print out the names. Unless otherwise specified, quote them. */
if (g.gl_pathv)
{
for (i = 0; i < g.gl_offs + g.gl_pathc; ++i)
- printf ("%s%s%s\n", quotes ? "`" : "",
- g.gl_pathv[i] ? g.gl_pathv[i] : "(null)",
- quotes ? "'" : "");
+ printf ("%s%s%s\n", quotes ? "`" : "",
+ g.gl_pathv[i] ? g.gl_pathv[i] : "(null)", quotes ? "'" : "");
}
globfree (&g);
return 0;
}
+
+#define TEST_FUNCTION_ARGV do_test_argv
+#include <support/test-driver.c>
diff --git a/posix/tst-glob_basic.c b/posix/tst-glob_basic.c
new file mode 100644
index 0000000..64b95a8
--- /dev/null
+++ b/posix/tst-glob_basic.c
@@ -0,0 +1,41 @@
+/* Basic glob tests.
+ Copyright (C) 2001-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <glob.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <support/check.h>
+
+static int
+do_test (void)
+{
+ glob_t g;
+ g.gl_pathc = 0;
+
+ TEST_VERIFY_EXIT (glob ("", 0, NULL, &g) == GLOB_NOMATCH);
+ TEST_VERIFY_EXIT (g.gl_pathc == 0);
+
+ TEST_VERIFY_EXIT (glob ("", GLOB_NOCHECK, NULL, &g) == 0);
+ TEST_VERIFY_EXIT (g.gl_pathc == 1);
+ TEST_VERIFY_EXIT (strcmp (g.gl_pathv[0], "") == 0);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/posix/tst-glob_common.c b/posix/tst-glob_common.c
new file mode 100644
index 0000000..b7a66c7
--- /dev/null
+++ b/posix/tst-glob_common.c
@@ -0,0 +1,103 @@
+/* Common glob test definition.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+// #define DEBUG
+#ifdef DEBUG
+# define PRINTF(fmt, args...) \
+ do \
+ { \
+ int save_errno = errno; \
+ printf (fmt, ##args); \
+ errno = save_errno; \
+ } while (0)
+#else
+# define PRINTF(fmt, args...)
+#endif
+
+struct filesystem_t
+{
+ const char *name;
+ int level;
+ int type;
+ mode_t mode;
+};
+
+static long int
+find_file (const char *s, const struct filesystem_t *filesystem,
+ size_t nfiles)
+{
+ int level = 1;
+ long int idx = 0;
+
+ while (s[0] == '/')
+ {
+ if (s[1] == '\0')
+ {
+ s = ".";
+ break;
+ }
+ ++s;
+ }
+
+ if (strcmp (s, ".") == 0)
+ return 0;
+
+ if (s[0] == '.' && s[1] == '/')
+ s += 2;
+
+ while (*s != '\0')
+ {
+ char *endp = strchrnul (s, '/');
+
+ PRINTF ("looking for %.*s, level %d\n", (int) (endp - s), s, level);
+
+ while (idx < nfiles && filesystem[idx].level >= level)
+ {
+ if (filesystem[idx].level == level
+ && memcmp (s, filesystem[idx].name, endp - s) == 0
+ && filesystem[idx].name[endp - s] == '\0')
+ break;
+ ++idx;
+ }
+
+ if (idx == nfiles || filesystem[idx].level < level)
+ {
+ errno = ENOENT;
+ return -1;
+ }
+
+ if (*endp == '\0')
+ return idx + 1;
+
+ if (filesystem[idx].type != DT_DIR
+ && (idx + 1 >= nfiles
+ || filesystem[idx].level >= filesystem[idx + 1].level))
+ {
+ errno = ENOTDIR;
+ return -1;
+ }
+
+ ++idx;
+
+ s = endp + 1;
+ ++level;
+ }
+
+ errno = ENOENT;
+ return -1;
+}
diff --git a/posix/bug-glob2.c b/posix/tst-glob_memory.c
similarity index 76%
rename from posix/bug-glob2.c
rename to posix/tst-glob_memory.c
index 592d957..33961e8 100644
--- a/posix/bug-glob2.c
+++ b/posix/tst-glob_memory.c
@@ -27,18 +27,10 @@
#include <string.h>
#include <sys/stat.h>
-// #define DEBUG
-#ifdef DEBUG
-# define PRINTF(fmt, args...) \
- do \
- { \
- int save_errno = errno; \
- printf (fmt, ##args); \
- errno = save_errno; \
- } while (0)
-#else
-# define PRINTF(fmt, args...)
-#endif
+#include <support/check.h>
+
+#include "tst-glob_common.c"
+
#define LONG_NAME \
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
@@ -52,13 +44,7 @@
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
-static struct
-{
- const char *name;
- int level;
- int type;
- mode_t mode;
-} filesystem[] =
+struct filesystem_t filesystem[] =
{
{ ".", 1, DT_DIR, 0755 },
{ "..", 1, DT_DIR, 0755 },
@@ -79,7 +65,7 @@ static struct
{ "..", 3, DT_DIR, 0755 },
{ "a", 3, DT_REG, 0644 }
};
-#define nfiles (sizeof (filesystem) / sizeof (filesystem[0]))
+static const size_t nfiles = sizeof (filesystem) / sizeof (filesystem[0]);
typedef struct
@@ -91,65 +77,10 @@ typedef struct
} my_DIR;
-static long int
-find_file (const char *s)
-{
- int level = 1;
- long int idx = 0;
-
- if (strcmp (s, ".") == 0)
- return 0;
-
- if (s[0] == '.' && s[1] == '/')
- s += 2;
-
- while (*s != '\0')
- {
- char *endp = strchrnul (s, '/');
-
- PRINTF ("looking for %.*s, level %d\n", (int) (endp - s), s, level);
-
- while (idx < nfiles && filesystem[idx].level >= level)
- {
- if (filesystem[idx].level == level
- && memcmp (s, filesystem[idx].name, endp - s) == 0
- && filesystem[idx].name[endp - s] == '\0')
- break;
- ++idx;
- }
-
- if (idx == nfiles || filesystem[idx].level < level)
- {
- errno = ENOENT;
- return -1;
- }
-
- if (*endp == '\0')
- return idx + 1;
-
- if (filesystem[idx].type != DT_DIR
- && (idx + 1 >= nfiles
- || filesystem[idx].level >= filesystem[idx + 1].level))
- {
- errno = ENOTDIR;
- return -1;
- }
-
- ++idx;
-
- s = endp + 1;
- ++level;
- }
-
- errno = ENOENT;
- return -1;
-}
-
-
static void *
my_opendir (const char *s)
{
- long int idx = find_file (s);
+ long int idx = find_file (s, filesystem, nfiles);
my_DIR *dir;
if (idx == -1)
@@ -241,7 +172,7 @@ my_closedir (void *dir)
static int
my_stat (const char *name, struct stat *st)
{
- long int idx = find_file (name);
+ long int idx = find_file (name, filesystem, nfiles);
if (idx == -1)
{
@@ -275,7 +206,7 @@ init_glob_altdirfuncs (glob_t *pglob)
}
-int
+static int
do_test (void)
{
mtrace ();
@@ -286,10 +217,7 @@ do_test (void)
if (glob ("dir/*able/*", GLOB_ERR | GLOB_ALTDIRFUNC, NULL, &gl)
!= GLOB_ABORTED)
- {
- puts ("glob did not fail with GLOB_ABORTED");
- exit (EXIT_FAILURE);
- }
+ FAIL_EXIT1 ("glob did not fail with GLOB_ABORTED");
globfree (&gl);
@@ -298,10 +226,7 @@ do_test (void)
gl.gl_offs = 3;
if (glob ("dir2/*", GLOB_DOOFFS, NULL, &gl) != GLOB_NOMATCH)
- {
- puts ("glob did not fail with GLOB_NOMATCH");
- exit (EXIT_FAILURE);
- }
+ FAIL_EXIT1 ("glot dit not fail with GLOB_NOMATCH");
globfree (&gl);
@@ -310,5 +235,4 @@ do_test (void)
return 0;
}
-#define TEST_FUNCTION do_test ()
-#include "../test-skeleton.c"
+#include <support/test-driver.c>
diff --git a/posix/tst-gnuglob.c b/posix/tst-gnuglob.c
index d753674..f86eef7 100644
--- a/posix/tst-gnuglob.c
+++ b/posix/tst-gnuglob.c
@@ -20,7 +20,6 @@
#include <dirent.h>
#include <errno.h>
-#include <error.h>
#include <glob.h>
#include <mcheck.h>
#include <stdio.h>
@@ -28,21 +27,11 @@
#include <string.h>
#include <sys/stat.h>
+#include <support/check.h>
-// #define DEBUG
-#ifdef DEBUG
-# define PRINTF(fmt, args...) printf (fmt, ##args)
-#else
-# define PRINTF(fmt, args...)
-#endif
-
+#include "tst-glob_common.c"
-static struct
-{
- const char *name;
- int level;
- int type;
-} filesystem[] =
+struct filesystem_t filesystem[] =
{
{ ".", 1, DT_DIR },
{ "..", 1, DT_DIR },
@@ -84,7 +73,7 @@ static struct
{ "..", 4, DT_DIR },
{ "hidden", 4, DT_REG }
};
-#define nfiles (sizeof (filesystem) / sizeof (filesystem[0]))
+static const size_t nfiles = sizeof (filesystem) / sizeof (filesystem[0]);
typedef struct
@@ -96,75 +85,10 @@ typedef struct
} my_DIR;
-static long int
-find_file (const char *s)
-{
- int level = 1;
- long int idx = 0;
-
- while (s[0] == '/')
- {
- if (s[1] == '\0')
- {
- s = ".";
- break;
- }
- ++s;
- }
-
- if (strcmp (s, ".") == 0)
- return 0;
-
- if (s[0] == '.' && s[1] == '/')
- s += 2;
-
- while (*s != '\0')
- {
- char *endp = strchrnul (s, '/');
-
- PRINTF ("looking for %.*s, level %d\n", (int) (endp - s), s, level);
-
- while (idx < nfiles && filesystem[idx].level >= level)
- {
- if (filesystem[idx].level == level
- && memcmp (s, filesystem[idx].name, endp - s) == 0
- && filesystem[idx].name[endp - s] == '\0')
- break;
- ++idx;
- }
-
- if (idx == nfiles || filesystem[idx].level < level)
- {
- errno = ENOENT;
- return -1;
- }
-
- if (*endp == '\0')
- return idx + 1;
-
- if (filesystem[idx].type != DT_DIR
- && (idx + 1 >= nfiles
- || filesystem[idx].level >= filesystem[idx + 1].level))
- {
- errno = ENOTDIR;
- return -1;
- }
-
- ++idx;
-
- s = endp + 1;
- ++level;
- }
-
- errno = ENOENT;
- return -1;
-}
-
-
static void *
my_opendir (const char *s)
{
- long int idx = find_file (s);
+ long int idx = find_file (s, filesystem, nfiles);
my_DIR *dir;
@@ -176,7 +100,7 @@ my_opendir (const char *s)
dir = (my_DIR *) malloc (sizeof (my_DIR));
if (dir == NULL)
- error (EXIT_FAILURE, errno, "cannot allocate directory handle");
+ FAIL_EXIT1 ("cannot allocate directory handle");
dir->level = filesystem[idx].level;
dir->idx = idx;
@@ -247,13 +171,11 @@ my_closedir (void *dir)
static int
my_stat (const char *name, struct stat *st)
{
- long int idx = find_file (name);
+ long int idx = find_file (name, filesystem, nfiles);
if (idx == -1)
- {
- PRINTF ("my_stat (\"%s\", ...) = -1 (%s)\n", name, strerror (errno));
- return -1;
- }
+ FAIL_EXIT1 ("%s (\"%s\", ...) == -1 (%s)", __func__, name,
+ strerror (errno));
memset (st, '\0', sizeof (*st));
@@ -276,7 +198,8 @@ static const char *glob_errstring[] =
[GLOB_ABORTED] = "read error",
[GLOB_NOMATCH] = "no matches found"
};
-#define nglob_errstring (sizeof (glob_errstring) / sizeof (glob_errstring[0]))
+static const size_t nglob_errstring = (sizeof (glob_errstring)
+ / sizeof (glob_errstring[0]));
static const char *
@@ -289,7 +212,7 @@ flagstr (int flags)
"GLOB_ALTDIRFUNC", "GLOB_BRACE", "GLOB_NOMAGIC", "GLOB_TILDE",
"GLOB_ONLYDIR", "GLOB_TILDECHECK"
};
-#define nstrs (sizeof (strs) / sizeof (strs[0]))
+ static const size_t nstrs = (sizeof (strs) / sizeof (strs[0]));
static char buf[100];
char *cp = buf;
int cnt;
@@ -311,7 +234,6 @@ flagstr (int flags)
}
return buf;
-#undef nstrs
}
@@ -378,7 +300,6 @@ test_result (const char *fmt, int flags, glob_t *gl, const char *str[])
return result;
}
-
static int
do_test (void)
{
@@ -416,7 +337,8 @@ do_test (void)
result |= test_result (fmt, flags, &gl, (const char *[]) { c, NULL }); \
else \
printf ("result for glob (\"%s\", %s) = %s\n\n", fmt, flagstr (flags), \
- errstr (errval))
+ errstr (errval)); \
+ globfree (&gl)
test ("*/*/*", 0, 0,
"dir1lev1/dir2lev2/dir1lev3",
@@ -498,5 +420,4 @@ do_test (void)
return result;
}
-#define TEST_FUNCTION do_test ()
-#include "../test-skeleton.c"
+#include <support/test-driver.c>
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=c1ba9d146a5fd7522fa45f4309922f693e7470f5
commit c1ba9d146a5fd7522fa45f4309922f693e7470f5
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Fri May 19 12:39:47 2017 -0300
posix: Allow glob to match dangling symlinks [BZ #866]
This patch makes glob match dangling symlinks. Compared to other glob
implementation (*BSD, bash, musl, and other shells as well), GLIBC seems
the be the only one that does not match dangling symlinks. As for
comment #5 in BZ #866, POSIX does not have any strict specification for
dangling symlinks match and it is reasonable that trying to glob everything
in a path should return all types of files (such as for a 'rm *'). Also,
comment #7 shows even more example where GLIBC current behavior is
unexepected.
I avoided adding another GNU specific flag to set this behavior and
instead make it the default. Although this change the semanthic from
previous implementation, I think adding another compat symbol to be
really unecessary as from aforementioned reasons (current behavior not
defined in any standard, general idea of different implementation is
to list dangling symbols).
Checked on x86_64-linux-gnu.
* posix/Makefile (tests): Add tst-glob_symlinks and remove tst-glob3.
* posix/bug-glob1.c: Remove file.
* posix/glob.c (glob): Match dangling symlinks.
(link_exists2_p): Remove function.
(link_exists_p): Likewise.
* posix/tst-glob_symlinks.c: New file.
* sysdeps/gnu/glob64.c (__stat): Redefine to __lstat.
* sysdeps/unix/sysv/linux/i386/glob64.c (__stat): Likewise.
diff --git a/posix/Makefile b/posix/Makefile
index 33abcae..1424703 100644
--- a/posix/Makefile
+++ b/posix/Makefile
@@ -69,7 +69,7 @@ tests := test-errno tstgetopt testfnm runtests runptests \
tst-mmap tst-mmap-offset tst-getaddrinfo tst-truncate \
tst-truncate64 tst-fork tst-fnmatch tst-regexloc tst-dir \
tst-chmod bug-regex1 bug-regex2 bug-regex3 bug-regex4 \
- tst-gnuglob tst-regex bug-regex6 bug-regex7 \
+ tst-gnuglob tst-glob_symlinks tst-regex bug-regex6 bug-regex7 \
bug-regex8 bug-regex9 bug-regex10 bug-regex11 bug-regex12 \
bug-regex13 bug-regex14 bug-regex15 bug-regex16 \
bug-regex17 bug-regex18 bug-regex19 \
@@ -79,7 +79,7 @@ tests := test-errno tstgetopt testfnm runtests runptests \
tst-nice tst-nanosleep tst-regex2 \
transbug tst-rxspencer tst-pcre tst-boost \
bug-ga1 tst-vfork1 tst-vfork2 tst-vfork3 tst-waitid \
- tst-getaddrinfo2 bug-glob1 bug-glob2 bug-glob3 tst-sysconf \
+ tst-getaddrinfo2 bug-glob2 bug-glob3 tst-sysconf \
tst-execvp1 tst-execvp2 tst-execlp1 tst-execlp2 \
tst-execv1 tst-execv2 tst-execl1 tst-execl2 \
tst-execve1 tst-execve2 tst-execle1 tst-execle2 \
@@ -250,7 +250,6 @@ tst-rxspencer-ARGS = --utf8 rxspencer/tests
tst-rxspencer-no-utf8-ARGS = rxspencer/tests
tst-pcre-ARGS = PCRE.tests
tst-boost-ARGS = BOOST.tests
-bug-glob1-ARGS = "$(objpfx)"
tst-execvp3-ARGS = --test-dir=$(objpfx)
testcases.h: TESTS TESTS2C.sed
diff --git a/posix/bug-glob1.c b/posix/bug-glob1.c
deleted file mode 100644
index 05c2da7..0000000
--- a/posix/bug-glob1.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/* Test case for globbing dangling symlink. By Ulrich Drepper. */
-#include <errno.h>
-#include <error.h>
-#include <glob.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-
-static void prepare (int argc, char *argv[]);
-#define PREPARE prepare
-static int do_test (void);
-#define TEST_FUNCTION do_test ()
-
-#include "../test-skeleton.c"
-
-
-static char *fname;
-
-static void
-prepare (int argc, char *argv[])
-{
- if (argc < 2)
- error (EXIT_FAILURE, 0, "missing argument");
-
- size_t len = strlen (argv[1]);
- static const char ext[] = "globXXXXXX";
- fname = malloc (len + sizeof (ext));
- if (fname == NULL)
- error (EXIT_FAILURE, errno, "cannot create temp file");
- again:
- strcpy (stpcpy (fname, argv[1]), ext);
- fname = mktemp (fname);
- if (fname == NULL || *fname == '\0')
- error (EXIT_FAILURE, errno, "cannot create temp file name");
- if (symlink ("bug-glob1-does-not-exist", fname) != 0)
- {
- if (errno == EEXIST)
- goto again;
-
- error (EXIT_FAILURE, errno, "cannot create symlink");
- }
- add_temp_file (fname);
-}
-
-
-static int
-do_test (void)
-{
- glob_t gl;
- int retval = 0;
- int e;
-
- e = glob (fname, 0, NULL, &gl);
- if (e == 0)
- {
- printf ("glob(\"%s\") succeeded\n", fname);
- retval = 1;
- }
- globfree (&gl);
-
- size_t fnamelen = strlen (fname);
- char buf[fnamelen + 2];
-
- strcpy (buf, fname);
- buf[fnamelen - 1] = '?';
- e = glob (buf, 0, NULL, &gl);
- if (e == 0)
- {
- printf ("glob(\"%s\") succeeded\n", buf);
- retval = 1;
- }
- globfree (&gl);
-
- strcpy (buf, fname);
- buf[fnamelen] = '*';
- buf[fnamelen + 1] = '\0';
- e = glob (buf, 0, NULL, &gl);
- if (e == 0)
- {
- printf ("glob(\"%s\") succeeded\n", buf);
- retval = 1;
- }
- globfree (&gl);
-
- return retval;
-}
diff --git a/posix/glob.c b/posix/glob.c
index 3c6b033..250bff1 100644
--- a/posix/glob.c
+++ b/posix/glob.c
@@ -71,8 +71,8 @@
# define readdir(str) __readdir64 (str)
# define getpwnam_r(name, bufp, buf, len, res) \
__getpwnam_r (name, bufp, buf, len, res)
-# ifndef __stat64
-# define __stat64(fname, buf) __xstat64 (_STAT_VER, fname, buf)
+# ifndef __lstat64
+# define __lstat64(fname, buf) __lxstat64 (_STAT_VER, fname, buf)
# endif
# define struct_stat64 struct stat64
#else /* !_LIBC */
@@ -1049,9 +1049,9 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
/* Return the directory if we don't check for error or if it exists. */
if ((flags & GLOB_NOCHECK)
|| (((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0))
- ? ((*pglob->gl_stat) (dirname, &st) == 0
+ ? ((*pglob->gl_lstat) (dirname, &st) == 0
&& S_ISDIR (st.st_mode))
- : (__stat64 (dirname, &st64) == 0 && S_ISDIR (st64.st_mode)))))
+ : (__lstat64 (dirname, &st64) == 0 && S_ISDIR (st64.st_mode)))))
{
size_t newcount = pglob->gl_pathc + pglob->gl_offs;
char **new_gl_pathv;
@@ -1318,10 +1318,10 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
for (i = oldcount; i < pglob->gl_pathc + pglob->gl_offs; ++i)
if ((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
- ? ((*pglob->gl_stat) (pglob->gl_pathv[i], &st) == 0
- && S_ISDIR (st.st_mode))
- : (__stat64 (pglob->gl_pathv[i], &st64) == 0
- && S_ISDIR (st64.st_mode))))
+ ? ((*pglob->gl_lstat) (pglob->gl_pathv[i], &st) == 0
+ && (S_ISDIR (st.st_mode) || S_ISLNK (st.st_mode)))
+ : (__lstat64 (pglob->gl_pathv[i], &st64) == 0
+ && (S_ISDIR (st64.st_mode) || S_ISLNK (st64.st_mode)))))
{
size_t len = strlen (pglob->gl_pathv[i]) + 2;
char *new = realloc (pglob->gl_pathv[i], len);
@@ -1500,54 +1500,6 @@ weak_alias (__glob_pattern_p, glob_pattern_p)
# endif
#endif
-
-/* We put this in a separate function mainly to allow the memory
- allocated with alloca to be recycled. */
-static int
-__attribute_noinline__
-link_exists2_p (const char *dir, size_t dirlen, const char *fname,
- glob_t *pglob
-# if !defined _LIBC && !HAVE_FSTATAT
- , int flags
-# endif
- )
-{
- size_t fnamelen = strlen (fname);
- char *fullname = __alloca (dirlen + 1 + fnamelen + 1);
- struct stat st;
-
- mempcpy (mempcpy (mempcpy (fullname, dir, dirlen), "/", 1),
- fname, fnamelen + 1);
-
-# if !defined _LIBC && !HAVE_FSTATAT
- if (__builtin_expect ((flags & GLOB_ALTDIRFUNC) == 0, 1))
- {
- struct_stat64 st64;
- return __stat64 (fullname, &st64) == 0;
- }
-# endif
- return (*pglob->gl_stat) (fullname, &st) == 0;
-}
-
-/* Return true if DIR/FNAME exists. */
-static int
-link_exists_p (int dfd, const char *dir, size_t dirlen, const char *fname,
- glob_t *pglob, int flags)
-{
-# if defined _LIBC || HAVE_FSTATAT
- if (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0))
- return link_exists2_p (dir, dirlen, fname, pglob);
- else
- {
- /* dfd cannot be -1 here, because dirfd never returns -1 on
- glibc, or on hosts that have fstatat. */
- struct_stat64 st64;
- return __fxstatat64 (_STAT_VER, dfd, fname, &st64, 0) == 0;
- }
-# else
- return link_exists2_p (dir, dirlen, fname, pglob, flags);
-# endif
-}
#endif /* !defined GLOB_ONLY_P */
@@ -1619,8 +1571,8 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
"/", 1),
pattern, patlen + 1);
if ((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
- ? (*pglob->gl_stat) (fullname, &ust.st)
- : __stat64 (fullname, &ust.st64)) == 0)
+ ? (*pglob->gl_lstat) (fullname, &ust.st)
+ : __lstat64 (fullname, &ust.st64)) == 0)
/* We found this file to be existing. Now tell the rest
of the function to copy this name into the result. */
flags |= GLOB_NOCHECK;
@@ -1642,8 +1594,6 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
}
else
{
- int dfd = (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
- ? -1 : dirfd ((DIR *) stream));
int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0)
| ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)
#if defined _AMIGA || defined VMS
@@ -1679,38 +1629,30 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
if (fnmatch (pattern, d.name, fnm_flags) == 0)
{
- /* If the file we found is a symlink we have to
- make sure the target file exists. */
- if (!readdir_result_might_be_symlink (d)
- || link_exists_p (dfd, directory, dirlen, d.name,
- pglob, flags))
+ if (cur == names->count)
{
- if (cur == names->count)
- {
- struct globnames *newnames;
- size_t count = names->count * 2;
- size_t size = (sizeof (struct globnames)
- + ((count - INITIAL_COUNT)
- * sizeof (char *)));
- if (glob_use_alloca (alloca_used, size))
- newnames = names_alloca
- = alloca_account (size, alloca_used);
- else if ((newnames = malloc (size))
- == NULL)
- goto memory_error;
- newnames->count = count;
- newnames->next = names;
- names = newnames;
- cur = 0;
- }
- names->name[cur] = strdup (d.name);
- if (names->name[cur] == NULL)
- goto memory_error;
- ++cur;
- ++nfound;
- if (SIZE_MAX - pglob->gl_offs <= nfound)
+ struct globnames *newnames;
+ size_t count = names->count * 2;
+ size_t size = (sizeof (struct globnames)
+ + ((count - INITIAL_COUNT)
+ * sizeof (char *)));
+ if (glob_use_alloca (alloca_used, size))
+ newnames = names_alloca
+ = alloca_account (size, alloca_used);
+ else if ((newnames = malloc (size)) == NULL)
goto memory_error;
- }
+ newnames->count = count;
+ newnames->next = names;
+ names = newnames;
+ cur = 0;
+ }
+ names->name[cur] = strdup (d.name);
+ if (names->name[cur] == NULL)
+ goto memory_error;
+ ++cur;
+ ++nfound;
+ if (SIZE_MAX - pglob->gl_offs <= nfound)
+ goto memory_error;
}
}
}
diff --git a/posix/tst-glob_symlinks.c b/posix/tst-glob_symlinks.c
new file mode 100644
index 0000000..c0f1802
--- /dev/null
+++ b/posix/tst-glob_symlinks.c
@@ -0,0 +1,133 @@
+/* Test glob symlinks return (BZ #866).
+ for the filesystem access functions.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <limits.h>
+#include <stddef.h>
+#include <glob.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <support/check.h>
+#include <support/temp_file.h>
+
+static void do_prepare (int argc, char *argv[]);
+#define PREPARE do_prepare
+static int do_test (void);
+#include <support/test-driver.c>
+
+static void
+create_link (const char *base, const char *fname, char *linkname,
+ size_t linknamesize)
+{
+ int ntries = 0;
+ while (1)
+ {
+ snprintf (linkname, linknamesize, "%s/%s%02d", test_dir, base,
+ ntries);
+ if (symlink (fname, linkname) == 0)
+ break;
+ if (errno != EEXIST)
+ FAIL_EXIT1 ("symlink failed: %m");
+ if (ntries++ == 10)
+ FAIL_EXIT1 ("symlink failed with EEXIST too many times");
+ }
+ add_temp_file (linkname);
+}
+
+static char valid_link[PATH_MAX];
+static char dangling_link[PATH_MAX];
+static char dangling_dir[PATH_MAX];
+
+static void
+do_prepare (int argc, char *argv[])
+{
+ char *fname;
+
+ create_temp_file ("tst-glob_symlinks.", &fname);
+
+ /* Create a existing symlink. */
+ create_link ("valid-symlink-tst-glob_symlinks", fname, valid_link,
+ sizeof valid_link);
+
+ /* Create a dangling symlink to a file. */
+ int fd = create_temp_file ("dangling-tst-glob_file", &fname);
+ TEST_VERIFY_EXIT (close (fd) == 0);
+ /* It throws an warning at process end due 'add_temp_file' trying to
+ unlink it again. */
+ TEST_VERIFY_EXIT (unlink (fname) == 0);
+ create_link ("dangling-symlink-file-tst-glob", fname, dangling_link,
+ sizeof dangling_link);
+
+ /* Create a dangling symlink to a directory. */
+ char tmpdir[PATH_MAX];
+ snprintf (tmpdir, sizeof tmpdir, "%s/dangling-tst-glob_folder.XXXXXX",
+ test_dir);
+ TEST_VERIFY_EXIT (mkdtemp (tmpdir) != NULL);
+ create_link ("dangling-symlink-dir-tst-glob", tmpdir, dangling_dir,
+ sizeof dangling_dir);
+ TEST_VERIFY_EXIT (rmdir (tmpdir) == 0);
+}
+
+static int
+do_test (void)
+{
+ char buf[PATH_MAX];
+ glob_t gl;
+
+ TEST_VERIFY_EXIT (glob (valid_link, 0, NULL, &gl) == 0);
+ TEST_VERIFY_EXIT (gl.gl_pathc == 1);
+ TEST_VERIFY_EXIT (strcmp (gl.gl_pathv[0], valid_link) == 0);
+ globfree (&gl);
+
+ TEST_VERIFY_EXIT (glob (dangling_link, 0, NULL, &gl) == 0);
+ TEST_VERIFY_EXIT (gl.gl_pathc == 1);
+ TEST_VERIFY_EXIT (strcmp (gl.gl_pathv[0], dangling_link) == 0);
+ globfree (&gl);
+
+ TEST_VERIFY_EXIT (glob (dangling_dir, 0, NULL, &gl) == 0);
+ TEST_VERIFY_EXIT (gl.gl_pathc == 1);
+ TEST_VERIFY_EXIT (strcmp (gl.gl_pathv[0], dangling_dir) == 0);
+ globfree (&gl);
+
+ snprintf (buf, sizeof buf, "%s", dangling_link);
+ buf[strlen(buf) - 1] = '?';
+ TEST_VERIFY_EXIT (glob (buf, 0, NULL, &gl) == 0);
+ TEST_VERIFY_EXIT (gl.gl_pathc == 1);
+ TEST_VERIFY_EXIT (strcmp (gl.gl_pathv[0], dangling_link) == 0);
+ globfree (&gl);
+
+ /* glob should handle dangling symbol as normal file, so <file>? should
+ return an empty string. */
+ snprintf (buf, sizeof buf, "%s?", dangling_link);
+ TEST_VERIFY_EXIT (glob (buf, 0, NULL, &gl) != 0);
+ globfree (&gl);
+
+ snprintf (buf, sizeof buf, "%s*", dangling_link);
+ TEST_VERIFY_EXIT (glob (buf, 0, NULL, &gl) == 0);
+ TEST_VERIFY_EXIT (gl.gl_pathc == 1);
+ TEST_VERIFY_EXIT (strcmp (gl.gl_pathv[0], dangling_link) == 0);
+ globfree (&gl);
+
+ return 0;
+}
diff --git a/sysdeps/gnu/glob64.c b/sysdeps/gnu/glob64.c
index d1e4e6f..250ff07 100644
--- a/sysdeps/gnu/glob64.c
+++ b/sysdeps/gnu/glob64.c
@@ -12,8 +12,8 @@
#undef stat
#define stat stat64
-#undef __stat
-#define __stat(file, buf) __xstat64 (_STAT_VER, file, buf)
+#undef __lstat
+#define __lstat(file, buf) __lxstat64 (_STAT_VER, file, buf)
#define NO_GLOB_PATTERN_P 1
diff --git a/sysdeps/unix/sysv/linux/i386/glob64.c b/sysdeps/unix/sysv/linux/i386/glob64.c
index 9c7abd8..2dcbe33 100644
--- a/sysdeps/unix/sysv/linux/i386/glob64.c
+++ b/sysdeps/unix/sysv/linux/i386/glob64.c
@@ -30,8 +30,8 @@
#undef stat
#define stat stat64
-#undef __stat
-#define __stat(file, buf) __xstat64 (_STAT_VER, file, buf)
+#undef __lstat
+#define __lstat(file, buf) __lxstat64 (_STAT_VER, file, buf)
#define NO_GLOB_PATTERN_P 1
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=b80fb4bbc472522aeeafa148061a5a480300fb50
commit b80fb4bbc472522aeeafa148061a5a480300fb50
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Wed May 17 17:01:05 2017 -0300
posix: Sync glob with gnulib [BZ #1062]
This patch syncs posix/glob.c implementation with gnulib version
1540f34. The main differences to gnulib code:
1. Commit 44c637c (Properly initialize glob structure with
GLOB_BRACE|GLOB_DOOFFS) which fixes BZ# 20707.
2. No inclusion of flexmember.h header and its usage on glob.
The code is meant to be rewritten and header is unrequired in
next patch in this set.
3. An additional define (GLOB_COMPAT_BUILD) to avoid building
size_and_wrapv and gblo_use_alloca twice on some configurations
(i368 compat code) due multiple inclusion.
The main changes are:
- Header organization mostly due gnulib requirements. It leads
to some simplification and less conditional includes.
- Use of glob_use_alloca with wraps up __libc_use_alloca with
saturated math for the total size calculation.
- Simplify some size allocation overflow calculation.
- Some fixed on non supported glibc systems.
- Some comments adjustments.
The changes does not alter current glob internal semantic. I also
added a missing globfree on posix/globtest.c (it helps silence
some valgrind or other memory profilers).
[BZ #1062]
* posix/glob.c: Sync with gnulib.
* posix/globtest.c (main): Add final globfree.
* sysdeps/unix/sysv/linux/i386/glob64.c (GLOB_COMPAT_BUILD):
Define.
diff --git a/posix/glob.c b/posix/glob.c
index c653809..3c6b033 100644
--- a/posix/glob.c
+++ b/posix/glob.c
@@ -15,7 +15,10 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#ifdef HAVE_CONFIG_H
+#ifndef _LIBC
+/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc
+ optimizes away the pattern == NULL || pglob == NULL tests below. */
+# define _GL_ARG_NONNULL(params)
# include <config.h>
#endif
@@ -34,22 +37,19 @@
#include <stdio.h> /* Needed on stupid SunOS for assert. */
-#if !defined _LIBC || !defined GLOB_ONLY_P
-#if defined HAVE_UNISTD_H || defined _LIBC
-# include <unistd.h>
-# ifndef POSIX
-# ifdef _POSIX_VERSION
-# define POSIX
-# endif
-# endif
+#ifndef GLOB_ONLY_P
+
+#include <unistd.h>
+#if !defined POSIX && defined _POSIX_VERSION
+# define POSIX
#endif
-#include <pwd.h>
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+# define WINDOWS32
+#endif
-#if defined HAVE_STDINT_H || defined _LIBC
-# include <stdint.h>
-#elif !defined UINTPTR_MAX
-# define UINTPTR_MAX (~((size_t) 0))
+#ifndef WINDOWS32
+# include <pwd.h>
#endif
#include <errno.h>
@@ -57,24 +57,7 @@
# define __set_errno(val) errno = (val)
#endif
-#if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__
-# include <dirent.h>
-#else
-# define dirent direct
-# ifdef HAVE_SYS_NDIR_H
-# include <sys/ndir.h>
-# endif
-# ifdef HAVE_SYS_DIR_H
-# include <sys/dir.h>
-# endif
-# ifdef HAVE_NDIR_H
-# include <ndir.h>
-# endif
-# ifdef HAVE_VMSDIR_H
-# include "vmsdir.h"
-# endif /* HAVE_VMSDIR_H */
-#endif
-
+#include <dirent.h>
#include <stdlib.h>
#include <string.h>
#include <alloca.h>
@@ -93,17 +76,16 @@
# endif
# define struct_stat64 struct stat64
#else /* !_LIBC */
-# include "getlogin_r.h"
-# include "mempcpy.h"
-# include "stat-macros.h"
-# include "strdup.h"
-# define __stat64(fname, buf) stat (fname, buf)
-# define struct_stat64 struct stat
-# define __stat(fname, buf) stat (fname, buf)
-# define __alloca alloca
-# define __readdir readdir
-# define __readdir64 readdir64
-# define __glob_pattern_p glob_pattern_p
+# define __getlogin_r(buf, len) getlogin_r (buf, len)
+# define __stat64(fname, buf) stat (fname, buf)
+# define __fxstatat64(_, d, f, st, flag) fstatat (d, f, st, flag)
+# define struct_stat64 struct stat
+# ifndef __MVS__
+# define __alloca alloca
+# endif
+# define __readdir readdir
+# define __glob_pattern_p glob_pattern_p
+# define COMPILE_GLOB64
#endif /* _LIBC */
#include <fnmatch.h>
@@ -186,7 +168,7 @@ readdir_result_might_be_dir (struct readdir_result d)
D_INO_TO_RESULT (source) \
}
-#endif /* !defined _LIBC || !defined GLOB_ONLY_P */
+#endif /* !defined GLOB_ONLY_P */
/* Call gl_readdir on STREAM. This macro can be overridden to reduce
type safety if an old interface version needs to be supported. */
@@ -230,13 +212,74 @@ convert_dirent64 (const struct dirent64 *source)
# define attribute_hidden
#endif
+#ifndef __attribute_noinline__
+# if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 1)
+# define __attribute_noinline__ /* Ignore */
+#else
+# define __attribute_noinline__ __attribute__ ((__noinline__))
+# endif
+#endif
+
+#ifndef __glibc_unlikely
+# define __glibc_unlikely(expr) __builtin_expect (expr, 0)
+#endif
+
+#ifndef _LIBC
+/* The results of opendir() in this file are not used with dirfd and fchdir,
+ and we do not leak fds to any single-threaded code that could use stdio,
+ therefore save some unnecessary recursion in fchdir.c and opendir_safer.c.
+ FIXME - if the kernel ever adds support for multi-thread safety for
+ avoiding standard fds, then we should use opendir_safer. */
+# ifdef GNULIB_defined_opendir
+# undef opendir
+# endif
+# ifdef GNULIB_defined_closedir
+# undef closedir
+# endif
+
+/* Just use malloc. */
+# define __libc_use_alloca(n) false
+# define alloca_account(len, avar) ((void) (len), (void) (avar), (void *) 0)
+# define extend_alloca_account(buf, len, newlen, avar) \
+ ((void) (buf), (void) (len), (void) (newlen), (void) (avar), (void *) 0)
+#endif
+
+/* Set *R = A + B. Return true if the answer is mathematically
+ incorrect due to overflow; in this case, *R is the low order
+ bits of the correct answer.. */
+
+static bool size_add_wrapv (size_t a, size_t b, size_t *r);
+static bool glob_use_alloca (size_t alloca_used, size_t len);
+
+/* We must not compile this function twice. */
+#ifndef GLOB_COMPAT_BUILD
+static bool
+size_add_wrapv (size_t a, size_t b, size_t *r)
+{
+#if 5 <= __GNUC__
+ return __builtin_add_overflow (a, b, r);
+#else
+ *r = a + b;
+ return *r < a;
+#endif
+}
+
+static bool
+glob_use_alloca (size_t alloca_used, size_t len)
+{
+ size_t size;
+ return (!size_add_wrapv (alloca_used, len, &size)
+ && __libc_use_alloca (size));
+}
+#endif
+
static int glob_in_dir (const char *pattern, const char *directory,
int flags, int (*errfunc) (const char *, int),
glob_t *pglob, size_t alloca_used);
extern int __glob_pattern_type (const char *pattern, int quote)
attribute_hidden;
-#if !defined _LIBC || !defined GLOB_ONLY_P
+#ifndef GLOB_ONLY_P
static int prefix_array (const char *prefix, char **array, size_t n) __THROWNL;
static int collated_compare (const void *, const void *) __THROWNL;
@@ -265,16 +308,16 @@ next_brace_sub (const char *cp, int flags)
return *cp != '\0' ? cp : NULL;
}
-#endif /* !defined _LIBC || !defined GLOB_ONLY_P */
+#endif /* !defined GLOB_ONLY_P */
/* Do glob searching for PATTERN, placing results in PGLOB.
The bits defined above may be set in FLAGS.
If a directory cannot be opened or read and ERRFUNC is not nil,
it is called with the pathname that caused the error, and the
- `errno' value from the failing call; if it returns non-zero
- `glob' returns GLOB_ABORTED; if it returns zero, the error is ignored.
+ 'errno' value from the failing call; if it returns non-zero
+ 'glob' returns GLOB_ABORTED; if it returns zero, the error is ignored.
If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.
- Otherwise, `glob' returns zero. */
+ Otherwise, 'glob' returns zero. */
int
#ifdef GLOB_ATTRIBUTE
GLOB_ATTRIBUTE
@@ -292,9 +335,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
int malloc_dirname = 0;
glob_t dirs;
int retval = 0;
-#ifdef _LIBC
size_t alloca_used = 0;
-#endif
if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0)
{
@@ -308,7 +349,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
flags |= GLOB_ONLYDIR;
if (!(flags & GLOB_DOOFFS))
- /* Have to do this so `globfree' knows where to start freeing. It
+ /* Have to do this so 'globfree' knows where to start freeing. It
also makes all the code that uses gl_offs simpler. */
pglob->gl_offs = 0;
@@ -363,7 +404,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
if (begin != NULL)
{
/* Allocate working buffer large enough for our work. Note that
- we have at least an opening and closing brace. */
+ we have at least an opening and closing brace. */
size_t firstc;
char *alt_start;
const char *p;
@@ -372,16 +413,21 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
size_t rest_len;
char *onealt;
size_t pattern_len = strlen (pattern) - 1;
-#ifdef _LIBC
- int alloca_onealt = __libc_use_alloca (alloca_used + pattern_len);
+ int alloca_onealt = glob_use_alloca (alloca_used, pattern_len);
if (alloca_onealt)
onealt = alloca_account (pattern_len, alloca_used);
else
-#endif
{
- onealt = (char *) malloc (pattern_len);
+ onealt = malloc (pattern_len);
if (onealt == NULL)
- return GLOB_NOSPACE;
+ {
+ if (!(flags & GLOB_APPEND))
+ {
+ pglob->gl_pathc = 0;
+ pglob->gl_pathv = NULL;
+ }
+ return GLOB_NOSPACE;
+ }
}
/* We know the prefix for all sub-patterns. */
@@ -392,14 +438,11 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
next = next_brace_sub (begin + 1, flags);
if (next == NULL)
{
- /* It is an illegal expression. */
+ /* It is an invalid expression. */
illegal_brace:
-#ifdef _LIBC
if (__glibc_unlikely (!alloca_onealt))
-#endif
free (onealt);
- flags &= ~GLOB_BRACE;
- goto no_brace;
+ return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
}
/* Now find the end of the whole brace expression. */
@@ -437,9 +480,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
/* If we got an error, return it. */
if (result && result != GLOB_NOMATCH)
{
-#ifdef _LIBC
if (__glibc_unlikely (!alloca_onealt))
-#endif
free (onealt);
if (!(flags & GLOB_APPEND))
{
@@ -458,9 +499,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
assert (next != NULL);
}
-#ifdef _LIBC
if (__glibc_unlikely (!alloca_onealt))
-#endif
free (onealt);
if (pglob->gl_pathc != firstc)
@@ -471,7 +510,6 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
}
}
- no_brace:
oldcount = pglob->gl_pathc + pglob->gl_offs;
/* Find the filename. */
@@ -536,22 +574,20 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
char *drive_spec;
++dirlen;
- drive_spec = (char *) __alloca (dirlen + 1);
+ drive_spec = __alloca (dirlen + 1);
*((char *) mempcpy (drive_spec, pattern, dirlen)) = '\0';
/* For now, disallow wildcards in the drive spec, to
prevent infinite recursion in glob. */
if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE)))
return GLOB_NOMATCH;
- /* If this is "d:pattern", we need to copy `:' to DIRNAME
+ /* If this is "d:pattern", we need to copy ':' to DIRNAME
as well. If it's "d:/pattern", don't remove the slash
from "d:/", since "d:" and "d:/" are not the same.*/
}
#endif
-#ifdef _LIBC
- if (__libc_use_alloca (alloca_used + dirlen + 1))
+ if (glob_use_alloca (alloca_used, dirlen + 1))
newp = alloca_account (dirlen + 1, alloca_used);
else
-#endif
{
newp = malloc (dirlen + 1);
if (newp == NULL)
@@ -572,6 +608,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
/* "pattern/". Expand "pattern", appending slashes. */
{
int orig_flags = flags;
+ int val;
if (!(flags & GLOB_NOESCAPE) && dirname[dirlen - 1] == '\\')
{
/* "pattern\\/". Remove the final backslash if it hasn't
@@ -585,7 +622,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC);
}
}
- int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob);
+ val = glob (dirname, flags | GLOB_MARK, errfunc, pglob);
if (val == 0)
pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK)
| (flags & GLOB_MARK));
@@ -602,7 +639,6 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
}
}
-#ifndef VMS
if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~')
{
if (dirname[1] == '\0' || dirname[1] == '/'
@@ -617,95 +653,129 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
home_dir = "SYS:";
# else
# ifdef WINDOWS32
+ /* Windows NT defines HOMEDRIVE and HOMEPATH. But give preference
+ to HOME, because the user can change HOME. */
if (home_dir == NULL || home_dir[0] == '\0')
- home_dir = "c:/users/default"; /* poor default */
+ {
+ const char *home_drive = getenv ("HOMEDRIVE");
+ const char *home_path = getenv ("HOMEPATH");
+
+ if (home_drive != NULL && home_path != NULL)
+ {
+ size_t home_drive_len = strlen (home_drive);
+ size_t home_path_len = strlen (home_path);
+ char *mem = alloca (home_drive_len + home_path_len + 1);
+
+ memcpy (mem, home_drive, home_drive_len);
+ memcpy (mem + home_drive_len, home_path, home_path_len + 1);
+ home_dir = mem;
+ }
+ else
+ home_dir = "c:/users/default"; /* poor default */
+ }
# else
if (home_dir == NULL || home_dir[0] == '\0')
{
int success;
char *name;
+ int malloc_name = 0;
size_t buflen = GET_LOGIN_NAME_MAX () + 1;
if (buflen == 0)
/* `sysconf' does not support _SC_LOGIN_NAME_MAX. Try
a moderate value. */
buflen = 20;
- name = alloca_account (buflen, alloca_used);
+ if (glob_use_alloca (alloca_used, buflen))
+ name = alloca_account (buflen, alloca_used);
+ else
+ {
+ name = malloc (buflen);
+ if (name == NULL)
+ {
+ retval = GLOB_NOSPACE;
+ goto out;
+ }
+ malloc_name = 1;
+ }
success = __getlogin_r (name, buflen) == 0;
if (success)
{
struct passwd *p;
-# if defined HAVE_GETPWNAM_R || defined _LIBC
- long int pwbuflen = GETPW_R_SIZE_MAX ();
+ char *malloc_pwtmpbuf = NULL;
char *pwtmpbuf;
+# if defined HAVE_GETPWNAM_R || defined _LIBC
+ long int pwbuflenmax = GETPW_R_SIZE_MAX ();
+ size_t pwbuflen = pwbuflenmax;
struct passwd pwbuf;
- int malloc_pwtmpbuf = 0;
int save = errno;
# ifndef _LIBC
- if (pwbuflen == -1)
+ if (! (0 < pwbuflenmax && pwbuflenmax <= SIZE_MAX))
/* `sysconf' does not support _SC_GETPW_R_SIZE_MAX.
Try a moderate value. */
pwbuflen = 1024;
# endif
- if (__libc_use_alloca (alloca_used + pwbuflen))
+ if (glob_use_alloca (alloca_used, pwbuflen))
pwtmpbuf = alloca_account (pwbuflen, alloca_used);
else
{
pwtmpbuf = malloc (pwbuflen);
if (pwtmpbuf == NULL)
{
+ if (__glibc_unlikely (malloc_name))
+ free (name);
retval = GLOB_NOSPACE;
goto out;
}
- malloc_pwtmpbuf = 1;
+ malloc_pwtmpbuf = pwtmpbuf;
}
while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p)
!= 0)
{
+ size_t newlen;
+ bool v;
if (errno != ERANGE)
{
p = NULL;
break;
}
-
- if (!malloc_pwtmpbuf
- && __libc_use_alloca (alloca_used
- + 2 * pwbuflen))
+ v = size_add_wrapv (pwbuflen, pwbuflen, &newlen);
+ if (!v && malloc_pwtmpbuf == NULL
+ && glob_use_alloca (alloca_used, newlen))
pwtmpbuf = extend_alloca_account (pwtmpbuf, pwbuflen,
- 2 * pwbuflen,
- alloca_used);
+ newlen, alloca_used);
else
{
- char *newp = realloc (malloc_pwtmpbuf
- ? pwtmpbuf : NULL,
- 2 * pwbuflen);
+ char *newp = (v ? NULL
+ : realloc (malloc_pwtmpbuf, newlen));
if (newp == NULL)
{
- if (__glibc_unlikely (malloc_pwtmpbuf))
- free (pwtmpbuf);
+ free (malloc_pwtmpbuf);
+ if (__glibc_unlikely (malloc_name))
+ free (name);
retval = GLOB_NOSPACE;
goto out;
}
- pwtmpbuf = newp;
- pwbuflen = 2 * pwbuflen;
- malloc_pwtmpbuf = 1;
+ malloc_pwtmpbuf = pwtmpbuf = newp;
}
+ pwbuflen = newlen;
__set_errno (save);
}
# else
p = getpwnam (name);
# endif
+ if (__glibc_unlikely (malloc_name))
+ free (name);
if (p != NULL)
{
- if (!malloc_pwtmpbuf)
+ if (malloc_pwtmpbuf == NULL)
home_dir = p->pw_dir;
else
{
size_t home_dir_len = strlen (p->pw_dir) + 1;
- if (__libc_use_alloca (alloca_used + home_dir_len))
+ if (glob_use_alloca (alloca_used, home_dir_len))
home_dir = alloca_account (home_dir_len,
alloca_used);
else
@@ -720,23 +790,30 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
malloc_home_dir = 1;
}
memcpy (home_dir, p->pw_dir, home_dir_len);
-
- free (pwtmpbuf);
}
}
+ free (malloc_pwtmpbuf);
+ }
+ else
+ {
+ if (__glibc_unlikely (malloc_name))
+ free (name);
}
}
if (home_dir == NULL || home_dir[0] == '\0')
{
+ if (__glibc_unlikely (malloc_home_dir))
+ free (home_dir);
if (flags & GLOB_TILDE_CHECK)
{
- if (__glibc_unlikely (malloc_home_dir))
- free (home_dir);
retval = GLOB_NOMATCH;
goto out;
}
else
- home_dir = (char *) "~"; /* No luck. */
+ {
+ home_dir = (char *) "~"; /* No luck. */
+ malloc_home_dir = 0;
+ }
}
# endif /* WINDOWS32 */
# endif
@@ -754,8 +831,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
{
char *newp;
size_t home_len = strlen (home_dir);
- int use_alloca = __libc_use_alloca (alloca_used
- + home_len + dirlen);
+ int use_alloca = glob_use_alloca (alloca_used, home_len + dirlen);
if (use_alloca)
newp = alloca_account (home_len + dirlen, alloca_used);
else
@@ -779,6 +855,9 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
dirname = newp;
dirlen += home_len - 1;
malloc_dirname = !use_alloca;
+
+ if (__glibc_unlikely (malloc_home_dir))
+ free (home_dir);
}
dirname_modified = 1;
}
@@ -806,7 +885,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
else
{
char *newp;
- if (__libc_use_alloca (alloca_used + (end_name - dirname)))
+ if (glob_use_alloca (alloca_used, end_name - dirname))
newp = alloca_account (end_name - dirname, alloca_used);
else
{
@@ -851,20 +930,21 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
/* Look up specific user's home directory. */
{
struct passwd *p;
+ char *malloc_pwtmpbuf = NULL;
# if defined HAVE_GETPWNAM_R || defined _LIBC
- long int buflen = GETPW_R_SIZE_MAX ();
+ long int buflenmax = GETPW_R_SIZE_MAX ();
+ size_t buflen = buflenmax;
char *pwtmpbuf;
- int malloc_pwtmpbuf = 0;
struct passwd pwbuf;
int save = errno;
# ifndef _LIBC
- if (buflen == -1)
- /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX. Try a
+ if (! (0 <= buflenmax && buflenmax <= SIZE_MAX))
+ /* Perhaps 'sysconf' does not support _SC_GETPW_R_SIZE_MAX. Try a
moderate value. */
buflen = 1024;
# endif
- if (__libc_use_alloca (alloca_used + buflen))
+ if (glob_use_alloca (alloca_used, buflen))
pwtmpbuf = alloca_account (buflen, alloca_used);
else
{
@@ -877,32 +957,32 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
retval = GLOB_NOSPACE;
goto out;
}
- malloc_pwtmpbuf = 1;
+ malloc_pwtmpbuf = pwtmpbuf;
}
while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0)
{
+ size_t newlen;
+ bool v;
if (errno != ERANGE)
{
p = NULL;
break;
}
- if (!malloc_pwtmpbuf
- && __libc_use_alloca (alloca_used + 2 * buflen))
+ v = size_add_wrapv (buflen, buflen, &newlen);
+ if (!v && malloc_pwtmpbuf == NULL
+ && glob_use_alloca (alloca_used, newlen))
pwtmpbuf = extend_alloca_account (pwtmpbuf, buflen,
- 2 * buflen, alloca_used);
+ newlen, alloca_used);
else
{
- char *newp = realloc (malloc_pwtmpbuf ? pwtmpbuf : NULL,
- 2 * buflen);
+ char *newp = v ? NULL : realloc (malloc_pwtmpbuf, newlen);
if (newp == NULL)
{
- if (__glibc_unlikely (malloc_pwtmpbuf))
- free (pwtmpbuf);
+ free (malloc_pwtmpbuf);
goto nomem_getpw;
}
- pwtmpbuf = newp;
- malloc_pwtmpbuf = 1;
+ malloc_pwtmpbuf = pwtmpbuf = newp;
}
__set_errno (save);
}
@@ -923,7 +1003,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
free (dirname);
malloc_dirname = 0;
- if (__libc_use_alloca (alloca_used + home_len + rest_len + 1))
+ if (glob_use_alloca (alloca_used, home_len + rest_len + 1))
dirname = alloca_account (home_len + rest_len + 1,
alloca_used);
else
@@ -931,8 +1011,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
dirname = malloc (home_len + rest_len + 1);
if (dirname == NULL)
{
- if (__glibc_unlikely (malloc_pwtmpbuf))
- free (pwtmpbuf);
+ free (malloc_pwtmpbuf);
retval = GLOB_NOSPACE;
goto out;
}
@@ -944,13 +1023,11 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
dirlen = home_len + rest_len;
dirname_modified = 1;
- if (__glibc_unlikely (malloc_pwtmpbuf))
- free (pwtmpbuf);
+ free (malloc_pwtmpbuf);
}
else
{
- if (__glibc_unlikely (malloc_pwtmpbuf))
- free (pwtmpbuf);
+ free (malloc_pwtmpbuf);
if (flags & GLOB_TILDE_CHECK)
/* We have to regard it as an error if we cannot find the
@@ -961,7 +1038,6 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
}
# endif /* Not Amiga && not WINDOWS32. */
}
-#endif /* Not VMS. */
/* Now test whether we looked for "~" or "~NAME". In this case we
can give the answer now. */
@@ -980,19 +1056,19 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
size_t newcount = pglob->gl_pathc + pglob->gl_offs;
char **new_gl_pathv;
- if (newcount > UINTPTR_MAX - (1 + 1)
- || newcount + 1 + 1 > ~((size_t) 0) / sizeof (char *))
+ if (newcount > SIZE_MAX / sizeof (char *) - 2)
{
nospace:
+ if (__glibc_unlikely (malloc_dirname))
+ free (dirname);
free (pglob->gl_pathv);
pglob->gl_pathv = NULL;
pglob->gl_pathc = 0;
return GLOB_NOSPACE;
}
- new_gl_pathv
- = (char **) realloc (pglob->gl_pathv,
- (newcount + 1 + 1) * sizeof (char *));
+ new_gl_pathv = realloc (pglob->gl_pathv,
+ (newcount + 2) * sizeof (char *));
if (new_gl_pathv == NULL)
goto nospace;
pglob->gl_pathv = new_gl_pathv;
@@ -1009,9 +1085,14 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
}
else
{
- pglob->gl_pathv[newcount] = strdup (dirname);
- if (pglob->gl_pathv[newcount] == NULL)
- goto nospace;
+ if (__glibc_unlikely (malloc_dirname))
+ pglob->gl_pathv[newcount] = dirname;
+ else
+ {
+ pglob->gl_pathv[newcount] = strdup (dirname);
+ if (pglob->gl_pathv[newcount] == NULL)
+ goto nospace;
+ }
}
pglob->gl_pathv[++newcount] = NULL;
++pglob->gl_pathc;
@@ -1078,7 +1159,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
{
size_t old_pathc;
-#ifdef SHELL
+#ifdef SHELL
{
/* Make globbing interruptible in the bash shell. */
extern int interrupt_state;
@@ -1134,22 +1215,20 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
size_t newcount = pglob->gl_pathc + pglob->gl_offs;
char **new_gl_pathv;
- if (newcount > UINTPTR_MAX - 2
- || newcount + 2 > ~((size_t) 0) / sizeof (char *))
+ if (newcount > SIZE_MAX / sizeof (char *) - 2)
{
nospace2:
globfree (&dirs);
return GLOB_NOSPACE;
}
- new_gl_pathv = (char **) realloc (pglob->gl_pathv,
- (newcount + 2)
- * sizeof (char *));
+ new_gl_pathv = realloc (pglob->gl_pathv,
+ (newcount + 2) * sizeof (char *));
if (new_gl_pathv == NULL)
goto nospace2;
pglob->gl_pathv = new_gl_pathv;
- pglob->gl_pathv[newcount] = __strdup (pattern);
+ pglob->gl_pathv[newcount] = strdup (pattern);
if (pglob->gl_pathv[newcount] == NULL)
{
globfree (&dirs);
@@ -1276,7 +1355,7 @@ libc_hidden_def (glob)
#endif
-#if !defined _LIBC || !defined GLOB_ONLY_P
+#ifndef GLOB_ONLY_P
/* Free storage allocated in PGLOB by a previous `glob' call. */
void
@@ -1300,8 +1379,8 @@ libc_hidden_def (globfree)
static int
collated_compare (const void *a, const void *b)
{
- const char *const s1 = *(const char *const * const) a;
- const char *const s2 = *(const char *const * const) b;
+ char *const *ps1 = a; char *s1 = *ps1;
+ char *const *ps2 = b; char *s2 = *ps2;
if (s1 == s2)
return 0;
@@ -1351,7 +1430,7 @@ prefix_array (const char *dirname, char **array, size_t n)
for (i = 0; i < n; ++i)
{
size_t eltlen = strlen (array[i]) + 1;
- char *new = (char *) malloc (dirlen + 1 + eltlen);
+ char *new = malloc (dirlen + 1 + eltlen);
if (new == NULL)
{
while (i > 0)
@@ -1373,7 +1452,7 @@ prefix_array (const char *dirname, char **array, size_t n)
/* We must not compile this function twice. */
-#if !defined _LIBC || !defined NO_GLOB_PATTERN_P
+#ifndef NO_GLOB_PATTERN_P
int
__glob_pattern_type (const char *pattern, int quote)
{
@@ -1421,50 +1500,55 @@ weak_alias (__glob_pattern_p, glob_pattern_p)
# endif
#endif
-#endif /* !GLOB_ONLY_P */
-
/* We put this in a separate function mainly to allow the memory
allocated with alloca to be recycled. */
-#if !defined _LIBC || !defined GLOB_ONLY_P
static int
__attribute_noinline__
link_exists2_p (const char *dir, size_t dirlen, const char *fname,
glob_t *pglob
-# ifndef _LIBC
+# if !defined _LIBC && !HAVE_FSTATAT
, int flags
# endif
)
{
size_t fnamelen = strlen (fname);
- char *fullname = (char *) __alloca (dirlen + 1 + fnamelen + 1);
+ char *fullname = __alloca (dirlen + 1 + fnamelen + 1);
struct stat st;
-# ifndef _LIBC
- struct_stat64 st64;
-# endif
mempcpy (mempcpy (mempcpy (fullname, dir, dirlen), "/", 1),
fname, fnamelen + 1);
-# ifdef _LIBC
- return (*pglob->gl_stat) (fullname, &st) == 0;
-# else
- return ((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
- ? (*pglob->gl_stat) (fullname, &st)
- : __stat64 (fullname, &st64)) == 0);
+# if !defined _LIBC && !HAVE_FSTATAT
+ if (__builtin_expect ((flags & GLOB_ALTDIRFUNC) == 0, 1))
+ {
+ struct_stat64 st64;
+ return __stat64 (fullname, &st64) == 0;
+ }
# endif
+ return (*pglob->gl_stat) (fullname, &st) == 0;
}
-# ifdef _LIBC
-# define link_exists_p(dfd, dirname, dirnamelen, fname, pglob, flags) \
- (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0) \
- ? link_exists2_p (dirname, dirnamelen, fname, pglob) \
- : ({ struct stat64 st64; \
- __fxstatat64 (_STAT_VER, dfd, fname, &st64, 0) == 0; }))
+
+/* Return true if DIR/FNAME exists. */
+static int
+link_exists_p (int dfd, const char *dir, size_t dirlen, const char *fname,
+ glob_t *pglob, int flags)
+{
+# if defined _LIBC || HAVE_FSTATAT
+ if (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0))
+ return link_exists2_p (dir, dirlen, fname, pglob);
+ else
+ {
+ /* dfd cannot be -1 here, because dirfd never returns -1 on
+ glibc, or on hosts that have fstatat. */
+ struct_stat64 st64;
+ return __fxstatat64 (_STAT_VER, dfd, fname, &st64, 0) == 0;
+ }
# else
-# define link_exists_p(dfd, dirname, dirnamelen, fname, pglob, flags) \
- link_exists2_p (dirname, dirnamelen, fname, pglob, flags)
+ return link_exists2_p (dir, dirlen, fname, pglob, flags);
# endif
-#endif
+}
+#endif /* !defined GLOB_ONLY_P */
/* Like `glob', but PATTERN is a final pathname component,
@@ -1492,6 +1576,7 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
size_t cur = 0;
int meta;
int save;
+ int result;
alloca_used += sizeof (init_names);
@@ -1516,14 +1601,16 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
struct_stat64 st64;
} ust;
size_t patlen = strlen (pattern);
- int alloca_fullname = __libc_use_alloca (alloca_used
- + dirlen + 1 + patlen + 1);
+ size_t fullsize;
+ bool alloca_fullname
+ = (! size_add_wrapv (dirlen + 1, patlen + 1, &fullsize)
+ && glob_use_alloca (alloca_used, fullsize));
char *fullname;
if (alloca_fullname)
- fullname = alloca_account (dirlen + 1 + patlen + 1, alloca_used);
+ fullname = alloca_account (fullsize, alloca_used);
else
{
- fullname = malloc (dirlen + 1 + patlen + 1);
+ fullname = malloc (fullsize);
if (fullname == NULL)
return GLOB_NOSPACE;
}
@@ -1555,10 +1642,8 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
}
else
{
-#ifdef _LIBC
int dfd = (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
? -1 : dirfd ((DIR *) stream));
-#endif
int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0)
| ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)
#if defined _AMIGA || defined VMS
@@ -1607,7 +1692,7 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
size_t size = (sizeof (struct globnames)
+ ((count - INITIAL_COUNT)
* sizeof (char *)));
- if (__libc_use_alloca (alloca_used + size))
+ if (glob_use_alloca (alloca_used, size))
newnames = names_alloca
= alloca_account (size, alloca_used);
else if ((newnames = malloc (size))
@@ -1623,6 +1708,8 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
goto memory_error;
++cur;
++nfound;
+ if (SIZE_MAX - pglob->gl_offs <= nfound)
+ goto memory_error;
}
}
}
@@ -1633,36 +1720,35 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
{
size_t len = strlen (pattern);
nfound = 1;
- names->name[cur] = (char *) malloc (len + 1);
+ names->name[cur] = malloc (len + 1);
if (names->name[cur] == NULL)
goto memory_error;
*((char *) mempcpy (names->name[cur++], pattern, len)) = '\0';
}
- int result = GLOB_NOMATCH;
+ result = GLOB_NOMATCH;
if (nfound != 0)
{
+ char **new_gl_pathv;
result = 0;
- if (pglob->gl_pathc > UINTPTR_MAX - pglob->gl_offs
- || pglob->gl_pathc + pglob->gl_offs > UINTPTR_MAX - nfound
- || pglob->gl_pathc + pglob->gl_offs + nfound > UINTPTR_MAX - 1
- || (pglob->gl_pathc + pglob->gl_offs + nfound + 1
- > UINTPTR_MAX / sizeof (char *)))
+ if (SIZE_MAX / sizeof (char *) - pglob->gl_pathc
+ < pglob->gl_offs + nfound + 1)
goto memory_error;
- char **new_gl_pathv;
new_gl_pathv
- = (char **) realloc (pglob->gl_pathv,
- (pglob->gl_pathc + pglob->gl_offs + nfound + 1)
- * sizeof (char *));
+ = realloc (pglob->gl_pathv,
+ (pglob->gl_pathc + pglob->gl_offs + nfound + 1)
+ * sizeof (char *));
+
if (new_gl_pathv == NULL)
{
memory_error:
while (1)
{
struct globnames *old = names;
- for (size_t i = 0; i < cur; ++i)
+ size_t i;
+ for (i = 0; i < cur; ++i)
free (names->name[i]);
names = names->next;
/* NB: we will not leak memory here if we exit without
@@ -1687,7 +1773,8 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
while (1)
{
struct globnames *old = names;
- for (size_t i = 0; i < cur; ++i)
+ size_t i;
+ for (i = 0; i < cur; ++i)
new_gl_pathv[pglob->gl_offs + pglob->gl_pathc++]
= names->name[i];
names = names->next;
diff --git a/posix/globtest.c b/posix/globtest.c
index 878ae33..7ffcb91 100644
--- a/posix/globtest.c
+++ b/posix/globtest.c
@@ -114,5 +114,8 @@ main (int argc, char *argv[])
g.gl_pathv[i] ? g.gl_pathv[i] : "(null)",
quotes ? "'" : "");
}
+
+ globfree (&g);
+
return 0;
}
diff --git a/sysdeps/unix/sysv/linux/i386/glob64.c b/sysdeps/unix/sysv/linux/i386/glob64.c
index f681951..9c7abd8 100644
--- a/sysdeps/unix/sysv/linux/i386/glob64.c
+++ b/sysdeps/unix/sysv/linux/i386/glob64.c
@@ -70,6 +70,8 @@ int __old_glob64 (const char *__pattern, int __flags,
#define GLOB_ONLY_P 1
+#define GLOB_COMPAT_BUILD 1
+
#include <posix/glob.c>
compat_symbol (libc, __old_glob64, glob64, GLIBC_2_1);
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=526d45c58ecbd329603c317bc5b80bfcfd6b08a1
commit 526d45c58ecbd329603c317bc5b80bfcfd6b08a1
Author: Florian Weimer <fweimer@redhat.com>
Date: Tue Jun 20 10:31:28 2017 -0300
gconv: Replace norm_add_slashes with __gconv_norm_add_slashes
2017-06-19 Florian Weimer <fweimer@redhat.com>
Adhemerval Zanella <adhemerval.zanella@linaro.org>
* iconv/Makefile (routine): Add norm_add_slashes.
* iconv/norm_add_slashes.c: New file, extracted from
iconv/gconv_int.h.
* iconv/gconv_int.h (norm_add_slashes): Remove.
(__gconv_norm_add_slashes): Declare.
* wcsmbs/wcsmbsload.c (__wcsmbs_load_conv): Use
__gconv_norm_add_slashes.
* intl/dcigettext.c (_nl_find_msg): Likewise. Simplify !_LIBC
case.
diff --git a/iconv/Makefile b/iconv/Makefile
index b2fead0..df82b0d 100644
--- a/iconv/Makefile
+++ b/iconv/Makefile
@@ -25,7 +25,8 @@ include ../Makeconfig
headers = iconv.h gconv.h
routines = iconv_open iconv iconv_close \
gconv_open gconv gconv_close gconv_db gconv_conf \
- gconv_builtin gconv_simple gconv_trans gconv_cache
+ gconv_builtin gconv_simple gconv_trans gconv_cache \
+ norm_add_slashes
routines += gconv_dl
vpath %.c ../locale/programs ../intl
diff --git a/iconv/gconv_int.h b/iconv/gconv_int.h
index 85a67ad..7a54e0f 100644
--- a/iconv/gconv_int.h
+++ b/iconv/gconv_int.h
@@ -121,38 +121,13 @@ extern const char *__gconv_path_envvar attribute_hidden;
__libc_lock_define (extern, __gconv_lock attribute_hidden)
-/* The gconv functions expects the name to be in upper case and complete,
- including the trailing slashes if necessary. */
-#define norm_add_slashes(str,suffix) \
- ({ \
- const char *cp = (str); \
- char *result; \
- char *tmp; \
- size_t cnt = 0; \
- const size_t suffix_len = strlen (suffix); \
- \
- while (*cp != '\0') \
- if (*cp++ == '/') \
- ++cnt; \
- \
- tmp = result = __alloca (cp - (str) + 3 + suffix_len); \
- cp = (str); \
- while (*cp != '\0') \
- *tmp++ = __toupper_l (*cp++, _nl_C_locobj_ptr); \
- if (cnt < 2) \
- { \
- *tmp++ = '/'; \
- if (cnt < 1) \
- { \
- *tmp++ = '/'; \
- if (suffix_len != 0) \
- tmp = __mempcpy (tmp, suffix, suffix_len); \
- } \
- } \
- *tmp = '\0'; \
- result; \
- })
-
+/* Convert NAME of NAME_LEN bytes to the form expected by the gconv
+ functions, including the trailing slashes if necessary. The caller
+ has to free the returned string. Return NULL on allocation
+ failure. */
+char *__gconv_norm_add_slashes (const char *name, size_t name_len,
+ const char *suffix)
+ attribute_hidden;
/* Return in *HANDLE decriptor for transformation from FROMSET to TOSET. */
extern int __gconv_open (const char *toset, const char *fromset,
diff --git a/iconv/norm_add_slashes.c b/iconv/norm_add_slashes.c
new file mode 100644
index 0000000..f457077
--- /dev/null
+++ b/iconv/norm_add_slashes.c
@@ -0,0 +1,85 @@
+/* Normalize the charset name and add a suffix with slashes.
+ Copyright (C) 1997-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <gconv_int.h>
+
+#define CHAR_ARRAY_INITIAL_SIZE 0
+#include <malloc/char_array-skeleton.c>
+
+char *
+__gconv_norm_add_slashes (const char *name, size_t name_len,
+ const char *suffix)
+{
+#if 0
+ const char *name_end = name + name_len;
+ const char *cp = name;
+ char *result;
+ char *tmp;
+ size_t cnt = 0;
+ const size_t suffix_len = strlen (suffix);
+
+ while (cp != name_end)
+ if (*cp++ == '/')
+ ++cnt;
+
+ tmp = result = malloc (name_len + 3 + suffix_len);
+ if (result == NULL)
+ return NULL;
+ cp = name;
+ while (cp != name_end)
+ *tmp++ = __toupper_l (*cp++, _nl_C_locobj_ptr);
+ if (cnt < 2)
+ {
+ *tmp++ = '/';
+ if (cnt < 1)
+ {
+ *tmp++ = '/';
+ if (suffix_len != 0)
+ tmp = __mempcpy (tmp, suffix, suffix_len);
+ }
+ }
+ *tmp = '\0';
+ return result;
+#endif
+
+ size_t cnt = 0;
+ for (size_t i = 0; i < name_len; i++)
+ if (name[i] == '/')
+ cnt++;
+
+ struct char_array result;
+ if (!char_array_init_str_size (&result, name, name_len))
+ return NULL;
+
+ for (size_t i = 0; i < char_array_length (&result); i++)
+ *char_array_at (&result, i) = __toupper_l (name[i], _nl_C_locobj_ptr);
+
+ if (cnt < 2)
+ {
+ if (!char_array_append_str (&result, "/"))
+ return NULL;
+ if (cnt < 1)
+ {
+ if (!char_array_append_str (&result, "/")
+ | !char_array_append_str (&result, suffix))
+ return NULL;
+ }
+ }
+
+ return char_array_finalize (&result, NULL);
+}
diff --git a/intl/dcigettext.c b/intl/dcigettext.c
index f63b34b..0e79b1f 100644
--- a/intl/dcigettext.c
+++ b/intl/dcigettext.c
@@ -1109,25 +1109,24 @@ _nl_find_msg (struct loaded_l10nfile *domain_file,
{
size_t len;
char *charset;
- const char *outcharset;
+ char *outcharset;
charsetstr += strlen ("charset=");
len = strcspn (charsetstr, " \t\n");
- charset = (char *) alloca (len + 1);
-# if defined _LIBC || HAVE_MEMPCPY
- *((char *) mempcpy (charset, charsetstr, len)) = '\0';
-# else
- memcpy (charset, charsetstr, len);
- charset[len] = '\0';
-# endif
-
- outcharset = encoding;
-
# ifdef _LIBC
/* We always want to use transliteration. */
- outcharset = norm_add_slashes (outcharset, "TRANSLIT");
- charset = norm_add_slashes (charset, "");
+ charset = __gconv_norm_add_slashes (charsetstr, len, "");
+ outcharset = __gconv_norm_add_slashes
+ (encoding, strlen (encoding), "TRANSLIT");
+ if (charset == NULL || outcharset == NULL)
+ {
+ free ((char *) encoding);
+ free (outcharset);
+ free (charset);
+ goto unlock_fail;
+ }
+
int r = __gconv_open (outcharset, charset, &convd->conv,
GCONV_AVOID_NOCONV);
if (__builtin_expect (r != __GCONV_OK, 0))
@@ -1139,6 +1138,8 @@ _nl_find_msg (struct loaded_l10nfile *domain_file,
{
gl_rwlock_unlock (domain->conversions_lock);
free ((char *) encoding);
+ free (outcharset);
+ free (charset);
return NULL;
}
@@ -1151,27 +1152,31 @@ _nl_find_msg (struct loaded_l10nfile *domain_file,
# if (((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2) \
&& !defined __UCLIBC__) \
|| _LIBICONV_VERSION >= 0x0105
+ charset = strndup (charsetstr, len);
if (strchr (outcharset, '/') == NULL)
{
- char *tmp;
-
- len = strlen (outcharset);
- tmp = (char *) alloca (len + 10 + 1);
- memcpy (tmp, outcharset, len);
- memcpy (tmp + len, "//TRANSLIT", 10 + 1);
- outcharset = tmp;
-
- convd->conv = iconv_open (outcharset, charset);
-
- freea (outcharset);
+ if (asprintf (&outcharset, "%s//TRANSLIT",
+ encoding) < 0)
+ outcharset = NULL;
}
else
+ outcharset = strdup (encoding);
+ if (charset == NULL || outcharset == NULL)
+ {
+ gl_rwlock_unlock (domain->conversions_lock);
+ free (outcharset);
+ free (charset);
+ free ((char *) encoding);
+ return NULL;
+ }
# endif
- convd->conv = iconv_open (outcharset, charset);
+ convd->conv = iconv_open (outcharset, charset);
# endif
# endif
-
- freea (charset);
+ free (outcharset);
+ free (charset);
+ /* Do not free encoding here because
+ convd->encoding takes ownership. */
}
}
}
diff --git a/wcsmbs/wcsmbsload.c b/wcsmbs/wcsmbsload.c
index 656cc0a..cf7f815 100644
--- a/wcsmbs/wcsmbsload.c
+++ b/wcsmbs/wcsmbsload.c
@@ -160,7 +160,6 @@ __wcsmbs_load_conv (struct __locale_data *new_category)
{
/* We must find the real functions. */
const char *charset_name;
- const char *complete_name;
struct gconv_fcts *new_fcts;
int use_translit;
@@ -177,8 +176,11 @@ __wcsmbs_load_conv (struct __locale_data *new_category)
/* Normalize the name and add the slashes necessary for a
complete lookup. */
- complete_name = norm_add_slashes (charset_name,
- use_translit ? "TRANSLIT" : "");
+ char *complete_name = __gconv_norm_add_slashes
+ (charset_name, strlen (charset_name),
+ use_translit ? "TRANSLIT" : "");
+ if (complete_name ==NULL)
+ goto failed;
/* It is not necessary to use transliteration in this direction
since the internal character set is supposed to be able to
@@ -188,6 +190,7 @@ __wcsmbs_load_conv (struct __locale_data *new_category)
if (new_fcts->towc != NULL)
new_fcts->tomb = __wcsmbs_getfct (complete_name, "INTERNAL",
&new_fcts->tomb_nsteps);
+ free (complete_name);
/* If any of the conversion functions is not available we don't
use any since this would mean we cannot convert back and
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=e7ffd8ee94da45cb3433c29d36f4fd96bbd6b42a
commit e7ffd8ee94da45cb3433c29d36f4fd96bbd6b42a
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Mon Jun 5 21:21:46 2017 -0300
malloc: Add specialized dynarray for C strings
This patch adds an specialized dynarray to manage C strings using the
dynarray internal implementation. It uses some private fields from
dynarray and thus it provided specific files to access and manage
the internal string buffer.
For instance:
struct char_array str;
// str == "testing"
char_array_init_str (&str, "testing");
// c == 's'
char c = char_array_pos (&str, 2);
// str = "testing2"
char_array_set_str (&str, "testing2");
// str = "testi"
char_array_erase (&str, 5);
// str = "123testi"
char_array_prepend_str (&str, "123");
// len = 8
size_t len = char_array_length (&str);
// str = "123testi456"
char_array_append_str (&str, "456");
// str = "123testi789"
char_array_replace_str_pos (&str, 7, "789", 3);
The provided function are not extensive and meant mainly to be use in
subsequent glob implementation cleanup. For internal object consistency
only the function provided by char_array.c should be used, including
internal object manipulation.
To check for possible overflows in internal size manipulation a new
function, check_add_wrapv_size_t, is added on malloc-internal. It basically
return whether the addition of two size_t overflows.
Checked on x86_64-linux-gnu.
* malloc/Makefile (test-internal): Add tst-char_array.
(routines): Add dynarray_overflow_failure and char_array-impl.
* malloc/Versions [GLIBC_PRIVATE] (libc): Add
__libc_dynarray_overflow_failure, __char_array_set_str_size,
__char_array_erase, __char_array_prepend_str_size, and
__char_array_replace_str_pos.
* malloc/char_array-impl.c: New file.
* malloc/char_array-skeleton.c: Likewise.
* malloc/char_array.h: Likewise.
* malloc/tst-char-array.c: Likewise.
* malloc/dynarray_overflow_failure.c: Likewise.
* malloc/malloc-internal.h (check_add_overflow_size_t): New function.
diff --git a/malloc/Makefile b/malloc/Makefile
index 3fa395b..7e8aa29 100644
--- a/malloc/Makefile
+++ b/malloc/Makefile
@@ -47,6 +47,7 @@ tests-internal += \
tst-dynarray \
tst-dynarray-fail \
tst-dynarray-at-fail \
+ tst-char_array
ifneq (no,$(have-tunables))
tests += tst-malloc-usable-tunables
@@ -59,7 +60,7 @@ test-srcs = tst-mtrace
routines = malloc morecore mcheck mtrace obstack reallocarray \
scratch_buffer_grow scratch_buffer_grow_preserve \
scratch_buffer_set_array_size \
- dynarray_at_failure \
+ dynarray_at_failure dynarray_overflow_failure \
dynarray_emplace_enlarge \
dynarray_finalize \
dynarray_resize \
@@ -69,6 +70,7 @@ routines = malloc morecore mcheck mtrace obstack reallocarray \
alloc_buffer_copy_bytes \
alloc_buffer_copy_string \
alloc_buffer_create_failure \
+ char_array-impl
install-lib := libmcheck.a
non-lib.a := libmcheck.a
diff --git a/malloc/Versions b/malloc/Versions
index 2357cff..b21fe59 100644
--- a/malloc/Versions
+++ b/malloc/Versions
@@ -81,6 +81,7 @@ libc {
# dynarray support
__libc_dynarray_at_failure;
+ __libc_dynarray_overflow_failure;
__libc_dynarray_emplace_enlarge;
__libc_dynarray_finalize;
__libc_dynarray_resize;
@@ -92,5 +93,11 @@ libc {
__libc_alloc_buffer_copy_bytes;
__libc_alloc_buffer_copy_string;
__libc_alloc_buffer_create_failure;
+
+ # char_array support
+ __char_array_set_str_size;
+ __char_array_erase;
+ __char_array_prepend_str_size;
+ __char_array_replace_str_pos;
}
}
diff --git a/malloc/char_array-impl.c b/malloc/char_array-impl.c
new file mode 100644
index 0000000..5a56bbc
--- /dev/null
+++ b/malloc/char_array-impl.c
@@ -0,0 +1,57 @@
+/* Specialized dynarray for C strings. Implementation file.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <malloc/char_array.h>
+
+void
+__char_array_set_str_size (struct dynarray_header *header, const char *str,
+ size_t size)
+{
+ *((char *) mempcpy (header->array, str, size)) = '\0';
+ header->used = size + 1;
+}
+libc_hidden_def (__char_array_set_str_size)
+
+void
+__char_array_erase (struct dynarray_header *header, size_t pos)
+{
+ char *ppos = header->array + pos;
+ char *lpos = header->array + header->used;
+ ptrdiff_t size = lpos - ppos;
+ memmove (ppos, ppos + 1, size);
+ header->used--;
+}
+libc_hidden_def (__char_array_erase)
+
+void
+__char_array_prepend_str_size (struct dynarray_header *header,
+ const char *str, size_t size, size_t used)
+{
+ memmove (header->array + size, header->array, used);
+ memcpy (header->array, str, size);
+}
+libc_hidden_def (__char_array_prepend_str_size)
+
+void
+__char_array_replace_str_pos (struct dynarray_header *header, size_t pos,
+ const char *str, size_t len)
+{
+ char *start = header->array + pos;
+ *(char *) mempcpy (start, str, len) = '\0';
+}
+libc_hidden_def (__char_array_replace_str_pos)
diff --git a/malloc/char_array-skeleton.c b/malloc/char_array-skeleton.c
new file mode 100644
index 0000000..7ad274e
--- /dev/null
+++ b/malloc/char_array-skeleton.c
@@ -0,0 +1,263 @@
+/* Specialized dynarray for C strings.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* This file provides a dynamic C string with an initial stack allocated
+ buffer. Since it is based on dynarray, it provided dynamic size
+ expansion and heap usage for large strings.
+
+ The following parameters are optional:
+
+ CHAR_ARRAY_INITIAL_SIZE
+ The size of the statically allocated array (default is 256). It will
+ be used to define DYNARRAY_INITIAL_SIZE.
+
+ The following functions are provided:
+
+ bool char_array_init_empty (struct char_array *);
+ bool char_array_init_str (struct char_array *, const char *);
+ bool char_array_init_str_size (struct char_array *, const char *, size_t);
+ bool char_array_is_empty (struct char_array *);
+ const char *char_array_str (struct char_array *);
+ char char_array_pos (struct char_array *, size_t);
+ size_t char_array_length (struct char_array *);
+ bool char_array_set_str (struct char_array *, const char *);
+ bool char_array_set_str_size (struct char_array *, const char *, size_t);
+ void char_array_erase (struct char_array *, size_t);
+ bool char_array_crop (struct char_array *, size_t);
+ bool char_array_prepend_str (struct char_array *, const char *);
+ bool char_array_append_str (struct char_array *, const char *);
+ bool char_array_replace_str_pos (struct char_array *, size_t, const char *,
+ size_t);
+
+ For instance:
+
+ struct char_array str;
+ // str == "testing";
+ char_array_init_str (&str, "testing");
+ // c == 's'
+ char c = char_array_pos (&str, 2);
+ // str = "testing2";
+ char_array_set_str (&str, "testing2");
+ // str = "testi";
+ char_array_erase (&str, 5);
+ // str = "123testi";
+ char_array_prepend_str (&str, "123");
+ // len = 8;
+ size_t len = char_array_length (&str);
+ // str = "123testi456";
+ char_array_append_str (&str, "456");
+ // str = "123testi789";
+ char_array_replace_str_pos (&str, 7, "789", 3);
+ */
+
+#define DYNARRAY_STRUCT char_array
+#define DYNARRAY_ELEMENT char
+#define DYNARRAY_PREFIX char_array_
+#ifndef CHAR_ARRAY_INITIAL_SIZE
+# define CHAR_ARRAY_INITIAL_SIZE 256
+#endif
+#define DYNARRAY_INITIAL_SIZE CHAR_ARRAY_INITIAL_SIZE
+#include <malloc/dynarray-skeleton.c>
+
+#include <malloc/malloc-internal.h>
+#include <malloc/char_array.h>
+
+/* Return a const char for the internal C string handled by 'array'. */
+__attribute__ ((unused, nonnull (1)))
+static const char *
+char_array_str (struct char_array *array)
+{
+ return char_array_begin (array);
+}
+
+/* Return the character at position 'pos' from the char_array 'array'. */
+__attribute__ ((unused, nonnull (1)))
+static char
+char_array_pos (struct char_array *array, size_t pos)
+{
+ return *char_array_at (array, pos);
+}
+
+/* Calculate the length of the string, excluding the terminating null. */
+__attribute__ ((unused, nonnull (1)))
+static size_t
+char_array_length (struct char_array *array)
+{
+ /* Exclude the final '\0'. */
+ return array->dynarray_header.used - 1;
+}
+
+/* Copy up 'size' bytes from string 'str' to char_array 'array'. A final
+ '\0' is appended in the char_array. */
+__attribute__ ((unused, nonnull (1, 2)))
+static bool
+char_array_set_str_size (struct char_array *array, const char *str,
+ size_t size)
+{
+ size_t newsize;
+ if (check_add_overflow_size_t (size, 1, &newsize))
+ __libc_dynarray_overflow_failure (size, 1);
+
+ if (!char_array_resize (array, newsize))
+ return false;
+
+ __char_array_set_str_size (&array->dynarray_abstract, str, size);
+ return true;
+}
+
+/* Copy the contents of string 'str' to char_array 'array', including the
+ final '\0'. */
+__attribute__ ((unused, nonnull (1, 2)))
+static bool
+char_array_set_str (struct char_array *array, const char *str)
+{
+ return char_array_set_str_size (array, str, strlen (str));
+}
+
+/* Initialize the char_array 'array' and sets it to an empty string (""). */
+__attribute__ ((unused, nonnull (1)))
+static bool
+char_array_init_empty (struct char_array *array)
+{
+ char_array_init (array);
+ return char_array_set_str (array, "");
+}
+
+/* Initialize the char_array 'array' and copy the content of string 'str'. */
+__attribute__ ((unused, nonnull (1, 2)))
+static bool
+char_array_init_str (struct char_array *array, const char *str)
+{
+ char_array_init (array);
+ return char_array_set_str (array, str);
+}
+
+/* Initialize the char_array 'array' and copy the content of string 'str'
+ up to 'size' characteres. */
+__attribute__ ((unused, nonnull (1, 2)))
+static bool
+char_array_init_str_size (struct char_array *array, const char *str,
+ size_t size)
+{
+ char_array_init (array);
+ return char_array_set_str_size (array, str, size);
+}
+
+/* Return if the char_array contain any characteres. */
+__attribute__ ((unused, nonnull (1)))
+static bool
+char_array_is_empty (struct char_array *array)
+{
+ return *char_array_begin (array) == '\0';
+}
+
+/* Remove the byte at position 'pos' from char_array 'array'. The contents
+ are moved internally if the position is not at the end of the internal
+ buffer. */
+__attribute__ ((unused, nonnull (1)))
+static bool
+char_array_erase (struct char_array *array, size_t pos)
+{
+ if (pos >= array->dynarray_header.used - 1)
+ return false;
+
+ __char_array_erase (&array->dynarray_abstract, pos);
+ return true;
+}
+
+/* Resize the char_array 'array' to size 'count' maintaining the ending
+ '\0' byte. */
+__attribute__ ((unused, nonnull (1)))
+static bool
+char_array_crop (struct char_array *array, size_t size)
+{
+ if (size >= (array->dynarray_header.used - 1)
+ || !char_array_resize (array, size + 1))
+ return false;
+
+ array->dynarray_header.array[size] = '\0';
+ return true;
+}
+
+/* Prepend the contents of string 'str' to char_array 'array', including the
+ final '\0' byte. */
+__attribute__ ((unused, nonnull (1, 2)))
+static bool
+char_array_prepend_str (struct char_array *array, const char *str)
+{
+ size_t size = strlen (str);
+ /* Resizing the array might change its used elements and we need below
+ to correct copy the elements. */
+ size_t used = array->dynarray_header.used;
+
+ size_t newsize;
+ if (check_add_overflow_size_t (used, size, &newsize))
+ __libc_dynarray_overflow_failure (used, size);
+
+ /* Make room for the string and copy it. */
+ if (!char_array_resize (array, newsize))
+ return false;
+ __char_array_prepend_str_size (&array->dynarray_abstract, str, size, used);
+ return true;
+}
+
+/* Append the contents of string 'str' to char_array 'array, including the
+ final '\0' byte. */
+__attribute__ ((unused, nonnull (1, 2)))
+static bool
+char_array_append_str (struct char_array *array, const char *str)
+{
+ size_t size = strlen (str);
+ /* Resizing the array might change its used elements and it used it below
+ to correct copy the elements. */
+ size_t used = array->dynarray_header.used - 1;
+
+ /* 'used' does account for final '\0', so there is no need to add
+ an extra element to calculate the final required size. */
+ size_t newsize;
+ if (check_add_overflow_size_t (used + 1, size, &newsize))
+ __libc_dynarray_overflow_failure (used + 1, size);
+
+ if (!char_array_resize (array, newsize))
+ return false;
+
+ /* Start to append at '\0' up to string length and add a final '\0'. */
+ *(char*) mempcpy (array->dynarray_header.array + used, str, size) = '\0';
+ return true;
+}
+
+/* Replace the contents starting of position 'pos' of char_array 'array'
+ with the contents of string 'str' up to 'len' bytes. A final '\0'
+ is appended in the string. */
+__attribute__ ((unused, nonnull (1, 3)))
+static bool
+char_array_replace_str_pos (struct char_array *array, size_t pos,
+ const char *str, size_t len)
+{
+ if (pos > array->dynarray_header.used)
+ __libc_dynarray_at_failure (array->dynarray_header.used, pos);
+
+ size_t newsize;
+ if (check_add_overflow_size_t (pos, len, &newsize)
+ || check_add_overflow_size_t (newsize, 1, &newsize)
+ || !char_array_resize (array, newsize))
+ return false;
+
+ __char_array_replace_str_pos (&array->dynarray_abstract, pos, str, len);
+ return true;
+}
diff --git a/malloc/char_array.h b/malloc/char_array.h
new file mode 100644
index 0000000..c696673
--- /dev/null
+++ b/malloc/char_array.h
@@ -0,0 +1,53 @@
+/* Specialized dynarray for C strings. Shared definitions.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _CHAR_ARRAY_H
+#define _CHAR_ARRAY_H
+
+#include <malloc/dynarray.h>
+
+/* Internal funciton. Set the dynarray to the content of the string STR up
+ to SIZE bytes. The dynarray must be resized previously. */
+void __char_array_set_str_size (struct dynarray_header *, const char *str,
+ size_t size);
+
+/* Internal function. Remove the character at position POS from dynarray.
+ The position must be a valid one. */
+void __char_array_erase (struct dynarray_header *, size_t pos);
+
+/* Internal function. Prepend the content of string STR up to SIZE bytes to
+ dynarray by moving USED bytes forward. The dynarray must be resized
+ previously. */
+void __char_array_prepend_str_size (struct dynarray_header *,
+ const char *str, size_t size,
+ size_t used);
+
+/* Internal function. Replace the content of dynarray starting at position
+ POS with the content of string STR up to LEN bytes. The dynarray must
+ be resize previously and STR must contain at least LEN bytes. */
+void __char_array_replace_str_pos (struct dynarray_header *, size_t pos,
+ const char *str, size_t len);
+
+#ifndef _ISOMAC
+libc_hidden_proto (__char_array_set_str_size)
+libc_hidden_proto (__char_array_erase)
+libc_hidden_proto (__char_array_prepend_str_size)
+libc_hidden_proto (__char_array_replace_str_pos)
+#endif
+
+#endif
diff --git a/malloc/dynarray.h b/malloc/dynarray.h
index 5888bcb..bb52b0f 100644
--- a/malloc/dynarray.h
+++ b/malloc/dynarray.h
@@ -168,12 +168,21 @@ bool __libc_dynarray_finalize (struct dynarray_header *list, void *scratch,
void __libc_dynarray_at_failure (size_t size, size_t index)
__attribute__ ((noreturn));
+/* Internal function. TErminate the process after an overflow in
+ new size allocation. SIZE is the current number of elements in
+ dynamic array and INCR is the new elements to add on current
+ size. */
+void __libc_dynarray_overflow_failure (size_t size, size_t incr)
+ __attribute__ ((noreturn));
+
#ifndef _ISOMAC
libc_hidden_proto (__libc_dynarray_emplace_enlarge)
libc_hidden_proto (__libc_dynarray_resize)
libc_hidden_proto (__libc_dynarray_resize_clear)
libc_hidden_proto (__libc_dynarray_finalize)
libc_hidden_proto (__libc_dynarray_at_failure)
+libc_hidden_proto (__libc_dynarray_overflow_failure)
+
#endif
#endif /* _DYNARRAY_H */
diff --git a/malloc/dynarray_overflow_failure.c b/malloc/dynarray_overflow_failure.c
new file mode 100644
index 0000000..14936b0
--- /dev/null
+++ b/malloc/dynarray_overflow_failure.c
@@ -0,0 +1,31 @@
+/* Report an dynamic array size overflow condition.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <dynarray.h>
+#include <stdio.h>
+
+void
+__libc_dynarray_overflow_failure (size_t size, size_t incr)
+{
+ char buf[200];
+ __snprintf (buf, sizeof (buf), "Fatal glibc error: "
+ "new size overflows (old %zu and increment %zu)\n",
+ size, incr);
+ __libc_fatal (buf);
+}
+libc_hidden_def (__libc_dynarray_overflow_failure)
diff --git a/malloc/malloc-internal.h b/malloc/malloc-internal.h
index 6a62717..ac845dc 100644
--- a/malloc/malloc-internal.h
+++ b/malloc/malloc-internal.h
@@ -91,4 +91,18 @@ check_mul_overflow_size_t (size_t left, size_t right, size_t *result)
#endif
}
+/* Set *R = A + B. Return true if the answer is mathematically incorrect due
+ to overflow; in this case, *R is the low order bits of the correct
+ answer. */
+static inline bool
+check_add_overflow_size_t (size_t a, size_t b, size_t *r)
+{
+#if 5 <= __GNUC__
+ return __builtin_add_overflow (a, b, r);
+#else
+ *r = a + b;
+ return *r < a;
+#endif
+}
+
#endif /* _MALLOC_INTERNAL_H */
diff --git a/malloc/tst-char_array.c b/malloc/tst-char_array.c
new file mode 100644
index 0000000..f55acb9
--- /dev/null
+++ b/malloc/tst-char_array.c
@@ -0,0 +1,110 @@
+/* Test for char_array.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <string.h>
+
+#include <malloc/char_array-skeleton.c>
+
+#include <malloc.h>
+#include <mcheck.h>
+#include <stdint.h>
+#include <support/check.h>
+#include <support/support.h>
+
+static int
+do_test (void)
+{
+ mtrace ();
+
+ {
+ struct char_array str;
+ TEST_VERIFY_EXIT (char_array_init_empty (&str) == true);
+ TEST_VERIFY_EXIT (char_array_length (&str) == 0);
+ TEST_VERIFY_EXIT (char_array_is_empty (&str) == true);
+ TEST_VERIFY_EXIT (strcmp (char_array_str (&str), "") == 0);
+ char_array_free (&str);
+ }
+
+ {
+ struct char_array str;
+ TEST_VERIFY_EXIT (char_array_init_str (&str, "testing"));
+ TEST_VERIFY_EXIT (char_array_length (&str) == strlen ("testing"));
+ TEST_VERIFY_EXIT (char_array_pos (&str, 2) == 's');
+ TEST_VERIFY_EXIT (char_array_is_empty (&str) == false);
+ TEST_VERIFY_EXIT (strcmp (char_array_str (&str), "testing") == 0);
+ char_array_free (&str);
+ }
+
+ {
+ struct char_array str;
+ TEST_VERIFY_EXIT (char_array_init_str_size (&str, "testing", 4));
+ TEST_VERIFY_EXIT (char_array_length (&str) == 4);
+ TEST_VERIFY_EXIT (char_array_pos (&str, 2) == 's');
+ TEST_VERIFY_EXIT (char_array_is_empty (&str) == false);
+ TEST_VERIFY_EXIT (strcmp (char_array_str (&str), "test") == 0);
+ char_array_free (&str);
+ }
+
+ {
+ struct char_array str;
+ TEST_VERIFY_EXIT (char_array_init_str (&str, "testing"));
+ TEST_VERIFY_EXIT (char_array_set_str (&str, "abcdef"));
+ TEST_VERIFY_EXIT (strcmp (char_array_str (&str), "abcdef") == 0);
+ TEST_VERIFY_EXIT (char_array_set_str_size (&str, "abcdef", 4));
+ TEST_VERIFY_EXIT (strcmp (char_array_str (&str), "abcd") == 0);
+ char_array_free (&str);
+ }
+
+ {
+ struct char_array str;
+ TEST_VERIFY_EXIT (char_array_init_str (&str, "testing"));
+ TEST_VERIFY_EXIT (char_array_erase (&str, 4) == true);
+ TEST_VERIFY_EXIT (char_array_length (&str) == strlen ("testing") - 1);
+ TEST_VERIFY_EXIT (strcmp (char_array_str (&str), "testng") == 0);
+ TEST_VERIFY_EXIT (char_array_erase (&str, char_array_length (&str))
+ == false);
+ TEST_VERIFY_EXIT (char_array_length (&str) == strlen ("testing") - 1);
+ TEST_VERIFY_EXIT (char_array_erase (&str, char_array_length (&str) - 1)
+ == true);
+ TEST_VERIFY_EXIT (char_array_length (&str) == strlen ("testing") - 2);
+ TEST_VERIFY_EXIT (strcmp (char_array_str (&str), "testn") == 0);
+ char_array_free (&str);
+ }
+
+ {
+ struct char_array str;
+ TEST_VERIFY_EXIT (char_array_init_str (&str, "test"));
+ TEST_VERIFY_EXIT (char_array_prepend_str (&str, "123"));
+ TEST_VERIFY_EXIT (strcmp (char_array_str (&str), "123test") == 0);
+ TEST_VERIFY_EXIT (char_array_length (&str) == strlen ("123test"));
+ TEST_VERIFY_EXIT (char_array_append_str (&str, "456"));
+ TEST_VERIFY_EXIT (strcmp (char_array_str (&str), "123test456") == 0);
+ TEST_VERIFY_EXIT (char_array_length (&str) == strlen ("123test456"));
+ TEST_VERIFY_EXIT (char_array_replace_str_pos (&str, 7, "789", 3));
+ TEST_VERIFY_EXIT (strcmp (char_array_str (&str), "123test789") == 0);
+ TEST_VERIFY_EXIT (char_array_length (&str) == strlen ("123test789"));
+ TEST_VERIFY_EXIT (char_array_crop (&str, 7));
+ TEST_VERIFY_EXIT (char_array_length (&str) == 7);
+ TEST_VERIFY_EXIT (strcmp (char_array_str (&str), "123test") == 0);
+ char_array_free (&str);
+ }
+
+ return 0;
+}
+
+#include <support/test-driver.c>
-----------------------------------------------------------------------
hooks/post-receive
--
GNU C Library master sources