Hello David, thanks for the response.

>  it may not be worth it

I agree.
I think it is wise to give up to simulate dirread() rigorously. plan9 is not 
unix.

> Ori's suggestion to use Getdirentries64 on OSX might be  better
I cannot find getdirentries64() on my OSX.



I examined david code and found the code have still some problems.

(1) some directory entries are lost.
(2) uid and gid is wrong.

the test program is attached here.

Attachment: test_dirread.c
Description: Binary data


the result is shown below.

#
#       ls   (official ls in osx)
#
-bash$ ls /usr/bin|wc
    1108    1108    9719
-bash$ ls /dev|wc
     352     352    2428

#
#       david
#

-bash$ mk -f mkfile_david
9c -D__DARWIN_64_BIT_INO_T test_dirread.c
9c -D__DARWIN_64_BIT_INO_T dirread_david2.c
9l -o o.test_dirread test_dirread.o dirread_david2.o 
-bash$ o.test_dirread .
.DS_Store root 501 416 0
_mp9dir.c root 501 200000320 0
_p9dir.c root 501 20000000106 0
a.out root 501 710 0
a1.c root 501 572 0
b1.c root 501 243 0
dirread.c.orig root 501 743 0
dirread1.c root 501 137 0
dirread_david.c root 501 473 0
...
-bash$ o.test_dirread /usr/bin |wc
     770    3850   20936
-bash$ o.test_dirread -a /usr/bin |wc
     770    3850   20936
-bash$ o.test_dirread /dev |wc
     320    1600    7739
-bash$ o.test_dirread -a /dev |wc
     320    1600    7739
-bash$ 

#
#       mine
#

-bash$ mk
9c -D__DARWIN_64_BIT_INO_T test_dirread.c
9c -D__DARWIN_64_BIT_INO_T mdirread2.c
9c -D__DARWIN_64_BIT_INO_T _mp9dir.c
9l -o o.test_dirread test_dirread.o mdirread2.o _mp9dir.o 
-bash$ o.test_dirread .
.DS_Store arisawa staff 644 6148
_mp9dir.c arisawa staff 644 4948
_mp9dir.o arisawa staff 644 10284
_p9dir.c arisawa staff 444 4733
a.out arisawa staff 755 9552
a1.c arisawa staff 644 741
b1.c arisawa staff 644 2390
dirread.c.orig arisawa staff 444 3699
dirread1.c arisawa staff 644 3790
dirread_david.c arisawa staff 644 3768
...
-bash$ o.test_dirread /usr/bin |wc
    1108    5540   33034
-bash$ o.test_dirread -a /usr/bin |wc
    1108    5540   33034
-bash$ o.test_dirread /dev |wc
     352    1760   10308
-bash$ o.test_dirread -a /dev |wc
     352    1760   10308
-bash$ 

David idea is nice. I borrowed the idea:
        dir = fdopendir(dup(fd));
in mdirread2.c

Attachment: mkfile
Description: Binary data

 

Attachment: mdirread2.c
Description: Binary data

 

Attachment: _mp9dir.c
Description: Binary data


NOTE on _p9dir.c

(A) d->length
I observed opening character device can make a problem.
I think length of those device is allowed to assign 0.

                if(S_ISBLK(lst->st_mode) || S_ISCHR(lst->st_mode)){
                        if((fd = open(name, O_RDONLY)) >= 0){
                                d->length = disksize(fd, st);
                                close(fd);
                        }
                }

(B) DMDEVICE
you will find the code in _p9dir.c

                else if(S_ISBLK(st->st_mode)){
                        d->mode |= DMDEVICE;
                        d->qid.path = ('b'<<16)|st->st_rdev;
                }
                else if(S_ISCHR(st->st_mode)){
                        d->mode |= DMDEVICE;
                        d->qid.path = ('c'<<16)|st->st_rdev;
                }

but I prefer
                else if(S_ISBLK(st->st_mode)){
                        d->mode |= DMBLOCK;
                        d->qid.path = ('b'<<16)|st->st_rdev;
                }
                else if(S_ISCHR(st->st_mode)){
                        d->mode |= DMCHAR;
                        d->qid.path = ('c'<<16)|st->st_rdev;
                }

(C) I fixed some codes that produce wrong uid and gid.

comments welcome


> 2017/04/12 16:05、David Arroyo <dr...@aqwari.net> のメール:
> 
> The problem is twofold;
> 
> * The function exits early if it can't read a max-length directory
> entry, so that entry is "skipped" in subsequent calls to mygetdents.
> * As you said, we also lose any buffered dirents that haven't been
> returned from readdir yet.
> 
> I think these are both fixable problems, but it may not be worth it.
> Ori's suggestion to use Getdirentries64 on OSX might be  better.
> 
> David
> 
> On Tue, Apr 11, 2017, at 10:33 PM, arisawa wrote:
>> I did more test on david code and found a problem.
>> 
>> -bash$ mk -f mkfile_david
>> -bash$ o.test_dirread -a /usr/bin |wc
>>    1084    4336   27266
>> -bash$ o.test_dirread /usr/bin |wc
>>    1084    4336   27266
>> -bash$ ls /usr/bin |wc
>>    1108    1108    9719
>> 
>> option -a is for dirreadall.
>> 1108 - 1084 entries are lost.
>> 
>> they are:
>> o.test_dirread /usr/bin | awk '{print $1}' | sort >/tmp/a
>> ls /usr/bin | sort >/tmp/b
>> diff /tmp/a /tmp/b
>> 
>> -bash$ diff /tmp/a /tmp/b
>> 21a22
>>> SplitForks
>> 240a242,246
>>> easy_install-2.6
>>> easy_install-2.7
>>> efax
>>> efix
>>> egrep
>> 461a468,473
>>> kcc
>>> kdestroy
>>> kextutil
>>> keytool
>>> kgetcred
>>> kill.d
>> 675a688,694
>>> piconv
>>> piconv5.16
>>> piconv5.18
>>> pidpersec.d
>>> pkgbuild
>>> pkill
>>> pl
>> 880a900,904
>>> spfquery5.18
>>> splain
>>> splain5.16
>>> splain5.18
>>> split
>> 
>> sorry if I make a mistake, but I suspect readdir_r() has a buffer,
>> which can make a problem in using dup().
>> 
>> Kenji Arisawa.
>> 
>>> 2017/04/09 13:18、arisawa <karis...@gmail.com> のメール:
>>> 
>>> thanks david.
>>> 
>>> using dup() is very nice idea!
>>> your code works with
>>>  CFLAGS=-D__DARWIN_64_BIT_INO_T             # manual is wrong
>>> and a fix:
>>> //  buf = ((char*)buf) + d_reclen(buf);
>>>     buf = (struct dirent *)(((char*)buf) + d_reclen(buf));
>>> and adding
>>>     #define NAME_MAX 256
>>> in somewhere.
>>> 
>>> now /dev is readable.
>>> 
>>> one problem is left.
>>> 
>>> my test code:
>>>     fd = open(dirname,OREAD);
>>>     if(fd < 0)
>>>             fatal("%s open error",dirname);
>>>     while((n = dirread(fd, &db)) > 0){
>>>             print("#DBG n=%d\n",n);
>>>             for(i = 0; i < n; i++)
>>>                     print("%s %s %s \n", db[i].name, db[i].uid, db[i].gid);
>>>     }
>>>     close(fd);
>>> shows for dirname=$HOME
>>>     ...
>>>     arch root 501 
>>>     bin root 501 
>>>     ...
>>> but they should be
>>>     arch arisawa staff 
>>>     bin arisawa staff
>>> this problem comes from _p9dir() that is used in dirpackage().
>>> 
>>> Kenji Arisawa
>>> 
>>> 
>>>> 2017/04/08 18:07、David Arroyo <dr...@aqwari.net> のメール:
>>>> 
>>>> Ignore my previous post, I was tired and forgot about dup(). How about
>>>> something like this? (attached)
>>>> 
>>>> I only tested this on Ubuntu, I don't have an OS X machine. I still went
>>>> with readdir_r because the AIX and Solaris man pages for readdir were
>>>> vague about its behavior when called from multiple threads (glibc, musl,
>>>> FreeBSD look pretty safe).
>>>> 
>>>> Cheers,
>>>> David
>>>> 
>>>> On Sat, Apr 8, 2017, at 03:27 AM, David Arroyo wrote:
>>>>> This should be doable with some combination of fdopendir(3) and
>>>>> readdir(3). I'm not sure how to avoid leaking memory through the
>>>>> returned DIR pointer and any memory allocated with by readdir(3).
>>>>> This is usually free'd by closedir(3), which we can't use without
>>>>> closing the underlying file.
>>>>> 
>>>>> It should be OK to use free() on the return value of fdopendir, and
>>>>> stick to the uglier readdir_r(3) interface. I can definitely see why
>>>>> Russ went with  the simpler  system-specific interfaces on this.
>>>>> 
>>>>> David
>>>>> 
>>>>> On Sat, Apr 8, 2017, at 02:46 AM, Ori Bernstein wrote:
>>>>>> On Sat, 8 Apr 2017 15:21:47 +0900, arisawa <karis...@gmail.com> wrote:
>>>>>> 
>>>>>>> but how to?
>>>>>>> 
>>>>>>> unix doesn’t have something like fdreaddir(int fd).
>>>>>>> my guess: russ unwillingly used a low level function such as
>>>>>>> int getdirentries(int fd, char *buf, int nbytes, long *basep).
>>>>>>> 
>>>>>>> readdirall() might be OK in regular usage.
>>>>>> 
>>>>>> I don't use OSX regularly, although I do maintain the syscall
>>>>>> layer for Myrddin on it.
>>>>>> 
>>>>>> Getdirentries64 exists, and rudimentary testing doesn't show
>>>>>> any difficulties with using it.
>>>>>> 
>>>>>> -- 
>>>>>>  Ori Bernstein
>>>>>> 
>>>>> 
>>>> <posix-dirread.patch>
>>> 
>> 
>> 
> <posix-dirread2.patch>

Reply via email to