add missing \0 to the end of several strncpy strings
[rrdtool.git] / src / rrd_thread_safe_nt.c
1 /*****************************************************************************
2  * RRDtool 1.2.15  Copyright by Tobi Oetiker, 1997-2006
3  * This file:     Copyright 2003 Peter Stamfest <peter@stamfest.at> 
4  *                             & Tobias Oetiker
5  * Distributed under the GPL
6  *****************************************************************************
7  * rrd_thread_safe.c   Contains routines used when thread safety is required
8  *                     for win32
9  *****************************************************************************
10  * $Id$
11  *************************************************************************** */
12
13 #include <windows.h>
14 #include <string.h>
15 /* #include <error.h> */
16 #include "rrd.h"
17 #include "rrd_tool.h"
18
19 /* Key for the thread-specific rrd_context */
20 static DWORD context_key;
21 static CRITICAL_SECTION CriticalSection; 
22
23
24 /* Once-only initialisation of the key */
25 static DWORD context_key_once = 0;
26
27
28 /* Free the thread-specific rrd_context - we might actually use
29    rrd_free_context instead...
30  */
31 static void context_destroy_context(void)
32 {
33         DeleteCriticalSection(&CriticalSection);
34     TlsFree(context_key);
35         context_key_once=0;
36 }
37 static void context_init_context(void)
38 {
39         if (!InterlockedExchange(&context_key_once, 1)) {
40                 context_key = TlsAlloc();
41                 InitializeCriticalSection(&CriticalSection);
42                 atexit(context_destroy_context);
43         }
44 }
45 struct rrd_context *rrd_get_context(void) {
46     struct rrd_context *ctx;
47                 
48         context_init_context();
49  
50     ctx = TlsGetValue(context_key);
51     if (!ctx) {
52                 ctx = rrd_new_context();
53                 TlsSetValue(context_key, ctx);
54     } 
55     return ctx;
56 }
57 #undef strerror
58 const char *rrd_strerror(int err) {
59     struct rrd_context *ctx;
60         context_init_context();
61
62         ctx = rrd_get_context();
63
64     EnterCriticalSection(&CriticalSection); 
65     strncpy(ctx->lib_errstr, strerror(err), ctx->errlen);
66     ctx->lib_errstr[ctx->errlen] = '\0';
67     LeaveCriticalSection(&CriticalSection); 
68
69     return ctx->lib_errstr;
70 }
71 /*
72  * there much be a re-entrant version of these somewhere in win32 land
73  */
74 struct tm* localtime_r(const time_t *timep, struct tm* result)
75 {
76         struct tm *local;
77         context_init_context();
78
79         EnterCriticalSection(&CriticalSection);
80         local = localtime(timep);
81         memcpy(result,local,sizeof(struct tm));
82         LeaveCriticalSection(&CriticalSection);
83         return result;
84 }
85 char* ctime_r(const time_t *timep, char* result)
86 {
87         char *local;
88         context_init_context();
89
90         EnterCriticalSection(&CriticalSection);
91         local = ctime(timep);
92         strcpy(result,local);
93         LeaveCriticalSection(&CriticalSection);
94         return result;
95 }
96
97 struct tm* gmtime_r(const time_t *timep, struct tm* result)
98 {
99         struct tm *local;
100         context_init_context();
101
102         EnterCriticalSection(&CriticalSection);
103         local = gmtime(timep);
104         memcpy(result,local,sizeof(struct tm));
105         LeaveCriticalSection(&CriticalSection);
106         return result;
107 }
108
109 /* implementation from Apache's APR library */
110 char *strtok_r(char *str, const char *sep, char **last)
111 {
112     char *token;
113         context_init_context();
114
115
116     if (!str)           /* subsequent call */
117         str = *last;    /* start where we left off */
118
119     /* skip characters in sep (will terminate at '\0') */
120     while (*str && strchr(sep, *str))
121         ++str;
122
123     if (!*str)          /* no more tokens */
124         return NULL;
125
126     token = str;
127
128     /* skip valid token characters to terminate token and
129      * prepare for the next call (will terminate at '\0) 
130      */
131     *last = token + 1;
132     while (**last && !strchr(sep, **last))
133         ++*last;
134
135     if (**last) {
136         **last = '\0';
137         ++*last;
138     }
139
140     return token;
141 }
142