Annotation of embedaddon/php/ext/standard/filestat.c, revision 1.1.1.3

1.1       misho       1: /*
                      2:    +----------------------------------------------------------------------+
                      3:    | PHP Version 5                                                        |
                      4:    +----------------------------------------------------------------------+
1.1.1.3 ! misho       5:    | Copyright (c) 1997-2013 The PHP Group                                |
1.1       misho       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: 
1.1.1.2   misho      19: /* $Id$ */
1.1       misho      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: 
1.1.1.2   misho     238:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &path, &path_len) == FAILURE) {
1.1       misho     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: 
1.1.1.2   misho     373:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &path, &path_len) == FAILURE) {
1.1       misho     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)
1.1.1.2   misho     389: PHPAPI int php_get_gid_by_name(const char *name, gid_t *gid TSRMLS_DC)
1.1       misho     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) {
1.1.1.2   misho     398:                        return FAILURE;
1.1       misho     399:                }
                    400: 
                    401:                grbuf = emalloc(grbuflen);
1.1.1.2   misho     402:                if (getgrnam_r(name, &gr, grbuf, grbuflen, &retgrptr) != 0 || retgrptr == NULL) {
1.1       misho     403:                        efree(grbuf);
1.1.1.2   misho     404:                        return FAILURE;
1.1       misho     405:                }
                    406:                efree(grbuf);
1.1.1.2   misho     407:                *gid = gr.gr_gid;
1.1       misho     408: #else
1.1.1.2   misho     409:                struct group *gr = getgrnam(name);
1.1       misho     410: 
                    411:                if (!gr) {
1.1.1.2   misho     412:                        return FAILURE;
1.1       misho     413:                }
1.1.1.2   misho     414:                *gid = gr->gr_gid;
1.1       misho     415: #endif
1.1.1.2   misho     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) {
1.1       misho     432:                RETURN_FALSE;
                    433:        }
                    434: 
1.1.1.2   misho     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));
1.1       misho     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;
1.1.1.2   misho     497: #endif
1.1       misho     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)
1.1.1.2   misho     526: PHPAPI uid_t php_get_uid_by_name(const char *name, uid_t *uid TSRMLS_DC)
1.1       misho     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) {
1.1.1.2   misho     535:                        return FAILURE;
1.1       misho     536:                }
                    537: 
                    538:                pwbuf = emalloc(pwbuflen);
1.1.1.2   misho     539:                if (getpwnam_r(name, &pw, pwbuf, pwbuflen, &retpwptr) != 0 || retpwptr == NULL) {
1.1       misho     540:                        efree(pwbuf);
1.1.1.2   misho     541:                        return FAILURE;
1.1       misho     542:                }
                    543:                efree(pwbuf);
1.1.1.2   misho     544:                *uid = pw.pw_uid;
1.1       misho     545: #else
1.1.1.2   misho     546:                struct passwd *pw = getpwnam(name);
1.1       misho     547: 
                    548:                if (!pw) {
1.1.1.2   misho     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) {
1.1       misho     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:        }
1.1.1.2   misho     634:        RETURN_TRUE;
                    635: #endif
1.1       misho     636: }
                    637: /* }}} */
1.1.1.2   misho     638: 
1.1       misho     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;
1.1.1.2   misho     674:        php_stream_wrapper *wrapper;
1.1       misho     675: 
1.1.1.2   misho     676:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pl", &filename, &filename_len, &mode) == FAILURE) {
1.1       misho     677:                return;
                    678:        }
                    679: 
1.1.1.2   misho     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:                }
1.1       misho     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;
1.1.1.2   misho     722:        php_stream_wrapper *wrapper;
1.1       misho     723: 
1.1.1.2   misho     724:        if (zend_parse_parameters(argc TSRMLS_CC, "p|ll", &filename, &filename_len, &filetime, &fileatime) == FAILURE) {
1.1       misho     725:                return;
                    726:        }
                    727: 
1.1.1.2   misho     728:        if (!filename_len) {
1.1       misho     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: 
1.1.1.2   misho     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:                }
1.1       misho     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
1.1.1.2   misho     806:         * as it may contains outdated data (e.g. "nlink" for a directory when deleting a file
1.1       misho     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: 
1.1.1.2   misho     834:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|bp", &clear_realpath_cache, &filename, &filename_len) == FAILURE) {
1.1       misho     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:        char *local;
                    861:        php_stream_wrapper *wrapper;
                    862: 
                    863:        if (!filename_length) {
                    864:                RETURN_FALSE;
                    865:        }
                    866: 
1.1.1.2   misho     867:        if ((wrapper = php_stream_locate_url_wrapper(filename, &local, 0 TSRMLS_CC)) == &php_plain_files_wrapper && php_check_open_basedir(local TSRMLS_CC)) {
1.1       misho     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)) {
1.1.1.3 ! misho     907:                /* Error Occurred */
1.1       misho     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:        \
1.1.1.2   misho    1085:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) { \
1.1       misho    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: 
1.1.1.3 ! misho    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:                        }
1.1       misho    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:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>