xref: /PHP-8.0/main/reentrancy.c (revision 816b4c12)
1 /*
2    +----------------------------------------------------------------------+
3    | Copyright (c) The PHP Group                                          |
4    +----------------------------------------------------------------------+
5    | This source file is subject to version 3.01 of the PHP license,      |
6    | that is bundled with this package in the file LICENSE, and is        |
7    | available through the world-wide-web at the following url:           |
8    | http://www.php.net/license/3_01.txt                                  |
9    | If you did not receive a copy of the PHP license and are unable to   |
10    | obtain it through the world-wide-web, please send a note to          |
11    | license@php.net so we can mail you a copy immediately.               |
12    +----------------------------------------------------------------------+
13    | Author: Sascha Schumann <sascha@schumann.cx>                         |
14    +----------------------------------------------------------------------+
15  */
16 
17 #include <sys/types.h>
18 #include <string.h>
19 #include <errno.h>
20 #ifdef HAVE_DIRENT_H
21 #include <dirent.h>
22 #endif
23 
24 #include "php_reentrancy.h"
25 #include "ext/standard/php_rand.h"                   /* for PHP_RAND_MAX */
26 
27 enum {
28 	LOCALTIME_R,
29 	CTIME_R,
30 	ASCTIME_R,
31 	GMTIME_R,
32 	READDIR_R,
33 	NUMBER_OF_LOCKS
34 };
35 
36 #if defined(PHP_NEED_REENTRANCY)
37 
38 #include <TSRM.h>
39 
40 static MUTEX_T reentrant_locks[NUMBER_OF_LOCKS];
41 
42 #define local_lock(x) tsrm_mutex_lock(reentrant_locks[x])
43 #define local_unlock(x) tsrm_mutex_unlock(reentrant_locks[x])
44 
45 #else
46 
47 #define local_lock(x)
48 #define local_unlock(x)
49 
50 #endif
51 
52 #if defined(PHP_IRIX_TIME_R)
53 
54 #define HAVE_CTIME_R 1
55 #define HAVE_ASCTIME_R 1
56 
php_ctime_r(const time_t * clock,char * buf)57 PHPAPI char *php_ctime_r(const time_t *clock, char *buf)
58 {
59 	if (ctime_r(clock, buf) == buf)
60 		return (buf);
61 	return (NULL);
62 }
63 
php_asctime_r(const struct tm * tm,char * buf)64 PHPAPI char *php_asctime_r(const struct tm *tm, char *buf)
65 {
66 	if (asctime_r(tm, buf) == buf)
67 		return (buf);
68 	return (NULL);
69 }
70 
71 #endif
72 
73 #if defined(PHP_HPUX_TIME_R)
74 
75 #define HAVE_LOCALTIME_R 1
76 #define HAVE_CTIME_R 1
77 #define HAVE_ASCTIME_R 1
78 #define HAVE_GMTIME_R 1
79 
php_localtime_r(const time_t * const timep,struct tm * p_tm)80 PHPAPI struct tm *php_localtime_r(const time_t *const timep, struct tm *p_tm)
81 {
82 	if (localtime_r(timep, p_tm) == 0)
83 		return (p_tm);
84 	return (NULL);
85 }
86 
php_ctime_r(const time_t * clock,char * buf)87 PHPAPI char *php_ctime_r(const time_t *clock, char *buf)
88 {
89 	if (ctime_r(clock, buf, 26) != -1)
90 		return (buf);
91 	return (NULL);
92 }
93 
php_asctime_r(const struct tm * tm,char * buf)94 PHPAPI char *php_asctime_r(const struct tm *tm, char *buf)
95 {
96 	if (asctime_r(tm, buf, 26) != -1)
97 		return (buf);
98 	return (NULL);
99 }
100 
php_gmtime_r(const time_t * const timep,struct tm * p_tm)101 PHPAPI struct tm *php_gmtime_r(const time_t *const timep, struct tm *p_tm)
102 {
103 	if (gmtime_r(timep, p_tm) == 0)
104 		return (p_tm);
105 	return (NULL);
106 }
107 
108 #endif
109 
110 #if !defined(HAVE_LOCALTIME_R) && defined(HAVE_LOCALTIME)
111 
php_localtime_r(const time_t * const timep,struct tm * p_tm)112 PHPAPI struct tm *php_localtime_r(const time_t *const timep, struct tm *p_tm)
113 {
114 	struct tm *tmp;
115 
116 	local_lock(LOCALTIME_R);
117 
118 	tmp = localtime(timep);
119 	if (tmp) {
120 		memcpy(p_tm, tmp, sizeof(struct tm));
121 		tmp = p_tm;
122 	}
123 
124 	local_unlock(LOCALTIME_R);
125 
126 	return tmp;
127 }
128 
129 #endif
130 
131 #if !defined(HAVE_CTIME_R) && defined(HAVE_CTIME)
132 
php_ctime_r(const time_t * clock,char * buf)133 PHPAPI char *php_ctime_r(const time_t *clock, char *buf)
134 {
135 	char *tmp;
136 
137 	local_lock(CTIME_R);
138 
139 	tmp = ctime(clock);
140 	if (tmp) {
141 		strcpy(buf, tmp);
142 		tmp = buf;
143 	}
144 
145 	local_unlock(CTIME_R);
146 
147 	return tmp;
148 }
149 
150 #endif
151 
152 #if !defined(HAVE_ASCTIME_R) && defined(HAVE_ASCTIME)
153 
php_asctime_r(const struct tm * tm,char * buf)154 PHPAPI char *php_asctime_r(const struct tm *tm, char *buf)
155 {
156 	char *tmp;
157 
158 	local_lock(ASCTIME_R);
159 
160 	tmp = asctime(tm);
161 	if (tmp) {
162 		strcpy(buf, tmp);
163 		tmp = buf;
164 	}
165 
166 	local_unlock(ASCTIME_R);
167 
168 	return tmp;
169 }
170 
171 #endif
172 
173 #if !defined(HAVE_GMTIME_R) && defined(HAVE_GMTIME)
174 
php_gmtime_r(const time_t * const timep,struct tm * p_tm)175 PHPAPI struct tm *php_gmtime_r(const time_t *const timep, struct tm *p_tm)
176 {
177 	struct tm *tmp;
178 
179 	local_lock(GMTIME_R);
180 
181 	tmp = gmtime(timep);
182 	if (tmp) {
183 		memcpy(p_tm, tmp, sizeof(struct tm));
184 		tmp = p_tm;
185 	}
186 
187 	local_unlock(GMTIME_R);
188 
189 	return tmp;
190 }
191 
192 #endif
193 
194 #if defined(PHP_NEED_REENTRANCY)
195 
reentrancy_startup(void)196 void reentrancy_startup(void)
197 {
198 	int i;
199 
200 	for (i = 0; i < NUMBER_OF_LOCKS; i++) {
201 		reentrant_locks[i] = tsrm_mutex_alloc();
202 	}
203 }
204 
reentrancy_shutdown(void)205 void reentrancy_shutdown(void)
206 {
207 	int i;
208 
209 	for (i = 0; i < NUMBER_OF_LOCKS; i++) {
210 		tsrm_mutex_free(reentrant_locks[i]);
211 	}
212 }
213 
214 #endif
215 
216 
217 #ifndef HAVE_STRTOK_R
218 
219 /*
220  * Copyright (c) 1998 Softweyr LLC.  All rights reserved.
221  *
222  * strtok_r, from Berkeley strtok
223  * Oct 13, 1998 by Wes Peters <wes@softweyr.com>
224  *
225  * Copyright (c) 1988, 1993
226  *	The Regents of the University of California.  All rights reserved.
227  *
228  * Redistribution and use in source and binary forms, with or without
229  * modification, are permitted provided that the following conditions
230  * are met:
231  *
232  * 1. Redistributions of source code must retain the above copyright
233  *    notices, this list of conditions and the following disclaimer.
234  *
235  * 2. Redistributions in binary form must reproduce the above copyright
236  *    notices, this list of conditions and the following disclaimer in the
237  *    documentation and/or other materials provided with the distribution.
238  *
239  * 3. All advertising materials mentioning features or use of this software
240  *    must display the following acknowledgement:
241  *
242  *	This product includes software developed by Softweyr LLC, the
243  *      University of California, Berkeley, and its contributors.
244  *
245  * 4. Neither the name of the University nor the names of its contributors
246  *    may be used to endorse or promote products derived from this software
247  *    without specific prior written permission.
248  *
249  * THIS SOFTWARE IS PROVIDED BY SOFTWEYR LLC, THE REGENTS AND CONTRIBUTORS
250  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
251  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
252  * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL SOFTWEYR LLC, THE
253  * REGENTS, OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
254  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
255  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
256  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
257  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
258  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
259  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
260  */
261 
262 #include <stddef.h>
263 
264 PHPAPI char *
php_strtok_r(char * s,const char * delim,char ** last)265 php_strtok_r(char *s, const char *delim, char **last)
266 {
267     char *spanp;
268     int c, sc;
269     char *tok;
270 
271     if (s == NULL && (s = *last) == NULL)
272     {
273 	return NULL;
274     }
275 
276     /*
277      * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
278      */
279 cont:
280     c = *s++;
281     for (spanp = (char *)delim; (sc = *spanp++) != 0; )
282     {
283 	if (c == sc)
284 	{
285 	    goto cont;
286 	}
287     }
288 
289     if (c == 0)		/* no non-delimiter characters */
290     {
291 	*last = NULL;
292 	return NULL;
293     }
294     tok = s - 1;
295 
296     /*
297      * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
298      * Note that delim must have one NUL; we stop if we see that, too.
299      */
300     for (;;)
301     {
302 	c = *s++;
303 	spanp = (char *)delim;
304 	do
305 	{
306 	    if ((sc = *spanp++) == c)
307 	    {
308 		if (c == 0)
309 		{
310 		    s = NULL;
311 		}
312 		else
313 		{
314 		    char *w = s - 1;
315 		    *w = '\0';
316 		}
317 		*last = s;
318 		return tok;
319 	    }
320 	}
321 	while (sc != 0);
322     }
323     /* NOTREACHED */
324 }
325 
326 #endif
327