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 2007 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_prop_int(zphp, ZPOOL_PROP_SIZE, NULL)); 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), 393 (DatasetBean_t *)bean); 394 } else { 395 result = populate_FileSystemBean( 396 env, zhp, (FileSystemBean_t *)bean); 397 } 398 } 399 400 return (result != 0); 401 } 402 403 static int 404 populate_FileSystemBean(JNIEnv *env, zfs_handle_t *zhp, FileSystemBean_t *bean) 405 { 406 return (populate_DatasetBean(env, zhp, (DatasetBean_t *)bean)); 407 } 408 409 static int 410 populate_VolumeBean(JNIEnv *env, zfs_handle_t *zhp, VolumeBean_t *bean) 411 { 412 return (populate_DatasetBean(env, zhp, (DatasetBean_t *)bean)); 413 } 414 415 static int 416 populate_SnapshotBean(JNIEnv *env, zfs_handle_t *zhp, SnapshotBean_t *bean) 417 { 418 return (populate_DatasetBean(env, zhp, (DatasetBean_t *)bean)); 419 } 420 421 static int 422 populate_FileSystemSnapshotBean(JNIEnv *env, zfs_handle_t *zhp, 423 FileSystemSnapshotBean_t *bean) 424 { 425 return (populate_SnapshotBean(env, zhp, (SnapshotBean_t *)bean)); 426 } 427 428 static int 429 populate_VolumeSnapshotBean(JNIEnv *env, zfs_handle_t *zhp, 430 VolumeSnapshotBean_t *bean) 431 { 432 return (populate_SnapshotBean(env, zhp, (SnapshotBean_t *)bean)); 433 } 434 435 static jobject 436 create_PoolBean(JNIEnv *env, zpool_handle_t *zphp, zfs_handle_t *zhp) 437 { 438 int result; 439 PoolBean_t bean_obj = {0}; 440 PoolBean_t *bean = &bean_obj; 441 442 /* Construct PoolBean */ 443 new_PoolBean(env, bean); 444 445 result = populate_PoolBean(env, zphp, zhp, bean); 446 if (result) { 447 /* Must not call any more Java methods to preserve exception */ 448 return (NULL); 449 } 450 451 return (((zjni_Object_t *)bean)->object); 452 } 453 454 static jobject 455 create_FileSystemBean(JNIEnv *env, zfs_handle_t *zhp) 456 { 457 int result; 458 FileSystemBean_t bean_obj = {0}; 459 FileSystemBean_t *bean = &bean_obj; 460 461 /* Construct FileSystemBean */ 462 new_FileSystemBean(env, bean); 463 464 result = populate_FileSystemBean(env, zhp, bean); 465 if (result) { 466 /* Must not call any more Java methods to preserve exception */ 467 return (NULL); 468 } 469 470 return (((zjni_Object_t *)bean)->object); 471 } 472 473 static jobject 474 create_VolumeBean(JNIEnv *env, zfs_handle_t *zhp) 475 { 476 int result; 477 VolumeBean_t bean_obj = {0}; 478 VolumeBean_t *bean = &bean_obj; 479 480 /* Construct VolumeBean */ 481 new_VolumeBean(env, bean); 482 483 result = populate_VolumeBean(env, zhp, bean); 484 if (result) { 485 /* Must not call any more Java methods to preserve exception */ 486 return (NULL); 487 } 488 489 return (((zjni_Object_t *)bean)->object); 490 } 491 492 static jobject 493 create_FileSystemSnapshotBean(JNIEnv *env, zfs_handle_t *zhp) 494 { 495 int result; 496 FileSystemSnapshotBean_t bean_obj = {0}; 497 FileSystemSnapshotBean_t *bean = &bean_obj; 498 499 /* Construct FileSystemSnapshotBean */ 500 new_FileSystemSnapshotBean(env, bean); 501 502 result = populate_FileSystemSnapshotBean(env, zhp, bean); 503 if (result) { 504 /* Must not call any more Java methods to preserve exception */ 505 return (NULL); 506 } 507 508 return (((zjni_Object_t *)bean)->object); 509 } 510 511 static jobject 512 create_VolumeSnapshotBean(JNIEnv *env, zfs_handle_t *zhp) 513 { 514 int result; 515 VolumeSnapshotBean_t bean_obj = {0}; 516 VolumeSnapshotBean_t *bean = &bean_obj; 517 518 /* Construct VolumeSnapshotBean */ 519 new_VolumeSnapshotBean(env, bean); 520 521 result = populate_VolumeSnapshotBean(env, zhp, bean); 522 if (result) { 523 /* Must not call any more Java methods to preserve exception */ 524 return (NULL); 525 } 526 527 return (((zjni_Object_t *)bean)->object); 528 } 529 530 static jobject 531 create_DatasetBean(JNIEnv *env, zfs_handle_t *zhp) 532 { 533 jobject object = NULL; 534 535 switch (zfs_get_type(zhp)) { 536 case ZFS_TYPE_FILESYSTEM: 537 object = create_FileSystemBean(env, zhp); 538 break; 539 540 case ZFS_TYPE_VOLUME: 541 object = create_VolumeBean(env, zhp); 542 break; 543 544 case ZFS_TYPE_SNAPSHOT: 545 object = is_fs_snapshot(zhp) ? 546 create_FileSystemSnapshotBean(env, zhp) : 547 create_VolumeSnapshotBean(env, zhp); 548 break; 549 } 550 551 return (object); 552 } 553 554 /* 555 * Determines whether the given snapshot is a snapshot of a file 556 * system or of a volume. 557 * 558 * Returns: 559 * 560 * 0 if it is a volume snapshot 561 * 1 if it is a file system snapshot 562 * -1 on error 563 */ 564 static int 565 is_fs_snapshot(zfs_handle_t *zhp) 566 { 567 char parent[ZFS_MAXNAMELEN]; 568 zfs_handle_t *parent_zhp; 569 int isfs; 570 571 if (zfs_get_type(zhp) != ZFS_TYPE_SNAPSHOT) { 572 return (-1); 573 } 574 575 zjni_get_dataset_from_snapshot( 576 zfs_get_name(zhp), parent, sizeof (parent)); 577 578 parent_zhp = zfs_open(g_zfs, parent, ZFS_TYPE_DATASET); 579 if (parent_zhp == NULL) { 580 return (-1); 581 } 582 583 isfs = zfs_get_type(parent_zhp) == ZFS_TYPE_FILESYSTEM; 584 zfs_close(parent_zhp); 585 586 return (isfs); 587 } 588 589 static int 590 is_pool_name(const char *name) 591 { 592 return (strchr(name, '/') == NULL && strchr(name, '@') == NULL); 593 } 594 595 /* 596 * Package-private functions 597 */ 598 599 /* 600 * Callback function for zpool_iter(). Creates a Pool and adds it to 601 * the given zjni_ArrayList. 602 */ 603 int 604 zjni_create_add_Pool(zpool_handle_t *zphp, void *data) 605 { 606 JNIEnv *env = ((zjni_ArrayCallbackData_t *)data)->env; 607 zjni_Collection_t *list = ((zjni_ArrayCallbackData_t *)data)->list; 608 609 /* Get root fs for this pool -- may be NULL if pool is faulted */ 610 zfs_handle_t *zhp = zfs_open(g_zfs, zpool_get_name(zphp), 611 ZFS_TYPE_FILESYSTEM); 612 613 jobject bean = create_PoolBean(env, zphp, zhp); 614 615 if (zhp != NULL) 616 zfs_close(zhp); 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_DATASET; 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, 757 ZFS_TYPE_DATASET); 758 if (zhp != NULL) { 759 /* Add all dependents of this Dataset to list */ 760 (void) zfs_iter_dependents(zhp, B_FALSE, 761 zjni_create_add_Dataset, &data); 762 763 /* Add this Dataset to list (and close zhp) */ 764 (void) zjni_create_add_Dataset(zhp, &data); 765 } else if (is_pool_name(path)) { 766 /* 767 * Path is not a dataset - 768 * see if it's a faulted pool 769 */ 770 zpool_handle_t *zphp = zpool_open_canfail(g_zfs, 771 path); 772 773 if (zphp != NULL) { 774 /* 775 * Add this Pool to list (and 776 * close zphp) 777 */ 778 (void) zjni_create_add_Pool(zphp, 779 &data.data); 780 } 781 } 782 783 (*env)->ReleaseStringUTFChars(env, pathUTF, path); 784 } 785 } 786 787 if ((*env)->ExceptionOccurred(env) == NULL) { 788 array = zjni_Collection_to_array(env, (zjni_Collection_t *)list, 789 ZFSJNI_PACKAGE_DATA "Dataset"); 790 } 791 792 return (array); 793 } 794 795 /* 796 * Gets a Dataset of the given name and type, or NULL if no such 797 * Dataset exists. 798 */ 799 jobject 800 zjni_get_Dataset(JNIEnv *env, jstring nameUTF, zfs_type_t typemask) 801 { 802 jobject device = NULL; 803 const char *name = (*env)->GetStringUTFChars(env, nameUTF, NULL); 804 zfs_handle_t *zhp = zfs_open(g_zfs, name, typemask); 805 806 if ((typemask & ZFS_TYPE_FILESYSTEM) && is_pool_name(name)) { 807 zpool_handle_t *zphp = zpool_open_canfail(g_zfs, name); 808 809 if (zphp != NULL) { 810 device = create_PoolBean(env, zphp, zhp); 811 zpool_close(zphp); 812 } 813 } else if (zhp != NULL) { 814 /* Creates a Dataset object of the appropriate class */ 815 device = create_DatasetBean(env, zhp); 816 } 817 818 if (zhp != NULL) { 819 zfs_close(zhp); 820 } 821 822 (*env)->ReleaseStringUTFChars(env, nameUTF, name); 823 824 return (device); 825 } 826