;;; tar-mode.el --- simple editing of tar files from GNU emacs
-;; Copyright (C) 1990,91,93,94,95,96,97,98,99,2000,2001
-;; Free Software Foundation, Inc.
+;; Copyright (C) 1990, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+;; 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
;; Author: Jamie Zawinski <jwz@lucid.com>
;; Maintainer: FSF
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; This code now understands the extra fields that GNU tar adds to tar files.
;; This interacts correctly with "uncompress.el" in the Emacs library,
-;; which you get with
+;; which you get with
;;
;; (autoload 'uncompress-while-visiting "uncompress")
;; (setq auto-mode-alist (cons '("\\.Z$" . uncompress-while-visiting)
;;
;; Do not attempt to use tar-mode.el with crypt.el, you will lose.
-;; *************** TO DO ***************
+;; *************** TO DO ***************
;;
;; o chmod should understand "a+x,og-w".
;;
-;; o It's not possible to add a NEW file to a tar archive; not that
+;; o It's not possible to add a NEW file to a tar archive; not that
;; important, but still...
;;
;; o The code is less efficient that it could be - in a lot of places, I
;; of an archive, where <esc> would leave you in a subfile-edit buffer.
;; (Like the Meta-R command of the Zmacs mail reader.)
;;
-;; o Sometimes (but not always) reverting the tar-file buffer does not
+;; o Sometimes (but not always) reverting the tar-file buffer does not
;; re-grind the listing, and you are staring at the binary tar data.
;; Typing 'g' again immediately after that will always revert and re-grind
;; it, though. I have no idea why this happens.
;; might be a problem if the tar write-file-hook does not come *first* on
;; the list.
;;
-;; o Block files, sparse files, continuation files, and the various header
+;; o Block files, sparse files, continuation files, and the various header
;; types aren't editable. Actually I don't know that they work at all.
;; Rationale:
(defcustom tar-anal-blocksize 20
"*The blocksize of tar files written by Emacs, or nil, meaning don't care.
The blocksize of a tar file is not really the size of the blocks; rather, it is
-the number of blocks written with one system call. When tarring to a tape,
+the number of blocks written with one system call. When tarring to a tape,
this is the size of the *tape* blocks, but when writing to a file, it doesn't
matter much. The only noticeable difference is that if a tar file does not
have a blocksize of 20, tar will tell you that; all this really controls is
tar file will update its datestamp. If false, the datestamp is unchanged.
You may or may not want this - it is good in that you can tell when a file
in a tar archive has been changed, but it is bad for the same reason that
-editing a file in the tar archive at all is bad - the changed version of
+editing a file in the tar archive at all is bad - the changed version of
the file never exists on disk."
:type 'boolean
:group 'tar)
(defun tar-header-block-tokenize (string)
"Return a `tar-header' structure.
-This is a list of name, mode, uid, gid, size,
+This is a list of name, mode, uid, gid, size,
write-date, checksum, link-type, and link-name."
(cond ((< (length string) 512) nil)
(;(some 'plusp string) ; <-- oops, massive cycle hog!
(dotimes (i L)
(if (or (< (aref string i) ?0)
(> (aref string i) ?7))
- (error "`%c' is not an octal digit"))))
+ (error "`%c' is not an octal digit" (aref string i)))))
(tar-parse-octal-integer string))
(format "%c%c%s%8s/%-8s%7s%s %s%s"
(if mod-p ?* ? )
(cond ((or (eq type nil) (eq type 0)) ?-)
- ((eq type 1) ?l) ; link
- ((eq type 2) ?s) ; symlink
+ ((eq type 1) ?h) ; link
+ ((eq type 2) ?l) ; symlink
((eq type 3) ?c) ; char special
((eq type 4) ?b) ; block special
((eq type 5) ?d) ; directory
then narrow to it, so that only that listing
is visible (and the real data of the buffer is hidden)."
(set-buffer-multibyte nil)
- (message "Parsing tar file...")
(let* ((result '())
(pos (point-min))
- (bs (max 1 (- (buffer-size) 1024))) ; always 2+ empty blocks at end.
- (bs100 (max 1 (/ bs 100)))
+ (progress-reporter
+ (make-progress-reporter "Parsing tar file..."
+ (point-min) (max 1 (- (buffer-size) 1024))))
tokens)
(while (and (<= (+ pos 512) (point-max))
(not (eq 'empty-tar-block
(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
- )
+ (progress-reporter-update progress-reporter pos)
(if (eq (tar-header-link-type tokens) 20)
;; Foo. There's an extra empty block after these.
(setq pos (+ pos 512)))
;; 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")
+ (progress-reporter-done progress-reporter)
(message "Warning: premature EOF parsing tar file")))
(save-excursion
(goto-char (point-min))
;;;###autoload
(define-derived-mode tar-mode nil "Tar"
"Major mode for viewing a tar file as a dired-like listing of its contents.
-You can move around using the usual cursor motion commands.
+You can move around using the usual cursor motion commands.
Letters no longer insert themselves.
Type `e' to pull a file out of the tar file and into its own buffer;
or click mouse-2 on the file's line in the Tar mode buffer.
Type `c' to copy an entry from the tar file into another file on disk.
-If you edit a sub-file of this archive (as with the `e' command) and
-save it with Control-x Control-s, the contents of that buffer will be
-saved back into the tar-file buffer; in this way you can edit a file
+If you edit a sub-file of this archive (as with the `e' command) and
+save it with Control-x Control-s, the contents of that buffer will be
+saved back into the tar-file buffer; in this way you can edit a file
inside of a tar archive without extracting it and re-archiving it.
See also: variables `tar-update-datestamp' and `tar-anal-blocksize'.
;; Prevent loss of data when saving the file.
(set (make-local-variable 'file-precious-flag) t)
(auto-save-mode 0)
- (set (make-local-variable 'write-contents-hooks) '(tar-mode-write-file))
+ (set (make-local-variable 'write-contents-functions) '(tar-mode-write-file))
+ (buffer-disable-undo)
(widen)
(if (and (boundp 'tar-header-offset) tar-header-offset)
(narrow-to-region (point-min) (byte-to-position tar-header-offset))
(set-buffer-multibyte nil)
(save-excursion
(set-buffer buffer)
- (if enable-multibyte-characters
- (progn
- ;; We must avoid unibyte->multibyte conversion.
- (set-buffer-multibyte nil)
- (insert-buffer-substring tar-buffer start end)
- (set-buffer-multibyte t))
- (insert-buffer-substring tar-buffer start end))
- (goto-char (point-min))
- (setq buffer-file-name new-buffer-file-name)
- (setq buffer-file-truename
- (abbreviate-file-name buffer-file-name))
- ;; We need to mimic the parts of insert-file-contents
- ;; which determine the coding-system and decode the text.
- (let ((coding
- (or coding-system-for-read
- (and set-auto-coding-function
- (save-excursion
- (funcall set-auto-coding-function
- name (- (point-max) (point)))))))
- (multibyte enable-multibyte-characters)
- (detected (detect-coding-region
- (point-min)
- (min (+ (point-min) 16384) (point-max)) t)))
- (if coding
- (or (numberp (coding-system-eol-type coding))
- (setq coding (coding-system-change-eol-conversion
- coding
- (coding-system-eol-type detected))))
- (setq coding
- (or (find-new-buffer-file-coding-system detected)
- (let ((file-coding
- (find-operation-coding-system
- 'insert-file-contents buffer-file-name)))
- (if (consp file-coding)
- (setq file-coding (car file-coding))
- file-coding)))))
- (if (or (eq coding 'no-conversion)
- (eq (coding-system-type coding) 5))
- (setq multibyte (set-buffer-multibyte nil)))
- (or multibyte
+ (let ((buffer-undo-list t))
+ (if enable-multibyte-characters
+ (progn
+ ;; We must avoid unibyte->multibyte conversion.
+ (set-buffer-multibyte nil)
+ (insert-buffer-substring tar-buffer start end)
+ (set-buffer-multibyte t))
+ (insert-buffer-substring tar-buffer start end))
+ (goto-char (point-min))
+ (setq buffer-file-name new-buffer-file-name)
+ (setq buffer-file-truename
+ (abbreviate-file-name buffer-file-name))
+ ;; We need to mimic the parts of insert-file-contents
+ ;; which determine the coding-system and decode the text.
+ (let ((coding
+ (or coding-system-for-read
+ (and set-auto-coding-function
+ (save-excursion
+ (funcall set-auto-coding-function
+ name (- (point-max) (point)))))
+ (car (find-operation-coding-system
+ 'insert-file-contents name t))))
+ (multibyte enable-multibyte-characters)
+ (detected (detect-coding-region
+ (point-min)
+ (min (+ (point-min) 16384) (point-max)) t)))
+ (if coding
+ (or (numberp (coding-system-eol-type coding))
+ (vectorp (coding-system-eol-type detected))
+ (setq coding (coding-system-change-eol-conversion
+ coding
+ (coding-system-eol-type detected))))
(setq coding
- (coding-system-change-text-conversion
- coding 'raw-text)))
- (decode-coding-region (point-min) (point-max) coding)
- (set-buffer-file-coding-system coding))
- ;; Set the default-directory to the dir of the
- ;; superior buffer.
- (setq default-directory
- (save-excursion
- (set-buffer tar-buffer)
- default-directory))
- (normal-mode) ; pick a mode.
- (rename-buffer bufname)
- (make-local-variable 'tar-superior-buffer)
- (make-local-variable 'tar-superior-descriptor)
- (setq tar-superior-buffer tar-buffer)
- (setq tar-superior-descriptor descriptor)
- (setq buffer-read-only read-only-p)
- (set-buffer-modified-p nil)
+ (find-new-buffer-file-coding-system detected)))
+ (if (or (eq coding 'no-conversion)
+ (eq (coding-system-type coding) 5))
+ (setq multibyte (set-buffer-multibyte nil)))
+ (or multibyte
+ (setq coding
+ (coding-system-change-text-conversion
+ coding 'raw-text)))
+ (decode-coding-region (point-min) (point-max) coding)
+ (set-buffer-file-coding-system coding))
+ ;; Set the default-directory to the dir of the
+ ;; superior buffer.
+ (setq default-directory
+ (save-excursion
+ (set-buffer tar-buffer)
+ default-directory))
+ (normal-mode) ; pick a mode.
+ (rename-buffer bufname)
+ (make-local-variable 'tar-superior-buffer)
+ (make-local-variable 'tar-superior-descriptor)
+ (setq tar-superior-buffer tar-buffer)
+ (setq tar-superior-descriptor descriptor)
+ (setq buffer-read-only read-only-p)
+ (set-buffer-modified-p nil))
(tar-subfile-mode 1))
(set-buffer tar-buffer))
(narrow-to-region (point-min) tar-header-offset)
(delete-region p (point))
(insert (tar-header-block-summarize tokens) "\n")
(setq tar-header-offset (position-bytes (point-max))))
-
+
(widen)
(set-buffer-multibyte nil)
(let* ((start (+ (tar-desc-data-start descriptor) tar-header-offset -513)))
(descriptor tar-superior-descriptor)
subfile-size)
;; We must make the current buffer unibyte temporarily to avoid
- ;; multibyte->unibyte conversion in `insert-buffer'.
+ ;; multibyte->unibyte conversion in `insert-buffer-substring'.
(set-buffer-multibyte nil)
(setq subfile-size (buffer-size))
(set-buffer tar-superior-buffer)
(delete-region data-start data-end)
;; insert the new data...
(goto-char data-start)
- (insert-buffer subfile)
+ (insert-buffer-substring subfile)
(setq subfile-size
(encode-coding-region
data-start (+ data-start subfile-size) coding))
\f
(provide 'tar-mode)
+;;; arch-tag: 8a585a4a-340e-42c2-89e7-d3b1013a4b78
;;; tar-mode.el ends here