1// Package fs is a generic file system interface for rclone object storage systems 2package fs 3 4import ( 5 "context" 6 "io" 7 "math" 8 "time" 9 10 "github.com/pkg/errors" 11) 12 13// Constants 14const ( 15 // ModTimeNotSupported is a very large precision value to show 16 // mod time isn't supported on this Fs 17 ModTimeNotSupported = 100 * 365 * 24 * time.Hour 18 // MaxLevel is a sentinel representing an infinite depth for listings 19 MaxLevel = math.MaxInt32 20) 21 22// Globals 23var ( 24 // ErrorNotFoundInConfigFile is returned by NewFs if not found in config file 25 ErrorNotFoundInConfigFile = errors.New("didn't find section in config file") 26 ErrorCantPurge = errors.New("can't purge directory") 27 ErrorCantCopy = errors.New("can't copy object - incompatible remotes") 28 ErrorCantMove = errors.New("can't move object - incompatible remotes") 29 ErrorCantDirMove = errors.New("can't move directory - incompatible remotes") 30 ErrorCantUploadEmptyFiles = errors.New("can't upload empty files to this remote") 31 ErrorDirExists = errors.New("can't copy directory - destination already exists") 32 ErrorCantSetModTime = errors.New("can't set modified time") 33 ErrorCantSetModTimeWithoutDelete = errors.New("can't set modified time without deleting existing object") 34 ErrorDirNotFound = errors.New("directory not found") 35 ErrorObjectNotFound = errors.New("object not found") 36 ErrorLevelNotSupported = errors.New("level value not supported") 37 ErrorListAborted = errors.New("list aborted") 38 ErrorListBucketRequired = errors.New("bucket or container name is needed in remote") 39 ErrorIsFile = errors.New("is a file not a directory") 40 ErrorIsDir = errors.New("is a directory not a file") 41 ErrorNotAFile = errors.New("is not a regular file") 42 ErrorNotDeleting = errors.New("not deleting files as there were IO errors") 43 ErrorNotDeletingDirs = errors.New("not deleting directories as there were IO errors") 44 ErrorOverlapping = errors.New("can't sync or move files on overlapping remotes") 45 ErrorDirectoryNotEmpty = errors.New("directory not empty") 46 ErrorImmutableModified = errors.New("immutable file modified") 47 ErrorPermissionDenied = errors.New("permission denied") 48 ErrorCantShareDirectories = errors.New("this backend can't share directories with link") 49 ErrorNotImplemented = errors.New("optional feature not implemented") 50 ErrorCommandNotFound = errors.New("command not found") 51 ErrorFileNameTooLong = errors.New("file name too long") 52) 53 54// CheckClose is a utility function used to check the return from 55// Close in a defer statement. 56func CheckClose(c io.Closer, err *error) { 57 cerr := c.Close() 58 if *err == nil { 59 *err = cerr 60 } 61} 62 63// FileExists returns true if a file remote exists. 64// If remote is a directory, FileExists returns false. 65func FileExists(ctx context.Context, fs Fs, remote string) (bool, error) { 66 _, err := fs.NewObject(ctx, remote) 67 if err != nil { 68 if err == ErrorObjectNotFound || err == ErrorNotAFile || err == ErrorPermissionDenied { 69 return false, nil 70 } 71 return false, err 72 } 73 return true, nil 74} 75 76// GetModifyWindow calculates the maximum modify window between the given Fses 77// and the Config.ModifyWindow parameter. 78func GetModifyWindow(ctx context.Context, fss ...Info) time.Duration { 79 window := GetConfig(ctx).ModifyWindow 80 for _, f := range fss { 81 if f != nil { 82 precision := f.Precision() 83 if precision == ModTimeNotSupported { 84 return ModTimeNotSupported 85 } 86 if precision > window { 87 window = precision 88 } 89 } 90 } 91 return window 92} 93