I'd like to implement a proper write(2)
loop that takes a buffer and keeps calling write
until the entire buffer is written.
I guess the basic approach is something like:
/** write len bytes of buf to fd, returns 0 on success */
int write_fully(int fd, char *buf, size_t len) {
while (len > 0) {
ssize_t written = write(fd, buf, len);
if (written < 0) {
// some kind of error, probably should try again if its EINTR?
return written;
}
buf += written;
len -= written;
}
return 0;
}
... but this raises the question of whether write()
can validly return 0 bytes written and what to do in this case. If the situation persists, the above code will just hot spin on the write
call which seems like a bad idea. As long as something other than zero is returned you are making forward progress.
The man page for write
is a bit ambiguous. It says, for example:
On success, the number of bytes written is returned (zero indicates nothing was written).
Which seems to indicate that it is possible in some scenarios. Only one such scenario is explicitly called out:
If count is zero and fd refers to a regular file, then write() may return a failure status if one of the errors below is detected. If no errors are detected, or error detection is not performed, 0 will be returned without causing any other effect. If count is zero and fd refers to a file other than a regular file, the results are not specified.
That case is avoided above because I never call write
with len == 0
. There are lot of other cases where nothing could be written, but in general they all have specific error codes associated with them.
The file itself will be a open
ed from a path/name given on the command line. So it will usually be a regular file, but users may of course pass things like pipes, do input redirection, pass special devices like /dev/stdout
and so on. I am at least in control of the open
call and the O_NONBLOCK
flag is not passed to open. I can't reasonably check the behavior for all the file systems, all the special devices (and even if I could, more will be added), so I want to know how to handle this in a reasonable and general way.
* ... for a non-zero buffer size.