@@ -5,56 +5,37 @@ import (
5
5
"context"
6
6
_ "embed"
7
7
"encoding/binary"
8
- "strconv"
9
8
10
9
"github.com/tetratelabs/wazero/api"
11
10
12
11
"github.com/ncruces/go-sqlite3/internal/util"
13
12
"github.com/ncruces/go-sqlite3/util/sql3util"
14
13
)
15
14
16
- func cksmWrapFile (name * Filename , flags OpenFlag , file File ) File {
17
- // Checksum only main databases and WALs .
18
- if flags & ( OPEN_MAIN_DB | OPEN_WAL ) == 0 {
15
+ func cksmWrapFile (file File , flags OpenFlag ) File {
16
+ // Checksum only main databases.
17
+ if flags & OPEN_MAIN_DB == 0 {
19
18
return file
20
19
}
21
-
22
- cksm := cksmFile {File : file }
23
-
24
- if flags & OPEN_WAL != 0 {
25
- main , _ := name .DatabaseFile ().(cksmFile )
26
- cksm .cksmFlags = main .cksmFlags
27
- } else {
28
- cksm .cksmFlags = new (cksmFlags )
29
- cksm .isDB = true
30
- }
31
-
32
- return cksm
20
+ return & cksmFile {File : file }
33
21
}
34
22
35
23
type cksmFile struct {
36
24
File
37
- * cksmFlags
38
- isDB bool
39
- }
40
-
41
- type cksmFlags struct {
42
- computeCksm bool
43
25
verifyCksm bool
44
- inCkpt bool
45
- pageSize int
26
+ computeCksm bool
46
27
}
47
28
48
- func (c cksmFile ) ReadAt (p []byte , off int64 ) (n int , err error ) {
29
+ func (c * cksmFile ) ReadAt (p []byte , off int64 ) (n int , err error ) {
49
30
n , err = c .File .ReadAt (p , off )
50
31
p = p [:n ]
51
32
52
- if isHeader (c . isDB , p , off ) {
33
+ if isHeader (p , off ) {
53
34
c .init ((* [100 ]byte )(p ))
54
35
}
55
36
56
37
// Verify checksums.
57
- if c .verifyCksm && ! c . inCkpt && len (p ) == c . pageSize {
38
+ if c .verifyCksm && sql3util . ValidPageSize ( len (p )) {
58
39
cksm1 := cksmCompute (p [:len (p )- 8 ])
59
40
cksm2 := * (* [8 ]byte )(p [len (p )- 8 :])
60
41
if cksm1 != cksm2 {
@@ -64,20 +45,20 @@ func (c cksmFile) ReadAt(p []byte, off int64) (n int, err error) {
64
45
return n , err
65
46
}
66
47
67
- func (c cksmFile ) WriteAt (p []byte , off int64 ) (n int , err error ) {
68
- if isHeader (c . isDB , p , off ) {
48
+ func (c * cksmFile ) WriteAt (p []byte , off int64 ) (n int , err error ) {
49
+ if isHeader (p , off ) {
69
50
c .init ((* [100 ]byte )(p ))
70
51
}
71
52
72
53
// Compute checksums.
73
- if c .computeCksm && ! c . inCkpt && len (p ) == c . pageSize {
54
+ if c .computeCksm && sql3util . ValidPageSize ( len (p )) {
74
55
* (* [8 ]byte )(p [len (p )- 8 :]) = cksmCompute (p [:len (p )- 8 ])
75
56
}
76
57
77
58
return c .File .WriteAt (p , off )
78
59
}
79
60
80
- func (c cksmFile ) Pragma (name string , value string ) (string , error ) {
61
+ func (c * cksmFile ) Pragma (name string , value string ) (string , error ) {
81
62
switch name {
82
63
case "checksum_verification" :
83
64
b , ok := sql3util .ParseBool (value )
@@ -90,29 +71,24 @@ func (c cksmFile) Pragma(name string, value string) (string, error) {
90
71
return "1" , nil
91
72
92
73
case "page_size" :
93
- if c .computeCksm {
74
+ if c .computeCksm && value != "" {
94
75
// Do not allow page size changes on a checksum database.
95
- return strconv . Itoa ( c . pageSize ) , nil
76
+ return "" , nil
96
77
}
97
78
}
98
79
return "" , _NOTFOUND
99
80
}
100
81
101
- func (c cksmFile ) DeviceCharacteristics () DeviceCharacteristic {
82
+ func (c * cksmFile ) DeviceCharacteristics () DeviceCharacteristic {
102
83
ret := c .File .DeviceCharacteristics ()
103
84
if c .verifyCksm {
104
85
ret &^= IOCAP_SUBPAGE_READ
105
86
}
106
87
return ret
107
88
}
108
89
109
- func (c cksmFile ) fileControl (ctx context.Context , mod api.Module , op _FcntlOpcode , pArg ptr_t ) _ErrorCode {
110
- switch op {
111
- case _FCNTL_CKPT_START :
112
- c .inCkpt = true
113
- case _FCNTL_CKPT_DONE :
114
- c .inCkpt = false
115
- case _FCNTL_PRAGMA :
90
+ func (c * cksmFile ) fileControl (ctx context.Context , mod api.Module , op _FcntlOpcode , pArg ptr_t ) _ErrorCode {
91
+ if op == _FCNTL_PRAGMA {
116
92
rc := vfsFileControlImpl (ctx , mod , c , op , pArg )
117
93
if rc != _NOTFOUND {
118
94
return rc
@@ -121,24 +97,26 @@ func (c cksmFile) fileControl(ctx context.Context, mod api.Module, op _FcntlOpco
121
97
return vfsFileControlImpl (ctx , mod , c .File , op , pArg )
122
98
}
123
99
124
- func (f * cksmFlags ) init (header * [100 ]byte ) {
125
- f .pageSize = 256 * int (binary .LittleEndian .Uint16 (header [16 :18 ]))
126
- if r := header [20 ] == 8 ; r != f .computeCksm {
127
- f .computeCksm = r
128
- f .verifyCksm = r
129
- }
130
- if ! sql3util .ValidPageSize (f .pageSize ) {
131
- f .computeCksm = false
132
- f .verifyCksm = false
100
+ func (c * cksmFile ) init (header * [100 ]byte ) {
101
+ if r := header [20 ] == 8 ; r != c .computeCksm {
102
+ c .computeCksm = r
103
+ c .verifyCksm = r
133
104
}
134
105
}
135
106
136
- func isHeader (isDB bool , p []byte , off int64 ) bool {
137
- check := sql3util .ValidPageSize (len (p ))
138
- if isDB {
139
- check = off == 0 && len (p ) >= 100
107
+ func (c * cksmFile ) SharedMemory () SharedMemory {
108
+ if f , ok := c .File .(FileSharedMemory ); ok {
109
+ return f .SharedMemory ()
140
110
}
141
- return check && bytes .HasPrefix (p , []byte ("SQLite format 3\000 " ))
111
+ return nil
112
+ }
113
+
114
+ func (c * cksmFile ) Unwrap () File {
115
+ return c .File
116
+ }
117
+
118
+ func isHeader (p []byte , off int64 ) bool {
119
+ return off == 0 && len (p ) >= 100 && bytes .HasPrefix (p , []byte ("SQLite format 3\000 " ))
142
120
}
143
121
144
122
func cksmCompute (a []byte ) (cksm [8 ]byte ) {
@@ -155,14 +133,3 @@ func cksmCompute(a []byte) (cksm [8]byte) {
155
133
binary .LittleEndian .PutUint32 (cksm [4 :8 ], s2 )
156
134
return
157
135
}
158
-
159
- func (c cksmFile ) SharedMemory () SharedMemory {
160
- if f , ok := c .File .(FileSharedMemory ); ok {
161
- return f .SharedMemory ()
162
- }
163
- return nil
164
- }
165
-
166
- func (c cksmFile ) Unwrap () File {
167
- return c .File
168
- }
0 commit comments