github.com/rclone/rclone@v1.66.1-0.20240517100346-7b89735ae726/fs/types.go (about) 1 // Filesystem related types and interfaces 2 // Note that optional interfaces are found in features.go 3 4 package fs 5 6 import ( 7 "context" 8 "io" 9 "time" 10 11 "github.com/rclone/rclone/fs/hash" 12 ) 13 14 // Fs is the interface a cloud storage system must provide 15 type Fs interface { 16 Info 17 18 // List the objects and directories in dir into entries. The 19 // entries can be returned in any order but should be for a 20 // complete directory. 21 // 22 // dir should be "" to list the root, and should not have 23 // trailing slashes. 24 // 25 // This should return ErrDirNotFound if the directory isn't 26 // found. 27 List(ctx context.Context, dir string) (entries DirEntries, err error) 28 29 // NewObject finds the Object at remote. If it can't be found 30 // it returns the error ErrorObjectNotFound. 31 // 32 // If remote points to a directory then it should return 33 // ErrorIsDir if possible without doing any extra work, 34 // otherwise ErrorObjectNotFound. 35 NewObject(ctx context.Context, remote string) (Object, error) 36 37 // Put in to the remote path with the modTime given of the given size 38 // 39 // When called from outside an Fs by rclone, src.Size() will always be >= 0. 40 // But for unknown-sized objects (indicated by src.Size() == -1), Put should either 41 // return an error or upload it properly (rather than e.g. calling panic). 42 // 43 // May create the object even if it returns an error - if so 44 // will return the object and the error, otherwise will return 45 // nil and the error 46 Put(ctx context.Context, in io.Reader, src ObjectInfo, options ...OpenOption) (Object, error) 47 48 // Mkdir makes the directory (container, bucket) 49 // 50 // Shouldn't return an error if it already exists 51 Mkdir(ctx context.Context, dir string) error 52 53 // Rmdir removes the directory (container, bucket) if empty 54 // 55 // Return an error if it doesn't exist or isn't empty 56 Rmdir(ctx context.Context, dir string) error 57 } 58 59 // Info provides a read only interface to information about a filesystem. 60 type Info interface { 61 // Name of the remote (as passed into NewFs) 62 Name() string 63 64 // Root of the remote (as passed into NewFs) 65 Root() string 66 67 // String returns a description of the FS 68 String() string 69 70 // Precision of the ModTimes in this Fs 71 Precision() time.Duration 72 73 // Returns the supported hash types of the filesystem 74 Hashes() hash.Set 75 76 // Features returns the optional features of this Fs 77 Features() *Features 78 } 79 80 // Object is a filesystem like object provided by an Fs 81 type Object interface { 82 ObjectInfo 83 84 // SetModTime sets the metadata on the object to set the modification date 85 SetModTime(ctx context.Context, t time.Time) error 86 87 // Open opens the file for read. Call Close() on the returned io.ReadCloser 88 Open(ctx context.Context, options ...OpenOption) (io.ReadCloser, error) 89 90 // Update in to the object with the modTime given of the given size 91 // 92 // When called from outside an Fs by rclone, src.Size() will always be >= 0. 93 // But for unknown-sized objects (indicated by src.Size() == -1), Upload should either 94 // return an error or update the object properly (rather than e.g. calling panic). 95 Update(ctx context.Context, in io.Reader, src ObjectInfo, options ...OpenOption) error 96 97 // Removes this object 98 Remove(ctx context.Context) error 99 } 100 101 // ObjectInfo provides read only information about an object. 102 type ObjectInfo interface { 103 DirEntry 104 105 // Hash returns the selected checksum of the file 106 // If no checksum is available it returns "" 107 Hash(ctx context.Context, ty hash.Type) (string, error) 108 109 // Storable says whether this object can be stored 110 Storable() bool 111 } 112 113 // DirEntry provides read only information about the common subset of 114 // a Dir or Object. These are returned from directory listings - type 115 // assert them into the correct type. 116 type DirEntry interface { 117 // Fs returns read only access to the Fs that this object is part of 118 Fs() Info 119 120 // String returns a description of the Object 121 String() string 122 123 // Remote returns the remote path 124 Remote() string 125 126 // ModTime returns the modification date of the file 127 // It should return a best guess if one isn't available 128 ModTime(context.Context) time.Time 129 130 // Size returns the size of the file 131 Size() int64 132 } 133 134 // Directory is a filesystem like directory provided by an Fs 135 type Directory interface { 136 DirEntry 137 138 // Items returns the count of items in this directory or this 139 // directory and subdirectories if known, -1 for unknown 140 Items() int64 141 142 // ID returns the internal ID of this directory if known, or 143 // "" otherwise 144 ID() string 145 } 146 147 // FullDirectory contains all the optional interfaces for Directory 148 // 149 // Use for checking making wrapping Directories implement everything 150 type FullDirectory interface { 151 Directory 152 Metadataer 153 SetMetadataer 154 SetModTimer 155 } 156 157 // MimeTyper is an optional interface for Object 158 type MimeTyper interface { 159 // MimeType returns the content type of the Object if 160 // known, or "" if not 161 MimeType(ctx context.Context) string 162 } 163 164 // IDer is an optional interface for Object 165 type IDer interface { 166 // ID returns the ID of the Object if known, or "" if not 167 ID() string 168 } 169 170 // ParentIDer is an optional interface for Object 171 type ParentIDer interface { 172 // ParentID returns the ID of the parent directory if known or nil if not 173 ParentID() string 174 } 175 176 // ObjectUnWrapper is an optional interface for Object 177 type ObjectUnWrapper interface { 178 // UnWrap returns the Object that this Object is wrapping or 179 // nil if it isn't wrapping anything 180 UnWrap() Object 181 } 182 183 // SetTierer is an optional interface for Object 184 type SetTierer interface { 185 // SetTier performs changing storage tier of the Object if 186 // multiple storage classes supported 187 SetTier(tier string) error 188 } 189 190 // GetTierer is an optional interface for Object 191 type GetTierer interface { 192 // GetTier returns storage tier or class of the Object 193 GetTier() string 194 } 195 196 // Metadataer is an optional interface for DirEntry 197 type Metadataer interface { 198 // Metadata returns metadata for an DirEntry 199 // 200 // It should return nil if there is no Metadata 201 Metadata(ctx context.Context) (Metadata, error) 202 } 203 204 // SetMetadataer is an optional interface for DirEntry 205 type SetMetadataer interface { 206 // SetMetadata sets metadata for an DirEntry 207 // 208 // It should return fs.ErrorNotImplemented if it can't set metadata 209 SetMetadata(ctx context.Context, metadata Metadata) error 210 } 211 212 // SetModTimer is an optional interface for Directory. 213 // 214 // Object implements this as part of its requires set of interfaces. 215 type SetModTimer interface { 216 // SetModTime sets the metadata on the DirEntry to set the modification date 217 // 218 // If there is any other metadata it does not overwrite it. 219 SetModTime(ctx context.Context, t time.Time) error 220 } 221 222 // FullObjectInfo contains all the read-only optional interfaces 223 // 224 // Use for checking making wrapping ObjectInfos implement everything 225 type FullObjectInfo interface { 226 ObjectInfo 227 MimeTyper 228 IDer 229 ObjectUnWrapper 230 GetTierer 231 Metadataer 232 } 233 234 // FullObject contains all the optional interfaces for Object 235 // 236 // Use for checking making wrapping Objects implement everything 237 type FullObject interface { 238 Object 239 MimeTyper 240 IDer 241 ObjectUnWrapper 242 GetTierer 243 SetTierer 244 Metadataer 245 SetMetadataer 246 } 247 248 // ObjectOptionalInterfaces returns the names of supported and 249 // unsupported optional interfaces for an Object 250 func ObjectOptionalInterfaces(o Object) (supported, unsupported []string) { 251 store := func(ok bool, name string) { 252 if ok { 253 supported = append(supported, name) 254 } else { 255 unsupported = append(unsupported, name) 256 } 257 } 258 259 _, ok := o.(MimeTyper) 260 store(ok, "MimeType") 261 262 _, ok = o.(IDer) 263 store(ok, "ID") 264 265 _, ok = o.(ObjectUnWrapper) 266 store(ok, "UnWrap") 267 268 _, ok = o.(SetTierer) 269 store(ok, "SetTier") 270 271 _, ok = o.(GetTierer) 272 store(ok, "GetTier") 273 274 _, ok = o.(Metadataer) 275 store(ok, "Metadata") 276 277 _, ok = o.(SetMetadataer) 278 store(ok, "SetMetadata") 279 280 return supported, unsupported 281 } 282 283 // DirectoryOptionalInterfaces returns the names of supported and 284 // unsupported optional interfaces for a Directory 285 func DirectoryOptionalInterfaces(d Directory) (supported, unsupported []string) { 286 store := func(ok bool, name string) { 287 if ok { 288 supported = append(supported, name) 289 } else { 290 unsupported = append(unsupported, name) 291 } 292 } 293 294 _, ok := d.(Metadataer) 295 store(ok, "Metadata") 296 297 _, ok = d.(SetMetadataer) 298 store(ok, "SetMetadata") 299 300 _, ok = d.(SetModTimer) 301 store(ok, "SetModTime") 302 303 return supported, unsupported 304 } 305 306 // ListRCallback defines a callback function for ListR to use 307 // 308 // It is called for each tranche of entries read from the listing and 309 // if it returns an error, the listing stops. 310 type ListRCallback func(entries DirEntries) error 311 312 // ListRFn is defines the call used to recursively list a directory 313 type ListRFn func(ctx context.Context, dir string, callback ListRCallback) error 314 315 // NewUsageValue makes a valid value 316 func NewUsageValue(value int64) *int64 { 317 p := new(int64) 318 *p = value 319 return p 320 } 321 322 // Usage is returned by the About call 323 // 324 // If a value is nil then it isn't supported by that backend 325 type Usage struct { 326 Total *int64 `json:"total,omitempty"` // quota of bytes that can be used 327 Used *int64 `json:"used,omitempty"` // bytes in use 328 Trashed *int64 `json:"trashed,omitempty"` // bytes in trash 329 Other *int64 `json:"other,omitempty"` // other usage e.g. gmail in drive 330 Free *int64 `json:"free,omitempty"` // bytes which can be uploaded before reaching the quota 331 Objects *int64 `json:"objects,omitempty"` // objects in the storage system 332 } 333 334 // WriterAtCloser wraps io.WriterAt and io.Closer 335 type WriterAtCloser interface { 336 io.WriterAt 337 io.Closer 338 } 339 340 type unknownFs struct{} 341 342 // Name of the remote (as passed into NewFs) 343 func (unknownFs) Name() string { return "unknown" } 344 345 // Root of the remote (as passed into NewFs) 346 func (unknownFs) Root() string { return "" } 347 348 // String returns a description of the FS 349 func (unknownFs) String() string { return "unknown" } 350 351 // Precision of the ModTimes in this Fs 352 func (unknownFs) Precision() time.Duration { return ModTimeNotSupported } 353 354 // Returns the supported hash types of the filesystem 355 func (unknownFs) Hashes() hash.Set { return hash.Set(hash.None) } 356 357 // Features returns the optional features of this Fs 358 func (unknownFs) Features() *Features { return &Features{} } 359 360 // Unknown holds an Info for an unknown Fs 361 // 362 // This is used when we need an Fs but don't have one. 363 var Unknown Info = unknownFs{}