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 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 nvlist_t *vdev_cfg = zjni_get_vdev(zhp, NULL, index); 343 if (vdev_cfg != NULL) { 344 vdev = zjni_get_VirtualDevice_from_vdev(env, 345 zhp, vdev_cfg); 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(pool); 372 (*env)->ReleaseStringUTFChars(env, poolUTF, pool); 373 374 /* Is the pool valid? */ 375 if (zhp != NULL) { 376 nvlist_t *vdev_cfg = zjni_get_vdev(zhp, NULL, index); 377 if (vdev_cfg != NULL) { 378 vdevs = zjni_get_VirtualDevices_from_vdev( 379 env, zhp, vdev_cfg); 380 } 381 zpool_close(zhp); 382 } 383 } 384 385 return (vdevs); 386 } 387 388 /* 389 * Class: com_sun_zfs_common_model_SystemDataModel 390 * Method: getVirtualDevices 391 * Signature: (Ljava/lang/String;) 392 * [Lcom/sun/zfs/common/model/VirtualDevice; 393 */ 394 /* ARGSUSED */ 395 JNIEXPORT jobjectArray JNICALL 396 /* CSTYLED */ 397 Java_com_sun_zfs_common_model_SystemDataModel_getVirtualDevices__Ljava_lang_String_2( 398 JNIEnv *env, jobject obj, jstring poolUTF) 399 { 400 jobjectArray vdevs = NULL; 401 402 if (poolUTF != NULL) { 403 const char *pool = (*env)->GetStringUTFChars(env, 404 poolUTF, NULL); 405 zpool_handle_t *zhp = zpool_open(pool); 406 (*env)->ReleaseStringUTFChars(env, poolUTF, pool); 407 408 /* Is the pool valid? */ 409 if (zhp != NULL) { 410 vdevs = zjni_get_VirtualDevices_from_vdev(env, 411 zhp, NULL); 412 zpool_close(zhp); 413 } 414 } 415 416 return (vdevs); 417 } 418 419 /* 420 * Class: com_sun_zfs_common_model_SystemDataModel 421 * Method: getAvailableDisks 422 * Signature: ()[Lcom/sun/zfs/common/model/DiskDevice; 423 */ 424 /* ARGSUSED */ 425 JNIEXPORT jobjectArray JNICALL 426 Java_com_sun_zfs_common_model_SystemDataModel_getAvailableDisks(JNIEnv *env, 427 jobject obj) 428 { 429 int error; 430 zjni_ArrayCallbackData_t data = {0}; 431 jobjectArray array = NULL; 432 433 /* Create an array list */ 434 zjni_ArrayList_t list_obj = {0}; 435 zjni_ArrayList_t *list = &list_obj; 436 zjni_new_ArrayList(env, list); 437 438 data.env = env; 439 data.list = (zjni_Collection_t *)list; 440 error = dmgt_avail_disk_iter(zjni_create_add_DiskDevice, &data); 441 442 if (error) { 443 zjni_throw_exception(env, "%s", libzfs_err); 444 } else { 445 array = zjni_Collection_to_array( 446 env, (zjni_Collection_t *)list, 447 ZFSJNI_PACKAGE_DATA "DiskDevice"); 448 } 449 450 return (array); 451 } 452 453 /* 454 * Class: com_sun_zfs_common_model_SystemDataModel 455 * Method: getDependents 456 * Signature: ([Ljava/lang/String;) 457 * [Lcom/sun/zfs/common/model/Dataset; 458 */ 459 /* ARGSUSED */ 460 JNIEXPORT jobjectArray JNICALL 461 Java_com_sun_zfs_common_model_SystemDataModel_getDependents(JNIEnv *env, 462 jobject obj, jobjectArray paths) 463 { 464 return (zjni_get_Datasets_dependents(env, paths)); 465 } 466 467 /* 468 * Class: com_sun_zfs_common_model_SystemDataModel 469 * Method: getPropertyDefault 470 * Signature: (Ljava/lang/String;) 471 * Lcom/sun/zfs/common/model/Property; 472 */ 473 /* ARGSUSED */ 474 JNIEXPORT jobject JNICALL 475 Java_com_sun_zfs_common_model_SystemDataModel_getPropertyDefault(JNIEnv *env, 476 jobject obj, jstring nameUTF) 477 { 478 jobject defProperty = NULL; 479 480 const char *name = (*env)->GetStringUTFChars(env, nameUTF, NULL); 481 zfs_prop_t prop = zjni_get_property_from_name(name); 482 (*env)->ReleaseStringUTFChars(env, nameUTF, name); 483 484 if (prop != ZFS_PROP_INVAL) { 485 defProperty = zjni_get_default_property(env, prop); 486 } 487 488 return (defProperty); 489 } 490 491 typedef struct zjni_class_type_map { 492 char *class; 493 zfs_type_t type; 494 } zjni_class_type_map_t; 495 496 /* 497 * Class: com_sun_zfs_common_model_SystemDataModel 498 * Method: getValidPropertyNames 499 * Signature: (Ljava/lang/Class;) 500 * [Ljava/lang/String; 501 */ 502 /* ARGSUSED */ 503 JNIEXPORT jobjectArray JNICALL 504 Java_com_sun_zfs_common_model_SystemDataModel_getValidPropertyNames(JNIEnv *env, 505 jobject obj, jclass class) 506 { 507 int i; 508 509 /* Mappings of class names to zfs_type_t */ 510 static zjni_class_type_map_t mappings[] = { 511 { ZFSJNI_PACKAGE_DATA "FileSystem", ZFS_TYPE_FILESYSTEM }, 512 { ZFSJNI_PACKAGE_DATA "Volume", ZFS_TYPE_VOLUME }, 513 { ZFSJNI_PACKAGE_DATA "Snapshot", ZFS_TYPE_SNAPSHOT }, 514 }; 515 int nmappings = sizeof (mappings) / sizeof (zjni_class_type_map_t); 516 517 jclass class_Class = (*env)->FindClass(env, "java/lang/Class"); 518 519 jmethodID isAssignableFrom = (*env)->GetMethodID( 520 env, class_Class, "isAssignableFrom", "(Ljava/lang/Class;)Z"); 521 522 /* Create an array list for the property names */ 523 zjni_ArrayList_t list_obj = {0}; 524 zjni_ArrayList_t *list = &list_obj; 525 zjni_new_ArrayList(env, list); 526 527 /* For each mapping... */ 528 for (i = 0; i < nmappings; i++) { 529 /* 530 * Is the given class an instance of the class in the mapping? 531 */ 532 jclass typeClass = (*env)->FindClass(env, mappings[i].class); 533 534 jboolean isInstance = (*env)->CallBooleanMethod( 535 env, typeClass, isAssignableFrom, class); 536 537 if (isInstance == JNI_TRUE) { 538 zfs_prop_t prop; 539 for (prop = 0; prop < ZFS_NPROP_VISIBLE; prop++) { 540 if (zfs_prop_valid_for_type(prop, 541 mappings[i].type)) { 542 /* Add name of property to list */ 543 jstring propName = 544 (*env)->NewStringUTF(env, 545 zfs_prop_to_name(prop)); 546 (*env)->CallBooleanMethod( 547 env, 548 ((zjni_Object_t *)list)->object, 549 ((zjni_Collection_t *)list)-> 550 method_add, propName); 551 } 552 } 553 break; 554 } 555 } 556 557 return (zjni_Collection_to_array( 558 env, (zjni_Collection_t *)list, "java/lang/String")); 559 } 560