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 のメール: > > 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 のメール: >>> >>> 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 のメール: >>>> >>>> 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 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 >>>>>> >>>>> >>>> >>> >> >> >