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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2006 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_property.h" 30 #include "libzfs_jni_util.h" 31 #include <strings.h> 32 33 /* 34 * Types 35 */ 36 37 /* Signature for function to convert string to a specific Java object */ 38 typedef jobject (*str_to_obj_f)(JNIEnv *, char *); 39 40 /* Signature for function to convert uint64_t to a specific Java object */ 41 typedef jobject (*uint64_to_obj_f)(JNIEnv *, uint64_t); 42 43 /* 44 * Describes a property and the parameters needed to create a Java 45 * Property object for it 46 */ 47 typedef struct custom_prop_desct { 48 zfs_prop_t prop; 49 str_to_obj_f convert_str; 50 uint64_to_obj_f convert_uint64; 51 char *propClass; 52 char *valueClass; 53 } custom_prop_desct_t; 54 55 /* 56 * Function prototypes 57 */ 58 59 static jobject create_BasicProperty(JNIEnv *, zfs_handle_t *, 60 zfs_prop_t, str_to_obj_f, uint64_to_obj_f, char *, char *); 61 static jobject create_BooleanProperty(JNIEnv *, zfs_handle_t *, zfs_prop_t); 62 static jobject create_LongProperty(JNIEnv *, zfs_handle_t *, zfs_prop_t); 63 static jobject create_StringProperty(JNIEnv *, zfs_handle_t *, zfs_prop_t); 64 static jobject create_ObjectProperty(JNIEnv *, zfs_handle_t *, 65 zfs_prop_t, str_to_obj_f, uint64_to_obj_f, char *, char *); 66 static jobject create_default_BasicProperty(JNIEnv *, zfs_prop_t, 67 str_to_obj_f, uint64_to_obj_f, char *, char *); 68 static jobject create_default_BooleanProperty(JNIEnv *, zfs_prop_t); 69 static jobject create_default_LongProperty(JNIEnv *, zfs_prop_t); 70 static jobject create_default_StringProperty(JNIEnv *, zfs_prop_t); 71 static jobject create_default_ObjectProperty( 72 JNIEnv *, zfs_prop_t, str_to_obj_f, uint64_to_obj_f, char *, char *); 73 static jobject str_to_enum_element(JNIEnv *, char *, char *); 74 static jobject str_to_aclinherit(JNIEnv *, char *); 75 static jobject str_to_aclmode(JNIEnv *, char *); 76 static jobject str_to_checksum(JNIEnv *, char *); 77 static jobject str_to_compression(JNIEnv *, char *); 78 static jobject str_to_snapdir(JNIEnv *, char *); 79 static jobject str_to_string(JNIEnv *, char *); 80 81 /* 82 * Static data 83 */ 84 85 zfs_prop_t props_boolean[] = { 86 ZFS_PROP_ATIME, 87 ZFS_PROP_DEVICES, 88 ZFS_PROP_EXEC, 89 ZFS_PROP_MOUNTED, 90 ZFS_PROP_READONLY, 91 ZFS_PROP_SETUID, 92 ZFS_PROP_ZONED, 93 ZFS_PROP_INVAL 94 }; 95 96 zfs_prop_t props_long[] = { 97 ZFS_PROP_AVAILABLE, 98 ZFS_PROP_CREATETXG, 99 ZFS_PROP_QUOTA, 100 ZFS_PROP_REFERENCED, 101 ZFS_PROP_RESERVATION, 102 ZFS_PROP_USED, 103 ZFS_PROP_VOLSIZE, 104 ZFS_PROP_INVAL 105 }; 106 107 zfs_prop_t props_string[] = { 108 ZFS_PROP_ORIGIN, 109 /* ZFS_PROP_TYPE, */ 110 ZFS_PROP_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 { ZFS_PROP_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 zfs_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 } 183 } else { 184 uint64_t value; 185 int result = zfs_prop_get_numeric( 186 zhp, prop, &value, &srctype, source, sizeof (source)); 187 188 if (result == 0) { 189 propValue = convert_uint64(env, value); 190 } 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 == ZFS_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_MAXNAMELEN]; 267 zfs_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 } 278 } else { 279 uint64_t value; 280 int result = zfs_prop_get_numeric( 281 zhp, prop, &value, &srctype, source, sizeof (source)); 282 283 if (result == 0) { 284 propValue = convert_uint64(env, value); 285 } 286 } 287 288 if (propValue != NULL) { 289 290 jmethodID constructor; 291 char signature[1024]; 292 jclass class = (*env)->FindClass(env, propClass); 293 294 if (srctype == ZFS_SRC_INHERITED) { 295 296 jstring propSource = (*env)->NewStringUTF(env, source); 297 298 (void) snprintf(signature, sizeof (signature), 299 "(L%s;Ljava/lang/String;)V", valueClass); 300 301 constructor = (*env)->GetMethodID( 302 env, class, "<init>", signature); 303 304 propertyObject = (*env)->NewObject(env, 305 class, constructor, propValue, propSource); 306 307 } else { 308 jobject lineage = zjni_int_to_Lineage(env, srctype); 309 310 (void) snprintf(signature, sizeof (signature), 311 "(L%s;L" ZFSJNI_PACKAGE_DATA "Property$Lineage;)V", 312 valueClass); 313 314 constructor = (*env)->GetMethodID( 315 env, class, "<init>", signature); 316 317 propertyObject = (*env)->NewObject(env, 318 class, constructor, propValue, lineage); 319 } 320 } 321 322 return (propertyObject); 323 } 324 325 static jobject 326 create_default_BasicProperty(JNIEnv *env, zfs_prop_t prop, 327 str_to_obj_f convert_str, uint64_to_obj_f convert_uint64, 328 char *propClass, char *valueClass) 329 { 330 jobject propertyObject = NULL; 331 332 if (!zfs_prop_readonly(prop)) { 333 jobject propValue; 334 335 if (convert_str != NULL) { 336 char propbuf[ZFS_MAXPROPLEN]; 337 zfs_prop_default_string( 338 prop, propbuf, sizeof (propbuf)); 339 propValue = convert_str(env, propbuf); 340 } else { 341 uint64_t value = zfs_prop_default_numeric(prop); 342 propValue = convert_uint64(env, value); 343 } 344 345 if (propValue != NULL) { 346 char signature[1024]; 347 jmethodID constructor; 348 349 jstring propName = 350 (*env)->NewStringUTF(env, zfs_prop_to_name(prop)); 351 352 jboolean readOnly = zfs_prop_readonly(prop) ? 353 JNI_TRUE : JNI_FALSE; 354 355 jclass class = (*env)->FindClass(env, propClass); 356 jobject lineage = 357 zjni_int_to_Lineage(env, ZFS_SRC_DEFAULT); 358 359 (void) snprintf(signature, sizeof (signature), 360 "(Ljava/lang/String;L%s;ZL" ZFSJNI_PACKAGE_DATA 361 "Property$Lineage;)V", valueClass); 362 363 constructor = (*env)->GetMethodID( 364 env, class, "<init>", signature); 365 366 propertyObject = (*env)->NewObject( 367 env, class, constructor, 368 propName, propValue, readOnly, lineage); 369 } 370 } 371 372 return (propertyObject); 373 } 374 375 static jobject 376 create_default_BooleanProperty(JNIEnv *env, zfs_prop_t prop) 377 { 378 return (create_default_BasicProperty(env, prop, NULL, 379 zjni_int_to_boolean, ZFSJNI_PACKAGE_DATA "BooleanProperty", 380 "java/lang/Boolean")); 381 } 382 383 static jobject 384 create_default_LongProperty(JNIEnv *env, zfs_prop_t prop) 385 { 386 return (create_default_BasicProperty(env, prop, NULL, 387 zjni_long_to_Long, ZFSJNI_PACKAGE_DATA "LongProperty", 388 "java/lang/Long")); 389 } 390 391 static jobject 392 create_default_StringProperty(JNIEnv *env, zfs_prop_t prop) 393 { 394 return (create_default_BasicProperty(env, prop, str_to_string, NULL, 395 ZFSJNI_PACKAGE_DATA "StringProperty", "java/lang/String")); 396 } 397 398 static jobject 399 create_default_ObjectProperty(JNIEnv *env, zfs_prop_t prop, 400 str_to_obj_f convert_str, uint64_to_obj_f convert_uint64, 401 char *propClass, char *valueClass) 402 { 403 jobject propertyObject = NULL; 404 405 if (!zfs_prop_readonly(prop)) { 406 jobject propValue; 407 408 if (convert_str != NULL) { 409 char propbuf[ZFS_MAXPROPLEN]; 410 zfs_prop_default_string( 411 prop, propbuf, sizeof (propbuf)); 412 propValue = convert_str(env, propbuf); 413 } else { 414 uint64_t value = zfs_prop_default_numeric(prop); 415 propValue = convert_uint64(env, value); 416 } 417 418 if (propValue != NULL) { 419 char signature[1024]; 420 jmethodID constructor; 421 422 jclass class = (*env)->FindClass(env, propClass); 423 jobject lineage = 424 zjni_int_to_Lineage(env, ZFS_SRC_DEFAULT); 425 426 (void) snprintf(signature, sizeof (signature), 427 "(L%s;L" ZFSJNI_PACKAGE_DATA "Property$Lineage;)V", 428 valueClass); 429 430 constructor = (*env)->GetMethodID( 431 env, class, "<init>", signature); 432 433 propertyObject = (*env)->NewObject( 434 env, class, constructor, propValue, lineage); 435 } 436 } 437 438 return (propertyObject); 439 } 440 441 static jobject 442 str_to_enum_element(JNIEnv *env, char *str, char *valueClass) 443 { 444 char signature[1024]; 445 jmethodID method_valueOf; 446 447 jstring utf = (*env)->NewStringUTF(env, str); 448 jclass class = (*env)->FindClass(env, valueClass); 449 450 (void) snprintf(signature, sizeof (signature), 451 "(Ljava/lang/String;)L%s;", valueClass); 452 453 method_valueOf = (*env)->GetStaticMethodID( 454 env, class, "valueOf", signature); 455 456 return (*env)->CallStaticObjectMethod(env, class, method_valueOf, utf); 457 } 458 459 static jobject 460 str_to_aclinherit(JNIEnv *env, char *str) 461 { 462 return (str_to_enum_element(env, str, 463 ZFSJNI_PACKAGE_DATA "AclInheritProperty$AclInherit")); 464 } 465 466 static jobject 467 str_to_aclmode(JNIEnv *env, char *str) 468 { 469 return (str_to_enum_element(env, str, 470 ZFSJNI_PACKAGE_DATA "AclModeProperty$AclMode")); 471 } 472 473 static jobject 474 str_to_checksum(JNIEnv *env, char *str) 475 { 476 return (str_to_enum_element(env, str, 477 ZFSJNI_PACKAGE_DATA "ChecksumProperty$Checksum")); 478 } 479 480 static jobject 481 str_to_compression(JNIEnv *env, char *str) 482 { 483 return (str_to_enum_element(env, str, 484 ZFSJNI_PACKAGE_DATA "CompressionProperty$Compression")); 485 } 486 487 static jobject 488 str_to_snapdir(JNIEnv *env, char *str) 489 { 490 return (str_to_enum_element(env, str, 491 ZFSJNI_PACKAGE_DATA "SnapDirProperty$SnapDir")); 492 } 493 494 static jobject 495 str_to_string(JNIEnv *env, char *str) 496 { 497 return (*env)->NewStringUTF(env, str); 498 } 499 500 /* 501 * Package-private functions 502 */ 503 504 jobject 505 zjni_get_default_property(JNIEnv *env, zfs_prop_t prop) 506 { 507 int i; 508 for (i = 0; props_boolean[i] != ZFS_PROP_INVAL; i++) { 509 if (prop == props_boolean[i]) { 510 return (create_default_BooleanProperty(env, prop)); 511 } 512 } 513 514 for (i = 0; props_long[i] != ZFS_PROP_INVAL; i++) { 515 if (prop == props_long[i]) { 516 return (create_default_LongProperty(env, prop)); 517 } 518 } 519 520 for (i = 0; props_string[i] != ZFS_PROP_INVAL; i++) { 521 if (prop == props_string[i]) { 522 return (create_default_StringProperty(env, prop)); 523 } 524 } 525 526 for (i = 0; props_custom[i].prop != ZFS_PROP_INVAL; i++) { 527 if (prop == props_custom[i].prop) { 528 return create_default_ObjectProperty(env, 529 props_custom[i].prop, props_custom[i].convert_str, 530 props_custom[i].convert_uint64, 531 props_custom[i].propClass, props_custom[i].valueClass); 532 } 533 } 534 535 return (NULL); 536 } 537 538 zfs_prop_t 539 zjni_get_property_from_name(const char *name) 540 { 541 zfs_prop_t prop; 542 for (prop = 0; prop < ZFS_NPROP_VISIBLE; prop++) { 543 if (strcasecmp(name, zfs_prop_to_name(prop)) == 0) { 544 return (prop); 545 } 546 } 547 548 return (ZFS_PROP_INVAL); 549 } 550 551 jobject 552 zjni_int_to_Lineage(JNIEnv *env, zfs_source_t srctype) 553 { 554 /* zfs_source_t to Property$Lineage map */ 555 static zjni_field_mapping_t lineage_map[] = { 556 { ZFS_SRC_NONE, "ZFS_PROP_LINEAGE_NOTINHERITABLE" }, 557 { ZFS_SRC_DEFAULT, "ZFS_PROP_LINEAGE_DEFAULT" }, 558 { ZFS_SRC_LOCAL, "ZFS_PROP_LINEAGE_LOCAL" }, 559 { ZFS_SRC_TEMPORARY, "ZFS_PROP_LINEAGE_TEMPORARY" }, 560 { ZFS_SRC_INHERITED, "ZFS_PROP_LINEAGE_INHERITED" } 561 }; 562 563 return (zjni_int_to_enum(env, srctype, 564 ZFSJNI_PACKAGE_DATA "Property$Lineage", 565 "ZFS_PROP_LINEAGE_INHERITED", lineage_map)); 566 } 567 568 jobjectArray 569 zjni_get_Dataset_properties(JNIEnv *env, zfs_handle_t *zhp) 570 { 571 jobject prop; 572 int i; 573 574 /* Create an array list for the properties */ 575 zjni_ArrayList_t proplist_obj = {0}; 576 zjni_ArrayList_t *proplist = &proplist_obj; 577 zjni_new_ArrayList(env, proplist); 578 579 for (i = 0; props_boolean[i] != ZFS_PROP_INVAL; i++) { 580 /* Create property and add to list */ 581 prop = create_BooleanProperty(env, zhp, props_boolean[i]); 582 583 /* Does this property apply to this object? */ 584 if (prop != NULL) { 585 586 (*env)->CallBooleanMethod( 587 env, ((zjni_Object_t *)proplist)->object, 588 ((zjni_Collection_t *)proplist)->method_add, prop); 589 } else { 590 591 if ((*env)->ExceptionOccurred(env) != NULL) { 592 return (NULL); 593 } 594 #ifdef DEBUG 595 (void) fprintf(stderr, "Property %s is not appropriate " 596 "for %s\n", zfs_prop_to_name(props_boolean[i]), 597 zfs_get_name(zhp)); 598 #endif 599 } 600 } 601 602 for (i = 0; props_long[i] != ZFS_PROP_INVAL; i++) { 603 /* Create property and add to list */ 604 prop = create_LongProperty(env, zhp, props_long[i]); 605 606 /* Does this property apply to this object? */ 607 if (prop != NULL) { 608 609 (*env)->CallBooleanMethod( 610 env, ((zjni_Object_t *)proplist)->object, 611 ((zjni_Collection_t *)proplist)->method_add, prop); 612 } else { 613 if ((*env)->ExceptionOccurred(env) != NULL) { 614 return (NULL); 615 } 616 #ifdef DEBUG 617 (void) fprintf(stderr, "Property %s is not appropriate " 618 "for %s\n", zfs_prop_to_name(props_long[i]), 619 zfs_get_name(zhp)); 620 #endif 621 } 622 } 623 624 for (i = 0; props_string[i] != ZFS_PROP_INVAL; i++) { 625 /* Create property and add to list */ 626 prop = create_StringProperty(env, zhp, props_string[i]); 627 628 /* Does this property apply to this object? */ 629 if (prop != NULL) { 630 631 (*env)->CallBooleanMethod( 632 env, ((zjni_Object_t *)proplist)->object, 633 ((zjni_Collection_t *)proplist)->method_add, prop); 634 } else { 635 if ((*env)->ExceptionOccurred(env) != NULL) { 636 return (NULL); 637 } 638 #ifdef DEBUG 639 (void) fprintf(stderr, "Property %s is not appropriate " 640 "for %s\n", zfs_prop_to_name(props_string[i]), 641 zfs_get_name(zhp)); 642 #endif 643 } 644 } 645 646 for (i = 0; props_custom[i].prop != ZFS_PROP_INVAL; i++) { 647 /* Create property and add to list */ 648 prop = create_ObjectProperty(env, zhp, props_custom[i].prop, 649 props_custom[i].convert_str, props_custom[i].convert_uint64, 650 props_custom[i].propClass, props_custom[i].valueClass); 651 652 /* Does this property apply to this object? */ 653 if (prop != NULL) { 654 655 (*env)->CallBooleanMethod( 656 env, ((zjni_Object_t *)proplist)->object, 657 ((zjni_Collection_t *)proplist)->method_add, prop); 658 } else { 659 if ((*env)->ExceptionOccurred(env) != NULL) { 660 return (NULL); 661 } 662 #ifdef DEBUG 663 (void) fprintf(stderr, "Property %s is not appropriate " 664 "for %s\n", zfs_prop_to_name(props_custom[i].prop), 665 zfs_get_name(zhp)); 666 #endif 667 } 668 } 669 670 return (zjni_Collection_to_array(env, 671 (zjni_Collection_t *)proplist, ZFSJNI_PACKAGE_DATA "Property")); 672 } 673