Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/MHSanaei/3x-ui.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--database/db.go27
-rw-r--r--web/service/server.go25
2 files changed, 46 insertions, 6 deletions
diff --git a/database/db.go b/database/db.go
index 6de81d79..6b579dd9 100644
--- a/database/db.go
+++ b/database/db.go
@@ -4,6 +4,7 @@ package database
import (
"bytes"
+ "errors"
"io"
"io/fs"
"log"
@@ -199,3 +200,29 @@ func Checkpoint() error {
}
return nil
}
+
+// ValidateSQLiteDB opens the provided sqlite DB path with a throw-away connection
+// and runs a PRAGMA integrity_check to ensure the file is structurally sound.
+// It does not mutate global state or run migrations.
+func ValidateSQLiteDB(dbPath string) error {
+ if _, err := os.Stat(dbPath); err != nil { // file must exist
+ return err
+ }
+ gdb, err := gorm.Open(sqlite.Open(dbPath), &gorm.Config{Logger: logger.Discard})
+ if err != nil {
+ return err
+ }
+ sqlDB, err := gdb.DB()
+ if err != nil {
+ return err
+ }
+ defer sqlDB.Close()
+ var res string
+ if err := gdb.Raw("PRAGMA integrity_check;").Scan(&res).Error; err != nil {
+ return err
+ }
+ if res != "ok" {
+ return errors.New("sqlite integrity check failed: " + res)
+ }
+ return nil
+}
diff --git a/web/service/server.go b/web/service/server.go
index eb261c88..b7cfc3a7 100644
--- a/web/service/server.go
+++ b/web/service/server.go
@@ -942,13 +942,26 @@ func (s *ServerService) ImportDB(file multipart.File) error {
return common.NewErrorf("Error saving db: %v", err)
}
- // Check if we can init the db or not
- if err = database.InitDB(tempPath); err != nil {
- return common.NewErrorf("Error checking db: %v", err)
+ // Close temp file before opening via sqlite
+ if err = tempFile.Close(); err != nil {
+ return common.NewErrorf("Error closing temporary db file: %v", err)
}
+ tempFile = nil
- // Stop Xray
- s.StopXrayService()
+ // Validate integrity (no migrations / side effects)
+ if err = database.ValidateSQLiteDB(tempPath); err != nil {
+ return common.NewErrorf("Invalid or corrupt db file: %v", err)
+ }
+
+ // Stop Xray (ignore error but log)
+ if errStop := s.StopXrayService(); errStop != nil {
+ logger.Warningf("Failed to stop Xray before DB import: %v", errStop)
+ }
+
+ // Close existing DB to release file locks (especially on Windows)
+ if errClose := database.CloseDB(); errClose != nil {
+ logger.Warningf("Failed to close existing DB before replacement: %v", errClose)
+ }
// Backup the current database for fallback
fallbackPath := fmt.Sprintf("%s.backup", config.GetDBPath())
@@ -983,7 +996,7 @@ func (s *ServerService) ImportDB(file multipart.File) error {
return common.NewErrorf("Error moving db file: %v", err)
}
- // Migrate DB
+ // Open & migrate new DB
if err = database.InitDB(config.GetDBPath()); err != nil {
if errRename := os.Rename(fallbackPath, config.GetDBPath()); errRename != nil {
return common.NewErrorf("Error migrating db and restoring fallback: %v", errRename)