fix(backup): restore mihomo-config.yaml from backup zip
Backup zip contains 3m-ui.db + mihomo-config.yaml + backup-meta.txt. RestoreDatabase only extracted 3m-ui.db — mihomo-config.yaml was silently dropped. After restoring a backup, the mihomo config file on disk was stale (from before the backup was taken). Fix: - extractDBFromZip now returns both dbContent and mihomoCfg - RestoreDatabase takes mihomoCfgPath parameter - After restoring the DB, also writes mihomo-config.yaml if the zip contained it and the path is configured - Mihomo config write failure does NOT fail the whole restore (DB is already restored; operator can manually restore config) - api.go passes h.mihomoCfg to RestoreDatabase fix(backup): restore mihomo-config.yaml from backup zip Backup zip contains 3m-ui.db + mihomo-config.yaml + backup-meta.txt. RestoreDatabase only extracted 3m-ui.db — mihomo-config.yaml was silently dropped. After restoring a backup, the mihomo config file on disk was stale (from before the backup was taken). Fix: - extractDBFromZip now returns both dbContent and mihomoCfg - RestoreDatabase takes mihomoCfgPath parameter - After restoring the DB, also writes mihomo-config.yaml if the zip contained it and the path is configured - Mihomo config write failure does NOT fail the whole restore (DB is already restored; operator can manually restore config) - api.go passes h.mihomoCfg to RestoreDatabase fix(backup): restore mihomo-config.yaml from backup zip Backup zip contains 3m-ui.db + mihomo-config.yaml + backup-meta.txt. RestoreDatabase only extracted 3m-ui.db — mihomo-config.yaml was silently dropped. After restoring a backup, the mihomo config file on disk was stale (from before the backup was taken). Fix: - extractDBFromZip now returns both dbContent and mihomoCfg - RestoreDatabase takes mihomoCfgPath parameter - After restoring the DB, also writes mihomo-config.yaml if the zip contained it and the path is configured - Mihomo config write failure does NOT fail the whole restore (DB is already restored; operator can manually restore config) - api.go passes h.mihomoCfg to RestoreDatabase fix(backup): restore mihomo-config.yaml from backup zip Backup zip contains 3m-ui.db + mihomo-config.yaml + backup-meta.txt. RestoreDatabase only extracted 3m-ui.db — mihomo-config.yaml was silently dropped. After restoring a backup, the mihomo config file on disk was stale (from before the backup was taken). Fix: - extractDBFromZip now returns both dbContent and mihomoCfg - RestoreDatabase takes mihomoCfgPath parameter - After restoring the DB, also writes mihomo-config.yaml if the zip contained it and the path is configured - Mihomo config write failure does NOT fail the whole restore (DB is already restored; operator can manually restore config) - api.go passes h.mihomoCfg to RestoreDatabase fix(backup): restore mihomo-config.yaml from backup zip Backup zip contains 3m-ui.db + mihomo-config.yaml + backup-meta.txt. RestoreDatabase only extracted 3m-ui.db — mihomo-config.yaml was silently dropped. After restoring a backup, the mihomo config file on disk was stale (from before the backup was taken). Fix: - extractDBFromZip now returns both dbContent and mihomoCfg - RestoreDatabase takes mihomoCfgPath parameter - After restoring the DB, also writes mihomo-config.yaml if the zip contained it and the path is configured - Mihomo config write failure does NOT fail the whole restore (DB is already restored; operator can manually restore config) - api.go passes h.mihomoCfg to RestoreDatabase fix(backup): restore mihomo-config.yaml from backup zip Backup zip contains 3m-ui.db + mihomo-config.yaml + backup-meta.txt. RestoreDatabase only extracted 3m-ui.db — mihomo-config.yaml was silently dropped. After restoring a backup, the mihomo config file on disk was stale (from before the backup was taken). Fix: - extractDBFromZip now returns both dbContent and mihomoCfg - RestoreDatabase takes mihomoCfgPath parameter - After restoring the DB, also writes mihomo-config.yaml if the zip contained it and the path is configured - Mihomo config write failure does NOT fail the whole restore (DB is already restored; operator can manually restore config) - api.go passes h.mihomoCfg to RestoreDatabase fix(backup): restore mihomo-config.yaml from backup zip Backup zip contains 3m-ui.db + mihomo-config.yaml + backup-meta.txt. RestoreDatabase only extracted 3m-ui.db — mihomo-config.yaml was silently dropped. After restoring a backup, the mihomo config file on disk was stale (from before the backup was taken). Fix: - extractDBFromZip now returns both dbContent and mihomoCfg - RestoreDatabase takes mihomoCfgPath parameter - After restoring the DB, also writes mihomo-config.yaml if the zip contained it and the path is configured - Mihomo config write failure does NOT fail the whole restore (DB is already restored; operator can manually restore config) - api.go passes h.mihomoCfg to RestoreDatabase fix(backup): restore mihomo-config.yaml from backup zip Backup zip contains 3m-ui.db + mihomo-config.yaml + backup-meta.txt. RestoreDatabase only extracted 3m-ui.db — mihomo-config.yaml was silently dropped. After restoring a backup, the mihomo config file on disk was stale (from before the backup was taken). Fix: - extractDBFromZip now returns both dbContent and mihomoCfg - RestoreDatabase takes mihomoCfgPath parameter - After restoring the DB, also writes mihomo-config.yaml if the zip contained it and the path is configured - Mihomo config write failure does NOT fail the whole restore (DB is already restored; operator can manually restore config) - api.go passes h.mihomoCfg to RestoreDatabase fix(backup): restore mihomo-config.yaml from backup zip Backup zip contains 3m-ui.db + mihomo-config.yaml + backup-meta.txt. RestoreDatabase only extracted 3m-ui.db — mihomo-config.yaml was silently dropped. After restoring a backup, the mihomo config file on disk was stale (from before the backup was taken). Fix: - extractDBFromZip now returns both dbContent and mihomoCfg - RestoreDatabase takes mihomoCfgPath parameter - After restoring the DB, also writes mihomo-config.yaml if the zip contained it and the path is configured - Mihomo config write failure does NOT fail the whole restore (DB is already restored; operator can manually restore config) - api.go passes h.mihomoCfg to RestoreDatabase fix(backup): restore mihomo-config.yaml from backup zip Backup zip contains 3m-ui.db + mihomo-config.yaml + backup-meta.txt. RestoreDatabase only extracted 3m-ui.db — mihomo-config.yaml was silently dropped. After restoring a backup, the mihomo config file on disk was stale (from before the backup was taken). Fix: - extractDBFromZip now returns both dbContent and mihomoCfg - RestoreDatabase takes mihomoCfgPath parameter - After restoring the DB, also writes mihomo-config.yaml if the zip contained it and the path is configured - Mihomo config write failure does NOT fail the whole restore (DB is already restored; operator can manually restore config) - api.go passes h.mihomoCfg to RestoreDatabase fix(backup): restore mihomo-config.yaml from backup zip Backup zip contains 3m-ui.db + mihomo-config.yaml + backup-meta.txt. RestoreDatabase only extracted 3m-ui.db — mihomo-config.yaml was silently dropped. After restoring a backup, the mihomo config file on disk was stale (from before the backup was taken). Fix: - extractDBFromZip now returns both dbContent and mihomoCfg - RestoreDatabase takes mihomoCfgPath parameter - After restoring the DB, also writes mihomo-config.yaml if the zip contained it and the path is configured - Mihomo config write failure does NOT fail the whole restore (DB is already restored; operator can manually restore config) - api.go passes h.mihomoCfg to RestoreDatabase fix(backup): restore mihomo-config.yaml from backup zip Backup zip contains 3m-ui.db + mihomo-config.yaml + backup-meta.txt. RestoreDatabase only extracted 3m-ui.db — mihomo-config.yaml was silently dropped. After restoring a backup, the mihomo config file on disk was stale (from before the backup was taken). Fix: - extractDBFromZip now returns both dbContent and mihomoCfg - RestoreDatabase takes mihomoCfgPath parameter - After restoring the DB, also writes mihomo-config.yaml if the zip contained it and the path is configured - Mihomo config write failure does NOT fail the whole restore (DB is already restored; operator can manually restore config) - api.go passes h.mihomoCfg to RestoreDatabase
This commit is contained in:
1 parent
913783b309
commit
5b9674987f
2 files changed
+45
-21
No files matched your search
@@ -76,7 +76,7 @@ func (h *Handler) RestoreDatabase(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
if err := RestoreDatabase(h.dbPath, f); err != nil {
|
||||
if err := RestoreDatabase(h.dbPath, h.mihomoCfg, f); err != nil {
|
||||
log.Printf("system restore-database failed: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "internal server error"})
|
||||
return
|
||||
|
||||
@@ -75,7 +75,7 @@ func WriteZip(w io.Writer, paths BackupPaths) error {
|
||||
// - A zip archive exported by ExportBackup (containing 3m-ui.db + mihomo-config.yaml)
|
||||
//
|
||||
// Callers should stop the panel or accept that a process restart may be required.
|
||||
func RestoreDatabase(dbPath string, r io.Reader) error {
|
||||
func RestoreDatabase(dbPath, mihomoCfgPath string, r io.Reader) error {
|
||||
if dbPath == "" {
|
||||
return fmt.Errorf("database path is empty")
|
||||
}
|
||||
@@ -92,10 +92,10 @@ func RestoreDatabase(dbPath string, r io.Reader) error {
|
||||
}
|
||||
|
||||
// Check if it's a zip file (PK magic).
|
||||
var dbContent []byte
|
||||
var dbContent, mihomoCfg []byte
|
||||
if len(raw) >= 4 && raw[0] == 0x50 && raw[1] == 0x4B && raw[2] == 0x03 && raw[3] == 0x04 {
|
||||
// Zip archive — extract 3m-ui.db from it.
|
||||
dbContent, err = extractDBFromZip(raw)
|
||||
dbContent, mihomoCfg, err = extractDBFromZip(raw)
|
||||
if err != nil {
|
||||
return fmt.Errorf("extract from zip: %w", err)
|
||||
}
|
||||
@@ -116,32 +116,56 @@ func RestoreDatabase(dbPath string, r io.Reader) error {
|
||||
if err := os.WriteFile(tmp, dbContent, 0o600); err != nil {
|
||||
return err
|
||||
}
|
||||
return os.Rename(tmp, dbPath)
|
||||
if err := os.Rename(tmp, dbPath); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Restore mihomo-config.yaml if the zip contained it and the path is set.
|
||||
if len(mihomoCfg) > 0 && mihomoCfgPath != "" {
|
||||
cfgDir := filepath.Dir(mihomoCfgPath)
|
||||
_ = os.MkdirAll(cfgDir, 0o750)
|
||||
cfgTmp := mihomoCfgPath + ".restore-tmp"
|
||||
defer os.Remove(cfgTmp)
|
||||
if err := os.WriteFile(cfgTmp, mihomoCfg, 0o600); err == nil {
|
||||
_ = os.Rename(cfgTmp, mihomoCfgPath)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// extractDBFromZip reads a zip archive and returns the contents of 3m-ui.db.
|
||||
// Also restores mihomo-config.yaml if mihomoCfgPath is set.
|
||||
func extractDBFromZip(raw []byte) ([]byte, error) {
|
||||
zr, err := zip.NewReader(bytes.NewReader(raw), int64(len(raw)))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("open zip: %w", err)
|
||||
// extractDBFromZip reads a zip archive and returns the contents of
|
||||
// 3m-ui.db and mihomo-config.yaml (if present).
|
||||
func extractDBFromZip(raw []byte) (dbContent, mihomoCfg []byte, err error) {
|
||||
zr, zErr := zip.NewReader(bytes.NewReader(raw), int64(len(raw)))
|
||||
if zErr != nil {
|
||||
return nil, nil, fmt.Errorf("open zip: %w", zErr)
|
||||
}
|
||||
var dbContent []byte
|
||||
for _, f := range zr.File {
|
||||
if f.Name == "3m-ui.db" {
|
||||
rc, err := f.Open()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("open %s in zip: %w", f.Name, err)
|
||||
switch f.Name {
|
||||
case "3m-ui.db":
|
||||
rc, e := f.Open()
|
||||
if e != nil {
|
||||
return nil, nil, fmt.Errorf("open %s in zip: %w", f.Name, e)
|
||||
}
|
||||
dbContent, err = io.ReadAll(rc)
|
||||
dbContent, e = io.ReadAll(rc)
|
||||
rc.Close()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("read %s in zip: %w", f.Name, err)
|
||||
if e != nil {
|
||||
return nil, nil, fmt.Errorf("read %s in zip: %w", f.Name, e)
|
||||
}
|
||||
case "mihomo-config.yaml":
|
||||
rc, e := f.Open()
|
||||
if e != nil {
|
||||
return nil, nil, fmt.Errorf("open %s in zip: %w", f.Name, e)
|
||||
}
|
||||
mihomoCfg, e = io.ReadAll(rc)
|
||||
rc.Close()
|
||||
if e != nil {
|
||||
return nil, nil, fmt.Errorf("read %s in zip: %w", f.Name, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
if dbContent == nil {
|
||||
return nil, fmt.Errorf("zip does not contain 3m-ui.db")
|
||||
return nil, nil, fmt.Errorf("zip does not contain 3m-ui.db")
|
||||
}
|
||||
return dbContent, nil
|
||||
return dbContent, mihomoCfg, nil
|
||||
}
|
||||
Reference in new issue
Block a user