Hi, According to the online OpenGroup specification for read(2) available at [1], read(2) on directories is implementation dependant. If unsupported, it shall fail with EISDIR.
Not all our file systems comply, and return random errno values in this case (mostly EINVAL or ENOTSUP). The attached patch fix some of them (the ones i have access to), adjust the man page accordingly and add a small testcase to exercize this. Is it ok to apply ? Thanks. [1] http://pubs.opengroup.org/onlinepubs/009695399/functions/read.html -- Nicolas Joly Projects and Developments in Bioinformatics Institut Pasteur, Paris.
Index: lib/libc/sys/read.2 =================================================================== RCS file: /cvsroot/src/lib/libc/sys/read.2,v retrieving revision 1.33 diff -u -p -r1.33 read.2 --- lib/libc/sys/read.2 5 Apr 2010 07:53:47 -0000 1.33 +++ lib/libc/sys/read.2 5 Dec 2011 09:30:04 -0000 @@ -29,7 +29,7 @@ .\" .\" @(#)read.2 8.4 (Berkeley) 2/26/94 .\" -.Dd April 3, 2010 +.Dd December 9, 2011 .Dt READ 2 .Os .Sh NAME @@ -161,6 +161,16 @@ the total length of the I/O is more than return value. .It Bq Er EIO An I/O error occurred while reading from the file system. +.It Bq Er EISDIR +.Fa d +refers to a directory and the implementation does not allow the directory +to be read using +.Fn read +or +.Fn pread . +The +.Fn readdir +function should be used instead. .El .Pp In addition, Index: sys/fs/ptyfs/ptyfs_vnops.c =================================================================== RCS file: /cvsroot/src/sys/fs/ptyfs/ptyfs_vnops.c,v retrieving revision 1.37 diff -u -p -r1.37 ptyfs_vnops.c --- sys/fs/ptyfs/ptyfs_vnops.c 18 Nov 2011 21:18:50 -0000 1.37 +++ sys/fs/ptyfs/ptyfs_vnops.c 5 Dec 2011 09:30:04 -0000 @@ -788,6 +788,9 @@ ptyfs_read(void *v) struct ptyfsnode *ptyfs = VTOPTYFS(vp); int error; + if (vp->v_type == VDIR) + return EISDIR; + ptyfs->ptyfs_flag |= PTYFS_ACCESS; /* hardclock() resolution is good enough for ptyfs */ getnanotime(&ts); Index: sys/fs/sysvbfs/sysvbfs_vnops.c =================================================================== RCS file: /cvsroot/src/sys/fs/sysvbfs/sysvbfs_vnops.c,v retrieving revision 1.38 diff -u -p -r1.38 sysvbfs_vnops.c --- sys/fs/sysvbfs/sysvbfs_vnops.c 19 May 2011 03:11:58 -0000 1.38 +++ sys/fs/sysvbfs/sysvbfs_vnops.c 5 Dec 2011 09:30:05 -0000 @@ -378,8 +378,14 @@ sysvbfs_read(void *arg) const int advice = IO_ADV_DECODE(a->a_ioflag); DPRINTF("%s: type=%d\n", __func__, v->v_type); - if (v->v_type != VREG) + switch (v->v_type) { + case VREG: + break; + case VDIR: + return EISDIR; + default: return EINVAL; + } while (uio->uio_resid > 0) { if ((sz = MIN(filesz - uio->uio_offset, uio->uio_resid)) == 0) Index: sys/miscfs/kernfs/kernfs_vnops.c =================================================================== RCS file: /cvsroot/src/sys/miscfs/kernfs/kernfs_vnops.c,v retrieving revision 1.143 diff -u -p -r1.143 kernfs_vnops.c --- sys/miscfs/kernfs/kernfs_vnops.c 21 Jul 2010 09:06:38 -0000 1.143 +++ sys/miscfs/kernfs/kernfs_vnops.c 5 Dec 2011 09:30:05 -0000 @@ -941,7 +941,7 @@ kernfs_default_xread(void *v) int error; if (ap->a_vp->v_type == VDIR) - return (EOPNOTSUPP); + return EISDIR; off = (int)uio->uio_offset; /* Don't allow negative offsets */ Index: sys/rump/librump/rumpvfs/rumpfs.c =================================================================== RCS file: /cvsroot/src/sys/rump/librump/rumpvfs/rumpfs.c,v retrieving revision 1.103 diff -u -p -r1.103 rumpfs.c --- sys/rump/librump/rumpvfs/rumpfs.c 27 Sep 2011 14:24:52 -0000 1.103 +++ sys/rump/librump/rumpvfs/rumpfs.c 5 Dec 2011 09:30:06 -0000 @@ -1284,6 +1284,9 @@ rump_vop_read(void *v) off_t chunk; int error = 0; + if (vp->v_type == VDIR) + return EISDIR; + /* et op? */ if (rn->rn_flags & RUMPNODE_ET_PHONE_HOST) return etread(rn, uio); Index: tests/fs/vfs/t_vnops.c =================================================================== RCS file: /cvsroot/src/tests/fs/vfs/t_vnops.c,v retrieving revision 1.29 diff -u -p -r1.29 t_vnops.c --- tests/fs/vfs/t_vnops.c 8 Oct 2011 13:08:54 -0000 1.29 +++ tests/fs/vfs/t_vnops.c 5 Dec 2011 09:30:06 -0000 @@ -827,6 +827,27 @@ access_simple(const atf_tc_t *tc, const FSTEST_EXIT(); } +static void +read_directory(const atf_tc_t *tc, const char *mp) +{ + char buf[1024]; + int fd, res; + ssize_t size; + + FSTEST_ENTER(); + fd = rump_sys_open(".", O_DIRECTORY | O_RDONLY, 0777); + ATF_REQUIRE(fd != -1); + + size = rump_sys_pread(fd, buf, sizeof(buf), 0); + ATF_CHECK(size != -1 || errno == EISDIR); + size = rump_sys_read(fd, buf, sizeof(buf)); + ATF_CHECK(size != -1 || errno == EISDIR); + + res = rump_sys_close(fd); + ATF_REQUIRE(res != -1); + FSTEST_EXIT(); +} + ATF_TC_FSAPPLY(lookup_simple, "simple lookup (./.. on root)"); ATF_TC_FSAPPLY(lookup_complex, "lookup of non-dot entries"); ATF_TC_FSAPPLY(dir_simple, "mkdir/rmdir"); @@ -844,6 +865,7 @@ ATF_TC_FSAPPLY(attrs, "check setting att ATF_TC_FSAPPLY(fcntl_lock, "check fcntl F_SETLK"); ATF_TC_FSAPPLY(fcntl_getlock_pids,"fcntl F_GETLK w/ many procs, PR kern/44494"); ATF_TC_FSAPPLY(access_simple, "access(2)"); +ATF_TC_FSAPPLY(read_directory, "read(2) on directories"); ATF_TP_ADD_TCS(tp) { @@ -865,6 +887,7 @@ ATF_TP_ADD_TCS(tp) ATF_TP_FSAPPLY(fcntl_lock); ATF_TP_FSAPPLY(fcntl_getlock_pids); ATF_TP_FSAPPLY(access_simple); + ATF_TP_FSAPPLY(read_directory); return atf_no_error(); }