@@ -276,7 +276,7 @@ static zend_result ps_files_write(ps_files *data, zend_string *key, zend_string
276276 return SUCCESS ;
277277}
278278
279- static int ps_files_cleanup_dir (const zend_string * dirname , zend_long maxlifetime )
279+ static int ps_files_cleanup_dir (const zend_string * dirname , zend_long maxlifetime , size_t remaining_depth )
280280{
281281 DIR * dir ;
282282 struct dirent * entry ;
@@ -291,44 +291,56 @@ static int ps_files_cleanup_dir(const zend_string *dirname, zend_long maxlifetim
291291 return -1 ;
292292 }
293293
294- time (& now );
295-
296294 if (ZSTR_LEN (dirname ) >= MAXPATHLEN ) {
297295 php_error_docref (NULL , E_NOTICE , "ps_files_cleanup_dir: dirname(%s) is too long" , ZSTR_VAL (dirname ));
298296 closedir (dir );
299297 return -1 ;
300298 }
301299
302- /* Prepare buffer (dirname never changes) */
303300 memcpy (buf , ZSTR_VAL (dirname ), ZSTR_LEN (dirname ));
304301 buf [ZSTR_LEN (dirname )] = PHP_DIR_SEPARATOR ;
305302
306- while ((entry = readdir (dir ))) {
307- /* does the file start with our prefix? */
308- if (!strncmp (entry -> d_name , FILE_PREFIX , sizeof (FILE_PREFIX ) - 1 )) {
303+ if (remaining_depth == 0 ) {
304+ time (& now );
305+ while ((entry = readdir (dir ))) {
306+ if (!strncmp (entry -> d_name , FILE_PREFIX , sizeof (FILE_PREFIX ) - 1 )) {
307+ size_t entry_len = strlen (entry -> d_name );
308+ if (entry_len + ZSTR_LEN (dirname ) + 2 < MAXPATHLEN ) {
309+ memcpy (buf + ZSTR_LEN (dirname ) + 1 , entry -> d_name , entry_len );
310+ buf [ZSTR_LEN (dirname ) + entry_len + 1 ] = '\0' ;
311+ if (VCWD_STAT (buf , & sbuf ) == 0 &&
312+ (now - sbuf .st_mtime ) > maxlifetime ) {
313+ VCWD_UNLINK (buf );
314+ nrdels ++ ;
315+ }
316+ }
317+ }
318+ }
319+ } else {
320+ while ((entry = readdir (dir ))) {
321+ if (entry -> d_name [0 ] == '.' &&
322+ (entry -> d_name [1 ] == '\0' ||
323+ (entry -> d_name [1 ] == '.' && entry -> d_name [2 ] == '\0' ))) {
324+ continue ;
325+ }
309326 size_t entry_len = strlen (entry -> d_name );
310-
311- /* does it fit into our buffer? */
312- if (entry_len + ZSTR_LEN (dirname ) + 2 < MAXPATHLEN ) {
313- /* create the full path.. */
327+ if (ZSTR_LEN (dirname ) + 1 + entry_len < MAXPATHLEN ) {
314328 memcpy (buf + ZSTR_LEN (dirname ) + 1 , entry -> d_name , entry_len );
315-
316- /* NUL terminate it and */
317- buf [ZSTR_LEN (dirname ) + entry_len + 1 ] = '\0' ;
318-
319- /* check whether its last access was more than maxlifetime ago */
320- if (VCWD_STAT (buf , & sbuf ) == 0 &&
321- (now - sbuf .st_mtime ) > maxlifetime ) {
322- VCWD_UNLINK (buf );
323- nrdels ++ ;
329+ buf [ZSTR_LEN (dirname ) + 1 + entry_len ] = '\0' ;
330+ if (VCWD_STAT (buf , & sbuf ) == 0 && S_ISDIR (sbuf .st_mode )) {
331+ zend_string * subdir = zend_string_init (buf , ZSTR_LEN (dirname ) + 1 + entry_len , 0 );
332+ int n = ps_files_cleanup_dir (subdir , maxlifetime , remaining_depth - 1 );
333+ zend_string_release (subdir );
334+ if (n >= 0 ) {
335+ nrdels += n ;
336+ }
324337 }
325338 }
326339 }
327340 }
328341
329342 closedir (dir );
330-
331- return (nrdels );
343+ return nrdels ;
332344}
333345
334346static zend_result ps_files_key_exists (ps_files * data , const zend_string * key )
@@ -624,15 +636,7 @@ PS_GC_FUNC(files)
624636{
625637 PS_FILES_DATA ;
626638
627- /* We don't perform any cleanup, if dirdepth is larger than 0.
628- we return SUCCESS, since all cleanup should be handled by
629- an external entity (i.e. find -ctime x | xargs rm) */
630-
631- if (data -> dirdepth == 0 ) {
632- * nrdels = ps_files_cleanup_dir (data -> basedir , maxlifetime );
633- } else {
634- * nrdels = -1 ; // Cannot process multiple depth save dir
635- }
639+ * nrdels = ps_files_cleanup_dir (data -> basedir , maxlifetime , data -> dirdepth );
636640
637641 return * nrdels ;
638642}
0 commit comments