Haiku's C library

Inspired by this post about Qemu & Haiku, I’m looking at the qemu source and building on & for Haiku. What’s the difference between open() and fopen()? The qemu source’s slirp libary (qemu/slirp/tftp.c) uses open(file_path, O_RDONLY | O_BINARY), and the I can’t find the binary flag in the Haiku source. For the time being, I put in a compiler directive to instead use fopen(file_path, "rb").

https://www.man7.org/linux/man-pages/man2/open.2.html
https://man7.org/linux/man-pages/man3/fopen.3.html

open comes from POSIX and fopen comes from the c standard. they pretty much do the same thing but they are not interchangeable. Haiku supports both.

1 Like

So then for Haiku, I should drop O_BINARY, since that doesn’t seem to exist? Using grep on src/ and headers/, I can see that there are a few places where it’s defined at 0 if not defined. Maybe that would be ideal for qemu.

What is the difference which makes them interchangeable? Is it how the file is closed?

According to this StackOverflow post Linux also does not have the O_BINARY or O_TEXT flags. Apparently they are specific to Windows because it is the only system which has to specify whether a file should be opened in binary or text mode.

Haiku could maybe define both as 0 just to make things easier to compile.

1 Like

in slirp.h there is:


#ifdef _WIN32

/* as defined in sdkddkver.h */
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0600 /* Vista */
#endif
/* reduces the number of implicitly included headers */
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <sys/timeb.h>
#include <iphlpapi.h>

#else
#if !defined(__HAIKU__)
#define O_BINARY 0
#endif
#endif

they are defining O_BINARY as 0 on non win32 platforms but for some reason not on haiku.

I’ll remove that from slirp.h in qemu’s code. I’m trying out to be the Haiku maintainer :slight_smile:

Simply speaking fopen() is a wrapper over open() and open() is a kernel syscall. fopen() use additional FILE structure, conversion and buffering mechanism, open() directly use kernel file descriptor.

4 Likes

I don’t get O_BINARY on MacOS either. I’m a little surprised, because it seems to me that I’ve seen it used and it wouldn’t have been on Windows. But it doesn’t make much sense to me - why would you support that kind of data transformation, with file operations at this level where there’s no support for reading by line?

Windows uses carriage returns and linefeeds together. Nothing outside of Microsoft does that. Unix conventions are to do a linefeed character at the end of a line without a carriage return so there is no need for translation for ASCII mode.

Reading a little further on it, I think I see why it’s this way.

The utility of this translation is fairly obvious with fopen(), since C I/O can use line separators to read line by line, but dubious if you’re reading data at the open() level (“POSIX” to us.) The examples where you’d make this distinction, however, involve both levels - you open() the file O_TEXT or O_BINARY, and then pass the handle to something like fdopen().

So legitimate support for this distinction requires kernel level support to attach that attribute to the file descriptor, to communicate it to the C I/O library or other library functions - it isn’t just that we don’t have CRLF data (we do, in network protocols like SMTP, and Windows filesystems), but that we presumably don’t have the means to support these flags as system level file descriptor attributes.

The implementation of these flags in Unix systems just does nothing. Binary and text files are the same. On some other platforms it could be different. On Windows it does some magic to convert line endings. I expect other systems (VMS?) will do other strange things. Maybe IBM does EBCDIC to ASCII conversion too?

1 Like