Adding a preserve thunk to call-with-temp-file/dir.

This commit is contained in:
Alex Shinn 2015-04-24 22:52:13 +09:00
parent 08cf38851e
commit a8848793e4
5 changed files with 50 additions and 21 deletions

View file

@ -209,7 +209,7 @@
(define (http-cgi-bin-servlet request local-path next restart) (define (http-cgi-bin-servlet request local-path next restart)
(call-with-temp-file "cgi.out" (call-with-temp-file "cgi.out"
(lambda (temp-file out) (lambda (temp-file out preserve)
(let ((pid (fork))) (let ((pid (fork)))
(cond (cond
((zero? pid) ((zero? pid)

View file

@ -5,5 +5,5 @@
(chibi temp-file) (chibi temp-file)
(srfi 33) (srfi 69)) (srfi 33) (srfi 69))
(export line-handler command-handler parse-command (export line-handler command-handler parse-command
get-host file-mime-type call-with-temp-file) get-host file-mime-type)
(include "server-util.scm")) (include "server-util.scm"))

View file

@ -1365,7 +1365,7 @@
(define (install-sexp-file cfg obj dest) (define (install-sexp-file cfg obj dest)
(if (install-with-sudo? cfg dest) (if (install-with-sudo? cfg dest)
(call-with-temp-file "sexp" (call-with-temp-file "sexp"
(lambda (tmp-path out) (lambda (tmp-path out preserve)
(write-simple-pretty obj out) (write-simple-pretty obj out)
(close-output-port out) (close-output-port out)
(system "sudo" "cp" tmp-path dest))) (system "sudo" "cp" tmp-path dest)))
@ -1715,7 +1715,7 @@
(else (else
(call-with-temp-dir (call-with-temp-dir
"pkg" "pkg"
(lambda (dir) (lambda (dir preserve)
(tar-extract snowball (lambda (f) (make-path dir (path-strip-top f)))) (tar-extract snowball (lambda (f) (make-path dir (path-strip-top f))))
(let ((libs (filter-map (lambda (lib) (build-library impl cfg lib dir)) (let ((libs (filter-map (lambda (lib) (build-library impl cfg lib dir))
(package-libraries pkg)))) (package-libraries pkg))))
@ -1745,7 +1745,8 @@
`(,@(remove (lambda (x) `(,@(remove (lambda (x)
(and (pair? x) (eq? 'installed-files (car x)))) (and (pair? x) (eq? 'installed-files (car x))))
pkg) pkg)
(installed-files ,@installed-files))))))))))) (installed-files ,@installed-files))))
(preserve))))))))
(define (install-package-from-file repo impl cfg file) (define (install-package-from-file repo impl cfg file)
(let ((pkg (package-file-meta file)) (let ((pkg (package-file-meta file))

View file

@ -1,8 +1,21 @@
(define (call-with-temp-file template proc) ;;> Runs a procedure on a temporary file. \var{proc} should be a
(let ((base (string-append ;;> procedure of three values: \scheme{(path out preserve)}, where
;;> \scheme{path} is the path to the temporary file, \scheme{out} is
;;> an output port opened on the file, and \scheme{preserve} is a
;;> thunk to disable deleting the file. The file name will be in a
;;> temp directory, based on \var{template} and having the same
;;> extension if present, with permissions from the optional
;;> \var{mode} which defaults to \scheme{#o700}. Returns the result
;;> of \var{proc}, after first deleting the file if the
;;> \scheme{preserve} thunk was not called.
(define (call-with-temp-file template proc . o)
(let* ((mode (if (pair? o) (car o) #o700))
(pid (current-process-id))
(base (string-append
"/tmp/" (path-strip-extension template) "/tmp/" (path-strip-extension template)
"-" (number->string (current-process-id)) "-" "-" (number->string pid) "-"
(number->string (exact (round (current-second)))) "-")) (number->string (exact (round (current-second)))) "-"))
(ext (or (path-extension template) "tmp"))) (ext (or (path-extension template) "tmp")))
(let lp ((i 0)) (let lp ((i 0))
@ -14,19 +27,33 @@
(lp (+ i 1))) (lp (+ i 1)))
(else (else
(let ((fd (open path (let ((fd (open path
(bitwise-ior open/write open/create open/exclusive)))) (bitwise-ior open/write open/create open/exclusive)
mode)))
(if (not fd) (if (not fd)
(if (file-exists? path) ;; created between test and open (if (file-exists? path) ;; created between test and open
(lp (+ i 1)) (lp (+ i 1))
(error "Couldn't generate temp file in /tmp " path)) (error "Couldn't generate temp file in /tmp " path))
(let* ((out (open-output-file-descriptor fd #o700)) (let* ((out (open-output-file-descriptor fd))
(res (proc path out))) (preserve? #f)
(res (proc path out (lambda () (set! preserve? #t)))))
(close-output-port out) (close-output-port out)
(delete-file path) (if (and (not preserve?) (equal? pid (current-process-id)))
(delete-file path))
res))))))))) res)))))))))
(define (call-with-temp-dir template proc) ;;> Runs a procedure on a temporary directory. \var{proc} should be a
(let* ((pid (current-process-id)) ;;> procedure of two values: \scheme{(path preserve)}, where
;;> \scheme{path} is the path to the temporary directory and
;;> \scheme{preserve} is a thunk to disable deleting the dir. The
;;> directory name will be in a temp directory, based on
;;> \var{template}, with permissions from the optional \var{mode}
;;> which defaults to \scheme{#o700}. Returns the result of
;;> \var{proc}, after first deleting the file hierarchy rooted at
;;> \scheme{path} if the \scheme{preserve} thunk was not called.
(define (call-with-temp-dir template proc . o)
(let* ((mode (if (pair? o) (car o) #o700))
(pid (current-process-id))
(base (string-append (base (string-append
"/tmp/" template "-" (number->string pid) "-" "/tmp/" template "-" (number->string pid) "-"
(number->string (exact (round (current-second)))) "-"))) (number->string (exact (round (current-second)))) "-")))
@ -37,10 +64,11 @@
(error "Repeatedly failed to generate temp dir in /tmp " path)) (error "Repeatedly failed to generate temp dir in /tmp " path))
((file-exists? path) ((file-exists? path)
(lp (+ i 1))) (lp (+ i 1)))
((create-directory path #o700) ((create-directory path mode)
(let ((res (proc path))) (let* ((preserve? #f)
(res (proc path (lambda () (set! preserve? #t)))))
;; sanity check for host threading issues and broken forks ;; sanity check for host threading issues and broken forks
(if (equal? pid (current-process-id)) (if (and (not preserve?) (equal? pid (current-process-id)))
(delete-file-hierarchy path)) (delete-file-hierarchy path))
res)) res))
(else (else

View file

@ -50,7 +50,7 @@
;; Use a temp file to avoid dead-lock issues with pipes. ;; Use a temp file to avoid dead-lock issues with pipes.
(define (process-run-bytevector cmd bvec) (define (process-run-bytevector cmd bvec)
(call-with-temp-file "bvec" (call-with-temp-file "bvec"
(lambda (path out) (lambda (path out preserve)
(write-bytevector bvec out) (write-bytevector bvec out)
(close-output-port out) (close-output-port out)
(process->bytevector (append cmd (list path)))))) (process->bytevector (append cmd (list path))))))