Skip to content

Commit bd184d5

Browse files
Add byte[] based bindings to c.s.j.p.linux.XAttr
1 parent 62cd54e commit bd184d5

File tree

2 files changed

+108
-64
lines changed

2 files changed

+108
-64
lines changed

contrib/platform/src/com/sun/jna/platform/linux/XAttr.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,16 +69,25 @@ public ssize_t(long value) {
6969
int EDQUOT = 122;
7070

7171
int setxattr(String path, String name, Pointer value, size_t size, int flags);
72+
int setxattr(String path, String name, byte[] value, size_t size, int flags);
7273
int lsetxattr(String path, String name, Pointer value, size_t size, int flags);
74+
int lsetxattr(String path, String name, byte[] value, size_t size, int flags);
7375
int fsetxattr(int fd, String name, Pointer value, size_t size, int flags);
76+
int fsetxattr(int fd, String name, byte[] value, size_t size, int flags);
7477

7578
ssize_t getxattr(String path, String name, Pointer value, size_t size);
79+
ssize_t getxattr(String path, String name, byte[] value, size_t size);
7680
ssize_t lgetxattr(String path, String name, Pointer value, size_t size);
81+
ssize_t lgetxattr(String path, String name, byte[] value, size_t size);
7782
ssize_t fgetxattr(int fd, String name, Pointer value, size_t size);
83+
ssize_t fgetxattr(int fd, String name, byte[] value, size_t size);
7884

7985
ssize_t listxattr(String path, Pointer list, size_t size);
86+
ssize_t listxattr(String path, byte[] list, size_t size);
8087
ssize_t llistxattr(String path, Pointer list, size_t size);
88+
ssize_t llistxattr(String path, byte[] list, size_t size);
8189
ssize_t flistxattr(int fd, Pointer list, size_t size);
90+
ssize_t flistxattr(int fd, byte[] list, size_t size);
8291

8392
int removexattr(String path, String name);
8493
int lremovexattr(String path, String name);

contrib/platform/src/com/sun/jna/platform/linux/XAttrUtil.java

Lines changed: 99 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,7 @@ public static void setXAttr(String path, String name, String value, String encod
7979
* @throws IOException on any error
8080
*/
8181
public static void setXAttr(String path, String name, byte[] value) throws IOException {
82-
Memory valueMem = bytesToMemory(value);
83-
int retval = XAttr.INSTANCE.setxattr(path, name, valueMem, new size_t(valueMem.size()), 0);
82+
int retval = XAttr.INSTANCE.setxattr(path, name, value, new size_t(value.length), 0);
8483
if (retval != 0) {
8584
final int eno = Native.getLastError();
8685
throw new IOException("errno: " + eno);
@@ -126,9 +125,7 @@ public static void lSetXAttr(String path, String name, String value, String enco
126125
* @throws IOException on any error
127126
*/
128127
public static void lSetXAttr(String path, String name, byte[] value) throws IOException {
129-
Memory valueMem = bytesToMemory(value);
130-
final int retval = XAttr.INSTANCE.lsetxattr(path, name, valueMem,
131-
new size_t(valueMem.size()), 0);
128+
final int retval = XAttr.INSTANCE.lsetxattr(path, name, value, new size_t(value.length), 0);
132129
if (retval != 0) {
133130
final int eno = Native.getLastError();
134131
throw new IOException("errno: " + eno);
@@ -171,9 +168,7 @@ public static void fSetXAttr(int fd, String name, String value, String encoding)
171168
* @throws IOException on any error
172169
*/
173170
public static void fSetXAttr(int fd, String name, byte[] value) throws IOException {
174-
Memory valueMem = bytesToMemory(value);
175-
final int retval = XAttr.INSTANCE.fsetxattr(fd, name, valueMem, new size_t(valueMem.size()),
176-
0);
171+
final int retval = XAttr.INSTANCE.fsetxattr(fd, name, value, new size_t(value.length), 0);
177172
if (retval != 0) {
178173
final int eno = Native.getLastError();
179174
throw new IOException("errno: " + eno);
@@ -203,10 +198,8 @@ public static String getXAttr(String path, String name) throws IOException {
203198
* @throws IOException on any error except <code>ERANGE</code> which handled internally
204199
*/
205200
public static String getXAttr(String path, String name, String encoding) throws IOException {
206-
Memory valueMem = getXAttrAsMemory(path, name);
207-
return Charset.forName(encoding)
208-
.decode(valueMem.getByteBuffer(0, valueMem.size()))
209-
.toString();
201+
byte[] valueMem = getXAttrBytes(path, name);
202+
return new String(valueMem, Charset.forName(encoding));
210203
}
211204

212205
/**
@@ -218,8 +211,28 @@ public static String getXAttr(String path, String name, String encoding) throws
218211
* @throws IOException on any error except <code>ERANGE</code> which handled internally
219212
*/
220213
public static byte[] getXAttrBytes(String path, String name) throws IOException {
221-
Memory valueMem = getXAttrAsMemory(path, name);
222-
return valueMem.getByteArray(0, (int) valueMem.size());
214+
ssize_t retval;
215+
byte[] valueMem;
216+
int eno = 0;
217+
218+
do {
219+
retval = XAttr.INSTANCE.getxattr(path, name, (byte[]) null, size_t.ZERO);
220+
if (retval.longValue() < 0) {
221+
eno = Native.getLastError();
222+
throw new IOException("errno: " + eno);
223+
}
224+
225+
valueMem = new byte[retval.intValue()];
226+
retval = XAttr.INSTANCE.getxattr(path, name, valueMem, new size_t(valueMem.length));
227+
if (retval.longValue() < 0) {
228+
eno = Native.getLastError();
229+
if (eno != XAttr.ERANGE) {
230+
throw new IOException("errno: " + eno);
231+
}
232+
}
233+
} while (retval.longValue() < 0 && eno == XAttr.ERANGE);
234+
235+
return valueMem;
223236
}
224237

225238
/**
@@ -236,7 +249,7 @@ public static Memory getXAttrAsMemory(String path, String name) throws IOExcepti
236249
int eno = 0;
237250

238251
do {
239-
retval = XAttr.INSTANCE.getxattr(path, name, null, size_t.ZERO);
252+
retval = XAttr.INSTANCE.getxattr(path, name, (Memory) null, size_t.ZERO);
240253
if (retval.longValue() < 0) {
241254
eno = Native.getLastError();
242255
throw new IOException("errno: " + eno);
@@ -280,10 +293,8 @@ public static String lGetXAttr(String path, String name) throws IOException {
280293
* @throws IOException on any error except <code>ERANGE</code> which handled internally
281294
*/
282295
public static String lGetXAttr(String path, String name, String encoding) throws IOException {
283-
Memory valueMem = lGetXAttrAsMemory(path, name);
284-
return Charset.forName(encoding)
285-
.decode(valueMem.getByteBuffer(0, valueMem.size()))
286-
.toString();
296+
byte[] valueMem = lGetXAttrBytes(path, name);
297+
return new String(valueMem, Charset.forName(encoding));
287298
}
288299

289300
/**
@@ -296,8 +307,28 @@ public static String lGetXAttr(String path, String name, String encoding) throws
296307
* @throws IOException on any error except <code>ERANGE</code> which handled internally
297308
*/
298309
public static byte[] lGetXAttrBytes(String path, String name) throws IOException {
299-
Memory valueMem = lGetXAttrAsMemory(path, name);
300-
return valueMem.getByteArray(0, (int) valueMem.size());
310+
ssize_t retval;
311+
byte[] valueMem;
312+
int eno = 0;
313+
314+
do {
315+
retval = XAttr.INSTANCE.lgetxattr(path, name, (byte[]) null, size_t.ZERO);
316+
if (retval.longValue() < 0) {
317+
eno = Native.getLastError();
318+
throw new IOException("errno: " + eno);
319+
}
320+
321+
valueMem = new byte[retval.intValue()];
322+
retval = XAttr.INSTANCE.lgetxattr(path, name, valueMem, new size_t(valueMem.length));
323+
if (retval.longValue() < 0) {
324+
eno = Native.getLastError();
325+
if (eno != XAttr.ERANGE) {
326+
throw new IOException("errno: " + eno);
327+
}
328+
}
329+
} while (retval.longValue() < 0 && eno == XAttr.ERANGE);
330+
331+
return valueMem;
301332
}
302333

303334
/**
@@ -315,7 +346,7 @@ public static Memory lGetXAttrAsMemory(String path, String name) throws IOExcept
315346
int eno = 0;
316347

317348
do {
318-
retval = XAttr.INSTANCE.lgetxattr(path, name, null, size_t.ZERO);
349+
retval = XAttr.INSTANCE.lgetxattr(path, name, (Memory) null, size_t.ZERO);
319350
if (retval.longValue() < 0) {
320351
eno = Native.getLastError();
321352
throw new IOException("errno: " + eno);
@@ -357,10 +388,8 @@ public static String fGetXAttr(int fd, String name) throws IOException {
357388
* @throws IOException on any error except <code>ERANGE</code> which handled internally
358389
*/
359390
public static String fGetXAttr(int fd, String name, String encoding) throws IOException {
360-
Memory valueMem = fGetXAttrAsMemory(fd, name);
361-
return Charset.forName(encoding)
362-
.decode(valueMem.getByteBuffer(0, valueMem.size()))
363-
.toString();
391+
byte[] valueMem = fGetXAttrBytes(fd, name);
392+
return new String(valueMem, Charset.forName(encoding));
364393
}
365394

366395
/**
@@ -372,8 +401,28 @@ public static String fGetXAttr(int fd, String name, String encoding) throws IOEx
372401
* @throws IOException on any error except <code>ERANGE</code> which handled internally
373402
*/
374403
public static byte[] fGetXAttrBytes(int fd, String name) throws IOException {
375-
Memory valueMem = fGetXAttrAsMemory(fd, name);
376-
return valueMem.getByteArray(0, (int) valueMem.size());
404+
ssize_t retval;
405+
byte[] valueMem;
406+
int eno = 0;
407+
408+
do {
409+
retval = XAttr.INSTANCE.fgetxattr(fd, name, (byte[]) null, size_t.ZERO);
410+
if (retval.longValue() < 0) {
411+
eno = Native.getLastError();
412+
throw new IOException("errno: " + eno);
413+
}
414+
415+
valueMem = new byte[retval.intValue()];
416+
retval = XAttr.INSTANCE.fgetxattr(fd, name, valueMem, new size_t(valueMem.length));
417+
if (retval.longValue() < 0) {
418+
eno = Native.getLastError();
419+
if (eno != XAttr.ERANGE) {
420+
throw new IOException("errno: " + eno);
421+
}
422+
}
423+
} while (retval.longValue() < 0 && eno == XAttr.ERANGE);
424+
425+
return valueMem;
377426
}
378427

379428
/**
@@ -390,7 +439,7 @@ public static Memory fGetXAttrAsMemory(int fd, String name) throws IOException {
390439
int eno = 0;
391440

392441
do {
393-
retval = XAttr.INSTANCE.fgetxattr(fd, name, null, size_t.ZERO);
442+
retval = XAttr.INSTANCE.fgetxattr(fd, name, (Memory) null, size_t.ZERO);
394443
if (retval.longValue() < 0) {
395444
eno = Native.getLastError();
396445
throw new IOException("errno: " + eno);
@@ -431,18 +480,18 @@ public static Collection<String> listXAttr(String path) throws IOException {
431480
*/
432481
public static Collection<String> listXAttr(String path, String encoding) throws IOException {
433482
ssize_t retval;
434-
Memory listMem;
483+
byte[] listMem;
435484
int eno = 0;
436485

437486
do {
438-
retval = XAttr.INSTANCE.listxattr(path, null, size_t.ZERO);
487+
retval = XAttr.INSTANCE.listxattr(path, (byte[]) null, size_t.ZERO);
439488
if (retval.longValue() < 0) {
440489
eno = Native.getLastError();
441490
throw new IOException("errno: " + eno);
442491
}
443492

444-
listMem = new Memory(retval.longValue());
445-
retval = XAttr.INSTANCE.listxattr(path, listMem, new size_t(listMem.size()));
493+
listMem = new byte[retval.intValue()];
494+
retval = XAttr.INSTANCE.listxattr(path, listMem, new size_t(listMem.length));
446495
if (retval.longValue() < 0) {
447496
eno = Native.getLastError();
448497
if (eno != XAttr.ERANGE) {
@@ -478,18 +527,18 @@ public static Collection<String> lListXAttr(String path) throws IOException {
478527
*/
479528
public static Collection<String> lListXAttr(String path, String encoding) throws IOException {
480529
ssize_t retval;
481-
Memory listMem;
530+
byte[] listMem;
482531
int eno = 0;
483532

484533
do {
485-
retval = XAttr.INSTANCE.llistxattr(path, null, size_t.ZERO);
534+
retval = XAttr.INSTANCE.llistxattr(path, (byte[]) null, size_t.ZERO);
486535
if (retval.longValue() < 0) {
487536
eno = Native.getLastError();
488537
throw new IOException("errno: " + eno);
489538
}
490539

491-
listMem = new Memory(retval.longValue());
492-
retval = XAttr.INSTANCE.llistxattr(path, listMem, new size_t(listMem.size()));
540+
listMem = new byte[retval.intValue()];
541+
retval = XAttr.INSTANCE.llistxattr(path, listMem, new size_t(listMem.length));
493542
if (retval.longValue() < 0) {
494543
eno = Native.getLastError();
495544
if (eno != XAttr.ERANGE) {
@@ -523,18 +572,18 @@ public static Collection<String> fListXAttr(int fd) throws IOException {
523572
*/
524573
public static Collection<String> fListXAttr(int fd, String encoding) throws IOException {
525574
ssize_t retval;
526-
Memory listMem;
575+
byte[] listMem;
527576
int eno = 0;
528577

529578
do {
530-
retval = XAttr.INSTANCE.flistxattr(fd, null, size_t.ZERO);
579+
retval = XAttr.INSTANCE.flistxattr(fd, (byte[]) null, size_t.ZERO);
531580
if (retval.longValue() < 0) {
532581
eno = Native.getLastError();
533582
throw new IOException("errno: " + eno);
534583
}
535584

536-
listMem = new Memory(retval.longValue());
537-
retval = XAttr.INSTANCE.flistxattr(fd, listMem, new size_t(listMem.size()));
585+
listMem = new byte[retval.intValue()];
586+
retval = XAttr.INSTANCE.flistxattr(fd, listMem, new size_t(listMem.length));
538587
if (retval.longValue() < 0) {
539588
eno = Native.getLastError();
540589
if (eno != XAttr.ERANGE) {
@@ -593,33 +642,19 @@ public static void fRemoveXAttr(int fd, String name) throws IOException {
593642
}
594643
}
595644

596-
private static Memory bytesToMemory(byte[] value) {
597-
Memory valueMem = new Memory(value.length);
598-
valueMem.write(0, value, 0, value.length);
599-
return valueMem;
600-
}
601-
602-
private static Collection<String> splitBufferToStrings(Memory valueMem, String encoding)
645+
private static Collection<String> splitBufferToStrings(byte[] valueMem, String encoding)
603646
throws IOException {
604647
final Charset charset = Charset.forName(encoding);
605648
final Set<String> attributesList = new LinkedHashSet<String>(1);
606-
long offset = 0;
607-
while (offset != valueMem.size()) {
608-
// Find terminating NUL character.
609-
long nulOffset = valueMem.indexOf(offset, (byte) 0);
610-
if (nulOffset == -1) {
611-
throw new IOException("Expected NUL character not found.");
649+
int offset = 0;
650+
for(int i = 0; i < valueMem.length; i++) {
651+
// each entry is terminated by a single \0 byte
652+
if(valueMem[i] == 0) {
653+
// Convert bytes of the name to String.
654+
final String name = new String(valueMem, offset, i - offset, charset);
655+
attributesList.add(name);
656+
offset = i + 1;
612657
}
613-
614-
// Duplicate buffer with limit at end of name.
615-
final ByteBuffer nameBuffer = valueMem.getByteBuffer(offset, nulOffset);
616-
617-
// Convert bytes of the name to String.
618-
final String name = charset.decode(nameBuffer).toString();
619-
attributesList.add(name);
620-
621-
// Move past NUL.
622-
offset += nulOffset + 1;
623658
}
624659
return attributesList;
625660
}

0 commit comments

Comments
 (0)