| 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(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 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 39 | 39 |
| 40 | 40 |
| 41 File::~File() { | 41 File::~File() { |
| 42 Close(); | 42 Close(); |
| 43 delete handle_; | 43 delete handle_; |
| 44 } | 44 } |
| 45 | 45 |
| 46 | 46 |
| 47 void File::Close() { | 47 void File::Close() { |
| 48 ASSERT(handle_->fd() >= 0); | 48 ASSERT(handle_->fd() >= 0); |
| 49 if (handle_->fd() == _fileno(stdout) || handle_->fd() == _fileno(stderr)) { | 49 if ((handle_->fd() == _fileno(stdout)) || |
| 50 (handle_->fd() == _fileno(stderr))) { |
| 50 int fd = _open("NUL", _O_WRONLY); | 51 int fd = _open("NUL", _O_WRONLY); |
| 51 ASSERT(fd >= 0); | 52 ASSERT(fd >= 0); |
| 52 _dup2(fd, handle_->fd()); | 53 _dup2(fd, handle_->fd()); |
| 53 close(fd); | 54 close(fd); |
| 54 } else { | 55 } else { |
| 55 int err = close(handle_->fd()); | 56 int err = close(handle_->fd()); |
| 56 if (err != 0) { | 57 if (err != 0) { |
| 57 Log::PrintErr("%s\n", strerror(errno)); | 58 Log::PrintErr("%s\n", strerror(errno)); |
| 58 } | 59 } |
| 59 } | 60 } |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 111 ASSERT(handle_->fd() >= 0); | 112 ASSERT(handle_->fd() >= 0); |
| 112 ASSERT(end == -1 || end > start); | 113 ASSERT(end == -1 || end > start); |
| 113 HANDLE handle = reinterpret_cast<HANDLE>(_get_osfhandle(handle_->fd())); | 114 HANDLE handle = reinterpret_cast<HANDLE>(_get_osfhandle(handle_->fd())); |
| 114 OVERLAPPED overlapped; | 115 OVERLAPPED overlapped; |
| 115 ZeroMemory(&overlapped, sizeof(OVERLAPPED)); | 116 ZeroMemory(&overlapped, sizeof(OVERLAPPED)); |
| 116 | 117 |
| 117 overlapped.Offset = Utils::Low32Bits(start); | 118 overlapped.Offset = Utils::Low32Bits(start); |
| 118 overlapped.OffsetHigh = Utils::High32Bits(start); | 119 overlapped.OffsetHigh = Utils::High32Bits(start); |
| 119 | 120 |
| 120 int64_t length = end == -1 ? 0 : end - start; | 121 int64_t length = end == -1 ? 0 : end - start; |
| 121 if (length == 0) length = kMaxInt64; | 122 if (length == 0) { |
| 123 length = kMaxInt64; |
| 124 } |
| 122 int32_t length_low = Utils::Low32Bits(length); | 125 int32_t length_low = Utils::Low32Bits(length); |
| 123 int32_t length_high = Utils::High32Bits(length); | 126 int32_t length_high = Utils::High32Bits(length); |
| 124 | 127 |
| 125 | 128 |
| 126 BOOL rc; | 129 BOOL rc; |
| 127 switch (lock) { | 130 switch (lock) { |
| 128 case File::kLockUnlock: | 131 case File::kLockUnlock: |
| 129 rc = UnlockFileEx(handle, 0, length_low, length_high, &overlapped); | 132 rc = UnlockFileEx(handle, 0, length_low, length_high, &overlapped); |
| 130 break; | 133 break; |
| 131 case File::kLockShared: | 134 case File::kLockShared: |
| (...skipping 16 matching lines...) Expand all Loading... |
| 148 int64_t File::Length() { | 151 int64_t File::Length() { |
| 149 ASSERT(handle_->fd() >= 0); | 152 ASSERT(handle_->fd() >= 0); |
| 150 struct __stat64 st; | 153 struct __stat64 st; |
| 151 if (_fstat64(handle_->fd(), &st) == 0) { | 154 if (_fstat64(handle_->fd(), &st) == 0) { |
| 152 return st.st_size; | 155 return st.st_size; |
| 153 } | 156 } |
| 154 return -1; | 157 return -1; |
| 155 } | 158 } |
| 156 | 159 |
| 157 | 160 |
| 158 File* File::Open(const char* name, FileOpenMode mode) { | 161 File* File::FileOpenW(const wchar_t* system_name, FileOpenMode mode) { |
| 159 int flags = O_RDONLY | O_BINARY | O_NOINHERIT; | 162 int flags = O_RDONLY | O_BINARY | O_NOINHERIT; |
| 160 if ((mode & kWrite) != 0) { | 163 if ((mode & kWrite) != 0) { |
| 161 ASSERT((mode & kWriteOnly) == 0); | 164 ASSERT((mode & kWriteOnly) == 0); |
| 162 flags = (O_RDWR | O_CREAT | O_BINARY | O_NOINHERIT); | 165 flags = (O_RDWR | O_CREAT | O_BINARY | O_NOINHERIT); |
| 163 } | 166 } |
| 164 if ((mode & kWriteOnly) != 0) { | 167 if ((mode & kWriteOnly) != 0) { |
| 165 ASSERT((mode & kWrite) == 0); | 168 ASSERT((mode & kWrite) == 0); |
| 166 flags = (O_WRONLY | O_CREAT | O_BINARY | O_NOINHERIT); | 169 flags = (O_WRONLY | O_CREAT | O_BINARY | O_NOINHERIT); |
| 167 } | 170 } |
| 168 if ((mode & kTruncate) != 0) { | 171 if ((mode & kTruncate) != 0) { |
| 169 flags = flags | O_TRUNC; | 172 flags = flags | O_TRUNC; |
| 170 } | 173 } |
| 171 const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name); | |
| 172 int fd = _wopen(system_name, flags, 0666); | 174 int fd = _wopen(system_name, flags, 0666); |
| 173 free(const_cast<wchar_t*>(system_name)); | |
| 174 if (fd < 0) { | 175 if (fd < 0) { |
| 175 return NULL; | 176 return NULL; |
| 176 } | 177 } |
| 177 if ((((mode & kWrite) != 0) && ((mode & kTruncate) == 0)) || | 178 if ((((mode & kWrite) != 0) && ((mode & kTruncate) == 0)) || |
| 178 (((mode & kWriteOnly) != 0) && ((mode & kTruncate) == 0))) { | 179 (((mode & kWriteOnly) != 0) && ((mode & kTruncate) == 0))) { |
| 179 int64_t position = _lseeki64(fd, 0, SEEK_END); | 180 int64_t position = _lseeki64(fd, 0, SEEK_END); |
| 180 if (position < 0) { | 181 if (position < 0) { |
| 181 return NULL; | 182 return NULL; |
| 182 } | 183 } |
| 183 } | 184 } |
| 184 return new File(new FileHandle(fd)); | 185 return new File(new FileHandle(fd)); |
| 185 } | 186 } |
| 186 | 187 |
| 187 | 188 |
| 189 File* File::ScopedOpen(const char* name, FileOpenMode mode) { |
| 190 const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name); |
| 191 return FileOpenW(system_name, mode); |
| 192 } |
| 193 |
| 194 |
| 195 File* File::Open(const char* path, FileOpenMode mode) { |
| 196 int path_len = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0); |
| 197 wchar_t* system_name = new wchar_t[path_len]; |
| 198 if (system_name == NULL) { |
| 199 return NULL; |
| 200 } |
| 201 MultiByteToWideChar(CP_UTF8, 0, path, -1, system_name, path_len); |
| 202 File* file = FileOpenW(system_name, mode); |
| 203 delete[] system_name; |
| 204 return file; |
| 205 } |
| 206 |
| 207 |
| 188 File* File::OpenStdio(int fd) { | 208 File* File::OpenStdio(int fd) { |
| 189 switch (fd) { | 209 switch (fd) { |
| 190 case 1: | 210 case 1: |
| 191 fd = _fileno(stdout); | 211 fd = _fileno(stdout); |
| 192 break; | 212 break; |
| 193 case 2: | 213 case 2: |
| 194 fd = _fileno(stderr); | 214 fd = _fileno(stderr); |
| 195 break; | 215 break; |
| 196 default: | 216 default: |
| 197 UNREACHABLE(); | 217 UNREACHABLE(); |
| 198 } | 218 } |
| 199 _setmode(fd, _O_BINARY); | 219 _setmode(fd, _O_BINARY); |
| 200 return new File(new FileHandle(fd)); | 220 return new File(new FileHandle(fd)); |
| 201 } | 221 } |
| 202 | 222 |
| 203 | 223 |
| 204 bool File::Exists(const char* name) { | 224 bool File::Exists(const char* name) { |
| 205 struct __stat64 st; | 225 struct __stat64 st; |
| 206 const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name); | 226 const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name); |
| 207 bool stat_status = _wstat64(system_name, &st); | 227 bool stat_status = _wstat64(system_name, &st); |
| 208 free(const_cast<wchar_t*>(system_name)); | |
| 209 if (stat_status == 0) { | 228 if (stat_status == 0) { |
| 210 return ((st.st_mode & S_IFMT) == S_IFREG); | 229 return ((st.st_mode & S_IFMT) == S_IFREG); |
| 211 } else { | 230 } else { |
| 212 return false; | 231 return false; |
| 213 } | 232 } |
| 214 } | 233 } |
| 215 | 234 |
| 216 | 235 |
| 217 bool File::Create(const char* name) { | 236 bool File::Create(const char* name) { |
| 218 const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name); | 237 const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name); |
| 219 int fd = _wopen(system_name, O_RDONLY | O_CREAT, 0666); | 238 int fd = _wopen(system_name, O_RDONLY | O_CREAT, 0666); |
| 220 free(const_cast<wchar_t*>(system_name)); | |
| 221 if (fd < 0) { | 239 if (fd < 0) { |
| 222 return false; | 240 return false; |
| 223 } | 241 } |
| 224 return (close(fd) == 0); | 242 return (close(fd) == 0); |
| 225 } | 243 } |
| 226 | 244 |
| 227 | 245 |
| 228 // This structure is needed for creating and reading Junctions. | 246 // This structure is needed for creating and reading Junctions. |
| 229 typedef struct _REPARSE_DATA_BUFFER { | 247 typedef struct _REPARSE_DATA_BUFFER { |
| 230 ULONG ReparseTag; | 248 ULONG ReparseTag; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 257 | 275 |
| 258 | 276 |
| 259 static const int kReparseDataHeaderSize = sizeof ULONG + 2 * sizeof USHORT; | 277 static const int kReparseDataHeaderSize = sizeof ULONG + 2 * sizeof USHORT; |
| 260 static const int kMountPointHeaderSize = 4 * sizeof USHORT; | 278 static const int kMountPointHeaderSize = 4 * sizeof USHORT; |
| 261 | 279 |
| 262 | 280 |
| 263 bool File::CreateLink(const char* utf8_name, const char* utf8_target) { | 281 bool File::CreateLink(const char* utf8_name, const char* utf8_target) { |
| 264 const wchar_t* name = StringUtilsWin::Utf8ToWide(utf8_name); | 282 const wchar_t* name = StringUtilsWin::Utf8ToWide(utf8_name); |
| 265 int create_status = CreateDirectoryW(name, NULL); | 283 int create_status = CreateDirectoryW(name, NULL); |
| 266 // If the directory already existed, treat it as a success. | 284 // If the directory already existed, treat it as a success. |
| 267 if (create_status == 0 && | 285 if ((create_status == 0) && |
| 268 (GetLastError() != ERROR_ALREADY_EXISTS || | 286 ((GetLastError() != ERROR_ALREADY_EXISTS) || |
| 269 (GetFileAttributesW(name) & FILE_ATTRIBUTE_DIRECTORY) != 0)) { | 287 ((GetFileAttributesW(name) & FILE_ATTRIBUTE_DIRECTORY) != 0))) { |
| 270 free(const_cast<wchar_t*>(name)); | |
| 271 return false; | 288 return false; |
| 272 } | 289 } |
| 273 | 290 |
| 274 HANDLE dir_handle = CreateFileW( | 291 HANDLE dir_handle = CreateFileW( |
| 275 name, | 292 name, |
| 276 GENERIC_READ | GENERIC_WRITE, | 293 GENERIC_READ | GENERIC_WRITE, |
| 277 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, | 294 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, |
| 278 NULL, | 295 NULL, |
| 279 OPEN_EXISTING, | 296 OPEN_EXISTING, |
| 280 FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, | 297 FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, |
| 281 NULL); | 298 NULL); |
| 282 free(const_cast<wchar_t*>(name)); | |
| 283 if (dir_handle == INVALID_HANDLE_VALUE) { | 299 if (dir_handle == INVALID_HANDLE_VALUE) { |
| 284 return false; | 300 return false; |
| 285 } | 301 } |
| 286 | 302 |
| 287 const wchar_t* target = StringUtilsWin::Utf8ToWide(utf8_target); | 303 const wchar_t* target = StringUtilsWin::Utf8ToWide(utf8_target); |
| 288 int target_len = wcslen(target); | 304 int target_len = wcslen(target); |
| 289 if (target_len > MAX_PATH - 1) { | 305 if (target_len > MAX_PATH - 1) { |
| 290 free(const_cast<wchar_t*>(target)); | |
| 291 CloseHandle(dir_handle); | 306 CloseHandle(dir_handle); |
| 292 return false; | 307 return false; |
| 293 } | 308 } |
| 294 | 309 |
| 295 int reparse_data_buffer_size = | 310 int reparse_data_buffer_size = |
| 296 sizeof REPARSE_DATA_BUFFER + 2 * MAX_PATH * sizeof WCHAR; | 311 sizeof REPARSE_DATA_BUFFER + 2 * MAX_PATH * sizeof WCHAR; |
| 297 REPARSE_DATA_BUFFER* reparse_data_buffer = | 312 REPARSE_DATA_BUFFER* reparse_data_buffer = |
| 298 static_cast<REPARSE_DATA_BUFFER*>(calloc(reparse_data_buffer_size, 1)); | 313 reinterpret_cast<REPARSE_DATA_BUFFER*>(Dart_ScopeAllocate( |
| 314 reparse_data_buffer_size)); |
| 299 reparse_data_buffer->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT; | 315 reparse_data_buffer->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT; |
| 300 wcscpy(reparse_data_buffer->MountPointReparseBuffer.PathBuffer, target); | 316 wcscpy(reparse_data_buffer->MountPointReparseBuffer.PathBuffer, target); |
| 301 wcscpy( | 317 wcscpy( |
| 302 reparse_data_buffer->MountPointReparseBuffer.PathBuffer + target_len + 1, | 318 reparse_data_buffer->MountPointReparseBuffer.PathBuffer + target_len + 1, |
| 303 target); | 319 target); |
| 304 reparse_data_buffer->MountPointReparseBuffer.SubstituteNameOffset = 0; | 320 reparse_data_buffer->MountPointReparseBuffer.SubstituteNameOffset = 0; |
| 305 reparse_data_buffer->MountPointReparseBuffer.SubstituteNameLength = | 321 reparse_data_buffer->MountPointReparseBuffer.SubstituteNameLength = |
| 306 target_len * sizeof WCHAR; | 322 target_len * sizeof WCHAR; |
| 307 reparse_data_buffer->MountPointReparseBuffer.PrintNameOffset = | 323 reparse_data_buffer->MountPointReparseBuffer.PrintNameOffset = |
| 308 (target_len + 1) * sizeof WCHAR; | 324 (target_len + 1) * sizeof WCHAR; |
| 309 reparse_data_buffer->MountPointReparseBuffer.PrintNameLength = | 325 reparse_data_buffer->MountPointReparseBuffer.PrintNameLength = |
| 310 target_len * sizeof WCHAR; | 326 target_len * sizeof WCHAR; |
| 311 reparse_data_buffer->ReparseDataLength = | 327 reparse_data_buffer->ReparseDataLength = |
| 312 (target_len + 1) * 2 * sizeof WCHAR + kMountPointHeaderSize; | 328 (target_len + 1) * 2 * sizeof WCHAR + kMountPointHeaderSize; |
| 313 DWORD dummy_received_bytes; | 329 DWORD dummy_received_bytes; |
| 314 int result = DeviceIoControl( | 330 int result = DeviceIoControl( |
| 315 dir_handle, | 331 dir_handle, |
| 316 FSCTL_SET_REPARSE_POINT, | 332 FSCTL_SET_REPARSE_POINT, |
| 317 reparse_data_buffer, | 333 reparse_data_buffer, |
| 318 reparse_data_buffer->ReparseDataLength + kReparseDataHeaderSize, | 334 reparse_data_buffer->ReparseDataLength + kReparseDataHeaderSize, |
| 319 NULL, | 335 NULL, |
| 320 0, | 336 0, |
| 321 &dummy_received_bytes, | 337 &dummy_received_bytes, |
| 322 NULL); | 338 NULL); |
| 323 if (CloseHandle(dir_handle) == 0) return false; | 339 if (CloseHandle(dir_handle) == 0) { |
| 324 free(const_cast<wchar_t*>(target)); | 340 return false; |
| 325 free(reparse_data_buffer); | 341 } |
| 326 return (result != 0); | 342 return (result != 0); |
| 327 } | 343 } |
| 328 | 344 |
| 329 | 345 |
| 330 bool File::Delete(const char* name) { | 346 bool File::Delete(const char* name) { |
| 331 const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name); | 347 const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name); |
| 332 int status = _wremove(system_name); | 348 int status = _wremove(system_name); |
| 333 free(const_cast<wchar_t*>(system_name)); | |
| 334 return status != -1; | 349 return status != -1; |
| 335 } | 350 } |
| 336 | 351 |
| 337 | 352 |
| 338 bool File::DeleteLink(const char* name) { | 353 bool File::DeleteLink(const char* name) { |
| 339 const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name); | 354 const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name); |
| 340 bool result = false; | 355 bool result = false; |
| 341 DWORD attributes = GetFileAttributesW(system_name); | 356 DWORD attributes = GetFileAttributesW(system_name); |
| 342 if ((attributes != INVALID_FILE_ATTRIBUTES) && | 357 if ((attributes != INVALID_FILE_ATTRIBUTES) && |
| 343 (attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) { | 358 (attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) { |
| 344 // It's a junction(link), delete it. | 359 // It's a junction(link), delete it. |
| 345 result = (RemoveDirectoryW(system_name) != 0); | 360 result = (RemoveDirectoryW(system_name) != 0); |
| 346 } else { | 361 } else { |
| 347 SetLastError(ERROR_NOT_A_REPARSE_POINT); | 362 SetLastError(ERROR_NOT_A_REPARSE_POINT); |
| 348 } | 363 } |
| 349 free(const_cast<wchar_t*>(system_name)); | |
| 350 return result; | 364 return result; |
| 351 } | 365 } |
| 352 | 366 |
| 353 | 367 |
| 354 bool File::Rename(const char* old_path, const char* new_path) { | 368 bool File::Rename(const char* old_path, const char* new_path) { |
| 355 File::Type type = GetType(old_path, false); | 369 File::Type type = GetType(old_path, false); |
| 356 if (type == kIsFile) { | 370 if (type == kIsFile) { |
| 357 const wchar_t* system_old_path = StringUtilsWin::Utf8ToWide(old_path); | 371 const wchar_t* system_old_path = StringUtilsWin::Utf8ToWide(old_path); |
| 358 const wchar_t* system_new_path = StringUtilsWin::Utf8ToWide(new_path); | 372 const wchar_t* system_new_path = StringUtilsWin::Utf8ToWide(new_path); |
| 359 DWORD flags = MOVEFILE_WRITE_THROUGH | MOVEFILE_REPLACE_EXISTING; | 373 DWORD flags = MOVEFILE_WRITE_THROUGH | MOVEFILE_REPLACE_EXISTING; |
| 360 int move_status = | 374 int move_status = |
| 361 MoveFileExW(system_old_path, system_new_path, flags); | 375 MoveFileExW(system_old_path, system_new_path, flags); |
| 362 free(const_cast<wchar_t*>(system_old_path)); | |
| 363 free(const_cast<wchar_t*>(system_new_path)); | |
| 364 return (move_status != 0); | 376 return (move_status != 0); |
| 365 } else { | 377 } else { |
| 366 SetLastError(ERROR_FILE_NOT_FOUND); | 378 SetLastError(ERROR_FILE_NOT_FOUND); |
| 367 } | 379 } |
| 368 return false; | 380 return false; |
| 369 } | 381 } |
| 370 | 382 |
| 371 | 383 |
| 372 bool File::RenameLink(const char* old_path, const char* new_path) { | 384 bool File::RenameLink(const char* old_path, const char* new_path) { |
| 373 File::Type type = GetType(old_path, false); | 385 File::Type type = GetType(old_path, false); |
| 374 if (type == kIsLink) { | 386 if (type == kIsLink) { |
| 375 const wchar_t* system_old_path = StringUtilsWin::Utf8ToWide(old_path); | 387 const wchar_t* system_old_path = StringUtilsWin::Utf8ToWide(old_path); |
| 376 const wchar_t* system_new_path = StringUtilsWin::Utf8ToWide(new_path); | 388 const wchar_t* system_new_path = StringUtilsWin::Utf8ToWide(new_path); |
| 377 DWORD flags = MOVEFILE_WRITE_THROUGH | MOVEFILE_REPLACE_EXISTING; | 389 DWORD flags = MOVEFILE_WRITE_THROUGH | MOVEFILE_REPLACE_EXISTING; |
| 378 int move_status = | 390 int move_status = |
| 379 MoveFileExW(system_old_path, system_new_path, flags); | 391 MoveFileExW(system_old_path, system_new_path, flags); |
| 380 free(const_cast<wchar_t*>(system_old_path)); | |
| 381 free(const_cast<wchar_t*>(system_new_path)); | |
| 382 return (move_status != 0); | 392 return (move_status != 0); |
| 383 } else { | 393 } else { |
| 384 SetLastError(ERROR_FILE_NOT_FOUND); | 394 SetLastError(ERROR_FILE_NOT_FOUND); |
| 385 } | 395 } |
| 386 return false; | 396 return false; |
| 387 } | 397 } |
| 388 | 398 |
| 389 | 399 |
| 390 bool File::Copy(const char* old_path, const char* new_path) { | 400 bool File::Copy(const char* old_path, const char* new_path) { |
| 391 File::Type type = GetType(old_path, false); | 401 File::Type type = GetType(old_path, false); |
| 392 if (type == kIsFile) { | 402 if (type == kIsFile) { |
| 393 const wchar_t* system_old_path = StringUtilsWin::Utf8ToWide(old_path); | 403 const wchar_t* system_old_path = StringUtilsWin::Utf8ToWide(old_path); |
| 394 const wchar_t* system_new_path = StringUtilsWin::Utf8ToWide(new_path); | 404 const wchar_t* system_new_path = StringUtilsWin::Utf8ToWide(new_path); |
| 395 bool success = CopyFileExW(system_old_path, | 405 bool success = CopyFileExW(system_old_path, |
| 396 system_new_path, | 406 system_new_path, |
| 397 NULL, | 407 NULL, |
| 398 NULL, | 408 NULL, |
| 399 NULL, | 409 NULL, |
| 400 0) != 0; | 410 0) != 0; |
| 401 free(const_cast<wchar_t*>(system_old_path)); | |
| 402 free(const_cast<wchar_t*>(system_new_path)); | |
| 403 return success; | 411 return success; |
| 404 } else { | 412 } else { |
| 405 SetLastError(ERROR_FILE_NOT_FOUND); | 413 SetLastError(ERROR_FILE_NOT_FOUND); |
| 406 } | 414 } |
| 407 return false; | 415 return false; |
| 408 } | 416 } |
| 409 | 417 |
| 410 | 418 |
| 411 int64_t File::LengthFromPath(const char* name) { | 419 int64_t File::LengthFromPath(const char* name) { |
| 412 struct __stat64 st; | 420 struct __stat64 st; |
| 413 const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name); | 421 const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name); |
| 414 int stat_status = _wstat64(system_name, &st); | 422 int stat_status = _wstat64(system_name, &st); |
| 415 free(const_cast<wchar_t*>(system_name)); | |
| 416 if (stat_status == 0) { | 423 if (stat_status == 0) { |
| 417 return st.st_size; | 424 return st.st_size; |
| 418 } | 425 } |
| 419 return -1; | 426 return -1; |
| 420 } | 427 } |
| 421 | 428 |
| 422 | 429 |
| 423 char* File::LinkTarget(const char* pathname) { | 430 const char* File::LinkTarget(const char* pathname) { |
| 424 const wchar_t* name = StringUtilsWin::Utf8ToWide(pathname); | 431 const wchar_t* name = StringUtilsWin::Utf8ToWide(pathname); |
| 425 HANDLE dir_handle = CreateFileW( | 432 HANDLE dir_handle = CreateFileW( |
| 426 name, | 433 name, |
| 427 GENERIC_READ, | 434 GENERIC_READ, |
| 428 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, | 435 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, |
| 429 NULL, | 436 NULL, |
| 430 OPEN_EXISTING, | 437 OPEN_EXISTING, |
| 431 FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, | 438 FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, |
| 432 NULL); | 439 NULL); |
| 433 free(const_cast<wchar_t*>(name)); | |
| 434 if (dir_handle == INVALID_HANDLE_VALUE) { | 440 if (dir_handle == INVALID_HANDLE_VALUE) { |
| 435 return NULL; | 441 return NULL; |
| 436 } | 442 } |
| 437 | 443 |
| 438 int buffer_size = | 444 int buffer_size = |
| 439 sizeof REPARSE_DATA_BUFFER + 2 * (MAX_PATH + 1) * sizeof WCHAR; | 445 sizeof REPARSE_DATA_BUFFER + 2 * (MAX_PATH + 1) * sizeof WCHAR; |
| 440 REPARSE_DATA_BUFFER* buffer = | 446 REPARSE_DATA_BUFFER* buffer = reinterpret_cast<REPARSE_DATA_BUFFER*>( |
| 441 static_cast<REPARSE_DATA_BUFFER*>(calloc(buffer_size, 1)); | 447 Dart_ScopeAllocate(buffer_size)); |
| 442 DWORD received_bytes; // Value is not used. | 448 DWORD received_bytes; // Value is not used. |
| 443 int result = DeviceIoControl( | 449 int result = DeviceIoControl( |
| 444 dir_handle, | 450 dir_handle, |
| 445 FSCTL_GET_REPARSE_POINT, | 451 FSCTL_GET_REPARSE_POINT, |
| 446 NULL, | 452 NULL, |
| 447 0, | 453 0, |
| 448 buffer, | 454 buffer, |
| 449 buffer_size, | 455 buffer_size, |
| 450 &received_bytes, | 456 &received_bytes, |
| 451 NULL); | 457 NULL); |
| 452 if (result == 0) { | 458 if (result == 0) { |
| 453 DWORD error = GetLastError(); | 459 DWORD error = GetLastError(); |
| 454 CloseHandle(dir_handle); | 460 CloseHandle(dir_handle); |
| 455 SetLastError(error); | 461 SetLastError(error); |
| 456 free(buffer); | |
| 457 return NULL; | 462 return NULL; |
| 458 } | 463 } |
| 459 if (CloseHandle(dir_handle) == 0) { | 464 if (CloseHandle(dir_handle) == 0) { |
| 460 free(buffer); | |
| 461 return NULL; | 465 return NULL; |
| 462 } | 466 } |
| 463 | 467 |
| 464 wchar_t* target; | 468 wchar_t* target; |
| 465 size_t target_offset; | 469 size_t target_offset; |
| 466 size_t target_length; | 470 size_t target_length; |
| 467 if (buffer->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) { | 471 if (buffer->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) { |
| 468 target = buffer->MountPointReparseBuffer.PathBuffer; | 472 target = buffer->MountPointReparseBuffer.PathBuffer; |
| 469 target_offset = buffer->MountPointReparseBuffer.SubstituteNameOffset; | 473 target_offset = buffer->MountPointReparseBuffer.SubstituteNameOffset; |
| 470 target_length = buffer->MountPointReparseBuffer.SubstituteNameLength; | 474 target_length = buffer->MountPointReparseBuffer.SubstituteNameLength; |
| 471 } else if (buffer->ReparseTag == IO_REPARSE_TAG_SYMLINK) { | 475 } else if (buffer->ReparseTag == IO_REPARSE_TAG_SYMLINK) { |
| 472 target = buffer->SymbolicLinkReparseBuffer.PathBuffer; | 476 target = buffer->SymbolicLinkReparseBuffer.PathBuffer; |
| 473 target_offset = buffer->SymbolicLinkReparseBuffer.SubstituteNameOffset; | 477 target_offset = buffer->SymbolicLinkReparseBuffer.SubstituteNameOffset; |
| 474 target_length = buffer->SymbolicLinkReparseBuffer.SubstituteNameLength; | 478 target_length = buffer->SymbolicLinkReparseBuffer.SubstituteNameLength; |
| 475 } else { // Not a junction or a symbolic link. | 479 } else { // Not a junction or a symbolic link. |
| 476 free(buffer); | |
| 477 SetLastError(ERROR_NOT_A_REPARSE_POINT); | 480 SetLastError(ERROR_NOT_A_REPARSE_POINT); |
| 478 return NULL; | 481 return NULL; |
| 479 } | 482 } |
| 480 | 483 |
| 481 target_offset /= sizeof(wchar_t); // Offset and length are in bytes. | 484 target_offset /= sizeof(wchar_t); // Offset and length are in bytes. |
| 482 target_length /= sizeof(wchar_t); | 485 target_length /= sizeof(wchar_t); |
| 483 target += target_offset; | 486 target += target_offset; |
| 484 // Remove "\??\" from beginning of target. | 487 // Remove "\??\" from beginning of target. |
| 485 if (target_length > 4 && wcsncmp(L"\\??\\", target, 4) == 0) { | 488 if ((target_length > 4) && (wcsncmp(L"\\??\\", target, 4) == 0)) { |
| 486 target += 4; | 489 target += 4; |
| 487 target_length -= 4; | 490 target_length -= 4; |
| 488 } | 491 } |
| 489 int utf8_length = WideCharToMultiByte(CP_UTF8, | 492 int utf8_length = WideCharToMultiByte(CP_UTF8, |
| 490 0, | 493 0, |
| 491 target, | 494 target, |
| 492 target_length, | 495 target_length, |
| 493 NULL, | 496 NULL, |
| 494 0, | 497 0, |
| 495 NULL, | 498 NULL, |
| 496 NULL); | 499 NULL); |
| 497 char* utf8_target = reinterpret_cast<char*>(malloc(utf8_length + 1)); | 500 char* utf8_target = DartUtils::ScopedCString(utf8_length + 1); |
| 498 if (0 == WideCharToMultiByte(CP_UTF8, | 501 if (0 == WideCharToMultiByte(CP_UTF8, |
| 499 0, | 502 0, |
| 500 target, | 503 target, |
| 501 target_length, | 504 target_length, |
| 502 utf8_target, | 505 utf8_target, |
| 503 utf8_length, | 506 utf8_length, |
| 504 NULL, | 507 NULL, |
| 505 NULL)) { | 508 NULL)) { |
| 506 free(buffer); | |
| 507 free(utf8_target); | |
| 508 return NULL; | 509 return NULL; |
| 509 } | 510 } |
| 510 utf8_target[utf8_length] = '\0'; | 511 utf8_target[utf8_length] = '\0'; |
| 511 free(buffer); | |
| 512 return utf8_target; | 512 return utf8_target; |
| 513 } | 513 } |
| 514 | 514 |
| 515 | 515 |
| 516 void File::Stat(const char* name, int64_t* data) { | 516 void File::Stat(const char* name, int64_t* data) { |
| 517 File::Type type = GetType(name, false); | 517 File::Type type = GetType(name, false); |
| 518 data[kType] = type; | 518 data[kType] = type; |
| 519 if (type != kDoesNotExist) { | 519 if (type != kDoesNotExist) { |
| 520 struct _stat64 st; | 520 struct _stat64 st; |
| 521 const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name); | 521 const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name); |
| 522 int stat_status = _wstat64(system_name, &st); | 522 int stat_status = _wstat64(system_name, &st); |
| 523 free(const_cast<wchar_t*>(system_name)); | |
| 524 if (stat_status == 0) { | 523 if (stat_status == 0) { |
| 525 data[kCreatedTime] = st.st_ctime * 1000; | 524 data[kCreatedTime] = st.st_ctime * 1000; |
| 526 data[kModifiedTime] = st.st_mtime * 1000; | 525 data[kModifiedTime] = st.st_mtime * 1000; |
| 527 data[kAccessedTime] = st.st_atime * 1000; | 526 data[kAccessedTime] = st.st_atime * 1000; |
| 528 data[kMode] = st.st_mode; | 527 data[kMode] = st.st_mode; |
| 529 data[kSize] = st.st_size; | 528 data[kSize] = st.st_size; |
| 530 } else { | 529 } else { |
| 531 data[kType] = File::kDoesNotExist; | 530 data[kType] = File::kDoesNotExist; |
| 532 } | 531 } |
| 533 } | 532 } |
| 534 } | 533 } |
| 535 | 534 |
| 536 | 535 |
| 537 time_t File::LastModified(const char* name) { | 536 time_t File::LastModified(const char* name) { |
| 538 struct __stat64 st; | 537 struct __stat64 st; |
| 539 const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name); | 538 const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name); |
| 540 int stat_status = _wstat64(system_name, &st); | 539 int stat_status = _wstat64(system_name, &st); |
| 541 free(const_cast<wchar_t*>(system_name)); | |
| 542 if (stat_status == 0) { | 540 if (stat_status == 0) { |
| 543 return st.st_mtime; | 541 return st.st_mtime; |
| 544 } | 542 } |
| 545 return -1; | 543 return -1; |
| 546 } | 544 } |
| 547 | 545 |
| 548 | 546 |
| 549 bool File::IsAbsolutePath(const char* pathname) { | 547 bool File::IsAbsolutePath(const char* pathname) { |
| 550 // Should we consider network paths? | 548 // Should we consider network paths? |
| 551 if (pathname == NULL) return false; | 549 if (pathname == NULL) { |
| 550 return false; |
| 551 } |
| 552 return (strlen(pathname) > 2) && | 552 return (strlen(pathname) > 2) && |
| 553 (pathname[1] == ':') && | 553 (pathname[1] == ':') && |
| 554 (pathname[2] == '\\' || pathname[2] == '/'); | 554 (pathname[2] == '\\' || pathname[2] == '/'); |
| 555 } | 555 } |
| 556 | 556 |
| 557 | 557 |
| 558 char* File::GetCanonicalPath(const char* pathname) { | 558 const char* File::GetCanonicalPath(const char* pathname) { |
| 559 const wchar_t* system_name = StringUtilsWin::Utf8ToWide(pathname); | 559 const wchar_t* system_name = StringUtilsWin::Utf8ToWide(pathname); |
| 560 HANDLE file_handle = CreateFileW( | 560 HANDLE file_handle = CreateFileW( |
| 561 system_name, | 561 system_name, |
| 562 0, | 562 0, |
| 563 FILE_SHARE_READ, | 563 FILE_SHARE_READ, |
| 564 NULL, | 564 NULL, |
| 565 OPEN_EXISTING, | 565 OPEN_EXISTING, |
| 566 FILE_FLAG_BACKUP_SEMANTICS, | 566 FILE_FLAG_BACKUP_SEMANTICS, |
| 567 NULL); | 567 NULL); |
| 568 if (file_handle == INVALID_HANDLE_VALUE) { | 568 if (file_handle == INVALID_HANDLE_VALUE) { |
| 569 free(const_cast<wchar_t*>(system_name)); | |
| 570 return NULL; | 569 return NULL; |
| 571 } | 570 } |
| 572 wchar_t dummy_buffer[1]; | 571 wchar_t dummy_buffer[1]; |
| 573 int required_size = GetFinalPathNameByHandle(file_handle, | 572 int required_size = GetFinalPathNameByHandle(file_handle, |
| 574 dummy_buffer, | 573 dummy_buffer, |
| 575 0, | 574 0, |
| 576 VOLUME_NAME_DOS); | 575 VOLUME_NAME_DOS); |
| 577 if (required_size == 0) { | 576 if (required_size == 0) { |
| 578 free(const_cast<wchar_t*>(system_name)); | |
| 579 DWORD error = GetLastError(); | 577 DWORD error = GetLastError(); |
| 580 CloseHandle(file_handle); | 578 CloseHandle(file_handle); |
| 581 SetLastError(error); | 579 SetLastError(error); |
| 582 return NULL; | 580 return NULL; |
| 583 } | 581 } |
| 584 wchar_t* path = | 582 wchar_t* path; |
| 585 static_cast<wchar_t*>(malloc(required_size * sizeof(wchar_t))); | 583 path = reinterpret_cast<wchar_t*>( |
| 584 Dart_ScopeAllocate(required_size * sizeof(*path))); |
| 586 int result_size = GetFinalPathNameByHandle(file_handle, | 585 int result_size = GetFinalPathNameByHandle(file_handle, |
| 587 path, | 586 path, |
| 588 required_size, | 587 required_size, |
| 589 VOLUME_NAME_DOS); | 588 VOLUME_NAME_DOS); |
| 590 ASSERT(result_size <= required_size - 1); | 589 ASSERT(result_size <= required_size - 1); |
| 591 // Remove leading \\?\ if possible, unless input used it. | 590 // Remove leading \\?\ if possible, unless input used it. |
| 592 char* result; | 591 char* result; |
| 593 if (result_size < MAX_PATH - 1 + 4 && | 592 if ((result_size < MAX_PATH - 1 + 4) && |
| 594 result_size > 4 && | 593 (result_size > 4) && |
| 595 wcsncmp(path, L"\\\\?\\", 4) == 0 && | 594 (wcsncmp(path, L"\\\\?\\", 4) == 0) && |
| 596 wcsncmp(system_name, L"\\\\?\\", 4) != 0) { | 595 (wcsncmp(system_name, L"\\\\?\\", 4) != 0)) { |
| 597 result = StringUtilsWin::WideToUtf8(path + 4); | 596 result = StringUtilsWin::WideToUtf8(path + 4); |
| 598 } else { | 597 } else { |
| 599 result = StringUtilsWin::WideToUtf8(path); | 598 result = StringUtilsWin::WideToUtf8(path); |
| 600 } | 599 } |
| 601 free(const_cast<wchar_t*>(system_name)); | |
| 602 free(path); | |
| 603 CloseHandle(file_handle); | 600 CloseHandle(file_handle); |
| 604 return result; | 601 return result; |
| 605 } | 602 } |
| 606 | 603 |
| 607 | 604 |
| 608 const char* File::PathSeparator() { | 605 const char* File::PathSeparator() { |
| 609 // This is already UTF-8 encoded. | 606 // This is already UTF-8 encoded. |
| 610 return "\\"; | 607 return "\\"; |
| 611 } | 608 } |
| 612 | 609 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 645 } else { | 642 } else { |
| 646 CloseHandle(dir_handle); | 643 CloseHandle(dir_handle); |
| 647 result = File::kIsDirectory; | 644 result = File::kIsDirectory; |
| 648 } | 645 } |
| 649 } else { | 646 } else { |
| 650 result = kIsLink; | 647 result = kIsLink; |
| 651 } | 648 } |
| 652 } else if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { | 649 } else if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { |
| 653 result = kIsDirectory; | 650 result = kIsDirectory; |
| 654 } | 651 } |
| 655 free(const_cast<wchar_t*>(name)); | |
| 656 return result; | 652 return result; |
| 657 } | 653 } |
| 658 | 654 |
| 659 | 655 |
| 660 File::Identical File::AreIdentical(const char* file_1, const char* file_2) { | 656 File::Identical File::AreIdentical(const char* file_1, const char* file_2) { |
| 661 BY_HANDLE_FILE_INFORMATION file_info[2]; | 657 BY_HANDLE_FILE_INFORMATION file_info[2]; |
| 662 const char* file_names[2] = { file_1, file_2 }; | 658 const char* file_names[2] = { file_1, file_2 }; |
| 663 for (int i = 0; i < 2; ++i) { | 659 for (int i = 0; i < 2; ++i) { |
| 664 const wchar_t* wide_name = StringUtilsWin::Utf8ToWide(file_names[i]); | 660 const wchar_t* wide_name = StringUtilsWin::Utf8ToWide(file_names[i]); |
| 665 HANDLE file_handle = CreateFileW( | 661 HANDLE file_handle = CreateFileW( |
| 666 wide_name, | 662 wide_name, |
| 667 0, | 663 0, |
| 668 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, | 664 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, |
| 669 NULL, | 665 NULL, |
| 670 OPEN_EXISTING, | 666 OPEN_EXISTING, |
| 671 FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, | 667 FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, |
| 672 NULL); | 668 NULL); |
| 673 if (file_handle == INVALID_HANDLE_VALUE) { | 669 if (file_handle == INVALID_HANDLE_VALUE) { |
| 674 free(const_cast<wchar_t*>(wide_name)); | |
| 675 return File::kError; | 670 return File::kError; |
| 676 } | 671 } |
| 677 free(const_cast<wchar_t*>(wide_name)); | |
| 678 int result = GetFileInformationByHandle(file_handle, &file_info[i]); | 672 int result = GetFileInformationByHandle(file_handle, &file_info[i]); |
| 679 if (result == 0) { | 673 if (result == 0) { |
| 680 DWORD error = GetLastError(); | 674 DWORD error = GetLastError(); |
| 681 CloseHandle(file_handle); | 675 CloseHandle(file_handle); |
| 682 SetLastError(error); | 676 SetLastError(error); |
| 683 return File::kError; | 677 return File::kError; |
| 684 } | 678 } |
| 685 if (CloseHandle(file_handle) == 0) { | 679 if (CloseHandle(file_handle) == 0) { |
| 686 return File::kError; | 680 return File::kError; |
| 687 } | 681 } |
| 688 } | 682 } |
| 689 if (file_info[0].dwVolumeSerialNumber == file_info[1].dwVolumeSerialNumber && | 683 if ((file_info[0].dwVolumeSerialNumber == |
| 690 file_info[0].nFileIndexHigh == file_info[1].nFileIndexHigh && | 684 file_info[1].dwVolumeSerialNumber) && |
| 691 file_info[0].nFileIndexLow == file_info[1].nFileIndexLow) { | 685 (file_info[0].nFileIndexHigh == file_info[1].nFileIndexHigh) && |
| 686 (file_info[0].nFileIndexLow == file_info[1].nFileIndexLow)) { |
| 692 return kIdentical; | 687 return kIdentical; |
| 693 } else { | 688 } else { |
| 694 return kDifferent; | 689 return kDifferent; |
| 695 } | 690 } |
| 696 } | 691 } |
| 697 | 692 |
| 698 } // namespace bin | 693 } // namespace bin |
| 699 } // namespace dart | 694 } // namespace dart |
| 700 | 695 |
| 701 #endif // defined(TARGET_OS_WINDOWS) | 696 #endif // defined(TARGET_OS_WINDOWS) |
| OLD | NEW |