xref: /PHP-7.4/main/php_scandir.c (revision 2b28f718)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 7                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 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 #include "php.h"
21 #include "php_scandir.h"
22 
23 #ifdef HAVE_SYS_TYPES_H
24 #include <sys/types.h>
25 #endif
26 
27 #ifdef HAVE_DIRENT_H
28 #include <dirent.h>
29 #endif
30 
31 #ifndef HAVE_SCANDIR
32 
33 #ifdef PHP_WIN32
34 #include "win32/param.h"
35 #include "win32/readdir.h"
36 #endif
37 
38 #include <stdlib.h>
39 #include <search.h>
40 
41 #endif /* HAVE_SCANDIR */
42 
43 #ifndef HAVE_ALPHASORT
44 
45 #include <string.h>
46 
php_alphasort(const struct dirent ** a,const struct dirent ** b)47 PHPAPI int php_alphasort(const struct dirent **a, const struct dirent **b)
48 {
49 	return strcoll((*a)->d_name,(*b)->d_name);
50 }
51 #endif /* HAVE_ALPHASORT */
52 
53 #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))54 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))
55 {
56 	DIR *dirp = NULL;
57 	struct dirent **vector = NULL;
58 	int vector_size = 0;
59 	int nfiles = 0;
60 	struct dirent *dp;
61 
62 	if (namelist == NULL) {
63 		return -1;
64 	}
65 
66 	if (!(dirp = opendir(dirname))) {
67 		return -1;
68 	}
69 
70 	while ((dp = readdir(dirp))) {
71 		size_t dsize = 0;
72 		struct dirent *newdp = NULL;
73 
74 		if (selector && (*selector)(dp) == 0) {
75 			continue;
76 		}
77 
78 		if (nfiles == vector_size) {
79 			struct dirent **newv;
80 			if (vector_size == 0) {
81 				vector_size = 10;
82 			} else {
83 				vector_size *= 2;
84 			}
85 
86 			newv = (struct dirent **) realloc (vector, vector_size * sizeof (struct dirent *));
87 			if (!newv) {
88 				return -1;
89 			}
90 			vector = newv;
91 		}
92 
93 		dsize = sizeof (struct dirent) + ((strlen(dp->d_name) + 1) * sizeof(char));
94 		newdp = (struct dirent *) malloc(dsize);
95 
96 		if (newdp == NULL) {
97 			goto fail;
98 		}
99 
100 		vector[nfiles++] = (struct dirent *) memcpy(newdp, dp, dsize);
101 	}
102 
103 	closedir(dirp);
104 
105 	*namelist = vector;
106 
107 	if (compare) {
108 		qsort (*namelist, nfiles, sizeof(struct dirent *), (int (*) (const void *, const void *)) compare);
109 	}
110 
111 	return nfiles;
112 
113 fail:
114 	while (nfiles-- > 0) {
115 		free(vector[nfiles]);
116 	}
117 	free(vector);
118 	return -1;
119 }
120 #endif
121