Function: archive-lzh-summarize
archive-lzh-summarize is a byte-compiled function defined in
arc-mode.el.gz.
Signature
(archive-lzh-summarize &optional START)
Source Code
;; Defined in /usr/src/emacs/lisp/arc-mode.el.gz
;; -------------------------------------------------------------------------
;;; Section: Lzh Archives
(defun archive-lzh-summarize (&optional start)
(let ((p (or start 1)) ;; 1 for .lzh, something further on for .exe
files)
(while (progn (goto-char p) ;beginning of a base header.
(looking-at "\\(.\\|\n\\)\\(.\\|\n\\)-l[hz][0-9ds]-"))
(let* ((hsize (get-byte 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),
;size of extended headers + the compressed file to follow (level 1).
(ucsize (archive-l-e (+ p 11) 4)) ;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 (get-byte (+ p 20))) ;header level
thsize ;total header size (base + extensions)
fnlen efnname osid fiddle ifnname p2
neh ;beginning of next extension header (level 1 and 2)
mode uid gid dir prname
gname uname modtime moddate)
(if (= hdrlvl 3) (error "Can't handle lzh level 3 header type"))
(when (or (= hdrlvl 0) (= hdrlvl 1))
(setq fnlen (get-byte (+ p 21))) ;filename length
(setq efnname (let ((str (buffer-substring (+ p 22) (+ p 22 fnlen)))) ;filename from offset 22
(decode-coding-string
str archive-file-name-coding-system)))
(setq p2 (+ p 22 fnlen))) ;
(if (= hdrlvl 1)
(setq neh (+ p2 3)) ;specific to level 1 header
(if (= hdrlvl 2)
(setq neh (+ p 24)))) ;specific to level 2 header
(if neh ;if level 1 or 2 we expect extension headers to follow
(let* ((ehsize (archive-l-e neh 2)) ;size of the extension header
(etype (get-byte (+ neh 2)))) ;extension type
(while (not (= ehsize 0))
(cond
((= etype 1) ;file name
(let ((i (+ neh 3)))
(while (< i (+ neh ehsize))
(setq efnname (concat efnname (char-to-string (get-byte i))))
(setq i (1+ i)))))
((= etype 2) ;directory name
(let ((i (+ neh 3)))
(while (< i (+ neh ehsize))
(setq dir (concat dir
(if (= (get-byte i)
255)
"/"
(char-to-string
(char-after i)))))
(setq i (1+ i)))))
((= etype 80) ;Unix file permission
(setq mode (archive-l-e (+ neh 3) 2)))
((= etype 81) ;UNIX file group/user ID
(progn (setq uid (archive-l-e (+ neh 3) 2))
(setq gid (archive-l-e (+ neh 5) 2))))
((= etype 82) ;UNIX file group name
(let ((i (+ neh 3)))
(while (< i (+ neh ehsize))
(setq gname (concat gname (char-to-string (char-after i))))
(setq i (1+ i)))))
((= etype 83) ;UNIX file user name
(let ((i (+ neh 3)))
(while (< i (+ neh ehsize))
(setq uname (concat uname (char-to-string (char-after i))))
(setq i (1+ i)))))
)
(setq neh (+ neh ehsize))
(setq ehsize (archive-l-e neh 2))
(setq etype (get-byte (+ neh 2))))
;;get total header size for level 1 and 2 headers
(setq thsize (- neh p))))
(if (= hdrlvl 0) ;total header size
(setq thsize hsize))
;; OS ID field not present in level 0 header, use code 0 "generic"
;; in that case as per lha program header.c get_header()
(setq osid (cond ((= hdrlvl 0) 0)
((= hdrlvl 1) (char-after (+ p 22 fnlen 2)))
((= hdrlvl 2) (char-after (+ p 23)))))
;; Filename fiddling must follow the lha program, otherwise the name
;; passed to "lha pq" etc won't match (which for an extract silently
;; results in no output). As of version 1.14i it goes from the OS ID,
;; - For 'M' MSDOS: msdos_to_unix_filename() downcases always, and
;; converts "\" to "/".
;; - For 0 generic: generic_to_unix_filename() downcases if there's
;; no lower case already present, and converts "\" to "/".
;; - For 'm' macOS: macos_to_unix_filename() changes "/" to ":" and
;; ":" to "/"
(setq fiddle (cond ((= ?M osid) t)
((= 0 osid) (string= efnname (upcase efnname)))))
(setq ifnname (if fiddle (downcase efnname) efnname))
(setq prname (if dir (concat dir ifnname) ifnname))
(setq moddate (if (= hdrlvl 2)
(archive-unixdate time1 time2) ;level 2 header in UNIX format
(archive-dosdate time2))) ;level 0 and 1 header in DOS format
(setq modtime (if (= hdrlvl 2)
(archive-unixtime time1 time2)
(archive-dostime time1)))
(push (archive--file-desc
prname ifnname mode ucsize
(concat moddate " " modtime)
:pos (1- p)
:uid (or uname (if uid (number-to-string uid)))
:gid (or gname (if gid (number-to-string gid))))
files)
(cond ((= hdrlvl 1)
(setq p (+ p hsize 2 csize)))
((or (= hdrlvl 2) (= hdrlvl 0))
(setq p (+ p thsize 2 csize))))
))
(archive--summarize-descs (nreverse files))))