Spyder
Spyder

Reputation: 974

In Linux fwrite command does not set errno, how to get proper errno on failure cases

From man page of fwrite in linux,

DESCRIPTION The function fread() reads nmemb elements of data, each size bytes long, from the stream pointed to by stream, storing them at the location given by ptr.

   The function fwrite() writes nmemb elements of data, each size bytes long, to the stream pointed to by stream, obtaining them from the location given by ptr.

   For nonlocking counterparts, see unlocked_stdio(3).

RETURN VALUE On success, fread() and fwrite() return the number of items read or written. This number equals the number of bytes transferred only when size is 1. If an error occurs, or the end of the file is reached, the return value is a short item count (or zero).

   fread() does not distinguish between end-of-file and error, and callers must use feof(3) and ferror(3) to determine which occurred.

Now my question is: Suppose fwrite() system call failure occurred due to No space on the drive. How can we get the errno for it. As fwrite is not setting the errno in case of failure.

Just in case errno is: The header file defines the integer variable errno, which is set by system calls and some library functions in the event of an error to indicate what went wrong.

Talking in terms of Programming language: C

Upvotes: 2

Views: 3846

Answers (3)

nos
nos

Reputation: 229058

fwrite() cannot fail due to EOF, but fread() can.

For fwrite(), you discover an error if it did not write the same amount of items you told it to, so you check it like this:

size_t written = fwrite(buf, element_size, num_elements, file);
if (written != num_elements) {
   //error , here errno do get set and you can inspect it/print it etc.
}

Now, a FILE* have an internal buffer, so a fwrite() call might not actually write the data to the operating system or file unless that internal buffer gets full.

This means you also either have to fflush() the FILE* and also check for errors after each fwrite() call like so:

if (fflush(file) == EOF) {
       //error , here errno do get set and you can inspect it/print it etc.
}

Or you have to accept that a potential write failure can be given to you on any future fwrite() calls you perform if e.g. those calls happens to flush() the FILE* automatically. And you'd also have to check for errors when calling fclose():

if (fclose(file) == EOF) {
       //error , here errno do get set and you can inspect it/print it etc.
}

For fread() you can inspect errno if it failed. After you have handled any data an fread() call have read, you can do

if (ferror(file)) {
     //error , here errno do get set and you can inspect it/print it etc.
}

Upvotes: 2

G. Sliepen
G. Sliepen

Reputation: 7973

fwrite() is not a direct system call, and in general all I/O done via a FILE * pointer is buffered. There is no guarantee that a call to fwrite() will actually perform a write at that time. Errors can be returned immediately, or by later calls to functions using FILE *. However, fclose() will write out any remaining buffered data, and will return an error if that write did not succeed.

In summary, you need to check for errors during every call to fwrite(), fread() and fclose(). If you want to avoid doing error checking everywhere, you can call ferror() at any time to check the error status of a FILE *.

The variable errno is set when errors occur, because the C library internally calls read() and write(), and those set errno in case of errors.

Upvotes: 2

Serge Ballesta
Serge Ballesta

Reputation: 148870

As fwrite is not setting the errno in case of failure: not exactly. The only possible error for fwrite is an error that would occur during the call of the underlying write system call. In that case the errno variable will be set but the write call and as such will be available, and you will be able to directly use the strerror or perror functions to get a textual description of the error.

BTW, fwrite is not a system call but a standard library function: is does not directly call a kernel function.

Upvotes: 1

Related Questions