summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDamien Miller <djm@cvs.openbsd.org>2011-09-22 06:27:30 +0000
committerDamien Miller <djm@cvs.openbsd.org>2011-09-22 06:27:30 +0000
commit2e36485a3a2199e923ce56f1ca9344cbd80ce691 (patch)
tree2efa6a2eda76749a424658f9efe78bfc9725b56f /lib
parent6cd47185b095fa022d3d52f071e7190a4b6699b6 (diff)
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 'lib')
-rw-r--r--lib/libc/gen/glob.c50
1 files changed, 44 insertions, 6 deletions
diff --git a/lib/libc/gen/glob.c b/lib/libc/gen/glob.c
index ca96dd01af5..fcc0c4120d9 100644
--- a/lib/libc/gen/glob.c
+++ b/lib/libc/gen/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.
@@ -126,16 +126,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 *);
@@ -545,9 +551,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);
}
@@ -558,6 +587,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];