1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-03 13:20:26 +02:00

rewrite ensure-writable-dir to not be racy

* module/system/base/compile.scm (ensure-writable-dir): Rewrite to not
  be racy.
This commit is contained in:
Andy Wingo 2011-03-29 11:40:05 +02:00
parent 9dadfa47b0
commit 56dbc8a899

View file

@ -68,16 +68,27 @@
x x
(lookup-language x))) (lookup-language x)))
;; Throws an exception if `dir' is not writable. The double-stat is OK, ;; Throws an exception if `dir' is not writable. The mkdir occurs
;; as this is only used during compilation. ;; before the check, so that we avoid races (possibly due to parallel
;; compilation).
;;
(define (ensure-writable-dir dir) (define (ensure-writable-dir dir)
(if (file-exists? dir) (catch 'system-error
(if (access? dir W_OK) (lambda ()
#t (mkdir dir))
(error "directory not writable" dir)) (lambda (k subr fmt args rest)
(begin (let ((errno (and (pair? rest) (car rest))))
(cond
((eqv? errno EEXIST)
(let ((st (stat dir)))
(if (or (not (eq? (stat:type st) 'directory))
(not (access? dir W_OK)))
(error "directory not writable" dir))))
((eqv? errno ENOENT)
(ensure-writable-dir (dirname dir)) (ensure-writable-dir (dirname dir))
(mkdir dir)))) (ensure-writable-dir dir))
(else
(throw k subr fmt args rest)))))))
;;; This function is among the trickiest I've ever written. I tried many ;;; This function is among the trickiest I've ever written. I tried many
;;; variants. In the end, simple is best, of course. ;;; variants. In the end, simple is best, of course.