Annotation of embedaddon/php/ext/standard/dir.c, revision 1.1.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>