From: "Mauricio Fernández" Date: 2004-03-19T00:13:25+09:00 Subject: [PATCH] IO#fsync on fds opened as RO 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 #include #include #include 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