xref: /illumos-gate/usr/src/lib/libzfs_jni/common/libzfs_jni_main.c (revision 65a89a64c60f3061bbe2381edaacc81660af9a95)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2006 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 /*
39  * Function prototypes
40  */
41 
42 static void handle_error(const char *, va_list);
43 static void init();
44 
45 /*
46  * Static functions
47  */
48 
49 char libzfs_err[1024];
50 static void
51 handle_error(const char *fmt, va_list ap)
52 {
53 	/* Save the error message in case it's needed */
54 	(void) vsnprintf(libzfs_err, sizeof (libzfs_err), fmt, ap);
55 #ifdef	DEBUG
56 	(void) fprintf(stderr, "caught error: %s\n", libzfs_err);
57 #endif
58 }
59 
60 /*
61  * Initialize the library.  Sets the error handler.
62  */
63 #pragma init(init)
64 static void
65 init()
66 {
67 	libzfs_err[0] = '\0';
68 
69 	/* libzfs error handler */
70 	zfs_set_error_handler(handle_error);
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_DatasetArrayCallbackData_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.data.env = env;
152 	data.data.list = (zjni_Collection_t *)list;
153 	data.typemask = ZFS_TYPE_FILESYSTEM;
154 
155 	result = zfs_iter_root(zjni_create_add_Dataset, &data);
156 	if (result && (*env)->ExceptionOccurred(env) != NULL) {
157 		/* Must not call any more Java methods to preserve exception */
158 		return (NULL);
159 	}
160 
161 	return (zjni_Collection_to_array(env, (zjni_Collection_t *)list,
162 	    ZFSJNI_PACKAGE_DATA "Pool"));
163 }
164 
165 /*
166  * Class:     com_sun_zfs_common_model_SystemDataModel
167  * Method:    getPool
168  * Signature: (Ljava/lang/String;)
169  *            Lcom/sun/zfs/common/model/Pool;
170  */
171 /* ARGSUSED */
172 JNIEXPORT jobject JNICALL
173 Java_com_sun_zfs_common_model_SystemDataModel_getPool(JNIEnv *env,
174     jobject obj, jstring poolUTF)
175 {
176 	jobject pool = zjni_get_Dataset(env, poolUTF, ZFS_TYPE_FILESYSTEM);
177 
178 	/* Verify that object is Pool, not some other Dataset */
179 	if (pool != NULL) {
180 	    jclass class = (*env)->FindClass(
181 		env, ZFSJNI_PACKAGE_DATA "Pool");
182 
183 	    jboolean is_pool = (*env)->IsInstanceOf(env, pool, class);
184 
185 	    if (is_pool != JNI_TRUE) {
186 		pool = NULL;
187 	    }
188 	}
189 
190 	return (pool);
191 }
192 
193 /*
194  * Class:     com_sun_zfs_common_model_SystemDataModel
195  * Method:    getFileSystems
196  * Signature: (Ljava/lang/String;)
197  *            [Lcom/sun/zfs/common/model/FileSystem;
198  */
199 /* ARGSUSED */
200 JNIEXPORT jobjectArray JNICALL
201 Java_com_sun_zfs_common_model_SystemDataModel_getFileSystems(JNIEnv *env,
202     jobject obj, jstring containerUTF)
203 {
204 	if (containerUTF == NULL) {
205 		return (Java_com_sun_zfs_common_model_SystemDataModel_getPools(
206 		    env, obj));
207 	}
208 
209 	return (zjni_get_Datasets_below(env, containerUTF,
210 	    ZFS_TYPE_FILESYSTEM, ZFS_TYPE_FILESYSTEM,
211 	    ZFSJNI_PACKAGE_DATA "FileSystem"));
212 }
213 
214 /*
215  * Class:     com_sun_zfs_common_model_SystemDataModel
216  * Method:    getFileSystem
217  * Signature: (Ljava/lang/String;)
218  *            Lcom/sun/zfs/common/model/FileSystem;
219  */
220 /* ARGSUSED */
221 JNIEXPORT jobject JNICALL
222 Java_com_sun_zfs_common_model_SystemDataModel_getFileSystem(JNIEnv *env,
223     jobject obj, jstring nameUTF)
224 {
225 	return (zjni_get_Dataset(env, nameUTF, ZFS_TYPE_FILESYSTEM));
226 }
227 
228 /*
229  * Class:     com_sun_zfs_common_model_SystemDataModel
230  * Method:    getVolumes
231  * Signature: (Ljava/lang/String;)
232  *            [Lcom/sun/zfs/common/model/Volume;
233  */
234 /* ARGSUSED */
235 JNIEXPORT jobjectArray JNICALL
236 Java_com_sun_zfs_common_model_SystemDataModel_getVolumes(JNIEnv *env,
237     jobject obj, jstring containerUTF)
238 {
239 	return (zjni_get_Datasets_below(env, containerUTF,
240 	    ZFS_TYPE_FILESYSTEM, ZFS_TYPE_VOLUME,
241 	    ZFSJNI_PACKAGE_DATA "Volume"));
242 }
243 
244 /*
245  * Class:     com_sun_zfs_common_model_SystemDataModel
246  * Method:    getVolume
247  * Signature: (Ljava/lang/String;)
248  *            Lcom/sun/zfs/common/model/Volume;
249  */
250 /* ARGSUSED */
251 JNIEXPORT jobject JNICALL
252 Java_com_sun_zfs_common_model_SystemDataModel_getVolume(JNIEnv *env,
253     jobject obj, jstring nameUTF)
254 {
255 	return (zjni_get_Dataset(env, nameUTF, ZFS_TYPE_VOLUME));
256 }
257 
258 /*
259  * Class:     com_sun_zfs_common_model_SystemDataModel
260  * Method:    getSnapshots
261  * Signature: (Ljava/lang/String;)
262  *            [Lcom/sun/zfs/common/model/Snapshot;
263  */
264 /* ARGSUSED */
265 JNIEXPORT jobjectArray JNICALL
266 Java_com_sun_zfs_common_model_SystemDataModel_getSnapshots(JNIEnv *env,
267     jobject obj, jstring datasetUTF)
268 {
269 	return (zjni_get_Datasets_below(env, datasetUTF,
270 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, ZFS_TYPE_SNAPSHOT,
271 	    ZFSJNI_PACKAGE_DATA "Snapshot"));
272 }
273 
274 /*
275  * Class:     com_sun_zfs_common_model_SystemDataModel
276  * Method:    getSnapshot
277  * Signature: (Ljava/lang/String;)
278  *            Lcom/sun/zfs/common/model/Snapshot;
279  */
280 /* ARGSUSED */
281 JNIEXPORT jobject JNICALL
282 Java_com_sun_zfs_common_model_SystemDataModel_getSnapshot(JNIEnv *env,
283     jobject obj, jstring nameUTF)
284 {
285 	return (zjni_get_Dataset(env, nameUTF, ZFS_TYPE_SNAPSHOT));
286 }
287 
288 /*
289  * Class:     com_sun_zfs_common_model_SystemDataModel
290  * Method:    getDatasets
291  * Signature: (Ljava/lang/String;)
292  *            [Lcom/sun/zfs/common/model/Dataset;
293  */
294 /* ARGSUSED */
295 JNIEXPORT jobjectArray JNICALL
296 Java_com_sun_zfs_common_model_SystemDataModel_getDatasets(JNIEnv *env,
297     jobject obj, jstring containerUTF)
298 {
299 	if (containerUTF == NULL) {
300 		return (Java_com_sun_zfs_common_model_SystemDataModel_getPools(
301 		    env, obj));
302 	}
303 
304 	return (zjni_get_Datasets_below(env, containerUTF,
305 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, ZFS_TYPE_ANY,
306 	    ZFSJNI_PACKAGE_DATA "Dataset"));
307 }
308 
309 /*
310  * Class:     com_sun_zfs_common_model_SystemDataModel
311  * Method:    getDataset
312  * Signature: (Ljava/lang/String;)
313  *            Lcom/sun/zfs/common/model/Dataset;
314  */
315 /* ARGSUSED */
316 JNIEXPORT jobject JNICALL
317 Java_com_sun_zfs_common_model_SystemDataModel_getDataset(JNIEnv *env,
318     jobject obj, jstring nameUTF)
319 {
320 	return (zjni_get_Dataset(env, nameUTF, ZFS_TYPE_ANY));
321 }
322 
323 /*
324  * Class:     com_sun_zfs_common_model_SystemDataModel
325  * Method:    getVirtualDevice
326  * Signature: (Ljava/lang/String;J)Lcom/sun/zfs/common/model/VirtualDevice;
327  */
328 /* ARGSUSED */
329 JNIEXPORT jobject JNICALL
330 Java_com_sun_zfs_common_model_SystemDataModel_getVirtualDevice(JNIEnv *env,
331     jobject obj, jstring poolUTF, jlong index)
332 {
333 	jobject vdev = NULL;
334 
335 	if (poolUTF != NULL) {
336 		const char *pool = (*env)->GetStringUTFChars(env, poolUTF,
337 		    NULL);
338 		zpool_handle_t *zhp = zpool_open(pool);
339 		(*env)->ReleaseStringUTFChars(env, poolUTF, pool);
340 
341 		if (zhp != NULL) {
342 			nvlist_t *vdev_cfg = zjni_get_vdev(zhp, NULL, index);
343 			if (vdev_cfg != NULL) {
344 				vdev = zjni_get_VirtualDevice_from_vdev(env,
345 				    zhp, vdev_cfg);
346 			}
347 			zpool_close(zhp);
348 		}
349 	}
350 
351 	return (vdev);
352 }
353 
354 /*
355  * Class:     com_sun_zfs_common_model_SystemDataModel
356  * Method:    getVirtualDevices
357  * Signature: (Ljava/lang/String;J)
358  *            [Lcom/sun/zfs/common/model/VirtualDevice;
359  */
360 /* ARGSUSED */
361 JNIEXPORT jobjectArray JNICALL
362 /* CSTYLED */
363 Java_com_sun_zfs_common_model_SystemDataModel_getVirtualDevices__Ljava_lang_String_2J(
364     JNIEnv *env, jobject obj, jstring poolUTF, jlong index)
365 {
366 	jobjectArray vdevs = NULL;
367 
368 	if (poolUTF != NULL) {
369 		const char *pool = (*env)->GetStringUTFChars(env, poolUTF,
370 		    NULL);
371 		zpool_handle_t *zhp = zpool_open(pool);
372 		(*env)->ReleaseStringUTFChars(env, poolUTF, pool);
373 
374 		/* Is the pool valid? */
375 		if (zhp != NULL) {
376 			nvlist_t *vdev_cfg = zjni_get_vdev(zhp, NULL, index);
377 			if (vdev_cfg != NULL) {
378 				vdevs = zjni_get_VirtualDevices_from_vdev(
379 				    env, zhp, vdev_cfg);
380 			}
381 			zpool_close(zhp);
382 		}
383 	}
384 
385 	return (vdevs);
386 }
387 
388 /*
389  * Class:     com_sun_zfs_common_model_SystemDataModel
390  * Method:    getVirtualDevices
391  * Signature: (Ljava/lang/String;)
392  *            [Lcom/sun/zfs/common/model/VirtualDevice;
393  */
394 /* ARGSUSED */
395 JNIEXPORT jobjectArray JNICALL
396 /* CSTYLED */
397 Java_com_sun_zfs_common_model_SystemDataModel_getVirtualDevices__Ljava_lang_String_2(
398     JNIEnv *env, jobject obj, jstring poolUTF)
399 {
400 	jobjectArray vdevs = NULL;
401 
402 	if (poolUTF != NULL) {
403 		const char *pool = (*env)->GetStringUTFChars(env,
404 		    poolUTF, NULL);
405 		zpool_handle_t *zhp = zpool_open(pool);
406 		(*env)->ReleaseStringUTFChars(env, poolUTF, pool);
407 
408 		/* Is the pool valid? */
409 		if (zhp != NULL) {
410 			vdevs = zjni_get_VirtualDevices_from_vdev(env,
411 			    zhp, NULL);
412 			zpool_close(zhp);
413 		}
414 	}
415 
416 	return (vdevs);
417 }
418 
419 /*
420  * Class:     com_sun_zfs_common_model_SystemDataModel
421  * Method:    getAvailableDisks
422  * Signature: ()[Lcom/sun/zfs/common/model/DiskDevice;
423  */
424 /* ARGSUSED */
425 JNIEXPORT jobjectArray JNICALL
426 Java_com_sun_zfs_common_model_SystemDataModel_getAvailableDisks(JNIEnv *env,
427     jobject obj)
428 {
429 	int error;
430 	zjni_ArrayCallbackData_t data = {0};
431 	jobjectArray array = NULL;
432 
433 	/* Create an array list */
434 	zjni_ArrayList_t list_obj = {0};
435 	zjni_ArrayList_t *list = &list_obj;
436 	zjni_new_ArrayList(env, list);
437 
438 	data.env = env;
439 	data.list = (zjni_Collection_t *)list;
440 	error = dmgt_avail_disk_iter(zjni_create_add_DiskDevice, &data);
441 
442 	if (error) {
443 		zjni_throw_exception(env, "%s", libzfs_err);
444 	} else {
445 		array = zjni_Collection_to_array(
446 		    env, (zjni_Collection_t *)list,
447 		    ZFSJNI_PACKAGE_DATA "DiskDevice");
448 	}
449 
450 	return (array);
451 }
452 
453 /*
454  * Class:     com_sun_zfs_common_model_SystemDataModel
455  * Method:    getDependents
456  * Signature: ([Ljava/lang/String;)
457  *            [Lcom/sun/zfs/common/model/Dataset;
458  */
459 /* ARGSUSED */
460 JNIEXPORT jobjectArray JNICALL
461 Java_com_sun_zfs_common_model_SystemDataModel_getDependents(JNIEnv *env,
462     jobject obj, jobjectArray paths)
463 {
464 	return (zjni_get_Datasets_dependents(env, paths));
465 }
466 
467 /*
468  * Class:     com_sun_zfs_common_model_SystemDataModel
469  * Method:    getPropertyDefault
470  * Signature: (Ljava/lang/String;)
471  *            Lcom/sun/zfs/common/model/Property;
472  */
473 /* ARGSUSED */
474 JNIEXPORT jobject JNICALL
475 Java_com_sun_zfs_common_model_SystemDataModel_getPropertyDefault(JNIEnv *env,
476     jobject obj, jstring nameUTF)
477 {
478 	jobject defProperty = NULL;
479 
480 	const char *name = (*env)->GetStringUTFChars(env, nameUTF, NULL);
481 	zfs_prop_t prop = zjni_get_property_from_name(name);
482 	(*env)->ReleaseStringUTFChars(env, nameUTF, name);
483 
484 	if (prop != ZFS_PROP_INVAL) {
485 		defProperty = zjni_get_default_property(env, prop);
486 	}
487 
488 	return (defProperty);
489 }
490 
491 typedef struct zjni_class_type_map {
492 	char *class;
493 	zfs_type_t type;
494 } zjni_class_type_map_t;
495 
496 /*
497  * Class:     com_sun_zfs_common_model_SystemDataModel
498  * Method:    getValidPropertyNames
499  * Signature: (Ljava/lang/Class;)
500  *            [Ljava/lang/String;
501  */
502 /* ARGSUSED */
503 JNIEXPORT jobjectArray JNICALL
504 Java_com_sun_zfs_common_model_SystemDataModel_getValidPropertyNames(JNIEnv *env,
505     jobject obj, jclass class)
506 {
507 	int i;
508 
509 	/* Mappings of class names to zfs_type_t */
510 	static zjni_class_type_map_t mappings[] = {
511 		{ ZFSJNI_PACKAGE_DATA "FileSystem", ZFS_TYPE_FILESYSTEM },
512 		{ ZFSJNI_PACKAGE_DATA "Volume", ZFS_TYPE_VOLUME },
513 		{ ZFSJNI_PACKAGE_DATA "Snapshot", ZFS_TYPE_SNAPSHOT },
514 	};
515 	int nmappings = sizeof (mappings) / sizeof (zjni_class_type_map_t);
516 
517 	jclass class_Class = (*env)->FindClass(env, "java/lang/Class");
518 
519 	jmethodID isAssignableFrom = (*env)->GetMethodID(
520 	    env, class_Class, "isAssignableFrom", "(Ljava/lang/Class;)Z");
521 
522 	/* Create an array list for the property names */
523 	zjni_ArrayList_t list_obj = {0};
524 	zjni_ArrayList_t *list = &list_obj;
525 	zjni_new_ArrayList(env, list);
526 
527 	/* For each mapping... */
528 	for (i = 0; i < nmappings; i++) {
529 		/*
530 		 * Is the given class an instance of the class in the mapping?
531 		 */
532 		jclass typeClass = (*env)->FindClass(env, mappings[i].class);
533 
534 		jboolean isInstance = (*env)->CallBooleanMethod(
535 		    env, typeClass, isAssignableFrom, class);
536 
537 		if (isInstance == JNI_TRUE) {
538 			zfs_prop_t prop;
539 			for (prop = 0; prop < ZFS_NPROP_VISIBLE; prop++) {
540 				if (zfs_prop_valid_for_type(prop,
541 				    mappings[i].type)) {
542 					/* Add name of property to list */
543 					jstring propName =
544 					    (*env)->NewStringUTF(env,
545 						zfs_prop_to_name(prop));
546 					(*env)->CallBooleanMethod(
547 					    env,
548 					    ((zjni_Object_t *)list)->object,
549 					    ((zjni_Collection_t *)list)->
550 					    method_add, propName);
551 				}
552 			}
553 			break;
554 		}
555 	}
556 
557 	return (zjni_Collection_to_array(
558 	    env, (zjni_Collection_t *)list, "java/lang/String"));
559 }
560