diff options
17 files changed, 142 insertions, 79 deletions
diff --git a/dalvik/src/main/java/dalvik/system/BlockGuard.java b/dalvik/src/main/java/dalvik/system/BlockGuard.java index c5c5d7c..7eefedb 100644 --- a/dalvik/src/main/java/dalvik/system/BlockGuard.java +++ b/dalvik/src/main/java/dalvik/system/BlockGuard.java @@ -202,15 +202,6 @@ public final class BlockGuard { return mFileSystem.writeDirect(fileDescriptor, address, offset, length); } - public boolean lock(int fileDescriptor, long start, long length, boolean shared, - boolean waitFlag) throws IOException { - return mFileSystem.lock(fileDescriptor, start, length, shared, waitFlag); - } - - public void unlock(int fileDescriptor, long start, long length) throws IOException { - mFileSystem.unlock(fileDescriptor, start, length); - } - public long transfer(int fileHandler, FileDescriptor socketDescriptor, long offset, long count) throws IOException { return mFileSystem.transfer(fileHandler, socketDescriptor, offset, count); diff --git a/luni/src/main/java/java/nio/FileChannelImpl.java b/luni/src/main/java/java/nio/FileChannelImpl.java index b54ac09..9a323ad 100644 --- a/luni/src/main/java/java/nio/FileChannelImpl.java +++ b/luni/src/main/java/java/nio/FileChannelImpl.java @@ -35,6 +35,7 @@ import java.util.TreeSet; import libcore.io.ErrnoException; import libcore.io.IoUtils; import libcore.io.Libcore; +import libcore.io.StructFlock; import org.apache.harmony.luni.platform.Platform; import static libcore.io.OsConstants.*; @@ -108,16 +109,27 @@ final class FileChannelImpl extends FileChannel { if (position < 0 || size < 0) { throw new IllegalArgumentException("position=" + position + " size=" + size); } + FileLock pendingLock = new FileLockImpl(this, position, size, shared); addLock(pendingLock); - if (Platform.FILE_SYSTEM.lock(IoUtils.getFd(fd), position, size, shared, wait)) { - return pendingLock; + StructFlock flock = new StructFlock(); + flock.l_type = (short) (shared ? F_RDLCK : F_WRLCK); + flock.l_whence = (short) SEEK_SET; + flock.l_start = position; + flock.l_len = translateLockLength(size); + if (Libcore.os.fcntlFlock(fd, wait ? F_SETLKW64 : F_SETLK64, flock) == -1) { + // Lock acquisition failed. + removeLock(pendingLock); + return null; } - // Lock acquisition failed - removeLock(pendingLock); - return null; + return pendingLock; + } + + private static long translateLockLength(long byteCount) { + // FileChannel uses Long.MAX_VALUE to mean "lock the whole file" where POSIX uses 0. + return (byteCount == Long.MAX_VALUE) ? 0 : byteCount; } private static final class FileLockImpl extends FileLock { @@ -169,7 +181,18 @@ final class FileChannelImpl extends FileChannel { */ public void release(FileLock lock) throws IOException { checkOpen(); - Platform.FILE_SYSTEM.unlock(IoUtils.getFd(fd), lock.position(), lock.size()); + + StructFlock flock = new StructFlock(); + flock.l_type = (short) F_UNLCK; + flock.l_whence = (short) SEEK_SET; + flock.l_start = lock.position(); + flock.l_len = translateLockLength(lock.size()); + try { + Libcore.os.fcntlFlock(fd, F_SETLKW64, flock); + } catch (ErrnoException errnoException) { + throw errnoException.rethrowAsIOException(); + } + removeLock(lock); } diff --git a/luni/src/main/java/java/nio/channels/FileLock.java b/luni/src/main/java/java/nio/channels/FileLock.java index 9862097..0916be0 100644 --- a/luni/src/main/java/java/nio/channels/FileLock.java +++ b/luni/src/main/java/java/nio/channels/FileLock.java @@ -96,8 +96,7 @@ public abstract class FileLock { * the lock's sharing mode of lock; {@code true} is shared, * {@code false} is exclusive. */ - protected FileLock(FileChannel channel, long position, long size, - boolean shared) { + protected FileLock(FileChannel channel, long position, long size, boolean shared) { if (position < 0 || size < 0 || position + size < 0) { throw new IllegalArgumentException(); } diff --git a/luni/src/main/java/libcore/io/ForwardingOs.java b/luni/src/main/java/libcore/io/ForwardingOs.java index c1ef461..1e45b31 100644 --- a/luni/src/main/java/libcore/io/ForwardingOs.java +++ b/luni/src/main/java/libcore/io/ForwardingOs.java @@ -31,6 +31,9 @@ public class ForwardingOs implements Os { public boolean access(String path, int mode) throws ErrnoException { return os.access(path, mode); } public void chmod(String path, int mode) throws ErrnoException { os.chmod(path, mode); } public String[] environ() { return os.environ(); } + public int fcntlVoid(FileDescriptor fd, int cmd) throws ErrnoException { return os.fcntlVoid(fd, cmd); } + public int fcntlLong(FileDescriptor fd, int cmd, long arg) throws ErrnoException { return os.fcntlLong(fd, cmd, arg); } + public int fcntlFlock(FileDescriptor fd, int cmd, StructFlock arg) throws ErrnoException { return os.fcntlFlock(fd, cmd, arg); } public void fdatasync(FileDescriptor fd) throws ErrnoException { os.fdatasync(fd); } public StructStat fstat(FileDescriptor fd) throws ErrnoException { return os.fstat(fd); } public StructStatFs fstatfs(FileDescriptor fd) throws ErrnoException { return os.fstatfs(fd); } diff --git a/luni/src/main/java/libcore/io/IoUtils.java b/luni/src/main/java/libcore/io/IoUtils.java index 2a9cf96..b5fbe81 100644 --- a/luni/src/main/java/libcore/io/IoUtils.java +++ b/luni/src/main/java/libcore/io/IoUtils.java @@ -99,7 +99,19 @@ public final class IoUtils { /** * Sets 'fd' to be blocking or non-blocking, according to the state of 'blocking'. */ - public static native void setBlocking(FileDescriptor fd, boolean blocking) throws IOException; + public static void setBlocking(FileDescriptor fd, boolean blocking) throws IOException { + try { + int flags = Libcore.os.fcntlVoid(fd, F_GETFL); + if (!blocking) { + flags |= O_NONBLOCK; + } else { + flags &= ~O_NONBLOCK; + } + Libcore.os.fcntlLong(fd, F_SETFL, flags); + } catch (ErrnoException errnoException) { + throw errnoException.rethrowAsIOException(); + } + } /** * Returns the contents of 'path' as a byte array. diff --git a/luni/src/main/java/libcore/io/Os.java b/luni/src/main/java/libcore/io/Os.java index dc6a640..44b8624 100644 --- a/luni/src/main/java/libcore/io/Os.java +++ b/luni/src/main/java/libcore/io/Os.java @@ -22,6 +22,9 @@ public interface Os { public boolean access(String path, int mode) throws ErrnoException; public void chmod(String path, int mode) throws ErrnoException; public String[] environ(); + public int fcntlVoid(FileDescriptor fd, int cmd) throws ErrnoException; + public int fcntlLong(FileDescriptor fd, int cmd, long arg) throws ErrnoException; + public int fcntlFlock(FileDescriptor fd, int cmd, StructFlock arg) throws ErrnoException; public void fdatasync(FileDescriptor fd) throws ErrnoException; public StructStat fstat(FileDescriptor fd) throws ErrnoException; public StructStatFs fstatfs(FileDescriptor fd) throws ErrnoException; diff --git a/luni/src/main/java/libcore/io/OsConstants.java b/luni/src/main/java/libcore/io/OsConstants.java index 6913aef..078e80d 100644 --- a/luni/src/main/java/libcore/io/OsConstants.java +++ b/luni/src/main/java/libcore/io/OsConstants.java @@ -125,13 +125,16 @@ public final class OsConstants { public static final int F_GETFD = placeholder(); public static final int F_GETFL = placeholder(); public static final int F_GETLK = placeholder(); + public static final int F_GETLK64 = placeholder(); public static final int F_GETOWN = placeholder(); public static final int F_OK = placeholder(); public static final int F_RDLCK = placeholder(); public static final int F_SETFD = placeholder(); public static final int F_SETFL = placeholder(); public static final int F_SETLK = placeholder(); + public static final int F_SETLK64 = placeholder(); public static final int F_SETLKW = placeholder(); + public static final int F_SETLKW64 = placeholder(); public static final int F_SETOWN = placeholder(); public static final int F_UNLCK = placeholder(); public static final int F_WRLCK = placeholder(); diff --git a/luni/src/main/java/libcore/io/Posix.java b/luni/src/main/java/libcore/io/Posix.java index 27b28ad..eb07894 100644 --- a/luni/src/main/java/libcore/io/Posix.java +++ b/luni/src/main/java/libcore/io/Posix.java @@ -24,6 +24,9 @@ public final class Posix implements Os { public native boolean access(String path, int mode) throws ErrnoException; public native void chmod(String path, int mode) throws ErrnoException; public native String[] environ(); + public native int fcntlVoid(FileDescriptor fd, int cmd) throws ErrnoException; + public native int fcntlLong(FileDescriptor fd, int cmd, long arg) throws ErrnoException; + public native int fcntlFlock(FileDescriptor fd, int cmd, StructFlock arg) throws ErrnoException; public native void fdatasync(FileDescriptor fd) throws ErrnoException; public native StructStat fstat(FileDescriptor fd) throws ErrnoException; public native StructStatFs fstatfs(FileDescriptor fd) throws ErrnoException; diff --git a/luni/src/main/java/libcore/io/StructFlock.java b/luni/src/main/java/libcore/io/StructFlock.java new file mode 100644 index 0000000..6d63064 --- /dev/null +++ b/luni/src/main/java/libcore/io/StructFlock.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package libcore.io; + +import static libcore.io.OsConstants.*; + +/** + * Information returned/taken by fcntl(2) F_GETFL and F_SETFL. Corresponds to C's + * {@code struct flock} from + * <a href="http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/fcntl.h.html"><fcntl.h></a> + */ +public final class StructFlock { + /** The operation type, one of F_RDLCK, F_WRLCK, or F_UNLCK. */ + public short l_type; + + /** How to interpret l_start, one of SEEK_CUR, SEEK_END, SEEK_SET. */ + public short l_whence; + + /** Start offset. */ + public long l_start; /*off_t*/ + + /** Byte count to operate on. */ + public long l_len; /*off_t*/ + + /** Process blocking our lock (filled in by F_GETLK, otherwise unused). */ + public int l_pid; /*pid_t*/ +} diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/IFileSystem.java b/luni/src/main/java/org/apache/harmony/luni/platform/IFileSystem.java index 9a82e20..3d7d647 100644 --- a/luni/src/main/java/org/apache/harmony/luni/platform/IFileSystem.java +++ b/luni/src/main/java/org/apache/harmony/luni/platform/IFileSystem.java @@ -41,12 +41,6 @@ public interface IFileSystem { public long writeDirect(int fileDescriptor, int address, int offset, int length) throws IOException; - public boolean lock(int fileDescriptor, long start, long length, boolean shared, - boolean waitFlag) throws IOException; - - public void unlock(int fileDescriptor, long start, long length) - throws IOException; - public long transfer(int fileHandler, FileDescriptor socketDescriptor, long offset, long count) throws IOException; diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/OSFileSystem.java b/luni/src/main/java/org/apache/harmony/luni/platform/OSFileSystem.java index 0940a14..779a395 100644 --- a/luni/src/main/java/org/apache/harmony/luni/platform/OSFileSystem.java +++ b/luni/src/main/java/org/apache/harmony/luni/platform/OSFileSystem.java @@ -33,17 +33,6 @@ class OSFileSystem implements IFileSystem { private OSFileSystem() { } - public boolean lock(int fd, long start, long length, boolean shared, boolean waitFlag) throws IOException { - int result = lockImpl(fd, start, length, shared ? F_RDLCK : F_WRLCK, waitFlag); - return result != -1; - } - - public void unlock(int fd, long start, long length) throws IOException { - lockImpl(fd, start, length, F_UNLCK, true); - } - - private native int lockImpl(int fd, long start, long length, int type, boolean wait); - /* * Direct read/write APIs work on addresses. */ diff --git a/luni/src/main/native/JniConstants.cpp b/luni/src/main/native/JniConstants.cpp index 6fb74c8..605a56e 100644 --- a/luni/src/main/native/JniConstants.cpp +++ b/luni/src/main/native/JniConstants.cpp @@ -47,6 +47,7 @@ jclass JniConstants::socketClass; jclass JniConstants::socketImplClass; jclass JniConstants::stringArrayClass; jclass JniConstants::stringClass; +jclass JniConstants::structFlockClass; jclass JniConstants::structStatClass; jclass JniConstants::structStatFsClass; jclass JniConstants::structUtsnameClass; @@ -90,6 +91,7 @@ void JniConstants::init(JNIEnv* env) { socketImplClass = findClass(env, "java/net/SocketImpl"); stringArrayClass = findClass(env, "[Ljava/lang/String;"); stringClass = findClass(env, "java/lang/String"); + structFlockClass = findClass(env, "libcore/io/StructFlock"); structStatClass = findClass(env, "libcore/io/StructStat"); structStatFsClass = findClass(env, "libcore/io/StructStatFs"); structUtsnameClass = findClass(env, "libcore/io/StructUtsname"); diff --git a/luni/src/main/native/JniConstants.h b/luni/src/main/native/JniConstants.h index c521b6b..364eb0a 100644 --- a/luni/src/main/native/JniConstants.h +++ b/luni/src/main/native/JniConstants.h @@ -69,6 +69,7 @@ struct JniConstants { static jclass socketImplClass; static jclass stringArrayClass; static jclass stringClass; + static jclass structFlockClass; static jclass structStatClass; static jclass structStatFsClass; static jclass structUtsnameClass; diff --git a/luni/src/main/native/libcore_io_IoUtils.cpp b/luni/src/main/native/libcore_io_IoUtils.cpp index 964d372..304354b 100644 --- a/luni/src/main/native/libcore_io_IoUtils.cpp +++ b/luni/src/main/native/libcore_io_IoUtils.cpp @@ -43,20 +43,9 @@ static jint IoUtils_getFd(JNIEnv* env, jclass, jobject fileDescriptor) { return jniGetFDFromFileDescriptor(env, fileDescriptor); } -static void IoUtils_setBlocking(JNIEnv* env, jclass, jobject fileDescriptor, jboolean blocking) { - int fd = jniGetFDFromFileDescriptor(env, fileDescriptor); - if (fd == -1) { - return; - } - if (!setBlocking(fd, blocking)) { - jniThrowIOException(env, errno); - } -} - static JNINativeMethod gMethods[] = { NATIVE_METHOD(IoUtils, close, "(Ljava/io/FileDescriptor;)V"), NATIVE_METHOD(IoUtils, getFd, "(Ljava/io/FileDescriptor;)I"), - NATIVE_METHOD(IoUtils, setBlocking, "(Ljava/io/FileDescriptor;Z)V"), }; int register_libcore_io_IoUtils(JNIEnv* env) { return jniRegisterNativeMethods(env, "libcore/io/IoUtils", gMethods, NELEM(gMethods)); diff --git a/luni/src/main/native/libcore_io_OsConstants.cpp b/luni/src/main/native/libcore_io_OsConstants.cpp index e8845b1..5bff510 100644 --- a/luni/src/main/native/libcore_io_OsConstants.cpp +++ b/luni/src/main/native/libcore_io_OsConstants.cpp @@ -126,13 +126,16 @@ static void OsConstants_initConstants(JNIEnv* env, jclass c) { initConstant(env, c, "F_GETFD", F_GETFD); initConstant(env, c, "F_GETFL", F_GETFL); initConstant(env, c, "F_GETLK", F_GETLK); + initConstant(env, c, "F_GETLK64", F_GETLK64); initConstant(env, c, "F_GETOWN", F_GETOWN); initConstant(env, c, "F_OK", F_OK); initConstant(env, c, "F_RDLCK", F_RDLCK); initConstant(env, c, "F_SETFD", F_SETFD); initConstant(env, c, "F_SETFL", F_SETFL); initConstant(env, c, "F_SETLK", F_SETLK); + initConstant(env, c, "F_SETLK64", F_SETLK64); initConstant(env, c, "F_SETLKW", F_SETLKW); + initConstant(env, c, "F_SETLKW64", F_SETLKW64); initConstant(env, c, "F_SETOWN", F_SETOWN); initConstant(env, c, "F_UNLCK", F_UNLCK); initConstant(env, c, "F_WRLCK", F_WRLCK); diff --git a/luni/src/main/native/libcore_io_Posix.cpp b/luni/src/main/native/libcore_io_Posix.cpp index 961ca52..5d512d1 100644 --- a/luni/src/main/native/libcore_io_Posix.cpp +++ b/luni/src/main/native/libcore_io_Posix.cpp @@ -158,6 +158,43 @@ static jobjectArray Posix_environ(JNIEnv* env, jobject) { return toStringArray(env, environ); } +static jint Posix_fcntlVoid(JNIEnv* env, jobject, jobject javaFd, jint cmd) { + int fd = jniGetFDFromFileDescriptor(env, javaFd); + return throwIfMinusOne(env, "fcntl", TEMP_FAILURE_RETRY(fcntl(fd, cmd))); +} + +static jint Posix_fcntlLong(JNIEnv* env, jobject, jobject javaFd, jint cmd, jlong arg) { + int fd = jniGetFDFromFileDescriptor(env, javaFd); + return throwIfMinusOne(env, "fcntl", TEMP_FAILURE_RETRY(fcntl(fd, cmd, arg))); +} + +static jint Posix_fcntlFlock(JNIEnv* env, jobject, jobject javaFd, jint cmd, jobject javaFlock) { + static jfieldID typeFid = env->GetFieldID(JniConstants::structFlockClass, "l_type", "S"); + static jfieldID whenceFid = env->GetFieldID(JniConstants::structFlockClass, "l_whence", "S"); + static jfieldID startFid = env->GetFieldID(JniConstants::structFlockClass, "l_start", "J"); + static jfieldID lenFid = env->GetFieldID(JniConstants::structFlockClass, "l_len", "J"); + static jfieldID pidFid = env->GetFieldID(JniConstants::structFlockClass, "l_pid", "I"); + + struct flock64 lock; + memset(&lock, 0, sizeof(lock)); + lock.l_type = env->GetShortField(javaFlock, typeFid); + lock.l_whence = env->GetShortField(javaFlock, whenceFid); + lock.l_start = env->GetLongField(javaFlock, startFid); + lock.l_len = env->GetLongField(javaFlock, lenFid); + lock.l_pid = env->GetIntField(javaFlock, pidFid); + + int fd = jniGetFDFromFileDescriptor(env, javaFd); + int rc = throwIfMinusOne(env, "fcntl", TEMP_FAILURE_RETRY(fcntl(fd, cmd, &lock))); + if (rc != -1) { + env->SetShortField(javaFlock, typeFid, lock.l_type); + env->SetShortField(javaFlock, whenceFid, lock.l_whence); + env->SetLongField(javaFlock, startFid, lock.l_start); + env->SetLongField(javaFlock, lenFid, lock.l_len); + env->SetIntField(javaFlock, pidFid, lock.l_pid); + } + return rc; +} + static void Posix_fdatasync(JNIEnv* env, jobject, jobject javaFd) { int fd = jniGetFDFromFileDescriptor(env, javaFd); throwIfMinusOne(env, "fdatasync", TEMP_FAILURE_RETRY(fdatasync(fd))); @@ -382,6 +419,9 @@ static JNINativeMethod gMethods[] = { NATIVE_METHOD(Posix, access, "(Ljava/lang/String;I)Z"), NATIVE_METHOD(Posix, chmod, "(Ljava/lang/String;I)V"), NATIVE_METHOD(Posix, environ, "()[Ljava/lang/String;"), + NATIVE_METHOD(Posix, fcntlVoid, "(Ljava/io/FileDescriptor;I)I"), + NATIVE_METHOD(Posix, fcntlLong, "(Ljava/io/FileDescriptor;IJ)I"), + NATIVE_METHOD(Posix, fcntlFlock, "(Ljava/io/FileDescriptor;ILlibcore/io/StructFlock;)I"), NATIVE_METHOD(Posix, fdatasync, "(Ljava/io/FileDescriptor;)V"), NATIVE_METHOD(Posix, fstat, "(Ljava/io/FileDescriptor;)Llibcore/io/StructStat;"), NATIVE_METHOD(Posix, fstatfs, "(Ljava/io/FileDescriptor;)Llibcore/io/StructStatFs;"), diff --git a/luni/src/main/native/org_apache_harmony_luni_platform_OSFileSystem.cpp b/luni/src/main/native/org_apache_harmony_luni_platform_OSFileSystem.cpp index 5ff130f..6e10b2a 100644 --- a/luni/src/main/native/org_apache_harmony_luni_platform_OSFileSystem.cpp +++ b/luni/src/main/native/org_apache_harmony_luni_platform_OSFileSystem.cpp @@ -58,38 +58,6 @@ static inline ssize_t sendfile(int out_fd, int in_fd, off_t* offset, size_t coun } #endif -static jlong translateLockLength(jlong length) { - // FileChannel.tryLock uses Long.MAX_VALUE to mean "lock the whole - // file", where POSIX would use 0. We can support that special case, - // even for files whose actual length we can't represent. For other - // out of range lengths, though, we want our range checking to fire. - return (length == 0x7fffffffffffffffLL) ? 0 : length; -} - -static struct flock64 flockFromStartAndLength(jlong start, jlong length) { - struct flock64 lock; - memset(&lock, 0, sizeof(lock)); - - lock.l_whence = SEEK_SET; - lock.l_start = start; - lock.l_len = length; - - return lock; -} - -static jint OSFileSystem_lockImpl(JNIEnv* env, jobject, jint fd, - jlong start, jlong length, jint lockType, jboolean waitFlag) { - - length = translateLockLength(length); - struct flock64 lock(flockFromStartAndLength(start, length)); - lock.l_type = lockType; - int rc = TEMP_FAILURE_RETRY(fcntl(fd, waitFlag ? F_SETLKW64 : F_SETLK64, &lock)); - if (lockType == F_UNLCK && rc == -1) { - jniThrowIOException(env, errno); - } - return rc; -} - // Translate three Java int[]s to a native iovec[] for readv and writev. static iovec* initIoVec(JNIEnv* env, jintArray jBuffers, jintArray jOffsets, jintArray jLengths, jint size) { @@ -272,7 +240,6 @@ static jint OSFileSystem_ioctlAvailable(JNIEnv*env, jobject, jobject fileDescrip static JNINativeMethod gMethods[] = { NATIVE_METHOD(OSFileSystem, ioctlAvailable, "(Ljava/io/FileDescriptor;)I"), - NATIVE_METHOD(OSFileSystem, lockImpl, "(IJJIZ)I"), NATIVE_METHOD(OSFileSystem, read, "(I[BII)J"), NATIVE_METHOD(OSFileSystem, readDirect, "(IIII)J"), NATIVE_METHOD(OSFileSystem, readv, "(I[I[I[II)J"), |