|
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