I have some legacy code that does this all over the place:
int fd; // open a file
if(fd == -1)
{
close(fd);
}
This looks very wrong to me.
Is closing an invalid file descriptor valid?
According to manual:
Upon successful completion, a value of 0 is returned. Otherwise, a
value
of -1 is returned and the global integer variable errno is set to indicate the error.
and then:
The close() system call will fail if:
[EBADF] fildes is not a valid, active file descriptor.
Then nothing harmful will happen.
It returns an error code.There is nothing wrong but it is not useful either, as there is no check made on the return value anyway.
Quoting the man page
Return Value
close() returns zero on success. On error, -1 is returned, and errno is set appropriately.
and
Errors
EBADF
fd isn't a valid open file descriptor.
note that in windows msvc, calling close with an invalid fd causes an abort() to occur by means of an assertion. the fd is checked it is greater than or equal to 0 and less than some magic number "nhandle" (which has the value of 64 on my system) not even an exception you can catch, or returning -1. it just bombs.
you'll get something like this (screenshot thanks to one of the users of my library):
Related
If open() returns a value of -1 to my program, which indicates a failure, do I still need to close the file? I read that if fopen() fails, then you do not need to call fclose() since you have not opened any files. I was wondering if this was the case for open() as well?
int fd = open(myfile, O_RDONLY);
if (fd == -1) {
close(fd);
}
No.
-1 isn't a file handle, so there's no need or reason to close it.
You could have answered your own question by checking the return value of close(-1). It returns -1, so that call was in error.
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
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.
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.
}
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.
I always struggle with return values of system calls - they are just so inconsistent!
Normally I check if they are NULL or -1 and then call perror. However, for fgets, the man page says:
gets() and fgets() return s on success, and NULL on error or when end of file occurs while no characters have been read.
which means the return value NULL is not necessarily an error - it can also be EOF. Is errno set when the end of file is reached? Can I still call perror in this case?
If not, what is the common way to tell if the call returned an error versus EOF. I want to use perror with NULL string for errors and a custom string for EOF.
Use ferror and feof to distinguish between error and EOF. There's no general way to find out exactly what the error was, if there was an error, but you can tell that there was one.
Standard C (f)gets (and (f)getc) are not required to set errno, although a conforming library implementation can set errno to a non-zero value pretty much at will.
Posix does requires that (f)get{c,s} set errno on read errors, but that only helps you after you have determined that there was a read error (by calling ferror). It's also important to remember that library functions never set errno to 0, but may set errno to a non-zero value even if no error occurs. So you cannot test errno as a replacement for checking the error return of any library function, including fgets. And since end-of-file is not an error, errno will (probably) not be modified on EOF, so its value in that case is meaningless.
According to fputs own documentation, yes, EOF does set errno. The man pages infer it indirectly as opposed to stating it outright, which hopefully will be amended. The function fputs returns an integer that will either be positive on success or EOF on failure. So the key to error handling fputs is to setup a code block that checks the return value of fputs as it is being called. The following is a snippet of how I've been taught to handle fputs errors.
if (fputs(buffer, stdout) == EOF)
{
fprintf(stderr, "fputs returned EOF: %s\n", strerror(errno));
// .. and now do whatever cleanup you need to do.
// or be lazy and exit(-1)
}
Here I am writing the contents of buffer to standard output and checking to see if fputs returns EOF. EOF indicates an error code was set, so as long as you follow the documentation on the man pages for fputs, you should be able to create a bunch of if statements to check the various error codes errno can be set to.
(1) What is buffer? Some character array I declared elsewhere.
(2) What does fprintf do? It prints output to a passed in file descriptor, which is in this case standard error (stderr... it prints to console like stdout, but for errors).
(3) What is strerror? It is a function defined in the string.h header that prints error information for the passed in error code. It has information for every single error code that errno can be set to. The header string.h should NOT be confused with strings.h, which is a BSD linux header file that does not contain strerror(3).
Edit: Ok, I messed up. You were looking for an answer on fgets, not fputs.
To check for an error on fgets, do the following
if (fgets(buffer, BUF_SIZE, myFile) == NULL)
{
// print out error as a string to stderr
fprintf(stderr, "fgets error occurred: %s\n", strerror(errno));
// do cleanup
}
// special: you also need to check errno AFTER the if statement...
The thing is, the only way you are getting an error on this is if the stream becomes unreadable, which is either due to permissions or trying to read something that is in write mode. In the case of a network, it may be possible for something to cut off your connection in the middle of reading, in which case you need to check the error code after the fgets if statement as well. But it will set the error code if something went wrong.
At least that is if the man pages are correct. See the linux man pages for more details. Only error code that can be set is the "I can't read this thing" code, which is errno == EBADF
What kind of errors faced by what kind of library functions affect the errno and set it to non-zero value? In my following program, I intended to use if(errno!=0) as a condition to check if the library functions I used functioned properly or not, and this is what I found (see the code below):
First I used if(errno!=0) to test if a file has been opened successfully with fopen() or not. If I try to open a non-existent file, then errno is set to non-zero (2 in my case) and it is verified by printing out the value of errno at each stage. But if I open an existing file, then the value of errno remains zero as fopen() opens the file properly. In this matter,if(errno!=0) acts as the perfect substitute to if(pFile==NULL) which I have commented out.
If the file is opened successfully, with errno still 0, the control moves to the first else block. This is where I find confusions about the behavior of errno. Here, since I have opened the file in r(read) mode and attempting to write to it using fputc(), I expect the resulting write-error to set errno to non-zero just as it is set by fopen() when it couldn't open the file successfully. But the value of errno continues to be zero even after that unsuccessful write using fputc(). (This is verifiable by printing value of errno after the faulty write).
Why is it so? Why is I/O error faced by one function fopen() setting the errno while write error faced by other function fputc() not affecting errno? If it's so, how can we reliably use errno as an indicator of error? Is my use of errno to test if fopen() worked successfully, instead of "if(pFile==NULL)" unwise? I will appreciate your analytic answers to this.
#include <stdio.h>
#include <errno.h>
int main ()
{
FILE * pFile;
printf("%d\n",errno);
pFile = fopen("D:\\decrypt.txt","r");
printf("%d\n",errno); // Prints 0 if fopen() successful,else 2
//if(pFile==NULL) perror("Error opening file");
if (errno!=0) perror ("Error opening file");
else
{
fputc ('x',pFile);
printf("%d\n",errno); //errno shows 0 even after write error
//if (ferror (pFile))
if (errno!=0) //Condition evaluates false even if faulty write
{
printf ("Error Writing to decrypt.txt\n");
}
fclose (pFile);
}
return 0;
}
The documentation largely tells you which function can set which values in errno, but there are some rules you need to know:
No library function sets errno to zero.
It is only valid to test errno when the function has indicated that an error has occurred (and the function is documented to set errno).
The first point means that if you want to know whether, for example, you've gotten an error from strtol(), you have to set errno to 0 before calling it.
The second point is crucial; for example, on Solaris, after many I/O operations when the channel was not a terminal, the setting of errno would be ENOTTY (not a terminal). There wasn't an error; nothing had failed; but basing your subsequent actions on errno alone (and not on the status reported by the I/O operation) would lead you to think everything failed.
Thus, in your code, the fopen() call may leave errno as a non-zero value, even though it successfully creates the file stream. You have to use:
const char filename[] = "D:\\crypt.txt";
if ((pFile = fopen(filename, "r")) == 0)
{
fprintf(stderr, "Failed to open %s for reading (%d: %s)\n",
filename, errno, strerror(errno));
...return or exit...
}
Beware: if you need to call a function that can alter errno, capture the value early:
int errnum = errno;
fprintf(stderr, "Failed to open %s for reading (%d: %s)\n",
filename, errnum, strerror(errnum));
And never declare errno yourself; always use #include <errno.h> to do it.
I'm not clear why your code is not getting an error on the fputc() call. On my Mac OS X 10.8.3 system, the equivalent code fails with errno set to 9 (EBADF) 'Bad file descriptor'.
Where is this documented? It's in the C standard, and reinforced by the POSIX standard.
ISO/IEC 9899:2011 §7.5 Errors <errno.h>
¶3 The value of errno in the initial thread is zero at program startup (the initial value of errno in other threads is an indeterminate value), but is never set to zero by any library function.202) The value of errno may be set to nonzero by a library function call whether or not there is an error, provided the use of errno is not documented in the description of the function in this International Standard.
202) Thus, a program that uses errno for error checking should set it to zero before a library function call, then inspect it before a subsequent library function call. Of course, a library function can save the value of errno on entry and then set it to zero, as long as the original value is restored if errno’s value is still zero just before the return.
The wording in previous versions of the C standard did not mention threads but was otherwise similar.
Note that the description of fopen() in the C standard does not mention errno. Therefore, it is permitted to set errno by the C standard. By contrast, the mbsrtowcs() function is documented to set errno to EILSEQ; it probably can't set it to other values because the C standard says it shouldn't (though there's nothing much to stop an implementation from doing so if it has a better error for some condition).
POSIX 2008
The POSIX page for errno says:
Many functions provide an error number in errno, which has type int and is defined in <errno.h>. The value of errno shall be defined only after a call to a function for which it is explicitly stated to be set and until it is changed by the next function call or if the application assigns it a value. The value of errno should only be examined when it is indicated to be valid by a function's return value. Applications shall obtain the definition of errno by the inclusion of <errno.h>. No function in this volume of POSIX.1-2008 shall set errno to 0. The setting of errno after a successful call to a function is unspecified unless the description of that function specifies that errno shall not be modified.
It is unspecified whether errno is a macro or an identifier declared with external linkage. If a macro definition is suppressed in order to access an actual object, or a program defines an identifier with the name errno, the behavior is undefined.
The symbolic values stored in errno are documented in the ERRORS sections on all relevant pages.
The wording in previous versions was similar.
Is my use of errno to test if fopen() worked successfully,instead of "if(pFile==NULL)" unwise?
From 7.5 Errors/3 of the C99 standard:
The value of errno is zero at program startup, but is never set to zero by any library function.159) The value of errno may be set to nonzero by a library function call whether or not there is an error, provided the use of errno is not documented in the description of the function in this International Standard.
So checking errno to determine success or failure of an operation is unwise as a function is permitted to, pessimistically, set the value of errno to indicate failure, even if there is none. Only query errno if a function fails (if fopen() returns NULL or fputc() returns EOF for example).
Just looked into the manual pages to confirm that valid error numbers are all nonzero; errno is never set to zero by any system call or library function.
Check the Linux errno.h man page:
I believe you should look at return value and then look at errno.
I have basic code as follows,
fd = open("test.file", O_RDONLY);
if (read(fd, &tempch, 1) < 1) {
perror("File Read Error");
exit(1);
}
printf("We could read from the file\n");
the test.file is present in file system and has been granted with 777 rights. the program throws error "file read error: success"... could anybody tell the possible reason? thanks
It is perfectly normal for read() to return a zero count, it simply means that it has encountered the end of a file. If it returns a value less than zero, it is an error.
If -1 is returned, errno should be set, which will tell you what went wrong.
Does your file contain anything? Since you mentioned UNIX like permissions, the POSIX specification for read() should be useful for you.
You might want to check the return value of open and also how many bytes are present in test.file! If the file is of 0 bytes then return value of less than 1 is as expected.
From the read manual page
On success, the number of bytes read
is returned (zero indicates end of
file), and the file position is
advanced by this number. It is not an
error if this number is smaller than
the number of bytes requested; this
may happen for example because fewer
bytes are actually available right now
(maybe because we were close to
end-of-file, or because we are reading
from a pipe, or from a terminal), or
because read() was interrupted by a
signal.
I'm not certain, but this
if (read(fd, &tempch, 1) < 1)
should almost certainly be
if (read(fd, &tempch, 1) < 0)