Jeegar Patel
Jeegar Patel

Reputation: 27210

why fopen() or open() use errno instead of just returning error code?

In usual case open() return the new file descriptor, or -1 if an error occurred and in that case, errno is set appropriately.

I am not understanding why this mechanism of errno is used here? whats the purpose of here? why just we can not map all error with some negative return no?

like

fd = open("/dev/tty0", O_RDWR | O_SYNC);
if(fd == -1)
  printf("this is EACCES error");
else if (fd == -2)
    printf("this is EPERM error");

Is there any benifit of errno mechanism.? if yes then i would like to know/understand then in other things i can also use this mechanism.

Upvotes: 8

Views: 3136

Answers (4)

Jens Gustedt
Jens Gustedt

Reputation: 78903

Since fopen returns a FILE* you can't expect it to return an error code in that pointer: the only "special" value for pointers is 0.

As you observe, for open this restriction doesn't hold. In fact systems as linux do exactly what you propose in their lower levels. The system call under the hood returns the negative error code if things go wrong. That (negated) code is then plug into errno by a shallow user space wrapper which then returns the -1 to indicate the error to the application.

The reason that this is done so is purely historical. In good old times there was no threading and errno was still just a simple global variable. At that time the chosen strategy incurred not much overhead and probably seemed an acceptable way to communicate between OS and application. Since such interfaces basically can't be changed without breaking a lot of code, we will be stuck with errno as a pseudo variable that is thread local.

This is not ideal, but the overhead is not as bad as it sounds, since these are clearly error indications that should occur only exceptionally.

Upvotes: 12

Kerrek SB
Kerrek SB

Reputation: 477040

Giving each function a distinct set of return values makes it overly complicated to write code in a generic fashion. With the current semantics, you can adopt a universal pattern:

int fd;
if ((fd = some_function(arg1, arg2)) == -1)
{
    perror("some_function");
    exit(1);
}

You can even wrap this in a macro:

#define CALL_OR_DIE(function, ret, ...)      \
    if ((ret = function(__VA_ARGS__)) == -1) \
    { perror(#function); exit(1); }

Usage:

int fd;
CALL_OR_DIE(open, fd, "/dev/tty0", O_RDWR | O_SYNC);

Upvotes: 1

fvu
fvu

Reputation: 32953

For me the advantage is that getting the error information is unified in that way, returning some negative value would work OK with open as it returns an integer, but fopen returns a FILE * so another technique would have to be used there.

Upvotes: 9

user195488
user195488

Reputation:

errno is an error code. It is important to map the errors to what is actually happening so you can make strategic decisions in your code on what to do next. For instance, ERANGE which is defined in errno.h, will tell you that the result of strtol("0xfffffffff",NULL,0) is out of that function's range. More importantly in your example, it is good to know whether you have an EACCES or EPERM error so you know how to handle the file.

You can't map all problems with one error code since you could have multiple issues that you would like to catch and handle. When I say catch, I do not mean try/catch.

The use of errno establishes and error handling mechanism so you get more information than just -1.

ERANGE, EACCES, EPERM, and others are considered macros that map to a particular error number for convenience purposes.

Upvotes: 1

Related Questions