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