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