Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/classes/sun/nio/fs/UnixChannelFactory.java
32288 views
1
/*
2
* Copyright (c) 2008, 2013, 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.nio.file.*;
29
import java.nio.channels.*;
30
import java.io.FileDescriptor;
31
import java.util.Set;
32
33
import sun.nio.ch.FileChannelImpl;
34
import sun.nio.ch.ThreadPool;
35
import sun.nio.ch.SimpleAsynchronousFileChannelImpl;
36
import sun.misc.SharedSecrets;
37
import sun.misc.JavaIOFileDescriptorAccess;
38
39
import static sun.nio.fs.UnixNativeDispatcher.*;
40
import static sun.nio.fs.UnixConstants.*;
41
42
/**
43
* Factory for FileChannels and AsynchronousFileChannels
44
*/
45
46
class UnixChannelFactory {
47
private static final JavaIOFileDescriptorAccess fdAccess =
48
SharedSecrets.getJavaIOFileDescriptorAccess();
49
50
protected UnixChannelFactory() {
51
}
52
53
/**
54
* Represents the flags from a user-supplied set of open options.
55
*/
56
protected static class Flags {
57
boolean read;
58
boolean write;
59
boolean append;
60
boolean truncateExisting;
61
boolean noFollowLinks;
62
boolean create;
63
boolean createNew;
64
boolean deleteOnClose;
65
boolean sync;
66
boolean dsync;
67
68
static Flags toFlags(Set<? extends OpenOption> options) {
69
Flags flags = new Flags();
70
for (OpenOption option: options) {
71
if (option instanceof StandardOpenOption) {
72
switch ((StandardOpenOption)option) {
73
case READ : flags.read = true; break;
74
case WRITE : flags.write = true; break;
75
case APPEND : flags.append = true; break;
76
case TRUNCATE_EXISTING : flags.truncateExisting = true; break;
77
case CREATE : flags.create = true; break;
78
case CREATE_NEW : flags.createNew = true; break;
79
case DELETE_ON_CLOSE : flags.deleteOnClose = true; break;
80
case SPARSE : /* ignore */ break;
81
case SYNC : flags.sync = true; break;
82
case DSYNC : flags.dsync = true; break;
83
default: throw new UnsupportedOperationException();
84
}
85
continue;
86
}
87
if (option == LinkOption.NOFOLLOW_LINKS && O_NOFOLLOW != 0) {
88
flags.noFollowLinks = true;
89
continue;
90
}
91
if (option == null)
92
throw new NullPointerException();
93
throw new UnsupportedOperationException(option + " not supported");
94
}
95
return flags;
96
}
97
}
98
99
100
/**
101
* Constructs a file channel from an existing (open) file descriptor
102
*/
103
static FileChannel newFileChannel(int fd, String path, boolean reading, boolean writing) {
104
FileDescriptor fdObj = new FileDescriptor();
105
fdAccess.set(fdObj, fd);
106
return FileChannelImpl.open(fdObj, path, reading, writing, null);
107
}
108
109
/**
110
* Constructs a file channel by opening a file using a dfd/path pair
111
*/
112
static FileChannel newFileChannel(int dfd,
113
UnixPath path,
114
String pathForPermissionCheck,
115
Set<? extends OpenOption> options,
116
int mode)
117
throws UnixException
118
{
119
Flags flags = Flags.toFlags(options);
120
121
// default is reading; append => writing
122
if (!flags.read && !flags.write) {
123
if (flags.append) {
124
flags.write = true;
125
} else {
126
flags.read = true;
127
}
128
}
129
130
// validation
131
if (flags.read && flags.append)
132
throw new IllegalArgumentException("READ + APPEND not allowed");
133
if (flags.append && flags.truncateExisting)
134
throw new IllegalArgumentException("APPEND + TRUNCATE_EXISTING not allowed");
135
136
FileDescriptor fdObj = open(dfd, path, pathForPermissionCheck, flags, mode);
137
return FileChannelImpl.open(fdObj, path.toString(), flags.read, flags.write, flags.append, null);
138
}
139
140
/**
141
* Constructs a file channel by opening the given file.
142
*/
143
static FileChannel newFileChannel(UnixPath path,
144
Set<? extends OpenOption> options,
145
int mode)
146
throws UnixException
147
{
148
return newFileChannel(-1, path, null, options, mode);
149
}
150
151
/**
152
* Constructs an asynchronous file channel by opening the given file.
153
*/
154
static AsynchronousFileChannel newAsynchronousFileChannel(UnixPath path,
155
Set<? extends OpenOption> options,
156
int mode,
157
ThreadPool pool)
158
throws UnixException
159
{
160
Flags flags = Flags.toFlags(options);
161
162
// default is reading
163
if (!flags.read && !flags.write) {
164
flags.read = true;
165
}
166
167
// validation
168
if (flags.append)
169
throw new UnsupportedOperationException("APPEND not allowed");
170
171
// for now use simple implementation
172
FileDescriptor fdObj = open(-1, path, null, flags, mode);
173
return SimpleAsynchronousFileChannelImpl.open(fdObj, flags.read, flags.write, pool);
174
}
175
176
/**
177
* Opens file based on parameters and options, returning a FileDescriptor
178
* encapsulating the handle to the open file.
179
*/
180
protected static FileDescriptor open(int dfd,
181
UnixPath path,
182
String pathForPermissionCheck,
183
Flags flags,
184
int mode)
185
throws UnixException
186
{
187
// map to oflags
188
int oflags;
189
if (flags.read && flags.write) {
190
oflags = O_RDWR;
191
} else {
192
oflags = (flags.write) ? O_WRONLY : O_RDONLY;
193
}
194
if (flags.write) {
195
if (flags.truncateExisting)
196
oflags |= O_TRUNC;
197
if (flags.append)
198
oflags |= O_APPEND;
199
200
// create flags
201
if (flags.createNew) {
202
byte[] pathForSysCall = path.asByteArray();
203
204
// throw exception if file name is "." to avoid confusing error
205
if ((pathForSysCall[pathForSysCall.length-1] == '.') &&
206
(pathForSysCall.length == 1 ||
207
(pathForSysCall[pathForSysCall.length-2] == '/')))
208
{
209
throw new UnixException(EEXIST);
210
}
211
oflags |= (O_CREAT | O_EXCL);
212
} else {
213
if (flags.create)
214
oflags |= O_CREAT;
215
}
216
}
217
218
// follow links by default
219
boolean followLinks = true;
220
if (!flags.createNew && (flags.noFollowLinks || flags.deleteOnClose)) {
221
if (flags.deleteOnClose && O_NOFOLLOW == 0) {
222
try {
223
if (UnixFileAttributes.get(path, false).isSymbolicLink())
224
throw new UnixException("DELETE_ON_CLOSE specified and file is a symbolic link");
225
} catch (UnixException x) {
226
if (!flags.create || x.errno() != ENOENT)
227
throw x;
228
}
229
}
230
followLinks = false;
231
oflags |= O_NOFOLLOW;
232
}
233
234
if (flags.dsync)
235
oflags |= O_DSYNC;
236
if (flags.sync)
237
oflags |= O_SYNC;
238
239
// permission check before we open the file
240
SecurityManager sm = System.getSecurityManager();
241
if (sm != null) {
242
if (pathForPermissionCheck == null)
243
pathForPermissionCheck = path.getPathForPermissionCheck();
244
if (flags.read)
245
sm.checkRead(pathForPermissionCheck);
246
if (flags.write)
247
sm.checkWrite(pathForPermissionCheck);
248
if (flags.deleteOnClose)
249
sm.checkDelete(pathForPermissionCheck);
250
}
251
252
int fd;
253
try {
254
if (dfd >= 0) {
255
fd = openat(dfd, path.asByteArray(), oflags, mode);
256
} else {
257
fd = UnixNativeDispatcher.open(path, oflags, mode);
258
}
259
} catch (UnixException x) {
260
// Linux error can be EISDIR or EEXIST when file exists
261
if (flags.createNew && (x.errno() == EISDIR)) {
262
x.setError(EEXIST);
263
}
264
265
// handle ELOOP to avoid confusing message
266
if (!followLinks && (x.errno() == ELOOP)) {
267
x = new UnixException(x.getMessage() + " (NOFOLLOW_LINKS specified)");
268
}
269
270
throw x;
271
}
272
273
// unlink file immediately if delete on close. The spec is clear that
274
// an implementation cannot guarantee to unlink the correct file when
275
// replaced by an attacker after it is opened.
276
if (flags.deleteOnClose) {
277
try {
278
if (dfd >= 0) {
279
unlinkat(dfd, path.asByteArray(), 0);
280
} else {
281
unlink(path);
282
}
283
} catch (UnixException ignore) {
284
// best-effort
285
}
286
}
287
288
// create java.io.FileDescriptor
289
FileDescriptor fdObj = new FileDescriptor();
290
fdAccess.set(fdObj, fd);
291
return fdObj;
292
}
293
}
294
295