aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lisp/tar-mode.el31
1 files changed, 25 insertions, 6 deletions
diff --git a/lisp/tar-mode.el b/lisp/tar-mode.el
index 569b01f978b..d3ad5830cf5 100644
--- a/lisp/tar-mode.el
+++ b/lisp/tar-mode.el
@@ -223,10 +223,14 @@ Preserve the modified states of the buffers and set `buffer-swapped-with'."
223 "Round S up to the next multiple of 512." 223 "Round S up to the next multiple of 512."
224 (ash (ash (+ s 511) -9) 9)) 224 (ash (ash (+ s 511) -9) 9))
225 225
226(defun tar-header-block-tokenize (pos coding) 226(defun tar-header-block-tokenize (pos coding &optional disable-slash)
227 "Return a `tar-header' structure. 227 "Return a `tar-header' structure.
228This is a list of name, mode, uid, gid, size, 228This is a list of name, mode, uid, gid, size,
229write-date, checksum, link-type, and link-name." 229write-date, checksum, link-type, and link-name.
230CODING is our best guess for decoding non-ASCII file names.
231DISABLE-SLASH, if non-nil, means don't decide an entry is a directory
232based on the trailing slash, only based on the \"link-type\" field
233of the file header. This is used for \"old GNU\" Tar format."
230 (if (> (+ pos 512) (point-max)) (error "Malformed Tar header")) 234 (if (> (+ pos 512) (point-max)) (error "Malformed Tar header"))
231 (cl-assert (zerop (mod (- pos (point-min)) 512))) 235 (cl-assert (zerop (mod (- pos (point-min)) 512)))
232 (cl-assert (not enable-multibyte-characters)) 236 (cl-assert (not enable-multibyte-characters))
@@ -272,7 +276,7 @@ write-date, checksum, link-type, and link-name."
272 (decode-coding-string name coding) 276 (decode-coding-string name coding)
273 linkname 277 linkname
274 (decode-coding-string linkname coding)) 278 (decode-coding-string linkname coding))
275 (if (and (null link-p) (string-match "/\\'" name)) 279 (if (and (null link-p) (null disable-slash) (string-match "/\\'" name))
276 (setq link-p 5)) ; directory 280 (setq link-p 5)) ; directory
277 281
278 (if (and (equal name "././@LongLink") 282 (if (and (equal name "././@LongLink")
@@ -283,12 +287,23 @@ write-date, checksum, link-type, and link-name."
283 ;; This is a GNU Tar long-file-name header. 287 ;; This is a GNU Tar long-file-name header.
284 (let* ((size (tar-parse-octal-integer 288 (let* ((size (tar-parse-octal-integer
285 string tar-size-offset tar-time-offset)) 289 string tar-size-offset tar-time-offset))
286 ;; -1 so as to strip the terminating 0 byte. 290 ;; The long name is in the next 512-byte block.
291 ;; We've already moved POS there, when we computed
292 ;; STRING above.
287 (name (decode-coding-string 293 (name (decode-coding-string
294 ;; -1 so as to strip the terminating 0 byte.
288 (buffer-substring pos (+ pos size -1)) coding)) 295 (buffer-substring pos (+ pos size -1)) coding))
296 ;; Tokenize the header of the _real_ file entry,
297 ;; which is further 512 bytes into the archive.
289 (descriptor (tar-header-block-tokenize 298 (descriptor (tar-header-block-tokenize
290 (+ pos (tar-roundup-512 size)) 299 (+ pos (tar-roundup-512 size)) coding
291 coding))) 300 ;; Don't intuit directories from
301 ;; the trailing slash, because the
302 ;; truncated name might by chance end
303 ;; in a slash.
304 'ignore-trailing-slash)))
305 ;; Fix the descriptor of the real file entry by using
306 ;; the information from the long name entry.
292 (cond 307 (cond
293 ((eq link-p (- ?L ?0)) ;GNUTYPE_LONGNAME. 308 ((eq link-p (- ?L ?0)) ;GNUTYPE_LONGNAME.
294 (setf (tar-header-name descriptor) name)) 309 (setf (tar-header-name descriptor) name))
@@ -296,6 +311,10 @@ write-date, checksum, link-type, and link-name."
296 (setf (tar-header-link-name descriptor) name)) 311 (setf (tar-header-link-name descriptor) name))
297 (t 312 (t
298 (message "Unrecognized GNU Tar @LongLink format"))) 313 (message "Unrecognized GNU Tar @LongLink format")))
314 ;; Fix the "link-type" attribute, based on the long name.
315 (if (and (null (tar-header-link-type descriptor))
316 (string-match "/\\'" name))
317 (setf (tar-header-link-type descriptor) 5)) ; directory
299 (setf (tar-header-header-start descriptor) 318 (setf (tar-header-header-start descriptor)
300 (copy-marker (- pos 512) t)) 319 (copy-marker (- pos 512) t))
301 descriptor) 320 descriptor)