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