;MAKE-PIECES - Make the pieces part of a BitTorrent info-hash via data-flow by CONCATENATED-STREAMs. ;Written in 2026 by Prince Trippy . ;To the extent possible under law, the author(s) have dedicated all copyright ;and related and neighboring rights to this software to the public domain worldwide. ;This software is distributed without any warranty. ;You should have received a copy of the CC0 Public Domain Dedication along with this software. ;If not, see . (defun make-pieces (dolist block &aux list) "Generate the pieces part of a BitTorrent info-hash. DOLIST is a list of pathnames and BLOCK the block size in octets. A function HASH corresponding to SHA1 operating on VECTORs must be present. The function HASH must have only one required parameter, the VECTOR to digest. This function exists as I noticed how easy a CONCATENATED-STREAM makes the task." (check-type block (integer 1)) (unwind-protect (progn (dolist (pathname dolist) (loop (restart-case (progn (push (open pathname :element-type 'octet) list) (return)) (abort () :report "Give up and return from MAKE-PIECES with NIL." (return-from make-pieces)) (continue () :report "Skip only the file in question." (return)) (use-value (filename) :report "Provide an alternative pathname to be tried." :interactive (lambda () (with-standard-io-syntax (let (*read-eval*) (list (read *query-io*))))) (setq pathname filename)) (store-value (use-value) :report "Provide an expression for an open stream to be used instead." :interactive (lambda () (with-standard-io-syntax (list (eval (read *query-io*))))) (push use-value list) (return))))) (setq list (nreverse list)) (with-open-stream (stream (apply 'make-concatenated-stream list)) (loop :with vector := (make-array block :element-type 'octet) :for count := (read-sequence vector stream) :until (zerop count) :if (= count block) :collect (hash vector) :else :collect (hash (make-array count :element-type 'octet :displaced-to vector :displaced-index-offset 0))))) (mapc 'close list))) .