From 7e9dfa4ae4bbafadd2f31fa31df9f25250847200 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Thu, 14 Nov 2024 16:27:22 +0000 Subject: [PATCH] 8343785: (fs) Remove syscalls that set file times with microsecond precision Reviewed-by: alanb --- .../sun/nio/fs/BsdFileAttributeViews.java | 78 ++++++------ .../sun/nio/fs/UnixFileAttributeViews.java | 66 +++-------- .../classes/sun/nio/fs/UnixFileSystem.java | 33 +++--- .../sun/nio/fs/UnixNativeDispatcher.java | 69 +---------- .../sun/nio/fs/UnixSecureDirectoryStream.java | 8 +- .../native/libnio/fs/UnixNativeDispatcher.c | 112 +----------------- .../BasicFileAttributeView/SetTimesNanos.java | 28 ++--- 7 files changed, 89 insertions(+), 305 deletions(-) diff --git a/src/java.base/macosx/classes/sun/nio/fs/BsdFileAttributeViews.java b/src/java.base/macosx/classes/sun/nio/fs/BsdFileAttributeViews.java index e071f25f22c..cac81af84dc 100644 --- a/src/java.base/macosx/classes/sun/nio/fs/BsdFileAttributeViews.java +++ b/src/java.base/macosx/classes/sun/nio/fs/BsdFileAttributeViews.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,12 +29,15 @@ import java.io.IOException; import java.nio.file.attribute.FileTime; import java.util.concurrent.TimeUnit; import static sun.nio.fs.BsdNativeDispatcher.*; -import static sun.nio.fs.UnixNativeDispatcher.lutimes; +import static sun.nio.fs.UnixConstants.ELOOP; +import static sun.nio.fs.UnixConstants.ENXIO; +import static sun.nio.fs.UnixNativeDispatcher.futimens; +import static sun.nio.fs.UnixNativeDispatcher.utimensat; class BsdFileAttributeViews { // - // Use setattrlist(2) system call which can set creation, modification, - // and access times. + // Use the futimens(2)/utimensat(2) system calls to set the access and + // modification times, and setattrlist(2) to set the creation time. // private static void setTimes(UnixPath path, FileTime lastModifiedTime, FileTime lastAccessTime, FileTime createTime, @@ -50,31 +53,29 @@ class BsdFileAttributeViews { // permission check path.checkWrite(); - boolean useLutimes = false; - try { - useLutimes = !followLinks && - UnixFileAttributes.get(path, false).isSymbolicLink(); - } catch (UnixException x) { - x.rethrowAsIOException(path); - } - + // use a file descriptor if possible to avoid a race due to accessing + // a path more than once as the file at that path could change. + // if path is a symlink, then the open should fail with ELOOP and + // the path will be used instead of the file descriptor. int fd = -1; - if (!useLutimes) { - try { - fd = path.openForAttributeAccess(followLinks); - } catch (UnixException x) { + try { + fd = path.openForAttributeAccess(followLinks); + } catch (UnixException x) { + if (!(x.errno() == ENXIO || (x.errno() == ELOOP))) { x.rethrowAsIOException(path); } } try { // not all volumes support setattrlist(2), so set the last - // modified and last access times using futimens(2)/lutimes(3) + // modified and last access times use futimens(2)/utimensat(2) if (lastModifiedTime != null || lastAccessTime != null) { // if not changing both attributes then need existing attributes if (lastModifiedTime == null || lastAccessTime == null) { try { - UnixFileAttributes attrs = UnixFileAttributes.get(fd); + UnixFileAttributes attrs = fd >= 0 ? + UnixFileAttributes.get(fd) : + UnixFileAttributes.get(path, followLinks); if (lastModifiedTime == null) lastModifiedTime = attrs.lastModifiedTime(); if (lastAccessTime == null) @@ -85,20 +86,21 @@ class BsdFileAttributeViews { } // update times - TimeUnit timeUnit = useLutimes ? - TimeUnit.MICROSECONDS : TimeUnit.NANOSECONDS; - long modValue = lastModifiedTime.to(timeUnit); - long accessValue= lastAccessTime.to(timeUnit); + long modValue = lastModifiedTime.to(TimeUnit.NANOSECONDS); + long accessValue= lastAccessTime.to(TimeUnit.NANOSECONDS); boolean retry = false; + int flags = followLinks ? 0 : UnixConstants.AT_SYMLINK_NOFOLLOW; try { - if (useLutimes) - lutimes(path, accessValue, modValue); - else + if (fd >= 0) futimens(fd, accessValue, modValue); + else + utimensat(UnixConstants.AT_FDCWD, path, accessValue, + modValue, flags); } catch (UnixException x) { - // if futimens fails with EINVAL and one/both of the times is - // negative then we adjust the value to the epoch and retry. + // if futimens/utimensat fails with EINVAL and one/both of + // the times is negative, then we adjust the value to the + // epoch and retry. if (x.errno() == UnixConstants.EINVAL && (modValue < 0L || accessValue < 0L)) { retry = true; @@ -110,34 +112,34 @@ class BsdFileAttributeViews { if (modValue < 0L) modValue = 0L; if (accessValue < 0L) accessValue= 0L; try { - if (useLutimes) - lutimes(path, accessValue, modValue); - else + if (fd >= 0) futimens(fd, accessValue, modValue); + else + utimensat(UnixConstants.AT_FDCWD, path, accessValue, + modValue, flags); } catch (UnixException x) { x.rethrowAsIOException(path); } } } - // set the creation time using setattrlist + // set the creation time using setattrlist(2) if (createTime != null) { long createValue = createTime.to(TimeUnit.NANOSECONDS); int commonattr = UnixConstants.ATTR_CMN_CRTIME; try { - if (useLutimes) - setattrlist(path, commonattr, 0L, 0L, createValue, - followLinks ? 0 : UnixConstants.FSOPT_NOFOLLOW); - else + if (fd >= 0) fsetattrlist(fd, commonattr, 0L, 0L, createValue, - followLinks ? 0 : UnixConstants.FSOPT_NOFOLLOW); + followLinks ? 0 : UnixConstants.FSOPT_NOFOLLOW); + else + setattrlist(path, commonattr, 0L, 0L, createValue, + followLinks ? 0 : UnixConstants.FSOPT_NOFOLLOW); } catch (UnixException x) { x.rethrowAsIOException(path); } } } finally { - if (!useLutimes) - close(fd, e -> null); + close(fd, e -> null); } } diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java b/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java index 033deee2f4f..4ba1d2b8774 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java @@ -72,42 +72,25 @@ class UnixFileAttributeViews { // permission check file.checkWrite(); - boolean haveFd = false; - boolean useFutimes = false; - boolean useFutimens = false; - boolean useLutimes = false; - boolean useUtimensat = false; + // use a file descriptor if possible to avoid a race due to + // accessing a path more than once as the file at that path could + // change. + // if path is a symlink, then the open should fail with ELOOP and + // the path will be used instead of the file descriptor. int fd = -1; try { - if (!followLinks) { - // these path-based syscalls also work if following links - if (!(useUtimensat = utimensatSupported())) { - useLutimes = lutimesSupported(); - } - } - if (!useUtimensat && !useLutimes) { - fd = file.openForAttributeAccess(followLinks); - if (fd != -1) { - haveFd = true; - if (!(useFutimens = futimensSupported())) { - useFutimes = futimesSupported(); - } - } - } + fd = file.openForAttributeAccess(followLinks); } catch (UnixException x) { - if (!(x.errno() == ENXIO || - (x.errno() == ELOOP && (useUtimensat || useLutimes)))) { + if (!(x.errno() == ENXIO || (x.errno() == ELOOP))) { x.rethrowAsIOException(file); } } try { - // assert followLinks || !UnixFileAttributes.get(fd).isSymbolicLink(); - // if not changing both attributes then need existing attributes if (lastModifiedTime == null || lastAccessTime == null) { try { - UnixFileAttributes attrs = haveFd ? + UnixFileAttributes attrs = fd >= 0 ? UnixFileAttributes.get(fd) : UnixFileAttributes.get(file, followLinks); if (lastModifiedTime == null) @@ -120,28 +103,20 @@ class UnixFileAttributeViews { } // update times - TimeUnit timeUnit = (useFutimens || useUtimensat) ? - TimeUnit.NANOSECONDS : TimeUnit.MICROSECONDS; - long modValue = lastModifiedTime.to(timeUnit); - long accessValue= lastAccessTime.to(timeUnit); + long modValue = lastModifiedTime.to(TimeUnit.NANOSECONDS); + long accessValue= lastAccessTime.to(TimeUnit.NANOSECONDS); boolean retry = false; try { - if (useFutimens) { + if (fd >= 0) futimens(fd, accessValue, modValue); - } else if (useFutimes) { - futimes(fd, accessValue, modValue); - } else if (useLutimes) { - lutimes(file, accessValue, modValue); - } else if (useUtimensat) { + else utimensat(AT_FDCWD, file, accessValue, modValue, followLinks ? 0 : AT_SYMLINK_NOFOLLOW); - } else { - utimes(file, accessValue, modValue); - } } catch (UnixException x) { - // if futimes/utimes fails with EINVAL and one/both of the times is - // negative then we adjust the value to the epoch and retry. + // if utimensat fails with EINVAL and one/both of + // the times is negative then we adjust the value to the + // epoch and retry. if (x.errno() == EINVAL && (modValue < 0L || accessValue < 0L)) { retry = true; @@ -153,18 +128,11 @@ class UnixFileAttributeViews { if (modValue < 0L) modValue = 0L; if (accessValue < 0L) accessValue= 0L; try { - if (useFutimens) { + if (fd >= 0) futimens(fd, accessValue, modValue); - } else if (useFutimes) { - futimes(fd, accessValue, modValue); - } else if (useLutimes) { - lutimes(file, accessValue, modValue); - } else if (useUtimensat) { + else utimensat(AT_FDCWD, file, accessValue, modValue, followLinks ? 0 : AT_SYMLINK_NOFOLLOW); - } else { - utimes(file, accessValue, modValue); - } } catch (UnixException x) { x.rethrowAsIOException(file); } diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java b/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java index 2b9ab775ed8..56a7624e436 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java @@ -577,14 +577,14 @@ abstract class UnixFileSystem // copy time stamps last if (flags.copyBasicAttributes) { try { - if (dfd >= 0 && futimesSupported()) { - futimes(dfd, - attrs.lastAccessTime().to(TimeUnit.MICROSECONDS), - attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS)); + if (dfd >= 0) { + futimens(dfd, + attrs.lastAccessTime().to(TimeUnit.NANOSECONDS), + attrs.lastModifiedTime().to(TimeUnit.NANOSECONDS)); } else { - utimes(target, - attrs.lastAccessTime().to(TimeUnit.MICROSECONDS), - attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS)); + utimensat(AT_FDCWD, target, + attrs.lastAccessTime().to(TimeUnit.NANOSECONDS), + attrs.lastModifiedTime().to(TimeUnit.NANOSECONDS), 0); } } catch (UnixException x) { // unable to set times @@ -727,15 +727,9 @@ abstract class UnixFileSystem // copy time attributes if (flags.copyBasicAttributes) { try { - if (futimesSupported()) { - futimes(fo, - attrs.lastAccessTime().to(TimeUnit.MICROSECONDS), - attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS)); - } else { - utimes(target, - attrs.lastAccessTime().to(TimeUnit.MICROSECONDS), - attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS)); - } + futimens(fo, + attrs.lastAccessTime().to(TimeUnit.NANOSECONDS), + attrs.lastModifiedTime().to(TimeUnit.NANOSECONDS)); } catch (UnixException x) { if (flags.failIfUnableToCopyBasic) x.rethrowAsIOException(target); @@ -814,9 +808,10 @@ abstract class UnixFileSystem } if (flags.copyBasicAttributes) { try { - utimes(target, - attrs.lastAccessTime().to(TimeUnit.MICROSECONDS), - attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS)); + utimensat(AT_FDCWD, target, + attrs.lastAccessTime().to(TimeUnit.NANOSECONDS), + attrs.lastModifiedTime().to(TimeUnit.NANOSECONDS), + 0); } catch (UnixException x) { if (flags.failIfUnableToCopyBasic) x.rethrowAsIOException(target); diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java b/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java index d6d2b9fdcd7..046f843371d 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java @@ -347,28 +347,6 @@ class UnixNativeDispatcher { } private static native void fchmod0(int fd, int mode) throws UnixException; - /** - * utimes(const char* path, const struct timeval times[2]) - */ - static void utimes(UnixPath path, long times0, long times1) - throws UnixException - { - try (NativeBuffer buffer = copyToNativeBuffer(path)) { - utimes0(buffer.address(), times0, times1); - } - } - private static native void utimes0(long pathAddress, long times0, long times1) - throws UnixException; - - /** - * futimes(int fildes, const struct timeval times[2]) - */ - static void futimes(int fd, long times0, long times1) throws UnixException { - futimes0(fd, times0, times1); - } - private static native void futimes0(int fd, long times0, long times1) - throws UnixException; - /** * futimens(int fildes, const struct timespec times[2]) */ @@ -378,19 +356,6 @@ class UnixNativeDispatcher { private static native void futimens0(int fd, long times0, long times1) throws UnixException; - /** - * lutimes(const char* path, const struct timeval times[2]) - */ - static void lutimes(UnixPath path, long times0, long times1) - throws UnixException - { - try (NativeBuffer buffer = copyToNativeBuffer(path)) { - lutimes0(buffer.address(), times0, times1); - } - } - private static native void lutimes0(long pathAddress, long times0, long times1) - throws UnixException; - /** * utimensat(int fd, const char* path, * const struct timeval times[2], int flags) @@ -568,11 +533,7 @@ class UnixNativeDispatcher { * Capabilities */ private static final int SUPPORTS_OPENAT = 1 << 1; // syscalls - private static final int SUPPORTS_FUTIMES = 1 << 2; - private static final int SUPPORTS_FUTIMENS = 1 << 3; - private static final int SUPPORTS_LUTIMES = 1 << 4; - private static final int SUPPORTS_UTIMENSAT = 1 << 5; - private static final int SUPPORTS_XATTR = 1 << 6; + private static final int SUPPORTS_XATTR = 1 << 3; private static final int SUPPORTS_BIRTHTIME = 1 << 16; // other features private static final int capabilities; @@ -583,34 +544,6 @@ class UnixNativeDispatcher { return (capabilities & SUPPORTS_OPENAT) != 0; } - /** - * Supports futimes - */ - static boolean futimesSupported() { - return (capabilities & SUPPORTS_FUTIMES) != 0; - } - - /** - * Supports futimens - */ - static boolean futimensSupported() { - return (capabilities & SUPPORTS_FUTIMENS) != 0; - } - - /** - * Supports lutimes - */ - static boolean lutimesSupported() { - return (capabilities & SUPPORTS_LUTIMES) != 0; - } - - /** - * Supports utimensat - */ - static boolean utimensatSupported() { - return (capabilities & SUPPORTS_UTIMENSAT) != 0; - } - /** * Supports file birth (creation) time attribute */ diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixSecureDirectoryStream.java b/src/java.base/unix/classes/sun/nio/fs/UnixSecureDirectoryStream.java index bedf847c6e7..9497ca3644e 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixSecureDirectoryStream.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixSecureDirectoryStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -415,9 +415,9 @@ class UnixSecureDirectoryStream } // update times try { - futimes(fd, - lastAccessTime.to(TimeUnit.MICROSECONDS), - lastModifiedTime.to(TimeUnit.MICROSECONDS)); + futimens(fd, + lastAccessTime.to(TimeUnit.NANOSECONDS), + lastModifiedTime.to(TimeUnit.NANOSECONDS)); } catch (UnixException x) { x.rethrowAsIOException(file); } diff --git a/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c b/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c index aa46a2470a1..1a616446b4a 100644 --- a/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c +++ b/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c @@ -204,28 +204,19 @@ typedef int openat_func(int, const char *, int, ...); typedef int fstatat_func(int, const char *, struct stat *, int); typedef int unlinkat_func(int, const char*, int); typedef int renameat_func(int, const char*, int, const char*); -typedef int futimes_func(int, const struct timeval *); -typedef int futimens_func(int, const struct timespec *); -typedef int lutimes_func(const char *, const struct timeval *); typedef DIR* fdopendir_func(int); #if defined(__linux__) typedef int statx_func(int dirfd, const char *restrict pathname, int flags, unsigned int mask, struct my_statx *restrict statxbuf); -typedef int utimensat_func(int dirfd, const char *pathname, - const struct timespec[2], int flags); #endif static openat_func* my_openat_func = NULL; static fstatat_func* my_fstatat_func = NULL; static unlinkat_func* my_unlinkat_func = NULL; static renameat_func* my_renameat_func = NULL; -static futimes_func* my_futimes_func = NULL; -static futimens_func* my_futimens_func = NULL; -static lutimes_func* my_lutimes_func = NULL; static fdopendir_func* my_fdopendir_func = NULL; #if defined(__linux__) static statx_func* my_statx_func = NULL; -static utimensat_func* my_utimensat_func = NULL; #endif /** @@ -375,18 +366,6 @@ Java_sun_nio_fs_UnixNativeDispatcher_init(JNIEnv* env, jclass this) #endif my_unlinkat_func = (unlinkat_func*) dlsym(RTLD_DEFAULT, "unlinkat"); my_renameat_func = (renameat_func*) dlsym(RTLD_DEFAULT, "renameat"); -#if defined(__linux__) && defined(__arm__) - my_futimes_func = (futimes_func*) lookup_time_t_function("futimes", - "__futimes64"); - my_lutimes_func = (lutimes_func*) lookup_time_t_function("lutimes", - "__lutimes64"); - my_futimens_func = (futimens_func*) lookup_time_t_function("futimens", - "__futimens64"); -#else - my_futimes_func = (futimes_func*) dlsym(RTLD_DEFAULT, "futimes"); - my_lutimes_func = (lutimes_func*) dlsym(RTLD_DEFAULT, "lutimes"); - my_futimens_func = (futimens_func*) dlsym(RTLD_DEFAULT, "futimens"); -#endif #if defined(_AIX) // Make sure we link to the 64-bit version of the function my_fdopendir_func = (fdopendir_func*) dlsym(RTLD_DEFAULT, "fdopendir64"); @@ -402,25 +381,11 @@ Java_sun_nio_fs_UnixNativeDispatcher_init(JNIEnv* env, jclass this) my_fstatat_func = (fstatat_func*)&fstatat_wrapper; #endif - /* supports futimes, futimens, and/or lutimes */ - -#ifdef _ALLBSD_SOURCE - capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_FUTIMES; - capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_LUTIMES; -#else - if (my_futimes_func != NULL) - capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_FUTIMES; - if (my_lutimes_func != NULL) - capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_LUTIMES; -#endif - if (my_futimens_func != NULL) - capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_FUTIMENS; - /* supports openat, etc. */ if (my_openat_func != NULL && my_fstatat_func != NULL && my_unlinkat_func != NULL && my_renameat_func != NULL && - my_futimes_func != NULL && my_fdopendir_func != NULL) + my_fdopendir_func != NULL) { capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_OPENAT; } @@ -435,10 +400,6 @@ Java_sun_nio_fs_UnixNativeDispatcher_init(JNIEnv* env, jclass this) if (my_statx_func != NULL) { capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_BIRTHTIME; } - my_utimensat_func = (utimensat_func*) dlsym(RTLD_DEFAULT, "utimensat"); - if (my_utimensat_func != NULL) { - capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_UTIMENSAT; - } #endif /* supports extended attributes */ @@ -905,33 +866,6 @@ Java_sun_nio_fs_UnixNativeDispatcher_utimes0(JNIEnv* env, jclass this, } } -JNIEXPORT void JNICALL -Java_sun_nio_fs_UnixNativeDispatcher_futimes0(JNIEnv* env, jclass this, jint filedes, - jlong accessTime, jlong modificationTime) -{ - struct timeval times[2]; - int err = 0; - - times[0].tv_sec = accessTime / 1000000; - times[0].tv_usec = accessTime % 1000000; - - times[1].tv_sec = modificationTime / 1000000; - times[1].tv_usec = modificationTime % 1000000; - -#ifdef _ALLBSD_SOURCE - RESTARTABLE(futimes(filedes, ×[0]), err); -#else - if (my_futimes_func == NULL) { - JNU_ThrowInternalError(env, "my_futimes_func is NULL"); - return; - } - RESTARTABLE((*my_futimes_func)(filedes, ×[0]), err); -#endif - if (err == -1) { - throwUnixException(env, errno); - } -} - JNIEXPORT void JNICALL Java_sun_nio_fs_UnixNativeDispatcher_futimens0(JNIEnv* env, jclass this, jint filedes, jlong accessTime, jlong modificationTime) @@ -945,39 +879,7 @@ Java_sun_nio_fs_UnixNativeDispatcher_futimens0(JNIEnv* env, jclass this, jint fi times[1].tv_sec = modificationTime / 1000000000; times[1].tv_nsec = modificationTime % 1000000000; - if (my_futimens_func == NULL) { - JNU_ThrowInternalError(env, "my_futimens_func is NULL"); - return; - } - RESTARTABLE((*my_futimens_func)(filedes, ×[0]), err); - if (err == -1) { - throwUnixException(env, errno); - } -} - -JNIEXPORT void JNICALL -Java_sun_nio_fs_UnixNativeDispatcher_lutimes0(JNIEnv* env, jclass this, - jlong pathAddress, jlong accessTime, jlong modificationTime) -{ - int err; - struct timeval times[2]; - const char* path = (const char*)jlong_to_ptr(pathAddress); - - times[0].tv_sec = accessTime / 1000000; - times[0].tv_usec = accessTime % 1000000; - - times[1].tv_sec = modificationTime / 1000000; - times[1].tv_usec = modificationTime % 1000000; - -#ifdef _ALLBSD_SOURCE - RESTARTABLE(lutimes(path, ×[0]), err); -#else - if (my_lutimes_func == NULL) { - JNU_ThrowInternalError(env, "my_lutimes_func is NULL"); - return; - } - RESTARTABLE((*my_lutimes_func)(path, ×[0]), err); -#endif + RESTARTABLE(futimens(filedes, ×[0]), err); if (err == -1) { throwUnixException(env, errno); } @@ -986,7 +888,6 @@ Java_sun_nio_fs_UnixNativeDispatcher_lutimes0(JNIEnv* env, jclass this, JNIEXPORT void JNICALL Java_sun_nio_fs_UnixNativeDispatcher_utimensat0(JNIEnv* env, jclass this, jint fd, jlong pathAddress, jlong accessTime, jlong modificationTime, jint flags) { -#if defined(__linux__) int err; struct timespec times[2]; const char* path = (const char*)jlong_to_ptr(pathAddress); @@ -997,18 +898,11 @@ Java_sun_nio_fs_UnixNativeDispatcher_utimensat0(JNIEnv* env, jclass this, times[1].tv_sec = modificationTime / 1000000000; times[1].tv_nsec = modificationTime % 1000000000; - if (my_utimensat_func == NULL) { - JNU_ThrowInternalError(env, "my_utimensat_func is NULL"); - return; - } - RESTARTABLE((*my_utimensat_func)(fd, path, ×[0], flags), err); + RESTARTABLE(utimensat(fd, path, ×[0], flags), err); if (err == -1) { throwUnixException(env, errno); } -#else - JNU_ThrowInternalError(env, "should not reach here"); -#endif } JNIEXPORT jlong JNICALL diff --git a/test/jdk/java/nio/file/attribute/BasicFileAttributeView/SetTimesNanos.java b/test/jdk/java/nio/file/attribute/BasicFileAttributeView/SetTimesNanos.java index d71b9407bbc..acdff692601 100644 --- a/test/jdk/java/nio/file/attribute/BasicFileAttributeView/SetTimesNanos.java +++ b/test/jdk/java/nio/file/attribute/BasicFileAttributeView/SetTimesNanos.java @@ -24,7 +24,6 @@ /* @test * @bug 8181493 8231174 8343417 * @summary Verify that nanosecond precision is maintained for file timestamps - * @requires (os.family == "linux") | (os.family == "mac") | (os.family == "windows") * @library ../.. /test/lib * @build jdk.test.lib.Platform * @modules java.base/sun.nio.fs:+open @@ -51,18 +50,6 @@ import jtreg.SkippedException; public class SetTimesNanos { public static void main(String[] args) throws Exception { - if (!Platform.isWindows()) { - // Check whether futimens() system call is supported - Class unixNativeDispatcherClass = - Class.forName("sun.nio.fs.UnixNativeDispatcher"); - Method futimensSupported = - unixNativeDispatcherClass.getDeclaredMethod("futimensSupported"); - futimensSupported.setAccessible(true); - if (!(boolean)futimensSupported.invoke(null)) { - throw new SkippedException("futimens() not supported"); - } - } - Path dirPath = Path.of("test"); Path dir = Files.createDirectory(dirPath); FileStore store = Files.getFileStore(dir); @@ -80,10 +67,8 @@ public class SetTimesNanos { Path file = Files.createFile(dir.resolve("test.dat")); testNanos(file); - if (Platform.isLinux()) { - testNanosLink(false); - testNanosLink(true); - } + testNanosLink(false); + testNanosLink(true); } private static void testNanos(Path path) throws IOException { @@ -130,7 +115,14 @@ public class SetTimesNanos { Files.createFile(target); Files.createSymbolicLink(symlink, target); - var newTime = FileTime.from(1730417633157646106L, NANOSECONDS); + long timeNanos = 1730417633157646106L; + + // Windows file time resolution is 100ns so truncate + if (Platform.isWindows()) { + timeNanos = 100L*(timeNanos/100L); + } + + var newTime = FileTime.from(timeNanos, NANOSECONDS); System.out.println("newTime: " + newTime.to(NANOSECONDS)); for (Path p : List.of(target, symlink)) {