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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 */ 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 */ 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 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 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 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 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)) { 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 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 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