Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 452 Vote(s) - 3.58 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Is there any ordinary reason to use open() instead of fopen()?

#1
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).
Reply

#2
usually, you should favor using the standard library (fopen). However, there are occasions where you will need to use open directly.

One example that comes to mind is to work around a bug in an older version of solaris which made fopen fail after 256 files were open. This was because they erroniously used an unsigned char for the fd field in their struct FILE implementation instead of an int. But this was a very specific case.
Reply

#3
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.
Reply

#4

fopen works at a higher level than open ....
fopen returns you a pointer to FILE stream which is similar to the stream abstraction that you read in C++

open returns you a file descriptor for the file opened ... It does not provide you a stream abstraction and you are responsible for handling the bits and bytes yourself ... This is at a lower level as compared to fopen

Stdio streams are buffered, while open() file descriptors are not. Depends on what you need. You can also create one from the other:

int fileno (FILE * stream) returns the file descriptor for a FILE *, FILE * fdopen(int fildes, const char * mode) creates a FILE * from a file descriptor.

Be careful when intermixing buffered and non-buffered IO, since you'll lose what's in your buffer when you don't flush it with fflush().
Reply

#5
Yes. When you need a low-level handle.

On UNIX operating systems, you can generally exchange file handles and sockets.

Also, low-level handles make for better ABI compatibility than FILE pointers.
Reply

#6
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().




Reply

#7
fopen and its cousins are buffered. open, read, and write are not buffered. Your application may or may not care.

fprintf and scanf have a richer API that allows you to read and write formatted text files. read and write use fundamental arrays of bytes. Conversions and formatting must be hand crafted.

The difference between file descriptors and (FILE *) is really inconsequential.

Randy
Reply

#8
*read()* & *write()* use unbuffered I/O. (***fd***: integer file descriptor)

*fread()* & *fwrite()* use buffered I/O. (***FILE**** structure pointer)


Binary data written to a pipe with *write()* ***may not*** be able to read binary data with *fread()*, because of byte alignments, variable sizes, etc. Its a crap-shoot.

Most low-level device driver code uses unbuffered I/O calls.

Most application level I/O uses buffered.

Use of the *FILE** and its associated functions
is OK on a machine-by-machine basis: but portability is lost
on other architectures in the reading and writing of binary data.
fwrite() is buffered I/O and can lead to unreliable results if
written for a 64 bit architecture and run on a 32bit; or (Windows/Linux).
Most OSs have compatibility macros within their own code to prevent this.

For low-level binary I/O portability *read()* and *write()* guarantee
the same binary reads and writes when compiled on differing architectures.
The basic thing is to pick one way or the other and be consistent about it,
throughout the binary suite.

<stdio.h> // mostly FILE* some fd input/output parameters for compatibility
// gives you a lot of helper functions -->
List of Functions
Function Description
───────────────────────────────────────────────────────────────────
clearerr check and reset stream status
fclose close a stream
fdopen stream open functions //( fd argument, returns FILE*) feof check and reset stream status
ferror check and reset stream status
fflush flush a stream
fgetc get next character or word from input stream
fgetpos reposition a stream
fgets get a line from a stream
fileno get file descriptor // (FILE* argument, returns fd)
fopen stream open functions
fprintf formatted output conversion
fpurge flush a stream
fputc output a character or word to a stream
fputs output a line to a stream
fread binary stream input/output
freopen stream open functions
fscanf input format conversion
fseek reposition a stream
fsetpos reposition a stream
ftell reposition a stream
fwrite binary stream input/output
getc get next character or word from input stream
getchar get next character or word from input stream
gets get a line from a stream
getw get next character or word from input stream
mktemp make temporary filename (unique)
perror system error messages
printf formatted output conversion
putc output a character or word to a stream
putchar output a character or word to a stream
puts output a line to a stream
putw output a character or word to a stream
remove remove directory entry
rewind reposition a stream
scanf input format conversion
setbuf stream buffering operations
setbuffer stream buffering operations
setlinebuf stream buffering operations
setvbuf stream buffering operations
sprintf formatted output conversion
sscanf input format conversion
strerror system error messages
sys_errlist system error messages
sys_nerr system error messages
tempnam temporary file routines
tmpfile temporary file routines
tmpnam temporary file routines
ungetc un-get character from input stream
vfprintf formatted output conversion
vfscanf input format conversion
vprintf formatted output conversion
vscanf input format conversion
vsprintf formatted output conversion
vsscanf input format conversion

**So for basic use I would personally use the above without mixing idioms too much.**

By contrast,

<unistd.h> write()
lseek()
close()
pipe()
<sys/types.h>
<sys/stat.h>
<fcntl.h> open()
creat()
fcntl()
all use file descriptors.

These provide fine-grained control over reading and writing bytes
(recommended for special devices and fifos (pipes) ).

So again, use what you need, but keep consistent in your idioms and interfaces.
If most of your code base uses one mode , use that too, unless there is
a real reason not to. Both sets of I/O library functions are extremely reliable
and used millions of times a day.

*note--* If you are interfacing C I/O with another language,
(perl, python, java, c#, lua ...) *check out* what the developers of those languages
recommend before you write your C code and save yourself some trouble.
Reply



Forum Jump:


Users browsing this thread:
3 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through