Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/windows/classes/sun/nio/fs/WindowsUserDefinedFileAttributeView.java
32288 views
1
/*
2
* Copyright (c) 2008, 2011, 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 static java.nio.file.StandardOpenOption.*;
30
import java.nio.ByteBuffer;
31
import java.nio.channels.FileChannel;
32
import java.io.IOException;
33
import java.util.*;
34
import sun.misc.Unsafe;
35
36
import static sun.nio.fs.WindowsNativeDispatcher.*;
37
import static sun.nio.fs.WindowsConstants.*;
38
39
/**
40
* Windows emulation of NamedAttributeView using Alternative Data Streams
41
*/
42
43
class WindowsUserDefinedFileAttributeView
44
extends AbstractUserDefinedFileAttributeView
45
{
46
private static final Unsafe unsafe = Unsafe.getUnsafe();
47
48
// syntax to address named streams
49
private String join(String file, String name) {
50
if (name == null)
51
throw new NullPointerException("'name' is null");
52
return file + ":" + name;
53
}
54
private String join(WindowsPath file, String name) throws WindowsException {
55
return join(file.getPathForWin32Calls(), name);
56
}
57
58
private final WindowsPath file;
59
private final boolean followLinks;
60
61
WindowsUserDefinedFileAttributeView(WindowsPath file, boolean followLinks) {
62
this.file = file;
63
this.followLinks = followLinks;
64
}
65
66
// enumerates the file streams using FindFirstStream/FindNextStream APIs.
67
private List<String> listUsingStreamEnumeration() throws IOException {
68
List<String> list = new ArrayList<>();
69
try {
70
FirstStream first = FindFirstStream(file.getPathForWin32Calls());
71
if (first != null) {
72
long handle = first.handle();
73
try {
74
// first stream is always ::$DATA for files
75
String name = first.name();
76
if (!name.equals("::$DATA")) {
77
String[] segs = name.split(":");
78
list.add(segs[1]);
79
}
80
while ((name = FindNextStream(handle)) != null) {
81
String[] segs = name.split(":");
82
list.add(segs[1]);
83
}
84
} finally {
85
FindClose(handle);
86
}
87
}
88
} catch (WindowsException x) {
89
x.rethrowAsIOException(file);
90
}
91
return Collections.unmodifiableList(list);
92
}
93
94
// enumerates the file streams by reading the stream headers using
95
// BackupRead
96
private List<String> listUsingBackupRead() throws IOException {
97
long handle = -1L;
98
try {
99
int flags = FILE_FLAG_BACKUP_SEMANTICS;
100
if (!followLinks && file.getFileSystem().supportsLinks())
101
flags |= FILE_FLAG_OPEN_REPARSE_POINT;
102
103
handle = CreateFile(file.getPathForWin32Calls(),
104
GENERIC_READ,
105
FILE_SHARE_READ, // no write as we depend on file size
106
OPEN_EXISTING,
107
flags);
108
} catch (WindowsException x) {
109
x.rethrowAsIOException(file);
110
}
111
112
// buffer to read stream header and stream name.
113
final int BUFFER_SIZE = 4096;
114
NativeBuffer buffer = null;
115
116
// result with names of alternative data streams
117
final List<String> list = new ArrayList<>();
118
119
try {
120
buffer = NativeBuffers.getNativeBuffer(BUFFER_SIZE);
121
long address = buffer.address();
122
123
/**
124
* typedef struct _WIN32_STREAM_ID {
125
* DWORD dwStreamId;
126
* DWORD dwStreamAttributes;
127
* LARGE_INTEGER Size;
128
* DWORD dwStreamNameSize;
129
* WCHAR cStreamName[ANYSIZE_ARRAY];
130
* } WIN32_STREAM_ID;
131
*/
132
final int SIZEOF_STREAM_HEADER = 20;
133
final int OFFSETOF_STREAM_ID = 0;
134
final int OFFSETOF_STREAM_SIZE = 8;
135
final int OFFSETOF_STREAM_NAME_SIZE = 16;
136
137
long context = 0L;
138
try {
139
for (;;) {
140
// read stream header
141
BackupResult result = BackupRead(handle, address,
142
SIZEOF_STREAM_HEADER, false, context);
143
context = result.context();
144
if (result.bytesTransferred() == 0)
145
break;
146
147
int streamId = unsafe.getInt(address + OFFSETOF_STREAM_ID);
148
long streamSize = unsafe.getLong(address + OFFSETOF_STREAM_SIZE);
149
int nameSize = unsafe.getInt(address + OFFSETOF_STREAM_NAME_SIZE);
150
151
// read stream name
152
if (nameSize > 0) {
153
result = BackupRead(handle, address, nameSize, false, context);
154
if (result.bytesTransferred() != nameSize)
155
break;
156
}
157
158
// check for alternative data stream
159
if (streamId == BACKUP_ALTERNATE_DATA) {
160
char[] nameAsArray = new char[nameSize/2];
161
unsafe.copyMemory(null, address, nameAsArray,
162
Unsafe.ARRAY_CHAR_BASE_OFFSET, nameSize);
163
164
String[] segs = new String(nameAsArray).split(":");
165
if (segs.length == 3)
166
list.add(segs[1]);
167
}
168
169
// sparse blocks not currently handled as documentation
170
// is not sufficient on how the spase block can be skipped.
171
if (streamId == BACKUP_SPARSE_BLOCK) {
172
throw new IOException("Spare blocks not handled");
173
}
174
175
// seek to end of stream
176
if (streamSize > 0L) {
177
BackupSeek(handle, streamSize, context);
178
}
179
}
180
} catch (WindowsException x) {
181
// failed to read or seek
182
throw new IOException(x.errorString());
183
} finally {
184
// release context
185
if (context != 0L) {
186
try {
187
BackupRead(handle, 0L, 0, true, context);
188
} catch (WindowsException ignore) { }
189
}
190
}
191
} finally {
192
if (buffer != null)
193
buffer.release();
194
CloseHandle(handle);
195
}
196
return Collections.unmodifiableList(list);
197
}
198
199
@Override
200
public List<String> list() throws IOException {
201
if (System.getSecurityManager() != null)
202
checkAccess(file.getPathForPermissionCheck(), true, false);
203
// use stream APIs on Windwos Server 2003 and newer
204
if (file.getFileSystem().supportsStreamEnumeration()) {
205
return listUsingStreamEnumeration();
206
} else {
207
return listUsingBackupRead();
208
}
209
}
210
211
@Override
212
public int size(String name) throws IOException {
213
if (System.getSecurityManager() != null)
214
checkAccess(file.getPathForPermissionCheck(), true, false);
215
216
// wrap with channel
217
FileChannel fc = null;
218
try {
219
Set<OpenOption> opts = new HashSet<>();
220
opts.add(READ);
221
if (!followLinks)
222
opts.add(WindowsChannelFactory.OPEN_REPARSE_POINT);
223
fc = WindowsChannelFactory
224
.newFileChannel(join(file, name), null, opts, 0L);
225
} catch (WindowsException x) {
226
x.rethrowAsIOException(join(file.getPathForPermissionCheck(), name));
227
}
228
try {
229
long size = fc.size();
230
if (size > Integer.MAX_VALUE)
231
throw new ArithmeticException("Stream too large");
232
return (int)size;
233
} finally {
234
fc.close();
235
}
236
}
237
238
@Override
239
public int read(String name, ByteBuffer dst) throws IOException {
240
if (System.getSecurityManager() != null)
241
checkAccess(file.getPathForPermissionCheck(), true, false);
242
243
// wrap with channel
244
FileChannel fc = null;
245
try {
246
Set<OpenOption> opts = new HashSet<>();
247
opts.add(READ);
248
if (!followLinks)
249
opts.add(WindowsChannelFactory.OPEN_REPARSE_POINT);
250
fc = WindowsChannelFactory
251
.newFileChannel(join(file, name), null, opts, 0L);
252
} catch (WindowsException x) {
253
x.rethrowAsIOException(join(file.getPathForPermissionCheck(), name));
254
}
255
256
// read to EOF (nothing we can do if I/O error occurs)
257
try {
258
if (fc.size() > dst.remaining())
259
throw new IOException("Stream too large");
260
int total = 0;
261
while (dst.hasRemaining()) {
262
int n = fc.read(dst);
263
if (n < 0)
264
break;
265
total += n;
266
}
267
return total;
268
} finally {
269
fc.close();
270
}
271
}
272
273
@Override
274
public int write(String name, ByteBuffer src) throws IOException {
275
if (System.getSecurityManager() != null)
276
checkAccess(file.getPathForPermissionCheck(), false, true);
277
278
/**
279
* Creating a named stream will cause the unnamed stream to be created
280
* if it doesn't already exist. To avoid this we open the unnamed stream
281
* for reading and hope it isn't deleted/moved while we create or
282
* replace the named stream. Opening the file without sharing options
283
* may cause sharing violations with other programs that are accessing
284
* the unnamed stream.
285
*/
286
long handle = -1L;
287
try {
288
int flags = FILE_FLAG_BACKUP_SEMANTICS;
289
if (!followLinks)
290
flags |= FILE_FLAG_OPEN_REPARSE_POINT;
291
292
handle = CreateFile(file.getPathForWin32Calls(),
293
GENERIC_READ,
294
(FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE),
295
OPEN_EXISTING,
296
flags);
297
} catch (WindowsException x) {
298
x.rethrowAsIOException(file);
299
}
300
try {
301
Set<OpenOption> opts = new HashSet<>();
302
if (!followLinks)
303
opts.add(WindowsChannelFactory.OPEN_REPARSE_POINT);
304
opts.add(CREATE);
305
opts.add(WRITE);
306
opts.add(StandardOpenOption.TRUNCATE_EXISTING);
307
FileChannel named = null;
308
try {
309
named = WindowsChannelFactory
310
.newFileChannel(join(file, name), null, opts, 0L);
311
} catch (WindowsException x) {
312
x.rethrowAsIOException(join(file.getPathForPermissionCheck(), name));
313
}
314
// write value (nothing we can do if I/O error occurs)
315
try {
316
int rem = src.remaining();
317
while (src.hasRemaining()) {
318
named.write(src);
319
}
320
return rem;
321
} finally {
322
named.close();
323
}
324
} finally {
325
CloseHandle(handle);
326
}
327
}
328
329
@Override
330
public void delete(String name) throws IOException {
331
if (System.getSecurityManager() != null)
332
checkAccess(file.getPathForPermissionCheck(), false, true);
333
334
String path = WindowsLinkSupport.getFinalPath(file, followLinks);
335
String toDelete = join(path, name);
336
try {
337
DeleteFile(toDelete);
338
} catch (WindowsException x) {
339
x.rethrowAsIOException(toDelete);
340
}
341
}
342
}
343
344