diff --git a/backend/sftp/sftp.go b/backend/sftp/sftp.go index a75d91902..305fbde98 100644 --- a/backend/sftp/sftp.go +++ b/backend/sftp/sftp.go @@ -1324,6 +1324,42 @@ func (f *Fs) Hashes() hash.Set { // About gets usage stats func (f *Fs) About(ctx context.Context) (*fs.Usage, error) { + // If server implements the vendor-specific VFS statistics extension prefer that + // (OpenSSH implements it on using syscall.Statfs on Linux and API function GetDiskFreeSpace on Windows) + c, err := f.getSftpConnection(ctx) + if err != nil { + return nil, err + } + var vfsStats *sftp.StatVFS + if _, found := c.sftpClient.HasExtension("statvfs@openssh.com"); found { + fs.Debugf(f, "Server has VFS statistics extension") + aboutPath := f.absRoot + if aboutPath == "" { + aboutPath = "/" + } + fs.Debugf(f, "About path %q", aboutPath) + vfsStats, err = c.sftpClient.StatVFS(aboutPath) + } + f.putSftpConnection(&c, err) // Return to pool asap, if running shell command below it will be re-used + if vfsStats != nil { + total := vfsStats.TotalSpace() + free := vfsStats.FreeSpace() + used := total - free + return &fs.Usage{ + Total: fs.NewUsageValue(int64(total)), + Used: fs.NewUsageValue(int64(used)), + Free: fs.NewUsageValue(int64(free)), + }, nil + } else if err != nil { + if errors.Is(err, os.ErrNotExist) { + return nil, err + } + fs.Debugf(f, "Failed to retrieve VFS statistics, trying shell command instead: %v", err) + } else { + fs.Debugf(f, "Server does not have the VFS statistics extension, trying shell command instead") + } + + // Fall back to shell command method if possible if f.shellType == shellTypeNotSupported || f.shellType == "cmd" { fs.Debugf(f, "About shell command is not available for shell type %q (set option shell_type to override)", f.shellType) return nil, fmt.Errorf("not supported with shell type %q", f.shellType) diff --git a/docs/content/sftp.md b/docs/content/sftp.md index ecd218990..a0fc7271c 100644 --- a/docs/content/sftp.md +++ b/docs/content/sftp.md @@ -370,17 +370,19 @@ your RClone backend configuration to disable this behaviour. ### About command -SFTP supports the [about](/commands/rclone_about/) command if the -same login has access to a Unix shell, where the `df` command is -available (e.g. in the remote's PATH). `about` will return the -total space, free space, and used space on the remote for the disk -of the specified path on the remote or, if not set, the disk of -the root on the remote. `about` will fail if it does not have -shell access or if `df` is not found. +The `about` command returns the total space, free space, and used +space on the remote for the disk of the specified path on the remote or, +if not set, the disk of the root on the remote. -If the server shell is PowerShell, probably with a Windows OpenSSH -server, rclone supports `about` using a built-in shell command -(see [shell access](#shell-access)). +SFTP usually supports the [about](/commands/rclone_about/) command, but +it depends on the server. If the server implements the vendor-specific +VFS statistics extension, which is normally the case with OpenSSH instances, +it will be used. If not, but the same login has access to a Unix shell, +where the `df` command is available (e.g. in the remote's PATH), then +this will be used instead. If the server shell is PowerShell, probably +with a Windows OpenSSH server, rclone will use a built-in shell command +(see [shell access](#shell-access)). If none of the above is applicable, +`about` will fail. {{< rem autogenerated options start" - DO NOT EDIT - instead edit fs.RegInfo in backend/sftp/sftp.go then run make backenddocs" >}} ### Standard options