[libvirt] [java] [PATCH 0/6] Fix JNA wrapping, fix memory leaks and wrap security model / label function

Hi. First and foremost, this series fixes a few mistakes in the wrapping code found by inspecting the org.libvirt.jna.Libvirt interface and the corresponding C types of the XML API file. The last two patches add two missing functions introduced in libvirt 0.6.1. At the end of the day, this means libvirt-java has gained full coverage of the libvirt functions up to and including version 0.8.5. Yay! Claudio Bley (6): JNA: fix wrong return type void vs. int JNA: add CString class and fix memory leaks JNA: simplify freeing memory for C strings Use the CString class for Arrays of CStrings too Implement Domain.getSecurityLabel and add SecurityLabel class Implement Connect.getSecurityModel and add SecurityModel class src/main/java/org/libvirt/Connect.java | 74 +++++++++-------- src/main/java/org/libvirt/Device.java | 9 +- src/main/java/org/libvirt/Domain.java | 57 ++++++------- src/main/java/org/libvirt/DomainSnapshot.java | 8 +- src/main/java/org/libvirt/Interface.java | 7 +- src/main/java/org/libvirt/Library.java | 44 +++------- src/main/java/org/libvirt/Network.java | 14 +--- src/main/java/org/libvirt/NetworkFilter.java | 2 +- src/main/java/org/libvirt/Secret.java | 2 +- src/main/java/org/libvirt/SecurityLabel.java | 49 +++++++++++ src/main/java/org/libvirt/SecurityModel.java | 37 +++++++++ src/main/java/org/libvirt/StoragePool.java | 9 +- src/main/java/org/libvirt/StorageVol.java | 16 +--- src/main/java/org/libvirt/jna/CString.java | 85 +++++++++++++++++++ src/main/java/org/libvirt/jna/Libvirt.java | 114 +++++++++++++++++--------- 15 files changed, 343 insertions(+), 184 deletions(-) create mode 100644 src/main/java/org/libvirt/SecurityLabel.java create mode 100644 src/main/java/org/libvirt/SecurityModel.java create mode 100644 src/main/java/org/libvirt/jna/CString.java -- 2.2.2

The functions virEventUpdateTimeout and virConnResetLastError have no return value, they return void. In Java they had been mistakenly wrapped as returning int. --- src/main/java/org/libvirt/jna/Libvirt.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/libvirt/jna/Libvirt.java b/src/main/java/org/libvirt/jna/Libvirt.java index a17bfc7..a3cee0a 100644 --- a/src/main/java/org/libvirt/jna/Libvirt.java +++ b/src/main/java/org/libvirt/jna/Libvirt.java @@ -217,7 +217,7 @@ public interface Libvirt extends Library { */ @Deprecated virError virConnGetLastError(ConnectionPointer virConnectPtr); - int virConnResetLastError(ConnectionPointer virConnectPtr); + void virConnResetLastError(ConnectionPointer virConnectPtr); String virConnectDomainXMLFromNative(ConnectionPointer virConnectPtr, String nativeFormat, String nativeConfig, int flags); String virConnectDomainXMLToNative(ConnectionPointer virConnectPtr, String nativeFormat, String domainXML, @@ -469,5 +469,5 @@ public interface Libvirt extends Library { // Event functions int virEventAddTimeout(int milliSeconds, VirEventTimeoutCallback cb, Pointer opaque, Pointer ff); int virEventRemoveTimeout(int timer); - int virEventUpdateTimeout(int timer, int timeout); + void virEventUpdateTimeout(int timer, int timeout); } -- 2.2.2

Some libvirt functions were wrapped using a Java String as return type, although they return a "char*". That means the memory allocated by libvirt for those strings is never freed because JNA assumes a "const char*". Start to refactor the String handling by using a type-safe Pointer for C Strings, which automatically frees the memory when converting from the native pointer to the Java type. --- src/main/java/org/libvirt/Connect.java | 17 +++--- src/main/java/org/libvirt/Device.java | 2 +- src/main/java/org/libvirt/NetworkFilter.java | 2 +- src/main/java/org/libvirt/Secret.java | 2 +- src/main/java/org/libvirt/StoragePool.java | 2 +- src/main/java/org/libvirt/jna/CString.java | 85 ++++++++++++++++++++++++++++ src/main/java/org/libvirt/jna/Libvirt.java | 18 +++--- 7 files changed, 108 insertions(+), 20 deletions(-) create mode 100644 src/main/java/org/libvirt/jna/CString.java diff --git a/src/main/java/org/libvirt/Connect.java b/src/main/java/org/libvirt/Connect.java index e86fd83..d0bdc4d 100644 --- a/src/main/java/org/libvirt/Connect.java +++ b/src/main/java/org/libvirt/Connect.java @@ -7,6 +7,7 @@ import java.util.UUID; import org.libvirt.event.*; import org.libvirt.jna.ConnectionPointer; +import org.libvirt.jna.CString; import org.libvirt.jna.DevicePointer; import org.libvirt.jna.DomainPointer; import org.libvirt.jna.InterfacePointer; @@ -364,7 +365,8 @@ public class Connect { * @throws LibvirtException */ public String baselineCPU(String[] xmlCPUs) throws LibvirtException { - return processError(libvirt.virConnectBaselineCPU(VCP, xmlCPUs, xmlCPUs.length, 0)); + CString result = libvirt.virConnectBaselineCPU(VCP, xmlCPUs, xmlCPUs.length, 0); + return processError(result).toString(); } /** @@ -920,7 +922,8 @@ public class Connect { * @throws LibvirtException */ public String domainXMLFromNative(String nativeFormat, String nativeConfig, int flags) throws LibvirtException { - return processError(libvirt.virConnectDomainXMLFromNative(VCP, nativeFormat, nativeConfig, 0)); + CString result = libvirt.virConnectDomainXMLFromNative(VCP, nativeFormat, nativeConfig, 0); + return processError(result).toString(); } /** @@ -932,8 +935,8 @@ public class Connect { * @throws LibvirtException */ public String domainXMLToNative(String nativeFormat, String domainXML, int flags) throws LibvirtException { - String returnValue = libvirt.virConnectDomainXMLToNative(VCP, nativeFormat, domainXML, 0); - return processError(returnValue); + CString returnValue = libvirt.virConnectDomainXMLToNative(VCP, nativeFormat, domainXML, 0); + return processError(returnValue).toString(); } @Override @@ -962,8 +965,8 @@ public class Connect { * @throws LibvirtException */ public String findStoragePoolSources(String type, String srcSpecs, int flags) throws LibvirtException { - String returnValue = libvirt.virConnectFindStoragePoolSources(VCP, type, srcSpecs, flags); - return processError(returnValue); + CString returnValue = libvirt.virConnectFindStoragePoolSources(VCP, type, srcSpecs, flags); + return processError(returnValue).toString(); } /** @@ -1109,7 +1112,7 @@ public class Connect { * @throws LibvirtException */ public String getURI() throws LibvirtException { - return processError(libvirt.virConnectGetURI(VCP)); + return processError(libvirt.virConnectGetURI(VCP)).toString(); } /** diff --git a/src/main/java/org/libvirt/Device.java b/src/main/java/org/libvirt/Device.java index 3c876c6..04f373e 100644 --- a/src/main/java/org/libvirt/Device.java +++ b/src/main/java/org/libvirt/Device.java @@ -118,7 +118,7 @@ public class Device { * @throws LibvirtException */ public String getXMLDescription() throws LibvirtException { - return processError(libvirt.virNodeDeviceGetXMLDesc(VDP, 0)); + return processError(libvirt.virNodeDeviceGetXMLDesc(VDP, 0)).toString(); } /** diff --git a/src/main/java/org/libvirt/NetworkFilter.java b/src/main/java/org/libvirt/NetworkFilter.java index 4f4bc6c..094a5f6 100644 --- a/src/main/java/org/libvirt/NetworkFilter.java +++ b/src/main/java/org/libvirt/NetworkFilter.java @@ -90,7 +90,7 @@ public class NetworkFilter { * @return the XML document */ public String getXMLDesc() throws LibvirtException { - return processError(libvirt.virNWFilterGetXMLDesc(NFP, 0)); + return processError(libvirt.virNWFilterGetXMLDesc(NFP, 0)).toString(); } /** diff --git a/src/main/java/org/libvirt/Secret.java b/src/main/java/org/libvirt/Secret.java index e0ded73..a5f13ac 100644 --- a/src/main/java/org/libvirt/Secret.java +++ b/src/main/java/org/libvirt/Secret.java @@ -127,7 +127,7 @@ public class Secret { * @return the XML document */ public String getXMLDesc() throws LibvirtException { - return processError(libvirt.virSecretGetXMLDesc(VSP, 0)); + return processError(libvirt.virSecretGetXMLDesc(VSP, 0)).toString(); } /** diff --git a/src/main/java/org/libvirt/StoragePool.java b/src/main/java/org/libvirt/StoragePool.java index 14ecab8..8caf9f5 100644 --- a/src/main/java/org/libvirt/StoragePool.java +++ b/src/main/java/org/libvirt/StoragePool.java @@ -207,7 +207,7 @@ public class StoragePool { * @return a XML document -java @throws LibvirtException */ public String getXMLDesc(int flags) throws LibvirtException { - return processError(libvirt.virStoragePoolGetXMLDesc(VSPP, flags)); + return processError(libvirt.virStoragePoolGetXMLDesc(VSPP, flags)).toString(); } /** diff --git a/src/main/java/org/libvirt/jna/CString.java b/src/main/java/org/libvirt/jna/CString.java new file mode 100644 index 0000000..b6d9dc2 --- /dev/null +++ b/src/main/java/org/libvirt/jna/CString.java @@ -0,0 +1,85 @@ +package org.libvirt.jna; + +import java.nio.charset.Charset; + +import com.sun.jna.FromNativeContext; +import com.sun.jna.Native; +import com.sun.jna.Pointer; +import com.sun.jna.PointerType; + +/** + * Represents an allocated C-String. + * <p> + * Either call {@link #toString} or {@link #free()}. Both methods make + * sure to reclaim the memory allocated for the string by calling + * Native.free. + */ +public class CString extends PointerType { + // all strings in libvirt are UTF-8 encoded + private final static Charset UTF8 = Charset.forName("UTF-8"); + private final static byte NUL = 0; + private String string = null; + + public CString() { + super(); + } + + public CString(Pointer p) { + super(p); + } + + /** + * Returns a String representing the value of this C-String + * <p> + * Side-effect: frees the memory of the C-String. + */ + @Override + public String toString() { + if (string == null) { + final Pointer ptr = getPointer(); + + if (ptr == null) return null; + + try { + // N.B. could be replaced with Pointer.getString(0L, "UTF-8") + // available in JNA >= 4.x + final long len = ptr.indexOf(0, NUL); + assert (len != -1): "C-Strings must be \\0 terminated."; + assert (len <= Integer.MAX_VALUE): "string length exceeded " + Integer.MAX_VALUE; + + if (len == 0) { + string = ""; + } else { + final byte[] data = ptr.getByteArray(0, (int)len); + + string = new String(data, UTF8); + } + } finally { + free(ptr); + } + } + return string; + } + + @Override + public CString fromNative(Object nativeValue, FromNativeContext context) { + if (nativeValue == null) return null; + + return new CString((Pointer)nativeValue); + } + + private void free(Pointer ptr) { + assert ptr != null; + + Native.free(Pointer.nativeValue(ptr)); + setPointer(null); + } + + /** + * Free the memory used by this C-String + */ + public void free() { + final Pointer ptr = getPointer(); + if (ptr != null) free(ptr); + } +} diff --git a/src/main/java/org/libvirt/jna/Libvirt.java b/src/main/java/org/libvirt/jna/Libvirt.java index a3cee0a..5a176b0 100644 --- a/src/main/java/org/libvirt/jna/Libvirt.java +++ b/src/main/java/org/libvirt/jna/Libvirt.java @@ -150,7 +150,7 @@ public interface Libvirt extends Library { public static int VIR_DOMAIN_SCHED_FIELD_LENGTH = 80; // Connection Functions - String virConnectBaselineCPU(ConnectionPointer virConnectPtr, String[] xmlCPUs, int ncpus, int flags); + CString virConnectBaselineCPU(ConnectionPointer virConnectPtr, String[] xmlCPUs, int ncpus, int flags); /** * @deprecated as of libvirt 0.6.0, all errors reported in the @@ -175,14 +175,14 @@ public interface Libvirt extends Library { int virConnectIsAlive(ConnectionPointer virConnectPtr); int virConnectIsEncrypted(ConnectionPointer virConnectPtr) ; int virConnectIsSecure(ConnectionPointer virConnectPtr) ; - String virConnectFindStoragePoolSources(ConnectionPointer virConnectPtr, String type, String srcSpec, int flags); + CString virConnectFindStoragePoolSources(ConnectionPointer virConnectPtr, String type, String srcSpec, int flags); Pointer virConnectGetCapabilities(ConnectionPointer virConnectPtr); Pointer virConnectGetHostname(ConnectionPointer virConnectPtr); int virConnectGetLibVersion(ConnectionPointer virConnectPtr, LongByReference libVer); int virConnectGetMaxVcpus(ConnectionPointer virConnectPtr, String type); Pointer virConnectGetSysinfo(ConnectionPointer virConnectPtr, int flags); String virConnectGetType(ConnectionPointer virConnectPtr); - String virConnectGetURI(ConnectionPointer virConnectPtr); + CString virConnectGetURI(ConnectionPointer virConnectPtr); int virConnectGetVersion(ConnectionPointer virConnectPtr, LongByReference hvVer); int virConnectListDefinedDomains(ConnectionPointer virConnectPtr, Pointer[] name, int maxnames); int virConnectListDefinedNetworks(ConnectionPointer virConnectPtr, Pointer[] name, int maxnames); @@ -218,9 +218,9 @@ public interface Libvirt extends Library { @Deprecated virError virConnGetLastError(ConnectionPointer virConnectPtr); void virConnResetLastError(ConnectionPointer virConnectPtr); - String virConnectDomainXMLFromNative(ConnectionPointer virConnectPtr, String nativeFormat, + CString virConnectDomainXMLFromNative(ConnectionPointer virConnectPtr, String nativeFormat, String nativeConfig, int flags); - String virConnectDomainXMLToNative(ConnectionPointer virConnectPtr, String nativeFormat, String domainXML, + CString virConnectDomainXMLToNative(ConnectionPointer virConnectPtr, String nativeFormat, String domainXML, int flags); // Global functions @@ -350,7 +350,7 @@ public interface Libvirt extends Library { String virNodeDeviceGetParent(DevicePointer virDevicePointer); int virNodeDeviceNumOfCaps(DevicePointer virDevicePointer); int virNodeDeviceListCaps(DevicePointer virDevicePointer, Pointer[] names, int maxNames); - String virNodeDeviceGetXMLDesc(DevicePointer virDevicePointer, int flags); + CString virNodeDeviceGetXMLDesc(DevicePointer virDevicePointer, int flags); int virNodeDeviceFree(DevicePointer virDevicePointer); int virNodeDeviceDettach(DevicePointer virDevicePointer); int virNodeDeviceReAttach(DevicePointer virDevicePointer); @@ -371,7 +371,7 @@ public interface Libvirt extends Library { String virStoragePoolGetName(StoragePoolPointer storagePoolPtr); int virStoragePoolGetUUID(StoragePoolPointer storagePoolPtr, byte[] uuidString); int virStoragePoolGetUUIDString(StoragePoolPointer storagePoolPtr, byte[] uuidString); - String virStoragePoolGetXMLDesc(StoragePoolPointer storagePoolPtr, int flags); + CString virStoragePoolGetXMLDesc(StoragePoolPointer storagePoolPtr, int flags); int virStoragePoolListVolumes(StoragePoolPointer storagePoolPtr, Pointer[] names, int maxnames); int virStoragePoolIsActive(StoragePoolPointer storagePoolPtr); int virStoragePoolIsPersistent(StoragePoolPointer storagePoolPtr); @@ -422,7 +422,7 @@ public interface Libvirt extends Library { String virSecretGetUsageID(SecretPointer virSecretPtr); int virSecretGetUsageType(SecretPointer virSecretPtr); Pointer virSecretGetValue(SecretPointer virSecretPtr, SizeTByReference value_size, int flags); - String virSecretGetXMLDesc(SecretPointer virSecretPtr, int flags); + CString virSecretGetXMLDesc(SecretPointer virSecretPtr, int flags); SecretPointer virSecretLookupByUsage(ConnectionPointer virConnectPtr, int usageType, String usageID); SecretPointer virSecretLookupByUUID(ConnectionPointer virConnectPtr, byte[] uuidBytes); SecretPointer virSecretLookupByUUIDString(ConnectionPointer virConnectPtr, String uuidstr); @@ -455,7 +455,7 @@ public interface Libvirt extends Library { int virDomainSnapshotNum(DomainPointer virDomainPtr, int flags); // Network Filter Methods - String virNWFilterGetXMLDesc(NetworkFilterPointer virNWFilterPtr, int flags); + CString virNWFilterGetXMLDesc(NetworkFilterPointer virNWFilterPtr, int flags); NetworkFilterPointer virNWFilterDefineXML(ConnectionPointer virConnectPtr, String xml); int virNWFilterFree(NetworkFilterPointer virNWFilterPtr); NetworkFilterPointer virNWFilterLookupByName(ConnectionPointer virConnectPtr, String name); -- 2.2.2

Make use of the CString class introduced recently and get rid of some boilerplate code required to release memory at the calling side. --- src/main/java/org/libvirt/Connect.java | 22 +++--------------- src/main/java/org/libvirt/Domain.java | 33 +++++++-------------------- src/main/java/org/libvirt/DomainSnapshot.java | 8 +------ src/main/java/org/libvirt/Interface.java | 7 +----- src/main/java/org/libvirt/Network.java | 14 ++---------- src/main/java/org/libvirt/StorageVol.java | 16 ++----------- src/main/java/org/libvirt/jna/Libvirt.java | 26 ++++++++++----------- 7 files changed, 30 insertions(+), 96 deletions(-) diff --git a/src/main/java/org/libvirt/Connect.java b/src/main/java/org/libvirt/Connect.java index d0bdc4d..437f423 100644 --- a/src/main/java/org/libvirt/Connect.java +++ b/src/main/java/org/libvirt/Connect.java @@ -978,12 +978,7 @@ public class Connect { * description</a> */ public String getCapabilities() throws LibvirtException { - Pointer ptr = processError(libvirt.virConnectGetCapabilities(VCP)); - try { - return Library.getString(ptr); - } finally { - Library.free(ptr); - } + return processError(libvirt.virConnectGetCapabilities(VCP)).toString(); } /** @@ -1014,12 +1009,7 @@ public class Connect { * @throws LibvirtException */ public String getHostName() throws LibvirtException { - Pointer ptr = processError(libvirt.virConnectGetHostname(VCP)); - try { - return Library.getString(ptr); - } finally { - Library.free(ptr); - } + return processError(libvirt.virConnectGetHostname(VCP)).toString(); } /** @@ -1083,13 +1073,7 @@ public class Connect { * @since 1.5.2 */ public String getSysinfo() throws LibvirtException { - Pointer p = processError(libvirt.virConnectGetSysinfo(this.VCP, 0)); - - try { - return Library.getString(p); - } finally { - Library.free(p); - } + return processError(libvirt.virConnectGetSysinfo(this.VCP, 0)).toString(); } /** diff --git a/src/main/java/org/libvirt/Domain.java b/src/main/java/org/libvirt/Domain.java index ab646de..087a06f 100644 --- a/src/main/java/org/libvirt/Domain.java +++ b/src/main/java/org/libvirt/Domain.java @@ -4,6 +4,7 @@ import java.nio.ByteBuffer; import java.util.concurrent.TimeUnit; import org.libvirt.event.IOErrorListener; +import org.libvirt.jna.CString; import org.libvirt.jna.DomainPointer; import org.libvirt.jna.DomainSnapshotPointer; import org.libvirt.jna.Libvirt; @@ -589,12 +590,7 @@ public class Domain { * @throws LibvirtException */ public String getOSType() throws LibvirtException { - Pointer ptr = processError(libvirt.virDomainGetOSType(VDP)); - try { - return Library.getString(ptr); - } finally { - Library.free(ptr); - } + return processError(libvirt.virDomainGetOSType(VDP)).toString(); } /** @@ -605,7 +601,7 @@ public class Domain { */ public SchedParameter[] getSchedulerParameters() throws LibvirtException { IntByReference nParams = new IntByReference(); - Library.free(processError(libvirt.virDomainGetSchedulerType(VDP, nParams))); + processError(libvirt.virDomainGetSchedulerType(VDP, nParams)); int n = nParams.getValue(); @@ -637,12 +633,7 @@ public class Domain { * @throws LibvirtException */ public String getSchedulerType() throws LibvirtException { - Pointer pScheduler = processError(libvirt.virDomainGetSchedulerType(VDP, null)); - try { - return Library.getString(pScheduler); - } finally { - Library.free(pScheduler); - } + return processError(libvirt.virDomainGetSchedulerType(VDP, null)).toString(); } /** @@ -725,12 +716,7 @@ public class Domain { * Description format </a> */ public String getXMLDesc(int flags) throws LibvirtException { - Pointer ptr = processError(libvirt.virDomainGetXMLDesc(VDP, flags)); - try { - return Library.getString(ptr); - } finally { - Library.free(ptr); - } + return processError(libvirt.virDomainGetXMLDesc(VDP, flags)).toString(); } /** @@ -1290,13 +1276,10 @@ public class Domain { } public String screenshot(Stream stream, int screen) throws LibvirtException { - Pointer ptr = processError(libvirt.virDomainScreenshot(this.VDP, stream.getVSP(), screen, 0)); + CString mimeType = libvirt.virDomainScreenshot(this.VDP, stream.getVSP(), screen, 0); + processError(mimeType); stream.markReadable(); - try { - return Library.getString(ptr); - } finally { - Library.free(ptr); - } + return mimeType.toString(); } /** diff --git a/src/main/java/org/libvirt/DomainSnapshot.java b/src/main/java/org/libvirt/DomainSnapshot.java index 3013117..ad49724 100644 --- a/src/main/java/org/libvirt/DomainSnapshot.java +++ b/src/main/java/org/libvirt/DomainSnapshot.java @@ -73,12 +73,6 @@ public class DomainSnapshot { * @return the XML document */ public String getXMLDesc() throws LibvirtException { - Pointer p = processError(libvirt.virDomainSnapshotGetXMLDesc(VDSP, 0)); - - try { - return Library.getString(p); - } finally { - Library.free(p); - } + return processError(libvirt.virDomainSnapshotGetXMLDesc(VDSP, 0)).toString(); } } diff --git a/src/main/java/org/libvirt/Interface.java b/src/main/java/org/libvirt/Interface.java index 4c9670c..2c29a35 100644 --- a/src/main/java/org/libvirt/Interface.java +++ b/src/main/java/org/libvirt/Interface.java @@ -120,12 +120,7 @@ public class Interface { * @throws LibvirtException */ public String getXMLDescription(int flags) throws LibvirtException { - Pointer xml = processError(libvirt.virInterfaceGetXMLDesc(VIP, flags)); - try { - return Library.getString(xml); - } finally { - Library.free(xml); - } + return processError(libvirt.virInterfaceGetXMLDesc(VIP, flags)).toString(); } /** diff --git a/src/main/java/org/libvirt/Network.java b/src/main/java/org/libvirt/Network.java index 2a77028..9f493f7 100644 --- a/src/main/java/org/libvirt/Network.java +++ b/src/main/java/org/libvirt/Network.java @@ -103,12 +103,7 @@ public class Network { * @throws LibvirtException */ public String getBridgeName() throws LibvirtException { - final Pointer ptr = processError(libvirt.virNetworkGetBridgeName(VNP)); - try { - return Library.getString(ptr); - } finally { - Library.free(ptr); - } + return processError(libvirt.virNetworkGetBridgeName(VNP)).toString(); } /** @@ -167,12 +162,7 @@ public class Network { * @throws LibvirtException */ public String getXMLDesc(int flags) throws LibvirtException { - Pointer ptr = processError(libvirt.virNetworkGetXMLDesc(VNP, flags)); - try { - return Library.getString(ptr); - } finally { - Library.free(ptr); - } + return processError(libvirt.virNetworkGetXMLDesc(VNP, flags)).toString(); } /** diff --git a/src/main/java/org/libvirt/StorageVol.java b/src/main/java/org/libvirt/StorageVol.java index 47b79f6..3b1533e 100644 --- a/src/main/java/org/libvirt/StorageVol.java +++ b/src/main/java/org/libvirt/StorageVol.java @@ -163,13 +163,7 @@ public class StorageVol { * @throws LibvirtException */ public String getPath() throws LibvirtException { - Pointer p = processError(libvirt.virStorageVolGetPath(VSVP)); - - try { - return Library.getString(p); - } finally { - Library.free(p); - } + return processError(libvirt.virStorageVolGetPath(VSVP)).toString(); } /** @@ -181,13 +175,7 @@ public class StorageVol { * @throws LibvirtException */ public String getXMLDesc(int flags) throws LibvirtException { - Pointer p = processError(libvirt.virStorageVolGetXMLDesc(VSVP, flags)); - - try { - return Library.getString(p); - } finally { - Library.free(p); - } + return processError(libvirt.virStorageVolGetXMLDesc(VSVP, flags)).toString(); } /** diff --git a/src/main/java/org/libvirt/jna/Libvirt.java b/src/main/java/org/libvirt/jna/Libvirt.java index 5a176b0..c6b7153 100644 --- a/src/main/java/org/libvirt/jna/Libvirt.java +++ b/src/main/java/org/libvirt/jna/Libvirt.java @@ -176,11 +176,11 @@ public interface Libvirt extends Library { int virConnectIsEncrypted(ConnectionPointer virConnectPtr) ; int virConnectIsSecure(ConnectionPointer virConnectPtr) ; CString virConnectFindStoragePoolSources(ConnectionPointer virConnectPtr, String type, String srcSpec, int flags); - Pointer virConnectGetCapabilities(ConnectionPointer virConnectPtr); - Pointer virConnectGetHostname(ConnectionPointer virConnectPtr); + CString virConnectGetCapabilities(ConnectionPointer virConnectPtr); + CString virConnectGetHostname(ConnectionPointer virConnectPtr); int virConnectGetLibVersion(ConnectionPointer virConnectPtr, LongByReference libVer); int virConnectGetMaxVcpus(ConnectionPointer virConnectPtr, String type); - Pointer virConnectGetSysinfo(ConnectionPointer virConnectPtr, int flags); + CString virConnectGetSysinfo(ConnectionPointer virConnectPtr, int flags); String virConnectGetType(ConnectionPointer virConnectPtr); CString virConnectGetURI(ConnectionPointer virConnectPtr); int virConnectGetVersion(ConnectionPointer virConnectPtr, LongByReference hvVer); @@ -261,14 +261,14 @@ public interface Libvirt extends Library { NativeLong virDomainGetMaxMemory(DomainPointer virDomainPtr); int virDomainGetMaxVcpus(DomainPointer virDomainPtr); String virDomainGetName(DomainPointer virDomainPtr); - Pointer virDomainGetOSType(DomainPointer virDomainPtr); + CString virDomainGetOSType(DomainPointer virDomainPtr); int virDomainGetSchedulerParameters(DomainPointer virDomainPtr, virSchedParameter[] params, IntByReference nparams); - Pointer virDomainGetSchedulerType(DomainPointer virDomainPtr, IntByReference nparams); + CString virDomainGetSchedulerType(DomainPointer virDomainPtr, IntByReference nparams); int virDomainGetUUID(DomainPointer virDomainPtr, byte[] uuidString); int virDomainGetUUIDString(DomainPointer virDomainPtr, byte[] uuidString); int virDomainGetVcpus(DomainPointer virDomainPtr, virVcpuInfo[] info, int maxInfo, byte[] cpumaps, int maplen); - Pointer virDomainGetXMLDesc(DomainPointer virDomainPtr, int flags); + CString virDomainGetXMLDesc(DomainPointer virDomainPtr, int flags); int virDomainHasCurrentSnapshot(DomainPointer virDomainPtr, int flags); int virDomainHasManagedSaveImage(DomainPointer virDomainPtr, int flags); int virDomainInterfaceStats(DomainPointer virDomainPtr, String path, virDomainInterfaceStats stats, SizeT size); @@ -303,7 +303,7 @@ public interface Libvirt extends Library { int virDomainResume(DomainPointer virDomainPtr); int virDomainSave(DomainPointer virDomainPtr, String to); int virDomainSendKey(DomainPointer virDomainPtr, int codeset, int holdtime, int[] keycodes, int nkeycodes, int flags); - Pointer virDomainScreenshot(DomainPointer virDomainPtr, StreamPointer virStreamPtr, int screen, int flags); + CString virDomainScreenshot(DomainPointer virDomainPtr, StreamPointer virStreamPtr, int screen, int flags); int virDomainSetAutostart(DomainPointer virDomainPtr, int autoStart); int virDomainSetMaxMemory(DomainPointer virDomainPtr, NativeLong maxMemory); int virDomainSetMemory(DomainPointer virDomainPtr, NativeLong maxMemory); @@ -322,11 +322,11 @@ public interface Libvirt extends Library { int virNetworkDestroy(NetworkPointer virConnectPtr); int virNetworkFree(NetworkPointer virConnectPtr); int virNetworkGetAutostart(NetworkPointer virNetworkPtr, IntByReference value); - Pointer virNetworkGetBridgeName(NetworkPointer virNetworkPtr); + CString virNetworkGetBridgeName(NetworkPointer virNetworkPtr); String virNetworkGetName(NetworkPointer virNetworkPtr); int virNetworkGetUUID(NetworkPointer virNetworkPtr, byte[] uuidString); int virNetworkGetUUIDString(NetworkPointer virNetworkPtr, byte[] uuidString); - Pointer virNetworkGetXMLDesc(NetworkPointer virNetworkPtr, int flags); + CString virNetworkGetXMLDesc(NetworkPointer virNetworkPtr, int flags); int virNetworkIsActive(NetworkPointer virNetworkPtr); int virNetworkIsPersistent(NetworkPointer virNetworkPtr); NetworkPointer virNetworkLookupByName(ConnectionPointer virConnectPtr, String name); @@ -393,8 +393,8 @@ public interface Libvirt extends Library { int virStorageVolGetInfo(StorageVolPointer storageVolPtr, virStorageVolInfo info); String virStorageVolGetKey(StorageVolPointer storageVolPtr); String virStorageVolGetName(StorageVolPointer storageVolPtr); - Pointer virStorageVolGetPath(StorageVolPointer storageVolPtr); - Pointer virStorageVolGetXMLDesc(StorageVolPointer storageVolPtr, int flags); + CString virStorageVolGetPath(StorageVolPointer storageVolPtr); + CString virStorageVolGetXMLDesc(StorageVolPointer storageVolPtr, int flags); StorageVolPointer virStorageVolLookupByKey(ConnectionPointer virConnectPtr, String name); StorageVolPointer virStorageVolLookupByName(StoragePoolPointer storagePoolPtr, String name); StorageVolPointer virStorageVolLookupByPath(ConnectionPointer virConnectPtr, String path); @@ -408,7 +408,7 @@ public interface Libvirt extends Library { int virInterfaceFree(InterfacePointer virDevicePointer); String virInterfaceGetName(InterfacePointer virInterfacePtr); String virInterfaceGetMACString(InterfacePointer virInterfacePtr); - Pointer virInterfaceGetXMLDesc(InterfacePointer virInterfacePtr, int flags); + CString virInterfaceGetXMLDesc(InterfacePointer virInterfacePtr, int flags); int virInterfaceIsActive(InterfacePointer virDevicePointer); InterfacePointer virInterfaceLookupByMACString(ConnectionPointer virConnectPtr, String mac); InterfacePointer virInterfaceLookupByName(ConnectionPointer virConnectPtr, String name); @@ -448,7 +448,7 @@ public interface Libvirt extends Library { DomainSnapshotPointer virDomainSnapshotCreateXML(DomainPointer virDomainPtr, String xmlDesc, int flags); DomainSnapshotPointer virDomainSnapshotCurrent(DomainPointer virDomainPtr, int flags); int virDomainSnapshotDelete(DomainSnapshotPointer virDomainSnapshotPtr, int flags); - Pointer virDomainSnapshotGetXMLDesc(DomainSnapshotPointer virDomainSnapshotPtr, int flags); + CString virDomainSnapshotGetXMLDesc(DomainSnapshotPointer virDomainSnapshotPtr, int flags); int virDomainSnapshotFree(DomainSnapshotPointer virDomainSnapshotPtr); int virDomainSnapshotListNames(DomainPointer virDomainPtr, Pointer[] names, int nameslen, int flags); DomainSnapshotPointer virDomainSnapshotLookupByName(DomainPointer virDomainPtr, String name, int flags); -- 2.2.2

Change the prototypes of the JNA library interface in order to take advantage of the CString class. This removes a fair amount of code in the org.libvirt.Library class and puts the decoding of C string data into a single place. --- src/main/java/org/libvirt/Connect.java | 20 +++++++------- src/main/java/org/libvirt/Device.java | 7 +++-- src/main/java/org/libvirt/Domain.java | 6 ++-- src/main/java/org/libvirt/Library.java | 44 ++++++++---------------------- src/main/java/org/libvirt/StoragePool.java | 7 +++-- src/main/java/org/libvirt/jna/Libvirt.java | 26 +++++++++--------- 6 files changed, 46 insertions(+), 64 deletions(-) diff --git a/src/main/java/org/libvirt/Connect.java b/src/main/java/org/libvirt/Connect.java index 437f423..1d37c22 100644 --- a/src/main/java/org/libvirt/Connect.java +++ b/src/main/java/org/libvirt/Connect.java @@ -1183,7 +1183,7 @@ public class Connect { public String[] listDefinedDomains() throws LibvirtException { int maxnames = numOfDefinedDomains(); if (maxnames > 0) { - final Pointer[] names = new Pointer[maxnames]; + final CString[] names = new CString[maxnames]; final int n = processError(libvirt.virConnectListDefinedDomains(VCP, names, maxnames)); return Library.toStringArray(names, n); } else { @@ -1201,7 +1201,7 @@ public class Connect { public String[] listDefinedInterfaces() throws LibvirtException { final int max = numOfDefinedInterfaces(); if (max > 0) { - final Pointer[] ifs = new Pointer[max]; + final CString[] ifs = new CString[max]; final int n = processError(libvirt.virConnectListDefinedInterfaces(VCP, ifs, max)); return Library.toStringArray(ifs, n); } else { @@ -1219,7 +1219,7 @@ public class Connect { public String[] listDefinedNetworks() throws LibvirtException { int maxnames = numOfDefinedNetworks(); if (maxnames > 0) { - final Pointer[] names = new Pointer[maxnames]; + final CString[] names = new CString[maxnames]; final int n = processError(libvirt.virConnectListDefinedNetworks(VCP, names, maxnames)); return Library.toStringArray(names, n); } else { @@ -1237,7 +1237,7 @@ public class Connect { public String[] listDefinedStoragePools() throws LibvirtException { int num = numOfDefinedStoragePools(); if (num > 0) { - Pointer[] pools = new Pointer[num]; + CString[] pools = new CString[num]; final int n = processError(libvirt.virConnectListDefinedStoragePools(VCP, pools, num)); return Library.toStringArray(pools, n); } else { @@ -1254,7 +1254,7 @@ public class Connect { public String[] listDevices(String capabilityName) throws LibvirtException { int maxDevices = numOfDevices(capabilityName); if (maxDevices > 0) { - Pointer[] names = new Pointer[maxDevices]; + CString[] names = new CString[maxDevices]; final int n = processError(libvirt.virNodeListDevices(VCP, capabilityName, names, maxDevices, 0)); return Library.toStringArray(names, n); } else { @@ -1288,7 +1288,7 @@ public class Connect { public String[] listInterfaces() throws LibvirtException { int num = numOfInterfaces(); if (num > 0) { - Pointer[] ifs = new Pointer[num]; + CString[] ifs = new CString[num]; final int n = processError(libvirt.virConnectListInterfaces(VCP, ifs, num)); return Library.toStringArray(ifs, n); } else { @@ -1305,7 +1305,7 @@ public class Connect { public String[] listNetworkFilters() throws LibvirtException { int maxnames = numOfNetworkFilters(); if (maxnames > 0) { - Pointer[] names = new Pointer[maxnames]; + CString[] names = new CString[maxnames]; final int n = processError(libvirt.virConnectListNWFilters(VCP, names, maxnames)); return Library.toStringArray(names, n); } else { @@ -1323,7 +1323,7 @@ public class Connect { public String[] listNetworks() throws LibvirtException { int maxnames = numOfNetworks(); if (maxnames > 0) { - Pointer[] names = new Pointer[maxnames]; + CString[] names = new CString[maxnames]; final int n = processError(libvirt.virConnectListNetworks(VCP, names, maxnames)); return Library.toStringArray(names, n); } else { @@ -1340,7 +1340,7 @@ public class Connect { public String[] listSecrets() throws LibvirtException { int num = numOfSecrets(); if (num > 0) { - Pointer[] returnValue = new Pointer[num]; + CString[] returnValue = new CString[num]; final int n = processError(libvirt.virConnectListSecrets(VCP, returnValue, num)); return Library.toStringArray(returnValue, n); } else { @@ -1358,7 +1358,7 @@ public class Connect { public String[] listStoragePools() throws LibvirtException { int num = numOfStoragePools(); if (num > 0) { - Pointer[] returnValue = new Pointer[num]; + CString[] returnValue = new CString[num]; final int n = processError(libvirt.virConnectListStoragePools(VCP, returnValue, num)); return Library.toStringArray(returnValue, n); } else { diff --git a/src/main/java/org/libvirt/Device.java b/src/main/java/org/libvirt/Device.java index 04f373e..6becbca 100644 --- a/src/main/java/org/libvirt/Device.java +++ b/src/main/java/org/libvirt/Device.java @@ -1,5 +1,6 @@ package org.libvirt; +import org.libvirt.jna.CString; import org.libvirt.jna.DevicePointer; import static org.libvirt.Library.libvirt; import static org.libvirt.ErrorHandler.processError; @@ -130,10 +131,10 @@ public class Device { int maxCaps = getNumberOfCapabilities(); if (maxCaps > 0) { - Pointer[] ptrs = new Pointer[maxCaps]; - int got = processError(libvirt.virNodeDeviceListCaps(VDP, ptrs, maxCaps)); + CString[] strings = new CString[maxCaps]; + int got = processError(libvirt.virNodeDeviceListCaps(VDP, strings, maxCaps)); - return Library.toStringArray(ptrs, got); + return Library.toStringArray(strings, got); } else { return Library.NO_STRINGS; } diff --git a/src/main/java/org/libvirt/Domain.java b/src/main/java/org/libvirt/Domain.java index 087a06f..ed6690c 100644 --- a/src/main/java/org/libvirt/Domain.java +++ b/src/main/java/org/libvirt/Domain.java @@ -1437,10 +1437,10 @@ public class Domain { public String[] snapshotListNames(int flags) throws LibvirtException { int num = snapshotNum(); if (num > 0) { - Pointer[] ptrs = new Pointer[num]; - int got = processError(libvirt.virDomainSnapshotListNames(VDP, ptrs, num, flags)); + CString[] names = new CString[num]; + int got = processError(libvirt.virDomainSnapshotListNames(VDP, names, num, flags)); - return Library.toStringArray(ptrs, got); + return Library.toStringArray(names, got); } else { return Library.NO_STRINGS; } diff --git a/src/main/java/org/libvirt/Library.java b/src/main/java/org/libvirt/Library.java index ac89de4..7ce986d 100644 --- a/src/main/java/org/libvirt/Library.java +++ b/src/main/java/org/libvirt/Library.java @@ -2,6 +2,7 @@ package org.libvirt; import org.libvirt.jna.Libvirt; import org.libvirt.jna.Libvirt.VirEventTimeoutCallback; +import org.libvirt.jna.CString; import static org.libvirt.ErrorHandler.processError; import com.sun.jna.Native; @@ -71,46 +72,25 @@ public final class Library { } /** - * Convert the data pointed to by {@code ptr} to a String. - */ - static String getString(Pointer ptr) { - final long len = ptr.indexOf(0, (byte)0); - assert (len != -1): "C-Strings must be \\0 terminated."; - - final byte[] data = ptr.getByteArray(0, (int)len); - try { - return new String(data, "utf-8"); - } catch (java.io.UnsupportedEncodingException e) { - throw new RuntimeException("Libvirt problem: UTF-8 decoding error.", e); - } - } - - /** - * Calls {@link #toStringArray(Pointer[], int)}. - */ - static String[] toStringArray(Pointer[] ptrArr) { - return toStringArray(ptrArr, ptrArr.length); - } - - /** - * Convert the given array of native pointers to "char" in - * UTF-8 encoding to an array of Strings. + * Convert the given array of UTF-8 encoded C-Strings to an array + * of Strings. * * \note The memory used by the elements of the original array - * is freed and ptrArr is modified. + * is freed. */ - static String[] toStringArray(Pointer[] ptrArr, final int size) { + static String[] toStringArray(CString[] cstrarr, final int size) { + int i = 0; try { final String[] result = new String[size]; - for (int i = 0; i < size; ++i) { - result[i] = Library.getString(ptrArr[i]); + for (; i < size; ++i) { + result[i] = cstrarr[i].toString(); } return result; - } finally { - for (int i = 0; i < size; ++i) { - Library.free(ptrArr[i]); - ptrArr[i] = null; + } catch (Exception e) { + for (; i < size; ++i) { + if (cstrarr[i] != null) cstrarr[i].free(); } + throw e; } } diff --git a/src/main/java/org/libvirt/StoragePool.java b/src/main/java/org/libvirt/StoragePool.java index 8caf9f5..04870bf 100644 --- a/src/main/java/org/libvirt/StoragePool.java +++ b/src/main/java/org/libvirt/StoragePool.java @@ -1,5 +1,6 @@ package org.libvirt; +import org.libvirt.jna.CString; import org.libvirt.jna.Libvirt; import org.libvirt.jna.StoragePoolPointer; import org.libvirt.jna.StorageVolPointer; @@ -247,11 +248,11 @@ public class StoragePool { public String[] listVolumes() throws LibvirtException { int num = numOfVolumes(); if (num > 0) { - Pointer[] ptrs = new Pointer[num]; + CString[] names = new CString[num]; - int got = processError(libvirt.virStoragePoolListVolumes(VSPP, ptrs, num)); + int got = processError(libvirt.virStoragePoolListVolumes(VSPP, names, num)); - return Library.toStringArray(ptrs, got); + return Library.toStringArray(names, got); } else { return Library.NO_STRINGS; } diff --git a/src/main/java/org/libvirt/jna/Libvirt.java b/src/main/java/org/libvirt/jna/Libvirt.java index c6b7153..3589525 100644 --- a/src/main/java/org/libvirt/jna/Libvirt.java +++ b/src/main/java/org/libvirt/jna/Libvirt.java @@ -184,16 +184,16 @@ public interface Libvirt extends Library { String virConnectGetType(ConnectionPointer virConnectPtr); CString virConnectGetURI(ConnectionPointer virConnectPtr); int virConnectGetVersion(ConnectionPointer virConnectPtr, LongByReference hvVer); - int virConnectListDefinedDomains(ConnectionPointer virConnectPtr, Pointer[] name, int maxnames); - int virConnectListDefinedNetworks(ConnectionPointer virConnectPtr, Pointer[] name, int maxnames); - int virConnectListDefinedStoragePools(ConnectionPointer virConnectPtr, Pointer[] names, int maxnames); - int virConnectListDefinedInterfaces(ConnectionPointer virConnectPtr, Pointer[] name, int maxNames); + int virConnectListDefinedDomains(ConnectionPointer virConnectPtr, CString[] name, int maxnames); + int virConnectListDefinedNetworks(ConnectionPointer virConnectPtr, CString[] name, int maxnames); + int virConnectListDefinedStoragePools(ConnectionPointer virConnectPtr, CString[] names, int maxnames); + int virConnectListDefinedInterfaces(ConnectionPointer virConnectPtr, CString[] name, int maxNames); int virConnectListDomains(ConnectionPointer virConnectPtr, int[] ids, int maxnames); - int virConnectListInterfaces(ConnectionPointer virConnectPtr, Pointer[] name, int maxNames); - int virConnectListNetworks(ConnectionPointer virConnectPtr, Pointer[] name, int maxnames); - int virConnectListNWFilters(ConnectionPointer virConnectPtr, Pointer[] name, int maxnames); - int virConnectListSecrets(ConnectionPointer virConnectPtr, Pointer[] uids, int maxUids); - int virConnectListStoragePools(ConnectionPointer virConnectPtr, Pointer[] names, int maxnames); + int virConnectListInterfaces(ConnectionPointer virConnectPtr, CString[] name, int maxNames); + int virConnectListNetworks(ConnectionPointer virConnectPtr, CString[] name, int maxnames); + int virConnectListNWFilters(ConnectionPointer virConnectPtr, CString[] name, int maxnames); + int virConnectListSecrets(ConnectionPointer virConnectPtr, CString[] uids, int maxUids); + int virConnectListStoragePools(ConnectionPointer virConnectPtr, CString[] names, int maxnames); int virConnectNumOfDefinedDomains(ConnectionPointer virConnectPtr); int virConnectNumOfDefinedNetworks(ConnectionPointer virConnectPtr); int virConnectNumOfDefinedInterfaces(ConnectionPointer virConnectPtr); @@ -343,13 +343,13 @@ public interface Libvirt extends Library { // Node/Device functions int virNodeNumOfDevices(ConnectionPointer virConnectPtr, String capabilityName, int flags); - int virNodeListDevices(ConnectionPointer virConnectPtr, String capabilityName, Pointer[] names, int maxnames, + int virNodeListDevices(ConnectionPointer virConnectPtr, String capabilityName, CString[] names, int maxnames, int flags); DevicePointer virNodeDeviceLookupByName(ConnectionPointer virConnectPtr, String name); String virNodeDeviceGetName(DevicePointer virDevicePointer); String virNodeDeviceGetParent(DevicePointer virDevicePointer); int virNodeDeviceNumOfCaps(DevicePointer virDevicePointer); - int virNodeDeviceListCaps(DevicePointer virDevicePointer, Pointer[] names, int maxNames); + int virNodeDeviceListCaps(DevicePointer virDevicePointer, CString[] names, int maxNames); CString virNodeDeviceGetXMLDesc(DevicePointer virDevicePointer, int flags); int virNodeDeviceFree(DevicePointer virDevicePointer); int virNodeDeviceDettach(DevicePointer virDevicePointer); @@ -372,7 +372,7 @@ public interface Libvirt extends Library { int virStoragePoolGetUUID(StoragePoolPointer storagePoolPtr, byte[] uuidString); int virStoragePoolGetUUIDString(StoragePoolPointer storagePoolPtr, byte[] uuidString); CString virStoragePoolGetXMLDesc(StoragePoolPointer storagePoolPtr, int flags); - int virStoragePoolListVolumes(StoragePoolPointer storagePoolPtr, Pointer[] names, int maxnames); + int virStoragePoolListVolumes(StoragePoolPointer storagePoolPtr, CString[] names, int maxnames); int virStoragePoolIsActive(StoragePoolPointer storagePoolPtr); int virStoragePoolIsPersistent(StoragePoolPointer storagePoolPtr); StoragePoolPointer virStoragePoolLookupByName(ConnectionPointer virConnectPtr, String name); @@ -450,7 +450,7 @@ public interface Libvirt extends Library { int virDomainSnapshotDelete(DomainSnapshotPointer virDomainSnapshotPtr, int flags); CString virDomainSnapshotGetXMLDesc(DomainSnapshotPointer virDomainSnapshotPtr, int flags); int virDomainSnapshotFree(DomainSnapshotPointer virDomainSnapshotPtr); - int virDomainSnapshotListNames(DomainPointer virDomainPtr, Pointer[] names, int nameslen, int flags); + int virDomainSnapshotListNames(DomainPointer virDomainPtr, CString[] names, int nameslen, int flags); DomainSnapshotPointer virDomainSnapshotLookupByName(DomainPointer virDomainPtr, String name, int flags); int virDomainSnapshotNum(DomainPointer virDomainPtr, int flags); -- 2.2.2

This wraps the native virDomainGetSecurityLabel libvirt function available since version 0.6.1. --- src/main/java/org/libvirt/Domain.java | 18 ++++++++++ src/main/java/org/libvirt/SecurityLabel.java | 49 ++++++++++++++++++++++++++++ src/main/java/org/libvirt/jna/Libvirt.java | 24 +++++++++++++- 3 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 src/main/java/org/libvirt/SecurityLabel.java diff --git a/src/main/java/org/libvirt/Domain.java b/src/main/java/org/libvirt/Domain.java index ed6690c..83a500c 100644 --- a/src/main/java/org/libvirt/Domain.java +++ b/src/main/java/org/libvirt/Domain.java @@ -637,6 +637,24 @@ public class Domain { } /** + * Get the security label of an active domain. + * + * @return the SecurityLabel or {@code null} if the domain is not + * running under a security model + * @throws LibvirtException + */ + public SecurityLabel getSecurityLabel() throws LibvirtException { + Libvirt.SecurityLabel seclabel = new Libvirt.SecurityLabel(); + + processError(libvirt.virDomainGetSecurityLabel(this.VDP, seclabel)); + + if (seclabel.label[0] == 0) + return null; + else + return new SecurityLabel(seclabel); + } + + /** * Get the UUID for this domain. * * @return the UUID as an unpacked int array diff --git a/src/main/java/org/libvirt/SecurityLabel.java b/src/main/java/org/libvirt/SecurityLabel.java new file mode 100644 index 0000000..60132ba --- /dev/null +++ b/src/main/java/org/libvirt/SecurityLabel.java @@ -0,0 +1,49 @@ +package org.libvirt; + +import org.libvirt.jna.Libvirt; +import com.sun.jna.Native; + +/** + * Represents a security label used for mandatory access control. + * + * @see Domain#getSecurityLabel + */ +public final class SecurityLabel { + private String label; + private boolean enforced; + private static byte NUL = 0; + + SecurityLabel(Libvirt.SecurityLabel seclabel) { + label = Native.toString(seclabel.label, "UTF-8"); + enforced = seclabel.enforcing == 1; + } + + /** + * Returns the label of this SecurityLabel. + * + * @return the security label string + */ + public String getLabel() { + return label; + } + + /** + * Returns true if the security policy is being enforced. + * + * @return true if the policy is enforced, false otherwise + */ + public boolean isEnforced() { + return enforced; + } + + @Override + public String toString() { + return new StringBuilder() + .append("(label=") + .append(label) + .append(", enforced=") + .append(enforced) + .append(")") + .toString(); + } +} diff --git a/src/main/java/org/libvirt/jna/Libvirt.java b/src/main/java/org/libvirt/jna/Libvirt.java index 3589525..2958233 100644 --- a/src/main/java/org/libvirt/jna/Libvirt.java +++ b/src/main/java/org/libvirt/jna/Libvirt.java @@ -8,9 +8,13 @@ import com.sun.jna.Native; import com.sun.jna.NativeLong; import com.sun.jna.Platform; import com.sun.jna.Pointer; +import com.sun.jna.Structure; import com.sun.jna.ptr.IntByReference; import com.sun.jna.ptr.LongByReference; +import java.util.Arrays; +import java.util.List; + /** * The libvirt interface which is exposed via JNA. The complete API is * documented at http://www.libvirt.org/html/libvirt-libvirt.html. @@ -36,7 +40,6 @@ import com.sun.jna.ptr.LongByReference; * LIBVIRT_0.6.1 * virFreeError * virSaveLastError - * virDomainGetSecurityLabel; * virNodeGetSecurityModel; * * LIBVIRT_0.6.4 @@ -152,6 +155,24 @@ public interface Libvirt extends Library { // Connection Functions CString virConnectBaselineCPU(ConnectionPointer virConnectPtr, String[] xmlCPUs, int ncpus, int flags); + /// + /// Structure definitions + /// + + static class SecurityLabel extends Structure { + private static final int VIR_SECURITY_LABEL_BUFLEN = 4096 + 1; + private static final List<String> fields = Arrays.asList("label", "enforcing"); + + public byte label[] = new byte[VIR_SECURITY_LABEL_BUFLEN]; + public int enforcing; + + @Override + protected List<String> getFieldOrder() { + return fields; + } + }; + + /** * @deprecated as of libvirt 0.6.0, all errors reported in the * per-connection object are also duplicated in the global error @@ -265,6 +286,7 @@ public interface Libvirt extends Library { int virDomainGetSchedulerParameters(DomainPointer virDomainPtr, virSchedParameter[] params, IntByReference nparams); CString virDomainGetSchedulerType(DomainPointer virDomainPtr, IntByReference nparams); + int virDomainGetSecurityLabel(DomainPointer virDomainPtr, SecurityLabel seclabel); int virDomainGetUUID(DomainPointer virDomainPtr, byte[] uuidString); int virDomainGetUUIDString(DomainPointer virDomainPtr, byte[] uuidString); int virDomainGetVcpus(DomainPointer virDomainPtr, virVcpuInfo[] info, int maxInfo, byte[] cpumaps, int maplen); -- 2.2.2

--- src/main/java/org/libvirt/Connect.java | 15 +++++++++++ src/main/java/org/libvirt/SecurityModel.java | 37 ++++++++++++++++++++++++++++ src/main/java/org/libvirt/jna/Libvirt.java | 16 +++++++++++- 3 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 src/main/java/org/libvirt/SecurityModel.java diff --git a/src/main/java/org/libvirt/Connect.java b/src/main/java/org/libvirt/Connect.java index 1d37c22..04de4fd 100644 --- a/src/main/java/org/libvirt/Connect.java +++ b/src/main/java/org/libvirt/Connect.java @@ -1062,6 +1062,21 @@ public class Connect { } /** + * Returns the security model of the connected node. + */ + public SecurityModel getSecurityModel() throws LibvirtException { + Libvirt.SecurityModel secmodel = new Libvirt.SecurityModel(); + + processError(libvirt.virNodeGetSecurityModel(this.VCP, secmodel)); + + if (secmodel.model[0] == 0) + return null; + else + return new SecurityModel(secmodel); + + } + + /** * Returns the XML description of the sysinfo details for the host * on which the hypervisor is running. * <p> diff --git a/src/main/java/org/libvirt/SecurityModel.java b/src/main/java/org/libvirt/SecurityModel.java new file mode 100644 index 0000000..b41835f --- /dev/null +++ b/src/main/java/org/libvirt/SecurityModel.java @@ -0,0 +1,37 @@ +package org.libvirt; + +import org.libvirt.jna.Libvirt; +import com.sun.jna.Native; + +/** + * A security model used for mandatory access control. + * + * @see Connect#getSecurityModel + */ +public final class SecurityModel { + private String model; + private String doi; + + SecurityModel(Libvirt.SecurityModel secmodel) { + model = Native.toString(secmodel.model, "UTF-8"); + doi = Native.toString(secmodel.doi, "UTF-8"); + } + + /** + * Returns the model of this SecurityModel. + * + * @return the model string + */ + public String getModel() { + return model; + } + + /** + * Returns the DOI, domain of interpretation of this security model. + * + * @return the DOI + */ + public String getDomainOfInterpretation() { + return doi; + } +} diff --git a/src/main/java/org/libvirt/jna/Libvirt.java b/src/main/java/org/libvirt/jna/Libvirt.java index 2958233..024e268 100644 --- a/src/main/java/org/libvirt/jna/Libvirt.java +++ b/src/main/java/org/libvirt/jna/Libvirt.java @@ -40,7 +40,6 @@ import java.util.List; * LIBVIRT_0.6.1 * virFreeError * virSaveLastError - * virNodeGetSecurityModel; * * LIBVIRT_0.6.4 * virInterfaceRef @@ -172,6 +171,20 @@ public interface Libvirt extends Library { } }; + static class SecurityModel extends Structure { + private static final int VIR_SECURITY_MODEL_BUFLEN = 256 + 1; + private static final int VIR_SECURITY_DOI_BUFLEN = 256 + 1; + + private static final List<String> fields = Arrays.asList("model", "doi"); + + public byte model[] = new byte[VIR_SECURITY_MODEL_BUFLEN]; + public byte doi[] = new byte[VIR_SECURITY_DOI_BUFLEN]; + + @Override + protected List<String> getFieldOrder() { + return fields; + } + } /** * @deprecated as of libvirt 0.6.0, all errors reported in the @@ -362,6 +375,7 @@ public interface Libvirt extends Library { int virNodeGetCellsFreeMemory(ConnectionPointer virConnectPtr, LongByReference freeMems, int startCell, int maxCells); long virNodeGetFreeMemory(ConnectionPointer virConnectPtr); + int virNodeGetSecurityModel(ConnectionPointer virConnectPtr, SecurityModel secmodel); // Node/Device functions int virNodeNumOfDevices(ConnectionPointer virConnectPtr, String capabilityName, int flags); -- 2.2.2

Hi. At Wed, 28 Jan 2015 21:45:41 +0100, Claudio Bley wrote:
Hi.
First and foremost, this series fixes a few mistakes in the wrapping code found by inspecting the org.libvirt.jna.Libvirt interface and the corresponding C types of the XML API file.
The last two patches add two missing functions introduced in libvirt 0.6.1.
At the end of the day, this means libvirt-java has gained full coverage of the libvirt functions up to and including version 0.8.5. Yay!
Claudio Bley (6): JNA: fix wrong return type void vs. int JNA: add CString class and fix memory leaks JNA: simplify freeing memory for C strings Use the CString class for Arrays of CStrings too Implement Domain.getSecurityLabel and add SecurityLabel class Implement Connect.getSecurityModel and add SecurityModel class
It has been a while since I posted these patches. Because nobody objected until now, I'm just going to push them. -- Claudio --

On 07.07.2015 23:25, Claudio Bley wrote:
Hi.
At Wed, 28 Jan 2015 21:45:41 +0100, Claudio Bley wrote:
Hi.
First and foremost, this series fixes a few mistakes in the wrapping code found by inspecting the org.libvirt.jna.Libvirt interface and the corresponding C types of the XML API file.
The last two patches add two missing functions introduced in libvirt 0.6.1.
At the end of the day, this means libvirt-java has gained full coverage of the libvirt functions up to and including version 0.8.5. Yay!
Claudio Bley (6): JNA: fix wrong return type void vs. int JNA: add CString class and fix memory leaks JNA: simplify freeing memory for C strings Use the CString class for Arrays of CStrings too Implement Domain.getSecurityLabel and add SecurityLabel class Implement Connect.getSecurityModel and add SecurityModel class
It has been a while since I posted these patches. Because nobody objected until now, I'm just going to push them.
Yes, that's the same approach I'm using for libvirt-php, where the reviewer's capacity consists of, well, just me. I guess it's okay until the time those projects drag more attention. Michal

At Wed, 08 Jul 2015 14:42:52 +0200, Michal Privoznik wrote:
Claudio Bley (6): JNA: fix wrong return type void vs. int JNA: add CString class and fix memory leaks JNA: simplify freeing memory for C strings Use the CString class for Arrays of CStrings too Implement Domain.getSecurityLabel and add SecurityLabel class Implement Connect.getSecurityModel and add SecurityModel class
It has been a while since I posted these patches. Because nobody objected until now, I'm just going to push them.
Yes, that's the same approach I'm using for libvirt-php, where the reviewer's capacity consists of, well, just me. I guess it's okay until the time those projects drag more attention.
Thanks, I'll do the same then. Took me a while, but pushed now (after all this time I had some _difficulties_ remembering the passphrase of my SSH key... ;-)) -- Claudio
participants (2)
-
Claudio Bley
-
Michal Privoznik