|
32 | 32 | import static com.oracle.graal.python.runtime.exception.PythonErrorType.TypeError; |
33 | 33 | import static com.oracle.graal.python.runtime.exception.PythonErrorType.ValueError; |
34 | 34 |
|
| 35 | +import static com.oracle.truffle.api.TruffleFile.CREATION_TIME; |
| 36 | +import static com.oracle.truffle.api.TruffleFile.IS_DIRECTORY; |
| 37 | +import static com.oracle.truffle.api.TruffleFile.IS_REGULAR_FILE; |
| 38 | +import static com.oracle.truffle.api.TruffleFile.IS_SYMBOLIC_LINK; |
| 39 | +import static com.oracle.truffle.api.TruffleFile.LAST_ACCESS_TIME; |
| 40 | +import static com.oracle.truffle.api.TruffleFile.LAST_MODIFIED_TIME; |
| 41 | +import static com.oracle.truffle.api.TruffleFile.SIZE; |
| 42 | +import static com.oracle.truffle.api.TruffleFile.UNIX_CTIME; |
| 43 | +import static com.oracle.truffle.api.TruffleFile.UNIX_DEV; |
| 44 | +import static com.oracle.truffle.api.TruffleFile.UNIX_INODE; |
| 45 | +import static com.oracle.truffle.api.TruffleFile.UNIX_GID; |
| 46 | +import static com.oracle.truffle.api.TruffleFile.UNIX_GROUP; |
| 47 | +import static com.oracle.truffle.api.TruffleFile.UNIX_MODE; |
| 48 | +import static com.oracle.truffle.api.TruffleFile.UNIX_NLINK; |
| 49 | +import static com.oracle.truffle.api.TruffleFile.UNIX_OWNER; |
| 50 | +import static com.oracle.truffle.api.TruffleFile.UNIX_PERMISSIONS; |
| 51 | +import static com.oracle.truffle.api.TruffleFile.UNIX_UID; |
| 52 | + |
35 | 53 | import java.io.IOException; |
36 | 54 | import java.io.InputStream; |
37 | 55 | import java.io.OutputStream; |
@@ -445,108 +463,189 @@ long fileTimeToSeconds(FileTime t) { |
445 | 463 | return t.to(TimeUnit.SECONDS); |
446 | 464 | } |
447 | 465 |
|
| 466 | + @TruffleBoundary |
448 | 467 | Object stat(String path, boolean followSymlinks) { |
449 | 468 | TruffleFile f = getContext().getEnv().getTruffleFile(path); |
450 | 469 | LinkOption[] linkOptions = followSymlinks ? new LinkOption[0] : new LinkOption[]{LinkOption.NOFOLLOW_LINKS}; |
451 | 470 | try { |
452 | | - if (!f.exists(linkOptions)) { |
453 | | - throw fileNoFound(path); |
| 471 | + return unixStat(f, linkOptions); |
| 472 | + } catch (UnsupportedOperationException unsupported) { |
| 473 | + try { |
| 474 | + return posixStat(f, linkOptions); |
| 475 | + } catch (UnsupportedOperationException unsupported2) { |
| 476 | + return basicStat(f, linkOptions); |
454 | 477 | } |
455 | | - } catch (SecurityException e) { |
456 | | - throw fileNoFound(path); |
457 | | - } |
458 | | - int mode = 0; |
459 | | - long size = 0; |
460 | | - long ctime = 0; |
461 | | - long atime = 0; |
462 | | - long mtime = 0; |
463 | | - long gid = 0; |
464 | | - long uid = 0; |
465 | | - if (f.isRegularFile(linkOptions)) { |
466 | | - mode |= S_IFREG; |
467 | | - } else if (f.isDirectory(linkOptions)) { |
468 | | - mode |= S_IFDIR; |
469 | | - } else if (f.isSymbolicLink()) { |
470 | | - mode |= S_IFLNK; |
471 | | - } else { |
472 | | - // TODO: differentiate these |
473 | | - mode |= S_IFSOCK | S_IFBLK | S_IFCHR | S_IFIFO; |
474 | | - } |
475 | | - try { |
476 | | - mtime = fileTimeToSeconds(f.getLastModifiedTime(linkOptions)); |
477 | | - } catch (IOException e1) { |
478 | | - mtime = 0; |
479 | | - } |
480 | | - try { |
481 | | - ctime = fileTimeToSeconds(f.getCreationTime(linkOptions)); |
482 | | - } catch (IOException e1) { |
483 | | - ctime = 0; |
484 | 478 | } |
| 479 | + } |
| 480 | + |
| 481 | + private PTuple unixStat(TruffleFile file, LinkOption... linkOptions) { |
485 | 482 | try { |
486 | | - atime = fileTimeToSeconds(f.getLastAccessTime(linkOptions)); |
487 | | - } catch (IOException e1) { |
488 | | - atime = 0; |
| 483 | + TruffleFile.Attributes attributes = file.getAttributes(Arrays.asList( |
| 484 | + UNIX_MODE, |
| 485 | + UNIX_INODE, |
| 486 | + UNIX_DEV, |
| 487 | + UNIX_NLINK, |
| 488 | + UNIX_UID, |
| 489 | + UNIX_GID, |
| 490 | + SIZE, |
| 491 | + LAST_ACCESS_TIME, |
| 492 | + LAST_MODIFIED_TIME, |
| 493 | + UNIX_CTIME), linkOptions); |
| 494 | + return factory().createTuple(new Object[]{ |
| 495 | + attributes.get(UNIX_MODE), |
| 496 | + attributes.get(UNIX_INODE), |
| 497 | + attributes.get(UNIX_DEV), |
| 498 | + attributes.get(UNIX_NLINK), |
| 499 | + attributes.get(UNIX_UID), |
| 500 | + attributes.get(UNIX_GID), |
| 501 | + attributes.get(SIZE), |
| 502 | + fileTimeToSeconds(attributes.get(LAST_ACCESS_TIME)), |
| 503 | + fileTimeToSeconds(attributes.get(LAST_MODIFIED_TIME)), |
| 504 | + fileTimeToSeconds(attributes.get(UNIX_CTIME)), |
| 505 | + }); |
| 506 | + } catch (IOException | SecurityException e) { |
| 507 | + throw fileNoFound(file.getPath()); |
489 | 508 | } |
490 | | - UserPrincipal owner; |
| 509 | + } |
| 510 | + |
| 511 | + private PTuple posixStat(TruffleFile file, LinkOption... linkOptions) { |
491 | 512 | try { |
492 | | - owner = f.getOwner(linkOptions); |
| 513 | + int mode = 0; |
| 514 | + long size = 0; |
| 515 | + long ctime = 0; |
| 516 | + long atime = 0; |
| 517 | + long mtime = 0; |
| 518 | + long gid = 0; |
| 519 | + long uid = 0; |
| 520 | + TruffleFile.Attributes attributes = file.getAttributes(Arrays.asList( |
| 521 | + IS_DIRECTORY, |
| 522 | + IS_SYMBOLIC_LINK, |
| 523 | + IS_REGULAR_FILE, |
| 524 | + LAST_MODIFIED_TIME, |
| 525 | + LAST_ACCESS_TIME, |
| 526 | + CREATION_TIME, |
| 527 | + SIZE, |
| 528 | + UNIX_OWNER, |
| 529 | + UNIX_GROUP, |
| 530 | + UNIX_PERMISSIONS), linkOptions); |
| 531 | + mode |= fileTypeBitsFromAttributes(attributes); |
| 532 | + mtime = fileTimeToSeconds(attributes.get(LAST_MODIFIED_TIME)); |
| 533 | + ctime = fileTimeToSeconds(attributes.get(CREATION_TIME)); |
| 534 | + atime = fileTimeToSeconds(attributes.get(LAST_ACCESS_TIME)); |
| 535 | + size = attributes.get(SIZE); |
| 536 | + UserPrincipal owner = attributes.get(UNIX_OWNER); |
493 | 537 | if (owner instanceof UnixNumericUserPrincipal) { |
494 | | - uid = strToLong(((UnixNumericUserPrincipal) owner).getName()); |
| 538 | + try { |
| 539 | + uid = strToLong(((UnixNumericUserPrincipal) owner).getName()); |
| 540 | + } catch (NumberFormatException e2) { |
| 541 | + } |
495 | 542 | } |
496 | | - } catch (NumberFormatException | IOException | UnsupportedOperationException | SecurityException e2) { |
497 | | - } |
498 | | - try { |
499 | | - GroupPrincipal group = f.getGroup(linkOptions); |
| 543 | + GroupPrincipal group = attributes.get(UNIX_GROUP); |
500 | 544 | if (group instanceof UnixNumericGroupPrincipal) { |
501 | | - gid = strToLong(((UnixNumericGroupPrincipal) group).getName()); |
| 545 | + try { |
| 546 | + gid = strToLong(((UnixNumericGroupPrincipal) group).getName()); |
| 547 | + } catch (NumberFormatException e2) { |
| 548 | + } |
502 | 549 | } |
503 | | - } catch (NumberFormatException | IOException | UnsupportedOperationException | SecurityException e2) { |
| 550 | + final Set<PosixFilePermission> posixFilePermissions = attributes.get(UNIX_PERMISSIONS); |
| 551 | + mode = posixPermissionsToMode(mode, posixFilePermissions); |
| 552 | + int inode = getInode(file); |
| 553 | + return factory().createTuple(new Object[]{ |
| 554 | + mode, |
| 555 | + inode, // ino |
| 556 | + 0, // dev |
| 557 | + 0, // nlink |
| 558 | + uid, |
| 559 | + gid, |
| 560 | + size, |
| 561 | + atime, |
| 562 | + mtime, |
| 563 | + ctime, |
| 564 | + }); |
| 565 | + } catch (IOException | SecurityException e) { |
| 566 | + throw fileNoFound(file.getPath()); |
504 | 567 | } |
| 568 | + } |
| 569 | + |
| 570 | + private PTuple basicStat(TruffleFile file, LinkOption... linkOptions) { |
505 | 571 | try { |
506 | | - final Set<PosixFilePermission> posixFilePermissions = f.getPosixPermissions(linkOptions); |
507 | | - mode = posixPermissionsToMode(mode, posixFilePermissions); |
508 | | - } catch (UnsupportedOperationException | IOException e1) { |
509 | | - if (f.isReadable()) { |
| 572 | + int mode = 0; |
| 573 | + long size = 0; |
| 574 | + long ctime = 0; |
| 575 | + long atime = 0; |
| 576 | + long mtime = 0; |
| 577 | + long gid = 0; |
| 578 | + long uid = 0; |
| 579 | + TruffleFile.Attributes attributes = file.getAttributes(Arrays.asList( |
| 580 | + IS_DIRECTORY, |
| 581 | + IS_SYMBOLIC_LINK, |
| 582 | + IS_REGULAR_FILE, |
| 583 | + LAST_MODIFIED_TIME, |
| 584 | + LAST_ACCESS_TIME, |
| 585 | + CREATION_TIME, |
| 586 | + SIZE), linkOptions); |
| 587 | + mode |= fileTypeBitsFromAttributes(attributes); |
| 588 | + mtime = fileTimeToSeconds(attributes.get(LAST_MODIFIED_TIME)); |
| 589 | + ctime = fileTimeToSeconds(attributes.get(CREATION_TIME)); |
| 590 | + atime = fileTimeToSeconds(attributes.get(LAST_ACCESS_TIME)); |
| 591 | + size = attributes.get(SIZE); |
| 592 | + if (file.isReadable()) { |
510 | 593 | mode |= 0004; |
511 | 594 | mode |= 0040; |
512 | 595 | mode |= 0400; |
513 | 596 | } |
514 | | - if (f.isWritable()) { |
| 597 | + if (file.isWritable()) { |
515 | 598 | mode |= 0002; |
516 | 599 | mode |= 0020; |
517 | 600 | mode |= 0200; |
518 | 601 | } |
519 | | - if (f.isExecutable()) { |
| 602 | + if (file.isExecutable()) { |
520 | 603 | mode |= 0001; |
521 | 604 | mode |= 0010; |
522 | 605 | mode |= 0100; |
523 | 606 | } |
| 607 | + int inode = getInode(file); |
| 608 | + return factory().createTuple(new Object[]{ |
| 609 | + mode, |
| 610 | + inode, // ino |
| 611 | + 0, // dev |
| 612 | + 0, // nlink |
| 613 | + uid, |
| 614 | + gid, |
| 615 | + size, |
| 616 | + atime, |
| 617 | + mtime, |
| 618 | + ctime, |
| 619 | + }); |
| 620 | + } catch (IOException | SecurityException e) { |
| 621 | + throw fileNoFound(file.getPath()); |
524 | 622 | } |
525 | | - try { |
526 | | - size = f.size(linkOptions); |
527 | | - } catch (IOException e) { |
528 | | - size = 0; |
| 623 | + } |
| 624 | + |
| 625 | + private static int fileTypeBitsFromAttributes(TruffleFile.Attributes attributes) { |
| 626 | + int mode = 0; |
| 627 | + if (attributes.get(IS_REGULAR_FILE)) { |
| 628 | + mode |= S_IFREG; |
| 629 | + } else if (attributes.get(IS_DIRECTORY)) { |
| 630 | + mode |= S_IFDIR; |
| 631 | + } else if (attributes.get(IS_SYMBOLIC_LINK)) { |
| 632 | + mode |= S_IFLNK; |
| 633 | + } else { |
| 634 | + // TODO: differentiate these |
| 635 | + mode |= S_IFSOCK | S_IFBLK | S_IFCHR | S_IFIFO; |
529 | 636 | } |
| 637 | + return mode; |
| 638 | + } |
| 639 | + |
| 640 | + private int getInode(TruffleFile file) { |
530 | 641 | TruffleFile canonical; |
531 | 642 | try { |
532 | | - canonical = f.getCanonicalFile(); |
| 643 | + canonical = file.getCanonicalFile(); |
533 | 644 | } catch (IOException | SecurityException e) { |
534 | 645 | // best effort |
535 | | - canonical = f.getAbsoluteFile(); |
| 646 | + canonical = file.getAbsoluteFile(); |
536 | 647 | } |
537 | | - int inode = getContext().getResources().getInodeId(canonical.getPath()); |
538 | | - return factory().createTuple(new Object[]{ |
539 | | - mode, |
540 | | - inode, // ino |
541 | | - 0, // dev |
542 | | - 0, // nlink |
543 | | - uid, |
544 | | - gid, |
545 | | - size, |
546 | | - atime, |
547 | | - mtime, |
548 | | - ctime, |
549 | | - }); |
| 648 | + return getContext().getResources().getInodeId(canonical.getPath()); |
550 | 649 | } |
551 | 650 |
|
552 | 651 | private PException fileNoFound(String path) { |
|
0 commit comments