2015-09-22 19:47:16 +02:00
|
|
|
// Package fs is a generic file system interface for rclone object storage systems
|
2013-06-27 21:13:07 +02:00
|
|
|
package fs
|
2012-12-26 13:23:58 +01:00
|
|
|
|
|
|
|
import (
|
2019-06-17 10:34:30 +02:00
|
|
|
"context"
|
2021-11-04 11:12:57 +01:00
|
|
|
"errors"
|
2012-12-26 13:23:58 +01:00
|
|
|
"io"
|
2016-04-21 21:06:21 +02:00
|
|
|
"math"
|
2012-12-26 13:23:58 +01:00
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
2014-07-13 19:58:06 +02:00
|
|
|
// Constants
|
|
|
|
const (
|
2015-09-22 19:47:16 +02:00
|
|
|
// ModTimeNotSupported is a very large precision value to show
|
|
|
|
// mod time isn't supported on this Fs
|
2015-08-17 00:24:34 +02:00
|
|
|
ModTimeNotSupported = 100 * 365 * 24 * time.Hour
|
2016-04-21 21:06:21 +02:00
|
|
|
// MaxLevel is a sentinel representing an infinite depth for listings
|
|
|
|
MaxLevel = math.MaxInt32
|
2022-07-10 17:47:32 +02:00
|
|
|
// The suffix added to a translated symbolic link
|
|
|
|
LinkSuffix = ".rclonelink"
|
2014-07-13 19:58:06 +02:00
|
|
|
)
|
|
|
|
|
2013-06-27 21:13:07 +02:00
|
|
|
// Globals
|
|
|
|
var (
|
2015-09-22 19:47:16 +02:00
|
|
|
// ErrorNotFoundInConfigFile is returned by NewFs if not found in config file
|
2017-06-13 14:58:39 +02:00
|
|
|
ErrorNotFoundInConfigFile = errors.New("didn't find section in config file")
|
|
|
|
ErrorCantPurge = errors.New("can't purge directory")
|
|
|
|
ErrorCantCopy = errors.New("can't copy object - incompatible remotes")
|
|
|
|
ErrorCantMove = errors.New("can't move object - incompatible remotes")
|
|
|
|
ErrorCantDirMove = errors.New("can't move directory - incompatible remotes")
|
2019-06-29 03:17:53 +02:00
|
|
|
ErrorCantUploadEmptyFiles = errors.New("can't upload empty files to this remote")
|
2017-06-13 14:58:39 +02:00
|
|
|
ErrorDirExists = errors.New("can't copy directory - destination already exists")
|
|
|
|
ErrorCantSetModTime = errors.New("can't set modified time")
|
|
|
|
ErrorCantSetModTimeWithoutDelete = errors.New("can't set modified time without deleting existing object")
|
|
|
|
ErrorDirNotFound = errors.New("directory not found")
|
|
|
|
ErrorObjectNotFound = errors.New("object not found")
|
|
|
|
ErrorLevelNotSupported = errors.New("level value not supported")
|
|
|
|
ErrorListAborted = errors.New("list aborted")
|
2017-06-11 23:43:31 +02:00
|
|
|
ErrorListBucketRequired = errors.New("bucket or container name is needed in remote")
|
2017-06-13 14:58:39 +02:00
|
|
|
ErrorIsFile = errors.New("is a file not a directory")
|
2021-09-06 14:54:08 +02:00
|
|
|
ErrorIsDir = errors.New("is a directory not a file")
|
2020-04-15 13:50:26 +02:00
|
|
|
ErrorNotAFile = errors.New("is not a regular file")
|
2017-06-13 14:58:39 +02:00
|
|
|
ErrorNotDeleting = errors.New("not deleting files as there were IO errors")
|
2017-08-09 22:06:39 +02:00
|
|
|
ErrorNotDeletingDirs = errors.New("not deleting directories as there were IO errors")
|
2022-07-11 23:31:30 +02:00
|
|
|
ErrorOverlapping = errors.New("can't sync or move files on overlapping remotes (try excluding the destination with a filter rule)")
|
2017-07-25 16:18:13 +02:00
|
|
|
ErrorDirectoryNotEmpty = errors.New("directory not empty")
|
2017-09-02 10:29:01 +02:00
|
|
|
ErrorImmutableModified = errors.New("immutable file modified")
|
2018-01-16 21:00:16 +01:00
|
|
|
ErrorPermissionDenied = errors.New("permission denied")
|
2019-07-24 17:57:56 +02:00
|
|
|
ErrorCantShareDirectories = errors.New("this backend can't share directories with link")
|
2019-08-12 12:07:31 +02:00
|
|
|
ErrorNotImplemented = errors.New("optional feature not implemented")
|
2020-04-28 13:58:34 +02:00
|
|
|
ErrorCommandNotFound = errors.New("command not found")
|
2020-11-27 12:49:37 +01:00
|
|
|
ErrorFileNameTooLong = errors.New("file name too long")
|
2013-06-27 21:13:07 +02:00
|
|
|
)
|
|
|
|
|
2015-11-28 19:13:08 +01:00
|
|
|
// CheckClose is a utility function used to check the return from
|
2012-12-26 13:23:58 +01:00
|
|
|
// Close in a defer statement.
|
2015-11-28 19:13:08 +01:00
|
|
|
func CheckClose(c io.Closer, err *error) {
|
2012-12-26 13:23:58 +01:00
|
|
|
cerr := c.Close()
|
|
|
|
if *err == nil {
|
|
|
|
*err = cerr
|
|
|
|
}
|
|
|
|
}
|
2017-11-13 14:46:31 +01:00
|
|
|
|
|
|
|
// FileExists returns true if a file remote exists.
|
|
|
|
// If remote is a directory, FileExists returns false.
|
2019-06-17 10:34:30 +02:00
|
|
|
func FileExists(ctx context.Context, fs Fs, remote string) (bool, error) {
|
|
|
|
_, err := fs.NewObject(ctx, remote)
|
2017-11-13 14:46:31 +01:00
|
|
|
if err != nil {
|
2018-01-16 21:00:16 +01:00
|
|
|
if err == ErrorObjectNotFound || err == ErrorNotAFile || err == ErrorPermissionDenied {
|
2017-11-13 14:46:31 +01:00
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
return true, nil
|
|
|
|
}
|
2018-01-12 17:30:54 +01:00
|
|
|
|
2018-06-03 20:45:34 +02:00
|
|
|
// GetModifyWindow calculates the maximum modify window between the given Fses
|
|
|
|
// and the Config.ModifyWindow parameter.
|
2020-11-05 17:27:01 +01:00
|
|
|
func GetModifyWindow(ctx context.Context, fss ...Info) time.Duration {
|
2020-11-05 12:33:32 +01:00
|
|
|
window := GetConfig(ctx).ModifyWindow
|
2018-01-12 17:30:54 +01:00
|
|
|
for _, f := range fss {
|
|
|
|
if f != nil {
|
|
|
|
precision := f.Precision()
|
|
|
|
if precision == ModTimeNotSupported {
|
2018-06-03 20:45:34 +02:00
|
|
|
return ModTimeNotSupported
|
|
|
|
}
|
|
|
|
if precision > window {
|
|
|
|
window = precision
|
2018-01-12 17:30:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-06-03 20:45:34 +02:00
|
|
|
return window
|
2018-01-12 17:30:54 +01:00
|
|
|
}
|