1*1449Stomee /* 2*1449Stomee * CDDL HEADER START 3*1449Stomee * 4*1449Stomee * The contents of this file are subject to the terms of the 5*1449Stomee * Common Development and Distribution License (the "License"). 6*1449Stomee * You may not use this file except in compliance with the License. 7*1449Stomee * 8*1449Stomee * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*1449Stomee * or http://www.opensolaris.org/os/licensing. 10*1449Stomee * See the License for the specific language governing permissions 11*1449Stomee * and limitations under the License. 12*1449Stomee * 13*1449Stomee * When distributing Covered Code, include this CDDL HEADER in each 14*1449Stomee * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*1449Stomee * If applicable, add the following below this CDDL HEADER, with the 16*1449Stomee * fields enclosed by brackets "[]" replaced with your own identifying 17*1449Stomee * information: Portions Copyright [yyyy] [name of copyright owner] 18*1449Stomee * 19*1449Stomee * CDDL HEADER END 20*1449Stomee */ 21*1449Stomee 22*1449Stomee /* 23*1449Stomee * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24*1449Stomee * Use is subject to license terms. 25*1449Stomee */ 26*1449Stomee 27*1449Stomee #pragma ident "%Z%%M% %I% %E% SMI" 28*1449Stomee 29*1449Stomee #include <stdlib.h> 30*1449Stomee #include <stddef.h> 31*1449Stomee #include <sys/types.h> 32*1449Stomee #include <pthread.h> 33*1449Stomee #include <string.h> 34*1449Stomee #include <dtj_util.h> 35*1449Stomee 36*1449Stomee /* 37*1449Stomee * dtj_util.c separates functionality that is generally useful from 38*1449Stomee * that which is specific to the Java DTrace API. If moved to a separate 39*1449Stomee * library, this functionality could be shared by other JNI wrappers. 40*1449Stomee */ 41*1449Stomee 42*1449Stomee boolean_t g_dtj_util_debug = B_FALSE; 43*1449Stomee static boolean_t g_dtj_load_common = B_FALSE; 44*1449Stomee 45*1449Stomee /* NativeException */ 46*1449Stomee jclass g_nx_jc = 0; 47*1449Stomee jmethodID g_nxinit_jm = 0; 48*1449Stomee 49*1449Stomee /* java.io.Serializable */ 50*1449Stomee jclass g_serial_jc = 0; 51*1449Stomee 52*1449Stomee /* java.lang.Number */ 53*1449Stomee jclass g_number_jc = 0; 54*1449Stomee jmethodID g_shortval_jm = 0; 55*1449Stomee jmethodID g_intval_jm = 0; 56*1449Stomee jmethodID g_longval_jm = 0; 57*1449Stomee 58*1449Stomee /* java.lang.Byte */ 59*1449Stomee jclass g_byte_jc = 0; 60*1449Stomee jmethodID g_byteinit_jm = 0; 61*1449Stomee 62*1449Stomee /* java.lang.Character */ 63*1449Stomee jclass g_char_jc = 0; 64*1449Stomee jmethodID g_charinit_jm = 0; 65*1449Stomee jmethodID g_charval_jm = 0; 66*1449Stomee 67*1449Stomee /* java.lang.Short */ 68*1449Stomee jclass g_short_jc = 0; 69*1449Stomee jmethodID g_shortinit_jm = 0; 70*1449Stomee 71*1449Stomee /* java.lang.Integer */ 72*1449Stomee jclass g_int_jc = 0; 73*1449Stomee jmethodID g_intinit_jm = 0; 74*1449Stomee 75*1449Stomee /* java.lang.Long */ 76*1449Stomee jclass g_long_jc = 0; 77*1449Stomee jmethodID g_longinit_jm = 0; 78*1449Stomee 79*1449Stomee /* java.lang.String */ 80*1449Stomee jclass g_string_jc = 0; 81*1449Stomee jmethodID g_strinit_bytes_jm = 0; 82*1449Stomee jmethodID g_strbytes_jm = 0; 83*1449Stomee jmethodID g_trim_jm = 0; 84*1449Stomee 85*1449Stomee /* java.lang.StringBuffer */ 86*1449Stomee jclass g_buf_jc = 0; 87*1449Stomee jmethodID g_bufinit_jm = 0; 88*1449Stomee jmethodID g_buf_append_char_jm = 0; 89*1449Stomee jmethodID g_buf_append_int_jm = 0; 90*1449Stomee jmethodID g_buf_append_long_jm = 0; 91*1449Stomee jmethodID g_buf_append_str_jm = 0; 92*1449Stomee jmethodID g_buf_append_obj_jm = 0; 93*1449Stomee jmethodID g_buflen_jm = 0; 94*1449Stomee jmethodID g_bufsetlen_jm = 0; 95*1449Stomee 96*1449Stomee /* java.lang.Object */ 97*1449Stomee jclass g_object_jc = 0; 98*1449Stomee jmethodID g_tostring_jm = 0; 99*1449Stomee jmethodID g_equals_jm = 0; 100*1449Stomee 101*1449Stomee /* java.lang.Enum */ 102*1449Stomee jclass g_enum_jc = 0; 103*1449Stomee jmethodID g_enumname_jm = 0; 104*1449Stomee 105*1449Stomee /* List */ 106*1449Stomee jclass g_list_jc = 0; 107*1449Stomee jmethodID g_listclear_jm = 0; 108*1449Stomee jmethodID g_listadd_jm = 0; 109*1449Stomee jmethodID g_listget_jm = 0; 110*1449Stomee jmethodID g_listsize_jm = 0; 111*1449Stomee 112*1449Stomee /* Global list pools */ 113*1449Stomee static uu_list_pool_t *g_pointer_pool = NULL; 114*1449Stomee static uu_list_pool_t *g_string_pool = NULL; 115*1449Stomee 116*1449Stomee static dtj_status_t dtj_get_jni_classes(JNIEnv *, uu_list_t *, uu_list_pool_t *, 117*1449Stomee uu_list_pool_t *, uu_list_pool_t *, const dtj_table_entry_t *); 118*1449Stomee static dtj_status_t dtj_cache_jni_methods(JNIEnv *, dtj_java_class_t *); 119*1449Stomee static dtj_status_t dtj_cache_jni_fields(JNIEnv *, dtj_java_class_t *); 120*1449Stomee 121*1449Stomee /* Constructors */ 122*1449Stomee static dtj_java_class_t *dtj_java_class_create(JNIEnv *, jclass *, char *, 123*1449Stomee uu_list_pool_t *, uu_list_pool_t *, uu_list_pool_t *); 124*1449Stomee static dtj_java_method_t *dtj_java_method_create(JNIEnv *, jmethodID *, char *, 125*1449Stomee char *, uu_list_pool_t *); 126*1449Stomee static dtj_java_method_t *dtj_java_static_method_create(JNIEnv *, jmethodID *, 127*1449Stomee char *, char *, uu_list_pool_t *); 128*1449Stomee static dtj_java_field_t *dtj_java_field_create(JNIEnv *, jfieldID *, char *, 129*1449Stomee char *, uu_list_pool_t *); 130*1449Stomee static dtj_java_field_t *dtj_java_static_field_create(JNIEnv *, jfieldID *, 131*1449Stomee char *, char *, uu_list_pool_t *); 132*1449Stomee 133*1449Stomee /* Destructors */ 134*1449Stomee static void dtj_java_class_destroy(void *, void *); 135*1449Stomee static void dtj_java_method_destroy(void *, void *); 136*1449Stomee static void dtj_java_field_destroy(void *, void *); 137*1449Stomee 138*1449Stomee /* Comparison functions, uu_compare_fn_t signature */ 139*1449Stomee static int dtj_java_class_cmp(const void *, const void *, void *); 140*1449Stomee static int dtj_java_method_cmp(const void *, const void *, void *); 141*1449Stomee static int dtj_java_field_cmp(const void *, const void *, void *); 142*1449Stomee 143*1449Stomee /* Java Throwable */ 144*1449Stomee static void dtj_throw(JNIEnv *, jclass, const char *, va_list *); 145*1449Stomee 146*1449Stomee /* Support for uu_list_t wrappers */ 147*1449Stomee static boolean_t dtj_check_pointer_pool(void); 148*1449Stomee static boolean_t dtj_check_string_pool(void); 149*1449Stomee 150*1449Stomee dtj_status_t 151*1449Stomee dtj_load_common(JNIEnv *jenv) 152*1449Stomee { 153*1449Stomee dtj_status_t status; 154*1449Stomee 155*1449Stomee static const dtj_table_entry_t table[] = { 156*1449Stomee /* NativeException */ 157*1449Stomee { JCLASS, &g_nx_jc, 158*1449Stomee "org/opensolaris/os/dtrace/NativeException" }, 159*1449Stomee { JMETHOD, &g_nxinit_jm, CONSTRUCTOR, 160*1449Stomee "(Ljava/lang/String;ILjava/lang/Throwable;)V" }, 161*1449Stomee 162*1449Stomee /* java.io.Serializable */ 163*1449Stomee { JCLASS, &g_serial_jc, "java/io/Serializable" }, 164*1449Stomee 165*1449Stomee /* java.lang.Number */ 166*1449Stomee { JCLASS, &g_number_jc, "java/lang/Number" }, 167*1449Stomee { JMETHOD, &g_shortval_jm, "shortValue", "()S" }, 168*1449Stomee { JMETHOD, &g_intval_jm, "intValue", "()I" }, 169*1449Stomee { JMETHOD, &g_longval_jm, "longValue", "()J" }, 170*1449Stomee 171*1449Stomee /* java.lang.Byte */ 172*1449Stomee { JCLASS, &g_byte_jc, "java/lang/Byte" }, 173*1449Stomee { JMETHOD, &g_byteinit_jm, CONSTRUCTOR, "(B)V" }, 174*1449Stomee 175*1449Stomee /* java.lang.Character */ 176*1449Stomee { JCLASS, &g_char_jc, "java/lang/Character" }, 177*1449Stomee { JMETHOD, &g_charinit_jm, CONSTRUCTOR, "(C)V" }, 178*1449Stomee { JMETHOD, &g_charval_jm, "charValue", "()C" }, 179*1449Stomee 180*1449Stomee /* java.lang.Short */ 181*1449Stomee { JCLASS, &g_short_jc, "java/lang/Short" }, 182*1449Stomee { JMETHOD, &g_shortinit_jm, CONSTRUCTOR, "(S)V" }, 183*1449Stomee 184*1449Stomee /* java.lang.Integer */ 185*1449Stomee { JCLASS, &g_int_jc, "java/lang/Integer" }, 186*1449Stomee { JMETHOD, &g_intinit_jm, CONSTRUCTOR, "(I)V" }, 187*1449Stomee 188*1449Stomee /* java.lang.Long */ 189*1449Stomee { JCLASS, &g_long_jc, "java/lang/Long" }, 190*1449Stomee { JMETHOD, &g_longinit_jm, CONSTRUCTOR, "(J)V" }, 191*1449Stomee 192*1449Stomee /* java.lang.String */ 193*1449Stomee { JCLASS, &g_string_jc, "java/lang/String" }, 194*1449Stomee { JMETHOD, &g_strinit_bytes_jm, CONSTRUCTOR, "([B)V" }, 195*1449Stomee { JMETHOD, &g_strbytes_jm, "getBytes", "()[B" }, 196*1449Stomee { JMETHOD, &g_trim_jm, "trim", "()Ljava/lang/String;" }, 197*1449Stomee 198*1449Stomee /* java.lang.StringBuffer */ 199*1449Stomee { JCLASS, &g_buf_jc, "java/lang/StringBuffer" }, 200*1449Stomee { JMETHOD, &g_bufinit_jm, CONSTRUCTOR, "()V" }, 201*1449Stomee { JMETHOD, &g_buf_append_char_jm, "append", 202*1449Stomee "(C)Ljava/lang/StringBuffer;" }, 203*1449Stomee { JMETHOD, &g_buf_append_int_jm, "append", 204*1449Stomee "(I)Ljava/lang/StringBuffer;" }, 205*1449Stomee { JMETHOD, &g_buf_append_long_jm, "append", 206*1449Stomee "(J)Ljava/lang/StringBuffer;" }, 207*1449Stomee { JMETHOD, &g_buf_append_str_jm, "append", 208*1449Stomee "(Ljava/lang/String;)Ljava/lang/StringBuffer;" }, 209*1449Stomee { JMETHOD, &g_buf_append_obj_jm, "append", 210*1449Stomee "(Ljava/lang/Object;)Ljava/lang/StringBuffer;" }, 211*1449Stomee { JMETHOD, &g_buflen_jm, "length", "()I" }, 212*1449Stomee { JMETHOD, &g_bufsetlen_jm, "setLength", "(I)V" }, 213*1449Stomee 214*1449Stomee /* java.lang.Object */ 215*1449Stomee { JCLASS, &g_object_jc, "java/lang/Object" }, 216*1449Stomee { JMETHOD, &g_tostring_jm, "toString", 217*1449Stomee "()Ljava/lang/String;" }, 218*1449Stomee { JMETHOD, &g_equals_jm, "equals", 219*1449Stomee "(Ljava/lang/Object;)Z" }, 220*1449Stomee 221*1449Stomee /* java.lang.Enum */ 222*1449Stomee { JCLASS, &g_enum_jc, "java/lang/Enum" }, 223*1449Stomee { JMETHOD, &g_enumname_jm, "name", 224*1449Stomee "()Ljava/lang/String;" }, 225*1449Stomee 226*1449Stomee /* List */ 227*1449Stomee { JCLASS, &g_list_jc, "java/util/List" }, 228*1449Stomee { JMETHOD, &g_listclear_jm, "clear", "()V" }, 229*1449Stomee { JMETHOD, &g_listadd_jm, "add", "(Ljava/lang/Object;)Z" }, 230*1449Stomee { JMETHOD, &g_listget_jm, "get", "(I)Ljava/lang/Object;" }, 231*1449Stomee { JMETHOD, &g_listsize_jm, "size", "()I" }, 232*1449Stomee 233*1449Stomee { DTJ_TYPE_END } 234*1449Stomee }; 235*1449Stomee 236*1449Stomee status = dtj_cache_jni_classes(jenv, table); 237*1449Stomee if (status == DTJ_OK) { 238*1449Stomee g_dtj_load_common = B_TRUE; 239*1449Stomee } 240*1449Stomee return (status); 241*1449Stomee } 242*1449Stomee 243*1449Stomee static int 244*1449Stomee /* ARGSUSED */ 245*1449Stomee dtj_java_class_cmp(const void * v1, const void * v2, void *arg) 246*1449Stomee { 247*1449Stomee const dtj_java_class_t *c1 = v1; 248*1449Stomee const dtj_java_class_t *c2 = v2; 249*1449Stomee return (strcmp(c1->djc_name, c2->djc_name)); 250*1449Stomee } 251*1449Stomee 252*1449Stomee static int 253*1449Stomee /* ARGSUSED */ 254*1449Stomee dtj_java_method_cmp(const void *v1, const void *v2, void *arg) 255*1449Stomee { 256*1449Stomee int cmp; 257*1449Stomee const dtj_java_method_t *m1 = v1; 258*1449Stomee const dtj_java_method_t *m2 = v2; 259*1449Stomee cmp = strcmp(m1->djm_name, m2->djm_name); 260*1449Stomee if (cmp == 0) { 261*1449Stomee cmp = strcmp(m1->djm_signature, m2->djm_signature); 262*1449Stomee } 263*1449Stomee return (cmp); 264*1449Stomee } 265*1449Stomee 266*1449Stomee static int 267*1449Stomee /* ARGSUSED */ 268*1449Stomee dtj_java_field_cmp(const void *v1, const void *v2, void *arg) 269*1449Stomee { 270*1449Stomee const dtj_java_field_t *f1 = v1; 271*1449Stomee const dtj_java_field_t *f2 = v2; 272*1449Stomee return (strcmp(f1->djf_name, f2->djf_name)); 273*1449Stomee } 274*1449Stomee 275*1449Stomee static dtj_java_class_t * 276*1449Stomee dtj_java_class_create(JNIEnv *jenv, jclass *jc, char *name, 277*1449Stomee uu_list_pool_t *classpool, uu_list_pool_t *methodpool, 278*1449Stomee uu_list_pool_t *fieldpool) 279*1449Stomee { 280*1449Stomee dtj_java_class_t *c = uu_zalloc(sizeof (dtj_java_class_t)); 281*1449Stomee if (c) { 282*1449Stomee uu_list_node_init(c, &c->djc_node, classpool); 283*1449Stomee c->djc_ptr = jc; 284*1449Stomee c->djc_name = name; 285*1449Stomee c->djc_methods = uu_list_create(methodpool, NULL, 286*1449Stomee (g_dtj_util_debug ? UU_LIST_DEBUG : 0)); 287*1449Stomee if (!c->djc_methods) { 288*1449Stomee dtj_throw_out_of_memory(jenv, 289*1449Stomee "Failed method list creation"); 290*1449Stomee uu_list_node_fini(c, &c->djc_node, classpool); 291*1449Stomee free(c); 292*1449Stomee c = NULL; 293*1449Stomee } 294*1449Stomee c->djc_fields = uu_list_create(fieldpool, NULL, 295*1449Stomee (g_dtj_util_debug ? UU_LIST_DEBUG : 0)); 296*1449Stomee if (!c->djc_fields) { 297*1449Stomee dtj_throw_out_of_memory(jenv, 298*1449Stomee "Failed field list creation"); 299*1449Stomee uu_list_destroy(c->djc_methods); 300*1449Stomee c->djc_methods = NULL; 301*1449Stomee uu_list_node_fini(c, &c->djc_node, classpool); 302*1449Stomee free(c); 303*1449Stomee c = NULL; 304*1449Stomee } 305*1449Stomee } else { 306*1449Stomee dtj_throw_out_of_memory(jenv, 307*1449Stomee "Failed to allocate class description"); 308*1449Stomee } 309*1449Stomee return (c); 310*1449Stomee } 311*1449Stomee 312*1449Stomee static dtj_java_method_t * 313*1449Stomee dtj_java_method_create(JNIEnv *jenv, jmethodID *jm, char *name, char *signature, 314*1449Stomee uu_list_pool_t *methodpool) 315*1449Stomee { 316*1449Stomee dtj_java_method_t *m = uu_zalloc(sizeof (dtj_java_method_t)); 317*1449Stomee if (m) { 318*1449Stomee uu_list_node_init(m, &m->djm_node, methodpool); 319*1449Stomee m->djm_ptr = jm; 320*1449Stomee m->djm_name = name; 321*1449Stomee m->djm_signature = signature; 322*1449Stomee m->djm_static = B_FALSE; 323*1449Stomee } else { 324*1449Stomee dtj_throw_out_of_memory(jenv, 325*1449Stomee "Failed to allocate method description"); 326*1449Stomee } 327*1449Stomee return (m); 328*1449Stomee } 329*1449Stomee 330*1449Stomee static dtj_java_method_t * 331*1449Stomee dtj_java_static_method_create(JNIEnv *jenv, jmethodID *jm, char *name, 332*1449Stomee char *signature, uu_list_pool_t *methodpool) 333*1449Stomee { 334*1449Stomee dtj_java_method_t *m = dtj_java_method_create(jenv, jm, name, signature, 335*1449Stomee methodpool); 336*1449Stomee if (m) { 337*1449Stomee m->djm_static = B_TRUE; 338*1449Stomee } 339*1449Stomee return (m); 340*1449Stomee } 341*1449Stomee 342*1449Stomee static dtj_java_field_t * 343*1449Stomee dtj_java_field_create(JNIEnv *jenv, jfieldID *jf, char *name, char *type, 344*1449Stomee uu_list_pool_t *fieldpool) 345*1449Stomee { 346*1449Stomee dtj_java_field_t *f = uu_zalloc(sizeof (dtj_java_field_t)); 347*1449Stomee if (f) { 348*1449Stomee uu_list_node_init(f, &f->djf_node, fieldpool); 349*1449Stomee f->djf_ptr = jf; 350*1449Stomee f->djf_name = name; 351*1449Stomee f->djf_type = type; 352*1449Stomee f->djf_static = B_FALSE; 353*1449Stomee } else { 354*1449Stomee dtj_throw_out_of_memory(jenv, 355*1449Stomee "Failed to allocate field description"); 356*1449Stomee } 357*1449Stomee return (f); 358*1449Stomee } 359*1449Stomee 360*1449Stomee static dtj_java_field_t * 361*1449Stomee dtj_java_static_field_create(JNIEnv *jenv, jfieldID *jf, char *name, char *type, 362*1449Stomee uu_list_pool_t *fieldpool) 363*1449Stomee { 364*1449Stomee dtj_java_field_t *f = dtj_java_field_create(jenv, jf, name, type, 365*1449Stomee fieldpool); 366*1449Stomee if (f) { 367*1449Stomee f->djf_static = B_TRUE; 368*1449Stomee } 369*1449Stomee return (f); 370*1449Stomee } 371*1449Stomee 372*1449Stomee static void 373*1449Stomee /* ARGSUSED */ 374*1449Stomee dtj_java_class_destroy(void *v, void *arg) 375*1449Stomee { 376*1449Stomee if (v) { 377*1449Stomee dtj_java_class_t *c = v; 378*1449Stomee c->djc_ptr = NULL; /* do not free user-defined storage */ 379*1449Stomee c->djc_name = NULL; /* string literal */ 380*1449Stomee dtj_list_destroy(c->djc_methods, dtj_java_method_destroy, NULL); 381*1449Stomee dtj_list_destroy(c->djc_fields, dtj_java_field_destroy, NULL); 382*1449Stomee c->djc_methods = NULL; 383*1449Stomee c->djc_fields = NULL; 384*1449Stomee uu_free(v); 385*1449Stomee } 386*1449Stomee } 387*1449Stomee 388*1449Stomee static void 389*1449Stomee /* ARGSUSED */ 390*1449Stomee dtj_java_method_destroy(void *v, void *arg) 391*1449Stomee { 392*1449Stomee if (v) { 393*1449Stomee dtj_java_method_t *m = v; 394*1449Stomee m->djm_ptr = NULL; /* do not free user-defined space */ 395*1449Stomee m->djm_name = NULL; /* string literal */ 396*1449Stomee m->djm_signature = NULL; /* string literal */ 397*1449Stomee uu_free(v); 398*1449Stomee } 399*1449Stomee } 400*1449Stomee 401*1449Stomee static void 402*1449Stomee /* ARGSUSED */ 403*1449Stomee dtj_java_field_destroy(void *v, void *arg) 404*1449Stomee { 405*1449Stomee if (v) { 406*1449Stomee dtj_java_field_t *f = v; 407*1449Stomee f->djf_ptr = NULL; /* do not free user-defined space */ 408*1449Stomee f->djf_name = NULL; /* string literal */ 409*1449Stomee f->djf_type = NULL; /* string literal */ 410*1449Stomee uu_free(f); 411*1449Stomee } 412*1449Stomee } 413*1449Stomee 414*1449Stomee dtj_status_t 415*1449Stomee dtj_cache_jni_classes(JNIEnv *jenv, const dtj_table_entry_t *table) 416*1449Stomee { 417*1449Stomee dtj_java_class_t *class; 418*1449Stomee uu_list_pool_t *classpool; 419*1449Stomee uu_list_pool_t *methodpool; 420*1449Stomee uu_list_pool_t *fieldpool; 421*1449Stomee uu_list_t *classes; 422*1449Stomee uu_list_walk_t *itr; 423*1449Stomee jclass jc; 424*1449Stomee jclass gjc; 425*1449Stomee dtj_status_t status; 426*1449Stomee 427*1449Stomee classpool = uu_list_pool_create("classpool", 428*1449Stomee sizeof (dtj_java_class_t), 429*1449Stomee offsetof(dtj_java_class_t, djc_node), dtj_java_class_cmp, 430*1449Stomee (g_dtj_util_debug ? UU_LIST_POOL_DEBUG : 0)); 431*1449Stomee if (!classpool) { 432*1449Stomee dtj_throw_out_of_memory(jenv, "failed class pool creation"); 433*1449Stomee return (DTJ_ERR); 434*1449Stomee } 435*1449Stomee methodpool = uu_list_pool_create("methodpool", 436*1449Stomee sizeof (dtj_java_method_t), 437*1449Stomee offsetof(dtj_java_method_t, djm_node), dtj_java_method_cmp, 438*1449Stomee (g_dtj_util_debug ? UU_LIST_POOL_DEBUG : 0)); 439*1449Stomee if (!methodpool) { 440*1449Stomee dtj_throw_out_of_memory(jenv, "failed method pool creation"); 441*1449Stomee return (DTJ_ERR); 442*1449Stomee } 443*1449Stomee fieldpool = uu_list_pool_create("fieldpool", 444*1449Stomee sizeof (dtj_java_field_t), 445*1449Stomee offsetof(dtj_java_field_t, djf_node), dtj_java_field_cmp, 446*1449Stomee (g_dtj_util_debug ? UU_LIST_POOL_DEBUG : 0)); 447*1449Stomee if (!fieldpool) { 448*1449Stomee dtj_throw_out_of_memory(jenv, "failed field pool creation"); 449*1449Stomee return (DTJ_ERR); 450*1449Stomee } 451*1449Stomee 452*1449Stomee classes = uu_list_create(classpool, NULL, 453*1449Stomee (g_dtj_util_debug ? UU_LIST_DEBUG : 0)); 454*1449Stomee if (!classes) { 455*1449Stomee dtj_throw_out_of_memory(jenv, "failed class list creation"); 456*1449Stomee return (DTJ_ERR); 457*1449Stomee } 458*1449Stomee 459*1449Stomee status = dtj_get_jni_classes(jenv, classes, classpool, methodpool, 460*1449Stomee fieldpool, table); 461*1449Stomee if (status != DTJ_OK) { 462*1449Stomee /* java error pending */ 463*1449Stomee return (status); 464*1449Stomee } 465*1449Stomee 466*1449Stomee itr = uu_list_walk_start(classes, 0); 467*1449Stomee while ((class = uu_list_walk_next(itr)) != NULL) { 468*1449Stomee jc = (*jenv)->FindClass(jenv, class->djc_name); 469*1449Stomee if (!jc) { 470*1449Stomee /* NoClassDefFoundError pending */ 471*1449Stomee return (DTJ_ERR); 472*1449Stomee } 473*1449Stomee gjc = (*jenv)->NewGlobalRef(jenv, jc); 474*1449Stomee (*jenv)->DeleteLocalRef(jenv, jc); 475*1449Stomee if (!gjc) { 476*1449Stomee dtj_throw_out_of_memory(jenv, 477*1449Stomee "Failed to create global class reference"); 478*1449Stomee return (DTJ_ERR); 479*1449Stomee } 480*1449Stomee *(class->djc_ptr) = gjc; 481*1449Stomee status = dtj_cache_jni_methods(jenv, class); 482*1449Stomee if (status != DTJ_OK) { 483*1449Stomee /* java error pending */ 484*1449Stomee return (status); 485*1449Stomee } 486*1449Stomee status = dtj_cache_jni_fields(jenv, class); 487*1449Stomee if (status != DTJ_OK) { 488*1449Stomee /* java error pending */ 489*1449Stomee return (status); 490*1449Stomee } 491*1449Stomee } 492*1449Stomee uu_list_walk_end(itr); 493*1449Stomee dtj_list_destroy(classes, dtj_java_class_destroy, NULL); 494*1449Stomee uu_list_pool_destroy(classpool); 495*1449Stomee uu_list_pool_destroy(methodpool); 496*1449Stomee uu_list_pool_destroy(fieldpool); 497*1449Stomee return (DTJ_OK); 498*1449Stomee } 499*1449Stomee 500*1449Stomee /* 501*1449Stomee * Converts JNI table entry desriptions into java_class_t descriptors. 502*1449Stomee */ 503*1449Stomee static dtj_status_t 504*1449Stomee dtj_get_jni_classes(JNIEnv *jenv, uu_list_t *classes, 505*1449Stomee uu_list_pool_t *classpool, uu_list_pool_t *methodpool, 506*1449Stomee uu_list_pool_t *fieldpool, const dtj_table_entry_t *table) 507*1449Stomee { 508*1449Stomee int i; 509*1449Stomee dtj_java_class_t *c = NULL; 510*1449Stomee dtj_java_method_t *m; 511*1449Stomee dtj_java_field_t *f; 512*1449Stomee 513*1449Stomee for (i = 0; table[i].djte_type != DTJ_TYPE_END; ++i) { 514*1449Stomee /* 515*1449Stomee * Class not added until all of its method and field information 516*1449Stomee * is attached, so we defer adding a class until the next 517*1449Stomee * element with type JCLASS. 518*1449Stomee */ 519*1449Stomee switch (table[i].djte_type) { 520*1449Stomee case JCLASS: 521*1449Stomee if (c) { 522*1449Stomee /* previous class */ 523*1449Stomee if (!dtj_list_add(classes, c)) { 524*1449Stomee dtj_throw_out_of_memory(jenv, 525*1449Stomee "Failed to add class description"); 526*1449Stomee /* 527*1449Stomee * In response to an error return value, 528*1449Stomee * the caller will delete the class 529*1449Stomee * descriptions list with any 530*1449Stomee * descriptions created so far. 531*1449Stomee */ 532*1449Stomee return (DTJ_ERR); 533*1449Stomee } 534*1449Stomee } 535*1449Stomee c = dtj_java_class_create(jenv, 536*1449Stomee (jclass *)table[i].djte_addr, table[i].djte_name, 537*1449Stomee classpool, methodpool, fieldpool); 538*1449Stomee if (!c) { 539*1449Stomee /* OutOfMemoryError pending */ 540*1449Stomee return (DTJ_ERR); 541*1449Stomee } 542*1449Stomee break; 543*1449Stomee case JMETHOD: 544*1449Stomee if (!c) { 545*1449Stomee dtj_throw_illegal_state(jenv, 546*1449Stomee "method description not preceded " 547*1449Stomee "by class description"); 548*1449Stomee return (DTJ_ERR); 549*1449Stomee } 550*1449Stomee m = dtj_java_method_create(jenv, 551*1449Stomee (jmethodID *)table[i].djte_addr, 552*1449Stomee table[i].djte_name, table[i].djte_desc, 553*1449Stomee methodpool); 554*1449Stomee if (!m) { 555*1449Stomee /* OutOfMemoryError pending */ 556*1449Stomee return (DTJ_ERR); 557*1449Stomee } 558*1449Stomee if (!dtj_list_add(c->djc_methods, m)) { 559*1449Stomee dtj_throw_out_of_memory(jenv, 560*1449Stomee "Failed to add method description"); 561*1449Stomee return (DTJ_ERR); 562*1449Stomee } 563*1449Stomee break; 564*1449Stomee case JMETHOD_STATIC: 565*1449Stomee if (!c) { 566*1449Stomee dtj_throw_illegal_state(jenv, 567*1449Stomee "static method description not preceded " 568*1449Stomee "by class description"); 569*1449Stomee return (DTJ_ERR); 570*1449Stomee } 571*1449Stomee m = dtj_java_static_method_create(jenv, 572*1449Stomee (jmethodID *)table[i].djte_addr, 573*1449Stomee table[i].djte_name, table[i].djte_desc, 574*1449Stomee methodpool); 575*1449Stomee if (!m) { 576*1449Stomee /* OutOfMemoryError pending */ 577*1449Stomee return (DTJ_ERR); 578*1449Stomee } 579*1449Stomee if (!dtj_list_add(c->djc_methods, m)) { 580*1449Stomee dtj_throw_out_of_memory(jenv, 581*1449Stomee "Failed to add static method description"); 582*1449Stomee return (DTJ_ERR); 583*1449Stomee } 584*1449Stomee break; 585*1449Stomee case JFIELD: 586*1449Stomee if (!c) { 587*1449Stomee dtj_throw_illegal_state(jenv, 588*1449Stomee "field description not preceded " 589*1449Stomee "by class description"); 590*1449Stomee return (DTJ_ERR); 591*1449Stomee } 592*1449Stomee f = dtj_java_field_create(jenv, 593*1449Stomee (jfieldID *)table[i].djte_addr, 594*1449Stomee table[i].djte_name, table[i].djte_desc, 595*1449Stomee fieldpool); 596*1449Stomee if (!f) { 597*1449Stomee /* OutOfMemoryError pending */ 598*1449Stomee return (DTJ_ERR); 599*1449Stomee } 600*1449Stomee if (!dtj_list_add(c->djc_fields, f)) { 601*1449Stomee dtj_throw_out_of_memory(jenv, 602*1449Stomee "Failed to add field description"); 603*1449Stomee return (DTJ_ERR); 604*1449Stomee } 605*1449Stomee break; 606*1449Stomee case JFIELD_STATIC: 607*1449Stomee if (!c) { 608*1449Stomee dtj_throw_illegal_state(jenv, 609*1449Stomee "static field description not preceded " 610*1449Stomee "by class description"); 611*1449Stomee return (DTJ_ERR); 612*1449Stomee } 613*1449Stomee f = dtj_java_static_field_create(jenv, 614*1449Stomee (jfieldID *)table[i].djte_addr, 615*1449Stomee table[i].djte_name, table[i].djte_desc, 616*1449Stomee fieldpool); 617*1449Stomee if (!f) { 618*1449Stomee /* OutOfMemoryError pending */ 619*1449Stomee return (DTJ_ERR); 620*1449Stomee } 621*1449Stomee if (!dtj_list_add(c->djc_fields, f)) { 622*1449Stomee dtj_throw_out_of_memory(jenv, 623*1449Stomee "Failed to add static field description"); 624*1449Stomee return (DTJ_ERR); 625*1449Stomee } 626*1449Stomee break; 627*1449Stomee default: 628*1449Stomee dtj_throw_illegal_state(jenv, 629*1449Stomee "Unexpected jni_type_e: %d", table[i].djte_type); 630*1449Stomee return (DTJ_ERR); 631*1449Stomee } 632*1449Stomee } 633*1449Stomee if (c) { 634*1449Stomee /* last class */ 635*1449Stomee if (!dtj_list_add(classes, c)) { 636*1449Stomee dtj_throw_out_of_memory(jenv, 637*1449Stomee "Failed to add class description"); 638*1449Stomee return (DTJ_ERR); 639*1449Stomee } 640*1449Stomee } 641*1449Stomee 642*1449Stomee return (DTJ_OK); 643*1449Stomee } 644*1449Stomee 645*1449Stomee static dtj_status_t 646*1449Stomee dtj_cache_jni_methods(JNIEnv *jenv, dtj_java_class_t *c) 647*1449Stomee { 648*1449Stomee dtj_java_method_t *method; 649*1449Stomee jmethodID jm; 650*1449Stomee uu_list_walk_t *itr; 651*1449Stomee itr = uu_list_walk_start(c->djc_methods, 0); 652*1449Stomee while ((method = uu_list_walk_next(itr)) != NULL) { 653*1449Stomee if (method->djm_static) { 654*1449Stomee jm = (*jenv)->GetStaticMethodID(jenv, *(c->djc_ptr), 655*1449Stomee method->djm_name, method->djm_signature); 656*1449Stomee } else { 657*1449Stomee jm = (*jenv)->GetMethodID(jenv, *(c->djc_ptr), 658*1449Stomee method->djm_name, method->djm_signature); 659*1449Stomee } 660*1449Stomee if (jm == 0) { 661*1449Stomee /* 662*1449Stomee * The pending NoSuchMethodError gives only the 663*1449Stomee * method name, which is not so helpful for 664*1449Stomee * overloaded methods and methods such as <init> 665*1449Stomee * that have the same name in multiple classes. 666*1449Stomee * Clear the pending error and throw one that 667*1449Stomee * includes the class name and the method 668*1449Stomee * signature. 669*1449Stomee */ 670*1449Stomee jclass jc; 671*1449Stomee char msg[DTJ_MSG_SIZE]; 672*1449Stomee (*jenv)->ExceptionClear(jenv); 673*1449Stomee (void) snprintf(msg, sizeof (msg), "%s %s %s", 674*1449Stomee c->djc_name, method->djm_name, 675*1449Stomee method->djm_signature); 676*1449Stomee 677*1449Stomee jc = (*jenv)->FindClass(jenv, 678*1449Stomee "java/lang/NoSuchMethodError"); 679*1449Stomee (*jenv)->ThrowNew(jenv, jc, msg); 680*1449Stomee (*jenv)->DeleteLocalRef(jenv, jc); 681*1449Stomee return (DTJ_ERR); 682*1449Stomee } 683*1449Stomee *(method->djm_ptr) = jm; 684*1449Stomee } 685*1449Stomee uu_list_walk_end(itr); 686*1449Stomee return (DTJ_OK); 687*1449Stomee } 688*1449Stomee 689*1449Stomee static dtj_status_t 690*1449Stomee dtj_cache_jni_fields(JNIEnv *jenv, dtj_java_class_t *c) 691*1449Stomee { 692*1449Stomee dtj_java_field_t *field; 693*1449Stomee jfieldID jf; 694*1449Stomee uu_list_walk_t *itr; 695*1449Stomee itr = uu_list_walk_start(c->djc_fields, 0); 696*1449Stomee while ((field = uu_list_walk_next(itr)) != NULL) { 697*1449Stomee if (field->djf_static) { 698*1449Stomee jf = (*jenv)->GetStaticFieldID(jenv, *(c->djc_ptr), 699*1449Stomee field->djf_name, field->djf_type); 700*1449Stomee } else { 701*1449Stomee jf = (*jenv)->GetFieldID(jenv, *(c->djc_ptr), 702*1449Stomee field->djf_name, field->djf_type); 703*1449Stomee } 704*1449Stomee if (jf == 0) { 705*1449Stomee jclass jc; 706*1449Stomee char msg[DTJ_MSG_SIZE]; 707*1449Stomee (*jenv)->ExceptionClear(jenv); 708*1449Stomee (void) snprintf(msg, sizeof (msg), 709*1449Stomee "%s.%s signature: %s", c->djc_name, 710*1449Stomee field->djf_name, field->djf_type); 711*1449Stomee 712*1449Stomee jc = (*jenv)->FindClass(jenv, 713*1449Stomee "java/lang/NoSuchFieldError"); 714*1449Stomee (*jenv)->ThrowNew(jenv, jc, msg); 715*1449Stomee (*jenv)->DeleteLocalRef(jenv, jc); 716*1449Stomee return (DTJ_ERR); 717*1449Stomee } 718*1449Stomee *(field->djf_ptr) = jf; 719*1449Stomee } 720*1449Stomee uu_list_walk_end(itr); 721*1449Stomee return (DTJ_OK); 722*1449Stomee } 723*1449Stomee 724*1449Stomee 725*1449Stomee /* Common utilities */ 726*1449Stomee 727*1449Stomee static void 728*1449Stomee dtj_throw(JNIEnv *jenv, jclass jc, const char *fmt, va_list *ap) 729*1449Stomee { 730*1449Stomee char msg[DTJ_MSG_SIZE]; 731*1449Stomee (void) vsnprintf(msg, sizeof (msg), fmt, *ap); 732*1449Stomee (*jenv)->ThrowNew(jenv, jc, msg); 733*1449Stomee } 734*1449Stomee 735*1449Stomee void 736*1449Stomee dtj_throw_out_of_memory(JNIEnv *jenv, const char *fmt, ...) 737*1449Stomee { 738*1449Stomee va_list ap; 739*1449Stomee jclass jc; 740*1449Stomee /* 741*1449Stomee * JNI documentation unclear whether NewGlobalRef() can throw 742*1449Stomee * OutOfMemoryError, so we'll make this function safe in case 743*1449Stomee * OutOfMemoryError has already been thrown 744*1449Stomee */ 745*1449Stomee if ((*jenv)->ExceptionCheck(jenv)) { 746*1449Stomee return; 747*1449Stomee } 748*1449Stomee jc = (*jenv)->FindClass(jenv, 749*1449Stomee "java/lang/OutOfMemoryError"); 750*1449Stomee va_start(ap, fmt); 751*1449Stomee dtj_throw(jenv, jc, fmt, &ap); 752*1449Stomee (*jenv)->DeleteLocalRef(jenv, jc); 753*1449Stomee va_end(ap); 754*1449Stomee } 755*1449Stomee 756*1449Stomee void 757*1449Stomee dtj_throw_null_pointer(JNIEnv *jenv, const char *fmt, ...) 758*1449Stomee { 759*1449Stomee va_list ap; 760*1449Stomee jclass jc = (*jenv)->FindClass(jenv, 761*1449Stomee "java/lang/NullPointerException"); 762*1449Stomee va_start(ap, fmt); 763*1449Stomee dtj_throw(jenv, jc, fmt, &ap); 764*1449Stomee (*jenv)->DeleteLocalRef(jenv, jc); 765*1449Stomee va_end(ap); 766*1449Stomee } 767*1449Stomee 768*1449Stomee void 769*1449Stomee dtj_throw_illegal_state(JNIEnv *jenv, const char *fmt, ...) 770*1449Stomee { 771*1449Stomee va_list ap; 772*1449Stomee jclass jc = (*jenv)->FindClass(jenv, 773*1449Stomee "java/lang/IllegalStateException"); 774*1449Stomee va_start(ap, fmt); 775*1449Stomee dtj_throw(jenv, jc, fmt, &ap); 776*1449Stomee (*jenv)->DeleteLocalRef(jenv, jc); 777*1449Stomee va_end(ap); 778*1449Stomee } 779*1449Stomee 780*1449Stomee void 781*1449Stomee dtj_throw_illegal_argument(JNIEnv *jenv, const char *fmt, ...) 782*1449Stomee { 783*1449Stomee va_list ap; 784*1449Stomee jclass jc = (*jenv)->FindClass(jenv, 785*1449Stomee "java/lang/IllegalArgumentException"); 786*1449Stomee va_start(ap, fmt); 787*1449Stomee dtj_throw(jenv, jc, fmt, &ap); 788*1449Stomee (*jenv)->DeleteLocalRef(jenv, jc); 789*1449Stomee va_end(ap); 790*1449Stomee } 791*1449Stomee 792*1449Stomee void 793*1449Stomee dtj_throw_no_such_element(JNIEnv *jenv, const char *fmt, ...) 794*1449Stomee { 795*1449Stomee va_list ap; 796*1449Stomee jclass jc = (*jenv)->FindClass(jenv, 797*1449Stomee "java/util/NoSuchElementException"); 798*1449Stomee va_start(ap, fmt); 799*1449Stomee dtj_throw(jenv, jc, fmt, &ap); 800*1449Stomee (*jenv)->DeleteLocalRef(jenv, jc); 801*1449Stomee va_end(ap); 802*1449Stomee } 803*1449Stomee 804*1449Stomee void 805*1449Stomee dtj_throw_class_cast(JNIEnv *jenv, const char *fmt, ...) 806*1449Stomee { 807*1449Stomee va_list ap; 808*1449Stomee jclass jc = (*jenv)->FindClass(jenv, 809*1449Stomee "java/lang/ClassCastException"); 810*1449Stomee va_start(ap, fmt); 811*1449Stomee dtj_throw(jenv, jc, fmt, &ap); 812*1449Stomee (*jenv)->DeleteLocalRef(jenv, jc); 813*1449Stomee va_end(ap); 814*1449Stomee } 815*1449Stomee 816*1449Stomee void 817*1449Stomee dtj_throw_assertion(JNIEnv *jenv, const char *fmt, ...) 818*1449Stomee { 819*1449Stomee va_list ap; 820*1449Stomee jclass jc = (*jenv)->FindClass(jenv, 821*1449Stomee "java/lang/AssertionError"); 822*1449Stomee va_start(ap, fmt); 823*1449Stomee dtj_throw(jenv, jc, fmt, &ap); 824*1449Stomee (*jenv)->DeleteLocalRef(jenv, jc); 825*1449Stomee va_end(ap); 826*1449Stomee } 827*1449Stomee 828*1449Stomee void 829*1449Stomee dtj_throw_resource_limit(JNIEnv *jenv, const char *fmt, ...) 830*1449Stomee { 831*1449Stomee va_list ap; 832*1449Stomee jclass jc = (*jenv)->FindClass(jenv, 833*1449Stomee "org/opensolaris/os/dtrace/ResourceLimitException"); 834*1449Stomee va_start(ap, fmt); 835*1449Stomee dtj_throw(jenv, jc, fmt, &ap); 836*1449Stomee (*jenv)->DeleteLocalRef(jenv, jc); 837*1449Stomee va_end(ap); 838*1449Stomee } 839*1449Stomee 840*1449Stomee void 841*1449Stomee dtj_wrap_exception(JNIEnv *jenv, const char *file, int line) 842*1449Stomee { 843*1449Stomee jthrowable e = NULL; 844*1449Stomee jthrowable nx = NULL; 845*1449Stomee jstring jfile = NULL; 846*1449Stomee 847*1449Stomee e = (*jenv)->ExceptionOccurred(jenv); 848*1449Stomee if (!e) { 849*1449Stomee return; 850*1449Stomee } 851*1449Stomee 852*1449Stomee if (!g_dtj_load_common) { 853*1449Stomee return; 854*1449Stomee } 855*1449Stomee 856*1449Stomee (*jenv)->ExceptionClear(jenv); 857*1449Stomee 858*1449Stomee /* Unsafe to test while exception pending */ 859*1449Stomee if ((*jenv)->IsInstanceOf(jenv, e, g_nx_jc)) { 860*1449Stomee /* Already wrapped */ 861*1449Stomee (*jenv)->Throw(jenv, e); 862*1449Stomee (*jenv)->DeleteLocalRef(jenv, e); 863*1449Stomee return; 864*1449Stomee } 865*1449Stomee 866*1449Stomee jfile = dtj_NewStringNative(jenv, file); 867*1449Stomee if ((*jenv)->ExceptionCheck(jenv)) { 868*1449Stomee /* 869*1449Stomee * Only wrap the exception if possible, otherwise just throw the 870*1449Stomee * original exception. 871*1449Stomee */ 872*1449Stomee (*jenv)->ExceptionClear(jenv); 873*1449Stomee (*jenv)->Throw(jenv, e); 874*1449Stomee (*jenv)->DeleteLocalRef(jenv, e); 875*1449Stomee return; 876*1449Stomee } 877*1449Stomee 878*1449Stomee nx = (jthrowable)(*jenv)->NewObject(jenv, g_nx_jc, g_nxinit_jm, 879*1449Stomee jfile, line, e); 880*1449Stomee (*jenv)->DeleteLocalRef(jenv, jfile); 881*1449Stomee if ((*jenv)->ExceptionCheck(jenv)) { 882*1449Stomee (*jenv)->ExceptionClear(jenv); 883*1449Stomee (*jenv)->Throw(jenv, e); 884*1449Stomee (*jenv)->DeleteLocalRef(jenv, e); 885*1449Stomee return; 886*1449Stomee } 887*1449Stomee 888*1449Stomee (*jenv)->DeleteLocalRef(jenv, e); 889*1449Stomee (*jenv)->Throw(jenv, nx); 890*1449Stomee (*jenv)->DeleteLocalRef(jenv, nx); 891*1449Stomee } 892*1449Stomee 893*1449Stomee /* 894*1449Stomee * Calls the given java object's toString() method and prints the value to 895*1449Stomee * stdout. Useful for debugging. Guaranteed that no exception is pending when 896*1449Stomee * this function returns. 897*1449Stomee */ 898*1449Stomee void 899*1449Stomee dtj_print_object(JNIEnv *jenv, jobject jobj) 900*1449Stomee { 901*1449Stomee jstring jstr; 902*1449Stomee const char *cstr; 903*1449Stomee 904*1449Stomee if (!g_dtj_load_common) { 905*1449Stomee dtj_throw_illegal_state(jenv, 906*1449Stomee "dtj_load_common() has not been called"); 907*1449Stomee (*jenv)->ExceptionDescribe(jenv); /* clears the exception */ 908*1449Stomee return; 909*1449Stomee } 910*1449Stomee 911*1449Stomee if (!jobj) { 912*1449Stomee (void) printf("null\n"); 913*1449Stomee return; 914*1449Stomee } 915*1449Stomee 916*1449Stomee jstr = (*jenv)->CallObjectMethod(jenv, jobj, g_tostring_jm); 917*1449Stomee if ((*jenv)->ExceptionCheck(jenv)) { 918*1449Stomee (*jenv)->ExceptionDescribe(jenv); /* clears the exception */ 919*1449Stomee return; 920*1449Stomee } 921*1449Stomee cstr = (*jenv)->GetStringUTFChars(jenv, jstr, 0); 922*1449Stomee if (cstr) { 923*1449Stomee (void) printf("%s\n", cstr); 924*1449Stomee } else { 925*1449Stomee (*jenv)->ExceptionDescribe(jenv); /* clears the exception */ 926*1449Stomee (*jenv)->DeleteLocalRef(jenv, jstr); 927*1449Stomee return; 928*1449Stomee } 929*1449Stomee (*jenv)->ReleaseStringUTFChars(jenv, jstr, cstr); 930*1449Stomee (*jenv)->DeleteLocalRef(jenv, jstr); 931*1449Stomee } 932*1449Stomee 933*1449Stomee jstring 934*1449Stomee dtj_format_string(JNIEnv *jenv, const char *fmt, ...) 935*1449Stomee { 936*1449Stomee va_list ap; 937*1449Stomee char str[DTJ_MSG_SIZE]; 938*1449Stomee 939*1449Stomee jstring jstr = NULL; 940*1449Stomee 941*1449Stomee va_start(ap, fmt); 942*1449Stomee (void) vsnprintf(str, sizeof (str), fmt, ap); 943*1449Stomee va_end(ap); 944*1449Stomee 945*1449Stomee jstr = dtj_NewStringNative(jenv, str); 946*1449Stomee /* return NULL if OutOfMemoryError pending */ 947*1449Stomee return (jstr); 948*1449Stomee } 949*1449Stomee 950*1449Stomee jstring 951*1449Stomee dtj_NewStringNative(JNIEnv *jenv, const char *str) 952*1449Stomee { 953*1449Stomee jstring result; 954*1449Stomee jbyteArray bytes = 0; 955*1449Stomee int len; 956*1449Stomee 957*1449Stomee if (!g_dtj_load_common) { 958*1449Stomee dtj_throw_illegal_state(jenv, 959*1449Stomee "dtj_load_common() has not been called"); 960*1449Stomee return (NULL); 961*1449Stomee } 962*1449Stomee 963*1449Stomee len = strlen(str); 964*1449Stomee 965*1449Stomee bytes = (*jenv)->NewByteArray(jenv, len); 966*1449Stomee if (!bytes) { 967*1449Stomee return (NULL); /* OutOfMemoryError pending */ 968*1449Stomee } 969*1449Stomee (*jenv)->SetByteArrayRegion(jenv, bytes, 0, len, 970*1449Stomee (jbyte *)str); 971*1449Stomee if ((*jenv)->ExceptionCheck(jenv)) { 972*1449Stomee (*jenv)->DeleteLocalRef(jenv, bytes); 973*1449Stomee return (NULL); /* ArrayIndexOutOfBoundsException pending */ 974*1449Stomee } 975*1449Stomee result = (*jenv)->NewObject(jenv, g_string_jc, g_strinit_bytes_jm, 976*1449Stomee bytes); 977*1449Stomee (*jenv)->DeleteLocalRef(jenv, bytes); 978*1449Stomee /* return NULL result if exception pending */ 979*1449Stomee return (result); 980*1449Stomee } 981*1449Stomee 982*1449Stomee char * 983*1449Stomee dtj_GetStringNativeChars(JNIEnv *jenv, jstring jstr) 984*1449Stomee { 985*1449Stomee jbyteArray bytes = NULL; 986*1449Stomee 987*1449Stomee jint len; 988*1449Stomee char *result = NULL; 989*1449Stomee 990*1449Stomee if (!g_dtj_load_common) { 991*1449Stomee dtj_throw_illegal_state(jenv, 992*1449Stomee "dtj_load_common() has not been called"); 993*1449Stomee return (NULL); 994*1449Stomee } 995*1449Stomee 996*1449Stomee bytes = (*jenv)->CallObjectMethod(jenv, jstr, g_strbytes_jm); 997*1449Stomee if ((*jenv)->ExceptionCheck(jenv)) { 998*1449Stomee return (NULL); /* OutOfMemoryError pending */ 999*1449Stomee } 1000*1449Stomee /* Does not throw exceptions */ 1001*1449Stomee len = (*jenv)->GetArrayLength(jenv, bytes); 1002*1449Stomee result = malloc(len + 1); 1003*1449Stomee if (!result) { 1004*1449Stomee (*jenv)->DeleteLocalRef(jenv, bytes); 1005*1449Stomee dtj_throw_out_of_memory(jenv, 1006*1449Stomee "could not allocate native chars"); 1007*1449Stomee return (NULL); 1008*1449Stomee } 1009*1449Stomee 1010*1449Stomee /* Skip check for ArrayIndexOutOfBoundsException */ 1011*1449Stomee (*jenv)->GetByteArrayRegion(jenv, bytes, 0, len, 1012*1449Stomee (jbyte *)result); 1013*1449Stomee (*jenv)->DeleteLocalRef(jenv, bytes); 1014*1449Stomee result[len] = '\0'; /* NUL-terminate */ 1015*1449Stomee 1016*1449Stomee return (result); 1017*1449Stomee } 1018*1449Stomee 1019*1449Stomee void 1020*1449Stomee /* ARGSUSED */ 1021*1449Stomee dtj_ReleaseStringNativeChars(JNIEnv *jenv, jstring jstr, const char *str) 1022*1449Stomee { 1023*1449Stomee free((void *)str); 1024*1449Stomee } 1025*1449Stomee 1026*1449Stomee char ** 1027*1449Stomee dtj_get_argv(JNIEnv *jenv, jobjectArray args, int *argc) 1028*1449Stomee { 1029*1449Stomee char **argv = NULL; /* return value */ 1030*1449Stomee const char *str; 1031*1449Stomee int i; 1032*1449Stomee 1033*1449Stomee jstring jstr = NULL; 1034*1449Stomee 1035*1449Stomee if (!g_dtj_load_common) { 1036*1449Stomee dtj_throw_illegal_state(jenv, 1037*1449Stomee "dtj_load_common() has not been called"); 1038*1449Stomee return (NULL); 1039*1449Stomee } 1040*1449Stomee 1041*1449Stomee *argc = (*jenv)->GetArrayLength(jenv, args); 1042*1449Stomee /* 1043*1449Stomee * Initialize all string pointers to NULL so that in case of an error 1044*1449Stomee * filling in the array, free_argv() will not attempt to free the 1045*1449Stomee * unallocated elements. Also NULL-terminate the string array for 1046*1449Stomee * functions that expect terminating NULL rather than rely on argc. 1047*1449Stomee */ 1048*1449Stomee argv = uu_zalloc((sizeof (char *)) * (*argc + 1)); 1049*1449Stomee if (!argv) { 1050*1449Stomee dtj_throw_out_of_memory(jenv, "Failed to allocate args array"); 1051*1449Stomee return (NULL); 1052*1449Stomee } 1053*1449Stomee 1054*1449Stomee for (i = 0; i < *argc; ++i) { 1055*1449Stomee jstr = (*jenv)->GetObjectArrayElement(jenv, args, i); 1056*1449Stomee if ((*jenv)->ExceptionCheck(jenv)) { 1057*1449Stomee dtj_free_argv(argv); 1058*1449Stomee return (NULL); 1059*1449Stomee } 1060*1449Stomee str = dtj_GetStringNativeChars(jenv, jstr); 1061*1449Stomee if ((*jenv)->ExceptionCheck(jenv)) { 1062*1449Stomee dtj_free_argv(argv); 1063*1449Stomee (*jenv)->DeleteLocalRef(jenv, jstr); 1064*1449Stomee return (NULL); 1065*1449Stomee } 1066*1449Stomee argv[i] = malloc(strlen(str) + 1); 1067*1449Stomee if (!argv[i]) { 1068*1449Stomee dtj_throw_out_of_memory(jenv, "Failed to allocate arg"); 1069*1449Stomee dtj_free_argv(argv); 1070*1449Stomee dtj_ReleaseStringNativeChars(jenv, jstr, str); 1071*1449Stomee (*jenv)->DeleteLocalRef(jenv, jstr); 1072*1449Stomee return (NULL); 1073*1449Stomee } 1074*1449Stomee (void) strcpy(argv[i], str); 1075*1449Stomee dtj_ReleaseStringNativeChars(jenv, jstr, str); 1076*1449Stomee (*jenv)->DeleteLocalRef(jenv, jstr); 1077*1449Stomee jstr = NULL; 1078*1449Stomee } 1079*1449Stomee 1080*1449Stomee return (argv); 1081*1449Stomee } 1082*1449Stomee 1083*1449Stomee char ** 1084*1449Stomee dtj_make_argv(JNIEnv *jenv, jstring command, int *argc) 1085*1449Stomee { 1086*1449Stomee const char *ws = "\f\n\r\t\v "; 1087*1449Stomee char **argv = NULL; /* return value */ 1088*1449Stomee const char *cmd; /* native command string */ 1089*1449Stomee char *s; /* writable command */ 1090*1449Stomee char *tok; /* token */ 1091*1449Stomee int len; 1092*1449Stomee 1093*1449Stomee if (!g_dtj_load_common) { 1094*1449Stomee dtj_throw_illegal_state(jenv, 1095*1449Stomee "dtj_load_common() has not been called"); 1096*1449Stomee return (NULL); 1097*1449Stomee } 1098*1449Stomee 1099*1449Stomee if (!command) { 1100*1449Stomee dtj_throw_null_pointer(jenv, "command is null"); 1101*1449Stomee return (NULL); 1102*1449Stomee } else if ((*jenv)->GetStringLength(jenv, command) == 0) { 1103*1449Stomee dtj_throw_illegal_argument(jenv, "command is empty"); 1104*1449Stomee return (NULL); 1105*1449Stomee } 1106*1449Stomee 1107*1449Stomee cmd = dtj_GetStringNativeChars(jenv, command); 1108*1449Stomee if ((*jenv)->ExceptionCheck(jenv)) { 1109*1449Stomee return (NULL); 1110*1449Stomee } 1111*1449Stomee len = strlen(cmd); 1112*1449Stomee s = malloc(len + 1); 1113*1449Stomee if (!s) { 1114*1449Stomee dtj_throw_out_of_memory(jenv, 1115*1449Stomee "failed to allocate command string"); 1116*1449Stomee dtj_ReleaseStringNativeChars(jenv, command, cmd); 1117*1449Stomee return (NULL); 1118*1449Stomee } 1119*1449Stomee (void) strcpy(s, cmd); 1120*1449Stomee /* 1121*1449Stomee * Initialize all string pointers to NULL so that in case of an error 1122*1449Stomee * filling in the array, free_argv() will not attempt to free the 1123*1449Stomee * unallocated elements. Also NULL-terminate the string array for 1124*1449Stomee * functions that expect terminating NULL rather than rely on argc. 1125*1449Stomee * Allow for maximum length resulting from single-character tokens 1126*1449Stomee * separated by single spaces. 1127*1449Stomee */ 1128*1449Stomee argv = uu_zalloc(sizeof (char *) * (len / 2 + 1)); 1129*1449Stomee if (!argv) { 1130*1449Stomee dtj_throw_out_of_memory(jenv, "failed to allocate args array"); 1131*1449Stomee free(s); 1132*1449Stomee dtj_ReleaseStringNativeChars(jenv, command, cmd); 1133*1449Stomee return (NULL); 1134*1449Stomee } 1135*1449Stomee 1136*1449Stomee *argc = 0; 1137*1449Stomee for (tok = strtok(s, ws); tok != NULL; tok = strtok(NULL, ws)) { 1138*1449Stomee argv[*argc] = malloc(strlen(tok) + 1); 1139*1449Stomee if (!argv[*argc]) { 1140*1449Stomee dtj_throw_out_of_memory(jenv, "Failed to allocate arg"); 1141*1449Stomee dtj_free_argv(argv); 1142*1449Stomee free(s); 1143*1449Stomee dtj_ReleaseStringNativeChars(jenv, command, cmd); 1144*1449Stomee return (NULL); 1145*1449Stomee } 1146*1449Stomee (void) strcpy(argv[(*argc)++], tok); 1147*1449Stomee } 1148*1449Stomee 1149*1449Stomee if (*argc == 0) { 1150*1449Stomee dtj_throw_illegal_argument(jenv, "command is blank"); 1151*1449Stomee dtj_free_argv(argv); 1152*1449Stomee free(s); 1153*1449Stomee dtj_ReleaseStringNativeChars(jenv, command, cmd); 1154*1449Stomee return (NULL); 1155*1449Stomee } 1156*1449Stomee 1157*1449Stomee free(s); 1158*1449Stomee dtj_ReleaseStringNativeChars(jenv, command, cmd); 1159*1449Stomee return (argv); 1160*1449Stomee } 1161*1449Stomee 1162*1449Stomee void 1163*1449Stomee dtj_free_argv(char **argv) 1164*1449Stomee { 1165*1449Stomee if (argv) { 1166*1449Stomee char **s = argv; 1167*1449Stomee while (*s) { 1168*1449Stomee free((void *)*s); 1169*1449Stomee *s++ = NULL; 1170*1449Stomee } 1171*1449Stomee free((void *)argv); 1172*1449Stomee } 1173*1449Stomee } 1174*1449Stomee 1175*1449Stomee 1176*1449Stomee /* Wrappers for uu_list_t */ 1177*1449Stomee 1178*1449Stomee int 1179*1449Stomee /* ARGSUSED */ 1180*1449Stomee dtj_pointer_list_entry_cmp(const void *v1, const void *v2, void *arg) 1181*1449Stomee { 1182*1449Stomee const dtj_pointer_list_entry_t *p1 = v1; 1183*1449Stomee const dtj_pointer_list_entry_t *p2 = v2; 1184*1449Stomee 1185*1449Stomee /* 1186*1449Stomee * It is not valid to compare pointers using the relational operators 1187*1449Stomee * unless they point to elements in the same array. 1188*1449Stomee */ 1189*1449Stomee uint64_t x = (uint64_t)p1->dple_ptr; 1190*1449Stomee uint64_t y = (uint64_t)p2->dple_ptr; 1191*1449Stomee int rc; 1192*1449Stomee rc = ((x > y) ? 1 : ((x < y) ? -1 : 0)); 1193*1449Stomee return (rc); 1194*1449Stomee } 1195*1449Stomee 1196*1449Stomee int 1197*1449Stomee /* ARGSUSED */ 1198*1449Stomee dtj_string_list_entry_cmp(const void *v1, const void *v2, void *arg) 1199*1449Stomee { 1200*1449Stomee const dtj_string_list_entry_t *p1 = v1; 1201*1449Stomee const dtj_string_list_entry_t *p2 = v2; 1202*1449Stomee const char *s1 = p1->dsle_value; 1203*1449Stomee const char *s2 = p2->dsle_value; 1204*1449Stomee if (s1 == NULL) { 1205*1449Stomee return (s2 == NULL ? 0 : -1); 1206*1449Stomee } 1207*1449Stomee if (s2 == NULL) { 1208*1449Stomee return (1); 1209*1449Stomee } 1210*1449Stomee return (strcmp(s1, s2)); 1211*1449Stomee } 1212*1449Stomee 1213*1449Stomee static boolean_t 1214*1449Stomee dtj_check_pointer_pool(void) 1215*1449Stomee { 1216*1449Stomee if (g_pointer_pool == NULL) { 1217*1449Stomee g_pointer_pool = uu_list_pool_create("g_pointer_pool", 1218*1449Stomee sizeof (dtj_pointer_list_entry_t), 1219*1449Stomee offsetof(dtj_pointer_list_entry_t, dple_node), 1220*1449Stomee dtj_pointer_list_entry_cmp, 1221*1449Stomee (g_dtj_util_debug ? UU_LIST_POOL_DEBUG : 0)); 1222*1449Stomee if (g_pointer_pool == NULL) { 1223*1449Stomee return (B_FALSE); 1224*1449Stomee } 1225*1449Stomee } 1226*1449Stomee return (B_TRUE); 1227*1449Stomee } 1228*1449Stomee 1229*1449Stomee uu_list_t * 1230*1449Stomee dtj_pointer_list_create(void) 1231*1449Stomee { 1232*1449Stomee uu_list_t *list; 1233*1449Stomee 1234*1449Stomee if (!dtj_check_pointer_pool()) { 1235*1449Stomee return (NULL); 1236*1449Stomee } 1237*1449Stomee 1238*1449Stomee list = uu_list_create(g_pointer_pool, NULL, 1239*1449Stomee (g_dtj_util_debug ? UU_LIST_DEBUG : 0)); 1240*1449Stomee return (list); 1241*1449Stomee } 1242*1449Stomee 1243*1449Stomee dtj_pointer_list_entry_t * 1244*1449Stomee dtj_pointer_list_entry_create(void *p) 1245*1449Stomee { 1246*1449Stomee dtj_pointer_list_entry_t *e; 1247*1449Stomee 1248*1449Stomee if (!dtj_check_pointer_pool()) { 1249*1449Stomee return (NULL); 1250*1449Stomee } 1251*1449Stomee 1252*1449Stomee e = uu_zalloc(sizeof (dtj_pointer_list_entry_t)); 1253*1449Stomee if (e) { 1254*1449Stomee uu_list_node_init(e, &e->dple_node, g_pointer_pool); 1255*1449Stomee e->dple_ptr = p; 1256*1449Stomee } 1257*1449Stomee return (e); 1258*1449Stomee } 1259*1449Stomee 1260*1449Stomee static boolean_t 1261*1449Stomee dtj_check_string_pool(void) 1262*1449Stomee { 1263*1449Stomee if (g_string_pool == NULL) { 1264*1449Stomee g_string_pool = uu_list_pool_create("g_string_pool", 1265*1449Stomee sizeof (dtj_string_list_entry_t), 1266*1449Stomee offsetof(dtj_string_list_entry_t, dsle_node), 1267*1449Stomee dtj_string_list_entry_cmp, 1268*1449Stomee (g_dtj_util_debug ? UU_LIST_POOL_DEBUG : 0)); 1269*1449Stomee if (g_string_pool == NULL) { 1270*1449Stomee return (B_FALSE); 1271*1449Stomee } 1272*1449Stomee } 1273*1449Stomee return (B_TRUE); 1274*1449Stomee } 1275*1449Stomee 1276*1449Stomee uu_list_t * 1277*1449Stomee dtj_string_list_create(void) 1278*1449Stomee { 1279*1449Stomee uu_list_t *list; 1280*1449Stomee 1281*1449Stomee if (!dtj_check_string_pool()) { 1282*1449Stomee return (NULL); 1283*1449Stomee } 1284*1449Stomee 1285*1449Stomee list = uu_list_create(g_string_pool, NULL, 1286*1449Stomee (g_dtj_util_debug ? UU_LIST_DEBUG : 0)); 1287*1449Stomee return (list); 1288*1449Stomee } 1289*1449Stomee 1290*1449Stomee dtj_string_list_entry_t * 1291*1449Stomee dtj_string_list_entry_create(const char *s) 1292*1449Stomee { 1293*1449Stomee dtj_string_list_entry_t *e; 1294*1449Stomee 1295*1449Stomee if (!dtj_check_string_pool()) { 1296*1449Stomee return (NULL); 1297*1449Stomee } 1298*1449Stomee 1299*1449Stomee e = uu_zalloc(sizeof (dtj_string_list_entry_t)); 1300*1449Stomee if (e) { 1301*1449Stomee uu_list_node_init(e, &e->dsle_node, g_string_pool); 1302*1449Stomee if (s) { 1303*1449Stomee e->dsle_value = malloc(strlen(s) + 1); 1304*1449Stomee if (e->dsle_value) { 1305*1449Stomee (void) strcpy(e->dsle_value, s); 1306*1449Stomee } else { 1307*1449Stomee uu_list_node_fini(e, &e->dsle_node, 1308*1449Stomee g_string_pool); 1309*1449Stomee uu_free(e); 1310*1449Stomee e = NULL; 1311*1449Stomee } 1312*1449Stomee } 1313*1449Stomee } 1314*1449Stomee return (e); 1315*1449Stomee } 1316*1449Stomee 1317*1449Stomee void 1318*1449Stomee dtj_pointer_list_entry_destroy(void *v, 1319*1449Stomee dtj_value_destroy_f *value_destroy, void *arg) 1320*1449Stomee { 1321*1449Stomee if (v) { 1322*1449Stomee dtj_pointer_list_entry_t *e = v; 1323*1449Stomee if (value_destroy) { 1324*1449Stomee value_destroy(e->dple_ptr, arg); 1325*1449Stomee } 1326*1449Stomee uu_list_node_fini(e, &e->dple_node, g_pointer_pool); 1327*1449Stomee e->dple_ptr = NULL; 1328*1449Stomee uu_free(v); 1329*1449Stomee } 1330*1449Stomee } 1331*1449Stomee 1332*1449Stomee void 1333*1449Stomee /* ARGSUSED */ 1334*1449Stomee dtj_string_list_entry_destroy(void *v, void *arg) 1335*1449Stomee { 1336*1449Stomee if (v) { 1337*1449Stomee dtj_string_list_entry_t *e = v; 1338*1449Stomee free(e->dsle_value); 1339*1449Stomee uu_list_node_fini(e, &e->dsle_node, g_string_pool); 1340*1449Stomee e->dsle_value = NULL; 1341*1449Stomee uu_free(v); 1342*1449Stomee } 1343*1449Stomee } 1344*1449Stomee 1345*1449Stomee void 1346*1449Stomee dtj_list_clear(uu_list_t *list, dtj_value_destroy_f *value_destroy, 1347*1449Stomee void *arg) 1348*1449Stomee { 1349*1449Stomee void *cookie; /* needed for uu_list_teardown */ 1350*1449Stomee void *value; 1351*1449Stomee 1352*1449Stomee if (!list) { 1353*1449Stomee return; 1354*1449Stomee } 1355*1449Stomee 1356*1449Stomee cookie = NULL; 1357*1449Stomee if (value_destroy) { 1358*1449Stomee while ((value = uu_list_teardown(list, &cookie)) != NULL) { 1359*1449Stomee value_destroy(value, arg); 1360*1449Stomee } 1361*1449Stomee } else { 1362*1449Stomee while ((value = uu_list_teardown(list, &cookie)) != NULL) { 1363*1449Stomee } 1364*1449Stomee } 1365*1449Stomee } 1366*1449Stomee 1367*1449Stomee void 1368*1449Stomee dtj_list_destroy(uu_list_t *list, 1369*1449Stomee dtj_value_destroy_f *value_destroy, void *arg) 1370*1449Stomee { 1371*1449Stomee dtj_list_clear(list, value_destroy, arg); 1372*1449Stomee uu_list_destroy(list); 1373*1449Stomee } 1374*1449Stomee 1375*1449Stomee void 1376*1449Stomee dtj_pointer_list_clear(uu_list_t *list, 1377*1449Stomee dtj_value_destroy_f *value_destroy, void *arg) 1378*1449Stomee { 1379*1449Stomee void *cookie; /* needed for uu_list_teardown */ 1380*1449Stomee dtj_pointer_list_entry_t *e; 1381*1449Stomee 1382*1449Stomee if (!list) { 1383*1449Stomee return; 1384*1449Stomee } 1385*1449Stomee 1386*1449Stomee cookie = NULL; 1387*1449Stomee while ((e = uu_list_teardown(list, &cookie)) != NULL) { 1388*1449Stomee dtj_pointer_list_entry_destroy(e, value_destroy, arg); 1389*1449Stomee } 1390*1449Stomee } 1391*1449Stomee 1392*1449Stomee void 1393*1449Stomee dtj_pointer_list_destroy(uu_list_t *list, 1394*1449Stomee dtj_value_destroy_f *value_destroy, void *arg) 1395*1449Stomee { 1396*1449Stomee dtj_pointer_list_clear(list, value_destroy, arg); 1397*1449Stomee uu_list_destroy(list); 1398*1449Stomee } 1399*1449Stomee 1400*1449Stomee void 1401*1449Stomee dtj_string_list_clear(uu_list_t *list) 1402*1449Stomee { 1403*1449Stomee dtj_list_clear(list, dtj_string_list_entry_destroy, NULL); 1404*1449Stomee } 1405*1449Stomee 1406*1449Stomee void 1407*1449Stomee dtj_string_list_destroy(uu_list_t *list) 1408*1449Stomee { 1409*1449Stomee dtj_list_destroy(list, dtj_string_list_entry_destroy, NULL); 1410*1449Stomee } 1411*1449Stomee 1412*1449Stomee boolean_t 1413*1449Stomee dtj_list_empty(uu_list_t *list) 1414*1449Stomee { 1415*1449Stomee return (uu_list_numnodes(list) == 0); 1416*1449Stomee } 1417*1449Stomee 1418*1449Stomee boolean_t 1419*1449Stomee dtj_list_add(uu_list_t *list, void *value) 1420*1449Stomee { 1421*1449Stomee return (uu_list_insert_before(list, NULL, value) == 0); 1422*1449Stomee } 1423*1449Stomee 1424*1449Stomee boolean_t 1425*1449Stomee dtj_pointer_list_add(uu_list_t *list, void *p) 1426*1449Stomee { 1427*1449Stomee dtj_pointer_list_entry_t *e = dtj_pointer_list_entry_create(p); 1428*1449Stomee if (!e) { 1429*1449Stomee return (B_FALSE); 1430*1449Stomee } 1431*1449Stomee return (dtj_list_add(list, e)); 1432*1449Stomee } 1433*1449Stomee 1434*1449Stomee void * 1435*1449Stomee dtj_pointer_list_walk_next(uu_list_walk_t *itr) 1436*1449Stomee { 1437*1449Stomee dtj_pointer_list_entry_t *e = uu_list_walk_next(itr); 1438*1449Stomee if (!e) { 1439*1449Stomee return (DTJ_INVALID_PTR); 1440*1449Stomee } 1441*1449Stomee return (e->dple_ptr); 1442*1449Stomee } 1443*1449Stomee 1444*1449Stomee void * 1445*1449Stomee dtj_pointer_list_first(uu_list_t *list) 1446*1449Stomee { 1447*1449Stomee dtj_pointer_list_entry_t *e = uu_list_first(list); 1448*1449Stomee if (!e) { 1449*1449Stomee /* NULL is a valid value; use -1 for invalid */ 1450*1449Stomee return (DTJ_INVALID_PTR); 1451*1449Stomee } 1452*1449Stomee return (e->dple_ptr); 1453*1449Stomee } 1454*1449Stomee 1455*1449Stomee void * 1456*1449Stomee dtj_pointer_list_last(uu_list_t *list) 1457*1449Stomee { 1458*1449Stomee dtj_pointer_list_entry_t *e = uu_list_last(list); 1459*1449Stomee if (!e) { 1460*1449Stomee /* NULL is a valid value; use -1 for invalid */ 1461*1449Stomee return (DTJ_INVALID_PTR); 1462*1449Stomee } 1463*1449Stomee return (e->dple_ptr); 1464*1449Stomee } 1465*1449Stomee 1466*1449Stomee boolean_t 1467*1449Stomee dtj_string_list_add(uu_list_t *list, const char *s) 1468*1449Stomee { 1469*1449Stomee dtj_string_list_entry_t *e = dtj_string_list_entry_create(s); 1470*1449Stomee if (!e) { 1471*1449Stomee return (B_FALSE); 1472*1449Stomee } 1473*1449Stomee return (dtj_list_add(list, e)); 1474*1449Stomee } 1475*1449Stomee 1476*1449Stomee const char * 1477*1449Stomee dtj_string_list_walk_next(uu_list_walk_t *itr) 1478*1449Stomee { 1479*1449Stomee dtj_string_list_entry_t *e = uu_list_walk_next(itr); 1480*1449Stomee if (!e) { 1481*1449Stomee return (DTJ_INVALID_STR); 1482*1449Stomee } 1483*1449Stomee return (e->dsle_value); 1484*1449Stomee } 1485*1449Stomee 1486*1449Stomee const char * 1487*1449Stomee dtj_string_list_first(uu_list_t *list) 1488*1449Stomee { 1489*1449Stomee dtj_string_list_entry_t *e = uu_list_first(list); 1490*1449Stomee if (!e) { 1491*1449Stomee /* NULL is a valid string value; use -1 for invalid */ 1492*1449Stomee return (DTJ_INVALID_STR); 1493*1449Stomee } 1494*1449Stomee return (e->dsle_value); 1495*1449Stomee } 1496*1449Stomee 1497*1449Stomee const char * 1498*1449Stomee dtj_string_list_last(uu_list_t *list) 1499*1449Stomee { 1500*1449Stomee dtj_string_list_entry_t *e = uu_list_last(list); 1501*1449Stomee if (!e) { 1502*1449Stomee /* NULL is a valid string value; use -1 for invalid */ 1503*1449Stomee return (DTJ_INVALID_STR); 1504*1449Stomee } 1505*1449Stomee return (e->dsle_value); 1506*1449Stomee } 1507