22

I'm learning about file descriptors and I wrote this code:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>

int fdrd, fdwr, fdwt;
char c;

main (int argc, char *argv[]) {

    if((fdwt = open("output", O_CREAT, 0777)) == -1) {
        perror("Error opening the file:");
        exit(1);
    }

    char c = 'x';

    if(write(fdwt, &c, 1) == -1) {
        perror("Error writing the file:");
    }

    close(fdwt);
    exit(0);

}

, but I'm getting: Error writing the file:: Bad file descriptor

I don't know what could be wrong, since this is a very simple example.

Sheena
  • 15,590
  • 14
  • 75
  • 113
Lucy
  • 241
  • 1
  • 3
  • 6
  • What is the val of fdwt on return from open( )? It should be a small integer, like less than 5. In fact, because no other fds are open in this code, it should be 3 (i.e., STDERR + 1). – Pete Wilson Jun 05 '11 at 20:11
  • 1
    Incidentally, your code has several problematic bits. Those variables don't need to be global (few ever do), you should declare them in `main`. You also declare `c` twice, you don't need the `char` in `char c` the second time. At the same time, the second declaration of `c` in the middle of the function is only valid in C99, but you declare `main` without a return type -- which is invalid in C99, which eliminates the "implicit int" rule that was present in C89 and earlier versions of C. Most compilers should issue warnings for that, some will throw an error and refuse to compile. – Nicholas Knight Jun 05 '11 at 20:27

4 Answers4

30

Try this:

open("output", O_CREAT|O_WRONLY, 0777)
patapizza
  • 2,398
  • 15
  • 14
  • 1
    Wow! So fast! :) That worked! Now I have to find out why! Thank you very much! – Lucy Jun 05 '11 at 20:04
  • 3
    @Lucy - It gave you a file descriptor, so the open didn't fail ... but the descriptor was not valid for writing. – asveikau Jun 05 '11 at 20:06
  • Could you explain why O_WRONLY is required, and where 0777 comes from? – r4bb1t Apr 12 '20 at 00:54
  • 0777 is honestly a bad idea from a security perspective (but it's what the OP already had). The "other" permissions shouldn't contain write without a _very_ good reason, nor should random data files be created with execute. – Charles Duffy Apr 08 '23 at 12:37
10

I think O_CREAT alone is not enough. Try adding O_WRONLY as flag to the open command.

RedX
  • 14,749
  • 1
  • 53
  • 76
9

According to the open(2) man page:

The argument flags must include one of the following access modes: O_RDONLY, O_WRONLY, or O_RDWR.

So yes, as suggested by others, please change your open to open("output", O_CREAT|O_WRONLY, 0777));. Use O_RDWR if you need to read from the file. You may also want O_TRUNC -- see the man page for details.

spacehunt
  • 803
  • 5
  • 8
0

My problem was that I used the S_IRUSR constant, which then, combined with O_CREAT created a file that can't be written to. So first run was OK, but on the second run I got the Bad file descriptor error message.

Using S_IRUSR | S_IWUSR solved the problem. Of course the badly created files have to be deleted.

int outfd = open("output.ppm", O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
Mutje
  • 1
  • 1