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 |