fclose(stdout) vs close(STDOUT_FILENO) - C [duplicate] - c

This question already has answers here:
Difference between fclose and close
(4 answers)
Closed 6 years ago.
I want to redirect STDOUT to a file on the disk. The point is to make the printf on my program write to a file instead of the console.
I saw some articles on the web where they used:
dup2(fileno(outputFile), STDOUT_FILENO);
Or:
close(STDOUT_FILENO);
dup(fileno(outputFile));
In every tutorial they use close() and it actually works. But I was curious and I tried to use fclose(stdout) instead but some error happened when I tried to use printf:
fclose(STDOUT_FILENO);
dup(fileno(outputFile));
Error:
Bad file descriptor
My question is, why does fclose() not work but close() does?
Thanks.

STDOUT_FILENO is a numeric file descriptor (usually 1). When you use close, you release the descriptor, but then reassign it with dup2. Any output to that descriptor will now go to the new file.
stdout on the other hand is a FILE*, an object of sorts that contains a file descriptor. Doing printf formats output into a buffer associated with the FILE, and then writes the buffer to the descriptor (depending upon the buffering mode). When you fclose a FILE*, it (normally) closes the underlying descriptor, and frees the FILE object. The dup2 does not ressurect stdout, so printf fails.

Related

Close file in C

Under Linux I use this code to redirect stdout and stderr on a file, as shown in the code the file is opened using fopen(f) and is it closed using close(fd).
int fd;
FILE *f;
f = fopen("test.txt", "rb+");
fd = fileno(f);
dup2(fd,STDOUT_FILENO);
dup2(fd,STDERR_FILENO);
close(fd);
My question is whether the close(fd) statement closes all file descriptors, or is it necessary to use fclose(f) as well ?
The rule is to close the outermost level. Here the FILE object pointed to by f contains the fd file handle but also internal data like a possible buffer and various pointers to it.
When you use close(fd), you free the kernel structures related to the file, but all the data structures provided by the standard library are not released. On the other hand, fclose(f) will internally close the fd file handle, but it will also release all the resources that were allocated by fopen.
TL/DR: if you use fd= open(...); to open a file, you should use close(fd); to close it, but if you use f = fopen(...);, then you should use fclose(f);.
As already pointed out in the other answers, you should use fclose(f); instead of close(fd);.
My question is whether the close(fd) statement closes all file descriptors [...]
No, it won't close all file descriptors. The file descriptors STDOUT_FILENO and STDERR_FILENO will still remain open and will now refer to the opened file test.txt. However, these file descriptors should probably not be closed, as it is good programming practice for STDOUT_FILENO and STDERR_FILENO to remain valid until the end of the program. They will be automatically closed by the kernel on process termination.
C FILE* streams use buffered I/O internally. fclose() flushes this buffer and then closes the file descriptor at OS level. close()'ing a FILE* stream may not flush this internal buffer and you may lose data. So for C streams always use C fxxx() functions.

What is the purpose of file descriptors? [duplicate]

This question already has answers here:
What's the difference between a file descriptor and a file pointer?
(9 answers)
Closed 4 years ago.
My understanding is that both fopen() and open() can be used to open files. open() returns a file descriptor. But they should be equivalent in terms of get a file for writing or reading. What is the purpose of definining the file descriptors? It is not clear from the wiki page.
https://en.wikipedia.org/wiki/File_descriptor
fopen returns a FILE * which is a wrapper around the file descriptor (I will ignore the "this is not required by the specification" aspect here, as I am not aware of an implementation that does not do this). At a high level, it looks like this:
application --FILE *--> libc --file descriptor--> kernel
Shells operate directly on file descriptors mainly because they are executing other programs, and you cannot modify the other program's FILE * objects. However, you are able to modify other program's file descriptors using the dup syscall at startup (i.e. between fork and exec). For example:
/bin/cat > foo.txt
This tells the shell to execute the /bin/cat program, but first redirect stdout (file descriptor #1) to a file that it opens. This is implemented as (pseudocode):
if (fork() == 0) {
int fd = open("foo.txt");
dup2(fd, 1);
exec("/bin/cat");
}
The closest thing you can do with FILE * is calling freopen, but this is not persisted when using exec unlike file descriptors.
But why do we need FILE * at all then, if it's just a wrapper around a file descriptor? One main benefit is having a readahead buffer. For example, consider fgets. This will eventually call the read syscall on the file descriptor associated with the FILE * that you pass in. But how does it know how much to read? The kernel has no option to say "give me one line" (line-buffered ttys aside). If you read more than one line in the first read, the next time you call fgets you might only get part of the next line, since the kernel has already given you the first part in the previous read syscall. The other option would be calling read one character at a time, which is horrible for performance.
So what does libc do? It reads a bunch of characters at once, then stores the extra characters in an internal buffer on the FILE * object. The next time you call fgets, it is able to use the internal buffer. This buffer is also shared with functions like fread, so you can interleave calls to fgets and fread without losing data.
The two function at different levels:
open() is a lower-level, POSIX function to open a file. It returns a distinct integer to identify, and enable access to, the file opened. This integer is a file descriptor.
fopen() is a higher-level, portable, C standard-library function to open a file.
On a POSIX system, the portable fopen() probably calls the nonportable open(), but this is an implementation detail.
When in doubt, prefer fopen().
For more information, on a Linux system, man 2 read. The POSIX read() function reads data via the file descriptor returned by open().

C read() function difficulty understanding file descriptor [duplicate]

This question already has answers here:
Strange behavior performing library functions on STDOUT and STDIN's file descriptors
(2 answers)
Closed 5 years ago.
I'm having difficulity understanding the read function in C.
len = read(fd, buf, 32);
when I assign fd as 0,1,2 and run the program, its basically doing the same thing, can someone tell me what difference does this make?
read() attempts to read up to count bytes from file descriptor fd.
fd = 0
fd = 1
fd = 2
Is reading from different file descriptors. The difference is, you are reading from different files, and the data read into the buffer is different.
What is the difference in reading from Book A and reading from Book B ? it is the same process of reading a book... it is the content that changes.
As far as I understand your question it is why nothing changes if you read from file descriptors 0, 1, 2.
In a normal program the file descriptor 0 is stdin, 1 is stdout and 2 is stderr. stdin is where you should read your input, 1 is where you should write your output and 2 is where you should write your error messages.
It is not uncommon that all three file descriptors may point to the same underlying file (a file can also be the console, network connection, etc.) behind the scenes. If you're just running your program from the command line this is actually quite likely. In that case you may be able to read from all of them and get the exact same result.
But. Then you decide that you want to save the output of the program in a file and run it like this: program > output. Now file descriptor 1 is no longer pointing to the same file as stdin and your program would break. Same thing happens if you point stderr to some error logging facility. Or get the input from a file or a pipe. Or run the program in some debuggers. Or a different terminal. This is why you should only read from 0 and no other file descriptors, even if you might get away with it sometimes.

Is possible opening stdin after close(0)? [duplicate]

This question already has answers here:
Re-opening stdout and stdin file descriptors after closing them
(3 answers)
Closed 6 years ago.
I have one question,studying standard I/O.
#include <stdio.h>
int main(){
void *mem = malloc(0x80);
close(0)
/*
something code (solution)
*/
read(0,mem,0x80);
}
with above code, Is possible opening stdin ?
before ask question on stackoverflow, i thought that open('/dev/tty'); .
but it not seem to completely open stdin.
i hope that do not use dup()
In my view, the ideal way to achieve this would be
use dup() to create a backup fd.
close() the stdin.
perform the operations
restore stdin using the dup2() and passing the previous backup fd.

application of open() and fopen() [duplicate]

This question already has answers here:
C fopen vs open
(11 answers)
Closed 8 years ago.
There are differences between open() and fopen() function. One is system call and other is library function. I try to figure out what is the application of these two function but I found nothing useful. Can you give some scenarios where to use open() and where fopen() should be used?
Sometimes you need a file descriptor. open() gives you one. Sometimes you need a FILE*, in which case use fopen(). You can always turn your FILE* into a file descriptor via fileno(), whereas the opposite transformation is not really supported. It mostly depends on what downstream functions you intend to call with the file handle.
open() will return the file descriptor. We overwrite the file, while using the fopen() we cannot overwrite the file. We use the file descriptor for reading and writing using the other
functions like read() write() etc. But in fopen() it will return file descriptor we have to
use fprintf() to write to the file stream. sscanf() to read from the stream.

Resources