explain_ferror(3)

πŸ“¦
version 1.4.D001 Β· 2 versions
, in debian bookworm, debian trixie, ubuntu jammy, ubuntu noble, ubuntu resolute

πŸ’– explain_ferror β€” the libexplain glow-up for ferror(3) πŸ’–

okay bestie, so you're out here calling ferror(3) and it's being messy, and you want an actual explanation instead of just vibes? that's literally what explain_ferror is for. this is the manual page for the libexplain functions that decode those errors for you. no cap. ✨


🌸 NAME 🌸

explain_ferror β€” bestie, this explains ferror(3) errors πŸ’…


πŸŽ€ SYNOPSIS πŸŽ€

#include <libexplain/ferror.h>
const char *explain_ferror(FILE *fp);
const char *explain_errno_ferror(int errnum, FILE *fp);
void explain_message_ferror(char *message, int message_size, FILE *fp);
void explain_message_errno_ferror(char *message, int message_size, int
errnum, FILE *fp);

πŸ¦‹ DESCRIPTION πŸ¦‹

so these functions? they're how you get explanations for errors that come back from the ferror(3) system call. that's the whole job. iconic behaviour honestly.


⭐ explain_ferror ⭐

const char *explain_ferror(FILE *fp);

explain_ferror is your girl for getting an explanation of an error that ferror(3) handed you. the bare minimum the message will contain is the value of strerror(errno), but usually it goes so much harder and tells you the underlying cause in way more detail. it's giving overachiever, and we love that. 😌

the errno global variable is what gets used to grab the error value that needs decoding.

this function is meant to be used kinda like this:

if (ferror(fp) < 0)
{
    fprintf(stderr, "%s\n", explain_ferror(fp));
    exit(EXIT_FAILURE);
}
🚨 bestie, listen β€” it is essential that this function gets placed as close as possible to the I/O code that caused the problem. otherwise the code in between could have altered the errno global variable and then your explanation is just lying to you. 😭

fp β€” the original fp, exactly as passed to the ferror(3) system call. like, don't be cute with it, pass it exactly.

Returns: the message explaining the error. ⚠️ heads up: this message buffer is shared by all the libexplain functions that don't supply a buffer in their argument list. it will get overwritten by the next call to any libexplain function that shares this buffer β€” including calls from other threads. so don't go holding onto it.

Note: this function is not thread safe, because it shares a return buffer across all threads, and so do many other functions in this library. not me being the bearer of bad news 🫠

πŸ’œ explain_errno_ferror πŸ’œ

const char *explain_errno_ferror(int errnum, FILE *fp);

explain_errno_ferror is the version where you bring the error number to the party. it obtains an explanation of an error returned by the ferror(3) system call. the least the message will contain is the value of strerror(errnum), but usually it does much better and points at the underlying cause in more detail. slay. πŸ”₯

this function is intended to be used in a fashion similar to this:

if (ferror(fp) < 0)
{
    int err = errno;
    fprintf(stderr, "%s\n", explain_errno_ferror(err, fp));
    exit(EXIT_FAILURE);
}
🚨 same energy as before: it is essential that this function gets placed as close as possible to the I/O code that caused the problem, otherwise intervening code could have altered the errno global variable. keep it tight. 🫢

errnum β€” the error value to be decoded, usually grabbed from the errno global variable right before this function is called. you need this if you have to run any code between the system call you're explaining and this function, because many libc functions will alter the value of errno. sneaky of them.

fp β€” the original fp, exactly as passed to the ferror(3) system call.

Returns: the message explaining the error. and again, ⚠️ this message buffer is shared by all libexplain functions which do not supply a buffer in their argument list. it will be overwritten by the next call to any libexplain function which shares this buffer, including other threads. it's a whole thing.

Note: this function is not thread safe, because it shares a return buffer across all threads, and many other functions in this library do too.

🌈 explain_message_ferror 🌈

void explain_message_ferror(char *message, int message_size, FILE *fp);

explain_message_ferror may be used to obtain an explanation of an error returned by the ferror(3) system call. the least the message will contain is the value of strerror(errno), but usually it does much better and indicates the underlying cause in more detail. she's thorough. πŸ’…

the errno global variable is what's used to obtain the error value to be decoded.

this function is intended to be used in a fashion similar to this:

if (ferror(fp) < 0)
{
    char message[3000];
    explain_message_ferror(message, sizeof(message), fp);
    fprintf(stderr, "%s\n", message);
    exit(EXIT_FAILURE);
}
🚨 yes, again: it is essential that this function gets placed as close as possible to the I/O code that has caused the problem, otherwise intervening code could have altered the errno global variable. i'm not gonna stop saying it. πŸ™ˆ

message β€” the location in which to store the returned message. good news: if you supply a suitable message return buffer, this function is thread safe. character development! πŸŽ€

message_size β€” the size in bytes of the location in which to store the returned message.

fp β€” the original fp, exactly as passed to the ferror(3) system call.


🧚 explain_message_errno_ferror 🧚

void explain_message_errno_ferror(char *message, int message_size, int
errnum, FILE *fp);

explain_message_errno_ferror may be used to obtain an explanation of an error returned by the ferror(3) system call. the least the message will contain is the value of strerror(errnum), but usually it does much better and indicates the underlying cause in more detail. main character energy fr fr. πŸ‘‘

this function is intended to be used in a fashion similar to this:

if (ferror(fp) < 0)
{
    int err = errno;
    char message[3000];
    explain_message_errno_ferror(message, sizeof(message), err, fp);
    fprintf(stderr, "%s\n", message);
    exit(EXIT_FAILURE);
}
🚨 and one more time for the people in the back: it is essential that this function gets placed as close as possible to the I/O code that has caused the problem, otherwise intervening code could have altered the errno global variable. πŸ™

message β€” the location in which to store the returned message. if a suitable message return buffer is supplied, this function is thread safe. we stan a safe function.

message_size β€” the size in bytes of the location in which to store the returned message.

errnum β€” the error value to be decoded, usually obtained from the errno global variable just before this function is called. this is necessary if you need to call any code between the system call to be explained and this function, because many libc functions will alter the value of errno. they're chaotic like that.

fp β€” the original fp, exactly as passed to the ferror(3) system call.


πŸ‘€ SEE ALSO πŸ‘€

  • ferror(3) β€” check stream status. the origin story.
  • explain_ferror_or_die(3) β€” check stream status and report errors. the dramatic version that literally exits if things go wrong πŸ’€

this is libexplain version 1.4, and the copyright belongs to Copyright (C) 2008 Peter Miller. respect the elders. 🫑


and that's the whole page, bestie β€” go forth and actually understand your ferror(3) errors. periodt. πŸ’–βœ¨πŸ¦‹

πŸ“¦ where this page comes from