xref: /illumos-gate/usr/src/lib/libzfs_jni/common/libzfs_jni_main.c (revision c8343062f6e25afd9c2a31b65df357030e69fa55)
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 	return (zjni_get_Dataset(env, poolUTF, ZFS_TYPE_FILESYSTEM));
177 }
178 
179 /*
180  * Class:     com_sun_zfs_common_model_SystemDataModel
181  * Method:    getFileSystems
182  * Signature: (Ljava/lang/String;)
183  *            [Lcom/sun/zfs/common/model/FileSystem;
184  */
185 /* ARGSUSED */
186 JNIEXPORT jobjectArray JNICALL
187 Java_com_sun_zfs_common_model_SystemDataModel_getFileSystems(JNIEnv *env,
188     jobject obj, jstring containerUTF)
189 {
190 	return (zjni_get_Datasets_below(env, containerUTF,
191 	    ZFS_TYPE_FILESYSTEM, ZFS_TYPE_FILESYSTEM,
192 	    ZFSJNI_PACKAGE_DATA "FileSystem"));
193 }
194 
195 /*
196  * Class:     com_sun_zfs_common_model_SystemDataModel
197  * Method:    getFileSystem
198  * Signature: (Ljava/lang/String;)
199  *            Lcom/sun/zfs/common/model/FileSystem;
200  */
201 /* ARGSUSED */
202 JNIEXPORT jobject JNICALL
203 Java_com_sun_zfs_common_model_SystemDataModel_getFileSystem(JNIEnv *env,
204     jobject obj, jstring nameUTF)
205 {
206 	return (zjni_get_Dataset(env, nameUTF, ZFS_TYPE_FILESYSTEM));
207 }
208 
209 /*
210  * Class:     com_sun_zfs_common_model_SystemDataModel
211  * Method:    getVolumes
212  * Signature: (Ljava/lang/String;)
213  *            [Lcom/sun/zfs/common/model/Volume;
214  */
215 /* ARGSUSED */
216 JNIEXPORT jobjectArray JNICALL
217 Java_com_sun_zfs_common_model_SystemDataModel_getVolumes(JNIEnv *env,
218     jobject obj, jstring containerUTF)
219 {
220 	return (zjni_get_Datasets_below(env, containerUTF,
221 	    ZFS_TYPE_FILESYSTEM, ZFS_TYPE_VOLUME,
222 	    ZFSJNI_PACKAGE_DATA "Volume"));
223 }
224 
225 /*
226  * Class:     com_sun_zfs_common_model_SystemDataModel
227  * Method:    getVolume
228  * Signature: (Ljava/lang/String;)
229  *            Lcom/sun/zfs/common/model/Volume;
230  */
231 /* ARGSUSED */
232 JNIEXPORT jobject JNICALL
233 Java_com_sun_zfs_common_model_SystemDataModel_getVolume(JNIEnv *env,
234     jobject obj, jstring nameUTF)
235 {
236 	return (zjni_get_Dataset(env, nameUTF, ZFS_TYPE_VOLUME));
237 }
238 
239 /*
240  * Class:     com_sun_zfs_common_model_SystemDataModel
241  * Method:    getSnapshots
242  * Signature: (Ljava/lang/String;)
243  *            [Lcom/sun/zfs/common/model/Snapshot;
244  */
245 /* ARGSUSED */
246 JNIEXPORT jobjectArray JNICALL
247 Java_com_sun_zfs_common_model_SystemDataModel_getSnapshots(JNIEnv *env,
248     jobject obj, jstring datasetUTF)
249 {
250 	return (zjni_get_Datasets_below(env, datasetUTF,
251 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, ZFS_TYPE_SNAPSHOT,
252 	    ZFSJNI_PACKAGE_DATA "Snapshot"));
253 }
254 
255 /*
256  * Class:     com_sun_zfs_common_model_SystemDataModel
257  * Method:    getSnapshot
258  * Signature: (Ljava/lang/String;)
259  *            Lcom/sun/zfs/common/model/Snapshot;
260  */
261 /* ARGSUSED */
262 JNIEXPORT jobject JNICALL
263 Java_com_sun_zfs_common_model_SystemDataModel_getSnapshot(JNIEnv *env,
264     jobject obj, jstring nameUTF)
265 {
266 	return (zjni_get_Dataset(env, nameUTF, ZFS_TYPE_SNAPSHOT));
267 }
268 
269 /*
270  * Class:     com_sun_zfs_common_model_SystemDataModel
271  * Method:    getDatasets
272  * Signature: (Ljava/lang/String;)
273  *            [Lcom/sun/zfs/common/model/Dataset;
274  */
275 /* ARGSUSED */
276 JNIEXPORT jobjectArray JNICALL
277 Java_com_sun_zfs_common_model_SystemDataModel_getDatasets(JNIEnv *env,
278     jobject obj, jstring containerUTF)
279 {
280 	if (containerUTF == NULL) {
281 		return (Java_com_sun_zfs_common_model_SystemDataModel_getPools(
282 		    env, obj));
283 	}
284 
285 	return (zjni_get_Datasets_below(env, containerUTF,
286 	    ZFS_TYPE_FILESYSTEM, ZFS_TYPE_ANY,
287 	    ZFSJNI_PACKAGE_DATA "Dataset"));
288 }
289 
290 /*
291  * Class:     com_sun_zfs_common_model_SystemDataModel
292  * Method:    getDataset
293  * Signature: (Ljava/lang/String;)
294  *            Lcom/sun/zfs/common/model/Dataset;
295  */
296 /* ARGSUSED */
297 JNIEXPORT jobject JNICALL
298 Java_com_sun_zfs_common_model_SystemDataModel_getDataset(JNIEnv *env,
299     jobject obj, jstring nameUTF)
300 {
301 	return (zjni_get_Dataset(env, nameUTF, ZFS_TYPE_ANY));
302 }
303 
304 /*
305  * Class:     com_sun_zfs_common_model_SystemDataModel
306  * Method:    getVirtualDevice
307  * Signature: (Ljava/lang/String;J)Lcom/sun/zfs/common/model/VirtualDevice;
308  */
309 /* ARGSUSED */
310 JNIEXPORT jobject JNICALL
311 Java_com_sun_zfs_common_model_SystemDataModel_getVirtualDevice(JNIEnv *env,
312     jobject obj, jstring poolUTF, jlong index)
313 {
314 	jobject vdev = NULL;
315 
316 	if (poolUTF != NULL) {
317 		const char *pool = (*env)->GetStringUTFChars(env, poolUTF,
318 		    NULL);
319 		zpool_handle_t *zhp = zpool_open(pool);
320 		(*env)->ReleaseStringUTFChars(env, poolUTF, pool);
321 
322 		if (zhp != NULL) {
323 			nvlist_t *vdev_cfg = zjni_get_vdev(zhp, NULL, index);
324 			if (vdev_cfg != NULL) {
325 				vdev = zjni_get_VirtualDevice_from_vdev(env,
326 				    zhp, vdev_cfg);
327 			}
328 			zpool_close(zhp);
329 		}
330 	}
331 
332 	return (vdev);
333 }
334 
335 /*
336  * Class:     com_sun_zfs_common_model_SystemDataModel
337  * Method:    getVirtualDevices
338  * Signature: (Ljava/lang/String;J)
339  *            [Lcom/sun/zfs/common/model/VirtualDevice;
340  */
341 /* ARGSUSED */
342 JNIEXPORT jobjectArray JNICALL
343 /* CSTYLED */
344 Java_com_sun_zfs_common_model_SystemDataModel_getVirtualDevices__Ljava_lang_String_2J(
345     JNIEnv *env, jobject obj, jstring poolUTF, jlong index)
346 {
347 	jobjectArray vdevs = NULL;
348 
349 	if (poolUTF != NULL) {
350 		const char *pool = (*env)->GetStringUTFChars(env, poolUTF,
351 		    NULL);
352 		zpool_handle_t *zhp = zpool_open(pool);
353 		(*env)->ReleaseStringUTFChars(env, poolUTF, pool);
354 
355 		/* Is the pool valid? */
356 		if (zhp != NULL) {
357 			nvlist_t *vdev_cfg = zjni_get_vdev(zhp, NULL, index);
358 			if (vdev_cfg != NULL) {
359 				vdevs = zjni_get_VirtualDevices_from_vdev(
360 				    env, zhp, vdev_cfg);
361 			}
362 			zpool_close(zhp);
363 		}
364 	}
365 
366 	return (vdevs);
367 }
368 
369 /*
370  * Class:     com_sun_zfs_common_model_SystemDataModel
371  * Method:    getVirtualDevices
372  * Signature: (Ljava/lang/String;)
373  *            [Lcom/sun/zfs/common/model/VirtualDevice;
374  */
375 /* ARGSUSED */
376 JNIEXPORT jobjectArray JNICALL
377 /* CSTYLED */
378 Java_com_sun_zfs_common_model_SystemDataModel_getVirtualDevices__Ljava_lang_String_2(
379     JNIEnv *env, jobject obj, jstring poolUTF)
380 {
381 	jobjectArray vdevs = NULL;
382 
383 	if (poolUTF != NULL) {
384 		const char *pool = (*env)->GetStringUTFChars(env,
385 		    poolUTF, NULL);
386 		zpool_handle_t *zhp = zpool_open(pool);
387 		(*env)->ReleaseStringUTFChars(env, poolUTF, pool);
388 
389 		/* Is the pool valid? */
390 		if (zhp != NULL) {
391 			vdevs = zjni_get_VirtualDevices_from_vdev(env,
392 			    zhp, NULL);
393 			zpool_close(zhp);
394 		}
395 	}
396 
397 	return (vdevs);
398 }
399 
400 /*
401  * Class:     com_sun_zfs_common_model_SystemDataModel
402  * Method:    getAvailableDisks
403  * Signature: ()[Lcom/sun/zfs/common/model/DiskDevice;
404  */
405 /* ARGSUSED */
406 JNIEXPORT jobjectArray JNICALL
407 Java_com_sun_zfs_common_model_SystemDataModel_getAvailableDisks(JNIEnv *env,
408     jobject obj)
409 {
410 	int error;
411 	zjni_ArrayCallbackData_t data = {0};
412 	jobjectArray array = NULL;
413 
414 	/* Create an array list */
415 	zjni_ArrayList_t list_obj = {0};
416 	zjni_ArrayList_t *list = &list_obj;
417 	zjni_new_ArrayList(env, list);
418 
419 	data.env = env;
420 	data.list = (zjni_Collection_t *)list;
421 	error = dmgt_avail_disk_iter(zjni_create_add_DiskDevice, &data);
422 
423 	if (error) {
424 		zjni_throw_exception(env, "%s", libzfs_err);
425 	} else {
426 		array = zjni_Collection_to_array(
427 		    env, (zjni_Collection_t *)list,
428 		    ZFSJNI_PACKAGE_DATA "DiskDevice");
429 	}
430 
431 	return (array);
432 }
433 
434 /*
435  * Class:     com_sun_zfs_common_model_SystemDataModel
436  * Method:    getDependents
437  * Signature: ([Ljava/lang/String;)
438  *            [Lcom/sun/zfs/common/model/Dataset;
439  */
440 /* ARGSUSED */
441 JNIEXPORT jobjectArray JNICALL
442 Java_com_sun_zfs_common_model_SystemDataModel_getDependents(JNIEnv *env,
443     jobject obj, jobjectArray paths)
444 {
445 	return (zjni_get_Datasets_dependents(env, paths));
446 }
447 
448 /*
449  * Class:     com_sun_zfs_common_model_SystemDataModel
450  * Method:    getPropertyDefault
451  * Signature: (Ljava/lang/String;)
452  *            Lcom/sun/zfs/common/model/Property;
453  */
454 /* ARGSUSED */
455 JNIEXPORT jobject JNICALL
456 Java_com_sun_zfs_common_model_SystemDataModel_getPropertyDefault(JNIEnv *env,
457     jobject obj, jstring nameUTF)
458 {
459 	jobject defProperty = NULL;
460 
461 	const char *name = (*env)->GetStringUTFChars(env, nameUTF, NULL);
462 	zfs_prop_t prop = zjni_get_property_from_name(name);
463 	(*env)->ReleaseStringUTFChars(env, nameUTF, name);
464 
465 	if (prop != ZFS_PROP_INVAL) {
466 		defProperty = zjni_get_default_property(env, prop);
467 	}
468 
469 	return (defProperty);
470 }
471 
472 typedef struct zjni_class_type_map {
473 	char *class;
474 	zfs_type_t type;
475 } zjni_class_type_map_t;
476 
477 /*
478  * Class:     com_sun_zfs_common_model_SystemDataModel
479  * Method:    getValidPropertyNames
480  * Signature: (Ljava/lang/Class;)
481  *            [Ljava/lang/String;
482  */
483 /* ARGSUSED */
484 JNIEXPORT jobjectArray JNICALL
485 Java_com_sun_zfs_common_model_SystemDataModel_getValidPropertyNames(JNIEnv *env,
486     jobject obj, jclass class)
487 {
488 	int i;
489 
490 	/* Mappings of class names to zfs_type_t */
491 	static zjni_class_type_map_t mappings[] = {
492 		{ ZFSJNI_PACKAGE_DATA "FileSystem", ZFS_TYPE_FILESYSTEM },
493 		{ ZFSJNI_PACKAGE_DATA "Volume", ZFS_TYPE_VOLUME },
494 		{ ZFSJNI_PACKAGE_DATA "Snapshot", ZFS_TYPE_SNAPSHOT },
495 	};
496 	int nmappings = sizeof (mappings) / sizeof (zjni_class_type_map_t);
497 
498 	jclass class_Class = (*env)->FindClass(env, "java/lang/Class");
499 
500 	jmethodID isAssignableFrom = (*env)->GetMethodID(
501 	    env, class_Class, "isAssignableFrom", "(Ljava/lang/Class;)Z");
502 
503 	/* Create an array list for the property names */
504 	zjni_ArrayList_t list_obj = {0};
505 	zjni_ArrayList_t *list = &list_obj;
506 	zjni_new_ArrayList(env, list);
507 
508 	/* For each mapping... */
509 	for (i = 0; i < nmappings; i++) {
510 		/*
511 		 * Is the given class an instance of the class in the mapping?
512 		 */
513 		jclass typeClass = (*env)->FindClass(env, mappings[i].class);
514 
515 		jboolean isInstance = (*env)->CallBooleanMethod(
516 		    env, typeClass, isAssignableFrom, class);
517 
518 		if (isInstance == JNI_TRUE) {
519 			zfs_prop_t prop;
520 			for (prop = 0; prop < ZFS_NPROP_VISIBLE; prop++) {
521 				if (zfs_prop_valid_for_type(prop,
522 				    mappings[i].type)) {
523 					/* Add name of property to list */
524 					jstring propName =
525 					    (*env)->NewStringUTF(env,
526 						zfs_prop_to_name(prop));
527 					(*env)->CallBooleanMethod(
528 					    env,
529 					    ((zjni_Object_t *)list)->object,
530 					    ((zjni_Collection_t *)list)->
531 					    method_add, propName);
532 				}
533 			}
534 			break;
535 		}
536 	}
537 
538 	return (zjni_Collection_to_array(
539 	    env, (zjni_Collection_t *)list, "java/lang/String"));
540 }
541