| Index: runtime/bin/file_win.cc
|
| diff --git a/runtime/bin/file_win.cc b/runtime/bin/file_win.cc
|
| index 883b911a13b0f571995859177f61852903d562bc..87734a9e20321420081b64ab2767154d3fd203d7 100644
|
| --- a/runtime/bin/file_win.cc
|
| +++ b/runtime/bin/file_win.cc
|
| @@ -26,48 +26,13 @@ namespace bin {
|
|
|
| class FileHandle {
|
| public:
|
| - explicit FileHandle(int fd)
|
| - : fd_(fd), real_fd_(-1), binary_(true), is_atty_(false) {}
|
| + explicit FileHandle(int fd) : fd_(fd) {}
|
| ~FileHandle() {}
|
| int fd() const { return fd_; }
|
| void set_fd(int fd) { fd_ = fd; }
|
|
|
| - int real_fd() const {
|
| - ASSERT(is_atty_);
|
| - return real_fd_;
|
| - }
|
| - void set_real_fd(int real_fd) {
|
| - ASSERT(is_atty_);
|
| - real_fd_ = real_fd;
|
| - }
|
| -
|
| - bool binary() const { return binary_; }
|
| - void SetBinary(bool binary) {
|
| - ASSERT(fd_ >= 0);
|
| - if (binary) {
|
| - // Setting the mode to _O_TEXT is needed first to reset _write to allow
|
| - // an odd number of bytes, which setting to _O_BINARY alone doesn't
|
| - // accomplish.
|
| - if (binary != binary_) {
|
| - _setmode(fd_, _O_TEXT);
|
| - }
|
| - _setmode(fd_, _O_BINARY);
|
| - } else {
|
| - // Only allow non-binary modes if we're attached to a terminal.
|
| - ASSERT(_isatty(fd_));
|
| - _setmode(fd_, _O_WTEXT);
|
| - }
|
| - binary_ = binary;
|
| - }
|
| -
|
| - bool is_atty() const { return is_atty_; }
|
| - void set_is_atty(bool is_atty) { is_atty_ = is_atty; }
|
| -
|
| private:
|
| int fd_;
|
| - int real_fd_;
|
| - bool binary_;
|
| - bool is_atty_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(FileHandle);
|
| };
|
| @@ -84,13 +49,7 @@ File::~File() {
|
|
|
| void File::Close() {
|
| ASSERT(handle_->fd() >= 0);
|
| - int closing_fd;
|
| - if (handle_->is_atty()) {
|
| - close(handle_->fd());
|
| - closing_fd = handle_->real_fd();
|
| - } else {
|
| - closing_fd = handle_->fd();
|
| - }
|
| + int closing_fd = handle_->fd();
|
| if ((closing_fd == _fileno(stdout)) || (closing_fd == _fileno(stderr))) {
|
| int fd = _open("NUL", _O_WRONLY);
|
| ASSERT(fd >= 0);
|
| @@ -173,15 +132,33 @@ int64_t File::Read(void* buffer, int64_t num_bytes) {
|
| int64_t File::Write(const void* buffer, int64_t num_bytes) {
|
| int fd = handle_->fd();
|
| ASSERT(fd >= 0);
|
| - if (handle_->binary()) {
|
| - return _write(fd, buffer, num_bytes);
|
| - } else {
|
| - // If we've done _setmode(fd, _O_WTEXT) then _write() expects
|
| - // a buffer of wchar_t with an even unmber of bytes.
|
| - Utf8ToWideScope wide(reinterpret_cast<const char*>(buffer), num_bytes);
|
| - ASSERT((wide.size_in_bytes() % 2) == 0);
|
| - return _write(fd, wide.wide(), wide.size_in_bytes());
|
| + HANDLE handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
|
| + DWORD written = 0;
|
| + BOOL result = WriteFile(handle, buffer, num_bytes, &written, NULL);
|
| + if (!result) {
|
| + return -1;
|
| }
|
| + DWORD mode;
|
| + int64_t bytes_written = written;
|
| + if (GetConsoleMode(handle, &mode)) {
|
| + // If `handle` is for a console, then `written` may refer to the number of
|
| + // characters printed to the screen rather than the number of bytes of the
|
| + // buffer that were actually consumed. To compute the number of bytes that
|
| + // were actually consumed, we convert the buffer to a wchar_t using the
|
| + // console's current code page, filling as many characters as were
|
| + // printed, and then convert that many characters back to the encoding for
|
| + // the code page, which gives the number of bytes of `buffer` used to
|
| + // generate the characters that were printed.
|
| + wchar_t* wide = new wchar_t[written];
|
| + int cp = GetConsoleOutputCP();
|
| + MultiByteToWideChar(cp, 0, reinterpret_cast<const char*>(buffer), -1, wide,
|
| + written);
|
| + int buffer_len =
|
| + WideCharToMultiByte(cp, 0, wide, written, NULL, 0, NULL, NULL);
|
| + delete wide;
|
| + bytes_written = buffer_len;
|
| + }
|
| + return bytes_written;
|
| }
|
|
|
|
|
| @@ -218,17 +195,6 @@ bool File::SetPosition(int64_t position) {
|
| }
|
|
|
|
|
| -void File::SetTranslation(DartFileTranslation translation) {
|
| - ASSERT(handle_->fd() >= 0);
|
| - // Only allow setting the translation mode if we're attached to a terminal.
|
| - // TODO(zra): Is this restriction needed? Is it already handled correctly
|
| - // by _write()?
|
| - if (handle_->is_atty()) {
|
| - handle_->SetBinary(translation == kBinary);
|
| - }
|
| -}
|
| -
|
| -
|
| bool File::Truncate(int64_t length) {
|
| ASSERT(handle_->fd() >= 0);
|
| return _chsize_s(handle_->fd(), length) == 0;
|
| @@ -342,22 +308,8 @@ File* File::OpenStdio(int fd) {
|
| default:
|
| UNREACHABLE();
|
| }
|
| - FileHandle* handle;
|
| - if (_isatty(stdio_fd)) {
|
| - // We _dup these fds to avoid different Isoaltes racing on calls to
|
| - // _setmode() and _write() on the same file descriptor. That is, a call to
|
| - // _setmode() followed by a call to _write() on the same file descriptor is
|
| - // not atomic. When the corresponding Dart File object is closed, these
|
| - // dup'd fds will be closed.
|
| - int stdio_fd_dup = _dup(stdio_fd);
|
| - handle = new FileHandle(stdio_fd_dup);
|
| - handle->set_is_atty(true);
|
| - handle->set_real_fd(stdio_fd);
|
| - } else {
|
| - handle = new FileHandle(stdio_fd);
|
| - }
|
| - handle->SetBinary(true);
|
| - return new File(handle);
|
| + _setmode(stdio_fd, _O_BINARY);
|
| + return new File(new FileHandle(stdio_fd));
|
| }
|
|
|
|
|
|
|