Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 22 Aug 2017 13:38:00 +0200
From:      Nikolaus Rath <Nikolaus@rath.org>
To:        freebsd-fs@freebsd.org
Subject:   Can telldir() == 0 value be made special?
Message-ID:  <87bmn7kf3b.fsf@vostro.rath.org>

next in thread | raw e-mail | index | archive | help
Hello,

I am trying to debug a test failure of libfuse under FreeBSD. I believe
I have reduced it to the following root cause:

Consider the following program:

#include <stdio.h>
#include <dirent.h>
#include <sys/types.h>

int main(void) {
    struct dirent *e =3D NULL;
    DIR *dirp;

    printf("opendir...\n");
    dirp =3D opendir("/");
    if(dirp =3D=3D NULL) {
        perror("opendir");
        return 1;
    }
    printf("telldir: %ld\n", telldir(dirp));
    e =3D readdir(dirp);
    printf("readdir: %s\n", e->d_name);
    printf("telldir: %ld\n", telldir(dirp));
    e =3D readdir(dirp);
    printf("readdir: %s\n", e->d_name);
    printf("closedir..\n");
    closedir(dirp);
=20=20=20=20
    printf("opendir...\n");
    dirp =3D opendir("/");
    if(dirp =3D=3D NULL) {
        perror("opendir");
        return 1;
    }
    e =3D readdir(dirp);
    printf("readdir: %s\n", e->d_name);
    printf("telldir: %ld\n", telldir(dirp));
    e =3D readdir(dirp);
    printf("readdir: %s\n", e->d_name);
    printf("closedir..\n");
    closedir(dirp);
=20=20=20=20
    return 0;
}


Under FreeBSD, running it gives:

# ./simple=20
opendir...
telldir: 0
readdir: .
telldir: 1
readdir: ..
closedir..
opendir...
readdir: .
telldir: 0
readdir: ..
closedir..

In other words, if telldir() is called right after opendir(), it gives
an offset of zero. But if telldir() is called only after the first
readdir() call, it also gives an offset of zero. My hypothesis is that
FreeBSD actually just enumerates the different telldir() calls - is that
correct?

Now, the offsets returned by telldir() are documented to be valid only
within a given *dirp, so FreeBSD isn't doing anything wrong.

However, having different meanings even for an offset of zero causes
problems for libfuse, because under Linux an offset of zero is
guaranteed to mean "first entry". This is reflected in the definition of
the fuse readdir() function which always receives an *offset* parameter
that needs to have a definite value even when telldir() was never
called. If zero is suddenly also a valid telldir() return value that may
indicate some other position in the stream, things get complicated.

Now, I think I managed to work around that by shifting all offsets by
one, but that is awkward (and I may have overlooked some problems that
the unit tests don't cover). So I am wondering:

Is there a reason why the FreeBSD kernel could not start enumerating
telldir() offsets with 1, so that 0 can always have the same meaning?


Best,
-Nikolaus

--=20
GPG Fingerprint: ED31 791B 2C5C 1613 AF38 8B8A D113 FCAC 3C4E 599F

             =C2=BBTime flies like an arrow, fruit flies like a Banana.=C2=
=AB



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?87bmn7kf3b.fsf>