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 && 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 } else { 664 zfs_close(zhp); 665 } 666 667 return (0); 668 } 669 670 jobjectArray 671 zjni_get_Datasets_below(JNIEnv *env, jstring parentUTF, 672 zfs_type_t parent_typemask, zfs_type_t child_typemask, char *arrayClass) 673 { 674 jobjectArray array = NULL; 675 676 if (parentUTF != NULL) { 677 zfs_handle_t *zhp; 678 int error = 1; 679 const char *name = 680 (*env)->GetStringUTFChars(env, parentUTF, NULL); 681 682 /* Create an array list to hold the children */ 683 zjni_DatasetSet_t list_obj = {0}; 684 zjni_DatasetSet_t *list = &list_obj; 685 zjni_new_DatasetSet(env, list); 686 687 /* Retrieve parent dataset */ 688 zhp = zfs_open(g_zfs, name, parent_typemask); 689 690 if (zhp != NULL) { 691 zjni_DatasetArrayCallbackData_t data = {0}; 692 data.data.env = env; 693 data.data.list = (zjni_Collection_t *)list; 694 data.typemask = child_typemask; 695 696 (void) zfs_iter_children(zhp, zjni_create_add_Dataset, 697 &data); 698 699 zfs_close(zhp); 700 701 if ((*env)->ExceptionOccurred(env) == NULL) { 702 error = 0; 703 } 704 } else 705 706 /* Parent is not a dataset -- see if it's a faulted pool */ 707 if ((parent_typemask & ZFS_TYPE_FILESYSTEM) && 708 is_pool_name(name)) { 709 zpool_handle_t *zphp = zpool_open_canfail(g_zfs, name); 710 711 if (zphp != NULL) { 712 /* A faulted pool has no datasets */ 713 error = 0; 714 zpool_close(zphp); 715 } 716 } 717 718 (*env)->ReleaseStringUTFChars(env, parentUTF, name); 719 720 if (!error) { 721 array = zjni_Collection_to_array( 722 env, (zjni_Collection_t *)list, arrayClass); 723 } 724 } 725 726 return (array); 727 } 728 729 jobjectArray 730 zjni_get_Datasets_dependents(JNIEnv *env, jobjectArray paths) 731 { 732 jint i; 733 jint npaths; 734 zjni_DatasetArrayCallbackData_t data = {0}; 735 jobjectArray array = NULL; 736 737 /* Create a list to hold the children */ 738 zjni_DatasetSet_t list_obj = {0}; 739 zjni_DatasetSet_t *list = &list_obj; 740 zjni_new_DatasetSet(env, list); 741 742 data.data.env = env; 743 data.data.list = (zjni_Collection_t *)list; 744 data.typemask = ZFS_TYPE_ANY; 745 746 npaths = (*env)->GetArrayLength(env, paths); 747 for (i = 0; i < npaths; i++) { 748 749 jstring pathUTF = (jstring) 750 ((*env)->GetObjectArrayElement(env, paths, i)); 751 752 if (pathUTF != NULL) { 753 const char *path = 754 (*env)->GetStringUTFChars(env, pathUTF, NULL); 755 756 zfs_handle_t *zhp = zfs_open(g_zfs, path, ZFS_TYPE_ANY); 757 if (zhp != NULL) { 758 /* Add all dependents of this Dataset to list */ 759 (void) zfs_iter_dependents(zhp, B_FALSE, 760 zjni_create_add_Dataset, &data); 761 762 /* Add this Dataset to list (and close zhp) */ 763 (void) zjni_create_add_Dataset(zhp, &data); 764 } else if (is_pool_name(path)) { 765 /* 766 * Path is not a dataset - 767 * see if it's a faulted pool 768 */ 769 zpool_handle_t *zphp = zpool_open_canfail(g_zfs, 770 path); 771 772 if (zphp != NULL) { 773 /* 774 * Add this Pool to list (and 775 * close zphp) 776 */ 777 (void) zjni_create_add_Pool(zphp, 778 &data.data); 779 } 780 } 781 782 (*env)->ReleaseStringUTFChars(env, pathUTF, path); 783 } 784 } 785 786 if ((*env)->ExceptionOccurred(env) == NULL) { 787 array = zjni_Collection_to_array(env, (zjni_Collection_t *)list, 788 ZFSJNI_PACKAGE_DATA "Dataset"); 789 } 790 791 return (array); 792 } 793 794 /* 795 * Gets a Dataset of the given name and type, or NULL if no such 796 * Dataset exists. 797 */ 798 jobject 799 zjni_get_Dataset(JNIEnv *env, jstring nameUTF, zfs_type_t typemask) 800 { 801 jobject device = NULL; 802 const char *name = (*env)->GetStringUTFChars(env, nameUTF, NULL); 803 zfs_handle_t *zhp = zfs_open(g_zfs, name, typemask); 804 805 if ((typemask & ZFS_TYPE_FILESYSTEM) && is_pool_name(name)) { 806 zpool_handle_t *zphp = zpool_open_canfail(g_zfs, name); 807 808 if (zphp != NULL) { 809 device = create_PoolBean(env, zphp, zhp); 810 zpool_close(zphp); 811 } 812 } else if (zhp != NULL) { 813 /* Creates a Dataset object of the appropriate class */ 814 device = create_DatasetBean(env, zhp); 815 } 816 817 if (zhp != NULL) { 818 zfs_close(zhp); 819 } 820 821 (*env)->ReleaseStringUTFChars(env, nameUTF, name); 822 823 return (device); 824 } 825