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