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

Side by Side Diff: runtime/bin/file_win.cc

Issue 2698813002: [dart:io][windows] Make unicode characters display correctly. (Closed)
Patch Set: Make tests pass 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "platform/globals.h" 5 #include "platform/globals.h"
6 #if defined(TARGET_OS_WINDOWS) 6 #if defined(TARGET_OS_WINDOWS)
7 7
8 #include "bin/file.h" 8 #include "bin/file.h"
9 9
10 #include <fcntl.h> // NOLINT 10 #include <fcntl.h> // NOLINT
11 #include <io.h> // NOLINT 11 #include <io.h> // NOLINT
12 #include <stdio.h> // NOLINT 12 #include <stdio.h> // NOLINT
13 #include <string.h> // NOLINT 13 #include <string.h> // NOLINT
14 #include <sys/stat.h> // NOLINT 14 #include <sys/stat.h> // NOLINT
15 #include <sys/utime.h> // NOLINT 15 #include <sys/utime.h> // NOLINT
16 #include <WinIoCtl.h> // NOLINT 16 #include <WinIoCtl.h> // NOLINT
17 17
18 #include "bin/builtin.h" 18 #include "bin/builtin.h"
19 #include "bin/log.h" 19 #include "bin/log.h"
20 #include "bin/utils.h" 20 #include "bin/utils.h"
21 #include "bin/utils_win.h" 21 #include "bin/utils_win.h"
22 #include "platform/utils.h" 22 #include "platform/utils.h"
23 23
24 namespace dart { 24 namespace dart {
25 namespace bin { 25 namespace bin {
26 26
27 class FileHandle { 27 class FileHandle {
28 public: 28 public:
29 explicit FileHandle(int fd) : fd_(fd) {} 29 explicit FileHandle(int fd)
30 : fd_(fd), real_fd_(-1), binary_(true), is_atty_(false) {}
30 ~FileHandle() {} 31 ~FileHandle() {}
31 int fd() const { return fd_; } 32 int fd() const { return fd_; }
32 void set_fd(int fd) { fd_ = fd; } 33 void set_fd(int fd) { fd_ = fd; }
33 34
35 int real_fd() const {
36 ASSERT(is_atty_);
37 return real_fd_;
38 }
39 void set_real_fd(int real_fd) {
40 ASSERT(is_atty_);
41 real_fd_ = real_fd;
42 }
43
44 bool binary() const { return binary_; }
45 void set_binary(bool binary) {
Florian Schneider 2017/02/21 20:34:50 SetBinary? - since it is not a simple setter
zra 2017/02/21 21:26:46 Done.
46 ASSERT(fd_ >= 0);
47 if (binary) {
48 // Setting the mode to _O_TEXT is needed first to reset _write to allow
49 // an odd number of bytes, which setting to _O_BINARY alone doesn't
50 // accomplish.
51 if (binary != binary_) {
52 _setmode(fd_, _O_TEXT);
53 }
54 _setmode(fd_, _O_BINARY);
55 } else {
56 // Only allow non-binary modes if we're attached to a terminal.
57 ASSERT(_isatty(fd_));
58 _setmode(fd_, _O_WTEXT);
59 }
60 binary_ = binary;
61 }
62
63 bool is_atty() const { return is_atty_; }
64 void set_is_atty(bool is_atty) { is_atty_ = is_atty; }
65
34 private: 66 private:
35 int fd_; 67 int fd_;
68 int real_fd_;
69 bool binary_;
70 bool is_atty_;
36 71
37 DISALLOW_COPY_AND_ASSIGN(FileHandle); 72 DISALLOW_COPY_AND_ASSIGN(FileHandle);
38 }; 73 };
39 74
40 75
41 File::~File() { 76 File::~File() {
42 if (!IsClosed() && handle_->fd() != _fileno(stdout) && 77 if (!IsClosed() && handle_->fd() != _fileno(stdout) &&
43 handle_->fd() != _fileno(stderr)) { 78 handle_->fd() != _fileno(stderr)) {
44 Close(); 79 Close();
45 } 80 }
46 delete handle_; 81 delete handle_;
47 } 82 }
48 83
49 84
50 void File::Close() { 85 void File::Close() {
51 ASSERT(handle_->fd() >= 0); 86 ASSERT(handle_->fd() >= 0);
52 if ((handle_->fd() == _fileno(stdout)) || 87 int closing_fd;
53 (handle_->fd() == _fileno(stderr))) { 88 if (handle_->is_atty()) {
89 close(handle_->fd());
90 closing_fd = handle_->real_fd();
91 } else {
92 closing_fd = handle_->fd();
93 }
94 if ((closing_fd == _fileno(stdout)) || (closing_fd == _fileno(stderr))) {
54 int fd = _open("NUL", _O_WRONLY); 95 int fd = _open("NUL", _O_WRONLY);
55 ASSERT(fd >= 0); 96 ASSERT(fd >= 0);
56 _dup2(fd, handle_->fd()); 97 _dup2(fd, closing_fd);
57 close(fd); 98 close(fd);
58 } else { 99 } else {
59 int err = close(handle_->fd()); 100 int err = close(closing_fd);
60 if (err != 0) { 101 if (err != 0) {
61 Log::PrintErr("%s\n", strerror(errno)); 102 Log::PrintErr("%s\n", strerror(errno));
62 } 103 }
63 } 104 }
64 handle_->set_fd(kClosedFd); 105 handle_->set_fd(kClosedFd);
65 } 106 }
66 107
67 108
68 intptr_t File::GetFD() { 109 intptr_t File::GetFD() {
69 return handle_->fd(); 110 return handle_->fd();
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
123 } 164 }
124 165
125 166
126 int64_t File::Read(void* buffer, int64_t num_bytes) { 167 int64_t File::Read(void* buffer, int64_t num_bytes) {
127 ASSERT(handle_->fd() >= 0); 168 ASSERT(handle_->fd() >= 0);
128 return read(handle_->fd(), buffer, num_bytes); 169 return read(handle_->fd(), buffer, num_bytes);
129 } 170 }
130 171
131 172
132 int64_t File::Write(const void* buffer, int64_t num_bytes) { 173 int64_t File::Write(const void* buffer, int64_t num_bytes) {
133 ASSERT(handle_->fd() >= 0); 174 int fd = handle_->fd();
134 return write(handle_->fd(), buffer, num_bytes); 175 ASSERT(fd >= 0);
176 if (handle_->binary()) {
177 return _write(fd, buffer, num_bytes);
178 } else {
179 // If we've done _setmode(fd, _O_WTEXT) then _write() expects
180 // a buffer of wchar_t with an even unmber of bytes.
181 Utf8ToWideScope wide(reinterpret_cast<const char*>(buffer), num_bytes);
182 ASSERT((wide.size_in_bytes() % 2) == 0);
183 return _write(fd, wide.wide(), wide.size_in_bytes());
184 }
135 } 185 }
136 186
137 187
138 int64_t File::Position() { 188 int64_t File::Position() {
139 ASSERT(handle_->fd() >= 0); 189 ASSERT(handle_->fd() >= 0);
140 return _lseeki64(handle_->fd(), 0, SEEK_CUR); 190 return _lseeki64(handle_->fd(), 0, SEEK_CUR);
141 } 191 }
142 192
143 193
144 bool File::SetPosition(int64_t position) { 194 bool File::SetPosition(int64_t position) {
145 ASSERT(handle_->fd() >= 0); 195 ASSERT(handle_->fd() >= 0);
146 return _lseeki64(handle_->fd(), position, SEEK_SET) >= 0; 196 return _lseeki64(handle_->fd(), position, SEEK_SET) >= 0;
147 } 197 }
148 198
149 199
200 void File::SetTranslation(DartFileTranslation translation) {
201 ASSERT(handle_->fd() >= 0);
202 // Only allow setting the translation mode if we're attached to a terminal.
203 // TODO(zra): Is this restriction needed? Is it already handled correctly
204 // by _write()?
205 if (handle_->is_atty()) {
206 handle_->set_binary(translation == kBinary);
207 }
208 }
209
210
150 bool File::Truncate(int64_t length) { 211 bool File::Truncate(int64_t length) {
151 ASSERT(handle_->fd() >= 0); 212 ASSERT(handle_->fd() >= 0);
152 return _chsize_s(handle_->fd(), length) == 0; 213 return _chsize_s(handle_->fd(), length) == 0;
153 } 214 }
154 215
155 216
156 bool File::Flush() { 217 bool File::Flush() {
157 ASSERT(handle_->fd()); 218 ASSERT(handle_->fd());
158 return _commit(handle_->fd()) != -1; 219 return _commit(handle_->fd()) != -1;
159 } 220 }
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 303
243 304
244 File* File::Open(const char* path, FileOpenMode mode) { 305 File* File::Open(const char* path, FileOpenMode mode) {
245 Utf8ToWideScope system_name(path); 306 Utf8ToWideScope system_name(path);
246 File* file = FileOpenW(system_name.wide(), mode); 307 File* file = FileOpenW(system_name.wide(), mode);
247 return file; 308 return file;
248 } 309 }
249 310
250 311
251 File* File::OpenStdio(int fd) { 312 File* File::OpenStdio(int fd) {
313 int stdio_fd = -1;
252 switch (fd) { 314 switch (fd) {
253 case 1: 315 case 1:
254 fd = _fileno(stdout); 316 stdio_fd = _fileno(stdout);
255 break; 317 break;
256 case 2: 318 case 2:
257 fd = _fileno(stderr); 319 stdio_fd = _fileno(stderr);
258 break; 320 break;
259 default: 321 default:
260 UNREACHABLE(); 322 UNREACHABLE();
261 } 323 }
262 _setmode(fd, _O_BINARY); 324 FileHandle* handle;
263 return new File(new FileHandle(fd)); 325 if (_isatty(stdio_fd)) {
326 // We _dup these fds so that we can do _setmode() without worrying about
327 // racing with other Isolates' calls to _setmode() and _write(). When the
siva 2017/02/22 00:58:45 Not sure I understand this comment, did we already
zra 2017/02/22 05:07:15 Tried to clarify. Without the _dup, calls to _setm
328 // corresponding Dart File object is closed, these dup'd fds will be
329 // closed.
330 int stdio_fd_dup = _dup(stdio_fd);
331 handle = new FileHandle(stdio_fd_dup);
332 handle->set_is_atty(true);
333 handle->set_real_fd(stdio_fd);
334 } else {
335 handle = new FileHandle(stdio_fd);
336 }
337 handle->set_binary(true);
338 return new File(handle);
264 } 339 }
265 340
266 341
267 static bool StatHelper(wchar_t* path, struct __stat64* st) { 342 static bool StatHelper(wchar_t* path, struct __stat64* st) {
268 int stat_status = _wstat64(path, st); 343 int stat_status = _wstat64(path, st);
269 if (stat_status != 0) { 344 if (stat_status != 0) {
270 return false; 345 return false;
271 } 346 }
272 if ((st->st_mode & S_IFMT) != S_IFREG) { 347 if ((st->st_mode & S_IFMT) != S_IFREG) {
273 SetLastError(ERROR_NOT_SUPPORTED); 348 SetLastError(ERROR_NOT_SUPPORTED);
(...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after
728 return kIdentical; 803 return kIdentical;
729 } else { 804 } else {
730 return kDifferent; 805 return kDifferent;
731 } 806 }
732 } 807 }
733 808
734 } // namespace bin 809 } // namespace bin
735 } // namespace dart 810 } // namespace dart
736 811
737 #endif // defined(TARGET_OS_WINDOWS) 812 #endif // defined(TARGET_OS_WINDOWS)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698