CUBRID Engine  latest
porting.c
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Search Solution Corporation
3  * Copyright 2016 CUBRID Corporation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 /*
20  * porting.c - Functions supporting platform porting
21  */
22 
23 #ident "$Id$"
24 
25 #include "config.h"
26 
27 #include <stdio.h>
28 #include <assert.h>
29 #include <errno.h>
30 #include <signal.h>
31 #include <ctype.h>
32 #include <time.h>
33 
34 #if defined(WINDOWS)
35 #include <tchar.h>
36 #include <float.h>
37 #include <io.h>
38 #include <conio.h>
39 #include <math.h>
40 #else
41 #if defined(AIX)
42 #define _BOOL
43 #include <unistd.h>
44 #include <curses.h>
45 #else
46 #include <unistd.h>
47 #include <curses.h>
48 #endif
49 #endif
50 
51 #include "porting.h"
52 
53 #if !defined(HAVE_ASPRINTF)
54 #include <stdarg.h>
55 #endif
56 
57 #ifndef HAVE_STRLCPY
58 #include <sys/types.h>
59 #include <string.h>
60 #endif
61 
62 #if defined(AIX) && !defined(DONT_HOOK_MALLOC)
63 #undef malloc
64 void *
65 aix_malloc (size_t size)
66 {
67  /* malloc 0 size memory will be failed in AIX */
68  if (size == 0)
69  {
70  size = 1;
71  }
72  return malloc (size);
73 }
74 
75 #define malloc(a) aix_malloc(a)
76 #endif
77 
78 #if defined (WINDOWS)
79 /*
80  * realpath() -
81  * return: pointer to resolved_path or NULL if error occurred
82  * path(in): the relative path to be resolved
83  * resolved_path(out): the buffer to output resolved path
84  */
85 char *
86 realpath (const char *path, char *resolved_path)
87 {
88  struct stat stat_buf;
89  char *tmp_str = _fullpath (resolved_path, path, _MAX_PATH);
90  char tmp_path[_MAX_PATH] = { 0 };
91  size_t len = 0;
92 
93  if (tmp_str != NULL)
94  {
95  strncpy (tmp_path, tmp_str, _MAX_PATH);
96 
97  /*
98  * The output of _fullpath() ends with '\'(Windows format) or without it.
99  * It doesn't end with '/'(Linux format).
100  *
101  * Even if the directory path exists, the stat() in Windows fails when
102  * the directory path ends with '\'.
103  */
104  len = strlen (tmp_path);
105  if (len > 0 && tmp_path[len - 1] == '\\')
106  {
107  tmp_path[len - 1] = '\0';
108  }
109 
110  if (stat (tmp_path, &stat_buf) == 0)
111  {
112  return tmp_str;
113  }
114  }
115 
116  return NULL;
117 }
118 
119 /*
120  * poll() -
121  * return: return poll result
122  * fds(in): socket descriptors to wait
123  * nfds(in): number of descriptors
124  * timeout(in): timeout in milliseconds
125  */
126 int
127 poll (struct pollfd *fds, nfds_t nfds, int timeout)
128 {
129  struct timeval to, *tp;
130  fd_set rset, wset, eset;
131  fd_set *rp, *wp, *ep;
132  unsigned long int i;
133  int r;
134  unsigned long long max_fd;
135 
136  tp = NULL;
137  if (timeout >= 0)
138  {
139  to.tv_sec = timeout / 1000;
140  to.tv_usec = (timeout % 1000) * 1000;
141  tp = &to;
142  }
143 
144  FD_ZERO (&rset);
145  FD_ZERO (&wset);
146  FD_ZERO (&eset);
147  rp = wp = ep = NULL;
148  max_fd = 0;
149 
150  for (i = 0; i < nfds; i++)
151  {
152  if (fds[i].events & POLLIN)
153  {
154  if (rp == NULL)
155  {
156  rp = &rset;
157  }
158  FD_SET (fds[i].fd, rp);
159  max_fd = MAX (fds[i].fd, max_fd);
160  }
161  if (fds[i].events & POLLOUT)
162  {
163  if (wp == NULL)
164  {
165  wp = &wset;
166  }
167  FD_SET (fds[i].fd, wp);
168  max_fd = MAX (fds[i].fd, max_fd);
169  }
170  if (fds[i].events & POLLPRI)
171  {
172  if (ep == NULL)
173  {
174  ep = &eset;
175  }
176  FD_SET (fds[i].fd, ep);
177  max_fd = MAX (fds[i].fd, max_fd);
178  }
179  }
180 
181  r = select ((int) max_fd + 1, rp, wp, ep, tp);
182  for (i = 0; i < nfds; i++)
183  {
184  fds[i].revents = 0;
185  if ((fds[i].events & POLLIN) && FD_ISSET (fds[i].fd, rp))
186  {
187  fds[i].revents |= POLLIN;
188  }
189  if ((fds[i].events & POLLOUT) && FD_ISSET (fds[i].fd, wp))
190  {
191  fds[i].revents |= POLLOUT;
192  }
193  if ((fds[i].events & POLLPRI) && FD_ISSET (fds[i].fd, ep))
194  {
195  fds[i].revents |= POLLPRI;
196  }
197  }
198 
199  return r;
200 }
201 
202 /* Number of 100 nanosecond units from 1/1/1601 to 1/1/1970 */
203 #define EPOCH_BIAS_IN_100NANOSECS 116444736000000000LL
204 
205 /*
206  * gettimeofday - Windows port of Unix gettimeofday()
207  * return: none
208  * tp(out): where time is stored
209  * tzp(in): unused
210  */
211 int
212 gettimeofday (struct timeval *tp, void *tzp)
213 {
214 /*
215  * Rapid calculation divisor for 10,000,000
216  * x/10000000 == x/128/78125 == (x>>7)/78125
217  */
218 #define RAPID_CALC_DIVISOR 78125
219 
220  union
221  {
222  unsigned __int64 nsec100; /* in 100 nanosecond units */
223  FILETIME ft;
224  } now;
225 
226  GetSystemTimeAsFileTime (&now.ft);
227 
228  /*
229  * Optimization for sec = (long) (x / 10000000);
230  * where "x" is number of 100 nanoseconds since 1/1/1970.
231  */
232  tp->tv_sec = (long) (((now.nsec100 - EPOCH_BIAS_IN_100NANOSECS) >> 7) / RAPID_CALC_DIVISOR);
233 
234  /*
235  * Optimization for usec = (long) (x % 10000000) / 10;
236  * Let c = x / b,
237  * An alternative for MOD operation (x % b) is: (x - c * b),
238  * which consumes less time, specially, for a 64 bit "x".
239  */
240  tp->tv_usec =
241  ((long) (now.nsec100 - EPOCH_BIAS_IN_100NANOSECS - (((unsigned __int64) (tp->tv_sec * RAPID_CALC_DIVISOR)) << 7))) /
242  10;
243 
244  return 0;
245 }
246 
247 #define LOCKING_SIZE 2000
248 /*
249  * lockf() - lockf() WINDOWS implementation
250  * return: 0 if success, -1 otherwise
251  * fd(in): file descriptor
252  * cmd(in): locking command to perform
253  * size(in): number of bytes
254  */
255 int
256 lockf (int fd, int cmd, long size)
257 {
258  switch (cmd)
259  {
260  case F_ULOCK:
261  return (_locking (fd, _LK_UNLCK, (size ? size : LOCKING_SIZE)));
262 
263  case F_LOCK:
264  return (_locking (fd, _LK_LOCK, (size ? size : LOCKING_SIZE)));
265 
266  case F_TLOCK:
267  return (_locking (fd, _LK_NBLCK, (size ? size : LOCKING_SIZE)));
268 
269  case F_TEST:
270  /* not implemented on WINDOWS */
271  return (-1);
272 
273  default:
274  errno = EINVAL;
275  return (-1);
276  }
277 }
278 
279 /*
280  * cuserid - returns a pointer to a string containing a user name
281  * associated with the effective user ID of the process
282  * return: string
283  * string(in):
284  *
285  * Note: Changed to allow the user name to be specified using an environment
286  * variable. This is primarily so that abortdb can have something
287  * meaningful when it displays connection info.
288  */
289 char *
290 cuserid (char *string)
291 {
292  const char *env;
293 
294  /* make 'em supply a buffer */
295  if (string != NULL)
296  {
297  env = getenv ("USERNAME");
298  if (env == NULL)
299  {
300  strcpy (string, "noname");
301  }
302  else
303  {
304  strlcpy (string, env, L_cuserid);
305  }
306 
307  return string;
308  }
309 
310  return string;
311 }
312 
313 int
314 getlogin_r (char *buf, size_t bufsize)
315 {
316  DWORD wd = static_cast < DWORD > (bufsize);
317  return GetUserName (buf, &wd);
318 }
319 
320 #if 0
321 /*
322  * umask - This is a stub for umask()
323  * return:
324  * mask(in):
325  *
326  * Note: It belongs in the os unit and should be moved there.
327  */
328 int
329 umask (int mask)
330 {
331  return (0);
332 }
333 #endif
334 
335 /*
336  * fsync - This is a stub for fsync()
337  * return:
338  * fd(in):
339  *
340  * Note: It belongs in the os unit and should be moved there.
341  */
342 int
343 fsync (int filedes)
344 {
345  return 0;
346 }
347 
348 /*
349  * pathconf -
350  * return:
351  * path(in):
352  * name(in):
353  *
354  * Note:
355  */
356 long
357 pathconf (char *path, int name)
358 {
359 
360  long namelen;
361  long filesysflags;
362 
363  switch (name)
364  {
365  case _PC_PATH_MAX:
366  /*
367  * NT and OS/2 file systems claim to be able to handle 255 char
368  * file names. But none of the system calls seem to be able to
369  * handle a path of more than 255 chars + 1 NULL. Nor does there
370  * appear to be a system function to return the real max length.
371  * MAX_PATH is defined in stdlib.h on the NT system.
372  */
373  return ((MAX_PATH - 1));
374 
375  case _PC_NAME_MAX:
376  if (GetVolumeInformation (NULL, NULL, 0, NULL, (LPDWORD) & namelen, (LPDWORD) & filesysflags, NULL, 0))
377  {
378  /* WARNING!, for "old" DOS style file systems, namelen will be 12 right now, totaling the 8 bytes for name
379  * with the 3 bytes for for extension plus a dot. This ISN'T what the caller wants, It really wants the
380  * maximum size of an unqualified pathname. I'm not sure what this works out to be under the new file system.
381  * We probably need to make a similar adjustment but hopefully we'll have more breathing room. */
382  if (namelen == 12)
383  namelen = 8;
384 
385  return (namelen);
386  }
387  else
388  {
389  return (8); /* Length of MSDOS file name */
390  }
391 
392  case _PC_NO_TRUNC:
393  return (TRUE);
394 
395  default:
396  return (-1);
397  }
398 }
399 
400 #define SIG_BLOCK 0
401 #define SIG_UNBLOCK 1
402 #define SIG_SETMASK 2
403 #define SIGABRT_BIT 1
404 #define SIGFPE_BIT 2
405 #define SIGILL_BIT 4
406 #define SIGINT_BIT 8
407 #define SIGSEGV_BIT 16
408 #define SIGTERM_BIT 64
409 
410 /*
411  * sigfillset -
412  * return:
413  * set(in/out):
414  */
415 int
416 sigfillset (sigset_t * set)
417 {
418  if (set)
419  {
420  set->mask = 0;
421  return (0);
422  }
423  else
424  {
425  return (-1);
426  }
427 }
428 
429 /* satic function for sigprocmask */
430 static int setmask (sigset_t * set, sigset_t * oldset);
431 static int block_signals (sigset_t * set, sigset_t * oldset);
432 static int unblock_signals (sigset_t * set, sigset_t * oldset);
433 static void sync_mask (sigset_t * set);
434 
435 /*
436  * setmask -
437  * return:
438  * set(in/out):
439  * oldset(out):
440  */
441 static int
442 setmask (sigset_t * set, sigset_t * oldset)
443 {
444  sigset_t tmp;
445  unsigned int test;
446 
447  if (set)
448  {
449  test = set->mask;
450  }
451  else
452  {
453  test = -1;
454  }
455 
456  tmp.mask = set->mask;
457 
458  tmp.abrt_state = signal (SIGABRT, (tmp.mask |= SIGABRT_BIT) ? SIG_IGN : SIG_DFL);
459  if (tmp.abrt_state < 0)
460  goto whoops;
461  if (!set)
462  (void) signal (SIGABRT, tmp.abrt_state);
463 
464  tmp.fpe_state = signal (SIGFPE, (tmp.mask |= SIGFPE_BIT) ? SIG_IGN : SIG_DFL);
465  if (tmp.fpe_state < 0)
466  goto whoops;
467  if (!set)
468  (void) signal (SIGFPE, tmp.fpe_state);
469 
470  tmp.ill_state = signal (SIGILL, (tmp.mask |= SIGILL_BIT) ? SIG_IGN : SIG_DFL);
471  if (tmp.ill_state < 0)
472  goto whoops;
473  if (!set)
474  (void) signal (SIGILL, tmp.ill_state);
475 
476  tmp.int_state = signal (SIGINT, (tmp.mask |= SIGINT_BIT) ? SIG_IGN : SIG_DFL);
477  if (tmp.int_state < 0)
478  goto whoops;
479  if (!set)
480  (void) signal (SIGINT, tmp.int_state);
481 
482  tmp.sev_state = signal (SIGSEGV, (tmp.mask |= SIGSEGV_BIT) ? SIG_IGN : SIG_DFL);
483  if (tmp.sev_state < 0)
484  goto whoops;
485  if (!set)
486  (void) signal (SIGSEGV, tmp.sev_state);
487 
488  tmp.term_state = signal (SIGTERM, (tmp.mask |= SIGTERM_BIT) ? SIG_IGN : SIG_DFL);
489  if (tmp.term_state < 0)
490  goto whoops;
491  if (!set)
492  (void) signal (SIGTERM, tmp.term_state);
493 
494  if (oldset)
495  {
496  oldset->term_state = tmp.term_state;
497  oldset->sev_state = tmp.sev_state;
498  oldset->int_state = tmp.int_state;
499  oldset->ill_state = tmp.ill_state;
500  oldset->fpe_state = tmp.fpe_state;
501  oldset->abrt_state = tmp.abrt_state;
502  sync_mask (oldset);
503  }
504 
505  return (0);
506 
507 whoops:
508  /*
509  * I'm supposed to restore the signals to the original
510  * state if something fails, but I'm blowing it off for now.
511  */
512 
513  return (-1);
514 }
515 
516 /*
517  * block_signals -
518  * return:
519  * set(in/out):
520  * oldset(out):
521  */
522 static int
523 block_signals (sigset_t * set, sigset_t * oldset)
524 {
525  sigset_t tmp;
526  unsigned int test;
527 
528  if (set)
529  {
530  test = set->mask;
531  }
532  else
533  {
534  test = -1;
535  }
536 
537  tmp.mask = 0;
538 
539  if (test & SIGABRT_BIT)
540  {
541  tmp.mask |= SIGABRT_BIT;
542  tmp.abrt_state = signal (SIGABRT, SIG_IGN);
543  if (tmp.abrt_state < 0)
544  goto whoops;
545  if (!set)
546  (void) signal (SIGABRT, tmp.abrt_state);
547  }
548 
549  if (test & SIGFPE_BIT)
550  {
551  tmp.mask |= SIGFPE_BIT;
552  tmp.fpe_state = signal (SIGFPE, SIG_IGN);
553  if (tmp.fpe_state < 0)
554  goto whoops;
555  if (!set)
556  (void) signal (SIGFPE, tmp.fpe_state);
557  }
558 
559  if (test & SIGILL_BIT)
560  {
561  tmp.mask |= SIGILL_BIT;
562  tmp.ill_state = signal (SIGILL, SIG_IGN);
563  if (tmp.ill_state < 0)
564  goto whoops;
565  if (!set)
566  (void) signal (SIGILL, tmp.ill_state);
567  }
568 
569  if (test & SIGINT_BIT)
570  {
571  tmp.mask |= SIGINT_BIT;
572  tmp.int_state = signal (SIGINT, SIG_IGN);
573  if (tmp.int_state < 0)
574  goto whoops;
575  if (!set)
576  (void) signal (SIGINT, tmp.int_state);
577  }
578 
579  if (test & SIGSEGV_BIT)
580  {
581  tmp.mask |= SIGSEGV_BIT;
582  tmp.sev_state = signal (SIGSEGV, SIG_IGN);
583  if (tmp.sev_state < 0)
584  goto whoops;
585  if (!set)
586  (void) signal (SIGSEGV, tmp.sev_state);
587  }
588 
589  if (test & SIGTERM_BIT)
590  {
591  tmp.mask |= SIGTERM_BIT;
592  tmp.term_state = signal (SIGTERM, SIG_IGN);
593  if (tmp.term_state < 0)
594  goto whoops;
595  if (!set)
596  (void) signal (SIGTERM, tmp.term_state);
597  }
598 
599  if (oldset)
600  {
601  oldset->term_state = tmp.term_state;
602  oldset->sev_state = tmp.sev_state;
603  oldset->int_state = tmp.int_state;
604  oldset->ill_state = tmp.ill_state;
605  oldset->fpe_state = tmp.fpe_state;
606  oldset->abrt_state = tmp.abrt_state;
607  sync_mask (oldset);
608  }
609 
610  return (0);
611 
612 whoops:
613  /*
614  * I'm supposed to restore the signals to the original
615  * state if something fails, but I'm blowing it off for now.
616  */
617 
618  return (-1);
619 }
620 
621 /*
622  * unblock_signals -
623  * return:
624  * set(in/out):
625  * oldset(out):
626  */
627 static int
628 unblock_signals (sigset_t * set, sigset_t * oldset)
629 {
630  sigset_t tmp;
631  unsigned int test;
632 
633  if (set)
634  {
635  test = set->mask;
636  }
637  else
638  {
639  test = -1;
640  }
641 
642  tmp.mask = 0;
643 
644  if (test & SIGABRT_BIT)
645  {
646  tmp.mask |= SIGABRT_BIT;
647  tmp.abrt_state = signal (SIGABRT, set->abrt_state);
648  if (tmp.abrt_state < 0)
649  goto whoops;
650  if (!set)
651  (void) signal (SIGABRT, tmp.abrt_state);
652  }
653 
654  if (test & SIGFPE_BIT)
655  {
656  tmp.mask |= SIGFPE_BIT;
657  tmp.fpe_state = signal (SIGFPE, set->fpe_state);
658  if (tmp.fpe_state < 0)
659  goto whoops;
660  if (!set)
661  (void) signal (SIGFPE, tmp.fpe_state);
662  }
663 
664  if (test & SIGILL_BIT)
665  {
666  tmp.mask |= SIGILL_BIT;
667  tmp.ill_state = signal (SIGILL, set->ill_state);
668  if (tmp.ill_state < 0)
669  goto whoops;
670  if (!set)
671  (void) signal (SIGILL, tmp.ill_state);
672  }
673 
674  if (test & SIGINT_BIT)
675  {
676  tmp.mask |= SIGINT_BIT;
677  tmp.int_state = signal (SIGINT, set->int_state);
678  if (tmp.int_state < 0)
679  goto whoops;
680  if (!set)
681  (void) signal (SIGINT, tmp.int_state);
682  }
683 
684  if (test & SIGSEGV_BIT)
685  {
686  tmp.mask |= SIGSEGV_BIT;
687  tmp.sev_state = signal (SIGSEGV, set->sev_state);
688  if (tmp.sev_state < 0)
689  goto whoops;
690  if (!set)
691  (void) signal (SIGSEGV, tmp.sev_state);
692  }
693 
694  if (test & SIGTERM_BIT)
695  {
696  tmp.mask |= SIGTERM_BIT;
697  tmp.term_state = signal (SIGTERM, set->term_state);
698  if (tmp.term_state < 0)
699  goto whoops;
700  if (!set)
701  (void) signal (SIGTERM, tmp.term_state);
702  }
703 
704  if (oldset)
705  {
706  oldset->term_state = tmp.term_state;
707  oldset->sev_state = tmp.sev_state;
708  oldset->int_state = tmp.int_state;
709  oldset->ill_state = tmp.ill_state;
710  oldset->fpe_state = tmp.fpe_state;
711  oldset->abrt_state = tmp.abrt_state;
712  sync_mask (oldset);
713  }
714 
715  return (0);
716 
717 whoops:
718  /*
719  * I'm supposed to restore the signals to the original
720  * state if something fails, but I'm blowing it off for now.
721  */
722 
723  return (-1);
724 }
725 
726 /*
727  * sync_mask -
728  * return:
729  * set(in/out):
730  */
731 static void
732 sync_mask (sigset_t * set)
733 {
734  set->mask |= (set->term_state == SIG_IGN) ? SIGTERM_BIT : set->mask;
735  set->mask |= (set->sev_state == SIG_IGN) ? SIGSEGV_BIT : set->mask;
736  set->mask |= (set->int_state == SIG_IGN) ? SIGINT_BIT : set->mask;
737  set->mask |= (set->ill_state == SIG_IGN) ? SIGILL_BIT : set->mask;
738  set->mask |= (set->fpe_state == SIG_IGN) ? SIGFPE_BIT : set->mask;
739  set->mask |= (set->abrt_state == SIG_IGN) ? SIGABRT_BIT : set->mask;
740 }
741 
742 /*
743  * sigprocmask -
744  * return:
745  * how(in):
746  * set(in/out):
747  * oldset(out):
748  *
749  * Note:
750  */
751 int
752 sigprocmask (int how, sigset_t * set, sigset_t * oldset)
753 {
754  switch (how)
755  {
756  case SIG_BLOCK:
757  return (block_signals (set, oldset));
758 
759  case SIG_UNBLOCK:
760  return (unblock_signals (set, oldset));
761 
762  case SIG_SETMASK:
763  return (setmask (set, oldset));
764  }
765 
766  return (-1);
767 }
768 
769 /*
770  * getpagesize -
771  * return:
772  */
773 DWORD
774 getpagesize ()
775 {
776  static DWORD NT_PageSize = 0;
777  SYSTEM_INFO sysinfo;
778 
779  if (NT_PageSize == 0)
780  {
781  GetSystemInfo (&sysinfo);
782  NT_PageSize = sysinfo.dwPageSize;
783  }
784  return (NT_PageSize);
785 }
786 
787 #if 0
788 /*
789  * stat - Windows port of Unix stat()
790  * return: 0 or -1
791  * path(in): file path
792  * buffer(in): struct _stat
793  */
794 int
795 stat (const char *path, struct stat *buf)
796 {
797  struct _stat _buf;
798  int rc;
799 
800  rc = _stat (path, &_buf);
801  if (buf)
802  *buf = _buf;
803  return rc;
804 }
805 #endif
806 
807 /*
808  * pc_init()
809  * return: none
810  */
811 void
812 pc_init (void)
813 {
814  unsigned int fpbits;
815 
816  fpbits = _EM_OVERFLOW | _EM_UNDERFLOW | _EM_ZERODIVIDE;
817  (void) _control87 (fpbits, fpbits);
818 }
819 
820 /*
821  * pc_final()
822  * return: none
823  */
824 void
825 pc_final (void)
826 {
827 }
828 
829 #if defined (ENABLE_UNUSED_FUNCTION)
830 /*
831  * lock_region() - lock/unlock region of a file
832  * return: 0 if success, -1 otherwise
833  * fd(in): file descriptor
834  * cmd(in): locking command to perform
835  * offset(in): start offset
836  * size(in): number of bytes
837  */
838 int
839 lock_region (int fd, int cmd, long offset, long size)
840 {
841  if (lseek (fd, offset, SEEK_SET) != offset)
842  {
843  return -1;
844  }
845  return lockf (fd, cmd, size);
846 }
847 #endif /* ENABLE_UNUSED_FUNCTION */
848 
849 /* free_space -
850  * return:
851  * path(in):
852  * page_size(in):
853  *
854  * Note:
855  * This function is designed to be compatible with both wide character
856  * and single byte character strings. Hence, the use of tchar.h.
857  * The definition of 'UNICODE' during compilation determines that TCHAR
858  * becomes 'wchar_t' and not 'char'. If so, we assume that 'path' is
859  * already a wide character type.
860  */
861 int
862 free_space (const char *path, int page_size)
863 {
864  ULARGE_INTEGER freebytes_user, total_bytes, freebytes_system;
865  TCHAR disk[PATH_MAX];
866  TCHAR *temp = NULL;
867 
868  /* If there is a : then change c:\foo\bar to c:\ */
869  _tcsncpy (disk, (TCHAR *) path, PATH_MAX);
870 
871  temp = _tcschr (disk, __TEXT (':'));
872  if (temp)
873  {
874  ++temp; /* move past the colon */
875  if (*temp == __TEXT ('\\') || *temp == __TEXT ('/'))
876  {
877  ++temp;
878  }
879  *temp = __TEXT ('\0'); /* terminate the string */
880  }
881 
882  /* if there's no colon use the root of local dir by passing a NULL */
883  if (!GetDiskFreeSpaceEx ((temp) ? disk : NULL, &freebytes_user, &total_bytes, &freebytes_system))
884  {
885  return (-1);
886  }
887  else
888  {
889  return ((int) (freebytes_user.QuadPart / page_size));
890  }
891 }
892 #endif /* WINDOWS */
893 
894 #if !defined(HAVE_STRDUP)
895 /*
896  * strdup() - duplicate a string
897  * return: returns a pointer to the duplicated string
898  * str(in): string
899  */
900 char *
901 strdup (const char *str)
902 {
903  char *sdup;
904 
905  assert (str != NULL);
906 
907  size_t len = strlen (str) + 1;
908  sdup = (char *) malloc (len);
909  if (sdup != NULL)
910  {
911  memcpy (sdup, str, len);
912  }
913 
914  return sdup;
915 }
916 #endif /* !HAVE_STRDUP */
917 
918 #if !defined(HAVE_VASPRINTF)
919 #if defined(WINDOWS)
920 int
921 vasprintf (char **ptr, const char *format, va_list ap)
922 {
923  int len;
924 
925  len = _vscprintf_p (format, ap) + 1;
926  *ptr = (char *) malloc (len * sizeof (char));
927  if (!*ptr)
928  {
929  return -1;
930  }
931 
932  return _vsprintf_p (*ptr, len, format, ap);
933 }
934 #else
935 int
936 vasprintf (char **ptr, const char *format, va_list ap)
937 {
938  va_list ap_copy;
939  char *buffer = NULL;
940  int count;
941 
942  va_copy (ap_copy, ap);
943  count = vsnprintf (NULL, 0, format, ap);
944  if (count >= 0)
945  {
946  buffer = (char *) malloc (count + 1);
947  if (buffer != NULL)
948  {
949  count = vsnprintf (buffer, count + 1, format, ap_copy);
950  if (count < 0)
951  {
952  free (buffer);
953  }
954  else
955  {
956  *ptr = buffer;
957  }
958  }
959  else
960  {
961  count = -1;
962  }
963  }
964  va_end (ap_copy);
965 
966  return count;
967 }
968 #endif
969 #endif /* !HAVE_VASPRINTF */
970 
971 #if !defined(HAVE_ASPRINTF)
972 int
973 asprintf (char **ptr, const char *format, ...)
974 {
975  va_list ap;
976  int ret;
977 
978  *ptr = NULL;
979 
980  va_start (ap, format);
981  ret = vasprintf (ptr, format, ap);
982  va_end (ap);
983 
984  return ret;
985 }
986 #endif /* !HAVE_ASPRINTF */
987 
988 int
989 cub_dirname_r (const char *path, char *pathbuf, size_t buflen)
990 {
991  const char *endp;
992  ptrdiff_t len;
993 
994  if (buflen < 2)
995  return (errno = ERANGE);
996 
997  /* Empty or NULL string gets treated as "." */
998  if (path == NULL || *path == '\0')
999  {
1000  pathbuf[0] = PATH_CURRENT;
1001  pathbuf[1] = '\0';
1002  return 1;
1003  }
1004 
1005  /* Strip trailing slashes */
1006  endp = path + strlen (path) - 1;
1007  while (endp > path && *endp == PATH_SEPARATOR)
1008  endp--;
1009 
1010  /* Find the start of the dir */
1011  while (endp > path && *endp != PATH_SEPARATOR)
1012  endp--;
1013 
1014  /* Either the dir is "/" or there are no slashes */
1015  if (endp == path)
1016  {
1017  if (*endp == PATH_SEPARATOR)
1018  pathbuf[0] = PATH_SEPARATOR;
1019  else
1020  pathbuf[0] = PATH_CURRENT;
1021  pathbuf[1] = '\0';
1022  return 1;
1023  }
1024  else
1025  {
1026  do
1027  {
1028  endp--;
1029  }
1030  while (endp > path && *endp == PATH_SEPARATOR);
1031  }
1032 
1033  len = (ptrdiff_t) (endp - path) + 1;
1034  if (len + 1 > PATH_MAX)
1035  {
1036  return (errno = ENAMETOOLONG);
1037  }
1038  if (len + 1 > (int) buflen)
1039  {
1040  return (errno = ERANGE);
1041  }
1042  (void) strncpy (pathbuf, path, len);
1043  pathbuf[len] = '\0';
1044  return (int) len;
1045 }
1046 
1047 #if defined(AIX)
1048 #undef ceil
1049 double
1050 aix_ceil (double x)
1051 {
1052  double result = ceil (x);
1053  /* e.g ceil(-0.5) should be -0, in AIX, it is 0 */
1054  if ((x < 0) && (result == 0))
1055  {
1056  result = -result;
1057  }
1058  return result;
1059 }
1060 
1061 #define ceil(x) aix_ceil(x)
1062 #endif
1063 
1064 #if !defined(HAVE_DIRNAME)
1065 char *
1066 dirname (const char *path)
1067 {
1068  static char *bname = NULL;
1069 
1070  if (bname == NULL)
1071  {
1072  bname = (char *) malloc (PATH_MAX);
1073  if (bname == NULL)
1074  return (NULL);
1075  }
1076 
1077  return (cub_dirname_r (path, bname, PATH_MAX) < 0) ? NULL : bname;
1078 }
1079 #endif /* !HAVE_DIRNAME */
1080 
1081 int
1082 basename_r (const char *path, char *pathbuf, size_t buflen)
1083 {
1084  const char *endp, *startp;
1085  ptrdiff_t len;
1086 
1087  if (buflen < 2)
1088  return (errno = ERANGE);
1089 
1090  /* Empty or NULL string gets treated as "." */
1091  if (path == NULL || *path == '\0')
1092  {
1093  pathbuf[0] = PATH_CURRENT;
1094  pathbuf[1] = '\0';
1095  return 1;
1096  }
1097 
1098  /* Strip trailing slashes */
1099  endp = path + strlen (path) - 1;
1100  while (endp > path && *endp == PATH_SEPARATOR)
1101  endp--;
1102 
1103  /* All slashes becomes "/" */
1104  if (endp == path && *endp == PATH_SEPARATOR)
1105  {
1106  pathbuf[0] = PATH_SEPARATOR;
1107  pathbuf[1] = '\0';
1108  return 1;
1109  }
1110 
1111  /* Find the start of the base */
1112  startp = endp;
1113  while (startp > path && *(startp - 1) != PATH_SEPARATOR)
1114  startp--;
1115 
1116  len = (ptrdiff_t) (endp - startp) + 1;
1117  if (len + 1 > PATH_MAX)
1118  {
1119  return (errno = ENAMETOOLONG);
1120  }
1121  if (len + 1 > (int) buflen)
1122  {
1123  return (errno = ERANGE);
1124  }
1125  (void) strncpy (pathbuf, startp, len);
1126  pathbuf[len] = '\0';
1127  return (int) len;
1128 }
1129 
1130 #if !defined(HAVE_BASENAME)
1131 char *
1132 basename (const char *path)
1133 {
1134  static char *bname = NULL;
1135 
1136  if (bname == NULL)
1137  {
1138  bname = (char *) malloc (PATH_MAX);
1139  if (bname == NULL)
1140  return (NULL);
1141  }
1142 
1143  return (basename_r (path, bname, PATH_MAX) < 0) ? NULL : bname;
1144 }
1145 #endif /* !HAVE_BASENAME */
1146 
1147 #if defined(WINDOWS)
1148 char *
1149 ctime_r (const time_t * time, char *time_buf)
1150 {
1151  int err;
1152  assert (time != NULL && time_buf != NULL);
1153 
1154  err = ctime_s (time_buf, CTIME_MAX, time);
1155  if (err != 0)
1156  {
1157  return NULL;
1158  }
1159  return time_buf;
1160 }
1161 #endif /* !WINDOWS */
1162 
1163 #if defined(WINDOWS)
1164 struct tm *
1165 localtime_r (const time_t * time, struct tm *tm_val)
1166 {
1167  int err;
1168  assert (time != NULL && tm_val != NULL);
1169 
1170  err = localtime_s (tm_val, time);
1171  if (err != 0)
1172  {
1173  return NULL;
1174  }
1175  return tm_val;
1176 }
1177 #endif /* WIDNOWS */
1178 
1179 
1180 #if defined (ENABLE_UNUSED_FUNCTION)
1181 int
1182 utona (unsigned int u, char *s, size_t n)
1183 {
1184  char nbuf[10], *p, *t;
1185 
1186  if (s == NULL || n == 0)
1187  {
1188  return 0;
1189  }
1190  if (n == 1)
1191  {
1192  *s = '\0';
1193  return 1;
1194  }
1195 
1196  p = nbuf;
1197  do
1198  {
1199  *p++ = u % 10 + '0';
1200  }
1201  while ((u /= 10) > 0);
1202  p--;
1203 
1204  t = s;
1205  do
1206  {
1207  *t++ = *p--;
1208  }
1209  while (p >= nbuf && --n > 1);
1210  *t++ = '\0';
1211 
1212  return (t - s);
1213 }
1214 
1215 int
1216 itona (int i, char *s, size_t n)
1217 {
1218  if (s == NULL || n == 0)
1219  {
1220  return 0;
1221  }
1222  if (n == 1)
1223  {
1224  *s = '\0';
1225  return 1;
1226  }
1227 
1228  if (i < 0)
1229  {
1230  *s++ = '-';
1231  n--;
1232  return utona (-i, s, n) + 1;
1233  }
1234  else
1235  {
1236  return utona (i, s, n);
1237  }
1238 }
1239 #endif /* ENABLE_UNUSED_FUNCTION */
1240 
1241 char *
1242 stristr (const char *s, const char *find)
1243 {
1244  char c, sc;
1245  size_t len;
1246 
1247  if ((c = *find++) != '0')
1248  {
1249  len = strlen (find);
1250  do
1251  {
1252  do
1253  {
1254  if ((sc = *s++) == '\0')
1255  {
1256  return NULL;
1257  }
1258  }
1259  while (toupper (sc) != toupper (c));
1260  }
1261  while (strncasecmp (s, find, len) != 0);
1262  s--;
1263  }
1264  return (char *) s;
1265 }
1266 
1267 /*
1268  * wrapper for cuserid() function
1269  */
1270 char *
1271 getuserid (char *string, int size)
1272 {
1273  if (cuserid (string) == NULL)
1274  {
1275  return NULL;
1276  }
1277  else
1278  {
1279  string[size - 1] = '\0';
1280  return string;
1281  }
1282 }
1283 
1284 /*
1285  * wrapper for OS dependent operations
1286  */
1287 /*
1288  * os_rename_file() - rename a file
1289  * return: 0 on success, otherwise -1
1290  * src_path(in): source path
1291  * dest_path(in): destination path
1292  */
1293 int
1294 os_rename_file (const char *src_path, const char *dest_path)
1295 {
1296 #if defined(WINDOWS)
1297  /* NOTE: Windows 95 and 98 do not support MoveFileEx */
1298  if (MoveFileEx (src_path, dest_path, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED))
1299  {
1300  return 0;
1301  }
1302  else
1303  {
1304  return -1;
1305  }
1306  /* TODO: Windows 95/98 does not replace the file if it already exists. (void) _unlink (dest_path); return rename
1307  * (src_path, dest_path); */
1308 #else
1309  return rename (src_path, dest_path);
1310 #endif /* WINDOWS */
1311 }
1312 
1313 #include <signal.h>
1314 /*
1315  * os_set_signal_handler() - sets the signal handler
1316  * return: Old signal handler which can be used to restore
1317  * If it fails, it returns SIG_ERR
1318  * signo(in): specifies the signal except SIGKILL and/or SIGSTOP
1319  * sig_handler(in): Function to handle the above signal or SIG_DFL, SIG_IGN
1320  *
1321  * Note: We would like the signals to work as follow:
1322  * - Multiple signals should not get lost; the system should queue them
1323  * - Signals must be reliable. The signal handler should not need to
1324  * reestablish itself like in the old days of Unix
1325  * - The signal hander remains installed after a signal has been delivered
1326  * - If a caught signal occurs during certain system calls terminating
1327  * the call prematurely, the call is automatically restarted
1328  * - If SIG_DFL is given, the default action is reinstaled
1329  * - If SIG_IGN is given as sig_handler, the signal is subsequently ignored
1330  * and pending instances of the signal are discarded
1331  */
1333 os_set_signal_handler (const int sig_no, SIGNAL_HANDLER_FUNCTION sig_handler)
1334 {
1335 #if defined(WINDOWS)
1336  return signal (sig_no, sig_handler);
1337 #else /* WINDOWS */
1338  struct sigaction act;
1339  struct sigaction oact;
1340 
1341  act.sa_handler = sig_handler;
1342  act.sa_flags = 0;
1343 
1344  if (sigemptyset (&act.sa_mask) < 0)
1345  {
1346  return (SIG_ERR);
1347  }
1348 
1349  switch (sig_no)
1350  {
1351  case SIGALRM:
1352 #if defined(SA_INTERRUPT)
1353  act.sa_flags |= SA_INTERRUPT; /* disable other interrupts */
1354 #endif /* SA_INTERRUPT */
1355  break;
1356  default:
1357 #if defined(SA_RESTART)
1358  act.sa_flags |= SA_RESTART; /* making certain system calls restartable across signals */
1359 #endif /* SA_RESTART */
1360  break;
1361  }
1362 
1363  if (sigaction (sig_no, &act, &oact) < 0)
1364  {
1365  return (SIG_ERR);
1366  }
1367 
1368  return (oact.sa_handler);
1369 #endif /* WINDOWS */
1370 }
1371 
1372 /*
1373  * os_send_signal() - send the signal to ourselves
1374  * return: none
1375  * signo(in): signal number to send
1376  */
1377 void
1378 os_send_signal (const int sig_no)
1379 {
1380 #if defined(WINDOWS)
1381  raise (sig_no);
1382 #else /* WINDOWS */
1383  kill (getpid (), sig_no);
1384 #endif /* WINDOWS */
1385 }
1386 
1387 #if defined(WINDOWS)
1388 #if !defined(HAVE_STRSEP)
1389 char *
1390 strsep (char **stringp, const char *delim)
1391 {
1392  char *p, *token;
1393 
1394  if (*stringp == NULL)
1395  return NULL;
1396 
1397  token = *stringp;
1398 
1399  p = strstr (*stringp, delim);
1400  if (p == NULL)
1401  {
1402  *stringp = NULL;
1403  }
1404  else
1405  {
1406  *p = '\0';
1407  *stringp = p + strlen (delim);
1408  }
1409 
1410  return token;
1411 }
1412 #endif
1413 
1414 /*
1415  * getpass() - get a password
1416  * return: password string
1417  * prompt(in): prompt message string
1418  */
1419 char *
1420 getpass (const char *prompt)
1421 {
1422  size_t pwlen = 0;
1423  int c;
1424  static char password_buffer[80];
1425 
1426  fprintf (stdout, prompt);
1427 
1428  while (1)
1429  {
1430  c = getch ();
1431  if (c == '\r' || c == '\n')
1432  break;
1433  if (c == '\b')
1434  { /* backspace */
1435  if (pwlen > 0)
1436  pwlen--;
1437  continue;
1438  }
1439  if (pwlen < sizeof (password_buffer) - 1)
1440  password_buffer[pwlen++] = c;
1441  }
1442  password_buffer[pwlen] = '\0';
1443  return password_buffer;
1444 }
1445 #endif /* WINDOWS */
1446 
1447 
1448 #if defined(WINDOWS)
1449 
1450 int
1451 setenv (const char *name, const char *val, int overwrite)
1452 {
1453  errno_t ret;
1454 
1455  if (!overwrite)
1456  {
1457  char *ptr = getenv (name);
1458  if (ptr != NULL)
1459  {
1460  return -1;
1461  }
1462  }
1463 
1464  ret = _putenv_s (name, val);
1465  if (ret == EINVAL)
1466  {
1467  return -1;
1468  }
1469 
1470  return 0;
1471 }
1472 
1473 int
1474 cub_vsnprintf (char *buffer, size_t count, const char *format, va_list argptr)
1475 {
1476  int len = _vscprintf_p (format, argptr) + 1;
1477 
1478  if (len > (int) count)
1479  {
1480  char *cp = (char *) malloc (len);
1481  if (cp == NULL)
1482  {
1483  return -1;
1484  }
1485 
1486  len = _vsprintf_p (cp, len, format, argptr);
1487  if (len < 0)
1488  {
1489  free (cp);
1490  return len;
1491  }
1492 
1493  memcpy (buffer, cp, count - 1);
1494  buffer[count - 1] = 0;
1495 
1496  free (cp);
1497  return (int) count;
1498  }
1499 
1500  return _vsprintf_p (buffer, count, format, argptr);
1501 }
1502 
1503 #if !defined(_MSC_VER) || _MSC_VER < 1800
1504 double
1505 round (double d)
1506 {
1507  return d >= 0 ? floor (d + 0.5) : ceil (d - 0.5);
1508 }
1509 #endif
1510 
1511 int
1512 pthread_mutex_init (pthread_mutex_t * mutex, pthread_mutexattr_t * attr)
1513 {
1514  if (mutex->csp == &mutex->cs && mutex->watermark == WATERMARK_MUTEX_INITIALIZED)
1515  {
1516  /* already inited */
1517  assert (0);
1518  return 0;
1519  }
1520 
1521  mutex->csp = &mutex->cs;
1522  mutex->watermark = WATERMARK_MUTEX_INITIALIZED;
1523  InitializeCriticalSection (mutex->csp);
1524 
1525  return 0;
1526 }
1527 
1528 int
1529 pthread_mutex_destroy (pthread_mutex_t * mutex)
1530 {
1531  if (mutex->csp != &mutex->cs || mutex->watermark != WATERMARK_MUTEX_INITIALIZED)
1532  {
1533  if (mutex->csp == NULL) /* inited by PTHREAD_MUTEX_INITIALIZER */
1534  {
1535  mutex->watermark = 0;
1536  return 0;
1537  }
1538 
1539  /* invalid destroy */
1540  assert (0);
1541  mutex->csp = NULL;
1542  mutex->watermark = 0;
1543  return 0;
1544  }
1545 
1546  DeleteCriticalSection (mutex->csp);
1547  mutex->csp = NULL;
1548  mutex->watermark = 0;
1549  return 0;
1550 }
1551 
1552 int
1553 pthread_mutexattr_init (pthread_mutexattr_t * attr)
1554 {
1555  return 0;
1556 }
1557 
1558 int
1559 pthread_mutexattr_settype (pthread_mutexattr_t * attr, int type)
1560 {
1561  return 0;
1562 }
1563 
1564 int
1565 pthread_mutexattr_destroy (pthread_mutexattr_t * attr)
1566 {
1567  return 0;
1568 }
1569 
1570 
1571 pthread_mutex_t css_Internal_mutex_for_mutex_initialize = PTHREAD_MUTEX_INITIALIZER;
1572 
1573 void
1574 port_win_mutex_init_and_lock (pthread_mutex_t * mutex)
1575 {
1576  if (css_Internal_mutex_for_mutex_initialize.csp != &css_Internal_mutex_for_mutex_initialize.cs
1577  || css_Internal_mutex_for_mutex_initialize.watermark != WATERMARK_MUTEX_INITIALIZED)
1578  {
1579  pthread_mutex_init (&css_Internal_mutex_for_mutex_initialize, NULL);
1580  }
1581 
1582  EnterCriticalSection (css_Internal_mutex_for_mutex_initialize.csp);
1583  if (mutex->csp != &mutex->cs || mutex->watermark != WATERMARK_MUTEX_INITIALIZED)
1584  {
1585  /*
1586  * below assert means that lock without pthread_mutex_init
1587  * or PTHREAD_MUTEX_INITIALIZER
1588  */
1589  assert (mutex->csp == NULL);
1590  pthread_mutex_init (mutex, NULL);
1591  }
1592  LeaveCriticalSection (css_Internal_mutex_for_mutex_initialize.csp);
1593 
1594  EnterCriticalSection (mutex->csp);
1595 }
1596 
1597 int
1598 port_win_mutex_init_and_trylock (pthread_mutex_t * mutex)
1599 {
1600  bool r;
1601 
1602  if (css_Internal_mutex_for_mutex_initialize.csp != &css_Internal_mutex_for_mutex_initialize.cs
1603  || css_Internal_mutex_for_mutex_initialize.watermark != WATERMARK_MUTEX_INITIALIZED)
1604  {
1605  pthread_mutex_init (&css_Internal_mutex_for_mutex_initialize, NULL);
1606  }
1607 
1608  EnterCriticalSection (css_Internal_mutex_for_mutex_initialize.csp);
1609  if (mutex->csp != &mutex->cs || mutex->watermark != WATERMARK_MUTEX_INITIALIZED)
1610  {
1611  /*
1612  * below assert means that trylock without pthread_mutex_init
1613  * or PTHREAD_MUTEX_INITIALIZER
1614  */
1615  assert (mutex->csp == NULL);
1616  pthread_mutex_init (mutex, NULL);
1617  }
1618  LeaveCriticalSection (css_Internal_mutex_for_mutex_initialize.csp);
1619 
1620  r = TryEnterCriticalSection (mutex->csp);
1621  if (mutex->csp->RecursionCount > 1)
1622  {
1623  LeaveCriticalSection (mutex->csp);
1624  return EBUSY;
1625  }
1626 
1627  return r ? 0 : EBUSY;
1628 }
1629 
1630 
1631 typedef void (WINAPI * InitializeConditionVariable_t) (CONDITION_VARIABLE *);
1632 typedef bool (WINAPI * SleepConditionVariableCS_t) (CONDITION_VARIABLE *, CRITICAL_SECTION *, DWORD dwMilliseconds);
1633 
1634 typedef void (WINAPI * WakeAllConditionVariable_t) (CONDITION_VARIABLE *);
1635 typedef void (WINAPI * WakeConditionVariable_t) (CONDITION_VARIABLE *);
1636 
1637 InitializeConditionVariable_t fp_InitializeConditionVariable;
1638 SleepConditionVariableCS_t fp_SleepConditionVariableCS;
1639 WakeAllConditionVariable_t fp_WakeAllConditionVariable;
1640 WakeConditionVariable_t fp_WakeConditionVariable;
1641 
1642 static bool have_CONDITION_VARIABLE = false;
1643 
1644 
1645 static void
1646 check_CONDITION_VARIABLE (void)
1647 {
1648  HMODULE kernel32 = GetModuleHandle ("kernel32");
1649 
1650  have_CONDITION_VARIABLE = true;
1651  fp_InitializeConditionVariable =
1652  (InitializeConditionVariable_t) GetProcAddress (kernel32, "InitializeConditionVariable");
1653  if (fp_InitializeConditionVariable == NULL)
1654  {
1655  have_CONDITION_VARIABLE = false;
1656  return;
1657  }
1658 
1659  fp_SleepConditionVariableCS = (SleepConditionVariableCS_t) GetProcAddress (kernel32, "SleepConditionVariableCS");
1660  fp_WakeAllConditionVariable = (WakeAllConditionVariable_t) GetProcAddress (kernel32, "WakeAllConditionVariable");
1661  fp_WakeConditionVariable = (WakeConditionVariable_t) GetProcAddress (kernel32, "WakeConditionVariable");
1662 }
1663 
1664 static int
1665 timespec_to_msec (const struct timespec *abstime)
1666 {
1667  long long msec = 0;
1668  struct timeval tv;
1669 
1670  if (abstime == NULL)
1671  {
1672  return INFINITE;
1673  }
1674 
1675  gettimeofday (&tv, NULL);
1676  msec = (abstime->tv_sec - tv.tv_sec) * 1000;
1677  msec += (abstime->tv_nsec / 1000 - tv.tv_usec) / 1000;
1678 
1679  if (msec < 0)
1680  {
1681  msec = 0;
1682  }
1683 
1684  return (int) msec;
1685 }
1686 
1687 
1688 /*
1689  * old (pre-vista) windows does not support CONDITION_VARIABLES
1690  * so, we need below custom pthread_cond modules for them
1691  */
1692 static int
1693 win_custom_cond_init (pthread_cond_t * cond, const pthread_condattr_t * attr)
1694 {
1695  cond->initialized = true;
1696  cond->waiting = 0;
1697  InitializeCriticalSection (&cond->lock_waiting);
1698 
1699  cond->events[COND_SIGNAL] = CreateEvent (NULL, FALSE, FALSE, NULL);
1700  cond->events[COND_BROADCAST] = CreateEvent (NULL, TRUE, FALSE, NULL);
1701  cond->broadcast_block_event = CreateEvent (NULL, TRUE, TRUE, NULL);
1702 
1703  if (cond->events[COND_SIGNAL] == NULL || cond->events[COND_BROADCAST] == NULL || cond->broadcast_block_event == NULL)
1704  {
1705  return ENOMEM;
1706  }
1707 
1708  return 0;
1709 }
1710 
1711 static int
1712 win_custom_cond_destroy (pthread_cond_t * cond)
1713 {
1714  if (!cond->initialized)
1715  {
1716  return 0;
1717  }
1718 
1719  DeleteCriticalSection (&cond->lock_waiting);
1720 
1721  if (CloseHandle (cond->events[COND_SIGNAL]) == 0 || CloseHandle (cond->events[COND_BROADCAST]) == 0
1722  || CloseHandle (cond->broadcast_block_event) == 0)
1723  {
1724  return EINVAL;
1725  }
1726 
1727  cond->initialized = false;
1728  return 0;
1729 }
1730 
1731 static int
1732 win_custom_cond_timedwait (pthread_cond_t * cond, pthread_mutex_t * mutex, struct timespec *abstime)
1733 {
1734  int result;
1735  int msec;
1736 
1737  assert (cond->initialized == true);
1738 
1739  msec = timespec_to_msec (abstime);
1740  WaitForSingleObject (cond->broadcast_block_event, INFINITE);
1741 
1742  EnterCriticalSection (&cond->lock_waiting);
1743  cond->waiting++;
1744  LeaveCriticalSection (&cond->lock_waiting);
1745 
1746  LeaveCriticalSection (mutex->csp);
1747  result = WaitForMultipleObjects (2, cond->events, FALSE, msec);
1748  assert (result == WAIT_TIMEOUT || result <= 2);
1749 
1750  /*** THREAD UNSAFE AREA ***/
1751 
1752  EnterCriticalSection (&cond->lock_waiting);
1753  cond->waiting--;
1754 
1755  if (cond->waiting == 0)
1756  {
1757  ResetEvent (cond->events[COND_BROADCAST]);
1758  SetEvent (cond->broadcast_block_event);
1759 
1760  /*
1761  * Remove additional signal if exists
1762  * (That's received in above THREAD UNSAFE AREA)
1763  */
1764  WaitForSingleObject (cond->events[COND_SIGNAL], 0);
1765  }
1766 
1767  LeaveCriticalSection (&cond->lock_waiting);
1768  EnterCriticalSection (mutex->csp);
1769 
1770  return result == WAIT_TIMEOUT ? ETIMEDOUT : 0;
1771 }
1772 
1773 static int
1774 win_custom_cond_signal (pthread_cond_t * cond)
1775 {
1776  assert (cond->initialized == true);
1777 
1778  EnterCriticalSection (&cond->lock_waiting);
1779 
1780  if (cond->waiting > 0)
1781  {
1782  SetEvent (cond->events[COND_SIGNAL]);
1783  }
1784 
1785  LeaveCriticalSection (&cond->lock_waiting);
1786 
1787  return 0;
1788 }
1789 
1790 static int
1791 win_custom_cond_broadcast (pthread_cond_t * cond)
1792 {
1793  assert (cond->initialized == true);
1794 
1795  EnterCriticalSection (&cond->lock_waiting);
1796 
1797  if (cond->waiting > 0)
1798  {
1799  ResetEvent (cond->broadcast_block_event);
1800  SetEvent (cond->events[COND_BROADCAST]);
1801  }
1802 
1803  LeaveCriticalSection (&cond->lock_waiting);
1804 
1805  return 0;
1806 }
1807 
1808 int
1809 pthread_cond_init (pthread_cond_t * cond, const pthread_condattr_t * attr)
1810 {
1811  static bool checked = false;
1812  if (checked == false)
1813  {
1814  check_CONDITION_VARIABLE ();
1815  checked = true;
1816  }
1817 
1818  if (have_CONDITION_VARIABLE)
1819  {
1820  fp_InitializeConditionVariable (&cond->native_cond);
1821  return 0;
1822  }
1823 
1824  return win_custom_cond_init (cond, attr);
1825 }
1826 
1827 int
1828 pthread_cond_destroy (pthread_cond_t * cond)
1829 {
1830  if (have_CONDITION_VARIABLE)
1831  {
1832  return 0;
1833  }
1834 
1835  return win_custom_cond_destroy (cond);
1836 }
1837 
1838 int
1839 pthread_cond_broadcast (pthread_cond_t * cond)
1840 {
1841  if (have_CONDITION_VARIABLE)
1842  {
1843  fp_WakeAllConditionVariable (&cond->native_cond);
1844  return 0;
1845  }
1846 
1847  return win_custom_cond_broadcast (cond);
1848 }
1849 
1850 int
1851 pthread_cond_signal (pthread_cond_t * cond)
1852 {
1853  if (have_CONDITION_VARIABLE)
1854  {
1855  fp_WakeConditionVariable (&cond->native_cond);
1856  return 0;
1857  }
1858 
1859  return win_custom_cond_signal (cond);
1860 }
1861 
1862 int
1863 pthread_cond_timedwait (pthread_cond_t * cond, pthread_mutex_t * mutex, struct timespec *abstime)
1864 {
1865  if (have_CONDITION_VARIABLE)
1866  {
1867  int msec = timespec_to_msec (abstime);
1868  if (fp_SleepConditionVariableCS (&cond->native_cond, mutex->csp, msec) == false)
1869  {
1870  return ETIMEDOUT;
1871  }
1872 
1873  return 0;
1874  }
1875 
1876  return win_custom_cond_timedwait (cond, mutex, abstime);
1877 }
1878 
1879 int
1880 pthread_cond_wait (pthread_cond_t * cond, pthread_mutex_t * mutex)
1881 {
1882  return pthread_cond_timedwait (cond, mutex, NULL);
1883 }
1884 
1885 
1886 int
1887 pthread_create (pthread_t * thread, const pthread_attr_t * attr,
1888  THREAD_RET_T (THREAD_CALLING_CONVENTION * start_routine) (void *), void *arg)
1889 {
1890  unsigned int tid;
1891  *thread = (pthread_t) _beginthreadex (NULL, 0, start_routine, arg, 0, &tid);
1892  return (*thread <= 0) ? -1 : 0;
1893 }
1894 
1895 void
1896 pthread_exit (THREAD_RET_T ptr)
1897 {
1898  _endthreadex (ptr);
1899 }
1900 
1901 pthread_t
1902 pthread_self ()
1903 {
1904  return (pthread_t) GetCurrentThreadId ();
1905 }
1906 
1907 int
1908 pthread_join (pthread_t thread, void **value_ptr)
1909 {
1910  return WaitForSingleObject (thread, INFINITE);
1911 }
1912 
1913 int
1914 pthread_key_create (pthread_key_t * key, void (*destructor) (void *))
1915 {
1916  return (*key = TlsAlloc ()) != 0xFFFFFFFF ? 0 : -1;
1917 }
1918 
1919 int
1920 pthread_key_delete (pthread_key_t key)
1921 {
1922  return TlsFree (key) != 0 ? 0 : -1;
1923 }
1924 
1925 int
1926 pthread_setspecific (pthread_key_t key, const void *value)
1927 {
1928  return TlsSetValue (key, (LPVOID) value) != 0 ? 0 : -1;
1929 }
1930 
1931 void *
1932 pthread_getspecific (pthread_key_t key)
1933 {
1934  return TlsGetValue (key);
1935 }
1936 
1937 #if !defined(_WIN64)
1938 /*
1939  * The following functions are used to provide atomic operations on
1940  * Windows 32bit OS. See the comment in porting.h for more information.
1941  */
1942 UINT64
1943 win32_compare_exchange64 (UINT64 volatile *val_ptr, UINT64 swap_val, UINT64 cmp_val)
1944 {
1945  /* *INDENT-OFF* */
1946  __asm
1947  {
1948  mov esi,[val_ptr]
1949  mov ebx, dword ptr[swap_val]
1950  mov ecx, dword ptr[swap_val + 4]
1951  mov eax, dword ptr[cmp_val]
1952  mov edx, dword ptr[cmp_val + 4]
1953  lock cmpxchg8b[esi]
1954  }
1955  /* *INDENT-ON* */
1956 }
1957 
1958 UINT64
1959 win32_exchange_add64 (UINT64 volatile *ptr, UINT64 amount)
1960 {
1961  UINT64 old;
1962  do
1963  {
1964  old = *ptr;
1965  }
1966  while (win32_compare_exchange64 (ptr, old + amount, old) != old);
1967  return old;
1968 }
1969 
1970 UINT64
1971 win32_exchange64 (UINT64 volatile *ptr, UINT64 new_val)
1972 {
1973  UINT64 old;
1974  do
1975  {
1976  old = *ptr;
1977  }
1978  while (win32_compare_exchange64 (ptr, new_val, old) != old);
1979  return old;
1980 }
1981 #endif /* _WIN64 */
1982 
1983 #endif /* WINDOWS */
1984 
1985 #if defined(WINDOWS)
1986 /*
1987  * strtod_win () convert string to double
1988  * return : the converted double
1989  * str (in): string to convert
1990  * end_ptr (in): see strtod
1991  */
1992 double
1993 strtod_win (const char *str, char **end_ptr)
1994 {
1995  bool is_hex = false;
1996  double result = 0.0, int_d = 0.0, float_d = 0.0;
1997  double tmp_d = 0.0;
1998  const char *p = NULL, *dot_p = NULL, *end_p = NULL;
1999  int sign_flag = 1;
2000 
2001  if (str == NULL || *str == '\0')
2002  {
2003  if (end_ptr != NULL)
2004  {
2005  *end_ptr = (char *) str;
2006  }
2007  return result;
2008  }
2009 
2010  /* if the string start with "0x", "0X", "+0x", "+0X", "-0x" or "-0X" then deal with it as hex string */
2011  p = str;
2012  if (*p == '+')
2013  {
2014  p++;
2015  }
2016  else if (*p == '-')
2017  {
2018  sign_flag = -1;
2019  p++;
2020  }
2021 
2022  if (*p == '0' && (*(p + 1) == 'x' || *(p + 1) == 'X'))
2023  {
2024  is_hex = true;
2025  p += 2;
2026  }
2027 
2028  if (is_hex)
2029  {
2030  /* convert integer part */
2031  while (*p != '\0')
2032  {
2033  if (*p == '.')
2034  {
2035  break;
2036  }
2037 
2038  if ('0' <= *p && *p <= '9')
2039  {
2040  tmp_d = (double) (*p - '0');
2041  }
2042  else if ('A' <= *p && *p <= 'F')
2043  {
2044  tmp_d = (double) (*p - 'A' + 10);
2045  }
2046  else if ('a' <= *p && *p <= 'f')
2047  {
2048  tmp_d = (double) (*p - 'a' + 10);
2049  }
2050  else
2051  {
2052  end_p = p;
2053  goto end;
2054  }
2055 
2056  int_d = int_d * 16.0 + tmp_d;
2057 
2058  p++;
2059  }
2060  end_p = p;
2061 
2062  /* convert float part */
2063  if (*p == '.')
2064  {
2065  /* find the end */
2066  dot_p = p;
2067  while (*++p != '\0')
2068  ;
2069  end_p = p;
2070  p--;
2071 
2072  while (p != dot_p)
2073  {
2074  if ('0' <= *p && *p <= '9')
2075  {
2076  tmp_d = (double) (*p - '0');
2077  }
2078  else if ('A' <= *p && *p <= 'F')
2079  {
2080  tmp_d = (double) (*p - 'A' + 10);
2081  }
2082  else if ('a' <= *p && *p <= 'f')
2083  {
2084  tmp_d = (double) (*p - 'a' + 10);
2085  }
2086  else
2087  {
2088  end_p = p;
2089  goto end;
2090  }
2091 
2092  float_d = (float_d + tmp_d) / 16.0;
2093 
2094  p--;
2095  }
2096  }
2097 
2098  result = int_d + float_d;
2099  if (sign_flag == -1)
2100  {
2101  result = -result;
2102  }
2103 
2104  /* underflow and overflow */
2105  if (result > DBL_MAX || (-result) > DBL_MAX)
2106  {
2107  errno = ERANGE;
2108  }
2109  }
2110  else
2111  {
2112  result = strtod (str, end_ptr);
2113  }
2114 
2115 end:
2116 
2117  if (is_hex && end_ptr != NULL)
2118  {
2119  *end_ptr = (char *) end_p;
2120  }
2121 
2122  return result;
2123 }
2124 #endif
2125 
2126 /*
2127  * timeval_diff_in_msec -
2128  *
2129  * return: msec
2130  *
2131  */
2132 INT64
2133 timeval_diff_in_msec (const struct timeval * end_time, const struct timeval * start_time)
2134 {
2135  INT64 msec;
2136 
2137  msec = (end_time->tv_sec - start_time->tv_sec) * 1000LL;
2138  msec += (end_time->tv_usec - start_time->tv_usec) / 1000LL;
2139 
2140  return msec;
2141 }
2142 
2143 /*
2144  * timeval_add_msec -
2145  * return: 0
2146  *
2147  * addted_time(out):
2148  * start_time(in):
2149  * msec(in):
2150  */
2151 int
2152 timeval_add_msec (struct timeval *added_time, const struct timeval *start_time, int msec)
2153 {
2154  int usec;
2155 
2156  added_time->tv_sec = start_time->tv_sec + msec / 1000LL;
2157  usec = (msec % 1000LL) * 1000LL;
2158 
2159  added_time->tv_sec += (start_time->tv_usec + usec) / 1000000LL;
2160  added_time->tv_usec = (start_time->tv_usec + usec) % 1000000LL;
2161 
2162  return 0;
2163 }
2164 
2165 /*
2166  * timeval_to_timespec -
2167  * return: 0
2168  *
2169  * to(out):
2170  * from(in):
2171  */
2172 int
2173 timeval_to_timespec (struct timespec *to, const struct timeval *from)
2174 {
2175  assert (to != NULL);
2176  assert (from != NULL);
2177 
2178  to->tv_sec = from->tv_sec;
2179  to->tv_nsec = from->tv_usec * 1000LL;
2180 
2181  return 0;
2182 }
2183 
2184 
2185 /*
2186  * port_open_memstream - make memory stream file handle if possible.
2187  * if not, make temporiry file handle.
2188  * return: file handle
2189  *
2190  * ptr (out): memory stream (or temp file name)
2191  * sizeloc (out): stream size
2192  *
2193  * NOTE: this function use memory allocation in it.
2194  * so you should ensure that stream size is not too huge
2195  * before you use this.
2196  */
2197 FILE *
2198 port_open_memstream (char **ptr, size_t * sizeloc)
2199 {
2200 #ifdef HAVE_OPEN_MEMSTREAM
2201  return open_memstream (ptr, sizeloc);
2202 #else
2203  *ptr = tempnam (NULL, "cubrid_");
2204  return fopen (*ptr, "w+");
2205 #endif
2206 }
2207 
2208 
2209 /*
2210  * port_close_memstream - flush file handle and close
2211  *
2212  * fp (in): file handle to close
2213  * ptr (in/out): memory stream (out) or temp file name (in)
2214  * sizeloc (out): stream size
2215  *
2216  * NOTE: you should call this function before refer ptr
2217  * this function flush contents to ptr before close handle
2218  */
2219 void
2220 port_close_memstream (FILE * fp, char **ptr, size_t * sizeloc)
2221 {
2222  fflush (fp);
2223 
2224  if (fp)
2225  {
2226 #ifdef HAVE_OPEN_MEMSTREAM
2227  fclose (fp);
2228 #else
2229  char *buff = NULL;
2230  struct stat stat_buf;
2231 
2232  if (fstat (fileno (fp), &stat_buf) == 0)
2233  {
2234  *sizeloc = stat_buf.st_size;
2235 
2236  buff = (char *) malloc (*sizeloc + 1);
2237  if (buff)
2238  {
2239  size_t n;
2240 
2241  fseek (fp, 0, SEEK_SET);
2242  n = fread (buff, 1, *sizeloc, fp);
2243  buff[n] = '\0';
2244  *sizeloc = n;
2245  }
2246  }
2247 
2248  fclose (fp);
2249  /* tempname from port_open_memstream */
2250  unlink (*ptr);
2251  free (*ptr);
2252 
2253  /* set output */
2254  *ptr = buff;
2255 #endif
2256  }
2257 }
2258 
2259 char *
2260 trim (char *str)
2261 {
2262  char *p;
2263  char *s;
2264 
2265  if (str == NULL)
2266  return (str);
2267 
2268  for (s = str; *s != '\0' && (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r'); s++)
2269  ;
2270  if (*s == '\0')
2271  {
2272  *str = '\0';
2273  return (str);
2274  }
2275 
2276  /* *s must be a non-white char */
2277  for (p = s; *p != '\0'; p++)
2278  ;
2279  for (p--; *p == ' ' || *p == '\t' || *p == '\n' || *p == '\r'; p--)
2280  ;
2281  *++p = '\0';
2282 
2283  if (s != str)
2284  memmove (str, s, strlen (s) + 1);
2285 
2286  return (str);
2287 }
2288 
2289 int
2290 parse_int (int *ret_p, const char *str_p, int base)
2291 {
2292  int error = 0;
2293  int val;
2294  char *end_p;
2295 
2296  assert (ret_p != NULL);
2297  assert (str_p != NULL);
2298 
2299  *ret_p = 0;
2300 
2301  error = str_to_int32 (&val, &end_p, str_p, base);
2302  if (error < 0)
2303  {
2304  return -1;
2305  }
2306 
2307  if (*end_p != '\0')
2308  {
2309  return -1;
2310  }
2311 
2312  *ret_p = val;
2313 
2314  return 0;
2315 }
2316 
2317 int
2318 parse_bigint (INT64 * ret_p, const char *str_p, int base)
2319 {
2320  int error = 0;
2321  INT64 val;
2322  char *end_p;
2323 
2324  assert (ret_p != NULL);
2325  assert (str_p != NULL);
2326 
2327  *ret_p = 0;
2328 
2329  error = str_to_int64 (&val, &end_p, str_p, base);
2330  if (error < 0)
2331  {
2332  return -1;
2333  }
2334 
2335  if (*end_p != '\0')
2336  {
2337  return -1;
2338  }
2339 
2340  *ret_p = val;
2341 
2342  return 0;
2343 }
2344 
2345 int
2346 str_to_int32 (int *ret_p, char **end_p, const char *str_p, int base)
2347 {
2348  long val = 0;
2349 
2350  assert (ret_p != NULL);
2351  assert (end_p != NULL);
2352  assert (str_p != NULL);
2353 
2354  *ret_p = 0;
2355  *end_p = NULL;
2356 
2357  errno = 0;
2358  val = strtol (str_p, end_p, base);
2359 
2360  if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) || (errno != 0 && val == 0))
2361  {
2362  return -1;
2363  }
2364 
2365  if (*end_p == str_p)
2366  {
2367  return -1;
2368  }
2369 
2370  /* Long is 8 bytes and int is 4 bytes in Linux 64bit, so the additional check of integer range is necessary. */
2371  if (val < INT_MIN || val > INT_MAX)
2372  {
2373  return -1;
2374  }
2375 
2376  *ret_p = (int) val;
2377 
2378  return 0;
2379 }
2380 
2381 int
2382 str_to_uint32 (unsigned int *ret_p, char **end_p, const char *str_p, int base)
2383 {
2384  unsigned long val = 0;
2385 
2386  assert (ret_p != NULL);
2387  assert (end_p != NULL);
2388  assert (str_p != NULL);
2389 
2390  *ret_p = 0;
2391  *end_p = NULL;
2392 
2393  errno = 0;
2394  val = strtoul (str_p, end_p, base);
2395 
2396  if ((errno == ERANGE && val == ULONG_MAX) || (errno != 0 && val == 0))
2397  {
2398  return -1;
2399  }
2400 
2401  if (*end_p == str_p)
2402  {
2403  return -1;
2404  }
2405 
2406  /* Long is 8 bytes and int is 4 bytes in Linux 64bit, so the additional check of integer range is necessary. */
2407  if (val > UINT_MAX)
2408  {
2409  return -1;
2410  }
2411 
2412  *ret_p = (unsigned int) val;
2413 
2414  return 0;
2415 }
2416 
2417 
2418 int
2419 str_to_int64 (INT64 * ret_p, char **end_p, const char *str_p, int base)
2420 {
2421  INT64 val;
2422 
2423  assert (ret_p != NULL);
2424  assert (end_p != NULL);
2425  assert (str_p != NULL);
2426 
2427  *ret_p = 0;
2428  *end_p = NULL;
2429 
2430  errno = 0;
2431  val = strtoll (str_p, end_p, base);
2432 
2433  if ((errno == ERANGE && (val == LLONG_MAX || val == LLONG_MIN)) || (errno != 0 && val == 0))
2434  {
2435  return -1;
2436  }
2437 
2438  if (*end_p == str_p)
2439  {
2440  return -1;
2441  }
2442 
2443  *ret_p = val;
2444 
2445  return 0;
2446 }
2447 
2448 int
2449 str_to_uint64 (UINT64 * ret_p, char **end_p, const char *str_p, int base)
2450 {
2451  UINT64 val;
2452 
2453  assert (ret_p != NULL);
2454  assert (end_p != NULL);
2455  assert (str_p != NULL);
2456 
2457  *ret_p = 0;
2458  *end_p = NULL;
2459 
2460  errno = 0;
2461  val = strtoull (str_p, end_p, base);
2462 
2463  if ((errno == ERANGE && val == ULLONG_MAX) || (errno != 0 && val == 0))
2464  {
2465  return -1;
2466  }
2467 
2468  if (*end_p == str_p)
2469  {
2470  return -1;
2471  }
2472 
2473  *ret_p = val;
2474 
2475  return 0;
2476 }
2477 
2478 int
2479 str_to_double (double *ret_p, char **end_p, const char *str_p)
2480 {
2481  double val = 0;
2482 
2483  assert (ret_p != NULL);
2484  assert (end_p != NULL);
2485  assert (str_p != NULL);
2486 
2487  *ret_p = 0;
2488  *end_p = NULL;
2489 
2490  errno = 0;
2491  val = strtod (str_p, end_p);
2492 
2493  if (errno == ERANGE || errno != 0)
2494  {
2495  return -1;
2496  }
2497 
2498  if (*end_p == str_p)
2499  {
2500  return -1;
2501  }
2502 
2503  *ret_p = val;
2504 
2505  return 0;
2506 }
2507 
2508 int
2509 str_to_float (float *ret_p, char **end_p, const char *str_p)
2510 {
2511  float val = 0;
2512 
2513  assert (ret_p != NULL);
2514  assert (end_p != NULL);
2515  assert (str_p != NULL);
2516 
2517  *ret_p = 0;
2518  *end_p = NULL;
2519 
2520  errno = 0;
2521  val = strtof (str_p, end_p);
2522 
2523  if (errno == ERANGE || errno != 0)
2524  {
2525  return -1;
2526  }
2527 
2528  if (*end_p == str_p)
2529  {
2530  return -1;
2531  }
2532 
2533  *ret_p = val;
2534 
2535  return 0;
2536 }
2537 
2538 #if defined(WINDOWS)
2539 float
2540 strtof_win (const char *nptr, char **endptr)
2541 {
2542  double d_val = 0;
2543  float f_val = 0;
2544 
2545  errno = 0;
2546 
2547  d_val = strtod (nptr, endptr);
2548  if (errno == ERANGE)
2549  {
2550  return 0.0f;
2551  }
2552 
2553  if (d_val > FLT_MAX) /* overflow */
2554  {
2555  errno = ERANGE;
2556  *endptr = const_cast < char *>(nptr);
2557  return (HUGE_VAL);
2558  }
2559  else if (d_val < (-FLT_MAX)) /* overflow */
2560  {
2561  errno = ERANGE;
2562  *endptr = const_cast < char *>(nptr);
2563  return (-HUGE_VAL);
2564  }
2565  else if (((d_val > 0) && (d_val < FLT_MIN)) || ((d_val < 0) && (d_val > (-FLT_MIN)))) /* underflow */
2566  {
2567  errno = ERANGE;
2568  *endptr = const_cast < char *>(nptr);
2569  return 0.0f;
2570  }
2571 
2572  f_val = (float) d_val;
2573  return f_val;
2574 }
2575 #endif
2576 
2577 #ifndef HAVE_STRLCPY
2578 /*
2579  * Copy src to string dst of size siz. At most siz-1 characters
2580  * will be copied. Always NUL terminates (unless siz == 0).
2581  * Returns strlen(src); if retval >= siz, truncation occurred.
2582  */
2583 size_t
2584 strlcpy (char *dst, const char *src, size_t siz)
2585 {
2586  char *d = dst;
2587  const char *s = src;
2588  size_t n = siz;
2589 
2590  assert (dst != NULL);
2591  assert (src != NULL);
2592 
2593  /* Copy as many bytes as will fit */
2594  if (n != 0 && --n != 0)
2595  {
2596  do
2597  {
2598  if ((*d++ = *s++) == 0)
2599  break;
2600  }
2601  while (--n != 0);
2602  }
2603 
2604  /* Not enough room in dst, add NUL and traverse rest of src */
2605  if (n == 0)
2606  {
2607  if (siz != 0)
2608  *d = '\0'; /* NUL-terminate dst */
2609  while (*s++)
2610  ;
2611  }
2612 
2613  return (s - src - 1); /* count does not include NUL */
2614 }
2615 #endif /* !HAVE_STRLCPY */
2616 
2617 #if (defined(WINDOWS) && defined(_WIN32))
2618 time_t
2619 mktime_for_win32 (struct tm * tm)
2620 {
2621  struct tm tm_tmp;
2622  __time32_t t_32;
2623  __time64_t t_64;
2624 
2625  tm_tmp = *tm;
2626 
2627  t_32 = _mktime32 (tm);
2628  if (t_32 != -1)
2629  {
2630  return (time_t) t_32;
2631  }
2632 
2633  *tm = tm_tmp;
2634 
2635  t_64 = _mktime64 (tm);
2636  /* '(time_t) 0x7FFFFFFF' is equal to '01-19-2038 03:14:07(UTC)' */
2637  if (t_64 >= 0x00 && t_64 <= 0x7FFFFFFF)
2638  {
2639  return (time_t) t_64;
2640  }
2641 
2642  /* There is a possibility that *tm was changed. (e.g. tm->tm_isdst) */
2643  if (t_64 != -1)
2644  {
2645  *tm = tm_tmp;
2646  }
2647  return (time_t) (-1);
2648 }
2649 #endif
2650 
2651 /* msleep (...) million second sleep
2652  *
2653  * return errno
2654  * msec(in):
2655  */
2656 int
2657 msleep (const long msec)
2658 {
2659  int error = 0;
2660 
2661  assert (msec >= 0);
2662 
2663 #if defined (WINDOWS)
2664  Sleep (msec);
2665 #else
2666  struct timeval tv;
2667 
2668  tv.tv_sec = msec / 1000L;
2669  tv.tv_usec = msec % 1000L * 1000L;
2670 
2671  errno = 0;
2672  select (0, NULL, NULL, NULL, &tv);
2673  error = errno;
2674 
2675  /* can only be 0 or EINTR here */
2676  assert (error == 0 || error == EINTR);
2677 #endif
2678 
2679  return error;
2680 }
int os_rename_file(const char *src_path, const char *dest_path)
Definition: porting.c:1294
#define PATH_CURRENT
Definition: porting.h:349
fd_set wset
int page_size
Definition: unloaddb.c:52
char * trim(char *str)
Definition: porting.c:2260
#define TRUE
Definition: broker_admin.c:49
char * dirname(const char *path)
Definition: porting.c:1066
int str_to_double(double *ret_p, char **end_p, const char *str_p)
Definition: porting.c:2479
#define COND_BROADCAST(a)
#define L_cuserid
Definition: porting.h:58
#define pthread_mutex_init(a, b)
Definition: area_alloc.c:48
int parse_int(int *ret_p, const char *str_p, int base)
Definition: porting.c:2290
static API_MUTEX mutex
Definition: api_util.c:72
int vasprintf(char **ptr, const char *format, va_list ap)
Definition: porting.c:936
int str_to_uint32(unsigned int *ret_p, char **end_p, const char *str_p, int base)
Definition: porting.c:2382
int str_to_int64(INT64 *ret_p, char **end_p, const char *str_p, int base)
Definition: porting.c:2419
#define bool
Definition: dbi_compat.h:31
void os_send_signal(const int sig_no)
Definition: porting.c:1378
char * getuserid(char *string, int size)
Definition: porting.c:1271
#define ULLONG_MAX
Definition: porting.h:81
INT64 timeval_diff_in_msec(const struct timeval *end_time, const struct timeval *start_time)
Definition: porting.c:2133
char * stristr(const char *s, const char *find)
Definition: porting.c:1242
void port_close_memstream(FILE *fp, char **ptr, size_t *sizeloc)
Definition: porting.c:2220
#define LLONG_MIN
Definition: porting.h:78
#define THREAD_RET_T
Definition: porting.h:713
#define assert(x)
int str_to_uint64(UINT64 *ret_p, char **end_p, const char *str_p, int base)
Definition: porting.c:2449
int asprintf(char **ptr, const char *format,...)
Definition: porting.c:973
int cub_dirname_r(const char *path, char *pathbuf, size_t buflen)
Definition: porting.c:989
#define NULL
Definition: freelistheap.h:34
int str_to_int32(int *ret_p, char **end_p, const char *str_p, int base)
Definition: porting.c:2346
#define CTIME_MAX
Definition: porting.h:72
#define err(fd,...)
Definition: porting.h:431
static struct timeval start_time
int count(int &result, const cub_regex_object &reg, const std::string &src, const int position, const INTL_CODESET codeset)
int timeval_to_timespec(struct timespec *to, const struct timeval *from)
Definition: porting.c:2173
#define LLONG_MAX
Definition: porting.h:75
static void error(const char *msg)
Definition: gencat.c:331
static int rc
Definition: serial.c:50
fd_set rset
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: porting.c:2584
#define strlen(s1)
Definition: intl_support.c:43
#define FALSE
Definition: broker_admin.c:50
char * basename(const char *path)
Definition: porting.c:1132
int i
Definition: dynamic_load.c:954
char * strdup(const char *str)
Definition: porting.c:901
int parse_bigint(INT64 *ret_p, const char *str_p, int base)
Definition: porting.c:2318
int msleep(const long msec)
Definition: porting.c:2657
void(* SIGNAL_HANDLER_FUNCTION)(int sig_no)
Definition: porting.h:502
int timeval_add_msec(struct timeval *added_time, const struct timeval *start_time, int msec)
Definition: porting.c:2152
int str_to_float(float *ret_p, char **end_p, const char *str_p)
Definition: porting.c:2509
#define PATH_SEPARATOR
Definition: porting.h:347
SIGNAL_HANDLER_FUNCTION os_set_signal_handler(const int sig_no, SIGNAL_HANDLER_FUNCTION sig_handler)
Definition: porting.c:1333
const char ** p
Definition: dynamic_load.c:945
#define THREAD_CALLING_CONVENTION
Definition: porting.h:714
int basename_r(const char *path, char *pathbuf, size_t buflen)
Definition: porting.c:1082
#define pthread_mutex_destroy(a)
Definition: area_alloc.c:49
FILE * port_open_memstream(char **ptr, size_t *sizeloc)
Definition: porting.c:2198