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 (*env)->CallVoidMethod(env, object->object, 386 pool_stats->method_setPoolVersion, 387 zpool_get_prop_int(zphp, ZPOOL_PROP_VERSION, NULL)); 388 389 /* 390 * If a root file system does not exist for this pool, the pool 391 * is likely faulted, so just set its name in the Java object. 392 * Otherwise, populate all fields of the Java object. 393 */ 394 if (zhp == NULL) { 395 result = set_name_in_DatasetBean(env, 396 (char *)zpool_get_name(zphp), 397 (DatasetBean_t *)bean); 398 } else { 399 result = populate_FileSystemBean( 400 env, zhp, (FileSystemBean_t *)bean); 401 } 402 } 403 404 return (result != 0); 405 } 406 407 static int 408 populate_FileSystemBean(JNIEnv *env, zfs_handle_t *zhp, FileSystemBean_t *bean) 409 { 410 return (populate_DatasetBean(env, zhp, (DatasetBean_t *)bean)); 411 } 412 413 static int 414 populate_VolumeBean(JNIEnv *env, zfs_handle_t *zhp, VolumeBean_t *bean) 415 { 416 return (populate_DatasetBean(env, zhp, (DatasetBean_t *)bean)); 417 } 418 419 static int 420 populate_SnapshotBean(JNIEnv *env, zfs_handle_t *zhp, SnapshotBean_t *bean) 421 { 422 return (populate_DatasetBean(env, zhp, (DatasetBean_t *)bean)); 423 } 424 425 static int 426 populate_FileSystemSnapshotBean(JNIEnv *env, zfs_handle_t *zhp, 427 FileSystemSnapshotBean_t *bean) 428 { 429 return (populate_SnapshotBean(env, zhp, (SnapshotBean_t *)bean)); 430 } 431 432 static int 433 populate_VolumeSnapshotBean(JNIEnv *env, zfs_handle_t *zhp, 434 VolumeSnapshotBean_t *bean) 435 { 436 return (populate_SnapshotBean(env, zhp, (SnapshotBean_t *)bean)); 437 } 438 439 static jobject 440 create_PoolBean(JNIEnv *env, zpool_handle_t *zphp, zfs_handle_t *zhp) 441 { 442 int result; 443 PoolBean_t bean_obj = {0}; 444 PoolBean_t *bean = &bean_obj; 445 446 /* Construct PoolBean */ 447 new_PoolBean(env, bean); 448 449 result = populate_PoolBean(env, zphp, zhp, bean); 450 if (result) { 451 /* Must not call any more Java methods to preserve exception */ 452 return (NULL); 453 } 454 455 return (((zjni_Object_t *)bean)->object); 456 } 457 458 static jobject 459 create_FileSystemBean(JNIEnv *env, zfs_handle_t *zhp) 460 { 461 int result; 462 FileSystemBean_t bean_obj = {0}; 463 FileSystemBean_t *bean = &bean_obj; 464 465 /* Construct FileSystemBean */ 466 new_FileSystemBean(env, bean); 467 468 result = populate_FileSystemBean(env, zhp, bean); 469 if (result) { 470 /* Must not call any more Java methods to preserve exception */ 471 return (NULL); 472 } 473 474 return (((zjni_Object_t *)bean)->object); 475 } 476 477 static jobject 478 create_VolumeBean(JNIEnv *env, zfs_handle_t *zhp) 479 { 480 int result; 481 VolumeBean_t bean_obj = {0}; 482 VolumeBean_t *bean = &bean_obj; 483 484 /* Construct VolumeBean */ 485 new_VolumeBean(env, bean); 486 487 result = populate_VolumeBean(env, zhp, bean); 488 if (result) { 489 /* Must not call any more Java methods to preserve exception */ 490 return (NULL); 491 } 492 493 return (((zjni_Object_t *)bean)->object); 494 } 495 496 static jobject 497 create_FileSystemSnapshotBean(JNIEnv *env, zfs_handle_t *zhp) 498 { 499 int result; 500 FileSystemSnapshotBean_t bean_obj = {0}; 501 FileSystemSnapshotBean_t *bean = &bean_obj; 502 503 /* Construct FileSystemSnapshotBean */ 504 new_FileSystemSnapshotBean(env, bean); 505 506 result = populate_FileSystemSnapshotBean(env, zhp, bean); 507 if (result) { 508 /* Must not call any more Java methods to preserve exception */ 509 return (NULL); 510 } 511 512 return (((zjni_Object_t *)bean)->object); 513 } 514 515 static jobject 516 create_VolumeSnapshotBean(JNIEnv *env, zfs_handle_t *zhp) 517 { 518 int result; 519 VolumeSnapshotBean_t bean_obj = {0}; 520 VolumeSnapshotBean_t *bean = &bean_obj; 521 522 /* Construct VolumeSnapshotBean */ 523 new_VolumeSnapshotBean(env, bean); 524 525 result = populate_VolumeSnapshotBean(env, zhp, bean); 526 if (result) { 527 /* Must not call any more Java methods to preserve exception */ 528 return (NULL); 529 } 530 531 return (((zjni_Object_t *)bean)->object); 532 } 533 534 static jobject 535 create_DatasetBean(JNIEnv *env, zfs_handle_t *zhp) 536 { 537 jobject object = NULL; 538 539 switch (zfs_get_type(zhp)) { 540 case ZFS_TYPE_FILESYSTEM: 541 object = create_FileSystemBean(env, zhp); 542 break; 543 544 case ZFS_TYPE_VOLUME: 545 object = create_VolumeBean(env, zhp); 546 break; 547 548 case ZFS_TYPE_SNAPSHOT: 549 object = is_fs_snapshot(zhp) ? 550 create_FileSystemSnapshotBean(env, zhp) : 551 create_VolumeSnapshotBean(env, zhp); 552 break; 553 } 554 555 return (object); 556 } 557 558 /* 559 * Determines whether the given snapshot is a snapshot of a file 560 * system or of a volume. 561 * 562 * Returns: 563 * 564 * 0 if it is a volume snapshot 565 * 1 if it is a file system snapshot 566 * -1 on error 567 */ 568 static int 569 is_fs_snapshot(zfs_handle_t *zhp) 570 { 571 char parent[ZFS_MAXNAMELEN]; 572 zfs_handle_t *parent_zhp; 573 int isfs; 574 575 if (zfs_get_type(zhp) != ZFS_TYPE_SNAPSHOT) { 576 return (-1); 577 } 578 579 zjni_get_dataset_from_snapshot( 580 zfs_get_name(zhp), parent, sizeof (parent)); 581 582 parent_zhp = zfs_open(g_zfs, parent, ZFS_TYPE_DATASET); 583 if (parent_zhp == NULL) { 584 return (-1); 585 } 586 587 isfs = zfs_get_type(parent_zhp) == ZFS_TYPE_FILESYSTEM; 588 zfs_close(parent_zhp); 589 590 return (isfs); 591 } 592 593 static int 594 is_pool_name(const char *name) 595 { 596 return (strchr(name, '/') == NULL && strchr(name, '@') == NULL); 597 } 598 599 /* 600 * Package-private functions 601 */ 602 603 /* 604 * Callback function for zpool_iter(). Creates a Pool and adds it to 605 * the given zjni_ArrayList. 606 */ 607 int 608 zjni_create_add_Pool(zpool_handle_t *zphp, void *data) 609 { 610 JNIEnv *env = ((zjni_ArrayCallbackData_t *)data)->env; 611 zjni_Collection_t *list = ((zjni_ArrayCallbackData_t *)data)->list; 612 613 /* Get root fs for this pool -- may be NULL if pool is faulted */ 614 zfs_handle_t *zhp = zfs_open(g_zfs, zpool_get_name(zphp), 615 ZFS_TYPE_FILESYSTEM); 616 617 jobject bean = create_PoolBean(env, zphp, zhp); 618 619 if (zhp != NULL) 620 zfs_close(zhp); 621 622 zpool_close(zphp); 623 624 if (bean == NULL) { 625 /* Must not call any more Java methods to preserve exception */ 626 return (-1); 627 } 628 629 /* Add pool to zjni_ArrayList */ 630 (*env)->CallBooleanMethod(env, ((zjni_Object_t *)list)->object, 631 ((zjni_Collection_t *)list)->method_add, bean); 632 633 return (0); 634 } 635 636 /* 637 * Callback function for zfs_iter_children(). Creates the appropriate 638 * Dataset and adds it to the given zjni_ArrayList. Per the contract 639 * with zfs_iter_children(), calls zfs_close() on the given 640 * zfs_handle_t. 641 */ 642 int 643 zjni_create_add_Dataset(zfs_handle_t *zhp, void *data) 644 { 645 JNIEnv *env = ((zjni_ArrayCallbackData_t *)data)->env; 646 zjni_Collection_t *list = ((zjni_ArrayCallbackData_t *)data)->list; 647 zfs_type_t typemask = 648 ((zjni_DatasetArrayCallbackData_t *)data)->typemask; 649 650 /* Only add allowed types */ 651 if (zfs_get_type(zhp) & typemask) { 652 653 jobject bean = create_DatasetBean(env, zhp); 654 zfs_close(zhp); 655 656 if (bean == NULL) { 657 /* 658 * Must not call any more Java methods to preserve 659 * exception 660 */ 661 return (-1); 662 } 663 664 /* Add Dataset to zjni_ArrayList */ 665 (*env)->CallBooleanMethod(env, ((zjni_Object_t *)list)->object, 666 ((zjni_Collection_t *)list)->method_add, bean); 667 } else { 668 zfs_close(zhp); 669 } 670 671 return (0); 672 } 673 674 jobjectArray 675 zjni_get_Datasets_below(JNIEnv *env, jstring parentUTF, 676 zfs_type_t parent_typemask, zfs_type_t child_typemask, char *arrayClass) 677 { 678 jobjectArray array = NULL; 679 680 if (parentUTF != NULL) { 681 zfs_handle_t *zhp; 682 int error = 1; 683 const char *name = 684 (*env)->GetStringUTFChars(env, parentUTF, NULL); 685 686 /* Create an array list to hold the children */ 687 zjni_DatasetSet_t list_obj = {0}; 688 zjni_DatasetSet_t *list = &list_obj; 689 zjni_new_DatasetSet(env, list); 690 691 /* Retrieve parent dataset */ 692 zhp = zfs_open(g_zfs, name, parent_typemask); 693 694 if (zhp != NULL) { 695 zjni_DatasetArrayCallbackData_t data = {0}; 696 data.data.env = env; 697 data.data.list = (zjni_Collection_t *)list; 698 data.typemask = child_typemask; 699 700 (void) zfs_iter_children(zhp, zjni_create_add_Dataset, 701 &data); 702 703 zfs_close(zhp); 704 705 if ((*env)->ExceptionOccurred(env) == NULL) { 706 error = 0; 707 } 708 } else 709 710 /* Parent is not a dataset -- see if it's a faulted pool */ 711 if ((parent_typemask & ZFS_TYPE_FILESYSTEM) && 712 is_pool_name(name)) { 713 zpool_handle_t *zphp = zpool_open_canfail(g_zfs, name); 714 715 if (zphp != NULL) { 716 /* A faulted pool has no datasets */ 717 error = 0; 718 zpool_close(zphp); 719 } 720 } 721 722 (*env)->ReleaseStringUTFChars(env, parentUTF, name); 723 724 if (!error) { 725 array = zjni_Collection_to_array( 726 env, (zjni_Collection_t *)list, arrayClass); 727 } 728 } 729 730 return (array); 731 } 732 733 jobjectArray 734 zjni_get_Datasets_dependents(JNIEnv *env, jobjectArray paths) 735 { 736 jint i; 737 jint npaths; 738 zjni_DatasetArrayCallbackData_t data = {0}; 739 jobjectArray array = NULL; 740 741 /* Create a list to hold the children */ 742 zjni_DatasetSet_t list_obj = {0}; 743 zjni_DatasetSet_t *list = &list_obj; 744 zjni_new_DatasetSet(env, list); 745 746 data.data.env = env; 747 data.data.list = (zjni_Collection_t *)list; 748 data.typemask = ZFS_TYPE_DATASET; 749 750 npaths = (*env)->GetArrayLength(env, paths); 751 for (i = 0; i < npaths; i++) { 752 753 jstring pathUTF = (jstring) 754 ((*env)->GetObjectArrayElement(env, paths, i)); 755 756 if (pathUTF != NULL) { 757 const char *path = 758 (*env)->GetStringUTFChars(env, pathUTF, NULL); 759 760 zfs_handle_t *zhp = zfs_open(g_zfs, path, 761 ZFS_TYPE_DATASET); 762 if (zhp != NULL) { 763 /* Add all dependents of this Dataset to list */ 764 (void) zfs_iter_dependents(zhp, B_FALSE, 765 zjni_create_add_Dataset, &data); 766 767 /* Add this Dataset to list (and close zhp) */ 768 (void) zjni_create_add_Dataset(zhp, &data); 769 } else if (is_pool_name(path)) { 770 /* 771 * Path is not a dataset - 772 * see if it's a faulted pool 773 */ 774 zpool_handle_t *zphp = zpool_open_canfail(g_zfs, 775 path); 776 777 if (zphp != NULL) { 778 /* 779 * Add this Pool to list (and 780 * close zphp) 781 */ 782 (void) zjni_create_add_Pool(zphp, 783 &data.data); 784 } 785 } 786 787 (*env)->ReleaseStringUTFChars(env, pathUTF, path); 788 } 789 } 790 791 if ((*env)->ExceptionOccurred(env) == NULL) { 792 array = zjni_Collection_to_array(env, (zjni_Collection_t *)list, 793 ZFSJNI_PACKAGE_DATA "Dataset"); 794 } 795 796 return (array); 797 } 798 799 /* 800 * Gets a Dataset of the given name and type, or NULL if no such 801 * Dataset exists. 802 */ 803 jobject 804 zjni_get_Dataset(JNIEnv *env, jstring nameUTF, zfs_type_t typemask) 805 { 806 jobject device = NULL; 807 const char *name = (*env)->GetStringUTFChars(env, nameUTF, NULL); 808 zfs_handle_t *zhp = zfs_open(g_zfs, name, typemask); 809 810 if ((typemask & ZFS_TYPE_FILESYSTEM) && is_pool_name(name)) { 811 zpool_handle_t *zphp = zpool_open_canfail(g_zfs, name); 812 813 if (zphp != NULL) { 814 device = create_PoolBean(env, zphp, zhp); 815 zpool_close(zphp); 816 } 817 } else if (zhp != NULL) { 818 /* Creates a Dataset object of the appropriate class */ 819 device = create_DatasetBean(env, zhp); 820 } 821 822 if (zhp != NULL) { 823 zfs_close(zhp); 824 } 825 826 (*env)->ReleaseStringUTFChars(env, nameUTF, name); 827 828 return (device); 829 } 830