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 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 23 * Copyright (c) 2015 by Delphix. All rights reserved. 24 */ 25 26 #include "libzfs_jni_property.h" 27 #include "libzfs_jni_util.h" 28 #include <strings.h> 29 30 /* 31 * Types 32 */ 33 34 /* Signature for function to convert string to a specific Java object */ 35 typedef jobject (*str_to_obj_f)(JNIEnv *, char *); 36 37 /* Signature for function to convert uint64_t to a specific Java object */ 38 typedef jobject (*uint64_to_obj_f)(JNIEnv *, uint64_t); 39 40 /* 41 * Describes a property and the parameters needed to create a Java 42 * Property object for it 43 */ 44 typedef struct custom_prop_desct { 45 zfs_prop_t prop; 46 str_to_obj_f convert_str; 47 uint64_to_obj_f convert_uint64; 48 char *propClass; 49 char *valueClass; 50 } custom_prop_desct_t; 51 52 /* 53 * Function prototypes 54 */ 55 56 static jobject create_BasicProperty(JNIEnv *, zfs_handle_t *, 57 zfs_prop_t, str_to_obj_f, uint64_to_obj_f, char *, char *); 58 static jobject create_BooleanProperty(JNIEnv *, zfs_handle_t *, zfs_prop_t); 59 static jobject create_LongProperty(JNIEnv *, zfs_handle_t *, zfs_prop_t); 60 static jobject create_StringProperty(JNIEnv *, zfs_handle_t *, zfs_prop_t); 61 static jobject create_ObjectProperty(JNIEnv *, zfs_handle_t *, 62 zfs_prop_t, str_to_obj_f, uint64_to_obj_f, char *, char *); 63 static jobject create_default_BasicProperty(JNIEnv *, zfs_prop_t, 64 str_to_obj_f, uint64_to_obj_f, char *, char *); 65 static jobject create_default_BooleanProperty(JNIEnv *, zfs_prop_t); 66 static jobject create_default_LongProperty(JNIEnv *, zfs_prop_t); 67 static jobject create_default_StringProperty(JNIEnv *, zfs_prop_t); 68 static jobject create_default_ObjectProperty( 69 JNIEnv *, zfs_prop_t, str_to_obj_f, uint64_to_obj_f, char *, char *); 70 static jobject str_to_enum_element(JNIEnv *, char *, char *); 71 static jobject str_to_aclinherit(JNIEnv *, char *); 72 static jobject str_to_aclmode(JNIEnv *, char *); 73 static jobject str_to_checksum(JNIEnv *, char *); 74 static jobject str_to_compression(JNIEnv *, char *); 75 static jobject str_to_snapdir(JNIEnv *, char *); 76 static jobject str_to_string(JNIEnv *, char *); 77 78 /* 79 * Static data 80 */ 81 82 zfs_prop_t props_boolean[] = { 83 ZFS_PROP_ATIME, 84 ZFS_PROP_DEVICES, 85 ZFS_PROP_EXEC, 86 ZFS_PROP_MOUNTED, 87 ZFS_PROP_READONLY, 88 ZFS_PROP_SETUID, 89 ZFS_PROP_ZONED, 90 ZFS_PROP_DEFER_DESTROY, 91 ZFS_PROP_FOLLOW, 92 ZPROP_INVAL 93 }; 94 95 zfs_prop_t props_long[] = { 96 ZFS_PROP_AVAILABLE, 97 ZFS_PROP_CREATETXG, 98 ZFS_PROP_QUOTA, 99 ZFS_PROP_REFERENCED, 100 ZFS_PROP_RESERVATION, 101 ZFS_PROP_USED, 102 ZFS_PROP_VOLSIZE, 103 ZFS_PROP_REFQUOTA, 104 ZFS_PROP_REFRESERVATION, 105 ZFS_PROP_USERREFS, 106 ZPROP_INVAL 107 }; 108 109 zfs_prop_t props_string[] = { 110 ZFS_PROP_ORIGIN, 111 /* ZFS_PROP_TYPE, */ 112 ZPROP_INVAL 113 }; 114 115 custom_prop_desct_t props_custom[] = { 116 { ZFS_PROP_ACLINHERIT, str_to_aclinherit, NULL, 117 ZFSJNI_PACKAGE_DATA "AclInheritProperty", 118 ZFSJNI_PACKAGE_DATA "AclInheritProperty$AclInherit" }, 119 120 { ZFS_PROP_ACLMODE, str_to_aclmode, NULL, 121 ZFSJNI_PACKAGE_DATA "AclModeProperty", 122 ZFSJNI_PACKAGE_DATA "AclModeProperty$AclMode" }, 123 124 { ZFS_PROP_CHECKSUM, str_to_checksum, NULL, 125 ZFSJNI_PACKAGE_DATA "ChecksumProperty", 126 ZFSJNI_PACKAGE_DATA "ChecksumProperty$Checksum" }, 127 128 { ZFS_PROP_COMPRESSION, str_to_compression, NULL, 129 ZFSJNI_PACKAGE_DATA "CompressionProperty", 130 ZFSJNI_PACKAGE_DATA "CompressionProperty$Compression" }, 131 132 { ZFS_PROP_COMPRESSRATIO, NULL, zjni_long_to_Long, 133 ZFSJNI_PACKAGE_DATA "CompressRatioProperty", 134 "java/lang/Long" }, 135 136 { ZFS_PROP_CREATION, zjni_str_to_date, NULL, 137 ZFSJNI_PACKAGE_DATA "CreationProperty", 138 "java/util/Date" }, 139 140 { ZFS_PROP_MOUNTPOINT, str_to_string, NULL, 141 ZFSJNI_PACKAGE_DATA "MountPointProperty", 142 "java/lang/String" }, 143 144 { ZFS_PROP_RECORDSIZE, NULL, zjni_long_to_Long, 145 ZFSJNI_PACKAGE_DATA "RecordSizeProperty", 146 "java/lang/Long" }, 147 148 { ZFS_PROP_SHARENFS, str_to_string, NULL, 149 ZFSJNI_PACKAGE_DATA "ShareNFSProperty", 150 "java/lang/String" }, 151 152 { ZFS_PROP_SNAPDIR, str_to_snapdir, NULL, 153 ZFSJNI_PACKAGE_DATA "SnapDirProperty", 154 ZFSJNI_PACKAGE_DATA "SnapDirProperty$SnapDir" }, 155 156 { ZFS_PROP_VOLBLOCKSIZE, NULL, zjni_long_to_Long, 157 ZFSJNI_PACKAGE_DATA "VolBlockSizeProperty", 158 "java/lang/Long" }, 159 160 { ZPROP_INVAL, NULL, NULL, NULL, NULL }, 161 }; 162 163 /* 164 * Static functions 165 */ 166 167 static jobject 168 create_BasicProperty(JNIEnv *env, zfs_handle_t *zhp, zfs_prop_t prop, 169 str_to_obj_f convert_str, uint64_to_obj_f convert_uint64, 170 char *propClass, char *valueClass) 171 { 172 jobject propertyObject = NULL; 173 char source[ZFS_MAX_DATASET_NAME_LEN]; 174 zprop_source_t srctype; 175 jobject propValue = NULL; 176 177 if (convert_str != NULL) { 178 char propbuf[ZFS_MAXPROPLEN]; 179 int result = zfs_prop_get(zhp, prop, propbuf, 180 sizeof (propbuf), &srctype, source, sizeof (source), 1); 181 182 if (result == 0) 183 propValue = convert_str(env, propbuf); 184 } else { 185 uint64_t value; 186 int result = zfs_prop_get_numeric( 187 zhp, prop, &value, &srctype, source, sizeof (source)); 188 189 if (result == 0) 190 propValue = convert_uint64(env, value); 191 } 192 193 if (propValue != NULL) { 194 195 jmethodID constructor; 196 char signature[1024]; 197 jclass class = (*env)->FindClass(env, propClass); 198 199 jstring propName = (*env)->NewStringUTF( 200 env, zfs_prop_to_name(prop)); 201 202 jboolean readOnly = zfs_prop_readonly(prop) ? 203 JNI_TRUE : JNI_FALSE; 204 205 if (srctype == ZPROP_SRC_INHERITED) { 206 207 jstring propSource = (*env)->NewStringUTF(env, source); 208 209 (void) snprintf(signature, sizeof (signature), 210 "(Ljava/lang/String;L%s;ZLjava/lang/String;)V", 211 valueClass); 212 213 constructor = (*env)->GetMethodID( 214 env, class, "<init>", signature); 215 216 propertyObject = (*env)->NewObject( 217 env, class, constructor, propName, propValue, 218 readOnly, propSource); 219 } else { 220 jobject lineage = zjni_int_to_Lineage(env, srctype); 221 222 (void) snprintf(signature, sizeof (signature), 223 "(Ljava/lang/String;L%s;ZL" 224 ZFSJNI_PACKAGE_DATA "Property$Lineage;)V", 225 valueClass); 226 227 constructor = (*env)->GetMethodID( 228 env, class, "<init>", signature); 229 230 propertyObject = (*env)->NewObject( 231 env, class, constructor, propName, propValue, 232 readOnly, lineage); 233 } 234 } 235 236 return (propertyObject); 237 } 238 239 static jobject 240 create_BooleanProperty(JNIEnv *env, zfs_handle_t *zhp, zfs_prop_t prop) 241 { 242 return (create_BasicProperty(env, zhp, prop, NULL, zjni_int_to_boolean, 243 ZFSJNI_PACKAGE_DATA "BooleanProperty", "java/lang/Boolean")); 244 } 245 246 static jobject 247 create_LongProperty(JNIEnv *env, zfs_handle_t *zhp, zfs_prop_t prop) 248 { 249 return (create_BasicProperty(env, zhp, prop, NULL, zjni_long_to_Long, 250 ZFSJNI_PACKAGE_DATA "LongProperty", "java/lang/Long")); 251 } 252 253 static jobject 254 create_StringProperty(JNIEnv *env, zfs_handle_t *zhp, zfs_prop_t prop) 255 { 256 return (create_BasicProperty(env, zhp, prop, str_to_string, NULL, 257 ZFSJNI_PACKAGE_DATA "StringProperty", "java/lang/String")); 258 } 259 260 static jobject 261 create_ObjectProperty(JNIEnv *env, zfs_handle_t *zhp, zfs_prop_t prop, 262 str_to_obj_f convert_str, uint64_to_obj_f convert_uint64, 263 char *propClass, char *valueClass) 264 { 265 jobject propertyObject = NULL; 266 char source[ZFS_MAX_DATASET_NAME_LEN]; 267 zprop_source_t srctype; 268 jobject propValue = NULL; 269 270 if (convert_str != NULL) { 271 char propbuf[ZFS_MAXPROPLEN]; 272 int result = zfs_prop_get(zhp, prop, propbuf, 273 sizeof (propbuf), &srctype, source, sizeof (source), 1); 274 275 if (result == 0) 276 propValue = convert_str(env, propbuf); 277 } else { 278 uint64_t value; 279 int result = zfs_prop_get_numeric( 280 zhp, prop, &value, &srctype, source, sizeof (source)); 281 282 if (result == 0) 283 propValue = convert_uint64(env, value); 284 } 285 286 if (propValue != NULL) { 287 288 jmethodID constructor; 289 char signature[1024]; 290 jclass class = (*env)->FindClass(env, propClass); 291 292 if (srctype == ZPROP_SRC_INHERITED) { 293 294 jstring propSource = (*env)->NewStringUTF(env, source); 295 296 (void) snprintf(signature, sizeof (signature), 297 "(L%s;Ljava/lang/String;)V", valueClass); 298 299 constructor = (*env)->GetMethodID( 300 env, class, "<init>", signature); 301 302 propertyObject = (*env)->NewObject(env, 303 class, constructor, propValue, propSource); 304 305 } else { 306 jobject lineage = zjni_int_to_Lineage(env, srctype); 307 308 (void) snprintf(signature, sizeof (signature), 309 "(L%s;L" ZFSJNI_PACKAGE_DATA "Property$Lineage;)V", 310 valueClass); 311 312 constructor = (*env)->GetMethodID( 313 env, class, "<init>", signature); 314 315 propertyObject = (*env)->NewObject(env, 316 class, constructor, propValue, lineage); 317 } 318 } 319 320 return (propertyObject); 321 } 322 323 static jobject 324 create_default_BasicProperty(JNIEnv *env, zfs_prop_t prop, 325 str_to_obj_f convert_str, uint64_to_obj_f convert_uint64, 326 char *propClass, char *valueClass) 327 { 328 jobject propertyObject = NULL; 329 330 if (!zfs_prop_readonly(prop)) { 331 jobject propValue; 332 333 if (convert_str != NULL) { 334 char *propbuf = (char *)zfs_prop_default_string(prop); 335 propValue = convert_str(env, propbuf); 336 } else { 337 uint64_t value = zfs_prop_default_numeric(prop); 338 propValue = convert_uint64(env, value); 339 } 340 341 if (propValue != NULL) { 342 char signature[1024]; 343 jmethodID constructor; 344 345 jstring propName = 346 (*env)->NewStringUTF(env, zfs_prop_to_name(prop)); 347 348 jboolean readOnly = zfs_prop_readonly(prop) ? 349 JNI_TRUE : JNI_FALSE; 350 351 jclass class = (*env)->FindClass(env, propClass); 352 jobject lineage = 353 zjni_int_to_Lineage(env, ZPROP_SRC_DEFAULT); 354 355 (void) snprintf(signature, sizeof (signature), 356 "(Ljava/lang/String;L%s;ZL" ZFSJNI_PACKAGE_DATA 357 "Property$Lineage;)V", valueClass); 358 359 constructor = (*env)->GetMethodID( 360 env, class, "<init>", signature); 361 362 propertyObject = (*env)->NewObject( 363 env, class, constructor, 364 propName, propValue, readOnly, lineage); 365 } 366 } 367 368 return (propertyObject); 369 } 370 371 static jobject 372 create_default_BooleanProperty(JNIEnv *env, zfs_prop_t prop) 373 { 374 return (create_default_BasicProperty(env, prop, NULL, 375 zjni_int_to_boolean, ZFSJNI_PACKAGE_DATA "BooleanProperty", 376 "java/lang/Boolean")); 377 } 378 379 static jobject 380 create_default_LongProperty(JNIEnv *env, zfs_prop_t prop) 381 { 382 return (create_default_BasicProperty(env, prop, NULL, 383 zjni_long_to_Long, ZFSJNI_PACKAGE_DATA "LongProperty", 384 "java/lang/Long")); 385 } 386 387 static jobject 388 create_default_StringProperty(JNIEnv *env, zfs_prop_t prop) 389 { 390 return (create_default_BasicProperty(env, prop, str_to_string, NULL, 391 ZFSJNI_PACKAGE_DATA "StringProperty", "java/lang/String")); 392 } 393 394 static jobject 395 create_default_ObjectProperty(JNIEnv *env, zfs_prop_t prop, 396 str_to_obj_f convert_str, uint64_to_obj_f convert_uint64, 397 char *propClass, char *valueClass) 398 { 399 jobject propertyObject = NULL; 400 401 if (!zfs_prop_readonly(prop)) { 402 jobject propValue; 403 404 if (convert_str != NULL) { 405 char *propbuf = (char *)zfs_prop_default_string(prop); 406 propValue = convert_str(env, propbuf); 407 } else { 408 uint64_t value = zfs_prop_default_numeric(prop); 409 propValue = convert_uint64(env, value); 410 } 411 412 if (propValue != NULL) { 413 char signature[1024]; 414 jmethodID constructor; 415 416 jclass class = (*env)->FindClass(env, propClass); 417 jobject lineage = 418 zjni_int_to_Lineage(env, ZPROP_SRC_DEFAULT); 419 420 (void) snprintf(signature, sizeof (signature), 421 "(L%s;L" ZFSJNI_PACKAGE_DATA "Property$Lineage;)V", 422 valueClass); 423 424 constructor = (*env)->GetMethodID( 425 env, class, "<init>", signature); 426 427 propertyObject = (*env)->NewObject( 428 env, class, constructor, propValue, lineage); 429 } 430 } 431 432 return (propertyObject); 433 } 434 435 static jobject 436 str_to_enum_element(JNIEnv *env, char *str, char *valueClass) 437 { 438 char signature[1024]; 439 jmethodID method_valueOf; 440 441 jstring utf = (*env)->NewStringUTF(env, str); 442 jclass class = (*env)->FindClass(env, valueClass); 443 444 (void) snprintf(signature, sizeof (signature), 445 "(Ljava/lang/String;)L%s;", valueClass); 446 447 method_valueOf = (*env)->GetStaticMethodID( 448 env, class, "valueOf", signature); 449 450 return (*env)->CallStaticObjectMethod(env, class, method_valueOf, utf); 451 } 452 453 static jobject 454 str_to_aclinherit(JNIEnv *env, char *str) 455 { 456 return (str_to_enum_element(env, str, 457 ZFSJNI_PACKAGE_DATA "AclInheritProperty$AclInherit")); 458 } 459 460 static jobject 461 str_to_aclmode(JNIEnv *env, char *str) 462 { 463 return (str_to_enum_element(env, str, 464 ZFSJNI_PACKAGE_DATA "AclModeProperty$AclMode")); 465 } 466 467 static jobject 468 str_to_checksum(JNIEnv *env, char *str) 469 { 470 return (str_to_enum_element(env, str, 471 ZFSJNI_PACKAGE_DATA "ChecksumProperty$Checksum")); 472 } 473 474 static jobject 475 str_to_compression(JNIEnv *env, char *str) 476 { 477 return (str_to_enum_element(env, str, 478 ZFSJNI_PACKAGE_DATA "CompressionProperty$Compression")); 479 } 480 481 static jobject 482 str_to_snapdir(JNIEnv *env, char *str) 483 { 484 return (str_to_enum_element(env, str, 485 ZFSJNI_PACKAGE_DATA "SnapDirProperty$SnapDir")); 486 } 487 488 static jobject 489 str_to_string(JNIEnv *env, char *str) 490 { 491 return (*env)->NewStringUTF(env, str); 492 } 493 494 /* 495 * Package-private functions 496 */ 497 498 jobject 499 zjni_get_default_property(JNIEnv *env, zfs_prop_t prop) 500 { 501 int i; 502 for (i = 0; props_boolean[i] != ZPROP_INVAL; i++) { 503 if (prop == props_boolean[i]) { 504 return (create_default_BooleanProperty(env, prop)); 505 } 506 } 507 508 for (i = 0; props_long[i] != ZPROP_INVAL; i++) { 509 if (prop == props_long[i]) { 510 return (create_default_LongProperty(env, prop)); 511 } 512 } 513 514 for (i = 0; props_string[i] != ZPROP_INVAL; i++) { 515 if (prop == props_string[i]) { 516 return (create_default_StringProperty(env, prop)); 517 } 518 } 519 520 for (i = 0; props_custom[i].prop != ZPROP_INVAL; i++) { 521 if (prop == props_custom[i].prop) { 522 return create_default_ObjectProperty(env, 523 props_custom[i].prop, 524 props_custom[i].convert_str, 525 props_custom[i].convert_uint64, 526 props_custom[i].propClass, 527 props_custom[i].valueClass); 528 } 529 } 530 531 return (NULL); 532 } 533 534 static int 535 zjni_get_property_from_name_cb(int prop, void *cb) 536 { 537 const char *name = cb; 538 539 if (strcasecmp(name, zfs_prop_to_name(prop)) == 0) 540 return (prop); 541 542 return (ZPROP_CONT); 543 } 544 545 zfs_prop_t 546 zjni_get_property_from_name(const char *name) 547 { 548 zfs_prop_t prop; 549 550 prop = zprop_iter(zjni_get_property_from_name_cb, (void *)name, 551 B_FALSE, B_FALSE, ZFS_TYPE_DATASET); 552 return (prop == ZPROP_CONT ? ZPROP_INVAL : prop); 553 } 554 555 jobject 556 zjni_int_to_Lineage(JNIEnv *env, zprop_source_t srctype) 557 { 558 /* zprop_source_t to Property$Lineage map */ 559 static zjni_field_mapping_t lineage_map[] = { 560 { ZPROP_SRC_NONE, "ZFS_PROP_LINEAGE_NOTINHERITABLE" }, 561 { ZPROP_SRC_DEFAULT, "ZFS_PROP_LINEAGE_DEFAULT" }, 562 { ZPROP_SRC_LOCAL, "ZFS_PROP_LINEAGE_LOCAL" }, 563 { ZPROP_SRC_TEMPORARY, "ZFS_PROP_LINEAGE_TEMPORARY" }, 564 { ZPROP_SRC_INHERITED, "ZFS_PROP_LINEAGE_INHERITED" } 565 }; 566 567 return (zjni_int_to_enum(env, srctype, 568 ZFSJNI_PACKAGE_DATA "Property$Lineage", 569 "ZFS_PROP_LINEAGE_INHERITED", lineage_map)); 570 } 571 572 jobjectArray 573 zjni_get_Dataset_properties(JNIEnv *env, zfs_handle_t *zhp) 574 { 575 jobject prop; 576 int i; 577 578 /* Create an array list for the properties */ 579 zjni_ArrayList_t proplist_obj = {0}; 580 zjni_ArrayList_t *proplist = &proplist_obj; 581 zjni_new_ArrayList(env, proplist); 582 583 for (i = 0; props_boolean[i] != ZPROP_INVAL; i++) { 584 /* Create property and add to list */ 585 prop = create_BooleanProperty(env, zhp, props_boolean[i]); 586 587 /* Does this property apply to this object? */ 588 if (prop != NULL) { 589 590 (*env)->CallBooleanMethod( 591 env, ((zjni_Object_t *)proplist)->object, 592 ((zjni_Collection_t *)proplist)->method_add, prop); 593 } else { 594 595 if ((*env)->ExceptionOccurred(env) != NULL) { 596 return (NULL); 597 } 598 #ifdef DEBUG 599 (void) fprintf(stderr, "Property %s is not appropriate " 600 "for %s\n", zfs_prop_to_name(props_boolean[i]), 601 zfs_get_name(zhp)); 602 #endif 603 } 604 } 605 606 for (i = 0; props_long[i] != ZPROP_INVAL; i++) { 607 /* Create property and add to list */ 608 prop = create_LongProperty(env, zhp, props_long[i]); 609 610 /* Does this property apply to this object? */ 611 if (prop != NULL) { 612 613 (*env)->CallBooleanMethod( 614 env, ((zjni_Object_t *)proplist)->object, 615 ((zjni_Collection_t *)proplist)->method_add, prop); 616 } else { 617 if ((*env)->ExceptionOccurred(env) != NULL) { 618 return (NULL); 619 } 620 #ifdef DEBUG 621 (void) fprintf(stderr, "Property %s is not appropriate " 622 "for %s\n", zfs_prop_to_name(props_long[i]), 623 zfs_get_name(zhp)); 624 #endif 625 } 626 } 627 628 for (i = 0; props_string[i] != ZPROP_INVAL; i++) { 629 /* Create property and add to list */ 630 prop = create_StringProperty(env, zhp, props_string[i]); 631 632 /* Does this property apply to this object? */ 633 if (prop != NULL) { 634 635 (*env)->CallBooleanMethod( 636 env, ((zjni_Object_t *)proplist)->object, 637 ((zjni_Collection_t *)proplist)->method_add, prop); 638 } else { 639 if ((*env)->ExceptionOccurred(env) != NULL) { 640 return (NULL); 641 } 642 #ifdef DEBUG 643 (void) fprintf(stderr, "Property %s is not appropriate " 644 "for %s\n", zfs_prop_to_name(props_string[i]), 645 zfs_get_name(zhp)); 646 #endif 647 } 648 } 649 650 for (i = 0; props_custom[i].prop != ZPROP_INVAL; i++) { 651 /* Create property and add to list */ 652 prop = create_ObjectProperty(env, zhp, props_custom[i].prop, 653 props_custom[i].convert_str, props_custom[i].convert_uint64, 654 props_custom[i].propClass, props_custom[i].valueClass); 655 656 /* Does this property apply to this object? */ 657 if (prop != NULL) { 658 659 (*env)->CallBooleanMethod( 660 env, ((zjni_Object_t *)proplist)->object, 661 ((zjni_Collection_t *)proplist)->method_add, prop); 662 } else { 663 if ((*env)->ExceptionOccurred(env) != NULL) { 664 return (NULL); 665 } 666 #ifdef DEBUG 667 (void) fprintf(stderr, "Property %s is not appropriate " 668 "for %s\n", zfs_prop_to_name(props_custom[i].prop), 669 zfs_get_name(zhp)); 670 #endif 671 } 672 } 673 674 return (zjni_Collection_to_array(env, 675 (zjni_Collection_t *)proplist, ZFSJNI_PACKAGE_DATA "Property")); 676 } 677