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 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 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 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_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 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 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 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 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 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 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 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 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 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 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 */ 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 */ 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 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 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 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 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 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 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