Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any ordinary reason to use open() instead of fopen()?

Tags:

c

file

posix

libc

I'm doing a small project in C after quite a long time away from it. These happen to include some file handling. I noticed in various documentation that there are functions which return FILE * handles and others which return (small integer) descriptors. Both sets of functions offer the same basic services I need so it really does not matter I use.

But I'm curious about the collection wisdom: is it better to use fopen() and friends, or open() and friends?

Edit Since someone mentioned buffered vs unbuffered and accessing devices, I should add that one part of this small project will be writing a userspace filesystem driver under FUSE. So the file level access could as easily be on a device (e.g. a CDROM or a SCSI drive) as on a "file" (i.e. an image).

like image 393
staticsan Avatar asked Feb 13 '09 04:02

staticsan


2 Answers

It is better to use open() if you are sticking to unix-like systems and you might like to:

  • Have more fine-grained control over unix permission bits on file creation.
  • Use the lower-level functions such as read/write/mmap as opposed to the C buffered stream I/O functions.
  • Use file descriptor (fd) based IO scheduling (poll, select, etc.) You can of course obtain an fd from a FILE * using fileno(), but care must be taken not to mix FILE * based stream functions with fd based functions.
  • Open any special device (not a regular file)

It is better to use fopen/fread/fwrite for maximum portability, as these are standard C functions, the functions I've mentioned above aren't.

like image 193
Chris Young Avatar answered Oct 29 '22 16:10

Chris Young


The objection that "fopen" is portable and "open" isn't is bogus.

fopen is part of libc, open is a POSIX system call.

Each is as portable as the place they come from.

i/o to fopen'ed files is (you must assume it may be, and for practical purposes, it is) buffered by libc, file descriptors open()'ed are not buffered by libc (they may well be, and usually are buffered in the filesystem -- but not everything you open() is a file on a filesystem.

What's the point of fopen'ing, for example, a device node like /dev/sg0, say, or /dev/tty0... What are you going to do? You're going to do an ioctl on a FILE *? Good luck with that.

Maybe you want to open with some flags like O_DIRECT -- makes no sense with fopen().

like image 31
smcameron Avatar answered Oct 29 '22 17:10

smcameron