Commit Graph
10466 Commits
Author SHA1 Message Date
Nick Craig-Wood ee0a70f875 serve ftp: fix transfers failing after 5 minutes with --auth-proxy
With --auth-proxy the backend of each user is shut down once it has
been unused for 5 minutes. Only the start of each FTP command counted
as a use, so an upload or download lasting longer than that had its
backend shut down under it and failed with "context canceled".

Each FTP command now holds the backend it uses until it has finished,
which for a download is when the file is closed.

This was introduced in v1.75.1 by

f425f8d46 serve: refactor VFS and proxy handling into Provider
2026-10-08 10:36:00 +01:00
Kayaandfiratkaya 408cc55171 Add new backend dosya for dosya.dev cloud storage
Add a new backend for dosya.dev, a cloud file storage, sharing, and
synchronization platform with workspace-based multi-tenancy.

Features:
- Server-side copy, move, rename (files and directories)
- Purge (recursive directory delete)
- Recursive listing (ListR) for --fast-list
- Multipart upload for large files (>10MB)
- Public link sharing via rclone link
- About (workspace storage quota)
- MIME type detection
- Empty directory support
- Workspace-based multi-tenancy (one remote per workspace)
- Download via presigned R2 URLs with Range header support

Co-authored-by: firatkaya <firat@netiket.com.tr>
2026-10-07 12:16:42 +01:00
mygrexit aeb98f9316 s3: add RelAix.Storage provider
RelAix.Storage is S3 compatible object storage from RelAix Networks in
Aachen, Germany, with two locations (Aachen-1 and Aachen-2).
2026-10-06 12:23:02 +01:00
Nick Craig-Wood d545615c16 sftp: fix failed uploads leaving disk space in use on the server - fixes #10033
When an upload failed during the transfer, the partial file was
removed but its handle was never closed. The server kept the deleted
file open, so its space stayed allocated until the pooled connection
was closed, which in rcd, mount or serve could be until rclone exited.

This closes the handle before removing the partial file.
2026-10-06 10:12:50 +01:00
Nick Craig-Wood 169a0c6118 docs: note in AGENTS.md that core tests run against all backends
Tests in fs/operations, fs/sync, cmd/bisync, cmd/gitannex and vfs are
run by the integration tests against every backend, so they need to
cope with backends with limited functionality, ideally by skipping on
the Fs.Features() flags.
2026-10-05 17:44:55 +01:00
Nick Craig-Wood ed92e4446e filescom: document that names with / or \ in can't be stored and ignore their tests
Files.com now treats the replacement characters rclone uses for / and
\ in file names (/ and \) as if they were the originals, and the
names . and .. as if they were . and .., and rejects them all with
"Invalid path". There is no other way of encoding these names, so
document the restriction and ignore the integration tests for them.
2026-10-05 17:39:34 +01:00
Nick Craig-Wood 9f0b40c7d2 hidrive: fix truncated file left behind when an upload hits --max-transfer
When an upload was stopped part way through by --max-transfer, HiDrive
kept the part of the file it had received, leaving a truncated file at
the destination, or replacing an existing file with a truncated one.

This was introduced in e8f421d28 which accounted the buffered start of
each upload as it was sent rather than as it was read, so the transfer
limit could abort the request which creates the file half way through.

Account the requests which create or replace a file in one go as they
are buffered once more, so the limit is hit before anything is sent.
The chunks of larger uploads are still accounted as they are sent.
2026-10-05 17:39:34 +01:00
Nick Craig-Wood f217c8a2aa webdav: fix "XML syntax error" on paths which don't exist with ownCloud 10.16
ownCloud 10.16 answers a PROPFIND for a path which doesn't exist with
a 207 Multi-Status response, rather than a 404, with a body which
starts a multistatus document then appends a Sabre NotFound error to
it. This isn't valid XML so rclone failed with

    read metadata failed: XML syntax error on line 2: expected attribute name in element

whenever it was pointed at a directory which didn't exist yet.

Detect the NotFound error in the response and treat it as a 404.
2026-10-05 17:39:34 +01:00
Nick Craig-Wood be8b238033 test_all: ignore index and files-from tests on cloudinary as search is eventually consistent
These tests look up objects straight after uploading them, which
fails with "object not found" on cloudinary until its search API
catches up.
2026-10-05 17:39:34 +01:00
Nick Craig-Wood c8a03f1f8e test_all: ignore index tests which download HTML on koofr and opendrive
Koofr refuses to download the HTML listings written by the index tests
with "FileBlocked: File download restricted due to possible dangerous
content" and OpenDrive refuses with 403 Forbidden, so the tests can't
read back what they wrote. The index tests which write other formats
still run.
2026-10-05 17:39:34 +01:00
Nick Craig-Wood 475997b6de chunker: fix panic listing a directory after an interrupted upload with meta_format none
With meta_format = none, listing a directory which contained the
temporary chunks of an interrupted upload, but no completed chunks for
that file, panicked with "invalid chunked object".

The listing made a placeholder object for the file on seeing a
temporary chunk, which then had no chunks in it when it was validated.
Only make the placeholder on seeing a data chunk, so files which have
nothing but temporary chunks are ignored as they are when metadata is
in use.
2026-10-05 17:39:34 +01:00
Nick Craig-Wood e14337ebef operations: fix index tests failing in the integration tests
- Only check the MIME type of the listings on backends which declare
  both ReadMimeType and WriteMimeType, and ignore its parameters, as
  many backends report a MIME type they chose themselves or drop the
  charset.
- Write the test file before turning --dry-run on. Chunker finishes
  an upload with operations.Move, which honours --dry-run, so it left
  temporary chunks behind which stopped the test directory being
  removed and made the tests following fail.
- Don't check the transfer and delete counts on chunker, as moving
  its chunks into place is counted in the same stats.
- Don't expect a new file to change the time of the directories above
  it on backends which can't set modification times, as it may get the
  same time as the files already there.
2026-10-05 17:39:34 +01:00
Nick Craig-Wood 3b9f0a05b5 azureblob: use the released Azure SDK for Apache Arrow listing
The Blob Listing with Apache Arrow feature is now public and shipped
in azblob v1.8.1, so the temporary backend/azureblob/arrowlist package
which implemented it on top of the previous SDK has been removed and
the backend now uses the SDK's own listing pager with ResponseFormat
set to Arrow.

As the SDK client handles every credential type this also makes Arrow
and parallel listing work with connection_string auth, and the
use_arrow_list and list_parallelism options are no longer hidden.
2026-10-05 11:42:24 +01:00
Nick Craig-Wood e3553ef8b3 Add 8 new contributors
- interested.tortoise
- hsdfat
- Dirk Petersen
- TastyHeadphones
- Neil Cawse
- Lev Devaev
- GhostCoder6969
- bounty-agent
2026-10-05 11:42:24 +01:00
GhostCoder6969andbounty-agent 7ebef790b4 docs: fix typo in speed test help text
Co-authored-by: bounty-agent <bounty@example.com>
2026-10-04 09:14:02 +02:00
Nick Craig-Wood a82c965ba1 build: move beta.downloads.org site to cloudflare 2026-10-03 16:27:30 +01:00
Nick Craig-Wood 9e27583e80 build: index the downloads site after uploading a new release 2026-10-02 15:44:25 +01:00
Nick Craig-Wood 67afe55a83 archive: fix a squashfs path to a single file listing its whole directory
Pointing the archive backend at a file inside a squashfs image, for
example `rclone cat :archive:image.sqfs/dir/file.txt`, listed every
file in the directory containing it instead of just that file. The zip
archiver already behaved correctly.

The squashfs archiver now remembers the file the root points at and
only exposes that one, as zip does. Its Root() includes the file so
that the fs cache does not hand back the Fs for the whole directory in
its place.
2026-10-02 15:44:25 +01:00
Nick Craig-Wood 0be5c88394 local: limit the size of symlink targets read from .rclonelink files
With -l/--links a .rclonelink object is buffered in memory to become
the target of a symlink. The read was unbounded, so a hostile or
corrupt source serving a large .rclonelink object made rclone use that
much memory and then log the whole body in the resulting error.

A symlink target can never be longer than a path, so the read now stops
at 128 KiB and anything longer is refused without retrying.
2026-10-02 15:44:25 +01:00
Lev Devaev 0b8e9c4ccd ncdu: show progress and the item count when deleting a selection
Deleting a selection finished with "Successfully deleted all items!",
which claimed more than had happened - only the selected entries were
removed.  It now names the number of items deleted.

The screen was not redrawn until the whole selection had been deleted,
which made the UI look hung, so a progress box is drawn before each
deletion.

Fixes #9516
2026-09-30 17:57:47 +01:00
Rohit Behera d8794f8192 fs: fix durations like 1d12h being rejected
The docs describe a duration as a sequence of numbers each with a unit
suffix, including d, w, M and y, but a sequence that used one of those
units, such as --max-age 1d12h, failed with a confusing error about
parsing it as a date. Only a single number with one of them, like 1.5d,
or a sequence of the time.ParseDuration units was accepted.

Parse such sequences before falling back to dates, rejecting ones too
long to represent.
2026-09-30 17:55:19 +01:00
Morax 49158b2d9f bisync: make --max-delete aware of --track-renames
Add an opt-in preflight that excludes only guaranteed tracked renames
from the max-delete count. Reuse normal bisync listing metadata,
validate strategy and flag conflicts early, and skip preflight work
when --force bypasses the safety check.

The max_delete_track_renames scenario uses the default hash
track-renames strategy, which requires a hash common to both paths.
Skip it on remote combinations without one, such as crypt, instead of
failing the integration tests.

Fixes #8685
2026-09-30 17:53:20 +01:00
Morax 015f9cd127 sync: export --track-renames matching logic
Move strategy parsing, capability checks, and matcher behavior into a
reusable package without changing sync behavior. Add a lightweight
candidate API so callers can count guaranteed matches without
retaining filesystem objects.
2026-09-30 17:53:20 +01:00
Neil Cawse 9380daed0d vfs: stop setting a file's modtime from discarding its cached data
Setting the modtime of a closed file refreshed the cache item's
fingerprint before the new modtime had been applied to the remote
object. The next open then saw a fingerprint mismatch, logged "removed
cache file as stale (remote is different)" and downloaded the whole
file again, even though only the modtime had changed.

Refresh the cache fingerprint again once the remote modtime has been
set.
2026-09-30 17:51:49 +01:00
Neil Cawse e0fb01084d vfs: fix reads returning zeros after a file changes during handle caching
When a file was reopened within the --vfs-handle-caching grace period
(default 5s) after its remote fingerprint changed - for example after a
touch or any other modtime change - _checkObject removed the stale
cache file and open recreated an empty one, but nothing sized it. The
next GetSize stat'd the empty file and set the item size to 0, so
ReadAt's _ensure clamped the request to nothing and skipped the
download, then the size check zero-extended the file and returned the
zeros. Reads through a mount returned the correct length but zeros for
the first read (128 KiB through FUSE).

This is easy to hit with git on a --vfs-cache-mode full mount: git
freshens pack files with utime, and a concurrent reader then sees
"not a GIT packfile".

Size the recreated cache file from the object before opening it, as a
normal open does.
2026-09-30 17:51:49 +01:00
TastyHeadphones 80e462d48c oauthutil: fix Renew.Shutdown nil timer panic and race
Shutdown was calling expiryTimer.Stop without holding ts.mu, so it could
panic if OnExpiry had not created the timer yet, and raced the write in
OnExpiry. Hold the lock and skip Stop when the timer is still nil.

Fixes #9980
2026-09-30 17:34:51 +01:00
Dirk Petersen 6ed7b9d775 s3: report the real storage class when an object needs restoring
Reading an object in an archive storage class failed with "Object in
GLACIER, restore first" even when the object was in DEEP_ARCHIVE or in
an Intelligent-Tiering archive access tier.

Use the storage class and access tier from the InvalidObjectState
error. The storage class is optional in that error, so fall back to
the storage class from the listing or HEAD, and then to GLACIER as
before.
2026-09-30 17:33:04 +01:00
Rohit Behera e497464b60 docs: fix the expanded --bwlimit timetable example
It was missing a space between two entries, so it didn't parse.
2026-09-30 17:30:06 +01:00
Rohit Behera 124f3bd830 fs: fix --bwlimit timetables written out of order using the wrong limit
Until the first time slot of the week, the timetable used its last entry
as the limit carried over from the week before. That is only the latest
slot of the week when the entries are in order, so a timetable written
weekend first, like "Sat-00:00,off Mon-00:00,1M", limited Sunday to 1M
instead of leaving it unlimited.

Carry over the latest time slot of the week instead.
2026-09-30 17:30:06 +01:00
Dirk Petersen e5eaf414f0 s3: fix storage class missing from --s3-versions listings
When listing with --s3-versions or --s3-version-at the storage class
of each object was dropped, so it read as STANDARD unless the object's
metadata was fetched separately. This meant backend restore skipped
objects in GLACIER or DEEP_ARCHIVE with "Not GLACIER or DEEP_ARCHIVE
or INTELLIGENT_TIERING storage class", and lsf --format T showed the
wrong tier.

This happened because ObjectVersion.StorageClass has a different type
from Object.StorageClass so the generated setFrom helper does not copy
it. Convert it explicitly after the setFrom call.
2026-09-30 17:23:07 +01:00
hsdfat 3cdf855547 docker: fix files uploaded with the wrong mime type - fixes #6384
The Docker image had no /etc/mime.types, so MIME types came only from
Go's built-in table plus rclone's small extra list, and many
extensions uploaded as application/octet-stream.

This installs Alpine's mailcap package to fix the problem.
2026-09-30 17:16:47 +01:00
interested.tortoise 9daa4ccfeb s3: Add the md5 value to debug message for multipart chunk for S3
Adding md5 information to debug message for multipart upload as this is useful when testing.
2026-09-30 17:13:04 +01:00
Nick Craig-Wood 8cd43746a3 selfupdate: fix --version X.Y depending on ./ in the download site links
To find the latest patch release of a minor version, for example
`rclone selfupdate --version 1.75`, selfupdate searched the listing of
downloads.rclone.org for href="./vX.Y.Z/". The leading ./ is a detail
of how Caddy's file server writes its links. A listing which linked to
the same directories as "vX.Y.Z/", which is an equally valid relative
URL, made selfupdate fail with "could not find the minor release".

This makes the ./ optional in the pattern, so selfupdate no longer
depends on which program wrote the listing, and takes the version from
a capture group rather than from fixed offsets into the match.

The listings written by rclone index now include the ./ for the
benefit of rclone versions without this fix, so this is to remove the
dependency for the future.
2026-09-30 12:14:28 +01:00
Nick Craig-Wood 89521d875d lib/http: prefix links in directory listings with ./ so selfupdate works
downloads.rclone.org is about to be served from static listings
written by rclone index instead of by Caddy's file server. Released
versions of rclone selfupdate find the latest patch release of a minor
version by searching that listing for href="./vX.Y.Z/", as written by
Caddy. rclone's listings linked to "vX.Y.Z/" without the ./ so `rclone
selfupdate --version X.Y` would have failed with "could not find the
minor release" for every rclone already installed.

Caddy prefixes every link with ./ so that a name with a colon in its
first path segment is not read as an absolute URL with a scheme (RFC
3986 section 4.2). rclone was already safe from that as url.URL.String
adds the ./ but only to names which need it, so links to plain names
had no prefix.

This prefixes all the links with ./ as Caddy does. It changes the
output of serve http, serve webdav and the rc server as well as rclone
index, since they share the code. The links resolve identically, and
it keeps the listings consistent with each other.

Now every URL has the prefix, the caddy.json template no longer needs
to add it.
2026-09-30 12:12:33 +01:00
Nick Craig-Wood 666d67f0eb index: add partial runs which only re-index changed directories
After a sync which changed a known set of files there is no need to
walk the whole remote. --changed PATH, --changed-from FILE and
--changed-combined FILE tell rclone index what changed, and it
re-indexes only the directories containing those paths and their
ancestors, each with one non-recursive listing.
2026-09-29 18:21:23 +01:00
Nick Craig-Wood 72a6d36cb2 serve http,webdav: redesign the directory listing page
The listing now shows the folder path with clickable breadcrumbs
above a card containing the entries:

- A summary of the directories, files and total size
- The directory and file counts are toggles
- The search box sits beside the Name heading (focussable with /)
- Sizes right aligned, empty columns are gone and the icons are simpler.
- The colours are CSS variables

The template data is unchanged so custom templates still work, and
the zip download links and ?sort= parameters work as before.
2026-09-29 18:21:23 +01:00
Nick Craig-Wood 1897074971 index: add a command to write static directory listings into a remote
This makes directory listings for buckets and other remotes served as
static websites, for example S3 website endpoints or R2 behind
Cloudflare, so they can be browsed without directory listing support
on the host.
2026-09-29 18:21:23 +01:00
Nick Craig-Wood ae9a50cacd operations: add Index to write static directory listings into a remote
Index writes a directory listing (e.g. index.html) into every
directory of a remote so it can be browsed when served as a static
website. It is also available over the rc as operations/index.

It works like sync. It walks the remote once, renders the listings in
memory and compares them with the existing ones by size and hash from
the listing, or by reading them where the backend has no hash.
Listings in directories which contain nothing else are deleted on
backends which can't have empty directories.

Listings can be written in the serve http HTML format, the lsjson
format, Caddy's browse JSON format, or from a user template. A second
rule set (--index-include and friends) controls which directories get
listings, --dir-time controls the time shown for directories and
--no-modtime avoids reading modification times altogether.
2026-09-29 18:21:23 +01:00
Nick Craig-Wood dcd5cf0640 lib/http: add static rendering support to the directory listing
- .Static hides the "up" link at the root
- .SetLinkIndex makes directory links point at an index doc
- .Render writes the listing to an io.Writer
- .Path, .IsRoot, .UpLink, .NumDirs, .NumFiles, .TotalSize and .MimeType.
- Sorting is now stable so the rendered output is deterministic
2026-09-29 18:21:23 +01:00
Nick Craig-Wood 4a3ce883b1 serve http,webdav: sort directory listings in the browser
Clicking the Name, Size or Modified heading now sorts the listing in
the browser and clicking again reverses it, rather than reloading the
page with ?sort= and ?order= parameters. Names sort naturally so
v1.9.0 comes before v1.10.0, and directories stay first when sorting
by name.

The ?sort= and ?order= parameters still work for the initial order and
are shown in the heading, so existing links and custom templates are
unaffected.
2026-09-29 18:21:23 +01:00
Nick Craig-Wood c81298473b Add 4 new contributors
- Mattias Michaux
- jxj
- Harsh Raj Singhania
- Roland
2026-09-29 18:21:23 +01:00
Nick Craig-Wood 9dc8b71ae9 serve s3: fix TestEtagHashAuto on Windows
The temporary directory contains a drive letter colon so it needs
quoting in the crypt connection string, otherwise the password
parameter is dropped.
2026-09-26 14:39:07 +01:00
Nick Craig-Wood 881cedd348 build: fix lint errors from golangci-lint v2.14.0
The newer revive flags an exported function returning an unexported
type and a redundant type in a var declaration.
2026-09-26 12:51:07 +01:00
Nick Craig-Wood 220c65f81d build: fix TestS3Minio by switching to pgsty/minio as quay.io image is gone
MinIO no longer publishes images on quay.io (nor Docker Hub or ghcr.io)
so pulling quay.io/minio/minio returns "unauthorized". pgsty/minio is a
maintained community fork with the same entrypoint layout.
2026-09-26 12:50:45 +01:00
nielash 94e319d2fa fs: retry "network is unreachable" and "network is down" errors
ENETUNREACH and ENETDOWN were not in the list of retriable errors on
non-Windows platforms, so a single failed connection aborted the
transfer instead of being retried as a low level retry. The Windows
list already includes the equivalent WSAENETUNREACH and WSAENETDOWN.

This is easy to hit on a host with IPv6 enabled but no IPv6 route: if
the A lookup fails transiently while the AAAA lookup succeeds, the only
address to dial is IPv6 and the connect fails with ENETUNREACH. A retry
resolves again and normally succeeds.
2026-09-25 17:11:08 +01:00
Roland 60bdc6d454 fs: fix bandwidth limits below 1 KiB being multiplied by 1024 - fixes #9958
BwPair.String printed a sub-KiB bandwidth as a bare number, and Set
reads a bare number as KiB, so a rate under 1 KiB grew by a factor of
1024 whenever it went through a string. rc core/bwlimit reports the
current rate in that format and accepts it back, so reading the limit
and setting it again raised it.

63c4fef27 fixed the same corruption for config values by suffixing bare
numbers with B inside Option.String. Move that into a SizeSuffix method
and use it from BwPair.String as well.
2026-09-25 17:09:52 +01:00
Harsh Raj Singhania 14a1359c96 serve webdav: escape filename in zip download Content-Disposition header
Use mime.FormatMediaType instead of unescaped string concatenation so a
directory name containing a double quote cannot inject extra disposition
parameters.

Fixes #9962
2026-09-25 17:09:33 +01:00
Harsh Raj Singhania 661484f36c serve http: escape filename in zip download Content-Disposition header
Use mime.FormatMediaType instead of unescaped string concatenation so a
directory name containing a double quote cannot inject extra disposition
parameters.

Fixes #9962
2026-09-25 17:09:33 +01:00
Nick Craig-Wood ce5351c52e serve s3: fix CopyObject of a missing object not returning NoSuchKey
Copying an object onto itself, as clients do to replace its metadata,
reported success when the object didn't exist, and copying a missing
object to a different key failed with an internal error. Both now fail
with NoSuchKey as S3 does.
2026-09-24 10:36:10 +01:00
Nick Craig-Wood 746eac73ef serve s3: fix --etag-hash auto crashing or using the wrong hash with --auth-proxy
With --etag-hash auto the hash for the ETags was chosen once from the
remote serve s3 was started with. With --auth-proxy there is no such
remote so serve s3 crashed on startup, and when started by the rc it
was the wrong remote, so users whose backends lacked that hash got no
ETags.

The hash is now chosen from the backend of the user making each
request.
2026-09-24 10:36:06 +01:00