On Tue, 9 Nov 2010 13:33:26 +0000 Nick Treleaven nick.treleaven@btinternet.com wrote:
On Sat, 6 Nov 2010 11:33:41 +0200 Dimitar Zhekov dimitar.zhekov@gmail.com wrote:
I'll write a non-GIO variant first, as a proof of concept.
First, I feel quite reluctant to use non-GLib/GIO functions for writing instead of g_file_replace_contents because if there is a better implementation, why don't they add it?
That was discussed later and proven as not worth.
The current non-GIO is buggy anyway. First:
if (G_UNLIKELY(len != bytes_written)) err = errno;
but fwrite() is not guaranteed to set errno, only write() is.
Second, and more important, the result of fclose() is not checked, for a buffered file stream. On lack of disk space, on my system fwrite() happily returns written == len, but fclose() fails. YMMV.
If not anything else, we should use non-buffered I/O, with fsync(), and check the result of close() anyway.
Thanks for finding these problems. I accept fclose should be checked.
I'm not sure why write is better than fwrite - POSIX says both set errno.
Geany runs under Linux and Windows, possibly also under MAC and BSD. None of Linux fwrite(3), MSVCRT, Darwin fwrite(3) and BSD fwrite(3) mentions anything about setting errno.
http://www.opengroup.org/onlinepubs/009695399/functions/fwrite.html
This is the 2004 Edition. Linux conforms to 2001, BSD/Darwin to 1990, MSVCRT to "ANSI"(?)
Can you explain why non-buffered I/O is better?
Depenting on the implementation, fwrite(data, sizeof(gchar), len, fp) may really try to write <len> single-byte blocks. A large number of buffered writes takes some time under MSVCRT, I've seen it taking seconds (YMMV). Swapping <size> and <len> helps for now, because they haven't implemented 2004, which mandates that the data must be written using fputc()...
With binary I/O we have fsync(), which really flushes the data. Even fflush() and fclose() are not guaranteed to do that.
Well, g_file_set_contents() uses buffered I/O, so obviously it's acceptable too. But since we don't write the file line-by-line or something, _why_ do we use buffered I/O in the first place?..