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

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

Issue 1781883002: Fixes some memory leaks in //runtime/bin (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Fix tests on Windows Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/bin/file_test.cc ('k') | runtime/bin/main.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "platform/globals.h" 5 #include "platform/globals.h"
6 #if defined(TARGET_OS_WINDOWS) 6 #if defined(TARGET_OS_WINDOWS)
7 7
8 #include "bin/file.h" 8 #include "bin/file.h"
9 9
10 #include <fcntl.h> // NOLINT 10 #include <fcntl.h> // NOLINT
(...skipping 28 matching lines...) Expand all
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
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
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
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
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)
OLDNEW
« no previous file with comments | « runtime/bin/file_test.cc ('k') | runtime/bin/main.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698