2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A
2N/A/*
2N/A * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
2N/A * Use is subject to license terms.
2N/A */
2N/A
2N/A#pragma ident "%Z%%M% %I% %E% SMI"
2N/A
2N/A#include "libzfs_jni_util.h"
2N/A#include "libzfs_jni_dataset.h"
2N/A#include "libzfs_jni_property.h"
2N/A#include "libzfs_jni_pool.h"
2N/A#include <strings.h>
2N/A
2N/A#define REGEX_ZFS_NAME "^((([^/]*)(/.+)?)[/@])?([^/]+)/*"
2N/A#define REGEX_ZFS_NAME_NGROUPS 6
2N/A#define REGEX_ZFS_NAME_POOL_GROUP 3
2N/A#define REGEX_ZFS_NAME_PARENT_GROUP 2
2N/A#define REGEX_ZFS_NAME_BASE_GROUP 5
2N/A
2N/A/*
2N/A * Types
2N/A */
2N/A
2N/Atypedef struct DatasetBean {
2N/A zjni_Object_t super;
2N/A
2N/A jmethodID method_setPoolName;
2N/A jmethodID method_setParentName;
2N/A jmethodID method_setBaseName;
2N/A jmethodID method_setProperties;
2N/A jmethodID method_addProperty;
2N/A} DatasetBean_t;
2N/A
2N/Atypedef struct FileSystemBean {
2N/A DatasetBean_t super;
2N/A} FileSystemBean_t;
2N/A
2N/Atypedef struct PoolBean {
2N/A FileSystemBean_t super;
2N/A PoolStatsBean_t interface_PoolStats;
2N/A} PoolBean_t;
2N/A
2N/Atypedef struct VolumeBean {
2N/A DatasetBean_t super;
2N/A} VolumeBean_t;
2N/A
2N/Atypedef struct SnapshotBean {
2N/A DatasetBean_t super;
2N/A} SnapshotBean_t;
2N/A
2N/Atypedef struct FileSystemSnapshotBean {
2N/A DatasetBean_t super;
2N/A} FileSystemSnapshotBean_t;
2N/A
2N/Atypedef struct VolumeSnapshotBean {
2N/A DatasetBean_t super;
2N/A} VolumeSnapshotBean_t;
2N/A
2N/A/*
2N/A * Function prototypes
2N/A */
2N/A
2N/Astatic void new_DatasetBean(JNIEnv *, DatasetBean_t *);
2N/Astatic void new_PoolBean(JNIEnv *, PoolBean_t *);
2N/Astatic void new_FileSystemBean(JNIEnv *, FileSystemBean_t *);
2N/Astatic void new_VolumeBean(JNIEnv *, VolumeBean_t *);
2N/Astatic void new_SnapshotBean(JNIEnv *, SnapshotBean_t *);
2N/Astatic void new_FileSystemSnapshotBean(JNIEnv *, FileSystemSnapshotBean_t *);
2N/Astatic void new_VolumeSnapshotBean(JNIEnv *, VolumeSnapshotBean_t *);
2N/Astatic int set_name_in_DatasetBean(JNIEnv *, char *, DatasetBean_t *);
2N/Astatic int populate_DatasetBean(JNIEnv *, zfs_handle_t *, DatasetBean_t *);
2N/Astatic int populate_PoolBean(
2N/A JNIEnv *, zpool_handle_t *, zfs_handle_t *, PoolBean_t *);
2N/Astatic int populate_FileSystemBean(
2N/A JNIEnv *, zfs_handle_t *, FileSystemBean_t *);
2N/Astatic int populate_VolumeBean(
2N/A JNIEnv *, zfs_handle_t *, VolumeBean_t *);
2N/Astatic int populate_SnapshotBean(JNIEnv *, zfs_handle_t *, SnapshotBean_t *);
2N/Astatic int populate_FileSystemSnapshotBean(
2N/A JNIEnv *, zfs_handle_t *, FileSystemSnapshotBean_t *);
2N/Astatic int populate_VolumeSnapshotBean(
2N/A JNIEnv *, zfs_handle_t *, VolumeSnapshotBean_t *);
2N/Astatic jobject create_PoolBean(JNIEnv *, zpool_handle_t *, zfs_handle_t *);
2N/Astatic jobject create_FileSystemBean(JNIEnv *, zfs_handle_t *);
2N/Astatic jobject create_VolumeBean(JNIEnv *, zfs_handle_t *);
2N/Astatic jobject create_FileSystemSnapshotBean(JNIEnv *, zfs_handle_t *);
2N/Astatic jobject create_VolumeSnapshotBean(JNIEnv *, zfs_handle_t *);
2N/Astatic jobject create_DatasetBean(JNIEnv *, zfs_handle_t *);
2N/Astatic int is_fs_snapshot(zfs_handle_t *);
2N/Astatic int is_pool_name(const char *);
2N/A
2N/A/*
2N/A * Static functions
2N/A */
2N/A
2N/A/* Create a DatasetBean */
2N/Astatic void
2N/Anew_DatasetBean(JNIEnv *env, DatasetBean_t *bean)
2N/A{
2N/A zjni_Object_t *object = (zjni_Object_t *)bean;
2N/A
2N/A if (object->object == NULL) {
2N/A object->class =
2N/A (*env)->FindClass(env, ZFSJNI_PACKAGE_DATA "DatasetBean");
2N/A
2N/A object->constructor =
2N/A (*env)->GetMethodID(env, object->class, "<init>", "()V");
2N/A
2N/A object->object =
2N/A (*env)->NewObject(env, object->class, object->constructor);
2N/A }
2N/A
2N/A bean->method_setPoolName = (*env)->GetMethodID(
2N/A env, object->class, "setPoolName", "(Ljava/lang/String;)V");
2N/A
2N/A bean->method_setParentName = (*env)->GetMethodID(
2N/A env, object->class, "setParentName", "(Ljava/lang/String;)V");
2N/A
2N/A bean->method_setBaseName = (*env)->GetMethodID(
2N/A env, object->class, "setBaseName", "(Ljava/lang/String;)V");
2N/A
2N/A bean->method_setProperties = (*env)->GetMethodID(
2N/A env, object->class, "setProperties",
2N/A "([L" ZFSJNI_PACKAGE_DATA "Property;)V");
2N/A
2N/A bean->method_addProperty = (*env)->GetMethodID(
2N/A env, object->class, "addProperty",
2N/A "(L" ZFSJNI_PACKAGE_DATA "Property;)V");
2N/A}
2N/A
2N/A/* Create a PoolBean */
2N/Astatic void
2N/Anew_PoolBean(JNIEnv *env, PoolBean_t *bean)
2N/A{
2N/A zjni_Object_t *object = (zjni_Object_t *)bean;
2N/A
2N/A if (object->object == NULL) {
2N/A
2N/A object->class =
2N/A (*env)->FindClass(env, ZFSJNI_PACKAGE_DATA "PoolBean");
2N/A
2N/A object->constructor =
2N/A (*env)->GetMethodID(env, object->class, "<init>", "()V");
2N/A
2N/A object->object =
2N/A (*env)->NewObject(env, object->class, object->constructor);
2N/A }
2N/A
2N/A new_FileSystemBean(env, (FileSystemBean_t *)bean);
2N/A new_PoolStats(env, &(bean->interface_PoolStats), object);
2N/A}
2N/A
2N/A/* Create a FileSystemBean */
2N/Astatic void
2N/Anew_FileSystemBean(JNIEnv *env, FileSystemBean_t *bean)
2N/A{
2N/A zjni_Object_t *object = (zjni_Object_t *)bean;
2N/A
2N/A if (object->object == NULL) {
2N/A object->class =
2N/A (*env)->FindClass(env,
2N/A ZFSJNI_PACKAGE_DATA "FileSystemBean");
2N/A
2N/A object->constructor =
2N/A (*env)->GetMethodID(env, object->class, "<init>", "()V");
2N/A
2N/A object->object =
2N/A (*env)->NewObject(env, object->class, object->constructor);
2N/A }
2N/A
2N/A new_DatasetBean(env, (DatasetBean_t *)bean);
2N/A}
2N/A
2N/A/* Create a VolumeBean */
2N/Astatic void
2N/Anew_VolumeBean(JNIEnv *env, VolumeBean_t *bean)
2N/A{
2N/A zjni_Object_t *object = (zjni_Object_t *)bean;
2N/A
2N/A if (object->object == NULL) {
2N/A object->class =
2N/A (*env)->FindClass(env,
2N/A ZFSJNI_PACKAGE_DATA "VolumeBean");
2N/A
2N/A object->constructor =
2N/A (*env)->GetMethodID(env, object->class, "<init>", "()V");
2N/A
2N/A object->object =
2N/A (*env)->NewObject(env, object->class, object->constructor);
2N/A }
2N/A
2N/A new_DatasetBean(env, (DatasetBean_t *)bean);
2N/A}
2N/A
2N/A/* Create a SnapshotBean */
2N/Astatic void
2N/Anew_SnapshotBean(JNIEnv *env, SnapshotBean_t *bean)
2N/A{
2N/A zjni_Object_t *object = (zjni_Object_t *)bean;
2N/A
2N/A if (object->object == NULL) {
2N/A object->class =
2N/A (*env)->FindClass(env,
2N/A ZFSJNI_PACKAGE_DATA "SnapshotBean");
2N/A
2N/A object->constructor =
2N/A (*env)->GetMethodID(env, object->class, "<init>", "()V");
2N/A
2N/A object->object =
2N/A (*env)->NewObject(env, object->class, object->constructor);
2N/A }
2N/A
2N/A new_DatasetBean(env, (DatasetBean_t *)bean);
2N/A}
2N/A
2N/A/* Create a FileSystemSnapshotBean */
2N/Astatic void
2N/Anew_FileSystemSnapshotBean(JNIEnv *env, FileSystemSnapshotBean_t *bean)
2N/A{
2N/A zjni_Object_t *object = (zjni_Object_t *)bean;
2N/A
2N/A if (object->object == NULL) {
2N/A object->class =
2N/A (*env)->FindClass(env,
2N/A ZFSJNI_PACKAGE_DATA "FileSystemSnapshotBean");
2N/A
2N/A object->constructor =
2N/A (*env)->GetMethodID(env, object->class, "<init>", "()V");
2N/A
2N/A object->object =
2N/A (*env)->NewObject(env, object->class, object->constructor);
2N/A }
2N/A
2N/A new_SnapshotBean(env, (SnapshotBean_t *)bean);
2N/A}
2N/A
2N/A/* Create a VolumeSnapshotBean */
2N/Astatic void
2N/Anew_VolumeSnapshotBean(JNIEnv *env, VolumeSnapshotBean_t *bean)
2N/A{
2N/A zjni_Object_t *object = (zjni_Object_t *)bean;
2N/A
2N/A if (object->object == NULL) {
2N/A object->class =
2N/A (*env)->FindClass(env,
2N/A ZFSJNI_PACKAGE_DATA "VolumeSnapshotBean");
2N/A
2N/A object->constructor =
2N/A (*env)->GetMethodID(env, object->class, "<init>", "()V");
2N/A
2N/A object->object =
2N/A (*env)->NewObject(env, object->class, object->constructor);
2N/A }
2N/A
2N/A new_SnapshotBean(env, (SnapshotBean_t *)bean);
2N/A}
2N/A
2N/Astatic int
2N/Aset_name_in_DatasetBean(JNIEnv *env, char *name, DatasetBean_t *bean)
2N/A{
2N/A jstring poolUTF;
2N/A jstring parentUTF;
2N/A jstring baseUTF;
2N/A zjni_Object_t *object = (zjni_Object_t *)bean;
2N/A
2N/A /*
2N/A * zhp->zfs_name has the format
2N/A * <pool>[[/<container...>]/<dataset>[@<snapshot>]]
2N/A */
2N/A
2N/A regex_t re;
2N/A regmatch_t matches[REGEX_ZFS_NAME_NGROUPS];
2N/A
2N/A if (regcomp(&re, REGEX_ZFS_NAME, REG_EXTENDED) != 0 ||
2N/A regexec(&re, name, REGEX_ZFS_NAME_NGROUPS, matches, 0) != 0) {
2N/A regfree(&re);
2N/A zjni_throw_exception(env, "invalid name: %s", name);
2N/A return (-1);
2N/A }
2N/A
2N/A regfree(&re);
2N/A
2N/A /* Set names */
2N/A poolUTF = zjni_get_matched_string(
2N/A env, name, matches + REGEX_ZFS_NAME_POOL_GROUP);
2N/A parentUTF = zjni_get_matched_string(
2N/A env, name, matches + REGEX_ZFS_NAME_PARENT_GROUP);
2N/A baseUTF = zjni_get_matched_string(
2N/A env, name, matches + REGEX_ZFS_NAME_BASE_GROUP);
2N/A
2N/A if (poolUTF == NULL) {
2N/A poolUTF = baseUTF;
2N/A }
2N/A
2N/A (*env)->CallVoidMethod(
2N/A env, object->object, bean->method_setPoolName, poolUTF);
2N/A (*env)->CallVoidMethod(
2N/A env, object->object, bean->method_setBaseName, baseUTF);
2N/A
2N/A if (parentUTF != NULL) {
2N/A (*env)->CallVoidMethod(
2N/A env, object->object, bean->method_setParentName, parentUTF);
2N/A }
2N/A
2N/A return (0);
2N/A}
2N/A
2N/Astatic int
2N/Apopulate_DatasetBean(JNIEnv *env, zfs_handle_t *zhp, DatasetBean_t *bean)
2N/A{
2N/A jobjectArray properties;
2N/A zjni_Object_t *object = (zjni_Object_t *)bean;
2N/A
2N/A int result = set_name_in_DatasetBean(
2N/A env, (char *)zfs_get_name(zhp), bean);
2N/A if (result != 0) {
2N/A /* Must not call any more Java methods to preserve exception */
2N/A return (-1);
2N/A }
2N/A
2N/A properties = zjni_get_Dataset_properties(env, zhp);
2N/A if (properties == NULL) {
2N/A /* Must not call any more Java methods to preserve exception */
2N/A return (-1);
2N/A }
2N/A
2N/A (*env)->CallVoidMethod(
2N/A env, object->object, bean->method_setProperties, properties);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/Astatic int
2N/Apopulate_PoolBean(JNIEnv *env, zpool_handle_t *zphp, zfs_handle_t *zhp,
2N/A PoolBean_t *bean)
2N/A{
2N/A int result = 0;
2N/A zjni_Object_t *object = (zjni_Object_t *)bean;
2N/A PoolStatsBean_t *pool_stats = &(bean->interface_PoolStats);
2N/A DeviceStatsBean_t *dev_stats = (DeviceStatsBean_t *)pool_stats;
2N/A nvlist_t *devices = zjni_get_root_vdev(zphp);
2N/A
2N/A if (devices == NULL ||
2N/A populate_DeviceStatsBean(env, devices, dev_stats, object)) {
2N/A result = -1;
2N/A } else {
2N/A char *msgid;
2N/A
2N/A /* Override value set in populate_DeviceStatsBean */
2N/A (*env)->CallVoidMethod(env, object->object,
2N/A dev_stats->method_setSize,
2N/A zpool_get_prop_int(zphp, ZPOOL_PROP_SIZE, NULL));
2N/A
2N/A (*env)->CallVoidMethod(env, object->object,
2N/A pool_stats->method_setPoolState,
2N/A zjni_pool_state_to_obj(
2N/A env, zpool_get_state(zphp)));
2N/A
2N/A (*env)->CallVoidMethod(env, object->object,
2N/A pool_stats->method_setPoolStatus,
2N/A zjni_pool_status_to_obj(env,
2N/A zpool_get_status(zphp, &msgid)));
2N/A
2N/A (*env)->CallVoidMethod(env, object->object,
2N/A pool_stats->method_setPoolVersion,
2N/A zpool_get_prop_int(zphp, ZPOOL_PROP_VERSION, NULL));
2N/A
2N/A /*
2N/A * If a root file system does not exist for this pool, the pool
2N/A * is likely faulted, so just set its name in the Java object.
2N/A * Otherwise, populate all fields of the Java object.
2N/A */
2N/A if (zhp == NULL) {
2N/A result = set_name_in_DatasetBean(env,
2N/A (char *)zpool_get_name(zphp),
2N/A (DatasetBean_t *)bean);
2N/A } else {
2N/A result = populate_FileSystemBean(
2N/A env, zhp, (FileSystemBean_t *)bean);
2N/A }
2N/A }
2N/A
2N/A return (result != 0);
2N/A}
2N/A
2N/Astatic int
2N/Apopulate_FileSystemBean(JNIEnv *env, zfs_handle_t *zhp, FileSystemBean_t *bean)
2N/A{
2N/A return (populate_DatasetBean(env, zhp, (DatasetBean_t *)bean));
2N/A}
2N/A
2N/Astatic int
2N/Apopulate_VolumeBean(JNIEnv *env, zfs_handle_t *zhp, VolumeBean_t *bean)
2N/A{
2N/A return (populate_DatasetBean(env, zhp, (DatasetBean_t *)bean));
2N/A}
2N/A
2N/Astatic int
2N/Apopulate_SnapshotBean(JNIEnv *env, zfs_handle_t *zhp, SnapshotBean_t *bean)
2N/A{
2N/A return (populate_DatasetBean(env, zhp, (DatasetBean_t *)bean));
2N/A}
2N/A
2N/Astatic int
2N/Apopulate_FileSystemSnapshotBean(JNIEnv *env, zfs_handle_t *zhp,
2N/A FileSystemSnapshotBean_t *bean)
2N/A{
2N/A return (populate_SnapshotBean(env, zhp, (SnapshotBean_t *)bean));
2N/A}
2N/A
2N/Astatic int
2N/Apopulate_VolumeSnapshotBean(JNIEnv *env, zfs_handle_t *zhp,
2N/A VolumeSnapshotBean_t *bean)
2N/A{
2N/A return (populate_SnapshotBean(env, zhp, (SnapshotBean_t *)bean));
2N/A}
2N/A
2N/Astatic jobject
2N/Acreate_PoolBean(JNIEnv *env, zpool_handle_t *zphp, zfs_handle_t *zhp)
2N/A{
2N/A int result;
2N/A PoolBean_t bean_obj = {0};
2N/A PoolBean_t *bean = &bean_obj;
2N/A
2N/A /* Construct PoolBean */
2N/A new_PoolBean(env, bean);
2N/A
2N/A result = populate_PoolBean(env, zphp, zhp, bean);
2N/A if (result) {
2N/A /* Must not call any more Java methods to preserve exception */
2N/A return (NULL);
2N/A }
2N/A
2N/A return (((zjni_Object_t *)bean)->object);
2N/A}
2N/A
2N/Astatic jobject
2N/Acreate_FileSystemBean(JNIEnv *env, zfs_handle_t *zhp)
2N/A{
2N/A int result;
2N/A FileSystemBean_t bean_obj = {0};
2N/A FileSystemBean_t *bean = &bean_obj;
2N/A
2N/A /* Construct FileSystemBean */
2N/A new_FileSystemBean(env, bean);
2N/A
2N/A result = populate_FileSystemBean(env, zhp, bean);
2N/A if (result) {
2N/A /* Must not call any more Java methods to preserve exception */
2N/A return (NULL);
2N/A }
2N/A
2N/A return (((zjni_Object_t *)bean)->object);
2N/A}
2N/A
2N/Astatic jobject
2N/Acreate_VolumeBean(JNIEnv *env, zfs_handle_t *zhp)
2N/A{
2N/A int result;
2N/A VolumeBean_t bean_obj = {0};
2N/A VolumeBean_t *bean = &bean_obj;
2N/A
2N/A /* Construct VolumeBean */
2N/A new_VolumeBean(env, bean);
2N/A
2N/A result = populate_VolumeBean(env, zhp, bean);
2N/A if (result) {
2N/A /* Must not call any more Java methods to preserve exception */
2N/A return (NULL);
2N/A }
2N/A
2N/A return (((zjni_Object_t *)bean)->object);
2N/A}
2N/A
2N/Astatic jobject
2N/Acreate_FileSystemSnapshotBean(JNIEnv *env, zfs_handle_t *zhp)
2N/A{
2N/A int result;
2N/A FileSystemSnapshotBean_t bean_obj = {0};
2N/A FileSystemSnapshotBean_t *bean = &bean_obj;
2N/A
2N/A /* Construct FileSystemSnapshotBean */
2N/A new_FileSystemSnapshotBean(env, bean);
2N/A
2N/A result = populate_FileSystemSnapshotBean(env, zhp, bean);
2N/A if (result) {
2N/A /* Must not call any more Java methods to preserve exception */
2N/A return (NULL);
2N/A }
2N/A
2N/A return (((zjni_Object_t *)bean)->object);
2N/A}
2N/A
2N/Astatic jobject
2N/Acreate_VolumeSnapshotBean(JNIEnv *env, zfs_handle_t *zhp)
2N/A{
2N/A int result;
2N/A VolumeSnapshotBean_t bean_obj = {0};
2N/A VolumeSnapshotBean_t *bean = &bean_obj;
2N/A
2N/A /* Construct VolumeSnapshotBean */
2N/A new_VolumeSnapshotBean(env, bean);
2N/A
2N/A result = populate_VolumeSnapshotBean(env, zhp, bean);
2N/A if (result) {
2N/A /* Must not call any more Java methods to preserve exception */
2N/A return (NULL);
2N/A }
2N/A
2N/A return (((zjni_Object_t *)bean)->object);
2N/A}
2N/A
2N/Astatic jobject
2N/Acreate_DatasetBean(JNIEnv *env, zfs_handle_t *zhp)
2N/A{
2N/A jobject object = NULL;
2N/A
2N/A switch (zfs_get_type(zhp)) {
2N/A case ZFS_TYPE_FILESYSTEM:
2N/A object = create_FileSystemBean(env, zhp);
2N/A break;
2N/A
2N/A case ZFS_TYPE_VOLUME:
2N/A object = create_VolumeBean(env, zhp);
2N/A break;
2N/A
2N/A case ZFS_TYPE_SNAPSHOT:
2N/A object = is_fs_snapshot(zhp) ?
2N/A create_FileSystemSnapshotBean(env, zhp) :
2N/A create_VolumeSnapshotBean(env, zhp);
2N/A break;
2N/A }
2N/A
2N/A return (object);
2N/A}
2N/A
2N/A/*
2N/A * Determines whether the given snapshot is a snapshot of a file
2N/A * system or of a volume.
2N/A *
2N/A * Returns:
2N/A *
2N/A * 0 if it is a volume snapshot
2N/A * 1 if it is a file system snapshot
2N/A * -1 on error
2N/A */
2N/Astatic int
2N/Ais_fs_snapshot(zfs_handle_t *zhp)
2N/A{
2N/A char parent[ZFS_MAXNAMELEN];
2N/A zfs_handle_t *parent_zhp;
2N/A int isfs;
2N/A
2N/A if (zfs_get_type(zhp) != ZFS_TYPE_SNAPSHOT) {
2N/A return (-1);
2N/A }
2N/A
2N/A zjni_get_dataset_from_snapshot(
2N/A zfs_get_name(zhp), parent, sizeof (parent));
2N/A
2N/A parent_zhp = zfs_open(g_zfs, parent, ZFS_TYPE_DATASET);
2N/A if (parent_zhp == NULL) {
2N/A return (-1);
2N/A }
2N/A
2N/A isfs = zfs_get_type(parent_zhp) == ZFS_TYPE_FILESYSTEM;
2N/A zfs_close(parent_zhp);
2N/A
2N/A return (isfs);
2N/A}
2N/A
2N/Astatic int
2N/Ais_pool_name(const char *name)
2N/A{
2N/A return (strchr(name, '/') == NULL && strchr(name, '@') == NULL);
2N/A}
2N/A
2N/A/*
2N/A * Package-private functions
2N/A */
2N/A
2N/A/*
2N/A * Callback function for zpool_iter(). Creates a Pool and adds it to
2N/A * the given zjni_ArrayList.
2N/A */
2N/Aint
2N/Azjni_create_add_Pool(zpool_handle_t *zphp, void *data)
2N/A{
2N/A JNIEnv *env = ((zjni_ArrayCallbackData_t *)data)->env;
2N/A zjni_Collection_t *list = ((zjni_ArrayCallbackData_t *)data)->list;
2N/A
2N/A /* Get root fs for this pool -- may be NULL if pool is faulted */
2N/A zfs_handle_t *zhp = zfs_open(g_zfs, zpool_get_name(zphp),
2N/A ZFS_TYPE_FILESYSTEM);
2N/A
2N/A jobject bean = create_PoolBean(env, zphp, zhp);
2N/A
2N/A if (zhp != NULL)
2N/A zfs_close(zhp);
2N/A
2N/A zpool_close(zphp);
2N/A
2N/A if (bean == NULL) {
2N/A /* Must not call any more Java methods to preserve exception */
2N/A return (-1);
2N/A }
2N/A
2N/A /* Add pool to zjni_ArrayList */
2N/A (*env)->CallBooleanMethod(env, ((zjni_Object_t *)list)->object,
2N/A ((zjni_Collection_t *)list)->method_add, bean);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Callback function for zfs_iter_children(). Creates the appropriate
2N/A * Dataset and adds it to the given zjni_ArrayList. Per the contract
2N/A * with zfs_iter_children(), calls zfs_close() on the given
2N/A * zfs_handle_t.
2N/A */
2N/Aint
2N/Azjni_create_add_Dataset(zfs_handle_t *zhp, void *data)
2N/A{
2N/A JNIEnv *env = ((zjni_ArrayCallbackData_t *)data)->env;
2N/A zjni_Collection_t *list = ((zjni_ArrayCallbackData_t *)data)->list;
2N/A zfs_type_t typemask =
2N/A ((zjni_DatasetArrayCallbackData_t *)data)->typemask;
2N/A
2N/A /* Only add allowed types */
2N/A if (zfs_get_type(zhp) & typemask) {
2N/A
2N/A jobject bean = create_DatasetBean(env, zhp);
2N/A zfs_close(zhp);
2N/A
2N/A if (bean == NULL) {
2N/A /*
2N/A * Must not call any more Java methods to preserve
2N/A * exception
2N/A */
2N/A return (-1);
2N/A }
2N/A
2N/A /* Add Dataset to zjni_ArrayList */
2N/A (*env)->CallBooleanMethod(env, ((zjni_Object_t *)list)->object,
2N/A ((zjni_Collection_t *)list)->method_add, bean);
2N/A } else {
2N/A zfs_close(zhp);
2N/A }
2N/A
2N/A return (0);
2N/A}
2N/A
2N/AjobjectArray
2N/Azjni_get_Datasets_below(JNIEnv *env, jstring parentUTF,
2N/A zfs_type_t parent_typemask, zfs_type_t child_typemask, char *arrayClass)
2N/A{
2N/A jobjectArray array = NULL;
2N/A
2N/A if (parentUTF != NULL) {
2N/A zfs_handle_t *zhp;
2N/A int error = 1;
2N/A const char *name =
2N/A (*env)->GetStringUTFChars(env, parentUTF, NULL);
2N/A
2N/A /* Create an array list to hold the children */
2N/A zjni_DatasetSet_t list_obj = {0};
2N/A zjni_DatasetSet_t *list = &list_obj;
2N/A zjni_new_DatasetSet(env, list);
2N/A
2N/A /* Retrieve parent dataset */
2N/A zhp = zfs_open(g_zfs, name, parent_typemask);
2N/A
2N/A if (zhp != NULL) {
2N/A zjni_DatasetArrayCallbackData_t data = {0};
2N/A data.data.env = env;
2N/A data.data.list = (zjni_Collection_t *)list;
2N/A data.typemask = child_typemask;
2N/A
2N/A (void) zfs_iter_children(zhp, zjni_create_add_Dataset,
2N/A &data);
2N/A
2N/A zfs_close(zhp);
2N/A
2N/A if ((*env)->ExceptionOccurred(env) == NULL) {
2N/A error = 0;
2N/A }
2N/A } else
2N/A
2N/A /* Parent is not a dataset -- see if it's a faulted pool */
2N/A if ((parent_typemask & ZFS_TYPE_FILESYSTEM) &&
2N/A is_pool_name(name)) {
2N/A zpool_handle_t *zphp = zpool_open_canfail(g_zfs, name);
2N/A
2N/A if (zphp != NULL) {
2N/A /* A faulted pool has no datasets */
2N/A error = 0;
2N/A zpool_close(zphp);
2N/A }
2N/A }
2N/A
2N/A (*env)->ReleaseStringUTFChars(env, parentUTF, name);
2N/A
2N/A if (!error) {
2N/A array = zjni_Collection_to_array(
2N/A env, (zjni_Collection_t *)list, arrayClass);
2N/A }
2N/A }
2N/A
2N/A return (array);
2N/A}
2N/A
2N/AjobjectArray
2N/Azjni_get_Datasets_dependents(JNIEnv *env, jobjectArray paths)
2N/A{
2N/A jint i;
2N/A jint npaths;
2N/A zjni_DatasetArrayCallbackData_t data = {0};
2N/A jobjectArray array = NULL;
2N/A
2N/A /* Create a list to hold the children */
2N/A zjni_DatasetSet_t list_obj = {0};
2N/A zjni_DatasetSet_t *list = &list_obj;
2N/A zjni_new_DatasetSet(env, list);
2N/A
2N/A data.data.env = env;
2N/A data.data.list = (zjni_Collection_t *)list;
2N/A data.typemask = ZFS_TYPE_DATASET;
2N/A
2N/A npaths = (*env)->GetArrayLength(env, paths);
2N/A for (i = 0; i < npaths; i++) {
2N/A
2N/A jstring pathUTF = (jstring)
2N/A ((*env)->GetObjectArrayElement(env, paths, i));
2N/A
2N/A if (pathUTF != NULL) {
2N/A const char *path =
2N/A (*env)->GetStringUTFChars(env, pathUTF, NULL);
2N/A
2N/A zfs_handle_t *zhp = zfs_open(g_zfs, path,
2N/A ZFS_TYPE_DATASET);
2N/A if (zhp != NULL) {
2N/A /* Add all dependents of this Dataset to list */
2N/A (void) zfs_iter_dependents(zhp, B_FALSE,
2N/A zjni_create_add_Dataset, &data);
2N/A
2N/A /* Add this Dataset to list (and close zhp) */
2N/A (void) zjni_create_add_Dataset(zhp, &data);
2N/A } else if (is_pool_name(path)) {
2N/A /*
2N/A * Path is not a dataset -
2N/A * see if it's a faulted pool
2N/A */
2N/A zpool_handle_t *zphp = zpool_open_canfail(g_zfs,
2N/A path);
2N/A
2N/A if (zphp != NULL) {
2N/A /*
2N/A * Add this Pool to list (and
2N/A * close zphp)
2N/A */
2N/A (void) zjni_create_add_Pool(zphp,
2N/A &data.data);
2N/A }
2N/A }
2N/A
2N/A (*env)->ReleaseStringUTFChars(env, pathUTF, path);
2N/A }
2N/A }
2N/A
2N/A if ((*env)->ExceptionOccurred(env) == NULL) {
2N/A array = zjni_Collection_to_array(env, (zjni_Collection_t *)list,
2N/A ZFSJNI_PACKAGE_DATA "Dataset");
2N/A }
2N/A
2N/A return (array);
2N/A}
2N/A
2N/A/*
2N/A * Gets a Dataset of the given name and type, or NULL if no such
2N/A * Dataset exists.
2N/A */
2N/Ajobject
2N/Azjni_get_Dataset(JNIEnv *env, jstring nameUTF, zfs_type_t typemask)
2N/A{
2N/A jobject device = NULL;
2N/A const char *name = (*env)->GetStringUTFChars(env, nameUTF, NULL);
2N/A zfs_handle_t *zhp = zfs_open(g_zfs, name, typemask);
2N/A
2N/A if ((typemask & ZFS_TYPE_FILESYSTEM) && is_pool_name(name)) {
2N/A zpool_handle_t *zphp = zpool_open_canfail(g_zfs, name);
2N/A
2N/A if (zphp != NULL) {
2N/A device = create_PoolBean(env, zphp, zhp);
2N/A zpool_close(zphp);
2N/A }
2N/A } else if (zhp != NULL) {
2N/A /* Creates a Dataset object of the appropriate class */
2N/A device = create_DatasetBean(env, zhp);
2N/A }
2N/A
2N/A if (zhp != NULL) {
2N/A zfs_close(zhp);
2N/A }
2N/A
2N/A (*env)->ReleaseStringUTFChars(env, nameUTF, name);
2N/A
2N/A return (device);
2N/A}