|
64 | 64 | import static com.oracle.graal.python.runtime.PosixConstants.EAI_SERVICE; |
65 | 65 | import static com.oracle.graal.python.runtime.PosixConstants.EAI_SOCKTYPE; |
66 | 66 | import static com.oracle.graal.python.runtime.PosixConstants.F_OK; |
| 67 | +import static com.oracle.graal.python.runtime.PosixConstants.F_RDLCK; |
| 68 | +import static com.oracle.graal.python.runtime.PosixConstants.F_UNLCK; |
| 69 | +import static com.oracle.graal.python.runtime.PosixConstants.F_WRLCK; |
67 | 70 | import static com.oracle.graal.python.runtime.PosixConstants.IN6ADDR_ANY; |
68 | 71 | import static com.oracle.graal.python.runtime.PosixConstants.INADDR_NONE; |
69 | 72 | import static com.oracle.graal.python.runtime.PosixConstants.IPPROTO_TCP; |
@@ -805,67 +808,90 @@ public void fsyncMessage(int fd) throws PosixException { |
805 | 808 | } |
806 | 809 |
|
807 | 810 | @ExportMessage |
808 | | - final void flock(int fd, int operation, |
| 811 | + void flock(int fd, int operation, |
809 | 812 | @Bind("$node") Node inliningTarget, |
810 | | - @Shared("errorBranch") @Cached InlinedBranchProfile errorBranch, |
811 | | - @Shared("eq") @Cached TruffleString.EqualNode eqNode) throws PosixException { |
| 813 | + @Shared("errorBranch") @Cached InlinedBranchProfile errorBranch) throws PosixException { |
812 | 814 | Channel channel = getFileChannel(fd); |
813 | 815 | if (channel == null) { |
814 | 816 | errorBranch.enter(inliningTarget); |
815 | 817 | throw posixException(OSErrorEnum.EBADFD); |
816 | 818 | } |
817 | | - // TODO: support other types, throw unsupported feature exception otherwise (GR-28740) |
818 | | - if (channel instanceof FileChannel) { |
819 | | - FileChannel fc = (FileChannel) channel; |
820 | | - FileLock lock = getFileLock(fd); |
821 | | - try { |
822 | | - lock = doLockOperation(operation, fc, lock); |
823 | | - } catch (IOException e) { |
824 | | - throw posixException(OSErrorEnum.fromException(e, eqNode)); |
825 | | - } |
826 | | - setFileLock(fd, lock); |
| 819 | + boolean unlock = operation == LOCK_UN.value; |
| 820 | + boolean shared = (operation & LOCK_SH.value) != 0; |
| 821 | + boolean exclusive = (operation & LOCK_EX.value) != 0; |
| 822 | + boolean blocking = (operation & LOCK_NB.value) == 0; |
| 823 | + if (!unlock && !shared && !exclusive) { |
| 824 | + errorBranch.enter(inliningTarget); |
| 825 | + throw posixException(OSErrorEnum.EINVAL); |
| 826 | + } |
| 827 | + doLockOperation(fd, channel, unlock, shared, blocking, 0, 0, Long.MAX_VALUE); |
| 828 | + } |
| 829 | + |
| 830 | + @ExportMessage |
| 831 | + void fcntlLock(int fd, boolean blocking, int lockType, int whence, long start, long length, |
| 832 | + @Bind("$node") Node inliningTarget, |
| 833 | + @Shared("errorBranch") @Cached InlinedBranchProfile errorBranch) throws PosixException { |
| 834 | + Channel channel = getFileChannel(fd); |
| 835 | + if (channel == null) { |
| 836 | + errorBranch.enter(inliningTarget); |
| 837 | + throw posixException(OSErrorEnum.EBADFD); |
827 | 838 | } |
| 839 | + boolean unlock = lockType == F_UNLCK.getValueIfDefined(); |
| 840 | + boolean shared = lockType == F_RDLCK.getValueIfDefined(); |
| 841 | + boolean exclusive = lockType == F_WRLCK.getValueIfDefined(); |
| 842 | + if (!unlock && !shared && !exclusive) { |
| 843 | + errorBranch.enter(inliningTarget); |
| 844 | + throw posixException(OSErrorEnum.EINVAL); |
| 845 | + } |
| 846 | + doLockOperation(fd, channel, unlock, shared, blocking, whence, start, length); |
828 | 847 | } |
829 | 848 |
|
830 | 849 | @TruffleBoundary |
831 | | - private static FileLock doLockOperation(int operation, FileChannel fc, FileLock oldLock) throws IOException { |
832 | | - FileLock lock = oldLock; |
833 | | - if (lock == null) { |
834 | | - if ((operation & LOCK_SH.value) != 0) { |
835 | | - if ((operation & LOCK_NB.value) != 0) { |
836 | | - lock = fc.tryLock(0, Long.MAX_VALUE, true); |
837 | | - } else { |
838 | | - lock = fc.lock(0, Long.MAX_VALUE, true); |
| 850 | + private void doLockOperation(int fd, Channel channel, boolean unlock, boolean shared, boolean blocking, int whence, long start, long length) throws PosixException { |
| 851 | + // TODO: support other types, throw unsupported feature exception otherwise (GR-28740) |
| 852 | + if (channel instanceof FileChannel fc) { |
| 853 | + FileLock lock = getFileLock(fd); |
| 854 | + try { |
| 855 | + long position = start; |
| 856 | + if (whence == SEEK_CUR.value) { |
| 857 | + position += fc.position(); |
| 858 | + } else if (whence == SEEK_END.value) { |
| 859 | + position += fc.size(); |
839 | 860 | } |
840 | | - } else if ((operation & LOCK_EX.value) != 0) { |
841 | | - if ((operation & LOCK_NB.value) != 0) { |
842 | | - lock = fc.tryLock(); |
| 861 | + if (lock == null) { |
| 862 | + if (unlock) { |
| 863 | + // not locked, that's ok |
| 864 | + } else { |
| 865 | + if (!blocking) { |
| 866 | + lock = fc.tryLock(position, length, shared); |
| 867 | + } else { |
| 868 | + lock = fc.lock(position, length, shared); |
| 869 | + } |
| 870 | + } |
843 | 871 | } else { |
844 | | - lock = fc.lock(); |
845 | | - } |
846 | | - } else { |
847 | | - // not locked, that's ok |
848 | | - } |
849 | | - } else { |
850 | | - if ((operation & LOCK_UN.value) != 0) { |
851 | | - lock.release(); |
852 | | - lock = null; |
853 | | - } else if ((operation & LOCK_EX.value) != 0) { |
854 | | - if (lock.isShared()) { |
855 | | - if ((operation & LOCK_NB.value) != 0) { |
856 | | - FileLock newLock = fc.tryLock(); |
857 | | - if (newLock != null) { |
858 | | - lock = newLock; |
| 872 | + if (unlock) { |
| 873 | + lock.release(); |
| 874 | + lock = null; |
| 875 | + } else if (!shared) { |
| 876 | + if (lock.isShared()) { |
| 877 | + if (!blocking) { |
| 878 | + FileLock newLock = fc.tryLock(position, length, false); |
| 879 | + if (newLock != null) { |
| 880 | + lock = newLock; |
| 881 | + } |
| 882 | + } else { |
| 883 | + lock = fc.lock(); |
| 884 | + } |
859 | 885 | } |
860 | 886 | } else { |
861 | | - lock = fc.lock(); |
| 887 | + // we already have a suitable lock |
862 | 888 | } |
863 | 889 | } |
864 | | - } else { |
865 | | - // we already have a suitable lock |
| 890 | + } catch (IOException e) { |
| 891 | + throw posixException(OSErrorEnum.fromException(e, TruffleString.EqualNode.getUncached())); |
866 | 892 | } |
| 893 | + setFileLock(fd, lock); |
867 | 894 | } |
868 | | - return lock; |
869 | 895 | } |
870 | 896 |
|
871 | 897 | @ExportMessage |
|
0 commit comments