comparison lisp/tar-mode.el @ 90261:7beb78bc1f8e

Revision: miles@gnu.org--gnu-2005/emacs--unicode--0--patch-97 Merge from emacs--cvs-trunk--0 Patches applied: * emacs--cvs-trunk--0 (patch 616-696) - Add lisp/mh-e/.arch-inventory - Update from CVS - Merge from gnus--rel--5.10 - Update from CVS: lisp/smerge-mode.el: Add 'tools' to file keywords. - lisp/gnus/ChangeLog: Remove duplicate entry * gnus--rel--5.10 (patch 147-181) - Update from CVS - Merge from emacs--cvs-trunk--0 - Update from CVS: lisp/mml.el (mml-preview): Doc fix. - Update from CVS: texi/message.texi: Fix default values. - Update from CVS: texi/gnus.texi (RSS): Addition.
author Miles Bader <miles@gnu.org>
date Mon, 16 Jan 2006 08:37:27 +0000
parents 2d92f5c9d6ae baa95d93b4e0
children 9970a9645ad9
comparison
equal deleted inserted replaced
90260:0ca0d9181b5e 90261:7beb78bc1f8e
99 "Simple editing of tar files." 99 "Simple editing of tar files."
100 :prefix "tar-" 100 :prefix "tar-"
101 :group 'data) 101 :group 'data)
102 102
103 (defcustom tar-anal-blocksize 20 103 (defcustom tar-anal-blocksize 20
104 "*The blocksize of tar files written by Emacs, or nil, meaning don't care. 104 "The blocksize of tar files written by Emacs, or nil, meaning don't care.
105 The blocksize of a tar file is not really the size of the blocks; rather, it is 105 The blocksize of a tar file is not really the size of the blocks; rather, it is
106 the number of blocks written with one system call. When tarring to a tape, 106 the number of blocks written with one system call. When tarring to a tape,
107 this is the size of the *tape* blocks, but when writing to a file, it doesn't 107 this is the size of the *tape* blocks, but when writing to a file, it doesn't
108 matter much. The only noticeable difference is that if a tar file does not 108 matter much. The only noticeable difference is that if a tar file does not
109 have a blocksize of 20, tar will tell you that; all this really controls is 109 have a blocksize of 20, tar will tell you that; all this really controls is
110 how many null padding bytes go on the end of the tar file." 110 how many null padding bytes go on the end of the tar file."
111 :type '(choice integer (const nil)) 111 :type '(choice integer (const nil))
112 :group 'tar) 112 :group 'tar)
113 113
114 (defcustom tar-update-datestamp nil 114 (defcustom tar-update-datestamp nil
115 "*Non-nil means Tar mode should play fast and loose with sub-file datestamps. 115 "Non-nil means Tar mode should play fast and loose with sub-file datestamps.
116 If this is true, then editing and saving a tar file entry back into its 116 If this is true, then editing and saving a tar file entry back into its
117 tar file will update its datestamp. If false, the datestamp is unchanged. 117 tar file will update its datestamp. If false, the datestamp is unchanged.
118 You may or may not want this - it is good in that you can tell when a file 118 You may or may not want this - it is good in that you can tell when a file
119 in a tar archive has been changed, but it is bad for the same reason that 119 in a tar archive has been changed, but it is bad for the same reason that
120 editing a file in the tar archive at all is bad - the changed version of 120 editing a file in the tar archive at all is bad - the changed version of
121 the file never exists on disk." 121 the file never exists on disk."
122 :type 'boolean 122 :type 'boolean
123 :group 'tar) 123 :group 'tar)
124 124
125 (defcustom tar-mode-show-date nil 125 (defcustom tar-mode-show-date nil
126 "*Non-nil means Tar mode should show the date/time of each subfile. 126 "Non-nil means Tar mode should show the date/time of each subfile.
127 This information is useful, but it takes screen space away from file names." 127 This information is useful, but it takes screen space away from file names."
128 :type 'boolean 128 :type 'boolean
129 :group 'tar) 129 :group 'tar)
130 130
131 (defvar tar-parse-info nil) 131 (defvar tar-parse-info nil)
283 lo (logand lo 65535))) 283 lo (logand lo 65535)))
284 (setq start (1+ start))) 284 (setq start (1+ start)))
285 (list hi lo)))) 285 (list hi lo))))
286 286
287 (defun tar-parse-octal-integer-safe (string) 287 (defun tar-parse-octal-integer-safe (string)
288 (let ((L (length string))) 288 (if (zerop (length string)) (error "empty string"))
289 (if (= L 0) (error "empty string")) 289 (mapc (lambda (c)
290 (dotimes (i L) 290 (if (or (< c ?0) (> c ?7))
291 (if (or (< (aref string i) ?0) 291 (error "`%c' is not an octal digit" c)))
292 (> (aref string i) ?7)) 292 string)
293 (error "`%c' is not an octal digit" (aref string i)))))
294 (tar-parse-octal-integer string)) 293 (tar-parse-octal-integer string))
295 294
296 295
297 (defun tar-header-block-checksum (string) 296 (defun tar-header-block-checksum (string)
298 "Compute and return a tar-acceptable checksum for this block." 297 "Compute and return a tar-acceptable checksum for this block."
343 (gid (tar-header-gid tar-hblock)) 342 (gid (tar-header-gid tar-hblock))
344 (uname (tar-header-uname tar-hblock)) 343 (uname (tar-header-uname tar-hblock))
345 (gname (tar-header-gname tar-hblock)) 344 (gname (tar-header-gname tar-hblock))
346 (size (tar-header-size tar-hblock)) 345 (size (tar-header-size tar-hblock))
347 (time (tar-header-date tar-hblock)) 346 (time (tar-header-date tar-hblock))
348 (ck (tar-header-checksum tar-hblock)) 347 ;; (ck (tar-header-checksum tar-hblock))
349 (type (tar-header-link-type tar-hblock)) 348 (type (tar-header-link-type tar-hblock))
350 (link-name (tar-header-link-name tar-hblock))) 349 (link-name (tar-header-link-name tar-hblock)))
351 (format "%c%c%s%8s/%-8s%7s%s %s%s" 350 (format "%c%c%s%8s/%-8s%7s%s %s%s"
352 (if mod-p ?* ? ) 351 (if mod-p ?* ? )
353 (cond ((or (eq type nil) (eq type 0)) ?-) 352 (cond ((or (eq type nil) (eq type 0)) ?-)
555 Type `e' to pull a file out of the tar file and into its own buffer; 554 Type `e' to pull a file out of the tar file and into its own buffer;
556 or click mouse-2 on the file's line in the Tar mode buffer. 555 or click mouse-2 on the file's line in the Tar mode buffer.
557 Type `c' to copy an entry from the tar file into another file on disk. 556 Type `c' to copy an entry from the tar file into another file on disk.
558 557
559 If you edit a sub-file of this archive (as with the `e' command) and 558 If you edit a sub-file of this archive (as with the `e' command) and
560 save it with Control-x Control-s, the contents of that buffer will be 559 save it with \\[save-buffer], the contents of that buffer will be
561 saved back into the tar-file buffer; in this way you can edit a file 560 saved back into the tar-file buffer; in this way you can edit a file
562 inside of a tar archive without extracting it and re-archiving it. 561 inside of a tar archive without extracting it and re-archiving it.
563 562
564 See also: variables `tar-update-datestamp' and `tar-anal-blocksize'. 563 See also: variables `tar-update-datestamp' and `tar-anal-blocksize'.
565 \\{tar-mode-map}" 564 \\{tar-mode-map}"
769 (switch-to-buffer-other-window buffer) 768 (switch-to-buffer-other-window buffer)
770 (switch-to-buffer buffer))))))) 769 (switch-to-buffer buffer)))))))
771 770
772 771
773 (defun tar-extract-other-window () 772 (defun tar-extract-other-window ()
774 "*In Tar mode, find this entry of the tar file in another window." 773 "In Tar mode, find this entry of the tar file in another window."
775 (interactive) 774 (interactive)
776 (tar-extract t)) 775 (tar-extract t))
777 776
778 (defun tar-display-other-window () 777 (defun tar-display-other-window ()
779 "*In Tar mode, display this entry of the tar file in another window." 778 "In Tar mode, display this entry of the tar file in another window."
780 (interactive) 779 (interactive)
781 (tar-extract 'display)) 780 (tar-extract 'display))
782 781
783 (defun tar-view () 782 (defun tar-view ()
784 "*In Tar mode, view the tar file entry on this line." 783 "In Tar mode, view the tar file entry on this line."
785 (interactive) 784 (interactive)
786 (tar-extract 'view)) 785 (tar-extract 'view))
787 786
788 787
789 (defun tar-read-file-name (&optional prompt) 788 (defun tar-read-file-name (&optional prompt)
805 (file-name-nondirectory default-file)))) 804 (file-name-nondirectory default-file))))
806 target)) 805 target))
807 806
808 807
809 (defun tar-copy (&optional to-file) 808 (defun tar-copy (&optional to-file)
810 "*In Tar mode, extract this entry of the tar file into a file on disk. 809 "In Tar mode, extract this entry of the tar file into a file on disk.
811 If TO-FILE is not supplied, it is prompted for, defaulting to the name of 810 If TO-FILE is not supplied, it is prompted for, defaulting to the name of
812 the current tar-entry." 811 the current tar-entry."
813 (interactive (list (tar-read-file-name))) 812 (interactive (list (tar-read-file-name)))
814 (let* ((descriptor (tar-get-descriptor)) 813 (let* ((descriptor (tar-get-descriptor))
815 (tokens (tar-desc-tokens descriptor)) 814 (tokens (tar-desc-tokens descriptor))
834 (let ((coding-system-for-write 'no-conversion)) 833 (let ((coding-system-for-write 'no-conversion))
835 (write-region start end to-file nil nil nil t))) 834 (write-region start end to-file nil nil nil t)))
836 (message "Copied tar entry %s to %s" name to-file))) 835 (message "Copied tar entry %s to %s" name to-file)))
837 836
838 (defun tar-flag-deleted (p &optional unflag) 837 (defun tar-flag-deleted (p &optional unflag)
839 "*In Tar mode, mark this sub-file to be deleted from the tar file. 838 "In Tar mode, mark this sub-file to be deleted from the tar file.
840 With a prefix argument, mark that many files." 839 With a prefix argument, mark that many files."
841 (interactive "p") 840 (interactive "p")
842 (beginning-of-line) 841 (beginning-of-line)
843 (dotimes (i (if (< p 0) (- p) p)) 842 (dotimes (i (abs p))
844 (if (tar-current-descriptor unflag) ; barf if we're not on an entry-line. 843 (if (tar-current-descriptor unflag) ; barf if we're not on an entry-line.
845 (progn 844 (progn
846 (delete-char 1) 845 (delete-char 1)
847 (insert (if unflag " " "D")))) 846 (insert (if unflag " " "D"))))
848 (forward-line (if (< p 0) -1 1))) 847 (forward-line (if (< p 0) -1 1)))
849 (if (eobp) nil (forward-char 36))) 848 (if (eobp) nil (forward-char 36)))
850 849
851 (defun tar-unflag (p) 850 (defun tar-unflag (p)
852 "*In Tar mode, un-mark this sub-file if it is marked to be deleted. 851 "In Tar mode, un-mark this sub-file if it is marked to be deleted.
853 With a prefix argument, un-mark that many files forward." 852 With a prefix argument, un-mark that many files forward."
854 (interactive "p") 853 (interactive "p")
855 (tar-flag-deleted p t)) 854 (tar-flag-deleted p t))
856 855
857 (defun tar-unflag-backwards (p) 856 (defun tar-unflag-backwards (p)
858 "*In Tar mode, un-mark this sub-file if it is marked to be deleted. 857 "In Tar mode, un-mark this sub-file if it is marked to be deleted.
859 With a prefix argument, un-mark that many files backward." 858 With a prefix argument, un-mark that many files backward."
860 (interactive "p") 859 (interactive "p")
861 (tar-flag-deleted (- p) t)) 860 (tar-flag-deleted (- p) t))
862 861
863 862
864 (defun tar-expunge-internal () 863 (defun tar-expunge-internal ()
865 "Expunge the tar-entry specified by the current line." 864 "Expunge the tar-entry specified by the current line."
866 (let* ((descriptor (tar-current-descriptor)) 865 (let* ((descriptor (tar-current-descriptor))
867 (tokens (tar-desc-tokens descriptor)) 866 (tokens (tar-desc-tokens descriptor))
868 (line (tar-desc-data-start descriptor)) 867 ;; (line (tar-desc-data-start descriptor))
869 (name (tar-header-name tokens)) 868 (name (tar-header-name tokens))
870 (size (tar-header-size tokens)) 869 (size (tar-header-size tokens))
871 (link-p (tar-header-link-type tokens)) 870 (link-p (tar-header-link-type tokens))
872 (start (tar-desc-data-start descriptor)) 871 (start (tar-desc-data-start descriptor))
873 (following-descs (cdr (memq descriptor tar-parse-info)))) 872 (following-descs (cdr (memq descriptor tar-parse-info))))
875 ;; 874 ;;
876 ;; delete the current line... 875 ;; delete the current line...
877 (beginning-of-line) 876 (beginning-of-line)
878 (let ((line-start (point))) 877 (let ((line-start (point)))
879 (end-of-line) (forward-char) 878 (end-of-line) (forward-char)
880 (let ((line-len (- (point) line-start))) 879 ;; decrement the header-pointer to be in sync...
881 (delete-region line-start (point)) 880 (setq tar-header-offset (- tar-header-offset (- (point) line-start)))
882 ;; 881 (delete-region line-start (point)))
883 ;; decrement the header-pointer to be in sync...
884 (setq tar-header-offset (- tar-header-offset line-len))))
885 ;; 882 ;;
886 ;; delete the data pointer... 883 ;; delete the data pointer...
887 (setq tar-parse-info (delq descriptor tar-parse-info)) 884 (setq tar-parse-info (delq descriptor tar-parse-info))
888 ;; 885 ;;
889 ;; delete the data from inside the file... 886 ;; delete the data from inside the file...
890 (widen) 887 (widen)
891 (let* ((data-start (+ start tar-header-offset -513)) 888 (let* ((data-start (+ start (- tar-header-offset (point-min)) -512))
892 (data-end (+ data-start 512 (ash (ash (+ size 511) -9) 9)))) 889 (data-end (+ data-start 512 (ash (ash (+ size 511) -9) 9))))
893 (delete-region data-start data-end) 890 (delete-region data-start data-end)
894 ;; 891 ;;
895 ;; and finally, decrement the start-pointers of all following 892 ;; and finally, decrement the start-pointers of all following
896 ;; entries in the archive. This is a pig when deleting a bunch 893 ;; entries in the archive. This is a pig when deleting a bunch
904 )) 901 ))
905 (narrow-to-region (point-min) tar-header-offset)) 902 (narrow-to-region (point-min) tar-header-offset))
906 903
907 904
908 (defun tar-expunge (&optional noconfirm) 905 (defun tar-expunge (&optional noconfirm)
909 "*In Tar mode, delete all the archived files flagged for deletion. 906 "In Tar mode, delete all the archived files flagged for deletion.
910 This does not modify the disk image; you must save the tar file itself 907 This does not modify the disk image; you must save the tar file itself
911 for this to be permanent." 908 for this to be permanent."
912 (interactive) 909 (interactive)
913 (if (or noconfirm 910 (if (or noconfirm
914 (y-or-n-p "Expunge files marked for deletion? ")) 911 (y-or-n-p "Expunge files marked for deletion? "))
938 (progn (delete-char 1) (insert " "))) 935 (progn (delete-char 1) (insert " ")))
939 (forward-line 1)))) 936 (forward-line 1))))
940 937
941 938
942 (defun tar-chown-entry (new-uid) 939 (defun tar-chown-entry (new-uid)
943 "*Change the user-id associated with this entry in the tar file. 940 "Change the user-id associated with this entry in the tar file.
944 If this tar file was written by GNU tar, then you will be able to edit 941 If this tar file was written by GNU tar, then you will be able to edit
945 the user id as a string; otherwise, you must edit it as a number. 942 the user id as a string; otherwise, you must edit it as a number.
946 You can force editing as a number by calling this with a prefix arg. 943 You can force editing as a number by calling this with a prefix arg.
947 This does not modify the disk image; you must save the tar file itself 944 This does not modify the disk image; you must save the tar file itself
948 for this to be permanent." 945 for this to be permanent."
966 (tar-alter-one-field tar-uid-offset 963 (tar-alter-one-field tar-uid-offset
967 (concat (substring (format "%6o" new-uid) 0 6) "\000 "))))) 964 (concat (substring (format "%6o" new-uid) 0 6) "\000 ")))))
968 965
969 966
970 (defun tar-chgrp-entry (new-gid) 967 (defun tar-chgrp-entry (new-gid)
971 "*Change the group-id associated with this entry in the tar file. 968 "Change the group-id associated with this entry in the tar file.
972 If this tar file was written by GNU tar, then you will be able to edit 969 If this tar file was written by GNU tar, then you will be able to edit
973 the group id as a string; otherwise, you must edit it as a number. 970 the group id as a string; otherwise, you must edit it as a number.
974 You can force editing as a number by calling this with a prefix arg. 971 You can force editing as a number by calling this with a prefix arg.
975 This does not modify the disk image; you must save the tar file itself 972 This does not modify the disk image; you must save the tar file itself
976 for this to be permanent." 973 for this to be permanent."
994 new-gid) 991 new-gid)
995 (tar-alter-one-field tar-gid-offset 992 (tar-alter-one-field tar-gid-offset
996 (concat (substring (format "%6o" new-gid) 0 6) "\000 "))))) 993 (concat (substring (format "%6o" new-gid) 0 6) "\000 ")))))
997 994
998 (defun tar-rename-entry (new-name) 995 (defun tar-rename-entry (new-name)
999 "*Change the name associated with this entry in the tar file. 996 "Change the name associated with this entry in the tar file.
1000 This does not modify the disk image; you must save the tar file itself 997 This does not modify the disk image; you must save the tar file itself
1001 for this to be permanent." 998 for this to be permanent."
1002 (interactive 999 (interactive
1003 (list (read-string "New name: " 1000 (list (read-string "New name: "
1004 (tar-header-name (tar-desc-tokens (tar-current-descriptor)))))) 1001 (tar-header-name (tar-desc-tokens (tar-current-descriptor))))))
1204 (tokens (tar-desc-tokens last-desc)) 1201 (tokens (tar-desc-tokens last-desc))
1205 (link-p (tar-header-link-type tokens)) 1202 (link-p (tar-header-link-type tokens))
1206 (size (if link-p 0 (tar-header-size tokens))) 1203 (size (if link-p 0 (tar-header-size tokens)))
1207 (data-end (+ start size)) 1204 (data-end (+ start size))
1208 (bbytes (ash tar-anal-blocksize 9)) 1205 (bbytes (ash tar-anal-blocksize 9))
1209 (pad-to (+ bbytes (* bbytes (/ (1- data-end) bbytes)))) 1206 (pad-to (+ bbytes (* bbytes (/ (- data-end (point-min)) bbytes))))
1210 (inhibit-read-only t) ; ## 1207 (inhibit-read-only t) ; ##
1211 ) 1208 )
1212 ;; If the padding after the last data is too long, delete some; 1209 ;; If the padding after the last data is too long, delete some;
1213 ;; else insert some until we are padded out to the right number of blocks. 1210 ;; else insert some until we are padded out to the right number of blocks.
1214 ;; 1211 ;;
1215 (goto-char (+ (or tar-header-offset 0) data-end)) 1212 (let ((goal-end (+ (or tar-header-offset 0) pad-to)))
1216 (if (> (1+ (buffer-size)) (+ (or tar-header-offset 0) pad-to)) 1213 (if (> (point-max) goal-end)
1217 (delete-region (+ (or tar-header-offset 0) pad-to) (1+ (buffer-size))) 1214 (delete-region goal-end (point-max))
1218 (insert (make-string (- (+ (or tar-header-offset 0) pad-to) 1215 (goto-char (point-max))
1219 (1+ (buffer-size))) 1216 (insert (make-string (- goal-end (point-max)) ?\0)))))))
1220 0)))
1221 )))
1222 1217
1223 1218
1224 ;; Used in write-file-hook to write tar-files out correctly. 1219 ;; Used in write-file-hook to write tar-files out correctly.
1225 (defun tar-mode-write-file () 1220 (defun tar-mode-write-file ()
1226 (unwind-protect 1221 (unwind-protect
1242 ;; Return t because we've written the file. 1237 ;; Return t because we've written the file.
1243 t) 1238 t)
1244 1239
1245 (provide 'tar-mode) 1240 (provide 'tar-mode)
1246 1241
1247 ;;; arch-tag: 8a585a4a-340e-42c2-89e7-d3b1013a4b78 1242 ;; arch-tag: 8a585a4a-340e-42c2-89e7-d3b1013a4b78
1248 ;;; tar-mode.el ends here 1243 ;;; tar-mode.el ends here