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_MACOS) | 6 #if defined(HOST_OS_MACOS) |
7 | 7 |
8 #include "bin/file.h" | 8 #include "bin/file.h" |
9 | 9 |
10 #include <copyfile.h> // NOLINT | 10 #include <copyfile.h> // NOLINT |
11 #include <errno.h> // NOLINT | 11 #include <errno.h> // NOLINT |
12 #include <fcntl.h> // NOLINT | 12 #include <fcntl.h> // NOLINT |
13 #include <libgen.h> // NOLINT | 13 #include <libgen.h> // NOLINT |
14 #include <limits.h> // NOLINT | 14 #include <limits.h> // NOLINT |
15 #include <sys/mman.h> // NOLINT | 15 #include <sys/mman.h> // NOLINT |
16 #include <sys/stat.h> // NOLINT | 16 #include <sys/stat.h> // NOLINT |
17 #include <unistd.h> // NOLINT | 17 #include <unistd.h> // NOLINT |
18 #include <utime.h> // NOLINT | 18 #include <utime.h> // NOLINT |
19 | 19 |
20 #include "bin/builtin.h" | 20 #include "bin/builtin.h" |
21 #include "bin/fdutils.h" | 21 #include "bin/fdutils.h" |
22 #include "bin/log.h" | 22 #include "bin/log.h" |
23 | 23 #include "bin/namespace.h" |
24 #include "platform/signal_blocker.h" | 24 #include "platform/signal_blocker.h" |
25 #include "platform/utils.h" | 25 #include "platform/utils.h" |
26 | 26 |
27 namespace dart { | 27 namespace dart { |
28 namespace bin { | 28 namespace bin { |
29 | 29 |
30 class FileHandle { | 30 class FileHandle { |
31 public: | 31 public: |
32 explicit FileHandle(int fd) : fd_(fd) {} | 32 explicit FileHandle(int fd) : fd_(fd) {} |
33 ~FileHandle() {} | 33 ~FileHandle() {} |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 return st.st_size; | 191 return st.st_size; |
192 } | 192 } |
193 return -1; | 193 return -1; |
194 } | 194 } |
195 | 195 |
196 File* File::FileOpenW(const wchar_t* system_name, FileOpenMode mode) { | 196 File* File::FileOpenW(const wchar_t* system_name, FileOpenMode mode) { |
197 UNREACHABLE(); | 197 UNREACHABLE(); |
198 return NULL; | 198 return NULL; |
199 } | 199 } |
200 | 200 |
201 File* File::Open(const char* name, FileOpenMode mode) { | 201 File* File::Open(Namespace* namespc, const char* name, FileOpenMode mode) { |
202 // Report errors for non-regular files. | 202 // Report errors for non-regular files. |
203 struct stat st; | 203 struct stat st; |
204 if (NO_RETRY_EXPECTED(stat(name, &st)) == 0) { | 204 if (NO_RETRY_EXPECTED(stat(name, &st)) == 0) { |
205 // Only accept regular files, character devices, and pipes. | 205 // Only accept regular files, character devices, and pipes. |
206 if (!S_ISREG(st.st_mode) && !S_ISCHR(st.st_mode) && !S_ISFIFO(st.st_mode)) { | 206 if (!S_ISREG(st.st_mode) && !S_ISCHR(st.st_mode) && !S_ISFIFO(st.st_mode)) { |
207 errno = (S_ISDIR(st.st_mode)) ? EISDIR : ENOENT; | 207 errno = (S_ISDIR(st.st_mode)) ? EISDIR : ENOENT; |
208 return NULL; | 208 return NULL; |
209 } | 209 } |
210 } | 210 } |
211 int flags = O_RDONLY; | 211 int flags = O_RDONLY; |
(...skipping 20 matching lines...) Expand all Loading... |
232 return NULL; | 232 return NULL; |
233 } | 233 } |
234 } | 234 } |
235 return new File(new FileHandle(fd)); | 235 return new File(new FileHandle(fd)); |
236 } | 236 } |
237 | 237 |
238 File* File::OpenStdio(int fd) { | 238 File* File::OpenStdio(int fd) { |
239 return ((fd < 0) || (2 < fd)) ? NULL : new File(new FileHandle(fd)); | 239 return ((fd < 0) || (2 < fd)) ? NULL : new File(new FileHandle(fd)); |
240 } | 240 } |
241 | 241 |
242 bool File::Exists(const char* name) { | 242 bool File::Exists(Namespace* namespc, const char* name) { |
243 struct stat st; | 243 struct stat st; |
244 if (NO_RETRY_EXPECTED(stat(name, &st)) == 0) { | 244 if (NO_RETRY_EXPECTED(stat(name, &st)) == 0) { |
245 // Everything but a directory and a link is a file to Dart. | 245 // Everything but a directory and a link is a file to Dart. |
246 return !S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode); | 246 return !S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode); |
247 } else { | 247 } else { |
248 return false; | 248 return false; |
249 } | 249 } |
250 } | 250 } |
251 | 251 |
252 bool File::Create(const char* name) { | 252 bool File::Create(Namespace* namespc, const char* name) { |
253 int fd = TEMP_FAILURE_RETRY(open(name, O_RDONLY | O_CREAT, 0666)); | 253 int fd = TEMP_FAILURE_RETRY(open(name, O_RDONLY | O_CREAT, 0666)); |
254 if (fd < 0) { | 254 if (fd < 0) { |
255 return false; | 255 return false; |
256 } | 256 } |
257 // File.create returns a File, so we shouldn't be giving the illusion that the | 257 // File.create returns a File, so we shouldn't be giving the illusion that the |
258 // call has created a file or that a file already exists if there is already | 258 // call has created a file or that a file already exists if there is already |
259 // an entity at the same path that is a directory or a link. | 259 // an entity at the same path that is a directory or a link. |
260 bool is_file = true; | 260 bool is_file = true; |
261 struct stat st; | 261 struct stat st; |
262 if (NO_RETRY_EXPECTED(fstat(fd, &st)) == 0) { | 262 if (NO_RETRY_EXPECTED(fstat(fd, &st)) == 0) { |
263 if (S_ISDIR(st.st_mode)) { | 263 if (S_ISDIR(st.st_mode)) { |
264 errno = EISDIR; | 264 errno = EISDIR; |
265 is_file = false; | 265 is_file = false; |
266 } else if (S_ISLNK(st.st_mode)) { | 266 } else if (S_ISLNK(st.st_mode)) { |
267 errno = ENOENT; | 267 errno = ENOENT; |
268 is_file = false; | 268 is_file = false; |
269 } | 269 } |
270 } | 270 } |
271 FDUtils::SaveErrorAndClose(fd); | 271 FDUtils::SaveErrorAndClose(fd); |
272 return is_file; | 272 return is_file; |
273 } | 273 } |
274 | 274 |
275 bool File::CreateLink(const char* name, const char* target) { | 275 bool File::CreateLink(Namespace* namespc, const char* name, const char* target)
{ |
276 int status = NO_RETRY_EXPECTED(symlink(target, name)); | 276 int status = NO_RETRY_EXPECTED(symlink(target, name)); |
277 return (status == 0); | 277 return (status == 0); |
278 } | 278 } |
279 | 279 |
280 File::Type File::GetType(const char* pathname, bool follow_links) { | 280 File::Type File::GetType(Namespace* namespc, const char* pathname, bool follow_l
inks) { |
281 struct stat entry_info; | 281 struct stat entry_info; |
282 int stat_success; | 282 int stat_success; |
283 if (follow_links) { | 283 if (follow_links) { |
284 stat_success = NO_RETRY_EXPECTED(stat(pathname, &entry_info)); | 284 stat_success = NO_RETRY_EXPECTED(stat(pathname, &entry_info)); |
285 } else { | 285 } else { |
286 stat_success = NO_RETRY_EXPECTED(lstat(pathname, &entry_info)); | 286 stat_success = NO_RETRY_EXPECTED(lstat(pathname, &entry_info)); |
287 } | 287 } |
288 if (stat_success == -1) { | 288 if (stat_success == -1) { |
289 return File::kDoesNotExist; | 289 return File::kDoesNotExist; |
290 } | 290 } |
291 if (S_ISDIR(entry_info.st_mode)) { | 291 if (S_ISDIR(entry_info.st_mode)) { |
292 return File::kIsDirectory; | 292 return File::kIsDirectory; |
293 } | 293 } |
294 if (S_ISREG(entry_info.st_mode)) { | 294 if (S_ISREG(entry_info.st_mode)) { |
295 return File::kIsFile; | 295 return File::kIsFile; |
296 } | 296 } |
297 if (S_ISLNK(entry_info.st_mode)) { | 297 if (S_ISLNK(entry_info.st_mode)) { |
298 return File::kIsLink; | 298 return File::kIsLink; |
299 } | 299 } |
300 return File::kDoesNotExist; | 300 return File::kDoesNotExist; |
301 } | 301 } |
302 | 302 |
303 static bool CheckTypeAndSetErrno(const char* name, | 303 static bool CheckTypeAndSetErrno(Namespace* namespc, |
| 304 const char* name, |
304 File::Type expected, | 305 File::Type expected, |
305 bool follow_links) { | 306 bool follow_links) { |
306 File::Type actual = File::GetType(name, follow_links); | 307 File::Type actual = File::GetType(namespc, name, follow_links); |
307 if (actual == expected) { | 308 if (actual == expected) { |
308 return true; | 309 return true; |
309 } | 310 } |
310 switch (actual) { | 311 switch (actual) { |
311 case File::kIsDirectory: | 312 case File::kIsDirectory: |
312 errno = EISDIR; | 313 errno = EISDIR; |
313 break; | 314 break; |
314 case File::kDoesNotExist: | 315 case File::kDoesNotExist: |
315 errno = ENOENT; | 316 errno = ENOENT; |
316 break; | 317 break; |
317 default: | 318 default: |
318 errno = EINVAL; | 319 errno = EINVAL; |
319 break; | 320 break; |
320 } | 321 } |
321 return false; | 322 return false; |
322 } | 323 } |
323 | 324 |
324 bool File::Delete(const char* name) { | 325 bool File::Delete(Namespace* namespc, const char* name) { |
325 return CheckTypeAndSetErrno(name, kIsFile, true) && | 326 return CheckTypeAndSetErrno(namespc, name, kIsFile, true) && |
326 (NO_RETRY_EXPECTED(unlink(name)) == 0); | 327 (NO_RETRY_EXPECTED(unlink(name)) == 0); |
327 } | 328 } |
328 | 329 |
329 bool File::DeleteLink(const char* name) { | 330 bool File::DeleteLink(Namespace* namespc, const char* name) { |
330 return CheckTypeAndSetErrno(name, kIsLink, false) && | 331 return CheckTypeAndSetErrno(namespc, name, kIsLink, false) && |
331 (NO_RETRY_EXPECTED(unlink(name)) == 0); | 332 (NO_RETRY_EXPECTED(unlink(name)) == 0); |
332 } | 333 } |
333 | 334 |
334 bool File::Rename(const char* old_path, const char* new_path) { | 335 bool File::Rename(Namespace* namespc, const char* old_path, const char* new_path
) { |
335 return CheckTypeAndSetErrno(old_path, kIsFile, true) && | 336 return CheckTypeAndSetErrno(namespc, old_path, kIsFile, true) && |
336 (NO_RETRY_EXPECTED(rename(old_path, new_path)) == 0); | 337 (NO_RETRY_EXPECTED(rename(old_path, new_path)) == 0); |
337 } | 338 } |
338 | 339 |
339 bool File::RenameLink(const char* old_path, const char* new_path) { | 340 bool File::RenameLink(Namespace* namespc, const char* old_path, const char* new_
path) { |
340 return CheckTypeAndSetErrno(old_path, kIsLink, false) && | 341 return CheckTypeAndSetErrno(namespc, old_path, kIsLink, false) && |
341 (NO_RETRY_EXPECTED(rename(old_path, new_path)) == 0); | 342 (NO_RETRY_EXPECTED(rename(old_path, new_path)) == 0); |
342 } | 343 } |
343 | 344 |
344 bool File::Copy(const char* old_path, const char* new_path) { | 345 bool File::Copy(Namespace* namespc, const char* old_path, const char* new_path)
{ |
345 return CheckTypeAndSetErrno(old_path, kIsFile, true) && | 346 return CheckTypeAndSetErrno(namespc, old_path, kIsFile, true) && |
346 (copyfile(old_path, new_path, NULL, COPYFILE_ALL) == 0); | 347 (copyfile(old_path, new_path, NULL, COPYFILE_ALL) == 0); |
347 } | 348 } |
348 | 349 |
349 static bool StatHelper(const char* name, struct stat* st) { | 350 static bool StatHelper(Namespace* namespc, const char* name, struct stat* st) { |
350 if (NO_RETRY_EXPECTED(stat(name, st)) != 0) { | 351 if (NO_RETRY_EXPECTED(stat(name, st)) != 0) { |
351 return false; | 352 return false; |
352 } | 353 } |
353 // Signal an error if it's a directory. | 354 // Signal an error if it's a directory. |
354 if (S_ISDIR(st->st_mode)) { | 355 if (S_ISDIR(st->st_mode)) { |
355 errno = EISDIR; | 356 errno = EISDIR; |
356 return false; | 357 return false; |
357 } | 358 } |
358 // Otherwise assume the caller knows what it's doing. | 359 // Otherwise assume the caller knows what it's doing. |
359 return true; | 360 return true; |
360 } | 361 } |
361 | 362 |
362 int64_t File::LengthFromPath(const char* name) { | 363 int64_t File::LengthFromPath(Namespace* namespc, const char* name) { |
363 struct stat st; | 364 struct stat st; |
364 if (!StatHelper(name, &st)) { | 365 if (!StatHelper(namespc, name, &st)) { |
365 return -1; | 366 return -1; |
366 } | 367 } |
367 return st.st_size; | 368 return st.st_size; |
368 } | 369 } |
369 | 370 |
370 static int64_t TimespecToMilliseconds(const struct timespec& t) { | 371 static int64_t TimespecToMilliseconds(const struct timespec& t) { |
371 return static_cast<int64_t>(t.tv_sec) * 1000L + | 372 return static_cast<int64_t>(t.tv_sec) * 1000L + |
372 static_cast<int64_t>(t.tv_nsec) / 1000000L; | 373 static_cast<int64_t>(t.tv_nsec) / 1000000L; |
373 } | 374 } |
374 | 375 |
375 void File::Stat(const char* name, int64_t* data) { | 376 void File::Stat(Namespace* namespc, const char* name, int64_t* data) { |
376 struct stat st; | 377 struct stat st; |
377 if (NO_RETRY_EXPECTED(stat(name, &st)) == 0) { | 378 if (NO_RETRY_EXPECTED(stat(name, &st)) == 0) { |
378 if (S_ISREG(st.st_mode)) { | 379 if (S_ISREG(st.st_mode)) { |
379 data[kType] = kIsFile; | 380 data[kType] = kIsFile; |
380 } else if (S_ISDIR(st.st_mode)) { | 381 } else if (S_ISDIR(st.st_mode)) { |
381 data[kType] = kIsDirectory; | 382 data[kType] = kIsDirectory; |
382 } else if (S_ISLNK(st.st_mode)) { | 383 } else if (S_ISLNK(st.st_mode)) { |
383 data[kType] = kIsLink; | 384 data[kType] = kIsLink; |
384 } else { | 385 } else { |
385 data[kType] = kDoesNotExist; | 386 data[kType] = kDoesNotExist; |
386 } | 387 } |
387 data[kCreatedTime] = st.st_ctime; | 388 data[kCreatedTime] = st.st_ctime; |
388 data[kModifiedTime] = st.st_mtime; | 389 data[kModifiedTime] = st.st_mtime; |
389 data[kAccessedTime] = st.st_atime; | 390 data[kAccessedTime] = st.st_atime; |
390 data[kCreatedTime] = TimespecToMilliseconds(st.st_ctimespec); | 391 data[kCreatedTime] = TimespecToMilliseconds(st.st_ctimespec); |
391 data[kModifiedTime] = TimespecToMilliseconds(st.st_mtimespec); | 392 data[kModifiedTime] = TimespecToMilliseconds(st.st_mtimespec); |
392 data[kAccessedTime] = TimespecToMilliseconds(st.st_atimespec); | 393 data[kAccessedTime] = TimespecToMilliseconds(st.st_atimespec); |
393 data[kMode] = st.st_mode; | 394 data[kMode] = st.st_mode; |
394 data[kSize] = st.st_size; | 395 data[kSize] = st.st_size; |
395 } else { | 396 } else { |
396 data[kType] = kDoesNotExist; | 397 data[kType] = kDoesNotExist; |
397 } | 398 } |
398 } | 399 } |
399 | 400 |
400 time_t File::LastModified(const char* name) { | 401 time_t File::LastModified(Namespace* namespc, const char* name) { |
401 struct stat st; | 402 struct stat st; |
402 if (!StatHelper(name, &st)) { | 403 if (!StatHelper(namespc, name, &st)) { |
403 return -1; | 404 return -1; |
404 } | 405 } |
405 return st.st_mtime; | 406 return st.st_mtime; |
406 } | 407 } |
407 | 408 |
408 time_t File::LastAccessed(const char* name) { | 409 time_t File::LastAccessed(Namespace* namespc, const char* name) { |
409 struct stat st; | 410 struct stat st; |
410 if (!StatHelper(name, &st)) { | 411 if (!StatHelper(namespc, name, &st)) { |
411 return -1; | 412 return -1; |
412 } | 413 } |
413 return st.st_atime; | 414 return st.st_atime; |
414 } | 415 } |
415 | 416 |
416 bool File::SetLastAccessed(const char* name, int64_t millis) { | 417 bool File::SetLastAccessed(Namespace* namespc, const char* name, int64_t millis)
{ |
417 // First get the current times. | 418 // First get the current times. |
418 struct stat st; | 419 struct stat st; |
419 if (!StatHelper(name, &st)) { | 420 if (!StatHelper(namespc, name, &st)) { |
420 return false; | 421 return false; |
421 } | 422 } |
422 | 423 |
423 // Set the new time: | 424 // Set the new time: |
424 struct utimbuf times; | 425 struct utimbuf times; |
425 times.actime = millis / kMillisecondsPerSecond; | 426 times.actime = millis / kMillisecondsPerSecond; |
426 times.modtime = st.st_mtime; | 427 times.modtime = st.st_mtime; |
427 return utime(name, ×) == 0; | 428 return utime(name, ×) == 0; |
428 } | 429 } |
429 | 430 |
430 bool File::SetLastModified(const char* name, int64_t millis) { | 431 bool File::SetLastModified(Namespace* namespc, const char* name, int64_t millis)
{ |
431 // First get the current times. | 432 // First get the current times. |
432 struct stat st; | 433 struct stat st; |
433 if (!StatHelper(name, &st)) { | 434 if (!StatHelper(namespc, name, &st)) { |
434 return false; | 435 return false; |
435 } | 436 } |
436 | 437 |
437 // Set the new time: | 438 // Set the new time: |
438 struct utimbuf times; | 439 struct utimbuf times; |
439 times.actime = st.st_atime; | 440 times.actime = st.st_atime; |
440 times.modtime = millis / kMillisecondsPerSecond; | 441 times.modtime = millis / kMillisecondsPerSecond; |
441 return utime(name, ×) == 0; | 442 return utime(name, ×) == 0; |
442 } | 443 } |
443 | 444 |
444 const char* File::LinkTarget(const char* pathname) { | 445 const char* File::LinkTarget(Namespace* namespc, const char* pathname) { |
445 struct stat link_stats; | 446 struct stat link_stats; |
446 if (lstat(pathname, &link_stats) != 0) { | 447 if (lstat(pathname, &link_stats) != 0) { |
447 return NULL; | 448 return NULL; |
448 } | 449 } |
449 if (!S_ISLNK(link_stats.st_mode)) { | 450 if (!S_ISLNK(link_stats.st_mode)) { |
450 errno = ENOENT; | 451 errno = ENOENT; |
451 return NULL; | 452 return NULL; |
452 } | 453 } |
453 // Don't rely on the link_stats.st_size for the size of the link | 454 // Don't rely on the link_stats.st_size for the size of the link |
454 // target. The link might have changed before the readlink call. | 455 // target. The link might have changed before the readlink call. |
455 const int kBufferSize = 1024; | 456 const int kBufferSize = 1024; |
456 char target[kBufferSize]; | 457 char target[kBufferSize]; |
457 size_t target_size = | 458 size_t target_size = |
458 TEMP_FAILURE_RETRY(readlink(pathname, target, kBufferSize)); | 459 TEMP_FAILURE_RETRY(readlink(pathname, target, kBufferSize)); |
459 if (target_size <= 0) { | 460 if (target_size <= 0) { |
460 return NULL; | 461 return NULL; |
461 } | 462 } |
462 char* target_name = DartUtils::ScopedCString(target_size + 1); | 463 char* target_name = DartUtils::ScopedCString(target_size + 1); |
463 ASSERT(target_name != NULL); | 464 ASSERT(target_name != NULL); |
464 memmove(target_name, target, target_size); | 465 memmove(target_name, target, target_size); |
465 target_name[target_size] = '\0'; | 466 target_name[target_size] = '\0'; |
466 return target_name; | 467 return target_name; |
467 } | 468 } |
468 | 469 |
469 bool File::IsAbsolutePath(const char* pathname) { | 470 bool File::IsAbsolutePath(const char* pathname) { |
470 return (pathname != NULL && pathname[0] == '/'); | 471 return (pathname != NULL && pathname[0] == '/'); |
471 } | 472 } |
472 | 473 |
473 const char* File::GetCanonicalPath(const char* pathname) { | 474 const char* File::GetCanonicalPath(Namespace* namespc, const char* pathname) { |
474 char* abs_path = NULL; | 475 char* abs_path = NULL; |
475 if (pathname != NULL) { | 476 if (pathname != NULL) { |
476 // On some older MacOs versions the default behaviour of realpath allocating | 477 // On some older MacOs versions the default behaviour of realpath allocating |
477 // space for the resolved_path when a NULL is passed in does not seem to | 478 // space for the resolved_path when a NULL is passed in does not seem to |
478 // work, so we explicitly allocate space. | 479 // work, so we explicitly allocate space. |
479 char* resolved_path = DartUtils::ScopedCString(PATH_MAX + 1); | 480 char* resolved_path = DartUtils::ScopedCString(PATH_MAX + 1); |
480 ASSERT(resolved_path != NULL); | 481 ASSERT(resolved_path != NULL); |
481 do { | 482 do { |
482 abs_path = realpath(pathname, resolved_path); | 483 abs_path = realpath(pathname, resolved_path); |
483 } while ((abs_path == NULL) && (errno == EINTR)); | 484 } while ((abs_path == NULL) && (errno == EINTR)); |
(...skipping 26 matching lines...) Expand all Loading... |
510 } | 511 } |
511 if (S_ISSOCK(buf.st_mode)) { | 512 if (S_ISSOCK(buf.st_mode)) { |
512 return kSocket; | 513 return kSocket; |
513 } | 514 } |
514 if (S_ISREG(buf.st_mode)) { | 515 if (S_ISREG(buf.st_mode)) { |
515 return kFile; | 516 return kFile; |
516 } | 517 } |
517 return kOther; | 518 return kOther; |
518 } | 519 } |
519 | 520 |
520 File::Identical File::AreIdentical(const char* file_1, const char* file_2) { | 521 File::Identical File::AreIdentical(Namespace* namespc, const char* file_1, const
char* file_2) { |
521 struct stat file_1_info; | 522 struct stat file_1_info; |
522 struct stat file_2_info; | 523 struct stat file_2_info; |
523 if ((NO_RETRY_EXPECTED(lstat(file_1, &file_1_info)) == -1) || | 524 if ((NO_RETRY_EXPECTED(lstat(file_1, &file_1_info)) == -1) || |
524 (NO_RETRY_EXPECTED(lstat(file_2, &file_2_info)) == -1)) { | 525 (NO_RETRY_EXPECTED(lstat(file_2, &file_2_info)) == -1)) { |
525 return File::kError; | 526 return File::kError; |
526 } | 527 } |
527 return ((file_1_info.st_ino == file_2_info.st_ino) && | 528 return ((file_1_info.st_ino == file_2_info.st_ino) && |
528 (file_1_info.st_dev == file_2_info.st_dev)) | 529 (file_1_info.st_dev == file_2_info.st_dev)) |
529 ? File::kIdentical | 530 ? File::kIdentical |
530 : File::kDifferent; | 531 : File::kDifferent; |
531 } | 532 } |
532 | 533 |
533 } // namespace bin | 534 } // namespace bin |
534 } // namespace dart | 535 } // namespace dart |
535 | 536 |
536 #endif // defined(HOST_OS_MACOS) | 537 #endif // defined(HOST_OS_MACOS) |
OLD | NEW |