#!/bin/env tclsh package require sha256 package require sqlite3 proc readbak {path} { set fd [open $path rb] set magic [read $fd 6] if {$magic != "AMEBAK"} { close $fd return -code error "invalid magic string: \"$magic\"" } set ver [read $fd 1] binary scan $ver c ver if {$ver != 0} { close $fd return -code error "archive file too new: $ver (self: 0)" } set mode [read $fd 1] switch -- $mode { r {} F { zlib push inflate $fd -level 9 } default { close $fd return -code error "unknown compression mode: $mode" } } set ret [read $fd] close $fd return $ret } proc readstore {store hash} { set hexhash [binary encode hex $hash] set path $store append path "/[string range $hexhash 0 1]" append path "/[string range $hexhash 2 3]" append path "/[string range $hexhash 4 5]/" append path "/[string range $hexhash 6 end]" if {[file exists $path]} { return [readbak $path] } else { return -code error "missing file" } } proc writebak {path data} { set bench [string range $data 0 10000000] binary scan $bench c _ set Fbench [zlib deflate $bench 9] set fd [open $path wb] puts -nonewline $fd "AMEBAK\0" if {[string length $Fbench] < ([string length $bench] * 95 / 100)} { puts -nonewline $fd "F" zlib push deflate $fd -level 9 } else { puts -nonewline $fd "r" } puts -nonewline $fd $data close $fd } proc writestore {store data} { set hash [::sha2::sha256 -bin -- $data] set hexhash [binary encode hex $hash] set path $store append path "/[string range $hexhash 0 1]" append path "/[string range $hexhash 2 3]" append path "/[string range $hexhash 4 5]/" file mkdir $path set path "$path/[string range $hexhash 6 end]" if {![file exists $path]} { writebak $path $data } return $hash }