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

Side by Side Diff: runtime/bin/file_linux.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_android.cc ('k') | runtime/bin/file_macos.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_LINUX) 6 #if defined(TARGET_OS_LINUX)
7 7
8 #include "bin/file.h" 8 #include "bin/file.h"
9 9
10 #include <errno.h> // NOLINT 10 #include <errno.h> // NOLINT
11 #include <fcntl.h> // NOLINT 11 #include <fcntl.h> // NOLINT
12 #include <sys/stat.h> // NOLINT 12 #include <sys/stat.h> // NOLINT
13 #include <sys/types.h> // NOLINT 13 #include <sys/types.h> // NOLINT
14 #include <sys/sendfile.h> // NOLINT 14 #include <sys/sendfile.h> // NOLINT
15 #include <unistd.h> // NOLINT 15 #include <unistd.h> // NOLINT
16 #include <libgen.h> // NOLINT 16 #include <libgen.h> // NOLINT
17 17
18 #include "bin/builtin.h" 18 #include "bin/builtin.h"
19 #include "bin/log.h" 19 #include "bin/log.h"
20 #include "platform/signal_blocker.h" 20 #include "platform/signal_blocker.h"
21 #include "platform/utils.h" 21 #include "platform/utils.h"
22 22
23
24 namespace dart { 23 namespace dart {
25 namespace bin { 24 namespace bin {
26 25
27 class FileHandle { 26 class FileHandle {
28 public: 27 public:
29 explicit FileHandle(int fd) : fd_(fd) { } 28 explicit FileHandle(int fd) : fd_(fd) { }
30 ~FileHandle() { } 29 ~FileHandle() { }
31 int fd() const { return fd_; } 30 int fd() const { return fd_; }
32 void set_fd(int fd) { fd_ = fd; } 31 void set_fd(int fd) { fd_ = fd; }
33 32
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
105 104
106 105
107 bool File::Flush() { 106 bool File::Flush() {
108 ASSERT(handle_->fd() >= 0); 107 ASSERT(handle_->fd() >= 0);
109 return NO_RETRY_EXPECTED(fsync(handle_->fd())) != -1; 108 return NO_RETRY_EXPECTED(fsync(handle_->fd())) != -1;
110 } 109 }
111 110
112 111
113 bool File::Lock(File::LockType lock, int64_t start, int64_t end) { 112 bool File::Lock(File::LockType lock, int64_t start, int64_t end) {
114 ASSERT(handle_->fd() >= 0); 113 ASSERT(handle_->fd() >= 0);
115 ASSERT(end == -1 || end > start); 114 ASSERT((end == -1) || (end > start));
116 struct flock fl; 115 struct flock fl;
117 switch (lock) { 116 switch (lock) {
118 case File::kLockUnlock: 117 case File::kLockUnlock:
119 fl.l_type = F_UNLCK; 118 fl.l_type = F_UNLCK;
120 break; 119 break;
121 case File::kLockShared: 120 case File::kLockShared:
122 fl.l_type = F_RDLCK; 121 fl.l_type = F_RDLCK;
123 break; 122 break;
124 case File::kLockExclusive: 123 case File::kLockExclusive:
125 fl.l_type = F_WRLCK; 124 fl.l_type = F_WRLCK;
(...skipping 13 matching lines...) Expand all
139 int64_t File::Length() { 138 int64_t File::Length() {
140 ASSERT(handle_->fd() >= 0); 139 ASSERT(handle_->fd() >= 0);
141 struct stat64 st; 140 struct stat64 st;
142 if (TEMP_FAILURE_RETRY(fstat64(handle_->fd(), &st)) == 0) { 141 if (TEMP_FAILURE_RETRY(fstat64(handle_->fd(), &st)) == 0) {
143 return st.st_size; 142 return st.st_size;
144 } 143 }
145 return -1; 144 return -1;
146 } 145 }
147 146
148 147
149 File* File::Open(const char* name, FileOpenMode mode) { 148 File* File::FileOpenW(const wchar_t* system_name, FileOpenMode mode) {
149 UNREACHABLE();
150 return NULL;
151 }
152
153
154 File* File::ScopedOpen(const char* name, FileOpenMode mode) {
150 // Report errors for non-regular files. 155 // Report errors for non-regular files.
151 struct stat64 st; 156 struct stat64 st;
152 if (TEMP_FAILURE_RETRY(stat64(name, &st)) == 0) { 157 if (TEMP_FAILURE_RETRY(stat64(name, &st)) == 0) {
153 // Only accept regular files and character devices. 158 // Only accept regular files and character devices.
154 if (!S_ISREG(st.st_mode) && !S_ISCHR(st.st_mode)) { 159 if (!S_ISREG(st.st_mode) && !S_ISCHR(st.st_mode)) {
155 errno = (S_ISDIR(st.st_mode)) ? EISDIR : ENOENT; 160 errno = (S_ISDIR(st.st_mode)) ? EISDIR : ENOENT;
156 return NULL; 161 return NULL;
157 } 162 }
158 } 163 }
159 int flags = O_RDONLY; 164 int flags = O_RDONLY;
(...skipping 17 matching lines...) Expand all
177 (((mode & kWriteOnly) != 0) && ((mode & kTruncate) == 0))) { 182 (((mode & kWriteOnly) != 0) && ((mode & kTruncate) == 0))) {
178 int64_t position = NO_RETRY_EXPECTED(lseek64(fd, 0, SEEK_END)); 183 int64_t position = NO_RETRY_EXPECTED(lseek64(fd, 0, SEEK_END));
179 if (position < 0) { 184 if (position < 0) {
180 return NULL; 185 return NULL;
181 } 186 }
182 } 187 }
183 return new File(new FileHandle(fd)); 188 return new File(new FileHandle(fd));
184 } 189 }
185 190
186 191
192 File* File::Open(const char* path, FileOpenMode mode) {
193 // ScopedOpen doesn't actually need a scope.
194 return ScopedOpen(path, mode);
195 }
196
197
187 File* File::OpenStdio(int fd) { 198 File* File::OpenStdio(int fd) {
188 if (fd < 0 || 2 < fd) return NULL; 199 if ((fd < 0) || (2 < fd)) {
200 return NULL;
201 }
189 return new File(new FileHandle(fd)); 202 return new File(new FileHandle(fd));
190 } 203 }
191 204
192 205
193 bool File::Exists(const char* name) { 206 bool File::Exists(const char* name) {
194 struct stat64 st; 207 struct stat64 st;
195 if (TEMP_FAILURE_RETRY(stat64(name, &st)) == 0) { 208 if (TEMP_FAILURE_RETRY(stat64(name, &st)) == 0) {
196 return S_ISREG(st.st_mode); 209 return S_ISREG(st.st_mode);
197 } else { 210 } else {
198 return false; 211 return false;
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
284 int64_t offset = 0; 297 int64_t offset = 0;
285 intptr_t result = 1; 298 intptr_t result = 1;
286 while (result > 0) { 299 while (result > 0) {
287 // Loop to ensure we copy everything, and not only up to 2GB. 300 // Loop to ensure we copy everything, and not only up to 2GB.
288 result = NO_RETRY_EXPECTED( 301 result = NO_RETRY_EXPECTED(
289 sendfile64(new_fd, old_fd, &offset, kMaxUint32)); 302 sendfile64(new_fd, old_fd, &offset, kMaxUint32));
290 } 303 }
291 // From sendfile man pages: 304 // From sendfile man pages:
292 // Applications may wish to fall back to read(2)/write(2) in the case 305 // Applications may wish to fall back to read(2)/write(2) in the case
293 // where sendfile() fails with EINVAL or ENOSYS. 306 // where sendfile() fails with EINVAL or ENOSYS.
294 if (result < 0 && (errno == EINVAL || errno == ENOSYS)) { 307 if ((result < 0) && ((errno == EINVAL) || (errno == ENOSYS))) {
295 const intptr_t kBufferSize = 8 * KB; 308 const intptr_t kBufferSize = 8 * KB;
296 uint8_t buffer[kBufferSize]; 309 uint8_t buffer[kBufferSize];
297 while ((result = TEMP_FAILURE_RETRY( 310 while ((result = TEMP_FAILURE_RETRY(
298 read(old_fd, buffer, kBufferSize))) > 0) { 311 read(old_fd, buffer, kBufferSize))) > 0) {
299 int wrote = TEMP_FAILURE_RETRY(write(new_fd, buffer, result)); 312 int wrote = TEMP_FAILURE_RETRY(write(new_fd, buffer, result));
300 if (wrote != result) { 313 if (wrote != result) {
301 result = -1; 314 result = -1;
302 break; 315 break;
303 } 316 }
304 } 317 }
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 374
362 time_t File::LastModified(const char* name) { 375 time_t File::LastModified(const char* name) {
363 struct stat64 st; 376 struct stat64 st;
364 if (TEMP_FAILURE_RETRY(stat64(name, &st)) == 0) { 377 if (TEMP_FAILURE_RETRY(stat64(name, &st)) == 0) {
365 return st.st_mtime; 378 return st.st_mtime;
366 } 379 }
367 return -1; 380 return -1;
368 } 381 }
369 382
370 383
371 char* File::LinkTarget(const char* pathname) { 384 const char* File::LinkTarget(const char* pathname) {
372 struct stat64 link_stats; 385 struct stat64 link_stats;
373 if (TEMP_FAILURE_RETRY(lstat64(pathname, &link_stats)) != 0) return NULL; 386 if (TEMP_FAILURE_RETRY(lstat64(pathname, &link_stats)) != 0) {
387 return NULL;
388 }
374 if (!S_ISLNK(link_stats.st_mode)) { 389 if (!S_ISLNK(link_stats.st_mode)) {
375 errno = ENOENT; 390 errno = ENOENT;
376 return NULL; 391 return NULL;
377 } 392 }
378 // Don't rely on the link_stats.st_size for the size of the link 393 // Don't rely on the link_stats.st_size for the size of the link
379 // target. For some filesystems, e.g. procfs, this value is always 394 // target. For some filesystems, e.g. procfs, this value is always
380 // 0. Also the link might have changed before the readlink call. 395 // 0. Also the link might have changed before the readlink call.
381 const int kBufferSize = PATH_MAX + 1; 396 const int kBufferSize = PATH_MAX + 1;
382 char target[kBufferSize]; 397 char target[kBufferSize];
383 size_t target_size = TEMP_FAILURE_RETRY( 398 size_t target_size = TEMP_FAILURE_RETRY(
384 readlink(pathname, target, kBufferSize)); 399 readlink(pathname, target, kBufferSize));
385 if (target_size <= 0) { 400 if (target_size <= 0) {
386 return NULL; 401 return NULL;
387 } 402 }
388 char* target_name = reinterpret_cast<char*>(malloc(target_size + 1)); 403 char* target_name = DartUtils::ScopedCString(target_size + 1);
389 if (target_name == NULL) { 404 ASSERT(target_name != NULL);
390 return NULL;
391 }
392 memmove(target_name, target, target_size); 405 memmove(target_name, target, target_size);
393 target_name[target_size] = '\0'; 406 target_name[target_size] = '\0';
394 return target_name; 407 return target_name;
395 } 408 }
396 409
397 410
398 bool File::IsAbsolutePath(const char* pathname) { 411 bool File::IsAbsolutePath(const char* pathname) {
399 return (pathname != NULL && pathname[0] == '/'); 412 return (pathname != NULL && pathname[0] == '/');
400 } 413 }
401 414
402 415
403 char* File::GetCanonicalPath(const char* pathname) { 416 const char* File::GetCanonicalPath(const char* pathname) {
404 char* abs_path = NULL; 417 char* abs_path = NULL;
405 if (pathname != NULL) { 418 if (pathname != NULL) {
419 char* resolved_path = DartUtils::ScopedCString(PATH_MAX + 1);
420 ASSERT(resolved_path != NULL);
406 do { 421 do {
407 abs_path = realpath(pathname, NULL); 422 abs_path = realpath(pathname, resolved_path);
408 } while (abs_path == NULL && errno == EINTR); 423 } while (abs_path == NULL && errno == EINTR);
409 ASSERT(abs_path == NULL || IsAbsolutePath(abs_path)); 424 ASSERT(abs_path == NULL || IsAbsolutePath(abs_path));
425 ASSERT(abs_path == NULL || (abs_path == resolved_path));
410 } 426 }
411 return abs_path; 427 return abs_path;
412 } 428 }
413 429
414 430
415 const char* File::PathSeparator() { 431 const char* File::PathSeparator() {
416 return "/"; 432 return "/";
417 } 433 }
418 434
419 435
420 const char* File::StringEscapedPathSeparator() { 436 const char* File::StringEscapedPathSeparator() {
421 return "/"; 437 return "/";
422 } 438 }
423 439
424 440
425 File::StdioHandleType File::GetStdioHandleType(int fd) { 441 File::StdioHandleType File::GetStdioHandleType(int fd) {
426 ASSERT(0 <= fd && fd <= 2); 442 ASSERT((0 <= fd) && (fd <= 2));
427 struct stat64 buf; 443 struct stat64 buf;
428 int result = TEMP_FAILURE_RETRY(fstat64(fd, &buf)); 444 int result = TEMP_FAILURE_RETRY(fstat64(fd, &buf));
429 if (result == -1) { 445 if (result == -1) {
430 const int kBufferSize = 1024; 446 const int kBufferSize = 1024;
431 char error_buf[kBufferSize]; 447 char error_buf[kBufferSize];
432 FATAL2("Failed stat on file descriptor %d: %s", fd, 448 FATAL2("Failed stat on file descriptor %d: %s", fd,
433 Utils::StrError(errno, error_buf, kBufferSize)); 449 Utils::StrError(errno, error_buf, kBufferSize));
434 } 450 }
435 if (S_ISCHR(buf.st_mode)) return kTerminal; 451 if (S_ISCHR(buf.st_mode)) {
436 if (S_ISFIFO(buf.st_mode)) return kPipe; 452 return kTerminal;
437 if (S_ISSOCK(buf.st_mode)) return kSocket; 453 }
438 if (S_ISREG(buf.st_mode)) return kFile; 454 if (S_ISFIFO(buf.st_mode)) {
455 return kPipe;
456 }
457 if (S_ISSOCK(buf.st_mode)) {
458 return kSocket;
459 }
460 if (S_ISREG(buf.st_mode)) {
461 return kFile;
462 }
439 return kOther; 463 return kOther;
440 } 464 }
441 465
442 466
443 File::Type File::GetType(const char* pathname, bool follow_links) { 467 File::Type File::GetType(const char* pathname, bool follow_links) {
444 struct stat64 entry_info; 468 struct stat64 entry_info;
445 int stat_success; 469 int stat_success;
446 if (follow_links) { 470 if (follow_links) {
447 stat_success = TEMP_FAILURE_RETRY(stat64(pathname, &entry_info)); 471 stat_success = TEMP_FAILURE_RETRY(stat64(pathname, &entry_info));
448 } else { 472 } else {
449 stat_success = TEMP_FAILURE_RETRY(lstat64(pathname, &entry_info)); 473 stat_success = TEMP_FAILURE_RETRY(lstat64(pathname, &entry_info));
450 } 474 }
451 if (stat_success == -1) return File::kDoesNotExist; 475 if (stat_success == -1) {
452 if (S_ISDIR(entry_info.st_mode)) return File::kIsDirectory; 476 return File::kDoesNotExist;
453 if (S_ISREG(entry_info.st_mode)) return File::kIsFile; 477 }
454 if (S_ISLNK(entry_info.st_mode)) return File::kIsLink; 478 if (S_ISDIR(entry_info.st_mode)) {
479 return File::kIsDirectory;
480 }
481 if (S_ISREG(entry_info.st_mode)) {
482 return File::kIsFile;
483 }
484 if (S_ISLNK(entry_info.st_mode)) {
485 return File::kIsLink;
486 }
455 return File::kDoesNotExist; 487 return File::kDoesNotExist;
456 } 488 }
457 489
458 490
459 File::Identical File::AreIdentical(const char* file_1, const char* file_2) { 491 File::Identical File::AreIdentical(const char* file_1, const char* file_2) {
460 struct stat64 file_1_info; 492 struct stat64 file_1_info;
461 struct stat64 file_2_info; 493 struct stat64 file_2_info;
462 if (TEMP_FAILURE_RETRY(lstat64(file_1, &file_1_info)) == -1 || 494 if ((TEMP_FAILURE_RETRY(lstat64(file_1, &file_1_info)) == -1) ||
463 TEMP_FAILURE_RETRY(lstat64(file_2, &file_2_info)) == -1) { 495 (TEMP_FAILURE_RETRY(lstat64(file_2, &file_2_info)) == -1)) {
464 return File::kError; 496 return File::kError;
465 } 497 }
466 return (file_1_info.st_ino == file_2_info.st_ino && 498 return ((file_1_info.st_ino == file_2_info.st_ino) &&
467 file_1_info.st_dev == file_2_info.st_dev) ? 499 (file_1_info.st_dev == file_2_info.st_dev)) ?
468 File::kIdentical : 500 File::kIdentical :
469 File::kDifferent; 501 File::kDifferent;
470 } 502 }
471 503
472 } // namespace bin 504 } // namespace bin
473 } // namespace dart 505 } // namespace dart
474 506
475 #endif // defined(TARGET_OS_LINUX) 507 #endif // defined(TARGET_OS_LINUX)
OLDNEW
« no previous file with comments | « runtime/bin/file_android.cc ('k') | runtime/bin/file_macos.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698