root/ext/standard/filestat.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. PHP_RINIT_FUNCTION
  2. PHP_RSHUTDOWN_FUNCTION
  3. php_disk_total_space
  4. PHP_FUNCTION
  5. php_disk_free_space
  6. PHP_FUNCTION
  7. php_get_gid_by_name
  8. php_do_chgrp
  9. PHP_FUNCTION
  10. PHP_FUNCTION
  11. php_get_uid_by_name
  12. php_do_chown
  13. PHP_FUNCTION
  14. PHP_FUNCTION
  15. PHP_FUNCTION
  16. PHP_FUNCTION
  17. php_clear_stat_cache
  18. PHP_FUNCTION
  19. php_stat
  20. FileFunction
  21. PHP_FUNCTION

   1 /*
   2    +----------------------------------------------------------------------+
   3    | PHP Version 5                                                        |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1997-2016 The PHP Group                                |
   6    +----------------------------------------------------------------------+
   7    | This source file is subject to version 3.01 of the PHP license,      |
   8    | that is bundled with this package in the file LICENSE, and is        |
   9    | available through the world-wide-web at the following url:           |
  10    | http://www.php.net/license/3_01.txt                                  |
  11    | If you did not receive a copy of the PHP license and are unable to   |
  12    | obtain it through the world-wide-web, please send a note to          |
  13    | license@php.net so we can mail you a copy immediately.               |
  14    +----------------------------------------------------------------------+
  15    | Author:  Jim Winstead <jimw@php.net>                                 |
  16    +----------------------------------------------------------------------+
  17  */
  18 
  19 /* $Id$ */
  20 
  21 #include "php.h"
  22 #include "fopen_wrappers.h"
  23 #include "php_globals.h"
  24 
  25 #include <stdlib.h>
  26 #include <sys/stat.h>
  27 #include <string.h>
  28 #include <errno.h>
  29 #include <ctype.h>
  30 #include <time.h>
  31 
  32 #if HAVE_UNISTD_H
  33 # include <unistd.h>
  34 #endif
  35 
  36 #if HAVE_SYS_PARAM_H
  37 # include <sys/param.h>
  38 #endif
  39 
  40 #if HAVE_SYS_VFS_H
  41 # include <sys/vfs.h>
  42 #endif
  43 
  44 #ifdef OS2
  45 #  define INCL_DOS
  46 #  include <os2.h>
  47 #endif
  48 
  49 #if defined(HAVE_SYS_STATVFS_H) && defined(HAVE_STATVFS)
  50 # include <sys/statvfs.h>
  51 #elif defined(HAVE_SYS_STATFS_H) && defined(HAVE_STATFS)
  52 # include <sys/statfs.h>
  53 #elif defined(HAVE_SYS_MOUNT_H) && defined(HAVE_STATFS)
  54 # include <sys/mount.h>
  55 #endif
  56 
  57 #if HAVE_PWD_H
  58 # ifdef PHP_WIN32
  59 #  include "win32/pwd.h"
  60 # else
  61 #  include <pwd.h>
  62 # endif
  63 #endif
  64 
  65 #if HAVE_GRP_H
  66 # ifdef PHP_WIN32
  67 #  include "win32/grp.h"
  68 # else
  69 #  include <grp.h>
  70 # endif
  71 #endif
  72 
  73 #if HAVE_UTIME
  74 # ifdef PHP_WIN32
  75 #  include <sys/utime.h>
  76 # else
  77 #  include <utime.h>
  78 # endif
  79 #endif
  80 
  81 #ifdef PHP_WIN32
  82 #include "win32/winutil.h"
  83 #endif
  84 
  85 #include "basic_functions.h"
  86 #include "php_filestat.h"
  87 
  88 #ifndef S_ISDIR
  89 #define S_ISDIR(mode)   (((mode)&S_IFMT) == S_IFDIR)
  90 #endif
  91 #ifndef S_ISREG
  92 #define S_ISREG(mode)   (((mode)&S_IFMT) == S_IFREG)
  93 #endif
  94 #ifndef S_ISLNK
  95 #define S_ISLNK(mode)   (((mode)&S_IFMT) == S_IFLNK)
  96 #endif
  97 
  98 #define S_IXROOT ( S_IXUSR | S_IXGRP | S_IXOTH )
  99 
 100 PHP_RINIT_FUNCTION(filestat) /* {{{ */
 101 {
 102         BG(CurrentStatFile)=NULL;
 103         BG(CurrentLStatFile)=NULL;
 104         return SUCCESS;
 105 }
 106 /* }}} */
 107 
 108 PHP_RSHUTDOWN_FUNCTION(filestat) /* {{{ */
 109 {
 110         if (BG(CurrentStatFile)) {
 111                 efree (BG(CurrentStatFile));
 112                 BG(CurrentStatFile) = NULL;
 113         }
 114         if (BG(CurrentLStatFile)) {
 115                 efree (BG(CurrentLStatFile));
 116                 BG(CurrentLStatFile) = NULL;
 117         }
 118         return SUCCESS;
 119 }
 120 /* }}} */
 121 
 122 static int php_disk_total_space(char *path, double *space TSRMLS_DC) /* {{{ */
 123 #if defined(WINDOWS) /* {{{ */
 124 {
 125         double bytestotal = 0;
 126         HINSTANCE kernel32;
 127         FARPROC gdfse;
 128         typedef BOOL (WINAPI *gdfse_func)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
 129         gdfse_func func;
 130 
 131         /* These are used by GetDiskFreeSpaceEx, if available. */
 132         ULARGE_INTEGER FreeBytesAvailableToCaller;
 133         ULARGE_INTEGER TotalNumberOfBytes;
 134         ULARGE_INTEGER TotalNumberOfFreeBytes;
 135 
 136         /* These are used by GetDiskFreeSpace otherwise. */
 137         DWORD SectorsPerCluster;
 138         DWORD BytesPerSector;
 139         DWORD NumberOfFreeClusters;
 140         DWORD TotalNumberOfClusters;
 141 
 142         /* GetDiskFreeSpaceEx is only available in NT and Win95 post-OSR2,
 143            so we have to jump through some hoops to see if the function
 144            exists. */
 145         kernel32 = LoadLibrary("kernel32.dll");
 146         if (kernel32) {
 147                 gdfse = GetProcAddress(kernel32, "GetDiskFreeSpaceExA");
 148                 /* It's available, so we can call it. */
 149                 if (gdfse) {
 150                         func = (gdfse_func)gdfse;
 151                         if (func(path,
 152                                                 &FreeBytesAvailableToCaller,
 153                                                 &TotalNumberOfBytes,
 154                                                 &TotalNumberOfFreeBytes) == 0) {
 155                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", php_win_err());
 156                                 return FAILURE;
 157                         }
 158 
 159                         /* i know - this is ugly, but i works <thies@thieso.net> */
 160                         bytestotal  = TotalNumberOfBytes.HighPart *
 161                                 (double) (((unsigned long)1) << 31) * 2.0 +
 162                                 TotalNumberOfBytes.LowPart;
 163                 } else { /* If it's not available, we just use GetDiskFreeSpace */
 164                         if (GetDiskFreeSpace(path,
 165                                                 &SectorsPerCluster, &BytesPerSector,
 166                                                 &NumberOfFreeClusters, &TotalNumberOfClusters) == 0) {
 167                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", php_win_err());
 168                                 return FAILURE;
 169                         }
 170                         bytestotal = (double)TotalNumberOfClusters * (double)SectorsPerCluster * (double)BytesPerSector;
 171                 }
 172         } else {
 173                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to load kernel32.dll");
 174                 return FAILURE;
 175         }
 176 
 177         *space = bytestotal;
 178         return SUCCESS;
 179 }
 180 /* }}} */
 181 #elif defined(OS2) /* {{{ */
 182 {
 183         double bytestotal = 0;
 184         FSALLOCATE fsinfo;
 185         char drive = path[0] & 95;
 186 
 187         if (DosQueryFSInfo( drive ? drive - 64 : 0, FSIL_ALLOC, &fsinfo, sizeof( fsinfo ) ) == 0) {
 188                 bytestotal = (double)fsinfo.cbSector * fsinfo.cSectorUnit * fsinfo.cUnit;
 189                 *space = bytestotal;
 190                 return SUCCESS;
 191         }
 192         return FAILURE;
 193 }
 194 /* }}} */
 195 #else /* {{{ if !defined(OS2) && !defined(WINDOWS) */
 196 {
 197         double bytestotal = 0;
 198 #if defined(HAVE_SYS_STATVFS_H) && defined(HAVE_STATVFS)
 199         struct statvfs buf;
 200 #elif (defined(HAVE_SYS_STATFS_H) || defined(HAVE_SYS_MOUNT_H)) && defined(HAVE_STATFS)
 201         struct statfs buf;
 202 #endif
 203 
 204 #if defined(HAVE_SYS_STATVFS_H) && defined(HAVE_STATVFS)
 205         if (statvfs(path, &buf)) {
 206                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
 207                 return FAILURE;
 208         }
 209         if (buf.f_frsize) {
 210                 bytestotal = (((double)buf.f_blocks) * ((double)buf.f_frsize));
 211         } else {
 212                 bytestotal = (((double)buf.f_blocks) * ((double)buf.f_bsize));
 213         }
 214 
 215 #elif (defined(HAVE_SYS_STATFS_H) || defined(HAVE_SYS_MOUNT_H)) && defined(HAVE_STATFS)
 216         if (statfs(path, &buf)) {
 217                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
 218                 return FAILURE;
 219         }
 220         bytestotal = (((double)buf.f_bsize) * ((double)buf.f_blocks));
 221 #endif
 222 
 223         *space = bytestotal;
 224         return SUCCESS;
 225 }
 226 #endif
 227 /* }}} */
 228 /* }}} */
 229 
 230 /* {{{ proto float disk_total_space(string path)
 231    Get total disk space for filesystem that path is on */
 232 PHP_FUNCTION(disk_total_space)
 233 {
 234         double bytestotal;
 235         char *path;
 236         int path_len;
 237 
 238         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &path, &path_len) == FAILURE) {
 239                 return;
 240         }
 241 
 242         if (php_check_open_basedir(path TSRMLS_CC)) {
 243                 RETURN_FALSE;
 244         }
 245 
 246         if (php_disk_total_space(path, &bytestotal TSRMLS_CC) == SUCCESS) {
 247                 RETURN_DOUBLE(bytestotal);
 248         }
 249         RETURN_FALSE;
 250 }
 251 /* }}} */
 252 
 253 static int php_disk_free_space(char *path, double *space TSRMLS_DC) /* {{{ */
 254 #if defined(WINDOWS) /* {{{ */
 255 {
 256         double bytesfree = 0;
 257 
 258         HINSTANCE kernel32;
 259         FARPROC gdfse;
 260         typedef BOOL (WINAPI *gdfse_func)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
 261         gdfse_func func;
 262 
 263         /* These are used by GetDiskFreeSpaceEx, if available. */
 264         ULARGE_INTEGER FreeBytesAvailableToCaller;
 265         ULARGE_INTEGER TotalNumberOfBytes;
 266         ULARGE_INTEGER TotalNumberOfFreeBytes;
 267 
 268         /* These are used by GetDiskFreeSpace otherwise. */
 269         DWORD SectorsPerCluster;
 270         DWORD BytesPerSector;
 271         DWORD NumberOfFreeClusters;
 272         DWORD TotalNumberOfClusters;
 273 
 274         /* GetDiskFreeSpaceEx is only available in NT and Win95 post-OSR2,
 275            so we have to jump through some hoops to see if the function
 276            exists. */
 277         kernel32 = LoadLibrary("kernel32.dll");
 278         if (kernel32) {
 279                 gdfse = GetProcAddress(kernel32, "GetDiskFreeSpaceExA");
 280                 /* It's available, so we can call it. */
 281                 if (gdfse) {
 282                         func = (gdfse_func)gdfse;
 283                         if (func(path,
 284                                                 &FreeBytesAvailableToCaller,
 285                                                 &TotalNumberOfBytes,
 286                                                 &TotalNumberOfFreeBytes) == 0) {
 287                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", php_win_err());
 288                                 return FAILURE;
 289                         }
 290 
 291                         /* i know - this is ugly, but i works <thies@thieso.net> */
 292                         bytesfree  = FreeBytesAvailableToCaller.HighPart *
 293                                 (double) (((unsigned long)1) << 31) * 2.0 +
 294                                 FreeBytesAvailableToCaller.LowPart;
 295                 } else { /* If it's not available, we just use GetDiskFreeSpace */
 296                         if (GetDiskFreeSpace(path,
 297                                                 &SectorsPerCluster, &BytesPerSector,
 298                                                 &NumberOfFreeClusters, &TotalNumberOfClusters) == 0) {
 299                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", php_win_err());
 300                                 return FAILURE;
 301                         }
 302                         bytesfree = (double)NumberOfFreeClusters * (double)SectorsPerCluster * (double)BytesPerSector;
 303                 }
 304         } else {
 305                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to load kernel32.dll");
 306                 return FAILURE;
 307         }
 308 
 309         *space = bytesfree;
 310         return SUCCESS;
 311 }
 312 /* }}} */
 313 #elif defined(OS2) /* {{{ */
 314 {
 315         double bytesfree = 0;
 316         FSALLOCATE fsinfo;
 317         char drive = path[0] & 95;
 318 
 319         if (DosQueryFSInfo( drive ? drive - 64 : 0, FSIL_ALLOC, &fsinfo, sizeof( fsinfo ) ) == 0) {
 320                 bytesfree = (double)fsinfo.cbSector * fsinfo.cSectorUnit * fsinfo.cUnitAvail;
 321                 *space = bytesfree;
 322                 return SUCCESS;
 323         }
 324         return FAILURE;
 325 }
 326 /* }}} */
 327 #else /* {{{ if !defined(OS2) && !defined(WINDOWS) */
 328 {
 329         double bytesfree = 0;
 330 #if defined(HAVE_SYS_STATVFS_H) && defined(HAVE_STATVFS)
 331         struct statvfs buf;
 332 #elif (defined(HAVE_SYS_STATFS_H) || defined(HAVE_SYS_MOUNT_H)) && defined(HAVE_STATFS)
 333         struct statfs buf;
 334 #endif
 335 
 336 #if defined(HAVE_SYS_STATVFS_H) && defined(HAVE_STATVFS)
 337         if (statvfs(path, &buf)) {
 338                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
 339                 return FAILURE;
 340         }
 341         if (buf.f_frsize) {
 342                 bytesfree = (((double)buf.f_bavail) * ((double)buf.f_frsize));
 343         } else {
 344                 bytesfree = (((double)buf.f_bavail) * ((double)buf.f_bsize));
 345         }
 346 #elif (defined(HAVE_SYS_STATFS_H) || defined(HAVE_SYS_MOUNT_H)) && defined(HAVE_STATFS)
 347         if (statfs(path, &buf)) {
 348                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
 349                 return FAILURE;
 350         }
 351 #ifdef NETWARE
 352         bytesfree = (((double)buf.f_bsize) * ((double)buf.f_bfree));
 353 #else
 354         bytesfree = (((double)buf.f_bsize) * ((double)buf.f_bavail));
 355 #endif
 356 #endif
 357 
 358         *space = bytesfree;
 359         return SUCCESS;
 360 }
 361 #endif
 362 /* }}} */
 363 /* }}} */
 364 
 365 /* {{{ proto float disk_free_space(string path)
 366    Get free disk space for filesystem that path is on */
 367 PHP_FUNCTION(disk_free_space)
 368 {
 369         double bytesfree;
 370         char *path;
 371         int path_len;
 372 
 373         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &path, &path_len) == FAILURE) {
 374                 return;
 375         }
 376 
 377         if (php_check_open_basedir(path TSRMLS_CC)) {
 378                 RETURN_FALSE;
 379         }
 380 
 381         if (php_disk_free_space(path, &bytesfree TSRMLS_CC) == SUCCESS) {
 382                 RETURN_DOUBLE(bytesfree);
 383         }
 384         RETURN_FALSE;
 385 }
 386 /* }}} */
 387 
 388 #if !defined(WINDOWS) && !defined(NETWARE)
 389 PHPAPI int php_get_gid_by_name(const char *name, gid_t *gid TSRMLS_DC)
 390 {
 391 #if defined(ZTS) && defined(HAVE_GETGRNAM_R) && defined(_SC_GETGR_R_SIZE_MAX)
 392                 struct group gr;
 393                 struct group *retgrptr;
 394                 long grbuflen = sysconf(_SC_GETGR_R_SIZE_MAX);
 395                 char *grbuf;
 396 
 397                 if (grbuflen < 1) {
 398                         return FAILURE;
 399                 }
 400 
 401                 grbuf = emalloc(grbuflen);
 402                 if (getgrnam_r(name, &gr, grbuf, grbuflen, &retgrptr) != 0 || retgrptr == NULL) {
 403                         efree(grbuf);
 404                         return FAILURE;
 405                 }
 406                 efree(grbuf);
 407                 *gid = gr.gr_gid;
 408 #else
 409                 struct group *gr = getgrnam(name);
 410 
 411                 if (!gr) {
 412                         return FAILURE;
 413                 }
 414                 *gid = gr->gr_gid;
 415 #endif
 416                 return SUCCESS;
 417 }
 418 #endif
 419 
 420 static void php_do_chgrp(INTERNAL_FUNCTION_PARAMETERS, int do_lchgrp) /* {{{ */
 421 {
 422         char *filename;
 423         int filename_len;
 424         zval *group;
 425 #if !defined(WINDOWS)
 426         gid_t gid;
 427         int ret;
 428 #endif
 429         php_stream_wrapper *wrapper;
 430 
 431         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pz/", &filename, &filename_len, &group) == FAILURE) {
 432                 RETURN_FALSE;
 433         }
 434 
 435         wrapper = php_stream_locate_url_wrapper(filename, NULL, 0 TSRMLS_CC);
 436         if(wrapper != &php_plain_files_wrapper || strncasecmp("file://", filename, 7) == 0) {
 437                 if(wrapper && wrapper->wops->stream_metadata) {
 438                         int option;
 439                         void *value;
 440                         if (Z_TYPE_P(group) == IS_LONG) {
 441                                 option = PHP_STREAM_META_GROUP;
 442                                 value = &Z_LVAL_P(group);
 443                         } else if (Z_TYPE_P(group) == IS_STRING) {
 444                                 option = PHP_STREAM_META_GROUP_NAME;
 445                                 value = Z_STRVAL_P(group);
 446                         } else {
 447                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "parameter 2 should be string or integer, %s given", zend_zval_type_name(group));
 448                                 RETURN_FALSE;
 449                         }
 450                         if(wrapper->wops->stream_metadata(wrapper, filename, option, value, NULL TSRMLS_CC)) {
 451                                 RETURN_TRUE;
 452                         } else {
 453                                 RETURN_FALSE;
 454                         }
 455                 } else {
 456 #if !defined(WINDOWS)
 457 /* On Windows, we expect regular chgrp to fail silently by default */
 458                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can not call chgrp() for a non-standard stream");
 459 #endif
 460                         RETURN_FALSE;
 461                 }
 462         }
 463 
 464 #if defined(WINDOWS)
 465         /* We have no native chgrp on Windows, nothing left to do if stream doesn't have own implementation */
 466         RETURN_FALSE;
 467 #else
 468         if (Z_TYPE_P(group) == IS_LONG) {
 469                 gid = (gid_t)Z_LVAL_P(group);
 470         } else if (Z_TYPE_P(group) == IS_STRING) {
 471                 if(php_get_gid_by_name(Z_STRVAL_P(group), &gid TSRMLS_CC) != SUCCESS) {
 472                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find gid for %s", Z_STRVAL_P(group));
 473                         RETURN_FALSE;
 474                 }
 475         } else {
 476                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "parameter 2 should be string or integer, %s given", zend_zval_type_name(group));
 477                 RETURN_FALSE;
 478         }
 479 
 480         /* Check the basedir */
 481         if (php_check_open_basedir(filename TSRMLS_CC)) {
 482                 RETURN_FALSE;
 483         }
 484 
 485         if (do_lchgrp) {
 486 #if HAVE_LCHOWN
 487                 ret = VCWD_LCHOWN(filename, -1, gid);
 488 #endif
 489         } else {
 490                 ret = VCWD_CHOWN(filename, -1, gid);
 491         }
 492         if (ret == -1) {
 493                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
 494                 RETURN_FALSE;
 495         }
 496         RETURN_TRUE;
 497 #endif
 498 }
 499 /* }}} */
 500 
 501 #ifndef NETWARE
 502 /* {{{ proto bool chgrp(string filename, mixed group)
 503    Change file group */
 504 PHP_FUNCTION(chgrp)
 505 {
 506         php_do_chgrp(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
 507 }
 508 /* }}} */
 509 
 510 /* {{{ proto bool lchgrp(string filename, mixed group)
 511    Change symlink group */
 512 #if HAVE_LCHOWN
 513 PHP_FUNCTION(lchgrp)
 514 {
 515 # if !defined(WINDOWS)
 516         php_do_chgrp(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
 517 # else
 518         RETURN_FALSE;
 519 # endif
 520 }
 521 #endif
 522 /* }}} */
 523 #endif /* !NETWARE */
 524 
 525 #if !defined(WINDOWS) && !defined(NETWARE)
 526 PHPAPI uid_t php_get_uid_by_name(const char *name, uid_t *uid TSRMLS_DC)
 527 {
 528 #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWNAM_R)
 529                 struct passwd pw;
 530                 struct passwd *retpwptr = NULL;
 531                 long pwbuflen = sysconf(_SC_GETPW_R_SIZE_MAX);
 532                 char *pwbuf;
 533 
 534                 if (pwbuflen < 1) {
 535                         return FAILURE;
 536                 }
 537 
 538                 pwbuf = emalloc(pwbuflen);
 539                 if (getpwnam_r(name, &pw, pwbuf, pwbuflen, &retpwptr) != 0 || retpwptr == NULL) {
 540                         efree(pwbuf);
 541                         return FAILURE;
 542                 }
 543                 efree(pwbuf);
 544                 *uid = pw.pw_uid;
 545 #else
 546                 struct passwd *pw = getpwnam(name);
 547 
 548                 if (!pw) {
 549                         return FAILURE;
 550                 }
 551                 *uid = pw->pw_uid;
 552 #endif
 553                 return SUCCESS;
 554 }
 555 #endif
 556 
 557 static void php_do_chown(INTERNAL_FUNCTION_PARAMETERS, int do_lchown) /* {{{ */
 558 {
 559         char *filename;
 560         int filename_len;
 561         zval *user;
 562 #if !defined(WINDOWS)
 563         uid_t uid;
 564         int ret;
 565 #endif
 566         php_stream_wrapper *wrapper;
 567 
 568         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pz/", &filename, &filename_len, &user) == FAILURE) {
 569                 return;
 570         }
 571 
 572         wrapper = php_stream_locate_url_wrapper(filename, NULL, 0 TSRMLS_CC);
 573         if(wrapper != &php_plain_files_wrapper || strncasecmp("file://", filename, 7) == 0) {
 574                 if(wrapper && wrapper->wops->stream_metadata) {
 575                         int option;
 576                         void *value;
 577                         if (Z_TYPE_P(user) == IS_LONG) {
 578                                 option = PHP_STREAM_META_OWNER;
 579                                 value = &Z_LVAL_P(user);
 580                         } else if (Z_TYPE_P(user) == IS_STRING) {
 581                                 option = PHP_STREAM_META_OWNER_NAME;
 582                                 value = Z_STRVAL_P(user);
 583                         } else {
 584                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "parameter 2 should be string or integer, %s given", zend_zval_type_name(user));
 585                                 RETURN_FALSE;
 586                         }
 587                         if(wrapper->wops->stream_metadata(wrapper, filename, option, value, NULL TSRMLS_CC)) {
 588                                 RETURN_TRUE;
 589                         } else {
 590                                 RETURN_FALSE;
 591                         }
 592                 } else {
 593 #if !defined(WINDOWS)
 594 /* On Windows, we expect regular chown to fail silently by default */
 595                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can not call chown() for a non-standard stream");
 596 #endif
 597                         RETURN_FALSE;
 598                 }
 599         }
 600 
 601 #if defined(WINDOWS)
 602         /* We have no native chown on Windows, nothing left to do if stream doesn't have own implementation */
 603         RETURN_FALSE;
 604 #else
 605 
 606         if (Z_TYPE_P(user) == IS_LONG) {
 607                 uid = (uid_t)Z_LVAL_P(user);
 608         } else if (Z_TYPE_P(user) == IS_STRING) {
 609                 if(php_get_uid_by_name(Z_STRVAL_P(user), &uid TSRMLS_CC) != SUCCESS) {
 610                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find uid for %s", Z_STRVAL_P(user));
 611                         RETURN_FALSE;
 612                 }
 613         } else {
 614                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "parameter 2 should be string or integer, %s given", zend_zval_type_name(user));
 615                 RETURN_FALSE;
 616         }
 617 
 618         /* Check the basedir */
 619         if (php_check_open_basedir(filename TSRMLS_CC)) {
 620                 RETURN_FALSE;
 621         }
 622 
 623         if (do_lchown) {
 624 #if HAVE_LCHOWN
 625                 ret = VCWD_LCHOWN(filename, uid, -1);
 626 #endif
 627         } else {
 628                 ret = VCWD_CHOWN(filename, uid, -1);
 629         }
 630         if (ret == -1) {
 631                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
 632                 RETURN_FALSE;
 633         }
 634         RETURN_TRUE;
 635 #endif
 636 }
 637 /* }}} */
 638 
 639 
 640 #ifndef NETWARE
 641 /* {{{ proto bool chown (string filename, mixed user)
 642    Change file owner */
 643 PHP_FUNCTION(chown)
 644 {
 645         php_do_chown(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
 646 }
 647 /* }}} */
 648 
 649 /* {{{ proto bool chown (string filename, mixed user)
 650    Change file owner */
 651 #if HAVE_LCHOWN
 652 PHP_FUNCTION(lchown)
 653 {
 654 # if !defined(WINDOWS)
 655         RETVAL_TRUE;
 656         php_do_chown(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
 657 # else
 658         RETURN_FALSE;
 659 # endif
 660 }
 661 #endif
 662 /* }}} */
 663 #endif /* !NETWARE */
 664 
 665 /* {{{ proto bool chmod(string filename, int mode)
 666    Change file mode */
 667 PHP_FUNCTION(chmod)
 668 {
 669         char *filename;
 670         int filename_len;
 671         long mode;
 672         int ret;
 673         mode_t imode;
 674         php_stream_wrapper *wrapper;
 675 
 676         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pl", &filename, &filename_len, &mode) == FAILURE) {
 677                 return;
 678         }
 679 
 680         wrapper = php_stream_locate_url_wrapper(filename, NULL, 0 TSRMLS_CC);
 681         if(wrapper != &php_plain_files_wrapper || strncasecmp("file://", filename, 7) == 0) {
 682                 if(wrapper && wrapper->wops->stream_metadata) {
 683                         if(wrapper->wops->stream_metadata(wrapper, filename, PHP_STREAM_META_ACCESS, &mode, NULL TSRMLS_CC)) {
 684                                 RETURN_TRUE;
 685                         } else {
 686                                 RETURN_FALSE;
 687                         }
 688                 } else {
 689                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can not call chmod() for a non-standard stream");
 690                         RETURN_FALSE;
 691                 }
 692         }
 693 
 694         /* Check the basedir */
 695         if (php_check_open_basedir(filename TSRMLS_CC)) {
 696                 RETURN_FALSE;
 697         }
 698 
 699         imode = (mode_t) mode;
 700 
 701         ret = VCWD_CHMOD(filename, imode);
 702         if (ret == -1) {
 703                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
 704                 RETURN_FALSE;
 705         }
 706         RETURN_TRUE;
 707 }
 708 /* }}} */
 709 
 710 #if HAVE_UTIME
 711 /* {{{ proto bool touch(string filename [, int time [, int atime]])
 712    Set modification time of file */
 713 PHP_FUNCTION(touch)
 714 {
 715         char *filename;
 716         int filename_len;
 717         long filetime = 0, fileatime = 0;
 718         int ret, argc = ZEND_NUM_ARGS();
 719         FILE *file;
 720         struct utimbuf newtimebuf;
 721         struct utimbuf *newtime = &newtimebuf;
 722         php_stream_wrapper *wrapper;
 723 
 724         if (zend_parse_parameters(argc TSRMLS_CC, "p|ll", &filename, &filename_len, &filetime, &fileatime) == FAILURE) {
 725                 return;
 726         }
 727 
 728         if (!filename_len) {
 729                 RETURN_FALSE;
 730         }
 731 
 732         switch (argc) {
 733                 case 1:
 734 #ifdef HAVE_UTIME_NULL
 735                         newtime = NULL;
 736 #else
 737                         newtime->modtime = newtime->actime = time(NULL);
 738 #endif
 739                         break;
 740                 case 2:
 741                         newtime->modtime = newtime->actime = filetime;
 742                         break;
 743                 case 3:
 744                         newtime->modtime = filetime;
 745                         newtime->actime = fileatime;
 746                         break;
 747                 default:
 748                         /* Never reached */
 749                         WRONG_PARAM_COUNT;
 750         }
 751 
 752         wrapper = php_stream_locate_url_wrapper(filename, NULL, 0 TSRMLS_CC);
 753         if(wrapper != &php_plain_files_wrapper || strncasecmp("file://", filename, 7) == 0) {
 754                 if(wrapper && wrapper->wops->stream_metadata) {
 755                         if(wrapper->wops->stream_metadata(wrapper, filename, PHP_STREAM_META_TOUCH, newtime, NULL TSRMLS_CC)) {
 756                                 RETURN_TRUE;
 757                         } else {
 758                                 RETURN_FALSE;
 759                         }
 760                 } else {
 761                         php_stream *stream;
 762                         if(argc > 1) {
 763                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can not call touch() for a non-standard stream");
 764                                 RETURN_FALSE;
 765                         }
 766                         stream = php_stream_open_wrapper_ex(filename, "c", REPORT_ERRORS, NULL, NULL);
 767                         if(stream != NULL) {
 768                                 php_stream_pclose(stream);
 769                                 RETURN_TRUE;
 770                         } else {
 771                                 RETURN_FALSE;
 772                         }
 773                 }
 774         }
 775 
 776         /* Check the basedir */
 777         if (php_check_open_basedir(filename TSRMLS_CC)) {
 778                 RETURN_FALSE;
 779         }
 780 
 781         /* create the file if it doesn't exist already */
 782         if (VCWD_ACCESS(filename, F_OK) != 0) {
 783                 file = VCWD_FOPEN(filename, "w");
 784                 if (file == NULL) {
 785                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create file %s because %s", filename, strerror(errno));
 786                         RETURN_FALSE;
 787                 }
 788                 fclose(file);
 789         }
 790 
 791         ret = VCWD_UTIME(filename, newtime);
 792         if (ret == -1) {
 793                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Utime failed: %s", strerror(errno));
 794                 RETURN_FALSE;
 795         }
 796         RETURN_TRUE;
 797 }
 798 /* }}} */
 799 #endif
 800 
 801 /* {{{ php_clear_stat_cache()
 802 */
 803 PHPAPI void php_clear_stat_cache(zend_bool clear_realpath_cache, const char *filename, int filename_len TSRMLS_DC)
 804 {
 805         /* always clear CurrentStatFile and CurrentLStatFile even if filename is not NULL
 806          * as it may contain outdated data (e.g. "nlink" for a directory when deleting a file
 807          * in this directory, as shown by lstat_stat_variation9.phpt) */
 808         if (BG(CurrentStatFile)) {
 809                 efree(BG(CurrentStatFile));
 810                 BG(CurrentStatFile) = NULL;
 811         }
 812         if (BG(CurrentLStatFile)) {
 813                 efree(BG(CurrentLStatFile));
 814                 BG(CurrentLStatFile) = NULL;
 815         }
 816         if (clear_realpath_cache) {
 817                 if (filename != NULL) {
 818                         realpath_cache_del(filename, filename_len TSRMLS_CC);
 819                 } else {
 820                         realpath_cache_clean(TSRMLS_C);
 821                 }
 822         }
 823 }
 824 /* }}} */
 825 
 826 /* {{{ proto void clearstatcache([bool clear_realpath_cache[, string filename]])
 827    Clear file stat cache */
 828 PHP_FUNCTION(clearstatcache)
 829 {
 830         zend_bool  clear_realpath_cache = 0;
 831         char      *filename             = NULL;
 832         int        filename_len         = 0;
 833 
 834         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|bp", &clear_realpath_cache, &filename, &filename_len) == FAILURE) {
 835                 return;
 836         }
 837 
 838         php_clear_stat_cache(clear_realpath_cache, filename, filename_len TSRMLS_CC);
 839 }
 840 /* }}} */
 841 
 842 #define IS_LINK_OPERATION(__t) ((__t) == FS_TYPE || (__t) == FS_IS_LINK || (__t) == FS_LSTAT)
 843 #define IS_EXISTS_CHECK(__t) ((__t) == FS_EXISTS  || (__t) == FS_IS_W || (__t) == FS_IS_R || (__t) == FS_IS_X || (__t) == FS_IS_FILE || (__t) == FS_IS_DIR || (__t) == FS_IS_LINK)
 844 #define IS_ABLE_CHECK(__t) ((__t) == FS_IS_R || (__t) == FS_IS_W || (__t) == FS_IS_X)
 845 #define IS_ACCESS_CHECK(__t) (IS_ABLE_CHECK(type) || (__t) == FS_EXISTS)
 846 
 847 /* {{{ php_stat
 848  */
 849 PHPAPI void php_stat(const char *filename, php_stat_len filename_length, int type, zval *return_value TSRMLS_DC)
 850 {
 851         zval *stat_dev, *stat_ino, *stat_mode, *stat_nlink, *stat_uid, *stat_gid, *stat_rdev,
 852                  *stat_size, *stat_atime, *stat_mtime, *stat_ctime, *stat_blksize, *stat_blocks;
 853         struct stat *stat_sb;
 854         php_stream_statbuf ssb;
 855         int flags = 0, rmask=S_IROTH, wmask=S_IWOTH, xmask=S_IXOTH; /* access rights defaults to other */
 856         char *stat_sb_names[13] = {
 857                 "dev", "ino", "mode", "nlink", "uid", "gid", "rdev",
 858                 "size", "atime", "mtime", "ctime", "blksize", "blocks"
 859         };
 860         const char *local;
 861         php_stream_wrapper *wrapper;
 862 
 863         if (!filename_length) {
 864                 RETURN_FALSE;
 865         }
 866 
 867         if ((wrapper = php_stream_locate_url_wrapper(filename, &local, 0 TSRMLS_CC)) == &php_plain_files_wrapper && php_check_open_basedir(local TSRMLS_CC)) {
 868                 RETURN_FALSE;
 869         }
 870 
 871         if (IS_ACCESS_CHECK(type)) {
 872                 if (wrapper == &php_plain_files_wrapper) {
 873 
 874                         switch (type) {
 875 #ifdef F_OK
 876                                 case FS_EXISTS:
 877                                         RETURN_BOOL(VCWD_ACCESS(local, F_OK) == 0);
 878                                         break;
 879 #endif
 880 #ifdef W_OK
 881                                 case FS_IS_W:
 882                                         RETURN_BOOL(VCWD_ACCESS(local, W_OK) == 0);
 883                                         break;
 884 #endif
 885 #ifdef R_OK
 886                                 case FS_IS_R:
 887                                         RETURN_BOOL(VCWD_ACCESS(local, R_OK) == 0);
 888                                         break;
 889 #endif
 890 #ifdef X_OK
 891                                 case FS_IS_X:
 892                                         RETURN_BOOL(VCWD_ACCESS(local, X_OK) == 0);
 893                                         break;
 894 #endif
 895                         }
 896                 }
 897         }
 898 
 899         if (IS_LINK_OPERATION(type)) {
 900                 flags |= PHP_STREAM_URL_STAT_LINK;
 901         }
 902         if (IS_EXISTS_CHECK(type)) {
 903                 flags |= PHP_STREAM_URL_STAT_QUIET;
 904         }
 905 
 906         if (php_stream_stat_path_ex((char *)filename, flags, &ssb, NULL)) {
 907                 /* Error Occurred */
 908                 if (!IS_EXISTS_CHECK(type)) {
 909                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "%sstat failed for %s", IS_LINK_OPERATION(type) ? "L" : "", filename);
 910                 }
 911                 RETURN_FALSE;
 912         }
 913 
 914         stat_sb = &ssb.sb;
 915 
 916 
 917 #ifndef NETWARE
 918         if (type >= FS_IS_W && type <= FS_IS_X) {
 919                 if(ssb.sb.st_uid==getuid()) {
 920                         rmask=S_IRUSR;
 921                         wmask=S_IWUSR;
 922                         xmask=S_IXUSR;
 923                 } else if(ssb.sb.st_gid==getgid()) {
 924                         rmask=S_IRGRP;
 925                         wmask=S_IWGRP;
 926                         xmask=S_IXGRP;
 927                 } else {
 928                         int   groups, n, i;
 929                         gid_t *gids;
 930 
 931                         groups = getgroups(0, NULL);
 932                         if(groups > 0) {
 933                                 gids=(gid_t *)safe_emalloc(groups, sizeof(gid_t), 0);
 934                                 n=getgroups(groups, gids);
 935                                 for(i=0;i<n;i++){
 936                                         if(ssb.sb.st_gid==gids[i]) {
 937                                                 rmask=S_IRGRP;
 938                                                 wmask=S_IWGRP;
 939                                                 xmask=S_IXGRP;
 940                                                 break;
 941                                         }
 942                                 }
 943                                 efree(gids);
 944                         }
 945                 }
 946         }
 947 #endif
 948 
 949 #ifndef NETWARE
 950         if (IS_ABLE_CHECK(type) && getuid() == 0) {
 951                 /* root has special perms on plain_wrapper
 952                    But we don't know about root under Netware */
 953                 if (wrapper == &php_plain_files_wrapper) {
 954                         if (type == FS_IS_X) {
 955                                 xmask = S_IXROOT;
 956                         } else {
 957                                 RETURN_TRUE;
 958                         }
 959                 }
 960         }
 961 #endif
 962 
 963         switch (type) {
 964         case FS_PERMS:
 965                 RETURN_LONG((long)ssb.sb.st_mode);
 966         case FS_INODE:
 967                 RETURN_LONG((long)ssb.sb.st_ino);
 968         case FS_SIZE:
 969                 RETURN_LONG((long)ssb.sb.st_size);
 970         case FS_OWNER:
 971                 RETURN_LONG((long)ssb.sb.st_uid);
 972         case FS_GROUP:
 973                 RETURN_LONG((long)ssb.sb.st_gid);
 974         case FS_ATIME:
 975                 RETURN_LONG((long)ssb.sb.st_atime);
 976         case FS_MTIME:
 977                 RETURN_LONG((long)ssb.sb.st_mtime);
 978         case FS_CTIME:
 979                 RETURN_LONG((long)ssb.sb.st_ctime);
 980         case FS_TYPE:
 981                 if (S_ISLNK(ssb.sb.st_mode)) {
 982                         RETURN_STRING("link", 1);
 983                 }
 984                 switch(ssb.sb.st_mode & S_IFMT) {
 985                 case S_IFIFO: RETURN_STRING("fifo", 1);
 986                 case S_IFCHR: RETURN_STRING("char", 1);
 987                 case S_IFDIR: RETURN_STRING("dir", 1);
 988                 case S_IFBLK: RETURN_STRING("block", 1);
 989                 case S_IFREG: RETURN_STRING("file", 1);
 990 #if defined(S_IFSOCK) && !defined(ZEND_WIN32)&&!defined(__BEOS__)
 991                 case S_IFSOCK: RETURN_STRING("socket", 1);
 992 #endif
 993                 }
 994                 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unknown file type (%d)", ssb.sb.st_mode&S_IFMT);
 995                 RETURN_STRING("unknown", 1);
 996         case FS_IS_W:
 997                 RETURN_BOOL((ssb.sb.st_mode & wmask) != 0);
 998         case FS_IS_R:
 999                 RETURN_BOOL((ssb.sb.st_mode&rmask)!=0);
1000         case FS_IS_X:
1001                 RETURN_BOOL((ssb.sb.st_mode&xmask)!=0 && !S_ISDIR(ssb.sb.st_mode));
1002         case FS_IS_FILE:
1003                 RETURN_BOOL(S_ISREG(ssb.sb.st_mode));
1004         case FS_IS_DIR:
1005                 RETURN_BOOL(S_ISDIR(ssb.sb.st_mode));
1006         case FS_IS_LINK:
1007                 RETURN_BOOL(S_ISLNK(ssb.sb.st_mode));
1008         case FS_EXISTS:
1009                 RETURN_TRUE; /* the false case was done earlier */
1010         case FS_LSTAT:
1011                 /* FALLTHROUGH */
1012         case FS_STAT:
1013                 array_init(return_value);
1014 
1015                 MAKE_LONG_ZVAL_INCREF(stat_dev, stat_sb->st_dev);
1016                 MAKE_LONG_ZVAL_INCREF(stat_ino, stat_sb->st_ino);
1017                 MAKE_LONG_ZVAL_INCREF(stat_mode, stat_sb->st_mode);
1018                 MAKE_LONG_ZVAL_INCREF(stat_nlink, stat_sb->st_nlink);
1019                 MAKE_LONG_ZVAL_INCREF(stat_uid, stat_sb->st_uid);
1020                 MAKE_LONG_ZVAL_INCREF(stat_gid, stat_sb->st_gid);
1021 #ifdef HAVE_ST_RDEV
1022                 MAKE_LONG_ZVAL_INCREF(stat_rdev, stat_sb->st_rdev);
1023 #else
1024                 MAKE_LONG_ZVAL_INCREF(stat_rdev, -1);
1025 #endif
1026                 MAKE_LONG_ZVAL_INCREF(stat_size, stat_sb->st_size);
1027                 MAKE_LONG_ZVAL_INCREF(stat_atime, stat_sb->st_atime);
1028                 MAKE_LONG_ZVAL_INCREF(stat_mtime, stat_sb->st_mtime);
1029                 MAKE_LONG_ZVAL_INCREF(stat_ctime, stat_sb->st_ctime);
1030 #ifdef HAVE_ST_BLKSIZE
1031                 MAKE_LONG_ZVAL_INCREF(stat_blksize, stat_sb->st_blksize);
1032 #else
1033                 MAKE_LONG_ZVAL_INCREF(stat_blksize,-1);
1034 #endif
1035 #ifdef HAVE_ST_BLOCKS
1036                 MAKE_LONG_ZVAL_INCREF(stat_blocks, stat_sb->st_blocks);
1037 #else
1038                 MAKE_LONG_ZVAL_INCREF(stat_blocks,-1);
1039 #endif
1040                 /* Store numeric indexes in propper order */
1041                 zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_dev, sizeof(zval *), NULL);
1042                 zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_ino, sizeof(zval *), NULL);
1043                 zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_mode, sizeof(zval *), NULL);
1044                 zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_nlink, sizeof(zval *), NULL);
1045                 zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_uid, sizeof(zval *), NULL);
1046                 zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_gid, sizeof(zval *), NULL);
1047 
1048                 zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_rdev, sizeof(zval *), NULL);
1049                 zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_size, sizeof(zval *), NULL);
1050                 zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_atime, sizeof(zval *), NULL);
1051                 zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_mtime, sizeof(zval *), NULL);
1052                 zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_ctime, sizeof(zval *), NULL);
1053                 zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_blksize, sizeof(zval *), NULL);
1054                 zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_blocks, sizeof(zval *), NULL);
1055 
1056                 /* Store string indexes referencing the same zval*/
1057                 zend_hash_update(HASH_OF(return_value), stat_sb_names[0], strlen(stat_sb_names[0])+1, (void *) &stat_dev, sizeof(zval *), NULL);
1058                 zend_hash_update(HASH_OF(return_value), stat_sb_names[1], strlen(stat_sb_names[1])+1, (void *) &stat_ino, sizeof(zval *), NULL);
1059                 zend_hash_update(HASH_OF(return_value), stat_sb_names[2], strlen(stat_sb_names[2])+1, (void *) &stat_mode, sizeof(zval *), NULL);
1060                 zend_hash_update(HASH_OF(return_value), stat_sb_names[3], strlen(stat_sb_names[3])+1, (void *) &stat_nlink, sizeof(zval *), NULL);
1061                 zend_hash_update(HASH_OF(return_value), stat_sb_names[4], strlen(stat_sb_names[4])+1, (void *) &stat_uid, sizeof(zval *), NULL);
1062                 zend_hash_update(HASH_OF(return_value), stat_sb_names[5], strlen(stat_sb_names[5])+1, (void *) &stat_gid, sizeof(zval *), NULL);
1063                 zend_hash_update(HASH_OF(return_value), stat_sb_names[6], strlen(stat_sb_names[6])+1, (void *) &stat_rdev, sizeof(zval *), NULL);
1064                 zend_hash_update(HASH_OF(return_value), stat_sb_names[7], strlen(stat_sb_names[7])+1, (void *) &stat_size, sizeof(zval *), NULL);
1065                 zend_hash_update(HASH_OF(return_value), stat_sb_names[8], strlen(stat_sb_names[8])+1, (void *) &stat_atime, sizeof(zval *), NULL);
1066                 zend_hash_update(HASH_OF(return_value), stat_sb_names[9], strlen(stat_sb_names[9])+1, (void *) &stat_mtime, sizeof(zval *), NULL);
1067                 zend_hash_update(HASH_OF(return_value), stat_sb_names[10], strlen(stat_sb_names[10])+1, (void *) &stat_ctime, sizeof(zval *), NULL);
1068                 zend_hash_update(HASH_OF(return_value), stat_sb_names[11], strlen(stat_sb_names[11])+1, (void *) &stat_blksize, sizeof(zval *), NULL);
1069                 zend_hash_update(HASH_OF(return_value), stat_sb_names[12], strlen(stat_sb_names[12])+1, (void *) &stat_blocks, sizeof(zval *), NULL);
1070 
1071                 return;
1072         }
1073         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Didn't understand stat call");
1074         RETURN_FALSE;
1075 }
1076 /* }}} */
1077 
1078 /* another quickie macro to make defining similar functions easier */
1079 /* {{{ FileFunction(name, funcnum) */
1080 #define FileFunction(name, funcnum) \
1081 void name(INTERNAL_FUNCTION_PARAMETERS) { \
1082         char *filename; \
1083         int filename_len; \
1084         \
1085         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) { \
1086                 return; \
1087         } \
1088         \
1089         php_stat(filename, (php_stat_len) filename_len, funcnum, return_value TSRMLS_CC); \
1090 }
1091 /* }}} */
1092 
1093 /* {{{ proto int fileperms(string filename)
1094    Get file permissions */
1095 FileFunction(PHP_FN(fileperms), FS_PERMS)
1096 /* }}} */
1097 
1098 /* {{{ proto int fileinode(string filename)
1099    Get file inode */
1100 FileFunction(PHP_FN(fileinode), FS_INODE)
1101 /* }}} */
1102 
1103 /* {{{ proto int filesize(string filename)
1104    Get file size */
1105 FileFunction(PHP_FN(filesize), FS_SIZE)
1106 /* }}} */
1107 
1108 /* {{{ proto int fileowner(string filename)
1109    Get file owner */
1110 FileFunction(PHP_FN(fileowner), FS_OWNER)
1111 /* }}} */
1112 
1113 /* {{{ proto int filegroup(string filename)
1114    Get file group */
1115 FileFunction(PHP_FN(filegroup), FS_GROUP)
1116 /* }}} */
1117 
1118 /* {{{ proto int fileatime(string filename)
1119    Get last access time of file */
1120 FileFunction(PHP_FN(fileatime), FS_ATIME)
1121 /* }}} */
1122 
1123 /* {{{ proto int filemtime(string filename)
1124    Get last modification time of file */
1125 FileFunction(PHP_FN(filemtime), FS_MTIME)
1126 /* }}} */
1127 
1128 /* {{{ proto int filectime(string filename)
1129    Get inode modification time of file */
1130 FileFunction(PHP_FN(filectime), FS_CTIME)
1131 /* }}} */
1132 
1133 /* {{{ proto string filetype(string filename)
1134    Get file type */
1135 FileFunction(PHP_FN(filetype), FS_TYPE)
1136 /* }}} */
1137 
1138 /* {{{ proto bool is_writable(string filename)
1139    Returns true if file can be written */
1140 FileFunction(PHP_FN(is_writable), FS_IS_W)
1141 /* }}} */
1142 
1143 /* {{{ proto bool is_readable(string filename)
1144    Returns true if file can be read */
1145 FileFunction(PHP_FN(is_readable), FS_IS_R)
1146 /* }}} */
1147 
1148 /* {{{ proto bool is_executable(string filename)
1149    Returns true if file is executable */
1150 FileFunction(PHP_FN(is_executable), FS_IS_X)
1151 /* }}} */
1152 
1153 /* {{{ proto bool is_file(string filename)
1154    Returns true if file is a regular file */
1155 FileFunction(PHP_FN(is_file), FS_IS_FILE)
1156 /* }}} */
1157 
1158 /* {{{ proto bool is_dir(string filename)
1159    Returns true if file is directory */
1160 FileFunction(PHP_FN(is_dir), FS_IS_DIR)
1161 /* }}} */
1162 
1163 /* {{{ proto bool is_link(string filename)
1164    Returns true if file is symbolic link */
1165 FileFunction(PHP_FN(is_link), FS_IS_LINK)
1166 /* }}} */
1167 
1168 /* {{{ proto bool file_exists(string filename)
1169    Returns true if filename exists */
1170 FileFunction(PHP_FN(file_exists), FS_EXISTS)
1171 /* }}} */
1172 
1173 /* {{{ proto array lstat(string filename)
1174    Give information about a file or symbolic link */
1175 FileFunction(php_if_lstat, FS_LSTAT)
1176 /* }}} */
1177 
1178 /* {{{ proto array stat(string filename)
1179    Give information about a file */
1180 FileFunction(php_if_stat, FS_STAT)
1181 /* }}} */
1182 
1183 /* {{{ proto bool realpath_cache_size()
1184    Get current size of realpath cache */
1185 PHP_FUNCTION(realpath_cache_size)
1186 {
1187         if (zend_parse_parameters_none() == FAILURE) {
1188                 return;
1189         }
1190         RETURN_LONG(realpath_cache_size(TSRMLS_C));
1191 }
1192 
1193 /* {{{ proto bool realpath_cache_get()
1194    Get current size of realpath cache */
1195 PHP_FUNCTION(realpath_cache_get)
1196 {
1197         realpath_cache_bucket **buckets = realpath_cache_get_buckets(TSRMLS_C), **end = buckets + realpath_cache_max_buckets(TSRMLS_C);
1198 
1199         if (zend_parse_parameters_none() == FAILURE) {
1200                 return;
1201         }
1202 
1203         array_init(return_value);
1204         while(buckets < end) {
1205                 realpath_cache_bucket *bucket = *buckets;
1206                 while(bucket) {
1207                         zval *entry;
1208                         MAKE_STD_ZVAL(entry);
1209                         array_init(entry);
1210 
1211                         /* bucket->key is unsigned long */
1212                         if (LONG_MAX >= bucket->key) {
1213                                 add_assoc_long(entry, "key", bucket->key);
1214                         } else {
1215                                 add_assoc_double(entry, "key", (double)bucket->key);
1216                         }
1217                         add_assoc_bool(entry, "is_dir", bucket->is_dir);
1218                         add_assoc_stringl(entry, "realpath", bucket->realpath, bucket->realpath_len, 1);
1219                         add_assoc_long(entry, "expires", bucket->expires);
1220 #ifdef PHP_WIN32
1221                         add_assoc_bool(entry, "is_rvalid", bucket->is_rvalid);
1222                         add_assoc_bool(entry, "is_wvalid", bucket->is_wvalid);
1223                         add_assoc_bool(entry, "is_readable", bucket->is_readable);
1224                         add_assoc_bool(entry, "is_writable", bucket->is_writable);
1225 #endif
1226                         zend_hash_update(Z_ARRVAL_P(return_value), bucket->path, bucket->path_len+1, &entry, sizeof(zval *), NULL);
1227                         bucket = bucket->next;
1228                 }
1229                 buckets++;
1230         }
1231 }
1232 
1233 /*
1234  * Local variables:
1235  * tab-width: 4
1236  * c-basic-offset: 4
1237  * End:
1238  * vim600: sw=4 ts=4 fdm=marker
1239  * vim<600: sw=4 ts=4
1240  */

/* [<][>][^][v][top][bottom][index][help] */