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(TARGET_OS_ANDROID) | 6 #if defined(TARGET_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 |
11 #include <fcntl.h> // NOLINT | 11 #include <fcntl.h> // NOLINT |
12 #include <sys/stat.h> // NOLINT | 12 #include <sys/stat.h> // NOLINT |
13 #include <sys/types.h> // NOLINT | 13 #include <sys/types.h> // NOLINT |
14 #include <sys/sendfile.h> // NOLINT | 14 #include <sys/sendfile.h> // NOLINT |
15 #include <unistd.h> // NOLINT | 15 #include <unistd.h> // NOLINT |
16 #include <libgen.h> // NOLINT | 16 #include <libgen.h> // NOLINT |
17 | 17 |
18 #include "bin/builtin.h" | 18 #include "bin/builtin.h" |
19 #include "bin/log.h" | 19 #include "bin/log.h" |
20 #include "bin/signal_blocker.h" | 20 |
| 21 #include "platform/signal_blocker.h" |
21 | 22 |
22 | 23 |
23 namespace dart { | 24 namespace dart { |
24 namespace bin { | 25 namespace bin { |
25 | 26 |
26 class FileHandle { | 27 class FileHandle { |
27 public: | 28 public: |
28 explicit FileHandle(int fd) : fd_(fd) { } | 29 explicit FileHandle(int fd) : fd_(fd) { } |
29 ~FileHandle() { } | 30 ~FileHandle() { } |
30 int fd() const { return fd_; } | 31 int fd() const { return fd_; } |
(...skipping 14 matching lines...) Expand all Loading... |
45 | 46 |
46 void File::Close() { | 47 void File::Close() { |
47 ASSERT(handle_->fd() >= 0); | 48 ASSERT(handle_->fd() >= 0); |
48 if (handle_->fd() == STDOUT_FILENO) { | 49 if (handle_->fd() == STDOUT_FILENO) { |
49 // If stdout, redirect fd to /dev/null. | 50 // If stdout, redirect fd to /dev/null. |
50 int null_fd = TEMP_FAILURE_RETRY(open("/dev/null", O_WRONLY)); | 51 int null_fd = TEMP_FAILURE_RETRY(open("/dev/null", O_WRONLY)); |
51 ASSERT(null_fd >= 0); | 52 ASSERT(null_fd >= 0); |
52 VOID_TEMP_FAILURE_RETRY(dup2(null_fd, handle_->fd())); | 53 VOID_TEMP_FAILURE_RETRY(dup2(null_fd, handle_->fd())); |
53 VOID_TEMP_FAILURE_RETRY(close(null_fd)); | 54 VOID_TEMP_FAILURE_RETRY(close(null_fd)); |
54 } else { | 55 } else { |
55 int err = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(handle_->fd())); | 56 int err = TEMP_FAILURE_RETRY(close(handle_->fd())); |
56 if (err != 0) { | 57 if (err != 0) { |
57 const int kBufferSize = 1024; | 58 const int kBufferSize = 1024; |
58 char error_message[kBufferSize]; | 59 char error_message[kBufferSize]; |
59 strerror_r(errno, error_message, kBufferSize); | 60 strerror_r(errno, error_message, kBufferSize); |
60 Log::PrintErr("%s\n", error_message); | 61 Log::PrintErr("%s\n", error_message); |
61 } | 62 } |
62 } | 63 } |
63 handle_->set_fd(kClosedFd); | 64 handle_->set_fd(kClosedFd); |
64 } | 65 } |
65 | 66 |
66 | 67 |
67 bool File::IsClosed() { | 68 bool File::IsClosed() { |
68 return handle_->fd() == kClosedFd; | 69 return handle_->fd() == kClosedFd; |
69 } | 70 } |
70 | 71 |
71 | 72 |
72 int64_t File::Read(void* buffer, int64_t num_bytes) { | 73 int64_t File::Read(void* buffer, int64_t num_bytes) { |
73 ASSERT(handle_->fd() >= 0); | 74 ASSERT(handle_->fd() >= 0); |
74 return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(read(handle_->fd(), buffer, | 75 return TEMP_FAILURE_RETRY(read(handle_->fd(), buffer, num_bytes)); |
75 num_bytes)); | |
76 } | 76 } |
77 | 77 |
78 | 78 |
79 int64_t File::Write(const void* buffer, int64_t num_bytes) { | 79 int64_t File::Write(const void* buffer, int64_t num_bytes) { |
80 ASSERT(handle_->fd() >= 0); | 80 ASSERT(handle_->fd() >= 0); |
81 return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(write(handle_->fd(), buffer, | 81 return TEMP_FAILURE_RETRY(write(handle_->fd(), buffer, num_bytes)); |
82 num_bytes)); | |
83 } | 82 } |
84 | 83 |
85 | 84 |
86 int64_t File::Position() { | 85 int64_t File::Position() { |
87 ASSERT(handle_->fd() >= 0); | 86 ASSERT(handle_->fd() >= 0); |
88 return lseek64(handle_->fd(), 0, SEEK_CUR); | 87 return NO_RETRY_EXPECTED(lseek64(handle_->fd(), 0, SEEK_CUR)); |
89 } | 88 } |
90 | 89 |
91 | 90 |
92 bool File::SetPosition(int64_t position) { | 91 bool File::SetPosition(int64_t position) { |
93 ASSERT(handle_->fd() >= 0); | 92 ASSERT(handle_->fd() >= 0); |
94 return lseek64(handle_->fd(), position, SEEK_SET) >= 0; | 93 return NO_RETRY_EXPECTED(lseek64(handle_->fd(), position, SEEK_SET)) >= 0; |
95 } | 94 } |
96 | 95 |
97 | 96 |
98 bool File::Truncate(int64_t length) { | 97 bool File::Truncate(int64_t length) { |
99 ASSERT(handle_->fd() >= 0); | 98 ASSERT(handle_->fd() >= 0); |
100 return TEMP_FAILURE_RETRY_BLOCK_SIGNALS( | 99 return TEMP_FAILURE_RETRY(ftruncate(handle_->fd(), length) != -1); |
101 ftruncate(handle_->fd(), length) != -1); | |
102 } | 100 } |
103 | 101 |
104 | 102 |
105 bool File::Flush() { | 103 bool File::Flush() { |
106 ASSERT(handle_->fd() >= 0); | 104 ASSERT(handle_->fd() >= 0); |
107 return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(fsync(handle_->fd()) != -1); | 105 return NO_RETRY_EXPECTED(fsync(handle_->fd()) != -1); |
108 } | 106 } |
109 | 107 |
110 | 108 |
111 int64_t File::Length() { | 109 int64_t File::Length() { |
112 ASSERT(handle_->fd() >= 0); | 110 ASSERT(handle_->fd() >= 0); |
113 struct stat st; | 111 struct stat st; |
114 if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(fstat(handle_->fd(), &st)) == 0) { | 112 if (NO_RETRY_EXPECTED(fstat(handle_->fd(), &st)) == 0) { |
115 return st.st_size; | 113 return st.st_size; |
116 } | 114 } |
117 return -1; | 115 return -1; |
118 } | 116 } |
119 | 117 |
120 | 118 |
121 File* File::Open(const char* name, FileOpenMode mode) { | 119 File* File::Open(const char* name, FileOpenMode mode) { |
122 // Report errors for non-regular files. | 120 // Report errors for non-regular files. |
123 struct stat st; | 121 struct stat st; |
124 if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(stat(name, &st)) == 0) { | 122 if (NO_RETRY_EXPECTED(stat(name, &st)) == 0) { |
125 if (!S_ISREG(st.st_mode)) { | 123 if (!S_ISREG(st.st_mode)) { |
126 errno = (S_ISDIR(st.st_mode)) ? EISDIR : ENOENT; | 124 errno = (S_ISDIR(st.st_mode)) ? EISDIR : ENOENT; |
127 return NULL; | 125 return NULL; |
128 } | 126 } |
129 } | 127 } |
130 int flags = O_RDONLY; | 128 int flags = O_RDONLY; |
131 if ((mode & kWrite) != 0) { | 129 if ((mode & kWrite) != 0) { |
132 flags = (O_RDWR | O_CREAT); | 130 flags = (O_RDWR | O_CREAT); |
133 } | 131 } |
134 if ((mode & kTruncate) != 0) { | 132 if ((mode & kTruncate) != 0) { |
135 flags = flags | O_TRUNC; | 133 flags = flags | O_TRUNC; |
136 } | 134 } |
137 flags |= O_CLOEXEC; | 135 flags |= O_CLOEXEC; |
138 int fd = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(open(name, flags, 0666)); | 136 int fd = TEMP_FAILURE_RETRY(open(name, flags, 0666)); |
139 if (fd < 0) { | 137 if (fd < 0) { |
140 return NULL; | 138 return NULL; |
141 } | 139 } |
142 if (((mode & kWrite) != 0) && ((mode & kTruncate) == 0)) { | 140 if (((mode & kWrite) != 0) && ((mode & kTruncate) == 0)) { |
143 int64_t position = lseek64(fd, 0, SEEK_END); | 141 int64_t position = lseek64(fd, 0, SEEK_END); |
144 if (position < 0) { | 142 if (position < 0) { |
145 return NULL; | 143 return NULL; |
146 } | 144 } |
147 } | 145 } |
148 return new File(new FileHandle(fd)); | 146 return new File(new FileHandle(fd)); |
149 } | 147 } |
150 | 148 |
151 | 149 |
152 File* File::OpenStdio(int fd) { | 150 File* File::OpenStdio(int fd) { |
153 if (fd < 0 || 2 < fd) return NULL; | 151 if (fd < 0 || 2 < fd) return NULL; |
154 return new File(new FileHandle(fd)); | 152 return new File(new FileHandle(fd)); |
155 } | 153 } |
156 | 154 |
157 | 155 |
158 bool File::Exists(const char* name) { | 156 bool File::Exists(const char* name) { |
159 struct stat st; | 157 struct stat st; |
160 if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(stat(name, &st)) == 0) { | 158 if (NO_RETRY_EXPECTED(stat(name, &st)) == 0) { |
161 return S_ISREG(st.st_mode); | 159 return S_ISREG(st.st_mode); |
162 } else { | 160 } else { |
163 return false; | 161 return false; |
164 } | 162 } |
165 } | 163 } |
166 | 164 |
167 | 165 |
168 bool File::Create(const char* name) { | 166 bool File::Create(const char* name) { |
169 int fd = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(open(name, | 167 int fd = TEMP_FAILURE_RETRY(open(name, O_RDONLY | O_CREAT | O_CLOEXEC, 0666)); |
170 O_RDONLY | O_CREAT | O_CLOEXEC, | |
171 0666)); | |
172 if (fd < 0) { | 168 if (fd < 0) { |
173 return false; | 169 return false; |
174 } | 170 } |
175 return (close(fd) == 0); | 171 return (close(fd) == 0); |
176 } | 172 } |
177 | 173 |
178 | 174 |
179 bool File::CreateLink(const char* name, const char* target) { | 175 bool File::CreateLink(const char* name, const char* target) { |
180 int status = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(symlink(target, name)); | 176 int status = NO_RETRY_EXPECTED(symlink(target, name)); |
181 return (status == 0); | 177 return (status == 0); |
182 } | 178 } |
183 | 179 |
184 | 180 |
185 bool File::Delete(const char* name) { | 181 bool File::Delete(const char* name) { |
186 File::Type type = File::GetType(name, true); | 182 File::Type type = File::GetType(name, true); |
187 if (type == kIsFile) { | 183 if (type == kIsFile) { |
188 return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(unlink(name)) == 0; | 184 return NO_RETRY_EXPECTED(unlink(name)) == 0; |
189 } else if (type == kIsDirectory) { | 185 } else if (type == kIsDirectory) { |
190 errno = EISDIR; | 186 errno = EISDIR; |
191 } else { | 187 } else { |
192 errno = ENOENT; | 188 errno = ENOENT; |
193 } | 189 } |
194 return false; | 190 return false; |
195 } | 191 } |
196 | 192 |
197 | 193 |
198 bool File::DeleteLink(const char* name) { | 194 bool File::DeleteLink(const char* name) { |
199 File::Type type = File::GetType(name, false); | 195 File::Type type = File::GetType(name, false); |
200 if (type == kIsLink) { | 196 if (type == kIsLink) { |
201 return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(unlink(name)) == 0; | 197 return NO_RETRY_EXPECTED(unlink(name)) == 0; |
202 } | 198 } |
203 errno = EINVAL; | 199 errno = EINVAL; |
204 return false; | 200 return false; |
205 } | 201 } |
206 | 202 |
207 | 203 |
208 bool File::Rename(const char* old_path, const char* new_path) { | 204 bool File::Rename(const char* old_path, const char* new_path) { |
209 File::Type type = File::GetType(old_path, true); | 205 File::Type type = File::GetType(old_path, true); |
210 if (type == kIsFile) { | 206 if (type == kIsFile) { |
211 return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(rename(old_path, new_path)) == 0; | 207 return NO_RETRY_EXPECTED(rename(old_path, new_path)) == 0; |
212 } else if (type == kIsDirectory) { | 208 } else if (type == kIsDirectory) { |
213 errno = EISDIR; | 209 errno = EISDIR; |
214 } else { | 210 } else { |
215 errno = ENOENT; | 211 errno = ENOENT; |
216 } | 212 } |
217 return false; | 213 return false; |
218 } | 214 } |
219 | 215 |
220 | 216 |
221 bool File::RenameLink(const char* old_path, const char* new_path) { | 217 bool File::RenameLink(const char* old_path, const char* new_path) { |
222 File::Type type = File::GetType(old_path, false); | 218 File::Type type = File::GetType(old_path, false); |
223 if (type == kIsLink) { | 219 if (type == kIsLink) { |
224 return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(rename(old_path, new_path)) == 0; | 220 return NO_RETRY_EXPECTED(rename(old_path, new_path)) == 0; |
225 } else if (type == kIsDirectory) { | 221 } else if (type == kIsDirectory) { |
226 errno = EISDIR; | 222 errno = EISDIR; |
227 } else { | 223 } else { |
228 errno = EINVAL; | 224 errno = EINVAL; |
229 } | 225 } |
230 return false; | 226 return false; |
231 } | 227 } |
232 | 228 |
233 | 229 |
234 bool File::Copy(const char* old_path, const char* new_path) { | 230 bool File::Copy(const char* old_path, const char* new_path) { |
235 File::Type type = File::GetType(old_path, true); | 231 File::Type type = File::GetType(old_path, true); |
236 if (type == kIsFile) { | 232 if (type == kIsFile) { |
237 struct stat st; | 233 struct stat st; |
238 if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(stat(old_path, &st)) != 0) { | 234 if (NO_RETRY_EXPECTED(stat(old_path, &st)) != 0) { |
239 return false; | 235 return false; |
240 } | 236 } |
241 int old_fd = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(open(old_path, | 237 int old_fd = TEMP_FAILURE_RETRY(open(old_path, O_RDONLY | O_CLOEXEC)); |
242 O_RDONLY | O_CLOEXEC)); | |
243 if (old_fd < 0) { | 238 if (old_fd < 0) { |
244 return false; | 239 return false; |
245 } | 240 } |
246 int new_fd = TEMP_FAILURE_RETRY_BLOCK_SIGNALS( | 241 int new_fd = TEMP_FAILURE_RETRY( |
247 open(new_path, O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, st.st_mode)); | 242 open(new_path, O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, st.st_mode)); |
248 if (new_fd < 0) { | 243 if (new_fd < 0) { |
249 VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(old_fd)); | 244 VOID_TEMP_FAILURE_RETRY(close(old_fd)); |
250 return false; | 245 return false; |
251 } | 246 } |
252 off_t offset = 0; | 247 off_t offset = 0; |
253 int result = 1; | 248 int result = 1; |
254 while (result > 0) { | 249 while (result > 0) { |
255 // Loop to ensure we copy everything, and not only up to 2GB. | 250 // Loop to ensure we copy everything, and not only up to 2GB. |
256 result = TEMP_FAILURE_RETRY_BLOCK_SIGNALS( | 251 result = NO_RETRY_EXPECTED( |
257 sendfile(new_fd, old_fd, &offset, kMaxUint32)); | 252 sendfile(new_fd, old_fd, &offset, kMaxUint32)); |
258 } | 253 } |
259 // From sendfile man pages: | 254 // From sendfile man pages: |
260 // Applications may wish to fall back to read(2)/write(2) in the case | 255 // Applications may wish to fall back to read(2)/write(2) in the case |
261 // where sendfile() fails with EINVAL or ENOSYS. | 256 // where sendfile() fails with EINVAL or ENOSYS. |
262 if (result < 0 && (errno == EINVAL || errno == ENOSYS)) { | 257 if (result < 0 && (errno == EINVAL || errno == ENOSYS)) { |
263 const intptr_t kBufferSize = 8 * KB; | 258 const intptr_t kBufferSize = 8 * KB; |
264 uint8_t buffer[kBufferSize]; | 259 uint8_t buffer[kBufferSize]; |
265 while ((result = TEMP_FAILURE_RETRY_BLOCK_SIGNALS( | 260 while ((result = TEMP_FAILURE_RETRY( |
266 read(old_fd, buffer, kBufferSize))) > 0) { | 261 read(old_fd, buffer, kBufferSize))) > 0) { |
267 int wrote = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(write(new_fd, buffer, | 262 int wrote = TEMP_FAILURE_RETRY(write(new_fd, buffer, result)); |
268 result)); | |
269 if (wrote != result) { | 263 if (wrote != result) { |
270 result = -1; | 264 result = -1; |
271 break; | 265 break; |
272 } | 266 } |
273 } | 267 } |
274 } | 268 } |
275 if (result < 0) { | 269 if (result < 0) { |
276 int e = errno; | 270 int e = errno; |
277 VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(old_fd)); | 271 VOID_TEMP_FAILURE_RETRY(close(old_fd)); |
278 VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(new_fd)); | 272 VOID_TEMP_FAILURE_RETRY(close(new_fd)); |
279 VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(unlink(new_path)); | 273 VOID_NO_RETRY_EXPECTED(unlink(new_path)); |
280 errno = e; | 274 errno = e; |
281 return false; | 275 return false; |
282 } | 276 } |
283 return true; | 277 return true; |
284 } else if (type == kIsDirectory) { | 278 } else if (type == kIsDirectory) { |
285 errno = EISDIR; | 279 errno = EISDIR; |
286 } else { | 280 } else { |
287 errno = ENOENT; | 281 errno = ENOENT; |
288 } | 282 } |
289 return false; | 283 return false; |
290 } | 284 } |
291 | 285 |
292 | 286 |
293 int64_t File::LengthFromPath(const char* name) { | 287 int64_t File::LengthFromPath(const char* name) { |
294 struct stat st; | 288 struct stat st; |
295 if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(stat(name, &st)) == 0) { | 289 if (NO_RETRY_EXPECTED(stat(name, &st)) == 0) { |
296 return st.st_size; | 290 return st.st_size; |
297 } | 291 } |
298 return -1; | 292 return -1; |
299 } | 293 } |
300 | 294 |
301 | 295 |
302 void File::Stat(const char* name, int64_t* data) { | 296 void File::Stat(const char* name, int64_t* data) { |
303 struct stat st; | 297 struct stat st; |
304 if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(stat(name, &st)) == 0) { | 298 if (NO_RETRY_EXPECTED(stat(name, &st)) == 0) { |
305 if (S_ISREG(st.st_mode)) { | 299 if (S_ISREG(st.st_mode)) { |
306 data[kType] = kIsFile; | 300 data[kType] = kIsFile; |
307 } else if (S_ISDIR(st.st_mode)) { | 301 } else if (S_ISDIR(st.st_mode)) { |
308 data[kType] = kIsDirectory; | 302 data[kType] = kIsDirectory; |
309 } else if (S_ISLNK(st.st_mode)) { | 303 } else if (S_ISLNK(st.st_mode)) { |
310 data[kType] = kIsLink; | 304 data[kType] = kIsLink; |
311 } else { | 305 } else { |
312 data[kType] = kDoesNotExist; | 306 data[kType] = kDoesNotExist; |
313 } | 307 } |
314 data[kCreatedTime] = st.st_ctime; | 308 data[kCreatedTime] = st.st_ctime; |
315 data[kModifiedTime] = st.st_mtime; | 309 data[kModifiedTime] = st.st_mtime; |
316 data[kAccessedTime] = st.st_atime; | 310 data[kAccessedTime] = st.st_atime; |
317 data[kMode] = st.st_mode; | 311 data[kMode] = st.st_mode; |
318 data[kSize] = st.st_size; | 312 data[kSize] = st.st_size; |
319 } else { | 313 } else { |
320 data[kType] = kDoesNotExist; | 314 data[kType] = kDoesNotExist; |
321 } | 315 } |
322 } | 316 } |
323 | 317 |
324 | 318 |
325 time_t File::LastModified(const char* name) { | 319 time_t File::LastModified(const char* name) { |
326 struct stat st; | 320 struct stat st; |
327 if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(stat(name, &st)) == 0) { | 321 if (NO_RETRY_EXPECTED(stat(name, &st)) == 0) { |
328 return st.st_mtime; | 322 return st.st_mtime; |
329 } | 323 } |
330 return -1; | 324 return -1; |
331 } | 325 } |
332 | 326 |
333 | 327 |
334 char* File::LinkTarget(const char* pathname) { | 328 char* File::LinkTarget(const char* pathname) { |
335 struct stat link_stats; | 329 struct stat link_stats; |
336 if (lstat(pathname, &link_stats) != 0) return NULL; | 330 if (lstat(pathname, &link_stats) != 0) return NULL; |
337 if (!S_ISLNK(link_stats.st_mode)) { | 331 if (!S_ISLNK(link_stats.st_mode)) { |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
399 if (S_ISSOCK(buf.st_mode)) return kSocket; | 393 if (S_ISSOCK(buf.st_mode)) return kSocket; |
400 if (S_ISREG(buf.st_mode)) return kFile; | 394 if (S_ISREG(buf.st_mode)) return kFile; |
401 return kOther; | 395 return kOther; |
402 } | 396 } |
403 | 397 |
404 | 398 |
405 File::Type File::GetType(const char* pathname, bool follow_links) { | 399 File::Type File::GetType(const char* pathname, bool follow_links) { |
406 struct stat entry_info; | 400 struct stat entry_info; |
407 int stat_success; | 401 int stat_success; |
408 if (follow_links) { | 402 if (follow_links) { |
409 stat_success = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(stat(pathname, | 403 stat_success = NO_RETRY_EXPECTED(stat(pathname, &entry_info)); |
410 &entry_info)); | |
411 } else { | 404 } else { |
412 stat_success = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(lstat(pathname, | 405 stat_success = NO_RETRY_EXPECTED(lstat(pathname, &entry_info)); |
413 &entry_info)); | |
414 } | 406 } |
415 if (stat_success == -1) return File::kDoesNotExist; | 407 if (stat_success == -1) return File::kDoesNotExist; |
416 if (S_ISDIR(entry_info.st_mode)) return File::kIsDirectory; | 408 if (S_ISDIR(entry_info.st_mode)) return File::kIsDirectory; |
417 if (S_ISREG(entry_info.st_mode)) return File::kIsFile; | 409 if (S_ISREG(entry_info.st_mode)) return File::kIsFile; |
418 if (S_ISLNK(entry_info.st_mode)) return File::kIsLink; | 410 if (S_ISLNK(entry_info.st_mode)) return File::kIsLink; |
419 return File::kDoesNotExist; | 411 return File::kDoesNotExist; |
420 } | 412 } |
421 | 413 |
422 | 414 |
423 File::Identical File::AreIdentical(const char* file_1, const char* file_2) { | 415 File::Identical File::AreIdentical(const char* file_1, const char* file_2) { |
424 struct stat file_1_info; | 416 struct stat file_1_info; |
425 struct stat file_2_info; | 417 struct stat file_2_info; |
426 if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(lstat(file_1, &file_1_info)) == -1 || | 418 if (NO_RETRY_EXPECTED(lstat(file_1, &file_1_info)) == -1 || |
427 TEMP_FAILURE_RETRY_BLOCK_SIGNALS(lstat(file_2, &file_2_info)) == -1) { | 419 NO_RETRY_EXPECTED(lstat(file_2, &file_2_info)) == -1) { |
428 return File::kError; | 420 return File::kError; |
429 } | 421 } |
430 return (file_1_info.st_ino == file_2_info.st_ino && | 422 return (file_1_info.st_ino == file_2_info.st_ino && |
431 file_1_info.st_dev == file_2_info.st_dev) ? | 423 file_1_info.st_dev == file_2_info.st_dev) ? |
432 File::kIdentical : | 424 File::kIdentical : |
433 File::kDifferent; | 425 File::kDifferent; |
434 } | 426 } |
435 | 427 |
436 } // namespace bin | 428 } // namespace bin |
437 } // namespace dart | 429 } // namespace dart |
438 | 430 |
439 #endif // defined(TARGET_OS_ANDROID) | 431 #endif // defined(TARGET_OS_ANDROID) |
OLD | NEW |