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