2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2006 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 | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
16 | George Schlossnagle <george@omniti.com> |
17 | Rasmus Lerdorf <rasmus@php.net> |
18 | Arun C. Murthy <arunc@yahoo-inc.com> |
19 | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
20 +----------------------------------------------------------------------+
22 This software was contributed to PHP by Community Connect Inc. in 2002
23 and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
24 Future revisions and derivatives of this source code must acknowledge
25 Community Connect Inc. as the original contributor of this module by
26 leaving this note intact in the source code.
28 All other licensing and usage conditions are those of the PHP Group.
32 /* $Id: apc.c,v 3.18 2007/11/29 22:15:53 shire Exp $ */
35 #include <regex.h> /* for POSIX regular expressions */
38 #define NELEMS(a) (sizeof(a)/sizeof((a)[0]))
40 /* {{{ memory allocation wrappers */
42 void* apc_emalloc(size_t n)
46 apc_eprint("apc_emalloc: malloc failed to allocate %u bytes:", n);
51 void* apc_erealloc(void* p, size_t n)
55 apc_eprint("apc_erealloc: realloc failed to allocate %u bytes:", n);
60 void apc_efree(void* p)
63 apc_eprint("apc_efree: attempt to free null pointer");
68 char* apc_estrdup(const char* s)
77 dup = (char*) malloc(len+1);
79 apc_eprint("apc_estrdup: malloc failed to allocate %u bytes:", len+1);
86 void* apc_xstrdup(const char* s, apc_malloc_t f)
88 return s != NULL ? apc_xmemcpy(s, strlen(s)+1, f) : NULL;
91 void* apc_xmemcpy(const void* p, size_t n, apc_malloc_t f)
95 if (p != NULL && (q = f(n)) != NULL) {
104 /* {{{ console display functions */
106 static void my_log(int level, const char* fmt, va_list args)
108 static const char* level_strings[] = {
114 static const int num_levels = NELEMS(level_strings);
117 char* buf; /* for ctime */
123 else if (level >= num_levels)
124 level = num_levels-1;
127 buf = ctime(&now); /* TODO: replace with reentrant impl */
130 fprintf(stderr, "[%s] [%s] ", buf, level_strings[level]);
131 vfprintf(stderr, fmt, args);
133 if (fmt[0] != '\0' && fmt[strlen(fmt)-1] == ':') {
134 fprintf(stderr, " %s", strerror(errno));
136 fprintf(stderr, "\n");
138 if (level == APC_ERROR) {
143 void apc_log(int level, const char* fmt, ...)
147 my_log(level, fmt, args);
151 void apc_eprint(const char* fmt, ...)
155 my_log(APC_ERROR, fmt, args);
159 void apc_wprint(const char* fmt, ...)
163 my_log(APC_WARNING, fmt, args);
167 void apc_nprint(const char* fmt, ...)
171 my_log(APC_NOTICE, fmt, args);
175 void apc_dprint(const char* fmt, ...)
180 my_log(APC_DBG, fmt, args);
187 /* {{{ string and text manipulation */
189 char* apc_append(const char* s, const char* t)
198 p = (char*) apc_emalloc((slen + tlen + 1) * sizeof(char));
200 memcpy(p + slen, t, tlen + 1);
205 char* apc_substr(const char* s, int start, int length)
208 int src_len = strlen(s);
210 /* bring start into range */
214 else if (start >= src_len) {
218 /* bring length into range */
219 if (length < 0 || src_len - start < length) {
220 length = src_len - start;
223 /* create the substring */
224 substr = apc_xmemcpy(s + start, length + 1, apc_emalloc);
225 substr[length] = '\0';
229 char** apc_tokenize(const char* s, char delim)
231 char** tokens; /* array of tokens, NULL terminated */
232 int size; /* size of tokens array */
233 int n; /* index of next token in tokens array */
234 int cur; /* current position in input string */
235 int end; /* final legal position in input string */
236 int next; /* position of next delimiter in input */
247 tokens = (char**) apc_emalloc(size * sizeof(char*));
251 /* search for the next delimiter */
252 char* p = strchr(s + cur, delim);
253 next = p ? p-s : end+1;
255 /* resize token array if necessary */
258 tokens = (char**) apc_erealloc(tokens, size * sizeof(char*));
261 /* save the current token */
262 tokens[n] = apc_substr(s, cur, next-cur);
273 /* {{{ filesystem functions */
276 int apc_win32_stat(const char *path, struct stat *buf TSRMLS_DC)
278 char rpath[MAXPATHLEN];
279 BY_HANDLE_FILE_INFORMATION fi;
282 if (VCWD_STAT(path, buf)) {
286 VCWD_REALPATH(path, rpath);
287 f = CreateFile(rpath, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_READONLY, NULL);
288 GetFileInformationByHandle(f, &fi);
289 buf->st_ino = (ino_t)fi.nFileIndexLow;
295 int apc_search_paths(const char* filename, const char* path, apc_fileinfo_t* fileinfo)
299 int exec_fname_length;
304 assert(filename && fileinfo);
306 if (IS_ABSOLUTE_PATH(filename, strlen(filename)) && apc_stat(filename, &fileinfo->st_buf) == 0) {
307 strncpy(fileinfo->fullpath, filename, MAXPATHLEN);
311 paths = apc_tokenize(path, DEFAULT_DIR_SEPARATOR);
315 /* for each directory in paths, look for filename inside */
316 for (i = 0; paths[i]; i++) {
317 snprintf(fileinfo->fullpath, sizeof(fileinfo->fullpath), "%s%c%s", paths[i], DEFAULT_SLASH, filename);
318 if (apc_stat(fileinfo->fullpath, &fileinfo->st_buf) == 0) {
324 /* check in path of the calling scripts' current working directory */
325 /* modified from main/streams/plain_wrapper.c */
326 if(!found && zend_is_executing(TSRMLS_C)) {
327 exec_fname = zend_get_executed_filename(TSRMLS_C);
328 exec_fname_length = strlen(exec_fname);
329 while((--exec_fname_length >= 0) && !IS_SLASH(exec_fname[exec_fname_length]));
330 if((exec_fname && exec_fname[0] != '[') && exec_fname_length > 0) {
331 /* not: [no active file] or no path */
332 memcpy(fileinfo->fullpath, exec_fname, exec_fname_length);
333 fileinfo->fullpath[exec_fname_length] = DEFAULT_SLASH;
334 strcpy(fileinfo->fullpath +exec_fname_length +1, filename);
335 /* apc_wprint("filename: %s, exec_fname: %s, fileinfo->fullpath: %s", filename, exec_fname, fileinfo->fullpath); */
336 if (apc_stat(fileinfo->fullpath, &fileinfo->st_buf) == 0) {
342 /* free the value returned by apc_tokenize */
343 for (i = 0; paths[i]; i++) {
348 return found ? 0 : -1;
353 /* {{{ regular expression wrapper functions */
360 void* apc_regex_compile_array(char* patterns[])
369 /* count the number of patterns in patterns */
370 for (npat = 0; patterns[npat] != NULL; npat++) {}
375 /* allocate the array of compiled expressions */
376 regs = (apc_regex**) apc_emalloc(sizeof(apc_regex*) * (npat + 1));
377 for (i = 0; i <= npat; i++) {
378 regs[i] = (apc_regex *) apc_emalloc(sizeof(apc_regex));
380 regs[i]->type = APC_NEGATIVE_MATCH;
383 /* compile the expressions */
384 for (i = 0; i < npat; i++) {
385 char *pattern = patterns[i];
386 if(pattern[0]=='+') { regs[i]->type = APC_POSITIVE_MATCH; pattern = patterns[i]+sizeof(char); }
387 else if(pattern[0]=='-') { regs[i]->type = APC_NEGATIVE_MATCH; pattern = patterns[i]+sizeof(char); }
389 regs[i]->reg = (regex_t*) apc_emalloc(sizeof(regex_t));
391 if (regcomp(regs[i]->reg, pattern, REG_EXTENDED | REG_NOSUB) != 0) {
392 apc_wprint("apc_regex_compile_array: invalid expression '%s'",
395 apc_regex_destroy_array(regs);
404 void apc_regex_destroy_array(void* p)
407 apc_regex** regs = (apc_regex**) p;
410 for (i = 0; regs[i]->reg != NULL; i++) {
411 regfree(regs[i]->reg);
412 apc_efree(regs[i]->reg);
419 int apc_regex_match_array(void* p, const char* input)
427 regs = (apc_regex**) p;
428 for (i = 0; regs[i]->reg != NULL; i++)
429 if (regexec(regs[i]->reg, input, 0, NULL, 0) == 0)
430 return (int)(regs[i]->type);
437 /* {{{ crc32 implementation */
439 /* this table was generated by crc32gen() */
440 static unsigned int crc32tab[] = {
441 /* 0 */ 0x00000000, 0x3b83984b, 0x77073096, 0x4c84a8dd,
442 /* 4 */ 0xee0e612c, 0xd58df967, 0x990951ba, 0xa28ac9f1,
443 /* 8 */ 0x076dc419, 0x3cee5c52, 0x706af48f, 0x4be96cc4,
444 /* 12 */ 0xe963a535, 0xd2e03d7e, 0x9e6495a3, 0xa5e70de8,
445 /* 16 */ 0x0edb8832, 0x35581079, 0x79dcb8a4, 0x425f20ef,
446 /* 20 */ 0xe0d5e91e, 0xdb567155, 0x97d2d988, 0xac5141c3,
447 /* 24 */ 0x09b64c2b, 0x3235d460, 0x7eb17cbd, 0x4532e4f6,
448 /* 28 */ 0xe7b82d07, 0xdc3bb54c, 0x90bf1d91, 0xab3c85da,
449 /* 32 */ 0x1db71064, 0x2634882f, 0x6ab020f2, 0x5133b8b9,
450 /* 36 */ 0xf3b97148, 0xc83ae903, 0x84be41de, 0xbf3dd995,
451 /* 40 */ 0x1adad47d, 0x21594c36, 0x6ddde4eb, 0x565e7ca0,
452 /* 44 */ 0xf4d4b551, 0xcf572d1a, 0x83d385c7, 0xb8501d8c,
453 /* 48 */ 0x136c9856, 0x28ef001d, 0x646ba8c0, 0x5fe8308b,
454 /* 52 */ 0xfd62f97a, 0xc6e16131, 0x8a65c9ec, 0xb1e651a7,
455 /* 56 */ 0x14015c4f, 0x2f82c404, 0x63066cd9, 0x5885f492,
456 /* 60 */ 0xfa0f3d63, 0xc18ca528, 0x8d080df5, 0xb68b95be,
457 /* 64 */ 0x3b6e20c8, 0x00edb883, 0x4c69105e, 0x77ea8815,
458 /* 68 */ 0xd56041e4, 0xeee3d9af, 0xa2677172, 0x99e4e939,
459 /* 72 */ 0x3c03e4d1, 0x07807c9a, 0x4b04d447, 0x70874c0c,
460 /* 76 */ 0xd20d85fd, 0xe98e1db6, 0xa50ab56b, 0x9e892d20,
461 /* 80 */ 0x35b5a8fa, 0x0e3630b1, 0x42b2986c, 0x79310027,
462 /* 84 */ 0xdbbbc9d6, 0xe038519d, 0xacbcf940, 0x973f610b,
463 /* 88 */ 0x32d86ce3, 0x095bf4a8, 0x45df5c75, 0x7e5cc43e,
464 /* 92 */ 0xdcd60dcf, 0xe7559584, 0xabd13d59, 0x9052a512,
465 /* 96 */ 0x26d930ac, 0x1d5aa8e7, 0x51de003a, 0x6a5d9871,
466 /* 100 */ 0xc8d75180, 0xf354c9cb, 0xbfd06116, 0x8453f95d,
467 /* 104 */ 0x21b4f4b5, 0x1a376cfe, 0x56b3c423, 0x6d305c68,
468 /* 108 */ 0xcfba9599, 0xf4390dd2, 0xb8bda50f, 0x833e3d44,
469 /* 112 */ 0x2802b89e, 0x138120d5, 0x5f058808, 0x64861043,
470 /* 116 */ 0xc60cd9b2, 0xfd8f41f9, 0xb10be924, 0x8a88716f,
471 /* 120 */ 0x2f6f7c87, 0x14ece4cc, 0x58684c11, 0x63ebd45a,
472 /* 124 */ 0xc1611dab, 0xfae285e0, 0xb6662d3d, 0x8de5b576,
473 /* 128 */ 0x76dc4190, 0x4d5fd9db, 0x01db7106, 0x3a58e94d,
474 /* 132 */ 0x98d220bc, 0xa351b8f7, 0xefd5102a, 0xd4568861,
475 /* 136 */ 0x71b18589, 0x4a321dc2, 0x06b6b51f, 0x3d352d54,
476 /* 140 */ 0x9fbfe4a5, 0xa43c7cee, 0xe8b8d433, 0xd33b4c78,
477 /* 144 */ 0x7807c9a2, 0x438451e9, 0x0f00f934, 0x3483617f,
478 /* 148 */ 0x9609a88e, 0xad8a30c5, 0xe10e9818, 0xda8d0053,
479 /* 152 */ 0x7f6a0dbb, 0x44e995f0, 0x086d3d2d, 0x33eea566,
480 /* 156 */ 0x91646c97, 0xaae7f4dc, 0xe6635c01, 0xdde0c44a,
481 /* 160 */ 0x6b6b51f4, 0x50e8c9bf, 0x1c6c6162, 0x27eff929,
482 /* 164 */ 0x856530d8, 0xbee6a893, 0xf262004e, 0xc9e19805,
483 /* 168 */ 0x6c0695ed, 0x57850da6, 0x1b01a57b, 0x20823d30,
484 /* 172 */ 0x8208f4c1, 0xb98b6c8a, 0xf50fc457, 0xce8c5c1c,
485 /* 176 */ 0x65b0d9c6, 0x5e33418d, 0x12b7e950, 0x2934711b,
486 /* 180 */ 0x8bbeb8ea, 0xb03d20a1, 0xfcb9887c, 0xc73a1037,
487 /* 184 */ 0x62dd1ddf, 0x595e8594, 0x15da2d49, 0x2e59b502,
488 /* 188 */ 0x8cd37cf3, 0xb750e4b8, 0xfbd44c65, 0xc057d42e,
489 /* 192 */ 0x4db26158, 0x7631f913, 0x3ab551ce, 0x0136c985,
490 /* 196 */ 0xa3bc0074, 0x983f983f, 0xd4bb30e2, 0xef38a8a9,
491 /* 200 */ 0x4adfa541, 0x715c3d0a, 0x3dd895d7, 0x065b0d9c,
492 /* 204 */ 0xa4d1c46d, 0x9f525c26, 0xd3d6f4fb, 0xe8556cb0,
493 /* 208 */ 0x4369e96a, 0x78ea7121, 0x346ed9fc, 0x0fed41b7,
494 /* 212 */ 0xad678846, 0x96e4100d, 0xda60b8d0, 0xe1e3209b,
495 /* 216 */ 0x44042d73, 0x7f87b538, 0x33031de5, 0x088085ae,
496 /* 220 */ 0xaa0a4c5f, 0x9189d414, 0xdd0d7cc9, 0xe68ee482,
497 /* 224 */ 0x5005713c, 0x6b86e977, 0x270241aa, 0x1c81d9e1,
498 /* 228 */ 0xbe0b1010, 0x8588885b, 0xc90c2086, 0xf28fb8cd,
499 /* 232 */ 0x5768b525, 0x6ceb2d6e, 0x206f85b3, 0x1bec1df8,
500 /* 236 */ 0xb966d409, 0x82e54c42, 0xce61e49f, 0xf5e27cd4,
501 /* 240 */ 0x5edef90e, 0x655d6145, 0x29d9c998, 0x125a51d3,
502 /* 244 */ 0xb0d09822, 0x8b530069, 0xc7d7a8b4, 0xfc5430ff,
503 /* 248 */ 0x59b33d17, 0x6230a55c, 0x2eb40d81, 0x153795ca,
504 /* 252 */ 0xb7bd5c3b, 0x8c3ec470, 0xc0ba6cad, 0xfb39f4e6,
507 unsigned int apc_crc32(const char* buf, int len)
513 /* preconditioning */
516 for (i = 0; i < len; i++) {
517 k = (crc ^ buf[i]) & 0x000000FF;
518 crc = ((crc >> 8) & 0x00FFFFFF) ^ crc32tab[k];
521 /* postconditioning */
525 /* crc32gen: generate the nth (0..255) crc32 table value */
527 static unsigned long crc32gen(int n)
533 for (i = 8; i >= 0; i--) {
535 crc = (crc >> 1) ^ 0xEDB88320;
552 * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
553 * vim<600: expandtab sw=4 ts=4 sts=4