9fans - fans of the OS Plan 9 from Bell Labs
 help / color / mirror / Atom feed
From: arisawa <karisawa@gmail.com>
To: Fans of the OS Plan 9 from Bell Labs <9fans@9fans.net>
Subject: Re: [9fans] p9p: 9 ls /dev
Date: Thu, 13 Apr 2017 12:04:21 +0900	[thread overview]
Message-ID: <0DF998AF-3534-47C6-83A9-9973FAB55ECF@gmail.com> (raw)
In-Reply-To: <1491980708.58243.942088184.4DEC0B7B@webmail.messagingengine.com>

[-- Attachment #1: Type: text/plain, Size: 456 bytes --]

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 #2: test_dirread.c --]
[-- Type: application/octet-stream, Size: 1281 bytes --]

/*	compile on p9p
 *	9c dirread.c
 *	9c test_dirread.c && 9l -o o.test_dirread test_dirread.o dirread.o
 */

#include <u.h>
#include <libc.h>

#define DBG if(0)

#define fatal sysfatal

void
usage(void)
{
	fprint(2,"usage: %s [-a] dir\n",argv0);
	exits(nil);
}


void
test2(char *dirname,int flag)
{
	int fd;
	Dir *db;
	int i,n;
	fd = open(dirname,OREAD);
	if(fd < 0)
		fatal("%s open error",dirname);
	if(flag){
		n = dirreadall(fd, &db);
		if(n < 0)
			fatal("dirread error");

		for(i = 0; i < n; i++)
			print("%s %s %s %uo %uld\n",\
				 db[i].name, db[i].uid, db[i].gid, db[i].mode,db[i].length);
		//free(db);

	}
	else{
		while((n = dirread(fd, &db)) > 0){
			DBG print("#DBG main: n=%d\n",n);
			for(i = 0; i < n; i++)
				print("%s %s %s %uo %uld\n",\
					db[i].name, db[i].uid, db[i].gid, db[i].mode,db[i].length);
		}
		//free(db);
	}
	close(fd);
}

int aflag;
char *ofile;

void
main(int argc, char *argv[])
{
	char *dirname;
	ARGBEGIN{
        case 'a':
		aflag = 1;
		break;
	case 'o':
		ofile = EARGF(usage());
		break;
	case '?':
	default:
		usage();
	} ARGEND;

	if(ofile)
		print("%s\n", ofile);
	if(argc == 0)
		usage();

	dirname = argv[0];
	test2(dirname,aflag);
	exits(nil);
}

[-- Attachment #3: Type: text/plain, Size: 1800 bytes --]



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 #4: mkfile --]
[-- Type: application/octet-stream, Size: 326 bytes --]

<$PLAN9/src/mkhdr

TARG=test_dirread test_dirent

OFILES=\
	test_dirread.$O\
	mdirread2.$O\
	_mp9dir.$O\

#HFILES=a.h

%.$O: %.c
	9c -o $target $stem.c

$O.test_dirread: test_dirread.$O mdirread2.$O _mp9dir.$O
	9l -o $target $stem.$O

<$PLAN9/src/mkone
#<$PLAN9/src/mkmany

CFLAGS=-D__DARWIN_64_BIT_INO_T

[-- Attachment #5: Type: text/plain, Size: 0 bytes --]



[-- Attachment #6: mdirread2.c --]
[-- Type: application/octet-stream, Size: 3787 bytes --]

#include <u.h>
#define NOPLAN9DEFINES
#include <libc.h>
#include <sys/stat.h>
#include <dirent.h>
#include <errno.h>

#define DBG if(0)
#define fatal sysfatal

extern int _p9dir(struct stat*, struct stat*, char*, Dir*, char**, char*);

#if defined(__DragonFly__)
static inline int d_reclen(struct dirent *de) { return _DIRENT_DIRSIZ(de); }
#else
static inline int d_reclen(struct dirent *de) { return de->d_reclen; }
#endif

static int
countde(char *p, int n)
{
	char *e;
	int m;
	struct dirent *de;

	e = p+n;
	m = 0;
	while(p < e){
		de = (struct dirent*)p;
		if(d_reclen(de) <= 4+2+2+1 || p+d_reclen(de) > e)
			break;
		if(de->d_name[0]=='.' && de->d_name[1]==0)
			de->d_name[0] = 0;
		else if(de->d_name[0]=='.' && de->d_name[1]=='.' && de->d_name[2]==0)
			de->d_name[0] = 0;
		m++;
		p += d_reclen(de);
	}
	return m;
}

static int
dirpackage(int fd, char *buf, int n, Dir **dp)
{
	int oldwd;
	char *p, *str, *estr;
	int i, nstr, m;
	struct dirent *de;
	struct stat st, lst;
	Dir *d;

	n = countde(buf, n);
	if(n <= 0)
		return n;

	if((oldwd = open(".", O_RDONLY)) < 0)
		return -1;
	if(fchdir(fd) < 0)
		return -1;

	p = buf;
	nstr = 0;

	for(i=0; i<n; i++){
		de = (struct dirent*)p;
		memset(&lst, 0, sizeof lst);
		if(de->d_name[0] == 0)
			/* nothing */ {}
		else if(lstat(de->d_name, &lst) < 0)
			de->d_name[0] = 0;
		else{
			st = lst;
			if(S_ISLNK(lst.st_mode))
				stat(de->d_name, &st);
			nstr += _p9dir(&lst, &st, de->d_name, nil, nil, nil);
		}
		p += d_reclen(de);
	}

	d = malloc(sizeof(Dir)*n+nstr);
	if(d == nil){
		fchdir(oldwd);
		close(oldwd);
		return -1;
	}
	str = (char*)&d[n];
	estr = str+nstr;

	p = buf;
	m = 0;
	for(i=0; i<n; i++){
		de = (struct dirent*)p;
		if(de->d_name[0] != 0 && lstat(de->d_name, &lst) >= 0){
			st = lst;
			if((lst.st_mode&S_IFMT) == S_IFLNK)
				stat(de->d_name, &st);
			_p9dir(&lst, &st, de->d_name, &d[m++], &str, estr);
		}
		p += d_reclen(de);
	}

	fchdir(oldwd);
	close(oldwd);
	*dp = d;
	return m;
}


/* return value
 * -1: on error
 * 0: on eof
 * others: filled bytes */
int
mreaddir(DIR *dirp, char *buf, int m)
{
	/* m is sizeof buf. must be > sizeof(struct dirent) */
	struct dirent *ep;
	int n,status;
	n = 0;
	for(;;){
		ep = (struct dirent *)(buf+n);
		status = readdir_r(dirp, ep, &ep);
		if(status || (ep == NULL))
			break;
		if(strcmp(ep->d_name,".") == 0 || strcmp(ep->d_name,"..") == 0)
			continue;
		DBG print("R %d %d %s\n",ep->d_namlen,ep->d_reclen,ep->d_name);
		n += ep->d_reclen;
		if(m -n < sizeof(struct dirent))
			break;
	}
	if(status)
		return -1;
	return n;
}

long
dirreadall(int fd, Dir **dp)
{
	static DIR *dir;
	struct dirent *ep;
	char *p,*buf,*bufend,*nbuf;
	int m, n, bufsz;
	int dentsz = sizeof(struct dirent);
	int allcsz = 1024;/* allocation unit */

	bufsz = allcsz + dentsz;/* what is the best value? */
	DBG print("#DBG mdirread begin\n");
	buf = malloc(bufsz);
	if(buf == nil)
		fatal("# malloc");

	dir = fdopendir(dup(fd));
	if(dir == nil)
		fatal("fdopendir");

	n = 0;
	for(;;){
		m = mreaddir(dir, buf+n, bufsz-n);
		if(m == 0)
			break;
		n += m;
		if(bufsz - n < dentsz){
			bufsz += allcsz;
			nbuf = realloc(buf, bufsz);
			if(nbuf == nil){
				free(buf);
				closedir(dir);
				return -1;
			}
			buf = nbuf;
		}
	}
	/* then n is num of effective bytes in buf */

	bufend = buf + n;
	for(p = buf; p < bufend;){
		ep = (struct dirent *)p;
		DBG print("C %d %d %s\n",ep->d_namlen,ep->d_reclen,ep->d_name);
		p += ep->d_reclen;
	}

	n = dirpackage(fd, buf, n, dp);

	free(buf);
	closedir(dir);

	return n;
}

long
dirread(int fd, Dir **dp)
{
	return dirreadall(fd,dp);
}


[-- Attachment #7: Type: text/plain, Size: 0 bytes --]



[-- Attachment #8: _mp9dir.c --]
[-- Type: application/octet-stream, Size: 5125 bytes --]

#include <u.h>
#define NOPLAN9DEFINES
#include <libc.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <pwd.h>
#include <grp.h>

#define DMBLOCK 0x00800000	/* same as DMDEVICE */
#define DMCHAR  0x00400000	/* we have room for new definition */

#if defined(__APPLE__)
#define _HAVESTGEN
#include <sys/disk.h>
static vlong
disksize(int fd, struct stat *st)
{
	u64int bc;
	u32int bs;

	bs = 0;
	bc = 0;
	ioctl(fd, DKIOCGETBLOCKSIZE, &bs);
	ioctl(fd, DKIOCGETBLOCKCOUNT, &bc);
	if(bs >0 && bc > 0)
		return bc*bs;
	return 0;
}

#elif defined(__FreeBSD__)
#define _HAVESTGEN
#include <sys/disk.h>
#include <sys/disklabel.h>
#include <sys/ioctl.h>
static vlong
disksize(int fd, struct stat *st)
{
	off_t mediasize;

	if(ioctl(fd, DIOCGMEDIASIZE, &mediasize) >= 0)
		return mediasize;
	return 0;
}

#elif defined(__OpenBSD__)
#define _HAVESTGEN
#include <sys/disklabel.h>
#include <sys/ioctl.h>
#include <sys/dkio.h>
static vlong
disksize(int fd, struct stat *st)
{
	struct disklabel lab;
	int n;

	if(!S_ISCHR(st->st_mode))
		return 0;
	if(ioctl(fd, DIOCGDINFO, &lab) < 0)
		return 0;
	n = minor(st->st_rdev)&7;
	if(n >= lab.d_npartitions)
		return 0;
	return (vlong)lab.d_partitions[n].p_size * lab.d_secsize;
}

#elif defined(__linux__)
#include <linux/hdreg.h>
#include <linux/fs.h>
#include <sys/ioctl.h>
#undef major
#define major(dev) ((int)(((dev) >> 8) & 0xff))
static vlong
disksize(int fd, struct stat *st)
{
	u64int u64;
	long l;
	struct hd_geometry geo;

	memset(&geo, 0, sizeof geo);
	l = 0;
	u64 = 0;
#ifdef BLKGETSIZE64
	if(ioctl(fd, BLKGETSIZE64, &u64) >= 0)
		return u64;
#endif
	if(ioctl(fd, BLKGETSIZE, &l) >= 0)
		return l*512;
	if(ioctl(fd, HDIO_GETGEO, &geo) >= 0)
		return (vlong)geo.heads*geo.sectors*geo.cylinders*512;
	return 0;
}

#else
static vlong
disksize(int fd, struct stat *st)
{
	return 0;
}
#endif

int _p9usepwlibrary = 1;
/*
 * Caching the last group and passwd looked up is
 * a significant win (stupidly enough) on most systems.
 * It's not safe for threaded programs, but neither is using
 * getpwnam in the first place, so I'm not too worried.
 */
int
_p9dir(struct stat *lst, struct stat *st, char *name, Dir *d, char **str, char *estr)
{
	char *s;
	char tmp[20];
	static struct group *g;
	static struct passwd *p;
	int sz, fd;

	fd = -1;
	USED(fd);
	sz = 0;
	if(d)
		memset(d, 0, sizeof *d);

	/* name */
	s = strrchr(name, '/');
	if(s)
		s++;
	if(!s || !*s)
		s = name;
	if(*s == '/')
		s++;
	if(*s == 0)
		s = "/";
	if(d){
		if(*str + strlen(s)+1 > estr)
			d->name = "oops";
		else{
			strcpy(*str, s);
			d->name = *str;
			*str += strlen(*str)+1;
		}
	}
	sz += strlen(s)+1;

	/* user */
	p = getpwuid(st->st_uid);
	if(p == nil){
		snprint(tmp, sizeof tmp, "%d", (int)st->st_uid);
		s = tmp;
	}
	else
		s = p->pw_name;

	sz += strlen(s)+1;
	if(d){
		if(*str+strlen(s)+1 > estr)
			d->uid = "oops";
		else{
			strcpy(*str, s);
			d->uid = *str;
			*str += strlen(*str)+1;
		}
	}

	/* group */
	g = getgrgid(st->st_gid);
	if(g == nil){
		snprint(tmp, sizeof tmp, "%d", (int)st->st_gid);
		s = tmp;
	}
	else
		s = g->gr_name;

	sz += strlen(s)+1;
	if(d){
		if(*str + strlen(s)+1 > estr)
			d->gid = "oops";
		else{
			strcpy(*str, s);
			d->gid = *str;
			*str += strlen(*str)+1;
		}
	}

	if(d){
		d->type = 'M';

		d->muid = "";
		d->qid.path = st->st_ino;
		/*
		 * do not include st->st_dev in path, because
		 * automounters give the same file system different
		 * st_dev values for successive mounts, causing
		 * spurious write warnings in acme and sam.
		d->qid.path |= (uvlong)st->st_dev<<32;
		 */
#ifdef _HAVESTGEN
		d->qid.vers = st->st_gen;
#endif
		if(d->qid.vers == 0)
			d->qid.vers = st->st_mtime + st->st_ctime;
		d->mode = st->st_mode&0777;
		d->atime = st->st_atime;
		d->mtime = st->st_mtime;
		d->length = st->st_size;

		if(S_ISLNK(lst->st_mode)){	/* yes, lst not st */
			d->mode |= DMSYMLINK;
			d->length = lst->st_size;
		}
		else if(S_ISDIR(st->st_mode)){
			d->length = 0;
			d->mode |= DMDIR;
			d->qid.type = QTDIR;
		}
		else if(S_ISFIFO(st->st_mode))
			d->mode |= DMNAMEDPIPE;
		else if(S_ISSOCK(st->st_mode))
			d->mode |= DMSOCKET;
#ifdef P9P_CMODE
		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;
		}
#else
		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;
		}
#endif
		/* fetch real size for disks
		 * we should avoid opening char device
		 * because it can make trouble */
		if(S_ISBLK(lst->st_mode)){
			if((fd = open(name, O_RDONLY)) >= 0){
				d->length = disksize(fd, st);
				close(fd);
			}
		}
		else if(S_ISCHR(lst->st_mode))
			d->length = 0;
	}

	return sz;
}


[-- Attachment #9: Type: text/plain, Size: 5529 bytes --]



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 <droyo@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 <karisawa@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 <droyo@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 <karisawa@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	other threads:[~2017-04-13  3:04 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-04-06 12:49 arisawa
2017-04-07  1:18 ` Lyndon Nerenberg
2017-04-08  1:18   ` arisawa
2017-04-08  4:06     ` Lyndon Nerenberg
2017-04-08  6:21       ` arisawa
2017-04-08  6:46         ` Ori Bernstein
2017-04-08  7:27           ` David Arroyo
2017-04-08  9:07             ` David Arroyo
2017-04-09  4:18               ` arisawa
2017-04-12  2:33                 ` arisawa
2017-04-12  7:05                   ` David Arroyo
2017-04-13  3:04                     ` arisawa [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=0DF998AF-3534-47C6-83A9-9973FAB55ECF@gmail.com \
    --to=karisawa@gmail.com \
    --cc=9fans@9fans.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).