tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

glob(3) GLOB_PERIOD bug?



It looks to me as though there's a bug in glob(3)'s GLOB_PERIOD.  When
matching the pattern "../?" without GLOB_PERIOD, I get what I would
expect: a list of directories sibling to . which have single-character
names, or GLOB_NOMATCH if there are none.  But with GLOB_PERIOD, I
always get GLOB_NOMATCH.  (Test program below, after my signature.)
4.0.1 gets this case right.  Looking at diffs between the two, I see
some code in glob2() reading

                if ((!anymeta) ||
                   ((pglob->gl_flags & GLOB_PERIOD) &&
                    (diff >= 1 && pend[-1] == DOT) &&
                    (diff >= 2 && (pend[-2] == SLASH || pend[-2] == DOT)) &&
                    (diff < 3 || pend[-3] == SLASH))) {

which was just

                if (!anymeta) {

in 4.0.1.  Reverting this one tidbit makes my test case work (../.
shows up in the results in addition, which is exactly what I would
expect).

This code looks very odd to me; I'm having trouble figuring out what it
does.  It appears to say "if GLOB_PERIOD is set and the component is .
or .., pretend we had no metacharacters" - but if the component is . or
.., then we _do_ have no metacharacters.  But my understanding of it is
clearly flawed, because removing it changes things, and my
understanding says that it shouldn't.

Furthermore, for GLOB_PERIOD to control anything which cares about more
than whether the component in question begins with a dot strikes me as
dubious, and this code is clearly special-casing more than that.

But someone must have had some kind of intent when making that change,
so I'm impelled to ask: what's the point of it?  What case does it get
righter than the other version?

/~\ The ASCII                             Mouse
\ / Ribbon Campaign
 X  Against HTML                mouse%rodents-montreal.org@localhost
/ \ Email!           7D C8 61 52 5D E7 2D 39  4E F1 31 3E E8 B3 27 4B

Here's that test program:

#include <glob.h>
#include <stdio.h>
#include <errno.h>
#include <strings.h>

static int err(const char *s, int e)
{
 printf("err: path=%s err=%d (%s)\n",s,e,strerror(e));
 return(0);
}

static void trywith(int f)
{
 int rv;
 glob_t g;
 int i;

 rv = glob("../?",f,&err,&g);
 switch (rv)
  { case GLOB_ABORTED:
       printf("  GLOB_ABORTED\n");
       break;
    case GLOB_NOMATCH:
       printf("  GLOB_NOMATCH\n");
       break;
    case GLOB_NOSPACE:
       printf("  GLOB_NOSPACE\n");
       break;
    default:
       printf("  rv = %d?\n",rv);
       break;
    case 0:
       printf("  pathc=%d matchc=%d\n",(int)g.gl_pathc,(int)g.gl_matchc);
       for (i=0;i<g.gl_pathc;i++)
        { printf("    [%d] %s\n",i,g.gl_pathv[i]);
        }
       break;
  }
}

int main(void);
int main(void)
{
 printf("flags = 0:\n");
 trywith(0);
 printf("flags = GLOB_PERIOD:\n");
 trywith(GLOB_PERIOD);
 return(0);
}


Home | Main Index | Thread Index | Old Index