Add handling of tar archives. Improved documentation.
[rrq/newlisp/packnl.git] / incore.lsp
index 5cd646b19c4890418daf6e3d92f1a9b9ee8becce..8f24187ef6b449daeaf2f27e404c40c80ed4aef4 100644 (file)
 ;; Use (archive pathname) to register all members of the nominated ar
 ;; style archive.
 
+;; This is a hashmap of loaded files
 (new Tree 'archives)
 
+;; A copy of the executable
 (define core:core (read-file "/proc/self/exe"))
 
 (context 'archive)
 
 (setf main nil)
 
-(constant 'AR "/usr/bin/ar")
+(constant 'AR "/usr/bin/ar" 'TAR "/bin/tar" 'FILE "/usr/bin/file")
 
+(define (tar-able PATH)
+  (when (file? FILE)
+    (if (exec (format "%s -Z %s" FILE PATH))
+        (find " tar archive" ($it 0)))))
+
+;; Install indexes for all members of the given archive file
 (define (archive:archive PATH)
   ;;(write-line 2 (string (list 'archive PATH)))
   (map (fn (F) (archives F PATH) F)
-       (exec (format "%s t %s" AR PATH))))
+       (if (directory? PATH) (directory PATH "^[^.]")
+         (ends-with PATH ".a") (exec (format "%s t %s" AR PATH))
+         (tar-able PATH) (exec (format "%s tf %s" TAR PATH))
+         '()
+         )))
 
-(define (get-ar PATH MEMBER)
-  ;;(write-line 2 (string (list 'get-ar PATH MEMBER)))
+;; Read a member of an external archive
+(define (get-stdin CMD)
   (let ((I (pipe)) (O (pipe)) (DATA "") (ALL "")
         (SUB (fn (I O)
-               (close (I 1)) (close (O 0)) (close 0)
-               (process (format "%s p %s %s" AR PATH MEMBER) (I 0) (O 1)))))
+               (map close (list (I 1) (O 0) 0))
+               (process CMD (I 0) (O 1)))))
     (fork (SUB I O))
     (close (O 1)) (close (I 0)) (close (I 1))
     (while (> (or (read (O 0) DATA 1000000) 0)) (extend ALL DATA))
     (close (I 0))
     ALL))
 
+;; Read an archive member. The given PATH is either a string path for
+;; an external archive file or the (position length) list for an
+;; incore packaged member.
 (define (get PATH MEMBER)
   (if (list? PATH) ((PATH 0) (PATH 1) core)
-    (ends-with PATH ".a") (get-ar PATH MEMBER)))
+    (directory? PATH) (read-file (format "%s/%s" PATH MEMBER))
+    (ends-with PATH ".a") (get-stdin (format "%s p %s %s" AR PATH MEMBER))
+    (tar-able PATH) (get-stdin (format "%s xOf %s %s" TAR PATH MEMBER))
+    ))
 
 ;; Discover and load an in-core archive by means of a marker row of 40
 ;; "x", and then a series of pathname\nsize\nbytes[size] members.