mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-11 14:11:36 +00:00
8298187: (fs) BsdFileAttributeViews::setTimes does not support lastAccessTime on HFS+
Reviewed-by: alanb
This commit is contained in:
parent
3cdbd878e6
commit
5412439445
@ -28,7 +28,8 @@ package sun.nio.fs;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.attribute.FileTime;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import static sun.nio.fs.BsdNativeDispatcher.setattrlist;
|
||||
import static sun.nio.fs.BsdNativeDispatcher.*;
|
||||
import static sun.nio.fs.UnixNativeDispatcher.lutimes;
|
||||
|
||||
class BsdFileAttributeViews {
|
||||
//
|
||||
@ -49,28 +50,94 @@ class BsdFileAttributeViews {
|
||||
// permission check
|
||||
path.checkWrite();
|
||||
|
||||
int commonattr = 0;
|
||||
long modValue = 0L;
|
||||
if (lastModifiedTime != null) {
|
||||
modValue = lastModifiedTime.to(TimeUnit.NANOSECONDS);
|
||||
commonattr |= UnixConstants.ATTR_CMN_MODTIME;
|
||||
boolean useLutimes = false;
|
||||
try {
|
||||
useLutimes = !followLinks &&
|
||||
UnixFileAttributes.get(path, false).isSymbolicLink();
|
||||
} catch (UnixException x) {
|
||||
x.rethrowAsIOException(path);
|
||||
}
|
||||
long accValue = 0L;
|
||||
if (lastAccessTime != null) {
|
||||
accValue = lastAccessTime.to(TimeUnit.NANOSECONDS);
|
||||
commonattr |= UnixConstants.ATTR_CMN_ACCTIME;
|
||||
}
|
||||
long createValue = 0L;
|
||||
if (createTime != null) {
|
||||
createValue = createTime.to(TimeUnit.NANOSECONDS);
|
||||
commonattr |= UnixConstants.ATTR_CMN_CRTIME;
|
||||
|
||||
int fd = -1;
|
||||
if (!useLutimes) {
|
||||
try {
|
||||
fd = path.openForAttributeAccess(followLinks);
|
||||
} catch (UnixException x) {
|
||||
x.rethrowAsIOException(path);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
setattrlist(path, commonattr, modValue, accValue, createValue,
|
||||
followLinks ? 0 : UnixConstants.FSOPT_NOFOLLOW);
|
||||
} catch (UnixException x) {
|
||||
x.rethrowAsIOException(path);
|
||||
// not all volumes support setattrlist(2), so set the last
|
||||
// modified and last access times using futimens(2)/lutimes(3)
|
||||
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);
|
||||
if (lastModifiedTime == null)
|
||||
lastModifiedTime = attrs.lastModifiedTime();
|
||||
if (lastAccessTime == null)
|
||||
lastAccessTime = attrs.lastAccessTime();
|
||||
} catch (UnixException x) {
|
||||
x.rethrowAsIOException(path);
|
||||
}
|
||||
}
|
||||
|
||||
// update times
|
||||
TimeUnit timeUnit = useLutimes ?
|
||||
TimeUnit.MICROSECONDS : TimeUnit.NANOSECONDS;
|
||||
long modValue = lastModifiedTime.to(timeUnit);
|
||||
long accessValue= lastAccessTime.to(timeUnit);
|
||||
|
||||
boolean retry = false;
|
||||
try {
|
||||
if (useLutimes)
|
||||
lutimes(path, accessValue, modValue);
|
||||
else
|
||||
futimens(fd, accessValue, modValue);
|
||||
} 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 (x.errno() == UnixConstants.EINVAL &&
|
||||
(modValue < 0L || accessValue < 0L)) {
|
||||
retry = true;
|
||||
} else {
|
||||
x.rethrowAsIOException(path);
|
||||
}
|
||||
}
|
||||
if (retry) {
|
||||
if (modValue < 0L) modValue = 0L;
|
||||
if (accessValue < 0L) accessValue= 0L;
|
||||
try {
|
||||
if (useLutimes)
|
||||
lutimes(path, accessValue, modValue);
|
||||
else
|
||||
futimens(fd, accessValue, modValue);
|
||||
} catch (UnixException x) {
|
||||
x.rethrowAsIOException(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set the creation time using setattrlist
|
||||
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
|
||||
fsetattrlist(fd, commonattr, 0L, 0L, createValue,
|
||||
followLinks ? 0 : UnixConstants.FSOPT_NOFOLLOW);
|
||||
} catch (UnixException x) {
|
||||
x.rethrowAsIOException(path);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (!useLutimes)
|
||||
close(fd, e -> null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -104,6 +104,27 @@ class BsdNativeDispatcher extends UnixNativeDispatcher {
|
||||
long createTime, long options)
|
||||
throws UnixException;
|
||||
|
||||
/**
|
||||
* fsetattrlist(int fd, struct attrlist* attrList, void* attrBuf,
|
||||
* size_t attrBufSize, unsigned long options)
|
||||
*/
|
||||
static void fsetattrlist(int fd, int commonattr, long modTime,
|
||||
long accTime, long createTime, long options)
|
||||
throws UnixException
|
||||
{
|
||||
long comp = Blocker.begin();
|
||||
try {
|
||||
fsetattrlist0(fd, commonattr, modTime, accTime,
|
||||
createTime, options);
|
||||
} finally {
|
||||
Blocker.end(comp);
|
||||
}
|
||||
}
|
||||
private static native void fsetattrlist0(int fd, int commonattr,
|
||||
long modTime, long accTime,
|
||||
long createTime, long options)
|
||||
throws UnixException;
|
||||
|
||||
// initialize field IDs
|
||||
private static native void initIDs();
|
||||
|
||||
|
||||
@ -39,6 +39,7 @@
|
||||
#define ISREADONLY MNT_RDONLY
|
||||
#endif
|
||||
#include <sys/attr.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -243,17 +244,11 @@ Java_sun_nio_fs_BsdNativeDispatcher_clonefile0(JNIEnv* env, jclass this,
|
||||
return 0;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_nio_fs_BsdNativeDispatcher_setattrlist0(JNIEnv* env, jclass this,
|
||||
jlong pathAddress, int commonattr, jlong modTime, jlong accTime,
|
||||
jlong createTime, jlong options)
|
||||
size_t initattrlist(jint commonattr, jlong modTime, jlong accTime,
|
||||
jlong createTime, const int attrsize, char* buf, struct attrlist *attrList)
|
||||
{
|
||||
const char* path = (const char*)jlong_to_ptr(pathAddress);
|
||||
// attributes must align on 4-byte boundaries per the getattrlist(2) spec
|
||||
const int attrsize = ((sizeof(struct timespec) + 3)/4)*4;
|
||||
char buf[3*attrsize];
|
||||
|
||||
int count = 0;
|
||||
|
||||
// attributes are ordered per the getattrlist(2) spec
|
||||
if ((commonattr & ATTR_CMN_CRTIME) != 0) {
|
||||
struct timespec* t = (struct timespec*)buf;
|
||||
@ -274,12 +269,46 @@ Java_sun_nio_fs_BsdNativeDispatcher_setattrlist0(JNIEnv* env, jclass this,
|
||||
count++;
|
||||
}
|
||||
|
||||
struct attrlist attrList;
|
||||
memset(&attrList, 0, sizeof(struct attrlist));
|
||||
attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
|
||||
attrList.commonattr = commonattr;
|
||||
memset(attrList, 0, sizeof(struct attrlist));
|
||||
attrList->bitmapcount = ATTR_BIT_MAP_COUNT;
|
||||
attrList->commonattr = commonattr;
|
||||
|
||||
if (setattrlist(path, &attrList, (void*)buf, count*attrsize, options) != 0) {
|
||||
return count*attrsize;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_nio_fs_BsdNativeDispatcher_setattrlist0(JNIEnv* env, jclass this,
|
||||
jlong pathAddress, int commonattr, jlong modTime, jlong accTime,
|
||||
jlong createTime, jlong options)
|
||||
{
|
||||
const char* path = (const char*)jlong_to_ptr(pathAddress);
|
||||
// attributes must align on 4-byte boundaries per the getattrlist(2) spec
|
||||
const int attrsize = ((sizeof(struct timespec) + 3)/4)*4;
|
||||
char buf[3*attrsize];
|
||||
|
||||
struct attrlist attrList;
|
||||
size_t attrBufSize = initattrlist(commonattr, modTime, accTime, createTime,
|
||||
attrsize, buf, &attrList);
|
||||
|
||||
if (setattrlist(path, &attrList, (void*)buf, attrBufSize, options) != 0) {
|
||||
throwUnixException(env, errno);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_nio_fs_BsdNativeDispatcher_fsetattrlist0(JNIEnv* env, jclass this,
|
||||
jint fd, int commonattr, jlong modTime, jlong accTime,
|
||||
jlong createTime, jlong options)
|
||||
{
|
||||
// attributes must align on 4-byte boundaries per the getattrlist(2) spec
|
||||
const int attrsize = ((sizeof(struct timespec) + 3)/4)*4;
|
||||
char buf[3*attrsize];
|
||||
|
||||
struct attrlist attrList;
|
||||
size_t attrBufSize = initattrlist(commonattr, modTime, accTime, createTime,
|
||||
attrsize, buf, &attrList);
|
||||
|
||||
if (fsetattrlist(fd, &attrList, (void*)buf, attrBufSize, options) != 0) {
|
||||
throwUnixException(env, errno);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2007, 2022, 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
|
||||
@ -134,7 +134,7 @@ public interface BasicFileAttributeView
|
||||
*
|
||||
* <p> This method updates the file's timestamp attributes. The values are
|
||||
* converted to the epoch and precision supported by the file system.
|
||||
* Converting from finer to coarser granularities result in precision loss.
|
||||
* Converting from finer to coarser granularities results in precision loss.
|
||||
* The behavior of this method when attempting to set a timestamp that is
|
||||
* not supported or to a value that is outside the range supported by the
|
||||
* underlying file store is not defined. It may or not fail by throwing an
|
||||
|
||||
@ -153,7 +153,7 @@ class UnixConstants {
|
||||
static final int PREFIX_CLONE_NOFOLLOW = CLONE_NOFOLLOW;
|
||||
static final int PREFIX_CLONE_NOOWNERCOPY = CLONE_NOOWNERCOPY;
|
||||
|
||||
// flags used with setattrlist
|
||||
// flags used with fsetattrlist
|
||||
static final int PREFIX_ATTR_CMN_CRTIME = ATTR_CMN_CRTIME;
|
||||
static final int PREFIX_ATTR_CMN_MODTIME = ATTR_CMN_MODTIME;
|
||||
static final int PREFIX_ATTR_CMN_ACCTIME = ATTR_CMN_ACCTIME;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user