xref: /PHP-7.1/main/reentrancy.c (revision ccd4716e)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 7                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1997-2018 The PHP Group                                |
6    +----------------------------------------------------------------------+
7    | This source file is subject to version 3.01 of the PHP license,      |
8    | that is bundled with this package in the file LICENSE, and is        |
9    | available through the world-wide-web at the following url:           |
10    | http://www.php.net/license/3_01.txt                                  |
11    | If you did not receive a copy of the PHP license and are unable to   |
12    | obtain it through the world-wide-web, please send a note to          |
13    | license@php.net so we can mail you a copy immediately.               |
14    +----------------------------------------------------------------------+
15    | Author: Sascha Schumann <sascha@schumann.cx>                         |
16    +----------------------------------------------------------------------+
17  */
18 
19 /* $Id$ */
20 
21 #include <sys/types.h>
22 #include <string.h>
23 #include <errno.h>
24 #ifdef HAVE_DIRENT_H
25 #include <dirent.h>
26 #endif
27 
28 #include "php_reentrancy.h"
29 #include "ext/standard/php_rand.h"                   /* for PHP_RAND_MAX */
30 
31 enum {
32 	LOCALTIME_R,
33 	CTIME_R,
34 	ASCTIME_R,
35 	GMTIME_R,
36 	READDIR_R,
37 	NUMBER_OF_LOCKS
38 };
39 
40 #if defined(PHP_NEED_REENTRANCY)
41 
42 #include <TSRM.h>
43 
44 static MUTEX_T reentrant_locks[NUMBER_OF_LOCKS];
45 
46 #define local_lock(x) tsrm_mutex_lock(reentrant_locks[x])
47 #define local_unlock(x) tsrm_mutex_unlock(reentrant_locks[x])
48 
49 #else
50 
51 #define local_lock(x)
52 #define local_unlock(x)
53 
54 #endif
55 
56 #if defined(PHP_IRIX_TIME_R)
57 
58 #define HAVE_CTIME_R 1
59 #define HAVE_ASCTIME_R 1
60 
php_ctime_r(const time_t * clock,char * buf)61 PHPAPI char *php_ctime_r(const time_t *clock, char *buf)
62 {
63 	if (ctime_r(clock, buf) == buf)
64 		return (buf);
65 	return (NULL);
66 }
67 
php_asctime_r(const struct tm * tm,char * buf)68 PHPAPI char *php_asctime_r(const struct tm *tm, char *buf)
69 {
70 	if (asctime_r(tm, buf) == buf)
71 		return (buf);
72 	return (NULL);
73 }
74 
75 #endif
76 
77 #if defined(PHP_HPUX_TIME_R)
78 
79 #define HAVE_LOCALTIME_R 1
80 #define HAVE_CTIME_R 1
81 #define HAVE_ASCTIME_R 1
82 #define HAVE_GMTIME_R 1
83 
php_localtime_r(const time_t * const timep,struct tm * p_tm)84 PHPAPI struct tm *php_localtime_r(const time_t *const timep, struct tm *p_tm)
85 {
86 	if (localtime_r(timep, p_tm) == 0)
87 		return (p_tm);
88 	return (NULL);
89 }
90 
php_ctime_r(const time_t * clock,char * buf)91 PHPAPI char *php_ctime_r(const time_t *clock, char *buf)
92 {
93 	if (ctime_r(clock, buf, 26) != -1)
94 		return (buf);
95 	return (NULL);
96 }
97 
php_asctime_r(const struct tm * tm,char * buf)98 PHPAPI char *php_asctime_r(const struct tm *tm, char *buf)
99 {
100 	if (asctime_r(tm, buf, 26) != -1)
101 		return (buf);
102 	return (NULL);
103 }
104 
php_gmtime_r(const time_t * const timep,struct tm * p_tm)105 PHPAPI struct tm *php_gmtime_r(const time_t *const timep, struct tm *p_tm)
106 {
107 	if (gmtime_r(timep, p_tm) == 0)
108 		return (p_tm);
109 	return (NULL);
110 }
111 
112 #endif
113 
114 #if defined(__BEOS__)
115 
php_gmtime_r(const time_t * const timep,struct tm * p_tm)116 PHPAPI struct tm *php_gmtime_r(const time_t *const timep, struct tm *p_tm)
117 {
118     /* Modified according to LibC definition */
119         if (((struct tm*)gmtime_r(timep, p_tm)) == p_tm)
120                 return (p_tm);
121         return (NULL);
122 }
123 
124 #endif /* BEOS */
125 
126 #if !defined(HAVE_POSIX_READDIR_R)
127 
php_readdir_r(DIR * dirp,struct dirent * entry,struct dirent ** result)128 PHPAPI int php_readdir_r(DIR *dirp, struct dirent *entry,
129 		struct dirent **result)
130 {
131 #if defined(HAVE_OLD_READDIR_R)
132 	int ret = 0;
133 
134 	/* We cannot rely on the return value of readdir_r
135 	   as it differs between various platforms
136 	   (HPUX returns 0 on success whereas Solaris returns non-zero)
137 	 */
138 	entry->d_name[0] = '\0';
139 	readdir_r(dirp, entry);
140 
141 	if (entry->d_name[0] == '\0') {
142 		*result = NULL;
143 		ret = errno;
144 	} else {
145 		*result = entry;
146 	}
147 	return ret;
148 #else
149 	struct dirent *ptr;
150 	int ret = 0;
151 
152 	local_lock(READDIR_R);
153 
154 	errno = 0;
155 
156 	ptr = readdir(dirp);
157 
158 	if (!ptr && errno != 0)
159 		ret = errno;
160 
161 	if (ptr)
162 		memcpy(entry, ptr, sizeof(*ptr));
163 
164 	*result = ptr;
165 
166 	local_unlock(READDIR_R);
167 
168 	return ret;
169 #endif
170 }
171 
172 #endif
173 
174 #if !defined(HAVE_LOCALTIME_R) && defined(HAVE_LOCALTIME)
175 
php_localtime_r(const time_t * const timep,struct tm * p_tm)176 PHPAPI struct tm *php_localtime_r(const time_t *const timep, struct tm *p_tm)
177 {
178 	struct tm *tmp;
179 
180 	local_lock(LOCALTIME_R);
181 
182 	tmp = localtime(timep);
183 	if (tmp) {
184 		memcpy(p_tm, tmp, sizeof(struct tm));
185 		tmp = p_tm;
186 	}
187 
188 	local_unlock(LOCALTIME_R);
189 
190 	return tmp;
191 }
192 
193 #endif
194 
195 #if !defined(HAVE_CTIME_R) && defined(HAVE_CTIME)
196 
php_ctime_r(const time_t * clock,char * buf)197 PHPAPI char *php_ctime_r(const time_t *clock, char *buf)
198 {
199 	char *tmp;
200 
201 	local_lock(CTIME_R);
202 
203 	tmp = ctime(clock);
204 	strcpy(buf, tmp);
205 
206 	local_unlock(CTIME_R);
207 
208 	return buf;
209 }
210 
211 #endif
212 
213 #if !defined(HAVE_ASCTIME_R) && defined(HAVE_ASCTIME)
214 
php_asctime_r(const struct tm * tm,char * buf)215 PHPAPI char *php_asctime_r(const struct tm *tm, char *buf)
216 {
217 	char *tmp;
218 
219 	local_lock(ASCTIME_R);
220 
221 	tmp = asctime(tm);
222 	strcpy(buf, tmp);
223 
224 	local_unlock(ASCTIME_R);
225 
226 	return buf;
227 }
228 
229 #endif
230 
231 #if !defined(HAVE_GMTIME_R) && defined(HAVE_GMTIME)
232 
php_gmtime_r(const time_t * const timep,struct tm * p_tm)233 PHPAPI struct tm *php_gmtime_r(const time_t *const timep, struct tm *p_tm)
234 {
235 	struct tm *tmp;
236 
237 	local_lock(GMTIME_R);
238 
239 	tmp = gmtime(timep);
240 	if (tmp) {
241 		memcpy(p_tm, tmp, sizeof(struct tm));
242 		tmp = p_tm;
243 	}
244 
245 	local_unlock(GMTIME_R);
246 
247 	return tmp;
248 }
249 
250 #endif
251 
252 #if defined(PHP_NEED_REENTRANCY)
253 
reentrancy_startup(void)254 void reentrancy_startup(void)
255 {
256 	int i;
257 
258 	for (i = 0; i < NUMBER_OF_LOCKS; i++) {
259 		reentrant_locks[i] = tsrm_mutex_alloc();
260 	}
261 }
262 
reentrancy_shutdown(void)263 void reentrancy_shutdown(void)
264 {
265 	int i;
266 
267 	for (i = 0; i < NUMBER_OF_LOCKS; i++) {
268 		tsrm_mutex_free(reentrant_locks[i]);
269 	}
270 }
271 
272 #endif
273 
274 #ifndef HAVE_RAND_R
275 
276 /*-
277  * Copyright (c) 1990, 1993
278  *	The Regents of the University of California.  All rights reserved.
279  *
280  * Redistribution and use in source and binary forms, with or without
281  * modification, are permitted provided that the following conditions
282  * are met:
283  * 1. Redistributions of source code must retain the above copyright
284  *    notice, this list of conditions and the following disclaimer.
285  * 2. Redistributions in binary form must reproduce the above copyright
286  *    notice, this list of conditions and the following disclaimer in the
287  *    documentation and/or other materials provided with the distribution.
288  * 3. All advertising materials mentioning features or use of this software
289  *    must display the following acknowledgement:
290  *	This product includes software developed by the University of
291  *	California, Berkeley and its contributors.
292  * 4. Neither the name of the University nor the names of its contributors
293  *    may be used to endorse or promote products derived from this software
294  *    without specific prior written permission.
295  *
296  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
297  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
298  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
299  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
300  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
301  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
302  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
303  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
304  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
305  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
306  * SUCH DAMAGE.
307  *
308  * Posix rand_r function added May 1999 by Wes Peters <wes@softweyr.com>.
309  */
310 
311 #include <sys/types.h>
312 #include <stdlib.h>
313 
314 static int
do_rand(unsigned long * ctx)315 do_rand(unsigned long *ctx)
316 {
317 	return ((*ctx = *ctx * 1103515245 + 12345) % ((u_long)PHP_RAND_MAX + 1));
318 }
319 
320 
321 PHPAPI int
php_rand_r(unsigned int * ctx)322 php_rand_r(unsigned int *ctx)
323 {
324 	u_long val = (u_long) *ctx;
325 	*ctx = do_rand(&val);
326 	return (int) *ctx;
327 }
328 
329 #endif
330 
331 
332 #ifndef HAVE_STRTOK_R
333 
334 /*
335  * Copyright (c) 1998 Softweyr LLC.  All rights reserved.
336  *
337  * strtok_r, from Berkeley strtok
338  * Oct 13, 1998 by Wes Peters <wes@softweyr.com>
339  *
340  * Copyright (c) 1988, 1993
341  *	The Regents of the University of California.  All rights reserved.
342  *
343  * Redistribution and use in source and binary forms, with or without
344  * modification, are permitted provided that the following conditions
345  * are met:
346  *
347  * 1. Redistributions of source code must retain the above copyright
348  *    notices, this list of conditions and the following disclaimer.
349  *
350  * 2. Redistributions in binary form must reproduce the above copyright
351  *    notices, this list of conditions and the following disclaimer in the
352  *    documentation and/or other materials provided with the distribution.
353  *
354  * 3. All advertising materials mentioning features or use of this software
355  *    must display the following acknowledgement:
356  *
357  *	This product includes software developed by Softweyr LLC, the
358  *      University of California, Berkeley, and its contributors.
359  *
360  * 4. Neither the name of the University nor the names of its contributors
361  *    may be used to endorse or promote products derived from this software
362  *    without specific prior written permission.
363  *
364  * THIS SOFTWARE IS PROVIDED BY SOFTWEYR LLC, THE REGENTS AND CONTRIBUTORS
365  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
366  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
367  * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL SOFTWEYR LLC, THE
368  * REGENTS, OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
369  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
370  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
371  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
372  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
373  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
374  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
375  */
376 
377 #include <stddef.h>
378 
379 PHPAPI char *
php_strtok_r(char * s,const char * delim,char ** last)380 php_strtok_r(char *s, const char *delim, char **last)
381 {
382     char *spanp;
383     int c, sc;
384     char *tok;
385 
386     if (s == NULL && (s = *last) == NULL)
387     {
388 	return NULL;
389     }
390 
391     /*
392      * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
393      */
394 cont:
395     c = *s++;
396     for (spanp = (char *)delim; (sc = *spanp++) != 0; )
397     {
398 	if (c == sc)
399 	{
400 	    goto cont;
401 	}
402     }
403 
404     if (c == 0)		/* no non-delimiter characters */
405     {
406 	*last = NULL;
407 	return NULL;
408     }
409     tok = s - 1;
410 
411     /*
412      * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
413      * Note that delim must have one NUL; we stop if we see that, too.
414      */
415     for (;;)
416     {
417 	c = *s++;
418 	spanp = (char *)delim;
419 	do
420 	{
421 	    if ((sc = *spanp++) == c)
422 	    {
423 		if (c == 0)
424 		{
425 		    s = NULL;
426 		}
427 		else
428 		{
429 		    char *w = s - 1;
430 		    *w = '\0';
431 		}
432 		*last = s;
433 		return tok;
434 	    }
435 	}
436 	while (sc != 0);
437     }
438     /* NOTREACHED */
439 }
440 
441 #endif
442 
443 /*
444  * Local variables:
445  * tab-width: 4
446  * c-basic-offset: 4
447  * End:
448  * vim600: sw=4 ts=4 fdm=marker
449  * vim<600: sw=4 ts=4
450  */
451