#!/usr/bin/newlisp
#
# This is a test script for the overlay function of fusefile.
#
# 1) prepare a base image
# 2) set up a fusefile 
# 3) run tests
# 4) dismantle the fusefile 
# 5) remove test images


; ID is hour, minute and second values packed into a string
(constant
 'ID (apply string (3 3 (now)))
 'BASE (format "%s.raw" ID) 'SEGSZ 17000 'SEGN 40
 'FILE (join (map (fn (R) (format "%s/%d:%d" (cons BASE R)))
                  (map (curry map (curry * SEGSZ) R)
                       '((14 22) (0 3) (22 40) (3 22))))
             " ")
 'LIBC6 "/lib/x86_64-linux-gnu/libc.so.6"
 'MINE "mine"
 )
(import LIBC6 "on_exit" "int" "void*" "void*")

;; BASE is set up as a holes file with SEGN segments of size SEGSZ
(! (format "dd if=/dev/zero of=%s bs=%d seek=%d count=0 status=none"
           BASE SEGSZ SEGN))

;; Set up the fusefile
(unless (= (! (format "fusefile %s %s %s"
                      "-ononempty -oallow_other" BASE FILE)))
  (exit 1))

(println (list BASE FILE))

(define (writer CODE ADDR)
  (println "writer " (char (CODE 0)) " " ADDR)
  (let ((FD (open BASE "u")))
    (when (> FD)
      (seek FD ADDR)
      (write FD CODE)
      (close FD))))

(define (reader CODE ADDR)
  (println "reader " (char (CODE 0)) " " ADDR)
  (let ((FD (open BASE "u")) (TODO (length CODE)) (BUFFER "") (B ""))
    (if (when (> FD)
          (seek FD ADDR)
          (while (and (> TODO) (> (setf N (read FD B TODO))))
            (extend BUFFER B)
            (dec TODO (length B)))
          (close FD)
          (and (= TODO) (= CODE BUFFER)))
        (println "reader " (char (CODE 0)) " done")
      (println "reader " (char (CODE 0)) " failed")
      )))

(define (forking FN I)
  (letex ((FN FN) (CODE (dup (char I) (/ SEGSZ 2))) (ADDR (* (- I 1) SEGSZ)))
    (fork (FN CODE ADDR))))

(map wait-pid (map (curry forking writer) (sequence 1 SEGN)))
(map wait-pid (map (curry forking reader) (sequence 1 SEGN)))

;; On exit: unmount the fusefile and delete the BASE
(! (format "fusermount -u %s" BASE))
(delete-file BASE)

(exit 0)

