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

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

Issue 2612653003: Standardize errno's from a few dart:io File and Link calls (Closed)
Patch Set: Created 3 years, 11 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_fuchsia.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
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
259 FDUtils::SaveErrorAndClose(fd); 259 FDUtils::SaveErrorAndClose(fd);
260 return is_file; 260 return is_file;
261 } 261 }
262 262
263 263
264 bool File::CreateLink(const char* name, const char* target) { 264 bool File::CreateLink(const char* name, const char* target) {
265 return NO_RETRY_EXPECTED(symlink(target, name)) == 0; 265 return NO_RETRY_EXPECTED(symlink(target, name)) == 0;
266 } 266 }
267 267
268 268
269 bool File::Delete(const char* name) { 269 File::Type File::GetType(const char* pathname, bool follow_links) {
270 File::Type type = File::GetType(name, true); 270 struct stat64 entry_info;
271 if (type == kIsFile) { 271 int stat_success;
272 return NO_RETRY_EXPECTED(unlink(name)) == 0; 272 if (follow_links) {
273 } else if (type == kIsDirectory) { 273 stat_success = TEMP_FAILURE_RETRY(stat64(pathname, &entry_info));
274 errno = EISDIR;
275 } else { 274 } else {
276 errno = ENOENT; 275 stat_success = TEMP_FAILURE_RETRY(lstat64(pathname, &entry_info));
276 }
277 if (stat_success == -1) {
278 return File::kDoesNotExist;
279 }
280 if (S_ISDIR(entry_info.st_mode)) {
281 return File::kIsDirectory;
282 }
283 if (S_ISREG(entry_info.st_mode)) {
284 return File::kIsFile;
285 }
286 if (S_ISLNK(entry_info.st_mode)) {
287 return File::kIsLink;
288 }
289 return File::kDoesNotExist;
290 }
291
292
293 static bool CheckTypeAndSetErrno(const char* name,
294 File::Type expected,
295 bool follow_links) {
296 File::Type actual = File::GetType(name, follow_links);
297 if (actual == expected) {
298 return true;
299 }
300 switch (actual) {
301 case File::kIsDirectory:
302 errno = EISDIR;
303 break;
304 case File::kDoesNotExist:
305 errno = ENOENT;
306 break;
307 default:
308 errno = EINVAL;
309 break;
277 } 310 }
278 return false; 311 return false;
279 } 312 }
280 313
281 314
315 bool File::Delete(const char* name) {
316 return CheckTypeAndSetErrno(name, kIsFile, true) &&
317 (NO_RETRY_EXPECTED(unlink(name)) == 0);
318 }
319
320
282 bool File::DeleteLink(const char* name) { 321 bool File::DeleteLink(const char* name) {
283 File::Type type = File::GetType(name, false); 322 return CheckTypeAndSetErrno(name, kIsLink, false) &&
284 if (type == kIsLink) { 323 (NO_RETRY_EXPECTED(unlink(name)) == 0);
285 return NO_RETRY_EXPECTED(unlink(name)) == 0;
286 }
287 errno = EINVAL;
288 return false;
289 } 324 }
290 325
291 326
292 bool File::Rename(const char* old_path, const char* new_path) { 327 bool File::Rename(const char* old_path, const char* new_path) {
293 File::Type type = File::GetType(old_path, true); 328 return CheckTypeAndSetErrno(old_path, kIsFile, true) &&
294 if (type == kIsFile) { 329 (NO_RETRY_EXPECTED(rename(old_path, new_path)) == 0);
295 return NO_RETRY_EXPECTED(rename(old_path, new_path)) == 0;
296 } else if (type == kIsDirectory) {
297 errno = EISDIR;
298 } else {
299 errno = ENOENT;
300 }
301 return false;
302 } 330 }
303 331
304 332
305 bool File::RenameLink(const char* old_path, const char* new_path) { 333 bool File::RenameLink(const char* old_path, const char* new_path) {
306 File::Type type = File::GetType(old_path, false); 334 return CheckTypeAndSetErrno(old_path, kIsLink, false) &&
307 if (type == kIsLink) { 335 (NO_RETRY_EXPECTED(rename(old_path, new_path)) == 0);
308 return NO_RETRY_EXPECTED(rename(old_path, new_path)) == 0;
309 } else if (type == kIsDirectory) {
310 errno = EISDIR;
311 } else {
312 errno = EINVAL;
313 }
314 return false;
315 } 336 }
316 337
317 338
318 bool File::Copy(const char* old_path, const char* new_path) { 339 bool File::Copy(const char* old_path, const char* new_path) {
319 File::Type type = File::GetType(old_path, true); 340 if (!CheckTypeAndSetErrno(old_path, kIsFile, true)) {
320 if (type == kIsFile) { 341 return false;
321 struct stat64 st; 342 }
322 if (TEMP_FAILURE_RETRY(stat64(old_path, &st)) != 0) { 343 struct stat64 st;
323 return false; 344 if (TEMP_FAILURE_RETRY(stat64(old_path, &st)) != 0) {
324 } 345 return false;
325 int old_fd = TEMP_FAILURE_RETRY(open64(old_path, O_RDONLY | O_CLOEXEC)); 346 }
326 if (old_fd < 0) { 347 int old_fd = TEMP_FAILURE_RETRY(open64(old_path, O_RDONLY | O_CLOEXEC));
327 return false; 348 if (old_fd < 0) {
328 } 349 return false;
329 int new_fd = TEMP_FAILURE_RETRY( 350 }
330 open64(new_path, O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, st.st_mode)); 351 int new_fd = TEMP_FAILURE_RETRY(
331 if (new_fd < 0) { 352 open64(new_path, O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, st.st_mode));
332 VOID_TEMP_FAILURE_RETRY(close(old_fd)); 353 if (new_fd < 0) {
333 return false; 354 VOID_TEMP_FAILURE_RETRY(close(old_fd));
334 } 355 return false;
335 int64_t offset = 0; 356 }
336 intptr_t result = 1; 357 int64_t offset = 0;
337 while (result > 0) { 358 intptr_t result = 1;
338 // Loop to ensure we copy everything, and not only up to 2GB. 359 while (result > 0) {
339 result = 360 // Loop to ensure we copy everything, and not only up to 2GB.
340 NO_RETRY_EXPECTED(sendfile64(new_fd, old_fd, &offset, kMaxUint32)); 361 result = NO_RETRY_EXPECTED(sendfile64(new_fd, old_fd, &offset, kMaxUint32));
341 } 362 }
342 // From sendfile man pages: 363 // From sendfile man pages:
343 // Applications may wish to fall back to read(2)/write(2) in the case 364 // Applications may wish to fall back to read(2)/write(2) in the case
344 // where sendfile() fails with EINVAL or ENOSYS. 365 // where sendfile() fails with EINVAL or ENOSYS.
345 if ((result < 0) && ((errno == EINVAL) || (errno == ENOSYS))) { 366 if ((result < 0) && ((errno == EINVAL) || (errno == ENOSYS))) {
346 const intptr_t kBufferSize = 8 * KB; 367 const intptr_t kBufferSize = 8 * KB;
347 uint8_t buffer[kBufferSize]; 368 uint8_t buffer[kBufferSize];
348 while ((result = TEMP_FAILURE_RETRY(read(old_fd, buffer, kBufferSize))) > 369 while ((result = TEMP_FAILURE_RETRY(read(old_fd, buffer, kBufferSize))) >
349 0) { 370 0) {
350 int wrote = TEMP_FAILURE_RETRY(write(new_fd, buffer, result)); 371 int wrote = TEMP_FAILURE_RETRY(write(new_fd, buffer, result));
351 if (wrote != result) { 372 if (wrote != result) {
352 result = -1; 373 result = -1;
353 break; 374 break;
354 }
355 } 375 }
356 } 376 }
357 int e = errno;
358 VOID_TEMP_FAILURE_RETRY(close(old_fd));
359 VOID_TEMP_FAILURE_RETRY(close(new_fd));
360 if (result < 0) {
361 VOID_NO_RETRY_EXPECTED(unlink(new_path));
362 errno = e;
363 return false;
364 }
365 return true;
366 } else if (type == kIsDirectory) {
367 errno = EISDIR;
368 } else {
369 errno = ENOENT;
370 } 377 }
371 return false; 378 int e = errno;
379 VOID_TEMP_FAILURE_RETRY(close(old_fd));
380 VOID_TEMP_FAILURE_RETRY(close(new_fd));
381 if (result < 0) {
382 VOID_NO_RETRY_EXPECTED(unlink(new_path));
383 errno = e;
384 return false;
385 }
386 return true;
372 } 387 }
373 388
374 389
375 int64_t File::LengthFromPath(const char* name) { 390 int64_t File::LengthFromPath(const char* name) {
376 struct stat64 st; 391 struct stat64 st;
377 if (TEMP_FAILURE_RETRY(stat64(name, &st)) == 0) { 392 if (TEMP_FAILURE_RETRY(stat64(name, &st)) == 0) {
378 // Signal an error if it's a directory. 393 // Signal an error if it's a directory.
379 if (S_ISDIR(st.st_mode)) { 394 if (S_ISDIR(st.st_mode)) {
380 errno = EISDIR; 395 errno = EISDIR;
381 return -1; 396 return -1;
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
507 if (S_ISSOCK(buf.st_mode)) { 522 if (S_ISSOCK(buf.st_mode)) {
508 return kSocket; 523 return kSocket;
509 } 524 }
510 if (S_ISREG(buf.st_mode)) { 525 if (S_ISREG(buf.st_mode)) {
511 return kFile; 526 return kFile;
512 } 527 }
513 return kOther; 528 return kOther;
514 } 529 }
515 530
516 531
517 File::Type File::GetType(const char* pathname, bool follow_links) {
518 struct stat64 entry_info;
519 int stat_success;
520 if (follow_links) {
521 stat_success = TEMP_FAILURE_RETRY(stat64(pathname, &entry_info));
522 } else {
523 stat_success = TEMP_FAILURE_RETRY(lstat64(pathname, &entry_info));
524 }
525 if (stat_success == -1) {
526 return File::kDoesNotExist;
527 }
528 if (S_ISDIR(entry_info.st_mode)) {
529 return File::kIsDirectory;
530 }
531 if (S_ISREG(entry_info.st_mode)) {
532 return File::kIsFile;
533 }
534 if (S_ISLNK(entry_info.st_mode)) {
535 return File::kIsLink;
536 }
537 return File::kDoesNotExist;
538 }
539
540
541 File::Identical File::AreIdentical(const char* file_1, const char* file_2) { 532 File::Identical File::AreIdentical(const char* file_1, const char* file_2) {
542 struct stat64 file_1_info; 533 struct stat64 file_1_info;
543 struct stat64 file_2_info; 534 struct stat64 file_2_info;
544 if ((TEMP_FAILURE_RETRY(lstat64(file_1, &file_1_info)) == -1) || 535 if ((TEMP_FAILURE_RETRY(lstat64(file_1, &file_1_info)) == -1) ||
545 (TEMP_FAILURE_RETRY(lstat64(file_2, &file_2_info)) == -1)) { 536 (TEMP_FAILURE_RETRY(lstat64(file_2, &file_2_info)) == -1)) {
546 return File::kError; 537 return File::kError;
547 } 538 }
548 return ((file_1_info.st_ino == file_2_info.st_ino) && 539 return ((file_1_info.st_ino == file_2_info.st_ino) &&
549 (file_1_info.st_dev == file_2_info.st_dev)) 540 (file_1_info.st_dev == file_2_info.st_dev))
550 ? File::kIdentical 541 ? File::kIdentical
551 : File::kDifferent; 542 : File::kDifferent;
552 } 543 }
553 544
554 } // namespace bin 545 } // namespace bin
555 } // namespace dart 546 } // namespace dart
556 547
557 #endif // defined(TARGET_OS_LINUX) 548 #endif // defined(TARGET_OS_LINUX)
OLDNEW
« no previous file with comments | « runtime/bin/file_fuchsia.cc ('k') | runtime/bin/file_macos.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698