@@ -59,39 +59,6 @@ static zend_function *dir_class_get_constructor(zend_object *object)
59
59
return NULL ;
60
60
}
61
61
62
- #define FETCH_DIRP () \
63
- myself = getThis(); \
64
- if (!myself) { \
65
- ZEND_PARSE_PARAMETERS_START(0, 1) \
66
- Z_PARAM_OPTIONAL \
67
- Z_PARAM_RESOURCE_OR_NULL(id) \
68
- ZEND_PARSE_PARAMETERS_END(); \
69
- if (id) { \
70
- if ((dirp = (php_stream *)zend_fetch_resource(Z_RES_P(id), "Directory", php_file_le_stream())) == NULL) { \
71
- RETURN_THROWS(); \
72
- } \
73
- } else { \
74
- if (!DIRG(default_dir)) { \
75
- zend_type_error("No resource supplied"); \
76
- RETURN_THROWS(); \
77
- } \
78
- if ((dirp = (php_stream *)zend_fetch_resource(DIRG(default_dir), "Directory", php_file_le_stream())) == NULL) { \
79
- RETURN_THROWS(); \
80
- } \
81
- } \
82
- } else { \
83
- ZEND_PARSE_PARAMETERS_NONE(); \
84
- zval *handle_zv = Z_DIRECTORY_HANDLE_P(myself); \
85
- if (Z_TYPE_P(handle_zv) != IS_RESOURCE) { \
86
- zend_throw_error(NULL, "Unable to find my handle property"); \
87
- RETURN_THROWS(); \
88
- } \
89
- if ((dirp = (php_stream *)zend_fetch_resource_ex(handle_zv, "Directory", php_file_le_stream())) == NULL) { \
90
- RETURN_THROWS(); \
91
- } \
92
- }
93
-
94
-
95
62
static void php_set_default_dir (zend_resource * res )
96
63
{
97
64
if (DIRG (default_dir )) {
@@ -189,21 +156,71 @@ PHP_FUNCTION(dir)
189
156
}
190
157
/* }}} */
191
158
159
+
160
+ static php_stream * php_dir_get_directory_stream_from_user_arg (zval * arg )
161
+ {
162
+ zend_resource * res ;
163
+ if (arg == NULL ) {
164
+ if (UNEXPECTED (DIRG (default_dir ) == NULL )) {
165
+ zend_type_error ("No resource supplied" );
166
+ return NULL ;
167
+ }
168
+ res = DIRG (default_dir );
169
+ } else {
170
+ ZEND_ASSERT (Z_TYPE_P (arg ) == IS_RESOURCE );
171
+ res = Z_RES_P (arg );
172
+ }
173
+
174
+ if (UNEXPECTED (res -> type != php_file_le_stream ())) {
175
+ zend_argument_type_error (1 , "must be a valid Directory resource" );
176
+ return NULL ;
177
+ }
178
+ php_stream * dir_stream = (php_stream * ) res -> ptr ;
179
+ if (UNEXPECTED ((dir_stream -> flags & PHP_STREAM_FLAG_IS_DIR )) == 0 ) {
180
+ zend_argument_type_error (1 , "must be a valid Directory resource" );
181
+ return NULL ;
182
+ }
183
+ return dir_stream ;
184
+ }
185
+
186
+ static php_stream * php_dir_get_directory_stream_from_this (zval * this_z )
187
+ {
188
+ zval * handle_zv = Z_DIRECTORY_HANDLE_P (this_z );
189
+ if (UNEXPECTED (Z_TYPE_P (handle_zv ) != IS_RESOURCE )) {
190
+ zend_throw_error (NULL , "internal directory stream has been altered" );
191
+ return NULL ;
192
+ }
193
+ zend_resource * res = Z_RES_P (handle_zv );
194
+ /* Assume the close() method was called
195
+ * (instead of the hacky case where a different resource would have been set via the ArrayObject "hack") */
196
+ if (UNEXPECTED (res -> type != php_file_le_stream ())) {
197
+ /* TypeError is used for BC, TODO: Use base Error in PHP 9 */
198
+ zend_type_error ("Directory::%s(): cannot use Directory resource after it has been closed" , get_active_function_name ());
199
+ return NULL ;
200
+ }
201
+ php_stream * dir_stream = (php_stream * ) res -> ptr ;
202
+ if (UNEXPECTED ((dir_stream -> flags & PHP_STREAM_FLAG_IS_DIR )) == 0 ) {
203
+ zend_throw_error (NULL , "internal directory stream has been altered" );
204
+ return NULL ;
205
+ }
206
+ return dir_stream ;
207
+ }
208
+
192
209
/* {{{ Close directory connection identified by the dir_handle */
193
210
PHP_FUNCTION (closedir )
194
211
{
195
- zval * id = NULL , * myself ;
196
- php_stream * dirp ;
197
- zend_resource * res ;
212
+ zval * id = NULL ;
198
213
199
- FETCH_DIRP ();
214
+ ZEND_PARSE_PARAMETERS_START (0 , 1 )
215
+ Z_PARAM_OPTIONAL
216
+ Z_PARAM_RESOURCE_OR_NULL (id )
217
+ ZEND_PARSE_PARAMETERS_END ();
200
218
201
- if (!( dirp -> flags & PHP_STREAM_FLAG_IS_DIR )) {
202
- zend_argument_type_error ( 1 , "must be a valid Directory resource" );
219
+ php_stream * dirp = php_dir_get_directory_stream_from_user_arg ( id );
220
+ if ( UNEXPECTED ( dirp == NULL )) {
203
221
RETURN_THROWS ();
204
222
}
205
-
206
- res = dirp -> res ;
223
+ zend_resource * res = dirp -> res ;
207
224
zend_list_close (dirp -> res );
208
225
209
226
if (res == DIRG (default_dir )) {
@@ -212,6 +229,93 @@ PHP_FUNCTION(closedir)
212
229
}
213
230
/* }}} */
214
231
232
+ PHP_METHOD (Directory , close )
233
+ {
234
+ ZEND_PARSE_PARAMETERS_NONE ();
235
+
236
+ php_stream * dirp = php_dir_get_directory_stream_from_this (ZEND_THIS );
237
+ if (UNEXPECTED (dirp == NULL )) {
238
+ RETURN_THROWS ();
239
+ }
240
+
241
+ zend_resource * res = dirp -> res ;
242
+ zend_list_close (res );
243
+
244
+ if (res == DIRG (default_dir )) {
245
+ php_set_default_dir (NULL );
246
+ }
247
+ }
248
+
249
+ /* {{{ Rewind dir_handle back to the start */
250
+ PHP_FUNCTION (rewinddir )
251
+ {
252
+ zval * id = NULL ;
253
+
254
+ ZEND_PARSE_PARAMETERS_START (0 , 1 )
255
+ Z_PARAM_OPTIONAL
256
+ Z_PARAM_RESOURCE_OR_NULL (id )
257
+ ZEND_PARSE_PARAMETERS_END ();
258
+
259
+ php_stream * dirp = php_dir_get_directory_stream_from_user_arg (id );
260
+ if (UNEXPECTED (dirp == NULL )) {
261
+ RETURN_THROWS ();
262
+ }
263
+
264
+ php_stream_rewinddir (dirp );
265
+ }
266
+ /* }}} */
267
+
268
+ PHP_METHOD (Directory , rewind )
269
+ {
270
+ ZEND_PARSE_PARAMETERS_NONE ();
271
+
272
+ php_stream * dirp = php_dir_get_directory_stream_from_this (ZEND_THIS );
273
+ if (UNEXPECTED (dirp == NULL )) {
274
+ RETURN_THROWS ();
275
+ }
276
+
277
+ php_stream_rewinddir (dirp );
278
+ }
279
+
280
+ /* {{{ Read directory entry from dir_handle */
281
+ PHP_FUNCTION (readdir )
282
+ {
283
+ zval * id = NULL ;
284
+
285
+ ZEND_PARSE_PARAMETERS_START (0 , 1 )
286
+ Z_PARAM_OPTIONAL
287
+ Z_PARAM_RESOURCE_OR_NULL (id )
288
+ ZEND_PARSE_PARAMETERS_END ();
289
+
290
+ php_stream * dirp = php_dir_get_directory_stream_from_user_arg (id );
291
+ if (UNEXPECTED (dirp == NULL )) {
292
+ RETURN_THROWS ();
293
+ }
294
+
295
+ php_stream_dirent entry ;
296
+ if (php_stream_readdir (dirp , & entry )) {
297
+ RETURN_STRINGL (entry .d_name , strlen (entry .d_name ));
298
+ }
299
+ RETURN_FALSE ;
300
+ }
301
+ /* }}} */
302
+
303
+ PHP_METHOD (Directory , read )
304
+ {
305
+ ZEND_PARSE_PARAMETERS_NONE ();
306
+
307
+ php_stream * dirp = php_dir_get_directory_stream_from_this (ZEND_THIS );
308
+ if (UNEXPECTED (dirp == NULL )) {
309
+ RETURN_THROWS ();
310
+ }
311
+
312
+ php_stream_dirent entry ;
313
+ if (php_stream_readdir (dirp , & entry )) {
314
+ RETURN_STRINGL (entry .d_name , strlen (entry .d_name ));
315
+ }
316
+ RETURN_FALSE ;
317
+ }
318
+
215
319
#if defined(HAVE_CHROOT ) && !defined(ZTS ) && defined(ENABLE_CHROOT_FUNC )
216
320
/* {{{ Change root directory */
217
321
PHP_FUNCTION (chroot )
@@ -300,44 +404,6 @@ PHP_FUNCTION(getcwd)
300
404
}
301
405
/* }}} */
302
406
303
- /* {{{ Rewind dir_handle back to the start */
304
- PHP_FUNCTION (rewinddir )
305
- {
306
- zval * id = NULL , * myself ;
307
- php_stream * dirp ;
308
-
309
- FETCH_DIRP ();
310
-
311
- if (!(dirp -> flags & PHP_STREAM_FLAG_IS_DIR )) {
312
- zend_argument_type_error (1 , "must be a valid Directory resource" );
313
- RETURN_THROWS ();
314
- }
315
-
316
- php_stream_rewinddir (dirp );
317
- }
318
- /* }}} */
319
-
320
- /* {{{ Read directory entry from dir_handle */
321
- PHP_FUNCTION (readdir )
322
- {
323
- zval * id = NULL , * myself ;
324
- php_stream * dirp ;
325
- php_stream_dirent entry ;
326
-
327
- FETCH_DIRP ();
328
-
329
- if (!(dirp -> flags & PHP_STREAM_FLAG_IS_DIR )) {
330
- zend_argument_type_error (1 , "must be a valid Directory resource" );
331
- RETURN_THROWS ();
332
- }
333
-
334
- if (php_stream_readdir (dirp , & entry )) {
335
- RETURN_STRINGL (entry .d_name , strlen (entry .d_name ));
336
- }
337
- RETURN_FALSE ;
338
- }
339
- /* }}} */
340
-
341
407
#ifdef HAVE_GLOB
342
408
/* {{{ Find pathnames matching a pattern */
343
409
PHP_FUNCTION (glob )
0 commit comments