2017-08-23 15:18:33 +05:30
|
|
|
(library
|
|
|
|
(temp-file)
|
|
|
|
|
|
|
|
(export
|
2017-08-24 18:33:07 +05:30
|
|
|
working-directory
|
|
|
|
with-dir-thunk
|
|
|
|
with-dir
|
|
|
|
with-temp-file-thunk
|
|
|
|
with-temp-file-containing-thunk
|
2017-08-25 15:56:45 +05:30
|
|
|
with-temp-file-sized-thunk
|
2017-08-24 18:33:07 +05:30
|
|
|
with-temp-file
|
|
|
|
with-temp-file-containing
|
2017-08-25 15:56:45 +05:30
|
|
|
with-temp-file-sized
|
2017-08-24 18:33:07 +05:30
|
|
|
disable-unlink)
|
2017-08-23 15:18:33 +05:30
|
|
|
|
2017-08-24 18:33:07 +05:30
|
|
|
(import (chezscheme)
|
2018-04-18 19:42:28 +05:30
|
|
|
(disk-units)
|
2017-08-29 19:16:59 +05:30
|
|
|
(fmt fmt)
|
|
|
|
(srfi s8 receive)
|
|
|
|
(only (srfi s1 lists) span))
|
2017-08-23 15:18:33 +05:30
|
|
|
|
2017-08-24 18:33:07 +05:30
|
|
|
;; FIXME: global var! Not thread safe.
|
2018-12-12 18:43:11 +05:30
|
|
|
(define working-dir ".")
|
2017-08-24 18:33:07 +05:30
|
|
|
|
|
|
|
(define (working-directory) working-dir)
|
|
|
|
|
|
|
|
(define (mkdir-p)
|
|
|
|
(system (string-append "mkdir -p " working-dir)))
|
|
|
|
|
|
|
|
(define (with-dir-thunk path thunk)
|
|
|
|
(fluid-let ((working-dir (string-append working-dir "/" path)))
|
|
|
|
(mkdir-p)
|
|
|
|
(thunk)))
|
|
|
|
|
|
|
|
(define-syntax with-dir
|
|
|
|
(syntax-rules ()
|
|
|
|
((_ path b1 b2 ...)
|
|
|
|
(with-dir-thunk path (lambda () b1 b2 ...)))))
|
|
|
|
|
|
|
|
(define (with-temp-dir-thunk path thunk)
|
|
|
|
(with-dir-thunk path
|
|
|
|
(lambda ()
|
|
|
|
(auto-unlink-file path
|
|
|
|
(thunk)))))
|
|
|
|
|
2017-08-29 19:16:59 +05:30
|
|
|
(define temp-filename
|
|
|
|
(lambda (filename)
|
|
|
|
(let ((counter 0))
|
|
|
|
(let loop ()
|
|
|
|
(let ((path (fmt #f (cat (dsp working-dir)
|
|
|
|
(dsp "/")
|
|
|
|
(pad-char #\0 (pad/left 4 (num counter)))
|
|
|
|
(dsp "-")
|
|
|
|
(dsp filename)))))
|
|
|
|
(set! counter (+ counter 1))
|
|
|
|
(if (file-exists? path)
|
|
|
|
(loop)
|
|
|
|
path))))))
|
2017-08-24 18:33:07 +05:30
|
|
|
|
|
|
|
;; fn takes the path
|
2017-08-29 19:16:59 +05:30
|
|
|
(define (with-temp-file-thunk filename fn)
|
|
|
|
(let ((path (temp-filename filename)))
|
2017-08-24 18:33:07 +05:30
|
|
|
(auto-unlink-file path
|
|
|
|
(lambda () (fn path)))))
|
|
|
|
|
|
|
|
(define-syntax with-temp-file
|
|
|
|
(syntax-rules ()
|
2017-08-29 19:16:59 +05:30
|
|
|
((_ ((v f)) b1 b2 ...)
|
|
|
|
(with-temp-file-thunk f
|
2017-08-24 18:33:07 +05:30
|
|
|
(lambda (v)
|
|
|
|
b1 b2 ...)))
|
|
|
|
|
2017-08-29 19:16:59 +05:30
|
|
|
((_ ((v1 f1) v2 ...) b1 b2 ...)
|
|
|
|
(with-temp-file-thunk f1
|
2017-08-24 18:33:07 +05:30
|
|
|
(lambda (v1)
|
|
|
|
(with-temp-file (v2 ...) b1 b2 ...))))))
|
|
|
|
|
|
|
|
;; Creates a temporary file with the specified contents.
|
2017-08-29 19:16:59 +05:30
|
|
|
(define (with-temp-file-containing-thunk filename contents fn)
|
|
|
|
(with-temp-file-thunk filename
|
2017-08-24 18:33:07 +05:30
|
|
|
(lambda (path)
|
|
|
|
(with-output-to-file path (lambda ()
|
|
|
|
(put-string (current-output-port) contents)))
|
|
|
|
(fn path))))
|
|
|
|
|
|
|
|
(define-syntax with-temp-file-containing
|
|
|
|
(syntax-rules ()
|
2017-08-29 19:16:59 +05:30
|
|
|
((_ ((v f txt)) b1 b2 ...)
|
|
|
|
(with-temp-file-containing-thunk f
|
2017-08-24 18:33:07 +05:30
|
|
|
txt (lambda (v) b1 b2 ...)))
|
|
|
|
|
2017-08-29 19:16:59 +05:30
|
|
|
((_ ((v f txt) rest ...) b1 b2 ...)
|
|
|
|
(with-temp-file-containing-thunk f
|
|
|
|
txt (lambda (v)
|
2017-08-24 18:33:07 +05:30
|
|
|
(with-temp-file-containing (rest ...)
|
|
|
|
b1 b2 ...))))))
|
|
|
|
|
2018-04-18 19:42:28 +05:30
|
|
|
(define (safe-to-bytes maybe-size)
|
|
|
|
(if (disk-size? maybe-size)
|
|
|
|
(to-bytes maybe-size)
|
|
|
|
maybe-size))
|
|
|
|
|
2018-12-12 18:44:09 +05:30
|
|
|
(define (suitable-block-size size)
|
|
|
|
(let loop ((bs (* 1024 1024 4)))
|
|
|
|
(if (> (mod size bs) 0)
|
|
|
|
(loop (/ bs 2))
|
|
|
|
bs)))
|
|
|
|
|
|
|
|
;; It's much faster if we write large blocks
|
|
|
|
(define (dd-zero-file path size)
|
|
|
|
(let* ((bytes (safe-to-bytes size))
|
|
|
|
(bs (suitable-block-size bytes))
|
|
|
|
(count (floor (/ bytes bs))))
|
|
|
|
(system (fmt #f "dd if=/dev/zero of=" path
|
|
|
|
" bs=" (wrt bs)
|
|
|
|
" count=" (wrt count)
|
|
|
|
" 2> /dev/null > /dev/null"))))
|
|
|
|
|
2017-08-29 19:16:59 +05:30
|
|
|
(define (with-temp-file-sized-thunk filename size fn)
|
|
|
|
(with-temp-file-thunk filename
|
2017-08-25 15:56:45 +05:30
|
|
|
(lambda (path)
|
2018-12-12 18:44:09 +05:30
|
|
|
(dd-zero-file path size)
|
2017-09-28 19:06:01 +05:30
|
|
|
(fn path))))
|
2017-08-25 15:56:45 +05:30
|
|
|
|
|
|
|
(define-syntax with-temp-file-sized
|
|
|
|
(syntax-rules ()
|
2017-08-29 19:16:59 +05:30
|
|
|
((_ ((v f size)) b1 b2 ...)
|
|
|
|
(with-temp-file-sized-thunk f
|
2017-08-25 15:56:45 +05:30
|
|
|
size
|
|
|
|
(lambda (v)
|
|
|
|
b1 b2 ...)))
|
|
|
|
|
2017-08-29 19:16:59 +05:30
|
|
|
((_ ((v f size) rest ...) b1 b2 ...)
|
|
|
|
(with-temp-file-sized-thunk f
|
2017-08-25 15:56:45 +05:30
|
|
|
size (lambda (v)
|
|
|
|
(with-temp-file-sized (rest ...) b1 b2 ...))))))
|
|
|
|
|
2017-08-24 18:33:07 +05:30
|
|
|
;;-------------------------
|
|
|
|
|
|
|
|
(define should-unlink #t)
|
|
|
|
|
|
|
|
(define (disable-unlink-thunk fn)
|
|
|
|
(fluid-let ((should-unlink #f))
|
|
|
|
(fn)))
|
|
|
|
|
|
|
|
(define-syntax disable-unlink
|
|
|
|
(syntax-rules ()
|
|
|
|
((_ b1 b2 ...)
|
|
|
|
(disable-unlink-thunk
|
|
|
|
(lambda () b1 b2 ...)))))
|
|
|
|
|
|
|
|
;; FIXME: use 'run' so we get logging
|
|
|
|
(define (unlink-file path)
|
|
|
|
(when should-unlink
|
|
|
|
(system (string-append "rm -f " path))))
|
|
|
|
|
|
|
|
(define (unlink-dir path)
|
|
|
|
(when should-unlink
|
|
|
|
(system (string-append "rmdir -f " path))))
|
|
|
|
|
|
|
|
(define (auto-unlink-file path thunk)
|
|
|
|
(dynamic-wind (lambda () #t)
|
|
|
|
thunk
|
|
|
|
(lambda () (unlink-file path))))
|
|
|
|
|
|
|
|
(define (auto-unlink-dir path thunk)
|
|
|
|
(dynamic-wind (lambda () #t)
|
|
|
|
thunk
|
|
|
|
(lambda () (unlink-dir path))))
|
|
|
|
)
|