Compare commits

...
72 Commits
Author SHA1 Message Date
Nick Craig-Wood 2c12ca64d4 Version v1.73.5 2026-04-19 11:42:48 +01:00
Nick Craig-Wood 2a9e952b38 operations: add AuthRequired to operations/fsinfo to prevent backend creation CVE-2026-41179
The operations/fsinfo RC endpoint was registered without AuthRequired,
allowing unauthenticated callers to instantiate arbitrary backends via
inline backend definitions.

See GHSA-jfwf-28xr-xw6q
2026-04-19 11:32:18 +01:00
Nick Craig-Wood c097c36064 rc: snapshot NoAuth at startup to prevent runtime auth bypass CVE-2026-41176
Snapshot the NoAuth setting when the RC server is created rather than
reading it from the mutable options struct on each request. This
prevents any runtime mutation of rc.NoAuth (e.g. via options/set)
from disabling the auth gate for protected RC methods.

See GHSA-25qr-6mpr-f7qx
2026-04-19 11:32:18 +01:00
Nick Craig-Wood cfa9072d9f rc: add AuthRequired to options/set to prevent auth bypass CVE-2026-41176
The options/set RC endpoint was registered without AuthRequired,
allowing unauthenticated callers to mutate global runtime options
including rc.NoAuth, which disables the auth gate for all protected
RC methods. Require authentication for options/set.

See GHSA-25qr-6mpr-f7qx
2026-04-19 11:32:18 +01:00
Nick Craig-Wood 03eed87045 s3: fix empty delimiter parameter rejected by Archiware P5 server
Some S3-compatible servers (e.g. Archiware P5) reject requests with an
empty `?delimiter=` query parameter. For recursive listings, pass `nil`
instead of a pointer to an empty string so the parameter is omitted
entirely from the request.

Fixes #9342
2026-04-19 10:34:15 +01:00
Nick Craig-Wood e4e4c5efe0 azureblob/auth: add Microsoft Partner Network User-Agent prefix
Set the User-Agent to include the APN prefix for Azure backends
(azureblob, azurefiles, onelake) to identify rclone as a Microsoft
Partner. The User-Agent is now:

    APN/1.0 rclone/1.0 rclone/<version>
2026-04-19 10:34:15 +01:00
a1pcm 08eecf4cc8 drime: fix User.EntryPermissions JSON unmarshalling
`json:"entry_permissions"` is known to be either empty [] or of
structure {string: boolean}. This may have been a breaking API change on
Drime's side. Because EntryPermissions is not used, the type was changed
to `any` to capture both cases, otherwise we could implement custom
unmarshalling for that type.
2026-04-19 10:34:15 +01:00
Nick Craig-Wood 5cd87e2d75 filter: fix debug logs that fire before logger is configured - fixes #9291
These Debugf calls in NewFilter() ran during GlobalOptionsInit(), before
InitLogging() configured the JSON log format. This caused plain-text
debug lines to leak to stderr when --use-json-log was set, breaking
tooling that expected only JSON output.

The resolved time values are already available via --dump filters so
this commit removes the debug messages.
2026-04-19 10:34:15 +01:00
Mozi f86f0518c3 s3: fix TencentCOS CDN endpoint failing on bucket check
The Global Acceleration Endpoint (cos.accelerate.myqcloud.com) of
Tencent COS does not seem to support "CreateBucket" (maybe also other
bucket management operations). Since the acceleration functionality must
be enabled per-bucket in the Tencent Cloud console, the bucket will
always exist before this endpoint is used, so this check can be safely
skipped.

Now, "no_check_bucket = true" will be auto set when using this endpoint.

Why "NewFs()": on-the-fly remotes (connection string remotes), for
example, ":s3,provider=TencentCOS,...:..." will also be fixed.

Why no unit test: I can't find a good way to test "NewFs()" without
leveraging live endpoints. I think we can extract all existing mutations
for different providers (e.g., AWS, Fastly, and Rabata) from "NewFs()"
to a new function in the future.

Some Tencent docs about this CDN endpoint:
- English: Global Acceleration Endpoint | https://www.tencentcloud.com/pt/document/product/436/40700
- Chinese: 对象存储 全球加速概述_腾讯云 | https://cloud.tencent.com/document/product/436/38866

Assisted-By: OpenCode
2026-04-19 10:34:07 +01:00
Brais Couce d6c937f908 iclouddrive: fix 'directory not found' error when the directory contains accent marks 2026-04-19 10:30:56 +01:00
Nick Craig-Wood b5465afd1c Start v1.73.5-DEV development 2026-04-08 16:42:50 +01:00
Nick Craig-Wood 984d07c9c3 Version v1.73.4 2026-04-08 12:19:50 +01:00
Nick Craig-Wood 06c054bbc8 Update to go 1.25.9 to fix multiple CVEs
- CVE-2026-32282: os: Root.Chmod can follow symlinks out of the root on Linux
- CVE-2026-32289: html/template: JS template literal context incorrectly tracked
- CVE-2026-33810: crypto/x509: excluded DNS constraints not properly applied to wildcard domains
- CVE-2026-27144: cmd/compile: no-op interface conversion bypasses overlap checking
- CVE-2026-27143: cmd/compile: possible memory corruption after bound check elimination
- CVE-2026-32288: archive/tar: unbounded allocation when parsing old format GNU sparse map
- CVE-2026-32283: crypto/tls: multiple key update handshake messages can cause connection to deadlock
- CVE-2026-27140: cmd/go: trust layer bypass when using cgo and SWIG
- CVE-2026-32280: crypto/x509: unexpected work during chain building
- CVE-2026-32281: crypto/x509: inefficient policy validation

Fixes #9302
2026-04-08 09:54:10 +01:00
dependabot[bot] 6987bc1318 build: fix Denial of Service due to Panic in AWS SDK for Go v2 SDK EventStream Decoder
Bumps [github.com/aws/aws-sdk-go-v2/service/s3](https://github.com/aws/aws-sdk-go-v2) from v1.90.0 to 1.97.3.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/s3/v1.90.0...service/s3/v1.97.3)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/service/s3
  dependency-version: 1.97.3
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-08 09:47:02 +01:00
albertony c9ea98e752 docs: fix markdown issues in mount docs 2026-04-08 09:45:39 +01:00
Clément Notin 4c5deb435c docs: fix header level for metadata option 2026-04-08 09:45:39 +01:00
Ross Smith II d757bd6645 fix(docs): Fix link to not be language specific 2026-04-08 09:45:39 +01:00
Enduriel 6b44b65fba filen: update SDK version
- increase timeout for http requests
- only use a single URL per request type
2026-04-08 09:45:39 +01:00
dependabot[bot] 28805943b0 build(deps): bump golang.org/x/image from 0.36.0 to 0.38.0
Bumps [golang.org/x/image](https://github.com/golang/image) from 0.36.0 to 0.38.0.
- [Commits](https://github.com/golang/image/compare/v0.36.0...v0.38.0)

---
updated-dependencies:
- dependency-name: golang.org/x/image
  dependency-version: 0.38.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-08 09:45:07 +01:00
kapitainsky 2ed57c301b docs: note macOS 10.15 (Catalina) support with version v1.70.3
due to min golang requirements macOS Catalina (10.15) can not run newer rclone versions
2026-04-08 09:30:46 +01:00
Nick Craig-Wood 3e8d4f2118 Start v1.73.4-DEV development 2026-03-23 23:03:10 +00:00
Nick Craig-Wood 0f6401e57e Version v1.73.3 2026-03-23 17:16:56 +00:00
dependabot[bot] 543ac7c50c build(deps): bump github.com/buger/jsonparser from 1.1.1 to 1.1.2
Bumps [github.com/buger/jsonparser](https://github.com/buger/jsonparser) from 1.1.1 to 1.1.2.
- [Release notes](https://github.com/buger/jsonparser/releases)
- [Commits](https://github.com/buger/jsonparser/compare/v1.1.1...v1.1.2)

---
updated-dependencies:
- dependency-name: github.com/buger/jsonparser
  dependency-version: 1.1.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-23 17:05:59 +00:00
albertony 61b4897c33 docs/jottacloud: fix broken link 2026-03-23 17:02:15 +00:00
Jason 504042f6aa docs: clarify Filen password change requires updating both password and API key in rclone config 2026-03-23 17:02:15 +00:00
Jason 68996b4429 docs: note that Filen API key changes on password change 2026-03-23 17:02:15 +00:00
dependabot[bot] 83025eaef2 build(deps): bump google.golang.org/grpc from 1.79.1 to 1.79.3
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.79.1 to 1.79.3.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.79.1...v1.79.3)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.79.3
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-23 17:02:07 +00:00
Marco Ferretti 634e93e339 s3: add multi tenant support for Cubbit 2026-03-23 16:58:04 +00:00
Andrew Furman f9bf6d823e lib/rest: fix URLPathEscapeAll breaking WebDAV servers (eg nzbdav) with strict path matching
URLPathEscapeAll was only passing [A-Za-z0-9/] through unencoded, causing
it to percent-encode RFC 3986 unreserved characters (-, ., _, ~). Per RFC
3986 §2.3, unreserved characters MUST NOT be percent-encoded, and a URI
that unnecessarily encodes them is not equivalent to one that does not.

Servers that perform strict path matching without normalising
percent-encoded characters will reject the over-encoded form with a 404.

Before: /files/my-report.pdf → /files/my%2Dreport%2Epdf
After:  /files/my-report.pdf → /files/my-report.pdf

Reserved characters (spaces, semicolons, colons, etc.) continue to be
encoded as before.
2026-03-23 16:58:04 +00:00
Nick Craig-Wood 14defb23dc list: fix nil pointer panic in Sorter when temp file creation fails
When extsort.Strings() cannot create temporary files (e.g. due to
apparmor restrictions or permission denied), it returns a nil sorter
with the error on errChan. The code then called Sort() on the nil
sorter, causing a panic.

Check for nil sorter and return the error instead of panicking.

Fixes #9244
2026-03-23 16:58:04 +00:00
Nick Craig-Wood 00b47c99a5 docs: update RELEASE procedure to avoid mistakes 2026-03-23 16:58:04 +00:00
Jan-Philipp ReßlerandJan-Philipp Reßler c7f4adb970 docs: added text to the label showing version-introduced info
Co-authored-by: Jan-Philipp Reßler <xodarap@xodarap.de>
2026-03-23 16:58:04 +00:00
Nick Craig-Wood 9468ac3129 Start v1.73.3-DEV development 2026-03-23 16:56:58 +00:00
Nick Craig-Wood 9fce660b4b docs: update sponsors 2026-03-08 11:12:34 +00:00
Nick Craig-Wood c0f03f8ac0 Version v1.73.2 2026-03-06 18:45:23 +00:00
Nick Craig-Wood 5f149a91c4 Update to go 1.25.8 to fix multiple CVEs
This fixes the following CVEs

- CVE-2026-27137
- CVE-2026-27138
- CVE-2026-25679
- CVE-2026-27142

This disables the go1.24 build as the updates no longer build on go1.24

Fixes #9220
2026-03-06 14:12:25 +00:00
Nick Craig-Wood 41fb73c669 build: update to golang.org/x/net v0.51.0 to fix CVE-2026-27141 #9220
See: https://pkg.go.dev/vuln/GO-2026-4559
2026-03-06 13:19:22 +00:00
razorloves 4b63e78358 docs: fix new drive flag typo in changelog 2026-03-06 13:19:22 +00:00
Romāns Potašovs 690587ebbf webdav: add missing headers for CORS
fix #7492
2026-03-06 13:19:22 +00:00
Adam Kasztenny 3821c64711 docs: Document unsupported S3 object keys with double slashes
Fixes #5063 by documenting that S3 object keys containing
consecutive forward slashes (//) are not supported by rclone.

The issue occurs because rclone normalizes paths like "a//b" to "a/b",
causing "object not found" errors when trying to access the original
object. This documentation addition explicitly warns users about this
limitation and provides workarounds.

Changes:
- Added new subsection "Important note about double slashes (//)"
  under "Restricted filename characters" in S3 documentation
- Explains the normalization behavior and its consequences
- Provides clear examples and workarounds

AI Model/Tool Attribution:
- Implemented using opencode AI assistant
- Issue analysis and documentation update performed by AI tools

Resolves: #5063
2026-03-06 13:19:22 +00:00
Nick Craig-Wood dc73dba9b5 docs: note that --use-server-modtime only works on some backends
Closes #6977
2026-03-06 13:19:22 +00:00
jzunigax2 9267568fe3 internxt: fix Entry doesn't belong in directory errors on windows 2026-03-06 13:19:22 +00:00
a1pcm a285c9eeee drime: fix chunk-uploaded files ignoring workspace ID
When specifying --drime-workspace-id, a file greater than the limit at
which file uploads get chunked would ignore the specified ID and get put
into the default workspace instead.

Completes the fix described in commit 2360e65 by properly closing the
chunkwriter by providing the workspace ID to the Drime API call.
2026-03-06 13:19:22 +00:00
Dark Dragon cf4d78e3c9 docs: Fix headers hierarchy for mount.md
Similar to "Mounting on macOS", "Mounting on Linux" needs to move one layer down. This also fixes the missing anchor overlay on hover.
2026-03-06 13:19:22 +00:00
Varun Chawla ea29edb35d webdav: escape reserved characters in URL path segments
Use URLPathEscapeAll instead of URLPathEscape for path encoding.

URLPathEscape relies on Go's url.URL.String() which only minimally
escapes paths - reserved sub-delimiter characters like semicolons and
equals signs pass through unescaped. Per RFC 3986 section 3.3, these
characters must be percent-encoded when used as literal values in
path segments.

Some WebDAV servers (notably dCache/Jetty) interpret unescaped
semicolons as path parameter delimiters, which truncates filenames
at the semicolon position. URLPathEscapeAll encodes everything
except [A-Za-z0-9/], which is safe for all servers.

Fixes #9082
2026-03-06 13:19:22 +00:00
Jan-Philipp ReßlerandJan-Philipp Reßler de93ad8744 bisync: add group Sync to the bisync command
Co-authored-by: Jan-Philipp Reßler <xodarap@xodarap.de>
2026-03-06 13:19:22 +00:00
Varun Chawla 9bfc1a7a8a archive: extract: strip "./" prefix from tar entry paths
Tar files created from the current directory (e.g. tar -czf archive.tar.gz .)
produce entries prefixed with "./". When extracting, rclone's character
encoding replaces the "." with a full-width dot (U+FF0E), creating a
spurious directory instead of merging into the destination root.

Strip the leading "./" from NameInArchive before processing. Only "./"
is stripped specifically to avoid enabling path traversal attacks via
"../".

Fixes #9168
2026-03-06 13:19:22 +00:00
Nick Craig-Wood d9e455d1d3 docs: add instructions on how to update Go version 2026-03-06 13:19:22 +00:00
Nick Craig-Wood 7502ec934b buid: update github.com/cloudflare/circl to v1.6.3 to fix CVE-2026-1229
Fixes #9227
2026-03-04 11:24:31 +00:00
Nick Craig-Wood bffc49742c Start v1.73.2-DEV development 2026-02-17 18:21:06 +00:00
Nick Craig-Wood c7dab94e94 Version v1.73.1 2026-02-17 16:55:43 +00:00
Nick Craig-Wood 615a6f57bb build: fix build using go 1.26.0 instead of go 1.25.7
In the actions config use Go ~1.25.7 to pin the go version to 1.25.x,
x >= 7.

Before this it was choosing Go 1.26.0 which isn't what we want.
2026-02-17 16:48:52 +00:00
Nick Craig-Wood b52fab6868 fs/march: fix runtime: program exceeds 10000-thread limit
Before this change when doing a sync with `--no-traverse` and
`--files-from` we could call `NewObject` a total of `--checkers` *
`--checkers` times simultaneously.

With `--checkers 128` this can exceed the 10,000 thread limit and
fails when run on a local to local transfer because `NewObject` calls
`lstat` which is a syscall which needs an OS thread of its own.

This patch uses a weighted semaphore to limit the number of
simultaneous calls to `NewObject` to `--checkers` instead which won't
blow the 10,000 thread limit and is far more sensible use of OS
resources.

Fixes #9073
2026-02-17 16:35:26 +00:00
Nick Craig-Wood b740e9c299 accounting: fix missing server side stats from core/stats rc
These stats weren't being updated in the global stats read by rc
core/stats:

- transferQueue
- deletesSize
- serverSideCopies
- serverSideCopyBytes
- serverSideMoves
- serverSideMoveBytes
2026-02-17 16:35:26 +00:00
Nick Craig-Wood 3b63bd280c pacer: re-read the sleep time as it may be stale
Before this change we read sleepTime before acquiring the pacer token
and uses that possibly stale value to schedule the token return. When
many goroutines enter while sleepTime is high (e.g., 10s), each
goroutine caches this 10s value. Even if successful calls rapidly
decay the pacer state to 0, the queued goroutines still schedule 10s
token returns, so the queue drains at 1 req/10s for the entire herd.
This can create multi‑minute delays even after the pacer has dropped
to 0.

After this change we refresh the sleep time after getting the token.

This problem was introduced by the desire to skip reading the pacer
token entirely when sleepTime is 0 in high performance backends (eg
s3, azure blob).
2026-02-17 16:35:26 +00:00
Nick Craig-Wood 3a902dd1a0 pacer: fix deadlock between pacer token and --max-connections
It was possible in the presence of --max-connections and recursive
calls to the pacer to deadlock it leaving all connections waiting on
either a max connection token or a pacer token.

This fixes the problem by making sure we return the pacer token on
schedule if we take it.

This also short circuits the pacer token if sleepTime is 0.
2026-02-17 16:35:26 +00:00
Nick Craig-Wood 1e24958861 build: fix CVE-2025-68121 by updating go to 1.25.7 or later - fixes #9167 2026-02-17 16:35:26 +00:00
Nick Craig-Wood 77e0a760d8 drime: fix files and directories being created in the default workspace
Before this change directories and files were created in the default
workspace, not the workspace specified by --drime-workspace-id.
2026-02-17 16:35:26 +00:00
Nick Craig-Wood e16ac436f7 docs: update sponsors 2026-02-17 16:35:26 +00:00
Jack Kelly 1f34163857 copyurl: Extend copyurl docs with an example of CSV FILENAMEs starting with a path. 2026-02-17 16:35:26 +00:00
José Zúniga 132184a47f internxt: implement re-login under refresh logic, improve retry logic - fixes #9174 2026-02-17 16:35:26 +00:00
Nick Craig-Wood 6e78bb1c40 docs: add ExchangeRate-API as a sponsor 2026-02-17 16:35:26 +00:00
albertony d720452656 build: bump github.com/go-chi/chi/v5 from 5.2.3 to 5.2.5 to fix GO-2026-4316 2026-02-17 16:35:26 +00:00
kingston125 a8d374f068 Set list_version to 2 for FileLu S3 configuration 2026-02-17 16:35:26 +00:00
kingston125 53fbeb21c8 filelu: add multipart upload support with configurable cutoff 2026-02-17 16:35:26 +00:00
kingston125 350a9bc389 filelu: add multipart init response type 2026-02-17 16:35:25 +00:00
kingston125 6ba40cc97e filelu: add comment for response body wrapping 2026-02-17 16:35:25 +00:00
kingston125 1d2a159c6a filelu: avoid buffering entire file in memory
Avoid buffering the entire file in memory during download, especially
for large files.
2026-02-17 16:35:25 +00:00
Nick Craig-Wood 1adc3e241d docs: update sponsor logos 2026-02-17 16:35:25 +00:00
Enduriel d5483e3e93 filen: fix potential panic in case of error during upload 2026-02-17 16:35:25 +00:00
Enduriel d6bc7a69a1 filen: fix 32 bit targets not being able to list directories Fixes #9142
or do pretty much anything,
this was caused by timestamps not being read to 64 bit integers
2026-02-17 16:35:25 +00:00
Nick Craig-Wood 3311b72407 Start v1.73.1-DEV development 2026-02-17 12:16:33 +00:00
67 changed files with 3920 additions and 1880 deletions

No files matched your search

+9 -15
View File
@@ -29,12 +29,12 @@ jobs:
strategy:
fail-fast: false
matrix:
job_name: ['linux', 'linux_386', 'mac_amd64', 'mac_arm64', 'windows', 'other_os', 'go1.24']
job_name: ['linux', 'linux_386', 'mac_amd64', 'mac_arm64', 'windows', 'other_os']
include:
- job_name: linux
os: ubuntu-latest
go: '>=1.25.0-rc.1'
go: '~1.25.9'
gotags: cmount
build_flags: '-include "^linux/"'
check: true
@@ -45,14 +45,14 @@ jobs:
- job_name: linux_386
os: ubuntu-latest
go: '>=1.25.0-rc.1'
go: '~1.25.9'
goarch: 386
gotags: cmount
quicktest: true
- job_name: mac_amd64
os: macos-latest
go: '>=1.25.0-rc.1'
go: '~1.25.9'
gotags: 'cmount'
build_flags: '-include "^darwin/amd64" -cgo'
quicktest: true
@@ -61,14 +61,14 @@ jobs:
- job_name: mac_arm64
os: macos-latest
go: '>=1.25.0-rc.1'
go: '~1.25.9'
gotags: 'cmount'
build_flags: '-include "^darwin/arm64" -cgo -macos-arch arm64 -cgo-cflags=-I/usr/local/include -cgo-ldflags=-L/usr/local/lib'
deploy: true
- job_name: windows
os: windows-latest
go: '>=1.25.0-rc.1'
go: '~1.25.9'
gotags: cmount
cgo: '0'
build_flags: '-include "^windows/"'
@@ -78,17 +78,11 @@ jobs:
- job_name: other_os
os: ubuntu-latest
go: '>=1.25.0-rc.1'
go: '~1.25.9'
build_flags: '-exclude "^(windows/|darwin/|linux/)"'
compile_all: true
deploy: true
- job_name: go1.24
os: ubuntu-latest
go: '1.24'
quicktest: true
racequicktest: true
name: ${{ matrix.job_name }}
runs-on: ${{ matrix.os }}
@@ -224,7 +218,7 @@ jobs:
id: setup-go
uses: actions/setup-go@v6
with:
go-version: '>=1.24.0-rc.1'
go-version: '~1.25.9'
check-latest: true
cache: false
@@ -315,7 +309,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version: '>=1.25.0-rc.1'
go-version: '~1.25.9'
- name: Set global environment variables
run: |
Generated
+1714 -1408
View File
File diff suppressed because it is too large. Load diff
Generated
+252 -44
View File
@@ -1,6 +1,6 @@
% rclone(1) User Manual
% Nick Craig-Wood
% Jan 30, 2026
% Apr 19, 2026
# NAME
@@ -3768,6 +3768,26 @@ Flags for anything which can copy a file
-u, --update Skip files that are newer on the destination
```
### Sync Options
Flags used for sync commands
```text
--backup-dir string Make backups into hierarchy based in DIR
--delete-after When synchronizing, delete files on destination after transferring (default)
--delete-before When synchronizing, delete files on destination before transferring
--delete-during When synchronizing, delete files during transfer
--fix-case Force rename of case insensitive dest to match source
--ignore-errors Delete even if there are I/O errors
--list-cutoff int To save memory, sort directory listings on disk above this threshold (default 1000000)
--max-delete int When synchronizing, limit the number of deletes (default -1)
--max-delete-size SizeSuffix When synchronizing, limit the total size of deletes (default off)
--suffix string Suffix to add to changed files
--suffix-keep-extension Preserve the extension when using --suffix
--track-renames When synchronizing, track file renames and do a server-side move if possible
--track-renames-strategy string Strategies to use when synchronizing using track-renames hash|modtime|leaf (default "hash")
```
### Important Options
Important flags useful for most commands
@@ -5388,12 +5408,12 @@ rclone convmv "stories/The Quick Brown Fox!.txt" --name-transform "all,command=e
```console
rclone convmv "stories/The Quick Brown Fox!" --name-transform "date=-{YYYYMMDD}"
// Output: stories/The Quick Brown Fox!-20260130
// Output: stories/The Quick Brown Fox!-20260419
```
```console
rclone convmv "stories/The Quick Brown Fox!" --name-transform "date=-{macfriendlytime}"
// Output: stories/The Quick Brown Fox!-2026-01-30 0825PM
// Output: stories/The Quick Brown Fox!-2026-04-19 1137AM
```
```console
@@ -5841,6 +5861,15 @@ Note that `--stdout` and `--print-filename` are incompatible with `--urls`.
This will do `--transfers` copies in parallel. Note that if `--auto-filename`
is desired for all URLs then a file with only URLs and no filename can be used.
Each FILENAME in the CSV file can start with a relative path which will be appended
to the destination path provided at the command line. For example, running the command
shown above with the following CSV file will write two files to the destination:
`remote:dir/local/path/bar.json` and `remote:dir/another/local/directory/qux.json`
```csv
https://example.org/foo/bar.json,local/path/bar.json
https://example.org/qux/baz.json,another/local/directory/qux.json
```
## Troubleshooting
If you can't get `rclone copyurl` to work then here are some things you can try:
@@ -6892,7 +6921,8 @@ Mount the remote as file system on a mountpoint.
Rclone mount allows Linux, FreeBSD, macOS and Windows to
mount any of Rclone's cloud storage systems as a file system with FUSE.
First set up your remote using `rclone config`. Check it works with `rclone ls` etc.
First set up your remote using `rclone config`. Check it works with `rclone ls`
etc.
On Linux and macOS, you can run mount in either foreground or background (aka
daemon) mode. Mount runs in foreground mode by default. Use the `--daemon` flag
@@ -6920,8 +6950,8 @@ The following examples will mount to an automatically assigned drive,
to specific drive letter `X:`, to path `C:\path\parent\mount`
(where parent directory or drive must exist, and mount must **not** exist,
and is not supported when [mounting as a network drive](#mounting-modes-on-windows)),
and the last example will mount as network share `\\cloud\remote` and map it to an
automatically assigned drive:
and the last example will mount as network share `\\cloud\remote` and map it to
an automatically assigned drive:
```console
rclone mount remote:path/to/files *
@@ -7027,8 +7057,8 @@ rclone mount remote:path/to/files X: --volname \\server\share
You may also specify the network share UNC path as the mountpoint itself. Then rclone
will automatically assign a drive letter, same as with `*` and use that as
mountpoint, and instead use the UNC path specified as the volume name, as if it were
specified with the `--volname` option. This will also implicitly set
mountpoint, and instead use the UNC path specified as the volume name, as if it
were specified with the `--volname` option. This will also implicitly set
the `--network-mode` option. This means the following two examples have same result:
```console
@@ -7159,7 +7189,7 @@ does not suffer from the same limitations.
Mounting on macOS can be done either via [built-in NFS server](https://rclone.org/commands/rclone_serve_nfs/),
[macFUSE](https://osxfuse.github.io/) (also known as osxfuse) or
[FUSE-T](https://www.fuse-t.org/).macFUSE is a traditional FUSE driver utilizing
[FUSE-T](https://www.fuse-t.org/). macFUSE is a traditional FUSE driver utilizing
a macOS kernel extension (kext). FUSE-T is an alternative FUSE system which
"mounts" via an NFSv4 local server.
@@ -7202,29 +7232,30 @@ current as of FUSE-T version 1.0.14.
As per the [FUSE-T wiki](https://github.com/macos-fuse-t/fuse-t/wiki#caveats):
> File access and modification times cannot be set separately as it seems to be an
> issue with the NFS client which always modifies both. Can be reproduced with
> 'touch -m' and 'touch -a' commands
> File access and modification times cannot be set separately as it seems to be
> an issue with the NFS client which always modifies both. Can be reproduced
> with `touch -m` and `touch -a` commands
This means that viewing files with various tools, notably macOS Finder, will cause
rlcone to update the modification time of the file. This may make rclone upload a
full new copy of the file.
This means that viewing files with various tools, notably macOS Finder, will
cause rlcone to update the modification time of the file. This may make rclone
upload a full new copy of the file.
#### Read Only mounts
When mounting with `--read-only`, attempts to write to files will fail *silently*
as opposed to with a clear warning as in macFUSE.
# Mounting on Linux
## Mounting on Linux
On newer versions of Ubuntu, you may encounter the following error when running
`rclone mount`:
> NOTICE: mount helper error: fusermount3: mount failed: Permission denied
> CRITICAL: Fatal error: failed to mount FUSE fs: fusermount: exit status 1
This may be due to newer [Apparmor](https://wiki.ubuntu.com/AppArmor) restrictions,
which can be disabled with `sudo aa-disable /usr/bin/fusermount3` (you may need to
`sudo apt install apparmor-utils` beforehand).
which can be disabled with `sudo aa-disable /usr/bin/fusermount3` (you may need
to `sudo apt install apparmor-utils` beforehand).
## Limitations
@@ -8334,7 +8365,8 @@ Mount the remote as file system on a mountpoint.
Rclone nfsmount allows Linux, FreeBSD, macOS and Windows to
mount any of Rclone's cloud storage systems as a file system with FUSE.
First set up your remote using `rclone config`. Check it works with `rclone ls` etc.
First set up your remote using `rclone config`. Check it works with `rclone ls`
etc.
On Linux and macOS, you can run mount in either foreground or background (aka
daemon) mode. Mount runs in foreground mode by default. Use the `--daemon` flag
@@ -8362,8 +8394,8 @@ The following examples will mount to an automatically assigned drive,
to specific drive letter `X:`, to path `C:\path\parent\mount`
(where parent directory or drive must exist, and mount must **not** exist,
and is not supported when [mounting as a network drive](#mounting-modes-on-windows)),
and the last example will mount as network share `\\cloud\remote` and map it to an
automatically assigned drive:
and the last example will mount as network share `\\cloud\remote` and map it to
an automatically assigned drive:
```console
rclone nfsmount remote:path/to/files *
@@ -8469,8 +8501,8 @@ rclone nfsmount remote:path/to/files X: --volname \\server\share
You may also specify the network share UNC path as the mountpoint itself. Then rclone
will automatically assign a drive letter, same as with `*` and use that as
mountpoint, and instead use the UNC path specified as the volume name, as if it were
specified with the `--volname` option. This will also implicitly set
mountpoint, and instead use the UNC path specified as the volume name, as if it
were specified with the `--volname` option. This will also implicitly set
the `--network-mode` option. This means the following two examples have same result:
```console
@@ -8601,7 +8633,7 @@ does not suffer from the same limitations.
Mounting on macOS can be done either via [built-in NFS server](https://rclone.org/commands/rclone_serve_nfs/),
[macFUSE](https://osxfuse.github.io/) (also known as osxfuse) or
[FUSE-T](https://www.fuse-t.org/).macFUSE is a traditional FUSE driver utilizing
[FUSE-T](https://www.fuse-t.org/). macFUSE is a traditional FUSE driver utilizing
a macOS kernel extension (kext). FUSE-T is an alternative FUSE system which
"mounts" via an NFSv4 local server.
@@ -8644,29 +8676,30 @@ current as of FUSE-T version 1.0.14.
As per the [FUSE-T wiki](https://github.com/macos-fuse-t/fuse-t/wiki#caveats):
> File access and modification times cannot be set separately as it seems to be an
> issue with the NFS client which always modifies both. Can be reproduced with
> 'touch -m' and 'touch -a' commands
> File access and modification times cannot be set separately as it seems to be
> an issue with the NFS client which always modifies both. Can be reproduced
> with `touch -m` and `touch -a` commands
This means that viewing files with various tools, notably macOS Finder, will cause
rlcone to update the modification time of the file. This may make rclone upload a
full new copy of the file.
This means that viewing files with various tools, notably macOS Finder, will
cause rlcone to update the modification time of the file. This may make rclone
upload a full new copy of the file.
#### Read Only mounts
When mounting with `--read-only`, attempts to write to files will fail *silently*
as opposed to with a clear warning as in macFUSE.
# Mounting on Linux
## Mounting on Linux
On newer versions of Ubuntu, you may encounter the following error when running
`rclone mount`:
> NOTICE: mount helper error: fusermount3: mount failed: Permission denied
> CRITICAL: Fatal error: failed to mount FUSE fs: fusermount: exit status 1
This may be due to newer [Apparmor](https://wiki.ubuntu.com/AppArmor) restrictions,
which can be disabled with `sudo aa-disable /usr/bin/fusermount3` (you may need to
`sudo apt install apparmor-utils` beforehand).
which can be disabled with `sudo aa-disable /usr/bin/fusermount3` (you may need
to `sudo apt install apparmor-utils` beforehand).
## Limitations
@@ -18685,7 +18718,7 @@ This is the default.
`CAUTIOUS` will try to prevent rclone from reaching the limit. Only applicable
for `--max-transfer`.
## -M, --metadata
### -M, --metadata
Setting this flag enables rclone to copy the metadata from the source
to the destination. For local backends this is ownership, permissions,
@@ -19587,6 +19620,10 @@ knowing the local file is newer than the time it was last uploaded to the
remote is sufficient. In those cases, this flag can speed up the process and
reduce the number of API calls necessary.
This flag is only supported on certain backends and will be silently
ignored on unsupported backends. Supported backends include
`azureblob`, `oracleobjectstorage`, `s3`, `swift`.
Using this flag on a sync operation without also using `--update` would cause
all files modified at any time other than the last upload time to be uploaded
again, which is probably not what you want.
@@ -23049,6 +23086,8 @@ This command does not have a command line equivalent so use this instead:
rclone rc --loopback operations/fsinfo fs=remote:
**Authentication is required for this call.**
### operations/hashsum: Produces a hashsum file for all the objects in the path. {#operations-hashsum}
Produces a hash file for all the objects in the path using the hash
@@ -23370,6 +23409,8 @@ And this sets NOTICE level logs (normal without -v)
rclone rc options/set --json '{"main": {"LogLevel": "NOTICE"}}'
**Authentication is required for this call.**
### pluginsctl/addPlugin: Add a plugin using url {#pluginsctl-addPlugin}
Used for adding a plugin to the webgui.
@@ -24776,7 +24817,7 @@ Flags for general networking and HTTP stuff.
--tpslimit float Limit HTTP transactions per second to this
--tpslimit-burst int Max burst of transactions for --tpslimit (default 1)
--use-cookies Enable session cookiejar
--user-agent string Set the user-agent to a specified string (default "rclone/v1.73.0")
--user-agent string Set the user-agent to a specified string (default "rclone/v1.73.5")
```
@@ -25260,9 +25301,11 @@ Backend-only flags (these can be set in the config file also).
--filefabric-token-expiry string Token expiry time
--filefabric-url string URL of the Enterprise File Fabric to connect to
--filefabric-version string Version read from the file fabric
--filelu-chunk-size SizeSuffix Chunk size to use for uploading. Used for multipart uploads (default 64Mi)
--filelu-description string Description of the remote
--filelu-encoding Encoding The encoding for the backend (default Slash,LtGt,DoubleQuote,SingleQuote,BackQuote,Dollar,Colon,Question,Asterisk,Pipe,Hash,Percent,BackSlash,CrLf,Del,Ctl,LeftSpace,LeftPeriod,LeftTilde,LeftCrLfHtVt,RightSpace,RightPeriod,RightCrLfHtVt,InvalidUtf8,Dot,SquareBracket,Semicolon,Exclamation)
--filelu-key string Your FileLu Rclone key from My Account
--filelu-upload-cutoff SizeSuffix Cutoff for switching to chunked upload. Any files larger than this will be uploaded in chunks of chunk_size (default 500Mi)
--filen-api-key string API Key for your Filen account (obscured)
--filen-auth-version string Authentication Version (internal use only)
--filen-base-folder-uuid string UUID of Account Root Directory (internal use only)
@@ -27528,11 +27571,9 @@ The following backends have known issues that need more investigation:
<!--- start list_failures - DO NOT EDIT THIS SECTION - use make commanddocs --->
- `TestDropbox` (`dropbox`)
- [`TestBisyncRemoteRemote/normalization`](https://pub.rclone.org/integration-tests/current/dropbox-cmd.bisync-TestDropbox-1.txt)
- `TestSeafile` (`seafile`)
- [`TestBisyncLocalRemote/volatile`](https://pub.rclone.org/integration-tests/current/seafile-cmd.bisync-TestSeafile-1.txt)
- `TestSeafileV6` (`seafile`)
- [`TestBisyncLocalRemote/volatile`](https://pub.rclone.org/integration-tests/current/seafile-cmd.bisync-TestSeafileV6-1.txt)
- Updated: 2026-01-30-010015
- [`TestBisyncLocalRemote/rmdirs`](https://pub.rclone.org/integration-tests/current/seafile-cmd.bisync-TestSeafileV6-1.txt)
- Updated: 2026-04-19-010011
<!--- end list_failures - DO NOT EDIT THIS SECTION - use make commanddocs --->
The following backends either have not been tested recently or have known issues
@@ -29649,6 +29690,20 @@ work with the SDK properly:
| . | . |
| .. | .. |
#### Important note about double slashes (`//`)
Object keys containing consecutive forward slashes (`//`) are **not supported** by rclone.
When rclone encounters an object key with `//` (e.g., `a//b`), it will normalize the path to use a single slash (e.g., `a/b`). This normalization can cause "object not found" errors when trying to access the original object, as rclone will look for the normalized path instead of the actual object key.
**Example:**
- Original S3 object key: `folder//file.txt`
- rclone interprets it as: `folder/file.txt`
- Result: "object not found" error when trying to access `folder//file.txt`
**Workaround:**
Avoid using consecutive forward slashes (`//`) in S3 object keys when using rclone. If you have existing objects with `//` in their keys, you will need to rename them to use single slashes or access them through other means.
### Multipart uploads
rclone supports multipart uploads with S3 which means that it can
@@ -30669,6 +30724,9 @@ Properties:
- "s3.cubbit.eu"
- Cubbit DS3 Object Storage endpoint
- Provider: Cubbit
- "s3.{tenant_name}.cubbit.eu"
- Multi-tenant endpoint - replace {tenant_name} with your actual tenant name. Do not select this directly
- Provider: Cubbit
- "syd1.digitaloceanspaces.com"
- DigitalOcean Spaces Sydney 1
- Provider: DigitalOcean
@@ -34065,7 +34123,9 @@ can follow this [guide](https://docs.cubbit.io/getting-started/quickstart#api-ke
to retrieve these keys. They will be needed when prompted by `rclone config`.
Default region will correspond to `eu-west-1` and the endpoint has to be specified
as `s3.cubbit.eu`.
as `s3.cubbit.eu`. If you set a custom tenant endpoint, you must use
`s3.{tenant_name}.cubbit.eu`, because the generic `s3.cubbit.eu` endpoint will not
work in this case.
Going through the whole process of creating a new remote by running `rclone config`,
each prompt should be answered as shown below:
@@ -34078,7 +34138,7 @@ env_auth> false
access_key_id> YOUR_ACCESS_KEY
secret_access_key> YOUR_SECRET_KEY
region> eu-west-1 (or leave empty)
endpoint> s3.cubbit.eu
endpoint> s3.cubbit.eu (or s3.{tenant_name}.cubbit.eu)
acl>
```
@@ -37965,6 +38025,15 @@ To configure access to Tencent COS, follow the steps below:
cos s3
```
#### Tencent COS Global Acceleration Endpoint
When using the Global Acceleration Endpoint (`cos.accelerate.myqcloud.com`),
rclone automatically sets `no_check_bucket = true` because this acceleration
endpoint does not support the `CreateBucket` call which is used for ensuring
a bucket's existence by rclone. Global Acceleration is a per-bucket feature,
so you should first create the bucket in one physical region, then enable it
in the Tencent Cloud console.
### Wasabi
[Wasabi](https://wasabi.com) is a cloud-based object storage service for a
@@ -44693,6 +44762,28 @@ Properties:
Here are the Advanced options specific to filelu (FileLu Cloud Storage).
#### --filelu-upload-cutoff
Cutoff for switching to chunked upload. Any files larger than this will be uploaded in chunks of chunk_size.
Properties:
- Config: upload_cutoff
- Env Var: RCLONE_FILELU_UPLOAD_CUTOFF
- Type: SizeSuffix
- Default: 500Mi
#### --filelu-chunk-size
Chunk size to use for uploading. Used for multipart uploads.
Properties:
- Config: chunk_size
- Env Var: RCLONE_FILELU_CHUNK_SIZE
- Type: SizeSuffix
- Default: 64Mi
#### --filelu-encoding
The encoding for the backend.
@@ -44734,6 +44825,8 @@ The initial setup for Filen requires that you get an API key for your account,
currently this is only possible using the [Filen CLI](https://github.com/FilenCloudDienste/filen-cli).
This means you must first download the CLI, login, and then run the `export-api-key` command.
**Note:** If you change your Filen account password, you will need to update your rclone configuration with the new password and a re-exported API key (via `export-api-key`).
Here is an example of how to make a remote called `FilenRemote`. First run:
rclone config
@@ -51980,7 +52073,7 @@ its own datacenters in Norway.
In addition to the official service at [jottacloud.com](https://www.jottacloud.com/),
it also provides white-label solutions to different companies. The following
are currently supported by this backend, using a different authentication setup
as described [below](#whitelabel-authentication):
as described [below](#traditional):
- Elkjøp (with subsidiaries):
- Elkjøp Cloud (cloud.elkjop.no)
@@ -67369,7 +67462,7 @@ handling file names.
| / | 0x2F | / |
When running on Windows the following characters are replaced. This
list is based on the [Windows file naming conventions](https://docs.microsoft.com/de-de/windows/desktop/FileIO/naming-a-file#naming-conventions).
list is based on the [Windows file naming conventions](https://docs.microsoft.com/windows/desktop/FileIO/naming-a-file#naming-conventions).
| Character | Value | Replacement |
| --------- |:-----:|:-----------:|
@@ -68058,6 +68151,121 @@ Options:
# Changelog
## v1.73.5 - 2026-04-19
[See commits](https://github.com/rclone/rclone/compare/v1.73.4...v1.73.5)
- Bug Fixes
- operations: Add AuthRequired to operations/fsinfo to prevent backend creation CVE-2026-41179 (Nick Craig-Wood)
- rc
- Add AuthRequired to options/set to prevent auth bypass CVE-2026-41176 (Nick Craig-Wood)
- Snapshot NoAuth at startup to prevent runtime auth bypass CVE-2026-41176 (Nick Craig-Wood)
- filter: Fix debug logs that fire before logger is configured (Nick Craig-Wood)
- Azureblob
- Add Microsoft Partner Network User-Agent prefix (Nick Craig-Wood)
- Drime
- Fix User.EntryPermissions JSON unmarshalling (a1pcm)
- Iclouddrive
- Fix 'directory not found' error when the directory contains accent marks (Brais Couce)
- S3
- Fix TencentCOS CDN endpoint failing on bucket check (Mozi)
- Fix empty delimiter parameter rejected by Archiware P5 server (Nick Craig-Wood)
## v1.73.4 - 2026-04-08
[See commits](https://github.com/rclone/rclone/compare/v1.73.3...v1.73.4)
- Bug Fixes
- build
- Update to go 1.25.9 to fix multiple CVEs (Nick Craig-Wood)
- CVE-2026-32282: os: Root.Chmod can follow symlinks out of the root on Linux
- CVE-2026-32289: html/template: JS template literal context incorrectly tracked
- CVE-2026-33810: crypto/x509: excluded DNS constraints not properly applied to wildcard domains
- CVE-2026-27144: cmd/compile: no-op interface conversion bypasses overlap checking
- CVE-2026-27143: cmd/compile: possible memory corruption after bound check elimination
- CVE-2026-32288: archive/tar: unbounded allocation when parsing old format GNU sparse map
- CVE-2026-32283: crypto/tls: multiple key update handshake messages can cause connection to deadlock
- CVE-2026-27140: cmd/go: trust layer bypass when using cgo and SWIG
- CVE-2026-32280: crypto/x509: unexpected work during chain building
- CVE-2026-32281: crypto/x509: inefficient policy validation
- Fix Denial of Service due to Panic in AWS SDK for Go v2 SDK EventStream Decoder (dependabot[bot])
- Update golang.org/x/image to 0.38.0 to fix CVE-2026-33809 (dependabot[bot])
- docs
- Fix header level for metadata option (Clément Notin)
- Fix markdown issues in mount docs (albertony)
- Fix link to not be language specific (Ross Smith II)
- Note macOS 10.15 (Catalina) support with version v1.70.3 (kapitainsky)
- Filen
- Update SDK version (Enduriel)
## v1.73.3 - 2026-03-23
[See commits](https://github.com/rclone/rclone/compare/v1.73.2...v1.73.3)
- Bug Fixes
- build
- Update to google.golang.org/grpc 1.79.3 to fix CVE-2026-33186 (dependabot[bot])
- Update to github.com/buger/jsonparser 1.1.2 to fix GHSA-6g7g-w4f8-9c9x (dependabot[bot])
- doc fixes
- Added text to the label showing version-introduced info (Jan-Philipp Reßler)
- Clarify Filen password change requires updating both password and API key in rclone config (Jason)
- s3: clarify multi tenant support for Cubbit (Marco Ferretti)
- jottacloud: Fix broken link (albertony)
- lib/rest: Fix URLPathEscapeAll breaking WebDAV servers (eg nzbdav) with strict path matching (Andrew Furman)
- list: Fix nil pointer panic in Sorter when temp file creation fails (Nick Craig-Wood)
## v1.73.2 - 2026-03-06
[See commits](https://github.com/rclone/rclone/compare/v1.73.1...v1.73.2)
- Bug Fixes
- build
- Update to go 1.25.8 to fix CVE-2026-27137 CVE-2026-27138 CVE-2026-25679 CVE-2026-27142 (Nick Craig-Wood)
- Update github.com/cloudflare/circl to v1.6.3 to fix CVE-2026-1229 (Nick Craig-Wood)
- Update to golang.org/x/net v0.51.0 to fix CVE-2026-27141 (Nick Craig-Wood)
- docs fixes:
- bisync: Add group Sync to the bisync command (Jan-Philipp Reßler)
- Note that --use-server-modtime only works on some backends (Nick Craig-Wood)
- Document unsupported S3 object keys with double slashes (Adam Kasztenny)
- Fix headers hierarchy for mount.md (Dark Dragon)
- Fix new drive flag typo in changelog (razorloves)
- Archive
- Extract: fix extraction with "./" prefix from tar entry paths (Varun Chawla)
- Drime
- Fix chunk-uploaded files ignoring workspace ID (a1pcm)
- Internxt
- Fix Entry doesn't belong in directory errors on windows (jzunigax2)
- WebDAV
- Escape reserved characters in URL path segments (Varun Chawla)
- Add missing headers for CORS (Romāns Potašovs)
## v1.73.1 - 2026-02-17
[See commits](https://github.com/rclone/rclone/compare/v1.73.0...v1.73.1)
- Bug Fixes
- accounting: Fix missing server side stats from core/stats rc (Nick Craig-Wood)
- build
- Fix CVE-2025-68121 by updating go to 1.25.7 or later (Nick Craig-Wood)
- Bump github.com/go-chi/chi/v5 from 5.2.3 to 5.2.5 to fix GO-2026-4316 (albertony)
- docs: Extend copyurl docs with an example of CSV FILENAMEs starting with a path. (Jack Kelly)
- march: Fix runtime: program exceeds 10000-thread limit (Nick Craig-Wood)
- pacer
- Fix deadlock between pacer token and --max-connections (Nick Craig-Wood)
- Re-read the sleep time as it may be stale (Nick Craig-Wood)
- Drime
- Fix files and directories being created in the default workspace (Nick Craig-Wood)
- Filelu
- Avoid buffering entire file in memory (kingston125)
- Add multipart upload support with configurable cutoff (kingston125)
- Filen
- Fix 32 bit targets not being able to list directories (Enduriel)
- Fix potential panic in case of error during upload (Enduriel)
- Internxt
- Implement re-login under refresh logic, improve retry logic (José Zúniga)
-S3
- Set list_version to 2 for FileLu S3 configuration (kingston125)
## v1.73.0 - 2026-01-30
[See commits](https://github.com/rclone/rclone/compare/v1.72.0...v1.73.0)
@@ -68088,7 +68296,7 @@ Options:
- B2
- Support authentication with new bucket restricted application keys (DianaNites)
- Drive
- Add `--drive-metadata-force-expansive-access` flag (Nick Craig-Wood)
- Add `--drive-metadata-enforce-expansive-access` flag (Nick Craig-Wood)
- Fix crash when trying to creating shortcut to a Google doc (Nick Craig-Wood)
- FTP
- Add http proxy authentication support (Nicolas Dessart)
Generated
+280 -21
View File
@@ -1,6 +1,6 @@
rclone(1) User Manual
Nick Craig-Wood
Jan 30, 2026
Apr 19, 2026
NAME
@@ -3277,6 +3277,24 @@ Flags for anything which can copy a file
--streaming-upload-cutoff SizeSuffix Cutoff for switching to chunked upload if file size is unknown, upload starts after reaching cutoff or when file ends (default 100Ki)
-u, --update Skip files that are newer on the destination
Sync Options
Flags used for sync commands
--backup-dir string Make backups into hierarchy based in DIR
--delete-after When synchronizing, delete files on destination after transferring (default)
--delete-before When synchronizing, delete files on destination before transferring
--delete-during When synchronizing, delete files during transfer
--fix-case Force rename of case insensitive dest to match source
--ignore-errors Delete even if there are I/O errors
--list-cutoff int To save memory, sort directory listings on disk above this threshold (default 1000000)
--max-delete int When synchronizing, limit the number of deletes (default -1)
--max-delete-size SizeSuffix When synchronizing, limit the total size of deletes (default off)
--suffix string Suffix to add to changed files
--suffix-keep-extension Preserve the extension when using --suffix
--track-renames When synchronizing, track file renames and do a server-side move if possible
--track-renames-strategy string Strategies to use when synchronizing using track-renames hash|modtime|leaf (default "hash")
Important Options
Important flags useful for most commands
@@ -4607,10 +4625,10 @@ Examples:
// Output: stories/The Quick Brown Fox!.txt
rclone convmv "stories/The Quick Brown Fox!" --name-transform "date=-{YYYYMMDD}"
// Output: stories/The Quick Brown Fox!-20260130
// Output: stories/The Quick Brown Fox!-20260419
rclone convmv "stories/The Quick Brown Fox!" --name-transform "date=-{macfriendlytime}"
// Output: stories/The Quick Brown Fox!-2026-01-30 0825PM
// Output: stories/The Quick Brown Fox!-2026-04-19 1137AM
rclone convmv "stories/The Quick Brown Fox!.txt" --name-transform "all,regex=[\\.\\w]/ab"
// Output: ababababababab/ababab ababababab ababababab ababab!abababab
@@ -5032,6 +5050,15 @@ incompatible with --urls. This will do --transfers copies in parallel.
Note that if --auto-filename is desired for all URLs then a file with
only URLs and no filename can be used.
Each FILENAME in the CSV file can start with a relative path which will
be appended to the destination path provided at the command line. For
example, running the command shown above with the following CSV file
will write two files to the destination: remote:dir/local/path/bar.json
and remote:dir/another/local/directory/qux.json
https://example.org/foo/bar.json,local/path/bar.json
https://example.org/qux/baz.json,another/local/directory/qux.json
Troubleshooting
If you can't get rclone copyurl to work then here are some things you
@@ -6173,7 +6200,7 @@ not suffer from the same limitations.
Mounting on macOS
Mounting on macOS can be done either via built-in NFS server, macFUSE
(also known as osxfuse) or FUSE-T.macFUSE is a traditional FUSE driver
(also known as osxfuse) or FUSE-T. macFUSE is a traditional FUSE driver
utilizing a macOS kernel extension (kext). FUSE-T is an alternative FUSE
system which "mounts" via an NFSv4 local server.
@@ -6218,7 +6245,7 @@ As per the FUSE-T wiki:
File access and modification times cannot be set separately as it
seems to be an issue with the NFS client which always modifies both.
Can be reproduced with 'touch -m' and 'touch -a' commands
Can be reproduced with touch -m and touch -a commands
This means that viewing files with various tools, notably macOS Finder,
will cause rlcone to update the modification time of the file. This may
@@ -6236,9 +6263,11 @@ running rclone mount:
NOTICE: mount helper error: fusermount3: mount failed: Permission
denied CRITICAL: Fatal error: failed to mount FUSE fs: fusermount:
exit status 1 This may be due to newer Apparmor restrictions, which
can be disabled with sudo aa-disable /usr/bin/fusermount3 (you may
need to sudo apt install apparmor-utils beforehand).
exit status 1
This may be due to newer Apparmor restrictions, which can be disabled
with sudo aa-disable /usr/bin/fusermount3 (you may need to
sudo apt install apparmor-utils beforehand).
Limitations
@@ -7522,7 +7551,7 @@ not suffer from the same limitations.
Mounting on macOS
Mounting on macOS can be done either via built-in NFS server, macFUSE
(also known as osxfuse) or FUSE-T.macFUSE is a traditional FUSE driver
(also known as osxfuse) or FUSE-T. macFUSE is a traditional FUSE driver
utilizing a macOS kernel extension (kext). FUSE-T is an alternative FUSE
system which "mounts" via an NFSv4 local server.
@@ -7567,7 +7596,7 @@ As per the FUSE-T wiki:
File access and modification times cannot be set separately as it
seems to be an issue with the NFS client which always modifies both.
Can be reproduced with 'touch -m' and 'touch -a' commands
Can be reproduced with touch -m and touch -a commands
This means that viewing files with various tools, notably macOS Finder,
will cause rlcone to update the modification time of the file. This may
@@ -7585,9 +7614,11 @@ running rclone mount:
NOTICE: mount helper error: fusermount3: mount failed: Permission
denied CRITICAL: Fatal error: failed to mount FUSE fs: fusermount:
exit status 1 This may be due to newer Apparmor restrictions, which
can be disabled with sudo aa-disable /usr/bin/fusermount3 (you may
need to sudo apt install apparmor-utils beforehand).
exit status 1
This may be due to newer Apparmor restrictions, which can be disabled
with sudo aa-disable /usr/bin/fusermount3 (you may need to
sudo apt install apparmor-utils beforehand).
Limitations
@@ -17856,6 +17887,10 @@ server's modified time. In cases such as a local to remote sync using
uploaded to the remote is sufficient. In those cases, this flag can
speed up the process and reduce the number of API calls necessary.
This flag is only supported on certain backends and will be silently
ignored on unsupported backends. Supported backends include azureblob,
oracleobjectstorage, s3, swift.
Using this flag on a sync operation without also using --update would
cause all files modified at any time other than the last upload time to
be uploaded again, which is probably not what you want.
@@ -21221,6 +21256,8 @@ instead:
rclone rc --loopback operations/fsinfo fs=remote:
Authentication is required for this call.
operations/hashsum: Produces a hashsum file for all the objects in the path.
Produces a hash file for all the objects in the path using the hash
@@ -21549,6 +21586,8 @@ And this sets NOTICE level logs (normal without -v)
rclone rc options/set --json '{"main": {"LogLevel": "NOTICE"}}'
Authentication is required for this call.
pluginsctl/addPlugin: Add a plugin using url
Used for adding a plugin to the webgui.
@@ -22962,7 +23001,7 @@ Flags for general networking and HTTP stuff.
--tpslimit float Limit HTTP transactions per second to this
--tpslimit-burst int Max burst of transactions for --tpslimit (default 1)
--use-cookies Enable session cookiejar
--user-agent string Set the user-agent to a specified string (default "rclone/v1.73.0")
--user-agent string Set the user-agent to a specified string (default "rclone/v1.73.5")
Performance
@@ -23416,9 +23455,11 @@ Backend-only flags (these can be set in the config file also).
--filefabric-token-expiry string Token expiry time
--filefabric-url string URL of the Enterprise File Fabric to connect to
--filefabric-version string Version read from the file fabric
--filelu-chunk-size SizeSuffix Chunk size to use for uploading. Used for multipart uploads (default 64Mi)
--filelu-description string Description of the remote
--filelu-encoding Encoding The encoding for the backend (default Slash,LtGt,DoubleQuote,SingleQuote,BackQuote,Dollar,Colon,Question,Asterisk,Pipe,Hash,Percent,BackSlash,CrLf,Del,Ctl,LeftSpace,LeftPeriod,LeftTilde,LeftCrLfHtVt,RightSpace,RightPeriod,RightCrLfHtVt,InvalidUtf8,Dot,SquareBracket,Semicolon,Exclamation)
--filelu-key string Your FileLu Rclone key from My Account
--filelu-upload-cutoff SizeSuffix Cutoff for switching to chunked upload. Any files larger than this will be uploaded in chunks of chunk_size (default 500Mi)
--filen-api-key string API Key for your Filen account (obscured)
--filen-auth-version string Authentication Version (internal use only)
--filen-base-folder-uuid string UUID of Account Root Directory (internal use only)
@@ -25626,11 +25667,9 @@ The following backends have known issues that need more investigation:
- TestDropbox (dropbox)
- TestBisyncRemoteRemote/normalization
- TestSeafile (seafile)
- TestBisyncLocalRemote/volatile
- TestSeafileV6 (seafile)
- TestBisyncLocalRemote/volatile
- Updated: 2026-01-30-010015
- TestBisyncLocalRemote/rmdirs
- Updated: 2026-04-19-010011
The following backends either have not been tested recently or have
known issues that are deemed unfixable for the time being:
@@ -27690,6 +27729,26 @@ work with the SDK properly:
. .
.. ..
Important note about double slashes (//)
Object keys containing consecutive forward slashes (//) are not
supported by rclone.
When rclone encounters an object key with // (e.g., a//b), it will
normalize the path to use a single slash (e.g., a/b). This normalization
can cause "object not found" errors when trying to access the original
object, as rclone will look for the normalized path instead of the
actual object key.
Example: - Original S3 object key: folder//file.txt - rclone interprets
it as: folder/file.txt - Result: "object not found" error when trying to
access folder//file.txt
Workaround: Avoid using consecutive forward slashes (//) in S3 object
keys when using rclone. If you have existing objects with // in their
keys, you will need to rename them to use single slashes or access them
through other means.
Multipart uploads
rclone supports multipart uploads with S3 which means that it can upload
@@ -28724,6 +28783,10 @@ Properties:
- "s3.cubbit.eu"
- Cubbit DS3 Object Storage endpoint
- Provider: Cubbit
- "s3.{tenant_name}.cubbit.eu"
- Multi-tenant endpoint - replace {tenant_name} with your
actual tenant name. Do not select this directly
- Provider: Cubbit
- "syd1.digitaloceanspaces.com"
- DigitalOcean Spaces Sydney 1
- Provider: DigitalOcean
@@ -32076,7 +32139,9 @@ pair. You can follow this guide to retrieve these keys. They will be
needed when prompted by rclone config.
Default region will correspond to eu-west-1 and the endpoint has to be
specified as s3.cubbit.eu.
specified as s3.cubbit.eu. If you set a custom tenant endpoint, you must
use s3.{tenant_name}.cubbit.eu, because the generic s3.cubbit.eu
endpoint will not work in this case.
Going through the whole process of creating a new remote by running
rclone config, each prompt should be answered as shown below:
@@ -32088,7 +32153,7 @@ rclone config, each prompt should be answered as shown below:
access_key_id> YOUR_ACCESS_KEY
secret_access_key> YOUR_SECRET_KEY
region> eu-west-1 (or leave empty)
endpoint> s3.cubbit.eu
endpoint> s3.cubbit.eu (or s3.{tenant_name}.cubbit.eu)
acl>
The resulting configuration file should look like:
@@ -35699,6 +35764,16 @@ To configure access to Tencent COS, follow the steps below:
==== ====
cos s3
Tencent COS Global Acceleration Endpoint
When using the Global Acceleration Endpoint
(cos.accelerate.myqcloud.com), rclone automatically sets
no_check_bucket = true because this acceleration endpoint does not
support the CreateBucket call which is used for ensuring a bucket's
existence by rclone. Global Acceleration is a per-bucket feature, so you
should first create the bucket in one physical region, then enable it in
the Tencent Cloud console.
Wasabi
Wasabi is a cloud-based object storage service for a broad range of
@@ -42261,6 +42336,29 @@ Advanced options
Here are the Advanced options specific to filelu (FileLu Cloud Storage).
--filelu-upload-cutoff
Cutoff for switching to chunked upload. Any files larger than this will
be uploaded in chunks of chunk_size.
Properties:
- Config: upload_cutoff
- Env Var: RCLONE_FILELU_UPLOAD_CUTOFF
- Type: SizeSuffix
- Default: 500Mi
--filelu-chunk-size
Chunk size to use for uploading. Used for multipart uploads.
Properties:
- Config: chunk_size
- Env Var: RCLONE_FILELU_CHUNK_SIZE
- Type: SizeSuffix
- Default: 64Mi
--filelu-encoding
The encoding for the backend.
@@ -42304,6 +42402,10 @@ account, currently this is only possible using the Filen CLI. This means
you must first download the CLI, login, and then run the export-api-key
command.
Note: If you change your Filen account password, you will need to update
your rclone configuration with the new password and a re-exported API
key (via export-api-key).
Here is an example of how to make a remote called FilenRemote. First
run:
@@ -65100,6 +65202,163 @@ Options:
Changelog
v1.73.5 - 2026-04-19
See commits
- Bug Fixes
- operations: Add AuthRequired to operations/fsinfo to prevent
backend creation CVE-2026-41179 (Nick Craig-Wood)
- rc
- Add AuthRequired to options/set to prevent auth bypass
CVE-2026-41176 (Nick Craig-Wood)
- Snapshot NoAuth at startup to prevent runtime auth bypass
CVE-2026-41176 (Nick Craig-Wood)
- filter: Fix debug logs that fire before logger is configured
(Nick Craig-Wood)
- Azureblob
- Add Microsoft Partner Network User-Agent prefix (Nick
Craig-Wood)
- Drime
- Fix User.EntryPermissions JSON unmarshalling (a1pcm)
- Iclouddrive
- Fix 'directory not found' error when the directory contains
accent marks (Brais Couce)
- S3
- Fix TencentCOS CDN endpoint failing on bucket check (Mozi)
- Fix empty delimiter parameter rejected by Archiware P5 server
(Nick Craig-Wood)
v1.73.4 - 2026-04-08
See commits
- Bug Fixes
- build
- Update to go 1.25.9 to fix multiple CVEs (Nick Craig-Wood)
- CVE-2026-32282: os: Root.Chmod can follow symlinks out
of the root on Linux
- CVE-2026-32289: html/template: JS template literal
context incorrectly tracked
- CVE-2026-33810: crypto/x509: excluded DNS constraints
not properly applied to wildcard domains
- CVE-2026-27144: cmd/compile: no-op interface conversion
bypasses overlap checking
- CVE-2026-27143: cmd/compile: possible memory corruption
after bound check elimination
- CVE-2026-32288: archive/tar: unbounded allocation when
parsing old format GNU sparse map
- CVE-2026-32283: crypto/tls: multiple key update
handshake messages can cause connection to deadlock
- CVE-2026-27140: cmd/go: trust layer bypass when using
cgo and SWIG
- CVE-2026-32280: crypto/x509: unexpected work during
chain building
- CVE-2026-32281: crypto/x509: inefficient policy
validation
- Fix Denial of Service due to Panic in AWS SDK for Go v2 SDK
EventStream Decoder (dependabot[bot])
- Update golang.org/x/image to 0.38.0 to fix CVE-2026-33809
(dependabot[bot])
- docs
- Fix header level for metadata option (Clément Notin)
- Fix markdown issues in mount docs (albertony)
- Fix link to not be language specific (Ross Smith II)
- Note macOS 10.15 (Catalina) support with version v1.70.3
(kapitainsky)
- Filen
- Update SDK version (Enduriel)
v1.73.3 - 2026-03-23
See commits
- Bug Fixes
- build
- Update to google.golang.org/grpc 1.79.3 to fix
CVE-2026-33186 (dependabot[bot])
- Update to github.com/buger/jsonparser 1.1.2 to fix
GHSA-6g7g-w4f8-9c9x (dependabot[bot])
- doc fixes
- Added text to the label showing version-introduced info
(Jan-Philipp Reßler)
- Clarify Filen password change requires updating both
password and API key in rclone config (Jason)
- s3: clarify multi tenant support for Cubbit (Marco Ferretti)
- jottacloud: Fix broken link (albertony)
- lib/rest: Fix URLPathEscapeAll breaking WebDAV servers (eg
nzbdav) with strict path matching (Andrew Furman)
- list: Fix nil pointer panic in Sorter when temp file creation
fails (Nick Craig-Wood)
v1.73.2 - 2026-03-06
See commits
- Bug Fixes
- build
- Update to go 1.25.8 to fix CVE-2026-27137 CVE-2026-27138
CVE-2026-25679 CVE-2026-27142 (Nick Craig-Wood)
- Update github.com/cloudflare/circl to v1.6.3 to fix
CVE-2026-1229 (Nick Craig-Wood)
- Update to golang.org/x/net v0.51.0 to fix CVE-2026-27141
(Nick Craig-Wood)
- docs fixes:
- bisync: Add group Sync to the bisync command (Jan-Philipp
Reßler)
- Note that --use-server-modtime only works on some backends
(Nick Craig-Wood)
- Document unsupported S3 object keys with double slashes
(Adam Kasztenny)
- Fix headers hierarchy for mount.md (Dark Dragon)
- Fix new drive flag typo in changelog (razorloves)
- Archive
- Extract: fix extraction with "./" prefix from tar entry paths
(Varun Chawla)
- Drime
- Fix chunk-uploaded files ignoring workspace ID (a1pcm)
- Internxt
- Fix Entry doesn't belong in directory errors on windows
(jzunigax2)
- WebDAV
- Escape reserved characters in URL path segments (Varun Chawla)
- Add missing headers for CORS (Romāns Potašovs)
v1.73.1 - 2026-02-17
See commits
- Bug Fixes
- accounting: Fix missing server side stats from core/stats rc
(Nick Craig-Wood)
- build
- Fix CVE-2025-68121 by updating go to 1.25.7 or later (Nick
Craig-Wood)
- Bump github.com/go-chi/chi/v5 from 5.2.3 to 5.2.5 to fix
GO-2026-4316 (albertony)
- docs: Extend copyurl docs with an example of CSV FILENAMEs
starting with a path. (Jack Kelly)
- march: Fix runtime: program exceeds 10000-thread limit (Nick
Craig-Wood)
- pacer
- Fix deadlock between pacer token and --max-connections (Nick
Craig-Wood)
- Re-read the sleep time as it may be stale (Nick Craig-Wood)
- Drime
- Fix files and directories being created in the default workspace
(Nick Craig-Wood)
- Filelu
- Avoid buffering entire file in memory (kingston125)
- Add multipart upload support with configurable cutoff
(kingston125)
- Filen
- Fix 32 bit targets not being able to list directories (Enduriel)
- Fix potential panic in case of error during upload (Enduriel)
- Internxt
- Implement re-login under refresh logic, improve retry logic
(José Zúniga) -S3
- Set list_version to 2 for FileLu S3 configuration (kingston125)
v1.73.0 - 2026-01-30
See commits
@@ -65135,7 +65394,7 @@ See commits
- Support authentication with new bucket restricted application
keys (DianaNites)
- Drive
- Add --drive-metadata-force-expansive-access flag (Nick
- Add --drive-metadata-enforce-expansive-access flag (Nick
Craig-Wood)
- Fix crash when trying to creating shortcut to a Google doc (Nick
Craig-Wood)
+55 -1
View File
@@ -32,10 +32,11 @@ This file describes how to make the various kinds of releases
- make sign_upload
- make check_sign
- make upload
- make upload_test_website # check sponsors are correct/unchanged
- make upload_website
- make upload_github
- make startdev # make startstable for stable branch
- \# announce with forum post, twitter post, patreon post
- \# announce with forum post, twitter post, and post to annoucements list
## Update dependencies
@@ -109,6 +110,59 @@ go run github.com/icholy/gomajor@latest list -major
Expect API breakage when updating major versions.
## Updating Go
When a new Go stable is released update to it. We support the current
stable Go and the previous release which is in line with the rest of
the Go ecosystem.
These files will need editing:
- `.github/workflows/build.yml` - change current and previous Go versions
- `docs/content/install.md` - change minimum Go version required
- `fs/versioncheck.go` - update minimum Go version required
- `go.mod` - update minimum Go version required
Check it builds
- `make GOTAGS=cmount`
- `make compiletest`
Assuming `go1.XX` is current and `go1.YY` is previous version:
Use `git grep go1.YY` and `git grep go1.YY` to look for opportunities
to remove build tags we no longer need.
Commit with message like this:
```text
build: update to go1.YY and make go1.YY the minimum required version
```
Send to CI and if it passes, merge.
### gofix
Updating the minimum required version of Go is a good opportunity to
run the `go fix` command to modernize Go usage.
This needs to be run for all architectures.
```console
GOOS=linux go fix -tags cmount ./...
GOOS=freebsd go fix -tags cmount ./...
GOOS=windows go fix -tags cmount ./...
GOOS=darwin go fix -tags cmount ./...
```
Examine the diff carefully.
Commit with message
```text
build: modernize Go code with go fix for go1.YY
```
## Tidy beta
At some point after the release run
+1 -1
View File
@@ -1 +1 @@
v1.73.0
v1.73.5
+4
View File
@@ -9,6 +9,7 @@ import (
"net/http"
"net/url"
"os"
"strings"
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
@@ -283,6 +284,9 @@ type transporter struct {
// Make a new transporter
func newTransporter(ctx context.Context) transporter {
// Set the User-Agent to include the Microsoft Partner Network prefix
ctx, ci := fs.AddConfig(ctx)
ci.UserAgent = "APN/1.0 rclone/1.0 rclone/" + strings.TrimPrefix(fs.Version, "v")
return transporter{
RoundTripper: fshttp.NewTransport(ctx),
}
+3 -1
View File
@@ -21,7 +21,7 @@ type User struct {
Avatar string `json:"avatar"`
ModelType string `json:"model_type"`
OwnsEntry bool `json:"owns_entry"`
EntryPermissions []any `json:"entry_permissions"`
EntryPermissions any `json:"entry_permissions"`
DisplayName string `json:"display_name"`
}
@@ -173,6 +173,7 @@ type MultiPartCreateRequest struct {
Extension string `json:"extension"`
ParentID json.Number `json:"parent_id"`
RelativePath string `json:"relativePath"`
WorkspaceID string `json:"workspaceId,omitempty"`
}
// MultiPartCreateResponse is returned by POST /s3/multipart/create
@@ -223,6 +224,7 @@ type MultiPartEntriesRequest struct {
ClientExtension string `json:"clientExtension"`
ParentID json.Number `json:"parent_id"`
RelativePath string `json:"relativePath"`
WorkspaceID string `json:"workspaceId,omitempty"`
}
// MultiPartEntriesResponse is the result of POST /s3/entries
+27 -8
View File
@@ -476,8 +476,12 @@ func (f *Fs) createDir(ctx context.Context, pathID, leaf string, modTime time.Ti
var resp *http.Response
var result api.CreateFolderResponse
opts := rest.Opts{
Method: "POST",
Path: "/folders",
Method: "POST",
Path: "/folders",
Parameters: url.Values{},
}
if f.opt.WorkspaceID != "" {
opts.Parameters.Set("workspaceId", f.opt.WorkspaceID)
}
mkdir := api.CreateFolderRequest{
Name: f.opt.Enc.FromStandardName(leaf),
@@ -779,8 +783,12 @@ func (f *Fs) patch(ctx context.Context, id, attribute string, value string) (ite
}
var result api.UpdateItemResponse
opts := rest.Opts{
Method: "PUT",
Path: "/file-entries/" + id,
Method: "PUT",
Path: "/file-entries/" + id,
Parameters: url.Values{},
}
if f.opt.WorkspaceID != "" {
opts.Parameters.Set("workspaceId", f.opt.WorkspaceID)
}
err = f.pacer.Call(func() (bool, error) {
resp, err = f.srv.CallJSON(ctx, &opts, &request, &result)
@@ -807,8 +815,12 @@ func (f *Fs) move(ctx context.Context, id, newDirID string) (err error) {
}
var result api.MoveResponse
opts := rest.Opts{
Method: "POST",
Path: "/file-entries/move",
Method: "POST",
Path: "/file-entries/move",
Parameters: url.Values{},
}
if f.opt.WorkspaceID != "" {
opts.Parameters.Set("workspaceId", f.opt.WorkspaceID)
}
err = f.pacer.Call(func() (bool, error) {
resp, err = f.srv.CallJSON(ctx, &opts, &request, &result)
@@ -945,8 +957,12 @@ func (f *Fs) copy(ctx context.Context, id, newDirID string) (item *api.Item, err
}
var result api.CopyResponse
opts := rest.Opts{
Method: "POST",
Path: "/file-entries/duplicate",
Method: "POST",
Path: "/file-entries/duplicate",
Parameters: url.Values{},
}
if f.opt.WorkspaceID != "" {
opts.Parameters.Set("workspaceId", f.opt.WorkspaceID)
}
err = f.pacer.Call(func() (bool, error) {
resp, err = f.srv.CallJSON(ctx, &opts, &request, &result)
@@ -1114,6 +1130,7 @@ func (f *Fs) OpenChunkWriter(ctx context.Context, remote string, src fs.ObjectIn
Extension: strings.TrimPrefix(path.Ext(leaf), `.`),
ParentID: json.Number(directoryID),
RelativePath: f.opt.Enc.FromStandardPath(path.Join(f.root, remote)),
WorkspaceID: f.opt.WorkspaceID,
}
var resp api.MultiPartCreateResponse
@@ -1297,6 +1314,7 @@ func (s *drimeChunkWriter) Close(ctx context.Context) error {
ClientExtension: s.extension,
ParentID: s.parentID,
RelativePath: s.relativePath,
WorkspaceID: s.f.opt.WorkspaceID,
}
entriesOpts := rest.Opts{
@@ -1509,6 +1527,7 @@ func (o *Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, op
MultipartParams: url.Values{
"parentId": {directoryID},
"relativePath": {encodedLeaf},
"workspaceId": {o.fs.opt.WorkspaceID},
},
MultipartContentName: "file",
MultipartFileName: encodedLeaf,
+13
View File
@@ -3,6 +3,19 @@ package api
import "encoding/json"
// MultipartInitResponse represents the response from multipart/init.
type MultipartInitResponse struct {
Status int `json:"status"`
Msg string `json:"msg"`
Result struct {
UploadID string `json:"upload_id"`
SessID string `json:"sess_id"`
Server string `json:"server"`
FolderID int64 `json:"folder_id"`
ObjectPath string `json:"object_path"`
} `json:"result"`
}
// CreateFolderResponse represents the response for creating a folder.
type CreateFolderResponse struct {
Status int `json:"status"`
+24 -19
View File
@@ -21,6 +21,11 @@ import (
"github.com/rclone/rclone/lib/rest"
)
const (
defaultUploadCutoff = fs.SizeSuffix(500 * 1024 * 1024)
defaultChunkSize = fs.SizeSuffix(64 * 1024 * 1024)
)
// Register the backend with Rclone
func init() {
fs.Register(&fs.RegInfo{
@@ -33,6 +38,17 @@ func init() {
Required: true,
Sensitive: true,
},
{
Name: "upload_cutoff",
Help: "Cutoff for switching to chunked upload. Any files larger than this will be uploaded in chunks of chunk_size.",
Default: defaultUploadCutoff,
Advanced: true,
}, {
Name: "chunk_size",
Help: "Chunk size to use for uploading. Used for multipart uploads.",
Default: defaultChunkSize,
Advanced: true,
},
{
Name: config.ConfigEncoding,
Help: config.ConfigEncodingHelp,
@@ -72,8 +88,10 @@ func init() {
// Options defines the configuration for the FileLu backend
type Options struct {
Key string `config:"key"`
Enc encoder.MultiEncoder `config:"encoding"`
Key string `config:"key"`
Enc encoder.MultiEncoder `config:"encoding"`
UploadCutoff fs.SizeSuffix `config:"upload_cutoff"`
ChunkSize fs.SizeSuffix `config:"chunk_size"`
}
// Fs represents the FileLu file system
@@ -189,7 +207,6 @@ func (f *Fs) Purge(ctx context.Context, dir string) error {
return f.deleteFolder(ctx, fullPath)
}
// List returns a list of files and folders
// List returns a list of files and folders for the given directory
func (f *Fs) List(ctx context.Context, dir string) (fs.DirEntries, error) {
// Compose full path for API call
@@ -250,23 +267,11 @@ func (f *Fs) List(ctx context.Context, dir string) (fs.DirEntries, error) {
// Put uploads a file directly to the destination folder in the FileLu storage system.
func (f *Fs) Put(ctx context.Context, in io.Reader, src fs.ObjectInfo, options ...fs.OpenOption) (fs.Object, error) {
if src.Size() == 0 {
return nil, fs.ErrorCantUploadEmptyFiles
o := &Object{
fs: f,
remote: src.Remote(),
}
err := f.uploadFile(ctx, in, src.Remote())
if err != nil {
return nil, err
}
newObject := &Object{
fs: f,
remote: src.Remote(),
size: src.Size(),
modTime: src.ModTime(ctx),
}
fs.Infof(f, "Put: Successfully uploaded new file %q", src.Remote())
return newObject, nil
return o, o.Update(ctx, in, src, options...)
}
// Move moves the file to the specified location
+53
View File
@@ -16,6 +16,59 @@ import (
"github.com/rclone/rclone/lib/rest"
)
// multipartInit starts a new multipart upload and returns server details.
func (f *Fs) multipartInit(ctx context.Context, folderPath, filename string) (*api.MultipartInitResponse, error) {
opts := rest.Opts{
Method: "GET",
Path: "/multipart/init",
Parameters: url.Values{
"key": {f.opt.Key},
"filename": {filename},
"folder_path": {folderPath},
},
}
var result api.MultipartInitResponse
err := f.pacer.Call(func() (bool, error) {
_, err := f.srv.CallJSON(ctx, &opts, nil, &result)
return fserrors.ShouldRetry(err), err
})
if err != nil {
return nil, err
}
if result.Status != 200 {
return nil, fmt.Errorf("multipart init error: %s", result.Msg)
}
return &result, nil
}
// completeMultipart finalizes the multipart upload on the file server.
func (f *Fs) completeMultipart(ctx context.Context, server string, uploadID string, sessID string, objectPath string) error {
req, err := http.NewRequestWithContext(ctx, "POST", server, nil)
if err != nil {
return err
}
req.Header.Set("X-RC-Upload-Id", uploadID)
req.Header.Set("X-Sess-ID", sessID)
req.Header.Set("X-Object-Path", objectPath)
resp, err := f.client.Do(req)
if err != nil {
return err
}
defer func() { _ = resp.Body.Close() }()
if resp.StatusCode != 202 {
body, _ := io.ReadAll(resp.Body)
return fmt.Errorf("completeMultipart failed %d: %s", resp.StatusCode, string(body))
}
return nil
}
// createFolder creates a folder at the specified path.
func (f *Fs) createFolder(ctx context.Context, dirPath string) (*api.CreateFolderResponse, error) {
encodedDir := f.fromStandardPath(dirPath)
+100
View File
@@ -1,6 +1,7 @@
package filelu
import (
"bytes"
"context"
"encoding/json"
"errors"
@@ -15,6 +16,105 @@ import (
"github.com/rclone/rclone/fs"
)
// multipartUpload uploads a file in fixed-size chunks using the multipart API.
func (f *Fs) multipartUpload(ctx context.Context, in io.Reader, remote string) error {
dir := path.Dir(remote)
if dir == "." {
dir = ""
}
if dir != "" {
_ = f.Mkdir(ctx, dir)
}
folder := strings.Trim(dir, "/")
if folder != "" {
folder = "/" + folder
}
file := path.Base(remote)
initResp, err := f.multipartInit(ctx, folder, file)
if err != nil {
return fmt.Errorf("multipart init failed: %w", err)
}
uploadID := initResp.Result.UploadID
sessID := initResp.Result.SessID
server := initResp.Result.Server
objectPath := initResp.Result.ObjectPath
chunkSize := int(f.opt.ChunkSize)
buf := make([]byte, 0, chunkSize)
tmp := make([]byte, 1024*1024)
partNo := 1
for {
n, errRead := in.Read(tmp)
if n > 0 {
buf = append(buf, tmp[:n]...)
// If buffer reached chunkSize, upload a full part
if len(buf) >= chunkSize {
err = f.uploadPart(ctx, server, uploadID, sessID, objectPath, partNo, bytes.NewReader(buf))
if err != nil {
return fmt.Errorf("upload part %d failed: %w", partNo, err)
}
partNo++
buf = buf[:0]
}
}
if errRead == io.EOF {
break
}
if errRead != nil {
return fmt.Errorf("read failed: %w", errRead)
}
}
if len(buf) > 0 {
err = f.uploadPart(ctx, server, uploadID, sessID, objectPath, partNo, bytes.NewReader(buf))
if err != nil {
return fmt.Errorf("upload part %d failed: %w", partNo, err)
}
}
err = f.completeMultipart(ctx, server, uploadID, sessID, objectPath)
if err != nil {
return fmt.Errorf("complete multipart failed: %w", err)
}
return nil
}
// uploadPart sends a single multipart chunk to the upload server.
func (f *Fs) uploadPart(ctx context.Context, server, uploadID, sessID, objectPath string, partNo int, r io.Reader) error {
url := fmt.Sprintf("%s?partNumber=%d&uploadId=%s", server, partNo, uploadID)
req, err := http.NewRequestWithContext(ctx, "PUT", url, r)
if err != nil {
return err
}
req.Header.Set("X-RC-Upload-Id", uploadID)
req.Header.Set("X-RC-Part-No", fmt.Sprintf("%d", partNo))
req.Header.Set("X-Sess-ID", sessID)
req.Header.Set("X-Object-Path", objectPath)
resp, err := f.client.Do(req)
if err != nil {
return err
}
defer func() { _ = resp.Body.Close() }()
if resp.StatusCode != 200 {
return fmt.Errorf("uploadPart failed: %s", resp.Status)
}
return nil
}
// uploadFile uploads a file to FileLu
func (f *Fs) uploadFile(ctx context.Context, fileContent io.Reader, fileFullPath string) error {
directory := path.Dir(fileFullPath)
+31 -20
View File
@@ -1,7 +1,6 @@
package filelu
import (
"bytes"
"context"
"encoding/json"
"fmt"
@@ -88,6 +87,7 @@ func (o *Object) Open(ctx context.Context, options ...fs.OpenOption) (io.ReadClo
}
}
// Wrap the response body to handle offset and count
var reader io.ReadCloser
err = o.fs.pacer.Call(func() (bool, error) {
req, err := http.NewRequestWithContext(ctx, "GET", directLink, nil)
@@ -109,22 +109,25 @@ func (o *Object) Open(ctx context.Context, options ...fs.OpenOption) (io.ReadClo
return false, fmt.Errorf("failed to download file: HTTP %d", resp.StatusCode)
}
// Wrap the response body to handle offset and count
currentContents, err := io.ReadAll(resp.Body)
if err != nil {
return false, fmt.Errorf("failed to read response body: %w", err)
if offset > 0 {
_, err = io.CopyN(io.Discard, resp.Body, offset)
if err != nil {
_ = resp.Body.Close()
return false, fmt.Errorf("failed to skip offset: %w", err)
}
}
if offset > 0 {
if offset > int64(len(currentContents)) {
return false, fmt.Errorf("offset %d exceeds file size %d", offset, len(currentContents))
if count > 0 {
reader = struct {
io.Reader
io.Closer
}{
Reader: io.LimitReader(resp.Body, count),
Closer: resp.Body,
}
currentContents = currentContents[offset:]
} else {
reader = resp.Body
}
if count > 0 && count < int64(len(currentContents)) {
currentContents = currentContents[:count]
}
reader = io.NopCloser(bytes.NewReader(currentContents))
return false, nil
})
@@ -137,15 +140,23 @@ func (o *Object) Open(ctx context.Context, options ...fs.OpenOption) (io.ReadClo
// Update updates the object with new data
func (o *Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, options ...fs.OpenOption) error {
if src.Size() <= 0 {
return fs.ErrorCantUploadEmptyFiles
size := src.Size()
if size <= int64(o.fs.opt.UploadCutoff) {
err := o.fs.uploadFile(ctx, in, o.remote)
if err != nil {
return err
}
} else {
fullPath := path.Join(o.fs.root, o.remote)
err := o.fs.multipartUpload(ctx, in, fullPath)
if err != nil {
return fmt.Errorf("failed to upload file: %w", err)
}
}
err := o.fs.uploadFile(ctx, in, o.remote)
if err != nil {
return fmt.Errorf("failed to upload file: %w", err)
}
o.size = src.Size()
o.size = size
o.modTime = src.ModTime(ctx)
return nil
}
+10 -10
View File
@@ -355,19 +355,19 @@ type chunkWriter struct {
chunkSize int64
chunksLock sync.Mutex
knownChunks map[int][]byte // known chunks to be hashed
nextChunkToHash int
knownChunks map[int64][]byte // known chunks to be hashed
nextChunkToHash int64
sizeLock sync.Mutex
size int64
}
func (cw *chunkWriter) WriteChunk(ctx context.Context, chunkNumber int, reader io.ReadSeeker) (bytesWritten int64, err error) {
realChunkNumber := int(int64(chunkNumber) * (cw.chunkSize) / sdk.ChunkSize)
realChunkNumber := int64(chunkNumber) * (cw.chunkSize) / sdk.ChunkSize
chunk := make([]byte, sdk.ChunkSize, sdk.ChunkSize+cw.EncryptionKey.Cipher.Overhead())
totalWritten := int64(0)
for sliceStart := 0; sliceStart < int(cw.chunkSize); sliceStart += sdk.ChunkSize {
for sliceStart := int64(0); sliceStart < cw.chunkSize; sliceStart += sdk.ChunkSize {
chunk = chunk[:sdk.ChunkSize]
chunkRead := 0
for {
@@ -415,13 +415,13 @@ func (cw *chunkWriter) WriteChunk(ctx context.Context, chunkNumber int, reader i
return totalWritten, err
}
resp, err := cw.filen.UploadChunk(ctx, &cw.FileUpload, realChunkNumber, chunkReadSlice)
if err != nil {
return totalWritten, err
}
select { // only care about getting this once
case cw.bucketAndRegion <- *resp:
default:
}
if err != nil {
return totalWritten, err
}
totalWritten += int64(len(chunkReadSlice))
realChunkNumber++
}
@@ -496,7 +496,7 @@ func (f *Fs) OpenChunkWriter(ctx context.Context, remote string, src fs.ObjectIn
filen: f.filen,
chunkSize: chunkSize,
bucketAndRegion: make(chan client.V3UploadResponse, 1),
knownChunks: make(map[int][]byte),
knownChunks: make(map[int64][]byte),
nextChunkToHash: 0,
size: 0,
}, nil
@@ -1122,8 +1122,8 @@ func (f *Fs) About(ctx context.Context) (*fs.Usage, error) {
return nil, err
}
total := int64(userInfo.MaxStorage)
used := int64(userInfo.UsedStorage)
total := userInfo.MaxStorage
used := userInfo.UsedStorage
free := total - used
return &fs.Usage{
Total: &total,
+4 -1
View File
@@ -27,6 +27,8 @@ import (
"github.com/rclone/rclone/lib/dircache"
"github.com/rclone/rclone/lib/encoder"
"github.com/rclone/rclone/lib/pacer"
"golang.org/x/text/unicode/norm"
)
/*
@@ -225,7 +227,8 @@ func (f *Fs) findLeafItem(ctx context.Context, pathID string, leaf string) (item
return nil, false, err
}
for _, item := range items {
if strings.EqualFold(item.FullName(), leaf) {
// iCloud returns file names in NFD Unicode normalization, so normalized to NFC for consistent comparison
if strings.EqualFold(norm.NFC.String(item.FullName()), leaf) {
return item, true, nil
}
}
+101 -1
View File
@@ -13,8 +13,12 @@ import (
"github.com/golang-jwt/jwt/v5"
internxtauth "github.com/internxt/rclone-adapter/auth"
internxtconfig "github.com/internxt/rclone-adapter/config"
sdkerrors "github.com/internxt/rclone-adapter/errors"
"github.com/rclone/rclone/fs"
"github.com/rclone/rclone/fs/config/configmap"
"github.com/rclone/rclone/fs/config/obscure"
"github.com/rclone/rclone/fs/fserrors"
"github.com/rclone/rclone/fs/fshttp"
"github.com/rclone/rclone/lib/oauthutil"
"golang.org/x/oauth2"
)
@@ -101,7 +105,6 @@ func jwtToOAuth2Token(jwtString string) (*oauth2.Token, error) {
}
// computeBasicAuthHeader creates the BasicAuthHeader for bucket operations
// Following the pattern from SDK's auth/access.go:96-102
func computeBasicAuthHeader(bridgeUser, userID string) string {
sum := sha256.Sum256([]byte(userID))
hexPass := hex.EncodeToString(sum[:])
@@ -144,3 +147,100 @@ func refreshJWTToken(ctx context.Context, name string, m configmap.Mapper) error
fs.Debugf(name, "Token refreshed successfully, new expiry: %v", token.Expiry)
return nil
}
// reLogin performs a full re-login using stored email+password credentials.
// Returns the AccessResponse on success, or an error if 2FA is required or login fails.
func (f *Fs) reLogin(ctx context.Context) (*internxtauth.AccessResponse, error) {
password, err := obscure.Reveal(f.opt.Pass)
if err != nil {
return nil, fmt.Errorf("couldn't decrypt password: %w", err)
}
cfg := internxtconfig.NewDefaultToken("")
cfg.HTTPClient = fshttp.NewClient(ctx)
loginResp, err := internxtauth.Login(ctx, cfg, f.opt.Email)
if err != nil {
return nil, fmt.Errorf("re-login check failed: %w", err)
}
if loginResp.TFA {
return nil, errors.New("account requires 2FA - please run: rclone config reconnect " + f.name + ":")
}
resp, err := internxtauth.DoLogin(ctx, cfg, f.opt.Email, password, "")
if err != nil {
return nil, fmt.Errorf("re-login failed: %w", err)
}
return resp, nil
}
// refreshOrReLogin tries to refresh the JWT token first; if that fails with 401,
// it falls back to a full re-login using stored credentials.
func (f *Fs) refreshOrReLogin(ctx context.Context) error {
refreshErr := refreshJWTToken(ctx, f.name, f.m)
if refreshErr == nil {
newToken, err := oauthutil.GetToken(f.name, f.m)
if err != nil {
return fmt.Errorf("failed to get refreshed token: %w", err)
}
f.cfg.Token = newToken.AccessToken
f.cfg.BasicAuthHeader = computeBasicAuthHeader(f.bridgeUser, f.userID)
fs.Debugf(f, "Token refresh succeeded")
return nil
}
var httpErr *sdkerrors.HTTPError
if !errors.As(refreshErr, &httpErr) || httpErr.StatusCode() != 401 {
if fserrors.ShouldRetry(refreshErr) {
return refreshErr
}
return refreshErr
}
fs.Debugf(f, "Token refresh returned 401, attempting re-login with stored credentials")
resp, err := f.reLogin(ctx)
if err != nil {
return fmt.Errorf("re-login fallback failed: %w", err)
}
oauthToken, err := jwtToOAuth2Token(resp.NewToken)
if err != nil {
return fmt.Errorf("failed to parse re-login token: %w", err)
}
err = oauthutil.PutToken(f.name, f.m, oauthToken, true)
if err != nil {
return fmt.Errorf("failed to save re-login token: %w", err)
}
f.cfg.Token = oauthToken.AccessToken
f.bridgeUser = resp.User.BridgeUser
f.userID = resp.User.UserID
f.cfg.BasicAuthHeader = computeBasicAuthHeader(f.bridgeUser, f.userID)
f.cfg.Bucket = resp.User.Bucket
f.cfg.RootFolderID = resp.User.RootFolderID
fs.Debugf(f, "Re-login succeeded, new token expiry: %v", oauthToken.Expiry)
return nil
}
// reAuthorize is called after getting 401 from the server.
// It serializes re-auth attempts and uses a circuit-breaker to avoid infinite loops.
func (f *Fs) reAuthorize(ctx context.Context) error {
f.authMu.Lock()
defer f.authMu.Unlock()
if f.authFailed {
return errors.New("re-authorization permanently failed")
}
err := f.refreshOrReLogin(ctx)
if err != nil {
f.authFailed = true
return err
}
return nil
}
+119 -71
View File
@@ -9,8 +9,8 @@ import (
"io"
"net"
"path"
"path/filepath"
"strings"
"sync"
"time"
"github.com/internxt/rclone-adapter/auth"
@@ -41,16 +41,34 @@ const (
decayConstant = 2 // bigger for slower decay, exponential
)
// shouldRetry determines if an error should be retried
func shouldRetry(ctx context.Context, err error) (bool, error) {
// shouldRetry determines if an error should be retried.
// On 401, it attempts to re-authorize before retrying.
// On 429, it honours the server's rate limit retry delay.
func (f *Fs) shouldRetry(ctx context.Context, err error) (bool, error) {
if fserrors.ContextError(ctx, &err) {
return false, err
}
var httpErr *sdkerrors.HTTPError
if errors.As(err, &httpErr) && httpErr.StatusCode() == 401 {
return true, err
if errors.As(err, &httpErr) {
switch httpErr.StatusCode() {
case 401:
if !f.authFailed {
authErr := f.reAuthorize(ctx)
if authErr != nil {
fs.Debugf(f, "Re-authorization failed: %v", authErr)
return false, err
}
return true, err
}
return false, err
case 429:
delay := httpErr.RetryAfter()
if delay <= 0 {
delay = time.Second
}
return true, pacer.RetryAfterError(err, delay)
}
}
return fserrors.ShouldRetry(err), err
}
@@ -184,6 +202,7 @@ type Fs struct {
name string
root string
opt Options
m configmap.Mapper
dirCache *dircache.DirCache
cfg *config.Config
features *fs.Features
@@ -191,6 +210,8 @@ type Fs struct {
tokenRenewer *oauthutil.Renew
bridgeUser string
userID string
authMu sync.Mutex
authFailed bool
}
// Object holds the data for a remote file object
@@ -263,45 +284,62 @@ func NewFs(ctx context.Context, name, root string, m configmap.Mapper) (fs.Fs, e
cfg.SkipHashValidation = opt.SkipHashValidation
cfg.HTTPClient = fshttp.NewClient(ctx)
userInfo, err := getUserInfo(ctx, &userInfoConfig{Token: cfg.Token})
if err != nil {
return nil, fmt.Errorf("failed to fetch user info: %w", err)
}
cfg.RootFolderID = userInfo.RootFolderID
cfg.Bucket = userInfo.Bucket
cfg.BasicAuthHeader = computeBasicAuthHeader(userInfo.BridgeUser, userInfo.UserID)
f := &Fs{
name: name,
root: strings.Trim(root, "/"),
opt: *opt,
cfg: cfg,
bridgeUser: userInfo.BridgeUser,
userID: userInfo.UserID,
name: name,
root: strings.Trim(root, "/"),
opt: *opt,
m: m,
cfg: cfg,
}
f.pacer = fs.NewPacer(ctx, pacer.NewDefault(pacer.MinSleep(minSleep), pacer.MaxSleep(maxSleep), pacer.DecayConstant(decayConstant)))
var userInfo *userInfo
const maxRetries = 3
for attempt := 1; attempt <= maxRetries; attempt++ {
userInfo, err = getUserInfo(ctx, &userInfoConfig{Token: f.cfg.Token})
if err == nil {
break
}
var httpErr *sdkerrors.HTTPError
if errors.As(err, &httpErr) && httpErr.StatusCode() == 401 {
fs.Debugf(f, "getUserInfo returned 401, attempting re-auth")
authErr := f.refreshOrReLogin(ctx)
if authErr != nil {
return nil, fmt.Errorf("failed to fetch user info (re-auth failed): %w", err)
}
userInfo, err = getUserInfo(ctx, &userInfoConfig{Token: f.cfg.Token})
if err == nil {
break
}
return nil, fmt.Errorf("failed to fetch user info after re-auth: %w", err)
}
if fserrors.ShouldRetry(err) && attempt < maxRetries {
fs.Debugf(f, "getUserInfo transient error (attempt %d/%d): %v", attempt, maxRetries, err)
time.Sleep(time.Duration(attempt) * time.Second)
continue
}
return nil, fmt.Errorf("failed to fetch user info: %w", err)
}
f.cfg.RootFolderID = userInfo.RootFolderID
f.cfg.Bucket = userInfo.Bucket
f.cfg.BasicAuthHeader = computeBasicAuthHeader(userInfo.BridgeUser, userInfo.UserID)
f.bridgeUser = userInfo.BridgeUser
f.userID = userInfo.UserID
f.features = (&fs.Features{
CanHaveEmptyDirectories: true,
}).Fill(ctx, f)
if ts != nil {
f.tokenRenewer = oauthutil.NewRenew(f.String(), ts, func() error {
err := refreshJWTToken(ctx, name, m)
if err != nil {
return err
}
newToken, err := oauthutil.GetToken(name, m)
if err != nil {
return fmt.Errorf("failed to get refreshed token: %w", err)
}
f.cfg.Token = newToken.AccessToken
f.cfg.BasicAuthHeader = computeBasicAuthHeader(f.bridgeUser, f.userID)
return nil
f.authMu.Lock()
defer f.authMu.Unlock()
return f.refreshOrReLogin(ctx)
})
f.tokenRenewer.Start()
}
@@ -312,9 +350,19 @@ func NewFs(ctx context.Context, name, root string, m configmap.Mapper) (fs.Fs, e
if err != nil {
// Assume it might be a file
newRoot, remote := dircache.SplitPath(f.root)
tempF := *f
tempF.dirCache = dircache.New(newRoot, f.cfg.RootFolderID, &tempF)
tempF.root = newRoot
tempF := &Fs{
name: f.name,
root: newRoot,
opt: f.opt,
m: f.m,
cfg: f.cfg,
features: f.features,
pacer: f.pacer,
tokenRenewer: f.tokenRenewer,
bridgeUser: f.bridgeUser,
userID: f.userID,
}
tempF.dirCache = dircache.New(newRoot, f.cfg.RootFolderID, tempF)
err = tempF.dirCache.FindRoot(ctx, false)
if err != nil {
@@ -367,7 +415,7 @@ func (f *Fs) Rmdir(ctx context.Context, dir string) error {
err = f.pacer.Call(func() (bool, error) {
var err error
childFolders, err = folders.ListAllFolders(ctx, f.cfg, id)
return shouldRetry(ctx, err)
return f.shouldRetry(ctx, err)
})
if err != nil {
return err
@@ -380,7 +428,7 @@ func (f *Fs) Rmdir(ctx context.Context, dir string) error {
err = f.pacer.Call(func() (bool, error) {
var err error
childFiles, err = folders.ListAllFiles(ctx, f.cfg, id)
return shouldRetry(ctx, err)
return f.shouldRetry(ctx, err)
})
if err != nil {
return err
@@ -395,7 +443,7 @@ func (f *Fs) Rmdir(ctx context.Context, dir string) error {
if err != nil && strings.Contains(err.Error(), "404") {
return false, fs.ErrorDirNotFound
}
return shouldRetry(ctx, err)
return f.shouldRetry(ctx, err)
})
if err != nil {
return err
@@ -412,7 +460,7 @@ func (f *Fs) FindLeaf(ctx context.Context, pathID, leaf string) (string, bool, e
err := f.pacer.Call(func() (bool, error) {
var err error
entries, err = folders.ListAllFolders(ctx, f.cfg, pathID)
return shouldRetry(ctx, err)
return f.shouldRetry(ctx, err)
})
if err != nil {
return "", false, err
@@ -437,7 +485,7 @@ func (f *Fs) CreateDir(ctx context.Context, pathID, leaf string) (string, error)
err := f.pacer.CallNoRetry(func() (bool, error) {
var err error
resp, err = folders.CreateFolder(ctx, f.cfg, request)
return shouldRetry(ctx, err)
return f.shouldRetry(ctx, err)
})
if err != nil {
// If folder already exists (409 conflict), try to find it
@@ -459,8 +507,8 @@ func (f *Fs) CreateDir(ctx context.Context, pathID, leaf string) (string, error)
func (f *Fs) preUploadCheck(ctx context.Context, leaf, directoryID string) (*folders.File, error) {
// Parse name and extension from the leaf
baseName := f.opt.Encoding.FromStandardName(leaf)
name := strings.TrimSuffix(baseName, filepath.Ext(baseName))
ext := strings.TrimPrefix(filepath.Ext(baseName), ".")
name := strings.TrimSuffix(baseName, path.Ext(baseName))
ext := strings.TrimPrefix(path.Ext(baseName), ".")
checkResult, err := files.CheckFilesExistence(ctx, f.cfg, directoryID, []files.FileExistenceCheck{
{
@@ -525,20 +573,20 @@ func (f *Fs) List(ctx context.Context, dir string) (fs.DirEntries, error) {
err = f.pacer.Call(func() (bool, error) {
var err error
foldersList, err = folders.ListAllFolders(ctx, f.cfg, dirID)
return shouldRetry(ctx, err)
return f.shouldRetry(ctx, err)
})
if err != nil {
return nil, err
}
for _, e := range foldersList {
remote := filepath.Join(dir, f.opt.Encoding.ToStandardName(e.PlainName))
remote := path.Join(dir, f.opt.Encoding.ToStandardName(e.PlainName))
out = append(out, fs.NewDir(remote, e.ModificationTime))
}
var filesList []folders.File
err = f.pacer.Call(func() (bool, error) {
var err error
filesList, err = folders.ListAllFiles(ctx, f.cfg, dirID)
return shouldRetry(ctx, err)
return f.shouldRetry(ctx, err)
})
if err != nil {
return nil, err
@@ -548,7 +596,7 @@ func (f *Fs) List(ctx context.Context, dir string) (fs.DirEntries, error) {
if len(e.Type) > 0 {
remote += "." + e.Type
}
remote = filepath.Join(dir, f.opt.Encoding.ToStandardName(remote))
remote = path.Join(dir, f.opt.Encoding.ToStandardName(remote))
out = append(out, newObjectWithFile(f, remote, &e))
}
return out, nil
@@ -616,7 +664,7 @@ func (f *Fs) Remove(ctx context.Context, remote string) error {
}
err = f.pacer.Call(func() (bool, error) {
err := folders.DeleteFolder(ctx, f.cfg, dirID)
return shouldRetry(ctx, err)
return f.shouldRetry(ctx, err)
})
if err != nil {
return err
@@ -627,7 +675,7 @@ func (f *Fs) Remove(ctx context.Context, remote string) error {
// NewObject creates a new object
func (f *Fs) NewObject(ctx context.Context, remote string) (fs.Object, error) {
parentDir := filepath.Dir(remote)
parentDir := path.Dir(remote)
if parentDir == "." {
parentDir = ""
@@ -642,12 +690,12 @@ func (f *Fs) NewObject(ctx context.Context, remote string) (fs.Object, error) {
err = f.pacer.Call(func() (bool, error) {
var err error
files, err = folders.ListAllFiles(ctx, f.cfg, dirID)
return shouldRetry(ctx, err)
return f.shouldRetry(ctx, err)
})
if err != nil {
return nil, err
}
targetName := filepath.Base(remote)
targetName := path.Base(remote)
for _, e := range files {
name := e.PlainName
if len(e.Type) > 0 {
@@ -720,7 +768,7 @@ func (f *Fs) About(ctx context.Context) (*fs.Usage, error) {
err := f.pacer.Call(func() (bool, error) {
var err error
internxtLimit, err = users.GetLimit(ctx, f.cfg)
return shouldRetry(ctx, err)
return f.shouldRetry(ctx, err)
})
if err != nil {
return nil, err
@@ -730,7 +778,7 @@ func (f *Fs) About(ctx context.Context) (*fs.Usage, error) {
err = f.pacer.Call(func() (bool, error) {
var err error
internxtUsage, err = users.GetUsage(ctx, f.cfg)
return shouldRetry(ctx, err)
return f.shouldRetry(ctx, err)
})
if err != nil {
return nil, err
@@ -776,7 +824,7 @@ func (o *Object) Open(ctx context.Context, options ...fs.OpenOption) (io.ReadClo
err := o.f.pacer.Call(func() (bool, error) {
var err error
stream, err = buckets.DownloadFileStream(ctx, o.f.cfg, o.id, rangeValue)
return shouldRetry(ctx, err)
return o.f.shouldRetry(ctx, err)
})
if err != nil {
return nil, err
@@ -788,9 +836,9 @@ func (o *Object) Open(ctx context.Context, options ...fs.OpenOption) (io.ReadClo
func (o *Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, options ...fs.OpenOption) error {
remote := o.remote
origBaseName := filepath.Base(remote)
origName := strings.TrimSuffix(origBaseName, filepath.Ext(origBaseName))
origType := strings.TrimPrefix(filepath.Ext(origBaseName), ".")
origBaseName := path.Base(remote)
origName := strings.TrimSuffix(origBaseName, path.Ext(origBaseName))
origType := strings.TrimPrefix(path.Ext(origBaseName), ".")
// Create directory if it doesn't exist
_, dirID, err := o.f.dirCache.FindPath(ctx, remote, true)
@@ -808,9 +856,9 @@ func (o *Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, op
// Step 1: If file exists, rename to backup (preserves old file during upload)
if oldUUID != "" {
// Generate unique backup name
baseName := filepath.Base(remote)
name := strings.TrimSuffix(baseName, filepath.Ext(baseName))
ext := strings.TrimPrefix(filepath.Ext(baseName), ".")
baseName := path.Base(remote)
name := strings.TrimSuffix(baseName, path.Ext(baseName))
ext := strings.TrimPrefix(path.Ext(baseName), ".")
backupSuffix := fmt.Sprintf(".rclone-backup-%s", random.String(8))
backupName = o.f.opt.Encoding.FromStandardName(name + backupSuffix)
@@ -826,7 +874,7 @@ func (o *Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, op
return false, nil
}
}
return shouldRetry(ctx, err)
return o.f.shouldRetry(ctx, err)
})
if err != nil {
return fmt.Errorf("failed to rename existing file to backup: %w", err)
@@ -842,12 +890,12 @@ func (o *Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, op
meta, err = buckets.UploadFileStreamAuto(ctx,
o.f.cfg,
dirID,
o.f.opt.Encoding.FromStandardName(filepath.Base(remote)),
o.f.opt.Encoding.FromStandardName(path.Base(remote)),
in,
src.Size(),
src.ModTime(ctx),
)
return shouldRetry(ctx, err)
return o.f.shouldRetry(ctx, err)
})
if err != nil && isEmptyFileLimitError(err) {
@@ -885,7 +933,7 @@ func (o *Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, op
}
}
}
return shouldRetry(ctx, err)
return o.f.shouldRetry(ctx, err)
})
if err != nil {
fs.Errorf(o.f, "Failed to delete backup file %s.%s (UUID: %s): %v. This may leave an orphaned backup file.",
@@ -932,18 +980,18 @@ func (o *Object) recoverFromTimeoutConflict(ctx context.Context, uploadErr error
return nil, uploadErr
}
baseName := filepath.Base(remote)
baseName := path.Base(remote)
encodedName := o.f.opt.Encoding.FromStandardName(baseName)
var meta *buckets.CreateMetaResponse
checkErr := o.f.pacer.Call(func() (bool, error) {
existingFile, err := o.f.preUploadCheck(ctx, encodedName, dirID)
if err != nil {
return shouldRetry(ctx, err)
return o.f.shouldRetry(ctx, err)
}
if existingFile != nil {
name := strings.TrimSuffix(baseName, filepath.Ext(baseName))
ext := strings.TrimPrefix(filepath.Ext(baseName), ".")
name := strings.TrimSuffix(baseName, path.Ext(baseName))
ext := strings.TrimPrefix(path.Ext(baseName), ".")
meta = &buckets.CreateMetaResponse{
UUID: existingFile.UUID,
@@ -978,7 +1026,7 @@ func (o *Object) restoreBackupFile(ctx context.Context, backupUUID, origName, or
_ = o.f.pacer.Call(func() (bool, error) {
err := files.RenameFile(ctx, o.f.cfg, backupUUID,
o.f.opt.Encoding.FromStandardName(origName), origType)
return shouldRetry(ctx, err)
return o.f.shouldRetry(ctx, err)
})
}
@@ -986,6 +1034,6 @@ func (o *Object) restoreBackupFile(ctx context.Context, backupUUID, origName, or
func (o *Object) Remove(ctx context.Context) error {
return o.f.pacer.Call(func() (bool, error) {
err := files.DeleteFile(ctx, o.f.cfg, o.uuid)
return shouldRetry(ctx, err)
return o.f.shouldRetry(ctx, err)
})
}
+1
View File
@@ -4,6 +4,7 @@ region:
eu-west-1: Europe West
endpoint:
s3.cubbit.eu: Cubbit DS3 Object Storage endpoint
s3.{tenant_name}.cubbit.eu: Multi-tenant endpoint - replace {tenant_name} with your actual tenant name. Do not select this directly
acl: {}
bucket_acl: true
quirks:
+1 -1
View File
@@ -15,7 +15,7 @@ endpoint:
acl: {}
bucket_acl: true
quirks:
list_version: 1
list_version: 2
force_path_style: true
list_url_encode: false
use_multipart_etag: false
+9 -3
View File
@@ -1691,6 +1691,10 @@ func NewFs(ctx context.Context, name, root string, m configmap.Mapper) (fs.Fs, e
if opt.Provider == "Rabata" {
f.features.Copy = nil
}
if opt.Provider == "TencentCOS" && strings.Contains(opt.Endpoint, "cos.accelerate.myqcloud.com") {
// Global Acceleration endpoint does not support bucket creation.
f.opt.NoCheckBucket = true
}
if opt.DirectoryMarkers {
f.features.CanHaveEmptyDirectories = true
}
@@ -2169,9 +2173,11 @@ func (f *Fs) list(ctx context.Context, opt listOpt, fn listFn) error {
opt.directory += "/"
}
}
delimiter := ""
// Use nil delimiter for recursive listings to omit the parameter
// entirely. Some S3-compatible servers reject an empty delimiter.
var delimiter *string
if !opt.recurse {
delimiter = "/"
delimiter = aws.String("/")
}
// URL encode the listings so we can use control characters in object names
// See: https://github.com/aws/aws-sdk-go/issues/1914
@@ -2191,7 +2197,7 @@ func (f *Fs) list(ctx context.Context, opt listOpt, fn listFn) error {
urlEncodeListings := f.opt.ListURLEncode.Value
req := s3.ListObjectsV2Input{
Bucket: &opt.bucket,
Delimiter: &delimiter,
Delimiter: delimiter,
Prefix: &opt.directory,
MaxKeys: &f.opt.ListChunk,
}
+1 -1
View File
@@ -423,7 +423,7 @@ func (f *Fs) filePath(file string) string {
if f.opt.Enc != encoder.EncodeZero {
subPath = f.opt.Enc.FromStandardPath(subPath)
}
return rest.URLPathEscape(subPath)
return rest.URLPathEscapeAll(subPath)
}
// dirPath returns a directory path (f.root, dir)
+32
View File
@@ -80,3 +80,35 @@ func TestHeaders(t *testing.T) {
_, err := f.Features().About(context.Background())
require.NoError(t, err)
}
// TestReservedCharactersInPathAreEscaped verifies that reserved characters
// like semicolons and equals signs in file paths are percent-encoded in
// HTTP requests to the WebDAV server (RFC 3986 compliance).
func TestReservedCharactersInPathAreEscaped(t *testing.T) {
var capturedPath string
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
capturedPath = r.RequestURI
// Return a 404 so the NewObject call fails cleanly
w.WriteHeader(http.StatusNotFound)
})
ts := httptest.NewServer(handler)
defer ts.Close()
configfile.Install()
m := configmap.Simple{
"type": "webdav",
"url": ts.URL,
}
f, err := webdav.NewFs(context.Background(), remoteName, "", m)
require.NoError(t, err)
// Try to access a file with a semicolon in the name.
// We expect the request to fail (404), but the path should be escaped.
_, _ = f.NewObject(context.Background(), "my;test")
// The semicolon must be percent-encoded as %3B
assert.Contains(t, capturedPath, "my%3Btest", "semicolons in path should be percent-encoded")
assert.NotContains(t, capturedPath, "my;test", "raw semicolons should not appear in path")
}
+10
View File
@@ -147,6 +147,16 @@ func ArchiveExtract(ctx context.Context, dst fs.Fs, dstDir string, src fs.Fs, sr
// extract files
err = ex.Extract(ctx, in, func(ctx context.Context, f archives.FileInfo) error {
remote := f.NameInArchive
// Strip leading "./" from archive paths. Tar files created with
// relative paths (e.g. "tar -czf archive.tar.gz .") use "./" prefixed
// entries. Without stripping, rclone encodes the "." as a full-width
// dot character creating a spurious directory. We only strip "./"
// specifically to avoid enabling path traversal attacks via "../".
remote = strings.TrimPrefix(remote, "./")
// If the entry was exactly "./" (the root dir), skip it
if remote == "" && f.IsDir() {
return nil
}
if dstDir != "" {
remote = path.Join(dstDir, remote)
}
+62
View File
@@ -0,0 +1,62 @@
//go:build !plan9
package extract
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
)
func TestStripDotSlashPrefix(t *testing.T) {
tests := []struct {
name string
input string
expected string
}{
{
name: "strip leading dot-slash from file",
input: "./file.txt",
expected: "file.txt",
},
{
name: "strip leading dot-slash from nested path",
input: "./subdir/file.txt",
expected: "subdir/file.txt",
},
{
name: "no prefix unchanged",
input: "file.txt",
expected: "file.txt",
},
{
name: "nested path unchanged",
input: "dir/file.txt",
expected: "dir/file.txt",
},
{
name: "dot-dot-slash NOT stripped (path traversal safety)",
input: "../etc/passwd",
expected: "../etc/passwd",
},
{
name: "dot-slash directory entry becomes empty",
input: "./",
expected: "",
},
{
name: "only single leading dot-slash stripped",
input: "././file.txt",
expected: "./file.txt",
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
// This mirrors the stripping logic in ArchiveExtract
got := strings.TrimPrefix(tc.input, "./")
assert.Equal(t, tc.expected, got)
})
}
}
+1 -1
View File
@@ -162,7 +162,7 @@ var commandDefinition = &cobra.Command{
Long: longHelp,
Annotations: map[string]string{
"versionIntroduced": "v1.58",
"groups": "Filter,Copy,Important",
"groups": "Filter,Copy,Important,Sync",
},
RunE: func(command *cobra.Command, args []string) error {
// NOTE: avoid putting too much handling here, as it won't apply to the rc.
+9
View File
@@ -70,6 +70,15 @@ Note that |--stdout| and |--print-filename| are incompatible with |--urls|.
This will do |--transfers| copies in parallel. Note that if |--auto-filename|
is desired for all URLs then a file with only URLs and no filename can be used.
Each FILENAME in the CSV file can start with a relative path which will be appended
to the destination path provided at the command line. For example, running the command
shown above with the following CSV file will write two files to the destination:
|remote:dir/local/path/bar.json| and |remote:dir/another/local/directory/qux.json|
|||csv
https://example.org/foo/bar.json,local/path/bar.json
https://example.org/qux/baz.json,another/local/directory/qux.json
|||
### Troubleshooting
If you can't get |rclone copyurl| to work then here are some things you can try:
+17 -15
View File
@@ -1,7 +1,8 @@
Rclone @ allows Linux, FreeBSD, macOS and Windows to
mount any of Rclone's cloud storage systems as a file system with FUSE.
First set up your remote using `rclone config`. Check it works with `rclone ls` etc.
First set up your remote using `rclone config`. Check it works with `rclone ls`
etc.
On Linux and macOS, you can run mount in either foreground or background (aka
daemon) mode. Mount runs in foreground mode by default. Use the `--daemon` flag
@@ -29,8 +30,8 @@ The following examples will mount to an automatically assigned drive,
to specific drive letter `X:`, to path `C:\path\parent\mount`
(where parent directory or drive must exist, and mount must **not** exist,
and is not supported when [mounting as a network drive](#mounting-modes-on-windows)),
and the last example will mount as network share `\\cloud\remote` and map it to an
automatically assigned drive:
and the last example will mount as network share `\\cloud\remote` and map it to
an automatically assigned drive:
```console
rclone @ remote:path/to/files *
@@ -136,8 +137,8 @@ rclone @ remote:path/to/files X: --volname \\server\share
You may also specify the network share UNC path as the mountpoint itself. Then rclone
will automatically assign a drive letter, same as with `*` and use that as
mountpoint, and instead use the UNC path specified as the volume name, as if it were
specified with the `--volname` option. This will also implicitly set
mountpoint, and instead use the UNC path specified as the volume name, as if it
were specified with the `--volname` option. This will also implicitly set
the `--network-mode` option. This means the following two examples have same result:
```console
@@ -268,7 +269,7 @@ does not suffer from the same limitations.
Mounting on macOS can be done either via [built-in NFS server](/commands/rclone_serve_nfs/),
[macFUSE](https://osxfuse.github.io/) (also known as osxfuse) or
[FUSE-T](https://www.fuse-t.org/).macFUSE is a traditional FUSE driver utilizing
[FUSE-T](https://www.fuse-t.org/). macFUSE is a traditional FUSE driver utilizing
a macOS kernel extension (kext). FUSE-T is an alternative FUSE system which
"mounts" via an NFSv4 local server.
@@ -311,29 +312,30 @@ current as of FUSE-T version 1.0.14.
As per the [FUSE-T wiki](https://github.com/macos-fuse-t/fuse-t/wiki#caveats):
> File access and modification times cannot be set separately as it seems to be an
> issue with the NFS client which always modifies both. Can be reproduced with
> 'touch -m' and 'touch -a' commands
> File access and modification times cannot be set separately as it seems to be
> an issue with the NFS client which always modifies both. Can be reproduced
> with `touch -m` and `touch -a` commands
This means that viewing files with various tools, notably macOS Finder, will cause
rlcone to update the modification time of the file. This may make rclone upload a
full new copy of the file.
This means that viewing files with various tools, notably macOS Finder, will
cause rlcone to update the modification time of the file. This may make rclone
upload a full new copy of the file.
##### Read Only mounts
When mounting with `--read-only`, attempts to write to files will fail *silently*
as opposed to with a clear warning as in macFUSE.
## Mounting on Linux
### Mounting on Linux
On newer versions of Ubuntu, you may encounter the following error when running
`rclone mount`:
> NOTICE: mount helper error: fusermount3: mount failed: Permission denied
> CRITICAL: Fatal error: failed to mount FUSE fs: fusermount: exit status 1
This may be due to newer [Apparmor](https://wiki.ubuntu.com/AppArmor) restrictions,
which can be disabled with `sudo aa-disable /usr/bin/fusermount3` (you may need to
`sudo apt install apparmor-utils` beforehand).
which can be disabled with `sudo aa-disable /usr/bin/fusermount3` (you may need
to `sudo apt install apparmor-utils` beforehand).
### Limitations
+2 -4
View File
@@ -1049,11 +1049,9 @@ The following backends have known issues that need more investigation:
<!--- start list_failures - DO NOT EDIT THIS SECTION - use make commanddocs --->
- `TestDropbox` (`dropbox`)
- [`TestBisyncRemoteRemote/normalization`](https://pub.rclone.org/integration-tests/current/dropbox-cmd.bisync-TestDropbox-1.txt)
- `TestSeafile` (`seafile`)
- [`TestBisyncLocalRemote/volatile`](https://pub.rclone.org/integration-tests/current/seafile-cmd.bisync-TestSeafile-1.txt)
- `TestSeafileV6` (`seafile`)
- [`TestBisyncLocalRemote/volatile`](https://pub.rclone.org/integration-tests/current/seafile-cmd.bisync-TestSeafileV6-1.txt)
- Updated: 2026-01-30-010015
- [`TestBisyncLocalRemote/rmdirs`](https://pub.rclone.org/integration-tests/current/seafile-cmd.bisync-TestSeafileV6-1.txt)
- Updated: 2026-04-19-010011
<!--- end list_failures - DO NOT EDIT THIS SECTION - use make commanddocs --->
The following backends either have not been tested recently or have known issues
+116 -1
View File
@@ -6,6 +6,121 @@ description: "Rclone Changelog"
# Changelog
## v1.73.5 - 2026-04-19
[See commits](https://github.com/rclone/rclone/compare/v1.73.4...v1.73.5)
- Bug Fixes
- operations: Add AuthRequired to operations/fsinfo to prevent backend creation CVE-2026-41179 (Nick Craig-Wood)
- rc
- Add AuthRequired to options/set to prevent auth bypass CVE-2026-41176 (Nick Craig-Wood)
- Snapshot NoAuth at startup to prevent runtime auth bypass CVE-2026-41176 (Nick Craig-Wood)
- filter: Fix debug logs that fire before logger is configured (Nick Craig-Wood)
- Azureblob
- Add Microsoft Partner Network User-Agent prefix (Nick Craig-Wood)
- Drime
- Fix User.EntryPermissions JSON unmarshalling (a1pcm)
- Iclouddrive
- Fix 'directory not found' error when the directory contains accent marks (Brais Couce)
- S3
- Fix TencentCOS CDN endpoint failing on bucket check (Mozi)
- Fix empty delimiter parameter rejected by Archiware P5 server (Nick Craig-Wood)
## v1.73.4 - 2026-04-08
[See commits](https://github.com/rclone/rclone/compare/v1.73.3...v1.73.4)
- Bug Fixes
- build
- Update to go 1.25.9 to fix multiple CVEs (Nick Craig-Wood)
- CVE-2026-32282: os: Root.Chmod can follow symlinks out of the root on Linux
- CVE-2026-32289: html/template: JS template literal context incorrectly tracked
- CVE-2026-33810: crypto/x509: excluded DNS constraints not properly applied to wildcard domains
- CVE-2026-27144: cmd/compile: no-op interface conversion bypasses overlap checking
- CVE-2026-27143: cmd/compile: possible memory corruption after bound check elimination
- CVE-2026-32288: archive/tar: unbounded allocation when parsing old format GNU sparse map
- CVE-2026-32283: crypto/tls: multiple key update handshake messages can cause connection to deadlock
- CVE-2026-27140: cmd/go: trust layer bypass when using cgo and SWIG
- CVE-2026-32280: crypto/x509: unexpected work during chain building
- CVE-2026-32281: crypto/x509: inefficient policy validation
- Fix Denial of Service due to Panic in AWS SDK for Go v2 SDK EventStream Decoder (dependabot[bot])
- Update golang.org/x/image to 0.38.0 to fix CVE-2026-33809 (dependabot[bot])
- docs
- Fix header level for metadata option (Clément Notin)
- Fix markdown issues in mount docs (albertony)
- Fix link to not be language specific (Ross Smith II)
- Note macOS 10.15 (Catalina) support with version v1.70.3 (kapitainsky)
- Filen
- Update SDK version (Enduriel)
## v1.73.3 - 2026-03-23
[See commits](https://github.com/rclone/rclone/compare/v1.73.2...v1.73.3)
- Bug Fixes
- build
- Update to google.golang.org/grpc 1.79.3 to fix CVE-2026-33186 (dependabot[bot])
- Update to github.com/buger/jsonparser 1.1.2 to fix GHSA-6g7g-w4f8-9c9x (dependabot[bot])
- doc fixes
- Added text to the label showing version-introduced info (Jan-Philipp Reßler)
- Clarify Filen password change requires updating both password and API key in rclone config (Jason)
- s3: clarify multi tenant support for Cubbit (Marco Ferretti)
- jottacloud: Fix broken link (albertony)
- lib/rest: Fix URLPathEscapeAll breaking WebDAV servers (eg nzbdav) with strict path matching (Andrew Furman)
- list: Fix nil pointer panic in Sorter when temp file creation fails (Nick Craig-Wood)
## v1.73.2 - 2026-03-06
[See commits](https://github.com/rclone/rclone/compare/v1.73.1...v1.73.2)
- Bug Fixes
- build
- Update to go 1.25.8 to fix CVE-2026-27137 CVE-2026-27138 CVE-2026-25679 CVE-2026-27142 (Nick Craig-Wood)
- Update github.com/cloudflare/circl to v1.6.3 to fix CVE-2026-1229 (Nick Craig-Wood)
- Update to golang.org/x/net v0.51.0 to fix CVE-2026-27141 (Nick Craig-Wood)
- docs fixes:
- bisync: Add group Sync to the bisync command (Jan-Philipp Reßler)
- Note that --use-server-modtime only works on some backends (Nick Craig-Wood)
- Document unsupported S3 object keys with double slashes (Adam Kasztenny)
- Fix headers hierarchy for mount.md (Dark Dragon)
- Fix new drive flag typo in changelog (razorloves)
- Archive
- Extract: fix extraction with "./" prefix from tar entry paths (Varun Chawla)
- Drime
- Fix chunk-uploaded files ignoring workspace ID (a1pcm)
- Internxt
- Fix Entry doesn't belong in directory errors on windows (jzunigax2)
- WebDAV
- Escape reserved characters in URL path segments (Varun Chawla)
- Add missing headers for CORS (Romāns Potašovs)
## v1.73.1 - 2026-02-17
[See commits](https://github.com/rclone/rclone/compare/v1.73.0...v1.73.1)
- Bug Fixes
- accounting: Fix missing server side stats from core/stats rc (Nick Craig-Wood)
- build
- Fix CVE-2025-68121 by updating go to 1.25.7 or later (Nick Craig-Wood)
- Bump github.com/go-chi/chi/v5 from 5.2.3 to 5.2.5 to fix GO-2026-4316 (albertony)
- docs: Extend copyurl docs with an example of CSV FILENAMEs starting with a path. (Jack Kelly)
- march: Fix runtime: program exceeds 10000-thread limit (Nick Craig-Wood)
- pacer
- Fix deadlock between pacer token and --max-connections (Nick Craig-Wood)
- Re-read the sleep time as it may be stale (Nick Craig-Wood)
- Drime
- Fix files and directories being created in the default workspace (Nick Craig-Wood)
- Filelu
- Avoid buffering entire file in memory (kingston125)
- Add multipart upload support with configurable cutoff (kingston125)
- Filen
- Fix 32 bit targets not being able to list directories (Enduriel)
- Fix potential panic in case of error during upload (Enduriel)
- Internxt
- Implement re-login under refresh logic, improve retry logic (José Zúniga)
-S3
- Set list_version to 2 for FileLu S3 configuration (kingston125)
## v1.73.0 - 2026-01-30
[See commits](https://github.com/rclone/rclone/compare/v1.72.0...v1.73.0)
@@ -36,7 +151,7 @@ description: "Rclone Changelog"
- B2
- Support authentication with new bucket restricted application keys (DianaNites)
- Drive
- Add `--drive-metadata-force-expansive-access` flag (Nick Craig-Wood)
- Add `--drive-metadata-enforce-expansive-access` flag (Nick Craig-Wood)
- Fix crash when trying to creating shortcut to a Google doc (Nick Craig-Wood)
- FTP
- Add http proxy authentication support (Nicolas Dessart)
+3 -1
View File
@@ -329,9 +329,11 @@ rclone [flags]
--filefabric-token-expiry string Token expiry time
--filefabric-url string URL of the Enterprise File Fabric to connect to
--filefabric-version string Version read from the file fabric
--filelu-chunk-size SizeSuffix Chunk size to use for uploading. Used for multipart uploads (default 64Mi)
--filelu-description string Description of the remote
--filelu-encoding Encoding The encoding for the backend (default Slash,LtGt,DoubleQuote,SingleQuote,BackQuote,Dollar,Colon,Question,Asterisk,Pipe,Hash,Percent,BackSlash,CrLf,Del,Ctl,LeftSpace,LeftPeriod,LeftTilde,LeftCrLfHtVt,RightSpace,RightPeriod,RightCrLfHtVt,InvalidUtf8,Dot,SquareBracket,Semicolon,Exclamation)
--filelu-key string Your FileLu Rclone key from My Account
--filelu-upload-cutoff SizeSuffix Cutoff for switching to chunked upload. Any files larger than this will be uploaded in chunks of chunk_size (default 500Mi)
--filen-api-key string API Key for your Filen account (obscured)
--filen-auth-version string Authentication Version (internal use only)
--filen-base-folder-uuid string UUID of Account Root Directory (internal use only)
@@ -1063,7 +1065,7 @@ rclone [flags]
--use-json-log Use json log format
--use-mmap Use mmap allocator (see docs)
--use-server-modtime Use server modified time instead of object metadata
--user-agent string Set the user-agent to a specified string (default "rclone/v1.73.0")
--user-agent string Set the user-agent to a specified string (default "rclone/v1.73.5")
-v, --verbose count Print lots more stuff (repeat for more)
-V, --version Print the version number
--webdav-auth-redirect Preserve authentication on redirect
+20
View File
@@ -107,6 +107,26 @@ Flags for anything which can copy a file
-u, --update Skip files that are newer on the destination
```
### Sync Options
Flags used for sync commands
```text
--backup-dir string Make backups into hierarchy based in DIR
--delete-after When synchronizing, delete files on destination after transferring (default)
--delete-before When synchronizing, delete files on destination before transferring
--delete-during When synchronizing, delete files during transfer
--fix-case Force rename of case insensitive dest to match source
--ignore-errors Delete even if there are I/O errors
--list-cutoff int To save memory, sort directory listings on disk above this threshold (default 1000000)
--max-delete int When synchronizing, limit the number of deletes (default -1)
--max-delete-size SizeSuffix When synchronizing, limit the total size of deletes (default off)
--suffix string Suffix to add to changed files
--suffix-keep-extension Preserve the extension when using --suffix
--track-renames When synchronizing, track file renames and do a server-side move if possible
--track-renames-strategy string Strategies to use when synchronizing using track-renames hash|modtime|leaf (default "hash")
```
### Important Options
Important flags useful for most commands
+2 -2
View File
@@ -231,12 +231,12 @@ rclone convmv "stories/The Quick Brown Fox!.txt" --name-transform "all,command=e
```console
rclone convmv "stories/The Quick Brown Fox!" --name-transform "date=-{YYYYMMDD}"
// Output: stories/The Quick Brown Fox!-20260130
// Output: stories/The Quick Brown Fox!-20260419
```
```console
rclone convmv "stories/The Quick Brown Fox!" --name-transform "date=-{macfriendlytime}"
// Output: stories/The Quick Brown Fox!-2026-01-30 0825PM
// Output: stories/The Quick Brown Fox!-2026-04-19 1137AM
```
```console
+9
View File
@@ -39,6 +39,15 @@ Note that `--stdout` and `--print-filename` are incompatible with `--urls`.
This will do `--transfers` copies in parallel. Note that if `--auto-filename`
is desired for all URLs then a file with only URLs and no filename can be used.
Each FILENAME in the CSV file can start with a relative path which will be appended
to the destination path provided at the command line. For example, running the command
shown above with the following CSV file will write two files to the destination:
`remote:dir/local/path/bar.json` and `remote:dir/another/local/directory/qux.json`
```csv
https://example.org/foo/bar.json,local/path/bar.json
https://example.org/qux/baz.json,another/local/directory/qux.json
```
## Troubleshooting
If you can't get `rclone copyurl` to work then here are some things you can try:
+17 -15
View File
@@ -13,7 +13,8 @@ Mount the remote as file system on a mountpoint.
Rclone mount allows Linux, FreeBSD, macOS and Windows to
mount any of Rclone's cloud storage systems as a file system with FUSE.
First set up your remote using `rclone config`. Check it works with `rclone ls` etc.
First set up your remote using `rclone config`. Check it works with `rclone ls`
etc.
On Linux and macOS, you can run mount in either foreground or background (aka
daemon) mode. Mount runs in foreground mode by default. Use the `--daemon` flag
@@ -41,8 +42,8 @@ The following examples will mount to an automatically assigned drive,
to specific drive letter `X:`, to path `C:\path\parent\mount`
(where parent directory or drive must exist, and mount must **not** exist,
and is not supported when [mounting as a network drive](#mounting-modes-on-windows)),
and the last example will mount as network share `\\cloud\remote` and map it to an
automatically assigned drive:
and the last example will mount as network share `\\cloud\remote` and map it to
an automatically assigned drive:
```console
rclone mount remote:path/to/files *
@@ -148,8 +149,8 @@ rclone mount remote:path/to/files X: --volname \\server\share
You may also specify the network share UNC path as the mountpoint itself. Then rclone
will automatically assign a drive letter, same as with `*` and use that as
mountpoint, and instead use the UNC path specified as the volume name, as if it were
specified with the `--volname` option. This will also implicitly set
mountpoint, and instead use the UNC path specified as the volume name, as if it
were specified with the `--volname` option. This will also implicitly set
the `--network-mode` option. This means the following two examples have same result:
```console
@@ -280,7 +281,7 @@ does not suffer from the same limitations.
Mounting on macOS can be done either via [built-in NFS server](/commands/rclone_serve_nfs/),
[macFUSE](https://osxfuse.github.io/) (also known as osxfuse) or
[FUSE-T](https://www.fuse-t.org/).macFUSE is a traditional FUSE driver utilizing
[FUSE-T](https://www.fuse-t.org/). macFUSE is a traditional FUSE driver utilizing
a macOS kernel extension (kext). FUSE-T is an alternative FUSE system which
"mounts" via an NFSv4 local server.
@@ -323,29 +324,30 @@ current as of FUSE-T version 1.0.14.
As per the [FUSE-T wiki](https://github.com/macos-fuse-t/fuse-t/wiki#caveats):
> File access and modification times cannot be set separately as it seems to be an
> issue with the NFS client which always modifies both. Can be reproduced with
> 'touch -m' and 'touch -a' commands
> File access and modification times cannot be set separately as it seems to be
> an issue with the NFS client which always modifies both. Can be reproduced
> with `touch -m` and `touch -a` commands
This means that viewing files with various tools, notably macOS Finder, will cause
rlcone to update the modification time of the file. This may make rclone upload a
full new copy of the file.
This means that viewing files with various tools, notably macOS Finder, will
cause rlcone to update the modification time of the file. This may make rclone
upload a full new copy of the file.
#### Read Only mounts
When mounting with `--read-only`, attempts to write to files will fail *silently*
as opposed to with a clear warning as in macFUSE.
# Mounting on Linux
## Mounting on Linux
On newer versions of Ubuntu, you may encounter the following error when running
`rclone mount`:
> NOTICE: mount helper error: fusermount3: mount failed: Permission denied
> CRITICAL: Fatal error: failed to mount FUSE fs: fusermount: exit status 1
This may be due to newer [Apparmor](https://wiki.ubuntu.com/AppArmor) restrictions,
which can be disabled with `sudo aa-disable /usr/bin/fusermount3` (you may need to
`sudo apt install apparmor-utils` beforehand).
which can be disabled with `sudo aa-disable /usr/bin/fusermount3` (you may need
to `sudo apt install apparmor-utils` beforehand).
## Limitations
+17 -15
View File
@@ -14,7 +14,8 @@ Mount the remote as file system on a mountpoint.
Rclone nfsmount allows Linux, FreeBSD, macOS and Windows to
mount any of Rclone's cloud storage systems as a file system with FUSE.
First set up your remote using `rclone config`. Check it works with `rclone ls` etc.
First set up your remote using `rclone config`. Check it works with `rclone ls`
etc.
On Linux and macOS, you can run mount in either foreground or background (aka
daemon) mode. Mount runs in foreground mode by default. Use the `--daemon` flag
@@ -42,8 +43,8 @@ The following examples will mount to an automatically assigned drive,
to specific drive letter `X:`, to path `C:\path\parent\mount`
(where parent directory or drive must exist, and mount must **not** exist,
and is not supported when [mounting as a network drive](#mounting-modes-on-windows)),
and the last example will mount as network share `\\cloud\remote` and map it to an
automatically assigned drive:
and the last example will mount as network share `\\cloud\remote` and map it to
an automatically assigned drive:
```console
rclone nfsmount remote:path/to/files *
@@ -149,8 +150,8 @@ rclone nfsmount remote:path/to/files X: --volname \\server\share
You may also specify the network share UNC path as the mountpoint itself. Then rclone
will automatically assign a drive letter, same as with `*` and use that as
mountpoint, and instead use the UNC path specified as the volume name, as if it were
specified with the `--volname` option. This will also implicitly set
mountpoint, and instead use the UNC path specified as the volume name, as if it
were specified with the `--volname` option. This will also implicitly set
the `--network-mode` option. This means the following two examples have same result:
```console
@@ -281,7 +282,7 @@ does not suffer from the same limitations.
Mounting on macOS can be done either via [built-in NFS server](/commands/rclone_serve_nfs/),
[macFUSE](https://osxfuse.github.io/) (also known as osxfuse) or
[FUSE-T](https://www.fuse-t.org/).macFUSE is a traditional FUSE driver utilizing
[FUSE-T](https://www.fuse-t.org/). macFUSE is a traditional FUSE driver utilizing
a macOS kernel extension (kext). FUSE-T is an alternative FUSE system which
"mounts" via an NFSv4 local server.
@@ -324,29 +325,30 @@ current as of FUSE-T version 1.0.14.
As per the [FUSE-T wiki](https://github.com/macos-fuse-t/fuse-t/wiki#caveats):
> File access and modification times cannot be set separately as it seems to be an
> issue with the NFS client which always modifies both. Can be reproduced with
> 'touch -m' and 'touch -a' commands
> File access and modification times cannot be set separately as it seems to be
> an issue with the NFS client which always modifies both. Can be reproduced
> with `touch -m` and `touch -a` commands
This means that viewing files with various tools, notably macOS Finder, will cause
rlcone to update the modification time of the file. This may make rclone upload a
full new copy of the file.
This means that viewing files with various tools, notably macOS Finder, will
cause rlcone to update the modification time of the file. This may make rclone
upload a full new copy of the file.
#### Read Only mounts
When mounting with `--read-only`, attempts to write to files will fail *silently*
as opposed to with a clear warning as in macFUSE.
# Mounting on Linux
## Mounting on Linux
On newer versions of Ubuntu, you may encounter the following error when running
`rclone mount`:
> NOTICE: mount helper error: fusermount3: mount failed: Permission denied
> CRITICAL: Fatal error: failed to mount FUSE fs: fusermount: exit status 1
This may be due to newer [Apparmor](https://wiki.ubuntu.com/AppArmor) restrictions,
which can be disabled with `sudo aa-disable /usr/bin/fusermount3` (you may need to
`sudo apt install apparmor-utils` beforehand).
which can be disabled with `sudo aa-disable /usr/bin/fusermount3` (you may need
to `sudo apt install apparmor-utils` beforehand).
## Limitations
+5 -1
View File
@@ -2059,7 +2059,7 @@ This is the default.
`CAUTIOUS` will try to prevent rclone from reaching the limit. Only applicable
for `--max-transfer`.
## -M, --metadata
### -M, --metadata
Setting this flag enables rclone to copy the metadata from the source
to the destination. For local backends this is ownership, permissions,
@@ -2961,6 +2961,10 @@ knowing the local file is newer than the time it was last uploaded to the
remote is sufficient. In those cases, this flag can speed up the process and
reduce the number of API calls necessary.
This flag is only supported on certain backends and will be silently
ignored on unsupported backends. Supported backends include
`azureblob`, `oracleobjectstorage`, `s3`, `swift`.
Using this flag on a sync operation without also using `--update` would cause
all files modified at any time other than the last upload time to be uploaded
again, which is probably not what you want.
+1
View File
@@ -143,6 +143,7 @@ The latest `rclone` version working for:
| Windows Server 2012 | v1.63.1 |
| Windows XP | v1.42 |
| Windows Vista | v1.42 |
| macOS 10.15 (Catalina) | v1.70.3 |
| macOS 10.14 (Mojave) | v1.63.1 |
| macOS 10.13 (High Sierra) | v1.63.1 |
| macOS 10.12 (Sierra) | v1.56.0 |
+22
View File
@@ -219,6 +219,28 @@ Properties:
Here are the Advanced options specific to filelu (FileLu Cloud Storage).
#### --filelu-upload-cutoff
Cutoff for switching to chunked upload. Any files larger than this will be uploaded in chunks of chunk_size.
Properties:
- Config: upload_cutoff
- Env Var: RCLONE_FILELU_UPLOAD_CUTOFF
- Type: SizeSuffix
- Default: 500Mi
#### --filelu-chunk-size
Chunk size to use for uploading. Used for multipart uploads.
Properties:
- Config: chunk_size
- Env Var: RCLONE_FILELU_CHUNK_SIZE
- Type: SizeSuffix
- Default: 64Mi
#### --filelu-encoding
The encoding for the backend.
+2
View File
@@ -10,6 +10,8 @@ The initial setup for Filen requires that you get an API key for your account,
currently this is only possible using the [Filen CLI](https://github.com/FilenCloudDienste/filen-cli).
This means you must first download the CLI, login, and then run the `export-api-key` command.
**Note:** If you change your Filen account password, you will need to update your rclone configuration with the new password and a re-exported API key (via `export-api-key`).
Here is an example of how to make a remote called `FilenRemote`. First run:
rclone config
+3 -1
View File
@@ -121,7 +121,7 @@ Flags for general networking and HTTP stuff.
--tpslimit float Limit HTTP transactions per second to this
--tpslimit-burst int Max burst of transactions for --tpslimit (default 1)
--use-cookies Enable session cookiejar
--user-agent string Set the user-agent to a specified string (default "rclone/v1.73.0")
--user-agent string Set the user-agent to a specified string (default "rclone/v1.73.5")
```
@@ -605,9 +605,11 @@ Backend-only flags (these can be set in the config file also).
--filefabric-token-expiry string Token expiry time
--filefabric-url string URL of the Enterprise File Fabric to connect to
--filefabric-version string Version read from the file fabric
--filelu-chunk-size SizeSuffix Chunk size to use for uploading. Used for multipart uploads (default 64Mi)
--filelu-description string Description of the remote
--filelu-encoding Encoding The encoding for the backend (default Slash,LtGt,DoubleQuote,SingleQuote,BackQuote,Dollar,Colon,Question,Asterisk,Pipe,Hash,Percent,BackSlash,CrLf,Del,Ctl,LeftSpace,LeftPeriod,LeftTilde,LeftCrLfHtVt,RightSpace,RightPeriod,RightCrLfHtVt,InvalidUtf8,Dot,SquareBracket,Semicolon,Exclamation)
--filelu-key string Your FileLu Rclone key from My Account
--filelu-upload-cutoff SizeSuffix Cutoff for switching to chunked upload. Any files larger than this will be uploaded in chunks of chunk_size (default 500Mi)
--filen-api-key string API Key for your Filen account (obscured)
--filen-auth-version string Authentication Version (internal use only)
--filen-base-folder-uuid string UUID of Account Root Directory (internal use only)
+1 -1
View File
@@ -12,7 +12,7 @@ its own datacenters in Norway.
In addition to the official service at [jottacloud.com](https://www.jottacloud.com/),
it also provides white-label solutions to different companies. The following
are currently supported by this backend, using a different authentication setup
as described [below](#whitelabel-authentication):
as described [below](#traditional):
- Elkjøp (with subsidiaries):
- Elkjøp Cloud (cloud.elkjop.no)
+1 -1
View File
@@ -62,7 +62,7 @@ handling file names.
| / | 0x2F | / |
When running on Windows the following characters are replaced. This
list is based on the [Windows file naming conventions](https://docs.microsoft.com/de-de/windows/desktop/FileIO/naming-a-file#naming-conventions).
list is based on the [Windows file naming conventions](https://docs.microsoft.com/windows/desktop/FileIO/naming-a-file#naming-conventions).
| Character | Value | Replacement |
| --------- |:-----:|:-----------:|
+4
View File
@@ -1659,6 +1659,8 @@ This command does not have a command line equivalent so use this instead:
rclone rc --loopback operations/fsinfo fs=remote:
**Authentication is required for this call.**
### operations/hashsum: Produces a hashsum file for all the objects in the path. {#operations-hashsum}
Produces a hash file for all the objects in the path using the hash
@@ -1980,6 +1982,8 @@ And this sets NOTICE level logs (normal without -v)
rclone rc options/set --json '{"main": {"LogLevel": "NOTICE"}}'
**Authentication is required for this call.**
### pluginsctl/addPlugin: Add a plugin using url {#pluginsctl-addPlugin}
Used for adding a plugin to the webgui.
+30 -2
View File
@@ -670,6 +670,20 @@ work with the SDK properly:
| . | . |
| .. | .. |
#### Important note about double slashes (`//`)
Object keys containing consecutive forward slashes (`//`) are **not supported** by rclone.
When rclone encounters an object key with `//` (e.g., `a//b`), it will normalize the path to use a single slash (e.g., `a/b`). This normalization can cause "object not found" errors when trying to access the original object, as rclone will look for the normalized path instead of the actual object key.
**Example:**
- Original S3 object key: `folder//file.txt`
- rclone interprets it as: `folder/file.txt`
- Result: "object not found" error when trying to access `folder//file.txt`
**Workaround:**
Avoid using consecutive forward slashes (`//`) in S3 object keys when using rclone. If you have existing objects with `//` in their keys, you will need to rename them to use single slashes or access them through other means.
### Multipart uploads
rclone supports multipart uploads with S3 which means that it can
@@ -1690,6 +1704,9 @@ Properties:
- "s3.cubbit.eu"
- Cubbit DS3 Object Storage endpoint
- Provider: Cubbit
- "s3.{tenant_name}.cubbit.eu"
- Multi-tenant endpoint - replace {tenant_name} with your actual tenant name. Do not select this directly
- Provider: Cubbit
- "syd1.digitaloceanspaces.com"
- DigitalOcean Spaces Sydney 1
- Provider: DigitalOcean
@@ -5086,7 +5103,9 @@ can follow this [guide](https://docs.cubbit.io/getting-started/quickstart#api-ke
to retrieve these keys. They will be needed when prompted by `rclone config`.
Default region will correspond to `eu-west-1` and the endpoint has to be specified
as `s3.cubbit.eu`.
as `s3.cubbit.eu`. If you set a custom tenant endpoint, you must use
`s3.{tenant_name}.cubbit.eu`, because the generic `s3.cubbit.eu` endpoint will not
work in this case.
Going through the whole process of creating a new remote by running `rclone config`,
each prompt should be answered as shown below:
@@ -5099,7 +5118,7 @@ env_auth> false
access_key_id> YOUR_ACCESS_KEY
secret_access_key> YOUR_SECRET_KEY
region> eu-west-1 (or leave empty)
endpoint> s3.cubbit.eu
endpoint> s3.cubbit.eu (or s3.{tenant_name}.cubbit.eu)
acl>
```
@@ -8986,6 +9005,15 @@ To configure access to Tencent COS, follow the steps below:
cos s3
```
#### Tencent COS Global Acceleration Endpoint
When using the Global Acceleration Endpoint (`cos.accelerate.myqcloud.com`),
rclone automatically sets `no_check_bucket = true` because this acceleration
endpoint does not support the `CreateBucket` call which is used for ensuring
a bucket's existence by rclone. Global Acceleration is a per-bucket feature,
so you should first create the bucket in one physical region, then enable it
in the Tencent Cloud console.
### Wasabi
[Wasabi](https://wasabi.com) is a cloud-based object storage service for a
+3 -1
View File
@@ -16,16 +16,18 @@ Thank you to our sponsors:
{{< sponsor src="/img/logos/rabata.svg" width="300" height="200" title="Visit our sponsor Rabata.io" link="https://rabata.io/?utm_source=banner&utm_medium=rclone&utm_content=general">}}
{{< sponsor src="/img/logos/idrive_e2.svg" width="300" height="200" title="Visit our sponsor IDrive e2" link="https://www.idrive.com/e2/?refer=rclone">}}
{{< sponsor src="/img/logos/filescom-enterprise-grade-workflows.png" width="300" height="200" title="Start Your Free Trial Today" link="https://files.com/?utm_source=rclone&utm_medium=referral&utm_campaign=banner&utm_term=rclone">}}
{{< sponsor src="/img/logos/internxt.jpg" width="300" height="200" title="Visit rclone's sponsor Internxt" link="https://internxt.com/specialoffer/rclone">}}
{{< sponsor src="/img/logos/mega-s4.svg" width="300" height="200" title="MEGA S4: New S3 compatible object storage. High scale. Low cost. Free egress." link="https://mega.io/objectstorage?utm_source=rclone&utm_medium=referral&utm_campaign=rclone-mega-s4&mct=rclonepromo">}}
{{< sponsor src="/img/logos/sia.svg" width="200" height="200" title="Visit our sponsor sia" link="https://sia.tech">}}
{{< sponsor src="/img/logos/route4me.svg" width="400" height="200" title="Visit our sponsor Route4Me" link="https://route4me.com/">}}
{{< sponsor src="/img/logos/rcloneview-banner.svg" width="300" height="200" title="Visit our sponsor RcloneView" link="https://rcloneview.com/">}}
{{< sponsor src="/img/logos/rcloneview.svg" width="300" height="200" title="Visit our sponsor RcloneView" link="https://rcloneview.com/">}}
{{< sponsor src="/img/logos/rcloneui.svg" width="300" height="200" title="Visit our sponsor RcloneUI" link="https://github.com/rclone-ui/rclone-ui">}}
{{< sponsor src="/img/logos/shade.svg" width="300" height="200" title="Visit our sponsor Shade" link="https://shade.inc">}}
{{< sponsor src="/img/logos/filelu-rclone.svg" width="300" height="200" title="Visit our sponsor FileLu" link="https://filelu.com/">}}
{{< sponsor src="/img/logos/torbox.png" width="200" height="200" title="Visit our sponsor TORBOX" link="https://www.torbox.app/">}}
{{< sponsor src="/img/logos/spectra-logic.svg" width="300" height="200" title="Visit our sponsor Spectra Logic" link="https://spectralogic.com/">}}
{{< sponsor src="/img/logos/servercore.svg" width="300" height="200" title="Visit our sponsor servercore" link="https://servercore.com/services/object-storage/?utm_source=rclone.org&utm_medium=referral&utm_campaign=cloud-s3_rclone_231025_paid">}}
{{< sponsor src="/img/logos/exchangerate-api.png" width="300" height="200" title="Visit our sponsor ExchangeRate-API" link="https://www.exchangerate-api.com/">}}
<!-- markdownlint-restore -->
+1 -1
View File
@@ -36,7 +36,7 @@
"beta" "This feature is currently in beta must be used with care."
}}
{{ if .Params.versionIntroduced }}<span class="badge badge-pill badge-secondary float-right" style="margin-top: 30px; font-size: 100%" title="This feature needs Rclone {{ .Params.versionIntroduced }} or later.">{{ .Params.versionIntroduced }}</span>{{ end }}
{{ if .Params.versionIntroduced }}<span class="badge badge-pill badge-secondary float-right" style="margin-top: 30px; font-size: 100%" title="This feature needs Rclone {{ .Params.versionIntroduced }} or later.">added in {{ .Params.versionIntroduced }}</span>{{ end }}
{{ with .Params.status | lower }}
{{ $statusCode := . }}
+1 -14
View File
@@ -12,7 +12,7 @@
<div class="card">
<div class="card-header">Platinum Sponso⁠r</div>
<div class="card-body">
<a href="https://rabata.io/?utm_source=banner&utm_medium=rclone&utm_content=general" target="_blank" rel="noopener" title="Visit rclone's sponsor Rabata.io"><img src="/img/logos/rabata.svg"></a><br />
<a href="https://internxt.com/specialoffer/rclone" target="_blank" rel="noopener" title="Visit rclone's sponsor Internxt"><img style="max-width: 100%; height: auto;" src="/img/logos/internxt.jpg"></a><br />
</div>
</div>
@@ -30,13 +30,6 @@
</div>
</div>
<div class="card">
<div class="card-header">Gold Sponso⁠r</div>
<div class="card-body">
<a href="https://internxt.com/?utm_source=rclone" target="_blank" rel="noopener" title="Visit rclone's sponsor Internxt"><img style="max-width: 100%; height: auto;" src="/img/logos/internxt.jpg"></a><br />
</div>
</div>
{{if .IsHome}}
<div class="card">
<div class="card-header">Silver Sponso⁠r</div>
@@ -44,12 +37,6 @@
<a href="https://rcloneview.com/?utm_source=rclone" target="_blank" rel="noopener" title="Visit rclone's sponsor RcloneView"><img src="/img/logos/rcloneview.svg"></a><br />
</div>
</div>
<div class="card">
<div class="card-header">Silver Sponso⁠r</div>
<div class="card-body">
<a href="https://rcloneui.com" target="_blank" rel="noopener" title="Visit rclone's sponsor rclone UI"><img src="/img/logos/rcloneui.svg"></a><br />
</div>
</div>
<div class="card">
<div class="card-header">Silver Sponso⁠r</div>
<div class="card-body">
+1 -1
View File
@@ -1 +1 @@
v1.73.0
v1.73.5
+6
View File
@@ -385,12 +385,14 @@ func (sg *statsGroups) sum(ctx context.Context) *StatsInfo {
sum.checkQueueSize += stats.checkQueueSize
sum.transfers += stats.transfers
sum.transferring.merge(stats.transferring)
sum.transferQueue += stats.transferQueue
sum.transferQueueSize += stats.transferQueueSize
sum.listed += stats.listed
sum.renames += stats.renames
sum.renameQueue += stats.renameQueue
sum.renameQueueSize += stats.renameQueueSize
sum.deletes += stats.deletes
sum.deletesSize += stats.deletesSize
sum.deletedDirs += stats.deletedDirs
sum.inProgress.merge(stats.inProgress)
sum.startedTransfers = append(sum.startedTransfers, stats.startedTransfers...)
@@ -399,6 +401,10 @@ func (sg *statsGroups) sum(ctx context.Context) *StatsInfo {
stats.average.mu.Lock()
sum.average.speed += stats.average.speed
stats.average.mu.Unlock()
sum.serverSideCopies += stats.serverSideCopies
sum.serverSideCopyBytes += stats.serverSideCopyBytes
sum.serverSideMoves += stats.serverSideMoves
sum.serverSideMoveBytes += stats.serverSideMoveBytes
}
stats.mu.RUnlock()
}
-3
View File
@@ -198,21 +198,18 @@ func NewFilter(opt *Options) (f *Filter, err error) {
// Filter flags
if f.Opt.MinAge.IsSet() {
f.ModTimeTo = time.Now().Add(-time.Duration(f.Opt.MinAge))
fs.Debugf(nil, "--min-age %v to %v", f.Opt.MinAge, f.ModTimeTo)
}
if f.Opt.MaxAge.IsSet() {
f.ModTimeFrom = time.Now().Add(-time.Duration(f.Opt.MaxAge))
if !f.ModTimeTo.IsZero() && f.ModTimeTo.Before(f.ModTimeFrom) {
return nil, fmt.Errorf("filter: --min-age %q can't be larger than --max-age %q", opt.MinAge, opt.MaxAge)
}
fs.Debugf(nil, "--max-age %v to %v", f.Opt.MaxAge, f.ModTimeFrom)
}
if f.Opt.HashFilter != "" {
f.hashFilterK, f.hashFilterN, err = parseHashFilter(f.Opt.HashFilter)
if err != nil {
return nil, err
}
fs.Debugf(nil, "Using --hash-filter %d/%d", f.hashFilterK, f.hashFilterN)
}
err = parseRules(&f.Opt.RulesOpt, f.Add, f.Clear)
+13
View File
@@ -50,6 +50,7 @@ type Sorter struct {
errChan <-chan error // for getting errors from the ext sort
sorter *extsort.StringSorter // external string sort
errs *errcount.ErrCount // accumulate errors
tempDir string // directory for temp files (empty for default)
}
// KeyFn turns an entry into a sort key
@@ -144,6 +145,7 @@ func (ls *Sorter) startExtSort() (err error) {
ChanBuffSize: 1024, // small effect
SortedChanBuffSize: 1024, // makes a lot of difference
ChunkSize: 32 * 1024, // tuned for 50 char records (UUID sized)
TempFilesDir: ls.tempDir,
// Defaults
// ChunkSize: int(1e6), // amount of records to store in each chunk which will be written to disk
// NumWorkers: 2, // maximum number of workers to use for parallel sorting
@@ -152,6 +154,17 @@ func (ls *Sorter) startExtSort() (err error) {
// TempFilesDir: "", // empty for use OS default ex: /tmp
}
ls.sorter, ls.outputChan, ls.errChan = extsort.Strings(ls.inputChan, &opt)
if ls.sorter == nil {
// extsort.Strings returns nil when it can't create temp
// files (e.g. due to permissions or apparmor restrictions).
// The error will be on errChan.
select {
case err = <-ls.errChan:
default:
err = errors.New("failed to initialise on-disk sort")
}
return fmt.Errorf("sorter: %w", err)
}
go ls.sorter.Sort(ls.ctx)
// Show we are extsorting now
+48
View File
@@ -4,6 +4,9 @@ import (
"cmp"
"context"
"fmt"
"os"
"path/filepath"
"runtime"
"slices"
"strings"
"testing"
@@ -231,6 +234,51 @@ func TestSorterExt(t *testing.T) {
}
}
// Test that startExtSort returns an error instead of panicking when
// temp file creation fails (e.g. due to permissions or apparmor).
// See: https://github.com/rclone/rclone/issues/9244
func TestSorterExtTempFileError(t *testing.T) {
ctx := context.Background()
ctx, ci := fs.AddConfig(ctx)
ci.ListCutoff = 1 // force ext sort on first Add
callback := func(entries fs.DirEntries) error {
return nil
}
ls, err := NewSorter(ctx, nil, callback, nil)
require.NoError(t, err)
defer ls.CleanUp()
// Override tempDir to a path where os.MkdirAll will fail,
// simulating apparmor or permission denial. This makes
// extsort.Strings return a nil sorter.
if runtime.GOOS == "windows" {
// On Windows, create a regular file and use a child path.
// os.MkdirAll fails because an intermediate component is a file.
// Windows stat returns ERROR_PATH_NOT_FOUND (treated as
// IsNotExist) so the extsort library won't fall back to a
// default directory.
blocker := filepath.Join(t.TempDir(), "notadir")
require.NoError(t, os.WriteFile(blocker, []byte("x"), 0644))
ls.tempDir = filepath.Join(blocker, "sub")
} else {
// On Unix, create a read-only parent directory. stat on the
// child returns ENOENT so the extsort library won't fall
// back, but os.MkdirAll fails with EACCES.
parent := filepath.Join(t.TempDir(), "roparent")
require.NoError(t, os.Mkdir(parent, 0o755))
require.NoError(t, os.Chmod(parent, 0o555))
t.Cleanup(func() { _ = os.Chmod(parent, 0o755) })
ls.tempDir = filepath.Join(parent, "child")
}
// Add enough entries to trigger ext sort. Before the fix this
// would panic with nil pointer dereference.
err = ls.Add(fs.DirEntries{mockobject.Object("a"), mockobject.Object("b")})
require.Error(t, err)
assert.Contains(t, err.Error(), "sorter:")
}
// benchFs implements enough of the fs.Fs interface for Sorter
type benchFs struct{}
+12 -3
View File
@@ -16,6 +16,7 @@ import (
"github.com/rclone/rclone/fs/list"
"github.com/rclone/rclone/fs/walk"
"github.com/rclone/rclone/lib/transform"
"golang.org/x/sync/semaphore"
"golang.org/x/text/unicode/norm"
)
@@ -41,9 +42,10 @@ type March struct {
NoCheckDest bool // transfer all objects regardless without checking dst
NoUnicodeNormalization bool // don't normalize unicode characters in filenames
// internal state
srcListDir listDirFn // function to call to list a directory in the src
dstListDir listDirFn // function to call to list a directory in the dst
transforms []matchTransformFn
srcListDir listDirFn // function to call to list a directory in the src
dstListDir listDirFn // function to call to list a directory in the dst
transforms []matchTransformFn
newObjectSem *semaphore.Weighted // make sure we don't call too many NewObjects simultaneously
}
// Marcher is called on each match
@@ -78,6 +80,8 @@ func (m *March) init(ctx context.Context) {
if m.Fdst.Features().CaseInsensitive || ci.IgnoreCaseSync {
m.transforms = append(m.transforms, strings.ToLower)
}
// Only allow ci.Checkers simultaneous calls to NewObject
m.newObjectSem = semaphore.NewWeighted(int64(ci.Checkers))
}
// srcOrDstKey turns a directory entry into a sort key using the defined transforms.
@@ -461,7 +465,12 @@ func (m *March) processJob(job listDirJob) ([]listDirJob, error) {
continue
}
leaf := path.Base(t.src.Remote())
if err := m.newObjectSem.Acquire(m.Ctx, 1); err != nil {
t.dstMatch <- nil
continue
}
dst, err := m.Fdst.NewObject(m.Ctx, path.Join(job.dstRemote, leaf))
m.newObjectSem.Release(1)
if err != nil {
dst = nil
}
+4 -3
View File
@@ -430,9 +430,10 @@ func rcPublicLink(ctx context.Context, in rc.Params) (out rc.Params, err error)
func init() {
rc.Add(rc.Call{
Path: "operations/fsinfo",
Fn: rcFsInfo,
Title: "Return information about the remote",
Path: "operations/fsinfo",
AuthRequired: true,
Fn: rcFsInfo,
Title: "Return information about the remote",
Help: `This takes the following parameters:
- fs - a remote name string e.g. "drive:"
+4 -3
View File
@@ -146,9 +146,10 @@ func rcOptionsLocal(ctx context.Context, in Params) (out Params, err error) {
func init() {
Add(Call{
Path: "options/set",
Fn: rcOptionsSet,
Title: "Set an option",
Path: "options/set",
AuthRequired: true,
Fn: rcOptionsSet,
Title: "Set an option",
Help: `Parameters:
- option block name containing an object with
+3 -1
View File
@@ -53,6 +53,7 @@ type Server struct {
files http.Handler
pluginsHandler http.Handler
opt *rc.Options
noAuth bool // snapshot of opt.NoAuth at startup to prevent runtime mutation
}
func newServer(ctx context.Context, opt *rc.Options, mux *http.ServeMux) (*Server, error) {
@@ -104,6 +105,7 @@ func newServer(ctx context.Context, opt *rc.Options, mux *http.ServeMux) (*Serve
opt: opt,
files: fileHandler,
pluginsHandler: pluginsHandler,
noAuth: opt.NoAuth,
}
var err error
@@ -263,7 +265,7 @@ func (s *Server) handlePost(w http.ResponseWriter, r *http.Request, path string)
}
// Check to see if it requires authorisation
if !s.opt.NoAuth && call.AuthRequired && !s.server.UsingAuth() {
if !s.noAuth && call.AuthRequired && !s.server.UsingAuth() {
writeError(path, in, w, fmt.Errorf("authentication must be set up on the rc server to use %q or the --rc-no-auth flag must be in use", path), http.StatusForbidden)
return
}
+1 -1
View File
@@ -1,4 +1,4 @@
package fs
// VersionTag of rclone
var VersionTag = "v1.73.0"
var VersionTag = "v1.73.5"
+40 -39
View File
@@ -1,6 +1,6 @@
module github.com/rclone/rclone
go 1.24.4
go 1.25.0
godebug x509negativeserial=1
@@ -11,7 +11,7 @@ require (
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.3
github.com/Azure/azure-sdk-for-go/sdk/storage/azfile v1.5.3
github.com/Azure/go-ntlmssp v0.0.2-0.20251110135918-10b7b7e7cd26
github.com/FilenCloudDienste/filen-sdk-go v0.0.35
github.com/FilenCloudDienste/filen-sdk-go v0.0.38
github.com/Files-com/files-sdk-go/v3 v3.2.264
github.com/Max-Sum/base32768 v0.0.0-20230304063302-18e6ce5945fd
github.com/a1ex3/zstd-seekable-format-go/pkg v0.10.0
@@ -21,13 +21,13 @@ require (
github.com/anacrolix/dms v1.7.2
github.com/anacrolix/log v0.17.0
github.com/atotto/clipboard v0.1.4
github.com/aws/aws-sdk-go-v2 v1.39.6
github.com/aws/aws-sdk-go-v2/config v1.31.17
github.com/aws/aws-sdk-go-v2/credentials v1.18.21
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.20.4
github.com/aws/aws-sdk-go-v2/service/s3 v1.90.0
github.com/aws/aws-sdk-go-v2/service/sts v1.39.1
github.com/aws/smithy-go v1.23.2
github.com/aws/aws-sdk-go-v2 v1.41.5
github.com/aws/aws-sdk-go-v2/config v1.32.8
github.com/aws/aws-sdk-go-v2/credentials v1.19.8
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.22.1
github.com/aws/aws-sdk-go-v2/service/s3 v1.97.3
github.com/aws/aws-sdk-go-v2/service/sts v1.41.6
github.com/aws/smithy-go v1.24.2
github.com/buengese/sgzip v0.1.1
github.com/cloudinary/cloudinary-go/v2 v2.13.0
github.com/cloudsoda/go-smb2 v0.0.0-20250228001242-d4c70e6251cc
@@ -39,13 +39,13 @@ require (
github.com/dropbox/dropbox-sdk-go-unofficial/v6 v6.0.5
github.com/gabriel-vasile/mimetype v1.4.11
github.com/gdamore/tcell/v2 v2.9.0
github.com/go-chi/chi/v5 v5.2.3
github.com/go-chi/chi/v5 v5.2.5
github.com/go-darwin/apfs v0.0.0-20211011131704-f84b94dbf348
github.com/go-git/go-billy/v5 v5.6.2
github.com/golang-jwt/jwt/v5 v5.3.0
github.com/google/uuid v1.6.0
github.com/hanwen/go-fuse/v2 v2.9.0
github.com/internxt/rclone-adapter v0.0.0-20260130171252-c3c6ebb49276
github.com/internxt/rclone-adapter v0.0.0-20260220172730-613f4cc8b8fd
github.com/jcmturner/gokrb5/v8 v8.4.4
github.com/jlaffaye/ftp v0.2.1-0.20240918233326-1b970516f5d3
github.com/josephspurrier/goversioninfo v1.5.0
@@ -92,12 +92,12 @@ require (
github.com/zeebo/xxh3 v1.0.2
go.etcd.io/bbolt v1.4.3
goftp.io/server/v2 v2.0.2
golang.org/x/crypto v0.45.0
golang.org/x/net v0.47.0
golang.org/x/oauth2 v0.33.0
golang.org/x/sync v0.18.0
golang.org/x/sys v0.38.0
golang.org/x/text v0.31.0
golang.org/x/crypto v0.48.0
golang.org/x/net v0.51.0
golang.org/x/oauth2 v0.34.0
golang.org/x/sync v0.20.0
golang.org/x/sys v0.41.0
golang.org/x/text v0.35.0
golang.org/x/time v0.14.0
google.golang.org/api v0.255.0
gopkg.in/natefinch/lumberjack.v2 v2.2.1
@@ -125,18 +125,19 @@ require (
github.com/andybalholm/brotli v1.2.0 // indirect
github.com/andybalholm/cascadia v1.3.3 // indirect
github.com/appscode/go-querystring v0.0.0-20170504095604-0126cfb3f1dc // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.3 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.13 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.13 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.13 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.13 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.3 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.4 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.13 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.13 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.30.1 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.5 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21 // indirect
github.com/aws/aws-sdk-go-v2/service/signin v1.0.5 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.30.9 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.14 // indirect
github.com/bahlo/generic-list-go v0.2.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bodgit/plumbing v1.3.0 // indirect
@@ -145,13 +146,13 @@ require (
github.com/boombuler/barcode v1.1.0 // indirect
github.com/bradenaw/juniper v0.15.3 // indirect
github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8 // indirect
github.com/buger/jsonparser v1.1.1 // indirect
github.com/buger/jsonparser v1.1.2 // indirect
github.com/calebcase/tmpfile v1.0.3 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/chilts/sid v0.0.0-20190607042430-660e94789ec9 // indirect
github.com/clipperhouse/stringish v0.1.1 // indirect
github.com/clipperhouse/uax29/v2 v2.3.0 // indirect
github.com/cloudflare/circl v1.6.1 // indirect
github.com/cloudflare/circl v1.6.3 // indirect
github.com/cloudsoda/sddl v0.0.0-20250224235906-926454e91efc // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
github.com/creasty/defaults v1.8.0 // indirect
@@ -252,17 +253,17 @@ require (
go.mongodb.org/mongo-driver v1.17.6 // indirect
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 // indirect
go.opentelemetry.io/otel v1.38.0 // indirect
go.opentelemetry.io/otel/metric v1.38.0 // indirect
go.opentelemetry.io/otel/trace v1.38.0 // indirect
go.opentelemetry.io/otel v1.39.0 // indirect
go.opentelemetry.io/otel/metric v1.39.0 // indirect
go.opentelemetry.io/otel/trace v1.39.0 // indirect
go.yaml.in/yaml/v2 v2.4.3 // indirect
go4.org v0.0.0-20230225012048-214862532bf5 // indirect
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect
golang.org/x/image v0.32.0 // indirect
golang.org/x/mod v0.29.0 // indirect
golang.org/x/tools v0.38.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20251103181224-f26f9409b101 // indirect
google.golang.org/grpc v1.76.0 // indirect
golang.org/x/image v0.38.0 // indirect
golang.org/x/mod v0.33.0 // indirect
golang.org/x/tools v0.42.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect
google.golang.org/grpc v1.79.3 // indirect
google.golang.org/protobuf v1.36.10 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
moul.io/http2curl/v2 v2.3.0 // indirect
@@ -281,5 +282,5 @@ require (
github.com/pkg/xattr v0.4.12
github.com/pquerna/otp v1.5.0
golang.org/x/mobile v0.0.0-20251021151156-188f512ec823
golang.org/x/term v0.37.0
golang.org/x/term v0.40.0
)
+84 -82
View File
@@ -61,8 +61,8 @@ github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0 h1:XRzhVemXdgv
github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0/go.mod h1:HKpQxkWaGLJ+D/5H8QRpyQXA1eKjxkFlOMwck5+33Jk=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/FilenCloudDienste/filen-sdk-go v0.0.35 h1:geuYpD/1ZXSp1H3kdW7si+KRUIrHHqM1kk8lqoA8Y9M=
github.com/FilenCloudDienste/filen-sdk-go v0.0.35/go.mod h1:0cBhKXQg49XbKZZfk5TCDa3sVLP+xMxZTWL+7KY0XR0=
github.com/FilenCloudDienste/filen-sdk-go v0.0.38 h1:YCyHs3wUXEe2BEWn40vcoyaQ2ruHNmNwkasfo3Th16A=
github.com/FilenCloudDienste/filen-sdk-go v0.0.38/go.mod h1:0cBhKXQg49XbKZZfk5TCDa3sVLP+xMxZTWL+7KY0XR0=
github.com/Files-com/files-sdk-go/v3 v3.2.264 h1:lMHTplAYI9FtmCo/QOcpRxmPA5REVAct1r2riQmDQKw=
github.com/Files-com/files-sdk-go/v3 v3.2.264/go.mod h1:wGqkOzRu/ClJibvDgcfuJNAqI2nLhe8g91tPlDKRCdE=
github.com/IBM/go-sdk-core/v5 v5.18.5 h1:g0JRl3sYXJczB/yuDlrN6x22LJ6jIxhp0Sa4ARNW60c=
@@ -118,44 +118,46 @@ github.com/appscode/go-querystring v0.0.0-20170504095604-0126cfb3f1dc h1:LoL75er
github.com/appscode/go-querystring v0.0.0-20170504095604-0126cfb3f1dc/go.mod h1:w648aMHEgFYS6xb0KVMMtZ2uMeemhiKCuD2vj6gY52A=
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
github.com/aws/aws-sdk-go-v2 v1.39.6 h1:2JrPCVgWJm7bm83BDwY5z8ietmeJUbh3O2ACnn+Xsqk=
github.com/aws/aws-sdk-go-v2 v1.39.6/go.mod h1:c9pm7VwuW0UPxAEYGyTmyurVcNrbF6Rt/wixFqDhcjE=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.3 h1:DHctwEM8P8iTXFxC/QK0MRjwEpWQeM9yzidCRjldUz0=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.3/go.mod h1:xdCzcZEtnSTKVDOmUZs4l/j3pSV6rpo1WXl5ugNsL8Y=
github.com/aws/aws-sdk-go-v2/config v1.31.17 h1:QFl8lL6RgakNK86vusim14P2k8BFSxjvUkcWLDjgz9Y=
github.com/aws/aws-sdk-go-v2/config v1.31.17/go.mod h1:V8P7ILjp/Uef/aX8TjGk6OHZN6IKPM5YW6S78QnRD5c=
github.com/aws/aws-sdk-go-v2/credentials v1.18.21 h1:56HGpsgnmD+2/KpG0ikvvR8+3v3COCwaF4r+oWwOeNA=
github.com/aws/aws-sdk-go-v2/credentials v1.18.21/go.mod h1:3YELwedmQbw7cXNaII2Wywd+YY58AmLPwX4LzARgmmA=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.13 h1:T1brd5dR3/fzNFAQch/iBKeX07/ffu/cLu+q+RuzEWk=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.13/go.mod h1:Peg/GBAQ6JDt+RoBf4meB1wylmAipb7Kg2ZFakZTlwk=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.20.4 h1:2fjfz3/G9BRvIKuNZ655GwzpklC2kEH0cowZQGO7uBg=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.20.4/go.mod h1:Ymws824lvMypLFPwyyUXM52SXuGgxpu0+DISLfKvB+c=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.13 h1:a+8/MLcWlIxo1lF9xaGt3J/u3yOZx+CdSveSNwjhD40=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.13/go.mod h1:oGnKwIYZ4XttyU2JWxFrwvhF6YKiK/9/wmE3v3Iu9K8=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.13 h1:HBSI2kDkMdWz4ZM7FjwE7e/pWDEZ+nR95x8Ztet1ooY=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.13/go.mod h1:YE94ZoDArI7awZqJzBAZ3PDD2zSfuP7w6P2knOzIn8M=
github.com/aws/aws-sdk-go-v2 v1.41.5 h1:dj5kopbwUsVUVFgO4Fi5BIT3t4WyqIDjGKCangnV/yY=
github.com/aws/aws-sdk-go-v2 v1.41.5/go.mod h1:mwsPRE8ceUUpiTgF7QmQIJ7lgsKUPQOUl3o72QBrE1o=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8 h1:eBMB84YGghSocM7PsjmmPffTa+1FBUeNvGvFou6V/4o=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8/go.mod h1:lyw7GFp3qENLh7kwzf7iMzAxDn+NzjXEAGjKS2UOKqI=
github.com/aws/aws-sdk-go-v2/config v1.32.8 h1:iu+64gwDKEoKnyTQskSku72dAwggKI5sV6rNvgSMpMs=
github.com/aws/aws-sdk-go-v2/config v1.32.8/go.mod h1:MI2XvA+qDi3i9AJxX1E2fu730syEBzp/jnXrjxuHwgI=
github.com/aws/aws-sdk-go-v2/credentials v1.19.8 h1:Jp2JYH1lRT3KhX4mshHPvVYsR5qqRec3hGvEarNYoR0=
github.com/aws/aws-sdk-go-v2/credentials v1.19.8/go.mod h1:fZG9tuvyVfxknv1rKibIz3DobRaFw1Poe8IKtXB3XYY=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17 h1:I0GyV8wiYrP8XpA70g1HBcQO1JlQxCMTW9npl5UbDHY=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17/go.mod h1:tyw7BOl5bBe/oqvoIeECFJjMdzXoa/dfVz3QQ5lgHGA=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.22.1 h1:IbWiN670htmBioc+Zj32vSpJgQ2+OYSlvTvfQ1nCORQ=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.22.1/go.mod h1:tw/B596EUhBWDFGdDGuLC21fVU4A3s4/5Efy8S39W18=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21 h1:Rgg6wvjjtX8bNHcvi9OnXWwcE0a2vGpbwmtICOsvcf4=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21/go.mod h1:A/kJFst/nm//cyqonihbdpQZwiUhhzpqTsdbhDdRF9c=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21 h1:PEgGVtPoB6NTpPrBgqSE5hE/o47Ij9qk/SEZFbUOe9A=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21/go.mod h1:p+hz+PRAYlY3zcpJhPwXlLC4C+kqn70WIHwnzAfs6ps=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 h1:WKuaxf++XKWlHWu9ECbMlha8WOEGm0OUEZqm4K/Gcfk=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4/go.mod h1:ZWy7j6v1vWGmPReu0iSGvRiise4YI5SkR3OHKTZ6Wuc=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.13 h1:eg/WYAa12vqTphzIdWMzqYRVKKnCboVPRlvaybNCqPA=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.13/go.mod h1:/FDdxWhz1486obGrKKC1HONd7krpk38LBt+dutLcN9k=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.3 h1:x2Ibm/Af8Fi+BH+Hsn9TXGdT+hKbDd5XOTZxTMxDk7o=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.3/go.mod h1:IW1jwyrQgMdhisceG8fQLmQIydcT/jWY21rFhzgaKwo=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.4 h1:NvMjwvv8hpGUILarKw7Z4Q0w1H9anXKsesMxtw++MA4=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.4/go.mod h1:455WPHSwaGj2waRSpQp7TsnpOnBfw8iDfPfbwl7KPJE=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.13 h1:kDqdFvMY4AtKoACfzIGD8A0+hbT41KTKF//gq7jITfM=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.13/go.mod h1:lmKuogqSU3HzQCwZ9ZtcqOc5XGMqtDK7OIc2+DxiUEg=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.13 h1:zhBJXdhWIFZ1acfDYIhu4+LCzdUS2Vbcum7D01dXlHQ=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.13/go.mod h1:JaaOeCE368qn2Hzi3sEzY6FgAZVCIYcC2nwbro2QCh8=
github.com/aws/aws-sdk-go-v2/service/s3 v1.90.0 h1:ef6gIJR+xv/JQWwpa5FYirzoQctfSJm7tuDe3SZsUf8=
github.com/aws/aws-sdk-go-v2/service/s3 v1.90.0/go.mod h1:+wArOOrcHUevqdto9k1tKOF5++YTe9JEcPSc9Tx2ZSw=
github.com/aws/aws-sdk-go-v2/service/sso v1.30.1 h1:0JPwLz1J+5lEOfy/g0SURC9cxhbQ1lIMHMa+AHZSzz0=
github.com/aws/aws-sdk-go-v2/service/sso v1.30.1/go.mod h1:fKvyjJcz63iL/ftA6RaM8sRCtN4r4zl4tjL3qw5ec7k=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.5 h1:OWs0/j2UYR5LOGi88sD5/lhN6TDLG6SfA7CqsQO9zF0=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.5/go.mod h1:klO+ejMvYsB4QATfEOIXk8WAEwN4N0aBfJpvC+5SZBo=
github.com/aws/aws-sdk-go-v2/service/sts v1.39.1 h1:mLlUgHn02ue8whiR4BmxxGJLR2gwU6s6ZzJ5wDamBUs=
github.com/aws/aws-sdk-go-v2/service/sts v1.39.1/go.mod h1:E19xDjpzPZC7LS2knI9E6BaRFDK43Eul7vd6rSq2HWk=
github.com/aws/smithy-go v1.23.2 h1:Crv0eatJUQhaManss33hS5r40CG3ZFH+21XSkqMrIUM=
github.com/aws/smithy-go v1.23.2/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22 h1:rWyie/PxDRIdhNf4DzRk0lvjVOqFJuNnO8WwaIRVxzQ=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22/go.mod h1:zd/JsJ4P7oGfUhXn1VyLqaRZwPmZwg44Jf2dS84Dm3Y=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 h1:5EniKhLZe4xzL7a+fU3C2tfUN4nWIqlLesfrjkuPFTY=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7/go.mod h1:x0nZssQ3qZSnIcePWLvcoFisRXJzcTVvYpAAdYX8+GI=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13 h1:JRaIgADQS/U6uXDqlPiefP32yXTda7Kqfx+LgspooZM=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13/go.mod h1:CEuVn5WqOMilYl+tbccq8+N2ieCy0gVn3OtRb0vBNNM=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21 h1:c31//R3xgIJMSC8S6hEVq+38DcvUlgFY0FM6mSI5oto=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21/go.mod h1:r6+pf23ouCB718FUxaqzZdbpYFyDtehyZcmP5KL9FkA=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21 h1:ZlvrNcHSFFWURB8avufQq9gFsheUgjVD9536obIknfM=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21/go.mod h1:cv3TNhVrssKR0O/xxLJVRfd2oazSnZnkUeTf6ctUwfQ=
github.com/aws/aws-sdk-go-v2/service/s3 v1.97.3 h1:HwxWTbTrIHm5qY+CAEur0s/figc3qwvLWsNkF4RPToo=
github.com/aws/aws-sdk-go-v2/service/s3 v1.97.3/go.mod h1:uoA43SdFwacedBfSgfFSjjCvYe8aYBS7EnU5GZ/YKMM=
github.com/aws/aws-sdk-go-v2/service/signin v1.0.5 h1:VrhDvQib/i0lxvr3zqlUwLwJP4fpmpyD9wYG1vfSu+Y=
github.com/aws/aws-sdk-go-v2/service/signin v1.0.5/go.mod h1:k029+U8SY30/3/ras4G/Fnv/b88N4mAfliNn08Dem4M=
github.com/aws/aws-sdk-go-v2/service/sso v1.30.9 h1:v6EiMvhEYBoHABfbGB4alOYmCIrcgyPPiBE1wZAEbqk=
github.com/aws/aws-sdk-go-v2/service/sso v1.30.9/go.mod h1:yifAsgBxgJWn3ggx70A3urX2AN49Y5sJTD1UQFlfqBw=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.14 h1:0jbJeuEHlwKJ9PfXtpSFc4MF+WIWORdhN1n30ITZGFM=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.14/go.mod h1:sTGThjphYE4Ohw8vJiRStAcu3rbjtXRsdNB0TvZ5wwo=
github.com/aws/aws-sdk-go-v2/service/sts v1.41.6 h1:5fFjR/ToSOzB2OQ/XqWpZBmNvmP/pJ1jOWYlFDJTjRQ=
github.com/aws/aws-sdk-go-v2/service/sts v1.41.6/go.mod h1:qgFDZQSD/Kys7nJnVqYlWKnh0SSdMjAi0uSwON4wgYQ=
github.com/aws/smithy-go v1.24.2 h1:FzA3bu/nt/vDvmnkg+R8Xl46gmzEDam6mZ1hzmwXFng=
github.com/aws/smithy-go v1.24.2/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc=
github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
@@ -175,8 +177,8 @@ github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8 h1:GKTyiRCL6zVf5wWaq
github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8/go.mod h1:spo1JLcs67NmW1aVLEgtA8Yy1elc+X8y5SRW1sFW4Og=
github.com/buengese/sgzip v0.1.1 h1:ry+T8l1mlmiWEsDrH/YHZnCVWD2S3im1KLsyO+8ZmTU=
github.com/buengese/sgzip v0.1.1/go.mod h1:i5ZiXGF3fhV7gL1xaRRL1nDnmpNj0X061FQzOS8VMas=
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
github.com/buger/jsonparser v1.1.2 h1:frqHqw7otoVbk5M8LlE/L7HTnIq2v9RX6EJ48i9AxJk=
github.com/buger/jsonparser v1.1.2/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
github.com/bytedance/sonic v1.13.2 h1:8/H1FempDZqC4VqjptGo14QQlJx8VdZJegxs6wwfqpQ=
github.com/bytedance/sonic v1.13.2/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4=
@@ -198,8 +200,8 @@ github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEX
github.com/clipperhouse/uax29/v2 v2.3.0 h1:SNdx9DVUqMoBuBoW3iLOj4FQv3dN5mDtuqwuhIGpJy4=
github.com/clipperhouse/uax29/v2 v2.3.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g=
github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I=
github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8=
github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4=
github.com/cloudinary/cloudinary-go/v2 v2.13.0 h1:ugiQwb7DwpWQnete2AZkTh94MonZKmxD7hDGy1qTzDs=
github.com/cloudinary/cloudinary-go/v2 v2.13.0/go.mod h1:ireC4gqVetsjVhYlwjUJwKTbZuWjEIynbR9zQTlqsvo=
github.com/cloudsoda/go-smb2 v0.0.0-20250228001242-d4c70e6251cc h1:t8YjNUCt1DimB4HCIXBztwWMhgxr5yG5/YaRl9Afdfg=
@@ -280,8 +282,8 @@ github.com/gin-contrib/sse v1.0.0 h1:y3bT1mUWUxDpW4JLQg/HnTqV4rozuW4tC9eFKTxYI9E
github.com/gin-contrib/sse v1.0.0/go.mod h1:zNuFdwarAygJBht0NTKiSi3jRf6RbqeILZ9Sp6Slhe0=
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
github.com/go-chi/chi/v5 v5.2.3 h1:WQIt9uxdsAbgIYgid+BpYc+liqQZGMHRaUwp0JUcvdE=
github.com/go-chi/chi/v5 v5.2.3/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug=
github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
github.com/go-darwin/apfs v0.0.0-20211011131704-f84b94dbf348 h1:JnrjqG5iR07/8k7NqrLNilRsl3s1EPRQEGvbPyOce68=
github.com/go-darwin/apfs v0.0.0-20211011131704-f84b94dbf348/go.mod h1:Czxo/d1g948LtrALAZdL04TL/HnkopquAjxYUuI02bo=
github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM=
@@ -423,8 +425,8 @@ github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyf
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/internxt/rclone-adapter v0.0.0-20260130171252-c3c6ebb49276 h1:PTJPYovznNqc9t/9MjvtqhrgEVC9OiK75ZPL6hqm6gM=
github.com/internxt/rclone-adapter v0.0.0-20260130171252-c3c6ebb49276/go.mod h1:vdPya4AIcDjvng4ViaAzqjegJf0VHYpYHQguFx5xBp0=
github.com/internxt/rclone-adapter v0.0.0-20260220172730-613f4cc8b8fd h1:dSIuz2mpJAPQfhHYtG57D0qwSkgC/vQ69gHfeyQ4kxA=
github.com/internxt/rclone-adapter v0.0.0-20260220172730-613f4cc8b8fd/go.mod h1:vdPya4AIcDjvng4ViaAzqjegJf0VHYpYHQguFx5xBp0=
github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8=
github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo=
@@ -727,16 +729,16 @@ go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 h1:RbKq8BG0FI8OiXhBfcRtqqHcZcka+gU3cskNuf05R18=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0/go.mod h1:h06DGIukJOevXaj/xrNjhi/2098RZzcLTbc0jDAUbsg=
go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM=
go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=
go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E=
go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg=
go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM=
go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA=
go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48=
go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8=
go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0=
go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs=
go.opentelemetry.io/otel/sdk v1.39.0 h1:nMLYcjVsvdui1B/4FRkwjzoRVsMK8uL/cj0OyhKzt18=
go.opentelemetry.io/otel/sdk v1.39.0/go.mod h1:vDojkC4/jsTJsE+kh+LXYQlbL8CgrEcwmt1ENZszdJE=
go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8=
go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew=
go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI=
go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
@@ -764,8 +766,8 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -780,8 +782,8 @@ golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.32.0 h1:6lZQWq75h7L5IWNk0r+SCpUJ6tUVd3v4ZHnbRKLkUDQ=
golang.org/x/image v0.32.0/go.mod h1:/R37rrQmKXtO6tYXAjtDLwQgFLHmhW+V6ayXlxzP2Pc=
golang.org/x/image v0.38.0 h1:5l+q+Y9JDC7mBOMjo4/aPhMDcxEptsX+Tt3GgRQRPuE=
golang.org/x/image v0.38.0/go.mod h1:/3f6vaXC+6CEanU4KJxbcUZyEePbyKbaLoDOe4ehFYY=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -808,8 +810,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8=
golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -849,16 +851,16 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo=
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo=
golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw=
golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -874,8 +876,8 @@ golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -925,8 +927,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -938,8 +940,8 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg=
golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -955,8 +957,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -1010,8 +1012,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k=
golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -1073,10 +1075,10 @@ google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20250603155806-513f23925822 h1:rHWScKit0gvAPuOnu87KpaYtjK5zBMLcULh7gxkCXu4=
google.golang.org/genproto v0.0.0-20250603155806-513f23925822/go.mod h1:HubltRL7rMh0LfnQPkMH4NPDFEWp0jw3vixw7jEM53s=
google.golang.org/genproto/googleapis/api v0.0.0-20250804133106-a7a43d27e69b h1:ULiyYQ0FdsJhwwZUwbaXpZF5yUE3h+RA+gxvBu37ucc=
google.golang.org/genproto/googleapis/api v0.0.0-20250804133106-a7a43d27e69b/go.mod h1:oDOGiMSXHL4sDTJvFvIB9nRQCGdLP1o/iVaqQK8zB+M=
google.golang.org/genproto/googleapis/rpc v0.0.0-20251103181224-f26f9409b101 h1:tRPGkdGHuewF4UisLzzHHr1spKw92qLM98nIzxbC0wY=
google.golang.org/genproto/googleapis/rpc v0.0.0-20251103181224-f26f9409b101/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 h1:fCvbg86sFXwdrl5LgVcTEvNC+2txB5mgROGmRL5mrls=
google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:+rXWjjaukWZun3mLfjmVnQi18E1AsFbDN9QdJ5YXLto=
google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 h1:gRkg/vSppuSQoDjxyiGfN4Upv/h/DQmIR10ZU8dh4Ww=
google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
@@ -1089,8 +1091,8 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A=
google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c=
google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE=
google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+1 -1
View File
@@ -189,7 +189,7 @@ func MiddlewareCORS(allowOrigin string) Middleware {
if allowOrigin != "" {
w.Header().Add("Access-Control-Allow-Origin", allowOrigin)
w.Header().Add("Access-Control-Allow-Headers", "authorization, Content-Type")
w.Header().Add("Access-Control-Allow-Headers", "Authorization, Content-Type, Depth, Destination, If, Lock-Token, Overwrite, TimeOut, Translate")
w.Header().Add("Access-Control-Allow-Methods", "COPY, DELETE, GET, HEAD, LOCK, MKCOL, MOVE, OPTIONS, POST, PROPFIND, PROPPATCH, PUT, TRACE, UNLOCK")
w.Header().Add("Access-Control-Max-Age", "86400")
}
+21 -9
View File
@@ -159,18 +159,30 @@ func (p *Pacer) beginCall(limitConnections bool) {
// XXX ms later we put another in. We could do this with a
// Ticker more accurately, but then we'd have to work out how
// not to run it when it wasn't needed
<-p.pacer
p.mu.Lock()
sleepTime := p.state.SleepTime
p.mu.Unlock()
if sleepTime > 0 {
<-p.pacer
// Re-read the sleep time as it may be stale
// after waiting for the pacer token
p.mu.Lock()
sleepTime = p.state.SleepTime
p.mu.Unlock()
// Restart the timer
go func(t time.Duration) {
time.Sleep(t)
p.pacer <- struct{}{}
}(sleepTime)
}
if limitConnections {
<-p.connTokens
}
p.mu.Lock()
// Restart the timer
go func(t time.Duration) {
time.Sleep(t)
p.pacer <- struct{}{}
}(p.state.SleepTime)
p.mu.Unlock()
}
// endCall implements the pacing algorithm
+37
View File
@@ -367,6 +367,43 @@ func TestCallMaxConnectionsRecursiveDeadlock(t *testing.T) {
assert.Equal(t, errFoo, err)
}
func TestCallMaxConnectionsRecursiveDeadlock2(t *testing.T) {
p := New(CalculatorOption(NewDefault(MinSleep(1*time.Millisecond), MaxSleep(2*time.Millisecond))))
p.SetMaxConnections(1)
dp := &dummyPaced{retry: false}
wg := new(sync.WaitGroup)
// Normal
for range 100 {
wg.Add(1)
go func() {
defer wg.Done()
err := p.Call(func() (bool, error) {
// check we have taken the connection token
assert.Equal(t, 0, len(p.connTokens))
return false, nil
})
assert.NoError(t, err)
}()
// Now attempt a recursive call
wg.Add(1)
go func() {
defer wg.Done()
err := p.Call(func() (bool, error) {
// check we have taken the connection token
assert.Equal(t, 0, len(p.connTokens))
// Do recursive call
return false, p.Call(dp.fn)
})
assert.Equal(t, errFoo, err)
}()
}
// Tidy up
wg.Wait()
}
func TestRetryAfterError_NonNilErr(t *testing.T) {
orig := errors.New("test failure")
dur := 2 * time.Second
+5 -2
View File
@@ -28,7 +28,9 @@ func URLPathEscape(in string) string {
// URLPathEscapeAll escapes URL path the in string using URL escaping rules
//
// It escapes every character except [A-Za-z0-9] and /
// It escapes every character except the RFC 3986 unreserved characters
// [A-Za-z0-9-._~] and the path separator /. Unreserved characters MUST NOT
// be percent-encoded per RFC 3986 §2.3.
func URLPathEscapeAll(in string) string {
var b strings.Builder
b.Grow(len(in) * 3) // worst case: every byte escaped
@@ -36,7 +38,8 @@ func URLPathEscapeAll(in string) string {
for i := range len(in) {
c := in[i]
if (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
(c >= '0' && c <= '9') || c == '/' {
(c >= '0' && c <= '9') || c == '/' ||
c == '-' || c == '.' || c == '_' || c == '~' {
b.WriteByte(c)
} else {
b.WriteByte('%')
+4 -1
View File
@@ -66,7 +66,10 @@ func TestURLPathEscapeAll(t *testing.T) {
want string
}{
{"", ""},
{"/hello.txt", "/hello%2Etxt"},
// RFC 3986 unreserved characters must not be encoded
{"/hello.txt", "/hello.txt"},
{"file-name_v2.~bak", "file-name_v2.~bak"},
// Reserved and other characters must be encoded
{"With Space", "With%20Space"},
{"With Colon:", "With%20Colon%3A"},
{"With Percent%", "With%20Percent%25"},
+2 -2
View File
@@ -218,12 +218,12 @@ rclone convmv "stories/The Quick Brown Fox!.txt" --name-transform "all,command=e
```console
rclone convmv "stories/The Quick Brown Fox!" --name-transform "date=-{YYYYMMDD}"
// Output: stories/The Quick Brown Fox!-20260130
// Output: stories/The Quick Brown Fox!-20260419
```
```console
rclone convmv "stories/The Quick Brown Fox!" --name-transform "date=-{macfriendlytime}"
// Output: stories/The Quick Brown Fox!-2026-01-30 0852PM
// Output: stories/The Quick Brown Fox!-2026-04-19 1141AM
```
```console
Generated
+431 -27
View File
@@ -15,7 +15,7 @@
. ftr VB CB
. ftr VBI CBI
.\}
.TH "rclone" "1" "Jan 30, 2026" "User Manual" ""
.TH "rclone" "1" "Apr 19, 2026" "User Manual" ""
.hy
.SH NAME
.PP
@@ -4489,6 +4489,27 @@ Flags for anything which can copy a file
-u, --update Skip files that are newer on the destination
\f[R]
.fi
.SS Sync Options
.PP
Flags used for sync commands
.IP
.nf
\f[C]
--backup-dir string Make backups into hierarchy based in DIR
--delete-after When synchronizing, delete files on destination after transferring (default)
--delete-before When synchronizing, delete files on destination before transferring
--delete-during When synchronizing, delete files during transfer
--fix-case Force rename of case insensitive dest to match source
--ignore-errors Delete even if there are I/O errors
--list-cutoff int To save memory, sort directory listings on disk above this threshold (default 1000000)
--max-delete int When synchronizing, limit the number of deletes (default -1)
--max-delete-size SizeSuffix When synchronizing, limit the total size of deletes (default off)
--suffix string Suffix to add to changed files
--suffix-keep-extension Preserve the extension when using --suffix
--track-renames When synchronizing, track file renames and do a server-side move if possible
--track-renames-strategy string Strategies to use when synchronizing using track-renames hash|modtime|leaf (default \[dq]hash\[dq])
\f[R]
.fi
.SS Important Options
.PP
Important flags useful for most commands
@@ -6292,14 +6313,14 @@ rclone convmv \[dq]stories/The Quick Brown Fox!.txt\[dq] --name-transform \[dq]a
.nf
\f[C]
rclone convmv \[dq]stories/The Quick Brown Fox!\[dq] --name-transform \[dq]date=-{YYYYMMDD}\[dq]
// Output: stories/The Quick Brown Fox!-20260130
// Output: stories/The Quick Brown Fox!-20260419
\f[R]
.fi
.IP
.nf
\f[C]
rclone convmv \[dq]stories/The Quick Brown Fox!\[dq] --name-transform \[dq]date=-{macfriendlytime}\[dq]
// Output: stories/The Quick Brown Fox!-2026-01-30 0825PM
// Output: stories/The Quick Brown Fox!-2026-04-19 1137AM
\f[R]
.fi
.IP
@@ -6832,6 +6853,20 @@ incompatible with \f[V]--urls\f[R].
This will do \f[V]--transfers\f[R] copies in parallel.
Note that if \f[V]--auto-filename\f[R] is desired for all URLs then a
file with only URLs and no filename can be used.
.PP
Each FILENAME in the CSV file can start with a relative path which will
be appended to the destination path provided at the command line.
For example, running the command shown above with the following CSV file
will write two files to the destination:
\f[V]remote:dir/local/path/bar.json\f[R] and
\f[V]remote:dir/another/local/directory/qux.json\f[R]
.IP
.nf
\f[C]
https://example.org/foo/bar.json,local/path/bar.json
https://example.org/qux/baz.json,another/local/directory/qux.json
\f[R]
.fi
.SS Troubleshooting
.PP
If you can\[aq]t get \f[V]rclone copyurl\f[R] to work then here are some
@@ -8309,8 +8344,9 @@ not suffer from the same limitations.
Mounting on macOS can be done either via built-in NFS
server (https://rclone.org/commands/rclone_serve_nfs/),
macFUSE (https://osxfuse.github.io/) (also known as osxfuse) or
FUSE-T (https://www.fuse-t.org/).macFUSE is a traditional FUSE driver
utilizing a macOS kernel extension (kext).
FUSE-T (https://www.fuse-t.org/).
macFUSE is a traditional FUSE driver utilizing a macOS kernel extension
(kext).
FUSE-T is an alternative FUSE system which \[dq]mounts\[dq] via an NFSv4
local server.
.SS Unicode Normalization
@@ -8364,7 +8400,7 @@ wiki (https://github.com/macos-fuse-t/fuse-t/wiki#caveats):
.PP
File access and modification times cannot be set separately as it seems
to be an issue with the NFS client which always modifies both.
Can be reproduced with \[aq]touch -m\[aq] and \[aq]touch -a\[aq]
Can be reproduced with \f[V]touch -m\f[R] and \f[V]touch -a\f[R]
commands
.RE
.PP
@@ -8376,7 +8412,7 @@ This may make rclone upload a full new copy of the file.
When mounting with \f[V]--read-only\f[R], attempts to write to files
will fail \f[I]silently\f[R] as opposed to with a clear warning as in
macFUSE.
.SH Mounting on Linux
.SS Mounting on Linux
.PP
On newer versions of Ubuntu, you may encounter the following error when
running \f[V]rclone mount\f[R]:
@@ -8384,11 +8420,13 @@ running \f[V]rclone mount\f[R]:
.PP
NOTICE: mount helper error: fusermount3: mount failed: Permission denied
CRITICAL: Fatal error: failed to mount FUSE fs: fusermount: exit status
1 This may be due to newer Apparmor (https://wiki.ubuntu.com/AppArmor)
1
.RE
.PP
This may be due to newer Apparmor (https://wiki.ubuntu.com/AppArmor)
restrictions, which can be disabled with
\f[V]sudo aa-disable /usr/bin/fusermount3\f[R] (you may need to
\f[V]sudo apt install apparmor-utils\f[R] beforehand).
.RE
.SS Limitations
.PP
Without the use of \f[V]--vfs-cache-mode\f[R] this can only write files
@@ -9963,8 +10001,9 @@ not suffer from the same limitations.
Mounting on macOS can be done either via built-in NFS
server (https://rclone.org/commands/rclone_serve_nfs/),
macFUSE (https://osxfuse.github.io/) (also known as osxfuse) or
FUSE-T (https://www.fuse-t.org/).macFUSE is a traditional FUSE driver
utilizing a macOS kernel extension (kext).
FUSE-T (https://www.fuse-t.org/).
macFUSE is a traditional FUSE driver utilizing a macOS kernel extension
(kext).
FUSE-T is an alternative FUSE system which \[dq]mounts\[dq] via an NFSv4
local server.
.SS Unicode Normalization
@@ -10018,7 +10057,7 @@ wiki (https://github.com/macos-fuse-t/fuse-t/wiki#caveats):
.PP
File access and modification times cannot be set separately as it seems
to be an issue with the NFS client which always modifies both.
Can be reproduced with \[aq]touch -m\[aq] and \[aq]touch -a\[aq]
Can be reproduced with \f[V]touch -m\f[R] and \f[V]touch -a\f[R]
commands
.RE
.PP
@@ -10030,7 +10069,7 @@ This may make rclone upload a full new copy of the file.
When mounting with \f[V]--read-only\f[R], attempts to write to files
will fail \f[I]silently\f[R] as opposed to with a clear warning as in
macFUSE.
.SH Mounting on Linux
.SS Mounting on Linux
.PP
On newer versions of Ubuntu, you may encounter the following error when
running \f[V]rclone mount\f[R]:
@@ -10038,11 +10077,13 @@ running \f[V]rclone mount\f[R]:
.PP
NOTICE: mount helper error: fusermount3: mount failed: Permission denied
CRITICAL: Fatal error: failed to mount FUSE fs: fusermount: exit status
1 This may be due to newer Apparmor (https://wiki.ubuntu.com/AppArmor)
1
.RE
.PP
This may be due to newer Apparmor (https://wiki.ubuntu.com/AppArmor)
restrictions, which can be disabled with
\f[V]sudo aa-disable /usr/bin/fusermount3\f[R] (you may need to
\f[V]sudo apt install apparmor-utils\f[R] beforehand).
.RE
.SS Limitations
.PP
Without the use of \f[V]--vfs-cache-mode\f[R] this can only write files
@@ -22761,6 +22802,11 @@ the remote is sufficient.
In those cases, this flag can speed up the process and reduce the number
of API calls necessary.
.PP
This flag is only supported on certain backends and will be silently
ignored on unsupported backends.
Supported backends include \f[V]azureblob\f[R],
\f[V]oracleobjectstorage\f[R], \f[V]s3\f[R], \f[V]swift\f[R].
.PP
Using this flag on a sync operation without also using
\f[V]--update\f[R] would cause all files modified at any time other than
the last upload time to be uploaded again, which is probably not what
@@ -27207,6 +27253,8 @@ instead:
rclone rc --loopback operations/fsinfo fs=remote:
\f[R]
.fi
.PP
\f[B]Authentication is required for this call.\f[R]
.SS operations/hashsum: Produces a hashsum file for all the objects in the path.
.PP
Produces a hash file for all the objects in the path using the hash
@@ -27628,6 +27676,8 @@ And this sets NOTICE level logs (normal without -v)
rclone rc options/set --json \[aq]{\[dq]main\[dq]: {\[dq]LogLevel\[dq]: \[dq]NOTICE\[dq]}}\[aq]
\f[R]
.fi
.PP
\f[B]Authentication is required for this call.\f[R]
.SS pluginsctl/addPlugin: Add a plugin using url
.PP
Used for adding a plugin to the webgui.
@@ -29878,7 +29928,7 @@ Flags for general networking and HTTP stuff.
--tpslimit float Limit HTTP transactions per second to this
--tpslimit-burst int Max burst of transactions for --tpslimit (default 1)
--use-cookies Enable session cookiejar
--user-agent string Set the user-agent to a specified string (default \[dq]rclone/v1.73.0\[dq])
--user-agent string Set the user-agent to a specified string (default \[dq]rclone/v1.73.5\[dq])
\f[R]
.fi
.SS Performance
@@ -30362,9 +30412,11 @@ Backend-only flags (these can be set in the config file also).
--filefabric-token-expiry string Token expiry time
--filefabric-url string URL of the Enterprise File Fabric to connect to
--filefabric-version string Version read from the file fabric
--filelu-chunk-size SizeSuffix Chunk size to use for uploading. Used for multipart uploads (default 64Mi)
--filelu-description string Description of the remote
--filelu-encoding Encoding The encoding for the backend (default Slash,LtGt,DoubleQuote,SingleQuote,BackQuote,Dollar,Colon,Question,Asterisk,Pipe,Hash,Percent,BackSlash,CrLf,Del,Ctl,LeftSpace,LeftPeriod,LeftTilde,LeftCrLfHtVt,RightSpace,RightPeriod,RightCrLfHtVt,InvalidUtf8,Dot,SquareBracket,Semicolon,Exclamation)
--filelu-key string Your FileLu Rclone key from My Account
--filelu-upload-cutoff SizeSuffix Cutoff for switching to chunked upload. Any files larger than this will be uploaded in chunks of chunk_size (default 500Mi)
--filen-api-key string API Key for your Filen account (obscured)
--filen-auth-version string Authentication Version (internal use only)
--filen-base-folder-uuid string UUID of Account Root Directory (internal use only)
@@ -33145,19 +33197,13 @@ The following backends have known issues that need more investigation:
\f[V]TestBisyncRemoteRemote/normalization\f[R] (https://pub.rclone.org/integration-tests/current/dropbox-cmd.bisync-TestDropbox-1.txt)
.RE
.IP \[bu] 2
\f[V]TestSeafile\f[R] (\f[V]seafile\f[R])
.RS 2
.IP \[bu] 2
\f[V]TestBisyncLocalRemote/volatile\f[R] (https://pub.rclone.org/integration-tests/current/seafile-cmd.bisync-TestSeafile-1.txt)
.RE
.IP \[bu] 2
\f[V]TestSeafileV6\f[R] (\f[V]seafile\f[R])
.RS 2
.IP \[bu] 2
\f[V]TestBisyncLocalRemote/volatile\f[R] (https://pub.rclone.org/integration-tests/current/seafile-cmd.bisync-TestSeafileV6-1.txt)
\f[V]TestBisyncLocalRemote/rmdirs\f[R] (https://pub.rclone.org/integration-tests/current/seafile-cmd.bisync-TestSeafileV6-1.txt)
.RE
.IP \[bu] 2
Updated: 2026-01-30-010015
Updated: 2026-04-19-010011
.PP
The following backends either have not been tested recently or have
known issues that are deemed unfixable for the time being:
@@ -35860,6 +35906,28 @@ T}@T{
..
T}
.TE
.SS Important note about double slashes (\f[V]//\f[R])
.PP
Object keys containing consecutive forward slashes (\f[V]//\f[R]) are
\f[B]not supported\f[R] by rclone.
.PP
When rclone encounters an object key with \f[V]//\f[R] (e.g.,
\f[V]a//b\f[R]), it will normalize the path to use a single slash (e.g.,
\f[V]a/b\f[R]).
This normalization can cause \[dq]object not found\[dq] errors when
trying to access the original object, as rclone will look for the
normalized path instead of the actual object key.
.PP
\f[B]Example:\f[R] - Original S3 object key: \f[V]folder//file.txt\f[R]
- rclone interprets it as: \f[V]folder/file.txt\f[R] - Result:
\[dq]object not found\[dq] error when trying to access
\f[V]folder//file.txt\f[R]
.PP
\f[B]Workaround:\f[R] Avoid using consecutive forward slashes
(\f[V]//\f[R]) in S3 object keys when using rclone.
If you have existing objects with \f[V]//\f[R] in their keys, you will
need to rename them to use single slashes or access them through other
means.
.SS Multipart uploads
.PP
rclone supports multipart uploads with S3 which means that it can upload
@@ -38168,6 +38236,16 @@ Cubbit DS3 Object Storage endpoint
Provider: Cubbit
.RE
.IP \[bu] 2
\[dq]s3.{tenant_name}.cubbit.eu\[dq]
.RS 2
.IP \[bu] 2
Multi-tenant endpoint - replace {tenant_name} with your actual tenant
name.
Do not select this directly
.IP \[bu] 2
Provider: Cubbit
.RE
.IP \[bu] 2
\[dq]syd1.digitaloceanspaces.com\[dq]
.RS 2
.IP \[bu] 2
@@ -44022,6 +44100,9 @@ They will be needed when prompted by \f[V]rclone config\f[R].
.PP
Default region will correspond to \f[V]eu-west-1\f[R] and the endpoint
has to be specified as \f[V]s3.cubbit.eu\f[R].
If you set a custom tenant endpoint, you must use
\f[V]s3.{tenant_name}.cubbit.eu\f[R], because the generic
\f[V]s3.cubbit.eu\f[R] endpoint will not work in this case.
.PP
Going through the whole process of creating a new remote by running
\f[V]rclone config\f[R], each prompt should be answered as shown below:
@@ -44035,7 +44116,7 @@ env_auth> false
access_key_id> YOUR_ACCESS_KEY
secret_access_key> YOUR_SECRET_KEY
region> eu-west-1 (or leave empty)
endpoint> s3.cubbit.eu
endpoint> s3.cubbit.eu (or s3.{tenant_name}.cubbit.eu)
acl>
\f[R]
.fi
@@ -48333,6 +48414,16 @@ cos s3
\f[R]
.fi
.RE
.SS Tencent COS Global Acceleration Endpoint
.PP
When using the Global Acceleration Endpoint
(\f[V]cos.accelerate.myqcloud.com\f[R]), rclone automatically sets
\f[V]no_check_bucket = true\f[R] because this acceleration endpoint does
not support the \f[V]CreateBucket\f[R] call which is used for ensuring a
bucket\[aq]s existence by rclone.
Global Acceleration is a per-bucket feature, so you should first create
the bucket in one physical region, then enable it in the Tencent Cloud
console.
.SS Wasabi
.PP
Wasabi (https://wasabi.com) is a cloud-based object storage service for
@@ -56514,6 +56605,34 @@ Required: true
.SS Advanced options
.PP
Here are the Advanced options specific to filelu (FileLu Cloud Storage).
.SS --filelu-upload-cutoff
.PP
Cutoff for switching to chunked upload.
Any files larger than this will be uploaded in chunks of chunk_size.
.PP
Properties:
.IP \[bu] 2
Config: upload_cutoff
.IP \[bu] 2
Env Var: RCLONE_FILELU_UPLOAD_CUTOFF
.IP \[bu] 2
Type: SizeSuffix
.IP \[bu] 2
Default: 500Mi
.SS --filelu-chunk-size
.PP
Chunk size to use for uploading.
Used for multipart uploads.
.PP
Properties:
.IP \[bu] 2
Config: chunk_size
.IP \[bu] 2
Env Var: RCLONE_FILELU_CHUNK_SIZE
.IP \[bu] 2
Type: SizeSuffix
.IP \[bu] 2
Default: 64Mi
.SS --filelu-encoding
.PP
The encoding for the backend.
@@ -56563,6 +56682,10 @@ CLI (https://github.com/FilenCloudDienste/filen-cli).
This means you must first download the CLI, login, and then run the
\f[V]export-api-key\f[R] command.
.PP
\f[B]Note:\f[R] If you change your Filen account password, you will need
to update your rclone configuration with the new password and a
re-exported API key (via \f[V]export-api-key\f[R]).
.PP
Here is an example of how to make a remote called \f[V]FilenRemote\f[R].
First run:
.IP
@@ -85633,7 +85756,7 @@ T}
.PP
When running on Windows the following characters are replaced.
This list is based on the Windows file naming
conventions (https://docs.microsoft.com/de-de/windows/desktop/FileIO/naming-a-file#naming-conventions).
conventions (https://docs.microsoft.com/windows/desktop/FileIO/naming-a-file#naming-conventions).
.PP
.TS
tab(@);
@@ -86814,6 +86937,287 @@ Options:
.IP \[bu] 2
\[dq]error\[dq]: Return an error based on option value.
.SH Changelog
.SS v1.73.5 - 2026-04-19
.PP
See commits (https://github.com/rclone/rclone/compare/v1.73.4...v1.73.5)
.IP \[bu] 2
Bug Fixes
.RS 2
.IP \[bu] 2
operations: Add AuthRequired to operations/fsinfo to prevent backend
creation CVE-2026-41179 (Nick Craig-Wood)
.IP \[bu] 2
rc
.RS 2
.IP \[bu] 2
Add AuthRequired to options/set to prevent auth bypass CVE-2026-41176
(Nick Craig-Wood)
.IP \[bu] 2
Snapshot NoAuth at startup to prevent runtime auth bypass CVE-2026-41176
(Nick Craig-Wood)
.RE
.IP \[bu] 2
filter: Fix debug logs that fire before logger is configured (Nick
Craig-Wood)
.RE
.IP \[bu] 2
Azureblob
.RS 2
.IP \[bu] 2
Add Microsoft Partner Network User-Agent prefix (Nick Craig-Wood)
.RE
.IP \[bu] 2
Drime
.RS 2
.IP \[bu] 2
Fix User.EntryPermissions JSON unmarshalling (a1pcm)
.RE
.IP \[bu] 2
Iclouddrive
.RS 2
.IP \[bu] 2
Fix \[aq]directory not found\[aq] error when the directory contains
accent marks (Brais Couce)
.RE
.IP \[bu] 2
S3
.RS 2
.IP \[bu] 2
Fix TencentCOS CDN endpoint failing on bucket check (Mozi)
.IP \[bu] 2
Fix empty delimiter parameter rejected by Archiware P5 server (Nick
Craig-Wood)
.RE
.SS v1.73.4 - 2026-04-08
.PP
See commits (https://github.com/rclone/rclone/compare/v1.73.3...v1.73.4)
.IP \[bu] 2
Bug Fixes
.RS 2
.IP \[bu] 2
build
.RS 2
.IP \[bu] 2
Update to go 1.25.9 to fix multiple CVEs (Nick Craig-Wood)
.RS 2
.IP \[bu] 2
CVE-2026-32282: os: Root.Chmod can follow symlinks out of the root on
Linux
.IP \[bu] 2
CVE-2026-32289: html/template: JS template literal context incorrectly
tracked
.IP \[bu] 2
CVE-2026-33810: crypto/x509: excluded DNS constraints not properly
applied to wildcard domains
.IP \[bu] 2
CVE-2026-27144: cmd/compile: no-op interface conversion bypasses overlap
checking
.IP \[bu] 2
CVE-2026-27143: cmd/compile: possible memory corruption after bound
check elimination
.IP \[bu] 2
CVE-2026-32288: archive/tar: unbounded allocation when parsing old
format GNU sparse map
.IP \[bu] 2
CVE-2026-32283: crypto/tls: multiple key update handshake messages can
cause connection to deadlock
.IP \[bu] 2
CVE-2026-27140: cmd/go: trust layer bypass when using cgo and SWIG
.IP \[bu] 2
CVE-2026-32280: crypto/x509: unexpected work during chain building
.IP \[bu] 2
CVE-2026-32281: crypto/x509: inefficient policy validation
.RE
.IP \[bu] 2
Fix Denial of Service due to Panic in AWS SDK for Go v2 SDK EventStream
Decoder (dependabot[bot])
.IP \[bu] 2
Update golang.org/x/image to 0.38.0 to fix CVE-2026-33809
(dependabot[bot])
.RE
.IP \[bu] 2
docs
.RS 2
.IP \[bu] 2
Fix header level for metadata option (Clément Notin)
.IP \[bu] 2
Fix markdown issues in mount docs (albertony)
.IP \[bu] 2
Fix link to not be language specific (Ross Smith II)
.IP \[bu] 2
Note macOS 10.15 (Catalina) support with version v1.70.3 (kapitainsky)
.RE
.RE
.IP \[bu] 2
Filen
.RS 2
.IP \[bu] 2
Update SDK version (Enduriel)
.RE
.SS v1.73.3 - 2026-03-23
.PP
See commits (https://github.com/rclone/rclone/compare/v1.73.2...v1.73.3)
.IP \[bu] 2
Bug Fixes
.RS 2
.IP \[bu] 2
build
.RS 2
.IP \[bu] 2
Update to google.golang.org/grpc 1.79.3 to fix CVE-2026-33186
(dependabot[bot])
.IP \[bu] 2
Update to github.com/buger/jsonparser 1.1.2 to fix GHSA-6g7g-w4f8-9c9x
(dependabot[bot])
.RE
.IP \[bu] 2
doc fixes
.RS 2
.IP \[bu] 2
Added text to the label showing version-introduced info (Jan-Philipp
Reßler)
.IP \[bu] 2
Clarify Filen password change requires updating both password and API
key in rclone config (Jason)
.IP \[bu] 2
s3: clarify multi tenant support for Cubbit (Marco Ferretti)
.IP \[bu] 2
jottacloud: Fix broken link (albertony)
.RE
.IP \[bu] 2
lib/rest: Fix URLPathEscapeAll breaking WebDAV servers (eg nzbdav) with
strict path matching (Andrew Furman)
.IP \[bu] 2
list: Fix nil pointer panic in Sorter when temp file creation fails
(Nick Craig-Wood)
.RE
.SS v1.73.2 - 2026-03-06
.PP
See commits (https://github.com/rclone/rclone/compare/v1.73.1...v1.73.2)
.IP \[bu] 2
Bug Fixes
.RS 2
.IP \[bu] 2
build
.RS 2
.IP \[bu] 2
Update to go 1.25.8 to fix CVE-2026-27137 CVE-2026-27138 CVE-2026-25679
CVE-2026-27142 (Nick Craig-Wood)
.IP \[bu] 2
Update github.com/cloudflare/circl to v1.6.3 to fix CVE-2026-1229 (Nick
Craig-Wood)
.IP \[bu] 2
Update to golang.org/x/net v0.51.0 to fix CVE-2026-27141 (Nick
Craig-Wood)
.RE
.IP \[bu] 2
docs fixes:
.RS 2
.IP \[bu] 2
bisync: Add group Sync to the bisync command (Jan-Philipp Reßler)
.IP \[bu] 2
Note that --use-server-modtime only works on some backends (Nick
Craig-Wood)
.IP \[bu] 2
Document unsupported S3 object keys with double slashes (Adam Kasztenny)
.IP \[bu] 2
Fix headers hierarchy for mount.md (Dark Dragon)
.IP \[bu] 2
Fix new drive flag typo in changelog (razorloves)
.RE
.RE
.IP \[bu] 2
Archive
.RS 2
.IP \[bu] 2
Extract: fix extraction with \[dq]./\[dq] prefix from tar entry paths
(Varun Chawla)
.RE
.IP \[bu] 2
Drime
.RS 2
.IP \[bu] 2
Fix chunk-uploaded files ignoring workspace ID (a1pcm)
.RE
.IP \[bu] 2
Internxt
.RS 2
.IP \[bu] 2
Fix Entry doesn\[aq]t belong in directory errors on windows (jzunigax2)
.RE
.IP \[bu] 2
WebDAV
.RS 2
.IP \[bu] 2
Escape reserved characters in URL path segments (Varun Chawla)
.IP \[bu] 2
Add missing headers for CORS (Romāns Potašovs)
.RE
.SS v1.73.1 - 2026-02-17
.PP
See commits (https://github.com/rclone/rclone/compare/v1.73.0...v1.73.1)
.IP \[bu] 2
Bug Fixes
.RS 2
.IP \[bu] 2
accounting: Fix missing server side stats from core/stats rc (Nick
Craig-Wood)
.IP \[bu] 2
build
.RS 2
.IP \[bu] 2
Fix CVE-2025-68121 by updating go to 1.25.7 or later (Nick Craig-Wood)
.IP \[bu] 2
Bump github.com/go-chi/chi/v5 from 5.2.3 to 5.2.5 to fix GO-2026-4316
(albertony)
.RE
.IP \[bu] 2
docs: Extend copyurl docs with an example of CSV FILENAMEs starting with
a path.
(Jack Kelly)
.IP \[bu] 2
march: Fix runtime: program exceeds 10000-thread limit (Nick Craig-Wood)
.IP \[bu] 2
pacer
.RS 2
.IP \[bu] 2
Fix deadlock between pacer token and --max-connections (Nick Craig-Wood)
.IP \[bu] 2
Re-read the sleep time as it may be stale (Nick Craig-Wood)
.RE
.RE
.IP \[bu] 2
Drime
.RS 2
.IP \[bu] 2
Fix files and directories being created in the default workspace (Nick
Craig-Wood)
.RE
.IP \[bu] 2
Filelu
.RS 2
.IP \[bu] 2
Avoid buffering entire file in memory (kingston125)
.IP \[bu] 2
Add multipart upload support with configurable cutoff (kingston125)
.RE
.IP \[bu] 2
Filen
.RS 2
.IP \[bu] 2
Fix 32 bit targets not being able to list directories (Enduriel)
.IP \[bu] 2
Fix potential panic in case of error during upload (Enduriel)
.RE
.IP \[bu] 2
Internxt
.RS 2
.IP \[bu] 2
Implement re-login under refresh logic, improve retry logic (José
Zúniga) -S3
.IP \[bu] 2
Set list_version to 2 for FileLu S3 configuration (kingston125)
.RE
.SS v1.73.0 - 2026-01-30
.PP
See commits (https://github.com/rclone/rclone/compare/v1.72.0...v1.73.0)
@@ -86894,7 +87298,7 @@ Support authentication with new bucket restricted application keys
Drive
.RS 2
.IP \[bu] 2
Add \f[V]--drive-metadata-force-expansive-access\f[R] flag (Nick
Add \f[V]--drive-metadata-enforce-expansive-access\f[R] flag (Nick
Craig-Wood)
.IP \[bu] 2
Fix crash when trying to creating shortcut to a Google doc (Nick