| OLD | NEW |
| 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(HOST_OS_WINDOWS) | 6 #if defined(HOST_OS_WINDOWS) |
| 7 | 7 |
| 8 #include "bin/file.h" | 8 #include "bin/file.h" |
| 9 | 9 |
| 10 #include <WinIoCtl.h> // NOLINT |
| 10 #include <fcntl.h> // NOLINT | 11 #include <fcntl.h> // NOLINT |
| 11 #include <io.h> // NOLINT | 12 #include <io.h> // NOLINT |
| 12 #include <stdio.h> // NOLINT | 13 #include <stdio.h> // NOLINT |
| 13 #include <string.h> // NOLINT | 14 #include <string.h> // NOLINT |
| 14 #include <sys/stat.h> // NOLINT | 15 #include <sys/stat.h> // NOLINT |
| 15 #include <sys/utime.h> // NOLINT | 16 #include <sys/utime.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) : fd_(fd) {} |
| 30 ~FileHandle() {} | 30 ~FileHandle() {} |
| 31 int fd() const { return fd_; } | 31 int fd() const { return fd_; } |
| 32 void set_fd(int fd) { fd_ = fd; } | 32 void set_fd(int fd) { fd_ = fd; } |
| 33 | 33 |
| 34 private: | 34 private: |
| 35 int fd_; | 35 int fd_; |
| 36 | 36 |
| 37 DISALLOW_COPY_AND_ASSIGN(FileHandle); | 37 DISALLOW_COPY_AND_ASSIGN(FileHandle); |
| 38 }; | 38 }; |
| 39 | 39 |
| 40 | |
| 41 File::~File() { | 40 File::~File() { |
| 42 if (!IsClosed() && handle_->fd() != _fileno(stdout) && | 41 if (!IsClosed() && handle_->fd() != _fileno(stdout) && |
| 43 handle_->fd() != _fileno(stderr)) { | 42 handle_->fd() != _fileno(stderr)) { |
| 44 Close(); | 43 Close(); |
| 45 } | 44 } |
| 46 delete handle_; | 45 delete handle_; |
| 47 } | 46 } |
| 48 | 47 |
| 49 | |
| 50 void File::Close() { | 48 void File::Close() { |
| 51 ASSERT(handle_->fd() >= 0); | 49 ASSERT(handle_->fd() >= 0); |
| 52 int closing_fd = handle_->fd(); | 50 int closing_fd = handle_->fd(); |
| 53 if ((closing_fd == _fileno(stdout)) || (closing_fd == _fileno(stderr))) { | 51 if ((closing_fd == _fileno(stdout)) || (closing_fd == _fileno(stderr))) { |
| 54 int fd = _open("NUL", _O_WRONLY); | 52 int fd = _open("NUL", _O_WRONLY); |
| 55 ASSERT(fd >= 0); | 53 ASSERT(fd >= 0); |
| 56 _dup2(fd, closing_fd); | 54 _dup2(fd, closing_fd); |
| 57 close(fd); | 55 close(fd); |
| 58 } else { | 56 } else { |
| 59 int err = close(closing_fd); | 57 int err = close(closing_fd); |
| 60 if (err != 0) { | 58 if (err != 0) { |
| 61 Log::PrintErr("%s\n", strerror(errno)); | 59 Log::PrintErr("%s\n", strerror(errno)); |
| 62 } | 60 } |
| 63 } | 61 } |
| 64 handle_->set_fd(kClosedFd); | 62 handle_->set_fd(kClosedFd); |
| 65 } | 63 } |
| 66 | 64 |
| 67 | |
| 68 intptr_t File::GetFD() { | 65 intptr_t File::GetFD() { |
| 69 return handle_->fd(); | 66 return handle_->fd(); |
| 70 } | 67 } |
| 71 | 68 |
| 72 | |
| 73 bool File::IsClosed() { | 69 bool File::IsClosed() { |
| 74 return handle_->fd() == kClosedFd; | 70 return handle_->fd() == kClosedFd; |
| 75 } | 71 } |
| 76 | 72 |
| 77 | |
| 78 MappedMemory* File::Map(File::MapType type, int64_t position, int64_t length) { | 73 MappedMemory* File::Map(File::MapType type, int64_t position, int64_t length) { |
| 79 DWORD prot_alloc; | 74 DWORD prot_alloc; |
| 80 DWORD prot_final; | 75 DWORD prot_final; |
| 81 switch (type) { | 76 switch (type) { |
| 82 case File::kReadOnly: | 77 case File::kReadOnly: |
| 83 prot_alloc = PAGE_READWRITE; | 78 prot_alloc = PAGE_READWRITE; |
| 84 prot_final = PAGE_READONLY; | 79 prot_final = PAGE_READONLY; |
| 85 break; | 80 break; |
| 86 case File::kReadExecute: | 81 case File::kReadExecute: |
| 87 prot_alloc = PAGE_EXECUTE_READWRITE; | 82 prot_alloc = PAGE_EXECUTE_READWRITE; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 107 DWORD old_prot; | 102 DWORD old_prot; |
| 108 bool result = VirtualProtect(addr, length, prot_final, &old_prot); | 103 bool result = VirtualProtect(addr, length, prot_final, &old_prot); |
| 109 if (!result) { | 104 if (!result) { |
| 110 Log::PrintErr("VirtualProtect failed %d\n", GetLastError()); | 105 Log::PrintErr("VirtualProtect failed %d\n", GetLastError()); |
| 111 VirtualFree(addr, 0, MEM_RELEASE); | 106 VirtualFree(addr, 0, MEM_RELEASE); |
| 112 return NULL; | 107 return NULL; |
| 113 } | 108 } |
| 114 return new MappedMemory(addr, length); | 109 return new MappedMemory(addr, length); |
| 115 } | 110 } |
| 116 | 111 |
| 117 | |
| 118 void MappedMemory::Unmap() { | 112 void MappedMemory::Unmap() { |
| 119 BOOL result = VirtualFree(address_, 0, MEM_RELEASE); | 113 BOOL result = VirtualFree(address_, 0, MEM_RELEASE); |
| 120 ASSERT(result); | 114 ASSERT(result); |
| 121 address_ = 0; | 115 address_ = 0; |
| 122 size_ = 0; | 116 size_ = 0; |
| 123 } | 117 } |
| 124 | 118 |
| 125 | |
| 126 int64_t File::Read(void* buffer, int64_t num_bytes) { | 119 int64_t File::Read(void* buffer, int64_t num_bytes) { |
| 127 ASSERT(handle_->fd() >= 0); | 120 ASSERT(handle_->fd() >= 0); |
| 128 return read(handle_->fd(), buffer, num_bytes); | 121 return read(handle_->fd(), buffer, num_bytes); |
| 129 } | 122 } |
| 130 | 123 |
| 131 | |
| 132 int64_t File::Write(const void* buffer, int64_t num_bytes) { | 124 int64_t File::Write(const void* buffer, int64_t num_bytes) { |
| 133 int fd = handle_->fd(); | 125 int fd = handle_->fd(); |
| 134 ASSERT(fd >= 0); | 126 ASSERT(fd >= 0); |
| 135 HANDLE handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd)); | 127 HANDLE handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd)); |
| 136 DWORD written = 0; | 128 DWORD written = 0; |
| 137 BOOL result = WriteFile(handle, buffer, num_bytes, &written, NULL); | 129 BOOL result = WriteFile(handle, buffer, num_bytes, &written, NULL); |
| 138 if (!result) { | 130 if (!result) { |
| 139 return -1; | 131 return -1; |
| 140 } | 132 } |
| 141 DWORD mode; | 133 DWORD mode; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 154 MultiByteToWideChar(cp, 0, reinterpret_cast<const char*>(buffer), -1, wide, | 146 MultiByteToWideChar(cp, 0, reinterpret_cast<const char*>(buffer), -1, wide, |
| 155 written); | 147 written); |
| 156 int buffer_len = | 148 int buffer_len = |
| 157 WideCharToMultiByte(cp, 0, wide, written, NULL, 0, NULL, NULL); | 149 WideCharToMultiByte(cp, 0, wide, written, NULL, 0, NULL, NULL); |
| 158 delete wide; | 150 delete wide; |
| 159 bytes_written = buffer_len; | 151 bytes_written = buffer_len; |
| 160 } | 152 } |
| 161 return bytes_written; | 153 return bytes_written; |
| 162 } | 154 } |
| 163 | 155 |
| 164 | |
| 165 bool File::VPrint(const char* format, va_list args) { | 156 bool File::VPrint(const char* format, va_list args) { |
| 166 // Measure. | 157 // Measure. |
| 167 va_list measure_args; | 158 va_list measure_args; |
| 168 va_copy(measure_args, args); | 159 va_copy(measure_args, args); |
| 169 intptr_t len = _vscprintf(format, measure_args); | 160 intptr_t len = _vscprintf(format, measure_args); |
| 170 va_end(measure_args); | 161 va_end(measure_args); |
| 171 | 162 |
| 172 char* buffer = reinterpret_cast<char*>(malloc(len + 1)); | 163 char* buffer = reinterpret_cast<char*>(malloc(len + 1)); |
| 173 | 164 |
| 174 // Print. | 165 // Print. |
| 175 va_list print_args; | 166 va_list print_args; |
| 176 va_copy(print_args, args); | 167 va_copy(print_args, args); |
| 177 _vsnprintf(buffer, len + 1, format, print_args); | 168 _vsnprintf(buffer, len + 1, format, print_args); |
| 178 va_end(print_args); | 169 va_end(print_args); |
| 179 | 170 |
| 180 bool result = WriteFully(buffer, len); | 171 bool result = WriteFully(buffer, len); |
| 181 free(buffer); | 172 free(buffer); |
| 182 return result; | 173 return result; |
| 183 } | 174 } |
| 184 | 175 |
| 185 | |
| 186 int64_t File::Position() { | 176 int64_t File::Position() { |
| 187 ASSERT(handle_->fd() >= 0); | 177 ASSERT(handle_->fd() >= 0); |
| 188 return _lseeki64(handle_->fd(), 0, SEEK_CUR); | 178 return _lseeki64(handle_->fd(), 0, SEEK_CUR); |
| 189 } | 179 } |
| 190 | 180 |
| 191 | |
| 192 bool File::SetPosition(int64_t position) { | 181 bool File::SetPosition(int64_t position) { |
| 193 ASSERT(handle_->fd() >= 0); | 182 ASSERT(handle_->fd() >= 0); |
| 194 return _lseeki64(handle_->fd(), position, SEEK_SET) >= 0; | 183 return _lseeki64(handle_->fd(), position, SEEK_SET) >= 0; |
| 195 } | 184 } |
| 196 | 185 |
| 197 | |
| 198 bool File::Truncate(int64_t length) { | 186 bool File::Truncate(int64_t length) { |
| 199 ASSERT(handle_->fd() >= 0); | 187 ASSERT(handle_->fd() >= 0); |
| 200 return _chsize_s(handle_->fd(), length) == 0; | 188 return _chsize_s(handle_->fd(), length) == 0; |
| 201 } | 189 } |
| 202 | 190 |
| 203 | |
| 204 bool File::Flush() { | 191 bool File::Flush() { |
| 205 ASSERT(handle_->fd()); | 192 ASSERT(handle_->fd()); |
| 206 return _commit(handle_->fd()) != -1; | 193 return _commit(handle_->fd()) != -1; |
| 207 } | 194 } |
| 208 | 195 |
| 209 | |
| 210 bool File::Lock(File::LockType lock, int64_t start, int64_t end) { | 196 bool File::Lock(File::LockType lock, int64_t start, int64_t end) { |
| 211 ASSERT(handle_->fd() >= 0); | 197 ASSERT(handle_->fd() >= 0); |
| 212 ASSERT((end == -1) || (end > start)); | 198 ASSERT((end == -1) || (end > start)); |
| 213 HANDLE handle = reinterpret_cast<HANDLE>(_get_osfhandle(handle_->fd())); | 199 HANDLE handle = reinterpret_cast<HANDLE>(_get_osfhandle(handle_->fd())); |
| 214 OVERLAPPED overlapped; | 200 OVERLAPPED overlapped; |
| 215 ZeroMemory(&overlapped, sizeof(OVERLAPPED)); | 201 ZeroMemory(&overlapped, sizeof(OVERLAPPED)); |
| 216 | 202 |
| 217 overlapped.Offset = Utils::Low32Bits(start); | 203 overlapped.Offset = Utils::Low32Bits(start); |
| 218 overlapped.OffsetHigh = Utils::High32Bits(start); | 204 overlapped.OffsetHigh = Utils::High32Bits(start); |
| 219 | 205 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 243 } | 229 } |
| 244 rc = LockFileEx(handle, flags, 0, length_low, length_high, &overlapped); | 230 rc = LockFileEx(handle, flags, 0, length_low, length_high, &overlapped); |
| 245 break; | 231 break; |
| 246 } | 232 } |
| 247 default: | 233 default: |
| 248 UNREACHABLE(); | 234 UNREACHABLE(); |
| 249 } | 235 } |
| 250 return rc; | 236 return rc; |
| 251 } | 237 } |
| 252 | 238 |
| 253 | |
| 254 int64_t File::Length() { | 239 int64_t File::Length() { |
| 255 ASSERT(handle_->fd() >= 0); | 240 ASSERT(handle_->fd() >= 0); |
| 256 struct __stat64 st; | 241 struct __stat64 st; |
| 257 if (_fstat64(handle_->fd(), &st) == 0) { | 242 if (_fstat64(handle_->fd(), &st) == 0) { |
| 258 return st.st_size; | 243 return st.st_size; |
| 259 } | 244 } |
| 260 return -1; | 245 return -1; |
| 261 } | 246 } |
| 262 | 247 |
| 263 | |
| 264 File* File::FileOpenW(const wchar_t* system_name, FileOpenMode mode) { | 248 File* File::FileOpenW(const wchar_t* system_name, FileOpenMode mode) { |
| 265 int flags = O_RDONLY | O_BINARY | O_NOINHERIT; | 249 int flags = O_RDONLY | O_BINARY | O_NOINHERIT; |
| 266 if ((mode & kWrite) != 0) { | 250 if ((mode & kWrite) != 0) { |
| 267 ASSERT((mode & kWriteOnly) == 0); | 251 ASSERT((mode & kWriteOnly) == 0); |
| 268 flags = (O_RDWR | O_CREAT | O_BINARY | O_NOINHERIT); | 252 flags = (O_RDWR | O_CREAT | O_BINARY | O_NOINHERIT); |
| 269 } | 253 } |
| 270 if ((mode & kWriteOnly) != 0) { | 254 if ((mode & kWriteOnly) != 0) { |
| 271 ASSERT((mode & kWrite) == 0); | 255 ASSERT((mode & kWrite) == 0); |
| 272 flags = (O_WRONLY | O_CREAT | O_BINARY | O_NOINHERIT); | 256 flags = (O_WRONLY | O_CREAT | O_BINARY | O_NOINHERIT); |
| 273 } | 257 } |
| 274 if ((mode & kTruncate) != 0) { | 258 if ((mode & kTruncate) != 0) { |
| 275 flags = flags | O_TRUNC; | 259 flags = flags | O_TRUNC; |
| 276 } | 260 } |
| 277 int fd = _wopen(system_name, flags, 0666); | 261 int fd = _wopen(system_name, flags, 0666); |
| 278 if (fd < 0) { | 262 if (fd < 0) { |
| 279 return NULL; | 263 return NULL; |
| 280 } | 264 } |
| 281 if ((((mode & kWrite) != 0) && ((mode & kTruncate) == 0)) || | 265 if ((((mode & kWrite) != 0) && ((mode & kTruncate) == 0)) || |
| 282 (((mode & kWriteOnly) != 0) && ((mode & kTruncate) == 0))) { | 266 (((mode & kWriteOnly) != 0) && ((mode & kTruncate) == 0))) { |
| 283 int64_t position = _lseeki64(fd, 0, SEEK_END); | 267 int64_t position = _lseeki64(fd, 0, SEEK_END); |
| 284 if (position < 0) { | 268 if (position < 0) { |
| 285 return NULL; | 269 return NULL; |
| 286 } | 270 } |
| 287 } | 271 } |
| 288 return new File(new FileHandle(fd)); | 272 return new File(new FileHandle(fd)); |
| 289 } | 273 } |
| 290 | 274 |
| 291 | |
| 292 File* File::Open(const char* path, FileOpenMode mode) { | 275 File* File::Open(const char* path, FileOpenMode mode) { |
| 293 Utf8ToWideScope system_name(path); | 276 Utf8ToWideScope system_name(path); |
| 294 File* file = FileOpenW(system_name.wide(), mode); | 277 File* file = FileOpenW(system_name.wide(), mode); |
| 295 return file; | 278 return file; |
| 296 } | 279 } |
| 297 | 280 |
| 298 | |
| 299 File* File::OpenStdio(int fd) { | 281 File* File::OpenStdio(int fd) { |
| 300 int stdio_fd = -1; | 282 int stdio_fd = -1; |
| 301 switch (fd) { | 283 switch (fd) { |
| 302 case 1: | 284 case 1: |
| 303 stdio_fd = _fileno(stdout); | 285 stdio_fd = _fileno(stdout); |
| 304 break; | 286 break; |
| 305 case 2: | 287 case 2: |
| 306 stdio_fd = _fileno(stderr); | 288 stdio_fd = _fileno(stderr); |
| 307 break; | 289 break; |
| 308 default: | 290 default: |
| 309 UNREACHABLE(); | 291 UNREACHABLE(); |
| 310 } | 292 } |
| 311 _setmode(stdio_fd, _O_BINARY); | 293 _setmode(stdio_fd, _O_BINARY); |
| 312 return new File(new FileHandle(stdio_fd)); | 294 return new File(new FileHandle(stdio_fd)); |
| 313 } | 295 } |
| 314 | 296 |
| 315 | |
| 316 static bool StatHelper(wchar_t* path, struct __stat64* st) { | 297 static bool StatHelper(wchar_t* path, struct __stat64* st) { |
| 317 int stat_status = _wstat64(path, st); | 298 int stat_status = _wstat64(path, st); |
| 318 if (stat_status != 0) { | 299 if (stat_status != 0) { |
| 319 return false; | 300 return false; |
| 320 } | 301 } |
| 321 if ((st->st_mode & S_IFMT) != S_IFREG) { | 302 if ((st->st_mode & S_IFMT) != S_IFREG) { |
| 322 SetLastError(ERROR_NOT_SUPPORTED); | 303 SetLastError(ERROR_NOT_SUPPORTED); |
| 323 return false; | 304 return false; |
| 324 } | 305 } |
| 325 return true; | 306 return true; |
| 326 } | 307 } |
| 327 | 308 |
| 328 | |
| 329 bool File::Exists(const char* name) { | 309 bool File::Exists(const char* name) { |
| 330 struct __stat64 st; | 310 struct __stat64 st; |
| 331 Utf8ToWideScope system_name(name); | 311 Utf8ToWideScope system_name(name); |
| 332 return StatHelper(system_name.wide(), &st); | 312 return StatHelper(system_name.wide(), &st); |
| 333 } | 313 } |
| 334 | 314 |
| 335 | |
| 336 bool File::Create(const char* name) { | 315 bool File::Create(const char* name) { |
| 337 Utf8ToWideScope system_name(name); | 316 Utf8ToWideScope system_name(name); |
| 338 int fd = _wopen(system_name.wide(), O_RDONLY | O_CREAT, 0666); | 317 int fd = _wopen(system_name.wide(), O_RDONLY | O_CREAT, 0666); |
| 339 if (fd < 0) { | 318 if (fd < 0) { |
| 340 return false; | 319 return false; |
| 341 } | 320 } |
| 342 return (close(fd) == 0); | 321 return (close(fd) == 0); |
| 343 } | 322 } |
| 344 | 323 |
| 345 | |
| 346 // This structure is needed for creating and reading Junctions. | 324 // This structure is needed for creating and reading Junctions. |
| 347 typedef struct _REPARSE_DATA_BUFFER { | 325 typedef struct _REPARSE_DATA_BUFFER { |
| 348 ULONG ReparseTag; | 326 ULONG ReparseTag; |
| 349 USHORT ReparseDataLength; | 327 USHORT ReparseDataLength; |
| 350 USHORT Reserved; | 328 USHORT Reserved; |
| 351 | 329 |
| 352 union { | 330 union { |
| 353 struct { | 331 struct { |
| 354 USHORT SubstituteNameOffset; | 332 USHORT SubstituteNameOffset; |
| 355 USHORT SubstituteNameLength; | 333 USHORT SubstituteNameLength; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 366 USHORT PrintNameLength; | 344 USHORT PrintNameLength; |
| 367 WCHAR PathBuffer[1]; | 345 WCHAR PathBuffer[1]; |
| 368 } MountPointReparseBuffer; | 346 } MountPointReparseBuffer; |
| 369 | 347 |
| 370 struct { | 348 struct { |
| 371 UCHAR DataBuffer[1]; | 349 UCHAR DataBuffer[1]; |
| 372 } GenericReparseBuffer; | 350 } GenericReparseBuffer; |
| 373 }; | 351 }; |
| 374 } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; | 352 } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; |
| 375 | 353 |
| 376 | |
| 377 static const int kReparseDataHeaderSize = sizeof ULONG + 2 * sizeof USHORT; | 354 static const int kReparseDataHeaderSize = sizeof ULONG + 2 * sizeof USHORT; |
| 378 static const int kMountPointHeaderSize = 4 * sizeof USHORT; | 355 static const int kMountPointHeaderSize = 4 * sizeof USHORT; |
| 379 | 356 |
| 380 | |
| 381 bool File::CreateLink(const char* utf8_name, const char* utf8_target) { | 357 bool File::CreateLink(const char* utf8_name, const char* utf8_target) { |
| 382 Utf8ToWideScope name(utf8_name); | 358 Utf8ToWideScope name(utf8_name); |
| 383 int create_status = CreateDirectoryW(name.wide(), NULL); | 359 int create_status = CreateDirectoryW(name.wide(), NULL); |
| 384 // If the directory already existed, treat it as a success. | 360 // If the directory already existed, treat it as a success. |
| 385 if ((create_status == 0) && | 361 if ((create_status == 0) && |
| 386 ((GetLastError() != ERROR_ALREADY_EXISTS) || | 362 ((GetLastError() != ERROR_ALREADY_EXISTS) || |
| 387 ((GetFileAttributesW(name.wide()) & FILE_ATTRIBUTE_DIRECTORY) != 0))) { | 363 ((GetFileAttributesW(name.wide()) & FILE_ATTRIBUTE_DIRECTORY) != 0))) { |
| 388 return false; | 364 return false; |
| 389 } | 365 } |
| 390 | 366 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 428 dir_handle, FSCTL_SET_REPARSE_POINT, reparse_data_buffer, | 404 dir_handle, FSCTL_SET_REPARSE_POINT, reparse_data_buffer, |
| 429 reparse_data_buffer->ReparseDataLength + kReparseDataHeaderSize, NULL, 0, | 405 reparse_data_buffer->ReparseDataLength + kReparseDataHeaderSize, NULL, 0, |
| 430 &dummy_received_bytes, NULL); | 406 &dummy_received_bytes, NULL); |
| 431 free(reparse_data_buffer); | 407 free(reparse_data_buffer); |
| 432 if (CloseHandle(dir_handle) == 0) { | 408 if (CloseHandle(dir_handle) == 0) { |
| 433 return false; | 409 return false; |
| 434 } | 410 } |
| 435 return (result != 0); | 411 return (result != 0); |
| 436 } | 412 } |
| 437 | 413 |
| 438 | |
| 439 bool File::Delete(const char* name) { | 414 bool File::Delete(const char* name) { |
| 440 Utf8ToWideScope system_name(name); | 415 Utf8ToWideScope system_name(name); |
| 441 int status = _wremove(system_name.wide()); | 416 int status = _wremove(system_name.wide()); |
| 442 return status != -1; | 417 return status != -1; |
| 443 } | 418 } |
| 444 | 419 |
| 445 | |
| 446 bool File::DeleteLink(const char* name) { | 420 bool File::DeleteLink(const char* name) { |
| 447 Utf8ToWideScope system_name(name); | 421 Utf8ToWideScope system_name(name); |
| 448 bool result = false; | 422 bool result = false; |
| 449 DWORD attributes = GetFileAttributesW(system_name.wide()); | 423 DWORD attributes = GetFileAttributesW(system_name.wide()); |
| 450 if ((attributes != INVALID_FILE_ATTRIBUTES) && | 424 if ((attributes != INVALID_FILE_ATTRIBUTES) && |
| 451 (attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) { | 425 (attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) { |
| 452 // It's a junction(link), delete it. | 426 // It's a junction(link), delete it. |
| 453 result = (RemoveDirectoryW(system_name.wide()) != 0); | 427 result = (RemoveDirectoryW(system_name.wide()) != 0); |
| 454 } else { | 428 } else { |
| 455 SetLastError(ERROR_NOT_A_REPARSE_POINT); | 429 SetLastError(ERROR_NOT_A_REPARSE_POINT); |
| 456 } | 430 } |
| 457 return result; | 431 return result; |
| 458 } | 432 } |
| 459 | 433 |
| 460 | |
| 461 bool File::Rename(const char* old_path, const char* new_path) { | 434 bool File::Rename(const char* old_path, const char* new_path) { |
| 462 File::Type type = GetType(old_path, false); | 435 File::Type type = GetType(old_path, false); |
| 463 if (type == kIsFile) { | 436 if (type == kIsFile) { |
| 464 Utf8ToWideScope system_old_path(old_path); | 437 Utf8ToWideScope system_old_path(old_path); |
| 465 Utf8ToWideScope system_new_path(new_path); | 438 Utf8ToWideScope system_new_path(new_path); |
| 466 DWORD flags = MOVEFILE_WRITE_THROUGH | MOVEFILE_REPLACE_EXISTING; | 439 DWORD flags = MOVEFILE_WRITE_THROUGH | MOVEFILE_REPLACE_EXISTING; |
| 467 int move_status = | 440 int move_status = |
| 468 MoveFileExW(system_old_path.wide(), system_new_path.wide(), flags); | 441 MoveFileExW(system_old_path.wide(), system_new_path.wide(), flags); |
| 469 return (move_status != 0); | 442 return (move_status != 0); |
| 470 } else { | 443 } else { |
| 471 SetLastError(ERROR_FILE_NOT_FOUND); | 444 SetLastError(ERROR_FILE_NOT_FOUND); |
| 472 } | 445 } |
| 473 return false; | 446 return false; |
| 474 } | 447 } |
| 475 | 448 |
| 476 | |
| 477 bool File::RenameLink(const char* old_path, const char* new_path) { | 449 bool File::RenameLink(const char* old_path, const char* new_path) { |
| 478 File::Type type = GetType(old_path, false); | 450 File::Type type = GetType(old_path, false); |
| 479 if (type == kIsLink) { | 451 if (type == kIsLink) { |
| 480 Utf8ToWideScope system_old_path(old_path); | 452 Utf8ToWideScope system_old_path(old_path); |
| 481 Utf8ToWideScope system_new_path(new_path); | 453 Utf8ToWideScope system_new_path(new_path); |
| 482 DWORD flags = MOVEFILE_WRITE_THROUGH | MOVEFILE_REPLACE_EXISTING; | 454 DWORD flags = MOVEFILE_WRITE_THROUGH | MOVEFILE_REPLACE_EXISTING; |
| 483 int move_status = | 455 int move_status = |
| 484 MoveFileExW(system_old_path.wide(), system_new_path.wide(), flags); | 456 MoveFileExW(system_old_path.wide(), system_new_path.wide(), flags); |
| 485 return (move_status != 0); | 457 return (move_status != 0); |
| 486 } else { | 458 } else { |
| 487 SetLastError(ERROR_FILE_NOT_FOUND); | 459 SetLastError(ERROR_FILE_NOT_FOUND); |
| 488 } | 460 } |
| 489 return false; | 461 return false; |
| 490 } | 462 } |
| 491 | 463 |
| 492 | |
| 493 bool File::Copy(const char* old_path, const char* new_path) { | 464 bool File::Copy(const char* old_path, const char* new_path) { |
| 494 File::Type type = GetType(old_path, false); | 465 File::Type type = GetType(old_path, false); |
| 495 if (type == kIsFile) { | 466 if (type == kIsFile) { |
| 496 Utf8ToWideScope system_old_path(old_path); | 467 Utf8ToWideScope system_old_path(old_path); |
| 497 Utf8ToWideScope system_new_path(new_path); | 468 Utf8ToWideScope system_new_path(new_path); |
| 498 bool success = CopyFileExW(system_old_path.wide(), system_new_path.wide(), | 469 bool success = CopyFileExW(system_old_path.wide(), system_new_path.wide(), |
| 499 NULL, NULL, NULL, 0) != 0; | 470 NULL, NULL, NULL, 0) != 0; |
| 500 return success; | 471 return success; |
| 501 } else { | 472 } else { |
| 502 SetLastError(ERROR_FILE_NOT_FOUND); | 473 SetLastError(ERROR_FILE_NOT_FOUND); |
| 503 } | 474 } |
| 504 return false; | 475 return false; |
| 505 } | 476 } |
| 506 | 477 |
| 507 | |
| 508 int64_t File::LengthFromPath(const char* name) { | 478 int64_t File::LengthFromPath(const char* name) { |
| 509 struct __stat64 st; | 479 struct __stat64 st; |
| 510 Utf8ToWideScope system_name(name); | 480 Utf8ToWideScope system_name(name); |
| 511 if (!StatHelper(system_name.wide(), &st)) { | 481 if (!StatHelper(system_name.wide(), &st)) { |
| 512 return -1; | 482 return -1; |
| 513 } | 483 } |
| 514 return st.st_size; | 484 return st.st_size; |
| 515 } | 485 } |
| 516 | 486 |
| 517 | |
| 518 const char* File::LinkTarget(const char* pathname) { | 487 const char* File::LinkTarget(const char* pathname) { |
| 519 const wchar_t* name = StringUtilsWin::Utf8ToWide(pathname); | 488 const wchar_t* name = StringUtilsWin::Utf8ToWide(pathname); |
| 520 HANDLE dir_handle = CreateFileW( | 489 HANDLE dir_handle = CreateFileW( |
| 521 name, GENERIC_READ, | 490 name, GENERIC_READ, |
| 522 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, | 491 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, |
| 523 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, | 492 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, |
| 524 NULL); | 493 NULL); |
| 525 if (dir_handle == INVALID_HANDLE_VALUE) { | 494 if (dir_handle == INVALID_HANDLE_VALUE) { |
| 526 return NULL; | 495 return NULL; |
| 527 } | 496 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 571 0, NULL, NULL); | 540 0, NULL, NULL); |
| 572 char* utf8_target = DartUtils::ScopedCString(utf8_length + 1); | 541 char* utf8_target = DartUtils::ScopedCString(utf8_length + 1); |
| 573 if (0 == WideCharToMultiByte(CP_UTF8, 0, target, target_length, utf8_target, | 542 if (0 == WideCharToMultiByte(CP_UTF8, 0, target, target_length, utf8_target, |
| 574 utf8_length, NULL, NULL)) { | 543 utf8_length, NULL, NULL)) { |
| 575 return NULL; | 544 return NULL; |
| 576 } | 545 } |
| 577 utf8_target[utf8_length] = '\0'; | 546 utf8_target[utf8_length] = '\0'; |
| 578 return utf8_target; | 547 return utf8_target; |
| 579 } | 548 } |
| 580 | 549 |
| 581 | |
| 582 void File::Stat(const char* name, int64_t* data) { | 550 void File::Stat(const char* name, int64_t* data) { |
| 583 File::Type type = GetType(name, false); | 551 File::Type type = GetType(name, false); |
| 584 data[kType] = type; | 552 data[kType] = type; |
| 585 if (type != kDoesNotExist) { | 553 if (type != kDoesNotExist) { |
| 586 struct _stat64 st; | 554 struct _stat64 st; |
| 587 Utf8ToWideScope system_name(name); | 555 Utf8ToWideScope system_name(name); |
| 588 int stat_status = _wstat64(system_name.wide(), &st); | 556 int stat_status = _wstat64(system_name.wide(), &st); |
| 589 if (stat_status == 0) { | 557 if (stat_status == 0) { |
| 590 data[kCreatedTime] = st.st_ctime * 1000; | 558 data[kCreatedTime] = st.st_ctime * 1000; |
| 591 data[kModifiedTime] = st.st_mtime * 1000; | 559 data[kModifiedTime] = st.st_mtime * 1000; |
| 592 data[kAccessedTime] = st.st_atime * 1000; | 560 data[kAccessedTime] = st.st_atime * 1000; |
| 593 data[kMode] = st.st_mode; | 561 data[kMode] = st.st_mode; |
| 594 data[kSize] = st.st_size; | 562 data[kSize] = st.st_size; |
| 595 } else { | 563 } else { |
| 596 data[kType] = File::kDoesNotExist; | 564 data[kType] = File::kDoesNotExist; |
| 597 } | 565 } |
| 598 } | 566 } |
| 599 } | 567 } |
| 600 | 568 |
| 601 | |
| 602 time_t File::LastAccessed(const char* name) { | 569 time_t File::LastAccessed(const char* name) { |
| 603 struct __stat64 st; | 570 struct __stat64 st; |
| 604 Utf8ToWideScope system_name(name); | 571 Utf8ToWideScope system_name(name); |
| 605 if (!StatHelper(system_name.wide(), &st)) { | 572 if (!StatHelper(system_name.wide(), &st)) { |
| 606 return -1; | 573 return -1; |
| 607 } | 574 } |
| 608 return st.st_atime; | 575 return st.st_atime; |
| 609 } | 576 } |
| 610 | 577 |
| 611 | |
| 612 time_t File::LastModified(const char* name) { | 578 time_t File::LastModified(const char* name) { |
| 613 struct __stat64 st; | 579 struct __stat64 st; |
| 614 Utf8ToWideScope system_name(name); | 580 Utf8ToWideScope system_name(name); |
| 615 if (!StatHelper(system_name.wide(), &st)) { | 581 if (!StatHelper(system_name.wide(), &st)) { |
| 616 return -1; | 582 return -1; |
| 617 } | 583 } |
| 618 return st.st_mtime; | 584 return st.st_mtime; |
| 619 } | 585 } |
| 620 | 586 |
| 621 | |
| 622 bool File::SetLastAccessed(const char* name, int64_t millis) { | 587 bool File::SetLastAccessed(const char* name, int64_t millis) { |
| 623 // First get the current times. | 588 // First get the current times. |
| 624 struct __stat64 st; | 589 struct __stat64 st; |
| 625 Utf8ToWideScope system_name(name); | 590 Utf8ToWideScope system_name(name); |
| 626 if (!StatHelper(system_name.wide(), &st)) { | 591 if (!StatHelper(system_name.wide(), &st)) { |
| 627 return false; | 592 return false; |
| 628 } | 593 } |
| 629 | 594 |
| 630 // Set the new time: | 595 // Set the new time: |
| 631 struct __utimbuf64 times; | 596 struct __utimbuf64 times; |
| 632 times.actime = millis / kMillisecondsPerSecond; | 597 times.actime = millis / kMillisecondsPerSecond; |
| 633 times.modtime = st.st_mtime; | 598 times.modtime = st.st_mtime; |
| 634 return _wutime64(system_name.wide(), ×) == 0; | 599 return _wutime64(system_name.wide(), ×) == 0; |
| 635 } | 600 } |
| 636 | 601 |
| 637 | |
| 638 bool File::SetLastModified(const char* name, int64_t millis) { | 602 bool File::SetLastModified(const char* name, int64_t millis) { |
| 639 // First get the current times. | 603 // First get the current times. |
| 640 struct __stat64 st; | 604 struct __stat64 st; |
| 641 Utf8ToWideScope system_name(name); | 605 Utf8ToWideScope system_name(name); |
| 642 if (!StatHelper(system_name.wide(), &st)) { | 606 if (!StatHelper(system_name.wide(), &st)) { |
| 643 return false; | 607 return false; |
| 644 } | 608 } |
| 645 | 609 |
| 646 // Set the new time: | 610 // Set the new time: |
| 647 struct __utimbuf64 times; | 611 struct __utimbuf64 times; |
| 648 times.actime = st.st_atime; | 612 times.actime = st.st_atime; |
| 649 times.modtime = millis / kMillisecondsPerSecond; | 613 times.modtime = millis / kMillisecondsPerSecond; |
| 650 return _wutime64(system_name.wide(), ×) == 0; | 614 return _wutime64(system_name.wide(), ×) == 0; |
| 651 } | 615 } |
| 652 | 616 |
| 653 | |
| 654 bool File::IsAbsolutePath(const char* pathname) { | 617 bool File::IsAbsolutePath(const char* pathname) { |
| 655 // Should we consider network paths? | 618 // Should we consider network paths? |
| 656 if (pathname == NULL) { | 619 if (pathname == NULL) { |
| 657 return false; | 620 return false; |
| 658 } | 621 } |
| 659 return ((strlen(pathname) > 2) && (pathname[1] == ':') && | 622 return ((strlen(pathname) > 2) && (pathname[1] == ':') && |
| 660 ((pathname[2] == '\\') || (pathname[2] == '/'))); | 623 ((pathname[2] == '\\') || (pathname[2] == '/'))); |
| 661 } | 624 } |
| 662 | 625 |
| 663 | |
| 664 const char* File::GetCanonicalPath(const char* pathname) { | 626 const char* File::GetCanonicalPath(const char* pathname) { |
| 665 Utf8ToWideScope system_name(pathname); | 627 Utf8ToWideScope system_name(pathname); |
| 666 HANDLE file_handle = | 628 HANDLE file_handle = |
| 667 CreateFileW(system_name.wide(), 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, | 629 CreateFileW(system_name.wide(), 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, |
| 668 FILE_FLAG_BACKUP_SEMANTICS, NULL); | 630 FILE_FLAG_BACKUP_SEMANTICS, NULL); |
| 669 if (file_handle == INVALID_HANDLE_VALUE) { | 631 if (file_handle == INVALID_HANDLE_VALUE) { |
| 670 return NULL; | 632 return NULL; |
| 671 } | 633 } |
| 672 wchar_t dummy_buffer[1]; | 634 wchar_t dummy_buffer[1]; |
| 673 int required_size = | 635 int required_size = |
| (...skipping 16 matching lines...) Expand all Loading... |
| 690 (wcsncmp(path, L"\\\\?\\", 4) == 0) && | 652 (wcsncmp(path, L"\\\\?\\", 4) == 0) && |
| 691 (wcsncmp(system_name.wide(), L"\\\\?\\", 4) != 0)) { | 653 (wcsncmp(system_name.wide(), L"\\\\?\\", 4) != 0)) { |
| 692 result = StringUtilsWin::WideToUtf8(path + 4); | 654 result = StringUtilsWin::WideToUtf8(path + 4); |
| 693 } else { | 655 } else { |
| 694 result = StringUtilsWin::WideToUtf8(path); | 656 result = StringUtilsWin::WideToUtf8(path); |
| 695 } | 657 } |
| 696 CloseHandle(file_handle); | 658 CloseHandle(file_handle); |
| 697 return result; | 659 return result; |
| 698 } | 660 } |
| 699 | 661 |
| 700 | |
| 701 const char* File::PathSeparator() { | 662 const char* File::PathSeparator() { |
| 702 // This is already UTF-8 encoded. | 663 // This is already UTF-8 encoded. |
| 703 return "\\"; | 664 return "\\"; |
| 704 } | 665 } |
| 705 | 666 |
| 706 | |
| 707 const char* File::StringEscapedPathSeparator() { | 667 const char* File::StringEscapedPathSeparator() { |
| 708 // This is already UTF-8 encoded. | 668 // This is already UTF-8 encoded. |
| 709 return "\\\\"; | 669 return "\\\\"; |
| 710 } | 670 } |
| 711 | 671 |
| 712 | |
| 713 File::StdioHandleType File::GetStdioHandleType(int fd) { | 672 File::StdioHandleType File::GetStdioHandleType(int fd) { |
| 714 // Treat all stdio handles as pipes. The Windows event handler and | 673 // Treat all stdio handles as pipes. The Windows event handler and |
| 715 // socket code will handle the different handle types. | 674 // socket code will handle the different handle types. |
| 716 return kPipe; | 675 return kPipe; |
| 717 } | 676 } |
| 718 | 677 |
| 719 | |
| 720 File::Type File::GetType(const char* pathname, bool follow_links) { | 678 File::Type File::GetType(const char* pathname, bool follow_links) { |
| 721 // Convert to wchar_t string. | 679 // Convert to wchar_t string. |
| 722 Utf8ToWideScope name(pathname); | 680 Utf8ToWideScope name(pathname); |
| 723 DWORD attributes = GetFileAttributesW(name.wide()); | 681 DWORD attributes = GetFileAttributesW(name.wide()); |
| 724 File::Type result = kIsFile; | 682 File::Type result = kIsFile; |
| 725 if (attributes == INVALID_FILE_ATTRIBUTES) { | 683 if (attributes == INVALID_FILE_ATTRIBUTES) { |
| 726 result = kDoesNotExist; | 684 result = kDoesNotExist; |
| 727 } else if ((attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) { | 685 } else if ((attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) { |
| 728 if (follow_links) { | 686 if (follow_links) { |
| 729 HANDLE dir_handle = | 687 HANDLE dir_handle = |
| 730 CreateFileW(name.wide(), 0, | 688 CreateFileW(name.wide(), 0, |
| 731 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, | 689 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, |
| 732 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); | 690 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); |
| 733 if (dir_handle == INVALID_HANDLE_VALUE) { | 691 if (dir_handle == INVALID_HANDLE_VALUE) { |
| 734 result = File::kIsLink; | 692 result = File::kIsLink; |
| 735 } else { | 693 } else { |
| 736 CloseHandle(dir_handle); | 694 CloseHandle(dir_handle); |
| 737 result = File::kIsDirectory; | 695 result = File::kIsDirectory; |
| 738 } | 696 } |
| 739 } else { | 697 } else { |
| 740 result = kIsLink; | 698 result = kIsLink; |
| 741 } | 699 } |
| 742 } else if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { | 700 } else if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { |
| 743 result = kIsDirectory; | 701 result = kIsDirectory; |
| 744 } | 702 } |
| 745 return result; | 703 return result; |
| 746 } | 704 } |
| 747 | 705 |
| 748 | |
| 749 File::Identical File::AreIdentical(const char* file_1, const char* file_2) { | 706 File::Identical File::AreIdentical(const char* file_1, const char* file_2) { |
| 750 BY_HANDLE_FILE_INFORMATION file_info[2]; | 707 BY_HANDLE_FILE_INFORMATION file_info[2]; |
| 751 const char* file_names[2] = {file_1, file_2}; | 708 const char* file_names[2] = {file_1, file_2}; |
| 752 for (int i = 0; i < 2; ++i) { | 709 for (int i = 0; i < 2; ++i) { |
| 753 Utf8ToWideScope wide_name(file_names[i]); | 710 Utf8ToWideScope wide_name(file_names[i]); |
| 754 HANDLE file_handle = CreateFileW( | 711 HANDLE file_handle = CreateFileW( |
| 755 wide_name.wide(), 0, | 712 wide_name.wide(), 0, |
| 756 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, | 713 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, |
| 757 OPEN_EXISTING, | 714 OPEN_EXISTING, |
| 758 FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); | 715 FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 777 return kIdentical; | 734 return kIdentical; |
| 778 } else { | 735 } else { |
| 779 return kDifferent; | 736 return kDifferent; |
| 780 } | 737 } |
| 781 } | 738 } |
| 782 | 739 |
| 783 } // namespace bin | 740 } // namespace bin |
| 784 } // namespace dart | 741 } // namespace dart |
| 785 | 742 |
| 786 #endif // defined(HOST_OS_WINDOWS) | 743 #endif // defined(HOST_OS_WINDOWS) |
| OLD | NEW |