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 |