mirror of
https://github.com/gesellix/Bose-SoundTouch.git
synced 2026-08-19 00:56:16 +00:00
fix(setup): prevent and clean up corrupted rc.local with cat error message
This commit is contained in:
+46
-28
@@ -1097,7 +1097,10 @@ func (m *Manager) migrateViaResolvConf(deviceIP, targetURL string) (string, erro
|
||||
hookMarker := "/mnt/nv/aftertouch.resolv.conf"
|
||||
|
||||
// Check if rc.local exists and read it
|
||||
currentRcLocal, _ := client.Run(fmt.Sprintf("cat %s", rcLocalPath))
|
||||
currentRcLocal, rcErr := client.Run(fmt.Sprintf("cat %s", rcLocalPath))
|
||||
if rcErr != nil {
|
||||
currentRcLocal = ""
|
||||
}
|
||||
|
||||
patchLogic := fmt.Sprintf(`
|
||||
# Aftertouch DNS hook: prioritizes our custom nameserver if it exists
|
||||
@@ -1109,6 +1112,11 @@ fi
|
||||
|
||||
if !strings.Contains(currentRcLocal, hookMarker) {
|
||||
newRcLocal := currentRcLocal
|
||||
// Remove "cat: can't open..." error message if it was accidentally saved in the file
|
||||
if strings.Contains(newRcLocal, "cat: can't open") {
|
||||
newRcLocal = ""
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(newRcLocal, "#!/bin/sh") {
|
||||
newRcLocal = "#!/bin/sh\n" + strings.TrimPrefix(newRcLocal, "#!/bin/sh")
|
||||
}
|
||||
@@ -1270,36 +1278,46 @@ func (m *Manager) revertAftertouchHook(client SSHClient, rwCmd string) string {
|
||||
_, _ = client.Run(fmt.Sprintf("rm %s", aftertouchConfPath))
|
||||
}
|
||||
|
||||
if currentRcLocal, err := client.Run(fmt.Sprintf("cat %s", rcLocalPath)); err == nil && (strings.Contains(currentRcLocal, aftertouchConfPath) || strings.Contains(currentRcLocal, "# Aftertouch DNS hook")) {
|
||||
logs += fmt.Sprintf("Removing Aftertouch hook logic from %s\n", rcLocalPath)
|
||||
fmt.Printf("Removing Aftertouch hook logic from %s\n", rcLocalPath)
|
||||
if currentRcLocal, err := client.Run(fmt.Sprintf("cat %s", rcLocalPath)); err == nil {
|
||||
// Remove "cat: can't open..." error message if it was accidentally saved in the file
|
||||
if strings.Contains(currentRcLocal, "cat: can't open") {
|
||||
logs += fmt.Sprintf("Removing corrupted %s\n", rcLocalPath)
|
||||
_, _ = client.Run(fmt.Sprintf("rm %s", rcLocalPath))
|
||||
|
||||
// Simple removal: filter out lines between the marker and the 'fi'
|
||||
lines := strings.Split(currentRcLocal, "\n")
|
||||
|
||||
var newLines []string
|
||||
|
||||
skip := false
|
||||
|
||||
for _, line := range lines {
|
||||
if strings.Contains(line, "# Aftertouch DNS hook") {
|
||||
skip = true
|
||||
continue
|
||||
}
|
||||
|
||||
if skip && strings.TrimSpace(line) == "fi" {
|
||||
skip = false
|
||||
continue
|
||||
}
|
||||
|
||||
if !skip {
|
||||
newLines = append(newLines, line)
|
||||
}
|
||||
return logs
|
||||
}
|
||||
|
||||
newRcLocal := strings.Join(newLines, "\n")
|
||||
if err := client.UploadContent([]byte(newRcLocal), rcLocalPath); err != nil {
|
||||
fmt.Printf("Warning: failed to update %s: %v\n", rcLocalPath, err)
|
||||
if strings.Contains(currentRcLocal, aftertouchConfPath) || strings.Contains(currentRcLocal, "# Aftertouch DNS hook") {
|
||||
logs += fmt.Sprintf("Removing Aftertouch hook logic from %s\n", rcLocalPath)
|
||||
fmt.Printf("Removing Aftertouch hook logic from %s\n", rcLocalPath)
|
||||
|
||||
// Simple removal: filter out lines between the marker and the 'fi'
|
||||
lines := strings.Split(currentRcLocal, "\n")
|
||||
|
||||
var newLines []string
|
||||
|
||||
skip := false
|
||||
|
||||
for _, line := range lines {
|
||||
if strings.Contains(line, "# Aftertouch DNS hook") {
|
||||
skip = true
|
||||
continue
|
||||
}
|
||||
|
||||
if skip && strings.TrimSpace(line) == "fi" {
|
||||
skip = false
|
||||
continue
|
||||
}
|
||||
|
||||
if !skip {
|
||||
newLines = append(newLines, line)
|
||||
}
|
||||
}
|
||||
|
||||
newRcLocal := strings.Join(newLines, "\n")
|
||||
if err := client.UploadContent([]byte(newRcLocal), rcLocalPath); err != nil {
|
||||
fmt.Printf("Warning: failed to update %s: %v\n", rcLocalPath, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -808,6 +808,47 @@ func TestRevertMigration(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRevertMigration_CorruptedRcLocal(t *testing.T) {
|
||||
m := NewManager("http://localhost:8000", nil, nil)
|
||||
|
||||
runCalls := []string{}
|
||||
m.NewSSH = func(host string) SSHClient {
|
||||
return &mockSSH{
|
||||
runFunc: func(command string) (string, error) {
|
||||
runCalls = append(runCalls, command)
|
||||
if command == "cat /mnt/nv/rc.local" {
|
||||
return "cat: can't open '/mnt/nv/rc.local': No such file or directory", nil
|
||||
}
|
||||
if strings.HasPrefix(command, "[ -f") {
|
||||
if strings.Contains(command, ".original") {
|
||||
if strings.Contains(command, "SoundTouchSdkPrivateCfg.xml") {
|
||||
return "", nil // Pretend XML backup exists to satisfy RevertMigration
|
||||
}
|
||||
return "", fmt.Errorf("not found")
|
||||
}
|
||||
}
|
||||
return "", nil
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
_, err := m.RevertMigration("192.168.1.10")
|
||||
if err != nil {
|
||||
t.Fatalf("RevertMigration failed: %v", err)
|
||||
}
|
||||
|
||||
foundRmRcLocal := false
|
||||
for _, call := range runCalls {
|
||||
if call == "rm /mnt/nv/rc.local" {
|
||||
foundRmRcLocal = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !foundRmRcLocal {
|
||||
t.Errorf("Expected corrupted rc.local to be removed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRevertMigration_NoBackup(t *testing.T) {
|
||||
m := NewManager("http://localhost:8000", nil, nil)
|
||||
|
||||
@@ -1113,6 +1154,59 @@ func TestMigrateViaResolvConf(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestMigrateViaResolvConf_CorruptedRcLocal(t *testing.T) {
|
||||
tempDir, err := os.MkdirTemp("", "setup-test-resolv-corrupted")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create temp dir: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(tempDir)
|
||||
|
||||
cm := certmanager.NewCertificateManager(filepath.Join(tempDir, "certs"))
|
||||
if err := cm.EnsureCA(); err != nil {
|
||||
t.Fatalf("Failed to ensure CA: %v", err)
|
||||
}
|
||||
|
||||
m := NewManager("http://192.168.1.100:8000", nil, cm)
|
||||
|
||||
uploads := make(map[string]string)
|
||||
|
||||
m.NewSSH = func(host string) SSHClient {
|
||||
return &mockSSH{
|
||||
runFunc: func(command string) (string, error) {
|
||||
if command == "cat /mnt/nv/rc.local" {
|
||||
// Simulate corrupted file containing error message
|
||||
return "cat: can't open '/mnt/nv/rc.local': No such file or directory", nil
|
||||
}
|
||||
if strings.HasPrefix(command, "[ -f") {
|
||||
return "", fmt.Errorf("file not found")
|
||||
}
|
||||
return "", nil
|
||||
},
|
||||
uploadContentFunc: func(content []byte, remotePath string) error {
|
||||
uploads[remotePath] = string(content)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
_, err = m.migrateViaResolvConf("192.168.1.10", "http://192.168.1.100:8000")
|
||||
if err != nil {
|
||||
t.Fatalf("migrateViaResolvConf failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify uploads - rc.local should have been sanitized and only contain shebang and hook
|
||||
rcLocal := uploads["/mnt/nv/rc.local"]
|
||||
if strings.Contains(rcLocal, "cat: can't open") {
|
||||
t.Errorf("rc.local still contains corrupted content: %s", rcLocal)
|
||||
}
|
||||
if !strings.HasPrefix(rcLocal, "#!/bin/sh") {
|
||||
t.Errorf("rc.local missing shebang: %s", rcLocal)
|
||||
}
|
||||
if !strings.Contains(rcLocal, "/mnt/nv/aftertouch.resolv.conf") {
|
||||
t.Errorf("rc.local missing hook logic: %s", rcLocal)
|
||||
}
|
||||
}
|
||||
|
||||
func contains(s, substr string) bool {
|
||||
return strings.Contains(s, substr)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user