Skip to content

Commit 5d14e01

Browse files
committed
Fix #304.
1 parent 342df98 commit 5d14e01

File tree

2 files changed

+34
-67
lines changed

2 files changed

+34
-67
lines changed

vfs/cksm.go

Lines changed: 33 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -5,56 +5,37 @@ import (
55
"context"
66
_ "embed"
77
"encoding/binary"
8-
"strconv"
98

109
"github.com/tetratelabs/wazero/api"
1110

1211
"github.com/ncruces/go-sqlite3/internal/util"
1312
"github.com/ncruces/go-sqlite3/util/sql3util"
1413
)
1514

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 {
1918
return file
2019
}
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}
3321
}
3422

3523
type cksmFile struct {
3624
File
37-
*cksmFlags
38-
isDB bool
39-
}
40-
41-
type cksmFlags struct {
42-
computeCksm bool
4325
verifyCksm bool
44-
inCkpt bool
45-
pageSize int
26+
computeCksm bool
4627
}
4728

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) {
4930
n, err = c.File.ReadAt(p, off)
5031
p = p[:n]
5132

52-
if isHeader(c.isDB, p, off) {
33+
if isHeader(p, off) {
5334
c.init((*[100]byte)(p))
5435
}
5536

5637
// Verify checksums.
57-
if c.verifyCksm && !c.inCkpt && len(p) == c.pageSize {
38+
if c.verifyCksm && sql3util.ValidPageSize(len(p)) {
5839
cksm1 := cksmCompute(p[:len(p)-8])
5940
cksm2 := *(*[8]byte)(p[len(p)-8:])
6041
if cksm1 != cksm2 {
@@ -64,20 +45,20 @@ func (c cksmFile) ReadAt(p []byte, off int64) (n int, err error) {
6445
return n, err
6546
}
6647

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) {
6950
c.init((*[100]byte)(p))
7051
}
7152

7253
// Compute checksums.
73-
if c.computeCksm && !c.inCkpt && len(p) == c.pageSize {
54+
if c.computeCksm && sql3util.ValidPageSize(len(p)) {
7455
*(*[8]byte)(p[len(p)-8:]) = cksmCompute(p[:len(p)-8])
7556
}
7657

7758
return c.File.WriteAt(p, off)
7859
}
7960

80-
func (c cksmFile) Pragma(name string, value string) (string, error) {
61+
func (c *cksmFile) Pragma(name string, value string) (string, error) {
8162
switch name {
8263
case "checksum_verification":
8364
b, ok := sql3util.ParseBool(value)
@@ -90,29 +71,24 @@ func (c cksmFile) Pragma(name string, value string) (string, error) {
9071
return "1", nil
9172

9273
case "page_size":
93-
if c.computeCksm {
74+
if c.computeCksm && value != "" {
9475
// Do not allow page size changes on a checksum database.
95-
return strconv.Itoa(c.pageSize), nil
76+
return "", nil
9677
}
9778
}
9879
return "", _NOTFOUND
9980
}
10081

101-
func (c cksmFile) DeviceCharacteristics() DeviceCharacteristic {
82+
func (c *cksmFile) DeviceCharacteristics() DeviceCharacteristic {
10283
ret := c.File.DeviceCharacteristics()
10384
if c.verifyCksm {
10485
ret &^= IOCAP_SUBPAGE_READ
10586
}
10687
return ret
10788
}
10889

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 {
11692
rc := vfsFileControlImpl(ctx, mod, c, op, pArg)
11793
if rc != _NOTFOUND {
11894
return rc
@@ -121,24 +97,26 @@ func (c cksmFile) fileControl(ctx context.Context, mod api.Module, op _FcntlOpco
12197
return vfsFileControlImpl(ctx, mod, c.File, op, pArg)
12298
}
12399

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
133104
}
134105
}
135106

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()
140110
}
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"))
142120
}
143121

144122
func cksmCompute(a []byte) (cksm [8]byte) {
@@ -155,14 +133,3 @@ func cksmCompute(a []byte) (cksm [8]byte) {
155133
binary.LittleEndian.PutUint32(cksm[4:8], s2)
156134
return
157135
}
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-
}

vfs/vfs.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ func vfsOpen(ctx context.Context, mod api.Module, pVfs, zPath, pFile ptr_t, flag
148148
if pOutFlags != 0 {
149149
util.Write32(mod, pOutFlags, flags)
150150
}
151-
file = cksmWrapFile(name, flags, file)
151+
file = cksmWrapFile(file, flags)
152152
vfsFileRegister(ctx, mod, pFile, file)
153153
return _OK
154154
}

0 commit comments

Comments
 (0)