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