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 "libzfs_jni_util.h" 30 #include "libzfs_jni_dataset.h" 31 #include "libzfs_jni_property.h" 32 #include "libzfs_jni_pool.h" 33 #include <strings.h> 34 35 #define REGEX_ZFS_NAME "^((([^/]*)(/.+)?)[/@])?([^/]+)/*" 36 #define REGEX_ZFS_NAME_NGROUPS 6 37 #define REGEX_ZFS_NAME_POOL_GROUP 3 38 #define REGEX_ZFS_NAME_PARENT_GROUP 2 39 #define REGEX_ZFS_NAME_BASE_GROUP 5 40 41 /* 42 * Types 43 */ 44 45 typedef struct DatasetBean { 46 zjni_Object_t super; 47 48 jmethodID method_setPoolName; 49 jmethodID method_setParentName; 50 jmethodID method_setBaseName; 51 jmethodID method_setProperties; 52 jmethodID method_addProperty; 53 } DatasetBean_t; 54 55 typedef struct FileSystemBean { 56 DatasetBean_t super; 57 } FileSystemBean_t; 58 59 typedef struct PoolBean { 60 FileSystemBean_t super; 61 PoolStatsBean_t interface_PoolStats; 62 } PoolBean_t; 63 64 typedef struct VolumeBean { 65 DatasetBean_t super; 66 } VolumeBean_t; 67 68 typedef struct SnapshotBean { 69 DatasetBean_t super; 70 } SnapshotBean_t; 71 72 typedef struct FileSystemSnapshotBean { 73 DatasetBean_t super; 74 } FileSystemSnapshotBean_t; 75 76 typedef struct VolumeSnapshotBean { 77 DatasetBean_t super; 78 } VolumeSnapshotBean_t; 79 80 /* 81 * Function prototypes 82 */ 83 84 static void new_DatasetBean(JNIEnv *, DatasetBean_t *); 85 static void new_PoolBean(JNIEnv *, PoolBean_t *); 86 static void new_FileSystemBean(JNIEnv *, FileSystemBean_t *); 87 static void new_VolumeBean(JNIEnv *, VolumeBean_t *); 88 static void new_SnapshotBean(JNIEnv *, SnapshotBean_t *); 89 static void new_FileSystemSnapshotBean(JNIEnv *, FileSystemSnapshotBean_t *); 90 static void new_VolumeSnapshotBean(JNIEnv *, VolumeSnapshotBean_t *); 91 static int set_name_in_DatasetBean(JNIEnv *, char *, DatasetBean_t *); 92 static int populate_DatasetBean(JNIEnv *, zfs_handle_t *, DatasetBean_t *); 93 static int populate_PoolBean( 94 JNIEnv *, zpool_handle_t *, zfs_handle_t *, PoolBean_t *); 95 static int populate_FileSystemBean( 96 JNIEnv *, zfs_handle_t *, FileSystemBean_t *); 97 static int populate_VolumeBean( 98 JNIEnv *, zfs_handle_t *, VolumeBean_t *); 99 static int populate_SnapshotBean(JNIEnv *, zfs_handle_t *, SnapshotBean_t *); 100 static int populate_FileSystemSnapshotBean( 101 JNIEnv *, zfs_handle_t *, FileSystemSnapshotBean_t *); 102 static int populate_VolumeSnapshotBean( 103 JNIEnv *, zfs_handle_t *, VolumeSnapshotBean_t *); 104 static jobject create_PoolBean(JNIEnv *, zpool_handle_t *, zfs_handle_t *); 105 static jobject create_FileSystemBean(JNIEnv *, zfs_handle_t *); 106 static jobject create_VolumeBean(JNIEnv *, zfs_handle_t *); 107 static jobject create_FileSystemSnapshotBean(JNIEnv *, zfs_handle_t *); 108 static jobject create_VolumeSnapshotBean(JNIEnv *, zfs_handle_t *); 109 static jobject create_DatasetBean(JNIEnv *, zfs_handle_t *); 110 static int is_fs_snapshot(zfs_handle_t *); 111 static int is_pool_name(const char *); 112 113 /* 114 * Static functions 115 */ 116 117 /* Create a DatasetBean */ 118 static void 119 new_DatasetBean(JNIEnv *env, DatasetBean_t *bean) 120 { 121 zjni_Object_t *object = (zjni_Object_t *)bean; 122 123 if (object->object == NULL) { 124 object->class = 125 (*env)->FindClass(env, ZFSJNI_PACKAGE_DATA "DatasetBean"); 126 127 object->constructor = 128 (*env)->GetMethodID(env, object->class, "<init>", "()V"); 129 130 object->object = 131 (*env)->NewObject(env, object->class, object->constructor); 132 } 133 134 bean->method_setPoolName = (*env)->GetMethodID( 135 env, object->class, "setPoolName", "(Ljava/lang/String;)V"); 136 137 bean->method_setParentName = (*env)->GetMethodID( 138 env, object->class, "setParentName", "(Ljava/lang/String;)V"); 139 140 bean->method_setBaseName = (*env)->GetMethodID( 141 env, object->class, "setBaseName", "(Ljava/lang/String;)V"); 142 143 bean->method_setProperties = (*env)->GetMethodID( 144 env, object->class, "setProperties", 145 "([L" ZFSJNI_PACKAGE_DATA "Property;)V"); 146 147 bean->method_addProperty = (*env)->GetMethodID( 148 env, object->class, "addProperty", 149 "(L" ZFSJNI_PACKAGE_DATA "Property;)V"); 150 } 151 152 /* Create a PoolBean */ 153 static void 154 new_PoolBean(JNIEnv *env, PoolBean_t *bean) 155 { 156 zjni_Object_t *object = (zjni_Object_t *)bean; 157 158 if (object->object == NULL) { 159 160 object->class = 161 (*env)->FindClass(env, ZFSJNI_PACKAGE_DATA "PoolBean"); 162 163 object->constructor = 164 (*env)->GetMethodID(env, object->class, "<init>", "()V"); 165 166 object->object = 167 (*env)->NewObject(env, object->class, object->constructor); 168 } 169 170 new_FileSystemBean(env, (FileSystemBean_t *)bean); 171 new_PoolStats(env, &(bean->interface_PoolStats), object); 172 } 173 174 /* Create a FileSystemBean */ 175 static void 176 new_FileSystemBean(JNIEnv *env, FileSystemBean_t *bean) 177 { 178 zjni_Object_t *object = (zjni_Object_t *)bean; 179 180 if (object->object == NULL) { 181 object->class = 182 (*env)->FindClass(env, 183 ZFSJNI_PACKAGE_DATA "FileSystemBean"); 184 185 object->constructor = 186 (*env)->GetMethodID(env, object->class, "<init>", "()V"); 187 188 object->object = 189 (*env)->NewObject(env, object->class, object->constructor); 190 } 191 192 new_DatasetBean(env, (DatasetBean_t *)bean); 193 } 194 195 /* Create a VolumeBean */ 196 static void 197 new_VolumeBean(JNIEnv *env, VolumeBean_t *bean) 198 { 199 zjni_Object_t *object = (zjni_Object_t *)bean; 200 201 if (object->object == NULL) { 202 object->class = 203 (*env)->FindClass(env, 204 ZFSJNI_PACKAGE_DATA "VolumeBean"); 205 206 object->constructor = 207 (*env)->GetMethodID(env, object->class, "<init>", "()V"); 208 209 object->object = 210 (*env)->NewObject(env, object->class, object->constructor); 211 } 212 213 new_DatasetBean(env, (DatasetBean_t *)bean); 214 } 215 216 /* Create a SnapshotBean */ 217 static void 218 new_SnapshotBean(JNIEnv *env, SnapshotBean_t *bean) 219 { 220 zjni_Object_t *object = (zjni_Object_t *)bean; 221 222 if (object->object == NULL) { 223 object->class = 224 (*env)->FindClass(env, 225 ZFSJNI_PACKAGE_DATA "SnapshotBean"); 226 227 object->constructor = 228 (*env)->GetMethodID(env, object->class, "<init>", "()V"); 229 230 object->object = 231 (*env)->NewObject(env, object->class, object->constructor); 232 } 233 234 new_DatasetBean(env, (DatasetBean_t *)bean); 235 } 236 237 /* Create a FileSystemSnapshotBean */ 238 static void 239 new_FileSystemSnapshotBean(JNIEnv *env, FileSystemSnapshotBean_t *bean) 240 { 241 zjni_Object_t *object = (zjni_Object_t *)bean; 242 243 if (object->object == NULL) { 244 object->class = 245 (*env)->FindClass(env, 246 ZFSJNI_PACKAGE_DATA "FileSystemSnapshotBean"); 247 248 object->constructor = 249 (*env)->GetMethodID(env, object->class, "<init>", "()V"); 250 251 object->object = 252 (*env)->NewObject(env, object->class, object->constructor); 253 } 254 255 new_SnapshotBean(env, (SnapshotBean_t *)bean); 256 } 257 258 /* Create a VolumeSnapshotBean */ 259 static void 260 new_VolumeSnapshotBean(JNIEnv *env, VolumeSnapshotBean_t *bean) 261 { 262 zjni_Object_t *object = (zjni_Object_t *)bean; 263 264 if (object->object == NULL) { 265 object->class = 266 (*env)->FindClass(env, 267 ZFSJNI_PACKAGE_DATA "VolumeSnapshotBean"); 268 269 object->constructor = 270 (*env)->GetMethodID(env, object->class, "<init>", "()V"); 271 272 object->object = 273 (*env)->NewObject(env, object->class, object->constructor); 274 } 275 276 new_SnapshotBean(env, (SnapshotBean_t *)bean); 277 } 278 279 static int 280 set_name_in_DatasetBean(JNIEnv *env, char *name, DatasetBean_t *bean) 281 { 282 jstring poolUTF; 283 jstring parentUTF; 284 jstring baseUTF; 285 zjni_Object_t *object = (zjni_Object_t *)bean; 286 287 /* 288 * zhp->zfs_name has the format 289 * <pool>[[/<container...>]/<dataset>[@<snapshot>]] 290 */ 291 292 regex_t re; 293 regmatch_t matches[REGEX_ZFS_NAME_NGROUPS]; 294 295 if (regcomp(&re, REGEX_ZFS_NAME, REG_EXTENDED) != 0 || 296 regexec(&re, name, REGEX_ZFS_NAME_NGROUPS, matches, 0) != 0) { 297 regfree(&re); 298 zjni_throw_exception(env, "invalid name: %s", name); 299 return (-1); 300 } 301 302 regfree(&re); 303 304 /* Set names */ 305 poolUTF = zjni_get_matched_string( 306 env, name, matches + REGEX_ZFS_NAME_POOL_GROUP); 307 parentUTF = zjni_get_matched_string( 308 env, name, matches + REGEX_ZFS_NAME_PARENT_GROUP); 309 baseUTF = zjni_get_matched_string( 310 env, name, matches + REGEX_ZFS_NAME_BASE_GROUP); 311 312 if (poolUTF == NULL) { 313 poolUTF = baseUTF; 314 } 315 316 (*env)->CallVoidMethod( 317 env, object->object, bean->method_setPoolName, poolUTF); 318 (*env)->CallVoidMethod( 319 env, object->object, bean->method_setBaseName, baseUTF); 320 321 if (parentUTF != NULL) { 322 (*env)->CallVoidMethod( 323 env, object->object, bean->method_setParentName, parentUTF); 324 } 325 326 return (0); 327 } 328 329 static int 330 populate_DatasetBean(JNIEnv *env, zfs_handle_t *zhp, DatasetBean_t *bean) 331 { 332 jobjectArray properties; 333 zjni_Object_t *object = (zjni_Object_t *)bean; 334 335 int result = set_name_in_DatasetBean( 336 env, (char *)zfs_get_name(zhp), bean); 337 if (result != 0) { 338 /* Must not call any more Java methods to preserve exception */ 339 return (-1); 340 } 341 342 properties = zjni_get_Dataset_properties(env, zhp); 343 if (properties == NULL) { 344 /* Must not call any more Java methods to preserve exception */ 345 return (-1); 346 } 347 348 (*env)->CallVoidMethod( 349 env, object->object, bean->method_setProperties, properties); 350 351 return (0); 352 } 353 354 static int 355 populate_PoolBean(JNIEnv *env, zpool_handle_t *zphp, zfs_handle_t *zhp, 356 PoolBean_t *bean) 357 { 358 int result = 0; 359 zjni_Object_t *object = (zjni_Object_t *)bean; 360 PoolStatsBean_t *pool_stats = &(bean->interface_PoolStats); 361 DeviceStatsBean_t *dev_stats = (DeviceStatsBean_t *)pool_stats; 362 nvlist_t *devices = zjni_get_root_vdev(zphp); 363 364 if (devices == NULL || 365 populate_DeviceStatsBean(env, devices, dev_stats, object)) { 366 result = -1; 367 } else { 368 char *msgid; 369 370 /* Override value set in populate_DeviceStatsBean */ 371 (*env)->CallVoidMethod(env, object->object, 372 dev_stats->method_setSize, 373 zpool_get_space_total(zphp)); 374 375 (*env)->CallVoidMethod(env, object->object, 376 pool_stats->method_setPoolState, 377 zjni_pool_state_to_obj( 378 env, zpool_get_state(zphp))); 379 380 (*env)->CallVoidMethod(env, object->object, 381 pool_stats->method_setPoolStatus, 382 zjni_pool_status_to_obj(env, 383 zpool_get_status(zphp, &msgid))); 384 385 /* 386 * If a root file system does not exist for this pool, the pool 387 * is likely faulted, so just set its name in the Java object. 388 * Otherwise, populate all fields of the Java object. 389 */ 390 if (zhp == NULL) { 391 result = set_name_in_DatasetBean(env, 392 (char *)zpool_get_name(zphp), (DatasetBean_t *)bean); 393 } else { 394 result = populate_FileSystemBean( 395 env, zhp, (FileSystemBean_t *)bean); 396 } 397 } 398 399 return (result != 0); 400 } 401 402 static int 403 populate_FileSystemBean(JNIEnv *env, zfs_handle_t *zhp, FileSystemBean_t *bean) 404 { 405 return (populate_DatasetBean(env, zhp, (DatasetBean_t *)bean)); 406 } 407 408 static int 409 populate_VolumeBean(JNIEnv *env, zfs_handle_t *zhp, VolumeBean_t *bean) 410 { 411 return (populate_DatasetBean(env, zhp, (DatasetBean_t *)bean)); 412 } 413 414 static int 415 populate_SnapshotBean(JNIEnv *env, zfs_handle_t *zhp, SnapshotBean_t *bean) 416 { 417 return (populate_DatasetBean(env, zhp, (DatasetBean_t *)bean)); 418 } 419 420 static int 421 populate_FileSystemSnapshotBean(JNIEnv *env, zfs_handle_t *zhp, 422 FileSystemSnapshotBean_t *bean) 423 { 424 return (populate_SnapshotBean(env, zhp, (SnapshotBean_t *)bean)); 425 } 426 427 static int 428 populate_VolumeSnapshotBean(JNIEnv *env, zfs_handle_t *zhp, 429 VolumeSnapshotBean_t *bean) 430 { 431 return (populate_SnapshotBean(env, zhp, (SnapshotBean_t *)bean)); 432 } 433 434 static jobject 435 create_PoolBean(JNIEnv *env, zpool_handle_t *zphp, zfs_handle_t *zhp) 436 { 437 int result; 438 PoolBean_t bean_obj = {0}; 439 PoolBean_t *bean = &bean_obj; 440 441 /* Construct PoolBean */ 442 new_PoolBean(env, bean); 443 444 result = populate_PoolBean(env, zphp, zhp, bean); 445 if (result) { 446 /* Must not call any more Java methods to preserve exception */ 447 return (NULL); 448 } 449 450 return (((zjni_Object_t *)bean)->object); 451 } 452 453 static jobject 454 create_FileSystemBean(JNIEnv *env, zfs_handle_t *zhp) 455 { 456 int result; 457 FileSystemBean_t bean_obj = {0}; 458 FileSystemBean_t *bean = &bean_obj; 459 460 /* Construct FileSystemBean */ 461 new_FileSystemBean(env, bean); 462 463 result = populate_FileSystemBean(env, zhp, bean); 464 if (result) { 465 /* Must not call any more Java methods to preserve exception */ 466 return (NULL); 467 } 468 469 return (((zjni_Object_t *)bean)->object); 470 } 471 472 static jobject 473 create_VolumeBean(JNIEnv *env, zfs_handle_t *zhp) 474 { 475 int result; 476 VolumeBean_t bean_obj = {0}; 477 VolumeBean_t *bean = &bean_obj; 478 479 /* Construct VolumeBean */ 480 new_VolumeBean(env, bean); 481 482 result = populate_VolumeBean(env, zhp, bean); 483 if (result) { 484 /* Must not call any more Java methods to preserve exception */ 485 return (NULL); 486 } 487 488 return (((zjni_Object_t *)bean)->object); 489 } 490 491 static jobject 492 create_FileSystemSnapshotBean(JNIEnv *env, zfs_handle_t *zhp) 493 { 494 int result; 495 FileSystemSnapshotBean_t bean_obj = {0}; 496 FileSystemSnapshotBean_t *bean = &bean_obj; 497 498 /* Construct FileSystemSnapshotBean */ 499 new_FileSystemSnapshotBean(env, bean); 500 501 result = populate_FileSystemSnapshotBean(env, zhp, bean); 502 if (result) { 503 /* Must not call any more Java methods to preserve exception */ 504 return (NULL); 505 } 506 507 return (((zjni_Object_t *)bean)->object); 508 } 509 510 static jobject 511 create_VolumeSnapshotBean(JNIEnv *env, zfs_handle_t *zhp) 512 { 513 int result; 514 VolumeSnapshotBean_t bean_obj = {0}; 515 VolumeSnapshotBean_t *bean = &bean_obj; 516 517 /* Construct VolumeSnapshotBean */ 518 new_VolumeSnapshotBean(env, bean); 519 520 result = populate_VolumeSnapshotBean(env, zhp, bean); 521 if (result) { 522 /* Must not call any more Java methods to preserve exception */ 523 return (NULL); 524 } 525 526 return (((zjni_Object_t *)bean)->object); 527 } 528 529 static jobject 530 create_DatasetBean(JNIEnv *env, zfs_handle_t *zhp) 531 { 532 jobject object = NULL; 533 534 switch (zfs_get_type(zhp)) { 535 case ZFS_TYPE_FILESYSTEM: 536 object = create_FileSystemBean(env, zhp); 537 break; 538 539 case ZFS_TYPE_VOLUME: 540 object = create_VolumeBean(env, zhp); 541 break; 542 543 case ZFS_TYPE_SNAPSHOT: 544 object = is_fs_snapshot(zhp) ? 545 create_FileSystemSnapshotBean(env, zhp) : 546 create_VolumeSnapshotBean(env, zhp); 547 break; 548 } 549 550 return (object); 551 } 552 553 /* 554 * Determines whether the given snapshot is a snapshot of a file 555 * system or of a volume. 556 * 557 * Returns: 558 * 559 * 0 if it is a volume snapshot 560 * 1 if it is a file system snapshot 561 * -1 on error 562 */ 563 static int 564 is_fs_snapshot(zfs_handle_t *zhp) 565 { 566 char parent[ZFS_MAXNAMELEN]; 567 zfs_handle_t *parent_zhp; 568 int isfs; 569 570 if (zfs_get_type(zhp) != ZFS_TYPE_SNAPSHOT) { 571 return (-1); 572 } 573 574 zjni_get_dataset_from_snapshot( 575 zfs_get_name(zhp), parent, sizeof (parent)); 576 577 parent_zhp = zfs_open(g_zfs, parent, ZFS_TYPE_ANY); 578 if (parent_zhp == NULL) { 579 return (-1); 580 } 581 582 isfs = zfs_get_type(parent_zhp) == ZFS_TYPE_FILESYSTEM; 583 zfs_close(parent_zhp); 584 585 return (isfs); 586 } 587 588 static int 589 is_pool_name(const char *name) 590 { 591 return (strchr(name, '/') == NULL); 592 } 593 594 /* 595 * Package-private functions 596 */ 597 598 /* 599 * Callback function for zpool_iter(). Creates a Pool and adds it to 600 * the given zjni_ArrayList. 601 */ 602 int 603 zjni_create_add_Pool(zpool_handle_t *zphp, void *data) 604 { 605 JNIEnv *env = ((zjni_ArrayCallbackData_t *)data)->env; 606 zjni_Collection_t *list = ((zjni_ArrayCallbackData_t *)data)->list; 607 608 /* Get root fs for this pool -- may be NULL if pool is faulted */ 609 zfs_handle_t *zhp = zfs_open(g_zfs, zpool_get_name(zphp), 610 ZFS_TYPE_FILESYSTEM); 611 612 jobject bean = create_PoolBean(env, zphp, zhp); 613 614 if (zhp != NULL) { 615 zfs_close(zhp); 616 } 617 618 zpool_close(zphp); 619 620 if (bean == NULL) { 621 /* Must not call any more Java methods to preserve exception */ 622 return (-1); 623 } 624 625 /* Add pool to zjni_ArrayList */ 626 (*env)->CallBooleanMethod(env, ((zjni_Object_t *)list)->object, 627 ((zjni_Collection_t *)list)->method_add, bean); 628 629 return (0); 630 } 631 632 /* 633 * Callback function for zfs_iter_children(). Creates the appropriate 634 * Dataset and adds it to the given zjni_ArrayList. Per the contract 635 * with zfs_iter_children(), calls zfs_close() on the given 636 * zfs_handle_t. 637 */ 638 int 639 zjni_create_add_Dataset(zfs_handle_t *zhp, void *data) 640 { 641 JNIEnv *env = ((zjni_ArrayCallbackData_t *)data)->env; 642 zjni_Collection_t *list = ((zjni_ArrayCallbackData_t *)data)->list; 643 zfs_type_t typemask = 644 ((zjni_DatasetArrayCallbackData_t *)data)->typemask; 645 646 /* Only add allowed types */ 647 if (zfs_get_type(zhp) & typemask) { 648 649 jobject bean = create_DatasetBean(env, zhp); 650 zfs_close(zhp); 651 652 if (bean == NULL) { 653 /* 654 * Must not call any more Java methods to preserve 655 * exception 656 */ 657 return (-1); 658 } 659 660 /* Add Dataset to zjni_ArrayList */ 661 (*env)->CallBooleanMethod(env, ((zjni_Object_t *)list)->object, 662 ((zjni_Collection_t *)list)->method_add, bean); 663 } 664 665 return (0); 666 } 667 668 jobjectArray 669 zjni_get_Datasets_below(JNIEnv *env, jstring parentUTF, 670 zfs_type_t parent_typemask, zfs_type_t child_typemask, char *arrayClass) 671 { 672 jobjectArray array = NULL; 673 674 if (parentUTF != NULL) { 675 zfs_handle_t *zhp; 676 int error = 1; 677 const char *name = 678 (*env)->GetStringUTFChars(env, parentUTF, NULL); 679 680 /* Create an array list to hold the children */ 681 zjni_DatasetSet_t list_obj = {0}; 682 zjni_DatasetSet_t *list = &list_obj; 683 zjni_new_DatasetSet(env, list); 684 685 /* Retrieve parent dataset */ 686 zhp = zfs_open(g_zfs, name, parent_typemask); 687 688 if (zhp != NULL) { 689 zjni_DatasetArrayCallbackData_t data = {0}; 690 data.data.env = env; 691 data.data.list = (zjni_Collection_t *)list; 692 data.typemask = child_typemask; 693 694 (void) zfs_iter_children(zhp, zjni_create_add_Dataset, 695 &data); 696 697 zfs_close(zhp); 698 699 if ((*env)->ExceptionOccurred(env) == NULL) { 700 error = 0; 701 } 702 } else 703 704 /* Parent is not a dataset -- see if it's a faulted pool */ 705 if ((parent_typemask & ZFS_TYPE_FILESYSTEM) && 706 is_pool_name(name)) { 707 zpool_handle_t *zphp = zpool_open_canfail(g_zfs, name); 708 709 if (zphp != NULL) { 710 /* A faulted pool has no datasets */ 711 error = 0; 712 zpool_close(zphp); 713 } 714 } 715 716 (*env)->ReleaseStringUTFChars(env, parentUTF, name); 717 718 if (!error) { 719 array = zjni_Collection_to_array( 720 env, (zjni_Collection_t *)list, arrayClass); 721 } 722 } 723 724 return (array); 725 } 726 727 jobjectArray 728 zjni_get_Datasets_dependents(JNIEnv *env, jobjectArray paths) 729 { 730 jint i; 731 jint npaths; 732 zjni_DatasetArrayCallbackData_t data = {0}; 733 jobjectArray array = NULL; 734 735 /* Create a list to hold the children */ 736 zjni_DatasetSet_t list_obj = {0}; 737 zjni_DatasetSet_t *list = &list_obj; 738 zjni_new_DatasetSet(env, list); 739 740 data.data.env = env; 741 data.data.list = (zjni_Collection_t *)list; 742 data.typemask = ZFS_TYPE_ANY; 743 744 npaths = (*env)->GetArrayLength(env, paths); 745 for (i = 0; i < npaths; i++) { 746 747 jstring pathUTF = (jstring) 748 ((*env)->GetObjectArrayElement(env, paths, i)); 749 750 if (pathUTF != NULL) { 751 const char *path = 752 (*env)->GetStringUTFChars(env, pathUTF, NULL); 753 754 zfs_handle_t *zhp = zfs_open(g_zfs, path, ZFS_TYPE_ANY); 755 if (zhp != NULL) { 756 /* Add all dependents of this Dataset to list */ 757 (void) zfs_iter_dependents(zhp, 758 zjni_create_add_Dataset, &data); 759 760 /* Add this Dataset to list (and close zhp) */ 761 (void) zjni_create_add_Dataset(zhp, &data); 762 } else 763 764 /* Path is not a dataset - see if it's a faulted pool */ 765 if (is_pool_name(path)) { 766 zpool_handle_t *zphp = zpool_open_canfail(g_zfs, 767 path); 768 769 if (zphp != NULL) { 770 /* 771 * Add this Pool to list (and 772 * close zphp) 773 */ 774 (void) zjni_create_add_Pool(zphp, 775 &data.data); 776 } 777 } 778 779 (*env)->ReleaseStringUTFChars(env, pathUTF, path); 780 } 781 } 782 783 if ((*env)->ExceptionOccurred(env) == NULL) { 784 array = zjni_Collection_to_array(env, (zjni_Collection_t *)list, 785 ZFSJNI_PACKAGE_DATA "Dataset"); 786 } 787 788 return (array); 789 } 790 791 /* 792 * Gets a Dataset of the given name and type, or NULL if no such 793 * Dataset exists. 794 */ 795 jobject 796 zjni_get_Dataset(JNIEnv *env, jstring nameUTF, zfs_type_t typemask) 797 { 798 jobject device = NULL; 799 const char *name = (*env)->GetStringUTFChars(env, nameUTF, NULL); 800 zfs_handle_t *zhp = zfs_open(g_zfs, name, typemask); 801 802 if ((typemask & ZFS_TYPE_FILESYSTEM) && is_pool_name(name)) { 803 zpool_handle_t *zphp = zpool_open_canfail(g_zfs, name); 804 805 if (zphp != NULL) { 806 device = create_PoolBean(env, zphp, zhp); 807 zpool_close(zphp); 808 } 809 } else if (zhp != NULL) { 810 /* Creates a Dataset object of the appropriate class */ 811 device = create_DatasetBean(env, zhp); 812 } 813 814 if (zhp != NULL) { 815 zfs_close(zhp); 816 } 817 818 (*env)->ReleaseStringUTFChars(env, nameUTF, name); 819 820 return (device); 821 } 822