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