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