xref: /PHP-5.5/main/php_scandir.c (revision 73c1be26)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 5                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1997-2015 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: Shane Caraveo <shane@caraveo.com>                            |
16    |         Ilia Alshanetsky <ilia@prohost.org>                          |
17    +----------------------------------------------------------------------+
18  */
19 
20 /* $Id$ */
21 
22 #include "php.h"
23 #include "php_scandir.h"
24 
25 #ifdef HAVE_SYS_TYPES_H
26 #include <sys/types.h>
27 #endif
28 
29 #ifdef HAVE_DIRENT_H
30 #include <dirent.h>
31 #endif
32 
33 #ifndef HAVE_SCANDIR
34 
35 #ifdef PHP_WIN32
36 #include "win32/param.h"
37 #include "win32/readdir.h"
38 #endif
39 
40 #include <stdlib.h>
41 #ifndef NETWARE
42 #include <search.h>
43 #endif
44 
45 #endif /* HAVE_SCANDIR */
46 
47 #ifndef HAVE_ALPHASORT
48 
49 #ifdef HAVE_STRING_H
50 #include <string.h>
51 #endif
52 
php_alphasort(const struct dirent ** a,const struct dirent ** b)53 PHPAPI int php_alphasort(const struct dirent **a, const struct dirent **b)
54 {
55 	return strcoll((*a)->d_name,(*b)->d_name);
56 }
57 #endif /* HAVE_ALPHASORT */
58 
59 #ifndef HAVE_SCANDIR
php_scandir(const char * dirname,struct dirent ** namelist[],int (* selector)(const struct dirent * entry),int (* compare)(const struct dirent ** a,const struct dirent ** b))60 PHPAPI int php_scandir(const char *dirname, struct dirent **namelist[], int (*selector) (const struct dirent *entry), int (*compare) (const struct dirent **a, const struct dirent **b))
61 {
62 	DIR *dirp = NULL;
63 	struct dirent **vector = NULL;
64 	int vector_size = 0;
65 	int nfiles = 0;
66 	char entry[sizeof(struct dirent)+MAXPATHLEN];
67 	struct dirent *dp = (struct dirent *)&entry;
68 
69 	if (namelist == NULL) {
70 		return -1;
71 	}
72 
73 	if (!(dirp = opendir(dirname))) {
74 		return -1;
75 	}
76 
77 	while (!php_readdir_r(dirp, (struct dirent *)entry, &dp) && dp) {
78 		int dsize = 0;
79 		struct dirent *newdp = NULL;
80 
81 		if (selector && (*selector)(dp) == 0) {
82 			continue;
83 		}
84 
85 		if (nfiles == vector_size) {
86 			struct dirent **newv;
87 			if (vector_size == 0) {
88 				vector_size = 10;
89 			} else {
90 				vector_size *= 2;
91 			}
92 
93 			newv = (struct dirent **) realloc (vector, vector_size * sizeof (struct dirent *));
94 			if (!newv) {
95 				return -1;
96 			}
97 			vector = newv;
98 		}
99 
100 		dsize = sizeof (struct dirent) + ((strlen(dp->d_name) + 1) * sizeof(char));
101 		newdp = (struct dirent *) malloc(dsize);
102 
103 		if (newdp == NULL) {
104 			goto fail;
105 		}
106 
107 		vector[nfiles++] = (struct dirent *) memcpy(newdp, dp, dsize);
108 	}
109 
110 	closedir(dirp);
111 
112 	*namelist = vector;
113 
114 	if (compare) {
115 		qsort (*namelist, nfiles, sizeof(struct dirent *), compare);
116 	}
117 
118 	return nfiles;
119 
120 fail:
121 	while (nfiles-- > 0) {
122 		free(vector[nfiles]);
123 	}
124 	free(vector);
125 	return -1;
126 }
127 #endif
128 
129 /*
130  * Local variables:
131  * tab-width: 4
132  * c-basic-offset: 4
133  * End:
134  * vim600: sw=4 ts=4 fdm=marker
135  * vim<600: sw=4 ts=4
136  */
137