From e42da68425826674df286895b69837eca292550c Mon Sep 17 00:00:00 2001 From: Ralph Ronnquist Date: Thu, 26 Oct 2023 14:35:11 +1100 Subject: [PATCH] Code cleanup and commenting --- merge-overlay.lsp | 138 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 107 insertions(+), 31 deletions(-) diff --git a/merge-overlay.lsp b/merge-overlay.lsp index ec44ba4..8bbced0 100755 --- a/merge-overlay.lsp +++ b/merge-overlay.lsp @@ -1,41 +1,55 @@ #!/usr/bin/newlisp -; -; Copy from a fusefile overlay file onto a fusefile. This may be done -; so as to "merge down" an overlay in an overlay stack. Eg, assume the -; original fusefile had overlay stack A:B:C then C could be merged -; onto an A:B stack, or B merged onto A; the latter allowing a -; subsequent A:C stack corresponding to previous A:B:C. +; Utility to copy from a previous overlay file onto a current +; fusefile. This would typically be done so as to "merge down" an +; overlay in an old fusefile overlay stack after having retired that +; stack. (There is an illustration example at the end of this file) ; ; Arguments: +; +; Technically this uitility merely "replays" the writes (in order of +; increasing position rather than their actual time order) that have +; been collated into an overlay file. It writes this into a file or +; fusefile that represents what the basis was when the writes +; happened. -(map set '(FUSEFILE OVERLAY) (-2 (main-args))) - -(setf FF.fd (open FUSEFILE "u") OL.fd (open OVERLAY "r")) - +; (die ...) - function to drop a note to stderr and exit with 1. (define (die) (write-line 2 (join (map string (args)) " ")) (exit 1)) -; Read N unsigned 64-bit integers from OL.fd, returned as a list of them. -(define (rd-uint64 FD N) +; (read-uint64 FD N) - function to read N consequtive unsigned long from +; file descriptor FD. Return them as a list in order +(define (read-uint64 FD N) (let ((B (* N 8)) (BUFFER nil) (HEAD "") (OUT '())) + ;; B = number of bytes to read + ;; BUFFER = input buffer symbol + ;; HEAD = prefix of bytes read but not processed + ;; OUT = list of unsigned long to return + ;; + ;; Note that (read..) might return fewer bytes than asked for so + ;; it needs a loop. (while (and (> B) (> (read FD BUFFER B))) - (dec B (length BUFFER)) + (dec B (length BUFFER)) (extend HEAD BUFFER) (let ((I (/ (length HEAD) 8))) (when (> I) (extend OUT (unpack (dup "Lu" ) HEAD)) (setf HEAD ((* 8 I) HEAD))))) - (when (> B) (die "Cannot read" N "table entries")) + (when (> B) (die "Cannot read" N "unsigned long.")) OUT)) -(define (copy-data AT SIZE) +; (copy-data AT SIZE) - copy the data block of SIZE bytes at position +; AT from OL.fd to FF.fd. +(define (copy-data AT SIZE) ; FUSEFILE FF.fd OVERLAY OL.fd (let ((BUFFER nil) (N 0)) + ;; BUFEER = transfer buffer symbol + ;; N = number of bytes written upon each (write...) (when (null? (seek FF.fd AT)) (die "Cannot seek" FUSEFILE AT)) (when (null? (seek OL.fd AT)) (die "Cannot seek" OVERLAY AT)) (while (> SIZE) - (when (<= (read OL.fd BUFFER SIZE)) (die "Failed reading" SIZE "bytes")) + (when (<= (read OL.fd BUFFER SIZE)) + (die "Failed reading" SIZE "bytes")) (dec SIZE (length BUFFER)) (while (and (> (length BUFFER)) (setf N (write FF.fd BUFFER (length BUFFER)))) @@ -43,26 +57,88 @@ (when (> (length BUFFER)) (die "Failed writing" AT SIZE )) ))) -(when (< FF.fd) (die "Cannot open" FUSEFILE)) -(when (< OL.fd) (die "Cannot open" OVERLAY)) - -(when (null? (seek OL.fd (setf P (file-info FUSEFILE 0)))) - (die "Seek error:" P)) +;=== Main program -(setf N (rd-uint64 OL.fd 1)) -(when (null? N) (die "Cannot read" OVERLAY "table count.")) -(setf N (N 0)) +; Require 2 command line arguments, afterinterpreter and script file. +(when (!= (length (main-args)) 4) + (die "Requires arguments: fusefile overlay")) -; Check size -(when (!= (+ P 8 (* N 16)) (file-info OVERLAY 0)) - (die "Wrong size for " OVERLAY "which should be" (+ P 8 (* N 16)))) +; Set up globals +(setf + FUSEFILE (main-args -2) + FF.fd (if (open FUSEFILE "u") $it (die "Cannot open" FUSEFILE)) + FF.end (file-info FUSEFILE 0) + OVERLAY (main-args -1) + OL.fd (if (open OVERLAY "r") $it (die "Cannot open" OVERLAY)) + OL.end (file-info OVERLAY 0) + OL.N (if (seek OL.fd FF.end) + (if (read-uint64 OL.fd 1) ($it 0) + (die "Cannot read" OVERLAY "table count.")) + (die "Cannot seek" OVERLY "to" FF.end)) + ) -(setf TABLE (rd-uint64 OL.fd (* 2 N))) -(when (null? TABLE) (die "Cannot read" OVERLAY "table")) +; Confirm expected file size for overlay +(unless (= OL.end (+ FF.end 8 (* OL.N 16))) + (die OVERLAY "should be" OL.end "bytes")) -(dolist (ENTRY (explode TABLE 2)) +; Load the overlay table and copy data according to its entries +(dolist (ENTRY (explode + (if (read-uint64 OL.fd (* 2 OL.N)) $it + (die "Cannot read overlay table from" OVERLAY)) + 2)) + ;; ENTRY = (begin end) for data block (println (format "copy %s/%d:%d" (cons OVERLAY ENTRY))) (copy-data (ENTRY 0) (- (ENTRY 1) (ENTRY 0)))) -"dumpoverlay.lsp" (exit 0) +"dumpoverlay.lsp" + +; E.g., consider a fusefile stack D:A:B:C with overlays A:B:C over D. +; That stack would have been built in a succession of first using +; stack D:A where changes are collated into overlay A, as in the +; following setup: +; +; $ fusefile E -overlay:A D +; ... writes to E (= D:A) goes into A +; $ fusermount -u E +; +; Note that the "D" part might in reality be a more complex +; composition of several file fragments, but in these examples we +; refer to it simply as "D". +; +; Continuing the example, the new stack D:A:B is used for collating +; further changes into B, as in the following setup: +; +; $ fusefile E -overlay:A:B D +; ... writes to E (= D:A:B) actually goes into B +; $ fusermount -u E +; +; Later again, the stack D:A:B:C is used for collating changes into C, +; as in the following setup: +; +; $ fusefile E -overlay:A:B:C D +; ... writes to E (= D:A:B:C) actually goes into C +; ... +; $ fusermount -u D +; +; At that point, one may decide to merge down the overlay C onto a +; D:A:B fusefile and thereby add the C changes over B. +; +; $ fusefile E -overlay:A:B D +; $ merge-overlay E C +; $ rm C +; $ fusermount -u E +; +; Or alternatively, one may decide to merge down the B changes without +; C onto a D:A fusefile and thereby add B to A. +; +; $ fusefile E -overlay:A D +; $ merge-overlay E B +; $ rm B +; $ fusermount -u E +; +; In the latter case the updated overlay A includes the writes +; collated in B and thus now the stack D:A:C would be the same as the +; previous stack D:A:B:C. +; +; End of example. -- 2.39.2