emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

tar-mode.el


From: Erik Assum
Subject: tar-mode.el
Date: Thu, 10 Jan 2002 15:38:27 +0100
User-agent: Gnus/5.090004 (Oort Gnus v0.04) Emacs/21.1

Hi all!

Here is a patch to tar-mode.el which adds untar functionality, eg lets
you untar a buffer to the filesystem.

I've also added a function tar-apply-to-buffer which accepts a
function as parameter and applies this to all entries in the tar file.

Erik.
-- 
"...as a robotics designer once told me, you don't really appreciate how smart
a moron is until you try to design a robot..." --Jerry Pournelle
--- lisp/tar-mode.el    Thu Sep 27 10:11:36 2001
+++ /usr/local/share/emacs/21.1/lisp/tar-mode.el        Thu Jan 10 15:36:27 2002
@@ -373,15 +373,37 @@
                (concat (if (= type 1) " ==> " " --> ") link-name)
              ""))))
 
-(defun tar-summarize-buffer ()
-  "Parse the contents of the tar file in the current buffer.
-Place a dired-like listing on the front;
-then narrow to it, so that only that listing
-is visible (and the real data of the buffer is hidden)."
-  (set-buffer-multibyte nil)
+(defun tar-untar-buffer (&optional buffer)
+  "Extracts all the files in the tar-file to the filesystem, like
+tar xf would have done"
+  (interactive)
+  (if buffer
+      (set-buffer buffer))
+  (let ((tar-directory nil))
+    (widen)
+      (beginning-of-buffer)
+      (forward-char (1- (or tar-header-offset 1)))
+      (tar-apply-to-buffer
+     (lambda (tokens pos)
+       (let* ((current-file (tar-header-name tokens))
+            (current-directory (or (file-name-directory current-file)
+                                   nil))
+            (current-size (tar-header-size tokens)))
+        (message "Extracting %s" current-file)
+        (if (and current-directory (not (file-exists-p current-directory)))
+          (make-directory current-directory  t))
+        (write-region pos (+ pos current-size) current-file)
+        (set-file-modes current-file (tar-header-mode tokens)))))
+      (narrow-to-region (point-min) tar-header-offset)
+    tar-directory))
+
+(defun tar-apply-to-buffer (func)
+  "Applies the function passed as parameter to each file in the tar file
+the function is passed two parameters, the tokens structure for the current
+entry in the tar-file, and the current position in the buffer"
   (message "Parsing tar file...")
-  (let* ((result '())
-        (pos 1)
+  (set-buffer-multibyte nil)
+  (let* ((pos (point))
         (bs (max 1 (- (buffer-size) 1024))) ; always 2+ empty blocks at end.
         (bs100 (max 1 (/ bs 100)))
         tokens)
@@ -391,14 +413,15 @@
                               (tar-header-block-tokenize
                                (buffer-substring pos (+ pos 512)))))))
       (setq pos (+ pos 512))
-      (message "Parsing tar file...%d%%"
-              ;(/ (* pos 100) bs)   ; this gets round-off lossage
-              (/ pos bs100)         ; this doesn't
-              )
+;       (message "Parsing tar file...%d%%"
+;             ;(/ (* pos 100) bs)   ; this gets round-off lossage
+;             (/ pos bs100)         ; this doesn't
+;             )
       (if (eq (tar-header-link-type tokens) 20)
          ;; Foo.  There's an extra empty block after these.
          (setq pos (+ pos 512)))
       (let ((size (tar-header-size tokens)))
+
        (if (< size 0)
            (error "%s has size %s - corrupted"
                   (tar-header-name tokens) size))
@@ -408,21 +431,31 @@
        ;  hblock (tar-header-block-checksum hblock)
        ;  (tar-header-name tokens))
 
-       (setq result (cons (make-tar-desc pos tokens) result))
+       (funcall func tokens pos)
 
        (and (null (tar-header-link-type tokens))
             (> size 0)
             (setq pos
                   (+ pos 512 (ash (ash (1- size) -9) 9))        ; this works
-                  ;(+ pos (+ size (- 512 (rem (1- size) 512)))) ; this doesn't
                   ))))
+     (if (eq tokens 'empty-tar-block)
+        (message "Parsing tar file...done")
+       (message "Warning: premature EOF parsing tar file"))))
+  
+(defun tar-summarize-buffer ()  
+  "Parse the contents of the tar file in the current buffer.
+Place a dired-like listing on the front;
+then narrow to it, so that only that listing
+is visible (and the real data of the buffer is hidden)."
+  (let ((result '()))
+    (beginning-of-buffer)
+    (tar-apply-to-buffer (lambda (tokens pos)
+                          (setq result (cons
+                                        (make-tar-desc pos tokens)
+                                        result))))
+;    (message "final result has length %s" result)
     (make-local-variable 'tar-parse-info)
     (setq tar-parse-info (nreverse result))
-    ;; A tar file should end with a block or two of nulls,
-    ;; but let's not get a fatal error if it doesn't.
-    (if (eq tokens 'empty-tar-block)
-       (message "Parsing tar file...done")
-      (message "Warning: premature EOF parsing tar file")))
   (save-excursion
     (goto-char (point-min))
     (let ((buffer-read-only nil)
@@ -443,7 +476,7 @@
       (narrow-to-region 1 tar-header-offset)
       (if enable-multibyte-characters
          (setq tar-header-offset (position-bytes tar-header-offset)))
-      (set-buffer-modified-p nil))))
+      (set-buffer-modified-p nil)))))
 
 (defvar tar-mode-map nil "*Local keymap for Tar mode listings.")
 






reply via email to

[Prev in Thread] Current Thread [Next in Thread]