1
2 /*
3 * Copyright (c) 2002-2011 by XMLVM.org
4 *
5 * Project Info: http://www.xmlvm.org
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 * License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20 * USA.
21 */
22
23 #include "xmlvm.h"
24 #include "xmlvm-hy.h"
25
26
errorMessage(I_32 errorCode)27 const char* errorMessage (I_32 errorCode)
28 {
29 PortlibPTBuffers_t ptBuffers;
30
31 ptBuffers = hyport_tls_peek ();
32 if (0 == ptBuffers->errorMessageBufferSize)
33 {
34 ptBuffers->errorMessageBuffer = XMLVM_ATOMIC_MALLOC(HYERROR_DEFAULT_BUFFER_SIZE);
35 if (NULL == ptBuffers->errorMessageBuffer)
36 {
37 return "";
38 }
39 ptBuffers->errorMessageBufferSize = HYERROR_DEFAULT_BUFFER_SIZE;
40 }
41
42 /* Copy from OS to ptBuffers */
43 #if !defined(ZOS)
44 strerror_r(errorCode,
45 ptBuffers->errorMessageBuffer, ptBuffers->errorMessageBufferSize);
46 #else
47 /* Do not have strerror_r on z/OS so use port library function instead */
48 portLibrary->str_printf(portLibrary, ptBuffers->errorMessageBuffer, ptBuffers->errorMessageBufferSize, strerror(errorCode));
49 #endif /* ZOS */
50 ptBuffers->errorMessageBuffer[ptBuffers->errorMessageBufferSize - 1] = '\0';
51 return ptBuffers->errorMessageBuffer;
52 }
53
54
swapMessageBuffer(PortlibPTBuffers_t ptBuffers,const char * message)55 static const char* swapMessageBuffer (PortlibPTBuffers_t ptBuffers, const char *message)
56 {
57 char *tempBuffer = ptBuffers->reportedMessageBuffer;
58 U_32 tempBufferSize = ptBuffers->reportedMessageBufferSize;
59
60 if (message == NULL)
61 {
62 return "";
63 }
64
65 /* Can't swap unknown message buffer */
66 if (message != ptBuffers->errorMessageBuffer)
67 {
68 return message;
69 }
70
71 /* Save reported information */
72 ptBuffers->reportedErrorCode = ptBuffers->portableErrorCode;
73 ptBuffers->reportedMessageBuffer = ptBuffers->errorMessageBuffer;
74 ptBuffers->reportedMessageBufferSize = ptBuffers->errorMessageBufferSize;
75
76 if (tempBufferSize > 0)
77 {
78 tempBuffer[0] = '\0';
79 }
80
81 /* Clear pending fields ready for next error */
82 ptBuffers->portableErrorCode = 0;
83 ptBuffers->errorMessageBuffer = tempBuffer;
84 ptBuffers->errorMessageBufferSize = tempBufferSize;
85
86 return ptBuffers->reportedMessageBuffer;
87 }
88
89
hyport_tls_get()90 void* hyport_tls_get ()
91 {
92 java_lang_Thread* curThread = (java_lang_Thread*) java_lang_Thread_currentThread__();
93 if (curThread->fields.java_lang_Thread.ptBuffers_ == JAVA_NULL) {
94 curThread->fields.java_lang_Thread.ptBuffers_ = XMLVM_MALLOC(sizeof(PortlibPTBuffers_struct));
95 XMLVM_BZERO(curThread->fields.java_lang_Thread.ptBuffers_, sizeof(PortlibPTBuffers_struct));
96 }
97
98 return curThread->fields.java_lang_Thread.ptBuffers_;
99 }
100
101
hyport_tls_peek()102 void* hyport_tls_peek ()
103 {
104 java_lang_Thread* curThread = (java_lang_Thread*) java_lang_Thread_currentThread__();
105 return curThread->fields.java_lang_Thread.ptBuffers_;
106 }
107
108
hyerror_last_error_message()109 const char* hyerror_last_error_message ()
110 {
111 PortlibPTBuffers_t ptBuffers;
112
113 /* Was an error saved ? */
114 ptBuffers = hyport_tls_peek ();
115 if (NULL == ptBuffers)
116 {
117 return "";
118 }
119
120 /* New error ? */
121 if (ptBuffers->portableErrorCode != 0)
122 {
123 const char *message = NULL;
124
125 /* Customized message stored ? */
126 if (ptBuffers->errorMessageBufferSize > 0)
127 {
128 if ('\0' != ptBuffers->errorMessageBuffer[0])
129 {
130 message = ptBuffers->errorMessageBuffer;
131 }
132 }
133
134 /* Call a helper to get the last message from the OS. */
135 if (message == NULL)
136 {
137 message = errorMessage (ptBuffers->platformErrorCode);
138 }
139
140 /* Avoid overwrite by internal portlib errors */
141 return swapMessageBuffer (ptBuffers, message);
142 }
143
144 /* Previous message stored ? */
145 if (ptBuffers->reportedMessageBufferSize > 0)
146 {
147 if ('\0' != ptBuffers->reportedMessageBuffer[0])
148 {
149 return ptBuffers->reportedMessageBuffer;
150 }
151 }
152
153 /* No error. */
154 return "";
155 }
156
157
hyerror_last_error_number()158 I_32 hyerror_last_error_number ()
159 {
160 PortlibPTBuffers_t ptBuffers;
161
162 /* get the buffers, return failure if not present */
163 ptBuffers = hyport_tls_peek ();
164 if (NULL == ptBuffers)
165 {
166 return 0;
167 }
168
169 /* New error ? */
170 if (ptBuffers->portableErrorCode != 0)
171 {
172 return ptBuffers->portableErrorCode;
173 }
174 else
175 {
176 return ptBuffers->reportedErrorCode;
177 }
178 }
179
180
hyerror_set_last_error(I_32 platformCode,I_32 portableCode)181 I_32 hyerror_set_last_error (I_32 platformCode, I_32 portableCode)
182 {
183 PortlibPTBuffers_t ptBuffers;
184
185 /* get the buffers, allocate if necessary.
186 * Silently return if not present, what else would the caller do anyway?
187 */
188 ptBuffers = hyport_tls_get ();
189 if (NULL == ptBuffers)
190 {
191 return portableCode;
192 }
193
194 /* Save the last error */
195 ptBuffers->platformErrorCode = platformCode;
196 ptBuffers->portableErrorCode = portableCode;
197
198 /* Overwrite any customized messages stored */
199 if (ptBuffers->errorMessageBufferSize > 0)
200 {
201 ptBuffers->errorMessageBuffer[0] = '\0';
202 }
203
204 return portableCode;
205 }
206
207
hyerror_set_last_error_with_message(I_32 portableCode,const char * errorMessage)208 I_32 hyerror_set_last_error_with_message (I_32 portableCode, const char *errorMessage)
209 {
210 PortlibPTBuffers_t ptBuffers;
211 U_32 requiredSize;
212
213 /* get the buffers, allocate if necessary.
214 * Silently return if not present, what else would the caller do anyway?
215 */
216 ptBuffers = hyport_tls_get ();
217 if (NULL == ptBuffers)
218 {
219 return portableCode;
220 }
221
222 /* Save the last error */
223 ptBuffers->platformErrorCode = -1;
224 ptBuffers->portableErrorCode = portableCode;
225
226 /* Store the message, allocate a bigger buffer if required. Keep the old buffer around
227 * just in case memory can not be allocated
228 */
229 requiredSize = strlen (errorMessage) + 1;
230 requiredSize =
231 requiredSize <
232 HYERROR_DEFAULT_BUFFER_SIZE ? HYERROR_DEFAULT_BUFFER_SIZE : requiredSize;
233 if (requiredSize > ptBuffers->errorMessageBufferSize)
234 {
235 char *newBuffer = XMLVM_ATOMIC_MALLOC(requiredSize);
236 if (NULL != newBuffer)
237 {
238 if (ptBuffers->errorMessageBuffer != NULL)
239 {
240 XMLVM_FREE(ptBuffers->errorMessageBuffer);
241 }
242 ptBuffers->errorMessageBuffer = newBuffer;
243 ptBuffers->errorMessageBufferSize = requiredSize;
244 }
245 }
246
247 /* Save the message */
248 if (ptBuffers->errorMessageBufferSize > 0)
249 {
250 sprintf(ptBuffers->errorMessageBuffer, "%s", errorMessage);
251 ptBuffers->errorMessageBuffer[ptBuffers->errorMessageBufferSize - 1] = '\0';
252 }
253
254 return portableCode;
255 }
256