Patch

diff -r -U 10 ruby-1.8.1/io.c ruby-1.8.1.inst/io.c
--- ruby-1.8.1/io.c     2004-03-18 15:52:24.000000000 +0100
+++ ruby-1.8.1.inst/io.c        2004-03-18 15:55:30.000000000 +0100
@@ -601,21 +601,20 @@

 static VALUE
 rb_io_fsync(io)
     VALUE io;
 {
 #ifdef HAVE_FSYNC
     OpenFile *fptr;
     FILE *f;

     GetOpenFile(io, fptr);
-    rb_io_check_writable(fptr);
     f = GetWriteFile(fptr);

     io_fflush(f, fptr);
     if (fsync(fileno(f)) < 0)
        rb_sys_fail(fptr->path);
     return INT2FIX(0);
 #else
     rb_notimplement();
     return Qnil;               /* not reached */
 #endif



Rationale

dir = open("somedir", "r")
dir.fsync

fails with a 'IOError: not opened for writing', due to an explicit check
in io.c ('rb_io_check_writable(fptr);'). 

On the other hand, 
dir = open("somedir", "w") raises Errno::EISDIR: Is a directory, as does
dir = open("somedir", "a").

However, the following works on my system (Linux 2.4)

batsman@tux-chan:/tmp/atomic/a/bla$ cat test.c

#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int
main(int argc, char *argv[])
{
  int dir, fd;
  int ret;

  dir = open("bleh", O_RDONLY);
  fd = open("journal", O_RDONLY);
  printf("dir is %d\n", dir);
  printf("fd is %d\n", fd);
  ret = fsync(dir);
  printf("ret for dir is %d\n", ret);
  ret = fsync(fd);
  printf("ret for fd is %d\n", ret);
  close(dir);
  close(fd);
}
batsman@tux-chan:/tmp/atomic/a/bla$ touch journal; mkdir bleh
batsman@tux-chan:/tmp/atomic/a/bla$ ./test
dir is 3
fd is 4
ret for dir is 0
ret for fd is 0

Additionally, SuSv2 indicates that

"The open() function will fail if: (...)
[EISDIR]
    The named file is a directory and oflag includes O_WRONLY or O_RDWR."
http://www.opengroup.org/onlinepubs/007908799/xsh/open.html

and man fsync under Linux indicates the following:

"It does not necessarily ensure that the entry in the directory containing
the file has also reached disk.  For that an explicit fsync on the file
descriptor of the directory is also needed."

If we cannot open a dir as WO or RW, and yet it is possible to fsync(dir)
(nothing in SuSv2 says explicitly that this is impossible), we can't but
conclude that fsync(dir) is OK for a dir opened as RO. Also, I couldn't
find any reason why fsync(file) should fail for a file opened in RO
mode.

-- 
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

How many chunks could checkchunk check if checkchunk could check chunks?
	-- Alan Cox