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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 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_ANY, 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(pool); 338 (*env)->ReleaseStringUTFChars(env, poolUTF, pool); 339 340 if (zhp != NULL) { 341 nvlist_t *vdev_cfg = zjni_get_vdev(zhp, NULL, index); 342 if (vdev_cfg != NULL) { 343 vdev = zjni_get_VirtualDevice_from_vdev(env, 344 zhp, vdev_cfg); 345 } 346 zpool_close(zhp); 347 } 348 } 349 350 return (vdev); 351 } 352 353 /* 354 * Class: com_sun_zfs_common_model_SystemDataModel 355 * Method: getVirtualDevices 356 * Signature: (Ljava/lang/String;J) 357 * [Lcom/sun/zfs/common/model/VirtualDevice; 358 */ 359 /* ARGSUSED */ 360 JNIEXPORT jobjectArray JNICALL 361 /* CSTYLED */ 362 Java_com_sun_zfs_common_model_SystemDataModel_getVirtualDevices__Ljava_lang_String_2J( 363 JNIEnv *env, jobject obj, jstring poolUTF, jlong index) 364 { 365 jobjectArray vdevs = NULL; 366 367 if (poolUTF != NULL) { 368 const char *pool = (*env)->GetStringUTFChars(env, poolUTF, 369 NULL); 370 zpool_handle_t *zhp = zpool_open(pool); 371 (*env)->ReleaseStringUTFChars(env, poolUTF, pool); 372 373 /* Is the pool valid? */ 374 if (zhp != NULL) { 375 nvlist_t *vdev_cfg = zjni_get_vdev(zhp, NULL, index); 376 if (vdev_cfg != NULL) { 377 vdevs = zjni_get_VirtualDevices_from_vdev( 378 env, zhp, vdev_cfg); 379 } 380 zpool_close(zhp); 381 } 382 } 383 384 return (vdevs); 385 } 386 387 /* 388 * Class: com_sun_zfs_common_model_SystemDataModel 389 * Method: getVirtualDevices 390 * Signature: (Ljava/lang/String;) 391 * [Lcom/sun/zfs/common/model/VirtualDevice; 392 */ 393 /* ARGSUSED */ 394 JNIEXPORT jobjectArray JNICALL 395 /* CSTYLED */ 396 Java_com_sun_zfs_common_model_SystemDataModel_getVirtualDevices__Ljava_lang_String_2( 397 JNIEnv *env, jobject obj, jstring poolUTF) 398 { 399 jobjectArray vdevs = NULL; 400 401 if (poolUTF != NULL) { 402 const char *pool = (*env)->GetStringUTFChars(env, 403 poolUTF, NULL); 404 zpool_handle_t *zhp = zpool_open(pool); 405 (*env)->ReleaseStringUTFChars(env, poolUTF, pool); 406 407 /* Is the pool valid? */ 408 if (zhp != NULL) { 409 vdevs = zjni_get_VirtualDevices_from_vdev(env, 410 zhp, NULL); 411 zpool_close(zhp); 412 } 413 } 414 415 return (vdevs); 416 } 417 418 /* 419 * Class: com_sun_zfs_common_model_SystemDataModel 420 * Method: getAvailableDisks 421 * Signature: ()[Lcom/sun/zfs/common/model/DiskDevice; 422 */ 423 /* ARGSUSED */ 424 JNIEXPORT jobjectArray JNICALL 425 Java_com_sun_zfs_common_model_SystemDataModel_getAvailableDisks(JNIEnv *env, 426 jobject obj) 427 { 428 int error; 429 zjni_ArrayCallbackData_t data = {0}; 430 jobjectArray array = NULL; 431 432 /* Create an array list */ 433 zjni_ArrayList_t list_obj = {0}; 434 zjni_ArrayList_t *list = &list_obj; 435 zjni_new_ArrayList(env, list); 436 437 data.env = env; 438 data.list = (zjni_Collection_t *)list; 439 error = dmgt_avail_disk_iter(zjni_create_add_DiskDevice, &data); 440 441 if (error) { 442 zjni_throw_exception(env, "%s", libzfs_err); 443 } else { 444 array = zjni_Collection_to_array( 445 env, (zjni_Collection_t *)list, 446 ZFSJNI_PACKAGE_DATA "DiskDevice"); 447 } 448 449 return (array); 450 } 451 452 /* 453 * Class: com_sun_zfs_common_model_SystemDataModel 454 * Method: getDependents 455 * Signature: ([Ljava/lang/String;) 456 * [Lcom/sun/zfs/common/model/Dataset; 457 */ 458 /* ARGSUSED */ 459 JNIEXPORT jobjectArray JNICALL 460 Java_com_sun_zfs_common_model_SystemDataModel_getDependents(JNIEnv *env, 461 jobject obj, jobjectArray paths) 462 { 463 return (zjni_get_Datasets_dependents(env, paths)); 464 } 465 466 /* 467 * Class: com_sun_zfs_common_model_SystemDataModel 468 * Method: getPropertyDefault 469 * Signature: (Ljava/lang/String;) 470 * Lcom/sun/zfs/common/model/Property; 471 */ 472 /* ARGSUSED */ 473 JNIEXPORT jobject JNICALL 474 Java_com_sun_zfs_common_model_SystemDataModel_getPropertyDefault(JNIEnv *env, 475 jobject obj, jstring nameUTF) 476 { 477 jobject defProperty = NULL; 478 479 const char *name = (*env)->GetStringUTFChars(env, nameUTF, NULL); 480 zfs_prop_t prop = zjni_get_property_from_name(name); 481 (*env)->ReleaseStringUTFChars(env, nameUTF, name); 482 483 if (prop != ZFS_PROP_INVAL) { 484 defProperty = zjni_get_default_property(env, prop); 485 } 486 487 return (defProperty); 488 } 489 490 typedef struct zjni_class_type_map { 491 char *class; 492 zfs_type_t type; 493 } zjni_class_type_map_t; 494 495 /* 496 * Class: com_sun_zfs_common_model_SystemDataModel 497 * Method: getValidPropertyNames 498 * Signature: (Ljava/lang/Class;) 499 * [Ljava/lang/String; 500 */ 501 /* ARGSUSED */ 502 JNIEXPORT jobjectArray JNICALL 503 Java_com_sun_zfs_common_model_SystemDataModel_getValidPropertyNames(JNIEnv *env, 504 jobject obj, jclass class) 505 { 506 int i; 507 508 /* Mappings of class names to zfs_type_t */ 509 static zjni_class_type_map_t mappings[] = { 510 { ZFSJNI_PACKAGE_DATA "FileSystem", ZFS_TYPE_FILESYSTEM }, 511 { ZFSJNI_PACKAGE_DATA "Volume", ZFS_TYPE_VOLUME }, 512 { ZFSJNI_PACKAGE_DATA "Snapshot", ZFS_TYPE_SNAPSHOT }, 513 }; 514 int nmappings = sizeof (mappings) / sizeof (zjni_class_type_map_t); 515 516 jclass class_Class = (*env)->FindClass(env, "java/lang/Class"); 517 518 jmethodID isAssignableFrom = (*env)->GetMethodID( 519 env, class_Class, "isAssignableFrom", "(Ljava/lang/Class;)Z"); 520 521 /* Create an array list for the property names */ 522 zjni_ArrayList_t list_obj = {0}; 523 zjni_ArrayList_t *list = &list_obj; 524 zjni_new_ArrayList(env, list); 525 526 /* For each mapping... */ 527 for (i = 0; i < nmappings; i++) { 528 /* 529 * Is the given class an instance of the class in the mapping? 530 */ 531 jclass typeClass = (*env)->FindClass(env, mappings[i].class); 532 533 jboolean isInstance = (*env)->CallBooleanMethod( 534 env, typeClass, isAssignableFrom, class); 535 536 if (isInstance == JNI_TRUE) { 537 zfs_prop_t prop; 538 for (prop = 0; prop < ZFS_NPROP_VISIBLE; prop++) { 539 if (zfs_prop_valid_for_type(prop, 540 mappings[i].type)) { 541 /* Add name of property to list */ 542 jstring propName = 543 (*env)->NewStringUTF(env, 544 zfs_prop_to_name(prop)); 545 (*env)->CallBooleanMethod( 546 env, 547 ((zjni_Object_t *)list)->object, 548 ((zjni_Collection_t *)list)-> 549 method_add, propName); 550 } 551 } 552 break; 553 } 554 } 555 556 return (zjni_Collection_to_array( 557 env, (zjni_Collection_t *)list, "java/lang/String")); 558 } 559