NCBI C++ ToolKit
threadsafe.c
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
2  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Brian Bruns
3  * Copyright (C) 2005-2015 Frediano Ziglio
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20 
21 #include <config.h>
22 
23 #include <stdarg.h>
24 #include <stdio.h>
25 
26 #if HAVE_UNISTD_H
27 #include <unistd.h>
28 #endif /* HAVE_UNISTD_H */
29 
30 #include <freetds/time.h>
31 
32 #if defined(HAVE_GETUID) && defined(HAVE_GETPWUID)
33 #include <pwd.h>
34 #endif
35 
36 #if HAVE_STDLIB_H
37 #include <stdlib.h>
38 #endif /* HAVE_STDLIB_H */
39 
40 #if HAVE_STRING_H
41 #include <string.h>
42 #endif /* HAVE_STRING_H */
43 
44 #if HAVE_NETDB_H
45 #include <netdb.h>
46 #endif /* HAVE_NETDB_H */
47 
48 #if HAVE_ERRNO_H
49 #include <errno.h>
50 #endif /* HAVE_ERRNO_H */
51 
52 #if HAVE_SYS_SOCKET_H
53 #include <sys/socket.h>
54 #endif /* HAVE_SYS_SOCKET_H */
55 
56 #if HAVE_NETINET_IN_H
57 #include <netinet/in.h>
58 #endif /* HAVE_NETINET_IN_H */
59 
60 #if HAVE_ARPA_INET_H
61 #include <arpa/inet.h>
62 #endif /* HAVE_ARPA_INET_H */
63 
64 #if HAVE_ROKEN_H
65 #include <roken.h>
66 #endif /* HAVE_ROKEN_H */
67 
68 #if defined(_WIN32) || defined(_WIN64)
69 #include <winsock2.h>
70 #include <shlobj.h>
71 #endif
72 
73 #include <freetds/tds.h>
74 #include <freetds/thread.h>
75 #include "replacements.h"
76 
77 struct tm *
78 tds_localtime_r(const time_t *timep, struct tm *result)
79 {
80  struct tm *tm;
81 
82 #if defined(_REENTRANT) && !defined(_WIN32)
83 #if HAVE_FUNC_LOCALTIME_R_TM
84  tm = localtime_r(timep, result);
85 #else
86  tm = NULL;
87  if (!localtime_r(timep, result))
88  tm = result;
89 #endif /* HAVE_FUNC_LOCALTIME_R_TM */
90 #else
91  tm = localtime(timep);
92  if (tm) {
93  memcpy(result, tm, sizeof(*result));
94  tm = result;
95  }
96 #endif
97  return tm;
98 }
99 
100 char *
101 tds_timestamp_str(char *str, int maxlen)
102 {
103 #if !defined(_WIN32) && !defined(_WIN64)
104  struct tm *tm;
105  struct tm res;
106  time_t t;
107 
108 #if HAVE_GETTIMEOFDAY
109  struct timeval tv;
110  char usecs[10];
111 
112  gettimeofday(&tv, NULL);
113  t = tv.tv_sec;
114 #else
115  /*
116  * XXX Need to get a better time resolution for
117  * systems that don't have gettimeofday().
118  */
119  time(&t);
120 #endif
121 
122  tm = tds_localtime_r(&t, &res);
123 
124 /** strftime(str, maxlen - 6, "%Y-%m-%d %H:%M:%S", tm); **/
125  strftime(str, maxlen - 6, "%H:%M:%S", tm);
126 
127 #if HAVE_GETTIMEOFDAY
128  sprintf(usecs, ".%06lu", (long) tv.tv_usec);
129  strcat(str, usecs);
130 #endif
131 
132 #else /* _WIN32 */
133  SYSTEMTIME st;
134 
135  GetLocalTime(&st);
136  _snprintf(str, maxlen - 1, "%02u:%02u:%02u.%03u", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
137  str[maxlen - 1] = 0;
138 #endif
139 
140  return str;
141 }
142 
143 /*
144  * If reentrant code was not requested, we don't care reentrancy, so
145  * just assume the standard BSD netdb interface is reentrant and use it.
146  */
147 #ifndef _REENTRANT
148 # undef NETDB_REENTRANT
149 # define NETDB_REENTRANT 1
150 #endif /* _REENTRANT */
151 
152 #if !defined(HAVE_GETADDRINFO)
153 
154 #if defined(NETDB_REENTRANT)
155 struct hostent *
156 tds_gethostbyname_r(const char *servername, struct hostent *result, char *buffer, int buflen, int *h_errnop)
157 {
158  return gethostbyname(servername);
159 }
160 
161 #elif defined(HAVE_GETIPNODEBYNAME) || defined(HAVE_GETIPNODEBYADDR)
162 /**
163  * Copy a hostent structure to an allocated buffer
164  * @return 0 on success, -1 otherwise
165  */
166 static int
167 tds_copy_hostent(struct hostent *he, struct hostent *result, char *buffer, int buflen)
168 {
169 #define CHECK_BUF(len) \
170  if (p + sizeof(struct hostent) - buffer > buflen) return -1;
171 #define ALIGN_P do { p += TDS_ALIGN_SIZE - 1; p -= (p-buffer) % TDS_ALIGN_SIZE; } while(0)
172 
173  int n, i;
174  char *p = buffer;
175  struct hostent *he2;
176 
177  /* copy structure */
178  he2 = result;
179  memcpy(he2, he, sizeof(struct hostent));
180 
181  if (he->h_addr_list) {
182  int len;
183  char **addresses;
184 
185  /* count addresses */
186  for (n = 0; he->h_addr_list[n]; ++n)
187  continue;
188 
189  /* copy addresses */
190  addresses = (char **) p;
191  he2->h_addr_list = (char **) p;
192  len = sizeof(char *) * (n + 1);
193  CHECK_BUF(len);
194  p += len;
195  ALIGN_P;
196  for (i = 0; i < n; ++i) {
197  addresses[i] = p;
198 
199  CHECK_BUF(he->h_length);
200  memcpy(p, he->h_addr_list[i], he->h_length);
201  p += he->h_length;
202  ALIGN_P;
203  }
204  addresses[n] = NULL;
205  }
206 
207  /* copy name */
208  if (he->h_name) {
209  n = strlen(he->h_name) + 1;
210  he2->h_name = p;
211  CHECK_BUF(n);
212  memcpy(p, he->h_name, n);
213  p += n;
214  ALIGN_P;
215  }
216 
217  if (he->h_aliases) {
218  int len;
219  char **aliases;
220 
221  /* count aliases */
222  for (n = 0; he->h_aliases[n]; ++n)
223  continue;
224 
225  /* copy aliases */
226  aliases = (char **) p;
227  he2->h_aliases = (char **) p;
228  len = sizeof(char *) * (n + 1);
229  CHECK_BUF(len);
230  p += len;
231  for (i = 0; i < n; ++i) {
232  len = strlen(he->h_aliases[i]) + 1;
233  aliases[i] = p;
234 
235  CHECK_BUF(len);
236  memcpy(p, he->h_aliases[i], len);
237  p += len;
238  }
239  aliases[n] = NULL;
240  }
241  return 0;
242 }
243 
244 struct hostent *
245 tds_gethostbyname_r(const char *servername, struct hostent *result, char *buffer, int buflen, int *h_errnop)
246 {
247  struct hostent *he = getipnodebyname(servername, AF_INET, 0, h_errnop);
248 
249  if (!he)
250  return NULL;
251  if (tds_copy_hostent(he, result, buffer, buflen)) {
252  errno = ENOMEM;
253  if (h_errnop)
254  *h_errnop = NETDB_INTERNAL;
255  freehostent(he);
256  return NULL;
257  }
258  freehostent(he);
259  return result;
260 }
261 
262 #elif defined(HAVE_FUNC_GETHOSTBYNAME_R_6)
263 struct hostent *
264 tds_gethostbyname_r(const char *servername, struct hostent *result, char *buffer, int buflen, int *h_errnop)
265 {
266  if (gethostbyname_r(servername, result, buffer, buflen, &result, h_errnop))
267  return NULL;
268  return result;
269 }
270 
271 #elif defined(HAVE_FUNC_GETHOSTBYNAME_R_5)
272 struct hostent *
273 tds_gethostbyname_r(const char *servername, struct hostent *result, char *buffer, int buflen, int *h_errnop)
274 {
275  result = gethostbyname_r(servername, result, buffer, buflen, h_errnop);
276  return result;
277 }
278 
279 #elif defined(HAVE_FUNC_GETHOSTBYNAME_R_3)
280 struct hostent *
281 tds_gethostbyname_r(const char *servername, struct hostent *result, char *buffer, int buflen, int *h_errnop)
282 {
283  struct hostent_data *data = (struct hostent_data *) buffer;
284 
285  memset(buffer, 0, buflen);
286  if (gethostbyname_r(servername, result, data)) {
287  *h_errnop = 0;
288  result = NULL;
289  }
290  return result;
291 }
292 
293 #elif defined(TDS_NO_THREADSAFE)
294 struct hostent *
295 tds_gethostbyname_r(const char *servername, struct hostent *result, char *buffer, int buflen, int *h_errnop)
296 {
297  return gethostbyname(servername);
298 }
299 
300 #else
301 #error gethostbyname_r style unknown
302 #endif
303 
304 #endif
305 
306 
307 #if 0
308 #undef HAVE_GETADDRINFO
309 #undef NETDB_REENTRANT
310 #undef HAVE_FUNC_GETSERVBYNAME_R_6
311 #undef HAVE_FUNC_GETSERVBYNAME_R_5
312 #undef HAVE_FUNC_GETSERVBYNAME_R_4
313 #undef TDS_NO_THREADSAFE
314 
315 # if 0
316 # define HAVE_FUNC_GETSERVBYNAME_R_6 1
317 int test_getservbyname_r(const char *name, const char *proto,
318  struct servent *result_buf, char *buffer,
319  size_t buflen, struct servent **result);
320 # define getservbyname_r test_getservbyname_r
321 # elif 0
322 # define HAVE_FUNC_GETSERVBYNAME_R_5 1
323 struct servent *
324 test_getservbyname_r(const char *name, const char *proto,
325  struct servent *result_buf, char *buffer,
326  size_t buflen);
327 # define getservbyname_r test_getservbyname_r
328 # else
329 # define HAVE_FUNC_GETSERVBYNAME_R_4 1
330 struct servent_data { int dummy; };
331 int
332 test_getservbyname_r(const char *name, const char *proto,
333  struct servent *result_buf,
334  struct servent_data *data);
335 # define getservbyname_r test_getservbyname_r
336 # endif
337 #endif
338 
339 /**
340  * Return service port given the name
341  */
342 int
343 tds_getservice(const char *name)
344 {
345 #if defined(HAVE_GETADDRINFO)
346  /* new OSes should implement this in a proper way */
347  struct addrinfo hints, *res;
348  int result;
349 
350  memset(&hints, 0, sizeof(hints));
351  hints.ai_family = AF_INET;
352  hints.ai_socktype = SOCK_STREAM;
353  hints.ai_flags = AI_PASSIVE;
354 #ifdef AI_CANONNAME
355  hints.ai_flags |= AI_CANONNAME;
356 #endif
357  res = NULL;
358  if (getaddrinfo(NULL, name, &hints, &res))
359  return 0;
360  if (res->ai_family != AF_INET || !res->ai_addr) {
361  freeaddrinfo(res);
362  return 0;
363  }
364  result = ntohs(((struct sockaddr_in *) res->ai_addr)->sin_port);
365  freeaddrinfo(res);
366  return result;
367 
368 #elif defined(NETDB_REENTRANT)
369  /* HP-UX/Windows */
370  struct servent *result = getservbyname(name, "tcp");
371  return result ? ntohs(result->s_port) : 0;
372 
373 #elif defined(HAVE_FUNC_GETSERVBYNAME_R_6)
374  /* Linux variant */
375  struct servent *result = NULL;
376  struct servent result_buf;
377  char buffer[4096];
378 
379  if (!getservbyname_r(name, "tcp", &result_buf, buffer, sizeof(buffer), &result))
380  return ntohs(result->s_port);
381  return 0;
382 
383 #elif defined(HAVE_FUNC_GETSERVBYNAME_R_5)
384  /* Solaris variant */
385  struct servent result;
386  char buffer[4096];
387 
388  if (getservbyname_r(name, "tcp", &result, buffer, sizeof(buffer)))
389  return ntohs(result.s_port);
390  return 0;
391 
392 #elif defined(HAVE_FUNC_GETSERVBYNAME_R_4)
393  /* AIX/BSD variant */
394  struct servent result;
395  struct servent_data data;
396 
397  if (!getservbyname_r(name, "tcp", &result, &data))
398  return ntohs(result.s_port);
399  return 0;
400 
401 #elif defined(TDS_NO_THREADSAFE)
402  struct servent *result = getservbyname(name, "tcp");
403  return result ? ntohs(result->s_port) : 0;
404 #else
405 #error getservbyname_r style unknown
406 #endif
407 }
408 
409 /**
410  * Get user home directory
411  * @return home directory or NULL if error. Should be freed with free
412  */
413 char *
415 {
416 #ifndef _WIN32
417 /* if is available getpwuid_r use it */
418 #if defined(HAVE_GETUID) && defined(HAVE_GETPWUID_R)
419  struct passwd *pw, bpw;
420  char buf[1024];
421 
422 # if defined(HAVE_FUNC_GETPWUID_R_5)
423  /* getpwuid_r can return 0 if uid is not found so check pw */
424  pw = NULL;
425  if (getpwuid_r(getuid(), &bpw, buf, sizeof(buf), &pw) || !pw)
426  return NULL;
427 
428 # elif defined(HAVE_FUNC_GETPWUID_R_4_PW)
429  if (!(pw = getpwuid_r(getuid(), &bpw, buf, sizeof(buf))))
430  return NULL;
431 # else /* !HAVE_FUNC_GETPWUID_R_4_PW */
432  if (getpwuid_r(getuid(), &bpw, buf, sizeof(buf)))
433  return NULL;
434  pw = &bpw;
435 # endif
436 
437  return strdup(pw->pw_dir);
438 
439 /* if getpwuid is available use it for no reentrant (getpwuid is not reentrant) */
440 #elif defined(HAVE_GETUID) && defined(HAVE_GETPWUID) && !defined(_REENTRANT)
441  struct passwd *pw;
442 
443  pw = getpwuid(getuid());
444  if (!pw)
445  return NULL;
446  return strdup(pw->pw_dir);
447 #else
448  char *home;
449 
450  home = getenv("HOME");
451  if (!home || !home[0])
452  return NULL;
453  return strdup(home);
454 #endif
455 #else /* _WIN32 */
456  /*
457  * For win32 we return application data cause we use "HOME"
458  * only to store configuration files
459  */
460  LPITEMIDLIST pidl;
461  /*
462  * SHGetPathFromIDListA() tries to count the length of "path",
463  * so we have to make sure that it has only zeros; otherwise,
464  * invalid memory access is inevitable.
465  */
466  char path[MAX_PATH] = "";
467  HRESULT hr;
468  LPMALLOC pMalloc = NULL;
469  char * res = NULL;
470 
471  hr = SHGetMalloc(&pMalloc);
472  if (!FAILED(hr)) {
473  hr = SHGetSpecialFolderLocation(NULL, CSIDL_APPDATA, &pidl);
474  if (!FAILED(hr)) {
475  if (SHGetPathFromIDListA(pidl, path))
476  res = strdup(path);
477  (*pMalloc->lpVtbl->Free)(pMalloc, pidl);
478  }
479  (*pMalloc->lpVtbl->Release)(pMalloc);
480  }
481  return res;
482 #endif
483 }
484 
unsigned dummy
Definition: block_cipher.h:0
#define strcat(s, k)
static const char * str(char *buf, int n)
Definition: stats.c:84
#define getaddrinfo(n, s, h, r)
Definition: replacements.h:99
#define addrinfo
Definition: replacements.h:98
#define freeaddrinfo(a)
Definition: replacements.h:101
struct tm * tds_localtime_r(const time_t *timep, struct tm *result)
Definition: threadsafe.c:78
int tds_getservice(const char *name)
Return service port given the name.
Definition: threadsafe.c:343
char * tds_get_homedir(void)
Get user home directory.
Definition: threadsafe.c:414
char * tds_timestamp_str(char *str, int maxlen)
Definition: threadsafe.c:101
struct hostent * tds_gethostbyname_r(const char *servername, struct hostent *result, char *buffer, int buflen, int *h_errnop)
Definition: threadsafe.c:156
char data[12]
Definition: iconv.c:80
#define NULL
Definition: ncbistd.hpp:225
char * buf
int i
yy_size_t n
int len
#define strdup
Definition: ncbi_ansi_ext.h:70
EIPRangeType t
Definition: ncbi_localip.c:101
const double FAILED
Definition: njn_root.hpp:55
static uint8_t * buffer
Definition: pcre2test.c:1016
static SLJIT_INLINE sljit_ins st(sljit_gpr r, sljit_s32 d, sljit_gpr x, sljit_gpr b)
else result
Definition: token2.c:20
Modified on Fri Sep 20 14:57:11 2024 by modify_doxy.py rev. 669887