"fprintf"-like function for file descriptors (i.e. int fd instead of FILE* fp)
Asked Answered
N

5

22

Maybe I'm just missing it, but isn't there a function equivalent to fprintf for file descriptors, or even a way to temporarily flip-flop between them?

Natie answered 22/11, 2010 at 14:43 Comment(0)
S
33

You could look into dprintf (GNU extensions, not in C or POSIX) :

The functions dprintf() and vdprintf() (as found in the glibc2 library) are exact analogues of fprintf() and vfprintf(), except that they output to a file descriptor fd instead of to a given stream.

EDIT As pointed by several of you in the comments, POSIX 2008 standardized these functions.

Shrader answered 22/11, 2010 at 14:45 Comment(4)
Thanks! Very interesting, had no idea those existed.Donner
Nor did I. Since this app is only going to run on Linux, this may be what I need. Cross-platform compatibility is not a concern, so using the GNU extension should be fine.Natie
If portability is not a concern, go for these.Belligerent
Indeed, POSIX 2008 standardized these functions.Ashling
B
9

There is no C or POSIX (edit: prior to 2008) standard function to do printf on a file descriptor, but you can “open” a file descriptor as a FILE * with the POSIX-standard fdopen(int desc, const char *mode). I'm not sure how well supported flipping back to using the descriptor directly is, but I'm guessing it might work if you flush the buffer first…

Of course you could just implement your own using something like vsprintf, but obviously you then have to take care of the buffering.

Belligerent answered 22/11, 2010 at 15:2 Comment(3)
I was thinking of fdopen, but really don't want to "open" another handle, especially since IIRC calling fclose on that handle will close the underlying file descriptor as well. That would be a problem with the code I'm working on, as the routine may get either a file descriptor or a socket handle.Natie
@Will: you can fdopen a file handled gotten from dup, so that the close won't affect your original fdDownstate
@Hasturkun: That's right, I forgot about dup. Not one of those functions I use regularly.Natie
N
3

For what it's worth, since dprintf is not a POSIX function, one could use the following if portability is an issue:

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>

int
fdprintf ( int fd, size_t bufmax, const char * fmt, ... )
{
  char * buffer;
  int n;
  va_list ap;

  buffer = ( char * ) malloc ( bufmax );
  if ( !buffer )
    return 0;

  va_start ( ap, fmt );
  n = vsnprintf ( buffer, bufmax, fmt, ap );
  va_end ( ap );

  write ( fd, buffer, n );
  free ( buffer );
  return n;
}

Most likely would want to check the return value of write, but you get the general idea. Obviously, this does not buffer like the FILE * routines do; I was looking more for the format specifiers and the ability to build the character data that would be written to the file descriptor, rather than worrying about buffering the data as it is being written.

Natie answered 22/11, 2010 at 15:45 Comment(2)
dprintf is POSIX (as of 2008), and functions that truncate data silently are usually a very bad idea. At least loop with larger buffers until it succeeds or return failure...Ashling
That's cool. My gcc version here is a little older and still shows dprintf as being only a GNU extension.Natie
P
2

No, there isn't as standard, but the two do different things. fprinft, as part of stdio, does things like buffer reads and writes, supports ungetc etc. Using a fd bypasses all that and calls the OS directly.

So they're not interchangeable. Flip flopping between them would screw up stdio buffering if nothing else

Periodate answered 22/11, 2010 at 14:47 Comment(3)
That's what I thought, but wasn't 100% sure.Natie
Except... you can do fdopen and flip flopping works just fine as long as you remember to flush() when needed.Weigela
Probably, but not guaranteed, and probably doesn't work if you seek to a different position, and...Periodate
A
2

You can open the file descriptor as a normal file that can be handled by fprintf() with fdopen.

Audie answered 22/11, 2010 at 15:3 Comment(1)
Just discovered dprintf up-thread which looks interesting, but reading this gave me a thought: how bad would it be to pass a fd into a function and call fdopen(fd) every single function call, if performance wasn't a concern? I'm imagining this would probably leak memory like crazy at the very least. (And then there are implementation differences to take into account, perhaps some implementations would leak and some wouldn't.) Or maybe this would work?Superheat

© 2022 - 2024 — McMap. All rights reserved.