@@ -21,40 +21,33 @@ func (h *hbshVFS) Open(name string, flags vfs.OpenFlag) (vfs.File, vfs.OpenFlag,
21
21
}
22
22
23
23
func (h * hbshVFS ) OpenFilename (name * vfs.Filename , flags vfs.OpenFlag ) (file vfs.File , _ vfs.OpenFlag , err error ) {
24
- var hbsh * hbsh.HBSH
25
-
26
- // Encrypt everything except super journals.
27
- if flags & vfs .OPEN_SUPER_JOURNAL == 0 {
28
- if f , ok := name .DatabaseFile ().(* hbshFile ); ok {
29
- hbsh = f .hbsh
30
- } else {
31
- var key []byte
32
- if params := name .URIParameters (); name == nil {
33
- key = h .hbsh .KDF ("" ) // Temporary files get a random key.
34
- } else if t , ok := params ["key" ]; ok {
35
- key = []byte (t [0 ])
36
- } else if t , ok := params ["hexkey" ]; ok {
37
- key , _ = hex .DecodeString (t [0 ])
38
- } else if t , ok := params ["textkey" ]; ok {
39
- key = h .hbsh .KDF (t [0 ])
40
- }
41
- if hbsh = h .hbsh .HBSH (key ); hbsh == nil {
42
- // Can't open without a valid key.
43
- return nil , flags , sqlite3 .CANTOPEN
44
- }
45
- }
46
- }
47
-
48
24
if h , ok := h .VFS .(vfs.VFSFilename ); ok {
49
25
file , flags , err = h .OpenFilename (name , flags )
50
26
} else {
51
27
file , flags , err = h .Open (name .String (), flags )
52
28
}
53
- if err != nil || hbsh == nil || flags & vfs . OPEN_MEMORY != 0 {
54
- // Error, or no encryption (super journals, memory files).
29
+ // Encrypt everything except super journals and memory files.
30
+ if err != nil || flags & ( vfs . OPEN_SUPER_JOURNAL | vfs . OPEN_MEMORY ) != 0 {
55
31
return file , flags , err
56
32
}
57
- return & hbshFile {File : file , hbsh : hbsh }, flags , err
33
+
34
+ var hbsh * hbsh.HBSH
35
+ if f , ok := name .DatabaseFile ().(* hbshFile ); ok {
36
+ hbsh = f .hbsh
37
+ } else {
38
+ var key []byte
39
+ if params := name .URIParameters (); name == nil {
40
+ key = h .hbsh .KDF ("" ) // Temporary files get a random key.
41
+ } else if t , ok := params ["key" ]; ok {
42
+ key = []byte (t [0 ])
43
+ } else if t , ok := params ["hexkey" ]; ok {
44
+ key , _ = hex .DecodeString (t [0 ])
45
+ } else if t , ok := params ["textkey" ]; ok {
46
+ key = h .hbsh .KDF (t [0 ])
47
+ }
48
+ hbsh = h .hbsh .HBSH (key )
49
+ }
50
+ return & hbshFile {File : file , hbsh : hbsh , reset : h .hbsh }, flags , err
58
51
}
59
52
60
53
const (
@@ -65,11 +58,43 @@ const (
65
58
type hbshFile struct {
66
59
vfs.File
67
60
hbsh * hbsh.HBSH
61
+ reset HBSHCreator
68
62
block [blockSize ]byte
69
63
tweak [tweakSize ]byte
70
64
}
71
65
66
+ func (h * hbshFile ) Pragma (name string , value string ) (string , error ) {
67
+ var key []byte
68
+ switch name {
69
+ case "key" :
70
+ key = []byte (value )
71
+ case "hexkey" :
72
+ key , _ = hex .DecodeString (value )
73
+ case "textkey" :
74
+ key = h .reset .KDF (value )
75
+ default :
76
+ if f , ok := h .File .(vfs.FilePragma ); ok {
77
+ return f .Pragma (name , value )
78
+ }
79
+ return "" , sqlite3 .NOTFOUND
80
+ }
81
+
82
+ if h .hbsh = h .reset .HBSH (key ); h .hbsh != nil {
83
+ return "ok" , nil
84
+ }
85
+ return "" , sqlite3 .CANTOPEN
86
+ }
87
+
72
88
func (h * hbshFile ) ReadAt (p []byte , off int64 ) (n int , err error ) {
89
+ if h .hbsh == nil {
90
+ // If it's trying to read the header, pretend the file is empty,
91
+ // so the key can be specified later.
92
+ if off == 0 && len (p ) == 100 {
93
+ return 0 , io .EOF
94
+ }
95
+ return 0 , sqlite3 .CANTOPEN
96
+ }
97
+
73
98
min := (off ) &^ (blockSize - 1 ) // round down
74
99
max := (off + int64 (len (p )) + blockSize - 1 ) &^ (blockSize - 1 ) // round up
75
100
@@ -96,6 +121,10 @@ func (h *hbshFile) ReadAt(p []byte, off int64) (n int, err error) {
96
121
}
97
122
98
123
func (h * hbshFile ) WriteAt (p []byte , off int64 ) (n int , err error ) {
124
+ if h .hbsh == nil {
125
+ return 0 , sqlite3 .READONLY
126
+ }
127
+
99
128
min := (off ) &^ (blockSize - 1 ) // round down
100
129
max := (off + int64 (len (p )) + blockSize - 1 ) &^ (blockSize - 1 ) // round up
101
130
0 commit comments