Code cleanup and commenting
authorRalph Ronnquist <rrq@rrq.au>
Thu, 26 Oct 2023 03:35:11 +0000 (14:35 +1100)
committerRalph Ronnquist <rrq@rrq.au>
Thu, 26 Oct 2023 03:35:11 +0000 (14:35 +1100)
merge-overlay.lsp

index ec44ba4ebe129c6138771f4b67c33a3373f0428b..8bbced0b410042f790425b12ee950b860b3697a2 100755 (executable)
@@ -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: <fusefile> <overlay>
+;
+; 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))))
       (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.