Date: Tue, 22 Aug 2017 12:05:29 -0700 From: Conrad Meyer <cem@freebsd.org> To: "freebsd-fs@freebsd.org" <freebsd-fs@freebsd.org> Subject: Re: Can telldir() == 0 value be made special? Message-ID: <CAG6CVpWf33CxbVJLtr-2-NESdoiPUWQHfcL_qaYrCUR2kQFS4g@mail.gmail.com> In-Reply-To: <CAF6rxg=J7TYQQtG4%2B9TzEPPAb7LTReAm6U3A19Aq24PWrnK4vw@mail.gmail.com> References: <87bmn7kf3b.fsf@vostro.rath.org> <CAG6CVpVViqnbGuVn_JETBC5Q0NoYfC4VJK7iWjEfA7tFurQ2ag@mail.gmail.com> <87lgmbfob2.fsf@vostro.rath.org> <CAF6rxg=J7TYQQtG4%2B9TzEPPAb7LTReAm6U3A19Aq24PWrnK4vw@mail.gmail.com>
next in thread | previous in thread | raw e-mail | index | archive | help
One could also make it reserve the zero slot for the loc == 0 entry,
but not create it dynamically. Just set loccnt=1 at initialization
and then special-case dd_loc==0. Like this:
--- a/lib/libc/gen/opendir.c
+++ b/lib/libc/gen/opendir.c
@@ -295,7 +295,7 @@ __opendir_common(int fd, int flags, bool use_current_pos)
dirp->dd_lock = NULL;
dirp->dd_td = (struct _telldir *)((char *)dirp + sizeof(DIR));
LIST_INIT(&dirp->dd_td->td_locq);
- dirp->dd_td->td_loccnt = 0;
+ dirp->dd_td->td_loccnt = 1;
dirp->dd_compat_de = NULL;
/*
--- a/lib/libc/gen/telldir.c
+++ b/lib/libc/gen/telldir.c
@@ -76,7 +76,10 @@ telldir(DIR *dirp)
_pthread_mutex_unlock(&dirp->dd_lock);
return (-1);
}
- lp->loc_index = dirp->dd_td->td_loccnt++;
+ if (dirp->dd_loc == 0)
+ lp->loc_index = 0;
+ else
+ lp->loc_index = dirp->dd_td->td_loccnt++;
lp->loc_seek = dirp->dd_seek;
lp->loc_loc = dirp->dd_loc;
if (flp != NULL)
Best,
Conrad
On Tue, Aug 22, 2017 at 11:35 AM, Eitan Adler <lists@eitanadler.com> wrote:
> On 22 August 2017 at 14:30, Nikolaus Rath <Nikolaus@rath.org> wrote:
>> On Aug 22 2017, Conrad Meyer <cem@freebsd.org> wrote:
>>> Hi Nikolaus,
>>>
>>> As you have surmised, DIR* seekpoints are created dynamically whenever
>>> requested by user's telldir() call:
>>
>> Good to know, thanks!
>>
>>> I believe we could special case zero without breaking ABI
>>> compatibility of correct programs. Something like this:
>>>
>>> --- a/lib/libc/gen/telldir.c
>>> +++ b/lib/libc/gen/telldir.c
>>> @@ -70,6 +70,20 @@ telldir(DIR *dirp)
>>> }
>>> }
>>> if (lp == NULL) {
>>> + /* Create special zero telldir entry, similar to Linux */
>>> + if (dirp->dd_td->td_loccnt == 0 && dirp->dd_loc != 0) {
>>> + lp = malloc(sizeof(struct ddloc));
>>> + if (lp == NULL) {
>>> + if (__isthreaded)
>>> + _pthread_mutex_unlock(&dirp->dd_lock);
>>> + return (-1);
>>> + }
>>> + lp->loc_index = dirp->dd_td->td_loccnt++;
>>> + lp->loc_seek = 0;
>>> + lp->loc_loc = 0;
>>> + LIST_INSERT_HEAD(&dirp->dd_td->td_locq, lp, loc_lqe);
>>> + }
>>> +
>>> lp = malloc(sizeof(struct ddloc));
>>> if (lp == NULL) {
>>> if (__isthreaded)
>>>
>>> I don't know if there are any downsides to special-casing zero like
>>> this, other than additional code complexity.
>>
>> This seems a little more complex than I would have expected.
>
>> Is this
>> maybe turning zero into a valid argument for seekdir() even if telldir()
>> has never been called?
>
> No, this code is called inside of telldir. I'd be against adding that
> behavior by contract since it complicates the contract of seekdir. No
> objection to this behavior by implementation though if it is simpler
> than modifying telldir (doubtful).
>
> What this is doing is ensuring that there will always be a 0 entry
> *after* telldir is called, and that seekdir(0) will return to the
> start of the directory if called with an argument of 0.
>
>
>> That would be even better, but the minimal change that I need is just to
>> ensure that telldir() either (a) never returns zero, or (b) only returns
>> zero if called at the beginning of the stream.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAG6CVpWf33CxbVJLtr-2-NESdoiPUWQHfcL_qaYrCUR2kQFS4g>
