diff options
-rw-r--r-- | luni/src/main/java/android/system/StructStat.java | 35 | ||||
-rw-r--r-- | luni/src/main/java/android/system/StructTimespec.java | 61 | ||||
-rw-r--r-- | luni/src/main/native/libcore_io_Linux.cpp | 13 | ||||
-rw-r--r-- | luni/src/test/java/libcore/io/OsTest.java | 20 | ||||
-rw-r--r-- | non_openjdk_java_files.mk | 1 |
5 files changed, 121 insertions, 9 deletions
diff --git a/luni/src/main/java/android/system/StructStat.java b/luni/src/main/java/android/system/StructStat.java index ce3548f6e8..a1e872965d 100644 --- a/luni/src/main/java/android/system/StructStat.java +++ b/luni/src/main/java/android/system/StructStat.java @@ -53,15 +53,24 @@ public final class StructStat { */ public final long st_size; /*off_t*/ - /** Time of last access. */ + /** Seconds part of time of last access. */ public final long st_atime; /*time_t*/ - /** Time of last data modification. */ + /** StructTimespec with time of last access. */ + public final StructTimespec st_atim; + + /** Seconds part of time of last data modification. */ public final long st_mtime; /*time_t*/ - /** Time of last status change. */ + /** StructTimespec with time of last modification. */ + public final StructTimespec st_mtim; + + /** Seconds part of time of last status change */ public final long st_ctime; /*time_t*/ + /** StructTimespec with time of last status change. */ + public final StructTimespec st_ctim; + /** * A file system-specific preferred I/O block size for this object. * For some file system types, this may vary from file to file. @@ -77,6 +86,17 @@ public final class StructStat { public StructStat(long st_dev, long st_ino, int st_mode, long st_nlink, int st_uid, int st_gid, long st_rdev, long st_size, long st_atime, long st_mtime, long st_ctime, long st_blksize, long st_blocks) { + this(st_dev, st_ino, st_mode, st_nlink, st_uid, st_gid, + st_rdev, st_size, new StructTimespec(st_atime, 0L), new StructTimespec(st_mtime, 0L), + new StructTimespec(st_ctime, 0L), st_blksize, st_blocks); + } + + /** + * Constructs an instance with the given field values. + */ + public StructStat(long st_dev, long st_ino, int st_mode, long st_nlink, int st_uid, int st_gid, + long st_rdev, long st_size, StructTimespec st_atim, StructTimespec st_mtim, + StructTimespec st_ctim, long st_blksize, long st_blocks) { this.st_dev = st_dev; this.st_ino = st_ino; this.st_mode = st_mode; @@ -85,9 +105,12 @@ public final class StructStat { this.st_gid = st_gid; this.st_rdev = st_rdev; this.st_size = st_size; - this.st_atime = st_atime; - this.st_mtime = st_mtime; - this.st_ctime = st_ctime; + this.st_atime = st_atim.tv_sec; + this.st_mtime = st_mtim.tv_sec; + this.st_ctime = st_ctim.tv_sec; + this.st_atim = st_atim; + this.st_mtim = st_mtim; + this.st_ctim = st_ctim; this.st_blksize = st_blksize; this.st_blocks = st_blocks; } diff --git a/luni/src/main/java/android/system/StructTimespec.java b/luni/src/main/java/android/system/StructTimespec.java new file mode 100644 index 0000000000..e999249ae7 --- /dev/null +++ b/luni/src/main/java/android/system/StructTimespec.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2017 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 android.system; + +import libcore.util.Objects;; + +/** + * Corresponds to C's {@code struct timespec} from {@code <time.h>}. + */ +public final class StructTimespec implements Comparable<StructTimespec> { + /** Seconds part of time of last data modification. */ + public final long tv_sec; /*time_t*/ + + /** Nanoseconds (values are [0, 999999999]). */ + public final long tv_nsec; + + public StructTimespec(long tv_sec, long tv_nsec) { + this.tv_sec = tv_sec; + this.tv_nsec = tv_nsec; + if (tv_nsec < 0 || tv_nsec > 999_999_999) { + throw new IllegalArgumentException( + "tv_nsec value " + tv_nsec + " is not in [0, 999999999]"); + } + } + + @Override + public int compareTo(StructTimespec other) { + if (tv_sec > other.tv_sec) { + return 1; + } + if (tv_sec < other.tv_sec) { + return -1; + } + if (tv_nsec > other.tv_nsec) { + return 1; + } + if (tv_nsec < other.tv_nsec) { + return -1; + } + return 0; + } + + @Override + public String toString() { + return Objects.toString(this); + } +} diff --git a/luni/src/main/native/libcore_io_Linux.cpp b/luni/src/main/native/libcore_io_Linux.cpp index 1e2f3a585c..176300ee56 100644 --- a/luni/src/main/native/libcore_io_Linux.cpp +++ b/luni/src/main/native/libcore_io_Linux.cpp @@ -423,16 +423,23 @@ static jobject makeStructPasswd(JNIEnv* env, const struct passwd& pw) { pw_name, static_cast<jint>(pw.pw_uid), static_cast<jint>(pw.pw_gid), pw_dir, pw_shell); } +static jobject makeStructTimespec(JNIEnv* env, const struct timespec& ts) { + static jmethodID ctor = env->GetMethodID(JniConstants::structTimespecClass, "<init>", + "(JJ)V"); + return env->NewObject(JniConstants::structTimespecClass, ctor, + static_cast<jlong>(ts.tv_sec), static_cast<jlong>(ts.tv_nsec)); +} + static jobject makeStructStat(JNIEnv* env, const struct stat64& sb) { static jmethodID ctor = env->GetMethodID(JniConstants::structStatClass, "<init>", - "(JJIJIIJJJJJJJ)V"); + "(JJIJIIJJLandroid/system/StructTimespec;Landroid/system/StructTimespec;Landroid/system/StructTimespec;JJ)V"); return env->NewObject(JniConstants::structStatClass, ctor, static_cast<jlong>(sb.st_dev), static_cast<jlong>(sb.st_ino), static_cast<jint>(sb.st_mode), static_cast<jlong>(sb.st_nlink), static_cast<jint>(sb.st_uid), static_cast<jint>(sb.st_gid), static_cast<jlong>(sb.st_rdev), static_cast<jlong>(sb.st_size), - static_cast<jlong>(sb.st_atime), static_cast<jlong>(sb.st_mtime), - static_cast<jlong>(sb.st_ctime), static_cast<jlong>(sb.st_blksize), + makeStructTimespec(env, sb.st_atim), makeStructTimespec(env, sb.st_mtim), + makeStructTimespec(env, sb.st_ctim), static_cast<jlong>(sb.st_blksize), static_cast<jlong>(sb.st_blocks)); } diff --git a/luni/src/test/java/libcore/io/OsTest.java b/luni/src/test/java/libcore/io/OsTest.java index 07ce7d223d..0f47d87b13 100644 --- a/luni/src/test/java/libcore/io/OsTest.java +++ b/luni/src/test/java/libcore/io/OsTest.java @@ -20,6 +20,7 @@ import android.system.ErrnoException; import android.system.NetlinkSocketAddress; import android.system.OsConstants; import android.system.PacketSocketAddress; +import android.system.StructStat; import android.system.StructTimeval; import android.system.StructUcred; import android.system.UnixSocketAddress; @@ -783,4 +784,23 @@ public class OsTest extends TestCase { assertEquals(srcSock.getLocalPort(), address.getPort()); } } + + public void test_fstat_times() throws Exception { + File file = File.createTempFile("OsTest", "fstattest"); + FileOutputStream fos = new FileOutputStream(file); + StructStat structStat1 = Libcore.os.fstat(fos.getFD()); + assertEquals(structStat1.st_mtim.tv_sec, structStat1.st_mtime); + assertEquals(structStat1.st_ctim.tv_sec, structStat1.st_ctime); + assertEquals(structStat1.st_atim.tv_sec, structStat1.st_atime); + Thread.sleep(100); + fos.write(new byte[]{1,2,3}); + fos.flush(); + StructStat structStat2 = Libcore.os.fstat(fos.getFD()); + fos.close(); + + assertEquals(-1, structStat1.st_mtim.compareTo(structStat2.st_mtim)); + assertEquals(-1, structStat1.st_ctim.compareTo(structStat2.st_ctim)); + assertEquals(0, structStat1.st_atim.compareTo(structStat2.st_atim)); + } + } diff --git a/non_openjdk_java_files.mk b/non_openjdk_java_files.mk index ecd0ffaa04..29f8d0ce48 100644 --- a/non_openjdk_java_files.mk +++ b/non_openjdk_java_files.mk @@ -19,6 +19,7 @@ non_openjdk_javadoc_files := \ luni/src/main/java/android/system/StructStat.java \ luni/src/main/java/android/system/StructStatVfs.java \ luni/src/main/java/android/system/StructTimeval.java \ + luni/src/main/java/android/system/StructTimespec.java \ luni/src/main/java/android/system/StructUcred.java \ luni/src/main/java/android/system/StructUtsname.java \ luni/src/main/java/android/util/MutableBoolean.java \ |