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