summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Stephenson <pws@zsh.org>2016-07-18 16:56:34 +0100
committerPeter Stephenson <pws@zsh.org>2016-07-18 16:57:38 +0100
commit72e5fe7aab91e21d0d746ec7137a6e4e0b405e39 (patch)
treec6797d412f818c92bc502c1e6cf8d6f4887b737e
parentbd707b47875a5bc61b2bea2d7ffd2ed8738afcce (diff)
downloadzsh-72e5fe7aab91e21d0d746ec7137a6e4e0b405e39.tar.gz
zsh-72e5fe7aab91e21d0d746ec7137a6e4e0b405e39.zip
38879: Unmetafy file names for glob sort.
Test using Polish UTF-8 collation sequence that'w known to cause the problems.
-rw-r--r--ChangeLog6
-rw-r--r--Src/glob.c30
-rw-r--r--Test/D07multibyte.ztst17
3 files changed, 52 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index 89bb2399b..909101a2d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2016-07-18 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 38879: Src/glob.c, Test/D07multibyte.ztst: Ensure file names
+ are sorted unmetafied. Test using Polish UTF-8 collation
+ sequence.
+
2016-07-18 Mikael Magnusson <mikachu@gmail.com>
* 38785 (plus tweak): Completion/Zsh/Command/_print: add -v
diff --git a/Src/glob.c b/Src/glob.c
index 2051016ec..146b4dbbc 100644
--- a/Src/glob.c
+++ b/Src/glob.c
@@ -41,7 +41,10 @@
typedef struct gmatch *Gmatch;
struct gmatch {
+ /* Metafied file name */
char *name;
+ /* Unmetafied file name; embedded nulls can't occur in file names */
+ char *uname;
/*
* Array of sort strings: one for each GS_EXEC sort type in
* the glob qualifiers.
@@ -911,7 +914,8 @@ gmatchcmp(Gmatch a, Gmatch b)
for (i = gf_nsorts, s = gf_sortlist; i; i--, s++) {
switch (s->tp & ~GS_DESC) {
case GS_NAME:
- r = zstrcmp(b->name, a->name, gf_numsort ? SORTIT_NUMERICALLY : 0);
+ r = zstrcmp(b->uname, a->uname,
+ gf_numsort ? SORTIT_NUMERICALLY : 0);
break;
case GS_DEPTH:
{
@@ -1859,6 +1863,7 @@ zglob(LinkList list, LinkNode np, int nountok)
int nexecs = 0;
struct globsort *sortp;
struct globsort *lastsortp = gf_sortlist + gf_nsorts;
+ Gmatch gmptr;
/* First find out if there are any GS_EXECs, counting them. */
for (sortp = gf_sortlist; sortp < lastsortp; sortp++)
@@ -1910,6 +1915,29 @@ zglob(LinkList list, LinkNode np, int nountok)
}
}
+ /*
+ * Where necessary, create unmetafied version of names
+ * for comparison. If no Meta characters just point
+ * to original string. All on heap.
+ */
+ for (gmptr = matchbuf; gmptr < matchptr; gmptr++)
+ {
+ char *nptr;
+ for (nptr = gmptr->name; *nptr; nptr++)
+ {
+ if (*nptr == Meta)
+ break;
+ }
+ if (*nptr == Meta)
+ {
+ int dummy;
+ gmptr->uname = dupstring(gmptr->name);
+ unmetafy(gmptr->uname, &dummy);
+ } else {
+ gmptr->uname = gmptr->name;
+ }
+ }
+
/* Sort arguments in to lexical (and possibly numeric) order. *
* This is reversed to facilitate insertion into the list. */
qsort((void *) & matchbuf[0], matchct, sizeof(struct gmatch),
diff --git a/Test/D07multibyte.ztst b/Test/D07multibyte.ztst
index dedf2417a..1b1d042a8 100644
--- a/Test/D07multibyte.ztst
+++ b/Test/D07multibyte.ztst
@@ -562,3 +562,20 @@
}
: $functions)
0:Multibtye handled of functions parameter
+
+ if [[ -n ${$(locale -a 2>/dev/null)[(R)pl_PL.utf8]} ]]; then
+ (
+ export LC_ALL=pl_PL.UTF-8
+ local -a names=(a b c d e f $'\u0105' $'\u0107' $'\u0119')
+ print -o $names
+ mkdir -p plchars
+ cd plchars
+ touch $names
+ print ?
+ )
+ else
+ ZTST_skip="No Polish UTF-8 local found, skipping sort test"
+ fi
+0:Sorting of metafied Polish characters
+>a ą b c ć d e ę f
+>a ą b c ć d e ę f