Browse Source

fix: Restore from .db file fails (#2988)

* fix: issue 2953. Restore from .db file fails because

* Update server.go
Columbiysky 3 weeks ago
parent
commit
3666d1193f
1 changed files with 108 additions and 101 deletions
  1. 108 101
      web/service/server.go

+ 108 - 101
web/service/server.go

@@ -302,25 +302,22 @@ func (s *ServerService) GetXrayVersions() ([]string, error) {
 	return versions, nil
 	return versions, nil
 }
 }
 
 
-func (s *ServerService) StopXrayService() (string error) {
+func (s *ServerService) StopXrayService() error {
 	err := s.xrayService.StopXray()
 	err := s.xrayService.StopXray()
 	if err != nil {
 	if err != nil {
 		logger.Error("stop xray failed:", err)
 		logger.Error("stop xray failed:", err)
 		return err
 		return err
 	}
 	}
-
 	return nil
 	return nil
 }
 }
 
 
-func (s *ServerService) RestartXrayService() (string error) {
+func (s *ServerService) RestartXrayService() error {
 	s.xrayService.StopXray()
 	s.xrayService.StopXray()
-	defer func() {
-		err := s.xrayService.RestartXray(true)
-		if err != nil {
-			logger.Error("start xray failed:", err)
-		}
-	}()
-
+	err := s.xrayService.RestartXray(true)
+	if err != nil {
+		logger.Error("start xray failed:", err)
+		return err
+	}
 	return nil
 	return nil
 }
 }
 
 
@@ -507,35 +504,43 @@ func (s *ServerService) ImportDB(file multipart.File) error {
 		return common.NewErrorf("Error resetting file reader: %v", err)
 		return common.NewErrorf("Error resetting file reader: %v", err)
 	}
 	}
 
 
-	// Save the file as temporary file
+	// Save the file as a temporary file
 	tempPath := fmt.Sprintf("%s.temp", config.GetDBPath())
 	tempPath := fmt.Sprintf("%s.temp", config.GetDBPath())
-	// Remove the existing fallback file (if any) before creating one
-	_, err = os.Stat(tempPath)
-	if err == nil {
-		errRemove := os.Remove(tempPath)
-		if errRemove != nil {
+
+	// Remove the existing temporary file (if any)
+	if _, err := os.Stat(tempPath); err == nil {
+		if errRemove := os.Remove(tempPath); errRemove != nil {
 			return common.NewErrorf("Error removing existing temporary db file: %v", errRemove)
 			return common.NewErrorf("Error removing existing temporary db file: %v", errRemove)
 		}
 		}
 	}
 	}
+
 	// Create the temporary file
 	// Create the temporary file
 	tempFile, err := os.Create(tempPath)
 	tempFile, err := os.Create(tempPath)
 	if err != nil {
 	if err != nil {
 		return common.NewErrorf("Error creating temporary db file: %v", err)
 		return common.NewErrorf("Error creating temporary db file: %v", err)
 	}
 	}
-	defer tempFile.Close()
 
 
-	// Remove temp file before returning
-	defer os.Remove(tempPath)
+	// Robust deferred cleanup for the temporary file
+	defer func() {
+		if tempFile != nil {
+			if cerr := tempFile.Close(); cerr != nil {
+				logger.Warningf("Warning: failed to close temp file: %v", cerr)
+			}
+		}
+		if _, err := os.Stat(tempPath); err == nil {
+			if rerr := os.Remove(tempPath); rerr != nil {
+				logger.Warningf("Warning: failed to remove temp file: %v", rerr)
+			}
+		}
+	}()
 
 
 	// Save uploaded file to temporary file
 	// Save uploaded file to temporary file
-	_, err = io.Copy(tempFile, file)
-	if err != nil {
+	if _, err = io.Copy(tempFile, file); err != nil {
 		return common.NewErrorf("Error saving db: %v", err)
 		return common.NewErrorf("Error saving db: %v", err)
 	}
 	}
 
 
-	// Check if we can init db or not
-	err = database.InitDB(tempPath)
-	if err != nil {
+	// Check if we can init the db or not
+	if err = database.InitDB(tempPath); err != nil {
 		return common.NewErrorf("Error checking db: %v", err)
 		return common.NewErrorf("Error checking db: %v", err)
 	}
 	}
 
 
@@ -544,111 +549,113 @@ func (s *ServerService) ImportDB(file multipart.File) error {
 
 
 	// Backup the current database for fallback
 	// Backup the current database for fallback
 	fallbackPath := fmt.Sprintf("%s.backup", config.GetDBPath())
 	fallbackPath := fmt.Sprintf("%s.backup", config.GetDBPath())
+
 	// Remove the existing fallback file (if any)
 	// Remove the existing fallback file (if any)
-	_, err = os.Stat(fallbackPath)
-	if err == nil {
-		errRemove := os.Remove(fallbackPath)
-		if errRemove != nil {
+	if _, err := os.Stat(fallbackPath); err == nil {
+		if errRemove := os.Remove(fallbackPath); errRemove != nil {
 			return common.NewErrorf("Error removing existing fallback db file: %v", errRemove)
 			return common.NewErrorf("Error removing existing fallback db file: %v", errRemove)
 		}
 		}
 	}
 	}
+
 	// Move the current database to the fallback location
 	// Move the current database to the fallback location
-	err = os.Rename(config.GetDBPath(), fallbackPath)
-	if err != nil {
-		return common.NewErrorf("Error backing up temporary db file: %v", err)
+	if err = os.Rename(config.GetDBPath(), fallbackPath); err != nil {
+		return common.NewErrorf("Error backing up current db file: %v", err)
 	}
 	}
 
 
-	// Remove the temporary file before returning
-	defer os.Remove(fallbackPath)
+	// Defer fallback cleanup ONLY if everything goes well
+	defer func() {
+		if _, err := os.Stat(fallbackPath); err == nil {
+			if rerr := os.Remove(fallbackPath); rerr != nil {
+				logger.Warningf("Warning: failed to remove fallback file: %v", rerr)
+			}
+		}
+	}()
 
 
 	// Move temp to DB path
 	// Move temp to DB path
-	err = os.Rename(tempPath, config.GetDBPath())
-	if err != nil {
-		errRename := os.Rename(fallbackPath, config.GetDBPath())
-		if errRename != nil {
+	if err = os.Rename(tempPath, config.GetDBPath()); err != nil {
+		// Restore from fallback
+		if errRename := os.Rename(fallbackPath, config.GetDBPath()); errRename != nil {
 			return common.NewErrorf("Error moving db file and restoring fallback: %v", errRename)
 			return common.NewErrorf("Error moving db file and restoring fallback: %v", errRename)
 		}
 		}
 		return common.NewErrorf("Error moving db file: %v", err)
 		return common.NewErrorf("Error moving db file: %v", err)
 	}
 	}
 
 
 	// Migrate DB
 	// Migrate DB
-	err = database.InitDB(config.GetDBPath())
-	if err != nil {
-		errRename := os.Rename(fallbackPath, config.GetDBPath())
-		if errRename != nil {
+	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)
 			return common.NewErrorf("Error migrating db and restoring fallback: %v", errRename)
 		}
 		}
 		return common.NewErrorf("Error migrating db: %v", err)
 		return common.NewErrorf("Error migrating db: %v", err)
 	}
 	}
+
 	s.inboundService.MigrateDB()
 	s.inboundService.MigrateDB()
 
 
 	// Start Xray
 	// Start Xray
-	err = s.RestartXrayService()
-	if err != nil {
-		return common.NewErrorf("Imported DB but Failed to start Xray: %v", err)
+	if err = s.RestartXrayService(); err != nil {
+		return common.NewErrorf("Imported DB but failed to start Xray: %v", err)
 	}
 	}
 
 
 	return nil
 	return nil
 }
 }
 
 
 func (s *ServerService) UpdateGeofile(fileName string) error {
 func (s *ServerService) UpdateGeofile(fileName string) error {
-    files := []struct {
-        URL      string
-        FileName string
-    }{
-        {"https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat", "geoip.dat"},
-        {"https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat", "geosite.dat"},
-        {"https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geoip.dat", "geoip_IR.dat"},
-        {"https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geosite.dat", "geosite_IR.dat"},
-        {"https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geoip.dat", "geoip_RU.dat"},
-        {"https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geosite.dat", "geosite_RU.dat"},
-    }
-
-    downloadFile := func(url, destPath string) error {
-        resp, err := http.Get(url)
-        if err != nil {
-            return common.NewErrorf("Failed to download Geofile from %s: %v", url, err)
-        }
-        defer resp.Body.Close()
-
-        file, err := os.Create(destPath)
-        if err != nil {
-            return common.NewErrorf("Failed to create Geofile %s: %v", destPath, err)
-        }
-        defer file.Close()
-
-        _, err = io.Copy(file, resp.Body)
-        if err != nil {
-            return common.NewErrorf("Failed to save Geofile %s: %v", destPath, err)
-        }
-
-        return nil
-    }
-
-    var fileURL string
-    for _, file := range files {
-        if file.FileName == fileName {
-            fileURL = file.URL
-            break
-        }
-    }
-
-    if fileURL == "" {
-        return common.NewErrorf("File '%s' not found in the list of Geofiles", fileName)
-    }
-
-    destPath := fmt.Sprintf("%s/%s", config.GetBinFolderPath(), fileName)
-
-    if err := downloadFile(fileURL, destPath); err != nil {
-        return common.NewErrorf("Error downloading Geofile '%s': %v", fileName, err)
-    }
-
-    err := s.RestartXrayService()
-    if err != nil {
-        return common.NewErrorf("Updated Geofile '%s' but Failed to start Xray: %v", fileName, err)
-    }
-
-    return nil
+	files := []struct {
+		URL      string
+		FileName string
+	}{
+		{"https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat", "geoip.dat"},
+		{"https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat", "geosite.dat"},
+		{"https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geoip.dat", "geoip_IR.dat"},
+		{"https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geosite.dat", "geosite_IR.dat"},
+		{"https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geoip.dat", "geoip_RU.dat"},
+		{"https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geosite.dat", "geosite_RU.dat"},
+	}
+
+	downloadFile := func(url, destPath string) error {
+		resp, err := http.Get(url)
+		if err != nil {
+			return common.NewErrorf("Failed to download Geofile from %s: %v", url, err)
+		}
+		defer resp.Body.Close()
+
+		file, err := os.Create(destPath)
+		if err != nil {
+			return common.NewErrorf("Failed to create Geofile %s: %v", destPath, err)
+		}
+		defer file.Close()
+
+		_, err = io.Copy(file, resp.Body)
+		if err != nil {
+			return common.NewErrorf("Failed to save Geofile %s: %v", destPath, err)
+		}
+
+		return nil
+	}
+
+	var fileURL string
+	for _, file := range files {
+		if file.FileName == fileName {
+			fileURL = file.URL
+			break
+		}
+	}
+
+	if fileURL == "" {
+		return common.NewErrorf("File '%s' not found in the list of Geofiles", fileName)
+	}
+
+	destPath := fmt.Sprintf("%s/%s", config.GetBinFolderPath(), fileName)
+
+	if err := downloadFile(fileURL, destPath); err != nil {
+		return common.NewErrorf("Error downloading Geofile '%s': %v", fileName, err)
+	}
+
+	err := s.RestartXrayService()
+	if err != nil {
+		return common.NewErrorf("Updated Geofile '%s' but Failed to start Xray: %v", fileName, err)
+	}
+
+	return nil
 }
 }
 
 
 func (s *ServerService) GetNewX25519Cert() (any, error) {
 func (s *ServerService) GetNewX25519Cert() (any, error) {