revert #16663, which was a revert of #16039
i believe the issue with #16039 was the loss of the semantics provided by the "b" part of the mode in `fopen()`. this is a nop on unix-like systems, but appears to be significant on windows.

the equivalent functionality on windows in `open()` is the `O_BINARY` flag. this adds that to the `open()` call, and provides compat for it on platforms without the flag by defining it to 0.

while here, fix an fd leak in `new_file_source()` if the buffer allocation fails.

 - [ ] closes #xxxx
 - [ ] tests added / passed
 - [ ] passes ``git diff upstream/master --name-only -- '*.py' | flake8 --diff``
 - [ ] whatsnew entry
