diff options
author | Ulrich Drepper <drepper@redhat.com> | 2006-09-25 15:33:09 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2006-09-25 15:33:09 +0000 |
commit | f1122ec3ae47bbf40e38bec56d879502005397b1 (patch) | |
tree | 8ac3b9d7a104815f0f3ff1b6b796827823f2ac90 /posix/glob.c | |
parent | 457b559e2ec7bd66c6da9e99d27f0d1723da4874 (diff) | |
download | glibc-f1122ec3ae47bbf40e38bec56d879502005397b1.tar.gz glibc-f1122ec3ae47bbf40e38bec56d879502005397b1.tar.xz glibc-f1122ec3ae47bbf40e38bec56d879502005397b1.zip |
[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.c | 142 |
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; } |