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