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_util.h" 30 #include <strings.h> 31 32 /* 33 * Package-private functions 34 */ 35 36 void 37 zjni_free_array(void **array, zjni_free_f freefunc) 38 { 39 if (array != NULL) { 40 if (freefunc != NULL) { 41 int i; 42 for (i = 0; array[i] != NULL; i++) { 43 freefunc(array[i]); 44 } 45 } 46 free(array); 47 } 48 } 49 50 /*PRINTFLIKE2*/ 51 void 52 zjni_throw_exception(JNIEnv *env, const char *fmt, ...) 53 { 54 char error[1024]; 55 va_list ap; 56 jclass class_UnsupportedOperationException; 57 58 va_start(ap, fmt); 59 (void) vsnprintf(error, sizeof (error), fmt, ap); 60 va_end(ap); 61 62 class_UnsupportedOperationException = 63 (*env)->FindClass(env, "java/lang/UnsupportedOperationException"); 64 65 (*env)->ThrowNew(env, class_UnsupportedOperationException, error); 66 } 67 68 jstring 69 zjni_get_matched_string(JNIEnv *env, char *name, regmatch_t *match) 70 { 71 jstring stringUTF = NULL; 72 if (match->rm_so != -1 && match->rm_eo != -1) { 73 char *end = name + match->rm_eo; 74 char tmp = *end; 75 *end = '\0'; 76 stringUTF = (*env)->NewStringUTF(env, name + match->rm_so); 77 *end = tmp; 78 } 79 return (stringUTF); 80 } 81 82 void 83 zjni_get_dataset_from_snapshot(const char *snapshot, char *dataset, 84 size_t len) 85 { 86 char *at; 87 (void) strncpy(dataset, snapshot, len); 88 at = strchr(dataset, '@'); 89 if (at != NULL) { 90 *at = '\0'; 91 } 92 } 93 94 /* Convert a zjni_Collection to a (Java) array */ 95 jobjectArray 96 zjni_Collection_to_array(JNIEnv *env, zjni_Collection_t *list, char *class) 97 { 98 /* Get size of zjni_Collection */ 99 jint length = (*env)->CallIntMethod( 100 env, ((zjni_Object_t *)list)->object, 101 ((zjni_Collection_t *)list)->method_size); 102 103 /* Create array to hold elements of list */ 104 jobjectArray array = (*env)->NewObjectArray( 105 env, length, (*env)->FindClass(env, class), NULL); 106 107 /* Copy list elements to array */ 108 return (*env)->CallObjectMethod(env, ((zjni_Object_t *)list)->object, 109 ((zjni_Collection_t *)list)->method_toArray, array); 110 } 111 112 /* Create a zjni_Collection */ 113 void 114 new_Collection(JNIEnv *env, zjni_Collection_t *collection) 115 { 116 zjni_Object_t *object = (zjni_Object_t *)collection; 117 118 collection->method_add = (*env)->GetMethodID( 119 env, object->class, "add", "(Ljava/lang/Object;)Z"); 120 121 collection->method_size = 122 (*env)->GetMethodID(env, object->class, "size", "()I"); 123 124 collection->method_toArray = 125 (*env)->GetMethodID(env, object->class, "toArray", 126 "([Ljava/lang/Object;)[Ljava/lang/Object;"); 127 } 128 129 /* Create an zjni_ArrayList */ 130 void 131 zjni_new_ArrayList(JNIEnv *env, zjni_ArrayList_t *list) 132 { 133 zjni_Object_t *object = (zjni_Object_t *)list; 134 135 if (object->object == NULL) { 136 object->class = (*env)->FindClass(env, "java/util/ArrayList"); 137 138 object->constructor = 139 (*env)->GetMethodID(env, object->class, "<init>", "()V"); 140 141 object->object = (*env)->NewObject( 142 env, object->class, object->constructor); 143 } 144 145 new_Collection(env, (zjni_Collection_t *)list); 146 } 147 148 /* Create an zjni_DatasetSet */ 149 void 150 zjni_new_DatasetSet(JNIEnv *env, zjni_DatasetSet_t *list) 151 { 152 zjni_Object_t *object = (zjni_Object_t *)list; 153 154 if (object->object == NULL) { 155 object->class = (*env)->FindClass( 156 env, "com/sun/zfs/common/util/DatasetSet"); 157 158 object->constructor = 159 (*env)->GetMethodID(env, object->class, "<init>", "()V"); 160 161 object->object = (*env)->NewObject( 162 env, object->class, object->constructor); 163 } 164 165 new_Collection(env, (zjni_Collection_t *)list); 166 } 167 168 jobject 169 zjni_int_to_boolean(JNIEnv *env, uint64_t value) 170 { 171 jclass class_Boolean = (*env)->FindClass( 172 env, "java/lang/Boolean"); 173 174 jfieldID id = (*env)->GetStaticFieldID(env, class_Boolean, 175 value ? "TRUE" : "FALSE", "Ljava/lang/Boolean;"); 176 177 return (*env)->GetStaticObjectField(env, class_Boolean, id); 178 } 179 180 jobject 181 zjni_int_to_enum(JNIEnv *env, int value, char *class_name, 182 char *default_field_name, zjni_field_mapping_t *mapping) 183 { 184 int i; 185 char *field_name; 186 jclass class; 187 jfieldID id; 188 jobject field_value = NULL; 189 int found = 0; 190 191 for (i = 0; mapping[i].name != NULL; i++) { 192 if (value == mapping[i].value) { 193 field_name = mapping[i].name; 194 found = 1; 195 break; 196 } 197 } 198 199 if (!found) { 200 field_name = default_field_name; 201 } 202 203 if (field_name != NULL) { 204 char signature[1024]; 205 206 (void) snprintf(signature, sizeof (signature), "L%s;", 207 class_name); 208 209 class = (*env)->FindClass(env, class_name); 210 id = (*env)->GetStaticFieldID( 211 env, class, field_name, signature); 212 field_value = (*env)->GetStaticObjectField(env, class, id); 213 } 214 215 return (field_value); 216 } 217 218 jobject 219 zjni_str_to_long(JNIEnv *env, char *str) 220 { 221 jobject value = NULL; 222 jclass class_Long = (*env)->FindClass(env, "java/lang/Long"); 223 224 jmethodID method_valueOf = (*env)->GetStaticMethodID(env, 225 class_Long, "valueOf", "(Ljava/lang/String;)Ljava/lang/Long;"); 226 227 jstring utf = (*env)->NewStringUTF(env, str); 228 229 /* May throw a NumberFormatException */ 230 value = (*env)->CallStaticObjectMethod( 231 env, class_Long, method_valueOf, utf); 232 233 return (value); 234 } 235 236 jobject 237 zjni_long_to_Long(JNIEnv *env, uint64_t value) 238 { 239 jclass class_Long = (*env)->FindClass(env, "java/lang/Long"); 240 241 jmethodID constructor_Long = (*env)->GetMethodID( 242 env, class_Long, "<init>", "(J)V"); 243 244 jobject obj = (*env)->NewObject( 245 env, class_Long, constructor_Long, value); 246 247 return (obj); 248 } 249 250 jobject 251 zjni_str_to_date(JNIEnv *env, char *str) 252 { 253 jobject date = NULL; 254 jclass class_Long = (*env)->FindClass(env, "java/lang/Long"); 255 256 jmethodID method_parseLong = (*env)->GetStaticMethodID(env, 257 class_Long, "parseLong", "(Ljava/lang/String;)J"); 258 259 jstring utf = (*env)->NewStringUTF(env, str); 260 if (utf != NULL) { 261 262 /* May throw a NumberFormatException */ 263 jlong time = (*env)->CallStaticLongMethod( 264 env, class_Long, method_parseLong, utf); 265 266 if ((*env)->ExceptionOccurred(env) == NULL) { 267 268 jclass class_Date = (*env)->FindClass(env, 269 "java/util/Date"); 270 271 jmethodID constructor_Date = (*env)->GetMethodID( 272 env, class_Date, "<init>", "(J)V"); 273 274 /* Date constructor takes epoch milliseconds */ 275 time *= 1000; 276 277 date = (*env)->NewObject( 278 env, class_Date, constructor_Date, time); 279 } 280 } 281 282 return (date); 283 } 284 285 jobjectArray 286 zjni_c_string_array_to_java(JNIEnv *env, char **array, int n) 287 { 288 int i; 289 jclass class_String = (*env)->FindClass(env, "java/lang/String"); 290 jobjectArray jarray = 291 (*env)->NewObjectArray(env, n, class_String, NULL); 292 293 for (i = 0; i < n; i++) { 294 jstring elementUTF = (*env)->NewStringUTF(env, array[i]); 295 (void) (*env)->SetObjectArrayElement(env, jarray, i, 296 elementUTF); 297 } 298 299 return (jarray); 300 } 301 302 /* 303 * Converts the non-null elements of the given Java String array into 304 * a NULL-terminated char* array. When done, each element and then 305 * the array itself must be free()d. Returns NULL if memory could not 306 * be allocated. 307 */ 308 char ** 309 zjni_java_string_array_to_c(JNIEnv *env, jobjectArray array) 310 { 311 int i, n; 312 jsize length = (*env)->GetArrayLength(env, array); 313 char **result = (char **)calloc(length + 1, sizeof (char *)); 314 315 if (result != NULL) { 316 for (i = 0, n = 0; i < length; i++) { 317 jboolean isCopy; 318 319 /* Retrive String from array */ 320 jstring string = (*env)->GetObjectArrayElement( 321 env, array, i); 322 323 if (string != NULL) { 324 /* Convert to char* */ 325 const char *converted = 326 (*env)->GetStringUTFChars(env, string, 327 &isCopy); 328 329 result[n] = strdup(converted); 330 331 if (isCopy == JNI_TRUE) { 332 /* Free chars in Java space */ 333 (void) (*env)->ReleaseStringUTFChars( 334 env, string, converted); 335 } 336 337 if (result[n++] == NULL) { 338 /* strdup failed */ 339 zjni_free_array((void *)result, free); 340 break; 341 } 342 } 343 } 344 345 /* Terminate array */ 346 result[n] = NULL; 347 } 348 349 return (result); 350 } 351 352 /* 353 * Counts the number of elements in the given NULL-terminated array. 354 * Does not include the terminating NULL in the count. 355 */ 356 int 357 zjni_count_elements(void **array) 358 { 359 int i = 0; 360 if (array != NULL) { 361 for (; array[i] != NULL; i++); 362 } 363 return (i); 364 } 365 366 /* 367 * Get a handle to the next nvpair with the specified name and data 368 * type in the list following the given nvpair. 369 * 370 * This function is needed because the nvlist_lookup_* routines can 371 * only be used with nvlists allocated with NV_UNIQUE_NAME or 372 * NV_UNIQUE_NAME_TYPE, ie. lists of unique name/value pairs. 373 * 374 * Some variation of this function will likely appear in the libnvpair 375 * library per 4981923. 376 * 377 * @param nvl 378 * the nvlist_t to search 379 * 380 * @param name 381 * the string key for the pair to find in the list, or 382 * NULL to match any name 383 * 384 * @param type 385 * the data type for the pair to find in the list, or 386 * DATA_TYPE_UNKNOWN to match any type 387 * 388 * @param nvp 389 * the pair to search from in the list, or NULL to search 390 * from the beginning of the list 391 * 392 * @return the next nvpair in the list matching the given 393 * criteria, or NULL if no matching nvpair is found 394 */ 395 nvpair_t * 396 zjni_nvlist_walk_nvpair(nvlist_t *nvl, const char *name, data_type_t type, 397 nvpair_t *nvp) 398 { 399 /* For each nvpair in the list following nvp... */ 400 while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) { 401 402 /* Does this pair's name match the given name? */ 403 if ((name == NULL || strcmp(nvpair_name(nvp), name) == 0) && 404 405 /* Does this pair's type match the given type? */ 406 (type == DATA_TYPE_UNKNOWN || type == nvpair_type(nvp))) { 407 return (nvp); 408 } 409 } 410 411 return (NULL); 412 } 413