summaryrefslogtreecommitdiffstats
path: root/openbsd-compat/glob.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2011-09-22 21:22:21 +1000
committerDamien Miller <djm@mindrot.org>2011-09-22 21:22:21 +1000
commite128a50e35eb4eabcf234ada07f07b8749b5e49c (patch)
tree327a45dccfa1654f7ba2b74a4c1fad20eef324e7 /openbsd-compat/glob.c
parentc4bf7dde9231194f4e38140a46e9957758317cb5 (diff)
- djm@cvs.openbsd.org 2011/09/22 06:27:29
[glob.c] fix GLOB_KEEPSTAT without GLOB_NOSORT; the implicit sort was being applied only to the gl_pathv vector and not the corresponding gl_statv array. reported in OpenSSH bz#1935; feedback and okay matthew@
Diffstat (limited to 'openbsd-compat/glob.c')
-rw-r--r--openbsd-compat/glob.c50
1 files changed, 44 insertions, 6 deletions
diff --git a/openbsd-compat/glob.c b/openbsd-compat/glob.c
index 85fccf4d..742b4b95 100644
--- a/openbsd-compat/glob.c
+++ b/openbsd-compat/glob.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: glob.c,v 1.37 2011/09/20 10:18:46 stsp Exp $ */
+/* $OpenBSD: glob.c,v 1.38 2011/09/22 06:27:29 djm Exp $ */
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
@@ -133,16 +133,22 @@ typedef char Char;
#define GLOB_LIMIT_STAT 128
#define GLOB_LIMIT_READDIR 16384
+/* Limit of recursion during matching attempts. */
+#define GLOB_LIMIT_RECUR 64
+
struct glob_lim {
size_t glim_malloc;
size_t glim_stat;
size_t glim_readdir;
};
-/* Limit of recursion during matching attempts. */
-#define GLOB_LIMIT_RECUR 64
+struct glob_path_stat {
+ char *gps_path;
+ struct stat *gps_stat;
+};
static int compare(const void *, const void *);
+static int compare_gps(const void *, const void *);
static int g_Ctoc(const Char *, char *, u_int);
static int g_lstat(Char *, struct stat *, glob_t *);
static DIR *g_opendir(Char *, glob_t *);
@@ -555,9 +561,32 @@ glob0(const Char *pattern, glob_t *pglob, struct glob_lim *limitp)
else
return(GLOB_NOMATCH);
}
- if (!(pglob->gl_flags & GLOB_NOSORT))
- qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
- pglob->gl_pathc - oldpathc, sizeof(char *), compare);
+ if (!(pglob->gl_flags & GLOB_NOSORT)) {
+ if ((pglob->gl_flags & GLOB_KEEPSTAT)) {
+ /* Keep the paths and stat info synced during sort */
+ struct glob_path_stat *path_stat;
+ int i;
+ int n = pglob->gl_pathc - oldpathc;
+ int o = pglob->gl_offs + oldpathc;
+
+ if ((path_stat = calloc(n, sizeof(*path_stat))) == NULL)
+ return GLOB_NOSPACE;
+ for (i = 0; i < n; i++) {
+ path_stat[i].gps_path = pglob->gl_pathv[o + i];
+ path_stat[i].gps_stat = pglob->gl_statv[o + i];
+ }
+ qsort(path_stat, n, sizeof(*path_stat), compare_gps);
+ for (i = 0; i < n; i++) {
+ pglob->gl_pathv[o + i] = path_stat[i].gps_path;
+ pglob->gl_statv[o + i] = path_stat[i].gps_stat;
+ }
+ free(path_stat);
+ } else {
+ qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
+ pglob->gl_pathc - oldpathc, sizeof(char *),
+ compare);
+ }
+ }
return(0);
}
@@ -568,6 +597,15 @@ compare(const void *p, const void *q)
}
static int
+compare_gps(const void *_p, const void *_q)
+{
+ const struct glob_path_stat *p = (const struct glob_path_stat *)_p;
+ const struct glob_path_stat *q = (const struct glob_path_stat *)_q;
+
+ return(strcmp(p->gps_path, q->gps_path));
+}
+
+static int
glob1(Char *pattern, Char *pattern_last, glob_t *pglob, struct glob_lim *limitp)
{
Char pathbuf[MAXPATHLEN];