mirror of
https://github.com/hackdiaz-dev/free-turn-proxy.git
synced 2026-10-12 09:41:53 +02:00
fix(clients): фиксировать базу на диск через fsync
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
||||
"maps"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
@@ -142,10 +143,13 @@ func (db *DB) save(next Data) error {
|
||||
}
|
||||
|
||||
tmpFile := db.path + ".tmp"
|
||||
err = os.WriteFile(tmpFile, b, 0o600) // 0o600: файл содержит Client ID токены авторизации
|
||||
err = writeSync(tmpFile, b)
|
||||
if err == nil {
|
||||
err = os.Rename(tmpFile, db.path)
|
||||
}
|
||||
if err == nil {
|
||||
syncDir(filepath.Dir(db.path))
|
||||
}
|
||||
if err == nil {
|
||||
// Авторизация меняется только после успешной замены файла.
|
||||
db.data = next
|
||||
@@ -157,6 +161,32 @@ func (db *DB) save(next Data) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func writeSync(path string, b []byte) error {
|
||||
f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o600) // 0o600: файл содержит Client ID токены авторизации
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = f.Write(b); err == nil {
|
||||
err = f.Sync()
|
||||
}
|
||||
if closeErr := f.Close(); err == nil {
|
||||
err = closeErr
|
||||
}
|
||||
if err != nil {
|
||||
_ = os.Remove(path)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func syncDir(dir string) {
|
||||
d, err := os.Open(dir)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_ = d.Sync()
|
||||
_ = d.Close()
|
||||
}
|
||||
|
||||
// Тег режима едет хвостом той же записи: клиент до этого поля его не писал, а читатель
|
||||
// брал ровно 1+len байт - лишний байт старый сервер молча пропускает.
|
||||
const (
|
||||
|
||||
@@ -14,11 +14,11 @@ func TestFailedSavePreservesAuthorization(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := db.Add("existing", "original"); err != nil {
|
||||
if err = db.Add("existing", "original"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// Каталог вместо временного файла воспроизводит отказ записи без прав root.
|
||||
if err := os.Mkdir(path+".tmp", 0o700); err != nil {
|
||||
if err = os.Mkdir(path+".tmp", 0o700); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
operations := []struct {
|
||||
@@ -31,7 +31,7 @@ func TestFailedSavePreservesAuthorization(t *testing.T) {
|
||||
}
|
||||
for _, op := range operations {
|
||||
t.Run(op.name, func(t *testing.T) {
|
||||
if err := op.run(); err == nil {
|
||||
if runErr := op.run(); runErr == nil {
|
||||
t.Fatal("save unexpectedly succeeded")
|
||||
}
|
||||
if !db.IsAuthorized("existing") || db.IsAuthorized("new") {
|
||||
|
||||
Reference in New Issue
Block a user