1

I have to use a certain cross-platform library which passes FILE* objects around.

I get a file descriptor from another source (inherited), I want to keep same fd across fork'd processes.

I currently use fdopen to convert a file descriptor to a FILE* object.

My problem is that fclose used to clean up FILE* objects closes connected file descriptor.

I would very much like to keep this file descriptor after it has been used.

is there a way rescue file descriptor from FILE*?

Is there a way to detach it?

Or a way to substitute a file descriptor in FILE* with a dummy?

P.S. this needs to be cross-platform, well across POSIX anyway.

Dima Tisnek
  • 11,241
  • 4
  • 68
  • 120

4 Answers4

2

My problem is that fclose used to clean up FILE* objects closes connected file descriptor.

You could use dup(2) to get a copy of the descriptor. Then the close(2) that fclose(3) does won't do anything.

I need to maintain exact same fd number

Then call dup2 again after fclose: dup2(savedfd, rescuedfd)

cnicutar
  • 178,505
  • 25
  • 365
  • 392
  • Please read again, I need to maintain exact same `fd` number due to `fork`'s – Dima Tisnek Apr 11 '14 at 09:42
  • 1
    Hey, this might actually work. It's not thread-safe though, as another thread may allocate this very fd number between `close` and `dup2`. `dup3` will highlight this case but not solve it. I'll think about it! – Dima Tisnek Apr 11 '14 at 10:08
  • @qarma There are other tricks to help you, like hijacking `fclose` etc. I wouldn't go that road though. – cnicutar Apr 11 '14 at 10:18
2

Supposing that fd is your file descriptor and f your FILE* got from it. Maybe something like the following will do the trick:

fd2 = dup(fd);
fclose(f);
dup2(fd2, fd);
close(fd2);
Marian
  • 7,402
  • 2
  • 22
  • 34
1

When you get a file descriptor from another source, Try to get its filename from that file descriptor. (Some says its possible using platform specific method. -google it.)

Once you get filename then fopen it again and get FILE* and do your work and clean up it using fclose.

Your original fd will not be disturbed.

Jeegar Patel
  • 26,264
  • 51
  • 149
  • 222
0

Here's a non-portable idea (vote if you think this is good/best):

GNU libc provides fopencookie and BSD provides equivalent funopen.

These return real FILE* handle, but implementation is your own:

It is then relatively trivial to map read/write/seek/close functions to underlying system calls:

read/readfn(cookie, buf, size){ return read((int)cookie, buf, size); }
write/writefn(cookie, buf, size) { return write((int)cookie, buf, size); }
seek/seekfn(cookie, offs, arg) { return seek((int)cookie, offs, arg); } // may require arg mapping to whence
close/closefn(cookie) {} // that's the whole point!
Dima Tisnek
  • 11,241
  • 4
  • 68
  • 120