Skip to content

Commit 6397d56

Browse files
author
Brian Burkhalter
committed
8151430: (fs) BasicFileAttributeView.setTimes should support setting file create time on OS X
Reviewed-by: alanb
1 parent 57e0da1 commit 6397d56

File tree

7 files changed

+272
-18
lines changed

7 files changed

+272
-18
lines changed
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
/*
2+
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
26+
package sun.nio.fs;
27+
28+
import java.io.IOException;
29+
import java.nio.file.attribute.FileTime;
30+
import java.util.concurrent.TimeUnit;
31+
import static sun.nio.fs.BsdNativeDispatcher.setattrlist;
32+
33+
class BsdFileAttributeViews {
34+
//
35+
// Use setattrlist(2) system call which can set creation, modification,
36+
// and access times.
37+
//
38+
private static void setTimes(UnixPath path, FileTime lastModifiedTime,
39+
FileTime lastAccessTime, FileTime createTime,
40+
boolean followLinks) throws IOException
41+
{
42+
// null => don't change
43+
if (lastModifiedTime == null && lastAccessTime == null &&
44+
createTime == null) {
45+
// no effect
46+
return;
47+
}
48+
49+
// permission check
50+
path.checkWrite();
51+
52+
int commonattr = 0;
53+
long modValue = 0L;
54+
if (lastModifiedTime != null) {
55+
modValue = lastModifiedTime.to(TimeUnit.NANOSECONDS);
56+
commonattr |= UnixConstants.ATTR_CMN_MODTIME;
57+
}
58+
long accValue = 0L;
59+
if (lastAccessTime != null) {
60+
accValue = lastAccessTime.to(TimeUnit.NANOSECONDS);
61+
commonattr |= UnixConstants.ATTR_CMN_ACCTIME;
62+
}
63+
long createValue = 0L;
64+
if (createTime != null) {
65+
createValue = createTime.to(TimeUnit.NANOSECONDS);
66+
commonattr |= UnixConstants.ATTR_CMN_CRTIME;
67+
}
68+
69+
try {
70+
setattrlist(path, commonattr, modValue, accValue, createValue,
71+
followLinks ? 0 : UnixConstants.FSOPT_NOFOLLOW);
72+
} catch (UnixException x) {
73+
x.rethrowAsIOException(path);
74+
}
75+
}
76+
77+
static class Basic extends UnixFileAttributeViews.Basic {
78+
Basic(UnixPath file, boolean followLinks) {
79+
super(file, followLinks);
80+
}
81+
82+
@Override
83+
public void setTimes(FileTime lastModifiedTime,
84+
FileTime lastAccessTime,
85+
FileTime createTime) throws IOException
86+
{
87+
BsdFileAttributeViews.setTimes(file, lastModifiedTime,
88+
lastAccessTime, createTime,
89+
followLinks);
90+
}
91+
}
92+
93+
static class Posix extends UnixFileAttributeViews.Posix {
94+
Posix(UnixPath file, boolean followLinks) {
95+
super(file, followLinks);
96+
}
97+
98+
@Override
99+
public void setTimes(FileTime lastModifiedTime,
100+
FileTime lastAccessTime,
101+
FileTime createTime) throws IOException
102+
{
103+
BsdFileAttributeViews.setTimes(file, lastModifiedTime,
104+
lastAccessTime, createTime,
105+
followLinks);
106+
}
107+
}
108+
109+
static class Unix extends UnixFileAttributeViews.Unix {
110+
Unix(UnixPath file, boolean followLinks) {
111+
super(file, followLinks);
112+
}
113+
114+
@Override
115+
public void setTimes(FileTime lastModifiedTime,
116+
FileTime lastAccessTime,
117+
FileTime createTime) throws IOException
118+
{
119+
BsdFileAttributeViews.setTimes(file, lastModifiedTime,
120+
lastAccessTime, createTime,
121+
followLinks);
122+
}
123+
}
124+
125+
static Basic createBasicView(UnixPath file, boolean followLinks) {
126+
return new Basic(file, followLinks);
127+
}
128+
129+
static Posix createPosixView(UnixPath file, boolean followLinks) {
130+
return new Posix(file, followLinks);
131+
}
132+
133+
static Unix createUnixView(UnixPath file, boolean followLinks) {
134+
return new Unix(file, followLinks);
135+
}
136+
}

src/java.base/macosx/classes/sun/nio/fs/BsdFileSystemProvider.java

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -54,10 +54,23 @@ public <V extends FileAttributeView> V getFileAttributeView(Path obj,
5454
Class<V> type,
5555
LinkOption... options)
5656
{
57-
if (type == UserDefinedFileAttributeView.class) {
58-
return (V) new BsdUserDefinedFileAttributeView(UnixPath.toUnixPath(obj),
59-
Util.followLinks(options));
57+
if (type == BasicFileAttributeView.class ||
58+
type == PosixFileAttributeView.class ||
59+
type == UserDefinedFileAttributeView.class) {
60+
61+
UnixPath file = UnixPath.toUnixPath(obj);
62+
boolean followLinks = Util.followLinks(options);
63+
64+
if (type == BasicFileAttributeView.class)
65+
return (V) BsdFileAttributeViews.createBasicView(file,
66+
followLinks);
67+
else if (type == PosixFileAttributeView.class)
68+
return (V) BsdFileAttributeViews.createPosixView(file,
69+
followLinks);
70+
// user-defined is the only possibility
71+
return (V) new BsdUserDefinedFileAttributeView(file, followLinks);
6072
}
73+
6174
return super.getFileAttributeView(obj, type, options);
6275
}
6376

@@ -66,10 +79,25 @@ public DynamicFileAttributeView getFileAttributeView(Path obj,
6679
String name,
6780
LinkOption... options)
6881
{
69-
if (name.equals("user")) {
70-
return new BsdUserDefinedFileAttributeView(UnixPath.toUnixPath(obj),
71-
Util.followLinks(options));
82+
if (name.equals("basic") || name.equals("posix") ||
83+
name.equals("unix") || name.equals("user")) {
84+
85+
UnixPath file = UnixPath.toUnixPath(obj);
86+
boolean followLinks = Util.followLinks(options);
87+
88+
if (name.equals("basic"))
89+
return BsdFileAttributeViews.createBasicView(file, followLinks);
90+
91+
if (name.equals("posix"))
92+
return BsdFileAttributeViews.createPosixView(file, followLinks);
93+
94+
if (name.equals("unix"))
95+
return BsdFileAttributeViews.createUnixView(file, followLinks);
96+
97+
// user-defined is the only possibility
98+
return new BsdUserDefinedFileAttributeView(file, followLinks);
7299
}
100+
73101
return super.getFileAttributeView(obj, name, options);
74102
}
75103
}

src/java.base/macosx/classes/sun/nio/fs/BsdNativeDispatcher.java

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,8 @@
2525

2626
package sun.nio.fs;
2727

28+
import jdk.internal.misc.Blocker;
29+
2830
/**
2931
* Bsd specific system calls.
3032
*/
@@ -62,6 +64,29 @@ static byte[] getmntonname(UnixPath path) throws UnixException {
6264
}
6365
static native byte[] getmntonname0(long pathAddress) throws UnixException;
6466

67+
/**
68+
* setattrlist(const char* path, struct attrlist* attrList, void* attrBuf,
69+
* size_t attrBufSize, unsigned long options)
70+
*/
71+
static void setattrlist(UnixPath path, int commonattr, long modTime,
72+
long accTime, long createTime, long options)
73+
throws UnixException
74+
{
75+
try (NativeBuffer buffer = copyToNativeBuffer(path)) {
76+
long comp = Blocker.begin();
77+
try {
78+
setattrlist0(buffer.address(), commonattr, modTime, accTime,
79+
createTime, options);
80+
} finally {
81+
Blocker.end(comp);
82+
}
83+
}
84+
}
85+
private static native void setattrlist0(long pathAddress, int commonattr,
86+
long modTime, long accTime,
87+
long createTime, long options)
88+
throws UnixException;
89+
6590
// initialize field IDs
6691
private static native void initIDs();
6792

src/java.base/macosx/native/libnio/fs/BsdNativeDispatcher.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#else
3939
#define ISREADONLY MNT_RDONLY
4040
#endif
41+
#include <sys/attr.h>
4142

4243
#include <stdlib.h>
4344
#include <string.h>
@@ -223,3 +224,44 @@ Java_sun_nio_fs_BsdNativeDispatcher_getmntonname0(JNIEnv *env, jclass this,
223224

224225
return mntonname;
225226
}
227+
228+
JNIEXPORT void JNICALL
229+
Java_sun_nio_fs_BsdNativeDispatcher_setattrlist0(JNIEnv* env, jclass this,
230+
jlong pathAddress, int commonattr, jlong modTime, jlong accTime,
231+
jlong createTime, jlong options)
232+
{
233+
const char* path = (const char*)jlong_to_ptr(pathAddress);
234+
// attributes must align on 4-byte boundaries per the getattrlist(2) spec
235+
const int attrsize = ((sizeof(struct timespec) + 3)/4)*4;
236+
char buf[3*attrsize];
237+
238+
int count = 0;
239+
// attributes are ordered per the getattrlist(2) spec
240+
if ((commonattr & ATTR_CMN_CRTIME) != 0) {
241+
struct timespec* t = (struct timespec*)buf;
242+
t->tv_sec = createTime / 1000000000;
243+
t->tv_nsec = createTime % 1000000000;
244+
count++;
245+
}
246+
if ((commonattr & ATTR_CMN_MODTIME) != 0) {
247+
struct timespec* t = (struct timespec*)(buf + count*attrsize);
248+
t->tv_sec = modTime / 1000000000;
249+
t->tv_nsec = modTime % 1000000000;
250+
count++;
251+
}
252+
if ((commonattr & ATTR_CMN_ACCTIME) != 0) {
253+
struct timespec* t = (struct timespec*)(buf + count*attrsize);
254+
t->tv_sec = accTime / 1000000000;
255+
t->tv_nsec = accTime % 1000000000;
256+
count++;
257+
}
258+
259+
struct attrlist attrList;
260+
memset(&attrList, 0, sizeof(struct attrlist));
261+
attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
262+
attrList.commonattr = commonattr;
263+
264+
if (setattrlist(path, &attrList, (void*)buf, count*attrsize, options) != 0) {
265+
throwUnixException(env, errno);
266+
}
267+
}

src/java.base/unix/classes/sun/nio/fs/UnixConstants.java.template

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -30,6 +30,9 @@
3030
#include <unistd.h>
3131
#include <fcntl.h>
3232
#include <sys/stat.h>
33+
#ifdef _ALLBSD_SOURCE
34+
#include <sys/attr.h>
35+
#endif
3336

3437
/* To be able to name the Java constants the same as the C constants without
3538
having the preprocessor rewrite those identifiers, add PREFIX_ to all
@@ -140,4 +143,17 @@ class UnixConstants {
140143
static final int PREFIX_AT_REMOVEDIR = 00;
141144
#endif
142145

146+
// flags used with setattrlist
147+
#ifdef _ALLBSD_SOURCE
148+
static final int PREFIX_ATTR_CMN_CRTIME = ATTR_CMN_CRTIME;
149+
static final int PREFIX_ATTR_CMN_MODTIME = ATTR_CMN_MODTIME;
150+
static final int PREFIX_ATTR_CMN_ACCTIME = ATTR_CMN_ACCTIME;
151+
static final int PREFIX_FSOPT_NOFOLLOW = FSOPT_NOFOLLOW;
152+
#else
153+
// not supported (dummy values will not be used at runtime).
154+
static final int PREFIX_ATTR_CMN_CRTIME = 00;
155+
static final int PREFIX_ATTR_CMN_MODTIME = 00;
156+
static final int PREFIX_ATTR_CMN_ACCTIME = 00;
157+
static final int PREFIX_FSOPT_NOFOLLOW = 00;
158+
#endif
143159
}

src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ public void setTimes(FileTime lastModifiedTime,
165165
}
166166
}
167167

168-
private static class Posix extends Basic implements PosixFileAttributeView {
168+
static class Posix extends Basic implements PosixFileAttributeView {
169169
private static final String PERMISSIONS_NAME = "permissions";
170170
private static final String OWNER_NAME = "owner";
171171
private static final String GROUP_NAME = "group";
@@ -331,7 +331,7 @@ public void setGroup(GroupPrincipal group)
331331
}
332332
}
333333

334-
private static class Unix extends Posix {
334+
static class Unix extends Posix {
335335
private static final String MODE_NAME = "mode";
336336
private static final String INO_NAME = "ino";
337337
private static final String DEV_NAME = "dev";

0 commit comments

Comments
 (0)