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 } else { 182 uint64_t value; 183 int result = zfs_prop_get_numeric( 184 zhp, prop, &value, &srctype, source, sizeof (source)); 185 186 if (result == 0) 187 propValue = convert_uint64(env, value); 188 } 189 190 if (propValue != NULL) { 191 192 jmethodID constructor; 193 char signature[1024]; 194 jclass class = (*env)->FindClass(env, propClass); 195 196 jstring propName = (*env)->NewStringUTF( 197 env, zfs_prop_to_name(prop)); 198 199 jboolean readOnly = zfs_prop_readonly(prop) ? 200 JNI_TRUE : JNI_FALSE; 201 202 if (srctype == ZFS_SRC_INHERITED) { 203 204 jstring propSource = (*env)->NewStringUTF(env, source); 205 206 (void) snprintf(signature, sizeof (signature), 207 "(Ljava/lang/String;L%s;ZLjava/lang/String;)V", 208 valueClass); 209 210 constructor = (*env)->GetMethodID( 211 env, class, "<init>", signature); 212 213 propertyObject = (*env)->NewObject( 214 env, class, constructor, propName, propValue, 215 readOnly, propSource); 216 } else { 217 jobject lineage = zjni_int_to_Lineage(env, srctype); 218 219 (void) snprintf(signature, sizeof (signature), 220 "(Ljava/lang/String;L%s;ZL" 221 ZFSJNI_PACKAGE_DATA "Property$Lineage;)V", 222 valueClass); 223 224 constructor = (*env)->GetMethodID( 225 env, class, "<init>", signature); 226 227 propertyObject = (*env)->NewObject( 228 env, class, constructor, propName, propValue, 229 readOnly, lineage); 230 } 231 } 232 233 return (propertyObject); 234 } 235 236 static jobject 237 create_BooleanProperty(JNIEnv *env, zfs_handle_t *zhp, zfs_prop_t prop) 238 { 239 return (create_BasicProperty(env, zhp, prop, NULL, zjni_int_to_boolean, 240 ZFSJNI_PACKAGE_DATA "BooleanProperty", "java/lang/Boolean")); 241 } 242 243 static jobject 244 create_LongProperty(JNIEnv *env, zfs_handle_t *zhp, zfs_prop_t prop) 245 { 246 return (create_BasicProperty(env, zhp, prop, NULL, zjni_long_to_Long, 247 ZFSJNI_PACKAGE_DATA "LongProperty", "java/lang/Long")); 248 } 249 250 static jobject 251 create_StringProperty(JNIEnv *env, zfs_handle_t *zhp, zfs_prop_t prop) 252 { 253 return (create_BasicProperty(env, zhp, prop, str_to_string, NULL, 254 ZFSJNI_PACKAGE_DATA "StringProperty", "java/lang/String")); 255 } 256 257 static jobject 258 create_ObjectProperty(JNIEnv *env, zfs_handle_t *zhp, zfs_prop_t prop, 259 str_to_obj_f convert_str, uint64_to_obj_f convert_uint64, 260 char *propClass, char *valueClass) 261 { 262 jobject propertyObject = NULL; 263 char source[ZFS_MAXNAMELEN]; 264 zfs_source_t srctype; 265 jobject propValue = NULL; 266 267 if (convert_str != NULL) { 268 char propbuf[ZFS_MAXPROPLEN]; 269 int result = zfs_prop_get(zhp, prop, propbuf, 270 sizeof (propbuf), &srctype, source, sizeof (source), 1); 271 272 if (result == 0) 273 propValue = convert_str(env, propbuf); 274 } else { 275 uint64_t value; 276 int result = zfs_prop_get_numeric( 277 zhp, prop, &value, &srctype, source, sizeof (source)); 278 279 if (result == 0) 280 propValue = convert_uint64(env, value); 281 } 282 283 if (propValue != NULL) { 284 285 jmethodID constructor; 286 char signature[1024]; 287 jclass class = (*env)->FindClass(env, propClass); 288 289 if (srctype == ZFS_SRC_INHERITED) { 290 291 jstring propSource = (*env)->NewStringUTF(env, source); 292 293 (void) snprintf(signature, sizeof (signature), 294 "(L%s;Ljava/lang/String;)V", valueClass); 295 296 constructor = (*env)->GetMethodID( 297 env, class, "<init>", signature); 298 299 propertyObject = (*env)->NewObject(env, 300 class, constructor, propValue, propSource); 301 302 } else { 303 jobject lineage = zjni_int_to_Lineage(env, srctype); 304 305 (void) snprintf(signature, sizeof (signature), 306 "(L%s;L" ZFSJNI_PACKAGE_DATA "Property$Lineage;)V", 307 valueClass); 308 309 constructor = (*env)->GetMethodID( 310 env, class, "<init>", signature); 311 312 propertyObject = (*env)->NewObject(env, 313 class, constructor, propValue, lineage); 314 } 315 } 316 317 return (propertyObject); 318 } 319 320 static jobject 321 create_default_BasicProperty(JNIEnv *env, zfs_prop_t prop, 322 str_to_obj_f convert_str, uint64_to_obj_f convert_uint64, 323 char *propClass, char *valueClass) 324 { 325 jobject propertyObject = NULL; 326 327 if (!zfs_prop_readonly(prop)) { 328 jobject propValue; 329 330 if (convert_str != NULL) { 331 char *propbuf = (char *)zfs_prop_default_string(prop); 332 propValue = convert_str(env, propbuf); 333 } else { 334 uint64_t value = zfs_prop_default_numeric(prop); 335 propValue = convert_uint64(env, value); 336 } 337 338 if (propValue != NULL) { 339 char signature[1024]; 340 jmethodID constructor; 341 342 jstring propName = 343 (*env)->NewStringUTF(env, zfs_prop_to_name(prop)); 344 345 jboolean readOnly = zfs_prop_readonly(prop) ? 346 JNI_TRUE : JNI_FALSE; 347 348 jclass class = (*env)->FindClass(env, propClass); 349 jobject lineage = 350 zjni_int_to_Lineage(env, ZFS_SRC_DEFAULT); 351 352 (void) snprintf(signature, sizeof (signature), 353 "(Ljava/lang/String;L%s;ZL" ZFSJNI_PACKAGE_DATA 354 "Property$Lineage;)V", valueClass); 355 356 constructor = (*env)->GetMethodID( 357 env, class, "<init>", signature); 358 359 propertyObject = (*env)->NewObject( 360 env, class, constructor, 361 propName, propValue, readOnly, lineage); 362 } 363 } 364 365 return (propertyObject); 366 } 367 368 static jobject 369 create_default_BooleanProperty(JNIEnv *env, zfs_prop_t prop) 370 { 371 return (create_default_BasicProperty(env, prop, NULL, 372 zjni_int_to_boolean, ZFSJNI_PACKAGE_DATA "BooleanProperty", 373 "java/lang/Boolean")); 374 } 375 376 static jobject 377 create_default_LongProperty(JNIEnv *env, zfs_prop_t prop) 378 { 379 return (create_default_BasicProperty(env, prop, NULL, 380 zjni_long_to_Long, ZFSJNI_PACKAGE_DATA "LongProperty", 381 "java/lang/Long")); 382 } 383 384 static jobject 385 create_default_StringProperty(JNIEnv *env, zfs_prop_t prop) 386 { 387 return (create_default_BasicProperty(env, prop, str_to_string, NULL, 388 ZFSJNI_PACKAGE_DATA "StringProperty", "java/lang/String")); 389 } 390 391 static jobject 392 create_default_ObjectProperty(JNIEnv *env, zfs_prop_t prop, 393 str_to_obj_f convert_str, uint64_to_obj_f convert_uint64, 394 char *propClass, char *valueClass) 395 { 396 jobject propertyObject = NULL; 397 398 if (!zfs_prop_readonly(prop)) { 399 jobject propValue; 400 401 if (convert_str != NULL) { 402 char *propbuf = (char *)zfs_prop_default_string(prop); 403 propValue = convert_str(env, propbuf); 404 } else { 405 uint64_t value = zfs_prop_default_numeric(prop); 406 propValue = convert_uint64(env, value); 407 } 408 409 if (propValue != NULL) { 410 char signature[1024]; 411 jmethodID constructor; 412 413 jclass class = (*env)->FindClass(env, propClass); 414 jobject lineage = 415 zjni_int_to_Lineage(env, ZFS_SRC_DEFAULT); 416 417 (void) snprintf(signature, sizeof (signature), 418 "(L%s;L" ZFSJNI_PACKAGE_DATA "Property$Lineage;)V", 419 valueClass); 420 421 constructor = (*env)->GetMethodID( 422 env, class, "<init>", signature); 423 424 propertyObject = (*env)->NewObject( 425 env, class, constructor, propValue, lineage); 426 } 427 } 428 429 return (propertyObject); 430 } 431 432 static jobject 433 str_to_enum_element(JNIEnv *env, char *str, char *valueClass) 434 { 435 char signature[1024]; 436 jmethodID method_valueOf; 437 438 jstring utf = (*env)->NewStringUTF(env, str); 439 jclass class = (*env)->FindClass(env, valueClass); 440 441 (void) snprintf(signature, sizeof (signature), 442 "(Ljava/lang/String;)L%s;", valueClass); 443 444 method_valueOf = (*env)->GetStaticMethodID( 445 env, class, "valueOf", signature); 446 447 return (*env)->CallStaticObjectMethod(env, class, method_valueOf, utf); 448 } 449 450 static jobject 451 str_to_aclinherit(JNIEnv *env, char *str) 452 { 453 return (str_to_enum_element(env, str, 454 ZFSJNI_PACKAGE_DATA "AclInheritProperty$AclInherit")); 455 } 456 457 static jobject 458 str_to_aclmode(JNIEnv *env, char *str) 459 { 460 return (str_to_enum_element(env, str, 461 ZFSJNI_PACKAGE_DATA "AclModeProperty$AclMode")); 462 } 463 464 static jobject 465 str_to_checksum(JNIEnv *env, char *str) 466 { 467 return (str_to_enum_element(env, str, 468 ZFSJNI_PACKAGE_DATA "ChecksumProperty$Checksum")); 469 } 470 471 static jobject 472 str_to_compression(JNIEnv *env, char *str) 473 { 474 return (str_to_enum_element(env, str, 475 ZFSJNI_PACKAGE_DATA "CompressionProperty$Compression")); 476 } 477 478 static jobject 479 str_to_snapdir(JNIEnv *env, char *str) 480 { 481 return (str_to_enum_element(env, str, 482 ZFSJNI_PACKAGE_DATA "SnapDirProperty$SnapDir")); 483 } 484 485 static jobject 486 str_to_string(JNIEnv *env, char *str) 487 { 488 return (*env)->NewStringUTF(env, str); 489 } 490 491 /* 492 * Package-private functions 493 */ 494 495 jobject 496 zjni_get_default_property(JNIEnv *env, zfs_prop_t prop) 497 { 498 int i; 499 for (i = 0; props_boolean[i] != ZFS_PROP_INVAL; i++) { 500 if (prop == props_boolean[i]) { 501 return (create_default_BooleanProperty(env, prop)); 502 } 503 } 504 505 for (i = 0; props_long[i] != ZFS_PROP_INVAL; i++) { 506 if (prop == props_long[i]) { 507 return (create_default_LongProperty(env, prop)); 508 } 509 } 510 511 for (i = 0; props_string[i] != ZFS_PROP_INVAL; i++) { 512 if (prop == props_string[i]) { 513 return (create_default_StringProperty(env, prop)); 514 } 515 } 516 517 for (i = 0; props_custom[i].prop != ZFS_PROP_INVAL; i++) { 518 if (prop == props_custom[i].prop) { 519 return create_default_ObjectProperty(env, 520 props_custom[i].prop, 521 props_custom[i].convert_str, 522 props_custom[i].convert_uint64, 523 props_custom[i].propClass, 524 props_custom[i].valueClass); 525 } 526 } 527 528 return (NULL); 529 } 530 531 static zfs_prop_t 532 zjni_get_property_from_name_cb(zfs_prop_t prop, void *cb) 533 { 534 const char *name = cb; 535 536 if (strcasecmp(name, zfs_prop_to_name(prop)) == 0) 537 return (prop); 538 539 return (ZFS_PROP_CONT); 540 } 541 542 zfs_prop_t 543 zjni_get_property_from_name(const char *name) 544 { 545 zfs_prop_t prop; 546 547 prop = zfs_prop_iter(zjni_get_property_from_name_cb, (void *)name); 548 return (prop == ZFS_PROP_CONT ? ZFS_PROP_INVAL : prop); 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