;;; tar-mode.el --- simple editing of tar files from GNU emacs
-;; Copyright (C) 1990, 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+;; Copyright (C) 1990,91,93,94,95,96,97,98,99,2000,01,2004
+;; Free Software Foundation, Inc.
;; Author: Jamie Zawinski <jwz@lucid.com>
;; Maintainer: FSF
;; 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)
(put 'tar-superior-buffer 'permanent-local t)
(put 'tar-superior-descriptor 'permanent-local t)
\f
-;;; First, duplicate some Common Lisp functions; I used to just (require 'cl)
-;;; but "cl.el" was messing some people up (also it's really big).
-
(defmacro tar-setf (form val)
"A mind-numbingly simple implementation of setf."
(let ((mform (macroexpand form (and (boundp 'byte-compile-macro-environment)
((eq (car mform) 'cdr)
(list 'setcdr (nth 1 mform) val))
(t (error "don't know how to setf %s" form)))))
-
-(defmacro tar-dolist (control &rest body)
- "syntax: (dolist (var-name list-expr &optional return-value) &body body)"
- (let ((var (car control))
- (init (car (cdr control)))
- (val (car (cdr (cdr control)))))
- (list 'let (list (list '_dolist_iterator_ init))
- (list 'while '_dolist_iterator_
- (cons 'let
- (cons (list (list var '(car _dolist_iterator_)))
- (append body
- (list (list 'setq '_dolist_iterator_
- (list 'cdr '_dolist_iterator_)))))))
- val)))
-
-(defmacro tar-dotimes (control &rest body)
- "syntax: (dolist (var-name count-expr &optional return-value) &body body)"
- (let ((var (car control))
- (n (car (cdr control)))
- (val (car (cdr (cdr control)))))
- (list 'let (list (list '_dotimes_end_ n)
- (list var 0))
- (cons 'while
- (cons (list '< var '_dotimes_end_)
- (append body
- (list (list 'setq var (list '1+ var))))))
- val)))
-
\f
;;; down to business.
(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!
(link-p (aref string tar-linkp-offset))
(magic-str (substring string tar-magic-offset (1- tar-uname-offset)))
(uname-valid-p (or (string= "ustar " magic-str) (string= "GNUtar " magic-str)))
- name
+ name linkname
(nulsexp "[^\000]*\000"))
- (and (string-match nulsexp string tar-name-offset) (setq name-end (min name-end (1- (match-end 0)))))
- (and (string-match nulsexp string tar-link-offset) (setq link-end (min link-end (1- (match-end 0)))))
- (and (string-match nulsexp string tar-uname-offset) (setq uname-end (min uname-end (1- (match-end 0)))))
- (and (string-match nulsexp string tar-gname-offset) (setq gname-end (min gname-end (1- (match-end 0)))))
+ (when (string-match nulsexp string tar-name-offset)
+ (setq name-end (min name-end (1- (match-end 0)))))
+ (when (string-match nulsexp string tar-link-offset)
+ (setq link-end (min link-end (1- (match-end 0)))))
+ (when (string-match nulsexp string tar-uname-offset)
+ (setq uname-end (min uname-end (1- (match-end 0)))))
+ (when (string-match nulsexp string tar-gname-offset)
+ (setq gname-end (min gname-end (1- (match-end 0)))))
(setq name (substring string tar-name-offset name-end)
link-p (if (or (= link-p 0) (= link-p ?0))
nil
(defun tar-parse-octal-integer-safe (string)
(let ((L (length string)))
(if (= L 0) (error "empty string"))
- (tar-dotimes (i L)
+ (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))
(if (not (= desired-checksum (tar-header-block-checksum hblock)))
(progn (beep) (message "Invalid checksum for file %s!" file-name))))
-(defun tar-header-block-recompute-checksum (hblock)
- "Modifies the given string to have a valid checksum field."
- (let* ((chk (tar-header-block-checksum hblock))
- (chk-string (format "%6o" chk))
- (l (length chk-string)))
- (aset hblock 154 0)
- (aset hblock 155 32)
- (tar-dotimes (i l) (aset hblock (- 153 i) (aref chk-string (- l i 1)))))
- hblock)
-
(defun tar-clip-time-string (time)
(let ((str (current-time-string time)))
- (concat (substring str 4 16) (substring str 19 24))))
+ (concat " " (substring str 4 16) (substring str 19 24))))
-(defun tar-grind-file-mode (mode string start)
- "Store `-rw--r--r--' indicating MODE into STRING beginning at START.
+(defun tar-grind-file-mode (mode)
+ "Construct a `-rw--r--r--' string indicating MODE.
MODE should be an integer which is a file mode value."
- (aset string start (if (zerop (logand 256 mode)) ?- ?r))
- (aset string (+ start 1) (if (zerop (logand 128 mode)) ?- ?w))
- (aset string (+ start 2) (if (zerop (logand 64 mode)) ?- ?x))
- (aset string (+ start 3) (if (zerop (logand 32 mode)) ?- ?r))
- (aset string (+ start 4) (if (zerop (logand 16 mode)) ?- ?w))
- (aset string (+ start 5) (if (zerop (logand 8 mode)) ?- ?x))
- (aset string (+ start 6) (if (zerop (logand 4 mode)) ?- ?r))
- (aset string (+ start 7) (if (zerop (logand 2 mode)) ?- ?w))
- (aset string (+ start 8) (if (zerop (logand 1 mode)) ?- ?x))
- (if (zerop (logand 1024 mode)) nil (aset string (+ start 2) ?s))
- (if (zerop (logand 2048 mode)) nil (aset string (+ start 5) ?s))
- string)
+ (string
+ (if (zerop (logand 256 mode)) ?- ?r)
+ (if (zerop (logand 128 mode)) ?- ?w)
+ (if (zerop (logand 1024 mode)) (if (zerop (logand 64 mode)) ?- ?x) ?s)
+ (if (zerop (logand 32 mode)) ?- ?r)
+ (if (zerop (logand 16 mode)) ?- ?w)
+ (if (zerop (logand 2048 mode)) (if (zerop (logand 8 mode)) ?- ?x) ?s)
+ (if (zerop (logand 4 mode)) ?- ?r)
+ (if (zerop (logand 2 mode)) ?- ?w)
+ (if (zerop (logand 1 mode)) ?- ?x)))
(defun tar-header-block-summarize (tar-hblock &optional mod-p)
- "Returns a line similar to the output of `tar -vtf'."
+ "Return a line similar to the output of `tar -vtf'."
(let ((name (tar-header-name tar-hblock))
(mode (tar-header-mode tar-hblock))
(uid (tar-header-uid tar-hblock))
(size (tar-header-size tar-hblock))
(time (tar-header-date tar-hblock))
(ck (tar-header-checksum tar-hblock))
- (link-p (tar-header-link-type tar-hblock))
- (link-name (tar-header-link-name tar-hblock))
- )
- (let* ((left 11)
- (namew 8)
- (groupw 8)
- (sizew 8)
- (datew (if tar-mode-show-date 18 0))
- (slash (1- (+ left namew)))
- (lastdigit (+ slash groupw sizew))
- (datestart (+ lastdigit 2))
- (namestart (+ datestart datew))
- (multibyte (or (multibyte-string-p name)
- (multibyte-string-p link-name)))
- ;; If multibyte, we can't use optimized method of aset,
- ;; instead we must use concat.
- (string (make-string (if multibyte
- namestart
- (+ namestart
- (length name)
- (if link-p (+ 5 (length link-name)) 0)))
- 32))
- (type (tar-header-link-type tar-hblock)))
- (aset string 0 (if mod-p ?* ? ))
- (aset string 1
+ (type (tar-header-link-type tar-hblock))
+ (link-name (tar-header-link-name tar-hblock)))
+ (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 3) ?c) ; char special
- ((eq type 4) ?b) ; block special
- ((eq type 5) ?d) ; directory
- ((eq type 6) ?p) ; FIFO/pipe
- ((eq type 20) ?*) ; directory listing
- ((eq type 29) ?M) ; multivolume continuation
- ((eq type 35) ?S) ; sparse
- ((eq type 38) ?V) ; volume header
- ))
- (tar-grind-file-mode mode string 2)
- (setq uid (if (= 0 (length uname)) (int-to-string uid) uname))
- (setq gid (if (= 0 (length gname)) (int-to-string gid) gname))
- (setq size (int-to-string size))
- (setq time (tar-clip-time-string time))
- (tar-dotimes (i (min (1- namew) (length uid))) (aset string (- slash i) (aref uid (- (length uid) i 1))))
- (aset string (1+ slash) ?/)
- (tar-dotimes (i (min (1- groupw) (length gid))) (aset string (+ (+ slash 2) i) (aref gid i)))
- (tar-dotimes (i (min sizew (length size))) (aset string (- lastdigit i) (aref size (- (length size) i 1))))
- (if tar-mode-show-date
- (tar-dotimes (i (length time)) (aset string (+ datestart i) (aref time i))))
- (if multibyte
- (setq string (concat string name))
- (tar-dotimes (i (length name)) (aset string (+ namestart i) (aref name i))))
- (if (or (eq link-p 1) (eq link-p 2))
- (if multibyte
- (setq string (concat string
- (if (= link-p 1) " ==> " " --> ")
- link-name))
- (tar-dotimes (i 3) (aset string (+ namestart 1 (length name) i) (aref (if (= link-p 1) "==>" "-->") i)))
- (tar-dotimes (i (length link-name)) (aset string (+ namestart 5 (length name) i) (aref link-name i)))))
- (put-text-property namestart (length string)
- 'mouse-face 'highlight string)
- string)))
-
+ ((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
+ ((eq type 6) ?p) ; FIFO/pipe
+ ((eq type 20) ?*) ; directory listing
+ ((eq type 28) ?L) ; next has longname
+ ((eq type 29) ?M) ; multivolume continuation
+ ((eq type 35) ?S) ; sparse
+ ((eq type 38) ?V) ; volume header
+ (t ?\ )
+ )
+ (tar-grind-file-mode mode)
+ (if (= 0 (length uname)) uid uname)
+ (if (= 0 (length gname)) gid gname)
+ size
+ (if tar-mode-show-date (tar-clip-time-string time) "")
+ (propertize name
+ 'mouse-face 'highlight
+ 'help-echo "mouse-2: extract this file into a buffer")
+ (if (or (eq type 1) (eq type 2))
+ (concat (if (= type 1) " ==> " " --> ") link-name)
+ ""))))
+
+(defun tar-untar-buffer ()
+ "Extract all archive members in the tar-file into the current directory."
+ (interactive)
+ (let ((multibyte enable-multibyte-characters))
+ (unwind-protect
+ (save-restriction
+ (widen)
+ (set-buffer-multibyte nil)
+ (dolist (descriptor tar-parse-info)
+ (let* ((tokens (tar-desc-tokens descriptor))
+ (name (tar-header-name tokens))
+ (dir (file-name-directory name))
+ (start (+ (tar-desc-data-start descriptor)
+ (- tar-header-offset (point-min))))
+ (end (+ start (tar-header-size tokens))))
+ (unless (file-directory-p name)
+ (message "Extracting %s" name)
+ (if (and dir (not (file-exists-p dir)))
+ (make-directory dir t))
+ (unless (file-directory-p name)
+ (write-region start end name))
+ (set-file-modes name (tar-header-mode tokens))))))
+ (set-buffer-multibyte multibyte))))
(defun tar-summarize-buffer ()
"Parse the contents of the tar file in the current buffer.
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 1)
- (bs (max 1 (- (buffer-size) 1024))) ; always 2+ empty blocks at end.
- (bs100 (max 1 (/ bs 100)))
+ (pos (point-min))
+ (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))
(summaries nil))
;; Collect summary lines and insert them all at once since tar files
;; can be pretty big.
- (tar-dolist (tar-desc (reverse tar-parse-info))
+ (dolist (tar-desc (reverse tar-parse-info))
(setq summaries
(cons (tar-header-block-summarize (tar-desc-tokens tar-desc))
(cons "\n"
(insert total-summaries))
(make-local-variable 'tar-header-offset)
(setq tar-header-offset (point))
- (narrow-to-region 1 tar-header-offset)
+ (narrow-to-region (point-min) tar-header-offset)
(if enable-multibyte-characters
(setq tar-header-offset (position-bytes tar-header-offset)))
(set-buffer-modified-p nil))))
(define-key tar-mode-map [down] 'tar-next-line)
(define-key tar-mode-map "o" 'tar-extract-other-window)
(define-key tar-mode-map "p" 'tar-previous-line)
- (define-key tar-mode-map "q" 'tar-quit)
+ (define-key tar-mode-map "q" 'quit-window)
(define-key tar-mode-map "\^P" 'tar-previous-line)
(define-key tar-mode-map [up] 'tar-previous-line)
(define-key tar-mode-map "R" 'tar-rename-entry)
(put 'tar-subfile-mode 'mode-class 'special)
;;;###autoload
-(defun tar-mode ()
+(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'.
;; mode on and off. You can corrupt things that way.
;; rms: with permanent locals, it should now be possible to make this work
;; interactively in some reasonable fashion.
- (kill-all-local-variables)
(make-local-variable 'tar-header-offset)
(make-local-variable 'tar-parse-info)
- (make-local-variable 'require-final-newline)
- (setq require-final-newline nil) ; binary data, dude...
- (make-local-variable 'revert-buffer-function)
- (setq revert-buffer-function 'tar-mode-revert)
- (make-local-variable 'local-enable-local-variables)
- (setq local-enable-local-variables nil)
- (make-local-variable 'next-line-add-newlines)
- (setq next-line-add-newlines nil)
+ (set (make-local-variable 'require-final-newline) nil) ; binary data, dude...
+ (set (make-local-variable 'revert-buffer-function) 'tar-mode-revert)
+ (set (make-local-variable 'local-enable-local-variables) nil)
+ (set (make-local-variable 'next-line-add-newlines) nil)
;; Prevent loss of data when saving the file.
- (make-local-variable 'file-precious-flag)
- (setq file-precious-flag t)
- (setq major-mode 'tar-mode)
- (setq mode-name "Tar")
- (use-local-map tar-mode-map)
+ (set (make-local-variable 'file-precious-flag) t)
(auto-save-mode 0)
- (make-local-variable 'write-contents-hooks)
- (setq write-contents-hooks '(tar-mode-write-file))
+ (set (make-local-variable 'write-contents-functions) '(tar-mode-write-file))
(widen)
(if (and (boundp 'tar-header-offset) tar-header-offset)
- (narrow-to-region 1 (byte-to-position tar-header-offset))
- (tar-summarize-buffer)
- (tar-next-line 0))
- (run-hooks 'tar-mode-hook)
- )
+ (narrow-to-region (point-min) (byte-to-position tar-header-offset))
+ (tar-summarize-buffer)
+ (tar-next-line 0)))
(defun tar-subfile-mode (p)
(interactive "P")
(or (and (boundp 'tar-superior-buffer) tar-superior-buffer)
(error "This buffer is not an element of a tar file"))
-;;; Don't do this, because it is redundant and wastes mode line space.
-;;; (or (assq 'tar-subfile-mode minor-mode-alist)
-;;; (setq minor-mode-alist (append minor-mode-alist
-;;; (list '(tar-subfile-mode " TarFile")))))
+ ;; Don't do this, because it is redundant and wastes mode line space.
+ ;; (or (assq 'tar-subfile-mode minor-mode-alist)
+ ;; (setq minor-mode-alist (append minor-mode-alist
+ ;; (list '(tar-subfile-mode " TarFile")))))
(make-local-variable 'tar-subfile-mode)
(setq tar-subfile-mode
(if (null p)
(not tar-subfile-mode)
(> (prefix-numeric-value p) 0)))
(cond (tar-subfile-mode
- (make-local-variable 'local-write-file-hooks)
- (setq local-write-file-hooks '(tar-subfile-save-buffer))
+ (add-hook 'write-file-functions 'tar-subfile-save-buffer nil t)
;; turn off auto-save.
(auto-save-mode -1)
(setq buffer-auto-save-file-name nil)
(run-hooks 'tar-subfile-mode-hook))
(t
- (kill-local-variable 'local-write-file-hooks))))
+ (remove-hook 'write-file-functions 'tar-subfile-save-buffer t))))
;; Revert the buffer and recompute the dired-like listing.
(setq tar-header-offset old-offset)))))
-(defun tar-next-line (p)
+(defun tar-next-line (arg)
+ "Move cursor vertically down ARG lines and to the start of the filename."
(interactive "p")
- (forward-line p)
+ (forward-line arg)
(if (eobp) nil (forward-char (if tar-mode-show-date 54 36))))
-(defun tar-previous-line (p)
+(defun tar-previous-line (arg)
+ "Move cursor vertically up ARG lines and to the start of the filename."
(interactive "p")
- (tar-next-line (- p)))
+ (tar-next-line (- arg)))
(defun tar-current-descriptor (&optional noerror)
"Return the tar-descriptor of the current line, or signals an error."
(error "This is a %s, not a real file"
(cond ((eq link-p 5) "directory")
((eq link-p 20) "tar directory header")
+ ((eq link-p 28) "next has longname")
((eq link-p 29) "multivolume-continuation")
((eq link-p 35) "sparse entry")
((eq link-p 38) "volume header")
(tokens (tar-desc-tokens descriptor))
(name (tar-header-name tokens))
(size (tar-header-size tokens))
- (start (+ (tar-desc-data-start descriptor) tar-header-offset -1))
+ (start (+ (tar-desc-data-start descriptor)
+ (- tar-header-offset (point-min))))
(end (+ start size)))
(let* ((tar-buffer (current-buffer))
(tar-buffer-multibyte enable-multibyte-characters)
- (tarname (file-name-nondirectory (buffer-file-name)))
+ (tarname (buffer-name))
(bufname (concat (file-name-nondirectory name)
" ("
- tarname
- ")"))
+ tarname
+ ")"))
(read-only-p (or buffer-read-only view-p))
- (buffer (get-buffer bufname))
+ (new-buffer-file-name (expand-file-name
+ ;; `:' is not allowed on Windows
+ (concat tarname "!" name)))
+ (buffer (get-file-buffer new-buffer-file-name))
(just-created nil))
- (if buffer
- nil
- (setq buffer (get-buffer-create bufname))
+ (unless buffer
+ (setq buffer (generate-new-buffer bufname))
+ (setq bufname (buffer-name buffer))
(setq just-created t)
(unwind-protect
(progn
(insert-buffer-substring tar-buffer start end)
(set-buffer-multibyte t))
(insert-buffer-substring tar-buffer start end))
- (goto-char 0)
- (setq buffer-file-name
- ;; `:' is not allowed on Windows
- (expand-file-name (concat tarname "!" name)))
+ (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
- (and set-auto-coding-function
- (save-excursion
- (funcall set-auto-coding-function
- name (point-max)))))
+ (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
- 1 (min 16384 (point-max)) t)))
+ (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 1 (point-max) coding)
+ (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.
+ ;; superior buffer.
(setq default-directory
(save-excursion
(set-buffer tar-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)
+ (setq buffer-read-only read-only-p)
(set-buffer-modified-p nil)
(tar-subfile-mode 1))
(set-buffer tar-buffer))
- (narrow-to-region 1 tar-header-offset)
+ (narrow-to-region (point-min) tar-header-offset)
(set-buffer-multibyte tar-buffer-multibyte)))
(if view-p
(view-buffer buffer (and just-created 'kill-buffer))
(tokens (tar-desc-tokens descriptor))
(name (tar-header-name tokens))
(size (tar-header-size tokens))
- (start (+ (tar-desc-data-start descriptor) tar-header-offset -1))
+ (start (+ (tar-desc-data-start descriptor)
+ (- tar-header-offset (point-min))))
(end (+ start size))
(multibyte enable-multibyte-characters)
(inhibit-file-name-handlers inhibit-file-name-handlers)
(unwind-protect
(let ((coding-system-for-write 'no-conversion))
(set-buffer-multibyte nil)
- (write-region start end to-file))
+ (write-region start end to-file nil nil nil t))
(set-buffer-multibyte multibyte)))
(message "Copied tar entry %s to %s" name to-file)))
With a prefix argument, mark that many files."
(interactive "p")
(beginning-of-line)
- (tar-dotimes (i (if (< p 0) (- p) p))
+ (dotimes (i (if (< p 0) (- p) p))
(if (tar-current-descriptor unflag) ; barf if we're not on an entry-line.
(progn
(delete-char 1)
;; iteration over the files that remain, or only iterate up to
;; the next file to be deleted.
(let ((data-length (- data-end data-start)))
- (tar-dolist (desc following-descs)
+ (dolist (desc following-descs)
(tar-setf (tar-desc-data-start desc)
(- (tar-desc-data-start desc) data-length))))
))
- (narrow-to-region 1 tar-header-offset))
+ (narrow-to-region (point-min) tar-header-offset))
(defun tar-expunge (&optional noconfirm)
(multibyte enable-multibyte-characters))
(set-buffer-multibyte nil)
(save-excursion
- (goto-char 0)
+ (goto-char (point-min))
(while (not (eobp))
(if (looking-at "D")
(progn (tar-expunge-internal)
(forward-line 1)))
;; after doing the deletions, add any padding that may be necessary.
(tar-pad-to-blocksize)
- (narrow-to-region 1 tar-header-offset))
+ (narrow-to-region (point-min) tar-header-offset))
(set-buffer-multibyte multibyte)
(if (zerop n)
(message "Nothing to expunge.")
"Remove the stars at the beginning of each line."
(interactive)
(save-excursion
- (goto-char 1)
+ (goto-char (point-min))
(while (< (position-bytes (point)) tar-header-offset)
(if (not (eq (following-char) ?\ ))
(progn (delete-char 1) (insert " ")))
(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)))
(buffer-substring start (+ start 512))
chk (tar-header-name tokens))
)))
- (narrow-to-region 1 tar-header-offset)
+ (narrow-to-region (point-min) tar-header-offset)
(set-buffer-multibyte multibyte)
(tar-next-line 0))))
(defun tar-octal-time (timeval)
;; Format a timestamp as 11 octal digits. Ghod, I hope this works...
(let ((hibits (car timeval)) (lobits (car (cdr timeval))))
- (insert (format "%05o%01o%05o"
- (lsh hibits -2)
- (logior (lsh (logand 3 hibits) 1) (> (logand lobits 32768) 0))
- (logand 32767 lobits)
- ))))
+ (format "%05o%01o%05o"
+ (lsh hibits -2)
+ (logior (lsh (logand 3 hibits) 1)
+ (if (> (logand lobits 32768) 0) 1 0))
+ (logand 32767 lobits)
+ )))
(defun tar-subfile-save-buffer ()
"In tar subfile mode, save this buffer into its parent tar-file buffer.
(widen)
(set-buffer-multibyte nil)
;; delete the old data...
- (let* ((data-start (+ start tar-header-offset -1))
+ (let* ((data-start (+ start (- tar-header-offset (point-min))))
(data-end (+ data-start (ash (ash (+ size 511) -9) 9))))
(delete-region data-start data-end)
;; insert the new data...
;; update the data pointer of this and all following files...
(tar-setf (tar-header-size tokens) subfile-size)
(let ((difference (- subfile-size-pad size-pad)))
- (tar-dolist (desc following-descs)
+ (dolist (desc following-descs)
(tar-setf (tar-desc-data-start desc)
(+ (tar-desc-data-start desc) difference))))
;;
;; alter the descriptor-line...
;;
(let ((position (- (length tar-parse-info) (length head))))
- (goto-char 1)
+ (goto-char (point-min))
(next-line position)
(beginning-of-line)
(let ((p (point))
)))
;; after doing the insertion, add any final padding that may be necessary.
(tar-pad-to-blocksize))
- (narrow-to-region 1 tar-header-offset)
+ (narrow-to-region (point-min) tar-header-offset)
(set-buffer-multibyte tar-buffer-multibyte)))
(set-buffer-modified-p t) ; mark the tar file as modified
(tar-next-line 0)
;; tar-header-offset turns out to be null for files fetched with W3,
;; at least.
(let ((coding-system-for-write 'no-conversion))
- (write-region (or (byte-to-position tar-header-offset)
- (point-min))
+ (write-region (if tar-header-offset
+ (byte-to-position tar-header-offset)
+ (point-min))
(point-max)
buffer-file-name nil t))
(tar-clear-modification-flags)
(set-buffer-modified-p nil))
- (narrow-to-region 1 (byte-to-position tar-header-offset)))
- ;; return T because we've written the file.
+ (narrow-to-region (point-min) (byte-to-position tar-header-offset)))
+ ;; Return t because we've written the file.
t)
-
-(defun tar-quit ()
- "Kill the current tar buffer."
- (interactive)
- (kill-buffer nil))
-
\f
(provide 'tar-mode)
+;;; arch-tag: 8a585a4a-340e-42c2-89e7-d3b1013a4b78
;;; tar-mode.el ends here