// loadConfigFile will load a config file, and // automatically decrypt it. func loadConfigFile() (*goconfig.ConfigFile, error) { b, err := ioutil.ReadFile(ConfigPath) if err != nil { if os.IsNotExist(err) { return nil, errorConfigFileNotFound } return nil, err } // Find first non-empty line r := bufio.NewReader(bytes.NewBuffer(b)) for { line, _, err := r.ReadLine() if err != nil { if err == io.EOF { return goconfig.LoadFromReader(bytes.NewBuffer(b)) } return nil, err } l := strings.TrimSpace(string(line)) if len(l) == 0 || strings.HasPrefix(l, ";") || strings.HasPrefix(l, "#") { continue } // First non-empty or non-comment must be ENCRYPT_V0 if l == "RCLONE_ENCRYPT_V0:" { break } if strings.HasPrefix(l, "RCLONE_ENCRYPT_V") { return nil, errors.New("unsupported configuration encryption - update rclone for support") } return goconfig.LoadFromReader(bytes.NewBuffer(b)) } // Encrypted content is base64 encoded. dec := base64.NewDecoder(base64.StdEncoding, r) box, err := ioutil.ReadAll(dec) if err != nil { return nil, errors.Wrap(err, "failed to load base64 encoded data") } if len(box) < 24+secretbox.Overhead { return nil, errors.New("Configuration data too short") } envpw := os.Getenv("RCLONE_CONFIG_PASS") var out []byte for { if len(configKey) == 0 && envpw != "" { err := setConfigPassword(envpw) if err != nil { fmt.Println("Using RCLONE_CONFIG_PASS returned:", err) envpw = "" } else { Debug(nil, "Using RCLONE_CONFIG_PASS password.") } } if len(configKey) == 0 { if !*AskPassword { return nil, errors.New("unable to decrypt configuration and not allowed to ask for password - set RCLONE_CONFIG_PASS to your configuration password") } getConfigPassword("Enter configuration password:"******"Couldn't decrypt configuration, most likely wrong password.") configKey = nil envpw = "" } return goconfig.LoadFromReader(bytes.NewBuffer(out)) }
// LoadConfig loads the config file func LoadConfig() { // Read some flags if set // // FIXME read these from the config file too Config.Verbose = *verbose Config.Quiet = *quiet Config.ModifyWindow = *modifyWindow Config.Checkers = *checkers Config.Transfers = *transfers Config.DryRun = *dryRun Config.Timeout = *timeout Config.ConnectTimeout = *connectTimeout Config.CheckSum = *checkSum Config.SizeOnly = *sizeOnly Config.IgnoreTimes = *ignoreTimes Config.IgnoreExisting = *ignoreExisting Config.DumpHeaders = *dumpHeaders Config.DumpBodies = *dumpBodies Config.DumpAuth = *dumpAuth Config.InsecureSkipVerify = *skipVerify Config.LowLevelRetries = *lowLevelRetries Config.UpdateOlder = *updateOlder Config.NoGzip = *noGzip Config.MaxDepth = *maxDepth Config.IgnoreSize = *ignoreSize Config.NoTraverse = *noTraverse Config.NoUpdateModTime = *noUpdateModTime Config.BackupDir = *backupDir ConfigPath = *configFile Config.DeleteBefore = *deleteBefore Config.DeleteDuring = *deleteDuring Config.DeleteAfter = *deleteAfter Config.TrackRenames = *trackRenames switch { case *deleteBefore && (*deleteDuring || *deleteAfter), *deleteDuring && *deleteAfter: log.Fatalf(`Only one of --delete-before, --delete-during or --delete-after can be used.`) // If none are specified, use "during". case !*deleteBefore && !*deleteDuring && !*deleteAfter: Config.DeleteDuring = true } if Config.IgnoreSize && Config.SizeOnly { log.Fatalf(`Can't use --size-only and --ignore-size together.`) } // Load configuration file. var err error configData, err = loadConfigFile() if err == errorConfigFileNotFound { Log(nil, "Config file %q not found - using defaults", ConfigPath) configData, _ = goconfig.LoadFromReader(&bytes.Buffer{}) } else if err != nil { log.Fatalf("Failed to load config file %q: %v", ConfigPath, err) } // Load filters Config.Filter, err = NewFilter() if err != nil { log.Fatalf("Failed to load filters: %v", err) } // Start the token bucket limiter startTokenBucket() // Start the bandwidth update ticker startTokenTicker() }