| | 518 | |
|---|
| | 519 | /**********************************************************************/ |
|---|
| | 520 | /************************** proxy methods ****************************/ |
|---|
| | 521 | /**********************************************************************/ |
|---|
| | 522 | |
|---|
| | 523 | |
|---|
| | 524 | /*********************************************************************** |
|---|
| | 525 | |
|---|
| | 526 | Does this path currently exist? |
|---|
| | 527 | |
|---|
| | 528 | ***********************************************************************/ |
|---|
| | 529 | |
|---|
| | 530 | final bool exists () |
|---|
| | 531 | { |
|---|
| | 532 | try { |
|---|
| | 533 | fileSize(); |
|---|
| | 534 | return true; |
|---|
| | 535 | } catch (IOException){} |
|---|
| | 536 | return false; |
|---|
| | 537 | } |
|---|
| | 538 | |
|---|
| | 539 | /*********************************************************************** |
|---|
| | 540 | |
|---|
| | 541 | Returns the time of the last modification. Accurate |
|---|
| | 542 | to whatever the OS supports |
|---|
| | 543 | |
|---|
| | 544 | ***********************************************************************/ |
|---|
| | 545 | |
|---|
| | 546 | final Time modified () |
|---|
| | 547 | { |
|---|
| | 548 | return timeStamps.modified; |
|---|
| | 549 | } |
|---|
| | 550 | |
|---|
| | 551 | /*********************************************************************** |
|---|
| | 552 | |
|---|
| | 553 | Returns the time of the last access. Accurate to |
|---|
| | 554 | whatever the OS supports |
|---|
| | 555 | |
|---|
| | 556 | ***********************************************************************/ |
|---|
| | 557 | |
|---|
| | 558 | final Time accessed () |
|---|
| | 559 | { |
|---|
| | 560 | return timeStamps.accessed; |
|---|
| | 561 | } |
|---|
| | 562 | |
|---|
| | 563 | /*********************************************************************** |
|---|
| | 564 | |
|---|
| | 565 | Returns the time of file creation. Accurate to |
|---|
| | 566 | whatever the OS supports |
|---|
| | 567 | |
|---|
| | 568 | ***********************************************************************/ |
|---|
| | 569 | |
|---|
| | 570 | final Time created () |
|---|
| | 571 | { |
|---|
| | 572 | return timeStamps.created; |
|---|
| | 573 | } |
|---|
| | 574 | |
|---|
| | 575 | /*********************************************************************** |
|---|
| | 576 | |
|---|
| | 577 | Create an entire path consisting of this folder along with |
|---|
| | 578 | all parent folders. The path must not contain '.' or '..' |
|---|
| | 579 | segments. Related methods include PathUtil.normalize() and |
|---|
| | 580 | FileSystem.absolutePath() |
|---|
| | 581 | |
|---|
| | 582 | Returns: a chaining reference (this) |
|---|
| | 583 | |
|---|
| | 584 | Throws: IOException upon systen errors |
|---|
| | 585 | |
|---|
| | 586 | Throws: IllegalArgumentException if the path contains invalid |
|---|
| | 587 | path segment names (such as '.' or '..') or a segment |
|---|
| | 588 | exists but as a file instead of a folder |
|---|
| | 589 | |
|---|
| | 590 | ***********************************************************************/ |
|---|
| | 591 | |
|---|
| | 592 | final FilePath create () |
|---|
| | 593 | { |
|---|
| | 594 | if (this.exists) |
|---|
| | 595 | if (this.isFolder) |
|---|
| | 596 | return this; |
|---|
| | 597 | else |
|---|
| | 598 | badArg ("FilePath.createPath :: file/folder conflict: "); |
|---|
| | 599 | |
|---|
| | 600 | auto parent = new FilePath (this.parent); |
|---|
| | 601 | char[] name = parent.name; |
|---|
| | 602 | |
|---|
| | 603 | if (name.length is 0 || |
|---|
| | 604 | name == FileConst.CurrentDirString || |
|---|
| | 605 | name == FileConst.ParentDirString) |
|---|
| | 606 | badArg ("FilePath.createPath :: invalid path: "); |
|---|
| | 607 | |
|---|
| | 608 | parent.create; |
|---|
| | 609 | return createFolder; |
|---|
| | 610 | } |
|---|
| | 611 | |
|---|
| | 612 | /*********************************************************************** |
|---|
| | 613 | |
|---|
| | 614 | List the set of filenames within this directory. All |
|---|
| | 615 | filenames are null terminated, though the null itself |
|---|
| | 616 | is hidden at the end of each name (not exposed by the |
|---|
| | 617 | length property) |
|---|
| | 618 | |
|---|
| | 619 | Each filename optionally includes the parent prefix, |
|---|
| | 620 | dictated by whether argument prefixed is enabled or |
|---|
| | 621 | not; default behaviour is to eschew the prefix |
|---|
| | 622 | |
|---|
| | 623 | ***********************************************************************/ |
|---|
| | 624 | |
|---|
| | 625 | final char[][] toList (bool prefixed = false) |
|---|
| | 626 | { |
|---|
| | 627 | int i; |
|---|
| | 628 | char[][] list; |
|---|
| | 629 | |
|---|
| | 630 | void add (char[] prefix, char[] name, bool dir) |
|---|
| | 631 | { |
|---|
| | 632 | if (i >= list.length) |
|---|
| | 633 | list.length = list.length * 2; |
|---|
| | 634 | |
|---|
| | 635 | // duplicate the path, including the null. Note that |
|---|
| | 636 | // the saved length *excludes* the terminator |
|---|
| | 637 | list[i++] = prefixed ? (prefix~name) : name.dup; |
|---|
| | 638 | } |
|---|
| | 639 | |
|---|
| | 640 | list = new char[][512]; |
|---|
| | 641 | toList (&add); |
|---|
| | 642 | return list [0 .. i]; |
|---|
| | 643 | } |
|---|
| | 644 | |
|---|
| | 725 | |
|---|
| | 726 | /*********************************************************************** |
|---|
| | 727 | |
|---|
| | 728 | Throw an exception using the last known error |
|---|
| | 729 | |
|---|
| | 730 | ***********************************************************************/ |
|---|
| | 731 | |
|---|
| | 732 | private void exception () |
|---|
| | 733 | { |
|---|
| | 734 | throw new IOException (toUtf8 ~ ": " ~ SysError.lastMsg); |
|---|
| | 735 | } |
|---|
| | 736 | |
|---|
| | 737 | /*********************************************************************** |
|---|
| | 738 | |
|---|
| | 739 | Throw an exception using the last known error |
|---|
| | 740 | |
|---|
| | 741 | ***********************************************************************/ |
|---|
| | 742 | |
|---|
| | 743 | private void badArg (char[] msg) |
|---|
| | 744 | { |
|---|
| | 745 | throw new IllegalArgumentException (msg ~ toUtf8); |
|---|
| | 746 | } |
|---|
| | 747 | |
|---|
| | 748 | /*********************************************************************** |
|---|
| | 749 | |
|---|
| | 750 | ***********************************************************************/ |
|---|
| | 751 | |
|---|
| | 752 | version (Win32) |
|---|
| | 753 | { |
|---|
| | 754 | /*************************************************************** |
|---|
| | 755 | |
|---|
| | 756 | return a wchar[] instance of the path |
|---|
| | 757 | |
|---|
| | 758 | ***************************************************************/ |
|---|
| | 759 | |
|---|
| | 760 | private wchar[] name16 (wchar[] tmp, bool withNull=true) |
|---|
| | 761 | { |
|---|
| | 762 | int offset = withNull ? 0 : 1; |
|---|
| | 763 | return Utf.toUtf16 (this.cString[0..$-offset], tmp); |
|---|
| | 764 | } |
|---|
| | 765 | |
|---|
| | 766 | /*************************************************************** |
|---|
| | 767 | |
|---|
| | 768 | Get info about this path |
|---|
| | 769 | |
|---|
| | 770 | ***************************************************************/ |
|---|
| | 771 | |
|---|
| | 772 | private DWORD getInfo (inout WIN32_FILE_ATTRIBUTE_DATA info) |
|---|
| | 773 | { |
|---|
| | 774 | version (Win32SansUnicode) |
|---|
| | 775 | { |
|---|
| | 776 | if (! GetFileAttributesExA (this.cString.ptr, GetFileInfoLevelStandard, &info)) |
|---|
| | 777 | exception; |
|---|
| | 778 | } |
|---|
| | 779 | else |
|---|
| | 780 | { |
|---|
| | 781 | wchar[MAX_PATH] tmp = void; |
|---|
| | 782 | if (! GetFileAttributesExW (name16(tmp).ptr, GetFileInfoLevelStandard, &info)) |
|---|
| | 783 | exception; |
|---|
| | 784 | } |
|---|
| | 785 | |
|---|
| | 786 | return info.dwFileAttributes; |
|---|
| | 787 | } |
|---|
| | 788 | |
|---|
| | 789 | /*************************************************************** |
|---|
| | 790 | |
|---|
| | 791 | Get flags for this path |
|---|
| | 792 | |
|---|
| | 793 | ***************************************************************/ |
|---|
| | 794 | |
|---|
| | 795 | private DWORD getFlags () |
|---|
| | 796 | { |
|---|
| | 797 | WIN32_FILE_ATTRIBUTE_DATA info = void; |
|---|
| | 798 | |
|---|
| | 799 | return getInfo (info); |
|---|
| | 800 | } |
|---|
| | 801 | |
|---|
| | 802 | /*************************************************************** |
|---|
| | 803 | |
|---|
| | 804 | Return the file length (in bytes) |
|---|
| | 805 | |
|---|
| | 806 | ***************************************************************/ |
|---|
| | 807 | |
|---|
| | 808 | final ulong fileSize () |
|---|
| | 809 | { |
|---|
| | 810 | WIN32_FILE_ATTRIBUTE_DATA info = void; |
|---|
| | 811 | |
|---|
| | 812 | getInfo (info); |
|---|
| | 813 | return (cast(ulong) info.nFileSizeHigh << 32) + |
|---|
| | 814 | info.nFileSizeLow; |
|---|
| | 815 | } |
|---|
| | 816 | |
|---|
| | 817 | /*************************************************************** |
|---|
| | 818 | |
|---|
| | 819 | Is this file writable? |
|---|
| | 820 | |
|---|
| | 821 | ***************************************************************/ |
|---|
| | 822 | |
|---|
| | 823 | final bool isWritable () |
|---|
| | 824 | { |
|---|
| | 825 | return (getFlags & FILE_ATTRIBUTE_READONLY) == 0; |
|---|
| | 826 | } |
|---|
| | 827 | |
|---|
| | 828 | /*************************************************************** |
|---|
| | 829 | |
|---|
| | 830 | Is this file actually a folder/directory? |
|---|
| | 831 | |
|---|
| | 832 | ***************************************************************/ |
|---|
| | 833 | |
|---|
| | 834 | final bool isFolder () |
|---|
| | 835 | { |
|---|
| | 836 | return (getFlags & FILE_ATTRIBUTE_DIRECTORY) != 0; |
|---|
| | 837 | } |
|---|
| | 838 | |
|---|
| | 839 | /*************************************************************** |
|---|
| | 840 | |
|---|
| | 841 | Return timestamp information |
|---|
| | 842 | |
|---|
| | 843 | ***************************************************************/ |
|---|
| | 844 | |
|---|
| | 845 | final Stamps timeStamps () |
|---|
| | 846 | { |
|---|
| | 847 | WIN32_FILE_ATTRIBUTE_DATA info = void; |
|---|
| | 848 | Stamps time = void; |
|---|
| | 849 | |
|---|
| | 850 | getInfo (info); |
|---|
| | 851 | time.modified = Utc.convert (info.ftLastWriteTime); |
|---|
| | 852 | time.accessed = Utc.convert (info.ftLastAccessTime); |
|---|
| | 853 | time.created = Utc.convert (info.ftCreationTime); |
|---|
| | 854 | return time; |
|---|
| | 855 | } |
|---|
| | 856 | |
|---|
| | 857 | /*********************************************************************** |
|---|
| | 858 | |
|---|
| | 859 | Transfer the content of another file to this one. Returns a |
|---|
| | 860 | reference to this class on success, or throws an IOException |
|---|
| | 861 | upon failure. |
|---|
| | 862 | |
|---|
| | 863 | ***********************************************************************/ |
|---|
| | 864 | |
|---|
| | 865 | final FilePath copy (char[] source) |
|---|
| | 866 | { |
|---|
| | 867 | auto src = new FilePath (source); |
|---|
| | 868 | |
|---|
| | 869 | version (Win32SansUnicode) |
|---|
| | 870 | { |
|---|
| | 871 | if (! CopyFileA (src.cString.ptr, this.cString.ptr, false)) |
|---|
| | 872 | exception; |
|---|
| | 873 | } |
|---|
| | 874 | else |
|---|
| | 875 | { |
|---|
| | 876 | wchar[MAX_PATH+1] tmp1 = void; |
|---|
| | 877 | wchar[MAX_PATH+1] tmp2 = void; |
|---|
| | 878 | |
|---|
| | 879 | if (! CopyFileW (Utf.toUtf16(src.cString, tmp1).ptr, name16(tmp2).ptr, false)) |
|---|
| | 880 | exception; |
|---|
| | 881 | } |
|---|
| | 882 | |
|---|
| | 883 | return this; |
|---|
| | 884 | } |
|---|
| | 885 | |
|---|
| | 886 | /*************************************************************** |
|---|
| | 887 | |
|---|
| | 888 | Remove the file/directory from the file-system |
|---|
| | 889 | |
|---|
| | 890 | ***************************************************************/ |
|---|
| | 891 | |
|---|
| | 892 | final FilePath remove () |
|---|
| | 893 | { |
|---|
| | 894 | if (isFolder) |
|---|
| | 895 | { |
|---|
| | 896 | version (Win32SansUnicode) |
|---|
| | 897 | { |
|---|
| | 898 | if (! RemoveDirectoryA (this.cString.ptr)) |
|---|
| | 899 | exception; |
|---|
| | 900 | } |
|---|
| | 901 | else |
|---|
| | 902 | { |
|---|
| | 903 | wchar[MAX_PATH] tmp = void; |
|---|
| | 904 | if (! RemoveDirectoryW (name16(tmp).ptr)) |
|---|
| | 905 | exception; |
|---|
| | 906 | } |
|---|
| | 907 | } |
|---|
| | 908 | else |
|---|
| | 909 | version (Win32SansUnicode) |
|---|
| | 910 | { |
|---|
| | 911 | if (! DeleteFileA (this.cString.ptr)) |
|---|
| | 912 | exception; |
|---|
| | 913 | } |
|---|
| | 914 | else |
|---|
| | 915 | { |
|---|
| | 916 | wchar[MAX_PATH] tmp = void; |
|---|
| | 917 | if (! DeleteFileW (name16(tmp).ptr)) |
|---|
| | 918 | exception; |
|---|
| | 919 | } |
|---|
| | 920 | |
|---|
| | 921 | return this; |
|---|
| | 922 | } |
|---|
| | 923 | |
|---|
| | 924 | /*************************************************************** |
|---|
| | 925 | |
|---|
| | 926 | change the name or location of a file/directory, and |
|---|
| | 927 | adopt the provided Path |
|---|
| | 928 | |
|---|
| | 929 | ***************************************************************/ |
|---|
| | 930 | |
|---|
| | 931 | final FilePath rename (FilePath dst) |
|---|
| | 932 | { |
|---|
| | 933 | const int Typical = MOVEFILE_REPLACE_EXISTING + |
|---|
| | 934 | MOVEFILE_COPY_ALLOWED + |
|---|
| | 935 | MOVEFILE_WRITE_THROUGH; |
|---|
| | 936 | |
|---|
| | 937 | int result; |
|---|
| | 938 | |
|---|
| | 939 | version (Win32SansUnicode) |
|---|
| | 940 | result = MoveFileExA (this.cString.ptr, dst.cString.ptr, Typical); |
|---|
| | 941 | else |
|---|
| | 942 | { |
|---|
| | 943 | wchar[MAX_PATH] tmp = void; |
|---|
| | 944 | result = MoveFileExW (name16(tmp).ptr, Utf.toUtf16(dst.cString).ptr, Typical); |
|---|
| | 945 | } |
|---|
| | 946 | |
|---|
| | 947 | if (! result) |
|---|
| | 948 | exception; |
|---|
| | 949 | |
|---|
| | 950 | this.set (dst); |
|---|
| | 951 | return this; |
|---|
| | 952 | } |
|---|
| | 953 | |
|---|
| | 954 | /*************************************************************** |
|---|
| | 955 | |
|---|
| | 956 | Create a new file |
|---|
| | 957 | |
|---|
| | 958 | ***************************************************************/ |
|---|
| | 959 | |
|---|
| | 960 | final FilePath createFile () |
|---|
| | 961 | { |
|---|
| | 962 | HANDLE h; |
|---|
| | 963 | |
|---|
| | 964 | version (Win32SansUnicode) |
|---|
| | 965 | h = CreateFileA (this.cString.ptr, GENERIC_WRITE, |
|---|
| | 966 | 0, null, CREATE_ALWAYS, |
|---|
| | 967 | FILE_ATTRIBUTE_NORMAL, cast(HANDLE) 0); |
|---|
| | 968 | else |
|---|
| | 969 | { |
|---|
| | 970 | wchar[MAX_PATH] tmp = void; |
|---|
| | 971 | h = CreateFileW (name16(tmp).ptr, GENERIC_WRITE, |
|---|
| | 972 | 0, null, CREATE_ALWAYS, |
|---|
| | 973 | FILE_ATTRIBUTE_NORMAL, cast(HANDLE) 0); |
|---|
| | 974 | } |
|---|
| | 975 | |
|---|
| | 976 | if (h == INVALID_HANDLE_VALUE) |
|---|
| | 977 | exception; |
|---|
| | 978 | |
|---|
| | 979 | if (! CloseHandle (h)) |
|---|
| | 980 | exception; |
|---|
| | 981 | |
|---|
| | 982 | return this; |
|---|
| | 983 | } |
|---|
| | 984 | |
|---|
| | 985 | /*************************************************************** |
|---|
| | 986 | |
|---|
| | 987 | Create a new directory |
|---|
| | 988 | |
|---|
| | 989 | ***************************************************************/ |
|---|
| | 990 | |
|---|
| | 991 | final FilePath createFolder () |
|---|
| | 992 | { |
|---|
| | 993 | version (Win32SansUnicode) |
|---|
| | 994 | { |
|---|
| | 995 | if (! CreateDirectoryA (this.cString.ptr, null)) |
|---|
| | 996 | exception; |
|---|
| | 997 | } |
|---|
| | 998 | else |
|---|
| | 999 | { |
|---|
| | 1000 | wchar[MAX_PATH] tmp = void; |
|---|
| | 1001 | if (! CreateDirectoryW (name16(tmp).ptr, null)) |
|---|
| | 1002 | exception; |
|---|
| | 1003 | } |
|---|
| | 1004 | return this; |
|---|
| | 1005 | } |
|---|
| | 1006 | |
|---|
| | 1007 | /*************************************************************** |
|---|
| | 1008 | |
|---|
| | 1009 | List the set of filenames within this directory. |
|---|
| | 1010 | |
|---|
| | 1011 | All filenames are null terminated and are passed |
|---|
| | 1012 | to the provided delegate as such, along with the |
|---|
| | 1013 | path prefix and whether the entry is a directory |
|---|
| | 1014 | or not. |
|---|
| | 1015 | |
|---|
| | 1016 | ***************************************************************/ |
|---|
| | 1017 | |
|---|
| | 1018 | final void toList (void delegate (char[], char[], bool) dg) |
|---|
| | 1019 | { |
|---|
| | 1020 | HANDLE h; |
|---|
| | 1021 | char[] prefix; |
|---|
| | 1022 | char[MAX_PATH+1] tmp = void; |
|---|
| | 1023 | FIND_DATA fileinfo = void; |
|---|
| | 1024 | |
|---|
| | 1025 | int next() |
|---|
| | 1026 | { |
|---|
| | 1027 | version (Win32SansUnicode) |
|---|
| | 1028 | return FindNextFileA (h, &fileinfo); |
|---|
| | 1029 | else |
|---|
| | 1030 | return FindNextFileW (h, &fileinfo); |
|---|
| | 1031 | } |
|---|
| | 1032 | |
|---|
| | 1033 | static T[] padded (T[] s, T[] ext) |
|---|
| | 1034 | { |
|---|
| | 1035 | if (s.length is 0 || s[$-1] != '\\') |
|---|
| | 1036 | return s ~ "\\" ~ ext; |
|---|
| | 1037 | return s ~ ext; |
|---|
| | 1038 | } |
|---|
| | 1039 | |
|---|
| | 1040 | version (Win32SansUnicode) |
|---|
| | 1041 | h = FindFirstFileA (padded(this.toUtf8, "*\0").ptr, &fileinfo); |
|---|
| | 1042 | else |
|---|
| | 1043 | { |
|---|
| | 1044 | wchar[MAX_PATH] host = void; |
|---|
| | 1045 | h = FindFirstFileW (padded(name16(host, false), "*\0").ptr, &fileinfo); |
|---|
| | 1046 | } |
|---|
| | 1047 | |
|---|
| | 1048 | if (h is INVALID_HANDLE_VALUE) |
|---|
| | 1049 | exception; |
|---|
| | 1050 | |
|---|
| | 1051 | scope (exit) |
|---|
| | 1052 | FindClose (h); |
|---|
| | 1053 | |
|---|
| | 1054 | prefix = FilePath.padded (this.toUtf8); |
|---|
| | 1055 | do { |
|---|
| | 1056 | version (Win32SansUnicode) |
|---|
| | 1057 | { |
|---|
| | 1058 | // ensure we include the null |
|---|
| | 1059 | auto len = strlen (fileinfo.cFileName.ptr); |
|---|
| | 1060 | auto str = fileinfo.cFileName.ptr [0 .. len]; |
|---|
| | 1061 | } |
|---|
| | 1062 | else |
|---|
| | 1063 | { |
|---|
| | 1064 | // ensure we include the null |
|---|
| | 1065 | auto len = wcslen (fileinfo.cFileName.ptr); |
|---|
| | 1066 | auto str = Utf.toUtf8 (fileinfo.cFileName [0 .. len], tmp); |
|---|
| | 1067 | } |
|---|
| | 1068 | |
|---|
| | 1069 | // skip hidden/system files |
|---|
| | 1070 | if ((fileinfo.dwFileAttributes & (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)) is 0) |
|---|
| | 1071 | dg (prefix, str, (fileinfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0); |
|---|
| | 1072 | |
|---|
| | 1073 | } while (next); |
|---|
| | 1074 | } |
|---|
| | 1075 | } |
|---|
| | 1076 | |
|---|
| | 1077 | |
|---|
| | 1078 | /*********************************************************************** |
|---|
| | 1079 | |
|---|
| | 1080 | ***********************************************************************/ |
|---|
| | 1081 | |
|---|
| | 1082 | version (Posix) |
|---|
| | 1083 | { |
|---|
| | 1084 | /*************************************************************** |
|---|
| | 1085 | |
|---|
| | 1086 | Get info about this path |
|---|
| | 1087 | |
|---|
| | 1088 | ***************************************************************/ |
|---|
| | 1089 | |
|---|
| | 1090 | private uint getInfo (inout stat_t stats) |
|---|
| | 1091 | { |
|---|
| | 1092 | if (posix.stat (this.cString.ptr, &stats)) |
|---|
| | 1093 | exception; |
|---|
| | 1094 | |
|---|
| | 1095 | return stats.st_mode; |
|---|
| | 1096 | } |
|---|
| | 1097 | |
|---|
| | 1098 | /*************************************************************** |
|---|
| | 1099 | |
|---|
| | 1100 | Return the file length (in bytes) |
|---|
| | 1101 | |
|---|
| | 1102 | ***************************************************************/ |
|---|
| | 1103 | |
|---|
| | 1104 | final ulong fileSize () |
|---|
| | 1105 | { |
|---|
| | 1106 | stat_t stats = void; |
|---|
| | 1107 | |
|---|
| | 1108 | getInfo (stats); |
|---|
| | 1109 | return cast(ulong) stats.st_size; // 32 bits only |
|---|
| | 1110 | } |
|---|
| | 1111 | |
|---|
| | 1112 | /*************************************************************** |
|---|
| | 1113 | |
|---|
| | 1114 | Is this file writable? |
|---|
| | 1115 | |
|---|
| | 1116 | ***************************************************************/ |
|---|
| | 1117 | |
|---|
| | 1118 | final bool isWritable () |
|---|
| | 1119 | { |
|---|
| | 1120 | stat_t stats = void; |
|---|
| | 1121 | |
|---|
| | 1122 | return (getInfo(stats) & O_RDONLY) == 0; |
|---|
| | 1123 | } |
|---|
| | 1124 | |
|---|
| | 1125 | /*************************************************************** |
|---|
| | 1126 | |
|---|
| | 1127 | Is this file actually a folder/directory? |
|---|
| | 1128 | |
|---|
| | 1129 | ***************************************************************/ |
|---|
| | 1130 | |
|---|
| | 1131 | final bool isFolder () |
|---|
| | 1132 | { |
|---|
| | 1133 | stat_t stats = void; |
|---|
| | 1134 | |
|---|
| | 1135 | return (getInfo(stats) & S_IFDIR) != 0; |
|---|
| | 1136 | } |
|---|
| | 1137 | |
|---|
| | 1138 | /*************************************************************** |
|---|
| | 1139 | |
|---|
| | 1140 | Return timestamp information |
|---|
| | 1141 | |
|---|
| | 1142 | ***************************************************************/ |
|---|
| | 1143 | |
|---|
| | 1144 | final Stamps timeStamps () |
|---|
| | 1145 | &nb |
|---|