I'm trying to parse data from stdin in binary mode under Win32.
The first thing my code does is to check for a 4byte header at the beginning:
int riff_header;
fread(&riff_header, sizeof(riff_header), 1, ifp);
// 'RIFF' = little-endian
if (riff_header != 0x46464952) {
fprintf(stderr, "wav2msu: Incorrect header: Invalid format or endianness\n");
fprintf(stderr, " Value was: 0x%x\n", riff_header);
return -1;
}
stdin
has been switched to binary mode before reading from it:
if (*argv[argc-1] == '-') {
fprintf(stderr, "Reading from stdin.\n");
infile = stdin;
// We need to switch stdin to binary mode, or else we run
// into problems under Windows
freopen(NULL, "rb", stdin);
}
This code works fine under Linux, however on Win32 (specifically Windows XP), the fread
only seems to read a single byte and thus cause the evaluation to fail.
Example:
> ffmeg.exe -i ..\test.mp3 -f wav pipe:1 2> nul |..\foo.exe -o test.bin -
Reading from stdin.
foo: Incorrect header: Invalid format or endianness
Value was: 0x4
What am I doing wrong?
At http://pubs.opengroup.org/onlinepubs/009695399/functions/freopen.html I have found the following:
If filename is a null pointer, the freopen() function shall attempt to
change the mode of the stream to that specified by mode, as if the
name of the file currently associated with the stream had been used.
In this case, the file descriptor associated with the stream need not
be closed if the call to freopen() succeeds. It is
implementation-defined which changes of mode are permitted (if any),
and under what circumstances.
Maybe you should check if the change of mode (from text to binary) is allowed by the compiler and libraries you are using. Which compiler are you using?
Update / summary
Using MinGW you can call setmode() to switch the mode of the stdin stream.
You should set the mode to _O_BINARY, which is defined in fcntl.h.
For more information see e.g. http://gnuwin32.sourceforge.net/compile.html
According to the MSDN documentation, it's not permitted to pass NULL
for the path
parameter of freopen
, so the call to freopen
is almost certainly failing; have you checked the return value and the value of errno
? C89 does not specify the behavior of freopen
when path
is NULL
; C99 does, but the Microsoft C runtime is not (and does not claim to be) C99-compliant.
If you really need to read binary info from stdin
, you might have to use platform-specific code and read the raw binary data directly with ReadFile
on the file GetStdHandle(STD_INPUT_HANDLE)
.