From b6a74904ab5aee2997623206c53d981e9dc6d9fa Mon Sep 17 00:00:00 2001 From: tidwall Date: Thu, 1 Apr 2021 10:23:25 -0700 Subject: [PATCH] Fixes issue where a partial write can corrupt the database --- buntdb.go | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/buntdb.go b/buntdb.go index 9f17322..6e612a7 100644 --- a/buntdb.go +++ b/buntdb.go @@ -1176,7 +1176,25 @@ func (tx *Tx) Commit() error { // Flushing the buffer only once per transaction. // If this operation fails then the write did failed and we must // rollback. - if _, err = tx.db.file.Write(tx.db.buf); err != nil { + var n int + n, err = tx.db.file.Write(tx.db.buf) + if err != nil { + if n > 0 { + // There was a partial write to disk. + // We are possibly out of disk space. + // Delete the partially written bytes from the data file by + // seeking to the previously known position and performing + // a truncate operation. + // At this point a syscall failure is fatal and the process + // should be killed to avoid corrupting the file. + pos, err := tx.db.file.Seek(-int64(n), 1) + if err != nil { + panic(err) + } + if err := tx.db.file.Truncate(pos); err != nil { + panic(err) + } + } tx.rollbackInner() } if tx.db.config.SyncPolicy == Always {