Home | History | Annotate | Download | only in common
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     28 
     29 #include <priv.h>
     30 #include "libzfs_jni_main.h"
     31 #include "libzfs_jni_util.h"
     32 #include "libzfs_jni_dataset.h"
     33 #include "libzfs_jni_property.h"
     34 #include "libzfs_jni_pool.h"
     35 #include "libzfs_jni_diskmgt.h"
     36 #include "libzfs_jni_disk.h"
     37 
     38 libzfs_handle_t *g_zfs;
     39 
     40 /*
     41  * Function prototypes
     42  */
     43 
     44 static void handle_error(const char *, va_list);
     45 static void init();
     46 
     47 /*
     48  * Static functions
     49  */
     50 
     51 char libdskmgt_err[1024];
     52 static void
     53 handle_error(const char *fmt, va_list ap)
     54 {
     55 	/* Save the error message in case it's needed */
     56 	(void) vsnprintf(libdskmgt_err, sizeof (libdskmgt_err), fmt, ap);
     57 #ifdef	DEBUG
     58 	(void) fprintf(stderr, "caught error: %s\n", libdskmgt_err);
     59 #endif
     60 }
     61 
     62 /*
     63  * Initialize the library.  Sets the error handler.
     64  */
     65 #pragma init(init)
     66 static void
     67 init()
     68 {
     69 	if ((g_zfs = libzfs_init()) == NULL)
     70 		abort();
     71 
     72 	/* diskmgt.o error handler */
     73 	dmgt_set_error_handler(handle_error);
     74 }
     75 
     76 /*
     77  * JNI functions
     78  */
     79 
     80 /*
     81  * Class:     com_sun_zfs_common_model_SystemDataModel
     82  * Method:    getImportablePools
     83  * Signature: ([Ljava/lang/String;)[Ljava/lang/String;
     84  */
     85 /* ARGSUSED */
     86 JNIEXPORT jobjectArray JNICALL
     87 Java_com_sun_zfs_common_model_SystemDataModel_getImportablePools(
     88     JNIEnv *env, jobject obj, jobjectArray dirs) {
     89 
     90 	int error;
     91 	int argc = 0;
     92 	char **argv = NULL;
     93 	zjni_ArrayCallbackData_t data = {0};
     94 	zjni_ArrayList_t list_obj = {0};
     95 	zjni_ArrayList_t *list = &list_obj;
     96 
     97 	if (!priv_ineffect(PRIV_SYS_CONFIG)) {
     98 		zjni_throw_exception(env,
     99 		    "cannot discover pools: permission denied\n");
    100 		return (NULL);
    101 	}
    102 
    103 	if (dirs != NULL) {
    104 		argv = zjni_java_string_array_to_c(env, dirs);
    105 		if (argv == NULL) {
    106 			zjni_throw_exception(env, "out of memory");
    107 			return (NULL);
    108 		}
    109 
    110 		/* Count elements */
    111 		for (argc = 0; argv[argc] != NULL; argc++);
    112 	}
    113 
    114 	/* Create an array list to hold each ImportablePoolBean */
    115 	zjni_new_ArrayList(env, list);
    116 
    117 	data.env = env;
    118 	data.list = (zjni_Collection_t *)list;
    119 
    120 	/* Iterate through all importable pools, building list */
    121 	error = zjni_ipool_iter(
    122 	    argc, argv, zjni_create_add_ImportablePool, &data);
    123 
    124 	zjni_free_array((void **)argv, free);
    125 
    126 	if (error) {
    127 		return (NULL);
    128 	}
    129 
    130 	return (zjni_Collection_to_array(env, (zjni_Collection_t *)list,
    131 	    ZFSJNI_PACKAGE_DATA "ImportablePool"));
    132 }
    133 
    134 /*
    135  * Class:     com_sun_zfs_common_model_SystemDataModel
    136  * Method:    getPools
    137  * Signature: ()[Lcom/sun/zfs/common/model/Pool;
    138  */
    139 /* ARGSUSED */
    140 JNIEXPORT jobjectArray JNICALL
    141 Java_com_sun_zfs_common_model_SystemDataModel_getPools(JNIEnv *env, jobject obj)
    142 {
    143 	zjni_ArrayCallbackData_t data = {0};
    144 	int result;
    145 
    146 	/* Create an array list */
    147 	zjni_ArrayList_t list_obj = {0};
    148 	zjni_ArrayList_t *list = &list_obj;
    149 	zjni_new_ArrayList(env, list);
    150 
    151 	data.env = env;
    152 	data.list = (zjni_Collection_t *)list;
    153 
    154 	result = zpool_iter(g_zfs, zjni_create_add_Pool, &data);
    155 	if (result && (*env)->ExceptionOccurred(env) != NULL) {
    156 		/* Must not call any more Java methods to preserve exception */
    157 		return (NULL);
    158 	}
    159 
    160 	return (zjni_Collection_to_array(env, (zjni_Collection_t *)list,
    161 	    ZFSJNI_PACKAGE_DATA "Pool"));
    162 }
    163 
    164 /*
    165  * Class:     com_sun_zfs_common_model_SystemDataModel
    166  * Method:    getPool
    167  * Signature: (Ljava/lang/String;)
    168  *            Lcom/sun/zfs/common/model/Pool;
    169  */
    170 /* ARGSUSED */
    171 JNIEXPORT jobject JNICALL
    172 Java_com_sun_zfs_common_model_SystemDataModel_getPool(JNIEnv *env,
    173     jobject obj, jstring poolUTF)
    174 {
    175 	jobject pool = zjni_get_Dataset(env, poolUTF, ZFS_TYPE_FILESYSTEM);
    176 
    177 	/* Verify that object is Pool, not some other Dataset */
    178 	if (pool != NULL) {
    179 		jclass class = (*env)->FindClass(
    180 		    env, ZFSJNI_PACKAGE_DATA "Pool");
    181 
    182 		jboolean is_pool = (*env)->IsInstanceOf(env, pool, class);
    183 
    184 		if (is_pool != JNI_TRUE)
    185 			pool = NULL;
    186 	}
    187 
    188 	return (pool);
    189 }
    190 
    191 /*
    192  * Class:     com_sun_zfs_common_model_SystemDataModel
    193  * Method:    getFileSystems
    194  * Signature: (Ljava/lang/String;)
    195  *            [Lcom/sun/zfs/common/model/FileSystem;
    196  */
    197 /* ARGSUSED */
    198 JNIEXPORT jobjectArray JNICALL
    199 Java_com_sun_zfs_common_model_SystemDataModel_getFileSystems(JNIEnv *env,
    200     jobject obj, jstring containerUTF)
    201 {
    202 	if (containerUTF == NULL) {
    203 		return (Java_com_sun_zfs_common_model_SystemDataModel_getPools(
    204 		    env, obj));
    205 	}
    206 
    207 	return (zjni_get_Datasets_below(env, containerUTF,
    208 	    ZFS_TYPE_FILESYSTEM, ZFS_TYPE_FILESYSTEM,
    209 	    ZFSJNI_PACKAGE_DATA "FileSystem"));
    210 }
    211 
    212 /*
    213  * Class:     com_sun_zfs_common_model_SystemDataModel
    214  * Method:    getFileSystem
    215  * Signature: (Ljava/lang/String;)
    216  *            Lcom/sun/zfs/common/model/FileSystem;
    217  */
    218 /* ARGSUSED */
    219 JNIEXPORT jobject JNICALL
    220 Java_com_sun_zfs_common_model_SystemDataModel_getFileSystem(JNIEnv *env,
    221     jobject obj, jstring nameUTF)
    222 {
    223 	return (zjni_get_Dataset(env, nameUTF, ZFS_TYPE_FILESYSTEM));
    224 }
    225 
    226 /*
    227  * Class:     com_sun_zfs_common_model_SystemDataModel
    228  * Method:    getVolumes
    229  * Signature: (Ljava/lang/String;)
    230  *            [Lcom/sun/zfs/common/model/Volume;
    231  */
    232 /* ARGSUSED */
    233 JNIEXPORT jobjectArray JNICALL
    234 Java_com_sun_zfs_common_model_SystemDataModel_getVolumes(JNIEnv *env,
    235     jobject obj, jstring containerUTF)
    236 {
    237 	return (zjni_get_Datasets_below(env, containerUTF,
    238 	    ZFS_TYPE_FILESYSTEM, ZFS_TYPE_VOLUME,
    239 	    ZFSJNI_PACKAGE_DATA "Volume"));
    240 }
    241 
    242 /*
    243  * Class:     com_sun_zfs_common_model_SystemDataModel
    244  * Method:    getVolume
    245  * Signature: (Ljava/lang/String;)
    246  *            Lcom/sun/zfs/common/model/Volume;
    247  */
    248 /* ARGSUSED */
    249 JNIEXPORT jobject JNICALL
    250 Java_com_sun_zfs_common_model_SystemDataModel_getVolume(JNIEnv *env,
    251     jobject obj, jstring nameUTF)
    252 {
    253 	return (zjni_get_Dataset(env, nameUTF, ZFS_TYPE_VOLUME));
    254 }
    255 
    256 /*
    257  * Class:     com_sun_zfs_common_model_SystemDataModel
    258  * Method:    getSnapshots
    259  * Signature: (Ljava/lang/String;)
    260  *            [Lcom/sun/zfs/common/model/Snapshot;
    261  */
    262 /* ARGSUSED */
    263 JNIEXPORT jobjectArray JNICALL
    264 Java_com_sun_zfs_common_model_SystemDataModel_getSnapshots(JNIEnv *env,
    265     jobject obj, jstring datasetUTF)
    266 {
    267 	return (zjni_get_Datasets_below(env, datasetUTF,
    268 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, ZFS_TYPE_SNAPSHOT,
    269 	    ZFSJNI_PACKAGE_DATA "Snapshot"));
    270 }
    271 
    272 /*
    273  * Class:     com_sun_zfs_common_model_SystemDataModel
    274  * Method:    getSnapshot
    275  * Signature: (Ljava/lang/String;)
    276  *            Lcom/sun/zfs/common/model/Snapshot;
    277  */
    278 /* ARGSUSED */
    279 JNIEXPORT jobject JNICALL
    280 Java_com_sun_zfs_common_model_SystemDataModel_getSnapshot(JNIEnv *env,
    281     jobject obj, jstring nameUTF)
    282 {
    283 	return (zjni_get_Dataset(env, nameUTF, ZFS_TYPE_SNAPSHOT));
    284 }
    285 
    286 /*
    287  * Class:     com_sun_zfs_common_model_SystemDataModel
    288  * Method:    getDatasets
    289  * Signature: (Ljava/lang/String;)
    290  *            [Lcom/sun/zfs/common/model/Dataset;
    291  */
    292 /* ARGSUSED */
    293 JNIEXPORT jobjectArray JNICALL
    294 Java_com_sun_zfs_common_model_SystemDataModel_getDatasets(JNIEnv *env,
    295     jobject obj, jstring containerUTF)
    296 {
    297 	if (containerUTF == NULL) {
    298 		return (Java_com_sun_zfs_common_model_SystemDataModel_getPools(
    299 		    env, obj));
    300 	}
    301 
    302 	return (zjni_get_Datasets_below(env, containerUTF,
    303 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, ZFS_TYPE_DATASET,
    304 	    ZFSJNI_PACKAGE_DATA "Dataset"));
    305 }
    306 
    307 /*
    308  * Class:     com_sun_zfs_common_model_SystemDataModel
    309  * Method:    getDataset
    310  * Signature: (Ljava/lang/String;)
    311  *            Lcom/sun/zfs/common/model/Dataset;
    312  */
    313 /* ARGSUSED */
    314 JNIEXPORT jobject JNICALL
    315 Java_com_sun_zfs_common_model_SystemDataModel_getDataset(JNIEnv *env,
    316     jobject obj, jstring nameUTF)
    317 {
    318 	return (zjni_get_Dataset(env, nameUTF, ZFS_TYPE_DATASET));
    319 }
    320 
    321 /*
    322  * Class:     com_sun_zfs_common_model_SystemDataModel
    323  * Method:    getVirtualDevice
    324  * Signature: (Ljava/lang/String;J)Lcom/sun/zfs/common/model/VirtualDevice;
    325  */
    326 /* ARGSUSED */
    327 JNIEXPORT jobject JNICALL
    328 Java_com_sun_zfs_common_model_SystemDataModel_getVirtualDevice(JNIEnv *env,
    329     jobject obj, jstring poolUTF, jlong index)
    330 {
    331 	jobject vdev = NULL;
    332 
    333 	if (poolUTF != NULL) {
    334 		const char *pool = (*env)->GetStringUTFChars(env, poolUTF,
    335 		    NULL);
    336 		zpool_handle_t *zhp = zpool_open_canfail(g_zfs, pool);
    337 		(*env)->ReleaseStringUTFChars(env, poolUTF, pool);
    338 
    339 		if (zhp != NULL) {
    340 			uint64_t p_vdev_id;
    341 			nvlist_t *vdev_cfg = zjni_get_vdev(
    342 			    zhp, NULL, index, &p_vdev_id);
    343 
    344 			if (vdev_cfg != NULL) {
    345 				vdev = zjni_get_VirtualDevice_from_vdev(
    346 				    env, zhp, vdev_cfg,
    347 				    p_vdev_id == index ? NULL : &p_vdev_id);
    348 			}
    349 			zpool_close(zhp);
    350 		}
    351 	}
    352 
    353 	return (vdev);
    354 }
    355 
    356 /*
    357  * Class:     com_sun_zfs_common_model_SystemDataModel
    358  * Method:    getVirtualDevices
    359  * Signature: (Ljava/lang/String;J)
    360  *            [Lcom/sun/zfs/common/model/VirtualDevice;
    361  */
    362 /* ARGSUSED */
    363 JNIEXPORT jobjectArray JNICALL
    364 /* CSTYLED */
    365 Java_com_sun_zfs_common_model_SystemDataModel_getVirtualDevices__Ljava_lang_String_2J(
    366     JNIEnv *env, jobject obj, jstring poolUTF, jlong index)
    367 {
    368 	jobjectArray vdevs = NULL;
    369 
    370 	if (poolUTF != NULL) {
    371 		const char *pool = (*env)->GetStringUTFChars(env, poolUTF,
    372 		    NULL);
    373 		zpool_handle_t *zhp = zpool_open_canfail(g_zfs, pool);
    374 		(*env)->ReleaseStringUTFChars(env, poolUTF, pool);
    375 
    376 		/* Is the pool valid? */
    377 		if (zhp != NULL) {
    378 			uint64_t p_vdev_id = index;
    379 			nvlist_t *vdev_cfg = zjni_get_vdev(
    380 			    zhp, NULL, index, NULL);
    381 
    382 			if (vdev_cfg != NULL) {
    383 				vdevs = zjni_get_VirtualDevices_from_vdev(
    384 				    env, zhp, vdev_cfg, &p_vdev_id);
    385 			}
    386 			zpool_close(zhp);
    387 		}
    388 	}
    389 
    390 	return (vdevs);
    391 }
    392 
    393 /*
    394  * Class:     com_sun_zfs_common_model_SystemDataModel
    395  * Method:    getVirtualDevices
    396  * Signature: (Ljava/lang/String;)
    397  *            [Lcom/sun/zfs/common/model/VirtualDevice;
    398  */
    399 /* ARGSUSED */
    400 JNIEXPORT jobjectArray JNICALL
    401 /* CSTYLED */
    402 Java_com_sun_zfs_common_model_SystemDataModel_getVirtualDevices__Ljava_lang_String_2(
    403     JNIEnv *env, jobject obj, jstring poolUTF)
    404 {
    405 	jobjectArray vdevs = NULL;
    406 
    407 	if (poolUTF != NULL) {
    408 		const char *pool = (*env)->GetStringUTFChars(env,
    409 		    poolUTF, NULL);
    410 		zpool_handle_t *zhp = zpool_open_canfail(g_zfs, pool);
    411 		(*env)->ReleaseStringUTFChars(env, poolUTF, pool);
    412 
    413 		/* Is the pool valid? */
    414 		if (zhp != NULL) {
    415 			vdevs = zjni_get_VirtualDevices_from_vdev(env,
    416 			    zhp, NULL, NULL);
    417 			zpool_close(zhp);
    418 		}
    419 	}
    420 
    421 	return (vdevs);
    422 }
    423 
    424 /*
    425  * Class:     com_sun_zfs_common_model_SystemDataModel
    426  * Method:    getAvailableDisks
    427  * Signature: ()[Lcom/sun/zfs/common/model/DiskDevice;
    428  */
    429 /* ARGSUSED */
    430 JNIEXPORT jobjectArray JNICALL
    431 Java_com_sun_zfs_common_model_SystemDataModel_getAvailableDisks(JNIEnv *env,
    432     jobject obj)
    433 {
    434 	int error;
    435 	zjni_ArrayCallbackData_t data = {0};
    436 	jobjectArray array = NULL;
    437 
    438 	/* Create an array list */
    439 	zjni_ArrayList_t list_obj = {0};
    440 	zjni_ArrayList_t *list = &list_obj;
    441 	zjni_new_ArrayList(env, list);
    442 
    443 	data.env = env;
    444 	data.list = (zjni_Collection_t *)list;
    445 	error = dmgt_avail_disk_iter(zjni_create_add_DiskDevice, &data);
    446 
    447 	if (error) {
    448 		zjni_throw_exception(env, "%s", libdskmgt_err);
    449 	} else {
    450 		array = zjni_Collection_to_array(
    451 		    env, (zjni_Collection_t *)list,
    452 		    ZFSJNI_PACKAGE_DATA "DiskDevice");
    453 	}
    454 
    455 	return (array);
    456 }
    457 
    458 /*
    459  * Class:     com_sun_zfs_common_model_SystemDataModel
    460  * Method:    getDependents
    461  * Signature: ([Ljava/lang/String;)
    462  *            [Lcom/sun/zfs/common/model/Dataset;
    463  */
    464 /* ARGSUSED */
    465 JNIEXPORT jobjectArray JNICALL
    466 Java_com_sun_zfs_common_model_SystemDataModel_getDependents(JNIEnv *env,
    467     jobject obj, jobjectArray paths)
    468 {
    469 	return (zjni_get_Datasets_dependents(env, paths));
    470 }
    471 
    472 /*
    473  * Class:     com_sun_zfs_common_model_SystemDataModel
    474  * Method:    getPropertyDefault
    475  * Signature: (Ljava/lang/String;)
    476  *            Lcom/sun/zfs/common/model/Property;
    477  */
    478 /* ARGSUSED */
    479 JNIEXPORT jobject JNICALL
    480 Java_com_sun_zfs_common_model_SystemDataModel_getPropertyDefault(JNIEnv *env,
    481     jobject obj, jstring nameUTF)
    482 {
    483 	jobject defProperty = NULL;
    484 
    485 	const char *name = (*env)->GetStringUTFChars(env, nameUTF, NULL);
    486 	zfs_prop_t prop = zjni_get_property_from_name(name);
    487 	(*env)->ReleaseStringUTFChars(env, nameUTF, name);
    488 
    489 	if (prop != ZPROP_INVAL) {
    490 		defProperty = zjni_get_default_property(env, prop);
    491 	}
    492 
    493 	return (defProperty);
    494 }
    495 
    496 typedef struct zjni_class_type_map {
    497 	char *class;
    498 	zfs_type_t type;
    499 } zjni_class_type_map_t;
    500 
    501 typedef struct mapping_data {
    502 	JNIEnv			*env;
    503 	zfs_type_t		type;
    504 	zjni_ArrayList_t	*list;
    505 } mapping_data_t;
    506 
    507 static int
    508 mapping_cb(int prop, void *cb)
    509 {
    510 	mapping_data_t *map = cb;
    511 	JNIEnv *env = map->env;
    512 	zjni_ArrayList_t *list = map->list;
    513 
    514 	if (zfs_prop_valid_for_type(prop, map->type)) {
    515 		/* Add name of property to list */
    516 		jstring propName = (*env)->NewStringUTF(env,
    517 		    zfs_prop_to_name(prop));
    518 		(*env)->CallBooleanMethod(env, ((zjni_Object_t *)list)->object,
    519 		    ((zjni_Collection_t *)list)->method_add, propName);
    520 	}
    521 
    522 	return (ZPROP_CONT);
    523 }
    524 
    525 /*
    526  * Class:     com_sun_zfs_common_model_SystemDataModel
    527  * Method:    getValidPropertyNames
    528  * Signature: (Ljava/lang/Class;)
    529  *            [Ljava/lang/String;
    530  */
    531 /* ARGSUSED */
    532 JNIEXPORT jobjectArray JNICALL
    533 Java_com_sun_zfs_common_model_SystemDataModel_getValidPropertyNames(JNIEnv *env,
    534     jobject obj, jclass class)
    535 {
    536 	int i;
    537 
    538 	/* Mappings of class names to zfs_type_t */
    539 	static zjni_class_type_map_t mappings[] = {
    540 		{ ZFSJNI_PACKAGE_DATA "FileSystem", ZFS_TYPE_FILESYSTEM },
    541 		{ ZFSJNI_PACKAGE_DATA "Volume", ZFS_TYPE_VOLUME },
    542 		{ ZFSJNI_PACKAGE_DATA "Snapshot", ZFS_TYPE_SNAPSHOT },
    543 	};
    544 	int nmappings = sizeof (mappings) / sizeof (zjni_class_type_map_t);
    545 
    546 	jclass class_Class = (*env)->FindClass(env, "java/lang/Class");
    547 
    548 	jmethodID isAssignableFrom = (*env)->GetMethodID(
    549 	    env, class_Class, "isAssignableFrom", "(Ljava/lang/Class;)Z");
    550 
    551 	/* Create an array list for the property names */
    552 	zjni_ArrayList_t list_obj = {0};
    553 	zjni_ArrayList_t *list = &list_obj;
    554 	zjni_new_ArrayList(env, list);
    555 
    556 	/* For each mapping... */
    557 	for (i = 0; i < nmappings; i++) {
    558 		/*
    559 		 * Is the given class an instance of the class in the mapping?
    560 		 */
    561 		jclass typeClass = (*env)->FindClass(env, mappings[i].class);
    562 
    563 		jboolean isInstance = (*env)->CallBooleanMethod(
    564 		    env, typeClass, isAssignableFrom, class);
    565 
    566 		if (isInstance == JNI_TRUE) {
    567 			mapping_data_t map_data;
    568 
    569 			map_data.env = env;
    570 			map_data.type = mappings[i].type;
    571 			map_data.list = list;
    572 			(void) zprop_iter(mapping_cb, &map_data, B_FALSE,
    573 			    B_FALSE, ZFS_TYPE_DATASET);
    574 			break;
    575 		}
    576 	}
    577 
    578 	return (zjni_Collection_to_array(
    579 	    env, (zjni_Collection_t *)list, "java/lang/String"));
    580 }
    581 
    582 /*
    583  * Class:     com_sun_zfs_common_model_SystemDataModel
    584  * Method:    getPoolCurrentVersion
    585  * Signature: ()J;
    586  */
    587 /* ARGSUSED */
    588 JNIEXPORT jlong JNICALL
    589 Java_com_sun_zfs_common_model_SystemDataModel_getPoolCurrentVersion(
    590     JNIEnv *env, jobject obj)
    591 {
    592 	jlong pool_current_version = SPA_VERSION;
    593 
    594 	return (pool_current_version);
    595 }
    596