LTP GCOV extension - code coverage report
Current view: directory - TSRM - tsrm_virtual_cwd.c
Test: PHP Code Coverage
Date: 2007-04-10 Instrumented lines: 432
Code covered: 37.5 % Executed lines: 162
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | PHP Version 5                                                        |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1997-2007 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,v 1.74.2.9.2.25 2007/04/03 20:20:56 tony2001 Exp $ */
      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                 : #endif
     219                 : 
     220                 : static int php_is_dir_ok(const cwd_state *state) 
     221               0 : {
     222                 :         struct stat buf;
     223                 : 
     224               0 :         if (php_sys_stat(state->cwd, &buf) == 0 && S_ISDIR(buf.st_mode))
     225               0 :                 return (0);
     226                 : 
     227               0 :         return (1);
     228                 : }
     229                 : 
     230                 : static int php_is_file_ok(const cwd_state *state) 
     231               0 : {
     232                 :         struct stat buf;
     233                 : 
     234               0 :         if (php_sys_stat(state->cwd, &buf) == 0 && S_ISREG(buf.st_mode))
     235               0 :                 return (0);
     236                 : 
     237               0 :         return (1);
     238                 : }
     239                 : 
     240                 : static void cwd_globals_ctor(virtual_cwd_globals *cwd_globals TSRMLS_DC)
     241             220 : {
     242             220 :         CWD_STATE_COPY(&cwd_globals->cwd, &main_cwd_state);
     243             220 :         cwd_globals->realpath_cache_size = 0;
     244             220 :         cwd_globals->realpath_cache_size_limit = REALPATH_CACHE_SIZE;
     245             220 :         cwd_globals->realpath_cache_ttl = REALPATH_CACHE_TTL;
     246             220 :         memset(cwd_globals->realpath_cache, 0, sizeof(cwd_globals->realpath_cache));
     247             220 : }
     248                 : 
     249                 : static void cwd_globals_dtor(virtual_cwd_globals *cwd_globals TSRMLS_DC)
     250             219 : {
     251             219 :         CWD_STATE_FREE(&cwd_globals->cwd);
     252             219 :         realpath_cache_clean(TSRMLS_C);
     253             219 : }
     254                 : 
     255                 : static char *tsrm_strndup(const char *s, size_t length)
     256             239 : {
     257                 :     char *p;
     258                 : 
     259             239 :     p = (char *) malloc(length+1);
     260             239 :     if (!p) {
     261               0 :         return (char *)NULL;
     262                 :     }
     263             239 :     if (length) {
     264             239 :         memcpy(p,s,length);
     265                 :     }
     266             239 :     p[length]=0;
     267             239 :     return p;
     268                 : }
     269                 : 
     270                 : CWD_API void virtual_cwd_startup(void)
     271             220 : {
     272                 :         char cwd[MAXPATHLEN];
     273                 :         char *result;
     274                 : 
     275                 : #ifdef NETWARE
     276                 :         result = getcwdpath(cwd, NULL, 1);
     277                 :         if(result)
     278                 :         {
     279                 :                 char *c=cwd;
     280                 :                 while(c = strchr(c, '\\'))
     281                 :                 {
     282                 :                         *c='/';
     283                 :                         ++c;
     284                 :                 }
     285                 :         }
     286                 : #else
     287             220 :         result = getcwd(cwd, sizeof(cwd));      
     288                 : #endif
     289             220 :         if (!result) {
     290               0 :                 cwd[0] = '\0';
     291                 :         }
     292             220 :         main_cwd_state.cwd = strdup(cwd);
     293             220 :         main_cwd_state.cwd_length = strlen(cwd);
     294                 : 
     295                 : #ifdef ZTS
     296                 :         ts_allocate_id(&cwd_globals_id, sizeof(virtual_cwd_globals), (ts_allocate_ctor) cwd_globals_ctor, (ts_allocate_dtor) cwd_globals_dtor);
     297                 : #else
     298             220 :         cwd_globals_ctor(&cwd_globals TSRMLS_CC);
     299                 : #endif
     300                 : 
     301                 : #if (defined(TSRM_WIN32) || defined(NETWARE)) && defined(ZTS)
     302                 :         cwd_mutex = tsrm_mutex_alloc();
     303                 : #endif
     304             220 : }
     305                 : 
     306                 : CWD_API void virtual_cwd_shutdown(void)
     307             219 : {
     308                 : #ifndef ZTS
     309             219 :         cwd_globals_dtor(&cwd_globals TSRMLS_CC);
     310                 : #endif
     311                 : #if (defined(TSRM_WIN32) || defined(NETWARE)) && defined(ZTS)
     312                 :         tsrm_mutex_free(cwd_mutex);
     313                 : #endif
     314                 : 
     315             219 :         free(main_cwd_state.cwd); /* Don't use CWD_STATE_FREE because the non global states will probably use emalloc()/efree() */
     316             219 : }
     317                 : 
     318                 : CWD_API char *virtual_getcwd_ex(size_t *length TSRMLS_DC)
     319               0 : {
     320                 :         cwd_state *state;
     321                 : 
     322               0 :         state = &CWDG(cwd);
     323                 : 
     324               0 :         if (state->cwd_length == 0) {
     325                 :                 char *retval;
     326                 : 
     327               0 :                 *length = 1;
     328               0 :                 retval = (char *) malloc(2);
     329               0 :                 retval[0] = DEFAULT_SLASH;
     330               0 :                 retval[1] = '\0';       
     331               0 :                 return retval;
     332                 :         }
     333                 : 
     334                 : #ifdef TSRM_WIN32
     335                 :         /* If we have something like C: */
     336                 :         if (state->cwd_length == 2 && state->cwd[state->cwd_length-1] == ':') {
     337                 :                 char *retval;
     338                 : 
     339                 :                 *length = state->cwd_length+1;
     340                 :                 retval = (char *) malloc(*length+1);
     341                 :                 memcpy(retval, state->cwd, *length);
     342                 :                 retval[*length-1] = DEFAULT_SLASH;
     343                 :                 retval[*length] = '\0';
     344                 :                 return retval;
     345                 :         }
     346                 : #endif
     347               0 :         *length = state->cwd_length;
     348               0 :         return strdup(state->cwd);
     349                 : }
     350                 : 
     351                 : 
     352                 : /* Same semantics as UNIX getcwd() */
     353                 : CWD_API char *virtual_getcwd(char *buf, size_t size TSRMLS_DC)
     354               0 : {
     355                 :         size_t length;
     356                 :         char *cwd;
     357                 : 
     358               0 :         cwd = virtual_getcwd_ex(&length TSRMLS_CC);
     359                 : 
     360               0 :         if (buf == NULL) {
     361               0 :                 return cwd;
     362                 :         }
     363               0 :         if (length > size-1) {
     364               0 :                 free(cwd);
     365               0 :                 errno = ERANGE; /* Is this OK? */
     366               0 :                 return NULL;
     367                 :         }
     368               0 :         memcpy(buf, cwd, length+1);
     369               0 :         free(cwd);
     370               0 :         return buf;
     371                 : }
     372                 : 
     373                 : static inline unsigned long realpath_cache_key(const char *path, int path_len)
     374            2259 : {
     375                 :         register unsigned long h;
     376            2259 :         const char *e = path + path_len;
     377                 : 
     378          116916 :         for (h = 2166136261U; path < e;) {
     379          112398 :                 h *= 16777619;
     380          112398 :                 h ^= *path++;
     381                 :         }
     382                 : 
     383            2259 :         return h;
     384                 : }
     385                 : 
     386                 : CWD_API void realpath_cache_clean(TSRMLS_D)
     387             474 : {
     388                 :         int i;
     389                 : 
     390          485850 :         for (i = 0; i < sizeof(CWDG(realpath_cache))/sizeof(CWDG(realpath_cache)[0]); i++) {
     391          485376 :                 realpath_cache_bucket *p = CWDG(realpath_cache)[i];
     392          971820 :                 while (p != NULL) {
     393            1068 :                         realpath_cache_bucket *r = p;
     394            1068 :                         p = p->next;
     395            1068 :                         free(r);
     396                 :                 }
     397          485376 :                 CWDG(realpath_cache)[i] = NULL;
     398                 :         }
     399             474 :         CWDG(realpath_cache_size) = 0;
     400             474 : }
     401                 : 
     402                 : CWD_API void realpath_cache_del(const char *path, int path_len TSRMLS_DC)
     403               0 : {
     404               0 :         unsigned long key = realpath_cache_key(path, path_len);
     405               0 :         unsigned long n = key % (sizeof(CWDG(realpath_cache)) / sizeof(CWDG(realpath_cache)[0]));
     406               0 :         realpath_cache_bucket **bucket = &CWDG(realpath_cache)[n];
     407                 : 
     408               0 :         while (*bucket != NULL) {
     409               0 :                 if (key == (*bucket)->key && path_len == (*bucket)->path_len &&
     410                 :                            memcmp(path, (*bucket)->path, path_len) == 0) {
     411               0 :                         realpath_cache_bucket *r = *bucket;
     412               0 :                         *bucket = (*bucket)->next;
     413               0 :                         CWDG(realpath_cache_size) -= sizeof(realpath_cache_bucket) + r->path_len + 1 + r->realpath_len + 1;
     414               0 :                         free(r);
     415               0 :                         return;
     416                 :                 } else {
     417               0 :                         bucket = &(*bucket)->next;
     418                 :                 }
     419                 :         }
     420                 : }
     421                 : 
     422                 : static inline void realpath_cache_add(const char *path, int path_len, const char *realpath, int realpath_len, time_t t TSRMLS_DC)
     423            1068 : {
     424            1068 :         long size = sizeof(realpath_cache_bucket) + path_len + 1 + realpath_len + 1;
     425            1068 :         if (CWDG(realpath_cache_size) + size <= CWDG(realpath_cache_size_limit)) {
     426            1068 :                 realpath_cache_bucket *bucket = malloc(size);
     427                 :                 unsigned long n;
     428                 :         
     429            1068 :                 bucket->key = realpath_cache_key(path, path_len);
     430            1068 :                 bucket->path = (char*)bucket + sizeof(realpath_cache_bucket);
     431            1068 :                 memcpy(bucket->path, path, path_len+1);
     432            1068 :                 bucket->path_len = path_len;
     433            1068 :                 bucket->realpath = bucket->path + (path_len + 1);
     434            1068 :                 memcpy(bucket->realpath, realpath, realpath_len+1);
     435            1068 :                 bucket->realpath_len = realpath_len;
     436            1068 :                 bucket->expires = t + CWDG(realpath_cache_ttl);
     437            1068 :                 n = bucket->key % (sizeof(CWDG(realpath_cache)) / sizeof(CWDG(realpath_cache)[0]));
     438            1068 :                 bucket->next = CWDG(realpath_cache)[n];
     439            1068 :                 CWDG(realpath_cache)[n] = bucket;
     440            1068 :                 CWDG(realpath_cache_size) += size;
     441                 :         }
     442            1068 : }
     443                 : 
     444                 : static inline realpath_cache_bucket* realpath_cache_find(const char *path, int path_len, time_t t TSRMLS_DC)
     445            1191 : {
     446            1191 :         unsigned long key = realpath_cache_key(path, path_len);
     447            1191 :         unsigned long n = key % (sizeof(CWDG(realpath_cache)) / sizeof(CWDG(realpath_cache)[0]));
     448            1191 :         realpath_cache_bucket **bucket = &CWDG(realpath_cache)[n];
     449                 : 
     450            2408 :         while (*bucket != NULL) {
     451             149 :                 if (CWDG(realpath_cache_ttl) && (*bucket)->expires < t) {
     452               0 :                         realpath_cache_bucket *r = *bucket;
     453               0 :                         *bucket = (*bucket)->next;
     454               0 :                         CWDG(realpath_cache_size) -= sizeof(realpath_cache_bucket) + r->path_len + 1 + r->realpath_len + 1;
     455               0 :                         free(r);
     456             149 :                 } else if (key == (*bucket)->key && path_len == (*bucket)->path_len &&
     457                 :                            memcmp(path, (*bucket)->path, path_len) == 0) {
     458             123 :                         return *bucket;
     459                 :                 } else {
     460              26 :                         bucket = &(*bucket)->next;
     461                 :                 }
     462                 :         }
     463            1068 :         return NULL;
     464                 : }
     465                 : 
     466                 : 
     467                 : /* Resolve path relatively to state and put the real path into state */
     468                 : /* returns 0 for ok, 1 for error */
     469                 : CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func verify_path, int use_realpath)
     470            1192 : {
     471            1192 :         int path_length = strlen(path);
     472                 :         cwd_state old_state;
     473                 :         char orig_path[MAXPATHLEN];
     474                 :         realpath_cache_bucket *bucket;
     475            1192 :         time_t t = 0;
     476                 :         int ret;
     477                 :         int use_cache;
     478            1192 :         int use_relative_path = 0;
     479                 :         TSRMLS_FETCH();
     480                 :         
     481            1192 :         use_cache = ((use_realpath != CWD_EXPAND) && CWDG(realpath_cache_size_limit));
     482                 : 
     483            1192 :         if (path_length == 0) 
     484               1 :                 return (0);
     485            1191 :         if (path_length >= MAXPATHLEN)
     486               0 :                 return (1);
     487                 : 
     488                 : #if VIRTUAL_CWD_DEBUG
     489                 :                 fprintf(stderr,"cwd = %s path = %s\n", state->cwd, path);
     490                 : #endif
     491                 : 
     492                 :         /* cwd_length can be 0 when getcwd() fails.
     493                 :          * This can happen under solaris when a dir does not have read permissions
     494                 :          * but *does* have execute permissions */
     495            1191 :         if (!IS_ABSOLUTE_PATH(path, path_length)) {
     496             286 :                 if (state->cwd_length == 0) {
     497               0 :                         use_cache = 0;
     498               0 :                         use_relative_path = 1;
     499                 :                 } else {
     500                 :                         int orig_path_len;
     501             286 :                         int state_cwd_length = state->cwd_length;
     502                 : 
     503                 : #ifdef TSRM_WIN32
     504                 :                         if (IS_SLASH(path[0])) {
     505                 :                                 state_cwd_length = 2;
     506                 :                         }
     507                 : #endif
     508             286 :                         orig_path_len = path_length + state_cwd_length + 1;
     509             286 :                         if (orig_path_len >= MAXPATHLEN) {
     510               0 :                                 return 1;
     511                 :                         }
     512             286 :                         memcpy(orig_path, state->cwd, state_cwd_length);
     513             286 :                         orig_path[state_cwd_length] = DEFAULT_SLASH;
     514             286 :                         memcpy(orig_path + state_cwd_length + 1, path, path_length + 1);
     515             286 :                         path = orig_path;
     516             286 :                         path_length = orig_path_len; 
     517                 :                 }
     518                 :         }
     519                 : 
     520            1191 :         if (use_cache) {
     521            1191 :                 t = CWDG(realpath_cache_ttl)?time(NULL):0;
     522            1191 :                 if ((bucket = realpath_cache_find(path, path_length, t TSRMLS_CC)) != NULL) {           
     523             123 :                         int len = bucket->realpath_len;
     524                 : 
     525             123 :                         CWD_STATE_COPY(&old_state, state);
     526             123 :                         state->cwd = (char *) realloc(state->cwd, len+1);
     527             123 :                         memcpy(state->cwd, bucket->realpath, len+1);
     528             123 :                         state->cwd_length = len;
     529             123 :                         if (verify_path && verify_path(state)) {
     530               0 :                                 CWD_STATE_FREE(state);
     531               0 :                                 *state = old_state;
     532               0 :                                 return 1;
     533                 :                         } else {
     534             123 :                                 CWD_STATE_FREE(&old_state);
     535             123 :                                 return 0;
     536                 :                         }
     537                 :                 }
     538                 :         }
     539                 : 
     540            1068 :         if (use_realpath != CWD_EXPAND) {
     541                 : #if !defined(TSRM_WIN32) && !defined(NETWARE)
     542                 :                 char resolved_path[MAXPATHLEN];
     543                 : 
     544            1068 :                 if (!realpath(path, resolved_path)) {  /* Note: Not threadsafe on older *BSD's */
     545             239 :                         if (use_realpath == CWD_REALPATH) {
     546               0 :                                 return 1;
     547                 :                         }
     548             239 :                         goto no_realpath;
     549                 :                 }
     550             829 :                 CWD_STATE_COPY(&old_state, state);
     551                 : 
     552             829 :                 state->cwd_length = strlen(resolved_path);
     553             829 :                 state->cwd = (char *) realloc(state->cwd, state->cwd_length+1);
     554             829 :                 memcpy(state->cwd, resolved_path, state->cwd_length+1);
     555                 : #else
     556                 :                 goto no_realpath;
     557                 : #endif
     558                 :         } else {
     559                 :                 char *ptr, *path_copy, *free_path;
     560                 :                 char *tok;
     561                 :                 int ptr_length;
     562                 : #ifdef TSRM_WIN32
     563                 :                 int is_unc;
     564                 : #endif
     565             239 : no_realpath:
     566                 : 
     567             239 :                 free_path = path_copy = tsrm_strndup(path, path_length);
     568             239 :                 CWD_STATE_COPY(&old_state, state);
     569                 : 
     570                 : #ifdef TSRM_WIN32
     571                 :                 is_unc = 0;
     572                 :                 if (path_length >= 2 && path[1] == ':') {                    
     573                 :                         state->cwd = (char *) realloc(state->cwd, 2 + 1);
     574                 :                         state->cwd[0] = toupper(path[0]);
     575                 :                         state->cwd[1] = ':';
     576                 :                         state->cwd[2] = '\0';
     577                 :                         state->cwd_length = 2;
     578                 :                         path_copy += 2;
     579                 :                 } else if (IS_UNC_PATH(path, path_length)) {
     580                 :                         state->cwd = (char *) realloc(state->cwd, 1 + 1);
     581                 :                         state->cwd[0] = DEFAULT_SLASH;
     582                 :                         state->cwd[1] = '\0';
     583                 :                         state->cwd_length = 1;
     584                 :                         path_copy += 2;
     585                 :                         is_unc = 2;
     586                 :                 } else {
     587                 : #endif
     588             239 :                         state->cwd = (char *) realloc(state->cwd, 1);
     589             239 :                         state->cwd[0] = '\0';
     590             239 :                         state->cwd_length = 0;
     591                 : #ifdef TSRM_WIN32
     592                 :                 }
     593                 : #endif
     594                 :                 
     595             239 :                 tok = NULL;
     596             239 :                 ptr = tsrm_strtok_r(path_copy, TOKENIZER_STRING, &tok);
     597            2147 :                 while (ptr) {
     598            1669 :                         ptr_length = strlen(ptr);
     599                 : 
     600            1669 :                         if (IS_DIRECTORY_UP(ptr, ptr_length)) {
     601                 :                                 char save;
     602                 : 
     603               0 :                                 if (use_relative_path) {
     604               0 :                                         CWD_STATE_FREE(state);
     605               0 :                                         *state = old_state;
     606               0 :                                         return 1;
     607                 :                                 }
     608                 : 
     609               0 :                                 save = DEFAULT_SLASH;
     610                 : 
     611                 : #define PREVIOUS state->cwd[state->cwd_length - 1]
     612                 : 
     613               0 :                                 while (IS_ABSOLUTE_PATH(state->cwd, state->cwd_length) &&
     614                 :                                                 !IS_SLASH(PREVIOUS)) {
     615               0 :                                         save = PREVIOUS;
     616               0 :                                         PREVIOUS = '\0';
     617               0 :                                         state->cwd_length--;
     618                 :                                 }
     619                 : 
     620               0 :                                 if (!IS_ABSOLUTE_PATH(state->cwd, state->cwd_length)) {
     621               0 :                                         state->cwd[state->cwd_length++] = save;
     622               0 :                                         state->cwd[state->cwd_length] = '\0';
     623                 :                                 } else {
     624               0 :                                         PREVIOUS = '\0';
     625               0 :                                         state->cwd_length--;
     626                 :                                 }
     627            1669 :                         } else if (!IS_DIRECTORY_CURRENT(ptr, ptr_length)) {
     628            1669 :                                 if (use_relative_path) {
     629               0 :                                         state->cwd = (char *) realloc(state->cwd, state->cwd_length+ptr_length+1);
     630               0 :                                         use_relative_path = 0;
     631                 :                                 } else {
     632            1669 :                                         state->cwd = (char *) realloc(state->cwd, state->cwd_length+ptr_length+1+1);
     633                 : #ifdef TSRM_WIN32
     634                 :                                         /* Windows 9x will consider C:\\Foo as a network path. Avoid it. */
     635                 :                                         if (state->cwd_length < 2 ||
     636                 :                                             (state->cwd[state->cwd_length-1]!='\\' && state->cwd[state->cwd_length-1]!='/') ||
     637                 :                                                         IsDBCSLeadByte(state->cwd[state->cwd_length-2])) {
     638                 :                                                 state->cwd[state->cwd_length++] = DEFAULT_SLASH;
     639                 :                                         }
     640                 : #elif defined(NETWARE)
     641                 :                                         /* 
     642                 :                                         Below code keeps appending to state->cwd a File system seperator
     643                 :                                         cases where this appending should not happen is given below,
     644                 :                                         a) sys: should just be left as it is
     645                 :                                         b) sys:system should just be left as it is,
     646                 :                                                 Colon is allowed only in the first token as volume names alone can have the : in their names.
     647                 :                                                 Files and Directories cannot have : in their names
     648                 :                                                 So the check goes like this,
     649                 :                                                 For second token and above simply append the DEFAULT_SLASH to the state->cwd.
     650                 :                                                 For first token check for the existence of : 
     651                 :                                                 if it exists don't append the DEFAULT_SLASH to the state->cwd.
     652                 :                                         */
     653                 :                                         if(((state->cwd_length == 0) && (strchr(ptr, ':') == NULL)) || (state->cwd_length > 0)) {
     654                 :                                                 state->cwd[state->cwd_length++] = DEFAULT_SLASH;
     655                 :                                         }
     656                 : #else
     657            1669 :                                         state->cwd[state->cwd_length++] = DEFAULT_SLASH;
     658                 : #endif
     659                 :                                 }
     660            1669 :                                 memcpy(&state->cwd[state->cwd_length], ptr, ptr_length+1);
     661                 : 
     662                 : #ifdef TSRM_WIN32
     663                 :                                 if (use_realpath != CWD_EXPAND) {
     664                 :                                         WIN32_FIND_DATA data;
     665                 :                                         HANDLE hFind;
     666                 : 
     667                 :                                         if ((hFind = FindFirstFile(state->cwd, &data)) != INVALID_HANDLE_VALUE) {
     668                 :                                                 int length = strlen(data.cFileName);
     669                 : 
     670                 :                                                 if (length != ptr_length) {
     671                 :                                                         state->cwd = (char *) realloc(state->cwd, state->cwd_length+length+1);
     672                 :                                                 }
     673                 :                                                 memcpy(&state->cwd[state->cwd_length], data.cFileName, length+1);
     674                 :                                                 ptr_length = length;
     675                 :                                                 FindClose(hFind);
     676                 :                                                 ret = 0;
     677                 :                                         } else if (use_realpath == CWD_REALPATH) {
     678                 :                                                 if (is_unc) {
     679                 :                                                         /* skip share name */
     680                 :                                                         is_unc--;
     681                 :                                                         ret = 0;
     682                 :                                                 } else {
     683                 :                                                         ret = 1;
     684                 :                                                 }
     685                 :                                         }
     686                 :                                 }
     687                 : #endif
     688                 : 
     689            1669 :                                 state->cwd_length += ptr_length;
     690                 :                         }
     691            1669 :                         ptr = tsrm_strtok_r(NULL, TOKENIZER_STRING, &tok);
     692                 :                 }
     693                 : 
     694             239 :                 free(free_path);
     695                 : 
     696             239 :                 if ((use_realpath == CWD_REALPATH) && ret) {
     697               0 :                         CWD_STATE_FREE(state);
     698               0 :                         *state = old_state;                                     
     699               0 :                         return 1;
     700                 :                 }
     701                 : 
     702             239 :                 if (state->cwd_length == COPY_WHEN_ABSOLUTE(state->cwd)) {
     703               0 :                         state->cwd = (char *) realloc(state->cwd, state->cwd_length+1+1);
     704               0 :                         state->cwd[state->cwd_length] = DEFAULT_SLASH;
     705               0 :                         state->cwd[state->cwd_length+1] = '\0';
     706               0 :                         state->cwd_length++;
     707                 :                 }
     708                 :         }
     709                 : 
     710            1068 :         if (use_cache) {
     711            1068 :                 realpath_cache_add(path, path_length, state->cwd, state->cwd_length, t TSRMLS_CC);
     712                 :         }
     713                 : 
     714            1068 :         if (verify_path && verify_path(state)) {
     715               0 :                 CWD_STATE_FREE(state);
     716               0 :                 *state = old_state;
     717               0 :                 ret = 1;
     718                 :         } else {
     719            1068 :                 CWD_STATE_FREE(&old_state);
     720            1068 :                 ret = 0;
     721                 :         }
     722                 :         
     723                 : #if VIRTUAL_CWD_DEBUG
     724                 :         fprintf (stderr, "virtual_file_ex() = %s\n",state->cwd);
     725                 : #endif
     726            1068 :         return (ret);
     727                 : }
     728                 : 
     729                 : CWD_API int virtual_chdir(const char *path TSRMLS_DC)
     730               0 : {
     731               0 :         return virtual_file_ex(&CWDG(cwd), path, php_is_dir_ok, CWD_REALPATH)?-1:0;
     732                 : }
     733                 : 
     734                 : CWD_API int virtual_chdir_file(const char *path, int (*p_chdir)(const char *path TSRMLS_DC) TSRMLS_DC)
     735             218 : {
     736             218 :         int length = strlen(path);
     737                 :         char *temp;
     738                 :         int retval;
     739                 : 
     740             218 :         if (length == 0) {
     741               0 :                 return 1; /* Can't cd to empty string */
     742                 :         }       
     743            5030 :         while(--length >= 0 && !IS_SLASH(path[length])) {
     744                 :         }
     745                 : 
     746             218 :         if (length == -1) {
     747                 :                 /* No directory only file name */
     748               0 :                 errno = ENOENT;
     749               0 :                 return -1;
     750                 :         }
     751                 : 
     752             218 :         if (length == COPY_WHEN_ABSOLUTE(path) && IS_ABSOLUTE_PATH(path, length+1)) { /* Also use trailing slash if this is absolute */
     753               0 :                 length++;
     754                 :         }
     755             218 :         temp = (char *) tsrm_do_alloca(length+1);
     756             218 :         memcpy(temp, path, length);
     757             218 :         temp[length] = 0;
     758                 : #if VIRTUAL_CWD_DEBUG
     759                 :         fprintf (stderr, "Changing directory to %s\n", temp);
     760                 : #endif
     761             218 :         retval = p_chdir(temp TSRMLS_CC);
     762                 :         tsrm_free_alloca(temp);
     763             218 :         return retval;
     764                 : }
     765                 : 
     766                 : CWD_API char *virtual_realpath(const char *path, char *real_path TSRMLS_DC)
     767               0 : {
     768                 :         cwd_state new_state;
     769                 :         char *retval;
     770                 : 
     771               0 :         CWD_STATE_COPY(&new_state, &CWDG(cwd));
     772                 :         
     773               0 :         if (virtual_file_ex(&new_state, path, NULL, CWD_REALPATH)==0) {
     774               0 :                 int len = new_state.cwd_length>MAXPATHLEN-1?MAXPATHLEN-1:new_state.cwd_length;
     775                 : 
     776               0 :                 memcpy(real_path, new_state.cwd, len);
     777               0 :                 real_path[len] = '\0';
     778               0 :                 retval = real_path;
     779                 :         } else {
     780               0 :                 retval = NULL;
     781                 :         }
     782                 : 
     783               0 :         CWD_STATE_FREE(&new_state);
     784                 : 
     785               0 :         return retval;
     786                 : }
     787                 : 
     788                 : CWD_API int virtual_filepath_ex(const char *path, char **filepath, verify_path_func verify_path TSRMLS_DC)
     789               0 : {
     790                 :         cwd_state new_state;
     791                 :         int retval;
     792                 : 
     793               0 :         CWD_STATE_COPY(&new_state, &CWDG(cwd));
     794               0 :         retval = virtual_file_ex(&new_state, path, verify_path, CWD_FILEPATH);
     795                 : 
     796               0 :         *filepath = new_state.cwd;
     797                 : 
     798               0 :         return retval;
     799                 : 
     800                 : }
     801                 : 
     802                 : CWD_API int virtual_filepath(const char *path, char **filepath TSRMLS_DC)
     803               0 : {
     804               0 :         return virtual_filepath_ex(path, filepath, php_is_file_ok TSRMLS_CC);
     805                 : }
     806                 : 
     807                 : CWD_API FILE *virtual_fopen(const char *path, const char *mode TSRMLS_DC)
     808               0 : {
     809                 :         cwd_state new_state;
     810                 :         FILE *f;
     811                 : 
     812               0 :         if (path[0] == '\0') { /* Fail to open empty path */
     813               0 :                 return NULL;
     814                 :         }
     815                 : 
     816               0 :         CWD_STATE_COPY(&new_state, &CWDG(cwd));
     817               0 :         if (virtual_file_ex(&new_state, path, NULL, CWD_FILEPATH)) {
     818               0 :                 CWD_STATE_FREE(&new_state);
     819               0 :                 return NULL;
     820                 :         }
     821                 : 
     822               0 :         f = fopen(new_state.cwd, mode);
     823                 : 
     824               0 :         CWD_STATE_FREE(&new_state);
     825               0 :         return f;
     826                 : }
     827                 : 
     828                 : CWD_API int virtual_access(const char *pathname, int mode TSRMLS_DC)
     829               0 : {
     830                 :         cwd_state new_state;
     831                 :         int ret;
     832                 :         
     833               0 :         CWD_STATE_COPY(&new_state, &CWDG(cwd));
     834               0 :         if (virtual_file_ex(&new_state, pathname, NULL, CWD_REALPATH)) {
     835               0 :                 CWD_STATE_FREE(&new_state);
     836               0 :                 return -1;
     837                 :         }
     838                 : 
     839                 : #if defined(TSRM_WIN32)
     840                 :         ret = tsrm_win32_access(new_state.cwd, mode);
     841                 : #else
     842               0 :         ret = access(new_state.cwd, mode);
     843                 : #endif
     844                 :         
     845               0 :         CWD_STATE_FREE(&new_state);
     846                 :         
     847               0 :         return ret;
     848                 : }
     849                 : 
     850                 : 
     851                 : #if HAVE_UTIME
     852                 : CWD_API int virtual_utime(const char *filename, struct utimbuf *buf TSRMLS_DC)
     853               0 : {
     854                 :         cwd_state new_state;
     855                 :         int ret;
     856                 : 
     857               0 :         CWD_STATE_COPY(&new_state, &CWDG(cwd));
     858               0 :         if (virtual_file_ex(&new_state, filename, NULL, CWD_REALPATH)) {
     859               0 :                 CWD_STATE_FREE(&new_state);
     860               0 :                 return -1;
     861                 :         }
     862                 : 
     863               0 :         ret = utime(new_state.cwd, buf);
     864                 : 
     865               0 :         CWD_STATE_FREE(&new_state);
     866               0 :         return ret;
     867                 : }
     868                 : #endif
     869                 : 
     870                 : CWD_API int virtual_chmod(const char *filename, mode_t mode TSRMLS_DC)
     871               0 : {
     872                 :         cwd_state new_state;
     873                 :         int ret;
     874                 : 
     875               0 :         CWD_STATE_COPY(&new_state, &CWDG(cwd));
     876               0 :         if (virtual_file_ex(&new_state, filename, NULL, CWD_REALPATH)) {
     877               0 :                 CWD_STATE_FREE(&new_state);
     878               0 :                 return -1;
     879                 :         }
     880                 : 
     881               0 :         ret = chmod(new_state.cwd, mode);
     882                 : 
     883               0 :         CWD_STATE_FREE(&new_state);
     884               0 :         return ret;
     885                 : }
     886                 : 
     887                 : #if !defined(TSRM_WIN32) && !defined(NETWARE)
     888                 : CWD_API int virtual_chown(const char *filename, uid_t owner, gid_t group, int link TSRMLS_DC)
     889               0 : {
     890                 :         cwd_state new_state;
     891                 :         int ret;
     892                 : 
     893               0 :         CWD_STATE_COPY(&new_state, &CWDG(cwd));
     894               0 :         if (virtual_file_ex(&new_state, filename, NULL, CWD_REALPATH)) {
     895               0 :                 CWD_STATE_FREE(&new_state);
     896               0 :                 return -1;
     897                 :         }
     898                 : 
     899               0 :         if (link) {
     900                 : #if HAVE_LCHOWN
     901               0 :                 ret = lchown(new_state.cwd, owner, group);
     902                 : #else
     903                 :                 ret = -1;
     904                 : #endif
     905                 :         } else {
     906               0 :                 ret = chown(new_state.cwd, owner, group);
     907                 :         }
     908                 : 
     909               0 :         CWD_STATE_FREE(&new_state);
     910               0 :         return ret;
     911                 : }
     912                 : #endif
     913                 : 
     914                 : CWD_API int virtual_open(const char *path TSRMLS_DC, int flags, ...)
     915               0 : {
     916                 :         cwd_state new_state;
     917                 :         int f;
     918                 : 
     919               0 :         CWD_STATE_COPY(&new_state, &CWDG(cwd));
     920               0 :         if (virtual_file_ex(&new_state, path, NULL, CWD_FILEPATH)) {
     921               0 :                 CWD_STATE_FREE(&new_state);
     922               0 :                 return -1;
     923                 :         }
     924                 : 
     925               0 :         if (flags & O_CREAT) {
     926                 :                 mode_t mode;
     927                 :                 va_list arg;
     928                 : 
     929               0 :                 va_start(arg, flags);
     930               0 :                 mode = (mode_t) va_arg(arg, int);
     931               0 :                 va_end(arg);
     932                 : 
     933               0 :                 f = open(new_state.cwd, flags, mode);
     934                 :         } else {
     935               0 :                 f = open(new_state.cwd, flags);
     936                 :         }       
     937               0 :         CWD_STATE_FREE(&new_state);
     938               0 :         return f;
     939                 : }
     940                 : 
     941                 : CWD_API int virtual_creat(const char *path, mode_t mode TSRMLS_DC)
     942               0 : {
     943                 :         cwd_state new_state;
     944                 :         int f;
     945                 : 
     946               0 :         CWD_STATE_COPY(&new_state, &CWDG(cwd));
     947               0 :         if (virtual_file_ex(&new_state, path, NULL, CWD_FILEPATH)) {
     948               0 :                 CWD_STATE_FREE(&new_state);
     949               0 :                 return -1;
     950                 :         }
     951                 : 
     952               0 :         f = creat(new_state.cwd,  mode);
     953                 : 
     954               0 :         CWD_STATE_FREE(&new_state);
     955               0 :         return f;
     956                 : }
     957                 : 
     958                 : CWD_API int virtual_rename(char *oldname, char *newname TSRMLS_DC)
     959               0 : {
     960                 :         cwd_state old_state;
     961                 :         cwd_state new_state;
     962                 :         int retval;
     963                 : 
     964               0 :         CWD_STATE_COPY(&old_state, &CWDG(cwd));
     965               0 :         if (virtual_file_ex(&old_state, oldname, NULL, CWD_REALPATH)) {
     966               0 :                 CWD_STATE_FREE(&old_state);
     967               0 :                 return -1;
     968                 :         }
     969               0 :         oldname = old_state.cwd;
     970                 : 
     971               0 :         CWD_STATE_COPY(&new_state, &CWDG(cwd));
     972               0 :         if (virtual_file_ex(&new_state, newname, NULL, CWD_FILEPATH)) {
     973               0 :                 CWD_STATE_FREE(&old_state);
     974               0 :                 CWD_STATE_FREE(&new_state);
     975               0 :                 return -1;
     976                 :         }
     977               0 :         newname = new_state.cwd;
     978                 :  
     979               0 :         retval = rename(oldname, newname);
     980                 : 
     981               0 :         CWD_STATE_FREE(&old_state);
     982               0 :         CWD_STATE_FREE(&new_state);
     983                 : 
     984               0 :         return retval;
     985                 : }
     986                 : 
     987                 : CWD_API int virtual_stat(const char *path, struct stat *buf TSRMLS_DC)
     988               0 : {
     989                 :         cwd_state new_state;
     990                 :         int retval;
     991                 : 
     992               0 :         CWD_STATE_COPY(&new_state, &CWDG(cwd));
     993               0 :         if (virtual_file_ex(&new_state, path, NULL, CWD_REALPATH)) {
     994               0 :                 CWD_STATE_FREE(&new_state);
     995               0 :                 return -1;
     996                 :         }
     997                 : 
     998               0 :         retval = php_sys_stat(new_state.cwd, buf);
     999                 : 
    1000               0 :         CWD_STATE_FREE(&new_state);
    1001               0 :         return retval;
    1002                 : }
    1003                 : 
    1004                 : #if !defined(TSRM_WIN32)
    1005                 : CWD_API int virtual_lstat(const char *path, struct stat *buf TSRMLS_DC)
    1006               0 : {
    1007                 :         cwd_state new_state;
    1008                 :         int retval;
    1009                 : 
    1010               0 :         CWD_STATE_COPY(&new_state, &CWDG(cwd));
    1011               0 :         if (virtual_file_ex(&new_state, path, NULL, CWD_REALPATH)) {
    1012               0 :                 CWD_STATE_FREE(&new_state);
    1013               0 :                 return -1;
    1014                 :         }
    1015                 : 
    1016               0 :         retval = lstat(new_state.cwd, buf);
    1017                 : 
    1018               0 :         CWD_STATE_FREE(&new_state);
    1019               0 :         return retval;
    1020                 : }
    1021                 : #endif
    1022                 : 
    1023                 : CWD_API int virtual_unlink(const char *path TSRMLS_DC)
    1024               0 : {
    1025                 :         cwd_state new_state;
    1026                 :         int retval;
    1027                 : 
    1028               0 :         CWD_STATE_COPY(&new_state, &CWDG(cwd));
    1029               0 :         if (virtual_file_ex(&new_state, path, NULL, CWD_EXPAND)) {
    1030               0 :                 CWD_STATE_FREE(&new_state);
    1031               0 :                 return -1;
    1032                 :         }
    1033                 : 
    1034               0 :         retval = unlink(new_state.cwd);
    1035                 : 
    1036               0 :         CWD_STATE_FREE(&new_state);
    1037               0 :         return retval;
    1038                 : }
    1039                 : 
    1040                 : CWD_API int virtual_mkdir(const char *pathname, mode_t mode TSRMLS_DC)
    1041               0 : {
    1042                 :         cwd_state new_state;
    1043                 :         int retval;
    1044                 : 
    1045               0 :         CWD_STATE_COPY(&new_state, &CWDG(cwd));
    1046               0 :         if (virtual_file_ex(&new_state, pathname, NULL, CWD_FILEPATH)) {
    1047               0 :                 CWD_STATE_FREE(&new_state);
    1048               0 :                 return -1;
    1049                 :         }
    1050                 : 
    1051                 : #ifdef TSRM_WIN32
    1052                 :         retval = mkdir(new_state.cwd);
    1053                 : #else
    1054               0 :         retval = mkdir(new_state.cwd, mode);
    1055                 : #endif
    1056               0 :         CWD_STATE_FREE(&new_state);
    1057               0 :         return retval;
    1058                 : }
    1059                 : 
    1060                 : CWD_API int virtual_rmdir(const char *pathname TSRMLS_DC)
    1061               0 : {
    1062                 :         cwd_state new_state;
    1063                 :         int retval;
    1064                 : 
    1065               0 :         CWD_STATE_COPY(&new_state, &CWDG(cwd));
    1066               0 :         if (virtual_file_ex(&new_state, pathname, NULL, CWD_EXPAND)) {
    1067               0 :                 CWD_STATE_FREE(&new_state);
    1068               0 :                 return -1;
    1069                 :         }
    1070                 : 
    1071               0 :         retval = rmdir(new_state.cwd);
    1072                 : 
    1073               0 :         CWD_STATE_FREE(&new_state);
    1074               0 :         return retval;
    1075                 : }
    1076                 : 
    1077                 : #ifdef TSRM_WIN32
    1078                 : DIR *opendir(const char *name);
    1079                 : #endif
    1080                 : 
    1081                 : CWD_API DIR *virtual_opendir(const char *pathname TSRMLS_DC)
    1082               0 : {
    1083                 :         cwd_state new_state;
    1084                 :         DIR *retval;
    1085                 : 
    1086               0 :         CWD_STATE_COPY(&new_state, &CWDG(cwd));
    1087               0 :         if (virtual_file_ex(&new_state, pathname, NULL, CWD_REALPATH)) {
    1088               0 :                 CWD_STATE_FREE(&new_state);
    1089               0 :                 return NULL;
    1090                 :         }
    1091                 : 
    1092               0 :         retval = opendir(new_state.cwd);
    1093                 : 
    1094               0 :         CWD_STATE_FREE(&new_state);
    1095               0 :         return retval;
    1096                 : }
    1097                 : 
    1098                 : #ifdef TSRM_WIN32
    1099                 : 
    1100                 : CWD_API FILE *virtual_popen(const char *command, const char *type TSRMLS_DC)
    1101                 : {
    1102                 :         return popen_ex(command, type, CWDG(cwd).cwd, NULL);
    1103                 : }
    1104                 : 
    1105                 : #elif defined(NETWARE)
    1106                 : 
    1107                 : /* On NetWare, the trick of prepending "cd cwd; " doesn't work so we need to perform
    1108                 :    a VCWD_CHDIR() and mutex it
    1109                 :  */
    1110                 : CWD_API FILE *virtual_popen(const char *command, const char *type TSRMLS_DC)
    1111                 : {
    1112                 :         char prev_cwd[MAXPATHLEN];
    1113                 :         char *getcwd_result;
    1114                 :         FILE *retval;
    1115                 : 
    1116                 :         getcwd_result = VCWD_GETCWD(prev_cwd, MAXPATHLEN);
    1117                 :         if (!getcwd_result) {
    1118                 :                 return NULL;
    1119                 :         }
    1120                 : 
    1121                 : #ifdef ZTS
    1122                 :         tsrm_mutex_lock(cwd_mutex);
    1123                 : #endif
    1124                 : 
    1125                 :         VCWD_CHDIR(CWDG(cwd).cwd);
    1126                 :         retval = popen(command, type);
    1127                 :         VCWD_CHDIR(prev_cwd);
    1128                 : 
    1129                 : #ifdef ZTS
    1130                 :         tsrm_mutex_unlock(cwd_mutex);
    1131                 : #endif
    1132                 : 
    1133                 :         return retval;
    1134                 : }
    1135                 : 
    1136                 : #else /* Unix */
    1137                 : 
    1138                 : CWD_API FILE *virtual_popen(const char *command, const char *type TSRMLS_DC)
    1139               0 : {
    1140                 :         int command_length;
    1141               0 :         int dir_length, extra = 0;
    1142                 :         char *command_line;
    1143                 :         char *ptr, *dir;
    1144                 :         FILE *retval;
    1145                 : 
    1146               0 :         command_length = strlen(command);
    1147                 : 
    1148               0 :         dir_length = CWDG(cwd).cwd_length;
    1149               0 :         dir = CWDG(cwd).cwd;
    1150               0 :         while (dir_length > 0) {
    1151               0 :                 if (*dir == '\'') extra+=3;
    1152               0 :                 dir++;
    1153               0 :                 dir_length--;
    1154                 :         }
    1155               0 :         dir_length = CWDG(cwd).cwd_length;
    1156               0 :         dir = CWDG(cwd).cwd;
    1157                 : 
    1158               0 :         ptr = command_line = (char *) malloc(command_length + sizeof("cd '' ; ") + dir_length + extra+1+1);
    1159               0 :         if (!command_line) {
    1160               0 :                 return NULL;
    1161                 :         }
    1162               0 :         memcpy(ptr, "cd ", sizeof("cd ")-1);
    1163               0 :         ptr += sizeof("cd ")-1;
    1164                 : 
    1165               0 :         if (CWDG(cwd).cwd_length == 0) {
    1166               0 :                 *ptr++ = DEFAULT_SLASH;
    1167                 :         } else {
    1168               0 :                 *ptr++ = '\'';
    1169               0 :                 while (dir_length > 0) {
    1170               0 :                         switch (*dir) {
    1171                 :                         case '\'':
    1172               0 :                                 *ptr++ = '\'';
    1173               0 :                                 *ptr++ = '\\';
    1174               0 :                                 *ptr++ = '\'';
    1175                 :                                 /* fall-through */
    1176                 :                         default:
    1177               0 :                                 *ptr++ = *dir;
    1178                 :                         }
    1179               0 :                         dir++;
    1180               0 :                         dir_length--;
    1181                 :                 }
    1182               0 :                 *ptr++ = '\'';
    1183                 :         }
    1184                 :         
    1185               0 :         *ptr++ = ' ';
    1186               0 :         *ptr++ = ';';
    1187               0 :         *ptr++ = ' ';
    1188                 : 
    1189               0 :         memcpy(ptr, command, command_length+1);
    1190               0 :         retval = popen(command_line, type);
    1191                 : 
    1192               0 :         free(command_line);
    1193               0 :         return retval;
    1194                 : }
    1195                 : 
    1196                 : #endif
    1197                 : 
    1198                 : CWD_API char *tsrm_realpath(const char *path, char *real_path TSRMLS_DC)
    1199             330 : {
    1200                 :         cwd_state new_state;
    1201                 :         char cwd[MAXPATHLEN];
    1202                 : 
    1203             332 :         if (!IS_ABSOLUTE_PATH(path, strlen(path)) &&
    1204                 :             VCWD_GETCWD(cwd, MAXPATHLEN)) {
    1205               2 :                 new_state.cwd = strdup(cwd);
    1206               2 :                 new_state.cwd_length = strlen(cwd);
    1207                 :         } else {
    1208             328 :                 new_state.cwd = (char*)malloc(1);
    1209             328 :                 new_state.cwd[0] = '\0';
    1210             328 :                 new_state.cwd_length = 0;               
    1211                 :         }
    1212                 : 
    1213             330 :         if (virtual_file_ex(&new_state, path, NULL, CWD_REALPATH)) {
    1214               0 :                 free(new_state.cwd);
    1215               0 :                 return NULL;
    1216                 :         }
    1217                 : 
    1218             330 :         if (real_path) {
    1219             222 :                 int copy_len = new_state.cwd_length>MAXPATHLEN-1 ? MAXPATHLEN-1 : new_state.cwd_length;
    1220             222 :                 memcpy(real_path, new_state.cwd, copy_len);
    1221             222 :                 real_path[copy_len] = '\0';
    1222             222 :                 free(new_state.cwd);
    1223             222 :                 return real_path;
    1224                 :         } else {
    1225             108 :                 return new_state.cwd;
    1226                 :         }
    1227                 : }
    1228                 : 
    1229                 : 
    1230                 : /*
    1231                 :  * Local variables:
    1232                 :  * tab-width: 4
    1233                 :  * c-basic-offset: 4
    1234                 :  * End:
    1235                 :  */

Generated by: LTP GCOV extension version 1.5