> that looks like a bug to me.

Yep,

In fact it turned out to be rather more subtle than I first though, my bad.

sorry for the noise.

-Steve


diff /n/dump/2019/0205/sys/src/cmd/cifs/main.c /sys/src/cmd/cifs/main.c
216a217,222
> /* remove "." and ".." from the cache */
> static int
> rmdots(Aux *a, int got)
> {
>       int i, num;
>       FInfo *fi;
217a224,237
>       num = 0;
>       fi = (FInfo *)a->cache;
>       for(i = 0; i < got; i++){
>               if(strcmp(fi->name, ".") == 0 || strcmp(fi->name, "..") == 0){
>                       memmove(fi, fi+1, got * sizeof(FInfo));
>                       continue;
>               }
>               fi++;
>               num++;
>       }
> 
>       return num;
> }
> 
250d269
<               fi = (FInfo *)a->cache;
257a277
>               got = rmdots(a, got);
260,266d279
< 
<               if(got >= 2 && strcmp(fi[0].name, ".") == 0 &&
<                   strcmp(fi[1].name, "..") == 0){
<                       a->end = (got - 2) * sizeof(FInfo);
<                       memmove(a->cache, a->cache + sizeof(FInfo)*2,
<                               a->end - a->off);
<               }
278a292
>               got = rmdots(a, got);
288a303,304
> 
> from_cache:
292d307
< from_cache:


------------------------------------------------------------------
or as a snippet:


/* remove "." and ".." from the cache */
static int
rmdots(Aux *a, int got)
{
        int i, num;
        FInfo *fi;

        num = 0;
        fi = (FInfo *)a->cache;
        for(i = 0; i < got; i++){
                if(strcmp(fi->name, ".") == 0 || strcmp(fi->name, "..") == 0){
                        memmove(fi, fi+1, got * sizeof(FInfo));
                        continue;
                }
                fi++;
                num++;
        }

        return num;
}

static int
dirgen(int slot, Dir *d, void *aux)
{
        long off;
        FInfo *fi;
        int rc, got;
        Aux *a = aux;
        char *npath;
        int numinf = numinfo();
        int slots;

        slots = 32;             /* number of dir entries to fetch at one time */

        if(strcmp(a->path, "/") == 0){
                if(slot < numinf){
                        dirgeninfo(slot, d);
                        return 0;
                } else
                        slot -= numinf;

                if(slot >= Nshares)
                        return -1;
                V2D(d, mkqid(Shares[slot].name, 1, 1, Pshare, slot),
                        Shares[slot].name);
                return 0;
        }

        off = slot * sizeof(FInfo);
        if(off >= a->off && off < a->end && time(nil) < a->expire)
                goto from_cache;

        if(off == 0){
                npath = smprint("%s/*", mapfile(a->path));
                a->sh = T2findfirst(Sess, a->sp, slots, npath, &got, &a->srch,
                        (FInfo *)a->cache);
                free(npath);
                if(a->sh == -1)
                        return -1;

                got = rmdots(a, got);
                a->off = 0;
                a->end = got * sizeof(FInfo);
                goto from_cache;
        }

        while(off >= a->end && a->sh != -1){
                fi = (FInfo *)(a->cache + (a->end - a->off) - sizeof(FInfo));
                a->off = a->end;
                npath = smprint("%s/%s", mapfile(a->path), fi->name);
                rc = T2findnext(Sess, a->sp, slots, npath,
                        &got, &a->srch, (FInfo *)a->cache, a->sh);
                free(npath);
                if(rc == -1 || got == 0)
                        break;
                got = rmdots(a, got);
                a->end = a->off + got * sizeof(FInfo);
        }
        a->expire = time(nil) + CACHETIME;

        if(got < slots){
                if(a->sh != -1)
                        CIFSfindclose2(Sess, a->sp, a->sh);
                a->sh = -1;
        }


from_cache:
        if(off >= a->end)
                return -1;

        fi = (FInfo *)(a->cache + (off - a->off));
        npath = smprint("%s/%s", mapfile(a->path), fi->name);
        I2D(d, a->sp, npath, realmtime(npath), fi);
        if(Billtrog == 0)
                upd_names(Sess, a->sp, npath, d);
        free(npath);
        return 0;
}

Reply via email to