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