diff --git a/CHANGES.md b/CHANGES.md index c47d73d25c..112c607bd3 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,6 +11,7 @@ Features Bug Fixes --------- +* [#1095](https://github.com/java-native-access/jna/pull/1095) Align behaviour of com.sun.jna.platform.macXAttrUtil#setXattr and #getXAttr with CLI tool - [@jrobhoward](https://github.com/jrobhoward), [@matthiasblaesing](https://github.com/matthiasblaesing). * [#1091](https://github.com/java-native-access/jna/issues/1091): Check target number to be greater than zero, before calling `Structure#toArray` in `c.s.j.p.win32.Netapi32Util` - [@trevormagg](https://github.com/trevormaggs), [@matthiasblaesing](https://github.com/matthiasblaesing). Release 5.3.1 diff --git a/contrib/platform/src/com/sun/jna/platform/mac/XAttrUtil.java b/contrib/platform/src/com/sun/jna/platform/mac/XAttrUtil.java index 09085d8d47..a8ba9d2fdf 100644 --- a/contrib/platform/src/com/sun/jna/platform/mac/XAttrUtil.java +++ b/contrib/platform/src/com/sun/jna/platform/mac/XAttrUtil.java @@ -29,6 +29,7 @@ import java.util.List; import com.sun.jna.Memory; +import com.sun.jna.Native; public class XAttrUtil { @@ -55,19 +56,23 @@ public static String getXAttr(String path, String name) { // get required buffer size long bufferLength = XAttr.INSTANCE.getxattr(path, name, null, 0, 0, 0); - if (bufferLength < 0) + if (bufferLength < 0) { return null; + } - if (bufferLength == 0) + if (bufferLength == 0) { return ""; + } Memory valueBuffer = new Memory(bufferLength); + valueBuffer.clear(); long valueLength = XAttr.INSTANCE.getxattr(path, name, valueBuffer, bufferLength, 0, 0); - if (valueLength < 0) + if (valueLength < 0) { return null; + } - return decodeString(valueBuffer.getByteBuffer(0, valueLength - 1)); + return Native.toString(valueBuffer.getByteArray(0, (int) bufferLength), "UTF-8"); } public static int setXAttr(String path, String name, String value) { @@ -82,9 +87,8 @@ public static int removeXAttr(String path, String name) { protected static Memory encodeString(String s) { // create NULL-terminated UTF-8 String byte[] bb = s.getBytes(Charset.forName("UTF-8")); - Memory valueBuffer = new Memory(bb.length + 1); + Memory valueBuffer = new Memory(bb.length); valueBuffer.write(0, bb, 0, bb.length); - valueBuffer.setByte(valueBuffer.size() - 1, (byte) 0); return valueBuffer; } diff --git a/contrib/platform/test/com/sun/jna/platform/mac/XAttrUtilTest.java b/contrib/platform/test/com/sun/jna/platform/mac/XAttrUtilTest.java index 3be908b9f8..bca9141b39 100644 --- a/contrib/platform/test/com/sun/jna/platform/mac/XAttrUtilTest.java +++ b/contrib/platform/test/com/sun/jna/platform/mac/XAttrUtilTest.java @@ -23,11 +23,14 @@ */ package com.sun.jna.platform.mac; -import com.sun.jna.Memory; import com.sun.jna.Pointer; +import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.IOException; +import java.io.InputStream; import java.util.Arrays; import java.util.List; +import java.util.concurrent.TimeUnit; import junit.framework.TestCase; @@ -136,4 +139,26 @@ public void testLargeData() { String value = XAttrUtil.getXAttr(testPath, name.toString()); assertEquals(data.toString(), value.toString()); } + + public void testReadAlignedCliTool() throws IOException { + XAttrUtil.setXAttr(testPath, "JNA", "Java Native Access"); + Process p = Runtime.getRuntime().exec(new String[] {"xattr", "-p", "JNA", testPath}); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int read; + InputStream is = p.getInputStream(); + while(((read = is.read(buffer))) > 0) { + baos.write(buffer, 0, read); + } + String resultString = baos.toString("UTF-8"); + // Trailing new line is added by command + assertEquals("Java Native Access\n", resultString); + } + + public void testWriteAlignedCliTool() throws IOException, InterruptedException { + Process p = Runtime.getRuntime().exec(new String[] {"xattr", "-w", "JNA", "Java Native Access", testPath}); + assertTrue(p.waitFor(10, TimeUnit.SECONDS)); + String resultString = XAttrUtil.getXAttr(testPath, "JNA"); + assertEquals("Java Native Access", resultString); + } }