| OLD | NEW |
| 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(HOST_OS_ANDROID) | 6 #if defined(HOST_OS_ANDROID) |
| 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 21 matching lines...) Expand all Loading... |
| 32 ~FileHandle() {} | 32 ~FileHandle() {} |
| 33 int fd() const { return fd_; } | 33 int fd() const { return fd_; } |
| 34 void set_fd(int fd) { fd_ = fd; } | 34 void set_fd(int fd) { fd_ = fd; } |
| 35 | 35 |
| 36 private: | 36 private: |
| 37 int fd_; | 37 int fd_; |
| 38 | 38 |
| 39 DISALLOW_COPY_AND_ASSIGN(FileHandle); | 39 DISALLOW_COPY_AND_ASSIGN(FileHandle); |
| 40 }; | 40 }; |
| 41 | 41 |
| 42 | |
| 43 File::~File() { | 42 File::~File() { |
| 44 if (!IsClosed()) { | 43 if (!IsClosed()) { |
| 45 Close(); | 44 Close(); |
| 46 } | 45 } |
| 47 delete handle_; | 46 delete handle_; |
| 48 } | 47 } |
| 49 | 48 |
| 50 | |
| 51 void File::Close() { | 49 void File::Close() { |
| 52 ASSERT(handle_->fd() >= 0); | 50 ASSERT(handle_->fd() >= 0); |
| 53 if (handle_->fd() == STDOUT_FILENO) { | 51 if (handle_->fd() == STDOUT_FILENO) { |
| 54 // If stdout, redirect fd to /dev/null. | 52 // If stdout, redirect fd to /dev/null. |
| 55 int null_fd = TEMP_FAILURE_RETRY(open("/dev/null", O_WRONLY)); | 53 int null_fd = TEMP_FAILURE_RETRY(open("/dev/null", O_WRONLY)); |
| 56 ASSERT(null_fd >= 0); | 54 ASSERT(null_fd >= 0); |
| 57 VOID_TEMP_FAILURE_RETRY(dup2(null_fd, handle_->fd())); | 55 VOID_TEMP_FAILURE_RETRY(dup2(null_fd, handle_->fd())); |
| 58 VOID_TEMP_FAILURE_RETRY(close(null_fd)); | 56 VOID_TEMP_FAILURE_RETRY(close(null_fd)); |
| 59 } else { | 57 } else { |
| 60 int err = TEMP_FAILURE_RETRY(close(handle_->fd())); | 58 int err = TEMP_FAILURE_RETRY(close(handle_->fd())); |
| 61 if (err != 0) { | 59 if (err != 0) { |
| 62 const int kBufferSize = 1024; | 60 const int kBufferSize = 1024; |
| 63 char error_message[kBufferSize]; | 61 char error_message[kBufferSize]; |
| 64 Utils::StrError(errno, error_message, kBufferSize); | 62 Utils::StrError(errno, error_message, kBufferSize); |
| 65 Log::PrintErr("%s\n", error_message); | 63 Log::PrintErr("%s\n", error_message); |
| 66 } | 64 } |
| 67 } | 65 } |
| 68 handle_->set_fd(kClosedFd); | 66 handle_->set_fd(kClosedFd); |
| 69 } | 67 } |
| 70 | 68 |
| 71 | |
| 72 intptr_t File::GetFD() { | 69 intptr_t File::GetFD() { |
| 73 return handle_->fd(); | 70 return handle_->fd(); |
| 74 } | 71 } |
| 75 | 72 |
| 76 | |
| 77 bool File::IsClosed() { | 73 bool File::IsClosed() { |
| 78 return handle_->fd() == kClosedFd; | 74 return handle_->fd() == kClosedFd; |
| 79 } | 75 } |
| 80 | 76 |
| 81 | |
| 82 MappedMemory* File::Map(MapType type, int64_t position, int64_t length) { | 77 MappedMemory* File::Map(MapType type, int64_t position, int64_t length) { |
| 83 ASSERT(handle_->fd() >= 0); | 78 ASSERT(handle_->fd() >= 0); |
| 84 ASSERT(length > 0); | 79 ASSERT(length > 0); |
| 85 int prot = PROT_NONE; | 80 int prot = PROT_NONE; |
| 86 switch (type) { | 81 switch (type) { |
| 87 case kReadOnly: | 82 case kReadOnly: |
| 88 prot = PROT_READ; | 83 prot = PROT_READ; |
| 89 break; | 84 break; |
| 90 case kReadExecute: | 85 case kReadExecute: |
| 91 prot = PROT_READ | PROT_EXEC; | 86 prot = PROT_READ | PROT_EXEC; |
| 92 break; | 87 break; |
| 93 default: | 88 default: |
| 94 return NULL; | 89 return NULL; |
| 95 } | 90 } |
| 96 void* addr = mmap(NULL, length, prot, MAP_PRIVATE, handle_->fd(), position); | 91 void* addr = mmap(NULL, length, prot, MAP_PRIVATE, handle_->fd(), position); |
| 97 if (addr == MAP_FAILED) { | 92 if (addr == MAP_FAILED) { |
| 98 return NULL; | 93 return NULL; |
| 99 } | 94 } |
| 100 return new MappedMemory(addr, length); | 95 return new MappedMemory(addr, length); |
| 101 } | 96 } |
| 102 | 97 |
| 103 | |
| 104 void MappedMemory::Unmap() { | 98 void MappedMemory::Unmap() { |
| 105 int result = munmap(address_, size_); | 99 int result = munmap(address_, size_); |
| 106 ASSERT(result == 0); | 100 ASSERT(result == 0); |
| 107 address_ = 0; | 101 address_ = 0; |
| 108 size_ = 0; | 102 size_ = 0; |
| 109 } | 103 } |
| 110 | 104 |
| 111 | |
| 112 int64_t File::Read(void* buffer, int64_t num_bytes) { | 105 int64_t File::Read(void* buffer, int64_t num_bytes) { |
| 113 ASSERT(handle_->fd() >= 0); | 106 ASSERT(handle_->fd() >= 0); |
| 114 return TEMP_FAILURE_RETRY(read(handle_->fd(), buffer, num_bytes)); | 107 return TEMP_FAILURE_RETRY(read(handle_->fd(), buffer, num_bytes)); |
| 115 } | 108 } |
| 116 | 109 |
| 117 | |
| 118 int64_t File::Write(const void* buffer, int64_t num_bytes) { | 110 int64_t File::Write(const void* buffer, int64_t num_bytes) { |
| 119 ASSERT(handle_->fd() >= 0); | 111 ASSERT(handle_->fd() >= 0); |
| 120 return TEMP_FAILURE_RETRY(write(handle_->fd(), buffer, num_bytes)); | 112 return TEMP_FAILURE_RETRY(write(handle_->fd(), buffer, num_bytes)); |
| 121 } | 113 } |
| 122 | 114 |
| 123 | |
| 124 bool File::VPrint(const char* format, va_list args) { | 115 bool File::VPrint(const char* format, va_list args) { |
| 125 // Measure. | 116 // Measure. |
| 126 va_list measure_args; | 117 va_list measure_args; |
| 127 va_copy(measure_args, args); | 118 va_copy(measure_args, args); |
| 128 intptr_t len = vsnprintf(NULL, 0, format, measure_args); | 119 intptr_t len = vsnprintf(NULL, 0, format, measure_args); |
| 129 va_end(measure_args); | 120 va_end(measure_args); |
| 130 | 121 |
| 131 char* buffer = reinterpret_cast<char*>(malloc(len + 1)); | 122 char* buffer = reinterpret_cast<char*>(malloc(len + 1)); |
| 132 | 123 |
| 133 // Print. | 124 // Print. |
| 134 va_list print_args; | 125 va_list print_args; |
| 135 va_copy(print_args, args); | 126 va_copy(print_args, args); |
| 136 vsnprintf(buffer, len + 1, format, print_args); | 127 vsnprintf(buffer, len + 1, format, print_args); |
| 137 va_end(print_args); | 128 va_end(print_args); |
| 138 | 129 |
| 139 bool result = WriteFully(buffer, len); | 130 bool result = WriteFully(buffer, len); |
| 140 free(buffer); | 131 free(buffer); |
| 141 return result; | 132 return result; |
| 142 } | 133 } |
| 143 | 134 |
| 144 | |
| 145 int64_t File::Position() { | 135 int64_t File::Position() { |
| 146 ASSERT(handle_->fd() >= 0); | 136 ASSERT(handle_->fd() >= 0); |
| 147 return NO_RETRY_EXPECTED(lseek64(handle_->fd(), 0, SEEK_CUR)); | 137 return NO_RETRY_EXPECTED(lseek64(handle_->fd(), 0, SEEK_CUR)); |
| 148 } | 138 } |
| 149 | 139 |
| 150 | |
| 151 bool File::SetPosition(int64_t position) { | 140 bool File::SetPosition(int64_t position) { |
| 152 ASSERT(handle_->fd() >= 0); | 141 ASSERT(handle_->fd() >= 0); |
| 153 return NO_RETRY_EXPECTED(lseek64(handle_->fd(), position, SEEK_SET)) >= 0; | 142 return NO_RETRY_EXPECTED(lseek64(handle_->fd(), position, SEEK_SET)) >= 0; |
| 154 } | 143 } |
| 155 | 144 |
| 156 | |
| 157 bool File::Truncate(int64_t length) { | 145 bool File::Truncate(int64_t length) { |
| 158 ASSERT(handle_->fd() >= 0); | 146 ASSERT(handle_->fd() >= 0); |
| 159 return TEMP_FAILURE_RETRY(ftruncate(handle_->fd(), length) != -1); | 147 return TEMP_FAILURE_RETRY(ftruncate(handle_->fd(), length) != -1); |
| 160 } | 148 } |
| 161 | 149 |
| 162 | |
| 163 bool File::Flush() { | 150 bool File::Flush() { |
| 164 ASSERT(handle_->fd() >= 0); | 151 ASSERT(handle_->fd() >= 0); |
| 165 return NO_RETRY_EXPECTED(fsync(handle_->fd()) != -1); | 152 return NO_RETRY_EXPECTED(fsync(handle_->fd()) != -1); |
| 166 } | 153 } |
| 167 | 154 |
| 168 | |
| 169 bool File::Lock(File::LockType lock, int64_t start, int64_t end) { | 155 bool File::Lock(File::LockType lock, int64_t start, int64_t end) { |
| 170 ASSERT(handle_->fd() >= 0); | 156 ASSERT(handle_->fd() >= 0); |
| 171 ASSERT((end == -1) || (end > start)); | 157 ASSERT((end == -1) || (end > start)); |
| 172 struct flock fl; | 158 struct flock fl; |
| 173 switch (lock) { | 159 switch (lock) { |
| 174 case File::kLockUnlock: | 160 case File::kLockUnlock: |
| 175 fl.l_type = F_UNLCK; | 161 fl.l_type = F_UNLCK; |
| 176 break; | 162 break; |
| 177 case File::kLockShared: | 163 case File::kLockShared: |
| 178 case File::kLockBlockingShared: | 164 case File::kLockBlockingShared: |
| (...skipping 10 matching lines...) Expand all Loading... |
| 189 fl.l_start = start; | 175 fl.l_start = start; |
| 190 fl.l_len = end == -1 ? 0 : end - start; | 176 fl.l_len = end == -1 ? 0 : end - start; |
| 191 int cmd = F_SETLK; | 177 int cmd = F_SETLK; |
| 192 if ((lock == File::kLockBlockingShared) || | 178 if ((lock == File::kLockBlockingShared) || |
| 193 (lock == File::kLockBlockingExclusive)) { | 179 (lock == File::kLockBlockingExclusive)) { |
| 194 cmd = F_SETLKW; | 180 cmd = F_SETLKW; |
| 195 } | 181 } |
| 196 return TEMP_FAILURE_RETRY(fcntl(handle_->fd(), cmd, &fl)) != -1; | 182 return TEMP_FAILURE_RETRY(fcntl(handle_->fd(), cmd, &fl)) != -1; |
| 197 } | 183 } |
| 198 | 184 |
| 199 | |
| 200 int64_t File::Length() { | 185 int64_t File::Length() { |
| 201 ASSERT(handle_->fd() >= 0); | 186 ASSERT(handle_->fd() >= 0); |
| 202 struct stat st; | 187 struct stat st; |
| 203 if (NO_RETRY_EXPECTED(fstat(handle_->fd(), &st)) == 0) { | 188 if (NO_RETRY_EXPECTED(fstat(handle_->fd(), &st)) == 0) { |
| 204 return st.st_size; | 189 return st.st_size; |
| 205 } | 190 } |
| 206 return -1; | 191 return -1; |
| 207 } | 192 } |
| 208 | 193 |
| 209 | |
| 210 File* File::FileOpenW(const wchar_t* system_name, FileOpenMode mode) { | 194 File* File::FileOpenW(const wchar_t* system_name, FileOpenMode mode) { |
| 211 UNREACHABLE(); | 195 UNREACHABLE(); |
| 212 return NULL; | 196 return NULL; |
| 213 } | 197 } |
| 214 | 198 |
| 215 | |
| 216 File* File::Open(const char* name, FileOpenMode mode) { | 199 File* File::Open(const char* name, FileOpenMode mode) { |
| 217 // Report errors for non-regular files. | 200 // Report errors for non-regular files. |
| 218 struct stat st; | 201 struct stat st; |
| 219 if (NO_RETRY_EXPECTED(stat(name, &st)) == 0) { | 202 if (NO_RETRY_EXPECTED(stat(name, &st)) == 0) { |
| 220 if (!S_ISREG(st.st_mode)) { | 203 if (!S_ISREG(st.st_mode)) { |
| 221 errno = (S_ISDIR(st.st_mode)) ? EISDIR : ENOENT; | 204 errno = (S_ISDIR(st.st_mode)) ? EISDIR : ENOENT; |
| 222 return NULL; | 205 return NULL; |
| 223 } | 206 } |
| 224 } | 207 } |
| 225 int flags = O_RDONLY; | 208 int flags = O_RDONLY; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 242 if ((((mode & kWrite) != 0) && ((mode & kTruncate) == 0)) || | 225 if ((((mode & kWrite) != 0) && ((mode & kTruncate) == 0)) || |
| 243 (((mode & kWriteOnly) != 0) && ((mode & kTruncate) == 0))) { | 226 (((mode & kWriteOnly) != 0) && ((mode & kTruncate) == 0))) { |
| 244 int64_t position = lseek64(fd, 0, SEEK_END); | 227 int64_t position = lseek64(fd, 0, SEEK_END); |
| 245 if (position < 0) { | 228 if (position < 0) { |
| 246 return NULL; | 229 return NULL; |
| 247 } | 230 } |
| 248 } | 231 } |
| 249 return new File(new FileHandle(fd)); | 232 return new File(new FileHandle(fd)); |
| 250 } | 233 } |
| 251 | 234 |
| 252 | |
| 253 File* File::OpenStdio(int fd) { | 235 File* File::OpenStdio(int fd) { |
| 254 return ((fd < 0) || (2 < fd)) ? NULL : new File(new FileHandle(fd)); | 236 return ((fd < 0) || (2 < fd)) ? NULL : new File(new FileHandle(fd)); |
| 255 } | 237 } |
| 256 | 238 |
| 257 | |
| 258 bool File::Exists(const char* name) { | 239 bool File::Exists(const char* name) { |
| 259 struct stat st; | 240 struct stat st; |
| 260 if (NO_RETRY_EXPECTED(stat(name, &st)) == 0) { | 241 if (NO_RETRY_EXPECTED(stat(name, &st)) == 0) { |
| 261 // Everything but a directory and a link is a file to Dart. | 242 // Everything but a directory and a link is a file to Dart. |
| 262 return !S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode); | 243 return !S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode); |
| 263 } else { | 244 } else { |
| 264 return false; | 245 return false; |
| 265 } | 246 } |
| 266 } | 247 } |
| 267 | 248 |
| 268 | |
| 269 bool File::Create(const char* name) { | 249 bool File::Create(const char* name) { |
| 270 int fd = TEMP_FAILURE_RETRY(open(name, O_RDONLY | O_CREAT | O_CLOEXEC, 0666)); | 250 int fd = TEMP_FAILURE_RETRY(open(name, O_RDONLY | O_CREAT | O_CLOEXEC, 0666)); |
| 271 if (fd < 0) { | 251 if (fd < 0) { |
| 272 return false; | 252 return false; |
| 273 } | 253 } |
| 274 // File.create returns a File, so we shouldn't be giving the illusion that the | 254 // File.create returns a File, so we shouldn't be giving the illusion that the |
| 275 // call has created a file or that a file already exists if there is already | 255 // call has created a file or that a file already exists if there is already |
| 276 // an entity at the same path that is a directory or a link. | 256 // an entity at the same path that is a directory or a link. |
| 277 bool is_file = true; | 257 bool is_file = true; |
| 278 struct stat st; | 258 struct stat st; |
| 279 if (NO_RETRY_EXPECTED(fstat(fd, &st)) == 0) { | 259 if (NO_RETRY_EXPECTED(fstat(fd, &st)) == 0) { |
| 280 if (S_ISDIR(st.st_mode)) { | 260 if (S_ISDIR(st.st_mode)) { |
| 281 errno = EISDIR; | 261 errno = EISDIR; |
| 282 is_file = false; | 262 is_file = false; |
| 283 } else if (S_ISLNK(st.st_mode)) { | 263 } else if (S_ISLNK(st.st_mode)) { |
| 284 errno = ENOENT; | 264 errno = ENOENT; |
| 285 is_file = false; | 265 is_file = false; |
| 286 } | 266 } |
| 287 } | 267 } |
| 288 FDUtils::SaveErrorAndClose(fd); | 268 FDUtils::SaveErrorAndClose(fd); |
| 289 return is_file; | 269 return is_file; |
| 290 } | 270 } |
| 291 | 271 |
| 292 | |
| 293 bool File::CreateLink(const char* name, const char* target) { | 272 bool File::CreateLink(const char* name, const char* target) { |
| 294 int status = NO_RETRY_EXPECTED(symlink(target, name)); | 273 int status = NO_RETRY_EXPECTED(symlink(target, name)); |
| 295 return (status == 0); | 274 return (status == 0); |
| 296 } | 275 } |
| 297 | 276 |
| 298 | |
| 299 File::Type File::GetType(const char* pathname, bool follow_links) { | 277 File::Type File::GetType(const char* pathname, bool follow_links) { |
| 300 struct stat entry_info; | 278 struct stat entry_info; |
| 301 int stat_success; | 279 int stat_success; |
| 302 if (follow_links) { | 280 if (follow_links) { |
| 303 stat_success = NO_RETRY_EXPECTED(stat(pathname, &entry_info)); | 281 stat_success = NO_RETRY_EXPECTED(stat(pathname, &entry_info)); |
| 304 } else { | 282 } else { |
| 305 stat_success = NO_RETRY_EXPECTED(lstat(pathname, &entry_info)); | 283 stat_success = NO_RETRY_EXPECTED(lstat(pathname, &entry_info)); |
| 306 } | 284 } |
| 307 if (stat_success == -1) { | 285 if (stat_success == -1) { |
| 308 return File::kDoesNotExist; | 286 return File::kDoesNotExist; |
| 309 } | 287 } |
| 310 if (S_ISDIR(entry_info.st_mode)) { | 288 if (S_ISDIR(entry_info.st_mode)) { |
| 311 return File::kIsDirectory; | 289 return File::kIsDirectory; |
| 312 } | 290 } |
| 313 if (S_ISREG(entry_info.st_mode)) { | 291 if (S_ISREG(entry_info.st_mode)) { |
| 314 return File::kIsFile; | 292 return File::kIsFile; |
| 315 } | 293 } |
| 316 if (S_ISLNK(entry_info.st_mode)) { | 294 if (S_ISLNK(entry_info.st_mode)) { |
| 317 return File::kIsLink; | 295 return File::kIsLink; |
| 318 } | 296 } |
| 319 return File::kDoesNotExist; | 297 return File::kDoesNotExist; |
| 320 } | 298 } |
| 321 | 299 |
| 322 | |
| 323 static bool CheckTypeAndSetErrno(const char* name, | 300 static bool CheckTypeAndSetErrno(const char* name, |
| 324 File::Type expected, | 301 File::Type expected, |
| 325 bool follow_links) { | 302 bool follow_links) { |
| 326 File::Type actual = File::GetType(name, follow_links); | 303 File::Type actual = File::GetType(name, follow_links); |
| 327 if (actual == expected) { | 304 if (actual == expected) { |
| 328 return true; | 305 return true; |
| 329 } | 306 } |
| 330 switch (actual) { | 307 switch (actual) { |
| 331 case File::kIsDirectory: | 308 case File::kIsDirectory: |
| 332 errno = EISDIR; | 309 errno = EISDIR; |
| 333 break; | 310 break; |
| 334 case File::kDoesNotExist: | 311 case File::kDoesNotExist: |
| 335 errno = ENOENT; | 312 errno = ENOENT; |
| 336 break; | 313 break; |
| 337 default: | 314 default: |
| 338 errno = EINVAL; | 315 errno = EINVAL; |
| 339 break; | 316 break; |
| 340 } | 317 } |
| 341 return false; | 318 return false; |
| 342 } | 319 } |
| 343 | 320 |
| 344 | |
| 345 bool File::Delete(const char* name) { | 321 bool File::Delete(const char* name) { |
| 346 return CheckTypeAndSetErrno(name, kIsFile, true) && | 322 return CheckTypeAndSetErrno(name, kIsFile, true) && |
| 347 (NO_RETRY_EXPECTED(unlink(name)) == 0); | 323 (NO_RETRY_EXPECTED(unlink(name)) == 0); |
| 348 } | 324 } |
| 349 | 325 |
| 350 | |
| 351 bool File::DeleteLink(const char* name) { | 326 bool File::DeleteLink(const char* name) { |
| 352 return CheckTypeAndSetErrno(name, kIsLink, false) && | 327 return CheckTypeAndSetErrno(name, kIsLink, false) && |
| 353 (NO_RETRY_EXPECTED(unlink(name)) == 0); | 328 (NO_RETRY_EXPECTED(unlink(name)) == 0); |
| 354 } | 329 } |
| 355 | 330 |
| 356 | |
| 357 bool File::Rename(const char* old_path, const char* new_path) { | 331 bool File::Rename(const char* old_path, const char* new_path) { |
| 358 return CheckTypeAndSetErrno(old_path, kIsFile, true) && | 332 return CheckTypeAndSetErrno(old_path, kIsFile, true) && |
| 359 (NO_RETRY_EXPECTED(rename(old_path, new_path)) == 0); | 333 (NO_RETRY_EXPECTED(rename(old_path, new_path)) == 0); |
| 360 } | 334 } |
| 361 | 335 |
| 362 | |
| 363 bool File::RenameLink(const char* old_path, const char* new_path) { | 336 bool File::RenameLink(const char* old_path, const char* new_path) { |
| 364 return CheckTypeAndSetErrno(old_path, kIsLink, false) && | 337 return CheckTypeAndSetErrno(old_path, kIsLink, false) && |
| 365 (NO_RETRY_EXPECTED(rename(old_path, new_path)) == 0); | 338 (NO_RETRY_EXPECTED(rename(old_path, new_path)) == 0); |
| 366 } | 339 } |
| 367 | 340 |
| 368 | |
| 369 bool File::Copy(const char* old_path, const char* new_path) { | 341 bool File::Copy(const char* old_path, const char* new_path) { |
| 370 if (!CheckTypeAndSetErrno(old_path, kIsFile, true)) { | 342 if (!CheckTypeAndSetErrno(old_path, kIsFile, true)) { |
| 371 return false; | 343 return false; |
| 372 } | 344 } |
| 373 struct stat st; | 345 struct stat st; |
| 374 if (NO_RETRY_EXPECTED(stat(old_path, &st)) != 0) { | 346 if (NO_RETRY_EXPECTED(stat(old_path, &st)) != 0) { |
| 375 return false; | 347 return false; |
| 376 } | 348 } |
| 377 int old_fd = TEMP_FAILURE_RETRY(open(old_path, O_RDONLY | O_CLOEXEC)); | 349 int old_fd = TEMP_FAILURE_RETRY(open(old_path, O_RDONLY | O_CLOEXEC)); |
| 378 if (old_fd < 0) { | 350 if (old_fd < 0) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 409 VOID_TEMP_FAILURE_RETRY(close(old_fd)); | 381 VOID_TEMP_FAILURE_RETRY(close(old_fd)); |
| 410 VOID_TEMP_FAILURE_RETRY(close(new_fd)); | 382 VOID_TEMP_FAILURE_RETRY(close(new_fd)); |
| 411 if (result < 0) { | 383 if (result < 0) { |
| 412 VOID_NO_RETRY_EXPECTED(unlink(new_path)); | 384 VOID_NO_RETRY_EXPECTED(unlink(new_path)); |
| 413 errno = e; | 385 errno = e; |
| 414 return false; | 386 return false; |
| 415 } | 387 } |
| 416 return true; | 388 return true; |
| 417 } | 389 } |
| 418 | 390 |
| 419 | |
| 420 static bool StatHelper(const char* name, struct stat* st) { | 391 static bool StatHelper(const char* name, struct stat* st) { |
| 421 if (NO_RETRY_EXPECTED(stat(name, st)) != 0) { | 392 if (NO_RETRY_EXPECTED(stat(name, st)) != 0) { |
| 422 return false; | 393 return false; |
| 423 } | 394 } |
| 424 // Signal an error if it's a directory. | 395 // Signal an error if it's a directory. |
| 425 if (S_ISDIR(st->st_mode)) { | 396 if (S_ISDIR(st->st_mode)) { |
| 426 errno = EISDIR; | 397 errno = EISDIR; |
| 427 return false; | 398 return false; |
| 428 } | 399 } |
| 429 // Otherwise assume the caller knows what it's doing. | 400 // Otherwise assume the caller knows what it's doing. |
| 430 return true; | 401 return true; |
| 431 } | 402 } |
| 432 | 403 |
| 433 | |
| 434 int64_t File::LengthFromPath(const char* name) { | 404 int64_t File::LengthFromPath(const char* name) { |
| 435 struct stat st; | 405 struct stat st; |
| 436 if (!StatHelper(name, &st)) { | 406 if (!StatHelper(name, &st)) { |
| 437 return -1; | 407 return -1; |
| 438 } | 408 } |
| 439 return st.st_size; | 409 return st.st_size; |
| 440 } | 410 } |
| 441 | 411 |
| 442 | |
| 443 void File::Stat(const char* name, int64_t* data) { | 412 void File::Stat(const char* name, int64_t* data) { |
| 444 struct stat st; | 413 struct stat st; |
| 445 if (NO_RETRY_EXPECTED(stat(name, &st)) == 0) { | 414 if (NO_RETRY_EXPECTED(stat(name, &st)) == 0) { |
| 446 if (S_ISREG(st.st_mode)) { | 415 if (S_ISREG(st.st_mode)) { |
| 447 data[kType] = kIsFile; | 416 data[kType] = kIsFile; |
| 448 } else if (S_ISDIR(st.st_mode)) { | 417 } else if (S_ISDIR(st.st_mode)) { |
| 449 data[kType] = kIsDirectory; | 418 data[kType] = kIsDirectory; |
| 450 } else if (S_ISLNK(st.st_mode)) { | 419 } else if (S_ISLNK(st.st_mode)) { |
| 451 data[kType] = kIsLink; | 420 data[kType] = kIsLink; |
| 452 } else { | 421 } else { |
| 453 data[kType] = kDoesNotExist; | 422 data[kType] = kDoesNotExist; |
| 454 } | 423 } |
| 455 data[kCreatedTime] = static_cast<int64_t>(st.st_ctime) * 1000; | 424 data[kCreatedTime] = static_cast<int64_t>(st.st_ctime) * 1000; |
| 456 data[kModifiedTime] = static_cast<int64_t>(st.st_mtime) * 1000; | 425 data[kModifiedTime] = static_cast<int64_t>(st.st_mtime) * 1000; |
| 457 data[kAccessedTime] = static_cast<int64_t>(st.st_atime) * 1000; | 426 data[kAccessedTime] = static_cast<int64_t>(st.st_atime) * 1000; |
| 458 data[kMode] = st.st_mode; | 427 data[kMode] = st.st_mode; |
| 459 data[kSize] = st.st_size; | 428 data[kSize] = st.st_size; |
| 460 } else { | 429 } else { |
| 461 data[kType] = kDoesNotExist; | 430 data[kType] = kDoesNotExist; |
| 462 } | 431 } |
| 463 } | 432 } |
| 464 | 433 |
| 465 | |
| 466 time_t File::LastModified(const char* name) { | 434 time_t File::LastModified(const char* name) { |
| 467 struct stat st; | 435 struct stat st; |
| 468 if (!StatHelper(name, &st)) { | 436 if (!StatHelper(name, &st)) { |
| 469 return -1; | 437 return -1; |
| 470 } | 438 } |
| 471 return st.st_mtime; | 439 return st.st_mtime; |
| 472 } | 440 } |
| 473 | 441 |
| 474 | |
| 475 time_t File::LastAccessed(const char* name) { | 442 time_t File::LastAccessed(const char* name) { |
| 476 struct stat st; | 443 struct stat st; |
| 477 if (!StatHelper(name, &st)) { | 444 if (!StatHelper(name, &st)) { |
| 478 return -1; | 445 return -1; |
| 479 } | 446 } |
| 480 return st.st_atime; | 447 return st.st_atime; |
| 481 } | 448 } |
| 482 | 449 |
| 483 | |
| 484 bool File::SetLastAccessed(const char* name, int64_t millis) { | 450 bool File::SetLastAccessed(const char* name, int64_t millis) { |
| 485 // First get the current times. | 451 // First get the current times. |
| 486 struct stat st; | 452 struct stat st; |
| 487 if (!StatHelper(name, &st)) { | 453 if (!StatHelper(name, &st)) { |
| 488 return false; | 454 return false; |
| 489 } | 455 } |
| 490 | 456 |
| 491 // Set the new time: | 457 // Set the new time: |
| 492 struct utimbuf times; | 458 struct utimbuf times; |
| 493 times.actime = millis / kMillisecondsPerSecond; | 459 times.actime = millis / kMillisecondsPerSecond; |
| 494 times.modtime = st.st_mtime; | 460 times.modtime = st.st_mtime; |
| 495 return utime(name, ×) == 0; | 461 return utime(name, ×) == 0; |
| 496 } | 462 } |
| 497 | 463 |
| 498 | |
| 499 bool File::SetLastModified(const char* name, int64_t millis) { | 464 bool File::SetLastModified(const char* name, int64_t millis) { |
| 500 // First get the current times. | 465 // First get the current times. |
| 501 struct stat st; | 466 struct stat st; |
| 502 if (!StatHelper(name, &st)) { | 467 if (!StatHelper(name, &st)) { |
| 503 return false; | 468 return false; |
| 504 } | 469 } |
| 505 | 470 |
| 506 // Set the new time: | 471 // Set the new time: |
| 507 struct utimbuf times; | 472 struct utimbuf times; |
| 508 times.actime = st.st_atime; | 473 times.actime = st.st_atime; |
| 509 times.modtime = millis / kMillisecondsPerSecond; | 474 times.modtime = millis / kMillisecondsPerSecond; |
| 510 return utime(name, ×) == 0; | 475 return utime(name, ×) == 0; |
| 511 } | 476 } |
| 512 | 477 |
| 513 | |
| 514 const char* File::LinkTarget(const char* pathname) { | 478 const char* File::LinkTarget(const char* pathname) { |
| 515 struct stat link_stats; | 479 struct stat link_stats; |
| 516 if (lstat(pathname, &link_stats) != 0) { | 480 if (lstat(pathname, &link_stats) != 0) { |
| 517 return NULL; | 481 return NULL; |
| 518 } | 482 } |
| 519 if (!S_ISLNK(link_stats.st_mode)) { | 483 if (!S_ISLNK(link_stats.st_mode)) { |
| 520 errno = ENOENT; | 484 errno = ENOENT; |
| 521 return NULL; | 485 return NULL; |
| 522 } | 486 } |
| 523 size_t target_size = link_stats.st_size; | 487 size_t target_size = link_stats.st_size; |
| 524 char* target_name = DartUtils::ScopedCString(target_size + 1); | 488 char* target_name = DartUtils::ScopedCString(target_size + 1); |
| 525 ASSERT(target_name != NULL); | 489 ASSERT(target_name != NULL); |
| 526 size_t read_size = readlink(pathname, target_name, target_size + 1); | 490 size_t read_size = readlink(pathname, target_name, target_size + 1); |
| 527 if (read_size != target_size) { | 491 if (read_size != target_size) { |
| 528 return NULL; | 492 return NULL; |
| 529 } | 493 } |
| 530 target_name[target_size] = '\0'; | 494 target_name[target_size] = '\0'; |
| 531 return target_name; | 495 return target_name; |
| 532 } | 496 } |
| 533 | 497 |
| 534 | |
| 535 bool File::IsAbsolutePath(const char* pathname) { | 498 bool File::IsAbsolutePath(const char* pathname) { |
| 536 return ((pathname != NULL) && (pathname[0] == '/')); | 499 return ((pathname != NULL) && (pathname[0] == '/')); |
| 537 } | 500 } |
| 538 | 501 |
| 539 | |
| 540 const char* File::GetCanonicalPath(const char* pathname) { | 502 const char* File::GetCanonicalPath(const char* pathname) { |
| 541 char* abs_path = NULL; | 503 char* abs_path = NULL; |
| 542 if (pathname != NULL) { | 504 if (pathname != NULL) { |
| 543 char* resolved_path = DartUtils::ScopedCString(PATH_MAX + 1); | 505 char* resolved_path = DartUtils::ScopedCString(PATH_MAX + 1); |
| 544 ASSERT(resolved_path != NULL); | 506 ASSERT(resolved_path != NULL); |
| 545 do { | 507 do { |
| 546 abs_path = realpath(pathname, resolved_path); | 508 abs_path = realpath(pathname, resolved_path); |
| 547 } while ((abs_path == NULL) && (errno == EINTR)); | 509 } while ((abs_path == NULL) && (errno == EINTR)); |
| 548 ASSERT((abs_path == NULL) || IsAbsolutePath(abs_path)); | 510 ASSERT((abs_path == NULL) || IsAbsolutePath(abs_path)); |
| 549 ASSERT((abs_path == NULL) || (abs_path == resolved_path)); | 511 ASSERT((abs_path == NULL) || (abs_path == resolved_path)); |
| 550 } | 512 } |
| 551 return abs_path; | 513 return abs_path; |
| 552 } | 514 } |
| 553 | 515 |
| 554 | |
| 555 const char* File::PathSeparator() { | 516 const char* File::PathSeparator() { |
| 556 return "/"; | 517 return "/"; |
| 557 } | 518 } |
| 558 | 519 |
| 559 | |
| 560 const char* File::StringEscapedPathSeparator() { | 520 const char* File::StringEscapedPathSeparator() { |
| 561 return "/"; | 521 return "/"; |
| 562 } | 522 } |
| 563 | 523 |
| 564 | |
| 565 File::StdioHandleType File::GetStdioHandleType(int fd) { | 524 File::StdioHandleType File::GetStdioHandleType(int fd) { |
| 566 ASSERT((0 <= fd) && (fd <= 2)); | 525 ASSERT((0 <= fd) && (fd <= 2)); |
| 567 struct stat buf; | 526 struct stat buf; |
| 568 int result = fstat(fd, &buf); | 527 int result = fstat(fd, &buf); |
| 569 if (result == -1) { | 528 if (result == -1) { |
| 570 return kOther; | 529 return kOther; |
| 571 } | 530 } |
| 572 if (S_ISCHR(buf.st_mode)) { | 531 if (S_ISCHR(buf.st_mode)) { |
| 573 return kTerminal; | 532 return kTerminal; |
| 574 } | 533 } |
| 575 if (S_ISFIFO(buf.st_mode)) { | 534 if (S_ISFIFO(buf.st_mode)) { |
| 576 return kPipe; | 535 return kPipe; |
| 577 } | 536 } |
| 578 if (S_ISSOCK(buf.st_mode)) { | 537 if (S_ISSOCK(buf.st_mode)) { |
| 579 return kSocket; | 538 return kSocket; |
| 580 } | 539 } |
| 581 if (S_ISREG(buf.st_mode)) { | 540 if (S_ISREG(buf.st_mode)) { |
| 582 return kFile; | 541 return kFile; |
| 583 } | 542 } |
| 584 return kOther; | 543 return kOther; |
| 585 } | 544 } |
| 586 | 545 |
| 587 | |
| 588 File::Identical File::AreIdentical(const char* file_1, const char* file_2) { | 546 File::Identical File::AreIdentical(const char* file_1, const char* file_2) { |
| 589 struct stat file_1_info; | 547 struct stat file_1_info; |
| 590 struct stat file_2_info; | 548 struct stat file_2_info; |
| 591 if ((NO_RETRY_EXPECTED(lstat(file_1, &file_1_info)) == -1) || | 549 if ((NO_RETRY_EXPECTED(lstat(file_1, &file_1_info)) == -1) || |
| 592 (NO_RETRY_EXPECTED(lstat(file_2, &file_2_info)) == -1)) { | 550 (NO_RETRY_EXPECTED(lstat(file_2, &file_2_info)) == -1)) { |
| 593 return File::kError; | 551 return File::kError; |
| 594 } | 552 } |
| 595 return ((file_1_info.st_ino == file_2_info.st_ino) && | 553 return ((file_1_info.st_ino == file_2_info.st_ino) && |
| 596 (file_1_info.st_dev == file_2_info.st_dev)) | 554 (file_1_info.st_dev == file_2_info.st_dev)) |
| 597 ? File::kIdentical | 555 ? File::kIdentical |
| 598 : File::kDifferent; | 556 : File::kDifferent; |
| 599 } | 557 } |
| 600 | 558 |
| 601 } // namespace bin | 559 } // namespace bin |
| 602 } // namespace dart | 560 } // namespace dart |
| 603 | 561 |
| 604 #endif // defined(HOST_OS_ANDROID) | 562 #endif // defined(HOST_OS_ANDROID) |
| OLD | NEW |