Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/windows/classes/sun/nio/fs/WindowsChannelFactory.java
41139 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.io.FileDescriptor;
29
import java.io.IOException;
30
import java.nio.channels.AsynchronousFileChannel;
31
import java.nio.channels.FileChannel;
32
import java.nio.file.LinkOption;
33
import java.nio.file.OpenOption;
34
import java.nio.file.StandardOpenOption;
35
import java.util.Set;
36
37
import jdk.internal.access.JavaIOFileDescriptorAccess;
38
import jdk.internal.access.SharedSecrets;
39
import sun.nio.ch.FileChannelImpl;
40
import sun.nio.ch.ThreadPool;
41
import sun.nio.ch.WindowsAsynchronousFileChannelImpl;
42
43
import static sun.nio.fs.WindowsNativeDispatcher.*;
44
import static sun.nio.fs.WindowsConstants.*;
45
46
/**
47
* Factory to create FileChannels and AsynchronousFileChannels.
48
*/
49
50
class WindowsChannelFactory {
51
private static final JavaIOFileDescriptorAccess fdAccess =
52
SharedSecrets.getJavaIOFileDescriptorAccess();
53
54
private WindowsChannelFactory() { }
55
56
/**
57
* Do not follow reparse points when opening an existing file. Do not fail
58
* if the file is a reparse point.
59
*/
60
static final OpenOption OPEN_REPARSE_POINT = new OpenOption() { };
61
62
/**
63
* Represents the flags from a user-supplied set of open options.
64
*/
65
private static class Flags {
66
boolean read;
67
boolean write;
68
boolean append;
69
boolean truncateExisting;
70
boolean create;
71
boolean createNew;
72
boolean deleteOnClose;
73
boolean sparse;
74
boolean overlapped;
75
boolean sync;
76
boolean dsync;
77
boolean direct;
78
79
// non-standard
80
boolean shareRead = true;
81
boolean shareWrite = true;
82
boolean shareDelete = true;
83
boolean noFollowLinks;
84
boolean openReparsePoint;
85
86
static Flags toFlags(Set<? extends OpenOption> options) {
87
Flags flags = new Flags();
88
for (OpenOption option: options) {
89
if (option instanceof StandardOpenOption) {
90
switch ((StandardOpenOption)option) {
91
case READ : flags.read = true; break;
92
case WRITE : flags.write = true; break;
93
case APPEND : flags.append = true; break;
94
case TRUNCATE_EXISTING : flags.truncateExisting = true; break;
95
case CREATE : flags.create = true; break;
96
case CREATE_NEW : flags.createNew = true; break;
97
case DELETE_ON_CLOSE : flags.deleteOnClose = true; break;
98
case SPARSE : flags.sparse = true; break;
99
case SYNC : flags.sync = true; break;
100
case DSYNC : flags.dsync = true; break;
101
default: throw new UnsupportedOperationException();
102
}
103
continue;
104
}
105
if (option == LinkOption.NOFOLLOW_LINKS) {
106
flags.noFollowLinks = true;
107
continue;
108
}
109
if (option == OPEN_REPARSE_POINT) {
110
flags.openReparsePoint = true;
111
continue;
112
}
113
if (ExtendedOptions.NOSHARE_READ.matches(option)) {
114
flags.shareRead = false;
115
continue;
116
}
117
if (ExtendedOptions.NOSHARE_WRITE.matches(option)) {
118
flags.shareWrite = false;
119
continue;
120
}
121
if (ExtendedOptions.NOSHARE_DELETE.matches(option)) {
122
flags.shareDelete = false;
123
continue;
124
}
125
if (ExtendedOptions.DIRECT.matches(option)) {
126
flags.direct = true;
127
continue;
128
}
129
if (option == null)
130
throw new NullPointerException();
131
throw new UnsupportedOperationException();
132
}
133
return flags;
134
}
135
}
136
137
/**
138
* Open/creates file, returning FileChannel to access the file
139
*
140
* @param pathForWindows
141
* The path of the file to open/create
142
* @param pathToCheck
143
* The path used for permission checks (if security manager)
144
*/
145
static FileChannel newFileChannel(String pathForWindows,
146
String pathToCheck,
147
Set<? extends OpenOption> options,
148
long pSecurityDescriptor)
149
throws WindowsException
150
{
151
Flags flags = Flags.toFlags(options);
152
153
// default is reading; append => writing
154
if (!flags.read && !flags.write) {
155
if (flags.append) {
156
flags.write = true;
157
} else {
158
flags.read = true;
159
}
160
}
161
162
// validation
163
if (flags.read && flags.append)
164
throw new IllegalArgumentException("READ + APPEND not allowed");
165
if (flags.append && flags.truncateExisting)
166
throw new IllegalArgumentException("APPEND + TRUNCATE_EXISTING not allowed");
167
168
FileDescriptor fdObj = open(pathForWindows, pathToCheck, flags, pSecurityDescriptor);
169
return FileChannelImpl.open(fdObj, pathForWindows, flags.read,
170
flags.write, flags.direct, null);
171
}
172
173
/**
174
* Open/creates file, returning AsynchronousFileChannel to access the file
175
*
176
* @param pathForWindows
177
* The path of the file to open/create
178
* @param pathToCheck
179
* The path used for permission checks (if security manager)
180
* @param pool
181
* The thread pool that the channel is associated with
182
*/
183
static AsynchronousFileChannel newAsynchronousFileChannel(String pathForWindows,
184
String pathToCheck,
185
Set<? extends OpenOption> options,
186
long pSecurityDescriptor,
187
ThreadPool pool)
188
throws IOException
189
{
190
Flags flags = Flags.toFlags(options);
191
192
// Overlapped I/O required
193
flags.overlapped = true;
194
195
// default is reading
196
if (!flags.read && !flags.write) {
197
flags.read = true;
198
}
199
200
// validation
201
if (flags.append)
202
throw new UnsupportedOperationException("APPEND not allowed");
203
204
// open file for overlapped I/O
205
FileDescriptor fdObj;
206
try {
207
fdObj = open(pathForWindows, pathToCheck, flags, pSecurityDescriptor);
208
} catch (WindowsException x) {
209
x.rethrowAsIOException(pathForWindows);
210
return null;
211
}
212
213
// create the AsynchronousFileChannel
214
try {
215
return WindowsAsynchronousFileChannelImpl.open(fdObj, flags.read, flags.write, pool);
216
} catch (IOException x) {
217
// IOException is thrown if the file handle cannot be associated
218
// with the completion port. All we can do is close the file.
219
fdAccess.close(fdObj);
220
throw x;
221
}
222
}
223
224
/**
225
* Opens file based on parameters and options, returning a FileDescriptor
226
* encapsulating the handle to the open file.
227
*/
228
private static FileDescriptor open(String pathForWindows,
229
String pathToCheck,
230
Flags flags,
231
long pSecurityDescriptor)
232
throws WindowsException
233
{
234
// set to true if file must be truncated after open
235
boolean truncateAfterOpen = false;
236
237
// map options
238
int dwDesiredAccess = 0;
239
if (flags.read)
240
dwDesiredAccess |= GENERIC_READ;
241
if (flags.write)
242
dwDesiredAccess |= GENERIC_WRITE;
243
244
int dwShareMode = 0;
245
if (flags.shareRead)
246
dwShareMode |= FILE_SHARE_READ;
247
if (flags.shareWrite)
248
dwShareMode |= FILE_SHARE_WRITE;
249
if (flags.shareDelete)
250
dwShareMode |= FILE_SHARE_DELETE;
251
252
int dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
253
int dwCreationDisposition = OPEN_EXISTING;
254
if (flags.write) {
255
if (flags.createNew) {
256
dwCreationDisposition = CREATE_NEW;
257
// force create to fail if file is orphaned reparse point
258
dwFlagsAndAttributes |= FILE_FLAG_OPEN_REPARSE_POINT;
259
} else {
260
if (flags.create)
261
dwCreationDisposition = OPEN_ALWAYS;
262
if (flags.truncateExisting) {
263
// Windows doesn't have a creation disposition that exactly
264
// corresponds to CREATE + TRUNCATE_EXISTING so we use
265
// the OPEN_ALWAYS mode and then truncate the file.
266
if (dwCreationDisposition == OPEN_ALWAYS) {
267
truncateAfterOpen = true;
268
} else {
269
dwCreationDisposition = TRUNCATE_EXISTING;
270
}
271
}
272
}
273
}
274
275
if (flags.dsync || flags.sync)
276
dwFlagsAndAttributes |= FILE_FLAG_WRITE_THROUGH;
277
if (flags.overlapped)
278
dwFlagsAndAttributes |= FILE_FLAG_OVERLAPPED;
279
if (flags.deleteOnClose)
280
dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
281
282
// NOFOLLOW_LINKS and NOFOLLOW_REPARSEPOINT mean open reparse point
283
boolean okayToFollowLinks = true;
284
if (dwCreationDisposition != CREATE_NEW &&
285
(flags.noFollowLinks ||
286
flags.openReparsePoint ||
287
flags.deleteOnClose))
288
{
289
if (flags.noFollowLinks || flags.deleteOnClose)
290
okayToFollowLinks = false;
291
dwFlagsAndAttributes |= FILE_FLAG_OPEN_REPARSE_POINT;
292
}
293
294
// permission check
295
if (pathToCheck != null) {
296
@SuppressWarnings("removal")
297
SecurityManager sm = System.getSecurityManager();
298
if (sm != null) {
299
if (flags.read)
300
sm.checkRead(pathToCheck);
301
if (flags.write)
302
sm.checkWrite(pathToCheck);
303
if (flags.deleteOnClose)
304
sm.checkDelete(pathToCheck);
305
}
306
}
307
308
// open file
309
long handle = CreateFile(pathForWindows,
310
dwDesiredAccess,
311
dwShareMode,
312
pSecurityDescriptor,
313
dwCreationDisposition,
314
dwFlagsAndAttributes);
315
316
// make sure this isn't a symbolic link.
317
if (!okayToFollowLinks) {
318
try {
319
if (WindowsFileAttributes.readAttributes(handle).isSymbolicLink())
320
throw new WindowsException("File is symbolic link");
321
} catch (WindowsException x) {
322
CloseHandle(handle);
323
throw x;
324
}
325
}
326
327
// truncate file (for CREATE + TRUNCATE_EXISTING case)
328
if (truncateAfterOpen) {
329
try {
330
SetEndOfFile(handle);
331
} catch (WindowsException x) {
332
// ignore exception if file size is zero
333
if (GetFileSizeEx(handle) != 0) {
334
CloseHandle(handle);
335
throw x;
336
}
337
}
338
}
339
340
// make the file sparse if needed
341
if (dwCreationDisposition == CREATE_NEW && flags.sparse) {
342
try {
343
DeviceIoControlSetSparse(handle);
344
} catch (WindowsException x) {
345
// ignore as sparse option is hint
346
}
347
}
348
349
// create FileDescriptor and return
350
FileDescriptor fdObj = new FileDescriptor();
351
fdAccess.setHandle(fdObj, handle);
352
fdAccess.setAppend(fdObj, flags.append);
353
fdAccess.registerCleanup(fdObj);
354
return fdObj;
355
}
356
}
357
358