fix: resolve empty query results in WAL mode by preventing usage of encrypted WAL files

This commit is contained in:
lx1056758714-glitch
2026-01-24 11:12:17 +08:00
parent 98e702f242
commit 944b81264c
2 changed files with 17 additions and 126 deletions

View File

@@ -311,9 +311,8 @@ func (s *Service) DecryptDBFile(dbFile string) error {
outputFile.Write(data)
}
if s.conf.GetWalEnabled() {
if err := s.syncWalFiles(dbFile, output); err != nil {
log.Debug().Err(err).Msgf("failed to sync wal files for %s", dbFile)
}
// Remove WAL files if they exist to prevent SQLite from reading encrypted WALs
s.removeWalFiles(output)
}
return nil
}
@@ -324,14 +323,24 @@ func (s *Service) DecryptDBFile(dbFile string) error {
log.Debug().Msgf("Decrypted %s to %s", dbFile, output)
if s.conf.GetWalEnabled() {
if err := s.syncWalFiles(dbFile, output); err != nil {
log.Debug().Err(err).Msgf("failed to sync wal files for %s", dbFile)
}
// Remove WAL files if they exist to prevent SQLite from reading encrypted WALs
s.removeWalFiles(output)
}
return nil
}
func (s *Service) removeWalFiles(dbFile string) {
walFile := dbFile + "-wal"
shmFile := dbFile + "-shm"
if err := os.Remove(walFile); err != nil && !os.IsNotExist(err) {
log.Debug().Err(err).Msgf("failed to remove wal file %s", walFile)
}
if err := os.Remove(shmFile); err != nil && !os.IsNotExist(err) {
log.Debug().Err(err).Msgf("failed to remove shm file %s", shmFile)
}
}
func (s *Service) getDebounceTime() time.Duration {
debounce := s.conf.GetAutoDecryptDebounce()
if debounce <= 0 {
@@ -405,65 +414,6 @@ func isWalFile(path string) bool {
return strings.HasSuffix(path, ".db-wal") || strings.HasSuffix(path, ".db-shm")
}
func (s *Service) syncWalFiles(dbFile, output string) error {
walSrc := dbFile + "-wal"
walDst := output + "-wal"
if err := syncAuxFile(walSrc, walDst); err != nil {
return err
}
shmSrc := dbFile + "-shm"
shmDst := output + "-shm"
if err := syncAuxFile(shmSrc, shmDst); err != nil {
return err
}
return nil
}
func syncAuxFile(src, dst string) error {
if _, err := os.Stat(src); err != nil {
if os.IsNotExist(err) {
if err := os.Remove(dst); err != nil && !os.IsNotExist(err) {
return err
}
return nil
}
return err
}
if err := util.PrepareDir(filepath.Dir(dst)); err != nil {
return err
}
return copyFileAtomic(src, dst)
}
func copyFileAtomic(src, dst string) error {
input, err := os.Open(src)
if err != nil {
return err
}
defer input.Close()
temp := dst + ".tmp"
output, err := os.Create(temp)
if err != nil {
return err
}
if _, err := io.Copy(output, input); err != nil {
output.Close()
os.Remove(temp)
return err
}
if err := output.Sync(); err != nil {
output.Close()
os.Remove(temp)
return err
}
if err := output.Close(); err != nil {
os.Remove(temp)
return err
}
return os.Rename(temp, dst)
}
func (s *Service) DecryptDBFiles() error {
dbGroup, err := filemonitor.NewFileGroup("wechat", s.conf.GetDataDir(), `.*\.db$`, []string{"fts"})
if err != nil {
@@ -663,9 +613,8 @@ func (s *Service) IncrementalDecryptDBFile(dbFile string) (bool, error) {
s.mutex.Unlock()
}
if err := s.syncWalFiles(dbFile, output); err != nil {
return true, err
}
// Remove WAL files if they exist to prevent SQLite from reading encrypted WALs
s.removeWalFiles(output)
if applied {
return true, nil

View File

@@ -131,12 +131,6 @@ func (d *DBManager) OpenDB(path string) (*sql.DB, error) {
log.Err(err).Msgf("获取临时拷贝文件 %s 失败", path)
return nil, err
}
if d.walEnabled {
if err := d.syncWalFiles(path, tempPath); err != nil {
log.Err(err).Msgf("同步 WAL 文件失败: %s", path)
return nil, err
}
}
}
db, err = sql.Open("sqlite3", tempPath)
if err != nil {
@@ -187,58 +181,6 @@ func (d *DBManager) Close() error {
return d.fm.Stop()
}
func (d *DBManager) syncWalFiles(dbPath, tempPath string) error {
if err := syncAuxFile(dbPath+"-wal", tempPath+"-wal"); err != nil {
return err
}
if err := syncAuxFile(dbPath+"-shm", tempPath+"-shm"); err != nil {
return err
}
return nil
}
func syncAuxFile(src, dst string) error {
if _, err := os.Stat(src); err != nil {
if os.IsNotExist(err) {
if err := os.Remove(dst); err != nil && !os.IsNotExist(err) {
return err
}
return nil
}
return err
}
return copyFileAtomic(src, dst)
}
func copyFileAtomic(src, dst string) error {
input, err := os.Open(src)
if err != nil {
return err
}
defer input.Close()
temp := dst + ".tmp"
output, err := os.Create(temp)
if err != nil {
return err
}
if _, err := io.Copy(output, input); err != nil {
output.Close()
os.Remove(temp)
return err
}
if err := output.Sync(); err != nil {
output.Close()
os.Remove(temp)
return err
}
if err := output.Close(); err != nil {
os.Remove(temp)
return err
}
return os.Rename(temp, dst)
}
func normalizeDBPath(path string) string {
if strings.HasSuffix(path, "-wal") || strings.HasSuffix(path, "-shm") {
return strings.TrimSuffix(strings.TrimSuffix(path, "-wal"), "-shm")