| 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;
|
|
|