This is a kernel bug.
sysfile.c:/^read says

        dir = c->qid.type&QTDIR;
        if(dir && mountrockread(c, p, n, &nn)){
                /* do nothing: mountrockread filled buffer */
        }else{
                if(dir && c->umh)
                        nn = unionread(c, p, n);
                else
                        nn = devtab[c->type]->read(c, p, n, off);
        }
        if(dir)
                nnn = mountfix(c, p, nn, n);
        else
                nnn = nn;

but should say (untested)

        if(c->qid.type&QTDIR) {
                if(mountrockread(c, p, n, &nn)) {
                        /* do nothing: mountrockread filled buffer */
                } else if(c->umh) {
                        nn = unionread(c, p, n);
                } else {
                        if(off != c->offset)
                                error(Edirseek);
                        nn = devtab[c->type]->read(c, p, n, c->devoffset);
                }
                nnn = mountfix(c, p, nn, n);
        } else {
                nn = devtab[c->type]->read(c, p, n, off);
                nnn = nn;
        }

I have separated out the various if(dir) tests into
one block, but more importantly the new code passes
c->devoffset to the directory read.

No one noticed before because most 9P2000 servers
assume they are being used correctly and implement
a simpler check: if offset == 0, seek to beginning,
otherwise continue where the last read left off.

Russ

Reply via email to