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