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