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 = (char *)zfs_prop_default_string(prop); 337 propValue = convert_str(env, propbuf); 338 } else { 339 uint64_t value = zfs_prop_default_numeric(prop); 340 propValue = convert_uint64(env, value); 341 } 342 343 if (propValue != NULL) { 344 char signature[1024]; 345 jmethodID constructor; 346 347 jstring propName = 348 (*env)->NewStringUTF(env, zfs_prop_to_name(prop)); 349 350 jboolean readOnly = zfs_prop_readonly(prop) ? 351 JNI_TRUE : JNI_FALSE; 352 353 jclass class = (*env)->FindClass(env, propClass); 354 jobject lineage = 355 zjni_int_to_Lineage(env, ZFS_SRC_DEFAULT); 356 357 (void) snprintf(signature, sizeof (signature), 358 "(Ljava/lang/String;L%s;ZL" ZFSJNI_PACKAGE_DATA 359 "Property$Lineage;)V", valueClass); 360 361 constructor = (*env)->GetMethodID( 362 env, class, "<init>", signature); 363 364 propertyObject = (*env)->NewObject( 365 env, class, constructor, 366 propName, propValue, readOnly, lineage); 367 } 368 } 369 370 return (propertyObject); 371 } 372 373 static jobject 374 create_default_BooleanProperty(JNIEnv *env, zfs_prop_t prop) 375 { 376 return (create_default_BasicProperty(env, prop, NULL, 377 zjni_int_to_boolean, ZFSJNI_PACKAGE_DATA "BooleanProperty", 378 "java/lang/Boolean")); 379 } 380 381 static jobject 382 create_default_LongProperty(JNIEnv *env, zfs_prop_t prop) 383 { 384 return (create_default_BasicProperty(env, prop, NULL, 385 zjni_long_to_Long, ZFSJNI_PACKAGE_DATA "LongProperty", 386 "java/lang/Long")); 387 } 388 389 static jobject 390 create_default_StringProperty(JNIEnv *env, zfs_prop_t prop) 391 { 392 return (create_default_BasicProperty(env, prop, str_to_string, NULL, 393 ZFSJNI_PACKAGE_DATA "StringProperty", "java/lang/String")); 394 } 395 396 static jobject 397 create_default_ObjectProperty(JNIEnv *env, zfs_prop_t prop, 398 str_to_obj_f convert_str, uint64_to_obj_f convert_uint64, 399 char *propClass, char *valueClass) 400 { 401 jobject propertyObject = NULL; 402 403 if (!zfs_prop_readonly(prop)) { 404 jobject propValue; 405 406 if (convert_str != NULL) { 407 char *propbuf = (char *)zfs_prop_default_string(prop); 408 propValue = convert_str(env, propbuf); 409 } else { 410 uint64_t value = zfs_prop_default_numeric(prop); 411 propValue = convert_uint64(env, value); 412 } 413 414 if (propValue != NULL) { 415 char signature[1024]; 416 jmethodID constructor; 417 418 jclass class = (*env)->FindClass(env, propClass); 419 jobject lineage = 420 zjni_int_to_Lineage(env, ZFS_SRC_DEFAULT); 421 422 (void) snprintf(signature, sizeof (signature), 423 "(L%s;L" ZFSJNI_PACKAGE_DATA "Property$Lineage;)V", 424 valueClass); 425 426 constructor = (*env)->GetMethodID( 427 env, class, "<init>", signature); 428 429 propertyObject = (*env)->NewObject( 430 env, class, constructor, propValue, lineage); 431 } 432 } 433 434 return (propertyObject); 435 } 436 437 static jobject 438 str_to_enum_element(JNIEnv *env, char *str, char *valueClass) 439 { 440 char signature[1024]; 441 jmethodID method_valueOf; 442 443 jstring utf = (*env)->NewStringUTF(env, str); 444 jclass class = (*env)->FindClass(env, valueClass); 445 446 (void) snprintf(signature, sizeof (signature), 447 "(Ljava/lang/String;)L%s;", valueClass); 448 449 method_valueOf = (*env)->GetStaticMethodID( 450 env, class, "valueOf", signature); 451 452 return (*env)->CallStaticObjectMethod(env, class, method_valueOf, utf); 453 } 454 455 static jobject 456 str_to_aclinherit(JNIEnv *env, char *str) 457 { 458 return (str_to_enum_element(env, str, 459 ZFSJNI_PACKAGE_DATA "AclInheritProperty$AclInherit")); 460 } 461 462 static jobject 463 str_to_aclmode(JNIEnv *env, char *str) 464 { 465 return (str_to_enum_element(env, str, 466 ZFSJNI_PACKAGE_DATA "AclModeProperty$AclMode")); 467 } 468 469 static jobject 470 str_to_checksum(JNIEnv *env, char *str) 471 { 472 return (str_to_enum_element(env, str, 473 ZFSJNI_PACKAGE_DATA "ChecksumProperty$Checksum")); 474 } 475 476 static jobject 477 str_to_compression(JNIEnv *env, char *str) 478 { 479 return (str_to_enum_element(env, str, 480 ZFSJNI_PACKAGE_DATA "CompressionProperty$Compression")); 481 } 482 483 static jobject 484 str_to_snapdir(JNIEnv *env, char *str) 485 { 486 return (str_to_enum_element(env, str, 487 ZFSJNI_PACKAGE_DATA "SnapDirProperty$SnapDir")); 488 } 489 490 static jobject 491 str_to_string(JNIEnv *env, char *str) 492 { 493 return (*env)->NewStringUTF(env, str); 494 } 495 496 /* 497 * Package-private functions 498 */ 499 500 jobject 501 zjni_get_default_property(JNIEnv *env, zfs_prop_t prop) 502 { 503 int i; 504 for (i = 0; props_boolean[i] != ZFS_PROP_INVAL; i++) { 505 if (prop == props_boolean[i]) { 506 return (create_default_BooleanProperty(env, prop)); 507 } 508 } 509 510 for (i = 0; props_long[i] != ZFS_PROP_INVAL; i++) { 511 if (prop == props_long[i]) { 512 return (create_default_LongProperty(env, prop)); 513 } 514 } 515 516 for (i = 0; props_string[i] != ZFS_PROP_INVAL; i++) { 517 if (prop == props_string[i]) { 518 return (create_default_StringProperty(env, prop)); 519 } 520 } 521 522 for (i = 0; props_custom[i].prop != ZFS_PROP_INVAL; i++) { 523 if (prop == props_custom[i].prop) { 524 return create_default_ObjectProperty(env, 525 props_custom[i].prop, props_custom[i].convert_str, 526 props_custom[i].convert_uint64, 527 props_custom[i].propClass, props_custom[i].valueClass); 528 } 529 } 530 531 return (NULL); 532 } 533 534 zfs_prop_t 535 zjni_get_property_from_name(const char *name) 536 { 537 zfs_prop_t prop; 538 for (prop = 0; prop < ZFS_NPROP_VISIBLE; prop++) { 539 if (strcasecmp(name, zfs_prop_to_name(prop)) == 0) { 540 return (prop); 541 } 542 } 543 544 return (ZFS_PROP_INVAL); 545 } 546 547 jobject 548 zjni_int_to_Lineage(JNIEnv *env, zfs_source_t srctype) 549 { 550 /* zfs_source_t to Property$Lineage map */ 551 static zjni_field_mapping_t lineage_map[] = { 552 { ZFS_SRC_NONE, "ZFS_PROP_LINEAGE_NOTINHERITABLE" }, 553 { ZFS_SRC_DEFAULT, "ZFS_PROP_LINEAGE_DEFAULT" }, 554 { ZFS_SRC_LOCAL, "ZFS_PROP_LINEAGE_LOCAL" }, 555 { ZFS_SRC_TEMPORARY, "ZFS_PROP_LINEAGE_TEMPORARY" }, 556 { ZFS_SRC_INHERITED, "ZFS_PROP_LINEAGE_INHERITED" } 557 }; 558 559 return (zjni_int_to_enum(env, srctype, 560 ZFSJNI_PACKAGE_DATA "Property$Lineage", 561 "ZFS_PROP_LINEAGE_INHERITED", lineage_map)); 562 } 563 564 jobjectArray 565 zjni_get_Dataset_properties(JNIEnv *env, zfs_handle_t *zhp) 566 { 567 jobject prop; 568 int i; 569 570 /* Create an array list for the properties */ 571 zjni_ArrayList_t proplist_obj = {0}; 572 zjni_ArrayList_t *proplist = &proplist_obj; 573 zjni_new_ArrayList(env, proplist); 574 575 for (i = 0; props_boolean[i] != ZFS_PROP_INVAL; i++) { 576 /* Create property and add to list */ 577 prop = create_BooleanProperty(env, zhp, props_boolean[i]); 578 579 /* Does this property apply to this object? */ 580 if (prop != NULL) { 581 582 (*env)->CallBooleanMethod( 583 env, ((zjni_Object_t *)proplist)->object, 584 ((zjni_Collection_t *)proplist)->method_add, prop); 585 } else { 586 587 if ((*env)->ExceptionOccurred(env) != NULL) { 588 return (NULL); 589 } 590 #ifdef DEBUG 591 (void) fprintf(stderr, "Property %s is not appropriate " 592 "for %s\n", zfs_prop_to_name(props_boolean[i]), 593 zfs_get_name(zhp)); 594 #endif 595 } 596 } 597 598 for (i = 0; props_long[i] != ZFS_PROP_INVAL; i++) { 599 /* Create property and add to list */ 600 prop = create_LongProperty(env, zhp, props_long[i]); 601 602 /* Does this property apply to this object? */ 603 if (prop != NULL) { 604 605 (*env)->CallBooleanMethod( 606 env, ((zjni_Object_t *)proplist)->object, 607 ((zjni_Collection_t *)proplist)->method_add, prop); 608 } else { 609 if ((*env)->ExceptionOccurred(env) != NULL) { 610 return (NULL); 611 } 612 #ifdef DEBUG 613 (void) fprintf(stderr, "Property %s is not appropriate " 614 "for %s\n", zfs_prop_to_name(props_long[i]), 615 zfs_get_name(zhp)); 616 #endif 617 } 618 } 619 620 for (i = 0; props_string[i] != ZFS_PROP_INVAL; i++) { 621 /* Create property and add to list */ 622 prop = create_StringProperty(env, zhp, props_string[i]); 623 624 /* Does this property apply to this object? */ 625 if (prop != NULL) { 626 627 (*env)->CallBooleanMethod( 628 env, ((zjni_Object_t *)proplist)->object, 629 ((zjni_Collection_t *)proplist)->method_add, prop); 630 } else { 631 if ((*env)->ExceptionOccurred(env) != NULL) { 632 return (NULL); 633 } 634 #ifdef DEBUG 635 (void) fprintf(stderr, "Property %s is not appropriate " 636 "for %s\n", zfs_prop_to_name(props_string[i]), 637 zfs_get_name(zhp)); 638 #endif 639 } 640 } 641 642 for (i = 0; props_custom[i].prop != ZFS_PROP_INVAL; i++) { 643 /* Create property and add to list */ 644 prop = create_ObjectProperty(env, zhp, props_custom[i].prop, 645 props_custom[i].convert_str, props_custom[i].convert_uint64, 646 props_custom[i].propClass, props_custom[i].valueClass); 647 648 /* Does this property apply to this object? */ 649 if (prop != NULL) { 650 651 (*env)->CallBooleanMethod( 652 env, ((zjni_Object_t *)proplist)->object, 653 ((zjni_Collection_t *)proplist)->method_add, prop); 654 } else { 655 if ((*env)->ExceptionOccurred(env) != NULL) { 656 return (NULL); 657 } 658 #ifdef DEBUG 659 (void) fprintf(stderr, "Property %s is not appropriate " 660 "for %s\n", zfs_prop_to_name(props_custom[i].prop), 661 zfs_get_name(zhp)); 662 #endif 663 } 664 } 665 666 return (zjni_Collection_to_array(env, 667 (zjni_Collection_t *)proplist, ZFSJNI_PACKAGE_DATA "Property")); 668 } 669