aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2020-04-03 16:45:54 -0400
committerStefan Monnier2020-04-03 16:45:54 -0400
commitc640be60d918d5a7be4d9d5e717cf159f878d38c (patch)
treead9ab7ec07f3b274f34bdab74aaae748976c397a
parent9b995320c853a45d785896fb25f788f9248658f4 (diff)
downloademacs-c640be60d918d5a7be4d9d5e717cf159f878d38c.tar.gz
emacs-c640be60d918d5a7be4d9d5e717cf159f878d38c.zip
* lisp/arc-mode.el: Use cl-structs rather than vectors
(archive--file-desc, archive--file-summary, archive-arc--file-desc) (archive-lzh--file-desc, archive-zip--file-desc) (archive-zoo--file-desc, archive-rar--file-desc) (archive-7z--file-desc, archive-ar--file-desc): New structs. (archive-get-descr, archive-mode, archive-summarize-files) (archive-maybe-copy, archive-extract, archive-*-write-file-member) (archive-expunge, archive-arc-summarize, archive-arc-rename-entry) (archive-lzh-summarize, archive-lzh-rename-entry, archive-lzh-ogm) (archive-zip-summarize, archive-zip-write-file-member) (archive-zip-chmod-entry, archive-zoo-summarize) (archive-rar-summarize, archive-7z-summarize, archive-ar-summarize) (archive-ar-write-file-member): Use struct constructors and accessors instead of `vector` and `aref`. (archive-calc-mode): Remove `error` arg which was always non-nil; adjust all callers. Rewrite using `string-to-number` and `file-modes-symbolic-to-number`.
-rw-r--r--lisp/arc-mode.el343
1 files changed, 196 insertions, 147 deletions
diff --git a/lisp/arc-mode.el b/lisp/arc-mode.el
index 21b9627e407..4609123dec9 100644
--- a/lisp/arc-mode.el
+++ b/lisp/arc-mode.el
@@ -366,7 +366,7 @@ file. Archive and member name will be added."
366(defvar archive-file-list-end nil "Position just after last contents line.") 366(defvar archive-file-list-end nil "Position just after last contents line.")
367(defvar archive-proper-file-start nil "Position of real archive's start.") 367(defvar archive-proper-file-start nil "Position of real archive's start.")
368(defvar archive-read-only nil "Non-nil if the archive is read-only on disk.") 368(defvar archive-read-only nil "Non-nil if the archive is read-only on disk.")
369(defvar archive-local-name nil "Name of local copy of remote archive.") 369(defvar-local archive-local-name nil "Name of local copy of remote archive.")
370(defvar archive-mode-map 370(defvar archive-mode-map
371 (let ((map (make-keymap))) 371 (let ((map (make-keymap)))
372 (set-keymap-parent map special-mode-map) 372 (set-keymap-parent map special-mode-map)
@@ -485,18 +485,23 @@ file. Archive and member name will be added."
485(defvar archive-superior-buffer nil "In archive members, points to archive.") 485(defvar archive-superior-buffer nil "In archive members, points to archive.")
486(put 'archive-superior-buffer 'permanent-local t) 486(put 'archive-superior-buffer 'permanent-local t)
487 487
488(defvar archive-subfile-mode nil "Non-nil in archive member buffers.") 488(defvar-local archive-subfile-mode nil
489(make-variable-buffer-local 'archive-subfile-mode) 489 "Non-nil in archive member buffers.
490Its value is an `archive--file-desc'.")
490(put 'archive-subfile-mode 'permanent-local t) 491(put 'archive-subfile-mode 'permanent-local t)
491 492
492(defvar archive-file-name-coding-system nil) 493(defvar archive-file-name-coding-system nil)
493(make-variable-buffer-local 'archive-file-name-coding-system) 494(make-variable-buffer-local 'archive-file-name-coding-system)
494(put 'archive-file-name-coding-system 'permanent-local t) 495(put 'archive-file-name-coding-system 'permanent-local t)
495 496
497(cl-defstruct (archive--file-desc
498 (:constructor nil)
499 (:constructor archive--file-desc
500 (ext-file-name int-file-name case-fiddled mode)))
501 ext-file-name int-file-name case-fiddled mode)
502
496(defvar archive-files nil 503(defvar archive-files nil
497 "Vector of file descriptors. 504 "Vector of `archive--file-desc' objects.")
498Each descriptor is a vector of the form
499 [EXT-FILE-NAME INT-FILE-NAME CASE-FIDDLED MODE ...]")
500(make-variable-buffer-local 'archive-files) 505(make-variable-buffer-local 'archive-files)
501 506
502;; ------------------------------------------------------------------------- 507;; -------------------------------------------------------------------------
@@ -550,52 +555,16 @@ in which case a second argument, length LEN, should be supplied."
550 (if (zerop (logand 2 mode)) ?- ?w) 555 (if (zerop (logand 2 mode)) ?- ?w)
551 (if (zerop (logand 1 mode)) ?- ?x))) 556 (if (zerop (logand 1 mode)) ?- ?x)))
552 557
553(defun archive-calc-mode (oldmode newmode &optional error) 558(defun archive-calc-mode (oldmode newmode)
554 "From the integer OLDMODE and the string NEWMODE calculate a new file mode. 559 "From the integer OLDMODE and the string NEWMODE calculate a new file mode.
555NEWMODE may be an octal number including a leading zero in which case it 560NEWMODE may be an octal number including a leading zero in which case it
556will become the new mode.\n 561will become the new mode.\n
557NEWMODE may also be a relative specification like \"og-rwx\" in which case 562NEWMODE may also be a relative specification like \"og-rwx\" in which case
558OLDMODE will be modified accordingly just like chmod(2) would have done.\n 563OLDMODE will be modified accordingly just like chmod(2) would have done."
559If optional third argument ERROR is non-nil an error will be signaled if 564 ;; FIXME: Use `file-modes-symbolic-to-number'!
560the mode is invalid. If ERROR is nil then nil will be returned." 565 (if (string-match "\\`0[0-7]*\\'" newmode)
561 (cond ((string-match "^0[0-7]*$" newmode) 566 (logior (logand oldmode #o177000) (string-to-number newmode 8))
562 (let ((result 0) 567 (file-modes-symbolic-to-number newmode oldmode)))
563 (len (length newmode))
564 (i 1))
565 (while (< i len)
566 (setq result (+ (ash result 3) (aref newmode i) (- ?0))
567 i (1+ i)))
568 (logior (logand oldmode 65024) result)))
569 ((string-match "^\\([agou]+\\)\\([---+=]\\)\\([rwxst]+\\)$" newmode)
570 (let ((who 0)
571 (result oldmode)
572 (op (aref newmode (match-beginning 2)))
573 (bits 0)
574 (i (match-beginning 3)))
575 (while (< i (match-end 3))
576 (let ((rwx (aref newmode i)))
577 (setq bits (logior bits (cond ((= rwx ?r) 292)
578 ((= rwx ?w) 146)
579 ((= rwx ?x) 73)
580 ((= rwx ?s) 3072)
581 ((= rwx ?t) 512)))
582 i (1+ i))))
583 (while (< who (match-end 1))
584 (let* ((whoc (aref newmode who))
585 (whomask (cond ((= whoc ?a) 4095)
586 ((= whoc ?u) 1472)
587 ((= whoc ?g) 2104)
588 ((= whoc ?o) 7))))
589 (if (= op ?=)
590 (setq result (logand result (lognot whomask))))
591 (if (= op ?-)
592 (setq result (logand result (lognot (logand whomask bits))))
593 (setq result (logior result (logand whomask bits)))))
594 (setq who (1+ who)))
595 result))
596 (t
597 (if error
598 (error "Invalid mode specification: %s" newmode)))))
599 568
600(defun archive-dosdate (date) 569(defun archive-dosdate (date)
601 "Stringify dos packed DATE record." 570 "Stringify dos packed DATE record."
@@ -644,7 +613,7 @@ Does not signal an error if optional argument NOERROR is non-nil."
644 (if (and (>= (point) archive-file-list-start) 613 (if (and (>= (point) archive-file-list-start)
645 (< no (length archive-files))) 614 (< no (length archive-files)))
646 (let ((item (aref archive-files no))) 615 (let ((item (aref archive-files no)))
647 (if (vectorp item) 616 (if (archive--file-desc-p item)
648 item 617 item
649 (if (not noerror) 618 (if (not noerror)
650 (error "Entry is not a regular member of the archive")))) 619 (error "Entry is not a regular member of the archive"))))
@@ -696,10 +665,8 @@ archive.
696 (or (not (file-writable-p (buffer-file-name))) 665 (or (not (file-writable-p (buffer-file-name)))
697 (and archive-subfile-mode 666 (and archive-subfile-mode
698 (string-match file-name-invalid-regexp 667 (string-match file-name-invalid-regexp
699 (aref archive-subfile-mode 0))))) 668 (archive--file-desc-ext-file-name
700 669 archive-subfile-mode)))))
701 ;; Should we use a local copy when accessing from outside Emacs?
702 (make-local-variable 'archive-local-name)
703 670
704 ;; An archive can contain another archive whose name is invalid 671 ;; An archive can contain another archive whose name is invalid
705 ;; on local filesystem. Treat such archives as remote. 672 ;; on local filesystem. Treat such archives as remote.
@@ -806,27 +773,35 @@ when parsing the archive."
806 (goto-char archive-file-list-start) 773 (goto-char archive-file-list-start)
807 (archive-next-line no))) 774 (archive-next-line no)))
808 775
776(cl-defstruct (archive--file-summary
777 (:constructor nil)
778 (:constructor archive--file-summary (text name-start name-end)))
779 text name-start name-end)
780
809(defun archive-summarize-files (files) 781(defun archive-summarize-files (files)
810 "Insert a description of a list of files annotated with proper mouse face." 782 "Insert a description of a list of files annotated with proper mouse face."
811 (setq archive-file-list-start (point-marker)) 783 (setq archive-file-list-start (point-marker))
812 (setq archive-file-name-indent (if files (aref (car files) 1) 0)) 784 ;; Here we assume that they all start at the same column.
785 (setq archive-file-name-indent
786 ;; FIXME: We assume chars=columns (no double-wide chars and such).
787 (if files (archive--file-summary-name-start (car files)) 0))
813 ;; We don't want to do an insert for each element since that takes too 788 ;; We don't want to do an insert for each element since that takes too
814 ;; long when the archive -- which has to be moved in memory -- is large. 789 ;; long when the archive -- which has to be moved in memory -- is large.
815 (insert 790 (insert
816 (apply 791 (mapconcat
817 #'concat 792 (lambda (fil)
818 (mapcar 793 ;; Using `concat' here copies the text also, so we can add
819 (lambda (fil) 794 ;; properties without problems.
820 ;; Using `concat' here copies the text also, so we can add 795 (let ((text (concat (archive--file-summary-text fil) "\n")))
821 ;; properties without problems. 796 (add-text-properties
822 (let ((text (concat (aref fil 0) "\n"))) 797 (archive--file-summary-name-start fil)
823 (add-text-properties 798 (archive--file-summary-name-end fil)
824 (aref fil 1) (aref fil 2) 799 '(mouse-face highlight
825 '(mouse-face highlight 800 help-echo "mouse-2: extract this file into a buffer")
826 help-echo "mouse-2: extract this file into a buffer") 801 text)
827 text) 802 text))
828 text)) 803 files
829 files))) 804 ""))
830 (setq archive-file-list-end (point-marker))) 805 (setq archive-file-list-end (point-marker)))
831 806
832(defun archive-alternate-display () 807(defun archive-alternate-display ()
@@ -880,7 +855,8 @@ using `make-temp-file', and the generated name is returned."
880 ;; "foo.zip:bar.zip", which is invalid on DOS/Windows. 855 ;; "foo.zip:bar.zip", which is invalid on DOS/Windows.
881 ;; So use the actual name if available. 856 ;; So use the actual name if available.
882 (archive-name 857 (archive-name
883 (or (and archive-subfile-mode (aref archive-subfile-mode 0)) 858 (or (and archive-subfile-mode (archive--file-desc-ext-file-name
859 archive-subfile-mode))
884 archive))) 860 archive)))
885 (setq archive-local-name 861 (setq archive-local-name
886 (archive-unique-fname archive-name archive-tmpdir)) 862 (archive-unique-fname archive-name archive-tmpdir))
@@ -989,8 +965,8 @@ using `make-temp-file', and the generated name is returned."
989 (if event (posn-set-point (event-end event))) 965 (if event (posn-set-point (event-end event)))
990 (let* ((view-p (eq other-window-p 'view)) 966 (let* ((view-p (eq other-window-p 'view))
991 (descr (archive-get-descr)) 967 (descr (archive-get-descr))
992 (ename (aref descr 0)) 968 (ename (archive--file-desc-ext-file-name descr))
993 (iname (aref descr 1)) 969 (iname (archive--file-desc-int-file-name descr))
994 (archive-buffer (current-buffer)) 970 (archive-buffer (current-buffer))
995 (arcdir default-directory) 971 (arcdir default-directory)
996 (archive (buffer-file-name)) 972 (archive (buffer-file-name))
@@ -1234,7 +1210,7 @@ using `make-temp-file', and the generated name is returned."
1234 t) 1210 t)
1235 1211
1236(defun archive-*-write-file-member (archive descr command) 1212(defun archive-*-write-file-member (archive descr command)
1237 (let* ((ename (aref descr 0)) 1213 (let* ((ename (archive--file-desc-ext-file-name descr))
1238 (tmpfile (expand-file-name ename archive-tmpdir)) 1214 (tmpfile (expand-file-name ename archive-tmpdir))
1239 (top (directory-file-name (file-name-as-directory archive-tmpdir))) 1215 (top (directory-file-name (file-name-as-directory archive-tmpdir)))
1240 (default-directory (file-name-as-directory top))) 1216 (default-directory (file-name-as-directory top)))
@@ -1251,9 +1227,10 @@ using `make-temp-file', and the generated name is returned."
1251 ;; further processing clobbers it (we restore it in 1227 ;; further processing clobbers it (we restore it in
1252 ;; archive-write-file-member, above). 1228 ;; archive-write-file-member, above).
1253 (setq archive-member-coding-system last-coding-system-used) 1229 (setq archive-member-coding-system last-coding-system-used)
1254 (if (aref descr 3) 1230 (if (archive--file-desc-mode descr)
1255 ;; Set the file modes, but make sure we can read it. 1231 ;; Set the file modes, but make sure we can read it.
1256 (set-file-modes tmpfile (logior ?\400 (aref descr 3)))) 1232 (set-file-modes tmpfile
1233 (logior ?\400 (archive--file-desc-mode descr))))
1257 (setq ename 1234 (setq ename
1258 (encode-coding-string ename archive-file-name-coding-system)) 1235 (encode-coding-string ename archive-file-name-coding-system))
1259 (let* ((coding-system-for-write 'no-conversion) 1236 (let* ((coding-system-for-write 'no-conversion)
@@ -1357,7 +1334,7 @@ Use \\[archive-unmark-all-files] to remove all marks."
1357 "Change the protection bits associated with all marked or this member. 1334 "Change the protection bits associated with all marked or this member.
1358The new protection bits can either be specified as an octal number or 1335The new protection bits can either be specified as an octal number or
1359as a relative change like \"g+rw\" as for chmod(2)." 1336as a relative change like \"g+rw\" as for chmod(2)."
1360 (interactive "sNew mode (octal or relative): ") 1337 (interactive "sNew mode (octal or symbolic): ")
1361 (if archive-read-only (error "Archive is read-only")) 1338 (if archive-read-only (error "Archive is read-only"))
1362 (let ((func (archive-name "chmod-entry"))) 1339 (let ((func (archive-name "chmod-entry")))
1363 (if (fboundp func) 1340 (if (fboundp func)
@@ -1396,7 +1373,9 @@ as a relative change like \"g+rw\" as for chmod(2)."
1396 (goto-char archive-file-list-start) 1373 (goto-char archive-file-list-start)
1397 (while (< (point) archive-file-list-end) 1374 (while (< (point) archive-file-list-end)
1398 (if (= (following-char) ?D) 1375 (if (= (following-char) ?D)
1399 (setq files (cons (aref (archive-get-descr) 0) files))) 1376 (setq files (cons (archive--file-desc-ext-file-name
1377 (archive-get-descr))
1378 files)))
1400 (forward-line 1))) 1379 (forward-line 1)))
1401 (setq files (nreverse files)) 1380 (setq files (nreverse files))
1402 (and files 1381 (and files
@@ -1460,6 +1439,14 @@ This doesn't recover lost files, it just undoes changes in the buffer itself."
1460;; ------------------------------------------------------------------------- 1439;; -------------------------------------------------------------------------
1461;;; Section: Arc Archives 1440;;; Section: Arc Archives
1462 1441
1442(cl-defstruct (archive-arc--file-desc
1443 (:include archive--file-desc)
1444 (:constructor nil)
1445 (:constructor archive-arc--file-desc
1446 (ext-file-name int-file-name case-fiddled mode
1447 pos)))
1448 pos)
1449
1463(defun archive-arc-summarize () 1450(defun archive-arc-summarize ()
1464 (let ((p 1) 1451 (let ((p 1)
1465 (totalsize 0) 1452 (totalsize 0)
@@ -1486,11 +1473,13 @@ This doesn't recover lost files, it just undoes changes in the buffer itself."
1486 ifnname))) 1473 ifnname)))
1487 (setq maxlen (max maxlen fnlen) 1474 (setq maxlen (max maxlen fnlen)
1488 totalsize (+ totalsize ucsize) 1475 totalsize (+ totalsize ucsize)
1489 visual (cons (vector text 1476 visual (cons (archive--file-summary
1490 (- (length text) (length ifnname)) 1477 text
1491 (length text)) 1478 (- (length text) (length ifnname))
1479 (length text))
1492 visual) 1480 visual)
1493 files (cons (vector efnname ifnname fiddle nil (1- p)) 1481 files (cons (archive-arc--file-desc
1482 efnname ifnname fiddle nil (1- p))
1494 files) 1483 files)
1495 p (+ p 29 csize)))) 1484 p (+ p 29 csize))))
1496 (goto-char (point-min)) 1485 (goto-char (point-min))
@@ -1519,12 +1508,21 @@ This doesn't recover lost files, it just undoes changes in the buffer itself."
1519 (save-restriction 1508 (save-restriction
1520 (save-excursion 1509 (save-excursion
1521 (widen) 1510 (widen)
1522 (goto-char (+ archive-proper-file-start (aref descr 4) 2)) 1511 (goto-char (+ archive-proper-file-start 2
1512 (archive-arc--file-desc-pos descr)))
1523 (delete-char 13) 1513 (delete-char 13)
1524 (arc-insert-unibyte name))))) 1514 (arc-insert-unibyte name)))))
1525;; ------------------------------------------------------------------------- 1515;; -------------------------------------------------------------------------
1526;;; Section: Lzh Archives 1516;;; Section: Lzh Archives
1527 1517
1518(cl-defstruct (archive-lzh--file-desc
1519 (:include archive--file-desc)
1520 (:constructor nil)
1521 (:constructor archive-lzh--file-desc
1522 (ext-file-name int-file-name case-fiddled mode
1523 pos)))
1524 pos)
1525
1528(defun archive-lzh-summarize (&optional start) 1526(defun archive-lzh-summarize (&optional start)
1529 (let ((p (or start 1)) ;; 1 for .lzh, something further on for .exe 1527 (let ((p (or start 1)) ;; 1 for .lzh, something further on for .exe
1530 (totalsize 0) 1528 (totalsize 0)
@@ -1639,11 +1637,13 @@ This doesn't recover lost files, it just undoes changes in the buffer itself."
1639 prname))) 1637 prname)))
1640 (setq maxlen (max maxlen width) 1638 (setq maxlen (max maxlen width)
1641 totalsize (+ totalsize ucsize) 1639 totalsize (+ totalsize ucsize)
1642 visual (cons (vector text 1640 visual (cons (archive--file-summary
1643 (- (length text) (length prname)) 1641 text
1644 (length text)) 1642 (- (length text) (length prname))
1643 (length text))
1645 visual) 1644 visual)
1646 files (cons (vector prname ifnname fiddle mode (1- p)) 1645 files (cons (archive-lzh--file-desc
1646 prname ifnname fiddle mode (1- p))
1647 files)) 1647 files))
1648 (cond ((= hdrlvl 1) 1648 (cond ((= hdrlvl 1)
1649 (setq p (+ p hsize 2 csize))) 1649 (setq p (+ p hsize 2 csize)))
@@ -1689,7 +1689,8 @@ This doesn't recover lost files, it just undoes changes in the buffer itself."
1689 (save-restriction 1689 (save-restriction
1690 (save-excursion 1690 (save-excursion
1691 (widen) 1691 (widen)
1692 (let* ((p (+ archive-proper-file-start (aref descr 4))) 1692 (let* ((p (+ archive-proper-file-start
1693 (archive-lzh--file-desc-pos descr)))
1693 (oldhsize (get-byte p)) 1694 (oldhsize (get-byte p))
1694 (oldfnlen (get-byte (+ p 21))) 1695 (oldfnlen (get-byte (+ p 21)))
1695 (newfnlen (length newname)) 1696 (newfnlen (length newname))
@@ -1709,7 +1710,7 @@ This doesn't recover lost files, it just undoes changes in the buffer itself."
1709 (save-restriction 1710 (save-restriction
1710 (widen) 1711 (widen)
1711 (dolist (fil files) 1712 (dolist (fil files)
1712 (let* ((p (+ archive-proper-file-start (aref fil 4))) 1713 (let* ((p (+ archive-proper-file-start (archive-lzh--file-desc-pos fil)))
1713 (hsize (get-byte p)) 1714 (hsize (get-byte p))
1714 (fnlen (get-byte (+ p 21))) 1715 (fnlen (get-byte (+ p 21)))
1715 (p2 (+ p 22 fnlen)) 1716 (p2 (+ p 22 fnlen))
@@ -1726,7 +1727,7 @@ This doesn't recover lost files, it just undoes changes in the buffer itself."
1726 (delete-char 1) 1727 (delete-char 1)
1727 (arc-insert-unibyte (archive-lzh-resum (1+ p) hsize))) 1728 (arc-insert-unibyte (archive-lzh-resum (1+ p) hsize)))
1728 (message "Member %s does not have %s field" 1729 (message "Member %s does not have %s field"
1729 (aref fil 1) errtxt))))))) 1730 (archive--file-desc-int-file-name fil) errtxt)))))))
1730 1731
1731(defun archive-lzh-chown-entry (newuid files) 1732(defun archive-lzh-chown-entry (newuid files)
1732 (archive-lzh-ogm newuid files "an uid" 10)) 1733 (archive-lzh-ogm newuid files "an uid" 10))
@@ -1736,8 +1737,7 @@ This doesn't recover lost files, it just undoes changes in the buffer itself."
1736 1737
1737(defun archive-lzh-chmod-entry (newmode files) 1738(defun archive-lzh-chmod-entry (newmode files)
1738 (archive-lzh-ogm 1739 (archive-lzh-ogm
1739 ;; This should work even though newmode will be dynamically accessed. 1740 (lambda (old) (archive-calc-mode old newmode))
1740 (lambda (old) (archive-calc-mode old newmode t))
1741 files "a unix-style mode" 8)) 1741 files "a unix-style mode" 8))
1742 1742
1743;; ------------------------------------------------------------------------- 1743;; -------------------------------------------------------------------------
@@ -1770,6 +1770,14 @@ This doesn't recover lost files, it just undoes changes in the buffer itself."
1770;; ------------------------------------------------------------------------- 1770;; -------------------------------------------------------------------------
1771;;; Section: Zip Archives 1771;;; Section: Zip Archives
1772 1772
1773(cl-defstruct (archive-zip--file-desc
1774 (:include archive--file-desc)
1775 (:constructor nil)
1776 (:constructor archive-zip--file-desc
1777 (ext-file-name int-file-name case-fiddled mode
1778 pos+len)))
1779 pos+len)
1780
1773(defun archive-zip-summarize () 1781(defun archive-zip-summarize ()
1774 (goto-char (- (point-max) (- 22 18))) 1782 (goto-char (- (point-max) (- 22 18)))
1775 (search-backward-regexp "[P]K\005\006") 1783 (search-backward-regexp "[P]K\005\006")
@@ -1832,14 +1840,15 @@ This doesn't recover lost files, it just undoes changes in the buffer itself."
1832 ifnname))) 1840 ifnname)))
1833 (setq maxlen (max maxlen width) 1841 (setq maxlen (max maxlen width)
1834 totalsize (+ totalsize ucsize) 1842 totalsize (+ totalsize ucsize)
1835 visual (cons (vector text 1843 visual (cons (archive--file-summary
1836 (- (length text) (length ifnname)) 1844 text
1837 (length text)) 1845 (- (length text) (length ifnname))
1846 (length text))
1838 visual) 1847 visual)
1839 files (cons (if isdir 1848 files (cons (if isdir
1840 nil 1849 nil
1841 (vector efnname ifnname fiddle mode 1850 (archive-zip--file-desc efnname ifnname fiddle mode
1842 (list (1- p) lheader))) 1851 (list (1- p) lheader)))
1843 files) 1852 files)
1844 p (+ p 46 fnlen exlen fclen)))) 1853 p (+ p 46 fnlen exlen fclen))))
1845 (goto-char (point-min)) 1854 (goto-char (point-min))
@@ -1884,17 +1893,19 @@ This doesn't recover lost files, it just undoes changes in the buffer itself."
1884 (archive-*-write-file-member 1893 (archive-*-write-file-member
1885 archive 1894 archive
1886 descr 1895 descr
1887 (if (aref descr 2) archive-zip-update-case archive-zip-update))) 1896 (if (archive--file-desc-case-fiddled descr)
1897 archive-zip-update-case archive-zip-update)))
1888 1898
1889(defun archive-zip-chmod-entry (newmode files) 1899(defun archive-zip-chmod-entry (newmode files)
1890 (save-restriction 1900 (save-restriction
1891 (save-excursion 1901 (save-excursion
1892 (widen) 1902 (widen)
1893 (dolist (fil files) 1903 (dolist (fil files)
1894 (let* ((p (+ archive-proper-file-start (car (aref fil 4)))) 1904 (let* ((p (+ archive-proper-file-start
1905 (car (archive-zip--file-desc-pos+len fil))))
1895 (creator (get-byte (+ p 5))) 1906 (creator (get-byte (+ p 5)))
1896 (oldmode (aref fil 3)) 1907 (oldmode (archive--file-desc-mode fil))
1897 (newval (archive-calc-mode oldmode newmode t)) 1908 (newval (archive-calc-mode oldmode newmode))
1898 (inhibit-read-only t)) 1909 (inhibit-read-only t))
1899 (cond ((memq creator '(2 3)) ; Unix 1910 (cond ((memq creator '(2 3)) ; Unix
1900 (goto-char (+ p 40)) 1911 (goto-char (+ p 40))
@@ -1911,6 +1922,14 @@ This doesn't recover lost files, it just undoes changes in the buffer itself."
1911;; ------------------------------------------------------------------------- 1922;; -------------------------------------------------------------------------
1912;;; Section: Zoo Archives 1923;;; Section: Zoo Archives
1913 1924
1925(cl-defstruct (archive-zoo--file-desc
1926 (:include archive--file-desc)
1927 (:constructor nil)
1928 (:constructor archive-zoo--file-desc
1929 (ext-file-name int-file-name case-fiddled mode
1930 pos)))
1931 pos)
1932
1914(defun archive-zoo-summarize () 1933(defun archive-zoo-summarize ()
1915 (let ((p (1+ (archive-l-e 25 4))) 1934 (let ((p (1+ (archive-l-e 25 4)))
1916 (maxlen 8) 1935 (maxlen 8)
@@ -1952,11 +1971,15 @@ This doesn't recover lost files, it just undoes changes in the buffer itself."
1952 ifnname))) 1971 ifnname)))
1953 (setq maxlen (max maxlen width) 1972 (setq maxlen (max maxlen width)
1954 totalsize (+ totalsize ucsize) 1973 totalsize (+ totalsize ucsize)
1955 visual (cons (vector text 1974 visual (cons (archive--file-summary
1956 (- (length text) (length ifnname)) 1975 text
1957 (length text)) 1976 (- (length text) (length ifnname))
1977 (length text))
1958 visual) 1978 visual)
1959 files (cons (vector efnname ifnname fiddle nil (1- p)) 1979 ;; FIXME: Keep size/date(/mode?) in the desc!
1980 files (cons (archive-zoo--file-desc
1981 ;; FIXME: The `pos' field seems unused!
1982 efnname ifnname fiddle nil (1- p))
1960 files) 1983 files)
1961 p next))) 1984 p next)))
1962 (goto-char (point-min)) 1985 (goto-char (point-min))
@@ -1980,6 +2003,14 @@ This doesn't recover lost files, it just undoes changes in the buffer itself."
1980;; ------------------------------------------------------------------------- 2003;; -------------------------------------------------------------------------
1981;;; Section: Rar Archives 2004;;; Section: Rar Archives
1982 2005
2006(cl-defstruct (archive-rar--file-desc
2007 (:include archive--file-desc)
2008 (:constructor nil)
2009 (:constructor archive-rar--file-desc
2010 (ext-file-name int-file-name case-fiddled mode
2011 size ratio date time)))
2012 size ratio date time)
2013
1983(defun archive-rar-summarize (&optional file) 2014(defun archive-rar-summarize (&optional file)
1984 ;; File is used internally for `archive-rar-exe-summarize'. 2015 ;; File is used internally for `archive-rar-exe-summarize'.
1985 (unless file (setq file buffer-file-name)) 2016 (unless file (setq file buffer-file-name))
@@ -2005,11 +2036,11 @@ This doesn't recover lost files, it just undoes changes in the buffer itself."
2005 (size (match-string 1))) 2036 (size (match-string 1)))
2006 (if (> (length name) maxname) (setq maxname (length name))) 2037 (if (> (length name) maxname) (setq maxname (length name)))
2007 (if (> (length size) maxsize) (setq maxsize (length size))) 2038 (if (> (length size) maxsize) (setq maxsize (length size)))
2008 (push (vector name name nil nil 2039 (push (archive-rar--file-desc name name nil nil
2009 ;; Size, Ratio. 2040 ;; Size, Ratio.
2010 size (match-string 2) 2041 size (match-string 2)
2011 ;; Date, Time. 2042 ;; Date, Time.
2012 (match-string 4) (match-string 5)) 2043 (match-string 4) (match-string 5))
2013 files)))) 2044 files))))
2014 (setq files (nreverse files)) 2045 (setq files (nreverse files))
2015 (goto-char (point-min)) 2046 (goto-char (point-min))
@@ -2019,18 +2050,20 @@ This doesn't recover lost files, it just undoes changes in the buffer itself."
2019 (column (length sep))) 2050 (column (length sep)))
2020 (insert (format format " Date " "Time " "Size" "Ratio" "Filename") "\n") 2051 (insert (format format " Date " "Time " "Size" "Ratio" "Filename") "\n")
2021 (insert sep (make-string maxname ?-) "\n") 2052 (insert sep (make-string maxname ?-) "\n")
2022 (archive-summarize-files (mapcar (lambda (desc) 2053 (archive-summarize-files
2023 (let ((text 2054 (mapcar (lambda (desc)
2024 (format format 2055 (let ((text
2025 (aref desc 6) 2056 (format format
2026 (aref desc 7) 2057 (archive-rar--file-desc-date desc)
2027 (aref desc 4) 2058 (archive-rar--file-desc-time desc)
2028 (aref desc 5) 2059 (archive-rar--file-desc-size desc)
2029 (aref desc 1)))) 2060 (archive-rar--file-desc-ratio desc)
2030 (vector text 2061 (archive--file-desc-int-file-name desc))))
2031 column 2062 (archive--file-summary
2032 (length text)))) 2063 text
2033 files)) 2064 column
2065 (length text))))
2066 files))
2034 (insert sep (make-string maxname ?-) "\n") 2067 (insert sep (make-string maxname ?-) "\n")
2035 (apply #'vector files)))) 2068 (apply #'vector files))))
2036 2069
@@ -2078,6 +2111,14 @@ This doesn't recover lost files, it just undoes changes in the buffer itself."
2078;; ------------------------------------------------------------------------- 2111;; -------------------------------------------------------------------------
2079;;; Section: 7z Archives 2112;;; Section: 7z Archives
2080 2113
2114(cl-defstruct (archive-7z--file-desc
2115 (:include archive--file-desc)
2116 (:constructor nil)
2117 (:constructor archive-7z--file-desc
2118 (ext-file-name int-file-name case-fiddled mode
2119 time user group size)))
2120 time user group size)
2121
2081(defun archive-7z-summarize () 2122(defun archive-7z-summarize ()
2082 (let ((maxname 10) 2123 (let ((maxname 10)
2083 (maxsize 5) 2124 (maxsize 5)
@@ -2100,7 +2141,7 @@ This doesn't recover lost files, it just undoes changes in the buffer itself."
2100 (match-string 1))))) 2141 (match-string 1)))))
2101 (if (> (length name) maxname) (setq maxname (length name))) 2142 (if (> (length name) maxname) (setq maxname (length name)))
2102 (if (> (length size) maxsize) (setq maxsize (length size))) 2143 (if (> (length size) maxsize) (setq maxsize (length size)))
2103 (push (vector name name nil nil time nil nil size) 2144 (push (archive-7z--file-desc name name nil nil time nil nil size)
2104 files)))) 2145 files))))
2105 (setq files (nreverse files)) 2146 (setq files (nreverse files))
2106 (goto-char (point-min)) 2147 (goto-char (point-min))
@@ -2109,16 +2150,16 @@ This doesn't recover lost files, it just undoes changes in the buffer itself."
2109 (column (length sep))) 2150 (column (length sep)))
2110 (insert (format format "Size " "Date Time " " Filename") "\n") 2151 (insert (format format "Size " "Date Time " " Filename") "\n")
2111 (insert sep (make-string maxname ?-) "\n") 2152 (insert sep (make-string maxname ?-) "\n")
2112 (archive-summarize-files (mapcar (lambda (desc) 2153 (archive-summarize-files
2113 (let ((text 2154 (mapcar (lambda (desc)
2114 (format format 2155 (let ((text
2115 (aref desc 7) 2156 (format format
2116 (aref desc 4) 2157 (archive-7z--file-desc-size desc)
2117 (aref desc 1)))) 2158 (archive-7z--file-desc-time desc)
2118 (vector text 2159 (archive--file-desc-int-file-name desc))))
2119 column 2160 (archive--file-summary
2120 (length text)))) 2161 text column (length text))))
2121 files)) 2162 files))
2122 (insert sep (make-string maxname ?-) "\n") 2163 (insert sep (make-string maxname ?-) "\n")
2123 (apply #'vector files)))) 2164 (apply #'vector files))))
2124 2165
@@ -2142,6 +2183,14 @@ This doesn't recover lost files, it just undoes changes in the buffer itself."
2142;; not the GNU nor the BSD extensions. As it turns out, this is sufficient 2183;; not the GNU nor the BSD extensions. As it turns out, this is sufficient
2143;; for .deb packages. 2184;; for .deb packages.
2144 2185
2186(cl-defstruct (archive-ar--file-desc
2187 (:include archive--file-desc)
2188 (:constructor nil)
2189 (:constructor archive-ar--file-desc
2190 (ext-file-name int-file-name case-fiddled mode
2191 time user group size)))
2192 time user group size)
2193
2145(autoload 'tar-grind-file-mode "tar-mode") 2194(autoload 'tar-grind-file-mode "tar-mode")
2146 2195
2147(defconst archive-ar-file-header-re 2196(defconst archive-ar-file-header-re
@@ -2193,8 +2242,8 @@ NAME is expected to be the 16-bytes part of an ar record."
2193 (if (> (length group) maxgroup) (setq maxgroup (length group))) 2242 (if (> (length group) maxgroup) (setq maxgroup (length group)))
2194 (if (> (length mode) maxmode) (setq maxmode (length mode))) 2243 (if (> (length mode) maxmode) (setq maxmode (length mode)))
2195 (if (> (length size) maxsize) (setq maxsize (length size))) 2244 (if (> (length size) maxsize) (setq maxsize (length size)))
2196 (push (vector extname extname nil mode 2245 (push (archive-ar--file-desc extname extname nil mode
2197 time user group size) 2246 time user group size)
2198 files))) 2247 files)))
2199 (setq files (nreverse files)) 2248 (setq files (nreverse files))
2200 (goto-char (point-min)) 2249 (goto-char (point-min))
@@ -2210,19 +2259,18 @@ NAME is expected to be the 16-bytes part of an ar record."
2210 " Date " "Filename") 2259 " Date " "Filename")
2211 "\n") 2260 "\n")
2212 (insert sep (make-string maxname ?-) "\n") 2261 (insert sep (make-string maxname ?-) "\n")
2213 (archive-summarize-files (mapcar (lambda (desc) 2262 (archive-summarize-files
2214 (let ((text 2263 (mapcar (lambda (desc)
2215 (format format 2264 (let ((text
2216 (aref desc 3) 2265 (format format
2217 (aref desc 5) 2266 (archive--file-desc-mode desc)
2218 (aref desc 6) 2267 (archive-ar--file-desc-user desc)
2219 (aref desc 7) 2268 (archive-ar--file-desc-group desc)
2220 (aref desc 4) 2269 (archive-ar--file-desc-size desc)
2221 (aref desc 1)))) 2270 (archive-ar--file-desc-time desc)
2222 (vector text 2271 (archive--file-desc-int-file-name desc))))
2223 column 2272 (archive--file-summary text column (length text))))
2224 (length text)))) 2273 files))
2225 files))
2226 (insert sep (make-string maxname ?-) "\n") 2274 (insert sep (make-string maxname ?-) "\n")
2227 (apply #'vector files)))) 2275 (apply #'vector files))))
2228 2276
@@ -2259,7 +2307,8 @@ NAME is expected to be the 16-bytes part of an ar record."
2259 archive 2307 archive
2260 (let ((d (copy-sequence descr))) 2308 (let ((d (copy-sequence descr)))
2261 ;; FIXME: Crude conversion from string modes to a number. 2309 ;; FIXME: Crude conversion from string modes to a number.
2262 (cl-callf (lambda (s) (if (string-match "x" s) ?\555 ?\444)) (aref d 3)) 2310 (cl-callf (lambda (s) (if (string-match "x" s) ?\555 ?\444))
2311 (archive--file-desc-mode d))
2263 d) 2312 d)
2264 '("ar" "r"))) 2313 '("ar" "r")))
2265 2314