Tizen 2.0 Release
[external/libgnutls26.git] / lib / system.c
1 /*
2  * Copyright (C) 2010 Free Software Foundation, Inc.
3  *
4  * Author: Nikos Mavrogiannopoulos
5  *
6  * This file is part of GnuTLS.
7  *
8  * The GnuTLS is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation; either version 2.1 of
11  * the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
21  * USA
22  *
23  */
24
25 #include <system.h>
26 #include <gnutls_int.h>
27 #include <gnutls_errors.h>
28
29 #include <errno.h>
30
31 #ifdef _WIN32
32 #include <windows.h>
33
34 #else
35 #ifdef HAVE_PTHREAD_LOCKS
36 #include <pthread.h>
37 #endif
38 #endif
39
40 /* We need to disable gnulib's replacement wrappers to get native
41    Windows interfaces. */
42 #undef recv
43 #undef send
44
45 /* System specific function wrappers.
46  */
47
48 /* wrappers for write() and writev()
49  */
50 #ifdef _WIN32
51
52 int
53 system_errno (gnutls_transport_ptr p)
54 {
55   int tmperr = WSAGetLastError ();
56   int ret = 0;
57   switch (tmperr)
58     {
59     case WSAEWOULDBLOCK:
60       ret = EAGAIN;
61       break;
62     case WSAEINTR:
63       ret = EINTR;
64       break;
65     default:
66       ret = EIO;
67       break;
68     }
69   WSASetLastError (tmperr);
70
71   return ret;
72 }
73
74 ssize_t
75 system_write (gnutls_transport_ptr ptr, const void *data, size_t data_size)
76 {
77   return send (GNUTLS_POINTER_TO_INT (ptr), data, data_size, 0);
78 }
79 #else /* POSIX */
80 int
81 system_errno (gnutls_transport_ptr ptr)
82 {
83   return errno;
84 }
85
86 ssize_t
87 system_writev (gnutls_transport_ptr ptr, const giovec_t * iovec,
88                int iovec_cnt)
89 {
90   return writev (GNUTLS_POINTER_TO_INT (ptr), (struct iovec *) iovec,
91                  iovec_cnt);
92
93 }
94 #endif
95
96 ssize_t
97 system_read (gnutls_transport_ptr ptr, void *data, size_t data_size)
98 {
99   return recv (GNUTLS_POINTER_TO_INT (ptr), data, data_size, 0);
100 }
101
102 ssize_t
103 system_read_peek (gnutls_transport_ptr ptr, void *data, size_t data_size)
104 {
105   return recv (GNUTLS_POINTER_TO_INT (ptr), data, data_size, MSG_PEEK);
106 }
107
108 /* Thread stuff */
109
110 #ifdef HAVE_WIN32_LOCKS
111
112
113 /* FIXME: win32 locks are untested */
114 static int
115 gnutls_system_mutex_init (void **priv)
116 {
117   CRITICAL_SECTION *lock = malloc (sizeof (CRITICAL_SECTION));
118
119   if (lock == NULL)
120     return GNUTLS_E_MEMORY_ERROR;
121
122   InitializeCriticalSection (lock);
123
124   *priv = lock;
125
126   return 0;
127 }
128
129 static int
130 gnutls_system_mutex_deinit (void **priv)
131 {
132   DeleteCriticalSection ((CRITICAL_SECTION *) * priv);
133   free (*priv);
134
135   return 0;
136 }
137
138 static int
139 gnutls_system_mutex_lock (void **priv)
140 {
141   EnterCriticalSection ((CRITICAL_SECTION *) * priv);
142   return 0;
143 }
144
145 static int
146 gnutls_system_mutex_unlock (void **priv)
147 {
148   LeaveCriticalSection ((CRITICAL_SECTION *) * priv);
149   return 0;
150 }
151
152 int
153 _gnutls_atfork (void (*prepare) (void), void (*parent) (void),
154                 void (*child) (void))
155 {
156   return 0;
157 }
158
159
160 #endif /* WIN32_LOCKS */
161
162 #ifdef HAVE_PTHREAD_LOCKS
163
164 static int
165 gnutls_system_mutex_init (void **priv)
166 {
167   pthread_mutex_t *lock = malloc (sizeof (pthread_mutex_t));
168   int ret;
169
170   if (lock == NULL)
171     return GNUTLS_E_MEMORY_ERROR;
172
173   ret = pthread_mutex_init (lock, NULL);
174   if (ret)
175     {
176       free (lock);
177       gnutls_assert ();
178       return GNUTLS_E_LOCKING_ERROR;
179     }
180
181   *priv = lock;
182
183   return 0;
184 }
185
186 static int
187 gnutls_system_mutex_deinit (void **priv)
188 {
189   pthread_mutex_destroy ((pthread_mutex_t *) * priv);
190   free (*priv);
191   return 0;
192 }
193
194 static int
195 gnutls_system_mutex_lock (void **priv)
196 {
197   if (pthread_mutex_lock ((pthread_mutex_t *) * priv))
198     {
199       gnutls_assert ();
200       return GNUTLS_E_LOCKING_ERROR;
201     }
202
203   return 0;
204 }
205
206 static int
207 gnutls_system_mutex_unlock (void **priv)
208 {
209   if (pthread_mutex_unlock ((pthread_mutex_t *) * priv))
210     {
211       gnutls_assert ();
212       return GNUTLS_E_LOCKING_ERROR;
213     }
214
215   return 0;
216 }
217
218 int
219 _gnutls_atfork (void (*prepare) (void), void (*parent) (void),
220                 void (*child) (void))
221 {
222   return pthread_atfork (prepare, parent, child);
223 }
224
225 #endif /* PTHREAD_LOCKS */
226
227 #ifdef HAVE_NO_LOCKS
228
229 static int
230 gnutls_system_mutex_init (void **priv)
231 {
232   return 0;
233 }
234
235 static int
236 gnutls_system_mutex_deinit (void **priv)
237 {
238   return 0;
239 }
240
241 static int
242 gnutls_system_mutex_lock (void **priv)
243 {
244   return 0;
245 }
246
247 static int
248 gnutls_system_mutex_unlock (void **priv)
249 {
250   return 0;
251 }
252
253 int
254 _gnutls_atfork (void (*prepare) (void), void (*parent) (void),
255                 void (*child) (void))
256 {
257   return 0;
258 }
259
260 #endif /* NO_LOCKS */
261
262 gnutls_time_func gnutls_time = time;
263 mutex_init_func gnutls_mutex_init = gnutls_system_mutex_init;
264 mutex_deinit_func gnutls_mutex_deinit = gnutls_system_mutex_deinit;
265 mutex_lock_func gnutls_mutex_lock = gnutls_system_mutex_lock;
266 mutex_unlock_func gnutls_mutex_unlock = gnutls_system_mutex_unlock;