PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LTP GCOV extension - code coverage report
Current view: directory - var/php_gcov/PHP_5_2/TSRM - tsrm_virtual_cwd.c
Test: PHP Code Coverage
Date: 2009-11-19 Instrumented lines: 454
Code covered: 40.7 % Executed lines: 185
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | PHP Version 5                                                        |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1997-2009 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: Andi Gutmans <andi@zend.com>                                |
      16                 :    |          Sascha Schumann <sascha@schumann.cx>                        |
      17                 :    +----------------------------------------------------------------------+
      18                 : */
      19                 : 
      20                 : /* $Id: tsrm_virtual_cwd.c 272374 2008-12-31 11:17:49Z sebastian $ */
      21                 : 
      22                 : #include <sys/types.h>
      23                 : #include <sys/stat.h>
      24                 : #include <string.h>
      25                 : #include <stdio.h>
      26                 : #include <limits.h>
      27                 : #include <errno.h>
      28                 : #include <stdlib.h>
      29                 : #include <fcntl.h>
      30                 : #include <time.h>
      31                 : 
      32                 : #include "tsrm_virtual_cwd.h"
      33                 : #include "tsrm_strtok_r.h"
      34                 : 
      35                 : #ifdef TSRM_WIN32
      36                 : #include <io.h>
      37                 : #include "tsrm_win32.h"
      38                 : #endif
      39                 : 
      40                 : #ifdef NETWARE
      41                 : #include <fsio.h>
      42                 : #endif
      43                 : 
      44                 : #ifndef HAVE_REALPATH
      45                 : #define realpath(x,y) strcpy(y,x)
      46                 : #endif
      47                 : 
      48                 : #define VIRTUAL_CWD_DEBUG 0
      49                 : 
      50                 : #include "TSRM.h"
      51                 : 
      52                 : /* Only need mutex for popen() in Windows and NetWare because it doesn't chdir() on UNIX */
      53                 : #if (defined(TSRM_WIN32) || defined(NETWARE)) && defined(ZTS)
      54                 : MUTEX_T cwd_mutex;
      55                 : #endif
      56                 : 
      57                 : #ifdef ZTS
      58                 : ts_rsrc_id cwd_globals_id;
      59                 : #else
      60                 : virtual_cwd_globals cwd_globals;
      61                 : #endif
      62                 : 
      63                 : cwd_state main_cwd_state; /* True global */
      64                 : 
      65                 : #ifndef TSRM_WIN32
      66                 : #include <unistd.h>
      67                 : #else
      68                 : #include <direct.h>
      69                 : #endif
      70                 : 
      71                 : #ifndef S_ISDIR
      72                 : #define S_ISDIR(mode) ((mode) & _S_IFDIR)
      73                 : #endif
      74                 : 
      75                 : #ifndef S_ISREG
      76                 : #define S_ISREG(mode) ((mode) & _S_IFREG)
      77                 : #endif
      78                 : 
      79                 : #ifdef TSRM_WIN32
      80                 : #include <tchar.h>
      81                 : #define tsrm_strtok_r(a,b,c) _tcstok((a),(b))
      82                 : #define TOKENIZER_STRING "/\\"
      83                 :         
      84                 : static int php_check_dots(const char *element, int n) 
      85                 : {
      86                 :         while (n-- > 0) if (element[n] != '.') break;
      87                 : 
      88                 :         return (n != -1);
      89                 : }
      90                 :         
      91                 : #define IS_DIRECTORY_UP(element, len) \
      92                 :         (len >= 2 && !php_check_dots(element, len))
      93                 : 
      94                 : #define IS_DIRECTORY_CURRENT(element, len) \
      95                 :         (len == 1 && element[0] == '.')
      96                 : 
      97                 : #elif defined(NETWARE)
      98                 : /* NetWare has strtok() (in LibC) and allows both slashes in paths, like Windows --
      99                 :    but rest of the stuff is like Unix */
     100                 : /* strtok() call in LibC is abending when used in a different address space -- hence using
     101                 :    PHP's version itself for now */
     102                 : /*#define tsrm_strtok_r(a,b,c) strtok((a),(b))*/
     103                 : #define TOKENIZER_STRING "/\\"
     104                 : 
     105                 : #else
     106                 : #define TOKENIZER_STRING "/"
     107                 : #endif
     108                 : 
     109                 : 
     110                 : /* default macros */
     111                 : 
     112                 : #ifndef IS_DIRECTORY_UP
     113                 : #define IS_DIRECTORY_UP(element, len) \
     114                 :         (len == 2 && element[0] == '.' && element[1] == '.')
     115                 : #endif
     116                 : 
     117                 : #ifndef IS_DIRECTORY_CURRENT
     118                 : #define IS_DIRECTORY_CURRENT(element, len) \
     119                 :         (len == 1 && element[0] == '.')
     120                 : #endif
     121                 : 
     122                 : /* define this to check semantics */
     123                 : #define IS_DIR_OK(s) (1)
     124                 :         
     125                 : #ifndef IS_DIR_OK
     126                 : #define IS_DIR_OK(state) (php_is_dir_ok(state) == 0)
     127                 : #endif
     128                 : 
     129                 : 
     130                 : #define CWD_STATE_COPY(d, s)                            \
     131                 :         (d)->cwd_length = (s)->cwd_length;                \
     132                 :         (d)->cwd = (char *) malloc((s)->cwd_length+1);    \
     133                 :         memcpy((d)->cwd, (s)->cwd, (s)->cwd_length+1);
     134                 : 
     135                 : #define CWD_STATE_FREE(s)                       \
     136                 :         free((s)->cwd);
     137                 :         
     138                 : #ifdef TSRM_WIN32
     139                 : CWD_API int php_sys_stat(const char *path, struct stat *buf) /* {{{ */
     140                 : {
     141                 :         WIN32_FILE_ATTRIBUTE_DATA data;
     142                 :         __int64 t;
     143                 : 
     144                 :         if (!GetFileAttributesEx(path, GetFileExInfoStandard, &data)) {
     145                 :                 return stat(path, buf);
     146                 :         }
     147                 : 
     148                 :         if (path[1] == ':') {
     149                 :                 if (path[0] >= 'A' && path[0] <= 'Z') {
     150                 :                         buf->st_dev = buf->st_rdev = path[0] - 'A';
     151                 :                 } else {
     152                 :                         buf->st_dev = buf->st_rdev = path[0] - 'a';
     153                 :                 }
     154                 :         } else {
     155                 :                 char  cur_path[MAXPATHLEN+1];
     156                 :                 DWORD len = sizeof(cur_path);
     157                 :                 char *tmp = cur_path;
     158                 : 
     159                 :                 while(1) {
     160                 :                         DWORD r = GetCurrentDirectory(len, tmp);
     161                 :                         if (r < len) {
     162                 :                                 if (tmp[1] == ':') {
     163                 :                                         if (path[0] >= 'A' && path[0] <= 'Z') {
     164                 :                                                 buf->st_dev = buf->st_rdev = path[0] - 'A';
     165                 :                                         } else {
     166                 :                                                 buf->st_dev = buf->st_rdev = path[0] - 'a';
     167                 :                                         }
     168                 :                                 } else {
     169                 :                                         buf->st_dev = buf->st_rdev = -1;
     170                 :                                 }
     171                 :                                 break;
     172                 :                         } else if (!r) {
     173                 :                                 buf->st_dev = buf->st_rdev = -1;
     174                 :                                 break;
     175                 :                         } else {
     176                 :                                 len = r+1;
     177                 :                                 tmp = (char*)malloc(len);
     178                 :                         }
     179                 :                 }
     180                 :                 if (tmp != cur_path) {
     181                 :                         free(tmp);
     182                 :                 }                       
     183                 :         }
     184                 :         buf->st_uid = buf->st_gid = buf->st_ino = 0;
     185                 :         buf->st_mode = (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? (S_IFDIR|S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6)) : S_IFREG;
     186                 :         buf->st_mode |= (data.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? (S_IREAD|(S_IREAD>>3)|(S_IREAD>>6)) : (S_IREAD|(S_IREAD>>3)|(S_IREAD>>6)|S_IWRITE|(S_IWRITE>>3)|(S_IWRITE>>6));
     187                 :         if ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
     188                 :                 int len = strlen(path);
     189                 : 
     190                 :                 if (path[len-4] == '.') {
     191                 :                         if (_memicmp(path+len-3, "exe", 3) == 0 ||
     192                 :                             _memicmp(path+len-3, "com", 3) == 0 ||
     193                 :                             _memicmp(path+len-3, "bat", 3) == 0 ||
     194                 :                             _memicmp(path+len-3, "cmd", 3) == 0) {
     195                 :                                 buf->st_mode  |= (S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6));
     196                 :                         }
     197                 :                 }
     198                 :         }                       
     199                 :     buf->st_nlink = 1;
     200                 :         t = data.nFileSizeHigh;
     201                 :         t = t << 32;
     202                 :         t |= data.nFileSizeLow;
     203                 :         buf->st_size = t;
     204                 :         t = data.ftLastAccessTime.dwHighDateTime;
     205                 :         t = t << 32;
     206                 :         t |= data.ftLastAccessTime.dwLowDateTime;
     207                 :         buf->st_atime = (unsigned long)((t / 10000000) - 11644473600);
     208                 :         t = data.ftCreationTime.dwHighDateTime;
     209                 :         t = t << 32;
     210                 :         t |= data.ftCreationTime.dwLowDateTime;
     211                 :         buf->st_ctime = (unsigned long)((t / 10000000) - 11644473600);
     212                 :         t = data.ftLastWriteTime.dwHighDateTime;
     213                 :         t = t << 32;
     214                 :         t |= data.ftLastWriteTime.dwLowDateTime;
     215                 :         buf->st_mtime = (unsigned long)((t / 10000000) - 11644473600);
     216                 :         return 0;
     217                 : }
     218                 : /* }}} */
     219                 : #endif
     220                 : 
     221                 : static int php_is_dir_ok(const cwd_state *state)  /* {{{ */
     222               0 : {
     223                 :         struct stat buf;
     224                 : 
     225               0 :         if (php_sys_stat(state->cwd, &buf) == 0 && S_ISDIR(buf.st_mode))
     226               0 :                 return (0);
     227                 : 
     228               0 :         return (1);
     229                 : }
     230                 : /* }}} */
     231                 : 
     232                 : static int php_is_file_ok(const cwd_state *state)  /* {{{ */
     233               0 : {
     234                 :         struct stat buf;
     235                 : 
     236               0 :         if (php_sys_stat(state->cwd, &buf) == 0 && S_ISREG(buf.st_mode))
     237               0 :                 return (0);
     238                 : 
     239               0 :         return (1);
     240                 : }
     241                 : /* }}} */
     242                 : 
     243                 : static void cwd_globals_ctor(virtual_cwd_globals *cwd_globals TSRMLS_DC) /* {{{ */
     244           13565 : {
     245           13565 :         CWD_STATE_COPY(&cwd_globals->cwd, &main_cwd_state);
     246           13565 :         cwd_globals->realpath_cache_size = 0;
     247           13565 :         cwd_globals->realpath_cache_size_limit = REALPATH_CACHE_SIZE;
     248           13565 :         cwd_globals->realpath_cache_ttl = REALPATH_CACHE_TTL;
     249           13565 :         memset(cwd_globals->realpath_cache, 0, sizeof(cwd_globals->realpath_cache));
     250           13565 : }
     251                 : /* }}} */
     252                 : 
     253                 : static void cwd_globals_dtor(virtual_cwd_globals *cwd_globals TSRMLS_DC) /* {{{ */
     254           13597 : {
     255           13597 :         CWD_STATE_FREE(&cwd_globals->cwd);
     256           13597 :         realpath_cache_clean(TSRMLS_C);
     257           13597 : }
     258                 : /* }}} */
     259                 : 
     260                 : static char *tsrm_strndup(const char *s, size_t length) /* {{{ */
     261           27186 : {
     262                 :     char *p;
     263                 : 
     264           27186 :     p = (char *) malloc(length+1);
     265           27186 :     if (!p) {
     266               0 :         return (char *)NULL;
     267                 :     }
     268           27186 :     if (length) {
     269           27186 :         memcpy(p,s,length);
     270                 :     }
     271           27186 :     p[length]=0;
     272           27186 :     return p;
     273                 : }
     274                 : /* }}} */
     275                 : 
     276                 : CWD_API void virtual_cwd_startup(void) /* {{{ */
     277           13565 : {
     278                 :         char cwd[MAXPATHLEN];
     279                 :         char *result;
     280                 : 
     281                 : #ifdef NETWARE
     282                 :         result = getcwdpath(cwd, NULL, 1);
     283                 :         if(result)
     284                 :         {
     285                 :                 char *c=cwd;
     286                 :                 while(c = strchr(c, '\\'))
     287                 :                 {
     288                 :                         *c='/';
     289                 :                         ++c;
     290                 :                 }
     291                 :         }
     292                 : #else
     293           13565 :         result = getcwd(cwd, sizeof(cwd));      
     294                 : #endif
     295           13565 :         if (!result) {
     296               0 :                 cwd[0] = '\0';
     297                 :         }
     298           13565 :         main_cwd_state.cwd = strdup(cwd);
     299           13565 :         main_cwd_state.cwd_length = strlen(cwd);
     300                 : 
     301                 : #ifdef ZTS
     302                 :         ts_allocate_id(&cwd_globals_id, sizeof(virtual_cwd_globals), (ts_allocate_ctor) cwd_globals_ctor, (ts_allocate_dtor) cwd_globals_dtor);
     303                 : #else
     304           13565 :         cwd_globals_ctor(&cwd_globals TSRMLS_CC);
     305                 : #endif
     306                 : 
     307                 : #if (defined(TSRM_WIN32) || defined(NETWARE)) && defined(ZTS)
     308                 :         cwd_mutex = tsrm_mutex_alloc();
     309                 : #endif
     310           13565 : }
     311                 : /* }}} */
     312                 : 
     313                 : CWD_API void virtual_cwd_shutdown(void) /* {{{ */
     314           13597 : {
     315                 : #ifndef ZTS
     316           13597 :         cwd_globals_dtor(&cwd_globals TSRMLS_CC);
     317                 : #endif
     318                 : #if (defined(TSRM_WIN32) || defined(NETWARE)) && defined(ZTS)
     319                 :         tsrm_mutex_free(cwd_mutex);
     320                 : #endif
     321                 : 
     322           13597 :         free(main_cwd_state.cwd); /* Don't use CWD_STATE_FREE because the non global states will probably use emalloc()/efree() */
     323           13597 : }
     324                 : /* }}} */
     325                 : 
     326                 : CWD_API char *virtual_getcwd_ex(size_t *length TSRMLS_DC) /* {{{ */
     327               0 : {
     328                 :         cwd_state *state;
     329                 : 
     330               0 :         state = &CWDG(cwd);
     331                 : 
     332               0 :         if (state->cwd_length == 0) {
     333                 :                 char *retval;
     334                 : 
     335               0 :                 *length = 1;
     336               0 :                 retval = (char *) malloc(2);
     337               0 :                 retval[0] = DEFAULT_SLASH;
     338               0 :                 retval[1] = '\0';       
     339               0 :                 return retval;
     340                 :         }
     341                 : 
     342                 : #ifdef TSRM_WIN32
     343                 :         /* If we have something like C: */
     344                 :         if (state->cwd_length == 2 && state->cwd[state->cwd_length-1] == ':') {
     345                 :                 char *retval;
     346                 : 
     347                 :                 *length = state->cwd_length+1;
     348                 :                 retval = (char *) malloc(*length+1);
     349                 :                 memcpy(retval, state->cwd, *length);
     350                 :                 retval[*length-1] = DEFAULT_SLASH;
     351                 :                 retval[*length] = '\0';
     352                 :                 return retval;
     353                 :         }
     354                 : #endif
     355               0 :         *length = state->cwd_length;
     356               0 :         return strdup(state->cwd);
     357                 : }
     358                 : /* }}} */
     359                 : 
     360                 : /* Same semantics as UNIX getcwd() */
     361                 : CWD_API char *virtual_getcwd(char *buf, size_t size TSRMLS_DC) /* {{{ */
     362               0 : {
     363                 :         size_t length;
     364                 :         char *cwd;
     365                 : 
     366               0 :         cwd = virtual_getcwd_ex(&length TSRMLS_CC);
     367                 : 
     368               0 :         if (buf == NULL) {
     369               0 :                 return cwd;
     370                 :         }
     371               0 :         if (length > size-1) {
     372               0 :                 free(cwd);
     373               0 :                 errno = ERANGE; /* Is this OK? */
     374               0 :                 return NULL;
     375                 :         }
     376               0 :         memcpy(buf, cwd, length+1);
     377               0 :         free(cwd);
     378               0 :         return buf;
     379                 : }
     380                 : /* }}} */
     381                 : 
     382                 : static inline unsigned long realpath_cache_key(const char *path, int path_len) /* {{{ */
     383          123276 : {
     384                 :         register unsigned long h;
     385          123276 :         const char *e = path + path_len;
     386                 : 
     387         7353952 :         for (h = 2166136261U; path < e;) {
     388         7107400 :                 h *= 16777619;
     389         7107400 :                 h ^= *path++;
     390                 :         }
     391                 : 
     392          123276 :         return h;
     393                 : }
     394                 : /* }}} */
     395                 : 
     396                 : CWD_API void realpath_cache_clean(TSRMLS_D) /* {{{ */
     397           40437 : {
     398                 :         int i;
     399                 : 
     400        41447925 :         for (i = 0; i < sizeof(CWDG(realpath_cache))/sizeof(CWDG(realpath_cache)[0]); i++) {
     401        41407488 :                 realpath_cache_bucket *p = CWDG(realpath_cache)[i];
     402        82856395 :                 while (p != NULL) {
     403           41419 :                         realpath_cache_bucket *r = p;
     404           41419 :                         p = p->next;
     405           41419 :                         free(r);
     406                 :                 }
     407        41407488 :                 CWDG(realpath_cache)[i] = NULL;
     408                 :         }
     409           40437 :         CWDG(realpath_cache_size) = 0;
     410           40437 : }
     411                 : /* }}} */
     412                 : 
     413                 : CWD_API void realpath_cache_del(const char *path, int path_len TSRMLS_DC) /* {{{ */
     414               0 : {
     415               0 :         unsigned long key = realpath_cache_key(path, path_len);
     416               0 :         unsigned long n = key % (sizeof(CWDG(realpath_cache)) / sizeof(CWDG(realpath_cache)[0]));
     417               0 :         realpath_cache_bucket **bucket = &CWDG(realpath_cache)[n];
     418                 : 
     419               0 :         while (*bucket != NULL) {
     420               0 :                 if (key == (*bucket)->key && path_len == (*bucket)->path_len &&
     421                 :                            memcmp(path, (*bucket)->path, path_len) == 0) {
     422               0 :                         realpath_cache_bucket *r = *bucket;
     423               0 :                         *bucket = (*bucket)->next;
     424               0 :                         CWDG(realpath_cache_size) -= sizeof(realpath_cache_bucket) + r->path_len + 1 + r->realpath_len + 1;
     425               0 :                         free(r);
     426               0 :                         return;
     427                 :                 } else {
     428               0 :                         bucket = &(*bucket)->next;
     429                 :                 }
     430                 :         }
     431                 : }
     432                 : /* }}} */
     433                 : 
     434                 : static inline void realpath_cache_add(const char *path, int path_len, const char *realpath, int realpath_len, time_t t TSRMLS_DC) /* {{{ */
     435           50169 : {
     436           50169 :         long size = sizeof(realpath_cache_bucket) + path_len + 1 + realpath_len + 1;
     437           50169 :         if (CWDG(realpath_cache_size) + size <= CWDG(realpath_cache_size_limit)) {
     438           41360 :                 realpath_cache_bucket *bucket = malloc(size);
     439                 :                 unsigned long n;
     440                 :         
     441           41360 :                 bucket->key = realpath_cache_key(path, path_len);
     442           41360 :                 bucket->path = (char*)bucket + sizeof(realpath_cache_bucket);
     443           41360 :                 memcpy(bucket->path, path, path_len+1);
     444           41360 :                 bucket->path_len = path_len;
     445           41360 :                 bucket->realpath = bucket->path + (path_len + 1);
     446           41360 :                 memcpy(bucket->realpath, realpath, realpath_len+1);
     447           41360 :                 bucket->realpath_len = realpath_len;
     448           41360 :                 bucket->expires = t + CWDG(realpath_cache_ttl);
     449           41360 :                 n = bucket->key % (sizeof(CWDG(realpath_cache)) / sizeof(CWDG(realpath_cache)[0]));
     450           41360 :                 bucket->next = CWDG(realpath_cache)[n];
     451           41360 :                 CWDG(realpath_cache)[n] = bucket;
     452           41360 :                 CWDG(realpath_cache_size) += size;
     453                 :         }
     454           50169 : }
     455                 : /* }}} */
     456                 : 
     457                 : static inline realpath_cache_bucket* realpath_cache_find(const char *path, int path_len, time_t t TSRMLS_DC) /* {{{ */
     458           81916 : {
     459           81916 :         unsigned long key = realpath_cache_key(path, path_len);
     460           81916 :         unsigned long n = key % (sizeof(CWDG(realpath_cache)) / sizeof(CWDG(realpath_cache)[0]));
     461           81916 :         realpath_cache_bucket **bucket = &CWDG(realpath_cache)[n];
     462                 : 
     463          165046 :         while (*bucket != NULL) {
     464            6309 :                 if (CWDG(realpath_cache_ttl) && (*bucket)->expires < t) {
     465               0 :                         realpath_cache_bucket *r = *bucket;
     466               0 :                         *bucket = (*bucket)->next;
     467               0 :                         CWDG(realpath_cache_size) -= sizeof(realpath_cache_bucket) + r->path_len + 1 + r->realpath_len + 1;
     468               0 :                         free(r);
     469            6309 :                 } else if (key == (*bucket)->key && path_len == (*bucket)->path_len &&
     470                 :                            memcmp(path, (*bucket)->path, path_len) == 0) {
     471            5095 :                         return *bucket;
     472                 :                 } else {
     473            1214 :                         bucket = &(*bucket)->next;
     474                 :                 }
     475                 :         }
     476           76821 :         return NULL;
     477                 : }
     478                 : /* }}} */
     479                 : 
     480                 : /* Resolve path relatively to state and put the real path into state */
     481                 : /* returns 0 for ok, 1 for error */
     482                 : CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func verify_path, int use_realpath) /* {{{ */
     483          113039 : {
     484          113039 :         int path_length = strlen(path);
     485                 :         cwd_state old_state;
     486                 :         char orig_path[MAXPATHLEN];
     487                 :         realpath_cache_bucket *bucket;
     488          113039 :         time_t t = 0;
     489                 :         int ret;
     490                 :         int use_cache;
     491          113039 :         int use_relative_path = 0;
     492                 : #ifdef TSRM_WIN32
     493                 :         int is_unc;
     494                 :         int exists;
     495                 : #endif
     496                 :         TSRMLS_FETCH();
     497                 : 
     498          113039 :         use_cache = ((use_realpath != CWD_EXPAND) && CWDG(realpath_cache_size_limit));
     499                 : 
     500          113039 :         if (path_length == 0) 
     501               0 :                 return (1);
     502          113039 :         if (path_length >= MAXPATHLEN)
     503               3 :                 return (1);
     504                 : 
     505                 : #if VIRTUAL_CWD_DEBUG
     506                 :                 fprintf(stderr,"cwd = %s path = %s\n", state->cwd, path);
     507                 : #endif
     508                 : 
     509                 :         /* cwd_length can be 0 when getcwd() fails.
     510                 :          * This can happen under solaris when a dir does not have read permissions
     511                 :          * but *does* have execute permissions */
     512          113036 :         if (!IS_ABSOLUTE_PATH(path, path_length)) {
     513            3997 :                 if (state->cwd_length == 0) {
     514               0 :                         use_cache = 0;
     515               0 :                         use_relative_path = 1;
     516                 :                 } else {
     517                 :                         int orig_path_len;
     518            3997 :                         int state_cwd_length = state->cwd_length;
     519                 : 
     520                 : #ifdef TSRM_WIN32
     521                 :                         if (IS_SLASH(path[0])) {
     522                 :                                 state_cwd_length = 2;
     523                 :                         }
     524                 : #endif
     525            3997 :                         orig_path_len = path_length + state_cwd_length + 1;
     526            3997 :                         if (orig_path_len >= MAXPATHLEN) {
     527               0 :                                 return 1;
     528                 :                         }
     529            3997 :                         memcpy(orig_path, state->cwd, state_cwd_length);
     530            3997 :                         orig_path[state_cwd_length] = DEFAULT_SLASH;
     531            3997 :                         memcpy(orig_path + state_cwd_length + 1, path, path_length + 1);
     532            3997 :                         path = orig_path;
     533            3997 :                         path_length = orig_path_len; 
     534                 :                 }
     535                 :         }
     536                 : 
     537          113036 :         if (use_cache) {
     538           81916 :                 t = CWDG(realpath_cache_ttl)?time(0):0;
     539           81916 :                 if ((bucket = realpath_cache_find(path, path_length, t TSRMLS_CC)) != NULL) {           
     540            5095 :                         int len = bucket->realpath_len;
     541                 : 
     542            5095 :                         CWD_STATE_COPY(&old_state, state);
     543            5095 :                         state->cwd = (char *) realloc(state->cwd, len+1);
     544            5095 :                         memcpy(state->cwd, bucket->realpath, len+1);
     545            5095 :                         state->cwd_length = len;
     546            5095 :                         if (verify_path && verify_path(state)) {
     547               0 :                                 CWD_STATE_FREE(state);
     548               0 :                                 *state = old_state;
     549               0 :                                 return 1;
     550                 :                         } else {
     551            5095 :                                 CWD_STATE_FREE(&old_state);
     552            5095 :                                 return 0;
     553                 :                         }
     554                 :                 }
     555                 :         }
     556                 : 
     557          107941 :         if (use_realpath != CWD_EXPAND) {
     558                 : #if !defined(TSRM_WIN32) && !defined(NETWARE)
     559                 :                 char resolved_path[MAXPATHLEN];
     560                 : 
     561          107941 :                 if (!realpath(path, resolved_path)) {  /* Note: Not threadsafe on older *BSD's */
     562           27654 :                         if (use_realpath == CWD_REALPATH) {
     563             468 :                                 return 1;
     564                 :                         }
     565           27186 :                         goto no_realpath;
     566                 :                 }
     567           80287 :                 use_realpath = CWD_REALPATH;
     568           80287 :                 CWD_STATE_COPY(&old_state, state);
     569                 : 
     570           80287 :                 state->cwd_length = strlen(resolved_path);
     571           80287 :                 state->cwd = (char *) realloc(state->cwd, state->cwd_length+1);
     572           80287 :                 memcpy(state->cwd, resolved_path, state->cwd_length+1);
     573                 : #else
     574                 :                 goto no_realpath;
     575                 : #endif
     576                 :         } else {
     577                 :                 char *ptr, *path_copy, *free_path;
     578                 :                 char *tok;
     579                 :                 int ptr_length;
     580           27186 : no_realpath:
     581                 : 
     582                 : #ifdef TSRM_WIN32
     583                 :                 if (memchr(path, '*', path_length) ||
     584                 :                     memchr(path, '?', path_length)) {
     585                 :                         return 1;
     586                 :                 }
     587                 : #endif
     588                 : 
     589           27186 :                 free_path = path_copy = tsrm_strndup(path, path_length);
     590           27186 :                 CWD_STATE_COPY(&old_state, state);
     591                 : 
     592                 : #ifdef TSRM_WIN32
     593                 :                 exists = (use_realpath != CWD_EXPAND);
     594                 :                 ret = 0;
     595                 :                 is_unc = 0;
     596                 :                 if (path_length >= 2 && path[1] == ':') {                    
     597                 :                         state->cwd = (char *) realloc(state->cwd, 2 + 1);
     598                 :                         state->cwd[0] = toupper(path[0]);
     599                 :                         state->cwd[1] = ':';
     600                 :                         state->cwd[2] = '\0';
     601                 :                         state->cwd_length = 2;
     602                 :                         path_copy += 2;
     603                 :                 } else if (IS_UNC_PATH(path, path_length)) {
     604                 :                         state->cwd = (char *) realloc(state->cwd, 1 + 1);
     605                 :                         state->cwd[0] = DEFAULT_SLASH;
     606                 :                         state->cwd[1] = '\0';
     607                 :                         state->cwd_length = 1;
     608                 :                         path_copy += 2;
     609                 :                         is_unc = 2;
     610                 :                 } else {
     611                 : #endif
     612           27186 :                         state->cwd = (char *) realloc(state->cwd, 1);
     613           27186 :                         state->cwd[0] = '\0';
     614           27186 :                         state->cwd_length = 0;
     615                 : #ifdef TSRM_WIN32
     616                 :                 }
     617                 : #endif
     618                 :                 
     619           27186 :                 tok = NULL;
     620           27186 :                 ptr = tsrm_strtok_r(path_copy, TOKENIZER_STRING, &tok);
     621          244695 :                 while (ptr) {
     622          190323 :                         ptr_length = strlen(ptr);
     623                 : 
     624          190454 :                         if (IS_DIRECTORY_UP(ptr, ptr_length)) {
     625                 :                                 char save;
     626                 : 
     627             131 :                                 if (use_relative_path) {
     628               0 :                                         CWD_STATE_FREE(state);
     629               0 :                                         *state = old_state;
     630               0 :                                         return 1;
     631                 :                                 }
     632                 : 
     633             131 :                                 save = DEFAULT_SLASH;
     634                 : 
     635                 : #define PREVIOUS state->cwd[state->cwd_length - 1]
     636                 : 
     637            1778 :                                 while (IS_ABSOLUTE_PATH(state->cwd, state->cwd_length) &&
     638                 :                                                 !IS_SLASH(PREVIOUS)) {
     639            1516 :                                         save = PREVIOUS;
     640            1516 :                                         PREVIOUS = '\0';
     641            1516 :                                         state->cwd_length--;
     642                 :                                 }
     643                 : 
     644             131 :                                 if (!IS_ABSOLUTE_PATH(state->cwd, state->cwd_length)) {
     645               0 :                                         state->cwd[state->cwd_length++] = save;
     646               0 :                                         state->cwd[state->cwd_length] = '\0';
     647                 :                                 } else {
     648             131 :                                         PREVIOUS = '\0';
     649             131 :                                         state->cwd_length--;
     650                 :                                 }
     651          190192 :                         } else if (!IS_DIRECTORY_CURRENT(ptr, ptr_length)) {
     652          187506 :                                 if (use_relative_path) {
     653               0 :                                         state->cwd = (char *) realloc(state->cwd, state->cwd_length+ptr_length+1);
     654               0 :                                         use_relative_path = 0;
     655                 :                                 } else {
     656          187506 :                                         state->cwd = (char *) realloc(state->cwd, state->cwd_length+ptr_length+1+1);
     657                 : #ifdef TSRM_WIN32
     658                 :                                         /* Windows 9x will consider C:\\Foo as a network path. Avoid it. */
     659                 :                                         if (state->cwd_length < 2 ||
     660                 :                                             (state->cwd[state->cwd_length-1]!='\\' && state->cwd[state->cwd_length-1]!='/') ||
     661                 :                                                         IsDBCSLeadByte(state->cwd[state->cwd_length-2])) {
     662                 :                                                 state->cwd[state->cwd_length++] = DEFAULT_SLASH;
     663                 :                                         }
     664                 : #elif defined(NETWARE)
     665                 :                                         /* 
     666                 :                                         Below code keeps appending to state->cwd a File system seperator
     667                 :                                         cases where this appending should not happen is given below,
     668                 :                                         a) sys: should just be left as it is
     669                 :                                         b) sys:system should just be left as it is,
     670                 :                                                 Colon is allowed only in the first token as volume names alone can have the : in their names.
     671                 :                                                 Files and Directories cannot have : in their names
     672                 :                                                 So the check goes like this,
     673                 :                                                 For second token and above simply append the DEFAULT_SLASH to the state->cwd.
     674                 :                                                 For first token check for the existence of : 
     675                 :                                                 if it exists don't append the DEFAULT_SLASH to the state->cwd.
     676                 :                                         */
     677                 :                                         if(((state->cwd_length == 0) && (strchr(ptr, ':') == NULL)) || (state->cwd_length > 0)) {
     678                 :                                                 state->cwd[state->cwd_length++] = DEFAULT_SLASH;
     679                 :                                         }
     680                 : #else
     681          187506 :                                         state->cwd[state->cwd_length++] = DEFAULT_SLASH;
     682                 : #endif
     683                 :                                 }
     684          187506 :                                 memcpy(&state->cwd[state->cwd_length], ptr, ptr_length+1);
     685                 : 
     686                 : #ifdef TSRM_WIN32
     687                 :                                 if (use_realpath != CWD_EXPAND) {
     688                 :                                         WIN32_FIND_DATA data;
     689                 :                                         HANDLE hFind;
     690                 : 
     691                 :                                         if ((hFind = FindFirstFile(state->cwd, &data)) != INVALID_HANDLE_VALUE) {
     692                 :                                                 int length = strlen(data.cFileName);
     693                 : 
     694                 :                                                 if (length != ptr_length) {
     695                 :                                                         state->cwd = (char *) realloc(state->cwd, state->cwd_length+length+1);
     696                 :                                                 }
     697                 :                                                 memcpy(&state->cwd[state->cwd_length], data.cFileName, length+1);
     698                 :                                                 ptr_length = length;
     699                 :                                                 FindClose(hFind);
     700                 :                                                 ret = 0;
     701                 :                                         } else {
     702                 :                                                 if (is_unc) {
     703                 :                                                         /* skip share name */
     704                 :                                                         is_unc--;
     705                 :                                                         ret = 0;
     706                 :                                                 } else {
     707                 :                                                         exists = 0;
     708                 :                                                         if (use_realpath == CWD_REALPATH) {
     709                 :                                                                 ret = 1;
     710                 :                                                         }
     711                 :                                                 }
     712                 :                                         }
     713                 :                                 }
     714                 : #endif
     715                 : 
     716          187506 :                                 state->cwd_length += ptr_length;
     717                 :                         }
     718          190323 :                         ptr = tsrm_strtok_r(NULL, TOKENIZER_STRING, &tok);
     719                 :                 }
     720           27186 :                 free(free_path);
     721                 : 
     722           27186 :                 if (use_realpath == CWD_REALPATH) {
     723               0 :                         if (ret) {
     724               0 :                                 CWD_STATE_FREE(state);
     725               0 :                                 *state = old_state;                                     
     726               0 :                                 return 1;
     727                 :                         }
     728                 :                 } else {
     729                 : #if defined(TSRM_WIN32) || defined(NETWARE)
     730                 :                         if (path[path_length-1] == '\\' || path[path_length-1] == '/') {
     731                 : #else 
     732           27186 :                         if (path[path_length-1] == '/') {
     733                 : #endif
     734               4 :                                 state->cwd = (char*)realloc(state->cwd, state->cwd_length + 2);
     735               4 :                                 state->cwd[state->cwd_length++] = DEFAULT_SLASH;
     736               4 :                                 state->cwd[state->cwd_length] = 0;
     737                 :                         }
     738                 :                 }
     739                 : 
     740           27186 :                 if (state->cwd_length == COPY_WHEN_ABSOLUTE(state->cwd)) {
     741               0 :                         state->cwd = (char *) realloc(state->cwd, state->cwd_length+1+1);
     742               0 :                         state->cwd[state->cwd_length] = DEFAULT_SLASH;
     743               0 :                         state->cwd[state->cwd_length+1] = '\0';
     744               0 :                         state->cwd_length++;
     745                 :                 }
     746                 :         }
     747                 : 
     748                 :         /* Store existent file in realpath cache. */
     749                 : #ifdef TSRM_WIN32
     750                 :         if (use_cache && !is_unc && exists) {
     751                 : #else
     752          107473 :         if (use_cache && (use_realpath == CWD_REALPATH)) {
     753                 : #endif
     754           50169 :                 realpath_cache_add(path, path_length, state->cwd, state->cwd_length, t TSRMLS_CC);
     755                 :         }
     756                 : 
     757          107473 :         if (verify_path && verify_path(state)) {
     758               0 :                 CWD_STATE_FREE(state);
     759               0 :                 *state = old_state;
     760               0 :                 ret = 1;
     761                 :         } else {
     762          107473 :                 CWD_STATE_FREE(&old_state);
     763          107473 :                 ret = 0;
     764                 :         }
     765                 :         
     766                 : #if VIRTUAL_CWD_DEBUG
     767                 :         fprintf (stderr, "virtual_file_ex() = %s\n",state->cwd);
     768                 : #endif
     769          107473 :         return (ret);
     770                 : }
     771                 : /* }}} */
     772                 : 
     773                 : CWD_API int virtual_chdir(const char *path TSRMLS_DC) /* {{{ */
     774               0 : {
     775               0 :         return virtual_file_ex(&CWDG(cwd), path, php_is_dir_ok, CWD_REALPATH)?-1:0;
     776                 : }
     777                 : /* }}} */
     778                 : 
     779                 : CWD_API int virtual_chdir_file(const char *path, int (*p_chdir)(const char *path TSRMLS_DC) TSRMLS_DC) /* {{{ */
     780              68 : {
     781              68 :         int length = strlen(path);
     782                 :         char *temp;
     783                 :         int retval;
     784                 : 
     785              68 :         if (length == 0) {
     786               0 :                 return 1; /* Can't cd to empty string */
     787                 :         }       
     788             823 :         while(--length >= 0 && !IS_SLASH(path[length])) {
     789                 :         }
     790                 : 
     791              68 :         if (length == -1) {
     792                 :                 /* No directory only file name */
     793               0 :                 errno = ENOENT;
     794               0 :                 return -1;
     795                 :         }
     796                 : 
     797              68 :         if (length == COPY_WHEN_ABSOLUTE(path) && IS_ABSOLUTE_PATH(path, length+1)) { /* Also use trailing slash if this is absolute */
     798               0 :                 length++;
     799                 :         }
     800              68 :         temp = (char *) tsrm_do_alloca(length+1);
     801              68 :         memcpy(temp, path, length);
     802              68 :         temp[length] = 0;
     803                 : #if VIRTUAL_CWD_DEBUG
     804                 :         fprintf (stderr, "Changing directory to %s\n", temp);
     805                 : #endif
     806              68 :         retval = p_chdir(temp TSRMLS_CC);
     807                 :         tsrm_free_alloca(temp);
     808              68 :         return retval;
     809                 : }
     810                 : /* }}} */
     811                 : 
     812                 : CWD_API char *virtual_realpath(const char *path, char *real_path TSRMLS_DC) /* {{{ */
     813               0 : {
     814                 :         cwd_state new_state;
     815                 :         char *retval;
     816                 :         char cwd[MAXPATHLEN];
     817                 : 
     818                 :         /* realpath("") returns CWD */
     819               0 :         if (!*path) {
     820               0 :                 new_state.cwd = (char*)malloc(1);
     821               0 :                 new_state.cwd[0] = '\0';
     822               0 :                 new_state.cwd_length = 0;               
     823               0 :             if (VCWD_GETCWD(cwd, MAXPATHLEN)) {
     824               0 :                     path = cwd;
     825                 :                 }
     826               0 :         } else if (!IS_ABSOLUTE_PATH(path, strlen(path))) {
     827               0 :                 CWD_STATE_COPY(&new_state, &CWDG(cwd));
     828                 :         } else {
     829               0 :                 new_state.cwd = (char*)malloc(1);
     830               0 :                 new_state.cwd[0] = '\0';
     831               0 :                 new_state.cwd_length = 0;               
     832                 :         }
     833                 :         
     834               0 :         if (virtual_file_ex(&new_state, path, NULL, CWD_REALPATH)==0) {
     835               0 :                 int len = new_state.cwd_length>MAXPATHLEN-1?MAXPATHLEN-1:new_state.cwd_length;
     836                 : 
     837               0 :                 memcpy(real_path, new_state.cwd, len);
     838               0 :                 real_path[len] = '\0';
     839               0 :                 retval = real_path;
     840                 :         } else {
     841               0 :                 retval = NULL;
     842                 :         }
     843                 : 
     844               0 :         CWD_STATE_FREE(&new_state);
     845                 : 
     846               0 :         return retval;
     847                 : }
     848                 : /* }}} */
     849                 : 
     850                 : CWD_API int virtual_filepath_ex(const char *path, char **filepath, verify_path_func verify_path TSRMLS_DC) /* {{{ */
     851               0 : {
     852                 :         cwd_state new_state;
     853                 :         int retval;
     854                 : 
     855               0 :         CWD_STATE_COPY(&new_state, &CWDG(cwd));
     856               0 :         retval = virtual_file_ex(&new_state, path, verify_path, CWD_FILEPATH);
     857                 : 
     858               0 :         *filepath = new_state.cwd;
     859                 : 
     860               0 :         return retval;
     861                 : 
     862                 : }
     863                 : /* }}} */
     864                 : 
     865                 : CWD_API int virtual_filepath(const char *path, char **filepath TSRMLS_DC) /* {{{ */
     866               0 : {
     867               0 :         return virtual_filepath_ex(path, filepath, php_is_file_ok TSRMLS_CC);
     868                 : }
     869                 : /* }}} */
     870                 : 
     871                 : CWD_API FILE *virtual_fopen(const char *path, const char *mode TSRMLS_DC) /* {{{ */
     872               0 : {
     873                 :         cwd_state new_state;
     874                 :         FILE *f;
     875                 : 
     876               0 :         if (path[0] == '\0') { /* Fail to open empty path */
     877               0 :                 return NULL;
     878                 :         }
     879                 : 
     880               0 :         CWD_STATE_COPY(&new_state, &CWDG(cwd));
     881               0 :         if (virtual_file_ex(&new_state, path, NULL, CWD_FILEPATH)) {
     882               0 :                 CWD_STATE_FREE(&new_state);
     883               0 :                 return NULL;
     884                 :         }
     885                 : 
     886               0 :         f = fopen(new_state.cwd, mode);
     887                 : 
     888               0 :         CWD_STATE_FREE(&new_state);
     889               0 :         return f;
     890                 : }
     891                 : /* }}} */
     892                 : 
     893                 : CWD_API int virtual_access(const char *pathname, int mode TSRMLS_DC) /* {{{ */
     894               0 : {
     895                 :         cwd_state new_state;
     896                 :         int ret;
     897                 :         
     898               0 :         CWD_STATE_COPY(&new_state, &CWDG(cwd));
     899               0 :         if (virtual_file_ex(&new_state, pathname, NULL, CWD_REALPATH)) {
     900               0 :                 CWD_STATE_FREE(&new_state);
     901               0 :                 return -1;
     902                 :         }
     903                 : 
     904                 : #if defined(TSRM_WIN32)
     905                 :         ret = tsrm_win32_access(new_state.cwd, mode);
     906                 : #else
     907               0 :         ret = access(new_state.cwd, mode);
     908                 : #endif
     909                 :         
     910               0 :         CWD_STATE_FREE(&new_state);
     911                 :         
     912               0 :         return ret;
     913                 : }
     914                 : /* }}} */
     915                 : 
     916                 : #if HAVE_UTIME
     917                 : CWD_API int virtual_utime(const char *filename, struct utimbuf *buf TSRMLS_DC) /* {{{ */
     918               0 : {
     919                 :         cwd_state new_state;
     920                 :         int ret;
     921                 : 
     922               0 :         CWD_STATE_COPY(&new_state, &CWDG(cwd));
     923               0 :         if (virtual_file_ex(&new_state, filename, NULL, CWD_REALPATH)) {
     924               0 :                 CWD_STATE_FREE(&new_state);
     925               0 :                 return -1;
     926                 :         }
     927                 : 
     928               0 :         ret = utime(new_state.cwd, buf);
     929                 : 
     930               0 :         CWD_STATE_FREE(&new_state);
     931               0 :         return ret;
     932                 : }
     933                 : /* }}} */
     934                 : #endif
     935                 : 
     936                 : CWD_API int virtual_chmod(const char *filename, mode_t mode TSRMLS_DC) /* {{{ */
     937               0 : {
     938                 :         cwd_state new_state;
     939                 :         int ret;
     940                 : 
     941               0 :         CWD_STATE_COPY(&new_state, &CWDG(cwd));
     942               0 :         if (virtual_file_ex(&new_state, filename, NULL, CWD_REALPATH)) {
     943               0 :                 CWD_STATE_FREE(&new_state);
     944               0 :                 return -1;
     945                 :         }
     946                 : 
     947               0 :         ret = chmod(new_state.cwd, mode);
     948                 : 
     949               0 :         CWD_STATE_FREE(&new_state);
     950               0 :         return ret;
     951                 : }
     952                 : /* }}} */
     953                 : 
     954                 : #if !defined(TSRM_WIN32) && !defined(NETWARE)
     955                 : CWD_API int virtual_chown(const char *filename, uid_t owner, gid_t group, int link TSRMLS_DC) /* {{{ */
     956               0 : {
     957                 :         cwd_state new_state;
     958                 :         int ret;
     959                 : 
     960               0 :         CWD_STATE_COPY(&new_state, &CWDG(cwd));
     961               0 :         if (virtual_file_ex(&new_state, filename, NULL, CWD_REALPATH)) {
     962               0 :                 CWD_STATE_FREE(&new_state);
     963               0 :                 return -1;
     964                 :         }
     965                 : 
     966               0 :         if (link) {
     967                 : #if HAVE_LCHOWN
     968               0 :                 ret = lchown(new_state.cwd, owner, group);
     969                 : #else
     970                 :                 ret = -1;
     971                 : #endif
     972                 :         } else {
     973               0 :                 ret = chown(new_state.cwd, owner, group);
     974                 :         }
     975                 : 
     976               0 :         CWD_STATE_FREE(&new_state);
     977               0 :         return ret;
     978                 : }
     979                 : /* }}} */
     980                 : #endif
     981                 : 
     982                 : CWD_API int virtual_open(const char *path TSRMLS_DC, int flags, ...) /* {{{ */
     983               0 : {
     984                 :         cwd_state new_state;
     985                 :         int f;
     986                 : 
     987               0 :         CWD_STATE_COPY(&new_state, &CWDG(cwd));
     988               0 :         if (virtual_file_ex(&new_state, path, NULL, CWD_FILEPATH)) {
     989               0 :                 CWD_STATE_FREE(&new_state);
     990               0 :                 return -1;
     991                 :         }
     992                 : 
     993               0 :         if (flags & O_CREAT) {
     994                 :                 mode_t mode;
     995                 :                 va_list arg;
     996                 : 
     997               0 :                 va_start(arg, flags);
     998               0 :                 mode = (mode_t) va_arg(arg, int);
     999               0 :                 va_end(arg);
    1000                 : 
    1001               0 :                 f = open(new_state.cwd, flags, mode);
    1002                 :         } else {
    1003               0 :                 f = open(new_state.cwd, flags);
    1004                 :         }       
    1005               0 :         CWD_STATE_FREE(&new_state);
    1006               0 :         return f;
    1007                 : }
    1008                 : /* }}} */
    1009                 : 
    1010                 : CWD_API int virtual_creat(const char *path, mode_t mode TSRMLS_DC) /* {{{ */
    1011               0 : {
    1012                 :         cwd_state new_state;
    1013                 :         int f;
    1014                 : 
    1015               0 :         CWD_STATE_COPY(&new_state, &CWDG(cwd));
    1016               0 :         if (virtual_file_ex(&new_state, path, NULL, CWD_FILEPATH)) {
    1017               0 :                 CWD_STATE_FREE(&new_state);
    1018               0 :                 return -1;
    1019                 :         }
    1020                 : 
    1021               0 :         f = creat(new_state.cwd,  mode);
    1022                 : 
    1023               0 :         CWD_STATE_FREE(&new_state);
    1024               0 :         return f;
    1025                 : }
    1026                 : /* }}} */
    1027                 : 
    1028                 : CWD_API int virtual_rename(char *oldname, char *newname TSRMLS_DC) /* {{{ */
    1029               0 : {
    1030                 :         cwd_state old_state;
    1031                 :         cwd_state new_state;
    1032                 :         int retval;
    1033                 : 
    1034               0 :         CWD_STATE_COPY(&old_state, &CWDG(cwd));
    1035               0 :         if (virtual_file_ex(&old_state, oldname, NULL, CWD_EXPAND)) {
    1036               0 :                 CWD_STATE_FREE(&old_state);
    1037               0 :                 return -1;
    1038                 :         }
    1039               0 :         oldname = old_state.cwd;
    1040                 : 
    1041               0 :         CWD_STATE_COPY(&new_state, &CWDG(cwd));
    1042               0 :         if (virtual_file_ex(&new_state, newname, NULL, CWD_EXPAND)) {
    1043               0 :                 CWD_STATE_FREE(&old_state);
    1044               0 :                 CWD_STATE_FREE(&new_state);
    1045               0 :                 return -1;
    1046                 :         }
    1047               0 :         newname = new_state.cwd;
    1048                 :  
    1049               0 :         retval = rename(oldname, newname);
    1050                 : 
    1051               0 :         CWD_STATE_FREE(&old_state);
    1052               0 :         CWD_STATE_FREE(&new_state);
    1053                 : 
    1054               0 :         return retval;
    1055                 : }
    1056                 : /* }}} */
    1057                 : 
    1058                 : CWD_API int virtual_stat(const char *path, struct stat *buf TSRMLS_DC) /* {{{ */
    1059               0 : {
    1060                 :         cwd_state new_state;
    1061                 :         int retval;
    1062                 : 
    1063               0 :         CWD_STATE_COPY(&new_state, &CWDG(cwd));
    1064               0 :         if (virtual_file_ex(&new_state, path, NULL, CWD_REALPATH)) {
    1065               0 :                 CWD_STATE_FREE(&new_state);
    1066               0 :                 return -1;
    1067                 :         }
    1068                 : 
    1069               0 :         retval = php_sys_stat(new_state.cwd, buf);
    1070                 : 
    1071               0 :         CWD_STATE_FREE(&new_state);
    1072               0 :         return retval;
    1073                 : }
    1074                 : /* }}} */
    1075                 : 
    1076                 : #if !defined(TSRM_WIN32)
    1077                 : CWD_API int virtual_lstat(const char *path, struct stat *buf TSRMLS_DC) /* {{{ */
    1078               0 : {
    1079                 :         cwd_state new_state;
    1080                 :         int retval;
    1081                 : 
    1082               0 :         CWD_STATE_COPY(&new_state, &CWDG(cwd));
    1083               0 :         if (virtual_file_ex(&new_state, path, NULL, CWD_EXPAND)) {
    1084               0 :                 CWD_STATE_FREE(&new_state);
    1085               0 :                 return -1;
    1086                 :         }
    1087                 : 
    1088               0 :         retval = lstat(new_state.cwd, buf);
    1089                 : 
    1090               0 :         CWD_STATE_FREE(&new_state);
    1091               0 :         return retval;
    1092                 : }
    1093                 : /* }}} */
    1094                 : #endif
    1095                 : 
    1096                 : CWD_API int virtual_unlink(const char *path TSRMLS_DC) /* {{{ */
    1097               0 : {
    1098                 :         cwd_state new_state;
    1099                 :         int retval;
    1100                 : 
    1101               0 :         CWD_STATE_COPY(&new_state, &CWDG(cwd));
    1102               0 :         if (virtual_file_ex(&new_state, path, NULL, CWD_EXPAND)) {
    1103               0 :                 CWD_STATE_FREE(&new_state);
    1104               0 :                 return -1;
    1105                 :         }
    1106                 : 
    1107               0 :         retval = unlink(new_state.cwd);
    1108                 : 
    1109               0 :         CWD_STATE_FREE(&new_state);
    1110               0 :         return retval;
    1111                 : }
    1112                 : /* }}} */
    1113                 : 
    1114                 : CWD_API int virtual_mkdir(const char *pathname, mode_t mode TSRMLS_DC) /* {{{ */
    1115               0 : {
    1116                 :         cwd_state new_state;
    1117                 :         int retval;
    1118                 : 
    1119               0 :         CWD_STATE_COPY(&new_state, &CWDG(cwd));
    1120               0 :         if (virtual_file_ex(&new_state, pathname, NULL, CWD_FILEPATH)) {
    1121               0 :                 CWD_STATE_FREE(&new_state);
    1122               0 :                 return -1;
    1123                 :         }
    1124                 : 
    1125                 : #ifdef TSRM_WIN32
    1126                 :         retval = mkdir(new_state.cwd);
    1127                 : #else
    1128               0 :         retval = mkdir(new_state.cwd, mode);
    1129                 : #endif
    1130               0 :         CWD_STATE_FREE(&new_state);
    1131               0 :         return retval;
    1132                 : }
    1133                 : /* }}} */
    1134                 : 
    1135                 : CWD_API int virtual_rmdir(const char *pathname TSRMLS_DC) /* {{{ */
    1136               0 : {
    1137                 :         cwd_state new_state;
    1138                 :         int retval;
    1139                 : 
    1140               0 :         CWD_STATE_COPY(&new_state, &CWDG(cwd));
    1141               0 :         if (virtual_file_ex(&new_state, pathname, NULL, CWD_EXPAND)) {
    1142               0 :                 CWD_STATE_FREE(&new_state);
    1143               0 :                 return -1;
    1144                 :         }
    1145                 : 
    1146               0 :         retval = rmdir(new_state.cwd);
    1147                 : 
    1148               0 :         CWD_STATE_FREE(&new_state);
    1149               0 :         return retval;
    1150                 : }
    1151                 : /* }}} */
    1152                 : 
    1153                 : #ifdef TSRM_WIN32
    1154                 : DIR *opendir(const char *name);
    1155                 : #endif
    1156                 : 
    1157                 : CWD_API DIR *virtual_opendir(const char *pathname TSRMLS_DC) /* {{{ */
    1158               0 : {
    1159                 :         cwd_state new_state;
    1160                 :         DIR *retval;
    1161                 : 
    1162               0 :         CWD_STATE_COPY(&new_state, &CWDG(cwd));
    1163               0 :         if (virtual_file_ex(&new_state, pathname, NULL, CWD_REALPATH)) {
    1164               0 :                 CWD_STATE_FREE(&new_state);
    1165               0 :                 return NULL;
    1166                 :         }
    1167                 : 
    1168               0 :         retval = opendir(new_state.cwd);
    1169                 : 
    1170               0 :         CWD_STATE_FREE(&new_state);
    1171               0 :         return retval;
    1172                 : }
    1173                 : /* }}} */
    1174                 : 
    1175                 : #ifdef TSRM_WIN32
    1176                 : CWD_API FILE *virtual_popen(const char *command, const char *type TSRMLS_DC) /* {{{ */
    1177                 : {
    1178                 :         return popen_ex(command, type, CWDG(cwd).cwd, NULL);
    1179                 : }
    1180                 : /* }}} */
    1181                 : #elif defined(NETWARE)
    1182                 : /* On NetWare, the trick of prepending "cd cwd; " doesn't work so we need to perform
    1183                 :    a VCWD_CHDIR() and mutex it
    1184                 :  */
    1185                 : CWD_API FILE *virtual_popen(const char *command, const char *type TSRMLS_DC) /* {{{ */
    1186                 : {
    1187                 :         char prev_cwd[MAXPATHLEN];
    1188                 :         char *getcwd_result;
    1189                 :         FILE *retval;
    1190                 : 
    1191                 :         getcwd_result = VCWD_GETCWD(prev_cwd, MAXPATHLEN);
    1192                 :         if (!getcwd_result) {
    1193                 :                 return NULL;
    1194                 :         }
    1195                 : 
    1196                 : #ifdef ZTS
    1197                 :         tsrm_mutex_lock(cwd_mutex);
    1198                 : #endif
    1199                 : 
    1200                 :         VCWD_CHDIR(CWDG(cwd).cwd);
    1201                 :         retval = popen(command, type);
    1202                 :         VCWD_CHDIR(prev_cwd);
    1203                 : 
    1204                 : #ifdef ZTS
    1205                 :         tsrm_mutex_unlock(cwd_mutex);
    1206                 : #endif
    1207                 : 
    1208                 :         return retval;
    1209                 : }
    1210                 : /* }}} */
    1211                 : #else /* Unix */
    1212                 : CWD_API FILE *virtual_popen(const char *command, const char *type TSRMLS_DC) /* {{{ */
    1213               0 : {
    1214                 :         int command_length;
    1215               0 :         int dir_length, extra = 0;
    1216                 :         char *command_line;
    1217                 :         char *ptr, *dir;
    1218                 :         FILE *retval;
    1219                 : 
    1220               0 :         command_length = strlen(command);
    1221                 : 
    1222               0 :         dir_length = CWDG(cwd).cwd_length;
    1223               0 :         dir = CWDG(cwd).cwd;
    1224               0 :         while (dir_length > 0) {
    1225               0 :                 if (*dir == '\'') extra+=3;
    1226               0 :                 dir++;
    1227               0 :                 dir_length--;
    1228                 :         }
    1229               0 :         dir_length = CWDG(cwd).cwd_length;
    1230               0 :         dir = CWDG(cwd).cwd;
    1231                 : 
    1232               0 :         ptr = command_line = (char *) malloc(command_length + sizeof("cd '' ; ") + dir_length + extra+1+1);
    1233               0 :         if (!command_line) {
    1234               0 :                 return NULL;
    1235                 :         }
    1236               0 :         memcpy(ptr, "cd ", sizeof("cd ")-1);
    1237               0 :         ptr += sizeof("cd ")-1;
    1238                 : 
    1239               0 :         if (CWDG(cwd).cwd_length == 0) {
    1240               0 :                 *ptr++ = DEFAULT_SLASH;
    1241                 :         } else {
    1242               0 :                 *ptr++ = '\'';
    1243               0 :                 while (dir_length > 0) {
    1244               0 :                         switch (*dir) {
    1245                 :                         case '\'':
    1246               0 :                                 *ptr++ = '\'';
    1247               0 :                                 *ptr++ = '\\';
    1248               0 :                                 *ptr++ = '\'';
    1249                 :                                 /* fall-through */
    1250                 :                         default:
    1251               0 :                                 *ptr++ = *dir;
    1252                 :                         }
    1253               0 :                         dir++;
    1254               0 :                         dir_length--;
    1255                 :                 }
    1256               0 :                 *ptr++ = '\'';
    1257                 :         }
    1258                 :         
    1259               0 :         *ptr++ = ' ';
    1260               0 :         *ptr++ = ';';
    1261               0 :         *ptr++ = ' ';
    1262                 : 
    1263               0 :         memcpy(ptr, command, command_length+1);
    1264               0 :         retval = popen(command_line, type);
    1265                 : 
    1266               0 :         free(command_line);
    1267               0 :         return retval;
    1268                 : }
    1269                 : /* }}} */
    1270                 : #endif
    1271                 : 
    1272                 : CWD_API char *tsrm_realpath(const char *path, char *real_path TSRMLS_DC) /* {{{ */
    1273           34375 : {
    1274                 :         cwd_state new_state;
    1275                 :         char cwd[MAXPATHLEN];
    1276                 : 
    1277                 :         /* realpath("") returns CWD */
    1278           34375 :         if (!*path) {
    1279               4 :                 new_state.cwd = (char*)malloc(1);
    1280               4 :                 new_state.cwd[0] = '\0';
    1281               4 :                 new_state.cwd_length = 0;               
    1282               4 :             if (VCWD_GETCWD(cwd, MAXPATHLEN)) {
    1283               4 :                     path = cwd;
    1284                 :                 }
    1285           34688 :         } else if (!IS_ABSOLUTE_PATH(path, strlen(path)) &&
    1286                 :             VCWD_GETCWD(cwd, MAXPATHLEN)) {
    1287             317 :                 new_state.cwd = strdup(cwd);
    1288             317 :                 new_state.cwd_length = strlen(cwd);
    1289                 :         } else {
    1290           34054 :                 new_state.cwd = (char*)malloc(1);
    1291           34054 :                 new_state.cwd[0] = '\0';
    1292           34054 :                 new_state.cwd_length = 0;               
    1293                 :         }
    1294                 : 
    1295           34375 :         if (virtual_file_ex(&new_state, path, NULL, CWD_REALPATH)) {
    1296             459 :                 free(new_state.cwd);
    1297             459 :                 return NULL;
    1298                 :         }
    1299                 : 
    1300           33916 :         if (real_path) {
    1301           33861 :                 int copy_len = new_state.cwd_length>MAXPATHLEN-1 ? MAXPATHLEN-1 : new_state.cwd_length;
    1302           33861 :                 memcpy(real_path, new_state.cwd, copy_len);
    1303           33861 :                 real_path[copy_len] = '\0';
    1304           33861 :                 free(new_state.cwd);
    1305           33861 :                 return real_path;
    1306                 :         } else {
    1307              55 :                 return new_state.cwd;
    1308                 :         }
    1309                 : }
    1310                 : /* }}} */
    1311                 : 
    1312                 : /*
    1313                 :  * Local variables:
    1314                 :  * tab-width: 4
    1315                 :  * c-basic-offset: 4
    1316                 :  * End:
    1317                 :  */

Generated by: LTP GCOV extension version 1.5

Generated at Thu, 19 Nov 2009 08:20:01 +0000 (5 days ago)

Copyright © 2005-2009 The PHP Group
All rights reserved.