Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can non-buffered write return 0?

Tags:

c

io

According to the documentation, write returns either the number of bytes written or -1 in case of an error. It's not clear whether the number of bytes written can be 0 when nbyte is positive. The documentation does state that the returned value of bytes can be smaller than nbyte, but it's unclear whether it can be 0:

If a write() requests that more bytes be written than there is room for ... only as many bytes as there is room for shall be written. For example, suppose there is space for 20 bytes more in a file before reaching a limit. A write of 512 bytes will return 20.

The question is: if there is no room at all, will write return 0 or an error?

This matters for the code that calls write in a loop until either all bytes were written or an error returned.

like image 519
Michael Avatar asked Aug 09 '26 23:08

Michael


1 Answers

The question is: if there is no room at all, will write return 0 or an error?

Per the documentation you linked:

if nbyte is zero and the file is a regular file [...] In the absence of errors, or if error detection is not performed, the write() function shall return zero and have no other results.

That is, write() may return 0 if the requested number of bytes to transfer is 0, including in cases where there is no space available.

write() will not return 0 in any other case. If it cannot fulfill a request to transfer a positive number of bytes, then either it will fail, returning -1 and setting errno appropriately, or it will block until it can transfer at least one byte. Specifics depend on a variety of details, but in the particular case of being up against a permanent system, process, or user limit, so that write() can recognize that it should not expect it to become possible to fulfill any portion of the write request in the future, write() will fail rather than block.

In particular, the docs say:

If a write() requests that more bytes be written than there is room for [...] only as many bytes as there is room for shall be written. For example, suppose there is space for 20 bytes more in a file before reaching a limit. A write of 512 bytes will return 20. The next write of a non-zero number of bytes would give a failure return (except as noted below).

(Emphasis added.)

Other parts of the doc talk about other kinds of permanent limits.

Also:

The write() [... function] shall fail if:

[...]

[EFBIG]
An attempt was made to write a file that exceeds the implementation-defined maximum file size [...] or the process' file size limit, [...] and there was no room for any bytes to be written.

[EFBIG]
The file is a regular file, nbyte is greater than 0, and the starting position is greater than or equal to the offset maximum established in the open file description associated with fildes.

[...]

[ENOSPC]
There was no free space remaining on the device containing the file.

Although the spec pays attention to a wide variety of cases, it is possible that it does not explicitly speak to one or more special cases relevant to the question. If so, then I see no good reason to interpret that as setting such cases aside as an exceptions where non-trivial write() requests may return 0. Rather, relying on the Rationale's remarks that ...

The error indications in this volume of IEEE Std 1003.1-2001 were chosen so that an application can distinguish these cases from end-of-file. While write() cannot receive an indication of end-of-file, read() can, and the two functions have similar return values.

... I take it that a return value of 0 for a non-trivial request is intended to be reserved for indicating end-of-file for both read() and write(), and furthermore that it is intended to follow from the fact that write() cannot receive an end-of-file indication that it cannot cannot return 0, except when nbytes is zero.


This matters for the code that calls write in a loop until either all bytes were written or an error returned.

Sort of. If you suppose that write() might return 0 on account of being up against a permanent limit of some kind, then you have to accept that such an indication would mean that you cannot safely expect any subsequent writes to the same file to transfer any bytes either, barring a corrective intervention such as modifying the file position. Therefore, you can code defensively to cover that possibility without being confident about whether it really can occur.

like image 77
John Bollinger Avatar answered Aug 12 '26 13:08

John Bollinger



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!