File: merge-overlay.lsp

package info (click to toggle)
fusefile 2.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 168 kB
  • sloc: ansic: 976; lisp: 194; makefile: 28; sh: 25
file content (144 lines) | stat: -rwxr-xr-x 4,945 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#!/usr/bin/newlisp

; 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.

; (die ...) - function to drop a note to stderr and exit with 1.
(define (die)
  (write-line 2 (join (map string (args)) " "))
  (exit 1))

; (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)) 
      (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 "unsigned long."))
    OUT))

; (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"))
      (dec SIZE (length BUFFER))
      (while (and (> (length BUFFER))
                  (setf N (write FF.fd BUFFER (length BUFFER))))
        (setf BUFFER (N BUFFER)))
      (when (> (length BUFFER)) (die "Failed writing" AT SIZE ))
      )))

;=== Main program

; Require 2 command line arguments, afterinterpreter and script file.
(when (!= (length (main-args)) 4)
  (die "Requires arguments: fusefile overlay"))

; 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))
 )

; Confirm expected file size for overlay
(unless (= OL.end (+ FF.end 8 (* OL.N 16)))
  (die OVERLAY "should be" OL.end "bytes"))

; 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))))

(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.