Annotation of embedaddon/php/ext/standard/dir.c, revision 1.1

1.1     ! misho       1: /*
        !             2:    +----------------------------------------------------------------------+
        !             3:    | PHP Version 5                                                        |
        !             4:    +----------------------------------------------------------------------+
        !             5:    | Copyright (c) 1997-2012 The PHP Group                                |
        !             6:    +----------------------------------------------------------------------+
        !             7:    | This source file is subject to version 3.01 of the PHP license,      |
        !             8:    | that is bundled with this package in the file LICENSE, and is        |
        !             9:    | available through the world-wide-web at the following url:           |
        !            10:    | http://www.php.net/license/3_01.txt                                  |
        !            11:    | If you did not receive a copy of the PHP license and are unable to   |
        !            12:    | obtain it through the world-wide-web, please send a note to          |
        !            13:    | license@php.net so we can mail you a copy immediately.               |
        !            14:    +----------------------------------------------------------------------+
        !            15:    | Author: Thies C. Arntzen <thies@thieso.net>                          |
        !            16:    +----------------------------------------------------------------------+
        !            17:  */
        !            18: 
        !            19: /* $Id: dir.c 321634 2012-01-01 13:15:04Z felipe $ */
        !            20: 
        !            21: /* {{{ includes/startup/misc */
        !            22: 
        !            23: #include "php.h"
        !            24: #include "fopen_wrappers.h"
        !            25: #include "file.h"
        !            26: #include "php_dir.h"
        !            27: #include "php_string.h"
        !            28: #include "php_scandir.h"
        !            29: #include "basic_functions.h"
        !            30: 
        !            31: #ifdef HAVE_DIRENT_H
        !            32: #include <dirent.h>
        !            33: #endif
        !            34: 
        !            35: #if HAVE_UNISTD_H
        !            36: #include <unistd.h>
        !            37: #endif
        !            38: 
        !            39: #include <errno.h>
        !            40: 
        !            41: #ifdef PHP_WIN32
        !            42: #include "win32/readdir.h"
        !            43: #endif
        !            44: 
        !            45: 
        !            46: #ifdef HAVE_GLOB
        !            47: #ifndef PHP_WIN32
        !            48: #include <glob.h>
        !            49: #else
        !            50: #include "win32/glob.h"
        !            51: #endif
        !            52: #endif
        !            53: 
        !            54: typedef struct {
        !            55:        int default_dir;
        !            56: } php_dir_globals;
        !            57: 
        !            58: #ifdef ZTS
        !            59: #define DIRG(v) TSRMG(dir_globals_id, php_dir_globals *, v)
        !            60: int dir_globals_id;
        !            61: #else
        !            62: #define DIRG(v) (dir_globals.v)
        !            63: php_dir_globals dir_globals;
        !            64: #endif
        !            65: 
        !            66: #if 0
        !            67: typedef struct {
        !            68:        int id;
        !            69:        DIR *dir;
        !            70: } php_dir;
        !            71: 
        !            72: static int le_dirp;
        !            73: #endif
        !            74: 
        !            75: static zend_class_entry *dir_class_entry_ptr;
        !            76: 
        !            77: #define FETCH_DIRP() \
        !            78:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &id) == FAILURE) { \
        !            79:                return; \
        !            80:        } \
        !            81:        if (ZEND_NUM_ARGS() == 0) { \
        !            82:                myself = getThis(); \
        !            83:                if (myself) { \
        !            84:                        if (zend_hash_find(Z_OBJPROP_P(myself), "handle", sizeof("handle"), (void **)&tmp) == FAILURE) { \
        !            85:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find my handle property"); \
        !            86:                                RETURN_FALSE; \
        !            87:                        } \
        !            88:                        ZEND_FETCH_RESOURCE(dirp, php_stream *, tmp, -1, "Directory", php_file_le_stream()); \
        !            89:                } else { \
        !            90:                        ZEND_FETCH_RESOURCE(dirp, php_stream *, 0, DIRG(default_dir), "Directory", php_file_le_stream()); \
        !            91:                } \
        !            92:        } else { \
        !            93:                dirp = (php_stream *) zend_fetch_resource(&id TSRMLS_CC, -1, "Directory", NULL, 1, php_file_le_stream()); \
        !            94:                if (!dirp) \
        !            95:                        RETURN_FALSE; \
        !            96:        } 
        !            97:        
        !            98: /* {{{ arginfo */
        !            99: ZEND_BEGIN_ARG_INFO_EX(arginfo_dir, 0, 0, 0)
        !           100:        ZEND_ARG_INFO(0, dir_handle)
        !           101: ZEND_END_ARG_INFO()
        !           102: /* }}} */
        !           103: 
        !           104: static const zend_function_entry php_dir_class_functions[] = {
        !           105:        PHP_FALIAS(close,       closedir,               arginfo_dir)
        !           106:        PHP_FALIAS(rewind,      rewinddir,              arginfo_dir)
        !           107:        PHP_NAMED_FE(read,  php_if_readdir, arginfo_dir)
        !           108:        {NULL, NULL, NULL}
        !           109: };
        !           110: 
        !           111: 
        !           112: static void php_set_default_dir(int id TSRMLS_DC)
        !           113: {
        !           114:        if (DIRG(default_dir)!=-1) {
        !           115:                zend_list_delete(DIRG(default_dir));
        !           116:        }
        !           117: 
        !           118:        if (id != -1) {
        !           119:                zend_list_addref(id);
        !           120:        }
        !           121:        
        !           122:        DIRG(default_dir) = id;
        !           123: }
        !           124: 
        !           125: PHP_RINIT_FUNCTION(dir)
        !           126: {
        !           127:        DIRG(default_dir) = -1;
        !           128:        return SUCCESS;
        !           129: }
        !           130: 
        !           131: PHP_MINIT_FUNCTION(dir)
        !           132: {
        !           133:        static char dirsep_str[2], pathsep_str[2];
        !           134:        zend_class_entry dir_class_entry;
        !           135: 
        !           136:        INIT_CLASS_ENTRY(dir_class_entry, "Directory", php_dir_class_functions);
        !           137:        dir_class_entry_ptr = zend_register_internal_class(&dir_class_entry TSRMLS_CC);
        !           138: 
        !           139: #ifdef ZTS
        !           140:        ts_allocate_id(&dir_globals_id, sizeof(php_dir_globals), NULL, NULL);
        !           141: #endif
        !           142: 
        !           143:        dirsep_str[0] = DEFAULT_SLASH;
        !           144:        dirsep_str[1] = '\0';
        !           145:        REGISTER_STRING_CONSTANT("DIRECTORY_SEPARATOR", dirsep_str, CONST_CS|CONST_PERSISTENT);
        !           146: 
        !           147:        pathsep_str[0] = ZEND_PATHS_SEPARATOR;
        !           148:        pathsep_str[1] = '\0';
        !           149:        REGISTER_STRING_CONSTANT("PATH_SEPARATOR", pathsep_str, CONST_CS|CONST_PERSISTENT);
        !           150: 
        !           151: #ifdef HAVE_GLOB
        !           152: 
        !           153: #ifdef GLOB_BRACE
        !           154:        REGISTER_LONG_CONSTANT("GLOB_BRACE", GLOB_BRACE, CONST_CS | CONST_PERSISTENT);
        !           155: #else
        !           156: # define GLOB_BRACE 0
        !           157: #endif
        !           158: 
        !           159: #ifdef GLOB_MARK
        !           160:        REGISTER_LONG_CONSTANT("GLOB_MARK", GLOB_MARK, CONST_CS | CONST_PERSISTENT);
        !           161: #else
        !           162: # define GLOB_MARK 0
        !           163: #endif
        !           164: 
        !           165: #ifdef GLOB_NOSORT
        !           166:        REGISTER_LONG_CONSTANT("GLOB_NOSORT", GLOB_NOSORT, CONST_CS | CONST_PERSISTENT);
        !           167: #else 
        !           168: # define GLOB_NOSORT 0
        !           169: #endif
        !           170: 
        !           171: #ifdef GLOB_NOCHECK
        !           172:        REGISTER_LONG_CONSTANT("GLOB_NOCHECK", GLOB_NOCHECK, CONST_CS | CONST_PERSISTENT);
        !           173: #else 
        !           174: # define GLOB_NOCHECK 0
        !           175: #endif
        !           176: 
        !           177: #ifdef GLOB_NOESCAPE
        !           178:        REGISTER_LONG_CONSTANT("GLOB_NOESCAPE", GLOB_NOESCAPE, CONST_CS | CONST_PERSISTENT);
        !           179: #else 
        !           180: # define GLOB_NOESCAPE 0
        !           181: #endif
        !           182: 
        !           183: #ifdef GLOB_ERR
        !           184:        REGISTER_LONG_CONSTANT("GLOB_ERR", GLOB_ERR, CONST_CS | CONST_PERSISTENT);
        !           185: #else 
        !           186: # define GLOB_ERR 0
        !           187: #endif
        !           188: 
        !           189: #ifndef GLOB_ONLYDIR
        !           190: # define GLOB_ONLYDIR (1<<30)
        !           191: # define GLOB_EMULATE_ONLYDIR
        !           192: # define GLOB_FLAGMASK (~GLOB_ONLYDIR)
        !           193: #else
        !           194: # define GLOB_FLAGMASK (~0)
        !           195: #endif
        !           196: 
        !           197: /* This is used for checking validity of passed flags (passing invalid flags causes segfault in glob()!! */
        !           198: #define GLOB_AVAILABLE_FLAGS (0 | GLOB_BRACE | GLOB_MARK | GLOB_NOSORT | GLOB_NOCHECK | GLOB_NOESCAPE | GLOB_ERR | GLOB_ONLYDIR)
        !           199: 
        !           200:        REGISTER_LONG_CONSTANT("GLOB_ONLYDIR", GLOB_ONLYDIR, CONST_CS | CONST_PERSISTENT);
        !           201:        REGISTER_LONG_CONSTANT("GLOB_AVAILABLE_FLAGS", GLOB_AVAILABLE_FLAGS, CONST_CS | CONST_PERSISTENT);
        !           202: 
        !           203: #endif /* HAVE_GLOB */
        !           204: 
        !           205:        return SUCCESS;
        !           206: }
        !           207: /* }}} */
        !           208: 
        !           209: /* {{{ internal functions */
        !           210: static void _php_do_opendir(INTERNAL_FUNCTION_PARAMETERS, int createobject)
        !           211: {
        !           212:        char *dirname;
        !           213:        int dir_len;
        !           214:        zval *zcontext = NULL;
        !           215:        php_stream_context *context = NULL;
        !           216:        php_stream *dirp;
        !           217: 
        !           218:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|r", &dirname, &dir_len, &zcontext) == FAILURE) {
        !           219:                RETURN_NULL();
        !           220:        }
        !           221: 
        !           222:        context = php_stream_context_from_zval(zcontext, 0);
        !           223:        
        !           224:        dirp = php_stream_opendir(dirname, ENFORCE_SAFE_MODE|REPORT_ERRORS, context);
        !           225: 
        !           226:        if (dirp == NULL) {
        !           227:                RETURN_FALSE;
        !           228:        }
        !           229: 
        !           230:        dirp->flags |= PHP_STREAM_FLAG_NO_FCLOSE;
        !           231:                
        !           232:        php_set_default_dir(dirp->rsrc_id TSRMLS_CC);
        !           233: 
        !           234:        if (createobject) {
        !           235:                object_init_ex(return_value, dir_class_entry_ptr);
        !           236:                add_property_stringl(return_value, "path", dirname, dir_len, 1);
        !           237:                add_property_resource(return_value, "handle", dirp->rsrc_id);
        !           238:                php_stream_auto_cleanup(dirp); /* so we don't get warnings under debug */
        !           239:        } else {
        !           240:                php_stream_to_zval(dirp, return_value);
        !           241:        }
        !           242: }
        !           243: /* }}} */
        !           244: 
        !           245: /* {{{ proto mixed opendir(string path[, resource context])
        !           246:    Open a directory and return a dir_handle */
        !           247: PHP_FUNCTION(opendir)
        !           248: {
        !           249:        _php_do_opendir(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
        !           250: }
        !           251: /* }}} */
        !           252: 
        !           253: /* {{{ proto object dir(string directory[, resource context])
        !           254:    Directory class with properties, handle and class and methods read, rewind and close */
        !           255: PHP_FUNCTION(getdir)
        !           256: {
        !           257:        _php_do_opendir(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
        !           258: }
        !           259: /* }}} */
        !           260: 
        !           261: /* {{{ proto void closedir([resource dir_handle])
        !           262:    Close directory connection identified by the dir_handle */
        !           263: PHP_FUNCTION(closedir)
        !           264: {
        !           265:        zval *id = NULL, **tmp, *myself;
        !           266:        php_stream *dirp;
        !           267:        int rsrc_id;
        !           268: 
        !           269:        FETCH_DIRP();
        !           270: 
        !           271:        if (!(dirp->flags & PHP_STREAM_FLAG_IS_DIR)) {
        !           272:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "%d is not a valid Directory resource", dirp->rsrc_id);
        !           273:                RETURN_FALSE;
        !           274:        }
        !           275: 
        !           276:        rsrc_id = dirp->rsrc_id;
        !           277:        zend_list_delete(dirp->rsrc_id);
        !           278: 
        !           279:        if (rsrc_id == DIRG(default_dir)) {
        !           280:                php_set_default_dir(-1 TSRMLS_CC);
        !           281:        }
        !           282: }
        !           283: /* }}} */
        !           284: 
        !           285: #if defined(HAVE_CHROOT) && !defined(ZTS) && ENABLE_CHROOT_FUNC
        !           286: /* {{{ proto bool chroot(string directory)
        !           287:    Change root directory */
        !           288: PHP_FUNCTION(chroot)
        !           289: {
        !           290:        char *str;
        !           291:        int ret, str_len;
        !           292:        
        !           293:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) {
        !           294:                RETURN_FALSE;
        !           295:        }
        !           296:        
        !           297:        ret = chroot(str);
        !           298:        if (ret != 0) {
        !           299:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s (errno %d)", strerror(errno), errno);
        !           300:                RETURN_FALSE;
        !           301:        }
        !           302: 
        !           303:        php_clear_stat_cache(1, NULL, 0 TSRMLS_CC);
        !           304:        
        !           305:        ret = chdir("/");
        !           306:        
        !           307:        if (ret != 0) {
        !           308:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s (errno %d)", strerror(errno), errno);
        !           309:                RETURN_FALSE;
        !           310:        }
        !           311: 
        !           312:        RETURN_TRUE;
        !           313: }
        !           314: /* }}} */
        !           315: #endif
        !           316: 
        !           317: /* {{{ proto bool chdir(string directory)
        !           318:    Change the current directory */
        !           319: PHP_FUNCTION(chdir)
        !           320: {
        !           321:        char *str;
        !           322:        int ret, str_len;
        !           323:        
        !           324:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) {
        !           325:                RETURN_FALSE;
        !           326:        }
        !           327: 
        !           328:        if (strlen(str) != str_len) {
        !           329:                RETURN_FALSE;
        !           330:        }
        !           331: 
        !           332:        if ((PG(safe_mode) && !php_checkuid(str, NULL, CHECKUID_CHECK_FILE_AND_DIR)) || php_check_open_basedir(str TSRMLS_CC)) {
        !           333:                RETURN_FALSE;
        !           334:        }
        !           335:        ret = VCWD_CHDIR(str);
        !           336:        
        !           337:        if (ret != 0) {
        !           338:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s (errno %d)", strerror(errno), errno);
        !           339:                RETURN_FALSE;
        !           340:        }
        !           341: 
        !           342:        if (BG(CurrentStatFile) && !IS_ABSOLUTE_PATH(BG(CurrentStatFile), strlen(BG(CurrentStatFile)))) {
        !           343:                efree(BG(CurrentStatFile));
        !           344:                BG(CurrentStatFile) = NULL;
        !           345:        }
        !           346:        if (BG(CurrentLStatFile) && !IS_ABSOLUTE_PATH(BG(CurrentLStatFile), strlen(BG(CurrentLStatFile)))) {
        !           347:                efree(BG(CurrentLStatFile));
        !           348:                BG(CurrentLStatFile) = NULL;
        !           349:        }
        !           350: 
        !           351:        RETURN_TRUE;
        !           352: }
        !           353: /* }}} */
        !           354: 
        !           355: /* {{{ proto mixed getcwd(void)
        !           356:    Gets the current directory */
        !           357: PHP_FUNCTION(getcwd)
        !           358: {
        !           359:        char path[MAXPATHLEN];
        !           360:        char *ret=NULL;
        !           361:        
        !           362:        if (zend_parse_parameters_none() == FAILURE) {
        !           363:                return;
        !           364:        }
        !           365: 
        !           366: #if HAVE_GETCWD
        !           367:        ret = VCWD_GETCWD(path, MAXPATHLEN);
        !           368: #elif HAVE_GETWD
        !           369:        ret = VCWD_GETWD(path);
        !           370: #endif
        !           371: 
        !           372:        if (ret) {
        !           373:                RETURN_STRING(path, 1);
        !           374:        } else {
        !           375:                RETURN_FALSE;
        !           376:        }
        !           377: }
        !           378: /* }}} */
        !           379: 
        !           380: /* {{{ proto void rewinddir([resource dir_handle])
        !           381:    Rewind dir_handle back to the start */
        !           382: PHP_FUNCTION(rewinddir)
        !           383: {
        !           384:        zval *id = NULL, **tmp, *myself;
        !           385:        php_stream *dirp;
        !           386:        
        !           387:        FETCH_DIRP();
        !           388: 
        !           389:        if (!(dirp->flags & PHP_STREAM_FLAG_IS_DIR)) {
        !           390:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "%d is not a valid Directory resource", dirp->rsrc_id);
        !           391:                RETURN_FALSE;
        !           392:        }
        !           393: 
        !           394:        php_stream_rewinddir(dirp);
        !           395: }
        !           396: /* }}} */
        !           397: 
        !           398: /* {{{ proto string readdir([resource dir_handle])
        !           399:    Read directory entry from dir_handle */
        !           400: PHP_NAMED_FUNCTION(php_if_readdir)
        !           401: {
        !           402:        zval *id = NULL, **tmp, *myself;
        !           403:        php_stream *dirp;
        !           404:        php_stream_dirent entry;
        !           405: 
        !           406:        FETCH_DIRP();
        !           407: 
        !           408:        if (!(dirp->flags & PHP_STREAM_FLAG_IS_DIR)) {
        !           409:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "%d is not a valid Directory resource", dirp->rsrc_id);
        !           410:                RETURN_FALSE;
        !           411:        }
        !           412: 
        !           413:        if (php_stream_readdir(dirp, &entry)) {
        !           414:                RETURN_STRINGL(entry.d_name, strlen(entry.d_name), 1);
        !           415:        }
        !           416:        RETURN_FALSE;
        !           417: }
        !           418: /* }}} */
        !           419: 
        !           420: #ifdef HAVE_GLOB
        !           421: /* {{{ proto array glob(string pattern [, int flags])
        !           422:    Find pathnames matching a pattern */
        !           423: PHP_FUNCTION(glob)
        !           424: {
        !           425:        int cwd_skip = 0;
        !           426: #ifdef ZTS
        !           427:        char cwd[MAXPATHLEN];
        !           428:        char work_pattern[MAXPATHLEN];
        !           429:        char *result;
        !           430: #endif
        !           431:        char *pattern = NULL;
        !           432:        int pattern_len;
        !           433:        long flags = 0;
        !           434:        glob_t globbuf;
        !           435:        int n;
        !           436:        int ret;
        !           437:        zend_bool basedir_limit = 0;
        !           438: 
        !           439:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &pattern, &pattern_len, &flags) == FAILURE) {
        !           440:                return;
        !           441:        }
        !           442: 
        !           443:        if (strlen(pattern) != pattern_len) {
        !           444:                RETURN_FALSE;
        !           445:        }
        !           446: 
        !           447:        if (pattern_len >= MAXPATHLEN) {
        !           448:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Pattern exceeds the maximum allowed length of %d characters", MAXPATHLEN);
        !           449:                RETURN_FALSE;
        !           450:        }
        !           451: 
        !           452:        if ((GLOB_AVAILABLE_FLAGS & flags) != flags) {
        !           453:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "At least one of the passed flags is invalid or not supported on this platform");
        !           454:                RETURN_FALSE;
        !           455:        }
        !           456: 
        !           457: #ifdef ZTS 
        !           458:        if (!IS_ABSOLUTE_PATH(pattern, pattern_len)) {
        !           459:                result = VCWD_GETCWD(cwd, MAXPATHLEN);  
        !           460:                if (!result) {
        !           461:                        cwd[0] = '\0';
        !           462:                }
        !           463: #ifdef PHP_WIN32
        !           464:                if (IS_SLASH(*pattern)) {
        !           465:                        cwd[2] = '\0';
        !           466:                }
        !           467: #endif
        !           468:                cwd_skip = strlen(cwd)+1;
        !           469: 
        !           470:                snprintf(work_pattern, MAXPATHLEN, "%s%c%s", cwd, DEFAULT_SLASH, pattern);
        !           471:                pattern = work_pattern;
        !           472:        } 
        !           473: #endif
        !           474: 
        !           475:        
        !           476:        memset(&globbuf, 0, sizeof(glob_t));
        !           477:        globbuf.gl_offs = 0;
        !           478:        if (0 != (ret = glob(pattern, flags & GLOB_FLAGMASK, NULL, &globbuf))) {
        !           479: #ifdef GLOB_NOMATCH
        !           480:                if (GLOB_NOMATCH == ret) {
        !           481:                        /* Some glob implementation simply return no data if no matches
        !           482:                           were found, others return the GLOB_NOMATCH error code.
        !           483:                           We don't want to treat GLOB_NOMATCH as an error condition
        !           484:                           so that PHP glob() behaves the same on both types of 
        !           485:                           implementations and so that 'foreach (glob() as ...'
        !           486:                           can be used for simple glob() calls without further error
        !           487:                           checking.
        !           488:                        */
        !           489:                        goto no_results;
        !           490:                }
        !           491: #endif
        !           492:                RETURN_FALSE;
        !           493:        }
        !           494: 
        !           495:        /* now catch the FreeBSD style of "no matches" */
        !           496:        if (!globbuf.gl_pathc || !globbuf.gl_pathv) {
        !           497: no_results:
        !           498:                if (PG(safe_mode) || (PG(open_basedir) && *PG(open_basedir))) {
        !           499:                        struct stat s;
        !           500: 
        !           501:                        if (0 != VCWD_STAT(pattern, &s) || S_IFDIR != (s.st_mode & S_IFMT)) {
        !           502:                                RETURN_FALSE;
        !           503:                        }
        !           504:                }
        !           505:                array_init(return_value);
        !           506:                return;
        !           507:        }
        !           508: 
        !           509:        array_init(return_value);
        !           510:        for (n = 0; n < globbuf.gl_pathc; n++) {
        !           511:                if (PG(safe_mode) || (PG(open_basedir) && *PG(open_basedir))) {
        !           512:                        if (PG(safe_mode) && (!php_checkuid_ex(globbuf.gl_pathv[n], NULL, CHECKUID_CHECK_FILE_AND_DIR, CHECKUID_NO_ERRORS))) {
        !           513:                                basedir_limit = 1;
        !           514:                                continue;
        !           515:                        } else if (php_check_open_basedir_ex(globbuf.gl_pathv[n], 0 TSRMLS_CC)) {
        !           516:                                basedir_limit = 1;
        !           517:                                continue;
        !           518:                        }
        !           519:                }
        !           520:                /* we need to do this everytime since GLOB_ONLYDIR does not guarantee that
        !           521:                 * all directories will be filtered. GNU libc documentation states the
        !           522:                 * following: 
        !           523:                 * If the information about the type of the file is easily available 
        !           524:                 * non-directories will be rejected but no extra work will be done to 
        !           525:                 * determine the information for each file. I.e., the caller must still be 
        !           526:                 * able to filter directories out. 
        !           527:                 */
        !           528:                if (flags & GLOB_ONLYDIR) {
        !           529:                        struct stat s;
        !           530: 
        !           531:                        if (0 != VCWD_STAT(globbuf.gl_pathv[n], &s)) {
        !           532:                                continue;
        !           533:                        }
        !           534: 
        !           535:                        if (S_IFDIR != (s.st_mode & S_IFMT)) {
        !           536:                                continue;
        !           537:                        }
        !           538:                }
        !           539:                add_next_index_string(return_value, globbuf.gl_pathv[n]+cwd_skip, 1);
        !           540:        }
        !           541: 
        !           542:        globfree(&globbuf);
        !           543: 
        !           544:        if (basedir_limit && !zend_hash_num_elements(Z_ARRVAL_P(return_value))) {
        !           545:                zval_dtor(return_value);
        !           546:                RETURN_FALSE;
        !           547:        }
        !           548: }
        !           549: /* }}} */
        !           550: #endif 
        !           551: 
        !           552: /* {{{ proto array scandir(string dir [, int sorting_order [, resource context]])
        !           553:    List files & directories inside the specified path */
        !           554: PHP_FUNCTION(scandir)
        !           555: {
        !           556:        char *dirn;
        !           557:        int dirn_len;
        !           558:        long flags = 0;
        !           559:        char **namelist;
        !           560:        int n, i;
        !           561:        zval *zcontext = NULL;
        !           562:        php_stream_context *context = NULL;
        !           563: 
        !           564:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lr", &dirn, &dirn_len, &flags, &zcontext) == FAILURE) {
        !           565:                return;
        !           566:        }
        !           567: 
        !           568:        if (strlen(dirn) != dirn_len) {
        !           569:                RETURN_FALSE;
        !           570:        }
        !           571: 
        !           572:        if (dirn_len < 1) {
        !           573:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Directory name cannot be empty");
        !           574:                RETURN_FALSE;
        !           575:        }
        !           576: 
        !           577:        if (zcontext) {
        !           578:                context = php_stream_context_from_zval(zcontext, 0);
        !           579:        }
        !           580: 
        !           581:        if (!flags) {
        !           582:                n = php_stream_scandir(dirn, &namelist, context, (void *) php_stream_dirent_alphasort);
        !           583:        } else {
        !           584:                n = php_stream_scandir(dirn, &namelist, context, (void *) php_stream_dirent_alphasortr);
        !           585:        }
        !           586:        if (n < 0) {
        !           587:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "(errno %d): %s", errno, strerror(errno));
        !           588:                RETURN_FALSE;
        !           589:        }
        !           590:        
        !           591:        array_init(return_value);
        !           592: 
        !           593:        for (i = 0; i < n; i++) {
        !           594:                add_next_index_string(return_value, namelist[i], 0);
        !           595:        }
        !           596: 
        !           597:        if (n) {
        !           598:                efree(namelist);
        !           599:        }
        !           600: }
        !           601: /* }}} */
        !           602: 
        !           603: /*
        !           604:  * Local variables:
        !           605:  * tab-width: 4
        !           606:  * c-basic-offset: 4
        !           607:  * End:
        !           608:  * vim600: sw=4 ts=4 fdm=marker
        !           609:  * vim<600: sw=4 ts=4
        !           610:  */

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