Index: runtime/bin/file_fuchsia.cc |
diff --git a/runtime/bin/file_fuchsia.cc b/runtime/bin/file_fuchsia.cc |
index 1c2fe03f0d36aebc68d3de3335a2fcde5a931e0c..7175d55c8f79578a36e62d813c06f0d0cdae513f 100644 |
--- a/runtime/bin/file_fuchsia.cc |
+++ b/runtime/bin/file_fuchsia.cc |
@@ -248,99 +248,114 @@ bool File::CreateLink(const char* name, const char* target) { |
} |
-bool File::Delete(const char* name) { |
- File::Type type = File::GetType(name, true); |
- if (type == kIsFile) { |
- return NO_RETRY_EXPECTED(unlink(name)) == 0; |
- } else if (type == kIsDirectory) { |
- errno = EISDIR; |
+File::Type File::GetType(const char* pathname, bool follow_links) { |
+ struct stat entry_info; |
+ int stat_success; |
+ if (follow_links) { |
+ stat_success = NO_RETRY_EXPECTED(stat(pathname, &entry_info)); |
} else { |
- errno = ENOENT; |
+ stat_success = NO_RETRY_EXPECTED(lstat(pathname, &entry_info)); |
} |
- return false; |
+ if (stat_success == -1) { |
+ return File::kDoesNotExist; |
+ } |
+ if (S_ISDIR(entry_info.st_mode)) { |
+ return File::kIsDirectory; |
+ } |
+ if (S_ISREG(entry_info.st_mode)) { |
+ return File::kIsFile; |
+ } |
+ if (S_ISLNK(entry_info.st_mode)) { |
+ return File::kIsLink; |
+ } |
+ return File::kDoesNotExist; |
} |
-bool File::DeleteLink(const char* name) { |
- File::Type type = File::GetType(name, false); |
- if (type == kIsLink) { |
- return NO_RETRY_EXPECTED(unlink(name)) == 0; |
+static bool CheckTypeAndSetErrno(const char* name, |
+ File::Type expected, |
+ bool follow_links) { |
+ File::Type actual = File::GetType(name, follow_links); |
+ if (actual == expected) { |
+ return true; |
+ } |
+ switch (actual) { |
+ case File::kIsDirectory: |
+ errno = EISDIR; |
+ break; |
+ case File::kDoesNotExist: |
+ errno = ENOENT; |
+ break; |
+ default: |
+ errno = EINVAL; |
+ break; |
} |
- errno = EINVAL; |
return false; |
} |
+bool File::Delete(const char* name) { |
+ return CheckTypeAndSetErrno(name, kIsFile, true) && |
+ (NO_RETRY_EXPECTED(unlink(name)) == 0); |
+} |
+ |
+ |
+bool File::DeleteLink(const char* name) { |
+ return CheckTypeAndSetErrno(name, kIsLink, false) && |
+ (NO_RETRY_EXPECTED(unlink(name)) == 0); |
+} |
+ |
+ |
bool File::Rename(const char* old_path, const char* new_path) { |
- File::Type type = File::GetType(old_path, true); |
- if (type == kIsFile) { |
- return NO_RETRY_EXPECTED(rename(old_path, new_path)) == 0; |
- } else if (type == kIsDirectory) { |
- errno = EISDIR; |
- } else { |
- errno = ENOENT; |
- } |
- return false; |
+ return CheckTypeAndSetErrno(old_path, kIsFile, true) && |
+ (NO_RETRY_EXPECTED(rename(old_path, new_path)) == 0); |
} |
bool File::RenameLink(const char* old_path, const char* new_path) { |
- File::Type type = File::GetType(old_path, false); |
- if (type == kIsLink) { |
- return NO_RETRY_EXPECTED(rename(old_path, new_path)) == 0; |
- } else if (type == kIsDirectory) { |
- errno = EISDIR; |
- } else { |
- errno = EINVAL; |
- } |
- return false; |
+ return CheckTypeAndSetErrno(old_path, kIsLink, false) && |
+ (NO_RETRY_EXPECTED(rename(old_path, new_path)) == 0); |
} |
bool File::Copy(const char* old_path, const char* new_path) { |
- File::Type type = File::GetType(old_path, true); |
- if (type == kIsFile) { |
- struct stat64 st; |
- if (NO_RETRY_EXPECTED(stat64(old_path, &st)) != 0) { |
- return false; |
- } |
- int old_fd = NO_RETRY_EXPECTED(open64(old_path, O_RDONLY | O_CLOEXEC)); |
- if (old_fd < 0) { |
- return false; |
- } |
- int new_fd = NO_RETRY_EXPECTED( |
- open64(new_path, O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, st.st_mode)); |
- if (new_fd < 0) { |
- VOID_TEMP_FAILURE_RETRY(close(old_fd)); |
- return false; |
- } |
- // TODO(MG-429): Use sendfile/copyfile or equivalent when there is one. |
- intptr_t result; |
- const intptr_t kBufferSize = 8 * KB; |
- uint8_t buffer[kBufferSize]; |
- while ((result = NO_RETRY_EXPECTED(read(old_fd, buffer, kBufferSize))) > |
- 0) { |
- int wrote = NO_RETRY_EXPECTED(write(new_fd, buffer, result)); |
- if (wrote != result) { |
- result = -1; |
- break; |
- } |
- } |
- FDUtils::SaveErrorAndClose(old_fd); |
- FDUtils::SaveErrorAndClose(new_fd); |
- if (result < 0) { |
- int e = errno; |
- VOID_NO_RETRY_EXPECTED(unlink(new_path)); |
- errno = e; |
- return false; |
+ if (!CheckTypeAndSetErrno(old_path, kIsFile, true)) { |
+ return false; |
+ } |
+ struct stat64 st; |
+ if (NO_RETRY_EXPECTED(stat64(old_path, &st)) != 0) { |
+ return false; |
+ } |
+ int old_fd = NO_RETRY_EXPECTED(open64(old_path, O_RDONLY | O_CLOEXEC)); |
+ if (old_fd < 0) { |
+ return false; |
+ } |
+ int new_fd = NO_RETRY_EXPECTED( |
+ open64(new_path, O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, st.st_mode)); |
+ if (new_fd < 0) { |
+ VOID_TEMP_FAILURE_RETRY(close(old_fd)); |
+ return false; |
+ } |
+ // TODO(MG-429): Use sendfile/copyfile or equivalent when there is one. |
+ intptr_t result; |
+ const intptr_t kBufferSize = 8 * KB; |
+ uint8_t buffer[kBufferSize]; |
+ while ((result = NO_RETRY_EXPECTED(read(old_fd, buffer, kBufferSize))) > 0) { |
+ int wrote = NO_RETRY_EXPECTED(write(new_fd, buffer, result)); |
+ if (wrote != result) { |
+ result = -1; |
+ break; |
} |
- return true; |
- } else if (type == kIsDirectory) { |
- errno = EISDIR; |
- } else { |
- errno = ENOENT; |
} |
- return false; |
+ FDUtils::SaveErrorAndClose(old_fd); |
+ FDUtils::SaveErrorAndClose(new_fd); |
+ if (result < 0) { |
+ int e = errno; |
+ VOID_NO_RETRY_EXPECTED(unlink(new_path)); |
+ errno = e; |
+ return false; |
+ } |
+ return true; |
} |
@@ -479,30 +494,6 @@ File::StdioHandleType File::GetStdioHandleType(int fd) { |
} |
-File::Type File::GetType(const char* pathname, bool follow_links) { |
- struct stat entry_info; |
- int stat_success; |
- if (follow_links) { |
- stat_success = NO_RETRY_EXPECTED(stat(pathname, &entry_info)); |
- } else { |
- stat_success = NO_RETRY_EXPECTED(lstat(pathname, &entry_info)); |
- } |
- if (stat_success == -1) { |
- return File::kDoesNotExist; |
- } |
- if (S_ISDIR(entry_info.st_mode)) { |
- return File::kIsDirectory; |
- } |
- if (S_ISREG(entry_info.st_mode)) { |
- return File::kIsFile; |
- } |
- if (S_ISLNK(entry_info.st_mode)) { |
- return File::kIsLink; |
- } |
- return File::kDoesNotExist; |
-} |
- |
- |
File::Identical File::AreIdentical(const char* file_1, const char* file_2) { |
struct stat file_1_info; |
struct stat file_2_info; |