Skip to content

Commit

Permalink
Fix binary files being clobbered in DirectoryAssetBundle on Windows
Browse files Browse the repository at this point in the history
FXL has various places where files are opened using `open` without the
`O_BINARY` flag.

As a workaround, I've implemented file reading on Windows using cstdio.
  • Loading branch information
ds84182 committed Mar 1, 2018
1 parent 245bbf2 commit 68ec232
Showing 1 changed file with 46 additions and 4 deletions.
50 changes: 46 additions & 4 deletions assets/directory_asset_bundle.cc
Expand Up @@ -7,6 +7,10 @@

#include <fcntl.h>

#if defined(OS_WIN)
#include <cstdio>
#endif

#include <utility>

#include "lib/fxl/files/eintr_wrapper.h"
Expand All @@ -19,11 +23,49 @@ namespace blink {

bool DirectoryAssetBundle::GetAsBuffer(const std::string& asset_name,
std::vector<uint8_t>* data) {
if (fd_.is_valid()) {
#if defined(OS_WIN)
// This code path is not valid in a Windows environment.
return false;
{
// On Windows, files::ReadFileToVector doesn't open the file with the O_BINARY flag
// Without this flag, binary data gets clobbered because '\n' gets translated to '\r\n'
// To avoid this, we use cstdio to read the file instead

struct AutoFile {
FILE* file_handle;
explicit AutoFile(FILE* handle) : file_handle(handle) {}
~AutoFile() {
std::fclose(file_handle);
}
operator FILE*() {
return file_handle;
}
};

auto path = GetPathForAsset(asset_name);
AutoFile fh(std::fopen(path.c_str(), "rb"));

if (!fh)
return false;

constexpr size_t kBufferSize = 1 << 16;
size_t offset = 0;
ssize_t bytes_read = 0;
do {
offset += bytes_read;
data->resize(offset + kBufferSize);
bytes_read = std::fread(&(*data)[offset], 1, kBufferSize, fh);
} while (bytes_read > 0);

if (bytes_read < 0) {
FXL_LOG(ERROR) << "Reading " << asset_name << " failed";
data->clear();
return false;
}

data->resize(offset + bytes_read);
return true;
}
#else
if (fd_.is_valid()) {
fxl::UniqueFD asset_file(openat(fd_.get(), asset_name.c_str(), O_RDONLY));
if (!asset_file.is_valid())
return false;
Expand All @@ -45,8 +87,8 @@ bool DirectoryAssetBundle::GetAsBuffer(const std::string& asset_name,

data->resize(offset + bytes_read);
return true;
#endif
}
#endif
std::string asset_path = GetPathForAsset(asset_name);
if (asset_path.empty())
return false;
Expand Down

0 comments on commit 68ec232

Please sign in to comment.