Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

NO_CASE_GLOB and unreadable directories (Episode VI: A New Hope)



On Wed, Jan 13, 2021 at 8:04 PM Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx> wrote:
>
> On Wed, Jan 13, 2021 at 4:28 PM Devin Hussey <husseydevin@xxxxxxxxx> wrote:
> >
> > Case insensitivity should not change the output due to file permissions.
>
> [... unless (?)] the filesystem is case-sensitive.  Why should
> (#i)file not be the same as [Ff][Ii][Ll][Ee] ?

I'm still of this opinion, but I now think zsh is [conceptually]
applying (#i) in the wrong way.

> The actual problem is that PAT_PURES is never true when NO_CASE_GLOB
> is set.

Effectively, NO_CASE_GLOB turns the pure path
  /data/data/com.termux/files/home
(to stick with the original example) into the extendedglob pattern
  /(#i)data/(#i)data/(#i)com.termux/(#i)files/(#i)home
which means every component has to be compared with pattry() rather
than as a literal string.  That in turn means that every parent must
be readable.

It further means that
  anydir/*
becomes
  (#i)anydir/(#i)*
which could be construed as incorrect, because if there are two directories
  AnyDir/
  anydir/
that pattern will return everything in both of them, even though only
the lower-case version was specified.  (This actually mentioned in
another of the github threads to which Devin linked.)

What's wanted in Devin's case is for (#i) to apply exactly when there
are other pattern characters in the component, e.g.,
  (#I)anydir/(#i)*
which I believe is expressed by the following patch.

This is not yet suitable for folding into the master branch, because
it is a significant change to the current zsh behavior (and because
there's some #ifdef __CYGWIN__ in there that I can't test and am not
sure what to do with).  For example (in the zsh source tree):

unpatched% setopt nocaseglob
unpatched% echo src/module?
Src/Modules

Whereas:

patched% setopt nocaseglob
patched% echo src/module?
zsh: no matches found: src/module?
patched% echo Src/module?
Src/Modules

There are no tests of NO_CASE_GLOB in Test/E01options.ztst, but all
the tests of (#i) in D02glob still pass.

diff --git a/Src/pattern.c b/Src/pattern.c
index c7c2c8bea..9869db5ef 100644
--- a/Src/pattern.c
+++ b/Src/pattern.c
@@ -509,10 +509,7 @@ void
 patcompstart(void)
 {
     patcompcharsset();
-    if (isset(CASEGLOB))
-       patglobflags = 0;
-    else
-       patglobflags = GF_IGNCASE;
+    patglobflags = 0;
     if (isset(MULTIBYTE))
        patglobflags |= GF_MULTIBYTE;
 }
@@ -632,6 +629,12 @@ patcompile(char *exp, int inflags, char **endexp)
     p->patmlen = len;
     p->patnpar = patnpar-1;

+    if (!isset(CASEGLOB) && !(patflags & PAT_PURES)) {
+       /* Special __CYGWIN__ handling needed? */
+       p->globflags |= GF_IGNCASE;
+       p->globend |= GF_IGNCASE;
+    }
+
     if (!strp) {
        pscan = (Upat)(patout + startoff);




Messages sorted by: Reverse Date, Date, Thread, Author