By using fdopen(), fileno() it's possible to open streams with existing file descriptors. However the proper way to close a file, once you've opened it with a stream is to fclose() the FILE pointer. How can one close the stream, but retain the open file descriptor?
This behaviour is akin to calling fflush() and then fileno(), and then never using the FILE pointer again, except in closing. An additional concern is that if you then fdopen() again, there are now multiple FILE pointers, and you can only close one of them.
If you're on a POSIXy system (which I assume you are, since you have fileno()), you can use dup() to clone the file descriptor:
int newfd = dup(fileno(stream));
fclose(stream);
Or you can hand fdopen() a duplicate file descriptor:
FILE *stream = fdopen(dup(fd), "r");
Either way, the other copy of the fd won't close with the FILE *. However, keep in mind the location pointer is shared, so be careful if you are using both at the same time. Also, any fcntl() locks held on the original fd will be released when you close the copy.
If everything else fails, dup(2) could help.
Related
When I want to change directory using a file descriptor, should I close the directory FD after calling fchdir, or the fchdir closes the FD automatically?
int fd = open(…);
if (fd == -1) error();
fchdir(fd);
//close(fd);
IMHO, if the code is done with fd to never use it again, call close.
The call to fchdir will not close the file descriptor (see the posix description of fchdir
).
fchdir likely (depends on OS and file system) obtains the needed information from fd before returning to the caller. Here is an example of how one specific OS file system handles system calls for fchdir
For a more informed decision whether you should or should not close fd investigate the description of close:
The close() function shall deallocate the file descriptor indicated by fildes. To deallocate means to make the file descriptor available for return by subsequent calls to open() or other functions that allocate file descriptors. All outstanding record locks owned by the process on the file associated with the file descriptor shall be removed (that is, unlocked).
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.
When should we use fdopen and how do we use it? My understanding of that is when we can't use fopen to read (read from pipe). I don't really understand the description of fdopen on the man page: The fdopen() function associates a stream with the existing file descriptor, fd.
You use fdopen() when you have a file descriptor (int fd;) of some sort but you need to call functions that require a file stream (FILE *fp;) instead. This could be a pipe file descriptor, or a socket file descriptor, or any other file descriptor type.
Once you've used fdopen(), you should not use the file descriptor again — you should use only the file stream. If you must use a file descriptor as well, it would be best to use fileno(fp) rather than the saved fd. Most importantly, if you mix access, you need to ensure that you've flushed the file stream before you do anything with the file descriptor. (There's no buffering with the file descriptor, so there's less of a problem reverting to the file stream from the file descriptor.). Operations that change the current file position on the file descriptor could mess up the file stream and vice versa (when there is a current position associated with the file descriptor or file stream). Note that both read and write operations change the current file position — there's not a lot you can do without risking a mess.
You must use fclose(fp); to close the file stream (and implicitly the file descriptor). Do NOT use just close(fd) or close(fileno(fp)).
Note that POSIX defines dprintf() to do formatted output to a file descriptor. Also, you could use snprintf() or its relatives to format data into a string and then write the string to the file descriptor. This might make it less important to use fdopen().
If I fopen a file, what's the difference between calling fclose or close and which one should I use?
If forked children have access to the file as well, what should they do when they are finished with the file?
fclose() is function related with file streams. When you open file with the help of fopen() and assign stream to FILE *ptr. Then you will use fclose() to close the opened file.
close() is a function related with file descriptors. When you open file with the help of open() and assign descriptor to int fd. Then you will use close() to close the opened file.
The functions like fopen(), fclose() etc are C standard functions, while the other category of open(), close() etc are POSIX-specific. This means that code written with open(), close() etc is not a standard C code and hence non-portable. Whereas the code written with fopen(), fclose etc is a standard code and can be ported on any type of system.
which one should I use?
It depends on how you opened the file. If you open a file with fopen(), you should use fclose() and if you open file with open(), you should use close().
If forked children have access to the file as well, what should they do when they are finished with the file?
This is also dependent on where you made the fork() call: before opening the file or after opening it.
See: Are file descriptors shared when fork()ing?
See: man fclose and man close
open() and close() are UNIX syscalls which return and take file descriptors, for use with other UNIX syscalls such as write(). fopen() and fclose() are standard C library functions which operate on FILE*s, for use with things like fwrite and fprintf. The latter are almost always what you should be using: They're simpler and more cross-platform.
As for your second question, forked children have the same numeric file descriptor as the parent, but it's a copy; they can close it, and it will still be open for the parent and other children. (Though personally, I don't like to have files open when I fork()... I like to make that sort of shared resource usage explicit. Pipes, of course, are an exception.)
which one should I use?
If you open a file with fopen, close it with fclose. Using close in this case may cause a memory leak on a handle allocated by fopen
When I create a socket using accept() and make a FILE out of it using fdopen(), what do I have to do to clean everything up? Do I need to do fclose() on the FILE, shutdown() and close() on the socket, or only the shutdown() and or close() or fclose()? If I don't do fclose(), do I have to free() the FILE pointer manually?
From man fdopen:
The file descriptor is not dup’ed, and will be closed when the stream created by fdopen() is closed
So I would just use fclose(), which also closes the underlying file descriptor. I don't know whether shutdown() is needed, either.
From http://opengroup.org/onlinepubs/007908775/xsh/fclose.html
The fclose() function will perform a
close() on the file descriptor that is
associated with the stream pointed to
by stream.
If you've wrapped your socket in a stream it probably no longer makes sense to shutdown(), at least not without flushing the stream first. But I won't swear to that, because I don't know that there are no uses where you'd want to shutdown() rather than just close().
You have 2 things here you need to clean up: the stream represented by FILE and the file descriptor represented by the socket. You need to close the stream first, then the file descriptor. So, in general you will need to fclose() any FILE objects, then close() any file descriptors.
Personally I have never used shutdown() when I want to cleanup after myself, so I can't say.
edit
Others have correctly pointed out that fdclose() will also close the underlying file descriptor, and since calling close() on a close file descriptor will lead to an error, in this case you only need fdclose().