[functional tests] first steps in parsing the binary format.
This commit is contained in:
parent
397d2006a5
commit
c90a7b9e2f
151
functional-tests/check-superblock.scm
Normal file
151
functional-tests/check-superblock.scm
Normal file
@ -0,0 +1,151 @@
|
||||
(import
|
||||
(fmt fmt)
|
||||
(matchable))
|
||||
|
||||
;;;;---------------------------------------------------
|
||||
;;;; Constants
|
||||
;;;;---------------------------------------------------
|
||||
|
||||
;; FIXME: duplicate with main.scm
|
||||
(define (current-metadata)
|
||||
"./metadata.bin")
|
||||
|
||||
(define metadata-block-size 4096)
|
||||
(define superblock-magic 27022010)
|
||||
(define superblock-salt 160774)
|
||||
(define uuid-size 16)
|
||||
(define space-map-root-size 128)
|
||||
|
||||
;;;;---------------------------------------------------
|
||||
;;;; Metadata IO
|
||||
;;;;---------------------------------------------------
|
||||
|
||||
(define (open-metadata path)
|
||||
(open-file-input-port path (file-options) (buffer-mode none)))
|
||||
|
||||
(define-syntax with-metadata
|
||||
(syntax-rules ()
|
||||
((_ (port path) body ...) (let ((port (open-metadata path)))
|
||||
(dynamic-wind
|
||||
(lambda () #f)
|
||||
(lambda () body ...)
|
||||
(lambda () (close-port port)))))))
|
||||
|
||||
;; FIXME: return our own condition?
|
||||
(define (io-error msg)
|
||||
(raise (condition
|
||||
(make-error)
|
||||
(make-message-condition msg))))
|
||||
|
||||
;;; Returns a 4k bytevector
|
||||
(define (read-block port b)
|
||||
(set-port-position! port (* b metadata-block-size))
|
||||
(let ((data (get-bytevector-n port metadata-block-size)))
|
||||
(unless (and (not (eof-object? data))
|
||||
(= metadata-block-size (bytevector-length data)))
|
||||
(io-error (fmt #f (dsp "unable to read metadata block: ") (num b))))
|
||||
data))
|
||||
|
||||
;;;;---------------------------------------------------
|
||||
;;;; CRC32
|
||||
;;;;---------------------------------------------------
|
||||
|
||||
;; FIXME: move to own library
|
||||
(load-shared-object "libz.so")
|
||||
(define crc32
|
||||
(foreign-procedure "crc32" (unsigned-long u8* unsigned-int) unsigned-long))
|
||||
|
||||
(define crc32-combine
|
||||
(foreign-procedure "crc32_combine" (unsigned-long unsigned-long unsigned-long) unsigned-long))
|
||||
|
||||
;; FIXME: stop copying the bytevector. I'm not sure how to pass an offset into
|
||||
;; the bv.
|
||||
(define (crc32-region salt bv start end)
|
||||
(assert (< start end))
|
||||
(let ((len (- end start)))
|
||||
(let ((copy (make-bytevector len)))
|
||||
(bytevector-copy! bv start copy 0 len)
|
||||
(let ((crc (crc32 salt copy 0)))
|
||||
(crc32 crc copy len)))))
|
||||
|
||||
;;;;---------------------------------------------------
|
||||
;;;; Decoding
|
||||
;;;;---------------------------------------------------
|
||||
|
||||
(define-syntax unpack-type
|
||||
(syntax-rules (le32 le64 bytes)
|
||||
((_ bv offset le32)
|
||||
(bytevector-u32-ref bv offset (endianness little)))
|
||||
|
||||
((_ bv offset le64)
|
||||
(bytevector-u64-ref bv offset (endianness little)))
|
||||
|
||||
((_ bv offset (bytes count))
|
||||
(let ((copy (make-bytevector count)))
|
||||
(bytevector-copy! bv offset copy 0 count)
|
||||
copy))))
|
||||
|
||||
(define (size-type t)
|
||||
(syntax->datum
|
||||
(syntax-case t (le32 le64 bytes)
|
||||
(le32 #'4)
|
||||
(le64 #'8)
|
||||
((bytes count) #'count))))
|
||||
|
||||
(define-syntax binary-format
|
||||
(lambda (x)
|
||||
(syntax-case x ()
|
||||
((_ (name pack-name unpack-name) (field type) ...)
|
||||
(with-syntax ((((t o) ...)
|
||||
(let f ((acc 0) (types #'(type ...)))
|
||||
(if (null? types)
|
||||
'()
|
||||
(cons (list (car types) acc)
|
||||
(f (+ acc (size-type (car types))) (cdr types)))))))
|
||||
#'(begin
|
||||
(define-record-type name (fields field ...))
|
||||
|
||||
(define (unpack-name bv offset)
|
||||
((record-constructor (record-type-descriptor name))
|
||||
(unpack-type bv (+ offset o) t) ...))))))))
|
||||
|
||||
(binary-format (superblock pack-superblock unpack-superblock)
|
||||
(csum le32)
|
||||
(flags le32)
|
||||
(block-nr le64)
|
||||
(uuid (bytes 16))
|
||||
(magic le64)
|
||||
(version le32)
|
||||
(time le32)
|
||||
(trans-id le64)
|
||||
(metadata-snap le64)
|
||||
(data-space-map-root (bytes 128))
|
||||
(metadata-space-map-root (bytes 128))
|
||||
(data-mapping-root le64)
|
||||
(device-details-root le64)
|
||||
(data-block-size le32)
|
||||
(metadata-block-size le32)
|
||||
(metadata-nr-blocks le64)
|
||||
(compat-flags le32)
|
||||
(compat-ro-flags le32)
|
||||
(incompat-flags le32))
|
||||
|
||||
;;;;---------------------------------------------------
|
||||
;;;; Top level
|
||||
;;;;---------------------------------------------------
|
||||
|
||||
(define (check-magic sb)
|
||||
((let ((m (bytevector-u32-ref sb 32 (endianness little))))
|
||||
(fmt #t (dsp "on disk magic: ") (num m) nl)
|
||||
)))
|
||||
|
||||
(define (read-superblock)
|
||||
(with-metadata (md (current-metadata))
|
||||
(unpack-superblock (read-block md 0) 0)))
|
||||
|
||||
(define (check-superblock)
|
||||
(with-metadata (md (current-metadata))
|
||||
(let ((superblock (read-block md 0)))
|
||||
(fmt #t (dsp "checksum on disk: ") (dsp (bytevector-u32-ref superblock 0 (endianness little))) nl)
|
||||
(fmt #t (dsp "calculated checksum: ") (dsp (crc32-region superblock-salt superblock 4 4092)) nl)
|
||||
(check-magic superblock))))
|
Loading…
Reference in New Issue
Block a user