0

I was writting a function to copy contents of a file to another file, but i still don't know how to workout this. I have two functions that are involved in exiting the program incase of any errors;

void exitErr(char *str, char *file1 char *file2, int ext_val)
void closeFile(int fd1, int fd2)

These two function are supposed to write error message to stderr - function 1 when the program experiences an error,(prints error message and exit) and function 2 in case the file fails to close, the program exits, also, with an error meaasage. If there is an error in the program (read / write) I want to exit with code 99, and when the files fails to close, I want to exit with code 100. I've tried to combine the two function on a single statement like this

/**
 *opf1 = successful open to file 1
 *opf2 = successful open to file 2
 */
closeFile(opf1, opf2) && exitErr("Error: Can't write to %s\n", NULL, argv[2], 99);

but gcc is not compiling the code

3-cp.c:91:25: error: void value not ignored as it ought to be
   91 |                         closeFile(opf1, opf2) &&
      |                         ^~~~~~~~~~~~~~~~~~~~~
3-cp.c:92:33: error: void value not ignored as it ought to be
   92 |                                 exitErr("Error: Can't write to %s\n", NULL, argv[2], 99);

Now, Is this possible or I'm I trying the impossible? Here are the two function:

void exitErr(char *str, char *file1 char *file2, int ext_val)
{
        if (file1 == NULL && file2 != NULL)
                dprintf(STDERR_FILENO, str, file2);
        if (file2 == NULL && file1 != NULL)
                dprintf(STDERR_FILENO, str, file1);
        if (file1 == NULL && file2 == NULL)
                dprintf(STDERR_FILENO, str);
        else
                dprintf(STDERR_FILENO, str, file1, file2);
        exit(ext_val);
}
void closeFile(int fd1, int fd2)
{
        int c1 = 0, c2 = 0;

        if (fd1 == 0 && fd2 != 0)
                c2 = close(fd2);
        if (fd2 == 0 && fd1 != 0)
                c1 = close(fd1);
        else
        {
                c1 = close(fd1);
                c2 = close(fd2);
        }
        if (c1 == -1)
                dprintf(STDERR_FILENO, "Error: Can't close fd %d\n", fd1);
        if (c2 == -1)
                dprintf(STDERR_FILENO, "Error: Can't close fd %d\n", fd2);
        if (c1 == -1 || c2 == -1)
               exit(100);
}

test scenario

                if (wr < 0)
                {
                        closeFile(opf1, opf2) &&
                                exitErr("Error: Can't write to %s\n", NULL, argv[2], 99);
                }

I want to print all errors messages...

David Ranieri
  • 39,972
  • 7
  • 52
  • 94
Alex
  • 31
  • 6
  • 2
    In this case `void closeFile(int fd1, int fd2)` should be `int closeFile(int fd1, int fd2)` and `return 1;` from it , same for `exitErr()` – David Ranieri Aug 23 '22 at 09:08
  • 1
    `exitErr` is a void function (that does not return a value) and `closeFile(opf1, opf2) && exitErr(...` implies that `exitErr` returns a value, so what do you expect? You could transform `exitErr` into a function returnin and `int` and always return0, then you code will compile – Jabberwocky Aug 23 '22 at 09:10
  • 1
    Why do you want to write two separate actions in a single line? This will obfuscate your source, which is meant to be as clear as possible. Each reader, including yourself in some weeks or even days, will frown upon such a statement because of its hidden "magic". – the busybee Aug 23 '22 at 10:27
  • Thanks guys. I read through your comments and i followed your suggestions, although i didn't implement everything, but you guys are awesome. I've included what i did in the comment section below, although it's a dump solution but it worked. Let me know where i can do better on it. – Alex Aug 23 '22 at 13:33
  • @thebusybee because each function has different exit code, and both are required to trace the errors – Alex Aug 23 '22 at 13:56

3 Answers3

1

You can not use a logical (or a binary) operator with a function that doesn't return anything, if you want exitErr be called in this line:

closeFile(opf1, opf2) && exitErr(...);

you need to return a value other than 0 from closeFile

int closeFile(int fd1, int fd2)  
{
    ...
    return 1;
}

or return any value including 0 and use the OR operator instead of AND

closeFile(opf1, opf2) || exitErr(...);

exitErr must also return some value so that it can be evaluated as the right side of the operator.

David Ranieri
  • 39,972
  • 7
  • 52
  • 94
0

To call two functions, write two call statements:

closeFile(opf1, opf2)
exitErr("Error: Can't write to %s\n", NULL, argv[2], 99);

If you need one statement that calls two functions, use a compound statement:

{
    closeFile(opf1, opf2)
    exitErr("Error: Can't write to %s\n", NULL, argv[2], 99);
}
Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • the problem will be, if there is an error in closeFile, the program will exit and exitErr will not run, and i want both of them to run no matter the outcome of the other function. – Alex Aug 23 '22 at 13:54
  • 1
    @Alex: So modify `closeFile` not to exit. And update the question with a statement of precisely the behavior you want. – Eric Postpischil Aug 23 '22 at 15:16
0

Okay... Thanks guys for taking time to respond to my question and i really appreciate your help and suggestions. After following what you suggested, i changed one of the two exit function, (can't remember exactly which), but it didn't work, so i changed both functions exitErr(...) & closeFile(...) to return an int value which i assigned it into an "unused variable".

int __attribute__ ((unused)) ret;

if (wr < 0)
    {
        ret = closeFile(opf1, opf2) &&
            exitErr("Error: Can't write to %s\n", NULL, argv[2], 99);
    }

I haven't tested it on "intentional errors" environment, but it passed the compiler flags successfully.

NeverSleeps
  • 1,439
  • 1
  • 11
  • 39
Alex
  • 31
  • 6
  • Passing the compiler means only that you don't have any syntactical error. BTW, have you raised your warning level to the maximum? You can still have logical errors, which are more severe and commonly harder to find. Anyway, I think your code is overly complicated. -- I think you don't need this unused variable, simply remove the assignment and keep only the expression. It just clutters the source. – the busybee Aug 23 '22 at 14:23