Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(434)

Unified Diff: runtime/bin/file_win.cc

Issue 2698813002: [dart:io][windows] Make unicode characters display correctly. (Closed)
Patch Set: Address comments Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/bin/file_unsupported.cc ('k') | runtime/bin/io_natives.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/bin/file_win.cc
diff --git a/runtime/bin/file_win.cc b/runtime/bin/file_win.cc
index 989adfdc8148c199ab73e23a1ac2df9b83514ec6..af2a38fafa9b3038035d040098d84e3e9bb62a58 100644
--- a/runtime/bin/file_win.cc
+++ b/runtime/bin/file_win.cc
@@ -26,13 +26,48 @@ namespace bin {
class FileHandle {
public:
- explicit FileHandle(int fd) : fd_(fd) {}
+ explicit FileHandle(int fd)
+ : fd_(fd), real_fd_(-1), binary_(true), is_atty_(false) {}
~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);
};
@@ -49,14 +84,20 @@ File::~File() {
void File::Close() {
ASSERT(handle_->fd() >= 0);
- if ((handle_->fd() == _fileno(stdout)) ||
- (handle_->fd() == _fileno(stderr))) {
+ int closing_fd;
+ if (handle_->is_atty()) {
+ close(handle_->fd());
+ closing_fd = handle_->real_fd();
+ } else {
+ closing_fd = handle_->fd();
+ }
+ if ((closing_fd == _fileno(stdout)) || (closing_fd == _fileno(stderr))) {
int fd = _open("NUL", _O_WRONLY);
ASSERT(fd >= 0);
- _dup2(fd, handle_->fd());
+ _dup2(fd, closing_fd);
close(fd);
} else {
- int err = close(handle_->fd());
+ int err = close(closing_fd);
if (err != 0) {
Log::PrintErr("%s\n", strerror(errno));
}
@@ -130,8 +171,17 @@ int64_t File::Read(void* buffer, int64_t num_bytes) {
int64_t File::Write(const void* buffer, int64_t num_bytes) {
- ASSERT(handle_->fd() >= 0);
- return write(handle_->fd(), buffer, 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());
+ }
}
@@ -147,6 +197,17 @@ 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;
@@ -249,18 +310,33 @@ File* File::Open(const char* path, FileOpenMode mode) {
File* File::OpenStdio(int fd) {
+ int stdio_fd = -1;
switch (fd) {
case 1:
- fd = _fileno(stdout);
+ stdio_fd = _fileno(stdout);
break;
case 2:
- fd = _fileno(stderr);
+ stdio_fd = _fileno(stderr);
break;
default:
UNREACHABLE();
}
- _setmode(fd, _O_BINARY);
- return new File(new FileHandle(fd));
+ 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);
}
« no previous file with comments | « runtime/bin/file_unsupported.cc ('k') | runtime/bin/io_natives.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698