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/UnixUserDefinedFileAttributeView.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.lang.ref.Reference;
29
import java.nio.file.*;
30
import java.nio.ByteBuffer;
31
import java.io.IOException;
32
import java.util.*;
33
import jdk.internal.misc.Unsafe;
34
35
import static sun.nio.fs.UnixConstants.*;
36
import static sun.nio.fs.UnixNativeDispatcher.*;
37
38
/**
39
* Unix implementation of UserDefinedFileAttributeView using extended attributes.
40
*/
41
abstract class UnixUserDefinedFileAttributeView
42
extends AbstractUserDefinedFileAttributeView
43
{
44
private static final Unsafe unsafe = Unsafe.getUnsafe();
45
46
// namespace for extended user attributes
47
private static final String USER_NAMESPACE = "user.";
48
49
private static final int MIN_LISTXATTR_BUF_SIZE = 1024;
50
private static final int MAX_LISTXATTR_BUF_SIZE = 32 * 1024;
51
52
private final UnixPath file;
53
private final boolean followLinks;
54
55
UnixUserDefinedFileAttributeView(UnixPath file, boolean followLinks) {
56
this.file = file;
57
this.followLinks = followLinks;
58
}
59
60
private byte[] nameAsBytes(UnixPath file, String name) throws IOException {
61
if (name == null)
62
throw new NullPointerException("'name' is null");
63
name = USER_NAMESPACE + name;
64
byte[] bytes = Util.toBytes(name);
65
if (bytes.length > maxNameLength()) {
66
throw new FileSystemException(file.getPathForExceptionMessage(),
67
null, "'" + name + "' is too big");
68
}
69
return bytes;
70
}
71
72
/**
73
* @return the maximum supported length of xattr names (in bytes, including namespace)
74
*/
75
protected abstract int maxNameLength();
76
77
// Parses buffer as array of NULL-terminated C strings.
78
private static List<String> asList(long address, int size) {
79
List<String> list = new ArrayList<>();
80
int start = 0;
81
int pos = 0;
82
while (pos < size) {
83
if (unsafe.getByte(address + pos) == 0) {
84
int len = pos - start;
85
byte[] value = new byte[len];
86
unsafe.copyMemory(null, address+start, value,
87
Unsafe.ARRAY_BYTE_BASE_OFFSET, len);
88
String s = Util.toString(value);
89
list.add(s);
90
start = pos + 1;
91
}
92
pos++;
93
}
94
return list;
95
}
96
97
// runs flistxattr, increases buffer size up to MAX_LISTXATTR_BUF_SIZE if required
98
private static List<String> list(int fd, int bufSize) throws UnixException {
99
try {
100
try (NativeBuffer buffer = NativeBuffers.getNativeBuffer(bufSize)) {
101
int n = flistxattr(fd, buffer.address(), bufSize);
102
return asList(buffer.address(), n);
103
} // release buffer before recursion
104
} catch (UnixException x) {
105
if (x.errno() == ERANGE && bufSize < MAX_LISTXATTR_BUF_SIZE) {
106
return list(fd, bufSize * 2); // try larger buffer size:
107
} else {
108
throw x;
109
}
110
}
111
}
112
113
@SuppressWarnings("removal")
114
@Override
115
public List<String> list() throws IOException {
116
if (System.getSecurityManager() != null)
117
checkAccess(file.getPathForPermissionCheck(), true, false);
118
119
int fd = -1;
120
try {
121
fd = file.openForAttributeAccess(followLinks);
122
} catch (UnixException x) {
123
x.rethrowAsIOException(file);
124
}
125
try {
126
List<String> attrNames = list(fd, MIN_LISTXATTR_BUF_SIZE);
127
return attrNames.stream()
128
.filter(s -> s.startsWith(USER_NAMESPACE))
129
.map(s -> s.substring(USER_NAMESPACE.length()))
130
.toList();
131
} catch (UnixException x) {
132
throw new FileSystemException(file.getPathForExceptionMessage(),
133
null, "Unable to get list of extended attributes: " +
134
x.getMessage());
135
} finally {
136
close(fd);
137
}
138
}
139
140
@SuppressWarnings("removal")
141
@Override
142
public int size(String name) throws IOException {
143
if (System.getSecurityManager() != null)
144
checkAccess(file.getPathForPermissionCheck(), true, false);
145
146
int fd = -1;
147
try {
148
fd = file.openForAttributeAccess(followLinks);
149
} catch (UnixException x) {
150
x.rethrowAsIOException(file);
151
}
152
try {
153
// fgetxattr returns size if called with size==0
154
return fgetxattr(fd, nameAsBytes(file,name), 0L, 0);
155
} catch (UnixException x) {
156
throw new FileSystemException(file.getPathForExceptionMessage(),
157
null, "Unable to get size of extended attribute '" + name +
158
"': " + x.getMessage());
159
} finally {
160
close(fd);
161
}
162
}
163
164
@SuppressWarnings("removal")
165
@Override
166
public int read(String name, ByteBuffer dst) throws IOException {
167
if (System.getSecurityManager() != null)
168
checkAccess(file.getPathForPermissionCheck(), true, false);
169
170
if (dst.isReadOnly())
171
throw new IllegalArgumentException("Read-only buffer");
172
int pos = dst.position();
173
int lim = dst.limit();
174
assert (pos <= lim);
175
int rem = (pos <= lim ? lim - pos : 0);
176
177
if (dst instanceof sun.nio.ch.DirectBuffer buf) {
178
try {
179
long address = buf.address() + pos;
180
int n = read(name, address, rem);
181
dst.position(pos + n);
182
return n;
183
} finally {
184
Reference.reachabilityFence(buf);
185
}
186
} else {
187
try (NativeBuffer nb = NativeBuffers.getNativeBuffer(rem)) {
188
long address = nb.address();
189
int n = read(name, address, rem);
190
191
// copy from buffer into backing array
192
int off = dst.arrayOffset() + pos + Unsafe.ARRAY_BYTE_BASE_OFFSET;
193
unsafe.copyMemory(null, address, dst.array(), off, n);
194
dst.position(pos + n);
195
196
return n;
197
}
198
}
199
}
200
201
private int read(String name, long address, int rem) throws IOException {
202
int fd = -1;
203
try {
204
fd = file.openForAttributeAccess(followLinks);
205
} catch (UnixException x) {
206
x.rethrowAsIOException(file);
207
}
208
try {
209
int n = fgetxattr(fd, nameAsBytes(file, name), address, rem);
210
211
// if remaining is zero then fgetxattr returns the size
212
if (rem == 0) {
213
if (n > 0)
214
throw new UnixException(ERANGE);
215
return 0;
216
}
217
return n;
218
} catch (UnixException x) {
219
String msg = (x.errno() == ERANGE) ?
220
"Insufficient space in buffer" : x.getMessage();
221
throw new FileSystemException(file.getPathForExceptionMessage(),
222
null, "Error reading extended attribute '" + name + "': " + msg);
223
} finally {
224
close(fd);
225
}
226
}
227
228
@SuppressWarnings("removal")
229
@Override
230
public int write(String name, ByteBuffer src) throws IOException {
231
if (System.getSecurityManager() != null)
232
checkAccess(file.getPathForPermissionCheck(), false, true);
233
234
int pos = src.position();
235
int lim = src.limit();
236
assert (pos <= lim);
237
int rem = (pos <= lim ? lim - pos : 0);
238
239
if (src instanceof sun.nio.ch.DirectBuffer buf) {
240
try {
241
long address = buf.address() + pos;
242
write(name, address, rem);
243
src.position(pos + rem);
244
return rem;
245
} finally {
246
Reference.reachabilityFence(buf);
247
}
248
} else {
249
try (NativeBuffer nb = NativeBuffers.getNativeBuffer(rem)) {
250
long address = nb.address();
251
252
if (src.hasArray()) {
253
// copy from backing array into buffer
254
int off = src.arrayOffset() + pos + Unsafe.ARRAY_BYTE_BASE_OFFSET;
255
unsafe.copyMemory(src.array(), off, null, address, rem);
256
} else {
257
// backing array not accessible so transfer via temporary array
258
byte[] tmp = new byte[rem];
259
src.get(tmp);
260
src.position(pos); // reset position as write may fail
261
unsafe.copyMemory(tmp, Unsafe.ARRAY_BYTE_BASE_OFFSET, null,
262
address, rem);
263
}
264
265
write(name, address, rem);
266
src.position(pos + rem);
267
return rem;
268
}
269
}
270
}
271
272
private void write(String name, long address, int rem) throws IOException {
273
int fd = -1;
274
try {
275
fd = file.openForAttributeAccess(followLinks);
276
} catch (UnixException x) {
277
x.rethrowAsIOException(file);
278
}
279
try {
280
fsetxattr(fd, nameAsBytes(file,name), address, rem);
281
} catch (UnixException x) {
282
throw new FileSystemException(file.getPathForExceptionMessage(),
283
null, "Error writing extended attribute '" + name + "': " +
284
x.getMessage());
285
} finally {
286
close(fd);
287
}
288
}
289
290
@SuppressWarnings("removal")
291
@Override
292
public void delete(String name) throws IOException {
293
if (System.getSecurityManager() != null)
294
checkAccess(file.getPathForPermissionCheck(), false, true);
295
296
int fd = -1;
297
try {
298
fd = file.openForAttributeAccess(followLinks);
299
} catch (UnixException x) {
300
x.rethrowAsIOException(file);
301
}
302
try {
303
fremovexattr(fd, nameAsBytes(file,name));
304
} catch (UnixException x) {
305
throw new FileSystemException(file.getPathForExceptionMessage(),
306
null, "Unable to delete extended attribute '" + name + "': " + x.getMessage());
307
} finally {
308
close(fd);
309
}
310
}
311
312
/**
313
* Used by copyTo/moveTo to copy extended attributes from source to target.
314
*
315
* @param ofd
316
* file descriptor for source file
317
* @param nfd
318
* file descriptor for target file
319
*/
320
static void copyExtendedAttributes(int ofd, int nfd) {
321
try {
322
List<String> attrNames = list(ofd, MIN_LISTXATTR_BUF_SIZE);
323
for (String name : attrNames) {
324
try {
325
copyExtendedAttribute(ofd, Util.toBytes(name), nfd);
326
} catch(UnixException ignore){
327
// ignore
328
}
329
}
330
} catch (UnixException e) {
331
// unable to get list of attributes
332
return;
333
}
334
}
335
336
private static void copyExtendedAttribute(int ofd, byte[] name, int nfd)
337
throws UnixException
338
{
339
int size = fgetxattr(ofd, name, 0L, 0);
340
NativeBuffer buffer = NativeBuffers.getNativeBuffer(size);
341
try {
342
long address = buffer.address();
343
size = fgetxattr(ofd, name, address, size);
344
fsetxattr(nfd, name, address, size);
345
} finally {
346
buffer.release();
347
}
348
}
349
}
350