1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-29 16:30:19 +02:00

scandir: Avoid 'stat' calls on each entry.

* module/ice-9/ftw.scm (scandir): Rewrite in terms of 'readdir'.
This commit is contained in:
Ludovic Courtès 2016-10-28 22:14:05 +02:00
parent 89ce9fb31b
commit 272473fee4

View file

@ -1,6 +1,6 @@
;;;; ftw.scm --- file system tree walk ;;;; ftw.scm --- file system tree walk
;;;; Copyright (C) 2002, 2003, 2006, 2011, 2012, 2014 Free Software Foundation, Inc. ;;;; Copyright (C) 2002, 2003, 2006, 2011, 2012, 2014, 2016 Free Software Foundation, Inc.
;;;; ;;;;
;;;; This library is free software; you can redistribute it and/or ;;;; This library is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU Lesser General Public ;;;; modify it under the terms of the GNU Lesser General Public
@ -535,36 +535,30 @@ when FILE-NAME is not readable."
"Return the list of the names of files contained in directory NAME "Return the list of the names of files contained in directory NAME
that match predicate SELECT? (by default, all files.) The returned list that match predicate SELECT? (by default, all files.) The returned list
of file names is sorted according to ENTRY<?, which defaults to of file names is sorted according to ENTRY<?, which defaults to
`string-locale<?'. Return #f when NAME is unreadable or is not a directory." `string-locale<?'. Return #f when NAME is unreadable or is not a
(define (enter? dir stat result) directory."
(and stat (string=? dir name)))
(define (visit basename result) ;; This procedure is implemented in terms of 'readdir' instead of
(if (select? basename) ;; 'file-system-fold' to avoid the extra 'stat' call that the latter
(cons basename result) ;; makes for each entry.
result))
(define (leaf name stat result) (define (opendir* directory)
(and result (catch 'system-error
(visit (basename name) result))) (lambda ()
(opendir directory))
(const #f)))
(define (down name stat result) (and=> (opendir* name)
(visit "." '())) (lambda (stream)
(let loop ((entry (readdir stream))
(define (up name stat result) (files '()))
(visit ".." result)) (if (eof-object? entry)
(begin
(define (skip name stat result) (closedir stream)
;; All the sub-directories are skipped. (sort files entry<?))
(visit (basename name) result)) (loop (readdir stream)
(if (select? entry)
(define (error name* stat errno result) (cons entry files)
(if (string=? name name*) ; top-level NAME is unreadable files)))))))
result
(visit (basename name*) result)))
(and=> (file-system-fold enter? leaf down up skip error #f name lstat)
(lambda (files)
(sort files entry<?))))
;;; ftw.scm ends here ;;; ftw.scm ends here