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