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