211

I have a FILE *, returned by a call to fopen(). I need to get a file descriptor from it, to make calls like fsync(fd) on it. What's the function to get a file descriptor from a file pointer?

Phil Miller
  • 36,389
  • 13
  • 67
  • 90
  • Or you could open the file with open(2), and you would have a file descriptor from the beginning – Antoine Pelisse Jun 29 '13 at 16:13
  • 11
    And the inverse: [How to get a FILE pointer from a file descriptor?](http://stackoverflow.com/questions/1941464/how-to-get-a-file-pointer-from-a-file-descriptor) – Michael Burr Oct 01 '13 at 20:35

3 Answers3

263

The proper function is int fileno(FILE *stream). It can be found in <stdio.h>, and is a POSIX standard but not standard C.

SO Stinks
  • 3,258
  • 4
  • 32
  • 37
Phil Miller
  • 36,389
  • 13
  • 67
  • 90
  • 4
    Strictly speaking, there wouldn't be any need to mention any headers or libraries if the function was indeed a part of standard C library. However, it is not standard, which is why it might make sense to mention the header at least. – AnT stands with Russia Jul 02 '10 at 23:55
  • 22
    Accessing functions in the standard C library does require including headers, at least if your compiler expects prototypes (I never remember what's actually standard behavior in that respect). Without headers, no names are defined at the beginning of a C file. – Phil Miller Jul 03 '10 at 00:20
  • 1
    @Novelocrat: I didn't mean that there's no need to `#include` anything. I merely meant that it is always easy to find the name of the proper header for a *standard* function. I.e. it is not really critical to mention the exact header name in the answer. – AnT stands with Russia Jul 03 '10 at 01:51
  • 10
    This is a good answer, but it is worth noting that this isn't a standard c function, it is a posix function. – Evan Teran Jul 03 '10 at 04:00
  • 9
    It is not in the C standard, because file descriptors are a UNIX thing (on Linux, it is open(2), not open(3)). – not-a-user Oct 16 '14 at 09:08
52

Even if fileno(FILE *) may return a file descriptor, be VERY careful not to bypass stdio's buffer. If there is buffer data (either read or unflushed write), reads/writes from the file descriptor might give you unexpected results.

To answer one of the side questions, to convert a file descriptor to a FILE pointer, use fdopen(3)

Brett Wolfington
  • 6,587
  • 4
  • 32
  • 51
Mark Gerolimatos
  • 2,424
  • 1
  • 23
  • 33
  • 1
    I don't believe this was helpful to people searching for this specifically, and this has already been answered in the comment section of OP's post a month before this was written. This is more of a logic clarification as opposed to real information. – kevr Feb 01 '18 at 15:03
  • 12
    Comments that are sooooper important need to be raised as answers. A huge percent of comments are snarky, pointless metacomments like yours...and this one ;) – Mark Gerolimatos Jan 15 '19 at 21:47
  • @MarkGerolimatos this answer is really helpful but would be even more so if you provided more info. Specifically, if I want to read/write to the file descriptor, how to I avoid bypassing stdio's buffer? Thanks! – Max888 Nov 20 '21 at 15:32
3
  fd = _fileno(fp);  // Probably the best way
       fd = fp->_file;     // direct from the FILE structure, member 

   
    typedef struct _iobuf  {
       char*   _ptr;
       int     _cnt;
       char*   _base;
       int     _flag;
       int     _file;
       int     _charbuf;
       int     _bufsiz;
       char*   _tmpfname; } FILE;