Back to index

php5  5.3.10
filestat.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1997-2012 The PHP Group                                |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 3.01 of the PHP license,      |
00008    | that is bundled with this package in the file LICENSE, and is        |
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.php.net/license/3_01.txt                                  |
00011    | If you did not receive a copy of the PHP license and are unable to   |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@php.net so we can mail you a copy immediately.               |
00014    +----------------------------------------------------------------------+
00015    | Author:  Jim Winstead <jimw@php.net>                                 |
00016    +----------------------------------------------------------------------+
00017  */
00018 
00019 /* $Id: filestat.c 321634 2012-01-01 13:15:04Z felipe $ */
00020 
00021 #include "php.h"
00022 #include "safe_mode.h"
00023 #include "fopen_wrappers.h"
00024 #include "php_globals.h"
00025 
00026 #include <stdlib.h>
00027 #include <sys/stat.h>
00028 #include <string.h>
00029 #include <errno.h>
00030 #include <ctype.h>
00031 #include <time.h>
00032 
00033 #if HAVE_UNISTD_H
00034 # include <unistd.h>
00035 #endif
00036 
00037 #if HAVE_SYS_PARAM_H
00038 # include <sys/param.h>
00039 #endif
00040 
00041 #if HAVE_SYS_VFS_H
00042 # include <sys/vfs.h>
00043 #endif
00044 
00045 #ifdef OS2
00046 #  define INCL_DOS
00047 #  include <os2.h>
00048 #endif
00049 
00050 #if defined(HAVE_SYS_STATVFS_H) && defined(HAVE_STATVFS)
00051 # include <sys/statvfs.h>
00052 #elif defined(HAVE_SYS_STATFS_H) && defined(HAVE_STATFS)
00053 # include <sys/statfs.h>
00054 #elif defined(HAVE_SYS_MOUNT_H) && defined(HAVE_STATFS)
00055 # include <sys/mount.h>
00056 #endif
00057 
00058 #if HAVE_PWD_H
00059 # ifdef PHP_WIN32
00060 #  include "win32/pwd.h"
00061 # else
00062 #  include <pwd.h>
00063 # endif
00064 #endif
00065 
00066 #if HAVE_GRP_H
00067 # ifdef PHP_WIN32
00068 #  include "win32/grp.h"
00069 # else
00070 #  include <grp.h>
00071 # endif
00072 #endif
00073 
00074 #if HAVE_UTIME
00075 # ifdef PHP_WIN32
00076 #  include <sys/utime.h>
00077 # else
00078 #  include <utime.h>
00079 # endif
00080 #endif
00081 
00082 #ifdef PHP_WIN32
00083 #include "win32/winutil.h"
00084 #endif
00085 
00086 #include "basic_functions.h"
00087 #include "php_filestat.h"
00088 
00089 #ifndef S_ISDIR
00090 #define S_ISDIR(mode)       (((mode)&S_IFMT) == S_IFDIR)
00091 #endif
00092 #ifndef S_ISREG
00093 #define S_ISREG(mode)       (((mode)&S_IFMT) == S_IFREG)
00094 #endif
00095 #ifndef S_ISLNK
00096 #define S_ISLNK(mode)       (((mode)&S_IFMT) == S_IFLNK)
00097 #endif
00098 
00099 #define S_IXROOT ( S_IXUSR | S_IXGRP | S_IXOTH )
00100 
00101 PHP_RINIT_FUNCTION(filestat) /* {{{ */
00102 {
00103        BG(CurrentStatFile)=NULL;
00104        BG(CurrentLStatFile)=NULL;
00105        return SUCCESS;
00106 }
00107 /* }}} */
00108 
00109 PHP_RSHUTDOWN_FUNCTION(filestat) /* {{{ */
00110 {
00111        if (BG(CurrentStatFile)) {
00112               efree (BG(CurrentStatFile));
00113               BG(CurrentStatFile) = NULL;
00114        }
00115        if (BG(CurrentLStatFile)) {
00116               efree (BG(CurrentLStatFile));
00117               BG(CurrentLStatFile) = NULL;
00118        }
00119        return SUCCESS;
00120 }
00121 /* }}} */
00122 
00123 static int php_disk_total_space(char *path, double *space TSRMLS_DC) /* {{{ */
00124 #if defined(WINDOWS) /* {{{ */
00125 {
00126        double bytestotal = 0;
00127        HINSTANCE kernel32;
00128        FARPROC gdfse;
00129        typedef BOOL (WINAPI *gdfse_func)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
00130        gdfse_func func;
00131 
00132        /* These are used by GetDiskFreeSpaceEx, if available. */
00133        ULARGE_INTEGER FreeBytesAvailableToCaller;
00134        ULARGE_INTEGER TotalNumberOfBytes;
00135        ULARGE_INTEGER TotalNumberOfFreeBytes;
00136 
00137        /* These are used by GetDiskFreeSpace otherwise. */
00138        DWORD SectorsPerCluster;
00139        DWORD BytesPerSector;
00140        DWORD NumberOfFreeClusters;
00141        DWORD TotalNumberOfClusters;
00142 
00143        /* GetDiskFreeSpaceEx is only available in NT and Win95 post-OSR2,
00144           so we have to jump through some hoops to see if the function
00145           exists. */
00146        kernel32 = LoadLibrary("kernel32.dll");
00147        if (kernel32) {
00148               gdfse = GetProcAddress(kernel32, "GetDiskFreeSpaceExA");
00149               /* It's available, so we can call it. */
00150               if (gdfse) {
00151                      func = (gdfse_func)gdfse;
00152                      if (func(path,
00153                                           &FreeBytesAvailableToCaller,
00154                                           &TotalNumberOfBytes,
00155                                           &TotalNumberOfFreeBytes) == 0) {
00156                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", php_win_err());
00157                             return FAILURE;
00158                      }
00159 
00160                      /* i know - this is ugly, but i works <thies@thieso.net> */
00161                      bytestotal  = TotalNumberOfBytes.HighPart *
00162                             (double) (((unsigned long)1) << 31) * 2.0 +
00163                             TotalNumberOfBytes.LowPart;
00164               } else { /* If it's not available, we just use GetDiskFreeSpace */
00165                      if (GetDiskFreeSpace(path,
00166                                           &SectorsPerCluster, &BytesPerSector,
00167                                           &NumberOfFreeClusters, &TotalNumberOfClusters) == 0) {
00168                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", php_win_err());
00169                             return FAILURE;
00170                      }
00171                      bytestotal = (double)TotalNumberOfClusters * (double)SectorsPerCluster * (double)BytesPerSector;
00172               }
00173        } else {
00174               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to load kernel32.dll");
00175               return FAILURE;
00176        }
00177 
00178        *space = bytestotal;
00179        return SUCCESS;
00180 }
00181 /* }}} */
00182 #elif defined(OS2) /* {{{ */
00183 {
00184        double bytestotal = 0;
00185        FSALLOCATE fsinfo;
00186        char drive = path[0] & 95;
00187 
00188        if (DosQueryFSInfo( drive ? drive - 64 : 0, FSIL_ALLOC, &fsinfo, sizeof( fsinfo ) ) == 0) {
00189               bytestotal = (double)fsinfo.cbSector * fsinfo.cSectorUnit * fsinfo.cUnit;
00190               *space = bytestotal;
00191               return SUCCESS;
00192        }
00193        return FAILURE;
00194 }
00195 /* }}} */
00196 #else /* {{{ if !defined(OS2) && !defined(WINDOWS) */
00197 {
00198        double bytestotal = 0;
00199 #if defined(HAVE_SYS_STATVFS_H) && defined(HAVE_STATVFS)
00200        struct statvfs buf;
00201 #elif (defined(HAVE_SYS_STATFS_H) || defined(HAVE_SYS_MOUNT_H)) && defined(HAVE_STATFS)
00202        struct statfs buf;
00203 #endif
00204 
00205 #if defined(HAVE_SYS_STATVFS_H) && defined(HAVE_STATVFS)
00206        if (statvfs(path, &buf)) {
00207               php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
00208               return FAILURE;
00209        }
00210        if (buf.f_frsize) {
00211               bytestotal = (((double)buf.f_blocks) * ((double)buf.f_frsize));
00212        } else {
00213               bytestotal = (((double)buf.f_blocks) * ((double)buf.f_bsize));
00214        }
00215 
00216 #elif (defined(HAVE_SYS_STATFS_H) || defined(HAVE_SYS_MOUNT_H)) && defined(HAVE_STATFS)
00217        if (statfs(path, &buf)) {
00218               php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
00219               return FAILURE;
00220        }
00221        bytestotal = (((double)buf.f_bsize) * ((double)buf.f_blocks));
00222 #endif
00223 
00224        *space = bytestotal;
00225        return SUCCESS;
00226 }
00227 #endif
00228 /* }}} */
00229 /* }}} */
00230 
00231 /* {{{ proto float disk_total_space(string path)
00232    Get total disk space for filesystem that path is on */
00233 PHP_FUNCTION(disk_total_space)
00234 {
00235        double bytestotal;
00236        char *path;
00237        int path_len;
00238 
00239        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &path, &path_len) == FAILURE) {
00240               return;
00241        }
00242 
00243        if (php_check_open_basedir(path TSRMLS_CC)) {
00244               RETURN_FALSE;
00245        }
00246 
00247        if (php_disk_total_space(path, &bytestotal TSRMLS_CC) == SUCCESS) {
00248               RETURN_DOUBLE(bytestotal);
00249        }
00250        RETURN_FALSE;
00251 }
00252 /* }}} */
00253 
00254 static int php_disk_free_space(char *path, double *space TSRMLS_DC) /* {{{ */
00255 #if defined(WINDOWS) /* {{{ */
00256 {
00257        double bytesfree = 0;
00258 
00259        HINSTANCE kernel32;
00260        FARPROC gdfse;
00261        typedef BOOL (WINAPI *gdfse_func)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
00262        gdfse_func func;
00263 
00264        /* These are used by GetDiskFreeSpaceEx, if available. */
00265        ULARGE_INTEGER FreeBytesAvailableToCaller;
00266        ULARGE_INTEGER TotalNumberOfBytes;
00267        ULARGE_INTEGER TotalNumberOfFreeBytes;
00268 
00269        /* These are used by GetDiskFreeSpace otherwise. */
00270        DWORD SectorsPerCluster;
00271        DWORD BytesPerSector;
00272        DWORD NumberOfFreeClusters;
00273        DWORD TotalNumberOfClusters;
00274 
00275        /* GetDiskFreeSpaceEx is only available in NT and Win95 post-OSR2,
00276           so we have to jump through some hoops to see if the function
00277           exists. */
00278        kernel32 = LoadLibrary("kernel32.dll");
00279        if (kernel32) {
00280               gdfse = GetProcAddress(kernel32, "GetDiskFreeSpaceExA");
00281               /* It's available, so we can call it. */
00282               if (gdfse) {
00283                      func = (gdfse_func)gdfse;
00284                      if (func(path,
00285                                           &FreeBytesAvailableToCaller,
00286                                           &TotalNumberOfBytes,
00287                                           &TotalNumberOfFreeBytes) == 0) {
00288                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", php_win_err());
00289                             return FAILURE;
00290                      }
00291 
00292                      /* i know - this is ugly, but i works <thies@thieso.net> */
00293                      bytesfree  = FreeBytesAvailableToCaller.HighPart *
00294                             (double) (((unsigned long)1) << 31) * 2.0 +
00295                             FreeBytesAvailableToCaller.LowPart;
00296               } else { /* If it's not available, we just use GetDiskFreeSpace */
00297                      if (GetDiskFreeSpace(path,
00298                                           &SectorsPerCluster, &BytesPerSector,
00299                                           &NumberOfFreeClusters, &TotalNumberOfClusters) == 0) {
00300                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", php_win_err());
00301                             return FAILURE;
00302                      }
00303                      bytesfree = (double)NumberOfFreeClusters * (double)SectorsPerCluster * (double)BytesPerSector;
00304               }
00305        } else {
00306               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to load kernel32.dll");
00307               return FAILURE;
00308        }
00309 
00310        *space = bytesfree;
00311        return SUCCESS;
00312 }
00313 /* }}} */
00314 #elif defined(OS2) /* {{{ */
00315 {
00316        double bytesfree = 0;
00317        FSALLOCATE fsinfo;
00318        char drive = path[0] & 95;
00319 
00320        if (DosQueryFSInfo( drive ? drive - 64 : 0, FSIL_ALLOC, &fsinfo, sizeof( fsinfo ) ) == 0) {
00321               bytesfree = (double)fsinfo.cbSector * fsinfo.cSectorUnit * fsinfo.cUnitAvail;
00322               *space = bytesfree;
00323               return SUCCESS;
00324        }
00325        return FAILURE;
00326 }
00327 /* }}} */
00328 #else /* {{{ if !defined(OS2) && !defined(WINDOWS) */
00329 {
00330        double bytesfree = 0;
00331 #if defined(HAVE_SYS_STATVFS_H) && defined(HAVE_STATVFS)
00332        struct statvfs buf;
00333 #elif (defined(HAVE_SYS_STATFS_H) || defined(HAVE_SYS_MOUNT_H)) && defined(HAVE_STATFS)
00334        struct statfs buf;
00335 #endif
00336 
00337 #if defined(HAVE_SYS_STATVFS_H) && defined(HAVE_STATVFS)
00338        if (statvfs(path, &buf)) {
00339               php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
00340               return FAILURE;
00341        }
00342        if (buf.f_frsize) {
00343               bytesfree = (((double)buf.f_bavail) * ((double)buf.f_frsize));
00344        } else {
00345               bytesfree = (((double)buf.f_bavail) * ((double)buf.f_bsize));
00346        }
00347 #elif (defined(HAVE_SYS_STATFS_H) || defined(HAVE_SYS_MOUNT_H)) && defined(HAVE_STATFS)
00348        if (statfs(path, &buf)) {
00349               php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
00350               return FAILURE;
00351        }
00352 #ifdef NETWARE
00353        bytesfree = (((double)buf.f_bsize) * ((double)buf.f_bfree));
00354 #else
00355        bytesfree = (((double)buf.f_bsize) * ((double)buf.f_bavail));
00356 #endif
00357 #endif
00358 
00359        *space = bytesfree;
00360        return SUCCESS;
00361 }
00362 #endif
00363 /* }}} */
00364 /* }}} */
00365 
00366 /* {{{ proto float disk_free_space(string path)
00367    Get free disk space for filesystem that path is on */
00368 PHP_FUNCTION(disk_free_space)
00369 {
00370        double bytesfree;
00371        char *path;
00372        int path_len;
00373 
00374        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &path, &path_len) == FAILURE) {
00375               return;
00376        }
00377 
00378        if (php_check_open_basedir(path TSRMLS_CC)) {
00379               RETURN_FALSE;
00380        }
00381 
00382        if (strlen(path) != path_len) {
00383               RETURN_FALSE;
00384        }
00385 
00386        if (php_disk_free_space(path, &bytesfree TSRMLS_CC) == SUCCESS) {
00387               RETURN_DOUBLE(bytesfree);
00388        }
00389        RETURN_FALSE;
00390 }
00391 /* }}} */
00392 
00393 #if !defined(WINDOWS) && !defined(NETWARE)
00394 static void php_do_chgrp(INTERNAL_FUNCTION_PARAMETERS, int do_lchgrp) /* {{{ */
00395 {
00396        char *filename;
00397        int filename_len;
00398        zval *group;
00399        gid_t gid;
00400        int ret;
00401 
00402        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz/", &filename, &filename_len, &group) == FAILURE) {
00403               RETURN_FALSE;
00404        }
00405 
00406        if (strlen(filename) != filename_len) {
00407               RETURN_FALSE;
00408        }
00409 
00410        if (Z_TYPE_P(group) == IS_LONG) {
00411               gid = (gid_t)Z_LVAL_P(group);
00412        } else if (Z_TYPE_P(group) == IS_STRING) {
00413 #if defined(ZTS) && defined(HAVE_GETGRNAM_R) && defined(_SC_GETGR_R_SIZE_MAX)
00414               struct group gr;
00415               struct group *retgrptr;
00416               long grbuflen = sysconf(_SC_GETGR_R_SIZE_MAX);
00417               char *grbuf;
00418 
00419               if (grbuflen < 1) {
00420                      RETURN_FALSE;
00421               }
00422 
00423               grbuf = emalloc(grbuflen);
00424               if (getgrnam_r(Z_STRVAL_P(group), &gr, grbuf, grbuflen, &retgrptr) != 0 || retgrptr == NULL) {
00425                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find gid for %s", Z_STRVAL_P(group));
00426                      efree(grbuf);
00427                      RETURN_FALSE;
00428               }
00429               efree(grbuf);
00430               gid = gr.gr_gid;
00431 #else
00432               struct group *gr = getgrnam(Z_STRVAL_P(group));
00433 
00434               if (!gr) {
00435                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find gid for %s", Z_STRVAL_P(group));
00436                      RETURN_FALSE;
00437               }
00438               gid = gr->gr_gid;
00439 #endif
00440        } else {
00441               php_error_docref(NULL TSRMLS_CC, E_WARNING, "parameter 2 should be string or integer, %s given", zend_zval_type_name(group));
00442               RETURN_FALSE;
00443        }
00444 
00445        if (PG(safe_mode) &&(!php_checkuid(filename, NULL, CHECKUID_ALLOW_FILE_NOT_EXISTS))) {
00446               RETURN_FALSE;
00447        }
00448 
00449        /* Check the basedir */
00450        if (php_check_open_basedir(filename TSRMLS_CC)) {
00451               RETURN_FALSE;
00452        }
00453 
00454        if (do_lchgrp) {
00455 #if HAVE_LCHOWN
00456               ret = VCWD_LCHOWN(filename, -1, gid);
00457 #endif
00458        } else {
00459               ret = VCWD_CHOWN(filename, -1, gid);
00460        }
00461        if (ret == -1) {
00462               php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
00463               RETURN_FALSE;
00464        }
00465        RETURN_TRUE;
00466 }
00467 /* }}} */
00468 #endif
00469 
00470 #ifndef NETWARE
00471 /* {{{ proto bool chgrp(string filename, mixed group)
00472    Change file group */
00473 PHP_FUNCTION(chgrp)
00474 {
00475 #if !defined(WINDOWS)
00476        php_do_chgrp(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
00477 #else
00478        RETURN_FALSE;
00479 #endif
00480 }
00481 /* }}} */
00482 
00483 /* {{{ proto bool lchgrp(string filename, mixed group)
00484    Change symlink group */
00485 #if HAVE_LCHOWN
00486 PHP_FUNCTION(lchgrp)
00487 {
00488 # if !defined(WINDOWS)
00489        php_do_chgrp(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
00490 # else
00491        RETURN_FALSE;
00492 # endif
00493 }
00494 #endif
00495 /* }}} */
00496 #endif /* !NETWARE */
00497 
00498 #if !defined(WINDOWS) && !defined(NETWARE)
00499 static void php_do_chown(INTERNAL_FUNCTION_PARAMETERS, int do_lchown) /* {{{ */
00500 {
00501        char *filename;
00502        int filename_len;
00503        zval *user;
00504        uid_t uid;
00505        int ret;
00506 
00507        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz/", &filename, &filename_len, &user) == FAILURE) {
00508               return;
00509        }
00510 
00511        if (strlen(filename) != filename_len) {
00512               RETURN_FALSE;
00513        }
00514 
00515        if (Z_TYPE_P(user) == IS_LONG) {
00516               uid = (uid_t)Z_LVAL_P(user);
00517        } else if (Z_TYPE_P(user) == IS_STRING) {
00518 #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWNAM_R)
00519               struct passwd pw;
00520               struct passwd *retpwptr = NULL;
00521               long pwbuflen = sysconf(_SC_GETPW_R_SIZE_MAX);
00522               char *pwbuf;
00523 
00524               if (pwbuflen < 1) {
00525                      RETURN_FALSE;
00526               }
00527 
00528               pwbuf = emalloc(pwbuflen);
00529               if (getpwnam_r(Z_STRVAL_P(user), &pw, pwbuf, pwbuflen, &retpwptr) != 0 || retpwptr == NULL) {
00530                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find uid for %s", Z_STRVAL_P(user));
00531                      efree(pwbuf);
00532                      RETURN_FALSE;
00533               }
00534               efree(pwbuf);
00535               uid = pw.pw_uid;
00536 #else
00537               struct passwd *pw = getpwnam(Z_STRVAL_P(user));
00538 
00539               if (!pw) {
00540                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find uid for %s", Z_STRVAL_P(user));
00541                      RETURN_FALSE;
00542               }
00543               uid = pw->pw_uid;
00544 #endif
00545        } else {
00546               php_error_docref(NULL TSRMLS_CC, E_WARNING, "parameter 2 should be string or integer, %s given", zend_zval_type_name(user));
00547               RETURN_FALSE;
00548        }
00549 
00550        if (PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_ALLOW_FILE_NOT_EXISTS))) {
00551               RETURN_FALSE;
00552        }
00553 
00554        /* Check the basedir */
00555        if (php_check_open_basedir(filename TSRMLS_CC)) {
00556               RETURN_FALSE;
00557        }
00558 
00559        if (do_lchown) {
00560 #if HAVE_LCHOWN
00561               ret = VCWD_LCHOWN(filename, uid, -1);
00562 #endif
00563        } else {
00564               ret = VCWD_CHOWN(filename, uid, -1);
00565        }
00566        if (ret == -1) {
00567               php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
00568               RETURN_FALSE;
00569        }
00570 }
00571 /* }}} */
00572 #endif
00573 
00574 #ifndef NETWARE
00575 /* {{{ proto bool chown (string filename, mixed user)
00576    Change file owner */
00577 PHP_FUNCTION(chown)
00578 {
00579 #if !defined(WINDOWS)
00580        RETVAL_TRUE;
00581        php_do_chown(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
00582 #else
00583        RETURN_FALSE;
00584 #endif
00585 }
00586 /* }}} */
00587 
00588 /* {{{ proto bool chown (string filename, mixed user)
00589    Change file owner */
00590 #if HAVE_LCHOWN
00591 PHP_FUNCTION(lchown)
00592 {
00593 # if !defined(WINDOWS)
00594        RETVAL_TRUE;
00595        php_do_chown(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
00596 # else
00597        RETURN_FALSE;
00598 # endif
00599 }
00600 #endif
00601 /* }}} */
00602 #endif /* !NETWARE */
00603 
00604 /* {{{ proto bool chmod(string filename, int mode)
00605    Change file mode */
00606 PHP_FUNCTION(chmod)
00607 {
00608        char *filename;
00609        int filename_len;
00610        long mode;
00611        int ret;
00612        mode_t imode;
00613 
00614        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &filename, &filename_len, &mode) == FAILURE) {
00615               return;
00616        }
00617 
00618        if (PG(safe_mode) &&(!php_checkuid(filename, NULL, CHECKUID_ALLOW_FILE_NOT_EXISTS))) {
00619               RETURN_FALSE;
00620        }
00621 
00622        if (strlen(filename) != filename_len) {
00623               RETURN_FALSE;
00624        }
00625 
00626        /* Check the basedir */
00627        if (php_check_open_basedir(filename TSRMLS_CC)) {
00628               RETURN_FALSE;
00629        }
00630 
00631        imode = (mode_t) mode;
00632        /* In safe mode, do not allow to setuid files.
00633         * Setuiding files could allow users to gain privileges
00634         * that safe mode doesn't give them. */
00635 
00636        if (PG(safe_mode)) {
00637               php_stream_statbuf ssb;
00638               if (php_stream_stat_path_ex(filename, 0, &ssb, NULL)) {
00639                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "stat failed for %s", filename);
00640                      RETURN_FALSE;
00641               }
00642               if ((imode & 04000) != 0 && (ssb.sb.st_mode & 04000) == 0) {
00643                      imode ^= 04000;
00644               }
00645               if ((imode & 02000) != 0 && (ssb.sb.st_mode & 02000) == 0) {
00646                      imode ^= 02000;
00647               }
00648               if ((imode & 01000) != 0 && (ssb.sb.st_mode & 01000) == 0) {
00649                      imode ^= 01000;
00650               }
00651        }
00652 
00653        ret = VCWD_CHMOD(filename, imode);
00654        if (ret == -1) {
00655               php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
00656               RETURN_FALSE;
00657        }
00658        RETURN_TRUE;
00659 }
00660 /* }}} */
00661 
00662 #if HAVE_UTIME
00663 /* {{{ proto bool touch(string filename [, int time [, int atime]])
00664    Set modification time of file */
00665 PHP_FUNCTION(touch)
00666 {
00667        char *filename;
00668        int filename_len;
00669        long filetime = 0, fileatime = 0;
00670        int ret, argc = ZEND_NUM_ARGS();
00671        FILE *file;
00672        struct utimbuf newtimebuf;
00673        struct utimbuf *newtime = &newtimebuf;
00674 
00675        if (zend_parse_parameters(argc TSRMLS_CC, "s|ll", &filename, &filename_len, &filetime, &fileatime) == FAILURE) {
00676               return;
00677        }
00678 
00679        if (strlen(filename) != filename_len) {
00680               RETURN_FALSE;
00681        }
00682 
00683        switch (argc) {
00684               case 1:
00685 #ifdef HAVE_UTIME_NULL
00686                      newtime = NULL;
00687 #else
00688                      newtime->modtime = newtime->actime = time(NULL);
00689 #endif
00690                      break;
00691               case 2:
00692                      newtime->modtime = newtime->actime = filetime;
00693                      break;
00694               case 3:
00695                      newtime->modtime = filetime;
00696                      newtime->actime = fileatime;
00697                      break;
00698               default:
00699                      /* Never reached */
00700                      WRONG_PARAM_COUNT;
00701        }
00702 
00703        /* Safe-mode */
00704        if (PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
00705               RETURN_FALSE;
00706        }
00707 
00708        /* Check the basedir */
00709        if (php_check_open_basedir(filename TSRMLS_CC)) {
00710               RETURN_FALSE;
00711        }
00712 
00713        /* create the file if it doesn't exist already */
00714        if (VCWD_ACCESS(filename, F_OK) != 0) {
00715               file = VCWD_FOPEN(filename, "w");
00716               if (file == NULL) {
00717                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create file %s because %s", filename, strerror(errno));
00718                      RETURN_FALSE;
00719               }
00720               fclose(file);
00721        }
00722 
00723        ret = VCWD_UTIME(filename, newtime);
00724        if (ret == -1) {
00725               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Utime failed: %s", strerror(errno));
00726               RETURN_FALSE;
00727        }
00728        RETURN_TRUE;
00729 }
00730 /* }}} */
00731 #endif
00732 
00733 /* {{{ php_clear_stat_cache()
00734 */
00735 PHPAPI void php_clear_stat_cache(zend_bool clear_realpath_cache, const char *filename, int filename_len TSRMLS_DC)
00736 {
00737        /* always clear CurrentStatFile and CurrentLStatFile even if filename is not NULL
00738         * as it may contain outdated data (e.g. "nlink" for a directory when deleting a file
00739         * in this directory, as shown by lstat_stat_variation9.phpt) */
00740 
00741        if (BG(CurrentStatFile)) {
00742               efree(BG(CurrentStatFile));
00743               BG(CurrentStatFile) = NULL;
00744        }
00745        if (BG(CurrentLStatFile)) {
00746               efree(BG(CurrentLStatFile));
00747               BG(CurrentLStatFile) = NULL;
00748        }
00749        if (clear_realpath_cache) {
00750               if (filename != NULL) {
00751                      realpath_cache_del(filename, filename_len TSRMLS_CC);
00752               } else {
00753                      realpath_cache_clean(TSRMLS_C);
00754               }
00755        }
00756 }
00757 /* }}} */
00758 
00759 /* {{{ proto void clearstatcache([bool clear_realpath_cache[, string filename]])
00760    Clear file stat cache */
00761 PHP_FUNCTION(clearstatcache)
00762 {
00763        zend_bool  clear_realpath_cache = 0;
00764        char      *filename             = NULL;
00765        int        filename_len         = 0;
00766 
00767        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|bs", &clear_realpath_cache, &filename, &filename_len) == FAILURE) {
00768               return;
00769        }
00770 
00771        php_clear_stat_cache(clear_realpath_cache, filename, filename_len TSRMLS_CC);
00772 }
00773 /* }}} */
00774 
00775 #define IS_LINK_OPERATION(__t) ((__t) == FS_TYPE || (__t) == FS_IS_LINK || (__t) == FS_LSTAT)
00776 #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)
00777 #define IS_ABLE_CHECK(__t) ((__t) == FS_IS_R || (__t) == FS_IS_W || (__t) == FS_IS_X)
00778 #define IS_ACCESS_CHECK(__t) (IS_ABLE_CHECK(type) || (__t) == FS_EXISTS)
00779 
00780 /* {{{ php_stat
00781  */
00782 PHPAPI void php_stat(const char *filename, php_stat_len filename_length, int type, zval *return_value TSRMLS_DC)
00783 {
00784        zval *stat_dev, *stat_ino, *stat_mode, *stat_nlink, *stat_uid, *stat_gid, *stat_rdev,
00785                *stat_size, *stat_atime, *stat_mtime, *stat_ctime, *stat_blksize, *stat_blocks;
00786        struct stat *stat_sb;
00787        php_stream_statbuf ssb;
00788        int flags = 0, rmask=S_IROTH, wmask=S_IWOTH, xmask=S_IXOTH; /* access rights defaults to other */
00789        char *stat_sb_names[13] = {
00790               "dev", "ino", "mode", "nlink", "uid", "gid", "rdev",
00791               "size", "atime", "mtime", "ctime", "blksize", "blocks"
00792        };
00793        char *local;
00794        php_stream_wrapper *wrapper;
00795        char safe_mode_buf[MAXPATHLEN];
00796 
00797        if (!filename_length) {
00798               RETURN_FALSE;
00799        }
00800 
00801        if (strlen(filename) != filename_length) {
00802               RETURN_FALSE;
00803        }
00804 
00805        if ((wrapper = php_stream_locate_url_wrapper(filename, &local, 0 TSRMLS_CC)) == &php_plain_files_wrapper) {
00806               if (php_check_open_basedir(local TSRMLS_CC)) {
00807                      RETURN_FALSE;
00808               } else if (PG(safe_mode)) {
00809                      if (type == FS_IS_X) {
00810                             if (strstr(local, "..")) {
00811                                    RETURN_FALSE;
00812                             } else {
00813                                    char *b = strrchr(local, PHP_DIR_SEPARATOR);
00814                                    snprintf(safe_mode_buf, MAXPATHLEN, "%s%s%s", PG(safe_mode_exec_dir), (b ? "" : "/"), (b ? b : local));
00815                                    local = (char *)&safe_mode_buf;
00816                             }
00817                      } else if (!php_checkuid_ex(local, NULL, CHECKUID_ALLOW_FILE_NOT_EXISTS, CHECKUID_NO_ERRORS)) {
00818                             RETURN_FALSE;
00819                      }
00820               }
00821        }
00822 
00823        if (IS_ACCESS_CHECK(type)) {
00824               if (wrapper == &php_plain_files_wrapper) {
00825 
00826                      switch (type) {
00827 #ifdef F_OK
00828                             case FS_EXISTS:
00829                                    RETURN_BOOL(VCWD_ACCESS(local, F_OK) == 0);
00830                                    break;
00831 #endif
00832 #ifdef W_OK
00833                             case FS_IS_W:
00834                                    RETURN_BOOL(VCWD_ACCESS(local, W_OK) == 0);
00835                                    break;
00836 #endif
00837 #ifdef R_OK
00838                             case FS_IS_R:
00839                                    RETURN_BOOL(VCWD_ACCESS(local, R_OK) == 0);
00840                                    break;
00841 #endif
00842 #ifdef X_OK
00843                             case FS_IS_X:
00844                                    RETURN_BOOL(VCWD_ACCESS(local, X_OK) == 0);
00845                                    break;
00846 #endif
00847                      }
00848               }
00849        }
00850 
00851        if (IS_LINK_OPERATION(type)) {
00852               flags |= PHP_STREAM_URL_STAT_LINK;
00853        }
00854        if (IS_EXISTS_CHECK(type)) {
00855               flags |= PHP_STREAM_URL_STAT_QUIET;
00856        }
00857 
00858        if (php_stream_stat_path_ex((char *)filename, flags, &ssb, NULL)) {
00859               /* Error Occured */
00860               if (!IS_EXISTS_CHECK(type)) {
00861                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "%sstat failed for %s", IS_LINK_OPERATION(type) ? "L" : "", filename);
00862               }
00863               RETURN_FALSE;
00864        }
00865 
00866        stat_sb = &ssb.sb;
00867 
00868 
00869 #ifndef NETWARE
00870        if (type >= FS_IS_W && type <= FS_IS_X) {
00871               if(ssb.sb.st_uid==getuid()) {
00872                      rmask=S_IRUSR;
00873                      wmask=S_IWUSR;
00874                      xmask=S_IXUSR;
00875               } else if(ssb.sb.st_gid==getgid()) {
00876                      rmask=S_IRGRP;
00877                      wmask=S_IWGRP;
00878                      xmask=S_IXGRP;
00879               } else {
00880                      int   groups, n, i;
00881                      gid_t *gids;
00882 
00883                      groups = getgroups(0, NULL);
00884                      if(groups > 0) {
00885                             gids=(gid_t *)safe_emalloc(groups, sizeof(gid_t), 0);
00886                             n=getgroups(groups, gids);
00887                             for(i=0;i<n;i++){
00888                                    if(ssb.sb.st_gid==gids[i]) {
00889                                           rmask=S_IRGRP;
00890                                           wmask=S_IWGRP;
00891                                           xmask=S_IXGRP;
00892                                           break;
00893                                    }
00894                             }
00895                             efree(gids);
00896                      }
00897               }
00898        }
00899 #endif
00900 
00901 #ifndef NETWARE
00902        if (IS_ABLE_CHECK(type) && getuid() == 0) {
00903               /* root has special perms on plain_wrapper
00904                  But we don't know about root under Netware */
00905               if (wrapper == &php_plain_files_wrapper) {
00906                      if (type == FS_IS_X) {
00907                             xmask = S_IXROOT;
00908                      } else {
00909                             RETURN_TRUE;
00910                      }
00911               }
00912        }
00913 #endif
00914 
00915        switch (type) {
00916        case FS_PERMS:
00917               RETURN_LONG((long)ssb.sb.st_mode);
00918        case FS_INODE:
00919               RETURN_LONG((long)ssb.sb.st_ino);
00920        case FS_SIZE:
00921               RETURN_LONG((long)ssb.sb.st_size);
00922        case FS_OWNER:
00923               RETURN_LONG((long)ssb.sb.st_uid);
00924        case FS_GROUP:
00925               RETURN_LONG((long)ssb.sb.st_gid);
00926        case FS_ATIME:
00927               RETURN_LONG((long)ssb.sb.st_atime);
00928        case FS_MTIME:
00929               RETURN_LONG((long)ssb.sb.st_mtime);
00930        case FS_CTIME:
00931               RETURN_LONG((long)ssb.sb.st_ctime);
00932        case FS_TYPE:
00933               if (S_ISLNK(ssb.sb.st_mode)) {
00934                      RETURN_STRING("link", 1);
00935               }
00936               switch(ssb.sb.st_mode & S_IFMT) {
00937               case S_IFIFO: RETURN_STRING("fifo", 1);
00938               case S_IFCHR: RETURN_STRING("char", 1);
00939               case S_IFDIR: RETURN_STRING("dir", 1);
00940               case S_IFBLK: RETURN_STRING("block", 1);
00941               case S_IFREG: RETURN_STRING("file", 1);
00942 #if defined(S_IFSOCK) && !defined(ZEND_WIN32)&&!defined(__BEOS__)
00943               case S_IFSOCK: RETURN_STRING("socket", 1);
00944 #endif
00945               }
00946               php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unknown file type (%d)", ssb.sb.st_mode&S_IFMT);
00947               RETURN_STRING("unknown", 1);
00948        case FS_IS_W:
00949               RETURN_BOOL((ssb.sb.st_mode & wmask) != 0);
00950        case FS_IS_R:
00951               RETURN_BOOL((ssb.sb.st_mode&rmask)!=0);
00952        case FS_IS_X:
00953               RETURN_BOOL((ssb.sb.st_mode&xmask)!=0 && !S_ISDIR(ssb.sb.st_mode));
00954        case FS_IS_FILE:
00955               RETURN_BOOL(S_ISREG(ssb.sb.st_mode));
00956        case FS_IS_DIR:
00957               RETURN_BOOL(S_ISDIR(ssb.sb.st_mode));
00958        case FS_IS_LINK:
00959               RETURN_BOOL(S_ISLNK(ssb.sb.st_mode));
00960        case FS_EXISTS:
00961               RETURN_TRUE; /* the false case was done earlier */
00962        case FS_LSTAT:
00963               /* FALLTHROUGH */
00964        case FS_STAT:
00965               array_init(return_value);
00966 
00967               MAKE_LONG_ZVAL_INCREF(stat_dev, stat_sb->st_dev);
00968               MAKE_LONG_ZVAL_INCREF(stat_ino, stat_sb->st_ino);
00969               MAKE_LONG_ZVAL_INCREF(stat_mode, stat_sb->st_mode);
00970               MAKE_LONG_ZVAL_INCREF(stat_nlink, stat_sb->st_nlink);
00971               MAKE_LONG_ZVAL_INCREF(stat_uid, stat_sb->st_uid);
00972               MAKE_LONG_ZVAL_INCREF(stat_gid, stat_sb->st_gid);
00973 #ifdef HAVE_ST_RDEV
00974               MAKE_LONG_ZVAL_INCREF(stat_rdev, stat_sb->st_rdev);
00975 #else
00976               MAKE_LONG_ZVAL_INCREF(stat_rdev, -1);
00977 #endif
00978               MAKE_LONG_ZVAL_INCREF(stat_size, stat_sb->st_size);
00979               MAKE_LONG_ZVAL_INCREF(stat_atime, stat_sb->st_atime);
00980               MAKE_LONG_ZVAL_INCREF(stat_mtime, stat_sb->st_mtime);
00981               MAKE_LONG_ZVAL_INCREF(stat_ctime, stat_sb->st_ctime);
00982 #ifdef HAVE_ST_BLKSIZE
00983               MAKE_LONG_ZVAL_INCREF(stat_blksize, stat_sb->st_blksize);
00984 #else
00985               MAKE_LONG_ZVAL_INCREF(stat_blksize,-1);
00986 #endif
00987 #ifdef HAVE_ST_BLOCKS
00988               MAKE_LONG_ZVAL_INCREF(stat_blocks, stat_sb->st_blocks);
00989 #else
00990               MAKE_LONG_ZVAL_INCREF(stat_blocks,-1);
00991 #endif
00992               /* Store numeric indexes in propper order */
00993               zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_dev, sizeof(zval *), NULL);
00994               zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_ino, sizeof(zval *), NULL);
00995               zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_mode, sizeof(zval *), NULL);
00996               zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_nlink, sizeof(zval *), NULL);
00997               zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_uid, sizeof(zval *), NULL);
00998               zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_gid, sizeof(zval *), NULL);
00999 
01000               zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_rdev, sizeof(zval *), NULL);
01001               zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_size, sizeof(zval *), NULL);
01002               zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_atime, sizeof(zval *), NULL);
01003               zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_mtime, sizeof(zval *), NULL);
01004               zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_ctime, sizeof(zval *), NULL);
01005               zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_blksize, sizeof(zval *), NULL);
01006               zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_blocks, sizeof(zval *), NULL);
01007 
01008               /* Store string indexes referencing the same zval*/
01009               zend_hash_update(HASH_OF(return_value), stat_sb_names[0], strlen(stat_sb_names[0])+1, (void *) &stat_dev, sizeof(zval *), NULL);
01010               zend_hash_update(HASH_OF(return_value), stat_sb_names[1], strlen(stat_sb_names[1])+1, (void *) &stat_ino, sizeof(zval *), NULL);
01011               zend_hash_update(HASH_OF(return_value), stat_sb_names[2], strlen(stat_sb_names[2])+1, (void *) &stat_mode, sizeof(zval *), NULL);
01012               zend_hash_update(HASH_OF(return_value), stat_sb_names[3], strlen(stat_sb_names[3])+1, (void *) &stat_nlink, sizeof(zval *), NULL);
01013               zend_hash_update(HASH_OF(return_value), stat_sb_names[4], strlen(stat_sb_names[4])+1, (void *) &stat_uid, sizeof(zval *), NULL);
01014               zend_hash_update(HASH_OF(return_value), stat_sb_names[5], strlen(stat_sb_names[5])+1, (void *) &stat_gid, sizeof(zval *), NULL);
01015               zend_hash_update(HASH_OF(return_value), stat_sb_names[6], strlen(stat_sb_names[6])+1, (void *) &stat_rdev, sizeof(zval *), NULL);
01016               zend_hash_update(HASH_OF(return_value), stat_sb_names[7], strlen(stat_sb_names[7])+1, (void *) &stat_size, sizeof(zval *), NULL);
01017               zend_hash_update(HASH_OF(return_value), stat_sb_names[8], strlen(stat_sb_names[8])+1, (void *) &stat_atime, sizeof(zval *), NULL);
01018               zend_hash_update(HASH_OF(return_value), stat_sb_names[9], strlen(stat_sb_names[9])+1, (void *) &stat_mtime, sizeof(zval *), NULL);
01019               zend_hash_update(HASH_OF(return_value), stat_sb_names[10], strlen(stat_sb_names[10])+1, (void *) &stat_ctime, sizeof(zval *), NULL);
01020               zend_hash_update(HASH_OF(return_value), stat_sb_names[11], strlen(stat_sb_names[11])+1, (void *) &stat_blksize, sizeof(zval *), NULL);
01021               zend_hash_update(HASH_OF(return_value), stat_sb_names[12], strlen(stat_sb_names[12])+1, (void *) &stat_blocks, sizeof(zval *), NULL);
01022 
01023               return;
01024        }
01025        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Didn't understand stat call");
01026        RETURN_FALSE;
01027 }
01028 /* }}} */
01029 
01030 /* another quickie macro to make defining similar functions easier */
01031 /* {{{ FileFunction(name, funcnum) */
01032 #define FileFunction(name, funcnum) \
01033 void name(INTERNAL_FUNCTION_PARAMETERS) { \
01034        char *filename; \
01035        int filename_len; \
01036        \
01037        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) { \
01038               return; \
01039        } \
01040        \
01041        php_stat(filename, (php_stat_len) filename_len, funcnum, return_value TSRMLS_CC); \
01042 }
01043 /* }}} */
01044 
01045 /* {{{ proto int fileperms(string filename)
01046    Get file permissions */
01047 FileFunction(PHP_FN(fileperms), FS_PERMS)
01048 /* }}} */
01049 
01050 /* {{{ proto int fileinode(string filename)
01051    Get file inode */
01052 FileFunction(PHP_FN(fileinode), FS_INODE)
01053 /* }}} */
01054 
01055 /* {{{ proto int filesize(string filename)
01056    Get file size */
01057 FileFunction(PHP_FN(filesize), FS_SIZE)
01058 /* }}} */
01059 
01060 /* {{{ proto int fileowner(string filename)
01061    Get file owner */
01062 FileFunction(PHP_FN(fileowner), FS_OWNER)
01063 /* }}} */
01064 
01065 /* {{{ proto int filegroup(string filename)
01066    Get file group */
01067 FileFunction(PHP_FN(filegroup), FS_GROUP)
01068 /* }}} */
01069 
01070 /* {{{ proto int fileatime(string filename)
01071    Get last access time of file */
01072 FileFunction(PHP_FN(fileatime), FS_ATIME)
01073 /* }}} */
01074 
01075 /* {{{ proto int filemtime(string filename)
01076    Get last modification time of file */
01077 FileFunction(PHP_FN(filemtime), FS_MTIME)
01078 /* }}} */
01079 
01080 /* {{{ proto int filectime(string filename)
01081    Get inode modification time of file */
01082 FileFunction(PHP_FN(filectime), FS_CTIME)
01083 /* }}} */
01084 
01085 /* {{{ proto string filetype(string filename)
01086    Get file type */
01087 FileFunction(PHP_FN(filetype), FS_TYPE)
01088 /* }}} */
01089 
01090 /* {{{ proto bool is_writable(string filename)
01091    Returns true if file can be written */
01092 FileFunction(PHP_FN(is_writable), FS_IS_W)
01093 /* }}} */
01094 
01095 /* {{{ proto bool is_readable(string filename)
01096    Returns true if file can be read */
01097 FileFunction(PHP_FN(is_readable), FS_IS_R)
01098 /* }}} */
01099 
01100 /* {{{ proto bool is_executable(string filename)
01101    Returns true if file is executable */
01102 FileFunction(PHP_FN(is_executable), FS_IS_X)
01103 /* }}} */
01104 
01105 /* {{{ proto bool is_file(string filename)
01106    Returns true if file is a regular file */
01107 FileFunction(PHP_FN(is_file), FS_IS_FILE)
01108 /* }}} */
01109 
01110 /* {{{ proto bool is_dir(string filename)
01111    Returns true if file is directory */
01112 FileFunction(PHP_FN(is_dir), FS_IS_DIR)
01113 /* }}} */
01114 
01115 /* {{{ proto bool is_link(string filename)
01116    Returns true if file is symbolic link */
01117 FileFunction(PHP_FN(is_link), FS_IS_LINK)
01118 /* }}} */
01119 
01120 /* {{{ proto bool file_exists(string filename)
01121    Returns true if filename exists */
01122 FileFunction(PHP_FN(file_exists), FS_EXISTS)
01123 /* }}} */
01124 
01125 /* {{{ proto array lstat(string filename)
01126    Give information about a file or symbolic link */
01127 FileFunction(php_if_lstat, FS_LSTAT)
01128 /* }}} */
01129 
01130 /* {{{ proto array stat(string filename)
01131    Give information about a file */
01132 FileFunction(php_if_stat, FS_STAT)
01133 /* }}} */
01134 
01135 /* {{{ proto bool realpath_cache_size()
01136    Get current size of realpath cache */
01137 PHP_FUNCTION(realpath_cache_size)
01138 {
01139        if (zend_parse_parameters_none() == FAILURE) {
01140               return;
01141        }
01142        RETURN_LONG(realpath_cache_size(TSRMLS_C));
01143 }
01144 
01145 /* {{{ proto bool realpath_cache_get()
01146    Get current size of realpath cache */
01147 PHP_FUNCTION(realpath_cache_get)
01148 {
01149        realpath_cache_bucket **buckets = realpath_cache_get_buckets(TSRMLS_C), **end = buckets + realpath_cache_max_buckets(TSRMLS_C);
01150 
01151        if (zend_parse_parameters_none() == FAILURE) {
01152               return;
01153        }
01154 
01155        array_init(return_value);
01156        while(buckets < end) {
01157               realpath_cache_bucket *bucket = *buckets;
01158               while(bucket) {
01159                      zval *entry;
01160                      MAKE_STD_ZVAL(entry);
01161                      array_init(entry);
01162 
01163                      add_assoc_long(entry, "key", bucket->key);
01164                      add_assoc_bool(entry, "is_dir", bucket->is_dir);
01165                      add_assoc_stringl(entry, "realpath", bucket->realpath, bucket->realpath_len, 1);
01166                      add_assoc_long(entry, "expires", bucket->expires);
01167 #ifdef PHP_WIN32
01168                      add_assoc_bool(entry, "is_rvalid", bucket->is_rvalid);
01169                      add_assoc_bool(entry, "is_wvalid", bucket->is_wvalid);
01170                      add_assoc_bool(entry, "is_readable", bucket->is_readable);
01171                      add_assoc_bool(entry, "is_writable", bucket->is_writable);
01172 #endif
01173                      zend_hash_update(Z_ARRVAL_P(return_value), bucket->path, bucket->path_len+1, &entry, sizeof(zval *), NULL);
01174                      bucket = bucket->next;
01175               }
01176               buckets++;
01177        }
01178 }
01179 
01180 /*
01181  * Local variables:
01182  * tab-width: 4
01183  * c-basic-offset: 4
01184  * End:
01185  * vim600: sw=4 ts=4 fdm=marker
01186  * vim<600: sw=4 ts=4
01187  */