On Godbolt, opening /dev/null
for writing fails when you use fopen
but succeeds when you use open
, and I have no idea why.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
int main() {
if (fopen("/dev/null", "w") == NULL) {
perror("fopen");
}
if (open("/dev/null", O_WRONLY) == -1) {
perror("open");
}
}
https://godbolt.org/z/1Y6x58Tv6
Edit: I've since opened a bug report.
I mostly agree with the existing answer:
fopen( "/dev/null", "w")
means "open for writing, create if it doesn't exist, then truncate to zero bytes"
By trial and error, I discovered that the problematic flag is O_CREAT
— you can't create /dev/null
if it doesn't exist. Go figure.
Also by trial and error: the following works:
fopen("/dev/null", "r+")
Here, "r+"
means "open for reading and writing", which is a clumsy way to say "the file should exist". You don't need read permissions, so it's less than ideal.
Another way to make this work:
int fd = open("/dev/null", O_WRONLY);
FILE *f = fdopen(fd, "w");
The manual page for fdopen
says
The mode of the stream ... must be compatible with the mode of the file descriptor
which is vague, but of course this has no chance to fail because of O_CREAT
— fdopen
has no access to file name so it can't try to create it.
This looks like a configuration problem on this specific system; fopen
with plain "w"
mode should work. So you shouldn't change the way you usually write code because of this.