These changes require microcode version 11.145 or later.
authorChris Hanson <org/chris-hanson/cph>
Tue, 9 Nov 1993 04:31:43 +0000 (04:31 +0000)
committerChris Hanson <org/chris-hanson/cph>
Tue, 9 Nov 1993 04:31:43 +0000 (04:31 +0000)
Reimplement handling of temporary files to update list in fixed
objects vector; this list tells the microcode that the files should be
deleted when Scheme is killed.

Additionally, change the handling of ".bci" file expansion to use the
new temporary file mechanism.  The expander now accepts a third value
for *SAVE-UNCOMPRESSED-FILES?* which says to expand the file into a
temporary file that is deleted (by the GC) after it has not been used
in a while, or when Scheme is killed.  This new option is now the
default, and the timeout for these temporary files defaults to five
minutes.

v7/src/runtime/dosprm.scm
v7/src/runtime/infutl.scm
v7/src/runtime/sfile.scm
v7/src/runtime/unxprm.scm
v7/src/runtime/version.scm
v8/src/runtime/infutl.scm

index 6b4d9e470f63a8c04460267070ff1d90cbac7ee6..6b10f6c63520b556dc5942fda47ed16a302bc284 100644 (file)
@@ -1,6 +1,6 @@
 #| -*-Scheme-*-
 
-$Id: dosprm.scm,v 1.20 1993/09/07 21:56:27 gjr Exp $
+$Id: dosprm.scm,v 1.21 1993/11/09 04:31:37 cph Exp $
 
 Copyright (c) 1992-1993 Massachusetts Institute of Technology
 
@@ -74,33 +74,37 @@ MIT in each case. |#
                (directory-namestring pathname)
                2))))))
 
-(define (call-with-temporary-filename receiver)
-  (let find-eligible-directory
-      ((eligible-directories 
-       (let ((tmp (or (get-environment-variable "TEMP")
-                      (get-environment-variable "TMP")))
-             (others '("/tmp" "c:/" "." "/")))
-         (if (not tmp) others (cons tmp others)))))
-    (if (null? eligible-directories)
-       (error "Can't locate directory for temporary file")
-       (let ((dir (->namestring
-                   (pathname-as-directory
-                    (merge-pathnames (car eligible-directories))))))
-         (if (and (file-directory? dir) (file-writable? dir))
-             (let ((base-name (string-append dir "_scm_tmp.")))
-               (let unique-file ((ext 0))
-                 (let ((name (string-append base-name (number->string ext))))
-                   (if (or (file-exists? name) (not (file-touch name)))
-                       (if (fix:> ext 999) ; don't get rediculous here
-                           (error "Cannot find unique temp file name"
-                                  base-name)
-                           (unique-file (fix:+ ext 1)))
-                       (dynamic-wind
-                        (lambda () unspecific)
-                        (lambda () (receiver name))
-                        (lambda () (if (file-exists? name)
-                                       (delete-file name))))))))
-             (find-eligible-directory (cdr eligible-directories)))))))
+(define (temporary-file-pathname)
+  (let ((root (merge-pathnames "_scm_tmp" (temporary-directory-pathname))))
+    (let loop ((ext 0))
+      (let ((pathname (pathname-new-type root (number->string ext))))
+       (if (allocate-temporary-file pathname)
+           pathname
+           (begin
+             (if (> ext 999)
+                 (error "Can't find unique temporary pathname:" root))
+             (loop (+ ext 1))))))))
+
+(define (temporary-directory-pathname)
+  (let ((try-directory
+        (lambda (directory)
+          (let ((directory
+                 (pathname-as-directory (merge-pathnames directory))))
+            (and (file-directory? directory)
+                 (file-writable? directory)
+                 directory)))))
+    (let ((try-variable
+          (lambda (name)
+            (let ((value (get-environment-variable name)))
+              (and value
+                   (try-directory value))))))
+      (or (try-variable "TEMP")
+         (try-variable "TMP")
+         (try-directory "/tmp")
+         (try-directory "c:/")
+         (try-directory ".")
+         (try-directory "/")
+         (error "Can't find temporary directory.")))))
 \f
 (define (file-attributes filename)
   ((ucode-primitive file-attributes 1)
index 401e2bc123d997a80f57dcfd3424cd3f6d9339b5..02ccc9d4e14736442c5bc9bf0af3365991cfa337 100644 (file)
@@ -1,6 +1,6 @@
 #| -*-Scheme-*-
 
-$Id: infutl.scm,v 1.47 1993/07/28 03:42:02 cph Exp $
+$Id: infutl.scm,v 1.48 1993/11/09 04:31:38 cph Exp $
 
 Copyright (c) 1988-1993 Massachusetts Institute of Technology
 
@@ -38,8 +38,6 @@ MIT in each case. |#
 (declare (usual-integrations))
 (declare (integrate-external "infstr" "char"))
 \f
-(define *save-uncompressed-files?* true)
-
 (define (initialize-package!)
   (set! special-form-procedure-names
        `((,lambda-tag:unnamed . LAMBDA)
@@ -49,7 +47,11 @@ MIT in each case. |#
          (,lambda-tag:fluid-let . FLUID-LET)
          (,lambda-tag:make-environment . MAKE-ENVIRONMENT)))
   (set! blocks-with-memoized-debugging-info (make-population))
-  (add-secondary-gc-daemon! discard-debugging-info!))
+  (add-secondary-gc-daemon! discard-debugging-info!)
+  (initialize-uncompressed-files!)
+  (add-event-receiver! event:after-restore initialize-uncompressed-files!)
+  (add-event-receiver! event:before-exit delete-uncompressed-files!)
+  (add-gc-daemon! clean-uncompressed-files!))
 
 (define (compiled-code-block/dbg-info block demand-load?)
   (let ((old-info (compiled-code-block/debugging-info block)))
@@ -96,12 +98,23 @@ MIT in each case. |#
   (let ((pathname (merge-pathnames filename)))
     (if (file-exists? pathname)
        (fasload-loader (->namestring pathname))
-       (find-alternate-file-type
-        pathname
-        `(("inf" . ,fasload-loader)
-          ("bif" . ,fasload-loader)
-          ("bci" . ,(lambda (pathname)
-                      (compressed-loader pathname "bif"))))))))
+       (find-alternate-file-type pathname
+                                 `(("inf" . ,fasload-loader)
+                                   ("bif" . ,fasload-loader)
+                                   ("bci" . ,(compressed-loader "bif")))))))
+
+(define (find-alternate-file-type base-pathname alist)
+  (let loop ((left alist) (time 0) (file #f) (receiver (lambda (x) x)))
+    (if (null? left)
+       (receiver file)
+       (let ((file* (pathname-new-type base-pathname (caar left)))
+             (receiver* (cdar left)))
+         (if (not (file-exists? file*))
+             (loop (cdr left) time file receiver)
+             (let ((time* (file-modification-time-direct file*)))
+               (if (> time* time)
+                   (loop (cdr left) time* file* receiver*)
+                   (loop (cdr left) time file receiver))))))))
 \f
 (define (memoize-debugging-info! block dbg-info)
   (without-interrupts
@@ -404,7 +417,7 @@ MIT in each case. |#
                            (loop (cdr types))))))))))
     (and pathname
         (if (equal? "bcs" (pathname-type pathname))
-            (compressed-loader pathname "bsm")
+            ((compressed-loader "bsm") pathname)
             (fasload-loader pathname)))))
 
 (define (process-bsym-filename name)
@@ -550,6 +563,59 @@ MIT in each case. |#
                      (vector-set! cp-table cp bp)
                      (loop nbp ncp))))))))))
 \f
+(define (fasload-loader filename)
+  (call-with-current-continuation
+    (lambda (if-fail)
+      (bind-condition-handler (list condition-type:fasload-band)
+        (lambda (condition) condition (if-fail false))
+        (lambda () (fasload filename true))))))
+
+(define (compressed-loader uncompressed-type)
+  (lambda (compressed-file)
+    (lookup-uncompressed-file compressed-file fasload-loader
+      (lambda ()
+       (let ((load-compressed
+              (lambda (temporary-file)
+                (call-with-current-continuation
+                 (lambda (k)
+                   (uncompress-internal compressed-file
+                                        temporary-file
+                                        (lambda (message . irritants)
+                                          message irritants
+                                          (k #f)))
+                   (fasload-loader temporary-file))))))
+         (case *save-uncompressed-files?*
+           ((#F)
+            (call-with-temporary-file-pathname load-compressed))
+           ((AUTOMATIC)
+            (call-with-uncompressed-file-pathname compressed-file
+                                                  load-compressed))
+           (else
+            (call-with-temporary-file-pathname
+             (lambda (temporary-file)
+               (let ((result (load-compressed temporary-file))
+                     (uncompressed-file
+                      (pathname-new-type compressed-file uncompressed-type)))
+                 (delete-file-no-errors uncompressed-file)
+                 (if (call-with-current-continuation
+                      (lambda (k)
+                        (bind-condition-handler
+                            (list condition-type:file-error
+                                  condition-type:port-error)
+                            (lambda (condition) condition (k #t))
+                          (lambda ()
+                            (rename-file temporary-file uncompressed-file)
+                            #f))))
+                     (call-with-current-continuation
+                      (lambda (k)
+                        (bind-condition-handler
+                            (list condition-type:file-error
+                                  condition-type:port-error)
+                            (lambda (condition) condition (k unspecific))
+                          (lambda ()
+                            (copy-file temporary-file uncompressed-file))))))
+                 result))))))))))
+
 (define (uncompress-internal ifile ofile if-fail)
   (call-with-binary-input-file (merge-pathnames ifile)
     (lambda (input)                           
@@ -557,62 +623,76 @@ MIT in each case. |#
             (marker-size (string-length file-marker))
             (actual-marker (make-string marker-size)))
        ;; This may get more hairy as we up versions
-       (if (and (fix:= (uncompress-read-substring
-                        input actual-marker 0 marker-size)
+       (if (and (fix:= (uncompress-read-substring input
+                                                  actual-marker 0 marker-size)
                        marker-size)
                 (string=? file-marker actual-marker))
            (call-with-binary-output-file (merge-pathnames ofile)
              (lambda (output)                                    
                (let ((size (file-attributes/length (file-attributes ifile))))
                  (uncompress-ports input output (fix:* size 2)))))
-           (if-fail "Not a recognized compressed file" ifile))))))
-
-(define (find-alternate-file-type base-pathname exts/receivers)
-  (let find-loop ((left exts/receivers)
-                 (time 0)
-                 (file false)
-                 (handler identity-procedure))
-                            
-    (if (null? left)
-       (handler file)
-       (let ((file* (pathname-new-type base-pathname (caar left)))
-             (handler* (cdar left)))
-         (if (not (file-exists? file*))
-             (find-loop (cdr left) time file handler)
-             (let ((time* (file-modification-time-direct file*)))
-               (if (> time* time)
-                   (find-loop (cdr left) time* file* handler*)
-                   (find-loop (cdr left) time file handler))))))))
-
-(define (fasload-loader filename)
-  (call-with-current-continuation
-    (lambda (if-fail)
-      (bind-condition-handler (list condition-type:fasload-band)
-        (lambda (condition) condition (if-fail false))
-        (lambda () (fasload filename true))))))
+           (if-fail "Not a recognized compressed file:" ifile))))))
+\f
+(define (lookup-uncompressed-file compressed-file if-found if-not-found)
+  (dynamic-wind
+   (lambda ()
+     (set-car! uncompressed-files (+ (car uncompressed-files) 1)))
+   (lambda ()
+     (let loop ((entries (cdr uncompressed-files)))
+       (cond ((null? entries)
+             (if-not-found))
+            ((and (pathname=? (caar entries) compressed-file)
+                  (cddar entries))
+             (dynamic-wind
+              (lambda () unspecific)
+              (lambda () (if-found (cadar entries)))
+              (lambda () (set-cdr! (cdar entries) (real-time-clock)))))
+            (else
+             (loop (cdr entries))))))
+   (lambda ()
+     (set-car! uncompressed-files (- (car uncompressed-files) 1)))))
+
+(define (call-with-uncompressed-file-pathname compressed-file receiver)
+  (let ((temporary-file (temporary-file-pathname)))
+    (let ((entry
+          (cons compressed-file
+                (cons temporary-file (real-time-clock)))))
+      (dynamic-wind
+       (lambda () unspecific)
+       (lambda ()
+        (without-interrupts
+         (lambda ()
+           (set-cdr! uncompressed-files
+                     (cons entry (cdr uncompressed-files)))))
+        (receiver temporary-file))
+       (lambda ()
+        (set-cdr! (cdr entry) (real-time-clock)))))))
+
+(define (delete-uncompressed-files!)
+  (do ((entries (cdr uncompressed-files) (cdr entries)))
+      ((null? entries) unspecific)
+    (deallocate-temporary-file (cadar entries))))
+
+(define (clean-uncompressed-files!)
+  (if (= 0 (car uncompressed-files))
+      (let ((time (real-time-clock)))
+       (let loop
+           ((entries (cdr uncompressed-files))
+            (prev uncompressed-files))
+         (if (not (null? entries))
+             (if (or (not (cddar entries))
+                     (< (- time (cddar entries))
+                        *uncompressed-file-lifetime*))
+                 (loop (cdr entries) entries)
+                 (begin
+                   (set-cdr! prev (cdr entries))
+                   (deallocate-temporary-file (cadar entries))
+                   (loop (cdr entries) prev))))))))
+
+(define (initialize-uncompressed-files!)
+  (set! uncompressed-files (list 0))
+  unspecific)
 
-(define (compressed-loader compressed-filename uncompressed-type)
-  (let ((core
-        (lambda (uncompressed-filename)
-          (call-with-current-continuation
-           (lambda (if-fail)
-             (uncompress-internal compressed-filename uncompressed-filename
-                                  (lambda (message . irritants)
-                                    message irritants
-                                    (if-fail false)))
-             (fasload-loader uncompressed-filename))))))
-
-    (call-with-temporary-filename
-     (if (not *save-uncompressed-files?*)
-        core
-        (lambda (temp-file)
-          (let ((result (core temp-file)))
-            (let ((new-file
-                   (pathname-new-type compressed-filename uncompressed-type))
-                  (dir (directory-pathname-as-file compressed-filename)))
-              (if (file-writable? dir)
-                  (begin
-                    (if (file-exists? new-file)
-                        (delete-file new-file))
-                    (copy-file temp-file new-file)))
-              result)))))))
\ No newline at end of file
+(define *save-uncompressed-files?* 'AUTOMATIC)
+(define *uncompressed-file-lifetime* 300000)
+(define uncompressed-files)
\ No newline at end of file
index 0d677be705f7988f3f6c4f8d3093a5ee5e7ae1ac..3bed07d15ae38da703aa3d50abcff279e2dfe57a 100644 (file)
@@ -1,6 +1,6 @@
 #| -*-Scheme-*-
 
-$Id: sfile.scm,v 14.9 1993/11/06 21:36:53 cph Exp $
+$Id: sfile.scm,v 14.10 1993/11/09 04:31:40 cph Exp $
 
 Copyright (c) 1988-93 Massachusetts Institute of Technology
 
@@ -97,4 +97,41 @@ MIT in each case. |#
                             n-read))))))))
        (lambda ()
         (if output-channel (channel-close output-channel))
-        (if input-channel (channel-close input-channel)))))))
\ No newline at end of file
+        (if input-channel (channel-close input-channel)))))))
+\f
+(define (call-with-temporary-filename receiver)
+  (call-with-temporary-file-pathname
+   (lambda (pathname)
+     (receiver (->namestring pathname)))))
+
+(define (call-with-temporary-file-pathname receiver)
+  (let ((pathname (temporary-file-pathname)))
+    (dynamic-wind
+     (lambda () unspecific)
+     (lambda () (receiver pathname))
+     (lambda () (deallocate-temporary-file pathname)))))
+
+(define (allocate-temporary-file pathname)
+  (and (not (file-exists? pathname))
+       (let ((objects (get-fixed-objects-vector))
+            (slot (fixed-objects-vector-slot 'FILES-TO-DELETE))
+            (filename (->namestring pathname)))
+        (without-interrupts
+         (lambda ()
+           (and (file-touch pathname)
+                (begin
+                  (vector-set! objects slot
+                               (cons filename (vector-ref objects slot)))
+                  ((ucode-primitive set-fixed-objects-vector! 1) objects)
+                  #t)))))))
+
+(define (deallocate-temporary-file pathname)
+  (delete-file-no-errors pathname)
+  (let ((objects (get-fixed-objects-vector))
+       (slot (fixed-objects-vector-slot 'FILES-TO-DELETE))
+       (filename (->namestring pathname)))
+    (without-interrupts
+     (lambda ()
+       (vector-set! objects slot
+                   (delete! filename (vector-ref objects slot)))
+       ((ucode-primitive set-fixed-objects-vector! 1) objects)))))
\ No newline at end of file
index efd03063f897e89eaf3a4d4b0abd0ecd9f733241..2ab887f1c7738db13df4dc2ea4c7edaecb26b858 100644 (file)
@@ -1,6 +1,6 @@
 #| -*-Scheme-*-
 
-$Id: unxprm.scm,v 1.25 1993/07/27 00:46:19 cph Exp $
+$Id: unxprm.scm,v 1.26 1993/11/09 04:31:41 cph Exp $
 
 Copyright (c) 1988-1993 Massachusetts Institute of Technology
 
@@ -73,35 +73,41 @@ MIT in each case. |#
                (directory-namestring pathname)
                2))))))
 
-(define (call-with-temporary-filename receiver)
-  (let find-eligible-directory
-      ((eligible-directories 
-       (let ((tmp (or (get-environment-variable "TEMP")
-                      (get-environment-variable "TMP")))
-             (others '("." "/tmp" "/usr/tmp")))
-         (if (not tmp) others (cons tmp others)))))
-    (if (null? eligible-directories)
-       (error "Can't locate directory for temporary file")
-       (let ((dir (->namestring
-                   (pathname-as-directory
-                    (merge-pathnames (car eligible-directories))))))
-         (if (and (file-directory? dir) (file-writable? dir))
-             (let ((base-name
-                    (string-append dir "_" (unix/current-user-name) "_scm")))
-               (let unique-file ((ext 0))
-                 (let ((name (string-append base-name (number->string ext))))
-                   (if (or (file-exists? name)
-                           (not (file-touch name)))
-                       (if (fix:> ext 999) ; don't get rediculous here
-                           (error "Cannot find unique temp file name"
-                                  base-name)
-                           (unique-file (fix:+ ext 1)))
-                       (dynamic-wind
-                        (lambda () unspecific)
-                        (lambda () (receiver name))
-                        (lambda () (if (file-exists? name)
-                                       (delete-file name))))))))
-             (find-eligible-directory (cdr eligible-directories)))))))
+(define (temporary-file-pathname)
+  (let ((root
+        (merge-pathnames
+         (string-append "sch"
+                        (string-pad-left (number->string (unix/current-pid))
+                                         6
+                                         #\0))
+         (temporary-directory-pathname))))
+    (let loop ((ext 0))
+      (let ((pathname (pathname-new-type root (number->string ext))))
+       (if (allocate-temporary-file pathname)
+           pathname
+           (begin
+             (if (> ext 999)
+                 (error "Can't find unique temporary pathname:" root))
+             (loop (+ ext 1))))))))
+
+(define (temporary-directory-pathname)
+  (let ((try-directory
+        (lambda (directory)
+          (let ((directory
+                 (pathname-as-directory (merge-pathnames directory))))
+            (and (file-directory? directory)
+                 (file-writable? directory)
+                 directory)))))
+    (let ((try-variable
+          (lambda (name)
+            (let ((value (get-environment-variable name)))
+              (and value
+                   (try-directory value))))))
+      (or (try-variable "TEMP")
+         (try-variable "TMP")
+         (try-directory "/tmp")
+         (try-directory "/usr/tmp")
+         (error "Can't find temporary directory.")))))
 \f
 (define (file-attributes-direct filename)
   ((ucode-primitive file-attributes 1)
@@ -232,6 +238,9 @@ MIT in each case. |#
   (or ((ucode-primitive gid->string 1) gid)
       (number->string gid 10)))
 
+(define-integrable unix/current-pid
+  (ucode-primitive current-pid 0))
+
 (define-integrable unix/system
   (ucode-primitive system 1))
 
index a7ac052bd4d8174dcc4e97634910b929ab2196e8..9d5d84602763bbeb5197923415b3ff8693f8b5a2 100644 (file)
@@ -1,6 +1,6 @@
 #| -*-Scheme-*-
 
-$Id: version.scm,v 14.165 1993/10/21 11:49:56 cph Exp $
+$Id: version.scm,v 14.166 1993/11/09 04:31:43 cph Exp $
 
 Copyright (c) 1988-1993 Massachusetts Institute of Technology
 
@@ -45,7 +45,7 @@ MIT in each case. |#
                     '()))
   (add-system! microcode-system)
   (add-event-receiver! event:after-restore snarf-microcode-version!)
-  (add-identification! "Runtime" 14 165))
+  (add-identification! "Runtime" 14 166))
 
 (define microcode-system)
 
index 401e2bc123d997a80f57dcfd3424cd3f6d9339b5..02ccc9d4e14736442c5bc9bf0af3365991cfa337 100644 (file)
@@ -1,6 +1,6 @@
 #| -*-Scheme-*-
 
-$Id: infutl.scm,v 1.47 1993/07/28 03:42:02 cph Exp $
+$Id: infutl.scm,v 1.48 1993/11/09 04:31:38 cph Exp $
 
 Copyright (c) 1988-1993 Massachusetts Institute of Technology
 
@@ -38,8 +38,6 @@ MIT in each case. |#
 (declare (usual-integrations))
 (declare (integrate-external "infstr" "char"))
 \f
-(define *save-uncompressed-files?* true)
-
 (define (initialize-package!)
   (set! special-form-procedure-names
        `((,lambda-tag:unnamed . LAMBDA)
@@ -49,7 +47,11 @@ MIT in each case. |#
          (,lambda-tag:fluid-let . FLUID-LET)
          (,lambda-tag:make-environment . MAKE-ENVIRONMENT)))
   (set! blocks-with-memoized-debugging-info (make-population))
-  (add-secondary-gc-daemon! discard-debugging-info!))
+  (add-secondary-gc-daemon! discard-debugging-info!)
+  (initialize-uncompressed-files!)
+  (add-event-receiver! event:after-restore initialize-uncompressed-files!)
+  (add-event-receiver! event:before-exit delete-uncompressed-files!)
+  (add-gc-daemon! clean-uncompressed-files!))
 
 (define (compiled-code-block/dbg-info block demand-load?)
   (let ((old-info (compiled-code-block/debugging-info block)))
@@ -96,12 +98,23 @@ MIT in each case. |#
   (let ((pathname (merge-pathnames filename)))
     (if (file-exists? pathname)
        (fasload-loader (->namestring pathname))
-       (find-alternate-file-type
-        pathname
-        `(("inf" . ,fasload-loader)
-          ("bif" . ,fasload-loader)
-          ("bci" . ,(lambda (pathname)
-                      (compressed-loader pathname "bif"))))))))
+       (find-alternate-file-type pathname
+                                 `(("inf" . ,fasload-loader)
+                                   ("bif" . ,fasload-loader)
+                                   ("bci" . ,(compressed-loader "bif")))))))
+
+(define (find-alternate-file-type base-pathname alist)
+  (let loop ((left alist) (time 0) (file #f) (receiver (lambda (x) x)))
+    (if (null? left)
+       (receiver file)
+       (let ((file* (pathname-new-type base-pathname (caar left)))
+             (receiver* (cdar left)))
+         (if (not (file-exists? file*))
+             (loop (cdr left) time file receiver)
+             (let ((time* (file-modification-time-direct file*)))
+               (if (> time* time)
+                   (loop (cdr left) time* file* receiver*)
+                   (loop (cdr left) time file receiver))))))))
 \f
 (define (memoize-debugging-info! block dbg-info)
   (without-interrupts
@@ -404,7 +417,7 @@ MIT in each case. |#
                            (loop (cdr types))))))))))
     (and pathname
         (if (equal? "bcs" (pathname-type pathname))
-            (compressed-loader pathname "bsm")
+            ((compressed-loader "bsm") pathname)
             (fasload-loader pathname)))))
 
 (define (process-bsym-filename name)
@@ -550,6 +563,59 @@ MIT in each case. |#
                      (vector-set! cp-table cp bp)
                      (loop nbp ncp))))))))))
 \f
+(define (fasload-loader filename)
+  (call-with-current-continuation
+    (lambda (if-fail)
+      (bind-condition-handler (list condition-type:fasload-band)
+        (lambda (condition) condition (if-fail false))
+        (lambda () (fasload filename true))))))
+
+(define (compressed-loader uncompressed-type)
+  (lambda (compressed-file)
+    (lookup-uncompressed-file compressed-file fasload-loader
+      (lambda ()
+       (let ((load-compressed
+              (lambda (temporary-file)
+                (call-with-current-continuation
+                 (lambda (k)
+                   (uncompress-internal compressed-file
+                                        temporary-file
+                                        (lambda (message . irritants)
+                                          message irritants
+                                          (k #f)))
+                   (fasload-loader temporary-file))))))
+         (case *save-uncompressed-files?*
+           ((#F)
+            (call-with-temporary-file-pathname load-compressed))
+           ((AUTOMATIC)
+            (call-with-uncompressed-file-pathname compressed-file
+                                                  load-compressed))
+           (else
+            (call-with-temporary-file-pathname
+             (lambda (temporary-file)
+               (let ((result (load-compressed temporary-file))
+                     (uncompressed-file
+                      (pathname-new-type compressed-file uncompressed-type)))
+                 (delete-file-no-errors uncompressed-file)
+                 (if (call-with-current-continuation
+                      (lambda (k)
+                        (bind-condition-handler
+                            (list condition-type:file-error
+                                  condition-type:port-error)
+                            (lambda (condition) condition (k #t))
+                          (lambda ()
+                            (rename-file temporary-file uncompressed-file)
+                            #f))))
+                     (call-with-current-continuation
+                      (lambda (k)
+                        (bind-condition-handler
+                            (list condition-type:file-error
+                                  condition-type:port-error)
+                            (lambda (condition) condition (k unspecific))
+                          (lambda ()
+                            (copy-file temporary-file uncompressed-file))))))
+                 result))))))))))
+
 (define (uncompress-internal ifile ofile if-fail)
   (call-with-binary-input-file (merge-pathnames ifile)
     (lambda (input)                           
@@ -557,62 +623,76 @@ MIT in each case. |#
             (marker-size (string-length file-marker))
             (actual-marker (make-string marker-size)))
        ;; This may get more hairy as we up versions
-       (if (and (fix:= (uncompress-read-substring
-                        input actual-marker 0 marker-size)
+       (if (and (fix:= (uncompress-read-substring input
+                                                  actual-marker 0 marker-size)
                        marker-size)
                 (string=? file-marker actual-marker))
            (call-with-binary-output-file (merge-pathnames ofile)
              (lambda (output)                                    
                (let ((size (file-attributes/length (file-attributes ifile))))
                  (uncompress-ports input output (fix:* size 2)))))
-           (if-fail "Not a recognized compressed file" ifile))))))
-
-(define (find-alternate-file-type base-pathname exts/receivers)
-  (let find-loop ((left exts/receivers)
-                 (time 0)
-                 (file false)
-                 (handler identity-procedure))
-                            
-    (if (null? left)
-       (handler file)
-       (let ((file* (pathname-new-type base-pathname (caar left)))
-             (handler* (cdar left)))
-         (if (not (file-exists? file*))
-             (find-loop (cdr left) time file handler)
-             (let ((time* (file-modification-time-direct file*)))
-               (if (> time* time)
-                   (find-loop (cdr left) time* file* handler*)
-                   (find-loop (cdr left) time file handler))))))))
-
-(define (fasload-loader filename)
-  (call-with-current-continuation
-    (lambda (if-fail)
-      (bind-condition-handler (list condition-type:fasload-band)
-        (lambda (condition) condition (if-fail false))
-        (lambda () (fasload filename true))))))
+           (if-fail "Not a recognized compressed file:" ifile))))))
+\f
+(define (lookup-uncompressed-file compressed-file if-found if-not-found)
+  (dynamic-wind
+   (lambda ()
+     (set-car! uncompressed-files (+ (car uncompressed-files) 1)))
+   (lambda ()
+     (let loop ((entries (cdr uncompressed-files)))
+       (cond ((null? entries)
+             (if-not-found))
+            ((and (pathname=? (caar entries) compressed-file)
+                  (cddar entries))
+             (dynamic-wind
+              (lambda () unspecific)
+              (lambda () (if-found (cadar entries)))
+              (lambda () (set-cdr! (cdar entries) (real-time-clock)))))
+            (else
+             (loop (cdr entries))))))
+   (lambda ()
+     (set-car! uncompressed-files (- (car uncompressed-files) 1)))))
+
+(define (call-with-uncompressed-file-pathname compressed-file receiver)
+  (let ((temporary-file (temporary-file-pathname)))
+    (let ((entry
+          (cons compressed-file
+                (cons temporary-file (real-time-clock)))))
+      (dynamic-wind
+       (lambda () unspecific)
+       (lambda ()
+        (without-interrupts
+         (lambda ()
+           (set-cdr! uncompressed-files
+                     (cons entry (cdr uncompressed-files)))))
+        (receiver temporary-file))
+       (lambda ()
+        (set-cdr! (cdr entry) (real-time-clock)))))))
+
+(define (delete-uncompressed-files!)
+  (do ((entries (cdr uncompressed-files) (cdr entries)))
+      ((null? entries) unspecific)
+    (deallocate-temporary-file (cadar entries))))
+
+(define (clean-uncompressed-files!)
+  (if (= 0 (car uncompressed-files))
+      (let ((time (real-time-clock)))
+       (let loop
+           ((entries (cdr uncompressed-files))
+            (prev uncompressed-files))
+         (if (not (null? entries))
+             (if (or (not (cddar entries))
+                     (< (- time (cddar entries))
+                        *uncompressed-file-lifetime*))
+                 (loop (cdr entries) entries)
+                 (begin
+                   (set-cdr! prev (cdr entries))
+                   (deallocate-temporary-file (cadar entries))
+                   (loop (cdr entries) prev))))))))
+
+(define (initialize-uncompressed-files!)
+  (set! uncompressed-files (list 0))
+  unspecific)
 
-(define (compressed-loader compressed-filename uncompressed-type)
-  (let ((core
-        (lambda (uncompressed-filename)
-          (call-with-current-continuation
-           (lambda (if-fail)
-             (uncompress-internal compressed-filename uncompressed-filename
-                                  (lambda (message . irritants)
-                                    message irritants
-                                    (if-fail false)))
-             (fasload-loader uncompressed-filename))))))
-
-    (call-with-temporary-filename
-     (if (not *save-uncompressed-files?*)
-        core
-        (lambda (temp-file)
-          (let ((result (core temp-file)))
-            (let ((new-file
-                   (pathname-new-type compressed-filename uncompressed-type))
-                  (dir (directory-pathname-as-file compressed-filename)))
-              (if (file-writable? dir)
-                  (begin
-                    (if (file-exists? new-file)
-                        (delete-file new-file))
-                    (copy-file temp-file new-file)))
-              result)))))))
\ No newline at end of file
+(define *save-uncompressed-files?* 'AUTOMATIC)
+(define *uncompressed-file-lifetime* 300000)
+(define uncompressed-files)
\ No newline at end of file