summaryrefslogtreecommitdiff
path: root/posix/glob.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2006-09-25 15:33:09 +0000
committerUlrich Drepper <drepper@redhat.com>2006-09-25 15:33:09 +0000
commitf1122ec3ae47bbf40e38bec56d879502005397b1 (patch)
tree8ac3b9d7a104815f0f3ff1b6b796827823f2ac90 /posix/glob.c
parent457b559e2ec7bd66c6da9e99d27f0d1723da4874 (diff)
[BZ #3252, BZ #3253]cvs/fedora-glibc-20060925T1535
2006-09-25 Jakub Jelinek <jakub@redhat.com> [BZ #3252] * sysdeps/unix/sysv/linux/powerpc/fchownat.c (fchownat): Handle only fchownat syscall and __ASSUME_LCHOWN_SYSCALL case inline, call __{,l}chown to handle the rest. * sysdeps/unix/sysv/linux/i386/fchownat.c (fchownat): Handle only fchownat syscall and __ASSUME_32BITUIDS case inline, call __{,l}chown to handle the rest. * sysdeps/unix/sysv/linux/sparc/sparc32/fchownat.c: Include i386/fchownat.c. * sysdeps/unix/sysv/linux/s390/s390-32/fchownat.c: Likewise. * sysdeps/unix/sysv/linux/sh/fchownat.c: Likewise. [BZ #3253] * posix/glob.c (glob_in_dir): Don't alloca one struct globlink at a time, rather allocate increasingly bigger arrays of pointers, if possible with alloca, if too large with malloc. 2006-09-24 Jakub Jelinek <jakub@redhat.com> * sysdeps/powerpc/fpu/libm-test-ulps: Updated. * sysdeps/ieee754/ldbl-128/s_lrintl.c (__lrintl): Fix 2 typos.
Diffstat (limited to 'posix/glob.c')
-rw-r--r--posix/glob.c142
1 files changed, 88 insertions, 54 deletions
diff --git a/posix/glob.c b/posix/glob.c
index d2a9981e31..630d54063a 100644
--- a/posix/glob.c
+++ b/posix/glob.c
@@ -1090,16 +1090,25 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
{
size_t dirlen = strlen (directory);
void *stream = NULL;
- struct globlink
+ struct globnames
{
- struct globlink *next;
- char *name;
+ struct globnames *next;
+ size_t count;
+ char *name[64];
};
- struct globlink *names = NULL;
- size_t nfound;
+#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;
+ size_t nfound = 0;
+ size_t allocasize = sizeof (init_names);
+ size_t cur = 0;
int meta;
int save;
+ init_names.next = NULL;
+ init_names.count = INITIAL_COUNT;
+
meta = __glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE));
if (meta == 0 && (flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
{
@@ -1107,7 +1116,6 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
characters and we must not return an error therefore the
result will always contain exactly one name. */
flags |= GLOB_NOCHECK;
- nfound = 0;
}
else if (meta == 0 &&
((flags & GLOB_NOESCAPE) || strchr (pattern, '\\') == NULL))
@@ -1128,8 +1136,6 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
/* We found this file to be existing. Now tell the rest
of the function to copy this name into the result. */
flags |= GLOB_NOCHECK;
-
- nfound = 0;
}
else
{
@@ -1137,12 +1143,10 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
{
/* This is a special case for matching directories like in
"*a/". */
- names = (struct globlink *) __alloca (sizeof (struct globlink));
- names->name = (char *) malloc (1);
- if (names->name == NULL)
+ names->name[cur] = (char *) malloc (1);
+ if (names->name[cur] == NULL)
goto memory_error;
- names->name[0] = '\0';
- names->next = NULL;
+ *names->name[cur++] = '\0';
nfound = 1;
meta = 0;
}
@@ -1157,7 +1161,6 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
&& ((errfunc != NULL && (*errfunc) (directory, errno))
|| (flags & GLOB_ERR)))
return GLOB_ABORTED;
- nfound = 0;
meta = 0;
}
else
@@ -1168,7 +1171,6 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
| FNM_CASEFOLD
#endif
);
- nfound = 0;
flags |= GLOB_MAGCHAR;
while (1)
@@ -1224,15 +1226,30 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
|| link_exists_p (directory, dirlen, name, pglob,
flags))
{
- struct globlink *new = (struct globlink *)
- __alloca (sizeof (struct globlink));
+ if (cur == names->count)
+ {
+ struct globnames *newnames;
+ size_t count = names->count * 2;
+ size_t size = (sizeof (struct globnames)
+ + ((count - INITIAL_COUNT)
+ * sizeof (char *)));
+ allocasize += size;
+ if (__libc_use_alloca (allocasize))
+ newnames = names_alloca = __alloca (size);
+ else if ((newnames = malloc (size))
+ == NULL)
+ goto memory_error;
+ newnames->count = count;
+ newnames->next = names;
+ names = newnames;
+ cur = 0;
+ }
len = NAMLEN (d);
- new->name = (char *) malloc (len + 1);
- if (new->name == NULL)
+ names->name[cur] = (char *) malloc (len + 1);
+ if (names->name[cur] == NULL)
goto memory_error;
- *((char *) mempcpy (new->name, name, len)) = '\0';
- new->next = names;
- names = new;
+ *((char *) mempcpy (names->name[cur++], name, len))
+ = '\0';
++nfound;
}
}
@@ -1245,59 +1262,76 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
{
size_t len = strlen (pattern);
nfound = 1;
- names = (struct globlink *) __alloca (sizeof (struct globlink));
- names->next = NULL;
- names->name = (char *) malloc (len + 1);
- if (names->name == NULL)
+ names->name[cur] = (char *) malloc (len + 1);
+ if (names->name[cur] == NULL)
goto memory_error;
- *((char *) mempcpy (names->name, pattern, len)) = '\0';
+ *((char *) mempcpy (names->name[cur++], pattern, len)) = '\0';
}
+ int result = GLOB_NOMATCH;
if (nfound != 0)
{
- char **new_gl_pathv;
+ result = 0;
+ char **new_gl_pathv;
new_gl_pathv
= (char **) realloc (pglob->gl_pathv,
(pglob->gl_pathc + pglob->gl_offs + nfound + 1)
* sizeof (char *));
if (new_gl_pathv == NULL)
- goto memory_error;
- pglob->gl_pathv = new_gl_pathv;
+ {
+ memory_error:
+ while (1)
+ {
+ struct globnames *old = names;
+ for (size_t i = 0; i < cur; ++i)
+ free (names->name[i]);
+ names = names->next;
+ if (names == NULL)
+ break;
+ cur = names->count;
+ if (old == names_alloca)
+ names_alloca = names;
+ else
+ free (old);
+ }
+ result = GLOB_NOSPACE;
+ }
+ else
+ {
+ while (1)
+ {
+ struct globnames *old = names;
+ for (size_t i = 0; i < cur; ++i)
+ new_gl_pathv[pglob->gl_offs + pglob->gl_pathc++]
+ = names->name[i];
+ names = names->next;
+ if (names == NULL)
+ break;
+ cur = names->count;
+ if (old == names_alloca)
+ names_alloca = names;
+ else
+ free (old);
+ }
+
+ pglob->gl_pathv = new_gl_pathv;
- for (; names != NULL; names = names->next)
- pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc++] = names->name;
- pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
+ pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
- pglob->gl_flags = flags;
+ pglob->gl_flags = flags;
+ }
}
- save = errno;
if (stream != NULL)
{
+ save = errno;
if (flags & GLOB_ALTDIRFUNC)
(*pglob->gl_closedir) (stream);
else
closedir (stream);
+ __set_errno (save);
}
- __set_errno (save);
-
- return nfound == 0 ? GLOB_NOMATCH : 0;
- memory_error:
- {
- int save = errno;
- if (flags & GLOB_ALTDIRFUNC)
- (*pglob->gl_closedir) (stream);
- else
- closedir (stream);
- __set_errno (save);
- }
- while (names != NULL)
- {
- if (names->name != NULL)
- free (names->name);
- names = names->next;
- }
- return GLOB_NOSPACE;
+ return result;
}