;;; -*- Mode:LISP; Package:FILE-SYSTEM; Readtable:CL; Base:10. -*- ;;; ;;; Hack for restoring TAR tapes. ;;; ;;; -dg 8/14/85 ;;; (defmacro defstring (name length) `(defvar ,name (make-string ,length))) (defstring *name* 100) (defstring *mode* 8) (defstring *uid* 8) (defstring *gid* 8) (defstring *size* 12) (defstring *time* 12) (defstring *checksum* 8) (defstring *link-flag* 1) (defstring *link-name* 100) (defstring *header-filler* 255) (defstring *moby-string* 1000000) (defvar *debug-plist* nil) (defconst *dummy-unix-host* (progn (si:define-host "dummy" :host-names (list "dummy") :machine-type :unix :system-type :unix :chaos '(#o01)) (add-file-computer '("dummy" :lmfs)) (si:parse-host "dummy"))) (defflavor tar-tm-input-stream () (tm-input-stream) (:default-init-plist :record-size 10240.)) (defflavor tar-tm-output-stream () (tm-output-stream) (:default-init-plist :record-size 10240.)) (defun pathname-translate-simple (namestring &optional (to-host si:local-host)) (let ((pn (fs:parse-pathname namestring *dummy-unix-host*))) (fs:make-pathname :host to-host :directory (pathname-directory pn) :name (pathname-name pn) :original-type (pathname-type pn) :canonical-type (send pn :canonical-type) :version (pathname-version pn)))) (defsubst read-from-string-octal (string) (parse-integer string :radix 8 :junk-allowed 't)) ; (let ((*read-base* 8.)) ; (read-from-string (string-trim '(0 #\space) string)))) (defun get-file-header-as-plist (&optional (stream (make-instance 'tar-tm-input-stream))) (dolist (string (list *name* *mode* *uid* *gid* *size* *time* *checksum* *link-flag* *link-name*)) (fill string 0) (send stream :string-in nil string)) (send stream :string-in nil *header-filler*) (setq *debug-plist* (list *name* *mode* *uid* *gid* *size* *time* *checksum* *link-flag* *link-name*)) (list (string-trim '(0) *name*) :mode (read-from-string-octal *mode*) :uid (read-from-string-octal *uid*) :gid (read-from-string-octal *gid*) :length-in-bytes (read-from-string-octal *size*) :creation-date (+ #.(time:parse-universal-time "January 1, 1970") (read-from-string-octal *time*) 0) :checksum (read-from-string-octal *checksum*) :link-flag (not (memq (char *link-flag* 0) `(#\center-dot #\space))) :link-name (string-trim '(0) *link-name*))) (defun print-header (plist &optional (stream *standard-output*)) (format stream "~&File relative name: ~A" (car plist)) (do ((list (cdr plist) (cddr list))) ((null list)) (format stream "~&~A: ~S" (car list) (cadr list))) (format stream "~2%")) (defsubst moby-indirect-string (size) (when (> size (length *moby-string*)) (setq *moby-string* (make-string size))) (nsubstring *moby-string* 0 size)) (defun list-tar-image (input-stream &optional (output-stream *standard-output*)) (condition-case () (do-forever (let ((plist (get-file-header-as-plist input-stream))) (print-header plist output-stream) (unless (get plist :link-flag) (send input-stream :string-in nil (moby-indirect-string (* (ceiling (get plist :length-in-bytes) 512.) 512.)))))) (fs:end-of-tape (close input-stream)))) (defun list-tar-tape (&optional (output-stream *standard-output*)) (tm-rewind) (let ((stream (make-instance 'tar-tm-input-stream))) (list-tar-image stream output-stream))) (defun list-tar-file (filename &optional (output-stream *standard-output*)) (with-open-file (stream filename) (list-tar-image stream output-stream))) (defun dump-tar-tape (stream &key (record-size 10240.) (ascii-translate t)) (let ((istream (make-instance 'tar-tm-input-stream)) (string (make-string record-size))) (condition-case () (do-forever (send istream :string-in nil string) (when ascii-translate (string-subst-char #\return #\delta string nil nil) (string-subst-char #\tab #\gamma string nil nil)) (send stream :string-out string)) (fs:end-of-tape)))) (defun dump-tar-tape-to-file (filename &optional ascii-translate) (tm-rewind) (with-open-file (file filename :direction :output) (dump-tar-tape file :ascii-translate ascii-translate))) (defun print-tar-tape () (dump-tar-tape *standard-output*)) (defun restore-tar-file (stream &key (pathname-function) ignore-links overwrite (ascii-translate t)) (let ((plist (get-file-header-as-plist stream))) (format t "~&Found file [~A] - " (car plist)) ; (when (neq (tyi) #\space) ; sldkj) (if (and (get plist :link-flag) ignore-links) (format t "[link] ignoring.~%") (multiple-value-bind (pathname characters-p) (funcall pathname-function (car plist)) (send stream :string-in nil (moby-indirect-string (* (ceiling (get plist :length-in-bytes) 512.) 512.))) (if (not pathname) (format t "filtered-out.~%") (when (if (typep (send pathname :truename nil) 'fs:pathname) (case overwrite (:ask (y-or-n-p "File ~A already exists; Overwrite it?" pathname)) (nil (format t "not overwriting.~%") nil) (t (format t "overwriting to [~A].~%" pathname) t)) (format t "writing to [~a]" pathname) t) (with-open-file (filestream pathname :characters characters-p :direction :output) (let ((string-to-output (moby-indirect-string (get plist :length-in-bytes)))) (when ascii-translate (string-subst-char #\return #\delta string-to-output nil nil) (string-subst-char #\tab #\gamma string-to-output nil nil)) (send filestream :string-out string-to-output))))))))) (defun restore-tar-tape (pathname-function &key overwrite ignore-links (ascii-translation t)) (tm-rewind) (with-open-file (ignore "half-inch-tape:") (let ((tar-stream (make-instance 'tar-tm-input-stream))) (condition-case () (do-forever (restore-tar-file tar-stream :ignore-links ignore-links :pathname-function pathname-function :overwrite overwrite :ascii-translate ascii-translation)) (fs:end-of-tape))))) (defun write-tar-tape (directory) (tm-rewind) (with-open-file (ignore "half-inch-tape:") (let ((tar-stream (make-instance 'tar-tm-output-stream))) (condition-case () (write-tar-directory directory tar-stream) (fs:end-of-tape))))) (defun write-tar-directory (directory stream) (let ((files (cdr (fs:directory-list directory)))) (loop for file in files unless (get files :directory) do (write-tar-file (first file) (cdr file) stream)) (loop for file in files when (get files :directory) do (write-tar-directory (send (send (first file) :pathname-as-directory) :new-pathname :name (send directory :name) :type (send directory :type) :version (send directory :version)) stream)))) (defun add-to-*name* (offset string) (let* ((lth (string-length string)) (end (+ offset lth))) (loop for findex from 0 below lth and tindex upfrom offset do (setf (aref *name* tindex) (char-downcase (aref string findex)))) end)) (defun generate-tar-file-name (path) (fill *name* 0) (let ((dirs (send path :directory)) (offset 0)) (cond ((not (listp dirs)) (setq offset (add-to-*name* offset dirs))) (t (setq offset (add-to-*name* offset (first dirs))) (loop for subdir in (cdr dirs) do (setq offset (add-to-*name* offset "/")) (setq offset (add-to-*name* offset subdir))))) (setq offset (add-to-*name* offset "/")) (setq offset (add-to-*name* offset (send path :name))) (setq offset (add-to-*name* offset ".")) (setq offset (add-to-*name* offset (send path :type))))) ;(defun write-tar-file (file properties stream) ; (generate-tar-file-name (first-file)) ; (fill *mode* #\7) ; (copy-array-contents "100" *uid*) ; (copy-array-contents "100" *gid*) ; (format