fully write new config file before moving to target location (fixes #1287)

* fully write new config file before moving to target location (fixes #1287)
* do not fail if there is no previous config; print temporary config path on failure
This commit is contained in:
Stefan 2017-06-01 09:57:10 +02:00 committed by Nick Craig-Wood
parent decd960867
commit 9cede6b372

View File

@ -16,6 +16,7 @@ import (
"log" "log"
"os" "os"
"os/user" "os/user"
"path"
"path/filepath" "path/filepath"
"regexp" "regexp"
"sort" "sort"
@ -589,28 +590,29 @@ func changeConfigPassword() {
// SaveConfig saves configuration file. // SaveConfig saves configuration file.
// if configKey has been set, the file will be encrypted. // if configKey has been set, the file will be encrypted.
func SaveConfig() { func SaveConfig() {
if len(configKey) == 0 { dir, name := path.Split(ConfigPath)
err := goconfig.SaveConfigFile(configData, ConfigPath) f, err := ioutil.TempFile(dir, name)
if err != nil { if err != nil {
log.Fatalf("Failed to save config file: %v", err) log.Fatalf("Failed to create temp file for new config: %v", err)
}
err = os.Chmod(ConfigPath, 0600)
if err != nil {
Errorf(nil, "Failed to set permissions on config file: %v", err)
}
return return
} }
defer func() {
if err := os.Remove(f.Name()); err != nil && !os.IsNotExist(err) {
Errorf(nil, "Failed to remove temp config file: %v", err)
}
}()
var buf bytes.Buffer var buf bytes.Buffer
err := goconfig.SaveConfigData(configData, &buf) err = goconfig.SaveConfigData(configData, &buf)
if err != nil { if err != nil {
log.Fatalf("Failed to save config file: %v", err) log.Fatalf("Failed to save config file: %v", err)
} }
f, err := os.Create(ConfigPath) if len(configKey) == 0 {
if err != nil { if _, err := buf.WriteTo(f); err != nil {
log.Fatalf("Failed to save config file: %v", err) log.Fatalf("Failed to write temp config file: %v", err)
} }
} else {
fmt.Fprintln(f, "# Encrypted rclone configuration File") fmt.Fprintln(f, "# Encrypted rclone configuration File")
fmt.Fprintln(f, "") fmt.Fprintln(f, "")
fmt.Fprintln(f, "RCLONE_ENCRYPT_V0:") fmt.Fprintln(f, "RCLONE_ENCRYPT_V0:")
@ -624,7 +626,7 @@ func SaveConfig() {
enc := base64.NewEncoder(base64.StdEncoding, f) enc := base64.NewEncoder(base64.StdEncoding, f)
_, err = enc.Write(nonce[:]) _, err = enc.Write(nonce[:])
if err != nil { if err != nil {
log.Fatalf("Failed to write config file: %v", err) log.Fatalf("Failed to write temp config file: %v", err)
} }
var key [32]byte var key [32]byte
@ -633,18 +635,30 @@ func SaveConfig() {
b := secretbox.Seal(nil, buf.Bytes(), &nonce, &key) b := secretbox.Seal(nil, buf.Bytes(), &nonce, &key)
_, err = enc.Write(b) _, err = enc.Write(b)
if err != nil { if err != nil {
log.Fatalf("Failed to write config file: %v", err) log.Fatalf("Failed to write temp config file: %v", err)
} }
_ = enc.Close() _ = enc.Close()
}
err = f.Close() err = f.Close()
if err != nil { if err != nil {
log.Fatalf("Failed to close config file: %v", err) log.Fatalf("Failed to close config file: %v", err)
} }
err = os.Chmod(ConfigPath, 0600) err = os.Chmod(f.Name(), 0600)
if err != nil { if err != nil {
Errorf(nil, "Failed to set permissions on config file: %v", err) Errorf(nil, "Failed to set permissions on config file: %v", err)
} }
if err = os.Rename(ConfigPath, ConfigPath+".old"); err != nil && !os.IsNotExist(err) {
log.Fatalf("Failed to move previous config to backup location: %v", err)
}
if err = os.Rename(f.Name(), ConfigPath); err != nil {
log.Fatalf("Failed to move newly written config from %s to final location: %v", f.Name(), err)
}
if err := os.Remove(ConfigPath + ".old"); err != nil && !os.IsNotExist(err) {
Errorf(nil, "Failed to remove backup config file: %v", err)
}
} }
// ConfigSetValueAndSave sets the key to the value and saves just that // ConfigSetValueAndSave sets the key to the value and saves just that