xref: /illumos-gate/usr/src/lib/libzfs_jni/common/libzfs_jni_main.c (revision 4bc0a2ef2b7ba50a7a717e7ddbf31472ad28e358)
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 "libzfs_jni_main.h"
30 #include "libzfs_jni_util.h"
31 #include "libzfs_jni_dataset.h"
32 #include "libzfs_jni_property.h"
33 #include "libzfs_jni_pool.h"
34 #include "libzfs_jni_diskmgt.h"
35 #include "libzfs_jni_disk.h"
36 
37 /*
38  * Function prototypes
39  */
40 
41 static void handle_error(const char *, va_list);
42 static void init();
43 
44 /*
45  * Static functions
46  */
47 
48 char libzfs_err[1024];
49 static void
50 handle_error(const char *fmt, va_list ap)
51 {
52 	/* Save the error message in case it's needed */
53 	(void) vsnprintf(libzfs_err, sizeof (libzfs_err), fmt, ap);
54 #ifdef	DEBUG
55 	(void) fprintf(stderr, "caught error: %s\n", libzfs_err);
56 #endif
57 }
58 
59 /*
60  * Initialize the library.  Sets the error handler.
61  */
62 #pragma init(init)
63 static void
64 init()
65 {
66 	libzfs_err[0] = '\0';
67 
68 	/* libzfs error handler */
69 	zfs_set_error_handler(handle_error);
70 
71 	/* diskmgt.o error handler */
72 	dmgt_set_error_handler(handle_error);
73 }
74 
75 /*
76  * JNI functions
77  */
78 
79 /*
80  * Class:     com_sun_zfs_common_model_SystemDataModel
81  * Method:    getPools
82  * Signature: ()[Lcom/sun/zfs/common/model/Pool;
83  */
84 /* ARGSUSED */
85 JNIEXPORT jobjectArray JNICALL
86 Java_com_sun_zfs_common_model_SystemDataModel_getPools(JNIEnv *env, jobject obj)
87 {
88 	zjni_DatasetArrayCallbackData_t data = {0};
89 	int result;
90 
91 	/* Create an array list */
92 	zjni_ArrayList_t list_obj = {0};
93 	zjni_ArrayList_t *list = &list_obj;
94 	zjni_new_ArrayList(env, list);
95 
96 	data.data.env = env;
97 	data.data.list = (zjni_Collection_t *)list;
98 	data.typemask = ZFS_TYPE_FILESYSTEM;
99 
100 	result = zfs_iter_root(zjni_create_add_Dataset, &data);
101 	if (result && (*env)->ExceptionOccurred(env) != NULL) {
102 		/* Must not call any more Java methods to preserve exception */
103 		return (NULL);
104 	}
105 
106 	return (zjni_Collection_to_array(env, (zjni_Collection_t *)list,
107 	    ZFSJNI_PACKAGE_DATA "Pool"));
108 }
109 
110 /*
111  * Class:     com_sun_zfs_common_model_SystemDataModel
112  * Method:    getPool
113  * Signature: (Ljava/lang/String;)
114  *            Lcom/sun/zfs/common/model/Pool;
115  */
116 /* ARGSUSED */
117 JNIEXPORT jobject JNICALL
118 Java_com_sun_zfs_common_model_SystemDataModel_getPool(JNIEnv *env,
119     jobject obj, jstring poolUTF)
120 {
121 	return (zjni_get_Dataset(env, poolUTF, ZFS_TYPE_FILESYSTEM));
122 }
123 
124 /*
125  * Class:     com_sun_zfs_common_model_SystemDataModel
126  * Method:    getFileSystems
127  * Signature: (Ljava/lang/String;)
128  *            [Lcom/sun/zfs/common/model/FileSystem;
129  */
130 /* ARGSUSED */
131 JNIEXPORT jobjectArray JNICALL
132 Java_com_sun_zfs_common_model_SystemDataModel_getFileSystems(JNIEnv *env,
133     jobject obj, jstring containerUTF)
134 {
135 	return (zjni_get_Datasets_below(env, containerUTF,
136 	    ZFS_TYPE_FILESYSTEM, ZFS_TYPE_FILESYSTEM,
137 	    ZFSJNI_PACKAGE_DATA "FileSystem"));
138 }
139 
140 /*
141  * Class:     com_sun_zfs_common_model_SystemDataModel
142  * Method:    getFileSystem
143  * Signature: (Ljava/lang/String;)
144  *            Lcom/sun/zfs/common/model/FileSystem;
145  */
146 /* ARGSUSED */
147 JNIEXPORT jobject JNICALL
148 Java_com_sun_zfs_common_model_SystemDataModel_getFileSystem(JNIEnv *env,
149     jobject obj, jstring nameUTF)
150 {
151 	return (zjni_get_Dataset(env, nameUTF, ZFS_TYPE_FILESYSTEM));
152 }
153 
154 /*
155  * Class:     com_sun_zfs_common_model_SystemDataModel
156  * Method:    getVolumes
157  * Signature: (Ljava/lang/String;)
158  *            [Lcom/sun/zfs/common/model/Volume;
159  */
160 /* ARGSUSED */
161 JNIEXPORT jobjectArray JNICALL
162 Java_com_sun_zfs_common_model_SystemDataModel_getVolumes(JNIEnv *env,
163     jobject obj, jstring containerUTF)
164 {
165 	return (zjni_get_Datasets_below(env, containerUTF,
166 	    ZFS_TYPE_FILESYSTEM, ZFS_TYPE_VOLUME,
167 	    ZFSJNI_PACKAGE_DATA "Volume"));
168 }
169 
170 /*
171  * Class:     com_sun_zfs_common_model_SystemDataModel
172  * Method:    getVolume
173  * Signature: (Ljava/lang/String;)
174  *            Lcom/sun/zfs/common/model/Volume;
175  */
176 /* ARGSUSED */
177 JNIEXPORT jobject JNICALL
178 Java_com_sun_zfs_common_model_SystemDataModel_getVolume(JNIEnv *env,
179     jobject obj, jstring nameUTF)
180 {
181 	return (zjni_get_Dataset(env, nameUTF, ZFS_TYPE_VOLUME));
182 }
183 
184 /*
185  * Class:     com_sun_zfs_common_model_SystemDataModel
186  * Method:    getSnapshots
187  * Signature: (Ljava/lang/String;)
188  *            [Lcom/sun/zfs/common/model/Snapshot;
189  */
190 /* ARGSUSED */
191 JNIEXPORT jobjectArray JNICALL
192 Java_com_sun_zfs_common_model_SystemDataModel_getSnapshots(JNIEnv *env,
193     jobject obj, jstring datasetUTF)
194 {
195 	return (zjni_get_Datasets_below(env, datasetUTF,
196 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, ZFS_TYPE_SNAPSHOT,
197 	    ZFSJNI_PACKAGE_DATA "Snapshot"));
198 }
199 
200 /*
201  * Class:     com_sun_zfs_common_model_SystemDataModel
202  * Method:    getSnapshot
203  * Signature: (Ljava/lang/String;)
204  *            Lcom/sun/zfs/common/model/Snapshot;
205  */
206 /* ARGSUSED */
207 JNIEXPORT jobject JNICALL
208 Java_com_sun_zfs_common_model_SystemDataModel_getSnapshot(JNIEnv *env,
209     jobject obj, jstring nameUTF)
210 {
211 	return (zjni_get_Dataset(env, nameUTF, ZFS_TYPE_SNAPSHOT));
212 }
213 
214 /*
215  * Class:     com_sun_zfs_common_model_SystemDataModel
216  * Method:    getDatasets
217  * Signature: (Ljava/lang/String;)
218  *            [Lcom/sun/zfs/common/model/Dataset;
219  */
220 /* ARGSUSED */
221 JNIEXPORT jobjectArray JNICALL
222 Java_com_sun_zfs_common_model_SystemDataModel_getDatasets(JNIEnv *env,
223     jobject obj, jstring containerUTF)
224 {
225 	if (containerUTF == NULL) {
226 		return (Java_com_sun_zfs_common_model_SystemDataModel_getPools(
227 		    env, obj));
228 	}
229 
230 	return (zjni_get_Datasets_below(env, containerUTF,
231 	    ZFS_TYPE_FILESYSTEM, ZFS_TYPE_ANY,
232 	    ZFSJNI_PACKAGE_DATA "Dataset"));
233 }
234 
235 /*
236  * Class:     com_sun_zfs_common_model_SystemDataModel
237  * Method:    getDataset
238  * Signature: (Ljava/lang/String;)
239  *            Lcom/sun/zfs/common/model/Dataset;
240  */
241 /* ARGSUSED */
242 JNIEXPORT jobject JNICALL
243 Java_com_sun_zfs_common_model_SystemDataModel_getDataset(JNIEnv *env,
244     jobject obj, jstring nameUTF)
245 {
246 	return (zjni_get_Dataset(env, nameUTF, ZFS_TYPE_ANY));
247 }
248 
249 /*
250  * Class:     com_sun_zfs_common_model_SystemDataModel
251  * Method:    getVirtualDevice
252  * Signature: (Ljava/lang/String;J)Lcom/sun/zfs/common/model/VirtualDevice;
253  */
254 /* ARGSUSED */
255 JNIEXPORT jobject JNICALL
256 Java_com_sun_zfs_common_model_SystemDataModel_getVirtualDevice(JNIEnv *env,
257     jobject obj, jstring poolUTF, jlong index)
258 {
259 	jobject vdev = NULL;
260 
261 	if (poolUTF != NULL) {
262 		const char *pool = (*env)->GetStringUTFChars(env, poolUTF,
263 		    NULL);
264 		zpool_handle_t *zhp = zpool_open(pool);
265 		(*env)->ReleaseStringUTFChars(env, poolUTF, pool);
266 
267 		if (zhp != NULL) {
268 			nvlist_t *vdev_cfg = zjni_get_vdev(zhp, NULL, index);
269 			if (vdev_cfg != NULL) {
270 				vdev = zjni_get_VirtualDevice_from_vdev(env,
271 				    zhp, vdev_cfg);
272 			}
273 			zpool_close(zhp);
274 		}
275 	}
276 
277 	return (vdev);
278 }
279 
280 /*
281  * Class:     com_sun_zfs_common_model_SystemDataModel
282  * Method:    getVirtualDevices
283  * Signature: (Ljava/lang/String;J)
284  *            [Lcom/sun/zfs/common/model/VirtualDevice;
285  */
286 /* ARGSUSED */
287 JNIEXPORT jobjectArray JNICALL
288 /* CSTYLED */
289 Java_com_sun_zfs_common_model_SystemDataModel_getVirtualDevices__Ljava_lang_String_2J(
290     JNIEnv *env, jobject obj, jstring poolUTF, jlong index)
291 {
292 	jobjectArray vdevs = NULL;
293 
294 	if (poolUTF != NULL) {
295 		const char *pool = (*env)->GetStringUTFChars(env, poolUTF,
296 		    NULL);
297 		zpool_handle_t *zhp = zpool_open(pool);
298 		(*env)->ReleaseStringUTFChars(env, poolUTF, pool);
299 
300 		/* Is the pool valid? */
301 		if (zhp != NULL) {
302 			nvlist_t *vdev_cfg = zjni_get_vdev(zhp, NULL, index);
303 			if (vdev_cfg != NULL) {
304 				vdevs = zjni_get_VirtualDevices_from_vdev(
305 				    env, zhp, vdev_cfg);
306 			}
307 			zpool_close(zhp);
308 		}
309 	}
310 
311 	return (vdevs);
312 }
313 
314 /*
315  * Class:     com_sun_zfs_common_model_SystemDataModel
316  * Method:    getVirtualDevices
317  * Signature: (Ljava/lang/String;)
318  *            [Lcom/sun/zfs/common/model/VirtualDevice;
319  */
320 /* ARGSUSED */
321 JNIEXPORT jobjectArray JNICALL
322 /* CSTYLED */
323 Java_com_sun_zfs_common_model_SystemDataModel_getVirtualDevices__Ljava_lang_String_2(
324     JNIEnv *env, jobject obj, jstring poolUTF)
325 {
326 	jobjectArray vdevs = NULL;
327 
328 	if (poolUTF != NULL) {
329 		const char *pool = (*env)->GetStringUTFChars(env,
330 		    poolUTF, NULL);
331 		zpool_handle_t *zhp = zpool_open(pool);
332 		(*env)->ReleaseStringUTFChars(env, poolUTF, pool);
333 
334 		/* Is the pool valid? */
335 		if (zhp != NULL) {
336 			vdevs = zjni_get_VirtualDevices_from_vdev(env,
337 			    zhp, NULL);
338 			zpool_close(zhp);
339 		}
340 	}
341 
342 	return (vdevs);
343 }
344 
345 /*
346  * Class:     com_sun_zfs_common_model_SystemDataModel
347  * Method:    getAvailableDisks
348  * Signature: ()[Lcom/sun/zfs/common/model/DiskDevice;
349  */
350 /* ARGSUSED */
351 JNIEXPORT jobjectArray JNICALL
352 Java_com_sun_zfs_common_model_SystemDataModel_getAvailableDisks(JNIEnv *env,
353     jobject obj)
354 {
355 	int error;
356 	zjni_ArrayCallbackData_t data = {0};
357 	jobjectArray array = NULL;
358 
359 	/* Create an array list */
360 	zjni_ArrayList_t list_obj = {0};
361 	zjni_ArrayList_t *list = &list_obj;
362 	zjni_new_ArrayList(env, list);
363 
364 	data.env = env;
365 	data.list = (zjni_Collection_t *)list;
366 	error = dmgt_avail_disk_iter(zjni_create_add_DiskDevice, &data);
367 
368 	if (error) {
369 		zjni_throw_exception(env, "%s", libzfs_err);
370 	} else {
371 		array = zjni_Collection_to_array(
372 		    env, (zjni_Collection_t *)list,
373 		    ZFSJNI_PACKAGE_DATA "DiskDevice");
374 	}
375 
376 	return (array);
377 }
378 
379 /*
380  * Class:     com_sun_zfs_common_model_SystemDataModel
381  * Method:    getDependents
382  * Signature: ([Ljava/lang/String;)
383  *            [Lcom/sun/zfs/common/model/Dataset;
384  */
385 /* ARGSUSED */
386 JNIEXPORT jobjectArray JNICALL
387 Java_com_sun_zfs_common_model_SystemDataModel_getDependents(JNIEnv *env,
388     jobject obj, jobjectArray paths)
389 {
390 	return (zjni_get_Datasets_dependents(env, paths));
391 }
392 
393 /*
394  * Class:     com_sun_zfs_common_model_SystemDataModel
395  * Method:    getPropertyDefault
396  * Signature: (Ljava/lang/String;)
397  *            Lcom/sun/zfs/common/model/Property;
398  */
399 /* ARGSUSED */
400 JNIEXPORT jobject JNICALL
401 Java_com_sun_zfs_common_model_SystemDataModel_getPropertyDefault(JNIEnv *env,
402     jobject obj, jstring nameUTF)
403 {
404 	jobject defProperty = NULL;
405 
406 	const char *name = (*env)->GetStringUTFChars(env, nameUTF, NULL);
407 	zfs_prop_t prop = zjni_get_property_from_name(name);
408 	(*env)->ReleaseStringUTFChars(env, nameUTF, name);
409 
410 	if (prop != ZFS_PROP_INVAL) {
411 		defProperty = zjni_get_default_property(env, prop);
412 	}
413 
414 	return (defProperty);
415 }
416 
417 typedef struct zjni_class_type_map {
418 	char *class;
419 	zfs_type_t type;
420 } zjni_class_type_map_t;
421 
422 /*
423  * Class:     com_sun_zfs_common_model_SystemDataModel
424  * Method:    getValidPropertyNames
425  * Signature: (Ljava/lang/Class;)
426  *            [Ljava/lang/String;
427  */
428 /* ARGSUSED */
429 JNIEXPORT jobjectArray JNICALL
430 Java_com_sun_zfs_common_model_SystemDataModel_getValidPropertyNames(JNIEnv *env,
431     jobject obj, jclass class)
432 {
433 	int i;
434 
435 	/* Mappings of class names to zfs_type_t */
436 	static zjni_class_type_map_t mappings[] = {
437 		{ ZFSJNI_PACKAGE_DATA "FileSystem", ZFS_TYPE_FILESYSTEM },
438 		{ ZFSJNI_PACKAGE_DATA "Volume", ZFS_TYPE_VOLUME },
439 		{ ZFSJNI_PACKAGE_DATA "Snapshot", ZFS_TYPE_SNAPSHOT },
440 	};
441 	int nmappings = sizeof (mappings) / sizeof (zjni_class_type_map_t);
442 
443 	jclass class_Class = (*env)->FindClass(env, "java/lang/Class");
444 
445 	jmethodID isAssignableFrom = (*env)->GetMethodID(
446 	    env, class_Class, "isAssignableFrom", "(Ljava/lang/Class;)Z");
447 
448 	/* Create an array list for the property names */
449 	zjni_ArrayList_t list_obj = {0};
450 	zjni_ArrayList_t *list = &list_obj;
451 	zjni_new_ArrayList(env, list);
452 
453 	/* For each mapping... */
454 	for (i = 0; i < nmappings; i++) {
455 		/*
456 		 * Is the given class an instance of the class in the mapping?
457 		 */
458 		jclass typeClass = (*env)->FindClass(env, mappings[i].class);
459 
460 		jboolean isInstance = (*env)->CallBooleanMethod(
461 		    env, typeClass, isAssignableFrom, class);
462 
463 		if (isInstance == JNI_TRUE) {
464 			zfs_prop_t prop;
465 			for (prop = 0; prop < ZFS_NPROP_VISIBLE; prop++) {
466 				if (zfs_prop_valid_for_type(prop,
467 				    mappings[i].type)) {
468 					/* Add name of property to list */
469 					jstring propName =
470 					    (*env)->NewStringUTF(env,
471 						zfs_prop_to_name(prop));
472 					(*env)->CallBooleanMethod(
473 					    env,
474 					    ((zjni_Object_t *)list)->object,
475 					    ((zjni_Collection_t *)list)->
476 					    method_add, propName);
477 				}
478 			}
479 			break;
480 		}
481 	}
482 
483 	return (zjni_Collection_to_array(
484 	    env, (zjni_Collection_t *)list, "java/lang/String"));
485 }
486