From f428589be681e8ced2d69a3cfcfa9e2e3e5e5851 Mon Sep 17 00:00:00 2001 From: Reinhard Pointner Date: Sat, 2 Sep 2023 00:33:30 +0700 Subject: [PATCH] Add c.s.j.p.bsd.ExtAttr and c.s.j.p.bsd.ExtAttrUtil to wrap BSD system calls --- CHANGES.md | 1 + .../src/com/sun/jna/platform/bsd/ExtAttr.java | 47 +++++++ .../com/sun/jna/platform/bsd/ExtAttrUtil.java | 115 ++++++++++++++++++ 3 files changed, 163 insertions(+) create mode 100644 contrib/platform/src/com/sun/jna/platform/bsd/ExtAttr.java create mode 100644 contrib/platform/src/com/sun/jna/platform/bsd/ExtAttrUtil.java diff --git a/CHANGES.md b/CHANGES.md index d43afe19c..8ba5a4263 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,6 +10,7 @@ Features * [#1534](https://github.com/java-native-access/jna/pull/1534): Add `GetMethod`, `Put`, `SpawnInstance` to `c.s.j.p.win32.COM.WbemCli#IWbemClassObject` and `ExecMethod` to `c.s.j.p.win32.COM.WbemCli#IWbemServices` - [@faddom](https://github.com/faddom). * [#1544](https://github.com/java-native-access/jna/pull/1544): Add `GetPriorityClass`, `SetPriorityClass`, `GetThreadPriority`, `SetThreadPriority` and associated constants to `c.s.j.p.win32.Kernel32` - [@dEajL3kA](https://github.com/dEajL3kA). * [#1548](https://github.com/java-native-access/jna/pull/1548): Make interface `c.s.j.p.mac.XAttr public` - [@matthiasblaesing](https://github.com/matthiasblaesing). +* [#1551](https://github.com/java-native-access/jna/pull/1551): Add `c.s.j.p.bsd.ExtAttr` and `c.s.j.p.bsd.ExtAttrUtil` to wrap BSD [](https://man.freebsd.org/cgi/man.cgi?query=extattr&sektion=2) system calls. [@rednoah](https://github.com/rednoah). Bug Fixes --------- diff --git a/contrib/platform/src/com/sun/jna/platform/bsd/ExtAttr.java b/contrib/platform/src/com/sun/jna/platform/bsd/ExtAttr.java new file mode 100644 index 000000000..4211068ee --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/bsd/ExtAttr.java @@ -0,0 +1,47 @@ +/* Copyright (c) 2023 Reinhard Pointner, All Rights Reserved + * + * The contents of this file is dual-licensed under 2 + * alternative Open Source/Free licenses: LGPL 2.1 or later and + * Apache License 2.0. (starting with JNA version 4.0.0). + * + * You can freely decide which license you want to apply to + * the project. + * + * You may obtain a copy of the LGPL License at: + * + * http://www.gnu.org/licenses/licenses.html + * + * A copy is also included in the downloadable source code package + * containing JNA, in file "LGPL2.1". + * + * You may obtain a copy of the Apache License at: + * + * http://www.apache.org/licenses/ + * + * A copy is also included in the downloadable source code package + * containing JNA, in file "AL2.0". + */ +package com.sun.jna.platform.bsd; + +import java.nio.ByteBuffer; + +import com.sun.jna.Library; +import com.sun.jna.Native; +import com.sun.jna.platform.unix.LibCAPI.size_t; +import com.sun.jna.platform.unix.LibCAPI.ssize_t; + +public interface ExtAttr extends Library { + + ExtAttr INSTANCE = Native.load(null, ExtAttr.class); + + int EXTATTR_NAMESPACE_USER = 0x1; + + ssize_t extattr_get_file(String path, int attrnamespace, String attrname, ByteBuffer data, size_t nbytes); + + ssize_t extattr_set_file(String path, int attrnamespace, String attrname, ByteBuffer data, size_t nbytes); + + int extattr_delete_file(String path, int attrnamespace, String attrname); + + ssize_t extattr_list_file(String path, int attrnamespace, ByteBuffer data, size_t nbytes); + +} diff --git a/contrib/platform/src/com/sun/jna/platform/bsd/ExtAttrUtil.java b/contrib/platform/src/com/sun/jna/platform/bsd/ExtAttrUtil.java new file mode 100644 index 000000000..63df36cf4 --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/bsd/ExtAttrUtil.java @@ -0,0 +1,115 @@ +/* Copyright (c) 2023 Reinhard Pointner, All Rights Reserved + * + * The contents of this file is dual-licensed under 2 + * alternative Open Source/Free licenses: LGPL 2.1 or later and + * Apache License 2.0. (starting with JNA version 4.0.0). + * + * You can freely decide which license you want to apply to + * the project. + * + * You may obtain a copy of the LGPL License at: + * + * http://www.gnu.org/licenses/licenses.html + * + * A copy is also included in the downloadable source code package + * containing JNA, in file "LGPL2.1". + * + * You may obtain a copy of the Apache License at: + * + * http://www.apache.org/licenses/ + * + * A copy is also included in the downloadable source code package + * containing JNA, in file "AL2.0". + */ +package com.sun.jna.platform.bsd; + +import static java.util.Collections.*; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; + +import com.sun.jna.Native; +import com.sun.jna.platform.unix.LibCAPI.size_t; + +public class ExtAttrUtil { + + public static List list(String path) throws IOException { + // get required buffer size + long bufferLength = ExtAttr.INSTANCE.extattr_list_file(path, ExtAttr.EXTATTR_NAMESPACE_USER, null, new size_t(0)).longValue(); + + if (bufferLength < 0) { + throw new IOException("errno: " + Native.getLastError()); + } + + if (bufferLength == 0) { + return emptyList(); + } + + ByteBuffer buffer = ByteBuffer.allocate((int) bufferLength); + long valueLength = ExtAttr.INSTANCE.extattr_list_file(path, ExtAttr.EXTATTR_NAMESPACE_USER, buffer, new size_t(bufferLength)).longValue(); + + if (valueLength < 0) { + throw new IOException("errno: " + Native.getLastError()); + } + + return decodeStringList(buffer); + } + + public static ByteBuffer get(String path, String name) throws IOException { + // get required buffer size + long bufferLength = ExtAttr.INSTANCE.extattr_get_file(path, ExtAttr.EXTATTR_NAMESPACE_USER, name, null, new size_t(0)).longValue(); + + if (bufferLength < 0) { + throw new IOException("errno: " + Native.getLastError()); + } + + if (bufferLength == 0) { + return ByteBuffer.allocate(0); + } + + ByteBuffer buffer = ByteBuffer.allocate((int) bufferLength); + long valueLength = ExtAttr.INSTANCE.extattr_get_file(path, ExtAttr.EXTATTR_NAMESPACE_USER, name, buffer, new size_t(bufferLength)).longValue(); + + if (valueLength < 0) { + throw new IOException("errno: " + Native.getLastError()); + } + + return buffer; + } + + public static void set(String path, String name, ByteBuffer value) throws IOException { + long r = ExtAttr.INSTANCE.extattr_set_file(path, ExtAttr.EXTATTR_NAMESPACE_USER, name, value, new size_t(value.remaining())).longValue(); + if (r < 0) { + throw new IOException("errno: " + Native.getLastError()); + } + } + + public static void delete(String path, String name) throws IOException { + int r = ExtAttr.INSTANCE.extattr_delete_file(path, ExtAttr.EXTATTR_NAMESPACE_USER, name); + if (r < 0) { + throw new IOException("errno: " + Native.getLastError()); + } + } + + private static List decodeStringList(ByteBuffer buffer) { + List list = new ArrayList(); + + while (buffer.hasRemaining()) { + int length = buffer.get() & 0xFF; + byte[] value = new byte[length]; + buffer.get(value); + + try { + list.add(new String(value, "UTF-8")); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + + return list; + } + +}