xref: /illumos-gate/usr/src/lib/libzfs_jni/common/libzfs_jni_main.c (revision 43d18f1c320355e93c47399bea0b2e022fe06364)
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 2005 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_ANY, ZFSJNI_PACKAGE_DATA "Dataset"));
306 }
307 
308 /*
309  * Class:     com_sun_zfs_common_model_SystemDataModel
310  * Method:    getDataset
311  * Signature: (Ljava/lang/String;)
312  *            Lcom/sun/zfs/common/model/Dataset;
313  */
314 /* ARGSUSED */
315 JNIEXPORT jobject JNICALL
316 Java_com_sun_zfs_common_model_SystemDataModel_getDataset(JNIEnv *env,
317     jobject obj, jstring nameUTF)
318 {
319 	return (zjni_get_Dataset(env, nameUTF, ZFS_TYPE_ANY));
320 }
321 
322 /*
323  * Class:     com_sun_zfs_common_model_SystemDataModel
324  * Method:    getVirtualDevice
325  * Signature: (Ljava/lang/String;J)Lcom/sun/zfs/common/model/VirtualDevice;
326  */
327 /* ARGSUSED */
328 JNIEXPORT jobject JNICALL
329 Java_com_sun_zfs_common_model_SystemDataModel_getVirtualDevice(JNIEnv *env,
330     jobject obj, jstring poolUTF, jlong index)
331 {
332 	jobject vdev = NULL;
333 
334 	if (poolUTF != NULL) {
335 		const char *pool = (*env)->GetStringUTFChars(env, poolUTF,
336 		    NULL);
337 		zpool_handle_t *zhp = zpool_open(pool);
338 		(*env)->ReleaseStringUTFChars(env, poolUTF, pool);
339 
340 		if (zhp != NULL) {
341 			nvlist_t *vdev_cfg = zjni_get_vdev(zhp, NULL, index);
342 			if (vdev_cfg != NULL) {
343 				vdev = zjni_get_VirtualDevice_from_vdev(env,
344 				    zhp, vdev_cfg);
345 			}
346 			zpool_close(zhp);
347 		}
348 	}
349 
350 	return (vdev);
351 }
352 
353 /*
354  * Class:     com_sun_zfs_common_model_SystemDataModel
355  * Method:    getVirtualDevices
356  * Signature: (Ljava/lang/String;J)
357  *            [Lcom/sun/zfs/common/model/VirtualDevice;
358  */
359 /* ARGSUSED */
360 JNIEXPORT jobjectArray JNICALL
361 /* CSTYLED */
362 Java_com_sun_zfs_common_model_SystemDataModel_getVirtualDevices__Ljava_lang_String_2J(
363     JNIEnv *env, jobject obj, jstring poolUTF, jlong index)
364 {
365 	jobjectArray vdevs = NULL;
366 
367 	if (poolUTF != NULL) {
368 		const char *pool = (*env)->GetStringUTFChars(env, poolUTF,
369 		    NULL);
370 		zpool_handle_t *zhp = zpool_open(pool);
371 		(*env)->ReleaseStringUTFChars(env, poolUTF, pool);
372 
373 		/* Is the pool valid? */
374 		if (zhp != NULL) {
375 			nvlist_t *vdev_cfg = zjni_get_vdev(zhp, NULL, index);
376 			if (vdev_cfg != NULL) {
377 				vdevs = zjni_get_VirtualDevices_from_vdev(
378 				    env, zhp, vdev_cfg);
379 			}
380 			zpool_close(zhp);
381 		}
382 	}
383 
384 	return (vdevs);
385 }
386 
387 /*
388  * Class:     com_sun_zfs_common_model_SystemDataModel
389  * Method:    getVirtualDevices
390  * Signature: (Ljava/lang/String;)
391  *            [Lcom/sun/zfs/common/model/VirtualDevice;
392  */
393 /* ARGSUSED */
394 JNIEXPORT jobjectArray JNICALL
395 /* CSTYLED */
396 Java_com_sun_zfs_common_model_SystemDataModel_getVirtualDevices__Ljava_lang_String_2(
397     JNIEnv *env, jobject obj, jstring poolUTF)
398 {
399 	jobjectArray vdevs = NULL;
400 
401 	if (poolUTF != NULL) {
402 		const char *pool = (*env)->GetStringUTFChars(env,
403 		    poolUTF, NULL);
404 		zpool_handle_t *zhp = zpool_open(pool);
405 		(*env)->ReleaseStringUTFChars(env, poolUTF, pool);
406 
407 		/* Is the pool valid? */
408 		if (zhp != NULL) {
409 			vdevs = zjni_get_VirtualDevices_from_vdev(env,
410 			    zhp, NULL);
411 			zpool_close(zhp);
412 		}
413 	}
414 
415 	return (vdevs);
416 }
417 
418 /*
419  * Class:     com_sun_zfs_common_model_SystemDataModel
420  * Method:    getAvailableDisks
421  * Signature: ()[Lcom/sun/zfs/common/model/DiskDevice;
422  */
423 /* ARGSUSED */
424 JNIEXPORT jobjectArray JNICALL
425 Java_com_sun_zfs_common_model_SystemDataModel_getAvailableDisks(JNIEnv *env,
426     jobject obj)
427 {
428 	int error;
429 	zjni_ArrayCallbackData_t data = {0};
430 	jobjectArray array = NULL;
431 
432 	/* Create an array list */
433 	zjni_ArrayList_t list_obj = {0};
434 	zjni_ArrayList_t *list = &list_obj;
435 	zjni_new_ArrayList(env, list);
436 
437 	data.env = env;
438 	data.list = (zjni_Collection_t *)list;
439 	error = dmgt_avail_disk_iter(zjni_create_add_DiskDevice, &data);
440 
441 	if (error) {
442 		zjni_throw_exception(env, "%s", libzfs_err);
443 	} else {
444 		array = zjni_Collection_to_array(
445 		    env, (zjni_Collection_t *)list,
446 		    ZFSJNI_PACKAGE_DATA "DiskDevice");
447 	}
448 
449 	return (array);
450 }
451 
452 /*
453  * Class:     com_sun_zfs_common_model_SystemDataModel
454  * Method:    getDependents
455  * Signature: ([Ljava/lang/String;)
456  *            [Lcom/sun/zfs/common/model/Dataset;
457  */
458 /* ARGSUSED */
459 JNIEXPORT jobjectArray JNICALL
460 Java_com_sun_zfs_common_model_SystemDataModel_getDependents(JNIEnv *env,
461     jobject obj, jobjectArray paths)
462 {
463 	return (zjni_get_Datasets_dependents(env, paths));
464 }
465 
466 /*
467  * Class:     com_sun_zfs_common_model_SystemDataModel
468  * Method:    getPropertyDefault
469  * Signature: (Ljava/lang/String;)
470  *            Lcom/sun/zfs/common/model/Property;
471  */
472 /* ARGSUSED */
473 JNIEXPORT jobject JNICALL
474 Java_com_sun_zfs_common_model_SystemDataModel_getPropertyDefault(JNIEnv *env,
475     jobject obj, jstring nameUTF)
476 {
477 	jobject defProperty = NULL;
478 
479 	const char *name = (*env)->GetStringUTFChars(env, nameUTF, NULL);
480 	zfs_prop_t prop = zjni_get_property_from_name(name);
481 	(*env)->ReleaseStringUTFChars(env, nameUTF, name);
482 
483 	if (prop != ZFS_PROP_INVAL) {
484 		defProperty = zjni_get_default_property(env, prop);
485 	}
486 
487 	return (defProperty);
488 }
489 
490 typedef struct zjni_class_type_map {
491 	char *class;
492 	zfs_type_t type;
493 } zjni_class_type_map_t;
494 
495 /*
496  * Class:     com_sun_zfs_common_model_SystemDataModel
497  * Method:    getValidPropertyNames
498  * Signature: (Ljava/lang/Class;)
499  *            [Ljava/lang/String;
500  */
501 /* ARGSUSED */
502 JNIEXPORT jobjectArray JNICALL
503 Java_com_sun_zfs_common_model_SystemDataModel_getValidPropertyNames(JNIEnv *env,
504     jobject obj, jclass class)
505 {
506 	int i;
507 
508 	/* Mappings of class names to zfs_type_t */
509 	static zjni_class_type_map_t mappings[] = {
510 		{ ZFSJNI_PACKAGE_DATA "FileSystem", ZFS_TYPE_FILESYSTEM },
511 		{ ZFSJNI_PACKAGE_DATA "Volume", ZFS_TYPE_VOLUME },
512 		{ ZFSJNI_PACKAGE_DATA "Snapshot", ZFS_TYPE_SNAPSHOT },
513 	};
514 	int nmappings = sizeof (mappings) / sizeof (zjni_class_type_map_t);
515 
516 	jclass class_Class = (*env)->FindClass(env, "java/lang/Class");
517 
518 	jmethodID isAssignableFrom = (*env)->GetMethodID(
519 	    env, class_Class, "isAssignableFrom", "(Ljava/lang/Class;)Z");
520 
521 	/* Create an array list for the property names */
522 	zjni_ArrayList_t list_obj = {0};
523 	zjni_ArrayList_t *list = &list_obj;
524 	zjni_new_ArrayList(env, list);
525 
526 	/* For each mapping... */
527 	for (i = 0; i < nmappings; i++) {
528 		/*
529 		 * Is the given class an instance of the class in the mapping?
530 		 */
531 		jclass typeClass = (*env)->FindClass(env, mappings[i].class);
532 
533 		jboolean isInstance = (*env)->CallBooleanMethod(
534 		    env, typeClass, isAssignableFrom, class);
535 
536 		if (isInstance == JNI_TRUE) {
537 			zfs_prop_t prop;
538 			for (prop = 0; prop < ZFS_NPROP_VISIBLE; prop++) {
539 				if (zfs_prop_valid_for_type(prop,
540 				    mappings[i].type)) {
541 					/* Add name of property to list */
542 					jstring propName =
543 					    (*env)->NewStringUTF(env,
544 						zfs_prop_to_name(prop));
545 					(*env)->CallBooleanMethod(
546 					    env,
547 					    ((zjni_Object_t *)list)->object,
548 					    ((zjni_Collection_t *)list)->
549 					    method_add, propName);
550 				}
551 			}
552 			break;
553 		}
554 	}
555 
556 	return (zjni_Collection_to_array(
557 	    env, (zjni_Collection_t *)list, "java/lang/String"));
558 }
559