Skip to content

Commit

Permalink
Merge pull request #1551 from rednoah/master
Browse files Browse the repository at this point in the history
Wrap BSD <sys/extattr.h> system calls
  • Loading branch information
matthiasblaesing committed Sep 1, 2023
2 parents 43b5f76 + f428589 commit aff2e35
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Expand Up @@ -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 [<sys/extattr.h>](https://man.freebsd.org/cgi/man.cgi?query=extattr&sektion=2) system calls. [@rednoah](https://github.com/rednoah).

Bug Fixes
---------
Expand Down
47 changes: 47 additions & 0 deletions 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);

}
115 changes: 115 additions & 0 deletions 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<String> 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<String> decodeStringList(ByteBuffer buffer) {
List<String> list = new ArrayList<String>();

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;
}

}

0 comments on commit aff2e35

Please sign in to comment.