2014-03-15 16:06:11 +00:00
package fs
import (
2020-11-05 11:33:32 +00:00
"context"
2021-11-04 10:12:57 +00:00
"errors"
2024-07-09 18:42:01 +01:00
"fmt"
2017-07-23 16:10:23 +01:00
"net"
2021-05-20 14:08:01 +02:00
"os"
2021-10-02 12:50:11 +03:00
"strconv"
2018-05-16 16:30:09 +01:00
"strings"
2014-03-15 16:06:11 +00:00
"time"
)
// Global
var (
2020-11-05 11:33:32 +00:00
// globalConfig for rclone
2024-07-09 18:42:01 +01:00
globalConfig = new ( ConfigInfo )
2014-03-15 16:06:11 +00:00
2018-01-12 16:30:54 +00:00
// Read a value from the config file
//
// This is a function pointer to decouple the config
// implementation from the fs
2018-05-21 14:53:45 +01:00
ConfigFileGet = func ( section , key string ) ( string , bool ) { return "" , false }
2017-01-02 18:52:41 -08:00
2019-08-14 17:06:13 +01:00
// Set a value into the config file and persist it
2018-05-14 18:06:57 +01:00
//
// This is a function pointer to decouple the config
// implementation from the fs
2019-08-14 17:06:13 +01:00
ConfigFileSet = func ( section , key , value string ) ( err error ) {
return errors . New ( "no config file set handler" )
2018-05-14 18:06:57 +01:00
}
2022-09-12 20:43:53 +01:00
// Check if the config file has the named section
//
// This is a function pointer to decouple the config
// implementation from the fs
ConfigFileHasSection = func ( section string ) bool { return false }
2018-01-12 16:30:54 +00:00
// CountError counts an error. If any errors have been
2020-12-30 10:37:14 +00:00
// counted then rclone will exit with a non zero error code.
2018-01-12 16:30:54 +00:00
//
// This is a function pointer to decouple the config
// implementation from the fs
2021-12-08 17:14:45 +01:00
CountError = func ( ctx context . Context , err error ) error { return err }
2018-04-13 16:06:37 +01:00
// ConfigProvider is the config key used for provider options
ConfigProvider = "provider"
2021-05-09 16:03:18 +01:00
// ConfigEdit is the config key used to show we wish to edit existing entries
ConfigEdit = "config_fs_edit"
2016-08-14 12:04:43 +01:00
)
2024-07-09 18:42:01 +01:00
// ConfigOptionsInfo describes the Options in use
var ConfigOptionsInfo = Options { {
Name : "modify_window" ,
Default : time . Nanosecond ,
Help : "Max time diff to be considered the same" ,
Groups : "Copy" ,
} , {
Name : "checkers" ,
Default : 8 ,
Help : "Number of checkers to run in parallel" ,
Groups : "Performance" ,
} , {
Name : "transfers" ,
Default : 4 ,
Help : "Number of file transfers to run in parallel" ,
Groups : "Performance" ,
} , {
Name : "checksum" ,
ShortOpt : "c" ,
Default : false ,
2024-08-10 16:50:20 +02:00
Help : "Check for changes with size & checksum (if available, or fallback to size only)" ,
2024-07-09 18:42:01 +01:00
Groups : "Copy" ,
} , {
Name : "size_only" ,
Default : false ,
Help : "Skip based on size only, not modtime or checksum" ,
Groups : "Copy" ,
} , {
Name : "ignore_times" ,
ShortOpt : "I" ,
Default : false ,
Help : "Don't skip items that match size and time - transfer all unconditionally" ,
Groups : "Copy" ,
} , {
Name : "ignore_existing" ,
Default : false ,
Help : "Skip all files that exist on destination" ,
Groups : "Copy" ,
} , {
Name : "ignore_errors" ,
Default : false ,
Help : "Delete even if there are I/O errors" ,
Groups : "Sync" ,
} , {
Name : "dry_run" ,
ShortOpt : "n" ,
Default : false ,
Help : "Do a trial run with no permanent changes" ,
Groups : "Config,Important" ,
} , {
Name : "interactive" ,
ShortOpt : "i" ,
Default : false ,
Help : "Enable interactive mode" ,
Groups : "Config,Important" ,
2024-11-22 11:42:31 +00:00
} , {
Name : "links" ,
Help : "Translate symlinks to/from regular files with a '" + LinkSuffix + "' extension." ,
Default : false ,
ShortOpt : "l" ,
Groups : "Copy" ,
2024-07-09 18:42:01 +01:00
} , {
Name : "contimeout" ,
Default : 60 * time . Second ,
Help : "Connect timeout" ,
Groups : "Networking" ,
} , {
Name : "timeout" ,
Default : 5 * 60 * time . Second ,
Help : "IO idle timeout" ,
Groups : "Networking" ,
} , {
Name : "expect_continue_timeout" ,
Default : 1 * time . Second ,
Help : "Timeout when using expect / 100-continue in HTTP" ,
Groups : "Networking" ,
} , {
Name : "no_check_certificate" ,
Default : false ,
Help : "Do not verify the server SSL certificate (insecure)" ,
Groups : "Networking" ,
} , {
Name : "ask_password" ,
Default : true ,
Help : "Allow prompt for password for encrypted configuration" ,
Groups : "Config" ,
} , {
Name : "password_command" ,
Default : SpaceSepList { } ,
Help : "Command for supplying password for encrypted configuration" ,
Groups : "Config" ,
} , {
Name : "max_delete" ,
Default : int64 ( - 1 ) ,
Help : "When synchronizing, limit the number of deletes" ,
Groups : "Sync" ,
} , {
Name : "max_delete_size" ,
Default : SizeSuffix ( - 1 ) ,
Help : "When synchronizing, limit the total size of deletes" ,
Groups : "Sync" ,
} , {
Name : "track_renames" ,
Default : false ,
Help : "When synchronizing, track file renames and do a server-side move if possible" ,
Groups : "Sync" ,
} , {
Name : "track_renames_strategy" ,
Default : "hash" ,
Help : "Strategies to use when synchronizing using track-renames hash|modtime|leaf" ,
Groups : "Sync" ,
} , {
Name : "retries" ,
Default : 3 ,
Help : "Retry operations this many times if they fail" ,
Groups : "Config" ,
} , {
Name : "retries_sleep" ,
Default : time . Duration ( 0 ) ,
Help : "Interval between retrying operations if they fail, e.g. 500ms, 60s, 5m (0 to disable)" ,
Groups : "Config" ,
} , {
Name : "low_level_retries" ,
Default : 10 ,
Help : "Number of low level retries to do" ,
Groups : "Config" ,
} , {
Name : "update" ,
ShortOpt : "u" ,
Default : false ,
Help : "Skip files that are newer on the destination" ,
Groups : "Copy" ,
} , {
Name : "use_server_modtime" ,
Default : false ,
Help : "Use server modified time instead of object metadata" ,
Groups : "Config" ,
} , {
Name : "no_gzip_encoding" ,
Default : false ,
Help : "Don't set Accept-Encoding: gzip" ,
Groups : "Networking" ,
} , {
Name : "max_depth" ,
Default : - 1 ,
Help : "If set limits the recursion depth to this" ,
Groups : "Filter" ,
} , {
Name : "ignore_size" ,
Default : false ,
Help : "Ignore size when skipping use modtime or checksum" ,
Groups : "Copy" ,
} , {
Name : "ignore_checksum" ,
Default : false ,
Help : "Skip post copy check of checksums" ,
Groups : "Copy" ,
} , {
Name : "ignore_case_sync" ,
Default : false ,
Help : "Ignore case when synchronizing" ,
Groups : "Copy" ,
} , {
Name : "fix_case" ,
Default : false ,
Help : "Force rename of case insensitive dest to match source" ,
Groups : "Sync" ,
} , {
Name : "no_traverse" ,
Default : false ,
Help : "Don't traverse destination file system on copy" ,
Groups : "Copy" ,
} , {
Name : "check_first" ,
Default : false ,
Help : "Do all the checks before starting transfers" ,
Groups : "Copy" ,
} , {
Name : "no_check_dest" ,
Default : false ,
Help : "Don't check the destination, copy regardless" ,
Groups : "Copy" ,
} , {
Name : "no_unicode_normalization" ,
Default : false ,
Help : "Don't normalize unicode characters in filenames" ,
Groups : "Config" ,
} , {
Name : "no_update_modtime" ,
Default : false ,
Help : "Don't update destination modtime if files identical" ,
Groups : "Copy" ,
} , {
Name : "no_update_dir_modtime" ,
Default : false ,
Help : "Don't update directory modification times" ,
Groups : "Copy" ,
} , {
Name : "compare_dest" ,
Default : [ ] string { } ,
Help : "Include additional server-side paths during comparison" ,
Groups : "Copy" ,
} , {
Name : "copy_dest" ,
Default : [ ] string { } ,
Help : "Implies --compare-dest but also copies files from paths into destination" ,
Groups : "Copy" ,
} , {
Name : "backup_dir" ,
Default : "" ,
Help : "Make backups into hierarchy based in DIR" ,
Groups : "Sync" ,
} , {
Name : "suffix" ,
Default : "" ,
Help : "Suffix to add to changed files" ,
Groups : "Sync" ,
} , {
Name : "suffix_keep_extension" ,
Default : false ,
Help : "Preserve the extension when using --suffix" ,
Groups : "Sync" ,
} , {
Name : "fast_list" ,
Default : false ,
Help : "Use recursive list if available; uses more memory but fewer transactions" ,
Groups : "Listing" ,
2024-12-09 11:30:34 +00:00
} , {
Name : "list_cutoff" ,
Default : 1_000_000 ,
Help : "To save memory, sort directory listings on disk above this threshold" ,
Groups : "Sync" ,
2024-07-09 18:42:01 +01:00
} , {
Name : "tpslimit" ,
Default : 0.0 ,
Help : "Limit HTTP transactions per second to this" ,
Groups : "Networking" ,
} , {
Name : "tpslimit_burst" ,
Default : 1 ,
Help : "Max burst of transactions for --tpslimit" ,
Groups : "Networking" ,
} , {
Name : "user_agent" ,
Default : "rclone/" + Version ,
Help : "Set the user-agent to a specified string" ,
Groups : "Networking" ,
} , {
Name : "immutable" ,
Default : false ,
Help : "Do not modify files, fail if existing files have been modified" ,
Groups : "Copy" ,
} , {
Name : "auto_confirm" ,
Default : false ,
Help : "If enabled, do not request console confirmation" ,
Groups : "Config" ,
} , {
Name : "stats_unit" ,
Default : "bytes" ,
Help : "Show data rate in stats as either 'bits' or 'bytes' per second" ,
Groups : "Logging" ,
} , {
Name : "stats_file_name_length" ,
Default : 45 ,
Help : "Max file name length in stats (0 for no limit)" ,
Groups : "Logging" ,
} , {
Name : "log_level" ,
Default : LogLevelNotice ,
Help : "Log level DEBUG|INFO|NOTICE|ERROR" ,
Groups : "Logging" ,
} , {
Name : "stats_log_level" ,
Default : LogLevelInfo ,
Help : "Log level to show --stats output DEBUG|INFO|NOTICE|ERROR" ,
Groups : "Logging" ,
} , {
Name : "bwlimit" ,
Default : BwTimetable { } ,
Help : "Bandwidth limit in KiB/s, or use suffix B|K|M|G|T|P or a full timetable" ,
Groups : "Networking" ,
} , {
Name : "bwlimit_file" ,
Default : BwTimetable { } ,
Help : "Bandwidth limit per file in KiB/s, or use suffix B|K|M|G|T|P or a full timetable" ,
Groups : "Networking" ,
} , {
Name : "buffer_size" ,
Default : SizeSuffix ( 16 << 20 ) ,
Help : "In memory buffer size when reading files for each --transfer" ,
Groups : "Performance" ,
} , {
Name : "streaming_upload_cutoff" ,
Default : SizeSuffix ( 100 * 1024 ) ,
Help : "Cutoff for switching to chunked upload if file size is unknown, upload starts after reaching cutoff or when file ends" ,
Groups : "Copy" ,
} , {
Name : "dump" ,
Default : DumpFlags ( 0 ) ,
Help : "List of items to dump from: " + DumpFlagsList ,
Groups : "Debugging" ,
} , {
Name : "max_transfer" ,
Default : SizeSuffix ( - 1 ) ,
Help : "Maximum size of data to transfer" ,
Groups : "Copy" ,
} , {
Name : "max_duration" ,
Default : time . Duration ( 0 ) ,
Help : "Maximum duration rclone will transfer data for" ,
Groups : "Copy" ,
} , {
Name : "cutoff_mode" ,
Default : CutoffMode ( 0 ) ,
Help : "Mode to stop transfers when reaching the max transfer limit HARD|SOFT|CAUTIOUS" ,
Groups : "Copy" ,
} , {
Name : "max_backlog" ,
Default : 10000 ,
Help : "Maximum number of objects in sync or check backlog" ,
Groups : "Copy,Check" ,
} , {
Name : "max_stats_groups" ,
Default : 1000 ,
Help : "Maximum number of stats groups to keep in memory, on max oldest is discarded" ,
Groups : "Logging" ,
} , {
Name : "stats_one_line" ,
Default : false ,
Help : "Make the stats fit on one line" ,
Groups : "Logging" ,
} , {
Name : "stats_one_line_date" ,
Default : false ,
Help : "Enable --stats-one-line and add current date/time prefix" ,
Groups : "Logging" ,
} , {
Name : "stats_one_line_date_format" ,
Default : "" ,
Help : "Enable --stats-one-line-date and use custom formatted date: Enclose date string in double quotes (\"), see https://golang.org/pkg/time/#Time.Format" ,
Groups : "Logging" ,
} , {
Name : "error_on_no_transfer" ,
Default : false ,
Help : "Sets exit code 9 if no files are transferred, useful in scripts" ,
Groups : "Config" ,
} , {
Name : "progress" ,
ShortOpt : "P" ,
Default : false ,
Help : "Show progress during transfer" ,
Groups : "Logging" ,
} , {
Name : "progress_terminal_title" ,
Default : false ,
Help : "Show progress on the terminal title (requires -P/--progress)" ,
Groups : "Logging" ,
} , {
Name : "use_cookies" ,
Default : false ,
Help : "Enable session cookiejar" ,
Groups : "Networking" ,
} , {
Name : "use_mmap" ,
Default : false ,
Help : "Use mmap allocator (see docs)" ,
Groups : "Config" ,
2025-02-15 18:04:09 +00:00
} , {
Name : "max_buffer_memory" ,
Default : SizeSuffix ( - 1 ) ,
Help : "If set, don't allocate more than this amount of memory as buffers" ,
Groups : "Config" ,
2024-07-09 18:42:01 +01:00
} , {
Name : "ca_cert" ,
Default : [ ] string { } ,
Help : "CA certificate used to verify servers" ,
Groups : "Networking" ,
} , {
Name : "client_cert" ,
Default : "" ,
Help : "Client SSL certificate (PEM) for mutual TLS auth" ,
Groups : "Networking" ,
} , {
Name : "client_key" ,
Default : "" ,
Help : "Client SSL private key (PEM) for mutual TLS auth" ,
Groups : "Networking" ,
} , {
Name : "multi_thread_cutoff" ,
Default : SizeSuffix ( 256 * 1024 * 1024 ) ,
Help : "Use multi-thread downloads for files above this size" ,
Groups : "Copy" ,
} , {
Name : "multi_thread_streams" ,
Default : 4 ,
Help : "Number of streams to use for multi-thread downloads" ,
Groups : "Copy" ,
} , {
Name : "multi_thread_write_buffer_size" ,
Default : SizeSuffix ( 128 * 1024 ) ,
Help : "In memory buffer size for writing when in multi-thread mode" ,
Groups : "Copy" ,
} , {
Name : "multi_thread_chunk_size" ,
Default : SizeSuffix ( 64 * 1024 * 1024 ) ,
Help : "Chunk size for multi-thread downloads / uploads, if not set by filesystem" ,
Groups : "Copy" ,
} , {
Name : "use_json_log" ,
Default : false ,
Help : "Use json log format" ,
Groups : "Logging" ,
} , {
Name : "order_by" ,
Default : "" ,
Help : "Instructions on how to order the transfers, e.g. 'size,descending'" ,
Groups : "Copy" ,
} , {
Name : "refresh_times" ,
Default : false ,
Help : "Refresh the modtime of remote files" ,
Groups : "Copy" ,
} , {
Name : "no_console" ,
Default : false ,
Help : "Hide console window (supported on Windows only)" ,
Groups : "Config" ,
} , {
Name : "fs_cache_expire_duration" ,
Default : 300 * time . Second ,
Help : "Cache remotes for this long (0 to disable caching)" ,
Groups : "Config" ,
} , {
Name : "fs_cache_expire_interval" ,
Default : 60 * time . Second ,
Help : "Interval to check for expired remotes" ,
Groups : "Config" ,
} , {
Name : "disable_http2" ,
Default : false ,
Help : "Disable HTTP/2 in the global transport" ,
Groups : "Networking" ,
} , {
Name : "human_readable" ,
Default : false ,
Help : "Print numbers in a human-readable format, sizes with suffix Ki|Mi|Gi|Ti|Pi" ,
Groups : "Config" ,
} , {
Name : "kv_lock_time" ,
Default : 1 * time . Second ,
Help : "Maximum time to keep key-value database locked by process" ,
Groups : "Config" ,
} , {
Name : "disable_http_keep_alives" ,
Default : false ,
Help : "Disable HTTP keep-alives and use each connection once." ,
Groups : "Networking" ,
} , {
Name : "metadata" ,
ShortOpt : "M" ,
Default : false ,
Help : "If set, preserve metadata when copying objects" ,
Groups : "Metadata,Copy" ,
} , {
Name : "server_side_across_configs" ,
Default : false ,
Help : "Allow server-side operations (e.g. copy) to work across different configs" ,
Groups : "Copy" ,
} , {
Name : "color" ,
Default : TerminalColorMode ( 0 ) ,
Help : "When to show colors (and other ANSI codes) AUTO|NEVER|ALWAYS" ,
Groups : "Config" ,
} , {
Name : "default_time" ,
Default : Time ( time . Date ( 2000 , 1 , 1 , 0 , 0 , 0 , 0 , time . UTC ) ) ,
Help : "Time to show if modtime is unknown for files and directories" ,
Groups : "Config,Listing" ,
} , {
Name : "inplace" ,
Default : false ,
Help : "Download directly to destination file instead of atomic download to temp/rename" ,
Groups : "Copy" ,
} , {
Name : "metadata_mapper" ,
Default : SpaceSepList { } ,
Help : "Program to run to transforming metadata before upload" ,
Groups : "Metadata" ,
} , {
Name : "partial_suffix" ,
Default : ".partial" ,
Help : "Add partial-suffix to temporary file name when --inplace is not used" ,
Groups : "Copy" ,
2025-03-21 16:48:00 +00:00
} , {
2025-05-06 15:23:13 +01:00
Name : "max_connections" ,
Help : "Maximum number of simultaneous backend API connections, 0 for unlimited." ,
2025-03-21 16:48:00 +00:00
Default : 0 ,
Advanced : true ,
2025-05-06 15:23:13 +01:00
Groups : "Networking" ,
2025-05-04 03:10:48 -04:00
} , {
Name : "name_transform" ,
Default : [ ] string { } ,
Help : "Transform paths during the copy process." ,
Groups : "Copy" ,
2025-07-02 17:20:58 +01:00
} , {
Name : "http_proxy" ,
Default : "" ,
Help : "HTTP proxy URL." ,
Groups : "Networking" ,
2024-07-09 18:42:01 +01:00
} }
2015-09-22 18:47:16 +01:00
// ConfigInfo is filesystem config options
2014-03-15 16:06:11 +00:00
type ConfigInfo struct {
2024-07-09 18:42:01 +01:00
LogLevel LogLevel ` config:"log_level" `
StatsLogLevel LogLevel ` config:"stats_log_level" `
UseJSONLog bool ` config:"use_json_log" `
DryRun bool ` config:"dry_run" `
Interactive bool ` config:"interactive" `
2024-11-22 11:42:31 +00:00
Links bool ` config:"links" `
2024-07-09 18:42:01 +01:00
CheckSum bool ` config:"checksum" `
SizeOnly bool ` config:"size_only" `
IgnoreTimes bool ` config:"ignore_times" `
IgnoreExisting bool ` config:"ignore_existing" `
IgnoreErrors bool ` config:"ignore_errors" `
ModifyWindow time . Duration ` config:"modify_window" `
Checkers int ` config:"checkers" `
Transfers int ` config:"transfers" `
ConnectTimeout time . Duration ` config:"contimeout" ` // Connect timeout
Timeout time . Duration ` config:"timeout" ` // Data channel timeout
ExpectContinueTimeout time . Duration ` config:"expect_continue_timeout" `
Dump DumpFlags ` config:"dump" `
InsecureSkipVerify bool ` config:"no_check_certificate" ` // Skip server certificate verification
DeleteMode DeleteMode ` config:"delete_mode" `
MaxDelete int64 ` config:"max_delete" `
MaxDeleteSize SizeSuffix ` config:"max_delete_size" `
TrackRenames bool ` config:"track_renames" ` // Track file renames.
TrackRenamesStrategy string ` config:"track_renames_strategy" ` // Comma separated list of strategies used to track renames
Retries int ` config:"retries" ` // High-level retries
RetriesInterval time . Duration ` config:"retries_sleep" `
LowLevelRetries int ` config:"low_level_retries" `
UpdateOlder bool ` config:"update" ` // Skip files that are newer on the destination
NoGzip bool ` config:"no_gzip_encoding" ` // Disable compression
MaxDepth int ` config:"max_depth" `
IgnoreSize bool ` config:"ignore_size" `
IgnoreChecksum bool ` config:"ignore_checksum" `
IgnoreCaseSync bool ` config:"ignore_case_sync" `
FixCase bool ` config:"fix_case" `
NoTraverse bool ` config:"no_traverse" `
CheckFirst bool ` config:"check_first" `
NoCheckDest bool ` config:"no_check_dest" `
NoUnicodeNormalization bool ` config:"no_unicode_normalization" `
NoUpdateModTime bool ` config:"no_update_modtime" `
NoUpdateDirModTime bool ` config:"no_update_dir_modtime" `
DataRateUnit string ` config:"stats_unit" `
CompareDest [ ] string ` config:"compare_dest" `
CopyDest [ ] string ` config:"copy_dest" `
BackupDir string ` config:"backup_dir" `
Suffix string ` config:"suffix" `
SuffixKeepExtension bool ` config:"suffix_keep_extension" `
UseListR bool ` config:"fast_list" `
2024-12-09 11:30:34 +00:00
ListCutoff int ` config:"list_cutoff" `
2024-07-09 18:42:01 +01:00
BufferSize SizeSuffix ` config:"buffer_size" `
BwLimit BwTimetable ` config:"bwlimit" `
BwLimitFile BwTimetable ` config:"bwlimit_file" `
TPSLimit float64 ` config:"tpslimit" `
TPSLimitBurst int ` config:"tpslimit_burst" `
BindAddr net . IP ` config:"bind_addr" `
DisableFeatures [ ] string ` config:"disable" `
UserAgent string ` config:"user_agent" `
Immutable bool ` config:"immutable" `
AutoConfirm bool ` config:"auto_confirm" `
StreamingUploadCutoff SizeSuffix ` config:"streaming_upload_cutoff" `
StatsFileNameLength int ` config:"stats_file_name_length" `
AskPassword bool ` config:"ask_password" `
PasswordCommand SpaceSepList ` config:"password_command" `
UseServerModTime bool ` config:"use_server_modtime" `
MaxTransfer SizeSuffix ` config:"max_transfer" `
MaxDuration time . Duration ` config:"max_duration" `
CutoffMode CutoffMode ` config:"cutoff_mode" `
MaxBacklog int ` config:"max_backlog" `
MaxStatsGroups int ` config:"max_stats_groups" `
StatsOneLine bool ` config:"stats_one_line" `
StatsOneLineDate bool ` config:"stats_one_line_date" ` // If we want a date prefix at all
StatsOneLineDateFormat string ` config:"stats_one_line_date_format" ` // If we want to customize the prefix
ErrorOnNoTransfer bool ` config:"error_on_no_transfer" ` // Set appropriate exit code if no files transferred
Progress bool ` config:"progress" `
ProgressTerminalTitle bool ` config:"progress_terminal_title" `
Cookie bool ` config:"use_cookies" `
UseMmap bool ` config:"use_mmap" `
2025-02-15 18:04:09 +00:00
MaxBufferMemory SizeSuffix ` config:"max_buffer_memory" `
2024-07-09 18:42:01 +01:00
CaCert [ ] string ` config:"ca_cert" ` // Client Side CA
ClientCert string ` config:"client_cert" ` // Client Side Cert
ClientKey string ` config:"client_key" ` // Client Side Key
MultiThreadCutoff SizeSuffix ` config:"multi_thread_cutoff" `
MultiThreadStreams int ` config:"multi_thread_streams" `
MultiThreadSet bool ` config:"multi_thread_set" ` // whether MultiThreadStreams was set (set in fs/config/configflags)
MultiThreadChunkSize SizeSuffix ` config:"multi_thread_chunk_size" ` // Chunk size for multi-thread downloads / uploads, if not set by filesystem
MultiThreadWriteBufferSize SizeSuffix ` config:"multi_thread_write_buffer_size" `
OrderBy string ` config:"order_by" ` // instructions on how to order the transfer
UploadHeaders [ ] * HTTPOption ` config:"upload_headers" `
DownloadHeaders [ ] * HTTPOption ` config:"download_headers" `
Headers [ ] * HTTPOption ` config:"headers" `
MetadataSet Metadata ` config:"metadata_set" ` // extra metadata to write when uploading
RefreshTimes bool ` config:"refresh_times" `
NoConsole bool ` config:"no_console" `
TrafficClass uint8 ` config:"traffic_class" `
FsCacheExpireDuration time . Duration ` config:"fs_cache_expire_duration" `
FsCacheExpireInterval time . Duration ` config:"fs_cache_expire_interval" `
DisableHTTP2 bool ` config:"disable_http2" `
HumanReadable bool ` config:"human_readable" `
KvLockTime time . Duration ` config:"kv_lock_time" ` // maximum time to keep key-value database locked by process
DisableHTTPKeepAlives bool ` config:"disable_http_keep_alives" `
Metadata bool ` config:"metadata" `
ServerSideAcrossConfigs bool ` config:"server_side_across_configs" `
TerminalColorMode TerminalColorMode ` config:"color" `
DefaultTime Time ` config:"default_time" ` // time that directories with no time should display
Inplace bool ` config:"inplace" ` // Download directly to destination file instead of atomic download to temp/rename
PartialSuffix string ` config:"partial_suffix" `
MetadataMapper SpaceSepList ` config:"metadata_mapper" `
2025-03-21 16:48:00 +00:00
MaxConnections int ` config:"max_connections" `
2025-05-04 03:10:48 -04:00
NameTransform [ ] string ` config:"name_transform" `
2025-07-02 17:20:58 +01:00
HTTPProxy string ` config:"http_proxy" `
2018-01-12 16:30:54 +00:00
}
2024-07-09 18:42:01 +01:00
func init ( ) {
2018-01-12 16:30:54 +00:00
// Set any values which aren't the zero for the type
2024-07-09 18:42:01 +01:00
globalConfig . DeleteMode = DeleteModeDefault
// Register the config and fill globalConfig with the defaults
RegisterGlobalOptions ( OptionsInfo { Name : "main" , Opt : globalConfig , Options : ConfigOptionsInfo , Reload : globalConfig . Reload } )
// initial guess at log level from the flags
2025-05-12 15:18:11 +01:00
globalConfig . LogLevel = InitialLogLevel ( )
2024-07-09 18:42:01 +01:00
}
2025-05-12 15:18:11 +01:00
// LogReload is written by fs/log to set variables which should really
// be there but we can't move due to them being visible here in the rc.
var LogReload = func ( * ConfigInfo ) error { return nil }
2024-07-09 18:42:01 +01:00
// Reload assumes the config has been edited and does what is necessary to make it live
func ( ci * ConfigInfo ) Reload ( ctx context . Context ) error {
// Set -vv if --dump is in use
if ci . Dump != 0 && ci . LogLevel != LogLevelDebug {
Logf ( nil , "Automatically setting -vv as --dump is enabled" )
ci . LogLevel = LogLevelDebug
}
// If --dry-run or -i then use NOTICE as minimum log level
if ( ci . DryRun || ci . Interactive ) && ci . StatsLogLevel > LogLevelNotice {
ci . StatsLogLevel = LogLevelNotice
}
// Check --compare-dest and --copy-dest
if len ( ci . CompareDest ) > 0 && len ( ci . CopyDest ) > 0 {
return fmt . Errorf ( "can't use --compare-dest with --copy-dest" )
}
// Check --stats-one-line and dependent flags
switch {
case len ( ci . StatsOneLineDateFormat ) > 0 :
ci . StatsOneLineDate = true
ci . StatsOneLine = true
case ci . StatsOneLineDate :
ci . StatsOneLineDateFormat = "2006/01/02 15:04:05 - "
ci . StatsOneLine = true
}
// Check --partial-suffix
if len ( ci . PartialSuffix ) > 16 {
return fmt . Errorf ( "--partial-suffix: Expecting suffix length not greater than %d but got %d" , 16 , len ( ci . PartialSuffix ) )
}
// Make sure some values are > 0
nonZero := func ( pi * int ) {
if * pi <= 0 {
* pi = 1
}
}
// Check --stats-unit
if ci . DataRateUnit != "bits" && ci . DataRateUnit != "bytes" {
Errorf ( nil , "Unknown unit %q passed to --stats-unit. Defaulting to bytes." , ci . DataRateUnit )
ci . DataRateUnit = "bytes"
}
// Check these are all > 0
nonZero ( & ci . Retries )
nonZero ( & ci . LowLevelRetries )
nonZero ( & ci . Transfers )
nonZero ( & ci . Checkers )
2025-05-12 15:18:11 +01:00
return LogReload ( ci )
2024-07-09 18:42:01 +01:00
}
2025-05-12 15:18:11 +01:00
// InitialLogLevel performs a simple check for debug flags to enable
// debug logging during the flag initialization.
func InitialLogLevel ( ) LogLevel {
2024-07-09 18:42:01 +01:00
logLevel := LogLevelNotice
2021-05-20 14:08:01 +02:00
for argIndex , arg := range os . Args {
if strings . HasPrefix ( arg , "-vv" ) && strings . TrimRight ( arg , "v" ) == "-" {
2024-07-09 18:42:01 +01:00
logLevel = LogLevelDebug
2021-05-20 14:08:01 +02:00
}
if arg == "--log-level=DEBUG" || ( arg == "--log-level" && len ( os . Args ) > argIndex + 1 && os . Args [ argIndex + 1 ] == "DEBUG" ) {
2024-07-09 18:42:01 +01:00
logLevel = LogLevelDebug
2021-05-20 14:08:01 +02:00
}
2021-10-02 12:50:11 +03:00
if strings . HasPrefix ( arg , "--verbose=" ) {
if level , err := strconv . Atoi ( arg [ 10 : ] ) ; err == nil && level >= 2 {
2024-07-09 18:42:01 +01:00
logLevel = LogLevelDebug
2021-10-02 12:50:11 +03:00
}
}
2021-05-20 14:08:01 +02:00
}
envValue , found := os . LookupEnv ( "RCLONE_LOG_LEVEL" )
if found && envValue == "DEBUG" {
2024-07-09 18:42:01 +01:00
logLevel = LogLevelDebug
2021-05-20 14:08:01 +02:00
}
2024-07-09 18:42:01 +01:00
return logLevel
2015-05-10 11:25:54 +01:00
}
2018-05-16 16:30:09 +01:00
2021-03-01 12:05:36 +00:00
// TimeoutOrInfinite returns ci.Timeout if > 0 or infinite otherwise
2024-07-09 18:42:01 +01:00
func ( ci * ConfigInfo ) TimeoutOrInfinite ( ) time . Duration {
if ci . Timeout > 0 {
return ci . Timeout
2021-03-01 12:05:36 +00:00
}
return ModTimeNotSupported
}
2020-11-05 11:33:32 +00:00
type configContextKeyType struct { }
// Context key for config
var configContextKey = configContextKeyType { }
// GetConfig returns the global or context sensitive context
func GetConfig ( ctx context . Context ) * ConfigInfo {
if ctx == nil {
return globalConfig
}
c := ctx . Value ( configContextKey )
if c == nil {
return globalConfig
}
return c . ( * ConfigInfo )
}
2021-02-19 13:13:54 +00:00
// CopyConfig copies the global config (if any) from srcCtx into
// dstCtx returning the new context.
func CopyConfig ( dstCtx , srcCtx context . Context ) context . Context {
if srcCtx == nil {
return dstCtx
}
c := srcCtx . Value ( configContextKey )
if c == nil {
return dstCtx
}
return context . WithValue ( dstCtx , configContextKey , c )
}
2020-11-05 11:33:32 +00:00
// AddConfig returns a mutable config structure based on a shallow
// copy of that found in ctx and returns a new context with that added
// to it.
func AddConfig ( ctx context . Context ) ( context . Context , * ConfigInfo ) {
c := GetConfig ( ctx )
cCopy := new ( ConfigInfo )
* cCopy = * c
newCtx := context . WithValue ( ctx , configContextKey , cCopy )
return newCtx , cCopy
}
2021-09-16 19:39:46 +02:00
// ConfigToEnv converts a config section and name, e.g. ("my-remote",
2018-05-16 16:30:09 +01:00
// "ignore-size") into an environment name
2021-09-16 19:39:46 +02:00
// "RCLONE_CONFIG_MY-REMOTE_IGNORE_SIZE"
2018-05-16 16:30:09 +01:00
func ConfigToEnv ( section , name string ) string {
2022-05-17 00:11:45 +08:00
return "RCLONE_CONFIG_" + strings . ToUpper ( section + "_" + strings . ReplaceAll ( name , "-" , "_" ) )
2018-05-16 16:30:09 +01:00
}
2020-10-13 17:49:58 -04:00
// OptionToEnv converts an option name, e.g. "ignore-size" into an
2018-05-16 16:30:09 +01:00
// environment name "RCLONE_IGNORE_SIZE"
func OptionToEnv ( name string ) string {
2022-05-17 00:11:45 +08:00
return "RCLONE_" + strings . ToUpper ( strings . ReplaceAll ( name , "-" , "_" ) )
2018-05-16 16:30:09 +01:00
}