;;; arc-mode.el --- simple editing of archives
-;; Copyright (C) 1995, 1997, 1998, 2003, 2005 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 1997, 1998, 2001, 2002, 2003, 2004,
+;; 2005, 2006 Free Software Foundation, Inc.
;; Author: Morten Welinder <terra@gnu.org>
;; Keywords: archives msdog editing major-mode
;; 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:
(make-temp-name
(expand-file-name (if (eq system-type 'ms-dos) "ar" "archive.tmp")
temporary-file-directory))
- "Directory for temporary files made by arc-mode.el."
+ "Directory for temporary files made by `arc-mode.el'."
:type 'directory
:group 'archive)
'("unzip" "-qq" "-c"))
"*Program and its options to run in order to extract a zip file member.
Extraction should happen to standard output. Archive and member name will
-be added. If `archive-zip-use-pkzip' is non-nil then this program is
-expected to extract to a file junking the directory part of the name."
+be added."
:type '(list (string :tag "Program")
(repeat :tag "Options"
:inline t
(defsubst archive-name (suffix)
(intern (concat "archive-" (symbol-name archive-subtype) "-" suffix)))
-(defun archive-l-e (str &optional len)
- "Convert little endian string/vector to integer.
-Alternatively, first argument may be a buffer position in the current buffer
-in which case a second argument, length, should be supplied."
+(defun archive-l-e (str &optional len float)
+ "Convert little endian string/vector STR to integer.
+Alternatively, STR may be a buffer position in the current buffer
+in which case a second argument, length LEN, should be supplied.
+FLOAT, if non-nil, means generate and return a float instead of an integer
+\(use this for numbers that can overflow the Emacs integer)."
(if (stringp str)
(setq len (length str))
(setq str (buffer-substring str (+ str len))))
(i 0))
(while (< i len)
(setq i (1+ i)
- result (+ (ash result 8) (aref str (- len i)))))
+ result (+ (if float (* result 256.0) (ash result 8))
+ (aref str (- len i)))))
result))
(defun archive-int-to-mode (mode)
(format "%02d:%02d:%02d" hour minute second)))
(defun archive-unixdate (low high)
- "Stringify unix (LOW HIGH) date."
+ "Stringify Unix (LOW HIGH) date."
(let ((str (current-time-string (cons high low))))
(format "%s-%s-%s"
(substring str 8 10)
(substring str 20 24))))
(defun archive-unixtime (low high)
- "Stringify unix (LOW HIGH) time."
+ "Stringify Unix (LOW HIGH) time."
(let ((str (current-time-string (cons high low))))
(substring str 11 19)))
(defun archive-get-descr (&optional noerror)
"Return the descriptor vector for file at point.
-Does not signal an error if optional second argument NOERROR is non-nil."
+Does not signal an error if optional argument NOERROR is non-nil."
(let ((no (archive-get-lineno)))
(if (and (>= (point) archive-file-list-start)
(< no (length archive-files)))
(defun archive-alternate-display ()
"Toggle alternative display.
-To avoid very long lines some archive mode don't show all information.
+To avoid very long lines archive mode does not show all information.
This function changes the set of information shown for each files."
(interactive)
(setq archive-alternate-display (not archive-alternate-display))
(archive-name
(or (and archive-subfile-mode (aref archive-subfile-mode 0))
archive)))
- (make-directory archive-tmpdir t)
- ;; If ARCHIVE includes leading directories, make sure they
- ;; exist under archive-tmpdir.
- (let ((arch-dir (file-name-directory archive)))
- (if arch-dir
- (make-directory (concat
- (file-name-as-directory archive-tmpdir)
- arch-dir)
- t)))
(setq archive-local-name
(archive-unique-fname archive-name archive-tmpdir))
+ ;; Maked sure all the leading directories in
+ ;; archive-local-name exist under archive-tmpdir, so that
+ ;; the directory structure recorded in the archive is
+ ;; reconstructed in the temporary directory.
+ (make-directory (file-name-directory archive-local-name) t)
(save-restriction
(widen)
(write-region start (point-max) archive-local-name nil 'nomessage))
"Set the current buffer as if it were visiting FILENAME."
(save-excursion
(goto-char (point-min))
- (let ((coding
+ (let ((buffer-undo-list t)
+ (coding
(or coding-system-for-read
(and set-auto-coding-function
(save-excursion
(funcall set-auto-coding-function
filename (- (point-max) (point-min)))))
- ;; dos-w32.el defines find-operation-coding-system for
- ;; DOS/Windows systems which preserves the coding-system
- ;; of existing files. We want it to act here as if the
- ;; extracted file existed.
+ ;; dos-w32.el defines the function
+ ;; find-buffer-file-type-coding-system for DOS/Windows
+ ;; systems which preserves the coding-system of existing files.
+ ;; (That function is called via file-coding-system-alist.)
+ ;; Here, we want it to act as if the extracted file existed.
+ ;; The following let-binding of file-name-handler-alist forces
+ ;; find-file-not-found-set-buffer-file-coding-system to ignore
+ ;; the file's name (see dos-w32.el).
(let ((file-name-handler-alist
'(("" . archive-file-name-handler))))
- (car (find-operation-coding-system 'insert-file-contents
- filename t))))))
+ (car (find-operation-coding-system
+ 'insert-file-contents
+ (cons filename (current-buffer)) t))))))
(if (and (not coding-system-for-read)
(not enable-multibyte-characters))
(setq coding
(defun archive-extract (&optional other-window-p event)
"In archive mode, extract this entry of the archive into its own buffer."
(interactive (list nil last-input-event))
- (if event (mouse-set-point event))
+ (if event (posn-set-point (event-end event)))
(let* ((view-p (eq other-window-p 'view))
(descr (archive-get-descr))
(ename (aref descr 0))
(read-only-p (or archive-read-only
view-p
(string-match file-name-invalid-regexp ename)))
+ (arcfilename (expand-file-name (concat arcname ":" iname)))
(buffer (get-buffer bufname))
(just-created nil))
- (if buffer
+ (if (and buffer
+ (string= (buffer-file-name buffer) arcfilename))
nil
(setq archive (archive-maybe-copy archive))
+ (setq bufname (generate-new-buffer-name bufname))
(setq buffer (get-buffer-create bufname))
(setq just-created t)
(with-current-buffer buffer
- (setq buffer-file-name
- (expand-file-name (concat arcname ":" iname)))
+ (setq buffer-file-name arcfilename)
(setq buffer-file-truename
(abbreviate-file-name buffer-file-name))
;; Set the default-directory to the dir of the superior buffer.
"In archive mode, un-mark this member if it is marked to be deleted.
With a prefix argument, un-mark that many files forward."
(interactive "p")
- (archive-flag-deleted p ? ))
+ (archive-flag-deleted p ?\s))
(defun archive-unflag-backwards (p)
"In archive mode, un-mark this member if it is marked to be deleted.
With a prefix argument, un-mark that many members backward."
(interactive "p")
- (archive-flag-deleted (- p) ? ))
+ (archive-flag-deleted (- p) ?\s))
(defun archive-unmark-all-files ()
"Remove all marks."
(save-excursion
(goto-char archive-file-list-start)
(while (< (point) archive-file-list-end)
- (or (= (following-char) ? )
- (progn (delete-char 1) (insert ? )))
+ (or (= (following-char) ?\s)
+ (progn (delete-char 1) (insert ?\s)))
(forward-line 1)))
(restore-buffer-modified-p modified)))
(defun archive-chmod-entry (new-mode)
"Change the protection bits associated with all marked or this member.
The new protection bits can either be specified as an octal number or
-as a relative change like \"g+rw\" as for chmod(2)"
+as a relative change like \"g+rw\" as for chmod(2)."
(interactive "sNew mode (octal or relative): ")
(if archive-read-only (error "Archive is read-only"))
(let ((func (archive-name "chmod-entry")))
(let* ((namefld (buffer-substring (+ p 2) (+ p 2 13)))
(fnlen (or (string-match "\0" namefld) 13))
(efnname (substring namefld 0 fnlen))
- (csize (archive-l-e (+ p 15) 4))
+ ;; Convert to float to avoid overflow for very large files.
+ (csize (archive-l-e (+ p 15) 4 'float))
(moddate (archive-l-e (+ p 19) 2))
(modtime (archive-l-e (+ p 21) 2))
- (ucsize (archive-l-e (+ p 25) 4))
+ (ucsize (archive-l-e (+ p 25) 4 'float))
(fiddle (string= efnname (upcase efnname)))
(ifnname (if fiddle (downcase efnname) efnname))
- (text (format " %8d %-11s %-8s %s"
+ (text (format " %8.0f %-11s %-8s %s"
ucsize
(archive-dosdate moddate)
(archive-dostime modtime)
visual)
files (cons (vector efnname ifnname fiddle nil (1- p))
files)
- p (+ p 29 csize))))
+ ;; p needs to stay an integer, since we use it in char-after
+ ;; above. Passing through `round' limits the compressed size
+ ;; to most-positive-fixnum, but if the compressed size exceeds
+ ;; that, we cannot visit the archive anyway.
+ p (+ p 29 (round csize)))))
(goto-char (point-min))
(let ((dash (concat "- -------- ----------- -------- "
(make-string maxlen ?-)
dash)
(archive-summarize-files (nreverse visual))
(insert dash
- (format " %8d %d file%s"
+ (format " %8.0f %d file%s"
totalsize
(length files)
(if (= 1 (length files)) "" "s"))
(while (progn (goto-char p) ;beginning of a base header.
(looking-at "\\(.\\|\n\\)\\(.\\|\n\\)-l[hz][0-9ds]-"))
(let* ((hsize (char-after p)) ;size of the base header (level 0 and 1)
- (csize (archive-l-e (+ p 7) 4)) ;size of a compressed file to follow (level 0 and 2),
+ ;; Convert to float to avoid overflow for very large files.
+ (csize (archive-l-e (+ p 7) 4 'float)) ;size of a compressed file to follow (level 0 and 2),
;size of extended headers + the compressed file to follow (level 1).
- (ucsize (archive-l-e (+ p 11) 4)) ;size of an uncompressed file.
+ (ucsize (archive-l-e (+ p 11) 4 'float)) ;size of an uncompressed file.
(time1 (archive-l-e (+ p 15) 2)) ;date/time (MSDOS format in level 0, 1 headers
(time2 (archive-l-e (+ p 17) 2)) ;and UNIX format in level 2 header.)
(hdrlvl (char-after (+ p 20))) ;header level
(archive-unixtime time1 time2)
(archive-dostime time1)))
(setq text (if archive-alternate-display
- (format " %8d %5S %5S %s"
+ (format " %8.0f %5S %5S %s"
ucsize
(or uid "?")
(or gid "?")
ifnname)
- (format " %10s %8d %-11s %-8s %s"
+ (format " %10s %8.0f %-11s %-8s %s"
modestr
ucsize
moddate
files (cons (vector prname ifnname fiddle mode (1- p))
files))
(cond ((= hdrlvl 1)
- (setq p (+ p hsize 2 csize)))
+ ;; p needs to stay an integer, since we use it in goto-char
+ ;; above. Passing through `round' limits the compressed size
+ ;; to most-positive-fixnum, but if the compressed size exceeds
+ ;; that, we cannot visit the archive anyway.
+ (setq p (+ p hsize 2 (round csize))))
((or (= hdrlvl 2) (= hdrlvl 0))
- (setq p (+ p thsize 2 csize))))
+ (setq p (+ p thsize 2 (round csize)))))
))
(goto-char (point-min))
(set-buffer-multibyte default-enable-multibyte-characters)
"M Length Uid Gid File\n"
"M Filemode Length Date Time File\n"))
(sumline (if archive-alternate-display
- " %8d %d file%s"
- " %8d %d file%s")))
+ " %8.0f %d file%s"
+ " %8.0f %d file%s")))
(insert header dash)
(archive-summarize-files (nreverse visual))
(insert dash
;; (method (archive-l-e (+ p 10) 2))
(modtime (archive-l-e (+ p 12) 2))
(moddate (archive-l-e (+ p 14) 2))
- (ucsize (archive-l-e (+ p 24) 4))
+ ;; Convert to float to avoid overflow for very large files.
+ (ucsize (archive-l-e (+ p 24) 4 'float))
(fnlen (archive-l-e (+ p 28) 2))
(exlen (archive-l-e (+ p 30) 2))
(fclen (archive-l-e (+ p 32) 2))
(string= (upcase efnname) efnname)))
(ifnname (if fiddle (downcase efnname) efnname))
(width (string-width ifnname))
- (text (format " %10s %8d %-11s %-8s %s"
+ (text (format " %10s %8.0f %-11s %-8s %s"
modestr
ucsize
(archive-dosdate moddate)
dash)
(archive-summarize-files (nreverse visual))
(insert dash
- (format " %8d %d file%s"
+ (format " %8.0f %d file%s"
totalsize
(length files)
(if (= 1 (length files)) "" "s"))
(let* ((next (1+ (archive-l-e (+ p 6) 4)))
(moddate (archive-l-e (+ p 14) 2))
(modtime (archive-l-e (+ p 16) 2))
- (ucsize (archive-l-e (+ p 20) 4))
+ ;; Convert to float to avoid overflow for very large files.
+ (ucsize (archive-l-e (+ p 20) 4 'float))
(namefld (buffer-substring (+ p 38) (+ p 38 13)))
(dirtype (char-after (+ p 4)))
(lfnlen (if (= dirtype 2) (char-after (+ p 56)) 0))
(fiddle (and (= lfnlen 0) (string= efnname (upcase efnname))))
(ifnname (if fiddle (downcase efnname) efnname))
(width (string-width ifnname))
- (text (format " %8d %-11s %-8s %s"
+ (text (format " %8.0f %-11s %-8s %s"
ucsize
(archive-dosdate moddate)
(archive-dostime modtime)
dash)
(archive-summarize-files (nreverse visual))
(insert dash
- (format " %8d %d file%s"
+ (format " %8.0f %d file%s"
totalsize
(length files)
(if (= 1 (length files)) "" "s"))