Skip to content

Commit daeca3f

Browse files
overheadhunterAlan Bateman
authored and
Alan Bateman
committed
8262958: (fs) UnixUserDefinedFileAttributeView cleanup
Reviewed-by: alanb
1 parent af02883 commit daeca3f

File tree

1 file changed

+38
-76
lines changed

1 file changed

+38
-76
lines changed

src/java.base/unix/classes/sun/nio/fs/UnixUserDefinedFileAttributeView.java

Lines changed: 38 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ abstract class UnixUserDefinedFileAttributeView
4646
// namespace for extended user attributes
4747
private static final String USER_NAMESPACE = "user.";
4848

49+
private static final int MIN_LISTXATTR_BUF_SIZE = 1024;
50+
private static final int MAX_LISTXATTR_BUF_SIZE = 32 * 1024;
51+
4952
private byte[] nameAsBytes(UnixPath file, String name) throws IOException {
5053
if (name == null)
5154
throw new NullPointerException("'name' is null");
@@ -59,7 +62,7 @@ private byte[] nameAsBytes(UnixPath file, String name) throws IOException {
5962
}
6063

6164
// Parses buffer as array of NULL-terminated C strings.
62-
private List<String> asList(long address, int size) {
65+
private static List<String> asList(long address, int size) {
6366
List<String> list = new ArrayList<>();
6467
int start = 0;
6568
int pos = 0;
@@ -70,17 +73,30 @@ private List<String> asList(long address, int size) {
7073
unsafe.copyMemory(null, address+start, value,
7174
Unsafe.ARRAY_BYTE_BASE_OFFSET, len);
7275
String s = Util.toString(value);
73-
if (s.startsWith(USER_NAMESPACE)) {
74-
s = s.substring(USER_NAMESPACE.length());
75-
list.add(s);
76-
}
76+
list.add(s);
7777
start = pos + 1;
7878
}
7979
pos++;
8080
}
8181
return list;
8282
}
8383

84+
// runs flistxattr, increases buffer size up to MAX_LISTXATTR_BUF_SIZE if required
85+
private static List<String> list(int fd, int bufSize) throws UnixException {
86+
try {
87+
try (NativeBuffer buffer = NativeBuffers.getNativeBuffer(bufSize)) {
88+
int n = flistxattr(fd, buffer.address(), bufSize);
89+
return asList(buffer.address(), n);
90+
} // release buffer before recursion
91+
} catch (UnixException x) {
92+
if (x.errno() == ERANGE && bufSize < MAX_LISTXATTR_BUF_SIZE) {
93+
return list(fd, bufSize * 2); // try larger buffer size:
94+
} else {
95+
throw x;
96+
}
97+
}
98+
}
99+
84100
private final UnixPath file;
85101
private final boolean followLinks;
86102

@@ -105,32 +121,17 @@ public List<String> list() throws IOException {
105121
} catch (UnixException x) {
106122
x.rethrowAsIOException(file);
107123
}
108-
NativeBuffer buffer = null;
109124
try {
110-
int size = 1024;
111-
buffer = NativeBuffers.getNativeBuffer(size);
112-
for (;;) {
113-
try {
114-
int n = flistxattr(fd, buffer.address(), size);
115-
List<String> list = asList(buffer.address(), n);
116-
return Collections.unmodifiableList(list);
117-
} catch (UnixException x) {
118-
// allocate larger buffer if required
119-
if (x.errno() == ERANGE && size < 32*1024) {
120-
buffer.release();
121-
size *= 2;
122-
buffer = null;
123-
buffer = NativeBuffers.getNativeBuffer(size);
124-
continue;
125-
}
126-
throw new FileSystemException(file.getPathForExceptionMessage(),
127-
null, "Unable to get list of extended attributes: " +
128-
x.getMessage());
129-
}
130-
}
125+
List<String> attrNames = list(fd, MIN_LISTXATTR_BUF_SIZE);
126+
return attrNames.stream()
127+
.filter(s -> s.startsWith(USER_NAMESPACE))
128+
.map(s -> s.substring(USER_NAMESPACE.length()))
129+
.toList();
130+
} catch (UnixException x) {
131+
throw new FileSystemException(file.getPathForExceptionMessage(),
132+
null, "Unable to get list of extended attributes: " +
133+
x.getMessage());
131134
} finally {
132-
if (buffer != null)
133-
buffer.release();
134135
close(fd);
135136
}
136137
}
@@ -312,57 +313,18 @@ public void delete(String name) throws IOException {
312313
* file descriptor for target file
313314
*/
314315
static void copyExtendedAttributes(int ofd, int nfd) {
315-
NativeBuffer buffer = null;
316316
try {
317-
318-
// call flistxattr to get list of extended attributes.
319-
int size = 1024;
320-
buffer = NativeBuffers.getNativeBuffer(size);
321-
for (;;) {
317+
List<String> attrNames = list(ofd, MIN_LISTXATTR_BUF_SIZE);
318+
for (String name : attrNames) {
322319
try {
323-
size = flistxattr(ofd, buffer.address(), size);
324-
break;
325-
} catch (UnixException x) {
326-
// allocate larger buffer if required
327-
if (x.errno() == ERANGE && size < 32*1024) {
328-
buffer.release();
329-
size *= 2;
330-
buffer = null;
331-
buffer = NativeBuffers.getNativeBuffer(size);
332-
continue;
333-
}
334-
335-
// unable to get list of attributes
336-
return;
337-
}
338-
}
339-
340-
// parse buffer as array of NULL-terminated C strings.
341-
long address = buffer.address();
342-
int start = 0;
343-
int pos = 0;
344-
while (pos < size) {
345-
if (unsafe.getByte(address + pos) == 0) {
346-
// extract attribute name and copy attribute to target.
347-
// FIXME: We can avoid needless copying by using address+pos
348-
// as the address of the name.
349-
int len = pos - start;
350-
byte[] name = new byte[len];
351-
unsafe.copyMemory(null, address+start, name,
352-
Unsafe.ARRAY_BYTE_BASE_OFFSET, len);
353-
try {
354-
copyExtendedAttribute(ofd, name, nfd);
355-
} catch (UnixException ignore) {
356-
// ignore
357-
}
358-
start = pos + 1;
320+
copyExtendedAttribute(ofd, Util.toBytes(name), nfd);
321+
} catch(UnixException ignore){
322+
// ignore
359323
}
360-
pos++;
361324
}
362-
363-
} finally {
364-
if (buffer != null)
365-
buffer.release();
325+
} catch (UnixException e) {
326+
// unable to get list of attributes
327+
return;
366328
}
367329
}
368330

0 commit comments

Comments
 (0)